From 34af60da11a4aab8f43163dcb31e94b5a13351e2 Mon Sep 17 00:00:00 2001 From: Sebastian Sumpf Date: Mon, 14 Jan 2013 12:18:53 +0100 Subject: [PATCH] FOC/L4RE: Upstream revision 42 --- kernel/fiasco/Makefile | 4 +- kernel/fiasco/src/Kconfig | 17 +- kernel/fiasco/src/Makeconf | 2 + kernel/fiasco/src/Makefile | 17 +- kernel/fiasco/src/Makefile.sub2 | 25 +- kernel/fiasco/src/Modules.amd64 | 19 +- kernel/fiasco/src/Modules.arm | 5 +- kernel/fiasco/src/Modules.generic | 7 +- kernel/fiasco/src/Modules.ia32 | 19 +- kernel/fiasco/src/Modules.ppc32 | 4 +- kernel/fiasco/src/Modules.sparc | 4 +- kernel/fiasco/src/Modules.ux | 14 +- kernel/fiasco/src/abi/l4_buf_desc.cpp | 58 +- kernel/fiasco/src/abi/l4_fpage.cpp | 54 +- kernel/fiasco/src/abi/l4_msg_item.cpp | 64 +- kernel/fiasco/src/abi/l4_types.cpp | 76 +- kernel/fiasco/src/doxygen.conf | 1889 ++++++++++++----- .../fiasco/src/drivers/arm/processor-arm.cpp | 6 +- kernel/fiasco/src/drivers/pci.cpp | 155 +- kernel/fiasco/src/drivers/uart.cpp | 2 +- kernel/fiasco/src/jdb/arm/jdb_extensions.cpp | 21 +- kernel/fiasco/src/jdb/arm/jdb_tcb-arm.cpp | 6 +- kernel/fiasco/src/jdb/ia32/jdb-ia32-amd64.cpp | 2 +- .../fiasco/src/jdb/ia32/jdb-int3-ia32-ux.cpp | 19 +- kernel/fiasco/src/jdb/ia32/jdb_io_ports.cpp | 8 +- .../fiasco/src/jdb/ia32/jdb_kern_info-pci.cpp | 49 +- .../src/jdb/ia32/jdb_trace_set-ia32-ux.cpp | 4 +- kernel/fiasco/src/jdb/jdb.cpp | 2 +- kernel/fiasco/src/jdb/jdb_dbinfo.cpp | 4 +- kernel/fiasco/src/jdb/jdb_kern_info-bench.cpp | 2 +- kernel/fiasco/src/jdb/jdb_kobject_names.cpp | 4 +- kernel/fiasco/src/jdb/jdb_mapdb.cpp | 9 +- kernel/fiasco/src/jdb/jdb_tbuf.cpp | 152 +- kernel/fiasco/src/jdb/jdb_tbuf_init.cpp | 13 +- kernel/fiasco/src/jdb/jdb_tbuf_output.cpp | 8 +- kernel/fiasco/src/jdb/jdb_tbuf_show.cpp | 185 +- kernel/fiasco/src/jdb/jdb_tcb.cpp | 6 +- kernel/fiasco/src/jdb/jdb_tetris.cpp | 109 +- kernel/fiasco/src/jdb/jdb_thread_list.cpp | 12 +- kernel/fiasco/src/jdb/jdb_timeout.cpp | 2 + kernel/fiasco/src/jdb/jdb_trace.cpp | 2 +- kernel/fiasco/src/kern/acpi.cpp | 207 +- kernel/fiasco/src/kern/app_cpu_thread.cpp | 38 +- kernel/fiasco/src/kern/arm/bootstrap.cpp | 13 + kernel/fiasco/src/kern/arm/bsp/imx/Kconfig | 23 +- kernel/fiasco/src/kern/arm/bsp/imx/Modules | 11 + .../kern/arm/bsp/imx/bootstrap-arm-imx.cpp | 26 +- .../src/kern/arm/bsp/imx/config-arm-imx.cpp | 8 + .../kern/arm/bsp/imx/mem_layout-arm-imx.cpp | 126 +- .../kern/arm/bsp/imx/outer_cache-arm-imx6.cpp | 8 + .../src/kern/arm/bsp/imx/pic-arm-imx51.cpp | 31 +- .../arm/bsp/imx/platform_control-arm-imx6.cpp | 33 + .../src/kern/arm/bsp/imx/reset-arm-imx.cpp | 19 +- .../kern/arm/bsp/imx/timer-arm-imx_epit.cpp | 2 +- .../arm/bsp/imx/timer-arm-mptimer-imx6.cpp | 45 + .../fiasco/src/kern/arm/bsp/imx/uart-imx.cpp | 16 +- .../src/kern/arm/bsp/integrator/Kconfig | 2 +- .../integrator/bootstrap-arm-integrator.cpp | 12 +- .../integrator/mem_layout-arm-integrator.cpp | 20 +- .../fiasco/src/kern/arm/bsp/kirkwood/Kconfig | 2 +- .../bsp/kirkwood/bootstrap-arm-kirkwood.cpp | 2 +- .../bsp/kirkwood/mem_layout-arm-kirkwood.cpp | 8 +- kernel/fiasco/src/kern/arm/bsp/omap3/Kconfig | 1 + kernel/fiasco/src/kern/arm/bsp/omap3/Modules | 4 +- .../kern/arm/bsp/omap3/bootstrap-arm-omap.cpp | 9 +- .../arm/bsp/omap3/mem_layout-arm-omap.cpp | 32 +- .../arm/bsp/omap3/outer_cache-arm-omap.cpp | 48 + .../kern/arm/bsp/omap3/pic-arm-gic-omap4.cpp | 2 +- ...ap4.cpp => platform_control-arm-omap4.cpp} | 17 +- kernel/fiasco/src/kern/arm/bsp/pxa/Kconfig | 2 +- .../kern/arm/bsp/pxa/bootstrap-arm-pxa.cpp | 11 +- .../kern/arm/bsp/pxa/mem_layout-arm-pxa.cpp | 16 +- .../fiasco/src/kern/arm/bsp/realview/Modules | 4 +- .../bsp/realview/board_check-arm-realview.cpp | 3 +- .../bsp/realview/bootstrap-arm-realview.cpp | 41 +- .../bsp/realview/mem_layout-arm-realview.cpp | 87 +- .../arm/bsp/realview/pic-arm-realview.cpp | 4 +- ....cpp => platform_control-arm-realview.cpp} | 13 +- kernel/fiasco/src/kern/arm/bsp/s3c/Kconfig | 2 +- .../arm/bsp/s3c/bootstrap-arm-s3c2410.cpp | 13 +- .../arm/bsp/s3c/mem_layout-arm-s3c2410.cpp | 20 +- kernel/fiasco/src/kern/arm/bsp/sa1100/Kconfig | 2 +- .../arm/bsp/sa1100/bootstrap-arm-sa1100.cpp | 8 +- .../arm/bsp/sa1100/mem_layout-arm-sa1100.cpp | 18 +- kernel/fiasco/src/kern/arm/bsp/tegra2/Kconfig | 2 +- kernel/fiasco/src/kern/arm/bsp/tegra2/Modules | 4 +- .../arm/bsp/tegra2/bootstrap-arm-tegra2.cpp | 6 +- .../arm/bsp/tegra2/mem_layout-arm-tegra2.cpp | 10 +- .../kern/arm/bsp/tegra2/pic-arm-tegra2.cpp | 4 +- ...a2.cpp => platform_control-arm-tegra2.cpp} | 25 +- kernel/fiasco/src/kern/arm/context-arm.cpp | 96 +- kernel/fiasco/src/kern/arm/cpu-arm.cpp | 150 +- kernel/fiasco/src/kern/arm/fpu-arm.cpp | 35 +- kernel/fiasco/src/kern/arm/gic.cpp | 34 +- kernel/fiasco/src/kern/arm/ivt.S | 44 +- kernel/fiasco/src/kern/arm/kern_lib_page.cpp | 2 + .../fiasco/src/kern/arm/kernel_thread-arm.cpp | 20 +- kernel/fiasco/src/kern/arm/logdefs.h | 238 --- kernel/fiasco/src/kern/arm/main.cpp | 34 +- kernel/fiasco/src/kern/arm/mem_layout-arm.cpp | 19 +- kernel/fiasco/src/kern/arm/mem_op.cpp | 3 +- kernel/fiasco/src/kern/arm/mem_space-arm.cpp | 30 +- kernel/fiasco/src/kern/arm/mem_unit.cpp | 5 +- .../src/kern/arm/outer_cache-l2cxx0.cpp | 14 +- kernel/fiasco/src/kern/arm/startup-arm.cpp | 4 + kernel/fiasco/src/kern/arm/tb_entry-arm.cpp | 106 +- kernel/fiasco/src/kern/arm/thread-arm.cpp | 119 +- kernel/fiasco/src/kern/arm/thread-jdb.cpp | 2 +- kernel/fiasco/src/kern/arm/tramp-mp.S | 13 +- kernel/fiasco/src/kern/arm/trap_state.cpp | 3 +- .../fiasco/src/kern/arm/utcb_support-arm.cpp | 6 +- kernel/fiasco/src/kern/arm/vcpu-arm.cpp | 9 + kernel/fiasco/src/kern/arm/vm.cpp | 60 +- kernel/fiasco/src/kern/boot_alloc.cpp | 13 +- kernel/fiasco/src/kern/config.cpp | 6 +- kernel/fiasco/src/kern/context-vcpu.cpp | 22 +- kernel/fiasco/src/kern/context.cpp | 588 ++--- kernel/fiasco/src/kern/context_base.cpp | 39 +- kernel/fiasco/src/kern/cpu.cpp | 48 +- kernel/fiasco/src/kern/cpu_mask.cpp | 15 +- kernel/fiasco/src/kern/dbg_page_info.cpp | 6 +- kernel/fiasco/src/kern/factory.cpp | 35 +- kernel/fiasco/src/kern/fpu.cpp | 40 +- kernel/fiasco/src/kern/helping_lock.cpp | 2 - kernel/fiasco/src/kern/hpet.cpp | 1 - kernel/fiasco/src/kern/ia32/32/cpu-32.cpp | 44 +- kernel/fiasco/src/kern/ia32/32/entry-native.S | 8 +- .../src/kern/ia32/32/tb_entry-ia32-32.cpp | 145 +- kernel/fiasco/src/kern/ia32/32/thread-dbf.cpp | 2 +- .../src/kern/ia32/32/thread-ia32-32.cpp | 16 +- kernel/fiasco/src/kern/ia32/32/trap_state.cpp | 5 + .../src/kern/ia32/64/tb_entry-ia32-64.cpp | 141 +- .../src/kern/ia32/64/thread-ia32-64.cpp | 13 +- .../src/kern/ia32/64/trap_state-amd64.cpp | 5 + kernel/fiasco/src/kern/ia32/apic-ia32-mp.cpp | 7 - kernel/fiasco/src/kern/ia32/apic-ia32.cpp | 43 +- kernel/fiasco/src/kern/ia32/cpu-ia32.cpp | 47 +- kernel/fiasco/src/kern/ia32/fpu-ia32-ux.cpp | 10 +- kernel/fiasco/src/kern/ia32/fpu-ia32.cpp | 8 +- kernel/fiasco/src/kern/ia32/io_apic.cpp | 60 +- kernel/fiasco/src/kern/ia32/kmem-ia32.cpp | 80 +- kernel/fiasco/src/kern/ia32/logdefs.h | 240 --- kernel/fiasco/src/kern/ia32/main-ia32.cpp | 20 +- kernel/fiasco/src/kern/ia32/map_util-io.cpp | 28 +- kernel/fiasco/src/kern/ia32/startup-ia32.cpp | 23 +- kernel/fiasco/src/kern/ia32/svm.cpp | 6 + kernel/fiasco/src/kern/ia32/thread-ia32.cpp | 47 +- kernel/fiasco/src/kern/ia32/thread-io.cpp | 47 +- .../fiasco/src/kern/ia32/timer_tick-apic.cpp | 2 - kernel/fiasco/src/kern/ia32/vm_svm.cpp | 14 +- kernel/fiasco/src/kern/ia32/vmx.cpp | 4 + kernel/fiasco/src/kern/ia32/x86desc.cpp | 1 - kernel/fiasco/src/kern/io_space.cpp | 40 +- kernel/fiasco/src/kern/ipc_gate.cpp | 24 +- kernel/fiasco/src/kern/ipc_sender.cpp | 8 +- kernel/fiasco/src/kern/ipc_timeout.cpp | 2 +- kernel/fiasco/src/kern/irq.cpp | 4 +- kernel/fiasco/src/kern/irq_chip.cpp | 31 +- kernel/fiasco/src/kern/irq_mgr.cpp | 9 +- kernel/fiasco/src/kern/kernel_thread-std.cpp | 4 +- kernel/fiasco/src/kern/kernel_thread.cpp | 16 +- kernel/fiasco/src/kern/kmem_alloc.cpp | 6 +- kernel/fiasco/src/kern/kobject.cpp | 18 +- kernel/fiasco/src/kern/kobject_dbg.cpp | 4 +- kernel/fiasco/src/kern/kobject_helper.cpp | 9 +- kernel/fiasco/src/kern/logdefs.h | 159 ++ kernel/fiasco/src/kern/map_util.cpp | 5 +- kernel/fiasco/src/kern/mapdb.cpp | 6 +- kernel/fiasco/src/kern/mapping_tree.cpp | 3 +- kernel/fiasco/src/kern/mp_lock.cpp | 14 +- kernel/fiasco/src/kern/obj_ref_ptr.cpp | 4 +- kernel/fiasco/src/kern/per_cpu_data.cpp | 23 +- kernel/fiasco/src/kern/per_cpu_data_alloc.cpp | 8 +- kernel/fiasco/src/kern/pit-i8254.cpp | 55 +- kernel/fiasco/src/kern/platform_control.cpp | 41 + .../src/kern/platform_control_object.cpp | 105 + kernel/fiasco/src/kern/poll_timeout_kclock.h | 39 + kernel/fiasco/src/kern/ppc32/cpu-ppc32.cpp | 5 + .../fiasco/src/kern/ppc32/mem_space-htab.cpp | 4 +- .../fiasco/src/kern/ppc32/mem_space-ppc32.cpp | 2 +- kernel/fiasco/src/kern/ppc32/paging-ppc32.cpp | 2 +- .../fiasco/src/kern/ppc32/tb_entry-ppc32.cpp | 103 +- kernel/fiasco/src/kern/ppc32/thread-jdb.cpp | 2 +- kernel/fiasco/src/kern/ppc32/thread-ppc32.cpp | 4 +- kernel/fiasco/src/kern/ppc32/trap_state.cpp | 1 + kernel/fiasco/src/kern/prio_list.cpp | 7 +- kernel/fiasco/src/kern/queue.cpp | 1 + kernel/fiasco/src/kern/ram_quota.cpp | 2 +- kernel/fiasco/src/kern/rcupdate.cpp | 52 +- kernel/fiasco/src/kern/ready_queue_fp.cpp | 15 + kernel/fiasco/src/kern/ready_queue_wfq.cpp | 74 +- kernel/fiasco/src/kern/receiver.cpp | 5 +- .../src/kern/sched_context-fixed_prio.cpp | 156 +- .../fiasco/src/kern/sched_context-fp_wfq.cpp | 201 +- kernel/fiasco/src/kern/sched_context-wfq.cpp | 145 +- kernel/fiasco/src/kern/sched_context.cpp | 121 +- kernel/fiasco/src/kern/scheduler.cpp | 117 +- kernel/fiasco/src/kern/sender.cpp | 8 +- kernel/fiasco/src/kern/sparc/cpu-sparc.cpp | 5 + .../fiasco/src/kern/sparc/mem_space-sparc.cpp | 6 +- .../fiasco/src/kern/sparc/tb_entry-sparc.cpp | 2 +- kernel/fiasco/src/kern/sparc/thread-jdb.cpp | 6 +- kernel/fiasco/src/kern/sparc/thread-sparc.cpp | 4 +- kernel/fiasco/src/kern/sparc/trap_state.cpp | 1 + kernel/fiasco/src/kern/sparc/uart-asi.cpp | 4 +- kernel/fiasco/src/kern/spin_lock.cpp | 18 +- kernel/fiasco/src/kern/switch_lock.cpp | 14 +- kernel/fiasco/src/kern/syscalls-log.cpp | 6 +- kernel/fiasco/src/kern/task.cpp | 39 +- kernel/fiasco/src/kern/tb_entry.cpp | 741 +++---- ...tb_entry_output.cpp => tb_entry_output.cc} | 177 +- kernel/fiasco/src/kern/thread-debug.cpp | 24 +- kernel/fiasco/src/kern/thread-ipc.cpp | 155 +- kernel/fiasco/src/kern/thread-log.cpp | 2 +- kernel/fiasco/src/kern/thread-pagefault.cpp | 2 +- kernel/fiasco/src/kern/thread-vcpu.cpp | 3 +- kernel/fiasco/src/kern/thread.cpp | 519 +++-- kernel/fiasco/src/kern/thread_lock.cpp | 10 +- kernel/fiasco/src/kern/thread_object.cpp | 67 +- kernel/fiasco/src/kern/timeout.cpp | 4 +- kernel/fiasco/src/kern/timer_tick.cpp | 15 +- kernel/fiasco/src/kern/timeslice_timeout.cpp | 8 +- kernel/fiasco/src/kern/ux/Makerules.KERNEL | 10 +- kernel/fiasco/src/kern/ux/context-ux.cpp | 5 + kernel/fiasco/src/kern/ux/cpu-ux.cpp | 2 +- kernel/fiasco/src/kern/ux/hostproc.cpp | 2 +- kernel/fiasco/src/kern/ux/mem_space-ux.cpp | 14 +- kernel/fiasco/src/kern/ux/task-ux.cpp | 2 +- kernel/fiasco/src/kern/ux/thread-ux.cpp | 8 +- kernel/fiasco/src/kern/ux/usermode.cpp | 6 +- kernel/fiasco/src/kern/vcpu.cpp | 2 + kernel/fiasco/src/kern/vlog.cpp | 3 +- kernel/fiasco/src/lib/libk/atomic.cpp | 2 +- kernel/fiasco/src/lib/libk/bitfield | 248 +++ kernel/fiasco/src/lib/libk/bitmap.cpp | 13 + kernel/fiasco/src/lib/libk/lock_guard.cpp | 63 +- .../src/lib/libk/poll_timeout_counter.h | 38 + kernel/fiasco/src/lib/libk/slab_cache.cpp | 6 +- kernel/fiasco/src/lib/libk/type_list | 61 + kernel/fiasco/src/lib/libk/union | 88 + kernel/fiasco/src/lib/minilibc/fprintf.c | 1 + kernel/fiasco/src/lib/minilibc/memccpy.c | 4 + kernel/fiasco/src/lib/minilibc/memmove.c | 4 + kernel/fiasco/src/lib/uart/io_regblock_asi.h | 15 +- kernel/fiasco/src/lib/uart/uart_dcc-v6.cc | 5 +- kernel/fiasco/src/lib/uart/uart_imx.cc | 11 +- kernel/fiasco/src/lib/uart/uart_imx.h | 8 +- kernel/fiasco/src/lib/uart/uart_leon3.cc | 4 +- kernel/fiasco/src/lib/uart/uart_omap35x.cc | 10 +- kernel/fiasco/src/lib/uart/uart_pl011.cc | 10 +- kernel/fiasco/src/lib/uart/uart_s3c2410.cc | 22 +- kernel/fiasco/src/templates/Makefile | 6 +- .../src/templates/globalconfig.out.amd64-1 | 3 +- .../src/templates/globalconfig.out.amd64-2 | 3 +- .../templates/globalconfig.out.amd64-3-noinl | 3 +- .../src/templates/globalconfig.out.amd64-mp | 3 +- .../templates/globalconfig.out.arm-a9-mp-1 | 5 +- .../templates/globalconfig.out.arm-a9-mp-2 | 4 +- .../globalconfig.out.arm-a9-mp-vexpress | 5 +- .../src/templates/globalconfig.out.arm-imx21 | 4 +- .../src/templates/globalconfig.out.arm-imx35 | 4 +- .../src/templates/globalconfig.out.arm-imx51 | 4 +- .../src/templates/globalconfig.out.arm-imx6 | 80 + .../src/templates/globalconfig.out.arm-int-1 | 3 +- .../src/templates/globalconfig.out.arm-int-2 | 3 +- .../templates/globalconfig.out.arm-kirkwood | 3 +- .../templates/globalconfig.out.arm-omap3evm | 3 +- .../globalconfig.out.arm-omap4-panda | 7 +- .../src/templates/globalconfig.out.arm-pxa | 3 +- .../src/templates/globalconfig.out.arm-rv-1 | 3 +- .../src/templates/globalconfig.out.arm-rv-2 | 3 +- .../src/templates/globalconfig.out.arm-rv-3 | 3 +- .../templates/globalconfig.out.arm-rv-4-noinl | 3 +- .../src/templates/globalconfig.out.arm-s3c | 3 +- .../src/templates/globalconfig.out.arm-sa | 3 +- .../src/templates/globalconfig.out.arm-t2 | 4 +- .../src/templates/globalconfig.out.arm-v6 | 3 +- .../templates/globalconfig.out.arm-v6-mp-eb | 5 +- .../templates/globalconfig.out.arm-v6-mp-pb | 5 +- .../src/templates/globalconfig.out.arm-v7 | 3 +- .../src/templates/globalconfig.out.ia32-1 | 1 - .../src/templates/globalconfig.out.ia32-2 | 3 +- .../templates/globalconfig.out.ia32-3-noinl | 1 - .../src/templates/globalconfig.out.ia32-big | 3 +- .../src/templates/globalconfig.out.ia32-mp | 3 +- .../templates/globalconfig.out.ia32-ndebug | 3 +- .../src/templates/globalconfig.out.ux-2 | 2 + .../src/test/wrappers/fake_helping_lock.cpp | 1 - kernel/fiasco/src/types/amd64/types-arch.h | 7 + kernel/fiasco/src/types/arm/types-arch.h | 7 + kernel/fiasco/src/types/ia32/types-arch.h | 7 + kernel/fiasco/src/types/ppc32/types-arch.h | 7 + kernel/fiasco/src/types/sparc/types-arch.h | 7 + kernel/fiasco/src/types/types.h | 81 +- kernel/fiasco/src/types/ux/types-arch.h | 7 + kernel/fiasco/tool/backtrace | 4 +- kernel/fiasco/tool/checkinitcalls | 2 +- kernel/fiasco/tool/gen_kconfig | 40 +- kernel/fiasco/tool/preprocess/src/preprocess | 38 + l4/Makefile | 36 +- l4/mk/Makeconf | 44 +- l4/mk/binary.inc | 2 +- l4/mk/export_defs.inc | 1 + l4/mk/platforms/imx6.conf | 4 + l4/mk/platforms/pandaboard.conf | 2 +- l4/pkg/bootstrap/Control | 2 +- l4/pkg/bootstrap/server/src/ARCH-arm/crt0.S | 29 +- l4/pkg/bootstrap/server/src/Make.rules | 68 +- l4/pkg/bootstrap/server/src/build.pl | 36 +- l4/pkg/bootstrap/server/src/platform/imx.cc | 4 + l4/pkg/bootstrap/server/src/platform/rv.cc | 8 +- .../server/src/platform/rv_vexpress.cc | 38 + l4/pkg/bootstrap/server/src/startup.cc | 21 +- l4/pkg/drivers-frst/Control | 2 +- l4/pkg/drivers-frst/include/Makefile | 3 +- .../include/poll_timeout_counter.h | 46 + l4/pkg/drivers-frst/uart/include/uart_imx.h | 8 +- l4/pkg/drivers-frst/uart/src/Makefile | 2 +- l4/pkg/drivers-frst/uart/src/uart_dcc-v6.cc | 5 +- l4/pkg/drivers-frst/uart/src/uart_imx.cc | 11 +- l4/pkg/drivers-frst/uart/src/uart_leon3.cc | 4 +- l4/pkg/drivers-frst/uart/src/uart_omap35x.cc | 10 +- l4/pkg/drivers-frst/uart/src/uart_pl011.cc | 10 +- l4/pkg/drivers-frst/uart/src/uart_pxa.cc | 13 +- l4/pkg/drivers-frst/uart/src/uart_s3c2410.cc | 23 +- l4/pkg/drivers-frst/uart/src/uart_sa1000.cc | 14 +- .../l4sys/include/ARCH-amd64/L4API-l4f/ipc.h | 8 +- l4/pkg/l4sys/include/ARCH-amd64/kdebug.h | 8 +- .../ARCH-arm/L4API-l4f/__kernel_object_impl.h | 6 +- l4/pkg/l4sys/include/ARCH-arm/__vcpu-arch.h | 1 + l4/pkg/l4sys/include/ARCH-arm/cache.h | 6 +- l4/pkg/l4sys/include/ARCH-arm/mem_op.h | 8 +- l4/pkg/l4sys/include/ARCH-arm/utcb.h | 3 +- .../L4API-l4f/__kernel_object_impl.h | 6 +- l4/pkg/l4sys/include/ARCH-ppc32/kdebug.h | 18 +- l4/pkg/l4sys/include/ARCH-x86/kdebug.h | 6 +- l4/pkg/l4sys/include/irq.h | 10 +- l4/pkg/l4sys/include/task | 16 + l4/pkg/l4sys/include/task.h | 77 + l4/pkg/l4sys/include/thread.h | 2 +- l4/pkg/l4sys/include/vcon.h | 2 +- .../l4util/include/ARCH-amd64/atomic_arch.h | 2 +- l4/pkg/l4util/include/ARCH-amd64/cpu.h | 9 +- l4/pkg/l4util/include/ARCH-x86/cpu.h | 23 +- l4/pkg/libvcpu/include/vcpu | 4 +- l4/pkg/libvcpu/include/vcpu.h | 2 +- .../libpthread/include/bits/pthreadtypes.h | 6 + .../lib/libpthread/include/pthread-l4.h | 13 + l4/pkg/uclibc/lib/libpthread/src/Makefile | 28 +- l4/pkg/uclibc/lib/libpthread/src/attr.c | 4 + l4/pkg/uclibc/lib/libpthread/src/manager.cc | 20 +- .../libpthread/src/sysdeps/arm/pspinlock.c | 82 + .../libpthread/src/sysdeps/i386/pspinlock.c | 103 + .../src/sysdeps/powerpc/pspinlock.c | 8 + .../libpthread/src/sysdeps/sparc/pspinlock.c | 14 + .../libpthread/src/sysdeps/x86_64/pspinlock.c | 97 + .../uclibc/ARCH-amd64/include/linux/param.h | 7 + .../lib/uclibc/ARCH-arm/include/linux/param.h | 7 + .../uclibc/ARCH-ppc32/include/linux/param.h | 7 +- .../uclibc/ARCH-sparc/include/linux/param.h | 7 +- .../lib/uclibc/ARCH-x86/include/linux/param.h | 7 + l4/pkg/uclibc/lib/uclibc/contrib_files.mk | 4 +- l4/pkg/uclibc/lib/uclibc/src_rules.mk | 11 +- l4/pkg/uclibc/lib/uclibc/target_headers.lst | 5 + 364 files changed, 7500 insertions(+), 5211 deletions(-) create mode 100644 kernel/fiasco/src/kern/arm/bsp/imx/outer_cache-arm-imx6.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/imx/platform_control-arm-imx6.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/imx/timer-arm-mptimer-imx6.cpp create mode 100644 kernel/fiasco/src/kern/arm/bsp/omap3/outer_cache-arm-omap.cpp rename kernel/fiasco/src/kern/arm/bsp/omap3/{boot_mp-arm-omap4.cpp => platform_control-arm-omap4.cpp} (87%) rename kernel/fiasco/src/kern/arm/bsp/realview/{boot_mp-arm-realview.cpp => platform_control-arm-realview.cpp} (78%) rename kernel/fiasco/src/kern/arm/bsp/tegra2/{boot_mp-arm-tegra2.cpp => platform_control-arm-tegra2.cpp} (76%) delete mode 100644 kernel/fiasco/src/kern/arm/logdefs.h create mode 100644 kernel/fiasco/src/kern/arm/vcpu-arm.cpp delete mode 100644 kernel/fiasco/src/kern/ia32/logdefs.h create mode 100644 kernel/fiasco/src/kern/logdefs.h create mode 100644 kernel/fiasco/src/kern/platform_control.cpp create mode 100644 kernel/fiasco/src/kern/platform_control_object.cpp create mode 100644 kernel/fiasco/src/kern/poll_timeout_kclock.h rename kernel/fiasco/src/kern/{tb_entry_output.cpp => tb_entry_output.cc} (76%) create mode 100644 kernel/fiasco/src/lib/libk/bitfield create mode 100644 kernel/fiasco/src/lib/libk/poll_timeout_counter.h create mode 100644 kernel/fiasco/src/lib/libk/type_list create mode 100644 kernel/fiasco/src/lib/libk/union create mode 100644 kernel/fiasco/src/templates/globalconfig.out.arm-imx6 create mode 100644 l4/mk/platforms/imx6.conf create mode 100644 l4/pkg/bootstrap/server/src/platform/rv_vexpress.cc create mode 100644 l4/pkg/drivers-frst/include/poll_timeout_counter.h create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/arm/pspinlock.c create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/i386/pspinlock.c create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/powerpc/pspinlock.c create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/sparc/pspinlock.c create mode 100644 l4/pkg/uclibc/lib/libpthread/src/sysdeps/x86_64/pspinlock.c diff --git a/kernel/fiasco/Makefile b/kernel/fiasco/Makefile index 474b8c36..05566909 100644 --- a/kernel/fiasco/Makefile +++ b/kernel/fiasco/Makefile @@ -89,7 +89,7 @@ config $(filter config %config,$(MAKECMDGOALS)): fiasco.builddir.create fiasco: fiasco.builddir.create $(MAKE) -C $(DFLBUILDDIR) -j$(PL) -checkall l4check: +checkallseq: error=0; \ $(RM) -r $(ALLBUILDDIR); \ for X in $(TEST_TEMPLATES); do \ @@ -109,7 +109,7 @@ checkall l4check: [ "$$failed" ] && echo -e "\nFailed configurations:$$failed"; \ exit $$error; -checkallp: +checkall l4check: $(RM) -r $(ALLBUILDDIR) $(MAKE) dobuildparallel SHELL=bash diff --git a/kernel/fiasco/src/Kconfig b/kernel/fiasco/src/Kconfig index bed59ed9..f6e98c5d 100644 --- a/kernel/fiasco/src/Kconfig +++ b/kernel/fiasco/src/Kconfig @@ -400,6 +400,10 @@ config ARM_1176_CACHE_ALIAS_FIX using cache sizes of more than 16kB cache. Enabling this option enables the workaround of reducing the cache size to 16kB. +config ARM_CPU_ERRATA + bool "Enable CPU errata workarounds" + depends on ARM && !ARM_TZ + endmenu # target menu "Kernel options" @@ -433,19 +437,6 @@ config CONTEXT_4K Use this option to use 4K kernel stacks. Only disable this option when you know what you're doing. -config IO_PROT - bool "Enable I/O port protection" - default y - depends on PF_PC - help - Enabling this option adds I/O port protection to the kernel. That - means that every thread starts running at IOPL 0 which means that - only the kernel has full access to all I/O ports. This includes - the right to set and clear the interrupt flags (that is using cli - and sti). Access rights to I/O ports can be mapped like memory. If - a task has access to the whole I/O port space, its IOPL is raised - to 3 allowing the task to use cli and sti. - config SLOW_RTC bool "Use RTC with 100 ticks per second" depends on SCHED_RTC diff --git a/kernel/fiasco/src/Makeconf b/kernel/fiasco/src/Makeconf index 64c327b1..75ca8806 100644 --- a/kernel/fiasco/src/Makeconf +++ b/kernel/fiasco/src/Makeconf @@ -100,6 +100,8 @@ L4STD_INCDIR_LAST ?= -I$(wildcard $(dir $(LIBGCC))/include \ $(dir $(LIBGCC))/../include) KERNEL_LDFLAGS += -gc-sections SHARED_FLAGS-gcc += -fno-defer-pop -freg-struct-return +# prevent a possible gcc 4.4 flaw from hitting us +SHARED_FLAGS-gcc += $(if $(filter 4.4,$(CCVER_MAJOR).$(CCVER_MINOR)),-fno-strict-aliasing) SHARED_FLAGS += -g -Wall -W SHARED_FLAGS += -Wno-parentheses SHARED_FLAGS += $(call CHECKCC,-Wformat=2,) diff --git a/kernel/fiasco/src/Makefile b/kernel/fiasco/src/Makefile index b0497ddd..4d157d3b 100644 --- a/kernel/fiasco/src/Makefile +++ b/kernel/fiasco/src/Makefile @@ -98,8 +98,11 @@ ALL = $(foreach subsys, $(SUBSYSTEMS), $($(subsys)) $($(subsys)_EXTRA)) $(foreach m, $(GENERATED_MODULES), auto/stamp-$(m).ready): $(MODULES_FILES) .PRECIOUS: .Modules.deps -.Modules.deps: $(MODULES_FILES) globalconfig.h +.Modules.deps: $(MODULES_FILES) globalconfig.h source @mkdir -p auto + @echo "Cleaning up build directory" + $(VERBOSE)$(RM_R) *.o fiasco *.d .*.d .*.d.new *.d.new + $(VERBOSE)$(RM_R) auto/*.cc auto/*.h auto/*.S auto/stamp-*.ready @echo "Creating $@" @($(foreach mod, $(GENERATED_MODULES), \ echo 'auto/stamp-$(mod).ready: \ @@ -148,6 +151,7 @@ all doc $(addsuffix .ps,$(DEPS_FILES)) $(addsuffix .svg,$(DEPS_FILES)) TAGS tags %.o %_t: $(MODULES_FILES) .Modules.deps create-sources globalconfig.h $(MAKE) srcdir=$(srcdir) objbase=$(objbase) -f $(srcdir)/Makefile.sub2 $@ + # Divert any target we do not explicitly mention in this Makefile to # Makefile.sub2. (Unfortunately 1, this does not work for file # targets that already exist in this directory. Unfortunately 2, @@ -171,6 +175,10 @@ endif # ! config xconfig menuconfig oldconfig auto: test -e auto || mkdir auto +source: + test -e source || ln -sf $(srcdir) source + + BSP_DIR := $(srcdir)/kern/arm/bsp $(srcdir)/kern/ppc32/bsp $(srcdir)/kern/sparc/bsp KCONFIG_FILE := Kconfig KCONFIG_SRC_FILE := $(srcdir)/Kconfig @@ -226,9 +234,10 @@ clean: $(foreach subsys, $(SUBSYSTEMS), clean-$(subsys)) $(RM) .Clean-auto .Compiler-config cleanall: clean $(foreach subsys, $(SUBSYSTEMS), cleanall-$(subsys)) - $(foreach subdir, $(SUBDIRS), $(RM) $(subdir)/{.,}*.d) - $(RM) {.,}*.d {.,}*.d.new *~ globalconfig.{h,h.old} Circular - $(RM) .Modules.deps + $(foreach subdir, $(SUBDIRS), $(RM) $(subdir)/*.d $(subdir)/.*.d) + $(RM) *.d .*.d .*.d.new *.d.new *~ + $(RM) globalconfig.h globalconfig.h.old Circular + $(RM) .Modules.deps source mrproper: cleanall $(RM_R) globalconfig.out Modules.* DEPS* diff --git a/kernel/fiasco/src/Makefile.sub2 b/kernel/fiasco/src/Makefile.sub2 index becf5772..70b18ce6 100644 --- a/kernel/fiasco/src/Makefile.sub2 +++ b/kernel/fiasco/src/Makefile.sub2 @@ -55,17 +55,14 @@ do-all: compilertest $(ALL) endif # ! maintainer mode ifeq ($(CC_TYPE),gcc) -ifneq ($(findstring $(CCVER_MAJOR),4 5 6 7),) - ifeq ($(CCVER_MAJOR),4) - ifeq ($(findstring $(CCVER_MINOR), 0 1 2 3),) - CC_OK := 1 + ifneq ($(findstring $(CCVER_MAJOR),4 5 6 7),) + ifeq ($(CCVER_MAJOR),4) + CC_OK := $(if $(findstring $(CCVER_MINOR),0 1 2 3),,y) + else + CC_OK := y endif - else - CC_OK := 1 endif endif - CC_OK := 1 -endif compilertest: ifeq ($(CC_TYPE),gcc) @@ -73,15 +70,15 @@ ifeq ($(CC_OK),) @$(ECHO_E) "\033[31m\n" \ " ERROR: gcc version "$(CCVER_MAJOR).$(CCVER_MINOR)" is not supported for "\ "Fiasco -- \n"\ - " please update gcc to at least version 4.4.\033[m\n"; exit -1 + " please update gcc to at least version 4.4.\033[m\n"; exit 1 endif endif -ifeq ($(CC_TYPE),gcc) -ifeq ($(CC_OK),) +ifeq ($(CC_TYPE),clang) +ifeq ($(CC_OK),not-yet) @$(ECHO_E) "\033[31m\n" \ " ERROR: clang version "$(CCVER_MAJOR).$(CCVER_MINOR)" is not supported for "\ "Fiasco -- \n"\ - " please update clang to at least version ?.?.\033[m\n"; exit -1 + " please update clang to at least version ?.?.\033[m\n"; exit 1 endif endif @@ -109,10 +106,10 @@ ToDoItems: doc: docs/stamp-doc.ready -docs/stamp-doc.ready: $(foreach m, $(GENERATED_MODULES), auto/stamp-$(m).ready) +docs/stamp-doc.ready: $(srcdir)/doxygen.conf $(foreach m, $(GENERATED_MODULES), auto/stamp-$(m).ready) @mkdir -p docs @touch $@ - @doxygen $(srcdir)/doxygen.conf + $(VERBOSE)doxygen $(srcdir)/doxygen.conf ### diff --git a/kernel/fiasco/src/Modules.amd64 b/kernel/fiasco/src/Modules.amd64 index 4c676d57..ff3963d4 100644 --- a/kernel/fiasco/src/Modules.amd64 +++ b/kernel/fiasco/src/Modules.amd64 @@ -12,7 +12,7 @@ endif PREPROCESS_PARTS += arch $(CONFIG_ABI) 64bit iofp \ $(CONFIG_XARCH) apic abs-timeout-hack \ i8259 pc i8254 fpu \ - auto_map_kip + auto_map_kip io OBJ_SPACE-y = phys OBJ_SPACE- = virt @@ -30,7 +30,6 @@ PREPROCESS_PARTS-$(CONFIG_SCHED_HPET) += hpet_timer PREPROCESS_PARTS-$(CONFIG_SERIAL) += serial 16550 PREPROCESS_PARTS-$(CONFIG_WATCHDOG) += watchdog PREPROCESS_PARTS-$(CONFIG_PERF_CNT) += perf_cnt -PREPROCESS_PARTS-$(CONFIG_IO_PROT) += io PREPROCESS_PARTS-$(CONFIG_CPU_VIRT) += svm vmx PREPROCESS_PARTS-$(CONFIG_SCHED_FIXED_PRIO) += sched_fixed_prio PREPROCESS_PARTS-$(CONFIG_SCHED_WFQ) += sched_wfq @@ -132,7 +131,8 @@ pmem_alloc_IMPL := pmem_alloc pmem_alloc-ia32-ux rtc_IMPL := rtc-ia32 sched_context_IMPL := sched_context-wfq sched_context-fixed_prio \ sched_context-fp_wfq sched_context -space_IMPL := space space-ia32 +sigma0_task_IMPL := sigma0_task sigma0_task-io +space_IMPL := space space-ia32 space-io spin_lock_IMPL := spin_lock spin_lock-ia32 startup_IMPL := startup startup-ia32 task_IMPL := task task-ia32-amd64 @@ -140,7 +140,7 @@ tb_entry_IMPL := tb_entry tb_entry-ia32-64 timer_IMPL := timer timer-ia32-amd64-ux thread_IMPL := thread thread-ia32 thread-ia32-64 \ thread-ipc thread-pagefault thread-log \ - thread-debug thread-dbf thread-vcpu + thread-debug thread-dbf thread-vcpu thread-io trap_state_IMPL := trap_state-amd64 tss_IMPL := tss-amd64 utcb_init_IMPL := utcb_init utcb_init-ia32 @@ -170,13 +170,6 @@ ifeq ("$(CONFIG_SCHED_HPET)","y") INTERFACES_KERNEL += hpet endif - -ifeq ("$(CONFIG_IO_PROT)","y") - space_IMPL += space-io - sigma0_task_IMPL = sigma0_task sigma0_task-io - thread_IMPL += thread-io -endif - ifeq ("$(CONFIG_JDB)","y") JDB := jdb_compound.o SUBSYSTEMS += JDB @@ -189,7 +182,7 @@ INTERFACES_JDB += jdb jdb_util jdb_prompt_ext jdb_symbol jdb_lines \ jdb_input jdb_dump jdb_ptab jdb_misc jdb_mapdb \ jdb_tcb jdb_attach_irq \ jdb_trace_set jdb_counters jdb_table kern_cnt \ - tb_entry_output jdb_exit_module \ + jdb_exit_module \ jdb_tbuf_show jdb_console_buffer \ jdb_list jdb_screen push_console jdb_timeout \ jdb_handler_queue jdb_halt_thread \ @@ -203,6 +196,8 @@ INTERFACES_JDB += jdb jdb_util jdb_prompt_ext jdb_symbol jdb_lines \ jdb_thread jdb_scheduler jdb_sender_list \ jdb_regex jdb_disasm +CXXSRC_JDB := tb_entry_output.cc + apic_IMPL += apic-debug jdb_IMPL := jdb jdb-ia32-amd64 jdb-ansi jdb-ia32-ux jdb-thread \ jdb-int3-ia32-amd64 jdb-int3-ia32-ux diff --git a/kernel/fiasco/src/Modules.arm b/kernel/fiasco/src/Modules.arm index d6516d7c..a8c05489 100644 --- a/kernel/fiasco/src/Modules.arm +++ b/kernel/fiasco/src/Modules.arm @@ -31,6 +31,7 @@ PREPROCESS_PARTS-$(CONFIG_ARM_CORTEX_A8) += armca8 PREPROCESS_PARTS-$(CONFIG_ARM_CORTEX_A9) += armca9 PREPROCESS_PARTS-$(CONFIG_ARM_TZ) += tz PREPROCESS_PARTS-$(CONFIG_ARM_1176_CACHE_ALIAS_FIX) += arm1176_cache_alias_fix +PREPROCESS_PARTS-$(CONFIG_ARM_CPU_ERRATA) += arm_cpu_errata PREPROCESS_PARTS-$(CONFIG_SCHED_FIXED_PRIO) += sched_fixed_prio PREPROCESS_PARTS-$(CONFIG_SCHED_WFQ) += sched_wfq PREPROCESS_PARTS-$(CONFIG_SCHED_FP_WFQ) += sched_fp_wfq @@ -196,6 +197,7 @@ utcb_init_IMPL := utcb_init utcb_init-arm utcb_support_IMPL := utcb_support utcb_support-arm vmem_alloc_IMPL := vmem_alloc vmem_alloc-arch tb_entry_IMPL := tb_entry tb_entry-arm +vcpu_IMPL := vcpu vcpu-arm ifeq ("$(CONFIG_JDB)","y") @@ -217,8 +219,9 @@ INTERFACES_JDB := jdb_handler_queue jdb_module jdb_pic \ jdb_ipc_gate jdb_obj_space jdb_log jdb_factory \ jdb_thread jdb_scheduler jdb_sender_list\ jdb_perf jdb_vm jdb_regex jdb_disasm jdb_bp \ - jdb_tbuf_output jdb_tbuf_show tb_entry_output \ + jdb_tbuf_output jdb_tbuf_show \ jdb_idle_stats +CXXSRC_JDB := tb_entry_output.cc INTERFACES_KERNEL += jdb_tbuf jdb_tbuf_init tb_entry jdb_trace diff --git a/kernel/fiasco/src/Modules.generic b/kernel/fiasco/src/Modules.generic index df7bf949..3ef2df7c 100644 --- a/kernel/fiasco/src/Modules.generic +++ b/kernel/fiasco/src/Modules.generic @@ -18,12 +18,15 @@ INTERFACES_KERNEL := cpu_mask rcupdate kobject_mapdb context_base \ main config vmem_alloc paging fpu \ fpu_state fpu_alloc cpu entry_frame \ kernel_console ipc_gate task sigma0_task \ - kernel_task \ + kernel_task platform_control_object \ irq_controller irq_chip irq_mgr terminate \ - continuation timer_tick \ + continuation timer_tick platform_control \ sched_context utcb_init perf_cnt trap_state \ buddy_alloc vkey kdb_ke prio_list ipi scheduler \ clock vm_factory sys_call_page boot_alloc +platform_control_IMPL := platform_control + syscalls_IMPL := syscalls syscalls-log + timer_tick_IMPL := timer_tick diff --git a/kernel/fiasco/src/Modules.ia32 b/kernel/fiasco/src/Modules.ia32 index 746771da..a790224e 100644 --- a/kernel/fiasco/src/Modules.ia32 +++ b/kernel/fiasco/src/Modules.ia32 @@ -12,7 +12,7 @@ endif PREPROCESS_PARTS += arch $(CONFIG_ABI) 32bit iofp \ $(CONFIG_XARCH) apic abs-timeout-hack \ i8259 pc i8254 fpu \ - abs_syscalls auto_map_kip + abs_syscalls auto_map_kip io OBJ_SPACE-y = phys OBJ_SPACE- = virt @@ -30,7 +30,6 @@ PREPROCESS_PARTS-$(CONFIG_SCHED_HPET) += hpet_timer PREPROCESS_PARTS-$(CONFIG_SERIAL) += serial 16550 PREPROCESS_PARTS-$(CONFIG_WATCHDOG) += watchdog PREPROCESS_PARTS-$(CONFIG_PERF_CNT) += perf_cnt -PREPROCESS_PARTS-$(CONFIG_IO_PROT) += io PREPROCESS_PARTS-$(CONFIG_CPU_VIRT) += svm vmx PREPROCESS_PARTS-$(CONFIG_SCHED_FIXED_PRIO) += sched_fixed_prio PREPROCESS_PARTS-$(CONFIG_SCHED_WFQ) += sched_wfq @@ -131,7 +130,8 @@ pmem_alloc_IMPL := pmem_alloc pmem_alloc-ia32-ux rtc_IMPL := rtc-ia32 sched_context_IMPL := sched_context-wfq sched_context-fixed_prio \ sched_context-fp_wfq sched_context -space_IMPL := space space-ia32 +sigma0_task_IMPL := sigma0_task sigma0_task-io +space_IMPL := space space-ia32 space-io spin_lock_IMPL := spin_lock spin_lock-ia32 startup_IMPL := startup startup-ia32 sys_call_page_IMPL := sys_call_page sys_call_page-abs-ia32 @@ -140,7 +140,7 @@ tb_entry_IMPL := tb_entry tb_entry-ia32-32 timer_IMPL := timer timer-ia32-amd64-ux thread_IMPL := thread thread-ia32 thread-ia32-32 \ thread-ipc thread-pagefault thread-log \ - thread-debug thread-dbf thread-vcpu + thread-debug thread-dbf thread-vcpu thread-io utcb_init_IMPL := utcb_init utcb_init-ia32 vmem_alloc_IMPL := vmem_alloc vmem_alloc-ia32 vm_factory_IMPL := vm_factory vm_factory-ia32 @@ -169,13 +169,6 @@ ifeq ("$(CONFIG_SCHED_HPET)","y") INTERFACES_KERNEL += hpet endif - -ifeq ("$(CONFIG_IO_PROT)","y") - space_IMPL += space-io - sigma0_task_IMPL = sigma0_task sigma0_task-io - thread_IMPL += thread-io -endif - ifeq ("$(CONFIG_JDB)","y") JDB := jdb_compound.o SUBSYSTEMS += JDB @@ -188,7 +181,7 @@ INTERFACES_JDB += jdb jdb_util jdb_prompt_ext jdb_symbol jdb_lines \ jdb_input jdb_dump jdb_ptab jdb_misc jdb_mapdb \ jdb_tcb jdb_attach_irq \ jdb_trace_set jdb_counters jdb_table kern_cnt \ - tb_entry_output jdb_exit_module \ + jdb_exit_module \ jdb_tbuf_show jdb_console_buffer \ jdb_list jdb_screen push_console jdb_timeout \ jdb_handler_queue jdb_halt_thread \ @@ -202,6 +195,8 @@ INTERFACES_JDB += jdb jdb_util jdb_prompt_ext jdb_symbol jdb_lines \ jdb_thread jdb_scheduler jdb_sender_list \ jdb_regex jdb_disasm +CXXSRC_JDB := tb_entry_output.cc + apic_IMPL += apic-debug jdb_IMPL := jdb jdb-ia32-amd64 jdb-ansi jdb-ia32-ux jdb-thread \ jdb-int3-ia32-amd64 jdb-int3-ia32-ux diff --git a/kernel/fiasco/src/Modules.ppc32 b/kernel/fiasco/src/Modules.ppc32 index 8802d384..21dcf719 100644 --- a/kernel/fiasco/src/Modules.ppc32 +++ b/kernel/fiasco/src/Modules.ppc32 @@ -160,7 +160,9 @@ INTERFACES_JDB := jdb jdb_attach_irq jdb_core jdb_scheduler jdb_entry_frame \ jdb_thread_list jdb_util kern_cnt \ push_console jdb_regex jdb_disasm jdb_bp \ jdb_tbuf_output \ - jdb_tbuf_show tb_entry_output + jdb_tbuf_show + +CXXSRC_JDB := tb_entry_output.cc INTERFACES_KERNEL += jdb_tbuf jdb_tbuf_init tb_entry jdb_trace diff --git a/kernel/fiasco/src/Modules.sparc b/kernel/fiasco/src/Modules.sparc index ea488ed6..041af7ea 100644 --- a/kernel/fiasco/src/Modules.sparc +++ b/kernel/fiasco/src/Modules.sparc @@ -158,7 +158,9 @@ INTERFACES_JDB := jdb jdb_attach_irq jdb_core jdb_scheduler jdb_entry_frame \ jdb_thread_list jdb_util kern_cnt \ push_console jdb_regex jdb_disasm jdb_bp \ jdb_tbuf_output \ - jdb_tbuf_show tb_entry_output + jdb_tbuf_show + +CXXSRC_JDB := tb_entry_output.cc INTERFACES_KERNEL += jdb_tbuf jdb_tbuf_init tb_entry jdb_trace diff --git a/kernel/fiasco/src/Modules.ux b/kernel/fiasco/src/Modules.ux index 01004734..1c6294ec 100644 --- a/kernel/fiasco/src/Modules.ux +++ b/kernel/fiasco/src/Modules.ux @@ -105,8 +105,8 @@ INTERFACES_KERNEL := mem_region simpleio kernel_console panic warn \ thread_lock timeslice_timeout \ ipc_timeout thread_state \ sender receiver ipc_sender thread thread_object \ - kobject_helper timer_tick \ - syscalls \ + kobject_helper timer_tick platform_control \ + syscalls \ kernel_thread dirq irq_chip irq_mgr \ irq_chip_ia32 irq_chip_pic \ banner fpu_alloc irq icu_helper main \ @@ -117,7 +117,7 @@ INTERFACES_KERNEL := mem_region simpleio kernel_console panic warn \ jdb_lines jdb_tcb jdb_prompt_module jdb_bt \ jdb_mapdb jdb_ptab jdb_kern_info jdb_counters \ glibc_getchar jdb_trace jdb_trace_set \ - tb_entry_output jdb_tbuf_init kern_cnt \ + jdb_tbuf_init kern_cnt \ jdb_tbuf_output jdb_tbuf_show \ jdb_misc checksum watchdog terminate \ jdb_screen push_console jdb_bp \ @@ -133,11 +133,11 @@ INTERFACES_KERNEL := mem_region simpleio kernel_console panic warn \ jdb_entry_frame kdb_ke jdb_ipi app_cpu_thread \ jdb_rcupdate jdb_kobject jdb_kobject_names \ jdb_list jdb_ipc_gate jdb_obj_space \ - jdb_log jdb_factory scheduler \ + jdb_log jdb_factory scheduler \ + platform_control_object \ jdb_scheduler clock jdb_sender_list \ jdb_disasm jdb_regex - boot_info_IMPL := boot_info boot_info-ia32 boot_info-ux clock_IMPL := clock clock-ia32 config_IMPL := config config-ia32-32 config-ux @@ -199,7 +199,7 @@ utcb_init_IMPL := utcb_init utcb_init-ux vmem_alloc_IMPL := vmem_alloc vmem_alloc-ia32 vmem_alloc-ux spin_lock_IMPL := spin_lock spin_lock-ia32 -CXXSRC_KERNEL := libc_backend_nolock.cc glue_libc_ux.cc +CXXSRC_KERNEL := libc_backend_nolock.cc glue_libc_ux.cc tb_entry_output.cc ASSRC_KERNEL := entry-ux.S entry.S sighandler.S \ sys_call_page-asm.S @@ -335,6 +335,7 @@ endif # UNITTEST subsystem # # disabled until unittests fixed +ifeq (1,2) SUBSYSTEMS += UNITTEST VPATH += test/unit @@ -342,6 +343,7 @@ INTERFACES_UNITTEST += mapdb_t map_util_t # Compile all unit tests without -DNDEBUG. NONDEBUG += $(patsubst %.o, %, $(OBJ_UNITTEST)) +endif MODULES_FILES = $(MODULES_FILE) $(MODULES_FILE_BSP) diff --git a/kernel/fiasco/src/abi/l4_buf_desc.cpp b/kernel/fiasco/src/abi/l4_buf_desc.cpp index be8dc6e8..b157a4ff 100644 --- a/kernel/fiasco/src/abi/l4_buf_desc.cpp +++ b/kernel/fiasco/src/abi/l4_buf_desc.cpp @@ -1,6 +1,7 @@ INTERFACE: #include "types.h" +#include /** * Description of the mapping buffer registers contained in the UTCB @@ -52,37 +53,12 @@ public: */ L4_buf_desc(unsigned mem, unsigned io, unsigned obj, unsigned flags = 0) - : _raw(mem | (io << 5) | (obj << 10) | flags) + : _raw( mem_bfm_t::val_dirty(mem) + | io_bfm_t::val_dirty(io) + | obj_bfm_t::val_dirty(obj) + | flags) {} - /** - * Index of the first memory receive buffer. - * \return the index of the first receive buffer for memory mappings. - * - * The memory receive items use two BRs each. - * \see L4_fpage, L4_msg_item - */ - unsigned mem() const { return _raw & ((1UL << 5)-1); } - - /** - * Index of the first I/O-port buffer item. - * \return the index of the first BR containing a I/O-port buffer. - * - * The I/O-port buffer items use two BRs each. - * \see L4_fpage, L4_msg_item. - */ - unsigned io() const { return (_raw >> 5) & ((1UL << 5)-1); } - - /** - * Index of the first object receive buffer. - * \return the BR index for the first object/capability receive buffer. - * - * An object receive buffer may use one or two BRs depending on the - * value in the L4_msg_item in the first BR. - * \see L4_msg_item, L4_fpage. - */ - unsigned obj() const { return (_raw >> 10) & ((1UL << 5)-1); } - /** * The flags of the BDR. * \return flags encoded in the BDR, see #Inherit_fpu, L4_buf_desc::Flags. @@ -106,4 +82,28 @@ private: * - Bits 24..31: Flags as defined above (only #Inherit_fpu is in use). */ Mword _raw; + +public: + /** \name Index of the first memory receive buffer + * + * The memory receive items use two BRs each. + * \see L4_fpage, L4_msg_item + */ + CXX_BITFIELD_MEMBER( 0, 4, mem, _raw); + + /** \name Index of the first IO-port receive buffer + * + * The I/O-port buffer items use two BRs each. + * \see L4_fpage, L4_msg_item. + */ + CXX_BITFIELD_MEMBER( 5, 9, io, _raw); + + /** \name Index of the first object receive buffer + * + * An object receive buffer may use one or two BRs depending on the + * value in the L4_msg_item in the first BR. + * \see L4_msg_item, L4_fpage. + */ + CXX_BITFIELD_MEMBER(10, 14, obj, _raw); + }; diff --git a/kernel/fiasco/src/abi/l4_fpage.cpp b/kernel/fiasco/src/abi/l4_fpage.cpp index 9fdb2777..4c774a9e 100644 --- a/kernel/fiasco/src/abi/l4_fpage.cpp +++ b/kernel/fiasco/src/abi/l4_fpage.cpp @@ -2,6 +2,8 @@ INTERFACE: #include "types.h" +#include + /** * A L4 flex page. * @@ -61,7 +63,8 @@ private: */ L4_fpage(Type type, Mword address, unsigned char order, unsigned char rights) - : _raw(address | Raw(rights) | (Raw(order) << 6) | (Raw(type) << 4)) + : _raw( address | rights_bfm_t::val_dirty(rights) + | order_bfm_t::val_dirty(order) | type_bfm_t::val_dirty(type)) {} public: @@ -80,7 +83,7 @@ public: * \param order the order of the I/O flex page, size is 2^\a order ports. */ static L4_fpage io(Mword port, unsigned char order) - { return L4_fpage(Io, port << Addr_shift, order, 0); } + { return L4_fpage(Io, adr_bfm_t::val_dirty(port), order, 0); } /** * Create an object flex page. @@ -91,7 +94,7 @@ public: * must be aligned to 2^(\a order + #Addr_shift. */ static L4_fpage obj(Mword idx, unsigned char order, unsigned char rights = 0) - { return L4_fpage(Obj, idx & (~0UL << Addr_shift), order, rights); } + { return L4_fpage(Obj, idx & adr_bfm_t::Mask, order, rights); } /** * Create a memory flex page. @@ -101,7 +104,7 @@ public: * \param order The size of the flex page is 2^\a order in bytes. */ static L4_fpage mem(Mword addr, unsigned char order, unsigned char rights = 0) - { return L4_fpage(Memory, addr & (~0UL << Addr_shift), order, rights); } + { return L4_fpage(Memory, addr & adr_bfm_t::Mask, order, rights); } /** * Create a nil (invalid) flex page. @@ -122,18 +125,6 @@ public: */ explicit L4_fpage(Raw raw) : _raw(raw) {} - /** - * Get the type, see #L4_fpage::Type. - * \return the type of the flex page. - */ - Type type() const { return Type((_raw >> 4) & 3); } - - /** - * Get the order of a flex page. - * \return the order of the flex page (size is 2^\a order). - */ - unsigned char order() const { return (_raw >> 6) & 0x3f; } - /** * The robust type for carrying virtual memory addresses. */ @@ -146,7 +137,7 @@ public: * \return The virtual memory base address of the flex page. */ Virt_addr mem_address() const - { return Virt_addr(_raw & (~0UL << Addr_shift)); } + { return Virt_addr(adr_bfm_t::get_unshifted(_raw)); } /** * Get the capability address of an object flex page. @@ -156,14 +147,14 @@ public: * This value is not shifted, so it is a multiple of 0x1000. * See obj_index() for reference. */ - Mword obj_address() const { return _raw & (~0UL << Addr_shift); } + Mword obj_address() const { return adr_bfm_t::get_unshifted(_raw); } /** * Get the I/O-port number of an I/O flex page. * \pre type() must return #Io to return a valid value. * \return The I/O-port index of this flex page. */ - Mword io_address() const { return _raw >> Addr_shift; } + Mword io_address() const { return adr(); } /** * Get the capability index of an object flex page. @@ -173,7 +164,7 @@ public: * This value is shifted #Addr_shift to be a real index * (opposed to obj_address()). */ - Mword obj_index() const { return _raw >> Addr_shift; } + Mword obj_index() const { return adr(); } /** * Test for memory flex page (if type() is #Memory). @@ -199,7 +190,8 @@ public: * @return not zero, if the flex page covers the * whole address space. */ - Mword is_all_spaces() const { return (_raw & 0xff8) == (Whole_space << 6); } + Mword is_all_spaces() const + { return (_raw & (type_bfm_t::Mask | order_bfm_t::Mask)) == order_bfm_t::val(Whole_space); } /** * Is the flex page valid? @@ -219,6 +211,17 @@ private: public: + /** \name Rights of the flex page */ + CXX_BITFIELD_MEMBER( 0, 3, rights, _raw); + /** \name Type of the flex page */ + CXX_BITFIELD_MEMBER( 4, 5, type, _raw); + /** \name Size (as power of 2) of the flex page */ + CXX_BITFIELD_MEMBER( 6, 11, order, _raw); +private: + /** \name Address encoded in the flex page */ + CXX_BITFIELD_MEMBER(12, MWORD_BITS-1, adr, _raw); + +public: /** * Rights bits for flex pages. * @@ -257,18 +260,11 @@ public: FULL = 0xf, ///< All rights shall be transferred, independent of the type }; - /** - * Get the rights associated with this flexpage. - * \return The rights associated with this flex page. The semantics of this - * value also depends on the type (type()) of the flex page. - */ - Rights rights() const { return Rights(_raw & FULL); } - /** * Remove the given rights from this flex page. * \param r the rights to remove. The semantics depend on the * type (type()) of the flex page. */ - void mask_rights(Rights r) { _raw &= (Mword(r) | ~0x0fUL); } + void mask_rights(Rights r) { _raw &= (Mword(r) | ~rights_bfm_t::Mask); } }; diff --git a/kernel/fiasco/src/abi/l4_msg_item.cpp b/kernel/fiasco/src/abi/l4_msg_item.cpp index 14982e5b..a5df29e4 100644 --- a/kernel/fiasco/src/abi/l4_msg_item.cpp +++ b/kernel/fiasco/src/abi/l4_msg_item.cpp @@ -2,6 +2,7 @@ INTERFACE: #include "types.h" #include "l4_fpage.h" +#include /** * The first word of a message item, either a send item or a receive buffer. @@ -119,13 +120,6 @@ public: */ Mword compound() const { return _raw & 1; } - /** - * Get the type of the message item. - * \return the type of the message item, currently Fiasco.OC - * supports map items only, see #L4_msg_item::Map). - */ - Type type() const { return Type(_raw & 8); } - /** * Is the item a a void item? * \return true if the item is \a void, false if it is valid. @@ -166,34 +160,6 @@ public: */ Mword raw() const { return _raw; } - /** - * Get the extra attributes for the send item. - * \pre The item is a send item. - * \pre type() == #L4_msg_item::Map. - * \return the extra attributes for this send item. - * - * The semantics of the extra attributes depends on - * the type of the second word, the L4_fpage, of the - * complete send item. - * \see L4_msg_item::Memory_attribs, L4_msg_item::Obj_attribs - */ - Mword attr() const { return _raw & 0xf0; } - - /** - * Get the value of the most significant bits of a map item. - * \pre type() == #L4_msg_item::Map - * \return the most significant bits (shifted by #L4_msg_item::Addr_shift). - */ - Mword index() const { return _raw >> Addr_shift; } - - /** - * Get the most significant bits of a map item (masked). - * \pre type() == #L4_msg_item::Map - * \return the most significant bits (masked the lower - * #L4_msg_item::Addr_shift bits). - */ - Mword address() const { return _raw & (~0UL << Addr_shift); } - /** * Get the L4_fpage that represents the small buffer item. * \pre type() == #L4_msg_item::Map @@ -201,7 +167,6 @@ public: * \return the flex page (L4_fpage) representing the single * object slot with index index(). */ - L4_fpage get_small_buf() { return L4_fpage::obj(_raw, 0, attr() >> 4); } /** @@ -215,4 +180,31 @@ private: * The binary representation. */ Mword _raw; + +public: + /** \name Type of the message item + * + * Currently the type must indicate a map item (#L4_msg_item::Map). + * \see L4_msg_item::Type + */ + CXX_BITFIELD_MEMBER_UNSHIFTED( 3, 3, type, _raw); + + /** \name Attribute bits of the message item + * \pre The item is a send item. + * \pre type() == #L4_msg_item::Map. + * + * The semantics of the extra attributes depends on + * the type of the second word, the L4_fpage, of the + * complete send item. + * \see L4_msg_item::Memory_attribs, L4_msg_item::Obj_attribs + */ + CXX_BITFIELD_MEMBER_UNSHIFTED( 4, 7, attr, _raw); + + /** \name the hot-spot address encoded in the message item + * \note Usefule for memory message items. */ + CXX_BITFIELD_MEMBER_UNSHIFTED(Addr_shift, sizeof(_raw)*8-1, address, _raw); + + /** \name the hot-spot index encoded in the message item + * \note In particular useful for IO-port receive items. */ + CXX_BITFIELD_MEMBER (Addr_shift, sizeof(_raw)*8-1, index, _raw); }; diff --git a/kernel/fiasco/src/abi/l4_types.cpp b/kernel/fiasco/src/abi/l4_types.cpp index 8e75cc07..6c629e19 100644 --- a/kernel/fiasco/src/abi/l4_types.cpp +++ b/kernel/fiasco/src/abi/l4_types.cpp @@ -567,6 +567,7 @@ public: EExists = 17, ///< Some object does already exist. ENodev = 19, ///< Objects of the specified type cannot be created. EInval = 22, ///< Invalid parameters passed. + ERange = 34, ///< Parameter out of range ENosys = 38, ///< No such operation. EBadproto = 39, ///< Protocol not supported by object. @@ -575,6 +576,75 @@ public: }; +class L4_cpu_set_descr +{ +private: + Mword _w; + +public: + Mword offset() const { return (_w & 0x00ffffff) & (~0 << granularity()); } + Mword granularity() const { return (_w >> 24) & (MWORD_BITS-1) ; } +}; + +class L4_cpu_set : public L4_cpu_set_descr +{ +private: + Mword _map; + +public: + bool contains(unsigned cpu) const + { + if (offset() > cpu) + return false; + + cpu -= offset(); + cpu >>= granularity(); + if (cpu >= MWORD_BITS) + return false; + + return _map & (1UL << cpu); + } + + template + Mword first(MAP const &bm, unsigned max) const + { + unsigned cpu = offset(); + + for (;;) + { + unsigned b = (cpu - offset()) >> granularity(); + if (cpu >= max || b >= MWORD_BITS) + return max; + + if (!(_map & (1UL << b))) + { + cpu += 1UL << granularity(); + continue; + } + + if (bm.get(cpu)) + return cpu; + + ++cpu; + } + } +}; + +struct L4_sched_param +{ + L4_cpu_set cpus; + Smword sched_class; // legacy prio when positive + Mword length; // sizeof (...) +}; + +struct L4_sched_param_legacy +{ + L4_cpu_set cpus; + Smword prio; // must be positive, overlays with sched_class + Mword quantum; +}; + + //---------------------------------------------------------------------------- INTERFACE [ia32 || ux]: @@ -584,7 +654,6 @@ public: enum { Msg_size = 16 }; }; - //---------------------------------------------------------------------------- INTERFACE [arm]: @@ -594,7 +663,6 @@ public: enum { Msg_size = 20 }; }; - //---------------------------------------------------------------------------- INTERFACE [amd64]: @@ -604,7 +672,9 @@ public: enum { Msg_size = 23 }; }; +//---------------------------------------------------------------------------- INTERFACE [ppc32]: + EXTENSION class L4_exception_ipc { public: @@ -930,5 +1000,3 @@ IMPLEMENT inline void L4_timeout::man (Mword w) { _t = (_t & ~Man_mask) | ((w << Man_shift) & Man_mask); } - - diff --git a/kernel/fiasco/src/doxygen.conf b/kernel/fiasco/src/doxygen.conf index 94adf241..f81fe4a6 100644 --- a/kernel/fiasco/src/doxygen.conf +++ b/kernel/fiasco/src/doxygen.conf @@ -1,670 +1,1381 @@ -# Doxyfile 1.2.15 +# Doxyfile 1.8.1.2 # This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project +# doxygen (www.doxygen.org) for a project. # -# All text after a hash (#) is considered a comment and will be ignored +# All text after a hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") +# Values that contain spaces should be placed between quotes (" "). #--------------------------------------------------------------------------- -# General configuration options +# Project related configuration options #--------------------------------------------------------------------------- -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# http://www.gnu.org/software/libiconv for the list of possible encodings. -PROJECT_NAME = Fiasco Microkernel +DOXYFILE_ENCODING = UTF-8 -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. + +PROJECT_NAME = FiascoMicrokernel + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = +PROJECT_NUMBER = -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = docs -# The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this -# information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Brazilian, Chinese, Croatian, Czech, Danish, Dutch, Finnish, French, -# German, Greek, Hungarian, Italian, Japanese, Korean, Norwegian, Polish, -# Portuguese, Romanian, Russian, Slovak, Slovene, Spanish and Swedish. +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES - -EXTRACT_ALL = YES - -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. - -EXTRACT_PRIVATE = NO - -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. - -EXTRACT_STATIC = YES - -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. - -EXTRACT_LOCAL_CLASSES = YES - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_MEMBERS = NO - -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these class will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. - -HIDE_UNDOC_CLASSES = NO - -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES -# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited -# members of a class in the documentation of that class as if those members were -# ordinary class members. Constructors, destructors and assignment operators of -# the base classes will not be shown. +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. It is allowed to use relative paths in the argument list. +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. -STRIP_FROM_PATH = +STRIP_FROM_PATH = -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. -INTERNAL_DOCS = NO +STRIP_FROM_INC_PATH = -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. - -STRIP_CODE_COMMENTS = YES - -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower case letters. If set to YES upper case letters are also -# allowed. This is useful if you have classes or files whose names only differ -# in case and if your file system supports case sensitive file names. Windows -# users are adviced to set this option to NO. - -CASE_SENSE_NAMES = YES - -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful if your file system # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like regular Qt-style comments +# (thus requiring an explicit @brief command for a brief description.) -HIDE_SCOPE_NAMES = NO - -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. - -VERBATIM_HEADERS = YES - -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put list of the files that are included by a file in the documentation -# of that file. - -SHOW_INCLUDE_FILES = YES - -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like the Qt-style comments (thus requiring an -# explict @brief command for a brief description. - -#JAVADOC_AUTOBRIEF = NO JAVADOC_AUTOBRIEF = YES -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# reimplements. +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will +# interpret the first line (until the first dot) of a Qt-style +# comment as the brief description. If set to NO, the comments +# will behave just like regular Qt-style comments (thus requiring +# an explicit \brief command for a brief description.) + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. INHERIT_DOCS = YES -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce +# a new page for each member. If set to NO, the documentation of a member will +# be part of the file/class/namespace that contains it. -INLINE_INFO = YES +SEPARATE_MEMBER_PAGES = NO -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. - -SORT_MEMBER_DOCS = YES - -# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first -# member in the group (if any) for the other members of the group. By default -# all members of a group must be documented explicitly. - -DISTRIBUTE_GROUP_DOC = NO - -# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. - -GENERATE_TODOLIST = YES - -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. - -GENERATE_TESTLIST = YES - -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. - -GENERATE_BUGLIST = YES - -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user defined paragraph with heading "Side Effects:". +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. -ALIASES = +ALIASES = -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding +# "class=itcl::class" will allow you to use the command class in the +# itcl::class meaning. -ENABLED_SECTIONS = +TCL_SUBST = -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consist of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. - -MAX_INITIALIZER_LINES = 30 - -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources -# only. Doxygen will then generate output that is more tailored for C. -# For instance some of the names that are used will be different. The list +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources -# only. Doxygen will then generate output that is more tailored for Java. -# For instance namespaces will be presented as packages, qualified scopes -# will look different, etc. +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java +# sources only. Doxygen will then generate output that is more tailored for +# Java. For instance, namespaces will be presented as packages, qualified +# scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources only. Doxygen will then generate output that is more tailored for +# Fortran. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for +# VHDL. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all +# comments according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you +# can mix doxygen, HTML, and XML commands with Markdown formatting. +# Disable only in case of backward compatibilities issues. + +MARKDOWN_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should +# set this tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. +# func(std::string) {}). This also makes the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. +# Doxygen will parse them like normal C++ but will assume all classes use public +# instead of private inheritance when no explicit protection keyword is present. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate getter +# and setter methods for a property. Setting this option to YES (the default) +# will make doxygen replace the get and set methods by a property in the +# documentation. This will only work if the methods are indeed getting or +# setting a simple type. If this is not the case, or you want to show the +# methods anyway, you should set this option to NO. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields will be shown inline in the documentation +# of the scope in which they are defined (i.e. file, namespace, or group +# documentation), provided this scope is documented. If set to NO (the default), +# structs, classes, and unions are shown on a separate page (for HTML and Man +# pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum +# is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically +# be useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. + +TYPEDEF_HIDES_STRUCT = NO + +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +SYMBOL_CACHE_SIZE = 0 + +# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be +# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given +# their name and scope. Since this can be an expensive process and often the +# same symbol appear multiple times in the code, doxygen keeps a cache of +# pre-resolved symbols. If the cache is too small doxygen will become slower. +# If the cache is too large, memory is wasted. The cache size is given by this +# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal scope will be included in the documentation. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base +# name of the file that contains the anonymous namespace. By default +# anonymous namespaces are hidden. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the +# hierarchy of group names into alphabetical order. If set to NO (the default) +# the group names will appear in their defined order. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or macro consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and macros in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. +# This will remove the Files entry from the Quick Index and from the +# Folder Tree View (if specified). The default is YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index +# and from the Folder Tree View (if specified). The default is YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the program writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this +# feature you need bibtex and perl available in the search path. + +CITE_BIB_FILES = + #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- -# The QUIET tag can be used to turn on/off the messages that are generated +# The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO -# The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# The WARN_NO_PARAMDOC option can be enabled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written # to stderr. -WARN_LOGFILE = +WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = auto/ +INPUT = auto/ \ + source/lib/libk/bitfield -# If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp -# *.h++ *.idl *.odl +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is +# also the default input encoding. Doxygen uses libiconv (or the iconv built +# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for +# the list of possible encodings. -FILE_PATTERNS = *.h *.cc +INPUT_ENCODING = UTF-8 -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl + +FILE_PATTERNS = *.h \ + *.cc + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO -# The EXCLUDE tag can be used to specify files and/or directories that should -# excluded from the INPUT source files. This way you can easily exclude a +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to the directory from which doxygen is +# run. -EXCLUDE = +EXCLUDE = -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories -# that are symbolic links (a Unix filesystem feature) are excluded from the input. +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. EXCLUDE_SYMLINKS = NO -# If the value of the INPUT tag contains directories, you can use the -# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. Note that the wildcards are matched +# against the file with absolute path, so to exclude all test directories +# for example use the pattern */test/* -EXCLUDE_PATTERNS = +EXCLUDE_PATTERNS = -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see # the \include command). -EXAMPLE_PATH = +EXAMPLE_PATH = -# If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left # blank all files are included. -EXAMPLE_PATTERNS = +EXAMPLE_PATTERNS = -# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see # the \image command). -IMAGE_PATH = +IMAGE_PATH = -# The INPUT_FILTER tag can be used to specify a program that doxygen should -# invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes # to standard output. +# If FILTER_PATTERNS is specified, this tag will be +# ignored. -INPUT_FILTER = +INPUT_FILTER = -# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse. +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- -# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO -# Setting the INLINE_SOURCES tag to YES will include the body +# Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO -# If the REFERENCED_BY_RELATION tag is set to YES (the default) -# then for each documented function all documented +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C, C++ and Fortran comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES +# then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES -# If the REFERENCES_RELATION tag is set to YES (the default) -# then for each documented function all documented entities +# If the REFERENCES_RELATION tag is set to YES +# then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES +# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) +# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from +# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will +# link to the source code. +# Otherwise they will link to the documentation. + +REFERENCES_LINK_SOURCE = YES + +# If the USE_HTAGS tag is set to YES then the references to source code +# will point to the HTML generated by the htags(1) tool instead of doxygen +# built-in source browser. The htags tool is part of GNU's global source +# tagging system (see http://www.gnu.org/software/global/global.html). You +# will need version 4.8.6 or higher. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. -IGNORE_PREFIX = +IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is advised to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! -HTML_HEADER = +HTML_HEADER = -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a # standard footer. -HTML_FOOTER = +HTML_FOOTER = -# The HTML_STYLESHEET tag can be used to specify a user defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# style sheet in the HTML output directory as well, or it will be erased! -HTML_STYLESHEET = +HTML_STYLESHEET = -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. -HTML_ALIGN_MEMBERS = YES +HTML_EXTRA_FILES = -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the style sheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of +# entries shown in the various tree structured indices initially; the user +# can expand and collapse entries dynamically later on. Doxygen will expand +# the tree to such a level that at most the specified number of entries are +# visible (unless a fully collapsed tree already exceeds this amount). +# So setting the number of entries 1 will produce a full collapsed tree by +# default. 0 is a special value representing an infinite number of entries +# and will result in a full expanded tree by default. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files +# will be generated that can be used as input for Apple's Xcode 3 +# integrated development environment, introduced with OSX 10.5 (Leopard). +# To create a documentation set, doxygen will generate a Makefile in the +# HTML output directory. Running make will produce the docset in that +# directory and running "make install" will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find +# it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. + +GENERATE_DOCSET = NO + +# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the +# feed. A documentation feed provides an umbrella under which multiple +# documentation sets from a single provider (such as a company or product suite) +# can be grouped. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that +# should uniquely identify the documentation set bundle. This should be a +# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen +# will append .docset to the name. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING +# is used to encode HtmlHelp index (hhk), content (hhc) and project file +# content. + +CHM_INDEX_ENCODING = + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the Html help documentation and to the tree view. +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# +# Qt Help Project / Custom Filters. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# +# Qt Help Project / Filter Attributes. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) +# at top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. Since the tabs have the same information as the +# navigation tree you can set this option to NO if you already set +# GENERATE_TREEVIEW to YES. DISABLE_INDEX = NO -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. - -ENUM_VALUES_PER_LINE = 4 - -# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be -# generated containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript and frames is required (for instance Mozilla, Netscape 4.0+, -# or Internet explorer 4.0+). Note that for large projects the tree generation -# can take a very long time. In such cases it is better to disable this feature. +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. +# If the tag value is set to YES, a side panel will be generated +# containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. +# Since the tree basically has the same information as the tab index you +# could consider to set DISABLE_INDEX to NO when enabling this option. GENERATE_TREEVIEW = NO -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of Latex formulas included +# as images in the HTML documentation. The default is 10. Note that +# when you change the font size after a successful doxygen run you need +# to manually remove any form_*.png images from the HTML output directory +# to force them to be regenerated. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you may also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to +# the MathJax Content Delivery Network so you can quickly see the result without +# installing MathJax. +# However, it is strongly recommended to install a local +# copy of MathJax from http://www.mathjax.org before deployment. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = NO + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- -# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO -# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex -# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be invoked. If left blank `latex' will be used as the default command name. +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. LATEX_CMD_NAME = latex -# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to -# generate index for LaTeX. If left blank `makeindex' will be used as the +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex -# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact -# LaTeX documents. This may be useful for small projects and may help to +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO -# The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide -# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. -EXTRA_PACKAGES = +EXTRA_PACKAGES = -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for -# the generated latex document. The header should contain everything until -# the first chapter. If it is left blank doxygen will generate a +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! -LATEX_HEADER = +LATEX_HEADER = -# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated -# is prepared for conversion to pdf (using ps2pdf). The pdf file will -# contain links (just like the HTML output) instead of page references +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO -# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of -# plain latex in the generated Makefile. Set this option to YES to get a +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. -# command to the generated LaTeX files. This will instruct LaTeX to keep -# running if errors occur, instead of asking the user for help. +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- -# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output -# The RTF output is optimised for Word 97 and may not look very pretty with +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO -# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf -# If the COMPACT_RTF tag is set to YES Doxygen generates more compact -# RTF documents. This may be useful for small projects and may help to +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO -# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated -# will contain hyperlink fields. The RTF file will -# contain links (just like the HTML output) instead of page references. -# This makes the output suitable for online browsing using WORD or other -# programs which support those fields. +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO -# Load stylesheet definitions from file. Syntax is similar to doxygen's -# config file, i.e. a series of assigments. You only have to provide +# Load style sheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. -RTF_STYLESHEET_FILE = +RTF_STYLESHEET_FILE = -# Set optional variables used in the generation of an rtf document. +# Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. -RTF_EXTENSIONS_FILE = +RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- -# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO -# The MAN_OUTPUT tag is used to specify where the man pages will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man -# The MAN_EXTENSION tag determines the extension that is added to +# The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, -# then it will generate one additional man file for each entity -# documented in the real man page(s). These additional files -# only source the real man page, but without them the man command +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO @@ -673,267 +1384,411 @@ MAN_LINKS = NO # configuration options related to the XML output #--------------------------------------------------------------------------- -# If the GENERATE_XML tag is set to YES Doxygen will -# generate an XML file that captures the structure of -# the code including all documentation. Note that this -# feature is still experimental and incomplete at the -# moment. +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. GENERATE_XML = NO +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +XML_PROGRAMLISTING = YES + #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- -# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will -# generate an AutoGen Definitions (see autogen.sf.net) file -# that captures the structure of the code including all -# documentation. Note that this feature is still experimental +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- -# Configuration options related to the preprocessor +# configuration options related to the Perl module output #--------------------------------------------------------------------------- -# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will -# evaluate all C-preprocessor directives found in the sources and include +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES -# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro -# names in the source code. If set to NO (the default) only conditional -# compilation will be performed. Macro expansion can be done in a controlled +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. -MACRO_EXPANSION = NO +MACRO_EXPANSION = YES -# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES -# then the macro expansion is limited to the macros specified with the -# PREDEFINED and EXPAND_AS_PREDEFINED tags. +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_DEFINED tags. -EXPAND_ONLY_PREDEF = NO +EXPAND_ONLY_PREDEF = YES -# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# pointed to by INCLUDE_PATH will be searched when a #include is found. SEARCH_INCLUDES = YES -# The INCLUDE_PATH tag can be used to specify one or more directories that -# contain include files that are not input files but should be processed by +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by # the preprocessor. -INCLUDE_PATH = +INCLUDE_PATH = source/lib/libk -# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard -# patterns (like *.h and *.hpp) to filter out the header-files in the -# directories. If left blank, the patterns specified with FILE_PATTERNS will +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. -INCLUDE_FILE_PATTERNS = +INCLUDE_FILE_PATTERNS = -# The PREDEFINED tag can be used to specify one or more macro names that -# are defined before the preprocessor is started (similar to the -D option of -# gcc). The argument of the tag is a list of macros of the form: name -# or name=definition (no spaces). If the definition and the = are -# omitted =1 is assumed. +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. -PREDEFINED = +PREDEFINED = -# If the MACRO_EXPANSION and EXPAND_PREDEF_ONLY tags are set to YES then -# this tag can be used to specify a list of macro names that should be expanded. -# The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. -EXPAND_AS_DEFINED = +EXPAND_AS_DEFINED = CXX_BITFIELD_MEMBER CXX_BITFIELD_MEMBER_UNSHIFTED -# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line and do not end with a semicolon. Such function macros are typically -# used for boiler-plate code, and will confuse the parser if not removed. +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- -# Configuration::addtions related to external references +# Configuration::additions related to external references #--------------------------------------------------------------------------- -# The TAGFILES tag can be used to specify one or more tagfiles. +# The TAGFILES option can be used to specify one or more tagfiles. For each +# tag file the location of the external documentation should be added. The +# format of a tag file without this location is as follows: +# +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths +# or URLs. Note that each tag file must have a unique name (where the name does +# NOT include the path). If a tag file is not located in the directory in which +# doxygen is run, you must also specify the path to the tagfile here. -TAGFILES = +TAGFILES = -# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. -GENERATE_TAGFILE = +GENERATE_TAGFILE = -# If the ALLEXTERNALS tag is set to YES all external classes will be listed -# in the class index. If set to NO only the inherited external classes +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES -# The PERL_PATH should be the absolute path and name of the perl script +# The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- -# Configuration options related to the dot tool +# Configuration options related to the dot tool #--------------------------------------------------------------------------- -# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will -# generate a inheritance diagram (in Html, RTF and LaTeX) for classes with base or -# super classes. Setting the tag to NO turns the diagrams off. Note that this -# option is superceded by the HAVE_DOT option below. This is only a fallback. It is -# recommended to install and use dot, since it yield more powerful graphs. +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is -# available from the path. This tool is part of Graphviz, a graph visualization -# toolkit from AT&T and Lucent Bell Labs. The other options in this section -# have no effect if this option is set to NO (the default) +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see +# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. -HAVE_DOT = NO +MSCGEN_PATH = -# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. - -CLASS_GRAPH = YES - -# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen -# will generate a graph for each documented class showing the direct and -# indirect implementation dependencies (inheritance, containment, and -# class references variables) of the class with other documented classes. - -COLLABORATION_GRAPH = YES - -# If set to YES, the inheritance and collaboration graphs will show the -# relations between templates and their instances. - -TEMPLATE_RELATIONS = YES - -# If set to YES, the inheritance and collaboration graphs will hide -# inheritance and usage relations if the target is undocumented +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT -# tags are set to YES then doxygen will generate a graph for each documented -# file showing the direct and indirect include dependencies of the file with +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = NO + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. + +DOT_FONTPATH = + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If the UML_LOOK tag is enabled, the fields and methods are shown inside +# the class node. If there are many fields or methods and many nodes the +# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS +# threshold limits the number of items for each type to make the size more +# managable. Set this to 0 for no limit. Note that the threshold may be +# exceeded by 50% before the limit is enforced. + +UML_LIMIT_NUM_FIELDS = 10 + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES -# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and -# HAVE_DOT tags are set to YES then doxygen will generate a graph for each -# documented header file showing the documented files that directly or +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES -# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. +# If the CALL_GRAPH and HAVE_DOT options are set to YES then +# doxygen will generate a call dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable call graphs +# for selected functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then +# doxygen will generate a caller dependency graph for every global function +# or class method. Note that enabling this option will significantly increase +# the time of a run. So in most cases it will be better to enable caller +# graphs for selected functions only using the \callergraph command. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will generate a graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES -# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, jpg, or gif -# If left blank png will be used. +# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). DOT_IMAGE_FORMAT = png -# The tag DOT_PATH can be used to specify the path where the dot tool can be -# found. If left blank, it is assumed the dot tool can be found on the path. +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. -DOT_PATH = +INTERACTIVE_SVG = NO -# The DOTFILE_DIRS tag can be used to specify one or more directories that -# contain dot files that are included in the documentation (see the +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the # \dotfile command). -DOTFILE_DIRS = +DOTFILE_DIRS = -# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width -# (in pixels) of the graphs generated by dot. If a graph becomes larger than -# this value, doxygen will try to truncate the graph, so that it fits within -# the specified constraint. Beware that most browsers cannot cope with very -# large images. +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). -MAX_DOT_GRAPH_WIDTH = 1024 +MSCFILE_DIRS = -# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height -# (in pixels) of the graphs generated by dot. If a graph becomes larger than -# this value, doxygen will try to truncate the graph, so that it fits within -# the specified constraint. Beware that most browsers cannot cope with very -# large images. +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of +# nodes that will be shown in the graph. If the number of nodes in a graph +# becomes larger than this value, doxygen will truncate the graph, which is +# visualized by representing a node as a red box. Note that doxygen if the +# number of direct children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note +# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. -MAX_DOT_GRAPH_HEIGHT = 1024 +DOT_GRAPH_MAX_NODES = 50 -# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will -# generate a legend page explaining the meaning of the various boxes and +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES -# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will -# remove the intermedate dot files that are used to generate +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES - -#--------------------------------------------------------------------------- -# Configuration::addtions related to the search engine -#--------------------------------------------------------------------------- - -# The SEARCHENGINE tag specifies whether or not a search engine should be -# used. If set to NO the values of all tags below this one will be ignored. - -SEARCHENGINE = NO - -# The CGI_NAME tag should be the name of the CGI script that -# starts the search engine (doxysearch) with the correct parameters. -# A script with this name will be generated by doxygen. - -CGI_NAME = search.cgi - -# The CGI_URL tag should be the absolute URL to the directory where the -# cgi binaries are located. See the documentation of your http daemon for -# details. - -CGI_URL = - -# The DOC_URL tag should be the absolute URL to the directory where the -# documentation is located. If left blank the absolute path to the -# documentation, with file:// prepended to it, will be used. - -DOC_URL = - -# The DOC_ABSPATH tag should be the absolute path to the directory where the -# documentation is located. If left blank the directory on the local machine -# will be used. - -DOC_ABSPATH = - -# The BIN_ABSPATH tag must point to the directory where the doxysearch binary -# is installed. - -BIN_ABSPATH = /usr/local/bin/ - -# The EXT_DOC_PATHS tag can be used to specify one or more paths to -# documentation generated for other projects. This allows doxysearch to search -# the documentation for these projects as well. - -EXT_DOC_PATHS = diff --git a/kernel/fiasco/src/drivers/arm/processor-arm.cpp b/kernel/fiasco/src/drivers/arm/processor-arm.cpp index e315ce8e..d067e37f 100644 --- a/kernel/fiasco/src/drivers/arm/processor-arm.cpp +++ b/kernel/fiasco/src/drivers/arm/processor-arm.cpp @@ -145,9 +145,9 @@ IMPLEMENTATION[arm && mp]: IMPLEMENT static inline unsigned Proc::cpu_id() { - unsigned int cpunum; - __asm__("mrc p15, 0, %0, c0, c0, 5": "=r" (cpunum)); - return cpunum & 0xf; + unsigned mpidr; + __asm__("mrc p15, 0, %0, c0, c0, 5": "=r" (mpidr)); + return mpidr & 0x7; // mind gic softirq } //---------------------------------------------------------------- diff --git a/kernel/fiasco/src/drivers/pci.cpp b/kernel/fiasco/src/drivers/pci.cpp index 07185e22..3d8b0f66 100644 --- a/kernel/fiasco/src/drivers/pci.cpp +++ b/kernel/fiasco/src/drivers/pci.cpp @@ -6,84 +6,115 @@ class Pci { enum { - Cfg_addr = 0xcf8, - Cfg_data = 0xcfc, + Cfg_addr_port = 0xcf8, + Cfg_data_port = 0xcfc, }; -}; +public: + enum class Cfg_width + { + Byte = 0, + Short = 1, + Long = 2 + }; + + + class Cfg_addr + { + public: + Cfg_addr() = default; + explicit Cfg_addr(Unsigned32 pci_express_adr) : _addr(pci_express_adr) {} + + Cfg_addr(unsigned bus, unsigned dev, unsigned function = 0, unsigned reg = 0) + : _addr( ((Unsigned32)bus << 20) + | ((Unsigned32)dev << 15) + | ((Unsigned32)function << 12) + | ((Unsigned32)reg)) + {} + + + Cfg_addr operator + (unsigned reg) const + { return Cfg_addr(_addr + reg); } + + Unsigned32 compat_addr() const + { return (_addr & 0xfc) | ((_addr >> 4) & 0xffff00); } + + Unsigned32 mmio_cfg_offset() const + { return _addr; } + + Unsigned32 express_cfg() const + { return _addr; } + + unsigned reg_offs(Cfg_width w = Cfg_width::Byte) const + { return (_addr & 0x3) & (~0U << (unsigned)w); } + + unsigned bus() const { return (_addr >> 20) & 0xff; } + unsigned dev() const { return (_addr >> 15) & 0x1f; } + unsigned func() const { return (_addr >> 12) & 0x7; } + unsigned reg() const { return _addr & 0xfff; } + + void bus(unsigned bus) { _addr = (_addr & ~0xff00000) | ((Unsigned32)bus << 20); } + void dev(unsigned dev) { _addr = (_addr & ~(0x1fUL << 15)) | ((Unsigned32)dev << 15); } + void func(unsigned func) { _addr = (_addr & ~(0x7UL << 12)) | ((Unsigned32)func << 12); } + void reg(unsigned reg) { _addr = (_addr & ~0xfff) | (Unsigned32)reg; } + + private: + Unsigned32 _addr; + }; + +}; IMPLEMENTATION: #include "io.h" +#include -PUBLIC static inline NEEDS["io.h"] -Unsigned8 -Pci::read_cfg8 (Mword bus, Mword dev, Mword subdev, Mword reg) -{ - Io::out32 (((bus & 0xffff) << 16) | - ((dev & 0x1f) << 11) | - ((subdev & 0x07) << 8) | - ((reg & 0xff) ) | - 1<<31, Cfg_addr); - return Io::in8 (Cfg_data + (reg & 3)); -} - -PUBLIC static inline NEEDS["io.h"] -Unsigned16 -Pci::read_cfg16 (Mword bus, Mword dev, Mword subdev, Mword reg) -{ - Io::out32 (((bus & 0xffff) << 16) | - ((dev & 0x1f) << 11) | - ((subdev & 0x07) << 8) | - ((reg & 0xfe) ) | - 1<<31, Cfg_addr); - return Io::in16 (Cfg_data + (reg & 2)); -} - -PUBLIC static inline NEEDS["io.h"] +PUBLIC static inline NEEDS["io.h", ] Unsigned32 -Pci::read_cfg32 (Mword bus, Mword dev, Mword subdev, Mword reg) +Pci::read_cfg(Cfg_addr addr, Cfg_width w) { - Io::out32 (((bus & 0xffff) << 16) | - ((dev & 0x1f) << 11) | - ((subdev & 0x07) << 8) | - ((reg & 0xfc) ) | - 1<<31, Cfg_addr); - return Io::in32 (Cfg_data); + Io::out32(addr.compat_addr() | (1<<31), Cfg_addr_port); + switch (w) + { + case Cfg_width::Byte: return Io::in8(Cfg_data_port + addr.reg_offs(w)); + case Cfg_width::Short: return Io::in16(Cfg_data_port + addr.reg_offs(w)); + case Cfg_width::Long: return Io::in32(Cfg_data_port); + default: assert (false /* invalid PCI config access */); + } + return 0; } -PUBLIC static inline NEEDS["io.h"] +PUBLIC static template< typename VT > inline void -Pci::write_cfg8 (Mword bus, Mword dev, Mword subdev, Mword reg, Unsigned8 v) +Pci::read_cfg(Cfg_addr addr, VT *value) { - Io::out32 (((bus & 0xffff) << 16) | - ((dev & 0x1f) << 11) | - ((subdev & 0x07) << 8) | - ((reg & 0xff) ) | - 1<<31, Cfg_addr); - Io::out8 (v, Cfg_data + (reg & 3)); + static_assert (sizeof (VT) == 1 || sizeof (VT) == 2 || sizeof (VT)==4, + "wrong PCI config space access size"); + Cfg_width w; + Io::out32(addr.compat_addr() | (1<<31), Cfg_addr_port); + switch (sizeof(VT)) + { + case 1: w = Cfg_width::Byte; break; + case 2: w = Cfg_width::Short; break; + case 4: w = Cfg_width::Long; break; + } + + *value = read_cfg(addr, w); } -PUBLIC static inline NEEDS["io.h"] + +PUBLIC static template< typename VT > inline NEEDS["io.h"] void -Pci::write_cfg16 (Mword bus, Mword dev, Mword subdev, Mword reg, Unsigned16 v) +Pci::write_cfg(Cfg_addr addr, VT value) { - Io::out32 (((bus & 0xffff) << 16) | - ((dev & 0x1f) << 11) | - ((subdev & 0x07) << 8) | - ((reg & 0xfe) ) | - 1<<31, Cfg_addr); - Io::out16 (v, Cfg_data + (reg & 2)); + static_assert (sizeof (VT) == 1 || sizeof (VT) == 2 || sizeof (VT)==4, + "wrong PCI config space access size"); + Io::out32(addr.compat_addr() | (1<<31), Cfg_addr_port); + switch (sizeof(VT)) + { + case 1: Io::out8(value, Cfg_data_port + addr.reg_offs(Cfg_width::Byte)); break; + case 2: Io::out16(value, Cfg_data_port + addr.reg_offs(Cfg_width::Short)); break; + case 4: Io::out32(value, Cfg_data_port + addr.reg_offs(Cfg_width::Long)); break; + } } -PUBLIC static inline NEEDS["io.h"] -void -Pci::write_cfg32 (Mword bus, Mword dev, Mword subdev, Mword reg, Unsigned32 v) -{ - Io::out32 (((bus & 0xffff) << 16) | - ((dev & 0x1f) << 11) | - ((subdev & 0x07) << 8) | - ((reg & 0xfc) ) | - 1<<31, Cfg_addr); - Io::out32 (v, Cfg_data); -} diff --git a/kernel/fiasco/src/drivers/uart.cpp b/kernel/fiasco/src/drivers/uart.cpp index aa064f30..188ea744 100644 --- a/kernel/fiasco/src/drivers/uart.cpp +++ b/kernel/fiasco/src/drivers/uart.cpp @@ -125,7 +125,7 @@ public: { MODE_8N1 = 1, }; -protected: + static L4::Uart *uart(); }; diff --git a/kernel/fiasco/src/jdb/arm/jdb_extensions.cpp b/kernel/fiasco/src/jdb/arm/jdb_extensions.cpp index eba7c0ea..0a2b745b 100644 --- a/kernel/fiasco/src/jdb/arm/jdb_extensions.cpp +++ b/kernel/fiasco/src/jdb/arm/jdb_extensions.cpp @@ -54,9 +54,9 @@ static void tbuf(Thread *t, Entry_frame *r) int len; char c; - Jdb_entry_frame *entry_frame = reinterpret_cast((char *)r - 8); - /* Why the -8? The Jdb_entry_frame has two more members in the beginning - * (see Trap_state_regs) so we're compensating for this with the -8. + Jdb_entry_frame *entry_frame = reinterpret_cast((char *)r - 12); + /* Why the -12? The Jdb_entry_frame has three more members in the beginning + * (see Trap_state_regs) so we're compensating for this with the -12. * Alex: Proper fix? */ user = entry_frame->from_user(); @@ -73,8 +73,7 @@ static void tbuf(Thread *t, Entry_frame *r) case 1: // fiasco_tbuf_log() { Jdb_log_frame *regs = reinterpret_cast(entry_frame); - Tb_entry_ke *tb = - static_cast(Jdb_tbuf::new_entry()); + Tb_entry_ke *tb = Jdb_tbuf::new_entry(); str = regs->str(); tb->set(t, ip-4); for (len=0; (c = s->peek(str++, user)); len++) @@ -94,10 +93,12 @@ static void tbuf(Thread *t, Entry_frame *r) // interrupts are disabled in handle_slow_trap() Jdb_log_3val_frame *regs = reinterpret_cast(entry_frame); - Tb_entry_ke_reg *tb = - static_cast(Jdb_tbuf::new_entry()); + Tb_entry_ke_reg *tb = Jdb_tbuf::new_entry(); str = regs->str(); - tb->set(t, ip-4, regs->val1(), regs->val2(), regs->val3()); + tb->set(t, ip-4); + tb->v[0] = regs->val1(); + tb->v[1] = regs->val2(); + tb->v[2] = regs->val3(); for (len=0; (c = s->peek(str++, user)); len++) tb->set_buf(len, c); tb->term_buf(len); @@ -123,8 +124,7 @@ static void tbuf(Thread *t, Entry_frame *r) case 8: // fiasco_tbuf_log_binary() // interrupts are disabled in handle_slow_trap() Jdb_log_frame *regs = reinterpret_cast(entry_frame); - Tb_entry_ke_bin *tb = - static_cast(Jdb_tbuf::new_entry()); + Tb_entry_ke_bin *tb = Jdb_tbuf::new_entry(); str = regs->str(); tb->set(t, ip-4); for (len=0; len < Tb_entry_ke_bin::SIZE; len++) @@ -165,4 +165,3 @@ static void init_dbg_extensions() } STATIC_INITIALIZER(init_dbg_extensions); - diff --git a/kernel/fiasco/src/jdb/arm/jdb_tcb-arm.cpp b/kernel/fiasco/src/jdb/arm/jdb_tcb-arm.cpp index 3f941e7a..f8950bc6 100644 --- a/kernel/fiasco/src/jdb/arm/jdb_tcb-arm.cpp +++ b/kernel/fiasco/src/jdb/arm/jdb_tcb-arm.cpp @@ -14,7 +14,7 @@ EXTENSION class Jdb_tcb }; IMPLEMENT -void Jdb_tcb::print_entry_frame_regs(Thread *) +void Jdb_tcb::print_entry_frame_regs(Thread *t) { Jdb_entry_frame *ef = Jdb::get_entry_frame(Jdb::current_cpu); int from_user = ef->from_user(); @@ -22,13 +22,13 @@ void Jdb_tcb::print_entry_frame_regs(Thread *) printf("Registers (before debug entry from %s mode):\n" "[0] %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n" "[8] %08lx %08lx %08lx %08lx %08lx %08lx %08lx %s%08lx\033[m\n" - "upsr = %08lx\n", + "upsr=%08lx tpidr: urw=%08lx uro=%08lx\n", from_user ? "user" : "kernel", ef->r[0], ef->r[1],ef->r[2], ef->r[3], ef->r[4], ef->r[5],ef->r[6], ef->r[7], ef->r[8], ef->r[9],ef->r[10], ef->r[11], ef->r[12], ef->usp, ef->ulr, Jdb::esc_iret, ef->pc, - ef->psr); + ef->psr, t->tpidrurw(), t->tpidruro()); } IMPLEMENT diff --git a/kernel/fiasco/src/jdb/ia32/jdb-ia32-amd64.cpp b/kernel/fiasco/src/jdb/ia32/jdb-ia32-amd64.cpp index 2fe08524..a8129982 100644 --- a/kernel/fiasco/src/jdb/ia32/jdb-ia32-amd64.cpp +++ b/kernel/fiasco/src/jdb/ia32/jdb-ia32-amd64.cpp @@ -1017,5 +1017,5 @@ static void Jdb::send_nmi(unsigned cpu) { - Apic::mp_send_ipi(Cpu::cpus.cpu(cpu).phys_id(), 0, Apic::APIC_IPI_NMI); + Apic::mp_send_ipi(Apic::apic.cpu(cpu)->apic_id(), 0, Apic::APIC_IPI_NMI); } diff --git a/kernel/fiasco/src/jdb/ia32/jdb-int3-ia32-ux.cpp b/kernel/fiasco/src/jdb/ia32/jdb-int3-ia32-ux.cpp index eae3c6ee..bef9febd 100644 --- a/kernel/fiasco/src/jdb/ia32/jdb-int3-ia32-ux.cpp +++ b/kernel/fiasco/src/jdb/ia32/jdb-int3-ia32-ux.cpp @@ -53,9 +53,11 @@ Jdb::handle_int3_threadctx_generic(Trap_state *ts) // special: enter_kdebug("*+...") => extended log msg // skip '+' len--; str++; - Tb_entry_ke_reg *tb = - static_cast(Jdb_tbuf::new_entry()); - tb->set(t, ip-1, ts); + Tb_entry_ke_reg *tb = Jdb_tbuf::new_entry(); + tb->set(t, ip-1); + tb->v[0] = ts->value(); + tb->v[1] = ts->value2(); + tb->v[2] = ts->value3(); for (i=0; iset_buf(i, s->peek(str++, user)); tb->term_buf(len); @@ -64,8 +66,7 @@ Jdb::handle_int3_threadctx_generic(Trap_state *ts) { // special: enter_kdebug("*...") => log entry // fill in entry - Tb_entry_ke *tb = - static_cast(Jdb_tbuf::new_entry()); + Tb_entry_ke *tb = Jdb_tbuf::new_entry(); tb->set(t, ip-1); for (i=0; iset_buf(i, s->peek(str++, user)); @@ -160,10 +161,12 @@ Jdb::handle_int3_threadctx_generic(Trap_state *ts) // interrupts are disabled in handle_slow_trap() Jdb_log_3val_frame *regs = reinterpret_cast(ts); - Tb_entry_ke_reg *tb = - static_cast(Jdb_tbuf::new_entry()); + Tb_entry_ke_reg *tb = Jdb_tbuf::new_entry(); str = regs->str(); - tb->set(t, ip-1, regs->val1(), regs->val2(), regs->val3()); + tb->set(t, ip-1); + tb->v[0] = regs->val1(); + tb->v[1] = regs->val2(); + tb->v[2] = regs->val3(); for (len=0; (c = s->peek(str++, user)); len++) tb->set_buf(len, c); tb->term_buf(len); diff --git a/kernel/fiasco/src/jdb/ia32/jdb_io_ports.cpp b/kernel/fiasco/src/jdb/ia32/jdb_io_ports.cpp index aa74b25e..016f72b8 100644 --- a/kernel/fiasco/src/jdb/ia32/jdb_io_ports.cpp +++ b/kernel/fiasco/src/jdb/ia32/jdb_io_ports.cpp @@ -174,11 +174,11 @@ Io_m::action( int cmd, void *&args, char const *&fmt, int &) case 'p': // pci if (cmd == 0) printf(" => 0x%08x", - Pci::read_cfg32 (buf.pci.bus, buf.pci.dev, buf.pci.subdev, - buf.pci.reg)); + Pci::read_cfg(Pci::Cfg_addr(buf.pci.bus, buf.pci.dev, buf.pci.subdev, + buf.pci.reg), Pci::Cfg_width::Long)); else - Pci::write_cfg32 (buf.pci.bus, buf.pci.dev, buf.pci.subdev, - buf.pci.reg, buf.pci.val); + Pci::write_cfg(Pci::Cfg_addr(buf.pci.bus, buf.pci.dev, buf.pci.subdev, + buf.pci.reg), (Unsigned32)buf.pci.val); putchar('\n'); break; diff --git a/kernel/fiasco/src/jdb/ia32/jdb_kern_info-pci.cpp b/kernel/fiasco/src/jdb/ia32/jdb_kern_info-pci.cpp index de0f1f12..4d81b8aa 100644 --- a/kernel/fiasco/src/jdb/ia32/jdb_kern_info-pci.cpp +++ b/kernel/fiasco/src/jdb/ia32/jdb_kern_info-pci.cpp @@ -33,34 +33,37 @@ Jdb_kern_info_pci::show() "data aquisition/signal processing controller" }; Mword bus, buses, dev, subdev, subdevs; - for (bus=0, buses=1; bus > guard(&_remote_call_lock); + auto guard = lock_guard(_remote_call_lock); _remote_work_ipi_func = f; _remote_work_ipi_func_data = data; diff --git a/kernel/fiasco/src/jdb/jdb_dbinfo.cpp b/kernel/fiasco/src/jdb/jdb_dbinfo.cpp index 1fefbe5f..2163af45 100644 --- a/kernel/fiasco/src/jdb/jdb_dbinfo.cpp +++ b/kernel/fiasco/src/jdb/jdb_dbinfo.cpp @@ -81,7 +81,7 @@ PRIVATE static Address Jdb_dbinfo::reserve_pages(unsigned pages) { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); Unsigned8 *ptr, bit; @@ -134,7 +134,7 @@ PRIVATE static void Jdb_dbinfo::return_pages(Address addr, unsigned pages) { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); unsigned nr_page = (addr-area_start) / Config::PAGE_SIZE; Unsigned8 *ptr = bitmap + nr_page/8, bit = nr_page % 8; diff --git a/kernel/fiasco/src/jdb/jdb_kern_info-bench.cpp b/kernel/fiasco/src/jdb/jdb_kern_info-bench.cpp index 1c7b516d..d6b0f4a5 100644 --- a/kernel/fiasco/src/jdb/jdb_kern_info-bench.cpp +++ b/kernel/fiasco/src/jdb/jdb_kern_info-bench.cpp @@ -128,7 +128,7 @@ Jdb_kern_info_bench::do_mp_benchmark() for (unsigned u = 0; u < Config::Max_num_cpus; ++u) if (Cpu::online(u)) { - printf("l%2u(p%8u): ", u, Cpu::cpus.cpu(u).phys_id()); + printf("l%2u: ", u); for (unsigned v = 0; v < Config::Max_num_cpus; ++v) if (Cpu::online(v)) diff --git a/kernel/fiasco/src/jdb/jdb_kobject_names.cpp b/kernel/fiasco/src/jdb/jdb_kobject_names.cpp index 30e63c70..813990ec 100644 --- a/kernel/fiasco/src/jdb/jdb_kobject_names.cpp +++ b/kernel/fiasco/src/jdb/jdb_kobject_names.cpp @@ -80,7 +80,7 @@ Jdb_kobject_name::operator new (size_t) throw() void **o = reinterpret_cast(n); if (!*o) { - Lock_guard > g(&allocator_lock); + auto g = lock_guard(allocator_lock); if (!*o) { *o = (void*)10; @@ -99,7 +99,7 @@ IMPLEMENT void Jdb_kobject_name::operator delete (void *p) { - Lock_guard > g(&allocator_lock); + auto g = lock_guard(allocator_lock); void **o = reinterpret_cast(p); *o = 0; } diff --git a/kernel/fiasco/src/jdb/jdb_mapdb.cpp b/kernel/fiasco/src/jdb/jdb_mapdb.cpp index 1f8abbc3..fe86479e 100644 --- a/kernel/fiasco/src/jdb/jdb_mapdb.cpp +++ b/kernel/fiasco/src/jdb/jdb_mapdb.cpp @@ -194,7 +194,7 @@ Jdb_mapdb::show (Page_number page, char which_mapdb) page_shift = 0; //Config::PAGE_SHIFT; super_inc = Page_count::create(Config::SUPERPAGE_SIZE / Config::PAGE_SIZE); break; -#ifdef CONFIG_IO_PROT +#ifdef CONFIG_PF_PC case 'i': type = "I/O port"; mapdb = mapdb_io.get(); @@ -263,7 +263,7 @@ Jdb_mapdb::show (Page_number page, char which_mapdb) break; case ' ': if (which_mapdb == 'm') -#ifdef CONFIG_IO_PROT +#ifdef CONFIG_PF_PC which_mapdb = 'i'; else if (which_mapdb == 'i') #endif @@ -320,7 +320,7 @@ Jdb_mapdb::action(int cmd, void *&args, char const *&fmt, int &next_char) fmt = " frame: " L4_FRAME_INPUT_FMT; break; -#ifdef CONFIG_IO_PROT +#ifdef CONFIG_PF_PC case 'i': fmt = " port: " L4_FRAME_INPUT_FMT; break; @@ -527,9 +527,6 @@ Jdb_mapdb::show_simple_tree(Kobject_common *f, unsigned indent = 1) } puts(Jdb_screen::Line); - - - return true; } diff --git a/kernel/fiasco/src/jdb/jdb_tbuf.cpp b/kernel/fiasco/src/jdb/jdb_tbuf.cpp index ccb20445..dc8ecd65 100644 --- a/kernel/fiasco/src/jdb/jdb_tbuf.cpp +++ b/kernel/fiasco/src/jdb/jdb_tbuf.cpp @@ -22,8 +22,8 @@ public: }; protected: - static Tb_entry *_tbuf_act; // current entry - static Tb_entry *_tbuf_max; + static Tb_entry_union *_tbuf_act; // current entry + static Tb_entry_union *_tbuf_max; static Mword _entries; // number of occupied entries static Mword _max_entries; // maximum number of entries static Mword _filter_enabled;// !=0 if filter is active @@ -49,13 +49,14 @@ protected: ".section \".debug.jdb.log_table\" \n\t" \ ".long 2f \n\t" \ ".long 1b \n\t" \ - ".long "#fmt" \n\t" \ + ".long %c[xfmt] \n\t" \ ".section \".rodata.log.str\" \n\t" \ "2: .asciz "#name" \n\t" \ " .asciz "#sc" \n\t" \ ".popsection \n\t" \ "movb 1b,%0 \n\t" \ - : "=q"(__do_log__) ); \ + : "=q"(__do_log__) \ + : [xfmt] "i" (&Tb_entry_formatter_t::singleton)); \ if (EXPECT_FALSE( __do_log__ )) \ { @@ -69,12 +70,13 @@ protected: ".pushsection \".debug.jdb.log_table\" \n\t" \ "3: .long 2f \n\t" \ " .long 1b \n\t" \ - " .long "#fmt" \n\t" \ + " .long %c[xfmt] \n\t" \ ".section \".rodata.log.str\" \n\t" \ "2: .asciz "#name" \n\t" \ " .asciz "#sc" \n\t" \ ".popsection \n\t" \ - : "=r"(__do_log__)); \ + : "=r"(__do_log__) \ + : [xfmt] "i" (&Tb_entry_formatter_t::singleton)); \ if (EXPECT_FALSE( __do_log__ )) \ { @@ -88,12 +90,13 @@ protected: ".pushsection \".debug.jdb.log_table\" \n\t" \ "3: .long 2f \n\t" \ " .long 1b + 1 \n\t" \ - " .long "#fmt" \n\t" \ + " .long %a[xfmt] \n\t" \ ".section \".rodata.log.str\" \n\t" \ "2: .asciz "#name" \n\t" \ " .asciz "#sc" \n\t" \ ".popsection \n\t" \ - : "=b"(__do_log__)); \ + : "=b"(__do_log__) \ + : [xfmt] "i" (&Tb_entry_formatter_t::singleton)); \ if (EXPECT_FALSE( __do_log__ )) \ { @@ -106,14 +109,16 @@ protected: ".pushsection \".debug.jdb.log_table\" \n\t" \ "3: .quad 2f \n\t" \ " .quad 1b + 1 \n\t" \ - " .quad "#fmt" \n\t" \ + " .quad %c[xfmt] \n\t" \ ".section \".rodata.log.str\" \n\t" \ "2: .asciz "#name" \n\t" \ " .asciz "#sc" \n\t" \ ".popsection \n\t" \ - : "=b"(__do_log__)); \ + : "=b"(__do_log__) \ + : [xfmt] "i"(&Tb_entry_formatter_t::singleton) ); \ if (EXPECT_FALSE( __do_log__ )) \ { + #elif defined(CONFIG_PPC32) //#warning TODO: Dummy implementation for PPC32 #define BEGIN_LOG_EVENT(name, sc, fmt) \ @@ -152,8 +157,8 @@ IMPLEMENTATION: #include "mem_layout.h" #include "std_macros.h" -Tb_entry *Jdb_tbuf::_tbuf_act; -Tb_entry *Jdb_tbuf::_tbuf_max; +Tb_entry_union *Jdb_tbuf::_tbuf_act; +Tb_entry_union *Jdb_tbuf::_tbuf_max; Mword Jdb_tbuf::_entries; Mword Jdb_tbuf::_max_entries; Mword Jdb_tbuf::_filter_enabled; @@ -176,10 +181,10 @@ Jdb_tbuf::status() } PROTECTED static inline NEEDS["mem_layout.h"] -Tb_entry * +Tb_entry_union * Jdb_tbuf::buffer() { - return (Tb_entry*)Mem_layout::Tbuf_buffer_area; + return (Tb_entry_union*)Mem_layout::Tbuf_buffer_area; } PUBLIC static inline @@ -210,7 +215,7 @@ Jdb_tbuf::new_entry() { Tb_entry *tb; { - Lock_guard guard(&_lock); + auto guard = lock_guard(_lock); tb = _tbuf_act; @@ -232,6 +237,14 @@ Jdb_tbuf::new_entry() return tb; } +PUBLIC template static inline +T* +Jdb_tbuf::new_entry() +{ + static_assert(sizeof(T) <= sizeof(Tb_entry_union), "tb entry T too big"); + return static_cast(new_entry()); +} + /** Commit tracebuffer entry. */ PUBLIC static void @@ -248,7 +261,7 @@ Jdb_tbuf::commit_entry() // fire the virtual 'buffer full' irq if (_observer) { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); _observer->notify(); } #endif @@ -321,12 +334,12 @@ Jdb_tbuf::unfiltered_lookup(Mword idx) if (!event_valid(idx)) return 0; - Tb_entry *e = _tbuf_act - idx - 1; + Tb_entry_union *e = _tbuf_act - idx - 1; if (e < buffer()) e += _max_entries; - return static_cast(e); + return e; } /** Return pointer to tracebuffer event. @@ -359,9 +372,9 @@ Jdb_tbuf::lookup(Mword look_idx) PUBLIC static Mword -Jdb_tbuf::unfiltered_idx(Tb_entry *e) +Jdb_tbuf::unfiltered_idx(Tb_entry const *e) { - Tb_entry *ef = static_cast(e); + Tb_entry_union const *ef = static_cast(e); Mword idx = _tbuf_act - ef - 1; if (idx > _max_entries) @@ -373,12 +386,12 @@ Jdb_tbuf::unfiltered_idx(Tb_entry *e) /** Tb_entry => tracebuffer index. */ PUBLIC static Mword -Jdb_tbuf::idx(Tb_entry *e) +Jdb_tbuf::idx(Tb_entry const *e) { if (!_filter_enabled) return unfiltered_idx(e); - Tb_entry *ef = static_cast(e); + Tb_entry_union const *ef = static_cast(e); Mword idx = (Mword)-1; for (;;) @@ -402,7 +415,7 @@ Jdb_tbuf::search(Mword nr) { Tb_entry *e; - for (Mword idx=0; (e = unfiltered_lookup(idx)); idx++) + for (Mword idx = 0; (e = unfiltered_lookup(idx)); idx++) if (e->number() == nr) return e; @@ -471,99 +484,6 @@ Jdb_tbuf::event(Mword idx, Mword *number, Unsigned32 *kclock, return true; } -/** Search the paired event to an ipc event or ipc result event. - * @param idx number of event to search the pair event for - * @retval type type of pair event - * @return number of pair event */ -PUBLIC static -Tb_entry* -Jdb_tbuf::ipc_pair_event(Mword idx, Unsigned8 *type) -{ - Tb_entry *e = lookup(idx); - - if (!e) - return 0; - - if (e->type() == Tbuf_ipc_res) - { - *type = Event; - return search(static_cast(e)->pair_event()); - } - - if (e->type() != Tbuf_ipc) - return 0; - - Tb_entry_ipc *e0 = static_cast(e); - Tb_entry_ipc_res *e1; - - // start at e and go until future until current event - while (idx > 0 && ((e1 = static_cast(lookup(--idx))))) - { - if (e1->type() == Tbuf_ipc_res && e1->pair_event() == e0->number()) - { - *type = Result; - return e1; - } - } - - return 0; -} - -/** Search the paired event to a pagefault / result event. - * @param idx position of event in tracebuffer to search the pair event for - * @retval type type of pair event - * @return number of pair event */ -PUBLIC static -Tb_entry* -Jdb_tbuf::pf_pair_event(Mword idx, Unsigned8 *type) -{ - Tb_entry *e = lookup(idx); - - if (!e) - return 0; - - if (e->type() == Tbuf_pf_res) - { - // we have a pf result event and we search the paired pf event - Tb_entry_pf_res *e0 = static_cast(e); - Tb_entry_pf *e1; - - // start at e and go into past until oldst event - while (((e1 = static_cast(lookup(++idx))))) - { - if (e1->type() == Tbuf_pf && - e1->ctx() == e0->ctx() && - e1->ip() == e0->ip() && - e1->pfa() == e0->pfa()) - { - *type = Event; - return e1; - } - } - } - else if (e->type() == Tbuf_pf) - { - // we have a pf event and we search the paired pf result event - Tb_entry_pf *e0 = static_cast(e); - Tb_entry_pf_res *e1; - - // start at e and go until future until current event - while (idx > 0 && ((e1 = static_cast(lookup(--idx))))) - { - if (e1->type() == Tbuf_pf_res && - e1->ctx() == e0->ctx() && - e1->ip() == e0->ip() && - e1->pfa() == e0->pfa()) - { - *type = Result; - return e1; - } - } - } - - return 0; -} - /** Get difference CPU cycles between event idx and event idx+1. * @param idx position of first event in tracebuffer * @retval difference in CPU cycles diff --git a/kernel/fiasco/src/jdb/jdb_tbuf_init.cpp b/kernel/fiasco/src/jdb/jdb_tbuf_init.cpp index baaa0e9e..74c4feae 100644 --- a/kernel/fiasco/src/jdb/jdb_tbuf_init.cpp +++ b/kernel/fiasco/src/jdb/jdb_tbuf_init.cpp @@ -45,18 +45,18 @@ void Jdb_tbuf_init::init() // minimum: 8KB ( 2 pages), maximum: 2MB (512 pages) // must be a power of 2 (for performance reasons) - for (n = Config::PAGE_SIZE/sizeof(Tb_entry); - n < want_entries && n*sizeof(Tb_entry)<0x200000; - n<<=1) + for (n = Config::PAGE_SIZE / sizeof(Tb_entry_union); + n < want_entries && n * sizeof(Tb_entry_union) < 0x200000; + n <<= 1) ; if (n < want_entries) panic("Cannot allocate more than %d entries for tracebuffer\n", n); max_entries(n); - unsigned size = n*sizeof(Tb_entry); + unsigned size = n * sizeof(Tb_entry_union); - if (! Vmem_alloc::page_alloc((void*) status(), Vmem_alloc::ZERO_FILL, Vmem_alloc::User)) + if (!Vmem_alloc::page_alloc((void*) status(), Vmem_alloc::ZERO_FILL, Vmem_alloc::User)) panic("jdb_tbuf: alloc status page at " L4_PTR_FMT " failed", (Address)Mem_layout::Tbuf_status_page); @@ -65,7 +65,7 @@ void Jdb_tbuf_init::init() { if (! Vmem_alloc::page_alloc((void*)va, Vmem_alloc::NO_ZERO_FILL, Vmem_alloc::User)) panic("jdb_tbuf: alloc buffer at " L4_PTR_FMT " failed", va); - + va += Config::PAGE_SIZE; } @@ -76,7 +76,6 @@ void Jdb_tbuf_init::init() status()->window[0].version = status()->window[1].version = 0; - status()->scaler_tsc_to_ns = Cpu::boot_cpu()->get_scaler_tsc_to_ns(); status()->scaler_tsc_to_us = Cpu::boot_cpu()->get_scaler_tsc_to_us(); status()->scaler_ns_to_tsc = Cpu::boot_cpu()->get_scaler_ns_to_tsc(); diff --git a/kernel/fiasco/src/jdb/jdb_tbuf_output.cpp b/kernel/fiasco/src/jdb/jdb_tbuf_output.cpp index 138bf9e5..18c94f03 100644 --- a/kernel/fiasco/src/jdb/jdb_tbuf_output.cpp +++ b/kernel/fiasco/src/jdb/jdb_tbuf_output.cpp @@ -39,7 +39,7 @@ IMPLEMENTATION: #include "watchdog.h" -Jdb_tbuf_output::Format_entry_fn *Jdb_tbuf_output::_format_entry_fn[Tbuf_max]; +Jdb_tbuf_output::Format_entry_fn *Jdb_tbuf_output::_format_entry_fn[Tbuf_dynentries]; bool Jdb_tbuf_output::show_names; static void @@ -99,7 +99,7 @@ PUBLIC static void Jdb_tbuf_output::register_ff(Unsigned8 type, Format_entry_fn format_entry_fn) { - assert(type < Tbuf_max); + assert(type < Tbuf_dynentries); if ( (_format_entry_fn[type] != 0) && (_format_entry_fn[type] != dummy_format_entry)) @@ -157,13 +157,13 @@ formatter_default(Tb_entry *tb, const char *tidstr, unsigned tidlen, snprintf(ip_buf, sizeof(ip_buf), " @ " L4_PTR_FMT, e->ip()); snprintf(buf, maxlen, "\"%s\" " L4_PTR_FMT " " L4_PTR_FMT " " L4_PTR_FMT "%s", - e->msg(), e->val1(), e->val2(), e->val3(), + e->msg(), e->v[0], e->v[1], e->v[2], e->ip() ? ip_buf : ""); return maxlen; } - return fmt(tb, maxlen, buf); + return fmt->print(tb, maxlen, buf); } PUBLIC static diff --git a/kernel/fiasco/src/jdb/jdb_tbuf_show.cpp b/kernel/fiasco/src/jdb/jdb_tbuf_show.cpp index 15c27014..d88ef390 100644 --- a/kernel/fiasco/src/jdb/jdb_tbuf_show.cpp +++ b/kernel/fiasco/src/jdb/jdb_tbuf_show.cpp @@ -22,6 +22,41 @@ IMPLEMENTATION: #include "static_init.h" #include "thread.h" +class Entry_group +{ +public: + enum { Max_group_size = 10 }; + typedef Tb_entry::Group_order Group_order; + + struct Item + { + Tb_entry const *e; + Mword y; + Group_order order; + Item() : e(0), y(0), order(Group_order::none()) {} + }; + + Entry_group() : _c(0) {} + + Item const &operator [] (unsigned i) const { return _i[i]; } + Item &operator [] (unsigned i) { return _i[i]; } + unsigned size() const { return _c; } + bool full() const { return _c >= Max_group_size; } + unsigned push_back(Tb_entry const *e, Mword y, Group_order t) + { + unsigned p = _c++; + Item *u = &_i[p]; + u->e = e; + u->y = y; + u->order = t; + return p; + } + +private: + unsigned _c; + Item _i[Max_group_size]; +}; + class Jdb_tbuf_show : public Jdb_module { public: @@ -494,7 +529,7 @@ Jdb_tbuf_show::show_events(Mword n, Mword ref, Mword count, Unsigned8 mode, } } printf("%s%-*.*s %12s\033[m%s", - c, Jdb_screen::width()-13, (int)Jdb_screen::width()-13, + c, Jdb_screen::width()-13, (int)Jdb_screen::width()-13, _buffer_str+y_offset, s, count != 1 ? "\n" : ""); } n++; @@ -503,7 +538,7 @@ Jdb_tbuf_show::show_events(Mword n, Mword ref, Mword count, Unsigned8 mode, // search in tracebuffer static Mword -Jdb_tbuf_show::search(Mword start, Mword entries, const char *str, +Jdb_tbuf_show::search(Mword start, Mword entries, const char *str, Unsigned8 direction) { Mword found = Nil; @@ -521,7 +556,7 @@ Jdb_tbuf_show::search(Mword start, Mword entries, const char *str, { static char buffer[120]; - // don't cycle through entries more than once + // don't cycle through entries more than once // (should not happen due to the following check) if (n == start) break; @@ -549,11 +584,11 @@ Jdb_tbuf_show::search(Mword start, Mword entries, const char *str, if (Jdb_regex::avail() && Jdb_regex::find(buffer, 0, 0)) { - found = n; + found = n; break; } else if (strstr(buffer, str)) - { + { found = n; break; } @@ -566,6 +601,62 @@ Jdb_tbuf_show::search(Mword start, Mword entries, const char *str, return found; } + +static void +Jdb_tbuf_show::find_group(Entry_group *g, Tb_entry const *e, bool older, unsigned lines, + unsigned depth) +{ + typedef Entry_group::Group_order Group_order; + + Tb_entry_formatter const *fmt = Tb_entry_formatter::get_fmt(e); + Mword idx = Jdb_tbuf::unfiltered_idx(e); + int dir = older ? 1 : -1; + while (idx > 0 && !g->full()) + { + idx += dir; + Tb_entry *e1 = Jdb_tbuf::unfiltered_lookup(idx); + if (!e1) + return; + + Mword py; + Group_order t = fmt->is_pair(e, e1); + if (t.grouped()) + { + py = Jdb_tbuf::idx(e1); + if (py < _absy || py >= _absy + lines) + return; + + if (older && t.depth() >= depth) + return; + if (!older && t.depth() <= depth) + return; + + g->push_back(e1, py, t); + + if (older && t.is_first()) + return; + if (!older && t.is_last()) + return; + + continue; + } + + if (!t.is_direct()) + continue; + + Tb_entry_formatter const *fmt2 = Tb_entry_formatter::get_fmt(e1); + if (fmt2 && fmt2->partner(e1) == e->number()) + { + py = Jdb_tbuf::idx(e1); + if (py < _absy || py >= _absy + lines) + return; + g->push_back(e1, py, older ? Group_order::first() : Group_order::last()); + // HM: is one direct enry enough + return; + } + } +} + static void Jdb_tbuf_show::show() { @@ -636,9 +727,9 @@ restart: Jdb::cursor(); printf("%3lu%% of %-6lu Perf:%-4s 1=" L4_PTR_FMT "(%s%s\033[m%s%s%s\033[m)\033[K", - Jdb_tbuf::unfiltered_entries()*100/Jdb_tbuf::max_entries(), + Jdb_tbuf::unfiltered_entries()*100/Jdb_tbuf::max_entries(), Jdb_tbuf::max_entries(), - perf_type, perf_event[0], Jdb::esc_emph, perf_mode[0], + perf_type, perf_event[0], Jdb::esc_emph, perf_mode[0], perf_name[0] && *perf_name[0] ? ":" : "", mode==Pmc1_delta_mode || mode==Pmc1_ref_mode ? Jdb::esc_emph : "", perf_name[0]); @@ -671,11 +762,9 @@ restart: status_line: for (bool redraw=false; !redraw;) - { - Tb_entry *pair_event = 0; - Mword pair_y = 0; + { + Smword c; - Unsigned8 type; Unsigned8 d = 0; // default search direction is forward if (_status_type == Status_redraw) @@ -687,44 +776,58 @@ restart: else if (_status_type == Status_error) _status_type = Status_redraw; - if (!_filter_str[0]) - { - // search for paired ipc event - pair_event = Jdb_tbuf::ipc_pair_event(_absy+addy, &type); - if (!pair_event) - // search for paired pagefault event - pair_event = Jdb_tbuf::pf_pair_event(_absy+addy, &type); - if (pair_event) - { - pair_y = Jdb_tbuf::idx(pair_event); - if (pair_y < _absy || pair_y >= _absy+lines) - pair_event = 0; - } - if (pair_event) - { - Jdb::cursor(pair_y-_absy+Tbuf_start_line, 1); - putstr(Jdb::esc_emph); - switch (type) - { - case Jdb_tbuf::Result: putstr("+++>"); break; - case Jdb_tbuf::Event: putstr("<+++"); break; - } - putstr("\033[m"); - } - } + Entry_group group; + + if (!_filter_str[0]) + { + typedef Tb_entry::Group_order Group_order; + + Tb_entry const *ce = Jdb_tbuf::lookup(_absy + addy); + Tb_entry_formatter const *fmt = Tb_entry_formatter::get_fmt(ce); + Group_order pt; + + if (fmt) + pt = fmt->has_partner(ce); + + if (!pt.not_grouped()) + { + if (!pt.is_first()) + find_group(&group, ce, true, lines, pt.depth()); + if (!pt.is_last()) + find_group(&group, ce, false, lines, pt.depth()); + } + + for (unsigned i = 0; i < group.size(); ++i) + { + Entry_group::Item const &item = group[i]; + Jdb::cursor(item.y - _absy + Tbuf_start_line, 3); + putstr(Jdb::esc_emph); + if (item.order.is_first()) + putstr("<++"); + else if (item.order.is_last()) + putstr("++>"); + else if (item.order.grouped()) + putstr("+++"); + putstr("\033[m"); + } + } Jdb::cursor(addy+Tbuf_start_line, 1); putstr(Jdb::esc_emph); show_events(_absy+addy, refy, 1, mode, time_mode, 0); putstr("\033[m"); Jdb::cursor(addy+Tbuf_start_line, 1); + + // WAIT for key..... c=Jdb_core::getchar(); + show_events(_absy+addy, refy, 1, mode, time_mode, 0); - if (pair_event) - { - Jdb::cursor(pair_y-_absy+Tbuf_start_line, 1); - show_events(pair_y, refy, 1, mode, time_mode, 0); - } + for (unsigned i = 0; i < group.size(); ++i) + { + Entry_group::Item const &item = group[i]; + Jdb::cursor(item.y - _absy + Tbuf_start_line, 1); + show_events(item.y, refy, 1, mode, time_mode, 0); + } if (Jdb::std_cursor_key(c, cols, lines, max_absy, &_absy, &addy, 0, &redraw)) diff --git a/kernel/fiasco/src/jdb/jdb_tcb.cpp b/kernel/fiasco/src/jdb/jdb_tcb.cpp index 8f33fde3..eb7b2948 100644 --- a/kernel/fiasco/src/jdb/jdb_tcb.cpp +++ b/kernel/fiasco/src/jdb/jdb_tcb.cpp @@ -561,7 +561,7 @@ whole_screen: printf("\t\ttimeslice: %llu/%llu %cs\n" "pager\t: ", - t->sched()->left(), t->sched()->quantum(), Config::char_micro); + t->sched()->left(), ~0ULL/*t->sched()->quantum()*/, Config::char_micro); print_kobject(t, t->_pager.raw()); putstr("\ttask : "); @@ -867,7 +867,7 @@ Jdb_tcb::show_kobject_short(char *buf, int max, Kobject_common *o) Thread *t = Kobject::dcast(Kobject::from_dbg(o->dbg_info())); bool is_current = Jdb_tcb::is_current(t); int cnt = 0; - if (t->space() == Kernel_task::kernel_task()) + if (t == Context::kernel_context(t->cpu())) { cnt = snprintf(buf, max, " {KERNEL} C=%u", t->cpu()); max -= cnt; @@ -898,7 +898,7 @@ Jdb_tcb::cmds() const { { 0, "t", "tcb", "%C", "t[]\tshow current/given thread control block (TCB)\n" - "t{+|-}\tshow current thread control block at Jdb every entry\n", + "t{+|-}\tshow current thread control block at every JDB entry\n", &first_char }, }; return cs; diff --git a/kernel/fiasco/src/jdb/jdb_tetris.cpp b/kernel/fiasco/src/jdb/jdb_tetris.cpp index bd24ae4e..c23009bc 100644 --- a/kernel/fiasco/src/jdb/jdb_tetris.cpp +++ b/kernel/fiasco/src/jdb/jdb_tetris.cpp @@ -56,28 +56,28 @@ static void show_grid() { int i, j; - printf ("\033[H"); + printf("\033[H"); for (i = j = 0; i < 264; i++) { if (grid[i]) - printf ("\033[m\033[1;4%d;30m \033[40m", grid[i]); + printf("\033[m\033[1;4%d;30m \033[40m", grid[i]); else - putstr (" "); + putstr(" "); if (i % 12 == 11) { for (; j <= i && j < 48; j++) if (next[j]) - printf ("\033[m\033[1;4%d;30m \033[40m", next[j]); + printf("\033[m\033[1;4%d;30m \033[40m", next[j]); else - putstr ("\033[m\033[30m \033[m"); + putstr("\033[m\033[30m \033[m"); - putchar ('\n'); + putchar('\n'); } - } + } - printf ("\033[mLines: %d Score: %d %s\033[K", lines, score, modes[mode]); + printf("\033[mLines: %d Score: %d %s\033[K", lines, score, modes[mode]); } IMPLEMENTATION [!ux]: @@ -91,28 +91,28 @@ static void show_grid() { int i, j; - printf ("\033[H"); + printf("\033[H"); for (i = j = 0; i < 264; i++) { if (grid[i]) - printf ("\033[1;3%dm\333\333", grid[i]); + printf("\033[1;3%dm\333\333", grid[i]); else - putstr (" "); + putstr(" "); if (i % 12 == 11) { for (; j <= i && j < 48; j++) if (next[j]) - printf ("\033[1;3%dm\333\333", next[j]); + printf("\033[1;3%dm\333\333", next[j]); else - putstr (" "); + putstr(" "); - putchar ('\n'); + putchar('\n'); } - } + } - printf ("Lines: %d Score: %d %s\033[K", lines, score, modes[mode]); + printf("Lines: %d Score: %d %s\033[K", lines, score, modes[mode]); } IMPLEMENTATION: @@ -125,7 +125,7 @@ static int getchar_timeout() to = slice_to_timeout(to); while (--to) { - if ((c = Kconsole::console()->getchar (false)) != -1) + if ((c = Kconsole::console()->getchar(false)) != -1) return c; if (Config::getchar_does_hlt_works_ok) @@ -145,14 +145,14 @@ static void add_score(int value) slice--; if (slice < 0) - slice = 0; + slice = 0; score += value; } -static long unsigned int myrand() +static long unsigned int myrand() { - randseed = (randseed * 13561+14000) % 150001; + randseed = (randseed * 13561 + 14000) % 150001; return randseed; } @@ -171,27 +171,27 @@ static int try_move (int pos, int *tile) return 1; } - -static void set_grid (int color) + +static void set_grid(int color) { grid[current_pos] = - grid[current_pos+current_tile[2]] = - grid[current_pos+current_tile[3]] = - grid[current_pos+current_tile[4]] = color; + grid[current_pos + current_tile[2]] = + grid[current_pos + current_tile[3]] = + grid[current_pos + current_tile[4]] = color; } static void set_next (int color) { next[17] = - next[17+next_tile[2]] = - next[17+next_tile[3]] = - next[17+next_tile[4]] = color; + next[17 + next_tile[2]] = + next[17 + next_tile[3]] = + next[17 + next_tile[4]] = color; } void show_tile (void) { set_grid(current_tile[5]); - set_next(next_tile[5]); + set_next(next_tile[5]); show_grid(); @@ -204,7 +204,7 @@ void show_tile (void) * * This module makes fun. */ -class Jdb_tetris_m +class Jdb_tetris_m : public Jdb_module { public: @@ -220,7 +220,7 @@ Jdb_tetris_m::Jdb_tetris_m() PUBLIC Jdb_module::Action_code -Jdb_tetris_m::action( int, void *&, char const *&, int & ) +Jdb_tetris_m::action(int, void *&, char const *&, int &) { int i, j, k, c; @@ -228,20 +228,20 @@ Jdb_tetris_m::action( int, void *&, char const *&, int & ) slice = 300; randseed= Cpu::rdtsc() & 0xffffffff; - puts ("\nDisabling output of serial console -- quit Tetris with 'q'!"); + puts("\nDisabling output of serial console -- quit Tetris with 'q'!"); Kconsole::console()->change_state(Console::UART, 0, ~Console::OUTENABLED, 0); - printf ("\033[H\033[J"); + printf("\033[H\033[J"); // Setup grid borders for (i = 0; i < 264; i++) grid[i] = (i % 12 == 0 || i % 12 == 11 || i > 251) ? 7 : 0; - try_move (17, new_tile()); + try_move(17, new_tile()); next_tile = new_tile(); while (1) - { + { if (c < 0) { if (!try_move (current_pos + 12, current_tile)) @@ -250,45 +250,50 @@ Jdb_tetris_m::action( int, void *&, char const *&, int & ) for (i = k = 0; i < 252; i += 12) for (j = i; grid[++j];) - if (j - i == 10) { - while (j > i) grid[j--] = 0; show_grid(); - while (--j) grid[j + 12] = grid[j]; show_grid(); - k++; - } + if (j - i == 10) + { + while (j > i) + grid[j--] = 0; + show_grid(); + while (--j) + grid[j + 12] = grid[j]; + show_grid(); + k++; + } lines += k; - add_score (k ? (1 << k) * 10 : 1); + add_score(k ? (1 << k) * 10 : 1); - if (!try_move (17, next_tile)) + if (!try_move(17, next_tile)) break; next_tile = new_tile(); } - } + } // Move left else if (c == KEY_CURSOR_LEFT) - try_move (current_pos - 1, current_tile); + try_move(current_pos - 1, current_tile); // Move right else if (c == KEY_CURSOR_RIGHT) - try_move (current_pos + 1, current_tile); + try_move(current_pos + 1, current_tile); // Drop tile else if (c == ' ') - while (try_move (current_pos + 12, current_tile)) + while (try_move(current_pos + 12, current_tile)) { show_tile(); add_score(3); } - + // Left-turn tile else if (c == KEY_CURSOR_DOWN) - try_move (current_pos, tiles + 6 ** current_tile); + try_move(current_pos, tiles + 6 ** current_tile); // Right-turn tile else if (c == KEY_CURSOR_UP) - try_move (current_pos, tiles + 6 ** (current_tile+1)); + try_move(current_pos, tiles + 6 ** (current_tile + 1)); // Quit else if (c == 'q' || c == KEY_ESC) @@ -304,7 +309,7 @@ Jdb_tetris_m::action( int, void *&, char const *&, int & ) } Kconsole::console()->change_state(Console::UART, 0, ~0U, Console::OUTENABLED); - printf ("\033[0m"); + printf("\033[0m"); return NOTHING; } @@ -312,7 +317,7 @@ Jdb_tetris_m::action( int, void *&, char const *&, int & ) PUBLIC int Jdb_tetris_m::num_cmds() const -{ +{ return 1; } @@ -321,7 +326,7 @@ Jdb_module::Cmd const * Jdb_tetris_m::cmds() const { static Cmd cs[] = - { + { { 0, "X", "X", "", "X\tPlay Tetris (cursor keys = left/right/rotate;\n" "\t[space] = drop; q = quit)", 0 }, diff --git a/kernel/fiasco/src/jdb/jdb_thread_list.cpp b/kernel/fiasco/src/jdb/jdb_thread_list.cpp index 58992d8f..e0da7ead 100644 --- a/kernel/fiasco/src/jdb/jdb_thread_list.cpp +++ b/kernel/fiasco/src/jdb/jdb_thread_list.cpp @@ -216,7 +216,7 @@ static inline NOEXPORT Sched_context * Jdb_thread_list::sc_wfq_iter_prev(Sched_context *t) { - Sched_context::Ready_queue &rq = Sched_context::rq(cpu); + Sched_context::Ready_queue &rq = Sched_context::rq.cpu(cpu); Sched_context **rl = RQP::link(t); if (!rl || rl == RQP::idle(rq)) return RQP::cnt(rq) ? RQP::heap(rq)[RQP::cnt(rq) - 1] : *RQP::idle(rq); @@ -232,7 +232,7 @@ static inline NOEXPORT Sched_context * Jdb_thread_list::sc_wfq_iter_next(Sched_context *t) { - Sched_context::Ready_queue &rq = Sched_context::rq(cpu); + Sched_context::Ready_queue &rq = Sched_context::rq.cpu(cpu); Sched_context **rl = RQP::link(t); if (!rl || rl == RQP::idle(rq)) return RQP::cnt(rq) ? RQP::heap(rq)[0] : *RQP::idle(rq); @@ -255,7 +255,7 @@ Sched_context * Jdb_thread_list::sc_fp_iter_prev(Sched_context *t) { unsigned prio = RQP::prio(t); - Sched_context::Ready_queue &rq = Sched_context::_ready_q.cpu(cpu); + Sched_context::Ready_queue &rq = Sched_context::rq.cpu(cpu); if (t != RQP::prio_next(rq, prio)) return RQP::prev(t); @@ -275,7 +275,7 @@ Sched_context * Jdb_thread_list::sc_fp_iter_next(Sched_context *t) { unsigned prio = RQP::prio(t); - Sched_context::Ready_queue &rq = Sched_context::_ready_q.cpu(cpu); + Sched_context::Ready_queue &rq = Sched_context::rq.cpu(cpu); if (RQP::next(t) != RQP::prio_next(rq, prio)) return RQP::next(t); @@ -734,10 +734,10 @@ Jdb_thread_list::list_threads(Thread *t_start, char pr) { // Hm, we are in JDB, however we have to make the assertion in // ready_enqueue happy. - Lock_guard g(&cpu_lock); + auto g = lock_guard(cpu_lock); // enqueue current, which may not be in the ready list due to lazy queueing if (!t_current->in_ready_list()) - t_current->ready_enqueue(false); + Sched_context::rq.cpu(t_current->cpu()).ready_enqueue(t_current->sched()); } Jdb::clear_screen(); diff --git a/kernel/fiasco/src/jdb/jdb_timeout.cpp b/kernel/fiasco/src/jdb/jdb_timeout.cpp index 9b743d21..aa9b3d50 100644 --- a/kernel/fiasco/src/jdb/jdb_timeout.cpp +++ b/kernel/fiasco/src/jdb/jdb_timeout.cpp @@ -217,9 +217,11 @@ Jdb_list_timeouts::get_owner(Timeout *t) return static_cast(context_of(t)); case Timeout_timeslice: return static_cast(Context::kernel_context(0)); +#if 0 // XXX: current_sched does not work from the debugger if (Context::current_sched()) return static_cast(Context::current_sched()->context()); +#endif default: return 0; } diff --git a/kernel/fiasco/src/jdb/jdb_trace.cpp b/kernel/fiasco/src/jdb/jdb_trace.cpp index 7e170f87..7b846190 100644 --- a/kernel/fiasco/src/jdb/jdb_trace.cpp +++ b/kernel/fiasco/src/jdb/jdb_trace.cpp @@ -182,7 +182,7 @@ Jdb_pf_trace::show() if (_log) { int res_enabled = 0; - BEGIN_LOG_EVENT("Page fault results", "pfr", 0) + BEGIN_LOG_EVENT("Page fault results", "pfr", Tb_entry_pf) res_enabled = 1; END_LOG_EVENT; printf("PF logging%s%s enabled", diff --git a/kernel/fiasco/src/kern/acpi.cpp b/kernel/fiasco/src/kern/acpi.cpp index 66233def..cd8ae951 100644 --- a/kernel/fiasco/src/kern/acpi.cpp +++ b/kernel/fiasco/src/kern/acpi.cpp @@ -32,47 +32,20 @@ public: } __attribute__((packed)); -template< typename T > -class Acpi_sdt : public Acpi_table_head +class Acpi_sdt { -public: - T ptrs[0]; - -} __attribute__((packed)); - -typedef Acpi_sdt Acpi_rsdt; -typedef Acpi_sdt Acpi_xsdt; - -class Acpi_rsdp -{ -public: - char signature[8]; - Unsigned8 chk_sum; - char oem[6]; - Unsigned8 rev; - Unsigned32 rsdt_phys; - Unsigned32 len; - Unsigned64 xsdt_phys; - Unsigned8 ext_chk_sum; - char reserved[3]; - - Acpi_rsdt const *rsdt() const; - Acpi_xsdt const *xsdt() const; - - bool checksum_ok() const; - - static Acpi_rsdp const *locate(); -} __attribute__((packed)); +private: + unsigned _num_tables; + Acpi_table_head const **_tables; +}; class Acpi { public: - static Acpi_rsdt const *rsdt() { return _rsdt; } - static Acpi_xsdt const *xsdt() { return _xsdt; } + static Acpi_sdt const *sdt() { return &_sdt; } private: - static Acpi_rsdt const *_rsdt; - static Acpi_xsdt const *_xsdt; + static Acpi_sdt _sdt; static bool _init_done; }; @@ -113,16 +86,56 @@ private: char data[0]; } __attribute__((packed)); +template< bool > +struct Acpi_helper_get_msb +{ template static Address msb(P) { return 0; } }; + +template<> +struct Acpi_helper_get_msb +{ template static Address msb(P p) { return p >> (sizeof(Address) * 8); } }; + IMPLEMENTATION: +#include "boot_alloc.h" #include "kmem.h" #include -Acpi_rsdt const *Acpi::_rsdt; -Acpi_xsdt const *Acpi::_xsdt; +Acpi_sdt Acpi::_sdt; bool Acpi::_init_done; +template< typename T > +class Acpi_sdt_p : public Acpi_table_head +{ +public: + T ptrs[0]; + +} __attribute__((packed)); + +typedef Acpi_sdt_p Acpi_rsdt_p; +typedef Acpi_sdt_p Acpi_xsdt_p; + +class Acpi_rsdp +{ +public: + char signature[8]; + Unsigned8 chk_sum; + char oem[6]; + Unsigned8 rev; + Unsigned32 rsdt_phys; + Unsigned32 len; + Unsigned64 xsdt_phys; + Unsigned8 ext_chk_sum; + char reserved[3]; + + Acpi_rsdt_p const *rsdt() const; + Acpi_xsdt_p const *xsdt() const; + + bool checksum_ok() const; + + static Acpi_rsdp const *locate(); +} __attribute__((packed)); + static void print_acpi_id(char const *id, unsigned len) @@ -153,21 +166,68 @@ Acpi_table_head::print_info() const printf("\n"); } -PUBLIC template< typename T > +PUBLIC void -Acpi_sdt::print_summary() const +Acpi_sdt::print_summary() const { - for (unsigned i = 0; i < ((len-sizeof(Acpi_table_head))/sizeof(ptrs[0])); ++i) - { - Acpi_table_head const *t = Kmem::dev_map.map((Acpi_table_head const*)ptrs[i]); - if (t == (Acpi_table_head const *)~0UL) - continue; + for (unsigned i = 0; i < _num_tables; ++i) + if (_tables[i]) + _tables[i]->print_info(); +} - t->print_info(); +PUBLIC template< typename T > +unsigned +Acpi_sdt_p::entries() const +{ return (len - sizeof(Acpi_table_head)) / sizeof(ptrs[0]); } + +PUBLIC template< typename SDT > +void +Acpi_sdt::init(SDT *sdt) +{ + unsigned entries = sdt->entries(); + _tables = (Acpi_table_head const **)Boot_alloced::alloc(sizeof(*_tables) * entries); + if (_tables) + { + _num_tables = entries; + for (unsigned i = 0; i < entries; ++i) + if (sdt->ptrs[i]) + this->map_entry(i, sdt->ptrs[i]); } } +PRIVATE template< typename T > +Acpi_table_head const * +Acpi_sdt::map_entry(unsigned idx, T phys) +{ + if (idx >= _num_tables) + { + printf("ACPI: table index out of range (%d >= %d)\n", idx, _num_tables); + return 0; + } + + // is the acpi address bigger that our handled physical addresses + if (Acpi_helper_get_msb<(sizeof(phys) > sizeof(Address))>::msb(phys)) + { + printf("ACPI: cannot map phys address %llx, out of range (%zdbit)\n", + (unsigned long long)phys, sizeof(Address) * 8); + return 0; + } + + Acpi_table_head const *t = Kmem::dev_map.map((Acpi_table_head const*)(unsigned long)phys); + if (t == (Acpi_table_head const *)~0UL) + { + printf("ACPI: cannot map phys address %llx, map failed\n", + (unsigned long long)phys); + return 0; + } + + _tables[idx] = t; + return t; +} + + + PUBLIC static void Acpi::init_virt() @@ -189,36 +249,35 @@ Acpi::init_virt() if (rsdp->rev && rsdp->xsdt_phys) { - Acpi_xsdt const *x = Kmem::dev_map.map((const Acpi_xsdt *)rsdp->xsdt_phys); - if (x == (Acpi_xsdt const *)~0UL) + Acpi_xsdt_p const *x = Kmem::dev_map.map((const Acpi_xsdt_p *)rsdp->xsdt_phys); + if (x == (Acpi_xsdt_p const *)~0UL) printf("ACPI: Could not map XSDT\n"); else if (!x->checksum_ok()) printf("ACPI: Checksum mismatch in XSDT\n"); else { - _xsdt = x; + _sdt.init(x); x->print_info(); + _sdt.print_summary(); + return; } } if (rsdp->rsdt_phys) { - Acpi_rsdt const *r = Kmem::dev_map.map((const Acpi_rsdt *)rsdp->rsdt_phys); - if (r == (Acpi_rsdt const *)~0UL) + Acpi_rsdt_p const *r = Kmem::dev_map.map((const Acpi_rsdt_p *)(unsigned long)rsdp->rsdt_phys); + if (r == (Acpi_rsdt_p const *)~0UL) printf("ACPI: Could not map RSDT\n"); else if (!r->checksum_ok()) printf("ACPI: Checksum mismatch in RSDT\n"); else { - _rsdt = r; + _sdt.init(r); r->print_info(); + _sdt.print_summary(); + return; } } - - if (_xsdt) - _xsdt->print_summary(); - else if (_rsdt) - _rsdt->print_summary(); } PUBLIC static @@ -226,29 +285,24 @@ template< typename T > T Acpi::find(const char *s) { - T a = 0; init_virt(); - if (_xsdt) - a = static_cast(_xsdt->find(s)); - else if (_rsdt) - a = static_cast(_rsdt->find(s)); - return a; + return static_cast(sdt()->find(s)); } IMPLEMENT -Acpi_rsdt const * +Acpi_rsdt_p const * Acpi_rsdp::rsdt() const { - return (Acpi_rsdt const*)rsdt_phys; + return (Acpi_rsdt_p const*)(unsigned long)rsdt_phys; } IMPLEMENT -Acpi_xsdt const * +Acpi_xsdt_p const * Acpi_rsdp::xsdt() const { if (rev == 0) return 0; - return (Acpi_xsdt const*)xsdt_phys; + return (Acpi_xsdt_p const*)xsdt_phys; } IMPLEMENT @@ -284,10 +338,31 @@ Acpi_table_head::checksum_ok() const return !sum; } +PUBLIC +Acpi_table_head const * +Acpi_sdt::find(char const sig[4]) const +{ + for (unsigned i = 0; i < _num_tables; ++i) + { + Acpi_table_head const *t = _tables[i]; + if (!t) + continue; + + if (t->signature[0] == sig[0] + && t->signature[1] == sig[1] + && t->signature[2] == sig[2] + && t->signature[3] == sig[3] + && t->checksum_ok()) + return t; + } + + return 0; +} + PUBLIC template< typename T > Acpi_table_head const * -Acpi_sdt::find(char const sig[4]) const +Acpi_sdt_p::find(char const sig[4]) const { for (unsigned i = 0; i < ((len-sizeof(Acpi_table_head))/sizeof(ptrs[0])); ++i) { diff --git a/kernel/fiasco/src/kern/app_cpu_thread.cpp b/kernel/fiasco/src/kern/app_cpu_thread.cpp index 6566708f..384d1a59 100644 --- a/kernel/fiasco/src/kern/app_cpu_thread.cpp +++ b/kernel/fiasco/src/kern/app_cpu_thread.cpp @@ -28,11 +28,21 @@ IMPLEMENTATION [mp]: #include "timer_tick.h" #include "spin_lock.h" +PUBLIC static +Kernel_thread * +App_cpu_thread::may_be_create(unsigned cpu, bool cpu_never_seen_before) +{ + if (!cpu_never_seen_before) + return static_cast(kernel_context(cpu)); + + Kernel_thread *t = new (Ram_quota::root) App_cpu_thread; + assert (t); + + set_cpu_of(t, cpu); + check(t->bind(Kernel_task::kernel_task(), User::Ptr(0))); + return t; +} -PUBLIC inline -Mword * -App_cpu_thread::init_stack() -{ return _kernel_sp; } // the kernel bootstrap routine IMPLEMENT @@ -43,35 +53,35 @@ App_cpu_thread::bootstrap() state_change_dirty(0, Thread_ready); // Set myself ready - // Setup initial timeslice - set_current_sched(sched()); - Fpu::init(cpu()); + Fpu::init(cpu(true)); // initialize the current_mem_space function to point to the kernel space Kernel_task::kernel_task()->make_current(); Mem_unit::tlb_flush(); - Cpu::cpus.cpu(current_cpu()).set_online(1); + Cpu::cpus.current().set_online(1); _tramp_mp_spinlock.set(1); - kernel_context(cpu(), this); - Sched_context::rq(cpu()).set_idle(this->sched()); - Rcu::leave_idle(cpu()); + kernel_context(cpu(true), this); + Sched_context::rq.current().set_idle(this->sched()); + Rcu::leave_idle(cpu(true)); Timer_tick::setup(cpu(true)); Timer_tick::enable(cpu(true)); - enable_tlb(cpu()); + enable_tlb(cpu(true)); + // Setup initial timeslice + Sched_context::rq.current().set_current_sched(sched()); - Per_cpu_data::run_late_ctors(cpu()); + Per_cpu_data::run_late_ctors(cpu(true)); Scheduler::scheduler.trigger_hotplug_event(); cpu_lock.clear(); - printf("CPU[%u]: goes to idle loop\n", cpu()); + printf("CPU[%u]: goes to idle loop\n", cpu(true)); for (;;) idle_op(); diff --git a/kernel/fiasco/src/kern/arm/bootstrap.cpp b/kernel/fiasco/src/kern/arm/bootstrap.cpp index 7db0355c..504fcd26 100644 --- a/kernel/fiasco/src/kern/arm/bootstrap.cpp +++ b/kernel/fiasco/src/kern/arm/bootstrap.cpp @@ -95,6 +95,19 @@ map_1mb(void *pd, Address va, Address pa, bool cache, bool local) | (local ? Section_local : Section_global); } +// This is a template so that we can have the static_assertion, checking the +// right value at compile time. At runtime we probably won't see anything +// as this also affects the UART mapping. +template< Address PA > +static void inline +map_dev(void *pd, unsigned va_slotnr) +{ + static_assert(PA == Invalid_address || (PA & ~0xfff00000) == 0, "Physical address must be 2^20 aligned"); + if (PA != Invalid_address) + map_1mb(pd, Mem_layout::Registers_map_start + va_slotnr * 0x100000, PA, + false, false); +} + asm ( ".section .text.init,#alloc,#execinstr \n" diff --git a/kernel/fiasco/src/kern/arm/bsp/imx/Kconfig b/kernel/fiasco/src/kern/arm/bsp/imx/Kconfig index 6348b4f9..5ec83881 100644 --- a/kernel/fiasco/src/kern/arm/bsp/imx/Kconfig +++ b/kernel/fiasco/src/kern/arm/bsp/imx/Kconfig @@ -11,19 +11,37 @@ config PF_IMX_21 depends on PF_IMX select CAN_ARM_CPU_926 help - Choose for i.MX21 + Choose for i.MX21. config PF_IMX_35 bool "i.MX35" depends on PF_IMX select CAN_ARM_CPU_1136 + help + Choose for i.MX35 platform. config PF_IMX_51 bool "i.MX51" depends on PF_IMX select CAN_ARM_CPU_CORTEX_A8 help - Choose for i.MX51 + Choose for i.MX51. + +# remove comment when actually tested... +#config PF_IMX_53 +# bool "i.MX53" +# depends on PF_IMX +# select CAN_ARM_CPU_CORTEX_A8 +# help +# Choose for i.MX53. + +config PF_IMX_6 + bool "i.MX6" + depends on PF_IMX + select CAN_ARM_CPU_CORTEX_A9 + select CAN_ARM_CACHE_L2CXX0 + help + Choose for i.MX6 platform. endchoice @@ -32,3 +50,4 @@ config PF_IMX_RAM_PHYS_BASE default 0xc0000000 if PF_IMX_21 default 0x80000000 if PF_IMX_35 default 0x90000000 if PF_IMX_51 + default 0x10000000 if PF_IMX_6 diff --git a/kernel/fiasco/src/kern/arm/bsp/imx/Modules b/kernel/fiasco/src/kern/arm/bsp/imx/Modules index 7f3021f0..5321e62b 100644 --- a/kernel/fiasco/src/kern/arm/bsp/imx/Modules +++ b/kernel/fiasco/src/kern/arm/bsp/imx/Modules @@ -7,9 +7,14 @@ PREPROCESS_PARTS += $(if $(CONFIG_PF_IMX_21),imx21 kern_start_0xd) PREPROCESS_PARTS += $(if $(CONFIG_PF_IMX_35),imx35 imx_epit) PREPROCESS_PARTS += $(if $(CONFIG_PF_IMX_51),imx51 imx_epit \ pic_gic pic_gic_mxc_tzic) +PREPROCESS_PARTS += $(if $(CONFIG_PF_IMX_53),imx53 imx_epit \ + pic_gic pic_gic_mxc_tzic) +PREPROCESS_PARTS += $(if $(CONFIG_PF_IMX_6),imx6 pic_gic mptimer) CONFIG_KERNEL_LOAD_ADDR := $(CONFIG_PF_IMX_RAM_PHYS_BASE) INTERFACES_KERNEL += $(if $(CONFIG_PF_IMX_51),gic) +INTERFACES_KERNEL += $(if $(CONFIG_PF_IMX_6),gic) +MPCORE_PHYS_BASE := 0x00a00000 uart_IMPL += uart-imx config_IMPL += config-arm-imx @@ -17,11 +22,17 @@ mem_layout_IMPL += mem_layout-arm-imx pic_IMPL += $(if $(CONFIG_PF_IMX_21),pic-arm-imx) pic_IMPL += $(if $(CONFIG_PF_IMX_35),pic-arm-imx) pic_IMPL += $(if $(CONFIG_PF_IMX_51),pic-gic pic-arm-imx51) +pic_IMPL += $(if $(CONFIG_PF_IMX_53),pic-gic pic-arm-imx51) +pic_IMPL += $(if $(CONFIG_PF_IMX_6),pic-gic pic-arm-imx51) bootstrap_IMPL += bootstrap-arm-imx timer_IMPL += $(if $(CONFIG_PF_IMX_21),timer-arm-imx21) timer_IMPL += $(if $(CONFIG_PF_IMX_35),timer-arm-imx_epit) timer_IMPL += $(if $(CONFIG_PF_IMX_51),timer-arm-imx_epit) +timer_IMPL += $(if $(CONFIG_PF_IMX_53),timer-arm-imx_epit) +timer_IMPL += $(if $(CONFIG_PF_IMX_6),timer-arm-mptimer timer-arm-mptimer-imx6) timer_tick_IMPL += timer_tick-single-vector kernel_uart_IMPL += kernel_uart-arm-imx reset_IMPL += reset-arm-imx +outer_cache_IMPL += outer_cache-arm-imx6 clock_IMPL += clock-generic +platform_control_IMPL += platform_control-arm-imx6 diff --git a/kernel/fiasco/src/kern/arm/bsp/imx/bootstrap-arm-imx.cpp b/kernel/fiasco/src/kern/arm/bsp/imx/bootstrap-arm-imx.cpp index b3023a8e..9c376503 100644 --- a/kernel/fiasco/src/kern/arm/bsp/imx/bootstrap-arm-imx.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/imx/bootstrap-arm-imx.cpp @@ -6,29 +6,11 @@ enum { }; //----------------------------------------------------------------------------- -IMPLEMENTATION [arm && imx21]: +IMPLEMENTATION [arm && imx]: void map_hw(void *pd) { - // map devices - map_1mb(pd, Mem_layout::Device_map_base_1, Mem_layout::Device_phys_base_1, false, false); -} - -//----------------------------------------------------------------------------- -IMPLEMENTATION [arm && imx35]: -void -map_hw(void *pd) -{ - map_1mb(pd, Mem_layout::Device_map_base_1, Mem_layout::Device_phys_base_1, false, false); - map_1mb(pd, Mem_layout::Device_map_base_2, Mem_layout::Device_phys_base_2, false, false); - map_1mb(pd, Mem_layout::Device_map_base_3, Mem_layout::Device_phys_base_3, false, false); -} - -//----------------------------------------------------------------------------- -IMPLEMENTATION [arm && imx51]: -void -map_hw(void *pd) -{ - map_1mb(pd, Mem_layout::Device_map_base_1, Mem_layout::Device_phys_base_1, false, false); - map_1mb(pd, Mem_layout::Device_map_base_2, Mem_layout::Device_phys_base_2, false, false); + map_dev(pd, 1); + map_dev(pd, 2); + map_dev(pd, 3); } diff --git a/kernel/fiasco/src/kern/arm/bsp/imx/config-arm-imx.cpp b/kernel/fiasco/src/kern/arm/bsp/imx/config-arm-imx.cpp index d4312141..95ebf207 100644 --- a/kernel/fiasco/src/kern/arm/bsp/imx/config-arm-imx.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/imx/config-arm-imx.cpp @@ -9,3 +9,11 @@ INTERFACE [arm && imx35]: INTERFACE [arm && imx51]: #define TARGET_NAME "i.MX51" + +INTERFACE [arm && imx53]: + +#define TARGET_NAME "i.MX53" + +INTERFACE [arm && imx6]: + +#define TARGET_NAME "i.MX6" diff --git a/kernel/fiasco/src/kern/arm/bsp/imx/mem_layout-arm-imx.cpp b/kernel/fiasco/src/kern/arm/bsp/imx/mem_layout-arm-imx.cpp index b86b2b06..1b849b7e 100644 --- a/kernel/fiasco/src/kern/arm/bsp/imx/mem_layout-arm-imx.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/imx/mem_layout-arm-imx.cpp @@ -3,13 +3,7 @@ INTERFACE [arm && imx]: //---------------------------------------------- EXTENSION class Mem_layout { public: - enum Virt_layout_imx { - Device_map_base_1 = Registers_map_start, - Device_map_base_2 = Registers_map_start + 0x100000, - Device_map_base_3 = Registers_map_start + 0x200000, - }; - - enum Phys_layout { + enum Phys_layout : Address { Sdram_phys_base = CONFIG_PF_IMX_RAM_PHYS_BASE, Flush_area_phys_base = 0xe0000000, }; @@ -20,23 +14,19 @@ INTERFACE [arm && imx && imx21]: // --------------------------------------- EXTENSION class Mem_layout { public: - enum Virt_layout_imx21 { - Uart_map_base = 0xef10a000, - Timer_map_base = 0xef103000, - Pll_map_base = 0xef127000, - Watchdog_map_base = 0xef102000, - Pic_map_base = 0xef140000, + enum Virt_layout_imx21 : Address { + Uart_map_base = Devices1_map_base + 0x0a000, + Timer_map_base = Devices1_map_base + 0x03000, + Pll_map_base = Devices1_map_base + 0x27000, + Watchdog_map_base = Devices1_map_base + 0x02000, + Pic_map_base = Devices1_map_base + 0x40000, Uart_base = Uart_map_base, }; - enum Phys_layout_imx21 { - Device_phys_base_1 = 0x10000000, - - Timer_phys_base = 0x10003000, - Uart_phys_base = 0x1000a000, - Pll_phys_base = 0x10027000, - Watchdog_phys_base = 0x10002000, - Pic_phys_base = 0x10040000, + enum Phys_layout_imx21 : Address { + Devices1_phys_base = 0x10000000, + Devices2_phys_base = Invalid_address, + Devices3_phys_base = Invalid_address, }; }; @@ -45,23 +35,18 @@ INTERFACE [arm && imx && imx35]: // --------------------------------------- EXTENSION class Mem_layout { public: - enum Virt_layout_imx35 { - Uart_map_base = Device_map_base_1 + 0x90000, - Timer_map_base = Device_map_base_2 + 0x94000, - Watchdog_map_base = Device_map_base_2 + 0xdc000, - Pic_map_base = Device_map_base_3 + 0x0, + enum Virt_layout_imx35 : Address { + Uart_map_base = Devices1_map_base + 0x90000, // uart1 + Timer_map_base = Devices2_map_base + 0x94000, // epit1 + Watchdog_map_base = Devices2_map_base + 0xdc000, // wdog + Pic_map_base = Devices3_map_base + 0x0, Uart_base = Uart_map_base, }; - enum Phys_layout_imx35 { - Device_phys_base_1 = 0x43f00000, - Device_phys_base_2 = 0x53f00000, - Device_phys_base_3 = 0x68000000, - - Timer_phys_base = 0x53f94000, // epit1 - Uart_phys_base = 0x43f90000, // uart1 - Watchdog_phys_base = 0x53fdc000, // wdog - Pic_phys_base = 0x68000000, + enum Phys_layout_imx35 : Address { + Devices1_phys_base = 0x43f00000, + Devices2_phys_base = 0x53f00000, + Devices3_phys_base = 0x68000000, }; }; @@ -71,22 +56,65 @@ INTERFACE [arm && imx && imx51]: // --------------------------------------- EXTENSION class Mem_layout { public: - enum Virt_layout_imx51 { - Timer_map_base = 0xef1ac000, - Uart_map_base = 0xef1bc000, - Watchdog_map_base = 0xef198000, - Gic_cpu_map_base = 0, - Gic_dist_map_base = 0xef200000, + enum Virt_layout_imx51 : Address { + Timer_map_base = Devices1_map_base + 0xac000, // epit1 + Uart_map_base = Devices1_map_base + 0xbc000, // uart1 + Watchdog_map_base = Devices1_map_base + 0x98000, // wdog1 + Gic_cpu_map_base = Invalid_address, + Gic_dist_map_base = Devices2_map_base + 0x00000, Uart_base = Uart_map_base, }; - enum Phys_layout_imx51 { - Device_phys_base_1 = 0x73f00000, - Device_phys_base_2 = 0xe0000000, - - Watchdog_phys_base = 0x73f98000, // wdog1 - Timer_phys_base = 0x73fac000, // epit1 - Uart_phys_base = 0x73fbc000, // uart1 - Gic_dist_phys_base = 0xe0000000, + enum Phys_layout_imx51 : Address { + Devices1_phys_base = 0x73f00000, + Devices2_phys_base = 0xe0000000, + Devices3_phys_base = Invalid_address, + }; +}; + +INTERFACE [arm && imx && imx53]: // --------------------------------------- + +EXTENSION class Mem_layout +{ +public: + enum Virt_layout_imx53 : Address { + Timer_map_base = Devices1_map_base + 0xac000, // epit1 + Uart_map_base = Devices1_map_base + 0xbc000, // uart1 + Watchdog_map_base = Devices1_map_base + 0x98000, // wdog1 + Gic_cpu_map_base = Invalid_address, + Gic_dist_map_base = Devices2_map_base + 0xfc000, + Uart_base = Uart_map_base, + }; + + enum Phys_layout_imx53 : Address { + Devices1_phys_base = 0x53f00000, + Devices2_phys_base = 0x0ff00000, + Devices3_phys_base = Invalid_address, + }; +}; + +INTERFACE [arm && imx && imx6]: // ----------------------------------------- + +EXTENSION class Mem_layout +{ +public: + enum Virt_layout_imx6 : Address { + Mp_scu_map_base = Devices1_map_base, + Gic_cpu_map_base = Mp_scu_map_base + 0x00100, + Gic_dist_map_base = Mp_scu_map_base + 0x01000, + L2cxx0_map_base = Mp_scu_map_base + 0x02000, + + Uart1_map_base = Devices2_map_base + 0x20000, // uart1 + Uart2_map_base = Devices3_map_base + 0xe8000, // uart2 + Watchdog_map_base = Devices2_map_base + 0xbc000, // wdog1 + Gpt_map_base = Devices2_map_base + 0x98000, + Src_map_base = Devices2_map_base + 0xd8000, + Uart_base = Uart2_map_base, + }; + + enum Phys_layout_imx6 : Address { + Devices1_phys_base = 0x00a00000, + Devices2_phys_base = 0x02000000, + Devices3_phys_base = 0x02100000, }; }; diff --git a/kernel/fiasco/src/kern/arm/bsp/imx/outer_cache-arm-imx6.cpp b/kernel/fiasco/src/kern/arm/bsp/imx/outer_cache-arm-imx6.cpp new file mode 100644 index 00000000..5cfa731d --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/imx/outer_cache-arm-imx6.cpp @@ -0,0 +1,8 @@ +IMPLEMENTATION [arm && imx6 && outer_cache_l2cxx0]: + +IMPLEMENT +Mword +Outer_cache::platform_init(Mword aux_control) +{ + return aux_control; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/imx/pic-arm-imx51.cpp b/kernel/fiasco/src/kern/arm/bsp/imx/pic-arm-imx51.cpp index 02ec9450..2041a083 100644 --- a/kernel/fiasco/src/kern/arm/bsp/imx/pic-arm-imx51.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/imx/pic-arm-imx51.cpp @@ -1,9 +1,23 @@ -INTERFACE [arm && pic_gic && imx51]: +INTERFACE [arm && pic_gic && (imx51 || imx53 || imx6)]: #include "gic.h" +INTERFACE [arm && pic_gic && (imx51 | imx53)]: + +EXTENSION class Pic +{ + enum { Gic_sz = 7 }; +}; + +INTERFACE [arm && pic_gic && imx6]: + +EXTENSION class Pic +{ + enum { Gic_sz = 8 }; +}; + // ------------------------------------------------------------------------ -IMPLEMENTATION [arm && pic_gic && imx51]: +IMPLEMENTATION [arm && pic_gic && (imx51 || imx53 || imx6)]: #include "irq_mgr_multi_chip.h" #include "kmem.h" @@ -12,11 +26,11 @@ IMPLEMENT FIASCO_INIT void Pic::init() { - typedef Irq_mgr_multi_chip<7> M; + typedef Irq_mgr_multi_chip M; M *m = new Boot_object(1); - gic.construct(0, Kmem::Gic_dist_map_base); + gic.construct(Kmem::Gic_cpu_map_base, Kmem::Gic_dist_map_base); m->add_chip(0, gic, gic->nr_irqs()); Irq_mgr::mgr = m; @@ -29,3 +43,12 @@ Pic::Status Pic::disable_all_save() IMPLEMENT inline void Pic::restore_all(Status) {} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && pic_gic && mp && imx6]: + +PUBLIC static +void Pic::init_ap(unsigned) +{ + gic->init_ap(); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/imx/platform_control-arm-imx6.cpp b/kernel/fiasco/src/kern/arm/bsp/imx/platform_control-arm-imx6.cpp new file mode 100644 index 00000000..39b27edf --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/imx/platform_control-arm-imx6.cpp @@ -0,0 +1,33 @@ +INTERFACE [arm && mp && imx6]: + +#include "types.h" + +IMPLEMENTATION [arm && mp && imx6]: + +#include "io.h" +#include "ipi.h" +#include "mem_layout.h" + +PUBLIC static +void +Platform_control::boot_ap_cpus(Address phys_tramp_mp_addr) +{ + enum + { + SRC_SCR = Mem_layout::Src_map_base + 0, + SRC_GPR1 = Mem_layout::Src_map_base + 0x20, + SRC_GPR3 = Mem_layout::Src_map_base + 0x28, + SRC_GPR5 = Mem_layout::Src_map_base + 0x30, + SRC_GPR7 = Mem_layout::Src_map_base + 0x38, + + SRC_SCR_CORE1_3_ENABLE = 7 << 22, + SRC_SCR_CORE1_3_RESET = 7 << 14, + }; + + Io::write(phys_tramp_mp_addr, SRC_GPR3); + Io::write(phys_tramp_mp_addr, SRC_GPR5); + Io::write(phys_tramp_mp_addr, SRC_GPR7); + + Io::set(SRC_SCR_CORE1_3_RESET, SRC_SCR); + Io::set(SRC_SCR_CORE1_3_ENABLE, SRC_SCR); +} diff --git a/kernel/fiasco/src/kern/arm/bsp/imx/reset-arm-imx.cpp b/kernel/fiasco/src/kern/arm/bsp/imx/reset-arm-imx.cpp index 7e7776f2..9ac16f4d 100644 --- a/kernel/fiasco/src/kern/arm/bsp/imx/reset-arm-imx.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/imx/reset-arm-imx.cpp @@ -25,7 +25,22 @@ platform_reset(void) } // ------------------------------------------------------------------------ -IMPLEMENTATION [arm && (imx35 || imx51)]: +IMPLEMENTATION [arm && (imx35 || imx51 || imx53)]: + +void platform_imx_cpus_off() +{} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && imx6]: + +void platform_imx_cpus_off() +{ + // switch off core1-3 + Io::clear(7 << 22, Mem_layout::Src_map_base + 0); +} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && (imx35 || imx51 || imx53 || imx6)]: #include "io.h" #include "kmem.h" @@ -38,6 +53,8 @@ platform_reset(void) WCR_SRS = 1 << 4, // Software Reset Signal }; + platform_imx_cpus_off(); + // Assert Software reset signal by making the bit zero Io::write(Io::read(WCR) & ~WCR_SRS, WCR); diff --git a/kernel/fiasco/src/kern/arm/bsp/imx/timer-arm-imx_epit.cpp b/kernel/fiasco/src/kern/arm/bsp/imx/timer-arm-imx_epit.cpp index 2231f5ac..52939356 100644 --- a/kernel/fiasco/src/kern/arm/bsp/imx/timer-arm-imx_epit.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/imx/timer-arm-imx_epit.cpp @@ -39,7 +39,7 @@ public: }; -INTERFACE [arm && imx51]: // ---------------------------------------------- +INTERFACE [arm && (imx51 || imx53)]: // ----------------------------------- EXTENSION class Timer { diff --git a/kernel/fiasco/src/kern/arm/bsp/imx/timer-arm-mptimer-imx6.cpp b/kernel/fiasco/src/kern/arm/bsp/imx/timer-arm-mptimer-imx6.cpp new file mode 100644 index 00000000..def5bc32 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/imx/timer-arm-mptimer-imx6.cpp @@ -0,0 +1,45 @@ +// -------------------------------------------------------------------------- +IMPLEMENTATION[arm && imx6 && mptimer]: + +#include "config.h" +#include "io.h" +#include "mem_layout.h" + +PRIVATE static Mword Timer::interval() +{ + enum + { + GPT_CR = Mem_layout::Gpt_map_base + 0x00, + GPT_PR = Mem_layout::Gpt_map_base + 0x04, + GPT_SR = Mem_layout::Gpt_map_base + 0x08, + GPT_IR = Mem_layout::Gpt_map_base + 0x0c, + GPT_CNT = Mem_layout::Gpt_map_base + 0x24, + + GPT_CR_EN = 1 << 0, + GPT_CR_CLKSRC_MASK = 7 << 6, + GPT_CR_CLKSRC_CRYSTAL_OSC = 7 << 6, + GPT_CR_CLKSRC_32KHZ = 4 << 6, + GPT_CR_FRR = 1 << 9, + GPT_CR_RESET = 1 << 15, + + Timer_freq = 32768, + Ticks = 50, + Gpt_ticks = (Timer_freq * Ticks) / Config::Scheduler_granularity, + }; + + Io::write(0, GPT_CR); + Io::write(GPT_CR_RESET, GPT_CR); + while (Io::read(GPT_CR) & GPT_CR_RESET) + ; + + Io::write(GPT_CR_CLKSRC_32KHZ | GPT_CR_FRR, GPT_CR); + Io::write(0, GPT_PR); + + Io::set(GPT_CR_EN, GPT_CR); + Mword vc = start_as_counter(); + while (Io::read(GPT_CNT) < Gpt_ticks) + ; + Mword interval = (vc - stop_counter()) / Ticks; + Io::write(0, GPT_CR); + return interval; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/imx/uart-imx.cpp b/kernel/fiasco/src/kern/arm/bsp/imx/uart-imx.cpp index 2f55d22a..67d7041d 100644 --- a/kernel/fiasco/src/kern/arm/bsp/imx/uart-imx.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/imx/uart-imx.cpp @@ -25,7 +25,7 @@ IMPLEMENT L4::Uart *Uart::uart() return &uart; } -IMPLEMENTATION [imx51]: +IMPLEMENTATION [imx51 || imx53]: #include "uart_imx.h" @@ -37,7 +37,19 @@ IMPLEMENT L4::Uart *Uart::uart() return &uart; } -IMPLEMENTATION [imx21 || imx35 || imx51]: +IMPLEMENTATION [imx6]: + +#include "uart_imx.h" + +IMPLEMENT int Uart::irq() const { return 90; } + +IMPLEMENT L4::Uart *Uart::uart() +{ + static L4::Uart_imx6 uart; + return &uart; +} + +IMPLEMENTATION: #include "mem_layout.h" diff --git a/kernel/fiasco/src/kern/arm/bsp/integrator/Kconfig b/kernel/fiasco/src/kern/arm/bsp/integrator/Kconfig index 4352bcee..a4fe022f 100644 --- a/kernel/fiasco/src/kern/arm/bsp/integrator/Kconfig +++ b/kernel/fiasco/src/kern/arm/bsp/integrator/Kconfig @@ -1,4 +1,4 @@ # PF: INTEGRATOR # PFDESCR: ARM Integrator Platform -# PFCAN: CAN_ARM_CPU_926 CAN_ARM_CPU_1176 +# PFSELECT: CAN_ARM_CPU_926 CAN_ARM_CPU_1176 # PFDEPENDS: ARM diff --git a/kernel/fiasco/src/kern/arm/bsp/integrator/bootstrap-arm-integrator.cpp b/kernel/fiasco/src/kern/arm/bsp/integrator/bootstrap-arm-integrator.cpp index 0facae8b..adc23e81 100644 --- a/kernel/fiasco/src/kern/arm/bsp/integrator/bootstrap-arm-integrator.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/integrator/bootstrap-arm-integrator.cpp @@ -10,12 +10,8 @@ IMPLEMENTATION [arm && integrator]: void map_hw(void *pd) { - // map UART - map_1mb(pd, Mem_layout::Uart_map_base, Mem_layout::Uart_phys_base, false, false); - // map Timer - map_1mb(pd, Mem_layout::Timer_map_base, Mem_layout::Timer_phys_base, false, false); - // map Pic - map_1mb(pd, Mem_layout::Pic_map_base, Mem_layout::Pic_phys_base, false, false); - // map Integrator hdr - map_1mb(pd, Mem_layout::Integrator_map_base, Mem_layout::Integrator_phys_base, false, false); + map_dev(pd, 0); + map_dev(pd, 1); + map_dev(pd, 2); + map_dev(pd, 3); } diff --git a/kernel/fiasco/src/kern/arm/bsp/integrator/mem_layout-arm-integrator.cpp b/kernel/fiasco/src/kern/arm/bsp/integrator/mem_layout-arm-integrator.cpp index 9d204195..523e7184 100644 --- a/kernel/fiasco/src/kern/arm/bsp/integrator/mem_layout-arm-integrator.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/integrator/mem_layout-arm-integrator.cpp @@ -3,19 +3,19 @@ INTERFACE [arm-integrator]: //---------------------------------------------- EXTENSION class Mem_layout { public: - enum Virt_layout_integrator { - Uart_map_base = 0xef100000, - Timer_map_base = 0xef200000, - Pic_map_base = 0xef300000, - Integrator_map_base = 0xef400000, + enum Virt_layout_integrator : Address { + Uart_map_base = Devices0_map_base, + Timer_map_base = Devices1_map_base, + Pic_map_base = Devices2_map_base, + Integrator_map_base = Devices3_map_base, Uart_base = Uart_map_base, }; - enum Phys_layout { - Uart_phys_base = 0x16000000, - Timer_phys_base = 0x13000000, - Pic_phys_base = 0x14000000, - Integrator_phys_base = 0x10000000, + enum Phys_layout : Address { + Devices0_phys_base = 0x16000000, + Devices1_phys_base = 0x13000000, + Devices2_phys_base = 0x14000000, + Devices3_phys_base = 0x10000000, Sdram_phys_base = 0x00000000, Flush_area_phys_base = 0xe0000000, }; diff --git a/kernel/fiasco/src/kern/arm/bsp/kirkwood/Kconfig b/kernel/fiasco/src/kern/arm/bsp/kirkwood/Kconfig index d74bf7e1..a1aa9e60 100644 --- a/kernel/fiasco/src/kern/arm/bsp/kirkwood/Kconfig +++ b/kernel/fiasco/src/kern/arm/bsp/kirkwood/Kconfig @@ -1,4 +1,4 @@ # PF: KIRKWOOD # PFDESCR: Marvell Kirkwood platform -# PFCAN: CAN_ARM_CPU_926 +# PFSELECT: CAN_ARM_CPU_926 # PFDEPENDS: ARM diff --git a/kernel/fiasco/src/kern/arm/bsp/kirkwood/bootstrap-arm-kirkwood.cpp b/kernel/fiasco/src/kern/arm/bsp/kirkwood/bootstrap-arm-kirkwood.cpp index 56b53dd1..5237e93f 100644 --- a/kernel/fiasco/src/kern/arm/bsp/kirkwood/bootstrap-arm-kirkwood.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/kirkwood/bootstrap-arm-kirkwood.cpp @@ -10,5 +10,5 @@ IMPLEMENTATION [arm && kirkwood]: void map_hw(void *pd) { - map_1mb(pd, Mem_layout::Devices0_map_base, Mem_layout::Devices0_phys_base, false, false); + map_dev(pd, 0); } diff --git a/kernel/fiasco/src/kern/arm/bsp/kirkwood/mem_layout-arm-kirkwood.cpp b/kernel/fiasco/src/kern/arm/bsp/kirkwood/mem_layout-arm-kirkwood.cpp index b8caafd8..e3e1e0b7 100644 --- a/kernel/fiasco/src/kern/arm/bsp/kirkwood/mem_layout-arm-kirkwood.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/kirkwood/mem_layout-arm-kirkwood.cpp @@ -3,19 +3,15 @@ INTERFACE [arm && kirkwood]: EXTENSION class Mem_layout { public: - enum Virt_layout_kirkwood + enum Virt_layout_kirkwood : Address { - Devices0_map_base = Registers_map_start, - Devices1_map_base = Registers_map_start + 0x00100000, - Devices2_map_base = Registers_map_start + 0x00200000, - Uart_base = Devices0_map_base + 0x00012000, Reset_map_base = Devices0_map_base, Timer_map_base = Devices0_map_base, Pic_map_base = Devices0_map_base, }; - enum Phys_layout_kirkwood + enum Phys_layout_kirkwood: Address { Devices0_phys_base = 0xf1000000, Sdram_phys_base = 0x0, diff --git a/kernel/fiasco/src/kern/arm/bsp/omap3/Kconfig b/kernel/fiasco/src/kern/arm/bsp/omap3/Kconfig index af74ed8a..80e17e6b 100644 --- a/kernel/fiasco/src/kern/arm/bsp/omap3/Kconfig +++ b/kernel/fiasco/src/kern/arm/bsp/omap3/Kconfig @@ -31,6 +31,7 @@ config PF_OMAP4_PANDABOARD bool "Pandaboard" depends on PF_OMAP select CAN_ARM_CPU_CORTEX_A9 + select CAN_ARM_CACHE_L2CXX0 help Choose for Pandaboard. diff --git a/kernel/fiasco/src/kern/arm/bsp/omap3/Modules b/kernel/fiasco/src/kern/arm/bsp/omap3/Modules index e320c7c9..bdc12f51 100644 --- a/kernel/fiasco/src/kern/arm/bsp/omap3/Modules +++ b/kernel/fiasco/src/kern/arm/bsp/omap3/Modules @@ -10,7 +10,6 @@ PREPROCESS_PARTS += $(if $(CONFIG_PF_OMAP4_PANDABOARD),omap4 mptimer pic_gic oma CONFIG_KERNEL_LOAD_ADDR := 0x80000000 MPCORE_PHYS_BASE := 0x48240000 -INTERFACES_KERNEL += $(if $(CONFIG_MP),boot_mp) INTERFACES_KERNEL += $(if $(CONFIG_PF_OMAP4_PANDABOARD),gic) uart_IMPL += uart-arm-omap @@ -23,4 +22,5 @@ timer_tick_IMPL += timer_tick-single-vector kernel_uart_IMPL += kernel_uart-arm-omap reset_IMPL += reset-arm-omap clock_IMPL += clock-generic -boot_mp_IMPL += boot_mp-arm-omap4 +platform_control_IMPL += platform_control-arm-omap4 +outer_cache_IMPL += outer_cache-arm-omap diff --git a/kernel/fiasco/src/kern/arm/bsp/omap3/bootstrap-arm-omap.cpp b/kernel/fiasco/src/kern/arm/bsp/omap3/bootstrap-arm-omap.cpp index 403f86e8..db547a00 100644 --- a/kernel/fiasco/src/kern/arm/bsp/omap3/bootstrap-arm-omap.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/omap3/bootstrap-arm-omap.cpp @@ -13,9 +13,8 @@ IMPLEMENTATION [arm && omap]: void map_hw(void *pd) { - // map devices - map_1mb(pd, Mem_layout::Devices1_map_base, Mem_layout::Devices1_phys_base, false, false); - map_1mb(pd, Mem_layout::Devices2_map_base, Mem_layout::Devices2_phys_base, false, false); - map_1mb(pd, Mem_layout::Devices3_map_base, Mem_layout::Devices3_phys_base, false, false); - map_1mb(pd, Mem_layout::Devices4_map_base, Mem_layout::Devices4_phys_base, false, false); + map_dev(pd, 1); + map_dev(pd, 2); + map_dev(pd, 3); + map_dev(pd, 4); } diff --git a/kernel/fiasco/src/kern/arm/bsp/omap3/mem_layout-arm-omap.cpp b/kernel/fiasco/src/kern/arm/bsp/omap3/mem_layout-arm-omap.cpp index 202fc5ff..e65a4cc3 100644 --- a/kernel/fiasco/src/kern/arm/bsp/omap3/mem_layout-arm-omap.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/omap3/mem_layout-arm-omap.cpp @@ -3,25 +3,21 @@ INTERFACE [arm && omap3_35x]: //------------------------------------------- EXTENSION class Mem_layout { public: - enum Virt_layout_omap3_35x { - Devices1_map_base = Registers_map_start, + enum Virt_layout_omap3_35x : Address { L4_addr_prot_map_base = Devices1_map_base + 0x00040000, Uart1_map_base = Devices1_map_base + 0x0006a000, Gptimer10_map_base = Devices1_map_base + 0x00086000, Wkup_cm_map_base = Devices1_map_base + 0x00004c00, - Devices2_map_base = Registers_map_start + 0x00100000, Intc_map_base = Devices2_map_base + 0x0, - Devices3_map_base = Registers_map_start + 0x00200000, Timer1ms_map_base = Devices3_map_base + 0x00018000, Prm_global_reg_map_base = Devices3_map_base + 0x00007200, - Devices4_map_base = Registers_map_start + 0x00300000, Uart3_map_base = Devices4_map_base + 0x00020000, }; - enum Phys_layout_omap3_35x { + enum Phys_layout_omap3_35x : Address { Devices1_phys_base = 0x48000000, Devices2_phys_base = 0x48200000, Devices3_phys_base = 0x48300000, @@ -36,7 +32,7 @@ INTERFACE [arm && omap3_35xevm]: //---------------------------------------- EXTENSION class Mem_layout { public: - enum Virt_layout_omap3_35xevm { + enum Virt_layout_omap3_35xevm : Address { Uart_base = Uart1_map_base, }; }; @@ -46,7 +42,7 @@ INTERFACE [arm && omap3_beagleboard]: //----------------------------------- EXTENSION class Mem_layout { public: - enum Virt_layout_omap3_beagleboard { + enum Virt_layout_omap3_beagleboard : Address { Uart_base = Uart3_map_base, }; }; @@ -56,12 +52,7 @@ INTERFACE [arm && omap3_am33xx]: //---------------------------------------- EXTENSION class Mem_layout { public: - enum Virt_layout_omap3_335x { - Devices1_map_base = Registers_map_start, - Devices2_map_base = Registers_map_start + 0x00100000, - Devices3_map_base = Registers_map_start + 0x00200000, - Devices4_map_base = Registers_map_start + 0x00300000, - + enum Virt_layout_omap3_335x : Address { Cm_per_map_base = Devices1_map_base + 0x00000000, Cm_wkup_map_base = Devices1_map_base + 0x00000400, Cm_dpll_map_base = Devices1_map_base + 0x00000500, @@ -73,7 +64,7 @@ public: Uart_base = Uart1_map_base, }; - enum Phys_layout_omap3_335x { + enum Phys_layout_omap3_335x : Address { Devices1_phys_base = 0x44e00000, Devices2_phys_base = 0x48000000, Devices3_phys_base = 0x48100000, @@ -88,7 +79,7 @@ INTERFACE [arm && omap4]: //----------------------------------------------- EXTENSION class Mem_layout { public: - enum Phys_layout_omap4 { + enum Phys_layout_omap4 : Address { Devices1_phys_base = 0x48000000, Devices2_phys_base = 0x48200000, Devices3_phys_base = 0x4a300000, @@ -96,19 +87,14 @@ public: Sdram_phys_base = 0x80000000, }; - enum Virt_layout_omap4_pandaboard { - Devices1_map_base = Registers_map_start, - Devices2_map_base = Registers_map_start + 0x00100000, - Devices3_map_base = Registers_map_start + 0x00200000, - Devices4_map_base = Registers_map_start + 0x00300000, - + enum Virt_layout_omap4_pandaboard : Address { Uart_base = Devices1_map_base + 0x20000, Mp_scu_map_base = Devices2_map_base + 0x40000, Gic_cpu_map_base = Devices2_map_base + 0x40100, Gic_dist_map_base = Devices2_map_base + 0x41000, + L2cxx0_map_base = Devices2_map_base + 0x42000, __Timer = Devices2_map_base + 0x40600, - __PL310 = Devices2_map_base + 0x42000, Prm_map_base = Devices3_map_base + 0x6000, }; diff --git a/kernel/fiasco/src/kern/arm/bsp/omap3/outer_cache-arm-omap.cpp b/kernel/fiasco/src/kern/arm/bsp/omap3/outer_cache-arm-omap.cpp new file mode 100644 index 00000000..65f58477 --- /dev/null +++ b/kernel/fiasco/src/kern/arm/bsp/omap3/outer_cache-arm-omap.cpp @@ -0,0 +1,48 @@ +IMPLEMENTATION [arm && omap4 && outer_cache_l2cxx0]: + +EXTENSION class Outer_cache +{ + enum + { + Omap_l2cache_set_debug_reg = 0x100, + Omap_l2cache_clean_and_inv_range = 0x101, + Omap_l2cache_enable = 0x102, + Omap_l2cache_aux_reg = 0x109, + Omap_l2cache_tag_and_data_ram_lat_ctrl = 0x112, + Omap_l2cache_prefetch_ctrl = 0x113, + }; +}; + +PRIVATE static inline +void +Outer_cache::smc(Mword func, Mword val) +{ + register Mword _func asm("r12") = func; + register Mword _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"); +} + +IMPLEMENT +Mword +Outer_cache::platform_init(Mword aux_control) +{ + aux_control = (1 << 16) // 16-way associativity + | (3 << 17) // 64k waysize + | (1 << 22) // shared attrib override + | (1 << 25) // reserved + | (1 << 26) // ns lockdown enable + | (1 << 27) // ns irq access enable + | (1 << 28) // data prefetch + | (1 << 29) // insn prefetch + | (1 << 30) // early BRESP enable + ; + + smc(Omap_l2cache_aux_reg, aux_control); + smc(Omap_l2cache_enable, 1); + + return aux_control; +} diff --git a/kernel/fiasco/src/kern/arm/bsp/omap3/pic-arm-gic-omap4.cpp b/kernel/fiasco/src/kern/arm/bsp/omap3/pic-arm-gic-omap4.cpp index a69bf612..c07a00c8 100644 --- a/kernel/fiasco/src/kern/arm/bsp/omap3/pic-arm-gic-omap4.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/omap3/pic-arm-gic-omap4.cpp @@ -34,7 +34,7 @@ void Pic::restore_all(Status) IMPLEMENTATION [arm && mp && pic_gic && omap4]: PUBLIC static -void Pic::init_ap() +void Pic::init_ap(unsigned) { gic->init_ap(); } diff --git a/kernel/fiasco/src/kern/arm/bsp/omap3/boot_mp-arm-omap4.cpp b/kernel/fiasco/src/kern/arm/bsp/omap3/platform_control-arm-omap4.cpp similarity index 87% rename from kernel/fiasco/src/kern/arm/bsp/omap3/boot_mp-arm-omap4.cpp rename to kernel/fiasco/src/kern/arm/bsp/omap3/platform_control-arm-omap4.cpp index e3cf796c..c5d6b84f 100644 --- a/kernel/fiasco/src/kern/arm/bsp/omap3/boot_mp-arm-omap4.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/omap3/platform_control-arm-omap4.cpp @@ -1,19 +1,14 @@ INTERFACE [arm && mp && omap4]: - #include "types.h" -class Boot_mp -{ -}; - IMPLEMENTATION [arm && mp && omap4]: #include "io.h" #include "kmem.h" -PRIVATE +PRIVATE static void -Boot_mp::aux(unsigned cmd, Mword arg0, Mword arg1) +Platform_control::aux(unsigned cmd, Mword arg0, Mword arg1) { register unsigned long r0 asm("r0") = arg0; register unsigned long r1 asm("r1") = arg1; @@ -25,9 +20,9 @@ Boot_mp::aux(unsigned cmd, Mword arg0, Mword arg1) "r7", "r8", "r9", "r10", "r11", "lr", "memory"); } -PUBLIC +PUBLIC static void -Boot_mp::start_ap_cpus(Address phys_tramp_mp_addr) +Platform_control::boot_ap_cpus(Address phys_tramp_mp_addr) { // two possibilities available, the memory mapped only in later board // revisions @@ -54,7 +49,3 @@ Boot_mp::start_ap_cpus(Address phys_tramp_mp_addr) } } -PUBLIC -void -Boot_mp::cleanup() -{} diff --git a/kernel/fiasco/src/kern/arm/bsp/pxa/Kconfig b/kernel/fiasco/src/kern/arm/bsp/pxa/Kconfig index 4965f959..290094bb 100644 --- a/kernel/fiasco/src/kern/arm/bsp/pxa/Kconfig +++ b/kernel/fiasco/src/kern/arm/bsp/pxa/Kconfig @@ -1,4 +1,4 @@ # PF: XSCALE # PFDESCR: Intel XScale Platform -# PFCAN: CAN_ARM_CPU_XSCALE +# PFSELECT: CAN_ARM_CPU_XSCALE # PFDEPENDS: ARM diff --git a/kernel/fiasco/src/kern/arm/bsp/pxa/bootstrap-arm-pxa.cpp b/kernel/fiasco/src/kern/arm/bsp/pxa/bootstrap-arm-pxa.cpp index 2c535f71..836e3f62 100644 --- a/kernel/fiasco/src/kern/arm/bsp/pxa/bootstrap-arm-pxa.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/pxa/bootstrap-arm-pxa.cpp @@ -13,11 +13,8 @@ map_hw(void *pd) { // map the cache flush area to 0xef000000 map_1mb(pd, Mem_layout::Cache_flush_area, Mem_layout::Flush_area_phys_base, true, false); - // map UART - map_1mb(pd, Mem_layout::Uart_map_base, Mem_layout::Uart_phys_base, false, false); - map_1mb(pd, Mem_layout::Uart_phys_base, Mem_layout::Uart_phys_base, false, false); - // map Timer - map_1mb(pd, Mem_layout::Timer_map_base, Mem_layout::Timer_phys_base, false, false); - // map Pic - map_1mb(pd, Mem_layout::Pic_map_base, Mem_layout::Pic_phys_base, false, false); + + map_dev(pd, 0); + map_dev(pd, 1); + map_dev(pd, 2); } diff --git a/kernel/fiasco/src/kern/arm/bsp/pxa/mem_layout-arm-pxa.cpp b/kernel/fiasco/src/kern/arm/bsp/pxa/mem_layout-arm-pxa.cpp index 4baa51bd..2d1da9cc 100644 --- a/kernel/fiasco/src/kern/arm/bsp/pxa/mem_layout-arm-pxa.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/pxa/mem_layout-arm-pxa.cpp @@ -3,17 +3,17 @@ INTERFACE [arm-pxa]: //------------------------------------------------------ EXTENSION class Mem_layout { public: - enum Virt_layout_pxa { - Timer_map_base = 0xef100000, - Pic_map_base = 0xef200000, - Uart_map_base = 0xef300000, + enum Virt_layout_pxa : Address { + Timer_map_base = Devices0_map_base, + Pic_map_base = Devices1_map_base, + Uart_map_base = Devices2_map_base, Uart_base = Uart_map_base, }; - enum Phys_layout { - Timer_phys_base = 0x40a00000, - Pic_phys_base = 0x40d00000, - Uart_phys_base = 0x40100000, + enum Phys_layout : Address { + Devices0_phys_base = 0x40a00000, + Devices1_phys_base = 0x40d00000, + Devices2_phys_base = 0x40100000, Sdram_phys_base = 0xa0000000, Flush_area_phys_base = 0xe0000000, }; diff --git a/kernel/fiasco/src/kern/arm/bsp/realview/Modules b/kernel/fiasco/src/kern/arm/bsp/realview/Modules index d5a7336d..b4f28a20 100644 --- a/kernel/fiasco/src/kern/arm/bsp/realview/Modules +++ b/kernel/fiasco/src/kern/arm/bsp/realview/Modules @@ -20,7 +20,7 @@ else timer_IMPL += timer-arm-mptimer timer-arm-mptimer-realview endif -INTERFACES_KERNEL += gic boot_mp platform board_check-arm-realview +INTERFACES_KERNEL += gic platform board_check-arm-realview timer_tick_IMPL += timer_tick-single-vector uart_IMPL += uart-arm-realview @@ -32,5 +32,5 @@ kernel_uart_IMPL += kernel_uart-arm-realview reset_IMPL += reset-arm-realview clock_IMPL += clock-arm-realview outer_cache_IMPL += outer_cache-arm-realview -boot_mp_IMPL += boot_mp-arm-realview platform_IMPL += platform-arm-realview +platform_control_IMPL += platform_control-arm-realview diff --git a/kernel/fiasco/src/kern/arm/bsp/realview/board_check-arm-realview.cpp b/kernel/fiasco/src/kern/arm/bsp/realview/board_check-arm-realview.cpp index 865fb5db..841f7f88 100644 --- a/kernel/fiasco/src/kern/arm/bsp/realview/board_check-arm-realview.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/realview/board_check-arm-realview.cpp @@ -9,7 +9,8 @@ public: private: static Mword read_board_id(); - struct id_pair { + struct id_pair + { unsigned mask, id; }; static id_pair ids[]; diff --git a/kernel/fiasco/src/kern/arm/bsp/realview/bootstrap-arm-realview.cpp b/kernel/fiasco/src/kern/arm/bsp/realview/bootstrap-arm-realview.cpp index 8583757b..3c4c046b 100644 --- a/kernel/fiasco/src/kern/arm/bsp/realview/bootstrap-arm-realview.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/realview/bootstrap-arm-realview.cpp @@ -4,48 +4,13 @@ INTERFACE [arm && realview]: enum { Cache_flush_area = 0, }; -//----------------------------------------------------------------------------- -IMPLEMENTATION [arm && realview && realview_eb && !(mpcore || (armca9 && mp))]: - -static void map_hw2(void *) -{} - -//----------------------------------------------------------------------------- -IMPLEMENTATION [arm && realview && realview_eb && (mpcore || (armca9 && mp))]: - -static void map_hw2(void *pd) -{ - map_1mb(pd, Mem_layout::Mp_scu_map_base, Mem_layout::Mp_scu_phys_base, - false, false); -} - -//----------------------------------------------------------------------------- -IMPLEMENTATION [arm && realview && (realview_pb11mp || realview_pbx)]: - -static void map_hw2(void *pd) -{ - map_1mb(pd, Mem_layout::Devices1_map_base, Mem_layout::Devices1_phys_base, - false, false); - map_1mb(pd, Mem_layout::Devices2_map_base, Mem_layout::Devices2_phys_base, - false, false); -} - -//----------------------------------------------------------------------------- -IMPLEMENTATION [arm && realview && realview_vexpress]: - -static void map_hw2(void *pd) -{ - map_1mb(pd, Mem_layout::Devices1_map_base, Mem_layout::Devices1_phys_base, - false, false); -} - //----------------------------------------------------------------------------- IMPLEMENTATION [arm && realview]: void map_hw(void *pd) { - // map devices - map_1mb(pd, Mem_layout::Devices0_map_base, Mem_layout::Devices0_phys_base, false, false); - map_hw2(pd); + map_dev(pd, 0); + map_dev(pd, 1); + map_dev(pd, 2); } diff --git a/kernel/fiasco/src/kern/arm/bsp/realview/mem_layout-arm-realview.cpp b/kernel/fiasco/src/kern/arm/bsp/realview/mem_layout-arm-realview.cpp index 5ee295aa..b7af3315 100644 --- a/kernel/fiasco/src/kern/arm/bsp/realview/mem_layout-arm-realview.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/realview/mem_layout-arm-realview.cpp @@ -5,14 +5,9 @@ INTERFACE [arm && realview]: // ------------------------------------------- EXTENSION class Mem_layout { public: - enum Phys_layout_realview_all { + enum Phys_layout_realview_all : Address { Sdram_phys_base = CONFIG_PF_REALVIEW_RAM_PHYS_BASE, Flush_area_phys_base = 0xe0000000, - - Devices0_map_base = Registers_map_start, - Devices1_map_base = Registers_map_start + 0x00100000, - Devices2_map_base = Registers_map_start + 0x00200000, - }; }; @@ -24,7 +19,7 @@ INTERFACE [arm && realview && (realview_eb || realview_pb11mp || realview_pbx || EXTENSION class Mem_layout { public: - enum Virt_layout_realview { + enum Virt_layout_realview : Address { System_regs_map_base = Devices0_map_base, System_ctrl_map_base = Devices0_map_base + 0x00001000, Uart0_map_base = Devices0_map_base + 0x00009000, @@ -38,13 +33,8 @@ public: Uart_base = Uart0_map_base, }; - enum Phys_layout_realview { + enum Phys_layout_realview : Address { Devices0_phys_base = 0x10000000, - System_regs_phys_base= Devices0_phys_base, - System_ctrl_phys_base= Devices0_phys_base + 0x00001000, - Uart0_phys_base = Devices0_phys_base + 0x00009000, - Timer0_1_phys_base = Devices0_phys_base + 0x00011000, - Timer2_3_phys_base = Devices0_phys_base + 0x00012000, }; }; @@ -54,14 +44,14 @@ INTERFACE [arm && realview && realview_eb && !(mpcore || armca9)]: EXTENSION class Mem_layout { public: - enum Virt_layout_realview_single { + enum Virt_layout_realview_single : Address { Gic_cpu_map_base = Devices0_map_base + 0x00040000, - Gic_dist_map_base = Gic_cpu_map_base + 0x00001000, + Gic_dist_map_base = Gic_cpu_map_base + 0x00001000, }; - enum Phys_layout_realview_single { - Gic_cpu_phys_base = Devices0_phys_base + 0x00040000, - Gic_dist_phys_base = Gic_cpu_phys_base + 0x00001000, + enum Phys_layout_realview_single : Address { + Devices1_phys_base = Invalid_address, + Devices2_phys_base = Invalid_address, }; }; @@ -71,7 +61,7 @@ INTERFACE [arm && realview && realview_eb && (mpcore || armca9)]: EXTENSION class Mem_layout { public: - enum Virt_layout_realview_mp { + enum Virt_layout_realview_mp : Address { Mp_scu_map_base = Devices1_map_base, Gic_cpu_map_base = Devices1_map_base + 0x00000100, Gic_dist_map_base = Devices1_map_base + 0x00001000, @@ -79,22 +69,18 @@ public: Gic1_cpu_map_base = Devices0_map_base + 0x00040000, Gic1_dist_map_base = Devices0_map_base + 0x00041000, + + Gic2_cpu_map_base = Devices0_map_base + 0x00050000, + Gic2_dist_map_base = Devices0_map_base + 0x00051000, + Gic3_cpu_map_base = Devices0_map_base + 0x00060000, + Gic3_dist_map_base = Devices0_map_base + 0x00061000, + Gic4_cpu_map_base = Devices0_map_base + 0x00070000, + Gic4_dist_map_base = Devices0_map_base + 0x00071000, }; - enum Phys_layout_realview_mp { - Mp_scu_phys_base = 0x1f000000, - Gic_cpu_phys_base = Mp_scu_phys_base + 0x00000100, - Gic_dist_phys_base = Mp_scu_phys_base + 0x00001000, - L2cxx0_phys_base = Mp_scu_phys_base + 0x00002000, - - Gic1_cpu_phys_base = Devices0_phys_base + 0x00040000, - Gic1_dist_phys_base = Devices0_phys_base + 0x00041000, - Gic2_cpu_phys_base = Devices0_phys_base + 0x00050000, - Gic2_dist_phys_base = Devices0_phys_base + 0x00051000, - Gic3_cpu_phys_base = Devices0_phys_base + 0x00060000, - Gic3_dist_phys_base = Devices0_phys_base + 0x00061000, - Gic4_cpu_phys_base = Devices0_phys_base + 0x00070000, - Gic4_dist_phys_base = Devices0_phys_base + 0x00071000, + enum Phys_layout_realview_mp : Address { + Devices1_phys_base = 0x1f000000, + Devices2_phys_base = Invalid_address, }; }; @@ -104,7 +90,7 @@ INTERFACE [arm && realview && realview_pb11mp]: EXTENSION class Mem_layout { public: - enum Virt_layout_realview_pb11mp { + enum Virt_layout_realview_pb11mp : Address { Mp_scu_map_base = Devices1_map_base, Gic_cpu_map_base = Devices1_map_base + 0x00000100, Gic_dist_map_base = Devices1_map_base + 0x00001000, @@ -114,18 +100,9 @@ public: Gic1_dist_map_base = Devices2_map_base + 0x00001000, }; - enum Phys_layout_realview_pb11mp { + enum Phys_layout_realview_pb11mp : Address { Devices1_phys_base = 0x1f000000, - Mp_scu_phys_base = 0x1f000000, - Gic_cpu_phys_base = Mp_scu_phys_base + 0x00000100, - Gic_dist_phys_base = Mp_scu_phys_base + 0x00001000, - L2cxx0_phys_base = Mp_scu_phys_base + 0x00002000, - Devices2_phys_base = 0x1e000000, - Gic0_cpu_phys_base = 0x1e000000, - Gic0_dist_phys_base = Gic0_cpu_phys_base + 0x00001000, - Gic1_cpu_phys_base = 0x1e010000, - Gic1_dist_phys_base = Gic1_cpu_phys_base + 0x00001000, }; }; @@ -135,7 +112,7 @@ INTERFACE [arm && realview && realview_pbx]: EXTENSION class Mem_layout { public: - enum Virt_layout_realview_pbx { + enum Virt_layout_realview_pbx : Address { Mp_scu_map_base = Devices1_map_base, Gic_cpu_map_base = Devices1_map_base + 0x00000100, Gic_dist_map_base = Devices1_map_base + 0x00001000, @@ -147,18 +124,9 @@ public: Gic3_dist_map_base = Devices2_map_base + 0x00031000, }; - enum Phys_layout_realview_pbx { + enum Phys_layout_realview_pbx : Address { Devices1_phys_base = 0x1f000000, - Mp_scu_phys_base = 0x1f000000, - Gic_cpu_phys_base = Mp_scu_phys_base + 0x00000100, - Gic_dist_phys_base = Mp_scu_phys_base + 0x00001000, - L2cxx0_phys_base = Mp_scu_phys_base + 0x00002000, - Devices2_phys_base = 0x1e000000, - Gic2_cpu_phys_base = 0x1e020000, - Gic2_dist_phys_base = Gic2_cpu_phys_base + 0x00001000, - Gic3_cpu_phys_base = 0x1e030000, - Gic3_dist_phys_base = Gic3_cpu_phys_base + 0x00001000, }; }; @@ -168,18 +136,15 @@ INTERFACE [arm && realview && realview_vexpress]: EXTENSION class Mem_layout { public: - enum Virt_layout_realview_vexpress { + enum Virt_layout_realview_vexpress : Address { Mp_scu_map_base = Devices1_map_base, Gic_cpu_map_base = Devices1_map_base + 0x00000100, Gic_dist_map_base = Devices1_map_base + 0x00001000, L2cxx0_map_base = Devices1_map_base + 0x00002000, }; - enum Phys_layout_realview_vexpress { + enum Phys_layout_realview_vexpress : Address { Devices1_phys_base = 0x1e000000, - Mp_scu_phys_base = 0x1e000000, - Gic_cpu_phys_base = Mp_scu_phys_base + 0x00000100, - Gic_dist_phys_base = Mp_scu_phys_base + 0x00001000, - L2cxx0_phys_base = Mp_scu_phys_base + 0x00002000, + Devices2_phys_base = Invalid_address, }; }; diff --git a/kernel/fiasco/src/kern/arm/bsp/realview/pic-arm-realview.cpp b/kernel/fiasco/src/kern/arm/bsp/realview/pic-arm-realview.cpp index 749a9745..4cf9c72c 100644 --- a/kernel/fiasco/src/kern/arm/bsp/realview/pic-arm-realview.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/realview/pic-arm-realview.cpp @@ -31,7 +31,7 @@ IMPLEMENTATION [arm && pic_gic && realview && (realview_pb11mp || (realview_eb & #include "cascade_irq.h" PUBLIC static -void Pic::init_ap() +void Pic::init_ap(unsigned) { gic->init_ap(); static_cast(Irq_mgr::mgr->chip(256).chip)->init_ap(); @@ -79,7 +79,7 @@ void Pic::init() } PUBLIC static -void Pic::init_ap() +void Pic::init_ap(unsigned) { gic->init_ap(); } diff --git a/kernel/fiasco/src/kern/arm/bsp/realview/boot_mp-arm-realview.cpp b/kernel/fiasco/src/kern/arm/bsp/realview/platform_control-arm-realview.cpp similarity index 78% rename from kernel/fiasco/src/kern/arm/bsp/realview/boot_mp-arm-realview.cpp rename to kernel/fiasco/src/kern/arm/bsp/realview/platform_control-arm-realview.cpp index 2cf7be7b..4cc9f992 100644 --- a/kernel/fiasco/src/kern/arm/bsp/realview/boot_mp-arm-realview.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/realview/platform_control-arm-realview.cpp @@ -1,20 +1,15 @@ INTERFACE [arm && mp && realview]: - #include "types.h" -class Boot_mp -{ -}; - IMPLEMENTATION [arm && mp && realview]: #include "io.h" #include "ipi.h" #include "platform.h" -PUBLIC +PUBLIC static void -Boot_mp::start_ap_cpus(Address phys_tramp_mp_addr) +Platform_control::boot_ap_cpus(Address phys_tramp_mp_addr) { // set physical start address for AP CPUs Platform::write(Platform::Sys::Flags_clr, 0xffffffff); @@ -24,7 +19,3 @@ Boot_mp::start_ap_cpus(Address phys_tramp_mp_addr) Ipi::bcast(Ipi::Global_request, 0); } -PUBLIC -void -Boot_mp::cleanup() -{} diff --git a/kernel/fiasco/src/kern/arm/bsp/s3c/Kconfig b/kernel/fiasco/src/kern/arm/bsp/s3c/Kconfig index 7ae57fca..3e777f3f 100644 --- a/kernel/fiasco/src/kern/arm/bsp/s3c/Kconfig +++ b/kernel/fiasco/src/kern/arm/bsp/s3c/Kconfig @@ -1,4 +1,4 @@ # PF: S3C2410 # PFDESCR: Samsung S3C2410 Platform # PFDEPENDS: ARM -# PFCAN: CAN_ARM_CPU_920T +# PFSELECT: CAN_ARM_CPU_920T diff --git a/kernel/fiasco/src/kern/arm/bsp/s3c/bootstrap-arm-s3c2410.cpp b/kernel/fiasco/src/kern/arm/bsp/s3c/bootstrap-arm-s3c2410.cpp index a8194f0c..cc46cee2 100644 --- a/kernel/fiasco/src/kern/arm/bsp/s3c/bootstrap-arm-s3c2410.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/s3c/bootstrap-arm-s3c2410.cpp @@ -12,13 +12,8 @@ IMPLEMENTATION [arm && s3c2410]: void map_hw(void *pd) { - // map UART - map_1mb(pd, Mem_layout::Uart_map_base, Mem_layout::Uart_phys_base, false, false); - // map Timer - map_1mb(pd, Mem_layout::Timer_map_base, Mem_layout::Timer_phys_base, false, false); - // map Pic - map_1mb(pd, Mem_layout::Pic_map_base, Mem_layout::Pic_phys_base, false, false); - - // map watchdog - map_1mb(pd, Mem_layout::Watchdog_map_base, Mem_layout::Watchdog_phys_base, false, false); + map_dev(pd, 0); + map_dev(pd, 1); + map_dev(pd, 2); + map_dev(pd, 3); } diff --git a/kernel/fiasco/src/kern/arm/bsp/s3c/mem_layout-arm-s3c2410.cpp b/kernel/fiasco/src/kern/arm/bsp/s3c/mem_layout-arm-s3c2410.cpp index 9fd3edab..6253830f 100644 --- a/kernel/fiasco/src/kern/arm/bsp/s3c/mem_layout-arm-s3c2410.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/s3c/mem_layout-arm-s3c2410.cpp @@ -3,19 +3,19 @@ INTERFACE [arm && s3c2410]: //---------------------------------------------- EXTENSION class Mem_layout { public: - enum Virt_layout_s3c2410 { - Uart_map_base = 0xef100000, - Timer_map_base = 0xef200000, - Pic_map_base = 0xef300000, - Watchdog_map_base = 0xef400000, + enum Virt_layout_s3c2410 : Address { + Uart_map_base = Devices0_map_base, + Timer_map_base = Devices1_map_base, + Pic_map_base = Devices2_map_base, + Watchdog_map_base = Devices3_map_base, Uart_base = Uart_map_base, }; - enum Phys_layout { - Uart_phys_base = 0x50000000, - Timer_phys_base = 0x51000000, - Pic_phys_base = 0x4a000000, - Watchdog_phys_base = 0x53000000, + enum Phys_layout : Address{ + Devices0_phys_base = 0x50000000, + Devices1_phys_base = 0x51000000, + Devices2_phys_base = 0x4a000000, + Devices3_phys_base = 0x53000000, Sdram_phys_base = 0x30000000, Flush_area_phys_base = 0xe0000000, }; diff --git a/kernel/fiasco/src/kern/arm/bsp/sa1100/Kconfig b/kernel/fiasco/src/kern/arm/bsp/sa1100/Kconfig index 1583fb5f..13b1af9f 100644 --- a/kernel/fiasco/src/kern/arm/bsp/sa1100/Kconfig +++ b/kernel/fiasco/src/kern/arm/bsp/sa1100/Kconfig @@ -1,4 +1,4 @@ # PF: SA1100 # PFDESCR: Intel StrongARM -# PFCAN: CAN_ARM_CPU_SA1100 +# PFSELECT: CAN_ARM_CPU_SA1100 # PFDEPENDS: ARM diff --git a/kernel/fiasco/src/kern/arm/bsp/sa1100/bootstrap-arm-sa1100.cpp b/kernel/fiasco/src/kern/arm/bsp/sa1100/bootstrap-arm-sa1100.cpp index 31eef57e..03cffb5a 100644 --- a/kernel/fiasco/src/kern/arm/bsp/sa1100/bootstrap-arm-sa1100.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/sa1100/bootstrap-arm-sa1100.cpp @@ -15,9 +15,7 @@ map_hw(void *pd) { // map the cache flush area to 0xef000000 map_1mb(pd, Mem_layout::Cache_flush_area, Mem_layout::Flush_area_phys_base, true, false); - // map UART - map_1mb(pd, Mem_layout::Uart_map_base, Mem_layout::Uart_phys_base, false, false); - map_1mb(pd, Mem_layout::Uart_phys_base, Mem_layout::Uart_phys_base, false, false); - // map Timer and Pic - map_1mb(pd, Mem_layout::Timer_map_base, Mem_layout::Timer_phys_base, false, false); + + map_dev(pd, 0); + map_dev(pd, 1); } diff --git a/kernel/fiasco/src/kern/arm/bsp/sa1100/mem_layout-arm-sa1100.cpp b/kernel/fiasco/src/kern/arm/bsp/sa1100/mem_layout-arm-sa1100.cpp index 578c6607..d9cc6c07 100644 --- a/kernel/fiasco/src/kern/arm/bsp/sa1100/mem_layout-arm-sa1100.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/sa1100/mem_layout-arm-sa1100.cpp @@ -4,20 +4,16 @@ INTERFACE [arm-sa1100]: EXTENSION class Mem_layout { public: - enum Virt_layout_sa1100 { - Uart_map_base = 0xef100000, - Timer_map_base = 0xef200000, - Pic_map_base = 0xef250000, - Uart_base = Uart_map_base + 0x50000, + enum Virt_layout_sa1100 : Address { + Uart_base = Devices0_map_base + 0x50000, + Timer_map_base = Devices1_map_base, + Pic_map_base = Devices1_map_base + 0x50000, }; - enum Phys_layout { - Uart_phys_base = 0x80050000, - Timer_phys_base = 0x90000000, - Pic_phys_base = 0x90050000, + enum Phys_layout : Address { + Devices0_phys_base = 0x80000000, + Devices1_phys_base = 0x90000000, Sdram_phys_base = 0xc0000000, Flush_area_phys_base = 0xe0000000, }; }; - - diff --git a/kernel/fiasco/src/kern/arm/bsp/tegra2/Kconfig b/kernel/fiasco/src/kern/arm/bsp/tegra2/Kconfig index 66d0ed9a..0904127b 100644 --- a/kernel/fiasco/src/kern/arm/bsp/tegra2/Kconfig +++ b/kernel/fiasco/src/kern/arm/bsp/tegra2/Kconfig @@ -1,4 +1,4 @@ # PF: TEGRA2 # PFDESCR: NVIDIA Tegra 2xx platform -# PFCAN: CAN_ARM_CPU_CORTEX_A9 CAN_ARM_CACHE_L2CXX0 +# PFSELECT: CAN_ARM_CPU_CORTEX_A9 CAN_ARM_CACHE_L2CXX0 # PFDEPENDS: ARM diff --git a/kernel/fiasco/src/kern/arm/bsp/tegra2/Modules b/kernel/fiasco/src/kern/arm/bsp/tegra2/Modules index 71c6144c..c3d09302 100644 --- a/kernel/fiasco/src/kern/arm/bsp/tegra2/Modules +++ b/kernel/fiasco/src/kern/arm/bsp/tegra2/Modules @@ -2,7 +2,7 @@ PREPROCESS_PARTS += tegra2 16550 pic_gic mptimer generic_tickless_idle CONFIG_KERNEL_LOAD_ADDR := 0x0 -INTERFACES_KERNEL += gic boot_mp +INTERFACES_KERNEL += gic MPCORE_PHYS_BASE := 0x50040000 uart_IMPL += uart-16550 uart-16550-arm-tegra2 @@ -15,5 +15,5 @@ timer_tick_IMPL += timer_tick-single-vector kernel_uart_IMPL += kernel_uart-arm-tegra2 reset_IMPL += reset-arm-tegra2 clock_IMPL += clock-generic -boot_mp_IMPL += boot_mp-arm-tegra2 +platform_control_IMPL += platform_control-arm-tegra2 outer_cache_IMPL += outer_cache-arm-tegra2 diff --git a/kernel/fiasco/src/kern/arm/bsp/tegra2/bootstrap-arm-tegra2.cpp b/kernel/fiasco/src/kern/arm/bsp/tegra2/bootstrap-arm-tegra2.cpp index eb52d614..b681c7ef 100644 --- a/kernel/fiasco/src/kern/arm/bsp/tegra2/bootstrap-arm-tegra2.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/tegra2/bootstrap-arm-tegra2.cpp @@ -10,7 +10,7 @@ IMPLEMENTATION [arm && tegra2]: void map_hw(void *pd) { - map_1mb(pd, Mem_layout::Devices0_map_base, Mem_layout::Devices0_phys_base, false, false); - map_1mb(pd, Mem_layout::Devices1_map_base, Mem_layout::Devices1_phys_base, false, false); - map_1mb(pd, Mem_layout::Devices2_map_base, Mem_layout::Devices2_phys_base, false, false); + map_dev(pd, 0); + map_dev(pd, 1); + map_dev(pd, 2); } diff --git a/kernel/fiasco/src/kern/arm/bsp/tegra2/mem_layout-arm-tegra2.cpp b/kernel/fiasco/src/kern/arm/bsp/tegra2/mem_layout-arm-tegra2.cpp index ff50b924..c8f81fe6 100644 --- a/kernel/fiasco/src/kern/arm/bsp/tegra2/mem_layout-arm-tegra2.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/tegra2/mem_layout-arm-tegra2.cpp @@ -3,12 +3,8 @@ INTERFACE [arm && tegra2]: EXTENSION class Mem_layout { public: - enum Virt_layout_tegra2 { - - Devices0_map_base = Registers_map_start, - Devices1_map_base = Registers_map_start + 0x00100000, - Devices2_map_base = Registers_map_start + 0x00200000, - + enum Virt_layout_tegra2 : Address + { Mp_scu_map_base = Devices2_map_base + 0x00040000, L2cxx0_map_base = Devices2_map_base + 0x00043000, @@ -21,7 +17,7 @@ public: Clock_reset_map_base = Devices1_map_base + 0x00006000, }; - enum Phys_layout_tegra2 { + enum Phys_layout_tegra2 : Address { Devices0_phys_base = 0x70000000, Devices1_phys_base = 0x60000000, Devices2_phys_base = 0x50000000, diff --git a/kernel/fiasco/src/kern/arm/bsp/tegra2/pic-arm-tegra2.cpp b/kernel/fiasco/src/kern/arm/bsp/tegra2/pic-arm-tegra2.cpp index f7177133..b9fd9fae 100644 --- a/kernel/fiasco/src/kern/arm/bsp/tegra2/pic-arm-tegra2.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/tegra2/pic-arm-tegra2.cpp @@ -15,7 +15,7 @@ void Pic::init() { typedef Irq_mgr_multi_chip<8> M; - M *m = new Boot_object(16); + M *m = new Boot_object(1); gic.construct(Kmem::Gic_cpu_map_base, Kmem::Gic_dist_map_base); m->add_chip(0, gic, gic->nr_irqs()); @@ -35,7 +35,7 @@ void Pic::restore_all(Status) IMPLEMENTATION [arm && mp && pic_gic && tegra2]: PUBLIC static -void Pic::init_ap() +void Pic::init_ap(unsigned) { gic->init_ap(); } diff --git a/kernel/fiasco/src/kern/arm/bsp/tegra2/boot_mp-arm-tegra2.cpp b/kernel/fiasco/src/kern/arm/bsp/tegra2/platform_control-arm-tegra2.cpp similarity index 76% rename from kernel/fiasco/src/kern/arm/bsp/tegra2/boot_mp-arm-tegra2.cpp rename to kernel/fiasco/src/kern/arm/bsp/tegra2/platform_control-arm-tegra2.cpp index 8430399b..87d41da2 100644 --- a/kernel/fiasco/src/kern/arm/bsp/tegra2/boot_mp-arm-tegra2.cpp +++ b/kernel/fiasco/src/kern/arm/bsp/tegra2/platform_control-arm-tegra2.cpp @@ -2,7 +2,7 @@ INTERFACE [arm && mp && tegra2]: #include "mem_layout.h" -class Boot_mp +EXTENSION class Platform_control { private: enum @@ -13,16 +13,25 @@ private: Unhalt_addr = Mem_layout::Devices1_map_base + 0x7014, }; - Mword _orig_reset_vector; + static Mword _orig_reset_vector; }; IMPLEMENTATION [arm && mp && tegra2]: #include "io.h" +#include -PUBLIC +Mword Platform_control::_orig_reset_vector; + +PRIVATE static +void Platform_control::reset_orig_reset_vector() +{ + Io::write(_orig_reset_vector, Reset_vector_addr); +} + +PUBLIC static void -Boot_mp::start_ap_cpus(Address phys_reset_vector) +Platform_control::boot_ap_cpus(Address phys_reset_vector) { // remember original reset vector _orig_reset_vector = Io::read(Reset_vector_addr); @@ -30,6 +39,8 @@ Boot_mp::start_ap_cpus(Address phys_reset_vector) // set (temporary) new reset vector Io::write(phys_reset_vector, Reset_vector_addr); + atexit(reset_orig_reset_vector); + // clocks on other cpu Mword r = Io::read(Clk_rst_ctrl_clk_cpu_cmplx); Io::write(r & ~(1 << 9), Clk_rst_ctrl_clk_cpu_cmplx); @@ -40,9 +51,3 @@ Boot_mp::start_ap_cpus(Address phys_reset_vector) Io::write(0, Unhalt_addr); } -PUBLIC -void -Boot_mp::cleanup() -{ - Io::write(_orig_reset_vector, Reset_vector_addr); -} diff --git a/kernel/fiasco/src/kern/arm/context-arm.cpp b/kernel/fiasco/src/kern/arm/context-arm.cpp index 15a49930..cc3b01c9 100644 --- a/kernel/fiasco/src/kern/arm/context-arm.cpp +++ b/kernel/fiasco/src/kern/arm/context-arm.cpp @@ -17,6 +17,9 @@ EXTENSION class Context { private: Mword _tpidrurw; + +protected: + Mword _tpidruro; }; // ------------------------------------------------------------------------ @@ -35,7 +38,7 @@ IMPLEMENTATION [arm]: #include "utcb_support.h" -IMPLEMENT inline NEEDS[Context::load_tpidrurw] +IMPLEMENT inline void Context::fill_user_state() { @@ -46,7 +49,7 @@ Context::fill_user_state() : : "m"(ef->usp), "m"(ef->ulr), [rf] "r" (&ef->usp)); } -IMPLEMENT inline NEEDS[Context::store_tpidrurw] +IMPLEMENT inline void Context::spill_user_state() { @@ -56,10 +59,8 @@ Context::spill_user_state() : "=m"(ef->usp), "=m"(ef->ulr) : [rf] "r" (&ef->usp)); } - -PROTECTED inline void Context::arch_setup_utcb_ptr() {} - -IMPLEMENT inline NEEDS[Context::spill_user_state] +IMPLEMENT inline NEEDS[Context::spill_user_state, Context::store_tpidrurw, + Context::load_tpidrurw, Context::load_tpidruro] void Context::switch_cpu(Context *t) { @@ -69,6 +70,7 @@ Context::switch_cpu(Context *t) store_tpidrurw(); t->fill_user_state(); t->load_tpidrurw(); + t->load_tpidruro(); { register Mword _old_this asm("r1") = (Mword)this; @@ -118,17 +120,12 @@ void Context::switchin_context(Context *from) assert_kdb (this == current()); assert_kdb (state() & Thread_ready_mask); -#if 0 - printf("switch in address space: %p\n",_space); -#endif - // switch to our page directory if nessecary vcpu_aware_space()->switchin_context(from->vcpu_aware_space()); - Utcb_support::current(utcb().usr()); + Utcb_support::current(current()->utcb().usr()); } - IMPLEMENT inline void Context::set_ignore_mem_op_in_progress(bool val) @@ -140,6 +137,36 @@ Context::set_ignore_mem_op_in_progress(bool val) // ------------------------------------------------------------------------ IMPLEMENTATION [armv6plus]: +PROTECTED inline void Context::arch_setup_utcb_ptr() +{ + _tpidruro = reinterpret_cast(utcb().usr().get()); +} + +IMPLEMENT inline +void +Context::arch_load_vcpu_kern_state(Vcpu_state *vcpu, bool do_load) +{ + _tpidruro = vcpu->_tpidruro; + if (do_load) + load_tpidruro(); +} + +IMPLEMENT inline +void +Context::arch_load_vcpu_user_state(Vcpu_state *vcpu, bool do_load) +{ + _tpidruro = vcpu->_ts.tpidruro; + if (do_load) + load_tpidruro(); +} + +IMPLEMENT inline +void +Context::arch_update_vcpu_state(Vcpu_state *vcpu) +{ + vcpu->_tpidruro = _tpidruro; +} + PRIVATE inline void Context::store_tpidrurw() @@ -154,15 +181,58 @@ Context::load_tpidrurw() const asm volatile ("mcr p15, 0, %0, c13, c0, 2" : : "r" (_tpidrurw)); } +PROTECTED inline +void +Context::load_tpidruro() const +{ + asm volatile ("mcr p15, 0, %0, c13, c0, 3" : : "r" (_tpidruro)); +} + +PUBLIC inline +Mword +Context::tpidrurw() const +{ + return _tpidrurw; +} + +PUBLIC inline +Mword +Context::tpidruro() const +{ + return _tpidruro; +} + // ------------------------------------------------------------------------ IMPLEMENTATION [!armv6plus]: +PROTECTED inline void Context::arch_setup_utcb_ptr() +{} + PRIVATE inline void -Context::store_tpidrurw() +Context::store_tpidrurw() const {} PRIVATE inline void Context::load_tpidrurw() const {} + +PROTECTED inline +void +Context::load_tpidruro() const +{} + +PUBLIC inline +Mword +Context::tpidrurw() const +{ + return 0; +} + +PUBLIC inline +Mword +Context::tpidruro() const +{ + return 0; +} diff --git a/kernel/fiasco/src/kern/arm/cpu-arm.cpp b/kernel/fiasco/src/kern/arm/cpu-arm.cpp index 2cb659bc..dddedde6 100644 --- a/kernel/fiasco/src/kern/arm/cpu-arm.cpp +++ b/kernel/fiasco/src/kern/arm/cpu-arm.cpp @@ -158,6 +158,38 @@ public: }; }; +INTERFACE [arm && (mpcore || armca9)]: + +class Scu +{ +public: + enum + { + Control = Mem_layout::Mp_scu_map_base + 0x0, + Config = Mem_layout::Mp_scu_map_base + 0x4, + Power_status = Mem_layout::Mp_scu_map_base + 0x8, + Inv = Mem_layout::Mp_scu_map_base + 0xc, + + Control_ic_standby = 1 << 6, + Control_scu_standby = 1 << 5, + Control_force_port0 = 1 << 4, + Control_spec_linefill = 1 << 3, + Control_ram_parity = 1 << 2, + Control_addr_filtering = 1 << 1, + Control_enable = 1 << 0, + }; + + static void reset() { Io::write(0xffffffff, Inv); } + + static void enable(Mword bits = 0) + { + Unsigned32 ctrl = Io::read(Control); + if (!(ctrl & Control_enable)) + Io::write(ctrl | bits | Control_enable, Control); + } +}; + + INTERFACE [arm]: EXTENSION class Cpu @@ -169,6 +201,24 @@ public: }; }; +//--------------------------------------------------------------------------- +INTERFACE [arm && !bsp_cpu]: + +EXTENSION class Cpu +{ +private: + void bsp_init(bool) {} +}; + +//--------------------------------------------------------------------------- +INTERFACE [arm && (mpcore || armca9) && !bsp_cpu]: + +EXTENSION class Scu +{ +public: + enum { Bsp_enable_bits = 0 }; +}; + //------------------------------------------------------------------------- IMPLEMENTATION [arm]: @@ -183,22 +233,18 @@ Cpu::midr() IMPLEMENTATION [arm && armv6]: // ----------------------------------------- -PUBLIC static inline void +PUBLIC static inline NEEDS[Cpu::set_actrl] +void Cpu::enable_smp() { - asm volatile ("mrc p15, 0, %0, c1, c0, 1 \n" - "orr %0, %1 \n" - "mcr p15, 0, %0, c1, c0, 1 \n" - : : "r" (0), "i" (0x20)); + set_actrl(0x20); } -PUBLIC static inline void +PUBLIC static inline NEEDS[Cpu::clear_actrl] +void Cpu::disable_smp() { - asm volatile ("mrc p15, 0, %0, c1, c0, 1 \n" - "bic %0, %1 \n" - "mcr p15, 0, %0, c1, c0, 1 \n" - : : "r" (0), "i" (0x20)); + clear_actrl(0x20); } IMPLEMENTATION [arm && armv7]: //------------------------------------------ @@ -224,17 +270,14 @@ Cpu::enable_smp() asm volatile ("mcr p15, 0, %0, c1, c0, 1" : : "r" (actrl | 0x41)); } -PUBLIC static inline +PUBLIC static inline NEEDS[Cpu::clear_actrl] void Cpu::disable_smp() { if (!is_smp_capable()) return; - asm volatile ("mrc p15, 0, %0, c1, c0, 1 \n" - "bic %0, %1 \n" - "mcr p15, 0, %0, c1, c0, 1 \n" - : : "r" (0), "i" (0x40)); + clear_actrl(0x41); } //--------------------------------------------------------------------------- @@ -243,15 +286,8 @@ IMPLEMENTATION [arm && (mpcore || armca9)]: PRIVATE static inline void Cpu::early_init_platform() { - enum { - Scu_control = Mem_layout::Mp_scu_map_base + 0x0, - Scu_config = Mem_layout::Mp_scu_map_base + 0x4, - Scu_power_status = Mem_layout::Mp_scu_map_base + 0x8, - Scu_inv = Mem_layout::Mp_scu_map_base + 0xc, - }; - - Io::write(0xffffffff, Scu_inv); - Io::write(Io::read(Scu_control) | 1, Scu_control); + Scu::reset(); + Scu::enable(Scu::Bsp_enable_bits); Io::write(Io::read(Mem_layout::Gic_cpu_map_base + 0) | 1, Mem_layout::Gic_cpu_map_base + 0); @@ -361,17 +397,17 @@ void Cpu::init_mmu() { extern char ivt_start; // map the interrupt vector table to 0xffff0000 - Pte pte = Kmem_space::kdir()->walk((void*)Kmem_space::Ivt_base, 4096, - true, Kmem_alloc::q_allocator(Ram_quota::root), Kmem_space::kdir()); + Pte pte = Kmem_space::kdir()->walk((void*)Kmem_space::Ivt_base, 4096, true, + Kmem_alloc::q_allocator(Ram_quota::root), + Kmem_space::kdir()); pte.set((unsigned long)&ivt_start, 4096, - Mem_page_attr(Page::KERN_RW | Page::CACHEABLE), - true); + Mem_page_attr(Page::KERN_RW | Page::CACHEABLE), true); Mem_unit::tlb_flush(); } -IMPLEMENT inline +PUBLIC inline unsigned Cpu::phys_id() const { return _phys_id; } @@ -391,6 +427,7 @@ Cpu::init(bool is_boot_cpu) init_tz(); id_init(); init_errata_workarounds(); + bsp_init(is_boot_cpu); print_infos(); } @@ -402,7 +439,7 @@ Cpu::enable_dcache() asm volatile("mrc p15, 0, %0, c1, c0, 0 \n" "orr %0, %1 \n" "mcr p15, 0, %0, c1, c0, 0 \n" - : : "r" (0), "i" (1 << 2)); + : : "r" (0), "i" (Cp15_c1_cache)); } PUBLIC static inline @@ -412,7 +449,7 @@ Cpu::disable_dcache() asm volatile("mrc p15, 0, %0, c1, c0, 0 \n" "bic %0, %1 \n" "mcr p15, 0, %0, c1, c0, 0 \n" - : : "r" (0), "i" (1 << 2)); + : : "r" (0), "i" (Cp15_c1_cache)); } //--------------------------------------------------------------------------- @@ -424,9 +461,6 @@ Cpu::id_init() { } -PRIVATE static inline -void Cpu::init_errata_workarounds() {} - //--------------------------------------------------------------------------- IMPLEMENTATION [arm && armv6plus]: @@ -441,6 +475,40 @@ Cpu::set_actrl(Mword bit_mask) : "=r"(t) : "r" (bit_mask)); } +PRIVATE static inline +void +Cpu::clear_actrl(Mword bit_mask) +{ + Mword t; + asm volatile("mrc p15, 0, %0, c1, c0, 1 \n\t" + "bic %0, %1 \n\t" + "mcr p15, 0, %0, c1, c0, 1 \n\t" + : "=r"(t) : "r" (bit_mask)); +} + +IMPLEMENT +void +Cpu::id_init() +{ + __asm__("mrc p15, 0, %0, c0, c1, 0": "=r" (_cpu_id._pfr[0])); + __asm__("mrc p15, 0, %0, c0, c1, 1": "=r" (_cpu_id._pfr[1])); + __asm__("mrc p15, 0, %0, c0, c1, 2": "=r" (_cpu_id._dfr0)); + __asm__("mrc p15, 0, %0, c0, c1, 3": "=r" (_cpu_id._afr0)); + __asm__("mrc p15, 0, %0, c0, c1, 4": "=r" (_cpu_id._mmfr[0])); + __asm__("mrc p15, 0, %0, c0, c1, 5": "=r" (_cpu_id._mmfr[1])); + __asm__("mrc p15, 0, %0, c0, c1, 6": "=r" (_cpu_id._mmfr[2])); + __asm__("mrc p15, 0, %0, c0, c1, 7": "=r" (_cpu_id._mmfr[3])); +} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [!arm_cpu_errata || !armv6plus]: + +PRIVATE static inline +void Cpu::init_errata_workarounds() {} + +//--------------------------------------------------------------------------- +IMPLEMENTATION [arm_cpu_errata && armv6plus]: + PRIVATE static inline void Cpu::set_c15_c0_1(Mword bits_mask) @@ -505,20 +573,6 @@ Cpu::init_errata_workarounds() } } -IMPLEMENT -void -Cpu::id_init() -{ - __asm__("mrc p15, 0, %0, c0, c1, 0": "=r" (_cpu_id._pfr[0])); - __asm__("mrc p15, 0, %0, c0, c1, 1": "=r" (_cpu_id._pfr[1])); - __asm__("mrc p15, 0, %0, c0, c1, 2": "=r" (_cpu_id._dfr0)); - __asm__("mrc p15, 0, %0, c0, c1, 3": "=r" (_cpu_id._afr0)); - __asm__("mrc p15, 0, %0, c0, c1, 4": "=r" (_cpu_id._mmfr[0])); - __asm__("mrc p15, 0, %0, c0, c1, 5": "=r" (_cpu_id._mmfr[1])); - __asm__("mrc p15, 0, %0, c0, c1, 6": "=r" (_cpu_id._mmfr[2])); - __asm__("mrc p15, 0, %0, c0, c1, 7": "=r" (_cpu_id._mmfr[3])); -} - //--------------------------------------------------------------------------- IMPLEMENTATION [arm && !tz]: diff --git a/kernel/fiasco/src/kern/arm/fpu-arm.cpp b/kernel/fiasco/src/kern/arm/fpu-arm.cpp index 60084830..70ffc63b 100644 --- a/kernel/fiasco/src/kern/arm/fpu-arm.cpp +++ b/kernel/fiasco/src/kern/arm/fpu-arm.cpp @@ -58,6 +58,28 @@ void Fpu::save_user_exception_state(Trap_state *, Exception_state_user *) {} +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && fpu && !armv6plus]: + +PRIVATE static inline +void +Fpu::copro_enable() +{} + +// ------------------------------------------------------------------------ +IMPLEMENTATION [arm && fpu && armv6plus]: + +PRIVATE static inline +void +Fpu::copro_enable() +{ + asm volatile("mrc p15, 0, %0, c1, c0, 2\n" + "orr %0, %0, %1 \n" + "mcr p15, 0, %0, c1, c0, 2\n" + : : "r" (0), "I" (0x00f00000)); + Mem::dsb(); +} + // ------------------------------------------------------------------------ IMPLEMENTATION [arm && fpu]: @@ -163,11 +185,11 @@ Fpu::is_emu_insn(Mword opcode) PUBLIC static inline bool -Fpu::emulate_insns(Mword opcode, Trap_state *ts, unsigned cpu) +Fpu::emulate_insns(Mword opcode, Trap_state *ts) { unsigned reg = (opcode >> 16) & 0xf; unsigned rt = (opcode >> 12) & 0xf; - Mword fpsid = Fpu::fpu(cpu).fpsid(); + Mword fpsid = Fpu::fpu.current().fpsid(); switch (reg) { case 0: // FPSID @@ -199,12 +221,11 @@ IMPLEMENT void Fpu::init(unsigned cpu) { - asm volatile(" mcr p15, 0, %0, c1, c0, 2 \n" : : "r"(0x00f00000)); - Mem::dsb(); + copro_enable(); Mword s = fpsid_read(); - _fpu.cpu(cpu)._fpsid = s; + fpu.cpu(cpu)._fpsid = s; printf("FPU%d: Arch: %s(%lx), Part: %s(%lx), r: %lx, v: %lx, i: %lx, t: %s, p: %s\n", cpu, fpsid_arch_version(s) == 1 @@ -221,7 +242,7 @@ Fpu::init(unsigned cpu) disable(); - set_owner(cpu, 0); + fpu.cpu(cpu).set_owner(0); } IMPLEMENT inline NEEDS ["fpu_state.h", "mem.h", "static_assert.h", ] @@ -251,7 +272,7 @@ Fpu::save_state(Fpu_state *s) IMPLEMENT void -Fpu::restore_state (Fpu_state *s) +Fpu::restore_state(Fpu_state *s) { assert (s->state_buffer()); Fpu_regs *fpu_regs = reinterpret_cast(s->state_buffer()); diff --git a/kernel/fiasco/src/kern/arm/gic.cpp b/kernel/fiasco/src/kern/arm/gic.cpp index da65e415..8b5f5f5c 100644 --- a/kernel/fiasco/src/kern/arm/gic.cpp +++ b/kernel/fiasco/src/kern/arm/gic.cpp @@ -18,6 +18,7 @@ public: DIST_IRQ_SEC = 0x080, DIST_ENABLE_SET = 0x100, DIST_ENABLE_CLEAR = 0x180, + DIST_CLR_PENDING = 0x280, DIST_PRI = 0x400, DIST_TARGET = 0x800, DIST_CONFIG = 0xc00, @@ -108,15 +109,20 @@ Gic::init_ap() } PUBLIC -Gic::Gic(Address cpu_base, Address dist_base, int nr_irqs_override = -1) - : _cpu_base(cpu_base), _dist_base(dist_base) +unsigned +Gic::init(bool primary_gic, int nr_irqs_override = -1) { + if (!primary_gic) + { + init_ap(); + return 0; + } + Io::write(0, _dist_base + DIST_CTRL); unsigned num = hw_nr_irqs(); if (nr_irqs_override != -1) num = nr_irqs_override; - printf("Number of IRQs available at this GIC: %d\n", num); if (!Config_mxc_tzic) { @@ -155,11 +161,33 @@ Gic::Gic(Address cpu_base, Address dist_base, int nr_irqs_override = -1) Io::write(0xf0, _cpu_base + CPU_PRIMASK); } + return num; +} + +PUBLIC +Gic::Gic(Address cpu_base, Address dist_base, int nr_irqs_override = -1) + : _cpu_base(cpu_base), _dist_base(dist_base) +{ + unsigned num = init(true, nr_irqs_override); + + printf("Number of IRQs available at this GIC: %d\n", num); + Irq_chip_gen::init(num); //enable_tz_support(); } +/** + * \brief Create a GIC device that is a physical alias for the + * master GIC. + */ +PUBLIC inline +Gic::Gic(Address cpu_base, Address dist_base, Gic *master_mapping) + : _cpu_base(cpu_base), _dist_base(dist_base) +{ + Irq_chip_gen::init(master_mapping->nr_irqs()); +} + PUBLIC inline NEEDS["io.h"] void Gic::disable_locked( unsigned irq ) { Io::write(1 << (irq % 32), _dist_base + DIST_ENABLE_CLEAR + (irq / 32) * 4); } diff --git a/kernel/fiasco/src/kern/arm/ivt.S b/kernel/fiasco/src/kern/arm/ivt.S index 9bedb922..b3a7d718 100644 --- a/kernel/fiasco/src/kern/arm/ivt.S +++ b/kernel/fiasco/src/kern/arm/ivt.S @@ -120,6 +120,9 @@ #endif .endm +.macro make_tpidruro_space base + sub \base, #4 +.endm /*********************************************************************** * Enter the kernel slowtrap handler @@ -136,6 +139,7 @@ .macro enter_slowtrap errorcode stmdb sp!, {r0 - r12} + make_tpidruro_space sp enter_slowtrap_w_stack \errorcode .endm @@ -162,18 +166,10 @@ /************************************************************************* - * * Generate stack for exception entries - * - Adjust return address - * - Store return address at [sp + 8] - * - Store spsr at [sp + 4] - * - sp := sp - 8 - * - Store user sp at [sp] - * - Store user lr at [sp + 4] */ .macro exceptionframe sub sp, sp, #8 -@ stmia sp, {sp,lr}^ @ now done lazy .endm @@ -205,7 +201,6 @@ add lr, sp, #RF(PC, -8) stmia lr, {lr}^ sub sp, sp, #8 -@ stmia sp, {sp}^ @ now done lazy .endm .macro enter_sys_call no_sys_call @@ -500,6 +495,7 @@ slowtrap_from_pagefault: msr cpsr_c, #0xd3 // disable IRQs ldmia sp!, {r0 - r3} stmdb sp!, {r0 - r11} + make_tpidruro_space sp stmdb sp!, {r12, lr} mov r0, sp adr lr, exception_return @@ -509,7 +505,7 @@ slowtrap_from_pagefault: __return_from_exception: exception_return: msr cpsr_c, #0xd3 // disable IRQs - add sp, sp, #8 + add sp, sp, #12 // pfa, err & tpidruro ldmia sp!, {r0 - r12} return_from_exception @@ -621,13 +617,15 @@ leave_by_trigger_exception: sub sp, sp, #RF_SIZE @ restore old return frame stmdb sp!, {r0 - r12} + make_tpidruro_space sp + /* restore original IP */ CONTEXT_OF r1, sp ldr r0, [r1, #(OFS__THREAD__EXCEPTION_IP)] - str r0, [sp, #RF(PC, 13*4)] + str r0, [sp, #RF(PC, 14*4)] ldr r0, [r1, #(OFS__THREAD__EXCEPTION_PSR)] - str r0, [sp, #RF(PSR, 13*4)] + str r0, [sp, #RF(PSR, 14*4)] mov r0, #~0 str r0, [r1, #(OFS__THREAD__EXCEPTION_IP)] @@ -639,6 +637,7 @@ leave_by_trigger_exception: leave_by_vcpu_upcall: sub sp, sp, #RF_SIZE @ restore old return frame + /* save r0, r1, r2 for scratch registers */ stmdb sp!, {r0 - r2} /* restore original IP */ @@ -648,6 +647,9 @@ leave_by_vcpu_upcall: ldr r2, [r1, #(OFS__THREAD__USER_VCPU)] add r2, r2, #(VAL__SIZEOF_TRAP_STATE - RF_SIZE) + /* r1 = current() */ + /* r2 = &vcpu_state->ts.r[13] */ + ldr r0, [r1, #(OFS__THREAD__EXCEPTION_IP)] str r0, [r2, #RF(PC, 0)] @@ -667,6 +669,7 @@ leave_by_vcpu_upcall: stmdb r2!, {r3-r12} + /* Restore scratch registers saved previously */ ldr r0, [sp, #8] str r0, [r2, #-4] @@ -678,13 +681,17 @@ leave_by_vcpu_upcall: add sp, sp, #(3*4) - add r0, r2, #(-8 + OFS__VCPU_STATE__ENTRY_SP) + /* r2 = &vcpu_state->ts.r[0] */ + /* r2 - 12 -> pfa, err & tpidruro -> &vcpu_state->ts */ + add r0, r2, #(-12 + OFS__VCPU_STATE__ENTRY_SP) ldm r0, {sp}^ - ldr r0, [r2, #(-8 + OFS__VCPU_STATE__ENTRY_IP)] + ldr r0, [r2, #(-12 + OFS__VCPU_STATE__ENTRY_IP)] str r0, [sp, #RF(PC, 0)] - add r0, r2, #(-8) + + /* r0 needs to be vcpu_state */ + add r0, r2, #(-12) b __iret @@ -708,6 +715,7 @@ fiq_label: .string "FIQ entry" str lr, [sp, #RF(PSR, 0)] stmdb sp!, {r0 - r12} + make_tpidruro_space sp mov r0, #-1 @ pfa mov r1, #0x00e00000 @ err orr r1, #\type @ + type @@ -718,7 +726,7 @@ fiq_label: .string "FIQ entry" ldr pc, 3f 1: - add sp, sp, #8 @ pfa and err + add sp, sp, #12 @ pfa, err and tpidruro ldmia sp!, {r0 - r12} ldr lr, [sp, #RF(PSR, 0)] msr cpsr, lr @@ -1178,9 +1186,11 @@ go_nonsecure: .global vcpu_resume vcpu_resume: add sp, r1, #RF_SIZE - add lr, r0, #8 + add lr, r0, #12 @ pfa, err + tpidruro +#if !defined(CONFIG_ARM_V6PLUS) ldr r1, [lr, #RF(PSR, 13*4)] @ Unstack SPSR msr spsr, r1 @ Load SPSR from kernel_lr +#endif ldmia lr!, {r0 - r12} ldmia lr, {sp,lr}^ @ restore user sp and lr (now lazy) #if defined(CONFIG_ARM_V6PLUS) diff --git a/kernel/fiasco/src/kern/arm/kern_lib_page.cpp b/kernel/fiasco/src/kern/arm/kern_lib_page.cpp index 72738b36..e12ba764 100644 --- a/kernel/fiasco/src/kern/arm/kern_lib_page.cpp +++ b/kernel/fiasco/src/kern/arm/kern_lib_page.cpp @@ -59,6 +59,7 @@ asm ( // r0: memory reference // r1: cmp value // r2: new value + // r3: tmp ".p2align(8) \n" " ldr r3, [r0] \n" " cmp r3, r1 \n" @@ -74,6 +75,7 @@ asm ( // in-r0: memory reference // in-r1: new value // out-r0: old value + // tmp-r2 ".p2align(8) \n" " ldr r2, [r0] \n" " nop \n" diff --git a/kernel/fiasco/src/kern/arm/kernel_thread-arm.cpp b/kernel/fiasco/src/kern/arm/kernel_thread-arm.cpp index 10a00413..7c4184ac 100644 --- a/kernel/fiasco/src/kern/arm/kernel_thread-arm.cpp +++ b/kernel/fiasco/src/kern/arm/kernel_thread-arm.cpp @@ -30,9 +30,9 @@ Kernel_thread::boot_app_cpus() //-------------------------------------------------------------------------- IMPLEMENTATION [mp]: -#include "boot_mp.h" #include "io.h" #include "pagetable.h" +#include "platform_control.h" #include "outer_cache.h" #include @@ -40,8 +40,6 @@ IMPLEMENTATION [mp]: static void Kernel_thread::boot_app_cpus() { - Boot_mp bmp; - extern char _tramp_mp_entry[]; extern volatile Mword _tramp_mp_startup_cp15_c1; extern volatile Mword _tramp_mp_startup_pdbr; @@ -65,21 +63,7 @@ Kernel_thread::boot_app_cpus() Outer_cache::clean(Mem_space::kernel_space()->virt_to_phys((Address)&_tramp_mp_startup_pdbr)); Outer_cache::clean(Mem_space::kernel_space()->virt_to_phys((Address)&_tramp_mp_start_dcr)); - bmp.start_ap_cpus(Mem_space::kernel_space()->virt_to_phys((Address)_tramp_mp_entry)); - - printf("Waiting for %d CPUs to come up\n", num_ap_cpus); - while (1) - { - Mem::dmb(); - if (num_ap_cpus == Config::num_ap_cpus) - break; - for (unsigned i = 0; i < 1000; ++i) - asm volatile("nop"); - } - - bmp.cleanup(); - - printf("Done waiting CPUs\n"); + Platform_control::boot_ap_cpus(Mem_space::kernel_space()->virt_to_phys((Address)_tramp_mp_entry)); } //-------------------------------------------------------------------------- diff --git a/kernel/fiasco/src/kern/arm/logdefs.h b/kernel/fiasco/src/kern/arm/logdefs.h deleted file mode 100644 index 7e46d2bc..00000000 --- a/kernel/fiasco/src/kern/arm/logdefs.h +++ /dev/null @@ -1,238 +0,0 @@ -#ifndef LOGDEFS_H -#define LOGDEFS_H - -// ### How to create a tracebuffer entry ### -// -// If you only need a temporary debugging aid then you can use one of -// the standard kernel logging events: -// -// LOG_MSG(Context *context, const char *msg) -// - context is something like context_of(this) or current_context() -// or 0 if there is no context available -// - msg should be displayed in the tracebuffer view -// -// LOG_MSG_3VAL(Context *context, const char *msg, -// Mword val1, Mword val2, Mword val3) -// - context and msg can be used the same way LOG_MSG does -// - val1, val2, and val3 are values that will be displayed in -// the tracebuffer view as hexadecimal values -// -// If you want to create a permanent log event xyz, you have to follow -// these instructions: -// - create enum Log_event_xyz (see jdb_ktrace.cpp) -// - create class Tb_entry_xyz derived from Tb_entry (see tb_entry.cpp) -// with an appropriate ::set method and with accessor methods -// - create function formatter_xyz (see tb_entry_output.cpp) and don't -// forget to register it (add an appropriate line to init_formatters) -// - create macro LOG_XYZ (see the following example) -// #define LOG_XYZ -// BEGIN_LOG_EVENT(log_xyz) -// Lock_guard guard (&cpu_lock); -// Tb_entry_xyz *tb = -// static_cast(Jdb_tbuf::new_entry()); -// tb->set (this, ) -// Jdb_tbuf::commit_entry(); -// END_LOG_EVENT -// (grabbing the cpu_lock isn't necessary if it is still grabbed) -// - create an empty macro declaration for CONFIG_JDB_LOGGING=n -// - insert the macro call into the code -// - WARNING: permanent log events should _not_ be placed into an inline -// function! -// - add -// DECLARE_PATCH (lp, log_xyz); -// static Log_event le(, -// Log_event_xyz, 1, &lp); -// and create an entry le for Jdb_tbuf_events::log_events[] -// (see jdb_tbuf_events.cpp) - -#include "globalconfig.h" - -#if defined(CONFIG_JDB) - -#include "globals.h" -#include "jdb_tbuf.h" -#include "cpu_lock.h" -#include "lock_guard.h" -#include "processor.h" - -#define LOG_CONTEXT_SWITCH \ - BEGIN_LOG_EVENT("Context switch", "csw", 0) \ - Tb_entry_ctx_sw *tb = \ - static_cast(Jdb_tbuf::new_entry()); \ - tb->set(this, space(), regs()->ip(), t, t_orig, \ - t_orig->lock_cnt(), current_sched(), \ - current_sched() ? current_sched()->prio() : 0, \ - (Mword)__builtin_return_address(0)); \ - Jdb_tbuf::commit_entry(); \ - END_LOG_EVENT - -#define LOG_TRAP \ - BEGIN_LOG_EVENT("Exceptions", "exc", 0) \ - Tb_entry_trap *tb = \ - static_cast(Jdb_tbuf::new_entry()); \ - tb->set(current_thread(), ts); \ - Jdb_tbuf::commit_entry(); \ - END_LOG_EVENT - -#define LOG_TRAP_N(n) \ - BEGIN_LOG_EVENT("Exception n", "exc", 0) \ - Tb_entry_trap *tb = \ - static_cast(Jdb_tbuf::new_entry()); \ - Mword ip = (Mword)(__builtin_return_address(0)); \ - tb->set(current(), ip, n); \ - Jdb_tbuf::commit_entry(); \ - END_LOG_EVENT - -#define LOG_PF_RES_USER \ - BEGIN_LOG_EVENT("Page-fault results", "pfr", 0) \ - Tb_entry_pf_res *tb = \ - static_cast(Jdb_tbuf::new_entry()); \ - tb->set(this, regs()->ip(), pfa, err, ret); \ - Jdb_tbuf::commit_entry(); \ - END_LOG_EVENT - -#define LOG_SCHED_SAVE(cs) \ - BEGIN_LOG_EVENT("Scheduling context save", "sch", 0) \ - Tb_entry_sched *tb = \ - static_cast(Jdb_tbuf::new_entry()); \ - tb->set (current(), 0, 0, \ - cs->context(), \ - 0, \ - cs->prio(), \ - cs->left(), \ - cs->quantum()); \ - Jdb_tbuf::commit_entry(); \ - END_LOG_EVENT - -#define LOG_SCHED_LOAD(cs) \ - BEGIN_LOG_EVENT("Scheduling context load", "sch", 0) \ - Tb_entry_sched *tb = \ - static_cast(Jdb_tbuf::new_entry()); \ - tb->set (current(), 0, 1, \ - cs->context(), \ - 0, \ - cs->prio(), \ - cs->left(), \ - cs->quantum()); \ - Jdb_tbuf::commit_entry(); \ - END_LOG_EVENT - -#define LOG_SCHED_INVALIDATE \ - BEGIN_LOG_EVENT("Schduling context invalidate", "sch", 0) \ - Tb_entry_sched *tb = \ - static_cast(Jdb_tbuf::new_entry()); \ - tb->set (current(), current()->regs()->ip(), 2, \ - current_sched()->context(), \ - current_sched()->id(), \ - current_sched()->prio(), \ - timeslice_timeout.cpu(cpu())->get_timeout(Kip::k()->clock), \ - current_sched()->quantum()); \ - Jdb_tbuf::commit_entry(); \ - END_LOG_EVENT - -#define LOG_SEND_PREEMPTION \ - BEGIN_LOG_EVENT("Preemption events", "pre", 0) \ - Lock_guard guard (&cpu_lock); \ - Tb_entry_preemption *tb = \ - static_cast(Jdb_tbuf::new_entry()); \ - tb->set (context_of(this), _receiver.raw(), current()->regs()->ip()); \ - Jdb_tbuf::commit_entry(); \ - END_LOG_EVENT - -/* - * Kernel instrumentation macro used by fm3. Do not remove! - */ -#define LOG_MSG(context, text) \ - do { \ - /* The cpu_lock is needed since virq::hit() depends on it */ \ - Lock_guard guard (&cpu_lock); \ - Tb_entry_ke *tb = static_cast(Jdb_tbuf::new_entry()); \ - tb->set_const(context, Proc::program_counter(), text); \ - Jdb_tbuf::commit_entry(); \ - } while (0) - -/* - * Kernel instrumentation macro used by fm3. Do not remove! - */ -#define LOG_MSG_3VAL(context, text, v1, v2, v3) \ - do { \ - /* The cpu_lock is needed since virq::hit() depends on it */ \ - Lock_guard guard (&cpu_lock); \ - Tb_entry_ke_reg *tb = \ - static_cast(Jdb_tbuf::new_entry()); \ - tb->set_const(context, Proc::program_counter(), text, v1, v2, v3); \ - Jdb_tbuf::commit_entry(); \ - } while (0) - - -#define LOG_TRACE(name, sc, ctx, fmt, code...) \ - BEGIN_LOG_EVENT(name, sc, fmt) \ - Tb_entry *tbe = Jdb_tbuf::new_entry(); \ - tbe->set_global(__do_log__, ctx, Proc::program_counter()); \ - code ; \ - Jdb_tbuf::commit_entry(); \ - END_LOG_EVENT - - -#else - -#define LOG_TRACE(name, sc, ctx, fmt, code...) do { } while (0) -#define LOG_CONTEXT_SWITCH do { } while (0) -#define LOG_TRAP do { } while (0) -#define LOG_TRAP_N(n) do { } while (0) -#define LOG_PF_RES_USER do { } while (0) -#define LOG_SCHED do { } while (0) -#define LOG_SCHED_SAVE(n) do { } while (0) -#define LOG_SCHED_LOAD(n) do { } while (0) -#define LOG_SCHED_INVALIDATE do { } while (0) -#define LOG_SEND_PREEMPTION do { } while (0) - -#endif // CONFIG_JDB - -#if defined(CONFIG_JDB) && defined(CONFIG_JDB_ACCOUNTING) - -#error ARM does not have CONFIG_JDB_ACCOUNTING - -#define CNT_CONTEXT_SWITCH \ - Jdb_tbuf::status()->kerncnts[Kern_cnt_context_switch]++; -#define CNT_ADDR_SPACE_SWITCH \ - Jdb_tbuf::status()->kerncnts[Kern_cnt_addr_space_switch]++; -#define CNT_SHORTCUT_FAILED \ - Jdb_tbuf::status()->kerncnts[Kern_cnt_shortcut_failed]++; -#define CNT_SHORTCUT_SUCCESS \ - Jdb_tbuf::status()->kerncnts[Kern_cnt_shortcut_success]++; -#define CNT_IRQ \ - Jdb_tbuf::status()->kerncnts[Kern_cnt_irq]++; -#define CNT_IPC_LONG \ - Jdb_tbuf::status()->kerncnts[Kern_cnt_ipc_long]++; -#define CNT_PAGE_FAULT \ - Jdb_tbuf::status()->kerncnts[Kern_cnt_page_fault]++; -#define CNT_IO_FAULT \ - Jdb_tbuf::status()->kerncnts[Kern_cnt_io_fault]++; -#define CNT_TASK_CREATE \ - Jdb_tbuf::status()->kerncnts[Kern_cnt_task_create]++; -#define CNT_SCHEDULE \ - Jdb_tbuf::status()->kerncnts[Kern_cnt_schedule]++; -#define CNT_IOBMAP_TLB_FLUSH \ - Jdb_tbuf::status()->kerncnts[Kern_cnt_iobmap_tlb_flush]++; -#define CNT_EXC_IPC \ - Jdb_tbuf::status()->kerncnts[Kern_cnt_exc_ipc]++; - -#else - -#define CNT_CONTEXT_SWITCH do { } while (0) -#define CNT_ADDR_SPACE_SWITCH do { } while (0) -#define CNT_SHORTCUT_FAILED do { } while (0) -#define CNT_SHORTCUT_SUCCESS do { } while (0) -#define CNT_IRQ do { } while (0) -#define CNT_IPC_LONG do { } while (0) -#define CNT_PAGE_FAULT do { } while (0) -#define CNT_IO_FAULT do { } while (0) -#define CNT_TASK_CREATE do { } while (0) -#define CNT_SCHEDULE do { } while (0) -#define CNT_IOBMAP_TLB_FLUSH do { } while (0) -#define CNT_EXC_IPC do { } while (0) - -#endif // CONFIG_JDB && CONFIG_JDB_ACCOUNTING - -#endif diff --git a/kernel/fiasco/src/kern/arm/main.cpp b/kernel/fiasco/src/kern/arm/main.cpp index aead15ad..6b191604 100644 --- a/kernel/fiasco/src/kern/arm/main.cpp +++ b/kernel/fiasco/src/kern/arm/main.cpp @@ -109,38 +109,53 @@ IMPLEMENTATION[arm && mp]: #include "per_cpu_data_alloc.h" #include "perf_cnt.h" #include "pic.h" +#include "platform_control.h" #include "spin_lock.h" #include "timer.h" #include "utcb_init.h" +int boot_ap_cpu() __asm__("BOOT_AP_CPU"); -int boot_ap_cpu(unsigned cpu) __asm__("BOOT_AP_CPU"); - -int boot_ap_cpu(unsigned _cpu) +int boot_ap_cpu() { - if (!Per_cpu_data_alloc::alloc(_cpu)) + static unsigned last_cpu; // keep track of the last cpu ever appeared + + unsigned _cpu = Cpu::cpus.find_cpu(Cpu::By_phys_id(Proc::cpu_id())); + bool cpu_is_new = false; + if (_cpu == ~0U) + { + _cpu = ++last_cpu; // 0 is the boot cpu, so pre increment + cpu_is_new = true; + } + + assert (_cpu != 0); + + if (cpu_is_new && !Per_cpu_data_alloc::alloc(_cpu)) { extern Spin_lock _tramp_mp_spinlock; printf("CPU allocation failed for CPU%u, disabling CPU.\n", _cpu); _tramp_mp_spinlock.clear(); + + // FIXME: use a Platform_control API to stop the CPU while (1) Proc::halt(); } + Per_cpu_data::run_ctors(_cpu); Cpu &cpu = Cpu::cpus.cpu(_cpu); cpu.init(); - Pic::init_ap(); + Pic::init_ap(_cpu); + Thread::init_per_cpu(_cpu); + Platform_control::init(_cpu); Ipi::init(_cpu); Timer::init(_cpu); Perf_cnt::init_ap(); // create kernel thread - App_cpu_thread *kernel = new (Ram_quota::root) App_cpu_thread(); - set_cpu_of(kernel, _cpu); - check(kernel->bind(Kernel_task::kernel_task(), User::Ptr(0))); + Kernel_thread *kernel = App_cpu_thread::may_be_create(_cpu, cpu_is_new); - // switch to stack of kernel thread and bootstrap the kernel + // switch to stack of kernel thread and continue thread init asm volatile (" mov sp,%0 \n" // switch stack " mov r0,%1 \n" // push "this" pointer @@ -149,4 +164,3 @@ int boot_ap_cpu(unsigned _cpu) : "r" (kernel->init_stack()), "r" (kernel)); return 0; } - diff --git a/kernel/fiasco/src/kern/arm/mem_layout-arm.cpp b/kernel/fiasco/src/kern/arm/mem_layout-arm.cpp index 0637460c..1da21916 100644 --- a/kernel/fiasco/src/kern/arm/mem_layout-arm.cpp +++ b/kernel/fiasco/src/kern/arm/mem_layout-arm.cpp @@ -3,7 +3,7 @@ INTERFACE [arm && !kern_start_0xd]: EXTENSION class Mem_layout { public: - enum Virt_layout_umax { + enum Virt_layout_umax : Address { User_max = 0xc0000000, }; }; @@ -15,7 +15,7 @@ INTERFACE [arm && kern_start_0xd]: EXTENSION class Mem_layout { public: - enum Virt_layout_umax { + enum Virt_layout_umax : Address { User_max = 0xd0000000, }; }; @@ -29,7 +29,7 @@ INTERFACE [arm]: EXTENSION class Mem_layout { public: - enum Virt_layout { + enum Virt_layout : Address { Utcb_addr = User_max - 0x10000, Service_page = 0xeac00000, Tbuf_status_page = Service_page + 0x5000, @@ -42,7 +42,7 @@ public: Cache_flush_area = 0xef000000, Cache_flush_area_end = 0xef100000, Registers_map_start = 0xef100000, - Registers_map_end = 0xef500000, + Registers_map_end = 0xeff00000, Map_base = 0xf0000000, Map_end = 0xf5000000, Caps_start = 0xf5000000, @@ -55,6 +55,17 @@ public: Syscalls = 0xfffff000, Kernel_max = 0x00000000, + + Devices0_map_base = Registers_map_start + 0x00000000, + Devices1_map_base = Registers_map_start + 0x00100000, + Devices2_map_base = Registers_map_start + 0x00200000, + Devices3_map_base = Registers_map_start + 0x00300000, + Devices4_map_base = Registers_map_start + 0x00400000, + Devices5_map_base = Registers_map_start + 0x00500000, + Devices6_map_base = Registers_map_start + 0x00600000, + Devices7_map_base = Registers_map_start + 0x00700000, + Devices8_map_base = Registers_map_start + 0x00800000, + Devices9_map_base = Registers_map_start + 0x00900000, }; }; diff --git a/kernel/fiasco/src/kern/arm/mem_op.cpp b/kernel/fiasco/src/kern/arm/mem_op.cpp index 2b973147..62df3c2b 100644 --- a/kernel/fiasco/src/kern/arm/mem_op.cpp +++ b/kernel/fiasco/src/kern/arm/mem_op.cpp @@ -228,8 +228,7 @@ Mem_op::outer_cache_op(int op, Address start, Address end) Mem_space::Phys_addr phys_addr; unsigned attrs; - if ( c->mem_space()->v_lookup(v, &phys_addr, - &phys_size, &attrs) + if ( c->mem_space()->v_lookup(v, &phys_addr, &phys_size, &attrs) && (attrs & Mem_space::Page_user_accessible)) { unsigned long sz = Virt_size(phys_size).value(); diff --git a/kernel/fiasco/src/kern/arm/mem_space-arm.cpp b/kernel/fiasco/src/kern/arm/mem_space-arm.cpp index 91668f6a..bb0c8e65 100644 --- a/kernel/fiasco/src/kern/arm/mem_space-arm.cpp +++ b/kernel/fiasco/src/kern/arm/mem_space-arm.cpp @@ -343,13 +343,6 @@ Mem_space::set_attributes(Address virt, unsigned page_attribs) return true; } -PROTECTED -void -Mem_space::destroy() -{ - reset_asid(); -} - /** * \brief Free all memory allocated for this Mem_space. * \pre Runs after the destructor! @@ -357,6 +350,7 @@ Mem_space::destroy() PUBLIC Mem_space::~Mem_space() { + reset_asid(); if (_dir) { _dir->free_page_tables(0, (void*)Mem_layout::User_max, @@ -523,7 +517,7 @@ Mem_space::asid() // FIFO ASID replacement strategy unsigned char new_asid = next_asid(cpu); Mem_space **bad_guy = &_active_asids.cpu(cpu)[new_asid]; - while (Mem_space *victim = access_once(*bad_guy)) + while (Mem_space *victim = access_once(bad_guy)) { // need ASID replacement if (victim == current_mem_space(cpu)) @@ -536,13 +530,19 @@ Mem_space::asid() //LOG_MSG_3VAL(current(), "ASIDr", new_asid, (Mword)*bad_guy, (Mword)this); Mem_unit::tlb_flush(new_asid); - if (victim != reinterpret_cast(~0UL)) - victim->_asid[cpu] = ~0UL; + + // If the victim is valid and we get a 1 written to the ASID array + // then we have to reset the ASID of our victim, else the + // reset_asid function is currently resetting the ASIDs of the + // victim on a different CPU. + if (victim != reinterpret_cast(~0UL) && + mp_cas(bad_guy, victim, reinterpret_cast(1))) + write_now(&victim->_asid[cpu], ~0UL); break; } - *bad_guy = this; _asid[cpu] = new_asid; + write_now(bad_guy, this); } //LOG_MSG_3VAL(current(), "ASID", (Mword)this, _asid[cpu], (Mword)__builtin_return_address(0)); @@ -555,12 +555,16 @@ Mem_space::reset_asid() { for (unsigned i = 0; i < Config::Max_num_cpus; ++i) { - unsigned asid = access_once(_asid[i]); + unsigned asid = access_once(&_asid[i]); if (asid == ~0UL) continue; Mem_space **a = &_active_asids.cpu(i)[asid]; - mp_cas(a, this, reinterpret_cast(~0UL)); + if (!mp_cas(a, this, reinterpret_cast(~0UL))) + // It could be our ASID is in the process of being preempted, + // so wait until this is done. + while (access_once(a) == reinterpret_cast(1)) + ; } } diff --git a/kernel/fiasco/src/kern/arm/mem_unit.cpp b/kernel/fiasco/src/kern/arm/mem_unit.cpp index 36413e61..af076c9a 100644 --- a/kernel/fiasco/src/kern/arm/mem_unit.cpp +++ b/kernel/fiasco/src/kern/arm/mem_unit.cpp @@ -86,9 +86,10 @@ void Mem_unit::dtlb_flush(unsigned long) IMPLEMENTATION [arm && (armv6 || armv7)]: PUBLIC static inline -void Mem_unit::tlb_flush( void* va, unsigned long asid ) +void Mem_unit::tlb_flush(void *va, unsigned long asid) { - if (asid == ~0UL) return; + if (asid == ~0UL) + return; btc_flush(); asm volatile ( "mcr p15, 0, %1, c7, c10, 4 \n" // drain write buffer diff --git a/kernel/fiasco/src/kern/arm/outer_cache-l2cxx0.cpp b/kernel/fiasco/src/kern/arm/outer_cache-l2cxx0.cpp index 41b295a3..15e96d62 100644 --- a/kernel/fiasco/src/kern/arm/outer_cache-l2cxx0.cpp +++ b/kernel/fiasco/src/kern/arm/outer_cache-l2cxx0.cpp @@ -79,7 +79,7 @@ PRIVATE static inline NEEDS ["io.h", "lock_guard.h"] void Outer_cache::write(Address reg, Mword val, bool before = false) { - Lock_guard > guard(&_lock); + auto guard = lock_guard(_lock); if (before) while (Io::read(reg) & 1) ; @@ -142,7 +142,7 @@ Outer_cache::invalidate(Address phys_addr, bool do_sync = true) PUBLIC static void -Outer_cache::init() +Outer_cache::initialize(bool v) { Mword cache_id = Io::read(CACHE_ID); Mword aux = Io::read(AUX_CONTROL); @@ -177,7 +177,15 @@ Outer_cache::init() Io::write(1, CONTROL); } - show_info(ways, cache_id, aux); + if (v) + show_info(ways, cache_id, aux); +} + +PUBLIC static +void +Outer_cache::init() +{ + initialize(true); } STATIC_INITIALIZE_P(Outer_cache, STARTUP_INIT_PRIO); diff --git a/kernel/fiasco/src/kern/arm/startup-arm.cpp b/kernel/fiasco/src/kern/arm/startup-arm.cpp index bfed9f26..56f77258 100644 --- a/kernel/fiasco/src/kern/arm/startup-arm.cpp +++ b/kernel/fiasco/src/kern/arm/startup-arm.cpp @@ -14,8 +14,10 @@ IMPLEMENTATION [arm]: #include "per_cpu_data_alloc.h" #include "perf_cnt.h" #include "pic.h" +#include "platform_control.h" #include "processor.h" #include "static_init.h" +#include "thread.h" #include "timer.h" #include "utcb_init.h" @@ -53,9 +55,11 @@ Startup::stage2() Kernel_task::init(); Mem_space::kernel_space(Kernel_task::kernel_task()); Pic::init(); + Thread::init_per_cpu(0); Cpu::init_mmu(); Cpu::cpus.cpu(0).init(true); + Platform_control::init(0); Fpu::init(0); Ipi::init(0); Timer::init(0); diff --git a/kernel/fiasco/src/kern/arm/tb_entry-arm.cpp b/kernel/fiasco/src/kern/arm/tb_entry-arm.cpp index 4ae64eb4..3edea573 100644 --- a/kernel/fiasco/src/kern/arm/tb_entry-arm.cpp +++ b/kernel/fiasco/src/kern/arm/tb_entry-arm.cpp @@ -1,6 +1,6 @@ INTERFACE [arm]: -EXTENSION class Tb_entry_base +EXTENSION class Tb_entry { public: enum @@ -10,44 +10,26 @@ public: static Mword (*read_cycle_counter)(); }; -/** logged kernel event plus register content. */ -class Tb_entry_ke_reg : public Tb_entry -{ -private: - struct Payload - { - union { - char _msg[16]; ///< debug message - struct { - char _dsc[2]; - char const*_const_msg; - }; - }; - Mword _r0, _r1, _r2; ///< registers - }; -}; - /** logged trap. */ class Tb_entry_trap : public Tb_entry { private: - struct Payload - { - Unsigned32 _error; - Mword _cpsr, _sp; - }; + Unsigned32 _error; + Mword _cpsr, _sp; +public: + unsigned print(int max, char *buf) const; }; // -------------------------------------------------------------------- IMPLEMENTATION [arm]: -PROTECTED static Mword Tb_entry_base::dummy_read_cycle_counter() { return 0; } +PROTECTED static Mword Tb_entry::dummy_read_cycle_counter() { return 0; } -Mword (*Tb_entry_base::read_cycle_counter)() = dummy_read_cycle_counter; +Mword (*Tb_entry::read_cycle_counter)() = dummy_read_cycle_counter; PUBLIC static void -Tb_entry_base::set_cycle_read_func(Mword (*f)()) +Tb_entry::set_cycle_read_func(Mword (*f)()) { read_cycle_counter = f; } PUBLIC inline @@ -55,60 +37,6 @@ void Tb_entry::rdtsc() { _tsc = read_cycle_counter(); } -PUBLIC inline -const char * -Tb_entry_ke_reg::msg() const -{ - return payload()->_dsc[0] == 0 && payload()->_dsc[1] == 1 - ? payload()->_const_msg : payload()->_msg; -} - -PUBLIC inline -Mword -Tb_entry_ke_reg::val1() const -{ return payload()->_r0; } - -PUBLIC inline -Mword -Tb_entry_ke_reg::val2() const -{ return payload()->_r1; } - -PUBLIC inline -Mword -Tb_entry_ke_reg::val3() const -{ return payload()->_r2; } - -PUBLIC inline -void -Tb_entry_ke_reg::set(Context const *ctx, Mword eip, Mword v1, Mword v2, Mword v3) -{ - set_global(Tbuf_ke_reg, ctx, eip); - payload()->_r0 = v1; payload()->_r1 = v2; payload()->_r2 = v3; -} - -PUBLIC inline -void -Tb_entry_ke_reg::set_const(Context const *ctx, Mword eip, const char * const msg, - Mword v1, Mword v2, Mword v3) -{ - set(ctx, eip, v1, v2, v3); - payload()->_dsc[0] = 0; payload()->_dsc[1] = 1; - payload()->_const_msg = msg; -} - -PUBLIC inline -void -Tb_entry_ke_reg::set_buf(unsigned i, char c) -{ - if (i < sizeof(payload()->_msg)-1) - payload()->_msg[i] = c >= ' ' ? c : '.'; -} - -PUBLIC inline -void -Tb_entry_ke_reg::term_buf(unsigned i) -{ payload()->_msg[i < sizeof(payload()->_msg)-1 ? i : sizeof(payload()->_msg)-1] = '\0'; } - // ------------------ PUBLIC inline Unsigned16 @@ -123,12 +51,12 @@ Tb_entry_trap::trapno() const PUBLIC inline Unsigned32 Tb_entry_trap::error() const -{ return payload()->_error; } +{ return _error; } PUBLIC inline Mword Tb_entry_trap::sp() const -{ return payload()->_sp; } +{ return _sp; } PUBLIC inline Mword @@ -142,17 +70,17 @@ Tb_entry_trap::eax() const PUBLIC inline NEEDS ["trap_state.h"] void -Tb_entry_trap::set(Context const *ctx, Trap_state *ts) +Tb_entry_trap::set(Mword ip, Trap_state *ts) { - set_global(Tbuf_trap, ctx, ts->ip()); - payload()->_error = ts->error_code; - payload()->_cpsr = ts->psr; - payload()->_sp = ts->sp(); + _ip = ip; + _error = ts->error_code; + _cpsr = ts->psr; + _sp = ts->sp(); } PUBLIC inline NEEDS ["trap_state.h"] void -Tb_entry_trap::set(Context const *ctx, Mword pc, Mword ) +Tb_entry_trap::set(Mword pc, Mword ) { - set_global(Tbuf_trap, ctx, pc); + _ip = pc; } diff --git a/kernel/fiasco/src/kern/arm/thread-arm.cpp b/kernel/fiasco/src/kern/arm/thread-arm.cpp index f73f2372..8dc4cbf8 100644 --- a/kernel/fiasco/src/kern/arm/thread-arm.cpp +++ b/kernel/fiasco/src/kern/arm/thread-arm.cpp @@ -4,6 +4,8 @@ class Trap_state; EXTENSION class Thread { +public: + static void init_per_cpu(unsigned cpu); private: bool _in_exception; @@ -59,6 +61,8 @@ Thread::fast_return_to_user(Mword ip, Mword sp, Vcpu_state *arg) // fill_user_state() fill_user_state(); + load_tpidruro(); + r->psr &= ~Proc::Status_thumb; { @@ -74,6 +78,12 @@ Thread::fast_return_to_user(Mword ip, Mword sp, Vcpu_state *arg) panic("__builtin_trap()"); } +IMPLEMENT_DEFAULT inline +void +Thread::init_per_cpu(unsigned) +{} + + // // Public services // @@ -244,6 +254,8 @@ extern "C" { void slowtrap_entry(Trap_state *ts) { + if (0) + printf("Trap: pfa=%08lx pc=%08lx err=%08lx psr=%lx\n", ts->pf_address, ts->pc, ts->error_code, ts->psr); Thread *t = current_thread(); LOG_TRAP; @@ -379,7 +391,7 @@ Thread::Thread() r->ip(0); r->psr = Proc::Status_mode_user; - state_add(Thread_dead | Thread_suspended); + state_add_dirty(Thread_dead, false); // ok, we're ready to go! } @@ -459,7 +471,7 @@ Thread::do_trigger_exception(Entry_frame *r, void *ret_handler) } -PRIVATE static inline +PRIVATE static inline NEEDS[Thread::get_ts_tpidruro] bool FIASCO_WARN_RESULT Thread::copy_utcb_to_ts(L4_msg_tag const &tag, Thread *snd, Thread *rcv, unsigned char rights) @@ -471,30 +483,30 @@ Thread::copy_utcb_to_ts(L4_msg_tag const &tag, Thread *snd, Thread *rcv, if (EXPECT_FALSE(rcv->exception_triggered())) { // triggered exception pending - Mem::memcpy_mwords (ts, snd_utcb->values, s > 15 ? 15 : s); - if (EXPECT_TRUE(s > 19)) + Mem::memcpy_mwords (ts, snd_utcb->values, s > 16 ? 16 : s); + if (EXPECT_TRUE(s > 20)) { // sanitize processor mode // XXX: fix race - snd_utcb->values[19] &= ~Proc::Status_mode_mask; // clear mode - snd_utcb->values[19] |= Proc::Status_mode_supervisor - | Proc::Status_interrupts_disabled; + snd_utcb->values[20] &= ~Proc::Status_mode_mask; // clear mode + snd_utcb->values[20] |= Proc::Status_mode_supervisor + | Proc::Status_interrupts_disabled; Continuation::User_return_frame const *s - = reinterpret_cast((char*)&snd_utcb->values[15]); + = reinterpret_cast((char*)&snd_utcb->values[16]); rcv->_exc_cont.set(ts, s); } } else { - Mem::memcpy_mwords (ts, snd_utcb->values, s > 18 ? 18 : s); - if (EXPECT_TRUE(s > 18)) - ts->pc = snd_utcb->values[18]; + Mem::memcpy_mwords (ts, snd_utcb->values, s > 19 ? 19 : s); if (EXPECT_TRUE(s > 19)) + ts->pc = snd_utcb->values[19]; + if (EXPECT_TRUE(s > 20)) { // sanitize processor mode - Mword p = snd_utcb->values[19]; + Mword p = snd_utcb->values[20]; p &= ~(Proc::Status_mode_mask | Proc::Status_interrupts_mask); // clear mode & irqs p |= Proc::Status_mode_user; ts->psr = p; @@ -507,6 +519,8 @@ Thread::copy_utcb_to_ts(L4_msg_tag const &tag, Thread *snd, Thread *rcv, if ((tag.flags() & 0x8000) && (rights & L4_fpage::W)) rcv->utcb().access()->user[2] = snd_utcb->values[25]; + rcv->get_ts_tpidruro(ts); + bool ret = transfer_msg_items(tag, snd, snd_utcb, rcv, rcv->utcb().access(), rights); @@ -515,7 +529,8 @@ Thread::copy_utcb_to_ts(L4_msg_tag const &tag, Thread *snd, Thread *rcv, } -PRIVATE static inline NEEDS[Thread::save_fpu_state_to_utcb] +PRIVATE static inline NEEDS[Thread::save_fpu_state_to_utcb, + Thread::set_ts_tpidruro] bool FIASCO_WARN_RESULT Thread::copy_ts_to_utcb(L4_msg_tag const &, Thread *snd, Thread *rcv, unsigned char rights) @@ -523,20 +538,22 @@ Thread::copy_ts_to_utcb(L4_msg_tag const &, Thread *snd, Thread *rcv, Trap_state *ts = (Trap_state*)snd->_utcb_handler; { - Lock_guard guard (&cpu_lock); + auto guard = lock_guard(cpu_lock); Utcb *rcv_utcb = rcv->utcb().access(); - Mem::memcpy_mwords (rcv_utcb->values, ts, 15); + snd->set_ts_tpidruro(ts); + + Mem::memcpy_mwords(rcv_utcb->values, ts, 16); Continuation::User_return_frame *d - = reinterpret_cast((char*)&rcv_utcb->values[15]); + = reinterpret_cast((char*)&rcv_utcb->values[16]); snd->_exc_cont.get(d, ts); if (EXPECT_TRUE(!snd->exception_triggered())) { - rcv_utcb->values[18] = ts->pc; - rcv_utcb->values[19] = ts->psr; + rcv_utcb->values[19] = ts->pc; + rcv_utcb->values[20] = ts->psr; } if (rcv_utcb->inherit_fpu() && (rights & L4_fpage::W)) @@ -547,11 +564,17 @@ Thread::copy_ts_to_utcb(L4_msg_tag const &, Thread *snd, Thread *rcv, return true; } -PROTECTED inline +PROTECTED inline NEEDS[Thread::set_tpidruro] L4_msg_tag -Thread::invoke_arch(L4_msg_tag /*tag*/, Utcb * /*utcb*/) +Thread::invoke_arch(L4_msg_tag tag, Utcb *utcb) { - return commit_result(-L4_err::ENosys); + switch (utcb->values[0] & Opcode_mask) + { + case Op_set_tpidruro_arm: + return set_tpidruro(tag, utcb); + default: + return commit_result(-L4_err::ENosys); + } } PROTECTED inline @@ -603,6 +626,37 @@ Thread::vcpu_resume_user_arch() : : "r" (utcb().access(true)->values[25]) : "memory"); } +PRIVATE inline +L4_msg_tag +Thread::set_tpidruro(L4_msg_tag tag, Utcb *utcb) +{ + if (EXPECT_FALSE(tag.words() < 2)) + return commit_result(-L4_err::EInval); + + _tpidruro = utcb->values[1]; + if (EXPECT_FALSE(state() & Thread_vcpu_enabled)) + arch_update_vcpu_state(vcpu_state().access()); + + if (this == current_thread()) + load_tpidruro(); + + return commit_result(0); +} + +PRIVATE inline +void +Thread::get_ts_tpidruro(Trap_state *ts) +{ + _tpidruro = ts->tpidruro; +} + +PRIVATE inline +void +Thread::set_ts_tpidruro(Trap_state *ts) +{ + ts->tpidruro = _tpidruro; +} + // ------------------------------------------------------------------------ IMPLEMENTATION [arm && !armv6plus]: @@ -611,6 +665,23 @@ void Thread::vcpu_resume_user_arch() {} +PRIVATE inline +L4_msg_tag +Thread::set_tpidruro(L4_msg_tag, Utcb *) +{ + return commit_result(-L4_err::EInval); +} + +PRIVATE inline +void +Thread::get_ts_tpidruro(Trap_state *) +{} + +PRIVATE inline +void +Thread::set_ts_tpidruro(Trap_state *) +{} + //----------------------------------------------------------------------------- IMPLEMENTATION [mp]: @@ -702,14 +773,14 @@ Thread::handle_fpu_trap(Unsigned32 opcode, Trap_state *ts) if (Fpu::is_enabled()) { - assert(Fpu::owner(current_cpu()) == current_thread()); + assert(Fpu::fpu.current().owner() == current()); if (Fpu::is_emu_insn(opcode)) - return Fpu::emulate_insns(opcode, ts, current_cpu()); + return Fpu::emulate_insns(opcode, ts); } else if (current_thread()->switchin_fpu()) { if (Fpu::is_emu_insn(opcode)) - return Fpu::emulate_insns(opcode, ts, current_cpu()); + return Fpu::emulate_insns(opcode, ts); ts->pc -= (ts->psr & Proc::Status_thumb) ? 2 : 4; return true; } diff --git a/kernel/fiasco/src/kern/arm/thread-jdb.cpp b/kernel/fiasco/src/kern/arm/thread-jdb.cpp index 1be7a5c8..32420e80 100644 --- a/kernel/fiasco/src/kern/arm/thread-jdb.cpp +++ b/kernel/fiasco/src/kern/arm/thread-jdb.cpp @@ -60,7 +60,7 @@ int Thread::call_nested_trap_handler(Trap_state *ts) { unsigned phys_cpu = Proc::cpu_id(); - unsigned log_cpu = Cpu::p2l(phys_cpu); + unsigned log_cpu = Cpu::cpus.find_cpu(Cpu::By_phys_id(phys_cpu)); if (log_cpu == ~0U) { printf("Trap on unknown CPU phys_id=%x\n", phys_cpu); diff --git a/kernel/fiasco/src/kern/arm/tramp-mp.S b/kernel/fiasco/src/kern/arm/tramp-mp.S index 96f87b1f..736cb2d5 100644 --- a/kernel/fiasco/src/kern/arm/tramp-mp.S +++ b/kernel/fiasco/src/kern/arm/tramp-mp.S @@ -121,13 +121,6 @@ _tramp_mp_entry: // we run paged now _tramp_mp_virt: - ldr r0, _cpu_counter_address -1: ldrex r3, [r0] - add r3, r3, #1 - strex r2, r3, [r0] - teq r2, #0 - bne 1b - // spinlock on cpu-init adr r0, _tramp_mp_spinlock 1: ldr r1, [r0] @@ -147,15 +140,13 @@ _tramp_mp_virt: mcr p15, 0, r0, c8, c7, 0 adr sp, _tramp_mp_init_stack_top - mov r0, r3 + nop + nop nop ldr pc, [pc, #-4] .long BOOT_AP_CPU -_cpu_counter_address: - .long config_num_ap_cpus - .global _tramp_mp_startup_cp15_c1 _tramp_mp_startup_cp15_c1: .long 0x00000000 diff --git a/kernel/fiasco/src/kern/arm/trap_state.cpp b/kernel/fiasco/src/kern/arm/trap_state.cpp index 1a309417..42dfd0a1 100644 --- a/kernel/fiasco/src/kern/arm/trap_state.cpp +++ b/kernel/fiasco/src/kern/arm/trap_state.cpp @@ -12,14 +12,15 @@ public: Mword pf_address; Mword error_code; + Mword tpidruro; Mword r[13]; }; - class Trap_state : public Trap_state_regs, public Return_frame { public: typedef int (*Handler)(Trap_state*, unsigned cpu); + bool exclude_logging() { return false; } }; diff --git a/kernel/fiasco/src/kern/arm/utcb_support-arm.cpp b/kernel/fiasco/src/kern/arm/utcb_support-arm.cpp index 21b536ea..de213518 100644 --- a/kernel/fiasco/src/kern/arm/utcb_support-arm.cpp +++ b/kernel/fiasco/src/kern/arm/utcb_support-arm.cpp @@ -27,7 +27,5 @@ Utcb_support::current() IMPLEMENT inline void -Utcb_support::current(User::Ptr const &utcb) -{ - asm volatile ("mcr p15, 0, %0, c13, c0, 3" : : "r" (utcb.get()) : "memory"); -} +Utcb_support::current(User::Ptr const &) +{} diff --git a/kernel/fiasco/src/kern/arm/vcpu-arm.cpp b/kernel/fiasco/src/kern/arm/vcpu-arm.cpp new file mode 100644 index 00000000..f7b6320d --- /dev/null +++ b/kernel/fiasco/src/kern/arm/vcpu-arm.cpp @@ -0,0 +1,9 @@ +INTERFACE [arm]: + +#include "l4_types.h" + +EXTENSION class Vcpu_state +{ +public: + Mword _tpidruro; +}; diff --git a/kernel/fiasco/src/kern/arm/vm.cpp b/kernel/fiasco/src/kern/arm/vm.cpp index 9ed2fce5..686343d3 100644 --- a/kernel/fiasco/src/kern/arm/vm.cpp +++ b/kernel/fiasco/src/kern/arm/vm.cpp @@ -77,10 +77,12 @@ private: //----------------------------------------------------------------------------- INTERFACE [debug]: +#include "tb_entry.h" + EXTENSION class Vm { public: - struct Vm_log + struct Vm_log : public Tb_entry { bool is_entry; Mword pc; @@ -89,10 +91,10 @@ public: Mword pending_events; Mword r0; Mword r1; - }; - - static unsigned vm_log_fmt(Tb_entry *tbe, int maxlen, char *buf) - asm ("__vm_log_fmt"); + unsigned print(int maxlen, char *buf) const; + unsigned vm_entry_log_fmt(int maxlen, char *buf) const; + unsigned vm_exit_log_fmt(int maxlen, char *buf) const; + }; }; //----------------------------------------------------------------------------- @@ -372,41 +374,40 @@ Vm::show_short(char *buf, int max) IMPLEMENT unsigned -Vm::vm_log_fmt(Tb_entry *e, int maxlen, char *buf) +Vm::Vm_log::print(int maxlen, char *buf) const { - Vm_log *l = e->payload(); - if (l->is_entry) - return vm_entry_log_fmt(l, maxlen, buf); + if (is_entry) + return vm_entry_log_fmt(maxlen, buf); else - return vm_exit_log_fmt(l, maxlen, buf); + return vm_exit_log_fmt(maxlen, buf); } -PRIVATE static +IMPLEMENT unsigned -Vm::vm_entry_log_fmt(Vm_log *l, int maxlen, char *buf) +Vm::Vm_log::vm_entry_log_fmt(int maxlen, char *buf) const { - if (l->r0 == 0x1110) - return snprintf(buf, maxlen, "entry: pc:%08lx/%03lx intack irq: %lx", l->pc, l->pending_events, l->r1); + if (r0 == 0x1110) + return snprintf(buf, maxlen, "entry: pc:%08lx/%03lx intack irq: %lx", pc, pending_events, r1); - return snprintf(buf, maxlen, "entry: pc:%08lx/%03lx r0:%lx", l->pc, l->pending_events, l->r0); + return snprintf(buf, maxlen, "entry: pc:%08lx/%03lx r0:%lx", pc, pending_events, r0); } -PRIVATE static +IMPLEMENT unsigned -Vm::vm_exit_log_fmt(Vm_log *l, int maxlen, char *buf) +Vm::Vm_log::vm_exit_log_fmt(int maxlen, char *buf) const { - if ((l->r0 & 0xffff0000) == 0xffff0000) - return snprintf(buf, maxlen, "=====: pc:%08lx/%03lx [%04lx]", l->pc, l->pending_events, l->r0 & 0xffff); - if (l->r0 == 0x1105) - return snprintf(buf, maxlen, "exit: pc:%08lx/%03lx enable irq: %lx", l->pc, l->pending_events, l->r1); - if (l->r0 == 0x1109) - return snprintf(buf, maxlen, "exit: pc:%08lx/%03lx disable irq: %lx", l->pc, l->pending_events, l->r1); - if (l->r0 == 0x1110) - return snprintf(buf, maxlen, "exit: pc:%08lx/%03lx intack", l->pc, l->pending_events); - if (l->r0 == 0x1115) - return snprintf(buf, maxlen, "exit: pc:%08lx/%03lx send ipi:%lx", l->pc, l->pending_events, l->r1); + if ((r0 & 0xffff0000) == 0xffff0000) + return snprintf(buf, maxlen, "=====: pc:%08lx/%03lx [%04lx]", pc, pending_events, r0 & 0xffff); + if (r0 == 0x1105) + return snprintf(buf, maxlen, "exit: pc:%08lx/%03lx enable irq: %lx", pc, pending_events, r1); + if (r0 == 0x1109) + return snprintf(buf, maxlen, "exit: pc:%08lx/%03lx disable irq: %lx", pc, pending_events, r1); + if (r0 == 0x1110) + return snprintf(buf, maxlen, "exit: pc:%08lx/%03lx intack", pc, pending_events); + if (r0 == 0x1115) + return snprintf(buf, maxlen, "exit: pc:%08lx/%03lx send ipi:%lx", pc, pending_events, r1); - return snprintf(buf, maxlen, "exit: pc:%08lx/%03lx r0:%lx", l->pc, l->pending_events, l->r0); + return snprintf(buf, maxlen, "exit: pc:%08lx/%03lx r0:%lx", pc, pending_events, r0); } PUBLIC static inline @@ -419,8 +420,7 @@ Vm::log_vm(Vm *vm, bool is_entry) return; if ((is_entry && (vm->state()->r[0] & 0xffff0000) == 0xffff0000)) return; - LOG_TRACE("VM entry/entry", "VM", current(), __vm_log_fmt, - Vm::Vm_log *l = tbe->payload(); + LOG_TRACE("VM entry/entry", "VM", current(), Vm_log, l->is_entry = is_entry; l->pc = vm->state()->pc; l->cpsr = vm->state()->cpsr; diff --git a/kernel/fiasco/src/kern/boot_alloc.cpp b/kernel/fiasco/src/kern/boot_alloc.cpp index 458a39c4..284ff54e 100644 --- a/kernel/fiasco/src/kern/boot_alloc.cpp +++ b/kernel/fiasco/src/kern/boot_alloc.cpp @@ -2,6 +2,7 @@ INTERFACE: #include #include +#include class Boot_alloced { @@ -18,16 +19,10 @@ template< typename Base > class Boot_object : public Base, public Boot_alloced { public: - Boot_object() : Base() {} + Boot_object() = default; - template< typename A1 > - Boot_object(A1 const &a1) : Base(a1) {} - - template< typename A1, typename A2 > - Boot_object(A1 const &a1, A2 const &a2) : Base(a1, a2) {} - - template< typename A1, typename A2, typename A3 > - Boot_object(A1 const &a1, A2 const &a2, A3 const &a3) : Base(a1, a2, a3) {} + template< typename... A > + Boot_object(A&&... args) : Base(cxx::forward(args)...) {} }; diff --git a/kernel/fiasco/src/kern/config.cpp b/kernel/fiasco/src/kern/config.cpp index 3d601a7a..9d0d17d9 100644 --- a/kernel/fiasco/src/kern/config.cpp +++ b/kernel/fiasco/src/kern/config.cpp @@ -27,7 +27,7 @@ INTERFACE: #define GREETING_COLOR_ANSI_OFF "\033[0m" -#define FIASCO_KERNEL_SUBVERSION 0 +#define FIASCO_KERNEL_SUBVERSION 1 class Config { @@ -217,6 +217,10 @@ unsigned Config::tbuf_entries = 0x20000 / sizeof(Mword); //1024; bool Config::getchar_does_hlt_works_ok = false; unsigned Config::num_ap_cpus; +#ifdef CONFIG_FINE_GRAINED_CPUTIME +KIP_KERNEL_FEATURE("fi_gr_cputime"); +#endif + //----------------------------------------------------------------------------- IMPLEMENTATION: diff --git a/kernel/fiasco/src/kern/context-vcpu.cpp b/kernel/fiasco/src/kern/context-vcpu.cpp index 2b37303d..5957957e 100644 --- a/kernel/fiasco/src/kern/context-vcpu.cpp +++ b/kernel/fiasco/src/kern/context-vcpu.cpp @@ -48,7 +48,7 @@ Context::vcpu_save_state_and_upcall() _exc_cont.activate(regs(), leave_by_vcpu_upcall); } -PUBLIC inline NEEDS["fpu.h", "space.h"] +PUBLIC inline NEEDS["fpu.h", "space.h", Context::arch_load_vcpu_kern_state] bool Context::vcpu_enter_kernel_mode(Vcpu_state *vcpu) { @@ -70,7 +70,11 @@ Context::vcpu_enter_kernel_mode(Vcpu_state *vcpu) _space.user_mode(false); state_del_dirty(Thread_vcpu_fpu_disabled); - if (current() == this) + bool load_cpu_state = current() == this; + + arch_load_vcpu_kern_state(vcpu, load_cpu_state); + + if (load_cpu_state) { if (state() & Thread_fpu_owner) Fpu::enable(); @@ -144,25 +148,23 @@ IMPLEMENTATION [debug]: IMPLEMENT unsigned -Context::vcpu_log_fmt(Tb_entry *e, int maxlen, char *buf) +Context::Vcpu_log::print(int maxlen, char *buf) const { - Vcpu_log *l = e->payload(); - - switch (l->type) + switch (type) { case 0: case 4: return snprintf(buf, maxlen, "%sret pc=%lx sp=%lx state=%lx task=D:%lx", - l->type == 4 ? "f" : "", l->ip, l->sp, l->state, l->space); + type == 4 ? "f" : "", ip, sp, state, space); case 1: return snprintf(buf, maxlen, "ipc from D:%lx task=D:%lx sp=%lx", - Kobject_dbg::pointer_to_id((Kobject*)l->ip), l->state, l->sp); + Kobject_dbg::pointer_to_id((Kobject*)ip), state, sp); case 2: return snprintf(buf, maxlen, "exc #%x err=%lx pc=%lx sp=%lx state=%lx task=D:%lx", - (unsigned)l->trap, l->err, l->ip, l->sp, l->state, l->space); + (unsigned)trap, err, ip, sp, state, space); case 3: return snprintf(buf, maxlen, "pf pc=%lx pfa=%lx state=%lx task=D:%lx", - l->ip, l->sp, l->state, l->space); + ip, sp, state, space); default: return snprintf(buf, maxlen, "unknown"); } diff --git a/kernel/fiasco/src/kern/context.cpp b/kernel/fiasco/src/kern/context.cpp index fbcd6b27..a364e66a 100644 --- a/kernel/fiasco/src/kern/context.cpp +++ b/kernel/fiasco/src/kern/context.cpp @@ -111,7 +111,7 @@ class Context : protected: virtual void finish_migration() = 0; - virtual void initiate_migration() = 0; + virtual bool initiate_migration() = 0; struct State_request { @@ -171,15 +171,18 @@ public: public: enum Drop_mode { Drop = true, No_drop = false }; void enq(Drq *rq); + bool dequeue(Drq *drq, Queue_item::Status reason); bool handle_requests(Drop_mode drop = No_drop); bool execute_request(Drq *r, Drop_mode drop, bool local); }; - struct Migration_info + struct Migration { - Mword quantum; unsigned cpu; - unsigned short prio; + L4_sched_param const *sp; + bool in_progress; + + Migration() : in_progress(false) {} }; template @@ -311,16 +314,12 @@ protected: jmp_buf *_recover_jmpbuf; // setjmp buffer for page-fault recovery - struct Migration_rq - { - Migration_info inf; - Spin_lock<> affinity_lock; - bool pending; - bool in_progress; + Migration *_migration; + bool _need_to_finish_migration; - Migration_rq() : pending(false), in_progress(false) - { affinity_lock.init(); } - } _migration_rq; + void arch_load_vcpu_kern_state(Vcpu_state *vcpu, bool do_load); + void arch_load_vcpu_user_state(Vcpu_state *vcpu, bool do_load); + void arch_update_vcpu_state(Vcpu_state *vcpu); protected: // XXX Timeout for both, sender and receiver! In normal case we would have @@ -343,18 +342,39 @@ INTERFACE [debug]: EXTENSION class Context { public: - struct Drq_log + struct Drq_log : public Tb_entry { void *func; void *reply; Context *thread; + Drq const *rq; unsigned target_cpu; - char const *type; + enum class Type { Send, Do_request, Do_reply, Done } type; bool wait; + unsigned print(int max, char *buf) const; + Group_order has_partner() const + { + switch (type) + { + case Type::Send: return Group_order::first(); + case Type::Done: return Group_order::last(); + case Type::Do_request: return Group_order(1); + case Type::Do_reply: return Group_order(2); + } + return Group_order::none(); + } + + Group_order is_partner(Drq_log const *o) const + { + if (rq != o->rq || func != o->func || reply != o->reply) + return Group_order::none(); + + return o->has_partner(); + } }; - struct Vcpu_log + struct Vcpu_log : public Tb_entry { Mword state; Mword ip; @@ -363,11 +383,8 @@ public: Mword err; unsigned char type; unsigned char trap; + unsigned print(int max, char *buf) const; }; - - static unsigned drq_log_fmt(Tb_entry *, int, char *) - asm ("__context_drq_log_fmt"); - }; // -------------------------------------------------------------------------- @@ -423,7 +440,10 @@ Context::Context() _helper(this), _sched_context(), _sched(&_sched_context), - _mode(Sched_mode(0)) + _mode(Sched_mode(0)), + _migration(0), + _need_to_finish_migration(false) + { // NOTE: We do not have to synchronize the initialization of // _space_context because it is constant for all concurrent @@ -432,7 +452,24 @@ Context::Context() // sys_task_new() and avoid calling us twice with different // space_context arguments. - set_cpu_of(this, current_cpu()); + set_cpu_of(this, Cpu::Invalid); +} + +PUBLIC inline +void +Context::spill_fpu_if_owner() +{ + // spill FPU state into memory before migration + if (state() & Thread_fpu_owner) + { + Fpu &f = Fpu::fpu.current(); + if (current() != this) + f.enable(); + + spill_fpu(); + f.set_owner(0); + f.disable(); + } } @@ -441,10 +478,11 @@ void Context::do_kill() { // If this context owned the FPU, noone owns it now - if (Fpu::is_owner(cpu(), this)) + Fpu &f = Fpu::fpu.current(); + if (f.is_owner(this)) { - Fpu::set_owner(cpu(), 0); - Fpu::disable(); + f.set_owner(0); + f.disable(); } } @@ -454,13 +492,23 @@ PUBLIC virtual Context::~Context() {} +PUBLIC inline +bool +Context::check_for_current_cpu() const +{ + bool r = cpu() == current_cpu() || !Cpu::online(cpu()); + if (0 && EXPECT_FALSE(!r)) // debug output disabled + printf("FAIL: cpu=%u (current=%u)\n", cpu(), current_cpu()); + return r; +} + PUBLIC inline Mword Context::state(bool check = true) const { (void)check; - assert_kdb(!check || cpu() == current_cpu()); + assert_kdb(!check || check_for_current_cpu()); return _state; } @@ -509,7 +557,7 @@ PUBLIC inline NEEDS ["atomic.h"] void Context::state_add(Mword bits) { - assert_kdb(cpu() == current_cpu()); + assert_kdb(check_for_current_cpu()); atomic_or(&_state, bits); } @@ -521,9 +569,10 @@ Context::state_add(Mword bits) */ PUBLIC inline void -Context::state_add_dirty(Mword bits) -{ - assert_kdb(cpu() == current_cpu()); +Context::state_add_dirty(Mword bits, bool check = true) +{ + (void)check; + assert_kdb(!check || check_for_current_cpu()); _state |= bits; } @@ -536,7 +585,7 @@ PUBLIC inline NEEDS ["atomic.h"] void Context::state_del(Mword bits) { - assert_kdb (current_cpu() == cpu()); + assert_kdb (check_for_current_cpu()); atomic_and(&_state, ~bits); } @@ -551,7 +600,7 @@ void Context::state_del_dirty(Mword bits, bool check = true) { (void)check; - assert_kdb(!check || cpu() == current_cpu()); + assert_kdb(!check || check_for_current_cpu()); _state &= ~bits; } @@ -568,7 +617,7 @@ PUBLIC inline NEEDS ["atomic.h"] Mword Context::state_change_safely(Mword mask, Mword bits) { - assert_kdb (current_cpu() == cpu()); + assert_kdb (check_for_current_cpu()); Mword old; do @@ -591,7 +640,7 @@ PUBLIC inline NEEDS ["atomic.h"] Mword Context::state_change(Mword mask, Mword bits) { - assert_kdb (current_cpu() == cpu()); + assert_kdb (check_for_current_cpu()); return atomic_change(&_state, mask, bits); } @@ -607,7 +656,7 @@ void Context::state_change_dirty(Mword mask, Mword bits, bool check = true) { (void)check; - assert_kdb(!check || cpu() == current_cpu()); + assert_kdb(!check || check_for_current_cpu()); _state &= mask; _state |= bits; } @@ -625,15 +674,6 @@ PUBLIC inline Space * Context::vcpu_aware_space() const { return _space.vcpu_aware(); } -#if 0 -/** Convenience function: Return memory space. */ -PUBLIC inline NEEDS["space.h"] -Mem_space* -Context::mem_space() const -{ - return space()->mem_space(); -} -#endif /** Registers used when iret'ing to user mode. @return return registers @@ -690,24 +730,10 @@ Context::lock_cnt() const */ PUBLIC void -Context::switch_sched(Sched_context * const next) +Context::switch_sched(Sched_context *next, Sched_context::Ready_queue *queue) { - // Ensure CPU lock protection - assert_kdb (cpu_lock.test()); - - // If we're leaving the global timeslice, invalidate it - // This causes schedule() to select a new timeslice via set_current_sched() - if (sched() == current_sched()) - invalidate_sched(); -#if 0 - // Ensure the new timeslice has a full quantum - assert_kdb (next->left() == next->quantum()); -#endif - if (in_ready_list()) - ready_dequeue(); - + queue->switch_sched(sched(), next); set_sched(next); - ready_enqueue(); } /** @@ -717,7 +743,8 @@ PUBLIC void Context::schedule() { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); + assert (!Sched_context::rq.current().schedule_in_progress); CNT_SCHEDULE; @@ -736,16 +763,18 @@ Context::schedule() do { // I may've been migrated during the switch_exec_locked in the while - // statement below. So cxheck out if I've to use a new ready queue. - if (cpu() != current_cpu) - { - current_cpu = cpu(); - rq = &Sched_context::rq(current_cpu); - if (rq->schedule_in_progress) - return; - // Nested invocations of schedule() are bugs - assert_kdb (!rq->schedule_in_progress); - } + // statement below. So check out if I've to use a new ready queue. + { + unsigned new_cpu = access_once(&_cpu); + if (new_cpu != current_cpu) + { + Mem::barrier(); + current_cpu = new_cpu; + rq = &Sched_context::rq.current(); + if (rq->schedule_in_progress) + return; + } + } for (;;) { @@ -757,7 +786,7 @@ Context::schedule() if (EXPECT_TRUE (next_to_run->state() & Thread_ready_mask)) break; - next_to_run->ready_dequeue(); + rq->ready_dequeue(next_to_run->sched()); rq->schedule_in_progress = this; @@ -766,10 +795,11 @@ Context::schedule() cpu_lock.lock(); // check if we've been migrated meanwhile - if (EXPECT_FALSE(current_cpu != cpu())) + if (EXPECT_FALSE(current_cpu != access_once(&_cpu))) { - current_cpu = cpu(); - rq = &Sched_context::rq(current_cpu); + current_cpu = _cpu; + Mem::barrier(); + rq = &Sched_context::rq.current(); if (rq->schedule_in_progress) return; } @@ -780,87 +810,17 @@ Context::schedule() while (EXPECT_FALSE(schedule_switch_to_locked(next_to_run))); } -/** - * Return if there is currently a schedule() in progress - */ -PUBLIC inline -Context * -Context::schedule_in_progress() -{ - return sched()->schedule_in_progress(cpu()); -} -PUBLIC inline NEEDS[Context::schedule_in_progress] +PUBLIC inline void Context::schedule_if(bool s) { - if (!s || schedule_in_progress()) + if (!s || Sched_context::rq.current().schedule_in_progress) return; schedule(); } -PROTECTED inline -void -Context::reset_schedule_in_progress() -{ sched()->reset_schedule_in_progress(cpu()); } - -/** - * Return currently active global Sched_context. - */ -PUBLIC static inline -Sched_context * -Context::current_sched() -{ - return Sched_context::rq(current_cpu()).current_sched(); -} - -/** - * Set currently active global Sched_context. - */ -PROTECTED -void -Context::set_current_sched(Sched_context *sched) -{ - assert_kdb (sched); - // Save remainder of previous timeslice or refresh it, unless it had - // been invalidated - unsigned cpu = this->cpu(); - Sched_context::Ready_queue &rq = Sched_context::rq(cpu); - - Timeout * const tt = timeslice_timeout.cpu(cpu); - Unsigned64 clock = Timer::system_clock(); - if (Sched_context *s = rq.current_sched()) - { - Signed64 left = tt->get_timeout(clock); - if (left > 0) - s->set_left(left); - else - s->replenish(); - - LOG_SCHED_SAVE(s); - } - - // Program new end-of-timeslice timeout - tt->reset(); - tt->set(clock + sched->left(), cpu); - - // Make this timeslice current - rq.activate(sched); - - LOG_SCHED_LOAD(sched); -} - -/** - * Invalidate (expire) currently active global Sched_context. - */ -PROTECTED inline NEEDS["logdefs.h","timeout.h"] -void -Context::invalidate_sched() -{ - //LOG_SCHED_INVALIDATE; - sched()->invalidate_sched(cpu()); -} /** * Return Context's Sched_context with id 'id'; return time slice 0 as default. @@ -961,8 +921,8 @@ Context::update_ready_list() { assert_kdb (this == current()); - if (state() & Thread_ready_mask) - ready_enqueue(); + if ((state() & Thread_ready_mask) && sched()->left()) + Sched_context::rq.current().ready_enqueue(sched()); } /** @@ -976,24 +936,6 @@ Context::in_ready_list() const return sched()->in_ready_list(); } -/** - * Enqueue context in ready-list. - */ -PUBLIC -void -Context::ready_enqueue(bool check = true) -{ - (void)check; - assert_kdb(!check || current_cpu() == cpu()); - //Lock_guard guard (&cpu_lock); - - // Don't enqueue threads that are not ready or have no own time - if (EXPECT_FALSE (!(state(check) & Thread_ready_mask) || !sched()->left())) - return; - - sched()->ready_enqueue(cpu()); -} - /** * \brief Activate a newly created thread. @@ -1005,11 +947,11 @@ PUBLIC bool Context::activate() { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); if (cpu() == current_cpu()) { state_add_dirty(Thread_ready); - if (sched()->deblock(cpu(), current()->sched(), true)) + if (Sched_context::rq.current().deblock(sched(), current()->sched(), true)) { current()->switch_to_locked(this); return true; @@ -1021,17 +963,6 @@ Context::activate() return false; } -/** - * Remove context from ready-list. - */ -PUBLIC inline NEEDS ["cpu_lock.h", "lock_guard.h", "std_macros.h"] -void -Context::ready_dequeue() -{ - assert_kdb(current_cpu() == cpu()); - sched()->ready_dequeue(); -} - /** Helper. Context that helps us by donating its time to us. It is set by switch_exec() if the calling thread says so. @@ -1148,7 +1079,7 @@ Context::switch_to(Context *t) assert (!cpu_lock.test()); // Grab the CPU lock - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); switch_to_locked(t); } @@ -1165,9 +1096,10 @@ Context::schedule_switch_to_locked(Context *t) // Must be called with CPU lock held assert_kdb (cpu_lock.test()); + Sched_context::Ready_queue &rq = Sched_context::rq.current(); // Switch to destination thread's scheduling context - if (current_sched() != t->sched()) - set_current_sched(t->sched()); + if (rq.current_sched() != t->sched()) + rq.set_current_sched(t->sched()); // XXX: IPC dependency tracking belongs here. @@ -1198,7 +1130,7 @@ Context::switch_exec(Context *t, enum Helping_mode mode) assert_kdb (!cpu_lock.test()); // Grab the CPU lock - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); return switch_exec_locked(t, mode); } @@ -1247,6 +1179,9 @@ bool FIASCO_WARN_RESULT //L4_IPC_CODE Context::switch_exec_locked(Context *t, enum Helping_mode mode) { // Must be called with CPU lock held + assert_kdb (t->cpu() != Cpu::Invalid); + assert_kdb (t->cpu() == current_cpu()); + assert_kdb (cpu() == current_cpu()); assert_kdb (cpu_lock.test()); assert_kdb (current() != t); assert_kdb (current() == this); @@ -1312,7 +1247,7 @@ void Context::Drq_q::enq(Drq *rq) { assert_kdb(cpu_lock.test()); - Lock_guard guard(q_lock()); + auto guard = lock_guard(q_lock()); enqueue(rq); } @@ -1337,9 +1272,9 @@ Context::Drq_q::execute_request(Drq *r, Drop_mode drop, bool local) // printf("CPU[%2u:%p]: context=%p: handle request for %p (func=%p, arg=%p)\n", current_cpu(), current(), context(), r->context(), r->func, r->arg); if (r->context() == self) { - LOG_TRACE("DRQ handling", "drq", current(), __context_drq_log_fmt, - Drq_log *l = tbe->payload(); - l->type = "reply"; + LOG_TRACE("DRQ handling", "drq", current(), Drq_log, + l->type = Drq_log::Type::Do_reply; + l->rq = r; l->func = (void*)r->func; l->reply = (void*)r->reply; l->thread = r->context(); @@ -1351,9 +1286,9 @@ Context::Drq_q::execute_request(Drq *r, Drop_mode drop, bool local) } else { - LOG_TRACE("DRQ handling", "drq", current(), __context_drq_log_fmt, - Drq_log *l = tbe->payload(); - l->type = "request"; + LOG_TRACE("DRQ handling", "drq", current(), Drq_log, + l->type = Drq_log::Type::Do_request; + l->rq = r; l->func = (void*)r->func; l->reply = (void*)r->reply; l->thread = r->context(); @@ -1384,6 +1319,16 @@ Context::Drq_q::execute_request(Drq *r, Drop_mode drop, bool local) return need_resched; } +IMPLEMENT inline NEEDS["lock_guard.h"] +bool +Context::Drq_q::dequeue(Drq *drq, Queue_item::Status reason) +{ + auto guard = lock_guard(q_lock()); + if (!drq->queued()) + return false; + return Queue::dequeue(drq, reason); +} + IMPLEMENT inline NEEDS["mem.h", "lock_guard.h"] bool Context::Drq_q::handle_requests(Drop_mode drop) @@ -1394,12 +1339,12 @@ Context::Drq_q::handle_requests(Drop_mode drop) { Queue_item *qi; { - Lock_guard guard(q_lock()); + auto guard = lock_guard(q_lock()); qi = first(); if (!qi) return need_resched; - check_kdb (dequeue(qi, Queue_item::Ok)); + check_kdb (Queue::dequeue(qi, Queue_item::Ok)); } Drq *r = static_cast(qi); @@ -1421,7 +1366,7 @@ Context::force_dequeue() // we're waiting for a lock or have a DRQ pending Queue *const q = qi->queue(); { - Lock_guard guard(q->q_lock()); + auto guard = lock_guard(q->q_lock()); // check again, with the queue lock held. // NOTE: we may be already removed from the queue on another CPU if (qi->queued() && qi->queue()) @@ -1461,9 +1406,9 @@ PUBLIC inline void Context::try_finish_migration() { - if (EXPECT_FALSE(_migration_rq.in_progress)) + if (EXPECT_FALSE(_need_to_finish_migration)) { - _migration_rq.in_progress = false; + _need_to_finish_migration = false; finish_migration(); } } @@ -1481,7 +1426,7 @@ PUBLIC //inline bool Context::handle_drq() { - assert_kdb (current_cpu() == this->cpu()); + assert_kdb (check_for_current_cpu()); assert_kdb (cpu_lock.test()); try_finish_migration(); @@ -1490,19 +1435,9 @@ Context::handle_drq() return false; Mem::barrier(); - bool ret = false; - while (true) - { - ret |= _drq_q.handle_requests(); + bool ret = _drq_q.handle_requests(); + state_del_dirty(Thread_drq_ready); - Lock_guard guard(_drq_q.q_lock()); - if (EXPECT_TRUE(!drq_pending())) - { - state_del_dirty(Thread_drq_ready); - break; - } - } - //LOG_MSG_3VAL(this, "xdrq", state(), ret, cpu_lock.test()); /* @@ -1588,7 +1523,7 @@ Context::drq_state_change(Mword mask, Mword add) * \param reply the reply handler (called in the context of \a src immediately * after receiving a successful reply). * - * DRQs are requests than any context can queue to any other context. DRQs are + * DRQs are requests that any context can queue to any other context. DRQs are * the basic mechanism to initiate actions on remote CPUs in an MP system, * however, are also allowed locally. * DRQ handlers of pending DRQs are executed by Context::handle_drq() in the @@ -1597,7 +1532,7 @@ Context::drq_state_change(Mword mask, Mword add) * * This function enqueues a DRQ and blocks the current context for a reply DRQ. */ -PUBLIC inline NEEDS[Context::enqueue_drq] +PUBLIC inline NEEDS[Context::enqueue_drq, "logdefs.h"] void Context::drq(Drq *drq, Drq::Request_func *func, void *arg, Drq::Request_func *reply = 0, @@ -1606,9 +1541,9 @@ Context::drq(Drq *drq, Drq::Request_func *func, void *arg, { // printf("CPU[%2u:%p]: > Context::drq(this=%p, src=%p, func=%p, arg=%p)\n", current_cpu(), current(), this, src, func,arg); Context *cur = current(); - LOG_TRACE("DRQ Stuff", "drq", cur, __context_drq_log_fmt, - Drq_log *l = tbe->payload(); - l->type = "send"; + LOG_TRACE("DRQ Stuff", "drq", cur, Drq_log, + l->type = Drq_log::Type::Send; + l->rq = drq; l->func = (void*)func; l->reply = (void*)reply; l->thread = this; @@ -1635,9 +1570,9 @@ Context::drq(Drq *drq, Drq::Request_func *func, void *arg, cur->schedule(); } - LOG_TRACE("DRQ Stuff", "drq", cur, __context_drq_log_fmt, - Drq_log *l = tbe->payload(); - l->type = "done"; + LOG_TRACE("DRQ Stuff", "drq", cur, Drq_log, + l->type = Drq_log::Type::Done; + l->rq = drq; l->func = (void*)func; l->reply = (void*)reply; l->thread = this; @@ -1652,12 +1587,14 @@ Context::kernel_context_drq(Drq::Request_func *func, void *arg, Drq::Request_func *reply = 0) { char align_buffer[2*sizeof(Drq)]; - Drq *mdrq = (Drq*)((Address(align_buffer) + __alignof__(Drq) - 1) & ~(__alignof__(Drq)-1)); + Drq *mdrq = new ((void*)((Address)(align_buffer + __alignof__(Drq) - 1) & ~(__alignof__(Drq)-1))) Drq; + mdrq->func = func; mdrq->arg = arg; mdrq->reply = reply; Context *kc = kernel_context(current_cpu()); + kc->_drq_q.enq(mdrq); bool resched = schedule_switch_to_locked(kc); (void)resched; @@ -1678,7 +1615,7 @@ Context::rcu_unblock(Rcu_item *i) assert_kdb(cpu_lock.test()); Context *const c = static_cast(i); c->state_change_dirty(~Thread_waiting, Thread_ready); - c->sched()->deblock(c->cpu()); + Sched_context::rq.current().deblock(c->sched()); return true; } @@ -1695,6 +1632,21 @@ Context::xcpu_tlb_flush(...) assert(0); } +IMPLEMENT_DEFAULT inline +void +Context::arch_load_vcpu_kern_state(Vcpu_state *, bool) +{} + +IMPLEMENT_DEFAULT inline +void +Context::arch_load_vcpu_user_state(Vcpu_state *, bool) +{} + +IMPLEMENT_DEFAULT inline +void +Context::arch_update_vcpu_state(Vcpu_state *) +{} + //---------------------------------------------------------------------------- IMPLEMENTATION [!mp]: @@ -1703,8 +1655,13 @@ IMPLEMENTATION [!mp]: PUBLIC inline unsigned -Context::cpu(bool = false) const -{ return 0; } +Context::cpu(bool running = false) const +{ + if (running) + return 0; + + return _cpu; +} PUBLIC static inline void @@ -1727,16 +1684,34 @@ Context::remote_ready_enqueue() PUBLIC bool -Context::enqueue_drq(Drq *rq, Drq::Exec_mode) +Context::enqueue_drq(Drq *rq, Drq::Exec_mode /*exec*/) { - bool sched = _drq_q.execute_request(rq, Drq_q::No_drop, true); - if (!in_ready_list() && (state() & Thread_ready_mask)) - { - ready_enqueue(); - return true; - } + assert_kdb (cpu_lock.test()); - return sched; + if (access_once(&_cpu) != current_cpu()) + { + bool do_sched = _drq_q.execute_request(rq, Drq_q::No_drop, true); + //LOG_MSG_3VAL(this, "drqX", access_once(&_cpu), current_cpu(), state()); + if (access_once(&_cpu) == current_cpu() && (state() & Thread_ready_mask)) + { + Sched_context::rq.current().ready_enqueue(sched()); + return true; + } + return do_sched; + } + else + { // LOG_MSG_3VAL(this, "adrq", state(), (Mword)current(), (Mword)rq); + + bool do_sched = _drq_q.execute_request(rq, Drq_q::No_drop, true); + if (!in_ready_list() && (state() & Thread_ready_mask)) + { + Sched_context::rq.current().ready_enqueue(sched()); + return true; + } + + return do_sched; + } + return false; } @@ -1827,7 +1802,7 @@ Context::Pending_rqq::enq(Context *c) //if (!c->_pending_rq.queued()) { Queue &q = Context::_pending_rqq.cpu(c->cpu()); - Lock_guard guard(q.q_lock()); + auto guard = lock_guard(q.q_lock()); if (c->_pending_rq.queued()) return; q.enqueue(&c->_pending_rq); @@ -1850,42 +1825,48 @@ Context::Pending_rqq::handle_requests(Context **mq) Context *curr = current(); while (1) { - Queue_item *qi; - { - Lock_guard guard(q_lock()); - qi = first(); - if (!qi) - return resched; - check_kdb (dequeue(qi, Queue_item::Ok)); - } - Context *c = static_cast(qi)->context(); - //LOG_MSG_3VAL(c, "pick", c->state(), c->cpu(), current_cpu()); - // Drop migrated threads - assert_kdb (EXPECT_FALSE(c->cpu() == current_cpu())); + Context *c; + { + auto guard = lock_guard(q_lock()); + Queue_item *qi = first(); + if (!qi) + return resched; - if (EXPECT_TRUE(c->drq_pending())) - c->state_add(Thread_drq_ready); + check_kdb (dequeue(qi, Queue_item::Ok)); + c = static_cast(qi)->context(); + } - if (EXPECT_FALSE(c->_migration_rq.pending)) + assert_kdb (c->check_for_current_cpu()); + + if (EXPECT_FALSE(c->_migration != 0)) { + // if the currently executing thread shall be migrated we must defer + // this until we have handled the whole request queue, otherwise we + // would miss the remaining requests or execute them on the wrong CPU. if (c != curr) { - c->initiate_migration(); - continue; + // we can directly migrate the thread... + resched |= c->initiate_migration(); + + // if migrated away skip the resched test below + if (access_once(&c->_cpu) != current_cpu()) + continue; } else - { - *mq = c; - resched = true; - } + *mq = c; } else c->try_finish_migration(); - if (EXPECT_TRUE((c->state() & Thread_ready_mask))) + if (EXPECT_TRUE(c != curr && c->drq_pending())) + c->state_add(Thread_drq_ready); + + // FIXME: must we also reschedule when c cannot preempt the current + // thread but its current scheduling context? + if (EXPECT_TRUE(c != curr && (c->state() & Thread_ready_mask))) { //printf("CPU[%2u:%p]: Context::Pending_rqq::handle_requests() dequeded %p(%u)\n", current_cpu(), current(), c, qi->queued()); - resched |= c->sched()->deblock(current_cpu(), current()->sched(), false); + resched |= Sched_context::rq.current().deblock(c->sched(), curr->sched(), false); } } } @@ -1932,28 +1913,51 @@ Context::enqueue_drq(Drq *rq, Drq::Exec_mode /*exec*/) if (cpu() != current_cpu()) { - bool ipi = true; + bool ipi = false; _drq_q.enq(rq); - // ready cpu again we may've been migrated meanwhile - unsigned cpu = this->cpu(); + // read cpu again we may've been migrated meanwhile + unsigned cpu = access_once(&this->_cpu); { Queue &q = Context::_pending_rqq.cpu(cpu); - Lock_guard g(q.q_lock()); + auto guard = lock_guard(q.q_lock()); // migrated between getting the lock and reading the CPU, so the // new CPU is responsible for executing our request - if (this->cpu() != cpu) + if (access_once(&this->_cpu) != cpu) return false; - if (q.first()) - ipi = false; + if (EXPECT_FALSE(!Cpu::online(cpu))) + { + if (EXPECT_FALSE(!_drq_q.dequeue(rq, Queue_item::Ok))) + // handled already + return false; - if (!_pending_rq.queued()) - q.enqueue(&_pending_rq); - } + // execute locally under the target CPU's queue lock + _drq_q.execute_request(rq, Drq_q::No_drop, true); + + // free the lock early + guard.reset(); + if ( access_once(&this->_cpu) == current_cpu() + && !in_ready_list() + && (state() & Thread_ready_mask)) + { + Sched_context::rq.current().ready_enqueue(sched()); + return true; + } + return false; + } + + if (!_pending_rq.queued()) + { + if (!q.first()) + ipi = true; + + q.enqueue(&_pending_rq); + } + } if (ipi) { @@ -1964,14 +1968,14 @@ Context::enqueue_drq(Drq *rq, Drq::Exec_mode /*exec*/) else { // LOG_MSG_3VAL(this, "adrq", state(), (Mword)current(), (Mword)rq); - bool sched = _drq_q.execute_request(rq, Drq_q::No_drop, true); + bool do_sched = _drq_q.execute_request(rq, Drq_q::No_drop, true); if (!in_ready_list() && (state() & Thread_ready_mask)) { - ready_enqueue(); + Sched_context::rq.current().ready_enqueue(sched()); return true; } - return sched; + return do_sched; } return false; } @@ -1983,7 +1987,7 @@ Context::shutdown_drqs() { if (_pending_rq.queued()) { - Lock_guard guard(_pending_rq.queue()->q_lock()); + auto guard = lock_guard(_pending_rq.queue()->q_lock()); if (_pending_rq.queued()) _pending_rq.queue()->dequeue(&_pending_rq, Queue_item::Ok); } @@ -2029,7 +2033,7 @@ PUBLIC inline NEEDS["cpu_lock.h", "lock_guard.h"] void Context::rcu_wait() { - Lock_guard gurad(&cpu_lock); + auto gurad = lock_guard(cpu_lock); state_change_dirty(~Thread_ready, Thread_waiting); Rcu::call(this, &rcu_unblock); schedule(); @@ -2051,7 +2055,7 @@ PUBLIC static void Context::xcpu_tlb_flush(bool flush_all_spaces, Mem_space *s1, Mem_space *s2) { - Lock_guard g(&cpu_lock); + auto g = lock_guard(cpu_lock); Mem_space *s[3] = { (Mem_space *)flush_all_spaces, s1, s2 }; unsigned ccpu = current_cpu(); for (unsigned i = 0; i < Config::Max_num_cpus; ++i) @@ -2059,12 +2063,26 @@ Context::xcpu_tlb_flush(bool flush_all_spaces, Mem_space *s1, Mem_space *s2) current()->global_drq(i, Context::handle_remote_tlb_flush, s); } - //---------------------------------------------------------------------------- IMPLEMENTATION [fpu && !ux]: #include "fpu.h" +PUBLIC inline NEEDS ["fpu.h"] +void +Context::spill_fpu() +{ + // If we own the FPU, we should never be getting an "FPU unavailable" trap + assert_kdb (Fpu::fpu.current().owner() == this); + assert_kdb (state() & Thread_fpu_owner); + assert_kdb (fpu_state()); + + // Save the FPU state of the previous FPU owner (lazy) if applicable + Fpu::save_state(fpu_state()); + state_del_dirty(Thread_fpu_owner); +} + + /** * When switching away from the FPU owner, disable the FPU to cause * the next FPU access to trap. @@ -2075,15 +2093,21 @@ IMPLEMENT inline NEEDS ["fpu.h"] void Context::switch_fpu(Context *t) { - if (Fpu::is_owner(cpu(), this)) - Fpu::disable(); - else if (Fpu::is_owner(cpu(), t) && !(t->state() & Thread_vcpu_fpu_disabled)) - Fpu::enable(); + Fpu &f = Fpu::fpu.current(); + if (f.is_owner(this)) + f.disable(); + else if (f.is_owner(t) && !(t->state() & Thread_vcpu_fpu_disabled)) + f.enable(); } //---------------------------------------------------------------------------- IMPLEMENTATION [!fpu]: +PUBLIC inline +void +Context::spill_fpu() +{} + IMPLEMENT inline void Context::switch_fpu(Context *) @@ -2096,11 +2120,17 @@ IMPLEMENTATION [debug]: IMPLEMENT unsigned -Context::drq_log_fmt(Tb_entry *e, int maxlen, char *buf) +Context::Drq_log::print(int maxlen, char *buf) const { - Drq_log *l = e->payload(); - return snprintf(buf, maxlen, "drq %s(%s) to ctxt=%lx/%p (func=%p, reply=%p) cpu=%u", - l->type, l->wait ? "wait" : "no-wait", Kobject_dbg::pointer_to_id(l->thread), - l->thread, l->func, l->reply, l->target_cpu); + static char const *const _types[] = + { "send", "request", "reply", "done" }; + + char const *t = "unk"; + if ((unsigned)type < sizeof(_types)/sizeof(_types[0])) + t = _types[(unsigned)type]; + + return snprintf(buf, maxlen, "%s(%s) rq=%p to ctxt=%lx/%p (func=%p, reply=%p) cpu=%u", + t, wait ? "wait" : "no-wait", rq, Kobject_dbg::pointer_to_id(thread), + thread, func, reply, target_cpu); } diff --git a/kernel/fiasco/src/kern/context_base.cpp b/kernel/fiasco/src/kern/context_base.cpp index aeb5f4e1..5ea22f66 100644 --- a/kernel/fiasco/src/kern/context_base.cpp +++ b/kernel/fiasco/src/kern/context_base.cpp @@ -17,34 +17,12 @@ public: // all start at offset 0 virtual ~Context_base() = 0; -protected: - Mword _state; -}; - -//--------------------------------------------------------------------------- -INTERFACE [mp]: - -EXTENSION class Context_base -{ protected: friend unsigned &__cpu_of(const void *); + Mword _state; unsigned _cpu; }; -//--------------------------------------------------------------------------- -IMPLEMENTATION [!mp]: - -inline -void set_cpu_of(const void *ptr, unsigned cpu) -{ (void)ptr; (void)cpu; } - -inline -unsigned cpu_of(const void *) -{ return 0; } - -inline -unsigned current_cpu() -{ return 0; } //--------------------------------------------------------------------------- IMPLEMENTATION: @@ -65,11 +43,6 @@ inline NEEDS [context_of, "processor.h"] Context *current() { return context_of((void *)Proc::stack_pointer()); } -//--------------------------------------------------------------------------- -IMPLEMENTATION [mp]: - -#include "config.h" - inline NEEDS ["config.h"] unsigned &__cpu_of(const void *ptr) { return reinterpret_cast(context_of(ptr))->_cpu; } @@ -83,6 +56,16 @@ inline NEEDS [__cpu_of] unsigned cpu_of(const void *ptr) { return __cpu_of(ptr); } +//--------------------------------------------------------------------------- +IMPLEMENTATION [!mp]: + +inline +unsigned current_cpu() +{ return 0; } + +//--------------------------------------------------------------------------- +IMPLEMENTATION [mp]: + inline NEEDS [current, cpu_of] unsigned current_cpu() { return cpu_of(current()); } diff --git a/kernel/fiasco/src/kern/cpu.cpp b/kernel/fiasco/src/kern/cpu.cpp index af9cd981..8d321862 100644 --- a/kernel/fiasco/src/kern/cpu.cpp +++ b/kernel/fiasco/src/kern/cpu.cpp @@ -8,7 +8,20 @@ class Cpu MEMBER_OFFSET(); public: - /** Get the locical ID of this CPU */ + struct By_phys_id + { + Unsigned32 _p; + By_phys_id(Unsigned32 p) : _p(p) {} + template + bool operator () (CPU const &c) const { return _p == c.phys_id(); } + }; + // we actually use a mask that has one CPU more that we can physically, + // have, to avoid lots of special cases for an invalid CPU number + typedef Cpu_mask_t Online_cpu_mask; + + enum { Invalid = Config::Max_num_cpus }; + + /** Get the logical ID of this CPU */ unsigned id() const; @@ -18,26 +31,16 @@ public: */ void set_online(bool o); - /** Get the physical ID of the CPU, for inter processor communication */ - unsigned phys_id() const; - /** Convienience for Cpu::cpus.cpu(cpu).online() */ static bool online(unsigned cpu); - /** - * Get logical CPU id from physical ID - * NOTE: This call is SLOW, use only for debugging/bootup - */ - static unsigned p2l(unsigned phys_id); - - static Cpu_mask const &online_mask(); - + static Online_cpu_mask const &online_mask(); private: /** Is this CPU online ? */ bool online() const; - static Cpu_mask _online_mask; + static Online_cpu_mask _online_mask; }; @@ -65,10 +68,10 @@ private: // -------------------------------------------------------------------------- IMPLEMENTATION: -Cpu_mask Cpu::_online_mask(Cpu_mask::Init::Bss); +Cpu::Online_cpu_mask Cpu::_online_mask(Online_cpu_mask::Init::Bss); IMPLEMENT inline -Cpu_mask const & +Cpu::Online_cpu_mask const & Cpu::online_mask() { return _online_mask; } @@ -97,16 +100,6 @@ Cpu::set_online(bool o) _online_mask.clear(_id); } -IMPLEMENT -unsigned -Cpu::p2l(unsigned phys_id) -{ - for (unsigned i = 0; i < Config::Max_num_cpus; ++i) - if (Per_cpu_data::valid(i) && Cpu::cpus.cpu(i).phys_id() == phys_id) - return i; - - return ~0U; -} IMPLEMENT static inline NEEDS["kdb_ke.h"] bool @@ -132,11 +125,6 @@ void Cpu::set_online(bool) {} -IMPLEMENT -unsigned -Cpu::p2l(unsigned) -{ return 0; } - IMPLEMENT static inline bool Cpu::online(unsigned _cpu) diff --git a/kernel/fiasco/src/kern/cpu_mask.cpp b/kernel/fiasco/src/kern/cpu_mask.cpp index e020d152..238bd26d 100644 --- a/kernel/fiasco/src/kern/cpu_mask.cpp +++ b/kernel/fiasco/src/kern/cpu_mask.cpp @@ -3,12 +3,17 @@ INTERFACE: #include "bitmap.h" #include "config.h" -class Cpu_mask +template +class Cpu_mask_t { public: + enum { Max_num_cpus = MAX_NUM_CPUS }; enum class Init { Bss }; - Cpu_mask(Init) {} - Cpu_mask() { _b.clear_all(); } + Cpu_mask_t(Init) {} + Cpu_mask_t() { _b.clear_all(); } + + Cpu_mask_t(Cpu_mask_t const &) = default; + Cpu_mask_t &operator = (Cpu_mask_t const &) = default; bool empty() const { return _b.is_empty(); } bool get(unsigned cpu) const { return _b[cpu]; } @@ -20,5 +25,7 @@ public: { return _b.atomic_get_and_clear(cpu); } private: - Bitmap _b; + Bitmap _b; }; + +typedef Cpu_mask_t Cpu_mask; diff --git a/kernel/fiasco/src/kern/dbg_page_info.cpp b/kernel/fiasco/src/kern/dbg_page_info.cpp index eb907bee..92e7f35c 100644 --- a/kernel/fiasco/src/kern/dbg_page_info.cpp +++ b/kernel/fiasco/src/kern/dbg_page_info.cpp @@ -98,7 +98,7 @@ Dbg_page_info * Dbg_page_info_table::operator [] (Page_number pfn) const { Entry &e = const_cast(this)->_tab[hash(pfn)]; - Lock_guard g(&e.l); + auto g = lock_guard(e.l); // we know that *end() is NULL return *find(e.h.begin(), e.h.end(), pfn); } @@ -108,7 +108,7 @@ void Dbg_page_info_table::insert(Dbg_page_info *i) { Entry *e = &_tab[hash(i->_pfn)]; - Lock_guardl)> g(&e->l); + auto g = lock_guard(e->l); e->h.add(i); } @@ -117,7 +117,7 @@ Dbg_page_info * Dbg_page_info_table::remove(Page_number pfn) { Entry *e = &_tab[hash(pfn)]; - Lock_guardl)> g(&e->l); + auto g = lock_guard(e->l); List::Iterator i = find(e->h.begin(), e->h.end(), pfn); if (i == e->h.end()) diff --git a/kernel/fiasco/src/kern/factory.cpp b/kernel/fiasco/src/kern/factory.cpp index 4261cae7..3c718bb4 100644 --- a/kernel/fiasco/src/kern/factory.cpp +++ b/kernel/fiasco/src/kern/factory.cpp @@ -75,7 +75,7 @@ PUBLIC void Factory::operator delete (void *_f) { Factory *f = (Factory*)_f; - LOG_TRACE("Factory delete", "fa del", ::current(), 0, {}); + LOG_TRACE("Factory delete", "fa del", ::current(), Tb_entry_empty, {}); if (!f->parent()) return; @@ -218,7 +218,7 @@ Factory::kinvoke(L4_obj_ref ref, Mword rights, Syscall_frame *f, // We take the existence_lock for syncronizing maps... // This is kind of coarse grained // try_lock fails if the lock is neither locked nor unlocked - if (!space_lock_guard.try_lock(&c_space->existence_lock)) + if (!space_lock_guard.check_and_lock(&c_space->existence_lock)) return commit_error(utcb, L4_error(L4_error::Overflow, L4_error::Rcv)); Lock_guard cpu_lock_guard(&cpu_lock); @@ -253,13 +253,12 @@ Factory::kinvoke(L4_obj_ref ref, Mword rights, Syscall_frame *f, return commit_result(-L4_err::ENodev); } - LOG_TRACE("Kobject create", "new", ::current(), __factory_log_fmt, - Log_entry *le = tbe->payload(); - le->op = utcb->values[0]; - le->buffer = buffer.obj_index(); - le->id = dbg_info()->dbg_id(); - le->ram = current(); - le->newo = new_o ? new_o->dbg_info()->dbg_id() : ~0); + LOG_TRACE("Kobject create", "new", ::current(), Log_entry, + l->op = utcb->values[0]; + l->buffer = buffer.obj_index(); + l->id = dbg_info()->dbg_id(); + l->ram = current(); + l->newo = new_o ? new_o->dbg_info()->dbg_id() : ~0); if (new_o) return map_obj(new_o, buffer.obj_index(), c_space, c_space); @@ -315,15 +314,15 @@ INTERFACE [debug]: EXTENSION class Factory { private: - struct Log_entry + struct Log_entry : public Tb_entry { Smword op; Mword buffer; Mword id; Mword ram; Mword newo; + unsigned print(int max, char *buf) const; }; - static unsigned log_fmt(Tb_entry *, int, char *) asm ("__factory_log_fmt"); }; // ------------------------------------------------------------------------ @@ -331,17 +330,17 @@ IMPLEMENTATION [debug]: IMPLEMENT unsigned -Factory::log_fmt(Tb_entry *e, int maxlen, char *buf) +Factory::Log_entry::print(int maxlen, char *buf) const { static char const *const ops[] = { /* 0 */ "gate", "irq", 0, 0, 0, 0, 0, 0, /* -8 */ 0, 0, 0, "task", "thread", 0, 0, "factory", /* -16 */ "vm", 0, 0, 0, "sem" }; - Log_entry *le = e->payload(); - char const *op = -le->op <= (int)(sizeof(ops)/sizeof(ops[0])) - ? ops[-le->op] : "invalid op"; - if (!op) - op = "(nan)"; + char const *_op = -op <= (int)(sizeof(ops)/sizeof(ops[0])) + ? ops[-op] : "invalid op"; + if (!_op) + _op = "(nan)"; - return snprintf(buf, maxlen, "factory=%lx [%s] new=%lx cap=[C:%lx] ram=%lx", le->id, op, le->newo, le->buffer, le->ram); + return snprintf(buf, maxlen, "factory=%lx [%s] new=%lx cap=[C:%lx] ram=%lx", + id, _op, newo, buffer, ram); } diff --git a/kernel/fiasco/src/kern/fpu.cpp b/kernel/fiasco/src/kern/fpu.cpp index 1a0c7f34..ac5c89ee 100644 --- a/kernel/fiasco/src/kern/fpu.cpp +++ b/kernel/fiasco/src/kern/fpu.cpp @@ -17,13 +17,9 @@ class Trap_state; class Fpu { public: - - static Context *owner(unsigned cpu); - static void set_owner(unsigned cpu, Context *owner); - static bool is_owner(unsigned cpu, Context *owner); - // all the following methods are arch dependent static void init(unsigned cpu) FIASCO_INIT_CPU; + static unsigned state_size(); static unsigned state_align(); static void init_state(Fpu_state *); @@ -32,42 +28,22 @@ public: static void disable(); static void enable(); + static Per_cpu fpu; + + Context *owner() const { return _owner; } + void set_owner(Context *owner) { _owner = owner; } + bool is_owner(Context *owner) const { return _owner == owner; } + private: Context *_owner; - - static Per_cpu _fpu; }; IMPLEMENTATION: #include "fpu_state.h" -DEFINE_PER_CPU Per_cpu Fpu::_fpu; +DEFINE_PER_CPU Per_cpu Fpu::fpu; -IMPLEMENT inline -Context * Fpu::owner(unsigned cpu) -{ - return _fpu.cpu(cpu)._owner; -} - -IMPLEMENT inline -void Fpu::set_owner(unsigned cpu, Context *owner) -{ - _fpu.cpu(cpu)._owner = owner; -} - -IMPLEMENT inline -bool Fpu::is_owner(unsigned cpu, Context *owner) -{ - return _fpu.cpu(cpu)._owner == owner; -} - -PUBLIC static inline -Fpu & -Fpu::fpu(unsigned cpu) -{ - return _fpu.cpu(cpu); -} //--------------------------------------------------------------------------- IMPLEMENTATION [!fpu]: diff --git a/kernel/fiasco/src/kern/helping_lock.cpp b/kernel/fiasco/src/kern/helping_lock.cpp index f229f04e..db644832 100644 --- a/kernel/fiasco/src/kern/helping_lock.cpp +++ b/kernel/fiasco/src/kern/helping_lock.cpp @@ -29,8 +29,6 @@ public: static bool threading_system_active; }; -typedef Lock_guard Helping_lock_guard; - #undef NO_INSTRUMENT #define NO_INSTRUMENT diff --git a/kernel/fiasco/src/kern/hpet.cpp b/kernel/fiasco/src/kern/hpet.cpp index 3f23b350..834b073a 100644 --- a/kernel/fiasco/src/kern/hpet.cpp +++ b/kernel/fiasco/src/kern/hpet.cpp @@ -64,7 +64,6 @@ public: return i; return ~0U; } - } __attribute__((packed)); class Hpet_device diff --git a/kernel/fiasco/src/kern/ia32/32/cpu-32.cpp b/kernel/fiasco/src/kern/ia32/32/cpu-32.cpp index 42fad374..ba23fc74 100644 --- a/kernel/fiasco/src/kern/ia32/32/cpu-32.cpp +++ b/kernel/fiasco/src/kern/ia32/32/cpu-32.cpp @@ -122,7 +122,6 @@ Address volatile & Cpu::kernel_sp() const { return *reinterpret_cast
(&get_tss()->_esp0); } - //---------------------------------------------------------------------------- IMPLEMENTATION[ia32]: @@ -130,11 +129,11 @@ PUBLIC static inline void Cpu:: set_cs() { - asm volatile ("ljmp %0,$1f ; 1:" - : : "i"(Gdt::gdt_code_kernel | Gdt::Selector_kernel)); + asm volatile("ljmp %0, $1f ; 1:" + : : "i"(Gdt::gdt_code_kernel | Gdt::Selector_kernel)); } -extern "C" void entry_vec08_dbf (); +extern "C" void entry_vec08_dbf(); extern "C" Address dbf_stack_top; PUBLIC FIASCO_INIT_CPU @@ -143,7 +142,7 @@ Cpu::init_tss_dbf(Address tss_dbf_mem, Address kdir) { tss_dbf = reinterpret_cast(tss_dbf_mem); - gdt->set_entry_byte(Gdt::gdt_tss_dbf/8, tss_dbf_mem, sizeof(Tss)-1, + gdt->set_entry_byte(Gdt::gdt_tss_dbf / 8, tss_dbf_mem, sizeof(Tss) - 1, Gdt_entry::Access_kernel | Gdt_entry::Access_tss | Gdt_entry::Accessed, 0); @@ -168,7 +167,7 @@ Cpu::init_tss(Address tss_mem, size_t tss_size) { tss = reinterpret_cast(tss_mem); - gdt->set_entry_byte(Gdt::gdt_tss/8, tss_mem, tss_size, + gdt->set_entry_byte(Gdt::gdt_tss / 8, tss_mem, tss_size, Gdt_entry::Access_kernel | Gdt_entry::Access_tss, 0); tss->set_ss0(Gdt::gdt_data_kernel); @@ -186,23 +185,20 @@ Cpu::init_gdt(Address gdt_mem, Address user_max) // cache line, respectively; pre-set all "accessed" flags so that // the CPU doesn't need to do this later - gdt->set_entry_4k(Gdt::gdt_code_kernel/8, 0, 0xffffffff, - Gdt_entry::Access_kernel | - Gdt_entry::Access_code_read | - Gdt_entry::Accessed, Gdt_entry::Size_32); - gdt->set_entry_4k(Gdt::gdt_data_kernel/8, 0, 0xffffffff, - Gdt_entry::Access_kernel | - Gdt_entry::Access_data_write | - Gdt_entry::Accessed, Gdt_entry::Size_32); - gdt->set_entry_4k(Gdt::gdt_code_user/8, 0, user_max, - Gdt_entry::Access_user | - Gdt_entry::Access_code_read | - Gdt_entry::Accessed, Gdt_entry::Size_32); - gdt->set_entry_4k(Gdt::gdt_data_user/8, 0, user_max, + gdt->set_entry_4k(Gdt::gdt_code_kernel / 8, 0, 0xffffffff, + Gdt_entry::Access_kernel | + Gdt_entry::Access_code_read | + Gdt_entry::Accessed, Gdt_entry::Size_32); + gdt->set_entry_4k(Gdt::gdt_data_kernel / 8, 0, 0xffffffff, + Gdt_entry::Access_kernel | + Gdt_entry::Access_data_write | + Gdt_entry::Accessed, Gdt_entry::Size_32); + gdt->set_entry_4k(Gdt::gdt_code_user / 8, 0, user_max, Gdt_entry::Access_user | - Gdt_entry::Access_data_write | - Gdt_entry::Accessed, Gdt_entry::Size_32); + Gdt_entry::Access_code_read | + Gdt_entry::Accessed, Gdt_entry::Size_32); + gdt->set_entry_4k(Gdt::gdt_data_user / 8, 0, user_max, + Gdt_entry::Access_user | + Gdt_entry::Access_data_write | + Gdt_entry::Accessed, Gdt_entry::Size_32); } - - - diff --git a/kernel/fiasco/src/kern/ia32/32/entry-native.S b/kernel/fiasco/src/kern/ia32/32/entry-native.S index d61d0610..5fb9958d 100644 --- a/kernel/fiasco/src/kern/ia32/32/entry-native.S +++ b/kernel/fiasco/src/kern/ia32/32/entry-native.S @@ -68,7 +68,7 @@ entry_vec01_debug: 2: mov 12(%esp), %esp pushl $(GDT_DATA_USER|SEL_PL_U) push %ebp - pushl $(EFLAGS_IOPL_U|EFLAGS_IF|EFLAGS_TF) + pushl $(EFLAGS_IF | EFLAGS_TF) pushl $(GDT_CODE_USER|SEL_PL_U) push %ebx cld @@ -181,8 +181,7 @@ entry_sys_fast_ipc_log: pop %esp pushl $(GDT_DATA_USER|SEL_PL_U) /* user ss */ pushl %ebp // user esp - // Fake user eflags, set IOPL to 3 - pushl $(EFLAGS_IOPL_U | EFLAGS_IF) + pushf // fake user eflags cld // Fake user cs. This cs value is never used with exception // that the thread is ex_regs'd before we leave with sysexit. @@ -230,8 +229,7 @@ entry_sys_fast_ipc_c: pop %esp pushl $(GDT_DATA_USER|SEL_PL_U) /* user ss */ pushl %ebp // push user SP (get in ebp) - // Fake user eflags, set IOPL to 3 - pushl $(EFLAGS_IOPL_U | EFLAGS_IF) + pushf // fake user eflags cld // Fake user cs. This cs value is never used with exception // that the thread is ex_regs'd before we leave with sysexit. diff --git a/kernel/fiasco/src/kern/ia32/32/tb_entry-ia32-32.cpp b/kernel/fiasco/src/kern/ia32/32/tb_entry-ia32-32.cpp index ae6aa88a..bb940e0a 100644 --- a/kernel/fiasco/src/kern/ia32/32/tb_entry-ia32-32.cpp +++ b/kernel/fiasco/src/kern/ia32/32/tb_entry-ia32-32.cpp @@ -1,6 +1,6 @@ INTERFACE [ia32,ux]: -EXTENSION class Tb_entry_base +EXTENSION class Tb_entry { public: enum @@ -9,35 +9,17 @@ public: }; }; -/** logged kernel event plus register content. */ -class Tb_entry_ke_reg : public Tb_entry -{ -private: - struct Payload - { - union { - char _msg[18]; ///< debug message - struct { - char _pad[3]; - const char *_m; - } _const_msg __attribute__((packed)); - }; - Mword _eax, _ecx, _edx; ///< registers - } __attribute__((packed)); -}; - /** logged trap. */ class Tb_entry_trap : public Tb_entry { private: - struct Payload - { - Unsigned8 _trapno; - Unsigned16 _error; - Mword _ebp, _cr2, _eax, _eflags, _esp; - Unsigned16 _cs, _ds; - } __attribute__((packed)); -}; + Unsigned8 _trapno; + Unsigned16 _error; + Mword _ebp, _cr2, _eax, _eflags, _esp; + Unsigned16 _cs, _ds; +public: + unsigned print(int max, char *buf) const; +} __attribute__((packed)); IMPLEMENTATION [ia32,ux]: @@ -48,136 +30,71 @@ void Tb_entry::rdtsc() { _tsc = Cpu::rdtsc(); } - - -PUBLIC inline -void -Tb_entry_ke_reg::set(Context const *ctx, Mword eip, Mword v1, Mword v2, Mword v3) -{ - set_global(Tbuf_ke_reg, ctx, eip); - payload()->_eax = v1; payload()->_ecx = v2; payload()->_edx = v3; -} - -PUBLIC inline NEEDS [] -void -Tb_entry_ke_reg::set(Context const *ctx, Mword eip, Trap_state *ts) -{ set(ctx, eip, ts->value(), ts->value2(), ts->value3()); } - -PUBLIC inline -void -Tb_entry_ke_reg::set_const(Context const *ctx, Mword eip, - const char * const msg, - Mword eax, Mword ecx, Mword edx) -{ - set(ctx, eip, eax, ecx, edx); - payload()->_msg[0] = 0; - payload()->_msg[1] = 1; - payload()->_const_msg._m = msg; -} - -PUBLIC inline -void -Tb_entry_ke_reg::set_buf(unsigned i, char c) -{ - if (i < sizeof(payload()->_msg) - 1) - payload()->_msg[i] = c >= ' ' ? c : '.'; -} - -PUBLIC inline -void -Tb_entry_ke_reg::term_buf(unsigned i) -{ payload()->_msg[i < sizeof(payload()->_msg)-1 ? i : sizeof(payload()->_msg)-1] = '\0'; } - -PUBLIC inline -const char * -Tb_entry_ke_reg::msg() const -{ - return payload()->_msg[0] == 0 && - payload()->_msg[1] == 1 ? payload()->_const_msg._m - : payload()->_msg; -} - -PUBLIC inline -Mword -Tb_entry_ke_reg::val1() const -{ return payload()->_eax; } - -PUBLIC inline -Mword -Tb_entry_ke_reg::val2() const -{ return payload()->_ecx; } - -PUBLIC inline -Mword -Tb_entry_ke_reg::val3() const -{ return payload()->_edx; } - - PUBLIC inline NEEDS ["trap_state.h"] void -Tb_entry_trap::set(Context const *ctx, Mword eip, Trap_state *ts) +Tb_entry_trap::set(Mword eip, Trap_state *ts) { - set_global(Tbuf_trap, ctx, eip); - payload()->_trapno = ts->_trapno; - payload()->_error = ts->_err; - payload()->_cr2 = ts->_cr2; - payload()->_eax = ts->_ax; - payload()->_cs = (Unsigned16)ts->cs(); - payload()->_ds = (Unsigned16)ts->_ds; - payload()->_esp = ts->sp(); - payload()->_eflags = ts->flags(); + _ip = eip; + _trapno = ts->_trapno; + _error = ts->_err; + _cr2 = ts->_cr2; + _eax = ts->_ax; + _cs = (Unsigned16)ts->cs(); + _ds = (Unsigned16)ts->_ds; + _esp = ts->sp(); + _eflags = ts->flags(); } PUBLIC inline void -Tb_entry_trap::set(Context const *ctx, Mword eip, Mword trapno) +Tb_entry_trap::set(Mword eip, Mword trapno) { - set_global(Tbuf_trap, ctx, eip); - payload()->_trapno = trapno; - payload()->_cs = 0; + _ip = eip; + _trapno = trapno; + _cs = 0; } PUBLIC inline Unsigned8 Tb_entry_trap::trapno() const -{ return payload()->_trapno; } +{ return _trapno; } PUBLIC inline Unsigned16 Tb_entry_trap::error() const -{ return payload()->_error; } +{ return _error; } PUBLIC inline Mword Tb_entry_trap::eax() const -{ return payload()->_eax; } +{ return _eax; } PUBLIC inline Mword Tb_entry_trap::cr2() const -{ return payload()->_cr2; } +{ return _cr2; } PUBLIC inline Mword Tb_entry_trap::ebp() const -{ return payload()->_ebp; } +{ return _ebp; } PUBLIC inline Unsigned16 Tb_entry_trap::cs() const -{ return payload()->_cs; } +{ return _cs; } PUBLIC inline Unsigned16 Tb_entry_trap::ds() const -{ return payload()->_ds; } +{ return _ds; } PUBLIC inline Mword Tb_entry_trap::sp() const -{ return payload()->_esp; } +{ return _esp; } PUBLIC inline Mword Tb_entry_trap::flags() const -{ return payload()->_eflags; } +{ return _eflags; } diff --git a/kernel/fiasco/src/kern/ia32/32/thread-dbf.cpp b/kernel/fiasco/src/kern/ia32/32/thread-dbf.cpp index 4b427057..fe3142a3 100644 --- a/kernel/fiasco/src/kern/ia32/32/thread-dbf.cpp +++ b/kernel/fiasco/src/kern/ia32/32/thread-dbf.cpp @@ -52,7 +52,7 @@ Thread::handle_double_fault (void) { puts ("Return reboots, \"k\" tries to enter the L4 kernel debugger..."); - while ((c=Kconsole::console()->getchar(false)) == -1) + while ((c = Kconsole::console()->getchar(false)) == -1) Proc::pause(); if (c == 'k' || c == 'K') diff --git a/kernel/fiasco/src/kern/ia32/32/thread-ia32-32.cpp b/kernel/fiasco/src/kern/ia32/32/thread-ia32-32.cpp index 3307b83a..1e45f9c6 100644 --- a/kernel/fiasco/src/kern/ia32/32/thread-ia32-32.cpp +++ b/kernel/fiasco/src/kern/ia32/32/thread-ia32-32.cpp @@ -127,7 +127,7 @@ Thread::copy_ts_to_utcb(L4_msg_tag const &, Thread *snd, Thread *rcv, Mword r = Utcb::Max_words; { - Lock_guard guard (&cpu_lock); + auto guard = lock_guard(cpu_lock); if (EXPECT_FALSE(snd->exception_triggered())) { Mem::memcpy_mwords (rcv_utcb->values, &ts->_gs, r > 12 ? 12 : r); @@ -289,7 +289,6 @@ Thread::invoke_arch(L4_msg_tag tag, Utcb *utcb) //--------------------------------------------------------------------------- IMPLEMENTATION [ia32 & (debug | kdb)]: -#include "ipi.h" #include "kernel_task.h" /** Call the nested trap handler (either Jdb::enter_kdebugger() or the @@ -298,14 +297,7 @@ PRIVATE static int Thread::call_nested_trap_handler(Trap_state *ts) { - unsigned long phys_cpu = Cpu::phys_id_direct(); - unsigned log_cpu = Cpu::p2l(phys_cpu); - if (log_cpu == ~0U) - { - printf("Trap on unknown CPU phys_id=%lx\n", phys_cpu); - log_cpu = 0; - } - + unsigned log_cpu = dbg_find_cpu(); unsigned long &ntr = nested_trap_recover.cpu(log_cpu); #if 0 @@ -364,8 +356,8 @@ Thread::call_nested_trap_handler(Trap_state *ts) "=d" (dummy3) : [ts] "a" (ts), [cpu] "d" (log_cpu), - [p] "r" (&p), - [ntr] "r" (&ntr) + [p] "S" (&p), + [ntr] "D" (&ntr) : "memory"); return ret == 0 ? 0 : -1; diff --git a/kernel/fiasco/src/kern/ia32/32/trap_state.cpp b/kernel/fiasco/src/kern/ia32/32/trap_state.cpp index a8289049..bbb1e6e9 100644 --- a/kernel/fiasco/src/kern/ia32/32/trap_state.cpp +++ b/kernel/fiasco/src/kern/ia32/32/trap_state.cpp @@ -247,3 +247,8 @@ trap_dump_panic(Trap_state *ts) ts->dump(); panic("terminated due to trap"); } + +PUBLIC inline +bool +Trap_state::exclude_logging() +{ return _trapno == 1 || _trapno == 3; } diff --git a/kernel/fiasco/src/kern/ia32/64/tb_entry-ia32-64.cpp b/kernel/fiasco/src/kern/ia32/64/tb_entry-ia32-64.cpp index a426111c..3131e420 100644 --- a/kernel/fiasco/src/kern/ia32/64/tb_entry-ia32-64.cpp +++ b/kernel/fiasco/src/kern/ia32/64/tb_entry-ia32-64.cpp @@ -1,6 +1,6 @@ INTERFACE [amd64]: -EXTENSION class Tb_entry_base +EXTENSION class Tb_entry { public: enum @@ -9,35 +9,17 @@ public: }; }; -/** logged kernel event plus register content. */ -class Tb_entry_ke_reg : public Tb_entry -{ -private: - struct Payload - { - union { - char _msg[19]; ///< debug message - struct { - char _pad[3]; - const char *_m; - } _const_msg __attribute__((packed)); - }; - Mword _rax, _rcx, _rdx; ///< registers - } __attribute__((packed)); -}; - /** logged trap. */ class Tb_entry_trap : public Tb_entry { private: - struct Payload - { - char _trapno; - Unsigned16 _error; - Mword _rbp, _cr2, _rax, _rflags, _rsp; - Unsigned16 _cs, _ds; - } __attribute__((packed)); -}; + char _trapno; + Unsigned16 _error; + Mword _rbp, _cr2, _rax, _rflags, _rsp; + Unsigned16 _cs, _ds; +public: + unsigned print(int max, char *buf) const; +} __attribute__((packed)); IMPLEMENTATION [amd64]: @@ -48,136 +30,71 @@ void Tb_entry::rdtsc() { _tsc = Cpu::rdtsc(); } - - -PUBLIC inline -void -Tb_entry_ke_reg::set(Context const *ctx, Mword rip, Mword v1, Mword v2, Mword v3) -{ - set_global(Tbuf_ke_reg, ctx, rip); - payload()->_rax = v1; payload()->_rcx = v2; payload()->_rdx = v3; -} - -PUBLIC inline NEEDS [] -void -Tb_entry_ke_reg::set(Context const *ctx, Mword rip, Trap_state *ts) -{ set(ctx, rip, ts->_ax, ts->_cx, ts->_dx); } - -PUBLIC inline -void -Tb_entry_ke_reg::set_const(Context const *ctx, Mword rip, - const char * const msg, - Mword rax, Mword rcx, Mword rdx) -{ - set(ctx, rip, rax, rcx, rdx); - payload()->_msg[0] = 0; - payload()->_msg[1] = 1; - payload()->_const_msg._m = msg; -} - -PUBLIC inline -void -Tb_entry_ke_reg::set_buf(unsigned i, char c) -{ - if (i < sizeof(payload()->_msg) - 1) - payload()->_msg[i] = c >= ' ' ? c : '.'; -} - -PUBLIC inline -void -Tb_entry_ke_reg::term_buf(unsigned i) -{ payload()->_msg[i < sizeof(payload()->_msg)-1 ? i : sizeof(payload()->_msg)-1] = '\0'; } - -PUBLIC inline -const char * -Tb_entry_ke_reg::msg() const -{ - return payload()->_msg[0] == 0 && - payload()->_msg[1] == 1 ? payload()->_const_msg._m - : payload()->_msg; -} - -PUBLIC inline -Mword -Tb_entry_ke_reg::val1() const -{ return payload()->_rax; } - -PUBLIC inline -Mword -Tb_entry_ke_reg::val2() const -{ return payload()->_rcx; } - -PUBLIC inline -Mword -Tb_entry_ke_reg::val3() const -{ return payload()->_rdx; } - - PUBLIC inline NEEDS ["trap_state.h"] void -Tb_entry_trap::set(Context const *ctx, Mword rip, Trap_state *ts) +Tb_entry_trap::set(Mword rip, Trap_state *ts) { - set_global(Tbuf_trap, ctx, rip); - payload()->_trapno = ts->_trapno; - payload()->_error = ts->_err; - payload()->_cr2 = ts->_cr2; - payload()->_rax = ts->_ax; - payload()->_cs = (Unsigned16)ts->cs(); - payload()->_rsp = ts->sp(); - payload()->_rflags = ts->flags(); + _ip = rip; + _trapno = ts->_trapno; + _error = ts->_err; + _cr2 = ts->_cr2; + _rax = ts->_ax; + _cs = (Unsigned16)ts->cs(); + _rsp = ts->sp(); + _rflags = ts->flags(); } PUBLIC inline void -Tb_entry_trap::set(Context const *ctx, Mword eip, Mword trapno) +Tb_entry_trap::set(Mword eip, Mword trapno) { - set_global(Tbuf_trap, ctx, eip); - payload()->_trapno = trapno | 0x80; + _ip = eip; + _trapno = trapno | 0x80; } PUBLIC inline char Tb_entry_trap::trapno() const -{ return payload()->_trapno; } +{ return _trapno; } PUBLIC inline Unsigned16 Tb_entry_trap::error() const -{ return payload()->_error; } +{ return _error; } PUBLIC inline Mword Tb_entry_trap::eax() const -{ return payload()->_rax; } +{ return _rax; } PUBLIC inline Mword Tb_entry_trap::cr2() const -{ return payload()->_cr2; } +{ return _cr2; } PUBLIC inline Mword Tb_entry_trap::ebp() const -{ return payload()->_rbp; } +{ return _rbp; } PUBLIC inline Unsigned16 Tb_entry_trap::cs() const -{ return payload()->_cs; } +{ return _cs; } PUBLIC inline Unsigned16 Tb_entry_trap::ds() const -{ return payload()->_ds; } +{ return _ds; } PUBLIC inline Mword Tb_entry_trap::sp() const -{ return payload()->_rsp; } +{ return _rsp; } PUBLIC inline Mword Tb_entry_trap::flags() const -{ return payload()->_rflags; } +{ return _rflags; } diff --git a/kernel/fiasco/src/kern/ia32/64/thread-ia32-64.cpp b/kernel/fiasco/src/kern/ia32/64/thread-ia32-64.cpp index 73aa5eef..9dfd0374 100644 --- a/kernel/fiasco/src/kern/ia32/64/thread-ia32-64.cpp +++ b/kernel/fiasco/src/kern/ia32/64/thread-ia32-64.cpp @@ -17,7 +17,7 @@ Thread::fast_return_to_user(Mword ip, Mword sp, T arg) ("mov %0, %%rsp \t\n" "iretq \t\n" : - : "r" (static_cast(regs())), "d"(arg) + : "r" (static_cast(regs())), "D"(arg) ); __builtin_trap(); } @@ -132,7 +132,7 @@ Thread::copy_ts_to_utcb(L4_msg_tag const &, Thread *snd, Thread *rcv, Trap_state *ts = (Trap_state*)snd->_utcb_handler; Utcb *rcv_utcb = rcv->utcb().access(); { - Lock_guard guard (&cpu_lock); + auto guard = lock_guard(cpu_lock); if (EXPECT_FALSE(snd->exception_triggered())) { Mem::memcpy_mwords (rcv_utcb->values, ts, 19); @@ -205,14 +205,7 @@ Thread::call_nested_trap_handler(Trap_state *ts) { Proc::cli(); - unsigned long phys_cpu = Cpu::phys_id_direct(); - unsigned log_cpu = Cpu::p2l(phys_cpu); - if (log_cpu == ~0U) - { - printf("Trap on unknown CPU phys_id=%lx\n", phys_cpu); - log_cpu = 0; - } - + unsigned log_cpu = dbg_find_cpu(); unsigned long &ntr = nested_trap_recover.cpu(log_cpu); #if 0 diff --git a/kernel/fiasco/src/kern/ia32/64/trap_state-amd64.cpp b/kernel/fiasco/src/kern/ia32/64/trap_state-amd64.cpp index 2bba048f..b6e871de 100644 --- a/kernel/fiasco/src/kern/ia32/64/trap_state-amd64.cpp +++ b/kernel/fiasco/src/kern/ia32/64/trap_state-amd64.cpp @@ -235,3 +235,8 @@ trap_dump_panic(Trap_state *ts) ts->dump(); panic("terminated due to trap"); } + +PUBLIC inline +bool +Trap_state::exclude_logging() +{ return _trapno == 1 || _trapno == 3; } diff --git a/kernel/fiasco/src/kern/ia32/apic-ia32-mp.cpp b/kernel/fiasco/src/kern/ia32/apic-ia32-mp.cpp index 67519263..42ca49cb 100644 --- a/kernel/fiasco/src/kern/ia32/apic-ia32-mp.cpp +++ b/kernel/fiasco/src/kern/ia32/apic-ia32-mp.cpp @@ -36,13 +36,6 @@ IMPLEMENTATION[mp]: #include "cpu.h" #include "processor.h" -PUBLIC static inline -Signed32 -Apic::apic_id() -{ - return ((reg_read(APIC_ID) >> 24) & 0xff); -} - PUBLIC static inline void Apic::disable_external_ints() diff --git a/kernel/fiasco/src/kern/ia32/apic-ia32.cpp b/kernel/fiasco/src/kern/ia32/apic-ia32.cpp index ef7ed5a1..566f66f7 100644 --- a/kernel/fiasco/src/kern/ia32/apic-ia32.cpp +++ b/kernel/fiasco/src/kern/ia32/apic-ia32.cpp @@ -1,5 +1,6 @@ INTERFACE: +#include "per_cpu_data.h" #include "types.h" #include "initcalls.h" @@ -10,10 +11,18 @@ class Apic { public: static void init() FIASCO_INIT; + Unsigned32 apic_id() const { return _id; } + Unsigned32 cpu_id() const { return _id >> 24; } + + static Per_cpu > apic; private: - Apic(); // default constructors are undefined - Apic(const Apic&); + Apic(const Apic&) = delete; + Apic &operator = (Apic const &) = delete; + + Unsigned32 _id; + + static void error_interrupt(Return_frame *regs) asm ("apic_error_interrupt") FIASCO_FASTCALL; @@ -92,10 +101,32 @@ extern unsigned apic_error_cnt; IMPLEMENTATION: #include "cpu.h" +DEFINE_PER_CPU Per_cpu > Apic::apic; + +PUBLIC inline +Apic::Apic() : _id(get_id()) {} + + PRIVATE static Cpu & Apic::cpu() { return *Cpu::boot_cpu(); } +// FIXME: workaround for missing lambdas in gcc < 4.5 +namespace { +struct By_id +{ + Unsigned32 p; + By_id(Unsigned32 p) : p(p) {} + bool operator () (Apic const *a) const { return a->apic_id() == p; } +}; +} + +PUBLIC static +unsigned +Apic::find_cpu(Unsigned32 phys_id) +{ + return apic.find_cpu(By_id(phys_id)); +} //---------------------------------------------------------------------------- IMPLEMENTATION[ia32]: @@ -461,7 +492,7 @@ Apic::check_working() timer_set_divisor(1); timer_reg_write(0x10000000); - tsc_until = Cpu::rdtsc() + 0x100; // we only have to wait for one bus cycle + tsc_until = Cpu::rdtsc() + 0x200; // we only have to wait for one bus cycle do { @@ -538,7 +569,7 @@ void Apic::route_pic_through_apic() { Unsigned32 tmp_val; - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); // mask 8259 interrupts Pic::Status old_irqs = Pic::disable_all_save(); @@ -566,7 +597,7 @@ void Apic::init_lvt() { Unsigned32 tmp_val; - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); // mask timer interrupt and set vector to _not_ invalid value tmp_val = reg_read(APIC_lvtt); @@ -677,7 +708,7 @@ Apic::calibrate_timer() timer_reg_write(1000000000); { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); Pit::setup_channel2_to_20hz(); diff --git a/kernel/fiasco/src/kern/ia32/cpu-ia32.cpp b/kernel/fiasco/src/kern/ia32/cpu-ia32.cpp index 5d080e28..a736075a 100644 --- a/kernel/fiasco/src/kern/ia32/cpu-ia32.cpp +++ b/kernel/fiasco/src/kern/ia32/cpu-ia32.cpp @@ -159,7 +159,7 @@ public: Address volatile &kernel_sp() const; public: - static Per_cpu cpus asm ("CPUS_BASE"); + static Per_cpu cpus; static Cpu *boot_cpu() { return _boot_cpu; } static bool have_superpages() { return boot_cpu()->superpages(); } @@ -957,6 +957,7 @@ Cpu::identify() // Check for Alignment Check Support set_flags(eflags ^ EFLAGS_AC); + // FIXME: must not panic at cpu hotplug if (((get_flags() ^ eflags) & EFLAGS_AC) == 0) panic("CPU too old"); @@ -1089,11 +1090,25 @@ Cpu::busy_wait_ns(Unsigned64 ns) Proc::pause(); } +PUBLIC +bool +Cpu::if_show_infos() const +{ + return id() == 0 + || !boot_cpu() + || family() != boot_cpu()->family() + || model() != boot_cpu()->model() + || stepping() != boot_cpu()->stepping() + || brand() != boot_cpu()->brand(); +} PUBLIC void Cpu::show_cache_tlb_info(const char *indent) const { + if (!if_show_infos()) + return; + char s[16]; *s = '\0'; @@ -1150,7 +1165,7 @@ Cpu::show_cache_tlb_info(const char *indent) const } IMPLEMENT -void +void Cpu::disable(unsigned cpu, char const *reason) { printf("CPU%u: is disabled: %s\n", cpu, reason); @@ -1539,10 +1554,12 @@ PUBLIC void Cpu::print() const { - printf ("CPU[%u:%u]: %s (%X:%X:%X:%X)[%08x] Model: %s at %llu MHz\n\n", - id(), phys_id() >> 24, - vendor_str(), family(), model(), stepping(), brand(), _version, model_str(), - div32(frequency(), 1000000)); + if (if_show_infos()) + printf("CPU[%u]: %s (%X:%X:%X:%X)[%08x] Model: %s at %lluMHz\n\n", + id(), + vendor_str(), family(), model(), stepping(), brand(), + _version, model_str(), + div32(frequency(), 1000000)); } PUBLIC @@ -1551,7 +1568,7 @@ Cpu::set_sysenter(void (*func)(void)) { // Check for Sysenter/Sysexit Feature if (sysenter()) - wrmsr ((Mword) func, 0, MSR_SYSENTER_EIP); + wrmsr((Mword) func, 0, MSR_SYSENTER_EIP); } @@ -1582,7 +1599,7 @@ Cpu::init_sysenter() // Return 2^32 / (tsc clocks per usec) FIASCO_INIT_CPU void -Cpu::calibrate_tsc () +Cpu::calibrate_tsc() { const unsigned calibrate_time = 50000 /*us*/ + 1; @@ -1643,6 +1660,7 @@ Cpu::calibrate_tsc () return; bad_ctc: + // FIXME: must not panic at cpu hotplug if (Config::Kip_timer_uses_rdtsc) panic("Can't calibrate tsc"); } @@ -1692,16 +1710,3 @@ void Cpu::set_gs(Unsigned32 val) { asm volatile ("mov %0, %%gs" : : "rm" (val)); } -IMPLEMENT inline -unsigned -Cpu::phys_id() const -{ return _brand & 0xff000000; } - -PUBLIC static -unsigned -Cpu::phys_id_direct() -{ - Unsigned32 a,b,c,d; - cpuid (1, &a, &b, &c, &d); - return b & 0xff000000; -} diff --git a/kernel/fiasco/src/kern/ia32/fpu-ia32-ux.cpp b/kernel/fiasco/src/kern/ia32/fpu-ia32-ux.cpp index 1c851689..342a0a30 100644 --- a/kernel/fiasco/src/kern/ia32/fpu-ia32-ux.cpp +++ b/kernel/fiasco/src/kern/ia32/fpu-ia32-ux.cpp @@ -118,7 +118,9 @@ Fpu::init(unsigned cpu) disable(); // At first, noone owns the FPU - set_owner(cpu, 0); + Fpu &f = Fpu::fpu.cpu(cpu); + + f.set_owner(0); init_disable(); @@ -137,19 +139,19 @@ Fpu::init(unsigned cpu) Unsigned32 eax, ecx, edx; Cpu::cpus.cpu(cpu).cpuid_0xd(0, &eax, &cpu_size, &ecx, &edx); cpu_align = 64; - fpu(cpu)._variant = Variant_xsave; + f._variant = Variant_xsave; } else if (Cpu::have_fxsr()) { cpu_size = sizeof(sse_regs); cpu_align = 16; - fpu(cpu)._variant = Variant_fxsr; + f._variant = Variant_fxsr; } else { cpu_size = sizeof(fpu_regs); cpu_align = 4; - fpu(cpu)._variant = Variant_fpu; + f._variant = Variant_fpu; } if (cpu_size > _state_size) diff --git a/kernel/fiasco/src/kern/ia32/fpu-ia32.cpp b/kernel/fiasco/src/kern/ia32/fpu-ia32.cpp index 6f1229ba..059603a6 100644 --- a/kernel/fiasco/src/kern/ia32/fpu-ia32.cpp +++ b/kernel/fiasco/src/kern/ia32/fpu-ia32.cpp @@ -54,7 +54,7 @@ Fpu::save_state(Fpu_state *s) // Both fxsave and fnsave are non-waiting instructions and thus // cannot cause exception #16 for pending FPU exceptions. - switch (fpu(current_cpu())._variant) + switch (fpu.current()._variant) { case Variant_xsave: asm volatile("xsave (%2)" : : "a" (~0UL), "d" (~0UL), "r" (s->state_buffer()) : "memory"); @@ -80,9 +80,9 @@ Fpu::restore_state(Fpu_state *s) // Only fxrstor is a non-waiting instruction and thus // cannot cause exception #16 for pending FPU exceptions. - unsigned cpu = current_cpu(); + Fpu &f = fpu.current(); - switch (fpu(cpu)._variant) + switch (f._variant) { case Variant_xsave: asm volatile ("xrstor (%2)" : : "a" (~0UL), "d" (~0UL), "r" (s->state_buffer())); @@ -119,7 +119,7 @@ Fpu::restore_state(Fpu_state *s) // invoked fnsave which re-initialized the FPU and cleared exceptions // 2) Otherwise we call fnclex instead to clear exceptions. - if (!Fpu::owner(cpu)) + if (!f.owner()) asm volatile ("fnclex"); asm volatile ("frstor (%0)" : : "r" (s->state_buffer())); diff --git a/kernel/fiasco/src/kern/ia32/io_apic.cpp b/kernel/fiasco/src/kern/ia32/io_apic.cpp index 6ac6a299..dfe94e6b 100644 --- a/kernel/fiasco/src/kern/ia32/io_apic.cpp +++ b/kernel/fiasco/src/kern/ia32/io_apic.cpp @@ -4,6 +4,7 @@ INTERFACE: #include "initcalls.h" #include #include "irq_chip_ia32.h" +#include class Acpi_madt; @@ -21,26 +22,20 @@ public: Io_apic_entry() {} Io_apic_entry(Unsigned8 vector, Delivery d, Dest_mode dm, Polarity p, - Trigger t, Unsigned8 dest) - : _e(vector | (d << 8) | (dm << 11) | (p << 13) | (t << 15) | (1<<16) - | (((Unsigned64)dest) << 56)) + Trigger t, Unsigned32 dest) + : _e( vector_bfm_t::val(vector) | delivery_bfm_t::val(d) | mask_bfm_t::val(1) + | dest_mode_bfm_t::val(dm) | polarity_bfm_t::val(p) + | trigger_bfm_t::val(t) | dest_bfm_t::val(dest >> 24)) {} - unsigned delivery() const { return (_e >> 8) & 7; } - void delivery(unsigned m) { _e = (_e & ~(7 << 8)) | ((m & 7) << 8); } - unsigned dest_mode() const { return _e & (1 << 11); } - void dest_mode(bool p) { _e = (_e & ~(1<<11)) | ((unsigned long)p << 11); } - unsigned dest() const { return _e >> 56; } - void dest(unsigned d) { _e = (_e & ~(0xffULL << 56)) | ((Unsigned64)d << 56); } - unsigned mask() const { return _e & (1U << 16); } - void mask(bool m) { _e = (_e & ~(1ULL << 16)) | ((Unsigned64)m << 16); } - unsigned trigger() const { return _e & (1 << 15); } - unsigned polarity() const { return _e & (1 << 13); } - unsigned vector() const { return _e & 0xff; } - void vector(Unsigned8 v) { _e = (_e & ~0xff) | v; } - void trigger(Mword tr) { _e = (_e & ~(1UL << 15)) | ((tr & 1) << 15); } - void polarity(Mword pl) { _e = (_e & ~(1UL << 13)) | ((pl & 1) << 13); } -} __attribute__((packed)); + CXX_BITFIELD_MEMBER( 0, 7, vector, _e); + CXX_BITFIELD_MEMBER( 8, 10, delivery, _e); + CXX_BITFIELD_MEMBER(11, 11, dest_mode, _e); + CXX_BITFIELD_MEMBER(13, 13, polarity, _e); + CXX_BITFIELD_MEMBER(15, 15, trigger, _e); + CXX_BITFIELD_MEMBER(16, 16, mask, _e); + CXX_BITFIELD_MEMBER(56, 63, dest, _e); +}; class Io_apic : public Irq_chip_ia32 @@ -166,7 +161,7 @@ PUBLIC inline NEEDS["kdb_ke.h", "lock_guard.h"] Io_apic_entry Io_apic::read_entry(unsigned i) { - Lock_guard g(&_l); + auto g = lock_guard(_l); Io_apic_entry e; //assert_kdb(i <= num_entries()); e._e = (Unsigned64)_apic->read(0x10+2*i) | (((Unsigned64)_apic->read(0x11+2*i)) << 32); @@ -178,7 +173,7 @@ PUBLIC inline NEEDS["kdb_ke.h", "lock_guard.h"] void Io_apic::write_entry(unsigned i, Io_apic_entry const &e) { - Lock_guard g(&_l); + auto g = lock_guard(_l); //assert_kdb(i <= num_entries()); _apic->write(0x10+2*i, e._e); _apic->write(0x11+2*i, e._e >> 32); @@ -186,7 +181,7 @@ Io_apic::write_entry(unsigned i, Io_apic_entry const &e) PUBLIC static FIASCO_INIT bool -Io_apic::init() +Io_apic::init(unsigned cpu) { _madt = Acpi::find("APIC"); @@ -226,7 +221,8 @@ Io_apic::init() { int v = 0x20+i; Io_apic_entry e(v, Io_apic_entry::Fixed, Io_apic_entry::Physical, - Io_apic_entry::High_active, Io_apic_entry::Edge, 0); + Io_apic_entry::High_active, Io_apic_entry::Edge, + ::Apic::apic.cpu(cpu)->apic_id()); apic->write_entry(i, e); } @@ -305,8 +301,8 @@ Io_apic::dump() Io_apic_entry e = read_entry(i); printf(" PIN[%2u%c]: vector=%2x, del=%u, dm=%s, dest=%u (%s, %s)\n", i, e.mask() ? 'm' : '.', - e.vector(), e.delivery(), e.dest_mode() ? "logical" : "physical", - e.dest(), + (unsigned)e.vector(), (unsigned)e.delivery(), e.dest_mode() ? "logical" : "physical", + (unsigned)e.dest(), e.polarity() ? "low" : "high", e.trigger() ? "level" : "edge"); } @@ -321,7 +317,7 @@ PRIVATE inline NEEDS["kdb_ke.h", "lock_guard.h"] void Io_apic::_mask(unsigned irq) { - Lock_guard g(&_l); + auto g = lock_guard(_l); //assert_kdb(irq <= _apic->num_entries()); _apic->modify(0x10 + irq * 2, 1UL << 16, 0); } @@ -330,7 +326,7 @@ PRIVATE inline NEEDS["kdb_ke.h", "lock_guard.h"] void Io_apic::_unmask(unsigned irq) { - Lock_guard g(&_l); + auto g = lock_guard(_l); //assert_kdb(irq <= _apic->num_entries()); _apic->modify(0x10 + irq * 2, 0, 1UL << 16); } @@ -339,7 +335,7 @@ PUBLIC inline NEEDS["kdb_ke.h", "lock_guard.h"] bool Io_apic::masked(unsigned irq) { - Lock_guard g(&_l); + auto g = lock_guard(_l); //assert_kdb(irq <= _apic->num_entries()); return _apic->read(0x10 + irq * 2) & (1UL << 16); } @@ -355,7 +351,7 @@ PUBLIC inline NEEDS["kdb_ke.h", "lock_guard.h"] void Io_apic::set_dest(unsigned irq, Mword dst) { - Lock_guard g(&_l); + auto g = lock_guard(_l); //assert_kdb(irq <= _apic->num_entries()); _apic->modify(0x11 + irq * 2, dst & (~0UL << 24), ~0UL << 24); } @@ -406,7 +402,7 @@ Io_apic::unmask(Mword irq) PUBLIC void Io_apic::set_cpu(Mword irq, unsigned cpu) { - set_dest(irq, Cpu::cpus.cpu(cpu).phys_id()); + set_dest(irq, ::Apic::apic.cpu(cpu)->apic_id()); } static inline @@ -432,8 +428,8 @@ Io_apic::set_mode(Mword pin, unsigned mode) mode = Irq_base::Polarity_low; Io_apic_entry e = read_entry(pin); - e.polarity(to_io_apic_polarity(mode)); - e.trigger(to_io_apic_trigger(mode)); + e.polarity() = to_io_apic_polarity(mode); + e.trigger() = to_io_apic_trigger(mode); write_entry(pin, e); return mode; } @@ -448,7 +444,7 @@ Io_apic::alloc(Irq_base *irq, Mword pin) return false; Io_apic_entry e = read_entry(pin); - e.vector(v); + e.vector() = v; write_entry(pin, e); return true; } diff --git a/kernel/fiasco/src/kern/ia32/kmem-ia32.cpp b/kernel/fiasco/src/kern/ia32/kmem-ia32.cpp index d9c8d390..834ee845 100644 --- a/kernel/fiasco/src/kern/ia32/kmem-ia32.cpp +++ b/kernel/fiasco/src/kern/ia32/kmem-ia32.cpp @@ -145,7 +145,7 @@ Device_map::map(Address phys, bool /*cache*/) unsigned idx = lookup_idx(phys); if (idx != ~0U) return (Virt_base + idx * Config::SUPERPAGE_SIZE) - | (phys & ~(~0UL << Config::SUPERPAGE_SHIFT)); + | (phys & ~(~0UL << Config::SUPERPAGE_SHIFT)); Address p = phys & (~0UL << Config::SUPERPAGE_SHIFT); Kmem_alloc *const alloc = Kmem_alloc::allocator(); @@ -153,14 +153,15 @@ Device_map::map(Address phys, bool /*cache*/) if (_map[i] == ~0UL) { Kmem::kdir->map(p, - Virt_addr(Virt_base + (i*Config::SUPERPAGE_SIZE)), - Virt_size(Config::SUPERPAGE_SIZE), - Pt_entry::Dirty | Pt_entry::Writable | Pt_entry::Referenced, - Pdir::super_level(), pdir_alloc(alloc)); + Virt_addr(Virt_base + (i * Config::SUPERPAGE_SIZE)), + Virt_size(Config::SUPERPAGE_SIZE), + Pt_entry::Dirty | Pt_entry::Writable + | Pt_entry::Referenced, + Pdir::super_level(), pdir_alloc(alloc)); _map[i] = p; - return (Virt_base + (i*Config::SUPERPAGE_SIZE)) - | (phys & ~(~0UL << Config::SUPERPAGE_SHIFT)); + return (Virt_base + (i * Config::SUPERPAGE_SIZE)) + | (phys & ~(~0UL << Config::SUPERPAGE_SHIFT)); } return ~0UL; @@ -205,7 +206,7 @@ Kmem::io_bitmap_delimiter_page() * @return corresponding physical address if a mappings exists. * -1 otherwise. */ -IMPLEMENT inline NEEDS["paging.h","std_macros.h","mem_layout.h"] +IMPLEMENT inline NEEDS["paging.h", "std_macros.h", "mem_layout.h"] Address Kmem::virt_to_phys(const void *addr) { @@ -227,7 +228,7 @@ Address Kmem::map_phys_page_tmp(Address phys, Mword idx) { unsigned long pte = phys & Pt_entry::Pfn; - Address virt; + Address virt; switch (idx) { @@ -240,9 +241,9 @@ Kmem::map_phys_page_tmp(Address phys, Mword idx) if (pte != tmp_phys_pte[idx]) { - // map two consecutive pages as to be able to access - map_phys_page(phys, virt, false, true); - map_phys_page(phys+0x1000, virt+0x1000, false, true); + // map two consecutive pages as to be able to access + map_phys_page(phys, virt, false, true); + map_phys_page(phys + 0x1000, virt + 0x1000, false, true); tmp_phys_pte[idx] = pte; } @@ -358,14 +359,14 @@ Kmem::init_mmu() kdir->map(Mem_layout::Kernel_image_phys, Virt_addr(Mem_layout::Kernel_image), Virt_size(Config::SUPERPAGE_SIZE), - Pt_entry::Dirty | Pt_entry::Writable | Pt_entry::Referenced + Pt_entry::Dirty | Pt_entry::Writable | Pt_entry::Referenced | Pt_entry::global(), Pdir::super_level(), pdir_alloc(alloc)); if (!Mem_layout::Adap_in_kernel_image) kdir->map(Mem_layout::Adap_image_phys, Virt_addr(Mem_layout::Adap_image), Virt_size(Config::SUPERPAGE_SIZE), - Pt_entry::Dirty | Pt_entry::Writable | Pt_entry::Referenced + Pt_entry::Dirty | Pt_entry::Writable | Pt_entry::Referenced | Pt_entry::global(), Pdir::super_level(), pdir_alloc(alloc)); // map the last 64MB of physical memory as kernel memory @@ -389,8 +390,7 @@ Kmem::init_mmu() assert((Mem_layout::Io_bitmap & ~Config::SUPERPAGE_MASK) == 0); - long cpu_page_size - = 0x10 + Config::Max_num_cpus * (sizeof(Tss) + 256); + long cpu_page_size = 0x10 + Config::Max_num_cpus * (sizeof(Tss) + 256); if (cpu_page_size < Config::PAGE_SIZE) cpu_page_size = Config::PAGE_SIZE; @@ -407,12 +407,12 @@ Kmem::init_mmu() *(kdir->walk(Virt_addr(Mem_layout::Io_bitmap - Config::SUPERPAGE_SIZE), Pdir::Super_level, pdir_alloc(alloc)).e) = (pmem_cpu_page & Config::SUPERPAGE_MASK) - | Pt_entry::Pse_bit - | Pt_entry::Writable | Pt_entry::Referenced - | Pt_entry::Dirty | Pt_entry::global() | Pt_entry::Valid; + | Pt_entry::Pse_bit + | Pt_entry::Writable | Pt_entry::Referenced + | Pt_entry::Dirty | Pt_entry::global() | Pt_entry::Valid; cpu_page_vm = (pmem_cpu_page & ~Config::SUPERPAGE_MASK) - + (Mem_layout::Io_bitmap - Config::SUPERPAGE_SIZE); + + (Mem_layout::Io_bitmap - Config::SUPERPAGE_SIZE); } else { @@ -431,22 +431,21 @@ Kmem::init_mmu() cpu_page_vm = Mem_layout::Io_bitmap - Config::PAGE_SIZE * i; } - // the IO bitmap must be followed by one byte containing 0xff - // if this byte is not present, then one gets page faults - // (or general protection) when accessing the last port - // at least on a Pentium 133. - // - // Therefore we write 0xff in the first byte of the cpu_page - // and map this page behind every IO bitmap - io_bitmap_delimiter = - reinterpret_cast(cpu_page_vm); + // the IO bitmap must be followed by one byte containing 0xff + // if this byte is not present, then one gets page faults + // (or general protection) when accessing the last port + // at least on a Pentium 133. + // + // Therefore we write 0xff in the first byte of the cpu_page + // and map this page behind every IO bitmap + io_bitmap_delimiter = reinterpret_cast(cpu_page_vm); - cpu_page_vm += 0x10; + cpu_page_vm += 0x10; - // did we really get the first byte ?? - assert((reinterpret_cast
(io_bitmap_delimiter) - & ~Config::PAGE_MASK) == 0); - *io_bitmap_delimiter = 0xff; + // did we really get the first byte ?? + assert((reinterpret_cast
(io_bitmap_delimiter) + & ~Config::PAGE_MASK) == 0); + *io_bitmap_delimiter = 0xff; } @@ -454,12 +453,11 @@ PUBLIC static FIASCO_INIT_CPU void Kmem::init_cpu(Cpu &cpu) { - void *cpu_mem = Kmem_alloc::allocator()->unaligned_alloc(1024); printf("Allocate cpu_mem @ %p\n", cpu_mem); - + // now initialize the global descriptor table - cpu.init_gdt (__alloc(&cpu_mem, Gdt::gdt_max), user_max()); + cpu.init_gdt(__alloc(&cpu_mem, Gdt::gdt_max), user_max()); // Allocate the task segment as the last thing from cpu_page_vm // because with IO protection enabled the task segment includes the @@ -468,12 +466,12 @@ Kmem::init_cpu(Cpu &cpu) // Allocate additional 256 bytes for emergency stack right beneath // the tss. It is needed if we get an NMI or debug exception at // entry_sys_fast_ipc/entry_sys_fast_ipc_c/entry_sys_fast_ipc_log. - Address tss_mem = alloc_tss(sizeof(Tss) + 256); + Address tss_mem = alloc_tss(sizeof(Tss) + 256); assert(tss_mem + sizeof(Tss) + 256 < Mem_layout::Io_bitmap); - size_t tss_size; tss_mem += 256; - // this is actually tss_size +1, including the io_bitmap_delimiter byte + // this is actually tss_size + 1, including the io_bitmap_delimiter byte + size_t tss_size; tss_size = Mem_layout::Io_bitmap + (Mem_layout::Io_port_max / 8) - tss_mem; assert(tss_size < 0x100000); // must fit into 20 Bits @@ -563,7 +561,6 @@ Kmem::alloc_tss(Address size) return ret; } - /** * Return Global page directory. * This is the master copy of the kernel's page directory. Kernel-memory @@ -572,4 +569,3 @@ Kmem::alloc_tss(Address size) * @return kernel's global page directory */ PUBLIC static inline const Pdir* Kmem::dir() { return kdir; } - diff --git a/kernel/fiasco/src/kern/ia32/logdefs.h b/kernel/fiasco/src/kern/ia32/logdefs.h deleted file mode 100644 index 7713a55c..00000000 --- a/kernel/fiasco/src/kern/ia32/logdefs.h +++ /dev/null @@ -1,240 +0,0 @@ -#ifndef LOGDEFS_H -#define LOGDEFS_H - -// ### How to create a tracebuffer entry ### -// -// If you only need a temporary debugging aid then you can use one of -// the standard kernel logging events: -// -// LOG_MSG(Context *context, const char *msg) -// - context is something like context_of(this) or current_context() -// or 0 if there is no context available -// - msg should be displayed in the tracebuffer view -// -// LOG_MSG_3VAL(Context *context, const char *msg, -// Mword val1, Mword val2, Mword val3) -// - context and msg can be used the same way LOG_MSG does -// - val1, val2, and val3 are values that will be displayed in -// the tracebuffer view as hexadecimal values -// -// If you want to create a permanent log event xyz, you have to follow -// these instructions: -// - create enum Log_event_xyz (see jdb_ktrace.cpp) -// - create class Tb_entry_xyz derived from Tb_entry (see tb_entry.cpp) -// with an appropriate ::set method and with accessor methods -// - create function formatter_xyz (see tb_entry_output.cpp) and don't -// forget to register it (add an appropriate line to init_formatters) -// - create macro LOG_XYZ (see the following example) -// #define LOG_XYZ -// BEGIN_LOG_EVENT(log_xyz) -// Lock_guard guard (&cpu_lock); -// Tb_entry_xyz *tb = -// static_cast(Jdb_tbuf::new_entry()); -// tb->set (this, ) -// Jdb_tbuf::commit_entry(); -// END_LOG_EVENT -// (grabbing the cpu_lock isn't necessary if it is still grabbed) -// - create an empty macro declaration for CONFIG_JDB_LOGGING=n -// - insert the macro call into the code -// - WARNING: permanent log events should _not_ be placed into an inline -// function! -// - add -// DECLARE_PATCH (lp, log_xyz); -// static Log_event le(, -// Log_event_xyz, 1, &lp); -// and create an entry le for Jdb_tbuf_events::log_events[] -// (see jdb_tbuf_events.cpp) - -#include "globalconfig.h" - -#if defined(CONFIG_JDB) - -#include "globals.h" -#include "jdb_tbuf.h" -#include "cpu_lock.h" -#include "lock_guard.h" -#include "processor.h" - -#define LOG_CONTEXT_SWITCH \ - BEGIN_LOG_EVENT("Context switch", "csw", 0) \ - Tb_entry_ctx_sw *tb = \ - static_cast(Jdb_tbuf::new_entry()); \ - tb->set(this, space(), regs()->ip_syscall_page_user(), t, t_orig, \ - t_orig->lock_cnt(), current_sched(), \ - current_sched() ? current_sched()->prio() : 0, \ - (Mword)__builtin_return_address(0)); \ - Jdb_tbuf::commit_entry(); \ - END_LOG_EVENT - - -#define LOG_TRAP \ - BEGIN_LOG_EVENT("Exceptions", "exc", 0) \ - if (ts->_trapno != 1 && ts->_trapno != 3) \ - { \ - Tb_entry_trap *tb = \ - static_cast(Jdb_tbuf::new_entry()); \ - tb->set(this, ts->ip(), ts); \ - Jdb_tbuf::commit_entry(); \ - } \ - END_LOG_EVENT - -#define LOG_TRAP_N(n) \ - BEGIN_LOG_EVENT("Exception n", "exc", 0) \ - Tb_entry_trap *tb = \ - static_cast(Jdb_tbuf::new_entry()); \ - Mword ip = (Mword)(__builtin_return_address(0)); \ - tb->set(current(), ip, n); \ - Jdb_tbuf::commit_entry(); \ - END_LOG_EVENT - -#define LOG_PF_RES_USER \ - BEGIN_LOG_EVENT("Page-fault results", "pfr", 0) \ - Tb_entry_pf_res *tb = \ - static_cast(Jdb_tbuf::new_entry()); \ - tb->set(this, regs()->ip_syscall_page_user(), pfa, err, ret); \ - Jdb_tbuf::commit_entry(); \ - END_LOG_EVENT - -#define LOG_SCHED_SAVE(cs) \ - BEGIN_LOG_EVENT("Scheduling context save", "sch", 0) \ - Tb_entry_sched *tb = \ - static_cast(Jdb_tbuf::new_entry()); \ - tb->set (current(), 0, 0, \ - cs->context(), \ - 0, \ - cs->prio(), \ - cs->left(), \ - cs->quantum()); \ - Jdb_tbuf::commit_entry(); \ - END_LOG_EVENT - -#define LOG_SCHED_LOAD(cs) \ - BEGIN_LOG_EVENT("Scheduling context load", "sch", 0) \ - Tb_entry_sched *tb = \ - static_cast(Jdb_tbuf::new_entry()); \ - tb->set (current(), 0, 1, \ - cs->context(), \ - 0, \ - cs->prio(), \ - cs->left(), \ - cs->quantum()); \ - Jdb_tbuf::commit_entry(); \ - END_LOG_EVENT - -#define LOG_SCHED_INVALIDATE \ - BEGIN_LOG_EVENT("Schduling context invalidate", "sch", 0) \ - Tb_entry_sched *tb = \ - static_cast(Jdb_tbuf::new_entry()); \ - tb->set (current(), current()->regs()->ip_syscall_page_user(), 2, \ - current_sched()->owner(), \ - current_sched()->id(), \ - current_sched()->prio(), \ - timeslice_timeout.cpu(cpu())->get_timeout(Kip::k()->clock), \ - current_sched()->quantum()); \ - Jdb_tbuf::commit_entry(); \ - END_LOG_EVENT - -#define LOG_SEND_PREEMPTION \ - BEGIN_LOG_EVENT("Preemption events", "pre", 0) \ - Lock_guard guard (&cpu_lock); \ - Tb_entry_preemption *tb = \ - static_cast(Jdb_tbuf::new_entry()); \ - tb->set (context_of(this), _receiver.raw(), current()->regs()->ip_syscall_page_user());\ - Jdb_tbuf::commit_entry(); \ - END_LOG_EVENT - -/* - * Kernel instrumentation macro used by fm3. Do not remove! - */ -#define LOG_MSG(context, text) \ - do { \ - /* The cpu_lock is needed since virq::hit() depends on it */ \ - Lock_guard guard (&cpu_lock); \ - Tb_entry_ke *tb = static_cast(Jdb_tbuf::new_entry()); \ - tb->set_const(context, Proc::program_counter(), text); \ - Jdb_tbuf::commit_entry(); \ - } while (0) - -/* - * Kernel instrumentation macro used by fm3. Do not remove! - */ -#define LOG_MSG_3VAL(context, text, v1, v2, v3) \ - do { \ - /* The cpu_lock is needed since virq::hit() depends on it */ \ - Lock_guard guard (&cpu_lock); \ - Tb_entry_ke_reg *tb = \ - static_cast(Jdb_tbuf::new_entry()); \ - tb->set_const(context, Proc::program_counter(), text, v1, v2, v3); \ - Jdb_tbuf::commit_entry(); \ - } while (0) - - -#define LOG_TRACE(name, sc, ctx, fmt, code...) \ - BEGIN_LOG_EVENT(name, sc, fmt) \ - Tb_entry *tbe = Jdb_tbuf::new_entry(); \ - tbe->set_global(__do_log__, ctx, Proc::program_counter()); \ - code; \ - Jdb_tbuf::commit_entry(); \ - END_LOG_EVENT - - -#else - -#define LOG_TRACE(name, sc, ctx, fmt, code...) do { } while (0) -#define LOG_CONTEXT_SWITCH do { } while (0) -#define LOG_TRAP do { } while (0) -#define LOG_TRAP_N(n) do { } while (0) -#define LOG_PF_RES_USER do { } while (0) -#define LOG_SCHED do { } while (0) -#define LOG_SCHED_SAVE(n) do { } while (0) -#define LOG_SCHED_LOAD(n) do { } while (0) -#define LOG_SCHED_INVALIDATE do { } while (0) -#define LOG_SEND_PREEMPTION do { } while (0) - -#endif // CONFIG_JDB - -#if defined(CONFIG_JDB) && defined(CONFIG_JDB_ACCOUNTING) - -#define CNT_CONTEXT_SWITCH \ - Jdb_tbuf::status()->kerncnts[Kern_cnt_context_switch]++; -#define CNT_ADDR_SPACE_SWITCH \ - Jdb_tbuf::status()->kerncnts[Kern_cnt_addr_space_switch]++; -#define CNT_SHORTCUT_FAILED \ - Jdb_tbuf::status()->kerncnts[Kern_cnt_shortcut_failed]++; -#define CNT_SHORTCUT_SUCCESS \ - Jdb_tbuf::status()->kerncnts[Kern_cnt_shortcut_success]++; -#define CNT_IRQ \ - Jdb_tbuf::status()->kerncnts[Kern_cnt_irq]++; -#define CNT_IPC_LONG \ - Jdb_tbuf::status()->kerncnts[Kern_cnt_ipc_long]++; -#define CNT_PAGE_FAULT \ - Jdb_tbuf::status()->kerncnts[Kern_cnt_page_fault]++; -#define CNT_IO_FAULT \ - Jdb_tbuf::status()->kerncnts[Kern_cnt_io_fault]++; -#define CNT_TASK_CREATE \ - Jdb_tbuf::status()->kerncnts[Kern_cnt_task_create]++; -#define CNT_SCHEDULE \ - Jdb_tbuf::status()->kerncnts[Kern_cnt_schedule]++; -#define CNT_IOBMAP_TLB_FLUSH \ - Jdb_tbuf::status()->kerncnts[Kern_cnt_iobmap_tlb_flush]++; -#define CNT_EXC_IPC \ - Jdb_tbuf::status()->kerncnts[Kern_cnt_exc_ipc]++; - -#else - -#define CNT_CONTEXT_SWITCH do { } while (0) -#define CNT_ADDR_SPACE_SWITCH do { } while (0) -#define CNT_SHORTCUT_FAILED do { } while (0) -#define CNT_SHORTCUT_SUCCESS do { } while (0) -#define CNT_IRQ do { } while (0) -#define CNT_IPC_LONG do { } while (0) -#define CNT_PAGE_FAULT do { } while (0) -#define CNT_IO_FAULT do { } while (0) -#define CNT_TASK_CREATE do { } while (0) -#define CNT_SCHEDULE do { } while (0) -#define CNT_IOBMAP_TLB_FLUSH do { } while (0) -#define CNT_EXC_IPC do { } while (0) - -#endif // CONFIG_JDB && CONFIG_JDB_ACCOUNTING - -#endif diff --git a/kernel/fiasco/src/kern/ia32/main-ia32.cpp b/kernel/fiasco/src/kern/ia32/main-ia32.cpp index 1e318c0f..6d797166 100644 --- a/kernel/fiasco/src/kern/ia32/main-ia32.cpp +++ b/kernel/fiasco/src/kern/ia32/main-ia32.cpp @@ -102,11 +102,20 @@ IMPLEMENTATION[(ia32,amd64) && mp]: #include "spin_lock.h" #include "utcb_init.h" -int FIASCO_FASTCALL boot_ap_cpu(unsigned _cpu) __asm__("BOOT_AP_CPU"); +int FIASCO_FASTCALL boot_ap_cpu() __asm__("BOOT_AP_CPU"); -int FIASCO_FASTCALL boot_ap_cpu(unsigned _cpu) +int FIASCO_FASTCALL boot_ap_cpu() { - if (!Per_cpu_data_alloc::alloc(_cpu)) + unsigned _cpu = Apic::find_cpu(Apic::get_id()); + bool cpu_is_new = false; + static unsigned last_cpu; // keep track of the last cpu ever appeared + if (_cpu == ~0U) + { + _cpu = ++last_cpu; // 0 is the boot cpu, so pre increment + cpu_is_new = true; + } + + if (cpu_is_new && !Per_cpu_data_alloc::alloc(_cpu)) { extern Spin_lock _tramp_mp_spinlock; printf("CPU allocation failed for CPU%u, disabling CPU.\n", _cpu); @@ -121,6 +130,7 @@ int FIASCO_FASTCALL boot_ap_cpu(unsigned _cpu) Idt::load(); Apic::init_ap(); + Apic::apic.cpu(_cpu).construct(); Ipi::init(_cpu); Timer::init(_cpu); Apic::check_still_getting_interrupts(); @@ -137,9 +147,7 @@ int FIASCO_FASTCALL boot_ap_cpu(unsigned _cpu) puts(""); // create kernel thread - App_cpu_thread *kernel = new (Ram_quota::root) App_cpu_thread(); - set_cpu_of(kernel, _cpu); - check(kernel->bind(Kernel_task::kernel_task(), User::Ptr(0))); + Kernel_thread *kernel = App_cpu_thread::may_be_create(_cpu, cpu_is_new); main_switch_ap_cpu_stack(kernel); return 0; diff --git a/kernel/fiasco/src/kern/ia32/map_util-io.cpp b/kernel/fiasco/src/kern/ia32/map_util-io.cpp index dbde29e4..01a699dd 100644 --- a/kernel/fiasco/src/kern/ia32/map_util-io.cpp +++ b/kernel/fiasco/src/kern/ia32/map_util-io.cpp @@ -26,13 +26,13 @@ void init_mapdb_io(Space *sigma0) mapdb_io.construct(sigma0, Page_number::create(0x10000 >> io_page_sizes[0]), io_page_sizes, 3); } -/** Map the IO port region described by "fp_from" of address space "from" - into address space "to". IO ports can only be mapped idempotently, - therefore there is no offset for fp_from and only those ports are mapped +/** Map the IO port region described by "fp_from" of address space "from" + into address space "to". IO ports can only be mapped idempotently, + therefore there is no offset for fp_from and only those ports are mapped that lay in the intersection of fp_from and fp_to @param from source address space @param fp_from... IO flexpage descripton for IO space range - in source IO space + in source IO space @param to destination address space @param fp_to... IO flexpage description for IO space range in destination IO space @@ -43,12 +43,12 @@ io_map(Space *from, L4_fpage const &fp_from, Space *to, L4_fpage const &fp_to, L4_msg_item control) { /* printf("io_map %u -> %u " - * "snd %08x base %x size %x rcv %08x base %x size %x\n", - * (unsigned)from->space(), (unsigned)to->space(), - * fp_from.fpage, - * fp_from.iofp.iopage, fp_from.iofp.iosize, - * fp_to.fpage, - * fp_to.iofp.iopage, fp_to.iofp.iosize); + * "snd %08x base %x size %x rcv %08x base %x size %x\n", + * (unsigned)from->space(), (unsigned)to->space(), + * fp_from.fpage, + * fp_from.iofp.iopage, fp_from.iofp.iosize, + * fp_to.fpage, + * fp_to.iofp.iopage, fp_to.iofp.iosize); * kdb_ke("io_fpage_map 1"); */ @@ -81,12 +81,12 @@ io_map(Space *from, L4_fpage const &fp_from, /** Unmap IO mappings. Unmap the region described by "fp" from the IO space "space" and/or the IO spaces the mappings have been - mapped into. + mapped into. XXX not implemented yet @param space address space that should be flushed @param fp IO flexpage descriptor of IO-space range that should be flushed - @param me_too If false, only flush recursive mappings. If true, + @param me_too If false, only flush recursive mappings. If true, additionally flush the region in the given address space. @return true if successful */ @@ -113,8 +113,8 @@ io_fpage_unmap(Space *space, L4_fpage fp, L4_map_mask mask) static inline void save_access_attribs(Mapdb* /*mapdb*/, const Mapdb::Frame& /*mapdb_frame*/, - Mapping* /*mapping*/, Io_space* /*space*/, - unsigned /*page_rights*/, + Mapping* /*mapping*/, Io_space* /*space*/, + unsigned /*page_rights*/, Io_space::Addr /*virt*/, Io_space::Phys_addr /*phys*/, Io_space::Size /*size*/, bool /*me_too*/) diff --git a/kernel/fiasco/src/kern/ia32/startup-ia32.cpp b/kernel/fiasco/src/kern/ia32/startup-ia32.cpp index 2d07d40e..fcf41bc2 100644 --- a/kernel/fiasco/src/kern/ia32/startup-ia32.cpp +++ b/kernel/fiasco/src/kern/ia32/startup-ia32.cpp @@ -47,6 +47,8 @@ IMPLEMENT FIASCO_INIT FIASCO_NOINLINE void Startup::stage2() { + // the logical ID of the boot CPU is always 0 + enum { Boot_cpu = 0 }; Kip_init::init(); Kmem_alloc::init(); @@ -58,13 +60,13 @@ Startup::stage2() // Initialize cpu-local data management and run constructors for CPU 0 Per_cpu_data::init_ctors(); - Per_cpu_data_alloc::alloc(0); - Per_cpu_data::run_ctors(0); + Per_cpu_data_alloc::alloc(Boot_cpu); + Per_cpu_data::run_ctors(Boot_cpu); // set frequency in KIP to that of the boot CPU - Kip_init::init_freq(Cpu::cpus.cpu(0)); + Kip_init::init_freq(Cpu::cpus.cpu(Boot_cpu)); - bool use_io_apic = Io_apic::init(); + bool use_io_apic = Io_apic::init(Boot_cpu); if (use_io_apic) { Config::apic = true; @@ -79,13 +81,14 @@ Startup::stage2() Kernel_task::init(); // enables current_mem_space() // initialize initial TSS, GDT, IDT - Kmem::init_cpu(Cpu::cpus.cpu(0)); + Kmem::init_cpu(Cpu::cpus.cpu(Boot_cpu)); Utcb_init::init(); Idt::init(); - Fpu::init(0); + Fpu::init(Boot_cpu); Apic::init(); - Ipi::init(0); - Timer::init(0); + Apic::apic.cpu(Boot_cpu).construct(); + Ipi::init(Boot_cpu); + Timer::init(Boot_cpu); int timer_irq = Timer::irq(); if (use_io_apic) { @@ -100,7 +103,7 @@ Startup::stage2() Io_apic *const apic = static_cast(irq.chip); Io_apic_entry e = apic->read_entry(irq.pin); - e.vector(Config::Apic_timer_vector); + e.vector() = Config::Apic_timer_vector; apic->write_entry(irq.pin, e); } } @@ -113,7 +116,7 @@ Startup::stage2() } Idt::set_vectors_run(); - Timer::master_cpu(0); + Timer::master_cpu(Boot_cpu); Apic::check_still_getting_interrupts(); // Cpu::init_global_features(); } diff --git a/kernel/fiasco/src/kern/ia32/svm.cpp b/kernel/fiasco/src/kern/ia32/svm.cpp index 65ae3ed0..d721c017 100644 --- a/kernel/fiasco/src/kern/ia32/svm.cpp +++ b/kernel/fiasco/src/kern/ia32/svm.cpp @@ -107,6 +107,8 @@ Svm::Svm(unsigned cpu) } printf("NASID: 0x%x\n", ebx); _max_asid = ebx - 1; + + // FIXME: MUST NOT PANIC ON CPU HOTPLUG assert(_max_asid > 0); enum @@ -118,6 +120,7 @@ Svm::Svm(unsigned cpu) }; /* 16kB IO permission map and Vmcb (16kB are good for the buddy allocator)*/ + // FIXME: MUST NOT PANIC ON CPU HOTPLUG check(_iopm = Kmem_alloc::allocator()->unaligned_alloc(Io_pm_size + Vmcb_size)); _iopm_base_pa = Kmem::virt_to_phys(_iopm); _kernel_vmcb = (Vmcb*)((char*)_iopm + Io_pm_size); @@ -131,6 +134,7 @@ Svm::Svm(unsigned cpu) memset(_kernel_vmcb, 0, Vmcb_size); /* 8kB MSR permission map */ + // FIXME: MUST NOT PANIC ON CPU HOTPLUG check(_msrpm = Kmem_alloc::allocator()->unaligned_alloc(Msr_pm_size)); _msrpm_base_pa = Kmem::virt_to_phys(_msrpm); memset(_msrpm, ~0, Msr_pm_size); @@ -141,6 +145,7 @@ Svm::Svm(unsigned cpu) set_msr_perm(MSR_SYSENTER_ESP, Msr_rw); /* 4kB Host state-safe area */ + // FIXME: MUST NOT PANIC ON CPU HOTPLUG check(_vm_hsave_area = Kmem_alloc::allocator()->unaligned_alloc(State_save_area_size)); Unsigned64 vm_hsave_pa = Kmem::virt_to_phys(_vm_hsave_area); @@ -237,6 +242,7 @@ Svm::next_asid () { _global_asid_generation++; _next_asid = 1; + // FIXME: must not crash on an overrun assert (_global_asid_generation < ~0U); _flush_all_asids = true; } diff --git a/kernel/fiasco/src/kern/ia32/thread-ia32.cpp b/kernel/fiasco/src/kern/ia32/thread-ia32.cpp index d2320f9d..d6fb0004 100644 --- a/kernel/fiasco/src/kern/ia32/thread-ia32.cpp +++ b/kernel/fiasco/src/kern/ia32/thread-ia32.cpp @@ -62,8 +62,7 @@ Thread::Thread() _exc_handler(Thread_ptr::Invalid), _del_observer(0) { - //assert (current() == thread_lock()->lock_owner()); - assert (state() == Thread_invalid); + assert (state(false) == Thread_invalid); inc_ref(); _space.space(Kernel_task::kernel_task()); @@ -80,7 +79,7 @@ Thread::Thread() arch_init(); - state_add_dirty(Thread_dead | Thread_suspended); + state_add_dirty(Thread_dead, false); // ok, we're ready to go! } @@ -159,7 +158,7 @@ thread_restore_exc_state() current_thread()->restore_exc_state(); } -PRIVATE static +PRIVATE static void Thread::print_page_fault_error(Mword e) { @@ -232,20 +231,19 @@ Thread::handle_slow_trap(Trap_state *ts) check_f00f_bug(ts); // so we were in user mode -- look for something to emulate - + // We continue running with interrupts off -- no sti() here. But // interrupts may be enabled by the pagefault handler if we get a // pagefault in peek_user(). // Set up exception handling. If we suffer an un-handled user-space // page fault, kill the thread. - jmp_buf pf_recovery; + jmp_buf pf_recovery; unsigned error; if (EXPECT_FALSE ((error = setjmp(pf_recovery)) != 0) ) { - WARN ("%p killed:\n" - "\033[1mUnhandled page fault, code=%08x\033[m\n", - this, error); + WARN("%p killed:\n" + "\033[1mUnhandled page fault, code=%08x\033[m\n", this, error); goto fail_nomsg; } @@ -288,9 +286,8 @@ check_exception: fail: // can't handle trap -- kill the thread - WARN ("%p killed:\n" - "\033[1mUnhandled trap \033[m\n", - this); + WARN("%p killed:\n" + "\033[1mUnhandled trap \033[m\n", this); fail_nomsg: if ((int)Config::Warn_level >= Warning) @@ -792,7 +789,7 @@ Thread::handle_not_nested_trap(Trap_state *ts) int r; // cannot use normal getchar because it may block with hlt and irq's // are off here - while ((r=Kconsole::console()->getchar(false)) == -1) + while ((r = Kconsole::console()->getchar(false)) == -1) Proc::pause(); if (r == '\033') @@ -808,6 +805,30 @@ Thread::sys_control_arch(Utcb *) return 0; } +//--------------------------------------------------------------------------- +IMPLEMENTATION [(ia32 | amd64) & (debug | kdb) & !mp]: + +PRIVATE static inline unsigned Thread::dbg_find_cpu() { return 0; } + +//--------------------------------------------------------------------------- +IMPLEMENTATION [(ia32 | amd64) & (debug | kdb) & mp]: + +#include "apic.h" + +PRIVATE static inline NEEDS["apic.h"] +unsigned +Thread::dbg_find_cpu() +{ + unsigned long phys_cpu = Apic::get_id(); + unsigned log_cpu = Apic::find_cpu(phys_cpu); + if (log_cpu == ~0U) + { + printf("Trap on unknown CPU phys_id=%lx\n", phys_cpu); + log_cpu = 0; + } + return log_cpu; +} + //--------------------------------------------------------------------------- IMPLEMENTATION [(ia32 |amd64) & !(debug | kdb)]: diff --git a/kernel/fiasco/src/kern/ia32/thread-io.cpp b/kernel/fiasco/src/kern/ia32/thread-io.cpp index 11c1198a..a9e6cda7 100644 --- a/kernel/fiasco/src/kern/ia32/thread-io.cpp +++ b/kernel/fiasco/src/kern/ia32/thread-io.cpp @@ -1,19 +1,18 @@ IMPLEMENTATION [io && (ia32 || amd64 || ux)]: -// -// disassamble IO statements to compute the port address and +// +// disassamble IO statements to compute the port address and // the number of ports accessed -// +// /** Compute port number and size for an IO instruction. - @param eip address of the instruction + @param eip address of the instruction @param ts thread state with registers @param port return port address @param size return number of ports accessed @return true if the instruction was handled successfully false otherwise */ - bool Thread::get_ioport(Address eip, Trap_state *ts, unsigned *port, unsigned *size) { @@ -35,7 +34,7 @@ Thread::get_ioport(Address eip, Trap_state *ts, unsigned *port, unsigned *size) case 0x6f: // outd *size = 2; *port = ts->dx() & 0xffff; - if (*port +4 <= Mem_layout::Io_port_max) + if (*port + 4 <= Mem_layout::Io_port_max) return true; else // Access beyond L4_IOPORT_MAX return false; @@ -47,24 +46,24 @@ Thread::get_ioport(Address eip, Trap_state *ts, unsigned *port, unsigned *size) } // handle 2 Byte IO - if (! (eip < Kmem::mem_user_max -1)) + if (!(eip < Kmem::mem_user_max - 1)) return false; - switch (mem_space()->peek((Unsigned8*)eip, from_user)) + switch (mem_space()->peek((Unsigned8 *)eip, from_user)) { case 0xe4: // in imm8, al - case 0xe6: // out al, imm8 + case 0xe6: // out al, imm8 *size = 0; - *port = mem_space()->peek((Unsigned8*)(eip+1), from_user); + *port = mem_space()->peek((Unsigned8 *)(eip + 1), from_user); return true; case 0xe5: // in imm8, eax case 0xe7: // out eax, imm8 *size = 2; - *port = mem_space()->peek((Unsigned8*)(eip+1), from_user); - return *port +4 <= Mem_layout::Io_port_max ? true : false; + *port = mem_space()->peek((Unsigned8 *)(eip + 1), from_user); + return *port + 4 <= Mem_layout::Io_port_max ? true : false; case 0x66: // operand size override - switch (mem_space()->peek((Unsigned8*)(eip+1), from_user)) + switch (mem_space()->peek((Unsigned8 *)(eip + 1), from_user)) { case 0xed: // in dx, ax case 0xef: // out ax, dx @@ -72,22 +71,22 @@ Thread::get_ioport(Address eip, Trap_state *ts, unsigned *port, unsigned *size) case 0x6f: // outw *size = 1; *port = ts->dx() & 0xffff; - if (*port +2 <= Mem_layout::Io_port_max) + if (*port + 2 <= Mem_layout::Io_port_max) return true; else // Access beyond L4_IOPORT_MAX return false; case 0xe5: // in imm8, ax case 0xe7: // out ax,imm8 *size = 1; - *port = mem_space()->peek((Unsigned8*)(eip + 2), from_user); - if (*port +2 <= Mem_layout::Io_port_max) + *port = mem_space()->peek((Unsigned8 *)(eip + 2), from_user); + if (*port + 2 <= Mem_layout::Io_port_max) return true; else return false; } case 0xf3: // REP - switch (mem_space()->peek((Unsigned8*)(eip +1), from_user)) + switch (mem_space()->peek((Unsigned8*)(eip + 1), from_user)) { case 0x6c: // REP insb case 0x6e: // REP outb @@ -98,7 +97,7 @@ Thread::get_ioport(Address eip, Trap_state *ts, unsigned *port, unsigned *size) case 0x6f: // REP outd *size = 2; *port = ts->dx() & 0xffff; - if(*port +4 <= Mem_layout::Io_port_max) + if (*port + 4 <= Mem_layout::Io_port_max) return true; else // Access beyond L4_IOPORT_MAX return false; @@ -106,20 +105,20 @@ Thread::get_ioport(Address eip, Trap_state *ts, unsigned *port, unsigned *size) } // handle 3 Byte IO - if (! (eip < Kmem::mem_user_max -2)) + if (!(eip < Kmem::mem_user_max - 2)) return false; - Unsigned16 w = mem_space()->peek((Unsigned16*)eip, from_user); + Unsigned16 w = mem_space()->peek((Unsigned16 *)eip, from_user); if (w == 0x66f3 || // sizeoverride REP w == 0xf366) // REP sizeoverride { - switch (mem_space()->peek((Unsigned8*)(eip +2), from_user)) + switch (mem_space()->peek((Unsigned8 *)(eip + 2), from_user)) { case 0x6d: // REP insw case 0x6f: // REP outw *size = 1; *port = ts->dx() & 0xffff; - if (*port +2 <= Mem_layout::Io_port_max) + if (*port + 2 <= Mem_layout::Io_port_max) return true; else // Access beyond L4_IOPORT_MAX return false; @@ -187,8 +186,8 @@ Thread::handle_io_page_fault(Trap_state *ts) } bool ipc_code = handle_page_fault_pager(_pager, io_page, - io_error_code, - L4_msg_tag::Label_io_page_fault); + io_error_code, + L4_msg_tag::Label_io_page_fault); if (ipc_code) return 1; diff --git a/kernel/fiasco/src/kern/ia32/timer_tick-apic.cpp b/kernel/fiasco/src/kern/ia32/timer_tick-apic.cpp index ddbbda9e..603151cd 100644 --- a/kernel/fiasco/src/kern/ia32/timer_tick-apic.cpp +++ b/kernel/fiasco/src/kern/ia32/timer_tick-apic.cpp @@ -69,5 +69,3 @@ thread_timer_interrupt_stop(void) { Apic::irq_ack(); } - - diff --git a/kernel/fiasco/src/kern/ia32/vm_svm.cpp b/kernel/fiasco/src/kern/ia32/vm_svm.cpp index f7072856..e1606651 100644 --- a/kernel/fiasco/src/kern/ia32/vm_svm.cpp +++ b/kernel/fiasco/src/kern/ia32/vm_svm.cpp @@ -23,15 +23,17 @@ private: // ------------------------------------------------------------------------ INTERFACE [svm && debug]: +#include "tb_entry.h" + EXTENSION class Vm_svm { protected: - struct Log_vm_svm_exit + struct Log_vm_svm_exit : public Tb_entry { Mword exitcode, exitinfo1, exitinfo2, rip; + unsigned print(int max, char *buf) const; }; - static unsigned log_fmt_svm(Tb_entry *, int max, char *buf) asm ("__fmt_vm_svm_exit"); }; // ------------------------------------------------------------------------ @@ -642,8 +644,7 @@ Vm_svm::do_resume_vcpu(Context *ctxt, Vcpu_state *vcpu, Vmcb *vmcb_s) vmcb_s->control_area.n_cr3 = orig_ncr3; - LOG_TRACE("VM-SVM", "svm", current(), __fmt_vm_svm_exit, - Log_vm_svm_exit *l = tbe->payload(); + LOG_TRACE("VM-SVM", "svm", current(), Log_vm_svm_exit, l->exitcode = vmcb_s->control_area.exitcode; l->exitinfo1 = vmcb_s->control_area.exitinfo1; l->exitinfo2 = vmcb_s->control_area.exitinfo2; @@ -710,9 +711,8 @@ IMPLEMENTATION [svm && debug]: IMPLEMENT unsigned -Vm_svm::log_fmt_svm(Tb_entry *e, int max, char *buf) +Vm_svm::Log_vm_svm_exit::print(int max, char *buf) const { - Log_vm_svm_exit *l = e->payload(); return snprintf(buf, max, "ec=%lx ei1=%08lx ei2=%08lx rip=%08lx", - l->exitcode, l->exitinfo1, l->exitinfo2, l->rip); + exitcode, exitinfo1, exitinfo2, rip); } diff --git a/kernel/fiasco/src/kern/ia32/vmx.cpp b/kernel/fiasco/src/kern/ia32/vmx.cpp index b93723c2..0e0a89f8 100644 --- a/kernel/fiasco/src/kern/ia32/vmx.cpp +++ b/kernel/fiasco/src/kern/ia32/vmx.cpp @@ -454,6 +454,7 @@ Vmx::Vmx(unsigned cpu) } // allocate a 4kb region for kernel vmcs + // FIXME: MUST NOT PANIC ON CPU HOTPLUG check(_kernel_vmcs = Kmem_alloc::allocator()->alloc(12)); _kernel_vmcs_pa = Kmem::virt_to_phys(_kernel_vmcs); // clean vmcs @@ -462,6 +463,7 @@ Vmx::Vmx(unsigned cpu) *(int *)_kernel_vmcs = (info.basic & 0xFFFFFFFF); // allocate a 4kb aligned region for VMXON + // FIXME: MUST NOT PANIC ON CPU HOTPLUG check(_vmxon = Kmem_alloc::allocator()->alloc(12)); _vmxon_base_pa = Kmem::virt_to_phys(_vmxon); @@ -481,6 +483,7 @@ Vmx::Vmx(unsigned cpu) asm volatile("vmclear %1 \n\t" "pushf \n\t" "pop %0 \n\t" : "=r"(eflags) : "m"(_kernel_vmcs_pa):); + // FIXME: MUST NOT PANIC ON CPU HOTPLUG if (eflags & 0x41) panic("VMX: vmclear: VMFailInvalid, vmcs pointer not valid\n"); @@ -489,6 +492,7 @@ Vmx::Vmx(unsigned cpu) "pushf \n\t" "pop %0 \n\t" : "=r"(eflags) : "m"(_kernel_vmcs_pa):); + // FIXME: MUST NOT PANIC ON CPU HOTPLUG if (eflags & 0x41) panic("VMX: vmptrld: VMFailInvalid, vmcs pointer not valid\n"); diff --git a/kernel/fiasco/src/kern/ia32/x86desc.cpp b/kernel/fiasco/src/kern/ia32/x86desc.cpp index 2c2c3e87..666bf41c 100644 --- a/kernel/fiasco/src/kern/ia32/x86desc.cpp +++ b/kernel/fiasco/src/kern/ia32/x86desc.cpp @@ -1,4 +1,3 @@ - INTERFACE: #include "l4_types.h" diff --git a/kernel/fiasco/src/kern/io_space.cpp b/kernel/fiasco/src/kern/io_space.cpp index b46ef356..13121c62 100644 --- a/kernel/fiasco/src/kern/io_space.cpp +++ b/kernel/fiasco/src/kern/io_space.cpp @@ -97,7 +97,7 @@ IMPLEMENTATION [io]: #include "kmem_alloc.h" #include "panic.h" #include "paging.h" - + PUBLIC template< typename SPACE > static inline @@ -148,14 +148,14 @@ Generic_io_space::~Generic_io_space() Kmem_alloc::allocator() ->q_free_phys(ram_quota(), Config::PAGE_SHIFT, iopte.e[0].addr()); - + if (iopte.e[1].valid()) Kmem_alloc::allocator() ->q_free_phys(ram_quota(), Config::PAGE_SHIFT, iopte.e[1].addr()); - + Pdir::Iter iopde = mem_space()->dir()->walk(Virt_addr(Mem_layout::Io_bitmap), 0); - + // free the page table Kmem_alloc::allocator() ->q_free_phys(ram_quota(), Config::PAGE_SHIFT, @@ -179,9 +179,9 @@ Generic_io_space::is_superpage() { return _io_counter & 0x10000000; } -// +// // Utilities for map and unmap -// +// PUBLIC template< typename SPACE > virtual @@ -195,8 +195,8 @@ Generic_io_space::v_fabricate(Addr address, Phys_addr *phys, } PUBLIC template< typename SPACE > -inline NEEDS[Generic_io_space::is_superpage] -bool +inline NEEDS[Generic_io_space::is_superpage] +bool Generic_io_space::v_lookup(Addr virt, Phys_addr *phys = 0, Size *size = 0, unsigned *attribs = 0) { @@ -289,7 +289,7 @@ Generic_io_space::tlb_flush() PUBLIC template< typename SPACE > inline static -bool +bool Generic_io_space::need_tlb_flush() { return false; } @@ -323,9 +323,9 @@ Generic_io_space::addto_io_counter(int incr) /** Lookup one IO port in the IO space. - @param port_number port address to lookup; + @param port_number port address to lookup; @return true if mapped - false if not + false if not */ PROTECTED template< typename SPACE > bool @@ -342,8 +342,8 @@ Generic_io_space::io_lookup(Address port_number) return false; // no bitmap -> no ports // so there is memory mapped in the IO bitmap - char * port = static_cast(Kmem::phys_to_virt(port_addr)); - + char *port = static_cast(Kmem::phys_to_virt(port_addr)); + // bit == 1 disables the port // bit == 0 enables the port return !(*port & get_port_bit(port_number)); @@ -370,8 +370,8 @@ Generic_io_space::io_insert(Address port_number) { // nothing mapped! Get a page and map it in the IO bitmap void *page; - if (!(page=Kmem_alloc::allocator()->q_alloc(ram_quota(), - Config::PAGE_SHIFT))) + if (!(page = Kmem_alloc::allocator()->q_alloc(ram_quota(), + Config::PAGE_SHIFT))) return Insert_err_nomem; // clear all IO ports @@ -387,13 +387,13 @@ Generic_io_space::io_insert(Address port_number) if (status == Mem_space::Insert_err_nomem) { - Kmem_alloc::allocator()->free(Config::PAGE_SHIFT,page); + Kmem_alloc::allocator()->free(Config::PAGE_SHIFT, page); ram_quota()->free(Config::PAGE_SIZE); return Insert_err_nomem; } // we've been careful, so insertion should have succeeded - assert(status == Mem_space::Insert_ok); + assert(status == Mem_space::Insert_ok); port_phys = mem_space()->virt_to_phys(port_virt); assert(port_phys != ~0UL); @@ -404,7 +404,7 @@ Generic_io_space::io_insert(Address port_number) if (*port & get_port_bit(port_number)) // port disabled? { - *port &= ~ get_port_bit(port_number); + *port &= ~get_port_bit(port_number); addto_io_counter(1); return Insert_ok; } @@ -433,7 +433,7 @@ Generic_io_space::io_delete(Address port_number) return 0; // so there is memory mapped in the IO bitmap -> disable the ports - char * port = static_cast (Kmem::phys_to_virt(port_addr)); + char *port = static_cast(Kmem::phys_to_virt(port_addr)); // bit == 1 disables the port // bit == 0 enables the port @@ -457,7 +457,7 @@ Generic_io_space::get_phys_port_addr(Address const port_number) const } template< typename SPACE > -INLINE +INLINE Unsigned8 Generic_io_space::get_port_bit(Address const port_number) const { diff --git a/kernel/fiasco/src/kern/ipc_gate.cpp b/kernel/fiasco/src/kern/ipc_gate.cpp index a53b7da1..c74fabb7 100644 --- a/kernel/fiasco/src/kern/ipc_gate.cpp +++ b/kernel/fiasco/src/kern/ipc_gate.cpp @@ -52,17 +52,19 @@ public: //--------------------------------------------------------------------------- INTERFACE [debug]: +#include "tb_entry.h" + EXTENSION class Ipc_gate { protected: - struct Log_ipc_gate_invoke + struct Log_ipc_gate_invoke : public Tb_entry { Mword gate_dbg_id; Mword thread_dbg_id; Mword label; + unsigned print(int max, char *buf) const; }; - static unsigned log_fmt(Tb_entry *, int max, char *buf) asm ("__fmt_ipc_gate_invoke"); }; //--------------------------------------------------------------------------- @@ -114,10 +116,10 @@ Ipc_gate_obj::unblock_all() { while (::Prio_list_elem *h = _wait_q.first()) { - Lock_guard g1(&cpu_lock); + auto g1 = lock_guard(cpu_lock); Thread *w; { - Lock_guard g2(_wait_q.lock()); + auto g2 = lock_guard(_wait_q.lock()); if (EXPECT_FALSE(h != _wait_q.first())) continue; @@ -286,7 +288,7 @@ Ipc_gate::block(Thread *ct, L4_timeout const &to, Utcb *u) } { - Lock_guard g(_wait_q.lock()); + auto g = lock_guard(_wait_q.lock()); ct->set_wait_queue(&_wait_q); ct->sender_enqueue(&_wait_q, ct->sched_context()->prio()); } @@ -295,7 +297,7 @@ Ipc_gate::block(Thread *ct, L4_timeout const &to, Utcb *u) IPC_timeout timeout; if (t) { - timeout.set(t, ct->cpu()); + timeout.set(t, ct->cpu(true)); ct->set_timeout(&timeout); } @@ -306,7 +308,7 @@ Ipc_gate::block(Thread *ct, L4_timeout const &to, Utcb *u) if (EXPECT_FALSE(ct->in_sender_list() && timeout.has_hit())) { - Lock_guard g(_wait_q.lock()); + auto g = lock_guard(_wait_q.lock()); if (!ct->in_sender_list()) return L4_error::None; @@ -347,8 +349,7 @@ Ipc_gate::invoke(L4_obj_ref /*self*/, Mword rights, Syscall_frame *f, Utcb *utcb bool ipc = _thread->check_sys_ipc(f->ref().op(), &partner, &sender, &have_rcv); - LOG_TRACE("IPC Gate invoke", "gate", current(), __fmt_ipc_gate_invoke, - Log_ipc_gate_invoke *l = tbe->payload(); + LOG_TRACE("IPC Gate invoke", "gate", current(), Log_ipc_gate_invoke, l->gate_dbg_id = dbg_id(); l->thread_dbg_id = _thread->dbg_id(); l->label = _id | rights; @@ -374,10 +375,9 @@ Ipc_gate_obj::dbg_info() const IMPLEMENT unsigned -Ipc_gate::log_fmt(Tb_entry *e, int max, char *buf) +Ipc_gate::Log_ipc_gate_invoke::print(int max, char *buf) const { - Log_ipc_gate_invoke *l = e->payload(); return snprintf(buf, max, "D-gate=%lx D-thread=%lx L=%lx", - l->gate_dbg_id, l->thread_dbg_id, l->label); + gate_dbg_id, thread_dbg_id, label); } diff --git a/kernel/fiasco/src/kern/ipc_sender.cpp b/kernel/fiasco/src/kern/ipc_sender.cpp index 646f0808..9f82f6f4 100644 --- a/kernel/fiasco/src/kern/ipc_sender.cpp +++ b/kernel/fiasco/src/kern/ipc_sender.cpp @@ -65,16 +65,18 @@ bool Ipc_sender_base::handle_shortcut(Syscall_frame *dst_regs, Receiver *receiver) { + auto &rq = Sched_context::rq.current(); + if (EXPECT_TRUE ((current() != receiver - && receiver->sched()->deblock(current_cpu(), current()->sched(), true) + && rq.deblock(receiver->sched(), current()->sched(), true) // avoid race in do_ipc() after Thread_send_in_progress // flag was deleted from receiver's thread state // also: no shortcut for alien threads, they need to see the // after-syscall exception && !(receiver->state() & (Thread_ready_mask | Thread_alien)) - && !current()->schedule_in_progress()))) // no schedule in progress + && !rq.schedule_in_progress))) // no schedule in progress { // we don't need to manipulate the state in a safe way // because we are still running with interrupts turned off @@ -163,7 +165,7 @@ Ipc_sender::send_msg(Receiver *receiver) // we don't need to manipulate the state in a safe way // because we are still running with interrupts turned off receiver->state_add_dirty(Thread_ready); - receiver->sched()->deblock(receiver->cpu()); + Sched_context::rq.current().deblock(receiver->sched()); return; } diff --git a/kernel/fiasco/src/kern/ipc_timeout.cpp b/kernel/fiasco/src/kern/ipc_timeout.cpp index 3cbf780c..08c20701 100644 --- a/kernel/fiasco/src/kern/ipc_timeout.cpp +++ b/kernel/fiasco/src/kern/ipc_timeout.cpp @@ -60,5 +60,5 @@ IPC_timeout::expired() // Flag reschedule if owner's priority is higher than the current // thread's (own or timeslice-donated) priority. - return _owner->sched()->deblock(current_cpu(), current()->sched(), false); + return Sched_context::rq.current().deblock(_owner->sched(), current()->sched(), false); } diff --git a/kernel/fiasco/src/kern/irq.cpp b/kernel/fiasco/src/kern/irq.cpp index 387cd556..7079fdc9 100644 --- a/kernel/fiasco/src/kern/irq.cpp +++ b/kernel/fiasco/src/kern/irq.cpp @@ -351,7 +351,7 @@ Irq_sender::free(Receiver *t) if (ret) { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); mask(); if (EXPECT_TRUE(t != 0)) @@ -390,7 +390,7 @@ PUBLIC void Irq_sender::destroy(Kobject ***rl) { - Lock_guard g(&cpu_lock); + auto g = lock_guard(cpu_lock); if (_irq_thread) free(_irq_thread); diff --git a/kernel/fiasco/src/kern/irq_chip.cpp b/kernel/fiasco/src/kern/irq_chip.cpp index 6bf168a9..83cd1662 100644 --- a/kernel/fiasco/src/kern/irq_chip.cpp +++ b/kernel/fiasco/src/kern/irq_chip.cpp @@ -117,7 +117,14 @@ public: Irq_chip *chip() const { return _chip; } void mask() { if (!__mask()) _chip->mask(_pin); } - void mask_and_ack() { if (!__mask()) _chip->mask_and_ack(_pin); } + void mask_and_ack() + { + if (!__mask()) + _chip->mask_and_ack(_pin); + else + _chip->ack(_pin); + } + void unmask() { if (__unmask()) _chip->unmask(_pin); } void ack() { _chip->ack(_pin); } @@ -266,7 +273,7 @@ PUBLIC inline NEEDS["lock_guard.h", "cpu_lock.h"] void Irq_base::destroy() { - Lock_guard g(&cpu_lock); + auto g = lock_guard(cpu_lock); unbind(); } @@ -284,15 +291,13 @@ INTERFACE [debug]: EXTENSION class Irq_base { public: - struct Irq_log + struct Irq_log : public Tb_entry { Irq_base *obj; Irq_chip *chip; Mword pin; + unsigned print(int max, char *buf) const; }; - - static unsigned irq_log_fmt(Tb_entry *, int, char *) - asm ("__irq_log_fmt"); }; @@ -306,19 +311,18 @@ IMPLEMENTATION [debug]: IMPLEMENT unsigned -Irq_base::irq_log_fmt(Tb_entry *e, int maxlen, char *buf) +Irq_base::Irq_log::print(int maxlen, char *buf) const { - Irq_log *l = e->payload(); - Kobject_dbg::Const_iterator irq = Kobject_dbg::pointer_to_obj(l->obj); + Kobject_dbg::Const_iterator irq = Kobject_dbg::pointer_to_obj(obj); if (irq != Kobject_dbg::end()) return snprintf(buf, maxlen, "0x%lx/%lu @ chip %s(%p) D:%lx", - l->pin, l->pin, l->chip->chip_type(), l->chip, + pin, pin, chip->chip_type(), chip, irq->dbg_id()); else return snprintf(buf, maxlen, "0x%lx/%lu @ chip %s(%p) irq=%p", - l->pin, l->pin, l->chip->chip_type(), l->chip, - l->obj); + pin, pin, chip->chip_type(), chip, + obj); } PUBLIC inline NEEDS["logdefs.h"] @@ -326,8 +330,7 @@ void Irq_base::log() { Context *c = current(); - LOG_TRACE("IRQ-Object triggers", "irq", c, __irq_log_fmt, - Irq_base::Irq_log *l = tbe->payload(); + LOG_TRACE("IRQ-Object triggers", "irq", c, Irq_log, l->obj = this; l->chip = chip(); l->pin = pin(); diff --git a/kernel/fiasco/src/kern/irq_mgr.cpp b/kernel/fiasco/src/kern/irq_mgr.cpp index 77221fee..a3974231 100644 --- a/kernel/fiasco/src/kern/irq_mgr.cpp +++ b/kernel/fiasco/src/kern/irq_mgr.cpp @@ -2,6 +2,7 @@ INTERFACE: #include "types.h" #include "irq_chip.h" +#include /** * Interface used to manage harware IRQs on a platform. @@ -68,12 +69,8 @@ class Irq_mgr_single_chip : public Irq_mgr public: Irq_mgr_single_chip() {} - template - explicit Irq_mgr_single_chip(A1 const &a1) : c(a1) {} - - template - Irq_mgr_single_chip(A1 const &a1, A2 const &a2) : c(a1, a2) {} - + template< typename... A > + explicit Irq_mgr_single_chip(A&&... args) : c(cxx::forward(args)...) {} Irq chip(Mword irqnum) const { return Irq(&c, irqnum); } unsigned nr_irqs() const { return c.nr_irqs(); } diff --git a/kernel/fiasco/src/kern/kernel_thread-std.cpp b/kernel/fiasco/src/kern/kernel_thread-std.cpp index e4eee6c9..2867ed06 100644 --- a/kernel/fiasco/src/kern/kernel_thread-std.cpp +++ b/kernel/fiasco/src/kern/kernel_thread-std.cpp @@ -32,7 +32,7 @@ IMPLEMENT void Kernel_thread::init_workload() { - Lock_guard g(&cpu_lock); + auto g = lock_guard(cpu_lock); if (Config::Jdb && !Koptions::o()->opt(Koptions::F_nojdb) && @@ -124,8 +124,6 @@ Kernel_thread::init_workload() set_cpu_of(sigma0_thread, 0); set_cpu_of(boot_thread, 0); - sigma0_thread->state_del_dirty(Thread_suspended); - boot_thread->state_del_dirty(Thread_suspended); sigma0_thread->activate(); check (obj_map(sigma0, C_factory, 1, boot_task, C_factory, 0).error() == 0); diff --git a/kernel/fiasco/src/kern/kernel_thread.cpp b/kernel/fiasco/src/kern/kernel_thread.cpp index 4fc61c74..1ff718d0 100644 --- a/kernel/fiasco/src/kern/kernel_thread.cpp +++ b/kernel/fiasco/src/kern/kernel_thread.cpp @@ -35,6 +35,7 @@ IMPLEMENTATION: #include "globals.h" #include "helping_lock.h" #include "kernel_task.h" +#include "per_cpu_data_alloc.h" #include "processor.h" #include "task.h" #include "thread.h" @@ -61,6 +62,9 @@ Kernel_thread::bootstrap() // Initializations done -- Helping_lock can now use helping lock Helping_lock::threading_system_active = true; + // we need per CPU data for our never running dummy CPU too + // FIXME: we in fact need only the _pending_rqq lock + Per_cpu_data_alloc::alloc(Cpu::Invalid); set_cpu_of(this, Cpu::boot_cpu()->id()); Mem::barrier(); @@ -68,16 +72,16 @@ Kernel_thread::bootstrap() state_change_dirty(0, Thread_ready); // Set myself ready Timer::init_system_clock(); - Sched_context::rq(cpu()).set_idle(this->sched()); + Sched_context::rq.current().set_idle(this->sched()); Kernel_task::kernel_task()->make_current(); // Setup initial timeslice - set_current_sched(sched()); + Sched_context::rq.current().set_current_sched(sched()); - Timer_tick::setup(cpu()); assert (cpu() == 0); // currently the boot cpu must be 0 - Timer_tick::enable(cpu()); - enable_tlb(cpu()); + Timer_tick::setup(cpu(true)); assert (cpu(true) == 0); // currently the boot cpu must be 0 + Timer_tick::enable(cpu(true)); + enable_tlb(cpu(true)); bootstrap_arch(); @@ -154,7 +158,7 @@ Kernel_thread::idle_op() { // this version must run with disabled IRQs and a wakup must continue directly // after the wait for event. - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); unsigned cpu = this->cpu(); ++_idle_counter.cpu(cpu); // 1. check for latency requirements that prevent low power modes diff --git a/kernel/fiasco/src/kern/kmem_alloc.cpp b/kernel/fiasco/src/kern/kmem_alloc.cpp index 54c48e96..31ab9e66 100644 --- a/kernel/fiasco/src/kern/kmem_alloc.cpp +++ b/kernel/fiasco/src/kern/kmem_alloc.cpp @@ -147,7 +147,7 @@ Kmem_alloc::unaligned_alloc(unsigned long size) void* ret; { - Lock_guard guard(&lock); + auto guard = lock_guard(lock); ret = a->alloc(size); } @@ -155,7 +155,7 @@ Kmem_alloc::unaligned_alloc(unsigned long size) { Kmem_alloc_reaper::morecore (/* desperate= */ true); - Lock_guard guard (&lock); + auto guard = lock_guard(lock); ret = a->alloc(size); } @@ -167,7 +167,7 @@ void Kmem_alloc::unaligned_free(unsigned long size, void *page) { assert(size >=8 /*NEW INTERFACE PARANIOIA*/); - Lock_guard guard (&lock); + auto guard = lock_guard(lock); a->free(page, size); } diff --git a/kernel/fiasco/src/kern/kobject.cpp b/kernel/fiasco/src/kern/kobject.cpp index cd109d3c..e5b3c860 100644 --- a/kernel/fiasco/src/kern/kobject.cpp +++ b/kernel/fiasco/src/kern/kobject.cpp @@ -127,7 +127,7 @@ PUBLIC inline NEEDS["lock_guard.h"] Smword Kobject_mappable::dec_cap_refcnt(Smword diff) { - Lock_guard g(&_lock); + auto g = lock_guard(_lock); _cnt -= diff; return _cnt; } @@ -147,8 +147,7 @@ PUBLIC virtual void Kobject::destroy(Kobject ***) { - LOG_TRACE("Kobject destroy", "des", current(), __fmt_kobj_destroy, - Log_destroy *l = tbe->payload(); + LOG_TRACE("Kobject destroy", "des", current(), Log_destroy, l->id = dbg_id(); l->obj = this; l->type = kobj_type()); @@ -158,8 +157,7 @@ Kobject::destroy(Kobject ***) PUBLIC virtual Kobject::~Kobject() { - LOG_TRACE("Kobject delete (generic)", "del", current(), __fmt_kobj_destroy, - Log_destroy *l = tbe->payload(); + LOG_TRACE("Kobject delete (generic)", "del", current(), Log_destroy, l->id = dbg_id(); l->obj = this; l->type = "unk"); @@ -207,15 +205,14 @@ INTERFACE [debug]: EXTENSION class Kobject { protected: - struct Log_destroy + struct Log_destroy : public Tb_entry { Kobject *obj; Mword id; char const *type; Mword ram; + unsigned print(int max, char *buf) const; }; - - static unsigned log_fmt(Tb_entry *, int max, char *buf) asm ("__fmt_kobj_destroy"); }; //--------------------------------------------------------------------------- @@ -242,8 +239,7 @@ Kobject::dbg_info() const IMPLEMENT unsigned -Kobject::log_fmt(Tb_entry *e, int max, char *buf) +Kobject::Log_destroy::print(int max, char *buf) const { - Log_destroy *l = e->payload(); - return snprintf(buf, max, "obj=%lx [%s] (%p) ram=%lx", l->id, l->type, l->obj, l->ram); + return snprintf(buf, max, "obj=%lx [%s] (%p) ram=%lx", id, type, obj, ram); } diff --git a/kernel/fiasco/src/kern/kobject_dbg.cpp b/kernel/fiasco/src/kern/kobject_dbg.cpp index 7d1b1503..19295879 100644 --- a/kernel/fiasco/src/kern/kobject_dbg.cpp +++ b/kernel/fiasco/src/kern/kobject_dbg.cpp @@ -118,7 +118,7 @@ Kobject_dbg::obj_to_id(void const *o) PROTECTED Kobject_dbg::Kobject_dbg() { - Lock_guard guard(&_kobjects_lock); + auto guard = lock_guard(_kobjects_lock); _dbg_id = _next_dbg_id++; _kobjects.push_back(this); @@ -128,7 +128,7 @@ IMPLEMENT inline Kobject_dbg::~Kobject_dbg() { { - Lock_guard guard(&_kobjects_lock); + auto guard = lock_guard(_kobjects_lock); _kobjects.remove(this); } diff --git a/kernel/fiasco/src/kern/kobject_helper.cpp b/kernel/fiasco/src/kern/kobject_helper.cpp index 8ec6a804..eb84b887 100644 --- a/kernel/fiasco/src/kern/kobject_helper.cpp +++ b/kernel/fiasco/src/kern/kobject_helper.cpp @@ -2,6 +2,7 @@ INTERFACE: #include "kobject.h" #include "thread.h" +#include class Kobject_helper_base { @@ -26,14 +27,14 @@ private: public: - explicit Kobject_h() : Base() {} + explicit Kobject_h() {} - template< typename A > - explicit Kobject_h(A a) : Base(a) {} + template< typename... A > + explicit Kobject_h(A&&... args) : Base(cxx::forward(args)...) {} void invoke(L4_obj_ref self, Mword rights, Syscall_frame *f, Utcb *u) { - L4_msg_tag res(0); + L4_msg_tag res(no_reply()); if (EXPECT_TRUE(self.op() & L4_obj_ref::Ipc_send)) res = static_cast(this)->T::kinvoke(self, rights, f, (Utcb const *)u, self.have_recv() ? u : utcb_dummy()); diff --git a/kernel/fiasco/src/kern/logdefs.h b/kernel/fiasco/src/kern/logdefs.h new file mode 100644 index 00000000..739e2d7e --- /dev/null +++ b/kernel/fiasco/src/kern/logdefs.h @@ -0,0 +1,159 @@ +// ### How to create a tracebuffer entry ### +// +// If you only need a temporary debugging aid then you can use one of +// the standard kernel logging events: +// +// LOG_MSG(Context *context, const char *msg) +// - context is something like context_of(this) or current_context() +// or 0 if there is no context available +// - msg should be displayed in the tracebuffer view +// +// LOG_MSG_3VAL(Context *context, const char *msg, +// Mword val1, Mword val2, Mword val3) +// - context and msg can be used the same way LOG_MSG does +// - val1, val2, and val3 are values that will be displayed in +// the tracebuffer view as hexadecimal values +// +// +#pragma once + +#include "globalconfig.h" + +#if !defined(CONFIG_JDB) + +#define LOG_TRACE_COND(name, sc, ctx, fmt, cond, code...) do { } while (0) +#define LOG_TRACE(name, sc, ctx, fmt, code...) do { } while (0) +#define LOG_CONTEXT_SWITCH do { } while (0) +#define LOG_TRAP do { } while (0) +#define LOG_TRAP_N(n) do { } while (0) +#define LOG_SCHED_SAVE(n) do { } while (0) +#define LOG_SCHED_LOAD(n) do { } while (0) + +#else + +#include "globals.h" +#include "jdb_tbuf.h" +#include "cpu_lock.h" +#include "lock_guard.h" +#include "processor.h" + +#define LOG_TRACE_COND(name, sc, ctx, fmt, cond, code...) \ + BEGIN_LOG_EVENT(name, sc, fmt) \ + if (cond) \ + { \ + fmt *l = Jdb_tbuf::new_entry(); \ + l->set_global(__do_log__, ctx, Proc::program_counter()); \ + {code;} \ + Jdb_tbuf::commit_entry(); \ + } \ + END_LOG_EVENT + +#define LOG_TRACE(name, sc, ctx, fmt, code...) \ + LOG_TRACE_COND(name, sc, ctx, fmt, true, code) + +#define LOG_CONTEXT_SWITCH \ + LOG_TRACE("Context switch", "csw", this, Tb_entry_ctx_sw, \ + Sched_context *cs = Sched_context::rq.current().current_sched(); \ + l->from_space = space(); \ + l->_ip = regs()->ip_syscall_page_user(); \ + l->dst = t; \ + l->dst_orig = t_orig; \ + l->lock_cnt = t_orig->lock_cnt(); \ + l->from_sched = cs; \ + l->from_prio = cs ? cs->prio() : 0; \ + l->kernel_ip = (Mword)__builtin_return_address(0) ) + +#define LOG_TRAP \ + LOG_TRACE_COND("Exceptions", "exc", current(), Tb_entry_trap, \ + (!ts->exclude_logging()), \ + l->set(ts->ip(), ts); \ + Jdb_tbuf::commit_entry() ) + +#define LOG_TRAP_N(n) \ + LOG_TRACE("Exceptions", "exc", current(), Tb_entry_trap, \ + Mword ip = (Mword)(__builtin_return_address(0)); \ + l->set(ip, n)) + +#define LOG_SCHED_SAVE(cs) \ + LOG_TRACE("Scheduling context save", "sch", current(), Tb_entry_sched,\ + l->mode = 0; \ + l->owner = cs->context(); \ + l->id = 0; \ + l->prio = cs->prio(); \ + l->left = cs->left(); \ + l->quantum = 0; /*cs->quantum()*/) + +#define LOG_SCHED_LOAD(cs) \ + LOG_TRACE("Scheduling context load", "sch", current(), Tb_entry_sched,\ + l->mode = 1; \ + l->owner = cs->context(); \ + l->id = 0; \ + l->prio = cs->prio(); \ + l->left = cs->left(); \ + l->quantum = 0; /*cs->quantum()*/) + +/* + * Kernel instrumentation macro used by fm3. Do not remove! + */ +#define LOG_MSG(context, text) \ + do { \ + /* The cpu_lock is needed since virq::hit() depends on it */ \ + auto guard = lock_guard(cpu_lock); \ + Tb_entry_ke *tb = static_cast(Jdb_tbuf::new_entry()); \ + tb->set_const(context, Proc::program_counter(), text); \ + Jdb_tbuf::commit_entry(); \ + } while (0) + +/* + * Kernel instrumentation macro used by fm3. Do not remove! + */ +#define LOG_MSG_3VAL(context, text, v1, v2, v3) \ + do { \ + /* The cpu_lock is needed since virq::hit() depends on it */ \ + auto guard = lock_guard(cpu_lock); \ + Tb_entry_ke_reg *tb = Jdb_tbuf::new_entry(); \ + tb->set_const(context, Proc::program_counter(), text, v1, v2, v3); \ + Jdb_tbuf::commit_entry(); \ + } while (0) + +#endif // !CONFIG_JDB + +#if defined(CONFIG_JDB) && defined(CONFIG_JDB_ACCOUNTING) + +#define CNT_CONTEXT_SWITCH Jdb_tbuf::status()->kerncnts[Kern_cnt_context_switch]++; +#define CNT_ADDR_SPACE_SWITCH Jdb_tbuf::status()->kerncnts[Kern_cnt_addr_space_switch]++; +#define CNT_IRQ Jdb_tbuf::status()->kerncnts[Kern_cnt_irq]++; +#define CNT_PAGE_FAULT Jdb_tbuf::status()->kerncnts[Kern_cnt_page_fault]++; +#define CNT_IO_FAULT Jdb_tbuf::status()->kerncnts[Kern_cnt_io_fault]++; +#define CNT_SCHEDULE Jdb_tbuf::status()->kerncnts[Kern_cnt_schedule]++; +#define CNT_EXC_IPC Jdb_tbuf::status()->kerncnts[Kern_cnt_exc_ipc]++; + +// FIXME: currently unused entries below +#define CNT_SHORTCUT_FAILED Jdb_tbuf::status()->kerncnts[Kern_cnt_shortcut_failed]++; +#define CNT_SHORTCUT_SUCCESS Jdb_tbuf::status()->kerncnts[Kern_cnt_shortcut_success]++; +#define CNT_IPC_LONG Jdb_tbuf::status()->kerncnts[Kern_cnt_ipc_long]++; +#define CNT_TASK_CREATE Jdb_tbuf::status()->kerncnts[Kern_cnt_task_create]++; +#define CNT_IOBMAP_TLB_FLUSH Jdb_tbuf::status()->kerncnts[Kern_cnt_iobmap_tlb_flush]++; + +#else + +#define CNT_CONTEXT_SWITCH do { } while (0) +#define CNT_ADDR_SPACE_SWITCH do { } while (0) +#define CNT_IRQ do { } while (0) +#define CNT_PAGE_FAULT do { } while (0) +#define CNT_IO_FAULT do { } while (0) +#define CNT_SCHEDULE do { } while (0) +#define CNT_EXC_IPC do { } while (0) + +// FIXME: currently unused entries below +#define CNT_SHORTCUT_FAILED do { } while (0) +#define CNT_SHORTCUT_SUCCESS do { } while (0) +#define CNT_IPC_LONG do { } while (0) +#define CNT_TASK_CREATE do { } while (0) +#define CNT_IOBMAP_TLB_FLUSH do { } while (0) + +#endif // CONFIG_JDB && CONFIG_JDB_ACCOUNTING + + + + diff --git a/kernel/fiasco/src/kern/map_util.cpp b/kernel/fiasco/src/kern/map_util.cpp index 41127a13..288d0ed7 100644 --- a/kernel/fiasco/src/kern/map_util.cpp +++ b/kernel/fiasco/src/kern/map_util.cpp @@ -303,7 +303,7 @@ fpage_map(Space *from, L4_fpage fp_from, Space *to, if (Map_traits::match(fp_from, fp_to)) return mem_map(from, fp_from, to, fp_to, control); -#ifdef CONFIG_IO_PROT +#ifdef CONFIG_PF_PC if (Map_traits::match(fp_from, fp_to)) return io_map(from, fp_from, to, fp_to, control); #endif @@ -489,7 +489,7 @@ map(MAPDB* mapdb, if (has_superpages && i_size == from_superpage_size) { if (i_size > snd_size - // want to send less that a superpage? + // want to send less than a superpage? || i_size > r_size // not enough space for superpage map? || snd_addr.offset(Size(SUPERPAGE_SIZE)) // snd page not aligned? || rcv_addr.offset(Size(SUPERPAGE_SIZE)) // rcv page not aligned? @@ -669,7 +669,6 @@ unmap(MAPDB* mapdb, SPACE* space, Space *space_id, { typedef typename SPACE::Size Size; - typedef typename SPACE::Addr Addr; typedef typename MAPDB::Mapping Mapping; typedef typename MAPDB::Iterator Iterator; typedef typename MAPDB::Frame Frame; diff --git a/kernel/fiasco/src/kern/mapdb.cpp b/kernel/fiasco/src/kern/mapdb.cpp index 3dd64ed2..3796072e 100644 --- a/kernel/fiasco/src/kern/mapdb.cpp +++ b/kernel/fiasco/src/kern/mapdb.cpp @@ -238,7 +238,7 @@ Physframe::~Physframe() { if (tree) { - Lock_guard guard(&lock); + auto guard = lock_guard(lock); // Find next-level trees. for (Mapping* m = tree->mappings(); @@ -333,7 +333,7 @@ Treemap_ops::grant(Treemap *submap, Space *new_space, Page_number va) const Physframe* subframe = submap->frame(key); if (Mapping_tree* tree = subframe->tree.get()) { - Lock_guard guard(&subframe->lock); + auto guard = lock_guard(subframe->lock); tree->mappings()->set_space(new_space); tree->mappings()->set_page(va + (key >> (_page_shift - submap->_page_shift))); } @@ -375,7 +375,7 @@ Treemap_ops::flush(Treemap *submap, Physframe* subframe = submap->frame(i); - Lock_guard guard(&subframe->lock); + auto guard = lock_guard(subframe->lock); if (offs_begin <= page_offs_begin && offs_end >= page_offs_end) subframe->tree.reset(); diff --git a/kernel/fiasco/src/kern/mapping_tree.cpp b/kernel/fiasco/src/kern/mapping_tree.cpp index f9ec5665..adbcc133 100644 --- a/kernel/fiasco/src/kern/mapping_tree.cpp +++ b/kernel/fiasco/src/kern/mapping_tree.cpp @@ -866,7 +866,8 @@ Mapping * Base_mappable::lookup(Space *space, Page_number va) { // get and lock the tree. - lock.lock(); + if (EXPECT_FALSE(lock.lock() == Lock::Invalid)) + return 0; Mapping_tree *t = tree.get(); assert (t); if (Mapping *m = t->lookup(space, va)) diff --git a/kernel/fiasco/src/kern/mp_lock.cpp b/kernel/fiasco/src/kern/mp_lock.cpp index 78988bcb..5d695c3b 100644 --- a/kernel/fiasco/src/kern/mp_lock.cpp +++ b/kernel/fiasco/src/kern/mp_lock.cpp @@ -33,10 +33,10 @@ Mp_lock::test_and_set() Context *const c = current(); - Lock_guard g(&cpu_lock); + auto g = lock_guard(cpu_lock); { - Lock_guard guard(_q.q_lock()); + auto guard = lock_guard(_q.q_lock()); if (EXPECT_FALSE(_q.invalid())) return Invalid; @@ -89,7 +89,7 @@ Mp_lock::clear() Queue_item *f; { - Lock_guard guard(_q.q_lock()); + auto guard = lock_guard(_q.q_lock()); //LOG_MSG_3VAL(current(), "clear", (Mword)this, current_cpu(), *((Mword*)this)); assert_kdb (_q.blocked()); @@ -114,10 +114,10 @@ Mp_lock::wait_free() Context *const c = current(); - Lock_guard g(&cpu_lock); + auto g = lock_guard(cpu_lock); { - Lock_guard guard(_q.q_lock()); + auto guard = lock_guard(_q.q_lock()); assert_kdb (invalid()); if (!_q.blocked()) @@ -157,14 +157,14 @@ void Mp_lock::invalidate() { { - Lock_guard guard(_q.q_lock()); + auto guard = lock_guard(_q.q_lock()); _q.invalidate(); } Queue_item *f; while (1) { - Lock_guard guard(_q.q_lock()); + auto guard = lock_guard(_q.q_lock()); f = _q.first(); //LOG_MSG_3VAL(current(), "deq", Mword(f), 0, 0); diff --git a/kernel/fiasco/src/kern/obj_ref_ptr.cpp b/kernel/fiasco/src/kern/obj_ref_ptr.cpp index fe38d442..f72596a3 100644 --- a/kernel/fiasco/src/kern/obj_ref_ptr.cpp +++ b/kernel/fiasco/src/kern/obj_ref_ptr.cpp @@ -29,8 +29,8 @@ private: { if (_o) { - Lock_guard guard(&cpu_lock); - _o->inc_ref_cnt(); + auto guard = lock_guard(cpu_lock); + _o->inc_ref_cnt(); } } diff --git a/kernel/fiasco/src/kern/per_cpu_data.cpp b/kernel/fiasco/src/kern/per_cpu_data.cpp index 90b5a139..32d53a07 100644 --- a/kernel/fiasco/src/kern/per_cpu_data.cpp +++ b/kernel/fiasco/src/kern/per_cpu_data.cpp @@ -18,6 +18,7 @@ INTERFACE [!mp]: INTERFACE: #include "static_init.h" +#include "config.h" #include "context_base.h" #include @@ -55,6 +56,16 @@ public: Per_cpu(); explicit Per_cpu(bool); + template + unsigned find_cpu(TEST const &test) const + { + for (unsigned i = 0; i < Config::Max_num_cpus; ++i) + if (valid(i) && test(cpu(i))) + return i; + + return ~0U; + } + private: T _d; }; @@ -186,8 +197,10 @@ private: private: unsigned _len; }; + protected: - static long _offsets[Config::Max_num_cpus] asm ("PER_CPU_OFFSETS"); + enum { Num_cpus = Config::Max_num_cpus + 1 }; // add one for the never running CPU + static long _offsets[Num_cpus] asm ("PER_CPU_OFFSETS"); static unsigned late_ctor_start; static Ctor_vector ctors; }; @@ -200,7 +213,7 @@ IMPLEMENTATION [mp]: #include #include -long Per_cpu_data::_offsets[Config::Max_num_cpus]; +long Per_cpu_data::_offsets[Per_cpu_data::Num_cpus]; unsigned Per_cpu_data::late_ctor_start; Per_cpu_data::Ctor_vector Per_cpu_data::ctors; @@ -223,7 +236,7 @@ Per_cpu_data::Ctor_vector::push_back(void (*func)(void*,unsigned), void *base) IMPLEMENT inline bool Per_cpu_data::valid(unsigned cpu) -{ return cpu < Config::Max_num_cpus && _offsets[cpu] != -1; } +{ return cpu < Num_cpus && _offsets[cpu] != -1; } IMPLEMENT inline template< typename T > T const &Per_cpu::cpu(unsigned cpu) const @@ -254,7 +267,7 @@ template< typename T > void Per_cpu::ctor_wo_arg(void *obj, unsigned cpu) { //printf("Per_cpu::ctor_wo_arg(obj=%p, cpu=%u -> %p)\n", obj, cpu, &(reinterpret_cast*>(obj)->cpu(cpu))); - new (&reinterpret_cast*>(obj)->cpu(cpu)) T(); + new (&reinterpret_cast*>(obj)->cpu(cpu)) T; } PRIVATE static @@ -274,7 +287,7 @@ IMPLEMENT void Per_cpu_data::init_ctors() { - for (unsigned i = 0; i < Config::Max_num_cpus; ++i) + for (unsigned i = 0; i < Num_cpus; ++i) _offsets[i] = -1; } diff --git a/kernel/fiasco/src/kern/per_cpu_data_alloc.cpp b/kernel/fiasco/src/kern/per_cpu_data_alloc.cpp index 8ce44663..86224572 100644 --- a/kernel/fiasco/src/kern/per_cpu_data_alloc.cpp +++ b/kernel/fiasco/src/kern/per_cpu_data_alloc.cpp @@ -28,7 +28,7 @@ IMPLEMENTATION [mp]: IMPLEMENT bool Per_cpu_data_alloc::alloc(unsigned cpu) { - if (cpu >= Config::Max_num_cpus || valid(cpu)) + if (cpu >= Num_cpus || valid(cpu)) return false; extern char _per_cpu_data_start[]; @@ -53,8 +53,10 @@ bool Per_cpu_data_alloc::alloc(unsigned cpu) memset(per_cpu, 0, size); _offsets[cpu] = per_cpu - _per_cpu_data_start; - printf("Allocate %u bytes (%uKB) for CPU[%u] local storage (offset=%lx)\n", - size, (size + 513) / 1024, cpu, _offsets[cpu]); + printf("Allocate %u bytes (%uKB) for CPU[%u] local storage (offset=%lx, %p-%p)\n", + size, (size + 513) / 1024, cpu, _offsets[cpu], + _per_cpu_data_start + _offsets[cpu], + _per_cpu_data_end + _offsets[cpu]); return true; diff --git a/kernel/fiasco/src/kern/pit-i8254.cpp b/kernel/fiasco/src/kern/pit-i8254.cpp index f4151261..92e6d33d 100644 --- a/kernel/fiasco/src/kern/pit-i8254.cpp +++ b/kernel/fiasco/src/kern/pit-i8254.cpp @@ -44,13 +44,26 @@ Pit::setup_channel2_to_20hz() //---------------------------------------------------------------------------- IMPLEMENTATION[i8254 & pit_timer]: +PRIVATE static +void +Pit::set_freq(unsigned freq) +{ + // set counter channel 0 to binary, mode2, lsb/msb + Io::out8_p(0x34, 0x43); + + // set counter frequency + const unsigned latch = Clock_tick_rate / freq; + Io::out8_p(latch & 0xff, 0x40); + Io::out8_p(latch >> 8, 0x40); +} + // set up timer interrupt (~ 1ms) -PUBLIC static inline NEEDS ["io.h", Pit::set_freq_normal] +PUBLIC static inline NEEDS ["io.h", Pit::set_freq] void Pit::init() { // set counter frequency to ~1000 Hz (1000.151 Hz) - set_freq_normal(); + set_freq(1000); } PUBLIC static inline NEEDS ["io.h", Pit::set_freq] @@ -60,43 +73,9 @@ Pit::init(unsigned freq) set_freq(freq); } -PUBLIC static inline NEEDS ["io.h"] +PUBLIC static inline NEEDS ["io.h", Pit::set_freq] void Pit::set_freq_slow() { - // set counter channel 0 to binary, mode2, lsb/msb - Io::out8_p(0x34, 0x43); - - // set counter frequency to 32 Hz - const unsigned latch = Clock_tick_rate / 32; - Io::out8_p(latch & 0xff, 0x40); - Io::out8_p(latch >> 8, 0x40); + set_freq(32); } - -PUBLIC static inline NEEDS ["io.h"] -void -Pit::set_freq_normal() -{ - // set counter channel 0 to binary, mode2, lsb/msb - Io::out8_p(0x34, 0x43); - - // set counter frequency to ~1000 Hz (1000.151 Hz) - const unsigned latch = Clock_tick_rate / 1000; - Io::out8_p(latch & 0xff, 0x40); - Io::out8_p(latch >> 8, 0x40); -} - -PUBLIC static inline NEEDS ["io.h"] -void -Pit::set_freq(unsigned freq) -{ - // set counter channel 0 to binary, mode2, lsb/msb - Io::out8_p(0x34, 0x43); - - // set counter frequency - const unsigned latch = Clock_tick_rate / freq; - Io::out8_p(latch & 0xff, 0x40); - Io::out8_p(latch >> 8, 0x40); -} - - diff --git a/kernel/fiasco/src/kern/platform_control.cpp b/kernel/fiasco/src/kern/platform_control.cpp new file mode 100644 index 00000000..339ac82d --- /dev/null +++ b/kernel/fiasco/src/kern/platform_control.cpp @@ -0,0 +1,41 @@ +INTERFACE: + +class Platform_control +{ +public: + static void init(unsigned); + static bool cpu_offline_available(); + static int resume_cpu(unsigned cpu); + static int suspend_cpu(unsigned cpu); + static int system_suspend(); +}; + +// ------------------------------------------------------------------------ +IMPLEMENTATION [!cpu_suspend]: + +#include "l4_types.h" + +IMPLEMENT inline +void +Platform_control::init(unsigned) +{} + +IMPLEMENT inline +bool +Platform_control::cpu_offline_available() +{ return false; } + +IMPLEMENT inline NEEDS["l4_types.h"] +int +Platform_control::suspend_cpu(unsigned) +{ return -L4_err::ENodev; } + +IMPLEMENT inline NEEDS["l4_types.h"] +int +Platform_control::resume_cpu(unsigned) +{ return -L4_err::ENodev; } + +IMPLEMENT inline NEEDS["l4_types.h"] +int +Platform_control::system_suspend() +{ return -L4_err::EBusy; } diff --git a/kernel/fiasco/src/kern/platform_control_object.cpp b/kernel/fiasco/src/kern/platform_control_object.cpp new file mode 100644 index 00000000..fe347547 --- /dev/null +++ b/kernel/fiasco/src/kern/platform_control_object.cpp @@ -0,0 +1,105 @@ +IMPLEMENTATION: +#include "kobject_helper.h" +#include "platform_control.h" + +namespace { + +class Pfc : public Kobject_h +{ + FIASCO_DECLARE_KOBJ(); + enum class Op + { + Suspend_cpu = 0x0, + Resume_cpu = 0x1, + Suspend_system = 0x2, + }; + + Pfc() { initial_kobjects.register_obj(this, 8); } + + L4_msg_tag sys_suspend_cpu(unsigned char /*rights*/, Syscall_frame *f, + Utcb const *utcb) + { + if (!Platform_control::cpu_offline_available()) + return commit_result(-L4_err::ENosys); + + if (f->tag().words() < 2) + return commit_result(-L4_err::EInval); + + unsigned cpu = utcb->values[1]; + + if (cpu >= Config::Max_num_cpus || !Per_cpu_data::valid(cpu)) + return commit_result(-L4_err::EInval); + + if (!Cpu::online(cpu)) + return commit_result(-L4_err::EInval); + + Platform_control::suspend_cpu(cpu); + return commit_result(0); + } + + L4_msg_tag + sys_resume_cpu(unsigned char /*rights*/, Syscall_frame *f, + Utcb const *utcb) + { + if (!Platform_control::cpu_offline_available()) + return commit_result(-L4_err::ENosys); + + if (f->tag().words() < 2) + return commit_result(-L4_err::EInval); + + unsigned cpu = utcb->values[1]; + + if (cpu >= Config::Max_num_cpus || !Per_cpu_data::valid(cpu)) + return commit_result(-L4_err::EInval); + + if (Cpu::online(cpu)) + return commit_result(-L4_err::EInval); + + int r = Platform_control::resume_cpu(cpu); + return commit_result(r); + } + + L4_msg_tag + sys_suspend_system(unsigned char, Syscall_frame *, Utcb const *) + { + unsigned c = 0; + for (unsigned cpu = 0; cpu < Config::Max_num_cpus; ++cpu) + c += Cpu::online(cpu) ? 1 : 0; + if (c > 1) + return commit_result(-L4_err::EBusy); + + return commit_result(Platform_control::system_suspend()); + } + + static Pfc pfc; + +public: + L4_msg_tag kinvoke(L4_obj_ref, Mword rights, Syscall_frame *f, + Utcb const *iutcb, Utcb *) + { +#if 0 + switch (f->tag().proto()) + { + case L4_msg_tag::Label_scheduler: + break; + default: + return commit_result(-L4_err::EBadproto); + } +#endif + + switch (static_cast(iutcb->values[0])) + { + case Op::Suspend_cpu: return sys_suspend_cpu(rights, f, iutcb); + case Op::Resume_cpu: return sys_resume_cpu(rights, f, iutcb); + case Op::Suspend_system: return sys_suspend_system(rights, f, iutcb); + default: return commit_result(-L4_err::ENosys); + } + } + +}; + +FIASCO_DEFINE_KOBJ(Pfc); + +Pfc Pfc::pfc; + +} diff --git a/kernel/fiasco/src/kern/poll_timeout_kclock.h b/kernel/fiasco/src/kern/poll_timeout_kclock.h new file mode 100644 index 00000000..3202436a --- /dev/null +++ b/kernel/fiasco/src/kern/poll_timeout_kclock.h @@ -0,0 +1,39 @@ +#pragma once + +#include "assert.h" +#include "cpu_lock.h" +#include "kip.h" +#include "processor.h" + +class Poll_timeout_kclock +{ +public: + Poll_timeout_kclock(unsigned poll_time_us) + { + set(poll_time_us); + } + + void set(unsigned poll_time_us) + { + _timeout = Kip::k()->clock + poll_time_us; + _last_check = true; + } + + bool test(bool expression = true) + { + // need open interrupts, otherwise clock won't tick + assert(!cpu_lock.test()); + + if (!expression) + return false; + + Proc::irq_chance(); + return _last_check = Kip::k()->clock < _timeout; + } + + bool timed_out() const { return !_last_check; } + +private: + Cpu_time _timeout; + bool _last_check; +}; diff --git a/kernel/fiasco/src/kern/ppc32/cpu-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/cpu-ppc32.cpp index 3d9aede5..a0b89c5b 100644 --- a/kernel/fiasco/src/kern/ppc32/cpu-ppc32.cpp +++ b/kernel/fiasco/src/kern/ppc32/cpu-ppc32.cpp @@ -58,6 +58,11 @@ Cpu::init(bool is_boot_cpu) printf("Timebase: %lu\n", Boot_info::get_time_base()); } +PUBLIC inline +unsigned +Cpu::phys_id() const +{ return _phys_id; } + IMPLEMENT void Cpu::early_init() diff --git a/kernel/fiasco/src/kern/ppc32/mem_space-htab.cpp b/kernel/fiasco/src/kern/ppc32/mem_space-htab.cpp index 617dbf8e..4c0f8d61 100644 --- a/kernel/fiasco/src/kern/ppc32/mem_space-htab.cpp +++ b/kernel/fiasco/src/kern/ppc32/mem_space-htab.cpp @@ -233,7 +233,7 @@ PRIVATE inline Mem_space::Status Mem_space::pte_attrib_upgrade(Address pte_addr, unsigned page_attribs) { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); Pte_htab * pte_phys = Pte_htab::addr_to_pte(pte_addr); if(EXPECT_FALSE((pte_phys->phys() | page_attribs) == pte_phys->phys())) @@ -315,7 +315,7 @@ IMPLEMENT unsigned long Mem_space::v_delete_htab(Address pte_addr, unsigned page_attribs = Page_all_attribs) { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); unsigned long ret; Pte_htab *pte_phys = Pte_htab::addr_to_pte(pte_addr); diff --git a/kernel/fiasco/src/kern/ppc32/mem_space-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/mem_space-ppc32.cpp index e4f77248..b3a81baa 100644 --- a/kernel/fiasco/src/kern/ppc32/mem_space-ppc32.cpp +++ b/kernel/fiasco/src/kern/ppc32/mem_space-ppc32.cpp @@ -292,7 +292,7 @@ Mem_space::try_htab_fault(Address virt) Status status; // insert in htab { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); status = v_insert_htab(phys, virt, &pte_ptr, &evict); diff --git a/kernel/fiasco/src/kern/ppc32/paging-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/paging-ppc32.cpp index f9cacf04..2a642691 100644 --- a/kernel/fiasco/src/kern/ppc32/paging-ppc32.cpp +++ b/kernel/fiasco/src/kern/ppc32/paging-ppc32.cpp @@ -360,7 +360,7 @@ bool Pte_htab::pte_lookup(Pte_base *e, Address *phys = 0, unsigned *page_attribs = 0) { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); Address raw; diff --git a/kernel/fiasco/src/kern/ppc32/tb_entry-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/tb_entry-ppc32.cpp index b5e2453a..07073857 100644 --- a/kernel/fiasco/src/kern/ppc32/tb_entry-ppc32.cpp +++ b/kernel/fiasco/src/kern/ppc32/tb_entry-ppc32.cpp @@ -1,6 +1,6 @@ INTERFACE [ppc32]: -EXTENSION class Tb_entry_base +EXTENSION class Tb_entry { public: enum @@ -9,33 +9,15 @@ public: }; }; -/** logged kernel event plus register content. */ -class Tb_entry_ke_reg : public Tb_entry -{ -private: - struct Payload - { - union { - char _msg[16]; ///< debug message - struct { - char _dsc[2]; - char const* _const_msg; - }; - }; - Mword _r3, _r4, _r5; ///< registers - }; -}; - /** logged trap. */ class Tb_entry_trap : public Tb_entry { private: - struct Payload - { - Unsigned8 _trapno; - Unsigned16 _error; - Mword _cpsr, _sp; - }; + Unsigned8 _trapno; + Unsigned16 _error; + Mword _cpsr, _sp; +public: + unsigned print(int max, char *buf) const; }; // -------------------------------------------------------------------- @@ -46,63 +28,6 @@ void Tb_entry::rdtsc() {} -PUBLIC inline -const char * -Tb_entry_ke_reg::msg() const -{ - return payload()->_dsc[0] == 0 && payload()->_dsc[1] == 1 - ? payload()->_const_msg : payload()->_msg; -} - -PUBLIC inline -Mword -Tb_entry_ke_reg::val1() const -{ return payload()->_r3; } - -PUBLIC inline -Mword -Tb_entry_ke_reg::val2() const -{ return payload()->_r4; } - -PUBLIC inline -Mword -Tb_entry_ke_reg::val3() const -{ return payload()->_r5; } - -PUBLIC inline -void -Tb_entry_ke_reg::set(Context const *ctx, Mword eip, Mword v1, Mword v2, Mword v3) -{ - set_global(Tbuf_ke_reg, ctx, eip); - payload()->_r3 = v1; - payload()->_r4 = v2; - payload()->_r5 = v3; -} - -PUBLIC inline -void -Tb_entry_ke_reg::set_const(Context const *ctx, Mword eip, const char * const msg, - Mword v1, Mword v2, Mword v3) -{ - set(ctx, eip, v1, v2, v3); - payload()->_dsc[0] = 0; payload()->_dsc[1] = 1; - payload()->_const_msg = msg; -} - -PUBLIC inline -void -Tb_entry_ke_reg::set_buf(unsigned i, char c) -{ - if (i < sizeof(payload()->_msg) - 1) - payload()->_msg[i] = c >= ' ' ? c : '.'; -} - -PUBLIC inline -void -Tb_entry_ke_reg::term_buf(unsigned i) -{payload()->_msg[i < sizeof(payload()->_msg)-1 ? i - : sizeof(payload()->_msg)-1] = '\0';} - // ------------------ PUBLIC inline Unsigned16 @@ -112,17 +37,17 @@ Tb_entry_trap::cs() const PUBLIC inline Unsigned8 Tb_entry_trap::trapno() const -{ return payload()->_trapno; } +{ return _trapno; } PUBLIC inline Unsigned16 Tb_entry_trap::error() const -{ return payload()->_error; } +{ return _error; } PUBLIC inline Mword Tb_entry_trap::sp() const -{ return payload()->_sp; } +{ return _sp; } PUBLIC inline Mword @@ -136,16 +61,16 @@ Tb_entry_trap::eax() const PUBLIC inline NEEDS ["trap_state.h"] void -Tb_entry_trap::set(Context const *ctx, Mword pc, Trap_state *) +Tb_entry_trap::set(Mword pc, Trap_state *) { - set_global(Tbuf_trap, ctx, pc); + _ip = pc; // More... } -PUBLIC inline NEEDS ["trap_state.h"] +PUBLIC inline void -Tb_entry_trap::set(Context const *ctx, Mword pc, Mword ) +Tb_entry_trap::set(Mword pc, Mword ) { - set_global(Tbuf_trap, ctx, pc); + _ip = pc; } diff --git a/kernel/fiasco/src/kern/ppc32/thread-jdb.cpp b/kernel/fiasco/src/kern/ppc32/thread-jdb.cpp index bcd8ee26..482095d0 100644 --- a/kernel/fiasco/src/kern/ppc32/thread-jdb.cpp +++ b/kernel/fiasco/src/kern/ppc32/thread-jdb.cpp @@ -54,7 +54,7 @@ int Thread::call_nested_trap_handler(Trap_state *ts) { unsigned phys_cpu = Proc::cpu_id(); - unsigned log_cpu = Cpu::p2l(phys_cpu); + unsigned log_cpu = Cpu::cpus.find_cpu(Cpu::By_phys_id(phys_cpu)); if (log_cpu == ~0U) { printf("Trap on unknown CPU phys_id=%x\n", phys_cpu); diff --git a/kernel/fiasco/src/kern/ppc32/thread-ppc32.cpp b/kernel/fiasco/src/kern/ppc32/thread-ppc32.cpp index 23f3d450..91618410 100644 --- a/kernel/fiasco/src/kern/ppc32/thread-ppc32.cpp +++ b/kernel/fiasco/src/kern/ppc32/thread-ppc32.cpp @@ -248,7 +248,7 @@ Thread::Thread() _del_observer(0) { - assert(state() == Thread_invalid); + assert(state(false) == Thread_invalid); inc_ref(); _space.space(Kernel_task::kernel_task()); @@ -271,7 +271,7 @@ Thread::Thread() r->sp(0); r->ip(0); - state_add(Thread_dead | Thread_suspended); + state_add_dirty(Thread_dead, false); // ok, we're ready to go! } diff --git a/kernel/fiasco/src/kern/ppc32/trap_state.cpp b/kernel/fiasco/src/kern/ppc32/trap_state.cpp index 3861b96a..020d6c14 100644 --- a/kernel/fiasco/src/kern/ppc32/trap_state.cpp +++ b/kernel/fiasco/src/kern/ppc32/trap_state.cpp @@ -18,6 +18,7 @@ class Trap_state : public Trap_state_regs, public Syscall_frame, { public: typedef int (*Handler)(Trap_state*, unsigned cpu); + bool exclude_logging() { return false; } }; diff --git a/kernel/fiasco/src/kern/prio_list.cpp b/kernel/fiasco/src/kern/prio_list.cpp index 8f6e2836..ea47b443 100644 --- a/kernel/fiasco/src/kern/prio_list.cpp +++ b/kernel/fiasco/src/kern/prio_list.cpp @@ -96,9 +96,10 @@ PUBLIC inline Prio_list_elem * Prio_list::next(Prio_list_elem *e) const { - if (P_list::in_list(*++S_list::iter(e))) - return *++P_list::iter(e); - return *++S_list::iter(e); + S_list::Iterator i = ++S_list::iter(e); + if (P_list::in_list(*i)) + return *++P_list::iter(*i); + return *i; } /** diff --git a/kernel/fiasco/src/kern/queue.cpp b/kernel/fiasco/src/kern/queue.cpp index f7b20d64..36559d26 100644 --- a/kernel/fiasco/src/kern/queue.cpp +++ b/kernel/fiasco/src/kern/queue.cpp @@ -72,6 +72,7 @@ void Queue::enqueue(Queue_item *i) { // Queue i at the end of the list + assert_kdb (i && !i->queued()); assert_kdb (_m.head().test()); i->_q = this; _m.push_back(i); diff --git a/kernel/fiasco/src/kern/ram_quota.cpp b/kernel/fiasco/src/kern/ram_quota.cpp index 60c52d0a..a18ae6eb 100644 --- a/kernel/fiasco/src/kern/ram_quota.cpp +++ b/kernel/fiasco/src/kern/ram_quota.cpp @@ -50,7 +50,7 @@ PUBLIC bool Ram_quota::alloc(signed long bytes) { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); if (unlimited() || _current + bytes <= _max) { _current += bytes; diff --git a/kernel/fiasco/src/kern/rcupdate.cpp b/kernel/fiasco/src/kern/rcupdate.cpp index 1560d104..398f0724 100644 --- a/kernel/fiasco/src/kern/rcupdate.cpp +++ b/kernel/fiasco/src/kern/rcupdate.cpp @@ -148,15 +148,18 @@ private: // ------------------------------------------------------------------------ INTERFACE [debug]: +#include "tb_entry.h" + EXTENSION class Rcu { public: - struct Log_rcu + struct Log_rcu : public Tb_entry { unsigned cpu; Rcu_item *item; void *cb; unsigned char event; + unsigned print(int max, char *buf) const; } __attribute__((packed)); enum Rcu_events @@ -172,15 +175,12 @@ IMPLEMENTATION [debug]: #include "logdefs.h" -unsigned log_fmt(Tb_entry *, int max, char *buf) asm ("__fmt_rcu"); - - IMPLEMENT -unsigned log_fmt(Tb_entry *e, int max, char *buf) +unsigned +Rcu::Log_rcu::print(int max, char *buf) const { - Rcu::Log_rcu *p = e->payload(); char const *events[] = { "call", "process"}; - return snprintf(buf, max, "rcu-%s (cpu=%u) item=%p", events[p->event], p->cpu, p->item); + return snprintf(buf, max, "rcu-%s (cpu=%u) item=%p", events[event], cpu, item); } @@ -272,7 +272,7 @@ Rcu_data::do_batch() //_d.head(l); { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); _len -= count; } #if 0 @@ -307,7 +307,7 @@ Rcu::enter_idle(unsigned cpu) if (EXPECT_TRUE(!rdp->_idle)) { rdp->_idle = true; - Lock_guard_lock)> guard(&rcu()->_lock); + auto guard = lock_guard(rcu()->_lock); rcu()->_active_cpus.clear(cpu); } } @@ -320,7 +320,7 @@ Rcu::leave_idle(unsigned cpu) if (EXPECT_FALSE(rdp->_idle)) { rdp->_idle = false; - Lock_guard_lock)> guard(&rcu()->_lock); + auto guard = lock_guard(rcu()->_lock); rcu()->_active_cpus.set(cpu); rdp->_q_batch = Rcu::rcu()->_current; } @@ -363,7 +363,7 @@ Rcu_data::check_quiescent_state(Rcu_glbl *rgp) _pending = 0; - Lock_guard_lock)> guard(&rgp->_lock); + auto guard = lock_guard(rgp->_lock); if (EXPECT_TRUE(_q_batch == rgp->_current)) rgp->cpu_quiet(_cpu); @@ -375,14 +375,13 @@ void Rcu::call(Rcu_item *i, bool (*cb)(Rcu_item *)) { i->_call_back = cb; - LOG_TRACE("Rcu call", "rcu", ::current(), __fmt_rcu, - Log_rcu *p = tbe->payload(); - p->cpu = current_cpu(); - p->event = Rcu_call; - p->item = i; - p->cb = (void*)cb); + LOG_TRACE("Rcu call", "rcu", ::current(), Log_rcu, + l->cpu = current_cpu(); + l->event = Rcu_call; + l->item = i; + l->cb = (void*)cb); - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); Rcu_data *rdp = &_rcu_data.current(); rdp->enqueue(i); @@ -392,7 +391,7 @@ PRIVATE void Rcu_data::move_batch(Rcu_list &l) { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); _n.append(l); } @@ -407,7 +406,7 @@ Rcu_data::~Rcu_data() Rcu_glbl *rgp = Rcu::rcu(); { - Lock_guard_lock)> guard(&rgp->_lock); + auto guard = lock_guard(rgp->_lock); if (rgp->_current != rgp->_completed) rgp->cpu_quiet(_cpu); } @@ -421,11 +420,10 @@ PUBLIC bool FIASCO_WARN_RESULT Rcu_data::process_callbacks(Rcu_glbl *rgp) { - LOG_TRACE("Rcu callbacks", "rcu", ::current(), __fmt_rcu, - Rcu::Log_rcu *p = tbe->payload(); - p->cpu = _cpu; - p->item = 0; - p->event = Rcu::Rcu_process); + LOG_TRACE("Rcu callbacks", "rcu", ::current(), Rcu::Log_rcu, + l->cpu = _cpu; + l->item = 0; + l->event = Rcu::Rcu_process); if (!_c.empty() && rgp->_completed >= _batch) _d.append(_c); @@ -433,7 +431,7 @@ Rcu_data::process_callbacks(Rcu_glbl *rgp) if (!_n.empty() && _c.empty()) { { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); _c = cxx::move(_n); } @@ -445,7 +443,7 @@ Rcu_data::process_callbacks(Rcu_glbl *rgp) if (!rgp->_next_pending) { // start the batch and schedule start if it's a new batch - Lock_guard_lock)> guard(&rgp->_lock); + auto guard = lock_guard(rgp->_lock); rgp->_next_pending = 1; rgp->start_batch(); } diff --git a/kernel/fiasco/src/kern/ready_queue_fp.cpp b/kernel/fiasco/src/kern/ready_queue_fp.cpp index e99d4ceb..6d65805d 100644 --- a/kernel/fiasco/src/kern/ready_queue_fp.cpp +++ b/kernel/fiasco/src/kern/ready_queue_fp.cpp @@ -6,6 +6,14 @@ INTERFACE [sched_fixed_prio || sched_fp_wfq]: #include "types.h" #include "globals.h" + +struct L4_sched_param_fixed_prio : public L4_sched_param +{ + enum : Smword { Class = -1 }; + Mword quantum; + unsigned short prio; +}; + template class Ready_queue_fp { @@ -99,3 +107,10 @@ Ready_queue_fp::requeue(E *i) prio_next[i->prio()].rotate_to(*++List::iter(i)); } + + +PUBLIC template inline +void +Ready_queue_fp::deblock_refill(E *) +{} + diff --git a/kernel/fiasco/src/kern/ready_queue_wfq.cpp b/kernel/fiasco/src/kern/ready_queue_wfq.cpp index 5459a21a..609b96ff 100644 --- a/kernel/fiasco/src/kern/ready_queue_wfq.cpp +++ b/kernel/fiasco/src/kern/ready_queue_wfq.cpp @@ -4,6 +4,13 @@ INTERFACE[sched_wfq || sched_fp_wfq]: #include "types.h" #include "globals.h" +struct L4_sched_param_wfq : public L4_sched_param +{ + enum : Smword { Class = -2 }; + Mword quantum; + Mword weight; +}; + template< typename E > class Ready_queue_wfq { @@ -19,11 +26,11 @@ public: void set_idle(E *sc) { idle = sc; - E::wfq_elem(sc)->_ready_link = &idle; - E::wfq_elem(sc)->_idle = 1; + _e(sc)->_ready_link = &idle; + _e(sc)->_idle = 1; } - void enqueue(E *); + void enqueue(E *, bool is_current); void dequeue(E *); E *next_to_run() const; @@ -35,6 +42,23 @@ private: E *_current_sched; unsigned _cnt; E *_heap[1024]; + + static typename E::Wfq_sc *_e(E *e) { return E::wfq_elem(e); } +}; + +template< typename IMPL > +class Sched_context_wfq +{ +public: + bool operator <= (Sched_context_wfq const &o) const + { return _impl()._dl <= o._impl()._dl; } + + bool operator < (Sched_context_wfq const &o) const + { return _impl()._dl < o._impl()._dl; } + +private: + IMPL const &_impl() const { return static_cast(*this); } + IMPL &_impl() { return static_cast(*this); } }; @@ -57,7 +81,7 @@ Ready_queue_wfq::next_to_run() const return _heap[0]; if (_current_sched) - E::wfq_elem(idle)->_dl = E::wfq_elem(_current_sched)->_dl; + _e(idle)->_dl = _e(_current_sched)->_dl; return idle; } @@ -67,8 +91,8 @@ template void Ready_queue_wfq::swap(unsigned a, unsigned b) { - E::wfq_elem(_heap[a])->_ready_link = &_heap[b]; - E::wfq_elem(_heap[b])->_ready_link = &_heap[a]; + _e(_heap[a])->_ready_link = &_heap[b]; + _e(_heap[b])->_ready_link = &_heap[a]; E *s = _heap[a]; _heap[a] = _heap[b]; _heap[b] = s; @@ -82,7 +106,7 @@ Ready_queue_wfq::heap_up(unsigned a) for (;a > 0;) { unsigned p = (a-1)/2; - if (*E::wfq_elem(_heap[p]) < *E::wfq_elem(_heap[a])) + if (*_e(_heap[p]) < *_e(_heap[a])) return; swap(p, a); a = p; @@ -102,10 +126,10 @@ Ready_queue_wfq::heap_down(unsigned a) if (_cnt <= c1) return; - if (_cnt > c2 && *E::wfq_elem(_heap[c2]) <= *E::wfq_elem(_heap[c1])) + if (_cnt > c2 && *_e(_heap[c2]) <= *_e(_heap[c1])) c1 = c2; - if (*E::wfq_elem(_heap[a]) <= *E::wfq_elem(_heap[c1])) + if (*_e(_heap[a]) <= *_e(_heap[c1])) return; swap(c1, a); @@ -120,7 +144,7 @@ Ready_queue_wfq::heap_down(unsigned a) IMPLEMENT template void -Ready_queue_wfq::enqueue(E *i) +Ready_queue_wfq::enqueue(E *i, bool /*is_current_sched**/) { assert_kdb(cpu_lock.test()); @@ -132,7 +156,7 @@ Ready_queue_wfq::enqueue(E *i) E *&h = _heap[n]; h = i; - E::wfq_elem(i)->_ready_link = &h; + _e(i)->_ready_link = &h; heap_up(n); } @@ -151,17 +175,17 @@ Ready_queue_wfq::dequeue(E *i) if (EXPECT_FALSE (!i->in_ready_list() || i == idle)) return; - unsigned x = E::wfq_elem(i)->_ready_link - _heap; + unsigned x = _e(i)->_ready_link - _heap; if (x == --_cnt) { - E::wfq_elem(i)->_ready_link = 0; + _e(i)->_ready_link = 0; return; } swap(x, _cnt); heap_down(x); - E::wfq_elem(i)->_ready_link = 0; + _e(i)->_ready_link = 0; } /** @@ -173,8 +197,26 @@ void Ready_queue_wfq::requeue(E *i) { if (!i->in_ready_list()) - enqueue(i); + enqueue(i, false); - heap_down(E::wfq_elem(i)->_ready_link - _heap); + heap_down(_e(i)->_ready_link - _heap); +} + + +PUBLIC template< typename E > inline +void +Ready_queue_wfq::deblock_refill(E *sc) +{ + Unsigned64 da = 0; + if (EXPECT_TRUE(_current_sched != 0)) + da = _e(_current_sched)->_dl; + + if (_e(sc)->_dl >= da) + return; + + _e(sc)->_left += (da - _e(sc)->_dl) * _e(sc)->_w; + if (_e(sc)->_left > _e(sc)->_q) + _e(sc)->_left = _e(sc)->_q; + _e(sc)->_dl = da; } diff --git a/kernel/fiasco/src/kern/receiver.cpp b/kernel/fiasco/src/kern/receiver.cpp index f4cbf106..8ce4c366 100644 --- a/kernel/fiasco/src/kern/receiver.cpp +++ b/kernel/fiasco/src/kern/receiver.cpp @@ -163,7 +163,7 @@ void Receiver::enqueue_timeout_again() { if (_timeout) - _timeout->set_again(current_cpu()); + _timeout->set_again(cpu()); } PUBLIC inline @@ -259,8 +259,7 @@ Receiver::vcpu_async_ipc(Sender const *sender) const if (self->vcpu_enter_kernel_mode(vcpu)) vcpu = vcpu_state().access(); - LOG_TRACE("VCPU events", "vcpu", this, __context_vcpu_log_fmt, - Vcpu_log *l = tbe->payload(); + LOG_TRACE("VCPU events", "vcpu", this, Vcpu_log, l->type = 1; l->state = vcpu->_saved_state; l->ip = Mword(sender); diff --git a/kernel/fiasco/src/kern/sched_context-fixed_prio.cpp b/kernel/fiasco/src/kern/sched_context-fixed_prio.cpp index b8dfe41b..43dd402f 100644 --- a/kernel/fiasco/src/kern/sched_context-fixed_prio.cpp +++ b/kernel/fiasco/src/kern/sched_context-fixed_prio.cpp @@ -21,16 +21,32 @@ class Sched_context : public cxx::D_list_item template friend struct Jdb_thread_list_policy; + union Sp + { + L4_sched_param p; + L4_sched_param_legacy legacy_fixed_prio; + L4_sched_param_fixed_prio fixed_prio; + }; + public: typedef cxx::Sd_list Fp_list; - class Ready_queue : public Ready_queue_fp + class Ready_queue_base : public Ready_queue_fp { public: - Context *schedule_in_progress; void activate(Sched_context *s) { _current_sched = s; } Sched_context *current_sched() const { return _current_sched; } + void ready_enqueue(Sched_context *sc) + { + assert_kdb(cpu_lock.test()); + + // Don't enqueue threads which are already enqueued + if (EXPECT_FALSE (sc->in_ready_list())) + return; + + enqueue(sc, sc == current_sched()); + } private: Sched_context *_current_sched; @@ -77,34 +93,40 @@ Sched_context::prio() const return _prio; } -/** - * Set priority of Sched_context - */ -PUBLIC inline -void -Sched_context::set_prio (unsigned short const prio) +PUBLIC +int +Sched_context::set(L4_sched_param const *_p) { - _prio = prio; -} + Sp const *p = reinterpret_cast(_p); + if (p->p.sched_class >= 0) + { + // legacy fixed prio + _prio = p->legacy_fixed_prio.prio; + if (p->legacy_fixed_prio.prio > 255) + _prio = 255; -/** - * Return full time quantum of Sched_context - */ -PUBLIC inline -Unsigned64 -Sched_context::quantum() const -{ - return _quantum; -} + _quantum = p->legacy_fixed_prio.quantum; + if (p->legacy_fixed_prio.quantum == 0) + _quantum = Config::Default_time_slice; + return 0; + } -/** - * Set full time quantum of Sched_context - */ -PUBLIC inline -void -Sched_context::set_quantum (Unsigned64 const quantum) -{ - _quantum = quantum; + switch (p->p.sched_class) + { + case L4_sched_param_fixed_prio::Class: + _prio = p->fixed_prio.prio; + if (p->fixed_prio.prio > 255) + _prio = 255; + + _quantum = p->fixed_prio.quantum; + if (p->fixed_prio.quantum == 0) + _quantum = Config::Default_time_slice; + break; + + default: + return L4_err::ERange; + }; + return 0; } /** @@ -117,17 +139,17 @@ Sched_context::left() const return _left; } -PUBLIC inline NEEDS[Sched_context::set_left, Sched_context::quantum] +PUBLIC inline NEEDS[Sched_context::set_left] void Sched_context::replenish() -{ set_left(quantum()); } +{ set_left(_quantum); } /** * Set remaining time quantum of Sched_context */ PUBLIC inline void -Sched_context::set_left (Unsigned64 const left) +Sched_context::set_left(Unsigned64 left) { _left = left; } @@ -144,82 +166,8 @@ Sched_context::in_ready_list() const return Fp_list::in_list(this); } -/** - * Remove context from ready-list. - */ -PUBLIC inline NEEDS ["cpu_lock.h", "kdb_ke.h", "std_macros.h"] -void -Sched_context::ready_dequeue() -{ - assert_kdb (cpu_lock.test()); - - // Don't dequeue threads which aren't enqueued - if (EXPECT_FALSE (!in_ready_list())) - return; - - unsigned cpu = current_cpu(); - - _ready_q.cpu(cpu).dequeue(this); -} - -/** - * Enqueue context in ready-list. - */ -PUBLIC inline -void -Sched_context::ready_enqueue(unsigned cpu) -{ - assert_kdb(cpu_lock.test()); - - // Don't enqueue threads which are already enqueued - if (EXPECT_FALSE (in_ready_list())) - return; - - Ready_queue &rq = _ready_q.cpu(cpu); - - rq.enqueue(this, this == rq.current_sched()); -} - -PUBLIC inline -void -Sched_context::requeue(unsigned cpu) -{ - _ready_q.cpu(cpu).requeue(this); -} - -/** - * Return if there is currently a schedule() in progress - */ -PUBLIC static inline -Context * -Sched_context::schedule_in_progress(unsigned cpu) -{ - return _ready_q.cpu(cpu).schedule_in_progress; -} - -PUBLIC static inline -void -Sched_context::reset_schedule_in_progress(unsigned cpu) -{ _ready_q.cpu(cpu).schedule_in_progress = 0; } - - -/** - * Invalidate (expire) currently active global Sched_context. - */ -PUBLIC static inline -void -Sched_context::invalidate_sched(unsigned cpu) -{ - _ready_q.cpu(cpu).activate(0); -} - PUBLIC inline bool Sched_context::dominates(Sched_context *sc) { return prio() > sc->prio(); } -PUBLIC inline -void -Sched_context::deblock_refill(unsigned) -{} - diff --git a/kernel/fiasco/src/kern/sched_context-fp_wfq.cpp b/kernel/fiasco/src/kern/sched_context-fp_wfq.cpp index 6610945d..2b12bc5a 100644 --- a/kernel/fiasco/src/kern/sched_context-fp_wfq.cpp +++ b/kernel/fiasco/src/kern/sched_context-fp_wfq.cpp @@ -8,6 +8,15 @@ class Sched_context MEMBER_OFFSET(); friend class Jdb_list_timeouts; friend class Jdb_thread_list; + friend class Ready_queue_wfq; + + union Sp + { + L4_sched_param p; + L4_sched_param_legacy legacy_fixed_prio; + L4_sched_param_fixed_prio fixed_prio; + L4_sched_param_wfq wfq; + }; struct Ready_list_item_concept { @@ -43,7 +52,7 @@ private: Sched_context *_ready_next, *_ready_prev; }; - struct Wfq_sc : public B_sc + struct Wfq_sc : public Sched_context_wfq, public B_sc { Sched_context **_ready_link; bool _idle:1; @@ -51,11 +60,6 @@ private: unsigned _w; unsigned _qdw; - bool operator <= (Wfq_sc const &o) const - { return _dl <= o._dl; } - - bool operator < (Wfq_sc const &o) const - { return _dl < o._dl; } }; union Sc @@ -69,32 +73,32 @@ private: public: static Wfq_sc *wfq_elem(Sched_context *x) { return &x->_sc.wfq; } - struct Ready_queue + struct Ready_queue_base { public: Ready_queue_fp fp_rq; Ready_queue_wfq wfq_rq; - Context *schedule_in_progress; Sched_context *current_sched() const { return _current_sched; } void activate(Sched_context *s) { - if (s && s->_t == Wfq) + if (!s || s->_t == Wfq) wfq_rq.activate(s); _current_sched = s; } - private: - Sched_context *_current_sched; + void enqueue(Sched_context *sc, bool is_current); + void dequeue(Sched_context *); + void requeue(Sched_context *sc); - friend class Jdb_thread_list; - - public: void set_idle(Sched_context *sc) { sc->_t = Wfq; sc->_sc.wfq._p = 0; wfq_rq.set_idle(sc); } - void enqueue(Sched_context *); - void dequeue(Sched_context *); Sched_context *next_to_run() const; + void deblock_refill(Sched_context *sc); + + private: + friend class Jdb_thread_list; + Sched_context *_current_sched; }; Context *context() const { return context_of(this); } @@ -124,7 +128,7 @@ Sched_context::Sched_context() IMPLEMENT inline Sched_context * -Sched_context::Ready_queue::next_to_run() const +Sched_context::Ready_queue_base::next_to_run() const { Sched_context *s = fp_rq.next_to_run(); if (s) @@ -147,119 +151,103 @@ Sched_context::in_ready_list() const return _sc.wfq._ready_link != 0; } -/** - * Return if there is currently a schedule() in progress - */ -PUBLIC static inline -Context * -Sched_context::schedule_in_progress(unsigned cpu) -{ - return _ready_q.cpu(cpu).schedule_in_progress; -} - -PUBLIC static inline -void -Sched_context::reset_schedule_in_progress(unsigned cpu) -{ _ready_q.cpu(cpu).schedule_in_progress = 0; } - - PUBLIC inline unsigned Sched_context::prio() const { return _sc.fp._p; } -PUBLIC inline -void -Sched_context::set_prio(unsigned p) +PUBLIC +int +Sched_context::set(L4_sched_param const *_p) { - if (_t == Fixed_prio) - _sc.fp._p = p; + Sp const *p = reinterpret_cast(_p); + if (p->p.sched_class >= 0) + { + // legacy fixed prio + _t = Fixed_prio; + _sc.fp._p = p->legacy_fixed_prio.prio; + if (p->legacy_fixed_prio.prio > 255) + _sc.fp._p = 255; + + _sc.fp._q = p->legacy_fixed_prio.quantum; + if (p->legacy_fixed_prio.quantum == 0) + _sc.fp._q = Config::Default_time_slice; + return 0; + } + switch (p->p.sched_class) + { + case L4_sched_param_fixed_prio::Class: + _t = Fixed_prio; + + _sc.fp._p = p->fixed_prio.prio; + if (p->fixed_prio.prio > 255) + _sc.fp._p = 255; + + _sc.fp._q = p->fixed_prio.quantum; + if (p->fixed_prio.quantum == 0) + _sc.fp._q = Config::Default_time_slice; + + break; + case L4_sched_param_wfq::Class: + if (p->wfq.quantum == 0 || p->wfq.weight == 0) + return -L4_err::EInval; + _t = Wfq; + _sc.wfq._p = 0; + _sc.wfq._q = p->wfq.quantum; + _sc.wfq._w = p->wfq.weight; + _sc.wfq._qdw = p->wfq.quantum / p->wfq.weight; + break; + default: + return L4_err::ERange; + }; + return 0; +} + + +IMPLEMENT inline +void +Sched_context::Ready_queue_base::deblock_refill(Sched_context *sc) +{ + if (sc->_t != Wfq) + fp_rq.deblock_refill(sc); else - _sc.fp._p = 0; -} - -/** - * Invalidate (expire) currently active global Sched_context. - */ -PUBLIC static inline -void -Sched_context::invalidate_sched(unsigned cpu) -{ - _ready_q.cpu(cpu).activate(0); -} - -PUBLIC inline -void -Sched_context::deblock_refill(unsigned cpu) -{ - if (_t != Wfq) - return; - - Unsigned64 da = 0; - Sched_context *cs = _ready_q.cpu(cpu).wfq_rq.current_sched(); - - if (EXPECT_TRUE(cs != 0)) - da = cs->_sc.wfq._dl; - - if (_sc.wfq._dl >= da) - return; - - _sc.wfq._left += (da - _sc.wfq._dl) * _sc.wfq._w; - if (_sc.wfq._left > _sc.wfq._q) - _sc.wfq._left = _sc.wfq._q; - _sc.wfq._dl = da; + wfq_rq.deblock_refill(sc); } /** * Enqueue context in ready-list. */ -PUBLIC +IMPLEMENT void -Sched_context::ready_enqueue(unsigned cpu) +Sched_context::Ready_queue_base::enqueue(Sched_context *sc, bool is_current) { - assert_kdb(cpu_lock.test()); - - // Don't enqueue threads which are already enqueued - if (EXPECT_FALSE (in_ready_list())) - return; - - Ready_queue &rq = _ready_q.cpu(cpu); - - if (_t == Fixed_prio) - rq.fp_rq.enqueue(this, this == rq.current_sched()); + if (sc->_t == Fixed_prio) + fp_rq.enqueue(sc, is_current); else - rq.wfq_rq.enqueue(this); + wfq_rq.enqueue(sc, is_current); } /** * Remove context from ready-list. */ -PUBLIC inline NEEDS ["cpu_lock.h", "kdb_ke.h", "std_macros.h"] +IMPLEMENT inline NEEDS ["cpu_lock.h", "kdb_ke.h", "std_macros.h"] void -Sched_context::ready_dequeue() +Sched_context::Ready_queue_base::dequeue(Sched_context *sc) { - assert_kdb (cpu_lock.test()); - - // Don't dequeue threads which aren't enqueued - if (EXPECT_FALSE (!in_ready_list())) - return; - - unsigned cpu = current_cpu(); - - if (_t == Fixed_prio) - _ready_q.cpu(cpu).fp_rq.dequeue(this); + if (sc->_t == Fixed_prio) + fp_rq.dequeue(sc); else - _ready_q.cpu(cpu).wfq_rq.dequeue(this); + wfq_rq.dequeue(sc); } -PUBLIC +IMPLEMENT void -Sched_context::requeue(unsigned cpu) +Sched_context::Ready_queue_base::requeue(Sched_context *sc) { - if (_t == Fixed_prio) - _ready_q.cpu(cpu).fp_rq.requeue(this); + if (sc->_t == Fixed_prio) + fp_rq.requeue(sc); else - _ready_q.cpu(cpu).wfq_rq.requeue(this); + wfq_rq.requeue(sc); } PUBLIC inline @@ -298,12 +286,3 @@ Unsigned64 Sched_context::left() const { return _sc.fp._left; } -PUBLIC inline -Unsigned64 -Sched_context::quantum() const -{ return _sc.fp._q; } - -PUBLIC inline -void -Sched_context::set_quantum(Unsigned64 q) -{ _sc.fp._q = q; } diff --git a/kernel/fiasco/src/kern/sched_context-wfq.cpp b/kernel/fiasco/src/kern/sched_context-wfq.cpp index 9cf4a606..b784c7a9 100644 --- a/kernel/fiasco/src/kern/sched_context-wfq.cpp +++ b/kernel/fiasco/src/kern/sched_context-wfq.cpp @@ -11,7 +11,7 @@ INTERFACE[sched_wfq] : #include "ready_queue_wfq.h" -class Sched_context +class Sched_context : public Sched_context_wfq { MEMBER_OFFSET(); friend class Jdb_list_timeouts; @@ -19,14 +19,17 @@ class Sched_context template friend class Jdb_thread_list_policy; + friend class Sched_context_wfq; -public: - class Ready_queue : public Ready_queue_wfq + union Sp { - public: - Context *schedule_in_progress; + L4_sched_param p; + L4_sched_param_wfq wfq; }; +public: + typedef Sched_context Wfq_sc; + typedef Ready_queue_wfq Ready_queue_base; Context *context() const { return context_of(this); } private: @@ -42,13 +45,6 @@ private: unsigned _qdw; friend class Ready_queue_wfq; - - bool operator <= (Sched_context const &o) const - { return _dl <= o._dl; } - - bool operator < (Sched_context const &o) const - { return _dl < o._dl; } - }; // -------------------------------------------------------------------------- @@ -85,25 +81,21 @@ Sched_context::owner() const return context(); } -/** - * Return full time quantum of Sched_context - */ -PUBLIC inline -Unsigned64 -Sched_context::quantum() const +PUBLIC +int +Sched_context::set(L4_sched_param const *_p) { - return _q; -} + Sp const *p = reinterpret_cast(_p); + if (p->p.sched_class != L4_sched_param_wfq::Class) + return -L4_err::ERange; -/** - * Set full time quantum of Sched_context - */ -PUBLIC inline -void -Sched_context::set_quantum(Unsigned64 const quantum) -{ - _q = quantum; - _qdw = _q/_w; + if (p->wfq.quantum == 0 || p->wfq.weight == 0) + return -L4_err::EInval; + + _q = p->wfq.quantum; + _w = p->wfq.weight; + _qdw = p->wfq.quantum / p->wfq.weight; + return 0; } /** @@ -116,7 +108,7 @@ Sched_context::left() const return _left; } -PUBLIC inline NEEDS[Sched_context::set_left, Sched_context::quantum] +PUBLIC inline NEEDS[Sched_context::set_left] void Sched_context::replenish() { @@ -129,7 +121,7 @@ Sched_context::replenish() */ PUBLIC inline void -Sched_context::set_left (Unsigned64 const left) +Sched_context::set_left(Unsigned64 left) { _left = left; } @@ -145,48 +137,6 @@ Sched_context::in_ready_list() const return _ready_link != 0; } -/** - * Remove context from ready-list. - */ -PUBLIC inline NEEDS ["cpu_lock.h", "kdb_ke.h", "std_macros.h"] -void -Sched_context::ready_dequeue() -{ - assert_kdb (cpu_lock.test()); - - // Don't dequeue threads which aren't enqueued - if (EXPECT_FALSE (!in_ready_list())) - return; - - unsigned cpu = current_cpu(); - - _ready_q.cpu(cpu).dequeue(this); - -} - -/** - * Enqueue context in ready-list. - */ -PUBLIC inline NEEDS["kdb_ke.h"] -void -Sched_context::ready_enqueue(unsigned cpu) -{ - assert_kdb(cpu_lock.test()); - - // Don't enqueue threads which are already enqueued - if (EXPECT_FALSE (in_ready_list())) - return; - - _ready_q.cpu(cpu).enqueue(this);; -} - -PUBLIC -void -Sched_context::requeue(unsigned cpu) -{ - _ready_q.cpu(cpu).requeue(this); -} - PUBLIC inline bool Sched_context::dominates(Sched_context *sc) @@ -198,57 +148,8 @@ Sched_context::dominates(Sched_context *sc) return !_idle && _dl < sc->_dl; } -PUBLIC inline -void -Sched_context::deblock_refill(unsigned cpu) -{ - Unsigned64 da = 0; - Sched_context *cs = rq(cpu).current_sched(); - if (EXPECT_TRUE(cs != 0)) - da = cs->_dl; - - if (_dl >= da) - return; - - _left += (da - _dl) * _w; - if (_left > _q) - _left = _q; - _dl = da; -} - - -/** - * Return if there is currently a schedule() in progress - */ -PUBLIC static inline -Context * -Sched_context::schedule_in_progress(unsigned cpu) -{ - return _ready_q.cpu(cpu).schedule_in_progress; -} - -PUBLIC static inline -void -Sched_context::reset_schedule_in_progress(unsigned cpu) -{ _ready_q.cpu(cpu).schedule_in_progress = 0; } - - -/** - * Invalidate (expire) currently active global Sched_context. - */ -PUBLIC static inline -void -Sched_context::invalidate_sched(unsigned cpu) -{ - _ready_q.cpu(cpu).activate(0); -} - PUBLIC static inline unsigned Sched_context::prio() { return 0; } -PUBLIC static inline -void -Sched_context::set_prio(unsigned) -{} diff --git a/kernel/fiasco/src/kern/sched_context.cpp b/kernel/fiasco/src/kern/sched_context.cpp index b402ceae..87b651ef 100644 --- a/kernel/fiasco/src/kern/sched_context.cpp +++ b/kernel/fiasco/src/kern/sched_context.cpp @@ -3,36 +3,115 @@ INTERFACE: EXTENSION class Sched_context { -private: - static Per_cpu _ready_q; +public: + class Ready_queue : public Ready_queue_base + { + public: + void set_current_sched(Sched_context *sched); + void invalidate_sched() { activate(0); } + bool deblock(Sched_context *sc, Sched_context *crs, bool lazy_q = false); + void deblock(Sched_context *sc); + void ready_enqueue(Sched_context *sc) + { + assert_kdb(cpu_lock.test()); + + // Don't enqueue threads which are already enqueued + if (EXPECT_FALSE (sc->in_ready_list())) + return; + + enqueue(sc, sc == current_sched()); + } + + void ready_dequeue(Sched_context *sc) + { + assert_kdb (cpu_lock.test()); + + // Don't dequeue threads which aren't enqueued + if (EXPECT_FALSE (!sc->in_ready_list())) + return; + + dequeue(sc); + } + + void switch_sched(Sched_context *from, Sched_context *to) + { + assert_kdb (cpu_lock.test()); + + // If we're leaving the global timeslice, invalidate it This causes + // schedule() to select a new timeslice via set_current_sched() + if (from == current_sched()) + invalidate_sched(); + + if (from->in_ready_list()) + dequeue(from); + + enqueue(to, false); + } + + Context *schedule_in_progress; + }; + + static Per_cpu rq; }; IMPLEMENTATION: #include "kdb_ke.h" +#include "timer.h" +#include "timeout.h" +#include "globals.h" +#include "logdefs.h" -DEFINE_PER_CPU Per_cpu Sched_context::_ready_q; +DEFINE_PER_CPU Per_cpu Sched_context::rq; -PUBLIC static inline -Sched_context::Ready_queue & -Sched_context::rq(unsigned cpu) -{ return _ready_q.cpu(cpu); } +/** + * Set currently active global Sched_context. + */ +IMPLEMENT +void +Sched_context::Ready_queue::set_current_sched(Sched_context *sched) +{ + assert_kdb (sched); + // Save remainder of previous timeslice or refresh it, unless it had + // been invalidated + Timeout * const tt = timeslice_timeout.current(); + Unsigned64 clock = Timer::system_clock(); + if (Sched_context *s = current_sched()) + { + Signed64 left = tt->get_timeout(clock); + if (left > 0) + s->set_left(left); + else + s->replenish(); + + LOG_SCHED_SAVE(s); + } + + // Program new end-of-timeslice timeout + tt->reset(); + tt->set(clock + sched->left(), current_cpu()); + + // Make this timeslice current + activate(sched); + + LOG_SCHED_LOAD(sched); +} /** * \param cpu must be current_cpu() */ -PUBLIC inline NEEDS["kdb_ke.h"] +IMPLEMENT inline NEEDS["kdb_ke.h"] void -Sched_context::deblock(unsigned cpu) +Sched_context::Ready_queue::deblock(Sched_context *sc) { assert_kdb(cpu_lock.test()); - Sched_context *cs = rq(cpu).current_sched(); - if (this != cs) - deblock_refill(cpu); + Sched_context *cs = current_sched(); + if (sc != cs) + deblock_refill(sc); - ready_enqueue(cpu); + ready_enqueue(sc); } /** @@ -40,31 +119,31 @@ Sched_context::deblock(unsigned cpu) * \param crs the Sched_context of the current context * \param lazy_q queue lazily if applicable */ -PUBLIC inline NEEDS["kdb_ke.h"] +IMPLEMENT inline NEEDS["kdb_ke.h"] bool -Sched_context::deblock(unsigned cpu, Sched_context *crs, bool lazy_q = false) +Sched_context::Ready_queue::deblock(Sched_context *sc, Sched_context *crs, bool lazy_q) { assert_kdb(cpu_lock.test()); - Sched_context *cs = rq(cpu).current_sched(); + Sched_context *cs = current_sched(); bool res = true; - if (this == cs) + if (sc == cs) { - if (crs->dominates(this)) + if (crs->dominates(sc)) res = false; } else { - deblock_refill(cpu); + deblock_refill(sc); - if ((EXPECT_TRUE(cs != 0) && cs->dominates(this)) || crs->dominates(this)) + if ((EXPECT_TRUE(cs != 0) && cs->dominates(sc)) || crs->dominates(sc)) res = false; } if (res && lazy_q) return true; - ready_enqueue(cpu); + ready_enqueue(sc); return res; } diff --git a/kernel/fiasco/src/kern/scheduler.cpp b/kernel/fiasco/src/kern/scheduler.cpp index 82dd1f0f..fa6984ee 100644 --- a/kernel/fiasco/src/kern/scheduler.cpp +++ b/kernel/fiasco/src/kern/scheduler.cpp @@ -17,28 +17,6 @@ public: Idle_time = 2, }; - class Cpu_set - { - private: - Mword _w; - - public: - Mword offset() const { return (_w & 0x00ffffff) & (~0 << granularity()); } - Mword granularity() const { return (_w >> 24) & (MWORD_BITS-1) ; } - bool contains(unsigned cpu, Mword map) const - { - if (offset() > cpu) - return false; - - cpu -= offset(); - cpu >>= granularity(); - if (cpu >= MWORD_BITS) - return false; - - return map & (1UL << cpu); - } - }; - static Scheduler scheduler; private: Irq_base *_irq; @@ -49,6 +27,7 @@ IMPLEMENTATION: #include "thread_object.h" #include "l4_buf_iter.h" +#include "l4_types.h" #include "entry_frame.h" FIASCO_DEFINE_KOBJ(Scheduler); @@ -68,30 +47,6 @@ Scheduler::Scheduler() : _irq(0) initial_kobjects.register_obj(this, 7); } -PRIVATE static -Mword -Scheduler::first_online(Cpu_set const *cpus, Mword bm) -{ - unsigned cpu = cpus->offset(); - - for (;;) - { - unsigned b = (cpu - cpus->offset()) >> cpus->granularity(); - if (cpu >= Config::Max_num_cpus || b >= MWORD_BITS) - return ~0UL; - - if (!(bm & (1UL << b))) - { - cpu += 1UL << cpus->granularity(); - continue; - } - - if (Cpu::online(cpu)) - return cpu; - - ++cpu; - } -} PRIVATE L4_msg_tag @@ -108,6 +63,20 @@ Scheduler::sys_run(unsigned char /*rights*/, Syscall_frame *f, Utcb const *utcb) if (EXPECT_FALSE(tag.words() < 5)) return commit_result(-L4_err::EInval); + unsigned long sz = sizeof (L4_sched_param_legacy); + + { + L4_sched_param const *sched_param = reinterpret_cast(&utcb->values[1]); + if (sched_param->sched_class < 0) + sz = sched_param->length; + + sz += sizeof(Mword) - 1; + sz /= sizeof(Mword); + + if (sz + 1 > tag.words()) + return commit_result(-L4_err::EInval); + } + if (EXPECT_FALSE(!tag.items() || !snd_items.next())) return commit_result(-L4_err::EInval); @@ -119,35 +88,30 @@ Scheduler::sys_run(unsigned char /*rights*/, Syscall_frame *f, Utcb const *utcb) if (!thread) return commit_result(-L4_err::EInval); - Cpu_set const *cpus = reinterpret_cast(&utcb->values[1]); - Thread::Migration_info info; + Mword _store[sz]; + memcpy(_store, &utcb->values[1], sz * sizeof(Mword)); + + L4_sched_param const *sched_param = reinterpret_cast(_store); + + Thread::Migration info; unsigned t_cpu = thread->cpu(); - if (cpus->contains(t_cpu, utcb->values[2])) + + if (Cpu::online(t_cpu) && sched_param->cpus.contains(t_cpu)) info.cpu = t_cpu; - else if (cpus->contains(curr_cpu, utcb->values[2])) + else if (sched_param->cpus.contains(curr_cpu)) info.cpu = curr_cpu; else - info.cpu = first_online(cpus, utcb->values[2]); -#if 0 - if (info.cpu == Invalid_cpu) - return commit_result(-L4_err::EInval); -#endif - info.prio = utcb->values[3]; - info.quantum = utcb->values[4]; -#if 0 - printf("CPU[%lx]: current_cpu=%u run(thread=%lx, prio=%ld, quantum=%ld, cpu=%ld (%lx,%u,%u)\n", - dbg_id(), curr_cpu, thread->dbg_id(), info.prio, info.quantum, info.cpu, utcb->values[2], cpus->offset(), cpus->granularity()); -#endif + info.cpu = sched_param->cpus.first(Cpu::online_mask(), Config::Max_num_cpus); - if (info.prio > 255) - info.prio = 255; - if (!info.quantum) - info.quantum = Config::Default_time_slice; + info.sp = sched_param; + if (0) + printf("CPU[%lx]: current_cpu=%u run(thread=%lx, cpu=%u (%lx,%lu,%lu)\n", + dbg_id(), curr_cpu, thread->dbg_id(), info.cpu, + utcb->values[2], sched_param->cpus.offset(), sched_param->cpus.granularity()); - - thread->migrate(info); + thread->migrate(&info); return commit_result(0); } @@ -160,9 +124,9 @@ Scheduler::sys_idle_time(unsigned char, if (f->tag().words() < 3) return commit_result(-L4_err::EInval); - Cpu_set const *cpus = reinterpret_cast(&utcb->values[1]); - Mword const cpu = first_online(cpus, utcb->values[2]); - if (cpu == ~0UL) + L4_cpu_set cpus = access_once(reinterpret_cast(&utcb->values[1])); + Mword const cpu = cpus.first(Cpu::online_mask(), Config::Max_num_cpus); + if (EXPECT_FALSE(cpu == Config::Max_num_cpus)) return commit_result(-L4_err::EInval); reinterpret_cast(utcb->values)->t @@ -174,24 +138,24 @@ Scheduler::sys_idle_time(unsigned char, PRIVATE L4_msg_tag Scheduler::sys_info(unsigned char, Syscall_frame *f, - Utcb const *iutcb, Utcb *outcb) + Utcb const *iutcb, Utcb *outcb) { if (f->tag().words() < 2) return commit_result(-L4_err::EInval); - Cpu_set const *s = reinterpret_cast(&iutcb->values[1]); + L4_cpu_set_descr const s = access_once(reinterpret_cast(&iutcb->values[1])); Mword rm = 0; Mword max = Config::Max_num_cpus; - Mword const offset = s->offset() << s->granularity(); + Mword const offset = s.offset() << s.granularity(); if (offset >= max) return commit_result(-L4_err::EInval); - if (max > offset + ((Mword)MWORD_BITS << s->granularity())) - max = offset + ((Mword)MWORD_BITS << s->granularity()); + if (max > offset + ((Mword)MWORD_BITS << s.granularity())) + max = offset + ((Mword)MWORD_BITS << s.granularity()); for (Mword i = 0; i < max - offset; ++i) if (Cpu::online(i + offset)) - rm |= (1 << (i >> s->granularity())); + rm |= (1 << (i >> s.granularity())); outcb->values[0] = rm; outcb->values[1] = Config::Max_num_cpus; @@ -208,7 +172,6 @@ Scheduler::icu_get_irq(unsigned irqnum) return _irq; } - PUBLIC inline void Scheduler::icu_get_info(Mword *features, Mword *num_irqs, Mword *num_msis) diff --git a/kernel/fiasco/src/kern/sender.cpp b/kernel/fiasco/src/kern/sender.cpp index f1abe782..d2fb87f0 100644 --- a/kernel/fiasco/src/kern/sender.cpp +++ b/kernel/fiasco/src/kern/sender.cpp @@ -109,7 +109,7 @@ void Sender::sender_enqueue(Prio_list *head, unsigned short prio) { assert(prio < 256); - Lock_guard guard (&cpu_lock); + auto guard = lock_guard(cpu_lock); head->insert(this, prio); } @@ -122,7 +122,7 @@ void Sender::sender_dequeue(P_LIST list) if (!in_sender_list()) return; - Lock_guard guard (&cpu_lock); + auto guard = lock_guard(cpu_lock); list->dequeue(this); } @@ -136,7 +136,7 @@ void Sender::sender_dequeue_head(P_LIST list) if (!in_sender_list()) return; - Lock_guard guard (&cpu_lock); + auto guard = lock_guard(cpu_lock); if (this == list->head()) list->dequeue(this); @@ -148,7 +148,7 @@ void Sender::sender_update_prio(P_LIST list, unsigned short newprio) if(EXPECT_FALSE(sender_prio() == newprio)) return; - Lock_guard guard (&cpu_lock); + auto guard = lock_guard(cpu_lock); if (!in_sender_list()) return; diff --git a/kernel/fiasco/src/kern/sparc/cpu-sparc.cpp b/kernel/fiasco/src/kern/sparc/cpu-sparc.cpp index fce30900..c3c1f66f 100644 --- a/kernel/fiasco/src/kern/sparc/cpu-sparc.cpp +++ b/kernel/fiasco/src/kern/sparc/cpu-sparc.cpp @@ -58,6 +58,11 @@ Cpu::init(bool is_boot_cpu) //printf("Timebase: %lu\n", Boot_info::get_time_base()); } +PUBLIC inline +unsigned +Cpu::phys_id() const +{ return _phys_id; } + IMPLEMENT void Cpu::early_init() diff --git a/kernel/fiasco/src/kern/sparc/mem_space-sparc.cpp b/kernel/fiasco/src/kern/sparc/mem_space-sparc.cpp index b72eb620..5c56903a 100644 --- a/kernel/fiasco/src/kern/sparc/mem_space-sparc.cpp +++ b/kernel/fiasco/src/kern/sparc/mem_space-sparc.cpp @@ -1,7 +1,8 @@ INTERFACE [sparc]: #include "entry_frame.h" -extern "C" + +extern "C" Mword pagefault_entry(Address, Mword, Mword, Return_frame *); @@ -72,6 +73,7 @@ IMPLEMENTATION [sparc]: #include "paging.h" #include "std_macros.h" #include "kmem.h" +#include "kmem_alloc.h" #include "logdefs.h" #include "panic.h" #include "lock_guard.h" @@ -84,7 +86,7 @@ IMPLEMENTATION [sparc]: PUBLIC explicit inline Mem_space::Mem_space(Ram_quota *q) : _quota(q), _dir(0) {} -PROTECTED inline +PROTECTED inline NEEDS["kmem_alloc.h"] bool Mem_space::initialize() { diff --git a/kernel/fiasco/src/kern/sparc/tb_entry-sparc.cpp b/kernel/fiasco/src/kern/sparc/tb_entry-sparc.cpp index 6a025e48..1f44db3e 100644 --- a/kernel/fiasco/src/kern/sparc/tb_entry-sparc.cpp +++ b/kernel/fiasco/src/kern/sparc/tb_entry-sparc.cpp @@ -1,6 +1,6 @@ INTERFACE [sparc]: -EXTENSION class Tb_entry_base +EXTENSION class Tb_entry { public: enum diff --git a/kernel/fiasco/src/kern/sparc/thread-jdb.cpp b/kernel/fiasco/src/kern/sparc/thread-jdb.cpp index cb839915..ce17d12e 100644 --- a/kernel/fiasco/src/kern/sparc/thread-jdb.cpp +++ b/kernel/fiasco/src/kern/sparc/thread-jdb.cpp @@ -25,7 +25,7 @@ extern "C" void sys_kdb_ke() Thread *t = current_thread(); //arriving from outx function - unsigned *x = (unsigned *)t->regs()->ip(); + //unsigned *x = (unsigned *)t->regs()->ip(); if(t->regs()->r[29] == (Mword)-0x24 && t->regs()->r[2] & (1 << 31)) //ip && r3 { NOT_IMPL_PANIC; @@ -50,10 +50,10 @@ extern "C" void sys_kdb_ke() IMPLEMENT int -Thread::call_nested_trap_handler(Trap_state *ts) +Thread::call_nested_trap_handler(Trap_state * /*ts*/) { unsigned phys_cpu = Proc::cpu_id(); - unsigned log_cpu = Cpu::p2l(phys_cpu); + unsigned log_cpu = Cpu::cpus.find_cpu(Cpu::By_phys_id(phys_cpu)); if (log_cpu == ~0U) { printf("Trap on unknown CPU phys_id=%x\n", phys_cpu); diff --git a/kernel/fiasco/src/kern/sparc/thread-sparc.cpp b/kernel/fiasco/src/kern/sparc/thread-sparc.cpp index 35bd0fd6..398ba44b 100644 --- a/kernel/fiasco/src/kern/sparc/thread-sparc.cpp +++ b/kernel/fiasco/src/kern/sparc/thread-sparc.cpp @@ -174,7 +174,7 @@ Thread::Thread() _del_observer(0) { - assert(state() == Thread_invalid); + assert(state(false) == Thread_invalid); inc_ref(); _space.space(Kernel_task::kernel_task()); @@ -193,7 +193,7 @@ Thread::Thread() r->sp(0); r->ip(0); - state_add(Thread_dead | Thread_suspended); + state_add_dirty(Thread_dead, false); // ok, we're ready to go! } diff --git a/kernel/fiasco/src/kern/sparc/trap_state.cpp b/kernel/fiasco/src/kern/sparc/trap_state.cpp index ede37845..21cab3b9 100644 --- a/kernel/fiasco/src/kern/sparc/trap_state.cpp +++ b/kernel/fiasco/src/kern/sparc/trap_state.cpp @@ -17,6 +17,7 @@ class Trap_state : public Trap_state_regs, public Syscall_frame, { public: typedef int (*Handler)(Trap_state*, unsigned cpu); + bool exclude_logging() { return false; } }; diff --git a/kernel/fiasco/src/kern/sparc/uart-asi.cpp b/kernel/fiasco/src/kern/sparc/uart-asi.cpp index a75ed046..7fec062e 100644 --- a/kernel/fiasco/src/kern/sparc/uart-asi.cpp +++ b/kernel/fiasco/src/kern/sparc/uart-asi.cpp @@ -1,4 +1,4 @@ -IMPLEMENTATION [libuart]: +INTERFACE [libuart]: #include "io_regblock_asi.h" @@ -7,6 +7,8 @@ EXTENSION class Uart L4::Io_register_block_asi _regs; }; +IMPLEMENTATION [libuart]: + IMPLEMENT inline Uart::Uart() : _regs(base()) {} PUBLIC bool Uart::startup() diff --git a/kernel/fiasco/src/kern/spin_lock.cpp b/kernel/fiasco/src/kern/spin_lock.cpp index dc1fc165..27c76a05 100644 --- a/kernel/fiasco/src/kern/spin_lock.cpp +++ b/kernel/fiasco/src/kern/spin_lock.cpp @@ -2,6 +2,12 @@ INTERFACE: #include "cpu_lock.h" +class Spin_lock_base : protected Cpu_lock +{ +public: + enum Lock_init { Unlocked = 0 }; +}; + /** * \brief Basic spin lock. * @@ -9,10 +15,8 @@ INTERFACE: * In the UP case it is in fact just the Cpu_lock. */ template -class Spin_lock : private Cpu_lock +class Spin_lock : public Spin_lock_base { -public: - enum Lock_init { Unlocked = 0 }; }; //-------------------------------------------------------------------------- @@ -71,6 +75,14 @@ class Spin_lock_coloc : public Spin_lock //-------------------------------------------------------------------------- IMPLEMENTATION: +PUBLIC inline +template< typename T > +Spin_lock_coloc::Spin_lock_coloc() {} + +PUBLIC inline +template< typename T > +Spin_lock_coloc::Spin_lock_coloc(Lock_init i) : Spin_lock(i) {} + PUBLIC inline template< typename T > T diff --git a/kernel/fiasco/src/kern/switch_lock.cpp b/kernel/fiasco/src/kern/switch_lock.cpp index 9253eef5..753cc881 100644 --- a/kernel/fiasco/src/kern/switch_lock.cpp +++ b/kernel/fiasco/src/kern/switch_lock.cpp @@ -121,7 +121,7 @@ inline Context * NO_INSTRUMENT Switch_lock::lock_owner() const { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); return (Context*)(_lock_owner & ~1UL); } @@ -134,7 +134,7 @@ inline Switch_lock::Status NO_INSTRUMENT Switch_lock::test() const { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); if (EXPECT_FALSE(!valid())) return Invalid; return (_lock_owner & ~1UL) ? Locked : Not_locked; @@ -151,7 +151,7 @@ inline NEEDS["atomic.h"] Switch_lock::Status NO_INSTRUMENT Switch_lock::try_lock() { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); if (EXPECT_FALSE(!valid())) return Invalid; @@ -175,7 +175,7 @@ PUBLIC Switch_lock::Status NO_INSTRUMENT Switch_lock::lock() { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); return lock_dirty(); } @@ -322,7 +322,7 @@ PUBLIC void NO_INSTRUMENT Switch_lock::clear() { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); switch_dirty(clear_no_switch_dirty()); } @@ -359,7 +359,7 @@ PUBLIC inline void NO_INSTRUMENT Switch_lock::invalidate() { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); _lock_owner |= 1; } @@ -367,7 +367,7 @@ PUBLIC void NO_INSTRUMENT Switch_lock::wait_free() { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); assert (!valid()); diff --git a/kernel/fiasco/src/kern/syscalls-log.cpp b/kernel/fiasco/src/kern/syscalls-log.cpp index 9615a1f5..d861d586 100644 --- a/kernel/fiasco/src/kern/syscalls-log.cpp +++ b/kernel/fiasco/src/kern/syscalls-log.cpp @@ -49,9 +49,9 @@ extern "C" void sys_ipc_log_wrapper(void) dbg_id = ~0UL; } Tb_entry_ipc _local; - Tb_entry_ipc *tb = static_cast - (EXPECT_TRUE(Jdb_ipc_trace::log_buf()) ? Jdb_tbuf::new_entry() - : &_local); + Tb_entry_ipc *tb = EXPECT_TRUE(Jdb_ipc_trace::log_buf()) + ? Jdb_tbuf::new_entry() + : &_local; tb->set(curr, regs->ip(), ipc_regs, utcb, dbg_id, curr->sched_context()->left()); diff --git a/kernel/fiasco/src/kern/task.cpp b/kernel/fiasco/src/kern/task.cpp index f9d8c9a3..7ca15153 100644 --- a/kernel/fiasco/src/kern/task.cpp +++ b/kernel/fiasco/src/kern/task.cpp @@ -299,8 +299,7 @@ void Task::operator delete (void *ptr) { Task *t = reinterpret_cast(ptr); - LOG_TRACE("Kobject delete", "del", current(), __fmt_kobj_destroy, - Log_destroy *l = tbe->payload(); + LOG_TRACE("Kobject delete", "del", current(), Log_destroy, l->id = t->dbg_id(); l->obj = t; l->type = "Task"; @@ -351,18 +350,16 @@ Task::destroy(Kobject ***reap_list) Kobject::destroy(reap_list); fpage_unmap(this, L4_fpage::all_spaces(L4_fpage::RWX), L4_map_mask::full(), reap_list); - Space::destroy(); } PRIVATE inline NOEXPORT L4_msg_tag Task::sys_map(unsigned char rights, Syscall_frame *f, Utcb *utcb) { - LOG_TRACE("Task map", "map", ::current(), __task_unmap_fmt, - Log_unmap *lu = tbe->payload(); - lu->id = dbg_id(); - lu->mask = utcb->values[1]; - lu->fpage = utcb->values[2]); + LOG_TRACE("Task map", "map", ::current(), Log_unmap, + l->id = dbg_id(); + l->mask = utcb->values[1]; + l->fpage = utcb->values[2]); if (EXPECT_FALSE(!(rights & L4_fpage::W))) return commit_result(-L4_err::EPerm); @@ -393,7 +390,7 @@ Task::sys_map(unsigned char rights, Syscall_frame *f, Utcb *utcb) Lock_guard_2 guard; // FIXME: avoid locking the current task, it is not needed - if (!guard.lock(&existence_lock, &from->existence_lock)) + if (!guard.check_and_lock(&existence_lock, &from->existence_lock)) return commit_result(-L4_err::EInval); cpu_lock.clear(); @@ -422,17 +419,16 @@ Task::sys_unmap(Syscall_frame *f, Utcb *utcb) ::Reap_list rl; unsigned words = f->tag().words(); - LOG_TRACE("Task unmap", "unm", ::current(), __task_unmap_fmt, - Log_unmap *lu = tbe->payload(); - lu->id = dbg_id(); - lu->mask = utcb->values[1]; - lu->fpage = utcb->values[2]); + LOG_TRACE("Task unmap", "unm", ::current(), Log_unmap, + l->id = dbg_id(); + l->mask = utcb->values[1]; + l->fpage = utcb->values[2]); { Lock_guard guard; // FIXME: avoid locking the current task, it is not needed - if (!guard.try_lock(&existence_lock)) + if (!guard.check_and_lock(&existence_lock)) return commit_error(utcb, L4_error::Not_existent); cpu_lock.clear(); @@ -577,17 +573,19 @@ Task::~Task() // --------------------------------------------------------------------------- INTERFACE [debug]: +#include "tb_entry.h" + EXTENSION class Task { private: - struct Log_unmap + struct Log_unmap : public Tb_entry { Mword id; Mword mask; Mword fpage; + unsigned print(int max, char *buf) const; } __attribute__((packed)); - static unsigned unmap_fmt(Tb_entry *, int max, char *buf) asm ("__task_unmap_fmt"); }; // --------------------------------------------------------------------------- @@ -595,12 +593,11 @@ IMPLEMENTATION [debug]: IMPLEMENT unsigned -Task::unmap_fmt(Tb_entry *e, int max, char *buf) +Task::Log_unmap::print(int max, char *buf) const { - Log_unmap *l = e->payload(); - L4_fpage fp(l->fpage); + L4_fpage fp(fpage); return snprintf(buf, max, "task=[U:%lx] mask=%lx fpage=[%u/%u]%lx", - l->id, l->mask, (unsigned)fp.order(), fp.type(), l->fpage); + id, mask, (unsigned)fp.order(), (unsigned)fp.type(), fpage); } // --------------------------------------------------------------------------- diff --git a/kernel/fiasco/src/kern/tb_entry.cpp b/kernel/fiasco/src/kern/tb_entry.cpp index 31c06803..603fd61e 100644 --- a/kernel/fiasco/src/kern/tb_entry.cpp +++ b/kernel/fiasco/src/kern/tb_entry.cpp @@ -5,24 +5,19 @@ INTERFACE: enum { Tbuf_unused = 0, - Tbuf_pf = 1, - Tbuf_ipc = 2, - Tbuf_ipc_res = 3, - Tbuf_ipc_trace = 4, - Tbuf_ke = 5, - Tbuf_ke_reg = 6, - Tbuf_unmap = 7, - Tbuf_shortcut_failed = 8, - Tbuf_shortcut_succeeded = 9, - Tbuf_context_switch = 10, - Tbuf_exregs = 11, - Tbuf_breakpoint = 12, - Tbuf_trap = 13, - Tbuf_pf_res = 14, - Tbuf_sched = 15, - Tbuf_preemption = 16, - Tbuf_ke_bin = 17, - Tbuf_dynentries = 18, + Tbuf_pf, + Tbuf_ipc, + Tbuf_ipc_res, + Tbuf_ipc_trace, + Tbuf_ke, + Tbuf_ke_reg, + Tbuf_exregs, + Tbuf_breakpoint, + Tbuf_pf_res, + Tbuf_preemption, + Tbuf_ke_bin, + Tbuf_dynentries, + Tbuf_max = 0x80, Tbuf_hidden = 0x80, }; @@ -30,8 +25,12 @@ enum { #include "l4_types.h" class Tb_entry; - -typedef unsigned Tb_entry_formatter(Tb_entry *e, int max, char *buf); +class Context; +class Space; +class Sched_context; +class Syscall_frame; +class Trap_state; +class Tb_entry_formatter; struct Tb_log_table_entry { @@ -43,13 +42,9 @@ struct Tb_log_table_entry extern Tb_log_table_entry _log_table[]; extern Tb_log_table_entry _log_table_end; -class Context; -class Space; -class Sched_context; -class Syscall_frame; -class Trap_state; -class Tb_entry_base + +class Tb_entry { protected: Mword _number; ///< event number @@ -64,103 +59,148 @@ protected: static Mword (*rdcnt1)(); static Mword (*rdcnt2)(); -} __attribute__((packed)); -class Tb_entry : public Tb_entry_base -{ public: - template - class Payload_traits + class Group_order { public: - enum - { - Align = __alignof__(T), //(sizeof(T) > sizeof(Mword)) ? sizeof(Mword) : sizeof(T), - Offset = sizeof(Tb_entry_base), - Payload_offset = ((Offset + Align -1) & ~(Align-1)) - Offset, - Total = Offset + Payload_offset + sizeof(T), - }; + Group_order() : _o(0) {} // not grouped + Group_order(unsigned v) : _o(2 + v) {} + static Group_order none() { return Group_order(); } + static Group_order last() { return Group_order(255, true); } + static Group_order first() { return Group_order(0); } + static Group_order direct() { return Group_order(1, true); } - template - struct TTI - {}; - - static void tb_entry_size_mismatch(TTI const &) {} - static void payload_too_big(TTI const &) {} - static void payload_too_big() - { - tb_entry_size_mismatch(TTI<(sizeof(Tb_entry) != Tb_entry_size)>()); - payload_too_big(TTI<((int)Total > (int)Tb_entry_size)>()); - } + bool not_grouped() const { return _o == 0; } + bool is_direct() const { return _o == 1; } + bool is_first() const { return _o == 2; } + bool is_last() const { return _o == 255; } + bool grouped() const { return _o >= 2; } + unsigned char depth() const { return _o - 2; } + private: + Group_order(unsigned char v, bool) : _o(v) {} + unsigned char _o; }; -private: - template< typename T > - T *addr_of_payload() const - { - Payload_traits::payload_too_big(); + Group_order has_partner() const { return Group_order::none(); } + Group_order is_partner(Tb_entry const *) const { return Group_order::none(); } + Mword partner() const { return 0; } - Address p = reinterpret_cast
(_payload); - return reinterpret_cast(p + Payload_traits::Payload_offset); +} __attribute__((__packed__, __aligned__(8))); + + +class Tb_entry_union : public Tb_entry +{ +private: + char _padding[Tb_entry_size - sizeof(Tb_entry)]; +}; + +static_assert(sizeof(Tb_entry_union) == Tb_entry::Tb_entry_size, + "Tb_entry_union has the wrong size"); + +struct Tb_entry_empty : public Tb_entry +{ + unsigned print(int, char *) const { return 0; } +}; + +class Tb_entry_formatter +{ +public: + typedef Tb_entry::Group_order Group_order; + + virtual unsigned print(Tb_entry const *e, int max, char *buf) const = 0; + virtual Group_order has_partner(Tb_entry const *e) const = 0; + virtual Group_order is_pair(Tb_entry const *e, Tb_entry const *n) const = 0; + virtual Mword partner(Tb_entry const *e) const = 0; + + static Tb_entry_formatter const *get_fmt(Tb_entry const *e) + { + if (e->type() >= Tbuf_dynentries) + return _log_table[e->type() - Tbuf_dynentries].fmt; + + return _fixed[e->type()]; } +private: + static Tb_entry_formatter const *_fixed[]; +}; + + +template< typename T > +class Tb_entry_formatter_t : public Tb_entry_formatter +{ public: - char _payload[Tb_entry_size-sizeof(Tb_entry_base)]; + typedef T const *Const_ptr; + typedef T *Ptr; - template - T *payload() { return addr_of_payload(); } - - template - T const *payload() const { return addr_of_payload(); } + unsigned print(Tb_entry const *e, int max, char *buf) const + { return static_cast(e)->print(max, buf); } + Group_order has_partner(Tb_entry const *e) const + { return static_cast(e)->has_partner(); } + + Group_order is_pair(Tb_entry const *e, Tb_entry const *n) const + { + //assert (get_fmt(e) == &singleton); + + if (&singleton == get_fmt(n)) + return static_cast(e)->is_partner(static_cast(n)); + return Tb_entry::Group_order::none(); + } + + Mword partner(Tb_entry const *e) const + { return static_cast(e)->partner(); } + + static Tb_entry_formatter_t const singleton; +}; + +template +Tb_entry_formatter_t const Tb_entry_formatter_t::singleton; -} __attribute__((__aligned__(8))) ; /** logged ipc. */ class Tb_entry_ipc : public Tb_entry { private: - struct Payload - { - L4_msg_tag _tag; ///< message tag - Mword _dword[2]; ///< first two message words - L4_obj_ref _dst; ///< destination id - Mword _dbg_id; - Mword _label; - L4_timeout_pair _timeout; ///< timeout - }; + L4_msg_tag _tag; ///< message tag + Mword _dword[2]; ///< first two message words + L4_obj_ref _dst; ///< destination id + Mword _dbg_id; + Mword _label; + L4_timeout_pair _timeout; ///< timeout +public: + Tb_entry_ipc() : _timeout(0) {} + unsigned print(int max, char *buf) const; }; /** logged ipc result. */ class Tb_entry_ipc_res : public Tb_entry { private: - struct Payload - { - L4_msg_tag _tag; ///< message tag - Mword _dword[2]; ///< first two dwords - L4_error _result; ///< result - Mword _from; ///< receive descriptor - Mword _pair_event; ///< referred event - Unsigned8 _have_snd; ///< ipc had send part - Unsigned8 _is_np; ///< next period bit set - }; + L4_msg_tag _tag; ///< message tag + Mword _dword[2]; ///< first two dwords + L4_error _result; ///< result + Mword _from; ///< receive descriptor + Mword _pair_event; ///< referred event + Unsigned8 _have_snd; ///< ipc had send part + Unsigned8 _is_np; ///< next period bit set +public: + unsigned print(int max, char *buf) const; }; /** logged ipc for user level tracing with Vampir. */ class Tb_entry_ipc_trace : public Tb_entry { private: - struct Payload - { - Unsigned64 _snd_tsc; ///< entry tsc - L4_msg_tag _result; ///< result - L4_obj_ref _snd_dst; ///< send destination - Mword _rcv_dst; ///< rcv partner - Unsigned8 _snd_desc; - Unsigned8 _rcv_desc; - }; + Unsigned64 _snd_tsc; ///< entry tsc + L4_msg_tag _result; ///< result + L4_obj_ref _snd_dst; ///< send destination + Mword _rcv_dst; ///< rcv partner + Unsigned8 _snd_desc; + Unsigned8 _rcv_desc; +public: + unsigned print(int max, char *buf) const; }; #if 0 @@ -179,94 +219,100 @@ private: class Tb_entry_pf : public Tb_entry { private: - struct Payload - { - Address _pfa; ///< pagefault address - Mword _error; ///< pagefault error code - Space *_space; - }; + Address _pfa; ///< pagefault address + Mword _error; ///< pagefault error code + Space *_space; +public: + unsigned print(int max, char *buf) const; }; /** pagefault result. */ class Tb_entry_pf_res : public Tb_entry { private: - struct Payload - { - Address _pfa; - L4_error _err; - L4_error _ret; - }; + Address _pfa; + L4_error _err; + L4_error _ret; +public: + unsigned print(int max, char *buf) const; }; /** logged kernel event. */ -class Tb_entry_ke : public Tb_entry +template +class Tb_entry_ke_t : public BASE +{ +protected: + union Msg + { + char msg[BASE::Tb_entry_size - sizeof(BASE)]; + struct Ptr + { + char tag[2]; + char const *ptr; + } mptr; + } _msg; +} __attribute__((__packed__)); + +typedef Tb_entry_ke_t Tb_entry_ke; + +class Tb_entry_ke_reg_b : public Tb_entry +{ +public: + Mword v[3]; +} __attribute__((__packed__)); + +class Tb_entry_ke_reg : public Tb_entry_ke_t { - enum { MSG_POINTER_PAYLOAD_OFFSET - = 5 - ((sizeof(Tb_entry_base) + 2 + 3) % sizeof(Mword)) }; }; /** logged breakpoint. */ class Tb_entry_bp : public Tb_entry { private: - struct Payload - { - Address _address; ///< breakpoint address - int _len; ///< breakpoint length - Mword _value; ///< value at address - int _mode; ///< breakpoint mode - } __attribute__((packed)); + Address _address; ///< breakpoint address + int _len; ///< breakpoint length + Mword _value; ///< value at address + int _mode; ///< breakpoint mode +public: + unsigned print(int max, char *buf) const; }; /** logged context switch. */ class Tb_entry_ctx_sw : public Tb_entry { -private: - struct Payload - { - Context const *_dst; ///< switcher target - Context const *_dst_orig; - Address _kernel_ip; - Mword _lock_cnt; - Space *_from_space; - Sched_context *_from_sched; - Mword _from_prio; - } __attribute__((packed)); -}; +public: + using Tb_entry::_ip; + + Context const *dst; ///< switcher target + Context const *dst_orig; + Address kernel_ip; + Mword lock_cnt; + Space const *from_space; + Sched_context const *from_sched; + Mword from_prio; + unsigned print(int max, char *buf) const; +} __attribute__((packed)); /** logged scheduling event. */ class Tb_entry_sched : public Tb_entry { -private: - struct Payload - { - unsigned short _mode; - Context const *_owner; - unsigned short _id; - unsigned short _prio; - signed long _left; - unsigned long _quantum; - } __attribute__((packed)); -}; - - -/** logged preemption */ -class Tb_entry_preemption : public Tb_entry -{ -private: - struct Payload - { - Mword _preempter; - }; -}; +public: + unsigned short mode; + Context const *owner; + unsigned short id; + unsigned short prio; + signed long left; + unsigned long quantum; + unsigned print(int max, char *buf) const; +} __attribute__((packed)); /** logged binary kernel event. */ class Tb_entry_ke_bin : public Tb_entry { public: + char _msg[Tb_entry_size - sizeof(Tb_entry)]; enum { SIZE = 30 }; }; @@ -284,10 +330,22 @@ IMPLEMENTATION: #include "trap_state.h" -PROTECTED static Mword Tb_entry_base::dummy_read_pmc() { return 0; } +PROTECTED static Mword Tb_entry::dummy_read_pmc() { return 0; } -Mword (*Tb_entry_base::rdcnt1)() = dummy_read_pmc; -Mword (*Tb_entry_base::rdcnt2)() = dummy_read_pmc; +Mword (*Tb_entry::rdcnt1)() = dummy_read_pmc; +Mword (*Tb_entry::rdcnt2)() = dummy_read_pmc; +Tb_entry_formatter const *Tb_entry_formatter::_fixed[Tbuf_dynentries]; + + +PUBLIC static +void +Tb_entry_formatter::set_fixed(unsigned type, Tb_entry_formatter const *f) +{ + if (type >= Tbuf_dynentries) + return; + + _fixed[type] = f; +} PUBLIC static @@ -402,89 +460,63 @@ Tb_entry_ipc::set(Context const *ctx, Mword ip, Syscall_frame *ipc_regs, Utcb *u Mword dbg_id, Unsigned64 left) { set_global(Tbuf_ipc, ctx, ip); - Payload *p = payload(); - p->_dst = ipc_regs->ref(); - p->_label = ipc_regs->from_spec(); + _dst = ipc_regs->ref(); + _label = ipc_regs->from_spec(); - p->_dbg_id = dbg_id; + _dbg_id = dbg_id; - p->_timeout = ipc_regs->timeout(); - p->_tag = ipc_regs->tag(); + _timeout = ipc_regs->timeout(); + _tag = ipc_regs->tag(); if (ipc_regs->next_period()) { - p->_dword[0] = (Unsigned32)(left & 0xffffffff); - p->_dword[1] = (Unsigned32)(left >> 32); + _dword[0] = (Unsigned32)(left & 0xffffffff); + _dword[1] = (Unsigned32)(left >> 32); } else { // hint for gcc register Mword tmp0 = utcb->values[0]; register Mword tmp1 = utcb->values[1]; - p->_dword[0] = tmp0; - p->_dword[1] = tmp1; + _dword[0] = tmp0; + _dword[1] = tmp1; } } -PUBLIC inline -void -Tb_entry_ipc::set_sc(Context const *ctx, Mword ip, Syscall_frame *ipc_regs, - Utcb *utcb, Unsigned64 left) -{ - set_global(Tbuf_shortcut_succeeded, ctx, ip); - Payload *p = payload(); - p->_dst = ipc_regs->ref(); - p->_timeout = ipc_regs->timeout(); - if (ipc_regs->next_period()) - { - p->_dword[0] = (Unsigned32)(left & 0xffffffff); - p->_dword[1] = (Unsigned32)(left >> 32); - } - else - { - // hint for gcc - register Mword tmp0 = utcb->values[0]; - register Mword tmp1 = utcb->values[1]; - p->_dword[0] = tmp0; - p->_dword[1] = tmp1; - } -} - - PUBLIC inline Mword Tb_entry_ipc::ipc_type() const -{ return payload()->_dst.op(); } +{ return _dst.op(); } PUBLIC inline Mword Tb_entry_ipc::dbg_id() const -{ return payload()->_dbg_id; } +{ return _dbg_id; } PUBLIC inline L4_obj_ref Tb_entry_ipc::dst() const -{ return payload()->_dst; } +{ return _dst; } PUBLIC inline L4_timeout_pair Tb_entry_ipc::timeout() const -{ return payload()->_timeout; } +{ return _timeout; } PUBLIC inline L4_msg_tag Tb_entry_ipc::tag() const -{ return payload()->_tag; } +{ return _tag; } PUBLIC inline Mword Tb_entry_ipc::label() const -{ return payload()->_label; } +{ return _label; } PUBLIC inline Mword Tb_entry_ipc::dword(unsigned index) const -{ return payload()->_dword[index]; } +{ return _dword[index]; } PUBLIC inline NEEDS ["entry_frame.h"] @@ -495,54 +527,53 @@ Tb_entry_ipc_res::set(Context const *ctx, Mword ip, Syscall_frame *ipc_regs, Unsigned8 is_np) { set_global(Tbuf_ipc_res, ctx, ip); - Payload *p = payload(); // hint for gcc register Mword tmp0 = utcb->values[0]; register Mword tmp1 = utcb->values[1]; - p->_dword[0] = tmp0; - p->_dword[1] = tmp1; - p->_tag = ipc_regs->tag(); - p->_pair_event = pair_event; - p->_result = L4_error::from_raw(result); - p->_from = ipc_regs->from_spec(); - p->_have_snd = have_snd; - p->_is_np = is_np; + _dword[0] = tmp0; + _dword[1] = tmp1; + _tag = ipc_regs->tag(); + _pair_event = pair_event; + _result = L4_error::from_raw(result); + _from = ipc_regs->from_spec(); + _have_snd = have_snd; + _is_np = is_np; } PUBLIC inline int Tb_entry_ipc_res::have_snd() const -{ return payload()->_have_snd; } +{ return _have_snd; } PUBLIC inline int Tb_entry_ipc_res::is_np() const -{ return payload()->_is_np; } +{ return _is_np; } PUBLIC inline Mword Tb_entry_ipc_res::from() const -{ return payload()->_from; } +{ return _from; } PUBLIC inline L4_error Tb_entry_ipc_res::result() const -{ return payload()->_result; } +{ return _result; } PUBLIC inline L4_msg_tag Tb_entry_ipc_res::tag() const -{ return payload()->_tag; } +{ return _tag; } PUBLIC inline Mword Tb_entry_ipc_res::dword(unsigned index) const -{ return payload()->_dword[index]; } +{ return _dword[index]; } PUBLIC inline Mword Tb_entry_ipc_res::pair_event() const -{ return payload()->_pair_event; } +{ return _pair_event; } PUBLIC inline @@ -553,103 +584,39 @@ Tb_entry_ipc_trace::set(Context const *ctx, Mword ip, Unsigned64 snd_tsc, Unsigned8 rcv_desc) { set_global(Tbuf_ipc_trace, ctx, ip); - payload()->_snd_tsc = snd_tsc; - payload()->_snd_dst = snd_dst; - payload()->_rcv_dst = rcv_dst; - payload()->_result = result; - payload()->_snd_desc = snd_desc; - payload()->_rcv_desc = rcv_desc; + _snd_tsc = snd_tsc; + _snd_dst = snd_dst; + _rcv_dst = rcv_dst; + _result = result; + _snd_desc = snd_desc; + _rcv_desc = rcv_desc; } -#if 0 -PUBLIC inline -void -Tb_entry_ipc_sfl::set(Context *ctx, Mword ip, - Global_id from, - L4_timeout_pair timeout, Global_id dst, - Unsigned8 is_irq, Unsigned8 snd_lst, - Unsigned8 dst_ok, Unsigned8 dst_lck, - Unsigned8 preempt) -{ - set_global(Tbuf_shortcut_failed, ctx, ip); - Payload *p = payload(); - p->_from = from; - p->_timeout = timeout; - p->_dst = dst; - p->_is_irq = is_irq; - p->_snd_lst = snd_lst; - p->_dst_ok = dst_ok; - p->_dst_lck = dst_lck; - p->_preempt = preempt; -} - -PUBLIC inline -L4_timeout_pair -Tb_entry_ipc_sfl::timeout() const -{ return _timeout; } - -PUBLIC inline -Global_id -Tb_entry_ipc_sfl::from() const -{ return _from; } - -PUBLIC inline -Global_id -Tb_entry_ipc_sfl::dst() const -{ return _dst; } - -PUBLIC inline -Unsigned8 -Tb_entry_ipc_sfl::is_irq() const -{ return _is_irq; } - -PUBLIC inline -Unsigned8 -Tb_entry_ipc_sfl::snd_lst() const -{ return _snd_lst; } - -PUBLIC inline -Unsigned8 -Tb_entry_ipc_sfl::dst_ok() const -{ return _dst_ok; } - -PUBLIC inline -Unsigned8 -Tb_entry_ipc_sfl::dst_lck() const -{ return _dst_lck; } - -PUBLIC inline -Unsigned8 -Tb_entry_ipc_sfl::preempt() const -{ return _preempt; } -#endif - PUBLIC inline void Tb_entry_pf::set(Context const *ctx, Address ip, Address pfa, Mword error, Space *spc) { set_global(Tbuf_pf, ctx, ip); - Payload *p = payload(); - p->_pfa = pfa; - p->_error = error; - p->_space = spc; + _pfa = pfa; + _error = error; + _space = spc; } PUBLIC inline Mword Tb_entry_pf::error() const -{ return payload()->_error; } +{ return _error; } PUBLIC inline Address Tb_entry_pf::pfa() const -{ return payload()->_pfa; } +{ return _pfa; } PUBLIC inline Space* Tb_entry_pf::space() const -{ return payload()->_space; } +{ return _space; } PUBLIC inline @@ -658,26 +625,25 @@ Tb_entry_pf_res::set(Context const *ctx, Address ip, Address pfa, L4_error err, L4_error ret) { set_global(Tbuf_pf_res, ctx, ip); - Payload *p = payload(); - p->_pfa = pfa; - p->_err = err; - p->_ret = ret; + _pfa = pfa; + _err = err; + _ret = ret; } PUBLIC inline Address Tb_entry_pf_res::pfa() const -{ return payload()->_pfa; } +{ return _pfa; } PUBLIC inline L4_error Tb_entry_pf_res::err() const -{ return payload()->_err; } +{ return _err; } PUBLIC inline L4_error Tb_entry_pf_res::ret() const -{ return payload()->_ret; } +{ return _ret; } PUBLIC inline @@ -686,10 +652,10 @@ Tb_entry_bp::set(Context const *ctx, Address ip, int mode, int len, Mword value, Address address) { set_global(Tbuf_breakpoint, ctx, ip); - payload()->_mode = mode; - payload()->_len = len; - payload()->_value = value; - payload()->_address = address; + _mode = mode; + _len = len; + _value = value; + _address = address; } @@ -697,181 +663,62 @@ Tb_entry_bp::set(Context const *ctx, Address ip, PUBLIC inline int Tb_entry_bp::mode() const -{ return payload()->_mode; } +{ return _mode; } PUBLIC inline int Tb_entry_bp::len() const -{ return payload()->_len; } +{ return _len; } PUBLIC inline Mword Tb_entry_bp::value() const -{ return payload()->_value; } +{ return _value; } PUBLIC inline Address Tb_entry_bp::addr() const -{ return payload()->_address; } +{ return _address; } -PUBLIC inline +PUBLIC template inline void -Tb_entry_ke::set(Context const *ctx, Address ip) -{ set_global(Tbuf_ke, ctx, ip); } +Tb_entry_ke_t::set(Context const *ctx, Address ip) +{ this->set_global(TAG, ctx, ip); } -PUBLIC inline +PUBLIC template inline void -Tb_entry_ke::set_const(Context const *ctx, Address ip, const char * const msg) +Tb_entry_ke_t::set_const(Context const *ctx, Address ip, char const *msg) { - set_global(Tbuf_ke, ctx, ip); - char *_msg = payload(); - _msg[0] = 0; _msg[1] = 1; - *(char const ** const)(_msg + MSG_POINTER_PAYLOAD_OFFSET) = msg; + this->set_global(TAG, ctx, ip); + _msg.mptr.tag[0] = 0; + _msg.mptr.tag[1] = 1; + _msg.mptr.ptr = msg; } -PUBLIC inline +PUBLIC template inline void -Tb_entry_ke::set_buf(unsigned i, char c) +Tb_entry_ke_t::set_buf(unsigned i, char c) { - char *_msg = payload(); - if (i < sizeof(_payload)-1) - _msg[i] = c >= ' ' ? c : '.'; + if (i < sizeof(_msg.msg)-1) + _msg.msg[i] = c >= ' ' ? c : '.'; } -PUBLIC inline +PUBLIC template inline void -Tb_entry_ke::term_buf(unsigned i) +Tb_entry_ke_t::term_buf(unsigned i) { - char *_msg = payload(); - _msg[i < sizeof(_payload)-1 ? i : sizeof(_payload)-1] = '\0'; + _msg.msg[i < sizeof(_msg.msg)-1 ? i : sizeof(_msg.msg)-1] = '\0'; } -PUBLIC inline -const char * -Tb_entry_ke::msg() const +PUBLIC template inline +char const * +Tb_entry_ke_t::msg() const { - char const *_msg = payload(); - return _msg[0] == 0 && _msg[1] == 1 - ? *(char const ** const)(_msg + MSG_POINTER_PAYLOAD_OFFSET) : _msg; + return _msg.mptr.tag[0] == 0 && _msg.mptr.tag[1] == 1 ? _msg.mptr.ptr : _msg.msg; } - -PUBLIC inline -void -Tb_entry_ctx_sw::set(Context const *ctx, Space *from_space, Address ip, - Context const *dst, Context const *dst_orig, - Mword lock_cnt, - Sched_context *from_sched, Mword from_prio, - Address kernel_ip) -{ - set_global(Tbuf_context_switch, ctx, ip); - payload()->_kernel_ip = kernel_ip; - payload()->_dst = dst; - payload()->_dst_orig = dst_orig; - payload()->_lock_cnt = lock_cnt; - payload()->_from_space = from_space; - payload()->_from_sched = from_sched; - payload()->_from_prio = from_prio; -} - -PUBLIC inline -Space* -Tb_entry_ctx_sw::from_space() const -{ return payload()->_from_space; } - -PUBLIC inline -Address -Tb_entry_ctx_sw::kernel_ip() const -{ return payload()->_kernel_ip; } - -PUBLIC inline -Mword -Tb_entry_ctx_sw::lock_cnt() const -{ return payload()->_lock_cnt; } - -PUBLIC inline -Context const * -Tb_entry_ctx_sw::dst() const -{ return payload()->_dst; } - -PUBLIC inline -Context const * -Tb_entry_ctx_sw::dst_orig() const -{ return payload()->_dst_orig; } - -PUBLIC inline -Mword -Tb_entry_ctx_sw::from_prio() const -{ return payload()->_from_prio; } - -PUBLIC inline -Sched_context* -Tb_entry_ctx_sw::from_sched() const -{ return payload()->_from_sched; } - -PUBLIC inline -void -Tb_entry_sched::set (Context const *ctx, Address ip, unsigned short mode, - Context const *owner, unsigned short id, unsigned short prio, - signed long left, unsigned long quantum) -{ - set_global (Tbuf_sched, ctx, ip); - payload()->_mode = mode; - payload()->_owner = owner; - payload()->_id = id; - payload()->_prio = prio; - payload()->_left = left; - payload()->_quantum = quantum; -} - -PUBLIC inline -unsigned short -Tb_entry_sched::mode() const -{ return payload()->_mode; } - -PUBLIC inline -Context const * -Tb_entry_sched::owner() const -{ return payload()->_owner; } - -PUBLIC inline -unsigned short -Tb_entry_sched::id() const -{ return payload()->_id; } - -PUBLIC inline -unsigned short -Tb_entry_sched::prio() const -{ return payload()->_prio; } - -PUBLIC inline -unsigned long -Tb_entry_sched::quantum() const -{ return payload()->_quantum; } - -PUBLIC inline -signed long -Tb_entry_sched::left() const -{ return payload()->_left; } - -PUBLIC inline -void -Tb_entry_preemption::set (Context const *ctx, Mword preempter, - Address ip) -{ - set_global (Tbuf_preemption, ctx, ip); - payload()->_preempter = preempter; -}; - -PUBLIC inline -Mword -Tb_entry_preemption::preempter() const -{ return payload()->_preempter; } - - - PUBLIC inline void Tb_entry_ke_bin::set(Context const *ctx, Address ip) @@ -881,7 +728,19 @@ PUBLIC inline void Tb_entry_ke_bin::set_buf(unsigned i, char c) { - char *_bin = payload(); - if (i < sizeof(_payload)-1) - _bin[i] = c; + if (i < sizeof(_msg)-1) + _msg[i] = c; } + +PUBLIC inline +void +Tb_entry_ke_reg::set_const(Context const *ctx, Mword eip, + const char *msg, + Mword v1, Mword v2, Mword v3) +{ + Tb_entry_ke_t::set_const(ctx, eip, msg); + v[0] = v1; + v[1] = v2; + v[2] = v3; +} + diff --git a/kernel/fiasco/src/kern/tb_entry_output.cpp b/kernel/fiasco/src/kern/tb_entry_output.cc similarity index 76% rename from kernel/fiasco/src/kern/tb_entry_output.cpp rename to kernel/fiasco/src/kern/tb_entry_output.cc index 4e0da8e1..ab776748 100644 --- a/kernel/fiasco/src/kern/tb_entry_output.cpp +++ b/kernel/fiasco/src/kern/tb_entry_output.cc @@ -1,5 +1,3 @@ -IMPLEMENTATION: - #include #include #include @@ -9,6 +7,7 @@ IMPLEMENTATION: #include "jdb_symbol.h" #include "jdb_tbuf_output.h" #include "jdb_util.h" +#include "kobject_dbg.h" #include "static_init.h" #include "tb_entry.h" #include "thread.h" @@ -139,6 +138,39 @@ tag_interpreter_snprintf(char *&buf, int &maxlen, L4_msg_tag const &tag) maxlen -= len; } +class Tb_entry_ipc_fmt : public Tb_entry_formatter +{ +public: + unsigned print(Tb_entry const *, int, char *) const { return 0; } + Group_order has_partner(Tb_entry const *) const + { return Tb_entry::Group_order::first(); } + Group_order is_pair(Tb_entry const *e, Tb_entry const *n) const + { + if (static_cast(n)->pair_event() == e->number()) + return Group_order::last(); + else + return Group_order::none(); + } + Mword partner(Tb_entry const *) const { return 0; } +}; + +class Tb_entry_ipc_res_fmt : public Tb_entry_formatter +{ +public: + unsigned print(Tb_entry const *, int, char *) const { return 0; } + Group_order has_partner(Tb_entry const *) const + { return Tb_entry::Group_order::last(); } + Group_order is_pair(Tb_entry const *e, Tb_entry const *n) const + { + if (static_cast(e)->pair_event() == n->number()) + return Group_order::first(); + else + return Group_order::none(); + } + Mword partner(Tb_entry const *e) const { return static_cast(e)->pair_event(); } +}; + + // ipc / irq / shortcut success static unsigned @@ -248,9 +280,6 @@ formatter_ipc_res(Tb_entry *tb, const char *tidstr, unsigned tidlen, return maxlen; } -IMPLEMENTATION: - -#include "kobject_dbg.h" // pagefault static @@ -272,23 +301,19 @@ formatter_pf(Tb_entry *tb, const char *tidstr, unsigned tidlen, return maxlen; } -// pagefault result -static +// pagefault unsigned -formatter_pf_res(Tb_entry *tb, const char *tidstr, unsigned tidlen, - char *buf, int maxlen) +Tb_entry_pf::print(int maxlen, char *buf) const { - Tb_entry_pf_res *e = static_cast(tb); + char ip_buf[32]; - // e->ret contains only an error code - // e->err contains only up to 3 dwords - my_snprintf(buf, maxlen, " %-*s pfa=" L4_PTR_FMT " dope=%02lx (%s%s) " - "err=%04lx (%s%s)", - tidlen, tidstr, e->pfa(), - e->ret().raw(), e->ret().error() ? "L4_IPC_" : "", - e->ret().str_error(), - e->err().raw(), e->err().error() ? "L4_IPC_" : "", - e->err().str_error()); + snprintf(ip_buf, sizeof(ip_buf), L4_PTR_FMT, ip()); + my_snprintf(buf, maxlen, "pfa=" L4_PTR_FMT " ip=%s (%c%c) spc=%p", + pfa(), ip() ? ip_buf : "unknown", + !PF::is_read_error(error()) ? (error() & 4 ? 'w' : 'W') + : (error() & 4 ? 'r' : 'R'), + !PF::is_translation_error(error()) ? 'p' : '-', + space()); return maxlen; } @@ -321,7 +346,7 @@ formatter_ke_reg(Tb_entry *tb, const char *tidstr, unsigned tidlen, snprintf(ip_buf, sizeof(ip_buf), " @ " L4_PTR_FMT, e->ip()); my_snprintf(buf, maxlen, "ke: %-*s \"%s\" " L4_PTR_FMT " " L4_PTR_FMT " " L4_PTR_FMT "%s", - tidlen, tidstr, e->msg(), e->val1(), e->val2(), e->val3(), + tidlen, tidstr, e->msg(), e->v[0], e->v[1], e->v[2], e->ip() ? ip_buf : ""); return maxlen; @@ -367,52 +392,51 @@ formatter_bp(Tb_entry *tb, const char *tidstr, unsigned tidlen, } // context switch -static +//IMPLEMENT unsigned -formatter_ctx_switch(Tb_entry *tb, const char *tidstr, unsigned tidlen, - char *buf, int maxlen) +Tb_entry_ctx_sw::print(int maxlen, char *buf) const { - char symstr[24], spcstr[16] = ""; - Tb_entry_ctx_sw *e = static_cast(tb); + char symstr[24]; - Context *sctx = 0; + Context *sctx = 0; Mword sctxid = ~0UL; Mword dst; Mword dst_orig; - sctx = e->from_sched()->context(); + sctx = from_sched->context(); sctxid = static_cast(sctx)->dbg_id(); - dst = static_cast(e->dst())->dbg_id(); - dst_orig = static_cast(e->dst_orig())->dbg_id(); + dst = static_cast(this->dst)->dbg_id(); + dst_orig = static_cast(this->dst_orig)->dbg_id(); - Address addr = e->kernel_ip(); + Address addr = kernel_ip; if (!Jdb_symbol::match_addr_to_symbol_fuzzy(&addr, 0 /*kernel*/, symstr, sizeof(symstr))) - snprintf(symstr, sizeof(symstr), L4_PTR_FMT, e->kernel_ip()); - + snprintf(symstr, sizeof(symstr), L4_PTR_FMT, kernel_ip); +#if 0 my_snprintf(buf, maxlen, " %-*s%s '%02lx", tidlen, tidstr, spcstr, e->from_prio()); - if (sctx != e->ctx()) +#endif + + if (sctx != ctx()) my_snprintf(buf, maxlen, "(%lx)", sctxid); my_snprintf(buf, maxlen, " ==> %lx ", dst); - if (dst != dst_orig || e->lock_cnt()) + if (dst != dst_orig || lock_cnt) my_snprintf(buf, maxlen, "("); if (dst != dst_orig) - my_snprintf(buf, maxlen, "want %lx", - dst_orig); + my_snprintf(buf, maxlen, "want %lx", dst_orig); - if (dst != dst_orig && e->lock_cnt()) + if (dst != dst_orig && lock_cnt) my_snprintf(buf, maxlen, " "); - if (e->lock_cnt()) - my_snprintf(buf, maxlen, "lck %ld", e->lock_cnt()); + if (lock_cnt) + my_snprintf(buf, maxlen, "lck %ld", lock_cnt); - if (dst != dst_orig || e->lock_cnt()) + if (dst != dst_orig || lock_cnt) my_snprintf(buf, maxlen, ") "); my_snprintf(buf, maxlen, " krnl %s", symstr); @@ -422,67 +446,43 @@ formatter_ctx_switch(Tb_entry *tb, const char *tidstr, unsigned tidlen, // trap -static unsigned -formatter_trap(Tb_entry *tb, const char *tidstr, unsigned tidlen, - char *buf, int maxlen) +Tb_entry_trap::print(int maxlen, char *buf) const { - Tb_entry_trap *e = static_cast(tb); - - if (!e->cs()) - my_snprintf(buf, maxlen, "#%02x: %-*s err=%08x @ " L4_PTR_FMT, - e->trapno(), tidlen, tidstr, e->error(), e->ip()); + if (!cs()) + my_snprintf(buf, maxlen, "#%02x: err=%08x @ " L4_PTR_FMT, + trapno(), error(), ip()); else my_snprintf(buf, maxlen, - e->trapno() == 14 - ? "#%02x: %-*s err=%04x @ " L4_PTR_FMT + trapno() == 14 + ? "#%02x: err=%04x @ " L4_PTR_FMT " cs=%04x sp=" L4_PTR_FMT " cr2=" L4_PTR_FMT - : "#%02x: %-*s err=%04x @ " L4_PTR_FMT + : "#%02x: err=%04x @ " L4_PTR_FMT " cs=%04x sp=" L4_PTR_FMT " eax=" L4_PTR_FMT, - e->trapno(), - tidlen, tidstr, e->error(), e->ip(), e->cs(), e->sp(), - e->trapno() == 14 ? e->cr2() : e->eax()); + trapno(), + error(), ip(), cs(), sp(), + trapno() == 14 ? cr2() : eax()); return maxlen; } // sched -static unsigned -formatter_sched(Tb_entry *tb, const char *tidstr, unsigned tidlen, - char *buf, int maxlen) +Tb_entry_sched::print(int maxlen, char *buf) const { - Tb_entry_sched *e = static_cast(tb); - Thread const *_t = static_cast(e->owner()); + Thread const *_t = static_cast(owner); Mword t = ~0UL; if (Jdb_util::is_mapped(_t)) t = _t->dbg_id(); my_snprintf(buf, maxlen, - "%-*s (ts %s) owner:%lx id:%2x, prio:%2x, left:%6ld/%-6lu", - tidlen, tidstr, - e->mode() == 0 ? "save" : - e->mode() == 1 ? "load" : - e->mode() == 2 ? "invl" : "????", - t, - e->id(), e->prio(), e->left(), e->quantum()); - - return maxlen; -} - -// preemption -static -unsigned -formatter_preemption(Tb_entry *tb, const char *tidstr, unsigned tidlen, - char *buf, int maxlen) -{ - Tb_entry_preemption *e = static_cast(tb); - Mword t = e->preempter(); - - my_snprintf(buf, maxlen, - "pre: %-*s sent to %lx", - tidlen, tidstr, t); + "(ts %s) owner:%lx id:%2x, prio:%2x, left:%6ld/%-6lu", + mode == 0 ? "save" : + mode == 1 ? "load" : + mode == 2 ? "invl" : "????", + t, + id, prio, left, quantum); return maxlen; } @@ -503,7 +503,8 @@ formatter_ke_bin(Tb_entry *tb, const char *tidstr, unsigned tidlen, return maxlen; } -STATIC_INITIALIZER(init_formatters); +static Tb_entry_ipc_fmt const _ipc_fmt; +static Tb_entry_ipc_res_fmt const _ipc_res_fmt; // register all available format functions static FIASCO_INIT @@ -511,16 +512,14 @@ void init_formatters() { Jdb_tbuf_output::register_ff(Tbuf_pf, formatter_pf); - Jdb_tbuf_output::register_ff(Tbuf_pf_res, formatter_pf_res); Jdb_tbuf_output::register_ff(Tbuf_ipc, formatter_ipc); + Tb_entry_formatter::set_fixed(Tbuf_ipc, &_ipc_fmt); Jdb_tbuf_output::register_ff(Tbuf_ipc_res, formatter_ipc_res); + Tb_entry_formatter::set_fixed(Tbuf_ipc_res, &_ipc_res_fmt); Jdb_tbuf_output::register_ff(Tbuf_ke, formatter_ke); Jdb_tbuf_output::register_ff(Tbuf_ke_reg, formatter_ke_reg); - Jdb_tbuf_output::register_ff(Tbuf_shortcut_succeeded, formatter_ipc); - Jdb_tbuf_output::register_ff(Tbuf_context_switch, formatter_ctx_switch); Jdb_tbuf_output::register_ff(Tbuf_breakpoint, formatter_bp); - Jdb_tbuf_output::register_ff(Tbuf_trap, formatter_trap); - Jdb_tbuf_output::register_ff(Tbuf_sched, formatter_sched); - Jdb_tbuf_output::register_ff(Tbuf_preemption, formatter_preemption); Jdb_tbuf_output::register_ff(Tbuf_ke_bin, formatter_ke_bin); } + +STATIC_INITIALIZER(init_formatters); diff --git a/kernel/fiasco/src/kern/thread-debug.cpp b/kernel/fiasco/src/kern/thread-debug.cpp index 6c9d9acd..984f1a16 100644 --- a/kernel/fiasco/src/kern/thread-debug.cpp +++ b/kernel/fiasco/src/kern/thread-debug.cpp @@ -1,13 +1,15 @@ INTERFACE [debug]: +#include "tb_entry.h" + EXTENSION class Thread { protected: - struct Log_thread_exregs + struct Log_thread_exregs : public Tb_entry { Mword id, ip, sp, op; + unsigned print(int, char *) const; }; - static unsigned fmt_exregs(Tb_entry *, int, char *) asm ("__fmt_thread_exregs"); }; //-------------------------------------------------------------------------- @@ -25,19 +27,15 @@ IMPLEMENTATION [debug]: IMPLEMENT unsigned -Thread::fmt_exregs(Tb_entry *e, int max, char *buf) +Thread::Log_thread_exregs::print(int max, char *buf) const { - Log_thread_exregs *l = e->payload(); return snprintf(buf, max, "D=%lx ip=%lx sp=%lx op=%s%s%s", - l->id, l->ip, l->sp, - l->op & Exr_cancel ? "Cancel" : "", - ((l->op & (Exr_cancel | - Exr_trigger_exception)) - == (Exr_cancel | - Exr_trigger_exception)) + id, ip, sp, + op & Exr_cancel ? "Cancel" : "", + ((op & (Exr_cancel | Exr_trigger_exception)) + == (Exr_cancel | Exr_trigger_exception)) ? "," - : ((l->op & (Exr_cancel | - Exr_trigger_exception)) + : ((op & (Exr_cancel | Exr_trigger_exception)) == 0 ? "0" : "") , - l->op & Exr_trigger_exception ? "TrExc" : ""); + op & Exr_trigger_exception ? "TrExc" : ""); } diff --git a/kernel/fiasco/src/kern/thread-ipc.cpp b/kernel/fiasco/src/kern/thread-ipc.cpp index f7900c0f..972c7d05 100644 --- a/kernel/fiasco/src/kern/thread-ipc.cpp +++ b/kernel/fiasco/src/kern/thread-ipc.cpp @@ -1,3 +1,25 @@ +INTERFACE [debug]: + +#include "tb_entry.h" + +EXTENSION class Thread +{ +protected: + struct Log_pf_invalid : public Tb_entry + { + Mword pfa; + Mword cap_idx; + Mword err; + unsigned print(int max, char *buf) const; + }; + + struct Log_exc_invalid : public Tb_entry + { + Mword cap_idx; + unsigned print(int max, char *buf) const; + }; +}; + INTERFACE: #include "l4_buf_iter.h" @@ -8,18 +30,6 @@ class Syscall_frame; EXTENSION class Thread { protected: - struct Log_pf_invalid - { - Mword pfa; - Mword cap_idx; - Mword err; - }; - - struct Log_exc_invalid - { - Mword cap_idx; - }; - enum Check_sender_result { Ok = 0, @@ -54,6 +64,31 @@ private: Mword msg[2]; }; +struct Ipc_remote_request; + +struct Ipc_remote_request +{ + L4_msg_tag tag; + Thread *partner; + Syscall_frame *regs; + unsigned char rights; + bool timeout; + bool have_rcv; + + unsigned result; +}; + +struct Ready_queue_request +{ + Thread *thread; + Mword state_add; + Mword state_del; + + enum Result { Done, Wrong_cpu, Not_existent }; + Result result; +}; + + // ------------------------------------------------------------------------ INTERFACE [debug]: @@ -139,7 +174,9 @@ Thread::ipc_send_msg(Receiver *recv) if (cpu() == current_cpu()) { state_change_dirty(~state_del, state_add); - if (current_sched()->deblock(cpu(), current_sched(), true)) + auto &rq = Sched_context::rq.current(); + Sched_context *cs = rq.current_sched(); + if (rq.deblock(cs, cs, true)) recv->switch_to_locked(this); } else @@ -203,7 +240,7 @@ Thread::handle_page_fault_pager(Thread_ptr const &_pager, if (EXPECT_FALSE((state() & Thread_alien))) return false; - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); unsigned char rights; Kobject_iface *pager = _pager.ptr(space(), &rights); @@ -216,9 +253,7 @@ Thread::handle_page_fault_pager(Thread_ptr const &_pager, _pager.raw(), regs()->ip()); - LOG_TRACE("Page fault invalid pager", "pf", this, - __fmt_page_fault_invalid_pager, - Log_pf_invalid *l = tbe->payload(); + LOG_TRACE("Page fault invalid pager", "pf", this, Log_pf_invalid, l->cap_idx = _pager.raw(); l->err = error_code; l->pfa = pfa); @@ -325,7 +360,7 @@ void Thread::goto_sleep(L4_timeout const &t, Sender *sender, Utcb *utcb) if (EXPECT_TRUE((tval > sysclock))) { set_timeout(&timeout); - timeout.set(tval, cpu()); + timeout.set(tval, cpu(true)); } else // timeout already hit state_change_dirty(~Thread_ipc_mask, Thread_ready | Thread_timeout); @@ -339,7 +374,7 @@ void Thread::goto_sleep(L4_timeout const &t, Sender *sender, Utcb *utcb) } if (sender == this) - switch_sched(sched()); + switch_sched(sched(), &Sched_context::rq.current()); schedule(); @@ -521,13 +556,21 @@ Thread::do_ipc(L4_msg_tag const &tag, bool have_send, Thread *partner, { if (partner->cpu() == current_cpu()) { - Sched_context *cs = Sched_context::rq(cpu()).current_sched(); - do_switch = do_switch && ((have_receive && sender) || cs->context() != this) - && !(next && current_sched()->dominates(cs)); + auto &rq = Sched_context::rq.current(); + Sched_context *cs = rq.current_sched(); + do_switch = do_switch && ((have_receive && sender) || cs->context() != this) && !next; partner->state_change_dirty(~Thread_ipc_transfer, Thread_ready); if (do_switch) - schedule_if(handle_drq() || switch_exec_locked(partner, Context::Not_Helping)); - else if (partner->current_sched()->deblock(current_cpu(), current_sched(), true)) + { + if (handle_drq()) + { + rq.deblock(partner->sched(), cs, false); + schedule(); + } + else + schedule_if(switch_exec_locked(partner, Context::Not_Helping)); + } + else if (rq.deblock(partner->sched(), cs, true)) switch_to_locked(partner); } else @@ -721,8 +764,7 @@ Thread::send_exception(Trap_state *ts) vcpu = vcpu_state().access(); } - LOG_TRACE("VCPU events", "vcpu", this, __context_vcpu_log_fmt, - Vcpu_log *l = tbe->payload(); + LOG_TRACE("VCPU events", "vcpu", this, Vcpu_log, l->type = 2; l->state = vcpu->_saved_state; l->ip = ts->ip(); @@ -748,9 +790,7 @@ Thread::send_exception(Trap_state *ts) if (EXPECT_FALSE(!pager)) { /* no pager (anymore), just ignore the exception, return success */ - LOG_TRACE("Exception invalid handler", "exc", this, - __fmt_exception_invalid_handler, - Log_exc_invalid *l = tbe->payload(); + LOG_TRACE("Exception invalid handler", "exc", this, Log_exc_invalid, l->cap_idx = _exc_handler.raw()); if (EXPECT_FALSE(space()->is_sigma0())) { @@ -929,13 +969,13 @@ Thread::transfer_msg_items(L4_msg_tag const &tag, Thread* snd, Utcb *snd_utcb, // We take the existence_lock for syncronizing maps... // This is kind of coarse grained Lock_guardexistence_lock)> sp_lock; - if (!sp_lock.try_lock(&rcv_t->existence_lock)) + if (!sp_lock.check_and_lock(&rcv_t->existence_lock)) { snd->set_ipc_error(L4_error::Overflow, rcv); return false; } - Lock_guard c_lock(&cpu_lock); + auto c_lock = lock_guard(cpu_lock); err = fpage_map(snd->space(), sfp, rcv->space(), L4_fpage(buf->d), item->b, &rl); } @@ -1062,49 +1102,6 @@ Thread::set_ipc_send_rights(unsigned char c) _ipc_send_rights = c; } -//--------------------------------------------------------------------- -IMPLEMENTATION [!mp]: - -PRIVATE inline NEEDS ["l4_types.h"] -unsigned -Thread::remote_handshake_receiver(L4_msg_tag const &, Thread *, - bool, L4_timeout, Syscall_frame *, unsigned char) -{ - kdb_ke("Remote IPC in UP kernel"); - return Failed; -} - -//--------------------------------------------------------------------- -INTERFACE [mp]: - -struct Ipc_remote_request; - -struct Ipc_remote_request -{ - L4_msg_tag tag; - Thread *partner; - Syscall_frame *regs; - unsigned char rights; - bool timeout; - bool have_rcv; - - unsigned result; -}; - -struct Ready_queue_request -{ - Thread *thread; - Mword state_add; - Mword state_del; - - enum Result { Done, Wrong_cpu, Not_existent }; - Result result; -}; - -//--------------------------------------------------------------------- -IMPLEMENTATION [mp]: - - PRIVATE inline NOEXPORT bool Thread::remote_ipc_send(Context *src, Ipc_remote_request *rq) @@ -1222,16 +1219,14 @@ IMPLEMENTATION [debug]: IMPLEMENT unsigned -Thread::log_fmt_pf_invalid(Tb_entry *e, int max, char *buf) +Thread::Log_pf_invalid::print(int max, char *buf) const { - Log_pf_invalid *l = e->payload(); - return snprintf(buf, max, "InvCap C:%lx pfa=%lx err=%lx", l->cap_idx, l->pfa, l->err); + return snprintf(buf, max, "InvCap C:%lx pfa=%lx err=%lx", cap_idx, pfa, err); } IMPLEMENT unsigned -Thread::log_fmt_exc_invalid(Tb_entry *e, int max, char *buf) +Thread::Log_exc_invalid::print(int max, char *buf) const { - Log_exc_invalid *l = e->payload(); - return snprintf(buf, max, "InvCap C:%lx", l->cap_idx); + return snprintf(buf, max, "InvCap C:%lx", cap_idx); } diff --git a/kernel/fiasco/src/kern/thread-log.cpp b/kernel/fiasco/src/kern/thread-log.cpp index 37c56f69..0ef1e6bd 100644 --- a/kernel/fiasco/src/kern/thread-log.cpp +++ b/kernel/fiasco/src/kern/thread-log.cpp @@ -22,7 +22,7 @@ Thread::page_fault_log(Address pfa, unsigned error_code, unsigned long eip) { if (Jdb_pf_trace::check_restriction(current_thread()->dbg_id(), pfa)) { - Lock_guard guard (&cpu_lock); + auto guard = lock_guard(cpu_lock); Tb_entry_pf _local; Tb_entry_pf *tb = static_cast diff --git a/kernel/fiasco/src/kern/thread-pagefault.cpp b/kernel/fiasco/src/kern/thread-pagefault.cpp index 63966ce5..c2ae77c5 100644 --- a/kernel/fiasco/src/kern/thread-pagefault.cpp +++ b/kernel/fiasco/src/kern/thread-pagefault.cpp @@ -36,7 +36,7 @@ int Thread::handle_page_fault (Address pfa, Mword error_code, Mword pc, //if (Config::Log_kernel_page_faults && !PF::is_usermode_error(error_code)) if (0 && current_cpu() != 0) { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); printf("*KP[cpu=%u, sp=%lx, pfa=%lx, pc=%lx, error=(%lx)", current_cpu(), Proc::stack_pointer(), pfa, pc, error_code); print_page_fault_error(error_code); printf("]\n"); diff --git a/kernel/fiasco/src/kern/thread-vcpu.cpp b/kernel/fiasco/src/kern/thread-vcpu.cpp index ac188e63..73276fd5 100644 --- a/kernel/fiasco/src/kern/thread-vcpu.cpp +++ b/kernel/fiasco/src/kern/thread-vcpu.cpp @@ -35,8 +35,7 @@ Thread::vcpu_pagefault(Address pfa, Mword err, Mword ip) { spill_user_state(); vcpu_enter_kernel_mode(vcpu); - LOG_TRACE("VCPU events", "vcpu", this, __context_vcpu_log_fmt, - Vcpu_log *l = tbe->payload(); + LOG_TRACE("VCPU events", "vcpu", this, Vcpu_log, l->type = 3; l->state = vcpu->_saved_state; l->ip = ip; diff --git a/kernel/fiasco/src/kern/thread.cpp b/kernel/fiasco/src/kern/thread.cpp index 9f1d0a45..f24ca322 100644 --- a/kernel/fiasco/src/kern/thread.cpp +++ b/kernel/fiasco/src/kern/thread.cpp @@ -56,6 +56,7 @@ public: Op_modify_senders = 6, Op_vcpu_control= 7, Op_gdt_x86 = 0x10, + Op_set_tpidruro_arm = 0x10, Op_set_fs_amd64 = 0x12, }; @@ -111,7 +112,7 @@ public: private: struct Migration_helper_info { - Migration_info inf; + Migration *inf; Thread *victim; }; @@ -232,7 +233,7 @@ Thread::bind(Task *t, User::Ptr utcb) if (EXPECT_FALSE(utcb && !u)) return false; - Lock_guard guard(_space.lock()); + auto guard = lock_guard(_space.lock()); if (_space.space() != Kernel_task::kernel_task()) return false; @@ -256,7 +257,7 @@ Thread::unbind() Task *old; { - Lock_guard guard(_space.lock()); + auto guard = lock_guard(_space.lock()); if (_space.space() == Kernel_task::kernel_task()) return true; @@ -357,7 +358,7 @@ void Thread::ipc_gate_deleted(Mword id) { (void) id; - Lock_guard g(&cpu_lock); + auto g = lock_guard(cpu_lock); if (_del_observer) _del_observer->hit(0); } @@ -438,7 +439,7 @@ Thread::handle_timer_interrupt() // Check if we need to reschedule due to timeouts or wakeups if ((Timeout_q::timeout_queue.cpu(_cpu).do_timeouts() || resched) - && !schedule_in_progress()) + && !Sched_context::rq.current().schedule_in_progress) { schedule(); assert (timeslice_timeout.cpu(cpu(true))->is_set()); // Coma check @@ -478,7 +479,7 @@ Thread::user_invoke_generic() Context *const c = current(); assert_kdb (c->state() & Thread_ready_mask); - if (c->handle_drq() && !c->schedule_in_progress()) + if (c->handle_drq()) c->schedule(); // release CPU lock explicitly, because @@ -511,7 +512,7 @@ PRIVATE bool Thread::do_kill() { - Lock_guard guard(thread_lock()); + auto guard = lock_guard(thread_lock()); if (state() == Thread_invalid) return false; @@ -523,7 +524,7 @@ Thread::do_kill() // But first prevent it from being woken up by asynchronous events { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); // if IPC timeout active, reset it if (_timeout) @@ -532,18 +533,20 @@ Thread::do_kill() // Switch to time-sharing mode set_mode(Sched_mode(0)); + Sched_context::Ready_queue &rq = Sched_context::rq.current(); + // Switch to time-sharing scheduling context if (sched() != sched_context()) - switch_sched(sched_context()); + switch_sched(sched_context(), &rq); - if (!current_sched() || current_sched()->context() == this) - set_current_sched(current()->sched()); + if (!rq.current_sched() || rq.current_sched()->context() == this) + rq.set_current_sched(current()->sched()); } // if other threads want to send me IPC messages, abort these // operations { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); while (Sender *s = Sender::cast(sender_list()->first())) { s->sender_dequeue(sender_list()); @@ -558,7 +561,7 @@ Thread::do_kill() { while (Locked_prio_list *q = wait_queue()) { - Lock_guardlock())> g(q->lock()); + auto g = lock_guard(q->lock()); if (wait_queue() == q) { sender_dequeue(q); @@ -580,7 +583,7 @@ Thread::do_kill() state_change_dirty(0, Thread_dead); // dequeue from system queues - ready_dequeue(); + Sched_context::rq.current().ready_dequeue(sched()); if (_del_observer) { @@ -601,7 +604,7 @@ Thread::do_kill() state_del_dirty(Thread_ready_mask); - ready_dequeue(); + Sched_context::rq.current().ready_dequeue(sched()); kernel_context_drq(handle_kill_helper, 0); kdb_ke("Im dead"); @@ -624,14 +627,14 @@ PROTECTED bool Thread::kill() { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); inc_ref(); if (cpu() == current_cpu()) { state_add_dirty(Thread_cancel | Thread_ready); - sched()->deblock(cpu()); + Sched_context::rq.current().deblock(sched()); _exc_cont.restore(regs()); // overwrite an already triggered exception do_trigger_exception(regs(), (void*)&Thread::leave_and_kill_myself); // current()->switch_exec (this, Helping); @@ -646,32 +649,31 @@ Thread::kill() PUBLIC void -Thread::set_sched_params(unsigned prio, Unsigned64 quantum) +Thread::set_sched_params(L4_sched_param const *p) { Sched_context *sc = sched_context(); + // FIXME: do not know how to figure this out currently, however this + // seems to be just an optimization +#if 0 bool const change = prio != sc->prio() || quantum != sc->quantum(); bool const ready_queued = in_ready_list(); if (!change && (ready_queued || this == current())) return; +#endif - ready_dequeue(); + Sched_context::Ready_queue &rq = Sched_context::rq.cpu(cpu()); + rq.ready_dequeue(sched()); - sc->set_prio(prio); - sc->set_quantum(quantum); + sc->set(p); sc->replenish(); - if (sc == current_sched()) - set_current_sched(sc); + if (sc == rq.current_sched()) + rq.set_current_sched(sc); - if (state() & Thread_ready_mask) - { - if (this != current()) - ready_enqueue(); - else - schedule(); - } + if (state() & Thread_ready_mask) // maybe we could ommit enqueueing current + rq.ready_enqueue(sched()); } PUBLIC @@ -700,7 +702,7 @@ PUBLIC static inline void Thread::assert_irq_entry() { - assert_kdb(current_thread()->schedule_in_progress() + assert_kdb(Sched_context::rq.current().schedule_in_progress || current_thread()->state() & (Thread_ready_mask | Thread_drq_wait | Thread_waiting | Thread_ipc_transfer)); } @@ -735,78 +737,80 @@ Thread::check_sys_ipc(unsigned flags, Thread **partner, Thread **sender, PUBLIC static unsigned -Thread::handle_migration_helper(Drq *, Context *, void *p) +Thread::handle_migration_helper(Drq *rq, Context *, void *p) { - Migration_helper_info const *inf = (Migration_helper_info const *)p; - return inf->victim->migration_helper(&inf->inf); + Migration *inf = reinterpret_cast(p); + Thread *v = static_cast(context_of(rq)); + unsigned target_cpu = access_once(&inf->cpu); + v->migrate_away(inf, false); + v->migrate_to(target_cpu); + return Drq::Need_resched | Drq::No_answer; } - -PRIVATE -void -Thread::do_migration() +PRIVATE inline +Thread::Migration * +Thread::start_migration() { assert_kdb(cpu_lock.test()); - assert_kdb(current_cpu() == cpu(true)); + Migration *m = _migration; - Migration_helper_info inf; + assert (!((Mword)m & 0x3)); // ensure alignment + if (!m || !mp_cas(&_migration, m, (Migration*)0)) + return reinterpret_cast(0x2); // bit one == 0 --> no need to reschedule + + if (m->cpu == cpu()) { - Lock_guard - g(&_migration_rq.affinity_lock); - inf.inf = _migration_rq.inf; - _migration_rq.pending = false; - _migration_rq.in_progress = true; + set_sched_params(m->sp); + Mem::mp_mb(); + write_now(&m->in_progress, true); + return reinterpret_cast(0x1); // bit one == 1 --> need to reschedule } - unsigned on_cpu = cpu(); - - if (inf.inf.cpu == ~0U) - { - state_add_dirty(Thread_suspended); - set_sched_params(0, 0); - _migration_rq.in_progress = false; - return; - } - - state_del_dirty(Thread_suspended); - - if (inf.inf.cpu == on_cpu) - { - // stay here - set_sched_params(inf.inf.prio, inf.inf.quantum); - _migration_rq.in_progress = false; - return; - } - - // spill FPU state into memory before migration - if (state() & Thread_fpu_owner) - { - if (current() != this) - Fpu::enable(); - - spill_fpu(); - Fpu::set_owner(on_cpu, 0); - Fpu::disable(); - } - - - // if we are in the middle of the scheduler, leave it now - if (schedule_in_progress() == this) - reset_schedule_in_progress(); - - inf.victim = this; - - if (current() == this && Config::Max_num_cpus > 1) - kernel_context_drq(handle_migration_helper, &inf); - else - migration_helper(&inf.inf); + return m; // need to do real migration } +PRIVATE +bool +Thread::do_migration() +{ + Migration *inf = start_migration(); + + if ((Mword)inf & 3) + return (Mword)inf & 1; // already migrated, nothing to do + + spill_fpu_if_owner(); + + if (current() == this) + { + assert_kdb (current_cpu() == cpu()); + kernel_context_drq(handle_migration_helper, inf); + } + else + { + unsigned target_cpu = access_once(&inf->cpu); + migrate_away(inf, false); + migrate_to(target_cpu); + } + return false; // we already are chosen by the scheduler... +} PUBLIC -void +bool Thread::initiate_migration() -{ do_migration(); } +{ + assert (current() != this); + Migration *inf = start_migration(); + + if ((Mword)inf & 3) + return (Mword)inf & 1; + + spill_fpu_if_owner(); + + unsigned target_cpu = access_once(&inf->cpu); + migrate_away(inf, false); + migrate_to(target_cpu); + return false; +} PUBLIC void @@ -814,37 +818,6 @@ Thread::finish_migration() { enqueue_timeout_again(); } -PUBLIC -void -Thread::migrate(Migration_info const &info) -{ - assert_kdb (cpu_lock.test()); - - LOG_TRACE("Thread migration", "mig", this, __thread_migration_log_fmt, - Migration_log *l = tbe->payload(); - l->state = state(); - l->src_cpu = cpu(); - l->target_cpu = info.cpu; - l->user_ip = regs()->ip(); - ); - - { - Lock_guard - g(&_migration_rq.affinity_lock); - _migration_rq.inf = info; - _migration_rq.pending = true; - } - - unsigned cpu = this->cpu(); - - if (current_cpu() == cpu) - { - do_migration(); - return; - } - - migrate_xcpu(cpu); -} //--------------------------------------------------------------------------- @@ -854,35 +827,20 @@ IMPLEMENTATION [fpu && !ux]: #include "fpu_alloc.h" #include "fpu_state.h" -PUBLIC inline NEEDS ["fpu.h"] -void -Thread::spill_fpu() -{ - // If we own the FPU, we should never be getting an "FPU unavailable" trap - assert_kdb (Fpu::owner(cpu()) == this); - assert_kdb (state() & Thread_fpu_owner); - assert_kdb (fpu_state()); - - // Save the FPU state of the previous FPU owner (lazy) if applicable - Fpu::save_state (fpu_state()); - state_del_dirty (Thread_fpu_owner); -} - /* * Handle FPU trap for this context. Assumes disabled interrupts */ -PUBLIC inline NEEDS [Thread::spill_fpu, "fpu_alloc.h","fpu_state.h"] +PUBLIC inline NEEDS ["fpu_alloc.h","fpu_state.h"] int Thread::switchin_fpu(bool alloc_new_fpu = true) { - unsigned cpu = this->cpu(true); - if (state() & Thread_vcpu_fpu_disabled) return 0; + Fpu &f = Fpu::fpu.current(); // If we own the FPU, we should never be getting an "FPU unavailable" trap - assert_kdb (Fpu::owner(cpu) != this); + assert_kdb (f.owner() != this); // Allocate FPU state slab if we didn't already have one if (!fpu_state()->state_buffer() @@ -892,17 +850,17 @@ Thread::switchin_fpu(bool alloc_new_fpu = true) return 0; // Enable the FPU before accessing it, otherwise recursive trap - Fpu::enable(); + f.enable(); // Save the FPU state of the previous FPU owner (lazy) if applicable - if (Fpu::owner(cpu)) - nonull_static_cast(Fpu::owner(cpu))->spill_fpu(); + if (f.owner()) + nonull_static_cast(f.owner())->spill_fpu(); // Become FPU owner and restore own FPU state - Fpu::restore_state(fpu_state()); + f.restore_state(fpu_state()); state_add_dirty(Thread_fpu_owner); - Fpu::set_owner(cpu, this); + f.set_owner(this); return 1; } @@ -910,8 +868,7 @@ PUBLIC inline NEEDS["fpu.h", "fpu_alloc.h"] void Thread::transfer_fpu(Thread *to) { - unsigned cpu = this->cpu(); - if (cpu != to->cpu()) + if (cpu() != to->cpu()) return; if (to->fpu_state()->state_buffer()) @@ -922,25 +879,27 @@ Thread::transfer_fpu(Thread *to) assert (current() == this || current() == to); - Fpu::disable(); // it will be reanabled in switch_fpu + Fpu &f = Fpu::fpu.current(); - if (EXPECT_FALSE(Fpu::owner(cpu) == to)) + f.disable(); // it will be reanabled in switch_fpu + + if (EXPECT_FALSE(f.owner() == to)) { assert_kdb (to->state() & Thread_fpu_owner); - Fpu::set_owner(cpu, 0); - to->state_del_dirty (Thread_fpu_owner); + f.set_owner(0); + to->state_del_dirty(Thread_fpu_owner); } - else if (Fpu::owner(cpu) == this) + else if (f.owner() == this) { assert_kdb (state() & Thread_fpu_owner); - state_del_dirty (Thread_fpu_owner); + state_del_dirty(Thread_fpu_owner); to->state_add_dirty (Thread_fpu_owner); - Fpu::set_owner(cpu, to); + f.set_owner(to); if (EXPECT_FALSE(current() == to)) - Fpu::enable(); + f.enable(); } } @@ -955,11 +914,6 @@ Thread::switchin_fpu(bool alloc_new_fpu = true) return 0; } -PUBLIC inline -void -Thread::spill_fpu() -{} - //--------------------------------------------------------------------------- IMPLEMENTATION [!fpu || ux]: @@ -997,59 +951,93 @@ IMPLEMENTATION [!mp]: PRIVATE inline -unsigned -Thread::migration_helper(Migration_info const *inf) +void +Thread::migrate_away(Migration *inf, bool /*remote*/) { + assert_kdb (current() != this); + assert_kdb (cpu_lock.test()); + unsigned cpu = inf->cpu; // LOG_MSG_3VAL(this, "MGi ", Mword(current()), (current_cpu() << 16) | cpu(), Context::current_sched()); if (_timeout) _timeout->reset(); - ready_dequeue(); + + auto &rq = Sched_context::rq.current(); + + // if we are in the middle of the scheduler, leave it now + if (rq.schedule_in_progress == this) + rq.schedule_in_progress = 0; + + rq.ready_dequeue(sched()); { // Not sure if this can ever happen - Sched_context *csc = Context::current_sched(); + Sched_context *csc = rq.current_sched(); if (!csc || csc->context() == this) - Context::set_current_sched(current()->sched()); + rq.set_current_sched(current()->sched()); } Sched_context *sc = sched_context(); - sc->set_prio(inf->prio); - sc->set_quantum(inf->quantum); + sc->set(inf->sp); sc->replenish(); set_sched(sc); - if (drq_pending()) - state_add_dirty(Thread_drq_ready); - set_cpu_of(this, cpu); - return Drq::No_answer | Drq::Need_resched; + inf->in_progress = true; + _need_to_finish_migration = true; } PRIVATE inline void -Thread::migrate_xcpu(unsigned cpu) +Thread::migrate_to(unsigned target_cpu) { - (void)cpu; - assert_kdb (false); + if (!Cpu::online(target_cpu)) + { + handle_drq(); + return; + } + + auto &rq = Sched_context::rq.current(); + if (state() & Thread_ready_mask && !in_ready_list()) + rq.ready_enqueue(sched()); + + enqueue_timeout_again(); +} + +PUBLIC +void +Thread::migrate(Migration *info) +{ + assert_kdb (cpu_lock.test()); + + LOG_TRACE("Thread migration", "mig", this, Migration_log, + l->state = state(false); + l->src_cpu = cpu(); + l->target_cpu = info->cpu; + l->user_ip = regs()->ip(); + ); + + _migration = info; + current()->schedule_if(do_migration()); } //---------------------------------------------------------------------------- INTERFACE [debug]: +#include "tb_entry.h" + EXTENSION class Thread { protected: - struct Migration_log + struct Migration_log : public Tb_entry { Mword state; Address user_ip; unsigned src_cpu; unsigned target_cpu; - static unsigned fmt(Tb_entry *, int, char *) - asm ("__thread_migration_log_fmt"); + unsigned print(int, char *) const; }; }; @@ -1059,6 +1047,43 @@ IMPLEMENTATION [mp]: #include "ipi.h" +PUBLIC +void +Thread::migrate(Migration *info) +{ + assert_kdb (cpu_lock.test()); + + LOG_TRACE("Thread migration", "mig", this, Migration_log, + l->state = state(false); + l->src_cpu = cpu(); + l->target_cpu = info->cpu; + l->user_ip = regs()->ip(); + ); + { + Migration *old; + do + old = _migration; + while (!mp_cas(&_migration, old, info)); + // flag old migration to be done / stale + if (old) + old->in_progress = true; + } + + unsigned cpu = this->cpu(); + + if (current_cpu() == cpu || Config::Max_num_cpus == 1) + current()->schedule_if(do_migration()); + else + migrate_xcpu(cpu); + + cpu_lock.clear(); + // FIXME: use monitor & mwait or wfe & sev if available + while (!access_once(&info->in_progress)) + Proc::pause(); + cpu_lock.lock(); + +} + IMPLEMENT void Thread::handle_remote_requests_irq() @@ -1068,21 +1093,20 @@ Thread::handle_remote_requests_irq() Context *const c = current(); Ipi::eoi(Ipi::Request, c->cpu()); //LOG_MSG_3VAL(c, "ipi", c->cpu(), (Mword)c, c->drq_pending()); + + // we might have to migrate the currently running thread, and we cannot do + // this during the processing of the request queue. In this case we get the + // thread in migration_q and do this here. Context *migration_q = 0; - bool resched = _pending_rqq.cpu(c->cpu()).handle_requests(&migration_q); + bool resched = _pending_rqq.current().handle_requests(&migration_q); resched |= Rcu::do_pending_work(c->cpu()); if (migration_q) - static_cast(migration_q)->do_migration(); + resched |= static_cast(migration_q)->do_migration(); - if ((resched || c->handle_drq()) && !c->schedule_in_progress()) - { - //LOG_MSG_3VAL(c, "ipis", 0, 0, 0); - // printf("CPU[%2u]: RQ IPI sched %p\n", current_cpu(), current()); - c->schedule(); - } - // printf("CPU[%2u]: < RQ IPI (current=%p)\n", current_cpu(), current()); + if ((c->handle_drq() || resched) && !Sched_context::rq.current().schedule_in_progress) + c->schedule(); } IMPLEMENT @@ -1096,104 +1120,148 @@ Thread::handle_global_remote_requests_irq() } PRIVATE inline -unsigned -Thread::migration_helper(Migration_info const *inf) +void +Thread::migrate_away(Migration *inf, bool remote) { - // LOG_MSG_3VAL(this, "MGi ", Mword(current()), (current_cpu() << 16) | cpu(), 0); - assert_kdb (cpu() == current_cpu()); + assert_kdb (check_for_current_cpu()); assert_kdb (current() != this); assert_kdb (cpu_lock.test()); if (_timeout) _timeout->reset(); - ready_dequeue(); + //printf("[%u] %lx: m %lx %u -> %u\n", current_cpu(), current_thread()->dbg_id(), this->dbg_id(), cpu(), inf->cpu); { + Sched_context::Ready_queue &rq = Sched_context::rq.cpu(cpu()); + + // if we are in the middle of the scheduler, leave it now + if (rq.schedule_in_progress == this) + rq.schedule_in_progress = 0; + + rq.ready_dequeue(sched()); + // Not sure if this can ever happen - Sched_context *csc = Context::current_sched(); - if (!csc || csc->context() == this) - Context::set_current_sched(current()->sched()); + Sched_context *csc = rq.current_sched(); + if (!remote && (!csc || csc->context() == this)) + rq.set_current_sched(current()->sched()); } - unsigned cpu = inf->cpu; + unsigned target_cpu = inf->cpu; { - Queue &q = _pending_rqq.cpu(current_cpu()); + Queue &q = _pending_rqq.cpu(cpu()); // The queue lock of the current CPU protects the cpu number in // the thread - Lock_guard g(q.q_lock()); + auto g = !remote + ? lock_guard(q.q_lock()) + : Lock_guard::type>(); + + assert_kdb (q.q_lock()->test()); // potentailly dequeue from our local queue if (_pending_rq.queued()) - check_kdb (q.dequeue(&_pending_rq, Queue_item::Ok)); + check_kdb (q.dequeue(&_pending_rq, Queue_item::Ok)); Sched_context *sc = sched_context(); - sc->set_prio(inf->prio); - sc->set_quantum(inf->quantum); + sc->set(inf->sp); sc->replenish(); set_sched(sc); - if (drq_pending()) - state_add_dirty(Thread_drq_ready); - Mem::mp_wmb(); assert_kdb (!in_ready_list()); + assert_kdb (!_pending_rq.queued()); - set_cpu_of(this, cpu); - // now we are migrated away fom current_cpu + set_cpu_of(this, target_cpu); + Mem::mp_mb(); + write_now(&inf->in_progress, true); + _need_to_finish_migration = true; } +} - bool ipi = true; +PRIVATE inline +void +Thread::migrate_to(unsigned target_cpu) +{ + bool ipi = false; { - Queue &q = _pending_rqq.cpu(cpu); - Lock_guard g(q.q_lock()); + Queue &q = _pending_rqq.cpu(target_cpu); + auto g = lock_guard(q.q_lock()); + + if (access_once(&this->_cpu) == target_cpu + && EXPECT_FALSE(!Cpu::online(target_cpu))) + { + handle_drq(); + return; + } // migrated meanwhile - if (this->cpu() != cpu || _pending_rq.queued()) - return Drq::No_answer | Drq::Need_resched; + if (access_once(&this->_cpu) != target_cpu || _pending_rq.queued()) + return; - if (q.first()) - ipi = false; + if (!_pending_rq.queued()) + { + if (!q.first()) + ipi = true; - q.enqueue(&_pending_rq); + q.enqueue(&_pending_rq); + } + else + assert_kdb (_pending_rq.queue() == &q); } if (ipi) { //LOG_MSG_3VAL(this, "sipi", current_cpu(), cpu(), (Mword)current()); - Ipi::send(Ipi::Request, current_cpu(), cpu); + Ipi::send(Ipi::Request, current_cpu(), target_cpu); } - - return Drq::No_answer | Drq::Need_resched; } PRIVATE inline void Thread::migrate_xcpu(unsigned cpu) { - bool ipi = true; + bool ipi = false; { Queue &q = Context::_pending_rqq.cpu(cpu); - Lock_guard g(q.q_lock()); + auto g = lock_guard(q.q_lock()); // already migrated - if (cpu != this->cpu()) - return; + if (cpu != access_once(&this->_cpu)) + return; - if (q.first()) - ipi = false; + // now we are shure that this thread stays on 'cpu' because + // we have the rqq lock of 'cpu' + if (!Cpu::online(cpu)) + { + Migration *inf = start_migration(); + + if ((Mword)inf & 3) + return; // all done, nothing to do + + unsigned target_cpu = access_once(&inf->cpu); + migrate_away(inf, true); + g.reset(); + migrate_to(target_cpu); + return; + // FIXME: Wie lange dauert es ready dequeue mit WFQ zu machen? + // wird unter spinlock gemacht !!!! + } if (!_pending_rq.queued()) - q.enqueue(&_pending_rq); - else - ipi = false; + { + if (!q.first()) + ipi = true; + + q.enqueue(&_pending_rq); + } } if (ipi) Ipi::send(Ipi::Request, current_cpu(), cpu); + return; } //---------------------------------------------------------------------------- @@ -1201,10 +1269,9 @@ IMPLEMENTATION [debug]: IMPLEMENT unsigned -Thread::Migration_log::fmt(Tb_entry *e, int maxlen, char *buf) +Thread::Migration_log::print(int maxlen, char *buf) const { - Migration_log *l = e->payload(); return snprintf(buf, maxlen, "migrate from %u to %u (state=%lx user ip=%lx)", - l->src_cpu, l->target_cpu, l->state, l->user_ip); + src_cpu, target_cpu, state, user_ip); } diff --git a/kernel/fiasco/src/kern/thread_lock.cpp b/kernel/fiasco/src/kern/thread_lock.cpp index a1f80e52..565be315 100644 --- a/kernel/fiasco/src/kern/thread_lock.cpp +++ b/kernel/fiasco/src/kern/thread_lock.cpp @@ -96,7 +96,7 @@ PUBLIC Thread_lock::Status Thread_lock::test_and_set() { - Lock_guard guard (&cpu_lock); + auto guard = lock_guard(cpu_lock); return test_and_set_dirty(); } @@ -163,7 +163,7 @@ Thread_lock::clear() { Switch_hint hint = _switch_hint; // Save hint before unlocking - Lock_guard guard (&cpu_lock); + auto guard = lock_guard(cpu_lock); // Passing on the thread lock implies both passing _switch_lock // and setting context()'s donatee to the new owner. This must be @@ -198,7 +198,7 @@ Thread_lock::clear() // Switch to lockee's execution context and timeslice if its priority // is higher than the current priority - if (context()->sched()->deblock(current_cpu(), current()->sched(), true)) + if (Sched_context::rq.current().deblock(context()->sched(), current()->sched(), true)) current()->switch_to_locked(context()); } @@ -248,13 +248,13 @@ Thread_lock::clear_dirty() // Switch to lockee's execution context if the switch hint says so if (hint == SWITCH_ACTIVATE_LOCKEE) { - check(!current()->switch_exec_locked (context(), Context::Not_Helping)); + check(!current()->switch_exec_locked(context(), Context::Not_Helping)); return; } // Switch to lockee's execution context and timeslice if its priority // is higher than the current priority - if (context()->sched()->deblock(current_cpu(), current()->sched(), true)) + if (Sched_context::rq.current().deblock(context()->sched(), current()->sched(), true)) current()->switch_to_locked(context()); } diff --git a/kernel/fiasco/src/kern/thread_object.cpp b/kernel/fiasco/src/kern/thread_object.cpp index 98eef88f..05314efd 100644 --- a/kernel/fiasco/src/kern/thread_object.cpp +++ b/kernel/fiasco/src/kern/thread_object.cpp @@ -89,8 +89,7 @@ Thread_object::operator delete(void *_t) Ram_quota * const q = t->_quota; Kmem_alloc::allocator()->q_unaligned_free(q, Thread::Size, t); - LOG_TRACE("Kobject delete", "del", current(), __fmt_kobj_destroy, - Log_destroy *l = tbe->payload(); + LOG_TRACE("Kobject delete", "del", current(), Log_destroy, l->id = t->dbg_id(); l->obj = t; l->type = "Thread"; @@ -196,28 +195,32 @@ Thread_object::sys_vcpu_resume(L4_msg_tag const &tag, Utcb *utcb) L4_snd_item_iter snd_items(utcb, tag.words()); int items = tag.items(); - for (; items && snd_items.more(); --items) - { - if (EXPECT_FALSE(!snd_items.next())) - break; + if (vcpu_user_space()) + for (; items && snd_items.more(); --items) + { + if (EXPECT_FALSE(!snd_items.next())) + break; - // XXX: need to take existance lock for map - cpu_lock.clear(); + Lock_guard guard; + if (!guard.check_and_lock(&static_cast(vcpu_user_space())->existence_lock)) + return commit_result(-L4_err::ENoent); - L4_snd_item_iter::Item const *const item = snd_items.get(); - L4_fpage sfp(item->d); + cpu_lock.clear(); - Reap_list rl; - L4_error err = fpage_map(space(), sfp, - vcpu_user_space(), L4_fpage::all_spaces(), - item->b, &rl); - rl.del(); + L4_snd_item_iter::Item const *const item = snd_items.get(); + L4_fpage sfp(item->d); - cpu_lock.lock(); + Reap_list rl; + L4_error err = fpage_map(space(), sfp, + vcpu_user_space(), L4_fpage::all_spaces(), + item->b, &rl); + rl.del(); - if (EXPECT_FALSE(!err.ok())) - return commit_error(utcb, err); - } + cpu_lock.lock(); + + if (EXPECT_FALSE(!err.ok())) + return commit_error(utcb, err); + } if ((vcpu->_saved_state & Vcpu_state::F_irqs) && (vcpu->sticky_flags & Vcpu_state::Sf_irq_pending)) @@ -238,12 +241,13 @@ Thread_object::sys_vcpu_resume(L4_msg_tag const &tag, Utcb *utcb) // tried to resume to user mode, so an IRQ enters from user mode if (vcpu->_saved_state & Vcpu_state::F_user_mode) - sp = vcpu->_entry_sp; + sp = vcpu->_entry_sp; else - sp = vcpu->_ts.sp(); + sp = vcpu->_ts.sp(); - LOG_TRACE("VCPU events", "vcpu", this, __context_vcpu_log_fmt, - Vcpu_log *l = tbe->payload(); + arch_load_vcpu_kern_state(vcpu, true); + + LOG_TRACE("VCPU events", "vcpu", this, Vcpu_log, l->type = 4; l->state = vcpu->state; l->ip = vcpu->_entry_ip; @@ -262,7 +266,7 @@ Thread_object::sys_vcpu_resume(L4_msg_tag const &tag, Utcb *utcb) if (vcpu->state & Vcpu_state::F_user_mode) { if (!vcpu_user_space()) - return commit_result(-L4_err::EInval); + return commit_result(-L4_err::ENoent); user_mode = true; @@ -275,10 +279,11 @@ Thread_object::sys_vcpu_resume(L4_msg_tag const &tag, Utcb *utcb) state_del_dirty(Thread_vcpu_fpu_disabled); target_space = static_cast(vcpu_user_space()); + + arch_load_vcpu_user_state(vcpu, true); } - LOG_TRACE("VCPU events", "vcpu", this, __context_vcpu_log_fmt, - Vcpu_log *l = tbe->payload(); + LOG_TRACE("VCPU events", "vcpu", this, Vcpu_log, l->type = 0; l->state = vcpu->state; l->ip = vcpu->_ts.ip(); @@ -483,6 +488,8 @@ Thread_object::sys_vcpu_control(unsigned char, L4_msg_tag const &tag, add_state |= Thread_vcpu_enabled; _vcpu_state.set(vcpu, vcpu_m->kern_addr(vcpu)); + + arch_update_vcpu_state(_vcpu_state.access()); } else return commit_result(-L4_err::EInval); @@ -564,8 +571,7 @@ Thread_object::ex_regs(Utcb *utcb) Mword flags; Mword ops = utcb->values[0]; - LOG_TRACE("Ex-regs", "exr", current(), __fmt_thread_exregs, - Log_thread_exregs *l = tbe->payload(); + LOG_TRACE("Ex-regs", "exr", current(), Log_thread_exregs, l->id = dbg_id(); l->ip = ip; l->sp = sp; l->op = ops;); @@ -621,8 +627,7 @@ Thread_object::sys_thread_switch(L4_msg_tag const &/*tag*/, Utcb *utcb) Sched_context * const cs = current_sched(); #endif - if (curr != this - && ((state() & (Thread_ready | Thread_suspended)) == Thread_ready)) + if (curr != this && (state() & Thread_ready_mask)) { curr->switch_exec_schedule_locked (this, Not_Helping); reinterpret_cast(utcb->values)->t = 0; // Assume timeslice was used up @@ -637,7 +642,7 @@ Thread_object::sys_thread_switch(L4_msg_tag const &/*tag*/, Utcb *utcb) cs->owner()->switch_sched(cs->id() ? cs->next() : cs); #endif reinterpret_cast(utcb->values)->t - = timeslice_timeout.cpu(current_cpu())->get_timeout(Timer::system_clock()); + = timeslice_timeout.current()->get_timeout(Timer::system_clock()); curr->schedule(); return commit_result(0, Utcb::Time_val::Words); diff --git a/kernel/fiasco/src/kern/timeout.cpp b/kernel/fiasco/src/kern/timeout.cpp index cacd8dc4..dc9cb8ad 100644 --- a/kernel/fiasco/src/kern/timeout.cpp +++ b/kernel/fiasco/src/kern/timeout.cpp @@ -190,7 +190,7 @@ void Timeout::set(Unsigned64 clock, unsigned cpu) { // XXX uses global kernel lock - Lock_guard guard (&cpu_lock); + auto guard = lock_guard(cpu_lock); assert (!is_set()); @@ -214,7 +214,7 @@ void Timeout::set_again(unsigned cpu) { // XXX uses global kernel lock - Lock_guard guard (&cpu_lock); + auto guard = lock_guard(cpu_lock); assert(! is_set()); if (has_hit()) diff --git a/kernel/fiasco/src/kern/timer_tick.cpp b/kernel/fiasco/src/kern/timer_tick.cpp index 43e8e53f..80c095c0 100644 --- a/kernel/fiasco/src/kern/timer_tick.cpp +++ b/kernel/fiasco/src/kern/timer_tick.cpp @@ -37,16 +37,17 @@ private: // ------------------------------------------------------------------------ INTERFACE [debug]: +#include "tb_entry.h" + EXTENSION class Timer_tick { public: - struct Log + struct Log : public Tb_entry { Irq_base *obj; Address user_ip; + unsigned print(int, char *) const; }; - - static unsigned tt_log_fmt(Tb_entry *, int, char *) asm ("__tt_log_fmt"); }; // ------------------------------------------------------------------------ @@ -108,10 +109,9 @@ IMPLEMENTATION [debug]: IMPLEMENT unsigned -Timer_tick::tt_log_fmt(Tb_entry *e, int maxlen, char *buf) +Timer_tick::Log::print(int maxlen, char *buf) const { - Log *l = e->payload(); - return snprintf(buf, maxlen, "u-ip=0x%lx", l->user_ip); + return snprintf(buf, maxlen, "u-ip=0x%lx", user_ip); } PUBLIC inline NEEDS["logdefs.h"] @@ -119,8 +119,7 @@ void Timer_tick::log_timer() { Context *c = current(); - LOG_TRACE("Timer IRQs (kernel scheduling)", "timer", c, __tt_log_fmt, - Log *l = tbe->payload(); + LOG_TRACE("Timer IRQs (kernel scheduling)", "timer", c, Log, l->user_ip = c->regs()->ip(); l->obj = this; ); diff --git a/kernel/fiasco/src/kern/timeslice_timeout.cpp b/kernel/fiasco/src/kern/timeslice_timeout.cpp index c3d412e7..9b22e6ed 100644 --- a/kernel/fiasco/src/kern/timeslice_timeout.cpp +++ b/kernel/fiasco/src/kern/timeslice_timeout.cpp @@ -33,8 +33,8 @@ PRIVATE bool Timeslice_timeout::expired() { - unsigned cpu = current_cpu(); - Sched_context *sched = Sched_context::rq(cpu).current_sched(); + Sched_context::Ready_queue &rq = Sched_context::rq.current(); + Sched_context *sched = rq.current_sched(); if (sched) { @@ -45,8 +45,8 @@ Timeslice_timeout::expired() assert (owner->sched() == sched); #endif sched->replenish(); - sched->requeue(cpu); - sched->invalidate_sched(cpu); + rq.requeue(sched); + rq.invalidate_sched(); // owner->switch_sched(sched); } diff --git a/kernel/fiasco/src/kern/ux/Makerules.KERNEL b/kernel/fiasco/src/kern/ux/Makerules.KERNEL index a8e203a0..ad8ef4e5 100644 --- a/kernel/fiasco/src/kern/ux/Makerules.KERNEL +++ b/kernel/fiasco/src/kern/ux/Makerules.KERNEL @@ -29,8 +29,14 @@ sys_call_page-asm.o: $(TCBOFFSET) $(KERNEL): kernel.ux.lds $(OBJ_KERNEL) $(MINILIBC) $(LIBK) $(KERNEL_EXTRA_LIBS) $(ABI) $(JABI) $(DRIVERS) $(CXXLIB) $(LINK_MESSAGE) $(VERBOSE)$(CXX) -m32 -Wl,-T$< -static -o $@ -Wl,--whole-archive $(MINILIBC) -Wl,--no-whole-archive $(KERNEL_UNRES_SYMS) $(filter-out $<,$+) -lutil $(WRAP_SYMBOLS) - chmod 755 $@ - ln -sf $@ fiasco + $(VERBOSE)chmod 755 $@ + @$(ECHO) " ==> Generating fiasco" + $(VERBOSE)ln -sf $@ fiasco + $(VERBOSE)preinit_array_start=$$(nm $(KERNEL) | grep __preinit_array_start | cut -d' ' -f1); \ + preinit_array_end=$$(nm $(KERNEL) | grep __preinit_array_end | cut -d' ' -f1); \ + if [ "$$preinit_array_start" != "$$preinit_array_end" ]; then \ + echo "preinit_array content appeared, check linker symbols"; \ + fi irq0.o: irq0.c $(COMP_MESSAGE) diff --git a/kernel/fiasco/src/kern/ux/context-ux.cpp b/kernel/fiasco/src/kern/ux/context-ux.cpp index 32df2003..9235c30f 100644 --- a/kernel/fiasco/src/kern/ux/context-ux.cpp +++ b/kernel/fiasco/src/kern/ux/context-ux.cpp @@ -20,6 +20,11 @@ void Context::switch_fpu (Context *) {} +PUBLIC inline +void +Context::spill_fpu() +{} + PUBLIC inline bool Context::is_native() diff --git a/kernel/fiasco/src/kern/ux/cpu-ux.cpp b/kernel/fiasco/src/kern/ux/cpu-ux.cpp index dc3bb9e8..b8d90265 100644 --- a/kernel/fiasco/src/kern/ux/cpu-ux.cpp +++ b/kernel/fiasco/src/kern/ux/cpu-ux.cpp @@ -101,7 +101,7 @@ Cpu::print() const div32(frequency(), 1000000)); } -IMPLEMENT inline +PUBLIC inline unsigned Cpu::phys_id() const { return _tid; } diff --git a/kernel/fiasco/src/kern/ux/hostproc.cpp b/kernel/fiasco/src/kern/ux/hostproc.cpp index 2d4befaf..f32288c7 100644 --- a/kernel/fiasco/src/kern/ux/hostproc.cpp +++ b/kernel/fiasco/src/kern/ux/hostproc.cpp @@ -83,7 +83,7 @@ PUBLIC static unsigned Hostproc::create() { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); static unsigned long esp; static Mword _stack[256]; diff --git a/kernel/fiasco/src/kern/ux/mem_space-ux.cpp b/kernel/fiasco/src/kern/ux/mem_space-ux.cpp index 55d34bfb..6f4cccaf 100644 --- a/kernel/fiasco/src/kern/ux/mem_space-ux.cpp +++ b/kernel/fiasco/src/kern/ux/mem_space-ux.cpp @@ -85,7 +85,7 @@ IMPLEMENT inline NEEDS [, , "boot_info.h", void Mem_space::page_map(Address phys, Address virt, Address size, unsigned attr) { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); Mword *trampoline = (Mword *)Mem_layout::kernel_trampoline_page; @@ -111,7 +111,7 @@ IMPLEMENT inline NEEDS [, "cpu_lock.h", "lock_guard.h", void Mem_space::page_unmap(Address virt, Address size) { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); Trampoline::syscall(pid(), __NR_munmap, virt, size); } @@ -121,7 +121,7 @@ IMPLEMENT inline NEEDS [, "cpu_lock.h", "lock_guard.h", void Mem_space::page_protect(Address virt, Address size, unsigned attr) { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); Trampoline::syscall(pid(), __NR_mprotect, virt, size, PROT_READ | (attr & Page_writable ? PROT_WRITE : 0)); @@ -191,7 +191,7 @@ Mem_space::peek_user(T const *addr) if (((Address)addr & Config::PAGE_MASK) == (((Address)addr + sizeof (T) - 1) & Config::PAGE_MASK)) { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); value = *user_to_kernel(addr, false); } else @@ -209,7 +209,7 @@ Mem_space::poke_user(T *addr, T value) if (((Address)addr & Config::PAGE_MASK) == (((Address)addr + sizeof (T) - 1) & Config::PAGE_MASK)) { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); *user_to_kernel(addr, true) = value; } else @@ -221,7 +221,7 @@ template< typename T > void Mem_space::copy_from_user(T *kdst, T const *usrc, size_t n) { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); char *ptr = (char *)usrc; char *dst = (char *)kdst; @@ -244,7 +244,7 @@ template< typename T > void Mem_space::copy_to_user(T *udst, T const *ksrc, size_t n) { - Lock_guard guard(&cpu_lock); + auto guard = lock_guard(cpu_lock); char *ptr = (char *)udst; char *src = (char *)ksrc; diff --git a/kernel/fiasco/src/kern/ux/task-ux.cpp b/kernel/fiasco/src/kern/ux/task-ux.cpp index 0ca13129..b78d3503 100644 --- a/kernel/fiasco/src/kern/ux/task-ux.cpp +++ b/kernel/fiasco/src/kern/ux/task-ux.cpp @@ -90,7 +90,7 @@ Task::~Task() { free_ku_mem(); - Lock_guard guard (&cpu_lock); + auto guard = lock_guard(cpu_lock); pid_t hostpid = pid(); ptrace (PTRACE_KILL, hostpid, NULL, NULL); diff --git a/kernel/fiasco/src/kern/ux/thread-ux.cpp b/kernel/fiasco/src/kern/ux/thread-ux.cpp index cab07f50..05a7b154 100644 --- a/kernel/fiasco/src/kern/ux/thread-ux.cpp +++ b/kernel/fiasco/src/kern/ux/thread-ux.cpp @@ -94,7 +94,7 @@ Thread::call_nested_trap_handler(Trap_state *ts) //static char nested_handler_stack [Config::PAGE_SIZE]; unsigned phys_cpu = Cpu::phys_id_direct(); - unsigned log_cpu = Cpu::p2l(phys_cpu); + unsigned log_cpu = Cpu::cpus.find_cpu(Cpu::By_phys_id(phys_cpu)); if (log_cpu == ~0U) { @@ -148,12 +148,6 @@ Thread::call_nested_trap_handler(Trap_state *ts) return ret == 0 ? 0 : -1; } -PUBLIC inline -void -Thread::spill_fpu() -{} - - // The "FPU not available" trap entry point extern "C" void thread_handle_fputrap (void) { panic ("fpu trap"); } diff --git a/kernel/fiasco/src/kern/ux/usermode.cpp b/kernel/fiasco/src/kern/ux/usermode.cpp index 30d87f6f..9c57df96 100644 --- a/kernel/fiasco/src/kern/ux/usermode.cpp +++ b/kernel/fiasco/src/kern/ux/usermode.cpp @@ -609,7 +609,7 @@ Usermode::emu_handler (int, siginfo_t *, void *ctx) struct ucontext *context = reinterpret_cast(ctx); unsigned int trap = context->uc_mcontext.gregs[REG_TRAPNO]; - unsigned _cpu = Cpu::p2l(Cpu::phys_id_direct()); + unsigned _cpu = Cpu::cpus.find_cpu(Cpu::By_phys_id(Cpu::phys_id_direct())); if (trap == 0xd) /* General protection fault */ { @@ -664,7 +664,7 @@ Usermode::int_handler (int, siginfo_t *, void *ctx) Pic::eat (irq); - kernel_entry (Cpu::p2l(Cpu::phys_id_direct()), + kernel_entry (Cpu::cpus.find_cpu(Cpu::By_phys_id(Cpu::phys_id_direct())), context, gate, context->uc_mcontext.gregs[REG_SS], /* XSS */ @@ -696,7 +696,7 @@ Usermode::jdb_handler (int sig, siginfo_t *, void *ctx) signal (SIGSEGV, SIG_IGN); // Cancel signal set_signal (SIGSEGV); // Reinstall handler - kernel_entry (Cpu::p2l(Cpu::phys_id_direct()), + kernel_entry (Cpu::cpus.find_cpu(Cpu::By_phys_id(Cpu::phys_id_direct())), context, sig == SIGTRAP ? 3 : 1, context->uc_mcontext.gregs[REG_SS], /* XSS */ context->uc_mcontext.gregs[REG_ESP], /* ESP */ diff --git a/kernel/fiasco/src/kern/vcpu.cpp b/kernel/fiasco/src/kern/vcpu.cpp index 8ceffc20..72afa785 100644 --- a/kernel/fiasco/src/kern/vcpu.cpp +++ b/kernel/fiasco/src/kern/vcpu.cpp @@ -35,5 +35,7 @@ public: Mword _entry_sp; Mword _entry_ip; + + // kernel-internal private state Mword _sp; }; diff --git a/kernel/fiasco/src/kern/vlog.cpp b/kernel/fiasco/src/kern/vlog.cpp index 13b75a66..96c9dbd2 100644 --- a/kernel/fiasco/src/kern/vlog.cpp +++ b/kernel/fiasco/src/kern/vlog.cpp @@ -110,7 +110,8 @@ Vlog::get_input(Mword rights, Syscall_frame *f, Utcb *u) return commit_result(-L4_err::EPerm); char *buffer = reinterpret_cast(&u->values[1]); - long cnt_down = u->values[0] >> 16; + long cnt_down = min(u->values[0] >> 16, + sizeof(u->values) - sizeof(u->values[0])); int i = 0; while (cnt_down && (i = Vkey::get()) != -1) { diff --git a/kernel/fiasco/src/lib/libk/atomic.cpp b/kernel/fiasco/src/lib/libk/atomic.cpp index 1f4681ce..ff4d5b10 100644 --- a/kernel/fiasco/src/lib/libk/atomic.cpp +++ b/kernel/fiasco/src/lib/libk/atomic.cpp @@ -179,7 +179,7 @@ tas(Mword *l) } //--------------------------------------------------------------------------- -IMPLEMENTATION[(ppc32 && !mp) || (arm && !armv6plus)]: +IMPLEMENTATION[(ppc32 && !mp) || (sparc && !mp) || (arm && !armv6plus)]: #include "processor.h" diff --git a/kernel/fiasco/src/lib/libk/bitfield b/kernel/fiasco/src/lib/libk/bitfield new file mode 100644 index 00000000..8b637e40 --- /dev/null +++ b/kernel/fiasco/src/lib/libk/bitfield @@ -0,0 +1,248 @@ +// vi: ft=cpp +/* + * (c) 2012 Alexander Warg , + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + +#pragma once + +#include + +/** \brief Our C++ library. */ +namespace cxx { + +/** \brief Definition for a member (part) of a bit field. + * + * \param T the underlying type of the bit field. + * \param LSB the least significant bit of our bits. + * \param MSB the mos significant bit if our bits. + */ +template +class Bitfield +{ +private: + static_assert(MSB >= LSB, "boundary mismatch in bit-field definition"); + static_assert(MSB < sizeof(T) * 8, "MSB outside of bit-field type"); + static_assert(LSB < sizeof(T) * 8, "LSB outside of bit-field type"); + + /** \brief Get the best unsigned type for \a bits. + * \param BITS number of bits to cover + */ + template struct Best_type + { + template< typename TY > struct Cmp { enum { value = (BITS <= sizeof(TY)*8) }; }; + typedef cxx::type_list< + unsigned char, + unsigned short, + unsigned int, + unsigned long, + unsigned long long + > Unsigned_types; + typedef typename cxx::find_type::type Type; + }; + +public: + enum + { + Bits = MSB + 1 - LSB, ///< Number of bits + Lsb = LSB, ///< index of the LSB + Msb = MSB, ///< index of the MSB + }; + + enum Masks : T + { + /** Mask value to get #Bits bits. */ + Low_mask = ((T)~0ULL) >> (sizeof(T)*8 - Bits), + /** Mask value to the bits out of a \a T. */ + Mask = Low_mask << Lsb, + }; + + /** \brief Type to hold at least #Bits bits. + * + * This type can handle all values that can be stored in this part of the bit + * field. + */ + typedef typename Best_type::Type Bits_type; + + /** \brief Type to hold at least #Bits + #Lsb bits. + * + * This type can handle all values that can be stored in this part of the bit + * field when they are at the target location (#Lsb bits shifted to the + * left). + */ + typedef typename Best_type::Type Shift_type; + +private: + static_assert(sizeof(Bits_type)*8 >= Bits, "error finding the type to store the bits"); + static_assert(sizeof(Shift_type)*8 >= Bits + Lsb, "error finding the type to keep the shifted bits"); + static_assert(sizeof(Bits_type) <= sizeof(T), "size mismatch for Bits_type"); + static_assert(sizeof(Shift_type) <= sizeof(T), "size mismatch for Shift_type"); + static_assert(sizeof(Bits_type) <= sizeof(Shift_type), "size mismacht for Shift_type and Bits_type"); + +public: + /** \brief Get the bits out of \a val. + * \param val the raw value of the whole bit field. + * \return the bits form #Lsb to #Msb shifted to the right. + */ + static Bits_type get(Shift_type val) + { return (val >> Lsb) & Low_mask; } + + /** \brief Get the bits in place out of \val. + * \param val the raw value of the whole bit field. + * \return the bits from #Lsb to #Msb (unshifted). + * + * This means other bits are masked out, however the result is not shifted to + * the right, + */ + static T get_unshifted(Shift_type val) + { return val & Mask; } + + /** \brief Set the bits corresponding to \a val. + * \param dest the current value of the whole bit field. + * \param val the value to set into the bits. + * \return the new value of the whole bit field. + * \pre \a val must contain not more than bits than #Bits. + * \note This function does not mask \a val to the right number of bits. + */ + static T set_dirty(T dest, Shift_type val) + { + //assert (!(val & ~Low_mask)); + return (dest & ~Mask) | (val << Lsb); + } + + /** \brief Set the bits corresponding to \a val. + * \param dest the current value of the whole bit field. + * \param val the value shifted #Lsb bits to the left that shall be set into + * the bits. + * \return the new value of the whole bit field. + * \pre \a val must contain not more than bits than #Bits shifted #Lsb bits + * to the left. + * \note This function does not mask \a val to the right number of bits. + */ + static T set_unshifted_dirty(T dest, Shift_type val) + { + //assert (!(val & ~Mask)); + return (dest & ~Mask) | val; + } + + /** \brief Set the bits corresponding to \a val. + * \param dest the current value of the whole bit field. + * \param val the value to set into the bits. + * \return the new value of the whole bit field. + */ + static T set(T dest, Bits_type val) + { return set_dirty(dest, val & Low_mask); } + + /** \brief Set the bits corresponding to \a val. + * \param dest the current value of the whole bit field. + * \param val the value shifted #Lsb bits to the left that shall be set into + * the bits. + * \return the new value of the whole bit field. + */ + static T set_unshifted(T dest, Shift_type val) + { return set_unshifted_dirty(dest, val & Mask); } + + /** \brief Get the shifted bits for \a val. + * \param val the value to set into the bits. + * \return the raw bit field value containing. + * \pre \a val must contain not more than bits than #Bits. + * \note This function does not mask \a val to the right number of bits. + */ + static T val_dirty(Shift_type val) { return val << Lsb; } + + /** \brief Get the shifted bits for \a val. + * \param val the value to set into the bits. + * \return the raw bit field value containing. + */ + static T val(Bits_type val) { return val_dirty(val & Low_mask); } + + /** \brief Get the shifted bits for \a val. + * \param val the value shifted #Lsb bits to the left that shall be set into + * the bits. + * \return the raw bit field value containing. + */ + static T val_unshifted(Shift_type val) { return val & Mask; } + + /** Internal helper type */ + template< typename TT > + class Value_base + { + private: + TT v; + + public: + Value_base(TT t) : v(t) {} + Bits_type get() const { return Bitfield::get(v); } + T get_unshifted() const { return Bitfield::get_unshifted(v); } + + void set(Bits_type val) { v = Bitfield::set(v, val); } + void set_dirty(Bits_type val) { v = Bitfield::set_dirty(v, val); } + void set_unshifted(Shift_type val) { v = Bitfield::set_unshifted(v, val); } + void set_unshifted_dirty(Shift_type val) { v = Bitfield::set_unshifted_dirty(v, val); } + }; + + /** Internal helper type */ + template< typename TT > + class Value : public Value_base + { + public: + Value(TT t) : Value_base(t) {} + operator Bits_type () const { return this->get(); } + Value &operator = (Bits_type val) { this->set(val); return *this; } + }; + + /** Internal helper type */ + template< typename TT > + class Value_unshifted : public Value_base + { + public: + Value_unshifted(TT t) : Value_base(t) {} + operator Shift_type () const { return this->get_unshifted(); } + Value_unshifted &operator = (Shift_type val) { this->set_unshifted(val); return *this; } + }; + + /** Reference type to access the bits inside a raw bit field. */ + typedef Value Ref; + /** Value type to access the bits inside a raw bit field. */ + typedef Value Val; + + /** Reference type to access the bits inside a raw bit field (in place). */ + typedef Value_unshifted Ref_unshifted; + /** Value type to access the bits inside a raw bit field (in place). */ + typedef Value_unshifted Val_unshifted; +}; + +#define CXX_BITFIELD_MEMBER(LSB, MSB, name, data_member) \ + /** @{ */ \ + /** \brief Type to access the \a name bits (LSB to MSB) of \a data_member. */ \ + typedef cxx::Bitfield name ## _bfm_t; \ + /** \brief Get the \a name bits (LSB to MSB) of \a data_member. */ \ + name ## _bfm_t::Val name() const { return data_member; } \ + /** \brief Get a reference to the \a name bits (LSB to MSB) of \a data_member. */ \ + name ## _bfm_t::Ref name() { return data_member; } \ + /** @} */ + +#define CXX_BITFIELD_MEMBER_UNSHIFTED(LSB, MSB, name, data_member) \ + /** @{ */ \ + /** \brief Type to access the \a name bits (LSB to MSB) of \a data_member. */ \ + typedef cxx::Bitfield name ## _bfm_t; \ + /** \brief Get the \a name bits (LSB to MSB) of \a data_member. */ \ + name ## _bfm_t::Val_unshifted name() const { return data_member; } \ + /** \brief Get a reference to the \a name bits (LSB to MSB) of \a data_member. */ \ + name ## _bfm_t::Ref_unshifted name() { return data_member; } \ + /** @} */ + +} diff --git a/kernel/fiasco/src/lib/libk/bitmap.cpp b/kernel/fiasco/src/lib/libk/bitmap.cpp index b10fca77..e92c6119 100644 --- a/kernel/fiasco/src/lib/libk/bitmap.cpp +++ b/kernel/fiasco/src/lib/libk/bitmap.cpp @@ -75,6 +75,8 @@ protected: }; Bitmap_base() {} + Bitmap_base(Bitmap_base const &) = delete; + Bitmap_base &operator = (Bitmap_base const &) = delete; private: unsigned long *_bits() @@ -137,6 +139,10 @@ protected: Bpl = sizeof(unsigned long) * 8, }; unsigned long _bits[1]; + + Bitmap_base() {} + Bitmap_base(Bitmap_base const &) = delete; + Bitmap_base &operator = (Bitmap_base const &) = delete; }; template @@ -157,6 +163,13 @@ public: return true; } + Bitmap() {} + Bitmap(Bitmap const &o) + { __builtin_memcpy(_bits, o._bits, sizeof(_bits)); } + + Bitmap &operator = (Bitmap const &o) + { __builtin_memcpy(_bits, o._bits, sizeof(_bits)); return *this; } + private: enum { Bpl = sizeof(unsigned long) * 8, diff --git a/kernel/fiasco/src/lib/libk/lock_guard.cpp b/kernel/fiasco/src/lib/libk/lock_guard.cpp index 4628e5ab..500f82da 100644 --- a/kernel/fiasco/src/lib/libk/lock_guard.cpp +++ b/kernel/fiasco/src/lib/libk/lock_guard.cpp @@ -38,6 +38,9 @@ class Lock_guard Lock *_lock; typename Policy::Status _state; + + Lock_guard(Lock_guard &) = delete; + Lock_guard &operator = (Lock_guard &) = delete; }; template< typename LOCK> @@ -49,23 +52,49 @@ class Lock_guard_2 IMPLEMENTATION: + PUBLIC template class POLICY> inline Lock_guard::Lock_guard() : _lock(0) -#ifndef NDEBUG - , _state(Lock::Invalid) // silence GCC warning -#endif {} PUBLIC template class POLICY> -inline +inline explicit Lock_guard::Lock_guard(Lock *l) : _lock(l) { _state = Policy::test_and_set(_lock); } +PUBLIC template class POLICY> +inline +Lock_guard::Lock_guard(Lock_guard &&l) + : _lock(l._lock), _state(l._state) +{ + l.release(); +} + +PUBLIC template class POLICY> +inline +Lock_guard +Lock_guard::operator = (Lock_guard &&l) +{ + reset(); + _lock = l._lock; + _state = l._state; + l.release(); +} + + +inline template +Lock_guard lock_guard(LOCK &lock) +{ return Lock_guard(&lock); } + +inline template +Lock_guard lock_guard(LOCK *lock) +{ return Lock_guard(lock); } + PUBLIC template class POLICY> inline void @@ -75,6 +104,16 @@ Lock_guard::lock(Lock *l) _state = Policy::test_and_set(l); } +PUBLIC template class POLICY> +inline +bool +Lock_guard::check_and_lock(Lock *l) +{ + _lock = l; + _state = Policy::test_and_set(l); + return _state != Lock::Invalid; +} + PUBLIC template class POLICY> inline bool @@ -150,8 +189,22 @@ Lock_guard_2::Lock_guard_2(LOCK *l1, LOCK *l2) PUBLIC template inline -bool +void Lock_guard_2::lock(LOCK *l1, LOCK *l2) +{ + _l1 = l1 < l2 ? l1 : l2; + _l2 = l1 < l2 ? l2 : l1; + _state1 = _l1->test_and_set(); + if (_l1 == _l2) + _l2 = 0; + else + _state2 = _l2->test_and_set(); +} + +PUBLIC template +inline +bool +Lock_guard_2::check_and_lock(LOCK *l1, LOCK *l2) { _l1 = l1 < l2 ? l1 : l2; _l2 = l1 < l2 ? l2 : l1; diff --git a/kernel/fiasco/src/lib/libk/poll_timeout_counter.h b/kernel/fiasco/src/lib/libk/poll_timeout_counter.h new file mode 100644 index 00000000..38796fc0 --- /dev/null +++ b/kernel/fiasco/src/lib/libk/poll_timeout_counter.h @@ -0,0 +1,38 @@ +#pragma once + +namespace L4 { + +class Poll_timeout_counter +{ +public: + Poll_timeout_counter(unsigned counter_val) + { + set(counter_val); + } + + void set(unsigned counter_val) + { + _c = counter_val; + } + + bool test(bool expression = true) + { + if (!expression) + return false; + + if (_c) + { + --_c; + return true; + } + + return false; + } + + bool timed_out() const { return _c == 0; } + +private: + unsigned _c; +}; + +} diff --git a/kernel/fiasco/src/lib/libk/slab_cache.cpp b/kernel/fiasco/src/lib/libk/slab_cache.cpp index 065b073d..6be647bc 100644 --- a/kernel/fiasco/src/lib/libk/slab_cache.cpp +++ b/kernel/fiasco/src/lib/libk/slab_cache.cpp @@ -225,7 +225,7 @@ Slab_cache::alloc() // request initialized member from cache void *unused_block = 0; void *ret; { - Lock_guard guard(&lock); + auto guard = lock_guard(lock); Slab *s = get_available_locked(); @@ -296,7 +296,7 @@ Slab_cache::free(void *cache_entry) // return initialized member to cache { Slab *to_free = 0; { - Lock_guard guard(&lock); + auto guard = lock_guard(lock); Slab *s = reinterpret_cast ((reinterpret_cast(cache_entry) & ~(_slab_size - 1)) + _slab_size - sizeof(Slab)); @@ -355,7 +355,7 @@ Slab_cache::reap() // request that cache returns memory to system for (;;) { { - Lock_guard guard(&lock); + auto guard = lock_guard(lock); s = _empty.front(); // nothing to free diff --git a/kernel/fiasco/src/lib/libk/type_list b/kernel/fiasco/src/lib/libk/type_list new file mode 100644 index 00000000..58bed7cd --- /dev/null +++ b/kernel/fiasco/src/lib/libk/type_list @@ -0,0 +1,61 @@ +// vi:ft=cpp +#pragma once + +/* + * (c) 2012 Alexander Warg , + * economic rights: Technische Universität Dresden (Germany) + * + * This file is part of TUD:OS and distributed under the terms of the + * GNU General Public License 2. + * Please see the COPYING-GPL-2 file for details. + * + * As a special exception, you may use this file as part of a free software + * library without restriction. Specifically, if other files instantiate + * templates or use macros or inline functions from this file, or you compile + * this file and link it with other files to produce an executable, this + * file does not by itself cause the resulting executable to be covered by + * the GNU General Public License. This exception does not however + * invalidate any other reasons why the executable file might be covered by + * the GNU General Public License. + */ + + +#include + +namespace cxx { + +template< typename ...T > +struct type_list; + +template<> +struct type_list<> +{ + typedef false_type head; + typedef false_type tail; +}; + +template +struct type_list +{ + typedef HEAD head; + typedef type_list tail; +}; + +template class PREDICATE> +struct find_type; + +template