diff --git a/repos/base-hw/lib/mk/bootstrap-hw-muen.mk b/repos/base-hw/lib/mk/bootstrap-hw-muen.mk deleted file mode 100644 index d4f5568c87..0000000000 --- a/repos/base-hw/lib/mk/bootstrap-hw-muen.mk +++ /dev/null @@ -1,2 +0,0 @@ -REQUIRES = x86_64 -LIBS = bootstrap-hw-muen_off diff --git a/repos/base-hw/lib/mk/bootstrap-hw-trustzone.mk b/repos/base-hw/lib/mk/bootstrap-hw-trustzone.mk deleted file mode 100644 index 1bd2e907e4..0000000000 --- a/repos/base-hw/lib/mk/bootstrap-hw-trustzone.mk +++ /dev/null @@ -1,4 +0,0 @@ -REQUIRES = imx53 - -# add library dependencies -LIBS += bootstrap-hw-trustzone_off diff --git a/repos/base-hw/lib/mk/bootstrap-hw.inc b/repos/base-hw/lib/mk/bootstrap-hw.inc index 9caab2729b..1c3a74bbdf 100644 --- a/repos/base-hw/lib/mk/bootstrap-hw.inc +++ b/repos/base-hw/lib/mk/bootstrap-hw.inc @@ -5,13 +5,10 @@ LIBS = cxx SRC_CC += bootstrap/env.cc SRC_CC += bootstrap/init.cc SRC_CC += bootstrap/lock.cc +SRC_CC += bootstrap/log.cc SRC_CC += bootstrap/platform.cc SRC_CC += bootstrap/thread.cc -SRC_CC += core/capability.cc -SRC_CC += core/core_log.cc -SRC_CC += core/default_log.cc -SRC_CC += core/dump_alloc.cc -SRC_CC += core/kernel_log.cc +SRC_CC += hw/capability.cc SRC_CC += lib/base/allocator_avl.cc SRC_CC += lib/base/avl_tree.cc SRC_CC += lib/base/console.cc @@ -25,21 +22,20 @@ SRC_CC += lib/base/sleep.cc SRC_CC += lib/base/sliced_heap.cc SRC_CC += lib/startup/_main.cc -INC_DIR += $(HW_DIR)/src/bootstrap/include -INC_DIR += $(HW_DIR)/src/core/include -INC_DIR += $(BASE_DIR)/src/core/include +INC_DIR += $(HW_DIR)/src/bootstrap +INC_DIR += $(HW_DIR)/src/lib INC_DIR += $(HW_DIR)/src/include INC_DIR += $(BASE_DIR)/src/include +INC_DIR += $(BASE_DIR)/src/core/include # for boot_modules.h only # configure multiprocessor mode NR_OF_CPUS ?= 1 CC_OPT += -Wa,--defsym -Wa,NR_OF_CPUS=$(NR_OF_CPUS) -DNR_OF_CPUS=$(NR_OF_CPUS) +vpath base/% $(HW_DIR)/src +vpath bootstrap/% $(HW_DIR)/src +vpath hw/% $(HW_DIR)/src/lib vpath lib/base/% $(HW_DIR)/src vpath lib/muen/% $(HW_DIR)/src vpath lib/base/% $(BASE_DIR)/src vpath lib/startup/% $(BASE_DIR)/src -vpath base/% $(HW_DIR)/src -vpath core/% $(HW_DIR)/src -vpath core/% $(BASE_DIR)/src -vpath bootstrap/% $(HW_DIR)/src diff --git a/repos/base-hw/lib/mk/core-hw.inc b/repos/base-hw/lib/mk/core-hw.inc index 7de46e3e27..93501f8f95 100644 --- a/repos/base-hw/lib/mk/core-hw.inc +++ b/repos/base-hw/lib/mk/core-hw.inc @@ -11,6 +11,7 @@ INC_DIR += $(BASE_DIR)/../base-hw/src/core/include INC_DIR += $(BASE_DIR)/src/core/include INC_DIR += $(BASE_DIR)/../base-hw/src/include INC_DIR += $(BASE_DIR)/src/include +INC_DIR += $(BASE_DIR)/../base-hw/src/lib # add C++ sources SRC_CC += cpu_session_component.cc diff --git a/repos/base-hw/lib/mk/spec/arm/bootstrap-hw.inc b/repos/base-hw/lib/mk/spec/arm/bootstrap-hw.inc deleted file mode 100644 index beb9dccca8..0000000000 --- a/repos/base-hw/lib/mk/spec/arm/bootstrap-hw.inc +++ /dev/null @@ -1,4 +0,0 @@ -INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/arm -SRC_S += bootstrap/spec/arm/crt0.s - -include $(BASE_DIR)/../base-hw/lib/mk/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/arm/core-hw.inc b/repos/base-hw/lib/mk/spec/arm/core-hw.inc index a2c96e2db3..58c981a5b6 100644 --- a/repos/base-hw/lib/mk/spec/arm/core-hw.inc +++ b/repos/base-hw/lib/mk/spec/arm/core-hw.inc @@ -14,7 +14,6 @@ SRC_CC += spec/arm/kernel/pd.cc SRC_CC += spec/arm/platform_support.cc # add assembly sources -SRC_S += spec/arm/kernel/crt0.s SRC_S += spec/arm/crt0.s # include less specific configuration diff --git a/repos/base-hw/lib/mk/spec/arm_v7/bootstrap-hw.inc b/repos/base-hw/lib/mk/spec/arm_v7/bootstrap-hw.inc deleted file mode 100644 index 159730220f..0000000000 --- a/repos/base-hw/lib/mk/spec/arm_v7/bootstrap-hw.inc +++ /dev/null @@ -1,4 +0,0 @@ -INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/arm_v7 -SRC_CC += core/spec/arm_v7/cpu.cc - -include $(BASE_DIR)/../base-hw/lib/mk/spec/arm/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/arndale/bootstrap-hw.mk b/repos/base-hw/lib/mk/spec/arndale/bootstrap-hw.mk index 5fb0ea0df6..a7742f508a 100644 --- a/repos/base-hw/lib/mk/spec/arndale/bootstrap-hw.mk +++ b/repos/base-hw/lib/mk/spec/arndale/bootstrap-hw.mk @@ -1,6 +1,11 @@ -SRC_CC += bootstrap/spec/arndale/cpu.cc -SRC_CC += core/spec/arndale/pic.cc +INC_DIR += $(BASE_DIR)/../base-hw/src/bootstrap/spec/arndale + +SRC_CC += bootstrap/spec/arm/cortex_a15_cpu.cc +SRC_CC += bootstrap/spec/arndale/pic.cc +SRC_CC += bootstrap/spec/arndale/platform.cc +SRC_CC += hw/spec/arm/arm_v7_cpu.cc +SRC_S += bootstrap/spec/arm/crt0.s NR_OF_CPUS = 2 -include $(REP_DIR)/lib/mk/spec/exynos5/bootstrap-hw.inc +include $(REP_DIR)/lib/mk/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/arndale/core-hw.mk b/repos/base-hw/lib/mk/spec/arndale/core-hw.mk index b604fd5b5a..5ba3e5d5a2 100644 --- a/repos/base-hw/lib/mk/spec/arndale/core-hw.mk +++ b/repos/base-hw/lib/mk/spec/arndale/core-hw.mk @@ -8,7 +8,7 @@ INC_DIR += $(REP_DIR)/src/core/include/spec/arm_v7/virtualization # add C++ sources -SRC_CC += spec/arndale/pic.cc +SRC_CC += spec/arm_gic/pic.cc SRC_CC += spec/arndale/platform_services.cc SRC_CC += kernel/vm_thread_on.cc SRC_CC += spec/arm_v7/virtualization/kernel/vm.cc diff --git a/repos/base-hw/lib/mk/spec/cortex_a15/bootstrap-hw.inc b/repos/base-hw/lib/mk/spec/cortex_a15/bootstrap-hw.inc deleted file mode 100644 index fe2916eea5..0000000000 --- a/repos/base-hw/lib/mk/spec/cortex_a15/bootstrap-hw.inc +++ /dev/null @@ -1,4 +0,0 @@ -INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/cortex_a15 -INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/arm_gic - -include $(BASE_DIR)/../base-hw/lib/mk/spec/arm_v7/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/cortex_a9/bootstrap-hw.inc b/repos/base-hw/lib/mk/spec/cortex_a9/bootstrap-hw.inc deleted file mode 100644 index 92df72006a..0000000000 --- a/repos/base-hw/lib/mk/spec/cortex_a9/bootstrap-hw.inc +++ /dev/null @@ -1,9 +0,0 @@ -INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/smp -INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/arm_gic -INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/cortex_a9 - -SRC_CC += core/spec/arm_gic/pic.cc -SRC_CC += core/spec/cortex_a9/board.cc -SRC_CC += bootstrap/spec/cortex_a9/platform.cc - -include $(BASE_DIR)/../base-hw/lib/mk/spec/arm_v7/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/exynos5/bootstrap-hw.inc b/repos/base-hw/lib/mk/spec/exynos5/bootstrap-hw.inc deleted file mode 100644 index de2807a272..0000000000 --- a/repos/base-hw/lib/mk/spec/exynos5/bootstrap-hw.inc +++ /dev/null @@ -1,5 +0,0 @@ -INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/exynos5 -SRC_CC += bootstrap/spec/exynos5/platform.cc - -include $(BASE_DIR)/../base-hw/lib/mk/spec/cortex_a15/bootstrap-hw.inc - diff --git a/repos/base-hw/lib/mk/spec/imx53/bootstrap-hw-trustzone_off.mk b/repos/base-hw/lib/mk/spec/imx53/bootstrap-hw-trustzone_off.mk deleted file mode 100644 index d6ab75d2be..0000000000 --- a/repos/base-hw/lib/mk/spec/imx53/bootstrap-hw-trustzone_off.mk +++ /dev/null @@ -1,3 +0,0 @@ -SRC_CC += bootstrap/spec/imx53/board.cc - -include $(BASE_DIR)/../base-hw/lib/mk/spec/imx53/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/imx53/bootstrap-hw-trustzone_on.mk b/repos/base-hw/lib/mk/spec/imx53/bootstrap-hw-trustzone_on.mk deleted file mode 100644 index ae770b4886..0000000000 --- a/repos/base-hw/lib/mk/spec/imx53/bootstrap-hw-trustzone_on.mk +++ /dev/null @@ -1,3 +0,0 @@ -SRC_CC += bootstrap/spec/imx53/board_trustzone.cc - -include $(BASE_DIR)/../base-hw/lib/mk/spec/imx53/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/imx53/bootstrap-hw.inc b/repos/base-hw/lib/mk/spec/imx53/bootstrap-hw.inc deleted file mode 100644 index d86cd10cc4..0000000000 --- a/repos/base-hw/lib/mk/spec/imx53/bootstrap-hw.inc +++ /dev/null @@ -1,8 +0,0 @@ -INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/cortex_a8 -INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/imx53 -INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/imx - -SRC_CC += core/spec/imx53/pic.cc -SRC_CC += bootstrap/spec/imx53/platform.cc - -include $(BASE_DIR)/../base-hw/lib/mk/spec/arm_v7/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/imx53/bootstrap-hw.mk b/repos/base-hw/lib/mk/spec/imx53/bootstrap-hw.mk deleted file mode 100644 index eb8c6c5eff..0000000000 --- a/repos/base-hw/lib/mk/spec/imx53/bootstrap-hw.mk +++ /dev/null @@ -1 +0,0 @@ -LIBS += bootstrap-hw-trustzone diff --git a/repos/base-hw/lib/mk/spec/imx53/core-hw-trustzone_off.mk b/repos/base-hw/lib/mk/spec/imx53/core-hw-trustzone_off.mk index 843f65eb86..24b588a43d 100644 --- a/repos/base-hw/lib/mk/spec/imx53/core-hw-trustzone_off.mk +++ b/repos/base-hw/lib/mk/spec/imx53/core-hw-trustzone_off.mk @@ -8,7 +8,6 @@ # add C++ sources SRC_CC += kernel/vm_thread_off.cc SRC_CC += spec/imx53/platform_support.cc -SRC_CC += spec/imx53/pic.cc SRC_CC += platform_services.cc # include less specific configuration diff --git a/repos/base-hw/lib/mk/spec/imx53/core-hw-trustzone_on.inc b/repos/base-hw/lib/mk/spec/imx53/core-hw-trustzone_on.inc index e533574f51..1c6e8f77ad 100644 --- a/repos/base-hw/lib/mk/spec/imx53/core-hw-trustzone_on.inc +++ b/repos/base-hw/lib/mk/spec/imx53/core-hw-trustzone_on.inc @@ -12,7 +12,6 @@ INC_DIR += $(REP_DIR)/src/core/include/spec/imx53/trustzone # add C++ sources SRC_CC += spec/imx53/trustzone/platform_support.cc SRC_CC += spec/imx53/trustzone/platform_services.cc -SRC_CC += spec/imx53/trustzone/pic.cc SRC_CC += kernel/vm_thread_on.cc SRC_CC += spec/arm_v7/trustzone/kernel/vm.cc SRC_CC += spec/arm_v7/vm_session_component.cc diff --git a/repos/base-hw/lib/mk/spec/imx53/core-hw.inc b/repos/base-hw/lib/mk/spec/imx53/core-hw.inc index b0721fb4fd..71449fc21a 100644 --- a/repos/base-hw/lib/mk/spec/imx53/core-hw.inc +++ b/repos/base-hw/lib/mk/spec/imx53/core-hw.inc @@ -9,5 +9,7 @@ INC_DIR += $(REP_DIR)/src/core/include/spec/imx53 INC_DIR += $(REP_DIR)/src/core/include/spec/imx +SRC_CC += spec/imx53/pic.cc + # include less specific configuration include $(REP_DIR)/lib/mk/spec/cortex_a8/core-hw.inc diff --git a/repos/base-hw/lib/mk/spec/imx53_qsb/bootstrap-hw.mk b/repos/base-hw/lib/mk/spec/imx53_qsb/bootstrap-hw.mk new file mode 100644 index 0000000000..54946fea06 --- /dev/null +++ b/repos/base-hw/lib/mk/spec/imx53_qsb/bootstrap-hw.mk @@ -0,0 +1,16 @@ +INC_DIR += $(BASE_DIR)/../base-hw/src/bootstrap/spec/imx53_qsb + +SRC_S += bootstrap/spec/arm/crt0.s + +SRC_CC += bootstrap/spec/arm/cortex_a8_mmu.cc +SRC_CC += bootstrap/spec/arm/cpu.cc +SRC_CC += bootstrap/spec/arm/imx_tzic.cc +SRC_CC += hw/spec/arm/arm_v7_cpu.cc + +ifneq ($(filter-out $(SPECS),trustzone),) +SRC_CC += bootstrap/spec/imx53_qsb/platform.cc +else +SRC_CC += bootstrap/spec/imx53_qsb/platform_trustzone.cc +endif + +include $(BASE_DIR)/../base-hw/lib/mk/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/imx6/bootstrap-hw.mk b/repos/base-hw/lib/mk/spec/imx6/bootstrap-hw.mk deleted file mode 100644 index 8418e15be8..0000000000 --- a/repos/base-hw/lib/mk/spec/imx6/bootstrap-hw.mk +++ /dev/null @@ -1,8 +0,0 @@ -INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/imx6 -INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/imx - -SRC_CC += bootstrap/spec/imx6/platform.cc - -NR_OF_CPUS = 4 - -include $(BASE_DIR)/../base-hw/lib/mk/spec/cortex_a9/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/muen/bootstrap-hw-muen.mk b/repos/base-hw/lib/mk/spec/muen/bootstrap-hw-muen.mk deleted file mode 100644 index 177f7c5de0..0000000000 --- a/repos/base-hw/lib/mk/spec/muen/bootstrap-hw-muen.mk +++ /dev/null @@ -1 +0,0 @@ -LIBS += bootstrap-hw-muen_on diff --git a/repos/base-hw/lib/mk/spec/odroid_xu/bootstrap-hw.mk b/repos/base-hw/lib/mk/spec/odroid_xu/bootstrap-hw.mk index 2163e99f2e..cb1f113a92 100644 --- a/repos/base-hw/lib/mk/spec/odroid_xu/bootstrap-hw.mk +++ b/repos/base-hw/lib/mk/spec/odroid_xu/bootstrap-hw.mk @@ -1,4 +1,9 @@ -SRC_CC += bootstrap/spec/odroid_xu/cpu.cc -SRC_CC += core/spec/arm_gic/pic.cc +INC_DIR += $(BASE_DIR)/../base-hw/src/bootstrap/spec/odroid_xu -include $(REP_DIR)/lib/mk/spec/exynos5/bootstrap-hw.inc +SRC_CC += bootstrap/spec/arm/cortex_a15_cpu.cc +SRC_CC += bootstrap/spec/arm/pic.cc +SRC_CC += bootstrap/spec/odroid_xu/platform.cc +SRC_CC += hw/spec/arm/arm_v7_cpu.cc +SRC_S += bootstrap/spec/arm/crt0.s + +include $(REP_DIR)/lib/mk/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/panda/bootstrap-hw.mk b/repos/base-hw/lib/mk/spec/panda/bootstrap-hw.mk index 339d72e14e..c5cf0f769e 100644 --- a/repos/base-hw/lib/mk/spec/panda/bootstrap-hw.mk +++ b/repos/base-hw/lib/mk/spec/panda/bootstrap-hw.mk @@ -1,8 +1,11 @@ -INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/panda -INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/tl16c750 - -SRC_CC += bootstrap/spec/panda/platform.cc - NR_OF_CPUS = 2 -include $(BASE_DIR)/../base-hw/lib/mk/spec/cortex_a9/bootstrap-hw.inc +INC_DIR += $(BASE_DIR)/../base-hw/src/bootstrap/spec/panda +SRC_CC += bootstrap/spec/arm/cpu.cc +SRC_CC += bootstrap/spec/arm/cortex_a9_mmu.cc +SRC_CC += bootstrap/spec/arm/pic.cc +SRC_CC += bootstrap/spec/panda/platform.cc +SRC_CC += hw/spec/arm/arm_v7_cpu.cc +SRC_S += bootstrap/spec/arm/crt0.s + +include $(BASE_DIR)/../base-hw/lib/mk/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/pbxa9/bootstrap-hw.mk b/repos/base-hw/lib/mk/spec/pbxa9/bootstrap-hw.mk index c01bc7973c..6180773401 100644 --- a/repos/base-hw/lib/mk/spec/pbxa9/bootstrap-hw.mk +++ b/repos/base-hw/lib/mk/spec/pbxa9/bootstrap-hw.mk @@ -1,6 +1,11 @@ -INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/pbxa9 -INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/pl011 +INC_DIR += $(BASE_DIR)/../base-hw/src/bootstrap/spec/pbxa9 +SRC_S += bootstrap/spec/arm/crt0.s + +SRC_CC += bootstrap/spec/arm/cpu.cc +SRC_CC += bootstrap/spec/arm/cortex_a9_mmu.cc +SRC_CC += bootstrap/spec/arm/pic.cc SRC_CC += bootstrap/spec/pbxa9/platform.cc +SRC_CC += hw/spec/arm/arm_v7_cpu.cc -include $(BASE_DIR)/../base-hw/lib/mk/spec/cortex_a9/bootstrap-hw.inc +include $(BASE_DIR)/../base-hw/lib/mk/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/riscv/bootstrap-hw.mk b/repos/base-hw/lib/mk/spec/riscv/bootstrap-hw.mk index e8d1ab5f64..3e3e0ff06e 100644 --- a/repos/base-hw/lib/mk/spec/riscv/bootstrap-hw.mk +++ b/repos/base-hw/lib/mk/spec/riscv/bootstrap-hw.mk @@ -1,11 +1,8 @@ -INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/riscv +INC_DIR += $(BASE_DIR)/../base-hw/src/bootstrap/spec/riscv -SRC_CC += bootstrap/spec/riscv/cpu.cc -SRC_CC += bootstrap/spec/riscv/exception_vector.cc SRC_CC += bootstrap/spec/riscv/platform.cc SRC_CC += lib/base/riscv/kernel/interface.cc SRC_S += bootstrap/spec/riscv/crt0.s -SRC_S += core/spec/riscv/mode_transition.s +SRC_S += bootstrap/spec/riscv/exception_vector.s include $(BASE_DIR)/../base-hw/lib/mk/bootstrap-hw.inc - diff --git a/repos/base-hw/lib/mk/spec/riscv/core-hw.mk b/repos/base-hw/lib/mk/spec/riscv/core-hw.mk index 9746c28f4b..d3f66c88fd 100644 --- a/repos/base-hw/lib/mk/spec/riscv/core-hw.mk +++ b/repos/base-hw/lib/mk/spec/riscv/core-hw.mk @@ -10,11 +10,9 @@ SRC_CC += spec/riscv/kernel/thread.cc SRC_CC += spec/riscv/kernel/pd.cc SRC_CC += spec/riscv/kernel/cpu.cc SRC_CC += spec/riscv/platform_support.cc -SRC_CC += spec/riscv/cpu.cc #add assembly sources SRC_S += spec/riscv/mode_transition.s -SRC_S += spec/riscv/kernel/crt0.s SRC_S += spec/riscv/crt0.s # include less specific configuration diff --git a/repos/base-hw/lib/mk/spec/rpi/bootstrap-hw.mk b/repos/base-hw/lib/mk/spec/rpi/bootstrap-hw.mk index aca694531a..0588218dc0 100644 --- a/repos/base-hw/lib/mk/spec/rpi/bootstrap-hw.mk +++ b/repos/base-hw/lib/mk/spec/rpi/bootstrap-hw.mk @@ -1,10 +1,7 @@ -INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/rpi -INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/arm_v6 -INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/pl011 +INC_DIR += $(BASE_DIR)/../base-hw/src/bootstrap/spec/rpi -SRC_CC += bootstrap/spec/arm_v6/cpu.cc SRC_CC += bootstrap/spec/rpi/platform.cc -SRC_CC += core/spec/rpi/pic.cc - -include $(BASE_DIR)/../base-hw/lib/mk/spec/arm/bootstrap-hw.inc +SRC_CC += hw/spec/arm/arm_v6_cpu.cc +SRC_S += bootstrap/spec/arm/crt0.s +include $(BASE_DIR)/../base-hw/lib/mk/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/trustzone/bootstrap-hw-trustzone.mk b/repos/base-hw/lib/mk/spec/trustzone/bootstrap-hw-trustzone.mk deleted file mode 100644 index e09ee0083c..0000000000 --- a/repos/base-hw/lib/mk/spec/trustzone/bootstrap-hw-trustzone.mk +++ /dev/null @@ -1 +0,0 @@ -LIBS += bootstrap-hw-trustzone_on diff --git a/repos/base-hw/lib/mk/spec/usb_armory/bootstrap-hw.mk b/repos/base-hw/lib/mk/spec/usb_armory/bootstrap-hw.mk index fbdc97cef2..9b978e2fb2 100644 --- a/repos/base-hw/lib/mk/spec/usb_armory/bootstrap-hw.mk +++ b/repos/base-hw/lib/mk/spec/usb_armory/bootstrap-hw.mk @@ -1,9 +1,11 @@ -INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/cortex_a8 -INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/imx53 -INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/imx +INC_DIR += $(BASE_DIR)/../base-hw/src/bootstrap/spec/usb_armory -SRC_CC += core/spec/imx53/pic.cc -SRC_CC += bootstrap/spec/imx53/platform.cc -SRC_CC += bootstrap/spec/imx53/board_trustzone.cc +SRC_S += bootstrap/spec/arm/crt0.s -include $(BASE_DIR)/../base-hw/lib/mk/spec/arm_v7/bootstrap-hw.inc +SRC_CC += bootstrap/spec/arm/cortex_a8_mmu.cc +SRC_CC += bootstrap/spec/arm/cpu.cc +SRC_CC += bootstrap/spec/arm/imx_tzic.cc +SRC_CC += bootstrap/spec/usb_armory/platform.cc +SRC_CC += hw/spec/arm/arm_v7_cpu.cc + +include $(BASE_DIR)/../base-hw/lib/mk/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/wand_quad/bootstrap-hw.mk b/repos/base-hw/lib/mk/spec/wand_quad/bootstrap-hw.mk new file mode 100644 index 0000000000..f172feac8a --- /dev/null +++ b/repos/base-hw/lib/mk/spec/wand_quad/bootstrap-hw.mk @@ -0,0 +1,13 @@ +INC_DIR += $(BASE_DIR)/../base-hw/src/bootstrap/spec/wand_quad + +SRC_S += bootstrap/spec/arm/crt0.s + +SRC_CC += bootstrap/spec/arm/cpu.cc +SRC_CC += bootstrap/spec/arm/cortex_a9_mmu.cc +SRC_CC += bootstrap/spec/arm/pic.cc +SRC_CC += bootstrap/spec/wand_quad/platform.cc +SRC_CC += hw/spec/arm/arm_v7_cpu.cc + +NR_OF_CPUS = 4 + +include $(BASE_DIR)/../base-hw/lib/mk/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/x86_64/bootstrap-hw-muen_off.mk b/repos/base-hw/lib/mk/spec/x86_64/bootstrap-hw-muen_off.mk deleted file mode 100644 index c311fffb7d..0000000000 --- a/repos/base-hw/lib/mk/spec/x86_64/bootstrap-hw-muen_off.mk +++ /dev/null @@ -1,5 +0,0 @@ -SRC_CC += core/spec/x86_64/pic.cc -SRC_CC += bootstrap/spec/x86_64/platform.cc -SRC_S += bootstrap/spec/x86_64/crt0_translation_table.s - -include $(BASE_DIR)/../base-hw/lib/mk/spec/x86_64/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/x86_64/bootstrap-hw-muen_on.mk b/repos/base-hw/lib/mk/spec/x86_64/bootstrap-hw-muen_on.mk deleted file mode 100644 index 7e60275a21..0000000000 --- a/repos/base-hw/lib/mk/spec/x86_64/bootstrap-hw-muen_on.mk +++ /dev/null @@ -1,9 +0,0 @@ -REQUIRES = muen - -INC_DIR += $(REP_DIR)/src/core/include/spec/x86_64/muen - -SRC_CC += lib/muen/sinfo.cc -SRC_CC += bootstrap/spec/x86_64/platform_muen.cc -SRC_S += bootstrap/spec/x86_64/crt0_translation_table_muen.s - -include $(BASE_DIR)/../base-hw/lib/mk/spec/x86_64/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/x86_64/bootstrap-hw.inc b/repos/base-hw/lib/mk/spec/x86_64/bootstrap-hw.inc deleted file mode 100644 index 611b678bbc..0000000000 --- a/repos/base-hw/lib/mk/spec/x86_64/bootstrap-hw.inc +++ /dev/null @@ -1,5 +0,0 @@ -INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/x86_64 - -SRC_S += bootstrap/spec/x86_64/crt0.s - -include $(BASE_DIR)/../base-hw/lib/mk/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/x86_64/bootstrap-hw.mk b/repos/base-hw/lib/mk/spec/x86_64/bootstrap-hw.mk index b967054948..f6b401a27a 100644 --- a/repos/base-hw/lib/mk/spec/x86_64/bootstrap-hw.mk +++ b/repos/base-hw/lib/mk/spec/x86_64/bootstrap-hw.mk @@ -1 +1,14 @@ -LIBS = bootstrap-hw-muen +INC_DIR += $(BASE_DIR)/../base-hw/src/bootstrap/spec/x86_64 + +SRC_S += bootstrap/spec/x86_64/crt0.s + +ifneq ($(filter-out $(SPECS),muen),) +SRC_CC += bootstrap/spec/x86_64/platform.cc +SRC_S += bootstrap/spec/x86_64/crt0_translation_table.s +else +SRC_CC += lib/muen/sinfo.cc +SRC_CC += bootstrap/spec/x86_64/platform_muen.cc +SRC_S += bootstrap/spec/x86_64/crt0_translation_table_muen.s +endif + +include $(BASE_DIR)/../base-hw/lib/mk/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/x86_64/core-hw.inc b/repos/base-hw/lib/mk/spec/x86_64/core-hw.inc index 06e70d79ab..8808ffbe13 100644 --- a/repos/base-hw/lib/mk/spec/x86_64/core-hw.inc +++ b/repos/base-hw/lib/mk/spec/x86_64/core-hw.inc @@ -10,7 +10,6 @@ INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/x86_64 # add assembly sources SRC_S += spec/x86_64/mode_transition.s -SRC_S += spec/x86_64/kernel/crt0.s SRC_S += spec/x86_64/crt0.s # add C++ sources diff --git a/repos/base-hw/lib/mk/spec/zynq/bootstrap-hw.inc b/repos/base-hw/lib/mk/spec/zynq/bootstrap-hw.inc deleted file mode 100644 index cd4cbd2568..0000000000 --- a/repos/base-hw/lib/mk/spec/zynq/bootstrap-hw.inc +++ /dev/null @@ -1,5 +0,0 @@ -INC_DIR += $(BASE_DIR)/../base-hw/src/core/include/spec/zynq - -SRC_CC += bootstrap/spec/zynq/platform.cc - -include $(BASE_DIR)/../base-hw/lib/mk/spec/cortex_a9/bootstrap-hw.inc diff --git a/repos/base-hw/lib/mk/spec/zynq_qemu/bootstrap-hw.mk b/repos/base-hw/lib/mk/spec/zynq_qemu/bootstrap-hw.mk index ec85ee3cc9..e15b86e72c 100644 --- a/repos/base-hw/lib/mk/spec/zynq_qemu/bootstrap-hw.mk +++ b/repos/base-hw/lib/mk/spec/zynq_qemu/bootstrap-hw.mk @@ -1,4 +1,11 @@ -INC_DIR += $(REP_DIR)/src/core/include/spec/xilinx_uartps_0 -INC_DIR += $(REP_DIR)/src/core/include/spec/zynq_qemu +INC_DIR += $(BASE_DIR)/../base-hw/src/bootstrap/spec/zynq -include $(BASE_DIR)/../base-hw/lib/mk/spec/zynq/bootstrap-hw.inc +SRC_S += bootstrap/spec/arm/crt0.s + +SRC_CC += bootstrap/spec/arm/cpu.cc +SRC_CC += bootstrap/spec/arm/cortex_a9_mmu.cc +SRC_CC += bootstrap/spec/arm/pic.cc +SRC_CC += bootstrap/spec/zynq/platform.cc +SRC_CC += hw/spec/arm/arm_v7_cpu.cc + +include $(BASE_DIR)/../base-hw/lib/mk/bootstrap-hw.inc diff --git a/repos/base-hw/src/bootstrap/env.cc b/repos/base-hw/src/bootstrap/env.cc index d350046348..f4fc94168a 100644 --- a/repos/base-hw/src/bootstrap/env.cc +++ b/repos/base-hw/src/bootstrap/env.cc @@ -11,11 +11,8 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* base includes */ #include - -/* core includes */ -#include +#include Genode::Env_deprecated * Genode::env_deprecated() { diff --git a/repos/base-hw/src/bootstrap/init.cc b/repos/base-hw/src/bootstrap/init.cc index 885719ef75..8c25f83a16 100644 --- a/repos/base-hw/src/bootstrap/init.cc +++ b/repos/base-hw/src/bootstrap/init.cc @@ -18,13 +18,14 @@ #include #include -Platform & platform() { return *unmanaged_singleton(); } +Bootstrap::Platform & Bootstrap::platform() { + return *unmanaged_singleton(); } extern "C" void init() __attribute__ ((noreturn)); extern "C" void init() { Genode::init_log(); - platform().enable_mmu(); - platform().start_core(); + Bootstrap::platform().enable_mmu(); + Bootstrap::platform().start_core(); } diff --git a/repos/base-hw/src/bootstrap/lock.cc b/repos/base-hw/src/bootstrap/lock.cc index bbe23c3286..c8f6661902 100644 --- a/repos/base-hw/src/bootstrap/lock.cc +++ b/repos/base-hw/src/bootstrap/lock.cc @@ -12,7 +12,7 @@ */ #include -#include +#include Genode::Cancelable_lock::Cancelable_lock(Genode::Cancelable_lock::State state) : _state(state), _owner(nullptr) { } diff --git a/repos/base-hw/src/bootstrap/log.cc b/repos/base-hw/src/bootstrap/log.cc new file mode 100644 index 0000000000..e8f4ebe754 --- /dev/null +++ b/repos/base-hw/src/bootstrap/log.cc @@ -0,0 +1,60 @@ +/* + * \brief Access to the log facility + * \author Norman Feske + * \author Stefan Kalkowski + * \date 2016-05-03 + */ + +/* + * Copyright (C) 2016 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +/* Genode includes */ +#include + +/* base-internal includes */ +#include +#include +#include + +#include + +using namespace Bootstrap; +using namespace Genode; + +struct Buffer +{ + struct Write_fn + { + Serial & serial; + + Write_fn(Serial & serial) : serial(serial) {} + + void operator () (char const *s) + { + enum { LINE_FEED = 10, CARRIAGE_RETURN = 13 }; + + for (unsigned i = 0; i < Genode::strlen(s); i++) { + if (s[i] == LINE_FEED) serial.put_char(CARRIAGE_RETURN); + serial.put_char(s[i]); + } + } + }; + + enum { BAUD_RATE = 115200 }; + + Serial serial { UART_BASE, UART_CLOCK, BAUD_RATE }; + Write_fn function { serial }; + Buffered_output<512, Write_fn> buffer { function }; + Log log { buffer }; +}; + + +Genode::Log &Genode::Log::log() { + return unmanaged_singleton()->log; } + + +void Genode::init_log() { }; diff --git a/repos/base-hw/src/bootstrap/platform.cc b/repos/base-hw/src/bootstrap/platform.cc index 5a29994928..c57497c356 100644 --- a/repos/base-hw/src/bootstrap/platform.cc +++ b/repos/base-hw/src/bootstrap/platform.cc @@ -11,14 +11,14 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* base-internal includes */ #include +#include -/* core includes */ -#include #include #include +using namespace Bootstrap; + /***************************** ** Platform::Ram_allocator ** @@ -27,6 +27,7 @@ void * Platform::Ram_allocator::alloc_aligned(size_t size, unsigned align) { using namespace Genode; + using namespace Hw; void * ret; assert(Base::alloc_aligned(round_page(size), &ret, @@ -55,18 +56,16 @@ void Platform::Ram_allocator::remove(Memory_region const & region) { ******************/ Platform::Pd::Pd(Platform::Ram_allocator & alloc) -: table_base(alloc.alloc_aligned(sizeof(Bootinfo::Table), - Bootinfo::Table::ALIGNM_LOG2)), - allocator_base(alloc.alloc_aligned(sizeof(Bootinfo::Table_allocator), - Bootinfo::Table::ALIGNM_LOG2)), - table(*Genode::construct_at(table_base)), - allocator(*Genode::construct_at(allocator_base)) +: table_base(alloc.alloc_aligned(sizeof(Table), Table::ALIGNM_LOG2)), + array_base(alloc.alloc_aligned(sizeof(Table_array), Table::ALIGNM_LOG2)), + table(*Genode::construct_at(table_base)), + array(*Genode::construct_at(array_base)) { using namespace Genode; map_insert(Mapping((addr_t)table_base, (addr_t)table_base, - sizeof(Bootinfo::Table), PAGE_FLAGS_KERN_DATA)); - map_insert(Mapping((addr_t)allocator_base, (addr_t)allocator_base, - sizeof(Bootinfo::Table_allocator), PAGE_FLAGS_KERN_DATA)); + sizeof(Table), Hw::PAGE_FLAGS_KERN_DATA)); + map_insert(Mapping((addr_t)array_base, (addr_t)array_base, + sizeof(Table_array), Hw::PAGE_FLAGS_KERN_DATA)); } @@ -74,8 +73,8 @@ void Platform::Pd::map(Mapping m) { try { table.insert_translation(m.virt(), m.phys(), m.size(), m.flags(), - allocator.alloc()); - } catch(Genode::Allocator::Out_of_memory) { + array.alloc()); + } catch (Hw::Out_of_tables &) { Genode::error("translation table needs to much RAM"); } catch (...) { Genode::error("invalid mapping ", m); @@ -97,6 +96,7 @@ void Platform::Pd::map_insert(Mapping m) addr_t Platform::_load_elf() { using namespace Genode; + using namespace Hw; addr_t start = ~0UL; addr_t end = 0; @@ -166,7 +166,7 @@ Platform::Platform() /* temporarily map all bootstrap memory 1:1 for transition to core */ // FIXME do not insert as mapping for core core_pd->map_insert(Mapping(bootstrap_region.base, bootstrap_region.base, - bootstrap_region.size, PAGE_FLAGS_KERN_TEXT)); + bootstrap_region.size, Hw::PAGE_FLAGS_KERN_TEXT)); /* map memory-mapped I/O for core */ board.core_mmio.for_each_mapping([&] (Mapping const & m) { @@ -176,11 +176,12 @@ Platform::Platform() addr_t const elf_end = _load_elf(); /* setup boot info page */ - void * bi_base = ram_alloc.alloc(sizeof(Bootinfo)); - core_pd->map_insert(Mapping((addr_t)bi_base, elf_end, sizeof(Bootinfo), - PAGE_FLAGS_KERN_TEXT)); - Bootinfo & bootinfo = - *construct_at(bi_base, &core_pd->table, &core_pd->allocator, + void * bi_base = ram_alloc.alloc(sizeof(Boot_info)); + core_pd->map_insert(Mapping((addr_t)bi_base, elf_end, sizeof(Boot_info), + Hw::PAGE_FLAGS_KERN_TEXT)); + Boot_info & bootinfo = + *construct_at(bi_base, (addr_t)&core_pd->table, + (addr_t)&core_pd->array, core_pd->mappings, board.core_mmio); /* add all left RAM to bootinfo */ diff --git a/repos/base-hw/src/bootstrap/include/platform.h b/repos/base-hw/src/bootstrap/platform.h similarity index 71% rename from repos/base-hw/src/bootstrap/include/platform.h rename to repos/base-hw/src/bootstrap/platform.h index 7dde4a2606..35ad183d21 100644 --- a/repos/base-hw/src/bootstrap/include/platform.h +++ b/repos/base-hw/src/bootstrap/platform.h @@ -11,40 +11,40 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _PLATFORM_H_ -#define _PLATFORM_H_ +#ifndef _SRC__BOOTSTRAP__PLATFORM_H_ +#define _SRC__BOOTSTRAP__PLATFORM_H_ -/* Genode includes */ #include #include +#include #include -/* core includes */ -#include #include -#include -#include -#include -using Genode::addr_t; -using Genode::size_t; -using Genode::Bootinfo; -using Genode::Core_mmio; -using Genode::Mapping; -using Genode::Memory_region; -using Genode::Memory_region_array; -using Genode::Rom_module; +namespace Bootstrap { + struct Platform; -class Platform + using Genode::addr_t; + using Genode::size_t; + using Hw::Boot_info; + using Hw::Mmio_space; + using Hw::Mapping; + using Hw::Memory_region; + using Hw::Memory_region_array; + + extern Platform & platform(); +} + +class Bootstrap::Platform { private: - struct Board : Genode::Board + struct Board : Genode::Board_base { Memory_region_array early_ram_regions; Memory_region_array late_ram_regions; - Core_mmio const core_mmio; + Mmio_space const core_mmio; Board(); }; @@ -80,7 +80,7 @@ class Platform _block_tree().for_each([&] (Block const & b) { if (!b.used()) - functor(Genode::Memory_region(b.addr(), b.size())); + functor(Memory_region(b.addr(), b.size())); }); } }; @@ -88,11 +88,14 @@ class Platform struct Pd { - void * const table_base; - void * const allocator_base; - Bootinfo::Table & table; - Bootinfo::Table_allocator & allocator; - Bootinfo::Mapping_pool mappings; + using Table = Hw::Page_table; + using Table_array = Table::Allocator::Array; + + void * const table_base; + void * const array_base; + Table & table; + Table_array & array; + Boot_info::Mapping_pool mappings; Pd(Ram_allocator & alloc); @@ -117,8 +120,8 @@ class Platform }; Board board; - Genode::Cpu cpu; - Genode::Pic pic; + Bootstrap::Cpu cpu; + Bootstrap::Pic pic; Ram_allocator ram_alloc; Memory_region const bootstrap_region; Genode::Constructible core_pd; @@ -131,12 +134,8 @@ class Platform Platform(); - static addr_t mmio_to_virt(addr_t mmio) { return mmio; } - void enable_mmu(); void start_core() __attribute__((noreturn)); }; -extern Platform & platform(); - -#endif /* _PLATFORM_H_ */ +#endif /* _SRC__BOOTSTRAP__PLATFORM_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/arm/cortex_a15_cpu.cc b/repos/base-hw/src/bootstrap/spec/arm/cortex_a15_cpu.cc new file mode 100644 index 0000000000..a5b658d83b --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/arm/cortex_a15_cpu.cc @@ -0,0 +1,61 @@ +/* + * \brief MMU initialization for Cortex A15 + * \author Stefan Kalkowski + * \date 2017-04-09 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + + +#include + +void Bootstrap::Cpu::enable_mmu_and_caches(Genode::addr_t table) +{ + /* invalidate TLB */ + Tlbiall::write(0); + + enum Memory_attributes { + DEVICE_MEMORY = 0x04, + NORMAL_MEMORY_UNCACHED = 0x44, + NORMAL_MEMORY_CACHED = 0xff, + }; + + /* set memory attributes in indirection register */ + Mair0::access_t mair0 = 0; + Mair0::Attr0::set(mair0, NORMAL_MEMORY_UNCACHED); + Mair0::Attr1::set(mair0, DEVICE_MEMORY); + Mair0::Attr2::set(mair0, NORMAL_MEMORY_CACHED); + Mair0::Attr3::set(mair0, DEVICE_MEMORY); + Mair0::write(mair0); + + /* do not use domains, but permission bits in table */ + Dacr::write(Dacr::D0::bits(1)); + + Ttbr_64bit::access_t ttbr0 = Ttbr_64bit::Ba::masked(table); + Ttbr_64bit::Asid::set(ttbr0, 0); + Ttbr0_64bit::write(ttbr0); + + Ttbcr::access_t ttbcr = 0; + Ttbcr::Irgn0::set(ttbcr, 1); + Ttbcr::Orgn0::set(ttbcr, 1); + Ttbcr::Sh0::set(ttbcr, 0b10); + Ttbcr::Eae::set(ttbcr, 1); + Ttbcr::write(ttbcr); + + Sctlr::access_t sctlr = Sctlr::read(); + Sctlr::C::set(sctlr, 1); + Sctlr::I::set(sctlr, 1); + Sctlr::V::set(sctlr, 1); + Sctlr::A::set(sctlr, 0); + Sctlr::M::set(sctlr, 1); + Sctlr::Z::set(sctlr, 1); + Sctlr::write(sctlr); + + /* invalidate branch predictor */ + Bpiall::write(0); +} diff --git a/repos/base-hw/src/bootstrap/spec/arm/cortex_a8_mmu.cc b/repos/base-hw/src/bootstrap/spec/arm/cortex_a8_mmu.cc new file mode 100644 index 0000000000..e53f87440b --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/arm/cortex_a8_mmu.cc @@ -0,0 +1,20 @@ +/* + * \brief MMU initialization for Cortex A8 + * \author Stefan Kalkowski + * \date 2015-12-09 + */ + +/* + * Copyright (C) 2015-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#include + +void Bootstrap::Platform::enable_mmu() +{ + Cpu::Sctlr::init(); + Cpu::enable_mmu_and_caches((addr_t)core_pd->table_base); +} diff --git a/repos/base-hw/src/bootstrap/spec/arm/cortex_a8_page_table.h b/repos/base-hw/src/bootstrap/spec/arm/cortex_a8_page_table.h new file mode 100644 index 0000000000..fb6f9c5fe8 --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/arm/cortex_a8_page_table.h @@ -0,0 +1,26 @@ +/* + * \brief Cortex A9 specific page table format + * \author Stefan Kalkowski + * \date 2017-02-20 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__BOOTSTRAP__SPEC__ARM__CORTEX_A8_PAGE_TABLE_H_ +#define _SRC__BOOTSTRAP__SPEC__ARM__CORTEX_A8_PAGE_TABLE_H_ + +#include + +constexpr unsigned Hw::Page_table::Descriptor_base::_device_tex() { + return 2; } + +constexpr bool Hw::Page_table::Descriptor_base::_smp() { return false; } + +void Hw::Page_table::_translation_added(unsigned long, unsigned long) { } + +#endif /* _SRC__BOOTSTRAP__SPEC__ARM__CORTEX_A8_PAGE_TABLE_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/arm/cortex_a9_actlr.h b/repos/base-hw/src/bootstrap/spec/arm/cortex_a9_actlr.h new file mode 100644 index 0000000000..1b041abfaf --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/arm/cortex_a9_actlr.h @@ -0,0 +1,33 @@ +/* + * \brief Cortex A9 specific ACTLR register settings + * \author Stefan Kalkowski + * \date 2017-02-20 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__BOOTSTRAP__SPEC__ARM__CORTEX_A9_ACTLR_H_ +#define _SRC__BOOTSTRAP__SPEC__ARM__CORTEX_A9_ACTLR_H_ + +#include + +namespace Bootstrap { struct Actlr; } + +struct Bootstrap::Actlr : Bootstrap::Cpu::Actlr +{ + struct Smp : Bitfield<6, 1> { }; + + static void enable_smp() + { + auto v = read(); + Smp::set(v, 1); + write(v); + } +}; + +#endif /* _SRC__BOOTSTRAP__SPEC__ARM__CORTEX_A9_ACTLR_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/cortex_a9/platform.cc b/repos/base-hw/src/bootstrap/spec/arm/cortex_a9_mmu.cc similarity index 75% rename from repos/base-hw/src/bootstrap/spec/cortex_a9/platform.cc rename to repos/base-hw/src/bootstrap/spec/arm/cortex_a9_mmu.cc index 1c42477eda..8d0df51425 100644 --- a/repos/base-hw/src/bootstrap/spec/cortex_a9/platform.cc +++ b/repos/base-hw/src/bootstrap/spec/arm/cortex_a9_mmu.cc @@ -1,5 +1,5 @@ /* - * \brief Cpu class implementation specific to Cortex A9 SMP + * \brief MMU initialization for Cortex A9 SMP * \author Stefan Kalkowski * \date 2015-12-09 */ @@ -12,13 +12,12 @@ */ #include +#include +#include +#include -/* core includes */ -#include #include -//using namespace Kernel; - /* entrypoint for non-boot CPUs */ extern "C" void * _start_setup_stack; @@ -30,14 +29,14 @@ class Cpu_counter { private: - Kernel::Lock _lock; + Hw::Spin_lock _lock; volatile int _value = 0; public: void inc() { - Kernel::Lock::Guard guard(_lock); + Hw::Spin_lock::Guard guard(_lock); Genode::memory_barrier(); _value++; } @@ -67,7 +66,9 @@ struct Scu : Genode::Mmio struct Cpu3_way : Bitfield<12, 4> { }; }; - Scu(Genode::addr_t mmio) : Genode::Mmio(mmio) { } + using Memory_map = Hw::Cpu_memory_map; + + Scu() : Genode::Mmio(Memory_map::SCU_MMIO_BASE) { } void invalidate() { @@ -96,9 +97,10 @@ struct Scu : Genode::Mmio * * See ARM's Cortex-A9 MPCore TRM r2p0 in section 5.3.5 for more details */ -void Platform::enable_mmu() +void Bootstrap::Platform::enable_mmu() { - using Genode::Cpu; + using namespace Bootstrap; + static volatile bool primary_cpu = true; static Cpu_counter data_cache_invalidated; static Cpu_counter data_cache_enabled; @@ -108,61 +110,57 @@ void Platform::enable_mmu() if (primary) primary_cpu = false; Cpu::Sctlr::init(); - Cpu::Psr::write(Cpu::Psr::init_kernel()); + Cpu::Cpsr::init(); /* locally initialize interrupt controller */ pic.init_cpu_local(); - cpu.invalidate_inner_data_cache(); + Cpu::invalidate_data_cache(); data_cache_invalidated.inc(); /* primary cpu wakes up all others */ - if (primary && NR_OF_CPUS > 1) { - board.wake_up_all_cpus(&_start_setup_stack); - - /* send an IPI to all other cpus */ - pic.send_ipi(); - } + if (primary && NR_OF_CPUS > 1) + Cpu::wake_up_all_cpus(&_start_setup_stack); /* wait for other cores' data cache invalidation */ data_cache_invalidated.wait_for(NR_OF_CPUS); if (primary) { - Scu scu(Board::SCU_MMIO_BASE); + Scu scu; scu.invalidate(); - Board::L2_cache l2_cache(Board::PL310_MMIO_BASE); + Bootstrap::L2_cache l2_cache(Board::PL310_MMIO_BASE); l2_cache.disable(); l2_cache.invalidate(); - scu.enable(board.errata(Platform::Board::ARM_764369)); + scu.enable(Cpu::errata(Cpu::ARM_764369)); } /* secondary cpus wait for the primary's cache activation */ if (!primary) data_cache_enabled.wait_for(1); - cpu.enable_mmu_and_caches((Genode::addr_t)core_pd->table_base); + Cpu::enable_mmu_and_caches((Genode::addr_t)core_pd->table_base); data_cache_enabled.inc(); - cpu.clean_invalidate_inner_data_cache(); + Cpu::clean_invalidate_data_cache(); /* wait for other cores' data cache activation */ data_cache_enabled.wait_for(NR_OF_CPUS); if (primary) { - Board::L2_cache l2_cache(board.core_mmio.virt_addr(Board::PL310_MMIO_BASE)); + Bootstrap::L2_cache l2_cache(board.core_mmio.virt_addr(Board::PL310_MMIO_BASE)); l2_cache.enable(); } /* secondary cpus wait for the primary's coherency activation */ if (!primary) smp_coherency_enabled.wait_for(1); - Cpu::Actlr::enable_smp(board); + Actlr::enable_smp(); smp_coherency_enabled.inc(); /* * strangely, some older versions (imx6) seem to not work cache coherent * until SMP bit is set, so write back the variable here. */ - cpu.clean_invalidate_inner_data_cache(); + Cpu::clean_invalidate_data_cache(); /* wait for other cores' coherency activation */ smp_coherency_enabled.wait_for(NR_OF_CPUS); diff --git a/repos/base-hw/src/bootstrap/spec/arm/cortex_a9_page_table.h b/repos/base-hw/src/bootstrap/spec/arm/cortex_a9_page_table.h new file mode 100644 index 0000000000..3ec85c6609 --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/arm/cortex_a9_page_table.h @@ -0,0 +1,26 @@ +/* + * \brief Cortex A9 specific page table format + * \author Stefan Kalkowski + * \date 2017-02-20 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__BOOTSTRAP__SPEC__ARM__CORTEX_A9_PAGE_TABLE_H_ +#define _SRC__BOOTSTRAP__SPEC__ARM__CORTEX_A9_PAGE_TABLE_H_ + +#include + +constexpr unsigned Hw::Page_table::Descriptor_base::_device_tex() { + return 2; } + +constexpr bool Hw::Page_table::Descriptor_base::_smp() { return true; } + +void Hw::Page_table::_translation_added(unsigned long, unsigned long) { } + +#endif /* _SRC__BOOTSTRAP__SPEC__ARM__CORTEX_A9_PAGE_TABLE_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/arm/cpu.cc b/repos/base-hw/src/bootstrap/spec/arm/cpu.cc new file mode 100644 index 0000000000..95460b85b7 --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/arm/cpu.cc @@ -0,0 +1,49 @@ +/* + * \brief Generic MMU initialization for ARM + * \author Stefan Kalkowski + * \date 2017-04-09 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#include + +void Bootstrap::Cpu::enable_mmu_and_caches(Genode::addr_t table) +{ + /* invalidate TLB */ + Tlbiall::write(0); + + /* address space ID to zero */ + Cidr::write(0); + + /* do not use domains, but permission bits in table */ + Dacr::write(Dacr::D0::bits(1)); + + Ttbcr::write(0); + + Ttbr::access_t ttbr0 = Ttbr::Ba::masked(table); + Ttbr::Rgn::set(ttbr0, Ttbr::CACHEABLE); + if (Mpidr::read()) { /* check for SMP system */ + Ttbr::Irgn::set(ttbr0, Ttbr::CACHEABLE); + Ttbr::S::set(ttbr0, 1); + } else + Ttbr::C::set(ttbr0, 1); + Ttbr0::write(ttbr0); + + Sctlr::access_t sctlr = Sctlr::read(); + Sctlr::C::set(sctlr, 1); + Sctlr::I::set(sctlr, 1); + Sctlr::V::set(sctlr, 1); + Sctlr::A::set(sctlr, 0); + Sctlr::M::set(sctlr, 1); + Sctlr::Z::set(sctlr, 1); + Sctlr::write(sctlr); + + /* invalidate branch predictor */ + Bpiall::write(0); +} diff --git a/repos/base-hw/src/bootstrap/spec/arm/cpu.h b/repos/base-hw/src/bootstrap/spec/arm/cpu.h new file mode 100644 index 0000000000..86363c9aad --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/arm/cpu.h @@ -0,0 +1,60 @@ +/* + * \brief CPU definitions for ARM + * \author Stefan Kalkowski + * \date 2017-02-22 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__BOOTSTRAP__SPEC__ARM__CPU_H_ +#define _SRC__BOOTSTRAP__SPEC__ARM__CPU_H_ + +#include + +namespace Bootstrap { struct Cpu; } + +struct Bootstrap::Cpu : Hw::Arm_cpu +{ + struct Sctlr : Hw::Arm_cpu::Sctlr + { + static void init() + { + /* + * disable alignment checks and + * set exception vector to 0xffff0000 + */ + access_t v = read(); + A::set(v, 0); + V::set(v, 1); + write(v); + } + }; + + struct Cpsr : Hw::Arm_cpu::Cpsr + { + static void init() + { + access_t v = read(); + Psr::F::set(v, 1); + Psr::A::set(v, 1); + Psr::M::set(v, Psr::M::SVC); + Psr::I::set(v, 1); + write(v); + } + }; + + enum Errata { ARM_764369 }; + + static bool errata(Errata); + + static void wake_up_all_cpus(void * const ip); + + static void enable_mmu_and_caches(Genode::addr_t table); +}; + +#endif /* _SRC__BOOTSTRAP__SPEC__ARM__CPU_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/arm/crt0.s b/repos/base-hw/src/bootstrap/spec/arm/crt0.s index 6b6fa43dde..9e19d4a642 100644 --- a/repos/base-hw/src/bootstrap/spec/arm/crt0.s +++ b/repos/base-hw/src/bootstrap/spec/arm/crt0.s @@ -11,8 +11,6 @@ * under the terms of the GNU Affero General Public License version 3. */ -.include "macros.s" - .set STACK_SIZE, 4 * 16 * 1024 .section ".text.crt0" @@ -20,7 +18,11 @@ .global _start _start: - /* zero-fill BSS segment */ + + /*************************** + ** Zero-fill BSS segment ** + ***************************/ + adr r0, _bss_local_start adr r1, _bss_local_end ldr r0, [r0] @@ -34,15 +36,38 @@ b 1b 2: - .global _start_setup_stack + + /***************************************************** + ** Setup multiprocessor-aware kernel stack-pointer ** + *****************************************************/ + + mov sp, #0 /* for boot cpu use id 0 */ + cps #31 /* change to system mode */ + + .global _start_setup_stack /* entrypoint for all cpus */ _start_setup_stack: - /* setup multiprocessor-aware kernel stack-pointer */ - adr r0, _start_stack - adr r1, _start_stack_size + mrs r2, cpsr + cmp r2, #31 /* check for system mode */ + mrcne p15, 0, sp, c0, c0, 5 /* read multiprocessor affinity register */ + andne sp, sp, #0xff /* set cpu id for non-boot cpu */ + cps #19 /* change to supervisor mode */ + + adr r0, _start_stack /* load stack address into r0 */ + adr r1, _start_stack_size /* load stack size per cpu into r1 */ ldr r1, [r1] - _init_kernel_sp r0, r1 - b init + + add sp, #1 /* calculate stack start for CPU */ + mul r1, r1, sp + add sp, r0, r1 + + + /************************************ + ** Jump to high-level entry point ** + ************************************/ + + b init + _bss_local_start: .long _bss_start diff --git a/repos/base-hw/src/core/include/spec/imx/board_support.h b/repos/base-hw/src/bootstrap/spec/arm/imx_aipstz.h similarity index 75% rename from repos/base-hw/src/core/include/spec/imx/board_support.h rename to repos/base-hw/src/bootstrap/spec/arm/imx_aipstz.h index 1b80b5d024..8eccfc4c45 100644 --- a/repos/base-hw/src/core/include/spec/imx/board_support.h +++ b/repos/base-hw/src/bootstrap/spec/arm/imx_aipstz.h @@ -1,5 +1,5 @@ /* - * \brief Board driver + * \brief Driver for Freescale's AIPSTZ bridge * \author Stefan Kalkowski * \author Martin Stein * \date 2012-10-24 @@ -12,14 +12,12 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _CORE__INCLUDE__SPEC__IMX__BOARD_SUPPORT_H_ -#define _CORE__INCLUDE__SPEC__IMX__BOARD_SUPPORT_H_ +#ifndef _SRC__BOOTSTRAP__SPEC__ARM__IMX_AIPSTZ_H_ +#define _SRC__BOOTSTRAP__SPEC__ARM__IMX_AIPSTZ_H_ -/* Genode includes */ -#include #include -namespace Imx +namespace Bootstrap { /** * AHB to IP Bridge @@ -28,14 +26,9 @@ namespace Imx * bus peripherals. */ class Aipstz; - - /** - * Board driver - */ - class Board; } -class Imx::Aipstz : public Genode::Mmio +class Bootstrap::Aipstz : public Genode::Mmio { private: @@ -69,12 +62,10 @@ class Imx::Aipstz : public Genode::Mmio public: - Aipstz(Genode::addr_t const base) : Genode::Mmio(base) { } - /** * Configure this module appropriately for the first kernel run */ - void init() + Aipstz(Genode::addr_t const base) : Genode::Mmio(base) { /* avoid AIPS intervention at any memory access */ write(Mpr::ALL_UNBUFFERED_AND_FULLY_TRUSTED); @@ -91,20 +82,4 @@ class Imx::Aipstz : public Genode::Mmio } }; -class Imx::Board : public Genode::Board_base -{ - public: - - /** - * Configure this module appropriately for the first kernel run - */ - void init() - { - Aipstz _aipstz_1(AIPS_1_MMIO_BASE); - Aipstz _aipstz_2(AIPS_2_MMIO_BASE); - _aipstz_1.init(); - _aipstz_2.init(); - } -}; - -#endif /* _CORE__INCLUDE__SPEC__IMX__BOARD_SUPPORT_H_ */ +#endif /* _SRC__BOOTSTRAP__SPEC__ARM__IMX_AIPSTZ_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/arm/imx_csu.h b/repos/base-hw/src/bootstrap/spec/arm/imx_csu.h new file mode 100644 index 0000000000..8acd28dff5 --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/arm/imx_csu.h @@ -0,0 +1,233 @@ +/* + * \brief Driver for the Central Security Unit + * \author Stefan Kalkowski + * \date 2012-11-06 + */ + +/* + * Copyright (C) 2012-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__BOOTSTRAP__SPEC__ARM__IMX_CSU_H_ +#define _SRC__BOOTSTRAP__SPEC__ARM__IMX_CSU_H_ + +#include +#include + +namespace Bootstrap { struct Csu; } + +struct Bootstrap::Csu : Genode::Mmio +{ + template + struct Csl : public Register + { + enum { + SECURE = 0x33, + UNSECURE = 0xff, + }; + + struct Slave_a : Register::template Bitfield<0, 9> { }; + struct Slave_b : Register::template Bitfield<16, 9> { }; + }; + + struct Master : public Register<0x218, 32> + { + enum { + SECURE_UNLOCKED, + UNSECURE_UNLOCKED, + SECURE_LOCKED, + UNSECURE_LOCKED + }; + + struct Esdhc3 : Bitfield<0,2> { }; + struct Cortex : Bitfield<2,2> { }; + struct Sdma : Bitfield<4,2> { }; + struct Gpu : Bitfield<6,2> { }; + struct Usb : Bitfield<8,2> { }; + struct Pata : Bitfield<10,2> { }; + struct Mlb : Bitfield<14,2> { }; + struct Rtic : Bitfield<18,2> { }; + struct Esdhc4 : Bitfield<20,2> { }; + struct Fec : Bitfield<22,2> { }; + struct Dap : Bitfield<24,2> { }; + struct Esdhc1 : Bitfield<26,2> { }; + struct Esdhc2 : Bitfield<28,2> { }; + }; + + struct Alarm_mask : public Register<0x230, 32> { }; + struct Irq_ctrl : public Register<0x368, 32> { }; + + typedef Csl<0x00> Csl00; + typedef Csl<0x04> Csl01; + typedef Csl<0x08> Csl02; + typedef Csl<0x0c> Csl03; + typedef Csl<0x10> Csl04; + typedef Csl<0x14> Csl05; + typedef Csl<0x18> Csl06; + typedef Csl<0x1c> Csl07; + typedef Csl<0x20> Csl08; + typedef Csl<0x24> Csl09; + typedef Csl<0x28> Csl10; + typedef Csl<0x2c> Csl11; + typedef Csl<0x30> Csl12; + typedef Csl<0x34> Csl13; + typedef Csl<0x38> Csl14; + typedef Csl<0x3c> Csl15; + typedef Csl<0x40> Csl16; + typedef Csl<0x44> Csl17; + typedef Csl<0x48> Csl18; + typedef Csl<0x4c> Csl19; + typedef Csl<0x50> Csl20; + typedef Csl<0x54> Csl21; + typedef Csl<0x58> Csl22; + typedef Csl<0x5c> Csl23; + typedef Csl<0x60> Csl24; + typedef Csl<0x64> Csl25; + typedef Csl<0x68> Csl26; + typedef Csl<0x6c> Csl27; + typedef Csl<0x70> Csl28; + typedef Csl<0x74> Csl29; + typedef Csl<0x78> Csl30; + typedef Csl<0x7c> Csl31; + + Csu(Genode::addr_t base, + bool secure_uart, + bool secure_gpio, + bool secure_esdhc, + bool secure_i2c) : Genode::Mmio(base) + { + /* Power (CCM, SRC, DPLLIP1-4, GPC and OWIRE) */ + write(Csl00::UNSECURE); + + /* AHBMAX S0-S2 */ + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); + + /* AHBMAX M6 */ + write(Csl00::UNSECURE); + + /* Timer (EPIT, GPT) TODO */ + write(Csl00::UNSECURE); + + /* UART 1-5 */ + Csl00::access_t uart_csl = + secure_uart ? Csl00::SECURE : Csl00::UNSECURE; + write(uart_csl); + write(uart_csl); + write(uart_csl); + write(uart_csl); + write(uart_csl); + + /* GPIO */ + Csl00::access_t gpio_csl = + secure_gpio ? Csl00::SECURE : Csl00::UNSECURE; + write(gpio_csl); + write(gpio_csl); + write(gpio_csl); + write(gpio_csl); + + /* IOMUXC TODO */ + write(Csl00::UNSECURE); + + /* SDMA TODO */ + write(Csl00::UNSECURE); + + /* USB */ + write(Csl00::UNSECURE); + + /* TVE */ + write(Csl00::SECURE); + + /* I2C */ + Csl00::access_t i2c_csl = + secure_i2c ? Csl00::SECURE : Csl00::UNSECURE; + write(i2c_csl); + write(i2c_csl); + write(i2c_csl); + + /* IPU */ + write(Csl00::SECURE); + + /* Audio */ + write(Csl00::UNSECURE); + + /* SATA */ + write(Csl00::UNSECURE); + + /* FEC */ + write(Csl00::UNSECURE); + + /* SDHCI 1-4 */ + Csl00::access_t esdhc_csl = + secure_esdhc ? Csl00::SECURE : Csl00::UNSECURE; + write(esdhc_csl); + write(esdhc_csl); + write(esdhc_csl); + write(esdhc_csl); + + /* SPDIF */ + write(Csl00::UNSECURE); + + /* GPU 2D */ + write(Csl00::SECURE); + + /* GPU 3D */ + write(Csl00::SECURE); + + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); // SRTC + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); // SCC + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); // RTIC + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); + write(Csl00::SECURE); //VPU + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); + write(Csl00::UNSECURE); + + /* DMA from graphical subsystem is considered to be secure */ + write(Master::SECURE_UNLOCKED); + + /* all other DMA operations are insecure */ + write(Master::UNSECURE_UNLOCKED); + write(Master::UNSECURE_UNLOCKED); + write(Master::UNSECURE_UNLOCKED); + write(Master::UNSECURE_UNLOCKED); + write(Master::UNSECURE_UNLOCKED); + + Master::access_t esdhc_master = + secure_esdhc ? Master::SECURE_UNLOCKED + : Master::UNSECURE_UNLOCKED; + write(esdhc_master); + write(esdhc_master); + write(esdhc_master); + write(esdhc_master); + } +}; + +#endif /* _SRC__BOOTSTRAP__SPEC__ARM__IMX_CSU_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/arm/imx_tzic.cc b/repos/base-hw/src/bootstrap/spec/arm/imx_tzic.cc new file mode 100644 index 0000000000..d160f01b4b --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/arm/imx_tzic.cc @@ -0,0 +1,29 @@ +/* + * \brief Freescale's TrustZone aware interrupt controller + * \author Stefan Kalkowski + * \date 2012-10-24 + */ + +/* + * Copyright (C) 2012-2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#include + +Hw::Pic::Pic() : Genode::Mmio(Genode::Board_base::IRQ_CONTROLLER_BASE) +{ + for (unsigned i = 0; i < NR_OF_IRQ; i++) { + write(!Bootstrap::secure_irq(i), i); + if (!Bootstrap::secure_irq(i)) write(0x80, i); + write(1, i); + } + write(0xff); + Intctrl::access_t v = 0; + Intctrl::Enable::set(v, 1); + Intctrl::Nsen::set(v, 1); + Intctrl::Nsen_mask::set(v, 1); + write(v); +} diff --git a/repos/base-hw/src/bootstrap/spec/arm/pic.cc b/repos/base-hw/src/bootstrap/spec/arm/pic.cc new file mode 100644 index 0000000000..c3eee962e3 --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/arm/pic.cc @@ -0,0 +1,50 @@ +/* + * \brief Programmable interrupt controller for core + * \author Stefan Kalkowski + * \date 2012-10-24 + */ + +/* + * Copyright (C) 2012-2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#include +#include + +using Memory_map = Hw::Cpu_memory_map; +using Bootstrap::Platform; + +void Bootstrap::Pic::init_cpu_local() +{ + /* disable the priority filter */ + _cpui.write(_distr.min_priority()); + + /* disable preemption of IRQ handling by other IRQs */ + _cpui.write(~0); + + /* enable device */ + _cpui.write(1); +} + + +Hw::Pic::Pic() +: _distr(Memory_map::IRQ_CONTROLLER_DISTR_BASE), + _cpui (Memory_map::IRQ_CONTROLLER_CPU_BASE), + _last_iar(Cpu_interface::Iar::Irq_id::bits(spurious_id)), + _max_irq(_distr.max_irq()) +{ + /* disable device */ + _distr.write(0); + + /* configure every shared peripheral interrupt */ + for (unsigned i = min_spi; i <= _max_irq; i++) { + _distr.write(0, i); + _distr.write(0, i); + _distr.write(1, i); + } + /* enable device */ + _distr.write(1); +} diff --git a/repos/base-hw/src/bootstrap/spec/arm/pic.h b/repos/base-hw/src/bootstrap/spec/arm/pic.h new file mode 100644 index 0000000000..115f633c88 --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/arm/pic.h @@ -0,0 +1,26 @@ +/* + * \brief Interrupt controller definitions for ARM + * \author Stefan Kalkowski + * \date 2017-02-22 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__BOOTSTRAP__SPEC__ARM__PIC_H_ +#define _SRC__BOOTSTRAP__SPEC__ARM__PIC_H_ + +#include + +namespace Bootstrap { struct Pic; } + +struct Bootstrap::Pic : Hw::Pic +{ + void init_cpu_local(); +}; + +#endif /* _SRC__BOOTSTRAP__SPEC__ARM__PIC_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/arndale/board.h b/repos/base-hw/src/bootstrap/spec/arndale/board.h new file mode 100644 index 0000000000..6d323f6351 --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/arndale/board.h @@ -0,0 +1,37 @@ +/* + * \brief Arndale specific board definitions + * \author Stefan Kalkowski + * \date 2017-04-03 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__BOOTSTRAP__SPEC__ARNDALE__BOARD_H_ +#define _SRC__BOOTSTRAP__SPEC__ARNDALE__BOARD_H_ + +#include +#include + +#include +#include +#include +#include + +namespace Bootstrap { + class L2_cache; + + using Serial = Genode::Exynos_uart_base; + + enum { + UART_BASE = Genode::Board_base::UART_2_MMIO_BASE, + UART_CLOCK = Genode::Board_base::UART_2_CLOCK, + CPU_MMIO_BASE = Genode::Board_base::IRQ_CONTROLLER_BASE, + }; +} + +#endif /* _SRC__BOOTSTRAP__SPEC__ARNDALE__BOARD_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/arndale/cpu.cc b/repos/base-hw/src/bootstrap/spec/arndale/cpu.cc index 9f23109557..2f1c69ce3c 100644 --- a/repos/base-hw/src/bootstrap/spec/arndale/cpu.cc +++ b/repos/base-hw/src/bootstrap/spec/arndale/cpu.cc @@ -15,89 +15,6 @@ #include #include -static unsigned char hyp_mode_stack[1024]; - - -static inline void prepare_nonsecure_world() -{ - using Nsacr = Genode::Cpu::Nsacr; - using Cpsr = Genode::Cpu::Psr; - using Scr = Genode::Cpu::Scr; - - /* if we are already in HYP mode we're done (depends on u-boot version) */ - if (Cpsr::M::get(Cpsr::read()) == Cpsr::M::HYP) - return; - - /* ARM generic timer counter freq needs to be set in secure mode */ - volatile unsigned long * mct_control = (unsigned long*) 0x101C0240; - *mct_control = 0x100; - asm volatile ("mcr p15, 0, %0, c14, c0, 0" :: "r" (24000000)); - - /* - * enable coprocessor 10 + 11 access and SMP bit access in auxiliary control - * register for non-secure world - */ - Nsacr::access_t nsacr = 0; - Nsacr::Cpnsae10::set(nsacr, 1); - Nsacr::Cpnsae11::set(nsacr, 1); - Nsacr::Ns_smp::set(nsacr, 1); - Nsacr::write(nsacr); - - asm volatile ( - "msr sp_mon, sp \n" /* copy current mode's sp */ - "msr lr_mon, lr \n" /* copy current mode's lr */ - "cps #22 \n" /* switch to monitor mode */ - ); - - Scr::access_t scr = 0; - Scr::Ns::set(scr, 1); - Scr::Fw::set(scr, 1); - Scr::Aw::set(scr, 1); - Scr::Scd::set(scr, 1); - Scr::Hce::set(scr, 1); - Scr::Sif::set(scr, 1); - Scr::write(scr); -} - - -static inline void prepare_hypervisor(Genode::Translation_table & table) -{ - using Genode::Cpu; - - /* set hypervisor exception vector */ - Cpu::hyp_exception_entry_at((void*)0xfff00000); /* FIXME */ - - /* set hypervisor's translation table */ - Cpu::Httbr::translation_table((Genode::addr_t)&table); - - /* prepare MMU usage by hypervisor code */ - Cpu::Htcr::write(Cpu::Ttbcr::init_virt_kernel()); - Cpu::Hcptr::write(Cpu::Hcptr::init()); - Cpu::Hmair0::write(Cpu::Mair0::init_virt_kernel()); - Cpu::Vtcr::write(Cpu::Vtcr::init()); - Cpu::Hsctlr::write(Cpu::Sctlr::init_value()); -} - - -static inline void switch_to_supervisor_mode() -{ - using Psr = Genode::Cpu::Psr; - - Psr::access_t psr = 0; - Psr::M::set(psr, Psr::M::SVC); - Psr::F::set(psr, 1); - Psr::I::set(psr, 1); - - asm volatile ( - "msr sp_svc, sp \n" /* copy current mode's sp */ - "msr lr_svc, lr \n" /* copy current mode's lr */ - "msr elr_hyp, lr \n" /* copy current mode's lr to hyp lr */ - "msr sp_hyp, %[stack] \n" /* copy to hyp stack pointer */ - "msr spsr_cxfs, %[psr] \n" /* set psr for supervisor mode */ - "adr lr, 1f \n" /* load exception return address */ - "eret \n" /* exception return */ - "1:":: [psr] "r" (psr), [stack] "r" (&hyp_mode_stack)); -} void Genode::Cpu::init(Genode::Translation_table & table) diff --git a/repos/base-hw/src/bootstrap/spec/arndale/pic.cc b/repos/base-hw/src/bootstrap/spec/arndale/pic.cc new file mode 100644 index 0000000000..a2dafa095d --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/arndale/pic.cc @@ -0,0 +1,66 @@ +/* + * \brief Programmable interrupt controller for core + * \author Stefan Kalkowski + * \date 2012-10-24 + */ + +/* + * Copyright (C) 2012-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#include +#include +#include + +using Memory_map = Hw::Cpu_memory_map; +using Bootstrap::Platform; + +void Bootstrap::Pic::init_cpu_local() +{ + _cpui.write(0); + + /* mark software-generated IRQs as being non-secure */ + for (unsigned i = 0; i < min_spi; i++) + _distr.write(1, i); + + /* disable the priority filter */ + _cpui.write(_distr.min_priority()); + + /* disable preemption of IRQ handling by other IRQs */ + _cpui.write(~0); + + /* enable device */ + Cpu_interface::Ctlr::access_t v = 0; + Cpu_interface::Ctlr::Enable_grp0::set(v, 1); + Cpu_interface::Ctlr::Enable_grp1::set(v, 1); + Cpu_interface::Ctlr::Fiq_en::set(v, 1); + _cpui.write(v); +} + + +Hw::Pic::Pic() +: _distr(Memory_map::IRQ_CONTROLLER_DISTR_BASE), + _cpui(Memory_map::IRQ_CONTROLLER_CPU_BASE), + _last_iar(Cpu_interface::Iar::Irq_id::bits(spurious_id)), + _max_irq(_distr.max_irq()) +{ + /* disable device */ + _distr.write(0); + + /* configure every shared peripheral interrupt */ + for (unsigned i = min_spi; i <= _max_irq; i++) { + /* mark as non-secure */ + _distr.write(1, i); + _distr.write(0, i); + _distr.write(0, i); + _distr.write(1, i); + } + /* enable device */ + Distributor::Ctlr::access_t v = 0; + Distributor::Ctlr::Enable_grp0::set(v, 1); + Distributor::Ctlr::Enable_grp1::set(v, 1); + _distr.write(v); +} diff --git a/repos/base-hw/src/bootstrap/spec/arndale/platform.cc b/repos/base-hw/src/bootstrap/spec/arndale/platform.cc new file mode 100644 index 0000000000..5a91785ac0 --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/arndale/platform.cc @@ -0,0 +1,181 @@ +/* + * \brief Parts of platform that are specific to Arndale + * \author Martin Stein + * \date 2012-04-27 + */ + +/* + * Copyright (C) 2012-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#include + +extern "C" void * _start_setup_stack; /* entrypoint for non-boot CPUs */ +static unsigned char hyp_mode_stack[1024]; /* hypervisor mode's kernel stack */ + +Bootstrap::Platform::Board::Board() +: early_ram_regions(Memory_region { RAM_0_BASE, RAM_0_SIZE }), + core_mmio(Memory_region { IRQ_CONTROLLER_BASE, IRQ_CONTROLLER_SIZE }, + Memory_region { IRQ_CONTROLLER_VT_CTRL_BASE, IRQ_CONTROLLER_VT_CTRL_SIZE }, + Memory_region { MCT_MMIO_BASE, MCT_MMIO_SIZE }, + Memory_region { UART_2_MMIO_BASE, UART_2_MMIO_SIZE }) { } + + +static inline void prepare_nonsecure_world() +{ + using Cpu = Hw::Arm_cpu; + + /* if we are already in HYP mode we're done (depends on u-boot version) */ + if (Cpu::Psr::M::get(Cpu::Cpsr::read()) == Cpu::Psr::M::HYP) + return; + + /* ARM generic timer counter freq needs to be set in secure mode */ + volatile unsigned long * mct_control = (unsigned long*) 0x101C0240; + *mct_control = 0x100; + Cpu::Cntfrq::write(24000000); + + /* + * enable coprocessor 10 + 11 access and SMP bit access in auxiliary control + * register for non-secure world + */ + Cpu::Nsacr::access_t nsacr = 0; + Cpu::Nsacr::Cpnsae10::set(nsacr, 1); + Cpu::Nsacr::Cpnsae11::set(nsacr, 1); + Cpu::Nsacr::Ns_smp::set(nsacr, 1); + Cpu::Nsacr::write(nsacr); + + asm volatile ( + "msr sp_mon, sp \n" /* copy current mode's sp */ + "msr lr_mon, lr \n" /* copy current mode's lr */ + "cps #22 \n" /* switch to monitor mode */ + ); + + Cpu::Scr::access_t scr = 0; + Cpu::Scr::Ns::set(scr, 1); + Cpu::Scr::Fw::set(scr, 1); + Cpu::Scr::Aw::set(scr, 1); + Cpu::Scr::Scd::set(scr, 1); + Cpu::Scr::Hce::set(scr, 1); + Cpu::Scr::Sif::set(scr, 1); + Cpu::Scr::write(scr); +} + + +static inline void prepare_hypervisor(Genode::addr_t table) +{ + using Cpu = Hw::Arm_cpu; + + /* set hypervisor exception vector */ + Cpu::Hvbar::write(0xfff00000); /* FIXME */ + + /* set hypervisor's translation table */ + Cpu::Httbr_64bit::write(table); + + Cpu::Ttbcr::access_t ttbcr = 0; + Cpu::Ttbcr::Irgn0::set(ttbcr, 1); + Cpu::Ttbcr::Orgn0::set(ttbcr, 1); + Cpu::Ttbcr::Sh0::set(ttbcr, 2); + Cpu::Ttbcr::Eae::set(ttbcr, 1); + + /* prepare MMU usage by hypervisor code */ + Cpu::Htcr::write(ttbcr); + + /* don't trap on cporocessor 10 + 11, but all others */ + Cpu::Hcptr::access_t hcptr = 0; + Cpu::Hcptr::Tcp<0>::set(hcptr, 1); + Cpu::Hcptr::Tcp<1>::set(hcptr, 1); + Cpu::Hcptr::Tcp<2>::set(hcptr, 1); + Cpu::Hcptr::Tcp<3>::set(hcptr, 1); + Cpu::Hcptr::Tcp<4>::set(hcptr, 1); + Cpu::Hcptr::Tcp<5>::set(hcptr, 1); + Cpu::Hcptr::Tcp<6>::set(hcptr, 1); + Cpu::Hcptr::Tcp<7>::set(hcptr, 1); + Cpu::Hcptr::Tcp<8>::set(hcptr, 1); + Cpu::Hcptr::Tcp<9>::set(hcptr, 1); + Cpu::Hcptr::Tcp<12>::set(hcptr, 1); + Cpu::Hcptr::Tcp<13>::set(hcptr, 1); + Cpu::Hcptr::Tta::set(hcptr, 1); + Cpu::Hcptr::Tcpac::set(hcptr, 1); + Cpu::Hcptr::write(hcptr); + + enum Memory_attributes { + DEVICE_MEMORY = 0x04, + NORMAL_MEMORY_UNCACHED = 0x44, + NORMAL_MEMORY_CACHED = 0xff, + }; + + Cpu::Mair0::access_t mair0 = 0; + Cpu::Mair0::Attr0::set(mair0, NORMAL_MEMORY_UNCACHED); + Cpu::Mair0::Attr1::set(mair0, DEVICE_MEMORY); + Cpu::Mair0::Attr2::set(mair0, NORMAL_MEMORY_CACHED); + Cpu::Mair0::Attr3::set(mair0, DEVICE_MEMORY); + Cpu::Hmair0::write(mair0); + + Cpu::Vtcr::access_t vtcr = ttbcr; + Cpu::Vtcr::Sl0::set(vtcr, 1); /* set to starting level 1 */ + Cpu::Vtcr::write(vtcr); + + Cpu::Sctlr::access_t sctlr = Cpu::Sctlr::read(); + Cpu::Sctlr::C::set(sctlr, 1); + Cpu::Sctlr::I::set(sctlr, 1); + Cpu::Sctlr::V::set(sctlr, 1); + Cpu::Sctlr::A::set(sctlr, 0); + Cpu::Sctlr::M::set(sctlr, 1); + Cpu::Sctlr::Z::set(sctlr, 1); + Cpu::Hsctlr::write(sctlr); +} + + +static inline void switch_to_supervisor_mode() +{ + using Cpsr = Hw::Arm_cpu::Psr; + + Cpsr::access_t cpsr = 0; + Cpsr::M::set(cpsr, Cpsr::M::SVC); + Cpsr::F::set(cpsr, 1); + Cpsr::I::set(cpsr, 1); + + asm volatile ( + "msr sp_svc, sp \n" /* copy current mode's sp */ + "msr lr_svc, lr \n" /* copy current mode's lr */ + "msr elr_hyp, lr \n" /* copy current mode's lr to hyp lr */ + "msr sp_hyp, %[stack] \n" /* copy to hyp stack pointer */ + "msr spsr_cxfs, %[cpsr] \n" /* set psr for supervisor mode */ + "adr lr, 1f \n" /* load exception return address */ + "eret \n" /* exception return */ + "1:":: [cpsr] "r" (cpsr), [stack] "r" (&hyp_mode_stack)); +} + + +void Bootstrap::Platform::enable_mmu() +{ + static volatile bool primary_cpu = true; + pic.init_cpu_local(); + + prepare_nonsecure_world(); + prepare_hypervisor((addr_t)core_pd->table_base); + switch_to_supervisor_mode(); + + Cpu::Sctlr::init(); + Cpu::Cpsr::init(); + + cpu.invalidate_data_cache(); + + /* primary cpu wakes up all others */ + if (primary_cpu && NR_OF_CPUS > 1) { + primary_cpu = false; + cpu.wake_up_all_cpus(&_start_setup_stack); + } + + cpu.enable_mmu_and_caches((Genode::addr_t)core_pd->table_base); +} + + +void Bootstrap::Cpu::wake_up_all_cpus(void * const ip) +{ + *(void * volatile *)Genode::Board_base::IRAM_BASE = ip; + asm volatile("dsb; sev;"); +} diff --git a/repos/base-hw/src/bootstrap/spec/imx53/board_trustzone.cc b/repos/base-hw/src/bootstrap/spec/imx53/board_trustzone.cc deleted file mode 100644 index 5ea4a235f5..0000000000 --- a/repos/base-hw/src/bootstrap/spec/imx53/board_trustzone.cc +++ /dev/null @@ -1,27 +0,0 @@ -/* - * \brief Specific core implementations - * \author Stefan Kalkowski - * \date 2017-01-27 - */ - -/* - * Copyright (C) 2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -/* core includes */ -#include -#include - -using Genode::Memory_region; - -Platform::Board::Board() -: early_ram_regions(Memory_region { Trustzone::SECURE_RAM_BASE, - Trustzone::SECURE_RAM_SIZE }), - core_mmio(Memory_region { UART_1_MMIO_BASE, UART_1_MMIO_SIZE }, - Memory_region { EPIT_1_MMIO_BASE, EPIT_1_MMIO_SIZE }, - Memory_region { IRQ_CONTROLLER_BASE, IRQ_CONTROLLER_SIZE }, - Memory_region { CSU_BASE, CSU_SIZE }) { - init(); } diff --git a/repos/base-hw/src/bootstrap/spec/imx53/platform.cc b/repos/base-hw/src/bootstrap/spec/imx53/platform.cc deleted file mode 100644 index 767d750712..0000000000 --- a/repos/base-hw/src/bootstrap/spec/imx53/platform.cc +++ /dev/null @@ -1,28 +0,0 @@ -/* - * \brief Specific i.MX53 bootstrap implementations - * \author Stefan Kalkowski - * \date 2012-10-24 - */ - -/* - * Copyright (C) 2012-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -/* core includes */ -#include -#include - - -void Platform::enable_mmu() -{ - Genode::Cpu::Sctlr::init(); - - cpu.enable_mmu_and_caches((addr_t)core_pd->table_base); -} - - -void Genode::Cpu::translation_added(Genode::addr_t const addr, - Genode::size_t const size) { } diff --git a/repos/base-hw/src/bootstrap/spec/imx53_qsb/board.h b/repos/base-hw/src/bootstrap/spec/imx53_qsb/board.h new file mode 100644 index 0000000000..37ee9ce6ae --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/imx53_qsb/board.h @@ -0,0 +1,36 @@ +/* + * \brief i.MX53 Quickstart board definitions + * \author Stefan Kalkowski + * \date 2017-03-22 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__BOOTSTRAP__SPEC__IMX53_QSB__BOARD_H_ +#define _SRC__BOOTSTRAP__SPEC__IMX53_QSB__BOARD_H_ + +#include +#include +#include + +#include +#include + +namespace Bootstrap { + using Hw::Pic; + using Serial = Genode::Imx_uart_base; + + enum { + UART_BASE = Genode::Board_base::UART_1_MMIO_BASE, + UART_CLOCK = 0, /* ignored value */ + }; + + bool secure_irq(unsigned irq); +} + +#endif /* _SRC__BOOTSTRAP__SPEC__IMX53_QSB__BOARD_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/imx53/board.cc b/repos/base-hw/src/bootstrap/spec/imx53_qsb/platform.cc similarity index 61% rename from repos/base-hw/src/bootstrap/spec/imx53/board.cc rename to repos/base-hw/src/bootstrap/spec/imx53_qsb/platform.cc index 9f3b9d090b..8e7945a4ec 100644 --- a/repos/base-hw/src/bootstrap/spec/imx53/board.cc +++ b/repos/base-hw/src/bootstrap/spec/imx53_qsb/platform.cc @@ -1,25 +1,29 @@ /* - * \brief Specific bootstrap implementations + * \brief Specific i.MX53 bootstrap implementations * \author Stefan Kalkowski - * \date 2017-01-27 + * \date 2012-10-24 */ /* - * Copyright (C) 2017 Genode Labs GmbH + * Copyright (C) 2012-2017 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. */ #include -#include +#include -using Genode::Memory_region; +bool Bootstrap::secure_irq(unsigned i) { return true; } -Platform::Board::Board() + +Bootstrap::Platform::Board::Board() : early_ram_regions(Memory_region { RAM0_BASE, RAM0_SIZE }, Memory_region { RAM1_BASE, RAM1_SIZE }), core_mmio(Memory_region { UART_1_MMIO_BASE, UART_1_MMIO_SIZE }, Memory_region { EPIT_1_MMIO_BASE, EPIT_1_MMIO_SIZE }, - Memory_region { IRQ_CONTROLLER_BASE, IRQ_CONTROLLER_SIZE }) { - init(); } + Memory_region { IRQ_CONTROLLER_BASE, IRQ_CONTROLLER_SIZE }) +{ + Aipstz aipstz_1(AIPS_1_MMIO_BASE); + Aipstz aipstz_2(AIPS_2_MMIO_BASE); +} diff --git a/repos/base-hw/src/bootstrap/spec/imx53_qsb/platform_trustzone.cc b/repos/base-hw/src/bootstrap/spec/imx53_qsb/platform_trustzone.cc new file mode 100644 index 0000000000..bec4b397e1 --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/imx53_qsb/platform_trustzone.cc @@ -0,0 +1,55 @@ +/* + * \brief Specific i.MX53 bootstrap implementations + * \author Stefan Kalkowski + * \date 2012-10-24 + */ + +/* + * Copyright (C) 2012-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#include +#include +#include +#include + +bool Bootstrap::secure_irq(unsigned i) +{ + using Board = Genode::Board_base; + + if (i == Board::EPIT_1_IRQ) return true; + if (i == Board::EPIT_2_IRQ) return true; + if (i == Board::I2C_2_IRQ) return true; + if (i == Board::I2C_3_IRQ) return true; + if (i >= Board::GPIO1_IRQL && i <= Board::GPIO4_IRQH) return true; + if (i >= Board::GPIO5_IRQL && i <= Board::GPIO7_IRQH) return true; + return false; +} + + +Bootstrap::Platform::Board::Board() +: early_ram_regions(Memory_region { Trustzone::SECURE_RAM_BASE, + Trustzone::SECURE_RAM_SIZE }), + core_mmio(Memory_region { UART_1_MMIO_BASE, UART_1_MMIO_SIZE }, + Memory_region { EPIT_1_MMIO_BASE, EPIT_1_MMIO_SIZE }, + Memory_region { IRQ_CONTROLLER_BASE, IRQ_CONTROLLER_SIZE }, + Memory_region { CSU_BASE, CSU_SIZE }) +{ + Aipstz aipstz_1(AIPS_1_MMIO_BASE); + Aipstz aipstz_2(AIPS_2_MMIO_BASE); + + /* set exception vector entry */ + Cpu::Mvbar::write(0xfff00000); + + /* enable coprocessor 10 + 11 access for TZ VMs */ + Cpu::Nsacr::access_t v = 0; + Cpu::Nsacr::Cpnsae10::set(v, 1); + Cpu::Nsacr::Cpnsae11::set(v, 1); + Cpu::Nsacr::write(v); + + /* configure central security unit */ + Csu csu(Genode::Board_base::CSU_BASE, false, true, false, true); +} diff --git a/repos/base-hw/src/bootstrap/spec/imx6/platform.cc b/repos/base-hw/src/bootstrap/spec/imx6/platform.cc deleted file mode 100644 index a0e8ebc0f9..0000000000 --- a/repos/base-hw/src/bootstrap/spec/imx6/platform.cc +++ /dev/null @@ -1,44 +0,0 @@ -/* - * \brief Specific bootstrap implementations - * \author Stefan Kalkowski - * \author Josef Soentgen - * \author Martin Stein - * \date 2014-02-25 - */ - -/* - * Copyright (C) 2014-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -/* core includes */ -#include -#include - -using namespace Genode; - -Platform::Board::Board() -: early_ram_regions(Memory_region { RAM0_BASE, RAM0_SIZE }), - core_mmio(Memory_region { UART_1_MMIO_BASE, - UART_1_MMIO_SIZE }, - Memory_region { CORTEX_A9_PRIVATE_MEM_BASE, - CORTEX_A9_PRIVATE_MEM_SIZE }, - Memory_region { PL310_MMIO_BASE, - PL310_MMIO_SIZE }) { init(); } - - -bool Cortex_a9::Board::errata(Cortex_a9::Board::Errata err) -{ - switch (err) { - case Cortex_a9::Board::ARM_754322: - case Cortex_a9::Board::ARM_764369: - case Cortex_a9::Board::ARM_775420: - case Cortex_a9::Board::PL310_588369: - case Cortex_a9::Board::PL310_727915: - case Cortex_a9::Board::PL310_769419: - return true; - }; - return false; -} diff --git a/repos/base-hw/src/bootstrap/spec/odroid_xu/board.h b/repos/base-hw/src/bootstrap/spec/odroid_xu/board.h new file mode 100644 index 0000000000..33e843fb02 --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/odroid_xu/board.h @@ -0,0 +1,37 @@ +/* + * \brief Odroid XU specific board definitions + * \author Stefan Kalkowski + * \date 2017-04-03 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__BOOTSTRAP__SPEC__ODROID_XU__BOARD_H_ +#define _SRC__BOOTSTRAP__SPEC__ODROID_XU__BOARD_H_ + +#include +#include + +#include +#include +#include +#include + +namespace Bootstrap { + class L2_cache; + + using Serial = Genode::Exynos_uart_base; + + enum { + UART_BASE = Genode::Board_base::UART_2_MMIO_BASE, + UART_CLOCK = Genode::Board_base::UART_2_CLOCK, + CPU_MMIO_BASE = Genode::Board_base::IRQ_CONTROLLER_BASE, + }; +} + +#endif /* _SRC__BOOTSTRAP__SPEC__ODROID_XU__BOARD_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/odroid_xu/cpu.cc b/repos/base-hw/src/bootstrap/spec/odroid_xu/cpu.cc deleted file mode 100644 index b34e2c29db..0000000000 --- a/repos/base-hw/src/bootstrap/spec/odroid_xu/cpu.cc +++ /dev/null @@ -1,16 +0,0 @@ -/* - * \brief Cpu-specific code for Cortex A15 - * \author Stefan Kalkowski - * \date 2016-01-07 - */ - -/* - * Copyright (C) 2016-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#include - -void Genode::Cpu::init(Genode::Translation_table&) {} diff --git a/repos/base-hw/src/bootstrap/spec/exynos5/platform.cc b/repos/base-hw/src/bootstrap/spec/odroid_xu/platform.cc similarity index 56% rename from repos/base-hw/src/bootstrap/spec/exynos5/platform.cc rename to repos/base-hw/src/bootstrap/spec/odroid_xu/platform.cc index 9756d080ba..ce0fea0024 100644 --- a/repos/base-hw/src/bootstrap/spec/exynos5/platform.cc +++ b/repos/base-hw/src/bootstrap/spec/odroid_xu/platform.cc @@ -1,5 +1,5 @@ /* - * \brief Parts of platform that are specific to Arndale + * \brief Parts of platform that are specific to Odroid XU * \author Martin Stein * \date 2012-04-27 */ @@ -13,10 +13,7 @@ #include -/* entrypoint for non-boot CPUs */ -extern "C" void * _start_setup_stack; - -Platform::Board::Board() +Bootstrap::Platform::Board::Board() : early_ram_regions(Memory_region { RAM_0_BASE, RAM_0_SIZE }), core_mmio(Memory_region { IRQ_CONTROLLER_BASE, IRQ_CONTROLLER_SIZE }, Memory_region { IRQ_CONTROLLER_VT_CTRL_BASE, IRQ_CONTROLLER_VT_CTRL_SIZE }, @@ -24,25 +21,11 @@ Platform::Board::Board() Memory_region { UART_2_MMIO_BASE, UART_2_MMIO_SIZE }) { } -void Platform::enable_mmu() +void Bootstrap::Platform::enable_mmu() { - using Genode::Cpu; - - static volatile bool primary_cpu = true; pic.init_cpu_local(); - - cpu.init(*reinterpret_cast(core_pd->table_base)); - Cpu::Sctlr::init(); - Cpu::Psr::write(Cpu::Psr::init_kernel()); - - cpu.invalidate_inner_data_cache(); - - /* primary cpu wakes up all others */ - if (primary_cpu && NR_OF_CPUS > 1) { - primary_cpu = false; - board.wake_up_all_cpus(&_start_setup_stack); - } - + Cpu::Cpsr::init(); + cpu.invalidate_data_cache(); cpu.enable_mmu_and_caches((Genode::addr_t)core_pd->table_base); } diff --git a/repos/base-hw/src/bootstrap/spec/panda/board.h b/repos/base-hw/src/bootstrap/spec/panda/board.h new file mode 100644 index 0000000000..1a8a285997 --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/panda/board.h @@ -0,0 +1,85 @@ +/* + * \brief Pbxa9 specific board definitions + * \author Stefan Kalkowski + * \date 2017-02-20 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__BOOTSTRAP__SPEC__PANDA__BOARD_H_ +#define _SRC__BOOTSTRAP__SPEC__PANDA__BOARD_H_ + +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace Bootstrap { + class L2_cache; + + using Serial = Genode::Tl16c750_base; + + enum { + UART_BASE = Genode::Board_base::TL16C750_3_MMIO_BASE, + UART_CLOCK = Genode::Board_base::TL16C750_CLOCK, + CPU_MMIO_BASE = Genode::Board_base::CORTEX_A9_PRIVATE_MEM_BASE, + }; + + struct Actlr; +} + + +struct Bootstrap::Actlr +{ + static void enable_smp() { + Hw::call_panda_firmware(Hw::CPU_ACTLR_SMP_BIT_RAISE, 0); } +}; + + +class Bootstrap::L2_cache : Hw::Pl310 +{ + private: + + unsigned long _init_value() + { + Aux::access_t v = 0; + Aux::Associativity::set(v, 1); + Aux::Way_size::set(v, 3); + Aux::Share_override::set(v, 1); + Aux::Reserved::set(v, 1); + Aux::Ns_lockdown::set(v, 1); + Aux::Ns_irq_ctrl::set(v, 1); + Aux::Data_prefetch::set(v, 1); + Aux::Inst_prefetch::set(v, 1); + Aux::Early_bresp::set(v, 1); + return v; + } + + public: + + L2_cache(Genode::addr_t mmio) : Hw::Pl310(mmio) { + Hw::call_panda_firmware(Hw::L2_CACHE_AUX_REG, _init_value()); } + + using Hw::Pl310::invalidate; + + void enable() + { + Hw::call_panda_firmware(Hw::L2_CACHE_ENABLE_REG, 1); + Pl310::mask_interrupts(); + } + + void disable() { + Hw::call_panda_firmware(Hw::L2_CACHE_ENABLE_REG, 0); } +}; + +#endif /* _SRC__BOOTSTRAP__SPEC__PANDA__BOARD_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/panda/platform.cc b/repos/base-hw/src/bootstrap/spec/panda/platform.cc index 3db092bfad..7162ea801d 100644 --- a/repos/base-hw/src/bootstrap/spec/panda/platform.cc +++ b/repos/base-hw/src/bootstrap/spec/panda/platform.cc @@ -12,9 +12,8 @@ */ #include -#include -Platform::Board::Board() +Bootstrap::Platform::Board::Board() : early_ram_regions(Memory_region { RAM_0_BASE, RAM_0_SIZE }), core_mmio(Memory_region { CORTEX_A9_PRIVATE_MEM_BASE, CORTEX_A9_PRIVATE_MEM_SIZE }, @@ -24,28 +23,28 @@ Platform::Board::Board() PL310_MMIO_SIZE }) { } -void Cortex_a9::Board::wake_up_all_cpus(void * const ip) +bool Bootstrap::Cpu::errata(Bootstrap::Cpu::Errata err) { + return false; } + + +void Bootstrap::Cpu::wake_up_all_cpus(void * const ip) { - Genode::Cortex_a9_wugen wugen; - wugen.init_cpu_1(ip); + struct Wakeup_generator : Genode::Mmio + { + struct Aux_core_boot_0 : Register<0x800, 32> { + struct Cpu1_status : Bitfield<2, 2> { }; }; + + struct Aux_core_boot_1 : Register<0x804, 32> { }; + + Wakeup_generator(void * const ip) + : Mmio(Genode::Board_base::CORTEX_A9_WUGEN_MMIO_BASE) + { + write((addr_t)ip); + write(1); + } + }; + + Wakeup_generator wgen(ip); asm volatile("dsb\n" "sev\n"); } - - -bool Cortex_a9::Board::errata(Cortex_a9::Board::Errata err) -{ - switch (err) { - case Cortex_a9::Board::PL310_588369: - case Cortex_a9::Board::PL310_727915: return true; - default: ; - }; - return false; -} - - -void Genode::Cpu::Actlr::enable_smp(Genode::Board & board) -{ - Board::Secure_monitor monitor; - monitor.call(Board::Secure_monitor::CPU_ACTLR_SMP_BIT_RAISE, 0); -} diff --git a/repos/base-hw/src/bootstrap/spec/pbxa9/board.h b/repos/base-hw/src/bootstrap/spec/pbxa9/board.h new file mode 100644 index 0000000000..218e13cc5b --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/pbxa9/board.h @@ -0,0 +1,38 @@ +/* + * \brief Pbxa9 specific board definitions + * \author Stefan Kalkowski + * \date 2017-02-20 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__BOOTSTRAP__SPEC__PBXA9__BOARD_H_ +#define _SRC__BOOTSTRAP__SPEC__PBXA9__BOARD_H_ + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace Bootstrap { + using L2_cache = Hw::Pl310; + using Serial = Genode::Pl011_base; + + enum { + UART_BASE = Genode::Board_base::PL011_0_MMIO_BASE, + UART_CLOCK = Genode::Board_base::PL011_0_CLOCK, + CPU_MMIO_BASE = Genode::Board_base::CORTEX_A9_PRIVATE_MEM_BASE, + }; +} + +#endif /* _SRC__BOOTSTRAP__SPEC__PBXA9__BOARD_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/pbxa9/platform.cc b/repos/base-hw/src/bootstrap/spec/pbxa9/platform.cc index 65840d660e..6af10c12d0 100644 --- a/repos/base-hw/src/bootstrap/spec/pbxa9/platform.cc +++ b/repos/base-hw/src/bootstrap/spec/pbxa9/platform.cc @@ -14,7 +14,7 @@ /* bootstrap includes */ #include -Platform::Board::Board() +Bootstrap::Platform::Board::Board() : early_ram_regions(Memory_region { RAM_0_BASE, RAM_0_SIZE }, Memory_region { RAM_1_BASE, RAM_1_SIZE }), core_mmio(Memory_region { Board::CORTEX_A9_PRIVATE_MEM_BASE, @@ -25,11 +25,11 @@ Platform::Board::Board() Board::PL310_MMIO_SIZE }) { } -bool Cortex_a9::Board::errata(Cortex_a9::Board::Errata err) { +bool Bootstrap::Cpu::errata(Bootstrap::Cpu::Errata err) { return false; } -void Cortex_a9::Board::wake_up_all_cpus(void * const ip) +void Bootstrap::Cpu::wake_up_all_cpus(void * const ip) { /** * set the entrypoint for the other CPUs via the flags register @@ -43,7 +43,7 @@ void Cortex_a9::Board::wake_up_all_cpus(void * const ip) struct Flagsclr : Register<0x34, 32> { }; System_control(void * const ip) - : Mmio(SYSTEM_CONTROL_MMIO_BASE) + : Mmio(Genode::Board_base::SYSTEM_CONTROL_MMIO_BASE) { write(~0UL); write(reinterpret_cast(ip)); diff --git a/repos/base-hw/src/bootstrap/spec/riscv/board.h b/repos/base-hw/src/bootstrap/spec/riscv/board.h new file mode 100644 index 0000000000..760d5605dd --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/riscv/board.h @@ -0,0 +1,36 @@ +/* + * \brief Riscv spike specific board definitions + * \author Stefan Kalkowski + * \date 2017-02-20 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__BOOTSTRAP__SPEC__RISCV__BOARD_H_ +#define _SRC__BOOTSTRAP__SPEC__RISCV__BOARD_H_ + +#include +#include + +namespace Genode { struct Board_base {}; } + +namespace Bootstrap { + struct Cpu {}; + struct Pic {}; + + enum { UART_BASE, UART_CLOCK }; + struct Serial : Hw::Riscv_uart { + Serial(unsigned, unsigned, unsigned) {} }; +} + +template +void Sv39::Level_x_translation_table::_translation_added(addr_t addr, + size_t size) +{ } + +#endif /* _SRC__BOOTSTRAP__SPEC__RISCV__BOARD_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/riscv/cpu.cc b/repos/base-hw/src/bootstrap/spec/riscv/cpu.cc index b92aee7f50..ca079ad118 100644 --- a/repos/base-hw/src/bootstrap/spec/riscv/cpu.cc +++ b/repos/base-hw/src/bootstrap/spec/riscv/cpu.cc @@ -12,7 +12,6 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* core includes */ #include void Genode::Cpu::translation_added(addr_t const addr, size_t const size) { diff --git a/repos/base-hw/src/bootstrap/spec/riscv/exception_vector.cc b/repos/base-hw/src/bootstrap/spec/riscv/exception_vector.cc deleted file mode 100644 index e40b4f8e04..0000000000 --- a/repos/base-hw/src/bootstrap/spec/riscv/exception_vector.cc +++ /dev/null @@ -1,30 +0,0 @@ -/* - * \brief Exception vector initialization - * \author Sebastian Sumpf - * \date 2015-07-12 - */ - -/* - * Copyright (C) 2015-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -/* Core includes */ -#include - -extern int _machine_begin, _machine_end; - -extern "C" void setup_riscv_exception_vector() -{ - using namespace Genode; - - /* retrieve exception vector */ - addr_t vector; - asm volatile ("csrr %0, mtvec\n" : "=r"(vector)); - - /* copy machine mode exception vector */ - memcpy((void *)vector, - &_machine_begin, (addr_t)&_machine_end - (addr_t)&_machine_begin); -} diff --git a/repos/base-hw/src/core/spec/riscv/mode_transition.s b/repos/base-hw/src/bootstrap/spec/riscv/exception_vector.s similarity index 100% rename from repos/base-hw/src/core/spec/riscv/mode_transition.s rename to repos/base-hw/src/bootstrap/spec/riscv/exception_vector.s diff --git a/repos/base-hw/src/bootstrap/spec/riscv/platform.cc b/repos/base-hw/src/bootstrap/spec/riscv/platform.cc index 4c5b984375..3c3136eef6 100644 --- a/repos/base-hw/src/bootstrap/spec/riscv/platform.cc +++ b/repos/base-hw/src/bootstrap/spec/riscv/platform.cc @@ -12,31 +12,30 @@ * under the terms of the GNU Affero General Public License version 3. */ +#include + #include -Platform::Board::Board() -: early_ram_regions(Genode::Memory_region { 0, 128 * 1024 * 1024 } ) {} +Bootstrap::Platform::Board::Board() +: early_ram_regions(Memory_region { 0, 128 * 1024 * 1024 } ) {} -struct Mstatus : Genode::Register<64> +void Bootstrap::Platform::enable_mmu() { - enum { - USER = 0, - SUPERVISOR = 1, - Sv39 = 9, + struct Mstatus : Genode::Register<64> + { + enum { + USER = 0, + SUPERVISOR = 1, + Sv39 = 9, + }; + struct Ie : Bitfield<0, 1> { }; + struct Priv : Bitfield<1, 2> { }; + struct Ie1 : Bitfield<3, 1> { }; + struct Priv1 : Bitfield<4, 2> { }; + struct Fs : Bitfield<12, 2> { enum { INITIAL = 1 }; }; + struct Vm : Bitfield<17, 5> { }; }; - struct Ie : Bitfield<0, 1> { }; - struct Priv : Bitfield<1, 2> { }; - struct Ie1 : Bitfield<3, 1> { }; - struct Priv1 : Bitfield<4, 2> { }; - struct Fs : Bitfield<12, 2> { enum { INITIAL = 1 }; }; - struct Vm : Bitfield<17, 5> { }; -}; - - -void Platform::enable_mmu() -{ - using Genode::Cpu; /* read status register */ Mstatus::access_t mstatus = 0; @@ -57,3 +56,19 @@ void Platform::enable_mmu() "r" (mstatus) : "memory"); } + + +extern int _machine_begin, _machine_end; + +extern "C" void setup_riscv_exception_vector() +{ + using namespace Genode; + + /* retrieve exception vector */ + addr_t vector; + asm volatile ("csrr %0, mtvec\n" : "=r"(vector)); + + /* copy machine mode exception vector */ + memcpy((void *)vector, + &_machine_begin, (addr_t)&_machine_end - (addr_t)&_machine_begin); +} diff --git a/repos/base-hw/src/bootstrap/spec/rpi/board.h b/repos/base-hw/src/bootstrap/spec/rpi/board.h new file mode 100644 index 0000000000..efb1bdfbde --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/rpi/board.h @@ -0,0 +1,46 @@ +/* + * \brief Raspberry PI specific board definitions + * \author Stefan Kalkowski + * \date 2017-02-20 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__BOOTSTRAP__SPEC__RPI__BOARD_H_ +#define _SRC__BOOTSTRAP__SPEC__RPI__BOARD_H_ + +#include +#include +#include + +#include + +namespace Bootstrap { + using Serial = Genode::Pl011_base; + + enum { + UART_BASE = Genode::Board_base::PL011_0_MMIO_BASE, + UART_CLOCK = Genode::Board_base::PL011_0_CLOCK, + }; + + struct Pic {}; +} + + +constexpr unsigned Hw::Page_table::Descriptor_base::_device_tex() { + return 0; } + + +constexpr bool Hw::Page_table::Descriptor_base::_smp() { return false; } + + +void Hw::Page_table::_translation_added(unsigned long addr, + unsigned long size) { + Bootstrap::Cpu::clean_invalidate_data_cache(); } + +#endif /* _SRC__BOOTSTRAP__SPEC__RPI__BOARD_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/rpi/platform.cc b/repos/base-hw/src/bootstrap/spec/rpi/platform.cc index 4791d24131..5ab454953d 100644 --- a/repos/base-hw/src/bootstrap/spec/rpi/platform.cc +++ b/repos/base-hw/src/bootstrap/spec/rpi/platform.cc @@ -12,15 +12,14 @@ * under the terms of the GNU Affero General Public License version 3. */ +#include #include -using Genode::Memory_region; - /** * Leave out the first page (being 0x0) from bootstraps RAM allocator, * some code does not feel happy with addresses being zero */ -Platform::Board::Board() +Bootstrap::Platform::Board::Board() : early_ram_regions(Memory_region { RAM_0_BASE + 0x1000, RAM_0_SIZE - 0x1000 }), late_ram_regions(Memory_region { RAM_0_BASE, 0x1000 }), @@ -34,13 +33,58 @@ Platform::Board::Board() USB_DWC_OTG_SIZE }) {} -void Platform::enable_mmu() +void Bootstrap::Platform::enable_mmu() { - Genode::Cpu::Sctlr::init(); - Genode::Cpu::Psr::write(Genode::Cpu::Psr::init_kernel()); + struct Sctlr : Cpu::Sctlr + { + struct W : Bitfield<3,1> { }; /* enable write buffer */ + struct Dt : Bitfield<16,1> { }; /* global data TCM enable */ + struct It : Bitfield<18,1> { }; /* global instruction TCM enable */ + struct U : Bitfield<22,1> { }; /* enable unaligned data access */ + struct Xp : Bitfield<23,1> { }; /* disable subpage AP bits */ + }; + + Cpu::Sctlr::init(); + Cpu::Sctlr::access_t sctlr = Cpu::Sctlr::read(); + Sctlr::W::set(sctlr, 1); + Sctlr::Dt::set(sctlr, 1); + Sctlr::It::set(sctlr, 1); + Sctlr::U::set(sctlr, 1); + Sctlr::Xp::set(sctlr, 1); + Cpu::Sctlr::write(sctlr); + + Cpu::Cpsr::init(); + + struct Ctr : Cpu::Ctr { + struct P : Bitfield<23, 1> { }; /* page mapping restriction on */ + }; /* check for mapping restrictions */ - assert(!Genode::Cpu::restricted_page_mappings()); + assert(!Ctr::P::get(Cpu::Ctr::read())); - cpu.enable_mmu_and_caches((addr_t)core_pd->table_base); + /* invalidate TLB */ + Cpu::Tlbiall::write(0); + + /* address space ID to zero */ + Cpu::Cidr::write(0); + + /* do not use domains, but permission bits in table */ + Cpu::Dacr::write(Cpu::Dacr::D0::bits(1)); + + Cpu::Ttbcr::write(0); + + Genode::addr_t table = (Genode::addr_t)core_pd->table_base; + Cpu::Ttbr::access_t ttbr0 = Cpu::Ttbr::Ba::masked(table); + Cpu::Ttbr::Rgn::set(ttbr0, Cpu::Ttbr::CACHEABLE); + Cpu::Ttbr::C::set(ttbr0, 1); + Cpu::Ttbr0::write(ttbr0); + + sctlr = Cpu::Sctlr::read(); + Cpu::Sctlr::C::set(sctlr, 1); + Cpu::Sctlr::I::set(sctlr, 1); + Cpu::Sctlr::M::set(sctlr, 1); + Cpu::Sctlr::write(sctlr); + + /* invalidate branch predictor */ + Cpu::Bpiall::write(0); } diff --git a/repos/base-hw/src/bootstrap/spec/usb_armory/board.h b/repos/base-hw/src/bootstrap/spec/usb_armory/board.h new file mode 100644 index 0000000000..5bcd50db77 --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/usb_armory/board.h @@ -0,0 +1,36 @@ +/* + * \brief i.MX53 Quickstart board definitions + * \author Stefan Kalkowski + * \date 2017-03-22 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__BOOTSTRAP__SPEC__USB_ARMORY__BOARD_H_ +#define _SRC__BOOTSTRAP__SPEC__USB_ARMORY__BOARD_H_ + +#include +#include +#include + +#include +#include + +namespace Bootstrap { + using Hw::Pic; + using Serial = Genode::Imx_uart_base; + + enum { + UART_BASE = Genode::Board_base::UART_1_MMIO_BASE, + UART_CLOCK = 0, /* ignored value */ + }; + + bool secure_irq(unsigned irq); +} + +#endif /* _SRC__BOOTSTRAP__SPEC__USB_ARMORY__BOARD_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/usb_armory/platform.cc b/repos/base-hw/src/bootstrap/spec/usb_armory/platform.cc new file mode 100644 index 0000000000..fb8fcd013f --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/usb_armory/platform.cc @@ -0,0 +1,52 @@ +/* + * \brief Specific i.MX53 bootstrap implementations + * \author Stefan Kalkowski + * \date 2012-10-24 + */ + +/* + * Copyright (C) 2012-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#include +#include +#include +#include + +bool Bootstrap::secure_irq(unsigned i) +{ + using Board = Genode::Board_base; + + if (i == Board::EPIT_1_IRQ) return true; + if (i == Board::EPIT_2_IRQ) return true; + if (i == Board::SDHC_IRQ) return true; + return false; +} + + +Bootstrap::Platform::Board::Board() +: early_ram_regions(Memory_region { Trustzone::SECURE_RAM_BASE, + Trustzone::SECURE_RAM_SIZE }), + core_mmio(Memory_region { UART_1_MMIO_BASE, UART_1_MMIO_SIZE }, + Memory_region { EPIT_1_MMIO_BASE, EPIT_1_MMIO_SIZE }, + Memory_region { IRQ_CONTROLLER_BASE, IRQ_CONTROLLER_SIZE }, + Memory_region { CSU_BASE, CSU_SIZE }) +{ + Aipstz aipstz_1(AIPS_1_MMIO_BASE); + Aipstz aipstz_2(AIPS_2_MMIO_BASE); + + /* set exception vector entry */ + Cpu::Mvbar::write(0xfff00000); //FIXME + + /* enable coprocessor 10 + 11 access for TZ VMs */ + Cpu::Nsacr::access_t v = 0; + Cpu::Nsacr::Cpnsae10::set(v, 1); + Cpu::Nsacr::Cpnsae11::set(v, 1); + Cpu::Nsacr::write(v); + + /* configure central security unit */ + Csu csu(Genode::Board_base::CSU_BASE, true, false, true, false); +} diff --git a/repos/base-hw/src/bootstrap/spec/wand_quad/board.h b/repos/base-hw/src/bootstrap/spec/wand_quad/board.h new file mode 100644 index 0000000000..218926ec39 --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/wand_quad/board.h @@ -0,0 +1,38 @@ +/* + * \brief Pbxa9 specific board definitions + * \author Stefan Kalkowski + * \date 2017-02-20 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__BOOTSTRAP__SPEC__WAND_QUAD__BOARD_H_ +#define _SRC__BOOTSTRAP__SPEC__WAND_QUAD__BOARD_H_ + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace Bootstrap { + using L2_cache = Hw::Pl310; + using Serial = Genode::Imx_uart_base; + + enum { + UART_BASE = Genode::Board_base::UART_1_MMIO_BASE, + UART_CLOCK = 0, /* dummy value, not used */ + CPU_MMIO_BASE = Genode::Board_base::CORTEX_A9_PRIVATE_MEM_BASE, + }; +} + +#endif /* _SRC__BOOTSTRAP__SPEC__WAND_QUAD__BOARD_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/wand_quad/platform.cc b/repos/base-hw/src/bootstrap/spec/wand_quad/platform.cc new file mode 100644 index 0000000000..0f4d5ccb8f --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/wand_quad/platform.cc @@ -0,0 +1,73 @@ +/* + * \brief Specific bootstrap implementations + * \author Stefan Kalkowski + * \author Josef Soentgen + * \author Martin Stein + * \date 2014-02-25 + */ + +/* + * Copyright (C) 2014-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#include +#include + +Bootstrap::Platform::Board::Board() +: early_ram_regions(Memory_region { RAM0_BASE, RAM0_SIZE }), + core_mmio(Memory_region { UART_1_MMIO_BASE, + UART_1_MMIO_SIZE }, + Memory_region { CORTEX_A9_PRIVATE_MEM_BASE, + CORTEX_A9_PRIVATE_MEM_SIZE }, + Memory_region { PL310_MMIO_BASE, + PL310_MMIO_SIZE }) +{ + Aipstz aipstz_1(AIPS_1_MMIO_BASE); + Aipstz aipstz_2(AIPS_2_MMIO_BASE); +} + + +bool Bootstrap::Cpu::errata(Bootstrap::Cpu::Errata err) { + return (err == ARM_764369) ? true : false; } + + +void Bootstrap::Cpu::wake_up_all_cpus(void * const entry) +{ + struct Src : Genode::Mmio + { + struct Scr : Register<0x0, 32> + { + struct Core_1_reset : Bitfield<14,1> {}; + struct Core_2_reset : Bitfield<15,1> {}; + struct Core_3_reset : Bitfield<16,1> {}; + struct Core_1_enable : Bitfield<22,1> {}; + struct Core_2_enable : Bitfield<23,1> {}; + struct Core_3_enable : Bitfield<24,1> {}; + }; + struct Gpr1 : Register<0x20, 32> {}; /* ep core 0 */ + struct Gpr3 : Register<0x28, 32> {}; /* ep core 1 */ + struct Gpr5 : Register<0x30, 32> {}; /* ep core 2 */ + struct Gpr7 : Register<0x38, 32> {}; /* ep core 3 */ + + Src(void * const entry) + : Genode::Mmio(Genode::Board_base::SRC_MMIO_BASE) + { + write((Gpr3::access_t)entry); + write((Gpr5::access_t)entry); + write((Gpr7::access_t)entry); + Scr::access_t v = read(); + Scr::Core_1_enable::set(v,1); + Scr::Core_1_reset::set(v,1); + Scr::Core_2_enable::set(v,1); + Scr::Core_2_reset::set(v,1); + Scr::Core_3_enable::set(v,1); + Scr::Core_3_reset::set(v,1); + write(v); + } + }; + + Src src(entry); +} diff --git a/repos/base-hw/src/bootstrap/spec/x86_64/board.h b/repos/base-hw/src/bootstrap/spec/x86_64/board.h new file mode 100644 index 0000000000..eba952cc83 --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/x86_64/board.h @@ -0,0 +1,41 @@ +/* + * \brief PC specific board definitions + * \author Stefan Kalkowski + * \date 2017-04-03 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__BOOTSTRAP__SPEC__X86_64__BOARD_H_ +#define _SRC__BOOTSTRAP__SPEC__X86_64__BOARD_H_ + +#include + +#include +#include +#include + +namespace Genode { struct Board_base {}; } + +namespace Bootstrap { + + struct Serial; + struct Pic {}; + + using Cpu = Hw::X86_64_cpu; + + enum Dummies { UART_BASE, UART_CLOCK }; +} + + +struct Bootstrap::Serial : Genode::X86_uart_base +{ + Serial(Genode::addr_t, Genode::size_t, unsigned); +}; + +#endif /* _SRC__BOOTSTRAP__SPEC__X86_64__BOARD_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/x86_64/crt0.s b/repos/base-hw/src/bootstrap/spec/x86_64/crt0.s index e2142154d7..d3169e0755 100644 --- a/repos/base-hw/src/bootstrap/spec/x86_64/crt0.s +++ b/repos/base-hw/src/bootstrap/spec/x86_64/crt0.s @@ -14,7 +14,7 @@ * under the terms of the GNU Affero General Public License version 3. */ -.include "macros.s" +.include "hw/spec/x86_64/gdt.s" .section ".text.crt0" diff --git a/repos/base-hw/src/bootstrap/spec/x86_64/crt0_translation_table.s b/repos/base-hw/src/bootstrap/spec/x86_64/crt0_translation_table.s index a519f21153..5906cf32f8 100644 --- a/repos/base-hw/src/bootstrap/spec/x86_64/crt0_translation_table.s +++ b/repos/base-hw/src/bootstrap/spec/x86_64/crt0_translation_table.s @@ -13,7 +13,7 @@ * under the terms of the GNU Affero General Public License version 3. */ -.include "macros.s" +.set MIN_PAGE_SIZE_LOG2, 12 .data diff --git a/repos/base-hw/src/bootstrap/spec/x86_64/crt0_translation_table_muen.s b/repos/base-hw/src/bootstrap/spec/x86_64/crt0_translation_table_muen.s index 264283c4b3..53502e9220 100644 --- a/repos/base-hw/src/bootstrap/spec/x86_64/crt0_translation_table_muen.s +++ b/repos/base-hw/src/bootstrap/spec/x86_64/crt0_translation_table_muen.s @@ -12,7 +12,7 @@ * under the terms of the GNU Affero General Public License version 3. */ -.include "macros.s" +.set MIN_PAGE_SIZE_LOG2, 12 .data diff --git a/repos/base-hw/src/core/include/spec/x86_64/multiboot.h b/repos/base-hw/src/bootstrap/spec/x86_64/multiboot.h similarity index 91% rename from repos/base-hw/src/core/include/spec/x86_64/multiboot.h rename to repos/base-hw/src/bootstrap/spec/x86_64/multiboot.h index 6ee665fe6d..89e05c5036 100644 --- a/repos/base-hw/src/core/include/spec/x86_64/multiboot.h +++ b/repos/base-hw/src/bootstrap/spec/x86_64/multiboot.h @@ -12,8 +12,8 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _MULTIBOOT_H_ -#define _MULTIBOOT_H_ +#ifndef _SRC__BOOTSTRAP__SPEC__X86_64__MULTIBOOT_H_ +#define _SRC__BOOTSTRAP__SPEC__X86_64__MULTIBOOT_H_ /* base includes */ #include @@ -82,4 +82,4 @@ class Genode::Multiboot_info : Mmio } }; -#endif /* _MULTIBOOT_H_ */ +#endif /* _SRC__BOOTSTRAP__SPEC__X86_64__MULTIBOOT_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/x86_64/platform.cc b/repos/base-hw/src/bootstrap/spec/x86_64/platform.cc index 7571142605..efa222dce7 100644 --- a/repos/base-hw/src/bootstrap/spec/x86_64/platform.cc +++ b/repos/base-hw/src/bootstrap/spec/x86_64/platform.cc @@ -14,7 +14,6 @@ /* core includes */ #include -#include #include #include @@ -23,12 +22,12 @@ using namespace Genode; /* contains physical pointer to multiboot */ extern "C" Genode::addr_t __initial_bx; -Platform::Board::Board() +Bootstrap::Platform::Board::Board() : core_mmio(Memory_region { 0, 0x1000 }, - Memory_region { Board::MMIO_LAPIC_BASE, - Board::MMIO_LAPIC_SIZE }, - Memory_region { Board::MMIO_IOAPIC_BASE, - Board::MMIO_IOAPIC_SIZE }, + Memory_region { Hw::Cpu_memory_map::MMIO_LAPIC_BASE, + Hw::Cpu_memory_map::MMIO_LAPIC_SIZE }, + Memory_region { Hw::Cpu_memory_map::MMIO_IOAPIC_BASE, + Hw::Cpu_memory_map::MMIO_IOAPIC_SIZE }, Memory_region { __initial_bx & ~0xFFFUL, get_page_size() }) { @@ -68,8 +67,12 @@ Platform::Board::Board() } -void Platform::enable_mmu() { - Cpu::Cr3::write(Cpu::Cr3::init((addr_t)core_pd->table_base)); } +void Bootstrap::Platform::enable_mmu() { + Cpu::Cr3::write(Cpu::Cr3::Pdb::masked((addr_t)core_pd->table_base)); } addr_t Bios_data_area::_mmio_base_virt() { return 0x1ff000; } + + +Bootstrap::Serial::Serial(addr_t, size_t, unsigned baudrate) +:X86_uart_base(Bios_data_area::singleton()->serial_port(), 0, baudrate) {} diff --git a/repos/base-hw/src/bootstrap/spec/x86_64/platform_muen.cc b/repos/base-hw/src/bootstrap/spec/x86_64/platform_muen.cc index fe500784d1..7178462c9f 100644 --- a/repos/base-hw/src/bootstrap/spec/x86_64/platform_muen.cc +++ b/repos/base-hw/src/bootstrap/spec/x86_64/platform_muen.cc @@ -12,15 +12,22 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* core includes */ -#include #include #include -using namespace Genode; +using Sinfo = Genode::Sinfo; + +enum { + TIMER_BASE_ADDR = 0xe00010000, + TIMER_SIZE = 0x1000, + TIMER_PREEMPT_BASE_ADDR = 0xe00011000, + TIMER_PREEMPT_SIZE = 0x1000, + + COM1_PORT = 0x3f8, +}; -Platform::Board::Board() +Bootstrap::Platform::Board::Board() : core_mmio(Memory_region { Sinfo::PHYSICAL_BASE_ADDR, Sinfo::SIZE }, Memory_region { TIMER_BASE_ADDR, TIMER_SIZE }, Memory_region { TIMER_PREEMPT_BASE_ADDR, TIMER_PREEMPT_SIZE }) @@ -29,11 +36,15 @@ Platform::Board::Board() Sinfo sinfo(Sinfo::PHYSICAL_BASE_ADDR); if (!sinfo.get_memregion_info("ram", ®ion)) - error("Unable to retrieve base-hw ram region"); + Genode::error("Unable to retrieve base-hw ram region"); else early_ram_regions.add(Memory_region { region.address, region.size }); } -void Platform::enable_mmu() { - Cpu::Cr3::write(Cpu::Cr3::init((addr_t)core_pd->table_base)); } +void Bootstrap::Platform::enable_mmu() { + Cpu::Cr3::write(Cpu::Cr3::Pdb::masked((addr_t)core_pd->table_base)); } + + +Bootstrap::Serial::Serial(addr_t, size_t, unsigned baudrate) +:X86_uart_base(COM1_PORT, 0, baudrate) {} diff --git a/repos/base-hw/src/bootstrap/spec/zynq/board.h b/repos/base-hw/src/bootstrap/spec/zynq/board.h new file mode 100644 index 0000000000..f3908ccc65 --- /dev/null +++ b/repos/base-hw/src/bootstrap/spec/zynq/board.h @@ -0,0 +1,38 @@ +/* + * \brief Zynq specific board definitions + * \author Stefan Kalkowski + * \date 2017-02-20 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__BOOTSTRAP__SPEC__ZYNQ__BOARD_H_ +#define _SRC__BOOTSTRAP__SPEC__ZYNQ__BOARD_H_ + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace Bootstrap { + using L2_cache = Hw::Pl310; + using Serial = Genode::Xilinx_uartps_base; + + enum { + UART_BASE = Genode::Board_base::UART_0_MMIO_BASE, + UART_CLOCK = Genode::Board_base::UART_CLOCK, + CPU_MMIO_BASE = Genode::Board_base::CORTEX_A9_PRIVATE_MEM_BASE, + }; +} + +#endif /* _SRC__BOOTSTRAP__SPEC__ZYNQ__BOARD_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/zynq/platform.cc b/repos/base-hw/src/bootstrap/spec/zynq/platform.cc index 4f7a6d9517..a88053eb30 100644 --- a/repos/base-hw/src/bootstrap/spec/zynq/platform.cc +++ b/repos/base-hw/src/bootstrap/spec/zynq/platform.cc @@ -15,18 +15,17 @@ /* core includes */ #include - -Platform::Board::Board() +Bootstrap::Platform::Board::Board() : early_ram_regions(Memory_region { RAM_0_BASE + 0x1000, RAM_0_SIZE - 0x1000 }), late_ram_regions(Memory_region { RAM_0_BASE, 0x1000 }), core_mmio(Memory_region { CORTEX_A9_PRIVATE_MEM_BASE, CORTEX_A9_PRIVATE_MEM_SIZE }, - Memory_region { KERNEL_UART_BASE, - KERNEL_UART_SIZE }, + Memory_region { UART_0_MMIO_BASE, + UART_SIZE }, Memory_region { PL310_MMIO_BASE, PL310_MMIO_SIZE }) { } -bool Cortex_a9::Board::errata(Cortex_a9::Board::Errata err) { +bool Bootstrap::Cpu::errata(Bootstrap::Cpu::Errata err) { return false; } diff --git a/repos/base-hw/src/bootstrap/thread.cc b/repos/base-hw/src/bootstrap/thread.cc index 0289934184..b20ede0f37 100644 --- a/repos/base-hw/src/bootstrap/thread.cc +++ b/repos/base-hw/src/bootstrap/thread.cc @@ -11,11 +11,8 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* base includes */ #include - -/* local includes */ -#include +#include Genode::Thread * Genode::Thread::myself() diff --git a/repos/base-hw/src/core/core_region_map.cc b/repos/base-hw/src/core/core_region_map.cc index 0efc9f8744..6cefb59e67 100644 --- a/repos/base-hw/src/core/core_region_map.cc +++ b/repos/base-hw/src/core/core_region_map.cc @@ -57,6 +57,8 @@ Core_region_map::attach(Dataspace_capability ds_cap, size_t size, return nullptr; } + using namespace Hw; + /* map the dataspace's physical pages to corresponding virtual addresses */ unsigned num_pages = page_rounded_size >> get_page_size_log2(); Page_flags const flags { ds->writable() ? RW : RO, NO_EXEC, USER, diff --git a/repos/base-hw/src/core/env.cc b/repos/base-hw/src/core/env.cc index 56559daf11..410d4f3d3a 100644 --- a/repos/base-hw/src/core/env.cc +++ b/repos/base-hw/src/core/env.cc @@ -11,11 +11,8 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* Genode includes */ -#include - -/* base-internal includes */ #include +#include - -void Genode::upgrade_pd_quota_non_blocking(Genode::size_t quota) { assert(false); } +void Genode::upgrade_pd_quota_non_blocking(Genode::size_t quota) { + ASSERT_NEVER_CALLED; } diff --git a/repos/base-hw/src/core/include/bootinfo.h b/repos/base-hw/src/core/include/bootinfo.h deleted file mode 100644 index cc2f547b8b..0000000000 --- a/repos/base-hw/src/core/include/bootinfo.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * \brief Boot information - * \author Stefan Kalkowski - * \date 2016-10-26 - */ - -/* - * Copyright (C) 2016-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _BOOTINFO_H_ -#define _BOOTINFO_H_ - -#include -#include -#include - -namespace Genode { struct Bootinfo; } - -struct Genode::Bootinfo -{ - using Table = Translation_table; - static constexpr size_t COUNT = Table::CORE_TRANS_TABLE_COUNT; - using Table_allocator = Translation_table_allocator_tpl; - using Mapping_pool = Array; - - Table * const table; - Table_allocator * const table_allocator; - Mapping_pool const elf_mappings; - Core_mmio const core_mmio; - Memory_region_array ram_regions; - - Bootinfo(Table * const table, - Table_allocator * const table_alloc, - Mapping_pool const elf_mappings, - Core_mmio const core_mmio) - : table(table), table_allocator(table_alloc), - elf_mappings(elf_mappings), core_mmio(core_mmio) {} -}; - -#endif /* _BOOTINFO_H_ */ diff --git a/repos/base-hw/src/core/include/kernel/cpu.h b/repos/base-hw/src/core/include/kernel/cpu.h index f25d198051..13c9510cb1 100644 --- a/repos/base-hw/src/core/include/kernel/cpu.h +++ b/repos/base-hw/src/core/include/kernel/cpu.h @@ -21,7 +21,7 @@ #include #include -namespace Genode { class Translation_table; } +namespace Hw { class Page_table; } namespace Kernel { @@ -80,7 +80,7 @@ class Kernel::Cpu_context : public Genode::Cpu::Context * * \param table mode-transition table */ - Cpu_context(Genode::Translation_table * const table); + Cpu_context(Hw::Page_table * const table); }; class Kernel::Cpu_domain_update : public Double_list_item diff --git a/repos/base-hw/src/core/include/kernel/cpu_scheduler.h b/repos/base-hw/src/core/include/kernel/cpu_scheduler.h index adc935031f..744bd49f8e 100644 --- a/repos/base-hw/src/core/include/kernel/cpu_scheduler.h +++ b/repos/base-hw/src/core/include/kernel/cpu_scheduler.h @@ -16,6 +16,7 @@ /* core includes */ #include +#include #include #include diff --git a/repos/base-hw/src/core/include/kernel/pd.h b/repos/base-hw/src/core/include/kernel/pd.h index d55bafe4ca..0dcfede67a 100644 --- a/repos/base-hw/src/core/include/kernel/pd.h +++ b/repos/base-hw/src/core/include/kernel/pd.h @@ -16,9 +16,9 @@ #define _CORE__INCLUDE__KERNEL__PD_H_ /* core includes */ -#include #include #include +#include namespace Genode { class Platform_pd; @@ -58,8 +58,8 @@ struct Kernel::Mode_transition_control * \param tt translation buffer of the address space * \param alloc translation table allocator used for the mapping */ - void map(Genode::Translation_table * tt, - Genode::Translation_table_allocator * alloc); + void map(Hw::Page_table & tt, + Hw::Page_table::Allocator & alloc); /** * Continue execution of client context @@ -92,12 +92,11 @@ class Kernel::Pd : public Cpu::Pd, static constexpr unsigned max_cap_ids = 1 << (sizeof(capid_t) * 8); - using Table = Genode::Translation_table; using Capid_allocator = Genode::Bit_allocator; private: - Table * const _table; + Hw::Page_table * const _table; Genode::Platform_pd * const _platform_pd; Capid_allocator _capid_alloc; Object_identity_reference_tree _cap_tree; @@ -110,7 +109,8 @@ class Kernel::Pd : public Cpu::Pd, * \param table translation table of the PD * \param platform_pd core object of the PD */ - Pd(Table * const table, Genode::Platform_pd * const platform_pd); + Pd(Hw::Page_table * const table, + Genode::Platform_pd * const platform_pd); ~Pd(); @@ -121,7 +121,7 @@ class Kernel::Pd : public Cpu::Pd, static capid_t syscall_create(void * const dst, - Genode::Translation_table * tt, + Hw::Page_table * tt, Genode::Platform_pd * const pd) { return call(call_id_new_pd(), (Call_arg)dst, @@ -136,7 +136,7 @@ class Kernel::Pd : public Cpu::Pd, ***************/ Genode::Platform_pd * platform_pd() const { return _platform_pd; } - Table * translation_table() const { return _table; } + Hw::Page_table * translation_table() const { return _table; } Capid_allocator & capid_alloc() { return _capid_alloc; } Object_identity_reference_tree & cap_tree() { return _cap_tree; } }; diff --git a/repos/base-hw/src/core/include/map_local.h b/repos/base-hw/src/core/include/map_local.h index e0501a9540..c835fc03f1 100644 --- a/repos/base-hw/src/core/include/map_local.h +++ b/repos/base-hw/src/core/include/map_local.h @@ -14,11 +14,12 @@ #ifndef _CORE__INCLUDE__MAP_LOCAL_H_ #define _CORE__INCLUDE__MAP_LOCAL_H_ -/* core includes */ -#include +#include namespace Genode { + using Hw::Page_flags; + /** * Map physical pages to core-local virtual address range * @@ -30,7 +31,7 @@ namespace Genode { * \return true on success */ bool map_local(addr_t from_phys, addr_t to_virt, size_t num_pages, - Page_flags flags = PAGE_FLAGS_KERN_DATA); + Page_flags flags = Hw::PAGE_FLAGS_KERN_DATA); /** * Unmap pages from core's address space diff --git a/repos/base-hw/src/core/include/mapping.h b/repos/base-hw/src/core/include/mapping.h deleted file mode 100644 index bf000d8297..0000000000 --- a/repos/base-hw/src/core/include/mapping.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * \brief Representation of physical to virtual memory mappings - * \author Stefan Kalkowski - * \date 2016-11-03 - */ - -/* - * Copyright (C) 2016-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _MAPPING_H_ -#define _MAPPING_H_ - -#include -#include - -namespace Genode { class Mapping; } - -class Genode::Mapping -{ - private: - - Memory_region _phys { 0, 0 }; - addr_t _virt = 0; - Page_flags _flags { RO, NO_EXEC, KERN, NO_GLOBAL, RAM, CACHED }; - - public: - - Mapping() {} - - Mapping(addr_t phys, addr_t virt, size_t size, Page_flags flags) - : _phys(phys, size), _virt(virt), _flags(flags) {} - - void print(Output & out) const - { - Genode::print(out, "physical region(", _phys, - ") => virtual address=", (void*) _virt, - " with page-flags: ", _flags, ")"); - } - - addr_t phys() const { return _phys.base; } - addr_t virt() const { return _virt; } - size_t size() const { return _phys.size; } - Page_flags flags() const { return _flags; } - - - /*********************************************** - ** Interface used by generic region_map code ** - ***********************************************/ - - Mapping(addr_t virt, addr_t phys, Cache_attribute cacheable, - bool io, unsigned size_log2, bool writeable) - : _phys(phys, 1 << size_log2), _virt(virt), - _flags { writeable ? RW : RO, EXEC, USER, NO_GLOBAL, - io ? DEVICE : RAM, cacheable } {} - - void prepare_map_operation() const {} -}; - -#endif /* _MAPPING_H_ */ diff --git a/repos/base-hw/src/core/include/pager.h b/repos/base-hw/src/core/include/pager.h index d4ec461909..aa287a61af 100644 --- a/repos/base-hw/src/core/include/pager.h +++ b/repos/base-hw/src/core/include/pager.h @@ -26,12 +26,17 @@ /* core-local includes */ #include -#include +#include #include #include namespace Genode { + /** + * Interface used by generic region_map code + */ + struct Mapping; + /** * Interface between the generic paging system and the base-hw backend */ @@ -50,6 +55,25 @@ namespace Genode enum { PAGER_EP_STACK_SIZE = sizeof(addr_t) * 2048 }; } + +struct Genode::Mapping : Hw::Mapping +{ + Mapping() {} + + Mapping(addr_t virt, + addr_t phys, + Cache_attribute cacheable, + bool io, + unsigned size_log2, + bool writeable) + : Hw::Mapping(phys, virt, 1 << size_log2, + { writeable ? Hw::RW : Hw::RO, Hw::EXEC, Hw::USER, + Hw::NO_GLOBAL, io ? Hw::DEVICE : Hw::RAM, cacheable }) {} + + void prepare_map_operation() const {} +}; + + class Genode::Ipc_pager { protected: @@ -63,10 +87,9 @@ class Genode::Ipc_pager addr_t addr; addr_t writes; addr_t signal; - }; + } _fault; - Fault_thread_regs _fault; - Mapping _mapping; + Mapping _mapping; public: diff --git a/repos/base-hw/src/core/include/platform.h b/repos/base-hw/src/core/include/platform.h index 866b770887..e850915798 100644 --- a/repos/base-hw/src/core/include/platform.h +++ b/repos/base-hw/src/core/include/platform.h @@ -21,130 +21,125 @@ #include /* base-hw includes */ +#include +#include #include #include /* core includes */ -#include -#include #include #include #include -#include +#include -namespace Genode { +namespace Genode { class Platform; }; - /** - * Manages all platform ressources - */ - class Platform : public Platform_generic - { - private: +class Genode::Platform : public Genode::Platform_generic +{ + private: - Core_mem_allocator _core_mem_alloc; /* core-accessible memory */ - Phys_allocator _io_mem_alloc; /* MMIO allocator */ - Phys_allocator _io_port_alloc; /* I/O port allocator */ - Phys_allocator _irq_alloc; /* IRQ allocator */ - Rom_fs _rom_fs; /* ROM file system */ + Core_mem_allocator _core_mem_alloc; /* core-accessible memory */ + Phys_allocator _io_mem_alloc; /* MMIO allocator */ + Phys_allocator _io_port_alloc; /* I/O port allocator */ + Phys_allocator _irq_alloc; /* IRQ allocator */ + Rom_fs _rom_fs; /* ROM file system */ - static Genode::Bootinfo const & _bootinfo(); - static Genode::Memory_region_array const & _core_virt_regions(); + static Hw::Boot_info const & _boot_info(); + static Hw::Memory_region_array const & _core_virt_regions(); - /** - * Initialize I/O port allocator - */ - void _init_io_port_alloc(); + /** + * Initialize I/O port allocator + */ + void _init_io_port_alloc(); - /** - * Initialize IO memory allocator - * - * Use byte granularity for MMIO regions because on some platforms, - * devices driven by core share a physical page with devices - * driven outside of core. Using byte granularity allows handing - * out the MMIO page to trusted user-level device drivers. - */ - void _init_io_mem_alloc(); + /** + * Initialize IO memory allocator + * + * Use byte granularity for MMIO regions because on some platforms, + * devices driven by core share a physical page with devices + * driven outside of core. Using byte granularity allows handing + * out the MMIO page to trusted user-level device drivers. + */ + void _init_io_mem_alloc(); - /** - * Perform additional platform-specific initialization. - */ - void _init_additional(); + /** + * Perform additional platform-specific initialization. + */ + void _init_additional(); - public: + public: - Platform(); + Platform(); - static addr_t mmio_to_virt(addr_t mmio); + static addr_t mmio_to_virt(addr_t mmio); - /** - * Return platform IRQ-number for user IRQ-number 'user_irq' - */ - static long irq(long const user_irq); + /** + * Return platform IRQ-number for user IRQ-number 'user_irq' + */ + static long irq(long const user_irq); - /** - * Setup mode of an IRQ to specified trigger mode and polarity - * - * \param irq_number ID of targeted interrupt - * \param trigger new interrupt trigger mode - * \param polarity new interrupt polarity setting - */ - static void setup_irq_mode(unsigned irq_number, unsigned trigger, - unsigned polarity); + /** + * Setup mode of an IRQ to specified trigger mode and polarity + * + * \param irq_number ID of targeted interrupt + * \param trigger new interrupt trigger mode + * \param polarity new interrupt polarity setting + */ + static void setup_irq_mode(unsigned irq_number, unsigned trigger, + unsigned polarity); - /** - * Get MSI-related parameters from device PCI config space - * - * \param mmconf PCI config space address of device - * \param address MSI address register value to use - * \param data MSI data register value to use - * \param irq_number IRQ to use - * - * \return true if the device is MSI-capable, false if not - */ - static bool get_msi_params(const addr_t mmconf, - addr_t &address, addr_t &data, - unsigned &irq_number); + /** + * Get MSI-related parameters from device PCI config space + * + * \param mmconf PCI config space address of device + * \param address MSI address register value to use + * \param data MSI data register value to use + * \param irq_number IRQ to use + * + * \return true if the device is MSI-capable, false if not + */ + static bool get_msi_params(const addr_t mmconf, + addr_t &address, addr_t &data, + unsigned &irq_number); - static addr_t core_phys_addr(addr_t virt); + static addr_t core_phys_addr(addr_t virt); - static Translation_table * core_translation_table(); - - static Translation_table_allocator * core_translation_table_allocator(); + static Hw::Page_table & core_page_table(); + static Hw::Page_table::Allocator & core_page_table_allocator(); - /******************************** - ** Platform_generic interface ** - ********************************/ + /******************************** + ** Platform_generic interface ** + ********************************/ - Range_allocator * core_mem_alloc() { - return &_core_mem_alloc; } + Range_allocator * core_mem_alloc() { + return &_core_mem_alloc; } - Range_allocator * ram_alloc() { - return _core_mem_alloc.phys_alloc(); } + Range_allocator * ram_alloc() { + return _core_mem_alloc.phys_alloc(); } - Range_allocator * region_alloc() { - return _core_mem_alloc.virt_alloc(); } + Range_allocator * region_alloc() { + return _core_mem_alloc.virt_alloc(); } - Range_allocator * io_mem_alloc() { return &_io_mem_alloc; } + Range_allocator * io_mem_alloc() { return &_io_mem_alloc; } - Range_allocator * io_port_alloc() { return &_io_port_alloc; } + Range_allocator * io_port_alloc() { return &_io_port_alloc; } - Range_allocator * irq_alloc() { return &_irq_alloc; } + Range_allocator * irq_alloc() { return &_irq_alloc; } - addr_t vm_start() const { return VIRT_ADDR_SPACE_START; } + addr_t vm_start() const { return VIRT_ADDR_SPACE_START; } - size_t vm_size() const { return VIRT_ADDR_SPACE_SIZE; } + size_t vm_size() const { return VIRT_ADDR_SPACE_SIZE; } - Rom_fs *rom_fs() { return &_rom_fs; } + Rom_fs *rom_fs() { return &_rom_fs; } - inline void wait_for_exit() { - while (1) { Kernel::stop_thread(); } }; + inline void wait_for_exit() { + while (1) { Kernel::stop_thread(); } }; - bool supports_direct_unmap() const { return 1; } + bool supports_direct_unmap() const { return 1; } - Affinity::Space affinity_space() const { - return Affinity::Space(NR_OF_CPUS); } - }; -} + Affinity::Space affinity_space() const { + return Affinity::Space(NR_OF_CPUS); } +}; #endif /* _CORE__INCLUDE__PLATFORM_H_ */ diff --git a/repos/base-hw/src/core/include/platform_pd.h b/repos/base-hw/src/core/include/platform_pd.h index 118e16bd9d..c7380df91c 100644 --- a/repos/base-hw/src/core/include/platform_pd.h +++ b/repos/base-hw/src/core/include/platform_pd.h @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -51,6 +51,8 @@ namespace Genode * Platform specific part of Core's protection domain */ class Core_platform_pd; + + using Hw::Page_flags; } @@ -61,14 +63,14 @@ class Hw::Address_space : public Genode::Address_space friend class Genode::Platform; friend class Genode::Mapped_mem_allocator; - using Table_allocator = - Translation_table_allocator_tpl; - - Genode::Lock _lock; /* table lock */ - Genode::Translation_table * _tt; /* table virt addr */ - Genode::Translation_table * _tt_phys; /* table phys addr */ - Genode::Translation_table_allocator * _tt_alloc; /* table allocator */ - Kernel::Pd * _kernel_pd; + using Table = Hw::Page_table; + using Array = Table::Allocator::Array; + Genode::Lock _lock; /* table lock */ + Table & _tt; /* table virt addr */ + Genode::addr_t _tt_phys; /* table phys addr */ + Array * _tt_array = nullptr; + Table::Allocator & _tt_alloc; /* table allocator */ + Kernel::Pd & _kernel_pd; static inline Genode::Core_mem_allocator * _cma(); static inline void * _table_alloc(); @@ -83,9 +85,9 @@ class Hw::Address_space : public Genode::Address_space * \param tt pointer to translation table * \param tt_alloc pointer to translation table allocator */ - Address_space(Kernel::Pd * pd, - Genode::Translation_table * tt, - Genode::Translation_table_allocator * tt_alloc); + Address_space(Kernel::Pd & pd, + Hw::Page_table & tt, + Hw::Page_table::Allocator & tt_alloc); public: @@ -94,7 +96,7 @@ class Hw::Address_space : public Genode::Address_space * * \param pd pointer to kernel's pd object */ - Address_space(Kernel::Pd* pd); + Address_space(Kernel::Pd & pd); ~Address_space(); @@ -121,10 +123,9 @@ class Hw::Address_space : public Genode::Address_space ** Accessors ** ***************/ - Kernel::Pd * kernel_pd() { return _kernel_pd; } - Genode::Translation_table * translation_table() { return _tt; } - Genode::Translation_table * translation_table_phys() { - return _tt_phys; } + Kernel::Pd & kernel_pd() { return _kernel_pd; } + Hw::Page_table & translation_table() { return _tt; } + Genode::addr_t translation_table_phys() { return _tt_phys; } }; @@ -168,8 +169,8 @@ class Genode::Platform_pd : public Hw::Address_space, * \param tt translation table address * \param tt_alloc translation table allocator */ - Platform_pd(Translation_table * tt, - Translation_table_allocator * tt_alloc); + Platform_pd(Hw::Page_table & tt, + Hw::Page_table::Allocator & tt_alloc); public: diff --git a/repos/base-hw/src/core/include/signal_broker.h b/repos/base-hw/src/core/include/signal_broker.h index 79e7f6b9fe..bc4e191b08 100644 --- a/repos/base-hw/src/core/include/signal_broker.h +++ b/repos/base-hw/src/core/include/signal_broker.h @@ -18,7 +18,6 @@ #include /* core-local includes */ -#include #include namespace Genode { class Signal_broker; } diff --git a/repos/base-hw/src/core/include/spec/arm/cpu_support.h b/repos/base-hw/src/core/include/spec/arm/cpu_support.h index 9eeb422cc1..435330f504 100644 --- a/repos/base-hw/src/core/include/spec/arm/cpu_support.h +++ b/repos/base-hw/src/core/include/spec/arm/cpu_support.h @@ -69,65 +69,6 @@ class Genode::Arm } }; - /** - * System control register - */ - struct Sctlr : Register<32> - { - struct M : Bitfield<0,1> { }; /* enable MMU */ - struct A : Bitfield<1,1> { }; /* enable alignment checks */ - struct C : Bitfield<2,1> { }; /* enable data cache */ - struct I : Bitfield<12,1> { }; /* enable instruction caches */ - struct V : Bitfield<13,1> { }; /* select exception entry */ - - static access_t read() - { - access_t v; - asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r" (v) :: ); - return v; - } - - static void write(access_t const v) { - asm volatile ("mcr p15, 0, %0, c1, c0, 0" :: "r" (v) : ); } - - static void init() - { - access_t v = read(); - - /* disable alignment checks */ - A::set(v, 0); - - /* set exception vector to 0xffff0000 */ - V::set(v, 1); - write(v); - } - - static void enable_mmu_and_caches() - { - access_t v = read(); - C::set(v, 1); - I::set(v, 1); - M::set(v, 1); - write(v); - } - }; - - /** - * Translation table base control register - */ - struct Ttbcr : Register<32> - { - static void write(access_t const v) { - asm volatile ("mcr p15, 0, %0, c2, c0, 2" :: "r" (v) : ); } - - static access_t read() - { - access_t v; - asm volatile ("mrc p15, 0, %0, c2, c0, 2" : "=r" (v) :: ); - return v; - } - }; - /** * Translation table base register 0 */ @@ -480,13 +421,13 @@ class Genode::Arm /** * Invalidate all entries of all instruction caches */ - void invalidate_instr_cache() { + static void invalidate_instr_cache() { asm volatile ("mcr p15, 0, %0, c7, c5, 0" :: "r" (0) : ); } /** * Flush all entries of all data caches */ - void clean_invalidate_data_cache(); + static void clean_invalidate_data_cache(); /** * Invalidate all branch predictions @@ -494,22 +435,6 @@ class Genode::Arm static void invalidate_branch_predicts() { asm volatile ("mcr p15, 0, r0, c7, c5, 6" ::: "r0"); }; - /** - * Switch on MMU and caches - * - * \param table page tables physical address - */ - void enable_mmu_and_caches(Genode::addr_t table) - { - invalidate_tlb(); - Cidr::write(0); - Dacr::write(Dacr::init_virt_kernel()); - Ttbr0::write(Ttbr0::init(table)); - Ttbcr::write(0); - Sctlr::enable_mmu_and_caches(); - invalidate_branch_predicts(); - } - /** * Invalidate all TLB entries of the address space named 'pid' */ diff --git a/repos/base-hw/src/core/include/spec/arm/short_translation_table.h b/repos/base-hw/src/core/include/spec/arm/short_translation_table.h deleted file mode 100644 index 157edf4fd7..0000000000 --- a/repos/base-hw/src/core/include/spec/arm/short_translation_table.h +++ /dev/null @@ -1,590 +0,0 @@ -/* - * \brief Short descriptor translation table definitions - * \author Martin Stein - * \author Stefan Kalkowski - * \date 2012-02-22 - */ - -/* - * Copyright (C) 2012-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _CORE__INCLUDE__SPEC__ARM__SHORT_TRANSLATION_TABLE_H_ -#define _CORE__INCLUDE__SPEC__ARM__SHORT_TRANSLATION_TABLE_H_ - -/* Genode includes */ -#include - -/* core includes */ -#include -#include -#include -#include -#include - -namespace Genode -{ - /** - * Commons for all translations - */ - class Translation; - - /** - * Second level translation table - */ - class Page_table; - - /** - * First level translation table - */ - class Translation_table; -} - -class Genode::Translation -{ - private: - - /** - * Return TEX value for device-memory translations - */ - static constexpr unsigned _device_tex(); - - protected: - - /** - * Return translation according to flags 'f' and phys. address 'pa' - */ - template static typename T::access_t - _create(Page_flags const & f, addr_t const pa) - { - typename T::access_t v = T::Pa::masked(pa); - T::S::set(v, Board::SMP); - T::Ng::set(v, !f.global); - T::Xn::set(v, !f.executable); - if (f.type == DEVICE) { - T::Tex::set(v, _device_tex()); - } else { - switch (f.cacheable) { - case CACHED: T::Tex::set(v, 5); - case WRITE_COMBINED: T::B::set(v, 1); break; - case UNCACHED: T::Tex::set(v, 1); break; - } - } - if (f.writeable) if (f.privileged) T::Ap::set(v, 1); - else T::Ap::set(v, 3); - else if (f.privileged) T::Ap::set(v, 5); - else T::Ap::set(v, 2); - return v; - } -}; - -class Genode::Page_table -{ - public: - - enum { - SIZE_LOG2 = 10, - SIZE = 1 << SIZE_LOG2, - ALIGNM_LOG2 = SIZE_LOG2, - }; - - /** - * Common descriptor structure - */ - struct Descriptor : Register<32>, Translation - { - enum Type { FAULT, SMALL_PAGE }; - - enum { - VIRT_SIZE_LOG2 = 12, - VIRT_SIZE = 1 << VIRT_SIZE_LOG2, - VIRT_OFFSET_MASK = (1 << VIRT_SIZE_LOG2) - 1, - VIRT_BASE_MASK = ~(VIRT_OFFSET_MASK), - }; - - struct Type_0 : Bitfield<0, 2> { }; - struct Type_1 : Bitfield<1, 1> { }; - - /** - * Get descriptor type of 'v' - */ - static Type type(access_t const v) - { - access_t const t0 = Type_0::get(v); - if (t0 == 0) { return FAULT; } - access_t const t1 = Type_1::get(v); - if (t1 == 1) { return SMALL_PAGE; } - return FAULT; - } - - /** - * At descriptor value 'v' set type to 't' - */ - static void type(access_t & v, Type const t) - { - switch (t) { - case FAULT: Type_0::set(v, 0); return; - case SMALL_PAGE: Type_1::set(v, 1); return; } - } - - static void invalidate(access_t & v) { type(v, FAULT); } - - static bool valid(access_t & v) { return type(v) != FAULT; } - }; - - /** - * Small page descriptor structure - */ - struct Small_page : Descriptor - { - struct Xn : Bitfield<0, 1> { }; /* execute never */ - struct B : Bitfield<2, 1> { }; /* mem region attr. */ - struct Ap_0 : Bitfield<4, 2> { }; /* access permission */ - struct Tex : Bitfield<6, 3> { }; /* mem region attr. */ - struct Ap_1 : Bitfield<9, 1> { }; /* access permission */ - struct S : Bitfield<10, 1> { }; /* shareable bit */ - struct Ng : Bitfield<11, 1> { }; /* not global bit */ - struct Pa : Bitfield<12, 20> { }; /* physical base */ - struct Ap : Bitset_2 { }; /* access permission */ - - /** - * Return page descriptor for physical address 'pa' and 'flags' - */ - static access_t create(Page_flags const & flags, addr_t const pa) - { - access_t v = _create(flags, pa); - Descriptor::type(v, Descriptor::SMALL_PAGE); - return v; - } - }; - - private: - - /* table payload that must be the only member of this class */ - Descriptor::access_t _entries[SIZE/sizeof(Descriptor::access_t)]; - - enum { MAX_INDEX = sizeof(_entries) / sizeof(_entries[0]) - 1 }; - - /** - * Get entry index by virtual offset - * - * \param i is overridden with the index if call returns 0 - * \param vo virtual offset relative to the virtual table base - * - * \retval 0 on success - * \retval <0 translation failed - */ - bool _index_by_vo (unsigned & i, addr_t const vo) const - { - if (vo > max_virt_offset()) return false; - i = vo >> Descriptor::VIRT_SIZE_LOG2; - return true; - } - - public: - - /** - * Constructor - */ - Page_table() - { - assert(aligned(this, ALIGNM_LOG2)); - memset(&_entries, 0, sizeof(_entries)); - } - - /** - * Maximum virtual offset that can be translated by this table - */ - static addr_t max_virt_offset() - { - return (MAX_INDEX << Descriptor::VIRT_SIZE_LOG2) - + (Descriptor::VIRT_SIZE - 1); - } - - /** - * Insert one atomic translation into this table - * - * \param vo offset of the virtual region represented - * by the translation within the virtual - * region represented by this table - * \param pa base of the physical backing store - * \param size size of the translated region - * \param flags mapping flags - */ - void insert_translation(addr_t vo, - addr_t pa, - size_t size, - Page_flags const & flags) - { - constexpr size_t sz = Descriptor::VIRT_SIZE; - - for (unsigned i; (size > 0) && _index_by_vo(i, vo); - size = (size < sz) ? 0 : size - sz, - vo += sz, pa += sz) - { - - /* compose new descriptor value */ - Small_page::access_t const e = - Small_page::create(flags, pa); - - /* check if it is a good idea to override the entry */ - assert(!Descriptor::valid(_entries[i]) || - _entries[i] == e); - - /* override entry */ - _entries[i] = e; - - /* some CPUs need to act on changed translations */ - Cpu::translation_added((addr_t)&_entries[i], - sizeof(Descriptor::access_t)); - } - } - - /** - * Remove translations that overlap with a given virtual region - * - * \param vo region offset within the tables virtual region - * \param size region size - */ - void remove_translation(addr_t vo, size_t size) - { - constexpr size_t sz = Descriptor::VIRT_SIZE; - - for (unsigned i; (size > 0) && _index_by_vo(i, vo); - size = (size < sz) ? 0 : size - sz, vo += sz) - { - switch (Descriptor::type(_entries[i])) { - case Descriptor::SMALL_PAGE: - Descriptor::invalidate(_entries[i]); - default: ; - } - } - } - - /** - * Does this table solely contain invalid entries - */ - bool empty() - { - for (unsigned i = 0; i <= MAX_INDEX; i++) { - if (Descriptor::valid(_entries[i])) return false; } - return true; - } - -} __attribute__((aligned(1<, Translation - { - enum Type { FAULT, PAGE_TABLE, SECTION }; - - enum { - VIRT_SIZE_LOG2 = 20, - VIRT_SIZE = 1 << VIRT_SIZE_LOG2, - VIRT_OFFSET_MASK = (1 << VIRT_SIZE_LOG2) - 1, - VIRT_BASE_MASK = ~VIRT_OFFSET_MASK, - }; - - struct Type_0 : Bitfield<0, 2> { }; - struct Type_1_0 : Bitfield<1, 1> { }; - struct Type_1_1 : Bitfield<18, 1> { }; - struct Type_1 : Bitset_2 { }; - - /** - * Get descriptor type of 'v' - */ - static Type type(access_t const v) - { - switch (Type_0::get(v)) { - case 0: return FAULT; - case 1: return PAGE_TABLE; } - - if (Type_1::get(v) == 1) { return SECTION; } - return FAULT; - } - - /** - * Set descriptor type of 'v' - */ - static void type(access_t & v, Type const t) - { - switch (t) { - case FAULT: Type_0::set(v, 0); return; - case PAGE_TABLE: Type_0::set(v, 1); return; - case SECTION: Type_1::set(v, 1); return; } - } - - static void invalidate(access_t & v) { type(v, FAULT); } - - static bool valid(access_t & v) { return type(v) != FAULT; } - - static inline Type align(addr_t vo, addr_t pa, size_t size) - { - return ((vo & VIRT_OFFSET_MASK) || (pa & VIRT_OFFSET_MASK) || - size < VIRT_SIZE) ? PAGE_TABLE : SECTION; - } - }; - - /** - * Link to a second level translation table - */ - struct Page_table_descriptor : Descriptor - { - struct Domain : Bitfield<5, 4> { }; /* domain */ - struct Pa : Bitfield<10, 22> { }; /* physical base */ - - /** - * Return descriptor value for page table 'pt - */ - static access_t create(Page_table * const pt) - { - access_t v = Pa::masked((addr_t)pt); - Descriptor::type(v, Descriptor::PAGE_TABLE); - return v; - } - }; - - /** - * Section translation descriptor - */ - struct Section : Descriptor - { - struct B : Bitfield<2, 1> { }; /* mem. region attr. */ - struct Xn : Bitfield<4, 1> { }; /* execute never bit */ - struct Ap_0 : Bitfield<10, 2> { }; /* access permission */ - struct Tex : Bitfield<12, 3> { }; /* mem. region attr. */ - struct Ap_1 : Bitfield<15, 1> { }; /* access permission */ - struct S : Bitfield<16, 1> { }; /* shared */ - struct Ng : Bitfield<17, 1> { }; /* not global */ - struct Pa : Bitfield<20, 12> { }; /* physical base */ - struct Ap : Bitset_2 { }; /* access permission */ - - /** - * Return section descriptor for physical address 'pa' and 'flags' - */ - static access_t create(Page_flags const & flags, addr_t const pa) - { - access_t v = _create
(flags, pa); - Descriptor::type(v, Descriptor::SECTION); - return v; - } - }; - - protected: - - /* table payload, must be the first member of this class */ - Descriptor::access_t _entries[SIZE/sizeof(Descriptor::access_t)]; - - enum { MAX_INDEX = sizeof(_entries) / sizeof(_entries[0]) - 1 }; - - /** - * Try to get entry index in 'i' for virtual offset 'vo! - * - * \return whether it was successful - */ - bool _index_by_vo(unsigned & i, addr_t const vo) const - { - if (vo > max_virt_offset()) return false; - i = vo >> Descriptor::VIRT_SIZE_LOG2; - return true; - } - - /** - * Insert a second level translation at the given entry index - * - * \param i the related index - * \param vo virtual start address of range - * \param pa physical start address of range - * \param size size of range - * \param flags mapping flags - * \param alloc second level translation table allocator - */ - void _insert_second_level(unsigned i, addr_t const vo, addr_t const pa, - size_t const size, Page_flags const & flags, - Translation_table_allocator * const alloc) - { - Page_table * pt = 0; - switch (Descriptor::type(_entries[i])) { - - case Descriptor::FAULT: - { - if (!alloc) throw Allocator::Out_of_memory(); - - /* create and link page table */ - pt = new (alloc) Page_table(); - Page_table * pt_phys = (Page_table*) alloc->phys_addr(pt); - pt_phys = pt_phys ? pt_phys : pt; /* hack for core */ - _entries[i] = Page_table_descriptor::create(pt_phys); - - /* some CPUs need to act on changed translations */ - size_t const dsize = sizeof(Descriptor::access_t); - Cpu::translation_added((addr_t)&_entries[i], dsize); - } - - case Descriptor::PAGE_TABLE: - { - /* use allocator to retrieve virtual addr. of page table */ - void * pt_phys = (void*) - Page_table_descriptor::Pa::masked(_entries[i]); - pt = (Page_table *) alloc->virt_addr(pt_phys); - pt = pt ? pt : (Page_table *)pt_phys ; /* hack for core */ - break; - } - - default: assert(0); - } - - /* insert translation */ - addr_t const pt_vo = vo - Section::Pa::masked(vo); - pt->insert_translation(pt_vo, pa, size, flags); - } - - public: - - /** - * Constructor - */ - Translation_table() - { - assert(aligned(this, ALIGNM_LOG2)); - memset(&_entries, 0, sizeof(_entries)); - } - - /** - * Maximum virtual offset that can be translated by this table - */ - static addr_t max_virt_offset() - { - constexpr addr_t base = MAX_INDEX << Descriptor::VIRT_SIZE_LOG2; - return base + (Descriptor::VIRT_SIZE - 1); - } - - /** - * Insert translations into this table - * - * \param vo offset of virt. transl. region in virt. table region - * \param pa base of physical backing store - * \param size size of translated region - * \param f mapping flags - * \param alloc second level translation table allocator - */ - void insert_translation(addr_t vo, addr_t pa, size_t size, - Page_flags const & f, - Translation_table_allocator * const alloc) - { - /* check sanity */ - assert(!(vo & Page_table::Descriptor::VIRT_OFFSET_MASK) && - size >= Page_table::Descriptor::VIRT_SIZE); - - for (unsigned i; (size > 0) && _index_by_vo (i, vo);) { - - addr_t const ve = (vo + Descriptor::VIRT_SIZE); - addr_t const end = ve & Descriptor::VIRT_BASE_MASK; - - /* decide granularity of entry that can be inserted */ - switch (Descriptor::align(vo, pa, size)) { - - case Descriptor::SECTION: - { - /* compose new entry */ - Section::access_t const e = Section::create(f, pa); - - /* override entry */ - if (_entries[i] == e) { break; } - assert(!Descriptor::valid(_entries[i])); - _entries[i] = e; - - /* some CPUs need to act on changed translations */ - constexpr size_t ds = sizeof(Descriptor::access_t); - Cpu::translation_added((addr_t)&_entries[i], ds); - break; - } - - default: - _insert_second_level(i, vo, pa, min(size, end - vo), f, - alloc); - }; - - /* check whether we wrap */ - if (end < vo) { return; } - - size_t sz = end - vo; - size = (size > sz) ? size - sz : 0; - vo += sz; - pa += sz; - } - } - - /** - * Remove translations that overlap with a given virtual region - * - * \param vo region offset within the tables virtual region - * \param size region size - * \param alloc second level translation table allocator - */ - void remove_translation(addr_t vo, size_t size, - Translation_table_allocator * alloc) - { - /* check sanity */ - assert(vo <= (vo + size)); - - for (unsigned i; (size > 0) && _index_by_vo(i, vo);) { - - constexpr addr_t dbm = Descriptor::VIRT_BASE_MASK; - addr_t const end = (vo + Descriptor::VIRT_SIZE) & dbm; - - switch (Descriptor::type(_entries[i])) { - - case Descriptor::PAGE_TABLE: - { - typedef Page_table_descriptor Ptd; - typedef Page_table Pt; - - Pt * pt_phys = (Pt *) Ptd::Pa::masked(_entries[i]); - Pt * pt = (Pt *) alloc->virt_addr(pt_phys); - pt = pt ? pt : pt_phys; // TODO hack for core - - addr_t const pt_vo = vo - Section::Pa::masked(vo); - pt->remove_translation(pt_vo, min(size, end-vo)); - - if (pt->empty()) { - Descriptor::invalidate(_entries[i]); - destroy(alloc, pt); - } - break; - } - - default: Descriptor::invalidate(_entries[i]); } - - /* check whether we wrap */ - if (end < vo) return; - - size_t sz = end - vo; - size = (size > sz) ? size - sz : 0; - vo += sz; - } - } -} __attribute__((aligned(1< - -/* core includes */ -#include - -namespace Genode -{ - /** - * Disributor of the ARM generic interrupt controller - */ - class Arm_gic_distributor; - - /** - * CPU interface of the ARM generic interrupt controller - */ - class Arm_gic_cpu_interface; - - /** - * Programmable interrupt controller for core - */ - class Pic; -} +#include +namespace Genode { class Pic; } namespace Kernel { using Pic = Genode::Pic; } - -class Genode::Arm_gic_distributor : public Mmio -{ - public: - - static constexpr unsigned nr_of_irq = 1024; - - /** - * Control register - */ - struct Ctlr : Register<0x000, 32> - { - struct Enable : Bitfield<0,1> { }; - struct Enable_grp0 : Bitfield<0,1> { }; - struct Enable_grp1 : Bitfield<1,1> { }; - }; - - /** - * Controller type register - */ - struct Typer : Register<0x004, 32> { - struct It_lines_number : Bitfield<0,5> { }; }; - - /** - * Interrupt group register - */ - struct Igroupr : Register_array<0x80, 32, nr_of_irq, 1> { - struct Group_status : Bitfield<0, 1> { }; }; - - /** - * Interrupt set enable registers - */ - struct Isenabler : Register_array<0x100, 32, nr_of_irq, 1, true> { - struct Set_enable : Bitfield<0, 1> { }; }; - - /** - * Interrupt clear enable registers - */ - struct Icenabler : Register_array<0x180, 32, nr_of_irq, 1, true> { - struct Clear_enable : Bitfield<0, 1> { }; }; - - /** - * Interrupt priority level registers - */ - struct Ipriorityr : Register_array<0x400, 32, nr_of_irq, 8> { - struct Priority : Bitfield<0, 8> { }; }; - - /** - * Interrupt CPU-target registers - */ - struct Itargetsr : Register_array<0x800, 32, nr_of_irq, 8> { - struct Cpu_targets : Bitfield<0, 8> { }; }; - - /** - * Interrupt configuration registers - */ - struct Icfgr : Register_array<0xc00, 32, nr_of_irq, 2> { - struct Edge_triggered : Bitfield<1, 1> { }; }; - - /** - * Software generated interrupt register - */ - struct Sgir : Register<0xf00, 32> - { - struct Sgi_int_id : Bitfield<0, 4> { }; - struct Cpu_target_list : Bitfield<16, 8> { }; - struct Target_list_filter : Bitfield<24, 2> - { - enum Target { TARGET_LIST, ALL_OTHER, MYSELF }; - }; - }; - - /** - * Constructor - */ - Arm_gic_distributor(addr_t const base) : Mmio(base) { } - - /** - * Return minimum IRQ priority - */ - unsigned min_priority() - { - write(~0, 0); - return read(0); - } - - /** - * Return highest IRQ number - */ - unsigned max_irq() - { - constexpr unsigned line_width_log2 = 5; - Typer::access_t const lnr = read(); - return ((lnr + 1) << line_width_log2) - 1; - } -}; - -class Genode::Arm_gic_cpu_interface : public Mmio -{ - public: - - /** - * Control register - */ - struct Ctlr : Register<0x00, 32> - { - struct Enable : Bitfield<0,1> { }; - struct Enable_grp0 : Bitfield<0,1> { }; - struct Enable_grp1 : Bitfield<1,1> { }; - struct Fiq_en : Bitfield<3,1> { }; - }; - - /** - * Priority mask register - */ - struct Pmr : Register<0x04, 32> { - struct Priority : Bitfield<0,8> { }; }; - - /** - * Binary point register - */ - struct Bpr : Register<0x08, 32> { - struct Binary_point : Bitfield<0,3> { }; }; - - /** - * Interrupt acknowledge register - */ - struct Iar : Register<0x0c, 32, true> { - struct Irq_id : Bitfield<0,10> { }; }; - - /** - * End of interrupt register - */ - struct Eoir : Register<0x10, 32, true> { - struct Irq_id : Bitfield<0,10> { }; }; - - /** - * Constructor - */ - Arm_gic_cpu_interface(addr_t const base) : Mmio(base) { } -}; - -class Genode::Pic +class Genode::Pic : public Hw::Pic { public: enum { IPI = 1 }; - protected: - - typedef Arm_gic_cpu_interface Cpui; - typedef Arm_gic_distributor Distr; - - static constexpr unsigned min_spi = 32; - static constexpr unsigned spurious_id = 1023; - - Distr _distr; - Cpui _cpui; - Cpui::Iar::access_t _last_iar; - unsigned const _max_irq; - - void _init(); - - bool _valid(unsigned const irq_id) const { return irq_id <= _max_irq; } - - public: - - enum { NR_OF_IRQ = Distr::nr_of_irq }; - - Pic(); - - /** - * Initialize CPU local interface of the controller - */ - void init_cpu_local(); - - /** - * Try to take an IRQ and return wether it was successful - * - * \param irq contains kernel name of taken IRQ on success - */ - bool take_request(unsigned & irq) - { - _last_iar = _cpui.read(); - irq = Cpui::Iar::Irq_id::get(_last_iar); - return _valid(irq); - } - - /** - * End the last taken IRQ - */ - void finish_request() - { - _cpui.write(_last_iar); - _last_iar = Cpui::Iar::Irq_id::bits(spurious_id); - } - - /** - * Unmask IRQ and assign it to one CPU - * - * \param irq_id kernel name of targeted IRQ - * \param cpu_id kernel name of targeted CPU - */ - void unmask(unsigned const irq_id, unsigned const cpu_id) - { - unsigned const targets = 1 << cpu_id; - _distr.write(targets, irq_id); - _distr.write(1, irq_id); - } - - /** - * Mask IRQ with kernel name 'irq_id' - */ - void mask(unsigned const irq_id) { - _distr.write(1, irq_id); } - /** * Raise inter-processor IRQ of the CPU with kernel name 'cpu_id' */ void send_ipi(unsigned const cpu_id) { - typedef Distr::Sgir Sgir; + using Sgir = Distributor::Sgir; Sgir::access_t sgir = 0; Sgir::Sgi_int_id::set(sgir, IPI); Sgir::Cpu_target_list::set(sgir, 1 << cpu_id); @@ -274,7 +43,7 @@ class Genode::Pic */ void send_ipi() { - typedef Distr::Sgir Sgir; + using Sgir = Distributor::Sgir; Sgir::access_t sgir = 0; Sgir::Sgi_int_id::set(sgir, IPI); Sgir::Target_list_filter::set(sgir, diff --git a/repos/base-hw/src/core/include/spec/arm_v6/cpu.h b/repos/base-hw/src/core/include/spec/arm_v6/cpu.h index 015951409e..f6b293da3e 100644 --- a/repos/base-hw/src/core/include/spec/arm_v6/cpu.h +++ b/repos/base-hw/src/core/include/spec/arm_v6/cpu.h @@ -17,8 +17,6 @@ /* core includes */ #include -#include -#include namespace Genode { class Cpu; } @@ -35,53 +33,18 @@ class Genode::Cpu : public Arm struct P : Bitfield<23, 1> { }; /* page mapping restriction on */ }; - /** - * System control register - */ - struct Sctlr : Arm::Sctlr - { - struct W : Bitfield<3,1> { }; /* enable write buffer */ - struct Dt : Bitfield<16,1> { }; /* global data TCM enable */ - struct It : Bitfield<18,1> { }; /* global instruction TCM enable */ - struct U : Bitfield<22,1> { }; /* enable unaligned data access */ - struct Xp : Bitfield<23,1> { }; /* disable subpage AP bits */ - - static void init() - { - access_t v = read(); - A::set(v, 0); - V::set(v, 1); - W::set(v, 1); - Dt::set(v, 1); - It::set(v, 1); - U::set(v, 1); - Xp::set(v, 1); - write(v); - } - }; - /** * If page descriptor bits [13:12] are restricted */ static bool restricted_page_mappings() { return Ctr::P::get(Ctr::read()); } - /** - * Post processing after a translation was added to a translation table - * - * \param addr virtual address of the translation - * \param size size of the translation - */ - static void translation_added(addr_t const addr, size_t const size); - /************* ** Dummies ** *************/ static void wait_for_interrupt() { /* FIXME */ } - static void data_synchronization_barrier() { /* FIXME */ } - static void invalidate_control_flow_predictions() { /* FIXME */ } }; #endif /* _CORE__INCLUDE__SPEC__ARM_V6__CPU_H_ */ diff --git a/repos/base-hw/src/core/include/spec/arm_v6/translation_table.h b/repos/base-hw/src/core/include/spec/arm_v6/translation_table.h index 7ffc9d047e..761f306c2c 100644 --- a/repos/base-hw/src/core/include/spec/arm_v6/translation_table.h +++ b/repos/base-hw/src/core/include/spec/arm_v6/translation_table.h @@ -15,9 +15,20 @@ #ifndef _CORE__INCLUDE__SPEC__ARM_V6__TRANSLATION_TABLE_H_ #define _CORE__INCLUDE__SPEC__ARM_V6__TRANSLATION_TABLE_H_ -/* core includes */ -#include +#include +#include -constexpr unsigned Genode::Translation::_device_tex() { return 0; } +#include + +constexpr unsigned Hw::Page_table::Descriptor_base::_device_tex() { + return 0; } + +constexpr bool Hw::Page_table::Descriptor_base::_smp() { return false; } + +void Hw::Page_table::_translation_added(unsigned long addr, unsigned long size) +{ + if (Genode::Cpu::is_user()) Kernel::update_data_region(addr, size); + else Genode::Cpu::clean_invalidate_data_cache(); +} #endif /* _CORE__INCLUDE__SPEC__ARM_V6__TRANSLATION_TABLE_H_ */ diff --git a/repos/base-hw/src/core/include/spec/arm_v7/cpu_support.h b/repos/base-hw/src/core/include/spec/arm_v7/cpu_support.h index 00641e3af5..4aee68a52b 100644 --- a/repos/base-hw/src/core/include/spec/arm_v7/cpu_support.h +++ b/repos/base-hw/src/core/include/spec/arm_v7/cpu_support.h @@ -81,30 +81,6 @@ class Genode::Arm_v7 : public Arm } }; - /** - * System control register - */ - struct Sctlr : Arm::Sctlr - { - struct Z : Bitfield<11,1> { }; /* enable program flow prediction */ - - static access_t init_value() - { - access_t v = read(); - C::set(v, 1); - I::set(v, 1); - V::set(v, 1); - A::set(v, 0); - M::set(v, 1); - Z::set(v, 1); - return v; - } - - static void enable_mmu_and_caches() { - write(init_value()); } - }; - - /** * Memory attribute indirection register 0 */ @@ -119,11 +95,6 @@ class Genode::Arm_v7 : public Arm asm volatile ("mcr p15, 0, %[v], c10, c2, 0" :: [v]"r"(v) : ); } }; - /** - * Finish all previous data transfers - */ - static void data_synchronization_barrier() { asm volatile ("dsb"); } - /** * Wait for the next interrupt as cheap as possible */ @@ -132,12 +103,12 @@ class Genode::Arm_v7 : public Arm /** * Write back dirty lines of inner data cache and invalidate all */ - void clean_invalidate_inner_data_cache(); + static void clean_invalidate_inner_data_cache(); /** * Invalidate all lines of the inner data cache */ - void invalidate_inner_data_cache(); + static void invalidate_inner_data_cache(); /** * Invalidate all lines of the instruction cache diff --git a/repos/base-hw/src/core/include/spec/arm_v7/virtualization/vm_session_component.h b/repos/base-hw/src/core/include/spec/arm_v7/virtualization/vm_session_component.h index df4923bb77..ae748fd1e6 100644 --- a/repos/base-hw/src/core/include/spec/arm_v7/virtualization/vm_session_component.h +++ b/repos/base-hw/src/core/include/spec/arm_v7/virtualization/vm_session_component.h @@ -19,11 +19,12 @@ #include #include #include -#include +#include /* Core includes */ #include #include +#include #include namespace Genode { @@ -36,24 +37,23 @@ class Genode::Vm_session_component { private: - using Translation_table = - Genode::Level_1_stage_2_translation_table; - using Table_allocator = Translation_table_allocator_tpl< - Kernel::DEFAULT_TRANSLATION_TABLE_MAX>; + using Table = Hw::Level_1_stage_2_translation_table; + using Array = Table::Allocator::Array; - Rpc_entrypoint *_ds_ep; - Range_allocator *_ram_alloc; - Dataspace_component _ds; - Dataspace_capability _ds_cap; - addr_t _ds_addr; - Translation_table *_table; - Translation_table_allocator *_tt_alloc; + Rpc_entrypoint *_ds_ep; + Range_allocator *_ram_alloc; + Dataspace_component _ds; + Dataspace_capability _ds_cap; + addr_t _ds_addr; + Table &_table; + Array &_table_array; static size_t _ds_size() { return align_addr(sizeof(Cpu_state_modes), get_page_size_log2()); } addr_t _alloc_ds(size_t &ram_quota); + void * _alloc_table(); void _attach(addr_t phys_addr, addr_t vm_addr, size_t size); public: diff --git a/repos/base-hw/src/core/include/spec/cortex_a15/cpu.h b/repos/base-hw/src/core/include/spec/cortex_a15/cpu.h index 10cb68df6e..dc804d6ebd 100644 --- a/repos/base-hw/src/core/include/spec/cortex_a15/cpu.h +++ b/repos/base-hw/src/core/include/spec/cortex_a15/cpu.h @@ -16,7 +16,6 @@ #define _CORE__INCLUDE__SPEC__CORTEX_A15__CPU_H_ /* core includes */ -#include #include namespace Genode { class Cpu; } @@ -26,55 +25,32 @@ class Genode::Cpu : public Arm_v7 { public: - /** - * Translation table base control register - */ - struct Ttbcr : Arm::Ttbcr + struct Sctlr : Register<32> { - struct Irgn0 : Bitfield<8, 2> { }; - struct Orgn0 : Bitfield<10, 2> { }; - struct Sh0 : Bitfield<12, 2> { }; - struct Eae : Bitfield<31, 1> { }; /* extended address enable */ - - static access_t init_virt_kernel() + static access_t read() { - access_t v = 0; - Irgn0::set(v, 1); - Orgn0::set(v, 1); - Sh0::set(v, 0b10); - Eae::set(v, 1); + access_t v; + asm volatile ("mcr p15, 0, %[v], c1, c0, 0" : [v] "=r" (v)); return v; } }; - - /** - * Memory attribute indirection register 0 - */ - struct Mair0 : Arm_v7::Mair0 + struct Ttbcr : Register<32> { - enum Attr { - DEVICE_MEMORY = 0x04, - NORMAL_MEMORY_UNCACHED = 0x44, - NORMAL_MEMORY_CACHED = 0xff, - }; - - static access_t init_virt_kernel() + static access_t read() { - access_t v = 0; - Attr0::set(v, NORMAL_MEMORY_UNCACHED); - Attr1::set(v, DEVICE_MEMORY); - Attr2::set(v, NORMAL_MEMORY_CACHED); - Attr3::set(v, DEVICE_MEMORY); + access_t v; + asm volatile ("mcr p15, 0, %[v], c2, c0, 2" : [v] "=r" (v)); return v; } }; - - /** - * Non-secure access control register - */ - struct Nsacr : Arm_v7::Nsacr + struct Mair0 : Register<32> { - struct Ns_smp : Bitfield<18,1> { }; + static access_t read() + { + access_t v; + asm volatile ("mcr p15, 0, %[v], c10, c2, 0" : [v] "=r" (v)); + return v; + } }; /** @@ -122,83 +98,6 @@ class Genode::Cpu : public Arm_v7 ** Virtualization extensions ** *********************************/ - /** - * Hypervisor translation table base register - */ - struct Httbr : Register<64> - { - static void translation_table(addr_t const table) - { - asm volatile ("mcrr p15, 4, %[v0], %[v1], c2" - :: [v0]"r"(table), [v1]"r"(0)); - } - }; - - /** - * Hypervisor translation control register - */ - struct Htcr : Register<32> - { - static void write(access_t const v) { - asm volatile ("mcr p15, 4, %[v], c2, c0, 2" :: [v] "r" (v)); } - }; - - /** - * Hypervisor coprocessor trap register - */ - struct Hcptr : Register<32> - { - /* Coprocessor access trap */ - template - struct Tcp : Bitfield {}; - - struct Tase : Bitfield<15, 1> { }; - struct Tta : Bitfield<20, 1> { }; - struct Tcpac : Bitfield<31, 1> { }; - - static access_t init() - { - /* don't trap on cporocessor 10 + 11, but all others */ - access_t v = 0; - Tcp<0>::set(v, 1); - Tcp<1>::set(v, 1); - Tcp<2>::set(v, 1); - Tcp<3>::set(v, 1); - Tcp<4>::set(v, 1); - Tcp<5>::set(v, 1); - Tcp<6>::set(v, 1); - Tcp<7>::set(v, 1); - Tcp<8>::set(v, 1); - Tcp<9>::set(v, 1); - Tcp<12>::set(v, 1); - Tcp<13>::set(v, 1); - Tta::set(v, 1); - Tcpac::set(v, 1); - return v; - } - - static void write(access_t const v) { - asm volatile ("mcr p15, 4, %[v], c1, c1, 2" :: [v] "r" (v)); } - }; - - /** - * Hypervisor Memory attribute indirection register 0 - */ - struct Hmair0 : Register<32> - { - static void write(access_t const v) { - asm volatile ("mcr p15, 4, %[v], c10, c2, 0" :: [v] "r" (v)); } - }; - - /** - * Hypervisor system control register - */ - struct Hsctlr : Arm_v7::Sctlr - { - static void write(access_t const v) { - asm volatile ("mcr p15, 4, %[v], c1, c0, 0" :: [v] "r" (v)); } - }; - /** * Hypervisor system trap register */ @@ -261,24 +160,6 @@ class Genode::Cpu : public Arm_v7 }; }; - /** - * Virtualization translation control register - */ - struct Vtcr : Ttbcr - { - struct Sl0 : Bitfield<6,2> {}; - - static access_t init() - { - access_t v = Ttbcr::init_virt_kernel(); - Sl0::set(v, 1); /* set to starting level 1 */ - return v; - } - - static void write(access_t const v) { - asm volatile ("mcr p15, 4, %[v], c2, c1, 2" :: [v] "r" (v)); } - }; - /** * Extend basic CPU state by members relevant for 'base-hw' only * @@ -287,9 +168,9 @@ class Genode::Cpu : public Arm_v7 struct Context : Genode::Cpu_state { Ttbr0::access_t ttbr0 = 0; - Sctlr::access_t sctlr = 0; - Ttbcr::access_t ttbrc = 0; - Mair0::access_t mair0 = 0; + addr_t sctlr = 0; + addr_t ttbrc = 0; + addr_t mair0 = 0; /** * Return base of assigned translation table @@ -407,13 +288,6 @@ class Genode::Cpu : public Arm_v7 */ static unsigned primary_id(); - /** - * Switch to the virtual mode in kernel - * - * \param pd kernel pd object pointer - */ - static void init_virt_kernel(Kernel::Pd & pd); - /** * Write back dirty cache lines and invalidate all cache lines */ @@ -426,27 +300,6 @@ class Genode::Cpu : public Arm_v7 void invalidate_data_cache() { invalidate_inner_data_cache(); } - /** - * Hook function called at the very beginning - * of the local cpu initialization - */ - void init(Genode::Translation_table&); - - /** - * Switch on MMU and caches - * - * \param table physical page table address - */ - void enable_mmu_and_caches(Genode::addr_t table) - { - Cpu::Mair0::write(Cpu::Mair0::init_virt_kernel()); - Cpu::Dacr::write(Cpu::Dacr::init_virt_kernel()); - Cpu::Ttbr0::write(Cpu::Ttbr0::init(table, 0)); - Cpu::Ttbcr::write(Cpu::Ttbcr::init_virt_kernel()); - Cpu::Sctlr::enable_mmu_and_caches(); - invalidate_branch_predicts(); - } - /************* ** Dummies ** diff --git a/repos/base-hw/src/core/include/spec/cortex_a15/translation_table.h b/repos/base-hw/src/core/include/spec/cortex_a15/translation_table.h index 7c9c1602de..c6a4bd40e5 100644 --- a/repos/base-hw/src/core/include/spec/cortex_a15/translation_table.h +++ b/repos/base-hw/src/core/include/spec/cortex_a15/translation_table.h @@ -15,6 +15,6 @@ #define _CORE__INCLUDE__SPEC__CORTEX_A15__TRANSLATION_TABLE_H_ /* core includes */ -#include +#include #endif /* _CORE__INCLUDE__SPEC__CORTEX_A15__TRANSLATION_TABLE_H_ */ diff --git a/repos/base-hw/src/core/include/spec/cortex_a8/cpu.h b/repos/base-hw/src/core/include/spec/cortex_a8/cpu.h index 405f6dc16f..3b1c5f09ea 100644 --- a/repos/base-hw/src/core/include/spec/cortex_a8/cpu.h +++ b/repos/base-hw/src/core/include/spec/cortex_a8/cpu.h @@ -28,13 +28,13 @@ class Genode::Cpu : public Arm_v7 /** * Write back dirty cache lines and invalidate the whole cache */ - void clean_invalidate_data_cache() { + static void clean_invalidate_data_cache() { clean_invalidate_inner_data_cache(); } /** * Invalidate all cache lines */ - void invalidate_data_cache() { + static void invalidate_data_cache() { invalidate_inner_data_cache(); } /** diff --git a/repos/base-hw/src/core/include/spec/cortex_a8/translation_table.h b/repos/base-hw/src/core/include/spec/cortex_a8/translation_table.h index 664380cc04..f63161a935 100644 --- a/repos/base-hw/src/core/include/spec/cortex_a8/translation_table.h +++ b/repos/base-hw/src/core/include/spec/cortex_a8/translation_table.h @@ -15,9 +15,27 @@ #ifndef _CORE__INCLUDE__SPEC__CORTEX_A8__TRANSLATION_TABLE_H_ #define _CORE__INCLUDE__SPEC__CORTEX_A8__TRANSLATION_TABLE_H_ -/* core includes */ -#include +#include +#include -constexpr unsigned Genode::Translation::_device_tex() { return 2; } +#include + +constexpr unsigned Hw::Page_table::Descriptor_base::_device_tex() { + return 2; } + +constexpr bool Hw::Page_table::Descriptor_base::_smp() { return false; } + +void Hw::Page_table::_translation_added(unsigned long addr, unsigned long size) +{ + /* + * The Cortex-A8 CPU can't use the L1 cache on page-table + * walks. Therefore, as the page-tables lie in write-back cacheable + * memory we've to clean the corresponding cache-lines even when a + * page table entry is added. We only do this as core as the kernel + * adds translations solely before MMU and caches are enabled. + */ + if (Genode::Cpu::is_user()) Kernel::update_data_region(addr, size); + else Genode::Cpu::clean_invalidate_data_cache(); +} #endif /* _CORE__INCLUDE__SPEC__CORTEX_A8__TRANSLATION_TABLE_H_ */ diff --git a/repos/base-hw/src/core/include/spec/cortex_a9/board_support.h b/repos/base-hw/src/core/include/spec/cortex_a9/board_support.h index 7b50e679f4..ebf8526bc5 100644 --- a/repos/base-hw/src/core/include/spec/cortex_a9/board_support.h +++ b/repos/base-hw/src/core/include/spec/cortex_a9/board_support.h @@ -16,7 +16,7 @@ /* core includes */ #include -#include +#include namespace Cortex_a9 { class Board; } @@ -24,7 +24,7 @@ class Cortex_a9::Board : public Genode::Board_base { public: - using L2_cache = Arm::Pl310; + using L2_cache = Hw::Pl310; static constexpr bool SMP = true; @@ -38,9 +38,6 @@ class Cortex_a9::Board : public Genode::Board_base }; enum { - /* snoop control unit */ - SCU_MMIO_BASE = CORTEX_A9_PRIVATE_MEM_BASE, - /* interrupt controller */ IRQ_CONTROLLER_DISTR_BASE = CORTEX_A9_PRIVATE_MEM_BASE + 0x1000, IRQ_CONTROLLER_DISTR_SIZE = 0x1000, diff --git a/repos/base-hw/src/core/include/spec/cortex_a9/cpu_support.h b/repos/base-hw/src/core/include/spec/cortex_a9/cpu.h similarity index 74% rename from repos/base-hw/src/core/include/spec/cortex_a9/cpu_support.h rename to repos/base-hw/src/core/include/spec/cortex_a9/cpu.h index dc2afa2c2a..80140cca1a 100644 --- a/repos/base-hw/src/core/include/spec/cortex_a9/cpu_support.h +++ b/repos/base-hw/src/core/include/spec/cortex_a9/cpu.h @@ -12,17 +12,17 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _SPEC__CORTEX_A9__CPU_SUPPORT_H_ -#define _SPEC__CORTEX_A9__CPU_SUPPORT_H_ +#ifndef _SPEC__CORTEX_A9__CPU_H_ +#define _SPEC__CORTEX_A9__CPU_H_ /* core includes */ #include #include #include -namespace Genode { class Cortex_a9; } +namespace Genode { class Cpu; } -class Genode::Cortex_a9 : public Arm_v7 +class Genode::Cpu : public Arm_v7 { protected: @@ -57,31 +57,6 @@ class Genode::Cortex_a9 : public Arm_v7 asm volatile ("mcr p15, 0, %[v], c1, c0, 2" :: [v]"r"(v) :); } }; - /** - * Auxiliary Control Register - */ - struct Actlr : Register<32> - { - struct Smp : Bitfield<6, 1> { }; - - static access_t read() - { - access_t v; - asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (v) :: ); - return v; - } - - static void write(access_t const v) { - asm volatile ("mcr p15, 0, %0, c1, c0, 1" :: "r" (v) : ); } - - static void enable_smp(Board&) - { - access_t v = read(); - Smp::set(v, 1); - write(v); - } - }; - struct User_context : Arm::User_context, Fpu::Context { }; /** @@ -129,13 +104,6 @@ class Genode::Cortex_a9 : public Arm_v7 } static unsigned executing_id() { return Mpidr::Aff_0::get(Mpidr::read()); } - - - /************* - ** Dummies ** - *************/ - - static void translation_added(addr_t, size_t) { } }; -#endif /* _SPEC__CORTEX_A9__CPU_SUPPORT_H_ */ +#endif /* _SPEC__CORTEX_A9__CPU_H_ */ diff --git a/repos/base-hw/src/core/include/spec/cortex_a9/scu.h b/repos/base-hw/src/core/include/spec/cortex_a9/scu.h deleted file mode 100644 index 40aaca48c2..0000000000 --- a/repos/base-hw/src/core/include/spec/cortex_a9/scu.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * \brief Snoop control unit - * \author Martin Stein - * \author Stefan Kalkowski - * \date 2015-12-15 - */ - -/* - * Copyright (C) 2015-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -/* Genode includes */ -#include - -/* local includes */ -#include - -namespace Genode { struct Scu; } - - -struct Genode::Scu : Genode::Mmio -{ - struct Cr : Register<0x0, 32> - { - struct Enable : Bitfield<0, 1> { }; - }; - - struct Dcr : Register<0x30, 32> - { - struct Bit_0 : Bitfield<0, 1> { }; - }; - - struct Iassr : Register<0xc, 32> - { - struct Cpu0_way : Bitfield<0, 4> { }; - struct Cpu1_way : Bitfield<4, 4> { }; - struct Cpu2_way : Bitfield<8, 4> { }; - struct Cpu3_way : Bitfield<12, 4> { }; - }; - - Scu() : Mmio(Board::SCU_MMIO_BASE) { } - - void invalidate() - { - Iassr::access_t iassr = 0; - for (Iassr::access_t way = 0; way <= Iassr::Cpu0_way::mask(); - way++) { - Iassr::Cpu0_way::set(iassr, way); - Iassr::Cpu1_way::set(iassr, way); - Iassr::Cpu2_way::set(iassr, way); - Iassr::Cpu3_way::set(iassr, way); - write(iassr); - } - } - - void enable(Board & board) - { - if (board.errata(Board::ARM_764369)) write(1); - write(1); - } -}; diff --git a/repos/base-hw/src/core/include/spec/cortex_a9/translation_table.h b/repos/base-hw/src/core/include/spec/cortex_a9/translation_table.h index 616fe9a638..e92f4222e0 100644 --- a/repos/base-hw/src/core/include/spec/cortex_a9/translation_table.h +++ b/repos/base-hw/src/core/include/spec/cortex_a9/translation_table.h @@ -15,9 +15,13 @@ #ifndef _CORE__INCLUDE__SPEC__CORTEX_A9__TRANSLATION_TABLE_H_ #define _CORE__INCLUDE__SPEC__CORTEX_A9__TRANSLATION_TABLE_H_ -/* core includes */ -#include +#include -constexpr unsigned Genode::Translation::_device_tex() { return 2; } +constexpr unsigned Hw::Page_table::Descriptor_base::_device_tex() { + return 2; } + +constexpr bool Hw::Page_table::Descriptor_base::_smp() { return true; } + +void Hw::Page_table::_translation_added(unsigned long, unsigned long) { } #endif /* _CORE__INCLUDE__SPEC__CORTEX_A9__TRANSLATION_TABLE_H_ */ diff --git a/repos/base-hw/src/core/include/spec/imx/serial.h b/repos/base-hw/src/core/include/spec/imx/serial.h index 5d3e577c80..3dadd1b245 100644 --- a/repos/base-hw/src/core/include/spec/imx/serial.h +++ b/repos/base-hw/src/core/include/spec/imx/serial.h @@ -30,13 +30,9 @@ namespace Genode { public: - /** - * Constructor - * - * XXX: The 'baud_rate' argument is ignored for now. - */ - Serial(unsigned) - : Imx_uart_base(Platform::mmio_to_virt(Board::UART_1_MMIO_BASE)) { } + Serial(unsigned baudrate) + : Imx_uart_base(Platform::mmio_to_virt(Board::UART_1_MMIO_BASE), + /* ignored clock rate */ 0, baudrate) { } }; } diff --git a/repos/base-hw/src/core/include/spec/imx53/board.h b/repos/base-hw/src/core/include/spec/imx53/board.h index 2270682760..16a87212ba 100644 --- a/repos/base-hw/src/core/include/spec/imx53/board.h +++ b/repos/base-hw/src/core/include/spec/imx53/board.h @@ -15,11 +15,10 @@ #ifndef _CORE__INCLUDE__SPEC__IMX53__BOARD_H_ #define _CORE__INCLUDE__SPEC__IMX53__BOARD_H_ -/* core includes */ -#include +#include namespace Genode { struct Board; } -struct Genode::Board : Imx::Board { static constexpr bool SMP = false; }; +struct Genode::Board : Genode::Board_base { static constexpr bool SMP = false; }; #endif /* _CORE__INCLUDE__SPEC__IMX53__BOARD_H_ */ diff --git a/repos/base-hw/src/core/include/spec/imx53/pic.h b/repos/base-hw/src/core/include/spec/imx53/pic.h index 71ea378955..735819bc24 100644 --- a/repos/base-hw/src/core/include/spec/imx53/pic.h +++ b/repos/base-hw/src/core/include/spec/imx53/pic.h @@ -14,16 +14,12 @@ #ifndef _CORE__INCLUDE__SPEC__IMX53__PIC_H_ #define _CORE__INCLUDE__SPEC__IMX53__PIC_H_ -/* Genode includes */ -#include - -/* core includes */ -#include +#include namespace Genode { class Pic; } -class Genode::Pic : public Mmio +class Genode::Pic : public Hw::Pic { public: @@ -32,141 +28,19 @@ class Genode::Pic : public Mmio * FIXME: dummy ipi value on non-SMP platform, should be removed * when SMP is an aspect of CPUs only compiled where necessary */ - IPI = 0, - NR_OF_IRQ = 109, + IPI = 0, }; - protected: - - /** - * Software Interrupt Trigger Register - */ - struct Swint : Register<0xf00, 32> { - struct Intid : Bitfield<0,10> { }; }; - - /** - * Interrupt control register - */ - struct Intctrl : Register<0, 32> - { - struct Enable : Bitfield<0,1> { }; - struct Nsen : Bitfield<16,1> { }; - struct Nsen_mask : Bitfield<31,1> { }; - }; - - /** - * Priority mask register - */ - struct Priomask : Register<0xc, 32> { - struct Mask : Bitfield<0,8> { }; }; - - /** - * Interrupt security registers - */ - struct Intsec : Register_array<0x80, 32, NR_OF_IRQ, 1> { - struct Nonsecure : Bitfield<0, 1> { }; }; - - /** - * Interrupt set enable registers - */ - struct Enset : Register_array<0x100, 32, NR_OF_IRQ, 1, true> { - struct Set_enable : Bitfield<0, 1> { }; }; - - /** - * Interrupt clear enable registers - */ - struct Enclear : Register_array<0x180, 32, NR_OF_IRQ, 1, true> { - struct Clear_enable : Bitfield<0, 1> { }; }; - - /** - * Interrupt priority level registers - */ - struct Priority : Register_array<0x400, 32, NR_OF_IRQ, 8> { }; - - /** - * Highest interrupt pending registers - */ - struct Hipndr : Register_array<0xd80, 32, NR_OF_IRQ, 1, true> { - struct Pending : Bitfield<0, 1> { }; }; - - /** - * Initializes security extension if needed - */ - void _init_security_ext(); - - public: - - Pic(); - - void init_cpu_local() - { - for (unsigned i = 0; i < NR_OF_IRQ; i++) { - write(1, i); - write(1, i); - } - write(0x1f); - Intctrl::access_t v = 0; - Intctrl::Enable::set(v, 1); - Intctrl::Nsen::set(v, 1); - Intctrl::Nsen_mask::set(v, 1); - write(v); - _init_security_ext(); - } - - /** - * Mark interrupt 'i' unsecure - */ - void unsecure(unsigned const i); - - /** - * Mark interrupt 'i' secure - */ - void secure(unsigned const i); - - /** - * Receive a pending request number 'i' - */ - bool take_request(unsigned & i) - { - for (unsigned j = 0; j < NR_OF_IRQ; j++) { - if (!read(j)) { continue; } - i = j; - return true; - } - return false; - } - - /** - * Validate request number 'i' - */ - bool valid(unsigned const i) const { return i < NR_OF_IRQ; } - - /** - * Unmask interrupt 'i' - */ - void unmask(unsigned const i, unsigned) { - if (valid(i)) { write(1, i); } } - - /** - * Mask interrupt 'i' - */ - void mask(unsigned const i) { - if (valid(i)) { write(1, i); } } - - /* * Trigger interrupt 'i' from software if possible */ void trigger(unsigned const i) { write(Swint::Intid::bits(i)); } - - /************* - ** Dummies ** - *************/ - void trigger_ip_interrupt(unsigned) { } - void finish_request() { } + + bool secure(unsigned i) { + return !read(i); } }; namespace Kernel { using Pic = Genode::Pic; } diff --git a/repos/base-hw/src/core/include/spec/imx53/trustzone/csu.h b/repos/base-hw/src/core/include/spec/imx53/trustzone/csu.h deleted file mode 100644 index 78ade30b3e..0000000000 --- a/repos/base-hw/src/core/include/spec/imx53/trustzone/csu.h +++ /dev/null @@ -1,242 +0,0 @@ -/* - * \brief Driver for the Central Security Unit - * \author Stefan Kalkowski - * \date 2012-11-06 - */ - -/* - * Copyright (C) 2012-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _CORE__INCLUDE__SPEC__IMX53__TRUSTZONE__CSU_H_ -#define _CORE__INCLUDE__SPEC__IMX53__TRUSTZONE__CSU_H_ - -/* Genode includes */ -#include -#include - -/* core includes */ -#include - -namespace Genode { - - class Csu : Mmio - { - private: - - template - struct Csl : public Register - { - enum { - SECURE = 0x33, - UNSECURE = 0xff, - }; - - struct Slave_a : Register::template Bitfield<0, 9> { }; - struct Slave_b : Register::template Bitfield<16, 9> { }; - }; - - struct Master : public Register<0x218, 32> - { - enum { - SECURE_UNLOCKED, - UNSECURE_UNLOCKED, - SECURE_LOCKED, - UNSECURE_LOCKED - }; - - struct Esdhc3 : Bitfield<0,2> { }; - struct Cortex : Bitfield<2,2> { }; - struct Sdma : Bitfield<4,2> { }; - struct Gpu : Bitfield<6,2> { }; - struct Usb : Bitfield<8,2> { }; - struct Pata : Bitfield<10,2> { }; - struct Mlb : Bitfield<14,2> { }; - struct Rtic : Bitfield<18,2> { }; - struct Esdhc4 : Bitfield<20,2> { }; - struct Fec : Bitfield<22,2> { }; - struct Dap : Bitfield<24,2> { }; - struct Esdhc1 : Bitfield<26,2> { }; - struct Esdhc2 : Bitfield<28,2> { }; - }; - - struct Alarm_mask : public Register<0x230, 32> { }; - struct Irq_ctrl : public Register<0x368, 32> { }; - - public: - - typedef Csl<0x00> Csl00; - typedef Csl<0x04> Csl01; - typedef Csl<0x08> Csl02; - typedef Csl<0x0c> Csl03; - typedef Csl<0x10> Csl04; - typedef Csl<0x14> Csl05; - typedef Csl<0x18> Csl06; - typedef Csl<0x1c> Csl07; - typedef Csl<0x20> Csl08; - typedef Csl<0x24> Csl09; - typedef Csl<0x28> Csl10; - typedef Csl<0x2c> Csl11; - typedef Csl<0x30> Csl12; - typedef Csl<0x34> Csl13; - typedef Csl<0x38> Csl14; - typedef Csl<0x3c> Csl15; - typedef Csl<0x40> Csl16; - typedef Csl<0x44> Csl17; - typedef Csl<0x48> Csl18; - typedef Csl<0x4c> Csl19; - typedef Csl<0x50> Csl20; - typedef Csl<0x54> Csl21; - typedef Csl<0x58> Csl22; - typedef Csl<0x5c> Csl23; - typedef Csl<0x60> Csl24; - typedef Csl<0x64> Csl25; - typedef Csl<0x68> Csl26; - typedef Csl<0x6c> Csl27; - typedef Csl<0x70> Csl28; - typedef Csl<0x74> Csl29; - typedef Csl<0x78> Csl30; - typedef Csl<0x7c> Csl31; - - Csu(addr_t const base) : Mmio(Platform::mmio_to_virt(base)) - { - /* Power (CCM, SRC, DPLLIP1-4, GPC and OWIRE) */ - write(Csl00::UNSECURE); - - /* AHBMAX S0-S2 */ - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); - - /* AHBMAX M6 */ - write(Csl00::UNSECURE); - - /* Timer (EPIT, GPT) TODO */ - write(Csl00::UNSECURE); - - /* UART 1-5 */ - Csl00::access_t constexpr uart_csl = - Csu_config::SECURE_UART ? Csl00::SECURE : - Csl00::UNSECURE; - write(uart_csl); - write(uart_csl); - write(uart_csl); - write(uart_csl); - write(uart_csl); - - /* GPIO */ - Csl00::access_t constexpr gpio_csl = - Csu_config::SECURE_GPIO ? Csl00::SECURE : - Csl00::UNSECURE; - write(gpio_csl); - write(gpio_csl); - write(gpio_csl); - write(gpio_csl); - - /* IOMUXC TODO */ - write(Csl00::UNSECURE); - - /* SDMA TODO */ - write(Csl00::UNSECURE); - - /* USB */ - write(Csl00::UNSECURE); - - /* TVE */ - write(Csl00::SECURE); - - /* I2C */ - Csl00::access_t constexpr i2c_csl = - Csu_config::SECURE_I2C ? Csl00::SECURE : - Csl00::UNSECURE; - write(i2c_csl); - write(i2c_csl); - write(i2c_csl); - - /* IPU */ - write(Csl00::SECURE); - - /* Audio */ - write(Csl00::UNSECURE); - - /* SATA */ - write(Csl00::UNSECURE); - - /* FEC */ - write(Csl00::UNSECURE); - - /* SDHCI 1-4 */ - Csl00::access_t constexpr esdhc_csl = - Csu_config::SECURE_ESDHC ? Csl00::SECURE : - Csl00::UNSECURE; - write(esdhc_csl); - write(esdhc_csl); - write(esdhc_csl); - write(esdhc_csl); - - /* SPDIF */ - write(Csl00::UNSECURE); - - /* GPU 2D */ - write(Csl00::SECURE); - - /* GPU 3D */ - write(Csl00::SECURE); - - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); // SRTC - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); // SCC - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); // RTIC - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); - write(Csl00::SECURE); //VPU - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); - write(Csl00::UNSECURE); - - /* DMA from graphical subsystem is considered to be secure */ - write(Master::SECURE_UNLOCKED); - - /* all other DMA operations are insecure */ - write(Master::UNSECURE_UNLOCKED); - write(Master::UNSECURE_UNLOCKED); - write(Master::UNSECURE_UNLOCKED); - write(Master::UNSECURE_UNLOCKED); - write(Master::UNSECURE_UNLOCKED); - - Master::access_t constexpr esdhc_master = - Csu_config::SECURE_ESDHC ? Master::SECURE_UNLOCKED : - Master::UNSECURE_UNLOCKED; - write(esdhc_master); - write(esdhc_master); - write(esdhc_master); - write(esdhc_master); - } - }; -} - -#endif /* _CORE__INCLUDE__SPEC__IMX53__TRUSTZONE__CSU_H_ */ diff --git a/repos/base-hw/src/core/include/spec/imx6/board.h b/repos/base-hw/src/core/include/spec/imx6/board.h index 210055ad91..d5e527efcc 100644 --- a/repos/base-hw/src/core/include/spec/imx6/board.h +++ b/repos/base-hw/src/core/include/spec/imx6/board.h @@ -16,59 +16,8 @@ #define _CORE__INCLUDE__SPEC__IMX6__BOARD_H_ /* core includes */ -#include #include -namespace Genode { class Board; } - - -class Genode::Board : public Imx::Board, public Cortex_a9::Board -{ - private: - - struct Src : Mmio - { - Src() : Mmio(SRC_MMIO_BASE) {} - - struct Scr : Register<0x0, 32> - { - struct Core_1_reset : Bitfield<14,1> {}; - struct Core_2_reset : Bitfield<15,1> {}; - struct Core_3_reset : Bitfield<16,1> {}; - struct Core_1_enable : Bitfield<22,1> {}; - struct Core_2_enable : Bitfield<23,1> {}; - struct Core_3_enable : Bitfield<24,1> {}; - }; - struct Gpr1 : Register<0x20, 32> {}; /* ep core 0 */ - struct Gpr3 : Register<0x28, 32> {}; /* ep core 1 */ - struct Gpr5 : Register<0x30, 32> {}; /* ep core 2 */ - struct Gpr7 : Register<0x38, 32> {}; /* ep core 3 */ - - void entrypoint(void * entry) - { - write((Gpr3::access_t)entry); - write((Gpr5::access_t)entry); - write((Gpr7::access_t)entry); - Scr::access_t v = read(); - Scr::Core_1_enable::set(v,1); - Scr::Core_1_reset::set(v,1); - Scr::Core_2_enable::set(v,1); - Scr::Core_3_reset::set(v,1); - Scr::Core_3_enable::set(v,1); - Scr::Core_3_reset::set(v,1); - write(v); - } - } _src; - - public: - - void init() - { - Imx::Board::init(); - Cortex_a9::Board::init(); - } - - void wake_up_all_cpus(void *entry) { _src.entrypoint(entry); } -}; +namespace Genode { using Board = Cortex_a9::Board; } #endif /* _CORE__INCLUDE__SPEC__IMX6__BOARD_H_ */ diff --git a/repos/base-hw/src/core/include/spec/imx6/cpu.h b/repos/base-hw/src/core/include/spec/imx6/cpu.h deleted file mode 100644 index fa4fe06d3c..0000000000 --- a/repos/base-hw/src/core/include/spec/imx6/cpu.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * \brief CPU driver for core - * \author Stefan Kalkowski - * \date 2015-12-15 - */ - -/* - * Copyright (C) 2015-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _CPU_H_ -#define _CPU_H_ - -/* core includes */ -#include - -namespace Genode -{ - using Cpu = Genode::Cortex_a9; -} - -#endif /* _CPU_H_ */ - diff --git a/repos/base-hw/src/core/include/spec/panda/board.h b/repos/base-hw/src/core/include/spec/panda/board.h index 280cdd5af9..d90e1bdae3 100644 --- a/repos/base-hw/src/core/include/spec/panda/board.h +++ b/repos/base-hw/src/core/include/spec/panda/board.h @@ -15,8 +15,7 @@ #ifndef _CORE__INCLUDE__SPEC__PANDA__BOARD_H_ #define _CORE__INCLUDE__SPEC__PANDA__BOARD_H_ -/* core includes */ -#include +#include #include namespace Genode { class Board; } @@ -28,52 +27,10 @@ class Genode::Board : public Cortex_a9::Board using Base = Cortex_a9::Board; - /** - * Frontend to firmware running in the secure world - */ - struct Secure_monitor - { - enum Syscalls - { - CPU_ACTLR_SMP_BIT_RAISE = 0x25, - L2_CACHE_SET_DEBUG_REG = 0x100, - L2_CACHE_ENABLE_REG = 0x102, - L2_CACHE_AUX_REG = 0x109, - }; - - void call(addr_t func, addr_t val) - { - register addr_t _func asm("r12") = func; - register addr_t _val asm("r0") = val; - asm volatile("dsb; smc #0" :: - "r" (_func), "r" (_val) : - "memory", "cc", "r1", "r2", "r3", "r4", "r5", "r6", "r7", - "r8", "r9", "r10", "r11"); - } - }; - - class L2_cache : public Base::L2_cache { private: - Secure_monitor _monitor; - - unsigned long _init_value() - { - Aux::access_t v = 0; - Aux::Associativity::set(v, 1); - Aux::Way_size::set(v, 3); - Aux::Share_override::set(v, 1); - Aux::Reserved::set(v, 1); - Aux::Ns_lockdown::set(v, 1); - Aux::Ns_irq_ctrl::set(v, 1); - Aux::Data_prefetch::set(v, 1); - Aux::Inst_prefetch::set(v, 1); - Aux::Early_bresp::set(v, 1); - return v; - } - unsigned long _debug_value() { Debug::access_t v = 0; @@ -84,30 +41,15 @@ class Genode::Board : public Cortex_a9::Board public: - L2_cache(Genode::addr_t mmio) : Base::L2_cache(mmio) - { - _monitor.call(Secure_monitor::L2_CACHE_AUX_REG, - _init_value()); - } + L2_cache(Genode::addr_t mmio) : Base::L2_cache(mmio) { } void clean_invalidate() { - _monitor.call(Secure_monitor::L2_CACHE_SET_DEBUG_REG, - _debug_value()); + using namespace Hw; + call_panda_firmware(L2_CACHE_SET_DEBUG_REG, _debug_value()); Base::L2_cache::clean_invalidate(); - _monitor.call(Secure_monitor::L2_CACHE_SET_DEBUG_REG, 0); + call_panda_firmware(L2_CACHE_SET_DEBUG_REG, 0); } - - void invalidate() { Base::L2_cache::invalidate(); } - - void enable() - { - _monitor.call(Secure_monitor::L2_CACHE_ENABLE_REG, 1); - Base::L2_cache::mask_interrupts(); - } - - void disable() { - _monitor.call(Secure_monitor::L2_CACHE_ENABLE_REG, 0); } }; L2_cache & l2_cache() { return _l2_cache; } diff --git a/repos/base-hw/src/core/include/spec/panda/cortex_a9_wugen.h b/repos/base-hw/src/core/include/spec/panda/cortex_a9_wugen.h deleted file mode 100644 index b70ee764c3..0000000000 --- a/repos/base-hw/src/core/include/spec/panda/cortex_a9_wugen.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * \brief Cortex-A9 Wake-Up Generator - * \author Martin Stein - * \date 2015-08-14 - */ - -/* - * Copyright (C) 2015-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef CORTEX_A9_WUGEN_H -#define CORTEX_A9_WUGEN_H - -/* Genode includes */ -#include - -namespace Genode { class Cortex_a9_wugen; } - -/** - * Cortex_a9 Wake-Up Generator - */ -class Genode::Cortex_a9_wugen : Mmio -{ - private: - - struct Aux_core_boot_0 : Register<0x800, 32> { - struct Cpu1_status : Bitfield<2, 2> { }; }; - - struct Aux_core_boot_1 : Register<0x804, 32> { }; - - public: - - Cortex_a9_wugen() : Mmio(Board_base::CORTEX_A9_WUGEN_MMIO_BASE) { } - - /** - * Start CPU 1 with instruction pointer 'ip' - */ - void init_cpu_1(void * const ip) - { - write((addr_t)ip); - write(1); - } -}; - -#endif /* CORTEX_A9_WUGEN_H */ diff --git a/repos/base-hw/src/core/include/spec/panda/cpu.h b/repos/base-hw/src/core/include/spec/panda/cpu.h deleted file mode 100644 index ebd3a393de..0000000000 --- a/repos/base-hw/src/core/include/spec/panda/cpu.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * \brief CPU driver for core - * \author Stefan Kalkowski - * \date 2015-12-15 - */ - -/* - * Copyright (C) 2015-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _CPU_H_ -#define _CPU_H_ - -/* core includes */ -#include - -namespace Genode { class Cpu; } - -/** - * Override the Cortex A9 Cpu driver, because some registers can be accessed - * via the firmware running in TrustZone's secure world only - */ -class Genode::Cpu : public Genode::Cortex_a9 -{ - public: - - struct Actlr : Cortex_a9::Actlr - { - static void enable_smp(Board&); - }; -}; - -#endif /* _CPU_H_ */ - diff --git a/repos/base-hw/src/core/include/spec/pbxa9/cpu.h b/repos/base-hw/src/core/include/spec/pbxa9/cpu.h deleted file mode 100644 index e05615329f..0000000000 --- a/repos/base-hw/src/core/include/spec/pbxa9/cpu.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * \brief CPU driver for core - * \author Stefan Kalkowski - * \date 2015-12-15 - */ - -/* - * Copyright (C) 2015-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _CPU_H_ -#define _CPU_H_ - -/* core includes */ -#include - -namespace Genode -{ - using Cpu = Cortex_a9; -} - -#endif /* _CPU_H_ */ diff --git a/repos/base-hw/src/core/include/spec/riscv/serial.h b/repos/base-hw/src/core/include/spec/riscv/serial.h index 1d20797cd4..b3b67f4535 100644 --- a/repos/base-hw/src/core/include/spec/riscv/serial.h +++ b/repos/base-hw/src/core/include/spec/riscv/serial.h @@ -14,40 +14,16 @@ #ifndef _SERIAL_H_ #define _SERIAL_H_ -/* Genode includes */ -#include -#include +#include -/* core includes */ -#include - -namespace Genode { class Serial; } +namespace Genode { struct Serial; } /** * Serial output driver for core */ -class Genode::Serial +struct Genode::Serial : Hw::Riscv_uart { - public: - - /** - * Constructor - */ - Serial(unsigned) { } - - void put_char(char const c) - { - struct Arg : Register<64> - { - struct Char : Bitfield<0, 8> { }; - struct Write_cmd : Bitfield<48, 1> { }; - struct Stdout : Bitfield<56, 1> { }; - }; - - Machine::put_char(Arg::Char::bits(c) | - Arg::Stdout::bits(1) | - Arg::Write_cmd::bits(1)); - } + Serial(unsigned) { } }; #endif /* _SERIAL_H_ */ diff --git a/repos/base-hw/src/core/include/spec/riscv/timer.h b/repos/base-hw/src/core/include/spec/riscv/timer.h index 8c7ddf5d56..47569d9951 100644 --- a/repos/base-hw/src/core/include/spec/riscv/timer.h +++ b/repos/base-hw/src/core/include/spec/riscv/timer.h @@ -16,12 +16,11 @@ /* base-hw includes */ #include +#include /* Genode includes */ #include -/* Core includes */ -#include namespace Genode { class Timer; } @@ -65,7 +64,7 @@ struct Genode::Timer void start_one_shot(time_t const tics, unsigned const) { _timeout = _stime() + tics; - Machine::set_sys_timer(_timeout); + Hw::set_sys_timer(_timeout); } time_t tics_to_us(time_t const tics) const { diff --git a/repos/base-hw/src/core/include/spec/riscv/translation_table.h b/repos/base-hw/src/core/include/spec/riscv/translation_table.h index c83ec7497d..ea46027227 100644 --- a/repos/base-hw/src/core/include/spec/riscv/translation_table.h +++ b/repos/base-hw/src/core/include/spec/riscv/translation_table.h @@ -11,408 +11,18 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _TRANSLATION_TABLE_H_ -#define _TRANSLATION_TABLE_H_ -/* Genode includes */ -#include -#include -#include +#ifndef _CORE__INCLUDE__SPEC__RISCV__TRANSLATION_TABLE_H_ +#define _CORE__INCLUDE__SPEC__RISCV__TRANSLATION_TABLE_H_ -/* Core includes */ -#include -#include -#include +#include +#include -namespace Sv39 +template +void Sv39::Level_x_translation_table::_translation_added(addr_t addr, + size_t size) { - using namespace Genode; - - enum { - SIZE_LOG2_4K = 12, - SIZE_LOG2_2M = 21, - SIZE_LOG2_1G = 30, - SIZE_LOG2_512G = 39, - }; - - struct None { }; - - template - class Level_x_translation_table; - - using Level_3_translation_table = - Level_x_translation_table; - - using Level_2_translation_table = - Level_x_translation_table; - - using Level_1_translation_table = - Level_x_translation_table; - - struct Descriptor; - struct Table_descriptor; - struct Block_descriptor; + Kernel::update_data_region(addr, size); } -struct Sv39::Descriptor : Register<64> -{ - enum Descriptor_type { INVALID, TABLE, BLOCK }; - struct V : Bitfield<0, 1> { }; /* present */ - struct Type : Bitfield<1, 4> /* type and access rights */ - { - enum { - POINTER = 0, - POINTER_GLOBAL = 1, - USER = 4, /* R + 0, RW + 1, RX + 2, RWX + 3 */ - KERNEL = 8, - GLOBAL = 12, - }; - }; - struct Ppn : Bitfield<10, 38> { }; /* physical address 10 bit aligned */ - struct Base : Bitfield<12, 38> { }; /* physical address page aligned */ - - template - static access_t rwx(Page_flags const &f) - { - if (f.writeable && f.executable) - return BASE + 3; - else if (f.writeable) - return BASE + 1; - else if (f.executable) - return BASE + 2; - else - return BASE; - } - - static access_t permission_bits(Page_flags const &f) - { - if (f.global) - return rwx(f); - - if (f.privileged) - return rwx(f); - - return rwx(f); - } - - static Descriptor_type type(access_t const v) - { - if (!V::get(v)) return INVALID; - if (Type::get(v) == Type::POINTER || Type::get(v) == Type::POINTER_GLOBAL) - return TABLE; - - return BLOCK; - } - - static bool valid(access_t const v) { - return V::get(v); } -}; - -struct Sv39::Table_descriptor : Descriptor -{ - static access_t create(void * const pa) - { - access_t base = Base::get((access_t)pa); - access_t desc = 0; - - Ppn::set(desc, base); - Type::set(desc, Type::POINTER); - V::set(desc, 1); - - return desc; - } -}; - -struct Sv39::Block_descriptor : Descriptor -{ - static access_t create(Page_flags const &f, addr_t const pa) - { - access_t base = Base::get(pa); - access_t desc = 0; - - Ppn::set(desc, base); - Type::set(desc, permission_bits(f)); - V::set(desc, 1); - - return desc; - } -}; - -template -class Sv39::Level_x_translation_table -{ - private: - - bool _aligned(addr_t const a, size_t const alignm_log2) { - return a == ((a >> alignm_log2) << alignm_log2); } - - public: - - static constexpr size_t MIN_PAGE_SIZE_LOG2 = SIZE_LOG2_4K; - static constexpr size_t ALIGNM_LOG2 = SIZE_LOG2_4K; - static constexpr size_t MAX_ENTRIES = 1 << (SIZE_LOG2 - BLOCK_SIZE_LOG2); - static constexpr size_t BLOCK_SIZE = 1 << BLOCK_SIZE_LOG2; - static constexpr size_t BLOCK_MASK = ~(BLOCK_SIZE - 1); - static constexpr size_t VM_MASK = (1UL<< SIZE_LOG2_512G) - 1; - - class Misaligned { }; - class Invalid_range { }; - class Double_insertion { }; - - protected: - - typename Descriptor::access_t _entries[MAX_ENTRIES]; - - /* - * Return how many entries of an alignment fit into region - */ - static constexpr size_t _count(size_t region, size_t alignment) { - return align_addr(region, alignment) / (1UL << alignment); } - - - template - void _range_op(addr_t vo, addr_t pa, size_t size, FUNC &&func) - { - /* sanity check vo bits 38 to 63 must be equal */ - addr_t sanity = vo >> 38; - if (sanity != 0 && sanity != 0x3ffffff) { - Genode::error("invalid virtual address: ", vo); - throw Invalid_range(); - } - - /* clear bits 39 - 63 */ - vo &= VM_MASK; - - for (size_t i = vo >> BLOCK_SIZE_LOG2; size > 0; - i = vo >> BLOCK_SIZE_LOG2) { - addr_t end = (vo + BLOCK_SIZE) & BLOCK_MASK; - size_t sz = min(size, end-vo); - - func(vo, pa, sz, _entries[i]); - - /* flush cached table entry address */ - Cpu::translation_added((addr_t)&_entries[i], sz); - - /* check whether we wrap */ - if (end < vo) return; - - size = size - sz; - vo += sz; - pa += sz; - } - } - - template - struct Insert_func - { - Page_flags const & flags; - Translation_table_allocator * alloc; - - Insert_func(Page_flags const & flags, - Translation_table_allocator * alloc) - : flags(flags), alloc(alloc) { } - - void operator () (addr_t const vo, - addr_t const pa, - size_t const size, - typename Descriptor::access_t &desc) - { - /* can we insert a whole block? */ - if (!((vo & ~BLOCK_MASK) || (pa & ~BLOCK_MASK) || size < BLOCK_SIZE)) { - typename Descriptor::access_t blk_desc = - Block_descriptor::create(flags, pa); - - if (Descriptor::valid(desc) && desc == blk_desc) - throw Double_insertion(); - - desc = blk_desc; - return; - } - - /* we need to use a next level table */ - ENTRY *table; - switch (Descriptor::type(desc)) { - - case Descriptor::INVALID: /* no entry */ - { - if (!alloc) - throw Allocator::Out_of_memory(); - - /* create and link next level table */ - table = new (alloc) ENTRY(); - ENTRY * phys_addr = (ENTRY*) alloc->phys_addr(table); - desc = Table_descriptor::create(phys_addr ? - phys_addr : table); - } - - case Descriptor::TABLE: /* table already available */ - { - /* use allocator to retrieve virt address of table */ - ENTRY * phys_addr = (ENTRY*) - Table_descriptor::Base::bits(Table_descriptor::Ppn::get(desc)); - table = (ENTRY*) alloc->virt_addr(phys_addr); - table = table ? table : (ENTRY*)phys_addr; - break; - } - - case Descriptor::BLOCK: /* there is already a block */ - throw Double_insertion(); - }; - - /* insert translation */ - table->insert_translation(vo - (vo & BLOCK_MASK), - pa, size, flags, alloc); - } - }; - - template - struct Remove_func - { - Translation_table_allocator * alloc; - - Remove_func(Translation_table_allocator * alloc) : alloc(alloc) { } - - void operator () (addr_t const vo, - addr_t const pa, - size_t const size, - typename Descriptor::access_t &desc) - { - switch (Descriptor::type(desc)) { - case Descriptor::TABLE: - { - /* use allocator to retrieve virt address of table */ - ENTRY * phys_addr = (ENTRY*) - Table_descriptor::Base::bits(Table_descriptor::Ppn::get(desc)); - ENTRY * table = (ENTRY*) alloc->virt_addr(phys_addr); - table = table ? table : (ENTRY*)phys_addr; - table->remove_translation(vo - (vo & BLOCK_MASK), - size, alloc); - if (!table->empty()) - break; - destroy(alloc, table); - } - case Descriptor::BLOCK: - case Descriptor::INVALID: - desc = 0; - } - } - }; - - public: - - Level_x_translation_table() - { - if (!_aligned((addr_t)this, ALIGNM_LOG2)) { - Genode::warning("misaligned address"); - throw Misaligned(); - } - - memset(&_entries, 0, sizeof(_entries)); - } - - bool empty() - { - for (unsigned i = 0; i < MAX_ENTRIES; i++) - if (Descriptor::valid(_entries[i])) - return false; - return true; - } - - /** - * Insert translations into this table - * - * \param vo offset of the virtual region represented - * by the translation within the virtual - * region represented by this table - * \param pa base of the physical backing store - * \param size size of the translated region - * \param flags mapping flags - * \param alloc level allocator - */ - void insert_translation(addr_t vo, addr_t pa, size_t size, - Page_flags const & flags, - Translation_table_allocator * alloc ) - { - _range_op(vo, pa, size, Insert_func(flags, alloc)); - } - - /** - * Remove translations that overlap with a given virtual region - * - * \param vo region offset within the tables virtual region - * \param size region size - * \param alloc level allocator - */ - void remove_translation(addr_t vo, size_t size, - Translation_table_allocator * alloc) - { - _range_op(vo, 0, size, Remove_func(alloc)); - } -} __attribute__((aligned(1 << ALIGNM_LOG2))); - -namespace Sv39 { - - /** - * Insert/Remove functor specialization for level 3 - */ - template <> template <> - struct Level_3_translation_table::Insert_func - { - Page_flags const & flags; - Translation_table_allocator * alloc; - - Insert_func(Page_flags const & flags, - Translation_table_allocator * alloc) - : flags(flags), alloc(alloc) { } - - void operator () (addr_t const vo, - addr_t const pa, - size_t const size, - Descriptor::access_t &desc) - { - if ((vo & ~BLOCK_MASK) || (pa & ~BLOCK_MASK) || - size < BLOCK_SIZE) { - Genode::warning("invalid range"); - throw Invalid_range(); - } - - Descriptor::access_t blk_desc = - Block_descriptor::create(flags, pa); - - if (Descriptor::valid(desc) && desc == blk_desc) - throw Double_insertion(); - - desc = blk_desc; - } - }; - - template <> template <> - struct Level_3_translation_table::Remove_func - { - Remove_func(Translation_table_allocator *) { } - - void operator () (addr_t const vo, - addr_t const pa, - size_t const size, - Descriptor::access_t &desc) { - desc = 0; } - }; -} - -namespace Genode { - - class Translation_table : public Sv39::Level_1_translation_table - { - public: - - enum { - TABLE_LEVEL_X_SIZE_LOG2 = Sv39::SIZE_LOG2_4K, - CORE_VM_AREA_SIZE = 128 * 1024 * 1024, - CORE_TRANS_TABLE_COUNT = - _count(CORE_VM_AREA_SIZE, Sv39::SIZE_LOG2_1G) + - _count(CORE_VM_AREA_SIZE, Sv39::SIZE_LOG2_2M), - }; - }; -} - -#endif /* _TRANSLATION_TABLE_H_ */ +#endif /* _CORE__INCLUDE__SPEC__RISCV__TRANSLATION_TABLE_H_ */ diff --git a/repos/base-hw/src/core/include/spec/smp/kernel/lock.h b/repos/base-hw/src/core/include/spec/smp/kernel/lock.h index a61084e029..2ace7b1772 100644 --- a/repos/base-hw/src/core/include/spec/smp/kernel/lock.h +++ b/repos/base-hw/src/core/include/spec/smp/kernel/lock.h @@ -15,49 +15,13 @@ #ifndef _CORE__INCLUDE__KERNEL__LOCK_H_ #define _CORE__INCLUDE__KERNEL__LOCK_H_ -/* Genode includes */ -#include -#include -#include +#include namespace Kernel { - /** - * Lock that enables synchronization inside the kernel - */ - class Lock; + using Lock = Hw::Spin_lock; Lock & data_lock(); } -class Kernel::Lock -{ - private: - - int volatile _locked; - - public: - - Lock() : _locked(0) { } - - /** - * Request the lock - */ - void lock() { while (!Genode::cmpxchg(&_locked, 0, 1)); } - - /** - * Free the lock - */ - void unlock() - { - Genode::memory_barrier(); - _locked = 0; - } - - /** - * Provide guard semantic for this type of lock - */ - typedef Genode::Lock_guard Guard; -}; - #endif /* _CORE__INCLUDE__KERNEL__LOCK_H_ */ diff --git a/repos/base-hw/src/core/include/spec/x86_64/board.h b/repos/base-hw/src/core/include/spec/x86_64/board.h index 983908a099..afdca80572 100644 --- a/repos/base-hw/src/core/include/spec/x86_64/board.h +++ b/repos/base-hw/src/core/include/spec/x86_64/board.h @@ -19,18 +19,11 @@ namespace Genode struct Board { enum { - MMIO_LAPIC_BASE = 0xfee00000, - MMIO_LAPIC_SIZE = 0x1000, - MMIO_IOAPIC_BASE = 0xfec00000, - MMIO_IOAPIC_SIZE = 0x1000, - VECTOR_REMAP_BASE = 48, TIMER_VECTOR_KERNEL = 32, TIMER_VECTOR_USER = 50, ISA_IRQ_END = 15, }; - - void init() { } }; } diff --git a/repos/base-hw/src/core/include/spec/x86_64/macros.s b/repos/base-hw/src/core/include/spec/x86_64/macros.s index 29ef1ca7c6..608368798a 100644 --- a/repos/base-hw/src/core/include/spec/x86_64/macros.s +++ b/repos/base-hw/src/core/include/spec/x86_64/macros.s @@ -12,6 +12,7 @@ * under the terms of the GNU Affero General Public License version 3. */ +.include "hw/spec/x86_64/gdt.s" /*************************************************** ** Constant values that are pretty commonly used ** @@ -20,51 +21,3 @@ /* alignment constraints */ .set MIN_PAGE_SIZE_LOG2, 12 .set DATA_ACCESS_ALIGNM_LOG2, 2 - - -/****************************************** - ** Global Descriptor Table (GDT) ** - ** See Intel SDM Vol. 3A, section 3.5.1 ** - ******************************************/ - -.macro _define_gdt tss_address - .align 4 - .space 2 - .global _mt_gdt_ptr - .global _mt_gdt_start - _mt_gdt_ptr: - .word _mt_gdt_end - _mt_gdt_start - 1 /* limit */ - .long _mt_gdt_start /* base address */ - - .set TSS_LIMIT, 0x68 - .set TSS_TYPE, 0x8900 - - .align 8 - _mt_gdt_start: - /* Null descriptor */ - .quad 0 - /* 64-bit code segment descriptor */ - .long 0 - /* GDTE_LONG | GDTE_PRESENT | GDTE_CODE | GDTE_NON_SYSTEM */ - .long 0x209800 - /* 64-bit data segment descriptor */ - .long 0 - /* GDTE_LONG | GDTE_PRESENT | GDTE_TYPE_DATA_A | GDTE_TYPE_DATA_W | GDTE_NON_SYSTEM */ - .long 0x209300 - /* 64-bit user code segment descriptor */ - .long 0 - /* GDTE_LONG | GDTE_PRESENT | GDTE_CODE | GDTE_NON_SYSTEM */ - .long 0x20f800 - /* 64-bit user data segment descriptor */ - .long 0 - /* GDTE_LONG | GDTE_PRESENT | GDTE_TYPE_DATA_A | GDTE_TYPE_DATA_W | GDTE_NON_SYSTEM */ - .long 0x20f300 - /* Task segment descriptor */ - .long (\tss_address & 0xffff) << 16 | TSS_LIMIT - /* GDTE_PRESENT | GDTE_SYS_TSS */ - .long ((\tss_address >> 24) & 0xff) << 24 | ((\tss_address >> 16) & 0xff) | TSS_TYPE - .long \tss_address >> 32 - .long 0 - .global _mt_gdt_end - _mt_gdt_end: -.endm diff --git a/repos/base-hw/src/core/include/spec/x86_64/translation_table.h b/repos/base-hw/src/core/include/spec/x86_64/translation_table.h index 7799cdbfc1..ff74888318 100644 --- a/repos/base-hw/src/core/include/spec/x86_64/translation_table.h +++ b/repos/base-hw/src/core/include/spec/x86_64/translation_table.h @@ -11,713 +11,4 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _CORE__INCLUDE__SPEC__X86_64__TRANSLATION_TABLE_H_ -#define _CORE__INCLUDE__SPEC__X86_64__TRANSLATION_TABLE_H_ - -/* Genode includes */ -#include -#include -#include - -/* base-hw includes */ -#include -#include -#include - -namespace Genode -{ - - /** - * IA-32e paging translates 48-bit linear addresses to 52-bit physical - * addresses. Translation structures are hierarchical and four levels - * deep. - * - * For detailed information refer to Intel SDM Vol. 3A, section 4.5. - */ - - enum { - SIZE_LOG2_4KB = 12, - SIZE_LOG2_2MB = 21, - SIZE_LOG2_1GB = 30, - SIZE_LOG2_512GB = 39, - SIZE_LOG2_256TB = 48, - }; - - class Level_4_translation_table; - class Pml4_table; - - /** - * IA-32e page directory template. - * - * Page directories can refer to paging structures of the next higher level - * or directly map page frames by using large page mappings. - * - * \param PAGE_SIZE_LOG2 virtual address range size in log2 - * of a single table entry - * \param SIZE_LOG2 virtual address range size in log2 of whole table - */ - template - class Page_directory; - - using Level_3_translation_table = - Page_directory; - using Level_2_translation_table = - Page_directory; - - /** - * IA-32e common descriptor. - * - * Table entry containing descriptor fields common to all four levels. - */ - struct Common_descriptor : Register<64> - { - struct P : Bitfield<0, 1> { }; /* present */ - struct Rw : Bitfield<1, 1> { }; /* read/write */ - struct Us : Bitfield<2, 1> { }; /* user/supervisor */ - struct Pwt : Bitfield<3, 1> { }; /* write-through */ - struct Pcd : Bitfield<4, 1> { }; /* cache disable */ - struct A : Bitfield<5, 1> { }; /* accessed */ - struct D : Bitfield<6, 1> { }; /* dirty */ - struct Xd : Bitfield<63, 1> { }; /* execute-disable */ - - static bool present(access_t const v) { return P::get(v); } - - static access_t create(Page_flags const &flags) - { - return P::bits(1) - | Rw::bits(flags.writeable) - | Us::bits(!flags.privileged) - | Xd::bits(!flags.executable); - } - - /** - * Return descriptor value with cleared accessed and dirty flags. These - * flags can be set by the MMU. - */ - static access_t clear_mmu_flags(access_t value) - { - A::clear(value); - D::clear(value); - return value; - } - - /** - * Merge access rights of descriptor with given flags. - */ - static void merge_access_rights(access_t &desc, - Page_flags const &flags) - { - Rw::set(desc, Rw::get(desc) | flags.writeable); - Us::set(desc, Us::get(desc) | !flags.privileged); - Xd::set(desc, Xd::get(desc) & !flags.executable); - } - }; -} - -class Genode::Level_4_translation_table -{ - private: - - static constexpr size_t PAGE_SIZE_LOG2 = SIZE_LOG2_4KB; - static constexpr size_t SIZE_LOG2 = SIZE_LOG2_2MB; - static constexpr size_t MAX_ENTRIES = 1UL << (SIZE_LOG2-PAGE_SIZE_LOG2); - static constexpr size_t PAGE_SIZE = 1UL << PAGE_SIZE_LOG2; - static constexpr size_t PAGE_MASK = ~((1UL << PAGE_SIZE_LOG2) - 1); - - class Misaligned {}; - class Invalid_range {}; - class Double_insertion {}; - - struct Descriptor : Common_descriptor - { - using Common = Common_descriptor; - - struct Pat : Bitfield<7, 1> { }; /* page attribute table */ - struct G : Bitfield<8, 1> { }; /* global */ - struct Pa : Bitfield<12, 36> { }; /* physical address */ - struct Mt : Bitset_3 { }; /* memory type */ - - static access_t create(Page_flags const &flags, addr_t const pa) - { - /* XXX: Set memory type depending on active PAT */ - return Common::create(flags) - | G::bits(flags.global) - | Pa::masked(pa); - } - }; - - typename Descriptor::access_t _entries[MAX_ENTRIES]; - - struct Insert_func - { - Page_flags const & flags; - Translation_table_allocator * alloc; - - Insert_func(Page_flags const & flags, - Translation_table_allocator * alloc) - : flags(flags), alloc(alloc) { } - - void operator () (addr_t const vo, addr_t const pa, - size_t const size, - Descriptor::access_t &desc) - { - if ((vo & ~PAGE_MASK) || (pa & ~PAGE_MASK) || - size < PAGE_SIZE) - { - throw Invalid_range(); - } - Descriptor::access_t table_entry = - Descriptor::create(flags, pa); - - if (Descriptor::present(desc) && - Descriptor::clear_mmu_flags(desc) != table_entry) - { - throw Double_insertion(); - } - desc = table_entry; - } - }; - - struct Remove_func - { - Translation_table_allocator * alloc; - - Remove_func(Translation_table_allocator * alloc) : alloc(alloc) { } - - void operator () (addr_t const vo, addr_t const pa, - size_t const size, - Descriptor::access_t &desc) - { desc = 0; } - }; - - template - void _range_op(addr_t vo, addr_t pa, size_t size, FUNC &&func) - { - for (size_t i = vo >> PAGE_SIZE_LOG2; size > 0; - i = vo >> PAGE_SIZE_LOG2) { - assert (i < MAX_ENTRIES); - addr_t end = (vo + PAGE_SIZE) & PAGE_MASK; - size_t sz = min(size, end-vo); - - func(vo, pa, sz, _entries[i]); - - /* check whether we wrap */ - if (end < vo) return; - - size = size - sz; - vo += sz; - pa += sz; - } - } - - public: - - static constexpr size_t MIN_PAGE_SIZE_LOG2 = SIZE_LOG2_4KB; - static constexpr size_t ALIGNM_LOG2 = SIZE_LOG2_4KB; - - /** - * IA-32e page table (Level 4) - * - * A page table consists of 512 entries that each maps a 4KB page - * frame. For further details refer to Intel SDM Vol. 3A, table 4-19. - */ - Level_4_translation_table() - { - if (!aligned(this, ALIGNM_LOG2)) throw Misaligned(); - memset(&_entries, 0, sizeof(_entries)); - } - - /** - * Returns True if table does not contain any page mappings. - */ - bool empty() - { - for (unsigned i = 0; i < MAX_ENTRIES; i++) - if (Descriptor::present(_entries[i])) - return false; - return true; - } - - /** - * Insert translations into this table - * - * \param vo offset of the virtual region represented - * by the translation within the virtual - * region represented by this table - * \param pa base of the physical backing store - * \param size size of the translated region - * \param flags mapping flags - * \param alloc second level translation table allocator - */ - void insert_translation(addr_t vo, addr_t pa, size_t size, - Page_flags const & flags, - Translation_table_allocator * alloc) - { - this->_range_op(vo, pa, size, Insert_func(flags, alloc)); - } - - /** - * Remove translations that overlap with a given virtual region - * - * \param vo region offset within the tables virtual region - * \param size region size - * \param alloc second level translation table allocator - */ - void remove_translation(addr_t vo, size_t size, - Translation_table_allocator * alloc) - { - this->_range_op(vo, 0, size, Remove_func(alloc)); - } -} __attribute__((aligned(1 << ALIGNM_LOG2))); - - -template -class Genode::Page_directory -{ - private: - - static constexpr size_t MAX_ENTRIES = 1UL << (SIZE_LOG2-PAGE_SIZE_LOG2); - static constexpr size_t PAGE_SIZE = 1UL << PAGE_SIZE_LOG2; - static constexpr size_t PAGE_MASK = ~((1UL << PAGE_SIZE_LOG2) - 1); - - class Misaligned {}; - class Invalid_range {}; - class Double_insertion {}; - - struct Base_descriptor : Common_descriptor - { - using Common = Common_descriptor; - - struct Ps : Common::template Bitfield<7, 1> { }; /* page size */ - - static bool maps_page(access_t const v) { return Ps::get(v); } - }; - - struct Page_descriptor : Base_descriptor - { - using Base = Base_descriptor; - - /** - * Global attribute - */ - struct G : Base::template Bitfield<8, 1> { }; - - /** - * Page attribute table - */ - struct Pat : Base::template Bitfield<12, 1> { }; - - /** - * Physical address - */ - struct Pa : Base::template Bitfield { }; - - /** - * Memory type - */ - struct Mt : Base::template Bitset_3 { }; - - static typename Base::access_t create(Page_flags const &flags, - addr_t const pa) - { - /* XXX: Set memory type depending on active PAT */ - return Base::create(flags) - | Base::Ps::bits(1) - | G::bits(flags.global) - | Pa::masked(pa); - } - }; - - struct Table_descriptor : Base_descriptor - { - using Base = Base_descriptor; - - /** - * Physical address - */ - struct Pa : Base::template Bitfield<12, 36> { }; - - /** - * Memory types - */ - struct Mt : Base::template Bitset_2 { }; - - static typename Base::access_t create(Page_flags const &flags, - addr_t const pa) - { - /* XXX: Set memory type depending on active PAT */ - return Base::create(flags) | Pa::masked(pa); - } - }; - - typename Base_descriptor::access_t _entries[MAX_ENTRIES]; - - struct Insert_func - { - Page_flags const & flags; - Translation_table_allocator * alloc; - - Insert_func(Page_flags const & flags, - Translation_table_allocator * alloc) - : flags(flags), alloc(alloc) { } - - void operator () (addr_t const vo, addr_t const pa, - size_t const size, - typename Base_descriptor::access_t &desc) - { - /* can we insert a large page mapping? */ - if (!((vo & ~PAGE_MASK) || (pa & ~PAGE_MASK) || - size < PAGE_SIZE)) - { - typename Base_descriptor::access_t table_entry = - Page_descriptor::create(flags, pa); - - if (Base_descriptor::present(desc) && - Base_descriptor::clear_mmu_flags(desc) != table_entry) - { - throw Double_insertion(); - } - - desc = table_entry; - return; - } - - /* we need to use a next level table */ - ENTRY *table; - if (!Base_descriptor::present(desc)) { - if (!alloc) - throw Allocator::Out_of_memory(); - - /* create and link next level table */ - table = new (alloc) ENTRY(); - ENTRY * phys_addr = (ENTRY*) alloc->phys_addr(table); - addr_t const pa = (addr_t)(phys_addr ? phys_addr : table); - desc = (typename Base_descriptor::access_t) - Table_descriptor::create(flags, pa); - - } else if (Base_descriptor::maps_page(desc)) { - throw Double_insertion(); - } else { - Base_descriptor::merge_access_rights(desc, flags); - ENTRY * phys_addr = (ENTRY*) - Table_descriptor::Pa::masked(desc); - table = (ENTRY*) alloc->virt_addr(phys_addr); - table = table ? table : (ENTRY*)phys_addr; - } - - /* insert translation */ - table->insert_translation(vo - (vo & PAGE_MASK), - pa, size, flags, alloc); - } - }; - - struct Remove_func - { - Translation_table_allocator * alloc; - - Remove_func(Translation_table_allocator * alloc) : alloc(alloc) { } - - void operator () (addr_t const vo, addr_t const pa, - size_t const size, - typename Base_descriptor::access_t &desc) - { - if (Base_descriptor::present(desc)) { - if (Base_descriptor::maps_page(desc)) { - desc = 0; - } else { - /* use allocator to retrieve virt address of table */ - ENTRY* phys_addr = (ENTRY*) - Table_descriptor::Pa::masked(desc); - ENTRY* table = (ENTRY*) alloc->virt_addr(phys_addr); - table = table ? table : (ENTRY*)phys_addr; - addr_t const table_vo = vo - (vo & PAGE_MASK); - table->remove_translation(table_vo, size, alloc); - if (table->empty()) { - destroy(alloc, table); - desc = 0; - } - } - } - } - }; - - template - void _range_op(addr_t vo, addr_t pa, size_t size, FUNC &&func) - { - for (size_t i = vo >> PAGE_SIZE_LOG2; size > 0; - i = vo >> PAGE_SIZE_LOG2) - { - assert (i < MAX_ENTRIES); - addr_t end = (vo + PAGE_SIZE) & PAGE_MASK; - size_t sz = min(size, end-vo); - - func(vo, pa, sz, _entries[i]); - - /* check whether we wrap */ - if (end < vo) return; - - size = size - sz; - vo += sz; - pa += sz; - } - } - - public: - - static constexpr size_t MIN_PAGE_SIZE_LOG2 = SIZE_LOG2_4KB; - static constexpr size_t ALIGNM_LOG2 = SIZE_LOG2_4KB; - - Page_directory() - { - if (!aligned(this, ALIGNM_LOG2)) throw Misaligned(); - memset(&_entries, 0, sizeof(_entries)); - } - - /** - * Returns True if table does not contain any page mappings. - * - * \return false if an entry is present, True otherwise - */ - bool empty() - { - for (unsigned i = 0; i < MAX_ENTRIES; i++) - if (Base_descriptor::present(_entries[i])) - return false; - return true; - } - - /** - * Insert translations into this table - * - * \param vo offset of the virtual region represented - * by the translation within the virtual - * region represented by this table - * \param pa base of the physical backing store - * \param size size of the translated region - * \param flags mapping flags - * \param alloc second level translation table allocator - */ - void insert_translation(addr_t vo, addr_t pa, size_t size, - Page_flags const & flags, - Translation_table_allocator * alloc) - { - _range_op(vo, pa, size, Insert_func(flags, alloc)); - } - - /** - * Remove translations that overlap with a given virtual region - * - * \param vo region offset within the tables virtual region - * \param size region size - * \param alloc second level translation table allocator - */ - void remove_translation(addr_t vo, size_t size, - Translation_table_allocator * alloc) - { - _range_op(vo, 0, size, Remove_func(alloc)); - } -} __attribute__((aligned(1 << ALIGNM_LOG2))); - - -class Genode::Pml4_table -{ - private: - - static constexpr size_t PAGE_SIZE_LOG2 = SIZE_LOG2_512GB; - static constexpr size_t SIZE_LOG2 = SIZE_LOG2_256TB; - static constexpr size_t MAX_ENTRIES = 512; - static constexpr size_t PAGE_SIZE = 1UL << PAGE_SIZE_LOG2; - static constexpr size_t PAGE_MASK = ~((1UL << PAGE_SIZE_LOG2) - 1); - - class Misaligned {}; - class Invalid_range {}; - - struct Descriptor : Common_descriptor - { - struct Pa : Bitfield<12, SIZE_LOG2> { }; /* physical address */ - struct Mt : Bitset_2 { }; /* memory type */ - - static access_t create(Page_flags const &flags, addr_t const pa) - { - /* XXX: Set memory type depending on active PAT */ - return Common_descriptor::create(flags) | Pa::masked(pa); - } - }; - - typename Descriptor::access_t _entries[MAX_ENTRIES]; - - using ENTRY = Level_2_translation_table; - - struct Insert_func - { - Page_flags const & flags; - Translation_table_allocator * alloc; - - Insert_func(Page_flags const & flags, - Translation_table_allocator * alloc) - : flags(flags), alloc(alloc) { } - - void operator () (addr_t const vo, addr_t const pa, - size_t const size, - Descriptor::access_t &desc) - { - /* we need to use a next level table */ - ENTRY *table; - if (!Descriptor::present(desc)) { - if (!alloc) - throw Allocator::Out_of_memory(); - - /* create and link next level table */ - table = new (alloc) ENTRY(); - ENTRY * phys_addr = (ENTRY*) alloc->phys_addr(table); - addr_t const pa = (addr_t)(phys_addr ? phys_addr : table); - desc = Descriptor::create(flags, pa); - } else { - Descriptor::merge_access_rights(desc, flags); - ENTRY * phys_addr = (ENTRY*) - Descriptor::Pa::masked(desc); - table = (ENTRY*) alloc->virt_addr(phys_addr); - table = table ? table : (ENTRY*)phys_addr; - } - - /* insert translation */ - addr_t const table_vo = vo - (vo & PAGE_MASK); - table->insert_translation(table_vo, pa, size, flags, alloc); - } - }; - - struct Remove_func - { - Translation_table_allocator * alloc; - - Remove_func(Translation_table_allocator * alloc) : alloc(alloc) { } - - void operator () (addr_t const vo, addr_t const pa, - size_t const size, - Descriptor::access_t &desc) - { - if (Descriptor::present(desc)) { - /* use allocator to retrieve virt address of table */ - ENTRY* phys_addr = (ENTRY*) - Descriptor::Pa::masked(desc); - ENTRY* table = (ENTRY*) alloc->virt_addr(phys_addr); - table = table ? table : (ENTRY*)phys_addr; - addr_t const table_vo = vo - (vo & PAGE_MASK); - table->remove_translation(table_vo, size, alloc); - if (table->empty()) { - destroy(alloc, table); - desc = 0; - } - } - } - }; - - template - void _range_op(addr_t vo, addr_t pa, size_t size, FUNC &&func) - { - for (size_t i = vo >> PAGE_SIZE_LOG2; size > 0; - i = vo >> PAGE_SIZE_LOG2) { - assert (i < MAX_ENTRIES); - addr_t end = (vo + PAGE_SIZE) & PAGE_MASK; - size_t sz = min(size, end-vo); - - func(vo, pa, sz, _entries[i]); - - /* check whether we wrap */ - if (end < vo) return; - - size = size - sz; - vo += sz; - pa += sz; - } - } - - protected: - - /** - * Return how many entries of an alignment fit into region - */ - static constexpr size_t _count(size_t region, size_t alignment) { - return align_addr(region, alignment) / (1UL << alignment); } - - public: - - static constexpr size_t MIN_PAGE_SIZE_LOG2 = SIZE_LOG2_4KB; - static constexpr size_t ALIGNM_LOG2 = SIZE_LOG2_4KB; - - Pml4_table() - { - if (!aligned(this, ALIGNM_LOG2)) throw Misaligned(); - memset(&_entries, 0, sizeof(_entries)); - } - - /** - * Returns True if table does not contain any page mappings. - * - * \return false if an entry is present, True otherwise - */ - bool empty() - { - for (unsigned i = 0; i < MAX_ENTRIES; i++) - if (Descriptor::present(_entries[i])) - return false; - return true; - } - - /** - * Insert translations into this table - * - * \param vo offset of the virtual region represented - * by the translation within the virtual - * region represented by this table - * \param pa base of the physical backing store - * \param size size of the translated region - * \param flags mapping flags - * \param alloc second level translation table allocator - */ - void insert_translation(addr_t vo, addr_t pa, size_t size, - Page_flags const & flags, - Translation_table_allocator * alloc) - { - _range_op(vo, pa, size, Insert_func(flags, alloc)); - } - - /** - * Remove translations that overlap with a given virtual region - * - * \param vo region offset within the tables virtual region - * \param size region size - * \param alloc second level translation table allocator - */ - void remove_translation(addr_t vo, size_t size, - Translation_table_allocator * alloc) - { - _range_op(vo, 0, size, Remove_func(alloc)); - } -} __attribute__((aligned(1 << ALIGNM_LOG2))); - - -namespace Genode { - class Translation_table; -} - -class Genode::Translation_table : public Pml4_table -{ - public: - - enum { - TABLE_LEVEL_X_SIZE_LOG2 = SIZE_LOG2_4KB, - CORE_VM_AREA_SIZE = 1024 * 1024 * 1024, - CORE_TRANS_TABLE_COUNT = - _count(CORE_VM_AREA_SIZE, SIZE_LOG2_512GB) - + _count(CORE_VM_AREA_SIZE, SIZE_LOG2_1GB) - + _count(CORE_VM_AREA_SIZE, SIZE_LOG2_2MB) - }; -}; - -#endif /* _CORE__INCLUDE__SPEC__X86_64__TRANSLATION_TABLE_H_ */ +#include diff --git a/repos/base-hw/src/core/include/spec/zynq/cpu.h b/repos/base-hw/src/core/include/spec/zynq/cpu.h deleted file mode 100644 index df1cdea656..0000000000 --- a/repos/base-hw/src/core/include/spec/zynq/cpu.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * \brief CPU driver for core - * \author Stefan Kalkowski - * \date 2015-12-15 - */ - -/* - * Copyright (C) 2015-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _CPU_H_ -#define _CPU_H_ - -/* core includes */ -#include - -namespace Genode -{ - using Cpu = Genode::Cortex_a9; -} - -#endif /* _CPU_H_ */ diff --git a/repos/base-hw/src/core/include/translation_table_allocator.h b/repos/base-hw/src/core/include/translation_table_allocator.h deleted file mode 100644 index e1898c4585..0000000000 --- a/repos/base-hw/src/core/include/translation_table_allocator.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * \brief Translation table allocator - * \author Stefan Kalkowski - * \date 2015-06-10 - */ - -/* - * Copyright (C) 2015-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _CORE__INCLUDE__TRANSLATION_TABLE_ALLOCATOR_H_ -#define _CORE__INCLUDE__TRANSLATION_TABLE_ALLOCATOR_H_ - -#include - -namespace Genode { - - /** - * Translation table allocator interface - */ - class Translation_table_allocator; -} - - -class Genode::Translation_table_allocator : public Genode::Allocator -{ - public: - - /** - * Return physical address of given virtual page address - * - * \param addr virtual page address - */ - virtual void * phys_addr(void * addr) = 0; - - /** - * Return virtual address of given physical page address - * - * \param addr physical page address - */ - virtual void * virt_addr(void * addr) = 0; -}; - -#endif /* _CORE__INCLUDE__TRANSLATION_TABLE_ALLOCATOR_H_ */ diff --git a/repos/base-hw/src/core/include/translation_table_allocator_tpl.h b/repos/base-hw/src/core/include/translation_table_allocator_tpl.h deleted file mode 100644 index 457b60ac25..0000000000 --- a/repos/base-hw/src/core/include/translation_table_allocator_tpl.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * \brief Translation table allocator template implementation - * \author Stefan Kalkowski - * \date 2015-06-10 - */ - -/* - * Copyright (C) 2015-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _CORE__INCLUDE__TRANSLATION_TABLE_ALLOCATOR_TPL_H_ -#define _CORE__INCLUDE__TRANSLATION_TABLE_ALLOCATOR_TPL_H_ - -#include -#include -#include -#include -#include - -namespace Genode { - - /** - * Statically dimensioned translation table allocator - * - * /param TABLES count of tables the allocator provides as maximum - */ - template class Translation_table_allocator_tpl; -} - - -template -class Genode::Translation_table_allocator_tpl -{ - private: - - /** - * The actual allocator interface cannot be implmented by our - * template class itself, because of its strict alignment constraints - * and therefore the impossibility to have a vtable pointer at the - * beginning of the object's layout. Therefore, we use a private - * implementation of the interface and aggregate it. - */ - class Allocator; - - struct Table { - enum { SIZE = 1 << Translation_table::TABLE_LEVEL_X_SIZE_LOG2 }; - - uint8_t data[SIZE]; - }; - - Table _tables[TABLES]; - Allocator _alloc; - - public: - - static constexpr unsigned ALIGN = Table::SIZE; - - Translation_table_allocator_tpl() : _alloc(_tables, (addr_t)&_tables) {} - Translation_table_allocator_tpl(Core_mem_allocator *cma) - : _alloc(_tables, (addr_t)cma->phys_addr((void*)&_tables)) {} - - Translation_table_allocator * alloc() { return &_alloc; } - - static Translation_table_allocator_tpl * - base(Translation_table_allocator * alloc) - { - return (Translation_table_allocator_tpl*)((addr_t)alloc - - sizeof(Table)*TABLES); - } -} __attribute__((aligned(ALIGN))); - - -template -class Genode::Translation_table_allocator_tpl::Allocator -: public Translation_table_allocator -{ - private: - - Table *_tables; - Bit_allocator _free_tables; - addr_t _phys_addr; - - /** - * Allocate a page - * - * \returns pointer to new slab, or nullptr if allocation failed - */ - void *_alloc() - { - try { - return &_tables[_free_tables.alloc()]; - } catch(typename Bit_allocator::Out_of_indices&) {} - return nullptr; - } - - /** - * Free a given page - * - * \param addr virtual address of page to free - */ - void _free(void *addr) - { - _free_tables.free(((addr_t)addr - (addr_t)_tables) - / sizeof(Table)); - } - - public: - - Allocator(Table * tables, addr_t phys_addr) - : _tables(tables), _phys_addr(phys_addr) {} - - void * phys_addr(void * addr) - { - return (void*)((addr_t)addr - (addr_t)_tables - + _phys_addr); - } - - void * virt_addr(void * addr) - { - return (void*)((addr_t)_tables + ((addr_t)addr - - _phys_addr)); - } - - - /************************ - * Allocator interface ** - ************************/ - - bool alloc(size_t, void **addr) override { - return (*addr = _alloc()); } - void free(void *addr, size_t) override { _free(addr); } - size_t consumed() const override { return 0; } - size_t overhead(size_t) const override { return 0; } - bool need_size_for_free() const override { return false; } -}; - -#endif /* _CORE__INCLUDE__TRANSLATION_TABLE_ALLOCATOR_TPL_H_ */ diff --git a/repos/base-hw/src/core/include/trustzone.h b/repos/base-hw/src/core/include/trustzone.h deleted file mode 100644 index b664d2403b..0000000000 --- a/repos/base-hw/src/core/include/trustzone.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * \brief TrustZone specific functions - * \author Stefan Kalkowski - * \date 2012-10-10 - */ - -/* - * Copyright (C) 2012-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _CORE__INCLUDE__TRUSTZONE_H_ -#define _CORE__INCLUDE__TRUSTZONE_H_ - -/* core includes */ -#include - -namespace Kernel { - void init_trustzone(Pic & pic); -} - -#endif /* _CORE__INCLUDE__TRUSTZONE_H_ */ diff --git a/repos/base-hw/src/core/include/util.h b/repos/base-hw/src/core/include/util.h index 82248891fa..23d80b3931 100644 --- a/repos/base-hw/src/core/include/util.h +++ b/repos/base-hw/src/core/include/util.h @@ -1,6 +1,7 @@ /* * \brief Core-internal utilities * \author Martin Stein + * \author Stefan Kalkowski * \date 2012-01-02 */ @@ -14,73 +15,21 @@ #ifndef _CORE__INCLUDE__UTIL_H_ #define _CORE__INCLUDE__UTIL_H_ -/* Genode includes */ -#include - -/* base-internal includes */ -#include - -/* base-hw includes */ -#include +#include namespace Genode { - enum { - ACTIVITY_TABLE_ON_FAULTS = 0, - }; - - /** - * Get the base mask for the minimal supported page-size - */ - constexpr addr_t get_page_mask() { return ~(get_page_size() - 1); } - - - /** - * Round down to the minimal page-size alignment - */ - constexpr addr_t trunc_page(addr_t addr) { - return addr & get_page_mask(); } - - - /** - * Round up to the minimal page-size alignment - */ - constexpr addr_t round_page(addr_t addr) - { return trunc_page(addr + get_page_size() - 1); } - - - /** - * Return an address rounded down to a specific alignment - * - * \param addr original address - * \param alignm_log2 log2 of the required alignment - */ - inline addr_t trunc(addr_t const addr, addr_t const alignm_log2) { - return (addr >> alignm_log2) << alignm_log2; } - - - /** - * Return wether a pointer fullfills an alignment - * - * \param p pointer - * \param alignm_log2 log2 of the required alignment - */ - inline bool aligned(void * const p, addr_t const alignm_log2) { - return (addr_t)p == trunc((addr_t)p, alignm_log2); } - - - /** - * Round up to a specific alignment - */ - inline addr_t round(addr_t const addr, unsigned const alignm_log2) - { return trunc(addr + (1< -#include +#include using namespace Kernel; diff --git a/repos/base-hw/src/core/kernel/cpu.cc b/repos/base-hw/src/core/kernel/cpu.cc index 9aa4254184..b937a37382 100644 --- a/repos/base-hw/src/core/kernel/cpu.cc +++ b/repos/base-hw/src/core/kernel/cpu.cc @@ -20,7 +20,7 @@ #include #include #include -#include +#include /* base-internal includes */ #include @@ -261,7 +261,7 @@ Genode::size_t kernel_stack_size = KERNEL_STACK_SIZE; Genode::uint8_t kernel_stack[NR_OF_CPUS][KERNEL_STACK_SIZE] __attribute__((aligned(Genode::get_page_size()))); -Cpu_context::Cpu_context(Genode::Translation_table * const table) +Cpu_context::Cpu_context(Hw::Page_table * const table) { sp = (addr_t)kernel_stack; ip = (addr_t)kernel; diff --git a/repos/base-hw/src/core/kernel/cpu_scheduler.cc b/repos/base-hw/src/core/kernel/cpu_scheduler.cc index 33b2c5492c..9db8e91f41 100644 --- a/repos/base-hw/src/core/kernel/cpu_scheduler.cc +++ b/repos/base-hw/src/core/kernel/cpu_scheduler.cc @@ -11,12 +11,9 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* Genode includes */ #include - -/* core includes */ +#include #include -#include using namespace Kernel; diff --git a/repos/base-hw/src/core/kernel/init.cc b/repos/base-hw/src/core/kernel/init.cc index f51f29f0f3..260451fee3 100644 --- a/repos/base-hw/src/core/kernel/init.cc +++ b/repos/base-hw/src/core/kernel/init.cc @@ -29,7 +29,7 @@ static_assert(sizeof(Genode::sizet_arithm_t) >= 2 * sizeof(size_t), "Bad result type for size_t arithmetics."); Pd * Kernel::core_pd() { - return unmanaged_singleton()->kernel_pd(); } + return &unmanaged_singleton()->kernel_pd(); } Pic * Kernel::pic() { return unmanaged_singleton(); } @@ -38,27 +38,29 @@ Genode::Board & Kernel::board() { return *unmanaged_singleton(); } +extern "C" void _start() __attribute__((section(".text.crt0"))); + /** * Setup kernel environment */ -extern "C" void init_kernel() +extern "C" void _start() { static volatile bool initialized = false; if (Cpu::executing_id()) while (!initialized) ; + else { + Genode::log(""); + Genode::log("kernel initialized"); + } /* initialize cpu pool */ cpu_pool(); /* initialize current cpu */ - cpu_pool()->cpu(Cpu::executing_id())->init(*pic()/*, *core_pd(), board()*/); + cpu_pool()->cpu(Cpu::executing_id())->init(*pic()); Core_thread::singleton(); - if (!Cpu::executing_id()) { - initialized = true; - Genode::log(""); - Genode::log("kernel initialized"); - } + if (!Cpu::executing_id()) initialized = true; kernel(); } diff --git a/repos/base-hw/src/core/kernel/ipc_node.cc b/repos/base-hw/src/core/kernel/ipc_node.cc index 51b21b9ea9..925a22e3fa 100644 --- a/repos/base-hw/src/core/kernel/ipc_node.cc +++ b/repos/base-hw/src/core/kernel/ipc_node.cc @@ -19,7 +19,6 @@ #include /* core includes */ -#include #include #include #include diff --git a/repos/base-hw/src/core/kernel/pd.cc b/repos/base-hw/src/core/kernel/pd.cc index b0edbef2c1..e0daad2a98 100644 --- a/repos/base-hw/src/core/kernel/pd.cc +++ b/repos/base-hw/src/core/kernel/pd.cc @@ -12,22 +12,18 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* core includes */ -#include -#include -#include -#include -#include - -#include -#include - -/* base-internal includes */ #include #include +#include +#include +#include +#include +#include + +#include using namespace Kernel; -using Genode::Translation_table; +using Hw::Page_table; using Genode::Platform; /* structure of the mode transition */ @@ -36,15 +32,15 @@ extern int _mt_user_entry_pic; extern int _mt_client_context_ptr; -void Mode_transition_control::map(Genode::Translation_table * tt, - Genode::Translation_table_allocator * alloc) +void Mode_transition_control::map(Page_table & tt, + Page_table::Allocator & alloc) { static addr_t const phys_base = Platform::core_phys_addr((addr_t)&_mt_begin); try { - tt->insert_translation(Cpu::exception_entry, phys_base, Cpu::mtc_size, - Genode::PAGE_FLAGS_KERN_EXCEP, alloc); + tt.insert_translation(Cpu::exception_entry, phys_base, Cpu::mtc_size, + Hw::PAGE_FLAGS_KERN_EXCEP, alloc); } catch(...) { Genode::error("inserting exception vector in page table failed!"); } } diff --git a/repos/base-hw/src/core/kernel/thread.cc b/repos/base-hw/src/core/kernel/thread.cc index ed071fac7f..edb9b51aaf 100644 --- a/repos/base-hw/src/core/kernel/thread.cc +++ b/repos/base-hw/src/core/kernel/thread.cc @@ -23,7 +23,7 @@ #include /* core includes */ -#include +#include #include #include #include @@ -583,8 +583,8 @@ void Thread::_call() case call_id_thread_pager(): _call_pager(); return; case call_id_update_pd(): _call_update_pd(); return; case call_id_new_pd(): - _call_new((Genode::Translation_table *) user_arg_2(), - (Genode::Platform_pd *) user_arg_3()); + _call_new((Hw::Page_table *) user_arg_2(), + (Genode::Platform_pd *) user_arg_3()); return; case call_id_delete_pd(): _call_delete(); return; case call_id_new_signal_receiver(): _call_new(); return; diff --git a/repos/base-hw/src/core/platform.cc b/repos/base-hw/src/core/platform.cc index f498471468..63d687755e 100644 --- a/repos/base-hw/src/core/platform.cc +++ b/repos/base-hw/src/core/platform.cc @@ -17,17 +17,16 @@ /* core includes */ #include -#include +#include #include #include #include #include -#include -#include +#include +#include #include #include #include -#include /* base-internal includes */ #include @@ -35,45 +34,47 @@ using namespace Genode; -void __attribute__((weak)) Kernel::init_trustzone(Pic & pic) { } - /************** ** Platform ** **************/ -Bootinfo const & Platform::_bootinfo() { - return *reinterpret_cast(round_page((addr_t)&_prog_img_end)); } +Hw::Boot_info const & Platform::_boot_info() { + return *reinterpret_cast(round_page((addr_t)&_prog_img_end)); } addr_t Platform::mmio_to_virt(addr_t mmio) { - return _bootinfo().core_mmio.virt_addr(mmio); } + return _boot_info().mmio_space.virt_addr(mmio); } -Translation_table * Platform::core_translation_table() { - return _bootinfo().table; } +Hw::Page_table & Platform::core_page_table() { + return *(Hw::Page_table*)_boot_info().table; } -Translation_table_allocator * Platform::core_translation_table_allocator() { - return _bootinfo().table_allocator->alloc(); } +Hw::Page_table::Allocator & Platform::core_page_table_allocator() +{ + using Allocator = Hw::Page_table::Allocator; + using Array = Allocator::Array; + return unmanaged_singleton(*((Array*)_boot_info().table_allocator))->alloc(); +} void Platform::_init_io_mem_alloc() { /* add entire adress space minus the RAM memory regions */ _io_mem_alloc.add_range(0, ~0x0UL); - _bootinfo().ram_regions.for_each([this] (Memory_region const &r) { + _boot_info().ram_regions.for_each([this] (Hw::Memory_region const &r) { _io_mem_alloc.remove_range(r.base, r.size); }); }; -Memory_region_array const & Platform::_core_virt_regions() +Hw::Memory_region_array const & Platform::_core_virt_regions() { - return *unmanaged_singleton( - Memory_region(stack_area_virtual_base(), stack_area_virtual_size())); + return *unmanaged_singleton( + Hw::Memory_region(stack_area_virtual_base(), stack_area_virtual_size())); } addr_t Platform::core_phys_addr(addr_t virt) { addr_t ret = 0; - _bootinfo().elf_mappings.for_each([&] (Mapping const & m) + _boot_info().elf_mappings.for_each([&] (Hw::Mapping const & m) { if (virt >= m.virt() && virt < (m.virt() + m.size())) ret = (virt - m.virt()) + m.phys(); @@ -90,11 +91,11 @@ Platform::Platform() { _core_mem_alloc.virt_alloc()->add_range(VIRT_ADDR_SPACE_START, VIRT_ADDR_SPACE_SIZE); - _core_virt_regions().for_each([this] (Memory_region const & r) { + _core_virt_regions().for_each([this] (Hw::Memory_region const & r) { _core_mem_alloc.virt_alloc()->remove_range(r.base, r.size); }); - _bootinfo().elf_mappings.for_each([this] (Mapping const & m) { + _boot_info().elf_mappings.for_each([this] (Hw::Mapping const & m) { _core_mem_alloc.virt_alloc()->remove_range(m.virt(), m.size()); }); - _bootinfo().ram_regions.for_each([this] (Memory_region const & region) { + _boot_info().ram_regions.for_each([this] (Hw::Memory_region const & region) { _core_mem_alloc.phys_alloc()->add_range(region.base, region.size); }); _init_io_port_alloc(); diff --git a/repos/base-hw/src/core/platform_pd.cc b/repos/base-hw/src/core/platform_pd.cc index 813cb50580..0da0e87aff 100644 --- a/repos/base-hw/src/core/platform_pd.cc +++ b/repos/base-hw/src/core/platform_pd.cc @@ -17,11 +17,12 @@ #include /* core includes */ -#include +#include #include #include using namespace Genode; +using Hw::Page_table; /************************************** @@ -35,8 +36,8 @@ Core_mem_allocator * Hw::Address_space::_cma() { void * Hw::Address_space::_table_alloc() { void * ret; - if (!_cma()->alloc_aligned(sizeof(Translation_table), (void**)&ret, - Translation_table::ALIGNM_LOG2).ok()) + if (!_cma()->alloc_aligned(sizeof(Page_table), (void**)&ret, + Page_table::ALIGNM_LOG2).ok()) throw Root::Quota_exceeded(); return ret; } @@ -49,9 +50,9 @@ bool Hw::Address_space::insert_translation(addr_t virt, addr_t phys, for (;;) { try { Lock::Guard guard(_lock); - _tt->insert_translation(virt, phys, size, flags, _tt_alloc); + _tt.insert_translation(virt, phys, size, flags, _tt_alloc); return true; - } catch(Allocator::Out_of_memory) { + } catch(Hw::Out_of_tables &) { flush(platform()->vm_start(), platform()->vm_size()); } } @@ -67,27 +68,29 @@ void Hw::Address_space::flush(addr_t virt, size_t size) Lock::Guard guard(_lock); try { - assert(_tt); - _tt->remove_translation(virt, size, _tt_alloc); + _tt.remove_translation(virt, size, _tt_alloc); /* update translation caches */ - Kernel::update_pd(_kernel_pd); + Kernel::update_pd(&_kernel_pd); } catch(...) { error("tried to remove invalid region!"); } } -Hw::Address_space::Address_space(Kernel::Pd* pd, Translation_table * tt, - Translation_table_allocator * tt_alloc) -: _tt(tt), _tt_phys(tt), _tt_alloc(tt_alloc), _kernel_pd(pd) { +Hw::Address_space::Address_space(Kernel::Pd & pd, Page_table & tt, + Page_table::Allocator & tt_alloc) +: _tt(tt), _tt_phys(Platform::core_phys_addr((addr_t)&tt)), + _tt_alloc(tt_alloc), _kernel_pd(pd) { Kernel::mtc()->map(_tt, _tt_alloc); } -Hw::Address_space::Address_space(Kernel::Pd * pd) -: _tt(construct_at(_table_alloc())), - _tt_phys(reinterpret_cast(_cma()->phys_addr(_tt))), - _tt_alloc((new (_cma()) Table_allocator(_cma()))->alloc()), +Hw::Address_space::Address_space(Kernel::Pd & pd) +: _tt(*construct_at(_table_alloc())), + _tt_phys((addr_t)_cma()->phys_addr(&_tt)), + _tt_array(new (_cma()) Array([this] (void * virt) { + return (addr_t)_cma()->phys_addr(virt);})), + _tt_alloc(_tt_array->alloc()), _kernel_pd(pd) { Lock::Guard guard(_lock); @@ -98,8 +101,8 @@ Hw::Address_space::Address_space(Kernel::Pd * pd) Hw::Address_space::~Address_space() { flush(platform()->vm_start(), platform()->vm_size()); - destroy(_cma(), Table_allocator::base(_tt_alloc)); - destroy(_cma(), _tt); + destroy(_cma(), _tt_array); + destroy(_cma(), &_tt); } @@ -151,16 +154,16 @@ void Platform_pd::assign_parent(Native_capability parent) } -Platform_pd::Platform_pd(Translation_table * tt, - Translation_table_allocator * alloc) -: Hw::Address_space(kernel_object(), tt, alloc), - Kernel_object(false, tt, this), +Platform_pd::Platform_pd(Page_table & tt, + Page_table::Allocator & alloc) +: Hw::Address_space(*kernel_object(), tt, alloc), + Kernel_object(false, (Page_table*)translation_table_phys(), this), _label("core") { } Platform_pd::Platform_pd(Allocator * md_alloc, char const *label) -: Hw::Address_space(kernel_object()), - Kernel_object(true, translation_table_phys(), this), +: Hw::Address_space(*kernel_object()), + Kernel_object(true, (Page_table*)translation_table_phys(), this), _label(label) { if (!_cap.valid()) { @@ -183,9 +186,9 @@ Platform_pd::~Platform_pd() extern int _mt_master_context_begin; Core_platform_pd::Core_platform_pd() -: Platform_pd(Platform::core_translation_table(), - Platform::core_translation_table_allocator()) +: Platform_pd(Platform::core_page_table(), + Platform::core_page_table_allocator()) { Genode::construct_at(&_mt_master_context_begin, - translation_table_phys()); + (Page_table*)translation_table_phys()); } diff --git a/repos/base-hw/src/core/platform_thread.cc b/repos/base-hw/src/core/platform_thread.cc index 647140f6c8..297cb1afa0 100644 --- a/repos/base-hw/src/core/platform_thread.cc +++ b/repos/base-hw/src/core/platform_thread.cc @@ -13,7 +13,6 @@ */ /* core includes */ -#include #include #include #include @@ -145,7 +144,7 @@ int Platform_thread::start(void * const ip, void * const sp) _utcb_pd_addr = utcb_main_thread(); Hw::Address_space * as = static_cast(&*locked_ptr); if (!as->insert_translation((addr_t)_utcb_pd_addr, dsc->phys_addr(), - sizeof(Native_utcb), PAGE_FLAGS_UTCB)) { + sizeof(Native_utcb), Hw::PAGE_FLAGS_UTCB)) { error("failed to attach UTCB"); return -1; } @@ -176,7 +175,7 @@ int Platform_thread::start(void * const ip, void * const sp) utcb->cap_add(Capability_space::capid(_pd->parent())); utcb->cap_add(Capability_space::capid(_utcb)); } - Kernel::start_thread(kernel_object(), cpu, _pd->kernel_pd(), + Kernel::start_thread(kernel_object(), cpu, &_pd->kernel_pd(), _utcb_core_addr); return 0; } diff --git a/repos/base-hw/src/core/spec/arm/kernel/cpu.cc b/repos/base-hw/src/core/spec/arm/kernel/cpu.cc index 217bad0ace..e9926439d8 100644 --- a/repos/base-hw/src/core/spec/arm/kernel/cpu.cc +++ b/repos/base-hw/src/core/spec/arm/kernel/cpu.cc @@ -17,16 +17,9 @@ #include #include #include -#include void Kernel::Cpu::init(Kernel::Pic &pic) { - /* locally initialize interrupt controller */ - pic.init_cpu_local(); - - /* TrustZone initialization code */ - init_trustzone(pic); - /* enable performance counter */ perf_counter()->enable(); diff --git a/repos/base-hw/src/core/spec/arm/kernel/cpu_idle.cc b/repos/base-hw/src/core/spec/arm/kernel/cpu_idle.cc index b93ae7a158..dcead4b3de 100644 --- a/repos/base-hw/src/core/spec/arm/kernel/cpu_idle.cc +++ b/repos/base-hw/src/core/spec/arm/kernel/cpu_idle.cc @@ -13,7 +13,7 @@ */ /* core includes */ -#include +#include #include #include #include @@ -37,5 +37,5 @@ void Cpu_idle::exception(unsigned const cpu) case INTERRUPT_REQUEST: _interrupt(cpu); return; case FAST_INTERRUPT_REQUEST: _interrupt(cpu); return; case RESET: return; - default: assert(0); } + default: Genode::raw("Unknown exception in idle thread"); } } diff --git a/repos/base-hw/src/core/spec/arm/kernel/crt0.s b/repos/base-hw/src/core/spec/arm/kernel/crt0.s deleted file mode 100644 index 9cfe2b867c..0000000000 --- a/repos/base-hw/src/core/spec/arm/kernel/crt0.s +++ /dev/null @@ -1,39 +0,0 @@ -/* - * \brief Startup code for core - * \author Martin Stein - * \author Stefan Kalkowski - * \date 2011-10-01 - */ - -/* - * Copyright (C) 2011-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -/************ - ** Macros ** - ************/ - -/* core includes */ -.include "macros.s" - -.section ".text.crt0" - - /********************************** - ** Startup code for primary CPU ** - **********************************/ - - .global _start - _start: - - /* setup temporary stack pointer */ - _get_constraints_of_kernel_stacks r2, r3 - _init_kernel_sp r2, r3 - - /* kernel-initialization */ - bl init_kernel - - /* catch erroneous return of the kernel initialization routine */ - 1: b 1b diff --git a/repos/base-hw/src/core/spec/arm/kernel/pd.cc b/repos/base-hw/src/core/spec/arm/kernel/pd.cc index 881062b237..36c20e8b73 100644 --- a/repos/base-hw/src/core/spec/arm/kernel/pd.cc +++ b/repos/base-hw/src/core/spec/arm/kernel/pd.cc @@ -15,7 +15,7 @@ #include /* core includes */ -#include +#include #include using Asid_allocator = Genode::Bit_allocator<256>; @@ -24,7 +24,7 @@ static Asid_allocator &alloc() { return *unmanaged_singleton(); } -Kernel::Pd::Pd(Kernel::Pd::Table * const table, +Kernel::Pd::Pd(Hw::Page_table * const table, Genode::Platform_pd * const platform_pd) : Kernel::Cpu::Pd((Genode::uint8_t)alloc().alloc()), _table(table), _platform_pd(platform_pd) diff --git a/repos/base-hw/src/core/spec/arm/kernel/thread.cc b/repos/base-hw/src/core/spec/arm/kernel/thread.cc index 1d3b882fd2..3fbd979da3 100644 --- a/repos/base-hw/src/core/spec/arm/kernel/thread.cc +++ b/repos/base-hw/src/core/spec/arm/kernel/thread.cc @@ -12,8 +12,6 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* core includes */ -#include #include #include #include diff --git a/repos/base-hw/src/core/spec/arm_gic/pic.cc b/repos/base-hw/src/core/spec/arm_gic/pic.cc index b070758634..810f5c3a64 100644 --- a/repos/base-hw/src/core/spec/arm_gic/pic.cc +++ b/repos/base-hw/src/core/spec/arm_gic/pic.cc @@ -12,45 +12,14 @@ */ /* core includes */ +#include #include #include using namespace Genode; -void Pic::_init() -{ - /* disable device */ - _distr.write(0); - - /* configure every shared peripheral interrupt */ - for (unsigned i = min_spi; i <= _max_irq; i++) { - _distr.write(0, i); - _distr.write(0, i); - _distr.write(1, i); - } - /* enable device */ - _distr.write(1); -} - - -void Pic::init_cpu_local() -{ - /* disable the priority filter */ - _cpui.write(_distr.min_priority()); - - /* disable preemption of IRQ handling by other IRQs */ - _cpui.write(~0); - - /* enable device */ - _cpui.write(1); -} - - -Pic::Pic() +Hw::Pic::Pic() : _distr(Platform::mmio_to_virt(Board::IRQ_CONTROLLER_DISTR_BASE)), _cpui (Platform::mmio_to_virt(Board::IRQ_CONTROLLER_CPU_BASE)), - _last_iar(Cpui::Iar::Irq_id::bits(spurious_id)), - _max_irq(_distr.max_irq()) -{ - _init(); -} + _last_iar(Cpu_interface::Iar::Irq_id::bits(spurious_id)), + _max_irq(_distr.max_irq()) { } diff --git a/repos/base-hw/src/core/spec/arm_v6/cpu.cc b/repos/base-hw/src/core/spec/arm_v6/cpu.cc index 27f7a906a2..44b7866569 100644 --- a/repos/base-hw/src/core/spec/arm_v6/cpu.cc +++ b/repos/base-hw/src/core/spec/arm_v6/cpu.cc @@ -14,28 +14,6 @@ */ #include -#include -#include void Genode::Arm::clean_invalidate_data_cache() { asm volatile ("mcr p15, 0, %[rd], c7, c14, 0" :: [rd]"r"(0) : ); } - - -void Genode::Cpu::translation_added(Genode::addr_t const addr, - Genode::size_t const size) -{ - using namespace Kernel; - - /* - * The Cortex-A8 CPU can't use the L1 cache on page-table - * walks. Therefore, as the page-tables lie in write-back cacheable - * memory we've to clean the corresponding cache-lines even when a - * page table entry is added. We only do this as core as the kernel - * adds translations solely before MMU and caches are enabled. - */ - if (is_user()) update_data_region(addr, size); - else { - Cpu * const cpu = cpu_pool()->cpu(Cpu::executing_id()); - cpu->clean_invalidate_data_cache(); - } -} diff --git a/repos/base-hw/src/core/spec/arm_v6/mode_transition.s b/repos/base-hw/src/core/spec/arm_v6/mode_transition.s index c47df8c9f7..311caa7e3b 100644 --- a/repos/base-hw/src/core/spec/arm_v6/mode_transition.s +++ b/repos/base-hw/src/core/spec/arm_v6/mode_transition.s @@ -234,8 +234,3 @@ .p2align 2 .global _mt_end _mt_end: - - /* FIXME exists only because _vm_mon_entry pollutes generic kernel code */ - .global _mt_vm_entry_pic - _mt_vm_entry_pic: - 1: b 1b diff --git a/repos/base-hw/src/core/spec/arm_v7/trustzone/kernel/vm.cc b/repos/base-hw/src/core/spec/arm_v7/trustzone/kernel/vm.cc index 122add3412..ec5310d741 100644 --- a/repos/base-hw/src/core/spec/arm_v7/trustzone/kernel/vm.cc +++ b/repos/base-hw/src/core/spec/arm_v7/trustzone/kernel/vm.cc @@ -62,7 +62,7 @@ void Vm::proceed(unsigned const cpu) { unsigned const irq = _state->irq_injection; if (irq) { - if (secure_irq(irq)) { + if (pic()->secure(irq)) { Genode::warning("Refuse to inject secure IRQ into VM"); } else { pic()->trigger(irq); diff --git a/repos/base-hw/src/core/spec/arm_v7/trustzone/mode_transition.s b/repos/base-hw/src/core/spec/arm_v7/trustzone/mode_transition.s index 0a9f2e6d43..fdb29cb9bf 100644 --- a/repos/base-hw/src/core/spec/arm_v7/trustzone/mode_transition.s +++ b/repos/base-hw/src/core/spec/arm_v7/trustzone/mode_transition.s @@ -61,6 +61,30 @@ .section .text +/* + * On TrustZone exceptions the CPU has to jump to one of the following + * 7 entry vectors to switch to a kernel context. + */ +.p2align MIN_PAGE_SIZE_LOG2 +.global _mon_kernel_entry +_mon_kernel_entry: + b _mon_rst_entry /* reset */ + b _mon_und_entry /* undefined instruction */ + b _mon_svc_entry /* supervisor call */ + b _mon_pab_entry /* prefetch abort */ + b _mon_dab_entry /* data abort */ + nop /* reserved */ + b _mon_irq_entry /* interrupt request */ + _nonsecure_to_secure FIQ_TYPE, 4 /* fast interrupt request */ + + /* PICs that switch from a vm exception to the kernel */ + _mon_rst_entry: _nonsecure_to_secure RST_TYPE, 0 + _mon_und_entry: _nonsecure_to_secure UND_TYPE, 4 + _mon_svc_entry: _nonsecure_to_secure SVC_TYPE, 0 + _mon_pab_entry: _nonsecure_to_secure PAB_TYPE, 4 + _mon_dab_entry: _nonsecure_to_secure DAB_TYPE, 8 + _mon_irq_entry: _nonsecure_to_secure IRQ_TYPE, 4 + /* space for a copy of the kernel context */ .p2align 2 .global _tz_master_context @@ -98,28 +122,3 @@ _nonsecure_kernel_entry: .global _mt_nonsecure_entry_pic _mt_nonsecure_entry_pic: _secure_to_nonsecure - -/* - * On TrustZone exceptions the CPU has to jump to one of the following - * 7 entry vectors to switch to a kernel context. - */ -.p2align 5 -.global _mon_kernel_entry -_mon_kernel_entry: - b _mon_rst_entry /* reset */ - b _mon_und_entry /* undefined instruction */ - b _mon_svc_entry /* supervisor call */ - b _mon_pab_entry /* prefetch abort */ - b _mon_dab_entry /* data abort */ - nop /* reserved */ - b _mon_irq_entry /* interrupt request */ - _nonsecure_to_secure FIQ_TYPE, 4 /* fast interrupt request */ - - /* PICs that switch from a vm exception to the kernel */ - _mon_rst_entry: _nonsecure_to_secure RST_TYPE, 0 - _mon_und_entry: _nonsecure_to_secure UND_TYPE, 4 - _mon_svc_entry: _nonsecure_to_secure SVC_TYPE, 0 - _mon_pab_entry: _nonsecure_to_secure PAB_TYPE, 4 - _mon_dab_entry: _nonsecure_to_secure DAB_TYPE, 8 - _mon_irq_entry: _nonsecure_to_secure IRQ_TYPE, 4 - diff --git a/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/cpu_context.cc b/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/cpu_context.cc index 0586845649..595e2f4b3b 100644 --- a/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/cpu_context.cc +++ b/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/cpu_context.cc @@ -20,7 +20,7 @@ void Kernel::Cpu_context::_init(size_t const stack_size, addr_t const table) cpu_exception = Genode::Cpu::Ttbr0::init(table); protection_domain(0); translation_table(table); - sctlr = Cpu::Sctlr::init_value(); - ttbrc = Cpu::Ttbcr::init_virt_kernel(); - mair0 = Cpu::Mair0::init_virt_kernel(); + sctlr = 0x00003805; // FIXME + ttbrc = 0x80002500; // FIXME + mair0 = 0x04ff0444; // FIXME } diff --git a/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc b/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc index 0eb758c177..ae53370a03 100644 --- a/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc +++ b/repos/base-hw/src/core/spec/arm_v7/virtualization/kernel/vm.cc @@ -12,7 +12,8 @@ */ #include -#include +#include + #include #include diff --git a/repos/base-hw/src/core/spec/arm_v7/virtualization/vm_session_component.cc b/repos/base-hw/src/core/spec/arm_v7/virtualization/vm_session_component.cc index b85f17f539..c29320a68b 100644 --- a/repos/base-hw/src/core/spec/arm_v7/virtualization/vm_session_component.cc +++ b/repos/base-hw/src/core/spec/arm_v7/virtualization/vm_session_component.cc @@ -22,26 +22,29 @@ using namespace Genode; +static Core_mem_allocator * cma() { + return static_cast(platform()->core_mem_alloc()); } + void Vm_session_component::exception_handler(Signal_context_capability handler) { - Core_mem_allocator * cma = - static_cast(platform()->core_mem_alloc()); - if (!create((void*)_ds.core_local_addr(), Capability_space::capid(handler), - cma->phys_addr(_table))) + cma()->phys_addr(&_table))) Genode::warning("Cannot instantiate vm kernel object, invalid signal context?"); } void Vm_session_component::_attach(addr_t phys_addr, addr_t vm_addr, size_t size) { + using namespace Hw; + Page_flags pflags { RW, NO_EXEC, USER, NO_GLOBAL, RAM, CACHED }; try { - _table->insert_translation(vm_addr, phys_addr, size, pflags, _tt_alloc); + _table.insert_translation(vm_addr, phys_addr, size, pflags, + _table_array.alloc()); return; - } catch(Allocator::Out_of_memory) { + } catch(Hw::Out_of_tables &) { Genode::error("Translation table needs to much RAM"); } catch(...) { Genode::error("Invalid mapping ", Genode::Hex(phys_addr), " -> ", @@ -69,29 +72,32 @@ void Vm_session_component::attach_pic(addr_t vm_addr) void Vm_session_component::detach(addr_t vm_addr, size_t size) { - _table->remove_translation(vm_addr, size, _tt_alloc); } + _table.remove_translation(vm_addr, size, _table_array.alloc()); } + + + +void * Vm_session_component::_alloc_table() +{ + void * table; + /* get some aligned space for the translation table */ + if (!cma()->alloc_aligned(sizeof(Table), (void**)&table, + Table::ALIGNM_LOG2).ok()) { + error("failed to allocate kernel object"); + throw Root::Quota_exceeded(); + } + return table; +} Vm_session_component::Vm_session_component(Rpc_entrypoint *ds_ep, size_t ram_quota) : _ds_ep(ds_ep), _ds(_ds_size(), _alloc_ds(ram_quota), UNCACHED, true, 0), - _ds_cap(static_cap_cast(_ds_ep->manage(&_ds))) + _ds_cap(static_cap_cast(_ds_ep->manage(&_ds))), + _table(*construct_at
(_alloc_table())), + _table_array(*(new (cma()) Array([this] (void * virt) { + return (addr_t)cma()->phys_addr(virt);}))) { _ds.assign_core_local_addr(core_env()->rm_session()->attach(_ds_cap)); - - Core_mem_allocator * cma = - static_cast(platform()->core_mem_alloc()); - void *tt; - - /* get some aligned space for the translation table */ - if (!cma->alloc_aligned(sizeof(Translation_table), (void**)&tt, - Translation_table::ALIGNM_LOG2).ok()) { - error("failed to allocate kernel object"); - throw Root::Quota_exceeded(); - } - - _table = construct_at(tt); - _tt_alloc = (new (cma) Table_allocator(cma))->alloc(); } @@ -105,6 +111,6 @@ Vm_session_component::~Vm_session_component() platform()->ram_alloc()->free((void*)_ds.phys_addr()); /* free guest-to-host page tables */ - destroy(platform()->core_mem_alloc(), _table); - destroy(platform()->core_mem_alloc(), Table_allocator::base(_tt_alloc)); + destroy(platform()->core_mem_alloc(), &_table); + destroy(platform()->core_mem_alloc(), &_table_array); } diff --git a/repos/base-hw/src/core/spec/arndale/pic.cc b/repos/base-hw/src/core/spec/arndale/pic.cc deleted file mode 100644 index bd969dba87..0000000000 --- a/repos/base-hw/src/core/spec/arndale/pic.cc +++ /dev/null @@ -1,71 +0,0 @@ -/* - * \brief Programmable interrupt controller for core - * \author Stefan Kalkowski - * \date 2012-10-24 - */ - -/* - * Copyright (C) 2012-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -/* core includes */ -#include -#include - -using namespace Genode; - -void Pic::_init() -{ - /* disable device */ - _distr.write(0); - - /* configure every shared peripheral interrupt */ - for (unsigned i = min_spi; i <= _max_irq; i++) { - /* mark as non-secure */ - _distr.write(1, i); - _distr.write(0, i); - _distr.write(0, i); - _distr.write(1, i); - } - /* enable device */ - Distr::Ctlr::access_t v = 0; - Distr::Ctlr::Enable_grp0::set(v, 1); - Distr::Ctlr::Enable_grp1::set(v, 1); - _distr.write(v); -} - - -void Pic::init_cpu_local() -{ - _cpui.write(0); - - /* mark software-generated IRQs as being non-secure */ - for (unsigned i = 0; i < min_spi; i++) - _distr.write(1, i); - - /* disable the priority filter */ - _cpui.write(_distr.min_priority()); - - /* disable preemption of IRQ handling by other IRQs */ - _cpui.write(~0); - - /* enable device */ - Cpui::Ctlr::access_t v = 0; - Cpui::Ctlr::Enable_grp0::set(v, 1); - Cpui::Ctlr::Enable_grp1::set(v, 1); - Cpui::Ctlr::Fiq_en::set(v, 1); - _cpui.write(v); -} - - -Pic::Pic() -: _distr(Platform::mmio_to_virt(Board::IRQ_CONTROLLER_DISTR_BASE)), - _cpui (Platform::mmio_to_virt(Board::IRQ_CONTROLLER_CPU_BASE)), - _last_iar(Cpui::Iar::Irq_id::bits(spurious_id)), - _max_irq(_distr.max_irq()) -{ - _init(); -} diff --git a/repos/base-hw/src/core/spec/arndale/platform_services.cc b/repos/base-hw/src/core/spec/arndale/platform_services.cc index b88722ee14..4ce0a0f533 100644 --- a/repos/base-hw/src/core/spec/arndale/platform_services.cc +++ b/repos/base-hw/src/core/spec/arndale/platform_services.cc @@ -37,7 +37,8 @@ void Genode::platform_add_local_services(Rpc_entrypoint *ep, /* initialize host context used in virtualization world switch */ *((void**)&_vt_host_context_ptr) = &_mt_master_context_begin; - map_local(Platform::core_phys_addr((addr_t)&_vt_host_entry), 0xfff00000, 1, PAGE_FLAGS_KERN_TEXT); + map_local(Platform::core_phys_addr((addr_t)&_vt_host_entry), + 0xfff00000, 1, Hw::PAGE_FLAGS_KERN_TEXT); static Vm_root vm_root(ep, sh); static Core_service vm_service(*services, vm_root); diff --git a/repos/base-hw/src/core/spec/cortex_a9/kernel/cpu.cc b/repos/base-hw/src/core/spec/cortex_a9/kernel/cpu.cc index c8e181606c..c436f9f49e 100644 --- a/repos/base-hw/src/core/spec/cortex_a9/kernel/cpu.cc +++ b/repos/base-hw/src/core/spec/cortex_a9/kernel/cpu.cc @@ -17,6 +17,7 @@ #include #include #include +#include extern int _mt_begin; extern int _mt_master_context_begin; @@ -24,11 +25,11 @@ extern int _mt_master_context_begin; void Kernel::Cpu::init(Kernel::Pic &pic) { - pic.init_cpu_local(); + Cpu_context * c = (Cpu_context*) + (Cpu::exception_entry + ((addr_t)&_mt_master_context_begin - + (addr_t)&_mt_begin)); + c->cpu_exception = Genode::Cpu::Ttbr0::read(); - static Hw::Address_space invalid_space(nullptr); - Cpu_context * c = (Cpu_context*) (Cpu::exception_entry + ((addr_t)&_mt_master_context_begin - (addr_t)&_mt_begin)); - c->cpu_exception = Genode::Cpu::Ttbr0::init((addr_t)invalid_space.translation_table_phys()); _fpu.init(); { diff --git a/repos/base-hw/src/core/spec/imx53/pic.cc b/repos/base-hw/src/core/spec/imx53/pic.cc index 694d5e6286..0e54051ae1 100644 --- a/repos/base-hw/src/core/spec/imx53/pic.cc +++ b/repos/base-hw/src/core/spec/imx53/pic.cc @@ -12,15 +12,10 @@ */ /* core includes */ +#include #include #include using namespace Genode; -Pic::Pic() : Mmio(Platform::mmio_to_virt(Board::IRQ_CONTROLLER_BASE)) { } - -void Pic::_init_security_ext() { } - -void Pic::unsecure(unsigned) { } - -void Pic::secure(unsigned) { } +Hw::Pic::Pic() : Mmio(Platform::mmio_to_virt(Board::IRQ_CONTROLLER_BASE)) { } diff --git a/repos/base-hw/src/core/spec/imx53/trustzone/pic.cc b/repos/base-hw/src/core/spec/imx53/trustzone/pic.cc deleted file mode 100644 index 5629fd526b..0000000000 --- a/repos/base-hw/src/core/spec/imx53/trustzone/pic.cc +++ /dev/null @@ -1,45 +0,0 @@ -/* - * \brief Programmable interrupt controller for core - * \author Stefan Kalkowski - * \date 2012-10-24 - */ - -/* - * Copyright (C) 2012-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -/* core includes */ -#include -#include - -using namespace Genode; - -Pic::Pic() : Mmio(Platform::mmio_to_virt(Board::IRQ_CONTROLLER_BASE)) { } - - -void Pic::_init_security_ext() -{ - for (unsigned i = 0; i < NR_OF_IRQ; i++) { secure(i); } - write(0xff); -} - - -void Pic::unsecure(unsigned const i) -{ - if (i < NR_OF_IRQ) { - write(1, i); - write(0x80, i); - } -} - - -void Pic::secure(unsigned const i) -{ - if (i < NR_OF_IRQ) { - write(0, i); - write(0, i); - } -} diff --git a/repos/base-hw/src/core/spec/imx53/trustzone/platform_services.cc b/repos/base-hw/src/core/spec/imx53/trustzone/platform_services.cc index ca4f00c696..a5a0e295be 100644 --- a/repos/base-hw/src/core/spec/imx53/trustzone/platform_services.cc +++ b/repos/base-hw/src/core/spec/imx53/trustzone/platform_services.cc @@ -20,7 +20,9 @@ #include #include #include +#include +extern int _mon_kernel_entry; /* * Add TrustZone specific vm service @@ -29,6 +31,9 @@ void Genode::platform_add_local_services(Rpc_entrypoint *ep, Sliced_heap *sliced_heap, Registry *local_services) { + static addr_t const phys_base = + Platform::core_phys_addr((addr_t)&_mon_kernel_entry); + map_local(phys_base, 0xfff00000, 1); // FIXME static Vm_root vm_root(ep, sliced_heap); static Core_service vm_service(*local_services, vm_root); } diff --git a/repos/base-hw/src/core/spec/imx53/trustzone/platform_support.cc b/repos/base-hw/src/core/spec/imx53/trustzone/platform_support.cc index e75365eec1..712d51fe5e 100644 --- a/repos/base-hw/src/core/spec/imx53/trustzone/platform_support.cc +++ b/repos/base-hw/src/core/spec/imx53/trustzone/platform_support.cc @@ -11,57 +11,9 @@ * under the terms of the GNU Affero General Public License version 3. */ -#include - /* core includes */ -#include -#include -#include #include -#include -#include - -#include using namespace Genode; -/* monitor exception vector address */ -extern int _mon_kernel_entry; - -bool secure_irq(unsigned const i) -{ - using namespace Csu_config; - if (i == Board::EPIT_1_IRQ) return true; - if (i == Board::EPIT_2_IRQ) return true; - if (i == Board::I2C_2_IRQ) return SECURE_I2C; - if (i == Board::I2C_3_IRQ) return SECURE_I2C; - if (i == Board::SDHC_IRQ) return SECURE_ESDHC; - if (i >= Board::GPIO1_IRQL && i <= Board::GPIO4_IRQH) return SECURE_GPIO; - if (i >= Board::GPIO5_IRQL && i <= Board::GPIO7_IRQH) return SECURE_GPIO; - return false; -} - - -void Kernel::init_trustzone(Pic & pic) -{ - using namespace Genode; - - /* set exception vector entry */ - Cpu::mon_exception_entry_at((Genode::addr_t)&_mon_kernel_entry); - - /* enable coprocessor 10 + 11 access for TZ VMs */ - Cpu::Nsacr::access_t v = 0; - Cpu::Nsacr::Cpnsae10::set(v, 1); - Cpu::Nsacr::Cpnsae11::set(v, 1); - Cpu::Nsacr::write(v); - - /* configure non-secure interrupts */ - for (unsigned i = 0; i < Pic::NR_OF_IRQ; i++) { - if (!secure_irq(i)) { pic.unsecure(i); } } - - /* configure central security unit */ - Genode::Csu csu(Board::CSU_BASE); -} - - Cpu::User_context::User_context() { cpsr = Psr::init_user_with_trustzone(); } diff --git a/repos/base-hw/src/core/spec/riscv/cpu.cc b/repos/base-hw/src/core/spec/riscv/cpu.cc deleted file mode 100644 index c7366c913c..0000000000 --- a/repos/base-hw/src/core/spec/riscv/cpu.cc +++ /dev/null @@ -1,26 +0,0 @@ -/* - * \brief CPU core implementation - * \author Sebastian Sumpf - * \date 2016-02-10 - */ - -/* - * Copyright (C) 2016-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -/* Genode includes */ -#include - -/* Core includes */ -#include -#include - -void Genode::Cpu::translation_added(addr_t const addr, size_t const size) -{ - if (Machine::is_user_mode()) - Kernel::update_data_region(addr, size); - else Genode::Cpu::sfence(); -} diff --git a/repos/base-hw/src/core/spec/riscv/kernel/cpu.cc b/repos/base-hw/src/core/spec/riscv/kernel/cpu.cc index 1b2d4f521a..d65c2028ac 100644 --- a/repos/base-hw/src/core/spec/riscv/kernel/cpu.cc +++ b/repos/base-hw/src/core/spec/riscv/kernel/cpu.cc @@ -12,7 +12,7 @@ */ /* core includes */ -#include +#include #include #include @@ -51,5 +51,5 @@ void Cpu_idle::exception(unsigned const cpu) return; } else if (cpu_exception == RESET) return; - assert(0); + ASSERT_NEVER_CALLED; } diff --git a/repos/base-hw/src/core/spec/riscv/kernel/crt0.s b/repos/base-hw/src/core/spec/riscv/kernel/crt0.s deleted file mode 100644 index aa6142cca4..0000000000 --- a/repos/base-hw/src/core/spec/riscv/kernel/crt0.s +++ /dev/null @@ -1,24 +0,0 @@ -/** - * \brief Kernel startup code - * \author Sebastian Sumpf - * \date 2015-06-010 - */ - -/* - * Copyright (C) 2015-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -.section ".text.crt0" - -.global _start -_start: - -la sp, kernel_stack -la a0, kernel_stack_size -ld a0, (a0) -add sp, sp, a0 - -jal init_kernel diff --git a/repos/base-hw/src/core/spec/riscv/kernel/pd.cc b/repos/base-hw/src/core/spec/riscv/kernel/pd.cc index 3c8f7d9782..2477f0eb53 100644 --- a/repos/base-hw/src/core/spec/riscv/kernel/pd.cc +++ b/repos/base-hw/src/core/spec/riscv/kernel/pd.cc @@ -11,18 +11,18 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* core includes */ -#include +#include + #include #include using Asid_allocator = Genode::Bit_allocator<256>; -static Asid_allocator &alloc() { +static Asid_allocator & alloc() { return *unmanaged_singleton(); } -Kernel::Pd::Pd(Kernel::Pd::Table * const table, +Kernel::Pd::Pd(Hw::Page_table * const table, Genode::Platform_pd * const platform_pd) : Kernel::Cpu::Pd((Genode::uint8_t)alloc().alloc()), _table(table), _platform_pd(platform_pd) diff --git a/repos/base-hw/src/core/spec/x86_64/kernel/cpu_exception.cc b/repos/base-hw/src/core/spec/x86_64/kernel/cpu_exception.cc index d75dd8995b..94b867488e 100644 --- a/repos/base-hw/src/core/spec/x86_64/kernel/cpu_exception.cc +++ b/repos/base-hw/src/core/spec/x86_64/kernel/cpu_exception.cc @@ -12,7 +12,7 @@ * under the terms of the GNU Affero General Public License version 3. */ -#include +#include #include void Kernel::Cpu_idle::exception(unsigned const cpu) @@ -26,5 +26,6 @@ void Kernel::Cpu_idle::exception(unsigned const cpu) Genode::warning("Unknown exception ", trapno, " with error code ", errcode, " at ip=", (void *)ip); - assert(0); + + ASSERT_NEVER_CALLED; } diff --git a/repos/base-hw/src/core/spec/x86_64/kernel/crt0.s b/repos/base-hw/src/core/spec/x86_64/kernel/crt0.s deleted file mode 100644 index 94de49d2cd..0000000000 --- a/repos/base-hw/src/core/spec/x86_64/kernel/crt0.s +++ /dev/null @@ -1,52 +0,0 @@ -/* - * \brief Startup code for kernel - * \author Adrian-Ken Rueegsegger - * \author Martin Stein - * \author Reto Buerki - * \author Stefan Kalkowski - * \date 2015-02-06 - */ - -/* - * Copyright (C) 2011-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -.include "macros.s" - -.section ".text.crt0" - -.global _start -_start: - /* - * Install initial temporary environment that is replaced later by the - * environment that init_main_thread creates. - */ - leaq _stack_high@GOTPCREL(%rip),%rax - movq (%rax), %rsp - - movq __initial_bx@GOTPCREL(%rip),%rax - movq %rbx, (%rax) - - /* kernel-initialization */ - call init_kernel - - /* catch erroneous return of the kernel initialization */ - 1: jmp 1b - - -/********************************* - ** .bss (non-initialized data) ** - *********************************/ - -.bss - - /* stack of the temporary initial environment */ - .p2align 8 - .space 32 * 1024 - _stack_high: - .globl __initial_bx - __initial_bx: - .space 8 diff --git a/repos/base-hw/src/core/spec/x86_64/kernel/pd.cc b/repos/base-hw/src/core/spec/x86_64/kernel/pd.cc index 7c7c42542c..cf7946a80c 100644 --- a/repos/base-hw/src/core/spec/x86_64/kernel/pd.cc +++ b/repos/base-hw/src/core/spec/x86_64/kernel/pd.cc @@ -12,10 +12,11 @@ */ /* core includes */ +#include #include #include -Kernel::Pd::Pd(Kernel::Pd::Table * const table, +Kernel::Pd::Pd(Hw::Page_table * const table, Genode::Platform_pd * const platform_pd) : _table(table), _platform_pd(platform_pd) { diff --git a/repos/base-hw/src/core/spec/x86_64/muen/kernel/cpu_exception.cc b/repos/base-hw/src/core/spec/x86_64/muen/kernel/cpu_exception.cc index 4122264a7d..552244e31f 100644 --- a/repos/base-hw/src/core/spec/x86_64/muen/kernel/cpu_exception.cc +++ b/repos/base-hw/src/core/spec/x86_64/muen/kernel/cpu_exception.cc @@ -12,7 +12,7 @@ * under the terms of the GNU Affero General Public License version 3. */ -#include +#include #include void Kernel::Cpu_idle::exception(unsigned const cpu) @@ -27,5 +27,6 @@ void Kernel::Cpu_idle::exception(unsigned const cpu) Genode::warning("Unknown exception ", trapno, " with error code ", errcode, " at ip=", (void *)ip); - assert(0); + + ASSERT_NEVER_CALLED; } diff --git a/repos/base-hw/src/core/spec/x86_64/muen/kernel/vm.cc b/repos/base-hw/src/core/spec/x86_64/muen/kernel/vm.cc index 251745365c..b9d0a0c8cf 100644 --- a/repos/base-hw/src/core/spec/x86_64/muen/kernel/vm.cc +++ b/repos/base-hw/src/core/spec/x86_64/muen/kernel/vm.cc @@ -13,6 +13,7 @@ * under the terms of the GNU Affero General Public License version 3. */ +#include #include #include #include @@ -52,7 +53,8 @@ void Kernel::Vm::exception(unsigned const cpu_id) } Genode::warning("VM: triggered unknown exception ", _state->trapno, " with error code ", _state->errcode); - assert(false); + + ASSERT_NEVER_CALLED; } diff --git a/repos/base-hw/src/core/spec/x86_64/pic.cc b/repos/base-hw/src/core/spec/x86_64/pic.cc index 8e096ea264..8d24c240fb 100644 --- a/repos/base-hw/src/core/spec/x86_64/pic.cc +++ b/repos/base-hw/src/core/spec/x86_64/pic.cc @@ -14,6 +14,7 @@ /* Genode includes */ #include +#include /* core includes */ #include @@ -29,7 +30,7 @@ enum { PIC_DATA_SLAVE = 0xa1, }; -Pic::Pic() : Mmio(Platform::mmio_to_virt(Board::MMIO_LAPIC_BASE)) +Pic::Pic() : Mmio(Platform::mmio_to_virt(Hw::Cpu_memory_map::MMIO_LAPIC_BASE)) { /* Start initialization sequence in cascade mode */ outb(PIC_CMD_MASTER, 0x11); @@ -167,7 +168,7 @@ Irte::access_t Ioapic::_create_irt_entry(unsigned const irq) } -Ioapic::Ioapic() : Mmio(Platform::mmio_to_virt(Board::MMIO_IOAPIC_BASE)) +Ioapic::Ioapic() : Mmio(Platform::mmio_to_virt(Hw::Cpu_memory_map::MMIO_IOAPIC_BASE)) { for (unsigned i = 0; i < IRQ_COUNT; i++) { diff --git a/repos/base-hw/src/core/spec/x86_64/timer.cc b/repos/base-hw/src/core/spec/x86_64/timer.cc index 74ae1eeed3..6c71dc1039 100644 --- a/repos/base-hw/src/core/spec/x86_64/timer.cc +++ b/repos/base-hw/src/core/spec/x86_64/timer.cc @@ -12,6 +12,8 @@ * under the terms of the GNU Affero General Public License version 3. */ +#include + /* core includes */ #include #include @@ -46,7 +48,7 @@ uint32_t Timer::_pit_calc_timer_freq(void) } -Timer::Timer() : Mmio(Platform::mmio_to_virt(Board::MMIO_LAPIC_BASE)) +Timer::Timer() : Mmio(Platform::mmio_to_virt(Hw::Cpu_memory_map::MMIO_LAPIC_BASE)) { write( Divide_configuration::Divide_value::MAX); diff --git a/repos/base-hw/src/core/include/array.h b/repos/base-hw/src/lib/hw/array.h similarity index 78% rename from repos/base-hw/src/core/include/array.h rename to repos/base-hw/src/lib/hw/array.h index b2707a741c..e8bc9d1bad 100644 --- a/repos/base-hw/src/core/include/array.h +++ b/repos/base-hw/src/lib/hw/array.h @@ -1,5 +1,5 @@ /* - * \brief Array helper class + * \brief Array class with static size * \author Stefan Kalkowski * \date 2016-09-30 */ @@ -11,16 +11,16 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _ARRAY_H_ -#define _ARRAY_H_ +#ifndef _SRC__LIB__HW__ARRAY_H_ +#define _SRC__LIB__HW__ARRAY_H_ #include -namespace Genode { template class Array; } +namespace Hw { template class Array; } template -class Genode::Array +class Hw::Array { private: @@ -49,7 +49,7 @@ class Genode::Array void add(T const & obj) { - if (_count == MAX) error("Array too small!"); + if (_count == MAX) Genode::error("Array too small!"); else _objs[_count++] = obj; } @@ -60,4 +60,4 @@ class Genode::Array unsigned count() const { return _count; } }; -#endif /* _ARRAY_H_ */ +#endif /* _SRC__LIB__HW__ARRAY_H_ */ diff --git a/repos/base-hw/src/core/include/assert.h b/repos/base-hw/src/lib/hw/assert.h similarity index 71% rename from repos/base-hw/src/core/include/assert.h rename to repos/base-hw/src/lib/hw/assert.h index c7290f91d3..6c3e02b887 100644 --- a/repos/base-hw/src/core/include/assert.h +++ b/repos/base-hw/src/lib/hw/assert.h @@ -1,6 +1,7 @@ /* * \brief Assertion macro * \author Martin Stein + * \author Stefan Kalkowski * \date 2012-04-04 */ @@ -11,20 +12,19 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _CORE__INCLUDE__ASSERT_H_ -#define _CORE__INCLUDE__ASSERT_H_ +#ifndef _SRC__LIB__HW__ASSERT_H_ +#define _SRC__LIB__HW__ASSERT_H_ /* Genode includes */ #include +#ifdef GENODE_RELEASE + /** * Suppress assertions in release version */ -#ifdef GENODE_RELEASE -#define DO_ASSERT false +#define assert(expression) #else -#define DO_ASSERT true -#endif /* GENODE_RELEASE */ /** * Make an assertion @@ -41,14 +41,15 @@ */ #define assert(expression) \ do { \ - if (DO_ASSERT) { \ - if (!(expression)) { \ - Genode::error("Assertion failed: "#expression""); \ - Genode::error(" File: ", __FILE__, ":", __LINE__); \ - Genode::error(" Function: ", __PRETTY_FUNCTION__); \ - while (1) ; \ - } \ + if (!(expression)) { \ + Genode::error("Assertion failed: "#expression""); \ + Genode::error(" File: ", __FILE__, ":", __LINE__); \ + Genode::error(" Function: ", __PRETTY_FUNCTION__); \ + while (1) ; \ } \ } while (0) ; -#endif /* _CORE__INCLUDE__ASSERT_H_ */ +#endif /* GENODE_RELEASE */ + + +#endif /* _SRC__LIB__HW__ASSERT_H_ */ diff --git a/repos/base-hw/src/lib/hw/boot_info.h b/repos/base-hw/src/lib/hw/boot_info.h new file mode 100644 index 0000000000..c0223d859d --- /dev/null +++ b/repos/base-hw/src/lib/hw/boot_info.h @@ -0,0 +1,39 @@ +/* + * \brief Boot information + * \author Stefan Kalkowski + * \date 2016-10-26 + */ + +/* + * Copyright (C) 2016-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__LIB__HW__BOOT_INFO_H_ +#define _SRC__LIB__HW__BOOT_INFO_H_ + +#include + +namespace Hw { struct Boot_info; } + +struct Hw::Boot_info +{ + using Mapping_pool = Array; + + addr_t const table; + addr_t const table_allocator; + Mapping_pool const elf_mappings; + Mmio_space const mmio_space; + Memory_region_array ram_regions; + + Boot_info(addr_t const table, + addr_t const table_alloc, + Mapping_pool const elf_mappings, + Mmio_space const mmio_space) + : table(table), table_allocator(table_alloc), + elf_mappings(elf_mappings), mmio_space(mmio_space) {} +}; + +#endif /* _SRC__LIB__HW__BOOT_INFO_H_ */ diff --git a/repos/base-hw/src/lib/hw/capability.cc b/repos/base-hw/src/lib/hw/capability.cc new file mode 100644 index 0000000000..a7dc3f3a63 --- /dev/null +++ b/repos/base-hw/src/lib/hw/capability.cc @@ -0,0 +1,34 @@ +/* + * \brief Dummy implementation of Native_capability + * \author Stefan Kalkowski + * \date 2015-05-20 + */ + +/* + * Copyright (C) 2015-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#include + +Genode::Native_capability::Native_capability() { } + + +void Genode::Native_capability::_inc() { } + + +void Genode::Native_capability::_dec() { } + + +long Genode::Native_capability::local_name() const { + return (long)_data; } + + +bool Genode::Native_capability::valid() const { + return (Genode::addr_t)_data != Kernel::cap_id_invalid(); } + + +Genode::Native_capability::Raw Genode::Native_capability::raw() const { + return { 0, 0, 0, 0 }; } diff --git a/repos/base-hw/src/lib/hw/mapping.h b/repos/base-hw/src/lib/hw/mapping.h new file mode 100644 index 0000000000..2b0dea4b5a --- /dev/null +++ b/repos/base-hw/src/lib/hw/mapping.h @@ -0,0 +1,51 @@ +/* + * \brief Representation of physical to virtual memory mappings + * \author Stefan Kalkowski + * \date 2016-11-03 + */ + +/* + * Copyright (C) 2016-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__LIB__HW__MAPPING_H_ +#define _SRC__LIB__HW__MAPPING_H_ + +#include +#include + +namespace Hw { class Mapping; } + +class Hw::Mapping +{ + protected: + + Memory_region _phys { 0, 0 }; + addr_t _virt = 0; + Page_flags _flags { RO, NO_EXEC, KERN, NO_GLOBAL, + RAM, Genode::CACHED }; + + public: + + Mapping() {} + + Mapping(addr_t phys, addr_t virt, size_t size, Page_flags flags) + : _phys(phys, size), _virt(virt), _flags(flags) {} + + void print(Genode::Output & out) const + { + Genode::print(out, "physical region(", _phys, ")", + " => virtual address=", (void*) _virt, + " with page-flags: ", _flags, ")"); + } + + addr_t phys() const { return _phys.base; } + addr_t virt() const { return _virt; } + size_t size() const { return _phys.size; } + Page_flags flags() const { return _flags; } +}; + +#endif /* _SRC__LIB__HW__MAPPING_H_ */ diff --git a/repos/base-hw/src/core/include/memory_region.h b/repos/base-hw/src/lib/hw/memory_region.h similarity index 50% rename from repos/base-hw/src/core/include/memory_region.h rename to repos/base-hw/src/lib/hw/memory_region.h index b88f59b864..4196e3a5d3 100644 --- a/repos/base-hw/src/core/include/memory_region.h +++ b/repos/base-hw/src/lib/hw/memory_region.h @@ -11,37 +11,36 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _MEMORY_REGION_H_ -#define _MEMORY_REGION_H_ +#ifndef _SRC__LIB__HW__MEMORY_REGION_H_ +#define _SRC__LIB__HW__MEMORY_REGION_H_ #include -#include -#include +#include +#include -namespace Genode { +namespace Hw { struct Memory_region; - using Memory_region_array = Array; } -struct Genode::Memory_region +struct Hw::Memory_region { - addr_t base = 0; - size_t size = 0; + Genode::addr_t base = 0; + Genode::size_t size = 0; - Memory_region(addr_t base, size_t size) + Memory_region(Genode::addr_t base, Genode::size_t size) : base(trunc(base, get_page_size_log2())), size(round(size, get_page_size_log2())) {} Memory_region() {} - addr_t end() const { return base + size; } + Genode::addr_t end() const { return base + size; } - void print(Output & out) const + void print(Genode::Output & out) const { - Genode::print(out, "base=", (void*)base, - " size=", Hex(size, Hex::PREFIX)); + Genode::print(out, "base=", (void*)base, " size=", + Genode::Hex(size, Genode::Hex::PREFIX)); } }; -#endif /* _MEMORY_REGION_H_ */ +#endif /* _SRC__LIB__HW__MEMORY_REGION_H_ */ diff --git a/repos/base-hw/src/core/include/core_mmio.h b/repos/base-hw/src/lib/hw/mmio_space.h similarity index 66% rename from repos/base-hw/src/core/include/core_mmio.h rename to repos/base-hw/src/lib/hw/mmio_space.h index 1c55fe0912..19541a55c0 100644 --- a/repos/base-hw/src/core/include/core_mmio.h +++ b/repos/base-hw/src/lib/hw/mmio_space.h @@ -1,5 +1,5 @@ /* - * \brief Representation of core's MMIO space + * \brief Representation of MMIO space * \author Stefan Kalkowski * \date 2016-11-24 */ @@ -11,20 +11,18 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _CORE_MMIO_H_ -#define _CORE_MMIO_H_ +#ifndef _SRC__LIB__HW__MMIO_SPACE_H_ +#define _SRC__LIB__HW__MMIO_SPACE_H_ -#include -#include -#include +#include +#include +#include -namespace Genode { struct Core_mmio; } +namespace Hw { struct Mmio_space; } -struct Genode::Core_mmio : Genode::Memory_region_array +struct Hw::Mmio_space : Hw::Memory_region_array { - using Memory_region_array::Memory_region_array; - - struct Not_found {}; + using Hw::Memory_region_array::Memory_region_array; template void for_each_mapping(FUNC f) const @@ -40,7 +38,7 @@ struct Genode::Core_mmio : Genode::Memory_region_array addr_t virt_addr(addr_t phys_addr) const { /* - * Sadly this method is used quite early in the kernel + * Sadly this method is used quite early during bootstrap * where no exceptions can be used */ addr_t ret = 0; @@ -54,4 +52,4 @@ struct Genode::Core_mmio : Genode::Memory_region_array } }; -#endif /* _CORE_MMIO_H_ */ +#endif /* _SRC__LIB__HW__MMIO_SPACE_H_ */ diff --git a/repos/base-hw/src/core/include/page_flags.h b/repos/base-hw/src/lib/hw/page_flags.h similarity index 64% rename from repos/base-hw/src/core/include/page_flags.h rename to repos/base-hw/src/lib/hw/page_flags.h index b7d303866b..9c8f1c5a0a 100644 --- a/repos/base-hw/src/core/include/page_flags.h +++ b/repos/base-hw/src/lib/hw/page_flags.h @@ -11,13 +11,13 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _CORE__INCLUDE__PAGE_FLAGS_H_ -#define _CORE__INCLUDE__PAGE_FLAGS_H_ +#ifndef _SRC__LIB__HW__PAGE_FLAGS_H_ +#define _SRC__LIB__HW__PAGE_FLAGS_H_ #include #include -namespace Genode { +namespace Hw { enum Writeable { RO, RW }; enum Executeable { NO_EXEC, EXEC }; @@ -28,18 +28,19 @@ namespace Genode { struct Page_flags; } -struct Genode::Page_flags +struct Hw::Page_flags { - Writeable writeable; - Executeable executable; - Privileged privileged; - Global global; - Type type; - Cache_attribute cacheable; + Writeable writeable; + Executeable executable; + Privileged privileged; + Global global; + Type type; + Genode::Cache_attribute cacheable; - void print(Output & out) const + void print(Genode::Output & out) const { using Genode::print; + using namespace Genode; print(out, (writeable == RW) ? "writeable, " : "readonly, ", (executable ==EXEC) ? "exec, " : "noexec, "); @@ -55,17 +56,17 @@ struct Genode::Page_flags }; -namespace Genode { +namespace Hw { static constexpr Page_flags PAGE_FLAGS_KERN_IO - { RW, NO_EXEC, USER, NO_GLOBAL, DEVICE, UNCACHED }; + { RW, NO_EXEC, USER, NO_GLOBAL, DEVICE, Genode::UNCACHED }; static constexpr Page_flags PAGE_FLAGS_KERN_DATA - { RW, EXEC, USER, NO_GLOBAL, RAM, CACHED }; + { RW, EXEC, USER, NO_GLOBAL, RAM, Genode::CACHED }; static constexpr Page_flags PAGE_FLAGS_KERN_TEXT - { RW, EXEC, USER, NO_GLOBAL, RAM, CACHED }; + { RW, EXEC, USER, NO_GLOBAL, RAM, Genode::CACHED }; static constexpr Page_flags PAGE_FLAGS_KERN_EXCEP - { RW, EXEC, USER, GLOBAL, RAM, CACHED }; + { RW, EXEC, USER, GLOBAL, RAM, Genode::CACHED }; static constexpr Page_flags PAGE_FLAGS_UTCB - { RW, NO_EXEC, USER, NO_GLOBAL, RAM, CACHED }; + { RW, NO_EXEC, USER, NO_GLOBAL, RAM, Genode::CACHED }; } -#endif /* _CORE__INCLUDE__PAGE_FLAGS_H_ */ +#endif /* _SRC__LIB__HW__PAGE_FLAGS_H_ */ diff --git a/repos/base-hw/src/lib/hw/page_table_allocator.h b/repos/base-hw/src/lib/hw/page_table_allocator.h new file mode 100644 index 0000000000..e5af15486d --- /dev/null +++ b/repos/base-hw/src/lib/hw/page_table_allocator.h @@ -0,0 +1,134 @@ +/* + * \brief Page table allocator + * \author Stefan Kalkowski + * \date 2015-06-10 + */ + +/* + * Copyright (C) 2015-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__LIB__HW__PAGE_TABLE_ALLOCATOR_H_ +#define _SRC__LIB__HW__PAGE_TABLE_ALLOCATOR_H_ + +#include +#include + +namespace Hw { + template class Page_table_allocator; + struct Out_of_tables {}; +} + +template +class Hw::Page_table_allocator +{ + protected: + + using addr_t = Genode::addr_t; + + addr_t const _virt_addr; + addr_t const _phys_addr; + + template addr_t _offset(TABLE & table) { + return (addr_t)&table - _virt_addr; } + + void * _index(unsigned idx) { + return (void*)(_virt_addr + TABLE_SIZE*idx); } + + virtual unsigned _alloc() = 0; + virtual void _free(unsigned idx) = 0; + + public: + + template class Array; + + Page_table_allocator(addr_t virt_addr, addr_t phys_addr) + : _virt_addr(virt_addr), _phys_addr(phys_addr) {} + + template addr_t phys_addr(TABLE & table) { + static_assert((sizeof(TABLE) == TABLE_SIZE), "unexpected size"); + return _offset(table) + _phys_addr; } + + template TABLE & virt_addr(addr_t phys_addr) { + static_assert((sizeof(TABLE) == TABLE_SIZE), "unexpected size"); + return *(TABLE*)(_virt_addr + (phys_addr - _phys_addr)); } + + template TABLE & construct() { + static_assert((sizeof(TABLE) == TABLE_SIZE), "unexpected size"); + return *Genode::construct_at
(_index(_alloc())); } + + template void destruct(TABLE & table) + { + static_assert((sizeof(TABLE) == TABLE_SIZE), "unexpected size"); + table.~TABLE(); + _free(_offset(table) / sizeof(TABLE)); + } +}; + + +template +template +class Hw::Page_table_allocator::Array +{ + public: + + class Allocator; + + private: + + struct Table { Genode::uint8_t data[TABLE_SIZE]; }; + + Table _tables[COUNT]; + Allocator _alloc; + + public: + + Array() : _alloc((Table*)&_tables, (addr_t)&_tables) {} + + template + explicit Array(T phys_addr) + : _alloc(_tables, phys_addr((void*)_tables)) { } + + Page_table_allocator & alloc() { return _alloc; } +}; + + +template +template +class Hw::Page_table_allocator::Array::Allocator +: public Hw::Page_table_allocator +{ + private: + + using Bit_allocator = Genode::Bit_allocator; + + Bit_allocator _free_tables; + + unsigned _alloc() + { + try { + return _free_tables.alloc(); + } catch (typename Bit_allocator::Out_of_indices&) {} + throw Out_of_tables(); + } + + void _free(unsigned idx) { _free_tables.free(idx); } + + public: + + Allocator(Table * tables, addr_t phys_addr) + : Page_table_allocator((addr_t)tables, phys_addr) {} + + explicit Allocator(Allocator & o) + : Page_table_allocator(o._virt_addr, o._phys_addr), + _free_tables(o._free_tables) + { + static_assert(!__is_polymorphic(Bit_allocator), + "base class needs to be non-virtual"); + } +}; + +#endif /* _SRC__LIB__HW__PAGE_TABLE_ALLOCATOR_H_ */ diff --git a/repos/base-hw/src/bootstrap/spec/arm_v6/cpu.cc b/repos/base-hw/src/lib/hw/spec/arm/arm_v6_cpu.cc similarity index 60% rename from repos/base-hw/src/bootstrap/spec/arm_v6/cpu.cc rename to repos/base-hw/src/lib/hw/spec/arm/arm_v6_cpu.cc index c161c8be48..2aece8729c 100644 --- a/repos/base-hw/src/bootstrap/spec/arm_v6/cpu.cc +++ b/repos/base-hw/src/lib/hw/spec/arm/arm_v6_cpu.cc @@ -1,5 +1,5 @@ /* - * \brief CPU driver for core + * \brief CPU cache maintenance functions for ARM v6 * \author Norman Feske * \author Martin stein * \author Stefan Kalkowski @@ -13,11 +13,11 @@ * under the terms of the GNU Affero General Public License version 3. */ -#include +#include -void Genode::Arm::clean_invalidate_data_cache() { +void Hw::Arm_cpu::invalidate_data_cache() { + asm volatile ("mcr p15, 0, %[rd], c7, c6, 0" :: [rd]"r"(0) : ); } + + +void Hw::Arm_cpu::clean_invalidate_data_cache() { asm volatile ("mcr p15, 0, %[rd], c7, c14, 0" :: [rd]"r"(0) : ); } - - -void Genode::Cpu::translation_added(Genode::addr_t const addr, - Genode::size_t const size) { } diff --git a/repos/base-hw/src/lib/hw/spec/arm/arm_v7_cpu.cc b/repos/base-hw/src/lib/hw/spec/arm/arm_v7_cpu.cc new file mode 100644 index 0000000000..a53bc24139 --- /dev/null +++ b/repos/base-hw/src/lib/hw/spec/arm/arm_v7_cpu.cc @@ -0,0 +1,150 @@ +/* + * \brief CPU cache maintenance functions for ARM v7 + * \author Martin stein + * \author Stefan Kalkowski + * \date 2011-11-03 + */ + +/* + * Copyright (C) 2011-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#include + +/** + * Helpers that increase readability of MCR and MRC commands + */ +#define READ_CLIDR(rd) "mrc p15, 1, " #rd ", c0, c0, 1\n" +#define READ_CCSIDR(rd) "mrc p15, 1, " #rd ", c0, c0, 0\n" +#define WRITE_CSSELR(rs) "mcr p15, 2, " #rs ", c0, c0, 0\n" +#define WRITE_DCISW(rs) "mcr p15, 0, " #rs ", c7, c6, 2\n" +#define WRITE_DCCSW(rs) "mcr p15, 0, " #rs ", c7, c10, 2\n" + +/** + * First macro to do a set/way operation on all entries of all data caches + * + * Must be inserted directly before the targeted operation. Returns operand + * for targeted operation in R6. + */ +#define FOR_ALL_SET_WAY_IN_R6_0 \ + \ + /* get the cache level value (Clidr::Loc) */ \ + READ_CLIDR(r0) \ + "ands r3, r0, #0x7000000\n" \ + "mov r3, r3, lsr #23\n" \ + \ + /* skip all if cache level value is zero */ \ + "beq 5f\n" \ + "mov r9, #0\n" \ + \ + /* begin loop over cache numbers */ \ + "1:\n" \ + \ + /* work out 3 x cache level */ \ + "add r2, r9, r9, lsr #1\n" \ + \ + /* get the cache type of current cache number (Clidr::CtypeX) */ \ + "mov r1, r0, lsr r2\n" \ + "and r1, r1, #7\n" \ + "cmp r1, #2\n" \ + \ + /* skip cache number if there's no data cache at this level */ \ + "blt 4f\n" \ + \ + /* select the appropriate CCSIDR according to cache level and type */ \ + WRITE_CSSELR(r9) \ + "isb\n" \ + \ + /* get the line length of current cache (Ccsidr::LineSize) */ \ + READ_CCSIDR(r1) \ + "and r2, r1, #0x7\n" \ + \ + /* add 4 for the line-length offset (log2 of 16 bytes) */ \ + "add r2, r2, #4\n" \ + \ + /* get the associativity or max way size (Ccsidr::Associativity) */ \ + "ldr r4, =0x3ff\n" \ + "ands r4, r4, r1, lsr #3\n" \ + \ + /* get the bit position of the way-size increment */ \ + "clz r5, r4\n" \ + \ + /* get a working copy of the max way size */ \ + "mov r8, r4\n" \ + \ + /* begin loop over way numbers */ \ + "2:\n" \ + \ + /* get the number of sets or the max index size (Ccsidr::NumSets) */ \ + "ldr r7, =0x00007fff\n" \ + "ands r7, r7, r1, lsr #13\n" \ + \ + /* begin loop over indices */ \ + "3:\n" \ + \ + /* factor in the way number and cache number into write value */ \ + "orr r6, r9, r8, lsl r5\n" \ + \ + /* factor in the index number into write value */ \ + "orr r6, r6, r7, lsl r2\n" + +/** + * Second macro to do a set/way operation on all entries of all data caches + * + * Must be inserted directly after the targeted operation. + */ +#define FOR_ALL_SET_WAY_IN_R6_1 \ + \ + /* decrement the index */ \ + "subs r7, r7, #1\n" \ + \ + /* end loop over indices */ \ + "bge 3b\n" \ + \ + /* decrement the way number */ \ + "subs r8, r8, #1\n" \ + \ + /* end loop over way numbers */ \ + "bge 2b\n" \ + \ + /* label to skip a cache number */ \ + "4:\n" \ + \ + /* increment the cache number */ \ + "add r9, r9, #2\n" \ + "cmp r3, r9\n" \ + \ + /* end loop over cache numbers */ \ + "bgt 1b\n" \ + \ + /* synchronize data */ \ + "dsb\n" \ + \ + /* label to skip all */ \ + "5:\n" \ + ::: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + + +void Hw::Arm_cpu::invalidate_data_cache() +{ + /** + * Data Cache Invalidate by Set/Way for all Set/Way + */ + asm volatile (FOR_ALL_SET_WAY_IN_R6_0 + WRITE_DCISW(r6) + FOR_ALL_SET_WAY_IN_R6_1); +} + + +void Hw::Arm_cpu::clean_invalidate_data_cache() +{ + /** + * Data Cache Clean by Set/Way for all Set/Way + */ + asm volatile (FOR_ALL_SET_WAY_IN_R6_0 + WRITE_DCCSW(r6) + FOR_ALL_SET_WAY_IN_R6_1); +} diff --git a/repos/base-hw/src/lib/hw/spec/arm/cortex_a15.h b/repos/base-hw/src/lib/hw/spec/arm/cortex_a15.h new file mode 100644 index 0000000000..a1b21ab94c --- /dev/null +++ b/repos/base-hw/src/lib/hw/spec/arm/cortex_a15.h @@ -0,0 +1,32 @@ +/* + * \brief Definitions common to all Cortex A15 CPUs + * \author Stefan Kalkowski + * \date 2017-02-23 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__LIB__HW__SPEC__ARM__CORTEX_A15_H_ +#define _SRC__LIB__HW__SPEC__ARM__CORTEX_A15_H_ + +#include + +namespace Hw { template struct Cpu_memory_map; } + +template +struct Hw::Cpu_memory_map +{ + enum { + IRQ_CONTROLLER_DISTR_BASE = BASE + 0x1000, + IRQ_CONTROLLER_DISTR_SIZE = 0x1000, + IRQ_CONTROLLER_CPU_BASE = BASE + 0x2000, + IRQ_CONTROLLER_CPU_SIZE = 0x2000, + }; +}; + +#endif /* _SRC__LIB__HW__SPEC__ARM__CORTEX_A15_H_ */ diff --git a/repos/base-hw/src/lib/hw/spec/arm/cortex_a9.h b/repos/base-hw/src/lib/hw/spec/arm/cortex_a9.h new file mode 100644 index 0000000000..f14dde76ae --- /dev/null +++ b/repos/base-hw/src/lib/hw/spec/arm/cortex_a9.h @@ -0,0 +1,38 @@ +/* + * \brief Definitions common to all Cortex A9 CPUs + * \author Stefan Kalkowski + * \date 2017-02-23 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__LIB__HW__SPEC__ARM__CORTEX_A9_H_ +#define _SRC__LIB__HW__SPEC__ARM__CORTEX_A9_H_ + +#include + +namespace Hw { template struct Cpu_memory_map; } + +template +struct Hw::Cpu_memory_map +{ + enum { + SCU_MMIO_BASE = BASE, + + IRQ_CONTROLLER_DISTR_BASE = BASE + 0x1000, + IRQ_CONTROLLER_DISTR_SIZE = 0x1000, + IRQ_CONTROLLER_CPU_BASE = BASE + 0x100, + IRQ_CONTROLLER_CPU_SIZE = 0x100, + + PRIVATE_TIMER_MMIO_BASE = BASE + 0x600, + PRIVATE_TIMER_MMIO_SIZE = 0x10, + PRIVATE_TIMER_IRQ = 29, + }; +}; + +#endif /* _SRC__LIB__HW__SPEC__ARM__CORTEX_A9_H_ */ diff --git a/repos/base-hw/src/lib/hw/spec/arm/cpu.h b/repos/base-hw/src/lib/hw/spec/arm/cpu.h new file mode 100644 index 0000000000..ed7c6be8f4 --- /dev/null +++ b/repos/base-hw/src/lib/hw/spec/arm/cpu.h @@ -0,0 +1,247 @@ +/* + * \brief CPU definitions for ARM + * \author Stefan Kalkowski + * \date 2017-02-02 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__LIB__HW__SPEC__ARM__CPU_H_ +#define _SRC__LIB__HW__SPEC__ARM__CPU_H_ + +#include + +namespace Hw { struct Arm_cpu; } + +struct Hw::Arm_cpu +{ + /*************************************** + ** System Coprocessor 15 Definitions ** + ***************************************/ + + /* Main ID Register */ + ARM_CP15_REGISTER_32BIT(Midr, c0, c0, 0, 0); + + /* Cache Type Register */ + ARM_CP15_REGISTER_32BIT(Ctr, c0, c0, 0, 1); + + /* Multiprocessor Affinity Register */ + ARM_CP15_REGISTER_32BIT(Mpidr, c0, c0, 0, 5); + + /* System Control Register */ + ARM_CP15_REGISTER_32BIT(Sctlr, c1, c0, 0, 0, + struct M : Bitfield<0,1> { }; /* enable MMU */ + struct A : Bitfield<1,1> { }; /* enable alignment checks */ + struct C : Bitfield<2,1> { }; /* enable data cache */ + struct I : Bitfield<12,1> { }; /* enable instruction caches */ + struct Z : Bitfield<11,1> { }; /* enable program flow prediction */ + struct V : Bitfield<13,1> { }; /* select exception entry */ + ); + + /* Auxiliary Control Register */ + ARM_CP15_REGISTER_32BIT(Actlr, c1, c0, 0, 1); + + /* Coprocessor Access Control Register */ + ARM_CP15_REGISTER_32BIT(Cpacr, c1, c0, 0, 2, + struct Cp10 : Bitfield<20, 2> { }; + struct Cp11 : Bitfield<22, 2> { }; + ); + + /* Hyp System Control Register */ + ARM_CP15_REGISTER_32BIT(Hsctlr, c1, c0, 4, 0); + + /* Secure Configuration Register */ + ARM_CP15_REGISTER_32BIT(Scr, c1, c1, 0, 0, + struct Ns : Bitfield<0, 1> { }; /* not secure */ + struct Fw : Bitfield<4, 1> { }; /* F bit writeable */ + struct Aw : Bitfield<5, 1> { }; /* A bit writeable */ + struct Scd : Bitfield<7, 1> { }; /* smc call disable */ + struct Hce : Bitfield<8, 1> { }; /* hyp call enable */ + struct Sif : Bitfield<9, 1> { }; /* secure instruction fetch */ + ); + + /* Secure Debug Enable Register */ + ARM_CP15_REGISTER_32BIT(Sder, c1, c1, 0, 1); + + /* Non-Secure Access Control Register */ + ARM_CP15_REGISTER_32BIT(Nsacr, c1, c1, 0, 2, + struct Cpnsae10 : Bitfield<10, 1> { }; /* Co-processor 10 access */ + struct Cpnsae11 : Bitfield<11, 1> { }; /* Co-processor 11 access */ + struct Ns_smp : Bitfield<18,1> { }; + ); + + /* Hyp Coprocessor Trap Register */ + ARM_CP15_REGISTER_32BIT(Hcptr, c1, c1, 4, 2, + template struct Tcp : Bitfield {}; + struct Tase : Bitfield<15, 1> { }; + struct Tta : Bitfield<20, 1> { }; + struct Tcpac : Bitfield<31, 1> { }; + ); + + /** + * Common translation table base register + */ + struct Ttbr : Genode::Register<32> + { + enum Memory_region { NON_CACHEABLE = 0, CACHEABLE = 1 }; + + struct C : Bitfield<0,1> { }; /* inner cacheable */ + struct S : Bitfield<1,1> { }; /* shareable */ + struct Rgn : Bitfield<3,2> { }; /* outer cachable mode */ + struct Nos : Bitfield<5,1> { }; /* not outer shareable */ + struct Ba : Bitfield<14, 18> { }; /* translation table base */ + + + /********************************* + * Multiprocessing Extensions ** + *********************************/ + + struct Irgn_1 : Bitfield<0,1> { }; + struct Irgn_0 : Bitfield<6,1> { }; + struct Irgn : Genode::Bitset_2 { }; /* inner cache mode */ + }; + + struct Ttbr_64bit : Genode::Register<64> + { + struct Ba : Bitfield<5, 34> { }; /* translation table base */ + struct Asid : Bitfield<48,8> { }; + }; + + /* Translation Table Base Control Register */ + ARM_CP15_REGISTER_32BIT(Ttbcr, c2, c0, 0, 2, + + /*************************************** + ** Large Physical Address Extensions ** + ***************************************/ + + struct Irgn0 : Bitfield<8, 2> { }; + struct Orgn0 : Bitfield<10, 2> { }; + struct Sh0 : Bitfield<12, 2> { }; + struct Eae : Bitfield<31, 1> { }; /* extended address enable */ + ); + + /* Translation Table Base Register 0 */ + ARM_CP15_REGISTER_32BIT(Ttbr0, c2, c0, 0, 0); + ARM_CP15_REGISTER_64BIT(Ttbr0_64bit, c2, 0); + + /* Translation Table Base Register 1 */ + ARM_CP15_REGISTER_32BIT(Ttbr1, c2, c0, 0, 1); + ARM_CP15_REGISTER_64BIT(Ttbr1_64bit, c2, 1); + + /* Hyp Translation Control Register */ + ARM_CP15_REGISTER_32BIT(Htcr, c2, c0, 4, 2); + + /* Hyp Translation Table Base Register */ + ARM_CP15_REGISTER_64BIT(Httbr_64bit, c2, 4); + + /* Virtualization Translation Control Register */ + ARM_CP15_REGISTER_32BIT(Vtcr, c2, c1, 4, 2, + struct Sl0 : Bitfield<6,2> {}; /* starting level for table walks */ + ); + + /* Domain Access Control Register */ + ARM_CP15_REGISTER_32BIT(Dacr, c3, c0, 0, 0, + struct D0 : Bitfield<0,2> { }; /* access mode for domain 0 */ + ); + + /** + * Common fault status register + */ + struct Fsr : Genode::Register<32> + { + struct Fs_0 : Bitfield<0, 4> { }; + struct Fs_1 : Bitfield<10, 1> { }; + struct Fs : Genode::Bitset_2 { }; /* fault status */ + }; + + /* Data Fault Status Register */ + ARM_CP15_REGISTER_32BIT(Dfsr, c5, c0, 0, 0); + + /* Instruction Fault Status Register */ + ARM_CP15_REGISTER_32BIT(Ifsr, c5, c0, 0, 1); + + /* Data Fault Address Register */ + ARM_CP15_REGISTER_32BIT(Dfar, c6, c0, 0, 0); + + /* Instruction Fault Address Register */ + ARM_CP15_REGISTER_32BIT(Ifar, c6, c0, 0, 2); + + /* Invalidate instruction cache line by MVA to PoU */ + ARM_CP15_REGISTER_32BIT(Icimvau, c7, c5, 0, 1); + + /* Branch predictor invalidate all */ + ARM_CP15_REGISTER_32BIT(Bpiall, c7, c5, 0, 6); + + /* Data Cache Clean and Invalidate by MVA to PoC */ + ARM_CP15_REGISTER_32BIT(Dccimvac, c7, c14, 0, 1); + + /* Invalidate entire unified TLB */ + ARM_CP15_REGISTER_32BIT(Tlbiall, c8, c7, 0, 0); + + /* Memory Attribute Indirection Register 0 */ + ARM_CP15_REGISTER_32BIT(Mair0, c10, c2, 0, 0, + struct Attr0 : Bitfield<0, 8> { }; + struct Attr1 : Bitfield<8, 8> { }; + struct Attr2 : Bitfield<16, 8> { }; + struct Attr3 : Bitfield<24, 8> { }; + ); + + /* Hyp Memory Attribute Indirection Register 0 */ + ARM_CP15_REGISTER_32BIT(Hmair0, c10, c2, 4, 0); + + /* Monitor Vector Base Address Register */ + ARM_CP15_REGISTER_32BIT(Mvbar, c12, c0, 0, 1); + + /* Hyp Vector Base Address Register */ + ARM_CP15_REGISTER_32BIT(Hvbar, c12, c0, 4, 0); + + /* Context ID Register */ + ARM_CP15_REGISTER_32BIT(Cidr, c13, c0, 0, 1); + + /* Counter Frequency register */ + ARM_CP15_REGISTER_32BIT(Cntfrq, c14, c0, 0, 0); + + /****************************** + ** Program status registers ** + ******************************/ + + /** + * Common program status register + */ + struct Psr : Genode::Register<32> + { + /* + * CPU mode + */ + struct M : Bitfield<0,5> + { + enum { + USR = 16, + SVC = 19, + MON = 22, + HYP = 26, + }; + }; + + struct F : Bitfield<6,1> { }; /* FIQ disable */ + struct I : Bitfield<7,1> { }; /* IRQ disable */ + struct A : Bitfield<8,1> { }; /* async. abort disable */ + }; + + ARM_BANKED_REGISTER(Cpsr, cpsr); + + + /********************************** + ** Cache maintainance functions ** + **********************************/ + + static void clean_invalidate_data_cache(); + static void invalidate_data_cache(); +}; + +#endif /* _SRC__LIB__HW__SPEC__ARM__CPU_H_ */ diff --git a/repos/base-hw/src/lib/hw/spec/arm/imx_tzic.h b/repos/base-hw/src/lib/hw/spec/arm/imx_tzic.h new file mode 100644 index 0000000000..aebbe58cea --- /dev/null +++ b/repos/base-hw/src/lib/hw/spec/arm/imx_tzic.h @@ -0,0 +1,118 @@ +/* + * \brief Freescale's TrustZone aware interrupt controller + * \author Stefan Kalkowski + * \date 2012-10-24 + */ + +/* + * Copyright (C) 2012-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__LIB__HW__SPEC__ARM__IMX_TZIC_H_ +#define _SRC__LIB__HW__SPEC__ARM__IMX_TZIC_H_ + +#include + +namespace Hw { class Pic; } + + +class Hw::Pic : public Genode::Mmio +{ + public: + + enum { NR_OF_IRQ = 109, }; + + protected: + + /** + * Software Interrupt Trigger Register + */ + struct Swint : Register<0xf00, 32> { + struct Intid : Bitfield<0,10> { }; }; + + /** + * Interrupt control register + */ + struct Intctrl : Register<0, 32> + { + struct Enable : Bitfield<0,1> { }; + struct Nsen : Bitfield<16,1> { }; + struct Nsen_mask : Bitfield<31,1> { }; + }; + + /** + * Priority mask register + */ + struct Priomask : Register<0xc, 32> { + struct Mask : Bitfield<0,8> { }; }; + + /** + * Interrupt security registers + */ + struct Intsec : Register_array<0x80, 32, NR_OF_IRQ, 1> { + struct Nonsecure : Bitfield<0, 1> { }; }; + + /** + * Interrupt set enable registers + */ + struct Enset : Register_array<0x100, 32, NR_OF_IRQ, 1, true> { + struct Set_enable : Bitfield<0, 1> { }; }; + + /** + * Interrupt clear enable registers + */ + struct Enclear : Register_array<0x180, 32, NR_OF_IRQ, 1, true> { + struct Clear_enable : Bitfield<0, 1> { }; }; + + /** + * Interrupt priority level registers + */ + struct Priority : Register_array<0x400, 32, NR_OF_IRQ, 8> { }; + + /** + * Highest interrupt pending registers + */ + struct Hipndr : Register_array<0xd80, 32, NR_OF_IRQ, 1, true> { + struct Pending : Bitfield<0, 1> { }; }; + + /** + * Validate request number 'i' + */ + bool _valid(unsigned const i) const { return i < NR_OF_IRQ; } + + public: + + Pic(); + + /** + * Receive a pending request number 'i' + */ + bool take_request(unsigned & i) + { + for (unsigned j = 0; j < NR_OF_IRQ; j++) { + if (!read(j)) { continue; } + i = j; + return true; + } + return false; + } + + void finish_request() { } + + /** + * Unmask interrupt 'i' + */ + void unmask(unsigned const i, unsigned) { + if (_valid(i)) { write(1, i); } } + + /** + * Mask interrupt 'i' + */ + void mask(unsigned const i) { + if (_valid(i)) { write(1, i); } } +}; + +#endif /* _SRC__LIB__HW__SPEC__ARM__IMX_TZIC_H_ */ diff --git a/repos/base-hw/src/core/include/spec/arm_v7/long_translation_table.h b/repos/base-hw/src/lib/hw/spec/arm/lpae.h similarity index 74% rename from repos/base-hw/src/core/include/spec/arm_v7/long_translation_table.h rename to repos/base-hw/src/lib/hw/spec/arm/lpae.h index 896c26ecb8..a39050f52f 100644 --- a/repos/base-hw/src/core/include/spec/arm_v7/long_translation_table.h +++ b/repos/base-hw/src/lib/hw/spec/arm/lpae.h @@ -1,5 +1,5 @@ /* - * \brief Long descriptor translation table definitions + * \brief ARM v7 long physical address space extension page table format * \author Stefan Kalkowski * \date 2014-07-07 */ @@ -11,19 +11,16 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _CORE__INCLUDE__SPEC__ARM_V7__LONG_TRANSLATION_TABLE_H_ -#define _CORE__INCLUDE__SPEC__ARM_V7__LONG_TRANSLATION_TABLE_H_ +#ifndef _SRC__LIB__HW__SPEC__ARM__LPAE_H_ +#define _SRC__LIB__HW__SPEC__ARM__LPAE_H_ -/* Genode includes */ #include #include +#include +#include -/* base-hw includes */ -#include -#include +namespace Hw { -namespace Genode -{ enum { SIZE_LOG2_4KB = 12, SIZE_LOG2_16KB = 14, @@ -105,15 +102,20 @@ namespace Genode using Level_1_stage_2_translation_table = Level_x_translation_table; + + struct Page_table; + + using addr_t = Genode::addr_t; + using size_t = Genode::size_t; } template -class Genode::Long_translation_table +class Hw::Long_translation_table { private: - inline bool _aligned(addr_t const a, size_t const alignm_log2) { + bool _aligned(addr_t const a, size_t const alignm_log2) { return a == ((a >> alignm_log2) << alignm_log2); } public: @@ -128,7 +130,7 @@ class Genode::Long_translation_table class Invalid_range {}; class Double_insertion {}; - struct Descriptor : Register<64> + struct Descriptor : Genode::Register<64> { enum Type { INVALID, TABLE, BLOCK }; @@ -196,20 +198,20 @@ class Genode::Long_translation_table struct Attribute_index : Base::template Bitfield<2, 3> { enum { - UNCACHED = Cache_attribute::UNCACHED, - CACHED = Cache_attribute::CACHED, + UNCACHED = Genode::Cache_attribute::UNCACHED, + CACHED = Genode::Cache_attribute::CACHED, DEVICE }; static typename Descriptor::access_t create(Page_flags const &f) { - if (f.type == Genode::DEVICE) + if (f.type == Hw::DEVICE) return Attribute_index::bits(DEVICE); switch (f.cacheable) { - case CACHED: return Attribute_index::bits(CACHED); - case WRITE_COMBINED: - case UNCACHED: return Attribute_index::bits(UNCACHED); + case Genode::CACHED: return Attribute_index::bits(CACHED); + case Genode::WRITE_COMBINED: + case Genode::UNCACHED: return Attribute_index::bits(UNCACHED); } return 0; } @@ -282,7 +284,7 @@ class Genode::Long_translation_table if (!_aligned((addr_t)this, ALIGNM_LOG2)) throw Misaligned(); - memset(&_entries, 0, sizeof(_entries)); + Genode::memset(&_entries, 0, sizeof(_entries)); } template @@ -291,7 +293,7 @@ class Genode::Long_translation_table for (size_t i = vo >> BLOCK_SIZE_LOG2; size > 0; i = vo >> BLOCK_SIZE_LOG2) { addr_t end = (vo + BLOCK_SIZE) & BLOCK_MASK; - size_t sz = min(size, end-vo); + size_t sz = Genode::min(size, end-vo); func(vo, pa, sz, _entries[i]); @@ -316,29 +318,26 @@ class Genode::Long_translation_table } __attribute__((aligned(1 << ALIGNM_LOG2))); -template -class Genode::Level_3_translation_table : - public Genode::Long_translation_table +template +class Hw::Level_3_translation_table : + public Hw::Long_translation_table { private: struct Insert_func { - Page_flags const & flags; - Translation_table_allocator * alloc; + Page_flags const & flags; - Insert_func(Page_flags const & flags, - Translation_table_allocator * alloc) - : flags(flags), alloc(alloc) { } + Insert_func(Page_flags const & flags) : flags(flags) { } void operator () (addr_t const vo, addr_t const pa, size_t const size, Descriptor::access_t &desc) { - using Base = Long_translation_table; + using Base = Long_translation_table; using Block_descriptor = typename Stage_trait::Type; if ((vo & ~BLOCK_MASK) || (pa & ~BLOCK_MASK) || @@ -356,9 +355,7 @@ class Genode::Level_3_translation_table : struct Remove_func { - Translation_table_allocator * alloc; - - Remove_func(Translation_table_allocator * alloc) : alloc(alloc) { } + Remove_func() { } void operator () (addr_t const vo, addr_t const pa, @@ -369,23 +366,28 @@ class Genode::Level_3_translation_table : public: + using Allocator = Hw::Page_table_allocator<1 << SIZE_LOG2_4KB>; + void insert_translation(addr_t vo, addr_t pa, size_t size, Page_flags const & flags, - Translation_table_allocator * alloc) { - _range_op(vo, pa, size, Insert_func(flags, alloc)); } + Allocator & alloc) { + _range_op(vo, pa, size, Insert_func(flags)); } - void remove_translation(addr_t vo, size_t size, - Translation_table_allocator * alloc) { - _range_op(vo, 0, size, Remove_func(alloc)); } + void remove_translation(addr_t vo, size_t size, Allocator&) { + _range_op(vo, 0, size, Remove_func()); } }; -template -class Genode::Level_x_translation_table : - public Genode::Long_translation_table +template +class Hw::Level_x_translation_table : + public Hw::Long_translation_table { + public: + + using Allocator = Hw::Page_table_allocator<1 << SIZE_LOG2_4KB>; + private: using Base = Long_translation_table; @@ -393,13 +395,13 @@ class Genode::Level_x_translation_table : using Table_descriptor = typename Base::Table_descriptor; using Block_descriptor = typename Stage_trait::Type; + template struct Insert_func { - Page_flags const & flags; - Translation_table_allocator * alloc; + Page_flags const & flags; + Allocator & alloc; - Insert_func(Page_flags const & flags, - Translation_table_allocator * alloc) + Insert_func(Page_flags const & flags, Allocator & alloc) : flags(flags), alloc(alloc) { } void operator () (addr_t const vo, @@ -407,6 +409,8 @@ class Genode::Level_x_translation_table : size_t const size, typename Descriptor::access_t &desc) { + using Nt = typename Table_descriptor::Next_table; + /* can we insert a whole block? */ if (!((vo & ~Base::BLOCK_MASK) || (pa & ~Base::BLOCK_MASK) || size < Base::BLOCK_SIZE)) { @@ -419,27 +423,21 @@ class Genode::Level_x_translation_table : } /* we need to use a next level table */ - ENTRY *table; switch (Descriptor::type(desc)) { case Descriptor::INVALID: /* no entry */ { - if (!alloc) throw Allocator::Out_of_memory(); - /* create and link next level table */ - table = new (alloc) ENTRY(); - ENTRY * phys_addr = (ENTRY*) alloc->phys_addr(table); - desc = Table_descriptor::create(phys_addr ? - phys_addr : table); + E & table = alloc.construct(); + desc = Table_descriptor::create((void*)alloc.phys_addr(table)); } case Descriptor::TABLE: /* table already available */ { /* use allocator to retrieve virt address of table */ - ENTRY * phys_addr = (ENTRY*) - Table_descriptor::Next_table::masked(desc); - table = (ENTRY*) alloc->virt_addr(phys_addr); - table = table ? table : (ENTRY*)phys_addr; + E & table = alloc.virt_addr(Nt::masked(desc)); + table.insert_translation(vo - (vo & Base::BLOCK_MASK), + pa, size, flags, alloc); break; } @@ -448,38 +446,33 @@ class Genode::Level_x_translation_table : throw typename Base::Double_insertion(); } }; - - /* insert translation */ - table->insert_translation(vo - (vo & Base::BLOCK_MASK), - pa, size, flags, alloc); } }; + template struct Remove_func { - Translation_table_allocator * alloc; + Allocator & alloc; - Remove_func(Translation_table_allocator * alloc) : alloc(alloc) { } + Remove_func(Allocator & alloc) : alloc(alloc) { } void operator () (addr_t const vo, addr_t const pa, size_t const size, typename Descriptor::access_t &desc) { + using Nt = typename Table_descriptor::Next_table; + switch (Descriptor::type(desc)) { case Descriptor::TABLE: { /* use allocator to retrieve virt address of table */ - ENTRY * phys_addr = (ENTRY*) - Table_descriptor::Next_table::masked(desc); - ENTRY * table = (ENTRY*) alloc->virt_addr(phys_addr); - table = table ? table : (ENTRY*)phys_addr; - table->remove_translation(vo - (vo & Base::BLOCK_MASK), - size, alloc); - if (!table->empty()) - break; - destroy(alloc, table); + E & table = alloc.virt_addr(Nt::masked(desc)); + table.remove_translation(vo - (vo & Base::BLOCK_MASK), + size, alloc); + if (!table.empty()) break; + alloc.destruct(table); } case Descriptor::BLOCK: case Descriptor::INVALID: @@ -508,8 +501,8 @@ class Genode::Level_x_translation_table : addr_t pa, size_t size, Page_flags const & flags, - Translation_table_allocator * alloc) { - this->_range_op(vo, pa, size, Insert_func(flags, alloc)); } + Allocator & alloc) { + this->_range_op(vo, pa, size, Insert_func(flags, alloc)); } /** * Remove translations that overlap with a given virtual region @@ -519,29 +512,23 @@ class Genode::Level_x_translation_table : * \param alloc second level translation table allocator */ void remove_translation(addr_t vo, size_t size, - Translation_table_allocator * alloc) { - this->_range_op(vo, 0, size, Remove_func(alloc)); } + Allocator & alloc) { + this->_range_op(vo, 0, size, Remove_func(alloc)); } }; -namespace Genode { - class Translation_table; -} - -class Genode::Translation_table : public Level_1_stage_1_translation_table +struct Hw::Page_table : Level_1_stage_1_translation_table { - public: - - enum { - TABLE_LEVEL_X_SIZE_LOG2 = SIZE_LOG2_4KB, - TABLE_LEVEL_X_ENTRIES = (1 << SIZE_LOG2_4KB) / sizeof(addr_t), - CORE_VM_AREA_SIZE = 1024 * 1024 * 1024, - SIZE_1GB = 1 << SIZE_LOG2_1GB, - CORE_LEVEL_2_TT_COUNT = ((uint64_t)CORE_VM_AREA_SIZE + - SIZE_1GB - 1) / SIZE_1GB, - CORE_TRANS_TABLE_COUNT = CORE_LEVEL_2_TT_COUNT + - CORE_LEVEL_2_TT_COUNT * - TABLE_LEVEL_X_ENTRIES, - }; + enum { + TABLE_LEVEL_X_SIZE_LOG2 = SIZE_LOG2_4KB, + TABLE_LEVEL_X_ENTRIES = (1 << SIZE_LOG2_4KB) / sizeof(addr_t), + CORE_VM_AREA_SIZE = 1024 * 1024 * 1024, + SIZE_1GB = 1 << SIZE_LOG2_1GB, + CORE_LEVEL_2_TT_COUNT = ((Genode::uint64_t)CORE_VM_AREA_SIZE + + SIZE_1GB - 1) / SIZE_1GB, + CORE_TRANS_TABLE_COUNT = CORE_LEVEL_2_TT_COUNT + + CORE_LEVEL_2_TT_COUNT * + TABLE_LEVEL_X_ENTRIES, + }; }; -#endif /* _CORE__INCLUDE__SPEC__ARM_V7__LONG_TRANSLATION_TABLE_H_ */ +#endif /* _SRC__LIB__HW__SPEC__ARM__LPAE_H_ */ diff --git a/repos/base-hw/src/lib/hw/spec/arm/page_table.h b/repos/base-hw/src/lib/hw/spec/arm/page_table.h new file mode 100644 index 0000000000..6a5ce9d96c --- /dev/null +++ b/repos/base-hw/src/lib/hw/spec/arm/page_table.h @@ -0,0 +1,571 @@ +/* + * \brief Standard ARM v7 2-level page table format + * \author Martin Stein + * \author Stefan Kalkowski + * \date 2012-02-22 + */ + +/* + * Copyright (C) 2012-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__LIB__HW__SPEC__ARM__PAGE_TABLE_H_ +#define _SRC__LIB__HW__SPEC__ARM__PAGE_TABLE_H_ + +#include +#include +#include +#include +#include + +namespace Hw { class Page_table; } + +class Hw::Page_table +{ + private: + + template + using Register = Genode::Register; + + template + using Bitset_2 = Genode::Bitset_2; + + class Descriptor_base + { + protected: + + /** + * Return TEX value for device-memory + */ + static constexpr unsigned _device_tex(); + + /** + * Return whether this is a SMP system + */ + static constexpr bool _smp(); + + /** + * Return descriptor value according to physical address 'pa' + */ + template + static typename T::access_t _create(Page_flags const & f, + addr_t pa) + { + using namespace Genode; + + typename T::access_t v = T::Pa::masked(pa); + T::S::set(v, _smp()); + T::Ng::set(v, !f.global); + T::Xn::set(v, !f.executable); + if (f.type == DEVICE) { + T::Tex::set(v, _device_tex()); + } else { + switch (f.cacheable) { + case CACHED: T::Tex::set(v, 5); + case WRITE_COMBINED: T::B::set(v, 1); break; + case UNCACHED: T::Tex::set(v, 1); break; + } + } + if (f.writeable) if (f.privileged) T::Ap::set(v, 1); + else T::Ap::set(v, 3); + else if (f.privileged) T::Ap::set(v, 5); + else T::Ap::set(v, 2); + return v; + } + }; + + class Page_table_level_2 + { + public: + + enum { + SIZE_LOG2 = 10, + SIZE = 1 << SIZE_LOG2, + ALIGNM_LOG2 = SIZE_LOG2, + }; + + /** + * Common descriptor structure + */ + struct Descriptor : Register<32>, Descriptor_base + { + enum Type { FAULT, SMALL_PAGE }; + + enum { + VIRT_SIZE_LOG2 = 12, + VIRT_SIZE = 1 << VIRT_SIZE_LOG2, + VIRT_OFFSET_MASK = (1 << VIRT_SIZE_LOG2) - 1, + VIRT_BASE_MASK = ~(VIRT_OFFSET_MASK), + }; + + struct Type_0 : Bitfield<0, 2> { }; + struct Type_1 : Bitfield<1, 1> { }; + + /** + * Get descriptor type of 'v' + */ + static Type type(access_t const v) + { + access_t const t0 = Type_0::get(v); + if (t0 == 0) { return FAULT; } + access_t const t1 = Type_1::get(v); + if (t1 == 1) { return SMALL_PAGE; } + return FAULT; + } + + /** + * At descriptor value 'v' set type to 't' + */ + static void type(access_t & v, Type const t) + { + switch (t) { + case FAULT: Type_0::set(v, 0); return; + case SMALL_PAGE: Type_1::set(v, 1); return; } + } + + static void invalidate(access_t & v) { type(v, FAULT); } + + static bool valid(access_t & v) { + return type(v) != FAULT; } + }; + + /** + * Small page descriptor structure + */ + struct Small_page : Descriptor + { + struct Xn : Bitfield<0, 1> { }; /* execute never */ + struct B : Bitfield<2, 1> { }; /* mem region attr. */ + struct Ap_0 : Bitfield<4, 2> { }; /* access permission */ + struct Tex : Bitfield<6, 3> { }; /* mem region attr. */ + struct Ap_1 : Bitfield<9, 1> { }; /* access permission */ + struct S : Bitfield<10, 1> { }; /* shareable bit */ + struct Ng : Bitfield<11, 1> { }; /* not global bit */ + struct Pa : Bitfield<12, 20> { }; /* physical base */ + struct Ap : Bitset_2 { }; /* access permission */ + + /** + * Return page descriptor for physical address 'pa' and 'flags' + */ + static access_t create(Page_flags const & flags, + addr_t const pa) + { + access_t v = _create(flags, pa); + Descriptor::type(v, Descriptor::SMALL_PAGE); + return v; + } + }; + + private: + + static constexpr size_t cnt = + SIZE / sizeof(Descriptor::access_t); + + Descriptor::access_t _entries[cnt]; + + enum { + MAX_INDEX = sizeof(_entries) / sizeof(_entries[0]) - 1 + }; + + /** + * Get entry index by virtual offset + * + * \param i is overridden with the index if call returns 0 + * \param vo virtual offset relative to the virtual table base + * + * \retval 0 on success + * \retval <0 translation failed + */ + bool _index_by_vo(unsigned & i, addr_t const vo) const + { + if (vo > max_virt_offset()) return false; + i = vo >> Descriptor::VIRT_SIZE_LOG2; + return true; + } + + public: + + Page_table_level_2() + { + assert(aligned(this, ALIGNM_LOG2)); + Genode::memset(&_entries, 0, sizeof(_entries)); + } + + /** + * Maximum virtual offset that can be translated by this table + */ + static addr_t max_virt_offset() + { + return (MAX_INDEX << Descriptor::VIRT_SIZE_LOG2) + + (Descriptor::VIRT_SIZE - 1); + } + + /** + * Insert one atomic translation into this table + * + * \param vo offset of the virtual region represented + * by the translation within the virtual + * region represented by this table + * \param pa base of the physical backing store + * \param size size of the translated region + * \param flags mapping flags + */ + void insert_translation(addr_t vo, + addr_t pa, + size_t size, + Page_flags const & flags) + { + constexpr size_t sz = Descriptor::VIRT_SIZE; + + for (unsigned i; (size > 0) && _index_by_vo(i, vo); + size = (size < sz) ? 0 : size - sz, + vo += sz, pa += sz) + { + + /* compose new descriptor value */ + Small_page::access_t const e = + Small_page::create(flags, pa); + + /* check if it is a good idea to override the entry */ + assert(!Descriptor::valid(_entries[i]) || + _entries[i] == e); + + /* override entry */ + _entries[i] = e; + } + } + + /** + * Remove translations that overlap with a given virtual region + * + * \param vo region offset within the tables virtual region + * \param size region size + */ + void remove_translation(addr_t vo, size_t size) + { + constexpr size_t sz = Descriptor::VIRT_SIZE; + + for (unsigned i; (size > 0) && _index_by_vo(i, vo); + size = (size < sz) ? 0 : size - sz, vo += sz) + { + switch (Descriptor::type(_entries[i])) { + case Descriptor::SMALL_PAGE: + Descriptor::invalidate(_entries[i]); + default: ; + } + } + } + + /** + * Does this table solely contain invalid entries + */ + bool empty() + { + for (unsigned i = 0; i <= MAX_INDEX; i++) { + if (Descriptor::valid(_entries[i])) return false; } + return true; + } + + } __attribute__((aligned(1<; + + enum { + SIZE_LOG2 = 14, + SIZE = 1 << SIZE_LOG2, + ALIGNM_LOG2 = SIZE_LOG2, + MAX_PAGE_SIZE_LOG2 = 20, + MIN_PAGE_SIZE_LOG2 = 12, + TABLE_LEVEL_X_VIRT_SIZE = 1 << MAX_PAGE_SIZE_LOG2, + TABLE_LEVEL_X_SIZE_LOG2 = MIN_PAGE_SIZE_LOG2, + CORE_VM_AREA_SIZE = 1024 * 1024 * 1024, + CORE_TRANS_TABLE_COUNT = CORE_VM_AREA_SIZE / TABLE_LEVEL_X_VIRT_SIZE, + }; + + /** + * A first level translation descriptor + */ + struct Descriptor : Register<32>, Descriptor_base + { + enum Type { FAULT, PAGE_TABLE, SECTION }; + + enum { + VIRT_SIZE_LOG2 = 20, + VIRT_SIZE = 1 << VIRT_SIZE_LOG2, + VIRT_OFFSET_MASK = (1 << VIRT_SIZE_LOG2) - 1, + VIRT_BASE_MASK = ~VIRT_OFFSET_MASK, + }; + + struct Type_0 : Bitfield<0, 2> { }; + struct Type_1_0 : Bitfield<1, 1> { }; + struct Type_1_1 : Bitfield<18, 1> { }; + struct Type_1 : Bitset_2 { }; + + /** + * Get descriptor type of 'v' + */ + static Type type(access_t const v) + { + switch (Type_0::get(v)) { + case 0: return FAULT; + case 1: return PAGE_TABLE; } + + if (Type_1::get(v) == 1) { return SECTION; } + return FAULT; + } + + /** + * Set descriptor type of 'v' + */ + static void type(access_t & v, Type const t) + { + switch (t) { + case FAULT: Type_0::set(v, 0); return; + case PAGE_TABLE: Type_0::set(v, 1); return; + case SECTION: Type_1::set(v, 1); return; } + } + + static void invalidate(access_t & v) { type(v, FAULT); } + + static bool valid(access_t & v) { return type(v) != FAULT; } + + static inline Type align(addr_t vo, addr_t pa, size_t size) + { + return ((vo & VIRT_OFFSET_MASK) || (pa & VIRT_OFFSET_MASK) || + size < VIRT_SIZE) ? PAGE_TABLE : SECTION; + } + }; + + /** + * Link to a second level translation table + */ + struct Page_table_descriptor : Descriptor + { + struct Domain : Bitfield<5, 4> { }; /* domain */ + struct Pa : Bitfield<10, 22> { }; /* physical base */ + + /** + * Return descriptor value for page table 'pt + */ + static access_t create(addr_t pt) + { + access_t v = Pa::masked(pt); + Descriptor::type(v, Descriptor::PAGE_TABLE); + return v; + } + }; + + /** + * Section translation descriptor + */ + struct Section : Descriptor + { + struct B : Bitfield<2, 1> { }; /* mem. region attr. */ + struct Xn : Bitfield<4, 1> { }; /* execute never bit */ + struct Ap_0 : Bitfield<10, 2> { }; /* access permission */ + struct Tex : Bitfield<12, 3> { }; /* mem. region attr. */ + struct Ap_1 : Bitfield<15, 1> { }; /* access permission */ + struct S : Bitfield<16, 1> { }; /* shared */ + struct Ng : Bitfield<17, 1> { }; /* not global */ + struct Pa : Bitfield<20, 12> { }; /* physical base */ + struct Ap : Bitset_2 { }; /* access permission */ + + /** + * Return section descriptor for physical address 'pa' and 'flags' + */ + static access_t create(Page_flags const & flags, addr_t const pa) + { + access_t v = _create
(flags, pa); + Descriptor::type(v, Descriptor::SECTION); + return v; + } + }; + + protected: + + /* table payload, must be the first member of this class */ + Descriptor::access_t _entries[SIZE/sizeof(Descriptor::access_t)]; + + enum { MAX_INDEX = sizeof(_entries) / sizeof(_entries[0]) - 1 }; + + static inline void _translation_added(addr_t, size_t); + + /** + * Try to get entry index in 'i' for virtual offset 'vo! + * + * \return whether it was successful + */ + bool _index_by_vo(unsigned & i, addr_t const vo) const + { + if (vo > max_virt_offset()) return false; + i = vo >> Descriptor::VIRT_SIZE_LOG2; + return true; + } + + /** + * Insert a second level translation at the given entry index + * + * \param i the related index + * \param vo virtual start address of range + * \param pa physical start address of range + * \param size size of range + * \param flags mapping flags + * \param alloc second level translation table allocator + */ + void _insert_second_level(unsigned i, addr_t const vo, addr_t const pa, + size_t const size, Page_flags const & flags, + Allocator & alloc) + { + using Pt = Page_table_level_2; + using Ptd = Page_table_descriptor; + + switch (Descriptor::type(_entries[i])) { + + case Descriptor::FAULT: + { + /* create and link page table */ + Pt & pt = alloc.construct(); + _entries[i] = Ptd::create(alloc.phys_addr(pt)); + _translation_added((addr_t)&_entries[i], sizeof(Ptd)); + } + + case Descriptor::PAGE_TABLE: + { + Pt & pt = alloc.virt_addr(Ptd::Pa::masked(_entries[i])); + pt.insert_translation(vo - Section::Pa::masked(vo), pa, size, flags); + _translation_added((addr_t)&pt, sizeof(Page_table_level_2)); + break; + } + + default: assert(0); + } + + } + + public: + + Page_table() + { + assert(aligned(this, ALIGNM_LOG2)); + Genode::memset(&_entries, 0, sizeof(_entries)); + } + + /** + * Maximum virtual offset that can be translated by this table + */ + static addr_t max_virt_offset() + { + constexpr addr_t base = MAX_INDEX << Descriptor::VIRT_SIZE_LOG2; + return base + (Descriptor::VIRT_SIZE - 1); + } + + /** + * Insert translations into this table + * + * \param vo offset of virt. transl. region in virt. table region + * \param pa base of physical backing store + * \param size size of translated region + * \param f mapping flags + * \param alloc second level translation table allocator + */ + void insert_translation(addr_t vo, addr_t pa, size_t size, + Page_flags const & f, Allocator & alloc) + { + /* check sanity */ + assert(!(vo & Page_table_level_2::Descriptor::VIRT_OFFSET_MASK) && + size >= Page_table_level_2::Descriptor::VIRT_SIZE); + + for (unsigned i; (size > 0) && _index_by_vo (i, vo);) { + + addr_t const ve = (vo + Descriptor::VIRT_SIZE); + addr_t const end = ve & Descriptor::VIRT_BASE_MASK; + + /* decide granularity of entry that can be inserted */ + switch (Descriptor::align(vo, pa, size)) { + + case Descriptor::SECTION: + { + /* compose new entry */ + Section::access_t const e = Section::create(f, pa); + + /* override entry */ + if (_entries[i] == e) { break; } + assert(!Descriptor::valid(_entries[i])); + _entries[i] = e; + + /* some CPUs need to act on changed translations */ + _translation_added((addr_t)&_entries[i], sizeof(Section)); + break; + } + + default: + _insert_second_level(i, vo, pa, Genode::min(size, end - vo), f, + alloc); + }; + + /* check whether we wrap */ + if (end < vo) { return; } + + size_t sz = end - vo; + size = (size > sz) ? size - sz : 0; + vo += sz; + pa += sz; + } + } + + /** + * Remove translations that overlap with a given virtual region + * + * \param vo region offset within the tables virtual region + * \param size region size + * \param alloc second level translation table allocator + */ + void remove_translation(addr_t vo, size_t size, Allocator & alloc) + { + using Pt = Page_table_level_2; + /* check sanity */ + assert(vo <= (vo + size)); + + for (unsigned i; (size > 0) && _index_by_vo(i, vo);) { + + constexpr addr_t dbm = Descriptor::VIRT_BASE_MASK; + addr_t const end = (vo + Descriptor::VIRT_SIZE) & dbm; + + switch (Descriptor::type(_entries[i])) { + + case Descriptor::PAGE_TABLE: + { + using Ptd = Page_table_descriptor; + + Pt & pt = + alloc.virt_addr(Ptd::Pa::masked(_entries[i])); + + addr_t const pt_vo = vo - Section::Pa::masked(vo); + pt.remove_translation(pt_vo, Genode::min(size, end-vo)); + + if (pt.empty()) { + Descriptor::invalidate(_entries[i]); + alloc.destruct(pt); + } + break; + } + + default: Descriptor::invalidate(_entries[i]); } + + /* check whether we wrap */ + if (end < vo) return; + + size_t sz = end - vo; + size = (size > sz) ? size - sz : 0; + vo += sz; + } + } +} __attribute__((aligned(1< + +namespace Hw { + + enum Panda_firmware_opcodes { + CPU_ACTLR_SMP_BIT_RAISE = 0x25, + L2_CACHE_SET_DEBUG_REG = 0x100, + L2_CACHE_ENABLE_REG = 0x102, + L2_CACHE_AUX_REG = 0x109, + }; + + static inline void call_panda_firmware(Genode::addr_t func, + Genode::addr_t val) + { + register Genode::addr_t _func asm("r12") = func; + register Genode::addr_t _val asm("r0") = val; + asm volatile("dsb; smc #0" :: "r" (_func), "r" (_val) : + "memory", "cc", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11"); + } +} + +#endif /* _SRC__LIB__HW__SPEC__ARM__PANDA_TRUSTZONE_FIRMWARE_H_ */ diff --git a/repos/base-hw/src/lib/hw/spec/arm/pic.h b/repos/base-hw/src/lib/hw/spec/arm/pic.h new file mode 100644 index 0000000000..f106e7a97f --- /dev/null +++ b/repos/base-hw/src/lib/hw/spec/arm/pic.h @@ -0,0 +1,224 @@ +/* + * \brief Programmable interrupt controller for core + * \author Martin stein + * \author Stefan Kalkowski + * \date 2011-10-26 + */ + +/* + * Copyright (C) 2011-2013 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__LIB__HW__SPEC__ARM__PIC_H_ +#define _SRC__LIB__HW__SPEC__ARM__PIC_H_ + +#include + +namespace Hw { class Pic; } + +class Hw::Pic +{ + protected: + + /** + * Distributor of the ARM generic interrupt controller + */ + struct Distributor : Genode::Mmio + { + static constexpr unsigned nr_of_irq = 1024; + + /** + * Control register + */ + struct Ctlr : Register<0x000, 32> + { + struct Enable : Bitfield<0,1> { }; + struct Enable_grp0 : Bitfield<0,1> { }; + struct Enable_grp1 : Bitfield<1,1> { }; + }; + + /** + * Controller type register + */ + struct Typer : Register<0x004, 32> { + struct It_lines_number : Bitfield<0,5> { }; }; + + /** + * Interrupt group register + */ + struct Igroupr : Register_array<0x80, 32, nr_of_irq, 1> { + struct Group_status : Bitfield<0, 1> { }; }; + + /** + * Interrupt set enable registers + */ + struct Isenabler : Register_array<0x100, 32, nr_of_irq, 1, true> { + struct Set_enable : Bitfield<0, 1> { }; }; + + /** + * Interrupt clear enable registers + */ + struct Icenabler : Register_array<0x180, 32, nr_of_irq, 1, true> { + struct Clear_enable : Bitfield<0, 1> { }; }; + + /** + * Interrupt priority level registers + */ + struct Ipriorityr : Register_array<0x400, 32, nr_of_irq, 8> { + struct Priority : Bitfield<0, 8> { }; }; + + /** + * Interrupt CPU-target registers + */ + struct Itargetsr : Register_array<0x800, 32, nr_of_irq, 8> { + struct Cpu_targets : Bitfield<0, 8> { }; }; + + /** + * Interrupt configuration registers + */ + struct Icfgr : Register_array<0xc00, 32, nr_of_irq, 2> { + struct Edge_triggered : Bitfield<1, 1> { }; }; + + /** + * Software generated interrupt register + */ + struct Sgir : Register<0xf00, 32> + { + struct Sgi_int_id : Bitfield<0, 4> { }; + struct Cpu_target_list : Bitfield<16, 8> { }; + struct Target_list_filter : Bitfield<24, 2> + { + enum Target { TARGET_LIST, ALL_OTHER, MYSELF }; + }; + }; + + Distributor(Genode::addr_t const base) : Genode::Mmio(base) { } + + /** + * Return minimum IRQ priority + */ + unsigned min_priority() + { + write(~0, 0); + return read(0); + } + + /** + * Return highest IRQ number + */ + unsigned max_irq() + { + constexpr unsigned line_width_log2 = 5; + Typer::access_t const lnr = read(); + return ((lnr + 1) << line_width_log2) - 1; + } + }; + + + /** + * CPU interface of the ARM generic interrupt controller + */ + struct Cpu_interface : Genode::Mmio + { + /** + * Control register + */ + struct Ctlr : Register<0x00, 32> + { + struct Enable : Bitfield<0,1> { }; + struct Enable_grp0 : Bitfield<0,1> { }; + struct Enable_grp1 : Bitfield<1,1> { }; + struct Fiq_en : Bitfield<3,1> { }; + }; + + /** + * Priority mask register + */ + struct Pmr : Register<0x04, 32> { + struct Priority : Bitfield<0,8> { }; }; + + /** + * Binary point register + */ + struct Bpr : Register<0x08, 32> { + struct Binary_point : Bitfield<0,3> { }; }; + + /** + * Interrupt acknowledge register + */ + struct Iar : Register<0x0c, 32, true> { + struct Irq_id : Bitfield<0,10> { }; }; + + /** + * End of interrupt register + */ + struct Eoir : Register<0x10, 32, true> { + struct Irq_id : Bitfield<0,10> { }; }; + + Cpu_interface(Genode::addr_t const base) : Genode::Mmio(base) { } + }; + + + static constexpr unsigned min_spi = 32; + static constexpr unsigned spurious_id = 1023; + + Distributor _distr; + Cpu_interface _cpui; + Cpu_interface::Iar::access_t _last_iar; + unsigned const _max_irq; + + void _init(); + + bool _valid(unsigned const irq_id) const { return irq_id <= _max_irq; } + + public: + + enum { NR_OF_IRQ = Distributor::nr_of_irq }; + + Pic(); + + /** + * Try to take an IRQ and return wether it was successful + * + * \param irq contains kernel name of taken IRQ on success + */ + bool take_request(unsigned & irq) + { + _last_iar = _cpui.read(); + irq = Cpu_interface::Iar::Irq_id::get(_last_iar); + return _valid(irq); + } + + /** + * End the last taken IRQ + */ + void finish_request() + { + _cpui.write(_last_iar); + _last_iar = Cpu_interface::Iar::Irq_id::bits(spurious_id); + } + + /** + * Unmask IRQ and assign it to one CPU + * + * \param irq_id kernel name of targeted IRQ + * \param cpu_id kernel name of targeted CPU + */ + void unmask(unsigned const irq_id, unsigned const cpu_id) + { + unsigned const targets = 1 << cpu_id; + _distr.write(targets, irq_id); + _distr.write(1, irq_id); + } + + /** + * Mask IRQ with kernel name 'irq_id' + */ + void mask(unsigned const irq_id) { + _distr.write(1, irq_id); } +}; + +#endif /* _SRC__LIB__HW__SPEC__ARM__PIC_H_ */ diff --git a/repos/base-hw/src/core/include/spec/arm/pl310.h b/repos/base-hw/src/lib/hw/spec/arm/pl310.h similarity index 88% rename from repos/base-hw/src/core/include/spec/arm/pl310.h rename to repos/base-hw/src/lib/hw/spec/arm/pl310.h index 2eaafa14bf..ac724a9087 100644 --- a/repos/base-hw/src/core/include/spec/arm/pl310.h +++ b/repos/base-hw/src/lib/hw/spec/arm/pl310.h @@ -13,19 +13,15 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _CORE__INCLUDE__SPEC__ARM__PL310_H_ -#define _CORE__INCLUDE__SPEC__ARM__PL310_H_ +#ifndef _SRC__LIB__HW__SPEC__ARM__PL310_H_ +#define _SRC__LIB__HW__SPEC__ARM__PL310_H_ /* Genode includes */ #include -namespace Arm { struct Pl310; } +namespace Hw { struct Pl310; } - -/** - * L2 outer cache controller - */ -class Arm::Pl310 : public Genode::Mmio +class Hw::Pl310 : public Genode::Mmio { protected: @@ -87,4 +83,4 @@ class Arm::Pl310 : public Genode::Mmio } }; -#endif /* _CORE__INCLUDE__SPEC__ARM__PL310_H_ */ +#endif /* _SRC__LIB__HW__SPEC__ARM__PL310_H_ */ diff --git a/repos/base-hw/src/lib/hw/spec/arm/register_macros.h b/repos/base-hw/src/lib/hw/spec/arm/register_macros.h new file mode 100644 index 0000000000..12155ab83e --- /dev/null +++ b/repos/base-hw/src/lib/hw/spec/arm/register_macros.h @@ -0,0 +1,71 @@ +/* + * \brief CPU register macros for ARM + * \author Stefan Kalkowski + * \date 2017-02-02 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__LIB__HW__SPEC__ARM__REGISTER_MACROS_H_ +#define _SRC__LIB__HW__SPEC__ARM__REGISTER_MACROS_H_ + +#include + +#define ARM_CP15_REGISTER_32BIT(name, crn, crm, op1, op2, ...) \ + struct name : Genode::Register<32> \ + { \ + static access_t read() \ + { \ + access_t v; \ + asm volatile ("mrc p15, " #op1 ", %0, " #crn ", " #crm ", " #op2 \ + : "=r" (v) :: ); \ + return v; \ + } \ + \ + static void write(access_t const v) { \ + asm volatile ("mcr p15, " #op1 ", %0, " #crn ", " #crm ", " #op2 \ + :: "r" (v) : ); } \ + \ + __VA_ARGS__; \ + }; + +#define ARM_CP15_REGISTER_64BIT(name, cr, op, ...) \ + struct name : Genode::Register<64> \ + { \ + static access_t read() \ + { \ + Genode::uint32_t v0, v1; \ + asm volatile ("mrrc p15, " #op ", %0, %1, " #cr \ + : "=r" (v0), "=r" (v1) :: ); \ + return (access_t) v0 | ((access_t) v1 << 32); \ + } \ + \ + static void write(access_t const v) { \ + asm volatile ("mcrr p15, " #op ", %0, %1, " #cr \ + :: "r" (v), "r" (v >> 32) : ); } \ + \ + __VA_ARGS__; \ + }; + +#define ARM_BANKED_REGISTER(name, reg, ...) \ + struct name : Genode::Register<32> \ + { \ + static access_t read() \ + { \ + access_t v; \ + asm volatile ("mrs %0, " #reg : "=r" (v)); \ + return v; \ + } \ + \ + static void write(access_t const v) { \ + asm volatile ("msr " #reg ", %0" :: "r" (v)); } \ + \ + __VA_ARGS__; \ + }; + +#endif /* _SRC__LIB__HW__SPEC__ARM__REGISTER_MACROS_H_ */ diff --git a/repos/base-hw/src/core/include/spec/riscv/machine_call.h b/repos/base-hw/src/lib/hw/spec/riscv/machine_call.h similarity index 55% rename from repos/base-hw/src/core/include/spec/riscv/machine_call.h rename to repos/base-hw/src/lib/hw/spec/riscv/machine_call.h index dbfe9f4a72..89eb6f7650 100644 --- a/repos/base-hw/src/core/include/spec/riscv/machine_call.h +++ b/repos/base-hw/src/lib/hw/spec/riscv/machine_call.h @@ -2,6 +2,7 @@ * \brief Calls supported by machine mode (or SBI interface in RISC-V) * \author Sebastian Sumpf * \author Martin Stein + * \author Stefan Kalkowski * \date 2015-06-14 */ @@ -12,15 +13,15 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _MACHINE_CALL_H_ -#define _MACHINE_CALL_H_ +#ifndef _SRC__LIB__HW__SPEC__RISCV__MACHINE_CALL_H_ +#define _SRC__LIB__HW__SPEC__RISCV__MACHINE_CALL_H_ -/* base-hw includes */ #include -namespace Machine { - - using namespace Kernel; +namespace Hw { + using Kernel::addr_t; + using Kernel::Call_arg; + using Genode::uint64_t; /** * SBI calls to machine mode. @@ -31,13 +32,14 @@ namespace Machine { constexpr Call_arg call_id_set_sys_timer() { return 0x101; } constexpr Call_arg call_id_is_user_mode() { return 0x102; } - inline void put_char(Genode::uint64_t const c) { - call(call_id_put_char(), (Call_arg)c); } + inline void put_char(uint64_t c) { + Kernel::call(call_id_put_char(), (Call_arg)c); } - inline void set_sys_timer(addr_t const t) { - call(call_id_set_sys_timer(), (Call_arg)t); } + inline void set_sys_timer(addr_t t) { + Kernel::call(call_id_set_sys_timer(), (Call_arg)t); } - inline bool is_user_mode() { return call(call_id_is_user_mode()); } + inline bool is_user_mode() { + return Kernel::call(call_id_is_user_mode()); } } -#endif /* _MACHINE_CALL_H_ */ +#endif /* _SRC__LIB__HW__SPEC__RISCV__MACHINE_CALL_H_ */ diff --git a/repos/base-hw/src/lib/hw/spec/riscv/page_table.h b/repos/base-hw/src/lib/hw/spec/riscv/page_table.h new file mode 100644 index 0000000000..0fae1b075e --- /dev/null +++ b/repos/base-hw/src/lib/hw/spec/riscv/page_table.h @@ -0,0 +1,401 @@ +/* + * \brief RISCV Sv39 page table format + * \author Sebastian Sumpf + * \date 2015-08-04 + */ + +/* + * Copyright (C) 2015-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__LIB__HW__SPEC__RISCV__PAGE_TABLE_H_ +#define _SRC__LIB__HW__SPEC__RISCV__PAGE_TABLE_H_ + +#include +#include +#include +#include +#include + +namespace Sv39 +{ + using namespace Genode; + + enum { + SIZE_LOG2_4K = 12, + SIZE_LOG2_2M = 21, + SIZE_LOG2_1G = 30, + SIZE_LOG2_512G = 39, + }; + + struct None { }; + + template + class Level_x_translation_table; + + using Level_3_translation_table = + Level_x_translation_table; + + using Level_2_translation_table = + Level_x_translation_table; + + using Level_1_translation_table = + Level_x_translation_table; + + struct Descriptor; + struct Table_descriptor; + struct Block_descriptor; +} + +struct Sv39::Descriptor : Register<64> +{ + enum Descriptor_type { INVALID, TABLE, BLOCK }; + struct V : Bitfield<0, 1> { }; /* present */ + struct Type : Bitfield<1, 4> /* type and access rights */ + { + enum { + POINTER = 0, + POINTER_GLOBAL = 1, + USER = 4, /* R + 0, RW + 1, RX + 2, RWX + 3 */ + KERNEL = 8, + GLOBAL = 12, + }; + }; + struct Ppn : Bitfield<10, 38> { }; /* physical address 10 bit aligned */ + struct Base : Bitfield<12, 38> { }; /* physical address page aligned */ + + template + static access_t rwx(Hw::Page_flags const &f) + { + if (f.writeable && f.executable) + return BASE + 3; + else if (f.writeable) + return BASE + 1; + else if (f.executable) + return BASE + 2; + else + return BASE; + } + + static access_t permission_bits(Hw::Page_flags const &f) + { + if (f.global) + return rwx(f); + + if (f.privileged) + return rwx(f); + + return rwx(f); + } + + static Descriptor_type type(access_t const v) + { + if (!V::get(v)) return INVALID; + if (Type::get(v) == Type::POINTER || Type::get(v) == Type::POINTER_GLOBAL) + return TABLE; + + return BLOCK; + } + + static bool valid(access_t const v) { + return V::get(v); } +}; + +struct Sv39::Table_descriptor : Descriptor +{ + static access_t create(void * const pa) + { + access_t base = Base::get((access_t)pa); + access_t desc = 0; + + Ppn::set(desc, base); + Type::set(desc, Type::POINTER); + V::set(desc, 1); + + return desc; + } +}; + +struct Sv39::Block_descriptor : Descriptor +{ + static access_t create(Hw::Page_flags const &f, addr_t const pa) + { + access_t base = Base::get(pa); + access_t desc = 0; + + Ppn::set(desc, base); + Type::set(desc, permission_bits(f)); + V::set(desc, 1); + + return desc; + } +}; + +template +class Sv39::Level_x_translation_table +{ + private: + + bool _aligned(addr_t const a, size_t const alignm_log2) { + return a == ((a >> alignm_log2) << alignm_log2); } + + void _translation_added(addr_t, size_t); + + public: + + static constexpr size_t MIN_PAGE_SIZE_LOG2 = SIZE_LOG2_4K; + static constexpr size_t ALIGNM_LOG2 = SIZE_LOG2_4K; + static constexpr size_t MAX_ENTRIES = 1 << (SIZE_LOG2 - BLOCK_SIZE_LOG2); + static constexpr size_t BLOCK_SIZE = 1 << BLOCK_SIZE_LOG2; + static constexpr size_t BLOCK_MASK = ~(BLOCK_SIZE - 1); + static constexpr size_t VM_MASK = (1UL<< SIZE_LOG2_512G) - 1; + + class Misaligned { }; + class Invalid_range { }; + class Double_insertion { }; + + using Allocator = Hw::Page_table_allocator<4096>; + + protected: + + typename Descriptor::access_t _entries[MAX_ENTRIES]; + + /* + * Return how many entries of an alignment fit into region + */ + static constexpr size_t _count(size_t region, size_t alignment) { + return align_addr(region, alignment) / (1UL << alignment); } + + + template + void _range_op(addr_t vo, addr_t pa, size_t size, FUNC &&func) + { + /* sanity check vo bits 38 to 63 must be equal */ + addr_t sanity = vo >> 38; + if (sanity != 0 && sanity != 0x3ffffff) { + Genode::error("invalid virtual address: ", vo); + throw Invalid_range(); + } + + /* clear bits 39 - 63 */ + vo &= VM_MASK; + + for (size_t i = vo >> BLOCK_SIZE_LOG2; size > 0; + i = vo >> BLOCK_SIZE_LOG2) { + addr_t end = (vo + BLOCK_SIZE) & BLOCK_MASK; + size_t sz = min(size, end-vo); + + func(vo, pa, sz, _entries[i]); + + /* flush cached table entry address */ + _translation_added((addr_t)&_entries[i], sz); + + /* check whether we wrap */ + if (end < vo) return; + + size = size - sz; + vo += sz; + pa += sz; + } + } + + template + struct Insert_func + { + Hw::Page_flags const & flags; + Allocator & alloc; + + Insert_func(Hw::Page_flags const & flags, Allocator & alloc) + : flags(flags), alloc(alloc) { } + + void operator () (addr_t const vo, + addr_t const pa, + size_t const size, + typename Descriptor::access_t &desc) + { + using Td = Table_descriptor; + + /* can we insert a whole block? */ + if (!((vo & ~BLOCK_MASK) || (pa & ~BLOCK_MASK) || size < BLOCK_SIZE)) { + typename Descriptor::access_t blk_desc = + Block_descriptor::create(flags, pa); + + if (Descriptor::valid(desc) && desc == blk_desc) + throw Double_insertion(); + + desc = blk_desc; + return; + } + + /* we need to use a next level table */ + switch (Descriptor::type(desc)) { + + case Descriptor::INVALID: /* no entry */ + { + /* create and link next level table */ + E & table = alloc.construct(); + desc = Td::create((void*)alloc.phys_addr(table)); + } + + case Descriptor::TABLE: /* table already available */ + { + /* use allocator to retrieve virt address of table */ + E & table = alloc.virt_addr(Td::Base::bits(Td::Ppn::get(desc))); + table.insert_translation(vo - (vo & BLOCK_MASK), + pa, size, flags, alloc); + break; + } + + case Descriptor::BLOCK: /* there is already a block */ + throw Double_insertion(); + }; + } + }; + + template + struct Remove_func + { + Allocator & alloc; + + Remove_func(Allocator & alloc) : alloc(alloc) { } + + void operator () (addr_t const vo, + addr_t const pa, + size_t const size, + typename Descriptor::access_t &desc) + { + using Td = Table_descriptor; + + switch (Descriptor::type(desc)) { + case Descriptor::TABLE: + { + /* use allocator to retrieve virt address of table */ + E & table = alloc.virt_addr(Td::Base::bits(Td::Ppn::get(desc))); + table.remove_translation(vo - (vo & BLOCK_MASK), size, alloc); + if (!table.empty()) break; + alloc.destruct(table); + } + case Descriptor::BLOCK: + case Descriptor::INVALID: + desc = 0; + } + } + }; + + public: + + Level_x_translation_table() + { + if (!_aligned((addr_t)this, ALIGNM_LOG2)) { + Genode::warning("misaligned address"); + throw Misaligned(); + } + + memset(&_entries, 0, sizeof(_entries)); + } + + bool empty() + { + for (unsigned i = 0; i < MAX_ENTRIES; i++) + if (Descriptor::valid(_entries[i])) + return false; + return true; + } + + /** + * Insert translations into this table + * + * \param vo offset of the virtual region represented + * by the translation within the virtual + * region represented by this table + * \param pa base of the physical backing store + * \param size size of the translated region + * \param flags mapping flags + * \param alloc level allocator + */ + void insert_translation(addr_t vo, addr_t pa, size_t size, + Hw::Page_flags const & flags, + Allocator & alloc ) + { + _range_op(vo, pa, size, Insert_func(flags, alloc)); + } + + /** + * Remove translations that overlap with a given virtual region + * + * \param vo region offset within the tables virtual region + * \param size region size + * \param alloc level allocator + */ + void remove_translation(addr_t vo, size_t size, Allocator & alloc) + { + _range_op(vo, 0, size, Remove_func(alloc)); + } +} __attribute__((aligned(1 << ALIGNM_LOG2))); + +namespace Sv39 { + + /** + * Insert/Remove functor specialization for level 3 + */ + template <> template <> + struct Level_3_translation_table::Insert_func + { + Hw::Page_flags const & flags; + + Insert_func(Hw::Page_flags const & flags, Allocator &) + : flags(flags) { } + + void operator () (addr_t const vo, + addr_t const pa, + size_t const size, + Descriptor::access_t &desc) + { + if ((vo & ~BLOCK_MASK) || (pa & ~BLOCK_MASK) || + size < BLOCK_SIZE) { + Genode::warning("invalid range"); + throw Invalid_range(); + } + + Descriptor::access_t blk_desc = + Block_descriptor::create(flags, pa); + + if (Descriptor::valid(desc) && desc == blk_desc) + throw Double_insertion(); + + desc = blk_desc; + } + }; + + template <> template <> + struct Level_3_translation_table::Remove_func + { + Remove_func(Allocator &) { } + + void operator () (addr_t const vo, + addr_t const pa, + size_t const size, + Descriptor::access_t &desc) { + desc = 0; } + }; +} + +namespace Hw { + + struct Page_table : Sv39::Level_1_translation_table + { + enum { + TABLE_LEVEL_X_SIZE_LOG2 = Sv39::SIZE_LOG2_4K, + CORE_VM_AREA_SIZE = 128 * 1024 * 1024, + CORE_TRANS_TABLE_COUNT = + _count(CORE_VM_AREA_SIZE, Sv39::SIZE_LOG2_1G) + + _count(CORE_VM_AREA_SIZE, Sv39::SIZE_LOG2_2M), + }; + + }; +} + +#endif /* _SRC__LIB__HW__SPEC__RISCV__PAGE_TABLE_H_ */ diff --git a/repos/base-hw/src/lib/hw/spec/riscv/uart.h b/repos/base-hw/src/lib/hw/spec/riscv/uart.h new file mode 100644 index 0000000000..8d7d13af1d --- /dev/null +++ b/repos/base-hw/src/lib/hw/spec/riscv/uart.h @@ -0,0 +1,40 @@ +/* + * \brief UART output driver for RISCV + * \author Sebastian Sumpf + * \author Stefan Kalkowski + * \date 2015-06-02 + */ + +/* + * Copyright (C) 2015-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__LIB__HW__SPEC__RISCV__UART_H_ +#define _SRC__LIB__HW__SPEC__RISCV__UART_H_ + +#include +#include + +namespace Hw { struct Riscv_uart; } + +struct Hw::Riscv_uart +{ + void put_char(char const c) + { + struct Arg : Genode::Register<64> + { + struct Char : Bitfield<0, 8> { }; + struct Write_cmd : Bitfield<48, 1> { }; + struct Stdout : Bitfield<56, 1> { }; + }; + + Hw::put_char(Arg::Char::bits(c) | + Arg::Stdout::bits(1) | + Arg::Write_cmd::bits(1)); + } +}; + +#endif /* _SRC__LIB__HW__SPEC__RISCV__UART_H_ */ diff --git a/repos/base-hw/src/lib/hw/spec/x86_64/cpu.h b/repos/base-hw/src/lib/hw/spec/x86_64/cpu.h new file mode 100644 index 0000000000..1639018ffd --- /dev/null +++ b/repos/base-hw/src/lib/hw/spec/x86_64/cpu.h @@ -0,0 +1,83 @@ +/* + * \brief x86_64 CPU definitions + * \author Stefan Kalkowski + * \date 2017-04-07 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__LIB__HW__SPEC__X86_64__CPU_H_ +#define _SRC__LIB__HW__SPEC__X86_64__CPU_H_ + +#include + +namespace Hw { struct X86_64_cpu; } + +struct Hw::X86_64_cpu +{ + X86_64_CR_REGISTER(Cr0, cr0, + struct Pe : Bitfield< 0, 1> { }; /* Protection Enable */ + struct Mp : Bitfield< 1, 1> { }; /* Monitor Coprocessor */ + struct Em : Bitfield< 2, 1> { }; /* Emulation */ + struct Ts : Bitfield< 3, 1> { }; /* Task Switched */ + struct Et : Bitfield< 4, 1> { }; /* Extension Type */ + struct Ne : Bitfield< 5, 1> { }; /* Numeric Error */ + struct Wp : Bitfield<16, 1> { }; /* Write Protect */ + struct Am : Bitfield<18, 1> { }; /* Alignment Mask */ + struct Nw : Bitfield<29, 1> { }; /* Not Write-through */ + struct Cd : Bitfield<30, 1> { }; /* Cache Disable */ + struct Pg : Bitfield<31, 1> { }; /* Paging */ + ); + + /** + * Control register 2: Page-fault linear address + * + * See Intel SDM Vol. 3A, section 2.5. + */ + X86_64_CR_REGISTER(Cr2, cr2, + struct Addr : Bitfield<0, 63> { }; + ); + + /** + * Control register 3: Page-Directory base register + * + * See Intel SDM Vol. 3A, section 2.5. + */ + X86_64_CR_REGISTER(Cr3, cr3, + struct Pwt : Bitfield<3,1> { }; /* Page-level write-through */ + struct Pcd : Bitfield<4,1> { }; /* Page-level cache disable */ + struct Pdb : Bitfield<12, 36> { }; /* Page-directory base address */ + ); + + X86_64_CR_REGISTER(Cr4, cr4, + struct Vme : Bitfield< 0, 1> { }; /* Virtual-8086 Mode Extensions */ + struct Pvi : Bitfield< 1, 1> { }; /* Protected-Mode Virtual IRQs */ + struct Tsd : Bitfield< 2, 1> { }; /* Time Stamp Disable */ + struct De : Bitfield< 3, 1> { }; /* Debugging Exceptions */ + struct Pse : Bitfield< 4, 1> { }; /* Page Size Extensions */ + struct Pae : Bitfield< 5, 1> { }; /* Physical Address Extension */ + struct Mce : Bitfield< 6, 1> { }; /* Machine-Check Enable */ + struct Pge : Bitfield< 7, 1> { }; /* Page Global Enable */ + struct Pce : Bitfield< 8, 1> { }; /* Performance-Monitoring Counter + Enable*/ + struct Osfxsr : Bitfield< 9, 1> { }; /* OS Support for FXSAVE and + FXRSTOR instructions*/ + struct Osxmmexcpt : Bitfield<10, 1> { }; /* OS Support for Unmasked + SIMD/FPU Exceptions */ + struct Vmxe : Bitfield<13, 1> { }; /* VMX Enable */ + struct Smxe : Bitfield<14, 1> { }; /* SMX Enable */ + struct Fsgsbase : Bitfield<16, 1> { }; /* FSGSBASE-Enable */ + struct Pcide : Bitfield<17, 1> { }; /* PCIDE Enable */ + struct Osxsave : Bitfield<18, 1> { }; /* XSAVE and Processor Extended + States-Enable */ + struct Smep : Bitfield<20, 1> { }; /* SMEP Enable */ + struct Smap : Bitfield<21, 1> { }; /* SMAP Enable */ + ); +}; + +#endif /* _SRC__LIB__HW__SPEC__X86_64__CPU_H_ */ diff --git a/repos/base-hw/src/lib/hw/spec/x86_64/gdt.s b/repos/base-hw/src/lib/hw/spec/x86_64/gdt.s new file mode 100644 index 0000000000..4eec155650 --- /dev/null +++ b/repos/base-hw/src/lib/hw/spec/x86_64/gdt.s @@ -0,0 +1,60 @@ +/* + * \brief GDT macro + * \author Martin Stein + * \author Stefan Kalkowski + * \date 2017-04-17 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +/****************************************** + ** Global Descriptor Table (GDT) ** + ** See Intel SDM Vol. 3A, section 3.5.1 ** + ******************************************/ + +.macro _define_gdt tss_address + .align 4 + .space 2 + .global _mt_gdt_ptr + .global _mt_gdt_start + _mt_gdt_ptr: + .word _mt_gdt_end - _mt_gdt_start - 1 /* limit */ + .long _mt_gdt_start /* base address */ + + .set TSS_LIMIT, 0x68 + .set TSS_TYPE, 0x8900 + + .align 8 + _mt_gdt_start: + /* Null descriptor */ + .quad 0 + /* 64-bit code segment descriptor */ + .long 0 + /* GDTE_LONG | GDTE_PRESENT | GDTE_CODE | GDTE_NON_SYSTEM */ + .long 0x209800 + /* 64-bit data segment descriptor */ + .long 0 + /* GDTE_LONG | GDTE_PRESENT | GDTE_TYPE_DATA_A | GDTE_TYPE_DATA_W | GDTE_NON_SYSTEM */ + .long 0x209300 + /* 64-bit user code segment descriptor */ + .long 0 + /* GDTE_LONG | GDTE_PRESENT | GDTE_CODE | GDTE_NON_SYSTEM */ + .long 0x20f800 + /* 64-bit user data segment descriptor */ + .long 0 + /* GDTE_LONG | GDTE_PRESENT | GDTE_TYPE_DATA_A | GDTE_TYPE_DATA_W | GDTE_NON_SYSTEM */ + .long 0x20f300 + /* Task segment descriptor */ + .long (\tss_address & 0xffff) << 16 | TSS_LIMIT + /* GDTE_PRESENT | GDTE_SYS_TSS */ + .long ((\tss_address >> 24) & 0xff) << 24 | ((\tss_address >> 16) & 0xff) | TSS_TYPE + .long \tss_address >> 32 + .long 0 + .global _mt_gdt_end + _mt_gdt_end: +.endm diff --git a/repos/base-hw/src/lib/hw/spec/x86_64/page_table.h b/repos/base-hw/src/lib/hw/spec/x86_64/page_table.h new file mode 100644 index 0000000000..02692b7a4f --- /dev/null +++ b/repos/base-hw/src/lib/hw/spec/x86_64/page_table.h @@ -0,0 +1,689 @@ +/* + * \brief x86_64 page table definitions + * \author Adrian-Ken Rueegsegger + * \date 2015-02-06 + */ + +/* + * Copyright (C) 2015-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__LIB__HW__SPEC__X86_64__PAGE_TABLE_H_ +#define _SRC__LIB__HW__SPEC__X86_64__PAGE_TABLE_H_ + +#include +#include +#include +#include +#include +#include + +namespace Hw +{ + + /** + * IA-32e paging translates 48-bit linear addresses to 52-bit physical + * addresses. Translation structures are hierarchical and four levels + * deep. + * + * For detailed information refer to Intel SDM Vol. 3A, section 4.5. + */ + + enum { + SIZE_LOG2_4KB = 12, + SIZE_LOG2_2MB = 21, + SIZE_LOG2_1GB = 30, + SIZE_LOG2_512GB = 39, + SIZE_LOG2_256TB = 48, + }; + + class Level_4_translation_table; + class Pml4_table; + class Page_table; + + /** + * IA-32e page directory template. + * + * Page directories can refer to paging structures of the next higher level + * or directly map page frames by using large page mappings. + * + * \param PAGE_SIZE_LOG2 virtual address range size in log2 + * of a single table entry + * \param SIZE_LOG2 virtual address range size in log2 of whole table + */ + template + class Page_directory; + + using Level_3_translation_table = + Page_directory; + using Level_2_translation_table = + Page_directory; + + /** + * IA-32e common descriptor. + * + * Table entry containing descriptor fields common to all four levels. + */ + struct Common_descriptor : Genode::Register<64> + { + struct P : Bitfield<0, 1> { }; /* present */ + struct Rw : Bitfield<1, 1> { }; /* read/write */ + struct Us : Bitfield<2, 1> { }; /* user/supervisor */ + struct Pwt : Bitfield<3, 1> { }; /* write-through */ + struct Pcd : Bitfield<4, 1> { }; /* cache disable */ + struct A : Bitfield<5, 1> { }; /* accessed */ + struct D : Bitfield<6, 1> { }; /* dirty */ + struct Xd : Bitfield<63, 1> { }; /* execute-disable */ + + static bool present(access_t const v) { return P::get(v); } + + static access_t create(Page_flags const &flags) + { + return P::bits(1) + | Rw::bits(flags.writeable) + | Us::bits(!flags.privileged) + | Xd::bits(!flags.executable); + } + + /** + * Return descriptor value with cleared accessed and dirty flags. These + * flags can be set by the MMU. + */ + static access_t clear_mmu_flags(access_t value) + { + A::clear(value); + D::clear(value); + return value; + } + + /** + * Merge access rights of descriptor with given flags. + */ + static void merge_access_rights(access_t &desc, + Page_flags const &flags) + { + Rw::set(desc, Rw::get(desc) | flags.writeable); + Us::set(desc, Us::get(desc) | !flags.privileged); + Xd::set(desc, Xd::get(desc) & !flags.executable); + } + }; +} + +class Hw::Level_4_translation_table +{ + private: + + static constexpr size_t PAGE_SIZE_LOG2 = SIZE_LOG2_4KB; + static constexpr size_t SIZE_LOG2 = SIZE_LOG2_2MB; + static constexpr size_t MAX_ENTRIES = 1UL << (SIZE_LOG2-PAGE_SIZE_LOG2); + static constexpr size_t PAGE_SIZE = 1UL << PAGE_SIZE_LOG2; + static constexpr size_t PAGE_MASK = ~((1UL << PAGE_SIZE_LOG2) - 1); + + class Misaligned {}; + class Invalid_range {}; + class Double_insertion {}; + + struct Descriptor : Common_descriptor + { + using Common = Common_descriptor; + + struct Pat : Bitfield<7, 1> { }; /* page attribute table */ + struct G : Bitfield<8, 1> { }; /* global */ + struct Pa : Bitfield<12, 36> { }; /* physical address */ + struct Mt : Genode::Bitset_3 { }; /* memory type */ + + static access_t create(Page_flags const &flags, addr_t const pa) + { + /* XXX: Set memory type depending on active PAT */ + return Common::create(flags) + | G::bits(flags.global) + | Pa::masked(pa); + } + }; + + typename Descriptor::access_t _entries[MAX_ENTRIES]; + + struct Insert_func + { + Page_flags const & flags; + + Insert_func(Page_flags const & flags) + : flags(flags) { } + + void operator () (addr_t const vo, addr_t const pa, + size_t const size, + Descriptor::access_t &desc) + { + if ((vo & ~PAGE_MASK) || (pa & ~PAGE_MASK) || + size < PAGE_SIZE) + { + throw Invalid_range(); + } + Descriptor::access_t table_entry = + Descriptor::create(flags, pa); + + if (Descriptor::present(desc) && + Descriptor::clear_mmu_flags(desc) != table_entry) + { + throw Double_insertion(); + } + desc = table_entry; + } + }; + + struct Remove_func + { + void operator () (addr_t const vo, addr_t const pa, + size_t const size, + Descriptor::access_t &desc) + { desc = 0; } + }; + + template + void _range_op(addr_t vo, addr_t pa, size_t size, FUNC &&func) + { + for (size_t i = vo >> PAGE_SIZE_LOG2; size > 0; + i = vo >> PAGE_SIZE_LOG2) { + assert (i < MAX_ENTRIES); + addr_t end = (vo + PAGE_SIZE) & PAGE_MASK; + size_t sz = Genode::min(size, end-vo); + + func(vo, pa, sz, _entries[i]); + + /* check whether we wrap */ + if (end < vo) return; + + size = size - sz; + vo += sz; + pa += sz; + } + } + + public: + + using Allocator = Page_table_allocator<1UL << SIZE_LOG2_4KB>; + + static constexpr size_t MIN_PAGE_SIZE_LOG2 = SIZE_LOG2_4KB; + static constexpr size_t ALIGNM_LOG2 = SIZE_LOG2_4KB; + + /** + * IA-32e page table (Level 4) + * + * A page table consists of 512 entries that each maps a 4KB page + * frame. For further details refer to Intel SDM Vol. 3A, table 4-19. + */ + Level_4_translation_table() + { + if (!aligned(this, ALIGNM_LOG2)) throw Misaligned(); + Genode::memset(&_entries, 0, sizeof(_entries)); + } + + /** + * Returns True if table does not contain any page mappings. + */ + bool empty() + { + for (unsigned i = 0; i < MAX_ENTRIES; i++) + if (Descriptor::present(_entries[i])) + return false; + return true; + } + + /** + * Insert translations into this table + * + * \param vo offset of the virtual region represented + * by the translation within the virtual + * region represented by this table + * \param pa base of the physical backing store + * \param size size of the translated region + * \param flags mapping flags + * \param alloc second level translation table allocator + */ + void insert_translation(addr_t vo, addr_t pa, size_t size, + Page_flags const & flags, Allocator &) + { + this->_range_op(vo, pa, size, Insert_func(flags)); + } + + /** + * Remove translations that overlap with a given virtual region + * + * \param vo region offset within the tables virtual region + * \param size region size + * \param alloc second level translation table allocator + */ + void remove_translation(addr_t vo, size_t size, Allocator &) + { + this->_range_op(vo, 0, size, Remove_func()); + } +} __attribute__((aligned(1 << ALIGNM_LOG2))); + + +template +class Hw::Page_directory +{ + private: + + static constexpr size_t MAX_ENTRIES = 1UL << (SIZE_LOG2-PAGE_SIZE_LOG2); + static constexpr size_t PAGE_SIZE = 1UL << PAGE_SIZE_LOG2; + static constexpr size_t PAGE_MASK = ~((1UL << PAGE_SIZE_LOG2) - 1); + + using Allocator = Page_table_allocator<1UL << SIZE_LOG2_4KB>; + + class Misaligned {}; + class Invalid_range {}; + class Double_insertion {}; + + struct Base_descriptor : Common_descriptor + { + using Common = Common_descriptor; + + struct Ps : Common::template Bitfield<7, 1> { }; /* page size */ + + static bool maps_page(access_t const v) { return Ps::get(v); } + }; + + struct Page_descriptor : Base_descriptor + { + using Base = Base_descriptor; + + /** + * Global attribute + */ + struct G : Base::template Bitfield<8, 1> { }; + + /** + * Page attribute table + */ + struct Pat : Base::template Bitfield<12, 1> { }; + + /** + * Physical address + */ + struct Pa : Base::template Bitfield { }; + + /** + * Memory type + */ + struct Mt : Base::template Bitset_3 { }; + + static typename Base::access_t create(Page_flags const &flags, + addr_t const pa) + { + /* XXX: Set memory type depending on active PAT */ + return Base::create(flags) + | Base::Ps::bits(1) + | G::bits(flags.global) + | Pa::masked(pa); + } + }; + + struct Table_descriptor : Base_descriptor + { + using Base = Base_descriptor; + + /** + * Physical address + */ + struct Pa : Base::template Bitfield<12, 36> { }; + + /** + * Memory types + */ + struct Mt : Base::template Bitset_2 { }; + + static typename Base::access_t create(Page_flags const &flags, + addr_t const pa) + { + /* XXX: Set memory type depending on active PAT */ + return Base::create(flags) | Pa::masked(pa); + } + }; + + typename Base_descriptor::access_t _entries[MAX_ENTRIES]; + + struct Insert_func + { + using Descriptor = Base_descriptor; + + Page_flags const & flags; + Allocator & alloc; + + Insert_func(Page_flags const & flags, + Allocator & alloc) + : flags(flags), alloc(alloc) { } + + void operator () (addr_t const vo, addr_t const pa, + size_t const size, + typename Descriptor::access_t &desc) + { + using Td = Table_descriptor; + using access_t = typename Descriptor::access_t; + + /* can we insert a large page mapping? */ + if (!((vo & ~PAGE_MASK) || (pa & ~PAGE_MASK) || + size < PAGE_SIZE)) + { + access_t table_entry = Page_descriptor::create(flags, pa); + + if (Descriptor::present(desc) && + Descriptor::clear_mmu_flags(desc) != table_entry) { + throw Double_insertion(); } + + desc = table_entry; + return; + } + + /* we need to use a next level table */ + if (!Descriptor::present(desc)) { + + /* create and link next level table */ + ENTRY & table = alloc.construct(); + desc = (access_t) Td::create(flags, alloc.phys_addr(table)); + + } else if (Descriptor::maps_page(desc)) { + throw Double_insertion(); + } else { + Descriptor::merge_access_rights(desc, flags); + } + + /* insert translation */ + ENTRY & table = alloc.virt_addr(Td::Pa::masked(desc)); + table.insert_translation(vo - (vo & PAGE_MASK), pa, size, + flags, alloc); + } + }; + + struct Remove_func + { + Allocator & alloc; + + Remove_func(Allocator & alloc) : alloc(alloc) { } + + void operator () (addr_t const vo, addr_t const pa, + size_t const size, + typename Base_descriptor::access_t &desc) + { + if (Base_descriptor::present(desc)) { + if (Base_descriptor::maps_page(desc)) { + desc = 0; + } else { + using Td = Table_descriptor; + + /* use allocator to retrieve virt address of table */ + ENTRY & table = alloc.virt_addr(Td::Pa::masked(desc)); + addr_t const table_vo = vo - (vo & PAGE_MASK); + table.remove_translation(table_vo, size, alloc); + if (table.empty()) { + alloc.destruct(table); + desc = 0; + } + } + } + } + }; + + template + void _range_op(addr_t vo, addr_t pa, size_t size, FUNC &&func) + { + for (size_t i = vo >> PAGE_SIZE_LOG2; size > 0; + i = vo >> PAGE_SIZE_LOG2) + { + assert (i < MAX_ENTRIES); + addr_t end = (vo + PAGE_SIZE) & PAGE_MASK; + size_t sz = Genode::min(size, end-vo); + + func(vo, pa, sz, _entries[i]); + + /* check whether we wrap */ + if (end < vo) return; + + size = size - sz; + vo += sz; + pa += sz; + } + } + + public: + + static constexpr size_t MIN_PAGE_SIZE_LOG2 = SIZE_LOG2_4KB; + static constexpr size_t ALIGNM_LOG2 = SIZE_LOG2_4KB; + + Page_directory() + { + if (!aligned(this, ALIGNM_LOG2)) throw Misaligned(); + Genode::memset(&_entries, 0, sizeof(_entries)); + } + + /** + * Returns True if table does not contain any page mappings. + * + * \return false if an entry is present, True otherwise + */ + bool empty() + { + for (unsigned i = 0; i < MAX_ENTRIES; i++) + if (Base_descriptor::present(_entries[i])) + return false; + return true; + } + + /** + * Insert translations into this table + * + * \param vo offset of the virtual region represented + * by the translation within the virtual + * region represented by this table + * \param pa base of the physical backing store + * \param size size of the translated region + * \param flags mapping flags + * \param alloc second level translation table allocator + */ + void insert_translation(addr_t vo, addr_t pa, size_t size, + Page_flags const & flags, + Allocator & alloc) { + _range_op(vo, pa, size, Insert_func(flags, alloc)); } + + /** + * Remove translations that overlap with a given virtual region + * + * \param vo region offset within the tables virtual region + * \param size region size + * \param alloc second level translation table allocator + */ + void remove_translation(addr_t vo, size_t size, Allocator & alloc) { + _range_op(vo, 0, size, Remove_func(alloc)); } +} __attribute__((aligned(1 << ALIGNM_LOG2))); + + +class Hw::Pml4_table +{ + public: + + using Allocator = Page_table_allocator<1UL << SIZE_LOG2_4KB>; + + private: + + static constexpr size_t PAGE_SIZE_LOG2 = SIZE_LOG2_512GB; + static constexpr size_t SIZE_LOG2 = SIZE_LOG2_256TB; + static constexpr size_t MAX_ENTRIES = 512; + static constexpr size_t PAGE_SIZE = 1UL << PAGE_SIZE_LOG2; + static constexpr size_t PAGE_MASK = ~((1UL << PAGE_SIZE_LOG2) - 1); + + class Misaligned {}; + class Invalid_range {}; + + struct Descriptor : Common_descriptor + { + struct Pa : Bitfield<12, SIZE_LOG2> { }; /* physical address */ + struct Mt : Genode::Bitset_2 { }; /* memory type */ + + static access_t create(Page_flags const &flags, addr_t const pa) + { + /* XXX: Set memory type depending on active PAT */ + return Common_descriptor::create(flags) | Pa::masked(pa); + } + }; + + typename Descriptor::access_t _entries[MAX_ENTRIES]; + + using ENTRY = Level_2_translation_table; + + struct Insert_func + { + Page_flags const & flags; + Allocator & alloc; + + Insert_func(Page_flags const & flags, + Allocator & alloc) + : flags(flags), alloc(alloc) { } + + void operator () (addr_t const vo, addr_t const pa, + size_t const size, + Descriptor::access_t &desc) + { + /* we need to use a next level table */ + if (!Descriptor::present(desc)) { + /* create and link next level table */ + ENTRY & table = alloc.construct(); + desc = Descriptor::create(flags, alloc.phys_addr(table)); + } else { + Descriptor::merge_access_rights(desc, flags); + } + + /* insert translation */ + ENTRY & table = alloc.virt_addr(Descriptor::Pa::masked(desc)); + addr_t const table_vo = vo - (vo & PAGE_MASK); + table.insert_translation(table_vo, pa, size, flags, alloc); + } + }; + + struct Remove_func + { + Allocator & alloc; + + Remove_func(Allocator & alloc) : alloc(alloc) { } + + void operator () (addr_t const vo, addr_t const pa, + size_t const size, + Descriptor::access_t &desc) + { + if (Descriptor::present(desc)) { + /* use allocator to retrieve virt address of table */ + ENTRY & table = alloc.virt_addr(Descriptor::Pa::masked(desc)); + addr_t const table_vo = vo - (vo & PAGE_MASK); + table.remove_translation(table_vo, size, alloc); + if (table.empty()) { + alloc.destruct(table); + desc = 0; + } + } + } + }; + + template + void _range_op(addr_t vo, addr_t pa, size_t size, FUNC &&func) + { + for (size_t i = vo >> PAGE_SIZE_LOG2; size > 0; + i = vo >> PAGE_SIZE_LOG2) { + assert (i < MAX_ENTRIES); + addr_t end = (vo + PAGE_SIZE) & PAGE_MASK; + size_t sz = Genode::min(size, end-vo); + + func(vo, pa, sz, _entries[i]); + + /* check whether we wrap */ + if (end < vo) return; + + size = size - sz; + vo += sz; + pa += sz; + } + } + + protected: + + /** + * Return how many entries of an alignment fit into region + */ + static constexpr size_t _count(size_t region, size_t alignment) + { + return Genode::align_addr(region, alignment) + / (1UL << alignment); + } + + public: + + static constexpr size_t MIN_PAGE_SIZE_LOG2 = SIZE_LOG2_4KB; + static constexpr size_t ALIGNM_LOG2 = SIZE_LOG2_4KB; + + Pml4_table() + { + if (!aligned(this, ALIGNM_LOG2)) throw Misaligned(); + Genode::memset(&_entries, 0, sizeof(_entries)); + } + + /** + * Returns True if table does not contain any page mappings. + * + * \return false if an entry is present, True otherwise + */ + bool empty() + { + for (unsigned i = 0; i < MAX_ENTRIES; i++) + if (Descriptor::present(_entries[i])) + return false; + return true; + } + + /** + * Insert translations into this table + * + * \param vo offset of the virtual region represented + * by the translation within the virtual + * region represented by this table + * \param pa base of the physical backing store + * \param size size of the translated region + * \param flags mapping flags + * \param alloc second level translation table allocator + */ + void insert_translation(addr_t vo, addr_t pa, size_t size, + Page_flags const & flags, Allocator & alloc) { + _range_op(vo, pa, size, Insert_func(flags, alloc)); } + + /** + * Remove translations that overlap with a given virtual region + * + * \param vo region offset within the tables virtual region + * \param size region size + * \param alloc second level translation table allocator + */ + void remove_translation(addr_t vo, size_t size, Allocator & alloc) { + _range_op(vo, 0, size, Remove_func(alloc)); } +} __attribute__((aligned(1 << ALIGNM_LOG2))); + + +class Hw::Page_table : public Pml4_table +{ + public: + + enum { + TABLE_LEVEL_X_SIZE_LOG2 = SIZE_LOG2_4KB, + CORE_VM_AREA_SIZE = 1024 * 1024 * 1024, + CORE_TRANS_TABLE_COUNT = + _count(CORE_VM_AREA_SIZE, SIZE_LOG2_512GB) + + _count(CORE_VM_AREA_SIZE, SIZE_LOG2_1GB) + + _count(CORE_VM_AREA_SIZE, SIZE_LOG2_2MB) + }; +}; + +#endif /* _SRC__LIB__HW__SPEC__X86_64__PAGE_TABLE_H_ */ diff --git a/repos/base-hw/src/lib/hw/spec/x86_64/register_macros.h b/repos/base-hw/src/lib/hw/spec/x86_64/register_macros.h new file mode 100644 index 0000000000..274ebe6a97 --- /dev/null +++ b/repos/base-hw/src/lib/hw/spec/x86_64/register_macros.h @@ -0,0 +1,35 @@ +/* + * \brief CPU register macros for x86_64 + * \author Stefan Kalkowski + * \date 2017-04-07 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__LIB__HW__SPEC__X86_64__REGISTER_MACROS_H_ +#define _SRC__LIB__HW__SPEC__X86_64__REGISTER_MACROS_H_ + +#include + +#define X86_64_CR_REGISTER(name, cr, ...) \ + struct name : Genode::Register<64> \ + { \ + static access_t read() \ + { \ + access_t v; \ + asm volatile ("mov %%" #cr ", %0" : "=r" (v) :: ); \ + return v; \ + } \ + \ + static void write(access_t const v) { \ + asm volatile ("mov %0, %%" #cr :: "r" (v) : ); } \ + \ + __VA_ARGS__; \ + }; + +#endif /* _SRC__LIB__HW__SPEC__X86_64__REGISTER_MACROS_H_ */ diff --git a/repos/base-hw/src/lib/hw/spec/x86_64/x86_64.h b/repos/base-hw/src/lib/hw/spec/x86_64/x86_64.h new file mode 100644 index 0000000000..8bbbd40377 --- /dev/null +++ b/repos/base-hw/src/lib/hw/spec/x86_64/x86_64.h @@ -0,0 +1,32 @@ +/* + * \brief Definitions common to all x86_64 CPUs + * \author Stefan Kalkowski + * \date 2017-04-10 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__LIB__HW__SPEC__X86_64__X86_64_H_ +#define _SRC__LIB__HW__SPEC__X86_64__X86_64_H_ + +#include + +namespace Hw { struct Cpu_memory_map; } + + +struct Hw::Cpu_memory_map +{ + enum { + MMIO_LAPIC_BASE = 0xfee00000, + MMIO_LAPIC_SIZE = 0x1000, + MMIO_IOAPIC_BASE = 0xfec00000, + MMIO_IOAPIC_SIZE = 0x1000, + }; +}; + +#endif /* _SRC__LIB__HW__SPEC__X86_64__X86_64_H_ */ diff --git a/repos/base-hw/src/lib/hw/spin_lock.h b/repos/base-hw/src/lib/hw/spin_lock.h new file mode 100644 index 0000000000..eeff5a87c2 --- /dev/null +++ b/repos/base-hw/src/lib/hw/spin_lock.h @@ -0,0 +1,49 @@ +/* + * \brief Spin lock used to synchronize different CPU cores + * \author Martin Stein + * \author Stefan Kalkowski + * \date 2012-11-30 + */ + +/* + * Copyright (C) 2012-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__LIB__HW__SPIN_LOCK_H_ +#define _SRC__LIB__HW__SPIN_LOCK_H_ + +#include +#include +#include + +namespace Hw { class Spin_lock; } + +class Hw::Spin_lock +{ + private: + + enum State { UNLOCKED, LOCKED }; + + State volatile _locked = UNLOCKED; + + public: + + void lock() + { + while (!Genode::cmpxchg((volatile int*)&_locked, UNLOCKED, LOCKED)) + ; + } + + void unlock() + { + Genode::memory_barrier(); + _locked = UNLOCKED; + } + + using Guard = Genode::Lock_guard; +}; + +#endif /* _SRC__LIB__HW__SPIN_LOCK_H_ */ diff --git a/repos/base-hw/src/lib/hw/util.h b/repos/base-hw/src/lib/hw/util.h new file mode 100644 index 0000000000..336e5fd2d7 --- /dev/null +++ b/repos/base-hw/src/lib/hw/util.h @@ -0,0 +1,69 @@ +/* + * \brief Common utilities + * \author Martin Stein + * \author Stefan Kalkowski + * \date 2012-01-02 + */ + +/* + * Copyright (C) 2012-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _SRC__LIB__HW__UTIL_H_ +#define _SRC__LIB__HW__UTIL_H_ + +#include + +namespace Hw +{ + using Genode::addr_t; + using Genode::size_t; + using Genode::get_page_size; + using Genode::get_page_size_log2; + + /** + * Get the base mask for the minimal supported page-size + */ + constexpr addr_t get_page_mask() { return ~(get_page_size() - 1UL); } + + /** + * Round down to the minimal page-size alignment + */ + constexpr addr_t trunc_page(addr_t addr) { + return addr & get_page_mask(); } + + /** + * Round up to the minimal page-size alignment + */ + constexpr addr_t round_page(addr_t addr) + { return trunc_page(addr + get_page_size() - 1UL); } + + /** + * Return an address rounded down to a specific alignment + * + * \param addr original address + * \param alignm_log2 log2 of the required alignment + */ + constexpr addr_t trunc(addr_t addr, addr_t alignm_log2) { + return (addr >> alignm_log2) << alignm_log2; } + + /** + * Return wether a pointer fullfills an alignment + * + * \param p pointer + * \param alignm_log2 log2 of the required alignment + */ + constexpr bool aligned(void * const p, addr_t alignm_log2) { + return (addr_t)p == trunc((addr_t)p, alignm_log2); } + + /** + * Round up to a specific alignment + */ + constexpr addr_t round(addr_t addr, unsigned alignm_log2) { + return trunc(addr + (1UL << alignm_log2) - 1UL, alignm_log2); } +} + +#endif /* _SRC__LIB__HW__UTIL_H_ */ diff --git a/repos/base-hw/src/lib/muen/muschedinfo.h b/repos/base-hw/src/lib/muen/muschedinfo.h index 8824788f4d..b368dd3fb0 100644 --- a/repos/base-hw/src/lib/muen/muschedinfo.h +++ b/repos/base-hw/src/lib/muen/muschedinfo.h @@ -8,7 +8,7 @@ * Copyright (C) 2016 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. + * under the terms of the GNU Affero General Public License version 3. */ #ifndef _BASE__MUEN__MUSCHEDINFO_H_ diff --git a/repos/base/include/spec/imx/drivers/uart_base.h b/repos/base/include/spec/imx/drivers/uart_base.h index 641bf8a7ce..d15feb78f2 100644 --- a/repos/base/include/spec/imx/drivers/uart_base.h +++ b/repos/base/include/spec/imx/drivers/uart_base.h @@ -233,7 +233,7 @@ class Genode::Imx_uart_base : Mmio /** * Transmit character 'c' without care about its type */ - inline void _put_char(char const c) + void _put_char(char c) { while (!read()) ; write(c); @@ -246,7 +246,7 @@ class Genode::Imx_uart_base : Mmio * * \param base device MMIO base */ - explicit Imx_uart_base(addr_t const base) : Mmio(base) + Imx_uart_base(addr_t base, uint32_t, uint32_t) : Mmio(base) { write(Cr1::init_value()); write(Cr2::init_value()); @@ -257,7 +257,7 @@ class Genode::Imx_uart_base : Mmio /** * Print character 'c' through the UART */ - inline void put_char(char const c) + void put_char(char c) { enum { ASCII_LINE_FEED = 10, ASCII_CARRIAGE_RETURN = 13 }; diff --git a/tool/create_builddir b/tool/create_builddir index 8ca62b0bc7..1618d5e84d 100755 --- a/tool/create_builddir +++ b/tool/create_builddir @@ -225,7 +225,7 @@ SPECS(rpi) := rpi SPECS(arndale) := arndale SPECS(imx53_qsb) := imx53_qsb SPECS(imx53_qsb_tz) := imx53_qsb trustzone -SPECS(usb_armory) := usb_armory +SPECS(usb_armory) := usb_armory trustzone SPECS(wand_quad) := wand_quad SPECS(odroid_xu) := odroid_xu SPECS(odroid_x2) := odroid_x2