l4re-base-25.08.0

This commit is contained in:
2025-09-12 15:55:45 +02:00
commit d959eaab98
37938 changed files with 9382688 additions and 0 deletions

17
src/fiasco/BENCHMARKING Normal file
View File

@@ -0,0 +1,17 @@
IMPORTANT NOTE ON BENCHMARKING Fiasco.OC/L4Re SOFTWARE
======================================================
Owing to the flexibility of configurations possible with this software we
urge you to send any benchmarking results for review prior to publication to
benchmarking@l4re.org
to get feedback and an 'OK' from our side that the presented figures are
reasonable.
In any case, for doing benchmarks and performance analysis, please ensure
to have CONFIG_PERFORMANCE selected in Fiasco's configuration.
Thank you.

301
src/fiasco/Makefile Normal file
View File

@@ -0,0 +1,301 @@
#
#
# GLOBAL Makefile for FIASCO
# enviroment
DFLBUILDDIR := build
ALLBUILDDIR := build-all
RANDBUILDDIR := build-rand
TEMPLDIR := src/templates
MAKEFILETEMPL := $(TEMPLDIR)/Makefile.builddir.templ
MANSUBDIRS := man
INSTALLSUBDIRS := $(MANSUBDIRS)
CLEANSUBDIRS := $(wildcard $(MANSUBDIRS) $(DFLBUILDDIR))
CONFIG_FILE := $(TEMPLDIR)/globalconfig.out
TEST_TEMPLATES := $(patsubst $(CONFIG_FILE).%,%,$(wildcard $(CONFIG_FILE).*))
TEST_TEMPLATES := $(if $(TEMPLATE_FILTER),$(filter $(TEMPLATE_FILTER),$(TEST_TEMPLATES)),$(TEST_TEMPLATES))
DFL_TEMPLATE := amd64-dfl
DEFCONFIG ?= $(TEMPLDIR)/globalconfig.out.$(DFL_TEMPLATE)
buildmakefile = mkdir -p "$(1)"; \
perl -p -e '$$s = "$(CURDIR)/src"; s/\@SRCDIR\@/$$s/' \
< $(MAKEFILETEMPL) > $(1)/Makefile
ifneq ($(strip $(B)),)
BUILDDIR := $(B)
endif
ifneq ($(strip $(BUILDDIR)),)
builddir:
@echo "Creating build directory \"$(BUILDDIR)\"..."
@if [ -e "$(BUILDDIR)" ]; then \
echo "Already exists, aborting."; \
exit 1; \
fi
@$(call buildmakefile,$(BUILDDIR))
@t_dfl="$(DEFCONFIG)"; \
if [ -n "$(T)" ]; then \
tfile="$(TEMPLDIR)/globalconfig.out.$(T)"; \
[ -f "$$tfile" ] || { \
echo "Template \"$(T)\" does not exist as $$tfile"; \
$(RM) -r $(BUILDDIR); \
exit 1; \
}; \
elif [ -f "$$t_dfl" ]; then \
tfile="$$t_dfl"; \
else \
echo "\"$$t_dfl\" does not exist."; \
$(RM) -r $(BUILDDIR); \
exit 1; \
fi; \
echo "Copying template configuration $$tfile"; \
cp "$$tfile" $(BUILDDIR)/globalconfig.out; \
$(MAKE) -C $(BUILDDIR) olddefconfig
@echo "done."
endif
ifneq ($(strip $(O)),)
.PHONY: builddir
builddir:
@if [ ! -e "$(O)" ]; then \
echo "build directory does not exist: '$(O)'";\
exit 1; \
fi
@if ! grep -qF "srcdir := $(CURDIR)/src" $(O)/Makefile 2>/dev/null; \
then \
echo "builddir '$(O)' not created from this source directory."; \
exit 1; \
fi
@$(MAKE) -C $(O) $(MAKECMDGOALS)
%: builddir
endif
ifneq ($(strip $(T)),)
this:
set -e; \
test -f $(TEMPLDIR)/globalconfig.out.$(T); \
bdir=T-$(DFLBUILDDIR)-$(T); \
rm -rf $$bdir; \
$(call buildmakefile,T-$(DFLBUILDDIR)-$(T)); \
cp $(TEMPLDIR)/globalconfig.out.$(T) $$bdir/globalconfig.out; \
$(MAKE) -C $$bdir olddefconfig; \
$(MAKE) -C $$bdir
endif
$(DFLBUILDDIR): fiasco.builddir.create
$(MAKE) -C $@
all: fiasco man
clean cleanall:
set -e; for i in $(CLEANSUBDIRS); do $(MAKE) -C $$i $@; done
purge: cleanall
$(RM) -r $(DFLBUILDDIR)
man:
set -e; for i in $(MANSUBDIRS); do $(MAKE) -C $$i; done
fiasco.builddir.create:
@[ -e $(DFLBUILDDIR)/Makefile ] || \
($(call buildmakefile,$(DFLBUILDDIR)))
@[ -f $(DFLBUILDDIR)/globalconfig.out ] || { \
cp $(DEFCONFIG) $(DFLBUILDDIR)/globalconfig.out; \
$(MAKE) -C $(DFLBUILDDIR) olddefconfig; \
}
config $(filter config %config,$(MAKECMDGOALS)): fiasco.builddir.create
$(MAKE) -C $(DFLBUILDDIR) $@
fiasco: fiasco.builddir.create
$(MAKE) -C $(DFLBUILDDIR)
checkallseq:
@error=0; \
$(RM) -r $(ALLBUILDDIR); \
for X in $(TEST_TEMPLATES); do \
echo -e "\n= Building configuration: $$X\n\n"; \
$(call buildmakefile,$(ALLBUILDDIR)/$$X); \
cp $(TEMPLDIR)/globalconfig.out.$$X \
$(ALLBUILDDIR)/$$X/globalconfig.out; \
if $(MAKE) -C $(ALLBUILDDIR)/$$X; then \
[ -z "$(KEEP_BUILD_DIRS)" ] && \
$(RM) -r $(ALLBUILDDIR)/$$X; \
else \
error=$$?; \
failed="$$failed $$X"; \
fi \
done; \
rmdir $(ALLBUILDDIR) >/dev/null 2>&1; \
[ "$$failed" ] && echo -e "\nFailed configurations:$$failed"; \
exit $$error;
checkall l4check:
$(RM) -r $(ALLBUILDDIR)
$(MAKE) dobuildparallel SHELL=bash
.PHONY: dobuildparallel checkallp
dobuildparallel: $(addprefix $(ALLBUILDDIR)/,$(TEST_TEMPLATES))
@error=0; \
echo "======================================================"; \
for d in $(TEST_TEMPLATES); do \
if [ -e $(ALLBUILDDIR)/$$d/build.failed ]; then \
error=1; failed="$$failed $$d"; \
fi; \
done; \
for f in $$failed; do echo "====== Failed Build Log: $$f ======"; \
tail -60 $(ALLBUILDDIR)/$$f/build.log; \
done; \
rmdir $(ALLBUILDDIR) >/dev/null 2>&1; \
[ "$$failed" ] && echo -e "\nFailed configurations:$$failed"; \
exit $$error;
$(addprefix $(ALLBUILDDIR)/,$(TEST_TEMPLATES)):
$(call buildmakefile,$@)
cp $(TEMPLDIR)/globalconfig.out.$(patsubst $(ALLBUILDDIR)/%,%,$@) \
$@/globalconfig.out
INCLUDE_PPC32=y INCLUDE_SPARC=y \
$(MAKE) -C $@ olddefconfig 2>&1 | tee -a $@/build.log
CHECK_CI_BUILDCHECK=y INCLUDE_PPC32=y INCLUDE_SPARC=y \
$(MAKE) -C $@ 2>&1 | tee -a $@/build.log; \
buildexitcode=$${PIPESTATUS[0]}; \
grep -2 ": warning: " $@/build.log > $@/warnings.log; \
test -s $@/warnings.log \
&& mv $@/warnings.log $(ALLBUILDDIR)/warnings.$(@F); \
if [ $$buildexitcode = 0 ]; \
then [ -z "$(KEEP_BUILD_DIRS)" ] && $(RM) -r $@; \
else echo $$buildexitcode > $@/build.failed; fi; true
list:
@echo "Templates:"
@echo $(TEST_TEMPLATES)
RANDBUILDMAXTIME = $(shell $$((2 * 3600)))
RANDBUILDONERUN = 50
RANDBUILDDIRS = $(foreach idx,$(shell seq $(RANDBUILDONERUN)),$(RANDBUILDDIR)/b-$(idx))
RANDBUILDAGAINDIRS = $(wildcard $(RANDBUILDDIR)/failed-*)
.PHONY: $(RANDBUILDAGAINDIRS)
randcheck:
$(RM) -r $(RANDBUILDDIR)
$(call buildmakefile,$(RANDBUILDDIR)/build-templ);
starttime=$$(date +%s); \
if [ -z "$$RANDBUILDTIME" ]; then d=0; else d=$$RANDBUILDTIME; fi; \
while [ "$$d" = 0 \
-o $$(date +%s) -lt $$(($$starttime + $$d)) ]; do \
$(MAKE) dobuildrandparallel SHELL=bash; \
if [ $$(ls $(RANDBUILDDIR) | grep -c failed-) \
-gt $$(($(RANDBUILDONERUN) / 2)) ]; \
then break; fi; \
done; \
echo "$$(ls $(RANDBUILDDIR) | grep -c failed-) directories" \
"failed to build."; \
echo "Build time: $$((($$(date +%s) - $$starttime) / 60)) minutes."
randchecktimed:
@$(MAKE) randcheck RANDBUILDTIME=$(RANDBUILDMAXTIME)
dobuildrandparallel: $(RANDBUILDDIRS)
define rand_build_a_dir
$(MAKE) -C $(1) 2>&1 | tee -a $(1)/build.log; \
buildexitcode=$${PIPESTATUS[0]}; \
grep -2 ": warning: " $(1)/build.log > $(1)/warn.log; \
test -s $(1)/warn.log \
&& mv $(1)/warn.log $(RANDBUILDDIR)/warnings-$(2); \
if [ $$buildexitcode = 0 ]; then \
cp $(1)/globalconfig.out $(RANDBUILDDIR)/ok-$(2); \
rm -r $(1); \
elif [ -n "$(3)" ]; then \
[ -n "$$STOP_ON_ERROR" ] && exit 1; \
mv $(1) $(RANDBUILDDIR)/failed-$(2); \
fi
endef
$(RANDBUILDDIRS):
cp -a $(RANDBUILDDIR)/build-templ $@
until \
INCLUDE_PPC32=y INCLUDE_SPARC=y \
$(MAKE) -C $@ randconfig | tee -a $@/build.log; \
INCLUDE_PPC32=y INCLUDE_SPARC=y \
$(MAKE) -C $@ oldconfig | tee -a $@/build.log; \
do [ $${PIPESTATUS[0]} != 0 ]; done
+fn=$$(cat $@/globalconfig.out \
| grep -e "^CONFIG_" | sort | sha1sum \
| cut -f1 -d\ ); \
if [ -e "ok-$$fn" -o -e "failed-$$fn" ]; then \
echo "Configuration $$fn already checked." \
continue; \
fi; \
$(call rand_build_a_dir,$@,$$fn,1)
$(RANDBUILDAGAINDIRS):
+$(call rand_build_a_dir,$@,$(patsubst $(RANDBUILDDIR)/failed-%,%,$@))
randcheckstop:
$(MAKE) STOP_ON_ERROR=1 randcheck
randcheckagain_bash: $(RANDBUILDAGAINDIRS)
randcheckagain:
$(MAKE) randcheckagain_bash SHELL=bash
@echo "Processed $(words $(RANDBUILDAGAINDIRS)) build directories."
@echo "$$(ls -d $(RANDBUILDDIR)/failed-* | wc -l) directories remain to fail."
randcheckagainstop:
$(MAKE) STOP_ON_ERROR=1 randcheckagain
randcheckstat:
@find $(RANDBUILDDIR) -name 'ok-*' | tool/configstat
@echo "Building: $$(ls $(RANDBUILDDIR) | grep -c b-) " \
"Ok: $$(ls $(RANDBUILDDIR) | grep -c ok-) " \
"Failed: $$(ls $(RANDBUILDDIR) | grep -c failed-) " \
"Warnings: $$(ls $(RANDBUILDDIR) | grep -c warnings-)"
randcheckstatloop:
@while true; do \
$(MAKE) --no-print-directory randcheckstat; \
sleep 5; \
done
remotemake:
@r=$(word 1,$(REMOTEOPTS)); h=$${r%:*}; p=$${r#*:}; \
ssh $$h mkdir -p $$p; \
rsync -aP --delete Makefile src tool $$r; \
ssh $$h "cd $$p && make $(wordlist 2,$(words $(REMOTEOPTS)),$(REMOTEOPTS))"; \
echo "Returned from $$r."
help:
@echo
@echo "fiasco Builds the default configuration ($(DFL_TEMPLATE))"
@echo "T=template Build a certain configuration"
@echo "checkall Build all template configurations in one go"
@echo "list List templates"
@echo
@echo "config menuconfig xconfig oldconfig"
@echo " Configure kernel in \"$(DFLBUILDDIR)\""
@echo "$(DFLBUILDDIR) Build kernel in \"$(DFLBUILDDIR)\""
@echo "clean cleanall clean or cleanall in \"$(CLEANSUBDIRS)\""
@echo "purge cleanall, remove \"$(DFLBUILDDIR)\" and build helper"
@echo
@echo "Creating a custom kernel:"
@echo
@echo " Create a build directory with:"
@echo " make BUILDDIR=builddir"
@echo " Then build the kernel:"
@echo " cd builddir"
@echo " make config"
@echo " make"
@echo
@echo "Call \"make help\" in the build directory for more information on build targets."
@echo
@echo "Default target: $(DFLBUILDDIR)"
@echo
.PHONY: man install clean cleanall fiasco.builddir.create fiasco \
l4check checkall config oldconfig menuconfig nconfig xconfig \
randcheck randcheckstop randcheckagain_bash randcheckstat \
randcheckstatloop help

70
src/fiasco/README.md Normal file
View File

@@ -0,0 +1,70 @@
# The L4Re Microkernel Repository
This repository contains the source code of the L4Re microkernel (also known as
the Fiasco microkernel). User level applications are not included in this
package.
The L4Re microkernel is used to construct flexible systems that support
running real-time, time-sharing and virtualization workloads concurrently on
one system. The kernel scales from big and complex systems down to small and
embedded applications. It supports the following architectures:
| Architecture | 32 bit | 64 bit | Status |
|:------------:|:------:|:------:|:-----------------:|
| x86 | x | x | ![Build check][3] |
| ARM | x | x | ![Build check][4] |
| MIPS | x | x | ![Build check][5] |
| RISC-V | x | x | ![Build check][6] |
For a full list of the supported platforms and features see the [feature
list][1].
We welcome contributions to the microkernel. Please see our contributors guide
on [how to contribute][2].
[1]: https://l4re.org/fiasco/features.html
[2]: https://kernkonzept.com/L4Re/contributing/fiasco
[3]: https://github.com/kernkonzept/fiasco/actions/workflows/check_build_x86.yml/badge.svg?branch=master
[4]: https://github.com/kernkonzept/fiasco/actions/workflows/check_build_arm.yml/badge.svg?branch=master
[5]: https://github.com/kernkonzept/fiasco/actions/workflows/check_build_mips.yml/badge.svg?branch=master
[6]: https://github.com/kernkonzept/fiasco/actions/workflows/check_build_riscv.yml/badge.svg?branch=master
## Reporting vulnerabilities
We encourage responsible disclosure of vulnerabilities you may discover. Please
disclose them privately via **security@kernkonzept.com** to us.
# Building
Fiasco.OC can be built using a recent version of gcc (>=7) or clang (>=9),
GNU binutils, GNU make and Perl (>=5.6).
Change to the top-level directory of this project and create a build directory
by typing
```
$ make BUILDDIR=/path/to/build
```
Change to the newly created build directory. You can now modify the default
configuration by typing
```
$ make menuconfig
```
Make the desired changes, save and exit the configuration. Now you can build
the kernel by typing
```
$ make
```
You can also build in parallel by providing a suitable ```-j``` option. If the
build completed successfully you can find the kernel binary as *fiasco* in
the build directory.
For further information please refer to our [detailed build
instructions](https://l4re.org/fiasco/build.html).
# License
The L4Re microkernel is licensed under the GPLv2.
For other licensing options, please contact **info@kernkonzept.com**.

Binary file not shown.

View File

@@ -0,0 +1,18 @@
Do "make DEPS" for full fine-grained dependency information.
---
checksum
boot_info
checksum
---
boot_info
checksum
boot_info
---
TOTAL CIRCULAR DEPS:
2

View File

@@ -0,0 +1,6 @@
Do "make DEPS" for full fine-grained dependency information.
---
TOTAL CIRCULAR DEPS:
0

View File

@@ -0,0 +1,18 @@
Do "make DEPS" for full fine-grained dependency information.
---
checksum
boot_info
checksum
---
boot_info
checksum
boot_info
---
TOTAL CIRCULAR DEPS:
2

View File

@@ -0,0 +1,18 @@
Do "make DEPS" for full fine-grained dependency information.
---
processor
cp0_status
processor
---
cp0_status
processor
cp0_status
---
TOTAL CIRCULAR DEPS:
2

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,6 @@
Do "make DEPS" for full fine-grained dependency information.
---
TOTAL CIRCULAR DEPS:
0

View File

@@ -0,0 +1,13 @@
# lines starting with '*' are black lists for dependents and dependees
# lines starting with '->' are black lists for dependees
# lines starting with ':' are black lists for dependents
# KERNEL
*config.* l4_types types globalconfig
# LIBC
*.?stdlib .?assert .?stdio .?stdarg .?string __main _exit initfini
*.?ctype .?setjmp .?alloca .?limits .?stddef .?cdefs .?signal
*sys_wait sys_types sys_ptrace sys_user .?errno asm_unistd sys_stat
*sys_mman fcntl sys_poll sys_ucontext simpleio keycodes

892
src/fiasco/src/Kconfig Normal file
View File

@@ -0,0 +1,892 @@
mainmenu "Fiasco configuration"
# generic options that might be selected by platforms etc.
config HAS_FPU_OPTION
bool
config HAS_LAZY_FPU
bool
config HAS_VIRT_OBJ_SPACE_OPTION
bool
config HAS_SERIAL_OPTION
bool
config HAS_WATCHDOG_OPTION
bool
config HAS_JDB_DISASM_OPTION
bool
config HAS_JDB_GZIP_OPTION
bool
config HAS_IOMMU_OPTION
bool
config HAS_MP_OPTION
bool
config HAS_COV_OPTION
bool
config HAS_PLAT_AMP_OPTION
bool
config HAS_CPU_VIRT
bool
config HAS_IRQ_DIRECT_INJECT_OPTION
bool
config HAS_CPU_AMP_OPTION
bool
config HAS_CPU_MPU
bool
config HAS_SYNC_CLOCK
bool
config HAS_ONE_SHOT
bool
config HAS_TICKLESS_IDLE
bool
config HAS_DT_OPTION
bool
################################################################################
menu "Target configuration"
# Platform-dependent options.
################################################################################
choice
prompt "Architecture"
default AMD64
# ARCH_CHOICE
endchoice
config BIG_ENDIAN
bool
choice
prompt "Platform"
# ARCH_DEFAULT_PF
# PF_CHOICE
endchoice
# PF_INCLUDE
# PF_SECTION: GLOBAL
config ABI_VF
def_bool y
# PF_SECTION: CPU
config MMU
def_bool y if !HAS_CPU_MPU
config MPU
def_bool y if HAS_CPU_MPU
config CPU_VIRT
bool "Virtualization"
default y
depends on HAS_CPU_VIRT
help
Support virtualization extensions provided by CPUs, including
nested paging. This feature allows you to run a virtual machine
monitor (VMM) on top of Fiasco.
config FPU
bool "Enable FPU co-processor" if HAS_FPU_OPTION
default y if HAS_FPU_OPTION
help
Enable this if your platform has hardware floating point support.
config LAZY_FPU
bool "Enable lazy FPU switching" if HAS_LAZY_FPU && FPU
depends on FPU && HAS_LAZY_FPU
default y if !AMD64
help
Enable this option to allow lazy context switching of FPU / SIMD
processor state. This removes the overhead incurred by eagerly
switching the FPU / SIMD state which is needed to mitigate the lazy
FPU restore side-channel attack found on Intel processors.
It is safe to enable this option on AMD CPUs.
# PF_SECTION: TARGET
config DT
bool "Device tree support"
depends on HAS_DT_OPTION
default y
help
Enable support to discover devices via device tree.
endmenu # target
################################################################################
menu "Kernel options"
# Platform-independent options (mostly).
################################################################################
config MP
bool "Enable symmetric multi-processor support"
default y
depends on HAS_MP_OPTION
help
Enable support for machines with cache-coherent, symmetric multiple
processors.
config AMP
bool "Enable homogeneous asymmetric multi-processor support"
depends on HAS_CPU_AMP_OPTION && HAS_PLAT_AMP_OPTION
help
Enable support for machines with non-cache-coherent, homogeneous
multiple processors.
config MP_MAX_CPUS
int "Maximal supported number of CPUs"
depends on MP || AMP
range 1 8192 if MP
default 16 if MP
range 1 16 if AMP
default 4 if AMP
help
The maximum number of CPUs the kernel supports.
config KMEM_SIZE_AUTO
bool "Automatically determine kernel memory size"
default y
help
If set to 'y' (default), the kernel automatically determines the
amount of kernel memory using Config::kmem_per_cent(). The size of
the kernel memory can be overriden by the kernel command line
parameter "-kmemsize" passed to the boot loader.
config KMEM_SIZE_KB
int "Kernel memory size in KiB"
depends on !KMEM_SIZE_AUTO
range 16 4194304
default 32768 if MMU
default 256 if !MMU
help
The amount of kernel memory in KiB. The size of the kernel memory can
be overridden by the kernel command line parameter "-kmemsize" passed
to the boot loader.
choice
prompt "Thread control block size"
default CONTEXT_SIZE_AUTO
help
Choose the stack size of each thread in the kernel.
config CONTEXT_SIZE_AUTO
bool "Automatic"
help
Uses 8k stack size on 64-bit systems, otherwise 4k stacks.
config CONTEXT_SIZE_8K
bool "8k stacks"
depends on EXPERIMENTAL
help
Use this option to use 8K kernel stacks. Only choose this option
when you know what you're doing.
config CONTEXT_SIZE_4K
bool "4k stacks"
depends on EXPERIMENTAL
help
Use this option to use 4K kernel stacks. Only choose this option
when you know what you're doing.
config CONTEXT_SIZE_2K
bool "2k stacks"
depends on EXPERIMENTAL
help
Use this option to use 2K kernel stacks. Only choose this option
when you know what you're doing.
endchoice
config CONTEXT_8K
bool
default y if CONTEXT_SIZE_8K || (CONTEXT_SIZE_AUTO && BIT64)
config CONTEXT_4K
bool
default y if CONTEXT_SIZE_4K || (CONTEXT_SIZE_AUTO && !BIT64)
config CONTEXT_2K
bool
default y if CONTEXT_SIZE_2K
config SYNC_CLOCK
bool "Synchronize kernel clock with scheduling timer"
depends on HAS_SYNC_CLOCK
default y if !(IA32 || AMD64)
help
Synchronize the kernel clock with the timer, i.e. the kernel clock
is no longer stored in the KIP and advanced with each timer tick,
but instead accessed by directly reading the timer.
This allows for high-precision timestamps and is a prerequisite
for running the scheduling timer in one-shot mode.
config ONE_SHOT
bool "Use scheduling timer in one-shot mode"
depends on HAS_ONE_SHOT
select FINE_GRAINED_CPUTIME
imply TICKLESS_IDLE
help
Compared to periodic timer mode, there is a small overhead in
processing the timeout queue and accounting consumed CPU time, but
one-shot mode allows for more fine-granular scheduling and better
utilization of tickless idle.
When enabling one-shot timer mode it is highly recommended to also
enable "Tickless idle", unless the wakeup latency from idle is
critical.
config TICKLESS_IDLE
bool "Tickless idle"
depends on HAS_TICKLESS_IDLE
help
When a CPU core is idle, disable the timer tick on that core,
detach the core from the RCU subsystem and halt the core until the
next timeout or interrupt.
Tickless idle works best together with the scheduling timer in
one-shot mode, so when enabling tickless idle it is highly
recommended to also set the scheduling timer to one-shot mode.
Tickless idle is good for saving energy, but can incur a small
overhead for waking up from idle.
On x86, tickless idle adds a small overhead on each context switch.
config FINE_GRAINED_CPUTIME
bool "Fine-grained CPU time"
depends on !PERFORMANCE || ONE_SHOT
help
Measure CPU time consumed by a thread from switching to the thread
until switching to another thread. Induces an overhead during each
thread switch, so only activate it for debugging.
choice
prompt "Scheduler"
default SCHED_FIXED_PRIO
config SCHED_FIXED_PRIO
bool "Fixed priority scheduler"
help
Choose this for the standard fixed priority scheduler with
256 priority levels.
config SCHED_WFQ
bool "Weighted fair queueing scheduler"
depends on EXPERIMENTAL
help
Choose this scheduler for a weighted fair queueing scheduler
running with dynamic priorities.
config SCHED_FP_WFQ
bool "Combined fixed priority RT and WFQ scheduler"
depends on EXPERIMENTAL
help
Combination of Fixed priority and weighted fair queueing
scheduler.
endchoice
config SCHED_GRANULARITY
int "Scheduler granularity"
depends on !PF_PC || SCHED_APIC
default 1000
range 10 1000000
help
Scheduler tick granularity in microseconds.
config SCHED_DEF_TIME_SLICE
int "Default thread time slice"
depends on !PF_PC || SCHED_APIC
default 10
range 1 1000000
help
Default thread time slice in scheduler ticks.
config IOMMU
bool "Enable IOMMU support" if HAS_IOMMU_OPTION
depends on HAS_IOMMU_OPTION
help
This option enables support for DMA remapping (IOMMUs).
When this option is enabled and the platform has a supported
IOMMU, by default all DMA will be blocked.
User-level must use kernel DMA spaces in combination with
the IOMMU kernel object to allow DMA.
config IRQ_DIRECT_INJECT
bool "Support direct interrupt forwarding to guests"
depends on CPU_VIRT && HAS_IRQ_DIRECT_INJECT_OPTION
default y
help
Adds support in the kernel to allow the VMM to let Fiasco directly
forward hardware interrupts to a guest. This enables just the
infrastructure. The virtual machine monitor needs to support this
feature as well and manage the hardware interrupts accordingly.
config DISABLE_VIRT_OBJ_SPACE
bool "No virtually mapped array for cap tables" if HAS_VIRT_OBJ_SPACE_OPTION
depends on HAS_VIRT_OBJ_SPACE_OPTION && EXPERIMENTAL && MMU
config VIRT_OBJ_SPACE
def_bool y
depends on HAS_VIRT_OBJ_SPACE_OPTION
depends on !DISABLE_VIRT_OBJ_SPACE
depends on !KERNEL_ISOLATION
depends on MMU
config PHYS_OBJ_SPACE_AVL
bool "Use AVL tree for object space"
depends on EXPERIMENTAL
help
Usually objects in a space are stored in a page-based two-level
tree. Depending on the distribution of the capabilites this might
waste some memory but is always O(1).
By enabling this option the object space is stored in an AVL tree.
This allocates less memory at the expense of an O(log n) lookup
time.
config DISABLE_MAPDB
bool "Disable mapdb"
depends on EXPERIMENTAL
help
This option disables the mapping database that tracks memory resource
delegation in the system. This saves kernel memory that is normally
required to find the task and the location where memory has been
mapped. Enabling this option will make unmap only work on the
affected task and child mappings cannot be (recursively) revoked any
more!
Say N unless you really know what you're doing.
config MAPDB
def_bool y
depends on !DISABLE_MAPDB
config KERNEL_ISOLATION
bool "Enable Kernel Address-Space Isolation" if AMD64
depends on AMD64
select NO_LDT
select NO_IO_PAGEFAULT
select CPU_LOCAL_MAP
help
Use an extra address space (page table) for the microkernel.
Only map a small trampoline and some static code and data into
each user address space and keep the kernel in its own address
space. This mitigates the deferred access rights check of some
Intel CPUs during speculative execution. However, there is the
extra TLB penalty for each system call.
config INTEL_IA32_BRANCH_BARRIERS
bool "Enable strict prediction barriers (IBRS,IBPB,STIBP)" if AMD64 && KERNEL_ISOLATION
depends on AMD64 && KERNEL_ISOLATION
help
Use indirect branch prediction barriers to prevent
speculation-based cache timing side-channels.
This option enables Intel specific indirect branch control
mitigation:
(a) IBRS on all kernel entries to prevent in-kernel
prediction attacks.
(b) STIBP to prevent cross hyper-thread attacks.
(c) IBPB after address space switches to prevent cross
application attacks.
config INTEL_MDS_MITIGATION
bool "Enable MDS mitigation" if AMD64 && KERNEL_ISOLATION
default y if AMD64 && KERNEL_ISOLATION
help
Use CPU buffer clearing to prevent forwarding of speculative data to
a disclosure gadget which allows to infer the value via a cache side
channel attack.
config KERNEL_NX
bool "Enable support for kernel RO and non-executable mappings" \
if AMD64 || (ARM && BIT64 && MMU)
depends on AMD64 || (ARM && BIT64 && MMU)
help
Make kernel mappings either writable or executable, but not
writable and executable at the same time. This makes certain
classes of programming errors more difficult to exploit by a potential
attacker.
config IA32_PCID
bool "Enable usage of Intel PCID feature"
depends on AMD64
depends on KERNEL_ISOLATION
help
Use Intel PCID to implement address space IDs on x86. This should
reduce the amount of TLB flushes needed during address space switches
or user/kernel switches with kernel page table isolation.
config CPU_LOCAL_MAP
bool "Enable CPU local page-tables for kernel mappings" if AMD64 \
&& !KERNEL_ISOLATION && EXPERIMENTAL
depends on AMD64
help
Enable to use per CPU page directories to allow CPU-local
mapping of kernel memory. This is used for kernel isolation
etc.
If unsure say N.
config NO_IO_PAGEFAULT
bool "Disable IO-Port fault IPC" if (IA32 || AMD64) && !KERNEL_ISOLATION
depends on IA32 || AMD64
default y if IA32 || AMD64
help
Disable page-fault IPC for IO-Port accesses. If this option is
enabled, the kernel does not generate page-fault IPC for failed
IO-Port accesses. An exception IPC with a #GP is generated instead.
# PF_SECTION: KERNEL
endmenu # kernel options
################################################################################
menu "Debugging"
# Options relevant for improving the debugging experience.
# Changing these options different from default could make the kernel slower!
################################################################################
menuconfig COV
bool "Coverage support"
depends on HAS_COV_OPTION && !AMP
help
Adds coverage support using gcov or llvm depending on the compiler that
is used. Do not enable this on production systems.
if COV
choice
prompt "Coverage output mode"
default COV_OUTPUT_SERIAL
config COV_OUTPUT_SERIAL
bool "Output via serial"
config COV_OUTPUT_MEMBUF
bool "Output via memory buffer"
help
With this mode coverage output is accumulated in a memory buffer.
This is useful for simulators which have the option to dump a section
of memory into a file.
endchoice
config COV_OUTPUT_MEMBUF_START
hex "Coverage output buffer start address"
depends on COV_OUTPUT_MEMBUF
default 0x94000000 if PF_FVP_BASE_R
default 0x0
help
Physical address of the beginning of the memory buffer, where Fiasco
shall dump its coverage data.
config COV_OUTPUT_MEMBUF_SIZE
hex "Coverage output buffer size"
depends on COV_OUTPUT_MEMBUF
default 0x800000 if PF_FVP_BASE_R
default 0x1000000
help
Length of the memory buffer, where Fiasco shall dump its coverage
data.
endif
config PERFORMANCE
bool "Performance configuration"
select INLINE
select NDEBUG
select NO_FRAME_PTR
select LAZY_FPU
help
Setup the kernel such that performance is chosen over
being friendly for debugging. With this option, no
assertions are included and additional run-time functionality
is de-selected.
config PERF_CNT
bool "Support for performance counters"
depends on (IA32 || AMD64 || ARM || ARM64 || MIPS)
default y if JDB
help
Enable support for performance counters. On IA32/AMD64, enable support
for fixed-function counters if supported by the target allowing to
read these counters from all privilege levels.
config PERF_CNT_COUNT_CPL0
bool "Enable performance counter to count while CPL=0"
depends on (IA32 || AMD64)
depends on PERF_CNT
help
Enable the fixed counters (if available) to count while CPL=0. Be
careful enabling this option because it generates overhead which
could worsen the timing of guest kernels in particular on QEMU.
config PERF_CNT_USER
bool "Allow user-level access to performance counters"
depends on PERF_CNT && EXPERT
depends on IA32 || AMD64 || ARM || ARM64
help
Allows user-level to access performance counters.
Do ONLY enable this when debugging, experimenting or evaluating!
config INLINE
bool "Generate inline code"
default y
help
Inlining specifies that it is desirable for the compiler to
integrate functions declared 'inline' into the calling routine.
This usually leads to faster code, so unless you want to debug the
kernel you should say 'Y' here.
config NDEBUG
bool "Do not compile assertions"
help
Don't insert assertions into the code. Should be enabled for
kernels which are used for measurements.
config NO_FRAME_PTR
bool "Compile without frame pointer"
default y
help
Enabling this option optimizes for speed but makes debugging more
difficult.
config STACK_DEPTH
bool "Measure stack depth of threads"
depends on !PERFORMANCE
help
When this option is enabled, each thread control block is marked
with magic numbers while creation. The function ``show thread
lists'' scans the TCB for these magic numbers and shows the
currently used depth of each thread.
config BEFORE_IRET_SANITY
bool "Sanity checks at syscall entry/exit"
depends on PF_PC
depends on !PERFORMANCE
help
Perform the following additional sanity checks before returning to
usermode:
- Does the thread hold any locks?
- Is the thread locked by any other thread?
- Does the thread have the right state:
* Thread_ready must be set.
* Thread_cancel and Thread_fpu_owner might be set.
* Any other state bit must not be set.
Don't use Fiasco compiled with this option for performance analysis!
config IRQ_SPINNER
bool "Display IRQ activity on VGA screen"
depends on PF_PC
help
Display IRQ activity on VGA screen.
config WATCHDOG
bool "Enable Watchdog support" if HAS_WATCHDOG_OPTION
default y if HAS_WATCHDOG_OPTION
depends on HAS_WATCHDOG_OPTION
help
Enable support for watchdog using the builtin Local APIC and a
performance counter. The watchdog can be enabled using the
-watchdog command line option.
config SERIAL
bool "Support for debugging over serial line" if HAS_SERIAL_OPTION
depends on HAS_SERIAL_OPTION
default y if HAS_SERIAL_OPTION
help
This option enables support for input/output over serial interface.
config UNIT_TEST
bool "Compile unit tests"
select TEST_SUPPORT_CODE
help
Compile fiasco unit tests.
config TEST_SUPPORT_CODE
bool "Compile test support code"
help
Include test support code when compiling Fiasco.
config CODE_RULES_TEST
bool "Build tests checking coding rules"
help
Builds files that are expected to generate warnings to check that
the coding rules are adhered to in a warning-free build. The
warnings are stored and can be evaluated by scripts generated into
the selftest directory inside the build directory. These scripts
then generate TAP output usable by prove.
The tests currently only work when using clang. When building with
gcc the test sources are not built and a test script that always
generates a SKIP is created.
config RT_DBG
bool "Runtime debug information"
default y
help
Adds support for the debugger kernel object, e.g. to set the name of
objects. This information may be used by a debugger to enable OS
aware debugging.
config JDB_KMEM_STATS
bool "Support kernel memory statistics dump"
default y
depends on RT_DBG
help
Support dumping kernel memory statistics to the console. This must be
triggered from user space and requires the JDB capability.
menuconfig JDB
bool "JDB kernel debugger"
default y
select RT_DBG
depends on !AMP
help
The powerful Fiasco kernel debugger.
if JDB
config JDB_LOGGING
bool "JDB extended logging"
default y
help
There are two classes of logging events: Basic events don't
consume any time if they are disabled (ipc, ipc result,
pagefaults, unmap). Extended logging events add an additional
overhead of most probably less than 10 cycles if they are
disabled. These events can be activated/deactivated by the 'O'
command in jdb.
Should be disabled for kernels which are used for measurements.
config JDB_DISASM
bool "JDB disassembler" if HAS_JDB_DISASM_OPTION
default y if HAS_JDB_DISASM_OPTION && !ARM && !MIPS
help
Add support for disassembly. Increases memory foot-print, only
enable when needed.
config JDB_GZIP
bool "GZIP compressed dumps" if HAS_JDB_GZIP_OPTION
default y if HAS_JDB_GZIP_OPTION
help
Add support for gzip compressed dumps of the trace buffer.
Increases memory foot-print, only enabled when needed.
config JDB_ACCOUNTING
bool "JDB accounting"
help
Enable accounting information about IPCs, context switches, page
faults, and other events. The counters are accessible from
userland through the tbuf status page.
Should be disabled for kernels which are used for measurements.
endif # JDB
config POWERSAVE_GETCHAR
bool "Save power in getchar()"
default y
depends on PF_PC
help
This option uses a processor HALT in getchar() to save power and
prevent some P4 processors from being overheated. This option
requires a working timer IRQ to wakeup getchar periodically.
config MBT_COUNTER
bool "Enable model-based testing counter"
depends on EXPERIMENTAL && BIT64
choice
prompt "Warn levels"
default WARN_WARNING
config WARN_NONE
bool "Do not show show any kernel warning"
config WARN_WARNING
bool "Show messages of warning level"
config WARN_ANY
bool "Show all kernel warnings"
endchoice # warn levels
config UART_CHECKSUM
bool "UART checksumming"
help
Ensure serial output integrity by adding checksums to it. This
ensures that the output transmitted over a serial line is not
accidentally altered, thus potentially turning a failing test
into a passing test, etc.
If enabled, the UART output is checksummed continously using
a CRC32 algorithm and the current checksum is printed periodically
with each newline using a checksum tag. A counterpart decoding
filter that checks the consistency of the checksums and removes
the checksum tags from the output is available.
The checksum tag size is 12 characters and it has the following
format:
"\n{hhhhhhhh} "
In this template, the 'h' characters represent lower-case
hexadecimal characters that encode the CRC32 checksum of all the
previous characters in the output (including newline characters,
but excluding the actual checksum tag, i.e. the curly brackets,
the hexadecimal characters in between them and the tailing space
character).
The checksumming starts only after the first checksum tag which
is:
"\n{00000000} "
config FB_CONSOLE
bool "Enable kernel framebuffer console"
depends on IA32 || AMD64 || ARM || ARM64
help
This enables the kernel framebuffer console and, if a framebuffer
is available, will output kernel messages.
# PF_SECTION: DEBUG
endmenu # debugging
################################################################################
menu "Compiling"
# Build-related options (tools, compiler optimizations).
################################################################################
config CC
string "C compiler"
default "gcc"
help
Use this option to override the default C compiler (gcc).
config CXX
string "C++ compiler"
default "g++"
help
Use this option to override the default C++ compiler (g++).
config LD
string "LD linker"
default "ld"
help
Use this operation to override the default linker (ld).
It's especially useful to use the LLVM linker (lld) when using
Clang/Clang++ for compilation.
config HOST_CC
string "C host compiler"
default "gcc"
help
Use this option to override the default C host compiler (gcc).
config HOST_CXX
string "C++ host compiler"
default "g++"
help
Use this option to override the default C++ host compiler (g++).
config OPTIMIZE_FOR_SIZE
bool "Optimize for size (-Os)"
config MAINTAINER_MODE
bool "Do additional checks at build time"
help
This enables the circular dependency and initcall checks.
Say 'Yes' here if you do kernel hacking.
config NO_VERSION
bool "Do not provide build version info"
depends on EXPERT
help
Do not provide build version info to avoid the need to relink all
kernel unit tests on each build.
config LABEL
string "Configuration label"
help
Text string with a name for this configuration. To be displayed in
the kernel boot-up.
# PF_SECTION: COMPILING
endmenu
################################################################################
config EXPERIMENTAL
bool "Prompt for experimental features"
help
Experimental features are available when enabling this option.
Enabling these features might be less than fully secure and may
disrupt the stability of your kernel.
Use with caution!
config EXPERT
bool "Prompt for expert features"
help
Expert features are available when enabling this option. Enabling
these features may pose security risks and may disrupt the stability
of your kernel.
Enable ONLY when you know what you are doing!
Do NOT enable for production builds!
################################################################################
config BIT32
bool
config BIT64
bool
config WARN_LEVEL
int
default 2 if WARN_ANY
default 1 if WARN_WARNING
default 0 if WARN_NONE
config XARCH
string
default "amd64" if AMD64 && PF_PC
default "ia32" if IA32 && PF_PC
# ARCH_NAME
config ABI
string
default "vf"

368
src/fiasco/src/Makeconf Normal file
View File

@@ -0,0 +1,368 @@
# vi:set ft=make:
# -*- Makefile -*-
# Fiasco make configuration file
#
# created 1996/04/20 by hohmuth
#
# ccache would make feature detection slower
CHECKCC = $(if $(shell $(filter-out $(CCACHE),$(CC)) $(1) $(CHECKCC_FLAGS) \
-c -o /dev/null -xc /dev/null >/dev/null 2>&1 || echo X),$(2),$(1))
CHECKCXX = $(if $(shell $(filter-out $(CCACHE),$(CXX)) $(1) $(CHECKCXX_FLAGS) \
-c -o /dev/null -xc++ /dev/null >/dev/null 2>&1 || echo X),$(2),$(1))
CHECKLD = $(shell if $(LD) -v "$1" > /dev/null 2>&1; $\
then echo "$(1)"; else echo "$(2)"; fi)
eval_impl = $(if $($(1)_IMPL),$($(1)_IMPL),$(1))
include $(objbase)/globalconfig.out
# use patsubst here to prevent confusion of syntax highlighting editors :-)
CONFIG_XARCH := $(patsubst "%",%,$(CONFIG_XARCH))
CONFIG_ABI := $(patsubst "%",%,$(CONFIG_ABI))
SYSTEM := $(shell uname)
CC := $(patsubst "%",%,$(CONFIG_CC))
CXX := $(patsubst "%",%,$(CONFIG_CXX))
LD := $(patsubst "%",%,$(CONFIG_LD))
HOST_CC := $(patsubst "%",%,$(CONFIG_HOST_CC))
HOST_CXX := $(patsubst "%",%,$(CONFIG_HOST_CXX))
RM := rm -f
RM_R := rm -rf
ECHO := echo
ECHO_E := bash --norc -c 'echo -e "$$0" "$$@"'
CP := cp
GREP := GREP_OPTIONS= grep
AWKP ?= gawk --posix
CCACHE ?= ccache
CFLAGS :=
CXXFLAGS :=
OPT_CFLAGS := $(if $(CONFIG_OPTIMIZE_FOR_SIZE),-Os,-O3)
OPT_CXXFLAGS := $(if $(CONFIG_OPTIMIZE_FOR_SIZE),-Os,-O3)
NOOPT_CFLAGS := -Os
NOOPT_CXXFLAGS := -Os
ARFLAGS := crsU
srcdir ?= .
L4DIR ?= $(srcdir)/../../../l4
tooldir := $(srcdir)/../tool
MOVE_IF_CHANGE := $(srcdir)/../tool/move-if-change
SHOWDEPS := $(srcdir)/../tool/showdeps
PREPROCESSDEPS := $(srcdir)/../tool/parsedeps
CIRCULAR := $(srcdir)/../tool/circular
ifeq ($(SYSTEM),FreeBSD)
MD5SUM := /sbin/md5
else
MD5SUM := md5sum
endif
# The name of this file can be overridden from the command line or in
# objdir/Makeconf.local.
MODULES_FILE = $(srcdir)/Modules.$(CONFIG_XARCH)
PREPROCESS = $(srcdir)/../tool/preprocess/src/preprocess
ifeq ($(CONFIG_INLINE),y)
PREPROCESS_FLAGS = -i -t
else
PREPROCESS_FLAGS = -t
endif
AS = $(CROSS_COMPILE)as
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
RANLIB = $(CROSS_COMPILE)ranlib
SIZE = $(CROSS_COMPILE)size
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
# Include architecture-specific rules. These may overwrite anything above
include $(srcdir)/Makeconf.$(CONFIG_XARCH)
# Include user-specific rules. These may overwrite anything above
-include $(srcdir)/Makeconf.local
-include $(objbase)/Makeconf.local
get_cc_version_part = $\
$(shell echo $(1) | $(filter-out $(CCACHE),$(CC)) -E -xc - | tail -1)
ifneq ($(CCXX_VERSION),)
CCXX_SUFFIX := -$(CCXX_VERSION)
endif
# We would use "CPP ?= cpp" but make has a default of "$(CC) -E" so we need to
# overwrite the default with 'cpp' too, because 'gcc -E' does not always work
# correctly.
CPP := $(if $(filter undefined default,$(origin CPP)),cpp,$(CPP))
CPP := $(CROSS_COMPILE)$(CPP)$(CCXX_SUFFIX)
detect_cross = $(if $(shell $\
sh -c "command -v $(CROSS_COMPILE)$(1)"),$(CROSS_COMPILE),)$(1)
CC_TYPE := $(if $(findstring clang,$\
$(shell $(call detect_cross,$(CC)) --version)),clang,gcc)
CC_IS_CLANG := $(if $(filter clang,$(CC_TYPE)),1)
CXX_TYPE := $(if $(findstring clang,$\
$(shell $(call detect_cross,$(CXX)) --version)),clang,gcc)
CXX_IS_CLANG := $(if $(filter clang,$(CXX_TYPE)),1)
LD_TYPE := $(if $(and $(LD),$(findstring LLD,$\
$(shell $(call detect_cross,$(LD)) --version))),clang,gnu)
CLANG_TARGET_FLAG = $(addprefix --target=, $(notdir $(CROSS_COMPILE:%-=%)))
comp_prefixes = $(CCXX_WRAP) $(if $(USE_CCACHE),$(CCACHE))
ifeq ($(CC_TYPE),clang)
CC := $(call comp_prefixes) $(CC)$(CCXX_SUFFIX) $(CLANG_TARGET_FLAG)
CHECKCC_FLAGS := -Werror=unknown-warning-option
else
CC := $(call comp_prefixes) $(CROSS_COMPILE)$(CC)$(CCXX_SUFFIX)
endif
ifeq ($(CXX_TYPE),clang)
CXX := $(call comp_prefixes) $(CXX)$(CCXX_SUFFIX) $(CLANG_TARGET_FLAG)
CHECKCXX_FLAGS := -Werror=unknown-warning-option
else
CXX := $(call comp_prefixes) $(CROSS_COMPILE)$(CXX)$(CCXX_SUFFIX)
endif
ifneq ($(LD_TYPE),clang)
LD := $(CROSS_COMPILE)$(LD)
endif
CCVER_ID_MAJOR-gcc := __GNUC__
CCVER_ID_MINOR-gcc := __GNUC_MINOR__
CCVER_ID_PATCHLEVEL-gcc := __GNUC_PATCHLEVEL__
CCVER_ID_MAJOR-clang := __clang_major__
CCVER_ID_MINOR-clang := __clang_minor__
CCVER_ID_PATCHLEVEL-clang := __clang_patchlevel__
CCVER_MAJOR := $(call get_cc_version_part, $(CCVER_ID_MAJOR-$(CC_TYPE)))
CCVER_MINOR := $(call get_cc_version_part, $(CCVER_ID_MINOR-$(CC_TYPE)))
CCVER_PATCHLEVEL := $(call get_cc_version_part, $(CCVER_ID_PATCHLEVEL-$(CC_TYPE)))
CCVER_VERSION-gcc := $(CCVER_MAJOR)
CCVER_VERSION-clang := $(CCVER_MAJOR)$(if $(filter $(CCVER_MAJOR),3),.$(CCVER_MINOR))
CCVER_VERSION := $(CCVER_VERSION-$(CC_TYPE))
CCVER_RELEASE-gcc := $(CCVER_MAJOR).$(CCVER_MINOR)$(if $(filter $\
$(CCVER_MAJOR),1 2 3 4),.$(CCVER_PATCHLEVEL))
CCVER_RELEASE-clang := $(CCVER_MAJOR).$(CCVER_MINOR).$(CCVER_PATCHLEVEL)
CCVER_RELEASE := $(CCVER_RELEASE-$(CC_TYPE))
CCVER_FULL := $(CCVER_MAJOR).$(CCVER_MINOR).$(CCVER_PATCHLEVEL)
L4ALL_INCDIR ?= $(addprefix -I, $(PRIVATE_INCDIR))
L4STD_INCDIR ?= -nostdinc
L4STD_INCDIR_LAST ?= -isystem $(GCCINCDIR)
KERNEL_LDFLAGS += -gc-sections -Map=fiasco.map
SHARED_FLAGS += -fno-pic
SHARED_FLAGS += -ffunction-sections -fdata-sections
SHARED_FLAGS-gcc += -fno-defer-pop
SHARED_FLAGS-gcc += $(if $(CONFIG_FULL_PATH_NAMES_IN_BINARIES),,$\
$(call CHECKCC,-fmacro-prefix-map=$(abspath $(srcdir)/../)=.))
# gcc #57845
SHARED_FLAGS-gcc += $(if $(filter sparc,$(CONFIG_XARCH)),,-freg-struct-return)
SHARED_FLAGS-gcc += $(call CHECKCXX,-Wmisleading-indentation,) $\
-Wlogical-op -Wfloat-equal
SHARED_FLAGS-gcc += $(if $(filter 7 8 9 10,$(CCVER_MAJOR)),-Wno-nonnull)
SHARED_FLAGS += $(if $(CHECK_CI_BUILDCHECK),,-g)
SHARED_FLAGS += -Wall -Wextra $(call CHECKCC,-Wdouble-promotion) $\
$(call CHECKCC,-Wfloat-conversion) -Wmissing-declarations
SHARED_FLAGS += -Wdeprecated
SHARED_FLAGS += -Wimplicit-fallthrough
SHARED_FLAGS-clang += -Wunreachable-code-aggressive
# WARNING EXCEPTION: not all members of a struct used to reflect hardware state
# are necessarily used.
SHARED_FLAGS-clang += -Wno-unused-private-field
# WARNING EXCEPTION: warnings about hiding overloaded functions do not expose
# problems in this code
SHARED_FLAGS-clang += -Wno-overloaded-virtual
# WARNING EXCEPTION: checking a parameter marked with the nonnull attribute for
# NULL is defensive programming.
SHARED_FLAGS-gcc += $(if $(call CHECKCC,-Wnonnull-compare),-Wno-nonnull-compare)
# WARNING EXCEPTION: checked during code review
SHARED_FLAGS-gcc += $(if $(call CHECKCC,-Waddress-of-packed-member),$\
-Wno-address-of-packed-member)
SHARED_FLAGS += -Wundef
SHARED_FLAGS += $(call CHECKCC,-Wformat=2,)
SHARED_FLAGS += $(call CHECKCC,-fno-stack-protector,)
SHARED_FLAGS += $(call CHECKCC,-fdiagnostics-show-option)
SHARED_FLAGS += $(call CHECKCC,-fno-builtin-bcmp)
OPT_CXXFLAGS-gcc += $(call CHECKCXX,-fweb,)
OPT_CFLAGS-gcc += $(call CHECKCC,-fweb,)
OPT_SHARED_FLAGS-gcc += $(call CHECKCC,-frename-registers,)
OPT_SHARED_FLAGS-gcc += $(call CHECKCC,-fgcse-after-reload,)
CXXFLAGS-gcc += -fno-implement-inlines
CXXFLAGS += -std=c++20 $(call CHECKCXX,-fno-sized-deallocation,)
CXXFLAGS += $(call CHECKCXX,-Wsuggest-override)
LDFLAGS += $(call CHECKLD,--no-warn-rwx-segments,) $\
$(call CHECKLD,--no-warn-execstack,)
WNO_DEPRECATED_NON_PROTOTYPE := $(if $(call CHECKCC,-Wdeprecated-non-prototype),$\
-Wno-deprecated-non-prototype)
DIAGNOSTICS_COLOR := $(call CHECKCC,-fdiagnostics-color=always)
# There are older versions of clang that have the mcdc flag but the feature is
# not at the stage where we want to use it. That's why we explicitly check for
# the version number here and dont use CHECK_CXX.
CLANG_SUPPORTS_MCDC := $(shell [ $(CCVER_VERSION) -gt 17 ] && echo 1)
ifneq ($(CONFIG_COV),)
SHARED_FLAGS-gcc += -fprofile-arcs -ftest-coverage
SHARED_FLAGS-clang += -fprofile-instr-generate -fcoverage-mapping \
$(if $(CLANG_SUPPORTS_MCDC),-fcoverage-mcdc) \
-mllvm -instrprof-atomic-counter-update-all
KERNEL_LDFLAGS += $(KERNEL_LDFLAGS-$(CC_TYPE))
OBJ_KERNEL-clang += fiasco-covpath.o
OBJ_KERNEL += $(OBJ_KERNEL-$(CC_TYPE))
OPT_CFLAGS-gcc += -O1
OPT_CXXFLAGS-gcc += -O1
endif
-include $(objbase)/.Host-config
# Configuration dependent compile flags
SHARED_FLAGS-$(CONFIG_NDEBUG) += -DNDEBUG
SHARED_FLAGS += $(if $(CONFIG_NO_FRAME_PTR),-f,-fno-)omit-frame-pointer
# To enable all warnings, including those with false positives.
ENABLE_ALL_WARNINGS ?= n
ifeq ($(ENABLE_ALL_WARNINGS),y)
SHARED_FLAGS += $(call CHECKCC,-Wframe-larger-than=512)
SHARED_FLAGS += -Wconversion -Wsign-conversion
else
# WARNING EXCEPTION: the variables are initialized when the warned about code
# is reached. The false positives are only produced by GCC on -Os
# optimization level.
SHARED_FLAGS-gcc += $(call CHECKCC,-Wno-maybe-uninitialized)
endif
# Eagerly compute SHARED_FLAGS to avoid calling CHECKCC over and over again.
SHARED_FLAGS := $(SHARED_FLAGS) $(SHARED_FLAGS-y)
SHARED_FLAGS += $(SHARED_FLAGS-$(CC_TYPE))
OPT_SHARED_FLAGS += $(OPT_SHARED_FLAGS-$(CC_TYPE))
NOOPT_SHARED_FLAGS += $(NOOPT_SHARED_FLAGS-$(CC_TYPE))
# Eagerly compute LDFLAGS to avoid calling CHECKLD over and over again.
LDFLAGS := $(LDFLAGS)
# Standard compile flags
ASFLAGS += $(SHARED_FLAGS) -DASSEMBLER
ASFLAGS-clang += -no-integrated-as
CFLAGS += $(SHARED_FLAGS) -Wbad-function-cast -Wstrict-prototypes $\
-Wmissing-prototypes
CXXFLAGS += $(SHARED_FLAGS) -fno-rtti -fno-exceptions -Wold-style-cast
OPT_CFLAGS += $(OPT_SHARED_FLAGS)
OPT_CXXFLAGS += $(OPT_SHARED_FLAGS)
NOOPT_CFLAGS += $(NOOPT_SHARED_FLAGS)
NOOPT_CXXFLAGS += $(NOOPT_SHARED_FLAGS)
CPPFLAGS += $(L4STD_INCDIR) $(L4ALL_INCDIR) $(L4STD_INCDIR_LAST)
CXXFLAGS += $(call CHECKCXX,-fno-threadsafe-statics,)
ASFLAGS += $(ASFLAGS-$(CC_TYPE))
CPPFLAGS += $(CPPFLAGS-$(CC_TYPE))
CXXFLAGS += $(CXXFLAGS-$(CC_TYPE))
OPT_CFLAGS += $(OPT_CFLAGS-$(CC_TYPE))
OPT_CXXFLAGS += $(OPT_CXXFLAGS-$(CC_TYPE))
NOOPT_CFLAGS += $(NOOPT_CFLAGS-$(CC_TYPE))
NOOPT_CXXFLAGS += $(NOOPT_CXXFLAGS-$(CC_TYPE))
HOST_CPPFLAGS +=
HOST_CFLAGS += -O2 -Wall -Wextra
HOST_CXXFLAGS += -O2 -Wall -Wextra
# for stddef.h, ...
GCCINCDIR := $(shell $(filter-out $(CCACHE),$(CXX)) $(SHARED_FLAGS) $\
-print-file-name=include)
# Output formatting:
# - set V=0 to prevent printing them (default)
# - set V=1 to see the command line of all tools except the preprocessor
# - set V=2 to see the command line of all tools including the preprocessor
# and verbose output from `move-if-change`
VERBOSE ?= @
VERBOSE_PREP ?= @
ifeq ($(V),1)
VERBOSE :=
else ifeq ($(V),2)
VERBOSE :=
VERBOSE_PREP :=
PREP_MESSAGE ?= @$(ECHO) " ... Preprocessing $(filter %.cpp,$^)"
endif
AR_MESSAGE ?= @$(ECHO) " ==> Archiving into $@"
COMP_MESSAGE ?= @$(ECHO) " ... Making $@"
LINK_MESSAGE ?= @$(ECHO) " ==> Linking $@"
DEP_MESSAGE ?= @$(ECHO) " ... Building dependencies for $<"
PREP_MESSAGE ?= @$(ECHO) " ... Preprocessing $*"
PATCH_MESSAGE ?= @$(ECHO) " ... Writing checksum into "
STRIP_MESSAGE ?= @$(ECHO) " ... Stripping $@"
GENVER_MESSAGE ?= @$(ECHO) " ... Generating version information"
CLEAN_MESSAGE ?= @$(ECHO) "Removing created files"
CLEANALL_MESSAGE?= @$(ECHO) "Removing all created files"
INST_MESSAGE ?= @$(ECHO) "Installing $(^F)"
OK_MESSAGE ?=
COMP_MESSAGE_NOOPT ?= $(COMP_MESSAGE)
ADD_CONFIGFILE = $\
$(VERBOSE)$(OBJCOPY) --add-section .debug.fiasco_config=globalconfig.out $(1)
ifneq ($(V),2)
MOVE_IF_CHANGE += -q
endif
SRC_ALL = $(SRC_S) $(SRC_CPP) $(SRC_C) $(SRC_CC)
ifeq ($(filter clean cleanall mrproper,$(MAKECMDGOALS)),)
DEPS = $(foreach file,$(SRC_ALL), $(dir $(file)).$(notdir $(file)).d)
CC_WHITELIST-gcc := 11 12 13 14 15
# Clang >= 5 required to support C++17. Furthermore:
# - ARM: Clang<9: "asm goto" constructs not supported
# - IA32: Clang<9: "CC_HAS_ASM_FLAG_OUTPUTS" not supported
CC_WHITELIST-clang := 10 11 12 13 14 15 16 17 18 19 20
CC_WHITELIST := $(CC_WHITELIST-$(CC_TYPE))
# https://github.com/llvm/llvm-project/issues/53645 -- e.g. printf=>puts
CC_BLACKLIST-ia32-clang := 12 13 14
# CC_LAST_BROKEN-REVISION* specifies the last broken minor version
# For gcc these are minor version numbers, for clang it is the patchlevel.
CC_LAST_BROKEN_REVISION-gcc-11 := 1
CC_LAST_BROKEN_REVISION := $(CC_LAST_BROKEN_REVISION-$(CC_TYPE)-$(CCVER_MAJOR))
ifneq ($(DISABLE_CC_CHECK),y)
ifeq ($(filter $(CC_WHITELIST),$(CCVER_VERSION)),)
$(error $(CC_TYPE)-$(CCVER_VERSION) is not supported. \
Please use one of the following versions: $(CC_WHITELIST))
endif
CC_BUGFIX_TYPE-clang = PATCHLEVEL
CC_BUGFIX_TYPE-gcc = MINOR
# This relies on minor versions being single digit!
ifneq ($(CC_LAST_BROKEN_REVISION),)
CC_BUGFIX_VERSION := $(CCVER_$(CC_BUGFIX_TYPE-$(CC_TYPE)))
MIN_VER := $(word 2,$(sort $(CC_LAST_BROKEN_REVISION) $(CC_BUGFIX_VERSION)))
ifeq ($(CC_LAST_BROKEN_REVISION),$(or $(MIN_VER),$(CC_LAST_BROKEN_REVISION)))
$(error $(CC_TYPE)-$(CCVER_FULL) is blacklisted, please update)
endif
endif
ifneq ($(strip \
$(filter $(CC_BLACKLIST-$(CONFIG_XARCH)-$(CC_TYPE)),$(CCVER_RELEASE)) \
$(filter $(CC_BLACKLIST-$(CC_TYPE)),$(CCVER_RELEASE)) \
$(filter $(CC_BLACKLIST-$(CONFIG_XARCH)-$(CC_TYPE)),$(CCVER_VERSION)) \
$(filter $(CC_BLACKLIST-$(CC_TYPE)),$(CCVER_VERSION))),)
$(error $(CC_TYPE)-$(CCVER_FULL) is blacklisted, please update)
endif
endif
else
DEPS = /dev/null
endif

View File

@@ -0,0 +1,31 @@
# -*- makefile -*-
# vi:se ft=make:
#OPT_SHARED_FLAGS += $(call CHECKCC,-finline-limit=10000,)
#OPT_CXXFLAGS += $(call CHECKCXX,--param large-function-insns=10000)
#OPT_CFLAGS += $(call CHECKCC,--param large-function-insns=10000)
CROSS_COMPILE ?= x86_64-linux-gnu-
# The -Os option of gcc-4.0 sets max-inline-insns-single to 5 which prevents
# inlining of almost every function
NOOPT_SHARED_FLAGS-gcc += $(call CHECKCC,--param max-inline-insns-single=50)
SHARED_FLAGS-gcc += -mpreferred-stack-boundary=4
SHARED_FLAGS += -m64 -mcmodel=kernel -mno-red-zone
OPT_CFLAGS += -mno-red-zone
OPT_CXXFLAGS += -mno-red-zone
SHARED_FLAGS += $(call CHECKCC,-mno-mmx,)
SHARED_FLAGS += $(call CHECKCC,-mno-sse,)
SHARED_FLAGS += $(call CHECKCC,-mno-sse2,)
SHARED_FLAGS += $(call CHECKCC,-mno-sse3,)
SHARED_FLAGS += $(call CHECKCC,-mno-sse4,)
SHARED_FLAGS += $(call CHECKCC,-mno-sse4a,)
SHARED_FLAGS += $(call CHECKCC,-mno-3dnow,)
SHARED_FLAGS-clang += $(call CHECKCC,-Wno-address-of-packed-member)
ASFLAGS += -m64 -mcmodel=kernel
OBJCOPY_BFDNAME := elf64-x86-64
OBJCOPY_BFDARCH := i386
LD_EMULATION_CHOICE := elf_x86_64 elf_x86_64_fbsd

View File

@@ -0,0 +1,48 @@
# -*- makefile -*-
# vi:se ft=make:
#OPT_SHARED_FLAGS += $(call CHECKCC,-finline-limit=10000,)
CROSS_COMPILE_DFL-$(CONFIG_BIT32) := arm-linux-gnueabihf-
CROSS_COMPILE_DFL-$(CONFIG_BIT64) := aarch64-linux-gnu-
CROSS_COMPILE ?= $(CROSS_COMPILE_DFL-y)
SHARED_FLAGS-$(CONFIG_ARM_PXA) += -mcpu=xscale
SHARED_FLAGS-$(CONFIG_ARM_SA) += -mcpu=strongarm1100
SHARED_FLAGS-$(CONFIG_ARM_920T) += -mcpu=arm920t
SHARED_FLAGS-$(CONFIG_ARM_926) += -mcpu=arm926ej-s
SHARED_FLAGS-$(CONFIG_ARM_1136) += -mcpu=arm1136jf-s
SHARED_FLAGS-$(CONFIG_ARM_1176) += -mcpu=arm1176jzf-s
SHARED_FLAGS-$(CONFIG_ARM_MPCORE) += -mcpu=mpcore
SHARED_FLAGS-$(CONFIG_ARM_CORTEX_A5) += $(call CHECKCC,-mcpu=cortex-a5)
SHARED_FLAGS-$(CONFIG_ARM_CORTEX_A7) += $(call CHECKCC,-mcpu=cortex-a7,-mcpu=cortex-a9)
SHARED_FLAGS-$(CONFIG_ARM_CORTEX_A8) += $(call CHECKCC,-mcpu=cortex-a8)
SHARED_FLAGS-$(CONFIG_ARM_CORTEX_A9) += $(call CHECKCC,-mcpu=cortex-a9)
SHARED_FLAGS-$(CONFIG_ARM_CORTEX_A15) += $(call CHECKCC,-mcpu=cortex-a15,-mcpu=cortex-a9)
SHARED_FLAGS-$(CONFIG_ARM_CORTEX_A35) += $(call CHECKCC,-mcpu=cortex-a35,-march=armv8-a)
SHARED_FLAGS-$(CONFIG_ARM_CORTEX_A53) += $(call CHECKCC,-mcpu=cortex-a53,-march=armv8-a)
SHARED_FLAGS-$(CONFIG_ARM_CORTEX_A55) += $(call CHECKCC,-mcpu=cortex-a55,-march=armv8-a)
SHARED_FLAGS-$(CONFIG_ARM_CORTEX_A57) += $(call CHECKCC,-mcpu=cortex-a57,-march=armv8-a)
SHARED_FLAGS-$(CONFIG_ARM_CORTEX_A72) += $(call CHECKCC,-mcpu=cortex-a72,-march=armv8-a)
SHARED_FLAGS-$(CONFIG_ARM_CORTEX_A73) += $(call CHECKCC,-mcpu=cortex-a73,-march=armv8-a)
SHARED_FLAGS-$(CONFIG_ARM_CORTEX_A76) += $(call CHECKCC,-mcpu=cortex-a76,-march=armv8-a)
SHARED_FLAGS-$(CONFIG_ARM_NEOVERSE_N1) += $(call CHECKCC,-mcpu=neoverse-n1,-march=armv8.2-a)
SHARED_FLAGS-$(CONFIG_ARM_KRAIT) += $(call CHECKCC,-mcpu=krait,-mcpu=cortex-a15)
SHARED_FLAGS-$(CONFIG_ARM_CORTEX_R52) += $(call CHECKCC,-mcpu=cortex-r52,-march=armv8-r)
SHARED_FLAGS-$(CONFIG_ARM_CORTEX_R82) += $(call CHECKCC,-mcpu=cortex-r82,-march=armv8-a) # armv8-r only supported starting with GCC-11
SHARED_FLAGS-$(CONFIG_BIT32) += $(if $(CC_IS_CLANG),,-Wno-psabi)
SHARED_FLAGS-$(CONFIG_BIT32) += -mfloat-abi=soft
SHARED_FLAGS-$(CONFIG_BIT32) += $(call CHECKCC,-masm-syntax-unified)
SHARED_FLAGS-$(CONFIG_BIT32) += $(call CHECKCC,-mno-thumb-interwork)
SHARED_FLAGS-$(CONFIG_BIT32) += $(if $(CONFIG_THUMB2),-mthumb -Xassembler -mimplicit-it=always,-marm) -mabi=aapcs
SHARED_FLAGS-$(CONFIG_BIT64) += -mgeneral-regs-only
SHARED_FLAGS-$(CONFIG_BIT64) += $(call CHECKCC,-mno-outline-atomics)
LDFLAGS-$(CONFIG_BIT32) += --no-warn-mismatch
LDFLAGS += $(LDFLAGS-y)
LD_EMULATION_CHOICE-$(CONFIG_BIT32) := armelf armelf_linux_eabi armelf_fbsd
LD_EMULATION_CHOICE-$(CONFIG_BIT64) := aarch64linux aarch64elf
LD_EMULATION_CHOICE := $(LD_EMULATION_CHOICE-y)
OBJCOPY_BFDNAME-$(CONFIG_BIT32) := elf32-littlearm
OBJCOPY_BFDNAME-$(CONFIG_BIT64) := elf64-littleaarch64
OBJCOPY_BFDNAME := $(OBJCOPY_BFDNAME-y)
OBJCOPY_BFDARCH-$(CONFIG_BIT32) := arm
OBJCOPY_BFDARCH-$(CONFIG_BIT64) := aarch64
OBJCOPY_BFDARCH := $(OBJCOPY_BFDARCH-y)

View File

@@ -0,0 +1,29 @@
# -*- makefile -*-
# vim:se ft=make:
#OPT_SHARED_FLAGS += $(call CHECKCC,-finline-limit=10000,)
#OPT_CXXFLAGS += $(call CHECKCXX,--param large-function-insns=10000)
#OPT_CFLAGS += $(call CHECKCC,--param large-function-insns=10000)
CROSS_COMPILE ?= x86_64-linux-gnu-
# The -Os option of gcc-4.0 sets max-inline-insns-single to 5 which prevents
# inlining of almost every function
NOOPT_SHARED_FLAGS-gcc += $(call CHECKCC,--param max-inline-insns-single=50)
SHARED_FLAGS-gcc += -mpreferred-stack-boundary=2
SHARED_FLAGS += -m32
SHARED_FLAGS-$(CONFIG_REGPARM3) += -mregparm=3
SHARED_FLAGS += $(call CHECKCC,-mno-mmx,)
SHARED_FLAGS += $(call CHECKCC,-mno-sse,)
SHARED_FLAGS += $(call CHECKCC,-mno-sse2,)
SHARED_FLAGS += $(call CHECKCC,-mno-sse3,)
SHARED_FLAGS += $(call CHECKCC,-mno-sse4,)
SHARED_FLAGS += $(call CHECKCC,-mno-sse4a,)
SHARED_FLAGS += $(call CHECKCC,-mno-3dnow,)
SHARED_FLAGS-clang += $(call CHECKCC,-Wno-address-of-packed-member)
ASFLAGS += -m32
OBJCOPY_BFDNAME := elf32-i386
OBJCOPY_BFDARCH := i386
LD_EMULATION_CHOICE := elf_i386 elf_i386_fbsd

View File

@@ -0,0 +1,20 @@
# -*- makefile -*-
# vi:se ft=make:
BITS-$(CONFIG_BIT32) = 32
BITS-$(CONFIG_BIT64) = 64
BITS = $(BITS-y)
CROSS_COMPILE ?= mips-linux-
LD_EMULATION_CHOICE-$(CONFIG_MIPS_LITTLE_ENDIAN) := elf$(BITS)ltsmip
LD_EMULATION_CHOICE-$(CONFIG_MIPS_BIG_ENDIAN) := elf$(BITS)btsmip
LD_EMULATION_CHOICE := $(LD_EMULATION_CHOICE-y)
SHARED_FLAGS-clang += -fno-integrated-as -G0
SHARED_FLAGS += -msoft-float -mabi=$(BITS)
SHARED_FLAGS += -mno-abicalls
SHARED_FLAGS-$(CONFIG_MIPS_LITTLE_ENDIAN) += -EL
SHARED_FLAGS-$(CONFIG_MIPS_BIG_ENDIAN) += -EB
SHARED_FLAGS-$(CONFIG_CPU_MIPS32_R2) += -march=mips32r2
SHARED_FLAGS-$(CONFIG_CPU_MIPS32_R6) += -march=mips32r6
SHARED_FLAGS-$(CONFIG_CPU_MIPS64_R2) += -march=mips64r2
SHARED_FLAGS-$(CONFIG_CPU_MIPS64_R6) += -march=mips64r6

View File

@@ -0,0 +1,8 @@
# -*- makefile -*-
# vi:se ft=make:
CROSS_COMPILE ?= powerpc-linux-
LD_EMULATION_CHOICE := elf32ppc
SHARED_FLAGS += -m32
ASFLAGS += -m32

View File

@@ -0,0 +1,42 @@
# -*- makefile -*-
# vi:se ft=make:
BITS-$(CONFIG_BIT32) = 32
BITS-$(CONFIG_BIT64) = 64
BITS = $(BITS-y)
CROSS_COMPILE ?= riscv64-linux-gnu-
LD_EMULATION_CHOICE := elf$(BITS)lriscv
OBJCOPY_BFDNAME := elf$(BITS)-littleriscv
OBJCOPY_BFDARCH := riscv
RISCV_FPU_EXT-$(CONFIG_RISCV_FPU_SINGLE) = f
RISCV_FPU_EXT-$(CONFIG_RISCV_FPU_DOUBLE) = fd
RISCV_ISA_C-$(CONFIG_RISCV_ISA_C) = c
# Supported ABIs: ilp32 ilp32d ilp32e ilp32f lp64 lp64d lp64f
RISCV_MABI-$(CONFIG_BIT32) := ilp32
RISCV_MABI-$(CONFIG_BIT64) := lp64
SHARED_FLAGS += -mabi=$(RISCV_MABI-y)
RISCV_MARCH_BASE = rv$(BITS)ima$(RISCV_FPU_EXT-y)$(RISCV_ISA_C-y)
# Since version 2.38, binutils by default targets the ISA specification version
# 20191213, where the CSR instructions and the FENCE.I instruction have been
# moved from the I extension into separate extensions: Zicsr and Zifencei
RISCV_ZICSR_ZIFENCEI = $(if $(call CHECKCC,-march=$(RISCV_MARCH_BASE)_zicsr_zifencei -mabi=$(RISCV_MABI-y)),_zicsr_zifencei)
RISCV_MARCH = $(RISCV_MARCH_BASE)$(RISCV_ZICSR_ZIFENCEI)
# With gcc-12 it is no longer possible to allow use of floating-point
# instructions in (inline) assembly, while disabling it for compiler-generated
# code. Until gcc adds such an option for RISC-V we have to assume that it does
# not implicitly generate floating-point instructions!
SHARED_FLAGS-gcc += -march=$(RISCV_MARCH)
# With clang allowing only explicit floating-point instructions is not yet
# possible, let's just assume that clang doesn't create implicit floating point
# instructions, or should it start to do so, introduces the -mno-implicit-float
# option available for other architectures also for RISC-V.
SHARED_FLAGS-clang += -march=$(RISCV_MARCH)
SHARED_FLAGS += -mcmodel=medany

View File

@@ -0,0 +1,7 @@
# -*- makefile -*-
# vi:se ft=make:
CROSS_COMPILE ?= sparc-linux-
LD_EMULATION_CHOICE := elf32_sparc
# why does leon3 not work?
SHARED_FLAGS += -mcpu=leon -m32

334
src/fiasco/src/Makefile Normal file
View File

@@ -0,0 +1,334 @@
srcdir ?= NOT_SET
tooldir := $(srcdir)/../tool
ifneq ($(if $(SANDBOX_IN_PROGRESS),,$(SANDBOX_ENABLE)),)
.PHONY: $(MAKECMDGOALS) do-all-make-targets
do-all-make-targets:
$(VERBOSE)SANDBOX_IN_PROGRESS=1 \
$(tooldir)/sandbox \
--sys-dir "$(or $(SANDBOX_SYSDIR),/)" \
--dir-rw "$(objbase)" \
--dir-ro "$(srcdir)/.." \
--cmd "$(MAKE) -C $(objbase) $(MAKECMDGOALS)"
$(MAKECMDGOALS): do-all-make-targets
VERBOSE ?= @
ifeq ($(V),1)
VERBOSE :=
endif
else
.PHONY: all do-all test-all config textconfig menuconfig xconfig \
oldconfig regenconfig mrproper doc help update nconfig \
savedefconfig listnewconfig oldnoconfig oldaskconfig FORCE
all:
help:
@echo "Possible targets are:"
@echo " menuconfig - configure Fiasco (ncurses mode)"
@echo " config - like menuconfig"
@echo " textconfig - line-oriented config"
@echo " xconfig - configure Fiasco (graphical mode)"
@echo " all - Fiasco binary"
@echo " clean - clear all auto-generated files in auto"
@echo " cleanall - like clean + dependencies"
@echo " mrproper - like cleanall + config files"
@echo " update - update Fiasco and preprocess using svn"
@echo " DEPS - dependencies between kernel object files"
@echo " DEPS.ps - graphical (ps) representation of DEPS"
@echo " DEPS.svg - graphical (svg) representation of DEPS"
@echo " DEPS.tred.ps - transitive reduction of DEPS.ps"
@echo " DEPS.tred.svg - transitive reduction of DEPS.svg"
@echo " doc - doxygen HTML documentation into docs/"
@echo " report - show host configuration information"
@echo " TAGS tags - create tags files"
ifneq ($(srcdir),NOT_SET)
Makefile: $(srcdir)/templates/Makefile.builddir.templ
perl -p -i -e '$$s = "$(srcdir)"; s/\@SRCDIR\@/$$s/' \
< $< >$@
endif
ifneq ($(MAKECMDGOALS),help)
ifeq ($(srcdir),NOT_SET)
all $(filter config %config,$(MAKECMDGOALS)):
@echo "======================================================================"
@echo " Building Fiasco in the src directory is not possible!"
@echo ""
@echo " Go to the Fiasco root directory and create your build directory with"
@echo " cd .. && make BUILDDIR=build-dir"
@echo "======================================================================"
@exit 1
else # srcdir != NOT_SET
all: globalconfig.h globalconfig.tags
ifeq ($(filter config %config,$(MAKECMDGOALS)),)
-include globalconfig.out
-include globalconfig.tags
# use patsubst here to prevent confusion of syntax highlighting editors :-)
CONFIG_XARCH := $(patsubst "%",%,$(CONFIG_XARCH))
CONFIG_ABI := $(patsubst "%",%,$(CONFIG_ABI))
ifeq ("$(CONFIG_XARCH)","")
all: menuconfig
@echo "========================================================="
@echo "Now run make again to build!"
@echo "========================================================="
@exit 1
else # ! no XARCH
ifeq ("$(CONFIG_ABI)","")
all:
@echo "========================================================="
@echo "ERROR: No ABI version set (run 'make menuconfig')!"
@echo "========================================================="
@exit 1
else # ! no ABI
#
# At this point, globalconfig.out is up-to-date. Update Modules and
# .Modules.deps, then restart using Makefile.sub1, Makefile.sub2.
#
.PRECIOUS: globalconfig.tags
# Read Make configuration
include $(srcdir)/Makeconf
include $(MODULES_FILE)
MODULES_FILES += $(srcdir)/Modules.generic
ifdef SUBSYSTEMS
_modules_read_ = true
endif
ifdef _modules_read_
GENERATED_MODULES = $(foreach subsys, $(SUBSYSTEMS), \
$(INTERFACES_$(subsys)))
ALL = $(foreach subsys, $(SUBSYSTEMS), $($(subsys)) $($(subsys)_EXTRA))
$(foreach m, $(GENERATED_MODULES), auto/stamp-$(m).ready): $(MODULES_FILES)
.PRECIOUS: .Modules.deps
.Modules.deps: $(MODULES_FILES) globalconfig.h globalconfig.tags | auto
@echo "Cleaning up build directory"
$(VERBOSE)$(RM_R) *.lds *.o fiasco *.d .*.d .*.d.new *.d.new
$(VERBOSE)$(RM_R) auto/*.cc auto/*.h auto/*.S auto/stamp-*.ready
$(VERBOSE)$(RM) dump_tcboffsets
@echo "Creating $@"
@($(foreach mod, $(GENERATED_MODULES), \
echo 'auto/stamp-$(mod).ready: \
$(addsuffix .cpp,$(call eval_impl,$(mod)))'; \
$(foreach cpp, $(call eval_impl,$(mod)), echo '$(cpp).cpp:';) \
echo '$(patsubst %,auto/%.cc,$(call eval_impl,$(mod)))' \
'auto/$(mod).h auto/$(mod)_i.h: \
auto/stamp-$(mod).ready ; \
@[ -e $$@ ] || { $$(RM) $$<; $$(MAKE) $$<; }'; \
)) > $@.new
@($(foreach subsys, $(SUBSYSTEMS), \
echo 'IFDEPS += $(addprefix ., $(addsuffix .cc.d, \
$(foreach in,$(INTERFACES_$(subsys)), \
$(call eval_impl,$(in)))))' ; \
echo 'CXXSRC_$(subsys) += $(addsuffix .cc, \
$(foreach in,$(INTERFACES_$(subsys)), \
$(call eval_impl,$(in))))'; \
echo 'OBJ_$(subsys) += $$(CXXSRC_$(subsys):.cc=.o) \
$$(CSRC_$(subsys):.c=.o) \
$$(ASSRC_$(subsys):.S=.o)' ; ) ) >> $@.new
@echo "GENERATED_MODULES = $(GENERATED_MODULES)" >> $@.new
@echo "ALL = $(ALL)" >> $@.new
@echo "_modules_deps_read_ = true" >> $@.new
@mv $@.new $@
endif # _modules_read_
#
# Makefile.sub1: Create source files.
#
.PHONY: create-sources
create-sources: $(MODULES_FILES) globalconfig.h globalconfig.tags .Modules.deps source
$(MAKE) srcdir=$(srcdir) objbase=$(objbase) -f $(srcdir)/Makefile.sub1
auto/stamp-%.ready: $(MODULES_FILES) globalconfig.h globalconfig.tags .Modules.deps
$(MAKE) srcdir=$(srcdir) objbase=$(objbase) -f $(srcdir)/Makefile.sub1 $@
DEPS_FILES=DEPS DEPS.a4 DEPS.tred
#
# Makefile.sub2: Create everything else.
#
all doc $(addsuffix .ps,$(DEPS_FILES)) $(addsuffix .svg,$(DEPS_FILES)) TAGS tags compile_commands.json: \
$(MODULES_FILES) .Modules.deps create-sources globalconfig.h globalconfig.tags
$(MAKE) srcdir=$(srcdir) objbase=$(objbase) -f $(srcdir)/Makefile.sub2 $@
%.o %_t: $(MODULES_FILES) .Modules.deps create-sources globalconfig.h globalconfig.tags
$(MAKE) srcdir=$(srcdir) objbase=$(objbase) -f $(srcdir)/Makefile.sub2 $@
# Divert any target we do not explicitly mention in this Makefile to
# Makefile.sub2. (Unfortunately 1, this does not work for file
# targets that already exist in this directory. Unfortunately 2,
# .DEFAULT does not accept prerequisites, so we must "make
# create-sources" manually.)
.DEFAULT:
$(MAKE) create-sources
$(MAKE) srcdir=$(srcdir) objbase=$(objbase) -f $(srcdir)/Makefile.sub2 $@
# Well, we need to provide some empty rules for some targets to
# prevent the above catch-all from running amok.
Makerules.local $(srcdir)/Makeconf.local $(objbase)/Makeconf.local \
$(objbase)/.Host-config: ;
%: %.o # delete implicit rule
endif # ! no ABI
endif # ! no XARCH
endif # ! config xconfig menuconfig oldconfig
auto:
@mkdir -p auto
source:
test -e source || ln -sf $(srcdir) source
BSP_DIR := $(wildcard $(srcdir)/kern/*/bsp)
KCONFIG_FILE := Kconfig
KCONFIG_SRC_FILE := $(srcdir)/Kconfig
KCONFIG_BSP_FILES := $(shell find $(BSP_DIR) -name Kconfig -follow -print)
KCONFIG_ARCH_FILES := $(wildcard $(srcdir)/kern/*/Kconfig)
KCONFIG_PART_FILES := $(sort $(KCONFIG_ARCH_FILES)) $(sort $(KCONFIG_BSP_FILES))
kconfig_call = $(MAKE) -C $(tooldir)/kconfig O=$(objbase) \
Kconfig=$(KCONFIG_FILE) \
KCONFIG_AUTOHEADER=globalconfig.h \
KCONFIG_TRISTATE=include/config/tristate.conf \
KCONFIG_CONFIG=globalconfig.out \
KCONFIG_AUTOCONFIG=include/config/auto.conf \
MENUCONFIG_COLOR=blackbg \
INCLUDE_PPC32=$(INCLUDE_PPC32) \
INCLUDE_SPARC=$(INCLUDE_SPARC) \
fiasco_srcdir=$(srcdir)/..
update_globalconfig_tags = \
@$(tooldir)/config-tags globalconfig.out > globalconfig.tags
# save config file dependencies to detect BSP removals
.$(KCONFIG_FILE).parts: FORCE
@echo '$(KCONFIG_PART_FILES)' | cmp -s - $@ || echo '$(KCONFIG_PART_FILES)' > $@
$(KCONFIG_FILE): $(KCONFIG_SRC_FILE) $(KCONFIG_PART_FILES) .$(KCONFIG_FILE).parts \
$(srcdir)/Makefile
@$(tooldir)/gen_kconfig $(KCONFIG_SRC_FILE) $(KCONFIG_FILE) \
$(KCONFIG_PART_FILES)
globalconfig.out: $(KCONFIG_FILE)
+$(VERBOSE)$(kconfig_call) oldconfig
globalconfig.h globalconfig.tags: globalconfig.out
+$(VERBOSE)$(kconfig_call) syncconfig
+$(VERBOSE)$(update_globalconfig_tags)
config: $(KCONFIG_FILE)
+$(VERBOSE)$(kconfig_call) menuconfig
+$(VERBOSE)$(kconfig_call) syncconfig
+$(VERBOSE)$(update_globalconfig_tags)
textconfig: $(KCONFIG_FILE)
+$(VERBOSE)$(kconfig_call) config syncconfig
+$(VERBOSE)$(update_globalconfig_tags)
menuconfig oldconfig xconfig gconfig nconfig randconfig allyesconfig allnoconfig: $(KCONFIG_FILE)
+$(VERBOSE)$(kconfig_call) $@
+$(VERBOSE)$(kconfig_call) syncconfig
+$(VERBOSE)$(update_globalconfig_tags)
olddefconfig oldnoconfig: $(KCONFIG_FILE)
+$(VERBOSE)$(kconfig_call) $@
+$(VERBOSE)$(update_globalconfig_tags)
oldaskconfig: $(KCONFIG_FILE)
+$(VERBOSE)$(kconfig_call) config
+$(VERBOSE)$(update_globalconfig_tags)
listnewconfig savedefconfig: $(KCONFIG_FILE)
+$(VERBOSE)$(kconfig_call) $@
ifneq ($(filter clean cleanall mrproper,$(MAKECMDGOALS)),)
# Try to suck in clean targets from subsystems' Makefile fragments
ifdef _modules_read_
MAKERULES_SUBSYS = $(foreach subsys, $(SUBSYSTEMS), $(firstword $(wildcard $(addsuffix /Makerules.$(subsys),$(addprefix $(srcdir)/,$(VPATH)) $(srcdir)))))
-include $(MAKERULES_SUBSYS)
endif
.DEFAULT:
.PHONY: clean cleanall mrproper \
$(foreach subsys, $(SUBSYSTEMS), clean-$(subsys)) \
$(foreach subsys, $(SUBSYSTEMS), cleanall-$(subsys))
clean: $(foreach subsys, $(SUBSYSTEMS), clean-$(subsys))
$(VERBOSE)$(RM) $(strip $(ALL))
$(VERBOSE)$(RM) *.o fiasco fiasco.map
$(VERBOSE)$(RM) auto/*.cc auto/*.h auto/*.S auto/stamp-*.ready
$(VERBOSE)$(RM) .Clean-auto .$(KCONFIG_FILE).parts
cleanall: clean $(foreach subsys, $(SUBSYSTEMS), cleanall-$(subsys))
$(foreach subdir, $(SUBDIRS), $(VERBOSE)$(RM) $(subdir)/*.d $(subdir)/.*.d)
$(VERBOSE)$(RM) *.d .*.d .*.d.new *.d.new *~ *.diag
$(VERBOSE)$(RM) globalconfig.h globalconfig.tags globalconfig.h.old Circular
$(VERBOSE)$(RM) .Modules.deps source .Compiler-config
$(VERBOSE)$(RM_R) scripts
mrproper: cleanall
$(VERBOSE)$(RM_R) globalconfig.out Modules.* DEPS*
$(VERBOSE)$(RM_R) auto docs config
endif # clean, cleanall, mrproper
update:
cd $(srcdir)/.. && svn update
cd $(dir $(PREPROCESS))/.. && svn update
diag:
@echo "Collected diagnostics during build:"
@cat *.diag 2>/dev/null || echo " None"
endif # srcdir != NOT_SET
endif # MAKECMDGOALS != help
define _ver_fun
@echo "$(strip $1) $(or $2,-v):"
@$1 $(or $2,-v) $3 || true
@echo
endef
define _ver_fun_var
@echo -n "$1: "
$(call _ver_fun,$($1),$2,$3)
endef
_ver_fun_vars=$(foreach v,$1,$(call _ver_fun_var,$v,$2,$3))
report:
$(call _ver_fun,make)
$(call _ver_fun_vars,CC CXX HOST_CC HOST_CXX,-v, 2>&1)
$(call _ver_fun_var,LD)
endif

View File

@@ -0,0 +1,136 @@
# -*- makefile -*-
# Targets in this Makefile:
# - all: Create C++ sources from Preprocess input
#
# This Makefile is invoked in a sub-Make from the top-level Makefile
# (via Makerules.global) when globalconfig.out, Modules and
# .Modules.deps are up-to-date.
all: do-all
BUILD_SOURCES=true
include $(srcdir)/Makeconf # also reads srcdir/Makeconf.local
# and objdir/Makeconf.local
include globalconfig.tags
include $(MODULES_FILE)
include .Modules.deps
include $(srcdir)/Makerules.global # also reads objdir/Makerules.local
# Read subsystem Makefile fragments. We do not explicity use any
# targets of these fragments in this Makefile, but this include allows
# subsystem Makefile fragments to implicitly create more Makefile
# fragments.
include $(MAKERULES_SUBSYS)
ALL_STAMPS = $(foreach m, $(GENERATED_MODULES), auto/stamp-$(m).ready)
.PHONY: do-all
do-all: $(ALL_STAMPS)
#
# Auto-created source files
#
auto_clean_files = $(strip $(filter-out \
$(addprefix auto/, \
$(addsuffix .cc, \
$(foreach mod, $(GENERATED_MODULES), $(call eval_impl,$(mod)))) \
$(foreach mod, $(GENERATED_MODULES), \
$(mod).h $(mod)_i.h stamp-$(mod).ready)), \
$(wildcard auto/*)))
.Clean-auto: $(MODULES_FILES) .Modules.deps globalconfig.out
$(if $(auto_clean_files),$(RM) $(auto_clean_files))
touch $@
define find_ld_emulation
emulations=$$(LC_ALL=C $(LD) --help | \
grep -i "supported emulations:" | \
sed -e 's/.*supported emulations: //') ; \
unset found_it; \
for e in $$emulations; do \
for c in $(2); do \
if [ "$$e" = "$$c" ]; then \
echo "LD_EMULATION_FLAG = -m $$e" >> $(1); \
found_it=1; \
break; \
fi; \
done; \
if [ "$$found_it" = "1" ]; then \
break; \
fi; \
done; \
if [ "$$found_it" != "1" ]; then \
echo "No known ld emulation found (available: $$emulations)"; \
exit 1; \
fi
endef
# Force that rule to ensure that compiler changes caused by make command line
# or system-wide compiler updates are noticed.
# Do not use .PHONY, because preprocess would then be triggered everytime.
.Compiler-config: force-the-rule
@echo -n "Checking compiler config... "
@echo "CC = $(CC)" > $@.new
@echo "CXX = $(CXX)" >> $@.new
@echo "CPPFLAGS = $(CPPFLAGS)" >> $@.new
@echo "CFLAGS = $(CFLAGS)" >> $@.new
@echo "CXXFLAGS = $(CXXFLAGS)" >> $@.new
@echo "OPT_CFLAGS = $(OPT_CFLAGS)" >> $@.new
@echo "OPT_CXXFLAGS = $(OPT_CXXFLAGS)" >> $@.new
@echo "ASFLAGS = $(ASFLAGS)" >> $@.new
@echo "CONFIG_XARCH = $(CONFIG_XARCH)" >> $@.new
# If the compiler configuration has changed, remove all dependency
# files -- they have just become useless.
# Since all object files are recompiled anyway when the compiler configuration
# has changed, also remove all generated source files, to avoid the situation
# that all generated source files are older than their ready stamp, resulting in
# a startup delay on each make run, due to their recipes being executed unnecessarily.
@$(MOVE_IF_CHANGE) $@.new $@ \
&& { $(RM) .*.d */.*.d auto/*.cc auto/*.h auto/*.S; echo "CHANGED. Recompiling."; } \
|| echo "unchanged."
# For the LLVM linker, -m cannot be detected as "ld.lld --help" does not list
# the supported emulations. But apparently it's also not necessary to pass this
# parameter.
ifeq ($(LD_TYPE),clang)
.Host-config:
else
.Host-config: force-the-rule
@$(call find_ld_emulation,$@.new,$(LD_EMULATION_CHOICE))
@$(MOVE_IF_CHANGE) $@.new $@ || true
endif
force-the-rule: ;
$(ALL_STAMPS): $(MODULES_FILES) .Modules.deps globalconfig.out \
.Clean-auto .Compiler-config .Host-config
# Basename of implementation files = Basename of first .cpp file
impl_name = $(basename $(firstword $(subst -, ,\
$(firstword $(filter %.cpp, $(notdir $(1)))))))
preprocess_cmd = $(PREPROCESS) $(PREPROCESS_FLAGS) \
$(if $(filter $(call impl_name,$(1)),$(ALWAYS_INLINE)),-i,) \
-p auto/new_ -e "$(PREPROCESS_PARTS)" -s -h $(2) \
-c $(call impl_name,$(1)) $(filter %.cpp, $(1))
$(ALL_STAMPS): auto/stamp-%.ready: $(PREPROCESS) | auto
$(PREP_MESSAGE)
$(VERBOSE_PREP)touch $@
$(VERBOSE_PREP)$(call preprocess_cmd,$^,$*)
@for i in $*.h $(call impl_name,$^)_i.h \
$(patsubst %.cpp, %.cc, $(filter %.cpp, $(notdir $^))); \
do \
$(MOVE_IF_CHANGE) auto/new_$$i auto/$$i || true; \
done
$(OK_MESSAGE)
auto:
@mkdir -p auto
.PRECIOUS: auto/stamp-%.ready
.PRECIOUS: %.cc %.h %_i.h

View File

@@ -0,0 +1,295 @@
# -*- makefile -*-
# Targets in this Makefile:
# - all: Run all subsystems' "all" targets
# - doc: Create doxygen documentation in directory "docs"
# - DEPS, DEPS.ps, DEPS.a4.ps, DEPS.tred.ps:
# Create dependency graphs
# - TAGS, tags:
# Create editor tags
# This Makefile is invoked in a sub-Make from the top-level Makefile
# when globalconfig.out, Modules and .Modules.deps are up-to-date and
# all `preprocess'd C++ source files have been created.
all: do-all
$(VERBOSE)$(if $(CONFIG_NO_VERSION),,echo " --> Build-Nr: $$(cat .build_nr)")
BUILD_OBJECTS=true
include $(srcdir)/Makeconf # also reads srcdir/Makeconf.local
# and objdir/Makeconf.local
include globalconfig.tags
include $(MODULES_FILE)
include .Modules.deps
# Compute sets of sources. From these variables, Makeconf computes
# $(DEPS) and $(SRC_ALL). Set them before including Makerules.global.
SRC_S = $(foreach subsys, $(SUBSYSTEMS), $(ASSRC_$(subsys)))
SRC_C = $(foreach subsys, $(SUBSYSTEMS), $(CSRC_$(subsys)))
SRC_CC = $(foreach subsys, $(SUBSYSTEMS), $(CXXSRC_$(subsys)))
include $(srcdir)/Makerules.global # also reads objdir/Makerules.local
include $(MAKERULES_SUBSYS)
-include $(DEPS)
# Recompile everything if the compiler configuration has changed.
OBJS = $(foreach subsys, $(SUBSYSTEMS), $(OBJ_$(subsys)))
$(OBJS): .Compiler-config
#
# Subsystem-specific rules and targets
#
ifeq ("$(CONFIG_MAINTAINER_MODE)","y")
do-all: Checkinitcalls Circular-ok ToDoItems $(ALL)
else # ! maintainer mode
do-all: $(ALL)
endif # ! maintainer mode
Checkinitcalls: $(KERNEL) $(OBJ_KERNEL)
@echo "Checking initcalls"
$(VERBOSE)$(srcdir)/../tool/checkinitcalls \
-k fiasco.debug \
-Werror $(filter-out fiasco.debug, $^) \
$(if $(CROSS_COMPILE),-t $(CROSS_COMPILE)) && \
echo "Initcalls OK"
TOOL_GDB_DIR=$(srcdir)/../tool/gdb
GDB ?= gdb-multiarch
gdb: fiasco
$(VERBOSE)FIASCO_TOOL_GDB_DIR=$(TOOL_GDB_DIR) \
$(GDB) -x $(TOOL_GDB_DIR)/interactive.gdb fiasco
gen_ktrace_events.h: fiasco
$(VERBOSE)FIASCO_TOOL_GDB_DIR=$(TOOL_GDB_DIR) \
$(GDB) --batch -x $(TOOL_GDB_DIR)/gen_ktrace_events.gdb fiasco
ToDoItems:
@files=$$(cd $(srcdir) && \
find . -type f -name '*.cpp' -o -name '*.cc' -o \
-name '*.h' -o -name '*.S' -o -name '*.h'); \
fixme=$$(cd $(srcdir) && cat $$files | grep -wc FIXME); \
XXX=$$(cd $(srcdir) && cat $$files | grep -wc XXX); \
if [ "$$fixme" -ne "0" -o "$$XXX" -ne "0" ]; then \
echo "Found $$fixme times 'FIXME' and $$XXX times 'XXX'"; \
fi
doc: docs/stamp-doc.ready
docs/stamp-doc.ready: $(srcdir)/doxygen.conf \
$(foreach m, $(GENERATED_MODULES), auto/stamp-$(m).ready) | docs
@touch $@
$(VERBOSE)doxygen $(srcdir)/doxygen.conf
docs:
@mkdir -p docs
###
fault_info:
$(VERBOSE)if [ -z "$(IP)" ]; then \
echo ""; \
echo "ERROR: Please provide the faulting instruction location via IP="; \
echo ""; \
exit 1; \
fi
$(VERBOSE)if [ ! -e "fiasco.debug" ]; then \
echo ""; \
echo "ERROR: There is no fiasco.debug finary"; \
echo ""; \
exit 1; \
fi
$(VERBOSE)grep -v -e '^#' globalconfig.out
$(VERBOSE)$(OBJDUMP) -ldSC fiasco.debug | \
grep --color=auto -C12 -E '^(0x)?([[:space:]]|0)*$(IP)'
###
# Make function "makedeps": Creates (on stdout) a list of Make-like
# dependencies in a format suitable for $(SHOWDEPS). Expects a list
# of source (BASE-suffix.{cpp,cc,c}, BASE[_i].h) files as input and extracts
# include directives from them. Dependecies contain only basenames of
# files (up to the first "-"). Suffixes and extensions are stripped.
makedeps= implname () { echo $$1 | sed 's|.*/||; s|_i\.h|.h|; s|[.-].*||;'; };\
for i in $(1); \
do \
echo $$(implname $$i): $$(perl -n -e \
'/^\s*\#include\s+["<](.*).h[">]/ && print "$$1 "; next;' \
$$i); \
done
DEPS: $(SRC_ALL) $(foreach idir, $(PRIVATE_INCDIR), $(wildcard $(idir)/*.h))
$(call makedeps, $^) | $(SHOWDEPS) > $@.new
mv $@.new $@
# Graphical version of DEPS dependency graph.
# XXX DEPS.{dot,ps} only contain dependency graphs for the KERNEL and
# LIBK subsystem. Also, we remove a number of top-level and low-level
# modules from the resulting graph to reduce the overwhelming number
# of edges; however, `gendotdeps' ensures that modules participating
# in circular dependencies are never removed.
GENDOT_FLAGS ?= -t1u1
KERNEL_MODULES_CPP = $(foreach mod, $(INTERFACES_KERNEL) $(INTERFACES_LIBK), \
$(addsuffix .cpp,$(call eval_impl,$(mod)))) \
$(foreach idir, $(srcdir)/kern $(srcdir)/kern/shared \
$(srcdir)/kern/$(CONFIG_XARCH), \
$(wildcard $(idir)/*.h))
DEPS.dot: $(KERNEL_MODULES_CPP)
@echo -n > source_files.mkdeps
@for f in $^ ; do \
echo $$f >> source_files.mkdeps ; \
done
$(srcdir)/../tool/gendotdeps \
-E "$(PREPROCESS_PARTS)" $(addprefix -I,$(PRIVATE_INCDIR)) \
$(EXTRA_INCLUDES) $(addprefix --vpath=,$(VPATH)) $(GENDOT_FLAGS) \
-v -b $(srcdir)/DEPS.blacklist source_files.mkdeps -o $@ || $(RM) $@
@$(RM) source_files.mkdeps
%.ps: %.dot
dot -Tps -Gmclimit=200.0 -Gnslimit=500.0 \
-Gsize=11,10 -Grotate=90 -o $@ $<
%.pdf: %.dot
dot -Tpdf -Gmclimit=200.0 -Gnslimit=500.0 -Gsize=11,10 -o $@ $<
%.a4.ps: %.dot
dot -Tps -Gmclimit=200.0 -Gnslimit=500.0 \
-Gsize="11,8" -Granksep=0.7 -Grotate=90 -o $@ $<
%.tred.ps: %.dot
tred $< | dot -Tps -Gmclimit=200.0 -Gnslimit=500.0 \
-Gsize="11,8" -Granksep=0.7 -Grotate=90 -o $@
%.svg: %.dot
dot -Tsvg -Gmclimit=200.0 -Gnslimit=500.0 \
-Gsize=11,10 -Grotate=90 -o $@ $<
%.a4.svg: %.dot
dot -Tsvg -Gmclimit=200.0 -Gnslimit=500.0 \
-Gsize="11,8" -Granksep=0.7 -Grotate=90 -o $@ $<
%.tred.svg: %.dot
tred $< | dot -Tsvg -Gmclimit=200.0 -Gnslimit=500.0 \
-Gsize="11,8" -Granksep=0.7 -Grotate=90 -o $@
###
# Circular should really be dependent on $(DEPS). However, we cannot
# enforce that all $(DEPS) are made before this target, because the
# Makefile contains "-include $(DEPS)" (which can result in Circular
# being created/updated before all $(DEPS) are). Therefore, depend on
# the fiasco.debug and on main. Once this is made, we know all $(DEPS)
# have been updated.
Circular: $(KERNEL) $(BOOT) $(RUN_TESTS) $(UTEST_BINARIES) $(CHECKSUM)
@echo "Creating $@"
@( \
echo 'Do "make DEPS" for full fine-grained dependency information.';\
for i in $(DEPS); \
do \
$(PREPROCESSDEPS) $$i; \
done | $(SHOWDEPS) | $(CIRCULAR) \
) > $@.new
@mv $@.new $@
# Create a Circular.max file for the first time. Usually this target
# is not needed -- there should be a Circular.max file in the CVS.
$(srcdir)/Circular.max.$(CONFIG_XARCH):
# Circular is not in the dependencies because we do not want a new
# copy of Circular.max every time Circular changes. We nevertheless
# need it to so the copy -- so create it explicitly
$(MAKE) -f $(srcdir)/Makefile.sub2 Circular
cp Circular $@
# Check that the number of circular dependency has not increased in
# this build.
.PHONY: Circular-ok
Circular-ok: $(srcdir)/Circular.max.$(CONFIG_XARCH) Circular
# Circular.max.* must be the first dependency: We are going to
# reference it as $<.
@ max=$$(tail -1 $<); \
current=$$(tail -1 Circular); \
if [ $$current -gt $$max ]; \
then \
echo "Number of circular dependencies increased!"; \
diff -up $< Circular; \
exit 1; \
fi; \
echo "Circular-dependency check OK ($$current <= $$max)"
###
.PHONY: TAGS tags
# Find directories for source and header files. There may be
# duplicates, so weed out the list using a tiny Perl script.
define source-files
( find $(shell perl -e ' \
%seen = (); \
foreach $$i (@ARGV) { \
next if ! -e $$i || $$i eq "."; \
next if defined $$seen{$$i}; \
$$seen{$$i} = 1; \
print "$$i "; \
}' $(filter-out auto, $(VPATH) $(PRIVATE_INCDIR))) \
-maxdepth 1 -type f -name '*.cpp' -o -name '*.h' \
-o -name '*.cc' -o -name '*.c' )
endef
TAGS:
$(source-files) | etags --members --language=c++ -
tags:
$(source-files) | ctags --members --language=c++ -d -w -T -
###
# Resolve absolute path for source file
# 1: (relative) path to source file
ccj_resolve_src = $(abspath $(wildcard $(addsuffix /$(1),$(subst :, ,$(VPATH)))))
# Get object file corresponding to source file
# 1: (relative) path to source file
ccj_src_to_obj = $(basename $(file)).o
# Resolve absolute path for object file corresponding to source file
# 1: (relative) path to source file
ccj_resolve_obj = $(abspath $(call ccj_src_to_obj,$(file)))
# Generate compiler command line for source file
# 1: Compiler used to compile the file
# 2: <...>_flgs prefix
# 3: (relative) path to source file
ccj_resolve_cmd = $($(1)) -c $(call $(2)_flgs,$(basename $(3)),$(call ccj_src_to_obj,$(3))) \
-o $(call ccj_src_to_obj,$(3)) \
$(subst $(abspath .)/,,$(call ccj_resolve_src,$(3)))
# Helper define to output literal comma
ccj_comma = ,
compile_commands.json: FORCE
$(file >$@,[)
$(foreach file,$(SRC_ALL), \
$(file >>$@, {) \
$(file >>$@, "command": "$(strip \
$(if $(filter %.c,$(file)),$(call ccj_resolve_cmd,CC,c,$(file))) \
$(if $(filter %.cc,$(file)),$(call ccj_resolve_cmd,CXX,cc,$(file))) \
$(if $(filter %.S,$(file)),$(call ccj_resolve_cmd,CC,as,$(file))) \
)",) \
$(file >>$@, "directory": "$(abspath .)",) \
$(file >>$@, "file": "$(call ccj_resolve_src,$(file))",) \
$(file >>$@, "output": "$(call ccj_resolve_obj,$(file))") \
$(file >>$@, }$(if $(filter-out $(lastword $(SRC_ALL)),$(file)),$(ccj_comma))) \
)
$(file >>$@,])

View File

@@ -0,0 +1,8 @@
# -*- makefile -*-
$(ABI): $(OBJ_ABI)
$(AR_MESSAGE)
$(VERBOSE)$(RM) $@
$(VERBOSE)$(AR) $(ARFLAGS) $@ $^

View File

@@ -0,0 +1,13 @@
# -*- makefile -*-
# Boot Makefile
# Add future prerequisites somewhere among the list of libraries.
# You really should not have to add anything in the $(LD) line.
include $(srcdir)/boot/$(CONFIG_XARCH)/Makerules.BOOT.$(CONFIG_XARCH)
clean-BOOT:
$(VERBOSE)$(RM) kernel kernel.o $(BOOT_CLEAN)
cleanall-BOOT:
$(VERBOSE)$(RM) fiasco

View File

@@ -0,0 +1,48 @@
# -*- makefile -*-
# $(1) = fiasco
# $(2) = fiasco.debug
# $(3) = symbol of section begin
# $(4) = symbol of section end
define get_checksum
$(OBJDUMP) \
`$(NM) $(2)|sed -n \
's/\([[:xdigit:]]\+\) *. *\<$(3)\>/--start-address=0x\1/p; \
s/\([[:xdigit:]]\+\) *. *\<$(4)\>/--stop-address=0x\1/p'` \
-s $(1) | cut -f3,4,5,6 -d' ' | ./genchecksum
endef
# Generate targets for checksumming and accumulate them as $(CHECKSUM):
# prerequisites.
# $(1) = fiasco - variable
# $(2) = fiasco.debug - variable
# $(3) = target suffix, e.g. unit test name
define all_checksum_rules =
do_chksum$(3): setchecksum genchecksum $(1)
$$(PATCH_MESSAGE)"$(1)"
$$(VERBOSE)\
cscode=$$$$($$(call get_checksum,$(1),$(2),_start,_etext)); \
csdata=$$$$($$(call get_checksum,$(1),$(2),_kernel_data_start,_edata)); \
./setchecksum $(1) 0x$$$$cscode 0x$$$$csdata && echo done > $$@
$$(call INSTALLFILE_RULE,fiasco,fiasco)
$$(CHECKSUM): do_chksum$(3)
endef
# generate checksum targets for normal kernel build
$(eval $(call all_checksum_rules,$(BOOT),$(KERNEL)))
setchecksum: setchecksum.c
$(COMP_MESSAGE)
$(VERBOSE)$(HOST_CC) $(HOST_CPPFLAGS) $(HOST_CFLAGS) -o $@ $^
genchecksum: genchecksum.cc
$(COMP_MESSAGE)
$(VERBOSE)$(HOST_CXX) -fno-rtti -fno-exceptions $(HOST_CPPFLAGS) $(HOST_CXXFLAGS) -o $@ $^
clean-CHECKSUM:
$(VERBOSE)$(RM) genchecksum setchecksum do_chksum* checksum.ro* checksum.rw*

View File

@@ -0,0 +1,60 @@
# -*- makefile -*-
# vi:se ft=make:
# Makerules for all coderules test targets.
#
# The coderule tests check that the coding rules are enforced by the compiler
# by compiling example code which should generate a warning if everything is
# configured as expected.
CRTEST_DIR = selftest/coderules
# select all test_* files to generate a build target for each.
ifeq ($(CXX_TYPE),clang)
# use preprocess for files from $(INTERFACES_CODERULES)
CRTEST_PREP_TESTS = $(INTERFACES_CODERULES)
# no preprocess for files from $(CXXSRC_CODERULES)
CRTEST_NOPREP_TESTS = $(patsubst %.cc,%,$(filter-out \
$(INTERFACES_CODERULES:=.cc),$(CXXSRC_CODERULES)))
else
crtest_subsys: $(CRTEST_DIR)/gcc-skip.t
$(CRTEST_DIR)/gcc-skip.t:
$(VERBOSE)mkdir -p $(@D)
$(VERBOSE)echo "#!/usr/bin/env cat" >$@
$(VERBOSE)echo "1..0 # SKIP Compiler '$(CXX_TYPE)' not supported. Use clang." >>$@
$(VERBOSE)chmod +x $@
endif
CRTEST_TESTS = $(CRTEST_PREP_TESTS) $(CRTEST_NOPREP_TESTS)
CRTEST_PREP_T_FILES := $(addprefix $(CRTEST_DIR)/,\
$(addsuffix .t, $(CRTEST_PREP_TESTS)))
CRTEST_NOPREP_T_FILES := $(addprefix $(CRTEST_DIR)/,\
$(addsuffix .t, $(CRTEST_NOPREP_TESTS)))
WARNING_CHECKER := $(abspath $(srcdir)/../tool/check_diagnostics)
# default target for the CODERULES subsystem, add all .t files
crtest_subsys: $(CRTEST_PREP_T_FILES) $(CRTEST_NOPREP_T_FILES)
# Currently SARIF is somewhat broken for clang wrt. location information. Use text parsing for now
# $(CRTEST_TESTS:=.o): CXXFLAGS += -fdiagnostics-format=sarif -Wno-sarif-format-unstable
$(CRTEST_TESTS:=.o): CXXFLAGS += $(call CHECKCC,-fno-diagnostics-fixit-info -fno-caret-diagnostics)
$(CRTEST_TESTS:=.diag): %.diag: %.o
$(foreach t,$(CRTEST_TESTS),$(eval $t.o: CXX := 2>$t.diag $(CXX)))
$(CRTEST_PREP_T_FILES): $(CRTEST_DIR)/%.t: %.cpp %.diag
$(VERBOSE)mkdir -p $(@D)
$(VERBOSE)echo '#!/usr/bin/env sh' >$@
$(VERBOSE)echo '$(WARNING_CHECKER) $(abspath $^)' >>$@
$(VERBOSE)chmod +x $@
$(CRTEST_NOPREP_T_FILES): $(CRTEST_DIR)/%.t: %.cc %.diag
$(VERBOSE)mkdir -p $(@D)
$(VERBOSE)echo '#!/usr/bin/env sh' >$@
$(VERBOSE)echo '$(WARNING_CHECKER) $(abspath $^)' >>$@
$(VERBOSE)chmod +x $@
clean-CODERULES:
$(VERBOSE)$(RM) -r selftest/coderules
$(VERBOSE)$(RM) *.diag

View File

@@ -0,0 +1,5 @@
# -*- makefile -*-
# No special rules -- crt0.o can be build using implicit rules.
clean-CRT0:

View File

@@ -0,0 +1,7 @@
# -*- makefile -*-
$(CXXLIB): $(OBJ_CXXLIB)
$(AR_MESSAGE)
$(VERBOSE)$(RM) $@
$(VERBOSE)$(AR) $(ARFLAGS) $@ $^

View File

@@ -0,0 +1,17 @@
# -*- makefile -*-
#$(DRIVERS): $(OBJ_DRIVERS)
# $(AR_MESSAGE)
# $(VERBOSE)$(RM) $@
# $(VERBOSE)$(AR) $(ARFLAGS) $@ $?
libdrivers.a: $(filter-out glue%.o, $(OBJ_DRIVERS))
$(AR_MESSAGE)
$(VERBOSE)$(RM) $@
$(VERBOSE)$(AR) $(ARFLAGS) $@ $^
libgluedriverslibc.a: $(filter glue%.o, $(OBJ_DRIVERS))
$(AR_MESSAGE)
$(VERBOSE)$(RM) $@
$(VERBOSE)$(AR) $(ARFLAGS) $@ $^

View File

@@ -0,0 +1,22 @@
# -*- makefile -*-
define bin_to_asm_recipe
$(ECHO_E) ".section .rodata, \"a\"\n" \
".global _binary_$(3)_start\n" \
".global _binary_$(3)_end\n" \
".p2align 3\n" \
"_binary_$(3)_start:\n" \
".incbin \"$(1)\"\n" \
"_binary_$(3)_end:\n" > $(2)
endef
$(addsuffix .bin.S,$(FONT_FILES)): %.bin.S: %
$(VERBOSE)$(call bin_to_asm_recipe,$<,$@,$(subst -,_,$(subst /,_,$(subst .,_,$(strip $(*F))))))
libfonts.a: $(OBJ_FONTS)
$(AR_MESSAGE)
$(VERBOSE)$(RM) $@
$(VERBOSE)$(AR) $(ARFLAGS) $@ $^
clean-FONTS:
$(VERBOSE)$(RM) $(FONT_FILES:%=%.bin.S)

View File

@@ -0,0 +1,19 @@
# -*- makefile -*-
# 'date -r' doesn't work on BSDs, so we use stat there
filedate = $(shell if date --version 2>&1 | grep -q "Free Software F"; then \
date -R -r $(1); \
else \
stat -f '%Sm' $(1); \
fi)
$(GBLCFG): globalconfig.out
$(COMP_MESSAGE)
$(VERBOSE)$(GREP) "CONFIG_.*=[^n].*$$" globalconfig.out | cut -f2- -d'_' > $@.txt
$(VERBOSE)echo "$(call filedate,globalconfig.out)" >> $@.txt
$(VERBOSE)$(OBJCOPY) -I binary -O $(OBJCOPY_BFDNAME) -B $(OBJCOPY_BFDARCH) $@.txt $@
$(VERBOSE)$(RM) $@.txt
clean-GBLCFG:
$(VERBOSE)$(RM) $(GBLCFG)

View File

@@ -0,0 +1,7 @@
# -*- makefile -*-
$(JABI): $(OBJ_JABI)
$(AR_MESSAGE)
$(VERBOSE)$(RM) $@
$(VERBOSE)$(AR) $(ARFLAGS) $@ $^

View File

@@ -0,0 +1,12 @@
$(JDB): $(OBJ_JDB) .$(JDB).deps
$(AR_MESSAGE)
$(VERBOSE)$(LD) -T/dev/null $(LD_EMULATION_FLAG) --unique -r -o $@ $(OBJ_JDB)
.$(JDB).deps: FORCE
$(VERBOSE)echo $(OBJ_JDB) > $@.new
$(VERBOSE)$(MOVE_IF_CHANGE) $@.new $@ || true
cleanall-JDB:
$(VERBOSE)$(RM) .$(JDB).deps

View File

@@ -0,0 +1,7 @@
# -*- makefile -*-
$(LIBC): $(OBJ_LIBC)
$(AR_MESSAGE)
$(VERBOSE)$(RM) $@
$(VERBOSE)$(AR) $(ARFLAGS) $@ $^

View File

@@ -0,0 +1,13 @@
# -*- makefile -*-
$(LIBCOV): $(OBJ_LIBCOV)
$(AR_MESSAGE)
$(VERBOSE)$(RM) $@
$(VERBOSE)$(AR) $(ARFLAGS) $@ $^
clean-LIBCOV:
$(VERBOSE)$(RM) *.gcno
fiasco-covpath.o:
$(COMP_MESSAGE)
$(VERBOSE)echo 'char const *__COV_PATH="$(PWD)/fiasco";' | $(CC) -o $@ -c -xc -

View File

@@ -0,0 +1,7 @@
# -*- makefile -*-
$(LIBDISASM): $(OBJ_LIBDISASM)
$(AR_MESSAGE)
$(VERBOSE)$(RM) $@
$(VERBOSE)$(AR) $(ARFLAGS) $@ $^

View File

@@ -0,0 +1,7 @@
# -*- makefile -*-
$(LIBFDT): $(OBJ_LIBFDT)
$(AR_MESSAGE)
$(VERBOSE)$(RM) $@
$(VERBOSE)$(AR) $(ARFLAGS) $@ $^

View File

@@ -0,0 +1,7 @@
# -*- makefile -*-
$(LIBGZIP): $(OBJ_LIBGZIP)
$(AR_MESSAGE)
$(VERBOSE)$(RM) $@
$(VERBOSE)$(AR) $(ARFLAGS) $@ $^

View File

@@ -0,0 +1,12 @@
# -*- makefile -*-
# Kernel library: stuff which is linked in optionally. This includes
# everything in the lib subdirectory, but may also include optional
# kernel subsystems which may be optimized away
$(LIBK): $(OBJ_LIBK)
$(AR_MESSAGE)
$(VERBOSE)$(RM) $@
$(VERBOSE)$(AR) $(ARFLAGS) $@ $^
clean-LIBK:

View File

@@ -0,0 +1,7 @@
# -*- makefile -*-
$(LIBPERFCTR): $(OBJ_LIBPERFCTR)
$(AR_MESSAGE)
$(VERBOSE)$(RM) $@
$(VERBOSE)$(AR) $(ARFLAGS) $@ $^

View File

@@ -0,0 +1,7 @@
# -*- makefile -*-
$(LIBREGEX): $(OBJ_LIBREGEX)
$(AR_MESSAGE)
$(VERBOSE)$(RM) $@
$(VERBOSE)$(AR) $(ARFLAGS) $@ $^

View File

@@ -0,0 +1,25 @@
# vim:set ft=make:
LIBUART_srcdir := $(strip $(abspath $(srcdir)))
LIBUART_VPATH_abs := $(abspath $(VPATH_LIBUART))
$(LIBUART): FORCE | $(dir $(LIBUART))
$(MAKE_MESSAGE)
$(VERBOSE)$(MAKE) -C uart \
-f $(LIBUART_srcdir)/lib/uart/Makefile \
srcdir=$(LIBUART_srcdir) \
objbase=$(objbase) \
VERBOSE="$(VERBOSE)" \
OBJECTS="$(OBJECTS_LIBUART)" \
TARGET="$(LIBUART)" \
VPATH_LIBUART="$(LIBUART_VPATH_abs)" \
PRIVATE_INCDIR="$(LIBUART_srcdir)/lib/uart $(PRIVATE_INCDIR)"
$(dir $(LIBUART)):
@mkdir -p $@
clean-LIBUART:
$(VERBOSE)$(RM) uart/*.o
cleanall-LIBUART:
$(VERBOSE)$(RM) uart/.*.d

View File

@@ -0,0 +1,8 @@
# -*- makefile -*-
$(SIMPLEMALLOC): $(OBJ_SIMPLEMALLOC)
$(AR_MESSAGE)
$(VERBOSE)$(RM) $@
$(VERBOSE)$(AR) $(ARFLAGS) $@ $^
clean-SIMPLEMALLOC:

View File

@@ -0,0 +1,3 @@
# -*- makefile -*-
include $(srcdir)/kern/$(CONFIG_XARCH)/Makerules.SYMBOLS.$(CONFIG_XARCH)

View File

@@ -0,0 +1,24 @@
# -*- makefile -*-
$(TCBOFFSET): dump_tcboffsets tcboffset.bin
$(COMP_MESSAGE)
$(VERBOSE)./$< tcboffset.bin > $@.new
$(VERBOSE)mv $@.new $@
dump_tcboffsets: dump_tcboffsets.cc tcboffset_in.h globalconfig.h .Compiler-config
$(COMP_MESSAGE)
$(VERBOSE)$(HOST_CXX) -MD -MP -MF .$@.cc.d.new -I . $(HOST_CPPFLAGS) $(HOST_CXXFLAGS) -o $@ $<
@mv .$@.cc.d.new .$@.cc.d
tcboffset.o: tcboffset_in.h
tcboffset.bin: tcboffset.o
$(LINK_MESSAGE)
$(VERBOSE)$(OBJCOPY) -j .e_length -Obinary $< elength.bin
$(VERBOSE)$(OBJCOPY) -j .offsets -Obinary $< offsets.bin
$(VERBOSE)cat elength.bin offsets.bin > $@
$(VERBOSE)$(RM) elength.bin offsets.bin
clean-TCBOFFSET:
$(VERBOSE)$(RM) tcboffset.o tcboffset.bin $(TCBOFFSET) dump_tcboffsets

View File

@@ -0,0 +1,8 @@
# -*- makefile -*-
$(TYPES): $(OBJ_TYPES)
$(AR_MESSAGE)
$(VERBOSE)$(RM) $@
$(VERBOSE)$(AR) $(ARFLAGS) $@ $^

View File

@@ -0,0 +1,78 @@
# -*- makefile -*-
# vi:se ft=make:
# Makerules for all unit test targets.
#
# Each unit test comes in its own kernel binary. Everything is preprocessed and
# compiled together. The linker stage adds the object file of the unit test to
# the link rule.
# All binaries are created in the utest/ directory.
# select all test_* files to generate a build target for each.
UTEST_TESTS-$(CONFIG_SCHED_FIXED_PRIO) = $(sort \
$(filter test_%,$(INTERFACES_UTEST)))
UTEST_TESTS += $(UTEST_TESTS-y)
# the final binaries go into the utest/ folder.
UTEST_BINARIES = $(addprefix utest/,$(UTEST_TESTS))
# select the utest framework files to add to each test build target.
UTEST_FRAMEWORK = $(filter utest_fw%,$(OBJ_UTEST))
# default target for the UTEST subsystem, add all test binaries as prerequisites.
utest_subsys: $(UTEST_BINARIES)
# the expected_* and config_* files go into the utest/ folder as well.
utest_suppl: $(addprefix utest/,$(UTEST_SUPPL))
# Ensure the utest folder exists before the target is build
$(UTEST_BINARIES): | utest/
# create utest folder
utest/:
@mkdir -p utest
# Generate link rules for each unit test binary.
$(foreach tname,$(UTEST_TESTS),\
$(eval $(call gen_kernel_rules,\
utest/$(tname),\
$(tname).debug,\
$$(UTEST_FRAMEWORK) $$(filter $(tname).o,$$(OBJ_UTEST))\
$$(filter $(tname)-%.o,$$(OBJ_UTEST))\
$$(foreach m,$$(UTEST_REQUIRES-$(tname)),\
$$(addsuffix .o,$$(call eval_impl,$$(m)))))))
define gen_utest_suppl_rule
$(1): $(2) globalconfig.out | $(dir $(1))
$$(COMP_MESSAGE)
$$(VERBOSE)ln -snf $$< $$@
endef
# Generate symlink rule for each supplemental file.
# For every supplemental file, the filename f is used
# unless $(f)-XARCH (e.g. 'fname-ia32') exists
# unless $(f)-XARCH-BITS (e.g. 'fname-mips-64') exists
# unless $(f)-bar (e.g. 'f-arm-nolpae') exists where
# 'bar' is evaluated from $(f-config).
$(foreach tname,$(UTEST_SUPPL),\
$(eval $(call gen_utest_suppl_rule,\
utest/$(tname),\
$(firstword $(wildcard $(foreach d,$(ALL_UTEST_DIRS),\
$(foreach f,\
$(if $($(tname)-config),\
$(tname)-$($(tname)-config),) \
$(tname)-$(CONFIG_XARCH)-$(BITS) \
$(tname)-$(CONFIG_XARCH) $(tname),\
$(srcdir)/$(d)/$(f))))))))
# Generate checksum rules for each unit test binary.
ifneq ($(filter CHECKSUM,$(SUBSYSTEMS)),)
$(foreach tname,$(UTEST_TESTS),\
$(eval $(call all_checksum_rules,$\
utest/$(tname),$(tname).debug,-$(tname))))
endif
clean-UTEST:
$(VERBOSE)$(RM) $(addprefix utest/,\
$(UTEST_TESTS) $(UTEST_SUPPL)) $(patsubst %,%.debug,$(UTEST_TESTS))

View File

@@ -0,0 +1,45 @@
# -*- makefile -*-
# vim:set ft=make:
# recent version.h required for any kip*.o files
$(filter kip%.o,$(OBJ_ABI)): $(VERSION)
$(VERSION): FORCE
ifeq ($(CONFIG_NO_VERSION),)
$(GENVER_MESSAGE)
$(VERBOSE)v=`cd $(srcdir) && git rev-parse \
--verify --short HEAD 2>/dev/null`; \
if [ -n "$$v" ]; then \
d=`cd $(srcdir) && git diff-index --name-only HEAD`; \
[ -n "$$d" ] && v="$$v-dirty"; \
else \
v=`LC_ALL=C svnversion -nc $(srcdir) 2>/dev/null`; \
if [ -n "$$v" \
-a "$$v" != "Unversioned directory" ]; then \
v=$${v%[A-Z]}; v="r$${v#*:}"; \
else \
v=`cd $(srcdir) && hg id 2>/dev/null`; \
if [ -n "$$v" ]; then \
v="$${v% *}"; \
else \
v="unknown"; \
fi \
fi \
fi; \
echo "#define CODE_VERSION \"$$v\"" > $@.new
$(VERBOSE)echo "#define BUILD_DATE \"$$(LC_ALL=C date)\"" >> $@.new
$(VERBOSE)if [ -e .build_nr ]; then \
nr=$$(($$(cat .build_nr) + 1)); \
else \
nr=1; \
fi; \
echo $$nr > .build_nr; \
echo "#define BUILD_NR \"$$nr\"" >> $@.new
else
$(VERBOSE)echo "#define CODE_VERSION \"Unknown version\"" > $@.new; \
echo "#define BUILD_DATE \"No date\"" >> $@.new; \
echo "#define BUILD_NR \"1\"" >> $@.new
endif
$(VERBOSE)$(MOVE_IF_CHANGE) $@.new $@ || true
clean-VERSION:

View File

@@ -0,0 +1,139 @@
# -*- makefile -*-
# vi:set ft=make:
#
# Makerules for the sources of Fiasco
#
#
# Source-code locations
#
# If building in a separate srcdir, prepend it to module-provided include paths
ifneq ($(srcdir),.)
VPATH := $(addprefix $(srcdir)/, $(VPATH))
PRIVATE_INCDIR := $(addprefix $(srcdir)/, $(PRIVATE_INCDIR))
endif
# Finally add the current directory and the preprocessor directory
VPATH += . auto
PRIVATE_INCDIR += . auto
#
# Function for all Makerules.<subsystem> files
#
MAKERULES_SUBSYS = $(foreach subsys, $(SUBSYSTEMS), $(firstword $(wildcard $(addsuffix /Makerules.$(subsys),$(VPATH) $(srcdir)))))
#
# Build certain sources with certain compiler flags.
#
# COMP_MESSAGE_NOOPT for files in NOOPT.
comp_msg = $(if $(filter $(1),$(NOOPT)),$(COMP_MESSAGE_NOOPT),$(COMP_MESSAGE))
# {C,CXX}FLAGS: Filter-out -DNDEBUG for files in NONDEBUG.
comp_c_flgs = $(filter-out $(if $(filter $(1),$(NONDEBUG)),-DNDEBUG),$(CFLAGS))
comp_cc_flgs = $(filter-out $(if $(filter $(1),$(NONDEBUG)),-DNDEBUG),$(CXXFLAGS))
# OPT_{C,CXX}FLAGS: For files not in NOPPT. Otherwise NOOPT_{C,CXX}FLAGS.
comp_c_opt_flgs = $(if $(filter $(1),$(NOOPT)),$(NOOPT_CFLAGS),$(OPT_CFLAGS))
comp_cc_opt_flgs = $(if $(filter $(1),$(NOOPT)),$(NOOPT_CXXFLAGS),$(OPT_CXXFLAGS))
# PROF_FLAGS: Only for files neither in NO_PROFILE nor in NOOPT.
comp_prof_flgs = $(if $(filter $(1),$(NOPROFILE)$(NOOPT)),,$(PROF_FLAGS))
# INST_FLAGS: Only for files in INSTRUMENT.
comp_inst_flgs = $(if $(filter $(1),$(INSTRUMENT)),$(INST_FLAGS))
# NOBUILTIN
comp_nobuiltin = $(if $(filter $(1),$(NOBUILTIN)),-fno-builtin)
# NOCOV
NOCOVFLAGS-gcc := -fno-profile-arcs -fno-test-coverage
NOCOVFLAGS-clang := -fno-profile-instr-generate -fno-coverage-mapping \
$(if $(CLANG_SUPPORTS_MCDC),-fno-coverage-mcdc)
NOCOVFLAGS = $(if $(CONFIG_COV),$(NOCOVFLAGS-$(CC_TYPE)))
comp_nocov = $(if $(filter $(1),$(NOCOV)),$(NOCOVFLAGS))
# Put it all together.
c_flgs = $(CPPFLAGS) $(call comp_c_flgs,$(1)) $(call comp_c_opt_flgs,$(1)) \
$(call comp_prof_flgs,$(1)) $(call comp_inst_flgs,$(1)) \
$(call comp_nobuiltin,$(1)) $(call comp_nocov,$(1)) \
$(CFLAGS_$(basename $(notdir $(2))))
cc_flgs = $(CPPFLAGS) $(call comp_cc_flgs,$(1)) $(call comp_cc_opt_flgs,$(1)) \
$(call comp_prof_flgs,$(1)) $(call comp_inst_flgs,$(1)) \
$(call comp_nobuiltin,$(1)) $(call comp_nocov,$(1)) \
$(CXXFLAGS_$(basename $(notdir $(2))))
as_flgs = $(CPPFLAGS) $(ASFLAGS)
###
#
# Implicit rules
#
.PHONY: FORCE
# Diagnostics collection features
ifneq ($(COLLECT_DIAGNOSTICS),)
CFLAGS += $(DIAGNOSTICS_COLOR)
CXXFLAGS += $(DIAGNOSTICS_COLOR)
COLLECT_REDIR ?= 2>&1 | tee $@.diag && ( [ -s $@.diag ] || rm $@.diag )
endif
%.o: %.cc
$(call comp_msg,$*)
$(VERBOSE)$(CXX) -c -MD -MP -MF .$*.cc.d.new -o $@ $(call cc_flgs,\
$*,$@) $< $(COLLECT_REDIR)
@mv .$*.cc.d.new .$*.cc.d
%.S: %.cc
$(call comp_msg,$*)
$(VERBOSE)$(CC) -S -o $@ -fverbose-asm $(call cc_flgs,\
$*,$@) $< $(COLLECT_REDIR)
%.o: %.c
$(call comp_msg,$*)
$(VERBOSE)$(CC) -c -MD -MP -MF .$*.c.d.new -o $@ $(call c_flgs,\
$*,$@) $< $(COLLECT_REDIR)
@mv .$*.c.d.new .$*.c.d
%.S: %.c
$(call comp_msg,$*)
$(VERBOSE)$(CC) -S -o $@ -fverbose-asm $(call c_flgs,\
$*,$@) $< $(COLLECT_REDIR)
%.o: %.S
$(COMP_MESSAGE)
$(VERBOSE)$(CC) -c -MD -MP -MF .$*.S.d.new -o $@ $(call as_flgs,\
) $< $(COLLECT_REDIR)
@mv .$*.S.d.new .$*.S.d
%.i: %.c
$(call comp_msg,$*)
$(VERBOSE)$(CC) -E -dD -o $@ $(call c_flgs,$*,$@) $< $(COLLECT_REDIR)
%.i: %.cc
$(call comp_msg,$*)
$(VERBOSE)$(CXX) -E -dD -o $@ $(call cc_flgs,$*,$@) $< $(COLLECT_REDIR)
%.i: %.S
$(COMP_MESSAGE)
$(VERBOSE)$(CC) -E -dD -o $@ $(as_flgs) $< $(COLLECT_REDIR)
%.lds: %.ld
$(COMP_MESSAGE)
$(VERBOSE)$(CPP) -x c -MD -MP -MF .$@.d -MT $@ -undef -P -DASSEMBLER \
-o $@ $(CPPFLAGS) $< $(COLLECT_REDIR)
(%): %
$(AR_MESSAGE)
$(VERBOSE)$(AR) $(ARFLAGS) $@ $<
vpath %.ld $(srcdir)
# Suck in user-specific optional Makerules files
-include Makerules.local

View File

@@ -0,0 +1,412 @@
# -*- makefile -*-
# vi:se ft=make:
include $(srcdir)/Modules.generic
# UTEST depends on KERNEL and CHECKSUM, must be listed after them
SUBSYSTEMS := $(filter-out UTEST,$(SUBSYSTEMS)) BOOT CHECKSUM SYMBOLS GBLCFG \
$(filter UTEST,$(SUBSYSTEMS))
ifeq ("$(CONFIG_COV)","y")
SUBSYSTEMS += LIBCOV
KERNEL_EXTRA_LIBS += $(LIBCOV)
PRIVATE_INCDIR += lib/gcov/include
INTERFACES_KERNEL-$(CONFIG_JDB) += jdb_cov_module
endif
PREPROCESS_PARTS += arch $(CONFIG_ABI) 64bit iofp recover_jmpbuf \
$(CONFIG_XARCH) apic i8259 pc i8254 fpu \
auto_map_kip io realmode libuart
PREPROCESS_PARTS-$(CONFIG_MP) += need_xcpu_tlb_flush
PREPROCESS_PARTS-$(CONFIG_JDB) += debug log
PREPROCESS_PARTS-$(CONFIG_SCHED_PIT) += pit_timer
PREPROCESS_PARTS-$(CONFIG_SCHED_RTC) += rtc_timer
PREPROCESS_PARTS-$(CONFIG_SCHED_APIC) += apic_timer
PREPROCESS_PARTS-$(CONFIG_SCHED_HPET) += hpet_timer
PREPROCESS_PARTS-$(CONFIG_CPU_VIRT) += svm vmx virtual_space_iface
PREPROCESS_PARTS-$(CONFIG_IOMMU) += virtual_space_iface
PREPROCESS_PARTS += $(PREPROCESS_PARTS-y)
#
# TYPES subsystem
#
PRIVATE_INCDIR += types/$(CONFIG_XARCH) types
#
# ABI Subsystem
#
INTERFACES_ABI += virt
kip_IMPL += kip-amd64-debug
virt_IMPL += virt-ia32
#
# JABI Subsystem
#
JABI := libjabi.a
VPATH += jabi/$(CONFIG_XARCH) jabi
INTERFACES_JABI := jdb_ktrace jdb_obj_info
VPATH_LIBUART := $(srcdir)/lib/uart
PRIVATE_INCDIR += lib/uart
SUBSYSTEMS += LIBUART
LIBUART := uart/libuart.a
OBJECTS_LIBUART = uart_16550.o
#
# DRIVERS subsystem
#
DRIVERS := libdrivers.a libgluedriverslibc.a
VPATH += drivers/$(CONFIG_XARCH) drivers
PRIVATE_INCDIR += drivers/$(CONFIG_XARCH) drivers
INTERFACES_DRIVERS := mux_console console keyb io pci vga_console reset \
processor delayloop mem
ifeq ("$(CONFIG_SERIAL)","y")
INTERFACES_DRIVERS += filter_console uart
INTERFACES_DRIVERS += $(if $(CONFIG_UART_CHECKSUM),stream_crc32)
endif
INTERFACES_DRIVERS += fb_console
reset_IMPL := reset-amd64
uart_IMPL := uart uart-libuart
CXXFLAGS_uart-libuart := $(call LIBUART_UART, 16550)
CXXFLAGS_uart-libuart += -DUART_16550_INIT_MCR=0x08
CXXSRC_DRIVERS := glue_libc.cc
NOOPT += $(patsubst %.o, %, $(OBJ_DRIVERS))
NOCOV += $(patsubst %.o, %, $(OBJ_DRIVERS)) # Because the BOOT subsystem requires DRIVERS.
keyb_IMPL := keyb keyb-pc
io_IMPL := io io-amd64
mem_IMPL := mem mem-amd64
processor_IMPL := processor processor-amd64
#
# FONTS subsystem
#
SUBSYSTEMS += FONTS
FONTS := libfonts.a
FONT_FILES := vgafont.psf
VPATH += ../data/fonts
OBJ_FONTS := $(addsuffix .bin.o,$(FONT_FILES))
NOOPT += $(patsubst %.o, %, $(OBJ_FONTS))
KERNEL_EXTRA_LIBS += $(FONTS)
#
# KERNEL subsystem
#
KERNEL := fiasco.debug
VPATH += kern/$(CONFIG_XARCH) kern/ia32/64 kern/ia32 kern
VPATH += jdb/ia32/64 jdb/ia32 jdb
PRIVATE_INCDIR += kern/$(CONFIG_XARCH) kern/ia32/64 kern/ia32 kern
INTERFACES_KERNEL += __main acpi acpi_fadt acpi_dmar \
irq_chip_ia32 irq_chip_pic \
io_apic intel_iommu io_apic_remapped \
boot_console syscall_entry \
irq_msi io_space apic pit boot_info checksum \
x86desc gdt idt tss timer_irq dirq \
i8259 allocator alternatives
INTERFACES_KERNEL-$(CONFIG_IOMMU) += intel_dmar dmar_space
INTERFACES_KERNEL-$(CONFIG_CPU_VIRT) += svm vmx vm vm_svm vm_vmx_ept
alternatives_IMPL := alternatives alternatives-ia32
apic_IMPL := apic-ia32 apic-ia32-mp
boot_console_IMPL := boot_console-ia32
boot_info_IMPL := boot_info boot_info-ia32
clock_IMPL := clock clock-ia32
config_IMPL := config config-ia32-64 config-ia32
context_IMPL := context context-ia32 context-ia32-64 context-vcpu
continuation_IMPL := continuation-ia32-64
cpu_IMPL := cpu cpu-ia32 cpu-64
dirq_IMPL := dirq-ia32
entry_frame_IMPL := entry_frame entry_frame-amd64
fpu_IMPL := fpu fpu-ia32
ipi_IMPL := ipi ipi-ia32
irq_IMPL := irq irq-ia32
kdb_ke_IMPL += kdb_ke-ia32
kernel_thread_IMPL := kernel_thread kernel_thread-ia32
kernel_uart_IMPL := kernel_uart kernel_uart-libuart
kip_init_IMPL := kip_init-ia32
kmem_IMPL := kmem kmem-ia32 kmem-ia32-64
kmem_alloc_IMPL := kmem_alloc kmem_alloc-ia32
main_IMPL := main-ia32-64 main-ia32
map_util_IMPL := map_util map_util-mem map_util-io map_util-objs
mem_layout_IMPL := mem_layout mem_layout-ia32 mem_layout-ia32-64
mem_space_IMPL := mem_space mem_space-user mem_space-ia32
mem_unit_IMPL := mem_unit-ia32
page_IMPL := page page-ia32
paging_IMPL := paging paging-ia32-64 paging-ia32
perf_cnt_IMPL := perf_cnt perf_cnt-ia32
pic_IMPL := pic pic-i8259
pit_IMPL := pit-i8254
platform_control_IMPL += platform_control-acpi_sleep platform_control-ia32
rtc_IMPL := rtc-ia32
sched_context_IMPL := sched_context-wfq sched_context-fixed_prio \
sched_context-fp_wfq sched_context
sigma0_task_IMPL := sigma0_task sigma0_task-io
space_IMPL := space space-ia32 space-io
spin_lock_IMPL := spin_lock spin_lock-ia32
startup_IMPL := startup startup-ia32
task_IMPL := task task-ia32
tb_entry_IMPL := tb_entry tb_entry-ia32-64
timer_IMPL := timer timer-ia32
thread_IMPL := thread thread-ia32 thread-ia32-64 \
thread-ipc thread-pagefault thread-log \
thread-debug thread-dbf thread-vcpu thread-io
trap_state_IMPL := trap_state-amd64
tss_IMPL := tss-amd64
utcb_init_IMPL := utcb_init utcb_init-ia32
vmem_alloc_IMPL := vmem_alloc vmem_alloc-ia32
watchdog_IMPL := watchdog watchdog-ia32
INTERFACES_KERNEL-$(CONFIG_SERIAL) += uart_console
cpu_lock_IMPL := cpu_lock cpu_lock-generic
ifeq ("$(CONFIG_SCHED_PIT)","y")
timer_IMPL += timer-pit
timer_tick_IMPL += timer_tick-single-vector timer_tick-ia32
endif
ifeq ("$(CONFIG_SCHED_RTC)","y")
timer_IMPL += timer-rtc
timer_tick_IMPL += timer_tick-single-vector timer_tick-ia32
INTERFACES_KERNEL += rtc
endif
ifeq ("$(CONFIG_SCHED_APIC)","y")
timer_IMPL += timer-apic
timer_tick_IMPL += timer_tick-apic
endif
ifeq ("$(CONFIG_SCHED_HPET)","y")
timer_IMPL += timer-hpet
timer_tick_IMPL += timer_tick-single-vector timer_tick-ia32
INTERFACES_KERNEL += hpet
endif
ifeq ("$(CONFIG_JDB)","y")
JDB := jdb_compound.o
SUBSYSTEMS += JDB
INTERFACES_JDB += jdb_io_ports jdb_ptab jdb_trace_set \
jdb_console_buffer loadcnt jdb_io_apic \
jdb_bt jdb_log jdb_iomap jdb_misc \
jdb_halt_thread
CXXSRC_JDB := tb_entry_output.cc
apic_IMPL += apic-debug
jdb_IMPL += jdb-ia32
jdb_bp_IMPL := jdb_bp-ia32 jdb_bp-amd64
jdb_bt_IMPL := jdb_bt-ia32
jdb_entry_frame_IMPL := jdb_entry_frame-ia32
jdb_kern_info_IMPL := jdb_kern_info jdb_kern_info-ia32 jdb_kern_info-apic \
jdb_kern_info-pci jdb_kern_info-bench \
jdb_kern_info-bench-ia32-64 \
jdb_kern_info-dr jdb_kern_info-mtrr
jdb_misc_IMPL := jdb_misc-ia32
jdb_ptab_IMPL := jdb_ptab jdb_ptab-amd64
jdb_screen_IMPL := jdb_screen jdb_screen-ia32
jdb_tcb_IMPL += jdb_tcb-amd64
jdb_trace_set_IMPL := jdb_trace_set jdb_trace_set-ia32
jdb_tbuf_fe_IMPL := jdb_tbuf_fe jdb_tbuf_fe-ia32
INTERFACES_JDB += $(INTERFACES_JDB-y)
endif
CXXSRC_KERNEL := kernel_panic.cc libc_backend_lock.cc
ASSRC_KERNEL := entry.S entry-native.S kip-time.S
ASSRC_KERNEL-$(CONFIG_MP) += tramp-mp.S entry-mp.S
ASSRC_KERNEL-y += tramp-realmode.S tramp-acpi.S
ASSRC_KERNEL-$(CONFIG_CPU_VIRT) += vm_svm_asm.S vm_vmx_asm.S
ASSRC_KERNEL += $(ASSRC_KERNEL-y)
NOOPT += $(filter jdb%,\
$(foreach in,$(INTERFACES_KERNEL), \
$(if $($(in)_IMPL),$($(in)_IMPL),$(in))))
NOOPT += tb_entry_output $(tb_entry_IMPL) $(perf_cnt_IMPL) \
kern_cnt loadcnt $(apic_IMPL) $(watchdog_IMPL) kdb \
$(kernel_uart_IMPL) push_console thread-dbf \
trap_state
NOOPT += $(foreach in,$(INTERFACES_JDB), \
$(if $($(in)_IMPL),$($(in)_IMPL),$(in)))
#
# CRT0 subsystem
#
CRT0 := crt0.o
ASSRC_CRT0 := crt0.S
#
# BOOT subsystem
#
BOOT := fiasco
VPATH += boot/$(CONFIG_XARCH) boot
PRIVATE_INCDIR += boot boot/amd64
CXXSRC_BOOT := boot_libc_glue.cc bootstrap.cc boot_cpu.cc \
direct_cons_putchar.cc
ASSRC_BOOT := boot.S boot_idt.S
NOOPT += $(patsubst %.o, %, $(OBJ_BOOT))
# Also applied for $(DRIVERS) and $(LIBC) which are used by BOOT.
NOCOV += $(patsubst %.o, %, $(OBJ_BOOT))
#
# TCBOFFSET subsystem
#
TCBOFFSET := tcboffset.h
CXXSRC_TCBOFFSET := tcboffset.cc dump_tcboffsets.cc
#
# SYMBOLS subsystem
#
SYMBOLS := Symbols
#
# CHECKSUM subsystem
#
CHECKSUM := checksum_subsys
#
# VERSION subsystem
#
VERSION := version.h
#
# GBLCFG subsystem
#
GBLCFG := gblcfg.o
OBJ_KERNEL += gblcfg.o
#
# CXXLIB Subsystem
#
CXXLIB := libcxx.a
VPATH += lib/cxxlib
CXXSRC_CXXLIB := paranoia.cc
#
# LIBK subsystem
#
LIBK := libk.a
VPATH += lib/libk/$(CONFIG_XARCH) lib/libk
PRIVATE_INCDIR += lib/libk/$(CONFIG_XARCH) lib/libk
INTERFACES_LIBK := atomic lock_guard std_macros
CXXSRC_LIBK += construction.cc
atomic_IMPL := atomic atomic-amd64
#
# LIBGZIP subsystem (only for Jdb)
#
ifneq ($(CONFIG_JDB_GZIP),)
LIBGZIP := libgzip.a
VPATH += lib/gzip
PRIVATE_INCDIR += lib/gzip
CSRC_LIBGZIP := adler32.c crc32.c gzip.c trees.c deflate.c zutil.c
NOOPT += $(patsubst %.o, %, $(OBJ_LIBGZIP))
$(foreach f, adler32 crc32 deflate trees zutil, \
$(eval CFLAGS_$(f) += $(WNO_DEPRECATED_NON_PROTOTYPE) \
-Wno-old-style-definition -Wno-strict-prototypes))
endif
# SIMPLEMALLOC
#
SIMPLEMALLOC := libsimple_malloc.a
VPATH += lib/simple_malloc
PRIVATE_INCDIR += lib/simple_malloc
CXXSRC_SIMPLEMALLOC = simple_malloc.cc
#
# LIBDISASM subsystem (only for Jdb)
#
ifeq ("$(CONFIG_JDB_DISASM)","y")
# $(srcdir)/lib/disasm may be removed
ifeq ($(wildcard $(srcdir)/lib/disasm),)
$(error $(srcdir)/lib/disasm is missing, disable CONFIG_JDB_DISASM)
endif
SUBSYSTEMS += LIBDISASM
KERNEL_EXTRA_LIBS += $(LIBDISASM)
PREPROCESS_PARTS += jdb_disasm
LIBDISASM := libdisasm.a
VPATH += lib/disasm lib/disasm/capstone \
lib/disasm/capstone/arch/X86
PRIVATE_INCDIR += lib/disasm lib/disasm/capstone/include
CXXSRC_LIBDISASM := disasm.cc
CSRC_LIBDISASM := cs.c utils.c \
MCInst.c MCInstrDesc.c MCRegisterInfo.c SStream.c
CSRC_LIBDISASM += X86Module.c X86Disassembler.c X86DisassemblerDecoder.c \
X86Mapping.c X86IntelInstPrinter.c X86ATTInstPrinter.c
CPPFLAGS += -DCAPSTONE_HAS_X86
CFLAGS_X86Mapping = -Wno-unused-parameter -Wno-missing-field-initializers
CFLAGS_X86Disassembler = -Wno-unused-parameter
CFLAGS_X86IntelInstPrinter = -Wno-unused-parameter -Wno-sign-compare
CFLAGS_X86ATTInstPrinter = -Wno-unused-parameter -Wno-sign-compare
CFLAGS_X86DisassemblerDecoder = -Wno-bad-function-cast
# Clang does not support fallthrough warning elision via comments
CFLAGS_X86DisassemblerDecoder += $(if $(CC_IS_CLANG),\
-Wno-implicit-fallthrough)
CFLAGS_X86Mapping += $(if $(CC_IS_CLANG),-Wno-implicit-fallthrough)
endif
#
# LIBPERFCTR subsystem (only for Jdb)
#
LIBPERFCTR := libperfctr.a
VPATH += lib/perfctr
PRIVATE_INCDIR += lib/perfctr
CSRC_LIBPERFCTR := event_set_p5.c event_set_p6.c event_set_amd.c \
event_set_p4.c event_set_x86.c perfctr.c \
event_set_centaur.c
NOOPT += $(patsubst %.o, %, $(OBJ_LIBPERFCTR))
#
# LIBREGEX subsystem (only for Jdb)
#
LIBREGEX := libregex.a
VPATH += lib/regex
PRIVATE_INCDIR += lib/regex
CSRC_LIBREGEX := rx.c
NOOPT += $(patsubst %.o, %, $(OBJ_LIBREGEX))
#
# LIBC Subsystem addendum
#
NOCOV += $(patsubst %.o, %, $(OBJ_LIBC)) # Because the BOOT subsystem requires LIBC.
ifeq ("$(CONFIG_JDB)","y")
ifneq ($(CONFIG_JDB_GZIP),)
ifneq ($(wildcard $(srcdir)/lib/gzip),)
SUBSYSTEMS += LIBGZIP
KERNEL_EXTRA_LIBS += $(LIBGZIP)
INTERFACES_KERNEL += jdb_gzip
endif
endif
ifneq ($(wildcard $(srcdir)/lib/perfctr),)
SUBSYSTEMS += LIBPERFCTR
KERNEL_EXTRA_LIBS += $(LIBPERFCTR)
KERNEL_UNRES_SYMS += -u perfctr_set_cputype
endif
ifneq ($(wildcard $(srcdir)/lib/regex),)
SUBSYSTEMS += LIBREGEX
KERNEL_EXTRA_LIBS += $(LIBREGEX)
PREPROCESS_PARTS += jdb_regex
endif
ifneq ($(filter LIBREGEX LIBDISASM,$(SUBSYSTEMS)),)
SUBSYSTEMS += SIMPLEMALLOC
KERNEL_EXTRA_LIBS += $(SIMPLEMALLOC)
endif
endif
MODULES_FILES += $(MODULES_FILE) $(MODULES_FILE_BSP)
INTERFACES_KERNEL += $(INTERFACES_KERNEL-y)

424
src/fiasco/src/Modules.arm Normal file
View File

@@ -0,0 +1,424 @@
# -*- makefile -*-
# vi:se ft=make:
###############################################################################
include $(srcdir)/Modules.generic
SUBSYSTEMS += LIBUART
PREPROCESS_PARTS += $(CONFIG_ABI) $(CONFIG_XARCH) libuart
ifeq ($(CONFIG_BIT64),y)
PREPROCESS_PARTS += 64bit arm_esr_traps
BITS := 64
else
PREPROCESS_PARTS += 32bit recover_jmpbuf
PREPROCESS_PARTS-$(CONFIG_MMU) += abs_syscalls
BITS := 32
endif
# On ARMv7 and above Fiasco uses broadcast TLB invalidation instructions. On
# MPU systems, IPIs are always required because each CPU has its own MPU
# instance.
NEED_TLB_IPI := $(if $(CONFIG_MMU),$(if $(CONFIG_ARM_V7PLUS),,y),y)
PREPROCESS_PARTS-$(CONFIG_MP) += $(if $(NEED_TLB_IPI),need_xcpu_tlb_flush)
PREPROCESS_PARTS-$(CONFIG_JDB) += debug log
PREPROCESS_PARTS-$(CONFIG_ARM_CACHE_L2CXX0) += outer_cache outer_cache_l2cxx0
PREPROCESS_PARTS-$(CONFIG_ARM_920T) += arm_v5 vcache
PREPROCESS_PARTS-$(CONFIG_ARM_926) += arm_v5 vcache
PREPROCESS_PARTS-$(CONFIG_CPU_VIRT) += vgic arm_esr_traps
PREPROCESS_PARTS-$(CONFIG_ARM_SVE) += fpu_alloc_typed
PREPROCESS_PARTS-$(CONFIG_IOMMU) += virtual_space_iface
#
# TYPES subsystem
#
PRIVATE_INCDIR += types/$(CONFIG_XARCH)/$(BITS) types/$(CONFIG_XARCH) types
VPATH_LIBUART := $(srcdir)/lib/uart
PRIVATE_INCDIR += lib/uart
#
# DRIVERS Subsystem
#
DRIVERS := libdrivers.a libgluedriverslibc.a
VPATH += drivers/$(CONFIG_XARCH)/$(BITS) drivers/$(CONFIG_XARCH) drivers
PRIVATE_INCDIR += drivers/$(CONFIG_XARCH)/$(BITS) drivers/$(CONFIG_XARCH) drivers
INTERFACES_DRIVERS := sa1100 mux_console console uart filter_console \
h3xxx io mem mmu reset processor delayloop ve_sysregs
INTERFACES_DRIVERS += $(if $(CONFIG_UART_CHECKSUM),stream_crc32)
INTERFACES_DRIVERS += fb_console
io_IMPL := io io-arm
mmu_IMPL := mmu mmu-arm mmu-arm-$(BITS)
mem_IMPL := mem mem-arm
uart_IMPL := uart uart-libuart
reset_IMPL :=
processor_IMPL := processor processor-arm-$(BITS) processor-arm
CXXSRC_DRIVERS := glue_libc.cc
NOOPT += $(patsubst %.o, %, $(OBJ_DRIVERS))
ALWAYS_INLINE += mem
#
# LIBREGEX subsystem (only for Jdb)
#
LIBREGEX := libregex.a
VPATH += lib/regex
PRIVATE_INCDIR += lib/regex
CSRC_LIBREGEX := rx.c
NOOPT += $(patsubst %.o, %, $(OBJ_LIBREGEX))
#
# LIBC Subsystem addendum
#
CSRC_LIBC += aeabi.c atexit-aeabi.c
#
# LIBGZIP subsystem (only for Jdb)
#
ifneq ($(CONFIG_JDB_GZIP),)
LIBGZIP := libgzip.a
VPATH += lib/gzip
PRIVATE_INCDIR += lib/gzip
CSRC_LIBGZIP := adler32.c crc32.c gzip.c trees.c deflate.c zutil.c
NOOPT += $(patsubst %.o, %, $(OBJ_LIBGZIP))
$(foreach f, adler32 crc32 deflate trees zutil, \
$(eval CFLAGS_$(f) += $(WNO_DEPRECATED_NON_PROTOTYPE) \
-Wno-old-style-definition -Wno-strict-prototypes))
endif
#
# JABI Subsystem
#
JABI := libjabi.a
VPATH += jabi/$(CONFIG_XARCH)/$(BITS) jabi/$(CONFIG_XARCH) jabi
INTERFACES_JABI := jdb_ktrace jdb_obj_info
#
# FONTS subsystem
#
SUBSYSTEMS += FONTS
FONTS := libfonts.a
FONT_FILES := vgafont.psf
VPATH += ../data/fonts
OBJ_FONTS := $(addsuffix .bin.o,$(FONT_FILES))
NOOPT += $(patsubst %.o, %, $(OBJ_FONTS))
KERNEL_EXTRA_LIBS += $(FONTS)
#
# KERNEL subsystem
#
KERNEL := fiasco
KERNEL_EXTRA := Symbols kernel.arm.lds fiasco.debug
VPATH += kern/$(CONFIG_XARCH)/$(BITS) kern/$(CONFIG_XARCH) kern
VPATH += jdb/arm/$(BITS) jdb/arm jdb
PRIVATE_INCDIR += kern/$(CONFIG_XARCH)/$(BITS) kern/$(CONFIG_XARCH) kern
INTERFACES_KERNEL += __main kmem_space boot_uart_init \
irq_chip_generic bootstrap \
outer_cache utcb_support \
smc_call psci alternatives
NEED_MEM_CHUNK = $(or $(and $(CONFIG_ARM_GIC_MSI),$(CONFIG_HAVE_ARM_GICV3)),\
$(CONFIG_IOMMU))
INTERFACES_KERNEL-$(CONFIG_MPU) += mpu kmem_mpu
INTERFACES_KERNEL-$(NEED_MEM_CHUNK) += mem_chunk
INTERFACES_KERNEL-$(CONFIG_ARM_ACPI) += acpi acpi_fadt
INTERFACES_KERNEL-$(CONFIG_ARM_MPCORE) += scu
INTERFACES_KERNEL-$(CONFIG_ARM_CORTEX_A9) += scu
INTERFACES_KERNEL-$(CONFIG_BIT32)-$(CONFIG_MMU) += kern_lib_page
INTERFACES_KERNEL-$(CONFIG_BIT32) += mem_op
INTERFACES_KERNEL-$(CONFIG_SERIAL) += uart_console
INTERFACES_KERNEL-$(CONFIG_ARM_EM_TZ) += vm
INTERFACES_KERNEL-$(CONFIG_CPU_VIRT) += hyp_vm_state vgic vgic_global
INTERFACES_KERNEL-$(CONFIG_CPU_VIRT)-$(CONFIG_HAVE_ARM_GICV2) += vgic_v2
INTERFACES_KERNEL-$(CONFIG_CPU_VIRT)-$(CONFIG_HAVE_ARM_GICV3) += vgic_v3
INTERFACES_KERNEL-$(CONFIG_ARM_SMC_USER) += smc_user
INTERFACES_KERNEL-$(CONFIG_ARM_GIC) += gic_dist gic
INTERFACES_KERNEL-$(CONFIG_HAVE_ARM_GICV3) += gic_redist
INTERFACES_KERNEL-$(CONFIG_HAVE_ARM_GICV2) += gic_v2 gic_cpu_v2
INTERFACES_KERNEL-$(CONFIG_HAVE_ARM_GICV3) += gic_v3 gic_cpu_v3 gic_its
INTERFACES_KERNEL-$(CONFIG_HAVE_ARM_GIC_MSI) += irq_mgr_msi
INTERFACES_KERNEL-$(CONFIG_ARM_GIC_MSI)-$(CONFIG_HAVE_ARM_GICV3) += gic_mem gic_msi
INTERFACES_KERNEL-$(CONFIG_IOMMU) += iommu arm_dmar dmar_space
INTERFACES_KERNEL += boot_infos
acpi_IMPL := acpi acpi-arm
alternatives_IMPL := alternatives alternatives-arm
bootstrap_IMPL := bootstrap bootstrap-arm-$(BITS)
clock_IMPL := clock
config_IMPL := config config-arm
context_base_IMPL := context_base context_base-arm
context_IMPL := context context-arm context-arm-$(BITS) \
context-vcpu context-arm-hyp context-arm-hyp-$(BITS)
continuation_IMPL := continuation-arm
cpu_IMPL := cpu cpu-arm cpu-arm-$(BITS)
cpu_lock_IMPL := cpu_lock cpu_lock-generic
dmar_space_IMPL := dmar_space \
$(if $(CONFIG_IOMMU_ARM_SMMU_400),dmar_space-smmuv2) \
$(if $(CONFIG_IOMMU_ARM_SMMU_500),dmar_space-smmuv2) \
$(if $(CONFIG_IOMMU_ARM_SMMU_V3),dmar_space-smmuv3)
ifeq ($(CONFIG_BIT64),y)
entry_frame_IMPL := entry_frame-arm
else
entry_frame_IMPL := entry_frame entry_frame-arm
endif
fpu_IMPL := fpu fpu-arm
ifeq ($(CONFIG_ARM_SVE),y)
fpu_alloc_IMPL := fpu_alloc fpu_alloc-arm
endif
gic_IMPL := gic
gic_cpu_v3_IMPL := gic_cpu_v3 gic_cpu_v3-$(BITS)
gic_dist_IMPL := gic_dist
globals_IMPL := globals globals-arm
hyp_vm_state_IMPL := hyp_vm_state hyp_vm_state-$(BITS)
iommu_IMPL := iommu-arm \
$(if $(CONFIG_IOMMU_ARM_SMMU_400),iommu-arm-smmuv2) \
$(if $(CONFIG_IOMMU_ARM_SMMU_500),iommu-arm-smmuv2) \
$(if $(CONFIG_IOMMU_ARM_SMMU_V3),iommu-arm-smmuv3)
ipi_IMPL := ipi ipi-arm
kdb_ke_IMPL += kdb_ke-arm
kernel_task_IMPL := kernel_task kernel_task-arm
kernel_thread_IMPL := kernel_thread kernel_thread-arm \
kernel_thread-arm-$(BITS)
kernel_uart_IMPL := kernel_uart kernel_uart-libuart
map_util_IMPL := map_util map_util-mem map_util-objs
mem_layout_IMPL := mem_layout mem_layout-arm-$(BITS) \
mem_layout-arm
mem_space_IMPL := mem_space mem_space-arm mem_space-arm-$(BITS)
mem_unit_IMPL := mem_unit mem_unit-arm-$(BITS)
kmem_IMPL := kmem kmem-arm
kmem_alloc_IMPL := kmem_alloc kmem_alloc-arm
kmem_mmio_IMPL := kmem_mmio kmem_mmio-arm
kmem_space_IMPL := kmem_space kmem_space-arm-$(BITS)
outer_cache_IMPL := outer_cache outer_cache-l2cxx0
page_IMPL := page page-arm page-arm-$(BITS)
paging_IMPL := paging paging-arm paging-arm-$(BITS)
perf_cnt_IMPL := perf_cnt perf_cnt-arm perf_cnt-arm-$(BITS)
pic_IMPL := pic
platform_control_IMPL += platform_control-arm platform_control-arm-psci \
platform_control-arm-dt
platform_control_object_IMPL := platform_control_object \
platform_control_object-arm
psci_IMPL := psci-arm
sched_context_IMPL := sched_context-wfq sched_context-fixed_prio \
sched_context-fp_wfq sched_context
scu_IMPL := scu
space_IMPL := space space-arm
spin_lock_IMPL := spin_lock spin_lock-arm spin_lock-arm-$(BITS)
startup_IMPL := startup startup-arm
sys_call_page_IMPL := sys_call_page \
$(if $(and $(CONFIG_BIT32),$(CONFIG_MMU)), sys_call_page-arm)
task_IMPL := task task-arm
thread_IMPL := thread thread-arm thread-arm-hyp \
thread-jdb thread-jdb-$(BITS) thread-ipc \
thread-pagefault thread-log \
thread-vcpu thread-arm-$(BITS)
timer_IMPL := timer timer-arm
timer_tick_IMPL := timer_tick timer_tick-arm
utcb_init_IMPL := utcb_init utcb_init-arm
utcb_support_IMPL := utcb_support utcb_support-arm
vgic_IMPL := vgic
vgic_v3_IMPL := vgic_v3 vgic_v3-$(BITS)
vmem_alloc_IMPL := vmem_alloc vmem_alloc-arch
tb_entry_IMPL := tb_entry tb_entry-arm
mpu_IMPL := mpu mpu-arm-$(BITS)
global_data_IMPL := global_data global_data-arm-$(BITS)
vcpu_IMPL := vcpu vcpu-arm
ifeq ("$(CONFIG_JDB)","y")
JDB := jdb_compound.o
SUBSYSTEMS += JDB
INTERFACES_JDB += jdb_trace_set jdb_log jdb_console_buffer
INTERFACES_JDB-$(CONFIG_PERF_CNT) += jdb_perf
INTERFACES_JDB-$(CONFIG_MMU) += jdb_ptab
CXXSRC_JDB := tb_entry_output.cc
jdb_IMPL += jdb-arm
jdb_kern_info_IMPL := jdb_kern_info jdb_kern_info-arm \
jdb_kern_info-bench jdb_kern_info-bench-arm \
jdb_kern_info-cpu-arm
jdb_dump_entry_frame_IMPL:= jdb_dump_entry_frame-arm
jdb_tcb_IMPL += jdb_tcb-arm
jdb_ptab_IMPL := jdb_ptab jdb_ptab-arm
jdb_entry_frame_IMPL := jdb_entry_frame-arm
jdb_trace_set_IMPL := jdb_trace_set jdb_trace_set-arm \
jdb_trace_set-arm-$(BITS)
jdb_bp_IMPL := jdb_bp-arm
thread_IMPL += thread-debug
jdb_tbuf_fe_IMPL := jdb_tbuf_fe jdb_tbuf_fe-arm
endif
CXXSRC_KERNEL := kernel_panic.cc libc_backend_lock.cc
ASSRC_KERNEL := $(if $(CONFIG_MP),tramp-mp.S)
ASSRC_KERNEL += $(if $(CONFIG_BIT32),$(if $(CONFIG_CPU_VIRT),hvt.S,ivt.S),ivt.S)
ASSRC_KERNEL += kip-time.S
CPPFLAGS += $(if $(MPCORE_PHYS_BASE),-DMPCORE_PHYS_BASE=$(MPCORE_PHYS_BASE))
CPPFLAGS += -DRAM_PHYS_BASE=$(RAM_PHYS_BASE)
NOOPT += $(filter jdb%,\
$(foreach in,$(INTERFACES_KERNEL), \
$(if $($(in)_IMPL),$($(in)_IMPL),$(in))))
NOOPT += tb_entry tb_entry_output
#
# CRT0 subsystem
#
CRT0 := crt0.o
ASSRC_CRT0 := crt0.S
#
# CXXLIB Subsystem
#
CXXLIB := libcxx.a
VPATH += lib/cxxlib
CXXSRC_CXXLIB := paranoia.cc
#
# LIBK subsystem
#
LIBK := libk.a
VPATH += lib/libk/$(CONFIG_XARCH)/$(BITS) lib/libk/$(CONFIG_XARCH) lib/libk
PRIVATE_INCDIR += lib/libk/$(CONFIG_XARCH)/$(BITS) lib/libk/$(CONFIG_XARCH) lib/libk
ifneq ($(CONFIG_COV),)
SUBSYSTEMS += LIBCOV
KERNEL_EXTRA_LIBS += $(LIBCOV)
PRIVATE_INCDIR += lib/gcov/include
INTERFACES_KERNEL-$(CONFIG_JDB) += jdb_cov_module
endif
#INTERFACES_LIBK:= atomic lock_guard profile uuencode gmon unistd panic
INTERFACES_LIBK := std_macros atomic lock_guard scaler_shift
ifeq ($(CONFIG_BIT32),y)
CSRC_LIBK += gcc_lib.c
ASSRC_LIBK += gcc_lib-aeabi.S
endif
CXXSRC_LIBK += construction.cc
atomic_IMPL := atomic atomic-arm-$(BITS) atomic-arm
scaler_shift_IMPL := scaler_shift scaler_shift-arm
#
# SIMPLEMALLOC
#
SIMPLEMALLOC := libsimple_malloc.a
VPATH += lib/simple_malloc
PRIVATE_INCDIR += lib/simple_malloc
CXXSRC_SIMPLEMALLOC = simple_malloc.cc
ifeq ("$(CONFIG_JDB_DISASM)","y")
# $(srcdir)/lib/disasm may be removed
ifeq ($(wildcard $(srcdir)/lib/disasm),)
$(error $(srcdir)/lib/disasm is missing, disable CONFIG_JDB_DISASM)
endif
SUBSYSTEMS += LIBDISASM
KERNEL_EXTRA_LIBS += $(LIBDISASM)
PREPROCESS_PARTS += jdb_disasm
LIBDISASM := libdisasm.a
VPATH += lib/disasm lib/disasm/capstone
PRIVATE_INCDIR += lib/disasm lib/disasm/capstone/include
CXXSRC_LIBDISASM := disasm.cc
CSRC_LIBDISASM := cs.c utils.c \
MCInst.c MCInstrDesc.c MCRegisterInfo.c SStream.c
ifeq ("$(CONFIG_BIT32)","y")
VPATH += lib/disasm/capstone/arch/ARM
CSRC_LIBDISASM += ARMModule.c ARMInstPrinter.c \
ARMDisassembler.c ARMMapping.c
CPPFLAGS += -DCAPSTONE_HAS_ARM
CFLAGS_ARMDisassembler = -Wno-unused-parameter
CFLAGS_ARMMapping = -Wno-unused-parameter
CFLAGS_ARMInstPrinter = -Wno-bad-function-cast -Wno-unused-parameter
$(foreach f, $(patsubst %.c, %, $(CSRC_LIBDISASM)), \
$(eval CFLAGS_$(f) += -mno-unaligned-access))
else
VPATH += lib/disasm/capstone/arch/AArch64
CSRC_LIBDISASM += AArch64Module.c AArch64InstPrinter.c \
AArch64Disassembler.c AArch64Mapping.c \
AArch64BaseInfo.c
CPPFLAGS += -DCAPSTONE_HAS_ARM64
CFLAGS_AArch64Mapping = -Wno-unused-parameter
CFLAGS_AArch64Disassembler = -Wno-unused-parameter
CFLAGS_AArch64InstPrinter = -Wno-bad-function-cast -Wno-unused-parameter
# Clang does not support fallthrough warning elision via comments
CFLAGS_AArch64Mapping += $(if $(CC_IS_CLANG),-Wno-implicit-fallthrough)
CFLAGS_AArch64Disassembler += $(if $(CC_IS_CLANG),-Wno-implicit-fallthrough)
endif
endif
ifeq ("$(CONFIG_JDB)","y")
ifneq ($(CONFIG_JDB_GZIP),)
ifneq ($(wildcard $(srcdir)/lib/gzip),)
SUBSYSTEMS += LIBGZIP
KERNEL_EXTRA_LIBS += $(LIBGZIP)
INTERFACES_KERNEL += jdb_gzip
endif
endif
ifneq ($(wildcard $(srcdir)/lib/regex),)
SUBSYSTEMS += LIBREGEX
KERNEL_EXTRA_LIBS += $(LIBREGEX)
PREPROCESS_PARTS += jdb_regex
endif
ifneq ($(filter LIBREGEX LIBDISASM,$(SUBSYSTEMS)),)
SUBSYSTEMS += SIMPLEMALLOC
KERNEL_EXTRA_LIBS += $(SIMPLEMALLOC)
endif
endif
#
# VERSION subsystem
#
VERSION := version.h
TCBOFFSET := tcboffset.h
CXXSRC_TCBOFFSET := tcboffset.cc dump_tcboffsets.cc
BSP_NAME := $(patsubst "%",%,$(CONFIG_BSP_NAME))
BSP_SRC_DIR := kern/arm/bsp/$(BSP_NAME)
MODULES_FILE_BSP := $(srcdir)/$(BSP_SRC_DIR)/Modules
ifeq ($(wildcard $(MODULES_FILE_BSP)),)
$(error No BSP name defined or no BSP Modules file available)
endif
include $(MODULES_FILE_BSP)
VPATH += $(BSP_SRC_DIR)
PREPROCESS_PARTS += $(PREPROCESS_PARTS-y)
INTERFACES_KERNEL += $(INTERFACES_KERNEL-y) $(INTERFACES_KERNEL-y-y)
INTERFACES_JDB += $(INTERFACES_JDB-y)
TRAMP_MP_ASM_INCLUDE ?= kern/arm/tramp-mp-asm-default.h
CPPFLAGS += -DTRAMP_MP_ASM_INCLUDE=\"$(srcdir)/$(TRAMP_MP_ASM_INCLUDE)\"
ifeq ("$(filter LIBUART, $(SUBSYSTEMS))","LIBUART")
LIBUART := uart/libuart.a
endif
CONFIG_KERNEL_LOAD_ADDR := $(RAM_PHYS_BASE)
ifneq ($(CONFIG_MP),)
ifneq ($(CONFIG_ARM_MPCORE)$(CONFIG_ARM_CORTEX_A9)$(CONFIG_ARM_CORTEX_A5),)
ifeq ($(MPCORE_PHYS_BASE),)
$(error $(MODULES_FILE_BSP) needs to set MPCORE_PHYS_BASE variable)
endif
endif
endif
MODULES_FILES += $(MODULES_FILE) $(MODULES_FILE_BSP)

View File

@@ -0,0 +1,275 @@
# -*- makefile -*-
# vi:se ft=make:
# Include for unit tests, enable by including UTEST in SUBSYSTEMS.
include $(srcdir)/test/utest/Modules.utest
# Include for code rules tests, enable by including CODERULES in SUBSYSTEMS.
include $(srcdir)/test/coderules/Modules.crtest
SUBSYSTEMS += ABI JABI KERNEL DRIVERS CRT0 VERSION TCBOFFSET STDWORKLOAD
SUBSYSTEMS += LIBK CXXLIB LIBC
ifeq ($(CONFIG_UNIT_TEST),y)
# UTEST depends on KERNEL and CHECKSUM, must be listed after them
SUBSYSTEMS += UTEST
endif
ifeq ($(CONFIG_CODE_RULES_TEST),y)
SUBSYSTEMS += CODERULES
endif
#
# ABI Subsystem
#
ABI := libabi.a
VPATH += abi/$(CONFIG_XARCH)/$(BITS) abi/$(CONFIG_XARCH) abi
INTERFACES_ABI := kip l4_types l4_fpage l4_msg_item l4_buf_desc l4_error
l4_types_IMPL := l4_types l4_types-debug
kip_IMPL := kip kip-debug kip-$(CONFIG_XARCH)
INTERFACES_KERNEL := cpu_mask rcupdate kobject_mapdb context_base pm \
mem_region per_cpu_data startup \
queue queue_item l4_buf_iter bitmap \
mapping spin_lock mapping_tree \
dbg_page_info mapdb pic kobject_dbg koptions \
kobject_iface kobject ready_queue_wfq \
obj_space_types obj_space_phys_util \
ready_queue_fp obj_space ptab_base ram_quota \
ref_obj mem_space space \
vlog kmem kmem_alloc kmem_mmio slab_cache \
mem_layout kmem_slab switch_lock kip_init \
helping_lock cpu_lock timer timeout \
ipc_timeout timeslice_timeout per_cpu_data_alloc \
vcpu_host_regs \
vcpu kobject_helper icu_helper thread_state \
context sender receiver mem_unit factory cpu_call \
ipc_sender thread thread_object syscalls \
kernel_thread map_util irq banner warn \
app_cpu_thread globals watchdog kernel_uart \
main config vmem_alloc page paging paging_bits \
fpu fpu_state_ptr fpu_alloc cpu entry_frame \
kernel_console ipc_gate task sigma0_task \
kernel_task platform_control_object \
irq_controller irq_chip irq_mgr terminate \
continuation timer_tick platform_control \
sched_context utcb_init perf_cnt trap_state \
buddy_alloc vkey kdb_ke prio_list ipi scheduler \
clock sys_call_page boot_alloc \
semaphore jdb_object tlbs amp_node global_data \
observer_irq dt
OBJ_SPACE_TYPE = $(if $(CONFIG_VIRT_OBJ_SPACE),virt,phys)
PREPROCESS_PARTS-y$(CONFIG_VIRT_OBJ_SPACE) += obj_space_phys
PREPROCESS_PARTS += obj_space_$(OBJ_SPACE_TYPE)
INTERFACES_KERNEL-$(CONFIG_VIRT_OBJ_SPACE) += obj_space_virt_util
INTERFACES_KERNEL-y$(CONFIG_NDEBUG) += assertion
obj_space_IMPL = obj_space obj_space-$(OBJ_SPACE_TYPE)
PREPROCESS_PARTS-$(CONFIG_PHYS_OBJ_SPACE_AVL) += obj_space_phys_avl
platform_control_IMPL := platform_control
syscalls_IMPL := syscalls syscalls-log
timer_tick_IMPL := timer_tick
vcpu_host_regs_IMPL := vcpu_host_regs-$(CONFIG_XARCH)
kdb_ke_IMPL := kdb_ke
INTERFACES_STDWORKLOAD := std_workload
INTERFACES_JDB += \
jdb_types \
jdb jdb_util jdb_core jdb_module jdb_prompt_ext jdb_list \
jdb_handler_queue jdb_attach_irq jdb_entry_frame \
jdb_exit_module jdb_bp jdb_factory jdb_input jdb_ipc_gate \
jdb_prompt_module \
jdb_obj_space jdb_screen jdb_table jdb_tcb \
jdb_thread jdb_thread_list kern_cnt jdb_counters push_console \
jdb_regex jdb_disasm jdb_tbuf_output jdb_input_task jdb_tbuf_show \
jdb_report jdb_dump jdb_mapdb jdb_timeout jdb_kern_info_kmem_alloc \
jdb_kern_info_kip jdb_kern_info jdb_kern_info_data jdb_utcb \
jdb_trap_state jdb_rcupdate jdb_sender_list jdb_tbuf_fe \
jdb_cpu_call jdb_ipi
INTERFACES_JDB-$(CONFIG_TICKLESS_IDLE) += jdb_idle_stats
jdb_IMPL += jdb jdb-ansi jdb-thread
jdb_tbuf_IMPL += jdb_tbuf jdb_tbuf-$(CONFIG_XARCH)
jdb_tcb_IMPL += jdb_tcb
ifeq ($(CONFIG_RT_DBG),y)
INTERFACES_KERNEL += \
jdb_kobject jdb_kobject_names jdb_space
endif
ifeq ("$(CONFIG_JDB)","y")
INTERFACES_KERNEL += \
jdb_tbuf jdb_tbuf_init tb_entry jdb_trace string_buffer
endif
# - do not profile all of LIBC, because it is used in the BOOT subsystem
# - save some space for debugger, disassembler, ...
NOOPT += $(patsubst %.o, %,\
$(OBJ_LIBC) $(OBJ_JDB) $(OBJ_LIBDISASM))
# Helper function to generate CXXFLAGS_uart-libuart
LIBUART_UART = -include uart_$(strip $(1)).h \
-DFIASCO_UART_TYPE=L4::Uart_$(strip $(if $(2),$(2),$(1)))
LIBUART_UART2 = -include uart_$(strip $(1)).h \
-DFIASCO_UART2_TYPE=L4::Uart_$(strip $(if $(2),$(2),$(1)))
#
# COV Subsystem
#
ifneq ($(CONFIG_COV),)
LIBCOV_CONTRIB_SUPPORTED_VERSIONS := 17 18 19 20
LIBCOV_CONTRIB_MIN_VERSION := $(lastword $(LIBCOV_CONTRIB_SUPPORTED_VERSIONS))
LIBCOV_CONTRIB_VERSION := $(CCVER_VERSION)
ifeq ($(filter $(LIBCOV_CONTRIB_VERSION),$(LIBCOV_CONTRIB_SUPPORTED_VERSIONS)),)
$(warning No suitable libcov version found for clang $(LIBCOV_CONTRIB_VERSION).)
$(warning Falling back to libcov $(LIBCOV_CONTRIB_MAX_VERSION), unexpected errors may occur.)
$(warning Please update the libcov package.)
LIBCOV_CONTRIB_VERSION := $(LIBCOV_CONTRIB_MAX_VERSION)
endif
LIBCOV := libcov.a
VPATH += lib/gcov/src
VPATH += lib/gcov/contrib/llvm_compiler-rt_profile/llvm-$(LIBCOV_CONTRIB_VERSION)/
PRIVATE_INCDIR += lib/gcov/src
PRIVATE_INCDIR += lib/gcov/contrib/llvm_compiler-rt_profile/llvm-$(LIBCOV_CONTRIB_VERSION)/
CSRC_LIBCOV-clang_contrib := \
InstrProfiling.c InstrProfilingBuffer.c InstrProfilingPlatformLinux.c \
InstrProfilingVersionVar.c InstrProfilingWriter.c \
InstrProfilingInternal.c
CSRC_LIBCOV-clang := llvmcov.c plain.c llvmcov-plain.c
CSRC_LIBCOV-clang += $(CSRC_LIBCOV-clang_contrib)
CSRC_LIBCOV-gcc := gcov.c plain.c gcov-plain.c
CSRC_LIBCOV = output.c base64.c
CSRC_LIBCOV += $(CSRC_LIBCOV-$(CC_TYPE))
CSRC_LIBCOV += $(if $(CONFIG_COV_OUTPUT_SERIAL),output-serial.c)
CXXSRC_LIBCOV += $(if $(CONFIG_COV_OUTPUT_MEMBUF),output-membuf.cc)
# WARNING EXCEPTION: suppress compiler warnings for clang compiler-rt code,
# only coverage tooling
$(foreach f, $(patsubst %.c, %, $(CSRC_LIBCOV-clang_contrib)), \
$(eval CFLAGS_$(f) += -Wno-strict-prototypes -Wno-unused-parameter \
-Wno-missing-prototypes -Wno-undef))
NOOPT += $(patsubst %.o, %, $(OBJ_LIBCOV))
endif
#
# LIBC Subsystem
#
LIBC_ARCH-arm- := arm
LIBC_ARCH-arm-y := aarch64
LIBC_ARCH-ia32- := i386
LIBC_ARCH-amd64-y := x86_64
LIBC_ARCH-mips- := mips
LIBC_ARCH-mips-y := mips64
LIBC_ARCH-riscv- := riscv32
LIBC_ARCH-riscv-y := riscv64
LIBC_ARCH-ppc- := powerpc
LIBC_ARCH-sparc- := sparc
LIBC_ARCH := $(LIBC_ARCH-$(CONFIG_XARCH)-$(CONFIG_BIT64))
LIBC := libc.a
VPATH += lib/libc/glue \
lib/libc/src/string \
lib/libc/src/ctype \
lib/libc/src/errno \
lib/libc/src/stdio \
lib/libc/src/exit \
lib/libc/src/stdlib \
lib/libc/src/internal \
lib/libc/src/setjmp/$(LIBC_ARCH)
PRIVATE_INCDIR += lib/libc/arch/$(LIBC_ARCH) \
lib/libc/src/internal \
lib/libc/src/include \
lib/libc/include
CSRC_LIBC := putchar.c \
putstr.c \
stdout_write.c \
\
memchr.c \
memmove.c \
memset.c \
memcmp.c \
strlen.c \
strnlen.c \
strcpy.c \
strncpy.c \
strcmp.c \
stpcpy.c \
strchr.c \
$(if $(filter ia32,$(CONFIG_XARCH)),,memcpy.c) \
strcspn.c \
strchrnul.c \
stpncpy.c \
strrchr.c \
memrchr.c \
strncmp.c \
\
strtol.c \
\
isalnum.c \
isalpha.c \
isdigit.c \
isprint.c \
isxdigit.c \
isspace.c \
tolower.c \
\
printf.c \
snprintf.c \
sprintf.c \
vfprintf.c \
vsnprintf.c \
vsprintf.c \
vprintf.c \
__towrite.c \
fputs.c \
fwrite.c \
puts.c \
\
atexit.c \
\
intscan.c
CXXSRC_LIBC += strstr.cc
# riscv32: needed by intscan.c
VPATH += lib/libk/quad
CSRC_LIBC += lshrdi3.c
ASSRC_LIBC := setjmp.S longjmp.S \
$(if $(filter ia32,$(CONFIG_XARCH)),memcpy-i386.S)
NOBUILTIN += $(patsubst %.o, %, $(OBJ_LIBC))
#
# LIBFDT subsystem
#
ifeq ($(CONFIG_DT),y)
LIBFDT := libfdt.a
SUBSYSTEMS += LIBFDT
KERNEL_EXTRA_LIBS += $(LIBFDT)
VPATH += lib/libfdt
PRIVATE_INCDIR += lib/libfdt
CSRC_LIBFDT := fdt.c fdt_ro.c fdt_strerror.c fdt_addresses.c
# WARNING EXCEPTION: suppress warnings about bad function casts in unmodified
# upstream code.
$(foreach f, $(patsubst %.c, %, $(CSRC_LIBFDT)), \
$(eval CFLAGS_$(f) += -Wno-bad-function-cast))
endif

395
src/fiasco/src/Modules.ia32 Normal file
View File

@@ -0,0 +1,395 @@
# -*- makefile -*-
# vi:se ft=make:
include $(srcdir)/Modules.generic
# UTEST depends on KERNEL and CHECKSUM, must be listed after them
SUBSYSTEMS := $(filter-out UTEST,$(SUBSYSTEMS)) BOOT CHECKSUM SYMBOLS GBLCFG \
$(filter UTEST,$(SUBSYSTEMS))
PREPROCESS_PARTS += arch $(CONFIG_ABI) 32bit iofp recover_jmpbuf \
$(CONFIG_XARCH) apic i8259 pc i8254 fpu \
abs_syscalls auto_map_kip io realmode libuart
PREPROCESS_PARTS-$(CONFIG_MP) += need_xcpu_tlb_flush
PREPROCESS_PARTS-$(CONFIG_JDB) += debug log
PREPROCESS_PARTS-$(CONFIG_SCHED_PIT) += pit_timer
PREPROCESS_PARTS-$(CONFIG_SCHED_RTC) += rtc_timer
PREPROCESS_PARTS-$(CONFIG_SCHED_APIC) += apic_timer
PREPROCESS_PARTS-$(CONFIG_SCHED_HPET) += hpet_timer
PREPROCESS_PARTS-$(CONFIG_CPU_VIRT) += svm vmx virtual_space_iface
PREPROCESS_PARTS-$(CONFIG_IOMMU) += virtual_space_iface
PREPROCESS_PARTS += $(PREPROCESS_PARTS-y)
#
# TYPES subsystem
#
PRIVATE_INCDIR += types/$(CONFIG_XARCH) types
#
# ABI Subsystem
#
INTERFACES_ABI += virt
kip_IMPL += kip-ia32-debug
virt_IMPL := virt-ia32
#
# JABI Subsystem
#
JABI := libjabi.a
VPATH += jabi/$(CONFIG_XARCH) jabi
INTERFACES_JABI := jdb_ktrace jdb_obj_info
VPATH_LIBUART := $(srcdir)/lib/uart
PRIVATE_INCDIR += lib/uart
SUBSYSTEMS += LIBUART
LIBUART := uart/libuart.a
OBJECTS_LIBUART = uart_16550.o
#
# DRIVERS subsystem
#
DRIVERS := libdrivers.a libgluedriverslibc.a
VPATH += drivers/$(CONFIG_XARCH) drivers
PRIVATE_INCDIR += drivers/$(CONFIG_XARCH) drivers
INTERFACES_DRIVERS := mux_console console keyb io pci vga_console reset \
processor delayloop mem
ifeq ("$(CONFIG_SERIAL)","y")
INTERFACES_DRIVERS += filter_console uart
INTERFACES_DRIVERS += $(if $(CONFIG_UART_CHECKSUM),stream_crc32)
endif
INTERFACES_DRIVERS += fb_console
reset_IMPL := reset-ia32
uart_IMPL := uart uart-libuart
CXXFLAGS_uart-libuart := $(call LIBUART_UART, 16550)
CXXFLAGS_uart-libuart += -DUART_16550_INIT_MCR=0x08
CXXSRC_DRIVERS := glue_libc.cc
NOOPT += $(patsubst %.o, %, $(OBJ_DRIVERS))
keyb_IMPL := keyb keyb-pc
io_IMPL := io io-ia32
mem_IMPL := mem mem-ia32
processor_IMPL := processor processor-ia32
#
# FONTS subsystem
#
SUBSYSTEMS += FONTS
FONTS := libfonts.a
FONT_FILES := vgafont.psf
VPATH += ../data/fonts
OBJ_FONTS := $(addsuffix .bin.o,$(FONT_FILES))
NOOPT += $(patsubst %.o, %, $(OBJ_FONTS))
KERNEL_EXTRA_LIBS += $(FONTS)
#
# KERNEL subsystem
#
KERNEL := fiasco.debug
VPATH += kern/$(CONFIG_XARCH) kern/ia32/32 kern/ia32 kern
VPATH += jdb/ia32/32 jdb/ia32 jdb
PRIVATE_INCDIR += kern/$(CONFIG_XARCH) kern/ia32/32 kern/ia32 kern
INTERFACES_KERNEL += __main acpi acpi_fadt acpi_dmar i8259 \
irq_chip_ia32 irq_chip_pic \
io_apic intel_iommu io_apic_remapped \
boot_console \
irq_msi io_space apic pit boot_info checksum \
x86desc gdt idt tss timer_irq dirq allocator \
alternatives
INTERFACES_KERNEL-$(CONFIG_IOMMU) += intel_dmar dmar_space
INTERFACES_KERNEL-$(CONFIG_CPU_VIRT) += svm vmx vm vm_svm vm_vmx_ept
alternatives_IMPL := alternatives alternatives-ia32
apic_IMPL := apic-ia32 apic-ia32-mp
boot_console_IMPL := boot_console-ia32
boot_info_IMPL := boot_info boot_info-ia32
clock_IMPL := clock clock-ia32
config_IMPL := config config-ia32-32 config-ia32
context_IMPL := context context-ia32 context-ia32-32 context-vcpu
continuation_IMPL := continuation-ia32-32
cpu_IMPL := cpu cpu-ia32 cpu-32
dirq_IMPL := dirq-ia32
entry_frame_IMPL := entry_frame entry_frame-ia32
fpu_IMPL := fpu fpu-ia32
ipi_IMPL := ipi ipi-ia32
irq_IMPL := irq irq-ia32
kdb_ke_IMPL += kdb_ke-ia32
kernel_thread_IMPL := kernel_thread kernel_thread-ia32
kernel_uart_IMPL := kernel_uart kernel_uart-libuart
kip_init_IMPL := kip_init-ia32
kmem_IMPL := kmem kmem-ia32 kmem-ia32-32
kmem_alloc_IMPL := kmem_alloc kmem_alloc-ia32
main_IMPL := main-ia32-32 main-ia32
map_util_IMPL := map_util map_util-mem map_util-io map_util-objs
mem_layout_IMPL := mem_layout mem_layout-ia32 mem_layout-ia32-32
mem_space_IMPL := mem_space mem_space-user mem_space-ia32
mem_unit_IMPL := mem_unit-ia32
page_IMPL := page page-ia32
paging_IMPL := paging paging-ia32-32 paging-ia32
perf_cnt_IMPL := perf_cnt perf_cnt-ia32
pic_IMPL := pic pic-i8259
pit_IMPL := pit-i8254
platform_control_IMPL += platform_control-acpi_sleep platform_control-ia32
rtc_IMPL := rtc-ia32
sched_context_IMPL := sched_context-wfq sched_context-fixed_prio \
sched_context-fp_wfq sched_context
sigma0_task_IMPL := sigma0_task sigma0_task-io
space_IMPL := space space-ia32 space-io
spin_lock_IMPL := spin_lock spin_lock-ia32
startup_IMPL := startup startup-ia32
sys_call_page_IMPL := sys_call_page sys_call_page-abs-ia32
task_IMPL := task task-ia32
tb_entry_IMPL := tb_entry tb_entry-ia32-32
timer_IMPL := timer timer-ia32
thread_IMPL := thread thread-ia32 thread-ia32-32 \
thread-ipc thread-pagefault thread-log \
thread-debug thread-dbf thread-vcpu thread-io
utcb_init_IMPL := utcb_init utcb_init-ia32
vmem_alloc_IMPL := vmem_alloc vmem_alloc-ia32
watchdog_IMPL := watchdog watchdog-ia32
INTERFACES_KERNEL-$(CONFIG_SERIAL) += uart_console
cpu_lock_IMPL := cpu_lock cpu_lock-generic
ifeq ("$(CONFIG_SCHED_PIT)","y")
timer_IMPL += timer-pit
timer_tick_IMPL += timer_tick-single-vector timer_tick-ia32
endif
ifeq ("$(CONFIG_SCHED_RTC)","y")
timer_IMPL += timer-rtc
timer_tick_IMPL += timer_tick-single-vector timer_tick-ia32
INTERFACES_KERNEL += rtc
endif
ifeq ("$(CONFIG_SCHED_APIC)","y")
timer_IMPL += timer-apic
timer_tick_IMPL += timer_tick-apic
endif
ifeq ("$(CONFIG_SCHED_HPET)","y")
timer_IMPL += timer-hpet
timer_tick_IMPL += timer_tick-single-vector timer_tick-ia32
INTERFACES_KERNEL += hpet
endif
ifeq ("$(CONFIG_JDB)","y")
JDB := jdb_compound.o
SUBSYSTEMS += JDB
INTERFACES_JDB += jdb_io_ports jdb_ptab jdb_trace_set \
jdb_console_buffer loadcnt jdb_io_apic \
jdb_bt jdb_log jdb_iomap jdb_misc \
jdb_halt_thread
CXXSRC_JDB := tb_entry_output.cc
apic_IMPL += apic-debug
jdb_IMPL += jdb-ia32
jdb_bp_IMPL := jdb_bp-ia32 jdb_bp-ia32-32
jdb_bt_IMPL := jdb_bt-ia32
jdb_entry_frame_IMPL := jdb_entry_frame-ia32
jdb_kern_info_IMPL := jdb_kern_info jdb_kern_info-ia32 jdb_kern_info-apic \
jdb_kern_info-pci jdb_kern_info-bench \
jdb_kern_info-bench-ia32-32 \
jdb_kern_info-dr jdb_kern_info-mtrr
jdb_misc_IMPL := jdb_misc-ia32
jdb_ptab_IMPL := jdb_ptab jdb_ptab-ia32
jdb_screen_IMPL := jdb_screen jdb_screen-ia32
jdb_tcb_IMPL += jdb_tcb-ia32
jdb_trace_set_IMPL := jdb_trace_set jdb_trace_set-ia32
jdb_tbuf_fe_IMPL := jdb_tbuf_fe jdb_tbuf_fe-ia32
INTERFACES_JDB += $(INTERFACES_JDB-y)
endif
CXXSRC_KERNEL := kernel_panic.cc libc_backend_lock.cc
ASSRC_KERNEL := entry.S entry-native.S sys_call_page-asm.S \
kip-time.S
ASSRC_KERNEL-$(CONFIG_MP) += tramp-mp.S entry-mp.S
ASSRC_KERNEL-y += tramp-realmode.S tramp-acpi.S
ASSRC_KERNEL-$(CONFIG_CPU_VIRT) += vm_svm_asm.S vm_vmx_asm.S
ASSRC_KERNEL += $(ASSRC_KERNEL-y)
NOOPT += $(filter jdb%,\
$(foreach in,$(INTERFACES_KERNEL), \
$(if $($(in)_IMPL),$($(in)_IMPL),$(in))))
NOOPT += tb_entry_output $(tb_entry_IMPL) $(perf_cnt_IMPL) \
kern_cnt loadcnt $(apic_IMPL) $(watchdog_IMPL) kdb \
$(kernel_uart_IMPL) push_console virq thread-dbf \
trap_state
NOOPT += $(foreach in,$(INTERFACES_JDB), \
$(if $($(in)_IMPL),$($(in)_IMPL),$(in)))
#
# CRT0 subsystem
#
CRT0 := crt0.o
ASSRC_CRT0 := crt0.S
#
# BOOT subsystem
#
BOOT := fiasco
VPATH += boot/$(CONFIG_XARCH) boot
PRIVATE_INCDIR += boot boot/ia32
CXXSRC_BOOT := boot_libc_glue.cc bootstrap.cc boot_cpu.cc \
direct_cons_putchar.cc
ASSRC_BOOT := boot.S boot_idt.S
NOOPT += $(patsubst %.o, %, $(OBJ_BOOT))
#
# TCBOFFSET subsystem
#
TCBOFFSET := tcboffset.h
CXXSRC_TCBOFFSET := tcboffset.cc dump_tcboffsets.cc
#
# SYMBOLS subsystem
#
SYMBOLS := Symbols
#
# CHECKSUM subsystem
#
CHECKSUM := checksum_subsys
#
# VERSION subsystem
#
VERSION := version.h
#
# GBLCFG subsystem
#
GBLCFG := gblcfg.o
OBJ_KERNEL += gblcfg.o
#
# CXXLIB Subsystem
#
CXXLIB := libcxx.a
VPATH += lib/cxxlib
CXXSRC_CXXLIB := paranoia.cc
#
# LIBK subsystem
#
LIBK := libk.a
VPATH += lib/libk/$(CONFIG_XARCH) lib/libk
PRIVATE_INCDIR += lib/libk/$(CONFIG_XARCH) lib/libk
INTERFACES_LIBK := atomic lock_guard std_macros
CSRC_LIBK += gcc_lib.c
CXXSRC_LIBK += construction.cc
atomic_IMPL := atomic atomic-ia32
#
# LIBGZIP subsystem (only for Jdb)
#
ifneq ($(CONFIG_JDB_GZIP),)
LIBGZIP := libgzip.a
VPATH += lib/gzip
PRIVATE_INCDIR += lib/gzip
CSRC_LIBGZIP := adler32.c crc32.c gzip.c trees.c deflate.c zutil.c
NOOPT += $(patsubst %.o, %, $(OBJ_LIBGZIP))
$(foreach f, adler32 crc32 deflate trees zutil, \
$(eval CFLAGS_$(f) += $(WNO_DEPRECATED_NON_PROTOTYPE) \
-Wno-old-style-definition -Wno-strict-prototypes))
endif
# SIMPLEMALLOC
#
SIMPLEMALLOC := libsimple_malloc.a
VPATH += lib/simple_malloc
PRIVATE_INCDIR += lib/simple_malloc
CXXSRC_SIMPLEMALLOC = simple_malloc.cc
#
# LIBDISASM subsystem (only for Jdb)
#
ifeq ("$(CONFIG_JDB_DISASM)","y")
# $(srcdir)/lib/disasm may be removed
ifeq ($(wildcard $(srcdir)/lib/disasm),)
$(error $(srcdir)/lib/disasm is missing, disable CONFIG_JDB_DISASM)
endif
SUBSYSTEMS += LIBDISASM
KERNEL_EXTRA_LIBS += $(LIBDISASM)
PREPROCESS_PARTS += jdb_disasm
LIBDISASM := libdisasm.a
VPATH += lib/disasm lib/disasm/capstone \
lib/disasm/capstone/arch/X86
PRIVATE_INCDIR += lib/disasm lib/disasm/capstone/include
CXXSRC_LIBDISASM := disasm.cc
CSRC_LIBDISASM := cs.c utils.c \
MCInst.c MCInstrDesc.c MCRegisterInfo.c SStream.c
CSRC_LIBDISASM += X86Module.c X86Disassembler.c X86DisassemblerDecoder.c \
X86Mapping.c X86IntelInstPrinter.c X86ATTInstPrinter.c
CPPFLAGS += -DCAPSTONE_HAS_X86
CFLAGS_cs = -Wno-unused-parameter
CFLAGS_SStream = -Wno-unused-parameter
CFLAGS_X86Mapping = -Wno-unused-parameter -Wno-missing-field-initializers
CFLAGS_X86Disassembler = -Wno-unused-parameter
CFLAGS_X86IntelInstPrinter = -Wno-unused-parameter -Wno-sign-compare
CFLAGS_X86ATTInstPrinter = -Wno-unused-parameter -Wno-sign-compare
CFLAGS_X86DisassemblerDecoder = -Wno-bad-function-cast
endif
#
# LIBPERFCTR subsystem (only for Jdb)
#
LIBPERFCTR := libperfctr.a
VPATH += lib/perfctr
PRIVATE_INCDIR += lib/perfctr
CSRC_LIBPERFCTR := event_set_p5.c event_set_p6.c event_set_amd.c \
event_set_p4.c event_set_x86.c perfctr.c \
event_set_centaur.c
NOOPT += $(patsubst %.o, %, $(OBJ_LIBPERFCTR))
#
# LIBREGEX subsystem (only for Jdb)
#
LIBREGEX := libregex.a
VPATH += lib/regex
PRIVATE_INCDIR += lib/regex
CSRC_LIBREGEX := rx.c
NOOPT += $(patsubst %.o, %, $(OBJ_LIBREGEX))
ifeq ("$(CONFIG_JDB)","y")
ifneq ($(CONFIG_JDB_GZIP),)
ifneq ($(wildcard $(srcdir)/lib/gzip),)
SUBSYSTEMS += LIBGZIP
KERNEL_EXTRA_LIBS += $(LIBGZIP)
INTERFACES_KERNEL += jdb_gzip
endif
endif
ifneq ($(wildcard $(srcdir)/lib/perfctr),)
SUBSYSTEMS += LIBPERFCTR
KERNEL_EXTRA_LIBS += $(LIBPERFCTR)
KERNEL_UNRES_SYMS += -u perfctr_set_cputype
endif
ifneq ($(wildcard $(srcdir)/lib/regex),)
SUBSYSTEMS += LIBREGEX
KERNEL_EXTRA_LIBS += $(LIBREGEX)
PREPROCESS_PARTS += jdb_regex
endif
ifneq ($(filter LIBREGEX LIBDISASM,$(SUBSYSTEMS)),)
SUBSYSTEMS += SIMPLEMALLOC
KERNEL_EXTRA_LIBS += $(SIMPLEMALLOC)
endif
endif
MODULES_FILES += $(MODULES_FILE) $(MODULES_FILE_BSP)
INTERFACES_KERNEL += $(INTERFACES_KERNEL-y)

257
src/fiasco/src/Modules.mips Normal file
View File

@@ -0,0 +1,257 @@
# -*- makefile -*-
# vi:se ft=make:
###############################################################################
include $(srcdir)/Modules.generic
SUBSYSTEMS += LIBUART
PREPROCESS_PARTS += $(CONFIG_XARCH) $(CONFIG_ABI) libuart
PREPROCESS_PARTS += recover_jmpbuf
PREPROCESS_PARTS-$(CONFIG_BIT32) += 32bit mips32
PREPROCESS_PARTS-$(CONFIG_BIT64) += 64bit mips64
BITS-$(CONFIG_BIT32) = 32
BITS-$(CONFIG_BIT64) = 64
BITS = $(BITS-y)
PREPROCESS_PARTS-$(CONFIG_CPU_VIRT) += mips_vz
PREPROCESS_PARTS-$(CONFIG_CPU_MIPSR6) += mips_r6
PREPROCESS_PARTS-$(CONFIG_PAGE_SIZE_16KB) += pagesize_16k
PREPROCESS_PARTS-$(CONFIG_PAGE_SIZE_4KB) += pagesize_4k
PREPROCESS_PARTS-$(CONFIG_SERIAL) += force_vkey
PREPROCESS_PARTS-$(CONFIG_MP) += need_xcpu_tlb_flush
PREPROCESS_PARTS-$(CONFIG_JDB) += debug log
PREPROCESS_PARTS-$(CONFIG_WEAK_ORDERING) += weak_ordering
PREPROCESS_PARTS-$(CONFIG_LIGHTWEIGHT_BARRIERS) += mips_lw_barriers
PREPROCESS_PARTS += $(PREPROCESS_PARTS-y)
#
# TYPES subsystem
#
PRIVATE_INCDIR += types/mips/$(BITS) types/mips types
#
# UART subsystem
#
VPATH_LIBUART := $(srcdir)/lib/uart
PRIVATE_INCDIR += lib/uart
#
# DRIVERS Subsystem
#
DRIVERS := libdrivers.a libgluedriverslibc.a
VPATH += drivers/mips/$(BITS) drivers/mips drivers
PRIVATE_INCDIR += drivers/mips/$(BITS) drivers/mips drivers
INTERFACES_DRIVERS := mux_console console mem reset uart filter_console \
processor delayloop io mmu
INTERFACES_DRIVERS += $(if $(CONFIG_UART_CHECKSUM),stream_crc32)
mem_IMPL := mem mem-mips
uart_IMPL := uart uart-libuart
processor_IMPL := processor processor-mips
CXXSRC_DRIVERS := glue_libc.cc
#NOOPT += $(patsubst %.o, %, $(OBJ_DRIVERS))
#
# JABI Subsystem
#
JABI := libjabi.a
VPATH += jabi/mips/$(BITS) jabi
INTERFACES_JABI := jdb_ktrace jdb_obj_info
#
# ABI Subsystem
#
l4_types_IMPL += l4_types-mips
#
# KERNEL subsystem
#
KERNEL := fiasco
KERNEL_EXTRA := Symbols kernel.mips.lds fiasco.debug
VPATH += kern/mips/$(BITS) kern/mips kern
VPATH += jdb/mips/$(BITS) jdb/mips jdb
PRIVATE_INCDIR += kern/mips/$(BITS) kern/mips kern
INTERFACES_KERNEL += boot_uart_init cp0_status cm \
mips_cpu_irqs irq_chip_generic \
alternatives \
cpu_p5600
#missing: jdb_extensions
INTERFACES_KERNEL-$(CONFIG_SERIAL) += uart_console
INTERFACES_KERNEL-$(CONFIG_CPU_VIRT) += vz
INTERFACES_KERNEL += $(INTERFACES_KERNEL-y)
alternatives_IMPL := alternatives-mips
bitmap_linux_IMPL := bitmap_linux
clock_IMPL := clock
config_IMPL := config config-mips
context_IMPL := context context-mips context-vcpu
continuation_IMPL := continuation-mips
cp0_status_IMPL := cp0_status
cpu_IMPL := cpu cpu-mips
cpu_lock_IMPL := cpu_lock cpu_lock-generic
entry_frame_IMPL := entry_frame-mips
fpu_IMPL := fpu fpu-mips
ipi_IMPL := ipi ipi-mips
kdb_ke_IMPL += kdb_ke-mips
kernel_task_IMPL := kernel_task
kernel_thread_IMPL := kernel_thread kernel_thread-mips
kernel_uart_IMPL := kernel_uart kernel_uart-libuart
kmem_IMPL := kmem kmem-mips
kmem_alloc_IMPL := kmem_alloc kmem_alloc-mips
kmem_mmio_IMPL := kmem_mmio kmem_mmio-mips
map_util_IMPL := map_util map_util-mem map_util-objs
mem_layout_IMPL := mem_layout mem_layout-mips$(BITS)
mem_unit_IMPL := mem_unit-mips
mem_space_IMPL := mem_space mem_space-mips
obj_space_IMPL := obj_space obj_space-phys
paging_IMPL := paging paging-mips
perf_cnt_IMPL := perf_cnt perf_cnt-mips
platform_control_IMPL += platform_control-mips
cm_IMPL := cm
cpc_IMPL := cpc
pic_IMPL := pic
sched_context_IMPL := sched_context-wfq sched_context-fixed_prio \
sched_context-fp_wfq sched_context
space_IMPL := space
spin_lock_IMPL := spin_lock spin_lock-mips
startup_IMPL := startup startup-mips
sys_call_page_IMPL := sys_call_page
task_IMPL := task task-mips
timer_IMPL ?= timer timer-mips
timer_tick_IMPL := timer_tick
thread_IMPL := thread thread-log thread-pagefault \
thread-mips thread-ipc thread-jdb \
thread-vcpu
vmem_alloc_IMPL := vmem_alloc
tb_entry_IMPL := tb_entry tb_entry-mips
ifeq ("$(CONFIG_JDB)","y")
JDB := jdb_compound.o
SUBSYSTEMS += JDB
CXXSRC_JDB := tb_entry_output.cc
jdb_IMPL += jdb-mips
jdb_tcb_IMPL += jdb_tcb-mips
jdb_entry_frame_IMPL := jdb_entry_frame-mips
jdb_trace_set_IMPL += jdb_trace_set jdb_trace_set-mips
jdb_kern_info_IMPL := jdb_kern_info
jdb_tbuf_init_IMPL := jdb_tbuf_init jdb_tbuf_init-mips
jdb_ptab_IMPL := jdb_ptab jdb_ptab-mips
thread_IMPL += thread-debug
INTERFACES_JDB += jdb_log jdb_trace_set jdb_ptab jdb_mips_tlb \
jdb_console_buffer
INTERFACES_JDB += $(INTERFACES_JDB-y)
endif
CXXSRC_KERNEL := kernel_panic.cc libc_backend_lock.cc
ASSRC_KERNEL := exception.S kip-time.S
#ASSRC_KERNEL-$(CONFIG_MP) += tramp-mp.S
ASSRC_KERNEL += $(ASSRC_KERNEL-y)
NOOPT += $(filter jdb%,\
$(foreach in,$(INTERFACES_KERNEL), \
$(if $($(in)_IMPL),$($(in)_IMPL),$(in))))
NOOPT += tb_entry #tb_entry_output
#
# CRT0 subsystem
#
CRT0 := crt0.o
ASSRC_CRT0 := crt0.S
#
# CXXLIB Subsystem
#
CXXLIB := libcxx.a
VPATH += lib/cxxlib
CXXSRC_CXXLIB := paranoia.cc
#
# LIBK subsystem
#
LIBK := libk.a
VPATH += lib/libk/mips/$(BITS) lib/libk/mips lib/libk lib/libk/quad
PRIVATE_INCDIR += lib/libk/mips/$(BITS) lib/libk/mips lib/libk
INTERFACES_LIBK := atomic lock_guard std_macros
CSRC_LIBK += umoddi3.c ashldi3.c udivdi3.c qdivrem.c ucmpdi2.c
CXXSRC_LIBK += construction.cc
atomic_IMPL := atomic atomic-mips
#
# SIMPLEMALLOC
#
SIMPLEMALLOC := libsimple_malloc.a
VPATH += lib/simple_malloc
PRIVATE_INCDIR += lib/simple_malloc
CXXSRC_SIMPLEMALLOC = simple_malloc.cc
#
# LIBDISASM subsystem (only for Jdb)
#
ifeq ("$(CONFIG_JDB_DISASM)","y")
# $(srcdir)/lib/disasm may be removed
ifeq ($(wildcard $(srcdir)/lib/disasm),)
$(error $(srcdir)/lib/disasm is missing, disable CONFIG_JDB_DISASM)
endif
SUBSYSTEMS += LIBDISASM
KERNEL_EXTRA_LIBS += $(LIBDISASM)
PREPROCESS_PARTS += jdb_disasm
SUBSYSTEMS += SIMPLEMALLOC
KERNEL_EXTRA_LIBS += $(SIMPLEMALLOC)
LIBDISASM := libdisasm.a
VPATH += lib/disasm lib/disasm/capstone \
lib/disasm/capstone/arch/Mips
PRIVATE_INCDIR += lib/disasm lib/disasm/capstone/include
CXXSRC_LIBDISASM := disasm.cc
CSRC_LIBDISASM := cs.c utils.c \
MCInst.c MCInstrDesc.c MCRegisterInfo.c SStream.c \
MipsModule.c MipsInstPrinter.c \
MipsDisassembler.c MipsMapping.c
CPPFLAGS += -DCAPSTONE_HAS_MIPS
CFLAGS_MipsInstPrinter = -Wno-unused-parameter -Wno-bad-function-cast
CFLAGS_MipsMapping = -Wno-unused-parameter
CFLAGS_MipsDisassembler = -Wno-unused-parameter
endif
#
# VERSION subsystem
#
VERSION := version.h
TCBOFFSET := tcboffset.h
CXXSRC_TCBOFFSET := tcboffset.cc dump_tcboffsets.cc
#
# BSP subsystem
#
BSP_NAME := $(patsubst "%",%,$(CONFIG_BSP_NAME))
MODULES_FILE_BSP := $(srcdir)/kern/mips/bsp/$(BSP_NAME)/Modules
PRIVATE_INCDIR += kern/mips/bsp/$(BSP_NAME)
ifeq ($(wildcard $(MODULES_FILE_BSP)),)
$(error No BSP name defined or no BSP Modules file available)
endif
include $(MODULES_FILE_BSP)
VPATH += kern/mips/bsp/$(BSP_NAME) kern/mips/bsp
ifeq ("$(filter LIBUART, $(SUBSYSTEMS))","LIBUART")
LIBUART := uart/libuart.a
endif
CONFIG_KERNEL_LOAD_ADDR-32 := 0x80010000
CONFIG_KERNEL_LOAD_ADDR-64 := 0xffffffff80010000
CONFIG_KERNEL_LOAD_ADDR := $(CONFIG_KERNEL_LOAD_ADDR-$(BITS))
MODULES_FILES += $(MODULES_FILE) $(MODULES_FILE_BSP)

View File

@@ -0,0 +1,207 @@
# -*- makefile -*-
# vi:se ft=make:
###############################################################################
include $(srcdir)/Modules.generic
SUBSYSTEMS += LIBUART
PREPROCESS_PARTS += $(CONFIG_XARCH) $(CONFIG_ABI) 32bit \
abs_syscalls big_endian jdb_thread_names \
obj_space_phys
PREPROCESS_PARTS-$(CONFIG_JDB) += debug log
PREPROCESS_PARTS += $(PREPROCESS_PARTS-y)
#
# TYPES subsystem
#
PRIVATE_INCDIR += types/$(CONFIG_XARCH) types
#
# LIBUART subsystem
#
ifeq ("$(filter LIBUART, $(SUBSYSTEMS))","LIBUART")
LIBUART := uart/libuart.a
PREPROCESS_PARTS += libuart
endif
VPATH_LIBUART := $(srcdir)/lib/uart
PRIVATE_INCDIR += lib/uart drivers/$(CONFIG_XARCH)/include
#
# DRIVERS Subsystem
#
DRIVERS := libdrivers.a libgluedriverslibc.a
VPATH += drivers/$(CONFIG_XARCH) drivers
PRIVATE_INCDIR += drivers/$(CONFIG_XARCH) drivers
INTERFACES_DRIVERS := mux_console console mem reset uart filter_console \
processor delayloop io
INTERFACES_DRIVERS += $(if $(CONFIG_UART_CHECKSUM),stream_crc32)
io_IMPL := io io-ppc32
mem_IMPL := mem mem-ppc32
uart_IMPL := uart uart-libuart
reset_IMPL := reset-ppc32
processor_IMPL := processor processor-ppc32
CXXSRC_DRIVERS := glue_libc.cc
NOOPT += $(patsubst %.o, %, $(OBJ_DRIVERS))
#
# JABI Subsystem
#
JABI := libjabi.a
VPATH += jabi/$(CONFIG_XARCH) jabi
INTERFACES_JABI := jdb_ktrace jdb_obj_info
#
# KERNEL subsystem
#
KERNEL := fiasco
KERNEL_EXTRA := Symbols kernel.ppc32.lds fiasco.debug
VPATH += kern/$(CONFIG_XARCH) kern
VPATH += jdb/$(CONFIG_XARCH) jdb
PRIVATE_INCDIR += kern/$(CONFIG_XARCH) kern
INTERFACES_KERNEL += boot_uart_init bootstrap decrementer msr ppc_types \
util utcb_support irq_chip_generic dirq boot_info
INTERFACES_KERNEL-$(CONFIG_SERIAL) += uart_console
INTERFACES_KERNEL += $(INTERFACES_KERNEL-y)
boot_info_IMPL := boot_info boot_info-ppc32
clock_IMPL := clock
config_IMPL := config config-ppc32
context_IMPL := context context-ppc32 context-vcpu
continuation_IMPL := continuation-ppc32
cpu_IMPL := cpu cpu-ppc32
cpu_lock_IMPL := cpu_lock cpu_lock-generic
dirq_IMPL := dirq-ppc32
entry_frame_IMPL := entry_frame entry_frame-ppc32
kdb_ke_IMPL += kdb_ke-ppc32
kernel_task_IMPL := kernel_task kernel_task-ppc32
kernel_thread_IMPL := kernel_thread kernel_thread-ppc32
kernel_uart_IMPL := kernel_uart kernel_uart-libuart
kmem_IMPL := kmem kmem-ppc32
kmem_alloc_IMPL := kmem_alloc kmem_alloc-ppc32
map_util_IMPL := map_util map_util-mem map_util-objs
mem_layout_IMPL := mem_layout mem_layout-ppc32
mem_unit_IMPL := mem_unit-ppc32
mem_space_IMPL := mem_space mem_space-ppc32 \
mem_space-htab mem_space-cache
obj_space_IMPL := obj_space obj_space-phys
page_IMPL := page page-ppc32
paging_IMPL := paging paging-ppc32
pic_IMPL := pic
sched_context_IMPL := sched_context-wfq sched_context-fixed_prio \
sched_context-fp_wfq sched_context
startup_IMPL := startup startup-ppc32
sys_call_page_IMPL := sys_call_page sys_call_page-ppc32
task_IMPL := task task-ppc32
timer_IMPL := timer timer-decr-ppc32
timer_tick_IMPL := timer_tick timer_tick-ppc32
thread_IMPL := thread thread-log thread-pagefault \
thread-ppc32 thread-ipc thread-jdb \
thread-vcpu
utcb_init_IMPL := utcb_init utcb_init-ppc32
utcb_support_IMPL := utcb_support utcb_support-ppc32
vmem_alloc_IMPL := vmem_alloc vmem_alloc-ppc32
tb_entry_IMPL := tb_entry tb_entry-ppc32
warn_IMPL := warn warn-ppc32
ifeq ("$(CONFIG_JDB)","y")
JDB := jdb_compound.o
SUBSYSTEMS += JDB
CXXSRC_JDB := tb_entry_output.cc
jdb_IMPL += jdb-ppc32
jdb_tcb_IMPL += jdb_tcb-ppc32
jdb_entry_frame_IMPL := jdb_entry_frame-ppc32
thread_IMPL += thread-debug
INTERFACES_JDB += $(INTERFACES_JDB-y)
endif
CXXSRC_KERNEL := kernel_panic.cc libc_backend_lock.cc
ASSRC_KERNEL := exception.S phys_mem.S
NOOPT += $(filter jdb%,\
$(foreach in,$(INTERFACES_KERNEL), \
$(if $($(in)_IMPL),$($(in)_IMPL),$(in))))
NOOPT += tb_entry #tb_entry_output
#
# CRT0 subsystem
#
CRT0 := crt0.o
ASSRC_CRT0 := crt0.S
#
# CXXLIB Subsystem
#
CXXLIB := libcxx.a
VPATH += lib/cxxlib
CXXSRC_CXXLIB := paranoia.cc
#
# LIBK subsystem
#
LIBK := libk.a
VPATH += lib/libk/$(CONFIG_XARCH) lib/libk
PRIVATE_INCDIR += lib/libk/$(CONFIG_XARCH) lib/libk
INTERFACES_LIBK := atomic lock_guard std_macros
CXXSRC_LIBK += construction.cc
atomic_IMPL := atomic atomic-ppc32
#
# LIBDISASM subsystem (only for Jdb)
#
ifeq ("$(CONFIG_JDB_DISASM)","y")
# $(srcdir)/lib/disasm may be removed
ifeq ($(wildcard $(srcdir)/lib/disasm),)
$(error $(srcdir)/lib/disasm is missing, disable CONFIG_JDB_DISASM)
endif
SUBSYSTEMS += LIBDISASM
KERNEL_EXTRA_LIBS += $(LIBDISASM)
PREPROCESS_PARTS += jdb_disasm
LIBDISASM := libdisasm.a
VPATH += lib/disasm lib/disasm/elf lib/disasm/include \
lib/disasm/include/opcode lib/disasm/opcodes \
lib/disasm/libiberty lib/disasm/bfd
PRIVATE_INCDIR += lib/disasm lib/disasm/elf lib/disasm/include \
lib/disasm/include/opcode lib/disasm/opcodes \
lib/disasm/libiberty lib/disasm/bfd
PRIVATE_INCDIR += lib/disasm
CXXSRC_LIBDISASM := disasm.cc
CSRC_LIBDISASM := ppc-dis.c ppc-opc.c dis-init.c dis-buf.c \
safe-ctype.c libbfd.c
endif
#
# VERSION subsystem
#
VERSION := version.h
TCBOFFSET := tcboffset.h
CXXSRC_TCBOFFSET := tcboffset.cc dump_tcboffsets.cc
#
# BSP subsystem
#
BSP_NAME := $(patsubst "%",%,$(CONFIG_BSP_NAME))
MODULES_FILE_BSP := $(srcdir)/kern/ppc32/bsp/$(BSP_NAME)/Modules
ifeq ($(wildcard $(MODULES_FILE_BSP)),)
$(error No BSP name defined or no BSP Modules file available)
endif
include $(MODULES_FILE_BSP)
VPATH += kern/ppc32/bsp/$(BSP_NAME) kern/ppc32/bsp
MODULES_FILES = $(MODULES_FILE) $(MODULES_FILE_BSP)

View File

@@ -0,0 +1,250 @@
# -*- makefile -*-
# vi:se ft=make:
###############################################################################
include $(srcdir)/Modules.generic
PREPROCESS_PARTS += $(CONFIG_XARCH) $(CONFIG_ABI) libuart
PREPROCESS_PARTS-$(CONFIG_BIT32) += 32bit riscv32
PREPROCESS_PARTS-$(CONFIG_BIT64) += 64bit riscv64
BITS-$(CONFIG_BIT32) = 32
BITS-$(CONFIG_BIT64) = 64
BITS = $(BITS-y)
PREPROCESS_PARTS-$(CONFIG_MP) += need_xcpu_tlb_flush
PREPROCESS_PARTS-$(CONFIG_SERIAL) += force_vkey
PREPROCESS_PARTS-$(CONFIG_JDB) += debug log
PREPROCESS_PARTS += $(PREPROCESS_PARTS-y)
#
# TYPES subsystem
#
PRIVATE_INCDIR += types/$(CONFIG_XARCH)/$(BITS) types/$(CONFIG_XARCH) types
#
# UART subsystem
#
VPATH_LIBUART := $(srcdir)/lib/uart
PRIVATE_INCDIR += lib/uart
SUBSYSTEMS += LIBUART
LIBUART := uart/libuart.a
OBJECTS_LIBUART = uart_sbi.o
#
# DRIVERS Subsystem
#
DRIVERS := libdrivers.a libgluedriverslibc.a
VPATH += drivers/$(CONFIG_XARCH)/$(BITS) drivers/$(CONFIG_XARCH) drivers
PRIVATE_INCDIR += drivers/$(CONFIG_XARCH)/$(BITS) drivers/$(CONFIG_XARCH) drivers
INTERFACES_DRIVERS := mux_console console mem reset uart filter_console \
processor delayloop io mmu sbi
INTERFACES_DRIVERS += $(if $(CONFIG_UART_CHECKSUM),stream_crc32)
mem_IMPL := mem mem-riscv
reset_IMPL := reset-riscv
uart_IMPL := uart uart-libuart
processor_IMPL := processor processor-riscv
CXXSRC_DRIVERS := glue_libc.cc
#NOOPT += $(patsubst %.o, %, $(OBJ_DRIVERS))
ALWAYS_INLINE += mem sbi
#
# JABI Subsystem
#
JABI := libjabi.a
VPATH += jabi/$(CONFIG_XARCH)/$(BITS) jabi/$(CONFIG_XARCH) jabi
INTERFACES_JABI := jdb_ktrace jdb_obj_info
#
# ABI Subsystem
#
l4_types_IMPL += l4_types-riscv
#
# KERNEL subsystem
#
KERNEL := fiasco
KERNEL_EXTRA := Symbols kernel.riscv.lds fiasco.debug
VPATH += kern/$(CONFIG_XARCH)/$(BITS) kern/$(CONFIG_XARCH) kern
VPATH += jdb/riscv/$(BITS) jdb/riscv jdb
PRIVATE_INCDIR += kern/$(CONFIG_XARCH)/$(BITS) kern/$(CONFIG_XARCH) kern
INTERFACES_KERNEL += __main boot_uart_init csr irq_chip_generic
INTERFACES_KERNEL += bootstrap boot_infos
INTERFACES_KERNEL-$(CONFIG_SERIAL) += uart_console
INTERFACES_KERNEL-$(CONFIG_CPU_VIRT) += hyp_ext_state
INTERFACES_KERNEL += $(INTERFACES_KERNEL-y)
clock_IMPL := clock
config_IMPL := config config-riscv
context_IMPL := context context-riscv context-vcpu
continuation_IMPL := continuation-riscv
cpu_IMPL := cpu cpu-riscv cpu-riscv-hyp
cpu_lock_IMPL := cpu_lock cpu_lock-generic
entry_frame_IMPL := entry_frame-riscv
fpu_IMPL := fpu fpu-riscv
ipi_IMPL := ipi ipi-riscv
kdb_ke_IMPL += kdb_ke-riscv
kernel_task_IMPL := kernel_task
kernel_thread_IMPL := kernel_thread kernel_thread-riscv
kernel_uart_IMPL := kernel_uart kernel_uart-libuart
kmem_IMPL := kmem kmem-riscv
kmem_alloc_IMPL := kmem_alloc kmem_alloc-riscv
kmem_mmio_IMPL := kmem_mmio kmem_mmio-riscv
map_util_IMPL := map_util map_util-mem map_util-objs
mem_layout_IMPL := mem_layout mem_layout-riscv mem_layout-riscv$(BITS)
mem_unit_IMPL := mem_unit-riscv
mem_space_IMPL := mem_space mem_space-riscv
obj_space_IMPL := obj_space obj_space-phys
paging_IMPL := paging paging-riscv
perf_cnt_IMPL := perf_cnt # perf_cnt-riscv
platform_control_IMPL += platform_control-riscv
cpc_IMPL := cpc
pic_IMPL := pic
sched_context_IMPL := sched_context-wfq sched_context-fixed_prio \
sched_context-fp_wfq sched_context
space_IMPL := space
spin_lock_IMPL := spin_lock spin_lock-riscv
startup_IMPL := startup startup-riscv
sys_call_page_IMPL := sys_call_page
task_IMPL := task task-riscv
timer_IMPL ?= timer timer-riscv
timer_tick_IMPL := timer_tick timer_tick-riscv
thread_IMPL := thread thread-log thread-pagefault \
thread-riscv thread-ipc thread-jdb \
thread-vcpu
vmem_alloc_IMPL := vmem_alloc vmem_alloc-riscv
tb_entry_IMPL := tb_entry tb_entry-riscv
ifeq ("$(CONFIG_JDB)","y")
JDB := jdb_compound.o
SUBSYSTEMS += JDB
CXXSRC_JDB := tb_entry_output.cc
jdb_IMPL += jdb-riscv
jdb_tcb_IMPL += jdb_tcb-riscv
jdb_entry_frame_IMPL := jdb_entry_frame-riscv
jdb_trace_set_IMPL += jdb_trace_set jdb_trace_set-riscv
jdb_kern_info_IMPL := jdb_kern_info
jdb_tbuf_init_IMPL := jdb_tbuf_init
jdb_tbuf_fe_IMPL := jdb_tbuf_fe jdb_tbuf_fe-riscv
jdb_ptab_IMPL := jdb_ptab jdb_ptab-riscv
thread_IMPL += thread-debug
INTERFACES_JDB += jdb_log jdb_trace_set jdb_ptab
INTERFACES_JDB += $(INTERFACES_JDB-y)
endif
CXXSRC_KERNEL := kernel_panic.cc libc_backend_lock.cc
ASSRC_KERNEL := exception.S bootstrap_crt0.S kip-time.S
ASSRC_KERNEL-$(CONFIG_MP) += tramp-mp.S
ASSRC_KERNEL += $(ASSRC_KERNEL-y)
CPPFLAGS += -DRAM_PHYS_BASE=$(RAM_PHYS_BASE)
NOOPT += $(filter jdb%,\
$(foreach in,$(INTERFACES_KERNEL), \
$(if $($(in)_IMPL),$($(in)_IMPL),$(in))))
NOOPT += tb_entry tb_entry_output
#
# CRT0 subsystem
#
CRT0 := crt0.o
ASSRC_CRT0 := crt0.S
#
# CXXLIB Subsystem
#
CXXLIB := libcxx.a
VPATH += lib/cxxlib
CXXSRC_CXXLIB := paranoia.cc
#
# LIBK subsystem
#
LIBK := libk.a
VPATH += lib/libk/$(CONFIG_XARCH)/$(BITS) lib/libk/$(CONFIG_XARCH) lib/libk
PRIVATE_INCDIR += lib/libk/$(CONFIG_XARCH)/$(BITS) lib/libk/$(CONFIG_XARCH) lib/libk
INTERFACES_LIBK := atomic lock_guard scaler_shift std_macros
CSRC_LIBK += gcc_lib.c
CXXSRC_LIBK += construction.cc
atomic_IMPL := atomic atomic-riscv
scaler_shift_IMPL := scaler_shift scaler_shift-riscv
#
# SIMPLEMALLOC
#
SIMPLEMALLOC := libsimple_malloc.a
VPATH += lib/simple_malloc
PRIVATE_INCDIR += lib/simple_malloc
CXXSRC_SIMPLEMALLOC = simple_malloc.cc
#
# LIBDISASM subsystem (only for Jdb)
#
ifeq ("$(CONFIG_JDB_DISASM)","y")
# $(srcdir)/lib/disasm may be removed
ifeq ($(wildcard $(srcdir)/lib/disasm),)
$(error $(srcdir)/lib/disasm is missing, disable CONFIG_JDB_DISASM)
endif
SUBSYSTEMS += LIBDISASM
KERNEL_EXTRA_LIBS += $(LIBDISASM)
PREPROCESS_PARTS += jdb_disasm
SUBSYSTEMS += SIMPLEMALLOC
KERNEL_EXTRA_LIBS += $(SIMPLEMALLOC)
LIBDISASM := libdisasm.a
VPATH += lib/disasm lib/disasm/capstone \
lib/disasm/capstone/arch/RISCV
PRIVATE_INCDIR += lib/disasm lib/disasm/capstone/include
CXXSRC_LIBDISASM := disasm.cc
CSRC_LIBDISASM := cs.c utils.c \
MCInst.c MCInstrDesc.c MCRegisterInfo.c SStream.c \
RISCVModule.c RISCVInstPrinter.c \
RISCVDisassembler.c RISCVMapping.c
CPPFLAGS += -DCAPSTONE_HAS_RISCV
CFLAGS_RISCVInstPrinter = -Wno-unused-parameter -Wno-missing-field-initializers \
-Wno-bad-function-cast -Wno-implicit-fallthrough
CFLAGS_RISCVMapping = -Wno-unused-parameter -Wno-sign-compare
CFLAGS_RISCVDisassembler = -Wno-unused-parameter -Wno-missing-field-initializers \
-Wno-implicit-fallthrough
endif
#
# VERSION subsystem
#
VERSION := version.h
TCBOFFSET := tcboffset.h
CXXSRC_TCBOFFSET := tcboffset.cc dump_tcboffsets.cc
#
# BSP subsystem
#
BSP_NAME := $(patsubst "%",%,$(CONFIG_BSP_NAME))
BSP_SRC_DIR := kern/riscv/bsp/$(BSP_NAME)
MODULES_FILE_BSP := $(srcdir)/$(BSP_SRC_DIR)/Modules
ifeq ($(wildcard $(MODULES_FILE_BSP)),)
$(error No BSP name defined or no BSP Modules file available)
endif
include $(MODULES_FILE_BSP)
VPATH += $(BSP_SRC_DIR)
ifeq ("$(filter LIBUART, $(SUBSYSTEMS))","LIBUART")
LIBUART := uart/libuart.a
endif
CONFIG_KERNEL_LOAD_ADDR := $$(($(RAM_PHYS_BASE) + 0x800000))
CONFIG_KERNEL_VIRT_ADDR-32 := 0xf0000000
CONFIG_KERNEL_VIRT_ADDR-64 := 0xfffffff000000000
CONFIG_KERNEL_VIRT_ADDR := $(CONFIG_KERNEL_VIRT_ADDR-$(BITS))
MODULES_FILES += $(MODULES_FILE) $(MODULES_FILE_BSP)

View File

@@ -0,0 +1,208 @@
# -*- makefile -*-
# vi:se ft=make:
###############################################################################
include $(srcdir)/Modules.generic
SUBSYSTEMS += LIBUART
PREPROCESS_PARTS += $(CONFIG_XARCH) $(CONFIG_ABI) 32bit \
abs_syscalls big_endian jdb_thread_names \
obj_space_phys
PREPROCESS_PARTS-$(CONFIG_JDB) += debug log
PREPROCESS_PARTS += $(PREPROCESS_PARTS-y)
#
# TYPES subsystem
#
PRIVATE_INCDIR += types/$(CONFIG_XARCH) types
#
# LIBUART subsystem
#
ifeq ("$(filter LIBUART, $(SUBSYSTEMS))","LIBUART")
LIBUART := uart/libuart.a
PREPROCESS_PARTS += libuart
endif
OBJECTS_LIBUART += uart_leon3.o
CXXFLAGS_uart-libuart += $(call LIBUART_UART, leon3)
VPATH_LIBUART := $(srcdir)/lib/uart
PRIVATE_INCDIR += lib/uart drivers/$(CONFIG_XARCH)/include
#
# DRIVERS Subsystem
#
DRIVERS := libdrivers.a libgluedriverslibc.a
VPATH += drivers/$(CONFIG_XARCH) drivers
PRIVATE_INCDIR += drivers/$(CONFIG_XARCH) drivers
INTERFACES_DRIVERS := mux_console console mem reset uart filter_console \
processor delayloop io
INTERFACES_DRIVERS += $(if $(CONFIG_UART_CHECKSUM),stream_crc32)
io_IMPL := io io-sparc
mem_IMPL := mem mem-sparc
reset_IMPL := reset-sparc
processor_IMPL := processor processor-sparc
uart_IMPL := uart uart-libuart
CXXSRC_DRIVERS := glue_libc.cc
NOOPT += $(patsubst %.o, %, $(OBJ_DRIVERS))
#
# JABI Subsystem
#
JABI := libjabi.a
VPATH += jabi/$(CONFIG_XARCH) jabi
INTERFACES_JABI := jdb_ktrace jdb_obj_info
#
# KERNEL subsystem
#
KERNEL := fiasco
KERNEL_EXTRA := Symbols kernel.sparc.lds fiasco.debug
VPATH += kern/$(CONFIG_XARCH) kern
VPATH += jdb/$(CONFIG_XARCH) jdb
PRIVATE_INCDIR += kern/$(CONFIG_XARCH) kern
INTERFACES_KERNEL += boot_uart_init bootstrap decrementer psr sparc_types \
util utcb_support irq_chip_generic
INTERFACES_KERNEL-$(CONFIG_SERIAL) += uart_console
INTERFACES_KERNEL += $(INTERFACES_KERNEL-y)
clock_IMPL := clock
config_IMPL := config config-sparc
context_IMPL := context context-sparc context-vcpu
continuation_IMPL := continuation-sparc
cpu_IMPL := cpu cpu-sparc
cpu_lock_IMPL := cpu_lock cpu_lock-generic
dirq_IMPL := dirq-sparc
entry_frame_IMPL := entry_frame entry_frame-sparc
kdb_ke_IMPL += kdb_ke-sparc
kernel_task_IMPL := kernel_task kernel_task-sparc
kernel_thread_IMPL := kernel_thread kernel_thread-sparc
kernel_uart_IMPL := kernel_uart kernel_uart-libuart
kmem_IMPL := kmem kmem-sparc
kmem_alloc_IMPL := kmem_alloc kmem_alloc-sparc
map_util_IMPL := map_util map_util-mem map_util-objs
mem_layout_IMPL := mem_layout mem_layout-sparc
mem_unit_IMPL := mem_unit-sparc
mem_space_IMPL := mem_space mem_space-sparc
obj_space_IMPL := obj_space obj_space-phys
page_IMPL := page page-sparc
paging_IMPL := paging paging-sparc
pic_IMPL := pic
sched_context_IMPL := sched_context-wfq sched_context-fixed_prio \
sched_context-fp_wfq sched_context
startup_IMPL := startup startup-sparc
sys_call_page_IMPL := sys_call_page sys_call_page-sparc
task_IMPL := task task-sparc
timer_IMPL := timer timer-decr-sparc
thread_IMPL := thread thread-log thread-pagefault \
thread-sparc thread-ipc thread-jdb \
thread-vcpu
utcb_init_IMPL := utcb_init utcb_init-sparc
utcb_support_IMPL := utcb_support utcb_support-sparc
vmem_alloc_IMPL := vmem_alloc vmem_alloc-sparc
tb_entry_IMPL := tb_entry tb_entry-sparc
warn_IMPL := warn warn-sparc
ifeq ("$(CONFIG_JDB)","y")
JDB := jdb_compound.o
SUBSYSTEMS += JDB
CXXSRC_JDB := tb_entry_output.cc
jdb_IMPL += jdb-sparc
jdb_tcb_IMPL += jdb_tcb-sparc
jdb_entry_frame_IMPL += jdb_entry_frame-sparc
thread_IMPL += thread-debug
INTERFACES_JDB += $(INTERFACES_JDB-y)
endif
CXXSRC_KERNEL := kernel_panic.cc libc_backend_lock.cc
ASSRC_KERNEL := exceptions.S
NOOPT += $(filter jdb%,\
$(foreach in,$(INTERFACES_KERNEL), \
$(if $($(in)_IMPL),$($(in)_IMPL),$(in))))
NOOPT += tb_entry #tb_entry_output
#
# CRT0 subsystem
#
CRT0 := crt0.o
ASSRC_CRT0 := crt0.S
#
# CXXLIB Subsystem
#
CXXLIB := libcxx.a
VPATH += lib/cxxlib
CXXSRC_CXXLIB := paranoia.cc
#
# LIBK subsystem
#
LIBK := libk.a
VPATH += lib/libk/$(CONFIG_XARCH) lib/libk
PRIVATE_INCDIR += lib/libk/$(CONFIG_XARCH) lib/libk
INTERFACES_LIBK := atomic lock_guard std_macros
CSRC_LIBK += gcc_lib.c
CXXSRC_LIBK += construction.cc
atomic_IMPL := atomic atomic-sparc
#
# LIBDISASM subsystem (only for Jdb)
#
ifeq ("$(CONFIG_JDB_DISASM)","y")
# $(srcdir)/lib/disasm may be removed
ifeq ($(wildcard $(srcdir)/lib/disasm),)
$(error $(srcdir)/lib/disasm is missing, disable CONFIG_JDB_DISASM)
endif
SUBSYSTEMS += LIBDISASM
KERNEL_EXTRA_LIBS += $(LIBDISASM)
PREPROCESS_PARTS += jdb_disasm
LIBDISASM := libdisasm.a
VPATH += lib/disasm lib/disasm/elf lib/disasm/include \
lib/disasm/include/opcode lib/disasm/opcodes \
lib/disasm/libiberty lib/disasm/bfd
PRIVATE_INCDIR += lib/disasm lib/disasm/elf lib/disasm/include \
lib/disasm/include/opcode lib/disasm/opcodes \
lib/disasm/libiberty lib/disasm/bfd
PRIVATE_INCDIR += lib/disasm
CXXSRC_LIBDISASM := disasm.cc
CSRC_LIBDISASM := sparc-dis.c sparc-opc.c dis-init.c dis-buf.c \
safe-ctype.c libbfd.c
endif
#
# VERSION subsystem
#
VERSION := version.h
TCBOFFSET := tcboffset.h
CXXSRC_TCBOFFSET := tcboffset.cc dump_tcboffsets.cc
#
# BSP subsystem
#
BSP_NAME := $(patsubst "%",%,$(CONFIG_BSP_NAME))
MODULES_FILE_BSP := $(srcdir)/kern/sparc/bsp/$(BSP_NAME)/Modules
ifeq ($(wildcard $(MODULES_FILE_BSP)),)
$(error No BSP name defined or no BSP Modules file available)
endif
include $(MODULES_FILE_BSP)
VPATH += kern/sparc/bsp/$(BSP_NAME) kern/sparc/bsp
MODULES_FILES = $(MODULES_FILE) $(MODULES_FILE_BSP)

View File

@@ -0,0 +1,121 @@
Fiasco's build system
Michael Hohmuth
Motivation
==========
My main goal when I designed Fiasco's build system was to allow for
multiple configurations of the kernel, based on different
implementations of the same interface, to coexist in multiple object
directories.
Configuration
=============
Fiasco's build system consists of a number of configuration files. All
configuration files are written in Makefile language.
* `src/Makefile`:
``Fiasco's build system´´ rules
* `src/Modules.in`:
Standard configuration for Fiasco
* `src/Makerules.*`:
Make rules for each subsystem defined in Modules
* `src/Makerules.local`:
(Optional) User-specific configuration files
In the remainder of this section, I describe by example the language
used in Modules file and the contents of the Makerules.* files.
SUBSYSTEMS = FOO BAR
# Defines two subsystems, FOO and BAR. This means that there
# exist two files, Makerules.FOO and Makerules.BAR, that
# contain rules on how to build the targets of these
# subsystems. These targets are defined later.
### Definitions for subsystem FOO follow
FOO = foo
# Defines the main target of subsystem FOO: a file named
# "foo".
FOO_EXTRA = foo.man
# (Optional) Defines more targets that should be built for
# subsystem FOO.
INTERFACES_FOO = foo1 foo2 foo3
# (Optional) C++ modules for subsystem FOO (written in
# `preprocess´ format; see
# <URL:http://os.inf.tu-dresden.de/~hohmuth/prj/preprocess/>)
# Each module normally consists of one implementation file
# such as foo1.cpp -- unless IMPL definitions such as the
# following ones are given:
foo2_IMPL = foo2 foo2-more
# (Optional) C++ module foo2 is implemented in two files
# foo2.cpp and foo2-more.cpp (instead of just foo2.cpp). The
# public header file generated from these implementation files
# will be called foo2.h.
foo3_IMPL = foo3-debug
# (Optional) C++ module foo3 is implemented in foo3-debug.cpp,
# not foo3.cpp. The public header file generated from this
# implementation file will be called foo3.h.
CXXSRC_FOO = frob1.cc frob2.cc
# (Optional) Additional C++ sources for subsystem FOO (not in
# `preprocess' format)
CSRC_FOO = frob3.c frob4.c
# (Optional) Additional C sources for subsystem FOO
ASSRC_FOO = frob5.S
# (Optional) Additional assembly-language sources for
# subsystem FOO
OBJ_FOO = frob6.o
# (Optional) Additional objects for subsystem FOO. These
# objects can be precompiled or generated using custom rules
# in Makerules.FOO.
NOPROFILE += frob2
# (Optional) Basenames of objects that should not be compiled
# with profiling options in profiling builds.
NOOPT += frob3
# (Optional) Basenames of objects that should not be compiled
# with optimization options.
PRIVATE_INCDIR += incdir
# (Optional) Add incdir to the include path for all source
# files. (This feature is implemented by l4/Makeconf.)
VPATH += foodir
# (Optional) Add foodir to Make's source-file search
# path. (This feature is implemented internally by Make.)
### Definitions for subsystem BAR follow
### (similar to FOO's definitions)
The Makerules.FOO file usually contains just rules for linking the
subsystem's targets. Additionally, it must contain a rule
"clean-FOO:" that cleans the object directory from files created by
this configuration file.
It can access the following Make variables:
* `FOO`, `FOO_EXTRA`:
names of targets
* `OBJ_FOO`:
expanded to contain _all_ objects that will be created for subsystem
`FOO`
* `BAR`:
targets of other subsystems

View File

@@ -0,0 +1,642 @@
Fiasco style guide
Michael Hohmuth
Introduction
============
Motivation and intended audience
--------------------------------
This document is meant as a quick reference to a number of guidelines
meant for existing and especially new Fiasco kernel developers.
How to follow these rules: Metarules
------------------------------------
This document does not differentiate between strict rules and "soft"
guidelines. Also, when browsing the source code, you will notice a
large number of deviations from these rules (because most rules are
younger than the current kernel code). In this sense, all rules are
"soft."
However, as the master guideline, when writing new code, please ensure
that the number of rule violations does not grow. (In the future, we
might even enforce this property automatically when someone is
checking in code.)
Programming language, dialect, and subset
=========================================
Fiasco has been written in C++. However, it uses C++ in a special
dialect supported by the Preprocess tool [Hohmuth: Preprocess]. In
effect, programmers do not need to write C++ header files, and do not
need to declare (member) functions -- Preprocess automates these
tasks.
We use some features of Preprocess for configuration
management---please refer to Section
[Configuration-specific source code](#configuration-specific-source-code).
Preprocess lacks support for the following C++ features, which
therefore cannot be used in Fiasco source code (but can be used in
third-party source code used, i.e., can be included, by Fiasco):
* Name spaces --- use static class interfaces or global or static free
functions instead (Section [Singletons](#singletons)).
* Nested classes --- use forward-declared "private classes" instead
* `#ifdef` and
`#if` on file top level, except for
`#if 0` --- use
Preprocess' configuration features instead (Section
[Configuration-specific source code](#configuration-specific-source-code)).
Some features of C++ are explicitly disallowed because Fiasco contains
no run-time support for them:
* Exceptions
* Run-time type identification and `dynamic_cast`
These features are always disabled on the compiler command line.
On the other hand, templates are allowed. However, please keep in
mind that Fiasco's source code needs to be interpreted not only by the
latest version of GCC, but also by at least the two preceding stable
versions of GCC.
Source-code organization and directory structure
================================================
Subsystems
----------
Fiasco consists of a number of subsystems; among them:
* `KERNEL`:
The kernel proper. This is the part that implements the L4
specification.
* `ABI`:
ABI-specific definitions, mostly type definitions and accessor
functions.
* `JDB`:
The built-in kernel debugger.
* `BOOT`:
The bootstrapper. This part sets up virtual memory, copies the
kernel to its standard virtual-address-space location (0xf0001000),
and runs the kernel.
Subsystems are defined in the Modules file, which is the main
configuration file for Fiasco's build system. Please refer to
the build-system documentation [README.buildsystem.md] for more
information on this build system.
Directory structure
-------------------
Subsystems usually reside in their own directory under src (the
exception being those subsystems which do not contain any source code,
but which exist only for maintenance purposes).
Inside each (source-code) subsystem directory such as kern, the
directory layout is as follows:
* `kern`:
Source files shared for all Fiasco-supported architectures
* `kern/ia32`, `kern/arm`, and so on:
Source files that are specific for only one architecture.
Currently, hardware architectures is the only configuration dimension
that motivates moving a source file into a subdirectory. In other
words, source files pertaining to a particular configuration option
(other than hardware architecture), but not another, are located in
one of the mentioned directories.
Source-file naming
------------------
Usually, source files belong to exactly one module, consisting of one
main C++ class plus, optionally, public utility functions, small
interface classes for exchanging data with the main class, and private
auxiliary classes and functions. A module can be comprised of
multiple source files. These source files all start with the name of
the module's main class, in all lower case (e.g., for class
`Thread_state`, file names start with the string "thread_state"). When
multiple source files implement one module, each file name (except for
the main file's) add a submodule-specific suffix, separated with a
dash (`-`). For example:
* `kern/thread.cpp`
* `kern/thread-ipc.cpp`
Fiasco's build system mandates that all source files (of all
subsystems) have different names, even if they reside in different
directories. To make file names different, our naming convention is
to add architecture-configuration strings to the file names, separated
by dashes (-). For example:
* `kern/thread.cpp`
* `kern/shared/thread-ia32.cpp`
Occasionally, it is useful to separate configuration-specific code
into a source file of its own (see Section
[Configuration-specific source code](#configuration-specific-source-code)).
In this case, the file name contains the configuration string as a suffix,
separated by dashes(-). For example:
* `kern/ia32/timer-pit.cpp`
* `kern/ia32/32/tb_entry-ia32-32.cpp`
* `kern/ia32/64/tb_entry-ia32-64.cpp`
Header files and the C++ preprocessor
-------------------------------------
As Preprocess assumes the task of writing header files, programmers
should not add new header files. The exception to this rule is that
header files are required when defining constants that are needed by
both assembly code and C++ code.
When using header files, these files must be protected from multiple
inclusions using include-file guards, as in the following example for
the file `config_gdt.h`:
```cpp
#ifndef CONFIG_GDT_H
#define CONFIG_GDT_H
// File contents
#endif
```
Configuration management
========================
The configuration tool
----------------------
The interactive configuration tool is started using `make menuconfig`.
The tool creates two files, intended for inclusion in C++ code and in
makefiles:
* `globalconfig.h`:
This file defines a preprocessor symbol for each
_enabled_ configuration option.
* `globalconfig.out`:
This file defines a Make variable for set _each_
configuration option. Variables for enables options are set to "y",
those for disabled options are set to "n".
### Adding new configuration options
Fiasco uses Kconfig to configure and select features. Please refer to the
[kconfig language][1] to learn how to add new configuration options.
After a new config option has been added, define under which conditions the
config option should be suppressed, if any. It is generally a good idea to
suppress config options for architectures and configurations where the option
is meaningless. New configuration options must add a help text describing what
the config option does.
Do not forget to update the configuration templates in the directory
src/templates after modifying configuration options.
[1]: https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt
Class Config
------------
This class defines boot-time and constant configuration variables for
Fiasco.
The constant variables can be derived from options the configuration
tool has written to globalconfig.h. As a special exception, `#ifdef`
is allowed here.
Configuration-specific source code
----------------------------------
### Single or multiple source files
Source code that is specific to one or a single combination of
configuration options can reside in a separate file or in the same
file as code for other configuration options. The decision of which
works better is in the developer's discretion. Developers should try
to combine logically cohesive code fragments in one source file, even
if the fragments are mutually exclusive.
### Conditional compilation
Using preprocessor constants and `#ifdef` for conditional compilation
is only allowed for source code passed to the assembler (assembly
files and header files meant to be included in assembly code). In C++
source code, this style is discouraged, and Preprocess does not even
support it (for top-level conditional compilation).
Configuration-specific C++ code blocks are labeled using Preprocess'
configuration-tag feature with `IMPLEMENTATION` and `INTERFACE`
directives.
This feature is available only on file top level. Conditional
compilation inside function or class blocks is not allowed. Instead,
programmers have the following options:
* For class definitions:
* Use Preprocess' `EXTENSION` feature to extend class data with
configuration-specific contents.
* For function definitions:
* Create a Boolean constant in class Config that depends on the
configuration option (`#ifdef` is allowed there; see Section
[Class Config](#class-config)), and use the normal C++ `if` statement
to conditionalize the code. We rely on the C++ compiler's optimizer
to remove dead code.
* Factor out configuration-specific functions with a common
interface.
Compile-time polymorphism
-------------------------
Many configurable aspects of Fiasco are implemented as a set of
(member) functions that implement a given interface in a specific way.
However, unlike typical C++ programs, Fiasco usually does not define
these interfaces as abstract base classes and then derives
configuration-specific subclass implementations from them. We have
deemed the overhead of virtual-function calls as too high in many
cases.
Instead, in Fiasco these interfaces are not declared as virtual
functions, but as non-virtual functions. These functions are then
defined in configuration-specific `IMPLEMENTATION` sections, which can
be combined in one file or spread across multiple files (see Section
[Configuration-specific source code](#configuration-specific-source-code)).
Preprocess assists in this kind of compile-time polymorphism by allowing
configuration-specific inline functions and private member functions.
These interfaces do not need to be split out into separate classes.
It is often useful to have a part of a class interface that is
implemented in a configuration-specific way.
Usually, Preprocess assumes the task of copying (member-) function
declarations into a module's public header file, and this is our
preferred usage. However, for interfaces that are implemented in a
configuration-specific source-code block, we make an exception: The
"public" interface (i.e., the interface used by generic client code,
which not necessarily needs consist of only public member functions)
can be declared and documented in the `INTERFACE` section of the
corresponding module. To prevent Preprocess from adding another
declaration, the definition needs to add the `IMPLEMENT` directive.
The prerequisite is that the interface is implemented in an
`IMPLEMENTATION` section that depends on _more_ configuration options
than the `INTERFACE` section containing the declaration. For example:
```cpp
INTERFACE:
class Pic
{
public:
/**
* Static initialization of the interrupt controller.
*/
static void init();
// ...
};
IMPLEMENTATION[i8259]:
IMPLEMENT
void
Pic::init()
{
pic_init(0x20,0x28);
}
```
Maintainer-mode configuration
-----------------------------
Fiasco's build process can be instrumented with a number of checks
that ensure some of the rules defined in this document. Fiasco
developers should enable this option in the interactive configuration
tool; the option is called `MAINTAINER_MODE` ("Do additional checks
at build time").
The checks enabled by this option include:
* Checking for mutual or circular dependencies between modules (see
Section [Dependency management](#dependency-management)).
* Checking for use of deallocated initialization data after
initialization time.
Dependency management
=====================
Fiasco has been designed to be configurable and robust. A
precondition for achieving these properties is that modules and
subsystems can be removed from the kernel and tested in isolation,
which in turn depends on the absence of mutual or circular
dependencies between modules and subsystems.
Therefore, as a rule, these dependencies must be avoided. Please
consult [Lakos: Large-scale C++ Software Design] for standard methods to
resolve circular dependencies.
The current dependency graph can be generated in text or graphics form
using "make DEPS" and "make DEPS.ps".
Source-code style and indentation
=================================
Naming conventions
------------------
In general, Fiasco developers despise the ugly
`MixedCapsNamingConvention` made popular by Java. If you really must
use such names, please go hack some Java project, not Fiasco. In
Fiasco, words in multi-word identifier names are generally separated
with underscores, with the sequencing words starting with a lowercase
letter or a digit (the only exception being preprocessor symbols).
Examples:
```cpp
Funky_type
thread_id
Thread_ready
_current_sched
_thread_0
```
In particular, the conventions are as follows:
* Type names (class names, typedef names, enum names) all start with a
capital letter.
Examples: `Thread`, `Jdb`, `Boot_info`
* Function names (both member functions and free functions) start with
a lowercase letter.
Examples: `fpage_map()`, `ipc_send_regs()`
* Nonstatic member variables start with an underscore (`_`).
Examples: `_mode`, `_ready_time`
* Other variables (including static member variables, global and local
variables, function-argument names) start with a lower-case letter.
Examples: `preempter`, `cpu_lock`
* Enumeration constants start with a capital letter.
Examples: `Thread_ready`, `Page_writable`
The Fiasco architecture board has declared that having the same
naming convention for types and constants is not confusing.
* Preprocessor-symbol identifiers are all-uppercase and start with a
letter. As with all other identifiers, multiple words are separated
using underscores.
Examples: `THREAD_BLOCK_SIZE`, `CONFIG_PF_PC`
Please note that preprocessor constants are deprecated and allowed
only in assembly files and header files meant to be included in
assembly code
(see Section [Constant definitions](#constant-definitions)).
(For file-naming conventions refer to
Section [Source-file naming](#source-file-naming).)
Comments
--------
All comments must be in English. American / Aussie / Kiwi English are
OK, too, but Pidgin English or Denglisch are not.
### Doxygen comments
Please document at least all interfaces of all classes that are meant
for client-code use. These interfaces usually include all public and
protected member functions and all nonstatic free functions, but
possibly more if there is a private interface implemented by
configuration-specific code.
The interface documentation belongs to the function definition, except
if configuration-specific functions (with the `IMPLEMENT` directive)
are declared in an `INTERFACE` section. In that case, the
documentation belongs to the declaration.
Please use Doxygen's `\command` syntax to document your interfaces. Fiasco's
documentation is generated using Doxygen's auto-brief feature, so `\brief`
directives are unnecessary [Heesch: Doxygen Manual].
### Comment style
The style of multi-line comments is not prescribed, but please be
consistent within one source file. All of the following forms are
OK:
```cpp
/** The foo function.
* This function frobnifies its arguments.
*/
/**
* The foo function.
* This function frobnifies its arguments.
*/
/** The foo function.
This function frobnifies its arguments.
*/
```
### Marking incomplete code
Please use the token `XXX` inside a comment to mark broken or
incomplete code.
Module-level rules
------------------
### Singletons
Singleton objects (classes that will be instantiated only once) should
be implemented as static class interfaces instead of a normal
instantiable class in order to save kernel-stack space (the this
pointer does not need to be passed to these classes). However,
developers should use normal classes when it is foreseeable that the
class needs to be instantiated multiple times in the future, for
instance to support SMP machines.
### Constant definitions
Constants should generally only be defined in enumerations.
Preprocessor constants are discouraged except for source code passed
to the assembler (assembly files and header files meant to be included
in assembly code).
In C++ code, preprocessor constants must not be used for conditional
compilation using `#ifdef` and friends (see Section
[Conditional compilation](#conditional-compilation)).
### Bit-field types
When implementing a binary interface that has been specified in terms
of bits of machine words (such as the L4 ABI or a device interface),
it is a bad idea to implement the interface using bit-field types,
unless the interface is architecture-specific. The reason is that the
assignment of bit-field members to bit offsets is both
compiler-dependent and architecture-dependent. If bit fiddling is
required, please define a class that wraps an integral type (such as
`unsigned`) and manipulate the bits using bit-and and bit-or
operators.
Bit-field structures are OK when the exact order of bits in the type's
memory representation does not matter.
Block-level rules
-----------------
### Assertions
Use assertions generously.
Fiasco supports two kinds of runtime assertions: `assert` and `check`.
Both cause a kernel panic when their argument evaluates to false.
The first, `assert`, works just like `assert` in standard C. It can
be removed from the build by defining the preprocessor symbol `NDEBUG`
and therefore must not include code that has side effects.
When side effects are desired, use `check` instead of assert. The
contents of this macro are not optimized away with `NDEBUG` -- only
the error-checking code is.
### Common idioms
* Endless loops are programmed like this:
```cpp
for (;;)
// do stuff
```
* Sometimes a private inline function is desired, for example if it
needs to be wrapped by a stub that is callable from assembly code.
In this case, use `inline NOEXPORT` to avoid having to specify a
lengthy `NEEDS[]` directive for the inline function:
```cpp
extern "C"
void
asm_callable_stub (Thread* t)
{
t->do_stuff();
}
PRIVATE inline NOEXPORT
Thread::do_stuff ()
{
// ...
}
```
* Macros are discouraged. Use inline functions instead.
* If you really, absolutely have to define a macro, please make sure
it can be used as single-statement blocks after `if`, `else`, and
the like, by wrapping it like this:
```cpp
#define foo(x) do { /* your stuff */ } while (0)
```
### Rules for spacing, bracing, and indentation
If not specified more precisely in this standard, the GNU Coding
Conventions for spacing and bracing apply (GNU Coding Standards,
Section 5.1).
* The tabulator size is 8. A tabulator can always be replaced with
spaces that lead to the next tab stop.
* The maximum line length is 80. If a code line becomes longer than
80 characters, it must be broken into shorter lines. If line length
becomes excessive, developers should factor out utility functions.
* The indentation increment is 2 spaces.
* In function definitions, put both the return type and the function
signature on a line by themselves. Example:
```cpp
PUBLIC inline
void
Preemption::set_preempter (Receiver *preempter)
{
// ...
}
```
* Put whitespace before each opening parenthesis, except if it is
preceded by another opening parenthesis. Put whitespace after each
closing parenthesis, except if it is followed by another closing
parenthesis or a comma or semicolon. As a special exception, you do
not need to put a space between a function name and the
function-call operator.
```cpp
a = f (b(), sin ((x + y) * z));
```
* Do not wrap the argument to the `return` statement into parentheses.
* Opening and closing braces (`{`, `}`, including the form `};`)
always reside on a line of their own. The braces are indented for
nested code blocks, but not for type and function definitions. The
braced content is always indented with respect to the braces.
Goto labels are back-indented 1 space, class-access specifiers
(public, protected, private) are back-indented 2 spaces.
```cpp
class Thread
{
public:
enum Thread_state
{
Thread_invalid, Thread_running
};
int _prio;
};
PUBLIC
void
Thread::stuff ()
{
if (receiver()->ipc_try_lock (this) == 0)
{
do_stuff();
}
}
```
As an exception, if a function definition fits into a single line,
the whole function can be defined in one line. This style can aid
readability when defining many small functions in a row.
* Curly braces around single-statement code blocks for `if`, `while`,
`do`, and `for` are optional, except if the control expression(s) of
these statement spans more than one line, the statement following it
must be braced.
* Spacing inside expressions is not prescribed. Please do something
sensible to save us from adding more rules to this document.

View File

@@ -0,0 +1,7 @@
IMPLEMENTATION [amd64 && debug]:
IMPLEMENT inline
void
Kip::debug_print_syscalls() const
{}

View File

@@ -0,0 +1,22 @@
/*
* AMD64 Kernel-Info Page
*/
INTERFACE [amd64]:
#include "types.h"
EXTENSION class Kip
{
public:
struct Platform_info
{
char name[16];
Unsigned32 is_mp;
};
/* 0x1E0 */
Platform_info platform_info;
Unsigned32 __reserved[3];
};

View File

@@ -0,0 +1,82 @@
/*
* ARM Kernel-Info Page
*/
INTERFACE [arm]:
#include "config.h"
#include "cxx/static_vector"
#include "types.h"
EXTENSION class Kip
{
public:
class Kip_array
{
Kip *_first;
unsigned _length;
enum : unsigned { Kip_size = Config::PAGE_SIZE };
public:
class Iterator
{
friend class Kip_array;
Iterator(Kip *i) : _i(i) {}
Kip *_i;
public:
bool operator==(Iterator const &other) const { return _i == other._i; }
bool operator!=(Iterator const &other) const { return _i != other._i; }
Kip *operator*() const { return _i; }
Kip *operator->() const { return _i; }
Iterator &operator++()
{
_i = offset_cast<Kip *>(_i, Kip_size);
return *this;
}
};
Kip_array(Kip *first, unsigned length)
: _first(first), _length(length)
{}
Iterator begin() const { return Iterator(_first); }
Iterator end() const { return Iterator(offset_cast<Kip *>(_first, Kip_size * _length)); }
Kip *operator[](unsigned i)
{ return offset_cast<Kip *>(_first, Kip_size * i); }
};
struct Platform_info
{
char name[16];
Unsigned32 is_mp;
Unsigned32 arch_cpuinfo[67];
};
/* 0xF0 / 0x1E0 */
Platform_info platform_info;
};
//---------------------------------------------------------------------------
IMPLEMENTATION [arm]:
#include "amp_node.h"
PUBLIC static inline NEEDS["amp_node.h"]
Kip::Kip_array
Kip::all_instances()
{
extern char my_kernel_info_page[];
Kip *first = reinterpret_cast<Kip*>(my_kernel_info_page);
return Kip_array(first, Amp_node::Max_num_nodes);
}
//---------------------------------------------------------------------------
IMPLEMENTATION [arm && debug]:
IMPLEMENT inline
void
Kip::debug_print_syscalls() const
{}

View File

@@ -0,0 +1,20 @@
IMPLEMENTATION [ia32 && debug]:
#include <cstring>
#include "types.h"
IMPLEMENT
void
Kip::debug_print_syscalls() const
{
unsigned kips = kip_sys_calls;
static char const* const KIPS[] = {"No KIP syscalls supported",
"KIP syscalls via KIP relative stubs",
"KIP syscalls via absolute stubs",
"KIP syscalls ERROR: bad value"};
if (kips > 3)
kips = 3;
printf("%s\n", KIPS[kips]);
}

View File

@@ -0,0 +1,21 @@
/*
* IA-32 Kernel-Info Page
*/
INTERFACE [ia32]:
#include "types.h"
EXTENSION class Kip
{
public:
struct Platform_info
{
char name[16];
Unsigned32 is_mp;
};
/* 0xF0 */
Platform_info platform_info;
Unsigned32 __reserved[3];
};

View File

@@ -0,0 +1,116 @@
INTERFACE [debug]:
EXTENSION class Kip
{
private:
void debug_print_syscalls() const;
};
//----------------------------------------------------------------------------
IMPLEMENTATION [debug]:
#include <cstdio>
#include <cstring>
#include "simpleio.h"
static char const *const memory_desc_types[] = {
"Undefined",
"Conventional",
"Reserved",
"Dedicated",
"Shared",
"(undef)",
"(undef)",
"(undef)",
"(undef)",
"(undef)",
"(undef)",
"(undef)",
"(undef)",
"(undef)",
"Bootloader",
"Arch"
};
PUBLIC
void
Mem_desc::dump() const
{
printf("%s [%016llx-%016llx] %s", is_virtual() ? "virt" : "phys",
Unsigned64{start()}, Unsigned64{end()} + 1, memory_desc_types[type()]);
}
PRIVATE
void
Kip::debug_print_memory() const
{
printf("Memory (max %u descriptors):\n",num_mem_descs());
for (auto const &m: mem_descs_a())
{
if (m.type() != Mem_desc::Undefined)
{
printf(" %2u:", mem_descs_a().index(m) + 1);
m.dump();
puts("");
}
}
}
PRIVATE
void
Kip::debug_print_features() const
{
printf("Kernel features:");
char const *f = version_string();
for (f += strlen(f) + 1; *f; f += strlen(f) + 1)
{
putchar(' ');
putstr(f);
}
putchar('\n');
}
IMPLEMENT
void
Kip::print() const
{
printf("KIP @ %p\n", static_cast<void const *>(this));
printf("magic: %.4s version: 0x%x\n",
reinterpret_cast<char const *>(&magic), version);
print_clock();
printf("freq_cpu: %llukHz\n", frequency_cpu);
printf("sigma0_ip: %016llx\n", sigma0_ip);
printf("root_ip: %016llx\n", root_ip);
debug_print_memory();
debug_print_syscalls();
printf("user_ptr: %016llx acpi_rsdp_addr: %016llx\n",
user_ptr, acpi_rsdp_addr);
debug_print_features();
}
//----------------------------------------------------------------------------
IMPLEMENTATION[!sync_clock && debug]:
PRIVATE inline
void
Kip::print_clock() const
{
Cpu_time c = clock();
printf("clock: " L4_X64_FMT " (%llu)\n", c, c);
printf("uptime: %llu day(s), %llu hour(s), %llu min(s), %llu sec(s)\n",
c / (1000000ULL * 60 * 60 * 24),
(c / (1000000ULL * 60 * 60)) % 24,
(c / (1000000ULL * 60)) % 60,
(c / 1000000ULL) % 60);
}
//----------------------------------------------------------------------------
IMPLEMENTATION[sync_clock && debug]:
PRIVATE inline
void
Kip::print_clock() const
{}

280
src/fiasco/src/abi/kip.cpp Normal file
View File

@@ -0,0 +1,280 @@
INTERFACE:
#include <cxx/static_vector>
class Mem_desc
{
public:
enum Mem_type
{
Undefined = 0x0,
Conventional = 0x1,
Reserved = 0x2,
Dedicated = 0x3,
Shared = 0x4,
Kernel_tmp = 0x7,
Info = 0xd,
Bootloader = 0xe,
Arch = 0xf,
};
enum Ext_type_info
{
Info_acpi_rsdp = 0
};
private:
Mword _l, _h;
};
//----------------------------------------------------------------------------
INTERFACE:
#include "types.h"
#include "global_data.h"
class Kip
{
public:
enum : Cpu_time
{
Clock_1_second = 1000000ULL,
Clock_1_hour = 3600ULL * Clock_1_second,
Clock_1_day = 24ULL * Clock_1_hour,
Clock_1_year = 365UL * Clock_1_day,
};
void print() const;
char const *version_string() const;
Cpu_time clock() const;
void set_clock(Cpu_time c);
void add_to_clock(Cpu_time plus);
/* 0x00 */
Unsigned32 magic;
Unsigned32 version;
Unsigned8 offset_version_strings;
Unsigned8 _fill0[3];
Unsigned8 kip_sys_calls;
Unsigned8 node;
Unsigned8 _fill1[2];
/* 0x10 */
Unsigned64 sigma0_ip; ///< Sigma0 instruction pointer
Unsigned64 root_ip; ///< Root task instruction pointer
/* 0x20 */
volatile Cpu_time _clock; // don't access directly, use clock() instead!
// not updated in certain configurations
Unsigned64 frequency_cpu; ///< CPU frequency in kHz
/* 0x30 */
Unsigned64 acpi_rsdp_addr; ///< ACPI RSDP/XSDP
Unsigned64 dt_addr; ///< Device Tree
/* 0x40 */
Unsigned64 user_ptr; ///< l4-mod-info pointer
Unsigned64 mbt_counter; // only used for model-based testing
/* 0x50 */
Unsigned32 sched_granularity; ///< for rounding time slices
Unsigned32 _mem_descs; ///< memory descriptors relative to Kip
Unsigned32 _mem_descs_num; ///< number of memory descriptors
Unsigned32 _res1[1]; ///< \internal
/* 0x60: */
Unsigned64 _res2[2]; ///< \internal - spare space
/* 0x70:
* Platform_info. */
/* 0x70 + sizeof(Platform_info):
* - Memory descriptors (2 Mwords per descriptor),
* - kernel version string ('\0'-terminated),
* - feature strings ('\0'-terminated)
* - terminating '\0'. */
/* 0x800-0x900:
* Code for syscall invocation. */
/* 0x900-0x97F:
* Code for reading the system clock with microsecond resolution. Depending on
* the configuration, this clock might or might not be synchronized with the
* KIP clock. */
/* 0x980-0x9FF:
* Code for reading the system clock with nanosecond resolution. Depending on
* the configuration, this clock might or might not be synchronized with the
* KIP clock. */
private:
static Global_data<Kip *> global_kip;
};
#define L4_KERNEL_INFO_MAGIC (0x4BE6344CL) /* "L4µK" */
//============================================================================
IMPLEMENTATION:
#include "assert.h"
#include "config.h"
#include "mem.h"
#include "panic.h"
#include "version.h"
PUBLIC inline
Mem_desc::Mem_desc(Address start, Address end, Mem_type t, bool v = false,
unsigned st = 0)
: _l((start & ~0x3ffUL) | (t & 0x0f) | ((st << 4) & 0x0f0)
| (v?0x0200:0x0)),
_h(end)
{}
PUBLIC inline ALWAYS_INLINE
Address Mem_desc::start() const
{ return _l & ~0x3ffUL; }
PUBLIC inline ALWAYS_INLINE
Address Mem_desc::end() const
{ return _h | 0x3ffUL; }
PUBLIC inline ALWAYS_INLINE
Address Mem_desc::size() const
{ return end() - start() + 1; }
PUBLIC inline ALWAYS_INLINE
void
Mem_desc::type(Mem_type t)
{ _l = (_l & ~0x0f) | (t & 0x0f); }
PUBLIC inline ALWAYS_INLINE
Mem_desc::Mem_type Mem_desc::type() const
{ return static_cast<Mem_type>(_l & 0x0f); }
PUBLIC inline
unsigned Mem_desc::ext_type() const
{ return (_l >> 4) & 0x0f; }
PUBLIC inline ALWAYS_INLINE
unsigned Mem_desc::is_virtual() const
{ return _l & 0x200; }
PUBLIC inline ALWAYS_INLINE
unsigned Mem_desc::eager_map() const
{ return _l & 0x100; }
PUBLIC inline
bool Mem_desc::contains(Address addr) const
{
return start() <= addr && end() >= addr;
}
PUBLIC inline ALWAYS_INLINE
bool Mem_desc::valid() const
{ return type() && start() < end(); }
PRIVATE inline ALWAYS_INLINE
Mem_desc *Kip::mem_descs()
{ return offset_cast<Mem_desc*>(this, _mem_descs); }
PRIVATE inline
Mem_desc const *Kip::mem_descs() const
{ return offset_cast<Mem_desc const *>(this, _mem_descs); }
PUBLIC inline ALWAYS_INLINE
unsigned Kip::num_mem_descs() const
{ return _mem_descs_num; }
PUBLIC inline NEEDS[Kip::num_mem_descs, Kip::mem_descs] ALWAYS_INLINE
cxx::static_vector<Mem_desc>
Kip::mem_descs_a()
{ return cxx::static_vector<Mem_desc>(mem_descs(), num_mem_descs()); }
PUBLIC inline NEEDS[Kip::num_mem_descs, Kip::mem_descs] ALWAYS_INLINE
cxx::static_vector<Mem_desc const>
Kip::mem_descs_a() const
{ return cxx::static_vector<Mem_desc const>(mem_descs(), num_mem_descs()); }
PUBLIC inline
void Kip::num_mem_descs(unsigned n)
{ _mem_descs_num = n; }
PUBLIC
Mem_desc *Kip::add_mem_region(Mem_desc const &md)
{
for (auto &m: mem_descs_a())
if (m.type() == Mem_desc::Undefined)
{
m = md;
return &m;
}
// Add mem region failed -- must be a Fiasco startup problem. Bail out.
panic("Too few memory descriptors in KIP");
}
DEFINE_GLOBAL Global_data<Kip *> Kip::global_kip;
PUBLIC static inline ALWAYS_INLINE NEEDS["config.h"]
void
Kip::init_global_kip(Kip *kip)
{
global_kip = kip;
kip->platform_info.is_mp = Config::Max_num_cpus > 1;
kip->sched_granularity = Config::Scheduler_granularity;
// check that the KIP has actually been set up
//assert(kip->sigma0_ip && kip->root_ip && kip->user_ptr);
}
PUBLIC static inline Kip *Kip::k() { return global_kip; }
IMPLEMENT
char const *Kip::version_string() const
{
static_assert((sizeof(Kip) & 0xf) == 0, "Invalid KIP structure size");
return reinterpret_cast <char const *> (this) + (offset_version_strings << 4);
}
#ifdef TARGET_NAME
#define TARGET_NAME_PHRASE " for " TARGET_NAME
#else
#define TARGET_NAME_PHRASE
#endif
asm(".section .initkip.version, \"a\", %progbits \n"
".string \"" CONFIG_KERNEL_VERSION_STRING "\" \n"
".previous \n");
asm(".section .initkip.features.end, \"a\", %progbits \n"
".string \"\" \n"
".previous \n");
//----------------------------------------------------------------------------
IMPLEMENTATION[!sync_clock]:
IMPLEMENT inline NEEDS["mem.h"]
Cpu_time
Kip::clock() const
{ return Mem::read64_consistent(const_cast<Cpu_time const *>(&_clock)); }
IMPLEMENT inline
void
Kip::set_clock(Cpu_time c)
{ _clock = c; }
IMPLEMENT inline NEEDS["mem.h"]
void
Kip::add_to_clock(Cpu_time plus)
{
// This function does not force a full atomic update. The caller needs to be
// aware about this: Either the update is performed by a single specific CPU
// (the boot CPU) or the callers have to use a lock.
// However, on ARM < v7, the update of the 64-bit clock can be observed in
// any order defeating the user-level retry loop for reading the clock which
// assumes that low word is written before the high word.
Mem::write64_consistent(const_cast<Cpu_time *>(&_clock), _clock + plus);
}

View File

@@ -0,0 +1,109 @@
INTERFACE:
#include "types.h"
#include <cxx/bitfield>
/**
* Description of the mapping buffer registers contained in the UTCB
* (used e.g. during IPC).
* The utcb can contain buffers that describe memory regions, bits in the
* I/O bitmap or capabilities. The buffer description is used to find the
* first buffer for each type.
* Additionally, the buffer description contains a flag to specify the
* willingness to receive FPU state in an IPC operation.
*
* Note that a single buffer might occupy more than one word in the buffer-
* registers array in the UTCB. The L4_buf_iter class can be used to iterate
* over buffers.
*/
class L4_buf_desc
{
public:
enum Flags
{
/**
* Flag the willingness to receive FPU state during IPC.
*
* If this flag is set, the receiving thread in an IPC is willing
* to receive the status of the floating point unit (FPU) from its partner
* as part of an IPC. Conceptually, this flag adds the FPU of the
* receiver as an additional message receiver buffer.
* The sender must set the corresponding flag L4_msg_tag::Transfer_fpu.
*/
Inherit_fpu = (1UL << 24)
};
/**
* Create an uninitialized buffer descriptor.
* \note The value of the buffer descriptor is unpredictable.
*/
L4_buf_desc() = default;
/**
* Create a buffer descriptor with given values.
* \param mem the BR index for the first memory buffer item.
* \param io the BR index for the first I/O-port buffer item.
* \param obj the BR index for the first object/capability buffer item.
* \param flags the flags, such as, Inherit_fpu.
*
* The buffer registers must contain blocks of buffers of identical
* type (memory, caps, I/O-ports) starting at the given index. The first
* non-matching item terminates the items of the particular type.
* \see Utcb and L4_msg_tag
*/
L4_buf_desc(unsigned mem, unsigned io, unsigned obj,
unsigned flags = 0)
: _raw( mem_bfm_t::val_dirty(mem)
| io_bfm_t::val_dirty(io)
| obj_bfm_t::val_dirty(obj)
| flags)
{}
/**
* The flags of the BDR.
* \return flags encoded in the BDR, see #Inherit_fpu, L4_buf_desc::Flags.
* \note The return value may have reserved bits set.
*/
Mword flags() const { return _raw; }
/**
* Get the raw binary representation of the buffer descriptor.
* \return binary representation of the buffer descriptor.
*/
Mword raw() const { return _raw; }
private:
/**
* A single machine word that describes the buffers that follow:
* - Bits 0..4: The index of the first memory buffer.
* - Bits 5..9: The index of the first io buffer.
* - Bits 10..14: The index of the first capability buffer.
* - Bits 15..23: Unused
* - Bits 24..31: Flags as defined above (only #Inherit_fpu is in use).
*/
Mword _raw;
public:
/** \name Index of the first memory receive buffer
*
* The memory receive items use two BRs each.
* \see L4_fpage, L4_msg_item
*/
CXX_BITFIELD_MEMBER( 0, 4, mem, _raw);
/** \name Index of the first IO-port receive buffer
*
* The I/O-port buffer items use two BRs each.
* \see L4_fpage, L4_msg_item.
*/
CXX_BITFIELD_MEMBER( 5, 9, io, _raw);
/** \name Index of the first object receive buffer
*
* An object receive buffer may use one or two BRs depending on the
* value in the L4_msg_item in the first BR.
* \see L4_msg_item, L4_fpage.
*/
CXX_BITFIELD_MEMBER(10, 14, obj, _raw);
};

View File

@@ -0,0 +1,65 @@
INTERFACE:
#include "types.h"
class L4_error
{
public:
enum Error_code
{
None = 0,
Timeout = 2,
R_timeout = 3,
Not_existent = 4,
Canceled = 6,
R_canceled = 7,
Overflow = 8,
Snd_xfertimeout = 10,
Rcv_xfertimeout = 12,
Aborted = 14,
R_aborted = 15,
Map_failed = 16,
};
enum Phase
{
Snd = 0,
Rcv = 1
};
L4_error(Error_code ec = None, Phase p = Snd) : _raw(Mword{ec} | Mword{p}) {}
L4_error(L4_error const &e, Phase p) : _raw(e._raw | p) {}
bool ok() const { return (_raw & 0xff) == 0; }
Error_code error() const { return Error_code(_raw & 0x1f); }
Mword raw() const { return _raw; }
bool snd_phase() const { return !(_raw & Rcv); }
bool empty_map() const { return _raw & 0x100; }
void set_empty_map() { _raw |= 0x100; }
static L4_error from_raw(Mword raw) { return L4_error(true, raw); }
private:
L4_error(bool, Mword raw) : _raw(raw) {}
Mword _raw;
};
//----------------------------------------------------------------------------
IMPLEMENTATION [debug]:
static char const *__errors[] =
{ "OK", "timeout", "not existent", "canceled", "overflow",
"xfer snd", "xfer rcv", "aborted", "map failed" };
PUBLIC
char const *
L4_error::str_error()
{
return __errors[(_raw >> 1) & 0xf];
}

View File

@@ -0,0 +1,349 @@
INTERFACE:
#include "types.h"
#include <cxx/bitfield>
#include <cxx/cxx_int>
/// Difference between two capability indexes
typedef cxx::int_type_order<Mword, struct Cap_diff_t, Order> Cap_diff;
/// A capability index
typedef cxx::int_type_full<Mword, struct Cap_index_t, Cap_diff, Order> Cap_index;
/// IA32 I/O port numbers
typedef cxx::int_type_order<unsigned long, struct Port_number_t, Order> Port_number;
/**
* An L4 flexpage.
*
* A flexpage represents a naturally aligned area of mappable space,
* such as memory, I/O-ports, and capabilities (kernel objects).
* There is also a representation for describing a flexpage that represents
* the whole of all these address spaces. The size of a flexpage is given
* as a power of two.
*
*
* The internal representation is a single machine word with the following
* layout:
* \verbatim
* +- bitsize-12 +- 11-6 -+ 5-4 -+-- 3-0 -+
* | page number | order | type | rights |
* +-------------+--------+------+--------+
* \endverbatim
*
* - The rights bits (0-3) denote the access rights to an object, see
* L4_fpage::Rights.
* - The \a type of a flexpage is denotes the address space that is
* referenced by that flexpage (see L4_fpage::Type).
* - The order is the exponent for the size calculation (size = 2^order).
* - The page number denotes the page address within the address space
* denoted by \a type. For example when \a type is #Memory, the \a page
* \a number must contain the most significant bits of a virtual address
* that must be aligned to \a order bits. In the case that \a type
* equals either #Io or #Obj, the \a page \a number contains all bits of
* the I/O-port number or the capability index, respectively (note, the
* values must also be aligned according to the value of \a order).
*
*/
class L4_fpage
{
public:
/**
* Data type to represent the binary representation of a flexpage.
*/
typedef Mword Raw;
/**
* Address space type of a flexpage.
*/
enum Type
{
Special = 0, ///< Special flexpages, either invalid or all spaces.
Memory, ///< Memory flexpage
Io, ///< I/O-port flexpage
Obj ///< Object flexpage (capabilities)
};
enum { Addr_shift = 12 };
struct Rights
: cxx::int_type_base<unsigned char, Rights>,
cxx::int_bit_ops<Rights>,
cxx::int_null_chk<Rights>
{
Rights() = default;
explicit constexpr Rights(unsigned char v)
: cxx::int_type_base<unsigned char, Rights>(v) {}
/// Explicit conversion from the Value_enum type
explicit constexpr Rights(Value_enum v)
: cxx::int_type_base<unsigned char, Rights>(v) {}
/// Explicit conversion to the Value_enum type
explicit constexpr operator Value_enum () const
{ return static_cast<Value_enum>(_v); }
constexpr bool empty() const { return _v == 0; }
constexpr Rights apply(Rights r) const { return *this & r; }
/// Memory flexpage is user accessible
static constexpr Rights U() { return Rights(8); }
/// Memory flexpage is readable
static constexpr Rights R() { return Rights(4); }
/// Memory flexpage is writable
static constexpr Rights W() { return Rights(2); }
/// Memory flexpage is executable (often equal to #R)
static constexpr Rights X() { return Rights(1); }
static constexpr Rights UR() { return U() | R(); }
static constexpr Rights URX() { return U() | R() | X(); }
static constexpr Rights URWX() { return U() | R() | W() | X(); }
static constexpr Rights URW() { return U() | R() | W(); }
/// Memory flexpage is readable and executable
static constexpr Rights RX() { return R() | X(); }
/// Memory flexpage is readable, writeable, and executable
static constexpr Rights RWX() { return R() | W() | X(); }
/// Memory flexpage is readable and writable
static constexpr Rights RW() { return R() | W(); }
///< Memory flexpage is writable and executable
static constexpr Rights WX() { return W() | X(); }
/// Object flexpage: delete rights
static constexpr Rights CD() { return Rights(0x8); }
/// Object flexpage: read rights (w/o this the mapping is not present)
static constexpr Rights CR() { return Rights(0x4); }
/** Object flexpage: strong semantics (object specific, i.e. not having
* this right on an IPC gate demotes all capabilities transferred via this
* IPC gate to also suffer this right. */
static constexpr Rights CS() { return Rights(0x2); }
/// Object flexpage: write rights (purely object specific)
static constexpr Rights CW() { return Rights(0x1); }
/// Object flexpage: combine #CR and #CW
static constexpr Rights CRW() { return CR() | CW(); }
/// Object flexpage: combine #CR and #CS
static constexpr Rights CRS() { return CR() | CS(); }
/// Object flexpage: combine #CR, #CW, and #CS
static constexpr Rights CRWS() { return CRW() | CS(); }
/// Object flexpage: combine #CS and #CW
static constexpr Rights CWS() { return CW() | CS(); }
/// Object flexpage: combine #CS, #CW, and #CD
static constexpr Rights CWSD() { return CW() | CS() | CD(); }
/// Object flexpage: combine #CR, #CW, #CS, and #CD
static constexpr Rights CRWSD() { return CRWS() | CD(); }
/// All rights shall be transferred, independent of the type
static constexpr Rights FULL() { return Rights(0xf); }
};
private:
/**
* Create a flexpage with the given parameters.
*/
constexpr L4_fpage(Type type, Mword address,
unsigned char order, Rights rights)
: _raw( address | _rights_bfm_t::val_dirty(cxx::int_value<Rights>(rights))
| order_bfm_t::val_dirty(order) | type_bfm_t::val_dirty(type))
{}
public:
enum
{
Whole_space = 63 ///< Value to use as \a order for a whole address space.
};
/**
* Create an I/O flexpage.
*
* IO flexpages do not support access rights other than RW or nothing.
* \param port base I/O-port number (0..65535), must be aligned to
* 2^\a order. The value is shifted by #Addr_shift bits to the
* left.
* \param order the order of the I/O flexpage, size is 2^\a order ports.
*/
static constexpr L4_fpage io(Mword port, unsigned char order, Rights rights = Rights(0))
{ return L4_fpage(Io, adr_bfm_t::val_dirty(port), order, rights); }
/**
* Create an object flexpage.
*
* \param idx capability index, note capability indexes are multiples of
* 0x1000. (hence \a idx is not shifted)
* \param order The size of the flexpage is 2^\a order. The value in \a idx
* must be aligned to 2^(\a order + #Addr_shift.
*/
static constexpr L4_fpage obj(Mword idx, unsigned char order, Rights rights = Rights(0))
{ return L4_fpage(Obj, idx & adr_bfm_t::Mask, order, rights); }
/**
* Create a memory flexpage.
*
* \param addr The virtual address. Only the most significant bits are
* considered, bits from 0 to \a order-1 are dropped.
* \param order The size of the flexpage is 2^\a order in bytes.
*/
static constexpr L4_fpage mem(Mword addr, unsigned char order, Rights rights = Rights(0))
{ return L4_fpage(Memory, addr & adr_bfm_t::Mask, order, rights); }
/**
* Create a nil (invalid) flexpage.
*/
static constexpr L4_fpage nil()
{ return L4_fpage(0); }
/**
* Create a special receive flexpage representing
* all available address spaces at once. This is used
* for page-fault and exception IPC.
*/
static constexpr L4_fpage all_spaces(Rights rights = Rights(0))
{ return L4_fpage(Special, 0, Whole_space, rights); }
/**
* Create a flexpage from the raw value.
*/
explicit constexpr L4_fpage(Raw raw) : _raw(raw) {}
/**
* The robust type for carrying virtual memory addresses.
*/
typedef Virt_addr Mem_addr;
/**
* Get the virtual address of a memory flexpage.
*
* \pre type() must return #Memory to return a valid value.
* \return The virtual memory base address of the flexpage.
*/
constexpr Virt_addr mem_address() const
{ return Virt_addr(adr_bfm_t::get_unshifted(_raw)); }
/**
* Get the capability address of an object flexpage.
*
* \pre type() must return #Obj to return a valid value.
* \return The capability value (index) of this flexpage.
* This value is not shifted, so it is a multiple of 0x1000.
* See obj_index() for reference.
*/
constexpr Mword obj_address() const { return adr_bfm_t::get_unshifted(_raw); }
/**
* Get the I/O-port number of an I/O flexpage.
* \pre type() must return #Io to return a valid value.
* \return The I/O-port index of this flexpage.
*/
constexpr Port_number io_address() const { return Port_number{adr()}; }
/**
* Get the capability index of an object flexpage.
*
* \pre type() must return #Obj to return a valid value.
* \return The index into the capability table provided by this flexpage.
* This value is shifted #Addr_shift to be a real index
* (opposed to obj_address()).
*/
constexpr Cap_index obj_index() const { return Cap_index{adr()}; }
/**
* Test for memory flexpage (if type() is #Memory).
* \return true if type() is #Memory.
*/
constexpr bool is_mempage() const { return type() == Memory; }
/**
* Test for I/O flexpage (if type() is #Io).
* \return true if type() is #Io.
*/
constexpr bool is_iopage() const { return type() == Io; }
/**
* Test for object flexpage (if type() is #Obj).
* \return true if type() is #Obj.
*/
constexpr bool is_objpage() const { return type() == Obj; }
/**
* Is the flexpage the whole address space?
* @return not zero, if the flexpage covers the
* whole address space.
*/
constexpr Mword is_all_spaces() const
{
Mword mask = Mword{type_bfm_t::Mask} | Mword{order_bfm_t::Mask};
return (_raw & mask) == order_bfm_t::val(Whole_space);
}
/**
* Is the flexpage valid?
* \return not zero if the flexpage
* contains a value other than 0.
*/
constexpr Mword is_valid() const { return _raw; }
/**
* Get the binary representation of the flexpage.
* \return this flexpage in binary representation.
*/
constexpr Raw raw() const { return _raw; }
private:
Raw _raw;
/** \name Rights of the flexpage */
CXX_BITFIELD_MEMBER( 0, 3, _rights, _raw);
public:
/** \name Type of the flexpage */
CXX_BITFIELD_MEMBER( 4, 5, type, _raw);
/** \name Size (as power of 2) of the flexpage */
CXX_BITFIELD_MEMBER( 6, 11, order, _raw);
private:
/** \name Address encoded in the flexpage */
CXX_BITFIELD_MEMBER(12, MWORD_BITS-1, adr, _raw);
public:
constexpr Rights rights() const { return Rights(_rights()); }
/**
* Rights bits for flexpages.
*
* The particular semantics of the rights bits in a flexpage differ depending
* on the type of the flexpage. For memory there are #R, #W, and #X rights.
* For I/O-ports there must be #R and #W, to get access. For object
* (capabilities) there are #CD, #CR, #CS, and #CW rights on the object and
* additional rights in the map control value of the map operation (see
* L4_fpage::Obj_map_ctl).
*/
/**
* Mask the flexpage with the given rights.
*
* \param r Rights mask. All rights missing in the mask are removed.
* The semantics depend on the type (type()) of the flexpage.
*/
void mask_rights(Rights r) { _raw &= (Mword{cxx::int_value<Rights>(r)} | ~_rights_bfm_t::Mask); }
};

View File

@@ -0,0 +1,477 @@
INTERFACE:
#include "types.h"
#include "l4_fpage.h"
#include <cxx/bitfield>
/**
* The first word of a message item, either a send item or a receive buffer.
*
* #L4_msg_item is the first word of a typed message item in system calls (incl.
* IPC). The #L4_msg_item may be followed by additional words that are part of
* the typed message item. The number of following words and their
* interpretation depend on the contents of the #L4_msg_item.
*
* *Void item:* If all bits of the first word of a typed message item are zero,
* then it is a void item (see is_void()).
*
* *Non-void item:* The first word of a generic non-void typed message item has
* the following binary layout:
*
* MSB 4 3 2 0 bits
* ┌────────────────────────────┬───┬────────┐
* │ │ t │ │
* └────────────────────────────┴───┴────────┘
*
* Bit 3 (`t`) is the type bit. If `t` is set, the item is a map item.
* \note Fiasco.OC currently has no support for other types than map items.
*
* There are three sub-types of typed message items with variations in the
* layout of the first word:
*
* 1. Typed message items set by the sender in its message registers.
* 2. Typed message items set by the receiver in its buffer registers.
* 3. Typed message items set by the kernel in the receivers message registers.
*
* They are abbreviated by *send item*, *buffer item*, and *return item*,
* respectively.
*
* The first word of the first two can be interpreted by the sub-classes
* #L4_snd_item and #L4_buf_item. The latter can be written by the independent
* class #L4_return_item_writer.
*
* A typed message item in the message registers (case 1 and case 3) always
* consists of two words (even if it is a void item). The size of a typed
* message item in the buffer registers (case 2) is determined by its first
* word. A void item in the buffer registers consists of a single word.
*/
class L4_msg_item
{
public:
enum Type
{
Map = 8,
};
/**
* Create a message item from its binary representation.
* \param raw is the binary representation of the message item.
*/
explicit constexpr L4_msg_item(Mword raw) : _raw(raw) {}
/**
* Is the item a \a void item?
* \return true if the item is \a void, false if it is valid.
*/
bool constexpr is_void() const { return _raw == 0; }
/**
* Get the binary representation of the item.
* \return the binary representation of this item.
*/
Mword constexpr raw() const { return _raw; }
protected:
/**
* The binary representation.
*/
Mword _raw;
public:
/** \name Type of the message item
*
* Currently the type must indicate a map item (#L4_msg_item::Map).
* \see L4_msg_item::Type
*/
CXX_BITFIELD_MEMBER_UNSHIFTED( 3, 3, type, _raw);
};
/**
* This class represents the first word of a typed message item set by the
* sender in its message registers (send item).
*
* The second word of a non-void send item is a flexpage (not represented by
* this class). The type of the flexpage determines the interpretation of the
* `attr` bits (see below).
*
* The getters of this sub-class are defined only if this is a non-void item
* (see is_void()).
*
* If not void, the layout is defined as follows:
*
* MSB 12 11 8 7 4 3 2 1 0 bits
* ┌──────────┬─────┬──────┬───┬─────┬───────┬──────────┐
* │ hot_spot │ SBZ │ attr │ 1 │ SBZ │ grant │ compound │
* └──────────┴─────┴──────┴───┴─────┴───────┴──────────┘
*
* `SBZ` means “should be zero”.
*
* Bit 0 (`compound`): If this bit is set on a send item, the next send item
* with the same flexpage type shall be mapped using the same buffer item as
* this send item. The caller should properly use the `hot_spot` to avoid
* overlapping mappings. Useful to implement scatter-gather behaviour.
*
* Bit 1 (`grant`): On a send map item, a set `grant` bit flags a grant
* operation. This means, the sender delegates access to the receiver and
* removes the own rights (basically a move operation).
*
* Bits 7..4 (`attr`): These bits contain extra attributes that influence the
* mapping itself. The concrete meaning is determined by the type of the
* flexpage in the second word of the send item. For memory mappings, these bits
* contain cacheability information (see L4_snd_item::Memory_type). For object
* mappings these bits contain extra rights on the object (see #Obj_attribs).
*
* Bits MSB­..12 (`hot_spot`): These bits are called *hot spot* and are used to
* disambiguate the cases where the send flexpage and the receive flexpage have
* different sizes.
*/
class L4_snd_item : public L4_msg_item
{
private:
enum
{
Addr_shift = 12, ///< number of bits an index must be shifted, or
/// an address must be aligned to, in the control word
};
public:
/**
* Create a from binary representation.
*/
explicit constexpr L4_snd_item(Mword raw) : L4_msg_item(raw) {}
/**
* Additional rights for object send items.
*/
enum Obj_attribs
{
C_weak_ref = 0x10, ///< Map a weak reference (not counted in the kernel)
C_ref = 0x00, ///< Map a normal reference (counted, if not derived
/// from a weak reference)
C_obj_right_1 = 0x20, ///< Some kernel internal, object-type specific right
C_obj_right_2 = 0x40, ///< Some kernel internal, object-type specific right
C_obj_right_3 = 0x80, ///< Some kernel internal, object-type specific right
C_obj_specific_rights = C_obj_right_1 | C_obj_right_2 | C_obj_right_3,
C_ctl_rights = C_obj_specific_rights | C_weak_ref,
};
/**
* Additional flags for memory send items.
*
* These flags are to control the caching attributes of memory mappings.
*/
struct Memory_type
: cxx::int_type_base<unsigned char, Memory_type>,
cxx::int_bit_ops<Memory_type>
{
Memory_type() = default;
constexpr explicit Memory_type(unsigned char v)
: cxx::int_type_base<unsigned char, Memory_type>(v) {}
static constexpr Memory_type Set() { return Memory_type(0x10); }
static constexpr Memory_type Normal() { return Memory_type(0x20); }
static constexpr Memory_type Buffered() { return Memory_type(0x40); }
static constexpr Memory_type Uncached() { return Memory_type(0x00); }
};
Memory_type constexpr mem_type() const { return Memory_type(attr() & 0x70); }
/**
* Use the same buffer item for the next send item.
* \return true if the next send item shall be handled with the
* same buffer item as this one.
*/
bool constexpr compound() const { return _raw & 1; }
/**
* Is the map item actually a grant item?
* \return true if the sender does a grant operation.
*/
bool constexpr is_grant() const { return _raw & 2; }
/**
* Create a map item.
* \param base the hot spot address of the map item.
*/
static constexpr L4_snd_item map(Mword base) { return L4_snd_item(base | Map); }
/** \name Attribute bits of the send item
*
* The semantics of the extra attributes depends on
* the type of the second word, the #L4_fpage, of the
* complete send item.
* \see L4_snd_item::Memory_type, #Obj_attribs
*/
CXX_BITFIELD_MEMBER_UNSHIFTED( 4, 7, attr, _raw);
/** \name the hot-spot address encoded in the send item
* \note Useful for memory send items. */
CXX_BITFIELD_MEMBER_UNSHIFTED(Addr_shift, sizeof(_raw)*8-1, address, _raw);
/** \name the hot-spot index encoded in the send item
* \note In particular useful for IO-port send items. */
CXX_BITFIELD_MEMBER (Addr_shift, sizeof(_raw)*8-1, index, _raw);
};
/**
* This class represents the first word of a message item in the buffer
* registers of the UTCB (buffer item).
*
* The getters of this sub-class are defined only if this is a non-void item
* (see is_void()).
*
* If not void, the general layout is defined as follows:
*
* MSB 4 3 2 1 0 bits
* ┌──────────────────────────┬───┬────────┬───────┬─────┐
* │ │ 1 │ rcv_id │ small │ fwd │
* └──────────────────────────┴───┴────────┴───────┴─────┘
*
* The `small` and `fwd` bits determine the details of the layout of the whole
* message item.
*
* If `small` is unset, then also `rcv_id` must be unset, and the most
* significant bits should be zero:
*
* ┌──────────────────────────┬───┬────────┬───────┬─────┐
* │ SBZ (should be zero) │ 1 │ 0 │ 0 │ fwd │
* └──────────────────────────┴───┴────────┴───────┴─────┘
*
* If `small` is set, the most significant bits are layouted as follows:
*
* MSB 12 11 4 3 2 1 0 bits
* ┌─────────────┬────────────┬───┬────────┬───────┬─────┐
* │ rcv cap idx │ SBZ │ 1 │ rcv_id │ 1 │ fwd │
* └─────────────┴────────────┴───┴────────┴───────┴─────┘
*
* At most one of `rcv_id` and `fwd` may be set.
*
* This class only represents the first word of a buffer item. However, it
* determines the number and meaning of the words in the whole item. They are
* determined by the `small` and `fwd` bits:
*
* rcv_id small fwd
* ─┬─────┬─────┬─────┐┌───────────────────┐
* │ 0 │ 0 │ 0 ││ rcv flexpage │
* ─┴─────┴─────┴─────┘└───────────────────┘ 12 11 0
* ─┬─────┬─────┬─────┐┌───────────────────┐┌─────────────┬─────┐
* │ 0 │ 0 │ 1 ││ rcv flexpage ││ fwd cap idx │ SBZ │
* ─┴─────┴─────┴─────┘└───────────────────┘└─────────────┴─────┘
* ─┬─────┬─────┬─────┐
* │ 0/1 │ 1 │ 0 │
* ─┴─────┴─────┴─────┘ 12 11 0
* ─┬─────┬─────┬─────┐┌─────────────┬─────┐
* │ 0 │ 1 │ 1 ││ fwd cap idx │ SBZ │
* ─┴─────┴─────┴─────┘└─────────────┴─────┘
*
* The meaning of the bits in detail:
*
* - Bit 0 (`fwd`): If `fwd` is unset, the task of the receiving thread is
* implicitly the destination task for any received capabilites. If the `fwd`
* bit is set, the received capabilities are forwarded to the destination task
* explicitly selected via the capability index in the second or third word of
* the buffer item (`fwd cap idx`).
*
* - Bit 1 (`small`): A buffer item needs to specify a *receive window*. The
* receive window determines which kind of capabilities (object, memory, I/O
* ports) may be received where in the respective space. If `small` is 0, the
* receive window is specified in the second word of the item via a flexpage
* (`rcv flexpage`). If `small` is 1, the receive window consists of a single
* capability index in the object space and the capability index is specified
* in the most significant bits of the first word starting at bit 12
* (`rcv cap idx`).
*
* - Bit 2 (`rcv_id`): This bit may be set only if `small` is set and `fwd` is
* unset. A set `rcv_id` bit denotes that the receiver wants to avoid a full
* mapping. Instead, if all preconditions are met, the receiver will get
* either the sent flexpage word or the label of an IPC gate (combined with
* some permissions that would have been mapped) in its message registers. If
* the `rcv_id` bit is set:
*
* - If the sending and the receiving thread are in the same task, then the
* flexpage word specified by the sender is received and nothing is mapped.
* - Otherwise, if an IPC gate capability was sent and the receiving thread is
* in the same task as the thread that is attached to the IPC gate, then the
* bitwise OR (`|`) of the label of the IPC gate and some permissions that
* would have been mapped is received.
* - Otherwise the behavior is the same as if the `rcv_id` bit was not set.
*/
class L4_buf_item : public L4_msg_item
{
public:
explicit constexpr L4_buf_item(Mword raw) : L4_msg_item(raw) {}
/**
* Is the destination task specified explicitly in a separate word?
*/
bool constexpr forward_mappings() const { return _raw & 1; }
/**
* Is the buffer item a small object buffer?
* \return true if the buffer is a single-word single-object
* receive buffer, false else.
*/
bool constexpr is_small_obj() const { return _raw & 2; }
/**
* Receiver tries to receive an IPC gate label or the sent flexpage word?
* \pre is_small_obj() && !has_dst_task()
*/
bool constexpr is_rcv_id() const { return _raw & 4; }
/**
* Get the #L4_fpage that represents the small buffer item.
* The rights are undefined and shall not be used.
* \pre is_small_obj() == true
* \return the flexpage (#L4_fpage) representing the single
* object slot with index `rcv cap idx`.
*/
L4_fpage constexpr get_small_buf() const
{
assert(is_small_obj());
return L4_fpage::obj(_raw, 0, L4_fpage::Rights(0));
}
/**
* Create a map item.
*/
static constexpr L4_buf_item map() { return L4_buf_item(Map); }
};
/**
* Helper class for writing a typed message item in the message registers of the
* receiver (return item).
*
* \note This class can only write non-void items.
*
* A return item always consists of two words. The general layout is defined as
* follows:
*
* MSB 12 11 6 5 4 3 2 1 0 bits
* ┌──────────┬───────┬──────┬───┬──────────┬───┐┌─────────────────┐
* │ hot_spot │ order │ type │ 1 │ rcv_type │ c ││ payload │
* └──────────┴───────┴──────┴───┴──────────┴───┘└─────────────────┘
* └──────────┘ └───┘ └───┘ from send items first word
* └──────────────┘ from send items flexpage
* └──────────┘ initially zero
*
* As indicated above, the `hot_spot`, `1` (see L4_msg_item::Map), and `c`
* (`compound`) are copied from the senders send items first word (see
* #L4_snd_item), and `order` and `type` are copied from the senders send
* items flexpage. The `rcv_type` and `payload` are determined by what is
* actually transferred, which is also affected by the `rcv_id` bit in the
* receivers buffer item (see #L4_buf_item). The `rcv_type` determines the
* content and layout of the payload.
*
* There are four cases for `rcv_type`:
*
* #Rcv_map_something: Used if at least one mapping was actually transferred for
* the corresponding send item. The payload is left unset:
*
* ┌──────────┬───────┬──────┬───┬──────────┬───┐┌─────────────────┐
* │ hot_spot │ order │ type │ 1 │ 00 │ c ││ unset │
* └──────────┴───────┴──────┴───┴──────────┴───┘└─────────────────┘
*
* #Rcv_map_nothing: Used if transfer of mappings was attempted, but actually
* nothing was transferred, because nothing was mapped on the senders side for
* the corresponding send item. The payload is left unset:
*
* ┌──────────┬───────┬──────┬───┬──────────┬───┐┌─────────────────┐
* │ hot_spot │ order │ type │ 1 │ 01 │ c ││ unset │
* └──────────┴───────┴──────┴───┴──────────┴───┘└─────────────────┘
*
* #Rcv_id: Used if the buffer items `rcv_id` bit was set and the conditions
* for transferring an IPC gate label were fulfilled. In that case, no mapping
* is done for this item and the payload consists of the bitwise OR (`|`) of the
* IPC gate label (`obj_id`; see Kobject_common::obj_id()) and the write and
* special permissions (see Obj::Capability::rights()) that would have been
* mapped (`rights`):
*
* 2 1 0
* ┌──────────┬───────┬──────┬───┬──────────┬───┐┌────────┬────────┐
* │ hot_spot │ order │ type │ 1 │ 10 │ c ││ obj_id │ rights │
* └──────────┴───────┴──────┴───┴──────────┴───┘└────────┴────────┘
*
* #Rcv_flexpage: Used if the buffer items `rcv_id` bit was set and the
* conditions for transferring the senders flexpage word were fulfilled. In
* that case, the payload is a copy of the senders flexpage word:
*
* ┌──────────┬───────┬──────┬───┬──────────┬───┐┌─────────────────┐
* │ hot_spot │ order │ type │ 1 │ 11 │ c ││ send flexpage │
* └──────────┴───────┴──────┴───┴──────────┴───┘└─────────────────┘
*/
class L4_return_item_writer
{
/** Pointer to the first word of the written return item. */
Mword *_words;
public:
/**
* Create a writer and immediately write the information from the
* corresponding send item.
*
* The `rcv_type` is initially set to #Rcv_map_something.
*
* \param regs Pointer to the first of two words of the return item to be
* written.
* \param snd First word of the corresponding send item.
* \param fp Second word of the corresponding send item.
*/
explicit constexpr L4_return_item_writer(Mword words[], L4_snd_item snd, L4_fpage fp)
: _words(words)
{ _words[0] = (snd.raw() & ~0x0ff6) | (fp.raw() & 0x0ff0); }
enum Rcv_type
{
Rcv_map_something = 0, ///< Mapping done, something mapped.
Rcv_map_nothing = 2, ///< Mapping done, nothing mapped.
Rcv_id = 4, ///< IPC gate label and permissions are transferred.
Rcv_flexpage = 6, ///< A flexpage word is transferred.
Rcv_type_mask = 6
};
/**
* Set the `rcv_type` to #Rcv_map_nothing.
*
* \pre No `set_…` member must have been called on this instance before.
*/
void constexpr set_rcv_type_map_nothing()
{
_words[0] |= L4_return_item_writer::Rcv_map_nothing;
}
/**
* Set the `rcv_type` to #Rcv_id and set the second word to the
* disjunction of the provided object id and permissions.
*
* \param id IPC gate label (see Kobject_common::obj_id()) of the sent
* IPC gate.
* \param rights Write and special permissions of the sent capability (see
* Obj::Capability::rights()).
*
* \pre No `set_…` member must have been called on this instance before.
*/
void constexpr set_rcv_type_id(Mword id, Mword rights)
{
_words[0] |= L4_return_item_writer::Rcv_id;
_words[1] = id | rights;
}
/**
* Set the `rcv_type` to #Rcv_flexpage and set the second word to the provided
* flexpage.
*
* \param sfp Flexpage of the corresponding send item.
*
* \pre No `set_…` member must have been called on this instance before.
*/
void constexpr set_rcv_type_flexpage(L4_fpage sfp)
{
_words[0] |= L4_return_item_writer::Rcv_flexpage;
_words[1] = sfp.raw();
}
};

View File

@@ -0,0 +1,43 @@
IMPLEMENTATION [debug]:
#include <cstdio>
#include "simpleio.h"
PUBLIC void L4_timeout::print() const
{
printf("m=%lu e=%lu", man(), exp());
}
PUBLIC void L4_timeout_pair::print() const
{
printf("snd: ");
snd.print();
printf(" rcv: ");
rcv.print();
}
PUBLIC
void
Utcb::print(char const *clreol_lf = "\n") const
{
printf("Values:%s", clreol_lf);
for (unsigned i = 0; i < Max_words; ++i)
printf("%2u:%16lx%s", i, values[i], !((i+1) % 4) ? clreol_lf : " ");
if (Max_words % 4)
putstr(clreol_lf);
printf("Reserved: %16lx%s", utcb_addr, clreol_lf);
printf("Buffers: dsc=%16lx%s", buf_desc.raw(), clreol_lf);
for (unsigned i = 0; i < cxx::size(buffers); ++i)
printf("%2u:%16lx%s", i, buffers[i], !((i+1) % 4) ? clreol_lf : " ");
if (cxx::size(buffers) % 4)
putstr(clreol_lf);
printf("Free marker: " L4_MWORD_FMT "%s", free_marker, clreol_lf);
printf("Error: %16lx%s", error.raw(), clreol_lf);
printf("User values: %16lx %16lx %16lx%s", user[0], user[1], user[2], clreol_lf);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,30 @@
/*
* MIPS Kernel-Info Page
*/
INTERFACE [mips]:
#include "types.h"
EXTENSION class Kip
{
public:
struct Platform_info
{
char name[16];
Unsigned32 is_mp;
Unsigned32 cpuid;
Unsigned32 pad[2];
};
/* 0xF0 0x1E0 */
Platform_info platform_info;
};
//---------------------------------------------------------------------------
IMPLEMENTATION [mips && debug]:
IMPLEMENT inline
void
Kip::debug_print_syscalls() const
{}

View File

@@ -0,0 +1,7 @@
INTERFACE [mips]:
EXTENSION class L4_exception_ipc
{
public:
enum { Msg_size = 41 };
};

View File

@@ -0,0 +1,29 @@
/*
* PPC32 Kernel-Info Page
*/
INTERFACE [ppc32]:
#include "types.h"
EXTENSION class Kip
{
public:
struct Platform_info
{
char name[16];
Unsigned32 is_mp;
};
/* 0xF0 */
Platform_info platform_info;
Unsigned32 __reserved[3];
};
//---------------------------------------------------------------------------
IMPLEMENTATION [ppc32 && debug]:
IMPLEMENT inline
void
Kip::debug_print_syscalls() const
{}

View File

@@ -0,0 +1,68 @@
/*
* RISC-V Kernel-Info Page
*/
INTERFACE [riscv]:
#include "config.h"
#include "types.h"
EXTENSION class Kip
{
public:
struct Platform_info
{
char name[16];
Unsigned32 is_mp;
struct
{
// Supported RISC-V ISA extensions
Unsigned32 isa_ext[7];
// Base frequency of the system timer / real-time counter (TIME csr)
Unsigned32 timebase_frequency;
// Number of populated entries in the following Hart ID list
Unsigned32 hart_num;
// List of harts present in the system, which is used to start secondary
// harts and to find the interrupt target context corresponding to a
// hart.
Unsigned32 hart_ids[16];
// Base address of the Platform Interrupt Controller (PLIC)
Mword plic_addr;
// Number of interrupt pins supported by the PLIC
Unsigned32 plic_nr_pins;
// Mapping of harts to their respective PLIC interrupt target context
Unsigned32 plic_hart_irq_targets[16];
static_assert(Config::Max_num_cpus <=
(sizeof(plic_hart_irq_targets) / sizeof(Unsigned32)),
"Maximum number of CPUs exceeds the PLIC target context map size.");
} arch;
};
/* 0xF0 0x1E0 */
Platform_info platform_info;
Unsigned8 __pad[(16 - (sizeof(Platform_info) % 16)) % 16];
};
//---------------------------------------------------------------------------
IMPLEMENTATION [riscv]:
PUBLIC inline
int
Kip::hart_idx(Mword hart_id)
{
for (unsigned i = 0; i < platform_info.arch.hart_num; i++)
{
if (platform_info.arch.hart_ids[i] == hart_id)
return i;
}
return -1;
}
//---------------------------------------------------------------------------
IMPLEMENTATION [riscv && debug]:
IMPLEMENT inline
void
Kip::debug_print_syscalls() const
{}

View File

@@ -0,0 +1,7 @@
INTERFACE [riscv]:
EXTENSION class L4_exception_ipc
{
public:
enum { Msg_size = 37 };
};

View File

@@ -0,0 +1,29 @@
/*
* SPARC Kernel-Info Page
*/
INTERFACE [sparc]:
#include "types.h"
EXTENSION class Kip
{
public:
struct Platform_info
{
char name[16];
Unsigned32 is_mp;
};
/* 0xF0 */
Platform_info platform_info;
Unsigned32 __reserved[3];
};
//---------------------------------------------------------------------------
IMPLEMENTATION [sparc && debug]:
IMPLEMENT inline
void
Kip::debug_print_syscalls() const
{}

View File

@@ -0,0 +1,179 @@
INTERFACE [svm]:
#include "l4_types.h"
#include <cxx/bitfield>
// TODO: Make this sharable with user-land (see uarts)
struct Vmcb_control_area
{
struct Clean_bits
{
Unsigned64 raw;
CXX_BITFIELD_MEMBER( 0, 0, i, raw);
CXX_BITFIELD_MEMBER( 1, 1, iopm, raw);
CXX_BITFIELD_MEMBER( 2, 2, asid, raw);
CXX_BITFIELD_MEMBER( 3, 3, tpr, raw);
CXX_BITFIELD_MEMBER( 4, 4, np, raw);
CXX_BITFIELD_MEMBER( 5, 5, crx, raw);
CXX_BITFIELD_MEMBER( 6, 6, drx, raw);
CXX_BITFIELD_MEMBER( 7, 7, dt, raw);
CXX_BITFIELD_MEMBER( 8, 8, seg, raw);
CXX_BITFIELD_MEMBER( 9, 9, cr2, raw);
CXX_BITFIELD_MEMBER(10, 10, lbr, raw);
CXX_BITFIELD_MEMBER(11, 11, avic, raw);
};
Unsigned16 intercept_rd_crX;
Unsigned16 intercept_wr_crX;
Unsigned16 intercept_rd_drX;
Unsigned16 intercept_wr_drX;
Unsigned32 intercept_exceptions;
Unsigned32 intercept_instruction0;
Unsigned32 intercept_instruction1;
Unsigned8 _reserved0[40];
Unsigned16 pause_filter_threshold;
Unsigned16 pause_filter_count;
Unsigned64 iopm_base_pa;
Unsigned64 msrpm_base_pa;
Unsigned64 tsc_offset;
Unsigned32 guest_asid;
Unsigned32 tlb_ctl;
Unsigned16 int_tpr_irq;
Unsigned16 int_ctl;
Unsigned8 int_vector;
Unsigned8 _reserved10[3];
Unsigned8 interrupt_shadow;
Unsigned8 _reserved11[7];
Unsigned64 exitcode;
Unsigned64 exitinfo1;
Unsigned64 exitinfo2;
Unsigned64 exitintinfo;
Unsigned64 np_enable;
Unsigned8 _reserved1[16];
Unsigned64 eventinj;
Unsigned64 n_cr3;
Unsigned64 lbr_virtualization_enable;
Clean_bits clean_bits;
Unsigned64 n_rip;
Unsigned8 _reserved2[816];
} __attribute__((packed));
struct Vmcb_state_save_area
{
Unsigned16 es_sel;
Unsigned16 es_attrib;
Unsigned32 es_limit;
Unsigned64 es_base;
Unsigned16 cs_sel;
Unsigned16 cs_attrib;
Unsigned32 cs_limit;
Unsigned64 cs_base;
Unsigned16 ss_sel;
Unsigned16 ss_attrib;
Unsigned32 ss_limit;
Unsigned64 ss_base;
Unsigned16 ds_sel;
Unsigned16 ds_attrib;
Unsigned32 ds_limit;
Unsigned64 ds_base;
Unsigned16 fs_sel;
Unsigned16 fs_attrib;
Unsigned32 fs_limit;
Unsigned64 fs_base;
Unsigned16 gs_sel;
Unsigned16 gs_attrib;
Unsigned32 gs_limit;
Unsigned64 gs_base;
Unsigned16 gdtr_sel;
Unsigned16 gdtr_attrib;
Unsigned32 gdtr_limit;
Unsigned64 gdtr_base;
Unsigned16 ldtr_sel;
Unsigned16 ldtr_attrib;
Unsigned32 ldtr_limit;
Unsigned64 ldtr_base;
Unsigned16 idtr_sel;
Unsigned16 idtr_attrib;
Unsigned32 idtr_limit;
Unsigned64 idtr_base;
Unsigned16 tr_sel;
Unsigned16 tr_attrib;
Unsigned32 tr_limit;
Unsigned64 tr_base;
Unsigned8 _reserved0[43];
Unsigned8 cpl;
Unsigned32 _reserved1;
Unsigned64 efer;
Unsigned8 _reserved2[112];
Unsigned64 cr4;
Unsigned64 cr3;
Unsigned64 cr0;
Unsigned64 dr7;
Unsigned64 dr6;
Unsigned64 rflags;
Unsigned64 rip;
Unsigned8 _reserved3[88];
Unsigned64 rsp;
Unsigned8 _reserved4[24];
Unsigned64 rax;
Unsigned64 star;
Unsigned64 lstar;
Unsigned64 cstar;
Unsigned64 sfmask;
Unsigned64 kernelgsbase;
Unsigned64 sysenter_cs;
Unsigned64 sysenter_esp;
Unsigned64 sysenter_eip;
Unsigned64 cr2;
Unsigned8 _reserved5[32];
Unsigned64 g_pat;
Unsigned64 dbgctl;
Unsigned64 br_from;
Unsigned64 br_to;
Unsigned64 lastexcpfrom;
Unsigned64 last_excpto;
// this field is _NOT_ part of AMDs hardware VMCB specification
// this is a software VMCB field
Unsigned64 xcr0;
Unsigned8 _reserved6[2400];
} __attribute__((packed));
struct Vmcb
{
unsigned np_enabled() const { return control_area.np_enable & 1; }
Vmcb_control_area control_area;
Vmcb_state_save_area state_save_area;
} __attribute__((packed));

View File

@@ -0,0 +1,63 @@
# -*- makefile -*-
# Boot Makefile
# Add future prerequisites somewhere among the list of libraries.
# You really should not have to add anything in the $(LD) line.
boot_img.o: boot_img.x2 boot_img.ren_syms
$(LINK_MESSAGE)
$(VERBOSE)$(OBJCOPY) --redefine-syms=boot_img.ren_syms $< $@
boot_img.ren_syms: boot_img.x2
$(LINK_MESSAGE)
$(VERBOSE)$(NM) -u $^ | perl -n -e 'if (/^\s*U\s+bootstrap_(.*)$$/) { print "bootstrap_$$1 $$1\n"; }' > $@
boot_img.x1: $(OBJ_BOOT) $(DRIVERS) $(LIBC)
$(LINK_MESSAGE)
$(VERBOSE)$(LD) $(LDFLAGS) $(LD_EMULATION_FLAG) -r -d -s -o $@ \
-T $(srcdir)/boot/amd64/bootstrap.ld -u_boot_start -gc-sections $^
boot_img.x2: boot_img.x1
$(LINK_MESSAGE)
$(VERBOSE)$(OBJCOPY) --prefix-alloc-sections=.bootstrap --prefix-symbols=bootstrap_ -G bootstrap__boot_start $^ $@
INTEL_MICROCODE_BIN ?= $(wildcard intel_microcode.bin)
ifneq ($(INTEL_MICROCODE_BIN),)
INTEL_MICROCODE_IMG = intel_microcode.img.o
intel_microcode.o: intel_microcode.c
$(COMP_MESSAGE)
$(VERBOSE)$(CC) -c -o $@ $<
intel_microcode.img.o: $(INTEL_MICROCODE_BIN) intel_microcode.o
$(COMP_MESSAGE)
$(VERBOSE)$(OBJCOPY) --add-section .intel_microcode=$< --set-section-flags .intel_microcode=a \
intel_microcode.o $@
endif
-include .kernel.amd64.lds.d
# $(1) = fiasco - variable
# $(2) = fiasco.debug - variable
# $(3) = Additional $(OBJ_X), e.g. OBJ_<unittest>
define gen_kernel_rules =
$(2): kernel.amd64.lds boot_img.o $$(CRT0) $$(OBJ_KERNEL) $(3) $$(JDB) $$(KERNEL_EXTRA_LIBS) $$(ABI) $$(JABI) libdrivers.a $$(LIBUART) $$(LIBK) $$(CXXLIB) $$(LIBC) libfonts.a libgluedriverslibc.a $$(INTEL_MICROCODE_IMG)
$$(LINK_MESSAGE)
$$(VERBOSE)$$(LD) $$(LDFLAGS) $$(LD_EMULATION_FLAG) -N -o $$@ \
-T $$< -gc-sections $$(filter-out $$<,$$+) \
$$(KERNEL_UNRES_SYMS)
$$(call ADD_CONFIGFILE,$$@)
$(1): $(2)
$$(LINK_MESSAGE)
$$(VERBOSE)$$(STRIP) -o $$@ $$<
$$(VERBOSE)$$(OBJCOPY) --add-gnu-debuglink=$$< $$@
$$(VERBOSE)chmod 755 $$@
endef
# generate fiasco and fiasco.debug rules
$(eval $(call gen_kernel_rules,$(BOOT),$(KERNEL),$(OBJ_STDWORKLOAD)))
BOOT_CLEAN := boot_img.x1 boot_img.x2 boot_img.ren_syms boot_img.ren_syms kernel.amd64.lds

View File

@@ -0,0 +1,19 @@
/* -*- c -*- */
.globl _boot_start
.p2align 4
_boot_start:
lea _stack,%rsp
push $0 /* no return address */
jmp bootstrap
.p2align 2, 0x90
.long 0x1BADB002 /* magic */
.long 0x00000000 /* feature flags */
.long 0 - 0x1BADB002
.bss
.align 16
.space 4096
_stack:

View File

@@ -0,0 +1,630 @@
#include <cassert>
#include <cstring>
#include <cstdio>
#include "types.h"
#include "boot_cpu.h"
#include "boot_paging.h"
#include "mem_layout.h"
#include "processor.h"
#include "panic.h"
#include "regdefs.h"
enum
{
PML4ESHIFT = 39,
PML4EMASK = 0x1ff,
PDPESHIFT = 30,
PDPEMASK = 0x1ff,
PDESHIFT = 21,
PDEMASK = 0x1ff,
PTESHIFT = 12,
PTEMASK = 0x1ff,
INTEL_PTE_VALID = 0x0000000000000001LL,
INTEL_PTE_WRITE = 0x0000000000000002LL,
INTEL_PTE_USER = 0x0000000000000004LL,
INTEL_PTE_WTHRU = 0x00000008,
INTEL_PTE_NCACHE = 0x00000010,
INTEL_PTE_REF = 0x00000020,
INTEL_PTE_MOD = 0x00000040,
INTEL_PTE_GLOBAL = 0x00000100,
INTEL_PTE_AVAIL = 0x00000e00,
INTEL_PTE_PFN = 0x000ffffffffff000LL,
INTEL_PDE_VALID = 0x0000000000000001LL,
INTEL_PDE_WRITE = 0x0000000000000002LL,
INTEL_PDE_USER = 0x0000000000000004LL,
INTEL_PDE_WTHRU = 0x00000008,
INTEL_PDE_NCACHE = 0x00000010,
INTEL_PDE_REF = 0x00000020,
INTEL_PDE_MOD = 0x00000040,
INTEL_PDE_SUPERPAGE = 0x0000000000000080LL,
INTEL_PDE_GLOBAL = 0x00000100,
INTEL_PDE_AVAIL = 0x00000e00,
INTEL_PDE_PFN = 0x000ffffffffff000LL,
INTEL_PDPE_VALID = 0x0000000000000001LL,
INTEL_PDPE_WRITE = 0x0000000000000002LL,
INTEL_PDPE_USER = 0x0000000000000004LL,
INTEL_PDPE_PFN = 0x000ffffffffff000LL,
INTEL_PML4E_VALID = 0x0000000000000001LL,
INTEL_PML4E_WRITE = 0x0000000000000002LL,
INTEL_PML4E_USER = 0x0000000000000004LL,
INTEL_PML4E_PFN = 0x000ffffffffff000LL,
CPUF_EXT_PCID = 1 << 17,
BASE_TSS = 0x08,
KERNEL_DS = 0x18,
KERNEL_CS_64 = 0x20, // XXX
DBF_TSS = 0x28, // XXX check this value
ACC_TSS = 0x09,
ACC_TSS_BUSY = 0x02,
ACC_CODE_R = 0x1a,
ACC_DATA_W = 0x12,
ACC_PL_K = 0x00,
ACC_P = 0x80,
SZ_32 = 0x4,
SZ_16 = 0x0,
SZ_G = 0x8,
SZ_CODE_64 = 0x2, // XXX 64 Bit Code Segment
GDTSZ = (0x30/8), // XXX check this value
IDTSZ = 256,
};
struct pseudo_descriptor
{
Unsigned16 pad;
Unsigned16 limit;
Unsigned64 linear_base;
} __attribute__((packed));
struct x86_desc
{
Unsigned16 limit_low;
Unsigned16 base_low;
Unsigned8 base_med;
Unsigned8 access;
Unsigned8 limit_high:4;
Unsigned8 granularity:4;
Unsigned8 base_high;
} __attribute__((packed));
struct idt_desc
{
Unsigned16 offset_low0;
Unsigned16 selector;
Unsigned8 zero_and_ist;
Unsigned8 access;
Unsigned16 offset_low1;
Unsigned32 offset_high;
Unsigned32 ignored;
} __attribute__((packed));
struct x86_tss
{
Unsigned32 ign0;
Unsigned64 rsp0;
Unsigned64 rsp1;
Unsigned64 rsp2;
Unsigned32 ign1;
Unsigned32 ign2;
Unsigned64 ist1;
Unsigned64 ist2;
Unsigned64 ist3;
Unsigned64 ist4;
Unsigned64 ist5;
Unsigned64 ist6;
Unsigned64 ist7;
Unsigned32 ign3;
Unsigned32 ign4;
Unsigned16 ign5;
Unsigned16 io_bit_map_offset;
} __attribute__((packed));
struct idt_init_entry
{
Unsigned64 entrypoint;
Unsigned16 vector;
Unsigned16 type;
} __attribute__((packed));
struct trap_state
{
Unsigned64 rax, rbx, rcx, rdx;
Unsigned64 rdi, rsi, rbp, cr2;
Unsigned64 r8, r9, r10, r11;
Unsigned64 r12, r13, r14, r15;
Unsigned64 trapno, err;
Unsigned64 rip, cs, rflags, rsp, ss;
};
static Unsigned32 cpu_feature_flags;
static Unsigned32 cpu_ext_feature_flags;
static Address base_pml4_pa;
static struct x86_tss base_tss;
static struct x86_desc base_gdt[GDTSZ];
static struct idt_desc base_idt[IDTSZ];
static char dbf_stack[2048];
static inline Unsigned64* find_pml4e(Address pml4_pa, Address la)
{ return &reinterpret_cast<Unsigned64*>(pml4_pa)[(la >> PML4ESHIFT) & PML4EMASK]; }
static inline Unsigned64* find_pdpe(Address pdp_pa, Address la)
{ return &reinterpret_cast<Unsigned64*>(pdp_pa)[(la >> PDPESHIFT) & PDPEMASK]; }
static inline Unsigned64* find_pde(Address pdir_pa, Address la)
{ return &reinterpret_cast<Unsigned64*>(pdir_pa)[(la >> PDESHIFT) & PDEMASK]; }
static inline Unsigned64* find_pte(Address ptab_pa, Address la)
{ return &reinterpret_cast<Unsigned64*>(ptab_pa)[(la >> PTESHIFT) & PTEMASK]; }
extern inline Unsigned32 get_eflags()
{ Mword efl; asm volatile("pushf \n\t pop %0" : "=r" (efl)); return efl; }
extern inline void set_eflags(Mword efl)
{ asm volatile("push %0 ; popf" : : "r" (efl) : "memory"); }
extern inline void set_ds(Unsigned16 ds)
{ asm volatile("mov %w0,%%ds" : : "r" (ds)); }
extern inline void set_es(Unsigned16 es)
{ asm volatile("mov %w0,%%es" : : "r" (es)); }
extern inline void set_fs(Unsigned16 fs)
{ asm volatile("mov %w0,%%fs" : : "r" (fs)); }
extern inline void set_gs(Unsigned16 gs)
{ asm volatile("mov %w0,%%gs" : : "r" (gs)); }
extern inline void set_ss(Unsigned16 ss)
{ asm volatile("mov %w0,%%ss" : : "r" (ss)); }
extern inline Unsigned16 get_ss()
{ Unsigned16 ss; asm volatile("mov %%ss,%w0" : "=r" (ss)); return ss; }
extern inline void set_idt(pseudo_descriptor *pdesc)
{ asm volatile("lidt %0" : : "m"((pdesc)->limit), "m"(*pdesc)); }
extern inline void set_gdt(pseudo_descriptor *pdesc)
{ asm volatile("lgdt %0" : : "m"((pdesc)->limit), "m"(*pdesc)); }
extern inline void set_tr(Unsigned16 seg)
{ asm volatile("ltr %0" : : "rm" (seg)); }
extern inline Unsigned64 get_esp()
{ Unsigned64 rsp; asm("mov %%rsp, %0" : "=r" (rsp)); return rsp; }
extern inline Unsigned64 get_cr0()
{ Unsigned64 cr0; asm volatile("mov %%cr0, %0" : "=r" (cr0)); return cr0; }
extern inline void set_cr3(Unsigned64 cr3)
{ asm volatile("mov %0, %%cr3" : : "r" (cr3)); }
extern inline Unsigned64 get_cr4()
{ Unsigned64 cr4; asm volatile("mov %%cr4, %0" : "=r" (cr4)); return cr4; }
extern inline void set_cr4(Unsigned64 cr4)
{ asm volatile("mov %0, %%cr4" : : "r" (cr4)); }
extern inline void enable_longmode()
{ Proc::efer(Proc::efer() | Proc::Efer_lme_flag | Proc::Efer_nxe_flag); }
static inline void
fill_descriptor(struct x86_desc *desc, Unsigned32 base, Unsigned32 limit,
Unsigned8 access, Unsigned8 sizebits)
{
if (limit > 0xfffff)
{
limit >>= 12;
sizebits |= SZ_G;
}
desc->limit_low = limit & 0xffff;
desc->base_low = base & 0xffff;
desc->base_med = (base >> 16) & 0xff;
desc->access = access | ACC_P;
desc->limit_high = limit >> 16;
desc->granularity = sizebits;
desc->base_high = base >> 24;
}
static inline void
fill_idt_desc(struct idt_desc *desc, Unsigned64 offset,
Unsigned16 selector, Unsigned8 access, Unsigned8 ist_entry)
{
desc->offset_low0 = offset & 0x000000000000ffffLL;
desc->selector = selector;
desc->zero_and_ist = ist_entry;
desc->access = access | ACC_P;
desc->offset_low1 = (offset & 0x00000000ffff0000LL) >> 16;
desc->offset_high = (offset & 0xffffffff00000000LL) >> 32;
desc->ignored = 0;
}
inline void ALWAYS_INLINE
paging_enable(Address pml4)
{
/* Enable Physical Address Extension (PAE). */
set_cr4(get_cr4() | CR4_PAE);
/* We need to check for the CPU feature otherwise setting the PCID bit may
* trigger a #GP, see Intel manual. If needed we will complain later. */
if (Config::Pcid_enabled && !!(cpu_ext_feature_flags & CPUF_EXT_PCID))
set_cr4(get_cr4() | CR4_PCID);
/* Load the page map level 4. */
set_cr3(pml4);
/* Enable long mode. */
enable_longmode();
/* Turn on paging and switch to long mode. */
asm volatile("mov %0,%%cr0 ; jmp 1f ; 1:" : : "r" (get_cr0() | CR0_PG));
}
static void
cpuid()
{
int orig_eflags = get_eflags();
/* Check for a dumb old 386 by trying to toggle the AC flag. */
set_eflags(orig_eflags ^ EFLAGS_AC);
if ((get_eflags() ^ orig_eflags) & EFLAGS_AC)
{
/* It's a 486 or better. Now try toggling the ID flag. */
set_eflags(orig_eflags ^ EFLAGS_ID);
if ((get_eflags() ^ orig_eflags) & EFLAGS_ID)
{
int highest_val, dummy;
asm volatile("cpuid"
: "=a" (highest_val)
: "a" (0) : "ebx", "ecx", "edx");
if (highest_val >= 1)
{
asm volatile("cpuid"
: "=a" (dummy),
"=c" (cpu_ext_feature_flags),
"=d" (cpu_feature_flags)
: "a" (1)
: "ebx");
}
}
}
set_eflags(orig_eflags);
}
extern "C" struct idt_init_entry boot_idt_inittab[];
static void
base_idt_init(void)
{
struct idt_desc *dst = base_idt;
const struct idt_init_entry *src = boot_idt_inittab;
while (src->entrypoint)
{
fill_idt_desc(&dst[src->vector], src->entrypoint, KERNEL_CS_64,
src->type,(src->vector==8)?1:0);
src++;
}
}
static void
base_gdt_init(void)
{
printf("base_tss @%p\n", static_cast<void *>(&base_tss));
/* Initialize the base TSS descriptor. */
fill_descriptor(&base_gdt[BASE_TSS / 8],
reinterpret_cast<Address>(&base_tss), sizeof(base_tss) - 1,
ACC_PL_K | ACC_TSS, 0);
memset(&base_gdt[(BASE_TSS / 8) + 1], 0, 8);
/* Initialize the 64-bit kernel code and data segment descriptors
to point to the base of the kernel linear space region. */
fill_descriptor(&base_gdt[KERNEL_CS_64 / 8], 0, 0xffffffff,
ACC_PL_K | ACC_CODE_R, SZ_CODE_64);
fill_descriptor(&base_gdt[KERNEL_DS / 8], 0, 0xffffffff,
ACC_PL_K | ACC_DATA_W, SZ_32);
}
static void
base_tss_init(void)
{
base_tss.rsp0 = get_esp(); /* only temporary */
base_tss.ist1 = reinterpret_cast<Unsigned64>(dbf_stack + sizeof(dbf_stack));
base_tss.io_bit_map_offset = sizeof(base_tss);
}
static void
base_gdt_load(void)
{
struct pseudo_descriptor pdesc;
/* Create a pseudo-descriptor describing the GDT. */
pdesc.limit = sizeof(base_gdt) - 1;
pdesc.linear_base = reinterpret_cast<Address>(&base_gdt);
/* Load it into the CPU. */
set_gdt(&pdesc);
// XXX must be fixed
/* Reload all the segment registers from the new GDT. */
asm volatile (
"movabsq $1f, %%rax \n"
"pushq %%rbx \n"
"pushq %%rax \n"
"lretq \n"
"1: \n"
:
: "b" (KERNEL_CS_64)
: "rax", "memory");
set_ds(KERNEL_DS);
set_es(KERNEL_DS);
set_ss(KERNEL_DS);
set_fs(0);
set_gs(0);
}
static void
base_idt_load(void)
{
struct pseudo_descriptor pdesc;
/* Create a pseudo-descriptor describing the GDT. */
pdesc.limit = sizeof(base_idt) - 1;
pdesc.linear_base = reinterpret_cast<Address>(&base_idt);
set_idt(&pdesc);
}
static void
base_tss_load(void)
{
/* Make sure the TSS isn't marked busy. */
base_gdt[BASE_TSS / 8].access &= ~ACC_TSS_BUSY;
asm volatile ("" : : : "memory");
set_tr(BASE_TSS);
}
void
base_cpu_setup(void)
{
cpuid();
base_idt_init();
base_gdt_init();
base_tss_init();
// force tables to memory before loading segment registers
asm volatile ("" : : : "memory");
base_gdt_load();
base_idt_load();
base_tss_load();
}
static void
ptab_alloc(Address *out_ptab_pa)
{
static char pool[69<<12] __attribute__((aligned(4096)));
static Address pdirs;
static int initialized;
if (! initialized)
{
initialized = 1;
memset(pool, 0, sizeof(pool));
pdirs = round_page(reinterpret_cast<Address>(pool));
}
if (pdirs > reinterpret_cast<Address>(pool) + sizeof(pool))
panic("Cannot allocate page table -- increase ptab_alloc::pool");
*out_ptab_pa = pdirs;
pdirs += PAGE_SIZE;
}
static void
pdir_map_range(Address pml4_pa, Address la, Address pa,
Unsigned32 size, Unsigned32 mapping_bits)
{
assert(la+size-1 > la); // avoid 4 GiB wrap around
while (size > 0)
{
Unsigned64 *pml4e = find_pml4e(pml4_pa, la);
/* Create new pml4e with corresponding pdp (page directory pointer)
* if no valid entry exists. */
if (!(*pml4e & INTEL_PML4E_VALID))
{
Address pdp_pa;
/* Allocate new page for pdp. */
ptab_alloc(&pdp_pa);
/* Set the pml4 to point to it. */
*pml4e = (pdp_pa & INTEL_PML4E_PFN)
| INTEL_PML4E_VALID | INTEL_PML4E_USER | INTEL_PML4E_WRITE;
}
do
{
Unsigned64 *pdpe = find_pdpe(*pml4e & INTEL_PML4E_PFN, la);
/* Create new pdpe with corresponding pd (page directory)
* if no valid entry exists. */
if (!(*pdpe & INTEL_PDPE_VALID))
{
Address pd_pa;
/* Allocate new page for pd. */
ptab_alloc(&pd_pa);
/* Set the pdpe to point to it. */
*pdpe = (pd_pa & INTEL_PDPE_PFN)
| INTEL_PDPE_VALID | INTEL_PDPE_USER | INTEL_PDPE_WRITE;
}
do
{
Unsigned64 *pde = find_pde(*pdpe & INTEL_PDPE_PFN, la);
/* Use a 2 MiB page if we can. */
if (superpage_aligned(la) && superpage_aligned(pa)
&& (size >= SUPERPAGE_SIZE))
{
/* a failed assertion here may indicate a memory wrap
around problem */
assert(!(*pde & INTEL_PDE_VALID));
/* XXX what if an empty page table exists
from previous finer-granularity mappings? */
*pde = pa | mapping_bits | INTEL_PDE_SUPERPAGE;
la += SUPERPAGE_SIZE;
pa += SUPERPAGE_SIZE;
size -= SUPERPAGE_SIZE;
}
else
{
/* Find the page table, creating one if necessary. */
if (!(*pde & INTEL_PDE_VALID))
{
Address ptab_pa;
/* Allocate a new page table. */
ptab_alloc(&ptab_pa);
/* Set the pde to point to it. */
*pde = (ptab_pa & INTEL_PTE_PFN)
| INTEL_PDE_VALID | INTEL_PDE_USER | INTEL_PDE_WRITE;
}
assert(!(*pde & INTEL_PDE_SUPERPAGE));
/* Use normal 4 KiB page mappings. */
do
{
Unsigned64 *pte = find_pte(*pde & INTEL_PDE_PFN, la);
assert(!(*pte & INTEL_PTE_VALID));
/* Insert the mapping. */
*pte = pa | mapping_bits;
/* Advance to the next page. */
//pte++;
la += PAGE_SIZE;
pa += PAGE_SIZE;
size -= PAGE_SIZE;
}
while ((size > 0) && !superpage_aligned(la));
}
}
while ((size > 0) && !pd_aligned(la));
}
while ((size > 0) && !pdp_aligned(la));
}
}
void
base_paging_init(void)
{
ptab_alloc(&base_pml4_pa);
// Establish one-to-one mappings for the first 4 MiB of physical memory
pdir_map_range(base_pml4_pa, /*virt*/0, /*phys*/0, /*size*/4 << 20,
INTEL_PDE_VALID | INTEL_PDE_WRITE | INTEL_PDE_USER);
// map in the physical start of the kernel to 0xfffffffff0000000
pdir_map_range(base_pml4_pa, Mem_layout::Kernel_image,
Mem_layout::Kernel_image_phys,
Mem_layout::Kernel_image_size,
INTEL_PDE_VALID | INTEL_PDE_WRITE | INTEL_PDE_USER);
// Adapter memory needs a separate mapping
if (!Mem_layout::Adap_in_kernel_image)
// map in the adapter memory (superpage) of physical memory to ...
pdir_map_range(base_pml4_pa, /*virt*/Mem_layout::Adap_image,
/*phys*/Mem_layout::Adap_image_phys,
/*size*/Config::SUPERPAGE_SIZE,
INTEL_PDE_VALID | INTEL_PDE_WRITE | INTEL_PDE_USER);
// XXX Turn on paging and activate 64Bit mode
paging_enable(base_pml4_pa);
}
void
base_map_physical_memory_for_kernel()
{
unsigned long sz = Mem_layout::pmem_size;
printf("map pmem %14lx-%14lx to %14lx-%14lx\n",
Mem_layout::pmem_to_phys(Mem_layout::Physmem),
Mem_layout::pmem_to_phys(Mem_layout::Physmem) + sz,
Mem_layout::Physmem,
Mem_layout::Physmem + sz);
// map in the last 60 MiB of physical memory to 0xfc400000
pdir_map_range(base_pml4_pa,
/*virt*/Mem_layout::Physmem,
/*phys*/Mem_layout::pmem_to_phys(Mem_layout::Physmem),
/*size*/sz,
INTEL_PDE_VALID | INTEL_PDE_WRITE | INTEL_PDE_USER);
}
extern "C" void trap_dump_panic(const struct trap_state *);
void
trap_dump_panic(const struct trap_state *st)
{
int from_user = (st->cs & 3);
int i;
putchar('\n');
printf("RAX %016llx RBX %016llx\n", st->rax, st->rbx);
printf("RCX %016llx RDX %016llx\n", st->rcx, st->rdx);
printf("RSI %016llx RDI %016llx\n", st->rsi, st->rdi);
printf("RBP %016llx RSP %016llx\n",
st->rbp, from_user ? st->rsp : reinterpret_cast<Address>(&st->rsp));
printf("R8 %016llx R9 %016llx\n", st->r8, st->r9);
printf("R10 %016llx R11 %016llx\n", st->r10, st->r11);
printf("R12 %016llx R13 %016llx\n", st->r12, st->r13);
printf("R14 %016llx R15 %016llx\n", st->r14, st->r15);
printf("RIP %016llx RFL %016llx\n", st->rip, st->rflags);
printf("CS %04llx SS %04llx\n",
st->cs & 0xffff, from_user ? st->ss & 0xffff : get_ss());
printf("trapno %llu, error %08llx, from %s mode\n",
st->trapno, st->err, from_user ? "user" : "kernel");
if (st->trapno == 0x0d)
{
if (st->err & 1)
printf("(external event");
else
printf("(internal event");
if (st->err & 2)
{
printf(" regarding IDT gate descriptor no. 0x%02llx)\n",
st->err >> 3);
}
else
{
printf(" regarding %s entry no. 0x%02llx)\n",
st->err & 4 ? "LDT" : "GDT", st->err >> 3);
}
}
else if (st->trapno == 0x0e)
printf("page fault linear address %016llx\n", st->cr2);
if (!from_user)
{
for (i = 0; i < 32; i++)
printf("%016llx%c", (&st->rsp)[i], ((i & 3) == 3) ? '\n' : ' ');
}
panic("Unexpected trap while booting Fiasco!");
}

View File

@@ -0,0 +1,84 @@
#include "globalconfig.h"
#include "idt_init.h"
.macro EXCEPTION n
GATE_ENTRY \n, 1f, 0x0e
1: push $(0)
push $(\n)
jmp 2f
.endm
.macro EXCEP_USR n
GATE_ENTRY \n, 1f, 0x6e
1: push $(0)
push $(\n)
jmp 2f
.endm
.macro EXCEP_ERR n
GATE_ENTRY \n, 1f, 0x0e
1: push $(\n)
jmp 2f
.endm
GATE_INITTAB_BEGIN boot_idt_inittab
EXCEPTION 0x00
EXCEPTION 0x01
EXCEPTION 0x02
EXCEP_USR 0x03
EXCEP_USR 0x04
EXCEP_USR 0x05
EXCEPTION 0x06
EXCEPTION 0x07
EXCEPTION 0x08
EXCEPTION 0x09
EXCEP_ERR 0x0a
EXCEP_ERR 0x0b
EXCEP_ERR 0x0c
EXCEP_ERR 0x0d
EXCEP_ERR 0x0e
EXCEPTION 0x0f
EXCEPTION 0x10
EXCEP_ERR 0x11
EXCEPTION 0x12
EXCEPTION 0x13
EXCEPTION 0x14
EXCEP_ERR 0x15
EXCEPTION 0x16
EXCEPTION 0x17
EXCEPTION 0x18
EXCEPTION 0x19
EXCEPTION 0x1a
EXCEPTION 0x1b
EXCEPTION 0x1c
EXCEPTION 0x1d
EXCEPTION 0x1e
EXCEPTION 0x1f
GATE_INITTAB_END
2:
push %r15
push %r14
push %r13
push %r12
push %r11
push %r10
push %r9
push %r8
mov %cr2,%r8
push %r8
push %rbp
push %rsi
push %rdi
push %rdx
push %rcx
push %rbx
push %rax
/* invoke trap_dump_panic(const struct trap_state *st)
* %rdi contains first argument
*/
mov %rsp,%rdi
call trap_dump_panic

View File

@@ -0,0 +1,32 @@
#ifndef BOOT_PAGING_H
#define BOOT_PAGING_H
#include "types.h"
enum
{
PAGE_SIZE = (1 << 12),
SUPERPAGE_SIZE = (1 << 21),
PD_SIZE = (1 << 30),
PDP_SIZE = (1LL << 39),
};
static inline int
superpage_aligned(Address x)
{ return (x & (SUPERPAGE_SIZE - 1)) == 0; }
static inline int
pd_aligned(Address x)
{ return (x & (PD_SIZE - 1)) == 0; }
static inline int
pdp_aligned(Address x)
{ return (x & (PDP_SIZE - 1)) == 0; }
static inline Address trunc_page(Address x)
{ return x & ~(PAGE_SIZE - 1); }
static inline Address round_page(Address x)
{ return (x + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); }
#endif

View File

@@ -0,0 +1,17 @@
SECTIONS
{
.text :
{
*(.init)
*(.text .text.* .gnu.linkonce.t.*)
*(.fini)
*(.rodata .rodata.* .gnu.linkonce.r.*)
*(.data .data.* .gnu.linkonce.d.*)
*(.anno)
} = 0x90909090
.bss :
{
*(.bss .bss.* .gnu.linkonce.b.* COMMON)
}
}

View File

@@ -0,0 +1,10 @@
#ifndef BOOT_CPU_H
#define BOOT_CPU_H
#include "types.h"
void base_paging_init (void);
void base_map_physical_memory_for_kernel ();
void base_cpu_setup (void);
#endif

View File

@@ -0,0 +1,6 @@
#ifndef BOOT_DIRECT_CONS_H
#define BOOT_DIRECT_CONS_H
void direct_cons_putchar(unsigned char c);
#endif

View File

@@ -0,0 +1,17 @@
#include <libc_backend.h>
#include "boot_direct_cons.h"
unsigned int __libc_backend_printf_lock()
{ return 0; }
void __libc_backend_printf_unlock(unsigned int)
{}
int __libc_backend_outs(const char *s, size_t len)
{
size_t i = 0;
for (; i < len; ++i)
direct_cons_putchar(s[i]);
return 1;
}

View File

@@ -0,0 +1,131 @@
/* this code is run directly from boot.S. our task is to setup the
paging just enough so that L4 can run in its native address space
at 0xf0001000, and then start up L4. */
#include <cassert>
#include <cstring>
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include "boot_cpu.h"
#include "boot_paging.h"
#include "boot_console.h"
#include "kernel_console.h"
#include "checksum.h"
#include "config.h"
#include "globalconfig.h"
#include "kip.h"
#include "kmem_alloc.h"
#include "mem_layout.h"
#include "mem_region.h"
#include "mem_unit.h"
#include "panic.h"
#include "processor.h"
#include "reset.h"
#include "simpleio.h"
struct check_sum
{
char delimiter[16];
Unsigned32 checksum_ro;
Unsigned32 checksum_rw;
} check_sum = {"FIASCOCHECKSUM=", 0, 0};
extern "C" char _start[];
extern "C" char _end[];
#ifndef NDEBUG
void assert_fail(char const *expr, char const *file, unsigned int line,
void const *caller)
{
panic("Assertion failed at %s:%u:%p: %s\n", file, line, caller, expr);
}
#endif
void
panic(char const *format, ...)
{
va_list args;
putstr("\033[1mPanic: ");
va_start(args, format);
vprintf(format, args);
va_end(args);
putstr("\033[m");
for (;;)
Proc::pause();
}
// test if [start1..end1-1] overlaps [start2..end2-1]
static
void
check_overlap (const char *str,
Address start1, Address end1, Address start2, Address end2)
{
if ((start1 >= start2 && start1 < end2) || (end1 > start2 && end1 <= end2))
panic("Kernel [0x%014lx,0x%014lx) overlaps %s [0x%014lx,0x%014lx).",
start1, end1, str, start2, end2);
}
typedef void (*Start)(unsigned) FIASCO_FASTCALL;
extern "C" FIASCO_FASTCALL void bootstrap();
void
bootstrap()
{
extern Kip my_kernel_info_page;
Start start;
// setup stuff for base_paging_init()
base_cpu_setup();
// now do base_paging_init(): sets up paging with one-to-one mapping
base_paging_init();
asm volatile ("" ::: "memory");
Kip::init_global_kip(&my_kernel_info_page);
Kconsole::init();
Boot_console::init();
printf("Boot: KIP @ %p\n", static_cast<void *>(Kip::k()));
printf("Boot: Kmem_alloc::base_init();\n");
if (!Kmem_alloc::base_init())
panic("Could not reserve kernel memory.");
printf("Boot: kernel memory reserved\n");
// make sure that we did not forgot to discard an unused header section
// (compare "objdump -p fiasco.debug")
if (reinterpret_cast<Address>(_start) < Mem_layout::Kernel_image)
panic("Fiasco kernel occupies memory below %014lx",
Mem_layout::Kernel_image);
if (reinterpret_cast<Address>(&_end) - Mem_layout::Kernel_image > Mem_layout::Kernel_image_size)
panic("Fiasco boot system occupies more than %lu MiB",
Mem_layout::Kernel_image_size / (1024 * 1024));
base_map_physical_memory_for_kernel();
Mem_unit::tlb_flush_early();
start = reinterpret_cast<Start>(_start);
Address phys_start = reinterpret_cast<Address>(_start)
- Mem_layout::Kernel_image
+ Mem_layout::Kernel_image_phys;
Address phys_end = reinterpret_cast<Address>(_end)
- Mem_layout::Kernel_image
+ Mem_layout::Kernel_image_phys;
check_overlap ("VGA/IO", phys_start, phys_end, 0xa0000, 0x100000);
if (Checksum::get_checksum_ro() != check_sum.checksum_ro)
panic("Read-only (text) checksum does not match.");
if (Checksum::get_checksum_rw() != check_sum.checksum_rw)
panic("Read-write (data) checksum does not match.");
start(check_sum.checksum_ro);
}

View File

@@ -0,0 +1,44 @@
#include <string.h>
#include "boot_direct_cons.h"
#include "boot_paging.h"
void
direct_cons_putchar(unsigned char c)
{
static int ofs = -1;
unsigned char *vidbase = reinterpret_cast<unsigned char *>(0xb8000);
if (ofs < 0)
{
ofs = 0;
direct_cons_putchar('\n');
}
switch (c)
{
case '\n':
memmove(vidbase, vidbase + 80 * 2, 80 * 2 * 24);
memset(vidbase + 80 * 2 * 24, 0, 80 * 2);
[[fallthrough]];
case '\r':
ofs = 0;
break;
case '\t':
ofs = (ofs + 8) & ~7;
break;
default:
{
if (ofs >= 80)
direct_cons_putchar('\n');
volatile unsigned char *p = vidbase + 80 * 2 * 24 + ofs * 2;
p[0] = c;
p[1] = 0x0f;
ofs++;
break;
}
}
}

View File

@@ -0,0 +1,53 @@
# -*- makefile -*-
# Boot Makefile
# Add future prerequisites somewhere among the list of libraries.
# You really should not have to add anything in the $(LD) line.
#
# Don't link against libgcc because of -mregparm=3. The library
# would only be necessary for 64-bit arithmetics. These functions
# can be replaced by using div32/mod32 from lib/libk (and should
# for efficency reasons).
boot_img.o: boot_img.x2 boot_img.ren_syms
$(LINK_MESSAGE)
$(VERBOSE)$(OBJCOPY) --redefine-syms=boot_img.ren_syms $< $@
boot_img.ren_syms: boot_img.x2
$(LINK_MESSAGE)
$(VERBOSE)$(NM) -u $^ | perl -n -e 'if (/^\s*U\s+bootstrap_(.*)$$/) { print "bootstrap_$$1 $$1\n"; }' > $@
boot_img.x1: $(OBJ_BOOT) $(DRIVERS) $(LIBC)
$(LINK_MESSAGE)
$(VERBOSE)$(LD) $(LDFLAGS) $(LD_EMULATION_FLAG) -r -s -o $@ \
-T $(srcdir)/boot/ia32/bootstrap.ld -u_boot_start -gc-sections $^
boot_img.x2: boot_img.x1
$(LINK_MESSAGE)
$(VERBOSE)$(OBJCOPY) --prefix-alloc-sections=.bootstrap --prefix-symbols=bootstrap_ -G bootstrap__boot_start $^ $@
-include .kernel.ia32.lds.d
# $(1) = fiasco - variable
# $(2) = fiasco.debug - variable
# $(3) = Additional $(OBJ_X), e.g. OBJ_<unittest>
define gen_kernel_rules =
$(2): kernel.ia32.lds boot_img.o $$(CRT0) $$(OBJ_KERNEL) $(3) $$(JDB) $$(KERNEL_EXTRA_LIBS) $$(ABI) $$(JABI) libdrivers.a $$(LIBUART) $$(LIBK) $$(CXXLIB) $$(LIBC) libfonts.a libgluedriverslibc.a
$$(LINK_MESSAGE)
$$(VERBOSE)$$(LD) $$(LDFLAGS) $$(LD_EMULATION_FLAG) -N -o $$@ \
-T $$< -gc-sections $$(filter-out $$<,$$+) \
$$(KERNEL_UNRES_SYMS)
$$(call ADD_CONFIGFILE,$$@)
$(1): $(2)
$$(LINK_MESSAGE)
$$(VERBOSE)$$(STRIP) -o $$@ $$<
$$(VERBOSE)$$(OBJCOPY) --add-gnu-debuglink=$$< $$@
$$(VERBOSE)chmod 755 $$@
endef
# generate fiasco and fiasco.debug rules
$(eval $(call gen_kernel_rules,$(BOOT),$(KERNEL),$(OBJ_STDWORKLOAD)))
BOOT_CLEAN := boot_img.x1 boot_img.x2 boot_img.ren_syms boot_img.ren_syms kernel.ia32.lds

View File

@@ -0,0 +1,18 @@
/* -*- c -*- */
.globl _boot_start
_boot_start:
leal _stack,%esp
pushl $0 /* no return address */
jmp bootstrap
.align 4, 0x90
.long 0x1BADB002 /* magic */
.long 0x00000000 /* feature flags */
.long 0 - 0x1BADB002
.bss
.align 16
.space 2048
_stack:

View File

@@ -0,0 +1,555 @@
#include <cassert>
#include <cstring>
#include <cstdio>
#include "types.h"
#include "boot_cpu.h"
#include "boot_paging.h"
#include "mem_layout.h"
#include "panic.h"
#include "regdefs.h"
enum
{
PDESHIFT = 22,
PDEMASK = 0x3ff,
PTESHIFT = 12,
PTEMASK = 0x3ff,
INTEL_PTE_VALID = 0x00000001,
INTEL_PTE_WRITE = 0x00000002,
INTEL_PTE_USER = 0x00000004,
INTEL_PTE_WTHRU = 0x00000008,
INTEL_PTE_NCACHE = 0x00000010,
INTEL_PTE_REF = 0x00000020,
INTEL_PTE_MOD = 0x00000040,
INTEL_PTE_GLOBAL = 0x00000100,
INTEL_PTE_AVAIL = 0x00000e00,
INTEL_PTE_PFN = 0xfffff000,
INTEL_PDE_VALID = 0x00000001,
INTEL_PDE_WRITE = 0x00000002,
INTEL_PDE_USER = 0x00000004,
INTEL_PDE_WTHRU = 0x00000008,
INTEL_PDE_NCACHE = 0x00000010,
INTEL_PDE_REF = 0x00000020,
INTEL_PDE_MOD = 0x00000040,
INTEL_PDE_SUPERPAGE = 0x00000080,
INTEL_PDE_GLOBAL = 0x00000100,
INTEL_PDE_AVAIL = 0x00000e00,
INTEL_PDE_PFN = 0xfffff000,
CPUF_4MB_PAGES = 0x00000008,
BASE_TSS = 0x08,
KERNEL_CS = 0x10,
KERNEL_DS = 0x18,
DBF_TSS = 0x20,
ACC_TSS = 0x09,
ACC_TSS_BUSY = 0x02,
ACC_CODE_R = 0x1a,
ACC_DATA_W = 0x12,
ACC_PL_K = 0x00,
ACC_P = 0x80,
SZ_32 = 0x4,
SZ_16 = 0x0,
SZ_G = 0x8,
GDTSZ = (0x28/8),
IDTSZ = 0x14,
};
struct pseudo_descriptor
{
Unsigned16 pad;
Unsigned16 limit;
Unsigned32 linear_base;
};
struct x86_desc
{
Unsigned16 limit_low; /* limit 0..15 */
Unsigned16 base_low; /* base 0..15 */
Unsigned8 base_med; /* base 16..23 */
Unsigned8 access; /* access byte */
Unsigned8 limit_high:4; /* limit 16..19 */
Unsigned8 granularity:4; /* granularity */
Unsigned8 base_high; /* base 24..31 */
} __attribute__((packed));
struct x86_gate
{
Unsigned16 offset_low; /* offset 0..15 */
Unsigned16 selector;
Unsigned8 word_count;
Unsigned8 access;
Unsigned16 offset_high; /* offset 16..31 */
} __attribute__((packed));
struct x86_tss
{
Unsigned32 back_link;
Unsigned32 esp0, ss0;
Unsigned32 esp1, ss1;
Unsigned32 esp2, ss2;
Unsigned32 cr3;
Unsigned32 eip, eflags;
Unsigned32 eax, ecx, edx, ebx, esp, ebp, esi, edi;
Unsigned32 es, cs, ss, ds, fs, gs;
Unsigned32 ldt;
Unsigned16 trace_trap;
Unsigned16 io_bit_map_offset;
};
struct gate_init_entry
{
Unsigned32 entrypoint;
Unsigned16 vector;
Unsigned16 type;
};
struct trap_state
{
Unsigned32 gs, fs, es, ds;
Unsigned32 edi, esi, ebp, cr2, ebx, edx, ecx, eax;
Unsigned32 trapno, err;
Unsigned32 eip, cs, eflags, esp, ss;
};
static Unsigned32 cpu_feature_flags;
static Address base_pdir_pa;
static struct x86_tss base_tss;
static struct x86_desc base_gdt[GDTSZ];
static struct x86_gate base_idt[IDTSZ];
static void handle_dbf(void);
static char dbf_stack[2048];
static struct x86_tss dbf_tss =
{
0/*back_link*/,
0/*esp0*/, 0/*ss0*/, 0/*esp1*/, 0/*ss1*/, 0/*esp2*/, 0/*ss2*/,
0/*cr3*/,
reinterpret_cast<Unsigned32>(handle_dbf)/*eip*/, 0x00000082/*eflags*/,
0/*eax*/, 0/*ecx*/, 0/*edx*/, 0/*ebx*/,
reinterpret_cast<Unsigned32>(dbf_stack) + sizeof(dbf_stack)/*esp*/,
0/*ebp*/, 0/*esi*/, 0/*edi*/,
KERNEL_DS/*es*/, KERNEL_CS/*cs*/, KERNEL_DS/*ss*/,
KERNEL_DS/*ds*/, KERNEL_DS/*fs*/, KERNEL_DS/*gs*/,
0/*ldt*/, 0/*trace_trap*/, 0x8000/*io_bit_map_offset*/
};
static inline Address* pdir_find_pde(Address pdir_pa, Address la)
{ return &reinterpret_cast<Address*>(pdir_pa)[(la >> PDESHIFT) & PDEMASK]; }
static inline Address* ptab_find_pte(Address ptab_pa, Address la)
{ return &reinterpret_cast<Address*>(ptab_pa)[(la >> PTESHIFT) & PTEMASK]; }
extern inline Unsigned32 get_eflags()
{ Unsigned32 efl; asm volatile("pushf ; popl %0" : "=r" (efl)); return efl; }
extern inline void set_eflags(Unsigned32 efl)
{ asm volatile("pushl %0 ; popf" : : "r" (efl) : "memory"); }
extern inline void set_ds(Unsigned16 ds)
{ asm volatile("movw %w0,%%ds" : : "r" (ds)); }
extern inline void set_es(Unsigned16 es)
{ asm volatile("movw %w0,%%es" : : "r" (es)); }
extern inline void set_fs(Unsigned16 fs)
{ asm volatile("movw %w0,%%fs" : : "r" (fs)); }
extern inline void set_gs(Unsigned16 gs)
{ asm volatile("movw %w0,%%gs" : : "r" (gs)); }
extern inline void set_ss(Unsigned16 ss)
{ asm volatile("movw %w0,%%ss" : : "r" (ss)); }
extern inline Unsigned16 get_ss()
{ Unsigned16 ss; asm volatile("movw %%ss,%w0" : "=r" (ss)); return ss; }
extern inline void set_idt(pseudo_descriptor *pdesc)
{ asm volatile("lidt %0" : : "m"((pdesc)->limit), "m"(*pdesc)); }
extern inline void set_gdt(pseudo_descriptor *pdesc)
{ asm volatile("lgdt %0" : : "m"((pdesc)->limit), "m"(*pdesc)); }
extern inline void set_tr(Unsigned16 seg)
{ asm volatile("ltr %0" : : "rm" (seg)); }
extern inline Unsigned32 get_esp()
{ Unsigned32 esp; asm("mov %%esp, %0" : "=r" (esp)); return esp; }
extern inline Unsigned32 get_cr0()
{ Unsigned32 cr0; asm volatile("mov %%cr0, %0" : "=r" (cr0)); return cr0; }
extern inline Unsigned32 get_cr2()
{ Unsigned32 cr2; asm volatile("mov %%cr2, %0" : "=r" (cr2)); return cr2; }
extern inline void set_cr3(Unsigned32 cr3)
{ asm volatile("mov %0, %%cr3" : : "r" (cr3)); }
extern inline Unsigned32 get_cr4()
{ Unsigned32 cr4; asm volatile("mov %%cr4, %0" : "=r" (cr4)); return cr4; }
extern inline void set_cr4(Unsigned32 cr4)
{ asm volatile("mov %0, %%cr4" : : "r" (cr4)); }
static inline void
fill_descriptor(struct x86_desc *desc, Unsigned32 base, Unsigned32 limit,
Unsigned8 access, Unsigned8 sizebits)
{
if (limit > 0xfffff)
{
limit >>= 12;
sizebits |= SZ_G;
}
desc->limit_low = limit & 0xffff;
desc->base_low = base & 0xffff;
desc->base_med = (base >> 16) & 0xff;
desc->access = access | ACC_P;
desc->limit_high = limit >> 16;
desc->granularity = sizebits;
desc->base_high = base >> 24;
}
static inline void
fill_gate(unsigned vector, Unsigned32 offset,
Unsigned16 selector, Unsigned8 access)
{
base_idt[vector].offset_low = offset & 0xffff;
base_idt[vector].selector = selector;
base_idt[vector].word_count = 0;
base_idt[vector].access = access | ACC_P;
base_idt[vector].offset_high = (offset >> 16) & 0xffff;
}
inline void ALWAYS_INLINE
paging_enable(Address pdir)
{
/* Load the page directory. */
set_cr3(pdir);
/* Turn on paging. */
asm volatile("movl %0,%%cr0 ; jmp 1f ; 1:" : : "r" ((get_cr0() & ~0xf0000000) | CR0_PG));
}
static void
cpuid()
{
int orig_eflags = get_eflags();
/* Check for a dumb old 386 by trying to toggle the AC flag. */
set_eflags(orig_eflags ^ EFLAGS_AC);
if ((get_eflags() ^ orig_eflags) & EFLAGS_AC)
{
/* It's a 486 or better. Now try toggling the ID flag. */
set_eflags(orig_eflags ^ EFLAGS_ID);
if ((get_eflags() ^ orig_eflags) & EFLAGS_ID)
{
int highest_val, dummy;
asm volatile("cpuid"
: "=a" (highest_val)
: "a" (0) : "ebx", "ecx", "edx");
if (highest_val >= 1)
{
asm volatile("cpuid"
: "=a" (dummy),
"=d" (cpu_feature_flags)
: "a" (1)
: "ebx", "ecx");
}
}
}
set_eflags(orig_eflags);
}
extern "C" struct gate_init_entry boot_idt_inittab[];
static void
base_idt_init(void)
{
const struct gate_init_entry *src = boot_idt_inittab;
while (src->entrypoint)
{
if ((src->type & 0x1f) == 0x05)
// task gate
fill_gate(src->vector, 0, src->entrypoint, src->type);
else
// interrupt gate
fill_gate(src->vector, src->entrypoint, KERNEL_CS, src->type);
src++;
}
}
static void
base_gdt_init(void)
{
/* Initialize the base TSS descriptor. */
fill_descriptor(&base_gdt[BASE_TSS / 8],
reinterpret_cast<Address>(&base_tss), sizeof(base_tss) - 1,
ACC_PL_K | ACC_TSS, 0);
/* Initialize the TSS descriptor for the double fault handler */
fill_descriptor(&base_gdt[DBF_TSS / 8],
reinterpret_cast<Address>(&dbf_tss), sizeof(dbf_tss) - 1,
ACC_PL_K | ACC_TSS, 0);
/* Initialize the 32-bit kernel code and data segment descriptors
to point to the base of the kernel linear space region. */
fill_descriptor(&base_gdt[KERNEL_CS / 8], 0, 0xffffffff,
ACC_PL_K | ACC_CODE_R, SZ_32);
fill_descriptor(&base_gdt[KERNEL_DS / 8], 0, 0xffffffff,
ACC_PL_K | ACC_DATA_W, SZ_32);
}
static void
base_tss_init(void)
{
base_tss.ss0 = KERNEL_DS;
base_tss.esp0 = get_esp(); /* only temporary */
base_tss.io_bit_map_offset = sizeof(base_tss);
}
static void
base_gdt_load(void)
{
struct pseudo_descriptor pdesc;
/* Create a pseudo-descriptor describing the GDT. */
pdesc.limit = sizeof(base_gdt) - 1;
pdesc.linear_base = reinterpret_cast<Address>(&base_gdt);
/* Load it into the CPU. */
set_gdt(&pdesc);
/* Reload all the segment registers from the new GDT. */
asm volatile("ljmp %0,$1f ; 1:" : : "i" (KERNEL_CS));
set_ds(KERNEL_DS);
set_es(KERNEL_DS);
set_ss(KERNEL_DS);
set_fs(0);
set_gs(0);
}
static void
base_idt_load(void)
{
struct pseudo_descriptor pdesc;
/* Create a pseudo-descriptor describing the GDT. */
pdesc.limit = sizeof(base_idt) - 1;
pdesc.linear_base = reinterpret_cast<Address>(&base_idt);
set_idt(&pdesc);
}
static void
base_tss_load(void)
{
/* Make sure the TSS isn't marked busy. */
base_gdt[BASE_TSS / 8].access &= ~ACC_TSS_BUSY;
set_tr(BASE_TSS);
}
void
base_cpu_setup(void)
{
cpuid();
base_idt_init();
base_gdt_init();
base_tss_init();
// force tables to memory before loading segment registers
asm volatile ("" : : : "memory");
base_gdt_load();
base_idt_load();
base_tss_load();
}
static void
ptab_alloc(Address *out_ptab_pa)
{
static char pool[140<<12] __attribute__((aligned(4096)));
static Address pdirs;
static int initialized;
if (! initialized)
{
initialized = 1;
memset(pool, 0, sizeof(pool));
pdirs = round_page(reinterpret_cast<Address>(pool));
}
if (pdirs >= reinterpret_cast<Address>(pool) + sizeof(pool))
panic("Cannot allocate page table -- increase ptab_alloc::pool");
*out_ptab_pa = pdirs;
pdirs += PAGE_SIZE;
}
static void
pdir_map_range(Address pdir_pa, Address la, Address pa,
Unsigned32 size, Unsigned32 mapping_bits)
{
while (size > 0)
{
Address *pde = pdir_find_pde(pdir_pa, la);
/* Use a 4 MiB page if we can. */
if (superpage_aligned(la) && superpage_aligned(pa)
&& (size >= SUPERPAGE_SIZE)
&& (cpu_feature_flags & CPUF_4MB_PAGES))
{
/* a failed assertion here may indicate a memory wrap
around problem */
assert(!(*pde & INTEL_PDE_VALID));
/* XXX what if an empty page table exists
from previous finer-granularity mappings? */
*pde = pa | mapping_bits | INTEL_PDE_SUPERPAGE;
la += SUPERPAGE_SIZE;
pa += SUPERPAGE_SIZE;
size -= SUPERPAGE_SIZE;
}
else
{
Address *pte;
/* Find the page table, creating one if necessary. */
if (!(*pde & INTEL_PDE_VALID))
{
Address ptab_pa;
/* Allocate a new page table. */
ptab_alloc(&ptab_pa);
/* Set the pde to point to it. */
*pde = (ptab_pa & INTEL_PTE_PFN)
| INTEL_PDE_VALID | INTEL_PDE_USER | INTEL_PDE_WRITE;
}
assert(!(*pde & INTEL_PDE_SUPERPAGE));
pte = ptab_find_pte(*pde & INTEL_PDE_PFN, la);
/* Use normal 4 KiB page mappings. */
do
{
assert(!(*pte & INTEL_PTE_VALID));
/* Insert the mapping. */
*pte = pa | mapping_bits;
/* Advance to the next page. */
pte++;
la += PAGE_SIZE;
pa += PAGE_SIZE;
size -= PAGE_SIZE;
}
while ((size > 0) && !superpage_aligned(la));
}
}
}
void
base_paging_init(void)
{
// We assume that we only have to map the first 4 MiB page. This has
// to be checked before base_paging_init was called.
ptab_alloc(&base_pdir_pa);
// Establish one-to-one mapping for the first 4 MiB of physical memory
pdir_map_range(base_pdir_pa, /*virt*/0, /*phys*/0, /*size*/4 << 20,
INTEL_PDE_VALID | INTEL_PDE_WRITE | INTEL_PDE_USER);
// Enable superpage support if we have it
if (cpu_feature_flags & CPUF_4MB_PAGES)
set_cr4(get_cr4() | CR4_PSE);
dbf_tss.cr3 = base_pdir_pa;
// map in the Kernel image (superpage) of physical memory to 0xf0000000
pdir_map_range(base_pdir_pa, /*virt*/Mem_layout::Kernel_image,
Mem_layout::Kernel_image_phys,
Mem_layout::Kernel_image_size,
INTEL_PDE_VALID | INTEL_PDE_WRITE | INTEL_PDE_USER);
// Adapter memory is already contrained in the kernel-image mapping
if (!Mem_layout::Adap_in_kernel_image)
{
// map in the adapter memory (superpage) of physical memory to ...
pdir_map_range(base_pdir_pa, /*virt*/Mem_layout::Adap_image,
/*phys*/Mem_layout::Adap_image_phys,
/*size*/Config::SUPERPAGE_SIZE,
INTEL_PDE_VALID | INTEL_PDE_WRITE | INTEL_PDE_USER);
}
// Turn on paging
paging_enable(base_pdir_pa);
}
void
base_map_physical_memory_for_kernel()
{
unsigned long sz = Mem_layout::pmem_size;
// map in the last 60 MiB of physical memory to 0xfc400000
pdir_map_range(base_pdir_pa,
/*virt*/Mem_layout::Physmem,
/*phys*/Mem_layout::pmem_to_phys(Mem_layout::Physmem),
/*size*/sz,
INTEL_PDE_VALID | INTEL_PDE_WRITE | INTEL_PDE_USER);
}
static char const * const base_regs =
"\n"
"EAX %08x EBX %08x ECX %08x EDX %08x\n"
"ESI %08x EDI %08x EBP %08x ESP %08x\n"
"EIP %08x EFL %08x\n"
"CS %04x SS %04x DS %04x ES %04x FS %04x GS %04x\n";
extern "C" FIASCO_FASTCALL void trap_dump_panic(const struct trap_state *);
void
trap_dump_panic(const struct trap_state *st)
{
int from_user = (st->cs & 3);
int i;
printf(base_regs,
st->eax, st->ebx, st->ecx, st->edx,
st->esi, st->edi, st->ebp,
from_user ? st->esp : reinterpret_cast<Unsigned32>(&st->esp),
st->eip, st->eflags,
st->cs & 0xffff, from_user ? st->ss & 0xffff : get_ss(),
st->ds & 0xffff, st->es & 0xffff, st->fs & 0xffff, st->gs & 0xffff);
printf("trapno %u, error %08x, from %s mode\n",
st->trapno, st->err, from_user ? "user" : "kernel");
if (st->trapno == 0x0d)
{
printf("(%sternal event regarding ", st->err & 1 ? "ex" : "in");
if (st->err & 2)
printf("IDT gate descriptor");
else
printf("%cDT entry", st->err & 4 ? 'L' : 'G');
printf(" no. 0x%02x)\n", st->err >> 3);
}
else if (st->trapno == 0x0e)
printf("page fault linear address %08x\n", get_cr2());
if (!from_user)
{
for (i = 0; i < 32; i++)
printf("%08x%c", (&st->esp)[i], ((i & 7) == 7) ? '\n' : ' ');
}
panic("Unexpected trap while booting Fiasco!");
}
static void
handle_dbf()
{
printf(base_regs,
base_tss.eax, base_tss.ebx, base_tss.ecx, base_tss.edx,
base_tss.esi, base_tss.edi, base_tss.ebp, base_tss.esp,
base_tss.eip, base_tss.eflags,
base_tss.cs & 0xffff, base_tss.ss & 0xffff, base_tss.ds & 0xffff,
base_tss.es & 0xffff, base_tss.fs & 0xffff, base_tss.gs & 0xffff);
panic("Unexpected DOUBLE FAULT while booting Fiasco!");
}

View File

@@ -0,0 +1,61 @@
#include "globalconfig.h"
#include "idt_init.h"
.macro EXCEPTION n
GATE_ENTRY \n, 1f, 0x0e
1: pushl $(0)
pushl $(\n)
jmp 2f
.endm
.macro EXCEP_USR n
GATE_ENTRY \n, 1f, 0x6e
1: pushl $(0)
pushl $(\n)
jmp 2f
.endm
.macro EXCEP_ERR n
GATE_ENTRY \n, 1f, 0x0e
1: pushl $(\n)
jmp 2f
.endm
GATE_INITTAB_BEGIN boot_idt_inittab
EXCEPTION 0x00
EXCEPTION 0x01
EXCEPTION 0x02
EXCEP_USR 0x03
EXCEP_USR 0x04
EXCEP_USR 0x05
EXCEPTION 0x06
EXCEPTION 0x07
GATE_ENTRY 0x08, 0x20 ,0x05
EXCEPTION 0x09
EXCEP_ERR 0x0a
EXCEP_ERR 0x0b
EXCEP_ERR 0x0c
EXCEP_ERR 0x0d
EXCEP_ERR 0x0e
EXCEPTION 0x0f
EXCEPTION 0x10
EXCEP_ERR 0x11
EXCEPTION 0x12
EXCEPTION 0x13
EXCEPTION 0x14
EXCEP_ERR 0x15
GATE_INITTAB_END
2: pusha
pushl %ds
pushl %es
pushl %fs
pushl %gs
movl %ss,%eax
movl %eax,%ds
movl %eax,%es
movl %esp,%eax
call trap_dump_panic

View File

@@ -0,0 +1,22 @@
#ifndef BOOT_PAGING_H
#define BOOT_PAGING_H
#include "types.h"
enum
{
PAGE_SIZE = (1 << 12),
SUPERPAGE_SIZE = (1 << 22),
};
static inline int
superpage_aligned(Address x)
{ return (x & (SUPERPAGE_SIZE - 1)) == 0; }
static inline Address trunc_page(Address x)
{ return x & ~(PAGE_SIZE - 1); }
static inline Address round_page(Address x)
{ return (x + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); }
#endif

View File

@@ -0,0 +1,17 @@
SECTIONS
{
.text :
{
*(.init)
*(.text .text.* .gnu.linkonce.t.*)
*(.fini)
*(.rodata .rodata.* .gnu.linkonce.r.*)
*(.data .data.* .gnu.linkonce.d.*)
*(.anno)
} = 0x90909090
.bss :
{
*(.bss .bss.* .gnu.linkonce.b.* COMMON)
}
}

1792
src/fiasco/src/doxygen.conf Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,36 @@
#pragma once
namespace Asm_access {
#define READ(type, inst, reg) \
inline type read(type const *mem) \
{ \
type val; \
asm volatile (inst " %[mem], %[val]" \
: [val] reg (val) : [mem] "m" (*mem)); \
return val; \
}
#define WRITE(type, inst, reg) \
inline void write(type val, type *mem) \
{ \
asm volatile (inst " %[val], %[mem]" \
: [mem] "=m" (*mem) : [val] reg (val)); \
}
READ(Unsigned8, "movb", "=q");
READ(Unsigned16, "movw", "=r");
READ(Unsigned32, "movl", "=r");
READ(Unsigned64, "movq", "=r");
READ(Mword, "movq", "=r");
WRITE(Unsigned8, "movb", "qi");
WRITE(Unsigned16, "movw", "ri");
WRITE(Unsigned32, "movl", "ri");
WRITE(Unsigned64, "movq", "r");
WRITE(Mword, "movq", "r");
#undef READ
#undef WRITE
}

View File

@@ -0,0 +1,56 @@
IMPLEMENTATION[amd64]:
EXTENSION class Io
{
public:
typedef unsigned short Port_addr;
};
/* This is a more reliable delay than a few short jmps. */
IMPLEMENT inline
void Io::iodelay()
{
asm volatile ("inb $0x80,%%al; inb $0x80,%%al" : : : "eax");
}
IMPLEMENT inline
Unsigned8 Io::in8(unsigned long port)
{
Unsigned8 tmp;
asm volatile ("inb %w1, %b0" : "=a"(tmp) : "Nd"(port));
return tmp;
}
IMPLEMENT inline
Unsigned16 Io::in16(unsigned long port)
{
Unsigned16 tmp;
asm volatile ("inw %w1, %w0" : "=a"(tmp) : "Nd"(port));
return tmp;
}
IMPLEMENT inline
Unsigned32 Io::in32(unsigned long port)
{
Unsigned32 tmp;
asm volatile ("in %w1, %0" : "=a"(tmp) : "Nd"(port));
return tmp;
}
IMPLEMENT inline
void Io::out8(Unsigned8 val, unsigned long port)
{
asm volatile ("outb %b0, %w1" : : "a"(val), "Nd"(port));
}
IMPLEMENT inline
void Io::out16(Unsigned16 val, unsigned long port)
{
asm volatile ("outw %w0, %w1" : : "a"(val), "Nd"(port));
}
IMPLEMENT inline
void Io::out32(Unsigned32 val, unsigned long port)
{
asm volatile ("out %0, %w1" : : "a"(val), "Nd"(port));
}

Some files were not shown because too many files have changed in this diff Show More