]> rtime.felk.cvut.cz Git - l4.git/commitdiff
update
authorl4check <l4check@d050ee49-bd90-4346-b210-929a50b99cfc>
Mon, 8 Apr 2013 17:39:36 +0000 (17:39 +0000)
committerl4check <l4check@d050ee49-bd90-4346-b210-929a50b99cfc>
Mon, 8 Apr 2013 17:39:36 +0000 (17:39 +0000)
git-svn-id: http://svn.tudos.org/repos/oc/tudos/trunk@51 d050ee49-bd90-4346-b210-929a50b99cfc

606 files changed:
kernel/fiasco/Makefile
kernel/fiasco/src/Kconfig
kernel/fiasco/src/Makeconf.amd64
kernel/fiasco/src/Makeconf.arm
kernel/fiasco/src/Makeconf.ia32
kernel/fiasco/src/Makefile
kernel/fiasco/src/Makerules.UNITTEST
kernel/fiasco/src/Makerules.global
kernel/fiasco/src/Modules.amd64
kernel/fiasco/src/Modules.arm
kernel/fiasco/src/Modules.generic
kernel/fiasco/src/Modules.ia32
kernel/fiasco/src/Modules.ux
kernel/fiasco/src/abi/kip.cpp
kernel/fiasco/src/abi/l4_buf_desc.cpp
kernel/fiasco/src/abi/l4_fpage.cpp
kernel/fiasco/src/abi/l4_msg_item.cpp
kernel/fiasco/src/abi/l4_types.cpp
kernel/fiasco/src/boot/amd64/Makerules.BOOT.amd64
kernel/fiasco/src/boot/amd64/boot_cpu.cc
kernel/fiasco/src/boot/amd64/boot_paging.h
kernel/fiasco/src/boot/ia32/Makerules.BOOT.ia32
kernel/fiasco/src/boot/ia32/boot_paging.h
kernel/fiasco/src/drivers/arm/mmu-arm.cpp
kernel/fiasco/src/drivers/arm/processor-arm.cpp
kernel/fiasco/src/drivers/arm/sa1100.cpp
kernel/fiasco/src/drivers/io.cpp
kernel/fiasco/src/drivers/mmio_register_block.h [new file with mode: 0644]
kernel/fiasco/src/drivers/ppc32/processor-ppc32.cpp
kernel/fiasco/src/drivers/sparc/processor-sparc.cpp
kernel/fiasco/src/drivers/uart-16550.cpp
kernel/fiasco/src/jdb/arm/jdb-arm.cpp
kernel/fiasco/src/jdb/arm/jdb_extensions.cpp
kernel/fiasco/src/jdb/arm/jdb_kern_info-arm.cpp
kernel/fiasco/src/jdb/arm/jdb_kern_info-bench-arm.cpp
kernel/fiasco/src/jdb/arm/jdb_ptab-arm.cpp
kernel/fiasco/src/jdb/arm/jdb_vm.cpp
kernel/fiasco/src/jdb/ia32/32/jdb_kern_info-bench-ia32-32.cpp
kernel/fiasco/src/jdb/ia32/64/jdb_ptab-amd64.cpp
kernel/fiasco/src/jdb/ia32/jdb-ia32-amd64.cpp
kernel/fiasco/src/jdb/ia32/jdb_bp-ia32-ux.cpp
kernel/fiasco/src/jdb/ia32/jdb_bt-ia32-ux.cpp
kernel/fiasco/src/jdb/ia32/jdb_kern_info-ia32-amd64.cpp
kernel/fiasco/src/jdb/ia32/jdb_kern_info-ia32-ux.cpp
kernel/fiasco/src/jdb/ia32/jdb_trace_set-ia32-ux.cpp
kernel/fiasco/src/jdb/jdb-thread.cpp
kernel/fiasco/src/jdb/jdb.cpp
kernel/fiasco/src/jdb/jdb_dbinfo.cpp
kernel/fiasco/src/jdb/jdb_exit_module.cpp
kernel/fiasco/src/jdb/jdb_idle_stats.cpp
kernel/fiasco/src/jdb/jdb_io_apic.cpp
kernel/fiasco/src/jdb/jdb_ipi.cpp
kernel/fiasco/src/jdb/jdb_kern_info-bench.cpp
kernel/fiasco/src/jdb/jdb_kern_info.cpp
kernel/fiasco/src/jdb/jdb_kobject.cpp
kernel/fiasco/src/jdb/jdb_mapdb.cpp
kernel/fiasco/src/jdb/jdb_module.cpp
kernel/fiasco/src/jdb/jdb_mp_request_sl.cpp
kernel/fiasco/src/jdb/jdb_obj_space.cpp
kernel/fiasco/src/jdb/jdb_prompt_ext.cpp
kernel/fiasco/src/jdb/jdb_ptab-ia32-ux-arm.cpp
kernel/fiasco/src/jdb/jdb_ptab.cpp
kernel/fiasco/src/jdb/jdb_rcupdate.cpp
kernel/fiasco/src/jdb/jdb_table.cpp
kernel/fiasco/src/jdb/jdb_tbuf.cpp
kernel/fiasco/src/jdb/jdb_tbuf_show.cpp
kernel/fiasco/src/jdb/jdb_tcb.cpp
kernel/fiasco/src/jdb/jdb_tetris.cpp
kernel/fiasco/src/jdb/jdb_thread_list.cpp
kernel/fiasco/src/jdb/jdb_timeout.cpp
kernel/fiasco/src/jdb/jdb_trap_state.cpp
kernel/fiasco/src/jdb/jdb_util.cpp
kernel/fiasco/src/jdb/ppc32/jdb-ppc32.cpp
kernel/fiasco/src/jdb/sparc/jdb-sparc.cpp
kernel/fiasco/src/jdb/ux/jdb-ux.cpp
kernel/fiasco/src/jdb/ux/jdb_bp-ux.cpp
kernel/fiasco/src/kern/app_cpu_thread.cpp
kernel/fiasco/src/kern/arm/Makerules.KERNEL
kernel/fiasco/src/kern/arm/asm_entry.h [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bootstrap.cpp
kernel/fiasco/src/kern/arm/bsp/bcm2835/Kconfig [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/bcm2835/Modules [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/bcm2835/bootstrap-arm-bcm2835.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/bcm2835/config-arm-bcm2835.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/bcm2835/kernel_uart-arm-bcm2835.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/bcm2835/mem_layout-arm-bcm2835.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/bcm2835/pic-arm-bcm2835.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/bcm2835/reset-arm-bcm2835.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/bcm2835/timer-arm-bcm2835.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/bcm2835/uart-arm-bcm2835.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/exynos/Kconfig [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/exynos/Modules [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/exynos/bootstrap-arm-exynos.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/exynos/config-arm-exynos.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/exynos/cpu-arm-exynos.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/exynos/ipi-arm-exynos.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/exynos/kernel_thread-arm-exynos.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/exynos/kernel_uart-arm-exynos.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/exynos/mem_layout-arm-exynos.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/exynos/outer_cache-arm-exynos.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/exynos/pic-arm-gic-exynos.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/exynos/platform-arm-exynos.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/exynos/platform_control-arm-exynos.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/exynos/reset-arm-exynos.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/exynos/scu-arm-exynos.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/exynos/smc.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/exynos/thread-arm-exynos.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/exynos/timer-arm-exynos.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/exynos/timer_mct.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/exynos/timer_tick-exynos-mct.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/exynos/uart-arm-exynos.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/exynos/watchdog-arm-exynos.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/imx/Modules
kernel/fiasco/src/kern/arm/bsp/imx/bootstrap-arm-imx.cpp
kernel/fiasco/src/kern/arm/bsp/imx/mem_layout-arm-imx.cpp
kernel/fiasco/src/kern/arm/bsp/imx/pic-arm-imx.cpp
kernel/fiasco/src/kern/arm/bsp/imx/pic-arm-imx51.cpp
kernel/fiasco/src/kern/arm/bsp/imx/platform_control-arm-imx6.cpp
kernel/fiasco/src/kern/arm/bsp/imx/reset-arm-imx.cpp
kernel/fiasco/src/kern/arm/bsp/imx/timer-arm-imx21.cpp
kernel/fiasco/src/kern/arm/bsp/imx/timer-arm-imx_epit.cpp
kernel/fiasco/src/kern/arm/bsp/imx/timer-arm-mptimer-imx6.cpp
kernel/fiasco/src/kern/arm/bsp/imx/timer_imx_epit.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/imx/uart-imx.cpp
kernel/fiasco/src/kern/arm/bsp/integrator/Modules
kernel/fiasco/src/kern/arm/bsp/integrator/bootstrap-arm-integrator.cpp
kernel/fiasco/src/kern/arm/bsp/integrator/mem_layout-arm-integrator.cpp
kernel/fiasco/src/kern/arm/bsp/integrator/pic-arm-integrator.cpp
kernel/fiasco/src/kern/arm/bsp/integrator/reset-arm-integrator.cpp
kernel/fiasco/src/kern/arm/bsp/integrator/timer-arm-integrator.cpp
kernel/fiasco/src/kern/arm/bsp/integrator/uart-arm-integrator.cpp
kernel/fiasco/src/kern/arm/bsp/kirkwood/Modules
kernel/fiasco/src/kern/arm/bsp/kirkwood/bootstrap-arm-kirkwood.cpp
kernel/fiasco/src/kern/arm/bsp/kirkwood/kernel_uart-arm-kirkwood.cpp
kernel/fiasco/src/kern/arm/bsp/kirkwood/mem_layout-arm-kirkwood.cpp
kernel/fiasco/src/kern/arm/bsp/kirkwood/pic-arm-kirkwood.cpp
kernel/fiasco/src/kern/arm/bsp/kirkwood/reset-arm-kirkwood.cpp
kernel/fiasco/src/kern/arm/bsp/kirkwood/timer-arm-kirkwood.cpp
kernel/fiasco/src/kern/arm/bsp/omap/Kconfig [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/omap/Modules [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/omap/bootstrap-arm-omap.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/omap/config-arm-omap.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/omap/kernel_uart-arm-omap.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/omap/mem_layout-arm-omap.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/omap/outer_cache-arm-omap.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/omap/pic-arm-gic-omap4.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/omap/pic-arm-omap3.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/omap/platform_control-arm-omap4.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/omap/reset-arm-omap.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/omap/timer-arm-mptimer-omap4.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/omap/timer-arm-omap3.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/omap/timer_omap_1mstimer.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/omap/timer_omap_gentimer.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/omap/uart-arm-omap.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/bsp/pxa-sa/pic-arm-pxa_sa1100.cpp
kernel/fiasco/src/kern/arm/bsp/pxa-sa/timer-arm-pxa_sa1100.cpp
kernel/fiasco/src/kern/arm/bsp/pxa/Modules
kernel/fiasco/src/kern/arm/bsp/pxa/bootstrap-arm-pxa.cpp
kernel/fiasco/src/kern/arm/bsp/pxa/kernel_uart-arm-pxa.cpp
kernel/fiasco/src/kern/arm/bsp/pxa/mem_layout-arm-pxa.cpp
kernel/fiasco/src/kern/arm/bsp/pxa/reset-arm-pxa.cpp
kernel/fiasco/src/kern/arm/bsp/realview/Kconfig
kernel/fiasco/src/kern/arm/bsp/realview/Modules
kernel/fiasco/src/kern/arm/bsp/realview/board_check-arm-realview.cpp
kernel/fiasco/src/kern/arm/bsp/realview/bootstrap-arm-realview.cpp
kernel/fiasco/src/kern/arm/bsp/realview/clock-arm-realview.cpp
kernel/fiasco/src/kern/arm/bsp/realview/mem_layout-arm-realview.cpp
kernel/fiasco/src/kern/arm/bsp/realview/outer_cache-arm-realview.cpp
kernel/fiasco/src/kern/arm/bsp/realview/pic-arm-realview.cpp
kernel/fiasco/src/kern/arm/bsp/realview/platform-arm-realview.cpp
kernel/fiasco/src/kern/arm/bsp/realview/platform_control-arm-realview.cpp
kernel/fiasco/src/kern/arm/bsp/realview/reset-arm-realview.cpp
kernel/fiasco/src/kern/arm/bsp/realview/timer-arm-mptimer-realview.cpp
kernel/fiasco/src/kern/arm/bsp/realview/timer-arm-realview.cpp
kernel/fiasco/src/kern/arm/bsp/realview/uart-arm-realview.cpp
kernel/fiasco/src/kern/arm/bsp/s3c/Modules
kernel/fiasco/src/kern/arm/bsp/s3c/bootstrap-arm-s3c2410.cpp
kernel/fiasco/src/kern/arm/bsp/s3c/mem_layout-arm-s3c2410.cpp
kernel/fiasco/src/kern/arm/bsp/s3c/pic-arm-s3c2410.cpp
kernel/fiasco/src/kern/arm/bsp/s3c/reset-arm-s3c2410.cpp
kernel/fiasco/src/kern/arm/bsp/s3c/timer-arm-s3c2410.cpp
kernel/fiasco/src/kern/arm/bsp/s3c/uart-s3c2410.cpp
kernel/fiasco/src/kern/arm/bsp/sa1100/Modules
kernel/fiasco/src/kern/arm/bsp/sa1100/bootstrap-arm-sa1100.cpp
kernel/fiasco/src/kern/arm/bsp/sa1100/kernel_uart-arm-sa1100.cpp
kernel/fiasco/src/kern/arm/bsp/sa1100/mem_layout-arm-sa1100.cpp
kernel/fiasco/src/kern/arm/bsp/sa1100/reset-arm-sa1100.cpp
kernel/fiasco/src/kern/arm/bsp/tegra2/Kconfig
kernel/fiasco/src/kern/arm/bsp/tegra2/Modules
kernel/fiasco/src/kern/arm/bsp/tegra2/bootstrap-arm-tegra2.cpp
kernel/fiasco/src/kern/arm/bsp/tegra2/kernel_uart-arm-tegra2.cpp
kernel/fiasco/src/kern/arm/bsp/tegra2/mem_layout-arm-tegra2.cpp
kernel/fiasco/src/kern/arm/bsp/tegra2/outer_cache-arm-tegra2.cpp
kernel/fiasco/src/kern/arm/bsp/tegra2/pic-arm-tegra2.cpp
kernel/fiasco/src/kern/arm/bsp/tegra2/platform_control-arm-tegra2.cpp
kernel/fiasco/src/kern/arm/bsp/tegra2/reset-arm-tegra2.cpp
kernel/fiasco/src/kern/arm/bsp/tegra2/timer-arm-tegra2.cpp
kernel/fiasco/src/kern/arm/config-arm.cpp
kernel/fiasco/src/kern/arm/cpu-arm.cpp
kernel/fiasco/src/kern/arm/fpu-arm.cpp
kernel/fiasco/src/kern/arm/gic.cpp
kernel/fiasco/src/kern/arm/ipi-arm.cpp
kernel/fiasco/src/kern/arm/ivt.S
kernel/fiasco/src/kern/arm/kern_lib_page.cpp
kernel/fiasco/src/kern/arm/kernel_task-arm.cpp
kernel/fiasco/src/kern/arm/kernel_thread-arm.cpp
kernel/fiasco/src/kern/arm/kip_init.cpp
kernel/fiasco/src/kern/arm/kmem.cpp
kernel/fiasco/src/kern/arm/kmem_alloc-arm.cpp
kernel/fiasco/src/kern/arm/kmem_space.cpp
kernel/fiasco/src/kern/arm/main.cpp
kernel/fiasco/src/kern/arm/mem_layout-arm.cpp
kernel/fiasco/src/kern/arm/mem_layout-noncont.cpp
kernel/fiasco/src/kern/arm/mem_op.cpp
kernel/fiasco/src/kern/arm/mem_space-arm.cpp
kernel/fiasco/src/kern/arm/mem_unit.cpp
kernel/fiasco/src/kern/arm/outer_cache-l2cxx0.cpp
kernel/fiasco/src/kern/arm/paging-arm.cpp
kernel/fiasco/src/kern/arm/perf_cnt-arm.cpp
kernel/fiasco/src/kern/arm/pic-gic.cpp
kernel/fiasco/src/kern/arm/scu.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/startup-arm.cpp
kernel/fiasco/src/kern/arm/sys_call_page-arm.cpp
kernel/fiasco/src/kern/arm/tb_entry-arm.cpp
kernel/fiasco/src/kern/arm/thread-arm.cpp
kernel/fiasco/src/kern/arm/thread-jdb.cpp
kernel/fiasco/src/kern/arm/timer-arm-mptimer.cpp
kernel/fiasco/src/kern/arm/timer-arm.cpp
kernel/fiasco/src/kern/arm/timer_sp804.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/tramp-mp.S
kernel/fiasco/src/kern/arm/trap_state.cpp
kernel/fiasco/src/kern/arm/vm.cpp
kernel/fiasco/src/kern/arm/vm_factory-arm.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/arm/vmem_alloc-arch.cpp
kernel/fiasco/src/kern/boot_alloc.cpp
kernel/fiasco/src/kern/buddy_alloc.cpp
kernel/fiasco/src/kern/clock.cpp
kernel/fiasco/src/kern/config.cpp
kernel/fiasco/src/kern/context.cpp
kernel/fiasco/src/kern/context_base.cpp
kernel/fiasco/src/kern/cpu.cpp
kernel/fiasco/src/kern/cpu_mask.cpp
kernel/fiasco/src/kern/dbg_page_info.cpp
kernel/fiasco/src/kern/factory.cpp
kernel/fiasco/src/kern/fpu.cpp
kernel/fiasco/src/kern/globals.cpp
kernel/fiasco/src/kern/ia32/32/paging-ia32-32.cpp
kernel/fiasco/src/kern/ia32/32/sys_call_page-abs-ia32.cpp
kernel/fiasco/src/kern/ia32/32/thread-ia32-32.cpp
kernel/fiasco/src/kern/ia32/64/paging-ia32-64.cpp
kernel/fiasco/src/kern/ia32/64/thread-ia32-64.cpp
kernel/fiasco/src/kern/ia32/apic-ia32.cpp
kernel/fiasco/src/kern/ia32/cpu-ia32.cpp
kernel/fiasco/src/kern/ia32/dirq-ia32-ux.cpp
kernel/fiasco/src/kern/ia32/fpu-ia32-ux.cpp
kernel/fiasco/src/kern/ia32/fpu-ia32.cpp
kernel/fiasco/src/kern/ia32/idt.cpp
kernel/fiasco/src/kern/ia32/io_apic.cpp
kernel/fiasco/src/kern/ia32/ipi-ia32.cpp
kernel/fiasco/src/kern/ia32/irq_chip_pic.cpp
kernel/fiasco/src/kern/ia32/irq_msi.cpp
kernel/fiasco/src/kern/ia32/kmem-ia32.cpp
kernel/fiasco/src/kern/ia32/kmem_alloc-ia32.cpp
kernel/fiasco/src/kern/ia32/main-ia32.cpp
kernel/fiasco/src/kern/ia32/map_util-io.cpp
kernel/fiasco/src/kern/ia32/mem_space-ia32.cpp
kernel/fiasco/src/kern/ia32/paging-ia32.cpp
kernel/fiasco/src/kern/ia32/startup-ia32.cpp
kernel/fiasco/src/kern/ia32/svm.cpp
kernel/fiasco/src/kern/ia32/thread-ia32.cpp
kernel/fiasco/src/kern/ia32/timer-apic.cpp
kernel/fiasco/src/kern/ia32/timer-ia32-amd64-ux.cpp
kernel/fiasco/src/kern/ia32/timer-pit.cpp
kernel/fiasco/src/kern/ia32/timer-rtc.cpp
kernel/fiasco/src/kern/ia32/timer_irq.cpp
kernel/fiasco/src/kern/ia32/timer_tick-apic.cpp
kernel/fiasco/src/kern/ia32/tramp-mp.S
kernel/fiasco/src/kern/ia32/vm.cpp
kernel/fiasco/src/kern/ia32/vm_factory-ia32.cpp
kernel/fiasco/src/kern/ia32/vm_svm.cpp
kernel/fiasco/src/kern/ia32/vm_vmx.cpp
kernel/fiasco/src/kern/ia32/vm_vmx_ept.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/ia32/vmem_alloc-ia32.cpp
kernel/fiasco/src/kern/ia32/vmx.cpp
kernel/fiasco/src/kern/icu_helper.cpp
kernel/fiasco/src/kern/io_space.cpp
kernel/fiasco/src/kern/ipc_gate.cpp
kernel/fiasco/src/kern/ipi.cpp
kernel/fiasco/src/kern/irq.cpp
kernel/fiasco/src/kern/irq_chip.cpp
kernel/fiasco/src/kern/irq_mgr.cpp
kernel/fiasco/src/kern/kernel_task.cpp
kernel/fiasco/src/kern/kernel_thread-std.cpp
kernel/fiasco/src/kern/kernel_thread.cpp
kernel/fiasco/src/kern/kmem_alloc.cpp
kernel/fiasco/src/kern/kmem_slab.cpp
kernel/fiasco/src/kern/kobject.cpp
kernel/fiasco/src/kern/kobject_dbg.cpp
kernel/fiasco/src/kern/kobject_helper.cpp
kernel/fiasco/src/kern/kobject_iface.cpp
kernel/fiasco/src/kern/kobject_mapdb.cpp
kernel/fiasco/src/kern/map_util-mem.cpp
kernel/fiasco/src/kern/map_util-objs.cpp
kernel/fiasco/src/kern/map_util.cpp
kernel/fiasco/src/kern/mapdb.cpp
kernel/fiasco/src/kern/mapdb_types.h [new file with mode: 0644]
kernel/fiasco/src/kern/mapping.cpp
kernel/fiasco/src/kern/mapping_tree.cpp
kernel/fiasco/src/kern/mem_layout.cpp
kernel/fiasco/src/kern/mem_space.cpp
kernel/fiasco/src/kern/obj_space-phys.cpp
kernel/fiasco/src/kern/obj_space-virt.cpp
kernel/fiasco/src/kern/obj_space.cpp
kernel/fiasco/src/kern/obj_space_phys_util.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/obj_space_types.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/obj_space_virt_util.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/paging.cpp
kernel/fiasco/src/kern/per_cpu_data.cpp
kernel/fiasco/src/kern/per_cpu_data_alloc.cpp
kernel/fiasco/src/kern/pic-i8259.cpp
kernel/fiasco/src/kern/pic.cpp
kernel/fiasco/src/kern/platform_control.cpp
kernel/fiasco/src/kern/platform_control_object.cpp
kernel/fiasco/src/kern/ppc32/boot_info-ppc32.cpp
kernel/fiasco/src/kern/ppc32/bsp/mpc52xx/pic-mpc52xx.cpp
kernel/fiasco/src/kern/ppc32/cpu-ppc32.cpp
kernel/fiasco/src/kern/ppc32/kernel_task-ppc32.cpp
kernel/fiasco/src/kern/ppc32/kmem.cpp
kernel/fiasco/src/kern/ppc32/kmem_alloc-ppc32.cpp
kernel/fiasco/src/kern/ppc32/mem_space-cache.cpp
kernel/fiasco/src/kern/ppc32/mem_space-htab.cpp
kernel/fiasco/src/kern/ppc32/mem_space-ppc32.cpp
kernel/fiasco/src/kern/ppc32/paging-ppc32.cpp
kernel/fiasco/src/kern/ppc32/startup-ppc32.cpp
kernel/fiasco/src/kern/ppc32/sys_call_page-ppc32.cpp
kernel/fiasco/src/kern/ppc32/thread-jdb.cpp
kernel/fiasco/src/kern/ppc32/thread-ppc32.cpp
kernel/fiasco/src/kern/ppc32/timer-decr-ppc32.cpp
kernel/fiasco/src/kern/ppc32/trap_state.cpp
kernel/fiasco/src/kern/prio_list.cpp
kernel/fiasco/src/kern/ptab_base.cpp
kernel/fiasco/src/kern/queue.cpp
kernel/fiasco/src/kern/queue_item.cpp
kernel/fiasco/src/kern/rcupdate.cpp
kernel/fiasco/src/kern/ready_queue_fp.cpp
kernel/fiasco/src/kern/receiver.cpp
kernel/fiasco/src/kern/sched_context-fixed_prio.cpp
kernel/fiasco/src/kern/sched_context.cpp
kernel/fiasco/src/kern/scheduler.cpp
kernel/fiasco/src/kern/sigma0_task-io.cpp
kernel/fiasco/src/kern/sigma0_task.cpp
kernel/fiasco/src/kern/space.cpp
kernel/fiasco/src/kern/sparc/bsp/leon3/pic-sparc-leon3.cpp
kernel/fiasco/src/kern/sparc/cpu-sparc.cpp
kernel/fiasco/src/kern/sparc/kernel_task-sparc.cpp
kernel/fiasco/src/kern/sparc/kernel_thread-sparc.cpp
kernel/fiasco/src/kern/sparc/kmem.cpp
kernel/fiasco/src/kern/sparc/kmem_alloc-sparc.cpp
kernel/fiasco/src/kern/sparc/mem_layout-sparc.cpp
kernel/fiasco/src/kern/sparc/mem_space-sparc.cpp
kernel/fiasco/src/kern/sparc/paging-sparc.cpp
kernel/fiasco/src/kern/sparc/startup-sparc.cpp
kernel/fiasco/src/kern/sparc/tb_entry-sparc.cpp
kernel/fiasco/src/kern/sparc/thread-jdb.cpp
kernel/fiasco/src/kern/sparc/thread-sparc.cpp
kernel/fiasco/src/kern/sparc/timer-decr-sparc.cpp
kernel/fiasco/src/kern/sparc/trap_state.cpp
kernel/fiasco/src/kern/syscalls-log.cpp
kernel/fiasco/src/kern/syscalls.cpp
kernel/fiasco/src/kern/task.cpp
kernel/fiasco/src/kern/tb_entry.cpp
kernel/fiasco/src/kern/tb_entry_output.cc
kernel/fiasco/src/kern/thread-ipc.cpp
kernel/fiasco/src/kern/thread-pagefault.cpp
kernel/fiasco/src/kern/thread-vcpu.cpp
kernel/fiasco/src/kern/thread.cpp
kernel/fiasco/src/kern/thread_object.cpp
kernel/fiasco/src/kern/timeout.cpp
kernel/fiasco/src/kern/timer-hpet.cpp
kernel/fiasco/src/kern/timer.cpp
kernel/fiasco/src/kern/timer_tick-broadcast.cpp [new file with mode: 0644]
kernel/fiasco/src/kern/timer_tick-single-vector.cpp
kernel/fiasco/src/kern/timer_tick.cpp
kernel/fiasco/src/kern/timeslice_timeout.cpp
kernel/fiasco/src/kern/uart-mmio.cpp
kernel/fiasco/src/kern/ux/Makerules.KERNEL
kernel/fiasco/src/kern/ux/cpu-ux.cpp
kernel/fiasco/src/kern/ux/fpu-ux.cpp
kernel/fiasco/src/kern/ux/glue_libc_ux.cc
kernel/fiasco/src/kern/ux/ipi-ux.cpp
kernel/fiasco/src/kern/ux/kmem-ux.cpp
kernel/fiasco/src/kern/ux/main-ux.cpp
kernel/fiasco/src/kern/ux/mem_layout-ux.cpp
kernel/fiasco/src/kern/ux/mem_space-ux.cpp
kernel/fiasco/src/kern/ux/pic-ux.cpp
kernel/fiasco/src/kern/ux/startup.cpp
kernel/fiasco/src/kern/ux/task-ux.cpp
kernel/fiasco/src/kern/ux/thread-ux.cpp
kernel/fiasco/src/kern/ux/timer-ux.cpp
kernel/fiasco/src/kern/ux/usermode.cpp
kernel/fiasco/src/kern/vkey.cpp
kernel/fiasco/src/kern/vlog.cpp
kernel/fiasco/src/kernel.arm.ld
kernel/fiasco/src/lib/libk/amd64/atomic-amd64.cpp
kernel/fiasco/src/lib/libk/arm/atomic-arm-up.cpp
kernel/fiasco/src/lib/libk/atomic.cpp
kernel/fiasco/src/lib/libk/cxx/bitfield [new file with mode: 0644]
kernel/fiasco/src/lib/libk/cxx/bits/list_basics.h [new file with mode: 0644]
kernel/fiasco/src/lib/libk/cxx/cxx_int [new file with mode: 0644]
kernel/fiasco/src/lib/libk/cxx/dlist [new file with mode: 0644]
kernel/fiasco/src/lib/libk/cxx/hlist [new file with mode: 0644]
kernel/fiasco/src/lib/libk/cxx/slist [new file with mode: 0644]
kernel/fiasco/src/lib/libk/cxx/type_list [new file with mode: 0644]
kernel/fiasco/src/lib/libk/cxx/type_traits [new file with mode: 0644]
kernel/fiasco/src/lib/libk/cxx/union [new file with mode: 0644]
kernel/fiasco/src/lib/libk/ia32/atomic-ia32-smp.cpp
kernel/fiasco/src/lib/libk/lock_guard.cpp
kernel/fiasco/src/lib/libk/slab_cache.cpp
kernel/fiasco/src/lib/libk/unique_ptr.h
kernel/fiasco/src/lib/uart/uart_s3c2410.cc
kernel/fiasco/src/lib/uart/uart_s3c2410.h
kernel/fiasco/src/templates/globalconfig.out.amd64-1
kernel/fiasco/src/templates/globalconfig.out.amd64-2
kernel/fiasco/src/templates/globalconfig.out.amd64-3-noinl
kernel/fiasco/src/templates/globalconfig.out.amd64-mp
kernel/fiasco/src/templates/globalconfig.out.arm-a9-mp-1
kernel/fiasco/src/templates/globalconfig.out.arm-a9-mp-2
kernel/fiasco/src/templates/globalconfig.out.arm-a9-mp-vexpress-1 [new file with mode: 0644]
kernel/fiasco/src/templates/globalconfig.out.arm-a9-mp-vexpress-2 [new file with mode: 0644]
kernel/fiasco/src/templates/globalconfig.out.arm-imx21
kernel/fiasco/src/templates/globalconfig.out.arm-imx35
kernel/fiasco/src/templates/globalconfig.out.arm-imx51
kernel/fiasco/src/templates/globalconfig.out.arm-imx6
kernel/fiasco/src/templates/globalconfig.out.arm-int-1
kernel/fiasco/src/templates/globalconfig.out.arm-int-2
kernel/fiasco/src/templates/globalconfig.out.arm-kirkwood
kernel/fiasco/src/templates/globalconfig.out.arm-omap3evm
kernel/fiasco/src/templates/globalconfig.out.arm-omap4-panda
kernel/fiasco/src/templates/globalconfig.out.arm-pxa
kernel/fiasco/src/templates/globalconfig.out.arm-rv-1
kernel/fiasco/src/templates/globalconfig.out.arm-rv-2
kernel/fiasco/src/templates/globalconfig.out.arm-rv-3
kernel/fiasco/src/templates/globalconfig.out.arm-rv-4-noinl
kernel/fiasco/src/templates/globalconfig.out.arm-s3c
kernel/fiasco/src/templates/globalconfig.out.arm-sa
kernel/fiasco/src/templates/globalconfig.out.arm-t2
kernel/fiasco/src/templates/globalconfig.out.arm-v6
kernel/fiasco/src/templates/globalconfig.out.arm-v6-mp-eb
kernel/fiasco/src/templates/globalconfig.out.arm-v6-mp-pb
kernel/fiasco/src/templates/globalconfig.out.arm-v7
kernel/fiasco/src/templates/globalconfig.out.ia32-1
kernel/fiasco/src/templates/globalconfig.out.ia32-2
kernel/fiasco/src/templates/globalconfig.out.ia32-3-noinl
kernel/fiasco/src/templates/globalconfig.out.ia32-big
kernel/fiasco/src/templates/globalconfig.out.ia32-mp
kernel/fiasco/src/templates/globalconfig.out.ia32-ndebug
kernel/fiasco/src/templates/globalconfig.out.ppc32-1 [new file with mode: 0644]
kernel/fiasco/src/templates/globalconfig.out.sparc-1 [new file with mode: 0644]
kernel/fiasco/src/templates/globalconfig.out.ux-1
kernel/fiasco/src/templates/globalconfig.out.ux-2
kernel/fiasco/src/templates/globalconfig.out.ux-3-noinl
kernel/fiasco/src/test/unit/map_util_t.cpp
kernel/fiasco/src/test/unit/map_util_t.out.verify.vf [new file with mode: 0755]
kernel/fiasco/src/test/unit/mapdb_t.cpp
kernel/fiasco/src/test/unit/mapdb_t.out.verify.vf [new file with mode: 0644]
kernel/fiasco/src/types/amd64/types-arch.h
kernel/fiasco/src/types/arm/types-arch.h
kernel/fiasco/src/types/ia32/types-arch.h
kernel/fiasco/src/types/ppc32/types-arch.h
kernel/fiasco/src/types/sparc/types-arch.h
kernel/fiasco/src/types/types.h
kernel/fiasco/src/types/ux/types-arch.h
kernel/fiasco/tool/kconfig/Makefile
kernel/fiasco/tool/kconfig/README
kernel/fiasco/tool/kconfig/scripts/Makefile.lib
l4/mk/platforms/rpi_a.conf [new file with mode: 0644]
l4/mk/platforms/rpi_b.conf [new file with mode: 0644]
l4/mk/platforms/rv_vexpress_a15.conf [new file with mode: 0644]
l4/pkg/bootstrap/server/src/ARCH-arm/crt0.S
l4/pkg/bootstrap/server/src/Make.rules
l4/pkg/bootstrap/server/src/Makefile.platform [new file with mode: 0644]
l4/pkg/bootstrap/server/src/platform/exynos.cc [new file with mode: 0644]
l4/pkg/bootstrap/server/src/platform/imx.cc
l4/pkg/bootstrap/server/src/platform/integrator.cc
l4/pkg/bootstrap/server/src/platform/kirkwood.cc
l4/pkg/bootstrap/server/src/platform/om.cc
l4/pkg/bootstrap/server/src/platform/omap.cc
l4/pkg/bootstrap/server/src/platform/pxa.cc
l4/pkg/bootstrap/server/src/platform/rpi.cc [new file with mode: 0644]
l4/pkg/bootstrap/server/src/platform/rv.cc
l4/pkg/bootstrap/server/src/platform/rv_vexpress.cc
l4/pkg/bootstrap/server/src/platform/sa1000.cc
l4/pkg/bootstrap/server/src/platform/tegra2.cc
l4/pkg/bootstrap/server/src/platform/x86_pc.cc
l4/pkg/cxx/lib/tl/include/Makefile
l4/pkg/cxx/lib/tl/include/bitfield [new file with mode: 0644]
l4/pkg/cxx/lib/tl/include/type_list [new file with mode: 0644]
l4/pkg/cxx/lib/tl/include/type_traits
l4/pkg/cxx/lib/tl/include/utils [new file with mode: 0644]
l4/pkg/drivers-frst/uart/src/uart_pxa.cc
l4/pkg/examples/Makefile
l4/pkg/examples/sys/vm-tz/Makefile
l4/pkg/examples/sys/vm-tz/main.cc
l4/pkg/examples/sys/vmtest/vmxtest.c
l4/pkg/io/server/src/Make.rules
l4/pkg/io/server/src/device.h
l4/pkg/io/server/src/gpio
l4/pkg/io/server/src/gpio.cc
l4/pkg/io/server/src/lua_glue.swg
l4/pkg/io/server/src/lua_glue.swg.cc
l4/pkg/io/server/src/main.cc
l4/pkg/io/server/src/resource.h
l4/pkg/io/server/src/vbus.cc
l4/pkg/io/server/src/vbus.h
l4/pkg/io/server/src/vdevice.h
l4/pkg/io/server/src/vgpio.cc
l4/pkg/l4sys/include/ARCH-arm/L4API-l4f/ipc.h
l4/pkg/l4sys/include/ARCH-arm/vm
l4/pkg/l4sys/include/ARCH-arm/vm.h
l4/pkg/l4sys/include/__vm-vmx.h
l4/pkg/l4sys/include/irq.h
l4/pkg/l4sys/include/vcon.h
l4/pkg/l4sys/include/vcpu.h
l4/pkg/libpng/lib/README
l4/pkg/libpng/lib/dist/ANNOUNCE
l4/pkg/libpng/lib/dist/CHANGES
l4/pkg/libpng/lib/dist/CMakeLists.txt
l4/pkg/libpng/lib/dist/INSTALL
l4/pkg/libpng/lib/dist/LICENSE
l4/pkg/libpng/lib/dist/Makefile.am
l4/pkg/libpng/lib/dist/Makefile.in
l4/pkg/libpng/lib/dist/README
l4/pkg/libpng/lib/dist/autogen.sh
l4/pkg/libpng/lib/dist/config.h.in
l4/pkg/libpng/lib/dist/configure
l4/pkg/libpng/lib/dist/configure.ac
l4/pkg/libpng/lib/dist/libpng-manual.txt
l4/pkg/libpng/lib/dist/libpng.3
l4/pkg/libpng/lib/dist/libpngpf.3
l4/pkg/libpng/lib/dist/png.5
l4/pkg/libpng/lib/dist/png.c
l4/pkg/libpng/lib/dist/png.h
l4/pkg/libpng/lib/dist/pngconf.h
l4/pkg/libpng/lib/dist/pngerror.c
l4/pkg/libpng/lib/dist/pngget.c
l4/pkg/libpng/lib/dist/pnginfo.h
l4/pkg/libpng/lib/dist/pngpriv.h
l4/pkg/libpng/lib/dist/pngread.c
l4/pkg/libpng/lib/dist/pngrtran.c
l4/pkg/libpng/lib/dist/pngrutil.c
l4/pkg/libpng/lib/dist/pngset.c
l4/pkg/libpng/lib/dist/pngstruct.h
l4/pkg/libpng/lib/dist/pngtest.c
l4/pkg/libpng/lib/dist/pngwrite.c
l4/pkg/libpng/lib/dist/scripts/README.txt
l4/pkg/libpng/lib/dist/scripts/checksym.awk
l4/pkg/libpng/lib/dist/scripts/def.dfn
l4/pkg/libpng/lib/dist/scripts/dfn.awk [new file with mode: 0644]
l4/pkg/libpng/lib/dist/scripts/intprefix.dfn
l4/pkg/libpng/lib/dist/scripts/libpng-config-head.in
l4/pkg/libpng/lib/dist/scripts/libpng.pc.in
l4/pkg/libpng/lib/dist/scripts/makefile.cegcc
l4/pkg/libpng/lib/dist/scripts/makefile.freebsd
l4/pkg/libpng/lib/dist/scripts/makefile.linux
l4/pkg/libpng/lib/dist/scripts/makefile.msys
l4/pkg/libpng/lib/dist/scripts/makefile.ne12bsd
l4/pkg/libpng/lib/dist/scripts/makefile.netbsd
l4/pkg/libpng/lib/dist/scripts/makefile.openbsd
l4/pkg/libpng/lib/dist/scripts/makefile.std
l4/pkg/libpng/lib/dist/scripts/options.awk
l4/pkg/libpng/lib/dist/scripts/pnglibconf.dfa
l4/pkg/libpng/lib/dist/scripts/pnglibconf.h.prebuilt
l4/pkg/libpng/lib/dist/scripts/pnglibconf.mak
l4/pkg/libpng/lib/dist/scripts/prefix.dfn
l4/pkg/libpng/lib/dist/scripts/sym.dfn
l4/pkg/libpng/lib/dist/scripts/symbols.def
l4/pkg/libpng/lib/dist/scripts/symbols.dfn
l4/pkg/libpng/lib/dist/scripts/vers.dfn
l4/pkg/libpng/lib/dist/test-driver [new file with mode: 0644]
l4/pkg/lwip/lib/arch/sys_arch.h
l4/pkg/mag/server/src/lua_glue.swg.cc
l4/pkg/plr/Control
l4/pkg/plr/include/pthread_rep.h
l4/pkg/plr/lib/libpthread_romain/src/Makefile
l4/pkg/plr/lib/libpthread_romain/src/mutex.c
l4/pkg/plr/server/src/app_loading.cc
l4/pkg/plr/server/src/app_thread.cc
l4/pkg/plr/server/src/fault_handlers/lock_observer.h
l4/pkg/plr/server/src/fault_handlers/pagefault.cc
l4/pkg/plr/server/src/fault_handlers/replicalog.cc
l4/pkg/plr/server/src/fault_handlers/syscalls.cc
l4/pkg/plr/server/src/manager
l4/pkg/plr/server/src/manager.cc
l4/pkg/plr/server/src/memory
l4/pkg/plr/server/src/memory.cc
l4/pkg/plr/server/src/thread_group.h
l4/pkg/rtc/server/src/main.cc
l4/pkg/sqlite/lib/README
l4/pkg/sqlite/lib/contrib/configure
l4/pkg/sqlite/lib/contrib/configure.ac
l4/pkg/sqlite/lib/contrib/shell.c
l4/pkg/sqlite/lib/contrib/sqlite3.c
l4/pkg/sqlite/lib/contrib/sqlite3.h
l4/pkg/sqlite/lib/contrib/sqlite3ext.h
l4/tool/lib/L4/ModList.pm
repomgr

index 05566909ba069d5488982240913162c560fca684..234711484bcc0b7037273b460162d3c248f002bc 100644 (file)
@@ -90,7 +90,7 @@ fiasco: fiasco.builddir.create
        $(MAKE) -C $(DFLBUILDDIR) -j$(PL)
 
 checkallseq:
-       error=0;                                                      \
+       @error=0;                                                     \
        $(RM) -r $(ALLBUILDDIR);                                      \
        for X in $(TEST_TEMPLATES); do                                \
                echo -e "\n= Building configuration: $$X\n\n";        \
@@ -116,7 +116,7 @@ checkall l4check:
 .PHONY: dobuildparallel checkallp
 
 dobuildparallel: $(addprefix $(ALLBUILDDIR)/,$(TEST_TEMPLATES))
-       error=0;                                                              \
+       @error=0;                                                             \
        echo "======================================================";        \
        for d in $(TEST_TEMPLATES); do                                        \
          if [ -e $(ALLBUILDDIR)/$$d/build.failed ]; then                     \
@@ -137,7 +137,7 @@ $(addprefix $(ALLBUILDDIR)/,$(TEST_TEMPLATES)):
        $(MAKE) -C $@ 2>&1 | tee $@/build.log;                                \
        if [ $${PIPESTATUS[0]} = 0 ];                                         \
        then [ -z "$(KEEP_BUILD_DIRS)" ] && $(RM) -r $@;                      \
-       else echo $${PIPESTATUS[0]} > $@/build.failed; fi
+       else echo $${PIPESTATUS[0]} > $@/build.failed; fi; true
 
 list:
        @echo "Templates:"
index f6e98c5d894f8076d7566267226951822a713e7b..b79185acc2d9a2dc90ea2a08e7b51b80df885d2e 100644 (file)
@@ -85,7 +85,7 @@ config ABI_VF
 
 config PF_ARM_MP_CAPABLE
        bool
-       default y if ARM_MPCORE || ARM_CORTEX_A9
+       default y if ARM_MPCORE || ARM_CORTEX_A7 || ARM_CORTEX_A9 || ARM_CORTEX_A15
 
 config CAN_ARM_CPU_SA1100
        bool
@@ -108,12 +108,21 @@ config CAN_ARM_CPU_1176
 config CAN_ARM_CPU_MPCORE
        bool
 
+config CAN_ARM_CPU_CORTEX_A5
+       bool
+
+config CAN_ARM_CPU_CORTEX_A7
+       bool
+
 config CAN_ARM_CPU_CORTEX_A8
        bool
 
 config CAN_ARM_CPU_CORTEX_A9
        bool
 
+config CAN_ARM_CPU_CORTEX_A15
+       bool
+
 config CAN_ARM_CACHE_L2CXX0
        bool
 
@@ -153,6 +162,14 @@ config ARM_MPCORE
        bool "ARM MPCore CPU"
        depends on CAN_ARM_CPU_MPCORE
 
+config ARM_CORTEX_A5
+       bool "ARM Cortex-A5 CPU"
+       depends on CAN_ARM_CPU_CORTEX_A5
+
+config ARM_CORTEX_A7
+       bool "ARM Cortex-A7 CPU"
+       depends on CAN_ARM_CPU_CORTEX_A7
+
 config ARM_CORTEX_A8
        bool "ARM Cortex-A8 CPU"
        depends on CAN_ARM_CPU_CORTEX_A8
@@ -161,6 +178,10 @@ config ARM_CORTEX_A9
        bool "ARM Cortex-A9 CPU"
        depends on CAN_ARM_CPU_CORTEX_A9
 
+config ARM_CORTEX_A15
+       bool "ARM Cortex-A15 CPU"
+       depends on CAN_ARM_CPU_CORTEX_A15
+
 config IA32_486
        bool "Intel 80486"
        depends on IA32
@@ -278,8 +299,6 @@ config LEON3
          Choose this if you have a LEON3 CPU.
 endchoice
 
-
-
 config CPU_VIRT
        bool "Enable CPU virtualization (SVM and VT)"
        depends on PF_PC
@@ -294,19 +313,50 @@ config ARM_ALIGNMENT_CHECK
        help
          Enable if you want to have alignment check enabled.
 
-config ARM_TZ
-       bool "Enable ARM TrustZone support"
-       depends on (ARM_1176 || ARM_CORTEX_A8 || ARM_CORTEX_A9) && EXPERIMENTAL
+choice
+       prompt "Execution Model"
+       default ARM_EM_STD
+       depends on ARM
+
+config ARM_EM_STD
+       bool "Standard mode"
        help
-         Support ARM TrustZone security extension.
+         Systems without ARM TrustZone support, or no specific TrustZone
+         support.
 
-config ARM_CA9_ENABLE_SWP
+config ARM_EM_NS
+       bool "TrustZone normal side"
+       depends on ARM_1176 || ARM_CORTEX_A7 || ARM_CORTEX_A8 || ARM_CORTEX_A9 || ARM_CORTEX_A15
+       help
+         In a system with ARM TrustZone extension, run on the normal side.
+
+config ARM_EM_TZ
+       bool "TrustZone secure side"
+       depends on ARM_1176 || ARM_CORTEX_A7 || ARM_CORTEX_A8 || ARM_CORTEX_A9 || ARM_CORTEX_A15
+       help
+         In a system with ARM TrustZone extension, run on the secure side,
+         and allow monitor services.
+
+endchoice
+
+config ARM_SECMONIF_MC
+       bool
+       depends on ARM_EM_NS
+       default y
+
+config ARM_ENABLE_SWP
        bool "Enable the deprecated 'swp' instruction"
-       depends on ARM_CORTEX_A9
+       depends on ARM_CORTEX_A9 || ARM_CORTEX_A15 || ARM_CORTEX_A7 || ARM_CORTEX_A5
        help
          Enabling this option enables the deprecated 'swp' instruction.
          Avoid to enable it.
 
+config ARM_LPAE
+        bool "Use LPAE page table format"
+        depends on ARM_CORTEX_A15 || ARM_CORTEX_A7
+        help
+          Use the extended page table format (LPAE).
+
 config ARM_CACHE_L2CXX0
        bool "Enable L2 Cache"
        default y
@@ -402,7 +452,7 @@ config ARM_1176_CACHE_ALIAS_FIX
 
 config ARM_CPU_ERRATA
         bool "Enable CPU errata workarounds"
-        depends on ARM && !ARM_TZ
+        depends on ARM
 
 endmenu # target
 
@@ -410,7 +460,7 @@ menu "Kernel options"
 
 config MP
        bool "Enable multi processor support"
-       depends on (PF_PC || PF_ARM_MP_CAPABLE || (PF_UX && EXPERIMENTAL))
+       depends on (PF_PC || PF_ARM_MP_CAPABLE) && !PF_UX
        help
          Enable support for machines with multiple processors.
 
@@ -510,8 +560,14 @@ endchoice
 
 config DISABLE_VIRT_OBJ_SPACE
        bool "No virtually mapped array for cap tables"
-       depends on (PF_PC || ARM) &&  EXPERIMENTAL
-       default n
+       depends on (PF_PC || (ARM && !CPU_VIRT)) &&  EXPERIMENTAL
+
+config VIRT_OBJ_SPACE
+       def_bool y
+       depends on !DISABLE_VIRT_OBJ_SPACE
+       depends on !(CPU_VIRT && ARM)
+        depends on !ARM || (ARM_V6PLUS && (!ARM_1176 || ARM_1176_CACHE_ALIAS_FIX))
+
 
 endmenu # kernel options
 
@@ -624,16 +680,14 @@ config JDB_LOGGING
 
 config JDB_DISASM
        bool "JDB disassembler"
-       default n if ARM
-       default y
+       default y if !ARM
        help
          Add support for disassembly. Increases memory foot-print, only
          enable when needed.
 
 config JDB_GZIP
        bool "GZIP compressed dumps"
-       default n if ARM
-       default y
+       default y if !ARM
        help
          Add supprt for gzip compressed dumps of the trace buffer.
          Increases memory foot-print, only enabled when needed.
@@ -755,7 +809,8 @@ config ARM_V6
        def_bool y if ARM_1136 || ARM_1176 || ARM_MPCORE
 
 config ARM_V7
-       def_bool y if ARM_CORTEX_A8 || ARM_CORTEX_A9
+       def_bool y if ARM_CORTEX_A8 || ARM_CORTEX_A9 \
+                     || ARM_CORTEX_A5 || ARM_CORTEX_A7 || ARM_CORTEX_A15
 
 config ARM_V6PLUS
        def_bool y if ARM_V6 || ARM_V7
index 1853672eb87357359acd85491c837eab13c70ca8..3f32d0dcfa7761dcba122ec4f9c47de66cea75c3 100644 (file)
@@ -20,6 +20,8 @@ SHARED_FLAGS                       += $(call CHECKCC,-mno-mmx,)
 SHARED_FLAGS                       += $(call CHECKCC,-mno-sse,)
 SHARED_FLAGS                       += $(call CHECKCC,-mno-sse2,)
 SHARED_FLAGS                       += $(call CHECKCC,-mno-sse3,)
+SHARED_FLAGS                       += $(call CHECKCC,-mno-sse4,)
+SHARED_FLAGS                       += $(call CHECKCC,-mno-sse4a,)
 SHARED_FLAGS                       += $(call CHECKCC,-mno-3dnow,)
 
 ASFLAGS                                += -m64 -mcmodel=kernel
index 43bfbfe5d2c324f0a7900539fe90e9649a359463..3d5c9e2c950ba674c792df352bf98962754cbe0d 100644 (file)
@@ -8,10 +8,13 @@ SHARED_FLAGS-$(CONFIG_ARM_926)    += -mcpu=arm926ej-s
 SHARED_FLAGS-$(CONFIG_ARM_1136)   += -mcpu=arm1136jf-s
 SHARED_FLAGS-$(CONFIG_ARM_1176)   += -mcpu=arm1176jzf-s
 SHARED_FLAGS-$(CONFIG_ARM_MPCORE) += -mcpu=mpcore
+SHARED_FLAGS-$(CONFIG_ARM_CORTEX_A5) += $(call CHECKCC,-mcpu=cortex-a5)
+SHARED_FLAGS-$(CONFIG_ARM_CORTEX_A7) += $(call CHECKCC,-mcpu=cortex-a7,-mcpu=cortex-a9)
 SHARED_FLAGS-$(CONFIG_ARM_CORTEX_A8) += $(call CHECKCC,-mcpu=cortex-a8)
 SHARED_FLAGS-$(CONFIG_ARM_CORTEX_A9) += $(call CHECKCC,-mcpu=cortex-a9)
+SHARED_FLAGS-$(CONFIG_ARM_CORTEX_A15) += $(call CHECKCC,-mcpu=cortex-a15,-mcpu=cortex-a9)
 SHARED_FLAGS                     += -msoft-float
 SHARED_FLAGS                      += $(call CHECKCC,-mno-thumb-interwork)
-SHARED_FLAGS                      += -marm -mabi=apcs-gnu
+SHARED_FLAGS                      += -marm -mabi=aapcs
 LDFLAGS                           += --no-warn-mismatch
 LD_EMULATION_CHOICE               := armelf armelf_linux_eabi armelf_fbsd
index 7635ee320e4a4361e551a8d277b8c8f1d36a5caf..7a7057ecc043bab223e756c4eacd8781feb4fa96 100644 (file)
@@ -33,6 +33,8 @@ SHARED_FLAGS                      += $(call CHECKCC,-mno-mmx,)
 SHARED_FLAGS                      += $(call CHECKCC,-mno-sse,)
 SHARED_FLAGS                      += $(call CHECKCC,-mno-sse2,)
 SHARED_FLAGS                      += $(call CHECKCC,-mno-sse3,)
+SHARED_FLAGS                      += $(call CHECKCC,-mno-sse4,)
+SHARED_FLAGS                      += $(call CHECKCC,-mno-sse4a,)
 SHARED_FLAGS                      += $(call CHECKCC,-mno-3dnow,)
 
 ASFLAGS                                  += -m32
index 4d157d3be044973821631f532c0297a545a9a44f..428b9a056c3cc64e7e1b876829ad5aa10f7f7d0d 100644 (file)
@@ -4,7 +4,8 @@ tooldir         := $(srcdir)/../tool
 CONFIG_BANNER_STRING ?= "Fiasco - prepare for world domination"
 
 .PHONY: all do-all test-all config textconfig menuconfig xconfig \
-        oldconfig regenconfig mrproper doc help update nconfig
+        oldconfig regenconfig mrproper doc help update nconfig \
+        savedefconfig listnewconfig oldnoconfig oldaskconfig
 
 all:
 
@@ -213,6 +214,12 @@ textconfig: $(KCONFIG_FILE)
 menuconfig oldconfig xconfig gconfig nconfig randconfig allyesconfig allnoconfig: $(KCONFIG_FILE)
        +$(kconfig_call) $@ silentoldconfig
 
+listnewconfig oldnoconfig savedefconfig: $(KCONFIG_FILE)
+       +$(kconfig_call) $@
+
+oldaskconfig: $(KCONFIG_FILE)
+       +$(kconfig_call) config
+
 ifneq ($(filter clean cleanall mrproper,$(MAKECMDGOALS)),)
 
 # Try to suck in clean targets from subsystems' Makefile fragments
index d6ce5b0a385fffbbda36a6b4684d761d4c2fc8ed..9cb4b185fb9ab3a61f16133cec4bd0b292b19fda 100644 (file)
@@ -87,12 +87,13 @@ $(ALL_TESTS): %: %.o
        @echo "Linking test $@"
        $(VERBOSE)$(CXX) -m32 -Wl,-Tkernel.ux.lds,--gc-sections \
          -static $(CXXFLAGS) $(LDFLAGS) $(PROF_FLAGS) $(OPT_CXXFLAGS) \
-         $(filter-out kernel.ux.lds,$^) -o $@ $(TEST_LIB)
+         $(filter-out kernel.ux.lds,$^) -o $@ $(TEST_LIB) -lutil
 
 %.ok: %
 ifeq ($(SYSTEM_TARGET)$(CONFIG_XARCH),ux)      # Test execution for non-cross UX builds
        @echo -n "Running test $* ... "
-       @./$< --test --quiet > $*.out
+       @./$< --test --quiet > $*.out.full
+       @grep "^\[UTEST\]" $*.out.full > $*.out
 ifeq ($(RECREATE_OUTPUT),1)
        @cp $*.out $(srcdir)/test/unit/$*.out.verify.$(CONFIG_ABI)
 endif # RECREATE_OUTPUT
index 85a21d4a870206362dc0f08db34ec44aea7a16d3..e0f1c3409d2508328774d3c7887ef74e5db34f2b 100644 (file)
@@ -116,7 +116,7 @@ $(NONDEBUG_C:.c=.S) : %.S: %.c
 %.o:   %.cc
        $(COMP_MESSAGE)
        $(VERBOSE)$(CXX) -c -MD -MP -MF .$*.cc.d.new -o $@ \
-         $(CPPFLAGS) $(CXXFLAGS) $(PROF_FLAGS) $(OPT_CXXFLAGS) $<
+         $(CPPFLAGS) $(CXXFLAGS) $(PROF_FLAGS) $(OPT_CXXFLAGS) $(CXXFLAGS_$(basename $(notdir $@))) $<
        @mv .$*.cc.d.new .$*.cc.d
 
 %.S:   %.cc
@@ -157,7 +157,7 @@ $(NONDEBUG_C:.c=.S) : %.S: %.c
 
 %.lds: %.ld
        $(COMP_MESSAGE)
-       $(VERBOSE)$(CPP) -undef -P -DASSEMBLER -o $@ $(CPPFLAGS) $<
+       $(VERBOSE)$(CPP) -MD -MP -MF .$*.ld.d -undef -P -DASSEMBLER -o $@ $(CPPFLAGS) $<
 
 (%): %
        $(AR_MESSAGE)
index ff3963d4442351edb8830f57e282d4ee5364fd16..77656164c18076d247bcb51e8a51e9995f5cd181 100644 (file)
@@ -14,11 +14,6 @@ PREPROCESS_PARTS     += arch $(CONFIG_ABI) 64bit iofp         \
                           i8259 pc i8254 fpu                    \
                           auto_map_kip io
 
-OBJ_SPACE-y = phys
-OBJ_SPACE-  = virt
-OBJ_SPACE   = $(OBJ_SPACE-$(CONFIG_DISABLE_VIRT_OBJ_SPACE))
-
-PREPROCESS_PARTS += obj_space_$(OBJ_SPACE)
 
 PREPROCESS_PARTS-$(CONFIG_MP)                += mp
 PREPROCESS_PARTS-$(CONFIG_LIST_ALLOC_SANITY) += list_alloc_debug
@@ -30,7 +25,7 @@ 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_CPU_VIRT)          += svm vmx
+PREPROCESS_PARTS-$(CONFIG_CPU_VIRT)          += svm vmx virtual_space_iface
 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
@@ -94,7 +89,7 @@ INTERFACES_KERNEL     += __main acpi io_apic irq_chip_ia32 irq_chip_pic     \
                           boot_console x86desc gdt idt tss timer_irq \
                           dirq
 
-INTERFACES_KERNEL-$(CONFIG_CPU_VIRT) += svm vmx vm vm_svm vm_vmx
+INTERFACES_KERNEL-$(CONFIG_CPU_VIRT) += svm vmx vm vm_svm vm_vmx vm_vmx_ept
 
 
 apic_IMPL              := apic-ia32 apic-ia32-mp
@@ -122,7 +117,6 @@ map_util_IMPL               := map_util map_util-mem map_util-io map_util-objs
 mem_layout_IMPL                := mem_layout mem_layout-ia32 mem_layout-ia32-64
 mem_space_IMPL         := mem_space mem_space-user mem_space-ia32
 mem_unit_IMPL          := mem_unit-amd64
-obj_space_IMPL          := obj_space obj_space-$(OBJ_SPACE)
 paging_IMPL            := paging-ia32-64 paging-ia32 paging
 perf_cnt_IMPL          := perf_cnt perf_cnt-ia32
 pic_IMPL               := pic pic-i8259
@@ -167,6 +161,7 @@ ifeq ("$(CONFIG_SCHED_APIC)","y")
 endif
 ifeq ("$(CONFIG_SCHED_HPET)","y")
   timer_IMPL           += timer-hpet
+  timer_tick_IMPL       += timer_tick-single-vector timer_tick-ia32
   INTERFACES_KERNEL     += hpet
 endif
 
@@ -266,7 +261,7 @@ ASSRC_CRT0          := crt0.S
 #
 # BOOT subsystem
 #
-BOOT                   := main
+BOOT                   := fiasco
 VPATH                  += boot/$(CONFIG_XARCH) boot
 PRIVATE_INCDIR                 += boot boot/amd64
 CXXSRC_BOOT            := boot_libc_glue.cc bootstrap.cc boot_cpu.cc \
index a8c05489ff5079b91b130023f98c5ec16447d032..2e75b027bbabaf901004b320fadb6847ba8ffa23 100644 (file)
@@ -9,7 +9,7 @@ SUBSYSTEMS :=   ABI KERNEL LIBK DRIVERS MINILIBC \
 
 
 PREPROCESS_PARTS       += arch $(CONFIG_ABI) 32bit $(CONFIG_XARCH) \
-                           h3800 noncont_mem abs_syscalls
+                           h3800 abs_syscalls
 
 PREPROCESS_PARTS-$(CONFIG_SERIAL)             += serial
 PREPROCESS_PARTS-$(CONFIG_MP)                 += mp
@@ -27,29 +27,26 @@ PREPROCESS_PARTS-$(CONFIG_ARM_V7)                   += armv7
 PREPROCESS_PARTS-$(CONFIG_ARM_1136)                 += arm1136
 PREPROCESS_PARTS-$(CONFIG_ARM_1176)                 += arm1176
 PREPROCESS_PARTS-$(CONFIG_ARM_MPCORE)               += mpcore
+PREPROCESS_PARTS-$(CONFIG_ARM_CORTEX_A7)            += armca9
 PREPROCESS_PARTS-$(CONFIG_ARM_CORTEX_A8)            += armca8
 PREPROCESS_PARTS-$(CONFIG_ARM_CORTEX_A9)            += armca9
-PREPROCESS_PARTS-$(CONFIG_ARM_TZ)                   += tz
+PREPROCESS_PARTS-$(CONFIG_ARM_CORTEX_A15)           += armca9
+PREPROCESS_PARTS-$(CONFIG_ARM_EM_TZ)                += arm_em_tz
+PREPROCESS_PARTS-$(CONFIG_ARM_EM_STD)               += arm_em_std
+PREPROCESS_PARTS-$(CONFIG_ARM_EM_NS)                += arm_em_ns
+PREPROCESS_PARTS-$(CONFIG_ARM_SECMONIF_MC)          += arm_smif_mc
+PREPROCESS_PARTS-$(CONFIG_ARM_SECMONIF_LP)          += arm_smif_lp
+PREPROCESS_PARTS-$(CONFIG_ARM_SECMONIF_TL)          += arm_smif_tl
 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
+PREPROCESS_PARTS-$(CONFIG_ARM_LPAE)          += arm_lpae
+PREPROCESS_PARTS-$(CONFIG_CPU_VIRT)                 += hyp
+PREPROCESS_PARTS-y$(CONFIG_CPU_VIRT)                += noncont_mem
 
 
-OBJ_SPACE-y = phys
-OBJ_SPACE-  = virt
-OBJ_SPACE   = $(OBJ_SPACE-$(CONFIG_DISABLE_VIRT_OBJ_SPACE))
-
-
-ifeq ("$(CONFIG_ARM_1176)@$(CONFIG_ARM_1176_CACHE_ALIAS_FIX)","y@")
-OBJ_SPACE_TYPE = phys
-else
-OBJ_SPACE_TYPE = $(if $(CONFIG_ARM_V6PLUS),$(OBJ_SPACE),phys)
-endif
-
-PREPROCESS_PARTS       += obj_space_$(OBJ_SPACE_TYPE)
-
 #
 # TYPES subsystem
 #
@@ -137,24 +134,24 @@ kip_IMPL  := kip kip-debug kip-arm
 # KERNEL subsystem
 #
 KERNEL                 := fiasco
-KERNEL_EXTRA   := Symbols
+KERNEL_EXTRA   := Symbols kernel.arm.lds
 VPATH          += kern/$(CONFIG_XARCH) kern
 VPATH          += jdb/arm jdb
 PRIVATE_INCDIR         += kern/$(CONFIG_XARCH) kern
 
-INTERFACES_KERNEL +=   __main mem_op pagetable kmem_space boot_uart_init     \
+INTERFACES_KERNEL +=   __main mem_op kmem_space boot_uart_init     \
                        irq_chip_generic bootstrap kern_lib_page              \
                        jdb_extensions outer_cache utcb_support cascade_irq   \
-                       irq_mgr_multi_chip
+                       irq_mgr_multi_chip scu
 
 INTERFACES_KERNEL-$(CONFIG_SERIAL) += uart_console
-INTERFACES_KERNEL-$(CONFIG_ARM_TZ) += vm
+INTERFACES_KERNEL-$(CONFIG_ARM_EM_TZ) += vm
 
-INTERFACES_KERNEL += $(INTERFACES_KERNEL-y)
 
 
 boot_info_IMPL         := boot_info boot_info-arch
 bootstrap_IMPL         := bootstrap
+CXXFLAGS_bootstrap      := -O3
 clock_IMPL              := clock
 config_IMPL            := config config-arm
 context_IMPL           := context context-arm context-vcpu
@@ -174,14 +171,13 @@ mapping_IMPL              := mapping-arm mapping
 mem_layout_IMPL                := mem_layout mem_layout-arm mem_layout-noncont
 mem_space_IMPL         := mem_space mem_space-arm mem_space-user
 kmem_alloc_IMPL                := kmem_alloc kmem_alloc-arm
-obj_space_IMPL          := obj_space obj_space-$(OBJ_SPACE_TYPE)
 outer_cache_IMPL       := outer_cache outer_cache-l2cxx0
-pagetable_IMPL         := pagetable pagetable-arch
 paging_IMPL            := paging-arm paging
 perf_cnt_IMPL          := perf_cnt perf_cnt-arm
 pic_IMPL               := pic
 sched_context_IMPL     := sched_context-wfq sched_context-fixed_prio \
                           sched_context-fp_wfq sched_context
+scu_IMPL                := scu
 space_IMPL             := space space-arm
 spin_lock_IMPL         := spin_lock spin_lock-arm
 startup_IMPL           := startup startup-arm
@@ -196,6 +192,7 @@ timer_tick_IMPL             := timer_tick timer_tick-arm
 utcb_init_IMPL         := utcb_init utcb_init-arm
 utcb_support_IMPL       := utcb_support utcb_support-arm
 vmem_alloc_IMPL                := vmem_alloc vmem_alloc-arch
+vm_factory_IMPL         := vm_factory vm_factory-arm
 tb_entry_IMPL          := tb_entry tb_entry-arm
 vcpu_IMPL               := vcpu vcpu-arm
 
@@ -245,12 +242,12 @@ ifneq ($(CONFIG_JDB_GZIP),)
  endif
 endif
 
-INTERFACES_JDB         += $(INTERFACES_JDB-y)
 endif
 
 CXXSRC_KERNEL          := kernel_panic.cc libc_backend_lock.cc
 ASSRC_KERNEL           := ivt.S $(if $(CONFIG_MP),tramp-mp.S)
 CPPFLAGS                += $(if $(CONFIG_MP),-DMPCORE_PHYS_BASE=$(MPCORE_PHYS_BASE))
+CPPFLAGS                += -DRAM_PHYS_BASE=$(RAM_PHYS_BASE)
 
 NOOPT                  += $(filter jdb%,\
                             $(foreach in,$(INTERFACES_KERNEL), \
@@ -323,11 +320,15 @@ endif
 include $(MODULES_FILE_BSP)
 VPATH += kern/arm/bsp/$(BSP_NAME)
 PREPROCESS_PARTS       += $(PREPROCESS_PARTS-y)
+INTERFACES_KERNEL       += $(INTERFACES_KERNEL-y)
+INTERFACES_JDB         += $(INTERFACES_JDB-y)
 
 ifeq ("$(filter LIBUART, $(SUBSYSTEMS))","LIBUART")
   LIBUART                      := uart/libuart.a
 endif
 
+CONFIG_KERNEL_LOAD_ADDR := $(RAM_PHYS_BASE)
+
 ifneq ($(CONFIG_MP),)
 ifeq ($(MPCORE_PHYS_BASE),)
 $(error $(MODULES_FILE_BSP) needs to set MPCORE_PHYS_BASE variable)
index 3ef2df7c5c17c7e1b9d02038aa140865dedd3eba..c652594fd48cdfa219f4e6fb5057e27d8670639b 100644 (file)
@@ -4,6 +4,7 @@ INTERFACES_KERNEL       := cpu_mask rcupdate kobject_mapdb context_base \
                           mapping spin_lock mapping_tree mappable           \
                           dbg_page_info mapdb pic kobject_dbg koptions      \
                           kobject_iface kobject ready_queue_wfq             \
+                           obj_space_types obj_space_phys_util \
                           ready_queue_fp obj_space ptab_base ram_quota      \
                           ref_ptr ref_obj mem_space space  \
                           vlog kmem kmem_alloc slab_cache mem_layout        \
@@ -25,6 +26,13 @@ INTERFACES_KERNEL    := cpu_mask rcupdate kobject_mapdb context_base \
                           buddy_alloc vkey kdb_ke prio_list ipi scheduler   \
                           clock vm_factory sys_call_page boot_alloc
 
+OBJ_SPACE_TYPE = $(if $(CONFIG_VIRT_OBJ_SPACE),virt,phys)
+PREPROCESS_PARTS-y$(CONFIG_VIRT_OBJ_SPACE) = obj_space_phys
+PREPROCESS_PARTS += obj_space_$(OBJ_SPACE_TYPE)
+INTERFACES_KERNEL-$(CONFIG_VIRT_OBJ_SPACE) += obj_space_virt_util
+obj_space_IMPL = obj_space obj_space-$(OBJ_SPACE_TYPE)
+
+
 platform_control_IMPL   := platform_control
 
 syscalls_IMPL          := syscalls syscalls-log
index a790224e705a630f7f0e5531f575502c95ff0198..d67205a49ffa58599449f63d6f0ec4e9ff9a8bfe 100644 (file)
@@ -14,12 +14,6 @@ PREPROCESS_PARTS     += arch $(CONFIG_ABI) 32bit iofp         \
                           i8259 pc i8254 fpu                    \
                           abs_syscalls auto_map_kip io
 
-OBJ_SPACE-y = phys
-OBJ_SPACE-  = virt
-OBJ_SPACE   = $(OBJ_SPACE-$(CONFIG_DISABLE_VIRT_OBJ_SPACE))
-
-PREPROCESS_PARTS += obj_space_$(OBJ_SPACE)
-
 PREPROCESS_PARTS-$(CONFIG_MP)                += mp
 PREPROCESS_PARTS-$(CONFIG_LIST_ALLOC_SANITY) += list_alloc_debug
 PREPROCESS_PARTS-$(CONFIG_JDB)               += debug log
@@ -30,7 +24,7 @@ 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_CPU_VIRT)          += svm vmx
+PREPROCESS_PARTS-$(CONFIG_CPU_VIRT)          += svm vmx virtual_space_iface
 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
@@ -94,7 +88,7 @@ INTERFACES_KERNEL     += __main acpi irq_chip_ia32 irq_chip_pic io_apic \
                           io_space apic pit checksum x86desc gdt idt tss \
                           timer_irq dirq
 
-INTERFACES_KERNEL-$(CONFIG_CPU_VIRT) += svm vmx vm vm_svm vm_vmx
+INTERFACES_KERNEL-$(CONFIG_CPU_VIRT) += svm vmx vm vm_svm vm_vmx vm_vmx_ept
 
 apic_IMPL              := apic-ia32 apic-ia32-mp
 boot_console_IMPL      := boot_console-ia32-amd64
@@ -121,7 +115,6 @@ map_util_IMPL               := map_util map_util-mem map_util-io map_util-objs
 mem_layout_IMPL                := mem_layout mem_layout-ia32 mem_layout-ia32-32
 mem_space_IMPL         := mem_space mem_space-user mem_space-ia32
 mem_unit_IMPL          := mem_unit-ia32
-obj_space_IMPL          := obj_space obj_space-$(OBJ_SPACE)
 paging_IMPL            := paging-ia32-32 paging-ia32 paging
 perf_cnt_IMPL          := perf_cnt perf_cnt-ia32
 pic_IMPL               := pic pic-i8259
@@ -267,7 +260,7 @@ ASSRC_CRT0          := crt0.S
 #
 # BOOT subsystem
 #
-BOOT                   := main
+BOOT                   := fiasco
 VPATH                  += boot/$(CONFIG_XARCH) boot
 PRIVATE_INCDIR                 += boot boot/ia32
 CXXSRC_BOOT            := boot_libc_glue.cc bootstrap.cc boot_cpu.cc \
index 1c6294eca1c00058df70b8d4ec609a4c81af5bdf..cbf0155a70695c07942f8c1b8086c4f137d3811f 100644 (file)
@@ -96,9 +96,10 @@ INTERFACES_KERNEL    := mem_region simpleio kernel_console panic warn \
                           sched_context switch_lock timer timeout        \
                           obj_space kobject_dbg kobject kobject_iface    \
                           l4_buf_iter lock  \
+                           obj_space_types obj_space_phys_util \
                           mem_space space vcpu context \
                           helping_lock \
-                          mp_lock ipc_gate irq_controller                \
+                          mp_lock             \
                           mapping mapping_tree mappable                  \
                           mapdb kobject_mapdb map_util \
                           hostproc task sigma0_task kernel_task prio_list \
@@ -106,7 +107,7 @@ INTERFACES_KERNEL   := mem_region simpleio kernel_console panic warn \
                           ipc_timeout thread_state       \
                           sender receiver ipc_sender thread thread_object \
                           kobject_helper timer_tick platform_control     \
-                          syscalls                                       \
+                          syscalls ipc_gate irq_controller \
                           kernel_thread dirq irq_chip irq_mgr \
                           irq_chip_ia32 irq_chip_pic  \
                           banner fpu_alloc irq icu_helper main           \
@@ -335,7 +336,7 @@ endif
 # UNITTEST subsystem
 #
 # disabled until unittests fixed
-ifeq (1,2)
+ifeq (0,1)
 SUBSYSTEMS             += UNITTEST
 VPATH                  += test/unit
 
index 346574bc88a1b22c131ef3f7fdbe0337d39957db..0a6e4e4c59e451a748ffdfee74c206275659695d 100644 (file)
@@ -147,7 +147,7 @@ void Kip::init_global_kip(Kip *kip)
   global_kip = kip;
 
   // check that the KIP has actually been set up
-  assert(kip->sigma0_ip && kip->root_ip && kip->user_ptr);
+  //assert(kip->sigma0_ip && kip->root_ip && kip->user_ptr);
 }
 
 PUBLIC static inline Kip *Kip::k() { return global_kip; }
index b157a4ff1db3ae8329f14fb2e190e04756fc5e7b..dd45bef1f409fa1b5adc74fb5325f3f41596252f 100644 (file)
@@ -1,7 +1,7 @@
 INTERFACE:
 
 #include "types.h"
-#include <bitfield>
+#include <cxx/bitfield>
 
 /**
  * Description of the mapping buffer registers contained in the UTCB 
index 4c774a9e946d9756cb2704f6b2c9acaec3562992..4e06cd21f8ead0701fd5e74e06d2e649f4c68aec 100644 (file)
@@ -1,8 +1,17 @@
 INTERFACE:
 
 #include "types.h"
+#include <cxx/bitfield>
+#include <cxx/cxx_int>
 
-#include <bitfield>
+/// Difference between two capability indexes
+typedef cxx::int_type_order<Mword, struct Cap_diff_t, Order> Cap_diff;
+
+/// A capability index
+typedef cxx::int_type_full<Mword, struct Cap_index_t, Cap_diff, Order> Cap_index;
+
+/// IA32 I/O port numbers
+typedef cxx::int_type_order<unsigned long, struct Port_number_t, Order> Port_number;
 
 /**
  * A L4 flex page.
@@ -57,17 +66,95 @@ public:
 
   enum { Addr_shift = 12 };
 
+  struct Rights
+  : cxx::int_type_base<unsigned char, Rights>,
+    cxx::int_bit_ops<Rights>,
+    cxx::int_null_chk<Rights>
+  {
+    Rights() = default;
+    explicit Rights(unsigned char v)
+    : cxx::int_type_base<unsigned char, Rights>(v) {}
+
+    Rights apply(Rights r) const { return *this & r; }
+
+    /// Memory flex page is user accessible
+    static Rights U() { return Rights(8); }
+
+    /// Memory flex page is readable
+    static Rights R() { return Rights(4); }
+
+    /// Memory flex page is writable
+    static Rights W() { return Rights(2); }
+
+    /// Memory flex page is executable (often equal to #R)
+    static Rights X() { return Rights(1); }
+
+    static Rights UR() { return U() | R(); }
+    static Rights URX() { return U() | R() | X(); }
+    static Rights URWX() { return U() | R() | W() | X(); }
+    static Rights URW() { return U() | R() | W(); }
+
+    /// Memory flex page is readable and executable
+    static Rights RX() { return R() | X(); }
+
+    /// Memory flex page is readable, writeable, and executable
+    static Rights RWX() { return R() | W() | X(); }
+
+    /// Memory flex page is readable and writable
+    static Rights RW() { return R() | W(); }
+
+    ///< Memory flex page is writable and executable
+    static Rights WX() { return W() | X(); }
+
+
+    /// Object flex page: delete rights
+    static Rights CD() { return Rights(0x8); }
+
+    /// Object flex page: read rights (w/o this the mapping is not present)
+    static Rights CR() { return Rights(0x4); }
+
+    /** Object flex page: strong semantics (object specific, i.e. not having
+     *  this right on an IPC gate demotes all capabilities transferred via this
+     *  IPC gate to also suffer this right. */
+    static Rights CS() { return Rights(0x2); }
+
+    /// Object flex page: write rights (purely object specific)
+    static Rights CW() { return Rights(0x1); }
+
+    /// Object flex page: combine #CR and #CW
+    static Rights CRW() { return CR() | CW(); }
+
+    /// Object flex page: combine #CR and #CS
+    static Rights CRS() { return CR() | CS(); }
+
+    /// Object flex page: combine #CR, #CW, and #CS
+    static Rights CRWS() { return CRW() | CS(); }
+
+    /// Object flex page: combine #CS and #CW
+    static Rights CWS() { return CW() | CS(); }
+
+    /// Object flex page: combine #CS, #CW, and #CD
+    static Rights CWSD() { return CW() | CS() | CD(); }
+
+    /// Object flex page: combine #CR, #CW, #CS, and #CD
+    static Rights CRWSD() { return CRWS() | CD(); }
+
+    /// All rights shall be transferred, independent of the type
+    static Rights FULL() { return Rights(0xf); }
+  };
+
 private:
   /**
    * Create a flex page with the given parameters.
    */
   L4_fpage(Type type, Mword address, unsigned char order,
-           unsigned char rights)
-  : _raw(  address | rights_bfm_t::val_dirty(rights)
+           Rights rights)
+  : _raw(  address | _rights_bfm_t::val_dirty(cxx::int_value<Rights>(rights))
          | order_bfm_t::val_dirty(order) | type_bfm_t::val_dirty(type))
   {}
 
 public:
+
   enum
   {
     Whole_space = 63 ///< Value to use as \a order for a whole address space.
@@ -83,7 +170,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, adr_bfm_t::val_dirty(port), order, 0); }
+  { return L4_fpage(Io, adr_bfm_t::val_dirty(port), order, Rights(0)); }
 
   /**
    * Create an object flex page.
@@ -93,7 +180,7 @@ public:
    * \param order The size of the flex page is 2^\a order. The value in \a idx
    *              must be aligned to 2^(\a order + #Addr_shift.
    */
-  static L4_fpage obj(Mword idx, unsigned char order, unsigned char rights = 0)
+  static L4_fpage obj(Mword idx, unsigned char order, Rights rights = Rights(0))
   { return L4_fpage(Obj, idx & adr_bfm_t::Mask, order, rights); }
 
   /**
@@ -103,7 +190,7 @@ public:
    *             considered, bits from 0 to \a order-1 are dropped.
    * \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)
+  static L4_fpage mem(Mword addr, unsigned char order, Rights rights = Rights(0))
   { return L4_fpage(Memory, addr & adr_bfm_t::Mask, order, rights); }
 
   /**
@@ -117,7 +204,7 @@ public:
    * all available address spaces at once. This is used
    * for page-fault and exception IPC.
    */
-  static L4_fpage all_spaces(unsigned char rights = 0)
+  static L4_fpage all_spaces(Rights rights = Rights(0))
   { return L4_fpage(Special, 0, Whole_space, rights); }
 
   /**
@@ -154,7 +241,7 @@ public:
    * \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 adr(); }
+  Port_number io_address() const { return (Port_number)(unsigned)adr(); }
 
   /**
    * Get the capability index of an object flex page.
@@ -164,7 +251,7 @@ public:
    *         This value is shifted #Addr_shift to be a real index
    *         (opposed to obj_address()).
    */
-  Mword obj_index() const { return adr(); }
+  Cap_index obj_index() const { return Cap_index((Mword)adr()); }
 
   /**
    * Test for memory flex page (if type() is #Memory).
@@ -209,10 +296,10 @@ public:
 private:
   Raw _raw;
 
-public:
-
   /** \name Rights of the flex page */
-  CXX_BITFIELD_MEMBER( 0,  3, rights, _raw);
+  CXX_BITFIELD_MEMBER( 0,  3, _rights, _raw);
+
+public:
   /** \name Type of the flex page */
   CXX_BITFIELD_MEMBER( 4,  5, type, _raw);
   /** \name Size (as power of 2) of the flex page */
@@ -222,6 +309,9 @@ private:
   CXX_BITFIELD_MEMBER(12, MWORD_BITS-1, adr, _raw);
 
 public:
+
+  Rights rights() const { return Rights(_rights()); }
+
   /**
    * Rights bits for flex pages.
    *
@@ -231,40 +321,13 @@ public:
    * there are #CD, #CR, #CS, and #CW rights on the object and additional
    * rights in the map control value of the map operation (see L4_fpage::Obj_map_ctl).
    */
-  enum Rights
-  {
-    R   = 4, ///< Memory flex page is readable
-    W   = 2, ///< Memory flex page is writable
-    X   = 1, ///< Memory flex page is executable (often equal to #R)
-
-    RX  = R | X,     ///< Memory flex page is readable and executable
-    RWX = R | W | X, ///< Memory flex page is readable, writeable, and executable
-    RW  = R | W,     ///< Memory flex page is readable and writable
-    WX  = W | X,     ///< Memory flex page is writable and executable
-
-
-    CD    = 0x8, ///< Object flex page: delete rights
-    CR    = 0x4, ///< Object flex page: read rights (w/o this the mapping is not present)
-    CS    = 0x2, ///< Object flex page: strong semantics (object specific, i.e. not having
-                 ///  this right on an IPC gate demotes all capabilities transferred via this
-                 ///  IPC gate to also suffer this right.
-    CW    = 0x1, ///< Object flex page: write rights (purely object specific)
-
-    CRW   = CR | CW,       ///< Object flex page: combine #CR and #CW
-    CRS   = CR | CS,       ///< Object flex page: combine #CR and #CS
-    CRWS  = CRW | CS,      ///< Object flex page: combine #CR, #CW, and #CS
-    CWS   = CW | CS,       ///< Object flex page: combine #CS and #CW
-    CWSD  = CW | CS | CD,  ///< Object flex page: combine #CS, #CW, and #CD
-    CRWSD = CRWS | CD,     ///< Object flex page: combine #CR, #CW, #CS, and #CD
-
-    FULL  = 0xf, ///< All rights shall be transferred, independent of the type
-  };
+
 
   /**
    * 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) | ~rights_bfm_t::Mask); }
+  void mask_rights(Rights r) { _raw &= (Mword(cxx::int_value<Rights>(r)) | ~_rights_bfm_t::Mask); }
 };
 
index a5df29e447dbb245b912b0cb1ab86635dc6ce9ee..6d537dc83270e3d6462548a6a4223f8da4e5b407 100644 (file)
@@ -2,7 +2,7 @@ INTERFACE:
 
 #include "types.h"
 #include "l4_fpage.h"
-#include <bitfield>
+#include <cxx/bitfield>
 
 /**
  * The first word of a message item, either a send item or a receive buffer.
@@ -93,14 +93,22 @@ public:
    *
    * These flags are to control the caching attributes of memory mappings.
    */
-  enum Memory_attribs
+  struct Memory_type
+  : cxx::int_type_base<unsigned char, Memory_type>,
+    cxx::int_bit_ops<Memory_type>
   {
-    Caching_opt = 0x10, ///< This flag denotes the presence of a cachability option
-    Cached      = 0x30, ///< Map the memory cachable
-    Buffered    = 0x50, ///< Map the memory bufferable (write combining in Intel speech)
-    Uncached    = 0x10, ///< Map the memory fully uncachable
+    Memory_type() = default;
+    explicit Memory_type(unsigned char v)
+    : cxx::int_type_base<unsigned char, Memory_type>(v) {}
+
+    static Memory_type Set() { return Memory_type(0x10); }
+    static Memory_type Normal() { return Memory_type(0x20); }
+    static Memory_type Buffered() { return Memory_type(0x40); }
+    static Memory_type Uncached() { return Memory_type(0x00); }
   };
 
+  Memory_type mem_type() const { return Memory_type(attr() & 0x70); }
+
   enum Type
   {
     Map    = 8,
@@ -167,7 +175,8 @@ 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); }
+  L4_fpage get_small_buf()
+  { return L4_fpage::obj(_raw, 0, L4_fpage::Rights(attr() >> 4)); }
 
   /**
    * Create a map item.
index 6c629e1945df4e21042868c81d44618e11ff8a71..7da85c2821eb37f34a8039e5921a52e051ec830f 100644 (file)
@@ -223,7 +223,7 @@ public:
    * \return The index into the capability table stored in the capability
    *         selector (i.e., the most significant bits of the selector).
    */
-  unsigned long cap() const { return _raw >> 12; }
+  Cap_index cap() const { return Cap_index(_raw >> 12); }
 
   /**
    * Get the operation stored in this selector (see L4_obj_ref::Operation).
@@ -245,6 +245,8 @@ public:
    * \param op the operation to be encoded in bits 0..3.
    */
   explicit L4_obj_ref(Mword cap, Operation op = None) : _raw(cap | op) {}
+  explicit L4_obj_ref(Cap_index cap, Operation op = None)
+  : _raw((cxx::int_value<Cap_index>(cap) << L4_obj_ref::Cap_shift) | op) {}
 
   /**
    * Create a capability selector (index 0) with the given operation.
@@ -582,8 +584,11 @@ private:
   Mword _w;
 
 public:
-  Mword offset() const { return (_w & 0x00ffffff) & (~0 << granularity()); }
-  Mword granularity() const { return (_w >> 24) & (MWORD_BITS-1) ; }
+  Order granularity() const
+  { return Order((_w >> 24) & (MWORD_BITS-1)) ; }
+
+  Cpu_number offset() const
+  { return cxx::mask_lsb(Cpu_number(_w & 0x00ffffff), granularity()); }
 };
 
 class L4_cpu_set : public L4_cpu_set_descr
@@ -592,33 +597,33 @@ private:
   Mword _map;
 
 public:
-  bool contains(unsigned cpu) const
+  bool contains(Cpu_number cpu) const
   {
     if (offset() > cpu)
       return false;
 
     cpu -= offset();
     cpu >>= granularity();
-    if (cpu >= MWORD_BITS)
+    if (cpu >= Cpu_number(MWORD_BITS))
       return false;
 
-    return _map & (1UL << cpu);
+    return (_map >> cxx::int_value<Cpu_number>(cpu)) & 1;
   }
 
   template<typename MAP>
-  Mword first(MAP const &bm, unsigned max) const
+  Cpu_number first(MAP const &bm, Cpu_number max) const
   {
-    unsigned cpu = offset();
+    Cpu_number cpu = offset();
 
     for (;;)
       {
-        unsigned b = (cpu - offset()) >> granularity();
-        if (cpu >= max || b >= MWORD_BITS)
+        Cpu_number b = (cpu - offset()) >> granularity();
+        if (cpu >= max || b >= Cpu_number(MWORD_BITS))
           return max;
 
-        if (!(_map & (1UL << b)))
+        if (!((_map >> cxx::int_value<Cpu_number>(b)) & 1))
           {
-            cpu += 1UL << granularity();
+            cpu += Cpu_number(1) << granularity();
             continue;
           }
 
index cdafb985e20cf8ff88152c888398c99474444d5c..2039c3a33f4ec2c4c119392d59a2763ebbdddb8a 100644 (file)
@@ -30,8 +30,9 @@ $(KERNEL):    kernel.amd64.lds boot_img.o $(CRT0) $(OBJ_KERNEL) $(JDB) $(LIBK) $(KE
                $(VERBOSE)$(LD) -m elf_x86_64 -N -T $< -gc-sections \
                -o $@ $(filter-out $<,$+) $(LIBGCC) $(KERNEL_UNRES_SYMS)
 
+# '$(RM) main' should be removed later - Late 2012
 $(BOOT): $(KERNEL)
                $(LINK_MESSAGE)
                $(VERBOSE)$(STRIP) -o $@ $<
                $(VERBOSE)chmod 755 $@
-               $(VERBOSE)ln -sf $@ fiasco
+               $(VERBOSE)$(RM) main
index 1d4a6c05a3f18c782495d0ccd4c9382685adf820..1621318401b2950dffe78536229251fac61af911 100644 (file)
@@ -221,7 +221,7 @@ extern inline Unsigned16 get_ss()
 
 
 extern inline void enable_longmode()
-{ Proc::efer(Proc::efer() | Proc::Efer_lme_flag); }
+{ Proc::efer(Proc::efer() | Proc::Efer_lme_flag | Proc::Efer_nxe_flag); }
 
 static inline void
 fill_descriptor(struct x86_desc *desc, Unsigned32 base, Unsigned32 limit,
index 0e423067134a9632a7cbd6739cee2d99c82c124f..a8489133445438ead9bcb3d2962c4bb47a7422cd 100644 (file)
@@ -33,7 +33,4 @@ static inline Address trunc_page(Address x)
 static inline Address round_page(Address x)
 { return (x + PAGE_MASK) & ~PAGE_MASK; }
 
-static inline Address round_superpage(Address x)
-{ return (x + SUPERPAGE_MASK) & ~SUPERPAGE_MASK; }
-
 #endif
index 1eb498aece2175d89d7aa5c8107bec7122796aa8..3e0600cb1cc23ad6527334a09a37f97d08e1ae00 100644 (file)
@@ -36,8 +36,9 @@ $(KERNEL):    kernel.ia32.lds boot_img.o $(CRT0) $(OBJ_KERNEL) $(JDB) $(LIBK) $(KER
                   -T $< -gc-sections $(filter-out $<,$+) \
                   $(KERNEL_UNRES_SYMS)
 
+# '$(RM) main' should be removed later - Late 2012
 $(BOOT): $(KERNEL)
                $(LINK_MESSAGE)
                $(VERBOSE)$(STRIP) -o $@ $<
                $(VERBOSE)chmod 755 $@
-               $(VERBOSE)ln -sf $@ fiasco
+               $(VERBOSE)$(RM) main
index 9e899161a1364a7776ede381972c97f50ea1bac2..0f5b50dbc4c537888b8a6986f497881ce8bfdf1d 100644 (file)
@@ -15,16 +15,10 @@ static inline int
 superpage_aligned(Address x)
 { return (x & SUPERPAGE_MASK) == 0; }
 
-static inline Address trunc_superpage(Address x)
-{ return x & ~SUPERPAGE_MASK; }
-
 static inline Address trunc_page(Address x)
 { return x & ~PAGE_MASK; }
 
 static inline Address round_page(Address x)
 { return (x + PAGE_MASK) & ~PAGE_MASK; }
 
-static inline Address round_superpage(Address x)
-{ return (x + SUPERPAGE_MASK) & ~SUPERPAGE_MASK; }
-
 #endif
index cf445f3e64b1be55f68bd8a22677e02f721ec935..3b2723885660dcb53336f075bf3cbb0acddf489f 100644 (file)
@@ -2,20 +2,13 @@ INTERFACE:
 
 #include "mem.h"
 #include "std_macros.h"
+#include "processor.h"
 
 EXTENSION class Mmu
 {
 public:
   static void btc_flush();
   static void btc_inv();
-
-  enum
-  {
-    Cache_line_size = 32,
-    Cache_line_mask = Cache_line_size - 1,
-    Icache_line_size = 32,
-    Icache_line_mask = Icache_line_size - 1,
-  };
 };
 
 //---------------------------------------------------------------------------
@@ -44,6 +37,24 @@ template < unsigned long Flush_area, bool Ram >
 void Mmu<Flush_area, Ram>::btc_inv()
 { asm volatile ("mcr p15, 0, %0, c7, c5, 0" : : "r" (0) : "memory"); }
 
+//-----------------------------------------------------------------------------
+IMPLEMENTATION [arm && (mpcore || arm1136 || arm1176 || pxa || sa1100 || 926 || arm920t)]:
+
+PUBLIC static inline
+template< unsigned long Flush_area, bool Ram >
+Mword Mmu<Flush_area, Ram>::dcache_line_size()
+{
+  return 32;
+}
+
+PUBLIC static inline
+template< unsigned long Flush_area, bool Ram >
+Mword
+Mmu<Flush_area, Ram>::icache_line_size()
+{
+  return 32;
+}
+
 // ---------------------------------------------------------------------------
 IMPLEMENTATION [arm && arm920t]:
 
@@ -84,6 +95,7 @@ IMPLEMENT
 template< unsigned long Flush_area, bool Ram >
 FIASCO_NOINLINE void Mmu<Flush_area, Ram>::inv_dcache(void const *start, void const *end)
 {
+  (void)start; (void)end;
   // clean && invalidate dcache  ||| XXX: all
 #if 1
   for (unsigned long index = 0; index < (1 << (32 - 26)); ++index)
@@ -95,7 +107,6 @@ FIASCO_NOINLINE void Mmu<Flush_area, Ram>::inv_dcache(void const *start, void co
 #endif
 }
 
-
 // ---------------------------------------------------------------------------
 IMPLEMENTATION [arm && (pxa || sa1100 || 926)]:
 
@@ -122,7 +133,7 @@ FIASCO_NOINLINE void Mmu<Flush_area, Ram>::clean_dcache(void const *start, void
          "    cmp  %0, %1                 \n"
          "    blo  1b                     \n"
          "    mcr  p15, 0, %0, c7, c10, 4 \n" // drain WB
-         : : "r" (start), "r" (end), "i" (Cache_line_size)
+         : : "r" (start), "r" (end), "i" (dcache_line_size())
          );
     }
 }
@@ -150,7 +161,7 @@ FIASCO_NOINLINE void Mmu<Flush_area, Ram>::flush_dcache(void const *start, void
          "    cmp  %0, %1                 \n"
          "    blo  1b                     \n"
          "    mcr  p15, 0, %0, c7, c10, 4 \n" // drain WB
-         : : "r" (start), "r" (end), "i" (Cache_line_size)
+         : : "r" (start), "r" (end), "i" (dcache_line_size())
          );
     }
 }
@@ -166,10 +177,31 @@ FIASCO_NOINLINE void Mmu<Flush_area, Ram>::inv_dcache(void const *start, void co
          "    add  %0, %0, %2             \n"
          "    cmp  %0, %1                 \n"
          "    blo  1b                     \n"
-         : : "r" (start), "r" (end), "i" (Cache_line_size)
+         : : "r" (start), "r" (end), "i" (dcache_line_size())
          );
 }
 
+//-----------------------------------------------------------------------------
+IMPLEMENTATION [arm && (armca8 || armca9)]:
+
+PUBLIC static inline
+template< unsigned long Flush_area, bool Ram >
+Mword Mmu<Flush_area, Ram>::dcache_line_size()
+{
+  Mword v;
+  __asm__ __volatile__("mrc p15, 0, %0, c0, c0, 1" : "=r" (v));
+  return 4 << ((v >> 16) & 0xf);
+}
+
+PUBLIC static inline
+template< unsigned long Flush_area, bool Ram >
+Mword Mmu<Flush_area, Ram>::icache_line_size()
+{
+  Mword v;
+  __asm__ __volatile__("mrc p15, 0, %0, c0, c0, 1" : "=r" (v));
+  return 4 << (v & 0xf);
+}
+
 //-----------------------------------------------------------------------------
 IMPLEMENTATION [arm && (mpcore || arm1136 || arm1176 || armca8 || armca9)]:
 
@@ -179,15 +211,15 @@ void Mmu<Flush_area, Ram>::flush_cache(void const *start,
                                       void const *end)
 {
   __asm__ __volatile__ (
-      "1:  mcr p15, 0, %[i], c7, c14, 1  \n"
-      "    mcr p15, 0, %[i], c7, c5, 1   \n"
+      "1:  mcr p15, 0, %[i], c7, c14, 1  \n" // DCCIMVAC
+      "    mcr p15, 0, %[i], c7, c5, 1   \n" // ICIMVAU
       "    add %[i], %[i], %[clsz]       \n"
       "    cmp %[i], %[end]              \n"
       "    blo 1b                        \n"
       : [i]     "=&r" (start)
-      :         "0"   ((unsigned long)start & ~(Cache_line_size - 1)),
+      :         "0"   ((unsigned long)start & ~(dcache_line_size() - 1)),
         [end]   "r"   (end),
-       [clsz]  "i"   (Cache_line_size)
+       [clsz]  "ir"  (dcache_line_size())
       : "r0", "memory");
   btc_inv();
   Mem::dsb();
@@ -199,10 +231,10 @@ void Mmu<Flush_area, Ram>::clean_dcache(void const *va)
 {
   Mem::dsb();
   __asm__ __volatile__ (
-      "mcr p15, 0, %1, c7, c10, 1       \n" // Clean Data Cache Line (using MVA) Register
+      "mcr p15, 0, %1, c7, c10, 1       \n" // DCCMVAC
       :
       : "r" (0),
-        "r"((unsigned long)va & ~(Cache_line_size - 1))
+        "r" ((unsigned long)va & ~(dcache_line_size() - 1))
       : "memory");
 }
 
@@ -213,14 +245,14 @@ void Mmu<Flush_area, Ram>::clean_dcache(void const *start, void const *end)
   Mem::dsb();
   __asm__ __volatile__ (
       // arm1176 only: "    mcrr p15, 0, %2, %1, c12         \n"
-      "1:  mcr p15, 0, %[i], c7, c10, 1   \n" // Clean Data Cache Line (using MVA) Register
+      "1:  mcr p15, 0, %[i], c7, c10, 1   \n" // DCCMVAC
       "    add %[i], %[i], %[clsz]        \n"
       "    cmp %[i], %[end]               \n"
       "    blo 1b                         \n"
       : [i]     "=&r" (start)
-      :         "0"   ((unsigned long)start & ~(Cache_line_size - 1)),
+      :         "0"   ((unsigned long)start & ~(dcache_line_size() - 1)),
         [end]   "r"   (end),
-       [clsz]  "i"   (Cache_line_size)
+       [clsz]  "ir"  (dcache_line_size())
       : "memory");
   btc_inv();
   Mem::dsb();
@@ -237,9 +269,9 @@ void Mmu<Flush_area, Ram>::flush_dcache(void const *start, void const *end)
       "    cmp %[i], %[end]             \n"
       "    blo 1b                       \n"
       : [i]    "=&r" (start)
-      :        "0"   ((unsigned long)start & ~(Cache_line_size - 1)),
+      :        "0"   ((unsigned long)start & ~(dcache_line_size() - 1)),
         [end]  "r"   (end),
-       [clsz] "i"   (Cache_line_size)
+       [clsz] "ir"  (dcache_line_size())
       : "memory");
   btc_inv();
   Mem::dsb();
@@ -256,9 +288,9 @@ void Mmu<Flush_area, Ram>::inv_dcache(void const *start, void const *end)
       "    cmp %[i], %[end]             \n"
       "    blo 1b                       \n"
       : [i]    "=&r" (start)
-      :        "0"   ((unsigned long)start & ~(Cache_line_size - 1)),
+      :        "0"   ((unsigned long)start & ~(dcache_line_size() - 1)),
         [end]  "r"   (end),
-       [clsz] "i"   (Cache_line_size)
+       [clsz] "ir"  (dcache_line_size())
       : "memory");
   btc_inv();
   Mem::dsb();
@@ -311,104 +343,96 @@ private:
   struct set_way_dcache_flush_op
   {
     void operator()(Mword v) const
-    { // clean+inv data cache by set/way
-      __asm__ __volatile__
-        ( "mcr p15, 0, %0, c7, c14, 2" : : "r"(v) : "memory");
+    { // DCCISW
+      asm volatile("mcr p15, 0, %0, c7, c14, 2" : : "r" (v) : "memory");
     }
   };
 
   struct set_way_dcache_clean_op
   {
     void operator()(Mword v) const
-    { // clean data cache by set/way
-      __asm__ __volatile__
-        ( "mcr p15, 0, %0, c7, c10, 2" : : "r"(v) : "memory");
+    { // DCCSW
+      asm volatile("mcr p15, 0, %0, c7, c10, 2" : : "r" (v) : "memory");
     }
   };
-};
 
-//-----------------------------------------------------------------------------
-INTERFACE [arm && armca8]:
-
-EXTENSION class Mmu
-{
-  enum
+  template< typename T >
+  static void
+  __attribute__((optimize("no-unroll-loops")))
+  set_way_full_loop(T const &f)
   {
-    SET_SIZE_16KB = 1 << 12,
-    SET_SIZE_32KB = 1 << 13,
-    SET_SIZE      = SET_SIZE_32KB,
-    SET_INCR      = 1 << 6,
-    WAY_INCR      = 1 << 30,
-    WAY_SIZE      = 4,
-  };
+    Mem::dmb();
+    Mword clidr;
+    asm volatile("mrc p15, 1, %0, c0, c0, 1" : "=r" (clidr));
+    unsigned lvl = (clidr >> 23) & 14;
+
+    for (unsigned cl = 0; cl < lvl; cl += 2)
+      {
+        // data cache only
+        if (((clidr >> (cl + (cl / 2))) & 6) == 0)
+          continue;
+
+        Mword ccsidr;
+          {
+            Proc::Status s = Proc::cli_save();
+            asm volatile("mcr p15, 2, %0, c0, c0, 0" : : "r" (cl));
+            Mem::isb();
+            asm volatile("mrc p15, 1, %0, c0, c0, 0" : "=r" (ccsidr));
+            Proc::sti_restore(s);
+          }
+
+        unsigned assoc       = ((ccsidr >> 3) & 0x3ff);
+        unsigned w_shift     = __builtin_clz(assoc);
+        unsigned set         = ((ccsidr >> 13) & 0x7fff);
+        unsigned log2linelen = (ccsidr & 7) + 4;
+        do
+          {
+            unsigned w = assoc;
+            do
+              f((w << w_shift) | (set << log2linelen) | cl);
+            while (w--);
+          }
+        while (set--);
+      }
+
+    asm volatile("mcr p15, 2, %0, c0, c0, 0" : : "r" (0));
+
+    btc_inv();
+    Mem::dsb();
+    Mem::isb();
+  }
 };
 
 //-----------------------------------------------------------------------------
-INTERFACE [arm && armca9]:
-
-EXTENSION class Mmu
-{
-  enum
-  {
-    SET_SIZE_16KB = 1 << 12,
-    SET_SIZE_32KB = 1 << 13,
-    SET_SIZE_64KB = 1 << 14,
-    SET_SIZE      = SET_SIZE_32KB,
-    SET_INCR      = 1 << 5,
-    WAY_INCR      = 1 << 30,
-    WAY_SIZE      = 4,
-  };
-
-};
-
-//-----------------------------------------
 IMPLEMENTATION [arm && (armca8 || armca9)]:
 
-PRIVATE
-template< unsigned long Flush_area, bool Ram >
-template< typename T >
-static inline
-void Mmu<Flush_area, Ram>::set_way_full_op(T const &f)
-{
-  unsigned wv, w;
-  for (w = 0, wv = 0; w < WAY_SIZE; ++w, wv += WAY_INCR)
-    for (unsigned s = 0; s < SET_SIZE; s += SET_INCR)
-      f(wv | s);
-  btc_inv();
-  __asm__ __volatile__ ("dsb; isb");
-}
-
 IMPLEMENT
 template< unsigned long Flush_area, bool Ram >
 void Mmu<Flush_area, Ram>::flush_dcache()
 {
-  __asm__ __volatile__("dsb");
-  set_way_full_op(set_way_dcache_flush_op());
+  Mem::dsb();
+  set_way_full_loop(set_way_dcache_flush_op());
 }
 
-
 IMPLEMENT
 template< unsigned long Flush_area, bool Ram >
 void Mmu<Flush_area, Ram>::flush_cache()
 {
-  __asm__ __volatile__ (
-      "    dsb       \n"
-      // Invalidate Entire Instruction Cache Register + BTC
-      "    mcr p15, 0, r0, c7, c5, 0 \n"
-      : : : "memory");
+  Mem::dsb();
+  asm volatile("mcr p15, 0, r0, c7, c5, 0 \n" // ICIALLU
+               "mcr p15, 0, r0, c7, c5, 6 \n" // BPIALL
+               "mcr p15, 0, r0, c8, c7, 0 \n" // TLBIALL
+               : : : "memory");
 
-  set_way_full_op(set_way_dcache_flush_op());
+  set_way_full_loop(set_way_dcache_flush_op());
 }
 
 IMPLEMENT
 template< unsigned long Flush_area, bool Ram >
 void Mmu<Flush_area, Ram>::clean_dcache()
 {
-  __asm__ __volatile__ (
-      "    dsb       \n" // Drain Synchronization Barrier Register
-      : : : "memory");
-
-  set_way_full_op(set_way_dcache_clean_op());
+  Mem::dsb();
+  set_way_full_loop(set_way_dcache_clean_op());
 }
 
 //-----------------------------------------------------------------------------
@@ -428,7 +452,7 @@ FIASCO_NOINLINE void Mmu<Flush_area, Ram>::flush_cache()
       "     mcr  p15, 0, r0, c7, c7, 0  \n"
       "     mcr  p15, 0, r0, c7, c10, 4 \n" // drain WB
       : "=r" (dummy)
-      : "r" (Flush_area), "i" (Cache_line_size)
+      : "r" (Flush_area), "i" (dcache_line_size())
       : "r0"
       );
 }
@@ -440,12 +464,12 @@ FIASCO_NOINLINE void Mmu<Flush_area, Ram>::clean_dcache()
   register Mword dummy;
   asm volatile (
       "     add %0, %1, #8192 \n" // 8k flush area
-      " 1:  ldr r0, [%1], %2  \n" // 32 bytes cache line size
+      " 1:  ldr r0, [%1], %2  \n"
       "     teq %1, %0        \n"
       "     bne 1b            \n"
       "     mcr  p15, 0, r0, c7, c10, 4 \n" // drain WB
       : "=r" (dummy)
-      : "r" (Flush_area), "i" (Cache_line_size)
+      : "r" (Flush_area), "i" (dcache_line_size())
       : "r0"
       );
 }
@@ -457,20 +481,18 @@ FIASCO_NOINLINE void Mmu<Flush_area, Ram>::flush_dcache()
   register Mword dummy;
   asm volatile (
       "     add %0, %1, #8192           \n" // 8k flush area
-      " 1:  ldr r0, [%1], %2            \n" // 32 bytes cache line size
+      " 1:  ldr r0, [%1], %2            \n"
       "     teq %1, %0                  \n"
       "     bne 1b                      \n"
       "     mov  r0, #0                 \n"
       "     mcr  p15, 0, r0, c7, c6, 0  \n" // inv D cache
       "     mcr  p15, 0, r0, c7, c10, 4 \n" // drain WB
       : "=r" (dummy)
-      : "r" (Flush_area), "i" (Cache_line_size)
+      : "r" (Flush_area), "i" (dcache_line_size())
       : "r0"
       );
-
 }
 
-
 //-----------------------------------------------------------------------------
 IMPLEMENTATION [arm && pxa]:
 
@@ -482,19 +504,19 @@ FIASCO_NOINLINE void Mmu<Flush_area, Ram>::flush_cache()
   asm volatile
     (
      // write back data cache
-     " 1: mcr p15,0,%0,c7,c2,5                           \n\t"
+     " 1: mcr p15, 0, %0, c7, c2, 5                      \n\t"
      "    add %0, %0, #32                                \n\t"
      "    subs %1, %1, #1                                \n\t"
      "    bne 1b                                         \n\t"
      // drain write buffer
-     "    mcr  p15, 0, %0, c7, c7, 0  \n"
+     "    mcr  p15, 0, %0, c7, c7, 0                     \n\t"
      "    mcr p15, 0, r0, c7, c10, 4                     \n\t"
      :
      "=r" (dummy1),
      "=r" (dummy2)
      :
      "0" (Flush_area),
-     "1" (Ram?2048:1024)
+     "1" (Ram ? 2048 : 1024)
     );
 }
 
@@ -506,7 +528,7 @@ FIASCO_NOINLINE void Mmu<Flush_area, Ram>::clean_dcache()
   asm volatile
     (
      // write back data cache
-     " 1: mcr p15,0,%0,c7,c2,5                           \n\t"
+     " 1: mcr p15, 0, %0, c7, c2, 5                      \n\t"
      "    add %0, %0, #32                                \n\t"
      "    subs %1, %1, #1                                \n\t"
      "    bne 1b                                         \n\t"
@@ -517,7 +539,7 @@ FIASCO_NOINLINE void Mmu<Flush_area, Ram>::clean_dcache()
      "=r" (dummy2)
      :
      "0" (Flush_area),
-     "1" (Ram?2048:1024)
+     "1" (Ram ? 2048 : 1024)
     );
 }
 
@@ -529,11 +551,11 @@ FIASCO_NOINLINE void Mmu<Flush_area, Ram>::flush_dcache()
   asm volatile
     (
      // write back data cache
-     " 1: mcr p15,0,%0,c7,c2,5                           \n\t"
+     " 1: mcr p15, 0, %0, c7, c2, 5                      \n\t"
      "    add %0, %0, #32                                \n\t"
      "    subs %1, %1, #1                                \n\t"
      "    bne 1b                                         \n\t"
-     "    mcr  p15, 0, %0, c7, c6, 0  \n" // inv D cache
+     "    mcr  p15, 0, %0, c7, c6, 0                     \n\t" // inv D cache
      // drain write buffer
      "    mcr p15, 0, r0, c7, c10, 4                     \n\t"
      :
@@ -541,7 +563,7 @@ FIASCO_NOINLINE void Mmu<Flush_area, Ram>::flush_dcache()
      "=r" (dummy2)
      :
      "0" (Flush_area),
-     "1" (Ram?2048:1024)
+     "1" (Ram ? 2048 : 1024)
     );
 }
 
@@ -563,7 +585,6 @@ FIASCO_NOINLINE void Mmu<Flush_area, Ram>::flush_cache()
   asm volatile("mcr p15,0,%0,c7,c5,0" : : "r" (0) : "memory");
 }
 
-
 IMPLEMENT
 template< unsigned long Flush_area, bool Ram >
 FIASCO_NOINLINE void Mmu<Flush_area, Ram>::clean_dcache()
@@ -623,12 +644,10 @@ FIASCO_NOINLINE void Mmu<Flush_area, Ram>::flush_dcache()
      // write back data cache
      "1:  mrc p15, 0, r15, c7, c14, 3                    \n\t"
      "    bne 1b                                         \n\t"
-     "    mcr  p15, 0, %0, c7, c6, 0  \n" // inv D cache
+     "    mcr  p15, 0, %0, c7, c6, 0                     \n\t" // inv D cache
      // drain write buffer
      "    mcr p15, 0, %0, c7, c10, 4                     \n\t"
      : :
      "r" (0)
     );
 }
-
-
index d067e37f034f024c5d57dc373ab251f4c422693d..41598371a2e3f3bfc945f46aa41a0ef96b6adbd4 100644 (file)
@@ -2,44 +2,54 @@ INTERFACE[arm]:
 
 EXTENSION class Proc
 {
+private:
+  enum : unsigned
+  {
+    Status_FIQ_disabled        = 0x40,
+    Status_IRQ_disabled        = 0x80,
+  };
+
 public:
-  enum
+  enum : unsigned
   {
     Status_mode_user           = 0x10,
     Status_mode_supervisor     = 0x13,
     Status_mode_mask           = 0x1f,
 
-    Status_FIQ_disabled        = 0x40,
-    Status_IRQ_disabled        = 0x80,
     Status_interrupts_disabled = Status_FIQ_disabled | Status_IRQ_disabled,
-    Status_interrupts_mask     = 0xc0,
     Status_thumb               = 0x20,
   };
 
-  static unsigned cpu_id();
+  static Cpu_phys_id cpu_id();
 };
 
-INTERFACE[arm && !tz]:
+INTERFACE[arm && !arm_em_tz]:
 
 EXTENSION class Proc
 {
 public:
-  enum
+  enum : unsigned
     {
-      Cli_mask = Status_IRQ_disabled,
-      Sti_mask = Status_IRQ_disabled,
+      Cli_mask                = Status_interrupts_disabled,
+      Sti_mask                = Status_interrupts_disabled,
+      Status_preempt_disabled = Status_IRQ_disabled,
+      Status_interrupts_mask  = Status_interrupts_disabled,
+      Status_always_mask      = 0,
     };
 };
 
-INTERFACE[arm && tz]:
+INTERFACE[arm && arm_em_tz]:
 
 EXTENSION class Proc
 {
 public:
-  enum
+  enum : unsigned
     {
-      Cli_mask = Status_IRQ_disabled | Status_FIQ_disabled,
-      Sti_mask = Status_IRQ_disabled | Status_FIQ_disabled,
+      Cli_mask                = Status_FIQ_disabled,
+      Sti_mask                = Status_FIQ_disabled,
+      Status_preempt_disabled = Status_FIQ_disabled,
+      Status_interrupts_mask  = Status_FIQ_disabled,
+      Status_always_mask      = Status_IRQ_disabled,
     };
 };
 
@@ -72,33 +82,38 @@ Mword Proc::program_counter()
 IMPLEMENT static inline
 void Proc::cli()
 {
-  asm volatile ( "    mrs    r6, cpsr    \n"
-                "    orr    r6,r6,%0    \n"
-                "    msr    cpsr_c, r6  \n"
-                : : "i" (Cli_mask) : "r6", "memory"
-                );
+  Mword v;
+  asm volatile("mrs %0, cpsr    \n"
+               "orr %0, %0, %1  \n"
+               "msr cpsr_c, %0  \n"
+               : "=r" (v)
+               : "I" (Cli_mask)
+               : "memory");
 }
 
 IMPLEMENT static inline
 void Proc::sti()
 {
-  asm volatile ( "    mrs    r6, cpsr    \n"
-                 "    bic    r6,r6,%0   \n"
-                "    msr    cpsr_c, r6  \n"
-                : : "i" (Sti_mask) : "r6", "memory"
-                );
+  Mword v;
+  asm volatile("mrs %0, cpsr    \n"
+               "bic %0, %0, %1  \n"
+               "msr cpsr_c, %0  \n"
+               : "=r" (v)
+               : "I" (Sti_mask)
+               : "memory");
 }
 
 IMPLEMENT static inline
 Proc::Status Proc::cli_save()
 {
   Status ret;
-  asm volatile ( "    mrs    r6, cpsr    \n"
-                "    mov    %0, r6      \n"
-                "    orr    r6,r6,%1    \n"
-                "    msr    cpsr_c, r6  \n"
-                : "=r"(ret) : "i" (Cli_mask) : "r6" 
-                );
+  Mword v;
+  asm volatile("mrs    %0, cpsr    \n"
+               "orr    %1, %0, %2  \n"
+               "msr    cpsr_c, %1  \n"
+               : "=r" (ret), "=r" (v)
+               : "I" (Cli_mask)
+               : "memory");
   return ret;
 }
 
@@ -106,23 +121,15 @@ IMPLEMENT static inline
 Proc::Status Proc::interrupts()
 {
   Status ret;
-  asm volatile ("   mrs  %0, cpsr  \n"
-               : "=r"(ret)
-               );
+  asm volatile("mrs %0, cpsr" : "=r" (ret));
   return !(ret & Sti_mask);
 }
 
 IMPLEMENT static inline
 void Proc::sti_restore(Status st)
 {
-  asm volatile ( "    tst    %0, %1      \n"
-                "    bne    1f          \n"
-                "    mrs    r6, cpsr    \n"
-                "    bic    r6,r6,%1    \n"
-                "    msr    cpsr_c, r6  \n"
-                "1:                     \n"
-                : : "r"(st), "i" (Sti_mask) : "r6"
-                );
+  if (!(st & Sti_mask))
+    sti();
 }
 
 IMPLEMENT static inline
@@ -136,18 +143,18 @@ void Proc::irq_chance()
 IMPLEMENTATION[arm && !mp]:
 
 IMPLEMENT static inline
-unsigned Proc::cpu_id()
-{ return 0; }
+Cpu_phys_id Proc::cpu_id()
+{ return Cpu_phys_id(0); }
 
 //----------------------------------------------------------------
 IMPLEMENTATION[arm && mp]:
 
 IMPLEMENT static inline
-unsigned Proc::cpu_id()
+Cpu_phys_id Proc::cpu_id()
 {
   unsigned mpidr;
   __asm__("mrc p15, 0, %0, c0, c0, 5": "=r" (mpidr));
-  return mpidr & 0x7; // mind gic softirq
+  return Cpu_phys_id(mpidr & 0x7); // mind gic softirq
 }
 
 //----------------------------------------------------------------
index da67fd755f3c5a23c6aaee83f6854db760b8f3ce..1d03b6416bde877d731bc61d08b6751f0a8cc834 100644 (file)
@@ -1,53 +1,35 @@
 INTERFACE [sa1100]:
 
 #include "types.h"
+#include "mmio_register_block.h"
 
-template< unsigned long Hw_regs_base >
-class Sa1100_generic 
+class Sa1100 : public Mmio_register_block
 {
 public:
   enum {
-    RSRR = Hw_regs_base + 0x030000,
+    RSRR = 0x030000,
 
     /* interrupt controller */
-    ICIP = Hw_regs_base + 0x050000,
-    ICMR = Hw_regs_base + 0x050004,
-    ICLR = Hw_regs_base + 0x050008,
-    ICCR = Hw_regs_base + 0x05000c,
-    ICFP = Hw_regs_base + 0x050010,
-    ICPR = Hw_regs_base + 0x050020,
+    ICIP = 0x050000,
+    ICMR = 0x050004,
+    ICLR = 0x050008,
+    ICCR = 0x05000c,
+    ICFP = 0x050010,
+    ICPR = 0x050020,
 
     /* OS Timer */
-    OSMR0 = Hw_regs_base + 0x000000,
-    OSMR1 = Hw_regs_base + 0x000004,
-    OSMR2 = Hw_regs_base + 0x000008,
-    OSMR3 = Hw_regs_base + 0x00000c,
-    OSCR  = Hw_regs_base + 0x000010,
-    OSSR  = Hw_regs_base + 0x000014,
-    OWER  = Hw_regs_base + 0x000018,
-    OIER  = Hw_regs_base + 0x00001c,
+    OSMR0 = 0x000000,
+    OSMR1 = 0x000004,
+    OSMR2 = 0x000008,
+    OSMR3 = 0x00000c,
+    OSCR  = 0x000010,
+    OSSR  = 0x000014,
+    OWER  = 0x000018,
+    OIER  = 0x00001c,
 
     RSRR_SWR = 1,
   };
 
-  static inline void  hw_reg( Mword value, Mword reg );
-  static inline Mword hw_reg( Mword reg );
+  Sa1100(Address base) : Mmio_register_block(base) {}
 };
 
-//---------------------------------------------------------------------------
-IMPLEMENTATION [sa1100]:
-
-IMPLEMENT inline
-template< unsigned long Hw_regs_base >
-void Sa1100_generic<Hw_regs_base>::hw_reg( Mword value, Mword reg )
-{
-  *(Mword volatile*)reg = value;
-}
-
-IMPLEMENT inline
-template< unsigned long Hw_regs_base >
-Mword Sa1100_generic<Hw_regs_base>::hw_reg( Mword reg )
-{
-  return *(Mword volatile*)reg;
-}
-
index 412bdb5abab2b06e8910f61050ac5780f7925c59..8530ed528a527ded10df277f8577b1e7f6790763 100644 (file)
@@ -3,7 +3,7 @@ INTERFACE:
 #include "types.h"
 
 /**
- * PC I/O port API.
+ * I/O API.
  */
 class Io
 {
@@ -42,73 +42,77 @@ public:
   template< typename T >
   static void set(T setbits, Address address);
 
+  /**
+   * Write ((read<T>(address) & ~disable) | enable) of type T at address.
+   */
+  template< typename T >
+  static void modify(T enable, T disable, Address address);
+
   /**
    * Read byte port.
    */
-  static Unsigned8  in8 ( unsigned long port );
+  static Unsigned8 in8(unsigned long port);
 
   /**
    * Read 16-bit port.
    */
-  static Unsigned16 in16( unsigned long port );
+  static Unsigned16 in16(unsigned long port);
 
   /**
    * Read 32-bit port.
    */
-  static Unsigned32 in32( unsigned long port );
+  static Unsigned32 in32(unsigned long port);
 
   /**
    * Write byte port.
    */
-  static void out8 ( Unsigned8  val, unsigned long port );
+  static void out8(Unsigned8 val, unsigned long port);
 
   /**
    * Write 16-bit port.
    */
-  static void out16( Unsigned16 val, unsigned long port );
+  static void out16(Unsigned16 val, unsigned long port);
 
   /**
    * Write 32-bit port.
    */
-  static void out32( Unsigned32 val, unsigned long port );
+  static void out32(Unsigned32 val, unsigned long port);
 
   /// @name Delayed versions.
-  //@{ 
+  //@{
 
   /**
    * Read 8-bit port.
    */
-  static Unsigned8  in8_p ( unsigned long port );
+  static Unsigned8 in8_p(unsigned long port);
 
   /**
    * Read 16-bit port.
    */
-  static Unsigned16 in16_p( unsigned long port );
+  static Unsigned16 in16_p(unsigned long port);
 
   /**
    * Read 32-bit port.
    */
-  static Unsigned32 in32_p( unsigned long port );
+  static Unsigned32 in32_p(unsigned long port);
 
   /**
    * Write 8-bit port.
    */
-  static void out8_p ( Unsigned8  val, unsigned long port );
+  static void out8_p(Unsigned8 val, unsigned long port);
 
   /**
    * Write 16-bit port.
    */
-  static void out16_p( Unsigned16 val, unsigned long port );
+  static void out16_p(Unsigned16 val, unsigned long port);
 
   /**
    * Write 32-bit port.
    */
-  static void out32_p( Unsigned32 val, unsigned long port );
+  static void out32_p(Unsigned32 val, unsigned long port);
   //@}
-
 };
 
-
 // ----------------------------------------------------------------------
 IMPLEMENTATION [!ppc32]:
 
@@ -122,6 +126,7 @@ template< typename T>
 void Io::write(T value, Address address)
 { *(volatile T *)address = value; }
 
+// ----------------------------------------------------------------------
 IMPLEMENTATION:
 
 IMPLEMENT inline
@@ -139,7 +144,12 @@ template< typename T>
 void Io::set(T setbits, Address address)
 { write<T>(read<T>(address) | setbits, address); }
 
-
+IMPLEMENT inline
+template< typename T>
+void Io::modify(T enable, T disable, Address address)
+{
+  write<T>((read<T>(address) & ~disable) | enable, address);
+}
 
 
 
@@ -170,16 +180,20 @@ Unsigned32 Io::in32_p(unsigned long port)
 IMPLEMENT inline
 void Io::out8_p(Unsigned8 val, unsigned long port)
 {
-  out8(val,port); iodelay();
+  out8(val, port);
+  iodelay();
 }
 
 IMPLEMENT inline
 void Io::out16_p(Unsigned16 val, unsigned long port)
 {
-  out16(val,port); iodelay();
+  out16(val, port);
+  iodelay();
 }
+
 IMPLEMENT inline
 void Io::out32_p(Unsigned32 val, unsigned long port)
 {
-  out32(val,port); iodelay();
+  out32(val, port);
+  iodelay();
 }
diff --git a/kernel/fiasco/src/drivers/mmio_register_block.h b/kernel/fiasco/src/drivers/mmio_register_block.h
new file mode 100644 (file)
index 0000000..9657fa5
--- /dev/null
@@ -0,0 +1,35 @@
+// vi:ft=cpp
+
+#pragma once
+
+#include "types.h"
+
+class Mmio_register_block
+{
+public:
+  Mmio_register_block() {}
+  explicit Mmio_register_block(Address base) : _base(base) {}
+
+  template< typename T >
+  void write(T t, Address reg) const
+  { *reinterpret_cast<T volatile *>(_base + reg) = t; }
+
+  template< typename T >
+  T read(Address reg) const
+  { return *reinterpret_cast<T volatile const *>(_base + reg); }
+
+  template< typename T >
+  void modify(T enable, T disable, Address reg) const
+  {
+    Mword tmp = read<T>(reg);
+    tmp &= ~disable;
+    tmp |= enable;
+    write<T>(tmp, reg);
+  }
+
+  Address get_mmio_base() const { return _base; }
+  void set_mmio_base(Address base) { _base = base; }
+
+private:
+  Address _base;
+};
index 1b04dbf8081d6ab9f31f74110e27efa597286ca2..2ce99c1b1154725035778a6ee9292f86171a91ed 100644 (file)
@@ -8,7 +8,7 @@ EXTENSION class Proc
 public:
   //disable power savings mode
  static Mword wake(Mword);
- static unsigned cpu_id();
+ static Cpu_phys_id cpu_id();
 };
 
 /// Unblock external inetrrupts
@@ -112,7 +112,7 @@ Mword Proc::program_counter()
 IMPLEMENTATION [ppc32 && !mpcore]:
 
 IMPLEMENT static inline
-unsigned Proc::cpu_id()
-{ return 0; }
+Cpu_phys_id Proc::cpu_id()
+{ return Cpu_phys_id(0); }
 
 
index 001d0c8f730af8d07f0a015cda453a097ecdae50..b4989c5045c6744d3939f83185a7be8cd2127332 100644 (file)
@@ -9,7 +9,7 @@ EXTENSION class Proc
 public:
   //disable power savings mode
  static Mword wake(Mword);
- static unsigned cpu_id();
+ static Cpu_phys_id cpu_id();
 };
 
 /// Unblock external interrupts
@@ -135,7 +135,7 @@ void Proc::write_alternative(Mword reg, Mword value)
 IMPLEMENTATION [sparc && !mpcore]:
 
 IMPLEMENT static inline
-unsigned Proc::cpu_id()
-{ return 0; }
+Cpu_phys_id Proc::cpu_id()
+{ return Cpu_phys_id(0); }
 
 
index 86e85bca62247335af4fb3c374d2440e84f14dbd..35cee60b5a502f89bb939bf5f9e3c4761d700fd7 100644 (file)
@@ -188,7 +188,7 @@ bool Uart::valid()
   scratch3 = ier();
   ier(scratch);
 
-  return (scratch2 == 0x00 && scratch3 == 0x0f);
+  return scratch2 == 0x00 && scratch3 == 0x0f;
 }
 
 IMPLEMENT
@@ -208,9 +208,7 @@ bool Uart::startup(Address _port, int __irq)
 
   ier(Base_ier_bits);/* disable all rs-232 interrupts */
   mcr(0x0b);         /* out2, rts, and dtr enabled */
-  fcr(1);            /* enable fifo */
-  fcr(0x07);         /* clear rcv xmit fifo */
-  fcr(1);            /* enable fifo */
+  fcr(7);            /* enable and clear rcv+xmit fifo */
   lcr(0);            /* clear line control register */
 
   /* clearall interrupts */
index a0ac4c139e57dd8a746efdb0cd8362712db689b7..0f989b72b9b06b0dfb91467809c8ff988757284c 100644 (file)
@@ -9,6 +9,7 @@ IMPLEMENTATION [arm]:
 #include "mem_unit.h"
 #include "static_init.h"
 #include "watchdog.h"
+#include "cxx/cxx_int"
 
 STATIC_INITIALIZE_P(Jdb, JDB_INIT_PRIO);
 
@@ -17,41 +18,41 @@ DEFINE_PER_CPU static Per_cpu<Proc::Status> jdb_irq_state;
 // disable interrupts before entering the kernel debugger
 IMPLEMENT
 void
-Jdb::save_disable_irqs(unsigned cpu)
+Jdb::save_disable_irqs(Cpu_number cpu)
 {
   jdb_irq_state.cpu(cpu) = Proc::cli_save();
-  if (cpu == 0)
+  if (cpu == Cpu_number::boot_cpu())
     Watchdog::disable();
 }
 
 // restore interrupts after leaving the kernel debugger
 IMPLEMENT
 void
-Jdb::restore_irqs(unsigned cpu)
+Jdb::restore_irqs(Cpu_number cpu)
 {
-  if (cpu == 0)
+  if (cpu == Cpu_number::boot_cpu())
     Watchdog::enable();
   Proc::sti_restore(jdb_irq_state.cpu(cpu));
 }
 
 IMPLEMENT inline
 void
-Jdb::enter_trap_handler(unsigned /*cpu*/)
+Jdb::enter_trap_handler(Cpu_number)
 {}
 
 IMPLEMENT inline
 void
-Jdb::leave_trap_handler(unsigned /*cpu*/)
+Jdb::leave_trap_handler(Cpu_number)
 {}
 
 PROTECTED static inline
 void
-Jdb::monitor_address(unsigned, void *)
+Jdb::monitor_address(Cpu_number, void *)
 {}
 
 IMPLEMENT inline
 bool
-Jdb::handle_conditional_breakpoint(unsigned /*cpu*/)
+Jdb::handle_conditional_breakpoint(Cpu_number)
 { return false; }
 
 IMPLEMENT
@@ -64,15 +65,15 @@ Jdb::handle_nested_trap(Jdb_entry_frame *e)
 
 IMPLEMENT
 bool
-Jdb::handle_debug_traps(unsigned cpu)
+Jdb::handle_debug_traps(Cpu_number cpu)
 {
   Jdb_entry_frame *ef = entry_frame.cpu(cpu);
 
   if (ef->error_code == 0x00e00000)
-    snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)), "%s",
+    snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(Cpu_number::first())), "%s",
              (char const *)ef->r[0]);
   else if (ef->debug_ipi())
-    snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)),
+    snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(Cpu_number::first())),
              "IPI ENTRY");
 
   return true;
@@ -80,7 +81,7 @@ Jdb::handle_debug_traps(unsigned cpu)
 
 IMPLEMENT inline
 bool
-Jdb::handle_user_request(unsigned cpu)
+Jdb::handle_user_request(Cpu_number cpu)
 {
   Jdb_entry_frame *ef = Jdb::entry_frame.cpu(cpu);
   const char *str = (char const *)ef->r[0];
@@ -88,7 +89,7 @@ Jdb::handle_user_request(unsigned cpu)
   char tmp;
 
   if (ef->debug_ipi())
-    return cpu != 0;
+    return cpu != Cpu_number::boot_cpu();
 
   if (ef->error_code == 0x00e00001)
     return execute_command_ni(task, str);
@@ -140,11 +141,11 @@ Jdb::access_mem_task(Address virt, Space * task)
     {
       if (Mem_layout::in_kernel(virt))
        {
-         Pte p = Kmem_space::kdir()->walk((void *)virt, 0, false, Ptab::Null_alloc(), 0);
-         if (!p.valid())
+         auto p = Kmem_space::kdir()->walk(Virt_addr(virt));
+         if (!p.is_valid())
            return 0;
 
-         phys = p.phys((void*)virt);
+         phys = p.page_addr() | cxx::get_lsb(virt, p.page_order());
        }
       else
        phys = virt;
@@ -165,14 +166,17 @@ Jdb::access_mem_task(Address virt, Space * task)
   if (addr == (Address)-1)
     {
       Mem_unit::flush_vdcache();
-      Pte pte = static_cast<Mem_space*>(Kernel_task::kernel_task())
-        ->_dir->walk((void*)Mem_layout::Jdb_tmp_map_area, 0, false, Ptab::Null_alloc(), 0);
+      auto pte = static_cast<Mem_space*>(Kernel_task::kernel_task())
+        ->_dir->walk(Virt_addr(Mem_layout::Jdb_tmp_map_area), Pdir::Super_level);
 
-      if (pte.phys() != (phys & ~(Config::SUPERPAGE_SIZE - 1)))
-        pte.set(phys & ~(Config::SUPERPAGE_SIZE - 1), Config::SUPERPAGE_SIZE,
-                Mem_page_attr(Page::KERN_RW | Page::CACHEABLE), true);
+      if (!pte.is_valid() || pte.page_addr() != cxx::mask_lsb(phys, pte.page_order()))
+        {
+          pte.create_page(Phys_mem_addr(cxx::mask_lsb(phys, pte.page_order())),
+                          Page::Attr(Page::Rights::RW()));
+          pte.write_back_if(true);
+        }
 
-      Mem_unit::dtlb_flush();
+      Mem_unit::tlb_flush();
 
       addr = Mem_layout::Jdb_tmp_map_area + (phys & (Config::SUPERPAGE_SIZE - 1));
     }
@@ -295,9 +299,10 @@ IMPLEMENTATION [arm && mp]:
 
 static
 void
-Jdb::send_nmi(unsigned cpu)
+Jdb::send_nmi(Cpu_number cpu)
 {
-  printf("NMI to %d, what's that?\n", cpu);
+  printf("NMI to %d, what's that?\n",
+         cxx::int_value<Cpu_number>(cpu));
 }
 
 PROTECTED static inline
@@ -312,7 +317,7 @@ Jdb::set_monitored_address(T *dest, T val)
 
 PROTECTED static inline
 template< typename T >
-T Jdb::monitor_address(unsigned, T volatile *addr)
+T Jdb::monitor_address(Cpu_number, T volatile *addr)
 {
   asm volatile("wfe");
   return *addr;
index 0a2b745b7a3f24c10aaa32e25720f8faeb6e2e1a..7f1a48d71e4f704aeda61b91ad995c73e6c2bc6c 100644 (file)
@@ -136,14 +136,14 @@ static void tbuf(Thread *t, Entry_frame *r)
 }
 
 static void do_cli(Thread *, Entry_frame *r)
-{ r->psr |= Proc::Status_IRQ_disabled; }
+{ r->psr |= Proc::Status_preempt_disabled; }
 
 static void do_sti(Thread *, Entry_frame *r)
-{ r->psr &= ~Proc::Status_IRQ_disabled; }
+{ r->psr &= ~Proc::Status_preempt_disabled; }
 
 static void getcpu(Thread *, Entry_frame *r)
 {
-  r->r[0] = current_cpu();
+  r->r[0] = cxx::int_value<Cpu_number>(current_cpu());
 }
 
 static void init_dbg_extensions()
@@ -159,9 +159,13 @@ static void init_dbg_extensions()
   Thread::dbg_extension[0x09] = &outhex8;
   Thread::dbg_extension[0x0d] = &inchar;
   Thread::dbg_extension[0x1d] = &tbuf;
-  Thread::dbg_extension[0x32] = &do_cli;
-  Thread::dbg_extension[0x33] = &do_sti;
-  Thread::dbg_extension[0x34] = &getcpu;
+
+  if (0)
+    {
+      Thread::dbg_extension[0x32] = &do_cli;
+      Thread::dbg_extension[0x33] = &do_sti;
+      Thread::dbg_extension[0x34] = &getcpu;
+    }
 }
 
 STATIC_INITIALIZER(init_dbg_extensions);
index 1c61a17555f99b23661dbe99631f55464a020bc5..3e7260833231cc9c0c2768b7f67546f05d345106 100644 (file)
@@ -29,7 +29,7 @@ Jdb_kern_info_misc::show()
         "pdir: %08x\n",
         (unsigned) (Kip::k()->clock >> 32), 
         (unsigned) (Kip::k()->clock),
-         (unsigned) Mem_space::current_mem_space(0)->dir());
+         (unsigned) Mem_space::current_mem_space(Cpu_number::boot_cpu())->dir());
 
 
 }
index 18453b9561de1effb777f6116333a5213aed6e6a..f0e1a718e9fe4236f32bf8f3139a5b618e3f7699 100644 (file)
@@ -12,7 +12,7 @@ IMPLEMENTATION[arm && realview]:
 IMPLEMENT inline NEEDS["platform.h"]
 Unsigned64
 Jdb_kern_info_bench::get_time_now()
-{ return Platform::read(Platform::Sys::Cnt_24mhz); }
+{ return Platform::sys->read<Mword>(Platform::Sys::Cnt_24mhz); }
 
 IMPLEMENTATION[arm && !realview]:
 
index cf96fd153169fd844bc34d7b46e8bd515523242e..1b5dcbc0193cc53bd22c4b09b9a000a910abcb34 100644 (file)
@@ -3,33 +3,9 @@ IMPLEMENTATION [arm]:
 #include "paging.h"
 #include "simpleio.h"
 
-unsigned Jdb_ptab::max_pt_level = 1;
-
 // -----------------------------------------------------------------------
 IMPLEMENTATION [arm && armv5]:
 
-IMPLEMENT inline
-unsigned
-Jdb_ptab::entry_valid(Mword entry, unsigned)
-{ return entry & 0x03; }
-
-IMPLEMENT inline
-unsigned
-Jdb_ptab::entry_is_pt_ptr(Mword entry, unsigned level,
-                          unsigned *entries, unsigned *next_level)
-{
-  if (level > 0 || (entry & 0x03) == 0x02)
-    return 0;
-
-  if ((entry & 0x03) == 0x01)
-    *entries = 256;  // coarse (1KB)
-  else
-    *entries = 1024; // fine (4KB)
-
-  *next_level = 1;
-  return 1;
-}
-
 PRIVATE inline
 bool
 Jdb_ptab::is_cached(Mword entry, unsigned level)
@@ -57,25 +33,7 @@ Jdb_ptab::ap_char(unsigned ap)
 
 
 // -----------------------------------------------------------------------
-IMPLEMENTATION [arm && (armv6 || armv7)]:
-
-IMPLEMENT inline NEEDS ["paging.h"]
-unsigned
-Jdb_ptab::entry_valid(Mword entry, unsigned)
-{ return (entry & 3) == 1 || (entry & 3) == 2; }
-
-IMPLEMENT inline
-unsigned
-Jdb_ptab::entry_is_pt_ptr(Mword entry, unsigned level,
-                          unsigned *entries, unsigned *next_level)
-{
-  if (level > 0 || (entry & 0x03) == 0x02)
-    return 0;
-
-  *entries = 256;  // coarse (1KB)
-  *next_level = 1;
-  return 1;
-}
+IMPLEMENTATION [arm && (armv6 || armv7) && !arm_lpae]:
 
 PRIVATE inline
 bool
@@ -115,68 +73,31 @@ Jdb_ptab::ap_char(unsigned ap)
 }
 
 // -----------------------------------------------------------------------
-IMPLEMENTATION [arm]:
-
-IMPLEMENT inline NEEDS ["paging.h"]
-Address
-Jdb_ptab::entry_phys(Mword entry, unsigned level)
-{
-  unsigned t = entry & 0x03;
-  if (level == 0)
-    {
-      switch(t)
-       {
-       default:
-       case 0:
-         return 0;
-       case 1:
-         return entry & 0xfffffc00;
-       case 2:
-         return entry & 0xfff00000;
-       case 3:
-         return entry & 0xfffff000;
-       }
-    }
-  else
-    {
-      switch (t)
-       {
-       default:
-       case 0:
-         return 0;
-       case 1:
-         return entry & 0xffff0000;
-       case 2:
-         return entry & 0xfffff000;
-       case 3:
-         return entry & 0xfffffc00;
-       }
-    }
-}
+IMPLEMENTATION [arm && !arm_lpae]:
 
 IMPLEMENT
 void
-Jdb_ptab::print_entry(Mword entry, unsigned level)
+Jdb_ptab::print_entry(Pte_ptr const &entry)
 {
   if (dump_raw)
-    printf("%08lx", entry);
+    printf("%08lx", *entry.pte);
   else
     {
-      if (!entry_valid(entry,level))
+      if (!entry.is_valid())
        {
          putstr("    -   ");
          return;
        }
-      Address phys = entry_phys(entry, level);
+      Address phys = entry_phys(entry);
 
-      unsigned t = entry & 0x03;
-      unsigned ap = entry >> 4;
+      unsigned t = *entry.pte & 0x03;
+      unsigned ap = *entry.pte >> 4;
       char ps;
-      if (level == 0)
+      if (entry.level == 0)
        switch (t)
          {
          case 1: ps = 'C'; break;
-         case 2: ps = 'S'; ap = entry >> 10; break;
+         case 2: ps = 'S'; ap = *entry.pte >> 10; break;
          case 3: ps = 'F'; break;
          default: ps = 'U'; break;
          }
@@ -190,19 +111,97 @@ Jdb_ptab::print_entry(Mword entry, unsigned level)
          }
 
       printf("%05lx%s%c", phys >> Config::PAGE_SHIFT,
-                          is_cached(entry, level)
+                          is_cached(*entry.pte, entry.level)
                            ? "-" : JDB_ANSI_COLOR(lightblue) "n" JDB_ANSI_END,
                           ps);
-      if (level == 0 && t != 2)
+      if (entry.level == 0 && t != 2)
         putchar('-');
       else
        printf("%s%c" JDB_ANSI_END,
-               is_executable(entry) ? "" : JDB_ANSI_COLOR(red),
+               is_executable(*entry.pte) ? "" : JDB_ANSI_COLOR(red),
               ap_char(ap));
     }
 }
 
-PUBLIC
-unsigned long
-Jdb_ptab::rows() const
-{ return entries/8; }
+// -----------------------------------------------------------------------
+IMPLEMENTATION [arm && arm_lpae]:
+
+PRIVATE inline
+bool
+Jdb_ptab::is_cached(Pte_ptr const &entry)
+{
+  if (!entry.is_leaf())
+    return true;
+  return (*entry.pte & Page::Cache_mask) == Page::CACHEABLE;
+}
+
+PRIVATE inline
+bool
+Jdb_ptab::is_executable(Mword entry)
+{
+  (void)entry;
+  return 1;
+}
+
+PRIVATE inline
+char
+Jdb_ptab::ap_char(Mword entry)
+{
+  switch ((entry >> 6) & 3)
+  {
+    case 0: return 'W';
+    case 1: return 'w';
+    case 2: return 'R';
+    case 3: default: return 'r';
+  };
+}
+
+IMPLEMENT
+void
+Jdb_ptab::print_entry(Pte_ptr const &entry)
+{
+  if (dump_raw)
+    printf("%08lx", (unsigned long)*entry.pte);
+  else
+    {
+      if (!entry.is_valid())
+       {
+         putstr("    -   ");
+         return;
+       }
+      Address phys = entry_phys(entry);
+
+      unsigned t = (*entry.pte & 2) >> 1;
+
+      char ps;
+      if (entry.level == 0)
+        switch (t)
+          {
+          case 0: ps = 'G'; break;
+          case 1: ps = 'P'; break;
+          }
+      else if (entry.level == 1)
+        switch (t)
+          {
+          case 0: ps = 'M'; break;
+          case 1: ps = 'P'; break;
+          }
+      else
+        switch (t)
+          {
+          case 0: ps = '?'; break;
+          case 1: ps = 'p'; break;
+          }
+
+      printf("%05lx%s%c", phys >> Config::PAGE_SHIFT,
+                          is_cached(entry)
+                           ? "-" : JDB_ANSI_COLOR(lightblue) "n" JDB_ANSI_END,
+                          ps);
+      if (!entry.is_leaf())
+        putchar('-');
+      else
+        printf("%s%c" JDB_ANSI_END,
+               is_executable(*entry.pte) ? "" : JDB_ANSI_COLOR(red),
+               ap_char(*entry.pte));
+    }
+}
index 1ccf454df449f95f8161238b99da363e3ccb458b..f184e02fa32b4ecd3ea6cee9dfa9136c31838d19 100644 (file)
@@ -1,17 +1,10 @@
-IMPLEMENTATION [tz]:
+IMPLEMENTATION [arm_em_tz]:
 
-#include <climits>
 #include <cstring>
 #include <cstdio>
 
-#include "jdb.h"
-#include "jdb_core.h"
 #include "jdb_module.h"
-#include "jdb_screen.h"
 #include "jdb_kobject.h"
-#include "kernel_console.h"
-#include "keycodes.h"
-#include "simpleio.h"
 #include "static_init.h"
 #include "vm.h"
 
@@ -32,7 +25,7 @@ PUBLIC
 bool
 Jdb_vm::show_kobject(Kobject_common *o, int lvl)
 {
-  Kobject::dcast<Vm*>(o)->dump_machine_state();
+  Kobject::dcast<Vm*>(o)->dump_vm_state();
   if (lvl)
     {
       Jdb::getchar();
@@ -53,15 +46,15 @@ PUBLIC
 int
 Jdb_vm::show_kobject_short(char *buf, int max, Kobject_common *o)
 {
-  return Kobject::dcast<Vm*>(o)->show_short(buf, max);
+  return Kobject::dcast<Vm *>(o)->show_short(buf, max);
 }
 
-static Jdb_vm jdb_vm INIT_PRIORITY(JDB_MODULE_INIT_PRIO);
+//static Jdb_vm jdb_vm INIT_PRIORITY(JDB_MODULE_INIT_PRIO);
 
-static
-bool
-filter_vm(Kobject_common const *o)
-{
-  return Kobject::dcast<Vm const *>(o);
-}
-static Jdb_kobject_list::Mode INIT_PRIORITY(JDB_MODULE_INIT_PRIO) tnt("[Vms]", filter_vm);
+//static
+//bool
+//filter_vm(Kobject_common const *o)
+//{
+//  return Kobject::dcast<Vm const *>(o);
+//}
+//static Jdb_kobject_list::Mode INIT_PRIORITY(JDB_MODULE_INIT_PRIO) tnt("[Vms]", filter_vm);
index 217eadf8121948ecce51bc16d54fa7ac213b4a44..dc7eafba77dce46ab563289003bfd5b501a18a11 100644 (file)
@@ -371,7 +371,7 @@ Jdb_kern_info_bench::show_arch()
       // and do "sysret ; syscall". Gdt doesn't care us since sysret loads a
       // flat segment. Sysret enables the interrupts again so make sure that
       // we don't receive a timer interrupt.
-      Timer_tick::disable(0);
+      Timer_tick::disable(Cpu_number::boot_cpu());
       Proc::sti();
       Proc::irq_chance();
       asm volatile ("pushf                     \n\t"
@@ -419,7 +419,7 @@ Jdb_kern_info_bench::show_arch()
                    : "i"(Mem_layout::Tbuf_status_page + Config::PAGE_SIZE-2)
                    : "ebx", "ecx", "esi", "edi", "memory");
       Proc::cli();
-      Timer_tick::enable(0);
+      Timer_tick::enable(Cpu_number::boot_cpu());
       show_time(time, 200000, "syscall + sysret");
     }
   BENCH("push EAX + pop EAX",  inst_push_pop,     200000);
index a3aaa2e20a0d5df019e2f22eb29df5ced41e2803..ac2c8a4bc60c45f92dfa8ff26b04b44af39446d1 100644 (file)
@@ -2,104 +2,41 @@ IMPLEMENTATION [amd64]:
 
 #include "paging.h"
 
-unsigned Jdb_ptab::max_pt_level = Pdir::Depth;
-
-IMPLEMENT inline NEEDS ["paging.h"]
-unsigned
-Jdb_ptab::entry_is_pt_ptr(Mword entry, unsigned level,
-                          unsigned *entries, unsigned *next_level)
-{
-  if (level > Pdir::Super_level || entry & Pt_entry::Pse_bit)
-    return 0;
-  *entries = Ptab::Level<Pdir::Traits, Pdir::Depth>::length(level);
-  *next_level = level+1;
-  return 1;
-}
-
-IMPLEMENT inline NEEDS ["paging.h"]
-Address
-Jdb_ptab::entry_phys(Mword entry, unsigned level)
-{
-  return Ptab::Level<Pdir::Traits, Pdir::Depth>::addr(level, entry);
-}
-
-IMPLEMENT inline NEEDS ["paging.h"]
-unsigned
-Jdb_ptab::entry_valid(Mword entry, unsigned)
-{ return entry & Pt_entry::Valid; }
-
 IMPLEMENT
 void
-Jdb_ptab::print_entry(Mword entry, unsigned level)
+Jdb_ptab::print_entry(Pdir::Pte_ptr const &entry)
 {
   if (dump_raw)
     {
-      printf(L4_PTR_FMT, entry);
+      printf(L4_PTR_FMT, *entry.pte);
       return;
     }
 
-  if (!entry_valid(entry,level))
+  if (!entry.is_valid())
     {
       putstr("        -       ");
       return;
     }
 
-  Address phys = entry_phys(entry, level);
+  Address phys = entry_phys(entry);
 
-  if (level == Pdir::Super_level && entry & Pt_entry::Pse_bit)
+  if (entry.level != Pdir::Depth && entry.is_leaf())
     printf((phys >> 20) > 0xFF
           ? "       %03lx/2" : "        %02lx/2", phys >> 20);
   else
     printf((phys >> Config::PAGE_SHIFT) > 0xFFFF
            ? "%13lx" : "         %04lx", phys >> Config::PAGE_SHIFT);
 
-  putchar(((cur_pt_level>=max_pt_level || (entry & Pt_entry::Pse_bit)) &&
-        (entry & Pt_entry::Cpu_global)) ? '+' : '-');
-  printf("%s%c%s", entry & Pt_entry::Noncacheable ? JDB_ANSI_COLOR(lightblue) : "",
-                   entry & Pt_entry::Noncacheable
-                    ? 'n' : (entry & Pt_entry::Write_through) ? 't' : '-',
-                   entry & Pt_entry::Noncacheable ? JDB_ANSI_END : "");
-  putchar(entry & Pt_entry::User
-           ? (entry & Pt_entry::Writable) ? 'w' : 'r'
-           : (entry & Pt_entry::Writable) ? 'W' : 'R');
+  putchar(((cur_pt_level >= Pdir::Depth || entry.is_leaf()) &&
+        (*entry.pte & Pt_entry::Cpu_global)) ? '+' : '-');
+  printf("%s%c%s", *entry.pte & Pt_entry::Noncacheable ? JDB_ANSI_COLOR(lightblue) : "",
+                   *entry.pte & Pt_entry::Noncacheable
+                    ? 'n' : (*entry.pte & Pt_entry::Write_through) ? 't' : '-',
+                   *entry.pte & Pt_entry::Noncacheable ? JDB_ANSI_END : "");
+  putchar(*entry.pte & Pt_entry::User
+           ? (*entry.pte & Pt_entry::Writable) ? 'w' : 'r'
+           : (*entry.pte & Pt_entry::Writable) ? 'W' : 'R');
 }
 
-PUBLIC
-unsigned long
-Jdb_ptab::rows() const
-{  return entries/4; }
 
-PRIVATE
-Address
-Jdb_ptab::disp_virt(unsigned long row, unsigned col)
-{
-  Pdir::Va e(Mword(col-1) + (Mword(row) * Mword(cols()-1)));
-  e <<= Ptab::Level<Pdir::Traits, Pdir::Depth>::shift(cur_pt_level);
-  return Virt_addr(e).value() + virt_base;
-}
 
-PUBLIC
-void
-Jdb_ptab::print_statline(unsigned long row, unsigned long col)
-{
-  if (cur_pt_level == 0)
-    {
-      Jdb::printf_statline("pml4", "<Space>=mode <CR>=goto pdp",
-         "<" L4_PTR_FMT "> task %p", disp_virt(row,col), _task);
-    }
-  else if (cur_pt_level == 1)
-    {
-      Jdb::printf_statline("pdp", "<Space>=mode <CR>=goto pdir",
-         "<" L4_PTR_FMT "> task %p", disp_virt(row,col), _task);
-    }
-  else if (cur_pt_level == 2)
-    {
-      Jdb::printf_statline("pdir", "<Space>=mode <CR>=goto ptab/superpage",
-         "<" L4_PTR_FMT "> task %p", disp_virt(row,col), _task);
-    }
-  else // PT_MODE
-    {
-      Jdb::printf_statline("ptab", "<Space>=mode <CR>=goto page",
-         "<" L4_PTR_FMT "> task %p", disp_virt(row,col), _task);
-    }
-}
index a812998277b582defb544e8f1c84b89d2e33bb80..a9145d58e3c931b077e3f4e47dd4313e005585c5 100644 (file)
@@ -214,7 +214,7 @@ Jdb::set_monitored_address(T *dest, T val)
 PROTECTED static inline
 template< typename T >
 T
-Jdb::monitor_address(unsigned current_cpu, T *addr)
+Jdb::monitor_address(Cpu_number current_cpu, T *addr)
 {
   if (!*addr && Cpu::cpus.cpu(current_cpu).has_monitor_mwait())
     {
@@ -227,23 +227,6 @@ Jdb::monitor_address(unsigned current_cpu, T *addr)
 }
 
 
-#if 0
-PUBLIC static
-template <typename T> T
-Jdb::peek(T const *addr)
-{
-  return *addr;
-}
-
-PUBLIC static
-template <typename T> T
-Jdb::peek(T const *addr, Address_type)
-{
-  // on IA32 we can touch directly into the user-space
-  return *(T*)addr;
-}
-#endif
-
 static inline
 void
 Jdb::backspace()
@@ -257,19 +240,19 @@ DEFINE_PER_CPU static Per_cpu<Proc::Status> jdb_saved_flags;
 // disable interrupts before entering the kernel debugger
 IMPLEMENT
 void
-Jdb::save_disable_irqs(unsigned cpu)
+Jdb::save_disable_irqs(Cpu_number cpu)
 {
   if (!jdb_irqs_disabled.cpu(cpu)++)
     {
       // save interrupt flags
       jdb_saved_flags.cpu(cpu) = Proc::cli_save();
 
-      if (cpu == 0)
+      if (cpu == Cpu_number::boot_cpu())
        {
          Watchdog::disable();
          pic_status = Pic::disable_all_save();
           if (Config::getchar_does_hlt_works_ok)
-            Timer_tick::disable(0);
+            Timer_tick::disable(Cpu_number::boot_cpu());
        }
       if (Io_apic::active() && Apic::is_present())
        {
@@ -277,16 +260,16 @@ Jdb::save_disable_irqs(unsigned cpu)
          Apic::tpr(APIC_IRQ_BASE - 0x10);
        }
 
-      if (cpu == 0 && Config::getchar_does_hlt_works_ok)
+      if (cpu == Cpu_number::boot_cpu() && Config::getchar_does_hlt_works_ok)
        {
          // set timer interrupt does nothing than wakeup from hlt
          Timer_tick::set_vectors_stop();
-         Timer_tick::enable(0);
+         Timer_tick::enable(Cpu_number::boot_cpu());
        }
 
     }
 
-  if (cpu == 0 && Config::getchar_does_hlt_works_ok)
+  if (cpu == Cpu_number::boot_cpu() && Config::getchar_does_hlt_works_ok)
     // explicit enable interrupts because the timer interrupt is
     // needed to wakeup from "hlt" state in getchar(). All other
     // interrupts are disabled at the pic.
@@ -296,7 +279,7 @@ Jdb::save_disable_irqs(unsigned cpu)
 // restore interrupts after leaving the kernel debugger
 IMPLEMENT
 void
-Jdb::restore_irqs(unsigned cpu)
+Jdb::restore_irqs(Cpu_number cpu)
 {
   if (!--jdb_irqs_disabled.cpu(cpu))
     {
@@ -305,14 +288,14 @@ Jdb::restore_irqs(unsigned cpu)
       if (Io_apic::active() && Apic::is_present())
        Apic::tpr(apic_tpr.cpu(cpu));
 
-      if (cpu == 0)
+      if (cpu == Cpu_number::boot_cpu())
        {
          Pic::restore_all(Jdb::pic_status);
          Watchdog::enable();
        }
 
       // reset timer interrupt vector
-      if (cpu == 0 && Config::getchar_does_hlt_works_ok)
+      if (cpu == Cpu_number::boot_cpu() && Config::getchar_does_hlt_works_ok)
        Idt::set_vectors_run();
 
       // reset interrupt flags
@@ -325,7 +308,7 @@ struct On_dbg_stack
 {
   Mword sp;
   On_dbg_stack(Mword sp) : sp(sp) {}
-  bool operator () (unsigned cpu) const
+  bool operator () (Cpu_number cpu) const
   {
     Thread::Dbg_stack const &st = Thread::dbg_stack.cpu(cpu);
     return sp <= Mword(st.stack_top) 
@@ -338,7 +321,7 @@ struct On_dbg_stack
 // context. We _never_ return 0!
 IMPLEMENT
 Thread*
-Jdb::get_thread(unsigned cpu)
+Jdb::get_thread(Cpu_number cpu)
 {
   Jdb_entry_frame *entry_frame = Jdb::entry_frame.cpu(cpu);
   Address sp = (Address) entry_frame;
@@ -398,8 +381,8 @@ Jdb::peek_task(Address addr, Space *task, void *value, int width)
       Address pdbr;
       asm volatile ("mov %%cr3, %0" : "=r" (pdbr));
       Pdir *kdir = (Pdir*)Mem_layout::phys_to_pmem(pdbr);
-      Pdir::Iter i = kdir->walk(Virt_addr(addr));
-      if (i.e->valid())
+      auto i = kdir->walk(Virt_addr(addr));
+      if (i.is_valid())
        {
           memcpy(value, (void*)addr, width);
           return 0;
@@ -435,8 +418,8 @@ Jdb::poke_task(Address addr, Space *task, void const *value, int width)
       Address pdbr;
       asm volatile ("mov %%cr3, %0" : "=r" (pdbr));
       Pdir *kdir = (Pdir*)Mem_layout::phys_to_pmem(pdbr);
-      Pdir::Iter i = kdir->walk(Virt_addr(addr));
-      if (i.e->valid())
+      auto i = kdir->walk(Virt_addr(addr));
+      if (i.is_valid())
        {
           memcpy((void*)addr, value, width);
           return 0;
@@ -557,7 +540,7 @@ Jdb::guess_thread_state(Thread *t)
 
 PUBLIC static
 void
-Jdb::set_single_step(unsigned cpu, int on)
+Jdb::set_single_step(Cpu_number cpu, int on)
 {
   if (on)
     entry_frame.cpu(cpu)->flags(entry_frame.cpu(cpu)->flags() | EFLAGS_TF);
@@ -618,7 +601,7 @@ IMPLEMENTATION[ia32]:
 // set global indicators code_call, code_ret, code_bra, code_int
 // This can fail if the current page is still not mapped
 static void
-Jdb::analyze_code(unsigned cpu)
+Jdb::analyze_code(Cpu_number cpu)
 {
   Jdb_entry_frame *entry_frame = Jdb::entry_frame.cpu(cpu);
   Space *task = get_task(cpu);
@@ -665,14 +648,14 @@ Jdb::analyze_code(unsigned cpu)
 IMPLEMENTATION[amd64]:
 
 static void
-Jdb::analyze_code(unsigned)
+Jdb::analyze_code(Cpu_number)
 {}
 
 IMPLEMENTATION[ia32,amd64]:
 
 // entered debugger because of single step trap
 static inline NOEXPORT int
-Jdb::handle_single_step(unsigned cpu)
+Jdb::handle_single_step(Cpu_number cpu)
 {
   int really_break = 1;
 
@@ -718,33 +701,33 @@ Jdb::handle_single_step(unsigned cpu)
        {
          // condition met
          ss_state.cpu(cpu) = SS_NONE;
-         snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)), "%s", "Branch/Call");
+         snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(Cpu_number::boot_cpu())), "%s", "Branch/Call");
        }
     }
   else // (ss_state == SS_NONE)
     // regular single_step
-    snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)), "%s", "Singlestep");
+    snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(Cpu_number::boot_cpu())), "%s", "Singlestep");
 
   return really_break;
 }
 
 // entered debugger due to debug exception
 static inline NOEXPORT int
-Jdb::handle_trap1(unsigned cpu)
+Jdb::handle_trap1(Cpu_number cpu)
 {
   // FIXME: currently only on bot cpu
-  if (cpu != 0)
+  if (cpu != Cpu_number::boot_cpu())
     return 0;
 
   if (bp_test_sstep && bp_test_sstep())
     return handle_single_step(cpu);
 
   if (bp_test_break
-      && bp_test_break(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0))))
+      && bp_test_break(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(Cpu_number::boot_cpu()))))
     return 1;
 
   if (bp_test_other
-      && bp_test_other(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0))))
+      && bp_test_other(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(Cpu_number::boot_cpu()))))
     return 1;
 
   return 0;
@@ -752,14 +735,14 @@ Jdb::handle_trap1(unsigned cpu)
 
 // entered debugger due to software breakpoint
 static inline NOEXPORT int
-Jdb::handle_trap3(unsigned cpu)
+Jdb::handle_trap3(Cpu_number cpu)
 {
   Jdb_entry_frame *entry_frame = Jdb::entry_frame.cpu(cpu);
   Space *task = get_task(cpu);
   Unsigned8 op;
   Unsigned8 len;
 
-  snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)), "%s", "INT 3");
+  snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(Cpu_number::boot_cpu())), "%s", "INT 3");
   if (   !peek((Unsigned8*)entry_frame->ip(), task, op)
       || !peek((Unsigned8*)(entry_frame->ip()+1), task, len)
       || op != 0xeb)
@@ -798,7 +781,7 @@ Jdb::handle_trap3(unsigned cpu)
                ctrl[i] = tmp;
            }
          ctrl[i] = '\0';
-         snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)),
+         snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(Cpu_number::boot_cpu())),
              "invalid ctrl sequence \"%s\"", ctrl);
        }
     }
@@ -807,9 +790,9 @@ Jdb::handle_trap3(unsigned cpu)
     {
       unsigned i;
       len = len < 47 ? len : 47;
-      len =   len < sizeof(error_buffer.cpu(0))-1
+      len =   len < sizeof(error_buffer.cpu(Cpu_number::boot_cpu()))-1
             ? len
-            : sizeof(error_buffer.cpu(0))-1;
+            : sizeof(error_buffer.cpu(Cpu_number::boot_cpu()))-1;
 
       for(i=0; i<len && peek(msg+i, task, buffer[0]); i++)
        error_buffer.cpu(cpu)[i] = buffer[0];
@@ -821,14 +804,14 @@ Jdb::handle_trap3(unsigned cpu)
 
 // entered debugger due to other exception
 static inline NOEXPORT int
-Jdb::handle_trapX(unsigned cpu)
+Jdb::handle_trapX(Cpu_number cpu)
 {
-  unsigned pos = snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)), "%s",
+  unsigned pos = snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(Cpu_number::boot_cpu())), "%s",
                          Cpu::exception_string(entry_frame.cpu(cpu)->_trapno)) + 1;
-  if (   pos < sizeof(error_buffer.cpu(0))
+  if (   pos < sizeof(error_buffer.cpu(Cpu_number::boot_cpu()))
       && entry_frame.cpu(cpu)->_trapno >= 10
       && entry_frame.cpu(cpu)->_trapno <= 14)
-    snprintf(error_buffer.cpu(cpu)+pos, sizeof(error_buffer.cpu(0))-pos,
+    snprintf(error_buffer.cpu(cpu)+pos, sizeof(error_buffer.cpu(Cpu_number::boot_cpu()))-pos,
              "(ERR=" L4_PTR_FMT ")", entry_frame.cpu(cpu)->_err);
 
   return 1;
@@ -840,7 +823,7 @@ Jdb::handle_trapX(unsigned cpu)
  */
 IMPLEMENT
 bool
-Jdb::handle_user_request(unsigned cpu)
+Jdb::handle_user_request(Cpu_number cpu)
 {
   Jdb_entry_frame *entry_frame = Jdb::entry_frame.cpu(cpu);
 
@@ -905,17 +888,17 @@ Jdb::handle_user_request(unsigned cpu)
 
 IMPLEMENT
 void
-Jdb::enter_trap_handler(unsigned cpu)
+Jdb::enter_trap_handler(Cpu_number cpu)
 { Cpu::cpus.cpu(cpu).debugctl_disable(); }
 
 IMPLEMENT
 void
-Jdb::leave_trap_handler(unsigned cpu)
+Jdb::leave_trap_handler(Cpu_number cpu)
 { Cpu::cpus.cpu(cpu).debugctl_enable(); }
 
 IMPLEMENT
 bool
-Jdb::handle_conditional_breakpoint(unsigned cpu)
+Jdb::handle_conditional_breakpoint(Cpu_number cpu)
 { return entry_frame.cpu(cpu)->_trapno == 1 && bp_test_log_only && bp_test_log_only(); }
 
 IMPLEMENT
@@ -969,7 +952,7 @@ Jdb::handle_nested_trap(Jdb_entry_frame *e)
 
 IMPLEMENT
 bool
-Jdb::handle_debug_traps(unsigned cpu)
+Jdb::handle_debug_traps(Cpu_number cpu)
 {
   bool really_break = true;
 
@@ -982,7 +965,7 @@ Jdb::handle_debug_traps(unsigned cpu)
 
   if (really_break)
     {
-      for (unsigned i = 0; i < Config::Max_num_cpus; ++i)
+      for (Cpu_number i = Cpu_number::first(); i < Config::max_num_cpus(); ++i)
        {
          if (!Cpu::online(i) || !running.cpu(i))
            continue;
@@ -1015,7 +998,7 @@ IMPLEMENTATION [(ia32 || amd64) && mp]:
 
 static
 void
-Jdb::send_nmi(unsigned cpu)
+Jdb::send_nmi(Cpu_number cpu)
 {
   Apic::mp_send_ipi(Apic::apic.cpu(cpu)->apic_id(), 0, Apic::APIC_IPI_NMI);
 }
index 94ffab90ba03c1a2057327f1a41d17e2c2520e02..a81801a59b7716a3ba17bfd5e62d99c4ed009b08 100644 (file)
@@ -493,8 +493,8 @@ PUBLIC static
 int
 Jdb_bp::test_break(Mword dr6, char *errbuf, size_t bufsize)
 {
-  Thread *t = Jdb::get_thread(0);
-  Jdb_entry_frame *e = Jdb::get_entry_frame(0);
+  Thread *t = Jdb::get_thread(Cpu_number::boot_cpu());
+  Jdb_entry_frame *e = Jdb::get_entry_frame(Cpu_number::boot_cpu());
 
   for (int i=0; i<4; i++)
     if (dr6 & (1<<i))
@@ -514,8 +514,8 @@ PUBLIC static
 void
 Jdb_bp::test_log(Mword &dr6)
 {
-  Thread *t = Jdb::get_thread(0);
-  Jdb_entry_frame *e = Jdb::get_entry_frame(0);
+  Thread *t = Jdb::get_thread(Cpu_number::boot_cpu());
+  Jdb_entry_frame *e = Jdb::get_entry_frame(Cpu_number::boot_cpu());
 
   for (int i=0; i<4; i++)
     if (dr6 & (1<<i))
index cffb0127f032270917d43b551c76570c51b0bd72..a9bdb774293981c69200072d45f2f4e319c486ef 100644 (file)
@@ -144,13 +144,13 @@ Jdb_bt::get_user_ebp_following_kernel_stack()
   return 0;
 }
 
-struct Is_current 
+struct Is_current
 {
   Thread *tid;
   mutable Thread *c;
-  mutable unsigned cpu;
+  mutable Cpu_number cpu;
 
-  void operator () (unsigned _cpu) const
+  void operator () (Cpu_number _cpu) const
   {
     Thread *t = Jdb::get_thread(_cpu);
     if (t == tid)
@@ -173,7 +173,7 @@ Jdb_bt::get_kernel_eip_ebp(Mword &eip1, Mword &eip2, Mword &ebp)
 
       is_current.tid = tid;
       is_current.c = 0;
-      is_current.cpu = 0;
+      is_current.cpu = Cpu_number::boot_cpu();
 
       Jdb::foreach_cpu(is_current);
 
@@ -184,7 +184,8 @@ Jdb_bt::get_kernel_eip_ebp(Mword &eip1, Mword &eip2, Mword &ebp)
        {
          ksp = (Mword*)Jdb::entry_frame.cpu(is_current.cpu)->sp();
          tcb = (Mword)is_current.c;
-         printf("\n current on cpu %u\n", is_current.cpu);
+         printf("\n current on cpu %u\n",
+                 cxx::int_value<Cpu_number>(is_current.cpu));
        }
       else
        {
index 6135c2473cb6166f367fe31c82751dc3bd187ac2..64bcb4441195c44016f856a41bd94675d4c8dd51 100644 (file)
@@ -289,14 +289,14 @@ Jdb_kern_info_gdt::Jdb_kern_info_gdt()
 
 PRIVATE static
 void
-Jdb_kern_info_gdt::show_gdt(unsigned cpu)
+Jdb_kern_info_gdt::show_gdt(Cpu_number cpu)
 {
   Gdt *gdt = Cpu::cpus.cpu(cpu).get_gdt();
   unsigned entries = Gdt::gdt_max / 8;
 
   if (Config::Max_num_cpus > 1)
     printf("CPU%d: GDT base=" L4_PTR_FMT "  limit=%04x (%04x bytes)\n",
-           cpu, (Mword)gdt, entries, Gdt::gdt_max);
+           cxx::int_value<Cpu_number>(cpu), (Mword)gdt, entries, Gdt::gdt_max);
   else
     printf("GDT base=" L4_PTR_FMT "  limit=%04x (%04x bytes)\n",
            (Mword)gdt, entries, Gdt::gdt_max);
index 28cb9c02f9292afd0fcb27699ace58cbbcca06df..6624280789daf1761fe57190477ca67bd31df566 100644 (file)
@@ -136,7 +136,7 @@ PRIVATE inline NEEDS["jdb_screen.h"]
 void
 Jdb_kern_info_misc::show_pdir()
 {
-  Mem_space *s = Mem_space::current_mem_space(0);
+  Mem_space *s = Mem_space::current_mem_space(Cpu_number::boot_cpu());
   printf("%s" L4_PTR_FMT "\n",
          Jdb_screen::Root_page_table, (Address)s->dir());
 }
index d6de9b71fd959c6d7294f63f9d2b4a5b5188a283..21881f42db35a6b5ee5d4b850a352ad202a6d5ef 100644 (file)
@@ -19,7 +19,7 @@ typedef void (Fast_entry_func)(void);
 
 PUBLIC static
 void
-Jdb_set_trace::ia32_set_fast_entry(unsigned cpu, void *entry)
+Jdb_set_trace::ia32_set_fast_entry(Cpu_number cpu, void *entry)
 {
   Cpu::cpus.cpu(cpu).set_fast_entry((Fast_entry_func*)entry);
 }
@@ -28,7 +28,7 @@ struct Set_fast_entry
 {
   void *entry;
   Set_fast_entry(Fast_entry_func *entry) : entry((void*)entry) {}
-  void operator () (unsigned cpu) const
+  void operator () (Cpu_number cpu) const
   { Jdb::remote_work(cpu, Jdb_set_trace::ia32_set_fast_entry, entry, true); }
 };
 
index e02e84a7995cc49364c9569240c79f2ca64e12a1..d4fc08fdabd26ef77edd2d05356a230ce11f98ae 100644 (file)
@@ -9,7 +9,7 @@ public:
    * Deliver Thread object which was active at entry of kernel debugger.
    * If we came from the kernel itself, return Thread with id 0.0
    */
-  static Thread *get_thread(unsigned cpu);
+  static Thread *get_thread(Cpu_number cpu);
 };
 
 //---------------------------------------------------------------------------
@@ -50,7 +50,7 @@ IMPLEMENTATION [arm || ux || ppc32 || sparc]:
 
 IMPLEMENT
 Thread *
-Jdb::get_thread(unsigned cpu)
+Jdb::get_thread(Cpu_number cpu)
 {
   Jdb_entry_frame *c = get_entry_frame(cpu);
 
@@ -65,7 +65,7 @@ IMPLEMENTATION:
 
 PUBLIC
 static void
-Jdb::get_current(unsigned cpu)
+Jdb::get_current(Cpu_number cpu)
 {
   current_active = get_thread(cpu);
 }
index e563397011a55a291422a4f346d3b8689e927292..6a944eec3a77c24c5a8b538acc06fc3d9c532a74 100644 (file)
@@ -15,19 +15,19 @@ class Jdb : public Jdb_core
 {
 public:
   static Per_cpu<Jdb_entry_frame*> entry_frame;
-  static unsigned current_cpu;
-  static Per_cpu<void (*)(unsigned, void *)> remote_func;
+  static Cpu_number current_cpu;
+  static Per_cpu<void (*)(Cpu_number, void *)> remote_func;
   static Per_cpu<void *> remote_func_data;
   static Per_cpu<bool> remote_func_running;
 
-  static int FIASCO_FASTCALL enter_jdb(Jdb_entry_frame *e, unsigned cpu);
+  static int FIASCO_FASTCALL enter_jdb(Jdb_entry_frame *e, Cpu_number cpu);
   static void cursor_end_of_screen();
   static void cursor_home();
   static void printf_statline(const char *prompt, const char *help,
                               const char *format, ...)
   __attribute__((format(printf, 3, 4)));
-  static void save_disable_irqs(unsigned cpu);
-  static void restore_irqs(unsigned cpu);
+  static void save_disable_irqs(Cpu_number cpu);
+  static void restore_irqs(Cpu_number cpu);
 
 private:
   Jdb();                       // default constructors are undefined
@@ -52,12 +52,12 @@ private:
   static bool never_break;
   static bool jdb_active;
 
-  static void enter_trap_handler(unsigned cpu);
-  static void leave_trap_handler(unsigned cpu);
-  static bool handle_conditional_breakpoint(unsigned cpu);
+  static void enter_trap_handler(Cpu_number cpu);
+  static void leave_trap_handler(Cpu_number cpu);
+  static bool handle_conditional_breakpoint(Cpu_number cpu);
   static void handle_nested_trap(Jdb_entry_frame *e);
-  static bool handle_user_request(unsigned cpu);
-  static bool handle_debug_traps(unsigned cpu);
+  static bool handle_user_request(Cpu_number cpu);
+  static bool handle_debug_traps(Cpu_number cpu);
   static bool test_checksums();
 
 public:
@@ -105,11 +105,11 @@ char Jdb::last_cmd;
 
 char Jdb::hide_statline;               // show status line on enter_kdebugger
 DEFINE_PER_CPU Per_cpu<Jdb_entry_frame*> Jdb::entry_frame;
-unsigned Jdb::current_cpu;              // current CPU JDB is running on
+Cpu_number Jdb::current_cpu;              // current CPU JDB is running on
 Thread *Jdb::current_active;           // current running thread
 bool Jdb::was_input_error;             // error in command sequence
 
-DEFINE_PER_CPU Per_cpu<void (*)(unsigned, void *)> Jdb::remote_func;
+DEFINE_PER_CPU Per_cpu<void (*)(Cpu_number, void *)> Jdb::remote_func;
 DEFINE_PER_CPU Per_cpu<void *> Jdb::remote_func_data;
 DEFINE_PER_CPU Per_cpu<bool> Jdb::remote_func_running;
 
@@ -130,7 +130,7 @@ unsigned long Jdb::cpus_in_debugger;
 
 PUBLIC static
 bool
-Jdb::cpu_in_jdb(unsigned cpu)
+Jdb::cpu_in_jdb(Cpu_number cpu)
 { return Cpu::online(cpu) && running.cpu(cpu); }
 
 
@@ -139,7 +139,7 @@ template< typename Func >
 void
 Jdb::foreach_cpu(Func const &f)
 {
-  for (unsigned i = 0; i < Config::Max_num_cpus; ++i)
+  for (Cpu_number i = Cpu_number::first(); i < Config::max_num_cpus(); ++i)
     {
       if (!Cpu::online(i) || !running.cpu(i))
        continue;
@@ -153,7 +153,7 @@ bool
 Jdb::foreach_cpu(Func const &f, bool positive)
 {
   bool r = positive;
-  for (unsigned i = 0; i < Config::Max_num_cpus; ++i)
+  for (Cpu_number i = Cpu_number::first(); i < Config::max_num_cpus(); ++i)
     {
       if (!Cpu::online(i) || !running.cpu(i))
        continue;
@@ -531,11 +531,11 @@ Jdb::execute_command()
 
 PRIVATE static
 bool
-Jdb::open_debug_console(unsigned cpu)
+Jdb::open_debug_console(Cpu_number cpu)
 {
   in_service = 1;
   save_disable_irqs(cpu);
-  if (cpu == 0)
+  if (cpu == Cpu_number::boot_cpu())
     jdb_enter.execute();
 
   if (!stop_all_cpus(cpu))
@@ -551,11 +551,11 @@ Jdb::open_debug_console(unsigned cpu)
 
 PRIVATE static
 void
-Jdb::close_debug_console(unsigned cpu)
+Jdb::close_debug_console(Cpu_number cpu)
 {
   Proc::cli();
   Mem::barrier();
-  if (cpu == 0)
+  if (cpu == Cpu_number::boot_cpu())
     {
       running.cpu(cpu) = 0;
       // eat up input from console
@@ -576,10 +576,10 @@ Jdb::close_debug_console(unsigned cpu)
 
 PUBLIC static
 void
-Jdb::remote_work(unsigned cpu, void (*func)(unsigned, void *), void *data,
+Jdb::remote_work(Cpu_number cpu, void (*func)(Cpu_number, void *), void *data,
                  bool sync = true)
 {
-  if (cpu == 0)
+  if (cpu == Cpu_number::boot_cpu())
     func(cpu, data);
   else
     {
@@ -742,7 +742,7 @@ Jdb::get_current_active()
 
 PUBLIC static inline
 Jdb_entry_frame*
-Jdb::get_entry_frame(unsigned cpu)
+Jdb::get_entry_frame(Cpu_number cpu)
 {
   return entry_frame.cpu(cpu);
 }
@@ -888,7 +888,7 @@ Jdb::std_cursor_key(int c, Mword cols, Mword lines, Mword max_absy, Mword *absy,
 
 PUBLIC static inline
 Space *
-Jdb::get_task(unsigned cpu)
+Jdb::get_task(Cpu_number cpu)
 {
   if (!get_thread(cpu))
     return 0;
@@ -1005,7 +1005,7 @@ char Jdb::esc_symbol[]   = "\033[33;1m";
 
 
 IMPLEMENT int
-Jdb::enter_jdb(Jdb_entry_frame *e, unsigned cpu)
+Jdb::enter_jdb(Jdb_entry_frame *e, Cpu_number cpu)
 {
   if (e->debug_ipi())
     {
@@ -1099,14 +1099,16 @@ Jdb::enter_jdb(Jdb_entry_frame *e, unsigned cpu)
                         "read-only data has changed!\n",
                     Jdb_screen::width()-11,
                     Jdb_screen::Line);
-             for (unsigned i = 0; i < Config::Max_num_cpus; ++i)
+             for (Cpu_number i = Cpu_number::first(); i < Config::max_num_cpus(); ++i)
                if (Cpu::online(i))
                  {
                    if (running.cpu(i))
-                     printf("    CPU%2u [" L4_PTR_FMT "]: %s\n", i,
+                     printf("    CPU%2u [" L4_PTR_FMT "]: %s\n",
+                             cxx::int_value<Cpu_number>(i),
                             entry_frame.cpu(i)->ip(), error_buffer.cpu(i));
                    else
-                     printf("    CPU%2u: is not in JDB (not responding)\n", i);
+                     printf("    CPU%2u: is not in JDB (not responding)\n",
+                             cxx::int_value<Cpu_number>(i));
                  }
              hide_statline = true;
            }
@@ -1140,7 +1142,7 @@ IMPLEMENTATION [!mp]:
 
 PRIVATE static
 bool
-Jdb::stop_all_cpus(unsigned /*current_cpu*/)
+Jdb::stop_all_cpus(Cpu_number)
 { return true; }
 
 PRIVATE
@@ -1156,7 +1158,7 @@ Jdb::check_for_cpus(bool)
 
 PRIVATE static inline
 int
-Jdb::remote_work_ipi_process(unsigned)
+Jdb::remote_work_ipi_process(Cpu_number)
 { return 1; }
 
 
@@ -1169,7 +1171,7 @@ EXTENSION class Jdb
 {
   // remote call
   static Spin_lock<> _remote_call_lock;
-  static void (*_remote_work_ipi_func)(unsigned, void *);
+  static void (*_remote_work_ipi_func)(Cpu_number, void *);
   static void *_remote_work_ipi_func_data;
   static unsigned long _remote_work_ipi_done;
 };
@@ -1177,7 +1179,7 @@ EXTENSION class Jdb
 //--------------------------------------------------------------------------
 IMPLEMENTATION [mp]:
 
-void (*Jdb::_remote_work_ipi_func)(unsigned, void *);
+void (*Jdb::_remote_work_ipi_func)(Cpu_number, void *);
 void *Jdb::_remote_work_ipi_func_data;
 unsigned long Jdb::_remote_work_ipi_done;
 Spin_lock<> Jdb::_remote_call_lock;
@@ -1187,10 +1189,10 @@ bool
 Jdb::check_for_cpus(bool try_nmi)
 {
   enum { Max_wait_cnt = 1000 };
-  for (unsigned c = 1; c < Config::Max_num_cpus; ++c)
+  for (Cpu_number c = Cpu_number::second(); c < Config::max_num_cpus(); ++c)
     {
       if (Cpu::online(c) && !running.cpu(c))
-       Ipi::send(Ipi::Debug, 0, c);
+       Ipi::send(Ipi::Debug, Cpu_number::first(), c);
     }
   Mem::barrier();
 retry:
@@ -1200,7 +1202,7 @@ retry:
       bool all_there = true;
       cpus_in_debugger = 0;
       // skip boot cpu 0
-      for (unsigned c = 1; c < Config::Max_num_cpus; ++c)
+      for (Cpu_number c = Cpu_number::second(); c < Config::max_num_cpus(); ++c)
        {
          if (Cpu::online(c))
            {
@@ -1225,13 +1227,14 @@ retry:
     }
 
   bool do_retry = false;
-  for (unsigned c = 1; c < Config::Max_num_cpus; ++c)
+  for (Cpu_number c = Cpu_number::second(); c < Config::max_num_cpus(); ++c)
     {
       if (Cpu::online(c))
        {
          if (!running.cpu(c))
            {
-             printf("JDB: CPU %d: is not responding ... %s\n",c,
+             printf("JDB: CPU %d: is not responding ... %s\n",
+                     cxx::int_value<Cpu_number>(c),
                     try_nmi ? "trying NMI" : "");
              if (try_nmi)
                {
@@ -1252,12 +1255,12 @@ retry:
 
 PRIVATE static
 bool
-Jdb::stop_all_cpus(unsigned current_cpu)
+Jdb::stop_all_cpus(Cpu_number current_cpu)
 {
   enum { Max_wait_cnt = 1000 };
-  // JDB allways runs on CPU 0, if any other CPU enters the debugger
-  // CPU 0 is notified to do enter the debugger too
-  if (current_cpu == 0)
+  // JDB allways runs on the boot CPU, if any other CPU enters the debugger
+  // the boot CPU is notified to do enter the debugger too
+  if (current_cpu == Cpu_number::boot_cpu())
     {
       // I'm CPU 0 stop all other CPUs and wait for them to enter the JDB
       jdb_active = 1;
@@ -1271,10 +1274,10 @@ Jdb::stop_all_cpus(unsigned current_cpu)
       // Huh, not CPU 0, so notify CPU 0 to enter JDB too
       // The notification is ignored if CPU 0 is already within JDB
       jdb_active = true;
-      Ipi::send(Ipi::Debug, current_cpu, 0);
+      Ipi::send(Ipi::Debug, current_cpu, Cpu_number::boot_cpu());
 
       unsigned long wait_count = Max_wait_cnt;
-      while (!running.cpu(0) && wait_count)
+      while (!running.cpu(Cpu_number::boot_cpu()) && wait_count)
        {
          Proc::pause();
           Delay::delay(1);
@@ -1283,14 +1286,14 @@ Jdb::stop_all_cpus(unsigned current_cpu)
        }
 
       if (wait_count == 0)
-       send_nmi(0);
+       send_nmi(Cpu_number::boot_cpu());
 
       // Wait for messages from CPU 0
       while ((volatile bool)jdb_active)
        {
          Mem::barrier();
-         void (**func)(unsigned, void *) = &remote_func.cpu(current_cpu);
-         void (*f)(unsigned, void *);
+         void (**func)(Cpu_number, void *) = &remote_func.cpu(current_cpu);
+         void (*f)(Cpu_number, void *);
 
          if ((f = monitor_address(current_cpu, func)))
            {
@@ -1334,13 +1337,13 @@ Jdb::leave_wait_for_others()
   for (;;)
     {
       bool all_there = true;
-      for (unsigned c = 0; c < Config::Max_num_cpus; ++c)
+      for (Cpu_number c = Cpu_number::first(); c < Config::max_num_cpus(); ++c)
        {
          if (Cpu::online(c) && running.cpu(c))
            {
              // notify other CPU
               set_monitored_address(&Jdb::remote_func.cpu(c),
-                                    (void (*)(unsigned, void *))0);
+                                    (void (*)(Cpu_number, void *))0);
 //           printf("JDB: wait for CPU[%2u] to leave\n", c);
              all_there = false;
            }
@@ -1369,7 +1372,7 @@ Jdb::leave_wait_for_others()
 // The remote_work_ipi* functions are for the IPI round-trip benchmark (only)
 PRIVATE static
 int
-Jdb::remote_work_ipi_process(unsigned cpu)
+Jdb::remote_work_ipi_process(Cpu_number cpu)
 {
   if (_remote_work_ipi_func)
     {
@@ -1383,8 +1386,8 @@ Jdb::remote_work_ipi_process(unsigned cpu)
 
 PUBLIC static
 bool
-Jdb::remote_work_ipi(unsigned this_cpu, unsigned to_cpu,
-                     void (*f)(unsigned, void *), void *data, bool wait = true)
+Jdb::remote_work_ipi(Cpu_number this_cpu, Cpu_number to_cpu,
+                     void (*f)(Cpu_number, void *), void *data, bool wait = true)
 {
   if (to_cpu == this_cpu)
     {
index 2163af45d9910631307a1076ace84623c31cdeeb..4473376d39f11e8b03ab164bd4ec874227de29ee 100644 (file)
@@ -71,7 +71,7 @@ Jdb_dbinfo::init()
   Address addr;
 
   for (addr = area_start; addr < area_end; addr += Config::SUPERPAGE_SIZE)
-    Kmem::kdir->walk(Virt_addr(addr), 100, pdir_alloc(Kmem_alloc::allocator()));
+    Kmem::kdir->walk(Virt_addr(addr), Pdir::Depth, false, pdir_alloc(Kmem_alloc::allocator()));
 
   init_symbols_lines();
 }
@@ -169,7 +169,7 @@ Jdb_dbinfo::map(Address phys, size_t &size, Address &virt)
 
   Kmem::kdir->map(phys, Virt_addr(virt), Virt_size(size),
       Pt_entry::Valid | Pt_entry::Writable | Pt_entry::Referenced
-      | Pt_entry::Dirty, 100, Ptab::Null_alloc());
+      | Pt_entry::Dirty, Pdir::Depth, false, Ptab::Null_alloc());
 
   virt += offs;
   return true;
@@ -183,8 +183,8 @@ Jdb_dbinfo::unmap(Address virt, size_t size)
     {
       virt &= Config::PAGE_MASK;
 
-      Kmem::kdir->unmap(Virt_addr(virt), Virt_size(size), 100);
-      Mem_unit::tlb_flush ();
+      Kmem::kdir->unmap(Virt_addr(virt), Virt_size(size), Pdir::Depth, false);
+      Mem_unit::tlb_flush();
 
       return_pages(virt, size/Config::PAGE_SIZE);
     }
index 0e8a985865cb1a31b43c8dddd587833babf8113f..0e734952afb7ae4da88936bc9e0f44b248631f38 100644 (file)
@@ -79,14 +79,14 @@ IMPLEMENTATION [vmx]:
 
 PRIVATE static
 void
-Jdb_exit_module::do_vmxoff(unsigned, void *)
+Jdb_exit_module::do_vmxoff(Cpu_number, void *)
 {
   asm volatile("vmxoff");
 }
 
 PRIVATE static
 void
-Jdb_exit_module::remote_vmxoff(unsigned cpu)
+Jdb_exit_module::remote_vmxoff(Cpu_number cpu)
 {
   Jdb::remote_work(cpu, do_vmxoff, 0);
 }
index a05b99d49a7886454be33971df01fed5c6212df8..9550e7ef184c93b9f481999a0246143db41a53bf 100644 (file)
@@ -24,12 +24,13 @@ Jdb_module::Action_code
 Jdb_idle_stats::action(int, void *&, char const *&, int &)
 {
   printf("\nIDLE STATISTICS --------------------------\n");
-  for (unsigned i = 0; i < Config::Max_num_cpus; ++i)
+  for (Cpu_number i = Cpu_number::first(); i < Config::max_num_cpus(); ++i)
     {
       if (!Cpu::online(i))
         continue;
 
-      printf("CPU[%2u]: %lu times idle, %lu times deep sleep\n", i,
+      printf("CPU[%2u]: %lu times idle, %lu times deep sleep\n",
+             cxx::int_value<Cpu_number>(i),
              Kernel_thread::_idle_counter.cpu(i),
              Kernel_thread::_deep_idle_counter.cpu(i));
     }
index fbc017646a2e5f5ccd35ca5cd9f0de798e98d4d9..24f16862e8ed42d50aebda435774da9d60a48a18 100644 (file)
@@ -28,10 +28,11 @@ static Jdb_io_apic_module jdb_io_apic_module INIT_PRIORITY(JDB_MODULE_INIT_PRIO)
 
 PRIVATE static
 void
-Jdb_io_apic_module::print_lapic(unsigned cpu, void *)
+Jdb_io_apic_module::print_lapic(Cpu_number cpu, void *)
 {
-  printf("\nLocal APIC [%u, %08x]: tpr=%2x ppr=%2x\n", cpu, Apic::get_id(), Apic::tpr(),
-         Apic::reg_read(0xa0));
+  printf("\nLocal APIC [%u, %08x]: tpr=%2x ppr=%2x\n",
+         cxx::int_value<Cpu_number>(cpu),
+         Apic::get_id(), Apic::tpr(), Apic::reg_read(0xa0));
   printf("  Running: tpr=%02x\n", Jdb::apic_tpr.cpu(cpu));
 
   unsigned const regs[] = { 0x200, 0x100, 0x180 };
@@ -50,7 +51,7 @@ Jdb_io_apic_module::print_lapic(unsigned cpu, void *)
 
 PRIVATE static
 void
-Jdb_io_apic_module::remote_print_lapic(unsigned cpu)
+Jdb_io_apic_module::remote_print_lapic(Cpu_number cpu)
 {
   Jdb::remote_work(cpu, print_lapic, 0);
 }
index 94f3d036238fac1021aab31ffbe40f04917ce034..eb47e989221d99fbe06f5a765bbd15e702009a22 100644 (file)
@@ -18,11 +18,11 @@ static Jdb_ipi_module jdb_ipi_module INIT_PRIORITY(JDB_MODULE_INIT_PRIO);
 
 PRIVATE static
 void
-Jdb_ipi_module::print_info(unsigned cpu)
+Jdb_ipi_module::print_info(Cpu_number cpu)
 {
   Ipi &ipi = Ipi::_ipi.cpu(cpu);
   printf("CPU%02u sent/rcvd: %ld/%ld\n",
-         cpu, ipi._stat_sent, ipi._stat_received);
+         cxx::int_value<Cpu_number>(cpu), ipi._stat_sent, ipi._stat_received);
 }
 
 PUBLIC
index d6b0f4a5427eb6beeb5552f6dc04d603d91245cf..e642bd5515730c09429ae133f4ece829294ec89c 100644 (file)
@@ -67,7 +67,7 @@ static int ipi_cnt;
 
 PRIVATE static
 void
-Jdb_kern_info_bench::wait_for_ipi(unsigned cpu, void *)
+Jdb_kern_info_bench::wait_for_ipi(Cpu_number cpu, void *)
 {
   Jdb::restore_irqs(cpu);
   stop_timer();
@@ -82,17 +82,17 @@ Jdb_kern_info_bench::wait_for_ipi(unsigned cpu, void *)
 
 PRIVATE static
 void
-Jdb_kern_info_bench::empty_func(unsigned, void *)
+Jdb_kern_info_bench::empty_func(Cpu_number, void *)
 {
   ++ipi_cnt;
 }
 
 PRIVATE static
 void
-Jdb_kern_info_bench::do_ipi_bench(unsigned my_cpu, void *_partner)
+Jdb_kern_info_bench::do_ipi_bench(Cpu_number my_cpu, void *_partner)
 {
   Unsigned64 time;
-  unsigned partner = (unsigned long)_partner;
+  Cpu_number partner = Cpu_number((unsigned long)_partner);
   enum {
     Runs2  = 3,
     Warmup = 4,
@@ -110,7 +110,8 @@ Jdb_kern_info_bench::do_ipi_bench(unsigned my_cpu, void *_partner)
   for (i = 0; i < (1 << Runs2); i++)
     Jdb::remote_work_ipi(my_cpu, partner, empty_func, 0, true);
 
-  printf(" %2u:%8lld", partner, (get_time_now() - time) >> Runs2);
+  printf(" %2u:%8lld", cxx::int_value<Cpu_number>(partner),
+         (get_time_now() - time) >> Runs2);
 
   if (ipi_cnt != Rounds)
     printf("\nCounter mismatch: cnt=%d v %d\n", ipi_cnt, Rounds);
@@ -125,33 +126,35 @@ Jdb_kern_info_bench::do_mp_benchmark()
 {
   // IPI bench matrix
   printf("IPI round-trips:\n");
-  for (unsigned u = 0; u < Config::Max_num_cpus; ++u)
+  for (Cpu_number u = Cpu_number::first(); u < Config::max_num_cpus(); ++u)
     if (Cpu::online(u))
       {
-        printf("l%2u: ", u);
+        printf("l%2u: ", cxx::int_value<Cpu_number>(u));
 
-       for (unsigned v = 0; v < Config::Max_num_cpus; ++v)
+       for (Cpu_number v = Cpu_number::first(); v < Config::max_num_cpus(); ++v)
          if (Cpu::online(v))
            {
              if (u == v)
-               printf(" %2u:%8s", u, "X");
+               printf(" %2u:%8s", cxx::int_value<Cpu_number>(u), "X");
              else
                {
                  ipi_bench_spin_done = 0;
 
                  // v is waiting for IPIs
-                 if (v != 0)
+                 if (v != Cpu_number::boot_cpu())
                    Jdb::remote_work(v, wait_for_ipi, 0, false);
 
                  // u is doing benchmark
-                 if (u == 0)
-                   do_ipi_bench(0, (void *)v);
+                 if (u == Cpu_number::boot_cpu())
+                   do_ipi_bench(Cpu_number::boot_cpu(),
+                                 (void *)(long)cxx::int_value<Cpu_number>(v));
                  else
-                    Jdb::remote_work(u, do_ipi_bench, (void *)v, false);
+                    Jdb::remote_work(u, do_ipi_bench,
+                                    (void *)(long)cxx::int_value<Cpu_number>(v), false);
 
                  // v is waiting for IPIs
-                 if (v == 0)
-                   wait_for_ipi(0, 0);
+                 if (v == Cpu_number::boot_cpu())
+                   wait_for_ipi(Cpu_number::boot_cpu(), 0);
 
                  Mem::barrier();
 
index a236586b09144a4712f1d72df317c7ba7d4c9e25..07cdecf8ea09b12b2af7b76fcb4c1c3e45b5ebd3 100644 (file)
@@ -1,7 +1,7 @@
 INTERFACE:
 
 #include "jdb_module.h"
-#include <slist>
+#include <cxx/slist>
 
 class Jdb_kern_info_module;
 
index db249840aa031d7fef9d7c5e1ec055bd81b66941..b432a8373d4b75c53726e79c485414259c4a9b03 100644 (file)
@@ -3,7 +3,7 @@ INTERFACE:
 #include "jdb_module.h"
 #include "jdb_list.h"
 #include "kobject.h"
-#include <slist>
+#include <cxx/slist>
 
 class Kobject;
 class Jdb_kobject_handler;
index fe86479ef30a131bd80c1db559baae41fd288dfd..64ff3edcde94ed736c3ad9e1a3618465df6df10c 100644 (file)
@@ -45,12 +45,22 @@ size_str (Mword size)
   return scratchbuf;
 }
 
+static
+unsigned long long
+Jdb_mapdb::val(Mdb_types::Pfn p, Mdb_types::Order base_size)
+{
+  return cxx::int_value<Mdb_types::Pfn>(p << base_size);
+}
+
+
 static
 bool
-Jdb_mapdb::show_tree(Treemap* pages, Page_number address,
+Jdb_mapdb::show_tree(Treemap* pages, Mapping::Pcnt offset, Mdb_types::Order base_size,
                     unsigned &screenline, unsigned indent = 1)
 {
-  Page_number   page = address >> pages->_page_shift;
+  typedef Treemap::Page Page;
+
+  Page       page = pages->trunc_to_page(offset);
   Physframe*    f = pages->frame(page);
   Mapping_tree* t = f->tree.get();
   unsigned      i;
@@ -58,16 +68,18 @@ Jdb_mapdb::show_tree(Treemap* pages, Page_number address,
 
   if (! t)
     {
-      printf(" no mapping tree registered for frame number 0x%x\033[K\n",
-            (unsigned) page.value());
+      printf(" no mapping tree registered for frame number 0x%lx\033[K\n",
+            cxx::int_value<Mapping::Page>(page));
       screenline++;
       return true;
     }
 
-  printf(" mapping tree for %s-page " L4_PTR_FMT " of task %p - header at "
-        L4_PTR_FMT "\033[K\n",
-        size_str (1UL << pages->_page_shift),
-        pages->vaddr(t->mappings()).value(), t->mappings()[0].space(), (Address)t);
+  printf(" mapping tree for %s-page %012llx of task %lx - header at "
+         L4_PTR_FMT "\033[K\n",
+         size_str(1ULL << cxx::int_value<Mdb_types::Order>(pages->_page_shift + base_size)),
+         val(pages->vaddr(t->mappings()), base_size),
+         Kobject_dbg::pointer_to_id(t->mappings()[0].space()),
+         (Address)t);
 #ifdef NDEBUG
   // If NDEBUG is active, t->_empty_count is undefined
   printf(" header info: "
@@ -118,10 +130,10 @@ Jdb_mapdb::show_tree(Treemap* pages, Page_number address,
               i+1, (Address) m->data(), (Mword) m->submap());
       else
        {
-         printf("%*u: %lx  va=" L4_PTR_FMT "  task=%lx  depth=",
+         printf("%*u: %lx  va=%012llx  task=%lx  depth=",
                 indent + m->depth() > 10 ? 0 : indent + m->depth(),
                 i+1, (Address) m->data(),
-                pages->vaddr(m).value(),
+                val(pages->vaddr(m), base_size),
                  Kobject_dbg::pointer_to_id(m->space()));
 
          if (m->depth() == Mapping::Depth_root)
@@ -154,7 +166,8 @@ Jdb_mapdb::show_tree(Treemap* pages, Page_number address,
       if (m->depth() == Mapping::Depth_submap)
        {
          if (! Jdb_mapdb::show_tree(m->submap(),
-                                    address.offset(Page_count::create(1UL << pages->_page_shift)),
+                                    cxx::get_lsb(offset, pages->_page_shift),
+                                     base_size,
                                     screenline, indent + m->parent()->depth()))
            return false;
        }
@@ -167,58 +180,58 @@ static
 Address
 Jdb_mapdb::end_address (Mapdb* mapdb)
 {
-  return mapdb->_treemap->end_addr().value();
+  return cxx::int_value<Mdb_types::Pfn>(mapdb->_treemap->end_addr());
 }
 
 static
 void
-Jdb_mapdb::show (Page_number page, char which_mapdb)
+Jdb_mapdb::show(Mapping::Pfn page, char which_mapdb)
 {
   unsigned     j;
   int          c;
 
   Jdb::clear_screen();
+  typedef Mdb_types::Order Order;
 
   for (;;)
     {
       Mapdb* mapdb;
       const char* type;
-      Mword page_shift;
-      Page_count super_inc;
+      Mapping::Pcnt super_inc;
+      Mdb_types::Order super_shift;
+      Order base_size = Order(0);
 
       switch (which_mapdb)
        {
        case 'm':
          type = "Phys frame";
          mapdb = mapdb_mem.get();
-         page_shift = 0; //Config::PAGE_SHIFT;
-         super_inc = Page_count::create(Config::SUPERPAGE_SIZE / Config::PAGE_SIZE);
+          base_size = Order(Config::PAGE_SHIFT);
+          super_shift = Mdb_types::Order(Config::SUPERPAGE_SHIFT - Config::PAGE_SHIFT);
          break;
 #ifdef CONFIG_PF_PC
        case 'i':
          type = "I/O port";
          mapdb = mapdb_io.get();
-         page_shift = 0;
-         super_inc = Page_count::create(0x100);
+          base_size = Order(0);
+          super_shift = Mdb_types::Order(8);
          break;
 #endif
        default:
          return;
        }
 
-      if (! mapdb->valid_address (page << page_shift))
-       page = Page_number::create(0);
+      super_inc = Mapping::Pcnt(1) << super_shift;
+
+      if (! mapdb->valid_address(page))
+       page = Mapping::Pfn(0);
 
       Jdb::cursor();
-      printf ("%s " L4_PTR_FMT "\033[K\n\033[K\n",
-             type, page.value() << page_shift);
+      printf("%s %012llx\033[K\n\033[K\n", type, val(page, base_size));
 
       j = 3;
 
-      if (! Jdb_mapdb::show_tree (mapdb->_treemap,
-                                 (page << page_shift)
-                                   - mapdb->_treemap->_page_offset,
-                                 j))
+      if (! Jdb_mapdb::show_tree(mapdb->_treemap, page - Mapping::Pfn(0), base_size, j))
        return;
 
       for (; j<Jdb_screen::height(); j++)
@@ -237,28 +250,28 @@ Jdb_mapdb::show (Page_number page, char which_mapdb)
            {
            case 'n':
            case KEY_CURSOR_DOWN:
-             if (! mapdb->valid_address(++page << page_shift))
-                page = Page_number::create(0);
+             if (! mapdb->valid_address(++page))
+                page = Mapping::Pfn(0);
              redraw = true;
              break;
            case 'p':
            case KEY_CURSOR_UP:
-             if (! mapdb->valid_address(--page << page_shift))
-                page = Page_number::create(end_address (mapdb) - 1) >> page_shift;
+             if (! mapdb->valid_address(--page))
+                page = Mapping::Pfn(end_address(mapdb) - 1);
              redraw = true;
              break;
            case 'N':
            case KEY_PAGE_DOWN:
-             page = (page + super_inc).trunc(super_inc);
-             if (! mapdb->valid_address(page << page_shift))
-                page = Page_number::create(0);
+             page = cxx::mask_lsb(page + super_inc, super_shift);
+             if (! mapdb->valid_address(page))
+                page = Mapping::Pfn(0);
              redraw = true;
              break;
            case 'P':
            case KEY_PAGE_UP:
-             page = (page - super_inc).trunc(super_inc);
-             if (! mapdb->valid_address(page << page_shift))
-                page = Page_number::create(end_address (mapdb) - 1) >> page_shift;
+             page = cxx::mask_lsb(page - super_inc, super_shift);
+             if (! mapdb->valid_address(page))
+                page = Mapping::Pfn(end_address(mapdb) - 1);
              redraw = true;
              break;
            case ' ':
@@ -325,11 +338,7 @@ Jdb_mapdb::action(int cmd, void *&args, char const *&fmt, int &next_char)
          fmt = " port: " L4_FRAME_INPUT_FMT;
          break;
 #endif
-
-       case 'o':
-         fmt = " object: %x";
-         break;
-       }
+        }
 
       which_mapdb = subcmd;
       args = &pagenum;
@@ -340,10 +349,7 @@ Jdb_mapdb::action(int cmd, void *&args, char const *&fmt, int &next_char)
     return NOTHING;
 
  doit:
-  if (which_mapdb == 'o')
-    Jdb_mapdb::show_simple_tree((Kobject_common*)pagenum);
-  else
-    show(Page_number::create(pagenum), which_mapdb);
+  show(Mapping::Pfn(pagenum), which_mapdb);
   return NOTHING;
 }
 
@@ -354,7 +360,7 @@ Jdb_mapdb::cmds() const
   static Cmd cs[] =
     {
        { 0, "m", "mapdb", "%c",
-         "m[it]<addr>\tshow [I/O,task] mapping database starting at address",
+         "m[i]<addr>\tshow [I/O] mapping database starting at address",
          &subcmd },
         { 1, "", "dumpmapdbobjs", "",
           "dumpmapdbobjs\tDump complete object mapping database", 0 },
@@ -502,12 +508,13 @@ Jdb_mapdb::show_simple_tree(Kobject_common *f, unsigned indent = 1)
 
       if (pi)
        {
-         space_id = static_cast<Task*>(pi->info<Obj_space::Dbg_info>()->s)->dbg_info()->dbg_id();
-         cap_idx += pi->info<Obj_space::Dbg_info>()->offset;
+         space_id = static_cast<Task*>(pi->info<Obj::Cap_page_dbg_info>()->s)->dbg_info()->dbg_id();
+         cap_idx += pi->info<Obj::Cap_page_dbg_info>()->offset;
        }
 
       printf("  " L4_PTR_FMT "[C:%lx]: space=D:%lx rights=%x flags=%lx obj=%p",
-            (Address)*m, cap_idx, space_id, (unsigned)e->rights(), e->_flags,
+            (Address)*m, cap_idx, space_id,
+             (unsigned)cxx::int_value<Obj::Attr>(e->rights()), e->_flags,
             e->obj());
 
       puts("\033[K");
index 8a649c246cceb30e0555ae2c45bb432a632c7767..30a7a6950ebbfc2b860348a323e53822d0c3f280 100644 (file)
@@ -1,8 +1,8 @@
 INTERFACE:
 
 #include <cstdarg>
-#include <hlist>
-#include <slist>
+#include <cxx/hlist>
+#include <cxx/slist>
 
 #include "initcalls.h"
 
index 2e4dcd6fb61ad1f66e09b4ce6f2b6c60f9e1a937..e50e9fc6f2b00e7ecde511e62c116ebedef2157d 100644 (file)
@@ -19,9 +19,9 @@ public:
   struct Find_cpu
   {
     Item const *r;
-    mutable unsigned cpu;
+    mutable Cpu_number cpu;
     Find_cpu(Item const *i) : r(i), cpu(~0U) {}
-    void operator()(unsigned _cpu) const
+    void operator()(Cpu_number _cpu) const
     {
       if (&Mp_request_queue::rq.cpu(_cpu) == r)
         {
@@ -35,11 +35,11 @@ public:
 static Jdb_mp_request_module jdb_mp_request_module INIT_PRIORITY(JDB_MODULE_INIT_PRIO);
 
 PRIVATE static
-unsigned
+Cpu_number
 Jdb_mp_request_module::find_cpu(Item const *r)
 {
   if (!r)
-    return 0;
+    return Cpu_number::boot_cpu();
 
   Find_cpu _find_cpu(r);
   Jdb::foreach_cpu(_find_cpu);
@@ -54,12 +54,12 @@ Jdb_mp_request_module::print_request(Item const *item)
          "    value  = { func = %p, arg = %p, _lock=%lu }\n"
          "    next   = %p (cpu %u)\n",
          find_cpu(item), item, item->value.func, item->value.arg, item->value._lock,
-         item->next, find_cpu(item->next));
+         item->next, Cpu_number::val(find_cpu(item->next)));
 }
 
 PRIVATE static
 void
-Jdb_mp_request_module::print_queue(unsigned cpu)
+Jdb_mp_request_module::print_queue(Cpu_number cpu)
 {
 
   if (!Jdb::cpu_in_jdb(cpu))
@@ -67,10 +67,10 @@ Jdb_mp_request_module::print_queue(unsigned cpu)
       bool online = Cpu::online(cpu);
       if (!online)
        {
-         printf("CPU %u is not online...\n", cpu);
+         printf("CPU %u is not online...\n", Cpu_number::val(cpu));
          return;
        }
-      printf("CPU %u has not entered JDB (try to display queue...\n", cpu);
+      printf("CPU %u has not entered JDB (try to display queue...\n", Cpu_number::val(cpu));
     }
 
   Item const *item = &Mp_request_queue::rq.cpu(cpu);
@@ -79,7 +79,7 @@ Jdb_mp_request_module::print_queue(unsigned cpu)
 
   printf("CPU[%2u]: Mp request item @%p, Mp request FIFO @%p\n"
          " Local queue Item:\n",
-         cpu, item, fifo);
+         Cpuz_number::val(cpu), item, fifo);
 
   print_request(item);
 
@@ -102,11 +102,11 @@ Jdb_module::Action_code
 Jdb_mp_request_module::action (int cmd, void *&argbuf, char const *&fmt, int &next)
 {
   char const *c = (char const *)argbuf;
-  unsigned cpu;
+  Cpu_number cpu;
   if (cmd!=0)
     return NOTHING;
 
-  if (argbuf != &cpu)
+  if (argbuf != &Cpu_number::val(cpu))
     {
       if (*c == 'a')
        Jdb::foreach_cpu(&print_queue);
index 26e2fb35ed2c0076d24dd6e6200398c882d5d8a1..ac728d0cb3814ff9aa38a6ab02abb05b6b4c1fb9 100644 (file)
@@ -96,18 +96,18 @@ Jdb_obj_space::print_statline(unsigned long row, unsigned long col)
   if (!o)
     {
       Jdb::printf_statline("objs", "<Space>=mode", "%lx: -- INVALID --",
-                           index(row,col));
+                           cxx::int_value<Cap_index>(index(row,col)));
       return;
     }
 
   unsigned len = Jdb_kobject::obj_description(buf, sizeof(buf), true, o->dbg_info());
   Jdb::printf_statline("objs", "<Space>=mode",
-                      "%lx: %-*s", index(row,col), len, buf);
+                      "%lx: %-*s", cxx::int_value<Cap_index>(index(row,col)), len, buf);
 }
 
 PUBLIC
 void
-Jdb_obj_space::print_entry(Address entry)
+Jdb_obj_space::print_entry(Cap_index entry)
 {
   unsigned rights;
   Kobject_iface *o = item(entry, &rights);
@@ -122,9 +122,9 @@ Jdb_obj_space::print_entry(Address entry)
        case Name:
          switch (rights)
            {
-           case L4_fpage::WX: r = '*'; break;
-           case L4_fpage::W:  r = 'w'; break;
-           case L4_fpage::X:  r = 'x'; break;
+           case 0x3: r = '*'; break;
+           case 0x2:  r = 'w'; break;
+           case 0x1:  r = 'x'; break;
            }
          printf("%05lx%c %-*s", o->dbg_info()->dbg_id(), r, 9, Jdb_kobject::kobject_type(o));
          break;
@@ -141,17 +141,17 @@ void
 Jdb_obj_space::draw_entry(unsigned long row, unsigned long col)
 {
   if (col==0)
-    printf("%06lx ", index(row, 1));
+    printf("%06lx ", cxx::int_value<Cap_index>(index(row, 1)));
   else
     print_entry(index(row, col));
 }
 
 PRIVATE
-Address
+Cap_index
 Jdb_obj_space::index(unsigned long row, unsigned long col)
 {
   Mword e = (col-1) + (row * (cols()-1));
-  return _base + e;
+  return Cap_index(_base + e);
 }
 
 PRIVATE
@@ -221,36 +221,11 @@ Jdb_obj_space::handle_key(Kobject_common *o, int code)
 
 static Jdb_obj_space jdb_obj_space INIT_PRIORITY(JDB_MODULE_INIT_PRIO);
 
-// ------------------------------------------------------------------------
-IMPLEMENTATION [obj_space_virt]:
-
-PUBLIC
-Kobject_iface *
-Jdb_obj_space::item(Address entry, unsigned *rights)
-{
-  Mword dummy;
-  Obj_space::Capability *c = _task->cap_virt(entry);
-  if (!c)
-    return 0;
-
-  Mword mapped = Jdb::peek((Mword*)c, _task, dummy);
-
-  if (!mapped)
-    return 0;
-
-  Kobject_iface *o = (Kobject_iface*)(dummy & ~3UL);
-  *rights = dummy & 3;
-
-  return o;
-}
-
-// ------------------------------------------------------------------------
-IMPLEMENTATION [obj_space_phys]:
 PUBLIC
 Kobject_iface *
-Jdb_obj_space::item(Address entry, unsigned *rights)
+Jdb_obj_space::item(Cap_index entry, unsigned *rights)
 {
-  Obj_space::Capability *c = _task->get_cap(entry);
+  Obj_space::Capability *c = _task->jdb_lookup_cap(entry);
 
   if (!c)
     return 0;
index e62dfa54e21ba02c01cbce5a80f522c33bfd22d7..1e63b1a66b5d30b87aadacb079fc1d27039d6735 100644 (file)
@@ -1,6 +1,6 @@
 INTERFACE:
 
-#include <hlist>
+#include <cxx/hlist>
 
 class Jdb_prompt_ext : public cxx::H_list_item
 {
index 01e1bca99418ccf4088335ba320aa5eeea57c016..b8f6df3c7de4c057ca4e1da59f7facc278c2df75 100644 (file)
-IMPLEMENTATION [ia32,ux]:
+IMPLEMENTATION [ia32,ux,arm]:
 
 #include "paging.h"
 
-unsigned Jdb_ptab::max_pt_level = Pdir::Depth;
-
-static unsigned long _leaf_check[]
-= { Pt_entry::Pse_bit | Pt_entry::Valid, 0 };
-static unsigned long next_level_mask[]
-= { 0xfffff000, 0 };
-
-
-static inline bool leaf_check(unsigned long entry, unsigned level)
-{ return (_leaf_check[level] & entry) == _leaf_check[level]; }
-
-IMPLEMENT
-unsigned
-Jdb_ptab::entry_is_pt_ptr(Mword entry, unsigned level,
-                          unsigned *entries, unsigned *next_level)
-{
-  if (leaf_check(entry, level))
-    return 0;
-  *entries = Ptab::Level<Pdir::Traits, Pdir::Depth>::length(level);
-  *next_level = level+1;
-  return 1;
-}
-
-IMPLEMENT
-Address
-Jdb_ptab::entry_phys(Mword entry, unsigned level)
-{
-  if (!leaf_check(entry, level))
-    return entry & next_level_mask[level];
-
-  return Ptab::Level<Pdir::Traits, Pdir::Depth>::addr(level, entry);
-}
-
-IMPLEMENT inline NEEDS ["paging.h"]
-unsigned
-Jdb_ptab::entry_valid(Mword entry, unsigned)
-{ return entry & Pt_entry::Valid; }
+IMPLEMENTATION [ia32,ux]:
 
 IMPLEMENT
 void
-Jdb_ptab::print_entry(Mword entry, unsigned level)
+Jdb_ptab::print_entry(Pdir::Pte_ptr const &entry)
 {
   if (dump_raw)
     {
-      printf(L4_PTR_FMT, entry);
+      printf(L4_PTR_FMT, *entry.pte);
       return;
     }
 
-  if (!entry_valid(entry,level))
+  if (!entry.is_valid())
     {
       putstr("    -   ");
       return;
     }
 
-  Address phys = entry_phys(entry, level);
+  Address phys = entry_phys(entry);
 
-  if (level == Pdir::Super_level && entry & Pt_entry::Pse_bit)
+  if (entry.level != Pdir::Depth && entry.is_leaf())
     printf((phys >> 20) > 0xFF
            ? "%03lX/4" : " %02lX/4", phys >> 20);
   else
     printf((phys >> Config::PAGE_SHIFT) > 0xFFFF
            ? "%05lx" : " %04lx", phys >> Config::PAGE_SHIFT);
 
-  putchar(((cur_pt_level>=max_pt_level || (entry & Pt_entry::Pse_bit)) &&
-        (entry & Pt_entry::Cpu_global)) ? '+' : '-');
-  printf("%s%c%s", entry & Pt_entry::Noncacheable ? JDB_ANSI_COLOR(lightblue) : "",
-                   entry & Pt_entry::Noncacheable
-                   ? 'n' : (entry & Pt_entry::Write_through) ? 't' : '-',
-                   entry & Pt_entry::Noncacheable ? JDB_ANSI_END : "");
-  putchar(entry & Pt_entry::User
-           ? (entry & Pt_entry::Writable) ? 'w' : 'r'
-           : (entry & Pt_entry::Writable) ? 'W' : 'R');
+  putchar(((cur_pt_level >= Pdir::Depth || entry.is_leaf()) &&
+         (*entry.pte & Pt_entry::Cpu_global)) ? '+' : '-');
+  printf("%s%c%s", *entry.pte & Pt_entry::Noncacheable ? JDB_ANSI_COLOR(lightblue) : "",
+                   *entry.pte & Pt_entry::Noncacheable
+                   ? 'n' : (*entry.pte & Pt_entry::Write_through) ? 't' : '-',
+                   *entry.pte & Pt_entry::Noncacheable ? JDB_ANSI_END : "");
+  putchar(*entry.pte & Pt_entry::User
+           ? (*entry.pte & Pt_entry::Writable) ? 'w' : 'r'
+           : (*entry.pte & Pt_entry::Writable) ? 'W' : 'R');
 }
 
-PUBLIC
-unsigned long
-Jdb_ptab::rows() const
-{ return entries/8; }
-
-IMPLEMENTATION [ia32,ux,arm]:
-
-#if 0
-// calculate row from virtual address
-PRIVATE
-unsigned
-Jdb_ptab::disp_virt_to_r(Address v)
-{
-  v = Ptab::Level<Pdir::Traits, Pdir::Depth>::index(cur_pt_level, v >> Pdir::Va::Shift);
-  return v / (cols()-1);
-}
-
-// calculate column from virtual address
-PRIVATE
-unsigned
-Jdb_ptab::disp_virt_to_c(Address v)
-{
-  v = Ptab::Level<Pdir::Traits, Pdir::Depth>::index(cur_pt_level, v >> Pdir::Va::Shift);
-  return (v % (cols()-1)) + 1;
-}
-#endif
-
-PRIVATE
-Address
-Jdb_ptab::disp_virt(unsigned row, unsigned col)
-{
-  Pdir::Va e((col-1) + (row * (cols()-1)));
-  e <<= Ptab::Level<Pdir::Traits, Pdir::Depth>::shift(cur_pt_level);
-  return Virt_addr(e).value() + virt_base;
-}
-
-PUBLIC
-void
-Jdb_ptab::print_statline(unsigned long row, unsigned long col)
-{
-  unsigned long sid = Kobject_dbg::pointer_to_id(_task);
-
-  if (cur_pt_level<max_pt_level)
-    Jdb::printf_statline("pdir", "<Space>=mode <CR>=goto ptab/superpage",
-                         "<" L4_PTR_FMT "> task D:%lx", disp_virt(row,col), sid);
-  else // PT_MODE
-    Jdb::printf_statline("ptab", "<Space>=mode <CR>=goto page",
-                         "<" L4_PTR_FMT "> task D:%lx", disp_virt(row,col), sid);
-}
index 4b99fe1861e2ce90c4ed020a1ac2b248cca57c1e..1745847863cf09387d9a68402666c9d7be427395 100644 (file)
@@ -38,15 +38,12 @@ private:
   unsigned char cur_pt_level;
   char dump_raw;
 
-  static unsigned max_pt_level;
-
-  static unsigned entry_valid(Mword entry, unsigned level);
-  static unsigned entry_is_pt_ptr(Mword entry, unsigned level,
+  static unsigned entry_is_pt_ptr(Pdir::Pte_ptr const &entry,
                                   unsigned *entries, unsigned *next_level);
-  static Address entry_phys(Mword entry, unsigned level);
+  static Address entry_phys(Pdir::Pte_ptr const &entry);
 
-  void print_entry(Mword entry, unsigned level);
-  void print_head(Mword entry);
+  void print_entry(Pdir::Pte_ptr const &);
+  void print_head(void *entry);
 };
 
 char Jdb_ptab_m::first_char;
@@ -61,8 +58,8 @@ Jdb_ptab::Jdb_ptab(void *pt_base = 0, Space *task = 0,
 : base((Address)pt_base), virt_base(virt_base), _level(level),
   _task(task), entries(entries), cur_pt_level(pt_level), dump_raw(0)
 {
-  if (!pt_level && entries == 0)
-    this->entries = 1UL << Ptab::Level<Pdir::Traits,0>::Traits::Size;
+  if (entries == 0)
+    this->entries = Pdir::entries_at_level(pt_level);
 }
 
 PUBLIC
@@ -92,25 +89,70 @@ PUBLIC
 void
 Jdb_ptab::draw_entry(unsigned long row, unsigned long col)
 {
-  if (col==0)
-    print_head(virt(row, 1));
+  int idx;
+  if (col == 0)
+    {
+      idx = index(row, 1);
+      if (idx >= 0)
+        print_head(pte(idx));
+      else
+        putstr("        ");
+    }
+  else if ((idx = index(row, col)) >= 0)
+    print_entry(Pdir::Pte_ptr(pte(idx), cur_pt_level));
   else
-    print_entry(*(My_pte*)(virt(row,col)), cur_pt_level);
+    putstr("   ###  ");
 }
 
-PRIVATE
+IMPLEMENT
 Address
-Jdb_ptab::virt(unsigned long row, unsigned long col)
+Jdb_ptab::entry_phys(Pdir::Pte_ptr const &entry)
+{
+  if (!entry.is_leaf())
+    return entry.next_level();
+
+  return entry.page_addr();
+}
+
+
+PRIVATE inline
+int
+Jdb_ptab::index(unsigned row, unsigned col)
 {
   Mword e = (col-1) + (row * (cols()-1));
-  return base + e * sizeof(Mword);
+  if (e < Pdir::Levels::length(cur_pt_level))
+    return e;
+  else
+    return -1;
+}
+
+
+PRIVATE inline
+void *
+Jdb_ptab::pte(int index)
+{
+  return (void*)(base + index * Pdir::Levels::entry_size(cur_pt_level));
+}
+
+IMPLEMENT
+unsigned
+Jdb_ptab::entry_is_pt_ptr(Pdir::Pte_ptr const &entry,
+                          unsigned *entries, unsigned *next_level)
+{
+  if (!entry.is_valid() || entry.is_leaf())
+    return 0;
+
+  *entries = Pdir::entries_at_level(entry.level+1);
+  *next_level = entry.level+1;
+  return 1;
 }
 
+
 IMPLEMENT
 void
-Jdb_ptab::print_head(Mword entry)
+Jdb_ptab::print_head(void *entry)
 {
-  printf(L4_PTR_FMT, entry);
+  printf(L4_PTR_FMT, (Address)entry);
 }
 
 PUBLIC
@@ -125,7 +167,7 @@ Jdb_ptab_m::handle_key(Kobject_common *o, int code)
     {
       Thread *th = Kobject::dcast<Thread_object*>(o);
       if (!th || !th->space())
-       return false;
+        return false;
 
       t = th->space();
     }
@@ -157,27 +199,30 @@ Jdb_ptab::key_pressed(int c, unsigned long &row, unsigned long &col)
     case KEY_RETURN:   // goto ptab/address under cursor
       if (_level<=7)
        {
-         My_pte pt_entry = *(My_pte*)virt(row,col);
-         if (!entry_valid(pt_entry, cur_pt_level))
+          int idx = index(row, col);
+          if (idx < 0)
+            break;
+
+          Pdir::Pte_ptr pt_entry(pte(idx), cur_pt_level);
+         if (!pt_entry.is_valid())
            break;
 
-         Address pd_virt = (Address)
-           Mem_layout::phys_to_pmem(entry_phys(pt_entry, cur_pt_level));
+         void *pd_virt = (void*)Mem_layout::phys_to_pmem(entry_phys(pt_entry));
 
          unsigned next_level, entries;
 
-         if (cur_pt_level < max_pt_level
-             && entry_is_pt_ptr(pt_entry, cur_pt_level, &entries, &next_level))
+         if (cur_pt_level < Pdir::Depth
+             && entry_is_pt_ptr(pt_entry, &entries, &next_level))
            {
-             Jdb_ptab pt_view((void *)pd_virt, _task, next_level, entries,
-                              disp_virt(row,col), _level+1);
+             Jdb_ptab pt_view(pd_virt, _task, next_level, entries,
+                              disp_virt(idx), _level+1);
              if (!pt_view.show(0,1))
                return Exit;
              return Redraw;
            }
          else if (jdb_dump_addr_task != 0)
            {
-             if (!jdb_dump_addr_task(disp_virt(row,col), _task, _level+1))
+             if (!jdb_dump_addr_task(disp_virt(idx), _task, _level+1))
                return Exit;
              return Redraw;
            }
@@ -188,6 +233,40 @@ Jdb_ptab::key_pressed(int c, unsigned long &row, unsigned long &col)
   return Handled;
 }
 
+PRIVATE
+Address
+Jdb_ptab::disp_virt(int idx)
+{
+  Pdir::Va e((Mword)idx << Pdir::lsb_for_level(cur_pt_level));
+  return Virt_addr::val(e) + virt_base;
+}
+
+PUBLIC
+unsigned long
+Jdb_ptab::rows() const
+{
+  if (cols() > 1)
+    return (entries + cols() - 2) / (cols()-1);
+  return 0;
+}
+
+PUBLIC
+void
+Jdb_ptab::print_statline(unsigned long row, unsigned long col)
+{
+  unsigned long sid = Kobject_dbg::pointer_to_id(_task);
+
+  Address va;
+  int idx = index(row, col);
+  if (idx >= 0)
+    va = disp_virt(idx);
+  else
+    va = -1;
+
+  Jdb::printf_statline("p:", "<Space>=mode <CR>=goto page/next level",
+                       "<level=%1d> <" L4_PTR_FMT "> task D:%lx", cur_pt_level, va, sid);
+}
+
 PUBLIC
 Jdb_module::Action_code
 Jdb_ptab_m::action(int cmd, void *&args, char const *&fmt, int &next_char)
index a3f081852e652cf394ba0063cab6e2e84431a88e..81c0c16156f9ff893ff998608e95742f8af62012 100644 (file)
@@ -45,17 +45,17 @@ Jdb_rcupdate::action(int cmd, void *&, char const *&, int &)
       print_batch(Rcu::_rcu._completed); puts("");
       printf("  next_pending=%s\n"
              "  cpus=", Rcu::_rcu._next_pending?"yes":"no");
-      for (unsigned i = 0; i < Config::Max_num_cpus; ++i)
-       printf("%s%s", Rcu::_rcu._cpus.get(i)?"1":"0", i%4 == 3?" ":"");
+      for (Cpu_number i = Cpu_number::first(); i < Config::max_num_cpus(); ++i)
+       printf("%s%s", Rcu::_rcu._cpus.get(i)?"1":"0", cxx::int_value<Cpu_number>(i) % 4 == 3?" ":"");
 
       puts("");
 
-      for (unsigned i = 0; i < Config::Max_num_cpus; ++i)
+      for (Cpu_number i = Cpu_number::first(); i < Config::max_num_cpus(); ++i)
        {
          if (!Cpu::online(i))
            continue;
 
-         printf("  CPU[%2u]:", i);
+         printf("  CPU[%2u]:", cxx::int_value<Cpu_number>(i));
          Rcu_data const *d = &Rcu::_rcu_data.cpu(i);
          printf("    quiescent batch=");
          print_batch(d->_q_batch); puts("");
index cf830b53c17427ee8074cc0ab61e89d76bf3f58c..4f1f1bc6ec2777a7aad35a60a6112ba717df6419 100644 (file)
@@ -342,7 +342,7 @@ screen:
 
 PUBLIC
 void
-Jdb_table::draw_table(unsigned long row, unsigned long col, 
+Jdb_table::draw_table(unsigned long row, unsigned long col,
                       unsigned lines, unsigned columns)
 {
   for (unsigned long y = 0; y < lines; ++y)
index dc8ecd65ca7c2ab16488044051b46dd0f1fd4c2d..dc7ccee006932dd87bdac801d6e756da9f608897 100644 (file)
@@ -138,7 +138,7 @@ protected:
 
 #else // ! CONFIG_JDB_LOGGING
 
-#define BEGIN_LOG_EVENT(name, sc, fmt)                                 \
+#define BEGIN_LOG_EVENT(name, sc, fmt)                         \
   if (0)                                                       \
     { char __do_log__ = 0; (void)__do_log__;
 
@@ -177,14 +177,14 @@ PUBLIC static inline NEEDS["mem_layout.h"]
 Tracebuffer_status *
 Jdb_tbuf::status()
 {
-  return (Tracebuffer_status*) Mem_layout::Tbuf_status_page;
+  return (Tracebuffer_status *)Mem_layout::Tbuf_status_page;
 }
 
 PROTECTED static inline NEEDS["mem_layout.h"]
 Tb_entry_union *
 Jdb_tbuf::buffer()
 {
-  return (Tb_entry_union*)Mem_layout::Tbuf_buffer_area;
+  return (Tb_entry_union *)Mem_layout::Tbuf_buffer_area;
 }
 
 PUBLIC static inline
@@ -201,7 +201,7 @@ Jdb_tbuf::clear_tbuf()
 {
   Mword i;
 
-  for (i=0; i<_max_entries; i++)
+  for (i = 0; i < _max_entries; i++)
     buffer()[i].clear();
 
   _tbuf_act = buffer();
@@ -286,7 +286,7 @@ Jdb_tbuf::entries()
 
   Mword cnt = 0;
 
-  for (Mword idx=0; idx<unfiltered_entries(); idx++)
+  for (Mword idx = 0; idx<unfiltered_entries(); idx++)
     if (!buffer()[idx].hidden())
       cnt++;
 
@@ -317,14 +317,14 @@ PUBLIC static inline
 int
 Jdb_tbuf::event_valid(Mword idx)
 {
-  return (idx < _entries);
+  return idx < _entries;
 }
 
 /** Return pointer to tracebuffer event.
- * @param  position of event in tracebuffer: 
+ * @param  position of event in tracebuffer:
  *         0 is last event, 1 the event before and so on
  * @return pointer to tracebuffer event
- * 
+ *
  * event with idx == 0 is the last event queued in
  * event with idx == 1 is the event before */
 PUBLIC static
@@ -344,10 +344,10 @@ Jdb_tbuf::unfiltered_lookup(Mword idx)
 
 /** Return pointer to tracebuffer event.
  * Don't count hidden events.
- * @param  position of event in tracebuffer: 
+ * @param  position of event in tracebuffer:
  *         0 is last event, 1 the event before and so on
  * @return pointer to tracebuffer event
- * 
+ *
  * event with idx == 0 is the last event queued in
  * event with idx == 1 is the event before */
 PUBLIC static
@@ -357,7 +357,7 @@ Jdb_tbuf::lookup(Mword look_idx)
   if (!_filter_enabled)
     return unfiltered_lookup(look_idx);
 
-  for (Mword idx=0;; idx++)
+  for (Mword idx = 0;; idx++)
     {
       Tb_entry *e = unfiltered_lookup(idx);
 
@@ -392,7 +392,7 @@ Jdb_tbuf::idx(Tb_entry const *e)
     return unfiltered_idx(e);
 
   Tb_entry_union const *ef = static_cast<Tb_entry_union const*>(e);
-  Mword idx = (Mword)-1;
+  Mword idx = (Mword) - 1;
 
   for (;;)
     {
@@ -431,8 +431,8 @@ PUBLIC static
 Mword
 Jdb_tbuf::search_to_idx(Mword nr)
 {
-  if (nr == (Mword)-1)
-    return (Mword)-1;
+  if (nr == (Mword) - 1)
+    return (Mword) - 1;
 
   Tb_entry *e;
 
@@ -440,14 +440,14 @@ Jdb_tbuf::search_to_idx(Mword nr)
     {
       e = search(nr);
       if (!e)
-       return (Mword)-1;
+       return (Mword) - 1;
       return unfiltered_idx(e);
     }
 
-  for (Mword idx_u=0, idx_f=0; (e = unfiltered_lookup(idx_u)); idx_u++)
+  for (Mword idx_u = 0, idx_f = 0; (e = unfiltered_lookup(idx_u)); idx_u++)
     {
       if (e->number() == nr)
-       return e->hidden() ? (Mword)-2 : idx_f;
+       return e->hidden() ? (Mword) - 2 : idx_f;
 
       if (!e->hidden())
        idx_f++;
@@ -487,14 +487,14 @@ Jdb_tbuf::event(Mword idx, Mword *number, Unsigned32 *kclock,
 /** Get difference CPU cycles between event idx and event idx+1.
  * @param idx position of first event in tracebuffer
  * @retval difference in CPU cycles
- * @return 0 if something wrong, 1 if everything ok */ 
+ * @return 0 if something wrong, 1 if everything ok */
 PUBLIC static
 int
 Jdb_tbuf::diff_tsc(Mword idx, Signed64 *delta)
 {
   Tb_entry *e      = lookup(idx);
-  Tb_entry *e_prev = lookup(idx+1);
-  
+  Tb_entry *e_prev = lookup(idx + 1);
+
   if (!e || !e_prev)
     return false;
 
@@ -506,14 +506,14 @@ Jdb_tbuf::diff_tsc(Mword idx, Signed64 *delta)
  * @param idx position of first event in tracebuffer
  * @param nr  number of perfcounter (0=first, 1=second)
  * @retval difference in perfcnt cycles
- * @return 0 if something wrong, 1 if everything ok */ 
+ * @return 0 if something wrong, 1 if everything ok */
 PUBLIC static
 int
 Jdb_tbuf::diff_pmc(Mword idx, Mword nr, Signed32 *delta)
 {
   Tb_entry *e      = lookup(idx);
-  Tb_entry *e_prev = lookup(idx+1);
-  
+  Tb_entry *e_prev = lookup(idx + 1);
+
   if (!e || !e_prev)
     return false;
 
index d91c4a952b34aea1928e7acb239c7573724247e4..52c6e2e323173e0d1c10c31f7370bff5370d754e 100644 (file)
@@ -755,7 +755,7 @@ restart:
       if (lines == 1)
        puts("\033[K");
 
-      for (Mword i=Tbuf_start_line+lines; i<Jdb_screen::height(); i++)
+      for (Mword i=Tbuf_start_line + lines; i<Jdb_screen::height(); i++)
        puts("\033[K");
 
       _status_type = Status_redraw;
@@ -763,7 +763,6 @@ restart:
  status_line:
       for (bool redraw=false; !redraw;)
         {
-
          Smword c;
          Unsigned8 d = 0; // default search direction is forward
 
@@ -816,16 +815,16 @@ restart:
                 }
             }
 
-         Jdb::cursor(addy+Tbuf_start_line, 1);
+         Jdb::cursor(addy + Tbuf_start_line, 1);
          putstr(Jdb::esc_emph);
-         show_events(_absy+addy, refy, 1, mode, time_mode, 0);
+         show_events(_absy + addy, refy, 1, mode, time_mode, 0);
          putstr("\033[m");
-         Jdb::cursor(addy+Tbuf_start_line, 1);
+         Jdb::cursor(addy + Tbuf_start_line, 1);
 
           // WAIT for key.....
          c=Jdb_core::getchar();
 
-         show_events(_absy+addy, refy, 1, mode, time_mode, 0);
+         show_events(_absy + addy, refy, 1, mode, time_mode, 0);
           for (unsigned i = 0; i < group.size(); ++i)
             {
               Entry_group::Item const &item = group[i];
@@ -833,7 +832,7 @@ restart:
              show_events(item.y, refy, 1, mode, time_mode, 0);
             }
 
-         if (Jdb::std_cursor_key(c, cols, lines, max_absy, 
+         if (Jdb::std_cursor_key(c, cols, lines, max_absy,
                                  &_absy, &addy, 0, &redraw))
            continue;
 
@@ -858,13 +857,13 @@ restart:
            case 'F': // filter view by regex
              Jdb::printf_statline("tbuf", 0, "Filter(%s)=%s",
                                   Jdb_regex::avail() ? "regex" : "instr",
-                                  _filter_str);
+                                  _filter_str);
              _status_type = Status_redraw;
              Jdb::cursor(Jdb_screen::height(), 21+strlen(_filter_str));
              if (!get_string(_filter_str, sizeof(_filter_str)))
                goto status_line;
              if (!Jdb_tbuf_output::set_filter(_filter_str, &entries))
-               {
+               {
                  error("Error in regular expression");
                  goto status_line;
                }
@@ -874,7 +873,7 @@ restart:
            case 'D': // dump to console
              if (!Kconsole::console()->find_console(Console::GZIP))
                break;
-             Jdb::cursor(Jdb_screen::height(), 10);
+             Jdb::cursor(Jdb_screen::height(), 10);
              Jdb::clear_to_eol();
              printf("Count=");
              if (Jdb_input::get_mword(&count, 7, 10))
index eb7b29484b73b4b218e1bd49d002cec4c7d79f78..fd476f4f91750e20acc8f38bf3a54e5abcde24ce 100644 (file)
@@ -510,7 +510,7 @@ whole_screen:
   putstr("thread  : ");
   Jdb_kobject::print_uid(t, 3);
   print_thread_uid_raw(t);
-  printf("\tCPU: %u ", t->cpu());
+  printf("\tCPU: %u ", cxx::int_value<Cpu_number>(t->cpu()));
 
   printf("\tprio: %02x  mode: %s\n",
          t->sched()->prio(),
@@ -559,7 +559,7 @@ whole_screen:
                    11 < sizeof(time_str) ? 11 : sizeof(time_str), false);
   printf("%-13s", time_str);
 
-  printf("\t\ttimeslice: %llu/%llu %cs\n"
+  printf("\t\ttimeslice: %llu/%lld %cs\n"
          "pager\t: ",
          t->sched()->left(), ~0ULL/*t->sched()->quantum()*/, Config::char_micro);
   print_kobject(t, t->_pager.raw());
@@ -869,7 +869,8 @@ Jdb_tcb::show_kobject_short(char *buf, int max, Kobject_common *o)
   int cnt = 0;
   if (t == Context::kernel_context(t->cpu()))
     {
-      cnt = snprintf(buf, max, " {KERNEL} C=%u", t->cpu());
+      cnt = snprintf(buf, max, " {KERNEL} C=%u",
+                     cxx::int_value<Cpu_number>(t->cpu()));
       max -= cnt;
       buf += cnt;
     }
@@ -877,7 +878,8 @@ Jdb_tcb::show_kobject_short(char *buf, int max, Kobject_common *o)
     return cnt + snprintf(buf, max, " R=%ld%s", t->ref_cnt(),
                           is_current ? " " JDB_ANSI_COLOR(green) "current" JDB_ANSI_END : "");
 
-  return cnt + snprintf(buf, max, " C=%u S=D:%lx R=%ld %s", t->cpu(),
+  return cnt + snprintf(buf, max, " C=%u S=D:%lx R=%ld %s",
+                        cxx::int_value<Cpu_number>(t->cpu()),
                         Kobject_dbg::pointer_to_id(t->space()),
                         t->ref_cnt(),
                         is_current ? " " JDB_ANSI_COLOR(green) "current" JDB_ANSI_END : "");
@@ -924,9 +926,9 @@ Jdb_tcb::print_thread_uid_raw(Thread *t)
 
 PRIVATE static
 void
-Jdb_tcb::print_kobject(Mword n)
+Jdb_tcb::print_kobject(Cap_index n)
 {
-  printf("[C:%4lx]       ", n);
+  printf("[C:%4lx]       ", cxx::int_value<Cap_index>(n));
 }
 
 PRIVATE static
@@ -938,7 +940,7 @@ Jdb_tcb::print_kobject(Kobject *o)
 
 PRIVATE static
 void
-Jdb_tcb::print_kobject(Thread *t, Mword capidx)
+Jdb_tcb::print_kobject(Thread *t, Cap_index capidx)
 {
   Space *space = t->space();
   if (!space)
@@ -947,14 +949,15 @@ Jdb_tcb::print_kobject(Thread *t, Mword capidx)
       return;
     }
 
-  Obj_space::Capability *c = space->get_cap(capidx);
+  Obj_space::Capability *c = space->jdb_lookup_cap(capidx);
   if (!c || !c->valid())
     {
       print_kobject(capidx);
       return;
     }
 
-  printf("[C:%4lx] D:%4lx", capidx, c->obj()->dbg_info()->dbg_id());
+  printf("[C:%4lx] D:%4lx", cxx::int_value<Cap_index>(capidx),
+         c->obj()->dbg_info()->dbg_id());
 }
 
 //
index c23009bc4da55cc30c2c6f978b4cf1e83247d6e8..afdfb8ce3acd4aa08ee707f69415741f9b12fc99 100644 (file)
@@ -131,7 +131,7 @@ static int getchar_timeout()
       if (Config::getchar_does_hlt_works_ok)
        Proc::halt();
       else
-       Cpu::cpus.cpu(0).busy_wait_ns(1000000ULL);
+       Cpu::cpus.cpu(Cpu_number::boot_cpu()).busy_wait_ns(1000000ULL);
     }
 
   to = slice;
index e0da7eada803b0c0d72c487668cc94e4b2cb298a..88e07f1aba54779bb31506a394028c1c51de5dcb 100644 (file)
@@ -26,7 +26,7 @@ public:
 private:
   static char subcmd;
   static char long_output;
-  static unsigned cpu;
+  static Cpu_number cpu;
 
 private:
   static int _mode;
@@ -43,7 +43,7 @@ private:
 
 char Jdb_thread_list::subcmd;
 char Jdb_thread_list::long_output;
-unsigned Jdb_thread_list::cpu;
+Cpu_number Jdb_thread_list::cpu;
 
 
 // available from the jdb_tcb module
@@ -577,14 +577,14 @@ Jdb_thread_list::action(int cmd, void *&argbuf, char const *&fmt, int &)
       Thread *t = Jdb::get_current_active();
       switch (subcmd)
        {
-       case 'r': cpu = 0; list_threads(t, 'r'); break;
+        case 'r': cpu = Cpu_number::first(); list_threads(t, 'r'); break;
        case 'p': list_threads(t, 'p'); break;
        case 'c':
                  if (Cpu::online(cpu))
                    list_threads(Jdb::get_thread(cpu), 'r');
                  else
-                   printf("\nCPU %u is not online!\n", cpu);
-                 cpu = 0;
+                   printf("\nCPU %u is not online!\n", Cpu_number::val(cpu));
+                 cpu = Cpu_number::first();
                  break;
        case 't': Jdb::execute_command("lt"); break; // other module
        case 's': Jdb::execute_command("ls"); break; // other module
@@ -640,7 +640,7 @@ Jdb_thread_list::list_threads_show_thread(Thread *t)
 
   Jdb_kobject::print_uid(t, 5);
 
-  printf(" %-3u ", t->cpu());
+  printf(" %-3u ", cxx::int_value<Cpu_number>(t->cpu()));
 
   print_thread_name(t);
 
index aa9b3d501c1bccd41dba89ece03b8ba124ea4d4b..5733944e02c281e127ce1c1b523312fdbbd8d7fd 100644 (file)
@@ -193,7 +193,7 @@ Jdb_list_timeouts::get_type(Timeout *t)
 {
   Address addr = (Address)t;
 
-  if (t == timeslice_timeout.cpu(0))
+  if (t == timeslice_timeout.cpu(Cpu_number::first()))
     // there is only one global timeslice timeout
     return Timeout_timeslice;
 
@@ -216,7 +216,7 @@ Jdb_list_timeouts::get_owner(Timeout *t)
       case Timeout_deadline:
         return static_cast<Thread*>(context_of(t));
       case Timeout_timeslice:
-        return static_cast<Thread*>(Context::kernel_context(0));
+        return static_cast<Thread*>(Context::kernel_context(Cpu_number::first()));
 #if 0
         // XXX: current_sched does not work from the debugger
         if (Context::current_sched())
@@ -308,7 +308,8 @@ Jdb_list_timeouts::list()
   typedef Rnd_container<Timeout_iter> Cont;
   typedef Cont::Iterator Iter;
 
-  Cont to_cont(Timeout_iter(&Timeout_q::timeout_queue.cpu(0)), Timeout_iter(&Timeout_q::timeout_queue.cpu(0), true));
+  Cont to_cont(Timeout_iter(&Timeout_q::timeout_queue.cpu(Cpu_number::first())),
+               Timeout_iter(&Timeout_q::timeout_queue.cpu(Cpu_number::first()), true));
   Iter first = to_cont.begin();
   Iter current = first;
   Iter end = to_cont.end();
index 4ada7aab1227cff3cc335520c6fa07174611dcc2..4a197d6633ccbe1831a38fbd0bddf0dd1149613d 100644 (file)
@@ -26,14 +26,15 @@ static Jdb_trap_state_module jdb_trap_state_module INIT_PRIORITY(JDB_MODULE_INIT
 
 PRIVATE static
 void
-Jdb_trap_state_module::print_trap_state(unsigned cpu)
+Jdb_trap_state_module::print_trap_state(Cpu_number cpu)
 {
   Jdb_entry_frame *ef = Jdb::entry_frame.cpu(cpu);
   if (!Jdb::cpu_in_jdb(cpu) || !ef)
-    printf("CPU %u has not entered JDB\n", cpu);
+    printf("CPU %u has not entered JDB\n", cxx::int_value<Cpu_number>(cpu));
   else
     {
-      printf("Registers of CPU %u (before entering JDB)\n", cpu);
+      printf("Registers of CPU %u (before entering JDB)\n",
+             cxx::int_value<Cpu_number>(cpu));
       ef->dump();
     }
 }
@@ -43,7 +44,7 @@ Jdb_module::Action_code
 Jdb_trap_state_module::action (int cmd, void *&argbuf, char const *&fmt, int &next)
 {
   char const *c = (char const *)argbuf;
-  static unsigned cpu;
+  static Cpu_number cpu;
 
   if (cmd != 0)
     return NOTHING;
index 3c801e12f1985c3879ae9f1dea6e704a9c35d0c4..9744b10445134abf43c72b7bb22d882a39df0cf1 100644 (file)
@@ -19,14 +19,13 @@ Jdb_util::is_mapped(void const *x)
 
 IMPLEMENTATION[arm]:
 
-#include "pagetable.h"
 #include "kmem_space.h"
 
-IMPLEMENT inline NEEDS["kmem_space.h", "pagetable.h"]
+IMPLEMENT inline NEEDS["kmem_space.h"]
 bool
 Jdb_util::is_mapped(void const* addr)
 {
-  return Kmem_space::kdir()->walk(const_cast<void*>(addr), 0, false, Ptab::Null_alloc(), 0).valid();
+  return Kmem_space::kdir()->virt_to_phys((Address)addr) != Address(~0UL);
 }
 
 IMPLEMENTATION[ppc32]:
index 1f02f5d71d495a300cb2b502de29bf8cd5e3f753..cdc9d7b288317e98998c00853903ce67d0600954 100644 (file)
@@ -15,7 +15,7 @@ DEFINE_PER_CPU static Per_cpu<Proc::Status> jdb_irq_state;
 // disable interrupts before entering the kernel debugger
 IMPLEMENT
 void
-Jdb::save_disable_irqs(unsigned cpu)
+Jdb::save_disable_irqs(Cpu_number cpu)
 {
   jdb_irq_state.cpu(cpu) = Proc::cli_save();
 }
@@ -23,24 +23,24 @@ Jdb::save_disable_irqs(unsigned cpu)
 // restore interrupts after leaving the kernel debugger
 IMPLEMENT
 void
-Jdb::restore_irqs(unsigned cpu)
+Jdb::restore_irqs(Cpu_number cpu)
 {
   Proc::sti_restore(jdb_irq_state.cpu(cpu));
 }
 
 IMPLEMENT inline
 void
-Jdb::enter_trap_handler(unsigned /*cpu*/)
+Jdb::enter_trap_handler(Cpu_number)
 {}
 
 IMPLEMENT inline
 void
-Jdb::leave_trap_handler(unsigned /*cpu*/)
+Jdb::leave_trap_handler(Cpu_number)
 {}
 
 IMPLEMENT inline
 bool
-Jdb::handle_conditional_breakpoint(unsigned /*cpu*/)
+Jdb::handle_conditional_breakpoint(Cpu_number)
 { return false; }
 
 IMPLEMENT
@@ -53,10 +53,10 @@ Jdb::handle_nested_trap(Jdb_entry_frame *e)
 
 IMPLEMENT
 bool
-Jdb::handle_debug_traps(unsigned cpu)
+Jdb::handle_debug_traps(Cpu_number cpu)
 {
   Jdb_entry_frame *ef = entry_frame.cpu(cpu);
-  snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)), "%s",
+  snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(Cpu_number::boot_cpu())), "%s",
            (char const *)ef->r[2]);
 
   return true;
@@ -64,7 +64,7 @@ Jdb::handle_debug_traps(unsigned cpu)
 
 IMPLEMENT inline
 bool
-Jdb::handle_user_request(unsigned cpu)
+Jdb::handle_user_request(Cpu_number cpu)
 {
   Jdb_entry_frame *ef = Jdb::entry_frame.cpu(cpu);
   const char *str = (char const *)ef->r[2];
index a036666e69fe3e125c493639c423499bd64b92fa..962cf2c75c377fd59387206ea4f6023b6a1118dd 100644 (file)
@@ -15,7 +15,7 @@ DEFINE_PER_CPU static Per_cpu<Proc::Status> jdb_irq_state;
 // disable interrupts before entering the kernel debugger
 IMPLEMENT
 void
-Jdb::save_disable_irqs(unsigned cpu)
+Jdb::save_disable_irqs(Cpu_number cpu)
 {
   jdb_irq_state.cpu(cpu) = Proc::cli_save();
 }
@@ -23,24 +23,24 @@ Jdb::save_disable_irqs(unsigned cpu)
 // restore interrupts after leaving the kernel debugger
 IMPLEMENT
 void
-Jdb::restore_irqs(unsigned cpu)
+Jdb::restore_irqs(Cpu_number cpu)
 {
   Proc::sti_restore(jdb_irq_state.cpu(cpu));
 }
 
 IMPLEMENT inline
 void
-Jdb::enter_trap_handler(unsigned /*cpu*/)
+Jdb::enter_trap_handler(Cpu_number)
 {}
 
 IMPLEMENT inline
 void
-Jdb::leave_trap_handler(unsigned /*cpu*/)
+Jdb::leave_trap_handler(Cpu_number)
 {}
 
 IMPLEMENT inline
 bool
-Jdb::handle_conditional_breakpoint(unsigned /*cpu*/)
+Jdb::handle_conditional_breakpoint(Cpu_number)
 { return false; }
 
 IMPLEMENT
@@ -53,10 +53,10 @@ Jdb::handle_nested_trap(Jdb_entry_frame *e)
 
 IMPLEMENT
 bool
-Jdb::handle_debug_traps(unsigned cpu)
+Jdb::handle_debug_traps(Cpu_number cpu)
 {
   Jdb_entry_frame *ef = entry_frame.cpu(cpu);
-  snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(0)), "%s",
+  snprintf(error_buffer.cpu(cpu), sizeof(error_buffer.cpu(Cpu_number::first())), "%s",
            (char const *)ef->r[2]);
 
   return true;
@@ -64,7 +64,7 @@ Jdb::handle_debug_traps(unsigned cpu)
 
 IMPLEMENT inline
 bool
-Jdb::handle_user_request(unsigned cpu)
+Jdb::handle_user_request(Cpu_number cpu)
 {
   Jdb_entry_frame *ef = Jdb::entry_frame.cpu(cpu);
   const char *str = (char const *)ef->r[2];
@@ -144,6 +144,7 @@ PUBLIC static
 Space *
 Jdb::translate_task(Address addr, Space * task)
 {
+  (void)addr;
 //  return (Kmem::is_kmem_page_fault(addr, 0)) ? 0 : task;
 
   return task;
@@ -190,6 +191,7 @@ PUBLIC static
 int
 Jdb::poke_task(Address virt, Space * task, void const *val, int width)
 {
+  (void)virt; (void)task; (void)val; (void)width;
   /*
   void *mem = access_mem_task(virt, task);
   if (!mem)
index daf86de1bc6a3e4f7731d588b4e53573fb35e787..13437105e7ad4d9a30b0f13a8faef804615434a7 100644 (file)
@@ -70,7 +70,7 @@ static Proc::Status jdb_irq_state;
 
 IMPLEMENT inline
 void
-Jdb::enter_trap_handler(unsigned /*cpu*/)
+Jdb::enter_trap_handler(Cpu_number)
 {
   conf_screen();
 
@@ -83,7 +83,7 @@ Jdb::enter_trap_handler(unsigned /*cpu*/)
 
 IMPLEMENT inline
 void
-Jdb::leave_trap_handler(unsigned)
+Jdb::leave_trap_handler(Cpu_number)
 {
   // Restore terminal mode
   leave_getchar();
@@ -95,12 +95,12 @@ Jdb::leave_trap_handler(unsigned)
 
 PROTECTED static inline
 void
-Jdb::monitor_address(unsigned, void *)
+Jdb::monitor_address(Cpu_number, void *)
 {}
 
 IMPLEMENT inline
 bool
-Jdb::handle_user_request(unsigned /*cpu*/)
+Jdb::handle_user_request(Cpu_number)
 { return false; }
 
 IMPLEMENT inline
@@ -112,18 +112,18 @@ Jdb::test_checksums()
 // disable interrupts before entering the kernel debugger
 IMPLEMENT
 void
-Jdb::save_disable_irqs(unsigned cpu)
+Jdb::save_disable_irqs(Cpu_number cpu)
 {
-  assert(cpu == 0);
+  assert(cpu == Cpu_number::boot_cpu());
   jdb_irq_state = Proc::cli_save();
 }
 
 // restore interrupts after leaving the kernel debugger
 IMPLEMENT
 void
-Jdb::restore_irqs(unsigned cpu)
+Jdb::restore_irqs(Cpu_number cpu)
 {
-  assert(cpu == 0);
+  assert(cpu == Cpu_number::boot_cpu());
   Proc::sti_restore(jdb_irq_state);
 }
 
@@ -167,7 +167,7 @@ PUBLIC static inline NOEXPORT
 int
 Jdb::int3_extension()
 {
-  Jdb_entry_frame *entry_frame = Jdb::entry_frame.cpu(0);
+  Jdb_entry_frame *entry_frame = Jdb::entry_frame.cpu(Cpu_number::boot_cpu());
   Address      addr = entry_frame->ip();
   Address_type user = (entry_frame->cs() & 3) ? ADDR_USER : ADDR_KERNEL;
   Unsigned8    todo = peek ((Unsigned8 *) addr, user);
@@ -183,7 +183,7 @@ Jdb::int3_extension()
     }
   else if (todo != 0xeb)
     {
-      snprintf (error_buffer.cpu(0), sizeof (error_buffer.cpu(0)), "INT 3");
+      snprintf (error_buffer.cpu(Cpu_number::boot_cpu()), sizeof (error_buffer.cpu(Cpu_number::boot_cpu())), "INT 3");
       return 0;
     }
 
@@ -203,10 +203,10 @@ Jdb::int3_extension()
        return 1; // => leave Jdb
     }
 
-  len = len < sizeof(error_buffer.cpu(0))-1 ? len : sizeof(error_buffer.cpu(0))-1;
+  len = len < sizeof(error_buffer.cpu(Cpu_number::boot_cpu()))-1 ? len : sizeof(error_buffer.cpu(Cpu_number::boot_cpu()))-1;
   for (i = 0; i < len; i++)
-    error_buffer.cpu(0)[i] = peek ((Unsigned8 *) ++addr, user);
-  error_buffer.cpu(0)[i] = 0;
+    error_buffer.cpu(Cpu_number::boot_cpu())[i] = peek ((Unsigned8 *) ++addr, user);
+  error_buffer.cpu(Cpu_number::boot_cpu())[i] = 0;
   return 0;
 }
 
@@ -217,7 +217,7 @@ Jdb::handle_special_cmds(int)
 
 IMPLEMENT
 bool
-Jdb::handle_debug_traps(unsigned cpu)
+Jdb::handle_debug_traps(Cpu_number cpu)
 {
   switch (entry_frame.cpu(cpu)->_trapno)
     {
@@ -251,7 +251,7 @@ Jdb::handle_nested_trap(Jdb_entry_frame *e)
 
 IMPLEMENT inline
 bool
-Jdb::handle_conditional_breakpoint(unsigned /*cpu*/)
+Jdb::handle_conditional_breakpoint(Cpu_number)
 { return false; }
 
 
@@ -269,7 +269,7 @@ static Address
 Jdb::virt_to_kvirt(Address virt, Mem_space* space)
 {
   Mem_space::Phys_addr phys;
-  Mem_space::Size size;
+  Mem_space::Page_order size;
 
   if (!space)
     {
@@ -291,8 +291,9 @@ Jdb::virt_to_kvirt(Address virt, Mem_space* space)
       // We can't directly access it because it's in a different host process
       // but if the task's pagetable has a mapping for it, we can translate
       // task-virtual -> physical -> kernel-virtual address and then access.
-      return (space->v_lookup(Mem_space::Addr::create(virt), &phys, &size, 0))
-       ? (Address) Kmem::phys_to_virt(phys.value() + (virt & (size.value()-1)))
+      Virt_addr va(virt);
+      return (space->v_lookup(va, &phys, &size, 0))
+       ? (Address) Kmem::phys_to_virt(Mem_space::Phys_addr::val(phys) + Virt_size::val(cxx::get_lsb(va, size)))
        : (Address) -1;
     }
 }
@@ -303,7 +304,7 @@ T
 Jdb::peek (T const *addr, Address_type user)
 {
   // FIXME: assume UP here (current_meme_space(0))
-  return Mem_space::current_mem_space(0)->peek(addr, user);
+  return Mem_space::current_mem_space(Cpu_number::boot_cpu())->peek(addr, user);
 }
 
 PUBLIC static
@@ -441,7 +442,7 @@ Jdb::set_monitored_address(T *dest, T val)
 
 PROTECTED static inline
 template< typename T >
-T Jdb::monitor_address(unsigned, T volatile *addr)
+T Jdb::monitor_address(Cpu_number, T volatile *addr)
 {
   return *addr;
 }
@@ -451,6 +452,6 @@ IMPLEMENTATION [ux && mp]:
 
 static
 void
-Jdb::send_nmi(unsigned /*cpu*/)
+Jdb::send_nmi(Cpu_number)
 {
 }
index 893c232b6fe40b9bbd995d6b5517d53fefbf061d..7a80f8ec9aff906d3281c7d9fc7ad80539a24cb0 100644 (file)
@@ -144,7 +144,7 @@ IMPLEMENT
 int
 Jdb_bp::test_log_only()
 {
-  Space *t = Jdb::get_thread(0)->space();
+  Space *t = Jdb::get_thread(Cpu_number::boot_cpu())->space();
   Mword dr6  = read_debug_register(6, t);
 
   if (dr6 & 0x0000000f)
@@ -164,7 +164,7 @@ IMPLEMENT
 int
 Jdb_bp::test_break(char *errbuf, size_t bufsize)
 {
-  Space *t = Jdb::get_thread(0)->space();
+  Space *t = Jdb::get_thread(Cpu_number::boot_cpu())->space();
   Mword dr6  = read_debug_register(6, t);
 
   if (!(dr6 & 0x000000f))
index 384d1a595aed3867454d821038e9a022d7c565e5..4ad65e1cfa8b398a7fd7ceae879e1765a9df718f 100644 (file)
@@ -30,7 +30,7 @@ IMPLEMENTATION [mp]:
 
 PUBLIC static
 Kernel_thread *
-App_cpu_thread::may_be_create(unsigned cpu, bool cpu_never_seen_before)
+App_cpu_thread::may_be_create(Cpu_number cpu, bool cpu_never_seen_before)
 {
   if (!cpu_never_seen_before)
     return static_cast<Kernel_thread *>(kernel_context(cpu));
@@ -81,7 +81,7 @@ App_cpu_thread::bootstrap()
 
   cpu_lock.clear();
 
-  printf("CPU[%u]: goes to idle loop\n", cpu(true));
+  printf("CPU[%u]: goes to idle loop\n", cxx::int_value<Cpu_number>(cpu(true)));
 
   for (;;)
     idle_op();
index 25f847f9b7cd9e8ff355f3adf9dc6f4193ff0a4b..1d88bc6ce423eab510ded4d8b79c393424e52b17 100644 (file)
@@ -6,7 +6,14 @@ tramp-mp.o: $(TCBOFFSET)
 # Add future prerequisites somewhere among the list of libraries.
 # You really should not have to add anything in the $(LD) line.
 
-$(KERNEL).image: kernel.arm.lds $(CRT0) $(OBJ_KERNEL) $(JDB) $(LIBK) $(KERNEL_EXTRA_LIBS) $(LIBDISASM) $(ABI) libdrivers.a $(LIBUART) $(CXXLIB) $(MINILIBC) $(LIBGCC) $(MINILIBC) libgluedriverslibc.a
+OBJ_KERNEL_noboot = $(filter-out bootstrap%,$(OBJ_KERNEL))
+OBJ_BOOTSTRAP = $(filter  bootstrap%,$(OBJ_KERNEL))
+
+bootstrap.$(KERNEL).o: $(OBJ_BOOTSTRAP) $(LIBGCC)
+       $(LINK_MESSAGE)
+       $(VERBOSE)$(LD) $(LDFLAGS) -r $(OBJ_BOOTSTRAP) $(LIBGCC) -o $@
+
+$(KERNEL).image: kernel.arm.lds $(CRT0) bootstrap.$(KERNEL).o $(OBJ_KERNEL_noboot) $(JDB) $(LIBK) $(KERNEL_EXTRA_LIBS) $(LIBDISASM) $(ABI) libdrivers.a $(LIBUART) $(CXXLIB) $(MINILIBC) $(LIBGCC) $(MINILIBC) libgluedriverslibc.a
        $(LINK_MESSAGE)
        $(VERBOSE)$(LD) $(LDFLAGS) -N -defsym kernel_load_addr=$(CONFIG_KERNEL_LOAD_ADDR) \
           -T $< -o $@ $(filter-out $<,$+)
@@ -25,3 +32,6 @@ Symbols: $(KERNEL).image
 
 
 clean-KERNEL:
+
+kernel.arm.lds: globalconfig.h
+
diff --git a/kernel/fiasco/src/kern/arm/asm_entry.h b/kernel/fiasco/src/kern/arm/asm_entry.h
new file mode 100644 (file)
index 0000000..34a989d
--- /dev/null
@@ -0,0 +1,215 @@
+#pragma once
+
+#include "globalconfig.h"
+#include "config_tcbsize.h"
+#include "tcboffset.h"
+
+/****************************
+ * some handy definitions
+ */
+#define RF_SIZE      20
+#define RF_PSR       16
+#define RF_PC        12
+#define RF_SVC_LR     8
+#define RF_USR_LR     4
+#define RF_USR_SP     0
+#define RF(reg, offs) (RF_##reg + (offs))
+
+
+/**********************************************************************
+ * calculate the TCB address from a stack pointer
+ */
+.macro CONTEXT_OF reg, ptr
+       bic     \reg, \ptr, #((THREAD_BLOCK_SIZE-1) & 0xff)
+       bic     \reg, \reg, #((THREAD_BLOCK_SIZE-1) & 0xff00)
+.endm
+
+/**********************************************************************
+ * Reset the thread cancel flag. 
+ * Register r0 is scratched and contains the thread state afterwards
+ */
+.macro RESET_THREAD_CANCEL_AT tcb
+       ldr     r0, [\tcb, #(OFS__THREAD__STATE)]
+       bic     r0, r0, #0x100
+       str     r0, [\tcb, #(OFS__THREAD__STATE)]
+.endm
+
+
+/*****************************************************************************/
+/* The syscall table stuff                                                   */
+/*****************************************************************************/
+.macro GEN_SYSCALL_TABLE
+.align 4
+.global sys_call_table
+sys_call_table:
+       .word sys_kdb_ke
+       .word sys_kdb_ke
+       .word sys_ipc_wrapper
+       .word sys_arm_mem_op
+       .word sys_invoke_debug_wrapper
+       .word sys_kdb_ke
+       .word sys_kdb_ke
+       .word sys_kdb_ke
+       .word sys_kdb_ke
+       .word sys_kdb_ke
+       .word sys_kdb_ke
+.endm
+
+.macro GEN_VCPU_UPCALL THREAD_VCPU, LOAD_USR_SP, LOAD_USR_VCPU
+.align 4
+.global leave_by_vcpu_upcall;
+
+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 */
+       CONTEXT_OF r1, sp
+       ldr     r2, [r1, #(\THREAD_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)]
+
+       ldr     r0, [r1, #(OFS__THREAD__EXCEPTION_PSR)]
+       str     r0, [r2, #RF(PSR, 0)]
+       bic     r0, #0x20 // force ARM mode
+       str     r0, [sp, #RF(PSR, 3*4)]
+
+       mov     r0, #~0
+       str     r0, [r1, #(OFS__THREAD__EXCEPTION_IP)]
+
+       ldr     r0, [sp, #RF(USR_LR, 3*4)]
+       str     r0, [r2, #RF(USR_LR, 0)]
+
+       ldr     r0, [sp, #RF(USR_SP, 3*4)]
+       str     r0, [r2, #RF(USR_SP, 0)]
+
+       stmdb   r2!, {r3-r12}
+
+       /* Restore scratch registers saved previously */
+       ldr     r0, [sp, #8]
+       str     r0, [r2, #-4]
+
+       ldr     r0, [sp, #4]
+       str     r0, [r2, #-8]
+
+       ldr     r0, [sp]
+       str     r0, [r2, #-12]!
+        sub     r2, r2, #12     @ now r2 points to the VCPU STATE again
+
+       add     sp, sp, #(3*4)
+
+       /* r2 = &vcpu_state->ts.r[0] */
+       /* r2 - 12 ->  pfa, err & tpidruro -> &vcpu_state->ts */
+        \LOAD_USR_SP r2
+
+       ldr     r0, [r2, #(OFS__VCPU_STATE__ENTRY_IP)]
+
+       str     r0, [sp, #RF(PC, 0)]
+        \LOAD_USR_VCPU r0, r2, r1
+       b       __iret
+
+.endm
+
+/**********************************************************************
+       kdebug entry
+ **********************************************************************/
+
+.macro DEBUGGER_ENTRY type
+#ifdef CONFIG_JDB
+       str     sp, [sp, #(RF(USR_SP, -RF_SIZE))] @ save r[13]
+       sub     sp, sp, #(RF_SIZE)
+
+       str     lr, [sp, #RF(SVC_LR, 0)]
+       str     lr, [sp, #RF(PC, 0)]
+        mrs    lr, cpsr
+       str     lr, [sp, #RF(PSR, 0)]
+
+       stmdb   sp!, {r0 - r12}
+       sub sp, sp, #4
+       mov     r0, #-1                 @ pfa
+       mov     r1, #0x00e00000         @ err
+       orr     r1, #\type              @ + type
+       stmdb   sp!, {r0, r1}
+
+       mov     r0, sp
+       adr     lr, 1f
+       ldr     pc, 3f
+
+1:
+       add     sp, sp, #12             @ pfa, err and tpidruro
+       ldmia   sp!, {r0 - r12}
+       ldr     lr, [sp, #RF(PSR, 0)]
+       msr     cpsr, lr
+       ldr     lr, [sp, #RF(SVC_LR, 0)]
+
+       ldr     sp, [sp, #(RF(USR_SP, 0))]
+       mov     pc, lr
+
+
+3:     .word call_nested_trap_handler
+#else
+       mov     pc, lr
+#endif
+.endm
+
+
+.macro GEN_DEBUGGER_ENTRIES
+       .global kern_kdebug_entry
+       .align 4
+kern_kdebug_entry:
+       DEBUGGER_ENTRY 0
+
+       .global kern_kdebug_sequence_entry
+       .align 4
+kern_kdebug_sequence_entry:
+       DEBUGGER_ENTRY 1
+
+
+#ifdef CONFIG_MP
+       .section ".text"
+       .global kern_kdebug_ipi_entry
+       .align 4
+kern_kdebug_ipi_entry:
+       DEBUGGER_ENTRY 2
+       .previous
+#endif
+
+.endm
+
+.macro         enter_slowtrap_w_stack errorcode
+       mov     r1, #\errorcode
+       stmdb   sp!, {r0, r1}
+       mov     r0, sp
+       adr     lr, exception_return
+       ldr     pc, .LCslowtrap_entry
+.endm
+
+.macro GEN_LEAVE_BY_TRIGGER_EXCEPTION
+.align 4
+.global leave_by_trigger_exception
+
+leave_by_trigger_exception:
+       sub     sp, sp, #RF_SIZE   @ restore old return frame
+       stmdb   sp!, {r0 - r12}
+
+       sub sp, sp, #4
+
+       /* restore original IP */
+       CONTEXT_OF r1, sp
+       ldr     r0, [r1, #(OFS__THREAD__EXCEPTION_IP)]
+       str     r0, [sp, #RF(PC, 14*4)]
+
+       ldr     r0, [r1, #(OFS__THREAD__EXCEPTION_PSR)]
+       str     r0, [sp, #RF(PSR, 14*4)]
+
+       mov     r0, #~0
+       str     r0, [r1, #(OFS__THREAD__EXCEPTION_IP)]
+
+       enter_slowtrap_w_stack 0x00500000
+.endm
index 504fcd26ec335bc20f710458170d09fc104da46c..33e4dc57c311a7a4d3692d9710561170b10d7ea5 100644 (file)
@@ -9,58 +9,73 @@ IMPLEMENTATION [arm]:
 
 #include "cpu.h"
 
-//---------------------------------------------------------------------------
-IMPLEMENTATION [arm && armv5]:
+extern char kernel_page_directory[];
+
+namespace Bootstrap {
+
+struct Order_t;
+struct Phys_addr_t;
+struct Virt_addr_t;
+
+typedef cxx::int_type<unsigned, Order_t> Order;
+typedef cxx::int_type_order<Unsigned32, Virt_addr_t, Order> Virt_addr;
 
 enum
 {
-  Section_cachable = 0x40e,
-  Section_no_cache = 0x402,
-  Section_local    = 0,
-  Section_global   = 0,
+  Virt_ofs = Mem_layout::Sdram_phys_base - Mem_layout::Map_base,
 };
 
-void
-set_asid()
-{}
+}
 
 //---------------------------------------------------------------------------
-IMPLEMENTATION [arm && armv6plus && (mpcore || armca9)]:
+INTERFACE [arm && armv5]:
 
-enum
-{
-  Section_shared = 1UL << 16,
-};
+namespace Bootstrap {
+inline void set_asid()
+{}
+}
 
 //---------------------------------------------------------------------------
-IMPLEMENTATION [arm && armv6plus && !(mpcore || armca9)]:
+INTERFACE [arm && (armv6 || armv7)]:
 
-enum
+namespace Bootstrap {
+inline void
+set_asid()
 {
-  Section_shared = 0,
-};
-
+  asm volatile ("mcr p15, 0, %0, c13, c0, 1" : : "r" (0)); // ASID 0
+}
+}
 
 //---------------------------------------------------------------------------
-IMPLEMENTATION [arm && (armv6 || armv7)]:
+INTERFACE [arm && !arm_lpae]:
 
-enum
+namespace Bootstrap {
+inline void
+set_ttbr(Mword pdir)
 {
-  Section_cachable = 0x5406 | Section_shared,
-  Section_no_cache = 0x0402 | Section_shared,
-  Section_local    = (1 << 17),
-  Section_global   = 0,
-};
+  asm volatile("mcr p15, 0, %[pdir], c2, c0" // TTBR0
+               : : [pdir] "r" (pdir));
+}
+}
 
-void
-set_asid()
+//---------------------------------------------------------------------------
+INTERFACE [arm && arm_lpae]:
+
+namespace Bootstrap {
+inline void
+set_ttbr(Mword pdir)
 {
-  asm volatile ("MCR p15, 0, %0, c13, c0, 1" : : "r" (0)); // ASID 0
+  asm volatile("mcrr p15, 0, %[pdir], %[null], c2" // TTBR0
+               : :
+               [pdir]  "r" (pdir),
+               [null]  "r" (0));
+}
 }
 
 //---------------------------------------------------------------------------
 IMPLEMENTATION [arm && arm1176_cache_alias_fix]:
 
+namespace Bootstrap {
 static void
 do_arm_1176_cache_alias_workaround()
 {
@@ -74,38 +89,101 @@ do_arm_1176_cache_alias_workaround()
                     : : : "r0");
     }
 }
+}
 
 //---------------------------------------------------------------------------
 IMPLEMENTATION [arm && !arm1176_cache_alias_fix]:
 
+namespace Bootstrap {
 static void do_arm_1176_cache_alias_workaround() {}
+}
+
+
+//---------------------------------------------------------------------------
+IMPLEMENTATION [arm && arm_lpae]:
+
+#include <cxx/cxx_int>
+
+extern char kernel_lpae_dir[];
+
+namespace Bootstrap {
+typedef cxx::int_type_order<Unsigned64, Phys_addr_t, Order> Phys_addr;
+inline Order map_page_order() { return Order(21); }
+
+inline Phys_addr pt_entry(Phys_addr pa, bool cache, bool local)
+{
+  Phys_addr res = cxx::mask_lsb(pa, map_page_order()) | Phys_addr(1); // this is a block
+
+  if (local)
+    res |= Phys_addr(1 << 11); // nG flag
+
+  if (cache)
+    res |= Phys_addr(8);
+
+  res |= Phys_addr(1 << 10); // AF
+  res |= Phys_addr(3 << 8);  // Inner sharable
+  return res;
+}
+
+inline Phys_addr init_paging(void *const page_dir)
+{
+  Phys_addr *const lpae = reinterpret_cast<Phys_addr*>(kernel_lpae_dir + Virt_ofs);
+
+  for (unsigned i = 0; i < 4; ++i)
+    lpae[i] = Phys_addr(((Address)page_dir + 0x1000 * i) | 3);;
+
+  asm volatile ("mcr p15, 0, %0, c10, c2, 0 \n" // MAIR0
+                : : "r"(Page::Mair0_bits));
+
+  return Phys_addr((Mword)lpae);
+}
+
+};
+
+//---------------------------------------------------------------------------
+IMPLEMENTATION [arm && !arm_lpae]:
+
+#include <cxx/cxx_int>
+
+namespace Bootstrap {
+typedef cxx::int_type_order<Unsigned32, Phys_addr_t, Order> Phys_addr;
+inline Order map_page_order() { return Order(20); }
+
+inline Phys_addr pt_entry(Phys_addr pa, bool cache, bool local)
+{
+  return cxx::mask_lsb(pa, map_page_order())
+                | Phys_addr(cache ? Page::Section_cachable : Page::Section_no_cache)
+                | Phys_addr(local ? Page::Section_local : Page::Section_global);
+}
+
+inline Phys_addr init_paging(void *const page_dir)
+{
+  return Phys_addr((Mword)page_dir);
+}
+
+};
 
 //---------------------------------------------------------------------------
 IMPLEMENTATION [arm]:
 
 #include "kmem_space.h"
-#include "pagetable.h"
 
-void
-map_1mb(void *pd, Address va, Address pa, bool cache, bool local)
-{
-  Unsigned32 *const p = (Unsigned32*)pd;
-  p[va >> 20] = (pa & 0xfff00000)
-                | (cache ? Section_cachable : Section_no_cache)
-                | (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)
+
+namespace Bootstrap {
+
+
+inline Phys_addr map_page_size_phys() { return Phys_addr(1) << map_page_order(); }
+inline Virt_addr map_page_size() { return Virt_addr(1) << map_page_order(); }
+
+static void
+map_memory(void volatile *pd, Virt_addr va, Phys_addr pa,
+           bool cache, bool local)
 {
-  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);
+  Phys_addr *const p = (Phys_addr*)pd;
+  p[cxx::int_value<Virt_addr>(va >> map_page_order())]
+    = pt_entry(pa, cache, local);
+}
+
 }
 
 asm
@@ -135,61 +213,62 @@ extern char bootstrap_bss_end[];
 extern char __bss_start[];
 extern char __bss_end[];
 
-enum
-{
-  Virt_ofs = Mem_layout::Sdram_phys_base - Mem_layout::Map_base,
-};
+extern "C" void _start_kernel(void) __attribute__((long_call));
 
 extern "C" void bootstrap_main()
 {
-  extern char kernel_page_directory[];
-  void *const page_dir = kernel_page_directory + Virt_ofs;
+  typedef Bootstrap::Phys_addr Phys_addr;
+  typedef Bootstrap::Virt_addr Virt_addr;
+  typedef Bootstrap::Order Order;
 
-  Address va, pa;
+  void *const page_dir = kernel_page_directory + Bootstrap::Virt_ofs;
+
+  Unsigned32 tbbr = cxx::int_value<Phys_addr>(Bootstrap::init_paging(page_dir))
+                    | Page::Ttbr_bits;
+
+  Virt_addr va;
+  Phys_addr pa;
   // map sdram linear from 0xf0000000
-  for (va = Mem_layout::Map_base, pa = Mem_layout::Sdram_phys_base;
-       va < Mem_layout::Map_base + (4 << 20); va += 0x100000, pa += 0x100000)
-    map_1mb(page_dir, va, pa, true, false);
+  for (va = Virt_addr(Mem_layout::Map_base), pa = Phys_addr(Mem_layout::Sdram_phys_base);
+       va < Virt_addr(Mem_layout::Map_base + (4 << 20));
+       va += Bootstrap::map_page_size(), pa += Bootstrap::map_page_size_phys())
+    Bootstrap::map_memory(page_dir, va, pa, true, false);
 
   // map sdram 1:1
-  for (va = Mem_layout::Sdram_phys_base;
-       va < Mem_layout::Sdram_phys_base + (4 << 20); va += 0x100000)
-    map_1mb(page_dir, va, va, true, true);
-
-  map_hw(page_dir);
-
-  unsigned domains      = 0x55555555; // client for all domains
-  unsigned control      = Config::Cache_enabled
-                          ? Cpu::Cp15_c1_cache_enabled : Cpu::Cp15_c1_cache_disabled;
-
-  Mmu<Cache_flush_area, true>::flush_cache();
-
-  extern char _start_kernel[];
-
-  do_arm_1176_cache_alias_workaround();
-  set_asid();
-
-  asm volatile (
-      "mcr p15, 0, %[null], c7, c10, 4\n" // dsb
-      "mcr p15, 0, %[null], c8, c7, 0 \n" // tlb flush
-      "mcr p15, 0, %[null], c7, c10, 4\n" // dsb
-      "mcr p15, 0, %[doms], c3, c0    \n" // domains
-      "mcr p15, 0, %[pdir], c2, c0    \n" // pdbr
-      "mcr p15, 0, %[control], c1, c0 \n" // control
-
-      "mrc p15, 0, r0, c2, c0, 0      \n" // arbitrary read of cp15
-      "mov r0, r0                     \n" // wait for result
-      "sub pc, pc, #4                 \n"
-
-      "mov pc, %[start]               \n"
-      : :
-      [pdir]    "r"((Mword)page_dir | Page_table::Ttbr_bits),
-      [doms]    "r"(domains),
-      [control] "r"(control),
-      [start]   "r"(_start_kernel),
-      [null]    "r"(0)
-      : "r0"
-      );
+  for (va = Virt_addr(Mem_layout::Sdram_phys_base);
+       va < Virt_addr(Mem_layout::Sdram_phys_base + (4 << 20));
+       va += Bootstrap::map_page_size())
+    Bootstrap::map_memory(page_dir, va, Phys_addr(cxx::int_value<Virt_addr>(va)), true, true);
+
+  unsigned domains = 0x55555555; // client for all domains
+  unsigned control = Config::Cache_enabled
+                     ? Cpu::Cp15_c1_cache_enabled : Cpu::Cp15_c1_cache_disabled;
+
+  Mmu<Bootstrap::Cache_flush_area, true>::flush_cache();
+
+  Bootstrap::do_arm_1176_cache_alias_workaround();
+  Bootstrap::set_asid();
+
+  asm volatile("mcr p15, 0, %[ttbcr], c2, c0, 2" // TTBCR
+               : : [ttbcr] "r" (Page::Ttbcr_bits));
+  Mem::dsb();
+  asm volatile("mcr p15, 0, %[null], c8, c7, 0" // TLBIALL
+               : : [null]  "r" (0));
+  Mem::dsb();
+  asm volatile("mcr p15, 0, %[doms], c3, c0" // domains
+               : : [doms]  "r" (domains));
+
+  Bootstrap::set_ttbr(tbbr | Page::Ttbr_bits);
+
+  asm volatile("mcr p15, 0, %[control], c1, c0" // control
+               : : [control] "r" (control));
+  Mem::isb();
+
+  // The first 4MB of phys memory are always mapped to Map_base
+  Mem_layout::add_pmem(Mem_layout::Sdram_phys_base, Mem_layout::Map_base,
+                       4 << 20);
+
+  _start_kernel();
 
   while(1)
     ;
diff --git a/kernel/fiasco/src/kern/arm/bsp/bcm2835/Kconfig b/kernel/fiasco/src/kern/arm/bsp/bcm2835/Kconfig
new file mode 100644 (file)
index 0000000..bd6e34f
--- /dev/null
@@ -0,0 +1,4 @@
+# PF: BCM2835
+# PFDESCR: Broadcom 2835
+# PFSELECT: CAN_ARM_CPU_1176
+# PFDEPENDS: ARM
diff --git a/kernel/fiasco/src/kern/arm/bsp/bcm2835/Modules b/kernel/fiasco/src/kern/arm/bsp/bcm2835/Modules
new file mode 100644 (file)
index 0000000..987cbe6
--- /dev/null
@@ -0,0 +1,18 @@
+# vim:set ft=make:
+
+SUBSYSTEMS              += LIBUART
+OBJECTS_LIBUART         += uart_pl011.o
+PREPROCESS_PARTS        += libuart generic_tickless_idle bcm2835
+RAM_PHYS_BASE           := 0
+
+
+uart_IMPL             += uart-arm-bcm2835
+config_IMPL           += config-arm-bcm2835
+mem_layout_IMPL       += mem_layout-arm-bcm2835
+pic_IMPL              += pic-arm-bcm2835
+bootstrap_IMPL        += bootstrap-arm-bcm2835
+timer_IMPL            += timer-arm-bcm2835
+timer_tick_IMPL       += timer_tick-single-vector
+kernel_uart_IMPL      += kernel_uart-arm-bcm2835
+reset_IMPL            += reset-arm-bcm2835
+clock_IMPL            += clock-generic
diff --git a/kernel/fiasco/src/kern/arm/bsp/bcm2835/bootstrap-arm-bcm2835.cpp b/kernel/fiasco/src/kern/arm/bsp/bcm2835/bootstrap-arm-bcm2835.cpp
new file mode 100644 (file)
index 0000000..1457c69
--- /dev/null
@@ -0,0 +1,6 @@
+INTERFACE [arm && bcm2835]:
+namespace Bootstrap {
+enum {
+  Cache_flush_area = 0xe0000000,
+};
+}
diff --git a/kernel/fiasco/src/kern/arm/bsp/bcm2835/config-arm-bcm2835.cpp b/kernel/fiasco/src/kern/arm/bsp/bcm2835/config-arm-bcm2835.cpp
new file mode 100644 (file)
index 0000000..0acd0b0
--- /dev/null
@@ -0,0 +1,3 @@
+INTERFACE [arm && bcm2835]:
+
+#define TARGET_NAME "Broadcom 2835"
diff --git a/kernel/fiasco/src/kern/arm/bsp/bcm2835/kernel_uart-arm-bcm2835.cpp b/kernel/fiasco/src/kern/arm/bsp/bcm2835/kernel_uart-arm-bcm2835.cpp
new file mode 100644 (file)
index 0000000..bc23ee1
--- /dev/null
@@ -0,0 +1,12 @@
+INTERFACE:
+
+// On ARM the MMIO for the uart is accessible before the MMU is fully up
+EXTENSION class Kernel_uart { enum { Bsp_init_mode = Init_before_mmu }; };
+
+IMPLEMENTATION [arm && bcm2835 && serial]:
+
+IMPLEMENT
+bool Kernel_uart::startup(unsigned, int)
+{
+  return Uart::startup();
+}
diff --git a/kernel/fiasco/src/kern/arm/bsp/bcm2835/mem_layout-arm-bcm2835.cpp b/kernel/fiasco/src/kern/arm/bsp/bcm2835/mem_layout-arm-bcm2835.cpp
new file mode 100644 (file)
index 0000000..aab5906
--- /dev/null
@@ -0,0 +1,12 @@
+INTERFACE [arm && bcm2835]: //---------------------------------------------
+
+EXTENSION class Mem_layout
+{
+public:
+  enum Phys_layout_bcm2835 : Address {
+    Timer_phys_base      = 0x20003000,
+    Pic_phys_base        = 0x2000b200,
+    Watchdog_phys_base   = 0x20100000,
+    Uart_phys_base       = 0x20201000,
+  };
+};
diff --git a/kernel/fiasco/src/kern/arm/bsp/bcm2835/pic-arm-bcm2835.cpp b/kernel/fiasco/src/kern/arm/bsp/bcm2835/pic-arm-bcm2835.cpp
new file mode 100644 (file)
index 0000000..2f24e09
--- /dev/null
@@ -0,0 +1,135 @@
+// ---------------------------------------------------------------------
+IMPLEMENTATION [arm && bcm2835]:
+
+#include "assert.h"
+#include "initcalls.h"
+#include "irq_chip_generic.h"
+#include "irq_mgr.h"
+#include "mmio_register_block.h"
+#include "kmem.h"
+
+class Irq_chip_bcm : public Irq_chip_gen, Mmio_register_block
+{
+public:
+  enum
+  {
+    Irq_basic_pending  = 0x0,
+    Irq_pending_1      = 0x4,
+    Irq_pending_2      = 0x8,
+    Fiq_control        = 0xc,
+    Enable_IRQs_1      = 0x10,
+    Enable_IRQs_2      = 0x14,
+    Enable_Basic_IRQs  = 0x18,
+    Disable_IRQs_1     = 0x1c,
+    Disable_IRQs_2     = 0x20,
+    Disable_Basic_IRQs = 0x24,
+  };
+
+  unsigned set_mode(Mword, unsigned) { return Irq_base::Trigger_level; }
+  void set_cpu(Mword, Cpu_number) {}
+  void ack(Mword) { /* ack is empty */ }
+};
+
+PUBLIC
+Irq_chip_bcm::Irq_chip_bcm()
+: Irq_chip_gen(96),
+  Mmio_register_block(Kmem::mmio_remap(Mem_layout::Pic_phys_base))
+{
+  write<Mword>(~0UL, Disable_Basic_IRQs);
+  write<Mword>(~0UL, Disable_IRQs_1);
+  write<Mword>(~0UL, Disable_IRQs_2);
+}
+
+PUBLIC
+void
+Irq_chip_bcm::mask(Mword irq)
+{
+  assert(cpu_lock.test());
+  write<Mword>(1 << (irq & 0x1f), Disable_IRQs_1 + ((irq & 0x60) >> 3));
+}
+
+PUBLIC
+void
+Irq_chip_bcm::mask_and_ack(Mword irq)
+{
+  mask(irq);
+  // ack is empty
+}
+
+PUBLIC
+void
+Irq_chip_bcm::unmask(Mword irq)
+{
+  assert(cpu_lock.test());
+  write<Mword>(1 << (irq & 0x1f), Enable_IRQs_1 + ((irq & 0x60) >> 3));
+}
+
+static Static_object<Irq_mgr_single_chip<Irq_chip_bcm> > mgr;
+
+IMPLEMENT FIASCO_INIT
+void Pic::init()
+{
+  Irq_mgr::mgr = mgr.construct();
+}
+
+IMPLEMENT inline
+Pic::Status Pic::disable_all_save()
+{
+  Status s = 0;
+  return s;
+}
+
+IMPLEMENT inline
+void Pic::restore_all(Status)
+{}
+
+PUBLIC
+void
+Irq_chip_bcm::irq_handler()
+{
+  while (1)
+    {
+      unsigned b = 64;
+      Mword p = read<Mword>(Irq_basic_pending);
+
+      if (p & 0x100)
+        {
+          b = 0;
+          p = read<Mword>(Irq_pending_1);
+        }
+      else if (p & 0x200)
+        {
+          b = 32;
+          p = read<Mword>(Irq_pending_2);
+        }
+      else if (p)
+        {
+          unsigned m = p & 0x1ffc00;
+          if (m)
+            {
+              m >>= 10;
+              char map[11] = { 7, 9, 10, 18, 19, 53, 54, 55, 56, 57, 62 };
+
+              handle_irq<Irq_chip_bcm>(map[31 - __builtin_clz(m)], 0);
+              continue;
+            }
+        }
+
+      if (p)
+        handle_irq<Irq_chip_bcm>(b + 31 - __builtin_clz(p), 0);
+      else
+        return;
+    }
+}
+
+extern "C"
+void irq_handler()
+{ mgr->c.irq_handler(); }
+
+//---------------------------------------------------------------------------
+IMPLEMENTATION [debug && bcm2835]:
+
+PUBLIC
+char const *
+Irq_chip_bcm::chip_type() const
+{ return "BCM2835"; }
diff --git a/kernel/fiasco/src/kern/arm/bsp/bcm2835/reset-arm-bcm2835.cpp b/kernel/fiasco/src/kern/arm/bsp/bcm2835/reset-arm-bcm2835.cpp
new file mode 100644 (file)
index 0000000..f34091c
--- /dev/null
@@ -0,0 +1,22 @@
+IMPLEMENTATION [arm && bcm2835]:
+
+#include "io.h"
+#include "kmem.h"
+
+#include <cstdio>
+
+void __attribute__ ((noreturn))
+platform_reset(void)
+{
+  enum { Rstc = 0x1c, Wdog = 0x24 };
+
+  Address base = Kmem::mmio_remap(Mem_layout::Watchdog_phys_base);
+
+  Mword pw = 0x5a << 24;
+  Io::write<Mword>(pw | 8, base + Wdog);
+  Io::write<Mword>((Io::read<Mword>(base + Rstc) & ~0x30) | pw | 0x20,
+                   base + Rstc);
+
+  for (;;)
+    ;
+}
diff --git a/kernel/fiasco/src/kern/arm/bsp/bcm2835/timer-arm-bcm2835.cpp b/kernel/fiasco/src/kern/arm/bsp/bcm2835/timer-arm-bcm2835.cpp
new file mode 100644 (file)
index 0000000..847ff5b
--- /dev/null
@@ -0,0 +1,87 @@
+// --------------------------------------------------------------------------
+INTERFACE [arm && bcm2835]:
+
+#include "mmio_register_block.h"
+
+EXTENSION class Timer : private Mmio_register_block
+{
+public:
+  static unsigned irq() { return 3; }
+
+private:
+  enum {
+      CS  = 0,
+      CLO = 4,
+      CHI = 8,
+      C0  = 0xc,
+      C1  = 0x10,
+      C2  = 0x14,
+      C3  = 0x18,
+
+      Timer_nr = 3,
+      Interval = 1000,
+  };
+
+  static Static_object<Timer> _timer;
+};
+
+// ----------------------------------------------------------------------
+IMPLEMENTATION [arm && bcm2835]:
+
+#include "config.h"
+#include "kip.h"
+#include "kmem.h"
+#include "mem_layout.h"
+
+Static_object<Timer> Timer::_timer;
+
+PRIVATE inline
+void
+Timer::set_next()
+{
+  write<Mword>(read<Mword>(CLO) + Interval, C0 + Timer_nr * 4);
+}
+
+PUBLIC
+Timer::Timer(Address base) : Mmio_register_block(base)
+{
+  set_next();
+}
+
+IMPLEMENT
+void Timer::init(Cpu_number)
+{ _timer.construct(Kmem::mmio_remap(Mem_layout::Timer_phys_base)); }
+
+static inline
+Unsigned64
+Timer::timer_to_us(Unsigned32 /*cr*/)
+{ return 0; }
+
+static inline
+Unsigned64
+Timer::us_to_timer(Unsigned64 us)
+{ (void)us; return 0; }
+
+PUBLIC static inline NEEDS[Timer::set_next]
+void
+Timer::acknowledge()
+{
+  _timer->set_next();
+  _timer->write<Mword>(1 << Timer_nr, CS);
+}
+
+IMPLEMENT inline
+void
+Timer::update_one_shot(Unsigned64 wakeup)
+{
+  (void)wakeup;
+}
+
+IMPLEMENT inline NEEDS["kip.h"]
+Unsigned64
+Timer::system_clock()
+{
+  if (Config::Scheduler_one_shot)
+    return 0;
+  return Kip::k()->clock;
+}
diff --git a/kernel/fiasco/src/kern/arm/bsp/bcm2835/uart-arm-bcm2835.cpp b/kernel/fiasco/src/kern/arm/bsp/bcm2835/uart-arm-bcm2835.cpp
new file mode 100644 (file)
index 0000000..60f90bb
--- /dev/null
@@ -0,0 +1,14 @@
+IMPLEMENTATION [bcm2835]:
+
+#include "uart_pl011.h"
+#include "mem_layout.h"
+
+IMPLEMENT Address Uart::base() const { return Mem_layout::Uart_phys_base; }
+
+IMPLEMENT int Uart::irq() const { return 57; }
+
+IMPLEMENT L4::Uart *Uart::uart()
+{
+  static L4::Uart_pl011 uart(3000000);
+  return &uart;
+}
diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos/Kconfig b/kernel/fiasco/src/kern/arm/bsp/exynos/Kconfig
new file mode 100644 (file)
index 0000000..0b3f2d1
--- /dev/null
@@ -0,0 +1,90 @@
+# PF: EXYNOS
+# PFDESCR: Samsung Exynos
+# PFDEPENDS: ARM
+
+config PF_EXYNOS4
+        bool
+        depends on PF_EXYNOS
+        select CAN_ARM_CPU_CORTEX_A9
+        select CAN_ARM_CACHE_L2CXX0
+        select ARM_SECMONIF_MC if ARM_EM_NS
+
+config PF_EXYNOS5
+        bool
+        depends on PF_EXYNOS
+        select CAN_ARM_CPU_CORTEX_A15
+        select ARM_SECMONIF_MC if ARM_EM_NS
+
+config PF_EXYNOS_PKG_IDS
+        string "Exynos package ID file"
+        default ""
+        help
+          Optional file for board IDs, to select proper UART at runtime.
+          It is safe to leave this empty and select the UART in this
+          configuration.
+
+choice
+        prompt "Exynos Platform"
+        default PF_EXYNOS_4210
+        help
+          Select the Exynos Soc type, if the optional package-ID
+          file is used (PF_EXYNOS_PKG_IDS) this file overrides the
+          Soc type for a matching platform.
+
+config PF_EXYNOS4_4210
+        bool "4210 - Exynos 4"
+        depends on PF_EXYNOS
+        select PF_EXYNOS4
+        help
+          Choose for Exynos4 based platforms.
+
+config PF_EXYNOS4_4412
+        bool "4412 - Exynos 4"
+        depends on PF_EXYNOS
+        select PF_EXYNOS4
+        help
+          Choose for Exynos4 based platforms.
+
+config PF_EXYNOS5_5250
+        bool "5250 - Exynos 5"
+        depends on PF_EXYNOS
+        select PF_EXYNOS5
+        help
+          Choose for Exynos5 based platforms.
+
+endchoice
+
+
+config PF_EXYNOS_UART_NR
+        int "Which UART to use for kernel output"
+        range 0 3
+        default 2
+        help
+          Select which UART to use for kernel I/O. If the optional
+          package-ID file is used (PF_EXYNOS_PKG_IDS) this file
+          overrides the UART number for a matching platform.
+          Odroid-A and Odroid-X use UART 1, the Exynos Snow platform uses
+          UART 3, most others use UART 2.
+
+choice
+       prompt "Platform Timer"
+       default PF_EXYNOS_TIMER_MCT
+
+config PF_EXYNOS_TIMER_MCT
+       bool "Multi-core timer"
+
+config PF_EXYNOS_TIMER_MP
+       bool "MP timer"
+       depends on ARM_CORTEX_A9
+
+config PF_EXYNOS_TIMER_PWM
+       bool "PWM timer"
+
+endchoice
+
+config PF_EXYNOS_EXTGIC
+        bool "Use ExtGic"
+       depends on PF_EXYNOS_TIMER_MCT
+        depends on PF_EXYNOS4
+        help
+          Use internal or external GIC.
diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos/Modules b/kernel/fiasco/src/kern/arm/bsp/exynos/Modules
new file mode 100644 (file)
index 0000000..a99c283
--- /dev/null
@@ -0,0 +1,47 @@
+# vim:set ft=make:
+
+SUBSYSTEMS              += LIBUART
+OBJECTS_LIBUART         += uart_s3c2410.o
+OBJECTS_LIBUART         += $(OBJECTS_LIBUART-y)
+PREPROCESS_PARTS        += exynos libuart pic_gic watchdog tickless_idle \
+                           bsp_cpu
+PREPROCESS_PARTS-$(CONFIG_PF_EXYNOS4)       += exynos4
+PREPROCESS_PARTS-$(CONFIG_PF_EXYNOS5)       += exynos5
+PREPROCESS_PARTS-$(CONFIG_PF_EXYNOS_TIMER_MCT) += exynos_mct
+PREPROCESS_PARTS-$(CONFIG_PF_EXYNOS_TIMER_MP)  += mptimer
+PREPROCESS_PARTS-$(CONFIG_PF_EXYNOS_EXTGIC) += exynos_extgic irregular_gic
+PREPROCESS_PARTS += $(if $(filter-out "",$(CONFIG_PF_EXYNOS_PKG_IDS)),pkg_id_file)
+
+INTERFACES_KERNEL       += gic platform smc timer_mct
+VPATH                   += kern/arm/bsp/s3c
+RAM_PHYS_BASE           := $(if $(CONFIG_ARM_EM_TZ),0xb0000000,0x40000000)
+MPCORE_PHYS_BASE        := 0x10500000
+
+
+uart_IMPL             += uart-arm-exynos
+config_IMPL           += config-arm-exynos
+cpu_IMPL              += cpu-arm-exynos
+scu_IMPL              += scu-arm-exynos
+mem_layout_IMPL       += mem_layout-arm-exynos
+pic_IMPL              += pic-arm-gic-exynos \
+                         $(if $(CONFIG_PF_EXYNOS_EXTGIC),,pic-gic)
+ipi_IMPL              += $(if $(CONFIG_PF_EXYNOS_EXTGIC),ipi-arm-exynos)
+thread_IMPL           += thread-arm-exynos
+bootstrap_IMPL        += bootstrap-arm-exynos
+
+timer_IMPL            += $(if $(CONFIG_PF_EXYNOS_TIMER_MP)$(CONFIG_PF_EXYNOS_TIMER_MCT),timer-arm-mptimer timer-arm-exynos)
+timer_IMPL            += $(if $(CONFIG_PF_EXYNOS_TIMER_PWM),timer-arm-s3c2410)
+
+timer_tick_IMPL       += $(if $(CONFIG_PF_EXYNOS_TIMER_MCT),timer_tick-exynos-mct)
+timer_tick_IMPL       += $(if $(CONFIG_PF_EXYNOS_TIMER_MP),timer_tick-single-vector)
+timer_tick_IMPL       += $(if $(CONFIG_PF_EXYNOS_TIMER_PWM),$(if $(CONFIG_MP),timer_tick-broadcast,timer_tick-single-vector))
+
+kernel_uart_IMPL      += kernel_uart-arm-exynos
+kernel_thread_IMPL    += kernel_thread-arm-exynos
+reset_IMPL            += reset-arm-exynos
+clock_IMPL            += clock-generic
+outer_cache_IMPL      += outer_cache-arm-exynos
+platform_IMPL         += platform-arm-exynos
+watchdog_IMPL         += watchdog-arm-exynos
+
+platform_control_IMPL += platform_control-arm-exynos
diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos/bootstrap-arm-exynos.cpp b/kernel/fiasco/src/kern/arm/bsp/exynos/bootstrap-arm-exynos.cpp
new file mode 100644 (file)
index 0000000..693a3a4
--- /dev/null
@@ -0,0 +1,6 @@
+INTERFACE [arm && exynos]:
+
+namespace Bootstrap {
+enum { Cache_flush_area = 0, };
+}
+
diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos/config-arm-exynos.cpp b/kernel/fiasco/src/kern/arm/bsp/exynos/config-arm-exynos.cpp
new file mode 100644 (file)
index 0000000..f5e6f85
--- /dev/null
@@ -0,0 +1,18 @@
+INTERFACE[arm && exynos]:
+
+#include "globalconfig.h"
+
+#define TARGET_NAME "Samsung Exynos"
+
+EXTENSION class Config
+{
+public:
+  enum
+  {
+#ifdef CONFIG_PF_EXYNOS_UART_NR
+    Uart_nr = CONFIG_PF_EXYNOS_UART_NR
+#else
+    Uart_nr = 0
+#endif
+  };
+};
diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos/cpu-arm-exynos.cpp b/kernel/fiasco/src/kern/arm/bsp/exynos/cpu-arm-exynos.cpp
new file mode 100644 (file)
index 0000000..0dc3302
--- /dev/null
@@ -0,0 +1,10 @@
+IMPLEMENTATION [arm && bsp_cpu]:
+
+PRIVATE
+void
+Cpu::bsp_init(bool is_boot_cpu)
+{
+  // enable FOZ -- do this in conjunction with L2 cache
+  if (is_boot_cpu)
+    set_actrl(1 << 3);
+}
diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos/ipi-arm-exynos.cpp b/kernel/fiasco/src/kern/arm/bsp/exynos/ipi-arm-exynos.cpp
new file mode 100644 (file)
index 0000000..853e333
--- /dev/null
@@ -0,0 +1,26 @@
+IMPLEMENTATION [mp && exynos && exynos_extgic]:
+
+#include "pic.h"
+#include "gic.h"
+
+PUBLIC static inline NEEDS["pic.h"]
+void Ipi::send(Message m, Cpu_number from_cpu, Cpu_phys_id to_cpu)
+{
+  Pic::gic.cpu(from_cpu)->softint_cpu(1UL << cxx::int_value<Cpu_phys_id>(to_cpu), m);
+  stat_sent(from_cpu);
+}
+
+PUBLIC static inline NEEDS["pic.h"]
+void Ipi::send(Message m, Cpu_number from_cpu, Cpu_number to_cpu)
+{
+  Pic::gic.cpu(from_cpu)->softint_cpu(1UL << cxx::int_value<Cpu_phys_id>(_ipi.cpu(to_cpu)._phys_id), m);
+  stat_sent(from_cpu);
+}
+
+PUBLIC static inline
+void
+Ipi::bcast(Message m, Cpu_number from_cpu)
+{
+  Pic::gic.cpu(from_cpu)->softint_bcast(m);
+}
+
diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos/kernel_thread-arm-exynos.cpp b/kernel/fiasco/src/kern/arm/bsp/exynos/kernel_thread-arm-exynos.cpp
new file mode 100644 (file)
index 0000000..e4ff31a
--- /dev/null
@@ -0,0 +1,22 @@
+//--------------------------------------------------------------------------
+IMPLEMENTATION [arm && tickless_idle && exynos]:
+
+#include "cpu.h"
+#include "pic.h"
+#include "platform_control.h"
+#include "processor.h"
+#include "scheduler.h"
+
+PROTECTED inline NEEDS["processor.h", "cpu.h", "platform_control.h", "scheduler.h"]
+void
+Kernel_thread::arch_tickless_idle(Cpu_number)
+{
+  Proc::halt();
+}
+
+PROTECTED inline NEEDS["processor.h"]
+void
+Kernel_thread::arch_idle(Cpu_number)
+{
+  Proc::halt();
+}
diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos/kernel_uart-arm-exynos.cpp b/kernel/fiasco/src/kern/arm/bsp/exynos/kernel_uart-arm-exynos.cpp
new file mode 100644 (file)
index 0000000..9e57057
--- /dev/null
@@ -0,0 +1,12 @@
+INTERFACE:
+
+// On ARM the MMIO for the uart is accessible before the MMU is fully up
+EXTENSION class Kernel_uart { enum { Bsp_init_mode = Init_before_mmu }; };
+
+IMPLEMENTATION [arm && exynos && serial]:
+
+IMPLEMENT
+bool Kernel_uart::startup(unsigned, int)
+{
+  return Uart::startup();
+}
diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos/mem_layout-arm-exynos.cpp b/kernel/fiasco/src/kern/arm/bsp/exynos/mem_layout-arm-exynos.cpp
new file mode 100644 (file)
index 0000000..6da8343
--- /dev/null
@@ -0,0 +1,89 @@
+INTERFACE [arm && exynos4]:
+
+#include <config.h>
+
+EXTENSION class Mem_layout
+{
+public:
+  enum Phys_layout_exynos : Address {
+    Sysram_phys_base     = 0x02020000,
+    Gpio3_phys_base      = 0x03860000,
+
+    Chip_id_phys_base    = 0x10000000,
+    Pmu_phys_base        = 0x10020000,
+    Cmu_phys_base        = 0x10030000,
+    Mct_phys_base        = 0x10050000,
+    Watchdog_phys_base   = 0x10060000,
+
+    Irq_combiner_ext_phys_base   = 0x10440000,
+    Irq_combiner_int_phys_base   = 0x10448000,
+
+    Gic_cpu_ext_cpu0_phys_base   = 0x10480000,
+    Gic_cpu_ext_cpu1_phys_base   = 0x10488000, // cpu 1 is + 8000
+    Gic_dist_ext_cpu0_phys_base  = 0x10490000,
+    Gic_dist_ext_cpu1_phys_base  = 0x10498000,
+
+    Devices0_phys_base     = 0x10500000,
+    Mp_scu_phys_base       = Devices0_phys_base + 0x00000000,
+    Gic_cpu_int_phys_base  = Devices0_phys_base + 0x00000100,
+    Gic_dist_int_phys_base = Devices0_phys_base + 0x00001000,
+    L2cxx0_phys_base       = Devices0_phys_base + 0x00002000,
+
+    Gpio2_phys_base      = 0x11000000,
+    Gpio1_phys_base      = 0x11400000,
+    Sromc_phys_base      = 0x12570000,
+    Uart_phys_base       = 0x13800000,
+    Pwm_phys_base        = 0x139d0000,
+  };
+};
+
+INTERFACE [arm && exynos4 && exynos_extgic]:
+
+EXTENSION class Mem_layout
+{
+public:
+  enum Phys_layout_exynos_extgic : Address {
+    Gic_cpu_phys_base            = Gic_cpu_ext_cpu0_phys_base,
+    Gic_dist_phys_base           = Gic_dist_ext_cpu0_phys_base,
+    Irq_combiner_phys_base       = Irq_combiner_ext_phys_base,
+  };
+};
+
+INTERFACE [arm && exynos4 && !exynos_extgic]:
+
+EXTENSION class Mem_layout
+{
+public:
+  enum Phys_layout_exynos_intgic : Address {
+
+    Gic_cpu_phys_base            = Gic_cpu_int_phys_base,
+    Gic_dist_phys_base           = Gic_dist_int_phys_base,
+    Irq_combiner_phys_base       = Irq_combiner_int_phys_base,
+  };
+};
+
+INTERFACE [arm && exynos5]:
+
+EXTENSION class Mem_layout
+{
+public:
+  enum Phys_layout_exynos : Address {
+    Sysram_phys_base       = 0x02020000,
+    Gpio3_phys_base        = 0x10d10000,
+    Gpio4_phys_base        = 0x03860000,
+    Chip_id_phys_base      = 0x10000000,
+    Cmu_phys_base          = 0x10010000,
+    Pmu_phys_base          = 0x10040000,
+    Mct_phys_base          = 0x101c0000,
+    Watchdog_phys_base     = 0x101d0000,
+    Irq_combiner_phys_base = 0x10440000,
+    Gic_dist_phys_base     = 0x10481000,
+    Gic_cpu_phys_base      = 0x10482000,
+    Mp_scu_phys_base       = 0x10500000,
+    Gpio1_phys_base        = 0x11400000,
+    Sromc_phys_base        = 0x12250000,
+    Uart_phys_base         = 0x12c00000,
+    Pwm_phys_base          = 0x12dd0000,
+    Gpio2_phys_base        = 0x13400000,
+  };
+};
diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos/outer_cache-arm-exynos.cpp b/kernel/fiasco/src/kern/arm/bsp/exynos/outer_cache-arm-exynos.cpp
new file mode 100644 (file)
index 0000000..2f0d4f0
--- /dev/null
@@ -0,0 +1,49 @@
+IMPLEMENTATION [arm && exynos && outer_cache_l2cxx0]:
+
+#include "platform.h"
+#include "smc.h"
+
+IMPLEMENT
+Mword
+Outer_cache::platform_init(Mword auxc)
+{
+  // power control
+  enum {
+    Standby_mode_enable       = 1 << 0,
+    Dynamic_clk_gating_enable = 1 << 1,
+  };
+
+  unsigned tag_lat = 0x110;
+  unsigned data_lat = Platform::is_4210() ? 0x110 : 0x120;
+  unsigned prefctrl = 0x30000007;
+  if (Platform::is_4412() && Platform::subrev() > 0x10)
+    prefctrl = 0x71000007;
+
+  Mword auxc_mask = 0xc200fffe;
+  Mword auxc_bits =   (1 <<  0)  // Full Line of Zero Enable
+                    | (1 << 16)  // 16 way
+                    | (3 << 17)  // way size == 64KB
+                    | (1 << 22)  // shared ignored
+                    | (3 << 26)  // tz
+                    | (1 << 28)  // data prefetch enable
+                    | (1 << 29)  // insn prefetch enable
+                    | (1 << 30)  // early BRESP enable
+                    ;
+
+  if (!Platform::running_ns())
+    {
+      l2cxx0->write<Mword>(tag_lat, L2cxx0::TAG_RAM_CONTROL);
+      l2cxx0->write<Mword>(data_lat, L2cxx0::DATA_RAM_CONTROL);
+
+      l2cxx0->write<Mword>(prefctrl, 0xf60);
+
+      l2cxx0->write<Mword>(Standby_mode_enable | Dynamic_clk_gating_enable,
+                           0xf80);
+    }
+  else
+    Exynos_smc::l2cache_setup(tag_lat, data_lat, prefctrl,
+                              Standby_mode_enable | Dynamic_clk_gating_enable,
+                              auxc_bits, auxc_mask);
+
+  return (auxc & auxc_mask) | auxc_bits;
+}
diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos/pic-arm-gic-exynos.cpp b/kernel/fiasco/src/kern/arm/bsp/exynos/pic-arm-gic-exynos.cpp
new file mode 100644 (file)
index 0000000..cc76efc
--- /dev/null
@@ -0,0 +1,904 @@
+INTERFACE:
+#include "gic.h"
+
+//-------------------------------------------------------------------------
+IMPLEMENTATION [arm && pic_gic && exynos]:
+
+class Mgr_exynos : public Irq_mgr
+{
+protected:
+  struct Chip_block
+  {
+    unsigned sz;
+    Irq_chip_gen *chip;
+  };
+
+  void calc_nr_irq()
+  {
+    _nr_irqs = 0;
+    for (unsigned i = 0; i < _nr_blocks; ++i)
+      _nr_irqs += _block[i].sz;
+  }
+
+public:
+  unsigned nr_irqs() const { return _nr_irqs; }
+  unsigned nr_msis() const { return 0; }
+
+protected:
+  unsigned _nr_blocks;
+  unsigned _nr_irqs;
+  Chip_block *_block;
+};
+
+
+//-------------------------------------------------------------------------
+IMPLEMENTATION [arm && pic_gic && exynos]:
+
+#include <cstring>
+#include <cstdio>
+
+#include "assert.h"
+#include "boot_alloc.h"
+#include "config.h"
+#include "initcalls.h"
+#include "io.h"
+#include "irq_chip.h"
+#include "irq_chip_generic.h"
+#include "irq_mgr.h"
+#include "gic.h"
+#include "kmem.h"
+#include "mmio_register_block.h"
+#include "warn.h"
+
+#include "platform.h"
+
+
+class Gpio_eint_chip : public Irq_chip_gen, private Mmio_register_block
+{
+private:
+  unsigned offs(Mword pin) const { return (pin >> 3) * 4; }
+
+public:
+  Gpio_eint_chip(Mword gpio_base)
+    : Irq_chip_gen(8 * 16), _gpio_base(gpio_base)
+  {}
+
+  void mask(Mword pin)
+  { Io::set<Mword>(1 << (pin & 7), _gpio_base + MASK + offs(pin)); }
+
+  void ack(Mword pin)
+  { Io::set<Mword>(1 << (pin & 7), _gpio_base + PEND + offs(pin)); }
+
+  void mask_and_ack(Mword pin) { mask(pin); ack(pin); }
+
+  void unmask(Mword pin)
+  { Io::clear<Mword>(1 << (pin & 7), _gpio_base + MASK + offs(pin)); }
+
+  void set_cpu(Mword, Cpu_number) {}
+  unsigned set_mode(Mword pin, unsigned m)
+  {
+    unsigned v;
+
+    m &= ~1;
+
+    switch (m)
+    {
+      default: m = Irq_base::Trigger_level | Irq_base::Polarity_low;
+               /* Fall-through */
+      case Irq_base::Trigger_level | Irq_base::Polarity_low:  v = 0; break;
+      case Irq_base::Trigger_level | Irq_base::Polarity_high: v = 1; break;
+      case Irq_base::Trigger_edge  | Irq_base::Polarity_low:  v = 2; break;
+      case Irq_base::Trigger_edge  | Irq_base::Polarity_high: v = 3; break;
+      case Irq_base::Trigger_edge  | Irq_base::Polarity_both: v = 4; break;
+    };
+
+    Mword a = _gpio_base + INTCON + offs(pin);
+    pin = pin % 8;
+    v <<= pin * 4;
+    Io::write<Mword>((Io::read<Mword>(a) & ~(7 << (pin * 4))) | v, a);
+
+    return m;
+  }
+  unsigned pending() { return Io::read<Mword>(_gpio_base + 0xb08); }
+
+private:
+  enum {
+    INTCON = 0x700,
+    MASK   = 0x900,
+    PEND   = 0xa00,
+  };
+  Mword _gpio_base;
+};
+
+class Gpio_wakeup_chip : public Irq_chip_gen, private Mmio_register_block
+{
+private:
+  unsigned offs(Mword pin) const { return (pin >> 3) * 4; }
+
+public:
+  explicit Gpio_wakeup_chip(Address physbase)
+  : Irq_chip_gen(32),
+    Mmio_register_block(Kmem::mmio_remap(physbase))
+  {}
+
+  void mask(Mword pin)
+  { modify<Mword>(1 << (pin & 7), 0, MASK + offs(pin)); }
+
+  void ack(Mword pin)
+  { modify<Mword>(1 << (pin & 7), 0, PEND + offs(pin)); }
+
+  void mask_and_ack(Mword pin) { mask(pin); ack(pin); }
+
+  void unmask(Mword pin)
+  { modify<Mword>(0, 1 << (pin & 7), MASK + offs(pin)); }
+  void set_cpu(Mword, Cpu_number) {}
+
+  unsigned set_mode(Mword pin, unsigned m)
+  {
+    unsigned v;
+    m &= ~1;
+
+    switch (m)
+    {
+      default: m = Irq_base::Trigger_level | Irq_base::Polarity_low;
+               /* Fall-through */
+      case Irq_base::Trigger_level | Irq_base::Polarity_low:  v = 0; break;
+      case Irq_base::Trigger_level | Irq_base::Polarity_high: v = 1; break;
+      case Irq_base::Trigger_edge  | Irq_base::Polarity_low:  v = 2; break;
+      case Irq_base::Trigger_edge  | Irq_base::Polarity_high: v = 3; break;
+      case Irq_base::Trigger_edge  | Irq_base::Polarity_both: v = 4; break;
+    };
+
+    Mword a = INTCON + offs(pin);
+    pin = pin % 8;
+    v <<= pin * 4;
+    modify<Mword>(v, 7UL << (pin * 4), a);
+
+    return m;
+  }
+
+  unsigned pending01() const // debug only
+  {
+    return read<Unsigned8>(PEND + 0) | (static_cast<unsigned>(read<Unsigned8>(PEND +  4)) << 8);
+  }
+
+  unsigned pending23() const
+  {
+    return read<Unsigned8>(PEND + 8) | (static_cast<unsigned>(read<Unsigned8>(PEND + 12)) << 8);
+  }
+
+private:
+  enum {
+    INTCON = 0xe00,
+    FLTCON = 0xe80,
+    MASK   = 0xf00,
+    PEND   = 0xf40,
+  };
+};
+
+class Combiner_chip : public Irq_chip_gen, private Mmio_register_block
+{
+public:
+  enum
+  {
+    Enable_set    = 0,
+    Enable_clear  = 4,
+    Status        = 12,
+  };
+
+  enum
+  {
+    No_pending = ~0UL,
+  };
+
+  Mword offset(unsigned irq) const { return (irq >> 2) * 0x10; }
+
+  static unsigned shift(int irq)
+  { return (irq % 4) * 8; }
+
+  static Mword bytemask(int irq)
+  { return 0xffUL << shift(irq); }
+
+  Mword status(int irq) const
+  { return read<Mword>(offset(irq) + Status) & bytemask(irq); }
+
+  void mask(Mword i)
+  { write<Mword>(1UL << (i & 31), offset(i / 8) + Enable_clear); }
+
+  void mask_and_ack(Mword i)
+  { Combiner_chip::mask(i); }
+
+  void ack(Mword) {}
+
+  void set_cpu(Mword, Cpu_number) {}
+
+  unsigned set_mode(Mword, unsigned)
+  { return Irq_base::Trigger_level; }
+
+  void unmask(Mword i)
+  { write<Mword>(1UL << (i & 31), offset(i / 8) + Enable_set); }
+
+  void init_irq(int irq) const
+  { write<Mword>(bytemask(irq), offset(irq) + Enable_clear); }
+
+  Unsigned32 pending(unsigned cnr)
+  {
+    unsigned v = status(cnr) >> shift(cnr);
+    for (unsigned i = 0; i < 8; ++i)
+      if (v & (1 << i))
+       return (cnr * 8) + i;
+    // use __builtin_clz...
+
+    return No_pending;
+  }
+
+  int num_combiner_chips() const
+  {
+    if (Platform::is_4210())
+      return Platform::gic_int() ? 54 : 16;
+    if (Platform::is_4412())
+      return 20;
+    if (Platform::is_5250())
+      return 32;
+    assert(0);
+    return 0;
+  }
+
+  Combiner_chip()
+  : Irq_chip_gen(num_combiner_chips() * 8),
+    Mmio_register_block(Kmem::mmio_remap(Mem_layout::Irq_combiner_phys_base))
+  {
+    // 0..39, 51, 53
+    if (Platform::gic_int())
+      {
+        for (int i = 0; i < 40; ++i)
+          init_irq(i);
+        init_irq(51);
+        init_irq(53);
+      }
+    else
+      {
+        const int num = num_combiner_chips();
+        for (int i = 0; i < num; ++i)
+          init_irq(i);
+      }
+  }
+};
+
+// ------------
+
+class Gpio_cascade_wu01_irq : public Irq_base
+{
+public:
+  explicit Gpio_cascade_wu01_irq(Gpio_wakeup_chip *gc, unsigned pin)
+  : _wu_gpio(gc), _pin(pin)
+  { set_hit(&handler_wrapper<Gpio_cascade_wu01_irq>); }
+
+  void switch_mode(unsigned) {}
+
+  void handle(Upstream_irq const *u)
+  {
+    // checking pending reg as a debug thing
+    if (!(_wu_gpio->pending01() & (1 << _pin)))
+      WARN("WU-GPIO not pending %d\n", _pin);
+
+    Upstream_irq ui(this, u);
+    _wu_gpio->irq(_pin)->hit(&ui);
+  }
+
+private:
+  Gpio_wakeup_chip *_wu_gpio;
+  unsigned _pin;
+};
+
+
+class Gpio_cascade_wu23_irq : public Irq_base
+{
+public:
+  explicit Gpio_cascade_wu23_irq(Gpio_wakeup_chip *gc)
+  : _wu_gpio(gc)
+  { set_hit(&handler_wrapper<Gpio_cascade_wu23_irq>); }
+
+  void switch_mode(unsigned) {}
+
+private:
+  Gpio_wakeup_chip *_wu_gpio;
+};
+
+PUBLIC
+void
+Gpio_cascade_wu23_irq::handle(Upstream_irq const *u)
+{
+  unsigned mask = _wu_gpio->pending23();
+  Upstream_irq ui(this, u);
+  for (unsigned p = 0; p < 16; ++p)
+    if ((1 << p) & mask)
+      {
+       _wu_gpio->irq(p + 16)->hit(&ui);
+       break;
+      }
+}
+
+class Gpio_cascade_xab_irq : public Irq_base
+{
+public:
+  explicit Gpio_cascade_xab_irq(Gpio_eint_chip *g)
+  : _eint_gc(g)
+  { set_hit(&handler_wrapper<Gpio_cascade_xab_irq>); }
+
+  void switch_mode(unsigned) {}
+
+private:
+  Gpio_eint_chip *_eint_gc;
+};
+
+PUBLIC
+void
+Gpio_cascade_xab_irq::handle(Upstream_irq const *u)
+{
+  Mword p = _eint_gc->pending();
+  Upstream_irq ui(this, u);
+  _eint_gc->irq(p - 8)->hit(&ui);
+}
+
+// ------------
+class Combiner_cascade_irq : public Irq_base
+{
+public:
+  Combiner_cascade_irq(unsigned nr, Combiner_chip *chld)
+  : _combiner_nr(nr), _child(chld)
+  { set_hit(&handler_wrapper<Combiner_cascade_irq>); }
+
+  void switch_mode(unsigned) {}
+  unsigned irq_nr_base() const { return _combiner_nr * 8; }
+
+private:
+  unsigned _combiner_nr;
+  Combiner_chip *_child;
+};
+
+PUBLIC
+void
+Combiner_cascade_irq::handle(Upstream_irq const *u)
+{
+  Unsigned32 num = _child->pending(_combiner_nr);
+  Upstream_irq ui(this, u);
+
+  if (num != Combiner_chip::No_pending)
+    _child->irq(num)->hit(&ui);
+}
+
+// ------------------------------------------------------------------------
+IMPLEMENTATION [arm && pic_gic && exynos]:
+
+IMPLEMENT inline
+Pic::Status Pic::disable_all_save()
+{ return 0; }
+
+IMPLEMENT inline
+void Pic::restore_all(Status)
+{}
+
+// ------------------------------------------------------------------------
+IMPLEMENTATION [exynos4 && !exynos_extgic]:
+
+class Mgr_int : public Mgr_exynos
+{
+public:
+
+  Irq chip(Mword irqnum) const
+  {
+    Mword origirq = irqnum;
+
+    for (unsigned i = 0; i < _nr_blocks; ++i)
+      {
+        if (irqnum < _block[i].sz)
+          return Irq(_block[i].chip, irqnum);
+
+        irqnum -= _block[i].sz;
+      }
+
+    printf("KERNEL: exynos-irq: Invalid irqnum=%ld\n", origirq);
+    return Irq();
+  }
+
+private:
+  Gic *_gic;
+  Combiner_chip *_cc;
+  Gpio_wakeup_chip *_wu_gc;
+  Gpio_eint_chip *_ei_gc1, *_ei_gc2;
+};
+
+PUBLIC
+Mgr_int::Mgr_int()
+{
+  _gic = Pic::gic.construct(Kmem::mmio_remap(Mem_layout::Gic_cpu_int_phys_base),
+                            Kmem::mmio_remap(Mem_layout::Gic_dist_int_phys_base));
+
+  _cc     = new Boot_object<Combiner_chip>();
+  _wu_gc  = new Boot_object<Gpio_wakeup_chip>(Kmem::Gpio2_phys_base);
+  _ei_gc1 = new Boot_object<Gpio_eint_chip>(Kmem::mmio_remap(Mem_layout::Gpio1_phys_base));
+  _ei_gc2 = new Boot_object<Gpio_eint_chip>(Kmem::mmio_remap(Mem_layout::Gpio2_phys_base));
+
+  // Combiners
+  for (unsigned i = 0; i < 40; ++i)
+    {
+      _gic->alloc(new Boot_object<Combiner_cascade_irq>(i, _cc), i + 32);
+      _gic->unmask(i + 32);
+    }
+  _gic->alloc(new Boot_object<Combiner_cascade_irq>(51, _cc), 51 + 32);
+  _gic->unmask(51 + 32);
+  _gic->alloc(new Boot_object<Combiner_cascade_irq>(53, _cc), 53 + 32);
+  _gic->unmask(53 + 32);
+
+  // GPIO-wakeup0-3 goes to GIC
+  _gic->alloc(new Boot_object<Gpio_cascade_wu01_irq>(_wu_gc, 0), 72); _gic->unmask(72);
+  _gic->alloc(new Boot_object<Gpio_cascade_wu01_irq>(_wu_gc, 1), 73); _gic->unmask(73);
+  _gic->alloc(new Boot_object<Gpio_cascade_wu01_irq>(_wu_gc, 2), 74); _gic->unmask(74);
+  _gic->alloc(new Boot_object<Gpio_cascade_wu01_irq>(_wu_gc, 3), 75); _gic->unmask(75);
+
+  // GPIO-wakeup4-7 -> comb37:0-3
+  for (unsigned i = 0; i < 4; ++i)
+    {
+      _cc->alloc(new Boot_object<Gpio_cascade_wu01_irq>(_wu_gc, 4 + i), 8 * 37 + i);
+      _cc->unmask(8 * 37 + i);
+    }
+
+  // GPIO-wakeup8-15 -> COMB:38:0-7
+  for (unsigned i = 0; i < 8; ++i)
+    {
+      _cc->alloc(new Boot_object<Gpio_cascade_wu01_irq>(_wu_gc, 8 + i), 8 * 38 + i);
+      _cc->unmask(8 * 38 + i);
+    }
+
+  // GPIO-wakeup16-31: COMP:39:0
+  _cc->alloc(new Boot_object<Gpio_cascade_wu23_irq>(_wu_gc), 8 * 39 + 0);
+  _cc->unmask(8 * 39 + 0);
+
+  // xa
+  _cc->alloc(new Boot_object<Gpio_cascade_xab_irq>(_ei_gc1), 8 * 24 + 1);
+  _cc->unmask(8 * 24 + 1);
+
+  // xb
+  _cc->alloc(new Boot_object<Gpio_cascade_xab_irq>(_ei_gc2), 8 * 24 + 0);
+  _cc->unmask(8 * 24 + 0);
+
+  static Chip_block soc[] = {
+    { 96,                _gic },
+    { 54 * 8,            _cc },
+    { 32,                _wu_gc },
+    { 16 * 8,            _ei_gc1 },
+    { (29 - 21 + 1) * 8, _ei_gc2 },
+  };
+
+  _block = soc;
+  _nr_blocks = sizeof(soc) / sizeof(soc[0]);
+
+  calc_nr_irq();
+}
+
+
+PUBLIC
+void
+Mgr_int::set_cpu(Mword irqnum, Cpu_number cpu) const
+{
+  // this handles only the MCT_L[01] timers
+  if (   irqnum == 379  // MCT_L1: Combiner 35:3
+      || irqnum == 504) // MCT_L0: Combiner 51:0
+    _gic->set_cpu(32 + (irqnum - 96) / 8, cpu);
+  else
+    WARNX(Warning, "IRQ%ld: ignoring CPU setting (%d).\n",
+          irqnum, cxx::int_value<Cpu_number>(cpu));
+}
+
+IMPLEMENT static FIASCO_INIT
+void Pic::init()
+{
+  Irq_mgr::mgr = new Boot_object<Mgr_int>();
+}
+
+PUBLIC static
+void Pic::init_ap(Cpu_number)
+{
+  gic->init_ap();
+}
+
+// ------------------------------------------------------------------------
+INTERFACE [exynos4 && exynos_extgic]:
+
+#include "gic.h"
+#include "per_cpu_data.h"
+#include "platform.h"
+
+EXTENSION class Pic
+{
+public:
+  static Per_cpu_ptr<Static_object<Gic> > gic;
+};
+
+// ------------------------------------------------------------------------
+IMPLEMENTATION [exynos4 && exynos_extgic]:
+
+#include "cpu.h"
+
+Per_cpu_ptr<Static_object<Gic> > Pic::gic;
+
+class Mgr_ext : public Mgr_exynos
+{
+public:
+  Irq chip(Mword irqnum) const
+  {
+    Mword origirq = irqnum;
+
+    for (unsigned i = 0; i < _nr_blocks; ++i)
+      {
+        if (irqnum < _block[i].sz)
+          {
+            if (i == 0) // some special handling in GIC block
+              if (!Platform::is_4412())
+                if (irqnum == 80 && Config::Max_num_cpus > 1) // MCT_L1 goes to CPU1
+                  return Irq(_gic.cpu(Cpu_number(1)), irqnum);
+
+            return Irq(_block[i].chip, irqnum);
+          }
+
+        irqnum -= _block[i].sz;
+      }
+
+    printf("KERNEL: exynos-irq: Invalid irqnum=%ld\n", origirq);
+    return Irq();
+  }
+
+private:
+  friend void irq_handler();
+  friend class Pic;
+  static Per_cpu<Static_object<Gic> > _gic;
+  Combiner_chip *_cc;
+  Gpio_wakeup_chip *_wu_gc;
+  Gpio_eint_chip *_ei_gc1, *_ei_gc2;
+  //Gpio_eint_chip *_ei_gc3, *_ei_gc4;
+};
+
+DEFINE_PER_CPU Per_cpu<Static_object<Gic> > Mgr_ext::_gic;
+
+PUBLIC
+Mgr_ext::Mgr_ext()
+{
+  Gic *g = _gic.cpu(Cpu_number(0)).construct(
+      Kmem::mmio_remap(Mem_layout::Gic_cpu_ext_cpu0_phys_base),
+      Kmem::mmio_remap(Mem_layout::Gic_dist_ext_cpu0_phys_base));
+
+  _cc = new Boot_object<Combiner_chip>();
+
+  _wu_gc = new Boot_object<Gpio_wakeup_chip>(Kmem::Gpio2_phys_base);
+  _ei_gc1 = new Boot_object<Gpio_eint_chip>(Kmem::mmio_remap(Mem_layout::Gpio1_phys_base));
+  _ei_gc2 = new Boot_object<Gpio_eint_chip>(Kmem::mmio_remap(Mem_layout::Gpio2_phys_base));
+
+  // Combiners
+  for (unsigned i = 0; i < 16; ++i)
+    {
+      g->alloc(new Boot_object<Combiner_cascade_irq>(i, _cc), i + 32);
+      g->unmask(i + 32);
+    }
+
+  if (Platform::is_4412())
+    {
+      g->alloc(new Boot_object<Combiner_cascade_irq>(16, _cc), 139); g->unmask(139);
+      g->alloc(new Boot_object<Combiner_cascade_irq>(17, _cc), 140); g->unmask(140);
+      g->alloc(new Boot_object<Combiner_cascade_irq>(18, _cc), 80);  g->unmask(80);
+      g->alloc(new Boot_object<Combiner_cascade_irq>(19, _cc), 74);  g->unmask(74);
+    }
+
+  // GPIO-wakeup0-15 goes to GIC
+  for (unsigned i = 0; i < 16; ++i)
+    {
+      g->alloc(new Boot_object<Gpio_cascade_wu01_irq>(_wu_gc, i), i + 48);
+      g->unmask(i + 48);
+    }
+
+  // GPIO-wakeup16-31: GIC:32+32
+  g->alloc(new Boot_object<Gpio_cascade_wu23_irq>(_wu_gc), 64);
+  g->unmask(64);
+
+  // xa GIC:32+47
+  g->alloc(new Boot_object<Gpio_cascade_xab_irq>(_ei_gc1), 79);
+  g->unmask(79);
+
+  // xb GIC:32+46
+  g->alloc(new Boot_object<Gpio_cascade_xab_irq>(_ei_gc2), 78);
+  g->unmask(78);
+
+
+  // 4210
+  //  - part1: ext-int 0x700: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
+  //  - part2: ext-int 0x700: 21, 22, 23, 24, 25, 26, 27, 28, 29
+  //                   0xe00: wu1, wu2, wu3, wu4
+  //  - part3: nix
+
+  static Chip_block soc4210[] = {
+    { 160,               _gic.cpu(Cpu_number(0)) },
+    { 16 * 8,            _cc },
+    { 32,                _wu_gc },
+    { 16 * 8,            _ei_gc1 },
+    { (29 - 21 + 1) * 8, _ei_gc2 },
+  };
+
+  // 4412
+  //  - part1: ext-int 0x700: 1, 2, 3, 4, 5, 6, 7, 13, 14, 15, 16, 21, 22
+  //  - part2: ext-int 0x700: 23, 24, 25, 26, 27, 28, 29, 8, 9, 10, 11, 12
+  //                   0xe00: 40, 41, 42, 43
+  //  - part3: ext-int 0x700: 50
+  //  - part4: ext-int 0x700: 30, 31, 32, 33, 34
+
+  static Chip_block soc4412[] = {
+    { 160,               _gic.cpu(Cpu_number(0)) },
+    { 20 * 8,            _cc },
+    {  4 * 8,            _wu_gc },
+    { 13 * 8,            _ei_gc1 },
+    { 12 * 8,            _ei_gc2 },
+    //{  1 * 8,            _ei_gc3 }, // Do not know upstream IRQ-num :(
+    //{  5 * 8,            _ei_gc4 }, // Do not know upstream IRQ-num :(
+  };
+
+  if (Platform::is_4412())
+    {
+      _block = soc4412;
+      _nr_blocks = sizeof(soc4412) / sizeof(soc4412[0]);
+    }
+  else
+    {
+      _block = soc4210;
+      _nr_blocks = sizeof(soc4210) / sizeof(soc4210[0]);
+    }
+
+  calc_nr_irq();
+}
+
+/**
+ * \pre must run on the CPU given in \a cpu.
+ */
+PUBLIC
+void
+Mgr_ext::set_cpu(Mword irqnum, Cpu_number cpu) const
+{
+  if (!Platform::is_4412() && irqnum == 80)  // MCT_L1
+    _gic.cpu(cpu)->set_cpu(80, cpu);
+  else
+    WARNX(Warning, "IRQ%ld: ignoring CPU setting (%d).\n", irqnum,
+          cxx::int_value<Cpu_number>(cpu));
+}
+
+IMPLEMENT static FIASCO_INIT
+void Pic::init()
+{
+  Mgr_ext *m = new Boot_object<Mgr_ext>();
+  Irq_mgr::mgr = m;
+  gic = &m->_gic;
+}
+
+PUBLIC static
+void
+Pic::reinit(Cpu_number cpu)
+{
+  gic.cpu(cpu)->init(true, 96);
+}
+
+class Check_irq0 : public Irq_base
+{
+public:
+  Check_irq0() { set_hit(&hndl); }
+  static void hndl(Irq_base *, Upstream_irq const *)
+  {
+    printf("IRQ0 appeared on CPU%d\n",
+           cxx::int_value<Cpu_number>(current_cpu()));
+  }
+private:
+  void switch_mode(unsigned) {}
+};
+
+DEFINE_PER_CPU static Per_cpu<Static_object<Check_irq0> > _check_irq0;
+
+
+PUBLIC static
+void Pic::init_ap(Cpu_number cpu)
+{
+  if (Platform::is_4412())
+    {
+      assert(cpu > Cpu_number(0));
+      assert(cpu < Cpu_number(4));
+
+      unsigned phys_cpu = cxx::int_value<Cpu_phys_id>(Cpu::cpus.cpu(cpu).phys_id());
+      gic.cpu(cpu).construct(
+          Kmem::mmio_remap(Mem_layout::Gic_cpu_ext_cpu0_phys_base + phys_cpu * 0x4000),
+          Kmem::mmio_remap(Mem_layout::Gic_dist_ext_cpu0_phys_base + phys_cpu * 0x4000),
+          gic.cpu(Cpu_number(0)));
+    }
+  else
+    {
+      assert (cpu == Cpu_number(1));
+      assert (Cpu::cpus.cpu(cpu).phys_id() == Cpu_phys_id(1));
+
+      gic.cpu(cpu).construct(Kmem::mmio_remap(Mem_layout::Gic_cpu_ext_cpu1_phys_base),
+                             Kmem::mmio_remap(Mem_layout::Gic_dist_ext_cpu1_phys_base),
+                             gic.cpu(Cpu_number(0)));
+    }
+
+  gic.cpu(cpu)->init_ap();
+
+
+  // This is a debug facility as we've been seeing IRQ0
+  // happening under (non-usual) high load
+  _check_irq0.cpu(cpu).construct();
+  gic.cpu(cpu)->alloc(_check_irq0.cpu(cpu), 0);
+}
+
+
+extern "C"
+void irq_handler()
+{ nonull_static_cast<Mgr_ext *>(Irq_mgr::mgr)->_gic.current()->hit(0); }
+
+//-------------------------------------------------------------------
+IMPLEMENTATION [arm && exynos_extgic && arm_em_tz]:
+
+PUBLIC static
+void
+Pic::set_pending_irq(unsigned group32num, Unsigned32 val)
+{
+  gic.current()->set_pending_irq(group32num, val);
+}
+
+// ------------------------------------------------------------------------
+IMPLEMENTATION [exynos5]:
+
+#include "platform.h"
+
+EXTENSION class Pic
+{
+};
+
+class Mgr : public Mgr_exynos
+{
+  Irq chip(Mword irqnum) const
+  {
+    Mword origirq = irqnum;
+
+    for (unsigned i = 0; i < _nr_blocks; ++i)
+      {
+        if (irqnum < _block[i].sz)
+          return Irq(_block[i].chip, irqnum);
+
+        irqnum -= _block[i].sz;
+      }
+
+    printf("KERNEL: exynos-irq: Invalid irqnum=%ld\n", origirq);
+    return Irq();
+  }
+
+private:
+  friend class Pic;
+  Combiner_chip *_cc;
+  Gpio_wakeup_chip *_wu_gc;
+  Gpio_eint_chip *_ei_gc1, *_ei_gc2;
+  Gpio_eint_chip *_ei_gc3, *_ei_gc4;
+};
+
+PUBLIC
+Mgr::Mgr()
+{
+  Gic *g = Pic::gic.construct(Kmem::mmio_remap(Mem_layout::Gic_cpu_phys_base),
+                              Kmem::mmio_remap(Mem_layout::Gic_dist_phys_base));
+
+  _cc = new Boot_object<Combiner_chip>();
+
+  _wu_gc = new Boot_object<Gpio_wakeup_chip>(Kmem::Gpio1_phys_base);
+
+  _ei_gc1 = new Boot_object<Gpio_eint_chip>(Kmem::mmio_remap(Mem_layout::Gpio1_phys_base));
+  _ei_gc2 = new Boot_object<Gpio_eint_chip>(Kmem::mmio_remap(Mem_layout::Gpio2_phys_base));
+  _ei_gc3 = new Boot_object<Gpio_eint_chip>(Kmem::mmio_remap(Mem_layout::Gpio3_phys_base));
+  _ei_gc4 = new Boot_object<Gpio_eint_chip>(Kmem::mmio_remap(Mem_layout::Gpio4_phys_base));
+
+  // Combiners
+  for (unsigned i = 0; i < 32; ++i)
+    {
+      g->alloc(new Boot_object<Combiner_cascade_irq>(i, _cc), i + 32);
+      g->unmask(i + 32);
+    }
+
+  _cc->alloc(new Boot_object<Gpio_cascade_wu01_irq>(_wu_gc, 0), 8 * 23 + 0);
+  _cc->alloc(new Boot_object<Gpio_cascade_wu01_irq>(_wu_gc, 1), 8 * 24 + 0);
+  for (int i = 25, nr = 2; i < 32; ++i, nr += 2)
+    {
+      _cc->alloc(new Boot_object<Gpio_cascade_wu01_irq>(_wu_gc, nr + 0), 8 * i + 0);
+      _cc->alloc(new Boot_object<Gpio_cascade_wu01_irq>(_wu_gc, nr + 1), 8 * i + 1);
+    }
+
+  // GPIO-wakeup16-31: GIC:32+32
+  g->alloc(new Boot_object<Gpio_cascade_wu23_irq>(_wu_gc), 64);
+  g->unmask(64);
+
+  if (0)
+    {
+      // xa GIC:32+47
+      g->alloc(new Boot_object<Gpio_cascade_xab_irq>(_ei_gc1), 79);
+      g->unmask(79);
+
+      // xb GIC:32+46
+      g->alloc(new Boot_object<Gpio_cascade_xab_irq>(_ei_gc2), 78);
+      g->unmask(78);
+    }
+
+  // 5250
+  //  - part1: ext-int 0x700: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 30
+  //                   0xe00: 40, 41, 42, 43
+  //  - part2: ext-int 0x700: 14, 15, 16, 17, 18, 19, 20, 21, 22
+  //  - part3: ext-int 0x700: 60, 61, 62, 63, 64
+  //  - part4: ext-int 0x700: 50
+
+  static Chip_block socblock[] = {
+    { 160,     Pic::gic },
+    { 32 * 8,  _cc },
+    { 32,      _wu_gc },
+    { 13 * 8,  _ei_gc1 },
+    {  8 * 8,  _ei_gc2 },
+    {  5 * 8,  _ei_gc3 },
+    {  1 * 8,  _ei_gc4 },
+  };
+
+  _block = socblock;
+  _nr_blocks = sizeof(socblock) / sizeof(socblock[0]);
+
+  calc_nr_irq();
+}
+
+/**
+ * \pre must run on the CPU given in \a cpu.
+ */
+PUBLIC
+void
+Mgr::set_cpu(Mword irqnum, Cpu_number cpu) const
+{
+  // this handles only the MCT_L[01] timers
+  if (   irqnum == 152   // MCT_L0
+      || irqnum == 153)  // MCT_L1
+    Pic::gic->set_cpu(irqnum, cpu);
+  else
+    WARNX(Warning, "IRQ%ld: ignoring CPU setting (%d).\n",
+         irqnum, cxx::int_value<Cpu_number>(cpu));
+}
+
+IMPLEMENT static FIASCO_INIT
+void Pic::init()
+{
+  Irq_mgr::mgr = new Boot_object<Mgr>();
+}
+
+PUBLIC static
+void
+Pic::reinit(Cpu_number)
+{
+  gic->init(true);
+}
+
+PUBLIC static
+void Pic::init_ap(Cpu_number)
+{
+  gic->init_ap();
+}
+
+//---------------------------------------------------------------------------
+IMPLEMENTATION [debug && exynos]:
+
+PUBLIC
+char const *
+Combiner_chip::chip_type() const
+{ return "Comb"; }
+
+PUBLIC
+char const *
+Gpio_eint_chip::chip_type() const
+{ return "EI-Gpio"; }
+
+PUBLIC
+char const *
+Gpio_wakeup_chip::chip_type() const
+{ return "WU-GPIO"; }
diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos/platform-arm-exynos.cpp b/kernel/fiasco/src/kern/arm/bsp/exynos/platform-arm-exynos.cpp
new file mode 100644 (file)
index 0000000..a8036cf
--- /dev/null
@@ -0,0 +1,180 @@
+INTERFACE[arm && exynos]:
+
+#include "types.h"
+
+class Platform
+{
+public:
+  struct Pkg_id
+  {
+    Mword mask;
+    Mword val;
+    unsigned soc;
+    unsigned uart;
+  };
+
+  enum Soc_type
+  {
+    Soc_unknown = 0,
+    Soc_4210,
+    Soc_4412,
+    Soc_5250,
+  };
+
+  enum Gic_type
+  {
+    Int_gic, Ext_gic,
+  };
+
+  static bool gic_ext() { return gic_type() == Ext_gic; }
+  static bool gic_int() { return gic_type() == Int_gic; }
+
+private:
+  static Soc_type _soc;
+  static unsigned _uart;
+  static unsigned _subrev;
+};
+
+// ------------------------------------------------------------------------
+INTERFACE [arm && exynos && exynos_extgic]:
+
+EXTENSION class Platform
+{
+public:
+  static Gic_type gic_type() { return Ext_gic; }
+};
+
+// ------------------------------------------------------------------------
+INTERFACE [arm && exynos && !exynos_extgic]:
+
+EXTENSION class Platform
+{
+public:
+  static Gic_type gic_type() { return Int_gic; }
+};
+
+// ------------------------------------------------------------------------
+IMPLEMENTATION [arm && exynos]:
+
+#include "io.h"
+#include "mem_layout.h"
+
+// ------------------------------------------------------------------------
+IMPLEMENTATION [arm && exynos && exynos_extgic]:
+
+#include <feature.h>
+KIP_KERNEL_FEATURE("exy:extgic");
+
+// ------------------------------------------------------------------------
+IMPLEMENTATION [arm && exynos]:
+
+#include "kmem.h"
+
+Platform::Soc_type Platform::_soc;
+unsigned Platform::_subrev;
+unsigned Platform::_uart;
+
+PUBLIC static
+unsigned
+Platform::subrev()
+{
+  return _subrev;
+}
+
+//-------------------------------------------------------------------------------------------
+IMPLEMENTATION [arm && exynos && pkg_id_file]:
+
+#include "types.h"
+#include "globalconfig.h"
+
+#include CONFIG_PF_EXYNOS_PKG_IDS
+
+PRIVATE static
+void
+Platform::process_pkg_ids()
+{
+  Mword pkg_id = Io::read<Mword>(Kmem::mmio_remap(Mem_layout::Chip_id_phys_base + 4));
+  for  (unsigned i = 0; i < sizeof(__pkg_ids) / sizeof(__pkg_ids[0]); ++i)
+    if ((pkg_id & __pkg_ids[i].mask) == __pkg_ids[i].val)
+      {
+        _soc = (Soc_type)__pkg_ids[i].soc;
+        _uart = __pkg_ids[i].uart;
+        return;
+      }
+}
+
+//-------------------------------------------------------------------------------------------
+IMPLEMENTATION [arm && exynos && !pkg_id_file]:
+
+#include "types.h"
+#include "globalconfig.h"
+
+PRIVATE static inline
+void
+Platform::process_pkg_ids()
+{}
+
+//-------------------------------------------------------------------------------------------
+IMPLEMENTATION [arm && exynos]:
+
+#include "config.h"
+
+PRIVATE static
+void
+Platform::type()
+{
+  if (_soc == 0)
+    {
+      Mword pro_id = Io::read<Mword>(Kmem::mmio_remap(Mem_layout::Chip_id_phys_base));
+
+      _subrev = pro_id & 0xff;
+
+      // set defaults from config
+      _uart = Config::Uart_nr;
+#if defined(CONFIG_PF_EXYNOS4_4210)
+      _soc = Soc_4210;
+#elif defined(CONFIG_PF_EXYNOS4_4412)
+      _soc = Soc_4412;
+#elif defined(CONFIG_PF_EXYNOS5_5250)
+      _soc = Soc_5250;
+#endif
+
+      process_pkg_ids();
+    }
+}
+
+PUBLIC static inline
+bool
+Platform::is_4210()
+{ type(); return _soc == Soc_4210; }
+
+PUBLIC static inline
+bool
+Platform::is_4412()
+{ type(); return _soc == Soc_4412; }
+
+PUBLIC static inline
+bool
+Platform::is_5250()
+{ type(); return _soc == Soc_5250; }
+
+PUBLIC static unsigned Platform::uart_nr() { type(); return _uart; }
+
+
+// ------------------------------------------------------------------------
+// this is actually a config option...
+IMPLEMENTATION [arm && arm_em_tz]:
+
+PUBLIC static inline
+bool Platform::running_ns() { return false; }
+
+IMPLEMENTATION [arm && arm_em_ns]: // -------------------------------------------
+
+PUBLIC static inline
+bool Platform::running_ns() { return true; }
+
+IMPLEMENTATION [arm && arm_em_std]: // -------------------------------------------
+
+PUBLIC static inline
+bool Platform::running_ns() { return false; }
+
diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos/platform_control-arm-exynos.cpp b/kernel/fiasco/src/kern/arm/bsp/exynos/platform_control-arm-exynos.cpp
new file mode 100644 (file)
index 0000000..2a993bd
--- /dev/null
@@ -0,0 +1,196 @@
+INTERFACE [arm && exynos]:
+
+#include "types.h"
+#include "io.h"
+#include "mem_layout.h"
+#include "mmio_register_block.h"
+
+EXTENSION class Platform_control
+{
+public:
+
+  class Pmu : public Mmio_register_block
+  {
+  public:
+    explicit Pmu(Address virt) : Mmio_register_block(virt) {}
+    enum Reg
+    {
+      Config      = 0,
+      Status      = 4,
+      Option      = 8,
+      Core_offset = 0x80,
+
+      ARM_COMMON_OPTION      = 0x2408,
+   };
+
+    static Mword core_pwr_reg(Cpu_phys_id cpu, unsigned func)
+    { return 0x2000 + Core_offset * cxx::int_value<Cpu_phys_id>(cpu) + func; }
+
+    Mword read(unsigned reg) const
+    { return Mmio_register_block::read<Mword>(reg); }
+
+    void write(Mword val, unsigned reg) const
+    { Mmio_register_block::write(val, reg); }
+
+    Mword core_read(Cpu_phys_id cpu, unsigned reg) const
+    { return Mmio_register_block::read<Mword>(core_pwr_reg(cpu, reg)); }
+
+    void core_write(Mword val, Cpu_phys_id cpu, unsigned reg) const
+    { Mmio_register_block::write(val, core_pwr_reg(cpu, reg)); }
+  };
+
+  enum Power_down_mode
+  {
+    Aftr, Lpa, Dstop, Sleep,
+
+    Pwr_down_mode = Aftr,
+  };
+
+  enum Pmu_regs
+  {
+    Pmu_core_local_power_enable = 3,
+  };
+
+  static Static_object<Pmu> pmu;
+};
+
+
+//--------------------------------------------------------------------------
+IMPLEMENTATION [arm && exynos && !mp]:
+
+PRIVATE static
+int
+Platform_control::power_up_core(Cpu_phys_id)
+{
+  return -L4_err::ENodev;
+}
+
+//--------------------------------------------------------------------------
+IMPLEMENTATION [arm && exynos]:
+
+Static_object<Platform_control::Pmu> Platform_control::pmu;
+
+IMPLEMENT
+void
+Platform_control::init(Cpu_number cpu)
+{
+  if (cpu == Cpu_number::boot_cpu())
+    {
+      assert (!pmu->get_mmio_base());
+      pmu.construct(Kmem::mmio_remap(Mem_layout::Pmu_phys_base));
+
+      for (Cpu_phys_id i = Cpu_phys_id(0);
+           i < Cpu_phys_id(2);
+           ++i)
+        pmu->core_write((pmu->core_read(i, Pmu::Option) & ~(1 << 0)) | (1 << 1), i, Pmu::Option);
+
+      pmu->write(2, Pmu::ARM_COMMON_OPTION);
+    }
+}
+
+//--------------------------------------------------------------------------
+IMPLEMENTATION [arm && exynos && mp]:
+
+#include "ipi.h"
+#include "outer_cache.h"
+#include "platform.h"
+#include "poll_timeout_kclock.h"
+#include "smc.h"
+
+PRIVATE static
+int
+Platform_control::power_up_core(Cpu_phys_id cpu)
+{
+  // CPU already powered up?
+  if ((pmu->core_read(cpu, Pmu::Status) & Pmu_core_local_power_enable) != 0)
+    return 0;
+
+  pmu->core_write(Pmu_core_local_power_enable, cpu, Pmu::Config);
+
+  Lock_guard<Cpu_lock, Lock_guard_inverse_policy> cpu_lock_guard(&cpu_lock);
+
+  Poll_timeout_kclock pt(10000);
+  while (pt.test((pmu->core_read(cpu, Pmu::Status)
+                  & Pmu_core_local_power_enable)
+                 != Pmu_core_local_power_enable))
+      ;
+
+  return pt.timed_out() ? -L4_err::ENodev : 0;
+}
+
+PRIVATE static
+void
+Platform_control::set_one_vector(Mword addr_p, Mword vector)
+{
+  Mword addr_v = Kmem::mmio_remap(addr_p);
+  Io::write<Mword>(vector, addr_v);
+  Mem_unit::flush_dcache((void *)addr_v, (void *)(addr_v + sizeof(void *)));
+  Outer_cache::flush(addr_p);
+}
+
+PUBLIC static
+void
+Platform_control::setup_cpu_start_vector(Cpu_phys_id cpu, Mword phys_reset_vector)
+{
+  if ((Platform::is_4210() && Platform::subrev() == 0)
+      || Platform::is_4412())
+    {
+      printf("AP bootup sysram\n");
+
+      unsigned o = 0;
+      if (Platform::is_4412())
+        o = (Platform::running_ns() ? 0x2f01c : 0)
+            + cxx::int_value<Cpu_phys_id>(cpu) * 4;
+
+      set_one_vector(Mem_layout::Sysram_phys_base + o,
+                     phys_reset_vector);
+    }
+  else if (Platform::is_5250())
+    {
+      unsigned o = Platform::running_ns() ? 0x2f01c : 0;
+      set_one_vector(Mem_layout::Sysram_phys_base + o,
+                     phys_reset_vector);
+    }
+  else
+    {
+      printf("AP bootup inform\n");
+      set_one_vector(Mem_layout::Pmu_phys_base + 0x814,
+                     phys_reset_vector);
+    }
+}
+
+
+PUBLIC static
+void
+Platform_control::boot_ap_cpus(Address phys_reset_vector)
+{
+  assert(current_cpu() == Cpu_number::boot_cpu());
+
+  if (Platform::is_4412())
+    {
+      for (Cpu_phys_id i = Cpu_phys_id(1);
+           i < Cpu_phys_id(4) && i < Cpu_phys_id(Config::Max_num_cpus);
+           ++i)
+        {
+          setup_cpu_start_vector(i, phys_reset_vector);
+          power_up_core(i);
+          if (Platform::running_ns())
+            Exynos_smc::cpuboot(phys_reset_vector,
+                                cxx::int_value<Cpu_phys_id>(i));
+          Ipi::send(Ipi::Global_request, Cpu_number::boot_cpu(), i);
+        }
+
+      return;
+    }
+
+  Mem_unit::flush_dcache();
+
+  Cpu_phys_id const second = Cpu_phys_id(1);
+  setup_cpu_start_vector(second, phys_reset_vector);
+  power_up_core(second);
+
+  if (Platform::is_5250() && Platform::running_ns())
+    Exynos_smc::cpuboot(phys_reset_vector, 1);
+
+  Ipi::send(Ipi::Global_request, Cpu_number::boot_cpu(), second);
+}
diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos/reset-arm-exynos.cpp b/kernel/fiasco/src/kern/arm/bsp/exynos/reset-arm-exynos.cpp
new file mode 100644 (file)
index 0000000..8ddb46e
--- /dev/null
@@ -0,0 +1,14 @@
+IMPLEMENTATION [arm && exynos]:
+
+#include "io.h"
+#include "kmem.h"
+
+void __attribute__ ((noreturn))
+platform_reset(void)
+{
+  Io::write<Mword>(1, Kmem::mmio_remap(Mem_layout::Pmu_phys_base + 0x400));
+
+  // we should reboot now
+  while (1)
+    ;
+}
diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos/scu-arm-exynos.cpp b/kernel/fiasco/src/kern/arm/bsp/exynos/scu-arm-exynos.cpp
new file mode 100644 (file)
index 0000000..27c7d76
--- /dev/null
@@ -0,0 +1,24 @@
+INTERFACE [arm && bsp_cpu && (exynos4 || !arm_em_ns)]:
+
+EXTENSION class Scu
+{
+public:
+  enum
+  {
+    Available   = 1,
+    Bsp_enable_bits = Control_scu_standby,
+  };
+};
+
+// ------------------------------------------------------------------------
+INTERFACE [arm && bsp_cpu && (exynos5 && arm_em_ns)]:
+
+EXTENSION class Scu
+{
+public:
+  enum
+  {
+    Available = 0,
+    Bsp_enable_bits = 0,
+  };
+};
diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos/smc.cpp b/kernel/fiasco/src/kern/arm/bsp/exynos/smc.cpp
new file mode 100644 (file)
index 0000000..6c0b8a6
--- /dev/null
@@ -0,0 +1,90 @@
+INTERFACE [exynos]:
+
+#include "l4_types.h"
+
+class Exynos_smc
+{
+public:
+  static void cpuboot(Mword, unsigned);
+  static void l2cache_setup(unsigned, unsigned, unsigned, Mword, Mword, Mword);
+};
+
+// ------------------------------------------------------------------------
+INTERFACE [exynos && arm_em_ns && arm_smif_mc]:
+
+#include "types.h"
+
+EXTENSION class Exynos_smc
+{
+private:
+  enum Command : Smword
+  {
+    Init       = -1,
+    Info       = -2,
+    Sleep      = -3,
+    Cpu1boot   = -4,
+    Cpu0aftr   = -5,
+    C15resume  = -11,
+    L2x0ctrl   = -21,
+    L2x0setup1 = -22,
+    L2x0setup2 = -23,
+    L2x0invall = -24,
+    L2x0debug  = -25,
+    Reg        = -101,
+  };
+
+  static int call(Command cmd, Mword a1 = 0, Mword a2 = 0, Mword a3 = 0)
+  {
+    register Mword _cmd asm("r0") = cmd;
+    register Mword _a1  asm("r1") = a1;
+    register Mword _a2  asm("r2") = a2;
+    register Mword _a3  asm("r3") = a3;
+
+    asm volatile("dmb   \t\n" // Errata 766421
+                 "smc 0 \t\n"
+                 "dmb   \t\n" // Errata 766421
+                 : "=r" (_cmd)
+                 : "r" (_cmd), "r" (_a1), "r" (_a2), "r" (_a3)
+                 : "memory", "cc");
+    return _cmd;
+  }
+};
+
+// ------------------------------------------------------------------------
+IMPLEMENTATION [exynos && arm_em_ns && arm_smif_mc]:
+
+#include "mem_space.h"
+#include "mem_unit.h"
+#include <cstdio>
+
+IMPLEMENT
+void
+Exynos_smc::cpuboot(Mword phys_start, unsigned cpu)
+{
+  call(Cpu1boot, cpu);
+}
+
+IMPLEMENT
+void
+Exynos_smc::l2cache_setup(unsigned tag_lat, unsigned data_lat,
+                          unsigned prefctrl, Mword setup2val,
+                          Mword aux_val, Mword aux_mask)
+{
+  call(L2x0setup1, tag_lat, data_lat, prefctrl);
+  call(L2x0setup2, setup2val, aux_val, aux_mask);
+  call(L2x0invall);
+  call(L2x0ctrl, 1);
+}
+
+// ------------------------------------------------------------------------
+IMPLEMENTATION [exynos && !arm_em_ns]:
+
+IMPLEMENT inline
+void
+Exynos_smc::cpuboot(Mword, unsigned)
+{}
+
+IMPLEMENT inline
+void
+Exynos_smc::l2cache_setup(unsigned, unsigned, unsigned, Mword, Mword, Mword)
+{}
diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos/thread-arm-exynos.cpp b/kernel/fiasco/src/kern/arm/bsp/exynos/thread-arm-exynos.cpp
new file mode 100644 (file)
index 0000000..0c1d060
--- /dev/null
@@ -0,0 +1,38 @@
+//-----------------------------------------------------------------------------
+IMPLEMENTATION [!mp && irregular_gic]:
+
+PUBLIC static inline
+void
+Thread::init_arm_ipis(Cpu_number)
+{}
+
+//-----------------------------------------------------------------------------
+IMPLEMENTATION [mp && irregular_gic]:
+
+#include "pic.h"
+
+class Arm_ipis
+{
+public:
+  Arm_ipis(Cpu_number cpu)
+  {
+    check(Pic::gic.cpu(cpu)->alloc(&remote_rq_ipi, Ipi::Request));
+    check(Pic::gic.cpu(cpu)->alloc(&glbl_remote_rq_ipi, Ipi::Global_request));
+    check(Pic::gic.cpu(cpu)->alloc(&debug_ipi, Ipi::Debug));
+    check(Pic::gic.cpu(cpu)->alloc(&timer_ipi, Ipi::Timer));
+  }
+
+  Thread_remote_rq_irq remote_rq_ipi;
+  Thread_glbl_remote_rq_irq glbl_remote_rq_ipi;
+  Thread_debug_ipi debug_ipi;
+  Thread_timer_tick_ipi timer_ipi;
+};
+
+DEFINE_PER_CPU static Per_cpu<Static_object<Arm_ipis> > _arm_ipis;
+
+IMPLEMENT
+void
+Thread::init_per_cpu(Cpu_number cpu)
+{
+  _arm_ipis.cpu(cpu).construct(cpu);
+}
diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos/timer-arm-exynos.cpp b/kernel/fiasco/src/kern/arm/bsp/exynos/timer-arm-exynos.cpp
new file mode 100644 (file)
index 0000000..4c6307f
--- /dev/null
@@ -0,0 +1,145 @@
+IMPLEMENTATION [arm && mptimer && exynos]: // -----------------------------
+
+#include "config.h"
+#include "timer_mct.h"
+#include "mem_layout.h"
+
+#include <cstdio>
+
+PRIVATE static
+Mword
+Timer::interval()
+{
+  Mct_timer mct(Kmem::mmio_remap(Mem_layout::Mct_phys_base));
+  // probably need to select proper clock source for MCT
+  Mword timer_start = 0UL;
+  unsigned factor = 5;
+  Mword sp_c = timer_start
+               + Mct_core_timer::Mct_freq / (1000000 / Config::Scheduler_granularity)
+                * (1 << factor);
+
+  mct.write<Mword>(0, Mct_timer::Reg::Cfg);
+  mct.write<Mword>(1 << 8, Mct_timer::Reg::Tcon);
+
+  mct.write<Mword>(0, Mct_timer::Reg::Cnt_u);
+  mct.write<Mword>(timer_start, Mct_timer::Reg::Cnt_l);
+  Mword vc = start_as_counter();
+  while (sp_c > mct.read<Mword>(Mct_timer::Reg::Cnt_l))
+    ;
+  Mword interval = (vc - stop_counter()) >> factor;
+
+  mct.write<Mword>(0, Mct_timer::Reg::Tcon);
+
+  if (0)
+    printf("MP-Timer-Interval: %ld\n", interval);
+
+  return interval;
+}
+
+INTERFACE [arm && exynos_mct]: // -----------------------------------------
+
+#include "types.h"
+#include "per_cpu_data.h"
+#include "timer_mct.h"
+
+EXTENSION class Timer : public Mct_core_timer
+{
+public:
+  explicit Timer(Address virt) : Mct_core_timer(virt) {}
+  static Static_object<Mct_timer> mct;
+  static Per_cpu<Static_object<Timer> > timers;
+};
+
+IMPLEMENTATION [arm && exynos_mct]: // ------------------------------------
+
+#include "cpu.h"
+#include "io.h"
+#include <cstdio>
+
+Static_object<Mct_timer> Timer::mct;
+DEFINE_PER_CPU Per_cpu<Static_object<Timer> > Timer::timers;
+
+PUBLIC static
+void
+Timer::configure(Cpu_number cpu)
+{
+  timers.cpu(cpu)->Mct_core_timer::configure();
+}
+
+IMPLEMENT
+void
+Timer::init(Cpu_number cpu)
+{
+  if (cpu == Cpu_number::boot_cpu())
+    {
+      mct.construct(Kmem::mmio_remap(Mem_layout::Mct_phys_base));
+      mct->write<Mword>(0, Mct_timer::Reg::Cfg);
+    }
+  timers.cpu(cpu).construct(Kmem::mmio_remap(Mem_layout::Mct_phys_base + 0x300
+                            + cxx::int_value<Cpu_phys_id>(Cpu::cpus.cpu(cpu).phys_id()) * 0x100));
+  timers.cpu(cpu)->Mct_core_timer::configure();
+}
+
+static inline
+Unsigned64
+Timer::timer_to_us(Unsigned32 /*cr*/)
+{ return 0; }
+
+static inline
+Unsigned64
+Timer::us_to_timer(Unsigned64 us)
+{ (void)us; return 0; }
+
+PRIVATE static
+unsigned
+Timer::us_to_mct(Unsigned64 d_us)
+{
+  if (d_us > Maxinterval_us)
+    return Maxinterval_mct;
+
+  return d_us * (Mct_freq / 1000000);
+}
+
+PUBLIC static
+void
+Timer::periodic_next_event(Cpu_number cpu, Unsigned64 next_wakeup)
+{
+  assert(next_wakeup >= Kip::k()->clock);
+
+  Unsigned64 d = next_wakeup - Kip::k()->clock;
+
+  d = (d / Config::Scheduler_granularity) * Config::Scheduler_granularity;
+
+  timers.cpu(cpu)->set_interval(us_to_mct(d));
+}
+
+PUBLIC static
+void
+Timer::periodic_default_freq(Cpu_number cpu)
+{
+  timers.cpu(cpu)->set_interval(Interval);
+}
+
+IMPLEMENT inline
+void
+Timer::update_one_shot(Unsigned64 wakeup)
+{
+  Unsigned64 now = Kip::k()->clock;
+  Mword interval_mct;
+  if (EXPECT_FALSE(wakeup <= now))
+    interval_mct = 1;
+  else
+    interval_mct = us_to_mct(wakeup - now);
+
+  timers.cpu(current_cpu())->set_interval(interval_mct);
+}
+
+IMPLEMENT inline NEEDS["config.h", "kip.h"]
+Unsigned64
+Timer::system_clock()
+{
+  if (Config::Scheduler_one_shot)
+    return 0;
+  else
+    return Kip::k()->clock;
+}
diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos/timer_mct.cpp b/kernel/fiasco/src/kern/arm/bsp/exynos/timer_mct.cpp
new file mode 100644 (file)
index 0000000..8a0d91d
--- /dev/null
@@ -0,0 +1,95 @@
+INTERFACE [arm && exynos]: // ------------------
+
+#include "mmio_register_block.h"
+#include "config.h"
+#include "types.h"
+
+class Mct_timer : public Mmio_register_block
+{
+public:
+  explicit Mct_timer(Address virt) : Mmio_register_block(virt) {}
+
+  struct Reg { enum
+  {
+    Cfg   = 0x0,
+    Cnt_l = 0x100,
+    Cnt_u = 0x104,
+    Tcon  = 0x240,
+  }; };
+};
+
+class Mct_core_timer : public Mmio_register_block
+{
+public:
+  explicit Mct_core_timer(Address virt) : Mmio_register_block(virt) {}
+  struct Reg { enum
+  {
+    L0          = 0x300,
+    L1          = 0x400,
+
+    L_TCNTB     = 0x00,
+    L_TCNTO     = 0x04,
+    L_ICNTB     = 0x08,
+    L_ICNTO     = 0x0c,
+    L_FRCNTB    = 0x10,
+    L_FRCNTO    = 0x14,
+    L_TCON      = 0x20,
+    L_INT_CSTAT = 0x30,
+    L_INT_ENB   = 0x34,
+    L_WSTAT     = 0x40,
+  }; };
+
+  enum
+  {
+    Mct_freq = 24000000,
+    Interval = Mct_freq / (1000000 / Config::Scheduler_granularity) / 2,
+    Maxinterval_mct = (1U << 31) - 1,
+    Maxinterval_us  = Maxinterval_mct / (Mct_freq / 1000000),
+  };
+
+};
+
+
+IMPLEMENTATION [arm && exynos]: // ------------------
+
+PRIVATE inline
+void
+Mct_core_timer::wstat_poll(unsigned val)
+{
+  while ((read<Mword>(Reg::L_WSTAT) & val) == 0)
+    ;
+  write<Mword>(val, Reg::L_WSTAT);
+}
+
+PUBLIC inline NEEDS[Mct_core_timer::wstat_poll]
+void
+Mct_core_timer::set_interval(Mword interval)
+{
+  write<Mword>((1 << 31) | interval, Reg::L_ICNTB);
+  wstat_poll(2);
+}
+
+PUBLIC
+void
+Mct_core_timer::configure()
+{
+  write<Mword>(1, Reg::L_TCNTB);
+  wstat_poll(1);
+  set_interval(Interval);
+
+  // run timer
+  write<Mword>(1, Reg::L_TCON);
+  wstat_poll(8);
+
+  // enable interrupt
+  write<Mword>(1, Reg::L_INT_ENB);
+  write<Mword>(7, Reg::L_TCON);
+  wstat_poll(8);
+}
+
+PUBLIC inline
+void
+Mct_core_timer::acknowledge() const
+{
+  write<Mword>(1, Reg::L_INT_CSTAT);
+}
diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos/timer_tick-exynos-mct.cpp b/kernel/fiasco/src/kern/arm/bsp/exynos/timer_tick-exynos-mct.cpp
new file mode 100644 (file)
index 0000000..b9b46b4
--- /dev/null
@@ -0,0 +1,119 @@
+INTERFACE [arm && exynos_mct]: // -----------------------------------------
+
+#include "types.h"
+#include "timer.h"
+
+EXTENSION class Timer_tick
+{
+private:
+  Timer *_timer;
+
+public:
+  static Per_cpu<Static_object<Timer_tick> > _timer_ticks;
+};
+
+IMPLEMENTATION [arm && exynos_mct]: // ------------------------------------
+
+#include "pic.h"
+#include "platform.h"
+
+DEFINE_PER_CPU Per_cpu<Static_object<Timer_tick> > Timer_tick::_timer_ticks;
+
+IMPLEMENTATION [arm && exynos_mct && exynos_extgic]: // -------------------
+
+PRIVATE static
+bool
+Timer_tick::alloc_irq_4412_timer_tick(Cpu_number cpu, unsigned irq)
+{
+  return Pic::gic.cpu(cpu)->alloc(_timer_ticks.cpu(cpu), irq);
+}
+
+IMPLEMENTATION [arm && exynos_mct && !exynos_extgic]: // ------------------
+
+PRIVATE static
+bool
+Timer_tick::alloc_irq_4412_timer_tick(Cpu_number cpu, unsigned irq)
+{
+  (void)cpu;
+  return allocate_irq(_timer_ticks.cpu(Cpu_number::boot_cpu()), irq);
+}
+
+IMPLEMENTATION [arm && arm_generic_timer]: // -----------------------------
+
+IMPLEMENT void Timer_tick::setup(Cpu_number cpu) {}
+IMPLEMENT void Timer_tick::enable(Cpu_number cpu) {}
+IMPLEMENT void Timer_tick::disable(Cpu_number cpu) {}
+PUBLIC inline void Timer_tick::ack() {}
+
+
+IMPLEMENTATION [arm && exynos_mct]: // ------------------------------------
+
+IMPLEMENT
+void
+Timer_tick::setup(Cpu_number cpu)
+{
+  int irq;
+  bool r;
+  unsigned pcpu = cxx::int_value<Cpu_phys_id>(Cpu::cpus.cpu(cpu).phys_id());
+
+  _timer_ticks.cpu(cpu).construct(cpu == Cpu_number::boot_cpu()
+                                  ? Sys_cpu : App_cpu);
+
+  if (Platform::is_5250())
+    {
+      assert(cpu < Cpu_number(2));
+      irq = 152 + pcpu;
+      r = allocate_irq(_timer_ticks.cpu(cpu), irq);
+    }
+  else if (Platform::is_4412())
+    {
+      assert(cpu < Cpu_number(4));
+      irq = 28;
+      r = alloc_irq_4412_timer_tick(cpu, irq);
+    }
+  else
+    {
+      assert(cpu < Cpu_number(2));
+
+      if (Platform::gic_int())
+        irq = pcpu == 0 ? 96 + 51 * 8 + 0 : 96 + 35 * 8 + 3;
+      else
+        irq = pcpu == 0 ? 74 : 80;
+
+      r = allocate_irq(_timer_ticks.cpu(cpu), irq);
+    }
+
+  if (!r)
+    panic("Could not allocate scheduling IRQ %d for CPU%d\n", irq, cxx::int_value<Cpu_number>(cpu));
+  else
+    printf("Timer for CPU%d is at IRQ %d\n", cxx::int_value<Cpu_number>(cpu), irq);
+
+  if (!Platform::is_4412())
+    Irq_mgr::mgr->set_cpu(irq, cpu);
+
+  _timer_ticks.cpu(cpu)->_timer = Timer::timers.cpu(cpu).get();
+}
+
+IMPLEMENT
+void
+Timer_tick::enable(Cpu_number cpu)
+{
+  Timer_tick &t = *_timer_ticks.cpu(cpu).get();
+  t.chip()->unmask(t.pin());
+}
+
+IMPLEMENT
+void
+Timer_tick::disable(Cpu_number cpu)
+{
+  Timer_tick &t = *_timer_ticks.cpu(cpu).get();
+  t.chip()->mask(t.pin());
+}
+
+PUBLIC inline
+void
+Timer_tick::ack()
+{
+  _timer->acknowledge();
+  Irq_base::ack();
+}
diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos/uart-arm-exynos.cpp b/kernel/fiasco/src/kern/arm/bsp/exynos/uart-arm-exynos.cpp
new file mode 100644 (file)
index 0000000..9203edd
--- /dev/null
@@ -0,0 +1,25 @@
+IMPLEMENTATION:
+
+#include "uart_s3c2410.h"
+#include "kmem.h"
+#include "mem_layout.h"
+#include "platform.h"
+
+IMPLEMENT_DEFAULT Address Uart::base() const
+{ return Mem_layout::Uart_phys_base + Platform::uart_nr() * 0x10000; }
+
+IMPLEMENT_DEFAULT int Uart::irq() const
+{
+  if (Platform::is_5250())
+    return 51 + 32 + Platform::uart_nr();
+  if (Platform::gic_ext())
+    return 52 + 32 + Platform::uart_nr();
+  return 96 + 8 * 26 + Platform::uart_nr();
+}
+
+IMPLEMENT_DEFAULT L4::Uart *Uart::uart()
+{
+  static L4::Uart_s5pv210 uart;
+  return &uart;
+}
+
diff --git a/kernel/fiasco/src/kern/arm/bsp/exynos/watchdog-arm-exynos.cpp b/kernel/fiasco/src/kern/arm/bsp/exynos/watchdog-arm-exynos.cpp
new file mode 100644 (file)
index 0000000..dcce070
--- /dev/null
@@ -0,0 +1,84 @@
+INTERFACE [watchdog]:
+
+#include "initcalls.h"
+#include "mmio_register_block.h"
+#include "kmem.h"
+#include "l4_types.h"
+
+class Watchdog : private Mmio_register_block
+{
+private:
+  enum {
+    WTCON = 0x0,
+    WTDAT = 0x4,
+    WTCNT = 0x8,
+
+    WTCON_RST_EN    = 1 << 0,
+    WTCON_EN        = 1 << 5,
+    WTCON_PRESCALER = (0x10 << 8),
+
+    Reset_timeout_val = 299999 * 1000,
+  };
+
+  static Static_object<Watchdog> wdog;
+
+public:
+  Watchdog(Address virt) : Mmio_register_block(virt) {}
+};
+
+IMPLEMENTATION [watchdog]:
+
+#include "io.h"
+#include "static_init.h"
+
+#include <cstdio>
+
+Static_object<Watchdog> Watchdog::wdog;
+
+PUBLIC static
+void
+Watchdog::enable()
+{
+  wdog->write(wdog->read<Mword>(WTCON) | WTCON_EN, WTCON);
+}
+
+PUBLIC static
+void
+Watchdog::disable()
+{
+  wdog->write(wdog->read<Mword>(WTCON) & ~WTCON_EN, WTCON);
+}
+
+PUBLIC static
+void
+Watchdog::touch()
+{
+  wdog->write<Mword>(Reset_timeout_val, WTCNT);
+}
+
+PUBLIC static
+void
+Watchdog::setup(Mword val)
+{
+  wdog->write<Mword>(0, WTCON); // disable
+  wdog->write<Mword>(val, WTDAT); // set initial values
+  wdog->write<Mword>(val, WTCNT);
+
+  wdog->write<Mword>(WTCON_RST_EN | WTCON_PRESCALER, WTCON);
+}
+
+PUBLIC static FIASCO_INIT
+void
+Watchdog::init()
+{
+  wdog.construct(Kmem::mmio_remap(Mem_layout::Watchdog_phys_base));
+  if (1)
+    {
+      wdog->setup(Reset_timeout_val);
+      printf("Watchdog initialized\n");
+    }
+  else
+    printf("Watchdog NOT running\n");
+}
+
+STATIC_INITIALIZE_P(Watchdog, WATCHDOG_INIT);
index 5321e62bd60d89b322c61b7138da94e3d526a1c5..92d6f77b5c60705d855954cca750478fdcfc27de 100644 (file)
@@ -10,10 +10,14 @@ PREPROCESS_PARTS    += $(if $(CONFIG_PF_IMX_51),imx51 imx_epit \
 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)
+RAM_PHYS_BASE           := $(CONFIG_PF_IMX_RAM_PHYS_BASE)
 
 INTERFACES_KERNEL     += $(if $(CONFIG_PF_IMX_51),gic)
 INTERFACES_KERNEL     += $(if $(CONFIG_PF_IMX_6),gic)
+INTERFACES_KERNEL-$(CONFIG_PF_IMX_35) += timer_imx_epit
+INTERFACES_KERNEL-$(CONFIG_PF_IMX_51) += timer_imx_epit
+INTERFACES_KERNEL-$(CONFIG_PF_IMX_53) += timer_imx_epit
+
 MPCORE_PHYS_BASE      := 0x00a00000
 
 uart_IMPL             += uart-imx
index 9c376503492afdf77cdb8b3a207e9af1be8c48b1..5bd2e92ac97d4f68914094831b140ea5a50f7c2d 100644 (file)
@@ -1,16 +1,6 @@
 //-----------------------------------------------------------------------------
 INTERFACE [arm && imx]:
-
-enum {
-  Cache_flush_area = 0xe0000000,
-};
-
-//-----------------------------------------------------------------------------
-IMPLEMENTATION [arm && imx]:
-void
-map_hw(void *pd)
-{
-  map_dev<Mem_layout::Devices1_phys_base>(pd, 1);
-  map_dev<Mem_layout::Devices2_phys_base>(pd, 2);
-  map_dev<Mem_layout::Devices3_phys_base>(pd, 3);
+namespace Bootstrap {
+enum { Cache_flush_area = 0xe0000000 };
 }
+
index 1b849b7ec17e2b1c8954c7060b2a4f05103f2328..240a682de4bc15fa0fb37d7b7a552e129b40afd8 100644 (file)
@@ -3,8 +3,7 @@ INTERFACE [arm && imx]: //----------------------------------------------
 EXTENSION class Mem_layout
 {
 public:
-  enum Phys_layout : Address {
-    Sdram_phys_base      = CONFIG_PF_IMX_RAM_PHYS_BASE,
+  enum Phys_layout_imx : Address {
     Flush_area_phys_base = 0xe0000000,
   };
 };
@@ -14,19 +13,12 @@ INTERFACE [arm && imx && imx21]: // ---------------------------------------
 EXTENSION class Mem_layout
 {
 public:
-  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 : Address {
-    Devices1_phys_base   = 0x10000000,
-    Devices2_phys_base   = Invalid_address,
-    Devices3_phys_base   = Invalid_address,
+    Uart_phys_base        = 0x1000a000,
+    Timer_phys_base       = 0x10003000,
+    Pll_phys_base         = 0x10027000,
+    Watchdog_phys_base    = 0x10002000,
+    Pic_phys_base         = 0x10040000,
   };
 };
 
@@ -35,18 +27,11 @@ INTERFACE [arm && imx && imx35]: // ---------------------------------------
 EXTENSION class Mem_layout
 {
 public:
-  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 : Address {
-    Devices1_phys_base   = 0x43f00000,
-    Devices2_phys_base   = 0x53f00000,
-    Devices3_phys_base   = 0x68000000,
+    Uart_phys_base        = 0x43f90000, // uart1
+    Timer_phys_base       = 0x53f94000, // epit1
+    Watchdog_phys_base    = 0x53fdc000, // wdog
+    Pic_phys_base         = 0x68000000,
   };
 };
 
@@ -56,19 +41,12 @@ INTERFACE [arm && imx && imx51]: // ---------------------------------------
 EXTENSION class Mem_layout
 {
 public:
-  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 : Address {
-    Devices1_phys_base   = 0x73f00000,
-    Devices2_phys_base   = 0xe0000000,
-    Devices3_phys_base   = Invalid_address,
+    Timer_phys_base       = 0x73fac000, // epit1
+    Uart_phys_base        = 0x73fbc000, // uart1
+    Watchdog_phys_base    = 0x73f98000, // wdog1
+    Gic_dist_phys_base    = 0xe0000000,
+    Gic_cpu_phys_base     = 0xe0000000, // this is a fake address and not used
   };
 };
 
@@ -77,19 +55,12 @@ 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,
+    Timer_phys_base       = 0x53fac000, // epit1
+    Uart_phys_base        = 0x53fbc000, // uart1
+    Watchdog_phys_base    = 0x53f98000, // wdog1
+    Gic_dist_phys_base    = 0x0fffc000,
+    Gic_cpu_phys_base     = 0x0fffc000, // this is a fake address and not used
   };
 };
 
@@ -98,23 +69,17 @@ 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,
+    Mp_scu_phys_base     = 0x00a00000,
+    Gic_cpu_phys_base    = 0x00a00100,
+    Gic_dist_phys_base   = 0x00a01000,
+    L2cxx0_phys_base     = 0x00a02000,
+
+    Uart1_phys_base      = 0x02020000, // uart1
+    Watchdog_phys_base   = 0x020bc000, // wdog1
+    Gpt_phys_base        = 0x02098000,
+    Src_phys_base        = 0x020d8000,
+    Uart2_phys_base      = 0x021e8000, // uart2
+    Uart_phys_base       = Uart2_phys_base,
   };
 };
index b71b04dc2f7cbee6ffbc7a7afd7fee1014a908ca..d7341cdbf7036b2be3ddfee4d3309b0c210536b2 100644 (file)
@@ -8,35 +8,6 @@ class Irq_base;
 EXTENSION class Pic
 {
 public:
-  enum
-  {
-    INTCTL      = Kmem::Pic_map_base + 0x00,
-    NIMASK      = Kmem::Pic_map_base + 0x04,
-    INTENNUM    = Kmem::Pic_map_base + 0x08,
-    INTDISNUM   = Kmem::Pic_map_base + 0x0c,
-    INTENABLEH  = Kmem::Pic_map_base + 0x10,
-    INTENABLEL  = Kmem::Pic_map_base + 0x14,
-    INTTYPEH    = Kmem::Pic_map_base + 0x18,
-    INTTYPEL    = Kmem::Pic_map_base + 0x1c,
-    NIPRIORITY7 = Kmem::Pic_map_base + 0x20,
-    NIPRIORITY0 = Kmem::Pic_map_base + 0x3c,
-    NIVECSR     = Kmem::Pic_map_base + 0x40,
-    FIVECSR     = Kmem::Pic_map_base + 0x44,
-    INTSRCH     = Kmem::Pic_map_base + 0x48,
-    INTSRCL     = Kmem::Pic_map_base + 0x4c,
-    INTFRCH     = Kmem::Pic_map_base + 0x50,
-    INTFRCL     = Kmem::Pic_map_base + 0x54,
-    NIPNDH      = Kmem::Pic_map_base + 0x58,
-    NIPNDL      = Kmem::Pic_map_base + 0x5c,
-    FIPNDH      = Kmem::Pic_map_base + 0x60,
-    FIPNDL      = Kmem::Pic_map_base + 0x64,
-
-
-    INTCTL_FIAD  = 1 << 19, // Fast Interrupt Arbiter Rise ARM Level
-    INTCTL_NIAD  = 1 << 20, // Normal Interrupt Arbiter Rise ARM Level
-    INTCTL_FIDIS = 1 << 21, // Fast Interrupt Disable
-    INTCTL_NIDIS = 1 << 22, // Normal Interrupt Disable
-  };
 };
 
 // ---------------------------------------------------------------------
@@ -45,13 +16,43 @@ IMPLEMENTATION [arm && (imx21 || imx35)]:
 #include "io.h"
 #include "irq_chip_generic.h"
 #include "irq_mgr.h"
+#include "mmio_register_block.h"
 
-class Irq_chip_arm_imx : public Irq_chip_gen
+class Irq_chip_arm_imx : public Irq_chip_gen, private Mmio_register_block
 {
+private:
+  enum
+  {
+    INTCTL      = 0x00,
+    NIMASK      = 0x04,
+    INTENNUM    = 0x08,
+    INTDISNUM   = 0x0c,
+    INTENABLEH  = 0x10,
+    INTENABLEL  = 0x14,
+    INTTYPEH    = 0x18,
+    INTTYPEL    = 0x1c,
+    NIPRIORITY7 = 0x20,
+    NIPRIORITY0 = 0x3c,
+    NIVECSR     = 0x40,
+    FIVECSR     = 0x44,
+    INTSRCH     = 0x48,
+    INTSRCL     = 0x4c,
+    INTFRCH     = 0x50,
+    INTFRCL     = 0x54,
+    NIPNDH      = 0x58,
+    NIPNDL      = 0x5c,
+    FIPNDH      = 0x60,
+    FIPNDL      = 0x64,
+
+
+    INTCTL_FIAD  = 1 << 19, // Fast Interrupt Arbiter Rise ARM Level
+    INTCTL_NIAD  = 1 << 20, // Normal Interrupt Arbiter Rise ARM Level
+    INTCTL_FIDIS = 1 << 21, // Fast Interrupt Disable
+    INTCTL_NIDIS = 1 << 22, // Normal Interrupt Disable
+  };
 public:
-  Irq_chip_arm_imx() : Irq_chip_gen(64) {}
   unsigned set_mode(Mword, unsigned) { return Irq_base::Trigger_level; }
-  void set_cpu(Mword, unsigned) {}
+  void set_cpu(Mword, Cpu_number) {}
   void ack(Mword) { /* ack is empty */ }
 };
 
@@ -60,7 +61,7 @@ void
 Irq_chip_arm_imx::mask(Mword irq)
 {
   assert(cpu_lock.test());
-  Io::write<Mword>(irq, Pic::INTDISNUM); // disable pin
+  write<Mword>(irq, INTDISNUM); // disable pin
 }
 
 PUBLIC
@@ -68,7 +69,7 @@ void
 Irq_chip_arm_imx::mask_and_ack(Mword irq)
 {
   assert(cpu_lock.test());
-  Io::write<Mword>(irq, Pic::INTDISNUM); // disable pin
+  write<Mword>(irq, INTDISNUM); // disable pin
   // ack is empty
 }
 
@@ -77,7 +78,23 @@ void
 Irq_chip_arm_imx::unmask(Mword irq)
 {
   assert (cpu_lock.test());
-  Io::write<Mword>(irq, Pic::INTENNUM);
+  write<Mword>(irq, INTENNUM);
+}
+
+PUBLIC inline
+Irq_chip_arm_imx::Irq_chip_arm_imx()
+: Irq_chip_gen(64),
+  Mmio_register_block(Kmem::mmio_remap(Mem_layout::Pic_phys_base))
+{
+  write<Mword>(0,    INTCTL);
+  write<Mword>(0x10, NIMASK); // Do not disable any normal interrupts
+
+  write<Mword>(0, INTTYPEH); // All interrupts generate normal interrupts
+  write<Mword>(0, INTTYPEL);
+
+  // Init interrupt priorities
+  for (int i = 0; i < 8; ++i)
+    write<Mword>(0x1111, NIPRIORITY7 + (i * 4)); // low addresses start with 7
 }
 
 static Static_object<Irq_mgr_single_chip<Irq_chip_arm_imx> > mgr;
@@ -87,16 +104,6 @@ IMPLEMENT FIASCO_INIT
 void Pic::init()
 {
   Irq_mgr::mgr = mgr.construct();
-
-  Io::write<Mword>(0,    INTCTL);
-  Io::write<Mword>(0x10, NIMASK); // Do not disable any normal interrupts
-
-  Io::write<Mword>(0, INTTYPEH); // All interrupts generate normal interrupts
-  Io::write<Mword>(0, INTTYPEL);
-
-  // Init interrupt priorities
-  for (int i = 0; i < 8; ++i)
-    Io::write<Mword>(0x1111, NIPRIORITY7 + (i * 4)); // low addresses start with 7
 }
 
 IMPLEMENT inline
@@ -110,10 +117,10 @@ IMPLEMENT inline
 void Pic::restore_all(Status)
 {}
 
-PUBLIC static inline NEEDS["io.h"]
+PUBLIC inline
 Unsigned32 Irq_chip_arm_imx::pending()
 {
-  return Io::read<Mword>(Pic::NIVECSR) >> 16;
+  return read<Mword>(NIVECSR) >> 16;
 }
 
 PUBLIC inline NEEDS[Irq_chip_arm_imx::pending]
index 2041a08305638b231bd7ccbb25f411be3c9181c3..cc9af4bd51bfb77e9f1968ea47550431dbcdffce 100644 (file)
@@ -30,7 +30,8 @@ Pic::init()
 
   M *m = new Boot_object<M>(1);
 
-  gic.construct(Kmem::Gic_cpu_map_base, Kmem::Gic_dist_map_base);
+  gic.construct(Kmem::mmio_remap(Mem_layout::Gic_cpu_phys_base),
+                Kmem::mmio_remap(Mem_layout::Gic_dist_phys_base));
   m->add_chip(0, gic, gic->nr_irqs());
 
   Irq_mgr::mgr = m;
@@ -48,7 +49,7 @@ void Pic::restore_all(Status)
 IMPLEMENTATION [arm && pic_gic && mp && imx6]:
 
 PUBLIC static
-void Pic::init_ap(unsigned)
+void Pic::init_ap(Cpu_number)
 {
   gic->init_ap();
 }
index 39b27edf2775f256b628bde010681d37d291bd06..d2b2d117e0a12eddef195a0a1442ced1426c8f3a 100644 (file)
@@ -4,30 +4,32 @@ INTERFACE [arm && mp && imx6]:
 
 IMPLEMENTATION [arm && mp && imx6]:
 
-#include "io.h"
 #include "ipi.h"
 #include "mem_layout.h"
+#include "mmio_register_block.h"
+#include "kmem.h"
 
 PUBLIC static
 void
 Platform_control::boot_ap_cpus(Address phys_tramp_mp_addr)
 {
+  Mmio_register_block src(Kmem::mmio_remap(Mem_layout::Src_phys_base));
   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  = 0,
+    SRC_GPR1 = 0x20,
+    SRC_GPR3 = 0x28,
+    SRC_GPR5 = 0x30,
+    SRC_GPR7 = 0x38,
 
     SRC_SCR_CORE1_3_ENABLE = 7 << 22,
     SRC_SCR_CORE1_3_RESET  = 7 << 14,
   };
 
-  Io::write<Mword>(phys_tramp_mp_addr, SRC_GPR3);
-  Io::write<Mword>(phys_tramp_mp_addr, SRC_GPR5);
-  Io::write<Mword>(phys_tramp_mp_addr, SRC_GPR7);
+  src.write<Mword>(phys_tramp_mp_addr, SRC_GPR3);
+  src.write<Mword>(phys_tramp_mp_addr, SRC_GPR5);
+  src.write<Mword>(phys_tramp_mp_addr, SRC_GPR7);
 
-  Io::set<Mword>(SRC_SCR_CORE1_3_RESET, SRC_SCR);
-  Io::set<Mword>(SRC_SCR_CORE1_3_ENABLE, SRC_SCR);
+  src.modify<Mword>(SRC_SCR_CORE1_3_RESET, 0, SRC_SCR);
+  src.modify<Mword>(SRC_SCR_CORE1_3_ENABLE, 0, SRC_SCR);
 }
index 9ac16f4dd532d20a8b5efd2353cde5d47a9e8dfd..c447c0fff460ac33dab900747fe8f0bd778e15a7 100644 (file)
@@ -7,18 +7,18 @@ void __attribute__ ((noreturn))
 platform_reset(void)
 {
   enum {
-    WCR  = Kmem::Watchdog_map_base + 0,
+    WCR  = Kmem::Watchdog_phys_base + 0,
     WCR_SRS = 1 << 4, // Software Reset Signal
 
-    PLL_PCCR1        = Kmem::Pll_map_base + 0x24,
+    PLL_PCCR1        = Kmem::Pll_phys_base + 0x24,
     PLL_PCCR1_WDT_EN = 1 << 24,
   };
 
   // WDT CLock Enable
-  Io::write<Unsigned32>(Io::read<Unsigned32>(PLL_PCCR1) | PLL_PCCR1_WDT_EN, PLL_PCCR1);
+  Io::set<Unsigned32>(PLL_PCCR1_WDT_EN, Kmem::mmio_remap(PLL_PCCR1));
 
   // Assert Software reset signal by making the bit zero
-  Io::write<Unsigned16>(Io::read<Unsigned16>(WCR) & ~WCR_SRS, WCR);
+  Io::mask<Unsigned16>(~WCR_SRS, Kmem::mmio_remap(WCR));
 
   for (;;)
     ;
@@ -36,7 +36,7 @@ IMPLEMENTATION [arm && imx6]:
 void platform_imx_cpus_off()
 {
   // switch off core1-3
-  Io::clear<Mword>(7 << 22, Mem_layout::Src_map_base + 0);
+  Io::clear<Mword>(7 << 22, Kmem::mmio_remap(Mem_layout::Src_phys_base) + 0);
 }
 
 // ------------------------------------------------------------------------
@@ -49,14 +49,14 @@ void __attribute__ ((noreturn))
 platform_reset(void)
 {
   enum {
-    WCR  = Kmem::Watchdog_map_base + 0,
+    WCR  = Mem_layout::Watchdog_phys_base + 0,
     WCR_SRS = 1 << 4, // Software Reset Signal
   };
 
   platform_imx_cpus_off();
 
   // Assert Software reset signal by making the bit zero
-  Io::write<Unsigned16>(Io::read<Unsigned16>(WCR) & ~WCR_SRS, WCR);
+  Io::mask<Unsigned16>(~WCR_SRS, Kmem::mmio_remap(WCR));
 
   for (;;)
     ;
index 672af88d8da70f5e1047fa15ed9f1d5fe0d19174..72cb8544095507e9b669f70335e36e9fa216e7b1 100644 (file)
@@ -3,6 +3,8 @@ INTERFACE [arm && imx21]:
 
 #include "kmem.h"
 #include "irq_chip.h"
+#include "mmio_register_block.h"
+
 
 EXTENSION class Timer
 {
@@ -10,20 +12,32 @@ public:
   static unsigned irq() { return 26; }
 
 private:
-  enum {
-    TCTL  = Kmem::Timer_map_base + 0x00,
-    TPRER = Kmem::Timer_map_base + 0x04,
-    TCMP  = Kmem::Timer_map_base + 0x08,
-    TCR   = Kmem::Timer_map_base + 0x0c,
-    TCN   = Kmem::Timer_map_base + 0x10,
-    TSTAT = Kmem::Timer_map_base + 0x14,
-
-    TCTL_TEN                            = 1 << 0,
-    TCTL_CLKSOURCE_PERCLK1_TO_PRESCALER = 1 << 1,
-    TCTL_CLKSOURCE_32kHz                = 1 << 3,
-    TCTL_COMP_EN                        = 1 << 4,
-    TCTL_SW_RESET                       = 1 << 15,
+  class Timer_imx21 : private Mmio_register_block
+  {
+  public:
+    Timer_imx21();
+
+  private:
+    enum {
+      TCTL  = 0x00,
+      TPRER = 0x04,
+      TCMP  = 0x08,
+      TCR   = 0x0c,
+      TCN   = 0x10,
+      TSTAT = 0x14,
+
+      TCTL_TEN                            = 1 << 0,
+      TCTL_CLKSOURCE_PERCLK1_TO_PRESCALER = 1 << 1,
+      TCTL_CLKSOURCE_32kHz                = 1 << 3,
+      TCTL_COMP_EN                        = 1 << 4,
+      TCTL_SW_RESET                       = 1 << 15,
+    };
+
+  public:
+    void acknowledge() const { write<Mword>(1, TSTAT); }
   };
+
+  static Static_object<Timer_imx21> _timer;
 };
 
 // ----------------------------------------------------------------------
@@ -36,18 +50,27 @@ IMPLEMENTATION [arm && imx21]:
 #include <cstdio>
 
 IMPLEMENT
-void Timer::init(unsigned)
+Timer::Timer_imx21::Timer_imx21()
+: Mmio_register_block(Kmem::mmio_remap(Mem_layout::Timer_phys_base))
 {
-  Io::write<Mword>(0, TCTL); // Disable
-  Io::write<Mword>(TCTL_SW_RESET, TCTL); // reset timer
+  write<Mword>(0, TCTL); // Disable
+  write<Mword>(TCTL_SW_RESET, TCTL); // reset timer
   for (int i = 0; i < 10; ++i)
-    Io::read<Mword>(TCN); // docu says reset takes 5 cycles
+    read<Mword>(TCN); // docu says reset takes 5 cycles
 
-  Io::write<Mword>(TCTL_CLKSOURCE_32kHz | TCTL_COMP_EN, TCTL);
-  Io::write<Mword>(0, TPRER);
-  Io::write<Mword>(32, TCMP);
+  write<Mword>(TCTL_CLKSOURCE_32kHz | TCTL_COMP_EN, TCTL);
+  write<Mword>(0, TPRER);
+  write<Mword>(32, TCMP);
 
-  Io::set<Mword>(TCTL_TEN, TCTL);
+  modify<Mword>(TCTL_TEN, 0, TCTL);
+}
+
+Static_object<Timer::Timer_imx21> Timer::_timer;
+
+IMPLEMENT
+void Timer::init(Cpu_number)
+{
+  _timer.construct();
 }
 
 static inline
@@ -64,7 +87,7 @@ PUBLIC static inline NEEDS["io.h"]
 void
 Timer::acknowledge()
 {
-  Io::write<Mword>(1, TSTAT);
+  _timer->acknowledge();
 }
 
 IMPLEMENT inline NEEDS["kip.h", "io.h", Timer::timer_to_us, Timer::us_to_timer]
index 529393562fd17b08bf430e91e2a7e66257c0e6d2..f8882220c99048719cf4d765ebe194d308e6f887 100644 (file)
@@ -1,32 +1,12 @@
 // --------------------------------------------------------------------------
 INTERFACE [arm && imx_epit]:
 
-#include "kmem.h"
+#include "timer_imx_epit.h"
 
 EXTENSION class Timer
 {
 private:
-  enum {
-    EPITCR   = Kmem::Timer_map_base + 0x00,
-    EPITSR   = Kmem::Timer_map_base + 0x04,
-    EPITLR   = Kmem::Timer_map_base + 0x08,
-    EPITCMPR = Kmem::Timer_map_base + 0x0c,
-    EPITCNR  = Kmem::Timer_map_base + 0x10,
-
-    EPITCR_ENABLE                  = 1 << 0, // enable EPIT
-    EPITCR_ENMOD                   = 1 << 1, // enable mode
-    EPITCR_OCIEN                   = 1 << 2, // output compare irq enable
-    EPITCR_RLD                     = 1 << 3, // reload
-    EPITCR_SWR                     = 1 << 16, // software reset
-    EPITCR_WAITEN                  = 1 << 19, // wait enabled
-    EPITCR_CLKSRC_IPG_CLK          = 1 << 24,
-    EPITCR_CLKSRC_IPG_CLK_HIGHFREQ = 2 << 24,
-    EPITCR_CLKSRC_IPG_CLK_32K      = 3 << 24,
-    EPITCR_PRESCALER_SHIFT         = 4,
-    EPITCR_PRESCALER_MASK          = ((1 << 12) - 1) << EPITCR_PRESCALER_SHIFT,
-
-    EPITSR_OCIF = 1,
-  };
+  static Static_object<Timer_imx_epit> _timer;
 };
 
 
@@ -51,32 +31,15 @@ public:
 // ------------------------------------------------------------------------
 IMPLEMENTATION [arm && imx_epit]:
 
-#include "io.h"
 #include "kip.h"
+#include "mem_layout.h"
+
+Static_object<Timer_imx_epit> Timer::_timer;
 
 IMPLEMENT
-void Timer::init(unsigned)
+void Timer::init(Cpu_number)
 {
-  Io::write<Mword>(0, EPITCR); // Disable
-  Io::write<Mword>(EPITCR_SWR, EPITCR);
-  while (Io::read<Mword>(EPITCR) & EPITCR_SWR)
-    ;
-
-  Io::write<Mword>(EPITSR_OCIF, EPITSR);
-
-  Io::write<Mword>(EPITCR_CLKSRC_IPG_CLK_32K
-                   | (0 << EPITCR_PRESCALER_SHIFT)
-                  | EPITCR_WAITEN
-                  | EPITCR_RLD
-                  | EPITCR_OCIEN
-                  | EPITCR_ENMOD,
-                   EPITCR);
-
-  Io::write<Mword>(0, EPITCMPR);
-
-  Io::write<Mword>(32, EPITLR);
-
-  Io::set<Mword>(EPITCR_ENABLE, EPITCR);
+  _timer.construct(Mem_layout::Timer_phys_base);
 }
 
 static inline
@@ -89,11 +52,11 @@ Unsigned64
 Timer::us_to_timer(Unsigned64 us)
 { (void)us; return 0; }
 
-PUBLIC static inline NEEDS["io.h"]
+PUBLIC static inline
 void
 Timer::acknowledge()
 {
-  Io::write<Mword>(EPITSR_OCIF, EPITSR);
+  _timer->acknowledge();
 }
 
 IMPLEMENT inline
index def5bc32335c9894236f00bc344401499f86c698..5a1da204260f101bb51259b8e8b4f98ebb1bd63f 100644 (file)
@@ -2,18 +2,19 @@
 IMPLEMENTATION[arm && imx6 && mptimer]:
 
 #include "config.h"
-#include "io.h"
+#include "kmem.h"
 #include "mem_layout.h"
+#include "mmio_register_block.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  = 0x00,
+    GPT_PR  = 0x04,
+    GPT_SR  = 0x08,
+    GPT_IR  = 0x0c,
+    GPT_CNT = 0x24,
 
     GPT_CR_EN                 = 1 << 0,
     GPT_CR_CLKSRC_MASK        = 7 << 6,
@@ -27,19 +28,21 @@ PRIVATE static Mword Timer::interval()
     Gpt_ticks = (Timer_freq * Ticks) / Config::Scheduler_granularity,
   };
 
-  Io::write<Mword>(0, GPT_CR);
-  Io::write<Mword>(GPT_CR_RESET, GPT_CR);
-  while (Io::read<Mword>(GPT_CR) & GPT_CR_RESET)
+  Mmio_register_block t(Kmem::mmio_remap(Mem_layout::Gpt_phys_base));
+
+  t.write<Mword>(0, GPT_CR);
+  t.write<Mword>(GPT_CR_RESET, GPT_CR);
+  while (t.read<Mword>(GPT_CR) & GPT_CR_RESET)
     ;
 
-  Io::write<Mword>(GPT_CR_CLKSRC_32KHZ | GPT_CR_FRR, GPT_CR);
-  Io::write<Mword>(0, GPT_PR);
+  t.write<Mword>(GPT_CR_CLKSRC_32KHZ | GPT_CR_FRR, GPT_CR);
+  t.write<Mword>(0, GPT_PR);
 
-  Io::set<Mword>(GPT_CR_EN, GPT_CR);
+  t.modify<Mword>(GPT_CR_EN, 0, GPT_CR);
   Mword vc = start_as_counter();
-  while (Io::read<Mword>(GPT_CNT) < Gpt_ticks)
+  while (t.read<Mword>(GPT_CNT) < Gpt_ticks)
     ;
   Mword interval = (vc - stop_counter()) / Ticks;
-  Io::write<Mword>(0, GPT_CR);
+  t.write<Mword>(0, GPT_CR);
   return interval;
 }
diff --git a/kernel/fiasco/src/kern/arm/bsp/imx/timer_imx_epit.cpp b/kernel/fiasco/src/kern/arm/bsp/imx/timer_imx_epit.cpp
new file mode 100644 (file)
index 0000000..729418d
--- /dev/null
@@ -0,0 +1,73 @@
+// --------------------------------------------------------------------------
+INTERFACE [arm && imx_epit]:
+
+#include "kmem.h"
+#include "mem_layout.h"
+#include "mmio_register_block.h"
+
+class Timer_imx_epit : private Mmio_register_block
+{
+private:
+  enum {
+    EPITCR   = 0x00,
+    EPITSR   = 0x04,
+    EPITLR   = 0x08,
+    EPITCMPR = 0x0c,
+    EPITCNR  = 0x10,
+
+    EPITCR_ENABLE                  = 1 << 0, // enable EPIT
+    EPITCR_ENMOD                   = 1 << 1, // enable mode
+    EPITCR_OCIEN                   = 1 << 2, // output compare irq enable
+    EPITCR_RLD                     = 1 << 3, // reload
+    EPITCR_SWR                     = 1 << 16, // software reset
+    EPITCR_WAITEN                  = 1 << 19, // wait enabled
+    EPITCR_CLKSRC_IPG_CLK          = 1 << 24,
+    EPITCR_CLKSRC_IPG_CLK_HIGHFREQ = 2 << 24,
+    EPITCR_CLKSRC_IPG_CLK_32K      = 3 << 24,
+    EPITCR_PRESCALER_SHIFT         = 4,
+    EPITCR_PRESCALER_MASK          = ((1 << 12) - 1) << EPITCR_PRESCALER_SHIFT,
+
+    EPITSR_OCIF = 1,
+  };
+};
+
+
+// ------------------------------------------------------------------------
+IMPLEMENTATION [arm && imx_epit]:
+
+#include "io.h"
+#include "kip.h"
+
+PUBLIC
+Timer_imx_epit::Timer_imx_epit(Address phys_base)
+: Mmio_register_block(Kmem::mmio_remap(phys_base))
+{
+  write<Mword>(0, EPITCR); // Disable
+  write<Mword>(EPITCR_SWR, EPITCR);
+  while (read<Mword>(EPITCR) & EPITCR_SWR)
+    ;
+
+  write<Mword>(EPITSR_OCIF, EPITSR);
+
+  write<Mword>(EPITCR_CLKSRC_IPG_CLK_32K
+               | (0 << EPITCR_PRESCALER_SHIFT)
+               | EPITCR_WAITEN
+               | EPITCR_RLD
+               | EPITCR_OCIEN
+               | EPITCR_ENMOD,
+               EPITCR);
+
+  write<Mword>(0, EPITCMPR);
+
+  write<Mword>(32, EPITLR);
+
+  modify<Mword>(EPITCR_ENABLE, 0, EPITCR);
+}
+
+PUBLIC inline
+void
+Timer_imx_epit::acknowledge()
+{
+  write<Mword>(EPITSR_OCIF, EPITSR);
+}
+
index 7f6e572f89731e6c760c464b2e64f0d8f09b3a10..08b96551ed5332fac481c17a25aa3711f942ae47 100644 (file)
@@ -53,4 +53,4 @@ IMPLEMENTATION:
 
 #include "mem_layout.h"
 
-IMPLEMENT Address Uart::base() const { return Mem_layout::Uart_base; }
+IMPLEMENT Address Uart::base() const { return Mem_layout::Uart_phys_base; }
index 04adfc7ee771888a77469d2c33e751cbc49a7f0a..cb3e357229504e376590d2f89bf5e2e68c06a4ab 100644 (file)
@@ -3,7 +3,7 @@
 SUBSYSTEMS              += LIBUART
 OBJECTS_LIBUART         += uart_pl011.o
 PREPROCESS_PARTS        += integrator libuart generic_tickless_idle
-CONFIG_KERNEL_LOAD_ADDR := 0x00000000
+RAM_PHYS_BASE           := 0x00000000
 
 
 uart_IMPL             += uart-arm-integrator
index adc23e8145bc2f6e5e1b519ce2120a3baad0ae78..5fb302f4675cf43a5e40b26372c709d218ffa70b 100644 (file)
@@ -1,17 +1,7 @@
 //-----------------------------------------------------------------------------
 INTERFACE [arm && integrator]:
-
+namespace Bootstrap {
 enum {
   Cache_flush_area = 0xe0000000,
 };
-
-//-----------------------------------------------------------------------------
-IMPLEMENTATION [arm && integrator]:
-void
-map_hw(void *pd)
-{
-  map_dev<Mem_layout::Devices0_phys_base>(pd, 0);
-  map_dev<Mem_layout::Devices1_phys_base>(pd, 1);
-  map_dev<Mem_layout::Devices2_phys_base>(pd, 2);
-  map_dev<Mem_layout::Devices3_phys_base>(pd, 3);
 }
index 523e7184319d46547f511240751618b24642dfaf..b350599b3e5aaaae8cef0f338b944d02c65d1cfd 100644 (file)
@@ -3,21 +3,11 @@ INTERFACE [arm-integrator]: //----------------------------------------------
 EXTENSION class Mem_layout
 {
 public:
-  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 : 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,
+  enum Phys_layout_integrator : Address {
+    Integrator_phys_base = 0x10000000,
+    Timer_phys_base      = 0x13000000,
+    Pic_phys_base        = 0x14000000,
+    Uart_phys_base       = 0x16000000,
   };
 };
 
index f8b37df2ab9220ef0781588364a24ed29f76d22d..fe90cf93ceb1c96f091e28698b3877e3c35f73bc 100644 (file)
@@ -1,46 +1,49 @@
 // ---------------------------------------------------------------------
-INTERFACE [arm-integrator]:
+IMPLEMENTATION [arm && integrator]:
 
+#include "assert.h"
+#include "initcalls.h"
+#include "irq_chip_generic.h"
+#include "irq_mgr.h"
+#include "mmio_register_block.h"
 #include "kmem.h"
 
-EXTENSION class Pic
+class Irq_chip_arm_integr : public Irq_chip_gen, Mmio_register_block
 {
-public:
+private:
   enum
   {
-    IRQ_STATUS       = Kmem::Pic_map_base + 0x00,
-    IRQ_ENABLE_SET   = Kmem::Pic_map_base + 0x08,
-    IRQ_ENABLE_CLEAR = Kmem::Pic_map_base + 0x0c,
+    IRQ_STATUS       = 0x00,
+    IRQ_ENABLE_SET   = 0x08,
+    IRQ_ENABLE_CLEAR = 0x0c,
 
-    FIQ_ENABLE_CLEAR = Kmem::Pic_map_base + 0x2c,
+    FIQ_ENABLE_CLEAR = 0x2c,
 
     PIC_START = 0,
     PIC_END   = 31,
   };
-};
 
-// ---------------------------------------------------------------------
-IMPLEMENTATION [arm && integrator]:
-
-#include "io.h"
-#include "irq_chip_generic.h"
-#include "irq_mgr.h"
-
-class Irq_chip_arm_integr : public Irq_chip_gen
-{
 public:
-  Irq_chip_arm_integr() : Irq_chip_gen(32) {}
   unsigned set_mode(Mword, unsigned) { return Irq_base::Trigger_level; }
-  void set_cpu(Mword, unsigned) {}
+  void set_cpu(Mword, Cpu_number) {}
   void ack(Mword) { /* ack is empty */ }
 };
 
+PUBLIC
+Irq_chip_arm_integr::Irq_chip_arm_integr()
+: Irq_chip_gen(32),
+  Mmio_register_block(Kmem::mmio_remap(Mem_layout::Pic_phys_base))
+{
+  write<Mword>(0xffffffff, IRQ_ENABLE_CLEAR);
+  write<Mword>(0xffffffff, FIQ_ENABLE_CLEAR);
+}
+
 PUBLIC
 void
 Irq_chip_arm_integr::mask(Mword irq)
 {
   assert(cpu_lock.test());
-  Io::write(1 << (irq - Pic::PIC_START), Pic::IRQ_ENABLE_CLEAR);
+  write<Mword>(1 << (irq - PIC_START), IRQ_ENABLE_CLEAR);
 }
 
 PUBLIC
@@ -48,7 +51,7 @@ void
 Irq_chip_arm_integr::mask_and_ack(Mword irq)
 {
   assert(cpu_lock.test());
-  Io::write(1 << (irq - Pic::PIC_START), Pic::IRQ_ENABLE_CLEAR);
+  write<Mword>(1 << (irq - PIC_START), IRQ_ENABLE_CLEAR);
   // ack is empty
 }
 
@@ -57,7 +60,7 @@ void
 Irq_chip_arm_integr::unmask(Mword irq)
 {
   assert(cpu_lock.test());
-  Io::write(1 << (irq - Pic::PIC_START), Pic::IRQ_ENABLE_SET);
+  write<Mword>(1 << (irq - PIC_START), IRQ_ENABLE_SET);
 }
 
 static Static_object<Irq_mgr_single_chip<Irq_chip_arm_integr> > mgr;
@@ -66,9 +69,6 @@ IMPLEMENT FIASCO_INIT
 void Pic::init()
 {
   Irq_mgr::mgr = mgr.construct();
-
-  Io::write(0xffffffff, IRQ_ENABLE_CLEAR);
-  Io::write(0xffffffff, FIQ_ENABLE_CLEAR);
 }
 
 IMPLEMENT inline
@@ -82,10 +82,10 @@ IMPLEMENT inline
 void Pic::restore_all(Status)
 {}
 
-PUBLIC static inline NEEDS["io.h"]
+PUBLIC inline
 Unsigned32 Irq_chip_arm_integr::pending()
 {
-  return Io::read<Mword>(Pic::IRQ_STATUS);
+  return read<Mword>(IRQ_STATUS);
 }
 
 extern "C"
index 8c99e7f70f6dacabc42e2e61f800852104d35225..3055bc074362eb177a41b0635082e8646dc29408 100644 (file)
@@ -7,10 +7,10 @@ void __attribute__ ((noreturn))
 platform_reset(void)
 {
   enum {
-    HDR_CTRL_OFFSET = Kmem::Integrator_map_base + 0xc,
+    HDR_CTRL_OFFSET = Mem_layout::Integrator_phys_base + 0xc,
   };
 
-  Io::write(1 << 3, HDR_CTRL_OFFSET);
+  Io::write(1 << 3, Kmem::mmio_remap(HDR_CTRL_OFFSET));
 
   for (;;)
     ;
index a796a378ce58b67b7b539740d2024a8680aa6569..c18427484240270bacaafa68534f2dbbfe885a77 100644 (file)
@@ -1,20 +1,18 @@
 // --------------------------------------------------------------------------
 INTERFACE [arm && integrator]:
 
-#include "kmem.h"
+#include "mmio_register_block.h"
 
-EXTENSION class Timer
+EXTENSION class Timer : private Mmio_register_block
 {
 public:
   static unsigned irq() { return 6; }
 
 private:
   enum {
-    Base = Kmem::Timer_map_base,
-
-    TIMER0_VA_BASE = Base + 0x000,
-    TIMER1_VA_BASE = Base + 0x100,
-    TIMER2_VA_BASE = Base + 0x200,
+    TIMER0_BASE = 0x000,
+    TIMER1_BASE = 0x100,
+    TIMER2_BASE = 0x200,
 
     TIMER_LOAD   = 0x00,
     TIMER_VALUE  = 0x04,
@@ -25,6 +23,8 @@ private:
     TIMER_CTRL_PERIODIC = 1 << 6,
     TIMER_CTRL_ENABLE   = 1 << 7,
   };
+
+  static Static_object<Timer> _timer;
 };
 
 // ----------------------------------------------------------------------
@@ -32,24 +32,31 @@ IMPLEMENTATION [arm && integrator]:
 
 #include "config.h"
 #include "kip.h"
-#include "io.h"
+#include "kmem.h"
+#include "mem_layout.h"
 
-IMPLEMENT
-void Timer::init(unsigned)
+Static_object<Timer> Timer::_timer;
+
+PUBLIC
+Timer::Timer(Address base) : Mmio_register_block(base)
 {
   /* Switch all timers off */
-  Io::write(0, TIMER0_VA_BASE + TIMER_CTRL);
-  Io::write(0, TIMER1_VA_BASE + TIMER_CTRL);
-  Io::write(0, TIMER2_VA_BASE + TIMER_CTRL);
+  write(0, TIMER0_BASE + TIMER_CTRL);
+  write(0, TIMER1_BASE + TIMER_CTRL);
+  write(0, TIMER2_BASE + TIMER_CTRL);
 
   unsigned timer_ctrl = TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC;
   unsigned timer_reload = 1000000 / Config::Scheduler_granularity;
 
-  Io::write(timer_reload, TIMER1_VA_BASE + TIMER_LOAD);
-  Io::write(timer_reload, TIMER1_VA_BASE + TIMER_VALUE);
-  Io::write(timer_ctrl | TIMER_CTRL_IE, TIMER1_VA_BASE + TIMER_CTRL);
+  write(timer_reload, TIMER1_BASE + TIMER_LOAD);
+  write(timer_reload, TIMER1_BASE + TIMER_VALUE);
+  write(timer_ctrl | TIMER_CTRL_IE, TIMER1_BASE + TIMER_CTRL);
 }
 
+IMPLEMENT
+void Timer::init(Cpu_number)
+{ _timer.construct(Kmem::mmio_remap(Mem_layout::Timer_phys_base)); }
+
 static inline
 Unsigned64
 Timer::timer_to_us(Unsigned32 /*cr*/)
@@ -60,11 +67,11 @@ Unsigned64
 Timer::us_to_timer(Unsigned64 us)
 { (void)us; return 0; }
 
-PUBLIC static inline NEEDS["io.h"]
+PUBLIC static inline
 void
 Timer::acknowledge()
 {
-  Io::write(1, TIMER1_VA_BASE + TIMER_INTCLR);
+  _timer->write(1, TIMER1_BASE + TIMER_INTCLR);
 }
 
 IMPLEMENT inline
index dbef46c80ae08905e6f4f293cad6295024afaa00..c6a0e77cf78f312460864b2047e1e80c51552625 100644 (file)
@@ -3,7 +3,7 @@ IMPLEMENTATION [integrator]:
 #include "uart_pl011.h"
 #include "mem_layout.h"
 
-IMPLEMENT Address Uart::base() const { return Mem_layout::Uart_base; }
+IMPLEMENT Address Uart::base() const { return Mem_layout::Uart_phys_base; }
 
 IMPLEMENT int Uart::irq() const { return 1; }
 
index 8dfab3e2d1c582dbfae4e2723aef17eff763a3eb..322994ca9c244b7e5add5eb66c7987f7addd3805 100644 (file)
@@ -1,7 +1,7 @@
 # vim:set ft=make:
 
 PREPROCESS_PARTS        += kirkwood 16550 generic_tickless_idle
-CONFIG_KERNEL_LOAD_ADDR := 0x0
+RAM_PHYS_BASE           := 0x0
 
 uart_IMPL             += uart-16550 uart-16550-arm-kirkwood
 config_IMPL           += config-arm-kirkwood
index 5237e93f67d89da1248d51d0d59535007827a83f..293feb18c926c0d537a0c45391ee25967af1f226 100644 (file)
@@ -1,14 +1,5 @@
 INTERFACE [arm && kirkwood]:
 
-#include "mem_layout.h"
-
+namespace Bootstrap {
 enum { Cache_flush_area = 0, };
-
-//-----------------------------------------------------------------------------
-IMPLEMENTATION [arm && kirkwood]:
-
-void
-map_hw(void *pd)
-{
-  map_dev<Mem_layout::Devices0_phys_base>(pd, 0);
 }
index 8796e234f45e8ebc47201368ae7770c4d1831e30..a5f65a0b99083ca361126c23ccdf183f6c71f9f2 100644 (file)
@@ -6,9 +6,10 @@ EXTENSION class Kernel_uart { enum { Bsp_init_mode = Init_before_mmu }; };
 IMPLEMENTATION [arm && kirkwood && serial]:
 
 #include "mem_layout.h"
+#include "kmem.h"
 
 IMPLEMENT
 bool Kernel_uart::startup(unsigned port, int /*irq*/)
 {
-  return Uart::startup(Mem_layout::Uart_base, 33);
+  return Uart::startup(Kmem::mmio_remap(Mem_layout::Uart_phys_base), 33);
 }
index e3e1e0b74f4389108d673ee99f8e528b0ac32390..4d6c8da9841b87eb511d16f90bf2cccd24497255 100644 (file)
@@ -3,17 +3,11 @@ INTERFACE [arm && kirkwood]:
 EXTENSION class Mem_layout
 {
 public:
-  enum Virt_layout_kirkwood : Address
-  {
-    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: Address
   {
-    Devices0_phys_base   = 0xf1000000,
-    Sdram_phys_base      = 0x0,
+    Reset_phys_base   = 0xf1000000,
+    Timer_phys_base   = 0xf1000000,
+    Pic_phys_base     = 0xf1000000,
+    Uart_phys_base    = 0xf1012000,
   };
 };
index 3ce543265ae28988bf6e2f36fadaf4cf9985df8f..64837a06dc7d82e431ded06de6bc8769da1aa9ed 100644 (file)
@@ -1,42 +1,48 @@
-INTERFACE [arm && kirkwood]:
-
-#include "kmem.h"
-
-class Irq_base;
-
-EXTENSION class Pic
-{
-public:
-  enum
-  {
-    Main_Irq_cause_low_reg     = Mem_layout::Pic_map_base + 0x20200,
-    Main_Irq_mask_low_reg      = Mem_layout::Pic_map_base + 0x20204,
-    Main_Fiq_mask_low_reg      = Mem_layout::Pic_map_base + 0x20208,
-    Endpoint_irq_mask_low_reg  = Mem_layout::Pic_map_base + 0x2020c,
-    Main_Irq_cause_high_reg    = Mem_layout::Pic_map_base + 0x20210,
-    Main_Irq_mask_high_reg     = Mem_layout::Pic_map_base + 0x20214,
-    Main_Fiq_mask_high_reg     = Mem_layout::Pic_map_base + 0x20218,
-    Endpoint_irq_mask_high_reg = Mem_layout::Pic_map_base + 0x2021c,
-
-    Bridge_int_num = 1,
-  };
-};
-
 //-------------------------------------------------------------------
 IMPLEMENTATION [arm && kirkwood]:
 
+#include "assert.h"
 #include "config.h"
 #include "initcalls.h"
 #include "io.h"
 #include "irq_chip_generic.h"
 #include "irq_mgr.h"
+#include "kmem.h"
+#include "mmio_register_block.h"
 
-class Irq_chip_kirkwood : public Irq_chip_gen
+class Irq_chip_kirkwood : public Irq_chip_gen, private Mmio_register_block
 {
+private:
+  enum
+  {
+    Main_Irq_cause_low_reg     = 0x20200,
+    Main_Irq_mask_low_reg      = 0x20204,
+    Main_Fiq_mask_low_reg      = 0x20208,
+    Endpoint_irq_mask_low_reg  = 0x2020c,
+    Main_Irq_cause_high_reg    = 0x20210,
+    Main_Irq_mask_high_reg     = 0x20214,
+    Main_Fiq_mask_high_reg     = 0x20218,
+    Endpoint_irq_mask_high_reg = 0x2021c,
+
+    Bridge_int_num = 1,
+  };
+
 public:
-  Irq_chip_kirkwood() : Irq_chip_gen(64) {}
+  Irq_chip_kirkwood()
+  : Irq_chip_gen(64),
+    Mmio_register_block(Kmem::mmio_remap(Mem_layout::Pic_phys_base))
+  {
+    // Disable all interrupts
+    write<Unsigned32>(0U, Main_Irq_mask_low_reg);
+    write<Unsigned32>(0U, Main_Fiq_mask_low_reg);
+    write<Unsigned32>(0U, Main_Irq_mask_high_reg);
+    write<Unsigned32>(0U, Main_Fiq_mask_high_reg);
+    // enable bridge (chain) IRQ
+    modify<Unsigned32>(1 << Bridge_int_num, 0, Main_Irq_mask_low_reg);
+  }
+
   unsigned set_mode(Mword, unsigned) { return Irq_base::Trigger_level; }
-  void set_cpu(Mword, unsigned) {}
+  void set_cpu(Mword, Cpu_number) {}
   void ack(Mword) { /* ack is empty */ }
 };
 
@@ -45,8 +51,8 @@ void
 Irq_chip_kirkwood::mask(Mword irq)
 {
   assert (cpu_lock.test());
-  Io::clear<Unsigned32>(1 << (irq & 0x1f),
-                       Pic::Main_Irq_mask_low_reg + ((irq & 0x20) >> 1));
+  modify<Unsigned32>(0, 1 << (irq & 0x1f),
+                     Main_Irq_mask_low_reg + ((irq & 0x20) >> 1));
 }
 
 PUBLIC
@@ -63,8 +69,8 @@ void
 Irq_chip_kirkwood::unmask(Mword irq)
 {
   assert(cpu_lock.test());
-  Io::set<Unsigned32>(1 << (irq & 0x1f),
-                      Pic::Main_Irq_mask_low_reg + ((irq & 0x20) >> 1));
+  modify<Unsigned32>(1 << (irq & 0x1f), 0,
+                     Main_Irq_mask_low_reg + ((irq & 0x20) >> 1));
 }
 
 static Static_object<Irq_mgr_single_chip<Irq_chip_kirkwood> > mgr;
@@ -74,14 +80,6 @@ void Pic::init()
 {
   Irq_mgr::mgr = mgr.construct();
 
-  // Disable all interrupts
-  Io::write<Unsigned32>(0U, Main_Irq_mask_low_reg);
-  Io::write<Unsigned32>(0U, Main_Fiq_mask_low_reg);
-  Io::write<Unsigned32>(0U, Main_Irq_mask_high_reg);
-  Io::write<Unsigned32>(0U, Main_Fiq_mask_high_reg);
-
-  // enable bridge (chain) IRQ
-  Io::set<Unsigned32>(1 << Bridge_int_num, Main_Irq_mask_low_reg);
 }
 
 IMPLEMENT inline
@@ -92,15 +90,16 @@ IMPLEMENT inline
 void Pic::restore_all(Status)
 {}
 
-PUBLIC static inline NEEDS["io.h"]
-Unsigned32 Irq_chip_kirkwood::pending()
+PUBLIC inline
+Unsigned32
+Irq_chip_kirkwood::pending()
 {
   Unsigned32 v;
 
-  v = Io::read<Unsigned32>(Pic::Main_Irq_cause_low_reg);
+  v = read<Unsigned32>(Main_Irq_cause_low_reg);
   if (v & 1)
     {
-      v = Io::read<Unsigned32>(Pic::Main_Irq_cause_high_reg);
+      v = read<Unsigned32>(Main_Irq_cause_high_reg);
       for (int i = 1; i < 32; ++i)
        if ((1 << i) & v)
          return 32 + i;
@@ -116,7 +115,7 @@ extern "C"
 void irq_handler()
 {
   Unsigned32 i;
-  while ((i = Irq_chip_kirkwood::pending()) < 64)
+  while ((i = mgr->c.pending()) < 64)
     mgr->c.handle_irq<Irq_chip_kirkwood>(i, 0);
 }
 
index 884b62fbfab92fb9bf634c62d75b5bcabc559ca5..9fafe8af46334454921c1308f649927d5633d11f 100644 (file)
@@ -2,28 +2,28 @@ IMPLEMENTATION [arm && kirkwood]:
 
 #include "io.h"
 #include "kmem.h"
+#include "mmio_register_block.h"
 
 class Kirkwood_reset
 {
 public:
   enum
   {
-    Mask_reg       = Mem_layout::Reset_map_base + 0x20108,
-    Soft_reset_reg = Mem_layout::Reset_map_base + 0x2010c,
+    Mask_reg       = 0x20108,
+    Soft_reset_reg = 0x2010c,
   };
 };
 
-// ------------------------------------------------------------------------
-IMPLEMENTATION [arm && kirkwood]:
 
 void __attribute__ ((noreturn))
 platform_reset(void)
 {
+  Mmio_register_block r(Kmem::mmio_remap(Mem_layout::Reset_phys_base));
   // enable software reset
-  Io::write(1 << 2, Kirkwood_reset::Mask_reg);
+  r.write(1 << 2, Kirkwood_reset::Mask_reg);
 
   // do software reset
-  Io::write(1, Kirkwood_reset::Soft_reset_reg);
+  r.write(1, Kirkwood_reset::Soft_reset_reg);
 
   for (;;)
     ;
index bda558af77a7d0efae305b55703fda039d14dad3..51488fb39e099fc52ab1d6e814dd37803214dab3 100644 (file)
@@ -2,22 +2,23 @@
 INTERFACE [arm && kirkwood]:
 
 #include "kmem.h"
+#include "mmio_register_block.h"
 
-EXTENSION class Timer
+EXTENSION class Timer : private Mmio_register_block
 {
 public:
   static unsigned irq() { return 1; }
 
 private:
   enum {
-    Control_Reg  = Mem_layout::Reset_map_base + 0x20300,
-    Reload0_Reg  = Mem_layout::Reset_map_base + 0x20310,
-    Timer0_Reg   = Mem_layout::Reset_map_base + 0x20314,
-    Reload1_Reg  = Mem_layout::Reset_map_base + 0x20318,
-    Timer1_Reg   = Mem_layout::Reset_map_base + 0x2031c,
+    Control_Reg  = 0x20300,
+    Reload0_Reg  = 0x20310,
+    Timer0_Reg   = 0x20314,
+    Reload1_Reg  = 0x20318,
+    Timer1_Reg   = 0x2031c,
 
-    Bridge_cause = Mem_layout::Reset_map_base + 0x20110,
-    Bridge_mask  = Mem_layout::Reset_map_base + 0x20114,
+    Bridge_cause = 0x20110,
+    Bridge_mask  = 0x20114,
 
     Timer0_enable = 1 << 0,
     Timer0_auto   = 1 << 1,
@@ -27,6 +28,8 @@ private:
 
     Reload_value = 200000,
   };
+
+  static Static_object<Timer> _timer;
 };
 
 // ----------------------------------------------------------------------
@@ -36,19 +39,27 @@ IMPLEMENTATION [arm && kirkwood]:
 #include "kip.h"
 #include "io.h"
 
-IMPLEMENT
-void Timer::init(unsigned)
+Static_object<Timer> Timer::_timer;
+
+PUBLIC
+Timer::Timer()
+: Mmio_register_block(Kmem::mmio_remap(Mem_layout::Timer_phys_base))
 {
   // Disable timer
-  Io::write(0, Control_Reg);
+  write(0, Control_Reg);
 
   // Set current timer value and reload value
-  Io::write<Mword>(Reload_value, Timer0_Reg);
-  Io::write<Mword>(Reload_value, Reload0_Reg);
+  write<Mword>(Reload_value, Timer0_Reg);
+  write<Mword>(Reload_value, Reload0_Reg);
 
-  Io::set<Mword>(Timer0_enable | Timer0_auto, Control_Reg);
+  modify<Mword>(Timer0_enable | Timer0_auto, 0, Control_Reg);
+  modify<Unsigned32>(Timer0_bridge_num, 0, Bridge_mask);
+}
 
-  Io::set<Unsigned32>(Timer0_bridge_num, Bridge_mask);
+IMPLEMENT
+void Timer::init(Cpu_number)
+{
+  _timer.construct();
 }
 
 static inline
@@ -65,7 +76,7 @@ PUBLIC static inline NEEDS["io.h"]
 void
 Timer::acknowledge()
 {
-  Io::clear<Unsigned32>(Timer0_bridge_num, Bridge_cause);
+  _timer->modify<Unsigned32>(0, Timer0_bridge_num, Bridge_cause);
 }
 
 IMPLEMENT inline
diff --git a/kernel/fiasco/src/kern/arm/bsp/omap/Kconfig b/kernel/fiasco/src/kern/arm/bsp/omap/Kconfig
new file mode 100644 (file)
index 0000000..80e17e6
--- /dev/null
@@ -0,0 +1,38 @@
+# PF: OMAP
+# PFDESCR: TI OMAP
+# PFDEPENDS: ARM
+
+choice
+       prompt "OMAP Platform"
+       default PF_OMAP3_EVM
+
+config PF_OMAP3_OMAP35XEVM
+       bool "TI OMAP35xEVM"
+       depends on PF_OMAP
+       select CAN_ARM_CPU_CORTEX_A8
+       help
+         Choose for OMAP35xEVM platform.
+
+config PF_OMAP3_BEAGLEBOARD
+       bool "Beagle Board"
+       depends on PF_OMAP
+       select CAN_ARM_CPU_CORTEX_A8
+       help
+         Choose for Beagleboard.
+
+config PF_OMAP3_AM33XX
+       bool "TI AM33xx"
+       depends on PF_OMAP
+       select CAN_ARM_CPU_CORTEX_A8
+       help
+         Choose for AM33xx platforms (e.g. Beaglebone).
+
+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.
+
+endchoice
diff --git a/kernel/fiasco/src/kern/arm/bsp/omap/Modules b/kernel/fiasco/src/kern/arm/bsp/omap/Modules
new file mode 100644 (file)
index 0000000..6587b5b
--- /dev/null
@@ -0,0 +1,29 @@
+# vim:set ft=make:
+
+SUBSYSTEMS              += LIBUART
+OBJECTS_LIBUART         += uart_omap35x.o
+PREPROCESS_PARTS        += omap libuart generic_tickless_idle
+PREPROCESS_PARTS       += $(if $(CONFIG_PF_OMAP3_OMAP35XEVM),omap3 omap3_35x omap3_35xevm)
+PREPROCESS_PARTS       += $(if $(CONFIG_PF_OMAP3_BEAGLEBOARD),omap3 omap3_35x omap3_beagleboard)
+PREPROCESS_PARTS       += $(if $(CONFIG_PF_OMAP3_AM33XX),omap3 omap3_am33xx)
+PREPROCESS_PARTS       += $(if $(CONFIG_PF_OMAP4_PANDABOARD),omap4 mptimer pic_gic omap4_pandaboard)
+RAM_PHYS_BASE           := 0x80000000
+MPCORE_PHYS_BASE        := 0x48240000
+
+INTERFACES_KERNEL     += $(if $(CONFIG_PF_OMAP4_PANDABOARD),gic)
+INTERFACES_KERNEL-omap3 += timer_omap_1mstimer
+INTERFACES_KERNEL-omap3_am33xx += timer_omap_gentimer
+INTERFACES_KERNEL     += $(foreach i,$(PREPROCESS_PARTS),$(INTERFACES_KERNEL-$(i)))
+
+uart_IMPL             += uart-arm-omap
+config_IMPL           += config-arm-omap
+mem_layout_IMPL       += mem_layout-arm-omap
+pic_IMPL              += $(if $(CONFIG_PF_OMAP4_PANDABOARD),pic-gic pic-arm-gic-omap4,pic-arm-omap3)
+bootstrap_IMPL        += bootstrap-arm-omap
+timer_IMPL            += $(if $(CONFIG_PF_OMAP4_PANDABOARD),timer-arm-mptimer timer-arm-mptimer-omap4,timer-arm-omap3)
+timer_tick_IMPL       += timer_tick-single-vector
+kernel_uart_IMPL      += kernel_uart-arm-omap
+reset_IMPL            += reset-arm-omap
+clock_IMPL            += clock-generic
+platform_control_IMPL += platform_control-arm-omap4
+outer_cache_IMPL      += outer_cache-arm-omap
diff --git a/kernel/fiasco/src/kern/arm/bsp/omap/bootstrap-arm-omap.cpp b/kernel/fiasco/src/kern/arm/bsp/omap/bootstrap-arm-omap.cpp
new file mode 100644 (file)
index 0000000..3b1cdc1
--- /dev/null
@@ -0,0 +1,5 @@
+INTERFACE [arm && omap]:
+
+namespace Bootstrap {
+enum { Cache_flush_area = 0 };
+}
diff --git a/kernel/fiasco/src/kern/arm/bsp/omap/config-arm-omap.cpp b/kernel/fiasco/src/kern/arm/bsp/omap/config-arm-omap.cpp
new file mode 100644 (file)
index 0000000..0a24f73
--- /dev/null
@@ -0,0 +1,11 @@
+INTERFACE[arm && omap3_35xevm]: //-----------------------------------------
+#define TARGET_NAME "OMAP35xEVM"
+
+INTERFACE[arm && omap3_beagleboard]: //------------------------------------
+#define TARGET_NAME "Beagleboard"
+
+INTERFACE[arm && omap3_am33xx]: //-----------------------------------------
+#define TARGET_NAME "AM33xx"
+
+INTERFACE[arm && omap4_pandaboard]: //-------------------------------------
+#define TARGET_NAME "Pandaboard"
diff --git a/kernel/fiasco/src/kern/arm/bsp/omap/kernel_uart-arm-omap.cpp b/kernel/fiasco/src/kern/arm/bsp/omap/kernel_uart-arm-omap.cpp
new file mode 100644 (file)
index 0000000..6d834e5
--- /dev/null
@@ -0,0 +1,12 @@
+INTERFACE:
+
+// On ARM the MMIO for the uart is accessible before the MMU is fully up
+EXTENSION class Kernel_uart { enum { Bsp_init_mode = Init_before_mmu }; };
+
+IMPLEMENTATION [arm && omap && serial]:
+
+IMPLEMENT
+bool Kernel_uart::startup(unsigned, int)
+{
+  return Uart::startup();
+}
diff --git a/kernel/fiasco/src/kern/arm/bsp/omap/mem_layout-arm-omap.cpp b/kernel/fiasco/src/kern/arm/bsp/omap/mem_layout-arm-omap.cpp
new file mode 100644 (file)
index 0000000..b7dec0f
--- /dev/null
@@ -0,0 +1,75 @@
+INTERFACE [arm && omap3_35x]: //-------------------------------------------
+
+EXTENSION class Mem_layout
+{
+public:
+  enum Phys_layout_omap3_35x : Address {
+    Wkup_cm_phys_base        = 0x48004c00,
+    L4_addr_prot_phys_base   = 0x48040000,
+    Uart1_phys_base          = 0x4806a000,
+    Gptimer10_phys_base      = 0x48086000,
+
+    Intc_phys_base           = 0x48200000,
+
+    Prm_global_reg_phys_base = 0x48307200,
+    Timer1ms_phys_base       = 0x48318000,
+
+    Uart3_phys_base          = 0x49020000,
+  };
+};
+
+INTERFACE [arm && omap3_35xevm]: //----------------------------------------
+
+EXTENSION class Mem_layout
+{
+public:
+  enum Phys_layout_omap3_35xevm : Address {
+    Uart_phys_base           = Uart1_phys_base,
+  };
+};
+
+INTERFACE [arm && omap3_beagleboard]: //-----------------------------------
+
+EXTENSION class Mem_layout
+{
+public:
+  enum Phys_layout_omap3_beagleboard : Address {
+    Uart_phys_base           = Uart3_phys_base,
+  };
+};
+
+INTERFACE [arm && omap3_am33xx]: //----------------------------------------
+
+EXTENSION class Mem_layout
+{
+public:
+  enum Phys_layout_omap3_335x : Address {
+    Cm_per_phys_base         = 0x44e00000,
+    Cm_wkup_phys_base        = 0x44e00400,
+    Cm_dpll_phys_base        = 0x44e00500,
+    Timergen_phys_base       = 0x44e05000, // DMTIMER0
+    Timer1ms_phys_base       = 0x44e31000,
+    Uart1_phys_base          = 0x44e09000,
+    Prm_global_reg_phys_base = 0x48107200,
+    Intc_phys_base           = 0x48200000,
+    Uart_phys_base           = Uart1_phys_base,
+  };
+};
+
+INTERFACE [arm && omap4]: //-----------------------------------------------
+
+EXTENSION class Mem_layout
+{
+public:
+  enum Phys_layout_omap4_pandaboard : Address {
+    Uart_phys_base          = 0x48020000,
+    Mp_scu_phys_base        = 0x48240000,
+    Gic_cpu_phys_base       = 0x48240100,
+    Gic_dist_phys_base      = 0x48241000,
+    L2cxx0_phys_base        = 0x48242000,
+
+    __Timer                 = 0x48240600,
+
+    Prm_phys_base           = 0x4a306000,
+  };
+};
diff --git a/kernel/fiasco/src/kern/arm/bsp/omap/outer_cache-arm-omap.cpp b/kernel/fiasco/src/kern/arm/bsp/omap/outer_cache-arm-omap.cpp
new file mode 100644 (file)
index 0000000..65f5847
--- /dev/null
@@ -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/omap/pic-arm-gic-omap4.cpp b/kernel/fiasco/src/kern/arm/bsp/omap/pic-arm-gic-omap4.cpp
new file mode 100644 (file)
index 0000000..be34ed8
--- /dev/null
@@ -0,0 +1,41 @@
+INTERFACE [arm && pic_gic && omap4]:
+
+#include "gic.h"
+
+// ------------------------------------------------------------------------
+IMPLEMENTATION [arm && pic_gic && omap4]:
+
+#include "irq_mgr_multi_chip.h"
+#include "kmem.h"
+
+IMPLEMENT FIASCO_INIT
+void
+Pic::init()
+{
+  typedef Irq_mgr_multi_chip<8> M;
+
+  M *m = new Boot_object<M>(1);
+
+  gic.construct(Kmem::mmio_remap(Mem_layout::Gic_cpu_phys_base),
+                Kmem::mmio_remap(Mem_layout::Gic_dist_phys_base));
+  m->add_chip(0, gic, gic->nr_irqs());
+
+  Irq_mgr::mgr = m;
+}
+
+IMPLEMENT inline
+Pic::Status Pic::disable_all_save()
+{ return 0; }
+
+IMPLEMENT inline
+void Pic::restore_all(Status)
+{}
+
+// ------------------------------------------------------------------------
+IMPLEMENTATION [arm && mp && pic_gic && omap4]:
+
+PUBLIC static
+void Pic::init_ap(Cpu_number)
+{
+  gic->init_ap();
+}
diff --git a/kernel/fiasco/src/kern/arm/bsp/omap/pic-arm-omap3.cpp b/kernel/fiasco/src/kern/arm/bsp/omap/pic-arm-omap3.cpp
new file mode 100644 (file)
index 0000000..1e24961
--- /dev/null
@@ -0,0 +1,176 @@
+INTERFACE [arm && omap3]:
+
+#include "kmem.h"
+
+class Irq_base;
+
+EXTENSION class Pic
+{
+public:
+};
+
+INTERFACE [arm && omap3_35x]: //-------------------------------------------
+
+EXTENSION class Pic
+{
+public:
+  enum { Num_irqs                 = 96, };
+};
+
+INTERFACE [arm && omap3_am33xx]: //----------------------------------------
+
+EXTENSION class Pic
+{
+public:
+  enum { Num_irqs                 = 128, };
+};
+
+//-------------------------------------------------------------------------
+IMPLEMENTATION [arm && omap3]:
+
+#include "assert.h"
+#include "config.h"
+#include "initcalls.h"
+#include "io.h"
+#include "irq_chip_generic.h"
+#include "irq_mgr.h"
+#include "mmio_register_block.h"
+
+#include <cstdio>
+
+class Irq_chip_arm_omap3 : public Irq_chip_gen, private Mmio_register_block
+{
+private:
+  enum
+  {
+    INTCPS_SYSCONFIG         = 0x010,
+    INTCPS_SYSSTATUS         = 0x014,
+    INTCPS_CONTROL           = 0x048,
+    INTCPS_TRESHOLD          = 0x068,
+    INTCPS_ITRn_base         = 0x080,
+    INTCPS_MIRn_base         = 0x084,
+    INTCPS_MIR_CLEARn_base   = 0x088,
+    INTCPS_MIR_SETn_base     = 0x08c,
+    INTCPS_ISR_SETn_base     = 0x090,
+    INTCPS_ISR_CLEARn_base   = 0x094,
+    INTCPS_PENDING_IRQn_base = 0x098,
+    INTCPS_ILRm_base         = 0x100,
+  };
+public:
+  unsigned set_mode(Mword, unsigned) { return Irq_base::Trigger_level; }
+  void set_cpu(Mword, Cpu_number) {}
+};
+
+PUBLIC inline
+Irq_chip_arm_omap3::Irq_chip_arm_omap3()
+: Irq_chip_gen(Pic::Num_irqs),
+  Mmio_register_block(Kmem::mmio_remap(Mem_layout::Intc_phys_base))
+{
+  // Reset
+  write<Mword>(2, INTCPS_SYSCONFIG);
+  while (!read<Mword>(INTCPS_SYSSTATUS))
+    ;
+
+  // auto-idle
+  write<Mword>(1, INTCPS_SYSCONFIG);
+
+  // disable treshold
+  write<Mword>(0xff, INTCPS_TRESHOLD);
+
+  // set priority for each interrupt line, lets take 0x20
+  // setting bit0 to 0 means IRQ (1 would mean FIQ)
+  for (int m = 0; m < Pic::Num_irqs; ++m)
+    write<Mword>(0x20 << 2, INTCPS_ILRm_base + (4 * m));
+
+  // mask all interrupts
+  for (int n = 0; n < 3; ++n)
+    write<Mword>(0xffffffff, INTCPS_MIR_SETn_base + 0x20 * n);
+}
+
+PUBLIC
+void
+Irq_chip_arm_omap3::mask(Mword irq)
+{
+  assert(cpu_lock.test());
+  write<Mword>(1 << (irq & 31), INTCPS_MIR_SETn_base + (irq & 0xe0));
+}
+
+PUBLIC
+void
+Irq_chip_arm_omap3::mask_and_ack(Mword irq)
+{
+  assert(cpu_lock.test());
+  write<Mword>(1 << (irq & 31), INTCPS_MIR_SETn_base + (irq & 0xe0));
+  write<Mword>(1, INTCPS_CONTROL);
+}
+
+PUBLIC
+void
+Irq_chip_arm_omap3::ack(Mword irq)
+{
+  (void)irq;
+  write<Mword>(1, INTCPS_CONTROL);
+}
+
+PUBLIC
+void
+Irq_chip_arm_omap3::unmask(Mword irq)
+{
+  assert(cpu_lock.test());
+  write<Mword>(1 << (irq & 31), INTCPS_MIR_CLEARn_base + (irq & 0xe0));
+}
+
+static Static_object<Irq_mgr_single_chip<Irq_chip_arm_omap3> > mgr;
+
+IMPLEMENT FIASCO_INIT
+void Pic::init()
+{
+  Irq_mgr::mgr = mgr.construct();
+}
+
+IMPLEMENT inline
+Pic::Status Pic::disable_all_save()
+{ return 0; }
+
+IMPLEMENT inline
+void Pic::restore_all(Status)
+{}
+
+PUBLIC inline
+Unsigned32 Irq_chip_arm_omap3::pending()
+{
+  for (int n = 0; n < (Pic::Num_irqs >> 5); ++n)
+    {
+      unsigned long x = read<Mword>(INTCPS_PENDING_IRQn_base + 0x20 * n);
+      for (int i = 0; i < 32; ++i)
+        if (x & (1 << i))
+          return i + n * 32;
+    }
+  return 0;
+}
+
+extern "C"
+void irq_handler()
+{
+  Unsigned32 i;
+  while ((i = mgr->c.pending()))
+    mgr->c.handle_irq<Irq_chip_arm_omap3>(i, 0);
+}
+
+// ------------------------------------------------------------------------
+IMPLEMENTATION [arm && omap3 && arm_em_tz]:
+
+PUBLIC static
+void
+Pic::set_pending_irq(unsigned group32num, Unsigned32 val)
+{
+  printf("%s(%d, %x): Not implemented\n", __func__, group32num, val);
+}
+
+//-------------------------------------------------------------------------
+IMPLEMENTATION [debug && omap3]:
+
+PUBLIC
+char const *
+Irq_chip_arm_omap3::chip_type() const
+{ return "HW OMAP3 IRQ"; }
diff --git a/kernel/fiasco/src/kern/arm/bsp/omap/platform_control-arm-omap4.cpp b/kernel/fiasco/src/kern/arm/bsp/omap/platform_control-arm-omap4.cpp
new file mode 100644 (file)
index 0000000..fb78bad
--- /dev/null
@@ -0,0 +1,52 @@
+INTERFACE [arm && mp && omap4]:
+#include "types.h"
+
+IMPLEMENTATION [arm && mp && omap4]:
+
+#include "io.h"
+#include "kmem.h"
+#include "mmio_register_block.h"
+
+PRIVATE static
+void
+Platform_control::aux(unsigned cmd, Mword arg0, Mword arg1)
+{
+  register unsigned long r0  asm("r0")  = arg0;
+  register unsigned long r1  asm("r1")  = arg1;
+  register unsigned long r12 asm("r12") = cmd;
+
+  asm volatile("dsb; smc #0"
+               : : "r" (r0), "r" (r1), "r" (r12)
+               : "r2", "r3", "r4", "r5", "r6",
+                 "r7", "r8", "r9", "r10", "r11", "lr", "memory");
+}
+
+PUBLIC static
+void
+Platform_control::boot_ap_cpus(Address phys_tramp_mp_addr)
+{
+  // two possibilities available, the memory mapped only in later board
+  // revisions
+  if (1)
+    {
+      enum {
+        AUX_CORE_BOOT_0 = 0x104,
+        AUX_CORE_BOOT_1 = 0x105,
+      };
+      aux(AUX_CORE_BOOT_1, phys_tramp_mp_addr, 0);
+      asm volatile("dsb; sev" : : : "memory");
+      aux(AUX_CORE_BOOT_0, 0x200, 0xfffffdff);
+    }
+  else
+    {
+      enum {
+        AUX_CORE_BOOT_0 = 0x00,
+        AUX_CORE_BOOT_1 = 0x04,
+      };
+      Mmio_register_block aux(Kmem::mmio_remap(0x48281800));
+      aux.write<Mword>(phys_tramp_mp_addr, AUX_CORE_BOOT_1);
+      asm volatile("dsb; sev" : : : "memory");
+      aux.modify<Mword>(0x200, 0xfffffdff, AUX_CORE_BOOT_0);
+    }
+}
+
diff --git a/kernel/fiasco/src/kern/arm/bsp/omap/reset-arm-omap.cpp b/kernel/fiasco/src/kern/arm/bsp/omap/reset-arm-omap.cpp
new file mode 100644 (file)
index 0000000..6107550
--- /dev/null
@@ -0,0 +1,54 @@
+IMPLEMENTATION [arm && omap3_35x]: //--------------------------------------
+
+#include "io.h"
+#include "kmem.h"
+
+void __attribute__ ((noreturn))
+platform_reset(void)
+{
+  enum
+  {
+    PRM_RSTCTRL = Mem_layout::Prm_global_reg_phys_base + 0x50,
+  };
+
+  Io::write<Mword>(2, Kmem::mmio_remap(PRM_RSTCTRL));
+
+  for (;;)
+    ;
+}
+
+IMPLEMENTATION [arm && omap3_am33xx]: //-----------------------------------
+
+#include "io.h"
+#include "kmem.h"
+
+void __attribute__ ((noreturn))
+platform_reset(void)
+{
+  enum { PRM_RSTCTRL = 0x44e00F00, };
+
+  Io::write<Mword>(1, Kmem::mmio_remap(PRM_RSTCTRL));
+
+  for (;;)
+    ;
+}
+
+IMPLEMENTATION [arm && omap4]: //------------------------------------------
+
+#include "io.h"
+#include "kmem.h"
+
+void __attribute__ ((noreturn))
+platform_reset(void)
+{
+  enum
+    {
+      DEVICE_PRM  = Mem_layout::Prm_phys_base + 0x1b00,
+      PRM_RSTCTRL = DEVICE_PRM + 0,
+    };
+
+  Io::write<Mword>(1, Kmem::mmio_remap(PRM_RSTCTRL));
+
+  for (;;)
+    ;
+}
diff --git a/kernel/fiasco/src/kern/arm/bsp/omap/timer-arm-mptimer-omap4.cpp b/kernel/fiasco/src/kern/arm/bsp/omap/timer-arm-mptimer-omap4.cpp
new file mode 100644 (file)
index 0000000..b721598
--- /dev/null
@@ -0,0 +1,8 @@
+// --------------------------------------------------------------------------
+INTERFACE [arm && mptimer && omap4_pandaboard]:
+
+EXTENSION class Timer
+{
+private:
+  static Mword interval() { return 499999; }
+};
diff --git a/kernel/fiasco/src/kern/arm/bsp/omap/timer-arm-omap3.cpp b/kernel/fiasco/src/kern/arm/bsp/omap/timer-arm-omap3.cpp
new file mode 100644 (file)
index 0000000..8573a4b
--- /dev/null
@@ -0,0 +1,152 @@
+// --------------------------------------------------------------------------
+INTERFACE [arm && omap3_35x]:
+
+#include "timer_omap_1mstimer.h"
+#include "mem_layout.h"
+
+EXTENSION class Timer
+{
+public:
+  static unsigned irq() { return 37; }
+
+private:
+  enum {
+    CM_CLKSEL_WKUP = Mem_layout::Wkup_cm_phys_base + 0x40,
+  };
+
+  static Static_object<Timer_omap_1mstimer> _timer;
+};
+
+INTERFACE [arm && omap3_am33xx]: //----------------------------------------
+
+#include "timer_omap_1mstimer.h"
+#include "timer_omap_gentimer.h"
+
+EXTENSION class Timer
+{
+public:
+  static unsigned irq()
+  {
+    switch (type())
+      {
+      case Timer0: default: return 66;
+      case Timer1_1ms: return 67;
+      }
+  }
+
+private:
+  enum Timer_type { Timer0, Timer1_1ms };
+  static Timer_type type() { return Timer1_1ms; }
+  enum {
+    CM_WKUP_CLKSTCTRL         = 0x00,
+    CM_WKUP_TIMER0_CLKCTRL    = 0x10,
+    CM_WKUP_TIMER1_CLKCTRL    = 0xc4,
+    CLKSEL_TIMER1MS_CLK       = 0x28,
+
+    CLKSEL_TIMER1MS_CLK_OSC   = 0,
+    CLKSEL_TIMER1MS_CLK_32KHZ = 1,
+    CLKSEL_TIMER1MS_CLK_VALUE = CLKSEL_TIMER1MS_CLK_OSC,
+  };
+  static Static_object<Timer_omap_1mstimer> _timer;
+  static Static_object<Timer_omap_gentimer> _gentimer;
+};
+
+IMPLEMENTATION [omap3]: // ------------------------------------------------
+
+Static_object<Timer_omap_1mstimer> Timer::_timer;
+
+// -----------------------------------------------------------------------
+IMPLEMENTATION [arm && omap3_35x]:
+
+#include "kmem.h"
+
+IMPLEMENT
+void
+Timer::init(Cpu_number)
+{
+  // select 32768 Hz input to GPTimer1 (timer1 only!)
+  Mmio_register_block(Kmem::mmio_remap(CM_CLKSEL_WKUP)).modify(0, 1, 0);
+  _timer.construct(true);
+}
+
+PUBLIC static inline
+void
+Timer::acknowledge()
+{
+  _timer->acknowledge();
+}
+
+// -----------------------------------------------------------------------
+IMPLEMENTATION [arm && omap3_am33xx]:
+
+#include "kmem.h"
+#include "mem_layout.h"
+
+Static_object<Timer_omap_gentimer> Timer::_gentimer;
+
+IMPLEMENT
+void
+Timer::init(Cpu_number)
+{
+  Mmio_register_block wkup(Kmem::mmio_remap(Mem_layout::Cm_wkup_phys_base));
+  Mmio_register_block clksel(Kmem::mmio_remap(Mem_layout::Cm_dpll_phys_base));
+  switch (type())
+    {
+    case Timer1_1ms:
+      // enable DMTIMER1_1MS
+      wkup.write<Mword>(2, CM_WKUP_TIMER1_CLKCTRL);
+      wkup.read<Mword>(CM_WKUP_TIMER1_CLKCTRL);
+      clksel.write<Mword>(CLKSEL_TIMER1MS_CLK_VALUE, CLKSEL_TIMER1MS_CLK);
+      for (int i = 0; i < 1000000; ++i) // instead, poll proper reg
+        asm volatile("" : : : "memory");
+
+      _timer.construct(CLKSEL_TIMER1MS_CLK_VALUE == CLKSEL_TIMER1MS_CLK_32KHZ);
+      break;
+    case Timer0:
+      wkup.write<Mword>(2, CM_WKUP_TIMER0_CLKCTRL);
+      _gentimer.construct();
+      break;
+    }
+}
+
+PUBLIC static inline
+void Timer::acknowledge()
+{
+  if (type() == Timer1_1ms)
+    _timer->acknowledge();
+  else
+    _gentimer->acknowledge();
+}
+
+// -----------------------------------------------------------------------
+IMPLEMENTATION [arm && omap3]:
+
+#include "config.h"
+#include "kip.h"
+
+static inline
+Unsigned64
+Timer::timer_to_us(Unsigned32 /*cr*/)
+{ return 0; }
+
+static inline
+Unsigned64
+Timer::us_to_timer(Unsigned64 us)
+{ (void)us; return 0; }
+
+IMPLEMENT inline
+void
+Timer::update_one_shot(Unsigned64 wakeup)
+{
+  (void)wakeup;
+}
+
+IMPLEMENT inline NEEDS["config.h", "kip.h"]
+Unsigned64
+Timer::system_clock()
+{
+  if (Config::Scheduler_one_shot)
+    return 0;
+  else
+    return Kip::k()->clock;
+}
diff --git a/kernel/fiasco/src/kern/arm/bsp/omap/timer_omap_1mstimer.cpp b/kernel/fiasco/src/kern/arm/bsp/omap/timer_omap_1mstimer.cpp
new file mode 100644 (file)
index 0000000..6936c5b
--- /dev/null
@@ -0,0 +1,112 @@
+INTERFACE [omap3]: // ------------------------------------------------
+
+#include "mmio_register_block.h"
+
+class Timer_omap_1mstimer : private Mmio_register_block
+{
+private:
+  enum {
+    TIDR      = 0x000, // IP revision code
+    TIOCP_CFG = 0x010, // config
+    TISTAT    = 0x014, // non-interrupt status
+    TISR      = 0x018, // pending interrupts
+    TIER      = 0x01c, // enable/disable of interrupt events
+    TWER      = 0x020, // wake-up features
+    TCLR      = 0x024, // optional features
+    TCRR      = 0x028, // internal counter
+    TLDR      = 0x02c, // timer load value
+    TTGR      = 0x030, // trigger reload by writing
+    TWPS      = 0x034, // write-posted pending
+    TMAR      = 0x038, // compare value
+    TCAR1     = 0x03c, // first capture value of the counter
+    TCAR2     = 0x044, // second capture value of the counter
+    TPIR      = 0x048, // positive inc, gpt1, 2 and 10 only
+    TNIR      = 0x04C, // negative inc, gpt1, 2 and 10 only
+  };
+};
+
+
+IMPLEMENTATION [omap3]: // ------------------------------------------------
+
+#include <cassert>
+#include <cstdio>
+
+#include "config.h"
+#include "kmem.h"
+#include "mem_layout.h"
+
+PRIVATE static
+void
+Timer_omap_1mstimer::get_timer_values_32khz(unsigned &reload, int &tpir, int &tnir)
+{
+  tpir   = 232000;
+  tnir   = -768000;
+  reload = 0xffffffe0;
+  assert(Config::Scheduler_granularity == 1000); // need to adapt here
+}
+
+PUBLIC explicit
+Timer_omap_1mstimer::Timer_omap_1mstimer(bool f_32khz)
+: Mmio_register_block(Kmem::mmio_remap(Mem_layout::Timer1ms_phys_base))
+{
+  // reset
+  write<Mword>(1, TIOCP_CFG);
+  while (!read<Mword>(TISTAT))
+    ;
+  // reset done
+
+  // overflow mode
+  write<Mword>(0x2, TIER);
+  // no wakeup
+  write<Mword>(0x0, TWER);
+
+  // program timer frequency
+  unsigned val;
+  int tpir, tnir;
+  get_timer_values(val, tpir, tnir, f_32khz);
+
+  write<Mword>(tpir, TPIR); // gpt1, gpt2 and gpt10 only
+  write<Mword>(tnir, TNIR); // gpt1, gpt2 and gpt10 only
+  write<Mword>(val,  TCRR);
+  write<Mword>(val,  TLDR);
+
+  // auto-reload + enable
+  write<Mword>(1 | 2, TCLR);
+}
+
+PUBLIC inline
+void
+Timer_omap_1mstimer::acknowledge()
+{
+  write<Mword>(2, TISR);
+}
+
+
+IMPLEMENTATION [arm && omap3_am33xx]: // ----------------------------------
+
+PRIVATE static
+void
+Timer_omap_1mstimer::get_timer_values(unsigned &reload, int &tpir, int &tnir,
+                                      bool f_32khz)
+{
+  if (f_32khz)
+    get_timer_values_32khz(reload, tpir, tnir);
+  else
+    {
+      tpir   = 100000;
+      tnir   = 0;
+      reload = ~0 - 24 * Config::Scheduler_granularity + 1; // 24 MHz
+    }
+}
+
+IMPLEMENTATION [arm && omap3_35x]: // -------------------------------------
+
+PRIVATE static
+void
+Timer_omap_1mstimer::get_timer_values(unsigned &reload, int &tpir, int &tnir, bool)
+{
+  get_timer_values_32khz(reload, tpir, tnir);
+}
+
+
+
diff --git a/kernel/fiasco/src/kern/arm/bsp/omap/timer_omap_gentimer.cpp b/kernel/fiasco/src/kern/arm/bsp/omap/timer_omap_gentimer.cpp
new file mode 100644 (file)
index 0000000..b40f445
--- /dev/null
@@ -0,0 +1,61 @@
+INTERFACE [arm]: //----------------------------------------
+
+#include "mmio_register_block.h"
+
+class Timer_omap_gentimer : private Mmio_register_block
+{
+public:
+  enum
+  {
+    TIDR          = 0x00, // ID
+    TIOCP_CFG     = 0x10, // config
+    EOI           = 0x20,
+    IRQSTATUS     = 0x28,
+    IRQENABLE_SET = 0x2c,
+    IRQWAKEEN     = 0x34,
+    TCLR          = 0x38,
+    TCRR          = 0x3c,
+    TLDR          = 0x40,
+  };
+};
+
+IMPLEMENTATION [arm]: // ----------------------------------
+
+#include "kmem.h"
+#include "mem_layout.h"
+
+PUBLIC
+Timer_omap_gentimer::Timer_omap_gentimer()
+: Mmio_register_block(Kmem::mmio_remap(Mem_layout::Timergen_phys_base))
+{
+  // Mword idr = Io::read<Mword>(TIDR);
+  // older timer: idr >> 16 == 0
+  // newer timer: idr >> 16 != 0
+
+  // reset
+  write<Mword>(1, TIOCP_CFG);
+  while (read<Mword>(TIOCP_CFG) & 1)
+    ;
+  // reset done
+
+  // overflow mode
+  write<Mword>(2, IRQENABLE_SET);
+  // no wakeup
+  write<Mword>(0, IRQWAKEEN);
+
+  // program 1000 Hz timer frequency
+  // (FFFFFFFFh - TLDR + 1) * timer-clock-period * clock-divider(ps)
+  Mword val = 0xffffffda;
+  write<Mword>(val, TLDR);
+  write<Mword>(val, TCRR);
+
+  write<Mword>(1 | 2, TCLR);
+}
+
+PUBLIC inline
+void
+Timer_omap_gentimer::acknowledge()
+{
+  write<Mword>(2, IRQSTATUS);
+  write<Mword>(0, EOI);
+}
diff --git a/kernel/fiasco/src/kern/arm/bsp/omap/uart-arm-omap.cpp b/kernel/fiasco/src/kern/arm/bsp/omap/uart-arm-omap.cpp
new file mode 100644 (file)
index 0000000..d48bb10
--- /dev/null
@@ -0,0 +1,24 @@
+IMPLEMENTATION [arm && (omap3_35xevm || omap3_am33xx)]: // ----------------
+
+IMPLEMENT int Uart::irq() const { return 72; }
+
+IMPLEMENTATION [arm && omap3_beagleboard]: // -----------------------------
+
+IMPLEMENT int Uart::irq() const { return 74; }
+
+IMPLEMENTATION [arm && omap4_pandaboard]: // ------------------------------
+
+IMPLEMENT int Uart::irq() const { return 32 + 74; }
+
+IMPLEMENTATION: // --------------------------------------------------------
+
+#include "mem_layout.h"
+#include "uart_omap35x.h"
+
+IMPLEMENT Address Uart::base() const { return Mem_layout::Uart_phys_base; }
+
+IMPLEMENT L4::Uart *Uart::uart()
+{
+  static L4::Uart_omap35x uart;
+  return &uart;
+}
index f01396bc4ce58212fa269df61f0726c90fb77547..b9ff15da296b84d1b07842d498b64f36e373d610 100644 (file)
@@ -6,12 +6,12 @@ EXTENSION class Pic
 {
 public:
   enum {
-    ICIP = Kmem::Pic_map_base + 0x000000,
-    ICMR = Kmem::Pic_map_base + 0x000004,
-    ICLR = Kmem::Pic_map_base + 0x000008,
-    ICCR = Kmem::Pic_map_base + 0x000014,
-    ICFP = Kmem::Pic_map_base + 0x00000c,
-    ICPR = Kmem::Pic_map_base + 0x000010,
+    ICIP = 0x000000,
+    ICMR = 0x000004,
+    ICLR = 0x000008,
+    ICCR = 0x000014,
+    ICFP = 0x00000c,
+    ICPR = 0x000010,
   };
 };
 
@@ -23,39 +23,52 @@ EXTENSION class Pic
 {
 public:
   enum {
-    ICIP = Kmem::Pic_map_base + 0x00000,
-    ICMR = Kmem::Pic_map_base + 0x00004,
-    ICLR = Kmem::Pic_map_base + 0x00008,
-    ICCR = Kmem::Pic_map_base + 0x0000c,
-    ICFP = Kmem::Pic_map_base + 0x00010,
-    ICPR = Kmem::Pic_map_base + 0x00020,
+    ICIP = 0x00000,
+    ICMR = 0x00004,
+    ICLR = 0x00008,
+    ICCR = 0x0000c,
+    ICFP = 0x00010,
+    ICPR = 0x00020,
   };
 };
 
 // -------------------------------------------------------------
 IMPLEMENTATION [arm && (sa1100 || pxa)]:
 
+#include "assert.h"
+#include "initcalls.h"
 #include "config.h"
-#include "io.h"
-#include "irq.h"
 #include "irq_chip_generic.h"
 #include "irq_mgr.h"
+#include "mmio_register_block.h"
 
-class Chip : public Irq_chip_gen
+class Chip : public Irq_chip_gen, private Mmio_register_block
 {
 public:
-  Chip() : Irq_chip_gen(32) {}
   unsigned set_mode(Mword, unsigned) { return Irq_base::Trigger_level; }
-  void set_cpu(Mword, unsigned) {}
+  void set_cpu(Mword, Cpu_number) {}
   void ack(Mword) { /* ack is empty */ }
 };
 
+PUBLIC inline
+Chip::Chip()
+: Irq_chip_gen(32),
+  Mmio_register_block(Kmem::mmio_remap(Mem_layout::Pic_phys_base))
+{
+  // only unmasked interrupts wakeup from idle
+  write<Mword>(0x01, Pic::ICCR);
+  // mask all interrupts
+  write<Mword>(0x00, Pic::ICMR);
+  // all interrupts are IRQ's (no FIQ)
+  write<Mword>(0x00, Pic::ICLR);
+}
+
 PUBLIC
 void
 Chip::mask(Mword irq)
 {
   assert(cpu_lock.test());
-  Io::write(Io::read<Mword>(Pic::ICMR) & ~(1 << irq), Pic::ICMR);
+  modify<Mword>(0, 1 << irq, Pic::ICMR);
 }
 
 PUBLIC
@@ -63,7 +76,7 @@ void
 Chip::mask_and_ack(Mword irq)
 {
   assert (cpu_lock.test());
-  Io::write(Io::read<Mword>(Pic::ICMR) & ~(1 << irq), Pic::ICMR);
+  modify<Mword>(0, 1 << irq, Pic::ICMR);
   // ack is empty
 }
 
@@ -71,48 +84,58 @@ PUBLIC
 void
 Chip::unmask(Mword irq)
 {
-  Io::write(Io::read<Mword>(Pic::ICMR) | (1 << irq), Pic::ICMR);
+  modify<Mword>(1 << irq, 0, Pic::ICMR);
 }
 
+// for JDB only
+PUBLIC inline
+Mword
+Chip::disable_all_save()
+{
+  Mword s = read<Mword>(Pic::ICMR);
+  write<Mword>(0, Pic::ICMR);
+  return s;
+}
+
+// for JDB only
+PUBLIC inline
+void
+Chip::restore_all(Mword s)
+{
+  write(s, Pic::ICMR);
+}
+
+
 static Static_object<Irq_mgr_single_chip<Chip> > mgr;
 
 IMPLEMENT FIASCO_INIT
 void Pic::init()
 {
   Irq_mgr::mgr = mgr.construct();
-
-  // only unmasked interrupts wakeup from idle
-  Io::write(0x01, ICCR);
-  // mask all interrupts
-  Io::write(0x00, ICMR);
-  // all interrupts are IRQ's (no FIQ)
-  Io::write(0x00, ICLR);
 }
 
-IMPLEMENT inline NEEDS["io.h"]
+// for JDB only
+IMPLEMENT
 Pic::Status Pic::disable_all_save()
-{
-  Status s = Io::read<Mword>(ICMR);
-  Io::write(0, ICMR);
-  return s;
-}
+{ return mgr->c.disable_all_save(); }
 
-IMPLEMENT inline NEEDS["io.h"]
-void Pic::restore_all(Status s)
+IMPLEMENT
+void
+Pic::restore_all(Status s)
 {
-  Io::write(s, ICMR);
+  mgr->c.restore_all(s);
 }
 
-PUBLIC static inline NEEDS["io.h"]
+PUBLIC inline
 Unsigned32 Chip::pending()
 {
-  return Io::read<Unsigned32>(Pic::ICIP);
+  return read<Unsigned32>(Pic::ICIP);
 }
 
 extern "C"
 void irq_handler()
 {
-  Unsigned32 i = Chip::pending();
+  Unsigned32 i = mgr->c.pending();
   if (i)
     mgr->c.handle_irq<Chip>(i, 0);
 }
index 1cfe0516ec3975b60d7b3ed4d32efbfb9a5e9e68..32b7198c008565b009bc02be7e360eaf3b4f32bd 100644 (file)
@@ -2,25 +2,28 @@
 INTERFACE [arm && (sa1100 || pxa)]:
 
 #include "kmem.h"
+#include "mmio_register_block.h"
 
-EXTENSION class Timer
+EXTENSION class Timer : private Mmio_register_block
 {
 public:
   static unsigned irq() { return 26; }
 
 private:
   enum {
-    OSMR0 = Kmem::Timer_map_base + 0x00,
-    OSMR1 = Kmem::Timer_map_base + 0x04,
-    OSMR2 = Kmem::Timer_map_base + 0x08,
-    OSMR3 = Kmem::Timer_map_base + 0x0c,
-    OSCR  = Kmem::Timer_map_base + 0x10,
-    OSSR  = Kmem::Timer_map_base + 0x14,
-    OWER  = Kmem::Timer_map_base + 0x18,
-    OIER  = Kmem::Timer_map_base + 0x1c,
+    OSMR0 = 0x00,
+    OSMR1 = 0x04,
+    OSMR2 = 0x08,
+    OSMR3 = 0x0c,
+    OSCR  = 0x10,
+    OSSR  = 0x14,
+    OWER  = 0x18,
+    OIER  = 0x1c,
 
     Timer_diff = (36864 * Config::Scheduler_granularity) / 10000, // 36864MHz*1ms
   };
+
+  static Static_object<Timer> _timer;
 };
 
 
@@ -30,16 +33,24 @@ IMPLEMENTATION [arm && (sa1100 || pxa)]:
 #include "config.h"
 #include "kip.h"
 #include "pic.h"
-#include "io.h"
+
+Static_object<Timer> Timer::_timer;
+
+PUBLIC
+Timer::Timer()
+: Mmio_register_block(Kmem::mmio_remap(Mem_layout::Timer_phys_base))
+{
+  write<Mword>(1,          OIER); // enable OSMR0
+  write<Mword>(0,          OWER); // disable Watchdog
+  write<Mword>(Timer_diff, OSMR0);
+  write<Mword>(0,          OSCR); // set timer counter to zero
+  write<Mword>(~0U,        OSSR); // clear all status bits
+}
 
 IMPLEMENT
-void Timer::init(unsigned)
+void Timer::init(Cpu_number)
 {
-  Io::write(1,          OIER); // enable OSMR0
-  Io::write(0,          OWER); // disable Watchdog
-  Io::write<Mword>(Timer_diff, OSMR0);
-  Io::write(0,          OSCR); // set timer counter to zero
-  Io::write(~0U,        OSSR); // clear all status bits
+  _timer.construct();
 }
 
 static inline
@@ -52,32 +63,38 @@ Unsigned64
 Timer::us_to_timer(Unsigned64 us)
 { return (us * 60398) >> 14; }
 
-PUBLIC static inline NEEDS["io.h", "config.h", Timer::timer_to_us]
+PUBLIC inline NEEDS["config.h", Timer::timer_to_us]
 void
-Timer::acknowledge()
+Timer::ack()
 {
   if (Config::Scheduler_one_shot)
     {
-      Kip::k()->clock += timer_to_us(Io::read<Unsigned32>(OSCR));
+      Kip::k()->clock += timer_to_us(read<Unsigned32>(OSCR));
       //puts("Reset timer");
-      Io::write(0, OSCR);
-      Io::write(0xffffffff, OSMR0);
+      write<Mword>(0, OSCR);
+      write<Mword>(0xffffffff, OSMR0);
     }
   else
-    Io::write(0, OSCR);
-  Io::write(1, OSSR); // clear all status bits
+    write<Mword>(0, OSCR);
+  write<Mword>(1, OSSR); // clear all status bits
 
   // hmmm?
   //enable();
 }
+PUBLIC static inline NEEDS["config.h", Timer::timer_to_us]
+void
+Timer::acknowledge()
+{
+  _timer->ack();
+}
 
-IMPLEMENT inline NEEDS["kip.h", "io.h", Timer::timer_to_us, Timer::us_to_timer]
+IMPLEMENT inline NEEDS["kip.h", Timer::timer_to_us, Timer::us_to_timer]
 void
 Timer::update_one_shot(Unsigned64 wakeup)
 {
   Unsigned32 apic;
-  Kip::k()->clock += timer_to_us(Io::read<Unsigned32>(OSCR));
-  Io::write(0, OSCR);
+  Kip::k()->clock += timer_to_us(_timer->read<Unsigned32>(OSCR));
+  _timer->write(0, OSCR);
   Unsigned64 now = Kip::k()->clock;
 
   if (EXPECT_FALSE (wakeup <= now) )
@@ -95,16 +112,16 @@ Timer::update_one_shot(Unsigned64 wakeup)
 
   //printf("%15lld: Set Timer to %lld [%08x]\n", now, wakeup, apic);
 
-  Io::write(apic, OSMR0);
-  Io::write(1, OSSR); // clear all status bits
+  _timer->write<Mword>(apic, OSMR0);
+  _timer->write<Mword>(1, OSSR); // clear all status bits
 }
 
-IMPLEMENT inline NEEDS["config.h", "kip.h", "io.h", Timer::timer_to_us]
+IMPLEMENT inline NEEDS["config.h", "kip.h", Timer::timer_to_us]
 Unsigned64
 Timer::system_clock()
 {
   if (Config::Scheduler_one_shot)
-    return Kip::k()->clock + timer_to_us(Io::read<Unsigned32>(OSCR));
+    return Kip::k()->clock + timer_to_us(_timer->read<Unsigned32>(OSCR));
   else
     return Kip::k()->clock;
 }
index 6140684484960d96135f20de6a83efe49ec047d8..24569ce13fe75bf3608f2ddbf213f2a6cc75788a 100644 (file)
@@ -1,7 +1,7 @@
 # vim:set ft=make:
 
 PREPROCESS_PARTS        += pxa 16550 vcache armv5 generic_tickless_idle
-CONFIG_KERNEL_LOAD_ADDR := 0xa0000000
+RAM_PHYS_BASE           := 0xa0000000
 VPATH                   += kern/arm/bsp/pxa-sa
 
 uart_IMPL             += uart-16550 uart-16550-arm-pxa
index 836e3f6206b16b273be8be478eb94dbbe93981f3..1748923d990865c176efaa3e55204d3dfa7d3599 100644 (file)
@@ -1,20 +1,7 @@
 //-----------------------------------------------------------------------------
 INTERFACE [arm && pxa]:
-
+namespace Bootstrap {
 enum {
   Cache_flush_area = 0xa0100000, // XXX: hacky
 };
-
-//-----------------------------------------------------------------------------
-IMPLEMENTATION [arm && pxa]:
-
-void
-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_dev<Mem_layout::Devices0_phys_base>(pd, 0);
-  map_dev<Mem_layout::Devices1_phys_base>(pd, 1);
-  map_dev<Mem_layout::Devices2_phys_base>(pd, 2);
 }
index b3864f244c58b376da36d129ae5b2bf88766e369..ca1295ece291857b59cfa6633cde4b4e5d45f95b 100644 (file)
@@ -4,10 +4,12 @@ INTERFACE:
 EXTENSION class Kernel_uart { enum { Bsp_init_mode = Init_before_mmu }; };
 
 IMPLEMENTATION [arm && pxa && serial]:
+
+#include "kmem.h"
 #include "mem_layout.h"
 
 IMPLEMENT
 bool Kernel_uart::startup(unsigned port, int /*irq*/)
 {
-  return Uart::startup(Mem_layout::Uart_base, 22);
+  return Uart::startup(Kmem::mmio_remap(Mem_layout::Uart_phys_base), 22);
 }
index 2d1da9ccf573a7ee211511d122f1a2de9ab9fe87..cd1a678e4a7941d1f7fd7ec79e0b2deaa93eb276 100644 (file)
@@ -3,18 +3,10 @@ INTERFACE [arm-pxa]: //------------------------------------------------------
 EXTENSION class Mem_layout
 {
 public:
-  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 : Address {
-    Devices0_phys_base   = 0x40a00000,
-    Devices1_phys_base   = 0x40d00000,
-    Devices2_phys_base   = 0x40100000,
-    Sdram_phys_base      = 0xa0000000,
+  enum Phys_layout_pxa : Address {
+    Timer_phys_base      = 0x40a00000,
+    Pic_phys_base        = 0x40d00000,
+    Uart_phys_base       = 0x40100000,
     Flush_area_phys_base = 0xe0000000,
   };
 };
index bd5dba4ed33b08fe46ed02f47603e69bf3e2a78b..6eacd5e23ac8c96a93fad043d45616840aff25f3 100644 (file)
@@ -1,17 +1,21 @@
 IMPLEMENTATION [arm && pxa]:
 
-#include "timer.h"
-#include "io.h"
+#include "mem_layout.h"
+#include "mmio_register_block.h"
+#include "kmem.h"
 
 void __attribute__ ((noreturn))
 platform_reset(void)
 {
   enum {
-    OSCR  = Kmem::Timer_map_base + 0x10,
-    OWER  = Kmem::Timer_map_base + 0x18,
+    OSCR  = 0x10,
+    OWER  = 0x18,
   };
-  Io::write(1, OWER);
-  Io::write(0xffffff00, OSCR);
+
+  Mmio_register_block timer(Kmem::mmio_remap(Mem_layout::Timer_phys_base));
+
+  timer.write<Mword>(1, OWER);
+  timer.write<Mword>(0xffffff00, OSCR);
 
   for (;;)
     ;
index 1b42875bda1806cc43477ae039c60550abece47d..ae7601028c38563cd8767bae5e7bb45600e2cae7 100644 (file)
@@ -38,17 +38,27 @@ config PF_REALVIEW_VEXPRESS
        bool "Versatile Express"
        depends on PF_REALVIEW
        select CAN_ARM_CPU_CORTEX_A9
+       select CAN_ARM_CPU_CORTEX_A15
        help
          Choose for Versatile Express.
 
 endchoice
 
+config PF_REALVIEW_VEXPRESS_A9
+       def_bool y
+       depends on PF_REALVIEW_VEXPRESS && ARM_CORTEX_A9
+
+config PF_REALVIEW_VEXPRESS_A15
+       def_bool y
+       depends on PF_REALVIEW_VEXPRESS && ARM_CORTEX_A15
+
 choice
        prompt "Start of RAM (physical address)" if !PF_REALVIEW_EB
        default PF_REALVIEW_RAM_PHYS_BASE_0x0
 
 config PF_REALVIEW_RAM_PHYS_BASE_0x0
        bool "0x00000000"
+       depends on !ARM_CORTEX_A15
 
 config PF_REALVIEW_RAM_PHYS_BASE_0x2
        bool "0x20000000"
@@ -56,16 +66,22 @@ config PF_REALVIEW_RAM_PHYS_BASE_0x2
 
 config PF_REALVIEW_RAM_PHYS_BASE_0x6
        bool "0x60000000"
-       depends on PF_REALVIEW_VEXPRESS
+       depends on PF_REALVIEW_VEXPRESS_A9
 
 config PF_REALVIEW_RAM_PHYS_BASE_0x7
        bool "0x70000000"
        depends on PF_REALVIEW_PBX || PF_REALVIEW_PB11MP
+
+config PF_REALVIEW_RAM_PHYS_BASE_0x8
+       bool "0x80000000"
+       depends on PF_REALVIEW_VEXPRESS_A15
+
 endchoice
 
 config PF_REALVIEW_RAM_PHYS_BASE
        hex
-       default 0x0        if !PF_REALVIEW_RAM_PHYS_BASE_0x2 && !PF_REALVIEW_RAM_PHYS_BASE_0x6 && !PF_REALVIEW_RAM_PHYS_BASE_0x7
+       default 0x0        if !PF_REALVIEW_RAM_PHYS_BASE_0x2 && !PF_REALVIEW_RAM_PHYS_BASE_0x6 && !PF_REALVIEW_RAM_PHYS_BASE_0x7 && !PF_REALVIEW_RAM_PHYS_BASE_0x8
        default 0x20000000 if PF_REALVIEW_RAM_PHYS_BASE_0x2
        default 0x60000000 if PF_REALVIEW_RAM_PHYS_BASE_0x6
        default 0x70000000 if PF_REALVIEW_RAM_PHYS_BASE_0x7
+       default 0x80000000 if PF_REALVIEW_RAM_PHYS_BASE_0x8
index b4f28a20894a331c016b3516b303c031d2c64f9a..8871fa784460f40e7b4ac18bb195979d0433cdd4 100644 (file)
@@ -7,10 +7,14 @@ PREPROCESS_PARTS        += $(if $(CONFIG_PF_REALVIEW_EB),realview_eb)
 PREPROCESS_PARTS        += $(if $(CONFIG_PF_REALVIEW_PB11MP),realview_pb11mp)
 PREPROCESS_PARTS        += $(if $(CONFIG_PF_REALVIEW_PBX),realview_pbx)
 PREPROCESS_PARTS        += $(if $(CONFIG_PF_REALVIEW_VEXPRESS),realview_vexpress)
+PREPROCESS_PARTS        += $(if $(CONFIG_PF_REALVIEW_VEXPRESS_A9),realview_vexpress_a9)
+PREPROCESS_PARTS        += $(if $(CONFIG_PF_REALVIEW_VEXPRESS_A15),realview_vexpress_a15)
 PREPROCESS_PARTS        += generic_tickless_idle
-CONFIG_KERNEL_LOAD_ADDR := $(CONFIG_PF_REALVIEW_RAM_PHYS_BASE)
+RAM_PHYS_BASE           := $(CONFIG_PF_REALVIEW_RAM_PHYS_BASE)
 
-MPCORE_PHYS_BASE        := $(if $(CONFIG_PF_REALVIEW_VEXPRESS),0x1e000000,0x1f000000)
+MPCORE_PHYS_BASE-$(CONFIG_PF_REALVIEW_VEXPRESS_A9)  := 0x1e000000
+MPCORE_PHYS_BASE-$(CONFIG_PF_REALVIEW_VEXPRESS_A15) := 0x2c000000
+MPCORE_PHYS_BASE        := $(if $(MPCORE_PHYS_BASE-y),$(MPCORE_PHYS_BASE-y),0x1f000000)
 
 timer_IMPL            += timer-arm-realview
 ifeq ($(CONFIG_ARM_MPCORE)$(CONFIG_ARM_CORTEX_A9),)
@@ -20,7 +24,7 @@ else
   timer_IMPL          += timer-arm-mptimer timer-arm-mptimer-realview
 endif
 
-INTERFACES_KERNEL     += gic platform board_check-arm-realview
+INTERFACES_KERNEL     += gic platform board_check-arm-realview timer_sp804
 
 timer_tick_IMPL       += timer_tick-single-vector
 uart_IMPL             += uart-arm-realview
index 841f7f8803ce65a2ef4ee5a9fc6b6ba522fb751f..b5184a827f55b50698ca1578793eadc0afc03e8f 100644 (file)
@@ -57,18 +57,14 @@ IMPLEMENTATION [arm && realview]:
 #include "io.h"
 #include "static_init.h"
 #include "processor.h"
+#include "platform.h"
 
 #include <cstdio>
 
-enum
-{
-  SYS_ID = Kmem::System_regs_map_base + 0x0,
-};
-
 IMPLEMENT static FIASCO_INIT
 Mword
 Board_check::read_board_id()
-{ return Io::read<Mword>(SYS_ID); }
+{ return Platform::sys->read<Mword>(Platform::Sys::Id); }
 
 IMPLEMENT static FIASCO_INIT
 void
index 3c4c046bd57937abb1db373401b8e68e75a48249..e0cb618fa74de87f178f73bd0484590dfd183f95 100644 (file)
@@ -1,16 +1,6 @@
 INTERFACE [arm && realview]:
 
-#include "mem_layout.h"
-
+namespace Bootstrap {
 enum { Cache_flush_area = 0, };
-
-//-----------------------------------------------------------------------------
-IMPLEMENTATION [arm && realview]:
-
-void
-map_hw(void *pd)
-{
-  map_dev<Mem_layout::Devices0_phys_base>(pd, 0);
-  map_dev<Mem_layout::Devices1_phys_base>(pd, 1);
-  map_dev<Mem_layout::Devices2_phys_base>(pd, 2);
 }
+
index ec70d662bfbd316712c58f550eb51c2253030053..60fbffccb667adab6da74ef91470bc3a4d14c7b7 100644 (file)
@@ -2,14 +2,11 @@ INTERFACE [arm && realview]:
 
 #include "kmem.h"
 #include "l4_types.h"
+#include "platform.h"
 
 EXTENSION class Clock_base
 {
 protected:
-  enum {
-    SYS_24MHZ = Kmem::System_regs_map_base + 0x5c,
-  };
-
   typedef Mword Counter;
 };
 
@@ -23,7 +20,7 @@ IMPLEMENT inline NEEDS["io.h", <cstdio>]
 Clock::Counter
 Clock::read_counter() const
 {
-  return Io::read<Mword>(SYS_24MHZ);
+  return Platform::sys->read<Mword>(Platform::Sys::Cnt_24mhz);
 }
 
 IMPLEMENT inline
index d33d22446311de27d523d873758513bc680686f4..37e5655c1d9f6368b0db4fea72d0b77026d9179e 100644 (file)
@@ -6,35 +6,27 @@ EXTENSION class Mem_layout
 {
 public:
   enum Phys_layout_realview_all : Address {
-    Sdram_phys_base      = CONFIG_PF_REALVIEW_RAM_PHYS_BASE,
     Flush_area_phys_base = 0xe0000000,
   };
 };
 
 // ------------------------------------------------------------------------
-INTERFACE [arm && realview && (realview_eb || realview_pb11mp || realview_pbx || realview_vexpress)]:
+INTERFACE [arm && realview && (realview_eb || realview_pb11mp || realview_pbx || realview_vexpress_a9)]:
 
 #include "globalconfig.h"
 
 EXTENSION class Mem_layout
 {
 public:
-  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,
-    Uart1_map_base       = Devices0_map_base + 0x0000a000,
-    Uart2_map_base       = Devices0_map_base + 0x0000b000,
-    Uart3_map_base       = Devices0_map_base + 0x0000c000,
-    Timer0_map_base      = Devices0_map_base + 0x00011000,
-    Timer1_map_base      = Devices0_map_base + 0x00011020,
-    Timer2_map_base      = Devices0_map_base + 0x00012000,
-    Timer3_map_base      = Devices0_map_base + 0x00012020,
-    Uart_base            = Uart0_map_base,
-  };
-
   enum Phys_layout_realview : Address {
-    Devices0_phys_base   = 0x10000000,
+    Devices0_phys_base    = 0x10000000,
+    System_regs_phys_base = Devices0_phys_base,
+    System_ctrl_phys_base = Devices0_phys_base + 0x00001000,
+    Uart_phys_base        = Devices0_phys_base + 0x00009000,
+    Timer0_phys_base      = Devices0_phys_base + 0x00011000,
+    //Timer1_phys_base      = Devices0_phys_base + 0x00011020,
+    //Timer2_phys_base      = Devices0_phys_base + 0x00012000,
+    //Timer3_phys_base      = Devices0_phys_base + 0x00012020,
   };
 };
 
@@ -44,14 +36,9 @@ INTERFACE [arm && realview && realview_eb && !(mpcore || armca9)]:
 EXTENSION class Mem_layout
 {
 public:
-  enum Virt_layout_realview_single : Address {
-    Gic_cpu_map_base    = Devices0_map_base  + 0x00040000,
-    Gic_dist_map_base   = Gic_cpu_map_base   + 0x00001000,
-  };
-
   enum Phys_layout_realview_single : Address {
-    Devices1_phys_base   = Invalid_address,
-    Devices2_phys_base   = Invalid_address,
+    Gic_cpu_phys_base    = Devices0_phys_base  + 0x00040000,
+    Gic_dist_phys_base   = Gic_cpu_phys_base   + 0x00001000,
   };
 };
 
@@ -61,26 +48,23 @@ INTERFACE [arm && realview && realview_eb && (mpcore || armca9)]:
 EXTENSION class Mem_layout
 {
 public:
-  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,
-    L2cxx0_map_base      = Devices1_map_base + 0x00002000,
-
-    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 : Address {
+    Gic1_cpu_phys_base    = Devices0_phys_base + 0x00040000,
+    Gic1_dist_phys_base   = Devices0_phys_base + 0x00041000,
+#if 0
+    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,
+#endif
     Devices1_phys_base   = 0x10100000,
-    Devices2_phys_base   = Invalid_address,
+
+    Mp_scu_phys_base      = Devices1_phys_base,
+    Gic_cpu_phys_base     = Devices1_phys_base + 0x00000100,
+    Gic_dist_phys_base    = Devices1_phys_base + 0x00001000,
+    L2cxx0_phys_base      = Devices1_phys_base + 0x00002000,
   };
 };
 
@@ -90,19 +74,16 @@ INTERFACE [arm && realview && realview_pb11mp]:
 EXTENSION class Mem_layout
 {
 public:
-  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,
-    L2cxx0_map_base      = Devices1_map_base + 0x00002000,
-
-    Gic1_cpu_map_base    = Devices2_map_base,
-    Gic1_dist_map_base   = Devices2_map_base + 0x00001000,
-  };
-
   enum Phys_layout_realview_pb11mp : Address {
     Devices1_phys_base   = 0x1f000000,
+    Mp_scu_phys_base      = Devices1_phys_base,
+    Gic_cpu_phys_base     = Devices1_phys_base + 0x00000100,
+    Gic_dist_phys_base    = Devices1_phys_base + 0x00001000,
+    L2cxx0_phys_base      = Devices1_phys_base + 0x00002000,
+
     Devices2_phys_base   = 0x1e000000,
+    Gic1_cpu_phys_base    = Devices2_phys_base,
+    Gic1_dist_phys_base   = Devices2_phys_base + 0x00001000,
   };
 };
 
@@ -112,39 +93,58 @@ INTERFACE [arm && realview && realview_pbx]:
 EXTENSION class Mem_layout
 {
 public:
-  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,
-    L2cxx0_map_base      = Devices1_map_base + 0x00002000,
-
-    Gic2_cpu_map_base    = Devices2_map_base + 0x00020000,
-    Gic2_dist_map_base   = Devices2_map_base + 0x00021000,
-    Gic3_cpu_map_base    = Devices2_map_base + 0x00030000,
-    Gic3_dist_map_base   = Devices2_map_base + 0x00031000,
-  };
-
   enum Phys_layout_realview_pbx : Address {
-    Devices1_phys_base   = 0x1f000000,
-    Devices2_phys_base   = 0x1e000000,
+    Devices1_phys_base    = 0x1f000000,
+    Mp_scu_phys_base      = Devices1_phys_base,
+    Gic_cpu_phys_base     = Devices1_phys_base + 0x00000100,
+    Gic_dist_phys_base    = Devices1_phys_base + 0x00001000,
+    L2cxx0_phys_base      = Devices1_phys_base + 0x00002000,
+
+    Devices2_phys_base    = 0x1e000000,
+    Gic2_cpu_phys_base    = Devices2_phys_base + 0x00020000,
+    Gic2_dist_phys_base   = Devices2_phys_base + 0x00021000,
+    Gic3_cpu_phys_base    = Devices2_phys_base + 0x00030000,
+    Gic3_dist_phys_base   = Devices2_phys_base + 0x00031000,
   };
 };
 
 // ------------------------------------------------------------------------
-INTERFACE [arm && realview && realview_vexpress]:
+INTERFACE [arm && realview && realview_vexpress_a9]:
 
 EXTENSION class Mem_layout
 {
 public:
-  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_a9 : Address {
+    Devices1_phys_base   = 0x1e000000,
+    Mp_scu_phys_base      = Devices1_phys_base,
+    Gic_cpu_phys_base     = Devices1_phys_base + 0x00000100,
+    Gic_dist_phys_base    = Devices1_phys_base + 0x00001000,
+    L2cxx0_phys_base      = Devices1_phys_base + 0x00002000,
   };
+};
 
-  enum Phys_layout_realview_vexpress : Address {
-    Devices1_phys_base   = 0x1e000000,
-    Devices2_phys_base   = Invalid_address,
+// ------------------------------------------------------------------------
+INTERFACE [arm && realview && realview_vexpress_a15]:
+
+EXTENSION class Mem_layout
+{
+public:
+  enum Phys_layout_realview_vexpress_a15 {
+    Devices0_phys_base   = 0x1c000000,
+    System_regs_phys_base = 0x1c010000,
+    System_ctrl_phys_base = 0x1c020000,
+    Uart_phys_base        = 0x1c090000,
+
+    Devices1_phys_base   = 0x1c100000,
+    Timer0_phys_base      = Devices1_phys_base + 0x00010000,
+    //Timer1_phys_base      = Devices1_phys_base + 0x00010020,
+    //Timer2_phys_base      = Devices1_phys_base + 0x00020000,
+    //Timer3_phys_base      = Devices1_phys_base + 0x00020020,
+
+    Devices2_phys_base   = 0x2c000000,
+    Mp_scu_phys_base      = Devices2_phys_base,
+    Gic_cpu_phys_base     = Devices2_phys_base + 0x00002000,
+    Gic_dist_phys_base    = Devices2_phys_base + 0x00001000,
+    L2cxx0_phys_base      = Devices2_phys_base + 0x00003000,
   };
 };
index 6e02784b2d61be09c13ce51ed4a9807d7b0afcfb..110555a15508c6e2fe898674660f7856757af912 100644 (file)
@@ -5,8 +5,8 @@ IMPLEMENT
 Mword
 Outer_cache::platform_init(Mword aux_control)
 {
-  Io::write<Mword>(0 , TAG_RAM_CONTROL);
-  Io::write<Mword>(0 , DATA_RAM_CONTROL);
+  l2cxx0->write<Mword>(0, L2cxx0::TAG_RAM_CONTROL);
+  l2cxx0->write<Mword>(0, L2cxx0::DATA_RAM_CONTROL);
   aux_control &= 0xc0000fff;
   aux_control |= 1 << 17; // 16kb way size
   aux_control |= 1 << 20; // event monitor bus enable
index 4cf9c72ceef1217b2b388d795755791f48350f8b..4d75b7803ac7c09e0ad57a1ff554439adaf3e4d0 100644 (file)
@@ -31,7 +31,7 @@ IMPLEMENTATION [arm && pic_gic && realview && (realview_pb11mp || (realview_eb &
 #include "cascade_irq.h"
 
 PUBLIC static
-void Pic::init_ap(unsigned)
+void Pic::init_ap(Cpu_number)
 {
   gic->init_ap();
   static_cast<Gic*>(Irq_mgr::mgr->chip(256).chip)->init_ap();
@@ -44,13 +44,15 @@ void Pic::init()
   configure_core();
   typedef Irq_mgr_multi_chip<8> Mgr;
 
-  Gic *g = gic.construct(Kmem::Gic_cpu_map_base, Kmem::Gic_dist_map_base);
+  Gic *g = gic.construct(Kmem::mmio_remap(Mem_layout::Gic_cpu_phys_base),
+                         Kmem::mmio_remap(Mem_layout::Gic_dist_phys_base));
   Mgr *m = new Boot_object<Mgr>(2);
   Irq_mgr::mgr = m;
 
   m->add_chip(0, g, g->nr_irqs());
 
-  g = new Boot_object<Gic>(Kmem::Gic1_cpu_map_base, Kmem::Gic1_dist_map_base);
+  g = new Boot_object<Gic>(Kmem::mmio_remap(Mem_layout::Gic1_cpu_phys_base),
+                           Kmem::mmio_remap(Mem_layout::Gic1_dist_phys_base));
   m->add_chip(256, g, g->nr_irqs());
 
   // FIXME: Replace static local variable, use placement new
@@ -71,7 +73,9 @@ void Pic::init()
   configure_core();
 
   typedef Irq_mgr_multi_chip<8> Mgr;
-  Gic *g = gic.construct(Kmem::Gic_cpu_map_base, Kmem::Gic_dist_map_base);
+
+  Gic *g = gic.construct(Kmem::mmio_remap(Mem_layout::Gic_cpu_phys_base),
+                         Kmem::mmio_remap(Mem_layout::Gic_dist_phys_base));
 
   Mgr *m = new Boot_object<Mgr>(1);
   m->add_chip(0, g, g->nr_irqs());
@@ -79,7 +83,7 @@ void Pic::init()
 }
 
 PUBLIC static
-void Pic::init_ap(unsigned)
+void Pic::init_ap(Cpu_number)
 {
   gic->init_ap();
 }
@@ -112,18 +116,17 @@ IMPLEMENTATION [arm && pic_gic && (mpcore || armca9)]:
 
 PRIVATE static
 void Pic::unlock_config()
-{ Io::write<Mword>(0xa05f, Platform::Sys::Lock); }
+{ Platform::sys->write<Mword>(0xa05f, Platform::Sys::Lock); }
 
 PRIVATE static
 void Pic::lock_config()
-{ Io::write<Mword>(0x0, Platform::Sys::Lock); }
+{ Platform::sys->write<Mword>(0x0, Platform::Sys::Lock); }
 
 PRIVATE static
 void Pic::configure_core()
 {
   // Enable 'new' interrupt-mode, no DCC
   unlock_config();
-  Io::write<Mword>(Io::read<Mword>(Platform::Sys::Pld_ctrl1) | INTMODE_NEW_NO_DDC,
-                   Platform::Sys::Pld_ctrl1);
+  Platform::sys->modify<Mword>(INTMODE_NEW_NO_DDC, 0, Platform::Sys::Pld_ctrl1);
   lock_config();
 }
index 0470b7877e679a92f6dcc04cc04e0e95eccc85d7..940c4fc967e3be6f779674145c6d1a2420b47747 100644 (file)
@@ -1,39 +1,68 @@
 INTERFACE[arm && realview]:
 
 #include "mem_layout.h"
+#include "mmio_register_block.h"
 
 class Platform
 {
 public:
-  class Sys
+  class Sys : public Mmio_register_block
   {
   public:
     enum Registers
     {
-      Id        = Mem_layout::System_regs_map_base + 0x0,
-      Sw        = Mem_layout::System_regs_map_base + 0x4,
-      Led       = Mem_layout::System_regs_map_base + 0x8,
-      Lock      = Mem_layout::System_regs_map_base + 0x20,
-      Flags     = Mem_layout::System_regs_map_base + 0x30,
-      Flags_clr = Mem_layout::System_regs_map_base + 0x34,
-      Cnt_24mhz = Mem_layout::System_regs_map_base + 0x5c,
-      Pld_ctrl1 = Mem_layout::System_regs_map_base + 0x74,
-      Pld_ctrl2 = Mem_layout::System_regs_map_base + 0x78,
+      Id        = 0x0,
+      Sw        = 0x4,
+      Led       = 0x8,
+      Lock      = 0x20,
+      Flags     = 0x30,
+      Flags_clr = 0x34,
+      Reset     = 0x40,
+      Cnt_24mhz = 0x5c,
+      Pld_ctrl1 = 0x74,
+      Pld_ctrl2 = 0x78,
     };
+    explicit Sys(Address virt) : Mmio_register_block(virt) {}
   };
 
+  class System_control : public Mmio_register_block
+  {
+  public:
+    enum
+    {
+      Timer0_enable = 1UL << 15,
+      Timer1_enable = 1UL << 17,
+      Timer2_enable = 1UL << 19,
+      Timer3_enable = 1UL << 21,
+    };
+    explicit System_control(Address virt) : Mmio_register_block(virt) {}
+  };
+
+  static Static_object<Sys> sys;
+  static Static_object<System_control> system_control;
 };
 
+class __Platform_init
+{
+};
+
+static __Platform_init __platform_init __attribute__((init_priority(101)));
+
 IMPLEMENTATION[arm && realview]:
 
-#include "io.h"
+#include "kmem.h"
 
-PUBLIC static inline NEEDS["io.h"]
-void
-Platform::write(enum Sys::Registers reg, Mword val)
-{ Io::write<Mword>(val, reg); }
 
-PUBLIC static inline NEEDS["io.h"]
-Mword
-Platform::read(enum Sys::Registers reg)
-{ return Io::read<Mword>(reg); }
+Static_object<Platform::Sys> Platform::sys;
+// hmmm
+Static_object<Platform::System_control> Platform::system_control;
+
+PUBLIC
+__Platform_init::__Platform_init()
+{
+  if (Platform::sys->get_mmio_base())
+    return;
+
+  Platform::sys.construct(Kmem::mmio_remap(Mem_layout::System_regs_phys_base));
+  Platform::system_control.construct(Kmem::mmio_remap(Mem_layout::System_ctrl_phys_base));
+}
index 4cc9f992ad078c5ff556a050bf5ae6805cfffb91..5c7d76bfba136ed3b79fd3282c713d75cbe8c73f 100644 (file)
@@ -12,10 +12,10 @@ void
 Platform_control::boot_ap_cpus(Address phys_tramp_mp_addr)
 {
   // set physical start address for AP CPUs
-  Platform::write(Platform::Sys::Flags_clr, 0xffffffff);
-  Platform::write(Platform::Sys::Flags, phys_tramp_mp_addr);
+  Platform::sys->write<Mword>(0xffffffff, Platform::Sys::Flags_clr);
+  Platform::sys->write<Mword>(phys_tramp_mp_addr, Platform::Sys::Flags);
 
   // wake up AP CPUs, always from CPU 0
-  Ipi::bcast(Ipi::Global_request, 0);
+  Ipi::bcast(Ipi::Global_request, Cpu_number::boot_cpu());
 }
 
index cb5a6c9f54310b9d5529069846a7e5cf6374948f..5bd47e98cad9c248b9f08524e89f45681f559abe 100644 (file)
@@ -2,23 +2,14 @@ IMPLEMENTATION [arm && realview]:
 
 #include "io.h"
 #include "kmem.h"
-
-class Realview_reset
-{
-public:
-  enum
-  {
-    LOCK  = Kmem::System_regs_map_base + 0x20,
-    RESET = Kmem::System_regs_map_base + 0x40,
-  };
-};
+#include "platform.h"
 
 // ------------------------------------------------------------------------
 IMPLEMENTATION [arm && realview && realview_eb]:
 
 static inline void do_reset()
 {
-  Io::write(0x108, Realview_reset::RESET); // the 0x100 is for Qemu
+  Platform::sys->write<Mword>(0x108, Platform::Sys::Reset); // the 0x100 is for Qemu
 }
 
 // ------------------------------------------------------------------------
@@ -26,7 +17,7 @@ IMPLEMENTATION [arm && realview && realview_pb11mp]:
 
 static inline void do_reset()
 {
-  Io::write(0x4, Realview_reset::RESET); // PORESET (0x8 would also be ok)
+  Platform::sys->write<Mword>(0x4, Platform::Sys::Reset);  // PORESET (0x8 would also be ok)
 }
 
 // ------------------------------------------------------------------------
@@ -34,7 +25,7 @@ IMPLEMENTATION [arm && realview && (realview_pbx || realview_vexpress)]:
 
 static inline void do_reset()
 {
-  Io::write(0x104, Realview_reset::RESET); // POWER reset, 0x100 for Qemu
+  Platform::sys->write<Mword>(0x104, Platform::Sys::Reset); // POWER reset, 0x100 for Qemu
 }
 
 // ------------------------------------------------------------------------
@@ -43,7 +34,7 @@ IMPLEMENTATION [arm && realview]:
 void __attribute__ ((noreturn))
 platform_reset(void)
 {
-  Io::write(0xa05f, Realview_reset::LOCK);  // unlock for reset
+  Platform::sys->write<Mword>(0xa05f, Platform::Sys::Lock);  // unlock for reset
   do_reset();
 
   for (;;)
index 0106124b2024d01d409509c8dced46d34c8001a3..64b0e9dcab0285ad72d1a433046a2a99e135b474 100644 (file)
@@ -1,28 +1,28 @@
 // --------------------------------------------------------------------------
 IMPLEMENTATION[arm && mptimer]:
 
+#include "platform.h"
+#include "timer_sp804.h"
+
 PRIVATE static Mword Timer::interval()
 {
-  Mword v = Io::read<Mword>(Timer_sp804::System_control);
-  v |= Timer_sp804::Timclk << Timer_sp804::Timer0_enable;
-  Io::write<Mword>(v, Timer_sp804::System_control);
+  Timer_sp804 timer(Kmem::mmio_remap(Mem_layout::Timer0_phys_base));
+  Platform::system_control->modify<Mword>(Platform::System_control::Timer0_enable, 0, 0);
 
   Mword frequency = 1000000;
   Mword timer_start = ~0UL;
   unsigned factor = 5;
   Mword sp_c = timer_start - frequency / 1000 * (1 << factor);
 
-  Io::write<Mword>(0, Timer_sp804::Ctrl_0);
-  Io::write<Mword>(timer_start, Timer_sp804::Value_0);
-  Io::write<Mword>(timer_start, Timer_sp804::Load_0);
-  Io::write<Mword>(  Timer_sp804::Ctrl_enable
-                   | Timer_sp804::Ctrl_periodic,
-                  Timer_sp804::Ctrl_0);
+  timer.disable();
+  timer.counter_value(timer_start);
+  timer.reload_value(timer_start);
+  timer.enable(Timer_sp804::Ctrl_periodic);
 
   Mword vc = start_as_counter();
-  while (sp_c < Io::read<Mword>(Timer_sp804::Value_0))
+  while (sp_c < timer.counter())
     ;
   Mword interval = (vc - stop_counter()) >> factor;
-  Io::write<Mword>(0, Timer_sp804::Ctrl_0);
+  timer.disable();
   return interval;
 }
index 8cbd14057fa864d8b8b5de75be33d5e76716ab26..b8f767b708345c12689447dd3bec403d997c53d4 100644 (file)
@@ -1,67 +1,30 @@
 // --------------------------------------------------------------------------
-INTERFACE [arm]:
+INTERFACE [arm && sp804]:
 
-#include "kmem.h"
+#include "timer_sp804.h"
 
-class Timer_sp804
+EXTENSION class Timer
+{
+private:
+  static Static_object<Timer_sp804> sp804;
+};
+
+// --------------------------------------------------------------------------
+INTERFACE [arm && sp804 && realview_vexpress_a15]:
+
+EXTENSION class Timer
 {
 public:
-  enum {
-    System_control = Kmem::System_ctrl_map_base,
-
-    Refclk = 0,
-    Timclk = 1,
-
-    Timer0_enable = 15,
-    Timer1_enable = 17,
-    Timer2_enable = 19,
-    Timer3_enable = 21,
-
-    Timer_load   = 0x00,
-    Timer_value  = 0x04,
-    Timer_ctrl   = 0x08,
-    Timer_intclr = 0x0c,
-
-    Load_0 = Kmem::Timer0_map_base + Timer_load,
-    Load_1 = Kmem::Timer1_map_base + Timer_load,
-    Load_2 = Kmem::Timer2_map_base + Timer_load,
-    Load_3 = Kmem::Timer3_map_base + Timer_load,
-
-    Value_0 = Kmem::Timer0_map_base + Timer_value,
-    Value_1 = Kmem::Timer1_map_base + Timer_value,
-    Value_2 = Kmem::Timer2_map_base + Timer_value,
-    Value_3 = Kmem::Timer3_map_base + Timer_value,
-
-    Ctrl_0 = Kmem::Timer0_map_base + Timer_ctrl,
-    Ctrl_1 = Kmem::Timer1_map_base + Timer_ctrl,
-    Ctrl_2 = Kmem::Timer2_map_base + Timer_ctrl,
-    Ctrl_3 = Kmem::Timer3_map_base + Timer_ctrl,
-
-    Intclr_0 = Kmem::Timer0_map_base + Timer_intclr,
-    Intclr_1 = Kmem::Timer1_map_base + Timer_intclr,
-    Intclr_2 = Kmem::Timer2_map_base + Timer_intclr,
-    Intclr_3 = Kmem::Timer3_map_base + Timer_intclr,
-
-    Interval = 1000,
-
-    Ctrl_ie        = 1 << 5,
-    Ctrl_periodic  = 1 << 6,
-    Ctrl_enable    = 1 << 7,
-  };
+  static unsigned irq() { return 34; }
 };
 
 // --------------------------------------------------------------------------
-INTERFACE [arm && sp804]:
+INTERFACE [arm && sp804 && !realview_vexpress_a15]:
 
 EXTENSION class Timer
 {
 public:
   static unsigned irq() { return 36; }
-
-private:
-  enum {
-    Interval = 1000,
-  };
 };
 
 // -----------------------------------------------------------------------
@@ -69,29 +32,27 @@ IMPLEMENTATION [arm && sp804]:
 
 #include "config.h"
 #include "kip.h"
-#include "io.h"
+#include "platform.h"
 
 #include <cstdio>
 
+Static_object<Timer_sp804> Timer::sp804;
+
 IMPLEMENT
-void Timer::init(unsigned)
+void Timer::init(Cpu_number)
 {
-  Mword v = Io::read<Mword>(Timer_sp804::System_control);
-  v |= Timer_sp804::Timclk << Timer_sp804::Timer0_enable;
-  Io::write<Mword>(v, Timer_sp804::System_control);
+  sp804.construct(Kmem::mmio_remap(Mem_layout::Timer0_phys_base));
+  Platform::system_control->modify<Mword>(Platform::System_control::Timer0_enable, 0, 0);
 
   // all timers off
-  Io::write<Mword>(0, Timer_sp804::Ctrl_0);
-  Io::write<Mword>(0, Timer_sp804::Ctrl_1);
-  Io::write<Mword>(0, Timer_sp804::Ctrl_2);
-  Io::write<Mword>(0, Timer_sp804::Ctrl_3);
-
-  Io::write<Mword>(Interval, Timer_sp804::Load_0);
-  Io::write<Mword>(Interval, Timer_sp804::Value_0);
-  Io::write<Mword>  (Timer_sp804::Ctrl_enable
-                   | Timer_sp804::Ctrl_periodic
-                   | Timer_sp804::Ctrl_ie,
-                   Timer_sp804::Ctrl_0);
+  sp804->disable();
+  //Io::write<Mword>(0, Timer_sp804::Ctrl_1);
+  //Io::write<Mword>(0, Timer_sp804::Ctrl_2);
+  //Io::write<Mword>(0, Timer_sp804::Ctrl_3);
+
+  sp804->reload_value(Timer_sp804::Interval);
+  sp804->counter_value(Timer_sp804::Interval);
+  sp804->enable(Timer_sp804::Ctrl_periodic | Timer_sp804::Ctrl_ie);
 }
 
 static inline
@@ -104,11 +65,11 @@ Unsigned64
 Timer::us_to_timer(Unsigned64 us)
 { (void)us; return 0; }
 
-PUBLIC static inline NEEDS["io.h"]
+PUBLIC static inline
 void
 Timer::acknowledge()
 {
-  Io::write<Mword>(0, Timer_sp804::Intclr_0);
+  sp804->irq_clear();
 }
 
 IMPLEMENT inline
index bd85d5648a9e4b4493e2cdd70cfed7cdfc00bb21..b0cfbb20b1a4d630282fc66537d815e5a1df4bb9 100644 (file)
@@ -15,7 +15,7 @@ IMPLEMENTATION: // --------------------------------------------------------
 #include "mem_layout.h"
 #include "uart_pl011.h"
 
-IMPLEMENT Address Uart::base() const { return Mem_layout::Uart_base; }
+IMPLEMENT Address Uart::base() const { return Mem_layout::Uart_phys_base; }
 
 IMPLEMENT L4::Uart *Uart::uart()
 {
index fea895347d08f45a0813b892ef8d7b6c5ed0efac..c7ad0823f64c7962a610b6a2337e1df52a361ce1 100644 (file)
@@ -3,7 +3,7 @@
 SUBSYSTEMS              += LIBUART
 OBJECTS_LIBUART         += uart_s3c2410.o
 PREPROCESS_PARTS        += libuart s3c2410 generic_tickless_idle
-CONFIG_KERNEL_LOAD_ADDR := 0x30000000
+RAM_PHYS_BASE           := 0x30000000
 
 uart_IMPL             += uart-s3c2410
 config_IMPL           += config-arm-s3c2410
index cc46cee28d5c9716a0dd7a2b0cf87d3128348b65..0f89d6bb731f1f439febe5277d448026fdc3b11b 100644 (file)
@@ -1,19 +1,7 @@
 //-----------------------------------------------------------------------------
 INTERFACE [arm && s3c2410]:
-
+namespace Bootstrap {
 enum {
   Cache_flush_area = 0x0,
 };
-
-
-//-----------------------------------------------------------------------------
-IMPLEMENTATION [arm && s3c2410]:
-
-void
-map_hw(void *pd)
-{
-  map_dev<Mem_layout::Devices0_phys_base>(pd, 0);
-  map_dev<Mem_layout::Devices1_phys_base>(pd, 1);
-  map_dev<Mem_layout::Devices2_phys_base>(pd, 2);
-  map_dev<Mem_layout::Devices3_phys_base>(pd, 3);
 }
index 6253830f0392fef49dbb7d9eea90ea6dbf97a9c6..8fcbe5d49db21675c8f609ba40eb8133648be8aa 100644 (file)
@@ -3,20 +3,10 @@ INTERFACE [arm && s3c2410]: //----------------------------------------------
 EXTENSION class Mem_layout
 {
 public:
-  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 : 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,
+  enum Phys_layout_s3c2410 : Address {
+    Pic_phys_base        = 0x4a000000,
+    Uart_phys_base       = 0x50000000,
+    Pwm_phys_base        = 0x51000000,
+    Watchdog_phys_base   = 0x53000000,
   };
 };
index a89d122cf268924c6e2a840b30a696ad81edcea0..ec51488db6fd5bf4f73bcab52f6f69f1506e381d 100644 (file)
@@ -5,16 +5,32 @@ INTERFACE [arm && s3c2410]:
 EXTENSION class Pic
 {
 public:
+};
+
+// ---------------------------------------------------------------------
+IMPLEMENTATION [arm && s3c2410]:
+
+#include "assert.h"
+#include "config.h"
+#include "initcalls.h"
+#include "irq_chip_generic.h"
+#include "irq_mgr.h"
+#include "mmio_register_block.h"
+
+#include <cstdio>
+
+class S3c_chip : public Irq_chip_gen, Mmio_register_block
+{
   enum
   {
-    SRCPND    = Kmem::Pic_map_base + 0x00,
-    INTMODE   = Kmem::Pic_map_base + 0x04,
-    INTMSK    = Kmem::Pic_map_base + 0x08,
-    PRIORITY  = Kmem::Pic_map_base + 0x0c,
-    INTPND    = Kmem::Pic_map_base + 0x10,
-    INTOFFSET = Kmem::Pic_map_base + 0x14,
-    SUBSRCPND = Kmem::Pic_map_base + 0x18,
-    INTSUBMSK = Kmem::Pic_map_base + 0x1c,
+    SRCPND    = 0x00,
+    INTMODE   = 0x04,
+    INTMSK    = 0x08,
+    PRIORITY  = 0x0c,
+    INTPND    = 0x10,
+    INTOFFSET = 0x14,
+    SUBSRCPND = 0x18,
+    INTSUBMSK = 0x1c,
   };
 
   enum
@@ -35,11 +51,11 @@ public:
     SUB_RXD1 = 3,
     SUB_TXD1 = 4,
     SUB_ERR1 = 5,
-    SUB_RXD2 = 6,
-    SUB_TXD2 = 7,
-    SUB_ERR2 = 8,
-    SUB_TC   = 9,
-    SUB_ADC  = 10,
+    SUB_RXD2 = 6,  // 53
+    SUB_TXD2 = 7,  // 54
+    SUB_ERR2 = 8,  // 52
+    SUB_TC   = 9,  // 64
+    SUB_ADC  = 10, // 63
   };
 
   enum // Interrupts
@@ -69,26 +85,26 @@ public:
     INT_ADC = 63,
     INT_TC  = 64,
   };
-};
 
-// ---------------------------------------------------------------------
-IMPLEMENTATION [arm && s3c2410]:
-
-#include "config.h"
-#include "io.h"
-#include "irq_chip_generic.h"
-#include "irq_mgr.h"
-
-#include <cstdio>
-
-class S3c_chip : public Irq_chip_gen
-{
 public:
-  S3c_chip() : Irq_chip_gen(32) {}
   unsigned set_mode(Mword, unsigned) { return Irq_base::Trigger_level; }
-  void set_cpu(Mword, unsigned) {}
+  void set_cpu(Mword, Cpu_number) {}
 };
 
+PUBLIC
+S3c_chip::S3c_chip()
+: Irq_chip_gen(32),
+  Mmio_register_block(Kmem::mmio_remap(Mem_layout::Pic_phys_base))
+{
+
+  write<Mword>(0xffffffff, INTMSK); // all masked
+  write<Mword>(0x7fe, INTSUBMSK);   // all masked
+  write<Mword>(0, INTMODE);         // all IRQs, no FIQs
+  modify<Mword>(0, 0, SRCPND); // clear source pending
+  modify<Mword>(0, 0, SUBSRCPND); // clear sub src pnd
+  modify<Mword>(0, 0, INTPND); // clear pending interrupt
+}
+
 
 PUBLIC
 void
@@ -98,24 +114,24 @@ S3c_chip::mask(Mword irq)
 
   switch (irq)
     {
-      case Pic::INT_TC:        Io::set<Mword>(1 << Pic::SUB_TC,   Pic::INTSUBMSK); mainirq = Pic::MAIN_ADC;   break;
-      case Pic::INT_ADC:       Io::set<Mword>(1 << Pic::SUB_ADC,  Pic::INTSUBMSK); mainirq = Pic::MAIN_ADC;   break;
-      case Pic::INT_UART0_RXD: Io::set<Mword>(1 << Pic::SUB_RXD0, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART0; break;
-      case Pic::INT_UART0_TXD: Io::set<Mword>(1 << Pic::SUB_TXD0, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART0; break;
-      case Pic::INT_UART0_ERR: Io::set<Mword>(1 << Pic::SUB_ERR0, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART0; break;
-      case Pic::INT_UART1_RXD: Io::set<Mword>(1 << Pic::SUB_RXD1, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART1; break;
-      case Pic::INT_UART1_TXD: Io::set<Mword>(1 << Pic::SUB_TXD1, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART1; break;
-      case Pic::INT_UART1_ERR: Io::set<Mword>(1 << Pic::SUB_ERR1, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART1; break;
-      case Pic::INT_UART2_RXD: Io::set<Mword>(1 << Pic::SUB_RXD2, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART2; break;
-      case Pic::INT_UART2_TXD: Io::set<Mword>(1 << Pic::SUB_TXD2, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART2; break;
-      case Pic::INT_UART2_ERR: Io::set<Mword>(1 << Pic::SUB_ERR2, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART2; break;
+      case INT_TC:        modify<Mword>(1 << SUB_TC,   0, INTSUBMSK); mainirq = MAIN_ADC;   break;
+      case INT_ADC:       modify<Mword>(1 << SUB_ADC,  0, INTSUBMSK); mainirq = MAIN_ADC;   break;
+      case INT_UART0_RXD: modify<Mword>(1 << SUB_RXD0, 0, INTSUBMSK); mainirq = MAIN_UART0; break;
+      case INT_UART0_TXD: modify<Mword>(1 << SUB_TXD0, 0, INTSUBMSK); mainirq = MAIN_UART0; break;
+      case INT_UART0_ERR: modify<Mword>(1 << SUB_ERR0, 0, INTSUBMSK); mainirq = MAIN_UART0; break;
+      case INT_UART1_RXD: modify<Mword>(1 << SUB_RXD1, 0, INTSUBMSK); mainirq = MAIN_UART1; break;
+      case INT_UART1_TXD: modify<Mword>(1 << SUB_TXD1, 0, INTSUBMSK); mainirq = MAIN_UART1; break;
+      case INT_UART1_ERR: modify<Mword>(1 << SUB_ERR1, 0, INTSUBMSK); mainirq = MAIN_UART1; break;
+      case INT_UART2_RXD: modify<Mword>(1 << SUB_RXD2, 0, INTSUBMSK); mainirq = MAIN_UART2; break;
+      case INT_UART2_TXD: modify<Mword>(1 << SUB_TXD2, 0, INTSUBMSK); mainirq = MAIN_UART2; break;
+      case INT_UART2_ERR: modify<Mword>(1 << SUB_ERR2, 0, INTSUBMSK); mainirq = MAIN_UART2; break;
       default:
          if (irq > 31)
            return; // XXX: need to add other cases
          mainirq = irq;
     };
 
-  Io::set<Mword>(1 << mainirq, Pic::INTMSK);
+  modify<Mword>(1 << mainirq, 0, INTMSK);
 }
 
 PUBLIC
@@ -126,24 +142,24 @@ S3c_chip::unmask(Mword irq)
 
   switch (irq)
     {
-      case Pic::INT_TC:        Io::clear<Mword>(1 << Pic::SUB_TC,   Pic::INTSUBMSK); mainirq = Pic::MAIN_ADC;   break;
-      case Pic::INT_ADC:       Io::clear<Mword>(1 << Pic::SUB_ADC,  Pic::INTSUBMSK); mainirq = Pic::MAIN_ADC;   break;
-      case Pic::INT_UART0_RXD: Io::clear<Mword>(1 << Pic::SUB_RXD0, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART0; break;
-      case Pic::INT_UART0_TXD: Io::clear<Mword>(1 << Pic::SUB_TXD0, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART0; break;
-      case Pic::INT_UART0_ERR: Io::clear<Mword>(1 << Pic::SUB_ERR0, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART0; break;
-      case Pic::INT_UART1_RXD: Io::clear<Mword>(1 << Pic::SUB_RXD1, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART1; break;
-      case Pic::INT_UART1_TXD: Io::clear<Mword>(1 << Pic::SUB_TXD1, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART1; break;
-      case Pic::INT_UART1_ERR: Io::clear<Mword>(1 << Pic::SUB_ERR1, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART1; break;
-      case Pic::INT_UART2_RXD: Io::clear<Mword>(1 << Pic::SUB_RXD2, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART2; break;
-      case Pic::INT_UART2_TXD: Io::clear<Mword>(1 << Pic::SUB_TXD2, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART2; break;
-      case Pic::INT_UART2_ERR: Io::clear<Mword>(1 << Pic::SUB_ERR2, Pic::INTSUBMSK); mainirq = Pic::MAIN_UART2; break;
+      case INT_TC:        modify<Mword>(0, 1 << SUB_TC,   INTSUBMSK); mainirq = MAIN_ADC;   break;
+      case INT_ADC:       modify<Mword>(0, 1 << SUB_ADC,  INTSUBMSK); mainirq = MAIN_ADC;   break;
+      case INT_UART0_RXD: modify<Mword>(0, 1 << SUB_RXD0, INTSUBMSK); mainirq = MAIN_UART0; break;
+      case INT_UART0_TXD: modify<Mword>(0, 1 << SUB_TXD0, INTSUBMSK); mainirq = MAIN_UART0; break;
+      case INT_UART0_ERR: modify<Mword>(0, 1 << SUB_ERR0, INTSUBMSK); mainirq = MAIN_UART0; break;
+      case INT_UART1_RXD: modify<Mword>(0, 1 << SUB_RXD1, INTSUBMSK); mainirq = MAIN_UART1; break;
+      case INT_UART1_TXD: modify<Mword>(0, 1 << SUB_TXD1, INTSUBMSK); mainirq = MAIN_UART1; break;
+      case INT_UART1_ERR: modify<Mword>(0, 1 << SUB_ERR1, INTSUBMSK); mainirq = MAIN_UART1; break;
+      case INT_UART2_RXD: modify<Mword>(0, 1 << SUB_RXD2, INTSUBMSK); mainirq = MAIN_UART2; break;
+      case INT_UART2_TXD: modify<Mword>(0, 1 << SUB_TXD2, INTSUBMSK); mainirq = MAIN_UART2; break;
+      case INT_UART2_ERR: modify<Mword>(0, 1 << SUB_ERR2, INTSUBMSK); mainirq = MAIN_UART2; break;
       default:
          if (irq > 31)
            return; // XXX: need to add other cases
          mainirq = irq;
     };
 
-  Io::clear<Mword>(1 << mainirq, Pic::INTMSK);
+  modify<Mword>(0, 1 << mainirq, INTMSK);
 }
 
 PUBLIC
@@ -154,25 +170,25 @@ S3c_chip::ack(Mword irq)
 
   switch (irq)
     {
-      case Pic::INT_TC:        Io::write<Mword>(1 << Pic::SUB_TC,   Pic::SUBSRCPND); mainirq = Pic::MAIN_ADC;   break;
-      case Pic::INT_ADC:       Io::write<Mword>(1 << Pic::SUB_ADC,  Pic::SUBSRCPND); mainirq = Pic::MAIN_ADC;   break;
-      case Pic::INT_UART0_RXD: Io::write<Mword>(1 << Pic::SUB_RXD0, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART0; break;
-      case Pic::INT_UART0_TXD: Io::write<Mword>(1 << Pic::SUB_TXD0, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART0; break;
-      case Pic::INT_UART0_ERR: Io::write<Mword>(1 << Pic::SUB_ERR0, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART0; break;
-      case Pic::INT_UART1_RXD: Io::write<Mword>(1 << Pic::SUB_RXD1, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART1; break;
-      case Pic::INT_UART1_TXD: Io::write<Mword>(1 << Pic::SUB_TXD1, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART1; break;
-      case Pic::INT_UART1_ERR: Io::write<Mword>(1 << Pic::SUB_ERR1, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART1; break;
-      case Pic::INT_UART2_RXD: Io::write<Mword>(1 << Pic::SUB_RXD2, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART2; break;
-      case Pic::INT_UART2_TXD: Io::write<Mword>(1 << Pic::SUB_TXD2, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART2; break;
-      case Pic::INT_UART2_ERR: Io::write<Mword>(1 << Pic::SUB_ERR2, Pic::SUBSRCPND); mainirq = Pic::MAIN_UART2; break;
+      case INT_TC:        write<Mword>(1 << SUB_TC,   SUBSRCPND); mainirq = MAIN_ADC;   break;
+      case INT_ADC:       write<Mword>(1 << SUB_ADC,  SUBSRCPND); mainirq = MAIN_ADC;   break;
+      case INT_UART0_RXD: write<Mword>(1 << SUB_RXD0, SUBSRCPND); mainirq = MAIN_UART0; break;
+      case INT_UART0_TXD: write<Mword>(1 << SUB_TXD0, SUBSRCPND); mainirq = MAIN_UART0; break;
+      case INT_UART0_ERR: write<Mword>(1 << SUB_ERR0, SUBSRCPND); mainirq = MAIN_UART0; break;
+      case INT_UART1_RXD: write<Mword>(1 << SUB_RXD1, SUBSRCPND); mainirq = MAIN_UART1; break;
+      case INT_UART1_TXD: write<Mword>(1 << SUB_TXD1, SUBSRCPND); mainirq = MAIN_UART1; break;
+      case INT_UART1_ERR: write<Mword>(1 << SUB_ERR1, SUBSRCPND); mainirq = MAIN_UART1; break;
+      case INT_UART2_RXD: write<Mword>(1 << SUB_RXD2, SUBSRCPND); mainirq = MAIN_UART2; break;
+      case INT_UART2_TXD: write<Mword>(1 << SUB_TXD2, SUBSRCPND); mainirq = MAIN_UART2; break;
+      case INT_UART2_ERR: write<Mword>(1 << SUB_ERR2, SUBSRCPND); mainirq = MAIN_UART2; break;
       default:
          if (irq > 31)
            return; // XXX: need to add other cases
         mainirq = irq;
     };
 
-  Io::write<Mword>(1 << mainirq, Pic::SRCPND); // only 1s are set to 0
-  Io::write<Mword>(1 << mainirq, Pic::INTPND); // clear pending interrupt
+  write<Mword>(1 << mainirq, SRCPND); // only 1s are set to 0
+  write<Mword>(1 << mainirq, INTPND); // clear pending interrupt
 }
 
 PUBLIC
@@ -192,13 +208,6 @@ IMPLEMENT FIASCO_INIT
 void Pic::init()
 {
   Irq_mgr::mgr = mgr.construct();
-
-  Io::write<Mword>(0xffffffff, INTMSK); // all masked
-  Io::write<Mword>(0x7fe, INTSUBMSK);   // all masked
-  Io::write<Mword>(0, INTMODE);         // all IRQs, no FIQs
-  Io::write<Mword>(Io::read<Mword>(SRCPND), SRCPND); // clear source pending
-  Io::write<Mword>(Io::read<Mword>(SUBSRCPND), SUBSRCPND); // clear sub src pnd
-  Io::write<Mword>(Io::read<Mword>(INTPND), INTPND); // clear pending interrupt
 }
 
 
@@ -213,16 +222,16 @@ IMPLEMENT inline
 void Pic::restore_all(Status)
 {}
 
-PUBLIC static inline NEEDS["io.h"]
-Unsigned32 Pic::pending()
+PUBLIC inline
+Unsigned32 S3c_chip::pending()
 {
-  int mainirq = Io::read<Mword>(INTOFFSET);
+  int mainirq = read<Mword>(INTOFFSET);
 
   switch (mainirq)
     {
     case MAIN_ADC:
        {
-         int subirq = Io::read<Mword>(SUBSRCPND);
+         int subirq = read<Mword>(SUBSRCPND);
          if ((1 << SUB_ADC) & subirq)
            return INT_ADC;
          else if ((1 << SUB_TC) & subirq)
@@ -239,7 +248,7 @@ Unsigned32 Pic::pending()
 extern "C"
 void irq_handler()
 {
-  Unsigned32 i = Pic::pending();
+  Unsigned32 i = mgr->c.pending();
   if (i != 32)
     mgr->c.handle_irq<S3c_chip>(i, 0);
 }
index 79fdff4fd9e7ce915c36639a58c381f95fc3b0b1..7ceecf826c53548fb9e1315c5a79934e58732476 100644 (file)
@@ -1,26 +1,27 @@
 IMPLEMENTATION [arm && s3c2410]:
 
-#include "io.h"
+#include "mmio_register_block.h"
 #include "kmem.h"
 
 void __attribute__ ((noreturn))
 platform_reset(void)
 {
+  Mmio_register_block wdg(Kmem::mmio_remap(Mem_layout::Watchdog_phys_base));
   enum {
-    WTCON = Kmem::Watchdog_map_base + 0x0,
-    WTDAT = Kmem::Watchdog_map_base + 0x4,
-    WTCNT = Kmem::Watchdog_map_base + 0x8,
+    WTCON = 0x0,
+    WTDAT = 0x4,
+    WTCNT = 0x8,
 
     WTCON_RST_EN    = 1 << 0,
     WTCON_EN        = 1 << 5,
     WTCON_PRESCALER = (0x10 << 8),
   };
 
-  Io::write(0, WTCON); // disable
-  Io::write(200, WTDAT); // set initial values
-  Io::write(200, WTCNT);
+  wdg.write(0, WTCON); // disable
+  wdg.write(200, WTDAT); // set initial values
+  wdg.write(200, WTCNT);
 
-  Io::write(WTCON_RST_EN | WTCON_EN | WTCON_PRESCALER, WTCON);
+  wdg.write(WTCON_RST_EN | WTCON_EN | WTCON_PRESCALER, WTCON);
 
   // we should reboot now
   while (1)
index 592a53fa51da4d0619253d784cdd2899a559d247..a505f63090db104ed3aeef05e17c6a545886bd62 100644 (file)
@@ -1,37 +1,59 @@
-INTERFACE [arm && s3c2410]:
+INTERFACE [arm && (s3c2410 || exynos)]:
 
 #include "kmem.h"
+#include "mmio_register_block.h"
 
-EXTENSION class Timer
+EXTENSION class Timer : private Mmio_register_block
 {
-public:
-  static unsigned irq() { return 14; }
-
 private:
   enum {
-    TCFG0  = Kmem::Timer_map_base + 0x00,
-    TCFG1  = Kmem::Timer_map_base + 0x04,
-    TCON   = Kmem::Timer_map_base + 0x08,
-    TCNTB0 = Kmem::Timer_map_base + 0x0c,
-    TCMPB0 = Kmem::Timer_map_base + 0x10,
-    TCNTO0 = Kmem::Timer_map_base + 0x14,
-    TCNTB1 = Kmem::Timer_map_base + 0x18,
-    TCMPB1 = Kmem::Timer_map_base + 0x1c,
-    TCNTO1 = Kmem::Timer_map_base + 0x20,
-    TCNTB2 = Kmem::Timer_map_base + 0x24,
-    TCMPB2 = Kmem::Timer_map_base + 0x28,
-    TCNTO2 = Kmem::Timer_map_base + 0x2c,
-    TCNTB3 = Kmem::Timer_map_base + 0x30,
-    TCMPB3 = Kmem::Timer_map_base + 0x34,
-    TCNTO3 = Kmem::Timer_map_base + 0x38,
-    TCNTB4 = Kmem::Timer_map_base + 0x3c,
-    TCNTO4 = Kmem::Timer_map_base + 0x40,
+    TCFG0      = 0x00,
+    TCFG1      = 0x04,
+    TCON       = 0x08,
+    TCNTB0     = 0x0c,
+    TCMPB0     = 0x10,
+    TCNTO0     = 0x14,
+    TCNTB1     = 0x18,
+    TCMPB1     = 0x1c,
+    TCNTO1     = 0x20,
+    TCNTB2     = 0x24,
+    TCMPB2     = 0x28,
+    TCNTO2     = 0x2c,
+    TCNTB3     = 0x30,
+    TCMPB3     = 0x34,
+    TCNTO3     = 0x38,
+    TCNTB4     = 0x3c,
+    TCNTO4     = 0x40,
+    TINT_CSTAT = 0x44,
+  };
 
+  enum {
+    Timer_nr = 4,
   };
+
+  static Static_object<Timer> _timer;
+};
+
+INTERFACE [arm && s3c2410]: // --------------------------------------------
+
+EXTENSION class Timer
+{
+public:
+  static unsigned irq() { return 10 + Timer_nr; }
+  enum { Reload_value = 33333, Tint_cstat_entable = 0 };
+};
+
+INTERFACE [arm && exynos]: // --------------------------------------------
+
+EXTENSION class Timer
+{
+public:
+  static unsigned irq() { return 68 + Timer_nr; }
+  enum { Reload_value = 66666, Tint_cstat_entable = 1 };
 };
 
 // -----------------------------------------------------------------------
-IMPLEMENTATION [arm && s3c2410]:
+IMPLEMENTATION [arm && (s3c2410 || exynos)]:
 
 #include "config.h"
 #include "kip.h"
@@ -39,20 +61,42 @@ IMPLEMENTATION [arm && s3c2410]:
 
 #include <cstdio>
 
-IMPLEMENT
-void Timer::init(unsigned)
+Static_object<Timer> Timer::_timer;
+
+PUBLIC static
+void
+Timer::configure(Cpu_number)
+{}
+
+PUBLIC
+Timer::Timer() : Mmio_register_block(Kmem::mmio_remap(Mem_layout::Pwm_phys_base))
 {
-  Io::write(0, TCFG0); // prescaler config
-  Io::write(0, TCFG1); // mux select
-  Io::write(33333, TCNTB4); // reload value
+  write<Mword>(0, TCFG0); // prescaler config
+  write<Mword>(0, TCFG1); // mux select
+  write<Mword>(Reload_value, TCNTB0  + Timer_nr * 0xc); // reload value
+  write<Mword>(Reload_value, TCMPB0  + Timer_nr * 0xc); // reload value
+
+  unsigned shift = Timer_nr == 0 ? 0 : (Timer_nr * 4 + 4);
+  write<Mword>(5 << shift, TCON); // start + autoreload
 
-  Io::write(5 << 20, TCON); // start + autoreload
+  if (Tint_cstat_entable)
+    write<Mword>(1 << Timer_nr, TINT_CSTAT);
+}
+
+IMPLEMENT
+void Timer::init(Cpu_number cpu)
+{
+  if (cpu == Cpu_number::boot_cpu())
+    _timer.construct();
 }
 
 PUBLIC static inline
 void
 Timer::acknowledge()
-{}
+{
+  if (Tint_cstat_entable)
+    _timer->modify<Mword>(1 << (Timer_nr + 5), 0, TINT_CSTAT);
+}
 
 static inline
 Unsigned64
@@ -71,13 +115,11 @@ Timer::update_one_shot(Unsigned64 wakeup)
   (void)wakeup;
 }
 
-IMPLEMENT inline NEEDS["config.h", "kip.h", "io.h", Timer::timer_to_us]
+IMPLEMENT inline NEEDS["config.h", "kip.h"]
 Unsigned64
 Timer::system_clock()
 {
   if (Config::Scheduler_one_shot)
-    //return Kip::k()->clock + timer_to_us(Io::read<Unsigned32>(OSCR));
     return 0;
-  else
-    return Kip::k()->clock;
+  return Kip::k()->clock;
 }
index fd7f50b52375ed56ae6fa719de9a9f779c672189..7138aeb9894017e643efbb8b3f2149fed377f59e 100644 (file)
@@ -3,7 +3,7 @@ IMPLEMENTATION [s3c2410]:
 #include "uart_s3c2410.h"
 #include "mem_layout.h"
 
-IMPLEMENT Address Uart::base() const { return Mem_layout::Uart_base; }
+IMPLEMENT Address Uart::base() const { return Mem_layout::Uart_phys_base; }
 
 IMPLEMENT int Uart::irq() const { return 28; }
 
index ffb338ce3b18c332262a32e99506f96fb375c231..e22e733213561187cd00f6e532e95be095aa923c 100644 (file)
@@ -1,7 +1,7 @@
 # vim:set ft=make:
 
 PREPROCESS_PARTS        += sa1100 vcache armv5 kern_start_0xd generic_tickless_idle
-CONFIG_KERNEL_LOAD_ADDR := 0xc0000000
+RAM_PHYS_BASE           := 0xc0000000
 VPATH                   += kern/arm/bsp/pxa-sa
     
 uart_IMPL             += uart-sa1100
index 03cffb5a05f83b9f2123c8411c5052f890318ed2..2165af161e63ae489ece306faf6d8e38e60c3633 100644 (file)
@@ -1,21 +1,8 @@
 //---------------------------------------------------------------------------
 INTERFACE[arm && sa1100]:
-
+namespace Bootstrap {
 enum {
   Cache_flush_area = 0xe0000000,
 };
-
-//---------------------------------------------------------------------------
-IMPLEMENTATION[arm && sa1100]:
-
-#include "mem_layout.h"
-
-void
-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_dev<Mem_layout::Devices0_phys_base>(pd, 0);
-  map_dev<Mem_layout::Devices1_phys_base>(pd, 1);
 }
+
index 3dbab3a7709b3e949596e1ab73ede2f3496c2519..5b92bda113462c62655df40c574996d0e5dce95b 100644 (file)
@@ -5,10 +5,11 @@ EXTENSION class Kernel_uart { enum { Bsp_init_mode = Init_before_mmu }; };
 
 IMPLEMENTATION [arm && sa1100 && serial]:
 
+#include "kmem.h"
 #include "mem_layout.h"
 
 IMPLEMENT
 bool Kernel_uart::startup(unsigned port, int /*irq*/)
 {
-  return Uart::startup(Mem_layout::Uart_base, 17);
+  return Uart::startup(Kmem::mmio_remap(Mem_layout::Uart_phys_base), 17);
 }
index d9cc6c0783238edfb2f83f17f48505476dfcbdfe..1c3965ab14ba8c023e0e532f4f44a76749799fcc 100644 (file)
@@ -4,16 +4,10 @@ INTERFACE [arm-sa1100]:
 EXTENSION class Mem_layout
 {
 public:
-  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 : Address {
-    Devices0_phys_base   = 0x80000000,
-    Devices1_phys_base   = 0x90000000,
-    Sdram_phys_base      = 0xc0000000,
+  enum Phys_layout_sa1100 : Address {
+    Uart_phys_base       = 0x80050000,
+    Timer_phys_base      = 0x90000000,
+    Pic_phys_base        = 0x90050000,
     Flush_area_phys_base = 0xe0000000,
   };
 };
index d1920e7533ff01d18a9ee98d089019cee0832c70..8b29759168d5571ce984772f959f692415f3b4d2 100644 (file)
@@ -2,14 +2,13 @@ IMPLEMENTATION [arm && sa1100]:
 
 #include <sa1100.h>
 #include "kmem.h"
-#include "io.h"
 
-typedef Sa1100_generic<Kmem::Timer_map_base> Sa1100;
 
 void __attribute__ ((noreturn))
 platform_reset(void)
 {
-  Io::write( (Mword)Sa1100::RSRR_SWR, (Address)Sa1100::RSRR );
+  Sa1100 sa(Kmem::mmio_remap(Mem_layout::Timer_phys_base));
+  sa.write( (Mword)Sa1100::RSRR_SWR, (Address)Sa1100::RSRR );
   for (;;)
     ;
 }
index 0904127b17fbae3205ad5a41dbed584712c4d2c5..81adcfb806dd4cac73b134a31aed1de1fdc9c513 100644 (file)
@@ -2,3 +2,19 @@
 # PFDESCR: NVIDIA Tegra 2xx platform
 # PFSELECT: CAN_ARM_CPU_CORTEX_A9 CAN_ARM_CACHE_L2CXX0
 # PFDEPENDS: ARM
+
+choice
+       prompt "Platform Timer"
+       default PF_TEGRA_TIMER_MP
+
+config PF_TEGRA_TIMER_MP
+       bool "MP timer"
+       help
+         ARM local-core multi-processor timer.
+
+config PF_TEGRA_TIMER_TMR
+       bool "TMR timer"
+       help
+         Single broadcasting timer.
+
+endchoice
index c3d093023484a9bbfdba0fcd2f3060617225113f..c49a4386186546eefe0b1cfe2a5a5213427b393a 100644 (file)
@@ -1,7 +1,9 @@
 # vim:set ft=make:
 
-PREPROCESS_PARTS        += tegra2 16550 pic_gic mptimer generic_tickless_idle
-CONFIG_KERNEL_LOAD_ADDR := 0x0
+PREPROCESS_PARTS        += tegra2 16550 pic_gic generic_tickless_idle
+PREPROCESS_PARTS-$(CONFIG_PF_TEGRA_TIMER_MP)  += mptimer
+PREPROCESS_PARTS-$(CONFIG_PF_TEGRA_TIMER_TMR) += tegra_timer_tmr
+RAM_PHYS_BASE           := 0x0
 INTERFACES_KERNEL       += gic
 MPCORE_PHYS_BASE        := 0x50040000
 
@@ -10,8 +12,10 @@ config_IMPL           += config-arm-tegra2
 mem_layout_IMPL       += mem_layout-arm-tegra2
 pic_IMPL              += pic-gic pic-arm-tegra2
 bootstrap_IMPL        += bootstrap-arm-tegra2
-timer_IMPL            += timer-arm-tegra2 timer-arm-mptimer
-timer_tick_IMPL       += timer_tick-single-vector
+timer_IMPL            += $(if $(CONFIG_PF_TEGRA_TIMER_MP),timer-arm-tegra2 timer-arm-mptimer)
+timer_IMPL            += $(if $(CONFIG_PF_TEGRA_TIMER_TMR),timer-arm-tegra2)
+timer_tick_IMPL       += $(if $(CONFIG_PF_TEGRA_TIMER_MP),timer_tick-single-vector)
+timer_tick_IMPL       += $(if $(CONFIG_PF_TEGRA_TIMER_TMR),timer_tick-broadcast)
 kernel_uart_IMPL      += kernel_uart-arm-tegra2
 reset_IMPL            += reset-arm-tegra2
 clock_IMPL            += clock-generic
index b681c7efbd2eb3a21917e7991d00b46c03090970..e0667e4a5da2a6761fcdc76e2525f72471d47a13 100644 (file)
@@ -1,16 +1,5 @@
 INTERFACE [arm && tegra2]:
 
-#include "mem_layout.h"
-
+namespace Bootstrap {
 enum { Cache_flush_area = 0, };
-
-//-----------------------------------------------------------------------------
-IMPLEMENTATION [arm && tegra2]:
-
-void
-map_hw(void *pd)
-{
-  map_dev<Mem_layout::Devices0_phys_base>(pd, 0);
-  map_dev<Mem_layout::Devices1_phys_base>(pd, 1);
-  map_dev<Mem_layout::Devices2_phys_base>(pd, 2);
 }
index e30f7cc92ceb1f497db8a35a6bfa9bba50a26254..b597f552ec8d53a8457353500465765bc0bd8e6f 100644 (file)
@@ -6,9 +6,9 @@ EXTENSION class Kernel_uart { enum { Bsp_init_mode = Init_before_mmu }; };
 IMPLEMENTATION [arm && tegra2 && serial]:
 
 #include "mem_layout.h"
-
+#include "kmem.h"
 IMPLEMENT
 bool Kernel_uart::startup(unsigned port, int /*irq*/)
 {
-  return Uart::startup(Mem_layout::Uart_base, 122);
+  return Uart::startup(Kmem::mmio_remap(Mem_layout::Uart_phys_base), 122);
 }
index c8f81fe6ee4aaab7278fe84846b8cfc25b1eabd5..d566a96084265168e5bf941514d6b3f34202211d 100644 (file)
@@ -3,24 +3,18 @@ INTERFACE [arm && tegra2]:
 EXTENSION class Mem_layout
 {
 public:
-  enum Virt_layout_tegra2 : Address
+  enum Phys_layout_tegra2 : Address
   {
-    Mp_scu_map_base      = Devices2_map_base + 0x00040000,
-    L2cxx0_map_base      = Devices2_map_base + 0x00043000,
+    Mp_scu_phys_base      = 0x50040000,
+    L2cxx0_phys_base      = 0x50043000,
 
-    Gic_cpu_map_base     = Devices2_map_base + 0x00040100,
-    Gic_dist_map_base    = Devices2_map_base + 0x00041000,
-    Gic2_cpu_map_base    = Devices2_map_base + 0x00020000,
-    Gic2_dist_map_base   = Devices2_map_base + 0x00021000,
+    Gic_cpu_phys_base     = 0x50040100,
+    Gic_dist_phys_base    = 0x50041000,
+    Gic2_cpu_phys_base    = 0x50020000,
+    Gic2_dist_phys_base   = 0x50021000,
 
-    Uart_base            = Devices0_map_base + 0x00006300,
-    Clock_reset_map_base = Devices1_map_base + 0x00006000,
-  };
-
-  enum Phys_layout_tegra2 : Address {
-    Devices0_phys_base   = 0x70000000,
-    Devices1_phys_base   = 0x60000000,
-    Devices2_phys_base   = 0x50000000,
-    Sdram_phys_base      = 0x0,
+    Tmr_phys_base         = 0x60005000,
+    Clock_reset_phys_base = 0x60006000,
+    Uart_phys_base        = 0x70006300,
   };
 };
index 56b760b8c9edbb17de228ceb6c4ad84ba2a8b1e6..413326e34936f51af2846bed03f10d1701bc4d30 100644 (file)
@@ -4,8 +4,8 @@ IMPLEMENT
 Mword
 Outer_cache::platform_init(Mword aux_control)
 {
-  Io::write<Mword>(0x331, TAG_RAM_CONTROL);
-  Io::write<Mword>(0x441, DATA_RAM_CONTROL);
+  l2cxx0->write<Mword>(0x331, L2cxx0::TAG_RAM_CONTROL);
+  l2cxx0->write<Mword>(0x441, L2cxx0::DATA_RAM_CONTROL);
 
   aux_control &= 0x8200c3fe;
   aux_control |=   (1 <<  0)  // Full Line of Zero Enable
index b9fd9fae0c44bcce0075dabe903e10371266ca1e..3e748a9695c1f74d6053de9fe1873931ab8058fc 100644 (file)
@@ -17,7 +17,8 @@ void Pic::init()
 
   M *m = new Boot_object<M>(1);
 
-  gic.construct(Kmem::Gic_cpu_map_base, Kmem::Gic_dist_map_base);
+  gic.construct(Kmem::mmio_remap(Mem_layout::Gic_cpu_phys_base),
+                Kmem::mmio_remap(Mem_layout::Gic_dist_phys_base));
   m->add_chip(0, gic, gic->nr_irqs());
 
   Irq_mgr::mgr = m;
@@ -35,7 +36,7 @@ void Pic::restore_all(Status)
 IMPLEMENTATION [arm && mp && pic_gic && tegra2]:
 
 PUBLIC static
-void Pic::init_ap(unsigned)
+void Pic::init_ap(Cpu_number)
 {
   gic->init_ap();
 }
index 87d41da2223bb09a5fff5ef93999d1ec0898ab4c..5a95d6f4642873682f1adbf85397fb3a178190be 100644 (file)
@@ -7,10 +7,10 @@ EXTENSION class Platform_control
 private:
   enum
   {
-    Reset_vector_addr              = Mem_layout::Devices1_map_base + 0xf100,
-    Clk_rst_ctrl_clk_cpu_cmplx     = Mem_layout::Devices1_map_base + 0x604c,
-    Clk_rst_ctrl_rst_cpu_cmplx_clr = Mem_layout::Devices1_map_base + 0x6344,
-    Unhalt_addr                    = Mem_layout::Devices1_map_base + 0x7014,
+    Reset_vector_addr              = 0x6000f100,
+    Clk_rst_ctrl_clk_cpu_cmplx     = 0x6000604c,
+    Clk_rst_ctrl_rst_cpu_cmplx_clr = 0x60006344,
+    Unhalt_addr                    = 0x60007014,
   };
 
   static Mword _orig_reset_vector;
@@ -19,6 +19,7 @@ private:
 IMPLEMENTATION [arm && mp && tegra2]:
 
 #include "io.h"
+#include "kmem.h"
 #include <cstdlib>
 
 Mword Platform_control::_orig_reset_vector;
@@ -26,7 +27,7 @@ Mword Platform_control::_orig_reset_vector;
 PRIVATE static
 void Platform_control::reset_orig_reset_vector()
 {
-  Io::write<Mword>(_orig_reset_vector, Reset_vector_addr);
+  Io::write<Mword>(_orig_reset_vector, Kmem::mmio_remap(Reset_vector_addr));
 }
 
 PUBLIC static
@@ -34,20 +35,20 @@ void
 Platform_control::boot_ap_cpus(Address phys_reset_vector)
 {
   // remember original reset vector
-  _orig_reset_vector = Io::read<Mword>(Reset_vector_addr);
+  _orig_reset_vector = Io::read<Mword>(Kmem::mmio_remap(Reset_vector_addr));
 
   // set (temporary) new reset vector
-  Io::write<Mword>(phys_reset_vector, Reset_vector_addr);
+  Io::write<Mword>(phys_reset_vector, Kmem::mmio_remap(Reset_vector_addr));
 
   atexit(reset_orig_reset_vector);
 
   // clocks on other cpu
-  Mword r = Io::read<Mword>(Clk_rst_ctrl_clk_cpu_cmplx);
-  Io::write<Mword>(r & ~(1 << 9), Clk_rst_ctrl_clk_cpu_cmplx);
+  Mword r = Io::read<Mword>(Kmem::mmio_remap(Clk_rst_ctrl_clk_cpu_cmplx));
+  Io::write<Mword>(r & ~(1 << 9), Kmem::mmio_remap(Clk_rst_ctrl_clk_cpu_cmplx));
   Io::write<Mword>((1 << 13) | (1 << 9) | (1 << 5) | (1 << 1),
-                  Clk_rst_ctrl_rst_cpu_cmplx_clr);
+                  Kmem::mmio_remap(Clk_rst_ctrl_rst_cpu_cmplx_clr));
 
   // kick cpu1
-  Io::write<Mword>(0, Unhalt_addr);
+  Io::write<Mword>(0, Kmem::mmio_remap(Unhalt_addr));
 }
 
index e7e042a123c5406699e169cb7706e0bad73bb1e5..78a03b7479c04afe886292185c67afe160c80816 100644 (file)
@@ -1,24 +1,15 @@
+// ------------------------------------------------------------------------
 IMPLEMENTATION [arm && tegra2]:
 
-#include "io.h"
 #include "kmem.h"
-
-class Tegra2_reset
-{
-public:
-  enum
-  {
-    RESET = Kmem::Clock_reset_map_base + 0x4,
-  };
-};
-
-// ------------------------------------------------------------------------
-IMPLEMENTATION [arm && tegra2]:
+#include "mmio_register_block.h"
 
 void __attribute__ ((noreturn))
 platform_reset(void)
 {
-  Io::write(Io::read<Mword>(Tegra2_reset::RESET) | 4, Tegra2_reset::RESET);
+  enum { RESET = Mem_layout::Clock_reset_phys_base + 0x4 };
+  Mmio_register_block b(Kmem::mmio_remap(RESET));
+  b.modify<Mword>(4, 0, 0);
   for (;;)
     ;
 }
index 3ddb07ebdf5e96af2bc653eb83dcea94227e533d..61a222fc52ec3996ce899927eb2cc5995fffb9db 100644 (file)
@@ -6,3 +6,65 @@ EXTENSION class Timer
 private:
   static Mword interval() { return 249999; }
 };
+
+// --------------------------------------------------------------------------
+INTERFACE [arm && tegra_timer_tmr]:
+
+#include "mmio_register_block.h"
+
+EXTENSION class Timer
+{
+public:
+  static unsigned irq() { return 32; };
+
+private:
+  static Static_object<Mmio_register_block> _tmr;
+
+  struct Reg { enum
+  {
+    PTV = 0,
+    PCR = 4,
+  }; };
+};
+
+// --------------------------------------------------------------------------
+IMPLEMENTATION [arm && tegra_timer_tmr]:
+
+#include "kmem.h"
+
+Static_object<Mmio_register_block> Timer::_tmr;
+
+IMPLEMENT
+void Timer::init(Cpu_number cpu)
+{
+  if (cpu == Cpu_number::boot_cpu())
+    {
+      _tmr.construct(Kmem::mmio_remap(Mem_layout::Tmr_phys_base));
+      _tmr->write<Mword>(  (1 << 31) // enable
+                         | (1 << 30) // periodic
+                         | (Config::Scheduler_granularity & 0x1fffffff),
+                         Reg::PTV);
+    }
+}
+
+
+PUBLIC static inline
+void
+Timer::acknowledge()
+{
+  _tmr->write<Mword>(1 << 30, Reg::PCR);
+}
+
+IMPLEMENT inline
+void
+Timer::update_one_shot(Unsigned64)
+{}
+
+IMPLEMENT inline NEEDS["config.h", "kip.h"]
+Unsigned64
+Timer::system_clock()
+{
+  if (Config::Scheduler_one_shot)
+    return 0;
+  return Kip::k()->clock;
+}
index 25795c5aafd75f407edda5d64d5e0eba8cd65416..136302fec66f9ee14299f41458a0a2506dc21693 100644 (file)
@@ -1,4 +1,15 @@
 /* ARM specific */
+INTERFACE [arm && armv5]:
+
+EXTENSION class Config
+{ public: enum { Access_user_mem = Must_access_user_mem_direct }; };
+
+/* ARM specific */
+INTERFACE [arm && armv6plus]:
+
+EXTENSION class Config
+{ public: enum { Access_user_mem = No_access_user_mem }; };
+
 INTERFACE [arm]:
 
 EXTENSION class Config
@@ -7,16 +18,10 @@ public:
 
   enum
   {
-    Access_user_mem = Must_access_user_mem_direct,
-
     PAGE_SHIFT = ARCH_PAGE_SHIFT,
     PAGE_SIZE  = 1 << PAGE_SHIFT,
     PAGE_MASK  = ~(PAGE_SIZE - 1),
 
-    SUPERPAGE_SHIFT = 20,
-    SUPERPAGE_SIZE  = 1 << SUPERPAGE_SHIFT,
-    SUPERPAGE_MASK  = ~(SUPERPAGE_SIZE -1),
-
     hlt_works_ok = 1,
     Irq_shortcut = 1,
   };
@@ -52,10 +57,10 @@ public:
 
   enum
   {
-#ifdef CONFIG_ARM_CA9_ENABLE_SWP
-    Cp15_c1_use_a9_swp_enable = 1,
+#ifdef CONFIG_ARM_ENABLE_SWP
+    Cp15_c1_use_swp_enable = 1,
 #else
-    Cp15_c1_use_a9_swp_enable = 0,
+    Cp15_c1_use_swp_enable = 0,
 #endif
 #ifdef CONFIG_ARM_ALIGNMENT_CHECK
     Cp15_c1_use_alignment_check = 1,
@@ -68,6 +73,36 @@ public:
 
 };
 
+// -----------------------------------------------------------------------
+INTERFACE [arm && arm_lpae]:
+
+EXTENSION class Config
+{
+public:
+
+  enum
+  {
+    SUPERPAGE_SHIFT = 21,
+    SUPERPAGE_SIZE  = 1 << SUPERPAGE_SHIFT,
+    SUPERPAGE_MASK  = ~(SUPERPAGE_SIZE -1)
+  };
+};
+
+// -----------------------------------------------------------------------
+INTERFACE [arm && !arm_lpae]:
+
+EXTENSION class Config
+{
+public:
+
+  enum
+  {
+    SUPERPAGE_SHIFT = 20,
+    SUPERPAGE_SIZE  = 1 << SUPERPAGE_SHIFT,
+    SUPERPAGE_MASK  = ~(SUPERPAGE_SIZE -1)
+  };
+};
+
 //---------------------------------------------------------------------------
 IMPLEMENTATION [arm]:
 
index dddedde63dcb3a5247778ffb686e7e81d1ba0122..336665cfd68f2766e83d2a48965b41e530a7258e 100644 (file)
@@ -27,7 +27,7 @@ public:
     Cp15_c1_high_vector     = 1 << 13,
   };
 
-  Cpu(unsigned id) { set_id(id); }
+  Cpu(Cpu_number id) { set_id(id); }
 
 
   struct Ids {
@@ -47,7 +47,7 @@ public:
 private:
   static Cpu *_boot_cpu;
 
-  unsigned _phys_id;
+  Cpu_phys_id _phys_id;
   Ids _cpu_id;
 };
 
@@ -154,42 +154,11 @@ public:
                              | Cp15_c1_branch_predict
                              | Cp15_c1_high_vector
                               | Cp15_c1_rao_sbop
-                             | (Config::Cp15_c1_use_a9_swp_enable ?  Cp15_c1_sw : 0),
+                             | (Config::Cp15_c1_use_swp_enable ? Cp15_c1_sw : 0),
   };
 };
 
-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<Mword>(0xffffffff, Inv); }
-
-  static void enable(Mword bits = 0)
-  {
-    Unsigned32 ctrl = Io::read<Unsigned32>(Control);
-    if (!(ctrl & Control_enable))
-      Io::write<Unsigned32>(ctrl | bits | Control_enable, Control);
-  }
-};
-
-
+// -------------------------------------------------------------------------------
 INTERFACE [arm]:
 
 EXTENSION class Cpu
@@ -210,15 +179,6 @@ private:
   void bsp_init(bool) {}
 };
 
-//---------------------------------------------------------------------------
-INTERFACE [arm && (mpcore || armca9) && !bsp_cpu]:
-
-EXTENSION class Scu
-{
-public:
-  enum { Bsp_enable_bits = 0 };
-};
-
 //-------------------------------------------------------------------------
 IMPLEMENTATION [arm]:
 
@@ -254,7 +214,16 @@ bool
 Cpu::is_smp_capable()
 {
   // ACTRL is implementation defined
-  return (midr() & 0xff0ffff0) == 0x410fc090;
+  Mword id = midr();
+  if ((id & 0xff0fff00) == 0x410fc000)
+    {
+      switch ((id >> 4) & 0xf)
+        {
+        case 7: case 9: case 15: return true;
+        }
+    }
+
+  return false;
 }
 
 PUBLIC static inline
@@ -264,10 +233,12 @@ Cpu::enable_smp()
   if (!is_smp_capable())
     return;
 
+  Mword v = ((midr() >> 4) & 7) == 7 ? 0x40 : 0x41;
+
   Mword actrl;
   asm volatile ("mrc p15, 0, %0, c1, c0, 1" : "=r" (actrl));
   if (!(actrl & 0x40))
-    asm volatile ("mcr p15, 0, %0, c1, c0, 1" : : "r" (actrl | 0x41));
+    asm volatile ("mcr p15, 0, %0, c1, c0, 1" : : "r" (actrl | v));
 }
 
 PUBLIC static inline NEEDS[Cpu::clear_actrl]
@@ -280,19 +251,34 @@ Cpu::disable_smp()
   clear_actrl(0x41);
 }
 
+//---------------------------------------------------------------------------
+INTERFACE [arm && (mpcore || armca9)]:
+
+#include "scu.h"
+
+EXTENSION class Cpu
+{
+public:
+ static Static_object<Scu> scu;
+};
+
 //---------------------------------------------------------------------------
 IMPLEMENTATION [arm && (mpcore || armca9)]:
 
+#include "kmem.h"
+
+Static_object<Scu> Cpu::scu;
+
 PRIVATE static inline void
 Cpu::early_init_platform()
 {
-  Scu::reset();
-  Scu::enable(Scu::Bsp_enable_bits);
+  if (Scu::Available)
+    {
+      scu.construct(Kmem::mmio_remap(Mem_layout::Mp_scu_phys_base));
 
-  Io::write<Mword>(Io::read<Mword>(Mem_layout::Gic_cpu_map_base + 0) | 1,
-                   Mem_layout::Gic_cpu_map_base + 0);
-  Io::write<Mword>(Io::read<Mword>(Mem_layout::Gic_dist_map_base + 0) | 1,
-                   Mem_layout::Gic_dist_map_base + 0);
+      scu->reset();
+      scu->enable(Scu::Bsp_enable_bits);
+    }
 
   Mem_unit::clean_dcache();
 
@@ -313,7 +299,7 @@ IMPLEMENTATION [arm]:
 #include <panic.h>
 
 #include "io.h"
-#include "pagetable.h"
+#include "paging.h"
 #include "kmem_space.h"
 #include "kmem_alloc.h"
 #include "mem_unit.h"
@@ -343,7 +329,8 @@ void Cpu::early_init()
                  :
                  : "r" (Config::Cache_enabled
                         ? Cp15_c1_cache_enabled : Cp15_c1_cache_disabled),
-                   "I" (0x0d3)
+                   "I" (Proc::Status_mode_supervisor
+                        | Proc::Status_interrupts_disabled)
                  : "r2", "r3");
 
   early_init_platform();
@@ -397,18 +384,18 @@ 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.set((unsigned long)&ivt_start, 4096,
-          Mem_page_attr(Page::KERN_RW | Page::CACHEABLE), true);
+  auto pte = Kmem_space::kdir()->walk(Virt_addr(Kmem_space::Ivt_base),
+      Pdir::Depth, true,
+      Kmem_alloc::q_allocator(Ram_quota::root));
 
+  pte.create_page(Phys_mem_addr((unsigned long)&ivt_start), Page::Attr(Page::Rights::RWX(),
+        Page::Type::Normal(), Page::Kern::Global()));
+  pte.write_back_if(true);
   Mem_unit::tlb_flush();
 }
 
 PUBLIC inline
-unsigned
+Cpu_phys_id
 Cpu::phys_id() const
 { return _phys_id; }
 
@@ -452,6 +439,16 @@ Cpu::disable_dcache()
                : : "r" (0), "i" (Cp15_c1_cache));
 }
 
+//---------------------------------------------------------------------------
+IMPLEMENTATION [arm && !arm_lpae]:
+
+PUBLIC static inline unsigned Cpu::phys_bits() { return 32; }
+
+//---------------------------------------------------------------------------
+IMPLEMENTATION [arm && arm_lpae]:
+
+PUBLIC static inline unsigned Cpu::phys_bits() { return 40; }
+
 //---------------------------------------------------------------------------
 IMPLEMENTATION [arm && !armv6plus]:
 
@@ -574,7 +571,7 @@ Cpu::init_errata_workarounds()
 }
 
 //---------------------------------------------------------------------------
-IMPLEMENTATION [arm && !tz]:
+IMPLEMENTATION [arm && !arm_em_tz]:
 
 PRIVATE static inline
 void
@@ -582,17 +579,16 @@ Cpu::init_tz()
 {}
 
 //---------------------------------------------------------------------------
-INTERFACE [arm && tz]:
+INTERFACE [arm && arm_em_tz]:
 
 EXTENSION class Cpu
 {
 public:
-
   static char monitor_vector_base asm ("monitor_vector_base");
 };
 
 //---------------------------------------------------------------------------
-IMPLEMENTATION [arm && tz]:
+IMPLEMENTATION [arm && arm_em_tz]:
 
 #include <cassert>
 
@@ -602,26 +598,61 @@ Cpu::init_tz()
 {
   // set monitor vector base address
   assert(!((Mword)&monitor_vector_base & 31));
-  tz_mvbar((Mword)&monitor_vector_base);
+  asm volatile ("mcr p15, 0, %0, c12, c0, 1" : : "r" (&monitor_vector_base));
+
+  Mword dummy;
+  asm volatile (
+      "mov  %[dummy], sp \n"
+      "cps  #0x16        \n"
+      "mov  sp, %[dummy] \n"
+      : [dummy] "=r" (dummy) : : "lr" );
+  // running in monitor mode
+
+  asm ("mcr  p15, 0, %[scr], c1, c1, 0" : : [scr] "r" (0x1));
+  Mem::isb();
+
+  asm ("mcr  p15, 0, %0, c12, c0, 0" : : "r" (0)); // reset VBAR
+  asm ("mcr  p15, 0, %0, c13, c0, 0" : : "r" (0)); // reset FCSEIDR
+  asm ("mcr  p15, 0, %0, c1, c0, 0"  : : "r" (0x4500a0));  // SCTLR = U | (18) | (16) | (7)
+
+  asm ("mcr  p15, 0, %[scr], c1, c1, 0 \n" : : [scr] "r" (0x100));
+  Mem::isb();
+  asm volatile (
+      "mov  %[dummy], sp \n"
+      "cps  #0x13        \n"
+      "mov  sp, %[dummy] \n"
+      : [dummy] "=r" (dummy) : : "lr" );
+  // running in svc mode
+
 
   // enable nonsecure access to vfp coprocessor
-  asm volatile("mov r0, #0xc00;"
-               "mcr p15, 0, r0, c1, c1, 2;"
-               : : : "r0"
-              );
+  asm volatile("mcr p15, 0, %0, c1, c1, 2" : : "r" (0xc00));
 
-  enable_irq_ovrr();
+  enum
+  {
+    SCR_NS  = 1 << 0,
+    SCR_IRQ = 1 << 1,
+    SCR_FIQ = 1 << 2,
+    SCR_EA  = 1 << 3,
+    SCR_FW  = 1 << 4,
+    SCR_AW  = 1 << 5,
+    SCR_nET = 1 << 6,
+    SCR_SCD = 1 << 7,
+    SCR_HCE = 1 << 8,
+    SCR_SIF = 1 << 9,
+  };
 }
 
 PUBLIC inline
 void
 Cpu::tz_switch_to_ns(Mword *nonsecure_state)
 {
-  volatile register Mword r0 asm("r0") = (Mword)nonsecure_state;
-  extern char go_nonsecure;
+  extern char go_nonsecure[];
+
+  register Mword r0 asm("r0") = (Mword)nonsecure_state;
+  register Mword r1 asm("r1") = (Mword)go_nonsecure;
 
-  asm volatile("stmdb sp!, {fp}   \n"
-               "stmdb sp!, {r0}   \n"
+  asm volatile("stmdb sp!, {r0}   \n"
                "mov    r2, sp     \n" // copy sp_svc to sp_mon
                "cps    #0x16      \n" // switch to monitor mode
                "mov    sp, r2     \n"
@@ -633,10 +664,9 @@ Cpu::tz_switch_to_ns(Mword *nonsecure_state)
                "cps    #0x13      \n" // switch to svc mode
                "mov    sp, r0     \n"
                "ldmia  sp!, {r0}  \n"
-               "ldmia  sp!, {fp}  \n"
-               : : "r" (r0), "r" (&go_nonsecure)
+               : : "r" (r0), "r" (r1)
                : "r2", "r3", "r4", "r5", "r6", "r7",
-                 "r8", "r9", "r10", "r12", "r14", "memory");
+                 "r8", "r9", "r10", "r11", "r12", "r14", "memory");
 }
 
 PUBLIC static inline
@@ -655,42 +685,6 @@ Cpu::tz_scr(Mword val)
   asm volatile ("mcr p15, 0, %0, c1, c1, 0" : : "r" (val));
 }
 
-PUBLIC static inline
-Mword
-Cpu::tz_mvbar()
-{
-  Mword r;
-  asm volatile ("mrc p15, 0, %0, c12, c0, 1" : "=r" (r));
-  return r;
-}
-
-PUBLIC static inline
-void
-Cpu::tz_mvbar(Mword val)
-{
-  asm volatile ("mcr p15, 0, %0, c12, c0, 1" : : "r" (val));
-}
-
-// ------------------------------------------------------------------------
-IMPLEMENTATION [arm && tz && armca9]:
-
-PUBLIC static inline
-void
-Cpu::enable_irq_ovrr()
-{
-  // set IRQ/FIQ/Abort override bits
-  asm volatile("mov r0, #0x1c0            \n"
-               "mcr p15, 0, r0, c1, c1, 3 \n"
-               : : : "r0");
-}
-
-IMPLEMENTATION [!tz || !armca9]:
-
-PUBLIC static inline
-void
-Cpu::enable_irq_ovrr()
-{}
-
 // ------------------------------------------------------------------------
 IMPLEMENTATION [!debug]:
 
index b221b76cf91037dfdc2ed08a4937193dbc537572..b72a0cb972aa7ec79245d9befa56777d0eedb754 100644 (file)
@@ -1,5 +1,7 @@
 INTERFACE [arm && fpu]:
 
+#include <cxx/bitfield>
+
 EXTENSION class Fpu
 {
 public:
@@ -10,8 +12,6 @@ public:
     Mword fpinst2;
   };
 
-  Mword fpsid() const { return _fpsid; }
-
   enum
   {
     FPEXC_EN  = 1 << 30,
@@ -24,17 +24,27 @@ public:
     Mword state[32 * 4]; // 4*32 bytes for each FP-reg
   };
 
-  static Mword fpsid_rev(Mword v)          { return v & 0xf; }
-  static Mword fpsid_variant(Mword v)      { return (v >> 4) & 0xf; }
-  static Mword fpsid_part_number(Mword v)  { return (v >> 8) & 0xff; }
-  static Mword fpsid_arch_version(Mword v) { return (v >> 16) & 0xf; }
-  static Mword fpsid_precision(Mword v)    { return (v >> 20) & 1; }
-  static Mword fpsid_format(Mword v)       { return (v >> 21) & 3; }
-  static Mword fpsid_hw_sw(Mword v)        { return (v >> 23) & 1; }
-  static Mword fpsid_implementer(Mword v)  { return v >> 24; }
+  struct Fpsid
+  {
+    Mword v;
+
+    Fpsid() = default;
+    explicit Fpsid(Mword v) : v(v) {}
+
+    CXX_BITFIELD_MEMBER(0, 3, rev, v);
+    CXX_BITFIELD_MEMBER(4, 7, variant, v);
+    CXX_BITFIELD_MEMBER(8, 15, part_number, v);
+    CXX_BITFIELD_MEMBER(16, 19, arch_version, v);
+    CXX_BITFIELD_MEMBER(20, 20, precision, v);
+    CXX_BITFIELD_MEMBER(21, 22, format, v);
+    CXX_BITFIELD_MEMBER(23, 23, hw_sw, v);
+    CXX_BITFIELD_MEMBER(24, 31, implementer, v);
+  };
+
+  Fpsid fpsid() const { return _fpsid; }
 
 private:
-  Mword _fpsid;
+  Fpsid _fpsid;
 };
 
 // ------------------------------------------------------------------------
@@ -189,19 +199,19 @@ Fpu::emulate_insns(Mword opcode, Trap_state *ts)
 {
   unsigned reg = (opcode >> 16) & 0xf;
   unsigned rt  = (opcode >> 12) & 0xf;
-  Mword fpsid = Fpu::fpu.current().fpsid();
+  Fpsid fpsid = Fpu::fpu.current().fpsid();
   switch (reg)
     {
     case 0: // FPSID
-      ts->r[rt] = fpsid;
+      ts->r[rt] = fpsid.v;
       break;
     case 6: // MVFR1
-      if (Fpu::fpsid_arch_version(fpsid) < 2)
+      if (fpsid.arch_version() < 2)
         return false;
       ts->r[rt] = Fpu::mvfr1();
       break;
     case 7: // MVFR0
-      if (Fpu::fpsid_arch_version(fpsid) < 2)
+      if (fpsid.arch_version() < 2)
         return false;
       ts->r[rt] = Fpu::mvfr0();
       break;
@@ -219,26 +229,29 @@ Fpu::emulate_insns(Mword opcode, Trap_state *ts)
 
 IMPLEMENT
 void
-Fpu::init(unsigned cpu)
+Fpu::init(Cpu_number cpu)
 {
   copro_enable();
 
-  Mword s = fpsid_read();
+  const Fpsid s(fpsid_read());
 
   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
-           ? "VFPv2"
-           : (fpsid_arch_version(s) == 3 ? "VFPv3" : "Unkn"),
-         fpsid_arch_version(s),
-         fpsid_part_number(s) == 0x20
+  unsigned arch = s.arch_version();
+  printf("FPU%d: Arch: %s(%x), Part: %s(%x), r: %x, v: %x, i: %x, t: %s, p: %s\n",
+         cxx::int_value<Cpu_number>(cpu),
+         arch == 1 ? "VFPv2"
+                   : (arch == 3 ? "VFPv3"
+                                : (arch == 4 ? "VFPv4"
+                                             : "Unkn")),
+         arch,
+         (int)s.part_number() == 0x20
            ? "VFP11"
-           : (fpsid_part_number(s) == 0x30 ?  "VFPv3" : "Unkn"),
-         fpsid_part_number(s),
-         fpsid_rev(s), fpsid_variant(s), fpsid_implementer(s),
-         fpsid_hw_sw(s) ? "soft" : "hard",
-         fpsid_precision(s) ? "sngl" : "dbl/sngl");
+           : (s.part_number() == 0x30 ?  "VFPv3" : "Unkn"),
+         (int)s.part_number(),
+         (int)s.rev(), (int)s.variant(), (int)s.implementer(),
+         (int)s.hw_sw() ? "soft" : "hard",
+         (int)s.precision() ? "sngl" : "dbl/sngl");
 
   disable();
 
index 8b5f5f5c4dd6e0afa415dbb908be0c57f8e86ee6..c43ebcb3b7cf995b5b917f03df2f623fde97b84a 100644 (file)
@@ -16,8 +16,10 @@ public:
     DIST_CTRL         = 0x000,
     DIST_CTR          = 0x004,
     DIST_IRQ_SEC      = 0x080,
+    GICD_IGROUPR      = DIST_IRQ_SEC, // new name
     DIST_ENABLE_SET   = 0x100,
     DIST_ENABLE_CLEAR = 0x180,
+    DIST_SET_PENDING  = 0x200,
     DIST_CLR_PENDING  = 0x280,
     DIST_PRI          = 0x400,
     DIST_TARGET       = 0x800,
@@ -41,8 +43,10 @@ public:
     MXC_TZIC_CTRL_NSEN       = 1 << 16,
     MXC_TZIC_CTRL_NSENMASK   = 1 << 31,
 
-    CPU_CTRL_ENABLE          = 1,
-    CPU_CTRL_USE_FIQ_FOR_SEC = 8,
+    CPU_CTRL_ENABLE_GRP0     = 1 << 0,
+    CPU_CTRL_ENABLE          = CPU_CTRL_ENABLE_GRP0,
+    CPU_CTRL_ENABLE_GRP1     = 1 << 1,
+    CPU_CTRL_USE_FIQ_FOR_SEC = 1 << 3,
   };
 
 };
@@ -58,14 +62,14 @@ INTERFACE [arm && pic_gic && !pic_gic_mxc_tzic]:
 EXTENSION class Gic { enum { Config_mxc_tzic = 0 }; };
 
 // ------------------------------------------------------------------------
-INTERFACE [arm && tz]:
+INTERFACE [arm && arm_em_tz]:
 
-EXTENSION class Gic { enum { Config_tz = 1 }; };
+EXTENSION class Gic { enum { Config_tz_sec = 1 }; };
 
 // ------------------------------------------------------------------------
-INTERFACE [arm && !tz]:
+INTERFACE [arm && !arm_em_tz]:
 
-EXTENSION class Gic { enum { Config_tz = 0 }; };
+EXTENSION class Gic { enum { Config_tz_sec = 0 }; };
 
 
 //-------------------------------------------------------------------
@@ -79,6 +83,7 @@ IMPLEMENTATION [arm && pic_gic]:
 #include "io.h"
 #include "irq_chip_generic.h"
 #include "panic.h"
+#include "processor.h"
 
 PUBLIC inline NEEDS["io.h"]
 unsigned
@@ -93,19 +98,54 @@ Gic::has_sec_ext()
 PUBLIC inline
 void Gic::softint_cpu(unsigned callmap, unsigned m)
 {
-  Io::write<Mword>((callmap & 0xff) << 16 | m, _dist_base + DIST_SOFTINT);
+  Io::write<Mword>(((callmap & 0xff) << 16) | m, _dist_base + DIST_SOFTINT);
 }
 
 PUBLIC inline
 void Gic::softint_bcast(unsigned m)
-{ Io::write<Mword>(1 << 24 | m, _dist_base + DIST_SOFTINT); }
+{ Io::write<Mword>((1 << 24) | m, _dist_base + DIST_SOFTINT); }
+
+PRIVATE
+void
+Gic::cpu_init()
+{
+  Io::write<Mword>(0, _cpu_base + CPU_CTRL);
+
+  Io::write<Mword>(0xffffffff, _dist_base + DIST_ENABLE_CLEAR);
+  if (Config_tz_sec)
+    {
+      Io::write<Mword>(0x00000f00, _dist_base + DIST_ENABLE_SET);
+      Io::write<Mword>(0xfffff0ff, _dist_base + GICD_IGROUPR);
+    }
+  else
+    {
+      Io::write<Mword>(0x0000001e, _dist_base + DIST_ENABLE_SET);
+      Io::write<Mword>(0, _dist_base + GICD_IGROUPR);
+    }
+
+  Io::write<Mword>(0xffffffff, _dist_base + DIST_CLR_PENDING);
+
+  Io::write<Mword>(0xffffffff, _dist_base + 0x380); // clear active
+  Io::write<Mword>(0xffffffff, _dist_base + 0xf10); // sgi pending clear
+  Io::write<Mword>(0xffffffff, _dist_base + 0xf14); // sgi pending clear
+  Io::write<Mword>(0xffffffff, _dist_base + 0xf18); // sgi pending clear
+  Io::write<Mword>(0xffffffff, _dist_base + 0xf1c); // sgi pending clear
+
+  for (unsigned i = 0; i < 32; i += 4)
+    Io::write<Mword>(0xa0a0a0a0, _dist_base + DIST_PRI + i);
+
+  if (Config_tz_sec)
+    Io::write<Mword>(0x40404040, _dist_base + DIST_PRI + 8);
+
+  Io::write<Mword>(CPU_CTRL_ENABLE | (Config_tz_sec ? CPU_CTRL_USE_FIQ_FOR_SEC : 0), _cpu_base + CPU_CTRL);
+  Io::write<Mword>(0xf0, _cpu_base + CPU_PRIMASK);
+}
 
 PUBLIC
 void
 Gic::init_ap()
 {
-  Io::write<Mword>(CPU_CTRL_ENABLE, _cpu_base + CPU_CTRL);
-  Io::write<Mword>(0xf0, _cpu_base + CPU_PRIMASK);
+  cpu_init();
 }
 
 PUBLIC
@@ -114,7 +154,7 @@ Gic::init(bool primary_gic, int nr_irqs_override = -1)
 {
   if (!primary_gic)
     {
-      init_ap();
+      cpu_init();
       return 0;
     }
 
@@ -126,7 +166,7 @@ Gic::init(bool primary_gic, int nr_irqs_override = -1)
 
   if (!Config_mxc_tzic)
     {
-      unsigned int intmask = 1 << Proc::cpu_id();
+      unsigned int intmask = 1U << cxx::int_value<Cpu_phys_id>(Proc::cpu_id());
       intmask |= intmask << 8;
       intmask |= intmask << 16;
 
@@ -135,19 +175,27 @@ Gic::init(bool primary_gic, int nr_irqs_override = -1)
       for (unsigned i = 32; i < num; i += 4)
         Io::write<Mword>(intmask, _dist_base + DIST_TARGET + i);
     }
-  for (unsigned i = 0; i < num; i += 4)
+
+  for (unsigned i = 32; i < num; i += 4)
     Io::write<Mword>(0xa0a0a0a0, _dist_base + DIST_PRI + i);
-  for (unsigned i = 0; i < num; i += 32)
+
+  for (unsigned i = 32; i < num; i += 32)
     Io::write<Mword>(0xffffffff, _dist_base + DIST_ENABLE_CLEAR + i * 4 / 32);
 
-  if (Config_mxc_tzic && !Config_tz)
-    for (unsigned i = 0; i < num; i += 32)
-      Io::write<Mword>(0xffffffff, _dist_base + DIST_IRQ_SEC + i * 4 / 32);
+  Mword v = 0;
+  if (Config_tz_sec || Config_mxc_tzic)
+    v = 0xffffffff;
+
+  for (unsigned i = 32; i < num; i += 32)
+    Io::write<Mword>(v, _dist_base + GICD_IGROUPR + i / 8);
 
   Mword dist_enable = DIST_CTRL_ENABLE;
-  if (Config_mxc_tzic && !Config_tz)
+  if (Config_mxc_tzic && !Config_tz_sec)
     dist_enable |= MXC_TZIC_CTRL_NSEN | MXC_TZIC_CTRL_NSENMASK;
 
+  for (unsigned i = 0; i < num; ++i)
+    set_cpu(i, Cpu_number(0));
+
   Io::write<Mword>(dist_enable, _dist_base + DIST_CTRL);
 
   if (Config_mxc_tzic)
@@ -156,10 +204,7 @@ Gic::init(bool primary_gic, int nr_irqs_override = -1)
       Io::write<Mword>(0xf0, _dist_base + MXC_TZIC_PRIOMASK);
     }
   else
-    {
-      Io::write<Mword>(CPU_CTRL_ENABLE, _cpu_base + CPU_CTRL);
-      Io::write<Mword>(0xf0, _cpu_base + CPU_PRIMASK);
-    }
+    cpu_init();
 
   return num;
 }
@@ -173,8 +218,6 @@ Gic::Gic(Address cpu_base, Address dist_base, int nr_irqs_override = -1)
   printf("Number of IRQs available at this GIC: %d\n", num);
 
   Irq_chip_gen::init(num);
-
-  //enable_tz_support();
 }
 
 /**
@@ -264,12 +307,55 @@ Gic::cascade_hit(Irq_base *_self, Upstream_irq const *u)
   gic->hit(&ui);
 }
 
+//-------------------------------------------------------------------
+IMPLEMENTATION [arm && arm_em_tz]:
+
+PUBLIC
+bool
+Gic::alloc(Irq_base *irq, Mword pin)
+{
+  if (Irq_chip_gen::alloc(irq, pin))
+    {
+      printf("GIC: Switching IRQ %ld to secure\n", pin);
+
+      unsigned shift = (pin & 3) * 8;
+
+      if (pin < 32)
+        {
+          assert(((Io::read<Mword>(_dist_base + GICD_IGROUPR) >> pin) & 1) == 0);
+          assert(((Io::read<Mword>(_dist_base + DIST_PRI + (pin & ~3)) >> shift) & 0xff) == 0x40);
+        }
+      else
+        {
+          Io::clear<Mword>(1UL << (pin & 0x1f),
+                           _dist_base + GICD_IGROUPR + (pin & ~0x1f) / 8);
+
+          Io::modify<Mword>(0x40 << shift, 0xff << shift,
+                            _dist_base + DIST_PRI + (pin & ~3));
+        }
+      return true;
+    }
+  return false;
+}
+
+PUBLIC
+void
+Gic::set_pending_irq(unsigned idx, Unsigned32 val)
+{
+  if (idx < 32)
+    {
+      Address o = _dist_base + idx * 4;
+      Io::write<Mword>(val & Io::read<Mword>(o + GICD_IGROUPR),
+                       o + DIST_SET_PENDING);
+    }
+}
+
 //-------------------------------------------------------------------
 IMPLEMENTATION [arm && !mp && pic_gic]:
 
 PUBLIC
 void
-Gic::set_cpu(Mword, unsigned)
+Gic::set_cpu(Mword, Cpu_number)
 {}
 
 PUBLIC inline NEEDS["io.h"]
@@ -309,51 +395,18 @@ Unsigned32 Gic::pending()
 
 PUBLIC inline NEEDS["cpu.h"]
 void
-Gic::set_cpu(Mword pin, unsigned cpu)
+Gic::set_cpu(Mword pin, Cpu_number cpu)
 {
   Mword reg = _dist_base + DIST_TARGET + (pin & ~3);
   Mword val = Io::read<Mword>(reg);
 
   int shift = (pin % 4) * 8;
-  val = (val & ~(0xf << shift)) | (1 << (Cpu::cpus.cpu(cpu).phys_id() + shift));
+  unsigned pcpu = cxx::int_value<Cpu_phys_id>(Cpu::cpus.cpu(cpu).phys_id());
+  val = (val & ~(0xf << shift)) | (1 << (pcpu + shift));
 
   Io::write<Mword>(val, reg);
 }
 
-
-//-------------------------------------------------------------------
-IMPLEMENTATION [arm && pic_gic && tz]:
-
-#if 0
-PRIVATE
-void
-Gic::set_irq_nonsecure(unsigned irqnum)
-{
-  Io::set<Mword>(1 << (irqnum % 32),
-                 _dist_base + DIST_IRQ_SEC + ((irqnum & ~31) / 8));
-}
-#endif
-
-PUBLIC inline NEEDS[<cstdio>]
-void
-Gic::enable_tz_support()
-{
-  if (has_sec_ext())
-    printf("GIC:Has security extension\n");
-
-  printf("GIC: Signal secure Interrupts as FIQs!\n");
-  Io::write<Mword>(CPU_CTRL_ENABLE | CPU_CTRL_USE_FIQ_FOR_SEC,
-                   _cpu_base + CPU_CTRL);
-}
-
-//-------------------------------------------------------------------
-IMPLEMENTATION [arm && pic_gic && !tz]:
-
-PUBLIC inline
-void
-Gic::enable_tz_support()
-{}
-
 //---------------------------------------------------------------------------
 IMPLEMENTATION [debug]:
 
index c1198c1aee720402e557a9c13745182c1efab734..7c2f7d929c49fc1af32a6f02880449becdc03885 100644 (file)
@@ -5,39 +5,54 @@ IMPLEMENTATION [mp]:
 #include "gic.h"
 #include "processor.h"
 
+IMPLEMENTATION [mp && arm_em_tz]: // --------------------------------------
+
 EXTENSION class Ipi
 {
-private:
-  Unsigned32 _phys_id;
+public:
+  enum { Ipi_start = 8 };
+};
+
+IMPLEMENTATION [mp && !arm_em_tz]: // -------------------------------------
+
+EXTENSION class Ipi
+{
+public:
+  enum { Ipi_start = 1 };
+};
+
+IMPLEMENTATION [mp]: // ---------------------------------------------------
 
+EXTENSION class Ipi
+{
 public:
   enum Message
   {
-    Ipi_start = 1,
-    Global_request = Ipi_start, Request, Debug,
+    Global_request = Ipi_start, Request, Debug, Timer,
     Ipi_end
   };
+private:
+  Cpu_phys_id _phys_id;
 };
 
 
 PUBLIC inline
-Ipi::Ipi() : _phys_id(~0)
+Ipi::Ipi() : _phys_id(Cpu_phys_id(~0))
 {}
 
 IMPLEMENT inline NEEDS["processor.h"]
 void
-Ipi::init(unsigned cpu)
+Ipi::init(Cpu_number cpu)
 {
   _ipi.cpu(cpu)._phys_id = Proc::cpu_id();
 }
 
 PUBLIC static
 void Ipi::ipi_call_debug_arch()
-{
-}
+{}
 
 PUBLIC static inline
-void Ipi::eoi(Message, unsigned on_cpu)
+void Ipi::eoi(Message, Cpu_number on_cpu)
 {
   // with the ARM-GIC we have to do the EOI right after the ACK
   stat_received(on_cpu);
@@ -47,15 +62,22 @@ void Ipi::eoi(Message, unsigned on_cpu)
 IMPLEMENTATION [mp && !irregular_gic]:
 
 PUBLIC static inline NEEDS["pic.h"]
-void Ipi::send(Message m, unsigned from_cpu, unsigned to_cpu)
+void Ipi::send(Message m, Cpu_number from_cpu, Cpu_number to_cpu)
+{
+  Pic::gic->softint_cpu(1UL << cxx::int_value<Cpu_phys_id>(_ipi.cpu(to_cpu)._phys_id), m);
+  stat_sent(from_cpu);
+}
+
+PUBLIC static inline NEEDS["pic.h"]
+void Ipi::send(Message m, Cpu_number from_cpu, Cpu_phys_id to_cpu)
 {
-  Pic::gic->softint_cpu(1 << _ipi.cpu(to_cpu)._phys_id, m);
+  Pic::gic->softint_cpu(1UL <<  cxx::int_value<Cpu_phys_id>(to_cpu), m);
   stat_sent(from_cpu);
 }
 
 PUBLIC static inline
 void
-Ipi::bcast(Message m, unsigned from_cpu)
+Ipi::bcast(Message m, Cpu_number from_cpu)
 {
   (void)from_cpu;
   Pic::gic->softint_bcast(m);
index b3a7d7184fa7163e406ae68e22ac09a8f6d68ff4..cc0c563d376875d003b221c6fa7067f3ec7bb16e 100644 (file)
@@ -3,38 +3,9 @@
 #include "globalconfig.h"
 #include "config_tcbsize.h"
 #include "tcboffset.h"
+#include "asm_entry.h"
 
 
-
-/**********************************************************************
- * calculate the TCB address from a stack pointer
- */
-.macro CONTEXT_OF reg, ptr
-       bic     \reg, \ptr, #((THREAD_BLOCK_SIZE-1) & 0xff)
-       bic     \reg, \reg, #((THREAD_BLOCK_SIZE-1) & 0xff00)
-.endm
-
-/**********************************************************************
- * Reset the thread cancel flag. 
- * Register r0 is scratched and contains the thread state afterwards
- */
-.macro RESET_THREAD_CANCEL_AT tcb
-       ldr     r0, [\tcb, #(OFS__THREAD__STATE)]
-       bic     r0, r0, #0x100
-       str     r0, [\tcb, #(OFS__THREAD__STATE)]
-.endm
-
-/****************************
- * some handy definitions
- */
-#define RF_SIZE      20
-#define RF_PSR       16
-#define RF_PC        12
-#define RF_SVC_LR     8
-#define RF_USR_LR     4
-#define RF_USR_SP     0
-#define RF(reg, offs) (RF_##reg + (offs))
-
 /**************************************************************************
  * Enter kernel mode (i.e. switch from any exception mode to the 
  * kernel mode and transfer the exception state).
  *
  * Stack the state and call 'slowtrap_entry' with sp and error code
  */
-.macro         enter_slowtrap_w_stack errorcode
-       mov     r1, #\errorcode
-       stmdb   sp!, {r0, r1}
-       mov     r0, sp
-       adr     lr, exception_return
-       ldr     pc, .LCslowtrap_entry
-.endm
-
 .macro         enter_slowtrap errorcode
        stmdb   sp!, {r0 - r12}
        make_tpidruro_space sp
  *
  * lr: must contain fault addr (from switch_to_kernel)
  */
-.macro syscallframe    
-       add     lr, sp, #RF(PC, -8)
-       stmia   lr, {lr}^
-       sub     sp, sp, #8
-.endm
-
 .macro  enter_sys_call no_sys_call
-       ldr     lr, [sp, #RF(PC,  -8)]
+       ldr     lr, [sp, #RF(PC,  0)]
        cmn     lr, #0x2a               @ Range Check !!! UNSIGNED !!!
        bls     \no_sys_call            @ no syscall
        cmn     lr, #0x08
        bhi     \no_sys_call
-       syscallframe                    
+
+       add     lr, sp, #RF(PC, 0)
+       stmia   lr, {lr}^
+
        stmdb   sp!, {r0 - r12}
        CONTEXT_OF      r1, sp
        RESET_THREAD_CANCEL_AT r1       @ sets r0 to state 
@@ -226,6 +186,7 @@ fast_ret_from_irq:
         msr    cpsr_c, #0xd3 // disable IRQs
         add     sp, sp, #13*4
 
+        // XXX: use rfe here
        /* Return */
        ldr     lr, [sp, #RF(PSR,0)]
        msr     spsr_cfsx, lr
@@ -235,13 +196,13 @@ fast_ret_from_irq:
        movs    pc, lr
 .endm
 
-
 /**************************************************************************
  * The Exception vector table.
  */
 .section       .vect,"a"
 .globl exception_vector
 exception_vector:
+#ifndef CONFIG_ARM_EM_TZ
        nop                             /* RESET        */
        b       undef_entry             /* UNDEF        */
        b       swi_entry               /* SWI          */
@@ -250,7 +211,28 @@ exception_vector:
        nop                             /* reserved     */
        b       irq_entry               /* IRQ          */
        b       fiq_entry               /* FIQ          */
+#else
+       nop                             /* RESET        */
+       adr     pc, (fiq_b_vector + 8)  /* UNDEF        */
+       adr     pc, (fiq_b_vector + 16) /* SWI          */
+       adr     pc, (fiq_b_vector + 24) /* IABORT       */
+       adr     pc, (fiq_b_vector + 32) /* DABORT       */
+       nop                             /* reserved     */
+       b       irq_entry               /* IRQ          */
+       b       fiq_entry               /* FIQ          */
 
+fiq_b_vector:
+       nop                             /* RESET        */
+        nop
+       cpsid f
+        b      undef_entry             /* UNDEF        */
+       cpsid f
+       b       swi_entry               /* SWI          */
+       cpsid f
+       b       inst_abort_entry        /* IABORT       */
+       cpsid f
+       b       data_abort_entry        /* DABORT       */
+#endif
 
 /* locations to pass lr and spsr from one mode to the other
    these are globally shared !!! */
@@ -286,9 +268,9 @@ undef_entry:
  */
 swi_entry:
        switch_to_kernel 0 0 0
+       exceptionframe
        enter_sys_call no_sys_call
 no_sys_call:
-       exceptionframe
        enter_slowtrap 0x00200000
 
 .align 4
@@ -542,14 +524,80 @@ irq_entry:
  *    Exception is a fast interrupt.
  *
  */
+
+#ifdef CONFIG_ARM_EM_TZ
+.pc_adjust_map_arm:
+       .long 0    /* RESET     */
+       .long 4    /* UNDEF     */
+       .long 4    /* SWI       */
+       .long 4    /* IABORT    */
+       .long 8    /* DABORT    */
+.pc_adjust_map_thumb:
+       .long 0    /* RESET     */
+       .long 2    /* UNDEF     */
+       .long 4    /* SWI       */
+       .long 4    /* IABORT    */
+       .long 8    /* DABORT    */
+#endif // ARM_EM_TZ
+
 fiq_entry:
-       switch_to_kernel 4 1 1
+#ifdef CONFIG_ARM_EM_TZ
+       mrs     r8, spsr
+       and     r9, r8, #0x1f
+       cmp     r9, #0x10
+       beq     9f
+
+       mov     r10, r0
+
+       cmp     r9, #0x13
+       bne     8f
+
+       cps     #0x13
+       mov     r0, sp
+       cps     #0x11
+       mov     r11, r0
+       mov     r0, r10 // restore
+
+       tst     r11, #0x0ff
+       tsteq   r11, #0xf00
+       bne     9f
+
+8:
+       sub     r12, lr, #4
+       movw    r11, #(fiq_b_vector - exception_vector)
+       movt    r11, #0xffff
+       cmp     r12, r11
+       subge   r12, r12, r11
+       lsrge   r12, #1
+       and     r12, r12, #0x1f
+
+       tst     r8, #0x20
+       adreq   r0, .pc_adjust_map_arm
+       adrne   r0, .pc_adjust_map_thumb
+       ldr     r0, [r0, r12]
+
+       orr     r9, #0xc0
+       msr     cpsr_c, r9
+
+       sub     lr, lr, r0
+       srsdb   #0x13!
+       cps     #0x13
+       str     lr, [sp, #-4]!
+
        exceptionframe
 
-       stmdb   sp!, {r0 - r3, r12}     @ Stack rest of user state
-       @ add r0, sp, #(5*4) @ debug
-       mov     lr, pc
-       ldr     pc, 1f
+       cps     #0x11
+       mov     r0, r10
+       cps     #0x13
+       b       7f
+9:
+#endif // ARM_EM_TZ
+       switch_to_kernel 4 1 1
+       exceptionframe
+7:
+       stmdb   sp!, {r0 - r3, r12}     @ Stack rest of user state
+       mov     lr, pc
+       ldr     pc, 1f
        ldmia   sp, {r0 - r3, r12}              @ Restore user state
        msr     cpsr_c, #0xd3 // disable IRQs
        add     sp, sp, #20
@@ -593,108 +641,19 @@ alien_syscall: @ Do it for an alien ---------------------------------------
 /*****************************************************************************/
 /* The syscall table stuff                                                   */
 /*****************************************************************************/
-#define SYSCALL(name) .word sys_##name##_wrapper
-
-.globl sys_call_table
-sys_call_table:
-       .word sys_kdb_ke
-       .word sys_kdb_ke
-/*SYSCALL(ipc)*/
-       .word sys_ipc_wrapper
-       .word sys_arm_mem_op
-SYSCALL(invoke_debug)
-       .word sys_kdb_ke
-       .word sys_kdb_ke
-       .word sys_kdb_ke
-       .word sys_kdb_ke
-       .word sys_kdb_ke
-       .word sys_kdb_ke
-
-       .align 4        
-       .global leave_by_trigger_exception
-
-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, 14*4)]
-
-       ldr     r0, [r1, #(OFS__THREAD__EXCEPTION_PSR)]
-       str     r0, [sp, #RF(PSR, 14*4)]
-
-       mov     r0, #~0
-       str     r0, [r1, #(OFS__THREAD__EXCEPTION_IP)]
-
-       enter_slowtrap_w_stack 0x00500000
-
-       .align 4        
-       .global leave_by_vcpu_upcall;
-
-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 */
-       CONTEXT_OF r1, sp
-
-       /* access_vcpu() for the local case */
-       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)]
-
-       ldr     r0, [r1, #(OFS__THREAD__EXCEPTION_PSR)]
-       str     r0, [r2, #RF(PSR, 0)]
-       bic     r0, #0x20 // force ARM mode
-       str     r0, [sp, #RF(PSR, 3*4)]
-
-       mov     r0, #~0
-       str     r0, [r1, #(OFS__THREAD__EXCEPTION_IP)]
+GEN_SYSCALL_TABLE
+GEN_LEAVE_BY_TRIGGER_EXCEPTION
 
-       ldr     r0, [sp, #RF(USR_LR, 3*4)]
-       str     r0, [r2, #RF(USR_LR, 0)]
-
-       ldr     r0, [sp, #RF(USR_SP, 3*4)]
-       str     r0, [r2, #RF(USR_SP, 0)]
-
-       stmdb   r2!, {r3-r12}
-
-       /* Restore scratch registers saved previously */
-       ldr     r0, [sp, #8]
-       str     r0, [r2, #-4]
-
-       ldr     r0, [sp, #4]
-       str     r0, [r2, #-8]
-
-       ldr     r0, [sp]
-       str     r0, [r2, #-12]!
-
-       add     sp, sp, #(3*4)
-
-       /* 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, #(-12 + OFS__VCPU_STATE__ENTRY_IP)]
-
-       str     r0, [sp, #RF(PC, 0)]
-
-        /* r0 needs to be vcpu_state */
-       add     r0, r2, #(-12)
+.macro LOAD_USR_SP vcpu_ptr
+        add  r0, \vcpu_ptr, #(OFS__VCPU_STATE__ENTRY_SP)
+        ldm  r0, {sp}^
+.endm
 
-       b       __iret
+.macro LOAD_USR_VCPU reg, kvcpu, thread
+        mov  \reg, \kvcpu
+.endm
 
+GEN_VCPU_UPCALL OFS__THREAD__USER_VCPU, LOAD_USR_SP, LOAD_USR_VCPU
 
 kernel_prefetch_abort_label: .string "Kernel prefetch abort"
 missed_excpt_ret_label:      .string "ERROR in exception return"
@@ -703,74 +662,16 @@ fiq_label:                     .string "FIQ entry"
 /**********************************************************************
        kdebug entry
  **********************************************************************/
+GEN_DEBUGGER_ENTRIES
 
-.macro DEBUGGER_ENTRY type
-#ifdef CONFIG_JDB
-       str     sp, [sp, #(RF(USR_SP, -RF_SIZE))] @ save r[13]
-       sub     sp, sp, #(RF_SIZE)
-
-       str     lr, [sp, #RF(SVC_LR, 0)]
-       str     lr, [sp, #RF(PC, 0)]
-        mrs    lr, cpsr
-       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
-       stmdb   sp!, {r0, r1}
-
-       mov     r0, sp
-       adr     lr, 1f
-       ldr     pc, 3f
-
-1:
-       add     sp, sp, #12             @ pfa, err and tpidruro
-       ldmia   sp!, {r0 - r12}
-       ldr     lr, [sp, #RF(PSR, 0)]
-       msr     cpsr, lr
-       ldr     lr, [sp, #RF(SVC_LR, 0)]
-
-       ldr     sp, [sp, #(RF(USR_SP, 0))]
-       mov     pc, lr
-
-
-3:     .word call_nested_trap_handler
-#else
-       mov     pc, lr
-#endif
-.endm
-
-       .global kern_kdebug_entry
-       .align 4
-kern_kdebug_entry:
-       DEBUGGER_ENTRY 0
-
-       .global kern_kdebug_sequence_entry
-       .align 4
-kern_kdebug_sequence_entry:
-       DEBUGGER_ENTRY 1
-
-
-#ifdef CONFIG_MP
-       .section ".text"
-       .global kern_kdebug_ipi_entry
-       .align 4
-kern_kdebug_ipi_entry:
-       DEBUGGER_ENTRY 2
-       .previous
-#endif
-
-
-
-#ifdef CONFIG_ARM_TZ
+#ifdef CONFIG_ARM_EM_TZ
 
 .macro ISB_OP reg
 #ifdef CONFIG_ARM_V7
        isb
 #else
-       mcr p15, 0, lr, c7, c5, 4       @ cp15isb
+       mcr p15, 0, \reg, c7, c5, 4     @ cp15isb
 #endif
 .endm
 
@@ -784,9 +685,8 @@ kern_kdebug_ipi_entry:
        str     lr, [sp,#-12]
        
        // switch to secure world
-       mov     lr, #0
-       mcr     p15, 0, lr, c1, c1, 0
-       
+       SWITCH_TO_SECURE_MODE lr
+
        // save gen-regs
        ldr     lr, [sp, #\off]
        //add   lr, lr, #8
@@ -803,7 +703,7 @@ kern_kdebug_ipi_entry:
        stmia   r0!, {sp, lr}
        mrs     r1, spsr
        stmia   r0!, {r1}
-       
+
        // fiq
        cps     #0x11
        stmia   r0!, {r8 - r12, sp, lr}
@@ -821,82 +721,44 @@ kern_kdebug_ipi_entry:
        stmia   r0!, {sp, lr}
        mrs     r1, spsr
        stmia   r0!, {r1}
-       
+
        // svc
        cps     #0x13
        stmia   r0!, {sp, lr}
        mrs     r1, spsr
        stmia   r0!, {r1}
-       
+
        cps     #0x16
-       
+
        // copy return pc/cpsr from stack
        sub     lr, sp, #8
        ldmia   lr, {r1, r2}
        stmia   r0!, {r1, r2}
        
        // save pending virtual interrupt state
-       mrc     p15, 0, r1, c12, c1, 1  
-       stmia   r0!, {r1}
-
-       // switch to non-secure world
-       mov     r1, #1
-       mcr     p15, 0, r1, c1, c1, 0
-       ISB_OP  r1
-       
-       mrc     p15, 0, r1, c2, c0, 0   @ read CP15_TTB0
-       stmia   r0!, {r1}
-
-       mrc     p15, 0, r1, c2, c0, 1   @ read CP15_TTB1
-       stmia   r0!, {r1}
-
-       mrc     p15, 0, r1, c2, c0, 2   @ read CP15_TTBC
-       stmia   r0!, {r1}
-
-       mrc     p15, 0, r1, c12, c0, 0  @ read CP15_VECTOR_BASE
-       stmia   r0!, {r1}
-
-       mrc     p15, 0, r1, c5, c0, 0   @ read CP15_DFSR
-       stmia   r0!, {r1}
-
-       mrc     p15, 0, r1, c6, c0, 0   @ read CP15_DFAR
-       stmia   r0!, {r1}
-
-       mrc     p15, 0, r1, c5, c0, 1   @ read CP15_IFSR
+       mrc     p15, 0, r1, c12, c1, 0
        stmia   r0!, {r1}
 
-       mrc     p15, 0, r1, c6, c0, 2   @ read CP15_IFAR
-       stmia   r0!, {r1}
-
-       mrc     p15, 0, r1, c1, c0, 0   @ read CP15_CONTROL
-       stmia   r0!, {r1}
-
-       mrc     p15, 0, r1, c10, c2, 0  @ read CP15_PRIM_REGION_REMAP
-       stmia   r0!, {r1}
-
-       mrc     p15, 0, r1, c10, c2, 1  @ read CP15_NORM_REGION_REMAP
-       stmia   r0!, {r1}
+        mrc     p15, 0, r1, c1, c0, 2 @ cpacr
+        str     r1, [r0], #4
 
-       mrc     p15, 0, r1, c13, c0, 1  @ read CP15_CID
-       stmia   r0!, {r1}
-
-       // tls regs are banked
-       mrc     p15, 0, r1, c13, c0, 2  @ read CP15_TLS1
-       stmia   r0!, {r1}
-
-       mrc     p15, 0, r1, c13, c0, 3  @ read CP15_TLS2
-       stmia   r0!, {r1}
+#ifdef CONFIG_FPU
+        mov     r1, #0x500000 @ enable CP10/11
+        mcr     p15, 0, r1, c1, c0, 2 @ cpacr
+#endif
 
-       mrc     p15, 0, r1, c13, c0, 4  @ read CP15_TLS3
-       stmia   r0!, {r1}
+       // switch to non-secure world
+       SWITCH_TO_NONSECURE_MODE r1
 
+#ifdef CONFIG_FPU
        mrc     p10, 7, r1, cr8, cr0, 0 @ fpexc
        stmia   r0!, {r1}
+#else
+       add     r0, #4
+#endif
 
        // switch to secure world
-       mov     r1, #0
-       mcr     p15, 0, r1, c1, c1, 0
-       ISB_OP  r1
+        SWITCH_TO_SECURE_MODE r1
        
        mrc     p15, 0, r1, c5, c0, 0   @ read CP15_DFSR
        stmia   r0!, {r1}
@@ -909,8 +771,8 @@ kern_kdebug_ipi_entry:
        stmia   r0!,{r1}
 .endm
 
-.macro RESTORE_NONSECURE_STATE off
-       
+.macro RESTORE_AND_SWITCH_TO_NONSECURE_STATE off
+
        ldr     r0, [sp, #\off]
 
        // jump over general purpose register
@@ -925,7 +787,7 @@ kern_kdebug_ipi_entry:
        ldmia   r0!, {sp, lr}
        ldmia   r0!, {r1}
        msr     spsr, r1
-       
+
        // fiq
        cps     #0x11
        ldmia   r0!, {r8 - r12, sp, lr}
@@ -936,7 +798,7 @@ kern_kdebug_ipi_entry:
        cps     #0x17
        ldmia   r0!, {sp, lr}
        ldmia   r0!, {r1}
-       mrs     r1, spsr
+       msr     spsr, r1
 
        // und
        cps     #0x1b
@@ -956,70 +818,20 @@ kern_kdebug_ipi_entry:
        ldmia   r0!, {r1, r2}
        stmdb   sp, {r1, r2}
 
-       // set pending events
-       ldmia   r0!, {r1}
-       and     r1, r1, #0x1c0
-       mcr     p15, 0, r1, c12, c1, 1
+       // skip pending events field
+       add     r0, #4
 
-#if 1
-       // switch to non-secure world
-       mov     r1, #1
-       mcr     p15, 0, r1, c1, c1, 0
-       ISB_OP  r1
+        ldr     r1, [r0], #4
+        mrc     p15, 0, r1, c1, c0, 2 @ cpacr
 
-       ldmia   r0!, {r1}
-       mcr     p15, 0, r1, c2, c0, 0   @ write CP15_TTB0
-
-       ldmia   r0!, {r1}
-       mcr     p15, 0, r1, c2, c0, 1   @ write CP15_TTB1
-
-       ldmia   r0!, {r1}
-       mcr     p15, 0, r1, c2, c0, 2   @ write CP15_TTBC
-
-       ldmia   r0!, {r1}
-       mcr     p15, 0, r1, c12, c0, 0  @ write CP15_VECTOR_BASE
-
-       ldmia   r0!, {r1}
-       mcr     p15, 0, r1, c5, c0, 0   @ write CP15_DFSR
-
-       ldmia   r0!, {r1}
-       mcr     p15, 0, r1, c6, c0, 0   @ write CP15_DFAR
-
-       ldmia   r0!, {r1}
-       mcr     p15, 0, r1, c5, c0, 1   @ write CP15_IFSR
-
-       ldmia   r0!, {r1}
-       mcr     p15, 0, r1, c6, c0, 2   @ write CP15_IFAR
-
-       ldmia   r0!, {r1}
-       mcr     p15, 0, r1, c1, c0, 0   @ write CP15_CONTROL
-
-       ldmia   r0!, {r1}
-       mcr     p15, 0, r1, c10, c2, 0  @ write CP15_PRIM_REGION_REMAP
-
-       ldmia   r0!, {r1}
-       mcr     p15, 0, r1, c10, c2, 1  @ write CP15_NORM_REGION_REMAP
-
-       ldmia   r0!, {r1}
-       mcr     p15, 0, r1, c13, c0, 1  @ write CP15_CID
-
-       // tls regs are banked
-       ldmia   r0!, {r1}
-       mcr     p15, 0, r1, c13, c0, 2  @ write CP15_TLS1
-
-       ldmia   r0!, {r1}
-       mcr     p15, 0, r1, c13, c0, 3  @ write CP15_TLS2
-
-       ldmia   r0!, {r1}
-       mcr     p15, 0, r1, c13, c0, 4  @ write CP15_TLS3
+       // switch to non-secure world
+       SWITCH_TO_NONSECURE_MODE r1
 
+#ifdef CONFIG_FPU
        ldmia   r0!, {r1}
-        mcr p10, 7, r1, cr8, cr0, 0     @ fpexc
-
-       // switch to secure world
-       mov     r1, #0
-       mcr     p15, 0, r1, c1, c1, 0
-       ISB_OP  r1
+       mcr     p10, 7, r1, cr8, cr0, 0     @ fpexc
+#else
+       add     r0, #4
 #endif
 
        // load gen-regs
@@ -1036,6 +848,8 @@ kern_kdebug_ipi_entry:
  */
 .macro SAVE_SECURE_STATE
 
+        mrc p15, 0, r5, c1, c0, 2
+        str     r5, [sp, #-4]!
        stmdb   sp!, {r3, r4}   @ save supervisor return values
        stmdb   sp, {sp, lr}^   @ save user-level return values
        sub     sp, sp, #8
@@ -1055,34 +869,20 @@ kern_kdebug_ipi_entry:
        ldmia   sp, {sp, lr}^   @ restore user-level return values
        add     sp, sp, #8
        ldmia   sp!, {r3, r4}   @ restore supervisor return values
+        ldr     r0, [sp], #4
+        mcr p15, 0, r0, c1, c0, 2
 .endm
 
-/**********************************************************************
- * Restore secure state when guest is interrupted by FIQ
- *
- * Don't remove secure state from stack as we need it
- * when application guest exits.
- * Just restore user-level state as this is spilled by the irq handler
- */
-.macro RESTORE_SECURE_STATE_FIQ
-
-       mov     r0, sp          @ restore stack pointer from supervisor mode
-       cps     #0x13
-       mov     sp, r0
-       cps     #0x16
-       ldmia   sp, {sp, lr}^   @ restore user-level return values
-.endm
-
-.macro SWITCH_TO_NONSECURE_MODE
-       mov     lr, #0xf
-       mcr     p15, 0, lr, c1, c1, 0
-       ISB_OP  lr
+.macro SWITCH_TO_NONSECURE_MODE reg
+       movw    \reg, #0x12d
+       mcr     p15, 0, \reg, c1, c1, 0
+       ISB_OP  \reg
 .endm
 
-.macro SWITCH_TO_SECURE_MODE
-       mov     lr, #0x0
-       mcr     p15, 0, lr, c1, c1, 0
-       ISB_OP  lr
+.macro SWITCH_TO_SECURE_MODE reg
+       mov     \reg, #0x100
+       mcr     p15, 0, \reg, c1, c1, 0
+       ISB_OP  \reg
 .endm
 
 
@@ -1101,38 +901,22 @@ monitor_vector_base:
        b       mon_irq_entry           /* IRQ          */
        b       mon_fiq_entry           /* FIQ          */
 
+.macro mon_enter_secure name, ec, sub_lr
+\name:
+.if \sub_lr
+        sub     lr, lr, #\sub_lr
+.endif
+        srsdb   sp, #0x16
+        mov     lr, #\ec
+        b       go_secure
+.endm
 
-mon_undef_entry:
-1:     b 1b
-
-mon_swi_entry:
-       srsdb   sp, #0x16               @ save return state temporarily on stack
-       mov     lr, #1                  @ set exit reason
-       b       go_secure
-       
-mon_inst_abort_entry:
-       sub     lr, lr, #4
-       srsdb   sp, #0x16
-       mov     lr, #2                  @ set exit reason
-       b       go_secure
-       
-mon_data_abort_entry:
-       sub     lr, lr, #4
-       srsdb   sp, #0x16
-       mov     lr, #3                  @ set exit reason
-       b       go_secure
-       
-mon_irq_entry:
-       sub     lr, lr, #4
-       srsdb   sp, #0x16
-       mov     lr, #4                  @ set exit reason
-       b       go_secure
-
-mon_fiq_entry:
-       sub     lr, lr, #4              @ adjust saved ip
-       srsdb   sp, #0x16
-       mov     lr, #4                  @ set exit reason
-       b       go_secure
+mon_enter_secure mon_undef_entry,      6, 4
+mon_enter_secure mon_swi_entry,        1, 0
+mon_enter_secure mon_inst_abort_entry, 2, 4
+mon_enter_secure mon_data_abort_entry, 3, 4
+mon_enter_secure mon_irq_entry,        4, 4
+mon_enter_secure mon_fiq_entry,        5, 4
 
 //     cps     #0x12                   @ switch to irq mode
 //     adr     lr, go_nonsecure_after_fiq + 4                  @ set lr_irq
@@ -1144,7 +928,7 @@ mon_fiq_entry:
  *
  */
 go_secure:
-       SAVE_NONSECURE_STATE 16
+       SAVE_NONSECURE_STATE 20
        RESTORE_SECURE_STATE
        
        mov     lr, r3
@@ -1168,17 +952,13 @@ go_secure:
 .globl go_nonsecure
 go_nonsecure:
        SAVE_SECURE_STATE
-       RESTORE_NONSECURE_STATE 16
-       SWITCH_TO_NONSECURE_MODE
-
-//     mcr p15, 0, lr, c7, c10, 4      @ drain write buffer
-//     mcr p15, 0, lr, c8, c7, 0       @ flush TLB entry
+       RESTORE_AND_SWITCH_TO_NONSECURE_STATE 20
 
        ldr     lr, [sp, #-4]
        msr     spsr, lr                @ set spsr_mon with unsecure spsr
        ldr     lr, [sp, #-8]           @ set lr_mon with unsecure ip
        movs    pc, lr
-#endif
+#endif /* TRUSTZONE */
 
 /* -------------------------------------- TEXT ---------------------------*/
 
index e12ba76407265c22d7ee435d5f5c52c32c4c44d7..7969847c1bf47d11cc964d2b5580232aafbedcf7 100644 (file)
@@ -14,26 +14,24 @@ IMPLEMENTATION [arm]:
 
 #include "kmem_alloc.h"
 #include "kmem_space.h"
-#include "pagetable.h"
 #include "ram_quota.h"
+#include "paging.h"
 
 IMPLEMENT
 void Kern_lib_page::init()
 {
   extern char kern_lib_start;
-  Pte pte = Kmem_space::kdir()->walk((void *)Kmem_space::Kern_lib_base,
-                                     Config::PAGE_SIZE, true,
-                                     Kmem_alloc::q_allocator(Ram_quota::root),
-                                     Kmem_space::kdir());
+  auto pte = Kmem_space::kdir()->walk(Virt_addr(Kmem_space::Kern_lib_base),
+      Pdir::Depth, true,
+      Kmem_alloc::q_allocator(Ram_quota::root));
 
-  if (pte.lvl() == 0) // allocation of second level faild
+  if (pte.level == 0) // allocation of second level faild
     panic("FATAL: Error mapping kernel-lib page to %p\n",
           (void *)Kmem_space::Kern_lib_base);
 
-  pte.set((Address)&kern_lib_start - Mem_layout::Map_base
-          + Mem_layout::Sdram_phys_base,
-          Config::PAGE_SIZE, Mem_page_attr(Page::USER_RO | Page::CACHEABLE),
-          true);
+  pte.create_page(Phys_mem_addr((Address)&kern_lib_start - Mem_layout::Map_base
+          + Mem_layout::Sdram_phys_base), Page::Attr(Page::Rights::URX(), Page::Type::Normal(), Page::Kern::Global()));
+  pte.write_back_if(true);
 }
 
 //---------------------------------------------------------------------------
index 0160508d1f4f8168d1dd9b06f7517ca15068832b..58d98045087a7a6d58af1e8eda565446bcd07a66 100644 (file)
@@ -6,6 +6,6 @@ IMPLEMENTATION[arm]:
 
 PRIVATE inline NEEDS["globals.h", "kmem_space.h"]
 Kernel_task::Kernel_task()
-: Task(Ram_quota::root, Kmem_space::kdir())
+: Task(Ram_quota::root, Kmem_space::kdir(), Caps::none())
 {}
 
index 7c4184ac0b992df0b13c71c6067591efc764d0e7..6f50f303149b72c5d6b8654fe3c5d49d835abade 100644 (file)
@@ -31,10 +31,9 @@ Kernel_thread::boot_app_cpus()
 IMPLEMENTATION [mp]:
 
 #include "io.h"
-#include "pagetable.h"
 #include "platform_control.h"
 #include "outer_cache.h"
-
+#include "paging.h"
 #include <cstdio>
 
 static void
@@ -43,25 +42,33 @@ Kernel_thread::boot_app_cpus()
   extern char _tramp_mp_entry[];
   extern volatile Mword _tramp_mp_startup_cp15_c1;
   extern volatile Mword _tramp_mp_startup_pdbr;
-  extern volatile Mword _tramp_mp_start_dcr;
-
-  unsigned num_ap_cpus = (Io::read<Mword>(Mem_layout::Mp_scu_map_base + 4) & 3);
+  extern volatile Mword _tramp_mp_startup_dcr;
+  extern volatile Mword _tramp_mp_startup_ttbcr;
+  extern volatile Mword _tramp_mp_startup_mair0;
 
-  printf("Number of CPUs: %d\n", num_ap_cpus + 1);
+  if (Scu::Available)
+    {
+      unsigned num_ap_cpus = Cpu::scu->config() & 3;
+      printf("Number of CPUs: %d\n", num_ap_cpus + 1);
+    }
 
   _tramp_mp_startup_cp15_c1 = Config::Cache_enabled
                               ? Cpu::Cp15_c1_cache_enabled : Cpu::Cp15_c1_cache_disabled;
   _tramp_mp_startup_pdbr
     = Mem_space::kernel_space()->virt_to_phys((Address)Mem_space::kernel_space()->dir())
-      | Page_table::Ttbr_bits;
-  _tramp_mp_start_dcr       = 0x55555555;
+      | Page::Ttbr_bits;
+  _tramp_mp_startup_ttbcr   = Page::Ttbcr_bits;
+  _tramp_mp_startup_mair0   = Page::Mair0_bits;
+  _tramp_mp_startup_dcr     = 0x55555555;
 
   __asm__ __volatile__ ("" : : : "memory");
   Mem_unit::clean_dcache();
 
   Outer_cache::clean(Mem_space::kernel_space()->virt_to_phys((Address)&_tramp_mp_startup_cp15_c1));
   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));
+  Outer_cache::clean(Mem_space::kernel_space()->virt_to_phys((Address)&_tramp_mp_startup_dcr));
+  Outer_cache::clean(Mem_space::kernel_space()->virt_to_phys((Address)&_tramp_mp_startup_ttbcr));
+  Outer_cache::clean(Mem_space::kernel_space()->virt_to_phys((Address)&_tramp_mp_startup_mair0));
 
   Platform_control::boot_ap_cpus(Mem_space::kernel_space()->virt_to_phys((Address)_tramp_mp_entry));
 }
index 534b6cd9ab2eb18e66cea2cb22d73cc6ddec775e..0503b5a8b7c5c447fe4470fb6c82f60825e43989 100644 (file)
@@ -15,9 +15,9 @@ IMPLEMENTATION [arm]:
 #include <cstring>
 
 #include "config.h"
+#include "mem_layout.h"
 #include "panic.h"
 #include "boot_info.h"
-#include "kmem.h"
 
 
 // Make the stuff below apearing only in this compilation unit.
index d58fa6d8db6449844560e0b6423d8b4286eeec61..c0cf9a619d2d03256f8c2c8cacd4d5117d13d09c 100644 (file)
@@ -7,24 +7,55 @@ class Kmem : public Mem_layout
 {
 public:
 
-  static Mword is_kmem_page_fault( Mword pfa, Mword error );
-  static Mword is_ipc_page_fault( Mword pfa, Mword error );
-  static Mword is_io_bitmap_page_fault( Mword pfa );
-
-  static Mword ipc_window( unsigned num );
+  static Mword is_kmem_page_fault(Mword pfa, Mword error);
+  static Mword is_ipc_page_fault(Mword pfa, Mword error);
+  static Mword is_io_bitmap_page_fault(Mword pfa);
 };
 
 //---------------------------------------------------------------------------
 IMPLEMENTATION [arm]:
 
+#include "mem_unit.h"
+#include "kmem_space.h"
+#include "paging.h"
+#include <cassert>
+
 IMPLEMENT inline
-Mword Kmem::is_kmem_page_fault( Mword pfa, Mword /*error*/ )
+Mword Kmem::is_kmem_page_fault(Mword pfa, Mword)
 {
   return in_kernel(pfa);
 }
 
 IMPLEMENT inline
-Mword Kmem::is_io_bitmap_page_fault( Mword /*pfa*/ )
+Mword Kmem::is_io_bitmap_page_fault(Mword)
 {
   return 0;
 }
+
+PUBLIC static
+Address
+Kmem::mmio_remap(Address phys)
+{
+  static Address ndev = 0;
+  Address v = phys_to_pmem(phys);
+  if (v != ~0UL)
+    return v;
+
+  Address dm = Mem_layout::Registers_map_start + ndev;
+  assert(dm < Mem_layout::Registers_map_end);
+
+  ndev += Config::SUPERPAGE_SIZE;
+
+  auto m = Kmem_space::kdir()->walk(Virt_addr(dm), Pte_ptr::Super_level);
+  assert (!m.is_valid());
+  assert (m.page_order() == Config::SUPERPAGE_SHIFT);
+  Address phys_page = cxx::mask_lsb(phys, Config::SUPERPAGE_SHIFT);
+  m.create_page(Phys_mem_addr(phys_page), Page::Attr(Page::Rights::RWX(), Page::Type::Uncached(),
+                Page::Kern::Global()));
+
+  m.write_back_if(true);
+
+  add_pmem(phys_page, dm, Config::SUPERPAGE_SIZE);
+
+  return phys_to_pmem(phys);
+}
index 8d3bd29032ac2ccab04f3c5ba2243c39e728eaf8..7c526628b11ef65602149e298ce70cb80bceda69 100644 (file)
@@ -2,7 +2,6 @@ IMPLEMENTATION [arm]:
 
 #include "mem_unit.h"
 #include "kmem_space.h"
-#include "pagetable.h"
 #include "ram_quota.h"
 
 
@@ -17,21 +16,24 @@ Kmem_alloc::map_pmem(unsigned long phy, unsigned long size)
   if (next_map + size > Mem_layout::Map_end)
     return false;
 
-  for (unsigned long i = 0; i <size; i+=Config::SUPERPAGE_SIZE)
+  for (unsigned long i = 0; i <size; i += Config::SUPERPAGE_SIZE)
     {
-      Pte pte = Kmem_space::kdir()->walk((char*)next_map+i,
-         Config::SUPERPAGE_SIZE, false, Ptab::Null_alloc(),
-          Kmem_space::kdir());
-      pte.set(phy+i, Config::SUPERPAGE_SIZE, 
-         Mem_page_attr(Page::KERN_RW | Page::CACHEABLE),
-         true);
-
+      auto pte = Kmem_space::kdir()->walk(Virt_addr(next_map + i), Pdir::Super_level);
+      pte.create_page(Phys_mem_addr(phy + i), Page::Attr(Page::Rights::RW()));
+      pte.write_back_if(true);
     }
   Mem_layout::add_pmem(phy, next_map, size);
   next_map += size;
   return true;
 }
 
+PUBLIC inline NEEDS["kmem_space.h"]
+Address
+Kmem_alloc::to_phys(void *v) const
+{
+  return Kmem_space::kdir()->virt_to_phys((Address)v);
+}
+
 IMPLEMENT
 Kmem_alloc::Kmem_alloc()
 {
@@ -53,13 +55,12 @@ Kmem_alloc::Kmem_alloc()
       if (f.size() > alloc_size)
        f.start += (f.size() - alloc_size);
 
-      Kip::k()->add_mem_region(Mem_desc(f.start, f.end,
-           Mem_desc::Reserved));
+      Kip::k()->add_mem_region(Mem_desc(f.start, f.end, Mem_desc::Reserved));
       //printf("ALLOC1: [%08lx; %08lx] sz=%ld\n", f.start, f.end, f.size());
       if (Mem_layout::phys_to_pmem(f.start) == ~0UL)
        if (!map_pmem(f.start, f.size()))
          panic("Kmem_alloc: cannot map physical memory %p\n", (void*)f.start);
-      a->add_mem((void*)Mem_layout::phys_to_pmem(f.start), f.size());
+      a->add_mem((void *)Mem_layout::phys_to_pmem(f.start), f.size());
       alloc_size -= f.size();
     }
 
index 9a993379c857112416886dcccfc2b8e0f2dcddcf..730eedb34e24aa702c88371aaa1f61aceb566867 100644 (file)
@@ -1,18 +1,17 @@
 INTERFACE [arm]:
 
-#include "kmem.h"
+#include "paging.h"
+#include "mem_layout.h"
 
-class Page_table;
-
-class Kmem_space : public Kmem
+class Kmem_space : public Mem_layout
 {
 public:
   static void init();
   static void init_hw();
-  static Page_table *kdir();
+  static Pdir *kdir();
 
 private:
-  static Page_table *_kdir;
+  static Pdir *_kdir;
 };
 
 //---------------------------------------------------------------------------
@@ -22,27 +21,42 @@ IMPLEMENTATION [arm]:
 #include <panic.h>
 
 #include "console.h"
-#include "pagetable.h"
-#include "kmem.h"
 #include "kip_init.h"
 #include "mem_unit.h"
 
 #include <cstdio>
 
-char kernel_page_directory[sizeof(Page_table)] __attribute__((aligned(0x4000)));
-
-Page_table *Kmem_space::_kdir = (Page_table*)&kernel_page_directory;
-
 IMPLEMENT inline
-Page_table *Kmem_space::kdir()
+Pdir *Kmem_space::kdir()
 { return _kdir; }
 
 // initialze the kernel space (page table)
 IMPLEMENT
 void Kmem_space::init()
 {
-  Page_table::init();
+  unsigned domains      = 0x0001;
+
+  asm volatile (
+      "mcr p15, 0, %0, c3, c0       \n" // domains
+      :
+      : "r"(domains) );
 
   Mem_unit::clean_vdcache();
 }
 
+// allways 16kB also for LPAE we use 4 consecutive second level tables
+char kernel_page_directory[0x4000] __attribute__((aligned(0x4000), section(".bss.kernel_page_dir")));
+
+//----------------------------------------------------------------------------------
+IMPLEMENTATION[arm && !arm_lpae]:
+
+Pdir *Kmem_space::_kdir = (Pdir*)&kernel_page_directory;
+
+//----------------------------------------------------------------------------------
+IMPLEMENTATION[arm && arm_lpae]:
+
+Unsigned64 kernel_lpae_dir[4] __attribute__((aligned(4*sizeof(Unsigned64))));
+Pdir *Kmem_space::_kdir = (Pdir*)&kernel_lpae_dir;
+
+
+
index 6b191604d022636b768c591627d2c4a966b46f86..a08dd479282265e53a24da68625df7521d840136 100644 (file)
@@ -13,7 +13,6 @@ IMPLEMENTATION [arm]:
 #include "initcalls.h"
 #include "kmem_alloc.h"
 #include "kip_init.h"
-#include "pagetable.h"
 #include "kdb_ke.h"
 #include "kernel_thread.h"
 #include "kernel_task.h"
@@ -118,22 +117,23 @@ int boot_ap_cpu() __asm__("BOOT_AP_CPU");
 
 int boot_ap_cpu()
 {
-  static unsigned last_cpu; // keep track of the last cpu ever appeared
+  static Cpu_number last_cpu; // keep track of the last cpu ever appeared
 
-  unsigned _cpu = Cpu::cpus.find_cpu(Cpu::By_phys_id(Proc::cpu_id()));
+  Cpu_number _cpu = Cpu::cpus.find_cpu(Cpu::By_phys_id(Proc::cpu_id()));
   bool cpu_is_new = false;
-  if (_cpu == ~0U)
+  if (_cpu == Cpu_number::nil())
     {
       _cpu = ++last_cpu; // 0 is the boot cpu, so pre increment
       cpu_is_new = true;
     }
 
-  assert (_cpu != 0);
+  assert (_cpu != Cpu_number::boot_cpu());
 
   if (cpu_is_new && !Per_cpu_data_alloc::alloc(_cpu))
     {
       extern Spin_lock<Mword> _tramp_mp_spinlock;
-      printf("CPU allocation failed for CPU%u, disabling CPU.\n", _cpu);
+      printf("CPU allocation failed for CPU%u, disabling CPU.\n",
+             cxx::int_value<Cpu_number>(_cpu));
       _tramp_mp_spinlock.clear();
 
       // FIXME: use a Platform_control API to stop the CPU
index 1da21916764c6d6650ce4a0fe5b6222046542f57..eb2c0667c228a5e56138c5e9842f0dddc47b04a0 100644 (file)
@@ -37,12 +37,10 @@ public:
     Tbuf_buffer_area    = Service_page + 0x200000,
     Tbuf_ubuffer_area    = Tbuf_buffer_area,
     Jdb_tmp_map_area     = Service_page + 0x400000,
-    __free_1_start       = 0xee000000,
-    __free_1_end         = 0xef000000,
+    Registers_map_start  = 0xee000000,
+    Registers_map_end    = 0xef000000,
     Cache_flush_area     = 0xef000000,
     Cache_flush_area_end = 0xef100000,
-    Registers_map_start  = 0xef100000,
-    Registers_map_end    = 0xeff00000,
     Map_base             = 0xf0000000,
     Map_end              = 0xf5000000,
     Caps_start           = 0xf5000000,
@@ -55,17 +53,10 @@ 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,
+  enum Phys_layout : Address {
+    Sdram_phys_base      = RAM_PHYS_BASE
   };
 };
 
index 7781a2d88b59ddd08b6d75a4e67125a314a4534e..0cf13954ad1ecdae33b1267fbdf76a46ab66e0e1 100644 (file)
@@ -13,7 +13,7 @@ public:
   static inline unsigned long trunc_superpage(unsigned long addr)
   { return addr & ~(Config::SUPERPAGE_SIZE-1); }
 private:
-  static unsigned short __ph_to_pm[1<<(32-Config::SUPERPAGE_SHIFT)];
+  static unsigned short __ph_to_pm[1UL<<(32-Config::SUPERPAGE_SHIFT)];
 };
 
 
@@ -22,9 +22,10 @@ IMPLEMENTATION [noncont_mem]:
 #include <config.h>
 #include <cstdio>
 
+
 PUBLIC static
 Address
-Mem_layout::pmem_to_phys (Address addr)
+Mem_layout::pmem_to_phys(Address addr)
 {
   printf("Mem_layout::pmem_to_phys(Address addr=%lx) is not implemented\n",
          addr);
@@ -43,10 +44,10 @@ IMPLEMENT inline NEEDS[<config.h>]
 Address
 Mem_layout::phys_to_pmem(Address phys)
 {
-  Address virt = ((unsigned long)__ph_to_pm[phys >> Config::SUPERPAGE_SHIFT]) 
+  Address virt = ((unsigned long)__ph_to_pm[phys >> Config::SUPERPAGE_SHIFT])
     << 16;
 
-  if (!virt) 
+  if (!virt)
     return ~0UL;
 
   return virt | (phys & (Config::SUPERPAGE_SIZE-1));
@@ -54,7 +55,7 @@ Mem_layout::phys_to_pmem(Address phys)
 
 
 
-IMPLEMENT inline NEEDS[<config.h>]
+IMPLEMENT inline ALWAYS_INLINE NEEDS[<config.h>]
 void
 Mem_layout::add_pmem(Address phys, Address virt, unsigned long size)
 {
@@ -64,6 +65,6 @@ Mem_layout::add_pmem(Address phys, Address virt, unsigned long size)
       phys += Config::SUPERPAGE_SIZE;
       virt += Config::SUPERPAGE_SIZE;
     }
-
 }
 
+
index b483216c5b010ffc4b54d1dd29d1c9b7edbe96b9..8e01bf005b4e6d4b69ef5539c743c031da13b5a2 100644 (file)
@@ -41,16 +41,18 @@ IMPLEMENTATION [arm]:
 PRIVATE static void
 Mem_op::l1_inv_dcache(Address start, Address end)
 {
-  if (start & Mem_unit::Cache_line_mask)
+  Mword s = Mem_unit::dcache_line_size();
+  Mword m = s - 1;
+  if (start & m)
     {
       Mem_unit::flush_dcache((void *)start, (void *)start);
-      start += Mem_unit::Cache_line_size;
-      start &= ~Mem_unit::Cache_line_mask;
+      start += s;
+      start &= ~m;
     }
-  if (end & Mem_unit::Cache_line_mask)
+  if (end & m)
     {
       Mem_unit::flush_dcache((void *)end, (void *)end);
-      end &= ~Mem_unit::Cache_line_mask;
+      end &= ~m;
     }
 
   if (start < end)
@@ -64,8 +66,9 @@ Mem_op::inv_icache(Address start, Address end)
     asm volatile("mcr p15, 0, r0, c7, c5, 0");
   else
     {
-      for (start &= ~Mem_unit::Icache_line_mask;
-           start < end; start += Mem_unit::Icache_line_size)
+      Mword s = Mem_unit::icache_line_size();
+      for (start &= ~(s - 1);
+           start < end; start += s)
        asm volatile("mcr p15, 0, %0, c7, c5, 1" : : "r" (start));
     }
 }
@@ -227,14 +230,14 @@ Mem_op::outer_cache_op(int op, Address start, Address end)
 
   while (v < e)
     {
-      Mem_space::Size phys_size;
+      Mem_space::Page_order phys_size;
       Mem_space::Phys_addr phys_addr;
-      unsigned attrs;
-      bool mapped =    c->mem_space()->v_lookup(Mem_space::Vaddr(v), &phys_addr, &phys_size, &attrs)
-                    && (attrs & Mem_space::Page_user_accessible);
+      Page::Attr attrs;
+      bool mapped = (   c->mem_space()->v_lookup(Mem_space::Vaddr(v), &phys_addr, &phys_size, &attrs)
+                     && (attrs.rights & Page::Rights::U()));
 
-      Virt_size sz = Virt_size(phys_size);
-      Virt_size offs = Virt_size(Virt_addr(v).value() & (Mem_space::Size(phys_size).value() - 1));
+      Virt_size sz = Virt_size(1) << phys_size;
+      Virt_size offs = cxx::get_lsb(v, phys_size);
       sz -= offs;
       if (e - v < sz)
         sz = e - v;
@@ -246,16 +249,13 @@ Mem_op::outer_cache_op(int op, Address start, Address end)
           switch (op)
             {
             case Op_cache_l2_clean:
-              Outer_cache::clean(Virt_addr(vstart).value(),
-                                 Virt_addr(vend).value(), false);
+              Outer_cache::clean(Virt_addr::val(vstart), Virt_addr::val(vend), false);
               break;
             case Op_cache_l2_flush:
-              Outer_cache::flush(Virt_addr(vstart).value(),
-                                 Virt_addr(vend).value(), false);
+              Outer_cache::flush(Virt_addr::val(vstart), Virt_addr::val(vend), false);
               break;
             case Op_cache_l2_inv:
-              Outer_cache::invalidate(Virt_addr(vstart).value(),
-                                      Virt_addr(vend).value(), false);
+              Outer_cache::invalidate(Virt_addr::val(vstart), Virt_addr::val(vend), false);
               break;
             }
         }
index bb0c8e65e720b55b3268ec0367c21d9bbb90e616..37de07a1d12460971665e295432715f64ce71e21 100644 (file)
@@ -5,7 +5,6 @@ INTERFACE [arm]:
 #include "member_offs.h"
 #include "paging.h"
 #include "types.h"
-#include "pagetable.h"
 #include "ram_quota.h"
 
 EXTENSION class Mem_space
@@ -13,45 +12,25 @@ EXTENSION class Mem_space
   friend class Jdb;
 
 public:
-  typedef Page_table Dir_type;
+  typedef Pdir Dir_type;
 
   /** Return status of v_insert. */
   enum // Status
   {
-    Insert_ok = Page_table::E_OK,              ///< Mapping was added successfully.
-    Insert_err_nomem  = Page_table::E_NOMEM,  ///< Couldn't alloc new page table
-    Insert_err_exists = Page_table::E_EXISTS, ///< A mapping already exists at the target addr
-    Insert_warn_attrib_upgrade = Page_table::E_UPGRADE,        ///< Mapping already existed, attribs upgrade
+    Insert_ok = 0,             ///< Mapping was added successfully.
+    Insert_err_exists, ///< A mapping already exists at the target addr
+    Insert_warn_attrib_upgrade,        ///< Mapping already existed, attribs upgrade
+    Insert_err_nomem,  ///< Couldn't alloc new page table
     Insert_warn_exists,                ///< Mapping already existed
 
   };
 
-  /** Attribute masks for page mappings. */
-  enum Page_attrib
-  {
-    Page_no_attribs = 0,
-    /// Page is writable.
-    Page_writable = Mem_page_attr::Write,
-    Page_user_accessible = Mem_page_attr::User,
-    /// Page is noncacheable.
-    Page_noncacheable = Page::NONCACHEABLE,
-    Page_cacheable = Page::CACHEABLE,
-    /// it's a user page (USER_NO | USER_RO = USER_RW).
-    /// A mask which contains all mask bits
-    Page_all_attribs = Page_user_accessible | Page_writable | Page_cacheable,
-    Page_referenced = 0,
-    Page_dirty = 0,
-    Page_references = 0,
-  };
-
   // Mapping utilities
-
   enum                         // Definitions for map_util
   {
     Need_insert_tlb_flush = 1,
     Map_page_size = Config::PAGE_SIZE,
     Page_shift = Config::PAGE_SHIFT,
-    Map_superpage_size = Config::SUPERPAGE_SIZE,
     Map_max_address = Mem_layout::User_max,
     Whole_space = 32,
     Identity_map = 0,
@@ -59,12 +38,11 @@ public:
 
 
   static void kernel_space(Mem_space *);
-  static bool has_superpages() { return true; }
-
 
 private:
   // DATA
   Dir_type *_dir;
+  Phys_mem_addr _dir_phys;
 };
 
 //---------------------------------------------------------------------------
@@ -88,36 +66,10 @@ IMPLEMENTATION [arm]:
 
 
 PUBLIC static inline
-Mword
-Mem_space::xlate_flush(unsigned char rights)
-{
-  Mword a = Page_references;
-  if (rights & L4_fpage::RX)
-    a |= Page_all_attribs;
-  else if (rights & L4_fpage::W)
-    a |= Page_writable;
-  return a;
-}
-
-PUBLIC static inline
-Mword
-Mem_space::is_full_flush(unsigned char rights)
-{
-  return rights & L4_fpage::RX;
-}
-
-PUBLIC static inline
-unsigned char
-Mem_space::xlate_flush_result(Mword attribs)
+bool
+Mem_space::is_full_flush(L4_fpage::Rights rights)
 {
-  unsigned char r = 0;
-  if (attribs & Page_referenced)
-    r |= L4_fpage::RX;
-
-  if (attribs & Page_dirty)
-    r |= L4_fpage::W;
-
-  return r;
+  return rights & L4_fpage::Rights::R();
 }
 
 // Mapping utilities
@@ -128,7 +80,7 @@ Mem_space::tlb_flush(bool force = false)
 {
   if (!Have_asids)
     Mem_unit::tlb_flush();
-  else if (force && c_asid() != ~0UL)
+  else if (force && c_asid() != Mem_unit::Asid_invalid)
     Mem_unit::tlb_flush(c_asid());
 
   // else do nothing, we manage ASID local flushes in v_* already
@@ -152,11 +104,25 @@ Mem_space::tlb_flush_spaces(bool all, Mem_space *s1, Mem_space *s2)
 
 
 IMPLEMENT inline
-Mem_space *Mem_space::current_mem_space(unsigned cpu)
+Mem_space *Mem_space::current_mem_space(Cpu_number cpu)
 {
   return _current.cpu(cpu);
 }
 
+PUBLIC inline
+bool
+Mem_space::set_attributes(Virt_addr virt, Attr page_attribs,
+                          bool writeback, Mword asid)
+{
+   auto i = _dir->walk(virt);
+
+  if (!i.is_valid())
+    return false;
+
+  i.set_attribs(page_attribs);
+  i.write_back_if(writeback, asid);
+  return true;
+}
 
 IMPLEMENT inline NEEDS ["kmem.h", Mem_space::c_asid]
 void Mem_space::switchin_context(Mem_space *from)
@@ -171,11 +137,6 @@ void Mem_space::switchin_context(Mem_space *from)
     make_current();
   else
     tlb_flush(true);
-#if 0
-  _dir->invalidate((void*)Kmem::ipc_window(0), Config::SUPERPAGE_SIZE * 4,
-      c_asid());
-#endif
-
 }
 
 
@@ -185,55 +146,43 @@ void Mem_space::kernel_space(Mem_space *_k_space)
   _kernel_space = _k_space;
 }
 
-
-inline
-static unsigned pd_index(void const *address)
-{ return (Mword)address >> 20; /* 1MB steps */ }
-
-inline
-static unsigned pt_index(void const *address)
-{ return ((Mword)address >> 12) & 255; /* 4KB steps for coarse pts */ }
-
-
 IMPLEMENT
 Mem_space::Status
-Mem_space::v_insert(Phys_addr phys, Vaddr virt, Vsize size, unsigned page_attribs,
-                    bool upgrade_ignore_size)
+Mem_space::v_insert(Phys_addr phys, Vaddr virt, Page_order size,
+                    Attr page_attribs)
 {
-  Mem_space *c = _current.current();
-  bool flush = c == this;
+  bool const flush = _current.current() == this;
+  assert (cxx::get_lsb(Phys_addr(phys), size) == 0);
+  assert (cxx::get_lsb(Virt_addr(virt), size) == 0);
 
-  Pte pte = _dir->walk((void*)virt.value(), size.value(), flush,
-                       Kmem_alloc::q_allocator(ram_quota()),
-                       c->dir());
-  if (pte.valid())
-    {
-      if (EXPECT_FALSE(!upgrade_ignore_size 
-           && (pte.size() != size.value() || pte.phys() != phys.value())))
-       return Insert_err_exists;
-      if (pte.attr().get_abstract() == page_attribs)
-       return Insert_warn_exists;
+  int level;
+  for (level = 0; level <= Pdir::Depth; ++level)
+    if (Page_order(Pdir::page_order_for_level(level)) <= size)
+      break;
 
-      Mem_page_attr a = pte.attr();
-      a.set_abstract(a.get_abstract() | page_attribs);
-      pte.set(phys.value(), size.value(), a, flush);
+  auto i = _dir->walk(virt, level, Pte_ptr::need_cache_write_back(flush),
+                      Kmem_alloc::q_allocator(_quota));
 
-      BUG_ON(pte.phys() != phys.value(), "overwrite phys addr: %lx with %lx\n",
-             pte.phys(), phys.value());
+  if (EXPECT_FALSE(!i.is_valid() && i.level != level))
+    return Insert_err_nomem;
 
-      if (Have_asids)
-        Mem_unit::tlb_flush((void*)virt.value(), c_asid());
+  if (EXPECT_FALSE(i.is_valid()
+                   && (i.level != level || Phys_addr(i.page_addr()) != phys)))
+    return Insert_err_exists;
 
+  if (i.is_valid())
+    {
+      if (EXPECT_FALSE(!i.add_attribs(page_attribs)))
+        return Insert_warn_exists;
+
+      i.write_back_if(flush, c_asid());
       return Insert_warn_attrib_upgrade;
     }
-  else if (pte.size() != size.value())
-    return Insert_err_nomem;
   else
     {
-      // we found an invalid entry for the right size
-      Mem_page_attr a(Page::Local_page);
-      a.set_abstract(page_attribs);
-      pte.set(phys.value(), size.value(), a, flush);
+      i.create_page(phys, page_attribs);
+      i.write_back_if(flush, Mem_unit::Asid_invalid);
+
       return Insert_ok;
     }
 }
@@ -249,11 +198,7 @@ PUBLIC inline
 Address
 Mem_space::virt_to_phys(Address virt) const
 {
-  Pte pte = _dir->walk((void*)virt, 0, false, Ptab::Null_alloc(), 0);
-  if (EXPECT_FALSE(!pte.valid()))
-    return ~0UL;
-
-  return (Address)pte.phys((void*)virt);
+  return dir()->virt_to_phys(virt);
 }
 
 PUBLIC inline NEEDS [Mem_space::virt_to_phys]
@@ -282,66 +227,45 @@ Mem_space::virt_to_phys_s0(void *a) const
 IMPLEMENT
 bool
 Mem_space::v_lookup(Vaddr virt, Phys_addr *phys,
-                    Size *size, unsigned *page_attribs)
+                    Page_order *order, Attr *page_attribs)
 {
-  Pte p = _dir->walk( (void*)virt.value(), 0, false, Ptab::Null_alloc(), 0);
+  auto i = _dir->walk(virt);
+  if (order) *order = Page_order(i.page_order());
+
+  if (!i.is_valid())
+    return false;
+
+  if (phys) *phys = Virt_addr(i.page_addr());
+  if (page_attribs) *page_attribs = i.attribs();
 
-  if (size) *size = Size(p.size());
-  if (page_attribs) *page_attribs = p.attr().get_abstract();
-  // FIXME: we should not use virt but 0 as offset for phys return value!
-  if (phys) *phys = Phys_addr(p.phys((void*)virt.value()));
-  return p.valid();
+  return true;
 }
 
 IMPLEMENT
-unsigned long
-Mem_space::v_delete(Vaddr virt, Vsize size,
-                    unsigned long del_attribs)
+L4_fpage::Rights
+Mem_space::v_delete(Vaddr virt, Page_order size,
+                    L4_fpage::Rights page_attribs)
 {
-  (void)size;
-  bool flush = _current.current() == this;
-  Pte pte = _dir->walk((void*)virt.value(), 0, false, Ptab::Null_alloc(), 0);
-  if (EXPECT_FALSE(!pte.valid()))
-    return 0;
-
-  BUG_ON(pte.size() != size.value(), "size mismatch: va=%lx sz=%lx dir=%p\n",
-         virt.value(), size.value(), _dir);
+  (void) size;
+  assert (cxx::get_lsb(Virt_addr(virt), size) == 0);
+  auto i = _dir->walk(virt);
 
-  Mem_unit::flush_vcache((void*)(virt.value() & ~(pte.size()-1)), 
-      (void*)((virt.value() & ~(pte.size()-1)) + pte.size()));
+  if (EXPECT_FALSE (! i.is_valid()))
+    return L4_fpage::Rights(0);
 
-  Mem_page_attr a = pte.attr();
-  unsigned long abs_a = a.get_abstract();
+  L4_fpage::Rights ret = i.access_flags();
 
-  if (!(del_attribs & Page_user_accessible))
-    {
-      a.set_ap(abs_a & ~del_attribs);
-      pte.attr(a, flush);
-    }
+  if (! (page_attribs & L4_fpage::Rights::R()))
+    i.del_rights(page_attribs);
   else
-    pte.set_invalid(0, flush);
+    i.clear();
 
-  if (Have_asids)
-    Mem_unit::tlb_flush((void*)virt.value(), c_asid());
+  i.write_back_if(_current.current() == this, c_asid());
 
-  return abs_a & del_attribs;
+  return ret;
 }
 
 
-PUBLIC inline
-bool
-Mem_space::set_attributes(Address virt, unsigned page_attribs)
-{
-  Pte p = _dir->walk( (void*)virt, 0, false, Ptab::Null_alloc(), 0);
-  if (!p.valid())
-  // copy current shared kernel page directory
-    return false;
-
-  Mem_page_attr a = p.attr();
-  a.set_ap(page_attribs);
-  p.attr(a, true);
-  return true;
-}
 
 /**
  * \brief Free all memory allocated for this Mem_space.
@@ -353,9 +277,17 @@ Mem_space::~Mem_space()
   reset_asid();
   if (_dir)
     {
-      _dir->free_page_tables(0, (void*)Mem_layout::User_max,
-                             Kmem_alloc::q_allocator(ram_quota()));
-      Kmem_alloc::allocator()->q_unaligned_free(ram_quota(), sizeof(Page_table), _dir);
+
+      // free all page tables we have allocated for this address space
+      // except the ones in kernel space which are always shared
+      _dir->destroy(Virt_addr(0UL),
+                    Virt_addr(Mem_layout::User_max-1), 0, Pdir::Depth,
+                    Kmem_alloc::q_allocator(_quota));
+      // free all unshared page table levels for the kernel space
+      _dir->destroy(Virt_addr(Mem_layout::User_max),
+                    Virt_addr(~0UL), 0, Pdir::Super_level,
+                    Kmem_alloc::q_allocator(_quota));
+      Kmem_alloc::allocator()->q_unaligned_free(ram_quota(), sizeof(Dir_type), _dir);
     }
 }
 
@@ -372,22 +304,23 @@ PUBLIC inline
 Mem_space::Mem_space(Ram_quota *q)
 : _quota(q), _dir(0)
 {
-  asid(~0UL);
+  asid(Mem_unit::Asid_invalid);
 }
 
 PROTECTED inline NEEDS[<new>, "kmem_alloc.h", Mem_space::asid]
 bool
 Mem_space::initialize()
 {
-  Auto_quota<Ram_quota> q(ram_quota(), sizeof(Page_table));
+  Auto_quota<Ram_quota> q(ram_quota(), sizeof(Dir_type));
   if (EXPECT_FALSE(!q))
     return false;
 
-  _dir = (Page_table*)Kmem_alloc::allocator()->unaligned_alloc(sizeof(Page_table));
+  _dir = (Dir_type*)Kmem_alloc::allocator()->unaligned_alloc(sizeof(Dir_type));
   if (!_dir)
     return false;
 
-  new (_dir) Page_table;
+  _dir->clear(Pte_ptr::need_cache_write_back(false));
+  _dir_phys = Phys_mem_addr(kernel_space()->virt_to_phys((Address)_dir));
 
   q.release();
   return true;
@@ -397,19 +330,20 @@ PROTECTED inline
 void
 Mem_space::sync_kernel()
 {
-  // copy current shared kernel page directory
-  _dir->copy_in((void*)Mem_layout::User_max,
-                kernel_space()->_dir,
-                (void*)Mem_layout::User_max,
-                Mem_layout::Kernel_max - Mem_layout::User_max);
+  _dir->sync(Virt_addr(Mem_layout::User_max), kernel_space()->_dir,
+             Virt_addr(Mem_layout::User_max),
+             Virt_size(-Mem_layout::User_max), Pdir::Super_level,
+             Pte_ptr::need_cache_write_back(this == _current.current()),
+             Kmem_alloc::q_allocator(_quota));
 }
 
 PUBLIC
 Mem_space::Mem_space(Ram_quota *q, Dir_type* pdir)
   : _quota(q), _dir (pdir)
 {
-  asid(~0UL);
-  _current.cpu(0) = this;
+  asid(Mem_unit::Asid_invalid);
+  _current.cpu(Cpu_number::boot_cpu()) = this;
+  _dir_phys = Phys_mem_addr(virt_to_phys((Address)_dir));
 }
 
 PUBLIC static inline
@@ -417,6 +351,24 @@ Page_number
 Mem_space::canonize(Page_number v)
 { return v; }
 
+IMPLEMENTATION [arm && !arm_lpae]:
+
+PUBLIC static
+void
+Mem_space::init_page_sizes()
+{
+  add_page_size(Page_order(Config::PAGE_SHIFT));
+  add_page_size(Page_order(20)); // 1MB
+}
+
+//----------------------------------------------------------------------------
+IMPLEMENTATION [armv5 || armv6 || armv7]:
+
+IMPLEMENT inline
+void
+Mem_space::v_set_access_flags(Vaddr, L4_fpage::Rights)
+{}
+
 //----------------------------------------------------------------------------
 IMPLEMENTATION [armv5]:
 
@@ -438,8 +390,18 @@ Mem_space::c_asid() const
 IMPLEMENT inline
 void Mem_space::make_current()
 {
-  _dir->activate();
   _current.current() = this;
+  Mem_unit::flush_vcache();
+  asm volatile (
+      "mcr p15, 0, r0, c8, c7, 0 \n" // TLBIALL
+      "mcr p15, 0, %0, c2, c0    \n" // TTBR0
+
+      "mrc p15, 0, r1, c2, c0    \n"
+      "mov r1, r1                \n"
+      "sub pc, pc, #4            \n"
+      :
+      : "r" (cxx::int_value<Phys_mem_addr>(_dir_phys))
+      : "r1");
 }
 
 
@@ -451,7 +413,8 @@ EXTENSION class Mem_space
 public:
   enum { Have_asids = 1 };
 private:
-  unsigned long _asid[Config::Max_num_cpus];
+  typedef Per_cpu_array<unsigned long> Asid_array;
+  Asid_array _asid;
 
   static Per_cpu<unsigned char> _next_free_asid;
   static Per_cpu<Mem_space *[256]>   _active_asids;
@@ -471,7 +434,7 @@ IMPLEMENTATION [armv6 || armca8]:
 
 PRIVATE inline static
 unsigned long
-Mem_space::next_asid(unsigned cpu)
+Mem_space::next_asid(Cpu_number cpu)
 {
   return _next_free_asid.cpu(cpu)++;
 }
@@ -481,7 +444,7 @@ IMPLEMENTATION [armv7 && armca9]:
 
 PRIVATE inline static
 unsigned long
-Mem_space::next_asid(unsigned cpu)
+Mem_space::next_asid(Cpu_number cpu)
 {
   if (_next_free_asid.cpu(cpu) == 0)
     ++_next_free_asid.cpu(cpu);
@@ -498,8 +461,8 @@ PRIVATE inline
 void
 Mem_space::asid(unsigned long a)
 {
-  for (unsigned i = 0; i < Config::Max_num_cpus; ++i)
-    _asid[i] = a;
+  for (Asid_array::iterator i = _asid.begin(); i != _asid.end(); ++i)
+    *i = a;
 }
 
 PUBLIC inline
@@ -511,8 +474,8 @@ PRIVATE inline NEEDS[Mem_space::next_asid, "types.h"]
 unsigned long
 Mem_space::asid()
 {
-  unsigned cpu = current_cpu();
-  if (EXPECT_FALSE(_asid[cpu] == ~0UL))
+  Cpu_number cpu = current_cpu();
+  if (EXPECT_FALSE(_asid[cpu] == Mem_unit::Asid_invalid))
     {
       // FIFO ASID replacement strategy
       unsigned char new_asid = next_asid(cpu);
@@ -529,7 +492,6 @@ Mem_space::asid()
            }
 
          //LOG_MSG_3VAL(current(), "ASIDr", new_asid, (Mword)*bad_guy, (Mword)this);
-         Mem_unit::tlb_flush(new_asid);
 
           // 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
@@ -537,11 +499,12 @@ Mem_space::asid()
           // victim on a different CPU.
           if (victim != reinterpret_cast<Mem_space*>(~0UL) &&
               mp_cas(bad_guy, victim, reinterpret_cast<Mem_space*>(1)))
-            write_now(&victim->_asid[cpu], ~0UL);
+            write_now(&victim->_asid[cpu], (Mword)Mem_unit::Asid_invalid);
          break;
        }
 
       _asid[cpu] = new_asid;
+      Mem_unit::tlb_flush(new_asid);
       write_now(bad_guy, this);
     }
 
@@ -553,10 +516,10 @@ PRIVATE inline
 void
 Mem_space::reset_asid()
 {
-  for (unsigned i = 0; i < Config::Max_num_cpus; ++i)
+  for (Cpu_number i = Cpu_number::first(); i < Config::max_num_cpus(); ++i)
     {
-      unsigned asid = access_once(&_asid[i]);
-      if (asid == ~0UL)
+      unsigned long asid = access_once(&_asid[i]);
+      if (asid == Mem_unit::Asid_invalid)
         continue;
 
       Mem_space **a = &_active_asids.cpu(i)[asid];
@@ -568,9 +531,84 @@ Mem_space::reset_asid()
     }
 }
 
-IMPLEMENT inline NEEDS[Mem_space::asid]
+//-----------------------------------------------------------------------------
+IMPLEMENTATION [armv6 || armca8]:
+
+IMPLEMENT inline
 void Mem_space::make_current()
 {
-  _dir->activate(asid());
+  asm volatile (
+      "mcr p15, 0, %2, c7, c5, 6    \n" // bt flush
+      "mcr p15, 0, r0, c7, c10, 4   \n" // dsb
+      "mcr p15, 0, %0, c2, c0       \n" // set TTBR
+      "mcr p15, 0, r0, c7, c10, 4   \n" // dsb
+      "mcr p15, 0, %1, c13, c0, 1   \n" // set new ASID value
+      "mcr p15, 0, r0, c7, c5, 4    \n" // isb
+      "mcr p15, 0, %2, c7, c5, 6    \n" // bt flush
+      "mrc p15, 0, r1, c2, c0       \n"
+      "mov r1, r1                   \n"
+      "sub pc, pc, #4               \n"
+      :
+      : "r" (Phys_mem_addr::val(_dir_phys) | Page::Ttbr_bits), "r"(asid()), "r" (0)
+      : "r1");
+  _current.current() = this;
+}
+
+
+//-----------------------------------------------------------------------------
+IMPLEMENTATION [armv7 && armca9 && !arm_lpae]:
+
+IMPLEMENT inline
+void
+Mem_space::make_current()
+{
+  asm volatile (
+      "mcr p15, 0, %2, c7, c5, 6    \n" // bt flush
+      "dsb                          \n"
+      "mcr p15, 0, %2, c13, c0, 1   \n" // change ASID to 0
+      "isb                          \n"
+      "mcr p15, 0, %0, c2, c0       \n" // set TTBR
+      "isb                          \n"
+      "mcr p15, 0, %1, c13, c0, 1   \n" // set new ASID value
+      "isb                          \n"
+      "mcr p15, 0, %2, c7, c5, 6    \n" // bt flush
+      "isb                          \n"
+      "mov r1, r1                   \n"
+      "sub pc, pc, #4               \n"
+      :
+      : "r" (Phys_mem_addr::val(_dir_phys) | Page::Ttbr_bits), "r"(asid()), "r" (0)
+      : "r1");
+  _current.current() = this;
+}
+
+//-----------------------------------------------------------------------------
+IMPLEMENTATION [armv7 && arm_lpae]:
+
+PUBLIC static
+void
+Mem_space::init_page_sizes()
+{
+  add_page_size(Page_order(Config::PAGE_SHIFT));
+  add_page_size(Page_order(21)); // 2MB
+  if (0)
+    add_page_size(Page_order(30)); // 1GB
+}
+
+IMPLEMENT inline
+void
+Mem_space::make_current()
+{
+  asm volatile (
+      "mcr p15, 0, %2, c7, c5, 6    \n" // bt flush
+      "isb                          \n"
+      "mcrr p15, 0, %0, %1, c2      \n" // set TTBR
+      "isb                          \n"
+      "mcr p15, 0, %2, c7, c5, 6    \n" // bt flush
+      "isb                          \n"
+      "mov r1, r1                   \n"
+      "sub pc, pc, #4               \n"
+      :
+      : "r" (Phys_mem_addr::val(_dir_phys)), "r"(asid() << 16), "r" (0)
+      : "r1");
   _current.current() = this;
 }
index af076c9acc49cea28b246d21926248f2bfad8acf..19ec4451f007e343e7ce7198601fbe1f67617e87 100644 (file)
@@ -1,16 +1,20 @@
 INTERFACE [arm]:
 
-#include "kmem.h"
+#include "mem_layout.h"
 #include "mmu.h"
 
-class Mem_unit : public Mmu< Kmem::Cache_flush_area >
+class Mem_unit : public Mmu< Mem_layout::Cache_flush_area >
 {
 public:
+  enum : Mword
+  {
+    Asid_invalid = ~0UL
+  };
+
   static void tlb_flush();
-  static void dtlb_flush( void* va );
-  static void dtlb_flush();
+  static void dtlb_flush(void *va);
   static void tlb_flush(unsigned long asid);
-  static void dtlb_flush(unsigned long asid);
+  static void tlb_flush(void *va, unsigned long asid);
 };
 
 //---------------------------------------------------------------------------
@@ -19,108 +23,52 @@ IMPLEMENTATION [arm]:
 IMPLEMENT inline
 void Mem_unit::tlb_flush()
 {
-  asm volatile (
-      "mcr p15, 0, %0, c8, c7, 0x00 \n"
-      :
-      : "r" (0)
-      : "memory" ); // TLB flush
-}
-
-
-IMPLEMENT inline
-void Mem_unit::dtlb_flush( void* va )
-{
-  asm volatile (
-      "mcr p15, 0, %0, c8, c6, 0x01 \n"
-      :
-      : "r"((unsigned long)va & 0xfffff000)
-      : "memory" ); // TLB flush
+  asm volatile("mcr p15, 0, %0, c8, c7, 0" // TLBIALL
+               : : "r" (0) : "memory");
 }
 
 IMPLEMENT inline
-void Mem_unit::dtlb_flush()
+void Mem_unit::dtlb_flush(void *va)
 {
-  asm volatile (
-      "mcr p15, 0, %0, c8, c6, 0x0 \n"
-      :
-      : "r"(0)
-      : "memory" ); // TLB flush
+  asm volatile("mcr p15, 0, %0, c8, c6, 1" // DTLBIMVA
+               : : "r" ((unsigned long)va & 0xfffff000) : "memory");
 }
 
 //---------------------------------------------------------------------------
 IMPLEMENTATION [arm && armv5]:
 
-PUBLIC static inline
-void Mem_unit::tlb_flush( void* va, unsigned long)
-{
-  asm volatile (
-      "mcr p15, 0, %0, c8, c7, 0x01 \n"
-      :
-      : "r"((unsigned long)va & 0xfffff000)
-      : "memory" ); // TLB flush
-}
-
-
 IMPLEMENT inline
-void Mem_unit::tlb_flush(unsigned long)
+void Mem_unit::tlb_flush(void *va, unsigned long)
 {
-  asm volatile (
-      "mcr p15, 0, r0, c8, c7, 0x00 \n"
-      :
-      :
-      : "memory" ); // TLB flush
+  asm volatile("mcr p15, 0, %0, c8, c7, 1"
+               : : "r" ((unsigned long)va & 0xfffff000) : "memory");
 }
 
 IMPLEMENT inline
-void Mem_unit::dtlb_flush(unsigned long)
+void Mem_unit::tlb_flush(unsigned long)
 {
-  asm volatile (
-      "mcr p15, 0, %0, c8, c6, 0x0 \n"
-      :
-      : "r"(0)
-      : "memory" ); // TLB flush
+  asm volatile("mcr p15, 0, r0, c8, c7, 0" : : "r" (0) : "memory");
 }
 
-
 //---------------------------------------------------------------------------
 IMPLEMENTATION [arm && (armv6 || armv7)]:
 
-PUBLIC static inline
+IMPLEMENT inline
 void Mem_unit::tlb_flush(void *va, unsigned long asid)
 {
-  if (asid == ~0UL)
+  if (asid == Asid_invalid)
     return;
   btc_flush();
-  asm volatile (
-      "mcr p15, 0, %1, c7, c10, 4   \n" // drain write buffer
-      "mcr p15, 0, %0, c8, c7, 1    \n" // flush both TLB entry
-      :
-      : "r"(((unsigned long)va & 0xfffff000) | (asid & 0xff)),
-        "r" (0)
-      : "memory" );
+  Mem::dsb();
+  asm volatile("mcr p15, 0, %0, c8, c7, 1" // TLBIMVA
+               : : "r" (((unsigned long)va & 0xfffff000) | asid) : "memory");
 }
 
 IMPLEMENT inline
 void Mem_unit::tlb_flush(unsigned long asid)
 {
   btc_flush();
-  asm volatile (
-      "mcr p15, 0, %1, c7, c10, 4   \n" // drain write buffer
-      "mcr p15, 0, %0, c8, c7, 2    \n" // flush both TLB with asid
-      :
-      : "r"(asid),
-        "r" (0)
-      : "memory" );
+  Mem::dsb();
+  asm volatile("mcr p15, 0, %0, c8, c7, 2" // TLBIASID
+               : : "r" (asid) : "memory");
 }
-
-IMPLEMENT inline
-void Mem_unit::dtlb_flush(unsigned long asid)
-{
-  asm volatile (
-      "mcr p15, 0, r0, c7, c10, 4   \n" // drain write buffer
-      "mcr p15, 0, %0, c8, c6, 2    \n" // flush data TLB with asid
-      :
-      : "r"(asid)
-      : "memory" );
-}
-
index 15e96d62a4fede421eca37959a3c315d4c30759e..538514477181e8436c2ee1326418835c8cc35bef 100644 (file)
@@ -1,56 +1,77 @@
 INTERFACE [arm && outer_cache_l2cxx0]:
 
+#include "lock_guard.h"
 #include "mem_layout.h"
 #include "spin_lock.h"
+#include "mmio_register_block.h"
 
 EXTENSION class Outer_cache
 {
 private:
-  enum
-  {
-    Cache_line_shift = 5,
 
-    CACHE_ID                       = Mem_layout::L2cxx0_map_base + 0x000,
-    CACHE_TYPE                     = Mem_layout::L2cxx0_map_base + 0x004,
-    CONTROL                        = Mem_layout::L2cxx0_map_base + 0x100,
-    AUX_CONTROL                    = Mem_layout::L2cxx0_map_base + 0x104,
-    TAG_RAM_CONTROL                = Mem_layout::L2cxx0_map_base + 0x108,
-    DATA_RAM_CONTROL               = Mem_layout::L2cxx0_map_base + 0x10c,
-    EVENT_COUNTER_CONTROL          = Mem_layout::L2cxx0_map_base + 0x200,
-    EVENT_COUTNER1_CONFIG          = Mem_layout::L2cxx0_map_base + 0x204,
-    EVENT_COUNTER0_CONFIG          = Mem_layout::L2cxx0_map_base + 0x208,
-    EVENT_COUNTER1_VALUE           = Mem_layout::L2cxx0_map_base + 0x20c,
-    EVENT_COUNTER0_VALUE           = Mem_layout::L2cxx0_map_base + 0x210,
-    INTERRUPT_MASK                 = Mem_layout::L2cxx0_map_base + 0x214,
-    MASKED_INTERRUPT_STATUS        = Mem_layout::L2cxx0_map_base + 0x218,
-    RAW_INTERRUPT_STATUS           = Mem_layout::L2cxx0_map_base + 0x21c,
-    INTERRUPT_CLEAR                = Mem_layout::L2cxx0_map_base + 0x220,
-    CACHE_SYNC                     = Mem_layout::L2cxx0_map_base + 0x730,
-    INVALIDATE_LINE_BY_PA          = Mem_layout::L2cxx0_map_base + 0x770,
-    INVALIDATE_BY_WAY              = Mem_layout::L2cxx0_map_base + 0x77c,
-    CLEAN_LINE_BY_PA               = Mem_layout::L2cxx0_map_base + 0x7b0,
-    CLEAN_LINE_BY_INDEXWAY         = Mem_layout::L2cxx0_map_base + 0x7bb,
-    CLEAN_BY_WAY                   = Mem_layout::L2cxx0_map_base + 0x7bc,
-    CLEAN_AND_INV_LINE_BY_PA       = Mem_layout::L2cxx0_map_base + 0x7f0,
-    CLEAN_AND_INV_LINE_BY_INDEXWAY = Mem_layout::L2cxx0_map_base + 0x7f8,
-    CLEAN_AND_INV_BY_WAY           = Mem_layout::L2cxx0_map_base + 0x7fc,
-    LOCKDOWN_BY_WAY_D_SIDE         = Mem_layout::L2cxx0_map_base + 0x900,
-    LOCKDOWN_BY_WAY_I_SIDE         = Mem_layout::L2cxx0_map_base + 0x904,
-    TEST_OPERATION                 = Mem_layout::L2cxx0_map_base + 0xf00,
-    LINE_TAG                       = Mem_layout::L2cxx0_map_base + 0xf30,
-    DEBUG_CONTROL_REGISTER         = Mem_layout::L2cxx0_map_base + 0xf40,
+  class L2cxx0 : public Mmio_register_block
+  {
+  public:
+    enum
+    {
+      CACHE_ID                       = 0x000,
+      CACHE_TYPE                     = 0x004,
+      CONTROL                        = 0x100,
+      AUX_CONTROL                    = 0x104,
+      TAG_RAM_CONTROL                = 0x108,
+      DATA_RAM_CONTROL               = 0x10c,
+      EVENT_COUNTER_CONTROL          = 0x200,
+      EVENT_COUTNER1_CONFIG          = 0x204,
+      EVENT_COUNTER0_CONFIG          = 0x208,
+      EVENT_COUNTER1_VALUE           = 0x20c,
+      EVENT_COUNTER0_VALUE           = 0x210,
+      INTERRUPT_MASK                 = 0x214,
+      MASKED_INTERRUPT_STATUS        = 0x218,
+      RAW_INTERRUPT_STATUS           = 0x21c,
+      INTERRUPT_CLEAR                = 0x220,
+      CACHE_SYNC                     = 0x730,
+      INVALIDATE_LINE_BY_PA          = 0x770,
+      INVALIDATE_BY_WAY              = 0x77c,
+      CLEAN_LINE_BY_PA               = 0x7b0,
+      CLEAN_LINE_BY_INDEXWAY         = 0x7bb,
+      CLEAN_BY_WAY                   = 0x7bc,
+      CLEAN_AND_INV_LINE_BY_PA       = 0x7f0,
+      CLEAN_AND_INV_LINE_BY_INDEXWAY = 0x7f8,
+      CLEAN_AND_INV_BY_WAY           = 0x7fc,
+      LOCKDOWN_BY_WAY_D_SIDE         = 0x900,
+      LOCKDOWN_BY_WAY_I_SIDE         = 0x904,
+      TEST_OPERATION                 = 0xf00,
+      LINE_TAG                       = 0xf30,
+      DEBUG_CONTROL_REGISTER         = 0xf40,
+    };
+
+    Spin_lock<> _lock;
+
+    explicit L2cxx0(Address virt) : Mmio_register_block(virt) {}
+
+    void write_op(Address reg, Mword val, bool before = false)
+    {
+      auto guard = lock_guard(_lock);
+      if (before)
+        while (read<Mword>(reg) & 1)
+          ;
+      Mmio_register_block::write<Mword>(val, reg);
+      if (!before)
+        while (read<Mword>(reg) & 1)
+          ;
+    }
   };
 
-  static Spin_lock<> _lock;
-
   static Mword platform_init(Mword aux);
 
+  static Static_object<L2cxx0> l2cxx0;
   static bool need_sync;
   static unsigned waymask;
 
 public:
   enum
   {
+    Cache_line_shift = 5,
     Cache_line_size = 1 << Cache_line_shift,
     Cache_line_mask = Cache_line_size - 1,
   };
@@ -59,83 +80,71 @@ public:
 // ------------------------------------------------------------------------
 IMPLEMENTATION [arm && outer_cache_l2cxx0]:
 
-#include "io.h"
-#include "lock_guard.h"
+#include "kmem.h"
+#include "processor.h"
 #include "static_init.h"
 
-Spin_lock<> Outer_cache::_lock;
+Static_object<Outer_cache::L2cxx0> Outer_cache::l2cxx0;
+
+//Spin_lock<> Outer_cache::_lock;
 bool Outer_cache::need_sync;
 unsigned Outer_cache::waymask;
 
-IMPLEMENT inline NEEDS ["io.h"]
+IMPLEMENT inline
 void
 Outer_cache::sync()
 {
-  while (Io::read<Mword>(CACHE_SYNC))
+  while (l2cxx0->read<Mword>(L2cxx0::CACHE_SYNC))
     Proc::preemption_point();
 }
 
-PRIVATE static inline NEEDS ["io.h", "lock_guard.h"]
-void
-Outer_cache::write(Address reg, Mword val, bool before = false)
-{
-  auto guard = lock_guard(_lock);
-  if (before)
-    while (Io::read<Mword>(reg) & 1)
-      ;
-  Io::write<Mword>(val, reg);
-  if (!before)
-    while (Io::read<Mword>(reg) & 1)
-      ;
-}
-
-IMPLEMENT inline NEEDS[Outer_cache::write]
+IMPLEMENT inline
 void
 Outer_cache::clean()
 {
-  write(CLEAN_BY_WAY, waymask);
+  l2cxx0->write_op(L2cxx0::CLEAN_BY_WAY, waymask);
   sync();
 }
 
-IMPLEMENT inline NEEDS[Outer_cache::write]
+IMPLEMENT inline
 void
 Outer_cache::clean(Mword phys_addr, bool do_sync = true)
 {
-  write(CLEAN_LINE_BY_PA, phys_addr & (~0UL << Cache_line_shift));
+  l2cxx0->write_op(L2cxx0::CLEAN_LINE_BY_PA, phys_addr & (~0UL << Cache_line_shift));
   if (need_sync && do_sync)
     sync();
 }
 
-IMPLEMENT inline NEEDS[Outer_cache::write]
+IMPLEMENT inline
 void
 Outer_cache::flush()
 {
-  write(CLEAN_AND_INV_BY_WAY, waymask);
+  l2cxx0->write_op(L2cxx0::CLEAN_AND_INV_BY_WAY, waymask);
   sync();
 }
 
-IMPLEMENT inline NEEDS[Outer_cache::write]
+IMPLEMENT inline
 void
 Outer_cache::flush(Mword phys_addr, bool do_sync = true)
 {
-  write(CLEAN_AND_INV_LINE_BY_PA, phys_addr & (~0UL << Cache_line_shift));
+  l2cxx0->write_op(L2cxx0::CLEAN_AND_INV_LINE_BY_PA, phys_addr & (~0UL << Cache_line_shift));
   if (need_sync && do_sync)
     sync();
 }
 
-IMPLEMENT inline NEEDS[Outer_cache::write]
+IMPLEMENT inline
 void
 Outer_cache::invalidate()
 {
-  write(INVALIDATE_BY_WAY, waymask);
+  l2cxx0->write_op(L2cxx0::INVALIDATE_BY_WAY, waymask);
   sync();
 }
 
-IMPLEMENT inline NEEDS[Outer_cache::write]
+IMPLEMENT inline
 void
 Outer_cache::invalidate(Address phys_addr, bool do_sync = true)
 {
-  write(INVALIDATE_LINE_BY_PA, phys_addr & (~0UL << Cache_line_shift));
+  l2cxx0->write_op(L2cxx0::INVALIDATE_LINE_BY_PA, phys_addr & (~0UL << Cache_line_shift));
   if (need_sync && do_sync)
     sync();
 }
@@ -144,8 +153,9 @@ PUBLIC static
 void
 Outer_cache::initialize(bool v)
 {
-  Mword cache_id   = Io::read<Mword>(CACHE_ID);
-  Mword aux        = Io::read<Mword>(AUX_CONTROL);
+  l2cxx0.construct(Kmem::mmio_remap(Mem_layout::L2cxx0_phys_base));
+  Mword cache_id   = l2cxx0->read<Mword>(L2cxx0::CACHE_ID);
+  Mword aux        = l2cxx0->read<Mword>(L2cxx0::AUX_CONTROL);
   unsigned ways    = 8;
 
   need_sync = true;
@@ -167,14 +177,14 @@ Outer_cache::initialize(bool v)
 
   waymask = (1 << ways) - 1;
 
-  Io::write<Mword>(0,    INTERRUPT_MASK);
-  Io::write<Mword>(~0UL, INTERRUPT_CLEAR);
+  l2cxx0->write<Mword>(0, L2cxx0::INTERRUPT_MASK);
+  l2cxx0->write<Mword>(~0UL, L2cxx0::INTERRUPT_CLEAR);
 
-  if (!(Io::read<Mword>(CONTROL) & 1))
+  if (!(l2cxx0->read<Mword>(L2cxx0::CONTROL) & 1))
     {
-      Io::write(aux, AUX_CONTROL);
+      l2cxx0->write(aux, L2cxx0::AUX_CONTROL);
       invalidate();
-      Io::write<Mword>(1, CONTROL);
+      l2cxx0->write<Mword>(1, L2cxx0::CONTROL);
     }
 
   if (v)
@@ -209,7 +219,7 @@ void
 Outer_cache::show_info(unsigned ways, Mword cache_id, Mword aux)
 {
   printf("L2: ID=%08lx Type=%08lx Aux=%08lx WMask=%x S=%d\n",
-         cache_id, Io::read<Mword>(CACHE_TYPE), aux, waymask, need_sync);
+         cache_id, l2cxx0->read<Mword>(L2cxx0::CACHE_TYPE), aux, waymask, need_sync);
 
   const char *type;
   switch ((cache_id >> 6) & 0xf)
index 731da3280b38d1da6fb3e12ef4593d5ba930df59..5dda90ef67f915a3f516f0c091f85ae6d3d19388 100644 (file)
 INTERFACE [arm]:
 
+#include "mem_unit.h"
 
 class PF {};
+class Page
+{
+};
+
+
+//-------------------------------------------------------------------------------------
+INTERFACE [arm && !arm_lpae]:
+
+class Pte_ptr
+{
+public:
+  typedef Mword Entry;
+  enum
+  {
+    Super_level    = 0,
+  };
+
+  Pte_ptr() = default;
+  Pte_ptr(void *p, unsigned char level) : pte((Mword*)p), level(level) {}
+
+  bool is_valid() const { return *pte & 3; }
+  void clear() { *pte = 0; }
+  bool is_leaf() const
+  {
+    switch (level)
+      {
+      case 0: return (*pte & 3) == 2;
+      default: return true;
+      };
+  }
+
+  Mword next_level() const
+  {
+    // 1KB second level tables
+    return cxx::mask_lsb(*pte, 10);
+  }
+
+  void set_next_level(Mword phys)
+  {
+    write_now(pte, phys | 1);
+  }
+
+  unsigned char page_order() const
+  {
+    if (level == 0)
+      return 20; // 1MB
+    else
+      { // no tiny pages !!!
+        if ((*pte & 3) == 1)
+          return 16;
+        else
+          return 12;
+      }
+  }
+
+  Mword page_addr() const
+  { return cxx::mask_lsb(*pte, page_order()); }
+
+  Mword *pte;
+  unsigned char level;
+};
+
+EXTENSION class Page
+{ public: enum { Ttbcr_bits = 0, Mair0_bits = 0 }; };
+
+//-----------------------------------------------------------------------------
+INTERFACE [arm && arm_lpae]:
+
+class Pte_ptr
+{
+public:
+  typedef Unsigned64 Entry;
+
+  enum
+  {
+    Super_level    = 1,
+  };
+
+  Pte_ptr() = default;
+  Pte_ptr(void *p, unsigned char level) : pte((Unsigned64*)p), level(level) {}
+
+  bool is_valid() const { return *pte & 1; }
+  void clear() { *pte = 0; }
+  bool is_leaf() const
+  {
+    if (level >= 2)
+      return true;
+    return (*pte & 3) == 1;
+  }
+
+  Unsigned64 next_level() const
+  {
+    // 1KB second level tables
+    return cxx::get_lsb(cxx::mask_lsb(*pte, 12), 40);
+  }
+
+  void set_next_level(Unsigned64 phys)
+  {
+    write_now(pte, phys | 3);
+  }
+
+  Mword page_addr() const
+  { return cxx::mask_lsb(*pte, page_order()); }
+
+  Unsigned64 *pte;
+  unsigned char level;
+};
+
+EXTENSION class Page
+{
+public:
+  enum
+  {
+    Ttbcr_bits =   (1 << 31) // EAE
+                 | (2 << 12) // SH0
+                 | (1 << 10) // ORGN0
+                 | (1 << 8), // IRGN0
+    Mair0_bits = 0x00ff4400
+  };
+};
+
+//---------------------------------------------------------------------------
+IMPLEMENTATION [arm && arm_lpae]:
+
+PUBLIC inline
+unsigned char
+Pte_ptr::page_order() const
+{ return Pdir::page_order_for_level(level); }
+
 
 //-----------------------------------------------------------------------------
 INTERFACE [arm && armv5]:
 
 #include "types.h"
 
-
-namespace Page
+EXTENSION class Page
 {
+public:
   typedef Unsigned32 Attribs;
 
   enum Attribs_enum
   {
-    KERN_RW  = 0x0400, ///< User No access
-    USER_RO  = 0x0000, ///< User Read only
-    USER_RW  = 0x0c00, ///< User Read/Write
-
-    USER_BIT = 0x00800,
-
     Cache_mask    = 0x0c,
     NONCACHEABLE  = 0x00, ///< Caching is off
     CACHEABLE     = 0x0c, ///< Cache is enabled
@@ -28,34 +152,93 @@ namespace Page
     // The next are ARM specific
     WRITETHROUGH = 0x08, ///< Write through cached
     BUFFERED     = 0x04, ///< Write buffer enabled
+  };
 
-    MAX_ATTRIBS  = 0x0dec,
-    Local_page   = 0,
+  enum Default_entries : Mword
+  {
+    Section_cachable = 0x40e,
+    Section_no_cache = 0x402,
+    Section_local    = 0,
+    Section_global   = 0,
   };
 };
 
+EXTENSION class Pte_ptr
+{
+  // we have virtually tagged caches so need a cache flush before enabling
+  // a page table
+  enum { Need_cache_clean = false }; // we have virtuially tagged caches
+};
 
 
 
+//---------------------------------------------------------------------------
+INTERFACE [arm && armv6plus && (mpcore || armca9)]:
+
+EXTENSION class Page
+{
+public:
+  enum
+  {
+    Section_shared = 1UL << 16,
+    Mp_set_shared = 0x400,
+  };
+};
+
+//---------------------------------------------------------------------------
+INTERFACE [arm && armv6plus && !(mpcore || armca9)]:
+
+EXTENSION class Page
+{
+public:
+  enum
+  {
+    Section_shared = 0,
+    Mp_set_shared = 0,
+  };
+};
+
+//---------------------------------------------------------------------------
+INTERFACE [arm && (armv5 || (armv6 && !mpcore))]:
+
+EXTENSION class Page
+{ public: enum { Ttbr_bits = 0 }; };
+
+//---------------------------------------------------------------------------
+INTERFACE [arm && mpcore]:
+
+EXTENSION class Page
+{ public: enum { Ttbr_bits = 0xa }; };
+
+//---------------------------------------------------------------------------
+INTERFACE [arm && armca9 && !arm_lpae]:
+
+// S Sharable | RGN = Outer WB-WA | IRGN = Inner WB-WA | NOS
+EXTENSION class Page
+{ public: enum { Ttbr_bits = 0x6a }; };
+
+//---------------------------------------------------------------------------
+INTERFACE [arm && armca9 && arm_lpae]:
+
+EXTENSION class Page
+{ public: enum { Ttbr_bits = 0 }; };
+
+//---------------------------------------------------------------------------
+INTERFACE [arm && armca8]: // armv7 w/o multiprocessing ext.
+
+EXTENSION class Page
+{ public: enum { Ttbr_bits = 0x2b }; };
 
 //----------------------------------------------------------------------------
-INTERFACE [arm && (armv6 || armv7)]:
+INTERFACE [arm && (armv6 || armv7) && !arm_lpae]:
 
 #include "types.h"
 
-namespace Page
+EXTENSION class Page
 {
-  typedef Unsigned32 Attribs;
-
+public:
   enum Attribs_enum
   {
-    KERN_RO  = 0x0210,
-    KERN_RW  = 0x0010, ///< User No access
-    USER_RO  = 0x0230, ///< User Read only
-    USER_RW  = 0x0030, ///< User Read/Write
-
-    USER_BIT = 0x0020,
-
     Cache_mask    = 0x1cc,
     NONCACHEABLE  = 0x000, ///< Caching is off
     CACHEABLE     = 0x144, ///< Cache is enabled
@@ -63,68 +246,117 @@ namespace Page
     // The next are ARM specific
     WRITETHROUGH = 0x08, ///< Write through cached
     BUFFERED     = 0x40, ///< Write buffer enabled -- Normal, non-cached
+  };
 
-    MAX_ATTRIBS  = 0x0ffc,
-    Local_page   = 0x800,
+  enum Default_entries : Mword
+  {
+    Section_cachable = 0x5406 | Section_shared,
+    Section_no_cache = 0x0402 | Section_shared,
+    Section_local    = (1 << 17),
+    Section_global   = 0,
   };
 };
 
-
 //-----------------------------------------------------------------------------
-INTERFACE [arm]:
+INTERFACE [arm && !arm_lpae]:
 
 #include "ptab_base.h"
 
+typedef Ptab::List< Ptab::Traits< Unsigned32, 20, 12, true>,
+                    Ptab::Traits< Unsigned32, 12, 8, true> > Ptab_traits;
+
+typedef Ptab::Shift<Ptab_traits, Virt_addr::Shift>::List Ptab_traits_vpn;
+typedef Ptab::Page_addr_wrap<Page_number, Virt_addr::Shift> Ptab_va_vpn;
+
+//-----------------------------------------------------------------------------
+INTERFACE [arm && arm_lpae]:
 
-// dummy for JDB
-class Pte_base
+#include "ptab_base.h"
+#include "types.h"
+
+EXTENSION class Page
 {
 public:
-  enum
+  enum Attribs_enum
   {
-    Super_level    = 0,
-    Valid          = 0x3,
-    Type_mask      = 0x3,
-    Type_1MB       = 0x2,
-    Type_4KB       = 0x2,
-    Type_coarse_pt = 0x1,
+    Cache_mask    = 0x01c,
+    NONCACHEABLE  = 0x000, ///< Caching is off
+    CACHEABLE     = 0x008, ///< Cache is enabled
+    BUFFERED      = 0x004, ///< Write buffer enabled -- Normal, non-cached
   };
-  typedef Mword Raw;
-  Raw raw() const  { return _raw; }
-  Address addr() const { return _raw & (~0UL << 12); }
-
-protected:
-  Raw _raw;
 };
 
-class Pd_entry : public Pte_base
+typedef Ptab::Tupel< Ptab::Traits< Unsigned64, 30, 2, true>,
+                     Ptab::Traits< Unsigned64, 21, 9, true>,
+                     Ptab::Traits< Unsigned64, 12, 9, true> >::List Ptab_traits;
+
+typedef Ptab::Shift<Ptab_traits, Virt_addr::Shift>::List Ptab_traits_vpn;
+typedef Ptab::Page_addr_wrap<Page_number, Virt_addr::Shift> Ptab_va_vpn;
+
+//---------------------------------------------------------------------------
+IMPLEMENTATION [arm && armv5]:
+
+PUBLIC static inline
+bool
+Pte_ptr::need_cache_write_back(bool current_pt)
+{ return current_pt; }
+
+PUBLIC inline
+void
+Pte_ptr::write_back_if(bool current_pt, Mword /*asid*/ = 0)
 {
-public:
-  enum { Page_shift = Config::SUPERPAGE_SHIFT };
-  Mword leaf() const { return (_raw & Type_mask) == Type_1MB; }
-  void set(Address p, bool intermed, bool present, unsigned long attrs = 0)
-  {
-    _raw = (p & (~0UL << Page_shift))
-      | (present ? (intermed ? Type_coarse_pt : Type_1MB) : 0) | attrs;
-  }
-};
+  if (current_pt)
+    Mem_unit::clean_dcache(pte);
+}
 
-class Pt_entry : public Pte_base
+PUBLIC static inline
+void
+Pte_ptr::write_back(void *start, void *end)
+{ Mem_unit::clean_dcache(start, end); }
+
+//---------------------------------------------------------------------------
+IMPLEMENTATION [arm && armv6]:
+
+PUBLIC static inline
+bool
+Pte_ptr::need_cache_write_back(bool)
+{ return true; }
+
+PUBLIC inline
+void
+Pte_ptr::write_back_if(bool, Mword asid = Mem_unit::Asid_invalid)
 {
-public:
-  enum { Page_shift = Config::PAGE_SHIFT };
-  Mword leaf() const { return true; }
-  void set(Address p, bool, bool present, unsigned long attrs = 0)
-  {
-    _raw = (p & (~0UL << Page_shift)) | (present ? Type_4KB : 0) | attrs;
-  }
-};
+  Mem_unit::clean_dcache(pte);
+  if (asid != Mem_unit::Asid_invalid)
+    Mem_unit::tlb_flush(asid);
+}
+
+PUBLIC static inline
+void
+Pte_ptr::write_back(void *start, void *end)
+{ Mem_unit::clean_dcache(start, end); }
+
+//---------------------------------------------------------------------------
+IMPLEMENTATION [arm && armv7]:
+
+PUBLIC static inline
+bool
+Pte_ptr::need_cache_write_back(bool)
+{ return false; }
 
-typedef Ptab::List< Ptab::Traits< Pd_entry, 20, 12, true>,
-                    Ptab::Traits< Pt_entry, 12, 8, true> > Ptab_traits;
+PUBLIC inline
+void
+Pte_ptr::write_back_if(bool, Mword asid = Mem_unit::Asid_invalid)
+{
+  if (asid != Mem_unit::Asid_invalid)
+    Mem_unit::tlb_flush(asid);
+}
+
+PUBLIC static inline
+void
+Pte_ptr::write_back(void *, void *)
+{}
 
-typedef Ptab_traits Ptab_traits_vpn;
-typedef Ptab::Page_addr_wrap<Virt_addr, 0> Ptab_va_vpn;
 
 //---------------------------------------------------------------------------
 IMPLEMENTATION [arm && armv5]:
@@ -133,34 +365,517 @@ PUBLIC static inline
 Mword PF::is_alignment_error(Mword error)
 { return (error & 0xf0000d) == 0x400001; }
 
+PRIVATE inline
+Pte_ptr::Entry
+Pte_ptr::_attribs_mask() const
+{
+  if (level == 0)
+    return ~Entry(0x00000c0c);
+  else
+    return ~Entry(0x00000ffc);
+}
+
+PRIVATE inline
+Mword
+Pte_ptr::_attribs(Page::Attr attr) const
+{
+  static const unsigned short perms[] = {
+      0x1 << 10, // 0000: none, hmmm
+      0x1 << 10, // 000X: kernel rw (there is no ro)
+      0x1 << 10, // 00W0:
+      0x1 << 10, // 00WX:
+
+      0x1 << 10, // 0R00:
+      0x1 << 10, // 0R0X:
+      0x1 << 10, // 0RW0:
+      0x1 << 10, // 0RWX:
+
+      0x1 << 10, // U000:
+      0x0 << 10, // U00X:
+      0x3 << 10, // U0W0:
+      0x3 << 10, // U0WX:
+
+      0x0 << 10, // UR00:
+      0x0 << 10, // UR0X:
+      0x3 << 10, // URW0:
+      0x3 << 10  // URWX:
+  };
+
+  typedef Page::Type T;
+  typedef Page::Kern K;
+  Mword r = 0;
+  if (attr.type == T::Normal())   r |= Page::CACHEABLE;
+  if (attr.type == T::Buffered()) r |= Page::BUFFERED;
+  if (attr.type == T::Uncached()) r |= Page::NONCACHEABLE;
+  if (level == 0)
+    return r | perms[cxx::int_value<L4_fpage::Rights>(attr.rights)];
+  else
+    {
+      Mword p = perms[cxx::int_value<L4_fpage::Rights>(attr.rights)];
+      p |= p >> 2;
+      p |= p >> 4;
+      return r | p;
+    }
+}
+
+PUBLIC inline
+Page::Attr
+Pte_ptr::attribs() const
+{
+  auto r = access_once(pte);
+  auto c = r & 0xc;
+  r &= 0xc00;
+
+  typedef L4_fpage::Rights R;
+  typedef Page::Type T;
+
+  R rights;
+  switch (r)
+    {
+    case 0x000: rights = R::URX(); break;
+    default:
+    case 0x400: rights = R::RWX(); break;
+    case 0xc00: rights = R::URWX(); break;
+    }
+
+  T type;
+  switch (c)
+    {
+    default:
+    case Page::CACHEABLE: type = T::Normal(); break;
+    case Page::BUFFERED:  type = T::Buffered(); break;
+    case Page::NONCACHEABLE: type = T::Uncached(); break;
+    }
+  return Page::Attr(rights, type);
+}
+
+PUBLIC inline NEEDS[Pte_ptr::_attribs, Pte_ptr::_attribs_mask]
+void
+Pte_ptr::set_attribs(Page::Attr attr)
+{
+  Mword p = access_once(pte);
+  p = (p & _attribs_mask()) | _attribs(attr);
+  write_now(pte, p);
+}
+
+PUBLIC inline NEEDS[Pte_ptr::_attribs]
+void
+Pte_ptr::create_page(Phys_mem_addr addr, Page::Attr attr)
+{
+  Mword p = 2 | _attribs(attr) | cxx::int_value<Phys_mem_addr>(addr);
+  write_now(pte, p);
+}
+
+PUBLIC inline
+bool
+Pte_ptr::add_attribs(Page::Attr attr)
+{
+  typedef L4_fpage::Rights R;
+
+  if (attr.rights & R::W())
+    {
+      auto p = access_once(pte);
+      if ((p & 0xc00) == 0x000)
+        {
+          p |= level == 0 ? 0xc00 : 0xff0;
+          write_now(pte, p);
+          return true;
+        }
+    }
+  return false;
+}
+
+PUBLIC inline
+Page::Rights
+Pte_ptr::access_flags() const
+{ return Page::Rights(0); }
+
+PUBLIC inline
+void
+Pte_ptr::del_rights(L4_fpage::Rights r)
+{
+  if (!(r & L4_fpage::Rights::W()))
+    return;
+
+  auto p = access_once(pte);
+  if ((p & 0xc00) == 0xc00)
+    {
+      p &= (level == 0) ? ~Mword(0xc00) : ~Mword(0xff0);
+      write_now(pte, p);
+    }
+}
+
+
 //---------------------------------------------------------------------------
-IMPLEMENTATION [arm && (armv6 || armv7)]:
+IMPLEMENTATION [arm && !arm_lpae && (armv6 || armv7)]:
+
+PRIVATE inline
+Pte_ptr::Entry
+Pte_ptr::_attribs_mask() const
+{
+  if (level == 0)
+    return ~Entry(0x0000881c);
+  else
+    return ~Entry(0x0000022d);
+}
+
+PRIVATE inline
+Mword
+Pte_ptr::_attribs(Page::Attr attr) const
+{
+  typedef L4_fpage::Rights R;
+  typedef Page::Type T;
+  typedef Page::Kern K;
+
+  Mword lower = Page::Mp_set_shared;
+  if (attr.type == T::Normal())   lower |= Page::CACHEABLE;
+  if (attr.type == T::Buffered()) lower |= Page::BUFFERED;
+  if (attr.type == T::Uncached()) lower |= Page::NONCACHEABLE;
+  Mword upper = lower & ~0x0f;
+  lower &= 0x0f;
+
+  if (!(attr.kern & K::Global()))
+    upper |= 0x800;
+
+  if (!(attr.rights & R::W()))
+    upper |= 0x200;
+
+  if (attr.rights & R::U())
+    upper |= 0x20;
+
+  if (!(attr.rights & R::X()))
+    {
+      if (level == 0)
+        lower |= 0x10;
+      else
+        lower |= 0x01;
+    }
+
+  if (level == 0)
+    return lower | (upper << 6);
+  else
+    return lower | upper;
+}
+
+PUBLIC inline
+Page::Attr
+Pte_ptr::attribs() const
+{
+  typedef L4_fpage::Rights R;
+  typedef Page::Type T;
+  typedef Page::Kern K;
+
+  auto c = access_once(pte);
+
+  R rights = R::R();
+
+  if (level == 0)
+    {
+      if (!(c & 0x10))
+        rights |= R::X();
+
+      c = (c & 0x0f) | ((c >> 6) & 0xfff0);
+    }
+  else if (!(c & 0x01))
+    rights |= R::X();
+
+  if (!(c & 0x200))
+    rights |= R::W();
+  if (c & 0x20)
+    rights |= R::U();
+
+  T type;
+  switch (c & Page::Cache_mask)
+    {
+    default:
+    case Page::CACHEABLE: type = T::Normal(); break;
+    case Page::BUFFERED:  type = T::Buffered(); break;
+    case Page::NONCACHEABLE: type = T::Uncached(); break;
+    }
+
+  K k(0);
+  if (!(c & 0x800))
+    k |= K::Global();
+
+  return Page::Attr(rights, type, k);
+}
+
+PUBLIC inline NEEDS[Pte_ptr::_attribs]
+void
+Pte_ptr::create_page(Phys_mem_addr addr, Page::Attr attr)
+{
+  Mword p = 2 | _attribs(attr) | cxx::int_value<Phys_mem_addr>(addr);
+  if (level == 0)
+    p |= 0x400;  // AP[0]
+  else
+    p |= 0x10;   // AP[0]
+
+  write_now(pte, p);
+}
+
+PUBLIC inline
+bool
+Pte_ptr::add_attribs(Page::Attr attr)
+{
+  typedef L4_fpage::Rights R;
+  Mword n_attr = 0;
+
+  if (attr.rights & R::W())
+    {
+      if (level == 0)
+        n_attr = 0x200 << 6;
+      else
+        n_attr = 0x200;
+    }
+
+  if (attr.rights & R::X())
+    {
+      if (level == 0)
+        n_attr |= 0x10;
+      else
+        n_attr |= 0x01;
+    }
+
+
+  auto p = access_once(pte);
+  if (p & n_attr)
+    {
+      p &= ~n_attr;
+      write_now(pte, p);
+      return true;
+    }
+
+  return false;
+}
+
+PUBLIC inline
+Page::Rights
+Pte_ptr::access_flags() const
+{ return Page::Rights(0); }
+
+PUBLIC inline
+void
+Pte_ptr::del_rights(L4_fpage::Rights r)
+{
+  Mword n_attr = 0;
+  if (r & L4_fpage::Rights::W())
+    {
+      if (level == 0)
+        n_attr = 0x200 << 6;
+      else
+        n_attr = 0x200;
+    }
+
+  if (r & L4_fpage::Rights::X())
+    {
+      if (level == 0)
+        n_attr |= 0x10;
+      else
+        n_attr |= 0x01;
+    }
+
+  if (!n_attr)
+    return;
+
+  auto p = access_once(pte);
+  if ((p & n_attr) != n_attr)
+    {
+      p |= n_attr;
+      write_now(pte, p);
+    }
+}
 
-PUBLIC static inline
-Mword PF::is_alignment_error(Mword error)
-{ return (error & 0xf0040f) == 0x400001; }
 
 //---------------------------------------------------------------------------
-IMPLEMENTATION [arm]:
+IMPLEMENTATION [arm && arm_lpae && (armv6 || armv7)]:
+
+PRIVATE inline
+Pte_ptr::Entry
+Pte_ptr::_attribs_mask() const
+{ return ~Entry(0x00400000000008dc); }
+
+PRIVATE inline
+Pte_ptr::Entry
+Pte_ptr::_attribs(Page::Attr attr) const
+{
+  typedef L4_fpage::Rights R;
+  typedef Page::Type T;
+  typedef Page::Kern K;
+
+  Entry lower = 0x300; // inner sharable
+  if (attr.type == T::Normal())   lower |= Page::CACHEABLE;
+  if (attr.type == T::Buffered()) lower |= Page::BUFFERED;
+  if (attr.type == T::Uncached()) lower |= Page::NONCACHEABLE;
+
+  if (!(attr.kern & K::Global()))
+    lower |= 0x800;
+
+  if (!(attr.rights & R::W()))
+    lower |= 0x080;
+
+  if (attr.rights & R::U())
+    lower |= 0x040;
+
+  if (!(attr.rights & R::X()))
+    lower |= 0x0040000000000000;
+
+  return lower;
+}
 
 PUBLIC inline
+Page::Attr
+Pte_ptr::attribs() const
+{
+  typedef L4_fpage::Rights R;
+  typedef Page::Type T;
+  typedef Page::Kern K;
+
+  auto c = access_once(pte);
+
+  R rights = R::R();
+  if (!(c & 0x80))
+    rights |= R::W();
+  if (c & 0x40)
+    rights |= R::U();
+
+  if (!(c & 0x0040000000000000))
+    rights |= R::X();
+
+  T type;
+  switch (c & Page::Cache_mask)
+    {
+    default:
+    case Page::CACHEABLE: type = T::Normal(); break;
+    case Page::BUFFERED:  type = T::Buffered(); break;
+    case Page::NONCACHEABLE: type = T::Uncached(); break;
+    }
+
+  K k(0);
+  if (!(c & 0x800))
+    k |= K::Global();
+
+  return Page::Attr(rights, type, k);
+}
+
+PUBLIC inline NEEDS[Pte_ptr::_attribs]
 void
-Pte_base::clear()
-{ _raw = 0; }
+Pte_ptr::create_page(Phys_mem_addr addr, Page::Attr attr)
+{
+  Entry p = 0x400 | _attribs(attr) | cxx::int_value<Phys_mem_addr>(addr);
+  if (level == Pdir::Depth)
+    p |= 3;
+  else
+    p |= 1;
+
+  write_now(pte, p);
+}
+
+PUBLIC inline
+bool
+Pte_ptr::add_attribs(Page::Attr attr)
+{
+  typedef L4_fpage::Rights R;
+
+  Entry n_attr = 0;
+
+  if (attr.rights & R::W())
+    n_attr = 0x80;
+
+  if (attr.rights & R::X())
+    n_attr |= 0x0040000000000000;
+
+  if (!n_attr)
+    return false;
+
+  auto p = access_once(pte);
+  if (p & n_attr)
+    {
+      p &= ~n_attr;
+      write_now(pte, p);
+      return true;
+    }
+  return false;
+}
+
+PUBLIC inline
+Page::Rights
+Pte_ptr::access_flags() const
+{ return Page::Rights(0); }
 
 PUBLIC inline
-int
-Pte_base::valid() const
+void
+Pte_ptr::del_rights(L4_fpage::Rights r)
+{
+  Entry n_attr = 0;
+  if (r & L4_fpage::Rights::W())
+    n_attr = 0x80;
+
+  if (r & L4_fpage::Rights::X())
+    n_attr |= 0x0040000000000000;
+
+  if (!n_attr)
+    return;
+
+  auto p = access_once(pte);
+  if ((p & n_attr) != n_attr)
+    {
+      p |= n_attr;
+      write_now(pte, p);
+    }
+}
+
+
+
+
+//---------------------------------------------------------------------------
+IMPLEMENTATION [arm && (armv6 || armv7) && !arm_lpae]:
+
+PUBLIC static inline
+Mword PF::is_alignment_error(Mword error)
+{ return (error & 0xf0040f) == 0x400001; }
+
+//---------------------------------------------------------------------------
+IMPLEMENTATION [arm && (armv6 || armv7) && arm_lpae]:
+
+PUBLIC static inline
+Mword PF::is_alignment_error(Mword error)
+{ return (error & 0xf0003f) == 0x400021; }
+
+//---------------------------------------------------------------------------
+IMPLEMENTATION [arm && (armv6 || armv7)]:
+
+PUBLIC inline NEEDS[Pte_ptr::_attribs, Pte_ptr::_attribs_mask]
+void
+Pte_ptr::set_attribs(Page::Attr attr)
 {
-  return _raw & Valid;
+  Entry p = access_once(pte);
+  p = (p & _attribs_mask()) | _attribs(attr);
+  write_now(pte, p);
 }
 
+
+
+//---------------------------------------------------------------------------
+IMPLEMENTATION [arm && !arm_lpae]:
+
 IMPLEMENT inline
 Mword PF::is_translation_error( Mword error )
 {
   return (error & 0x0d/*FSR_STATUS_MASK*/) == 0x05/*FSR_TRANSL*/;
 }
 
+//---------------------------------------------------------------------------
+IMPLEMENTATION [arm && arm_lpae]:
+
+IMPLEMENT inline
+Mword PF::is_translation_error(Mword error)
+{
+  return (error & 0x3c) == 0x04;
+}
+
+//---------------------------------------------------------------------------
+IMPLEMENTATION [arm]:
+
 IMPLEMENT inline
 Mword PF::is_usermode_error( Mword error )
 {
index cbb81d261fd6da5eb7c174c4fbd86fd04a8984e5..55afdef25507fa60ce80d398a0927fb8a65a2408 100644 (file)
@@ -32,10 +32,10 @@ EXTENSION class Perf_cnt
 {
 private:
   enum {
-    CPU_CONTROL = Mem_layout::Mp_scu_map_base + 0x00,
-    CONFIG      = Mem_layout::Mp_scu_map_base + 0x04,
-    CPU_STATUS  = Mem_layout::Mp_scu_map_base + 0x08,
-    MON_CONTROL = Mem_layout::Mp_scu_map_base + 0x10,
+    CPU_CONTROL = 0x00,
+    CONFIG      = 0x04,
+    CPU_STATUS  = 0x08,
+    MON_CONTROL = 0x10,
 
     MON_CONTROL_ENABLE = 1,
     MON_CONTROL_RESET  = 2,
@@ -74,10 +74,10 @@ private:
   };
 
   static Address mon_event_type_addr(int nr)
-  { return Mem_layout::Mp_scu_map_base + 0x14 + nr; }
+  { return 0x14 + nr; }
 
   static Address mon_counter(int nr)
-  { return Mem_layout::Mp_scu_map_base + 0x1c + nr * 4; }
+  { return 0x1c + nr * 4; }
 };
 
 // ------------------------------------------------------------------------
@@ -231,27 +231,29 @@ Perf_cnt::set_event_type(int, int)
 // ------------------------------------------------------------------------
 IMPLEMENTATION [arm && perf_cnt && mpcore]:
 
-#include "io.h"
+#include "cpu.h"
 
 char const *Perf_cnt::perf_type_str = "MP-C";
 
 PRIVATE static
 void
 Perf_cnt::set_event_type(int counter_nr, int event)
-{ Io::write<unsigned char>(event, mon_event_type_addr(counter_nr)); }
+{ Cpu::scu->write<unsigned char>(event, mon_event_type_addr(counter_nr)); }
 
 PUBLIC static
 unsigned long
 Perf_cnt::read_counter(int counter_nr)
-{ return Io::read<Mword>(mon_counter(counter_nr)); }
+{ return Cpu::scu->read<Mword>(mon_counter(counter_nr)); }
 
 PUBLIC static FIASCO_INIT_CPU
 void
 Perf_cnt::init_cpu()
 {
-  Io::write<Mword>(0xff << 16 // clear overflow flags
-                   | MON_CONTROL_RESET | MON_CONTROL_ENABLE,
-                   MON_CONTROL);
+  static_assert(Scu::Available, "No SCU available in this configuration");
+
+  Cpu::scu->write<Mword>(0xff << 16 // clear overflow flags
+                        | MON_CONTROL_RESET | MON_CONTROL_ENABLE,
+                        MON_CONTROL);
 
   // static config for now...
   set_event_type(7, EVENT_CYCLE_COUNT);
@@ -281,7 +283,7 @@ Perf_cnt::read_cycle_cnt()
 PUBLIC static
 unsigned
 Perf_cnt::mon_event_type(int nr)
-{ return Io::read<unsigned char>(mon_event_type_addr(nr)); }
+{ return Cpu::scu->read<unsigned char>(mon_event_type_addr(nr)); }
 
 // ------------------------------------------------------------------------
 IMPLEMENTATION [arm && perf_cnt && (armca8 || armca9)]:
@@ -454,7 +456,8 @@ Perf_cnt::init()
   Tb_entry::set_cycle_read_func(read_cycle_cnt);
 }
 
-PUBLIC static inline void
+PUBLIC static inline FIASCO_INIT_CPU
+void
 Perf_cnt::init_ap()
 {
   init_cpu();
index cf7a1bd3d85f46414d688cfff32dc48629c399ce..4dab29afd028e8a743e6ff7c7db807210ff68cca 100644 (file)
@@ -16,3 +16,12 @@ extern "C"
 void irq_handler()
 { Pic::gic->hit(0); }
 
+//-------------------------------------------------------------------
+IMPLEMENTATION [arm && pic_gic && arm_em_tz]:
+
+PUBLIC static
+void
+Pic::set_pending_irq(unsigned group32num, Unsigned32 val)
+{
+  gic->set_pending_irq(group32num, val);
+}
diff --git a/kernel/fiasco/src/kern/arm/scu.cpp b/kernel/fiasco/src/kern/arm/scu.cpp
new file mode 100644 (file)
index 0000000..24d1904
--- /dev/null
@@ -0,0 +1,88 @@
+
+INTERFACE [arm && (mpcore || armca9)]:
+
+#include <mmio_register_block.h>
+
+class Scu : public Mmio_register_block
+{
+private:
+  enum
+  {
+    Control      = 0x0,
+    Config       = 0x4,
+    Power_status = 0x8,
+    Inv          = 0xc,
+    SAC          = 0x50,
+    SNSAC        = 0x54,
+  };
+
+public:
+  enum
+  {
+    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,
+  };
+
+  void reset() const { write<Mword>(0xffffffff, Inv); }
+
+  void enable(Mword bits = 0) const
+  {
+    Unsigned32 ctrl = read<Unsigned32>(Control);
+    if (!(ctrl & Control_enable))
+      write<Unsigned32>(ctrl | bits | Control_enable, Control);
+  }
+
+  Mword config() const { return read<Mword>(Config); }
+};
+
+//-------------------------------------------------------------------------
+INTERFACE [arm && (mpcore || armca9) && !bsp_cpu]:
+
+EXTENSION class Scu
+{
+public:
+  enum
+  {
+    Bsp_enable_bits = 0,
+    Available = 1,
+  };
+};
+
+// ------------------------------------------------------------------------
+INTERFACE [arm && armca9 && arm_em_tz && mptimer]:
+
+EXTENSION class Scu
+{
+  enum : Mword { SNSAC_value = 0 };
+};
+
+// ------------------------------------------------------------------------
+INTERFACE [arm && armca9 && arm_em_tz && !mptimer]:
+
+EXTENSION class Scu
+{
+  enum : Mword { SNSAC_value = 0xfff };
+};
+
+// ------------------------------------------------------------------------
+IMPLEMENTATION [arm && (mpcore || (armca9 && !arm_em_tz))]:
+
+PUBLIC explicit
+Scu::Scu(Address base)
+: Mmio_register_block(base)
+{}
+
+// ------------------------------------------------------------------------
+IMPLEMENTATION [arm && armca9 && arm_em_tz]:
+
+PUBLIC explicit
+Scu::Scu(Address base)
+: Mmio_register_block(base)
+{
+  write<Mword>(SNSAC_value, SNSAC);
+}
index 56f772583d779c27d96e5c9990611ad57357c105..36c1f40b2fe17d816a9c96f2d5bd8a4c666cdf7e 100644 (file)
@@ -38,31 +38,30 @@ IMPLEMENT FIASCO_INIT FIASCO_NOINLINE
 void
 Startup::stage2()
 {
+  Cpu_number const boot_cpu = Cpu_number::boot_cpu();
   puts("Hello from Startup::stage2");
+  Mem_space::init_page_sizes();
 
-  // The first 4MB of phys memory are always mapped to Map_base
-  Mem_layout::add_pmem(Mem_layout::Sdram_phys_base, Mem_layout::Map_base,
-                       4 << 20);
   Kip_init::init();
   Kmem_alloc::init();
 
   // 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);
 
   Kmem_space::init();
   Kernel_task::init();
   Mem_space::kernel_space(Kernel_task::kernel_task());
   Pic::init();
-  Thread::init_per_cpu(0);
+  Thread::init_per_cpu(boot_cpu);
 
   Cpu::init_mmu();
-  Cpu::cpus.cpu(0).init(true);
-  Platform_control::init(0);
-  Fpu::init(0);
-  Ipi::init(0);
-  Timer::init(0);
+  Cpu::cpus.cpu(boot_cpu).init(true);
+  Platform_control::init(boot_cpu);
+  Fpu::init(boot_cpu);
+  Ipi::init(boot_cpu);
+  Timer::init(boot_cpu);
   Kern_lib_page::init();
   Utcb_init::init();
 }
index 814d0ea5908c342fde0d7de656c378a9b336c862..407ef8e9b042e518919c6b10014cb137ef144dd8 100644 (file)
@@ -49,8 +49,10 @@ Sys_call_page::init()
   set_utcb_get_code((Mword*)(Mem_layout::Syscalls + 0xf00));
 
   Kernel_task::kernel_task()
-      ->set_attributes(Mem_layout::Syscalls,
-                       Mem_space::Page_cacheable | Mem_space::Page_user_accessible);
+      ->set_attributes(Virt_addr(Mem_layout::Syscalls),
+                       Page::Attr(Page::Rights::URX(), Page::Type::Normal(),
+                                  Page::Kern::Global()),
+                       true, 0 /*kernel ASID*/);
 
   Mem_unit::flush_cache();
 }
index 3edea57365264bbcc8b14286c4020d93eb76f28d..74e036824b94df628c06bf980de6bde5e659f78d 100644 (file)
@@ -72,15 +72,15 @@ PUBLIC inline NEEDS ["trap_state.h"]
 void
 Tb_entry_trap::set(Mword ip, Trap_state *ts)
 {
-    _ip    = ip;
-    _error = ts->error_code;
-    _cpsr  = ts->psr;
-    _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(Mword pc, Mword )
+Tb_entry_trap::set(Mword pc, Mword)
 {
-    _ip    = pc;
+  _ip    = pc;
 }
index 8dc4cbf8556eb541fcc92da276719e48b90a27e2..e890feecbd651ff1b10faf085b8c55bb2786f724 100644 (file)
@@ -5,7 +5,7 @@ class Trap_state;
 EXTENSION class Thread
 {
 public:
-  static void init_per_cpu(unsigned cpu);
+  static void init_per_cpu(Cpu_number cpu);
 private:
   bool _in_exception;
 
@@ -80,7 +80,7 @@ Thread::fast_return_to_user(Mword ip, Mword sp, Vcpu_state *arg)
 
 IMPLEMENT_DEFAULT inline
 void
-Thread::init_per_cpu(unsigned)
+Thread::init_per_cpu(Cpu_number)
 {}
 
 
@@ -102,8 +102,9 @@ Thread::user_invoke()
   Mem::memset_mwords(&ts->r[0], 0, sizeof(ts->r) / sizeof(ts->r[0]));
 
   if (current()->space()->is_sigma0())
-    ts->r[0] = Kmem_space::kdir()->walk(Kip::k(), 0, false, Ptab::Null_alloc(),
-                                        0).phys(Kip::k());
+    ts->r[0] = Mem_space::kernel_space()->virt_to_phys((Address)Kip::k());
+
+  ts->psr |= Proc::Status_always_mask;
 
   extern char __return_from_exception;
 
@@ -130,11 +131,10 @@ IMPLEMENT inline NEEDS["space.h", <cstdio>, "types.h" ,"config.h"]
 bool Thread::handle_sigma0_page_fault( Address pfa )
 {
   return (mem_space()->v_insert(
-       Mem_space::Phys_addr::create((pfa & Config::SUPERPAGE_MASK)),
-       Mem_space::Addr::create(pfa & Config::SUPERPAGE_MASK),
-       Mem_space::Size(Config::SUPERPAGE_SIZE),
-       Mem_space::Page_writable | Mem_space::Page_user_accessible
-       | Mem_space::Page_cacheable)
+       Mem_space::Phys_addr((pfa & Config::SUPERPAGE_MASK)),
+       Virt_addr(pfa & Config::SUPERPAGE_MASK),
+       Virt_order(Config::SUPERPAGE_SHIFT) /*mem_space()->largest_page_size()*/,
+       Mem_space::Attr(L4_fpage::Rights::URWX()))
       != Mem_space::Insert_err_nomem);
 }
 
@@ -189,7 +189,8 @@ extern "C" {
     if (EXPECT_FALSE(PF::is_alignment_error(error_code)))
       {
        printf("KERNEL%d: alignment error at %08lx (PC: %08lx, SP: %08lx, FSR: %lx, PSR: %lx)\n",
-               current_cpu(), pfa, pc, ret_frame->usp, error_code, ret_frame->psr);
+               cxx::int_value<Cpu_number>(current_cpu()), pfa, pc,
+               ret_frame->usp, error_code, ret_frame->psr);
         return false;
       }
 
@@ -204,7 +205,7 @@ extern "C" {
         Proc::sti();
       }
     // or interrupts were enabled
-    else if (!(ret_frame->psr & Proc::Status_IRQ_disabled))
+    else if (!(ret_frame->psr & Proc::Status_preempt_disabled))
       Proc::sti();
 
       // Pagefault in kernel mode and interrupts were disabled
@@ -474,7 +475,7 @@ Thread::do_trigger_exception(Entry_frame *r, void *ret_handler)
 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)
+                        L4_fpage::Rights rights)
 {
   Trap_state *ts = (Trap_state*)rcv->_utcb_handler;
   Utcb *snd_utcb = snd->utcb().access();
@@ -513,10 +514,10 @@ Thread::copy_utcb_to_ts(L4_msg_tag const &tag, Thread *snd, Thread *rcv,
        }
     }
 
-  if (tag.transfer_fpu() && (rights & L4_fpage::W))
+  if (tag.transfer_fpu() && (rights & L4_fpage::Rights::W()))
     snd->transfer_fpu(rcv);
 
-  if ((tag.flags() & 0x8000) && (rights & L4_fpage::W))
+  if ((tag.flags() & 0x8000) && (rights & L4_fpage::Rights::W()))
     rcv->utcb().access()->user[2] = snd_utcb->values[25];
 
   rcv->get_ts_tpidruro(ts);
@@ -533,7 +534,7 @@ 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)
+                        L4_fpage::Rights rights)
 {
   Trap_state *ts = (Trap_state*)snd->_utcb_handler;
 
@@ -556,7 +557,7 @@ Thread::copy_ts_to_utcb(L4_msg_tag const &, Thread *snd, Thread *rcv,
         rcv_utcb->values[20] = ts->psr;
       }
 
-    if (rcv_utcb->inherit_fpu() && (rights & L4_fpage::W))
+    if (rcv_utcb->inherit_fpu() && (rights & L4_fpage::Rights::W()))
       snd->transfer_fpu(rcv);
 
     save_fpu_state_to_utcb(ts, rcv_utcb);
@@ -736,6 +737,25 @@ public:
   void switch_mode(unsigned) {}
 };
 
+class Thread_timer_tick_ipi : public Irq_base
+{
+public:
+  void handle(Upstream_irq const *ui)
+  {
+    //Timer_tick *self = nonull_static_cast<Timer_tick *>(_s);
+    //self->ack();
+    ui->ack();
+    //self->log_timer();
+    current_thread()->handle_timer_interrupt();
+  }
+
+  Thread_timer_tick_ipi()
+  { set_hit(&handler_wrapper<Thread_timer_tick_ipi>); }
+
+  void switch_mode(unsigned) {}
+};
+
+
 //-----------------------------------------------------------------------------
 IMPLEMENTATION [mp && !irregular_gic]:
 
@@ -744,14 +764,16 @@ class Arm_ipis
 public:
   Arm_ipis()
   {
-    Irq_mgr::mgr->alloc(&remote_rq_ipi, Ipi::Request);
-    Irq_mgr::mgr->alloc(&glbl_remote_rq_ipi, Ipi::Global_request);
-    Irq_mgr::mgr->alloc(&debug_ipi, Ipi::Debug);
+    check(Irq_mgr::mgr->alloc(&remote_rq_ipi, Ipi::Request));
+    check(Irq_mgr::mgr->alloc(&glbl_remote_rq_ipi, Ipi::Global_request));
+    check(Irq_mgr::mgr->alloc(&debug_ipi, Ipi::Debug));
+    check(Irq_mgr::mgr->alloc(&timer_ipi, Ipi::Timer));
   }
 
   Thread_remote_rq_irq remote_rq_ipi;
   Thread_glbl_remote_rq_irq glbl_remote_rq_ipi;
   Thread_debug_ipi debug_ipi;
+  Thread_timer_tick_ipi timer_ipi;
 };
 
 static Arm_ipis _arm_ipis;
index 32420e808d9c200776563c263ed42afba42a63cf..a9586924b1f0fc5c0d67defa6d987eac691b7a56 100644 (file)
@@ -59,12 +59,13 @@ IMPLEMENT
 int
 Thread::call_nested_trap_handler(Trap_state *ts)
 {
-  unsigned phys_cpu = Proc::cpu_id();
-  unsigned log_cpu = Cpu::cpus.find_cpu(Cpu::By_phys_id(phys_cpu));
-  if (log_cpu == ~0U)
+  Cpu_phys_id phys_cpu = Proc::cpu_id();
+  Cpu_number log_cpu = Cpu::cpus.find_cpu(Cpu::By_phys_id(phys_cpu));
+  if (log_cpu == Cpu_number::nil())
     {
-      printf("Trap on unknown CPU phys_id=%x\n", phys_cpu);
-      log_cpu = 0;
+      printf("Trap on unknown CPU phys_id=%x\n",
+             cxx::int_value<Cpu_phys_id>(phys_cpu));
+      log_cpu = Cpu_number::boot_cpu();
     }
 
   unsigned long &ntr = nested_trap_recover.cpu(log_cpu);
@@ -82,7 +83,7 @@ Thread::call_nested_trap_handler(Trap_state *ts)
   Mword dummy1, tmp, ret;
   {
     register Mword _ts asm("r0") = (Mword)ts;
-    register Mword _lcpu asm("r1") = log_cpu;
+    register Cpu_number _lcpu asm("r1") = log_cpu;
 
     asm volatile(
        "mov    %[origstack], sp         \n"
index e9cb29e4092cb0d2e28f631f329ef33f63616c2f..16dee85ec9835a2e314b39050285fd9ee0926320 100644 (file)
@@ -1,8 +1,8 @@
 // --------------------------------------------------------------------------
 INTERFACE [arm && mptimer]:
 
-#include "irq_chip.h"
 #include "kmem.h"
+#include "cpu.h"
 
 EXTENSION class Timer
 {
@@ -10,12 +10,14 @@ public:
   static unsigned irq() { return 29; }
 
 private:
+  typedef Mmio_register_block Mp_timer;
+
   enum
   {
-    Timer_load_reg     = Kmem::Mp_scu_map_base + 0x600 + 0x0,
-    Timer_counter_reg  = Kmem::Mp_scu_map_base + 0x600 + 0x4,
-    Timer_control_reg  = Kmem::Mp_scu_map_base + 0x600 + 0x8,
-    Timer_int_stat_reg = Kmem::Mp_scu_map_base + 0x600 + 0xc,
+    Timer_load_reg     = 0x600 + 0x0,
+    Timer_counter_reg  = 0x600 + 0x4,
+    Timer_control_reg  = 0x600 + 0x8,
+    Timer_int_stat_reg = 0x600 + 0xc,
 
     Prescaler = 0,
 
@@ -33,8 +35,6 @@ IMPLEMENTATION [arm && mptimer]:
 
 #include <cstdio>
 #include "config.h"
-#include "io.h"
-#include "irq_chip.h"
 #include "kip.h"
 
 #include "globals.h"
@@ -43,12 +43,14 @@ PRIVATE static
 Mword
 Timer::start_as_counter()
 {
-  Io::write<Mword>(Timer_control_prescaler | Timer_control_reload
-                   | Timer_control_enable,
-                   Timer_control_reg);
+  static_assert(Scu::Available, "No SCU available in this configuration");
+
+  Cpu::scu->write<Mword>(Timer_control_prescaler | Timer_control_reload
+                         | Timer_control_enable,
+                         Timer_control_reg);
 
   Mword v = ~0UL;
-  Io::write<Mword>(v, Timer_counter_reg);
+  Cpu::scu->write<Mword>(v, Timer_counter_reg);
   return v;
 }
 
@@ -56,22 +58,23 @@ PRIVATE static
 Mword
 Timer::stop_counter()
 {
-  Mword v = Io::read<Mword>(Timer_counter_reg);
-  Io::write<Mword>(0, Timer_control_reg);
+  Mword v = Cpu::scu->read<Mword>(Timer_counter_reg);
+  Cpu::scu->write<Mword>(0, Timer_control_reg);
   return v;
 }
 
 IMPLEMENT
 void
-Timer::init(unsigned)
+Timer::init(Cpu_number)
 {
+
   Mword i = interval();
 
-  Io::write<Mword>(i, Timer_load_reg);
-  Io::write<Mword>(i, Timer_counter_reg);
-  Io::write<Mword>(Timer_control_prescaler | Timer_control_reload
-                   | Timer_control_enable | Timer_control_itenable,
-                   Timer_control_reg);
+  Cpu::scu->write<Mword>(i, Timer_load_reg);
+  Cpu::scu->write<Mword>(i, Timer_counter_reg);
+  Cpu::scu->write<Mword>(Timer_control_prescaler | Timer_control_reload
+                         | Timer_control_enable | Timer_control_itenable,
+                         Timer_control_reg);
 }
 
 static inline
@@ -84,11 +87,11 @@ Unsigned64
 Timer::us_to_timer(Unsigned64 us)
 { (void)us; return 0; }
 
-PUBLIC static inline NEEDS["io.h"]
+PUBLIC static inline
 void
 Timer::acknowledge()
 {
-  Io::write<Mword>(Timer_int_stat_event, Timer_int_stat_reg);
+  Cpu::scu->write<Mword>(Timer_int_stat_event, Timer_int_stat_reg);
 }
 
 IMPLEMENT inline
index 9a03120d61b705ba4809b35bb08128b980d60c5a..356e570b907e82d1957e1de52ffb3e88cb12cc66 100644 (file)
@@ -46,9 +46,9 @@ Timer::init_system_clock()
 
 IMPLEMENT inline NEEDS["config.h", "globals.h", "kip.h", "watchdog.h", Timer::kipclock_cache]
 void
-Timer::update_system_clock(unsigned cpu)
+Timer::update_system_clock(Cpu_number cpu)
 {
-  if (cpu == 0)
+  if (cpu == Cpu_number::boot_cpu())
     {
       Kip::k()->clock += Config::Scheduler_granularity;
       kipclock_cache();
diff --git a/kernel/fiasco/src/kern/arm/timer_sp804.cpp b/kernel/fiasco/src/kern/arm/timer_sp804.cpp
new file mode 100644 (file)
index 0000000..0f34862
--- /dev/null
@@ -0,0 +1,36 @@
+// --------------------------------------------------------------------------
+INTERFACE [arm]:
+
+#include "kmem.h"
+#include "mmio_register_block.h"
+
+class Timer_sp804 : private Mmio_register_block
+{
+public:
+  enum {
+    Refclk = 0,
+    Timclk = 1,
+
+    Load   = 0x00,
+    Value  = 0x04,
+    Ctrl   = 0x08,
+    Intclr = 0x0c,
+
+    Interval = 1000,
+
+    Ctrl_ie        = 1 << 5,
+    Ctrl_periodic  = 1 << 6,
+    Ctrl_enable    = 1 << 7,
+  };
+
+  Timer_sp804(Address virt) : Mmio_register_block(virt) {}
+  void disable() const { write<Mword>(0, Ctrl); }
+  void enable(Mword flags) const
+  { write<Mword>(Ctrl_enable | flags, Ctrl); }
+  void reload_value(Mword v) const { write(v, Load); }
+  void counter_value(Mword v) const { write(v, Value); }
+  Mword counter() const { return read<Mword>(Value); }
+  void irq_clear() const { write<Mword>(0, Intclr); }
+};
+
+
index 736cb2d5d80270f5fedcc88e84c887e2dc99e38f..e4cb4bc0a5cbd099f4c0b2d3f8814675af7a99ed 100644 (file)
@@ -5,34 +5,49 @@
        .p2align 12
 
 #ifdef CONFIG_ARM_V7
-/* See cache_func_gen.cpp */
-       .global v7_invalidate_l1
 invalidate_l1_v7:
-       mov     r3, #0
-       mcr     p15, 2, r3, c0, c0, 0
-       mrc     p15, 1, r2, c0, c0, 0
-       mov     r3, r2, lsr #3
-       mov     r0, r2, lsr #13
-       mov     r3, r3, asl #22
-       mov     r3, r3, lsr #22
-       and     r2, r2, #7
-       mov     r0, r0, asl #17
-       add     ip, r2, #4
-       mov     r0, r0, lsr #17
-       mov     r2, r3
-       clz     r3, r3
-.L3:
-       mov     r4, r2, asl r3
-       mov     r1, r0
-.L2:
-       orr     r5, r4, r1, asl ip
-       mcr     p15, 0, r5, c7, c6, 2
-       subs    r1, r1, #1
-       bcs     .L2
-       subs    r2, r2, #1
-       bcs     .L3
+       // B2.2.7
+       mrc     p15, 1, r0, c0, c0, 1
+       ands    r3, r0, #0x07000000
+       mov     r3, r3, lsr #23
+       beq     finished
+       mov     r10, #0
+loop1:
+       add     r2, r10, r10, lsr #1
+       mov     r1, r0, lsr r2
+       and     r1, r1, #7
+       cmp     r1, #2
+       blt     skip
+       mcr     p15, 2, r10, c0, c0, 0
        isb
+       mrc     p15, 1, r1, c0, c0, 0
+       and     r2, r1, #7
+       add     r2, r2, #4
+       movw    r4, #0x3ff
+       ands    r4, r4, r1, lsr #3
+       clz     r5, r4
+       mov     r9, r4
+loop2:
+       movw    r7, #0x7fff
+       ands    r7, r7, r1, lsr #13
+loop3:
+       orr     r11, r10, r9, lsl r5
+       orr     r11, r11, r7, lsl r2
+       mcr     p15, 0, r11, c7, c6, 2
+       subs    r7, r7, #1
+       bge     loop3
+       subs    r9, r9, #1
+       bge     loop2
+skip:
+       add     r10, r10, #2
+       cmp     r3, r10
+       bgt     loop1
        dsb
+finished:
+       mov     r0, #0
+       mcr     p15, 2, r0, c0, c0, 0
+       dsb
+       isb
        mov     pc, lr
 #endif
 
@@ -44,11 +59,13 @@ _tramp_mp_entry:
        msr   cpsr_c, r0
 
        // enable SMP
+#ifndef CONFIG_ARM_EM_NS
        adr   r0, .Lmpcore_phys_base
        ldr   r0, [r0]
        ldr   r1, [r0]
        orr   r1, #1
        str   r1, [r0]
+#endif
 
 #ifdef CONFIG_ARM_V7
        bl    invalidate_l1_v7
@@ -65,39 +82,60 @@ _tramp_mp_entry:
 #ifdef CONFIG_ARM_V7
        // ACTRL is implementation defined
        mrc   p15, 0, r0, c0, c0, 0  // read MIDR
-       adr   r3, .Lactrl_cpuid_a9   // load addr
-       ldm   r3, {r1,r2}            // load mask + val
-       and   r0, r1                 // apply mask
-       teq   r0, r2                 // check value
+       adr   r3, .Lactrl_cpuid      // load addr
+       ldm   r3, {r1, r2}           // load mask + val
+       and   r3, r0, r1             // apply mask
+       teq   r3, r2                 // check value
        bne   2f                     // only do mcr on this CPU
 #endif
 
-       mrc   p15, 0, r0, c1, c0, 1
+       mrc   p15, 0, r1, c1, c0, 1
 #ifdef CONFIG_ARM_V7
-        tst   r0, #0x40
-        bne   2f
-       orr   r0, r0, #0x41
+       tst   r1, #0x40
+       bne   2f
+       lsr   r0, r0, #8
+       and   r0, r0, #7
+       cmp   r0, #7
+       orrne r1, r1, #0x41
+       orreq r1, r1, #0x40
 #else
-       orr   r0, r0, #0x20
+       orr   r1, r1, #0x20
 #endif
-       mcr   p15, 0, r0, c1, c0, 1
+       mcr   p15, 0, r1, c1, c0, 1
 
 2:
 
        // TLB flush
        mcr p15, 0, r0, c8, c7, 0
 
-       adr r0, _tramp_mp_start_dcr
+       adr r0, _tramp_mp_startup_dcr
        ldr r0, [r0]
        mcr p15, 0, r0, c3, c0
 
+       // reset ASID and PROCID
+       mov r0, #0
+       mcr p15, 0, r0, c13, c0, 1
+
        // init TTBCR
+       adr r0, _tramp_mp_startup_ttbcr
+       ldr r1, [r0]
+       mcr p15, 0, r1, c2, c0, 2
+
+#ifdef CONFIG_ARM_LPAE
+       adr r0, _tramp_mp_startup_mair0
+       ldr r0, [r0]
+       mcr p15, 0, r0, c10, c2, 0  // MAIR0
+#endif
+
        mov r0, #0
-       mcr p15, 0, r0, c2, c0, 2
+       mcr p15, 0, r0, c8, c7, 0
 
        adr r0, _tramp_mp_startup_pdbr
        ldr r0, [r0]
-       mcr p15, 0, r0, c2, c0
+       tst r1, #(1 << 31)
+       movne  r1, #0
+       mcrrne p15, 0, r0, r1, c2
+       mcreq  p15, 0, r0, c2, c0
 
        adr r0, _tramp_mp_startup_cp15_c1
        ldr r0, [r0]
@@ -114,10 +152,9 @@ _tramp_mp_entry:
 .Lmpcore_phys_base:
        .long MPCORE_PHYS_BASE
 
-// only one currently
-.Lactrl_cpuid_a9:
-         .long 0xff0ffff0
-         .long 0x410fc090
+.Lactrl_cpuid:
+       .long 0xff0fff00
+       .long 0x410fc000
 
        // we run paged now
 _tramp_mp_virt:
@@ -141,27 +178,21 @@ _tramp_mp_virt:
 
        adr     sp, _tramp_mp_init_stack_top
        nop
-       nop
-       nop
        ldr     pc, [pc, #-4]
 
        .long BOOT_AP_CPU
 
-.global _tramp_mp_startup_cp15_c1
-_tramp_mp_startup_cp15_c1:
-       .long 0x00000000
-
-.global _tramp_mp_startup_pdbr
-_tramp_mp_startup_pdbr:
-       .long 0x00000000
-
-.global _tramp_mp_start_dcr
-_tramp_mp_start_dcr:
-       .long 0x00000000
-
-.global _tramp_mp_spinlock
-_tramp_mp_spinlock:
-       .long 0
+.macro defvar name
+.global \name
+\name: .long 0
+.endm
+
+defvar _tramp_mp_startup_cp15_c1
+defvar _tramp_mp_startup_pdbr
+defvar _tramp_mp_startup_dcr
+defvar _tramp_mp_startup_ttbcr
+defvar _tramp_mp_startup_mair0
+defvar _tramp_mp_spinlock
 
 _tramp_mp_init_stack:
        .space 1024
index 42dfd0a1004410134dee93f86e9c8a7c3ef5e668..25d351594ee09b0534c56618ae2796043bf2364d 100644 (file)
@@ -34,7 +34,7 @@ void
 Trap_state::sanitize_user_state()
 {
   psr &= ~(Proc::Status_mode_mask | Proc::Status_interrupts_mask);
-  psr |= Proc::Status_mode_user;
+  psr |= Proc::Status_mode_user | Proc::Status_always_mask;
 }
 
 PUBLIC inline
index 686343d313e3deb6386d5798d9b7b986b70e5ff5..d387dccd333cb134a7bbc30145279b29f69862fb 100644 (file)
@@ -1,81 +1,84 @@
-INTERFACE:
+INTERFACE [arm_em_tz]:
 
-#include "mapping_tree.h"
-#include "kobject.h"
 #include "kmem_slab.h"
-#include "l4_types.h"
-#include "prio_list.h"
-#include "slab_cache.h"
-#include "ref_obj.h"
+#include "task.h"
 
-class Ram_quota;
-
-class Vm : public Kobject, public Ref_cnt_obj
+class Vm : public Task
 {
-  FIASCO_DECLARE_KOBJ();
+public:
+  explicit Vm(Ram_quota *q) : Task(q, Caps::mem() | Caps::obj()) {}
 
-  struct machine_state
-    {
-      Mword r[13];
-
-      Mword sp_usr;
-      Mword lr_usr;
-
-      Mword sp_irq;
-      Mword lr_irq;
-      Mword spsr_irq;
-
-      Mword r_fiq[5]; // r8 - r12
-      Mword sp_fiq;
-      Mword lr_fiq;
-      Mword spsr_fiq;
-
-      Mword sp_abt;
-      Mword lr_abt;
-      Mword spsr_abt;
-
-      Mword sp_und;
-      Mword lr_und;
-      Mword spsr_und;
-
-      Mword sp_svc;
-      Mword lr_svc;
-      Mword spsr_svc;
-      
-      Mword pc;
-      Mword cpsr;
-
-      Mword pending_events;
-      
-      Mword cp15_ttbr0;
-      Mword cp15_ttbr1;
-      Mword cp15_ttbcr;
-      Mword cp15_vector_base;
-      Mword cp15_dfsr;
-      Mword cp15_dfar;
-      Mword cp15_ifsr;
-      Mword cp15_ifar;
-      Mword cp15_control;
-      Mword cp15_prim_region_remap;
-      Mword cp15_norm_region_remap;
-      Mword cp15_cid;
-      Mword cp15_tls[3];
-      Mword cp10_fpexc;
-
-      Mword pfs;
-      Mword pfa;
-      Mword exit_reason;
-    };
+  struct Vm_state_mode
+  {
+    Mword sp;
+    Mword lr;
+    Mword spsr;
+  };
+
+  enum
+  {
+    Max_num_inject_irqs = 32 * 8,
+    Nr_irq_fields = (Max_num_inject_irqs + (sizeof(Unsigned32) * 8 - 1))
+                    / (sizeof(Unsigned32) * 8),
+  };
+
+  struct Vm_state_irq_inject
+  {
+    Unsigned32 group;
+    Unsigned32 irqs[Nr_irq_fields];
+  };
+
+  struct Vm_state
+  {
+    Mword r[13];
+
+    Mword sp_usr;
+    Mword lr_usr;
+
+    Vm_state_mode irq;
+    Mword r_fiq[5]; // r8 - r12
+    Vm_state_mode fiq;
+    Vm_state_mode abt;
+    Vm_state_mode und;
+    Vm_state_mode svc;
+
+    Mword pc;
+    Mword cpsr;
+
+    Mword pending_events;
+    Unsigned32 cpacr;
+    Mword cp10_fpexc;
+
+    Mword pfs;
+    Mword pfa;
+    Mword exit_reason;
+
+    Vm_state_irq_inject irq_inject;
+  };
 
 private:
-  typedef Slab_cache Allocator;
+  Vm_state *state_for_dbg;
+
+  enum Exit_reasons
+  {
+    ER_none       = 0,
+    ER_vmm_call   = 1,
+    ER_inst_abort = 2,
+    ER_data_abort = 3,
+    ER_irq        = 4,
+    ER_fiq        = 5,
+    ER_undef      = 6,
+  };
 
-  Mword *_state;
-  Space *_space; // space the state is contained in
+};
+
+struct Vm_allocator
+{
+  static Kmem_slab_t<Vm> a;
 };
 
 //-----------------------------------------------------------------------------
-INTERFACE [debug]:
+INTERFACE [debug && arm_em_tz]:
 
 #include "tb_entry.h"
 
@@ -92,14 +95,11 @@ public:
     Mword r0;
     Mword r1;
     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;
  };
 };
 
 //-----------------------------------------------------------------------------
-
-IMPLEMENTATION:
+IMPLEMENTATION [arm]:
 
 #include "cpu.h"
 #include "cpu_lock.h"
@@ -109,136 +109,128 @@ IMPLEMENTATION:
 #include "mem_space.h"
 #include "thread_state.h"
 #include "timer.h"
-#include "ref_ptr.h"
 
-FIASCO_DEFINE_KOBJ(Vm);
+Kmem_slab_t<Vm> Vm_allocator::a("Vm");
 
-PUBLIC
-static
-Vm *
-Vm::create(Ram_quota *quota)
-{
-  if (void *a = allocator()->q_alloc(quota))
-    {
-      Vm *vm = new (a) Vm;
-      return vm;
-    }
-
-  return 0;
-}
+PUBLIC inline virtual
+Page_number
+Vm::map_max_address() const
+{ return Page_number(1UL << (MWORD_BITS - Mem_space::Page_shift)); }
 
-PUBLIC
-Vm::Vm() : _state(0), _space(0)
-{ inc_ref(); }
+PUBLIC static
+Slab_cache *
+Vm::allocator()
+{ return &Vm_allocator::a; }
 
-PUBLIC virtual
-bool
-Vm::put()
-{ return dec_ref() == 0; }
+PUBLIC inline
+void *
+Vm::operator new(size_t size, void *p) throw()
+{
+  (void)size;
+  assert (size == sizeof(Vm));
+  return p;
+}
 
 PUBLIC
-inline
-Vm::machine_state *
-Vm::state()
-{ return reinterpret_cast<machine_state *>(_state); };
+void
+Vm::operator delete(void *ptr)
+{
+  Vm *t = reinterpret_cast<Vm*>(ptr);
+  allocator()->q_free(t->ram_quota(), ptr);
+}
 
 // ------------------------------------------------------------------------
-IMPLEMENTATION [arm && tz]:
+IMPLEMENTATION [arm && arm_em_tz]:
 
+#include "pic.h"
 #include "thread.h"
 
-void
-Vm::run(Syscall_frame *f, Utcb *utcb)
+PUBLIC
+int
+Vm::resume_vcpu(Context *ctxt, Vcpu_state *vcpu, bool user_mode)
 {
-  assert(cpu_lock.test());
-  Ref_ptr<Vm> ref_ptr(this);
+  (void)user_mode;
+  assert_kdb(user_mode);
 
-  L4_msg_tag const &tag = f->tag();
+  assert(cpu_lock.test());
 
-  if (tag.words() != 3)
+  if (EXPECT_FALSE(!(ctxt->state(true) & Thread_ext_vcpu_enabled)))
     {
-      WARN("tz: Invalid message length\n");
-      f->tag(commit_result(-L4_err::EInval));
-      return;
+      ctxt->arch_load_vcpu_kern_state(vcpu, true);
+      return -L4_err::EInval;
     }
 
-  // FIXME: use a send item (fpage) for vm_state. this implementation is wrong!
-  L4_fpage state_fpage(utcb->values[1]);
-
-  if (!state_fpage.is_mempage()
-      || state_fpage.order() != 12)
-    {
-      WARN("tz: Fpage invalid\n");
-      f->tag(commit_result(-L4_err::EInval));
-      return;
-    }
+  Vm_state *state = reinterpret_cast<Vm_state *>(reinterpret_cast<char *>(vcpu) + 0x400);
 
-  _state = (Mword *)(Virt_addr(state_fpage.mem_address()).value());
+  state_for_dbg = state;
 
+  if (state->irq_inject.group)
     {
-      bool resident;
-      Mem_space::Phys_addr phys;
-      Mem_space::Size size;
-      unsigned int attribs;
-
-      _space = current()->space();
-      assert_opt (_space);
-      Mem_space *const curr_mem_space = _space;
-      resident = curr_mem_space->v_lookup(Virt_addr(_state), &phys, &size, &attribs);
-
-      if (!resident)
-       {
-         WARN("tz: Vm_state not mapped\n");
-         f->tag(commit_result(-L4_err::EInval));
-         return;
-       }
+      Unsigned32 g = state->irq_inject.group;
+      for (unsigned i = 1; i < Nr_irq_fields; ++i)
+        if ((1 << i) & g)
+          {
+            Pic::set_pending_irq(i, state->irq_inject.irqs[i]);
+            state->irq_inject.irqs[i] = 0;
+          }
+
+      state->irq_inject.group = 0;
     }
 
-  // set the temporary label for this VM
-  Mword label = f->from_spec();
-
+  int err = 0;
   while (true)
     {
-      Proc::preemption_point();
-
-      if (current_thread()->sender_list()->first())
-       {
-         current_thread()->do_ipc(L4_msg_tag(), 0, 0, true, 0,
-             L4_timeout_pair(L4_timeout::Zero, L4_timeout::Zero), f, 7);
-         if (EXPECT_TRUE(!f->tag().has_error()))
-           return;
-         WARN("tz: Receive event failed\n");
-       }
+      if (   !(vcpu->_saved_state & Vcpu_state::F_irqs)
+          && (vcpu->sticky_flags & Vcpu_state::Sf_irq_pending))
+        {
+          state->exit_reason = ER_irq;
+          err = 1;
+          break;
+        }
 
-      log_vm(this, 1);
+      log_vm(state, 1);
 
       if (!get_fpu())
-       {
-         f->tag(commit_result(-L4_err::EInval));
-         return;
-       }
+        {
+          err = -L4_err::EInval;
+          break;
+        }
 
-      Cpu::cpus.cpu(current()->cpu()).tz_switch_to_ns(_state);
+      Cpu::cpus.current().tz_switch_to_ns((Mword *)state);
 
       assert(cpu_lock.test());
 
-      log_vm(this, 0);
+      log_vm(state, 0);
+
+      if (state->exit_reason == ER_irq || state->exit_reason == ER_fiq)
+        Proc::preemption_point();
+
+      if (   state->exit_reason == ER_vmm_call
+          || state->exit_reason == ER_inst_abort
+          || state->exit_reason == ER_data_abort)
+        break;
 
-      if ((state()->exit_reason != 1) || 
-        ((state()->exit_reason == 1) &&
-         ((state()->r[0] & 0xffff0000) == 0xffff0000)))
-       continue;
-      else
-       break;
+      if (state->exit_reason == ER_undef)
+        {
+          printf("should not happen: %lx\n", state->pc);
+          break;
+        }
+
+      Thread *t = nonull_static_cast<Thread*>(ctxt);
+      if (t->continuation_test_and_restore())
+        {
+          ctxt->arch_load_vcpu_kern_state(vcpu, true);
+          t->fast_return_to_user(vcpu->_entry_ip, vcpu->_entry_sp,
+                                 t->vcpu_state().usr().get());
+        }
     }
 
-  // set label as return value for this vm
-  f->from(label);
-  f->tag(L4_msg_tag(L4_msg_tag::Label_task, 0, 0, 0));
-  return;
+  ctxt->arch_load_vcpu_kern_state(vcpu, true);
+  return err;
 }
 
-IMPLEMENTATION [arm && tz && fpu]:
+// --------------------------------------------------------------------------
+IMPLEMENTATION [arm && arm_em_tz && fpu]:
 
 PUBLIC
 bool
@@ -256,64 +248,15 @@ Vm::get_fpu()
 }
 
 // --------------------------------------------------------------------------
-IMPLEMENTATION [arm && tz && !fpu]:
+IMPLEMENTATION [arm && arm_em_tz && !fpu]:
 
 PUBLIC
 bool
 Vm::get_fpu()
 { return true; }
 
-IMPLEMENTATION [arm && !tz]:
-
-PUBLIC
-L4_msg_tag
-Vm::run(Utcb *u)
-{
-  return L4_msg_tag(0, 0, 0, 0);
-}
-
-// --------------------------------------------------------------------------
-IMPLEMENTATION:
-
-PUBLIC
-void *
-Vm::operator new (size_t, void *p) throw()
-{ return p; }
-
-PUBLIC
-void
-Vm::operator delete (void *_l)
-{
-  Vm *l = reinterpret_cast<Vm*>(_l);
-  allocator()->free(l);
-}
-
-static Kmem_slab_t<Vm> _vm_allocator("Vm");
-
-PRIVATE static
-Vm::Allocator *
-Vm::allocator()
-{ return &_vm_allocator; }
-
-PUBLIC
-void
-Vm::invoke(L4_obj_ref, Mword, Syscall_frame *f, Utcb *u)
-{
-  switch (f->tag().proto())
-    {
-    case 0:
-    case L4_msg_tag::Label_task:
-      run(nonull_static_cast<Syscall_frame*>(f), u);
-      return;
-    default:
-      break;
-    }
-
-  f->tag(L4_msg_tag(0,0,0,-L4_err::EInval));
-}
-
 // --------------------------------------------------------------------------
-IMPLEMENTATION [debug]:
+IMPLEMENTATION [debug && arm_em_tz]:
 
 #include "jdb.h"
 
@@ -322,119 +265,77 @@ Mword
 Vm::jdb_get(Mword *state_ptr)
 {
   Mword v = ~0UL;
-  Jdb::peek(state_ptr, _space, v);
+  Jdb::peek(state_ptr, this, v);
   return v;
 }
 
 PUBLIC
 void
-Vm::dump_machine_state()
+Vm::dump_vm_state()
 {
-  machine_state *s = reinterpret_cast<machine_state*>(_state);
+  Vm_state *s = state_for_dbg;
   printf("pc: %08lx  cpsr: %08lx exit_reason:%ld \n",
-      jdb_get(&s->pc), jdb_get(&s->cpsr), jdb_get(&s->exit_reason));
+         jdb_get(&s->pc), jdb_get(&s->cpsr), jdb_get(&s->exit_reason));
   printf("r0: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
-      jdb_get(&s->r[0]), jdb_get(&s->r[1]), jdb_get(&s->r[2]), jdb_get(&s->r[3]),
-      jdb_get(&s->r[4]), jdb_get(&s->r[5]), jdb_get(&s->r[6]), jdb_get(&s->r[7]));
+         jdb_get(&s->r[0]), jdb_get(&s->r[1]), jdb_get(&s->r[2]), jdb_get(&s->r[3]),
+         jdb_get(&s->r[4]), jdb_get(&s->r[5]), jdb_get(&s->r[6]), jdb_get(&s->r[7]));
   printf("r8: %08lx %08lx %08lx %08lx %08lx\n",
-      jdb_get(&s->r[8]), jdb_get(&s->r[9]), jdb_get(&s->r[10]), jdb_get(&s->r[11]),
-      jdb_get(&s->r[12]));
+         jdb_get(&s->r[8]), jdb_get(&s->r[9]), jdb_get(&s->r[10]), jdb_get(&s->r[11]),
+         jdb_get(&s->r[12]));
 
   printf("usr: sp %08lx lr %08lx\n",
-      jdb_get(&s->sp_usr), jdb_get(&s->lr_usr));
+         jdb_get(&s->sp_usr), jdb_get(&s->lr_usr));
   printf("irq: sp %08lx lr %08lx psr %08lx\n",
-      jdb_get(&s->sp_irq), jdb_get(&s->lr_irq), jdb_get(&s->spsr_irq));
+         jdb_get(&s->irq.sp), jdb_get(&s->irq.lr), jdb_get(&s->irq.spsr));
   printf("fiq: sp %08lx lr %08lx psr %08lx\n",
-      jdb_get(&s->sp_fiq), jdb_get(&s->lr_fiq), jdb_get(&s->spsr_fiq));
+         jdb_get(&s->fiq.sp), jdb_get(&s->fiq.lr), jdb_get(&s->fiq.spsr));
   printf("r8: %08lx %08lx %08lx %08lx %08lx\n",
-      jdb_get(&s->r_fiq[0]), jdb_get(&s->r_fiq[1]), jdb_get(&s->r_fiq[2]),
-      jdb_get(&s->r_fiq[3]), jdb_get(&s->r_fiq[4]));
+         jdb_get(&s->r_fiq[0]), jdb_get(&s->r_fiq[1]), jdb_get(&s->r_fiq[2]),
+         jdb_get(&s->r_fiq[3]), jdb_get(&s->r_fiq[4]));
 
   printf("abt: sp %08lx lr %08lx psr %08lx\n",
-      jdb_get(&s->sp_abt), jdb_get(&s->lr_abt), jdb_get(&s->spsr_abt));
+         jdb_get(&s->abt.sp), jdb_get(&s->abt.lr), jdb_get(&s->abt.spsr));
   printf("und: sp %08lx lr %08lx psr %08lx\n",
-      jdb_get(&s->sp_und), jdb_get(&s->lr_und), jdb_get(&s->spsr_und));
+         jdb_get(&s->und.sp), jdb_get(&s->und.lr), jdb_get(&s->und.spsr));
   printf("svc: sp %08lx lr %08lx psr %08lx\n",
-      jdb_get(&s->sp_svc), jdb_get(&s->lr_svc), jdb_get(&s->spsr_svc));
-  printf("cp15_sctlr:%08lx\n", jdb_get(&s->cp15_control));
-  printf("cp15_ttbr0:%08lx\n", jdb_get(&s->cp15_ttbr0));
-  printf("cp15_ttbr1:%08lx\n", jdb_get(&s->cp15_ttbr1));
-  printf("cp15_ttbcr:%08lx\n", jdb_get(&s->cp15_ttbcr));
-  printf("dfar: %08lx dfsr: %08lx ifar: %08lx ifsr: %08lx\n",
-      jdb_get(&s->cp15_dfar), jdb_get(&s->cp15_dfsr), jdb_get(&s->cp15_ifar),
-      jdb_get(&s->cp15_ifsr));
+         jdb_get(&s->svc.sp), jdb_get(&s->svc.lr), jdb_get(&s->svc.spsr));
 }
 
 PUBLIC
 int
 Vm::show_short(char *buf, int max)
 {
-  return snprintf(buf, max, " utcb:%lx pc:%lx ", (Mword)_state, (Mword)jdb_get(&state()->pc));
+  return snprintf(buf, max, " utcb:%lx pc:%lx ", (Mword)state_for_dbg, (Mword)jdb_get(&state_for_dbg->pc));
 }
 
 IMPLEMENT
 unsigned
 Vm::Vm_log::print(int maxlen, char *buf) const
 {
-  if (is_entry)
-    return vm_entry_log_fmt(maxlen, buf);
-  else
-    return vm_exit_log_fmt(maxlen, buf);
-}
-
-IMPLEMENT
-unsigned
-Vm::Vm_log::vm_entry_log_fmt(int maxlen, char *buf) const
-{
-  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", pc, pending_events, r0);
-}
-
-IMPLEMENT
-unsigned
-Vm::Vm_log::vm_exit_log_fmt(int maxlen, char *buf) const
-{
-  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", pc, pending_events, r0);
+  return snprintf(buf, maxlen, "%s: pc:%08lx/%03lx psr:%lx er:%lx r0:%lx r1:%lx",
+                               is_entry ? "entry" : "exit ",
+                               pc, pending_events, cpsr, exit_reason, r0, r1);
 }
 
 PUBLIC static inline
 void
-Vm::log_vm(Vm *vm, bool is_entry)
+Vm::log_vm(Vm_state *state, bool is_entry)
 {
-  if (vm->state()->exit_reason != 1)
-      return;
-  if ((vm->state()->r[0] & 0xf000) == 0x7000)
-    return;
-  if ((is_entry && (vm->state()->r[0] & 0xffff0000) == 0xffff0000))
-    return;
   LOG_TRACE("VM entry/entry", "VM", current(), Vm_log,
       l->is_entry = is_entry;
-      l->pc = vm->state()->pc;
-      l->cpsr = vm->state()->cpsr;
-      l->exit_reason = vm->state()->exit_reason;
-      l->pending_events = vm->state()->pending_events;
-      l->r0 = vm->state()->r[0];
-      l->r1 = vm->state()->r[1];
+      l->pc = state->pc;
+      l->cpsr = state->cpsr;
+      l->exit_reason = state->exit_reason;
+      l->pending_events = state->pending_events;
+      l->r0 = state->r[0];
+      l->r1 = state->r[1];
   );
 }
 
 // --------------------------------------------------------------------------
-IMPLEMENTATION [!debug]:
+IMPLEMENTATION [!debug && arm_em_tz]:
 
 PUBLIC static inline
 void
-Vm::log_vm(Vm *, bool)
+Vm::log_vm(Vm_state *, bool)
 {}
diff --git a/kernel/fiasco/src/kern/arm/vm_factory-arm.cpp b/kernel/fiasco/src/kern/arm/vm_factory-arm.cpp
new file mode 100644 (file)
index 0000000..409ef7c
--- /dev/null
@@ -0,0 +1,21 @@
+IMPLEMENTATION [arm && arm_em_tz]:
+
+#include "ram_quota.h"
+#include "vm.h"
+
+IMPLEMENT
+Vm *
+Vm_factory::create(Ram_quota *quota, int *err)
+{
+  if (void *t = Vm::allocator()->q_alloc(quota))
+    {
+      Vm *a = new (t) Vm(quota);
+      if (a->initialize())
+        return a;
+
+      delete a;
+    }
+
+  *err = -L4_err::ENomem;
+  return 0;
+}
index 4f0c01fa507873cceabf0fe02136ad4619267376..8daa490d3f00df0725dc4ff899f11a66945ee516 100644 (file)
@@ -2,7 +2,7 @@
 IMPLEMENTATION [arm]:
 
 #include "mem.h"
-#include "pagetable.h"
+#include "paging.h"
 #include "mem_space.h"
 #include "kmem_alloc.h"
 #include "config.h"
@@ -30,18 +30,15 @@ void *Vmem_alloc::page_alloc(void *address, Zero_fill zf, unsigned mode)
   Mem_unit::inv_dcache(vpage, ((char*)vpage) + Config::PAGE_SIZE);
 
   // insert page into master page table
-  Pte pte = Mem_space::kernel_space()->dir()->walk(address, Config::PAGE_SIZE, true,
-                                                   Kmem_alloc::q_allocator(Ram_quota::root),
-                                                   Mem_space::kernel_space()->dir());
+  auto pte = Mem_space::kernel_space()->dir()->walk(Virt_addr(address),
+      Pdir::Depth, true, Kmem_alloc::q_allocator(Ram_quota::root));
 
-  unsigned long pa = Page::CACHEABLE;
+  Page::Rights r = Page::Rights::RWX();
   if (mode & User)
-    pa |= Page::USER_RW;
-  else
-    pa |= Page::KERN_RW;
-
-  pte.set(page, Config::PAGE_SIZE, Mem_page_attr(pa), true);
+    r |= Page::Rights::U();
 
+  pte.create_page(Phys_mem_addr(page), Page::Attr(r, Page::Type::Normal(), Page::Kern::Global()));
+  pte.write_back_if(true);
   Mem_unit::dtlb_flush(address);
 
   if (zf == ZERO_FILL)
index 284ff54e6e72f391980c9a6de9e01de340484e49..be23d89dc238f10e1efecf805b87e8603e8fc418 100644 (file)
@@ -1,8 +1,8 @@
 INTERFACE:
 
 #include <cstddef>
-#include <slist>
-#include <type_traits>
+#include <cxx/slist>
+#include <cxx/type_traits>
 
 class Boot_alloced
 {
index 803eb72f6ede09f220a428168b247e2480c879ac..650cf59f6e0aa0347a15e7dd8a46ceb530457edf 100644 (file)
@@ -1,7 +1,7 @@
 INTERFACE:
 
 #include <cassert>
-#include <hlist>
+#include <cxx/hlist>
 #include "bitmap.h"
 #include "config.h"
 
@@ -145,16 +145,16 @@ Buddy_t_base<A,B,M>::add_mem(void *b, unsigned long size)
 {
   unsigned long start = (unsigned long)b;
   unsigned long al_start;
-  al_start = (start + Min_size - 1) & ~(Min_size -1);
+  al_start = (start + Min_size - 1) & ~(Min_size - 1);
 
   //printf("Buddy::add_mem(%p, %lx): al_start=%lx; _base=%lx\n", b, size, al_start, _base);
 
   // _debug = 0;
-  if (size <= al_start-start)
+  if (size <= al_start - start)
     return;
 
-  size -= (al_start-start);
-  size &= ~(Min_size -1);
+  size -= al_start - start;
+  size &= ~(Min_size - 1);
 
   while (size)
     {
index 64e3ef3f8277e58b16d737fe88b888c7b699c7f7..28c5389f5d6350085484c0ff171f526ab0b6900d 100644 (file)
@@ -11,7 +11,7 @@ class Clock : public Clock_base
 public:
   typedef Unsigned64 Time;
 
-  Clock(unsigned cpu);
+  Clock(Cpu_number cpu);
 
   Time delta();
 
@@ -19,7 +19,7 @@ public:
 
 
 private:
-  unsigned _cpu_id;
+  Cpu_number _cpu_id;
   Counter _last_value;
 
   Counter read_counter() const;
@@ -28,7 +28,7 @@ private:
 IMPLEMENTATION:
 
 IMPLEMENT inline
-Clock::Clock(unsigned cpu)
+Clock::Clock(Cpu_number cpu)
   : _cpu_id(cpu), _last_value(read_counter())
 {}
 
index 15d125c5732c6289b10a1293f36b3b90c733ab8f..47e36bc94962767a395f3a1b09b2dbe96c8d8de4 100644 (file)
@@ -111,6 +111,8 @@ public:
 #endif
   };
 
+  static Cpu_number max_num_cpus() { return Cpu_number(Max_num_cpus); }
+
   static bool getchar_does_hlt_works_ok;
   static bool esc_hack;
   static unsigned tbuf_entries;
@@ -195,6 +197,17 @@ public:
   static const int serial_esc = 0;
 };
 
+
+//---------------------------------------------------------------------------
+INTERFACE [!virtual_space_iface]:
+
+#define FIASCO_SPACE_VIRTUAL
+
+//---------------------------------------------------------------------------
+INTERFACE [virtual_space_iface]:
+
+#define FIASCO_SPACE_VIRTUAL virtual
+
 //---------------------------------------------------------------------------
 IMPLEMENTATION:
 
index d78c1bc3dd3fc3c6daed786ed226d2b8a3361ede..7879e36ef68b7f3aaa24ca4a18a6b6b416d26ba0 100644 (file)
@@ -27,22 +27,22 @@ class Kobject_iface;
 class Context_ptr
 {
 public:
-  explicit Context_ptr(unsigned long id) : _t(id) {}
+  explicit Context_ptr(Cap_index id) : _t(id) {}
   Context_ptr() {}
   Context_ptr(Context_ptr const &o) : _t(o._t) {}
   Context_ptr const &operator = (Context_ptr const &o)
   { _t = o._t; return *this; }
 
-  Kobject_iface *ptr(Space *, unsigned char *) const;
+  Kobject_iface *ptr(Space *, L4_fpage::Rights *) const;
 
   bool is_kernel() const { return false; }
-  bool is_valid() const { return _t != ~0UL; }
+  bool is_valid() const { return _t != Cap_index(~0UL); }
 
   // only for debugging use
-  Mword raw() const { return _t;}
+  Cap_index raw() const { return _t; }
 
 private:
-  Mword _t;
+  Cap_index _t;
 
 };
 
@@ -51,8 +51,10 @@ class Context_ptr_base : public Context_ptr
 {
 public:
   enum Invalid_type { Invalid };
-  explicit Context_ptr_base(Invalid_type) : Context_ptr(0) {}
-  explicit Context_ptr_base(unsigned long id) : Context_ptr(id) {}
+  enum Null_type { Null };
+  explicit Context_ptr_base(Invalid_type) : Context_ptr(Cap_index(~0UL)) {}
+  explicit Context_ptr_base(Null_type) : Context_ptr(Cap_index(0)) {}
+  explicit Context_ptr_base(Cap_index id) : Context_ptr(id) {}
   Context_ptr_base() {}
   Context_ptr_base(Context_ptr_base<T> const &o) : Context_ptr(o) {}
   template< typename X >
@@ -178,7 +180,7 @@ public:
 
   struct Migration
   {
-    unsigned cpu;
+    Cpu_number cpu;
     L4_sched_param const *sp;
     bool in_progress;
 
@@ -208,7 +210,7 @@ public:
           && (int)Config::Access_user_mem == Config::Access_user_mem_direct)
         return _u.get();
 
-      unsigned const cpu = current_cpu();
+      Cpu_number const cpu = current_cpu();
       if ((int)Config::Access_user_mem == Config::Must_access_user_mem_direct
           && cpu == context()->cpu()
           && Mem_space::current_mem_space(cpu) == context()->space())
@@ -350,7 +352,7 @@ public:
     void *reply;
     Context *thread;
     Drq const *rq;
-    unsigned target_cpu;
+    Cpu_number target_cpu;
     enum class Type { Send, Do_request, Do_reply, Done } type;
     bool wait;
     unsigned print(int max, char *buf) const;
@@ -416,7 +418,7 @@ DEFINE_PER_CPU Per_cpu<Context *> Context::_kernel_ctxt;
 
 IMPLEMENT inline NEEDS["kdb_ke.h"]
 Kobject_iface * __attribute__((nonnull(1, 2)))
-Context_ptr::ptr(Space *s, unsigned char *rights) const
+Context_ptr::ptr(Space *s, L4_fpage::Rights *rights) const
 {
   assert_kdb (cpu_lock.test());
 
@@ -454,7 +456,7 @@ Context::Context()
   // sys_task_new() and avoid calling us twice with different
   // space_context arguments.
 
-  set_cpu_of(this, Cpu::Invalid);
+  set_cpu_of(this, Cpu::invalid());
 }
 
 PUBLIC inline
@@ -500,7 +502,9 @@ 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());
+    printf("FAIL: cpu=%u (current=%u)\n",
+           cxx::int_value<Cpu_number>(cpu()),
+           cxx::int_value<Cpu_number>(current_cpu()));
   return r;
 }
 
@@ -516,12 +520,12 @@ Context::state(bool check = true) const
 
 PUBLIC static inline
 Context*
-Context::kernel_context(unsigned cpu)
+Context::kernel_context(Cpu_number cpu)
 { return _kernel_ctxt.cpu(cpu); }
 
 PROTECTED static inline
 void
-Context::kernel_context(unsigned cpu, Context *ctxt)
+Context::kernel_context(Cpu_number cpu, Context *ctxt)
 { _kernel_ctxt.cpu(cpu) = ctxt; }
 
 
@@ -753,7 +757,7 @@ Context::schedule()
   // Ensure only the current thread calls schedule
   assert_kdb (this == current());
 
-  unsigned current_cpu = ~0U;
+  Cpu_number current_cpu = Cpu_number::nil();
   Sched_context::Ready_queue *rq = 0;
 
   // Enqueue current thread into ready-list to schedule correctly
@@ -767,7 +771,7 @@ Context::schedule()
       // I may've been migrated during the switch_exec_locked in the while
       // statement below. So check out if I've to use a new ready queue.
         {
-          unsigned new_cpu = access_once(&_cpu);
+          Cpu_number new_cpu = access_once(&_cpu);
           if (new_cpu != current_cpu)
             {
               Mem::barrier();
@@ -1181,7 +1185,7 @@ 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() != Cpu::invalid());
   assert_kdb (t->cpu() == current_cpu());
   assert_kdb (cpu() == current_cpu());
   assert_kdb (cpu_lock.test());
@@ -1656,23 +1660,23 @@ IMPLEMENTATION [!mp]:
 #include "kdb_ke.h"
 
 PUBLIC inline
-unsigned
+Cpu_number
 Context::cpu(bool running = false) const
 {
   if (running)
-    return 0;
+    return Cpu_number::boot_cpu();
 
   return _cpu;
 }
 
 PUBLIC static inline
 void
-Context::enable_tlb(unsigned)
+Context::enable_tlb(Cpu_number)
 {}
 
 PUBLIC static inline
 void
-Context::disable_tlb(unsigned)
+Context::disable_tlb(Cpu_number)
 {}
 
 
@@ -1782,12 +1786,12 @@ Cpu_mask Context::_tlb_active;
 
 PUBLIC static inline
 void
-Context::enable_tlb(unsigned cpu)
+Context::enable_tlb(Cpu_number cpu)
 { _tlb_active.atomic_set(cpu); }
 
 PUBLIC static inline
 void
-Context::disable_tlb(unsigned cpu)
+Context::disable_tlb(Cpu_number cpu)
 { _tlb_active.atomic_clear(cpu); }
 
 /**
@@ -1875,7 +1879,7 @@ Context::Pending_rqq::handle_requests(Context **mq)
 
 PUBLIC
 void
-Context::global_drq(unsigned cpu, Drq::Request_func *func, void *arg,
+Context::global_drq(Cpu_number cpu, Drq::Request_func *func, void *arg,
                     Drq::Request_func *reply = 0, bool wait = true)
 {
   assert_kdb (this == current());
@@ -1890,7 +1894,7 @@ Context::global_drq(unsigned cpu, Drq::Request_func *func, void *arg,
 
   Ipi::send(Ipi::Global_request, this->cpu(), cpu);
 
-  //LOG_MSG_3VAL(src, "<drq", src->state(), Mword(this), 0);
+  //LOG_MSG_3VAL(this, "<drq", state(), Mword(this), 0);
   while (wait && (state() & Thread_drq_wait))
     {
       state_del(Thread_ready_mask);
@@ -1919,7 +1923,7 @@ Context::enqueue_drq(Drq *rq, Drq::Exec_mode /*exec*/)
       _drq_q.enq(rq);
 
       // read cpu again we may've been migrated meanwhile
-      unsigned cpu = access_once(&this->_cpu);
+      Cpu_number cpu = access_once(&this->_cpu);
 
        {
          Queue &q = Context::_pending_rqq.cpu(cpu);
@@ -1999,7 +2003,7 @@ Context::shutdown_drqs()
 
 
 PUBLIC inline
-unsigned
+Cpu_number
 Context::cpu(bool running = false) const
 {
   (void)running;
@@ -2049,6 +2053,7 @@ Context::handle_remote_tlb_flush(Drq *, Context *, void *_s)
 {
   Mem_space **s = (Mem_space **)_s;
   Mem_space::tlb_flush_spaces((bool)s[0], s[1], s[2]);
+
   return 0;
 }
 
@@ -2059,8 +2064,8 @@ Context::xcpu_tlb_flush(bool flush_all_spaces, Mem_space *s1, Mem_space *s2)
 {
   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)
+  Cpu_number ccpu = current_cpu();
+  for (Cpu_number i = Cpu_number::first(); i < Config::max_num_cpus(); ++i)
     if (ccpu != i && _tlb_active.get(i))
       current()->global_drq(i, Context::handle_remote_tlb_flush, s);
 }
@@ -2115,6 +2120,29 @@ void
 Context::switch_fpu(Context *)
 {}
 
+//----------------------------------------------------------------------------
+INTERFACE [debug]:
+
+#include "tb_entry.h"
+
+/** logged context switch. */
+class Tb_entry_ctx_sw : public Tb_entry
+{
+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));
+
+
+
 // --------------------------------------------------------------------------
 IMPLEMENTATION [debug]:
 
@@ -2133,6 +2161,53 @@ Context::Drq_log::print(int maxlen, char *buf) const
 
   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);
+      thread, func, reply, cxx::int_value<Cpu_number>(target_cpu));
+}
+
+// context switch
+IMPLEMENT
+unsigned
+Tb_entry_ctx_sw::print(int maxlen, char *buf) const
+{
+  char symstr[24];
+  int max = maxlen;
+
+  Context *sctx = 0;
+  Mword sctxid = ~0UL;
+  Mword dst;
+  Mword dst_orig;
+
+  sctx = from_sched->context();
+  sctxid = Kobject_dbg::pointer_to_id(sctx);
+
+  dst = Kobject_dbg::pointer_to_id(this->dst);
+  dst_orig = Kobject_dbg::pointer_to_id(this->dst_orig);
+
+  snprintf(symstr, sizeof(symstr), L4_PTR_FMT, kernel_ip); // Jdb_symbol::...
+
+  if (sctx != ctx())
+    maxlen -= snprintf(buf, maxlen, "(%lx)", sctxid);
+
+  maxlen -= snprintf(buf, maxlen, " ==> %lx ", dst);
+
+  if (dst != dst_orig || lock_cnt)
+    maxlen -= snprintf(buf, maxlen, "(");
+
+  if (dst != dst_orig)
+    maxlen -= snprintf(buf, maxlen, "want %lx", dst_orig);
+
+  if (dst != dst_orig && lock_cnt)
+    maxlen -= snprintf(buf, maxlen, " ");
+
+  if (lock_cnt)
+    maxlen -= snprintf(buf, maxlen, "lck %ld", lock_cnt);
+
+  if (dst != dst_orig || lock_cnt)
+    maxlen -= snprintf(buf, maxlen, ") ");
+
+  maxlen -= snprintf(buf, maxlen, " krnl %s", symstr);
+
+  return max - maxlen;
 }
 
+
index 5ea22f666af2393a4a0a0e0bded4910a2f9220b8..0c8517fcd16984c90452f64d3309a7e83c25ce71 100644 (file)
@@ -18,9 +18,9 @@ public:
   virtual ~Context_base() = 0;
 
 protected:
-  friend unsigned &__cpu_of(const void *);
+  friend Cpu_number &__cpu_of(const void *);
   Mword _state;
-  unsigned _cpu;
+  Cpu_number _cpu;
 };
 
 
@@ -44,29 +44,29 @@ Context *current()
 { return context_of((void *)Proc::stack_pointer()); }
 
 inline NEEDS ["config.h"]
-unsigned &__cpu_of(const void *ptr)
+Cpu_number &__cpu_of(const void *ptr)
 { return reinterpret_cast<Context_base*>(context_of(ptr))->_cpu; }
 
 inline NEEDS [__cpu_of]
-void set_cpu_of(const void *ptr, unsigned cpu)
+void set_cpu_of(const void *ptr, Cpu_number cpu)
 { __cpu_of(ptr) = cpu; }
 
 
 inline NEEDS [__cpu_of]
-unsigned cpu_of(const void *ptr)
+Cpu_number cpu_of(const void *ptr)
 { return __cpu_of(ptr); }
 
 //---------------------------------------------------------------------------
 IMPLEMENTATION [!mp]:
 
 inline
-unsigned current_cpu()
-{ return 0; }
+Cpu_number current_cpu()
+{ return Cpu_number::boot_cpu(); }
 
 //---------------------------------------------------------------------------
 IMPLEMENTATION [mp]:
 
 inline NEEDS [current, cpu_of]
-unsigned current_cpu()
+Cpu_number current_cpu()
 { return cpu_of(current()); }
 
index 8d32186236c979fe441e398796754479a6695636..6ac7780c04cbedec68ed6b1c9bc84bd1357fd557 100644 (file)
@@ -10,8 +10,8 @@ class Cpu
 public:
   struct By_phys_id
   {
-    Unsigned32 _p;
-    By_phys_id(Unsigned32 p) : _p(p) {}
+    Cpu_phys_id _p;
+    By_phys_id(Cpu_phys_id p) : _p(p) {}
     template<typename CPU>
     bool operator () (CPU const &c) const { return _p == c.phys_id(); }
   };
@@ -20,9 +20,10 @@ public:
   typedef Cpu_mask_t<Config::Max_num_cpus + 1> Online_cpu_mask;
 
   enum { Invalid = Config::Max_num_cpus };
+  static Cpu_number invalid() { return Cpu_number(Invalid); }
 
   /** Get the logical ID of this CPU */
-  unsigned id() const;
+  Cpu_number id() const;
 
 
   /**
@@ -32,7 +33,7 @@ public:
   void set_online(bool o);
 
   /** Convienience for Cpu::cpus.cpu(cpu).online() */
-  static bool online(unsigned cpu);
+  static bool online(Cpu_number cpu);
 
   static Online_cpu_mask const &online_mask();
 
@@ -51,8 +52,8 @@ EXTENSION class Cpu
 {
 
 private:
-  void set_id(unsigned id) { _id = id; }
-  unsigned _id;
+  void set_id(Cpu_number id) { _id = id; }
+  Cpu_number _id;
 };
 
 //--------------------------------------------------------------------------
@@ -61,7 +62,7 @@ INTERFACE[!mp]:
 EXTENSION class Cpu
 {
 private:
-  void set_id(unsigned) {}
+  void set_id(Cpu_number) {}
 };
 
 
@@ -81,7 +82,7 @@ IMPLEMENTATION [mp]:
 #include "kdb_ke.h"
 
 IMPLEMENT inline
-unsigned
+Cpu_number
 Cpu::id() const
 { return _id; }
 
@@ -103,7 +104,7 @@ Cpu::set_online(bool o)
 
 IMPLEMENT static inline NEEDS["kdb_ke.h"]
 bool
-Cpu::online(unsigned _cpu)
+Cpu::online(Cpu_number _cpu)
 { return _online_mask.get(_cpu); }
 
 
@@ -111,9 +112,9 @@ Cpu::online(unsigned _cpu)
 IMPLEMENTATION [!mp]:
 
 IMPLEMENT inline
-unsigned
+Cpu_number
 Cpu::id() const
-{ return 0; }
+{ return Cpu_number::boot_cpu(); }
 
 IMPLEMENT inline
 bool
@@ -127,6 +128,6 @@ Cpu::set_online(bool)
 
 IMPLEMENT static inline
 bool
-Cpu::online(unsigned _cpu)
-{ return _cpu == 0; }
+Cpu::online(Cpu_number _cpu)
+{ return _cpu == Cpu_number::boot_cpu(); }
 
index 238bd26d78c0f6bf5e220cda333b0f46f8540775..89c7b0647680c804ef6b422b78f218cb47715dc6 100644 (file)
@@ -2,6 +2,7 @@ INTERFACE:
 
 #include "bitmap.h"
 #include "config.h"
+#include "types.h"
 
 template<unsigned MAX_NUM_CPUS>
 class Cpu_mask_t
@@ -16,13 +17,23 @@ public:
   Cpu_mask_t &operator = (Cpu_mask_t const &) = default;
 
   bool empty() const { return _b.is_empty(); }
-  bool get(unsigned cpu) const { return _b[cpu]; }
-  void clear(unsigned cpu) { return _b.clear_bit(cpu); }
-  void set(unsigned cpu) { _b.set_bit(cpu); };
-  void atomic_set(unsigned cpu) {_b.atomic_set_bit(cpu); }
-  void atomic_clear(unsigned cpu) {_b.atomic_clear_bit(cpu); }
-  bool atomic_get_and_clear(unsigned cpu)
-  { return _b.atomic_get_and_clear(cpu); }
+  bool get(Cpu_number cpu) const
+  { return _b[cxx::int_value<Cpu_number>(cpu)]; }
+
+  void clear(Cpu_number cpu)
+  { return _b.clear_bit(cxx::int_value<Cpu_number>(cpu)); }
+
+  void set(Cpu_number cpu)
+  { _b.set_bit(cxx::int_value<Cpu_number>(cpu)); };
+
+  void atomic_set(Cpu_number cpu)
+  { _b.atomic_set_bit(cxx::int_value<Cpu_number>(cpu)); }
+
+  void atomic_clear(Cpu_number cpu)
+  { _b.atomic_clear_bit(cxx::int_value<Cpu_number>(cpu)); }
+
+  bool atomic_get_and_clear(Cpu_number cpu)
+  { return _b.atomic_get_and_clear(cxx::int_value<Cpu_number>(cpu)); }
 
 private:
   Bitmap<Max_num_cpus> _b;
index 92e7f35c3fb5bf2d0393ed9596243bf1db354608..24858c5e2111f8aa154ab9643b1fab602f56e112 100644 (file)
@@ -4,7 +4,7 @@ INTERFACE [debug]:
 #include "lock_guard.h"
 #include "spin_lock.h"
 #include "slab_cache.h"
-#include <slist>
+#include <cxx/slist>
 
 class Dbg_page_info_table;
 
@@ -56,7 +56,8 @@ public:
 
 private:
   Entry _tab[Hash_tab_size];
-  static unsigned hash(Page_number p) { return p.value() % Hash_tab_size; }
+  static unsigned hash(Page_number p)
+  { return cxx::int_value<Page_number>(p) % Hash_tab_size; }
 };
 
 
index 3c718bb43e0c5e6f25dcc636c8a4d08e27c978ef..2ff5451efffd0db398d3fbec3735b905f12262a2 100644 (file)
@@ -89,7 +89,7 @@ void Factory::operator delete (void *_f)
 
 PRIVATE
 L4_msg_tag
-Factory::map_obj(Kobject_iface *o, Mword cap, Space *c_space,
+Factory::map_obj(Kobject_iface *o, Cap_index cap, Space *c_space,
                  Obj_space *o_space)
 {
   Reap_list rl;
@@ -149,11 +149,11 @@ Factory::new_gate(L4_msg_tag const &tag, Utcb const *utcb, Obj_space *o_space,
       if (EXPECT_FALSE(!bind_thread.is_objpage()))
        return 0;
 
-      unsigned char thread_rights = 0;
+      L4_fpage::Rights thread_rights = L4_fpage::Rights(0);
       thread = Kobject::dcast<Thread_object*>(o_space->lookup_local(bind_thread.obj_index(), &thread_rights));
 
       *err = L4_err::EPerm;
-      if (EXPECT_FALSE(!(thread_rights & L4_fpage::W)))
+      if (EXPECT_FALSE(!(thread_rights & L4_fpage::Rights::W())))
        return 0;
     }
 #if 0
@@ -177,7 +177,7 @@ Factory::new_irq(unsigned w, Utcb const *utcb, int *)
 
 PUBLIC
 L4_msg_tag
-Factory::kinvoke(L4_obj_ref ref, Mword rights, Syscall_frame *f,
+Factory::kinvoke(L4_obj_ref ref, L4_fpage::Rights rights, Syscall_frame *f,
                  Utcb const *utcb, Utcb *)
 {
   register Context *const c_thread = ::current();
@@ -186,7 +186,7 @@ Factory::kinvoke(L4_obj_ref ref, Mword rights, Syscall_frame *f,
   if (EXPECT_FALSE(f->tag().proto() != L4_msg_tag::Label_factory))
     return commit_result(-L4_err::EBadproto);
 
-  if (EXPECT_FALSE(!(rights & L4_fpage::W)))
+  if (EXPECT_FALSE(!(rights & L4_fpage::Rights::CS())))
     return commit_result(-L4_err::EPerm);
 
   if (EXPECT_FALSE(!ref.have_recv()))
@@ -269,9 +269,10 @@ Factory::kinvoke(L4_obj_ref ref, Mword rights, Syscall_frame *f,
 
 
 //----------------------------------------------------------------------------
-IMPLEMENTATION [svm || vmx]:
+IMPLEMENTATION [svm || vmx || arm_em_tz]:
 
 #include "vm_factory.h"
+#include "vm.h"
 
 PRIVATE inline NOEXPORT
 Kobject_iface *
@@ -283,20 +284,8 @@ Factory::new_vm(Utcb const *, int *err)
   return 0;
 }
 
-IMPLEMENTATION [tz]:
-
-#include "vm.h"
-
-PRIVATE inline NOEXPORT
-Kobject_iface *
-Factory::new_vm(Utcb const *, int *err)
-{
-  *err = L4_err::ENomem;
-  return Vm::create(this);
-}
-
 //----------------------------------------------------------------------------
-IMPLEMENTATION [!svm && !tz && !vmx]:
+IMPLEMENTATION [!svm && !vmx && !arm_em_tz]:
 
 PRIVATE inline NOEXPORT
 Kobject_iface *
@@ -317,7 +306,7 @@ private:
   struct Log_entry : public Tb_entry
   {
     Smword op;
-    Mword buffer;
+    Cap_index buffer;
     Mword id;
     Mword ram;
     Mword newo;
@@ -342,5 +331,5 @@ Factory::Log_entry::print(int maxlen, char *buf) const
     _op = "(nan)";
 
   return snprintf(buf, maxlen, "factory=%lx [%s] new=%lx cap=[C:%lx] ram=%lx",
-                  id, _op, newo, buffer, ram);
+                  id, _op, newo, cxx::int_value<Cap_index>(buffer), ram);
 }
index ac5c89ee7a4351f1c5496c97309b23e90b173b5f..d2f11a4c63c733961d2256e2b355fce9f0022d49 100644 (file)
@@ -18,7 +18,7 @@ class Fpu
 {
 public:
   // all the following methods are arch dependent
-  static void init(unsigned cpu) FIASCO_INIT_CPU;
+  static void init(Cpu_number cpu) FIASCO_INIT_CPU;
 
   static unsigned state_size();
   static unsigned state_align();
@@ -61,7 +61,7 @@ unsigned Fpu::state_align()
 { return 1; }
 
 IMPLEMENT
-void Fpu::init(unsigned)
+void Fpu::init(Cpu_number)
 {}
 
 IMPLEMENT inline
index 4dc88b3dae4086cb1319825391b86dcffed8b60b..cb9d40d0d37e4060f9c8c336b1fcdd6185ec65ac 100644 (file)
@@ -40,6 +40,9 @@ public:
     End_cap = First_cap + Max,
   };
 
+  static Cap_index first() { return Cap_index(First_cap); }
+  static Cap_index end() { return Cap_index(End_cap); }
+
   void register_obj(Kobject_iface *o, unsigned cap)
   {
     assert (cap >= First_cap);
@@ -52,14 +55,12 @@ public:
     _v[cap] = o;
   }
 
-  Kobject_iface *obj(unsigned cap) const
+  Kobject_iface *obj(Cap_index cap) const
   {
-    assert (cap >= First_cap);
-    assert (cap < End_cap);
-
-    cap -= First_cap;
+    assert (cap >= first());
+    assert (cap < end());
 
-    return _v[cap];
+    return _v[cxx::int_value<Cap_diff>(cap - first())];
   }
 
 private:
index b05eddbc2b9e3a7f2e11f83ebe398a7bfc17fe71..e721a9cada62385a5bbd2acea8414e1c638ace63 100644 (file)
@@ -6,12 +6,11 @@ INTERFACE[ia32,ux]:
 #include "ptab_base.h"
 
 class PF {};
+class Page {};
 
-class Pte_base
+class Pt_entry
 {
 public:
-  typedef Mword Raw;
-
   enum
   {
     Super_level   = 0,
@@ -26,46 +25,25 @@ public:
     Pse_bit       = 0x00000080, ///< Indicates a super page
     Cpu_global    = 0x00000100, ///< pinned in the TLB
     L4_global     = 0x00000200, ///< pinned in the TLB
-    Pfn           = 0xfffff000, ///< page frame number
+    XD            = 0,
+    ATTRIBS_MASK  = 0x06,
   };
-
-  Mword addr() const { return _raw & Pfn; }
-
-protected:
-  Raw _raw;
-
-private:
-  static Unsigned32 _cpu_global;
 };
 
-class Pt_entry : public Pte_base
+class Pte_ptr
 {
 public:
-  enum { Page_shift = Config::PAGE_SHIFT };
-  Mword leaf() const { return true; }
-  void set(Address p, bool intermed, bool present, unsigned long attrs = 0)
-  {
-    _raw = (p & Pfn) | (present ? 1 : 0)
-      | (intermed ? (Writable | User | Cacheable) : 0) | attrs;
-  }
-};
+  Pte_ptr(void *pte, unsigned char level) : pte((Mword*)pte), level(level) {}
+  Pte_ptr() = default;
 
-class Pd_entry : public Pte_base
-{
-public:
-  enum { Page_shift = Config::SUPERPAGE_SHIFT };
-  Mword leaf() const { return _raw & Pse_bit; }
-  void set(Address p, bool intermed, bool present, unsigned long attrs = 0)
-  {
-    _raw = (p & Pfn) | (present ? 1 : 0)
-      | (intermed ? (Writable | User | Cacheable) : Pse_bit) | attrs;
-  }
+  Mword *pte;
+  unsigned char level;
 };
 
 
 
-typedef Ptab::List< Ptab::Traits<Pd_entry, 22, 10, true, false>,
-                    Ptab::Traits<Pt_entry, 12, 10, true> > Ptab_traits;
+typedef Ptab::List< Ptab::Traits<Unsigned32, 22, 10, true, false>,
+                    Ptab::Traits<Unsigned32, 12, 10, true> > Ptab_traits;
 
 typedef Ptab::Shift<Ptab_traits, Virt_addr::Shift>::List Ptab_traits_vpn;
 typedef Ptab::Page_addr_wrap<Page_number, Virt_addr::Shift> Ptab_va_vpn;
index d244f0811d90db55e94418c489e280cee55a7103..bcda86295797a6f94a6286e8d207868230b8d8b9 100644 (file)
@@ -65,6 +65,7 @@ Sys_call_page::init()
   COPY_SYSCALL(debugger);
 
   Kernel_task::kernel_task()->set_attributes(
-      Mem_space::Addr(Mem_layout::Syscalls),
-      Page::USER_RO);
+      Virt_addr(Mem_layout::Syscalls),
+      Page::Attr(Page::Rights::UR(), Page::Type::Normal(),
+                 Page::Kern::Global()));
 }
index 1e45f9c684512c76b77379a4c8707961655e7a74..60112269eadfa4a99f7f1c631dee1a69f8a7a178 100644 (file)
@@ -74,7 +74,7 @@ Thread::trap_state_to_rf(Trap_state *ts)
 PRIVATE static inline NEEDS[Thread::trap_state_to_rf]
 bool FIASCO_WARN_RESULT
 Thread::copy_utcb_to_ts(L4_msg_tag const &tag, Thread *snd, Thread *rcv,
-                        unsigned char rights)
+                        L4_fpage::Rights rights)
 {
   Trap_state *ts = (Trap_state*)rcv->_utcb_handler;
   Mword       s  = tag.words();
@@ -101,7 +101,7 @@ Thread::copy_utcb_to_ts(L4_msg_tag const &tag, Thread *snd, Thread *rcv,
   // reset segments
   rcv->_gs = rcv->_fs = 0;
 
-  if (tag.transfer_fpu() && (rights & L4_fpage::W))
+  if (tag.transfer_fpu() && (rights & L4_fpage::Rights::W()))
     snd->transfer_fpu(rcv);
 
   // sanitize eflags
@@ -120,7 +120,7 @@ Thread::copy_utcb_to_ts(L4_msg_tag const &tag, Thread *snd, Thread *rcv,
 PRIVATE static inline
 bool FIASCO_WARN_RESULT
 Thread::copy_ts_to_utcb(L4_msg_tag const &, Thread *snd, Thread *rcv,
-                        unsigned char rights)
+                        L4_fpage::Rights rights)
 {
   Utcb *rcv_utcb = rcv->utcb().access();
   Trap_state *ts = (Trap_state*)snd->_utcb_handler;
@@ -139,7 +139,7 @@ Thread::copy_ts_to_utcb(L4_msg_tag const &, Thread *snd, Thread *rcv,
     else
       Mem::memcpy_mwords (rcv_utcb->values, &ts->_gs, r > 16 ? 16 : r);
 
-    if (rcv_utcb->inherit_fpu() && (rights & L4_fpage::W))
+    if (rcv_utcb->inherit_fpu() && (rights & L4_fpage::Rights::W()))
        snd->transfer_fpu(rcv);
   }
   return true;
@@ -297,7 +297,7 @@ PRIVATE static
 int
 Thread::call_nested_trap_handler(Trap_state *ts)
 {
-  unsigned log_cpu = dbg_find_cpu();
+  Cpu_number log_cpu = dbg_find_cpu();
   unsigned long &ntr = nested_trap_recover.cpu(log_cpu);
 
 #if 0
@@ -324,7 +324,6 @@ Thread::call_nested_trap_handler(Trap_state *ts)
   p.pdir = Kernel_task::kernel_task()->virt_to_phys((Address)Kmem::dir());
   p.handler = nested_trap_handler;
 
-
   // don't set %esp if gdb fault recovery to ensure that exceptions inside
   // kdb/jdb don't overwrite the stack
   asm volatile
index 1bc533badf381effd813d9c7a401e42da6ae31ac..70b0a97a449af65b89dfb7d369c83e5228c49e09 100644 (file)
@@ -7,12 +7,12 @@ INTERFACE[amd64]:
 #include "ptab_base.h"
 
 class PF {};
+class Page {};
 
-class Pte_base
+
+class Pt_entry
 {
 public:
-  typedef Mword Raw;
-
   enum
   {
     Super_level   = 2,
@@ -27,60 +27,25 @@ public:
     Pse_bit       = 0x00000080LL, ///< Indicates a super page
     Cpu_global    = 0x00000100LL, ///< pinned in the TLB
     L4_global     = 0x00000200LL, ///< pinned in the TLB
-    Pfn           = 0x000ffffffffff000LL, ///< page frame number
+    XD            = 0x8000000000000000ULL,
+    ATTRIBS_MASK  = 0x8000000000000006ULL
   };
-
-  Mword addr() const { return _raw & Pfn; }
-
-protected:
-  Raw _raw;
-
-private:
-  static Unsigned32 _cpu_global;
-};
-
-class Pt_entry : public Pte_base
-{
-public:
-  enum { Page_shift = Config::PAGE_SHIFT };
-  Mword leaf() const { return true; }
-  void set(Address p, bool intermed, bool present, unsigned long attrs = 0) 
-  {
-    _raw = (p & Pfn) | (present ? 1 : 0)
-      | (intermed ? (Writable | User | Cacheable) : 0) | attrs;
-  }
 };
 
-class Pd_entry : public Pte_base
+class Pte_ptr
 {
 public:
-  enum { Page_shift = Config::SUPERPAGE_SHIFT };
-  Mword leaf() const { return _raw & Pse_bit; }
-  void set(Address p, bool intermed, bool present, unsigned long attrs = 0)
-  {
-    _raw = (p & Pfn) | (present ? 1 : 0)
-      | (intermed ? (Writable | User | Cacheable) : Pse_bit) | attrs;
-  }
-};
+  Pte_ptr(void *pte, unsigned char level) : pte((Mword*)pte), level(level) {}
+  Pte_ptr() = default;
 
-class Pdp_entry : public Pte_base
-{
-public:
-  // this is just a dummy, because there are no real pages on level 0 and 1
-  enum { Page_shift = 0 };
-  Mword leaf() const { return false; }
-  void set(Address p, bool, bool present, unsigned long attrs = 0)
-  {
-    _raw = (p & Pfn) | (present ? 1 : 0)
-      | (Writable | User | Cacheable) | attrs;
-  }
+  Mword *pte;
+  unsigned char level;
 };
 
-
-typedef Ptab::List< Ptab::Traits<Pdp_entry, 39, 9, false>,
-        Ptab::List< Ptab::Traits<Pdp_entry, 30, 9, false>,
-        Ptab::List< Ptab::Traits<Pd_entry,  21, 9, true>,
-                    Ptab::Traits<Pt_entry,  12, 9, true> > > > Ptab_traits;
+typedef Ptab::Tupel< Ptab::Traits<Unsigned64, 39, 9, false>,
+                     Ptab::Traits<Unsigned64, 30, 9, true>,
+                     Ptab::Traits<Unsigned64,  21, 9, true>,
+                     Ptab::Traits<Unsigned64,  12, 9, true> >::List Ptab_traits;
 
 typedef Ptab::Shift<Ptab_traits, Virt_addr::Shift>::List Ptab_traits_vpn;
 typedef Ptab::Page_addr_wrap<Page_number, Virt_addr::Shift> Ptab_va_vpn;
index 9dfd0374b380f9cb10d97b3031e78dabbb662ad0..fbefc9633a5e3c25e64ed2c6ad3f0de9a9374da5 100644 (file)
@@ -86,7 +86,7 @@ Thread::trap_state_to_rf(Trap_state *ts)
 PRIVATE static inline NEEDS[Thread::trap_state_to_rf]
 bool FIASCO_WARN_RESULT
 Thread::copy_utcb_to_ts(L4_msg_tag const &tag, Thread *snd, Thread *rcv,
-                        unsigned char rights)
+                        L4_fpage::Rights rights)
 {
   Trap_state *ts = (Trap_state*)rcv->_utcb_handler;
   Mword       s  = tag.words();
@@ -108,7 +108,7 @@ Thread::copy_utcb_to_ts(L4_msg_tag const &tag, Thread *snd, Thread *rcv,
   else
     Mem::memcpy_mwords (ts, snd_utcb->values, s > 23 ? 23 : s);
 
-  if (tag.transfer_fpu() && (rights & L4_fpage::W))
+  if (tag.transfer_fpu() && (rights & L4_fpage::Rights::W()))
     snd->transfer_fpu(rcv);
 
   // sanitize eflags
@@ -127,7 +127,7 @@ Thread::copy_utcb_to_ts(L4_msg_tag const &tag, Thread *snd, Thread *rcv,
 PRIVATE static inline NEEDS[Thread::trap_state_to_rf]
 bool FIASCO_WARN_RESULT
 Thread::copy_ts_to_utcb(L4_msg_tag const &, Thread *snd, Thread *rcv,
-                        unsigned char rights)
+                        L4_fpage::Rights rights)
 {
   Trap_state *ts = (Trap_state*)snd->_utcb_handler;
   Utcb *rcv_utcb = rcv->utcb().access();
@@ -144,7 +144,7 @@ Thread::copy_ts_to_utcb(L4_msg_tag const &, Thread *snd, Thread *rcv,
     else
       Mem::memcpy_mwords (rcv_utcb->values, ts, 23);
 
-    if (rcv_utcb->inherit_fpu() && (rights & L4_fpage::W))
+    if (rcv_utcb->inherit_fpu() && (rights & L4_fpage::Rights::W()))
       snd->transfer_fpu(rcv);
 }
   return true;
@@ -205,7 +205,7 @@ Thread::call_nested_trap_handler(Trap_state *ts)
 {
   Proc::cli();
 
-  unsigned log_cpu = dbg_find_cpu();
+  Cpu_number log_cpu = dbg_find_cpu();
   unsigned long &ntr = nested_trap_recover.cpu(log_cpu);
 
 #if 0
index 566f66f764b5b10edc76f256883948695eb6f08d..c894e2eed6b64d0ba84eb5e67dd706f83c40f3ca 100644 (file)
@@ -122,7 +122,7 @@ struct By_id
 }
 
 PUBLIC static
-unsigned
+Cpu_number
 Apic::find_cpu(Unsigned32 phys_id)
 {
   return apic.find_cpu(By_id(phys_id));
@@ -766,12 +766,13 @@ Apic::error_interrupt(Return_frame *regs)
        return;
 
       printf("cpu%d: APIC invalid register access error at " L4_PTR_FMT "\n",
-            current_cpu(), regs->ip());
+            cxx::int_value<Cpu_number>(current_cpu()), regs->ip());
       return;
     }
 
   apic_error_cnt++;
-  printf("cpu%d: APIC error %08x(%08x)\n", current_cpu(), err1, err2);
+  printf("cpu%d: APIC error %08x(%08x)\n",
+         cxx::int_value<Cpu_number>(current_cpu()), err1, err2);
 }
 
 // deactivate APIC by writing to appropriate MSR
index a736075afc99d8bd5ad82b439bdf622196cab1ea..b3a3929d6d126d4c58829b723d859a751e0fac28 100644 (file)
@@ -118,7 +118,7 @@ private:
 
 public:
 
-  void disable(unsigned cpu, char const *reason);
+  void disable(Cpu_number cpu, char const *reason);
 
   char const *model_str() const { return _model_str; }
   Vendor vendor() const { return _vendor; }
@@ -662,10 +662,10 @@ char const * const Cpu::exception_strings[] =
 };
 
 PUBLIC explicit FIASCO_INIT_CPU
-Cpu::Cpu(unsigned cpu)
+Cpu::Cpu(Cpu_number cpu)
 {
   set_id(cpu);
-  if (cpu == 0)
+  if (cpu == Cpu_number::boot_cpu())
     {
       _boot_cpu = this;
       set_online(1);
@@ -1094,7 +1094,7 @@ PUBLIC
 bool
 Cpu::if_show_infos() const
 {
-  return    id() == 0
+  return    id() == Cpu_number::boot_cpu()
          || !boot_cpu()
          || family()    != boot_cpu()->family()
          || model()     != boot_cpu()->model()
@@ -1166,9 +1166,9 @@ Cpu::show_cache_tlb_info(const char *indent) const
 
 IMPLEMENT
 void
-Cpu::disable(unsigned cpu, char const *reason)
+Cpu::disable(Cpu_number cpu, char const *reason)
 {
-  printf("CPU%u: is disabled: %s\n", cpu, reason);
+  printf("CPU%u: is disabled: %s\n", cxx::int_value<Cpu_number>(cpu), reason);
 }
 
 // Function used for calculating apic scaler
@@ -1556,7 +1556,7 @@ Cpu::print() const
 {
   if (if_show_infos())
     printf("CPU[%u]: %s (%X:%X:%X:%X)[%08x] Model: %s at %lluMHz\n\n",
-           id(),
+           cxx::int_value<Cpu_number>(id()),
            vendor_str(), family(), model(), stepping(), brand(),
            _version, model_str(),
            div32(frequency(), 1000000));
index 153a5fa29325ee47568cb5d87142a9c4bf35c46c..70abd54ef9f1df063163da06d69be78b2b25b01e 100644 (file)
@@ -20,7 +20,7 @@ static inline void irq_spinners(int irqnum)
 {
 #ifdef CONFIG_IRQ_SPINNER
   Unsigned16 *p = (Unsigned16 *)Mem_layout::Adap_vram_cga_beg;
-  p += (20 + current_cpu()) * 80 + irqnum;
+  p += (20 + cxx::int_value<Cpu_number>(current_cpu())) * 80 + irqnum;
   if (p < (Unsigned16 *)Mem_layout::Adap_vram_cga_end)
     (*p)++;
 #else
index 342a0a3016b342e559c9dcd3b91571aa57ca3416..e2a8d5ac42b424300b23a7895a44f441987ed25d 100644 (file)
@@ -112,7 +112,7 @@ Fpu::init_state(Fpu_state *s)
 
 IMPLEMENT
 void
-Fpu::init(unsigned cpu)
+Fpu::init(Cpu_number cpu)
 {
   // Mark FPU busy, so that first FPU operation will yield an exception
   disable();
@@ -124,7 +124,7 @@ Fpu::init(unsigned cpu)
 
   init_disable();
 
-  printf("FPU%d: %s%s\n", cpu,
+  printf("FPU%d: %s%s\n", cxx::int_value<Cpu_number>(cpu),
          Cpu::cpus.cpu(cpu).features() & FEAT_SSE  ? "SSE "  : "",
         Cpu::cpus.cpu(cpu).ext_features() & FEATX_AVX ? "AVX "  : "");
 
index 059603a6eb10a4e864fad4ec3d6bb202e138f8de..2a717cbb35a0cfe97e64b88abe2295ca3c4a18a0 100644 (file)
@@ -15,7 +15,7 @@ IMPLEMENTATION [{ia32,amd64}-fpu]:
 
 PRIVATE static
 void
-Fpu::init_xsave(unsigned cpu)
+Fpu::init_xsave(Cpu_number cpu)
 {
   Unsigned32 eax, ebx, ecx, edx;
 
index be65a8acabb7665e35c959d37c252c406a901a82..35a866cd712ac7f92d303c069f541aea08ff7da0 100644 (file)
@@ -42,15 +42,15 @@ PRIVATE static
 void
 Idt::set_writable(bool writable)
 {
-  Pdir::Iter e = Kmem::dir()->walk(Virt_addr(_idt));
+  auto e = Kmem::dir()->walk(Virt_addr(_idt));
 
   // Make sure page directory entry is valid and not a 4MB page
-  assert (e.e->valid() && e.shift() < Config::SUPERPAGE_SHIFT);
+  assert (e.is_valid() && e.level == Pdir::Depth);
 
   if (writable)
-    e.e->add_attr(Pt_entry::Writable); // Make read-write
+    e.add_attribs(Pt_entry::Writable); // Make read-write
   else
-    e.e->del_attr(Pt_entry::Writable); // Make read-only
+    e.del_attribs(Pt_entry::Writable); // Make read-only
 
   Mem_unit::tlb_flush (_idt);
 }
index dfe94e6b5e8e21ebad47fec4240019f325fc0410..603697eab9f269a7ab8a246db10ab5ce7ce3994c 100644 (file)
@@ -4,7 +4,7 @@ INTERFACE:
 #include "initcalls.h"
 #include <spin_lock.h>
 #include "irq_chip_ia32.h"
-#include <bitfield>
+#include <cxx/bitfield>
 
 class Acpi_madt;
 
@@ -181,7 +181,7 @@ Io_apic::write_entry(unsigned i, Io_apic_entry const &e)
 
 PUBLIC static FIASCO_INIT
 bool
-Io_apic::init(unsigned cpu)
+Io_apic::init(Cpu_number cpu)
 {
   _madt = Acpi::find<Acpi_madt const *>("APIC");
 
@@ -400,7 +400,7 @@ Io_apic::unmask(Mword irq)
 }
 
 PUBLIC void
-Io_apic::set_cpu(Mword irq, unsigned cpu)
+Io_apic::set_cpu(Mword irq, Cpu_number cpu)
 {
   set_dest(irq, ::Apic::apic.cpu(cpu)->apic_id());
 }
index be32ed30bd32998031acad08b35acf0cabfcfda9..421802aabfc2adaf9eab54f74f8e34294e3f8753 100644 (file)
@@ -36,7 +36,7 @@ Ipi::Ipi() : _apic_id(~0)
  */
 IMPLEMENT static inline NEEDS["apic.h"]
 void
-Ipi::init(unsigned cpu)
+Ipi::init(Cpu_number cpu)
 {
   _ipi.cpu(cpu)._apic_id = Apic::get_id();
 }
@@ -51,7 +51,7 @@ Ipi::ipi_call_debug_arch()
 
 PUBLIC static inline NEEDS["apic.h"]
 void
-Ipi::eoi(Message, unsigned cpu)
+Ipi::eoi(Message, Cpu_number cpu)
 {
   Apic::mp_ipi_ack();
   stat_received(cpu);
@@ -59,7 +59,7 @@ Ipi::eoi(Message, unsigned cpu)
 
 PUBLIC static inline NEEDS["apic.h"]
 void
-Ipi::send(Message m, unsigned from_cpu, unsigned to_cpu)
+Ipi::send(Message m, Cpu_number from_cpu, Cpu_number to_cpu)
 {
   Apic::mp_send_ipi(_ipi.cpu(to_cpu)._apic_id, (Unsigned8)m);
   stat_sent(from_cpu);
@@ -67,7 +67,7 @@ Ipi::send(Message m, unsigned from_cpu, unsigned to_cpu)
 
 PUBLIC static inline NEEDS["apic.h"]
 void
-Ipi::bcast(Message m, unsigned from_cpu)
+Ipi::bcast(Message m, Cpu_number from_cpu)
 {
   (void)from_cpu;
   Apic::mp_send_ipi(Apic::APIC_IPI_OTHERS, (Unsigned8)m);
@@ -79,9 +79,9 @@ Ipi::bcast(Message m, unsigned from_cpu)
 PRIVATE static
 void Ipi::ipi_call_spin()
 {
-  unsigned cpu;
+  Cpu_number cpu;
   Ipi *ipi = 0;
-  for (cpu = 0; cpu < Config::Max_num_cpus; ++cpu)
+  for (cpu = Cpu_number::first(); cpu < Config::max_num_cpus(); ++cpu)
     {
       if (!Per_cpu_data::valid(cpu))
        continue;
@@ -96,7 +96,7 @@ void Ipi::ipi_call_spin()
   if (!ipi)
     return;
 
-  *(unsigned char*)(Mem_layout::Adap_vram_cga_beg + 22*160 + cpu*+2)
+  *(unsigned char*)(Mem_layout::Adap_vram_cga_beg + 22*160 + cxx::int_value<Cpu_number>(cpu)*2)
     = '0' + (ipi->_count++ % 10);
 }
 #endif
index 323cafe75bae34ed3f820a063fe9a6729fa31c2d..439079e65ab2eb83298dad1b01e3584215e945cd 100644 (file)
@@ -92,7 +92,7 @@ Irq_chip_ia32_pic::unmask(Mword irq)
 
 PUBLIC
 void
-Irq_chip_ia32_pic::set_cpu(Mword, unsigned)
+Irq_chip_ia32_pic::set_cpu(Mword, Cpu_number)
 {}
 
 
index b9cc8a99036571d89e1726d92074875d0dd05d10..4372efc6ca23ed07eca58b28b728a6586feebebb 100644 (file)
@@ -62,7 +62,7 @@ Irq_chip_msi::set_mode(Mword, unsigned)
 { return Irq_base::Trigger_edge | Irq_base::Polarity_low; }
 
 PUBLIC void
-Irq_chip_msi::set_cpu(Mword, unsigned)
+Irq_chip_msi::set_cpu(Mword, Cpu_number)
 {}
 
 PUBLIC void
index 834ee8457082f3145296efd3e0d6700394be931c..8d1febf8d831e251cbcd33e88811839f9e63c04e 100644 (file)
@@ -157,7 +157,7 @@ Device_map::map(Address phys, bool /*cache*/)
                         Virt_size(Config::SUPERPAGE_SIZE),
                         Pt_entry::Dirty | Pt_entry::Writable
                         | Pt_entry::Referenced,
-                        Pdir::super_level(), pdir_alloc(alloc));
+                        Pt_entry::super_level(), false, pdir_alloc(alloc));
        _map[i] = p;
 
        return (Virt_base + (i * Config::SUPERPAGE_SIZE))
@@ -183,7 +183,8 @@ Device_map::unmap(void const *phys)
 
   Address v = Virt_base + (idx * Config::SUPERPAGE_SIZE);
 
-  Kmem::kdir->unmap(Virt_addr(v), Virt_size(Config::SUPERPAGE_SIZE), -1);
+  Kmem::kdir->unmap(Virt_addr(v), Virt_size(Config::SUPERPAGE_SIZE),
+                    Pdir::Depth, false);
 }
 
 
@@ -227,7 +228,7 @@ PUBLIC static
 Address
 Kmem::map_phys_page_tmp(Address phys, Mword idx)
 {
-  unsigned long pte = phys & Pt_entry::Pfn;
+  unsigned long pte = cxx::mask_lsb(phys, Pdir::page_order_for_level(Pdir::Depth));
   Address virt;
 
   switch (idx)
@@ -294,18 +295,17 @@ Kmem::is_kmem_page_fault(Address addr, Mword /*error*/)
 PUBLIC static
 void
 Kmem::map_phys_page(Address phys, Address virt,
-                    bool cached, bool global, Address *offs=0)
+                    bool cached, bool global, Address *offs = 0)
 {
-  Pdir::Iter i = kdir->walk(Virt_addr(virt), 100, pdir_alloc(Kmem_alloc::allocator()));
-  Pte_base *e = i.e;
+  auto i = kdir->walk(Virt_addr(virt), Pdir::Depth, false,
+                      pdir_alloc(Kmem_alloc::allocator()));
   Mword pte = phys & Config::PAGE_MASK;
 
-  assert(i.shift() == Config::PAGE_SHIFT);
+  assert(i.level == Pdir::Depth);
 
-  *e = pte | Pt_entry::Valid | Pt_entry::Writable
-          | Pt_entry::Referenced | Pt_entry::Dirty
-          | (cached ? 0 : (Pt_entry::Write_through | Pt_entry::Noncacheable))
-          | (global ? Pt_entry::global() : 0);
+  i.set_page(pte, Pt_entry::Writable | Pt_entry::Referenced | Pt_entry::Dirty
+                  | (cached ? 0 : (Pt_entry::Write_through | Pt_entry::Noncacheable))
+                  | (global ? Pt_entry::global() : 0));
   Mem_unit::tlb_flush(virt);
 
   if (offs)
@@ -328,7 +328,7 @@ Kmem::init_mmu()
 
   printf("Superpages: %s\n", superpages?"yes":"no");
 
-  Pdir::have_superpages(superpages);
+  Pt_entry::have_superpages(superpages);
   if (superpages)
     Cpu::set_cr4(Cpu::get_cr4() | CR4_PSE);
 
@@ -351,36 +351,39 @@ Kmem::init_mmu()
   //     sometimes comes in handy (mostly useful for debugging)
 
   // first 4MB page
-  kdir->map(0, Virt_addr(0), Virt_size(4 << 20),
+  kdir->map(0, Virt_addr(0UL), Virt_size(4 << 20),
       Pt_entry::Dirty | Pt_entry::Writable | Pt_entry::Referenced,
-      Pdir::super_level(), pdir_alloc(alloc));
+      Pt_entry::super_level(), false, pdir_alloc(alloc));
 
 
   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::global(), Pdir::super_level(), pdir_alloc(alloc));
+            | Pt_entry::global(), Pt_entry::super_level(), false,
+            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::global(), Pdir::super_level(), pdir_alloc(alloc));
+               | Pt_entry::global(), Pt_entry::super_level(),
+               false, pdir_alloc(alloc));
 
   // map the last 64MB of physical memory as kernel memory
   kdir->map(Mem_layout::pmem_to_phys(Mem_layout::Physmem),
             Virt_addr(Mem_layout::Physmem), Virt_size(Mem_layout::pmem_size),
             Pt_entry::Writable | Pt_entry::Referenced | Pt_entry::global(),
-            Pdir::super_level(), pdir_alloc(alloc));
+            Pt_entry::super_level(), false, pdir_alloc(alloc));
 
   // The service page directory entry points to an universal usable
   // page table which is currently used for the Local APIC and the
   // jdb adapter page.
   assert((Mem_layout::Service_page & ~Config::SUPERPAGE_MASK) == 0);
 
-  Pdir::Iter pt = kdir->walk(Virt_addr(Mem_layout::Service_page), 100, pdir_alloc(alloc));
+  auto pt = kdir->walk(Virt_addr(Mem_layout::Service_page), Pdir::Depth,
+                       false, pdir_alloc(alloc));
 
   // kernel mode should acknowledge write-protected page table entries
   Cpu::set_cr0(Cpu::get_cr0() | CR0_WP);
@@ -404,12 +407,12 @@ Kmem::init_mmu()
     {
       // can map as 4MB page because the cpu_page will land within a
       // 16-bit range from io_bitmap
-      *(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;
+      auto e = kdir->walk(Virt_addr(Mem_layout::Io_bitmap - Config::SUPERPAGE_SIZE),
+                          Pdir::Super_level, false, pdir_alloc(alloc));
+
+      e.set_page(pmem_cpu_page & Config::SUPERPAGE_MASK,
+                 Pt_entry::Writable | Pt_entry::Referenced
+                 | Pt_entry::Dirty | Pt_entry::global());
 
       cpu_page_vm = (pmem_cpu_page & ~Config::SUPERPAGE_MASK)
                     + (Mem_layout::Io_bitmap - Config::SUPERPAGE_SIZE);
@@ -418,15 +421,14 @@ Kmem::init_mmu()
     {
       unsigned i;
       for (i = 0; cpu_page_size > 0; ++i, cpu_page_size -= Config::PAGE_SIZE)
-       {
-         pt = kdir->walk(Virt_addr(Mem_layout::Io_bitmap - Config::PAGE_SIZE * (i+1)),
-                         100, pdir_alloc(alloc));
-
-         *pt.e = (pmem_cpu_page + i*Config::PAGE_SIZE)
-                 | Pt_entry::Valid | Pt_entry::Writable
-                 | Pt_entry::Referenced | Pt_entry::Dirty
-                 | Pt_entry::global();
-       }
+        {
+          pt = kdir->walk(Virt_addr(Mem_layout::Io_bitmap - Config::PAGE_SIZE * (i+1)),
+                          Pdir::Depth, false, pdir_alloc(alloc));
+
+          pt.set_page(pmem_cpu_page + i*Config::PAGE_SIZE,
+                      Pt_entry::Writable | Pt_entry::Referenced | Pt_entry::Dirty
+                      | Pt_entry::global());
+        }
 
       cpu_page_vm = Mem_layout::Io_bitmap - Config::PAGE_SIZE * i;
     }
index 822a6e856c11d8ade22a9c7072fae198746f1cc2..b0d50d4c07a7724aaa4f92180772606bacd09d56 100644 (file)
@@ -12,6 +12,13 @@ IMPLEMENTATION [ia32,ux,amd64]:
 #include "panic.h"
 #include "types.h"
 
+PUBLIC static inline
+Phys_mem_addr::Value
+Kmem_alloc::to_phys(void *v)
+{
+  return Mem_layout::pmem_to_phys(v);
+}
+
 PUBLIC static FIASCO_INIT
 bool
 Kmem_alloc::base_init()
index 6d79716684e72aacdfbcbe860c8418fdb1b97881..75aea1c306c94f6b81f1e06408a911bdb75e5a19 100644 (file)
@@ -49,7 +49,7 @@ exit_question()
   if (Config::getchar_does_hlt_works_ok)
     {
       Timer_tick::set_vectors_stop();
-      Timer_tick::enable(0); // hmexit alway on CPU 0
+      Timer_tick::enable(Cpu_number::boot_cpu()); // hmexit alway on CPU 0
       Proc::sti();
     }
 
@@ -106,10 +106,10 @@ int FIASCO_FASTCALL boot_ap_cpu() __asm__("BOOT_AP_CPU");
 
 int FIASCO_FASTCALL boot_ap_cpu()
 {
-  unsigned _cpu = Apic::find_cpu(Apic::get_id());
+  Cpu_number _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)
+  static Cpu_number last_cpu; // keep track of the last cpu ever appeared
+  if (_cpu == Cpu_number::nil())
     {
       _cpu = ++last_cpu; // 0 is the boot cpu, so pre increment
       cpu_is_new = true;
@@ -118,7 +118,8 @@ int FIASCO_FASTCALL boot_ap_cpu()
   if (cpu_is_new && !Per_cpu_data_alloc::alloc(_cpu))
     {
       extern Spin_lock<Mword> _tramp_mp_spinlock;
-      printf("CPU allocation failed for CPU%u, disabling CPU.\n", _cpu);
+      printf("CPU allocation failed for CPU%u, disabling CPU.\n",
+             cxx::int_value<Cpu_number>(_cpu));
       _tramp_mp_spinlock.clear();
       while (1)
        Proc::halt();
index 01a699dd1f3b383eab578b391fc7fce6d3a59fbb..01aa4abcc01cf07244783f784c749748d35bede2 100644 (file)
@@ -23,7 +23,7 @@ void init_mapdb_io(Space *sigma0)
   static size_t const io_page_sizes[] =
     {Io_space::Map_superpage_shift, 9, Io_space::Page_shift};
 
-  mapdb_io.construct(sigma0, Page_number::create(0x10000 >> io_page_sizes[0]), io_page_sizes, 3);
+  mapdb_io.construct(sigma0, Mapping::Page(0x10000 >> io_page_sizes[0]), io_page_sizes, 3);
 }
 
 /** Map the IO port region described by "fp_from" of address space "from"
@@ -52,29 +52,38 @@ io_map(Space *from, L4_fpage const &fp_from,
  *   kdb_ke("io_fpage_map 1");
  */
 
-  typedef Map_traits<Io_space> Mt;
-  Mt::Addr rcv_pos = Mt::get_addr(fp_to);
-  Mt::Addr snd_pos = Mt::get_addr(fp_from);
+  Io_space::V_pfn rcv_addr = fp_to.io_address();
+  Io_space::V_pfn snd_addr = fp_from.io_address();
 
-  Mt::Size rcv_size = Mt::Size::from_shift(fp_to.order());
-  Mt::Size snd_size = Mt::Size::from_shift(fp_from.order());
+  Order ro = Mu::get_order_from_fp<Io_space::V_pfc>(fp_to);
+  Order so = Mu::get_order_from_fp<Io_space::V_pfc>(fp_from);
 
-  snd_pos = snd_pos.trunc(snd_size);
-  rcv_pos = rcv_pos.trunc(rcv_size);
-  Mt::constraint(snd_pos, snd_size, rcv_pos, rcv_size, Mt::Addr(0));
+  snd_addr = cxx::mask_lsb(snd_addr, so);
+  rcv_addr = cxx::mask_lsb(rcv_addr, ro);
 
-  if (snd_size == 0)
-    return L4_error::None;
+  Io_space::V_pfc rcv_size = Io_space::V_pfc(1) << ro;
+  Io_space::V_pfc snd_size = Io_space::V_pfc(1) << so;
+
+  if (rcv_addr > snd_addr)
+    {
+      if (rcv_addr - snd_addr < snd_size)
+        snd_size -= rcv_addr - snd_addr;
+      else
+        return L4_error::None;
 
-  //assert(snd_pos < L4_fpage::Io_port_max);
+      snd_addr = rcv_addr;
+    }
 
-  unsigned long del_attribs, add_attribs;
-  Mt::attribs(control, fp_from, &del_attribs, &add_attribs);
+  if (snd_size > rcv_size)
+    snd_size = rcv_size;
+
+  if (snd_size == Io_space::V_pfc(0))
+    return L4_error::None;
 
-  return map<Io_space>(mapdb_io.get(), from, from, snd_pos,
+  return map<Io_space>(mapdb_io.get(), from, from, snd_addr,
              snd_size,
-             to, to, snd_pos,
-             control.is_grant(), add_attribs, del_attribs,
+             to, to, snd_addr,
+             control.is_grant(), fp_from.rights(),
              (Io_space::Reap_list**)0);
 }
 
@@ -90,13 +99,12 @@ io_map(Space *from, L4_fpage const &fp_from,
                  additionally flush the region in the given address space.
     @return true if successful
 */
-unsigned __attribute__((nonnull(1)))
+L4_fpage::Rights __attribute__((nonnull(1)))
 io_fpage_unmap(Space *space, L4_fpage fp, L4_map_mask mask)
 {
-  typedef Map_traits<Io_space> Mt;
-  Mt::Size size = Mt::Size::from_shift(fp.order());
-  Mt::Addr port = Mt::get_addr(fp);
-  port = port.trunc(size);
+  Order size = Mu::get_order_from_fp<Io_space::V_pfc>(fp);
+  Io_space::V_pfn port = fp.io_address();
+  port = cxx::mask_lsb(port, size);
 
   // Here we _would_ reset IOPL to 0 but this doesn't make much sense
   // for only one thread since this thread may have forwarded the right
@@ -106,16 +114,7 @@ io_fpage_unmap(Space *space, L4_fpage fp, L4_map_mask mask)
   // current()->regs()->eflags &= ~EFLAGS_IOPL;
 
   return unmap<Io_space>(mapdb_io.get(), space, space,
-               port, size,
+               port, Io_space::V_pfc(1) << size,
                fp.rights(), mask, (Io_space::Reap_list**)0);
 }
 
-static inline
-void
-save_access_attribs(Mapdb* /*mapdb*/, const Mapdb::Frame& /*mapdb_frame*/,
-                   Mapping* /*mapping*/, Io_space* /*space*/,
-                   unsigned /*page_rights*/,
-                   Io_space::Addr /*virt*/, Io_space::Phys_addr /*phys*/,
-                   Io_space::Size /*size*/,
-                   bool /*me_too*/)
-{}
index a3b3695ac1258961160f1affb9d81b9003405655..8edfd11c386378a9fe2ec6f180f843ea8ced3c12 100644 (file)
@@ -43,7 +43,6 @@ public:
     Need_insert_tlb_flush = 0,
     Map_page_size = Config::PAGE_SIZE,
     Page_shift = Config::PAGE_SHIFT,
-    Map_superpage_size = Config::SUPERPAGE_SIZE,
     Map_max_address = Mem_layout::User_max,
     Whole_space = MWORD_BITS,
     Identity_map = 0,
@@ -51,7 +50,7 @@ public:
 
 
   void page_map        (Address phys, Address virt,
-                         Address size, unsigned page_attribs);
+                         Address size, Attr);
 
   void page_unmap      (Address virt, Address size);
 
@@ -91,7 +90,7 @@ Mem_space::initialize()
     return false;
 
   _dir = static_cast<Dir_type*>(b);
-  _dir->clear();       // initialize to zero
+  _dir->clear(false);  // initialize to zero
   return true; // success
 }
 
@@ -100,41 +99,14 @@ Mem_space::Mem_space(Ram_quota *q, Dir_type* pdir)
   : _quota(q), _dir(pdir)
 {
   _kernel_space = this;
-  _current.cpu(0) = this;
-}
-
-
-PUBLIC static inline
-Mword
-Mem_space::xlate_flush(unsigned char rights)
-{
-  Mword a = Page_references;
-  if (rights & L4_fpage::RX)
-    a |= Page_all_attribs;
-  else if (rights & L4_fpage::W)
-    a |= Page_writable;
-  return a;
-}
-
-PUBLIC static inline
-Mword
-Mem_space::is_full_flush(unsigned char rights)
-{
-  return rights & L4_fpage::RX;
+  _current.cpu(Cpu_number::boot_cpu()) = this;
 }
 
 PUBLIC static inline
-unsigned char
-Mem_space::xlate_flush_result(Mword attribs)
+bool
+Mem_space::is_full_flush(L4_fpage::Rights rights)
 {
-  unsigned char r = 0;
-  if (attribs & Page_referenced)
-    r |= L4_fpage::RX;
-
-  if (attribs & Page_dirty)
-    r |= L4_fpage::W;
-
-  return r;
+  return rights & L4_fpage::Rights::R();
 }
 
 PUBLIC inline NEEDS["cpu.h"]
@@ -162,22 +134,21 @@ Mem_space::tlb_flush_spaces(bool, Mem_space *, Mem_space *)
 
 IMPLEMENT inline
 Mem_space *
-Mem_space::current_mem_space(unsigned cpu) /// XXX: do not fix, deprecated, remove!
+Mem_space::current_mem_space(Cpu_number cpu) /// XXX: do not fix, deprecated, remove!
 {
   return _current.cpu(cpu);
 }
 
 PUBLIC inline
 bool
-Mem_space::set_attributes(Addr virt, unsigned page_attribs)
+Mem_space::set_attributes(Virt_addr virt, Attr page_attribs)
 {
-  Pdir::Iter i = _dir->walk(virt);
+  auto i = _dir->walk(virt);
 
-  if (!i.e->valid() || i.shift() != Config::PAGE_SHIFT)
-    return 0;
+  if (!i.is_valid())
+    return false;
 
-  i.e->del_attr(Page::MAX_ATTRIBS);
-  i.e->add_attr(page_attribs);
+  i.set_attribs(page_attribs);
   return true;
 }
 
@@ -197,61 +168,82 @@ Mem_space::dir_shutdown()
 {
   // free all page tables we have allocated for this address space
   // except the ones in kernel space which are always shared
-  _dir->destroy(Virt_addr(0),
-                Virt_addr(Kmem::mem_user_max), Pdir::Depth - 1,
+  _dir->destroy(Virt_addr(0UL),
+                Virt_addr(Kmem::mem_user_max-1), 0, Pdir::Depth,
+                Kmem_alloc::q_allocator(_quota));
+
+  // free all unshared page table levels for the kernel space
+  _dir->destroy(Virt_addr(Kmem::mem_user_max),
+                Virt_addr(~0UL), 0, Pdir::Super_level,
                 Kmem_alloc::q_allocator(_quota));
 
 }
 
 IMPLEMENT
 Mem_space::Status
-Mem_space::v_insert(Phys_addr phys, Vaddr virt, Vsize size,
-                    unsigned page_attribs, bool upgrade_ignore_size)
+Mem_space::v_insert(Phys_addr phys, Vaddr virt, Page_order size,
+                    Attr page_attribs)
 {
   // insert page into page table
 
   // XXX should modify page table using compare-and-swap
 
-  assert_kdb (size == Size(Config::PAGE_SIZE)
-              || size == Size(Config::SUPERPAGE_SIZE));
-  if (size == Size(Config::SUPERPAGE_SIZE))
-    {
-      assert (Cpu::have_superpages());
-      assert (virt.offset(Size(Config::SUPERPAGE_SIZE)) == 0);
-      assert (phys.offset(Size(Config::SUPERPAGE_SIZE)) == 0);
-    }
+  assert (cxx::get_lsb(Phys_addr(phys), size) == 0);
+  assert (cxx::get_lsb(Virt_addr(virt), size) == 0);
 
-  unsigned level = (size == Size(Config::SUPERPAGE_SIZE) ? (int)Pdir::Super_level : (int)Pdir::Depth);
-  unsigned shift = (size == Size(Config::SUPERPAGE_SIZE) ? Config::SUPERPAGE_SHIFT : Config::PAGE_SHIFT);
-  unsigned attrs = (size == Size(Config::SUPERPAGE_SIZE) ? (unsigned long)Pt_entry::Pse_bit : 0);
+  int level;
+  for (level = 0; level <= Pdir::Depth; ++level)
+    if (Page_order(Pdir::page_order_for_level(level)) <= size)
+      break;
 
-  Pdir::Iter i = _dir->walk(virt, level,
+  auto i = _dir->walk(virt, level, false,
                             Kmem_alloc::q_allocator(_quota));
 
-  if (EXPECT_FALSE(!i.e->valid() && i.shift() != shift))
+  if (EXPECT_FALSE(!i.is_valid() && i.level != level))
     return Insert_err_nomem;
 
-  if (EXPECT_FALSE(!upgrade_ignore_size
-       && i.e->valid() && (i.shift() != shift || i.addr() != phys.value())))
+  if (EXPECT_FALSE(i.is_valid()
+                   && (i.level != level || Phys_addr(i.page_addr()) != phys)))
     return Insert_err_exists;
 
-  if (i.e->valid())
+  if (i.is_valid())
     {
-      if (EXPECT_FALSE((i.e->raw() | page_attribs) == i.e->raw()))
-       return Insert_warn_exists;
+      if (EXPECT_FALSE(!i.add_attribs(page_attribs)))
+        return Insert_warn_exists;
 
-      i.e->add_attr(page_attribs);
-      page_protect (Addr(virt).value(), Size(size).value(), i.e->raw() & Page_all_attribs);
+      page_protect(Virt_addr::val(virt), Address(1) << Page_order::val(size),
+                   *i.pte & Page_all_attribs);
 
       return Insert_warn_attrib_upgrade;
     }
   else
     {
-      *i.e = Addr(phys).value() | Pt_entry::Valid | attrs | page_attribs;
-      page_map (Addr(phys).value(), Addr(virt).value(), Size(size).value(), page_attribs);
+      i.create_page(phys, page_attribs);
+      page_map(Virt_addr::val(phys), Virt_addr::val(virt),
+               Address(1) << Page_order::val(size), page_attribs);
 
       return Insert_ok;
     }
+
+}
+
+IMPLEMENT
+void
+Mem_space::v_set_access_flags(Vaddr virt, L4_fpage::Rights access_flags)
+{
+  auto i = _dir->walk(virt);
+
+  if (EXPECT_FALSE(!i.is_valid()))
+    return;
+
+  unsigned page_attribs = 0;
+
+  if (access_flags & L4_fpage::Rights::R())
+    page_attribs |= Page_referenced;
+  if (access_flags & L4_fpage::Rights::W())
+    page_attribs |= Page_dirty;
+
+  i.add_attribs(page_attribs);
 }
 
 /**
@@ -275,7 +267,7 @@ Mem_space::virt_to_phys(Address virt) const
  */
 PUBLIC inline NEEDS ["mem_layout.h"]
 Address
-Mem_space::pmem_to_phys (Address virt) const
+Mem_space::pmem_to_phys(Address virt) const
 {
   return Mem_layout::pmem_to_phys(virt);
 }
@@ -303,56 +295,47 @@ Mem_space::virt_to_phys_s0(void *a) const
 IMPLEMENT
 bool
 Mem_space::v_lookup(Vaddr virt, Phys_addr *phys,
-                    Size *size, unsigned *page_attribs)
+                    Page_order *order, Attr *page_attribs)
 {
-  Pdir::Iter i = _dir->walk(virt);
-  if (size) *size = Size(1UL << i.shift());
+  auto i = _dir->walk(virt);
+  if (order) *order = Page_order(i.page_order());
 
-  if (!i.e->valid())
+  if (!i.is_valid())
     return false;
 
-  if (phys) *phys = Addr(i.e->addr() & (~0UL << i.shift()));
-  if (page_attribs) *page_attribs = (i.e->raw() & Page_all_attribs);
+  if (phys) *phys = Phys_addr(i.page_addr());
+  if (page_attribs) *page_attribs = i.attribs();
 
   return true;
 }
 
 IMPLEMENT
-unsigned long
-Mem_space::v_delete(Vaddr virt, Vsize size,
-                    unsigned long page_attribs = Page_all_attribs)
+L4_fpage::Rights
+Mem_space::v_delete(Vaddr virt, Page_order size, L4_fpage::Rights page_attribs)
 {
-  unsigned ret;
+  assert (cxx::get_lsb(Virt_addr(virt), size) == 0);
 
-  // delete pages from page tables
-  assert (size == Size(Config::PAGE_SIZE) || size == Size(Config::SUPERPAGE_SIZE));
+  auto i = _dir->walk(virt);
 
-  if (size == Size(Config::SUPERPAGE_SIZE))
-    {
-      assert (Cpu::have_superpages());
-      assert (!virt.offset(Size(Config::SUPERPAGE_SIZE)));
-    }
-
-  Pdir::Iter i = _dir->walk(virt);
-
-  if (EXPECT_FALSE (! i.e->valid()))
-    return 0;
+  if (EXPECT_FALSE (! i.is_valid()))
+    return L4_fpage::Rights(0);
 
-  assert (! (i.e->raw() & Pt_entry::global())); // Cannot unmap shared ptables
+  assert (! (*i.pte & Pt_entry::global())); // Cannot unmap shared pages
 
-  ret = i.e->raw() & page_attribs;
+  L4_fpage::Rights ret = i.access_flags();
 
-  if (! (page_attribs & Page_user_accessible))
+  if (! (page_attribs & L4_fpage::Rights::R()))
     {
       // downgrade PDE (superpage) rights
-      i.e->del_attr(page_attribs);
-      page_protect (Addr(virt).value(), Size(size).value(), i.e->raw() & Page_all_attribs);
+      i.del_rights(page_attribs);
+      page_protect(Virt_addr::val(virt), Address(1) << Page_order::val(size),
+                   *i.pte & Page_all_attribs);
     }
   else
     {
       // delete PDE (superpage)
-      *i.e = 0;
-      page_unmap (Addr(virt).value(), Size(size).value());
+      i.clear();
+      page_unmap(Virt_addr::val(virt), Address(1) << Page_order::val(size));
     }
 
   return ret;
@@ -412,17 +395,17 @@ Mem_space::phys_dir()
 
 IMPLEMENT inline
 void
-Mem_space::page_map (Address, Address, Address, unsigned)
+Mem_space::page_map(Address, Address, Address, Attr)
 {}
 
 IMPLEMENT inline
 void
-Mem_space::page_protect (Address, Address, unsigned)
+Mem_space::page_protect(Address, Address, unsigned)
 {}
 
 IMPLEMENT inline
 void
-Mem_space::page_unmap (Address, Address)
+Mem_space::page_unmap(Address, Address)
 {}
 
 IMPLEMENT inline NEEDS["kmem.h", "logdefs.h"]
@@ -450,26 +433,52 @@ Mem_space::sync_kernel()
 {
   _dir->sync(Virt_addr(Mem_layout::User_max), Kmem::dir(),
              Virt_addr(Mem_layout::User_max),
-             Virt_addr(-Mem_layout::User_max), Pdir::Super_level,
+             Virt_size(-Mem_layout::User_max), Pdir::Super_level,
+             false,
              Kmem_alloc::q_allocator(_quota));
 }
 
 // --------------------------------------------------------------------
 IMPLEMENTATION [amd64]:
 
+#include "cpu.h"
+
 PUBLIC static inline
 Page_number
 Mem_space::canonize(Page_number v)
 {
-  if (v & Virt_addr(1UL << 48))
-    v = v | Virt_addr(~0UL << 48);
+  if (v & Page_number(Virt_addr(1UL << 48)))
+    v = v | Page_number(Virt_addr(~0UL << 48));
   return v;
 }
 
+PUBLIC static
+void
+Mem_space::init_page_sizes()
+{
+  add_page_size(Page_order(Config::PAGE_SHIFT));
+  if (Cpu::cpus.cpu(Cpu_number::boot_cpu()).superpages())
+    add_page_size(Page_order(21)); // 2MB
+
+  if (Cpu::cpus.cpu(Cpu_number::boot_cpu()).ext_8000_0001_edx() & (1UL<<26))
+    add_page_size(Page_order(30)); // 1GB
+}
+
 // --------------------------------------------------------------------
 IMPLEMENTATION [ia32 || ux]:
 
+#include "cpu.h"
+
 PUBLIC static inline
 Page_number
 Mem_space::canonize(Page_number v)
 { return v; }
+
+PUBLIC static
+void
+Mem_space::init_page_sizes()
+{
+  add_page_size(Page_order(Config::PAGE_SHIFT));
+  if (Cpu::cpus.cpu(Cpu_number::boot_cpu()).superpages())
+    add_page_size(Page_order(22)); // 4MB
+}
index d35081ee44aec62643877a48335bc4780508392b..d568ee4abf7f42a7531006d3a11f29712c2cfd55 100644 (file)
@@ -4,18 +4,11 @@ INTERFACE [ia32 || amd64 || ux]:
 #include "config.h"
 
 
-namespace Page
+EXTENSION class Page
 {
-  typedef Unsigned32 Attribs;
-
+public:
   enum Attribs_enum
   {
-    KERN_RW       = 0x00000002, ///< User No access
-    USER_RO       = 0x00000004, ///< User Read only
-    USER_RW       = 0x00000006, ///< User Read/Write
-    USER_RX       = 0x00000004, ///< User Read/Execute
-    USER_XO       = 0x00000004, ///< User Execute only
-    USER_RWX      = 0x00000006, ///< User Read/Write/Execute
     MAX_ATTRIBS   = 0x00000006,
     Cache_mask    = 0x00000018, ///< Cache attrbute mask
     CACHEABLE     = 0x00000000,
@@ -24,84 +17,258 @@ namespace Page
   };
 };
 
-EXTENSION class Pte_base {};
+EXTENSION class Pt_entry
+{
+private:
+  static Unsigned32 _cpu_global;
+  static unsigned _super_level;
+  static bool _have_superpages;
+};
+
+EXTENSION class Pte_ptr : private Pt_entry
+{
+public:
+  using Pt_entry::Super_level;
+};
 
 
 //---------------------------------------------------------------------------
 IMPLEMENTATION [ia32 || amd64 || ux]:
 
-PUBLIC inline
-Pte_base &
-Pte_base::operator = (Pte_base const &other)
+#include "atomic.h"
+
+bool Pt_entry::_have_superpages;
+unsigned  Pt_entry::_super_level;
+
+PUBLIC static inline
+void
+Pt_entry::have_superpages(bool yes)
 {
-  _raw = other.raw();
-  return *this;
+  _have_superpages = yes;
+  _super_level = yes ? Super_level : (Super_level + 1);
 }
 
+PUBLIC static inline
+unsigned
+Pt_entry::super_level()
+{ return _super_level; }
+
+
 PUBLIC inline
-Pte_base &
-Pte_base::operator = (Mword raw)
-{
-  _raw = raw;
-  return *this;
-}
+bool
+Pte_ptr::is_valid() const
+{ return *pte & Valid; }
 
+PUBLIC inline
+bool
+Pte_ptr::is_leaf() const
+{ return level == Pdir::Depth || (*pte & Pse_bit); }
+
+/**
+ * \pre is_leaf() == false
+ */
 PUBLIC inline
 Mword
-Pte_base::raw() const
+Pte_ptr::next_level() const
+{ return cxx::mask_lsb(*pte, (unsigned)Config::PAGE_SHIFT); }
+
+/**
+ * \pre cxx::get_lsb(phys_addr, Config::PAGE_SHIFT) == 0
+ */
+PUBLIC inline
+void
+Pte_ptr::set_next_level(Mword phys_addr)
+{ *pte = phys_addr | Valid | User | Writable; }
+
+PUBLIC inline
+void
+Pte_ptr::set_page(Mword phys, Mword attr)
 {
-  return _raw;
+  Mword v = phys | Valid | attr;
+  if (level < Pdir::Depth)
+    v |= Pse_bit;
+  *pte = v;
 }
 
 PUBLIC inline
-void
-Pte_base::add_attr(Mword attr)
+Pte_ptr const &
+Pte_ptr::operator ++ ()
 {
-  _raw |= attr;
+  ++pte;
+  return *this;
 }
 
+PUBLIC inline
+Mword
+Pte_ptr::page_addr() const
+{ return cxx::mask_lsb(*pte, Pdir::page_order_for_level(level)) & ~Mword(XD); }
+
+
 PUBLIC inline
 void
-Pte_base::del_attr(Mword attr)
+Pte_ptr::set_attribs(Page::Attr attr)
 {
-  _raw &= ~attr;
+  typedef L4_fpage::Rights R;
+  typedef Page::Type T;
+  typedef Page::Kern K;
+  Mword r = 0;
+  if (attr.rights & R::W()) r |= Writable;
+  if (attr.rights & R::U()) r |= User;
+  if (!(attr.rights & R::X())) r |= XD;
+  if (attr.type == T::Normal()) r |= Page::CACHEABLE;
+  if (attr.type == T::Buffered()) r |= Page::BUFFERED;
+  if (attr.type == T::Uncached()) r |= Page::NONCACHEABLE;
+  if (attr.kern & K::Global()) r |= global();
+  *pte = (*pte & ~(ATTRIBS_MASK | Page::Cache_mask)) | r;
 }
 
 PUBLIC inline
 void
-Pte_base::clear()
-{ _raw = 0; }
+Pte_ptr::create_page(Phys_mem_addr addr, Page::Attr attr)
+{
+  Mword r = (level < Pdir::Depth) ? (Mword)Pse_bit : 0;
+  typedef L4_fpage::Rights R;
+  typedef Page::Type T;
+  typedef Page::Kern K;
+  if (attr.rights & R::W()) r |= Writable;
+  if (attr.rights & R::U()) r |= User;
+  if (!(attr.rights & R::X())) r |= XD;
+  if (attr.type == T::Normal()) r |= Page::CACHEABLE;
+  if (attr.type == T::Buffered()) r |= Page::BUFFERED;
+  if (attr.type == T::Uncached()) r |= Page::NONCACHEABLE;
+  if (attr.kern & K::Global()) r |= global();
+  *pte = cxx::int_value<Phys_mem_addr>(addr) | r | Valid;
+}
 
 PUBLIC inline
-int
-Pte_base::valid() const
+Page::Attr
+Pte_ptr::attribs() const
 {
-  return _raw & Valid;
+  typedef L4_fpage::Rights R;
+  typedef Page::Type T;
+
+  Mword _raw = *pte;
+  R r = R::R();
+  if (_raw & Writable) r |= R::W();
+  if (_raw & User) r |= R::U();
+  if (!(_raw & XD)) r |= R::X();
+
+  T t;
+  switch (_raw & Page::Cache_mask)
+    {
+    default:
+    case Page::CACHEABLE:    t = T::Normal(); break;
+    case Page::BUFFERED:     t = T::Buffered(); break;
+    case Page::NONCACHEABLE: t = T::Uncached(); break;
+    }
+  // do not care for kernel special flags, as this is used for user
+  // level mappings
+  return Page::Attr(r, t);
 }
 
 PUBLIC inline
-int
-Pte_base::writable() const
+bool
+Pte_ptr::add_attribs(Page::Attr attr)
 {
-  return _raw & Writable;
+  typedef L4_fpage::Rights R;
+  unsigned long a = 0;
+
+  if (attr.rights & R::W())
+    a = Writable;
+
+  if (attr.rights & R::X())
+    a |= XD;
+
+  if (!a)
+    return false;
+
+  auto p = access_once(pte);
+  auto o = p;
+  p ^= XD;
+  p |= a;
+  p ^= XD;
+
+  if (o != p)
+    {
+      write_now(pte, p);
+      return true;
+    }
+  return false;
 }
 
 PUBLIC inline
-Address
-Pt_entry::pfn() const
+void
+Pte_ptr::add_attribs(Mword attr)
+{ *pte |= attr; }
+
+PUBLIC inline
+unsigned char
+Pte_ptr::page_order() const
+{ return Pdir::page_order_for_level(level); }
+
+PUBLIC inline NEEDS["atomic.h"]
+L4_fpage::Rights
+Pte_ptr::access_flags() const
 {
-  return _raw & Pfn;
+
+  if (!is_valid())
+    return L4_fpage::Rights(0);
+
+  L4_fpage::Rights r;
+  for (;;)
+    {
+      auto raw = *pte;
+
+      if (raw & Dirty)
+        r = L4_fpage::Rights::RW();
+      else if (raw & Referenced)
+        r = L4_fpage::Rights::R();
+      else
+        return L4_fpage::Rights(0);
+
+      if (mp_cas(pte, raw, raw & ~(Dirty | Referenced)))
+        return r;
+    }
 }
 
-Unsigned32 Pte_base::_cpu_global = Pte_base::L4_global;
+PUBLIC inline
+void
+Pte_ptr::clear()
+{ *pte = 0; }
 
 PUBLIC static inline
 void
-Pte_base::enable_global()
+Pte_ptr::write_back(void *, void *)
+{}
+
+PUBLIC static inline
+void
+Pte_ptr::write_back_if(bool)
+{}
+
+PUBLIC inline
+void
+Pte_ptr::del_attribs(Mword attr)
+{ *pte &= ~attr; }
+
+PUBLIC inline
+void
+Pte_ptr::del_rights(L4_fpage::Rights r)
 {
-  _cpu_global |= Pte_base::Cpu_global;
+  if (r & L4_fpage::Rights::W())
+    *pte &= ~Writable;
+
+  if (r & L4_fpage::Rights::X())
+    *pte |= XD;
 }
 
+Unsigned32 Pt_entry::_cpu_global = Pt_entry::L4_global;
+
+PUBLIC static inline
+void
+Pt_entry::enable_global()
+{ _cpu_global |= Cpu_global; }
+
 /**
  * Global entries are entries that are not automatically flushed when the
  * page-table base register is reloaded. They are intended for kernel data
@@ -110,10 +277,8 @@ Pte_base::enable_global()
  */
 PUBLIC static inline
 Unsigned32
-Pte_base::global()
-{
-  return _cpu_global;
-}
+Pt_entry::global()
+{ return _cpu_global; }
 
 
 //--------------------------------------------------------------------------
index fcf41bc2561ac994cef0750a782d787e7ce42bee..bdd4a429c065b3bf227538d2cf29f10fd8ae9f25 100644 (file)
@@ -48,11 +48,12 @@ void
 Startup::stage2()
 {
   // the logical ID of the boot CPU is always 0
-  enum { Boot_cpu = 0 };
   Kip_init::init();
   Kmem_alloc::init();
 
+  Cpu::cpus.cpu(Cpu_number::boot_cpu()).identify();
   // initialize initial page tables (also used for other CPUs later)
+  Mem_space::init_page_sizes();
   Kmem::init_mmu();
 
   if (Kernel_uart::init(Kernel_uart::Init_after_mmu))
@@ -60,13 +61,13 @@ Startup::stage2()
 
   // Initialize cpu-local data management and run constructors for CPU 0
   Per_cpu_data::init_ctors();
-  Per_cpu_data_alloc::alloc(Boot_cpu);
-  Per_cpu_data::run_ctors(Boot_cpu);
+  Per_cpu_data_alloc::alloc(Cpu_number::boot_cpu());
+  Per_cpu_data::run_ctors(Cpu_number::boot_cpu());
 
   // set frequency in KIP to that of the boot CPU
-  Kip_init::init_freq(Cpu::cpus.cpu(Boot_cpu));
+  Kip_init::init_freq(Cpu::cpus.cpu(Cpu_number::boot_cpu()));
 
-  bool use_io_apic = Io_apic::init(Boot_cpu);
+  bool use_io_apic = Io_apic::init(Cpu_number::boot_cpu());
   if (use_io_apic)
     {
       Config::apic = true;
@@ -81,14 +82,14 @@ Startup::stage2()
   Kernel_task::init(); // enables current_mem_space()
 
   // initialize initial TSS, GDT, IDT
-  Kmem::init_cpu(Cpu::cpus.cpu(Boot_cpu));
+  Kmem::init_cpu(Cpu::cpus.cpu(Cpu_number::boot_cpu()));
   Utcb_init::init();
   Idt::init();
-  Fpu::init(Boot_cpu);
+  Fpu::init(Cpu_number::boot_cpu());
   Apic::init();
-  Apic::apic.cpu(Boot_cpu).construct();
-  Ipi::init(Boot_cpu);
-  Timer::init(Boot_cpu);
+  Apic::apic.cpu(Cpu_number::boot_cpu()).construct();
+  Ipi::init(Cpu_number::boot_cpu());
+  Timer::init(Cpu_number::boot_cpu());
   int timer_irq = Timer::irq();
   if (use_io_apic)
     {
@@ -116,7 +117,7 @@ Startup::stage2()
     }
 
   Idt::set_vectors_run();
-  Timer::master_cpu(Boot_cpu);
+  Timer::master_cpu(Cpu_number::boot_cpu());
   Apic::check_still_getting_interrupts();
 //  Cpu::init_global_features();
 }
index d721c0171cc25321f260e68b8e52af600d1ed66c..aaa77ae089cb7ded87b64931cfdbf76efdb05c0e 100644 (file)
@@ -70,7 +70,7 @@ IMPLEMENTATION[svm]:
 DEFINE_PER_CPU Per_cpu<Svm> Svm::cpus(true);
 
 PUBLIC
-Svm::Svm(unsigned cpu)
+Svm::Svm(Cpu_number cpu)
 {
   Cpu &c = Cpu::cpus.cpu(cpu);
   _svm_enabled = false;
index d6fb0004eee6c24bcb70299deee98d2a8d6d3507..079f9999608bbb1b4580bdc26c159dca9150944e 100644 (file)
@@ -395,28 +395,21 @@ IMPLEMENT inline
 bool
 Thread::handle_sigma0_page_fault(Address pfa)
 {
-  size_t size;
+  Mem_space::Page_order size = mem_space()->largest_page_size(); // take a page size less than 16MB (1<<24)
+  auto f = mem_space()->fitting_sizes();
+  Virt_addr va = Virt_addr(pfa);
 
   // Check if mapping a superpage doesn't exceed the size of physical memory
-  if (Cpu::have_superpages()
-     // Some distributions do not allow to mmap below a certain threshold
-     // (like 64k on Ubuntu 8.04) so we cannot map a superpage at 0 if
-     // we're Fiasco-UX
-      && (!Config::Is_ux || !(pfa < Config::SUPERPAGE_SIZE)))
-    {
-      pfa &= Config::SUPERPAGE_MASK;
-      size = Config::SUPERPAGE_SIZE;
-    }
-  else
-    {
-      pfa &= Config::PAGE_MASK;
-      size = Config::PAGE_SIZE;
-    }
+  // Some distributions do not allow to mmap below a certain threshold
+  // (like 64k on Ubuntu 8.04) so we cannot map a superpage at 0 if
+  // we're Fiasco-UX
+  while (Config::Is_ux && (va < (Virt_addr(1) << size)))
+    size = f(--size);
+
+  va = cxx::mask_lsb(va, size);
 
-  return mem_space()->v_insert(Mem_space::Phys_addr(pfa), Mem_space::Addr(pfa),
-                               Mem_space::Size(size),
-                               Mem_space::Page_writable
-                               | Mem_space::Page_user_accessible)
+  return mem_space()->v_insert(Mem_space::Phys_addr(va), va, size,
+                               Page::Attr(L4_fpage::Rights::URWX()))
     != Mem_space::Insert_err_nomem;
 }
 
@@ -454,6 +447,25 @@ Thread::send_exception_arch(Trap_state *ts)
 }
 
 
+//----------------------------------------------------------------------------
+IMPLEMENTATION [(vmx || svm) && (ia32 || amd64)]:
+
+#include "vmx.h"
+#include "svm.h"
+
+IMPLEMENT inline NEEDS["vmx.h", "svm.h"]
+void
+Thread::arch_init_vcpu_state(Vcpu_state *vcpu_state, bool ext)
+{
+  if (!ext)
+    return;
+
+  if (Vmx::cpus.current().vmx_enabled())
+    Vmx::cpus.current().init_vmcs_infos(vcpu_state);
+
+  // currently we do nothing for SVM here
+}
+
 //----------------------------------------------------------------------------
 IMPLEMENTATION [ia32 || amd64]:
 
@@ -727,9 +739,9 @@ Thread::check_io_bitmap_delimiter_fault(Trap_state *ts)
       Mem_space::Status result =
        mem_space()->v_insert(
            Mem_space::Phys_addr(mem_space()->virt_to_phys_s0((void*)Kmem::io_bitmap_delimiter_page())),
-           Mem_space::Addr::create(Mem_layout::Io_bitmap + Mem_layout::Io_port_max / 8),
-           Mem_space::Size::create(Config::PAGE_SIZE),
-           Pt_entry::global());
+           Virt_addr(Mem_layout::Io_bitmap + Mem_layout::Io_port_max / 8),
+           Mem_space::Page_order(Config::PAGE_SHIFT),
+           Page::Attr(Page::Rights::R(), Page::Type::Normal(), Page::Kern::Global()));
 
       switch (result)
        {
@@ -808,7 +820,7 @@ Thread::sys_control_arch(Utcb *)
 //---------------------------------------------------------------------------
 IMPLEMENTATION [(ia32 | amd64) & (debug | kdb) & !mp]:
 
-PRIVATE static inline unsigned Thread::dbg_find_cpu() { return 0; }
+PRIVATE static inline Cpu_number Thread::dbg_find_cpu() { return Cpu_number::boot_cpu(); }
 
 //---------------------------------------------------------------------------
 IMPLEMENTATION [(ia32 | amd64) & (debug | kdb) & mp]:
@@ -816,15 +828,15 @@ IMPLEMENTATION [(ia32 | amd64) & (debug | kdb) & mp]:
 #include "apic.h"
 
 PRIVATE static inline NEEDS["apic.h"]
-unsigned
+Cpu_number
 Thread::dbg_find_cpu()
 {
   unsigned long phys_cpu = Apic::get_id();
-  unsigned log_cpu = Apic::find_cpu(phys_cpu);
-  if (log_cpu == ~0U)
+  Cpu_number log_cpu = Apic::find_cpu(phys_cpu);
+  if (log_cpu == Cpu_number::nil())
     {
       printf("Trap on unknown CPU phys_id=%lx\n", phys_cpu);
-      log_cpu = 0;
+      log_cpu = Cpu_number::boot_cpu();
     }
   return log_cpu;
 }
index cb302280e736cbd7ff85735461438780d14f30ac..4cd29f9b79bc552c818ccce981889af319d2a644 100644 (file)
@@ -14,7 +14,7 @@ PUBLIC static inline int Timer::irq() { return -1; }
 
 IMPLEMENT
 void
-Timer::init(unsigned)
+Timer::init(Cpu_number)
 {
   Apic::timer_assign_irq_vector(Config::Apic_timer_vector);
 
@@ -50,9 +50,8 @@ static
 void
 Timer::update_one_shot(Unsigned64 wakeup)
 {
-  //unsigned cpu = current_cpu();
   Unsigned32 apic;
-  Unsigned64 now = Kip::k()->clock; //Cpu::cpus.cpu(cpu).time_us();
+  Unsigned64 now = Kip::k()->clock;
   if (EXPECT_FALSE (wakeup <= now))
     // already expired
     apic = 1;
index 192a84f9fbd00186d06d29bb7689c3832393f937..e6d0086642fd6491a0dfac4eb1ccd8c924bd15b0 100644 (file)
@@ -19,7 +19,8 @@ IMPLEMENT inline NEEDS ["config.h", "cpu.h", "globals.h", "kip.h"]
 Unsigned64
 Timer::system_clock()
 {
-  if (!current_cpu() && Config::Kip_timer_uses_rdtsc)
+  if (current_cpu() == Cpu_number::boot_cpu()
+      && Config::Kip_timer_uses_rdtsc)
     Kip::k()->clock = Cpu::cpus.cpu(_cpu).time_us();
 
   return Kip::k()->clock;
@@ -27,13 +28,13 @@ Timer::system_clock()
 
 IMPLEMENT inline NEEDS ["config.h", "cpu.h", "globals.h", "kip.h"]
 void
-Timer::update_system_clock(unsigned cpu)
+Timer::update_system_clock(Cpu_number cpu)
 {
-  if (cpu != 0)
+  if (cpu != Cpu_number::boot_cpu())
     return;
 
   if (Config::Kip_timer_uses_rdtsc)
-    Kip::k()->clock = Cpu::cpus.cpu(0).time_us();
+    Kip::k()->clock = Cpu::cpus.cpu(Cpu_number::boot_cpu()).time_us();
   else
     Kip::k()->clock += Config::Scheduler_granularity;
 }
index 55217b36a23fb1218117ee9bf162de1a34dd3953..6b05ec1907a2f3a1d7f85537c961ffa3d1de7d0f 100644 (file)
@@ -7,7 +7,7 @@ IMPLEMENTATION[{ia32,amd64}-pit_timer]:
 
 IMPLEMENT
 void
-Timer::init(unsigned)
+Timer::init(Cpu_number)
 {
   printf("Using the PIT (i8254) on IRQ %d for scheduling\n", irq());
 
index 92d7392ed803051d30419c0cea0dbafcb501050a..03643f99d1c8e85ba13f423a4d3a530cc3bb78db 100644 (file)
@@ -17,7 +17,7 @@ unsigned Timer::irq_mode()
 
 IMPLEMENT
 void
-Timer::init(unsigned)
+Timer::init(Cpu_number)
 {
   printf("Using the RTC on IRQ %d (%sHz) for scheduling\n", 8,
 #ifdef CONFIG_SLOW_RTC
index f0211efba1d0786e366eed633ab39f563b4183e8..ff38e566532d9df6234632a63a89440e1f058eb2 100644 (file)
@@ -18,7 +18,7 @@ extern "C"
 void
 thread_timer_interrupt_slow(void)
 {
-  if (!current_cpu())
+  if (current_cpu() == Cpu_number::boot_cpu())
     {
       if (Config::esc_hack)
        {
index 603151cdcd8b5566b8f82a1765bc2614264feef8..c31c9415440a12b6d33f169c736a84f31bd3d0e2 100644 (file)
@@ -5,12 +5,12 @@ IMPLEMENTATION [ia32 || amd64]:
 
 IMPLEMENT
 void
-Timer_tick::setup(unsigned)
+Timer_tick::setup(Cpu_number)
 {}
 
 IMPLEMENT
 void
-Timer_tick::enable(unsigned)
+Timer_tick::enable(Cpu_number)
 {
   Apic::timer_enable_irq();
   Apic::irq_ack();
@@ -18,7 +18,7 @@ Timer_tick::enable(unsigned)
 
 IMPLEMENT
 void
-Timer_tick::disable(unsigned)
+Timer_tick::disable(Cpu_number)
 {
   Apic::timer_disable_irq();
 }
index 88893a5bd5a63e30301ad012233cd130c05034d4..8eed8ce50f201dc92b5ebf4ac5525cac67b766f8 100644 (file)
@@ -54,7 +54,7 @@ _tramp_mp_entry32:
        mov %edx, %edi
        mov $0xc0000080, %ecx
        rdmsr
-       bts $8,%eax
+       or  $0x900,%eax // LME+NXE
        wrmsr
        mov %edi, %edx
        
index 60408ad7d107a74aa033f2eebcd58fb99e38fa0e..a35b1856c5da958ff06287ddaf361e3f0bf8c9d9 100644 (file)
@@ -5,7 +5,7 @@ INTERFACE:
 class Vm : public Task
 {
 public:
-  explicit Vm(Ram_quota *q) : Task(q) {}
+  explicit Vm(Ram_quota *q) : Task(q, Caps::mem() | Caps::obj()) {}
   int resume_vcpu(Context *, Vcpu_state *, bool) = 0;
 };
 
@@ -18,13 +18,43 @@ struct Vm_allocator
 template<typename VM>
 Kmem_slab_t<VM> Vm_allocator<VM>::a("Vm");
 
+
+// ------------------------------------------------------------------------
+INTERFACE [obj_space_virt]:
+
+#include "obj_space_phys_util.h"
+
+EXTENSION class Vm : Obj_space_phys<Vm>
+{
+public:
+  typedef Obj_space_phys<Vm> Vm_obj_space;
+  using Task::ram_quota;
+  static Ram_quota *ram_quota(Vm_obj_space const *obj_sp)
+  { return static_cast<Vm const *>(obj_sp)->ram_quota(); }
+
+  bool v_lookup(Obj_space::V_pfn const &virt, Obj_space::Phys_addr *phys,
+                Obj_space::Page_order *size, Obj_space::Attr *attribs);
+
+  L4_fpage::Rights v_delete(Obj_space::V_pfn virt, Order size,
+                            L4_fpage::Rights page_attribs);
+  Obj_space::Status v_insert(Obj_space::Phys_addr phys,
+                             Obj_space::V_pfn const &virt,
+                             Order size,
+                             Obj_space::Attr page_attribs);
+
+  Obj_space::Capability lookup(Cap_index virt);
+  Obj_space::V_pfn obj_map_max_address() const;
+  void caps_free();
+};
+
+
 // ------------------------------------------------------------------------
 IMPLEMENTATION:
 
-PUBLIC inline virtual
+PUBLIC inline
 Page_number
-Vm::map_max_address() const
-{ return Page_number::create(1UL << (MWORD_BITS - Mem_space::Page_shift)); }
+Vm::mem_space_map_max_address() const
+{ return Page_number(1UL << (MWORD_BITS - Mem_space::Page_shift)); }
 
 PUBLIC static
 template< typename VM >
@@ -47,3 +77,70 @@ PROTECTED static inline
 bool
 Vm::is_64bit()
 { return true; }
+
+
+//----------------------------------------------------------------------------
+IMPLEMENTATION [obj_space_virt]:
+
+//
+// Utilities for map<Generic_obj_space> and unmap<Generic_obj_space>
+//
+
+IMPLEMENT
+void __attribute__((__flatten__))
+Vm::caps_free()
+{ Vm_obj_space::caps_free(); }
+
+IMPLEMENT
+inline
+bool __attribute__((__flatten__))
+Vm::v_lookup(Obj_space::V_pfn const &virt, Obj_space::Phys_addr *phys,
+             Obj_space::Page_order *size, Obj_space::Attr *attribs)
+{ return Vm_obj_space::v_lookup(virt, phys, size, attribs); }
+
+IMPLEMENT
+inline __attribute__((__flatten__))
+Obj_space::Capability __attribute__((__flatten__))
+Vm::lookup(Cap_index virt)
+{ return Vm_obj_space::lookup(virt); }
+
+IMPLEMENT
+inline __attribute__((__flatten__))
+L4_fpage::Rights __attribute__((__flatten__))
+Vm::v_delete(Obj_space::V_pfn virt, Obj_space::Page_order size,
+             L4_fpage::Rights page_attribs)
+{ return Vm_obj_space::v_delete(virt, size, page_attribs); }
+
+IMPLEMENT
+inline __attribute__((__flatten__))
+Obj_space::Status __attribute__((__flatten__))
+Vm::v_insert(Obj_space::Phys_addr phys, Obj_space::V_pfn const &virt,
+             Obj_space::Page_order size, Obj_space::Attr page_attribs)
+{ return (Obj_space::Status)Vm_obj_space::v_insert(phys, virt, size, page_attribs); }
+
+IMPLEMENT
+inline __attribute__((__flatten__))
+Obj_space::V_pfn
+Vm::obj_map_max_address() const
+{ return Vm_obj_space::obj_map_max_address(); }
+
+// ------------------------------------------------------------------------------
+IMPLEMENTATION [obj_space_virt && debug]:
+
+PUBLIC static inline
+Vm *
+Vm::get_space(Vm_obj_space *base)
+{ return static_cast<Vm*>(base); }
+
+PUBLIC virtual
+Vm::Vm_obj_space::Entry *
+Vm::jdb_lookup_cap(Cap_index index)
+{ return Vm_obj_space::jdb_lookup_cap(index); }
+
+// ------------------------------------------------------------------------------
+IMPLEMENTATION [obj_space_virt && !debug]:
+
+PUBLIC static inline
+Vm *
+Vm::get_space(Vm_obj_space *)
+{ return 0; }
index b06b8d39a2963caae8ca40b02cb72b006f79868c..2f5f47888af9e6a98ed66ca87fda66ea8115bfff 100644 (file)
@@ -5,6 +5,7 @@ IMPLEMENTATION [vmx && svm]:
 #include "vm_svm.h"
 #include "vmx.h"
 #include "vm_vmx.h"
+#include "vm_vmx_ept.h"
 
 PRIVATE static inline
 template< typename VM >
@@ -28,11 +29,15 @@ Vm *
 Vm_factory::create(Ram_quota *quota, int *err)
 {
   *err = -L4_err::ENomem;
-  if (Svm::cpus.cpu(current_cpu()).svm_enabled())
+  if (Svm::cpus.current().svm_enabled())
     return allocate<Vm_svm>(quota);
-  if (Vmx::cpus.cpu(current_cpu()).vmx_enabled())
-    return allocate<Vm_vmx>(quota);
-
+  if (Vmx::cpus.current().vmx_enabled())
+    {
+      if (Vmx::cpus.current().info.procbased_ctls2.allowed(Vmx::PRB2_enable_ept))
+        return allocate<Vm_vmx_ept>(quota);
+      else
+        return allocate<Vm_vmx>(quota);
+    }
   *err = L4_err::ENodev;
   return 0;
 }
index f89770bdbebf510276d3b33ff64f243f5af88f16..ed2e4dbf833c2ef77d2dc6e63eb234a856e11ced 100644 (file)
@@ -10,8 +10,12 @@ class Vm_svm : public Vm
 private:
   static void resume_vm_svm(Mword phys_vmcb, Vcpu_state *regs)
     asm("resume_vm_svm") __attribute__((__regparm__(3)));
-  Unsigned8 _asid[Config::Max_num_cpus];
-  Unsigned32 _asid_generation[Config::Max_num_cpus];
+
+  typedef Per_cpu_array<Unsigned8> Asid_array;
+  typedef Per_cpu_array<Unsigned32> Asid_version_array;
+
+  Asid_array _asid;
+  Asid_version_array _asid_generation;
 
   enum
   {
@@ -107,13 +111,13 @@ Vm_svm::get_vm_cr3(Vmcb *v)
   //    So why is the code still here? Well, QEmu isn't so picky about the
   //    bits in the PDPE and it thus works there...
   assert_opt (this);
-  Address vm_cr3 = static_cast<Mem_space*>(this)->dir()->walk(Virt_addr(0), 0).e->addr();
+  Address vm_cr3 = static_cast<Mem_space*>(this)->dir()->walk(Virt_addr(0), 0).next_level();
   if (EXPECT_FALSE(!vm_cr3))
     {
       // force allocation of new secondary page-table level
       static_cast<Mem_space*>(this)->dir()
-                 ->walk(Virt_addr(0), 1, Kmem_alloc::q_allocator(ram_quota()));
-      vm_cr3 = static_cast<Mem_space*>(this)->dir()->walk(Virt_addr(0), 0).e->addr();
+        ->walk(Virt_addr(0), 1, false, Kmem_alloc::q_allocator(ram_quota()));
+      vm_cr3 = static_cast<Mem_space*>(this)->dir()->walk(Virt_addr(0), 0).next_level();
     }
 
   if (EXPECT_FALSE(vm_cr3 >= 1UL << 32))
@@ -160,8 +164,8 @@ PUBLIC
 Vm_svm::Vm_svm(Ram_quota *q)
   : Vm(q)
 {
-  memset(_asid, 0, sizeof(_asid));
-  memset(_asid_generation, 0, sizeof(_asid_generation));
+  memset(&_asid, 0, sizeof(_asid));
+  memset(&_asid_generation, 0, sizeof(_asid_generation));
 }
 
 PUBLIC inline
index 586a4a381503dbeb6bc36048cd00e2651872e359..cf686a38998efbba5e73e76fe968e5a0317df02f 100644 (file)
@@ -7,9 +7,9 @@ INTERFACE [vmx]:
 
 class Vmcs;
 
-class Vm_vmx : public Vm
+class Vm_vmx_b : public Vm
 {
-private:
+protected:
   static unsigned long resume_vm_vmx(Vcpu_state *regs)
     asm("resume_vm_vmx") __attribute__((__regparm__(3)));
 
@@ -18,7 +18,15 @@ private:
     EFER_LME = 1 << 8,
     EFER_LMA = 1 << 10,
   };
+};
+
+template<typename X>
+class Vm_vmx_t : public Vm_vmx_b
+{
+};
 
+class Vm_vmx : public Vm_vmx_t<Vm_vmx>
+{
 };
 
 //----------------------------------------------------------------------------
@@ -34,9 +42,16 @@ IMPLEMENTATION [vmx]:
 #include "idt.h"
 
 
+PUBLIC inline
+Vm_vmx_b::Vm_vmx_b(Ram_quota *q) : Vm(q)
+{}
+
+PUBLIC inline template<typename X>
+Vm_vmx_t<X>::Vm_vmx_t(Ram_quota *q) : Vm_vmx_b(q)
+{}
+
 PUBLIC
-Vm_vmx::Vm_vmx(Ram_quota *q)
-  : Vm(q)
+Vm_vmx::Vm_vmx(Ram_quota *q) : Vm_vmx_t<Vm_vmx>(q)
 {}
 
 PUBLIC inline
@@ -61,60 +76,57 @@ Vm_vmx::operator delete (void *ptr)
 
 PRIVATE static inline
 void *
-Vm_vmx::field_offset(void *vmcs, unsigned field)
+Vm_vmx_b::field_ptr(void *vmcs, unsigned field)
 {
-  return (void *)((char *)vmcs
-                          + ((field >> 13) * 4 + ((field >> 10) & 3) + 1) * 0x80);
+  return Vmx_user_info::Fo_table::field(vmcs, field);
 }
 
 PRIVATE static inline
 unsigned
-Vm_vmx::field_width(unsigned field)
+Vm_vmx_b::field_width(unsigned field)
 {
   static const char widths[4] = { 2, 8, 4, sizeof(Mword) };
   return widths[field >> 13];
 }
 
 
-PRIVATE inline
+PROTECTED inline
 template<typename T>
 Vmx_info::Flags<T>
-Vm_vmx::load(unsigned field, void *vmcs, Vmx_info::Bit_defs<T> const &m)
+Vm_vmx_b::load(unsigned field, void *vmcs, Vmx_info::Bit_defs<T> const &m)
 {
   T res = m.apply(read<T>(vmcs, field));
   Vmx::vmwrite(field, res);
   return Vmx_info::Flags<T>(res);
 }
 
-PRIVATE inline
+PROTECTED inline
 void
-Vm_vmx::load(unsigned field_first, unsigned field_last, void *vmcs)
+Vm_vmx_b::load(unsigned field_first, unsigned field_last, void *vmcs)
 {
   for (; field_first <= field_last; field_first += 2)
     load(field_first, vmcs);
 }
 
-PRIVATE inline static
+PRIVATE inline NEEDS[Vm_vmx_b::field_ptr] static
 template< typename T >
 T
-Vm_vmx::_internal_read(void *vmcs, unsigned field)
+Vm_vmx_b::_internal_read(void *vmcs, unsigned field)
 {
-  vmcs = field_offset(vmcs, field);
-  return *((T *)vmcs + ((field >> 1) & 0xff));
+  return *(T *)field_ptr(vmcs, field);
 }
 
-PRIVATE inline static
+PRIVATE inline NEEDS[Vm_vmx_b::field_ptr] static
 template< typename T >
 void
-Vm_vmx::_internal_write(void *vmcs, unsigned field, T value)
+Vm_vmx_b::_internal_write(void *vmcs, unsigned field, T value)
 {
-  vmcs = field_offset(vmcs, field);
-  *((T*)vmcs + ((field >> 1) & 0xff)) = value;
+  *(T*)field_ptr(vmcs, field) = value;
 }
 
-PRIVATE inline
+PROTECTED inline NEEDS[Vm_vmx_b::_internal_read]
 void
-Vm_vmx::load(unsigned field, void *vmcs)
+Vm_vmx_b::load(unsigned field, void *vmcs)
 {
   switch (field >> 13)
     {
@@ -125,9 +137,9 @@ Vm_vmx::load(unsigned field, void *vmcs)
     }
 }
 
-PRIVATE inline
+PROTECTED inline NEEDS[Vm_vmx_b::_internal_write]
 void
-Vm_vmx::store(unsigned field, void *vmcs)
+Vm_vmx_b::store(unsigned field, void *vmcs)
 {
   switch (field >> 13)
     {
@@ -138,18 +150,18 @@ Vm_vmx::store(unsigned field, void *vmcs)
     }
 }
 
-PRIVATE inline
+PROTECTED inline
 void
-Vm_vmx::store(unsigned field_first, unsigned field_last, void *vmcs)
+Vm_vmx_b::store(unsigned field_first, unsigned field_last, void *vmcs)
 {
   for (; field_first <= field_last; field_first += 2)
     store(field_first, vmcs);
 }
 
-PRIVATE inline static
+PROTECTED inline NEEDS[Vm_vmx_b::_internal_write] static
 template< typename T >
 void
-Vm_vmx::write(void *vmcs, unsigned field, T value)
+Vm_vmx_b::write(void *vmcs, unsigned field, T value)
 {
   switch (field >> 13)
     {
@@ -160,10 +172,10 @@ Vm_vmx::write(void *vmcs, unsigned field, T value)
     }
 }
 
-PRIVATE inline static
+PROTECTED inline NEEDS[Vm_vmx_b::_internal_read] static
 template< typename T >
 T
-Vm_vmx::read(void *vmcs, unsigned field)
+Vm_vmx_b::read(void *vmcs, unsigned field)
 {
   switch (field >> 13)
     {
@@ -175,10 +187,27 @@ Vm_vmx::read(void *vmcs, unsigned field)
   return 0;
 }
 
+PUBLIC inline
+void
+Vm_vmx::load_vm_memory(void *src)
+{
+  if (sizeof(long) > sizeof(int))
+    {
+      if (read<Mword>(src, 0x2806) & EFER_LME)
+        Vmx::vmwrite(0x6802, (Mword)phys_dir());
+      else
+       WARN("VMX: No, not possible\n");
+    }
+  else
+    {
+      // for 32bit we can just load the Vm pdbr
+      Vmx::vmwrite(0x6802, (Mword)phys_dir());
+    }
+}
 
-PRIVATE
+PRIVATE template<typename X>
 void
-Vm_vmx::load_guest_state(unsigned cpu, void *src)
+Vm_vmx_t<X>::load_guest_state(Cpu_number cpu, void *src)
 {
   Vmx &vmx = Vmx::cpus.cpu(cpu);
 
@@ -231,18 +260,7 @@ Vm_vmx::load_guest_state(unsigned cpu, void *src)
   // write natural-width fields
   load<Mword>(0x6800, src, vmx.info.cr0_defs);
 
-  if (sizeof(long) > sizeof(int))
-    {
-      if (read<Mword>(src, 0x2806) & EFER_LME)
-        Vmx::vmwrite(0x6802, (Mword)phys_dir());
-      else
-       WARN("VMX: No, not possible\n");
-    }
-  else
-    {
-      // for 32bit we can just load the Vm pdbr
-      Vmx::vmwrite(0x6802, (Mword)phys_dir());
-    }
+  static_cast<X*>(this)->load_vm_memory(src);
 
   load<Mword>(0x6804, src, vmx.info.cr4_defs);
   load(0x6806, 0x6826, src);
@@ -295,9 +313,9 @@ Vm_vmx::load_guest_state(unsigned cpu, void *src)
 }
 
 
-PRIVATE
+PROTECTED
 void
-Vm_vmx::store_guest_state(unsigned cpu, void *dest)
+Vm_vmx_b::store_guest_state(Cpu_number cpu, void *dest)
 {
   // read 16-bit fields
   store(0x800, 0x80e, dest);
@@ -335,9 +353,9 @@ Vm_vmx::store_guest_state(unsigned cpu, void *dest)
   store(0x6804, 0x6822, dest);
 }
 
-PRIVATE
+PROTECTED
 void
-Vm_vmx::store_exit_info(unsigned cpu, void *dest)
+Vm_vmx_b::store_exit_info(Cpu_number cpu, void *dest)
 {
   (void)cpu;
   // read 64-bit fields, that is a EPT pf thing
@@ -360,18 +378,18 @@ Vm_vmx::store_exit_info(unsigned cpu, void *dest)
   store(0x6400, 0x640a, dest);
 }
 
-PRIVATE
+PROTECTED
 void
-Vm_vmx::dump(void *v, unsigned f, unsigned t)
+Vm_vmx_b::dump(void *v, unsigned f, unsigned t)
 {
   for (; f <= t; f += 2)
     printf("%04x: VMCS: %16lx   V: %16lx\n",
           f, Vmx::vmread<Mword>(f), read<Mword>(v, f));
 }
 
-PRIVATE
+PROTECTED
 void
-Vm_vmx::dump_state(void *v)
+Vm_vmx_b::dump_state(void *v)
 {
   dump(v, 0x0800, 0x080e);
   dump(v, 0x0c00, 0x0c0c);
@@ -385,9 +403,9 @@ Vm_vmx::dump_state(void *v)
   dump(v, 0x6c00, 0x6c16);
 }
 
-PRIVATE inline NOEXPORT
+PROTECTED inline template<typename X>
 int
-Vm_vmx::do_resume_vcpu(Context *ctxt, Vcpu_state *vcpu, void *vmcs_s)
+Vm_vmx_t<X>::do_resume_vcpu(Context *ctxt, Vcpu_state *vcpu, void *vmcs_s)
 {
   assert (cpu_lock.test());
 
@@ -397,7 +415,7 @@ Vm_vmx::do_resume_vcpu(Context *ctxt, Vcpu_state *vcpu, void *vmcs_s)
   assert (!(Cpu::get_ds() & (1 << 2)));
   assert (!(Cpu::get_es() & (1 << 2)));
 
-  unsigned cpu = current_cpu();
+  Cpu_number const cpu = current_cpu();
   Vmx &v = Vmx::cpus.cpu(cpu);
 
   if (!v.vmx_enabled())
@@ -427,17 +445,19 @@ Vm_vmx::do_resume_vcpu(Context *ctxt, Vcpu_state *vcpu, void *vmcs_s)
 #endif
 
   // increment our refcount, and drop it at the end automatically
-  Ref_ptr<Vm_vmx> pin_myself(this);
+  Ref_ptr<Vm_vmx_b> pin_myself(this);
 
   // set volatile host state
+  Vmx::vmwrite<Mword>(Vmx::F_host_cr0, Cpu::get_cr0());
   Vmx::vmwrite<Mword>(Vmx::F_host_cr3, Cpu::get_pdbr()); // host_area.cr3
 
+  // host cr0 und cr4
   load_guest_state(cpu, vmcs_s);
 
   Unsigned16 ldt = Cpu::get_ldt();
 
   // set guest CR2
-  asm volatile("mov %0, %%cr2" : : "r" (read<Mword>(vmcs_s, Vmx::F_guest_cr2)));
+  asm volatile("mov %0, %%cr2" : : "r" (read<Mword>(vmcs_s, Vmx::F_sw_guest_cr2)));
 
   unsigned long ret = resume_vm_vmx(vcpu);
   // vmread error?
@@ -448,7 +468,7 @@ Vm_vmx::do_resume_vcpu(Context *ctxt, Vcpu_state *vcpu, void *vmcs_s)
     {
       Mword cpu_cr2;
       asm volatile("mov %%cr2, %0" : "=r" (cpu_cr2));
-      write(vmcs_s, Vmx::F_guest_cr2, cpu_cr2);
+      write(vmcs_s, Vmx::F_sw_guest_cr2, cpu_cr2);
     }
 
   Cpu::set_ldt(ldt);
@@ -466,16 +486,24 @@ Vm_vmx::do_resume_vcpu(Context *ctxt, Vcpu_state *vcpu, void *vmcs_s)
   store_guest_state(cpu, vmcs_s);
   store_exit_info(cpu, vmcs_s);
 
-  if ((read<Unsigned32>(vmcs_s, Vmx::F_exit_reason) & 0xffff) == 1)
-    return 1;
+  Unsigned32 reason = read<Unsigned32>(vmcs_s, Vmx::F_exit_reason) & 0xffff;
+  switch (reason)
+    {
+    case 1: // IRQ
+      return 1;
+    case 48: // EPT violation
+      store(0x2400, vmcs_s); // Guest phys
+      store(0x640a, vmcs_s); // Guest linear
+      break;
+    }
 
   vcpu->state &= ~(Vcpu_state::F_traps | Vcpu_state::F_user_mode);
   return 0;
 }
 
-PUBLIC
+PUBLIC template<typename X> inline
 int
-Vm_vmx::resume_vcpu(Context *ctxt, Vcpu_state *vcpu, bool user_mode)
+Vm_vmx_t<X>::resume_vcpu(Context *ctxt, Vcpu_state *vcpu, bool user_mode)
 {
   (void)user_mode;
   assert_kdb (user_mode);
diff --git a/kernel/fiasco/src/kern/ia32/vm_vmx_ept.cpp b/kernel/fiasco/src/kern/ia32/vm_vmx_ept.cpp
new file mode 100644 (file)
index 0000000..ebcf4c1
--- /dev/null
@@ -0,0 +1,365 @@
+INTERFACE [vmx]:
+
+#include "vm_vmx.h"
+#include "ptab_base.h"
+
+class Vm_vmx_ept : public Vm_vmx_t<Vm_vmx_ept>
+{
+private:
+  //typedef Mem_space::Attr Attr;
+  //typedef Mem_space::Vaddr Vaddr;
+  //typedef Mem_space::Vsize Vsize;
+  //using Mem_space::Phys_addr;
+  //using Mem_space::Page_order;
+
+  class Epte_ptr
+  {
+    Unsigned64 *e;
+
+    void set(Unsigned64 v);
+
+  public:
+    typedef Mem_space::Attr Attr;
+
+    unsigned char level;
+    Epte_ptr() = default;
+    Epte_ptr(Unsigned64 *e, unsigned char level) : e(e), level(level) {}
+
+    bool is_valid() const { return *e & 7; }
+    bool is_leaf() const { return (*e & (1 << 7)) || level == 3; }
+    Unsigned64 next_level() const
+    { return cxx::get_lsb(cxx::mask_lsb(*e, 12), 52); }
+
+    void clear() { set(0); }
+
+    unsigned char page_order() const;
+    Unsigned64 page_addr() const;
+    Attr attribs() const
+    {
+      typedef L4_fpage::Rights R;
+      typedef Page::Type T;
+
+      auto raw = access_once(e);
+
+      R r = R::UR();
+      if (raw & 2) r |= R::W();
+      if (raw & 4) r |= R::X();
+
+      T t;
+      switch (raw & 0x38)
+        {
+        case (0 << 3): t = T::Uncached(); break;
+        case (1 << 3): t = T::Buffered(); break;
+        default:
+        case (6 << 3): t = T::Normal(); break;
+        }
+
+      return Attr(r, t);
+    }
+
+    bool add_attribs(Page::Attr attr)
+    {
+      typedef L4_fpage::Rights R;
+
+      if (attr.rights & R::WX())
+        {
+          Unsigned64 a = 0;
+          if (attr.rights & R::W())
+            a = 2;
+
+          if (attr.rights & R::X())
+            a |= 4;
+
+          auto p = access_once(e);
+          auto o = p;
+          p |= a;
+          if (o != p)
+            {
+              write_now(e, p);
+              return true;
+            }
+        }
+      return false;
+    }
+
+    void set_next_level(Unsigned64 phys)
+    { set(phys | 7); }
+
+    void write_back_if(bool) const {}
+    static void write_back(void *, void*) {}
+
+    L4_fpage::Rights access_flags() const
+    {
+      return L4_fpage::Rights(0);
+    }
+
+    void del_rights(L4_fpage::Rights r)
+    {
+      Unsigned64 dr = 0;
+      if (r & L4_fpage::Rights::W())
+        dr = 2;
+
+      if (r & L4_fpage::Rights::X())
+        dr |= 4;
+
+      if (dr)
+        *e &= ~dr;
+    }
+
+    void create_page(Phys_mem_addr addr, Page::Attr attr)
+    {
+      typedef L4_fpage::Rights R;
+      typedef Page::Type T;
+
+      Unsigned64 r = (level < 3) ? (Unsigned64)(1 << 7) : 0;
+      r |= 1; // R
+      if (attr.rights & R::W()) r |= 2;
+      if (attr.rights & R::X()) r |= 4;
+
+      if (attr.type == T::Normal())   r |= 6 << 3;
+      if (attr.type == T::Buffered()) r |= 1 << 3;
+      if (attr.type == T::Uncached()) r |= 0;
+
+      set(cxx::int_value<Phys_mem_addr>(addr) | r);
+    }
+
+  };
+
+  typedef Ptab::Tupel< Ptab::Traits<Unsigned64, 39, 9, false>,
+                       Ptab::Traits<Unsigned64, 30, 9, true>,
+                       Ptab::Traits<Unsigned64, 21, 9, true>,
+                       Ptab::Traits<Unsigned64, 12, 9, true> >::List Ept_traits;
+
+  typedef Ptab::Shift<Ept_traits, 12>::List Ept_traits_vpn;
+  typedef Ptab::Page_addr_wrap<Page_number, 12> Ept_va_vpn;
+  typedef Ptab::Base<Epte_ptr, Ept_traits_vpn, Ept_va_vpn> Ept;
+
+  Mword _ept_phys;
+  Ept *_ept;
+};
+
+// -------------------------------------------------------------------------
+IMPLEMENTATION [vmx && 64bit]:
+
+IMPLEMENT inline
+void
+Vm_vmx_ept::Epte_ptr::set(Unsigned64 v) { write_now(e, v); }
+
+// -------------------------------------------------------------------------
+IMPLEMENTATION [vmx && !64bit]:
+
+IMPLEMENT inline
+void
+Vm_vmx_ept::Epte_ptr::set(Unsigned64 v)
+{
+  // this assumes little endian!
+  union T
+  {
+    Unsigned64 l;
+    Unsigned32 u[2];
+  };
+
+  T *t = (T*)e;
+
+  write_now(&t->u[0], Unsigned32(0));
+  write_now(&t->u[1], Unsigned32(v >> 32));
+  write_now(&t->u[0], Unsigned32(v));
+}
+
+// -------------------------------------------------------------------------
+IMPLEMENTATION [vmx]:
+
+IMPLEMENT inline
+unsigned char
+Vm_vmx_ept::Epte_ptr::page_order() const
+{ return Vm_vmx_ept::Ept::page_order_for_level(level); }
+
+IMPLEMENT inline
+Unsigned64
+Vm_vmx_ept::Epte_ptr::page_addr() const
+{ return cxx::get_lsb(cxx::mask_lsb(*e, Vm_vmx_ept::Ept::page_order_for_level(level)), 52); }
+
+static Mem_space::Fit_size::Size_array __ept_ps;
+
+PUBLIC
+Mem_space::Fit_size
+Vm_vmx_ept::mem_space_fitting_sizes() const
+{ return Mem_space::Fit_size(__ept_ps); }
+
+PUBLIC static
+void
+Vm_vmx_ept::add_page_size(Mem_space::Page_order o)
+{
+  add_global_page_size(o);
+  for (Mem_space::Page_order c = o; c < __ept_ps.size(); ++c)
+    __ept_ps[c] = o;
+}
+
+PUBLIC
+bool
+Vm_vmx_ept::v_lookup(Mem_space::Vaddr virt, Mem_space::Phys_addr *phys,
+                     Mem_space::Page_order *order, Mem_space::Attr *page_attribs)
+{
+  auto i = _ept->walk(virt);
+  if (order) *order = Mem_space::Page_order(i.page_order());
+
+  if (!i.is_valid())
+    return false;
+
+  // FIXME: we may get a problem on 32 bit systems and using more than 4G ram
+  if (phys) *phys = Mem_space::Phys_addr(i.page_addr());
+  if (page_attribs) *page_attribs = i.attribs();
+
+  return true;
+}
+PUBLIC
+Mem_space::Status
+Vm_vmx_ept::v_insert(Mem_space::Phys_addr phys, Mem_space::Vaddr virt,
+                     Mem_space::Page_order size, Mem_space::Attr page_attribs)
+{
+  // insert page into page table
+
+  // XXX should modify page table using compare-and-swap
+
+  assert (cxx::get_lsb(Mem_space::Phys_addr(phys), size) == 0);
+  assert (cxx::get_lsb(Virt_addr(virt), size) == 0);
+
+  int level;
+  for (level = 0; level <= Ept::Depth; ++level)
+    if (Mem_space::Page_order(Ept::page_order_for_level(level)) <= size)
+      break;
+
+  auto i = _ept->walk(virt, level, false,
+                      Kmem_alloc::q_allocator(ram_quota()));
+
+  if (EXPECT_FALSE(!i.is_valid() && i.level != level))
+    return Mem_space::Insert_err_nomem;
+
+  if (EXPECT_FALSE(i.is_valid()
+                   && (i.level != level || Mem_space::Phys_addr(i.page_addr()) != phys)))
+    return Mem_space::Insert_err_exists;
+
+  if (i.is_valid())
+    {
+      if (EXPECT_FALSE(!i.add_attribs(page_attribs)))
+        return Mem_space::Insert_warn_exists;
+
+      return Mem_space::Insert_warn_attrib_upgrade;
+    }
+  else
+    {
+      i.create_page(phys, page_attribs);
+      return Mem_space::Insert_ok;
+    }
+
+}
+
+PUBLIC
+L4_fpage::Rights
+Vm_vmx_ept::v_delete(Mem_space::Vaddr virt, Mem_space::Page_order size,
+                     L4_fpage::Rights page_attribs)
+{
+  (void)size;
+  assert (cxx::get_lsb(Virt_addr(virt), size) == 0);
+
+  auto i = _ept->walk(virt);
+
+  if (EXPECT_FALSE (! i.is_valid()))
+    return L4_fpage::Rights(0);
+
+  L4_fpage::Rights ret = i.access_flags();
+
+  if (! (page_attribs & L4_fpage::Rights::R()))
+    {
+      // downgrade PDE (superpage) rights
+      i.del_rights(page_attribs);
+    }
+  else
+    {
+      // delete PDE (superpage)
+      i.clear();
+    }
+
+  return ret;
+}
+
+PUBLIC
+void
+Vm_vmx_ept::v_set_access_flags(Mem_space::Vaddr, L4_fpage::Rights)
+{}
+
+PUBLIC inline
+void *
+Vm_vmx_ept::operator new (size_t size, void *p) throw()
+{
+  (void)size;
+  assert (size == sizeof (Vm_vmx_ept));
+  return p;
+}
+
+PUBLIC
+void
+Vm_vmx_ept::operator delete (void *ptr)
+{
+  Vm_vmx_ept *t = reinterpret_cast<Vm_vmx_ept*>(ptr);
+  allocator<Vm_vmx_ept>()->q_free(t->ram_quota(), ptr);
+}
+
+PUBLIC inline
+Vm_vmx_ept::Vm_vmx_ept(Ram_quota *q) : Vm_vmx_t<Vm_vmx_ept>(q) {}
+
+PUBLIC
+Vm_vmx_ept::~Vm_vmx_ept()
+{
+  if (_ept)
+    {
+      _ept->destroy(Virt_addr(0UL), Virt_addr(~0UL), 0, Ept::Depth,
+                    Kmem_alloc::q_allocator(ram_quota()));
+      Kmem_alloc::allocator()->q_free(ram_quota(), Config::PAGE_SHIFT, _ept);
+      _ept = 0;
+      _ept_phys = 0;
+    }
+}
+
+PUBLIC inline
+bool
+Vm_vmx_ept::initialize()
+{
+  void *b;
+  if (EXPECT_FALSE(!(b = Kmem_alloc::allocator()
+         ->q_alloc(ram_quota(), Config::PAGE_SHIFT))))
+    return false;
+
+  _ept = static_cast<Ept*>(b);
+  _ept->clear(false);  // initialize to zero
+  _ept_phys = Mem_layout::pmem_to_phys(_ept);
+  return true; // success
+
+}
+
+PUBLIC inline
+void
+Vm_vmx_ept::load_vm_memory(void *src)
+{
+  load(0x6802, src);
+  Vmx::vmwrite(0x201a, _ept_phys | 6 | (3 << 3));
+}
+
+PUBLIC static
+void
+Vm_vmx_ept::init()
+{
+#if 0
+  printf("VMX: init page sizes\n");
+  if (!Vmx::cpus.cpu(Cpu_number::boot_cpu()).vmx_enabled())
+    return;
+#endif
+  add_page_size(Mem_space::Page_order(12));
+//  add_page_size(Mem_space::Page_order(21));
+//  add_page_size(Mem_space::Page_order(30));
+}
+
+STATIC_INITIALIZE(Vm_vmx_ept);
+
+
+
index 183483c0f8e1b3f615948efddd5187fd0d110a39..a194c370136c7865af82dff3b5d55a0211673655 100644 (file)
@@ -27,15 +27,15 @@ Vmem_alloc::page_alloc(void *address, Zero_fill zf, unsigned mode)
     return 0;
 
   // insert page into master page table
-  Pdir::Iter e = Kmem::kdir->walk(Virt_addr(address), 100,
-                                  pdir_alloc(Kmem_alloc::allocator()));
-  if (EXPECT_FALSE(e.e->valid()))
+  auto e = Kmem::kdir->walk(Virt_addr(address), Pdir::Depth,
+                            false, pdir_alloc(Kmem_alloc::allocator()));
+  if (EXPECT_FALSE(e.is_valid()))
     {
       kdb_ke("page_alloc: address already mapped");
       goto error;
     }
 
-  if (e.shift() != Config::PAGE_SHIFT)
+  if (e.level != Pdir::Depth)
     goto error;
 
   if (zf == ZERO_FILL)
@@ -43,13 +43,10 @@ Vmem_alloc::page_alloc(void *address, Zero_fill zf, unsigned mode)
 
   page = Mem_layout::pmem_to_phys((Address)vpage);
 
-  *e.e = page | Pt_entry::Writable | Pt_entry::Dirty
-    | Pt_entry::Valid | Pt_entry::Referenced | Pt_entry::global();
+  e.set_page(page, Pt_entry::Writable | Pt_entry::Dirty
+                   | Pt_entry::Referenced
+                   | Pt_entry::global() | (mode & User ? (unsigned)Pt_entry::User : 0));
   page_map (address, 0, zf, page);
-
-  if (mode & User)
-    e.e->add_attr(Pt_entry::User);
-
   return address;
 
 error:
index 0e0a89f8ce7928fcc65f6135d88bc9980d660c02..6f0104707484826e4ffb4b6bdf4613dd9d6b6a0a 100644 (file)
@@ -1,12 +1,13 @@
 INTERFACE [vmx]:
 
 #include "per_cpu_data.h"
+#include <cassert>
 #include <cstdio>
+#include <cstring>
 
 class Vmx_info
 {
 public:
-  static bool nested_paging() { return false; }
 
   template<typename T>
   class Bit_defs
@@ -18,11 +19,7 @@ public:
   public:
     Bit_defs() {}
     Bit_defs(T _or, T _and) : _or(_or), _and(_and) {}
-#if 0
-    template<typename T2>
-    explicit Bit_defs(Bit_defs<T2> const &o)
-    : _or(o.must_be_one()), _and(o.may_be_one()) {}
-#endif
+
     T must_be_one() const { return _or; }
     T may_be_one() const { return _and; }
 
@@ -44,6 +41,12 @@ public:
     }
 
   public:
+    void relax(unsigned char bit)
+    {
+      _or &= ~(T(1) << T(bit));
+      _and |= T(1) << T(bit);
+    }
+
     void enforce(unsigned char bit, bool value = true)
     { enforce_bits((T)1 << (T)bit, value); }
 
@@ -96,10 +99,71 @@ public:
   Bit_defs_32 procbased_ctls2;
 
   Unsigned64 ept_vpid_cap;
-  Unsigned64 true_pinbased_ctls;
-  Unsigned64 true_procbased_ctls;
-  Unsigned64 true_exit_ctls;
-  Unsigned64 true_entry_ctls;
+  Unsigned64 max_index;
+  Unsigned32 pinbased_ctls_default1;
+  Unsigned32 procbased_ctls_default1;
+  Unsigned32 exit_ctls_default1;
+  Unsigned32 entry_ctls_default1;
+};
+
+
+struct Vmx_user_info
+{
+  struct Fo_table
+  {
+    unsigned char offsets[32];
+    static unsigned char const master_offsets[32];
+
+    enum
+    {
+      Foi_size = 4
+    };
+
+    static void *field(void *b, unsigned vm_field)
+    {
+      return (char*)b + master_offsets[vm_field >> 10] * 64
+             + ((vm_field & 0x3ff) << master_offsets[Foi_size + (vm_field >> 13)]);
+    }
+
+    void init()
+    { memcpy(offsets, master_offsets, sizeof(offsets)); }
+
+    static void check_offsets(unsigned max_idx)
+    {
+      for (unsigned t1 = 0; t1 < 3; ++t1)
+        for (unsigned w1 = 0; w1 < 4; ++w1)
+          for (unsigned t2 = 0; t2 < 3; ++t2)
+            for (unsigned w2 = 0; w2 < 4; ++w2)
+              if (t1 != t2 || w1 != w2)
+                {
+                  unsigned s1 = ((t1 << 10) | (w1 << 13));
+                  unsigned s2 = ((t2 << 10) | (w2 << 13));
+                  unsigned e1 = s1 | max_idx;
+                  unsigned e2 = s2 | max_idx;
+                  assert (field(0, s1) > field(0, e2)
+                          || field(0, s2) > field(0, e1));
+                  (void) s1; (void) s2; (void) e1; (void) e2;
+                }
+    }
+  };
+
+  Unsigned64 basic;
+  Vmx_info::Bit_defs_32 pinbased;
+  Vmx_info::Bit_defs_32 procbased;
+  Vmx_info::Bit_defs_32 exit;
+  Vmx_info::Bit_defs_32 entry;
+  Unsigned64 misc;
+  Unsigned64 cr0_or;
+  Unsigned64 cr0_and;
+  Unsigned64 cr4_or;
+  Unsigned64 cr4_and;
+  Unsigned64 vmcs_field_info;
+  Vmx_info::Bit_defs_32 procbased2;
+  Unsigned64 ept_vpid_cap;
+  Unsigned32 pinbased_dfl1;
+  Unsigned32 procbased_dfl1;
+  Unsigned32 exit_dfl1;
+  Unsigned32 entry_dfl1;
 };
 
 INTERFACE:
@@ -140,6 +204,7 @@ public:
     F_entry_ctls         = 0x4012,
     F_entry_msr_load_cnt = 0x4014,
     F_entry_int_info     = 0x4016,
+
     F_entry_exc_error_code = 0x4018,
     F_entry_insn_len     = 0x401a,
     F_proc_based_ctls_2  = 0x401e,
@@ -151,7 +216,8 @@ public:
 
     F_host_sysenter_cs   = 0x4c00,
 
-    F_guest_cr2          = 0x6830,
+    F_sw_guest_cr2       = 0x683e,
+
 
     F_host_cr0           = 0x6c00,
     F_host_cr3           = 0x6c02,
@@ -164,6 +230,7 @@ public:
     F_host_sysenter_esp  = 0x6c10,
     F_host_sysenter_eip  = 0x6c12,
     F_host_rip           = 0x6c16,
+
   };
 
   enum Pin_based_ctls
@@ -187,7 +254,6 @@ public:
     PRB2_enable_ept      = 1,
     PRB2_enable_vpid     = 5,
   };
-
 };
 
 INTERFACE [vmx]:
@@ -252,22 +318,36 @@ PUBLIC
 void
 Vmx_info::init()
 {
+  bool ept = false;
   basic = Cpu::rdmsr(0x480);
   pinbased_ctls = Cpu::rdmsr(0x481);
+  pinbased_ctls_default1 = pinbased_ctls.must_be_one();
   procbased_ctls = Cpu::rdmsr(0x482);
+  procbased_ctls_default1 = procbased_ctls.must_be_one();
   exit_ctls = Cpu::rdmsr(0x483);
+  exit_ctls_default1 = exit_ctls.must_be_one();
   entry_ctls = Cpu::rdmsr(0x484);
+  entry_ctls_default1 = entry_ctls.must_be_one();
   misc = Cpu::rdmsr(0x485);
 
   cr0_defs = Bit_defs<Mword>(Cpu::rdmsr(0x486), Cpu::rdmsr(0x487));
   cr4_defs = Bit_defs<Mword>(Cpu::rdmsr(0x488), Cpu::rdmsr(0x489));
 
+  max_index = Cpu::rdmsr(0x48a);
+
+  assert ((Vmx::F_sw_guest_cr2 & 0x3ff) > max_index);
+  max_index = Vmx::F_sw_guest_cr2 & 0x3ff;
+  Vmx_user_info::Fo_table::check_offsets(max_index);
+
   if (basic & (1ULL << 55))
     {
-      true_pinbased_ctls = Cpu::rdmsr(0x48d);
-      true_procbased_ctls = Cpu::rdmsr(0x48e);
-      true_exit_ctls = Cpu::rdmsr(0x48f);
-      true_entry_ctls = Cpu::rdmsr(0x490);
+      // do not use the true pin-based ctls because user-level then needs to
+      // be aware of the fact that it has to set bits 1, 2, and 4 to default 1
+      if (0) pinbased_ctls = Cpu::rdmsr(0x48d);
+
+      procbased_ctls = Cpu::rdmsr(0x48e);
+      exit_ctls = Cpu::rdmsr(0x48f);
+      entry_ctls = Cpu::rdmsr(0x490);
     }
 
   if (0)
@@ -287,16 +367,34 @@ Vmx_info::init()
 
   if (procbased_ctls.allowed(31))
     {
+      procbased_ctls.enforce(31, true);
+
       procbased_ctls2 = Cpu::rdmsr(0x48b);
       if (procbased_ctls2.allowed(1))
        ept_vpid_cap = Cpu::rdmsr(0x48c);
 
+
       // we disable VPID so far, need to handle virtualize it in Fiasco,
       // as done for AMDs ASIDs
       procbased_ctls2.enforce(Vmx::PRB2_enable_vpid, false);
 
-      // no EPT support yet
-      procbased_ctls2.enforce(Vmx::PRB2_enable_ept, false);
+      // EPT only in conjunction with unrestricted guest !!!
+      if (procbased_ctls2.allowed(Vmx::PRB2_enable_ept)
+          && procbased_ctls2.allowed(7))
+        {
+          ept = true;
+          procbased_ctls2.enforce(Vmx::PRB2_enable_ept, true);
+
+          // unrestricted guest allows PE and PG to be 0
+          cr0_defs.relax(0);  // PE
+          cr0_defs.relax(31); // PG
+          procbased_ctls2.enforce(7);
+        }
+      else
+        { // disallow EPT and unrestricted guest otherwise
+          procbased_ctls2.enforce(Vmx::PRB2_enable_ept, false);
+          procbased_ctls2.enforce(7, false);
+        }
     }
   else
     procbased_ctls2 = 0;
@@ -307,7 +405,7 @@ Vmx_info::init()
   // host-state is 64bit or not
   exit_ctls.enforce(9, sizeof(long) > sizeof(int));
 
-  if (!nested_paging()) // needs to be per VM
+  if (!ept) // needs to be per VM
     {
       // always enable paging
       cr0_defs.enforce(31);
@@ -338,10 +436,6 @@ Vmx_info::dump(const char *tag) const
   cr4_defs.print("cr4_fixed");
   procbased_ctls2.print("procbased_ctls2");
   printf("ept_vpid_cap         = %16llx\n", ept_vpid_cap);
-  printf("true_pinbased_ctls   = %16llx\n", true_pinbased_ctls);
-  printf("true_procbased_ctls  = %16llx\n", true_procbased_ctls);
-  printf("true_exit_ctls       = %16llx\n", true_exit_ctls);
-  printf("true_entry_ctls      = %16llx\n", true_entry_ctls);
 }
 
 PRIVATE static inline
@@ -382,13 +476,13 @@ Vmx::vmwrite(Mword field, T value)
 }
 
 PUBLIC
-Vmx::Vmx(unsigned cpu)
+Vmx::Vmx(Cpu_number cpu)
   : _vmx_enabled(false), _has_vpid(false)
 {
   Cpu &c = Cpu::cpus.cpu(cpu);
   if (!c.vmx())
     {
-      if (!cpu)
+      if (cpu == Cpu_number::boot_cpu())
         WARNX(Info, "VMX: Not supported\n");
       return;
     }
@@ -408,7 +502,7 @@ Vmx::Vmx(unsigned cpu)
     {
       if (!(feature & Msr_ia32_feature_control_vmx_outside_SMX))
        {
-         if (!cpu)
+         if (cpu == Cpu_number::boot_cpu())
             WARNX(Info, "VMX: CPU has VMX support but it is disabled\n");
          return;
        }
@@ -417,13 +511,13 @@ Vmx::Vmx(unsigned cpu)
     c.wrmsr(feature | Msr_ia32_feature_control_vmx_outside_SMX | Msr_ia32_feature_control_lock,
             MSR_IA32_FEATURE_CONTROL);
 
-  if (!cpu)
+  if (cpu == Cpu_number::boot_cpu())
     WARNX(Info, "VMX: Enabled\n");
 
   info.init();
 
   // check for EPT support
-  if (!cpu)
+  if (cpu == Cpu_number::boot_cpu())
     {
       if (info.procbased_ctls2.allowed(1))
         WARNX(Info, "VMX:  EPT supported\n");
@@ -476,7 +570,7 @@ Vmx::Vmx(unsigned cpu)
   asm volatile("vmxon %0" : :"m"(_vmxon_base_pa):);
   _vmx_enabled = true;
 
-  if (cpu == 0)
+  if (cpu == Cpu_number::boot_cpu())
     WARNX(Info, "VMX: initialized\n");
 
   Mword eflags;
@@ -514,7 +608,10 @@ Vmx::Vmx(unsigned cpu)
   vmwrite(F_host_sysenter_eip, entry_sys_fast_ipc_c);
 
   if (c.features() & FEAT_PAT && info.exit_ctls.allowed(19))
-    vmwrite(F_host_ia32_pat, Cpu::rdmsr(MSR_PAT));
+    {
+      vmwrite(F_host_ia32_pat, Cpu::rdmsr(MSR_PAT));
+      info.exit_ctls.enforce(19, true);
+    }
   else
     {
       // We have no proper PAT support, so disallow PAT load store for
@@ -524,7 +621,10 @@ Vmx::Vmx(unsigned cpu)
     }
 
   if (info.exit_ctls.allowed(21)) // Load IA32_EFER
-    vmwrite(F_host_ia32_efer, Cpu::rdmsr(MSR_EFER));
+    {
+      vmwrite(F_host_ia32_efer, Cpu::rdmsr(MSR_EFER));
+      info.exit_ctls.enforce(21, true);
+    }
   else
     {
       // We have no EFER load for host, so disallow EFER load store for
@@ -539,8 +639,8 @@ Vmx::Vmx(unsigned cpu)
     // do not allow Load IA32_PERF_GLOBAL_CTRL on entry
     info.entry_ctls.enforce(13, false);
 
-  vmwrite(F_host_cr0, info.cr0_defs.apply(Cpu::get_cr0()));
-  vmwrite(F_host_cr4, info.cr4_defs.apply(Cpu::get_cr4()));
+  vmwrite(F_host_cr0, Cpu::get_cr0());
+  vmwrite(F_host_cr4, Cpu::get_cr4());
 
   Pseudo_descriptor pseudo;
   c.get_gdt()->get(&pseudo);
@@ -561,6 +661,62 @@ Vmx::Vmx(unsigned cpu)
 
 }
 
+/*
+ * VMCS field offset table:
+ *  0h -  2h: 3 offsets for 16bit fields:
+ *            0: Control fields, 1: read-only fields, 2: guest state
+ *            all offsets in 64byte granules relative to the start of the VMCS
+ *        3h: Reserved
+ *  4h -  7h: Index shift values for 16bit, 64bit, 32bit, and natural width fields
+ *  8h -  Ah: 3 offsets for 64bit fields
+ *  Bh -  Fh: Reserved
+ * 10h - 12h: 3 offsets for 32bit fields
+ * 13h - 17h: Reserved
+ * 18h - 1Ah: 3 offsets for natural width fields
+ *       1Bh: Reserved
+ *       1Ch: Offset of first VMCS field
+ *       1Dh: Full size of VMCS fields
+ * 1Eh - 1Fh: Reserved
+ *
+ */
+unsigned char const Vmx_user_info::Fo_table::master_offsets[32] =
+{
+    64 / 64,  768 / 64, 1472 / 64, 0,   0, 2, 1, 2,
+   128 / 64,  832 / 64, 1536 / 64, 0,   0, 0, 0, 0,
+   384 / 64, 1088 / 64, 1792 / 64, 0,   0, 0, 0, 0,
+   512 / 64, 1216 / 64, 1920 / 64, 0,   64 / 64, 2112 / 64, 0, 0,
+};
+
+PUBLIC inline
+void
+Vmx::init_vmcs_infos(void *vcpu_state) const
+{
+  Vmx_user_info *i = reinterpret_cast<Vmx_user_info*>((char*)vcpu_state + 0x200);
+  i->basic = info.basic;
+  i->pinbased = info.pinbased_ctls;
+  i->procbased = info.procbased_ctls;
+  i->exit = info.exit_ctls;
+  i->entry = info.entry_ctls;
+  i->misc = info.misc;
+  i->cr0_or = info.cr0_defs.must_be_one();
+  i->cr0_and = info.cr0_defs.may_be_one();
+  i->cr4_or = info.cr4_defs.must_be_one();
+  i->cr4_and = info.cr4_defs.may_be_one();
+  i->vmcs_field_info = info.max_index;
+  i->procbased2 = info.procbased_ctls2;
+  i->ept_vpid_cap = info.ept_vpid_cap;
+  i->pinbased_dfl1 = info.pinbased_ctls_default1;
+  i->procbased_dfl1 = info.procbased_ctls_default1;
+  i->exit_dfl1 = info.exit_ctls_default1;
+  i->entry_dfl1 = info.entry_ctls_default1;
+
+  Vmx_user_info::Fo_table *infos = reinterpret_cast<Vmx_user_info::Fo_table *>((char*)vcpu_state + 0x420);
+  Unsigned32 *inf = reinterpret_cast<Unsigned32 *>((char*)vcpu_state + 0x410);
+  inf[0] = F_sw_guest_cr2;
+  infos->init();
+}
+
+
 PUBLIC
 void *
 Vmx::kernel_vmcs() const
index fdc15f1568ba2b09e29fa9e679ddd57fe2d11610..842ea7fe3337881f46be465a8d4d31b69ae187e4 100644 (file)
@@ -63,7 +63,7 @@ Icu_h_base::deref_irq(L4_msg_tag *tag, Utcb const *utcb)
 
   register Context *const c_thread = ::current();
   register Space *const c_space = c_thread->space();
-  unsigned char irq_rights = 0;
+  L4_fpage::Rights irq_rights = L4_fpage::Rights(0);
   irq = Kobject::dcast<Irq*>(c_space->lookup_local(bind_irq.obj_index(), &irq_rights));
 
   if (!irq)
@@ -72,7 +72,7 @@ Icu_h_base::deref_irq(L4_msg_tag *tag, Utcb const *utcb)
       return 0;
     }
 
-  if (EXPECT_FALSE(!(irq_rights & L4_fpage::X)))
+  if (EXPECT_FALSE(!(irq_rights & L4_fpage::Rights::X())))
     {
       *tag = Kobject_iface::commit_result(-L4_err::EPerm);
       return 0;
@@ -124,7 +124,7 @@ Icu_h<REAL_ICU>::icu_get_msi_info(Mword msi, Utcb *out)
 PUBLIC template< typename REAL_ICU >
 inline
 L4_msg_tag
-Icu_h<REAL_ICU>::icu_invoke(L4_obj_ref, Mword /*rights*/,
+Icu_h<REAL_ICU>::icu_invoke(L4_obj_ref, L4_fpage::Rights /*rights*/,
                             Syscall_frame *f,
                             Utcb const *utcb, Utcb *out)
 {
@@ -189,7 +189,7 @@ Icu_h<REAL_ICU>::icu_invoke(L4_obj_ref, Mword /*rights*/,
 PUBLIC
 template< typename REAL_ICU >
 L4_msg_tag
-Icu_h<REAL_ICU>::kinvoke(L4_obj_ref ref, Mword rights,
+Icu_h<REAL_ICU>::kinvoke(L4_obj_ref ref, L4_fpage::Rights rights,
                          Syscall_frame *f,
                          Utcb const *in, Utcb *out)
 {
index 13121c621bb86055a685281cce2015fd8fd5366b..bb8f2214c5e58172089b7e7f44a27fb44602a3c6 100644 (file)
@@ -17,11 +17,15 @@ class Generic_io_space
 public:
   static char const * const name;
 
-  typedef Page_number Addr;
-  typedef Page_count Size;
-  typedef Page_number Phys_addr;
   typedef void Reap_list;
 
+  typedef Port_number V_pfn;
+  typedef Port_number V_pfc;
+  typedef Port_number Phys_addr;
+  typedef Order Page_order;
+  typedef L4_fpage::Rights Attr;
+  typedef L4_fpage::Rights Rights;
+
   enum
   {
     Need_insert_tlb_flush = 0,
@@ -35,6 +39,16 @@ public:
     Identity_map = 1,
   };
 
+  struct Fit_size
+  {
+    Page_order operator () (Page_order o) const
+    {
+      return o >= Order(Map_superpage_shift)
+             ? Order(Map_superpage_shift)
+             : Order(0);
+    }
+  };
+
   // We'd rather like to use a "using Mem_space::Status" declaration here,
   // but that wouldn't make the enum values accessible as
   // Generic_io_space::Insert_ok and so on.
@@ -47,28 +61,45 @@ public:
     Insert_err_exists          ///< A mapping already exists at the target addr
   };
 
-  enum Page_attribs
-  {
-    Page_writable = Mem_space::Page_writable,
-    Page_user_accessible = Mem_space::Page_user_accessible,
-    Page_references = 0,
-    Page_all_attribs = Page_writable | Page_user_accessible
-  };
+  static V_pfn map_max_address()
+  { return V_pfn(Map_max_address); }
+
+  static Phys_addr page_address(Phys_addr o, Page_order s)
+  { return cxx::mask_lsb(o, s); }
 
-  static Addr map_max_address()
-  { return Addr(Map_max_address); }
+  static Phys_addr subpage_address(Phys_addr addr, V_pfc offset)
+  { return addr | offset; }
 
-  static Address superpage_size()
-  { return Map_superpage_size; }
+  static V_pfn subpage_offset(V_pfn addr, Page_order size)
+  { return cxx::get_lsb(addr, size); }
 
-  static bool has_superpages()
-  { return true; }
+  static Mdb_types::Pfn to_pfn(V_pfn p)
+  { return Mdb_types::Pfn(cxx::int_value<V_pfn>(p)); }
 
-  static Phys_addr page_address(Phys_addr o, Size s)
-  { return o.trunc(s); }
+  static V_pfn to_virt(Mdb_types::Pfn p)
+  { return V_pfn(cxx::int_value<Mdb_types::Pfn>(p)); }
 
-  static Phys_addr subpage_address(Phys_addr addr, Size offset)
-  { return addr | offset; }
+  static Mdb_types::Pcnt to_pcnt(Page_order s)
+  { return Mdb_types::Pcnt(cxx::int_value<V_pfc>(V_pfc(1) << s)); }
+
+  static Page_order to_order(Mdb_types::Order p)
+  { return Page_order(cxx::int_value<Mdb_types::Order>(p) + Config::PAGE_SHIFT); }
+
+  static V_pfc to_size(Page_order p)
+  { return V_pfc(1) << p; }
+
+
+  FIASCO_SPACE_VIRTUAL
+  Status v_insert(Phys_addr phys, V_pfn virt, Order size, Attr page_attribs);
+
+  FIASCO_SPACE_VIRTUAL
+  bool v_lookup(V_pfn virt, Phys_addr *phys = 0, Page_order *order = 0,
+                Attr *attribs = 0);
+  virtual
+  bool v_fabricate(V_pfn address, Phys_addr *phys, Page_order *order,
+                   Attr *attribs = 0);
+  FIASCO_SPACE_VIRTUAL
+  Rights v_delete(V_pfn virt, Order size, Rights page_attribs);
 
 private:
   // DATA
@@ -99,31 +130,21 @@ IMPLEMENTATION [io]:
 #include "paging.h"
 
 
-PUBLIC template< typename SPACE >
-static inline
-Mword
-Generic_io_space<SPACE>::xlate_flush(unsigned char rights)
+PUBLIC template< typename SPACE > inline
+typename Generic_io_space<SPACE>::Fit_size
+Generic_io_space<SPACE>::fitting_sizes() const
 {
-  if (rights)
-    return Page_all_attribs;
-  else
-    return 0;
+  return Fit_size();
 }
 
 PUBLIC template< typename SPACE >
 static inline
-Mword
-Generic_io_space<SPACE>::is_full_flush(unsigned char rights)
+bool
+Generic_io_space<SPACE>::is_full_flush(L4_fpage::Rights rights)
 {
   return rights;
 }
 
-PUBLIC template< typename SPACE >
-static inline
-Mword
-Generic_io_space<SPACE>::xlate_flush_result(Mword /*attribs*/)
-{ return 0; }
-
 PUBLIC template< typename SPACE >
 inline
 Generic_io_space<SPACE>::Generic_io_space()
@@ -137,32 +158,33 @@ Generic_io_space<SPACE>::~Generic_io_space()
   if (!mem_space()->dir())
     return;
 
-  Pdir::Iter iopte = mem_space()->dir()->walk(Virt_addr(Mem_layout::Io_bitmap));
+  auto iopte = mem_space()->dir()->walk(Virt_addr(Mem_layout::Io_bitmap));
 
   // do we have an IO bitmap?
-  if (iopte.e->valid())
+  if (iopte.is_valid())
     {
       // sanity check
-      assert (iopte.shift() != Config::SUPERPAGE_SHIFT);
+      assert (iopte.level != Pdir::Super_level);
+
+      Kmem_alloc::allocator()->q_free_phys(ram_quota(), Config::PAGE_SHIFT,
+                                           iopte.page_addr());
 
-      Kmem_alloc::allocator()
-       ->q_free_phys(ram_quota(), Config::PAGE_SHIFT,
-                     iopte.e[0].addr());
+      // switch to next page-table entry
+      ++iopte;
 
-      if (iopte.e[1].valid())
-       Kmem_alloc::allocator()
-         ->q_free_phys(ram_quota(), Config::PAGE_SHIFT,
-                       iopte.e[1].addr());
+      if (iopte.is_valid())
+        Kmem_alloc::allocator()->q_free_phys(ram_quota(), Config::PAGE_SHIFT,
+                                             iopte.page_addr());
 
-      Pdir::Iter iopde = mem_space()->dir()->walk(Virt_addr(Mem_layout::Io_bitmap), 0);
+      auto iopde = mem_space()->dir()->walk(Virt_addr(Mem_layout::Io_bitmap),
+                                            Pdir::Super_level);
 
       // free the page table
-      Kmem_alloc::allocator()
-       ->q_free_phys(ram_quota(), Config::PAGE_SHIFT,
-                     iopde.e->addr());
+      Kmem_alloc::allocator()->q_free_phys(ram_quota(), Config::PAGE_SHIFT,
+                                           iopde.next_level());
 
       // free reference
-      *iopde.e = 0;
+      *iopde.pte = 0;
     }
 }
 
@@ -183,90 +205,86 @@ Generic_io_space<SPACE>::is_superpage()
 // Utilities for map<Generic_io_space> and unmap<Generic_io_space>
 //
 
-PUBLIC template< typename SPACE >
-virtual
+IMPLEMENT template< typename SPACE >
 bool
-Generic_io_space<SPACE>::v_fabricate(Addr address, Phys_addr *phys,
-                                     Size *size, unsigned *attribs = 0)
+Generic_io_space<SPACE>::v_fabricate(V_pfn address, Phys_addr *phys,
+                                     Page_order *order, Attr *attribs)
 {
-  return Generic_io_space::v_lookup(address.trunc(Size(Map_page_size)),
-      phys, size, attribs);
-
+  return this->v_lookup(address, phys, order, attribs);
 }
 
-PUBLIC template< typename SPACE >
+IMPLEMENT template< typename SPACE >
 inline NEEDS[Generic_io_space::is_superpage]
-bool
-Generic_io_space<SPACE>::v_lookup(Addr virt, Phys_addr *phys = 0,
-                                  Size *size = 0, unsigned *attribs = 0)
+bool __attribute__((__flatten__))
+Generic_io_space<SPACE>::v_lookup(V_pfn virt, Phys_addr *phys,
+                                  Page_order *order, Attr *attribs)
 {
   if (is_superpage())
     {
-      if (size) *size = Size(Map_superpage_size);
+      if (order) *order = Order(Map_superpage_shift);
       if (phys) *phys = Phys_addr(0);
-      if (attribs) *attribs = Page_writable | Page_user_accessible;
+      if (attribs) *attribs = Attr::URW();
       return true;
     }
 
-  if (size) *size = Size(1);
+  if (order) *order = Order(0);
 
-  if (io_lookup(virt.value()))
+  if (io_lookup(cxx::int_value<V_pfn>(virt)))
     {
       if (phys) *phys = virt;
-      if (attribs) *attribs = Page_writable | Page_user_accessible;
+      if (attribs) *attribs = Attr::URW();
       return true;
     }
 
   if (get_io_counter() == 0)
     {
-      if (size) *size = Size(Map_superpage_size);
+      if (order) *order = Order(Map_superpage_shift);
       if (phys) *phys = Phys_addr(0);
     }
 
   return false;
 }
 
-PUBLIC template< typename SPACE >
+IMPLEMENT template< typename SPACE >
 inline NEEDS [Generic_io_space::is_superpage]
-unsigned long
-Generic_io_space<SPACE>::v_delete(Addr virt, Size size,
-                                  unsigned long page_attribs = Page_all_attribs)
+L4_fpage::Rights __attribute__((__flatten__))
+Generic_io_space<SPACE>::v_delete(V_pfn virt, Order size, Rights page_attribs)
 {
-  (void)size;
-  (void)page_attribs;
-  assert (page_attribs == Page_all_attribs);
+  if (!(page_attribs & L4_fpage::Rights::FULL()))
+    return L4_fpage::Rights(0);
 
   if (is_superpage())
     {
-      assert (size.value() == Map_superpage_size);
+      assert (size == Order(Map_superpage_shift));
 
       for (unsigned p = 0; p < Map_max_address; ++p)
        io_delete(p);
 
       _io_counter = 0;
-      return Page_writable | Page_user_accessible;
+      return L4_fpage::Rights(0);
     }
 
-  assert (size.value() == 1);
+  (void)size;
+  assert (size == Order(0));
 
-  return io_delete(virt.value());
+  io_delete(cxx::int_value<V_pfn>(virt));
+  return L4_fpage::Rights(0);
 }
 
-PUBLIC template< typename SPACE >
+IMPLEMENT template< typename SPACE >
 inline
-typename Generic_io_space<SPACE>::Status
-Generic_io_space<SPACE>::v_insert(Phys_addr phys, Addr virt, Size size,
-                                  unsigned page_attribs)
+typename Generic_io_space<SPACE>::Status __attribute__((__flatten__))
+Generic_io_space<SPACE>::v_insert(Phys_addr phys, V_pfn virt, Order size,
+                                  Attr page_attribs)
 {
   (void)phys;
-  (void)size;
   (void)page_attribs;
 
   assert (phys == virt);
-  if (is_superpage() && size.value() == Map_superpage_size)
+  if (is_superpage() && size == Order(Map_superpage_shift))
     return Insert_warn_exists;
 
-  if (get_io_counter() == 0 && size.value() == Map_superpage_size)
+  if (get_io_counter() == 0 && size == Order(Map_superpage_shift))
     {
       for (unsigned p = 0; p < Map_max_address; ++p)
        io_insert(p);
@@ -275,9 +293,9 @@ Generic_io_space<SPACE>::v_insert(Phys_addr phys, Addr virt, Size size,
       return Insert_ok;
     }
 
-  assert (size.value() == 1);
+  assert (size == Order(0));
 
-  return typename Generic_io_space::Status(io_insert(virt.value()));
+  return typename Generic_io_space::Status(io_insert(cxx::int_value<V_pfn>(virt)));
 }
 
 
@@ -287,6 +305,13 @@ void
 Generic_io_space<SPACE>::tlb_flush()
 {}
 
+PUBLIC template< typename SPACE >
+inline static
+void
+Generic_io_space<SPACE>::tlb_flush_spaces(bool, Generic_io_space<SPACE> *,
+                                          Generic_io_space<SPACE> *)
+{}
+
 PUBLIC template< typename SPACE >
 inline static
 bool
@@ -327,7 +352,7 @@ Generic_io_space<SPACE>::addto_io_counter(int incr)
     @return true if mapped
      false if not
  */
-PROTECTED template< typename SPACE >
+PROTECTED template< typename SPACE > inline
 bool
 Generic_io_space<SPACE>::io_lookup(Address port_number)
 {
@@ -357,7 +382,7 @@ Generic_io_space<SPACE>::io_lookup(Address port_number)
        Insert_err_nomem if memory allocation failed
        Insert_ok if otherwise insertion succeeded
  */
-PROTECTED template< typename SPACE >
+PROTECTED template< typename SPACE > inline
 typename Generic_io_space<SPACE>::Status
 Generic_io_space<SPACE>::io_insert(Address port_number)
 {
@@ -382,8 +407,9 @@ Generic_io_space<SPACE>::io_insert(Address port_number)
       Mem_space::Status status =
        mem_space()->v_insert(
            Mem_space::Phys_addr(Mem_layout::pmem_to_phys(page)),
-           Mem_space::Addr(port_virt & Config::PAGE_MASK),
-           Mem_space::Size(Config::PAGE_SIZE), Page_writable);
+           Virt_addr(port_virt & Config::PAGE_MASK),
+           Mem_space::Page_order(Config::PAGE_SHIFT),
+            Mem_space::Attr(L4_fpage::Rights::RW()));
 
       if (status == Mem_space::Insert_err_nomem)
        {
@@ -417,8 +443,8 @@ Generic_io_space<SPACE>::io_insert(Address port_number)
 /** Disable one IO port in the IO space.
     @param port_number port to disable
  */
-PROTECTED template< typename SPACE >
-unsigned
+PROTECTED template< typename SPACE > inline
+void
 Generic_io_space<SPACE>::io_delete(Address port_number)
 {
   assert(port_number < Mem_layout::Io_port_max);
@@ -430,7 +456,7 @@ Generic_io_space<SPACE>::io_delete(Address port_number)
 
   if (port_addr == ~0UL)
     // nothing mapped -> nothing to delete
-    return 0;
+    return;
 
   // so there is memory mapped in the IO bitmap -> disable the ports
   char *port = static_cast<char *>(Kmem::phys_to_virt(port_addr));
@@ -441,11 +467,7 @@ Generic_io_space<SPACE>::io_delete(Address port_number)
     {
       *port |= get_port_bit(port_number);
       addto_io_counter(-1);
-
-      return Page_writable | Page_user_accessible;
     }
-
-  return 0;
 }
 
 template< typename SPACE >
@@ -467,6 +489,6 @@ Generic_io_space<SPACE>::get_port_bit(Address const port_number) const
 
 PUBLIC template< typename SPACE >
 inline static
-Page_number
-Generic_io_space<SPACE>::canonize(Page_number v)
+typename Generic_io_space<SPACE>::V_pfn
+Generic_io_space<SPACE>::canonize(V_pfn v)
 { return v; }
index c74fabb7041d9639da614fed97304fc33a1787c9..beb13734f1b33542ce44685757a6165a2a872aa6 100644 (file)
@@ -197,7 +197,8 @@ void Ipc_gate_obj::operator delete (void *_f)
 
 PRIVATE inline NOEXPORT NEEDS["assert_opt.h"]
 L4_msg_tag
-Ipc_gate_ctl::bind_thread(L4_obj_ref, Mword, Syscall_frame *f, Utcb const *in, Utcb *)
+Ipc_gate_ctl::bind_thread(L4_obj_ref, L4_fpage::Rights,
+                          Syscall_frame *f, Utcb const *in, Utcb *)
 {
   L4_msg_tag tag = f->tag();
   L4_snd_item_iter snd_items(in, tag.words());
@@ -213,10 +214,10 @@ Ipc_gate_ctl::bind_thread(L4_obj_ref, Mword, Syscall_frame *f, Utcb const *in, U
   assert_opt(c_thread);
   register Space *const c_space = c_thread->space();
   assert_opt (c_space);
-  unsigned char t_rights = 0;
+  L4_fpage::Rights t_rights(0);
   Thread *t = Kobject::dcast<Thread_object*>(c_space->lookup_local(bind_thread.obj_index(), &t_rights));
 
-  if (!(t_rights & L4_fpage::CS))
+  if (!(t_rights & L4_fpage::Rights::CS()))
     return commit_result(-L4_err::EPerm);
 
 
@@ -234,7 +235,8 @@ Ipc_gate_ctl::bind_thread(L4_obj_ref, Mword, Syscall_frame *f, Utcb const *in, U
 
 PRIVATE inline NOEXPORT
 L4_msg_tag
-Ipc_gate_ctl::get_infos(L4_obj_ref, Mword, Syscall_frame *, Utcb const *, Utcb *out)
+Ipc_gate_ctl::get_infos(L4_obj_ref, L4_fpage::Rights,
+                        Syscall_frame *, Utcb const *, Utcb *out)
 {
   Ipc_gate_obj *g = static_cast<Ipc_gate_obj*>(this);
   out->values[0] = g->_id;
@@ -243,7 +245,7 @@ Ipc_gate_ctl::get_infos(L4_obj_ref, Mword, Syscall_frame *, Utcb const *, Utcb *
 
 PUBLIC
 void
-Ipc_gate_ctl::invoke(L4_obj_ref self, Mword rights, Syscall_frame *f, Utcb *utcb)
+Ipc_gate_ctl::invoke(L4_obj_ref self, L4_fpage::Rights rights, Syscall_frame *f, Utcb *utcb)
 {
   if (f->tag().proto() == L4_msg_tag::Label_kobject)
     Kobject_h<Ipc_gate_ctl, Kobject_iface>::invoke(self, rights, f, utcb);
@@ -254,7 +256,8 @@ Ipc_gate_ctl::invoke(L4_obj_ref self, Mword rights, Syscall_frame *f, Utcb *utcb
 
 PUBLIC
 L4_msg_tag
-Ipc_gate_ctl::kinvoke(L4_obj_ref self, Mword rights, Syscall_frame *f, Utcb const *in, Utcb *out)
+Ipc_gate_ctl::kinvoke(L4_obj_ref self, L4_fpage::Rights rights,
+                      Syscall_frame *f, Utcb const *in, Utcb *out)
 {
   L4_msg_tag tag = f->tag();
 
@@ -321,7 +324,7 @@ Ipc_gate::block(Thread *ct, L4_timeout const &to, Utcb *u)
 
 PUBLIC
 void
-Ipc_gate::invoke(L4_obj_ref /*self*/, Mword rights, Syscall_frame *f, Utcb *utcb)
+Ipc_gate::invoke(L4_obj_ref /*self*/, L4_fpage::Rights rights, Syscall_frame *f, Utcb *utcb)
 {
   Syscall_frame *ipc_f = f;
   //LOG_MSG_3VAL(current(), "gIPC", Mword(_thread), _id, f->obj_2_flags());
@@ -352,14 +355,14 @@ Ipc_gate::invoke(L4_obj_ref /*self*/, Mword rights, Syscall_frame *f, Utcb *utcb
   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;
+      l->label = _id | cxx::int_value<L4_fpage::Rights>(rights);
   );
 
   if (EXPECT_FALSE(!ipc))
     f->tag(commit_error(utcb, L4_error::Not_existent));
   else
     {
-      ipc_f->from(_id | rights);
+      ipc_f->from(_id | cxx::int_value<L4_fpage::Rights>(rights));
       ct->do_ipc(f->tag(), partner, partner, have_rcv, sender,
                  f->timeout(), f, rights);
     }
index 76b0ca140577f185e0bccfdadc673c57f0cf6887..007ae57eb10da2e1a6931a4bd2d6fdf5f07d050e 100644 (file)
@@ -1,9 +1,11 @@
 INTERFACE:
 
+#include "types.h"
+
 class Ipi
 {
 public:
-  static void init(unsigned cpu);
+  static void init(Cpu_number cpu);
 };
 
 INTERFACE[!mp]:
@@ -30,22 +32,22 @@ IMPLEMENTATION[!mp]:
 
 IMPLEMENT inline
 void
-Ipi::init(unsigned cpu)
+Ipi::init(Cpu_number cpu)
 { (void)cpu; }
 
 PUBLIC static inline
 void
-Ipi::send(Message, unsigned from_cpu, unsigned to_cpu)
+Ipi::send(Message, Cpu_number from_cpu, Cpu_number to_cpu)
 { (void)from_cpu; (void)to_cpu; }
 
 PUBLIC static inline
 void
-Ipi::eoi(Message, unsigned on_cpu)
+Ipi::eoi(Message, Cpu_number on_cpu)
 { (void)on_cpu; }
 
 PUBLIC static inline
 void
-Ipi::bcast(Message, unsigned from_cpu)
+Ipi::bcast(Message, Cpu_number from_cpu)
 { (void)from_cpu; }
 
 
@@ -59,12 +61,12 @@ IMPLEMENTATION[!(mp && debug)]:
 
 PUBLIC static inline
 void
-Ipi::stat_sent(unsigned from_cpu)
+Ipi::stat_sent(Cpu_number from_cpu)
 { (void)from_cpu; }
 
 PUBLIC static inline
 void
-Ipi::stat_received(unsigned on_cpu)
+Ipi::stat_received(Cpu_number on_cpu)
 { (void)on_cpu; }
 
 // ------------------------------------------------------------------------
@@ -82,10 +84,10 @@ private:
 
 PUBLIC static inline
 void
-Ipi::stat_sent(unsigned from_cpu)
+Ipi::stat_sent(Cpu_number from_cpu)
 { atomic_mp_add(&_ipi.cpu(from_cpu)._stat_sent, 1); }
 
 PUBLIC static inline
 void
-Ipi::stat_received(unsigned on_cpu)
+Ipi::stat_received(Cpu_number on_cpu)
 { _ipi.cpu(on_cpu)._stat_received++; }
index 7079fdc988f8350dc3e0a462c8e4551ba3aa3424..32c57db766cc0e43d5d5cdd17fef89f4e3cdd9eb 100644 (file)
@@ -79,7 +79,7 @@ public:
     // level triggered
   }
 
-  void set_cpu(Mword, unsigned)
+  void set_cpu(Mword, Cpu_number)
   {
     // don't know what to do here, may be multiple targets on different
     // CPUs!
@@ -279,7 +279,7 @@ Irq_muxer::sys_attach(L4_msg_tag const &tag, Utcb const *utcb, Syscall_frame * /
 
 PUBLIC
 L4_msg_tag
-Irq_muxer::kinvoke(L4_obj_ref, Mword /*rights*/, Syscall_frame *f,
+Irq_muxer::kinvoke(L4_obj_ref, L4_fpage::Rights /*rights*/, Syscall_frame *f,
                    Utcb const *utcb, Utcb *)
 {
   register Context *const c_thread = ::current();
@@ -624,7 +624,7 @@ Irq_sender::sys_attach(L4_msg_tag const &tag, Utcb const *utcb, Syscall_frame *
 
 PUBLIC
 L4_msg_tag
-Irq_sender::kinvoke(L4_obj_ref, Mword /*rights*/, Syscall_frame *f,
+Irq_sender::kinvoke(L4_obj_ref, L4_fpage::Rights /*rights*/, Syscall_frame *f,
                     Utcb const *utcb, Utcb *)
 {
   register Context *const c_thread = ::current();
index 83cd1662120c0062f41f28b562c104c7f6941ba9..6c6b0bfff093df99f1b543464413980c48b42065 100644 (file)
@@ -35,7 +35,7 @@ public:
    * \param pin the pin to configure
    * \param cpu the logical CPU number.
    */
-  virtual void set_cpu(Mword pin, unsigned cpu) = 0;
+  virtual void set_cpu(Mword pin, Cpu_number cpu) = 0;
   virtual void unbind(Irq_base *irq);
   virtual ~Irq_chip() = 0;
 };
@@ -51,7 +51,7 @@ public:
   void mask_and_ack(Mword) {}
   void ack(Mword) {}
 
-  void set_cpu(Mword, unsigned) {}
+  void set_cpu(Mword, Cpu_number) {}
   unsigned set_mode(Mword, unsigned mode) { return mode; }
 
   char const *chip_type() const { return "Soft"; }
@@ -136,7 +136,7 @@ public:
     switch_mode(mode);
   }
 
-  void set_cpu(unsigned cpu) { _chip->set_cpu(_pin, cpu); }
+  void set_cpu(Cpu_number cpu) { _chip->set_cpu(_pin, cpu); }
 
   unsigned get_mode() const
   { return _flags & 0xe; }
index a39742318a887541d6d98ea7be7f80cd33c568b0..52fd6ce80541d616addd8a55fcfcd1c9beddc43b 100644 (file)
@@ -2,7 +2,7 @@ INTERFACE:
 
 #include "types.h"
 #include "irq_chip.h"
-#include <type_traits>
+#include <cxx/type_traits>
 
 /**
  * Interface used to manage harware IRQs on a platform.
@@ -54,7 +54,7 @@ public:
    */
   virtual Mword msg(Mword irqnum) const { (void)irqnum; return 0; }
 
-  virtual void set_cpu(Mword irqnum, unsigned cpu) const;
+  virtual void set_cpu(Mword irqnum, Cpu_number cpu) const;
 
   /// The pointer to the single global instance of the actual IRQ manager.
   static Irq_mgr *mgr;
@@ -122,7 +122,8 @@ Irq_mgr::irq(Mword irqnum) const
 
 IMPLEMENT
 void
-Irq_mgr::set_cpu(Mword irqnum, unsigned cpu) const
+Irq_mgr::set_cpu(Mword irqnum, Cpu_number cpu) const
 {
-  WARNX(Warning, "IRQ%ld: ignoring CPU setting (%d).\n", irqnum, cpu);
+  WARNX(Warning, "IRQ%ld: ignoring CPU setting (%d).\n", irqnum,
+        cxx::int_value<Cpu_number>(cpu));
 }
index c5a2e2e110d81cdd35fd950a7b427566311e9627..bea47e3a94ac8abab6afb44816e95723468d7efe 100644 (file)
@@ -21,7 +21,7 @@ IMPLEMENTATION[!(arm || ppc32 || sparc)]:
 
 PRIVATE inline NEEDS["globals.h"]
 Kernel_task::Kernel_task()
-: Task(Ram_quota::root, Kmem::kdir)
+: Task(Ram_quota::root, Kmem::kdir, Caps::none())
 {}
 
 
index 2867ed06c0d5cc408bd64b8b8cb2cd8f323870db..4dca58ef533f215dfbb0c1705e935404c0113b9c 100644 (file)
@@ -15,17 +15,13 @@ IMPLEMENTATION:
 #include "types.h"
 #include "ram_quota.h"
 
-enum Default_base_caps
-{
-  C_task      = 1,
-  C_factory   = 2,
-  C_thread    = 3,
-  C_pager     = 4,
-  C_log       = 5,
-  C_icu       = 6,
-  C_scheduler = 7
-
-};
+static Cap_index const C_task      = Cap_index(1);
+static Cap_index const C_factory   = Cap_index(2);
+static Cap_index const C_thread    = Cap_index(3);
+static Cap_index const C_pager     = Cap_index(4);
+static Cap_index const C_log       = Cap_index(5);
+static Cap_index const C_icu       = Cap_index(6);
+static Cap_index const C_scheduler = Cap_index(7);
 
 
 IMPLEMENT
@@ -71,7 +67,7 @@ Kernel_thread::init_workload()
   check (map(sigma0,          sigma0, sigma0, C_task, 0));
   check (map(Factory::root(), sigma0, sigma0, C_factory, 0));
 
-  for (unsigned c = Initial_kobjects::First_cap; c < Initial_kobjects::End_cap; ++c)
+  for (Cap_index c = Initial_kobjects::first(); c < Initial_kobjects::end(); ++c)
     {
       Kobject_iface *o = initial_kobjects.obj(c);
       if (o)
@@ -87,7 +83,7 @@ Kernel_thread::init_workload()
   check (map(sigma0_thread, sigma0, sigma0, C_thread, 0));
 
   Address sp = init_workload_s0_stack();
-  check (sigma0_thread->control(Thread_ptr(false), Thread_ptr(false)) == 0);
+  check (sigma0_thread->control(Thread_ptr(Thread_ptr::Null), Thread_ptr(Thread_ptr::Null)) == 0);
   check (sigma0_thread->bind(sigma0, User<Utcb>::Ptr((Utcb*)Mem_layout::Utcb_addr)));
   check (sigma0_thread->ex_regs(Kip::k()->sigma0_ip, sp));
 
@@ -113,7 +109,7 @@ Kernel_thread::init_workload()
   check (map(boot_task,   boot_task, boot_task, C_task, 0));
   check (map(boot_thread, boot_task, boot_task, C_thread, 0));
 
-  check (boot_thread->control(Thread_ptr(C_pager), Thread_ptr(~0UL)) == 0);
+  check (boot_thread->control(Thread_ptr(C_pager), Thread_ptr(Thread_ptr::Null)) == 0);
   check (boot_thread->bind(boot_task, User<Utcb>::Ptr((Utcb*)Mem_layout::Utcb_addr)));
   check (boot_thread->ex_regs(Kip::k()->root_ip, Kip::k()->root_sp));
 
@@ -122,12 +118,12 @@ Kernel_thread::init_workload()
   check (s0_b_gate);
   check (map(s0_b_gate, boot_task, boot_task, C_pager, 0));
 
-  set_cpu_of(sigma0_thread, 0);
-  set_cpu_of(boot_thread, 0);
+  set_cpu_of(sigma0_thread, Cpu_number::boot_cpu());
+  set_cpu_of(boot_thread, Cpu_number::boot_cpu());
 
   sigma0_thread->activate();
-  check (obj_map(sigma0, C_factory,   1, boot_task, C_factory, 0).error() == 0);
-  for (unsigned c = Initial_kobjects::First_cap; c < Initial_kobjects::End_cap; ++c)
+  check (obj_map(sigma0, C_factory, 1, boot_task, C_factory, 0).error() == 0);
+  for (Cap_index c = Initial_kobjects::first(); c < Initial_kobjects::end(); ++c)
     {
       Kobject_iface *o = initial_kobjects.obj(c);
       if (o)
index 1ff718d044cbbf85077b9c180cb0c62aaa7bcdb3..0b065c2f9248a697498ee8859df13591b0e222c3 100644 (file)
@@ -64,7 +64,7 @@ Kernel_thread::bootstrap()
 
   // 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);
+  Per_cpu_data_alloc::alloc(Cpu::invalid());
 
   set_cpu_of(this, Cpu::boot_cpu()->id());
   Mem::barrier();
@@ -79,13 +79,14 @@ Kernel_thread::bootstrap()
   // Setup initial timeslice
   Sched_context::rq.current().set_current_sched(sched());
 
-  Timer_tick::setup(cpu(true)); assert (cpu(true) == 0); // currently the boot cpu must be 0
+  Timer_tick::setup(cpu(true));
+  assert (cpu(true) == Cpu_number::boot_cpu()); // currently the boot cpu must be 0
   Timer_tick::enable(cpu(true));
   enable_tlb(cpu(true));
 
   bootstrap_arch();
 
-  Per_cpu_data::run_late_ctors(0);
+  Per_cpu_data::run_late_ctors(Cpu_number::boot_cpu());
 
   Proc::sti();
   Watchdog::enable();
@@ -159,7 +160,7 @@ Kernel_thread::idle_op()
   // this version must run with disabled IRQs and a wakup must continue directly
   // after the wait for event.
   auto guard = lock_guard(cpu_lock);
-  unsigned cpu = this->cpu();
+  Cpu_number cpu = this->cpu();
   ++_idle_counter.cpu(cpu);
   // 1. check for latency requirements that prevent low power modes
   // 2. check for timouts on this CPU ignore the idle thread's timeslice
index 31ab9e6620990c94927af15c6ab8fec68665869a..efb865bf27c756b0b9b3a5447067b4be1669386b 100644 (file)
@@ -1,7 +1,7 @@
 INTERFACE:
 
 #include <auto_quota.h>
-#include <slist>
+#include <cxx/slist>
 
 #include "spin_lock.h"
 #include "lock_guard.h"
@@ -63,6 +63,10 @@ public:
     _q->free(size);
   }
 
+  template<typename V>
+  Phys_mem_addr::Value to_phys(V v) const
+  { return _a->to_phys(v); }
+
 private:
   Kmem_alloc *_a;
   Q *_q;
index 6de15446d6bf88fc7eec946815bb03fb69af2c71..6c1aef543828ba432d6c3590ef0569a87ddf7cbe 100644 (file)
@@ -7,7 +7,7 @@ INTERFACE:
 #include "spin_lock.h"
 
 #include "slab_cache.h"                // Slab_cache
-#include <slist>
+#include <cxx/slist>
 
 class Kmem_slab : public Slab_cache, public cxx::S_list_item
 {
index e5b3c86002290ad0f722eabaebf684f69695ce3b..0f88303d43a8c0e9b7e153dddcf04e461433a73b 100644 (file)
@@ -2,7 +2,7 @@ INTERFACE:
 
 #include "lock.h"
 #include "obj_space.h"
-#include <hlist>
+#include <cxx/hlist>
 
 
 class Kobject_mappable
@@ -178,7 +178,7 @@ Kobject::sys_dec_refcnt(L4_msg_tag tag, Utcb const *in, Utcb *out)
 
 PUBLIC
 L4_msg_tag
-Kobject::kobject_invoke(L4_obj_ref, Mword /*rights*/,
+Kobject::kobject_invoke(L4_obj_ref, L4_fpage::Rights /*rights*/,
                         Syscall_frame *f,
                         Utcb const *in, Utcb *out)
 {
index 19295879ba5204ae9943b487379686c4f32b4952..3da3a2626d171409d79c83f3878d224f499ce5bc 100644 (file)
@@ -9,8 +9,8 @@ INTERFACE[debug]:
 
 #include "spin_lock.h"
 #include "lock_guard.h"
-#include <dlist>
-#include <hlist>
+#include <cxx/dlist>
+#include <cxx/hlist>
 
 class Kobject;
 
index eb84b887109c890bde8d4434f9b8dd5dd4e18ec3..6964efbbf16278c4a29153610b697140d195a707 100644 (file)
@@ -2,7 +2,7 @@ INTERFACE:
 
 #include "kobject.h"
 #include "thread.h"
-#include <type_traits>
+#include <cxx/type_traits>
 
 class Kobject_helper_base
 {
@@ -32,7 +32,7 @@ public:
   template< typename... A >
   explicit Kobject_h(A&&... args) : Base(cxx::forward<A>(args)...) {}
 
-  void invoke(L4_obj_ref self, Mword rights, Syscall_frame *f, Utcb *u)
+  void invoke(L4_obj_ref self, L4_fpage::Rights rights, Syscall_frame *f, Utcb *u)
   {
     L4_msg_tag res(no_reply());
     if (EXPECT_TRUE(self.op() & L4_obj_ref::Ipc_send))
index 7385039335a1b431902e22734730b16b87ac04a8..812dea1614dfdfbc35888ca917cd7e93843c9737 100644 (file)
@@ -27,7 +27,7 @@ public:
 class Kobject_iface : public Kobject_common
 {
 public:
-  virtual void invoke(L4_obj_ref self, Mword rights, Syscall_frame *, Utcb *) = 0;
+  virtual void invoke(L4_obj_ref self, L4_fpage::Rights rights, Syscall_frame *, Utcb *) = 0;
 };
 
 IMPLEMENTATION:
index 3e78478fd502ff8922e2b7f0b6eefec1fc66f86c..bcfee21fdab0d26576982b2f83f3be4b50e54538 100644 (file)
@@ -14,7 +14,7 @@ public:
   // TYPES
 
   typedef Obj_space::Phys_addr Phys_addr;
-  typedef Obj_space::Addr Vaddr;
+  typedef Obj_space::V_pfn Vaddr;
   typedef Obj::Mapping Mapping;
 
   class Iterator;
@@ -40,7 +40,7 @@ public:
     inline operator Mapping*() const   { return 0; }
     Iterator() {}
 
-    Iterator(Frame const &, Mapping *, Page_number, Page_number) {}
+    Iterator(Frame const &, Mapping *, Obj_space::V_pfn, Obj_space::V_pfn) {}
 
     Iterator &operator ++ () { return *this; }
   };
@@ -89,8 +89,8 @@ Kobject_mapdb::vaddr(const Frame&, Mapping*)
 PUBLIC inline
 Kobject_mapdb::Mapping *
 Kobject_mapdb::check_for_upgrade(Obj_space::Phys_addr,
-                                 Space *, Page_number,
-                                 Space *, Page_number,
+                                 Space *, Obj_space::V_pfn,
+                                 Space *, Obj_space::V_pfn,
                                  Frame *)
 {
   // Hm we never or seldomly do upgrades on cap anyway
@@ -100,11 +100,11 @@ Kobject_mapdb::check_for_upgrade(Obj_space::Phys_addr,
 PUBLIC inline static
 Kobject_mapdb::Mapping *
 Kobject_mapdb::insert(const Frame&, Mapping*, Space *,
-                      Vaddr va, Obj_space::Phys_addr o, Page_count size)
+                      Vaddr va, Obj_space::Phys_addr o, Obj_space::V_pfc size)
 {
   (void)size;
   (void)o;
-  assert (size.value() == 1);
+  assert (size == Obj_space::V_pfc(1));
 
   Mapping *m = va._c;
   Kobject_mappable *rn = o->map_root();
@@ -143,10 +143,10 @@ Kobject_mapdb::free (const Frame& f)
   f.frame->_lock.clear();
 } // free()
 
-PUBLIC static
+PUBLIC static inline
 void
 Kobject_mapdb::flush(const Frame& f, Mapping *m, L4_map_mask mask,
-                     Page_number, Page_number)
+                     Obj_space::V_pfn, Obj_space::V_pfn)
 {
   //LOG_MSG_3VAL(current(), "unm", f.frame->dbg_id(), (Mword)m, 0);
   if (!mask.self_unmap())
index 32110b5d2f4344ba160a153c9b45ccc997263e25..4eb76dda5a746072f9ea4e700b25d3b6abd9a0c6 100644 (file)
@@ -5,11 +5,12 @@ INTERFACE [debug]:
 
 extern Static_object<Mapdb> mapdb_mem;
 
-
 IMPLEMENTATION:
 
 #include "config.h"
 #include "mapdb.h"
+#include "mem_space.h"
+#include <minmax.h>
 
 Static_object<Mapdb> mapdb_mem;
 
@@ -29,36 +30,37 @@ L4_error __attribute__((nonnull(1, 3)))
 mem_map(Space *from, L4_fpage const &fp_from,
         Space *to, L4_fpage const &fp_to, L4_msg_item control)
 {
-  typedef Map_traits<Mem_space> Mt;
+  assert_opt (from);
+  assert_opt (to);
+
+  typedef Mem_space::V_pfn Pfn;
+  typedef Mem_space::V_pfc Pfc;
+  typedef Mem_space::V_order Order;
 
   if (EXPECT_FALSE(fp_from.order() < L4_fpage::Mem_addr::Shift
                    || fp_to.order() < L4_fpage::Mem_addr::Shift))
     return L4_error::None;
 
   // loop variables
-  Mt::Addr rcv_addr = fp_to.mem_address();
-  Mt::Addr snd_addr = fp_from.mem_address();
-  Mt::Addr offs = Virt_addr(control.address());
+  Pfn rcv_addr = fp_to.mem_address();
+  Pfn snd_addr = fp_from.mem_address();
+  Pfn offs = Virt_addr(control.address());
 
-  Mt::Size snd_size = Mt::Size::from_shift(fp_from.order() - L4_fpage::Mem_addr::Shift);
-  Mt::Size rcv_size = Mt::Size::from_shift(fp_to.order() - L4_fpage::Mem_addr::Shift);
+  // calc size in bytes from power of twos
+  Order so = Mu::get_order_from_fp<Pfc>(fp_from, L4_fpage::Mem_addr::Shift);
+  Order ro = Mu::get_order_from_fp<Pfc>(fp_to, L4_fpage::Mem_addr::Shift);
 
-  // calc size in bytes from power of tows
-  snd_addr = snd_addr.trunc(snd_size);
-  rcv_addr = rcv_addr.trunc(rcv_size);
-  Mt::constraint(snd_addr, snd_size, rcv_addr, rcv_size, offs);
-
-  if (snd_size == 0)
-    return L4_error::None;
+  snd_addr = cxx::mask_lsb(snd_addr, so);
+  rcv_addr = cxx::mask_lsb(rcv_addr, ro);
+  Mu::free_constraint(snd_addr, so, rcv_addr, ro, offs);
 
-  unsigned long del_attribs, add_attribs;
-  Mt::attribs(control, fp_from, &del_attribs, &add_attribs);
+  Mem_space::Attr attribs(fp_from.rights() | L4_fpage::Rights::U(), control.mem_type());
 
   return map<Mem_space>(mapdb_mem.get(),
-            from, from, snd_addr,
-            snd_size, to, to,
-            rcv_addr, control.is_grant(), add_attribs, del_attribs,
-            (Mem_space::Reap_list**)0);
+                        from, from, snd_addr,
+                        Pfc(1) << so, to, to,
+                        rcv_addr, control.is_grant(), attribs,
+                        (Mem_space::Reap_list**)0);
 }
 
 /** Unmap the mappings in the region described by "fp" from the address
@@ -73,73 +75,25 @@ mem_map(Space *from, L4_fpage const &fp_from,
     @param flush_mode determines which access privileges to remove.
     @return combined (bit-ORed) access status of unmapped physical pages
 */
-unsigned __attribute__((nonnull(1)))
+L4_fpage::Rights __attribute__((nonnull(1)))
 mem_fpage_unmap(Space *space, L4_fpage fp, L4_map_mask mask)
 {
-  typedef Map_traits<Mem_space> Mt;
-  Mt::Size size = Mt::Size::from_shift(fp.order() - L4_fpage::Mem_addr::Shift);
-  Mt::Addr start = Mt::get_addr(fp);
+  if (fp.order() < L4_fpage::Mem_addr::Shift)
+    return L4_fpage::Rights(0);
 
-  start = start.trunc(size);
+  Mem_space::V_order o = Mu::get_order_from_fp<Mem_space::V_pfc>(fp, L4_fpage::Mem_addr::Shift);
+  Mem_space::V_pfc size = Mem_space::V_pfc(1) << o;
+  Mem_space::V_pfn start = fp.mem_address();
+
+  start = cxx::mask_lsb(start, o);
 
   return unmap<Mem_space>(mapdb_mem.get(), space, space,
                start, size,
                fp.rights(), mask, (Mem_space::Reap_list**)0);
 }
 
-static inline
-void
-save_access_attribs(Mapdb* mapdb, const Mapdb::Frame& mapdb_frame,
-                    Mapping* mapping, Mem_space* space, unsigned page_rights, 
-                    Mem_space::Addr virt, Mem_space::Phys_addr phys,
-                    Mem_space::Size size,
-                    bool me_too)
-{
-  typedef Mem_space::Size Size;
-  typedef Mem_space::Addr Addr;
-  typedef Mem_space::Phys_addr Phys_addr;
 
-  if (unsigned page_accessed
-      = page_rights & (Mem_space::Page_referenced | Mem_space::Page_dirty))
-    {
-      Mem_space::Status status;
-
-      // When flushing access attributes from our space as well,
-      // cache them in parent space, otherwise in our space.
-      if (! me_too || !mapping->parent())
-       {
-         status = space->v_insert(phys, virt, size,
-                                  page_accessed);
-       }
-      else
-       {
-         Mapping *parent = mapping->parent();
-
-          assert (parent->space());
-         Mem_space *parent_space = parent->space();
-
-         Address parent_shift = mapdb->shift(mapdb_frame, parent) + Mem_space::Page_shift;
-         Address parent_address = parent->page().value() << parent_shift;
-
-         status =
-           parent_space->v_insert(phys.trunc(Phys_addr::create(1UL << parent_shift)),
-                                  Addr::create(parent_address),
-                                  Size::create(1UL << parent_shift),
-                                  page_accessed, true);
-       }
-
-      assert (status == Mem_space::Insert_ok
-             || status == Mem_space::Insert_warn_exists
-             || status == Mem_space::Insert_warn_attrib_upgrade
-             /*|| s->is_sigma0()*/);
-      // Be forgiving to sigma0 because it's address
-      // space is not kept in sync with its mapping-db
-      // entries.
-    }
-}
 
-//---------------------------------------------------------------------------
-IMPLEMENTATION[!64bit]:
 
 /** The mapping database.
     This is the system's instance of the mapping database.
@@ -147,40 +101,38 @@ IMPLEMENTATION[!64bit]:
 void
 init_mapdb_mem(Space *sigma0)
 {
-  static size_t const page_sizes[]
+  enum { Max_num_page_sizes = 7 };
+  static size_t page_sizes[Max_num_page_sizes]
     = { Config::SUPERPAGE_SHIFT - Config::PAGE_SHIFT, 0 };
 
-  mapdb_mem.construct(sigma0,
-      Page_number::create(1U << (32 - Config::SUPERPAGE_SHIFT)),
-      page_sizes, 2);
-}
-
-//---------------------------------------------------------------------------
-IMPLEMENTATION[amd64]:
+  typedef Mem_space::Page_order Page_order;
+  Page_order const *ps = Mem_space::get_global_page_sizes();
+  unsigned idx = 0;
+  unsigned phys_bits(Cpu::boot_cpu()->phys_bits());
+  phys_bits = min(phys_bits, (unsigned)MWORD_BITS);
 
-#include "cpu.h"
+  Page_order last_bits(phys_bits);
 
-/** The mapping database.
-    This is the system's instance of the mapping database.
- */
-void
-init_mapdb_mem(Space *sigma0)
-{
-  static size_t const amd64_page_sizes[] =
-  { Config::PML4E_SHIFT - Config::PAGE_SHIFT,
-    Config::PDPE_SHIFT - Config::PAGE_SHIFT,
-    Config::SUPERPAGE_SHIFT - Config::PAGE_SHIFT,
-    0};
-
-  unsigned const num_page_sizes = Cpu::boot_cpu()->phys_bits() >= 42 ?  4 : 3;
+  for (Page_order c = last_bits; c >= Page_order(Config::PAGE_SHIFT); --c)
+    {
+      c = *ps;
+      // not more than 2K entries per MDB split array
+      if (c < last_bits && (last_bits - c) > Page_order(12))
+        c = last_bits - Page_order(12);
+      else
+        ++ps;
 
-  Address const largest_page_max_index = num_page_sizes == 4 ?
-    Config::PML4E_MASK + 1ULL
-    : 1ULL << (Cpu::boot_cpu()->phys_bits() - Config::PDPE_SHIFT);
+      assert_kdb (idx < Max_num_page_sizes);
+      page_sizes[idx++] = Page_order::val(c) - Config::PAGE_SHIFT;
+      last_bits = c;
+    }
 
-  size_t const *const page_sizes = num_page_sizes == 4 ? amd64_page_sizes : amd64_page_sizes + 1;
+  if (0)
+    printf("MDB: phys_bits=%d levels = %d\n", Cpu::boot_cpu()->phys_bits(), idx);
 
-  mapdb_mem.construct(sigma0, Page_number::create(largest_page_max_index),
-      page_sizes, num_page_sizes);
+  mapdb_mem.construct(sigma0,
+      Mapping::Page(1U << (phys_bits - Config::PAGE_SHIFT - page_sizes[0])),
+      page_sizes, idx);
 }
 
+
index d8b0c27a61e16b15d89a74a04b0ef0f6a92f90fc..752b6869a1a8a8957d60bfe05b6296728695bdcc 100644 (file)
@@ -12,16 +12,6 @@ IMPLEMENTATION:
 #include "l4_types.h"
 #include "mappable.h"
 
-inline NEEDS["assert_opt.h"]
-void
-save_access_attribs (Kobject_mapdb* /*mapdb*/,
-    const Kobject_mapdb::Frame& /*mapdb_frame*/,
-    Kobject_mapdb::Mapping* /*mapping*/, Obj_space* /*space*/,
-    unsigned /*page_rights*/,
-    Obj_space::Addr /*virt*/, Obj_space::Phys_addr /*phys*/, Obj_space::Size /*size*/,
-    bool /*me_too*/)
-{}
-
 L4_error
 obj_map(Space *from, L4_fpage const &fp_from,
         Space *to, L4_fpage const &fp_to, L4_msg_item control,
@@ -30,80 +20,75 @@ obj_map(Space *from, L4_fpage const &fp_from,
   assert_opt (from);
   assert_opt (to);
 
-  typedef Map_traits<Obj_space> Mt;
-  Mt::Addr rcv_addr = Mt::get_addr(fp_to);
-  Mt::Addr snd_addr = Mt::get_addr(fp_from);
-  Mt::Size snd_size = Mt::Size::from_shift(fp_from.order());
-  Mt::Size rcv_size = Mt::Size::from_shift(fp_to.order());
-  Mt::Addr offs(control.index());
+  Cap_index rcv_addr = fp_to.obj_index();
+  Cap_index snd_addr = fp_from.obj_index();
+  Order so = Mu::get_order_from_fp<Cap_diff>(fp_from);
+  Order ro = Mu::get_order_from_fp<Cap_diff>(fp_to);
+  Cap_index offs = Cap_index((Mword)control.index());
 
-  snd_addr = snd_addr.trunc(snd_size);
-  rcv_addr = rcv_addr.trunc(rcv_size);
+  snd_addr = cxx::mask_lsb(snd_addr, so);
+  rcv_addr = cxx::mask_lsb(rcv_addr, ro);
 
-  Mt::constraint(snd_addr, snd_size, rcv_addr, rcv_size, offs);
+  Mu::free_constraint(snd_addr, so, rcv_addr, ro, offs);
+  Cap_diff snd_size = Cap_diff(1) << so;
 
-  if (snd_size == 0)
+  if (snd_size == Cap_diff(0))
     return L4_error::None;
 
-  unsigned long del_attribs, add_attribs;
-  Mt::attribs(control, fp_from, &del_attribs, &add_attribs);
+  Obj_space::Attr attribs(fp_from.rights(), L4_msg_item::C_weak_ref ^ control.attr());
 
   return map<Obj_space>((Kobject_mapdb*)0,
-             from, from, snd_addr,
-             snd_size,
-             to, to, rcv_addr,
-             control.is_grant(), add_attribs, del_attribs,
-             reap_list);
+                        from, from, Obj_space::V_pfn(snd_addr),
+                        snd_size,
+                        to, to, Obj_space::V_pfn(rcv_addr),
+                        control.is_grant(), attribs,
+                        reap_list);
 }
 
-unsigned __attribute__((nonnull(1)))
+L4_fpage::Rights __attribute__((nonnull(1)))
 obj_fpage_unmap(Space * space, L4_fpage fp, L4_map_mask mask,
                 Kobject ***reap_list)
 {
   assert_opt (space);
-  typedef Map_traits<Obj_space> Mt;
-  Mt::Size size = Mt::Size::from_shift(fp.order());
-  Mt::Addr addr = Mt::get_addr(fp);
-  addr = addr.trunc(size);
+  Order size = Mu::get_order_from_fp<Cap_diff>(fp);
+  Cap_index addr = fp.obj_index();
+  addr = cxx::mask_lsb(addr, size);
 
   // XXX prevent unmaps when a task has no caps enabled
 
   return unmap<Obj_space>((Kobject_mapdb*)0, space, space,
-               addr, size,
+               Obj_space::V_pfn(addr), Obj_space::V_pfc(1) << size,
                fp.rights(), mask, reap_list);
 }
 
 
 L4_error
-obj_map(Space *from, unsigned long snd_addr, unsigned long snd_size,
-        Space *to, unsigned long rcv_addr,
+obj_map(Space *from, Cap_index snd_addr, unsigned long snd_size,
+        Space *to, Cap_index rcv_addr,
         Kobject ***reap_list, bool grant = false,
-        unsigned attrib_add = 0, unsigned attrib_del = 0)
+        Obj_space::Attr attribs = Obj_space::Attr::Full())
 {
   assert_opt (from);
   assert_opt (to);
-  typedef Map_traits<Obj_space> Mt;
 
   return map<Obj_space>((Kobject_mapdb*)0,
-            from, from, Mt::Addr(snd_addr),
-            Mt::Size(snd_size),
-            to, to, Mt::Addr(rcv_addr),
-            grant, attrib_add, attrib_del, reap_list);
+            from, from, Obj_space::V_pfn(snd_addr),
+            Cap_diff(snd_size),
+            to, to, Obj_space::V_pfn(rcv_addr),
+            grant, attribs, reap_list);
 }
 
 bool
-map(Kobject_iface *o, Obj_space* to, Space *to_id, Address _rcv_addr,
-    Kobject ***reap_list, unsigned attribs = L4_fpage::CRWSD)
+map(Kobject_iface *o, Obj_space* to, Space *to_id, Cap_index rcv_addr,
+    Kobject ***reap_list)
 {
   assert_opt (o);
   assert_opt (to);
   assert_opt (to_id);
 
   typedef Obj_space SPACE;
-  typedef Obj_space::Addr Addr;
-  typedef Obj_space::Size Size;
-
-  Page_number const rcv_addr = Page_number::create(_rcv_addr);
+  typedef Obj_space::V_pfn Addr;
+  typedef Obj_space::Page_order Size;
 
   if (EXPECT_FALSE(rcv_addr >= to->map_max_address()))
     return 0;
@@ -111,17 +96,15 @@ map(Kobject_iface *o, Obj_space* to, Space *to_id, Address _rcv_addr,
   // Receiver lookup.
   Obj_space::Phys_addr r_phys;
   Size r_size;
-  unsigned r_attribs;
+  Obj_space::Attr r_attribs;
 
   Addr ra(rcv_addr);
   if (to->v_lookup(ra, &r_phys, &r_size, &r_attribs))
-    unmap((Kobject_mapdb*)0, to, to_id, ra, r_size,
-          L4_fpage::RWX, L4_map_mask::full(), reap_list);
+    unmap((Kobject_mapdb*)0, to, to_id, ra, Obj_space::V_pfc(1) << r_size,
+          L4_fpage::Rights::FULL(), L4_map_mask::full(), reap_list);
 
-  attribs &= L4_fpage::WX;
   // Do the actual insertion.
-  Obj_space::Status status
-    = to->v_insert(o, ra, Size::create(1), attribs);
+  Obj_space::Status status = to->v_insert(o, ra, Size(0), Obj_space::Attr::Full());
 
   switch (status)
     {
@@ -133,7 +116,7 @@ map(Kobject_iface *o, Obj_space* to, Space *to_id, Address _rcv_addr,
        {
          if (! o->map_root()->insert(0, to_id, ra))
            {
-             to->v_delete(rcv_addr, Obj_space::Size::create(1));
+             to->v_delete(Obj_space::V_pfn(rcv_addr), Size(0), L4_fpage::Rights::FULL());
              return 0;
            }
        }
index 288d0ed727ca18fc327e29272489416e0eb1b4d4..d9e0a68825467d113d5b5b23e23d1c6ca66ef8e7 100644 (file)
@@ -7,25 +7,77 @@ INTERFACE:
 class Mapdb;
 
 namespace Mu {
-template<typename SPACE>
-struct Virt_addr { typedef Page_number Type; };
-
-template<>
-struct Virt_addr<Obj_space> { typedef Obj_space::Addr Type; };
 
+struct Mapping_type_t;
+typedef cxx::int_type<unsigned, Mapping_type_t> Mapping_type;
 
 template< typename SPACE, typename M >
 inline
-Mword v_delete(M &m, Mword flush_rights, bool full_flush)
+L4_fpage::Rights
+v_delete(M &m, L4_fpage::Rights flush_rights, bool full_flush)
 {
   SPACE* child_space = m->space();
   assert_opt (child_space);
-  Mword res = child_space->v_delete(m.page(), m.size(), flush_rights);
+  L4_fpage::Rights res = child_space->v_delete(SPACE::to_virt(m.page()),
+                                               SPACE::to_order(m.order()),
+                                               flush_rights);
   (void) full_flush;
-  assert_kdb (full_flush != child_space->v_lookup(m.page()));
+  assert_kdb (full_flush != child_space->v_lookup(SPACE::to_virt(m.page())));
   return res;
 }
 
+template<>
+inline
+L4_fpage::Rights
+v_delete<Obj_space>(Kobject_mapdb::Iterator &m, L4_fpage::Rights flush_rights, bool /*full_flush*/)
+{
+  Obj_space::Entry *c = static_cast<Obj_space::Entry*>(*m);
+
+  if (c->valid())
+    {
+      if (flush_rights & L4_fpage::Rights::R())
+        c->invalidate();
+      else
+        c->del_rights(flush_rights & L4_fpage::Rights::WX());
+    }
+  return L4_fpage::Rights(0);
+}
+
+template< typename SIZE_TYPE >
+static typename SIZE_TYPE::Order_type
+get_order_from_fp(L4_fpage const &fp, int base_order = 0)
+{
+  typedef typename cxx::underlying_type<SIZE_TYPE>::type Value;
+  typedef typename SIZE_TYPE::Order_type Order;
+
+  enum : int {
+    Bits = sizeof(Value) * 8 - 1,
+    Max  = cxx::is_signed<Value>::value ? Bits - 1 : Bits
+  };
+
+  int shift = fp.order() - base_order;
+
+  if (shift <= Max)
+    return Order(shift);
+  else
+    return Order(Max);
+}
+
+template<typename Addr, typename Size>
+static inline
+void free_constraint(Addr &snd_addr, Size &snd_size,
+                     Addr &rcv_addr, Size rcv_size,
+                     Addr const &hot_spot)
+{
+  if (rcv_size >= snd_size)
+    rcv_addr += cxx::mask_lsb(cxx::get_lsb(hot_spot, rcv_size), snd_size);
+  else
+    {
+      snd_addr += cxx::mask_lsb(cxx::get_lsb(hot_spot, snd_size), rcv_size);
+      snd_size = rcv_size;
+      // reduce size of address range
+    }
+}
 
 }
 
@@ -33,13 +85,6 @@ template< typename SPACE >
 class Map_traits
 {
 public:
-  typedef Page_number Addr;
-  typedef Page_count Size;
-
-  static Addr get_addr(L4_fpage const &fp);
-  static void constraint(Addr &snd_addr, Size &snd_size,
-                         Addr &rcv_addr, Size const &rcv_size,
-                         Addr const &hot_spot);
   static bool match(L4_fpage const &from, L4_fpage const &to);
   static bool free_object(typename SPACE::Phys_addr o,
                           typename SPACE::Reap_list **reap_list);
@@ -57,24 +102,6 @@ public:
   Kobject ***list() { return &_t; }
 };
 
-namespace Mu {
-template<>
-inline
-Mword v_delete<Obj_space>(Kobject_mapdb::Iterator &m, Mword flush_rights, bool /*full_flush*/)
-{
-  Obj_space::Entry *c = static_cast<Obj_space::Entry*>(*m);
-
-  if (c->valid())
-    {
-      if (flush_rights & L4_fpage::R)
-        c->invalidate();
-      else
-        c->del_rights(flush_rights & L4_fpage::WX);
-    }
-  return 0;
-}
-}
-
 //------------------------------------------------------------------------
 IMPLEMENTATION:
 
@@ -103,68 +130,11 @@ Map_traits<SPACE>::free_object(typename SPACE::Phys_addr,
 
 PUBLIC template< typename SPACE >
 static inline
-void
-Map_traits<SPACE>::attribs(L4_msg_item /*control*/, L4_fpage const &/*fp*/,
-                           unsigned long *del_attr, unsigned long *set_attr)
-{ *del_attr = 0; *set_attr = 0; }
-
-PUBLIC template< typename SPACE >
-static inline
-unsigned long
-Map_traits<SPACE>::apply_attribs(unsigned long attribs,
+typename SPACE::Attr
+Map_traits<SPACE>::apply_attribs(typename SPACE::Attr attribs,
                                  typename SPACE::Phys_addr &,
-                                 unsigned long set_attr, unsigned long del_attr)
-{ return (attribs & ~del_attr) | set_attr; }
-
-PRIVATE template<typename SPACE>
-static inline
-void
-Map_traits<SPACE>::identity_constraint(Addr &snd_addr, Size &snd_size,
-                                       Addr rcv_addr, Size rcv_size)
-{
-  if (rcv_addr > snd_addr)
-    {
-      if (rcv_addr - snd_addr < snd_size)
-       snd_size -= rcv_addr - snd_addr;
-      else
-       snd_size = Size(0);
-      snd_addr = rcv_addr;
-    }
-
-  if (snd_size > rcv_size)
-    snd_size = rcv_size;
-}
-
-PRIVATE template<typename SPACE>
-static inline
-void
-Map_traits<SPACE>::free_constraint(Addr &snd_addr, Size &snd_size,
-                                   Addr &rcv_addr, Size rcv_size,
-                                   Addr const &hot_spot)
-{
-  if (rcv_size >= snd_size)
-    rcv_addr += hot_spot.offset(rcv_size).trunc(snd_size);
-  else
-    {
-      snd_addr += hot_spot.offset(snd_size).trunc(rcv_size);
-      snd_size = rcv_size;
-      // reduce size of address range
-    }
-}
-
-IMPLEMENT template<typename SPACE>
-inline
-void
-Map_traits<SPACE>::constraint(Addr &snd_addr, Size &snd_size,
-                              Addr &rcv_addr, Size const &rcv_size,
-                              Addr const &hot_spot)
-{
-  if (SPACE::Identity_map)
-    identity_constraint(snd_addr, snd_size, rcv_addr, rcv_size);
-  else
-    free_constraint(snd_addr, snd_size, rcv_addr, rcv_size, hot_spot);
-}
-
+                                 typename SPACE::Attr set_attr)
+{ return attribs.apply(set_attr); }
 
 
 //-------------------------------------------------------------------------
@@ -176,13 +146,6 @@ bool
 Map_traits<Io_space>::match(L4_fpage const &from, L4_fpage const &to)
 { return from.is_iopage() && (to.is_iopage() || to.is_all_spaces()); }
 
-IMPLEMENT template<>
-inline
-Map_traits<Io_space>::Addr
-Map_traits<Io_space>::get_addr(L4_fpage const &fp)
-{ return Addr(fp.io_address()); }
-
-
 
 //-------------------------------------------------------------------------
 IMPLEMENTATION:
@@ -191,38 +154,8 @@ IMPLEMENT template<>
 inline
 bool
 Map_traits<Mem_space>::match(L4_fpage const &from, L4_fpage const &to)
-{ 
-  return from.is_mempage() && (to.is_all_spaces() || to.is_mempage());
-}
-
-IMPLEMENT template<>
-inline
-Map_traits<Mem_space>::Addr
-Map_traits<Mem_space>::get_addr(L4_fpage const &fp)
-{ return Addr(fp.mem_address()); }
-
-IMPLEMENT template<>
-inline
-void
-Map_traits<Mem_space>::attribs(L4_msg_item control, L4_fpage const &fp,
-    unsigned long *del_attr, unsigned long *set_attr)
 {
-  *del_attr = (fp.rights() & L4_fpage::W) ? 0 : Mem_space::Page_writable;
-  short cache = control.attr() & 0x70;
-
-  if (cache & L4_msg_item::Caching_opt)
-    {
-      *del_attr |= Page::Cache_mask;
-
-      if (cache == L4_msg_item::Cached)
-       *set_attr = Page::CACHEABLE;
-      else if (cache == L4_msg_item::Buffered)
-       *set_attr = Page::BUFFERED;
-      else
-       *set_attr = Page::NONCACHEABLE;
-    }
-  else
-    *set_attr = 0;
+  return from.is_mempage() && (to.is_all_spaces() || to.is_mempage());
 }
 
 
@@ -232,13 +165,6 @@ bool
 Map_traits<Obj_space>::match(L4_fpage const &from, L4_fpage const &to)
 { return from.is_objpage() && (to.is_objpage() || to.is_all_spaces()); }
 
-
-IMPLEMENT template<>
-inline
-Map_traits<Obj_space>::Addr
-Map_traits<Obj_space>::get_addr(L4_fpage const &fp)
-{ return Addr(fp.obj_index()); }
-
 IMPLEMENT template<>
 inline
 bool
@@ -254,28 +180,18 @@ Map_traits<Obj_space>::free_object(Obj_space::Phys_addr o,
   return false;
 }
 
-IMPLEMENT template<>
-inline
-void
-Map_traits<Obj_space>::attribs(L4_msg_item control, L4_fpage const &fp,
-    unsigned long *del_attr, unsigned long *set_attr)
-{
-  *set_attr = 0;
-  *del_attr = (~(fp.rights() | (L4_msg_item::C_weak_ref ^ control.attr())));
-}
-
 IMPLEMENT template<>
 static inline
-unsigned long
-Map_traits<Obj_space>::apply_attribs(unsigned long attribs,
+Obj_space::Attr
+Map_traits<Obj_space>::apply_attribs(Obj_space::Attr attribs,
                                      Obj_space::Phys_addr &a,
-                                     unsigned long set_attr,
-                                     unsigned long del_attr)
+                                     Obj_space::Attr set_attr)
 {
-  if (attribs & del_attr & L4_msg_item::C_obj_specific_rights)
-    a = a->downgrade(del_attr);
+  if (attribs.extra() & ~set_attr.extra())
+    a = a->downgrade(~set_attr.extra());
 
-  return (attribs & ~del_attr) | set_attr;
+  attribs &= set_attr;
+  return attribs;
 }
 
 
@@ -300,15 +216,17 @@ L4_error
 fpage_map(Space *from, L4_fpage fp_from, Space *to,
           L4_fpage fp_to, L4_msg_item control, Reap_list *r)
 {
- if (Map_traits<Mem_space>::match(fp_from, fp_to))
+  Space::Caps caps = from->caps() & to->caps();
+
+  if (Map_traits<Mem_space>::match(fp_from, fp_to) && (caps & Space::Caps::mem()))
     return mem_map(from, fp_from, to, fp_to, control);
 
 #ifdef CONFIG_PF_PC
-  if (Map_traits<Io_space>::match(fp_from, fp_to))
+  if (Map_traits<Io_space>::match(fp_from, fp_to) && (caps & Space::Caps::io()))
     return io_map(from, fp_from, to, fp_to, control);
 #endif
 
-  if (Map_traits<Obj_space>::match(fp_from, fp_to))
+  if (Map_traits<Obj_space>::match(fp_from, fp_to) && (caps & Space::Caps::obj()))
     return obj_map(from, fp_from, to, fp_to, control, r->list());
 
   return L4_error::None;
@@ -327,18 +245,19 @@ fpage_map(Space *from, L4_fpage fp_from, Space *to,
 */
 // Don't inline -- it eats too much stack.
 // inline NEEDS ["config.h", io_fpage_unmap]
-unsigned
+L4_fpage::Rights
 fpage_unmap(Space *space, L4_fpage fp, L4_map_mask mask, Kobject ***rl)
 {
-  unsigned ret = 0;
+  L4_fpage::Rights ret(0);
+  Space::Caps caps = space->caps();
 
-  if (fp.is_iopage() || fp.is_all_spaces())
+  if ((caps & Space::Caps::io()) && (fp.is_iopage() || fp.is_all_spaces()))
     ret |= io_fpage_unmap(space, fp, mask);
 
-  if (fp.is_objpage() || fp.is_all_spaces())
+  if ((caps & Space::Caps::obj()) && (fp.is_objpage() || fp.is_all_spaces()))
     ret |= obj_fpage_unmap(space, fp, mask, rl);
 
-  if (fp.is_mempage() || fp.is_all_spaces())
+  if ((caps & Space::Caps::mem()) && (fp.is_mempage() || fp.is_all_spaces()))
     ret |= mem_fpage_unmap(space, fp, mask);
 
   return ret;
@@ -377,43 +296,41 @@ Reap_list::~Reap_list()
 // Utility functions for all address-space types
 //
 
-#include "mapdb.h"
-
 inline
 template <typename SPACE, typename MAPDB>
 L4_error
 map(MAPDB* mapdb,
     SPACE* from, Space *from_id,
-    Page_number _snd_addr,
-    Page_count snd_size,
+    typename SPACE::V_pfn snd_addr,
+    typename SPACE::V_pfc snd_size,
     SPACE* to, Space *to_id,
-    Page_number _rcv_addr,
-    bool grant, unsigned attrib_add, unsigned attrib_del,
+    typename SPACE::V_pfn rcv_addr,
+    bool grant, typename SPACE::Attr attribs,
     typename SPACE::Reap_list **reap_list = 0)
 {
-  enum
-  {
-    PAGE_SIZE = SPACE::Map_page_size,
-    PAGE_MASK = ~(PAGE_SIZE - 1),
-    SUPERPAGE_SIZE = SPACE::Map_superpage_size,
-    SUPERPAGE_MASK = ~((SUPERPAGE_SIZE - 1) >> SPACE::Page_shift)
-  };
+  using namespace Mu;
+
+  typedef typename SPACE::Attr Attr;
+  typedef typename SPACE::Page_order Page_order;
+
+  typedef typename SPACE::V_pfn V_pfn;
+  typedef typename SPACE::V_pfc V_pfc;
 
-  typedef typename SPACE::Size Size;
   typedef typename MAPDB::Mapping Mapping;
   typedef typename MAPDB::Frame Frame;
-  typedef typename Mu::Virt_addr<SPACE>::Type Vaddr;
   typedef Map_traits<SPACE> Mt;
 
+
   L4_error condition = L4_error::None;
 
   // FIXME: make this debugging code optional
   bool no_page_mapped = true;
 
-  Vaddr rcv_addr(_rcv_addr);
-  Vaddr snd_addr(_snd_addr);
-  const Vaddr rcv_start = rcv_addr;
-  const Page_count rcv_size = snd_size;
+  V_pfn const rcv_start = rcv_addr;
+  V_pfc const rcv_size = snd_size;
+
+  auto const to_fit_size = to->fitting_sizes();
+
   // We now loop through all the pages we want to send from the
   // sender's address space, looking up appropriate parent mappings in
   // the mapping data base, and entering a child mapping and a page
@@ -432,16 +349,18 @@ map(MAPDB* mapdb,
   // verify sender and receiver virtual addresses are still within
   // bounds; if not, bail out.  Sigma0 may send from any address (even
   // from an out-of-bound one)
-  Page_count size;
-  bool need_tlb_flush = false;
+
+  // increment variable for our map loop
+  V_pfc size;
+
+  bool from_needs_tlb_flush = false;
+  bool to_needs_tlb_flush = false;
   bool need_xcpu_tlb_flush = false;
-  Page_number const to_max = to->map_max_address();
-  Page_number const from_max = from->map_max_address();
-  Size const from_superpage_size(from->superpage_size());
-  bool const has_superpages = to->has_superpages();
+  V_pfn const to_max = to->map_max_address();
+  V_pfn const from_max = from->map_max_address();
 
   for (;
-       snd_size                               // pages left for sending?
+       snd_size != V_pfc(0)       // pages left for sending?
        && rcv_addr < to_max
        && snd_addr < from_max;
 
@@ -449,24 +368,26 @@ map(MAPDB* mapdb,
        snd_addr += size,
        snd_size -= size)
     {
-      // Reset the increment size to one page.
-      size = Size(PAGE_SIZE);
-
       // First, look up the page table entries in the sender and
       // receiver address spaces.
 
       // Sender lookup.
       // make gcc happy, initialized later anyway
       typename SPACE::Phys_addr s_phys;
-      Size s_size(0);
-      unsigned s_attribs = 0;
+      Page_order s_order;
+      Attr s_attribs;
 
       // Sigma0 special case: Sigma0 doesn't need to have a
       // fully-constructed page table, and it can fabricate mappings
-      // for all physical addresses.:435
+      // for all physical addresses.
       if (EXPECT_FALSE(! from->v_fabricate(snd_addr, &s_phys,
-                                           &s_size, &s_attribs)))
-       continue;
+                                           &s_order, &s_attribs)))
+        {
+          size = SPACE::to_size(s_order) - SPACE::subpage_offset(snd_addr, s_order);
+          if (size >= snd_size)
+            break;
+          continue;
+        }
 
       // We have a mapping in the sender's address space.
       // FIXME: make this debugging code optional
@@ -477,44 +398,37 @@ map(MAPDB* mapdb,
       // The may be used uninitialized warning for this variable is bogus
       // the v_lookup function must initialize the value if it returns true.
       typename SPACE::Phys_addr r_phys;
-      Size r_size;
-      unsigned r_attribs;
+      Page_order r_order;
+      Attr r_attribs;
 
       // Compute attributes for to-be-inserted frame
-      typename SPACE::Phys_addr i_phys = s_phys;
-      Size i_size = s_size;
-      bool const rcv_page_mapped
-       = to->v_lookup(rcv_addr, &r_phys, &r_size, &r_attribs);
-      // See if we have to degrade to non-superpage mappings
-      if (has_superpages && i_size == from_superpage_size)
-       {
-         if (i_size > snd_size
-             // 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?
-             || (rcv_addr + from_superpage_size > rcv_start + rcv_size))
-                                                     // rcv area to small?
-           {
-             // We map a 4K mapping from a 4MB mapping
-             i_size = Size(PAGE_SIZE);
-
-             if (Size super_offset = snd_addr.offset(Size(SUPERPAGE_SIZE)))
-               {
-                 // Just use OR here because i_phys may already contain
-                 // the offset. (As is on ARM)
-                 i_phys = SPACE::subpage_address(i_phys, super_offset);
-               }
-
-             if (grant)
-               {
-                 WARN("XXX Can't GRANT page from superpage (%p: " L4_PTR_FMT
-                      " -> %p: " L4_PTR_FMT "), demoting to MAP\n",
-                      from_id, snd_addr.value(), to_id, rcv_addr.value());
-                 grant = 0;
-               }
-           }
-       }
+      V_pfc page_offset = SPACE::subpage_offset(snd_addr, s_order);
+      typename SPACE::Phys_addr i_phys = SPACE::subpage_address(s_phys, page_offset);
+      Page_order i_order = to_fit_size(s_order);
+
+      V_pfc i_size = SPACE::to_size(i_order);
+      bool const rcv_page_mapped = to->v_lookup(rcv_addr, &r_phys, &r_order, &r_attribs);
+
+      while (i_size > snd_size
+          // want to send less than a superpage?
+          || i_order > r_order         // not enough space for superpage map?
+          || SPACE::subpage_offset(snd_addr, i_order) != V_pfc(0) // snd page not aligned?
+          || SPACE::subpage_offset(rcv_addr, i_order) != V_pfc(0) // rcv page not aligned?
+          || (rcv_addr + i_size > rcv_start + rcv_size))
+        // rcv area to small?
+        {
+          i_order = to_fit_size(--i_order);
+          i_size = SPACE::to_size(i_order);
+          if (grant)
+            {
+              WARN("XXX Can't GRANT page from superpage (%p: " L4_PTR_FMT
+                  " -> %p: " L4_PTR_FMT "), demoting to MAP\n",
+                  from_id,
+                  (unsigned long)cxx::int_value<V_pfn>(snd_addr), to_id,
+                  (unsigned long)cxx::int_value<V_pfn>(rcv_addr));
+              grant = 0;
+            }
+        }
 
       // Also, look up mapping database entry.  Depending on whether
       // we can overmap, either look up the destination mapping first
@@ -524,34 +438,34 @@ map(MAPDB* mapdb,
       // mapdb_frame will be initialized by the mapdb lookup function when
       // it returns true, so don't care about "may be use uninitialized..."
       Frame mapdb_frame;
-      bool doing_upgrade = false;
 
       if (rcv_page_mapped)
-       {
-         // We have something mapped.
-
-         // Check if we can upgrade mapping.  Otherwise, flush target
-         // mapping.
-         if (! grant                         // Grant currently always flushes
-             && r_size <= i_size             // Rcv frame in snd frame
-             && SPACE::page_address(r_phys, i_size) == i_phys
-             && (sender_mapping = mapdb->check_for_upgrade(r_phys, from_id, snd_addr, to_id, rcv_addr, &mapdb_frame)))
-           doing_upgrade = true;
-
-         if (! sender_mapping) // Need flush
-           {
-             unmap(mapdb, to, to_id, rcv_addr.trunc(r_size), r_size,
-                   L4_fpage::RWX, L4_map_mask::full(), reap_list);
-           }
-       }
-
-      if (! sender_mapping && mapdb->valid_address(s_phys))
-       {
-         if (EXPECT_FALSE(! mapdb->lookup(from_id,
-                                          snd_addr.trunc(s_size), s_phys,
-                                          &sender_mapping, &mapdb_frame)))
-           continue;           // someone deleted this mapping in the meantime
-       }
+        {
+          // We have something mapped.
+
+          // Check if we can upgrade mapping.  Otherwise, flush target
+          // mapping.
+          if (! grant                         // Grant currently always flushes
+              && r_order <= i_order             // Rcv frame in snd frame
+              && SPACE::page_address(r_phys, i_order) == i_phys)
+            sender_mapping = mapdb->check_for_upgrade(SPACE::to_pfn(r_phys), from_id,
+                                                      SPACE::to_pfn(snd_addr), to_id,
+                                                      SPACE::to_pfn(rcv_addr), &mapdb_frame);
+
+          if (! sender_mapping)        // Need flush
+            unmap(mapdb, to, to_id, SPACE::page_address(rcv_addr, r_order), SPACE::to_size(r_order),
+                  L4_fpage::Rights::FULL(), L4_map_mask::full(), reap_list);
+        }
+
+      // Loop increment is size of insertion
+      size = i_size;
+
+      if (! sender_mapping && mapdb->valid_address(SPACE::to_pfn(s_phys))
+          && EXPECT_FALSE(! mapdb->lookup(from_id,
+                                          SPACE::to_pfn(SPACE::page_address(snd_addr, s_order)),
+                                          SPACE::to_pfn(s_phys),
+                                          &sender_mapping, &mapdb_frame)))
+        continue;              // someone deleted this mapping in the meantime
 
       // from here mapdb_frame is always initialized, so ignore the warning
       // in grant / insert
@@ -561,138 +475,190 @@ map(MAPDB* mapdb,
       // (r_phys), the sender_mapping, and whether a receiver mapping
       // already exists (doing_upgrade).
 
-      unsigned i_attribs
-        = Mt::apply_attribs(s_attribs, i_phys, attrib_add, attrib_del);
-
-      // Loop increment is size of insertion
-      size = i_size;
+      Attr i_attribs = Mt::apply_attribs(s_attribs, i_phys, attribs);
 
       // Do the actual insertion.
       typename SPACE::Status status
-       = to->v_insert(i_phys, rcv_addr, i_size, i_attribs);
+        = to->v_insert(i_phys, rcv_addr, i_order, i_attribs);
 
       switch (status)
-       {
-       case SPACE::Insert_warn_exists:
-       case SPACE::Insert_warn_attrib_upgrade:
-       case SPACE::Insert_ok:
+        {
+        case SPACE::Insert_warn_exists:
+        case SPACE::Insert_warn_attrib_upgrade:
+        case SPACE::Insert_ok:
 
-         assert_kdb (mapdb->valid_address(s_phys) || status == SPACE::Insert_ok);
+          assert_kdb (mapdb->valid_address(SPACE::to_pfn(s_phys)) || status == SPACE::Insert_ok);
           // Never doing upgrades for mapdb-unmanaged memory
 
-         if (grant)
-           {
-             if (mapdb->valid_address(s_phys))
-               if (EXPECT_FALSE(!mapdb->grant(mapdb_frame, sender_mapping,
-                                              to_id, rcv_addr)))
-                 {
-                   // Error -- remove mapping again.
-                   to->v_delete(rcv_addr, i_size);
-
-                   // may fail due to quota limits
-                   condition = L4_error::Map_failed;
-                   break;
-                 }
-
-             from->v_delete(snd_addr.trunc(s_size), s_size);
-             need_tlb_flush = true;
-           }
-         else if (status == SPACE::Insert_ok)
-           {
-             assert_kdb (!doing_upgrade);
-
-             if (mapdb->valid_address(s_phys)
-                 && !mapdb->insert(mapdb_frame, sender_mapping,
-                                   to_id, rcv_addr,
-                                   i_phys, i_size))
-               {
-                 // Error -- remove mapping again.
-                 to->v_delete(rcv_addr, i_size);
-
-                 // XXX This is not race-free as the mapping could have
-                 // been used in the mean-time, but we do not care.
-                 condition = L4_error::Map_failed;
-                 break;
-               }
-           }
-
-         if (SPACE::Need_xcpu_tlb_flush && SPACE::Need_insert_tlb_flush)
-           need_xcpu_tlb_flush = true;
-
-         break;
-
-       case SPACE::Insert_err_nomem:
-         condition = L4_error::Map_failed;
-         break;
-
-       case SPACE::Insert_err_exists:
-         WARN("map (%s) skipping area (%p/%lx): " L4_PTR_FMT
-              " -> %p/%lx: " L4_PTR_FMT "(%lx)", SPACE::name,
-              from_id, Kobject_dbg::pointer_to_id(from_id), snd_addr.value(),
-              to_id, Kobject_dbg::pointer_to_id(to_id), rcv_addr.value(), i_size.value());
-         // Do not flag an error here -- because according to L4
-         // semantics, it isn't.
-         break;
-       }
+          if (grant)
+            {
+              if (mapdb->valid_address(SPACE::to_pfn(s_phys))
+                  && EXPECT_FALSE(!mapdb->grant(mapdb_frame, sender_mapping,
+                                                to_id, SPACE::to_pfn(rcv_addr))))
+                {
+                  // Error -- remove mapping again.
+                  to->v_delete(rcv_addr, i_order, L4_fpage::Rights::FULL());
+                  to_needs_tlb_flush = true;
+
+                  // may fail due to quota limits
+                  condition = L4_error::Map_failed;
+                  break;
+                }
+
+              from->v_delete(SPACE::page_address(snd_addr, s_order), s_order, L4_fpage::Rights::FULL());
+              from_needs_tlb_flush = true;
+            }
+          else if (status == SPACE::Insert_ok)
+            {
+              if (mapdb->valid_address(SPACE::to_pfn(s_phys))
+                  && !mapdb->insert(mapdb_frame, sender_mapping,
+                                    to_id, SPACE::to_pfn(rcv_addr),
+                                    SPACE::to_pfn(i_phys), SPACE::to_pcnt(i_order)))
+                {
+                  // Error -- remove mapping again.
+                  to->v_delete(rcv_addr, i_order, L4_fpage::Rights::FULL());
+                  to_needs_tlb_flush = true;
+
+                  // XXX This is not race-free as the mapping could have
+                  // been used in the mean-time, but we do not care.
+                  condition = L4_error::Map_failed;
+                  break;
+                }
+            }
+
+          if (SPACE::Need_xcpu_tlb_flush && SPACE::Need_insert_tlb_flush)
+            need_xcpu_tlb_flush = true;
+
+            {
+              V_pfc super_offset = SPACE::subpage_offset(snd_addr, i_order);
+              if (super_offset != V_pfc(0))
+                // Just use OR here because i_phys may already contain
+                // the offset. (As is on ARM)
+                i_phys = SPACE::subpage_address(i_phys, super_offset);
+            }
+
+          break;
+
+        case SPACE::Insert_err_nomem:
+          condition = L4_error::Map_failed;
+          break;
+
+        case SPACE::Insert_err_exists:
+          WARN("map (%s) skipping area (%p/%lx): " L4_PTR_FMT
+               " -> %p/%lx: " L4_PTR_FMT "(%lx)", SPACE::name,
+               from_id, Kobject_dbg::pointer_to_id(from_id),
+               (unsigned long)cxx::int_value<V_pfn>(snd_addr),
+               to_id, Kobject_dbg::pointer_to_id(to_id),
+               (unsigned long)cxx::int_value<V_pfn>(rcv_addr),
+               (unsigned long)cxx::int_value<V_pfc>(i_size));
+          // Do not flag an error here -- because according to L4
+          // semantics, it isn't.
+          break;
+        }
 
       if (sender_mapping)
-       mapdb->free(mapdb_frame);
+        mapdb->free(mapdb_frame);
 
       if (!condition.ok())
-       break;
+        break;
     }
 
-  if (need_tlb_flush)
-    from->tlb_flush();
+  if (from_needs_tlb_flush || to_needs_tlb_flush)
+    {
+      SPACE *f = from_needs_tlb_flush ? from : 0;
+      SPACE *t = to_needs_tlb_flush   ? to   : 0;
+      SPACE::tlb_flush_spaces(false, t, f);
+      if (SPACE::Need_xcpu_tlb_flush)
+        {
+          need_xcpu_tlb_flush = false;
+          Context::xcpu_tlb_flush(false, t, f);
+        }
+    }
 
-  if (SPACE::Need_xcpu_tlb_flush && need_xcpu_tlb_flush)
+  if (need_xcpu_tlb_flush)
     Context::xcpu_tlb_flush(false, to, from);
 
   // FIXME: make this debugging code optional
   if (EXPECT_FALSE(no_page_mapped))
-    {
-      WARN("nothing mapped: (%s) from [%p/%lx]: " L4_PTR_FMT
-           " size: " L4_PTR_FMT " to [%p/%lx]\n", SPACE::name,
-           from_id, Kobject_dbg::pointer_to_id(from_id), snd_addr.value(), rcv_size.value(),
-           to_id, Kobject_dbg::pointer_to_id(to_id));
-    }
+    WARN("nothing mapped: (%s) from [%p/%lx]: " L4_PTR_FMT
+         " size: " L4_PTR_FMT " to [%p/%lx]\n", SPACE::name,
+         from_id, Kobject_dbg::pointer_to_id(from_id),
+         (unsigned long)cxx::int_value<V_pfn>(snd_addr),
+         (unsigned long)cxx::int_value<V_pfc>(rcv_size),
+         to_id, Kobject_dbg::pointer_to_id(to_id));
 
   return condition;
 }
 
+// save access rights for Mem_space
+template<typename MAPDB>
+void
+save_access_flags(Mem_space *space, typename Mem_space::V_pfn page_address, bool me_too,
+                  typename MAPDB::Mapping *mapping,
+                  typename MAPDB::Frame const &mapdb_frame,
+                  L4_fpage::Rights page_rights)
+{
+  if (L4_fpage::Rights accessed = page_rights & (L4_fpage::Rights::RW()))
+    {
+      // When flushing access attributes from our space as well,
+      // cache them in parent space, otherwise in our space.
+      if (! me_too || !mapping->parent())
+        space->v_set_access_flags(page_address, accessed);
+      else
+        {
+          typename MAPDB::Mapping *parent = mapping->parent();
+          typename Mem_space::V_pfn parent_address = Mem_space::to_virt(mapdb_frame.vaddr(parent));
+          parent->space()->v_set_access_flags(parent_address, accessed);
+        }
+    }
+}
+
+// do nothing for IO and OBJs
+template<typename MAPDB, typename SPACE,
+         typename = typename cxx::enable_if<!cxx::is_same<SPACE, Mem_space>::value>::type>
+void
+save_access_flags(SPACE *, typename SPACE::V_pfn, bool,
+                  typename MAPDB::Mapping *,
+                  typename MAPDB::Frame const &,
+                  L4_fpage::Rights)
+{}
+
 
 template <typename SPACE, typename MAPDB>
-unsigned
+L4_fpage::Rights
 unmap(MAPDB* mapdb, SPACE* space, Space *space_id,
-      Page_number start, Page_count size, unsigned char rights,
+      typename SPACE::V_pfn start,
+      typename SPACE::V_pfc size,
+      L4_fpage::Rights rights,
       L4_map_mask mask, typename SPACE::Reap_list **reap_list)
 {
+  using namespace Mu;
 
-  typedef typename SPACE::Size Size;
   typedef typename MAPDB::Mapping Mapping;
   typedef typename MAPDB::Iterator Iterator;
   typedef typename MAPDB::Frame Frame;
-  typedef typename Mu::Virt_addr<SPACE>::Type Vaddr;
+
+  typedef typename SPACE::V_pfn V_pfn;
+  typedef typename SPACE::V_pfc V_pfc;
 
   bool me_too = mask.self_unmap();
 
-  Mword flushed_rights = 0;
-  Page_number end = start + size;
-  Page_number const map_max = space->map_max_address();
+  L4_fpage::Rights flushed_rights(0);
+  V_pfn end = start + size;
+  V_pfn const map_max = space->map_max_address();
 
   // make gcc happy, initialized later anyway
   typename SPACE::Phys_addr phys;
-  Page_count phys_size;
-  Vaddr page_address;
+  V_pfc phys_size;
+  V_pfn page_address;
 
-  Mword const flush_rights = SPACE::xlate_flush(rights);
   bool const full_flush = SPACE::is_full_flush(rights);
   bool need_tlb_flush = false;
   bool need_xcpu_tlb_flush = false;
 
   // iterate over all pages in "space"'s page table that are mapped
   // into the specified region
-  for (Vaddr address(start);
+  for (V_pfn address = start;
        address < end && address < map_max;
        address = page_address + phys_size)
     {
@@ -701,79 +667,72 @@ unmap(MAPDB* mapdb, SPACE* space, Space *space_id,
 
       bool have_page;
 
-       {
-         Size ps;
-         have_page = space->v_fabricate(address, &phys, &ps);
-         phys_size = ps;
-       }
+      typename SPACE::Page_order phys_order;
+      have_page = space->v_fabricate(address, &phys, &phys_order);
 
-      page_address = address.trunc(phys_size);
+      phys_size = SPACE::to_size(phys_order);
+      page_address = SPACE::page_address(address, phys_order);
 
       // phys_size and page_address have now been set up, allowing the
       // use of continue (which evaluates the for-loop's iteration
       // expression involving these to variables).
 
       if (! have_page)
-       continue;
+        continue;
 
       if (me_too)
-       {
-         assert_kdb (address == page_address
-                 || phys_size == Size(SPACE::Map_superpage_size));
-
-         // Rewind flush address to page address.  We always flush
-         // the whole page, even if it is larger than the specified
-         // flush area.
-         address = page_address;
-         if (end < address + phys_size)
-           end = address + phys_size;
-       }
+        {
+          // Rewind flush address to page address.  We always flush
+          // the whole page, even if it is larger than the specified
+          // flush area.
+          address = page_address;
+          if (end < address + phys_size)
+            end = address + phys_size;
+        }
 
       // all pages shall be handled by our mapping data base
-      assert_kdb (mapdb->valid_address(phys));
+      assert_kdb (mapdb->valid_address(SPACE::to_pfn(phys)));
 
       Mapping *mapping;
       Frame mapdb_frame;
 
-      if (! mapdb->lookup(space_id, page_address, phys,
-                         &mapping, &mapdb_frame))
-       // someone else unmapped faster
-       continue;               // skip
+      if (! mapdb->lookup(space_id, SPACE::to_pfn(page_address), SPACE::to_pfn(phys),
+                          &mapping, &mapdb_frame))
+        // someone else unmapped faster
+        continue;              // skip
 
-      Mword page_rights = 0;
+      L4_fpage::Rights page_rights(0);
 
       // Delete from this address space
       if (me_too)
-       {
-         page_rights |=
-           space->v_delete(address, phys_size, flush_rights);
+        {
+          page_rights |=
+            space->v_delete(address, phys_order, rights);
 
           // assert_kdb (full_flush != space->v_lookup(address));
-         need_tlb_flush = true;
-         need_xcpu_tlb_flush = true;
-       }
+          need_tlb_flush = true;
+          need_xcpu_tlb_flush = true;
+        }
 
       // now delete from the other address spaces
-      for (Iterator m(mapdb_frame, mapping, address, end);
-          m;
-          ++m)
-       {
-         page_rights |= Mu::v_delete<SPACE>(m, flush_rights, full_flush);
-         need_xcpu_tlb_flush = true;
-       }
+      for (Iterator m(mapdb_frame, mapping, SPACE::to_pfn(address), SPACE::to_pfn(end));
+           m;
+           ++m)
+        {
+          page_rights |= v_delete<SPACE>(m, rights, full_flush);
+          need_xcpu_tlb_flush = true;
+        }
 
       flushed_rights |= page_rights;
 
       // Store access attributes for later retrieval
-      save_access_attribs(mapdb, mapdb_frame, mapping,
-                         space, page_rights, page_address, phys, phys_size,
-                         me_too);
+      save_access_flags<MAPDB>(space, page_address, me_too, mapping, mapdb_frame, page_rights);
 
       if (full_flush)
-       mapdb->flush(mapdb_frame, mapping, mask, address, end);
+        mapdb->flush(mapdb_frame, mapping, mask, SPACE::to_pfn(address), SPACE::to_pfn(end));
 
       if (full_flush)
-       Map_traits<SPACE>::free_object(phys, reap_list);
+        Map_traits<SPACE>::free_object(phys, reap_list);
 
       mapdb->free(mapdb_frame);
     }
@@ -784,7 +743,7 @@ unmap(MAPDB* mapdb, SPACE* space, Space *space_id,
   if (SPACE::Need_xcpu_tlb_flush && need_xcpu_tlb_flush)
     Context::xcpu_tlb_flush(true, space, 0);
 
-  return SPACE::xlate_flush_result(flushed_rights);
+  return flushed_rights;
 }
 
 //----------------------------------------------------------------------------
@@ -803,9 +762,9 @@ io_map(Space *, L4_fpage const &, Space *, L4_fpage const &, L4_msg_item)
 }
 
 inline
-unsigned
+L4_fpage::Rights
 io_fpage_unmap(Space * /*space*/, L4_fpage const &/*fp*/, L4_map_mask)
 {
-  return 0;
+  return L4_fpage::Rights(0);
 }
 
index 3796072e95af50ec0da6a573a08257f6f6375d3a..27ea61888622a90e28a4ee7f8f51212ca6494e36 100644 (file)
@@ -19,39 +19,44 @@ class Mapdb
 
 public:
   typedef ::Mapping Mapping;
+  typedef Mapping::Pfn Pfn;
+  typedef Mapping::Pcnt Pcnt;
+  typedef Mdb_types::Order Order;
+
   class Frame;
+
   /** Iterator for mapping trees.  This iterator knows how to descend
     into Treemap nodes.
    */
   class Iterator
   {
+    typedef Mapping::Page Page;
     Mapping_tree* _mapping_tree;
     Mapping* _parent;
     Mapping* _cursor;
-    size_t   _page_shift;
+    Order  _page_shift;
     Treemap *_submap;
     Physframe *_subframe;
-    Page_number _submap_index;
-    Page_number _offs_begin, _offs_end;
+    Page _submap_index;
+    Pcnt _offs_begin, _offs_end;
 
   public:
     inline Mapping* operator->() const { return _cursor; }
     inline operator Mapping*() const { return _cursor; }
-    inline Iterator() : _submap (0), _submap_index(Page_number::create(0)) {}
+    inline Iterator() : _submap (0), _submap_index(Page(0)) {}
     inline Iterator(const Mapdb::Frame& f, Mapping* parent,
-                    Page_number va_begin, Page_number va_end);
+                    Pfn va_begin, Pfn va_end);
     inline ~Iterator();
     inline void neutralize();
-    inline Page_count size() const;
-    inline size_t shift() const { return _page_shift; }
-    inline Page_number page() const
-    { return Page_number(_cursor->page() << shift()); }
+    inline Order order() const { return _page_shift; }
+    inline Pfn page() const
+    { return Pfn(cxx::int_value<Page>(_cursor->page())) << order(); }
 
     inline Iterator &operator++ ();
   };
 
   // TYPES
-  class Frame 
+  class Frame
   {
     friend class Mapdb;
     friend class Mapdb::Iterator;
@@ -59,7 +64,8 @@ public:
     Physframe* frame;
 
   public:
-    inline Page_number vaddr(Mapping* m) const;
+    inline Pfn vaddr(Mapping* m) const;
+    inline Order page_shift() const;
   };
 
 private:
@@ -176,7 +182,6 @@ IMPLEMENTATION:
 #include "helping_lock.h"
 #include "kmem_alloc.h"
 #include "mapping_tree.h"
-#include "paging.h"
 #include "kmem_slab.h"
 #include "ram_quota.h"
 #include "std_macros.h"
@@ -269,14 +274,21 @@ Physframe::free(Physframe *block, size_t size)
 
 class Treemap
 {
+public:
+  typedef Mapping_tree::Page Page;
+  typedef Mapdb::Pfn Pfn;
+  typedef Mapdb::Pcnt Pcnt;
+  typedef Mapdb::Order Order;
+
+private:
   friend class Jdb_mapdb;
   friend class Treemap_ops;
 
   // DATA
-  Page_count _key_end;         ///< Number of Physframe entries
+  Page _key_end;               ///< Number of Physframe entries
   Space *_owner_id;    ///< ID of owner of mapping trees 
-  Page_number _page_offset;    ///< Virt. page address in owner's addr space
-  size_t _page_shift;          ///< Page size of mapping trees
+  Pfn _page_offset;    ///< Virt. page address in owner's addr space
+  Order _page_shift;           ///< Page size of mapping trees
   Physframe* _physframe;       ///< Pointer to Physframe array
   const size_t* const _sub_shifts; ///< Pointer to array of sub-page sizes
   const unsigned _sub_shifts_max;  ///< Number of valid _page_sizes entries
@@ -292,22 +304,36 @@ class Treemap
 
 class Treemap_ops
 {
-  unsigned long _page_shift;
+  typedef Treemap::Order Order;
+  typedef Treemap::Page Page;
+  typedef Treemap::Pfn Pfn;
+  typedef Treemap::Pcnt Pcnt;
+  Order _page_shift;
 };
 
 PUBLIC inline
-Treemap_ops::Treemap_ops(unsigned long page_shift)
+Treemap_ops::Treemap_ops(Order page_shift)
 : _page_shift(page_shift)
 {}
 
+PUBLIC inline
+Treemap::Pfn
+Treemap_ops::to_vaddr(Page v) const
+{ return Pfn(cxx::int_value<Page>(v << _page_shift)); }
+
+PUBLIC inline
+Treemap::Pcnt
+Treemap_ops::page_size() const
+{ return Pcnt(1) << _page_shift; }
+
 PUBLIC 
 unsigned long
 Treemap_ops::mem_size(Treemap const *submap) const
 {
-  unsigned long quota 
-    = submap->_key_end.value() * sizeof(Physframe) + sizeof(Treemap);
+  unsigned long quota
+    = cxx::int_value<Page>(submap->_key_end) * sizeof(Physframe) + sizeof(Treemap);
 
-  for (Page_number key = Page_number::create(0);
+  for (Page key = Page(0);
       key < submap->_key_end;
       ++key)
     {
@@ -321,12 +347,12 @@ Treemap_ops::mem_size(Treemap const *submap) const
 
 PUBLIC
 void
-Treemap_ops::grant(Treemap *submap, Space *new_space, Page_number va) const
+Treemap_ops::grant(Treemap *submap, Space *new_space, Page page) const
 {
   submap->_owner_id = new_space;
-  submap->_page_offset = va << _page_shift;
+  submap->_page_offset = to_vaddr(page);
 
-  for (Page_number key = Page_number::create(0);
+  for (Page key = Page(0);
       key < submap->_key_end;
       ++key)
     {
@@ -335,7 +361,7 @@ Treemap_ops::grant(Treemap *submap, Space *new_space, Page_number va) const
        {
          auto guard = lock_guard(subframe->lock);
          tree->mappings()->set_space(new_space);
-         tree->mappings()->set_page(va + (key >> (_page_shift - submap->_page_shift)));
+         tree->mappings()->set_page(page + (key >> (_page_shift - submap->_page_shift)));
        }
     }
 }
@@ -347,11 +373,11 @@ Treemap_ops::owner(Treemap const *submap) const
 
 PUBLIC inline
 bool
-Treemap_ops::is_partial(Treemap const *submap, Page_count offs_begin,
-                        Page_count offs_end) const
+Treemap_ops::is_partial(Treemap const *submap, Treemap::Pcnt offs_begin,
+                        Treemap::Pcnt offs_end) const
 {
-  return offs_begin > Page_count::create(0)
-    || offs_end < (submap->_key_end << submap->_page_shift);
+  return offs_begin > Treemap::Pcnt(0)
+         || offs_end < submap->size();
 }
 
 PUBLIC inline
@@ -359,19 +385,21 @@ void
 Treemap_ops::del(Treemap *submap) const
 { delete submap; }
 
-PUBLIC inline
+PUBLIC inline NEEDS[Treemap::round_to_page, Treemap::trunc_to_page]
 void
 Treemap_ops::flush(Treemap *submap,
-                   Page_number offs_begin, Page_number offs_end) const
+                   Treemap::Pcnt offs_begin, Treemap::Pcnt offs_end) const
 {
-  for (Page_number i = offs_begin >> submap->_page_shift;
-      i < (offs_end + Page_count::create((1UL << submap->_page_shift) - 1)
-       >> submap->_page_shift);
+  typedef Treemap::Pcnt Pcnt;
+  typedef Treemap::Pfn Pfn;
+
+  for (Treemap::Page i = submap->trunc_to_page(offs_begin);
+      i < submap->round_to_page(offs_end);
       i++)
     {
-      Page_count page_offs_begin = i << submap->_page_shift;
-      Page_count page_offs_end = page_offs_begin;
-      page_offs_end += Page_count::create(1UL << submap->_page_shift);
+      Pcnt page_offs_begin = submap->to_vaddr(i) - Pfn(0);
+      Pcnt page_offs_end = page_offs_begin;
+      page_offs_end += submap->page_size();
 
       Physframe* subframe = submap->frame(i);
 
@@ -381,15 +409,13 @@ Treemap_ops::flush(Treemap *submap,
        subframe->tree.reset();
       else
        {
-         Page_count psz = Page_count::create(1UL << _page_shift);
           // FIXME: do we have to check for subframe->tree != 0 here ?
          submap->flush(subframe, subframe->tree->mappings(), false,
            page_offs_begin > offs_begin
-           ? Page_number::create(0) : offs_begin.offset(psz),
+           ? Pcnt(0) : cxx::get_lsb(offs_begin, _page_shift),
            page_offs_end < offs_end
-           ? psz
-           : (offs_end - Page_count::create(1)).offset(psz)
-             + Page_count::create(1));
+           ? page_size()
+           : cxx::get_lsb(offs_end - Pcnt(1), _page_shift) + Pcnt(1));
        }
     }
 }
@@ -400,8 +426,8 @@ Treemap_ops::flush(Treemap *submap,
 //
 
 PRIVATE inline
-Treemap::Treemap(Page_number key_end, Space *owner_id,
-                 Page_number page_offset, size_t page_shift,
+Treemap::Treemap(Page key_end, Space *owner_id,
+                 Pfn page_offset, Order page_shift,
                  const size_t* sub_shifts, unsigned sub_shifts_max,
                  Physframe *physframe)
   : _key_end(key_end),
@@ -415,15 +441,43 @@ Treemap::Treemap(Page_number key_end, Space *owner_id,
   assert (_physframe);
 }
 
+PUBLIC inline
+Treemap::Page
+Treemap::round_to_page(Pcnt v) const
+{
+  return Page(cxx::int_value<Pcnt>(v + ((Pcnt(1) << _page_shift) - Pcnt(1))
+              >> _page_shift));
+}
+
+PUBLIC inline
+Treemap::Page
+Treemap::trunc_to_page(Pcnt v) const
+{ return Page(cxx::int_value<Pcnt>(v >> _page_shift)); }
+
+PUBLIC inline
+Treemap::Page
+Treemap::trunc_to_page(Pfn v) const
+{ return Page(cxx::int_value<Pfn>(v >> _page_shift)); }
+
+PUBLIC inline
+Treemap::Pfn
+Treemap::to_vaddr(Page v) const
+{ return Pfn(cxx::int_value<Page>(v << _page_shift)); }
+
+PUBLIC inline
+Treemap::Pcnt
+Treemap::page_size() const
+{ return Pcnt(1) << _page_shift; }
+
 PRIVATE static inline
 unsigned long
-Treemap::quota_size(Page_number key_end)
-{ return Physframe::mem_size(key_end.value()) + sizeof(Treemap); }
+Treemap::quota_size(Page key_end)
+{ return Physframe::mem_size(cxx::int_value<Page>(key_end)) + sizeof(Treemap); }
 
 PUBLIC static
 Treemap *
-Treemap::create(Page_number key_end, Space *owner_id,
-                Page_number page_offset, size_t page_shift,
+Treemap::create(Page key_end, Space *owner_id,
+                Pfn page_offset, Order page_shift,
                 const size_t* sub_shifts, unsigned sub_shifts_max)
 {
   Auto_quota<Ram_quota> quota(Mapping_tree::quota(owner_id), quota_size(key_end));
@@ -431,8 +485,7 @@ Treemap::create(Page_number key_end, Space *owner_id,
   if (EXPECT_FALSE(!quota))
     return 0;
 
-
-  Physframe *pf = Physframe::alloc(key_end.value());
+  Physframe *pf = Physframe::alloc(cxx::int_value<Page>(key_end));
 
   if (EXPECT_FALSE(!pf))
     return 0;
@@ -440,7 +493,7 @@ Treemap::create(Page_number key_end, Space *owner_id,
   void *m = allocator()->alloc();
   if (EXPECT_FALSE(!m))
     {
-      Physframe::free(pf, key_end.value());
+      Physframe::free(pf, cxx::int_value<Page>(key_end));
       return 0;
     }
 
@@ -455,7 +508,7 @@ PUBLIC
 inline NEEDS[Physframe::free, Mapdb] //::Iterator::neutralize]
 Treemap::~Treemap()
 {
-  Physframe::free(_physframe, _key_end.value());
+  Physframe::free(_physframe, cxx::int_value<Page>(_key_end));
 
   // Make sure that _unwind.~Mapdb_iterator is harmless: Reinitialize it.
   _unwind.neutralize();
@@ -481,7 +534,7 @@ Treemap::operator delete (void *block)
 }
 
 PUBLIC inline
-size_t
+Treemap::Order
 Treemap::page_shift() const
 {
   return _page_shift;
@@ -494,34 +547,42 @@ Treemap::owner() const
   return _owner_id;
 }
 
-PUBLIC inline
-Page_number
+
+PUBLIC inline NEEDS[Treemap::to_vaddr]
+Treemap::Pcnt
+Treemap::size() const
+{
+  return to_vaddr(_key_end) - Pfn(0);
+}
+
+PUBLIC inline NEEDS[Treemap::size]
+Treemap::Pfn
 Treemap::end_addr() const
 {
-  return (_key_end << _page_shift) + _page_offset;
+  return _page_offset + size();
 }
 
-PUBLIC inline NEEDS["paging.h"]
-Page_number
+PUBLIC inline NEEDS[Treemap::to_vaddr]
+Treemap::Pfn
 Treemap::vaddr(Mapping* m) const
 {
-  return m->page() << _page_shift;
+  return to_vaddr(m->page());
 }
 
 PUBLIC inline
 void
-Treemap::set_vaddr(Mapping* m, Page_number address) const
+Treemap::set_vaddr(Mapping* m, Pfn address) const
 {
-  m->set_page(address >> _page_shift);
+  m->set_page(trunc_to_page(address));
 }
 
 PUBLIC
 Physframe*
-Treemap::tree(Page_number key)
+Treemap::tree(Page key)
 {
   assert (key < _key_end);
 
-  Physframe *f = &_physframe[key.value()];
+  Physframe *f = &_physframe[cxx::int_value<Page>(key)];
 
   f->lock.lock();
 
@@ -535,7 +596,7 @@ Treemap::tree(Page_number key)
         }
 
       cxx::unique_ptr<Mapping_tree> new_tree
-       (new (Mapping_tree::Size_id_min) Mapping_tree(Mapping_tree::Size_id_min, key + (_page_offset >> _page_shift),
+       (new (Mapping_tree::Size_id_min) Mapping_tree(Mapping_tree::Size_id_min, key + trunc_to_page(_page_offset),
                              _owner_id));
 
       if (EXPECT_FALSE(!new_tree))
@@ -553,30 +614,30 @@ Treemap::tree(Page_number key)
 
 PUBLIC
 Physframe*
-Treemap::frame(Page_number key) const
+Treemap::frame(Page key) const
 {
   assert (key < _key_end);
 
-  return &_physframe[key.value()];
+  return &_physframe[cxx::int_value<Page>(key)];
 }
 
 PUBLIC
 bool
-Treemap::lookup(Page_number key, Space *search_space, Page_number search_va,
+Treemap::lookup(Pcnt key, Space *search_space, Pfn search_va,
                 Mapping** out_mapping, Treemap** out_treemap,
                 Physframe** out_frame)
 {
   // get and lock the tree.
-  assert (key >> _page_shift < _key_end);
-  Physframe *f = tree(key >> _page_shift); // returns locked frame
+  assert (trunc_to_page(key) < _key_end);
+  Physframe *f = tree(trunc_to_page(key)); // returns locked frame
   assert (f);
 
   Mapping_tree *t = f->tree.get();
-  Page_count const psz = Page_count::create(1UL << _page_shift);
+  Order const psz = _page_shift;
 
   assert (t);
   assert (t->mappings()[0].space() == _owner_id);
-  assert (vaddr(t->mappings()) == key.trunc(psz) + _page_offset);
+  assert (vaddr(t->mappings()) == cxx::mask_lsb(key, psz) + _page_offset);
 
   Mapping *m;
   bool ret = false;
@@ -587,13 +648,13 @@ Treemap::lookup(Page_number key, Space *search_space, Page_number search_va,
        {
          // XXX Recursion.  The max. recursion depth should better be
          // limited!
-         if ((ret = sub->lookup(key.offset(psz),
+         if ((ret = sub->lookup(cxx::get_lsb(key, psz),
                                 search_space, search_va,
                                 out_mapping, out_treemap, out_frame)))
            break;
        }
       else if (m->space() == search_space
-              && vaddr(m) == search_va.trunc(psz))
+              && vaddr(m) == cxx::mask_lsb(search_va, psz))
        {
          *out_mapping = m;
          *out_treemap = this;
@@ -611,22 +672,18 @@ Treemap::lookup(Page_number key, Space *search_space, Page_number search_va,
 PUBLIC
 Mapping *
 Treemap::insert(Physframe* frame, Mapping* parent, Space *space,
-                Page_number va, Page_number phys, Page_count size)
+                Pfn va, Pcnt phys, Pcnt size)
 {
   Mapping_tree* t = frame->tree.get();
   Treemap* submap = 0;
   Ram_quota *payer;
-  Page_count const psz = Page_count::create(1UL << _page_shift);
-  bool insert_submap = psz != size;
+  Order const psz = _page_shift;
+  bool insert_submap = page_size() != size;
 
   // Inserting subpage mapping?  See if we can find a submap.  If so,
   // we don't have to allocate a new Mapping entry.
   if (insert_submap)
-    {
-      assert (psz > size);
-
-      submap = t->find_submap(parent);
-    }
+    submap = t->find_submap(parent);
 
   if (! submap) // Need allocation of new entry -- for submap or
                // normal mapping
@@ -652,8 +709,8 @@ Treemap::insert(Physframe* frame, Mapping* parent, Space *space,
       assert (_sub_shifts_max > 0);
 
       submap
-        = Treemap::create(Page_number::create(1UL << (_page_shift - _sub_shifts[0])),
-            parent->space(), vaddr(parent), _sub_shifts[0],
+        = Treemap::create(Page(1) << (_page_shift - Order(_sub_shifts[0])),
+            parent->space(), vaddr(parent), Order(_sub_shifts[0]),
             _sub_shifts + 1, _sub_shifts_max - 1);
       if (! submap)
        {
@@ -665,7 +722,7 @@ Treemap::insert(Physframe* frame, Mapping* parent, Space *space,
       free->set_submap(submap);
     }
 
-  Physframe* subframe = submap->tree(phys.offset(psz) >> submap->_page_shift);
+  Physframe* subframe = submap->tree(submap->trunc_to_page(cxx::get_lsb(phys, psz)));
   if (! subframe)
     return 0;
 
@@ -675,8 +732,8 @@ Treemap::insert(Physframe* frame, Mapping* parent, Space *space,
     return 0;
 
   // XXX recurse.
-  Mapping* ret = submap->insert(subframe, subtree->mappings(), space, va, 
-                                phys.offset(psz), size);
+  Mapping* ret = submap->insert(subframe, subtree->mappings(), space, va,
+                                cxx::get_lsb(phys, psz), size);
   submap->free(subframe);
 
   return ret;
@@ -697,7 +754,7 @@ Treemap::free(Physframe* f)
 PUBLIC
 void
 Treemap::flush(Physframe* f, Mapping* parent, bool me_too,
-               Page_number offs_begin, Page_number offs_end)
+               Pcnt offs_begin, Pcnt offs_end)
 {
   assert (! parent->unused());
 
@@ -712,9 +769,9 @@ Treemap::flush(Physframe* f, Mapping* parent, bool me_too,
 
 PUBLIC
 bool
-Treemap::grant(Physframe* f, Mapping* m, Space *new_space, Page_number va)
+Treemap::grant(Physframe* f, Mapping* m, Space *new_space, Pfn va)
 {
-  return f->tree->grant(m, new_space, va >> _page_shift,
+  return f->tree->grant(m, new_space, trunc_to_page(va),
                         Treemap_ops(_page_shift));
 }
 
@@ -730,25 +787,28 @@ Treemap::grant(Physframe* f, Mapping* m, Space *new_space, Page_number va)
  */
 IMPLEMENT inline NEEDS[Treemap::vaddr]
 Mapdb::Iterator::Iterator(const Mapdb::Frame& f, Mapping* parent,
-                          Page_number va_begin, Page_number va_end)
+                          Pfn va_begin, Pfn va_end)
   : _mapping_tree(f.frame->tree.get()),
     _parent(parent),
     _cursor(parent),
     _page_shift(f.treemap->_page_shift),
     _submap(0),
     _subframe(0),
-    _submap_index(Page_number::create(0))
+    _submap_index(Page(0))
 {
   assert (_mapping_tree == Mapping_tree::head_of(parent));
   assert (! parent->submap());
+  assert (va_begin <= va_end);
 
-  if (va_begin < f.treemap->vaddr(parent))
-    va_begin = f.treemap->vaddr(parent);
-  if (va_begin > va_end)
-    va_begin = va_end;
+  if (va_begin <= f.treemap->vaddr(parent))
+    _offs_begin = Pcnt(0);
+  else
+    _offs_begin = va_begin - f.treemap->vaddr(parent);
 
-  _offs_begin = va_begin - f.treemap->vaddr(parent);
-  _offs_end = va_end - f.treemap->vaddr(parent);
+  if (va_end <= f.treemap->vaddr(parent))
+    _offs_end = Pcnt(0);
+  else
+    _offs_end = va_end - f.treemap->vaddr(parent);
 
   ++*this;
 }
@@ -775,14 +835,7 @@ Mapdb::Iterator::neutralize()
   _submap = 0;
 }
 
-IMPLEMENT inline 
-Page_count
-Mapdb::Iterator::size() const
-{
-  return Page_count(1UL << _page_shift);
-}
-
-IMPLEMENT inline NEEDS ["mapping_tree.h"]
+IMPLEMENT inline NEEDS [Treemap::round_to_page, "mapping_tree.h"]
 Mapdb::Iterator&
 Mapdb::Iterator::operator++ ()
 {
@@ -810,19 +863,18 @@ Mapdb::Iterator::operator++ ()
          // to other subpages because operations on a part of a
          // superpage always affect *complete* child-superpages, as
          // we do not support splitting out parts of superpages.
-         Page_count parent_size = submap->_key_end << submap->_page_shift;
+         Pcnt parent_size = submap->size();
 
-         if (_offs_end > parent_size)
-           _offs_end = parent_size;
 
          if (_cursor->parent() == _parent)
            {                   // Submap of iteration root
-             _offs_begin = _offs_begin.offset(parent_size);
-             _offs_end = (_offs_end - Page_count::create(1)).offset(parent_size) + Page_count::create(1);
+              assert (_offs_begin < parent_size);
+              if (_offs_end > parent_size)
+                _offs_end = parent_size;
            }
          else                  // Submap of a child mapping
            {
-             _offs_begin = Page_number::create(0);
+             _offs_begin = Pcnt(0);
              _offs_end = parent_size;
            }
 
@@ -830,7 +882,7 @@ Mapdb::Iterator::operator++ ()
          _submap = submap;
          _page_shift = _submap->_page_shift;
          _subframe = 0;
-         _submap_index = _offs_begin >> _page_shift;
+         _submap_index = Page(cxx::int_value<Pcnt>(_offs_begin >> _page_shift));
          _mapping_tree = 0;
          _parent = _cursor = 0;
        }
@@ -848,10 +900,7 @@ Mapdb::Iterator::operator++ ()
       // Find a new subframe.
       Physframe* f = 0;
 
-      Page_count end_offs = _offs_end;
-      end_offs += Page_count::create((1UL << _submap->_page_shift) - 1);
-      end_offs >>= _submap->_page_shift;
-
+      Page end_offs = _submap->round_to_page(_offs_end);
       assert (end_offs <= _submap->_key_end);
 
       for (; _submap_index < end_offs;)
@@ -885,11 +934,11 @@ Mapdb::Iterator::operator++ ()
            Config::Mapdb_ram_only is true.) 
  */
 PUBLIC
-Mapdb::Mapdb(Space *owner, Page_number end_frame, size_t const *page_shifts,
+Mapdb::Mapdb(Space *owner, Mapping::Page end_frame, size_t const *page_shifts,
              unsigned page_shifts_max)
 : _treemap(Treemap::create(end_frame, owner,
-                           Page_number::create(0),
-                           page_shifts[0], page_shifts + 1,
+                           Pfn(0),
+                           Order(page_shifts[0]), page_shifts + 1,
                            page_shifts_max - 1))
 {
   // assert (boot_time);
@@ -922,9 +971,10 @@ Mapdb::~Mapdb()
 PUBLIC
 Mapping *
 Mapdb::insert(const Mapdb::Frame& frame, Mapping* parent, Space *space,
-              Page_number va, Page_number phys, Page_count size)
+              Pfn va, Pfn phys, Pcnt size)
 {
-  return frame.treemap->insert(frame.frame, parent, space, va, phys, size);
+  return frame.treemap->insert(frame.frame, parent, space, va, phys - Pfn(0),
+                               size);
 } // insert()
 
 
@@ -942,10 +992,10 @@ Mapdb::insert(const Mapdb::Frame& frame, Mapping* parent, Space *space,
  */
 PUBLIC
 bool
-Mapdb::lookup(Space *space, Page_number va, Page_number phys,
+Mapdb::lookup(Space *space, Pfn va, Pfn phys,
              Mapping** out_mapping, Mapdb::Frame* out_lock)
 {
-  return _treemap->lookup(phys, space, va, out_mapping,
+  return _treemap->lookup(phys - Pfn(0), space, va, out_mapping,
                           & out_lock->treemap, & out_lock->frame);
 }
 
@@ -977,13 +1027,15 @@ Mapdb::free(const Mapdb::Frame& f)
 PUBLIC static
 void
 Mapdb::flush(const Mapdb::Frame& f, Mapping *m, L4_map_mask mask,
-             Page_number va_start, Page_number va_end)
+             Pfn va_start, Pfn va_end)
 {
-  Page_count size = Page_count::create(1UL << f.treemap->page_shift());
-  Page_number offs_begin = va_start > f.treemap->vaddr(m)
-    ? va_start - f.treemap->vaddr(m) : Page_number::create(0);
-  Page_number offs_end = va_end > f.treemap->vaddr(m) + size
-    ? size : va_end - f.treemap->vaddr(m);
+  Pcnt size = f.treemap->page_size();
+  Pcnt offs_begin = va_start > f.treemap->vaddr(m)
+                  ? va_start - f.treemap->vaddr(m)
+                  : Pcnt(0);
+  Pcnt offs_end = va_end > f.treemap->vaddr(m) + size
+                ? size
+                : va_end - f.treemap->vaddr(m);
 
   f.treemap->flush(f.frame, m, mask.self_unmap(), offs_begin, offs_end);
 } // flush()
@@ -997,14 +1049,14 @@ Mapdb::flush(const Mapdb::Frame& f, Mapping *m, L4_map_mask mask,
 PUBLIC
 bool
 Mapdb::grant(const Mapdb::Frame& f, Mapping *m, Space *new_space,
-             Page_number va)
+             Pfn va)
 {
   return f.treemap->grant(f.frame, m, new_space, va);
 }
 
 /** Return page size of given mapping and frame. */
 PUBLIC static inline NEEDS[Treemap::page_shift]
-size_t
+Mapdb::Order
 Mapdb::shift(const Mapdb::Frame& f, Mapping * /*m*/)
 {
   // XXX add special case for _mappings[0]: Return superpage size.
@@ -1012,7 +1064,7 @@ Mapdb::shift(const Mapdb::Frame& f, Mapping * /*m*/)
 }
 
 PUBLIC static inline NEEDS[Treemap::vaddr]
-Page_number
+Mapdb::Pfn
 Mapdb::vaddr(const Mapdb::Frame& f, Mapping* m)
 {
   return f.treemap->vaddr(m);
@@ -1023,26 +1075,30 @@ Mapdb::vaddr(const Mapdb::Frame& f, Mapping* m)
 // 
 
 IMPLEMENT inline NEEDS[Treemap::vaddr]
-Page_number
+Mapdb::Pfn
 Mapdb::Frame::vaddr(Mapping* m) const
-{
-  return treemap->vaddr(m);
+{ return treemap->vaddr(m); }
 
-}
+IMPLEMENT inline NEEDS[Treemap::page_shift]
+Mapdb::Order
+Mapdb::Frame::page_shift() const
+{ return treemap->page_shift(); }
 
 PUBLIC inline NEEDS [Treemap::end_addr]
 bool
-Mapdb::valid_address(Page_number phys)
+Mapdb::valid_address(Pfn phys)
 {
+  // on the root level physical and virtual frame numbers
+  // are the same
   return phys < _treemap->end_addr();
 }
 
 
 PUBLIC inline
 Mapdb::Mapping *
-Mapdb::check_for_upgrade(Page_number phys,
-                         Space *from_id, Page_number snd_addr,
-                         Space *to_id, Page_number rcv_addr,
+Mapdb::check_for_upgrade(Pfn phys,
+                         Space *from_id, Pfn snd_addr,
+                         Space *to_id, Pfn rcv_addr,
                          Frame *mapdb_frame)
 {
   // Check if we can upgrade mapping.  Otherwise, flush target
@@ -1069,10 +1125,10 @@ bool
 Treemap::find_space(Space *s)
 {
   bool bug = _owner_id == s;
-  for (unsigned i = 0; i < _key_end.value(); ++i)
+  for (Page i = Page(0); i < _key_end; ++i)
     {
       bool tree_bug = false;
-      Mapping_tree *t = _physframe[i].tree.get();
+      Mapping_tree *t = _physframe[cxx::int_value<Page>(i)].tree.get();
       if (!t)
         continue;
 
@@ -1094,21 +1150,24 @@ Treemap::find_space(Space *s)
             {
               mapping_bug = true;
               printf("MAPDB: found space %p in mapdb (idx=%d, mapping=%p, depth=%d, page=%lx)\n",
-                     s, mx, ma, ma->depth(), ma->page().value());
+                     s, mx, ma, ma->depth(), cxx::int_value<Page>(ma->page()));
             }
 
           tree_bug |= mapping_bug;
         }
 
       if (tree_bug)
-        printf("MAPDB: error in mapping tree: index=%d\n", i);
+        printf("MAPDB: error in mapping tree: index=%ld\n",
+               cxx::int_value<Page>(i));
 
       bug |= tree_bug;
     }
 
   if (bug)
-    printf("MAPDB: error in treemap: owner(space)=%p, offset=%lx, size=%lx, pageshift=%zd\n",
-           _owner_id, _page_offset.value(), _key_end.value(), _page_shift);
+    printf("MAPDB: error in treemap: owner(space)=%p, offset=%lx, size=%lx, pageshift=%d\n",
+           _owner_id, cxx::int_value<Pfn>(_page_offset),
+           cxx::int_value<Page>(_key_end),
+           cxx::int_value<Order>(_page_shift));
 
   return bug;
 }
diff --git a/kernel/fiasco/src/kern/mapdb_types.h b/kernel/fiasco/src/kern/mapdb_types.h
new file mode 100644 (file)
index 0000000..4735c89
--- /dev/null
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "types.h"
+
+namespace Mdb_types {
+  struct Order_t;
+  struct Pcnt_t;
+  struct Pfn_t;
+
+  typedef cxx::int_type<unsigned, Order_t > Order;
+  typedef cxx::int_type_order<Address, Pcnt_t, Order> Pcnt;
+  typedef cxx::int_type_full<Address, Pfn_t, Pcnt, Order> Pfn;
+}
+
index a7d4090aa2f61fdcb7df961dae64d938baeb54dc..0ec6968cab32290ef264a3c769d2ee1f212b4f6e 100644 (file)
@@ -1,6 +1,7 @@
 INTERFACE:
 
 #include "types.h"
+#include "mapdb_types.h"
 
 class Space;
 /** Represents one mapping in a mapping tree.
@@ -15,11 +16,17 @@ class Space;
     become invalid) when Mapdb::free is called with any one of its
     mappings.
  */
-class Mapping 
+class Mapping
 {
   friend class Jdb_mapdb;
 public:
-  enum Mapping_depth 
+  typedef Mdb_types::Order Order;
+  typedef Mdb_types::Pcnt Pcnt;
+  typedef Mdb_types::Pfn Pfn;
+  struct Page_t;
+  typedef cxx::int_type_order<Address, Page_t, Order> Page;
+
+  enum Mapping_depth
   {
     Depth_root = 0, Depth_max = 252, 
     Depth_submap = 253, Depth_empty = 254, Depth_end = 255 
@@ -81,20 +88,20 @@ Mapping::set_space(Space *space)
     @return the virtual address at which the frame is mapped.
  */
 PUBLIC inline NEEDS[Mapping::data]
-Page_number
+Mapping::Page
 Mapping::page() const
 {
-  return Page_number::create(data()->data.address);
+  return Page(data()->data.address);
 }
 
 /** Set virtual address.
     @param address the virtual address at which the frame is mapped.
  */
 PUBLIC inline NEEDS[Mapping::data]
-void 
-Mapping::set_page(Page_number address) 
+void
+Mapping::set_page(Page address)
 {
-  data()->data.address = address.value();
+  data()->data.address = cxx::int_value<Page>(address);
 }
 
 /** Depth of mapping in mapping tree. */
index adbcc1332e50d4a78789446b98800bdafdf95055..7f99a714e7bf1049135f523621d5f8087b872595 100644 (file)
@@ -119,6 +119,10 @@ INTERFACE [!big_endian]:
 // FIXME: do we need this depending on endianess ?
 struct Mapping_tree
 {
+  typedef Mapping::Page Page;
+  typedef Mapping::Pfn Pfn;
+  typedef Mapping::Pcnt Pcnt;
+
   enum Size_id
   {
     Size_id_min = 0,
@@ -144,6 +148,10 @@ INTERFACE [big_endian]:
 // FIXME: do we need this depending on endianess ?
 struct Mapping_tree
 {
+  typedef Mapping::Page Page;
+  typedef Mapping::Pfn Pfn;
+  typedef Mapping::Pcnt Pcnt;
+
   enum Size_id
   {
     Size_id_min = 0,
@@ -169,6 +177,7 @@ INTERFACE:
 class Base_mappable
 {
 public:
+  typedef Mapping_tree::Page Page;
   // DATA
   cxx::unique_ptr<Mapping_tree> tree;
   typedef ::Lock Lock;
@@ -326,7 +335,7 @@ Mapping_tree::operator delete (void* block)
 }
 
 PUBLIC //inline NEEDS[Mapping_depth, Mapping_tree::last]
-Mapping_tree::Mapping_tree(Size_id size_id, Page_number page,
+Mapping_tree::Mapping_tree(Size_id size_id, Page page,
                            Space *owner)
 {
   _count = 1;                  // 1 valid mapping
@@ -537,7 +546,7 @@ Mapping_tree::check_integrity(Space *owner = (Space*)-1)
       printf("mapdb corrupted: owner=%p\n"
              "  m=%p (end: %s depth: %d space: %p page: %lx)\n",
              owner, m, m->is_end_tag()?"yes":"no", m->depth(), m->space(),
-             m->page().value());
+             cxx::int_value<Page>(m->page()));
       kdb_ke("XXX");
     }
 
@@ -728,7 +737,7 @@ Mapping_tree::free_mapping(Ram_quota *q, Mapping *m)
 PUBLIC template< typename SUBMAP_OPS >
 void
 Mapping_tree::flush(Mapping *parent, bool me_too,
-                    Page_number offs_begin, Page_number offs_end, 
+                    Pcnt offs_begin, Pcnt offs_end, 
                     SUBMAP_OPS const &submap_ops = SUBMAP_OPS())
 {
   assert (! parent->unused());
@@ -820,7 +829,7 @@ Mapping_tree::flush(Mapping *parent, bool me_too,
 
 PUBLIC template< typename SUBMAP_OPS >
 bool
-Mapping_tree::grant(Mapping* m, Space *new_space, Page_number va,
+Mapping_tree::grant(Mapping* m, Space *new_space, Page page,
                     SUBMAP_OPS const &submap_ops = SUBMAP_OPS())
 {
   unsigned long _quota = sizeof(Mapping);
@@ -834,10 +843,10 @@ Mapping_tree::grant(Mapping* m, Space *new_space, Page_number va,
   Space *old_space = m->space();
 
   m->set_space(new_space);
-  m->set_page(va);
+  m->set_page(page);
 
   if (submap)
-    submap_ops.grant(submap, new_space, va);
+    submap_ops.grant(submap, new_space, page);
 
   quota(old_space)->free(_quota);
   return true;
@@ -845,7 +854,7 @@ Mapping_tree::grant(Mapping* m, Space *new_space, Page_number va,
 
 PUBLIC inline
 Mapping *
-Mapping_tree::lookup(Space *space, Page_number page)
+Mapping_tree::lookup(Space *space, Page page)
 {
 
   Mapping *m;
@@ -863,14 +872,14 @@ Mapping_tree::lookup(Space *space, Page_number page)
 
 PUBLIC
 Mapping *
-Base_mappable::lookup(Space *space, Page_number va)
+Base_mappable::lookup(Space *space, Page page)
 {
   // get and lock the tree.
   if (EXPECT_FALSE(lock.lock() == Lock::Invalid))
     return 0;
   Mapping_tree *t = tree.get();
   assert (t);
-  if (Mapping *m = t->lookup(space, va))
+  if (Mapping *m = t->lookup(space, page))
     return m;
 
   lock.clear();
@@ -879,7 +888,7 @@ Base_mappable::lookup(Space *space, Page_number va)
 
 PUBLIC inline
 Mapping *
-Base_mappable::insert(Mapping* parent, Space *space, Page_number page)
+Base_mappable::insert(Mapping* parent, Space *space, Page page)
 {
   Mapping_tree* t = tree.get();
   if (!t)
@@ -1002,6 +1011,7 @@ Base_mappable::pack()
   // The last entry of the tree should now be free -- exept if we're
   // out of memory.
   assert (t->last()->unused() || maybe_out_of_memory);
+  (void) maybe_out_of_memory;
 }
 
 
index cc1d2857bdd8c90363b335b5fb7620e2ce6f6b89..a73a68c7611bb24554192941899729c7935edd9a 100644 (file)
@@ -21,15 +21,24 @@ public:
   static Mword in_kernel (Address a); // XXX: not right for UX
 };
 
-IMPLEMENTATION:
-
-#include "config.h"
+IMPLEMENTATION [obj_space_virt]:
 
 PUBLIC static inline
 bool
 Mem_layout::is_caps_area(Address a)
 { return (a >= Caps_start) && (a < Caps_end); }
 
+IMPLEMENTATION [!obj_space_virt]:
+
+PUBLIC static inline
+bool
+Mem_layout::is_caps_area(Address)
+{ return false; }
+
+IMPLEMENTATION:
+
+#include "config.h"
+
 IMPLEMENT inline
 Mword
 Mem_layout::in_kernel (Address a)
index ae1bdf1bd0fa8751f0f0829dc06ea750f62ae210..e0431faedffece45d8a04ced688927326c8e68f1 100644 (file)
@@ -7,6 +7,7 @@ INTERFACE:
 #include "per_cpu_data.h"
 #include "ram_quota.h"
 #include "types.h"
+#include "mapdb_types.h"
 
 class Space;
 
@@ -24,17 +25,23 @@ class Mem_space
 
 public:
   typedef int Status;
-
   static char const *const name;
 
+  typedef Page::Attr Attr;
   typedef Pdir::Va Vaddr;
-  typedef Pdir::Va Vsize;
+  typedef Pdir::Vs Vsize;
+
+  typedef Addr::Addr<Config::PAGE_SHIFT> Phys_addr;
+  typedef Addr::Diff<Config::PAGE_SHIFT> Phys_diff;
+  typedef Addr::Order<Config::PAGE_SHIFT> Page_order;
 
-  typedef Virt_addr Addr;
-  typedef Virt_size Size;
-  typedef Page_addr<Config::PAGE_SHIFT> Phys_addr;
   typedef void Reap_list;
 
+  // for map_util
+  typedef Page_number V_pfn;
+  typedef Page_count V_pfc;
+  typedef Addr::Order<0> V_order;
+
   // Each architecture must provide these members:
   void switchin_context(Mem_space *from);
 
@@ -57,8 +64,9 @@ public:
    *                           range
    * @pre phys and virt need to be size-aligned according to the size argument.
    */
-  Status v_insert(Phys_addr phys, Vaddr virt, Vsize size,
-                  unsigned page_attribs, bool upgrade_ignore_size = false);
+  FIASCO_SPACE_VIRTUAL
+  Status v_insert(Phys_addr phys, Vaddr virt, Page_order size,
+                  Attr page_attribs);
 
   /** Look up a page-table entry.
    *
@@ -76,8 +84,9 @@ public:
    *             either case, it is either 4KB or 4MB.
    * @return True if an entry was found, false otherwise.
    */
-  bool v_lookup(Vaddr virt, Phys_addr *phys = 0, Size *size = 0,
-                unsigned *page_attribs = 0);
+  FIASCO_SPACE_VIRTUAL
+  bool v_lookup(Vaddr virt, Phys_addr *phys = 0, Page_order *order = 0,
+                Attr *page_attribs = 0);
 
   /** Delete page-table entries, or some of the entries' attributes.
    *
@@ -91,8 +100,12 @@ public:
    * @return Combined (bit-ORed) page attributes that were removed.  In
    *         case of errors, ~Page_all_attribs is additionally bit-ORed in.
    */
-  unsigned long v_delete(Vaddr virt, Vsize size,
-                         unsigned long page_attribs = Page_all_attribs);
+  FIASCO_SPACE_VIRTUAL
+  L4_fpage::Rights v_delete(Vaddr virt, Page_order size,
+                            L4_fpage::Rights page_attribs);
+
+  FIASCO_SPACE_VIRTUAL
+  void v_set_access_flags(Vaddr virt, L4_fpage::Rights access_flags);
 
   /** Set this memory space as the current on on this CPU. */
   void make_current();
@@ -100,19 +113,75 @@ public:
   static Mem_space *kernel_space()
   { return _kernel_space; }
 
-  static inline Mem_space *current_mem_space(unsigned cpu);
+  static inline Mem_space *current_mem_space(Cpu_number cpu);
+
+
+  virtual
+  Page_number mem_space_map_max_address() const
+  { return Virt_addr(Map_max_address); }
+
+  Page_number map_max_address() const
+  { return mem_space_map_max_address(); }
+
+  static Phys_addr page_address(Phys_addr o, Page_order s)
+  { return cxx::mask_lsb(o, s); }
+
+  static V_pfn page_address(V_pfn a, Page_order o)
+  { return cxx::mask_lsb(a, o); }
+
+  static Phys_addr subpage_address(Phys_addr addr, V_pfc offset)
+  { return addr | Phys_diff(offset); }
+
+  struct Fit_size
+  {
+    typedef cxx::array<Page_order, Page_order, 65> Size_array;
+    Size_array const &o;
+    Page_order operator () (Page_order i) const { return o[i]; }
+
+    explicit Fit_size(Size_array const &o) :o(o) {}
+  };
+
+  FIASCO_SPACE_VIRTUAL
+  Fit_size mem_space_fitting_sizes() const __attribute__((pure));
+
+  Fit_size fitting_sizes() const
+  { return mem_space_fitting_sizes(); }
+
+  static Mdb_types::Pfn to_pfn(Phys_addr p)
+  { return Mdb_types::Pfn(cxx::int_value<Page_number>(p)); }
+
+  static Mdb_types::Pfn to_pfn(V_pfn p)
+  { return Mdb_types::Pfn(cxx::int_value<Page_number>(p)); }
+
+  static Mdb_types::Pcnt to_pcnt(Page_order s)
+  { return Mdb_types::Pcnt(1) << Mdb_types::Order(cxx::int_value<Page_order>(s) - Config::PAGE_SHIFT); }
+
+  static V_pfn to_virt(Mdb_types::Pfn p)
+  { return Page_number(cxx::int_value<Mdb_types::Pfn>(p)); }
 
-  virtual Page_number map_max_address() const
-  { return Addr::create(Map_max_address); }
+  static Page_order to_order(Mdb_types::Order p)
+  { return Page_order(cxx::int_value<Mdb_types::Order>(p) + Config::PAGE_SHIFT); }
 
-  static Address superpage_size()
-  { return Map_superpage_size; }
+  static V_pfc to_size(Page_order p)
+  { return V_pfc(1) << p; }
 
-  static Phys_addr page_address(Phys_addr o, Size s)
-  { return o.trunc(s); }
+  static V_pfc subpage_offset(V_pfn a, Page_order o)
+  { return cxx::get_lsb(a, o); }
 
-  static Phys_addr subpage_address(Phys_addr addr, Size offset)
-  { return addr | offset; }
+  Page_order largest_page_size() const
+  { return mem_space_fitting_sizes()(Page_order(64)); }
+
+  enum
+  {
+    Max_num_global_page_sizes = 5
+  };
+
+  static Page_order const *get_global_page_sizes(bool finalize = true)
+  {
+    if (finalize)
+      _glbl_page_sizes_finished = true;
+    return _glbl_page_sizes;
+  }
 
 private:
   Mem_space(const Mem_space &) = delete;
@@ -121,6 +190,9 @@ private:
 
   static Per_cpu<Mem_space *> _current;
   static Mem_space *_kernel_space;
+  static Page_order _glbl_page_sizes[Max_num_global_page_sizes];
+  static unsigned _num_glbl_page_sizes;
+  static bool _glbl_page_sizes_finished;
 };
 
 
@@ -168,6 +240,52 @@ DEFINE_PER_CPU Per_cpu<Mem_space *> Mem_space::_current;
 char const * const Mem_space::name = "Mem_space";
 Mem_space *Mem_space::_kernel_space;
 
+static Mem_space::Fit_size::Size_array __mfs;
+Mem_space::Page_order Mem_space::_glbl_page_sizes[Max_num_global_page_sizes];
+unsigned Mem_space::_num_glbl_page_sizes;
+bool Mem_space::_glbl_page_sizes_finished;
+
+PROTECTED static
+void
+Mem_space::add_global_page_size(Page_order o)
+{
+  assert_kdb (!_glbl_page_sizes_finished);
+  unsigned i;
+  for (i = 0; i < _num_glbl_page_sizes; ++i)
+    {
+      if (_glbl_page_sizes[i] == o)
+        return;
+
+      if (_glbl_page_sizes[i] < o)
+        break;
+    }
+
+  assert (_num_glbl_page_sizes + 1 < Max_num_global_page_sizes);
+
+  for (unsigned x = _num_glbl_page_sizes; x > i; --x)
+    _glbl_page_sizes[x] = _glbl_page_sizes[x - 1];
+
+  _glbl_page_sizes[i] = o;
+  assert (_glbl_page_sizes[_num_glbl_page_sizes] <= Page_order(Config::PAGE_SHIFT));
+
+  ++_num_glbl_page_sizes;
+}
+
+PUBLIC static
+void
+Mem_space::add_page_size(Page_order o)
+{
+  add_global_page_size(o);
+  for (Page_order c = o; c < __mfs.size(); ++c)
+    __mfs[c] = o;
+}
+
+IMPLEMENT
+Mem_space::Fit_size
+Mem_space::mem_space_fitting_sizes() const
+{
+  return Fit_size(__mfs);
+}
 
 PUBLIC inline
 Ram_quota *
@@ -193,11 +311,11 @@ Mem_space::dir() const
 
 PUBLIC
 virtual bool
-Mem_space::v_fabricate(Vaddr address,
-                       Phys_addr* phys, Size* size, unsigned* attribs = 0)
+Mem_space::v_fabricate(Vaddr address, Phys_addr *phys, Page_order *order,
+                       Attr *attribs = 0)
 {
-  return Mem_space::v_lookup(address.trunc(Size(Map_page_size)),
-      phys, size, attribs);
+  return v_lookup(cxx::mask_lsb(address, Page_order(Config::PAGE_SHIFT)),
+      phys, order, attribs);
 }
 
 PUBLIC virtual
index 0fbd2bdc5fe407a48e420b080f50ac9dc7c51200..6465e0a1fe87590a068378f535e22fa2e6c9f42b 100644 (file)
@@ -1,23 +1,18 @@
 INTERFACE:
 
 #include "assert_opt.h"
+#include "obj_space_phys_util.h"
 
-EXTENSION class Generic_obj_space
+EXTENSION class Generic_obj_space : Obj_space_phys<Generic_obj_space< SPACE > >
 {
 private:
-  enum
-  {
-    Slots_per_dir = Config::PAGE_SIZE / sizeof(void*)
-  };
-
-  struct Cap_table { Entry e[Caps_per_page]; };
-  struct Cap_dir   { Cap_table *d[Slots_per_dir]; };
-  Cap_dir *_dir;
+  typedef Obj_space_phys<Generic_obj_space< SPACE > > Base;
 
-  Ram_quota *ram_quota() const
+public:
+  static Ram_quota *ram_quota(Base const *base)
   {
-    assert_opt (this);
-    return static_cast<SPACE const *>(this)->ram_quota();
+    assert_opt (base);
+    return static_cast<SPACE const *>(base)->ram_quota();
   }
 };
 
@@ -25,219 +20,66 @@ private:
 //----------------------------------------------------------------------------
 IMPLEMENTATION:
 
-#include <cstring>
-#include <cassert>
-
-#include "atomic.h"
-#include "config.h"
-#include "cpu.h"
-#include "kdb_ke.h"
-#include "kmem_alloc.h"
-#include "mem.h"
-#include "mem_layout.h"
-#include "ram_quota.h"
-#include "static_assert.h"
-
-
-PUBLIC template< typename SPACE >
-inline NEEDS["static_assert.h"]
-Generic_obj_space<SPACE>::Generic_obj_space()
-{
-  static_assert(sizeof(Cap_dir) == Config::PAGE_SIZE, "cap_dir size mismatch");
-  _dir = (Cap_dir*)Kmem_alloc::allocator()->q_unaligned_alloc(ram_quota(), Config::PAGE_SIZE);
-  if (_dir)
-    Mem::memset_mwords(_dir, 0, Config::PAGE_SIZE / sizeof(Mword));
-}
-
-PRIVATE template< typename SPACE >
-typename Generic_obj_space<SPACE>::Entry *
-Generic_obj_space<SPACE>::get_cap(Address index)
-{
-  if (EXPECT_FALSE(!_dir))
-    return 0;
-
-  unsigned d_idx = index / Caps_per_page;
-  if (EXPECT_FALSE(d_idx >= Slots_per_dir))
-    return 0;
-
-  Cap_table *tab = _dir->d[d_idx];
-
-  if (EXPECT_FALSE(!tab))
-    return 0;
-
-  unsigned offs  = index % Caps_per_page;
-  return &tab->e[offs];
-}
-
-PRIVATE template< typename SPACE >
-typename Generic_obj_space<SPACE>::Entry *
-Generic_obj_space<SPACE>::caps_alloc(Address virt)
-{
-  static_assert(sizeof(Cap_table) == Config::PAGE_SIZE, "cap table size mismatch");
-  unsigned d_idx = virt / Caps_per_page;
-  if (EXPECT_FALSE(d_idx >= Slots_per_dir))
-    return 0;
-
-  void *mem = Kmem_alloc::allocator()->q_unaligned_alloc(ram_quota(), Config::PAGE_SIZE);
-
-  if (!mem)
-    return 0;
-
-  add_dbg_info(mem, this, virt);
-
-  Mem::memset_mwords(mem, 0, Config::PAGE_SIZE / sizeof(Mword));
-
-
-
-  Cap_table *tab = _dir->d[d_idx] = (Cap_table*)mem;
-
-  return &tab->e[virt % Caps_per_page];
-}
-
-PRIVATE template< typename SPACE >
-void
-Generic_obj_space<SPACE>::caps_free()
-{ 
-  if (!_dir)
-    return;
-
-  Cap_dir *d = _dir;
-  _dir = 0;
-
-  Kmem_alloc *a = Kmem_alloc::allocator();
-  for (unsigned i = 0; i < Slots_per_dir; ++i)
-    {
-      if (!d->d[i])
-        continue;
-
-      remove_dbg_info(d->d[i]);
-      a->q_unaligned_free(ram_quota(), Config::PAGE_SIZE, d->d[i]);
-    }
-
-  a->q_unaligned_free(ram_quota(), Config::PAGE_SIZE, d);
-}
-
 //
 // Utilities for map<Generic_obj_space> and unmap<Generic_obj_space>
 //
 
-PUBLIC template< typename SPACE >
-inline NEEDS[Generic_obj_space::get_cap]
-bool
-Generic_obj_space<SPACE>::v_lookup(Addr const &virt, Phys_addr *phys = 0,
-                                   Size *size = 0, unsigned *attribs = 0)
-{
-  if (size) *size = Size::create(1);
-  Entry *cap = get_cap(virt.value());
-
-  if (EXPECT_FALSE(!cap))
-    {
-      if (size) *size = Size::create(Caps_per_page);
-      return false;
-    }
-
-  Capability c = *cap;
-
-  Obj::set_entry(virt, cap);
-  if (phys) *phys = c.obj();
-  if (c.valid() && attribs) *attribs = cap->rights();
-  return c.valid();
-}
-
-PUBLIC template< typename SPACE >
-inline NEEDS [Generic_obj_space::get_cap]
-typename Generic_obj_space<SPACE>::Capability
-Generic_obj_space<SPACE>::lookup(Address virt)
-{
-  Capability *c = get_cap(virt);
-
-  if (EXPECT_FALSE(!c))
-    return Capability(0); // void
-
-  return *c;
-}
-
-PUBLIC template< typename SPACE >
+IMPLEMENT template< typename SPACE >
 inline
+bool __attribute__((__flatten__))
+Generic_obj_space<SPACE>::v_lookup(V_pfn const &virt, Phys_addr *phys,
+                                   Page_order *size, Attr *attribs)
+{ return Base::v_lookup(virt, phys, size, attribs); }
+
+IMPLEMENT template< typename SPACE >
+inline __attribute__((__flatten__))
+typename Generic_obj_space<SPACE>::Capability __attribute__((__flatten__))
+Generic_obj_space<SPACE>::lookup(Cap_index virt)
+{ return Base::lookup(virt); }
+
+IMPLEMENT template< typename SPACE >
+inline __attribute__((__flatten__))
 Kobject_iface *
-Generic_obj_space<SPACE>::lookup_local(Address virt, unsigned char *rights = 0)
-{
-  Entry *c = get_cap(virt);
-
-  if (EXPECT_FALSE(!c))
-    return 0;
-
-  Capability cap = *c;
-
-  if (rights)
-    *rights = cap.rights();
-
-  return cap.obj();
-}
-
-
-PUBLIC template< typename SPACE >
-inline NEEDS[<cassert>, Generic_obj_space::get_cap]
-unsigned long
-Generic_obj_space<SPACE>::v_delete(Page_number virt, Size size,
-                                   unsigned long page_attribs = L4_fpage::RWX)
-{
-  (void)size;
-  assert (size.value() == 1);
-  Capability *c = get_cap(virt.value());
-
-  if (c && c->valid())
-    {
-      if (page_attribs & L4_fpage::R)
-        c->invalidate();
-      else
-       c->del_rights(page_attribs & L4_fpage::WX);
-    }
-
-  return 0;
-}
-
-PUBLIC template< typename SPACE >
-inline NEEDS[Generic_obj_space::caps_alloc, "kdb_ke.h"]
-typename Generic_obj_space<SPACE>::Status
-Generic_obj_space<SPACE>::v_insert(Phys_addr phys, Addr const &virt, Size size,
-                                   unsigned char page_attribs)
-{
-  (void)size;
-  assert (size.value() == 1);
-
-  Entry *c = get_cap(virt.value());
-
-  if (!c && !(c = caps_alloc(virt.value())))
-    return Insert_err_nomem;
-
-  assert (size.value() == 1);
-
-  if (c->valid())
-    {
-      if (c->obj() == phys)
-       {
-         if (EXPECT_FALSE(c->rights() == page_attribs))
-           return Insert_warn_exists;
-
-         c->add_rights(page_attribs);
-         return Insert_warn_attrib_upgrade;
-       }
-      else
-       return Insert_err_exists;
-    }
-
-  Obj::set_entry(virt, c);
-  c->set(phys, page_attribs);
-  return Insert_ok;
-}
-
+Generic_obj_space<SPACE>::lookup_local(Cap_index virt, L4_fpage::Rights *rights = 0)
+{ return Base::lookup_local(virt, rights); }
+
+IMPLEMENT template< typename SPACE >
+inline __attribute__((__flatten__))
+L4_fpage::Rights __attribute__((__flatten__))
+Generic_obj_space<SPACE>::v_delete(V_pfn virt, Page_order size,
+                                   L4_fpage::Rights page_attribs)
+{ return Base::v_delete(virt, size, page_attribs); }
+
+IMPLEMENT template< typename SPACE >
+inline __attribute__((__flatten__))
+typename Generic_obj_space<SPACE>::Status __attribute__((__flatten__))
+Generic_obj_space<SPACE>::v_insert(Phys_addr phys, V_pfn const &virt, Page_order size,
+                                   Attr page_attribs)
+{ return (Status)Base::v_insert(phys, virt, size, page_attribs); }
+
+IMPLEMENT template< typename SPACE >
+inline __attribute__((__flatten__))
+typename Generic_obj_space<SPACE>::V_pfn
+Generic_obj_space<SPACE>::obj_map_max_address() const
+{ return Base::obj_map_max_address(); }
+
+// ------------------------------------------------------------------------------
+IMPLEMENTATION [debug]:
+
+PUBLIC template< typename SPACE > static inline
+SPACE *
+Generic_obj_space<SPACE>::get_space(Base *base)
+{ return static_cast<SPACE*>(base); }
+
+IMPLEMENT template< typename SPACE > inline
+typename Generic_obj_space<SPACE>::Entry *
+Generic_obj_space<SPACE>::jdb_lookup_cap(Cap_index index)
+{ return Base::jdb_lookup_cap(index); }
 
-PUBLIC template< typename SPACE >
-static inline
-typename Generic_obj_space<SPACE>::Addr
-Generic_obj_space<SPACE>::map_max_address()
-{
-  return Addr(Slots_per_dir * Caps_per_page);
-}
+// ------------------------------------------------------------------------------
+IMPLEMENTATION [!debug]:
 
+PUBLIC template< typename SPACE > static inline
+SPACE *
+Generic_obj_space<SPACE>::get_space(Base *)
+{ return 0; }
index d42f551ae03470e1117ced1af5189661d9ff30d2..7d30b07fde31eaea5ca3e5399f31427875a114be 100644 (file)
@@ -3,313 +3,91 @@ INTERFACE:
 #include "mem.h"
 #include "mem_space.h"
 #include "ram_quota.h"
+#include "obj_space_virt_util.h"
 
-EXTENSION class Generic_obj_space
+EXTENSION class Generic_obj_space : Obj_space_virt<Generic_obj_space<SPACE> >
 {
-  // do not use the virtually mapped cap table in
-  // v_lookup and v_insert, because the map logic needs the kernel
-  // address for link pointers in the map-nodes and these addresses must
-  // be valid in all address spaces.
-  enum { Optimize_local = 0 };
+  typedef Obj_space_virt<Generic_obj_space<SPACE> > Base;
 };
 
 IMPLEMENTATION:
 
-#include <cstring>
-#include <cassert>
-
-#include "atomic.h"
-#include "config.h"
-#include "cpu.h"
-#include "kdb_ke.h"
-#include "kmem_alloc.h"
-#include "mem_layout.h"
-
-PRIVATE template< typename SPACE > inline
-Mem_space *
-Generic_obj_space<SPACE>::mem_space()
-{ return static_cast<SPACE*>(this); }
-
-PRIVATE  template< typename SPACE >
-static inline NEEDS["mem_layout.h"]
-typename Generic_obj_space<SPACE>::Entry *
-Generic_obj_space<SPACE>::cap_virt(Address index)
-{ return reinterpret_cast<Entry*>(Mem_layout::Caps_start) + index; }
-
-PRIVATE  template< typename SPACE >
-inline NEEDS["mem_space.h", "mem_layout.h", Generic_obj_space::cap_virt]
-typename Generic_obj_space<SPACE>::Entry *
-Generic_obj_space<SPACE>::alien_lookup(Address index)
-{
-  Mem_space *ms = mem_space();
-
-  Address phys = Address(ms->virt_to_phys((Address)cap_virt(index)));
-  if (EXPECT_FALSE(phys == ~0UL))
-    return 0;
-
-  return reinterpret_cast<Entry*>(Mem_layout::phys_to_pmem(phys));
-}
-
-PRIVATE template< typename SPACE >
-typename Generic_obj_space<SPACE>::Entry *
-Generic_obj_space<SPACE>::get_cap(Address index)
-{ return alien_lookup(index); }
-
-PUBLIC  template< typename SPACE >
-inline NEEDS["mem_space.h"]
+PUBLIC  template< typename SPACE > static
+inline
 Ram_quota *
-Generic_obj_space<SPACE>::ram_quota() const
-{ return static_cast<SPACE const *>(this)->ram_quota(); }
-
-
-PRIVATE  template< typename SPACE >
-/*inline NEEDS["kmem_alloc.h", <cstring>, "ram_quota.h",
-                     Generic_obj_space::cap_virt]*/
-typename Generic_obj_space<SPACE>::Entry *
-Generic_obj_space<SPACE>::caps_alloc(Address virt)
-{
-  Address cv = (Address)cap_virt(virt);
-  void *mem = Kmem_alloc::allocator()->q_unaligned_alloc(ram_quota(), Config::PAGE_SIZE);
-
-  if (!mem)
-    return 0;
-
-  add_dbg_info(mem, this, virt);
-
-  Mem::memset_mwords(mem, 0, Config::PAGE_SIZE / sizeof(Mword));
-
-  Mem_space::Status s;
-  s = mem_space()->v_insert(
-      Mem_space::Phys_addr::create(Mem_space::kernel_space()->virt_to_phys((Address)mem)),
-      Mem_space::Addr::create(cv).trunc(Mem_space::Size::create(Config::PAGE_SIZE)),
-      Mem_space::Size::create(Config::PAGE_SIZE),
-      Mem_space::Page_cacheable | Mem_space::Page_writable
-      | Mem_space::Page_referenced | Mem_space::Page_dirty);
-
-  switch (s)
-    {
-    case Insert_ok:
-      break;
-    case Insert_warn_exists:
-    case Insert_warn_attrib_upgrade:
-      assert (false);
-      break;
-    case Insert_err_exists:
-    case Insert_err_nomem:
-      Kmem_alloc::allocator()->q_unaligned_free(ram_quota(),
-          Config::PAGE_SIZE, mem);
-      return 0;
-    };
-
-  unsigned long cap = cv & (Config::PAGE_SIZE - 1) | (unsigned long)mem;
-
-  return reinterpret_cast<Entry*>(cap);
-}
-
-PRIVATE template< typename SPACE >
-void
-Generic_obj_space<SPACE>::caps_free()
-{
-  Mem_space *ms = mem_space();
-  if (EXPECT_FALSE(!ms || !ms->dir()))
-    return;
-
-  Kmem_alloc *a = Kmem_alloc::allocator();
-  for (unsigned long i = 0; i < map_max_address().value();
-       i += Caps_per_page)
-    {
-      Entry *c = get_cap(i);
-      if (!c)
-       continue;
+Generic_obj_space<SPACE>::ram_quota(Base const *base)
+{ return static_cast<SPACE const *>(base)->ram_quota(); }
 
-      Address cp = Address(ms->virt_to_phys(Address(c)));
-      assert_kdb (cp != ~0UL);
-      void *cv = (void*)Mem_layout::phys_to_pmem(cp);
-      remove_dbg_info(cv);
 
-      a->q_unaligned_free(ram_quota(), Config::PAGE_SIZE, cv);
-    }
-#if defined (CONFIG_ARM)
-  ms->dir()->free_page_tables((void*)Mem_layout::Caps_start, (void*)Mem_layout::Caps_end, Kmem_alloc::q_allocator(ram_quota()));
-#else
-  ms->dir()->destroy(Virt_addr(Mem_layout::Caps_start),
-                     Virt_addr(Mem_layout::Caps_end), Pdir::Depth - 1,
-                     Kmem_alloc::q_allocator(ram_quota()));
-#endif
-}
+PUBLIC template< typename SPACE > static inline
+Mem_space *
+Generic_obj_space<SPACE>::mem_space(Base *base)
+{ return static_cast<SPACE*>(base); }
 
 //
 // Utilities for map<Generic_obj_space> and unmap<Generic_obj_space>
 //
 
-PUBLIC  template< typename SPACE >
-inline NEEDS[Generic_obj_space::cap_virt, Generic_obj_space::get_cap]
-bool
-Generic_obj_space<SPACE>::v_lookup(Addr const &virt, Phys_addr *phys = 0,
-                                   Size *size = 0, unsigned *attribs = 0)
+IMPLEMENT  template< typename SPACE >
+inline
+bool __attribute__((__flatten__))
+Generic_obj_space<SPACE>::v_lookup(V_pfn const &virt, Phys_addr *phys,
+                                   Page_order *size, Attr *attribs)
 {
-  if (size) size->set_value(1);
-  Entry *cap;
-
-  if (Optimize_local
-      && mem_space() == Mem_space::current_mem_space(current_cpu()))
-    cap = cap_virt(virt.value());
-  else
-    cap = get_cap(virt.value());
-
-  if (EXPECT_FALSE(!cap))
-    {
-      if (size) size->set_value(Caps_per_page);
-      return false;
-    }
-
-  if (Optimize_local)
-    {
-      Capability c = Mem_layout::read_special_safe((Capability*)cap);
-
-      if (phys) *phys = c.obj();
-      if (c.valid() && attribs) *attribs = c.rights();
-      return c.valid();
-    }
-  else
-    {
-      Obj::set_entry(virt, cap);
-      if (phys) *phys = cap->obj();
-      if (cap->valid() && attribs) *attribs = cap->rights();
-      return cap->valid();
-    }
+  return Base::v_lookup(virt, phys, size, attribs);
 }
 
-PUBLIC template< typename SPACE >
-inline NEEDS [Generic_obj_space::cap_virt, Generic_obj_space::get_cap]
-typename Generic_obj_space<SPACE>::Capability
-Generic_obj_space<SPACE>::lookup(Address virt)
-{
-  Capability *c;
-  virt &= ~(~0UL << Whole_space);
-
-  if (mem_space() == Mem_space::current_mem_space(current_cpu()))
-    c = reinterpret_cast<Capability*>(cap_virt(virt));
-  else
-    c = get_cap(virt);
+IMPLEMENT template< typename SPACE >
+inline __attribute__((__flatten__))
+typename Generic_obj_space<SPACE>::Capability __attribute__((__flatten__))
+Generic_obj_space<SPACE>::lookup(Cap_index virt)
+{ return Base::lookup(virt); }
 
-  if (EXPECT_FALSE(!c))
-    return Capability(0); // void
-
-  return Mem_layout::read_special_safe(c);
-}
-
-PUBLIC template< typename SPACE >
-inline NEEDS [Generic_obj_space::cap_virt]
+IMPLEMENT template< typename SPACE >
+inline __attribute__((__flatten__))
 Kobject_iface *
-Generic_obj_space<SPACE>::lookup_local(Address virt, unsigned char *rights = 0)
-{
-  virt &= ~(~0UL << Whole_space);
-  Capability *c = reinterpret_cast<Capability*>(cap_virt(virt));
-  Capability cap = Mem_layout::read_special_safe(c);
-  if (rights) *rights = cap.rights();
-  return cap.obj();
-}
+Generic_obj_space<SPACE>::lookup_local(Cap_index virt, L4_fpage::Rights *rights = 0)
+{ return Base::lookup_local(virt, rights); }
 
 
-PUBLIC template< typename SPACE >
-inline NEEDS[<cassert>, Generic_obj_space::cap_virt, Generic_obj_space::get_cap]
-unsigned long
-Generic_obj_space<SPACE>::v_delete(Page_number virt, Size size,
-                                   unsigned long page_attribs = L4_fpage::CRWSD)
-{
-  (void)size;
-  assert (size.value() == 1);
+IMPLEMENT template< typename SPACE >
+inline __attribute__((__flatten__))
+L4_fpage::Rights __attribute__((__flatten__))
+Generic_obj_space<SPACE>::v_delete(V_pfn virt, Order size,
+                                   L4_fpage::Rights page_attribs)
+{ return  Base::v_delete(virt, size, page_attribs); }
 
-  Entry *c;
-  if (Optimize_local
-      && mem_space() == Mem_space::current_mem_space(current_cpu()))
-    {
-      c = cap_virt(virt.value());
-      if (!c)
-       return 0;
+IMPLEMENT  template< typename SPACE >
+inline __attribute__((__flatten__))
+typename Generic_obj_space<SPACE>::Status __attribute__((__flatten__))
+Generic_obj_space<SPACE>::v_insert(Phys_addr phys, V_pfn const &virt, Order size,
+                                   Attr page_attribs)
+{ return (Status)Base::v_insert(phys, virt, size, page_attribs); }
 
-      Capability cap = Mem_layout::read_special_safe((Capability*)c);
-      if (!cap.valid())
-       return 0;
-    }
-  else
-    c = get_cap(virt.value());
 
-  if (c && c->valid())
-    {
-      if (page_attribs & L4_fpage::R)
-        c->invalidate();
-      else
-        c->del_rights(page_attribs & L4_fpage::CWSD);
-    }
+IMPLEMENT template< typename SPACE >
+inline __attribute__((__flatten__))
+typename Generic_obj_space<SPACE>::V_pfn
+Generic_obj_space<SPACE>::obj_map_max_address() const
+{ return Base::obj_map_max_address(); }
 
-  return 0;
-}
+// ------------------------------------------------------------------------------
+IMPLEMENTATION [debug]:
 
-PUBLIC  template< typename SPACE >
-inline NEEDS[Generic_obj_space::cap_virt, Generic_obj_space::caps_alloc,
-             Generic_obj_space::alien_lookup, "kdb_ke.h"]
-typename Generic_obj_space<SPACE>::Status
-Generic_obj_space<SPACE>::v_insert(Phys_addr phys, Addr const &virt, Size size,
-                                   unsigned char page_attribs)
-{
-  (void)size;
-  assert (size.value() == 1);
-
-  Entry *c;
-
-  if (Optimize_local
-      && mem_space() == Mem_space::current_mem_space(current_cpu()))
-    {
-      c = cap_virt(virt.value());
-      if (!c)
-       return Insert_err_nomem;
-
-      Capability cap;
-      if (!Mem_layout::read_special_safe((Capability*)c, cap)
-         && !caps_alloc(virt.value()))
-       return Insert_err_nomem;
-    }
-  else
-    {
-      c = alien_lookup(virt.value());
-      if (!c && !(c = caps_alloc(virt.value())))
-       return Insert_err_nomem;
-      Obj::set_entry(virt, c);
-    }
-
-  if (c->valid())
-    {
-      if (c->obj() == phys)
-       {
-         if (EXPECT_FALSE(c->rights() == page_attribs))
-           return Insert_warn_exists;
-
-         c->add_rights(page_attribs);
-         return Insert_warn_attrib_upgrade;
-       }
-      else
-       return Insert_err_exists;
-    }
-
-  c->set(phys, page_attribs);
-  return Insert_ok;
-}
-
-
-PUBLIC  template< typename SPACE >
-static inline
-typename Generic_obj_space<SPACE>::Addr
-Generic_obj_space<SPACE>::map_max_address()
-{
-  Mword r;
+PUBLIC template< typename SPACE > static inline
+SPACE *
+Generic_obj_space<SPACE>::get_space(Base *base)
+{ return static_cast<SPACE*>(base); }
 
-  r = (Mem_layout::Caps_end - Mem_layout::Caps_start) / sizeof(Entry);
-  if (Map_max_address < r)
-    r = Map_max_address;
-
-  return Addr(r);
-}
+IMPLEMENT template< typename SPACE > inline
+typename Generic_obj_space<SPACE>::Entry *
+Generic_obj_space<SPACE>::jdb_lookup_cap(Cap_index index)
+{ return Base::jdb_lookup_cap(index); }
 
+// ------------------------------------------------------------------------------
+IMPLEMENTATION [!debug]:
 
+PUBLIC template< typename SPACE > static inline
+SPACE *
+Generic_obj_space<SPACE>::get_space(Base *)
+{ return 0; }
index e8b110d2db2ad57d0ad18ae6af4f09eb852a3078..c22f141fc3633888779404b285124a3773bdb5ff 100644 (file)
 INTERFACE:
 
+#include "obj_space_types.h"
 #include "config.h"
 #include "l4_types.h"
-#include "l4_msg_item.h"
-#include <hlist>
+#include "template_math.h"
 
-class Kobject_mapdb;
-class Jdb_mapdb;
-class Kobject_iface;
 class Kobject;
 class Space;
-class Ram_quota;
-class Mem_space;
-
-
-namespace Obj {
-
-  class Capability
-  {
-  private:
-    Mword _obj;
-
-  public:
-    Capability() {}
-    explicit Capability(Mword v) : _obj(v) {}
-    Kobject_iface *obj() const { return (Kobject_iface *)(_obj & ~3UL); }
-    //void obj(Phys_addr obj) { _obj = Mword(obj); }
-    void set(Kobject_iface *obj, unsigned char rights)
-    { _obj = Mword(obj) | rights; }
-    bool valid() const { return _obj; }
-    void invalidate() { _obj = 0; }
-    unsigned char rights() const { return _obj & 3; }
-    void add_rights(unsigned char r) { _obj |= r & L4_fpage::CWS; }
-    void del_rights(unsigned char r) { _obj &= ~(r & L4_fpage::CWS); }
-
-    bool operator == (Capability const &c) const { return _obj == c._obj; }
-  };
-
-  /**
-   * Tn the case of a flat copy model for capabilities, we have some
-   * extra mapping information directly colocated within the cap tables.
-   */
-  class Mapping : public cxx::H_list_item
-  {
-    friend class ::Kobject_mapdb;
-    friend class ::Jdb_mapdb;
-
-  public:
-    typedef cxx::H_list<Mapping> List;
-
-    enum Flag
-    {
-      Delete  = L4_fpage::CD,
-      Ref_cnt = 0x10,
-
-      Initial_flags = Delete | Ref_cnt | L4_msg_item::C_ctl_rights
-    };
-
-  protected:
-    Mword _flags : 8;
-    Mword _pad   : 24;
-
-  public:
-    Mapping() : _flags(0) {}
-    // fake this really badly
-    Mapping *parent() { return this; }
-    Mword delete_rights() const { return _flags & Delete; }
-    Mword ref_cnt() const { return _flags & Ref_cnt; }
-
-    void put_as_root() { _flags = Initial_flags; }
-  };
-
-
-  class Entry : public Capability, public Mapping
-  {
-  public:
-    Entry() {}
-    explicit Entry(Mword v) : Capability(v) {}
-
-    unsigned rights() const
-    { return Capability::rights() | (_flags & ~3); }
-
-    void set(Kobject_iface *obj, unsigned char rights)
-    {
-      Capability::set(obj, rights & 3);
-      _flags = rights & 0xf8;
-    }
-    void add_rights(unsigned char r)
-    {
-      Capability::add_rights(r & 3);
-      _flags |= (r & 0xf8);
-    }
-
-    void del_rights(unsigned char r)
-    {
-      Capability::del_rights(r & 3);
-      _flags &= ~(r & 0xf8);
-    }
-  };
-
-
-  struct Cap_addr
-  {
-  public:
-    Page_number _a;
-    mutable Entry *_c;
-    Cap_addr() {}
-    Cap_addr(Page_number a, Entry *c) : _a(a), _c(c) {}
-
-    explicit Cap_addr(Page_number a) : _a(a), _c(0) {}
-    explicit Cap_addr(Address adr) : _a(adr), _c(0) {}
-
-    Address value() const { return _a.value(); }
-    void set_entry(Entry *e) const { _c = e; }
-
-    bool operator == (Cap_addr const &o) const { return _a == o._a; }
-    bool operator < (Cap_addr const &o) const { return _a < o._a; }
-    bool operator > (Cap_addr const &o) const { return _a > o._a; }
-
-    void operator += (Page_number o) { _a += o; }
-    void operator += (Cap_addr const &o) { operator += (o._a); }
-
-    Cap_addr operator + (Page_number o) const { return Cap_addr(_a + o); }
-
-    Cap_addr offset(Page_number s) const { return Cap_addr(_a.offset(s)); }
-    Cap_addr trunc(Page_number s) const
-    {
-      if (s == Page_number(1))
-       return *this;
-      return Cap_addr(_a.trunc(s));
-    }
-
-    operator Page_number::Type_conversion_error const * () const
-    { return (Page_number::Type_conversion_error const *)_a; }
-
-    operator Page_number () const { return _a; }
-  };
-
-  inline void set_entry(Cap_addr const &ca, Entry *e)
-  { ca.set_entry(e); }
-};
-
 
 
 template< typename SPACE >
@@ -150,16 +16,18 @@ class Generic_obj_space
   friend class Jdb_tcb;
 
 public:
-  enum { Caps_per_page = Config::PAGE_SIZE / sizeof(Obj::Entry) };
-
   static char const * const name;
 
+  typedef Obj::Attr Attr;
   typedef Obj::Capability Capability;
   typedef Obj::Entry Entry;
   typedef Kobject *Reap_list;
   typedef Kobject_iface *Phys_addr;
-  typedef Obj::Cap_addr Addr;
-  typedef Page_count Size;
+
+  typedef Obj::Cap_addr V_pfn;
+  typedef Cap_diff V_pfc;
+  typedef Order Page_order;
+
 
   enum
   {
@@ -167,7 +35,6 @@ public:
     Need_xcpu_tlb_flush = 0,
     Map_page_size = 1,
     Page_shift = 0,
-    Map_superpage_size = 1,
     Map_max_address = 1UL << 20, /* 20bit obj index */
     Whole_space = 20,
     Identity_map = 0,
@@ -175,147 +42,137 @@ public:
 
   enum Status
   {
-    Insert_ok = 0,             ///< Mapping was added successfully.
-    Insert_warn_exists,                ///< Mapping already existed
-    Insert_warn_attrib_upgrade,        ///< Mapping already existed, attribs upgrade
-    Insert_err_nomem,          ///< Couldn't alloc new page table
-    Insert_err_exists          ///< A mapping already exists at the target addr
+    Insert_ok = Obj::Insert_ok,                ///< Mapping was added successfully.
+    Insert_warn_exists = Obj::Insert_warn_exists,      ///< Mapping already existed
+    Insert_warn_attrib_upgrade = Obj::Insert_warn_attrib_upgrade,      ///< Mapping already existed, attribs upgrade
+    Insert_err_nomem = Obj::Insert_err_nomem,  ///< Couldn't alloc new page table
+    Insert_err_exists = Obj::Insert_err_exists ///< A mapping already exists at the target addr
   };
 
-  enum Page_attrib 
+  struct Fit_size
   {
-    /// A mask which contains all mask bits
-    //Page_user_accessible = 1,
-    //Page_writable = 2,
-    Page_references = 0,
-    Page_all_attribs = 3
+    Order operator () (Order s) const
+    {
+      return s >= Order(Obj::Caps_per_page_ld2)
+             ? Order(Obj::Caps_per_page_ld2)
+             : Order(0);
+    }
   };
 
-  static Address superpage_size() { return Map_superpage_size; }
-  static bool has_superpages() { return false; }
-  static Phys_addr page_address(Phys_addr o, Size) { return o; }
-  static Phys_addr subpage_address(Phys_addr addr, Size) { return addr; }
+  Fit_size fitting_sizes() const { return Fit_size(); }
+
+  static Phys_addr page_address(Phys_addr o, Order) { return o; }
+  static Phys_addr subpage_address(Phys_addr addr, V_pfc) { return addr; }
+  static V_pfn page_address(V_pfn addr, Order) { return addr; }
+  static V_pfc subpage_offset(V_pfn addr, Order o) { return cxx::get_lsb(addr, o); }
+
+  static Phys_addr to_pfn(Phys_addr p) { return p; }
+  static V_pfn to_pfn(V_pfn p) { return p; }
+  static V_pfc to_pcnt(Order s) { return V_pfc(1) << s; }
+
+  static V_pfc to_size(Page_order p)
+  { return V_pfc(1) << p; }
+
+  FIASCO_SPACE_VIRTUAL
+  bool v_lookup(V_pfn const &virt, Phys_addr *phys = 0,
+                Page_order *size = 0, Attr *attribs = 0);
+
+  FIASCO_SPACE_VIRTUAL
+  L4_fpage::Rights v_delete(V_pfn virt, Order size,
+                            L4_fpage::Rights page_attribs);
+
+  FIASCO_SPACE_VIRTUAL
+  Status v_insert(Phys_addr phys, V_pfn const &virt, Order size,
+                  Attr page_attribs);
+
+  FIASCO_SPACE_VIRTUAL
+  Capability lookup(Cap_index virt);
+
+  FIASCO_SPACE_VIRTUAL
+  V_pfn obj_map_max_address() const;
+
+  FIASCO_SPACE_VIRTUAL
+  void caps_free();
+
+  Kobject_iface *lookup_local(Cap_index virt, L4_fpage::Rights *rights = 0);
+
+  inline V_pfn map_max_address() const
+  { return obj_map_max_address(); }
 };
 
 template< typename SPACE >
 char const * const Generic_obj_space<SPACE>::name = "Obj_space";
 
 
+// ------------------------------------------------------------------------------
+INTERFACE [debug]:
+
+EXTENSION class Generic_obj_space
+{
+public:
+  FIASCO_SPACE_VIRTUAL Entry *jdb_lookup_cap(Cap_index index);
+};
+
 // -------------------------------------------------------------------------
 IMPLEMENTATION:
 
 PUBLIC template< typename SPACE >
 static inline
 Mword
-Generic_obj_space<SPACE>::xlate_flush(unsigned char rights)
-{ return rights; }
+Generic_obj_space<SPACE>::xlate_flush(L4_fpage::Rights rights)
+{ return L4_fpage::Rights::val(rights); }
 
 PUBLIC template< typename SPACE >
 static inline
-Mword
-Generic_obj_space<SPACE>::is_full_flush(unsigned char rights)
-{ return rights & L4_fpage::R; }
+bool
+Generic_obj_space<SPACE>::is_full_flush(L4_fpage::Rights rights)
+{ return rights & L4_fpage::Rights::R(); }
 
 PUBLIC template< typename SPACE >
 static inline
-Mword
+L4_fpage::Rights
 Generic_obj_space<SPACE>::xlate_flush_result(Mword /*attribs*/)
-{ return 0; }
+{ return L4_fpage::Rights(0); }
 
 PUBLIC template< typename SPACE >
-inline NEEDS[Generic_obj_space::caps_free]
+inline
 Generic_obj_space<SPACE>::~Generic_obj_space()
 {
-  caps_free();
+  this->caps_free();
 }
 
+IMPLEMENT template< typename SPACE > inline
+void __attribute__((__flatten__))
+Generic_obj_space<SPACE>::caps_free()
+{ Base::caps_free(); }
+
 PUBLIC template< typename SPACE >
 inline
 bool
-Generic_obj_space<SPACE>::v_fabricate(Addr const &address,
-                                      Phys_addr *phys, Size *size,
-                                      unsigned* attribs = 0)
+Generic_obj_space<SPACE>::v_fabricate(V_pfn const &address,
+                                      Phys_addr *phys, Page_order *size,
+                                      Attr* attribs = 0)
 {
-  return Generic_obj_space::v_lookup(address, phys, size, attribs);
+  return this->v_lookup(address, phys, size, attribs);
 }
 
 
 PUBLIC template< typename SPACE >
 inline static
 void
-Generic_obj_space<SPACE>::tlb_flush ()
+Generic_obj_space<SPACE>::tlb_flush_spaces(bool, Generic_obj_space<SPACE> *,
+                                           Generic_obj_space<SPACE> *)
 {}
 
 PUBLIC template< typename SPACE >
 inline static
-typename Generic_obj_space<SPACE>::Addr
-Generic_obj_space<SPACE>::canonize(Addr v)
-{ return v; }
-
-// ------------------------------------------------------------------------
-INTERFACE [debug]:
-
-EXTENSION class Generic_obj_space
-{
-public:
-  struct Dbg_info
-  {
-    Address offset;
-    Generic_obj_space<SPACE> *s;
-  };
-
-};
-
-
-// ------------------------------------------------------------------------
-IMPLEMENTATION [debug]:
-
-#include "dbg_page_info.h"
-#include "warn.h"
-
-PUBLIC  template< typename SPACE >
-static
-void
-Generic_obj_space<SPACE>::add_dbg_info(void *p, Generic_obj_space *s,
-                                         Address cap)
-{
-  Dbg_page_info *info = new Dbg_page_info(Virt_addr((Address)p));
-
-  if (EXPECT_FALSE(!info))
-    {
-      WARN("oom: could not allocate debug info fo page %p\n", p);
-      return;
-    }
-
-  info->info<Dbg_info>()->s = s;
-  info->info<Dbg_info>()->offset = (cap / Caps_per_page) * Caps_per_page;
-  Dbg_page_info::table().insert(info);
-}
-
-PUBLIC  template< typename SPACE >
-static
 void
-Generic_obj_space<SPACE>::remove_dbg_info(void *p)
-{
-  Dbg_page_info *info = Dbg_page_info::table().remove(Virt_addr((Address)p));
-  if (info)
-    delete info;
-  else
-    WARN("could not find debug info for page %p\n", p);
-}
-
+Generic_obj_space<SPACE>::tlb_flush()
+{}
 
-// ------------------------------------------------------------------------
-IMPLEMENTATION [!debug]:
+PUBLIC template< typename SPACE >
+inline static
+typename Generic_obj_space<SPACE>::V_pfn
+Generic_obj_space<SPACE>::canonize(V_pfn v)
+{ return v; }
 
-PUBLIC  template< typename SPACE > inline
-static
-void
-Generic_obj_space<SPACE>::add_dbg_info(void *, Generic_obj_space *, Address)
-{}
-  
-PUBLIC  template< typename SPACE > inline
-static
-void
-Generic_obj_space<SPACE>::remove_dbg_info(void *)
-{}
diff --git a/kernel/fiasco/src/kern/obj_space_phys_util.cpp b/kernel/fiasco/src/kern/obj_space_phys_util.cpp
new file mode 100644 (file)
index 0000000..fd12203
--- /dev/null
@@ -0,0 +1,267 @@
+INTERFACE:
+
+#include "assert_opt.h"
+#include "obj_space_types.h"
+#include "ram_quota.h"
+
+template< typename SPACE >
+class Obj_space_phys
+{
+public:
+  typedef Obj::Attr Attr;
+  typedef Obj::Capability Capability;
+  typedef Obj::Entry Entry;
+  typedef Kobject_iface *Phys_addr;
+
+  typedef Obj::Cap_addr V_pfn;
+  typedef Cap_diff V_pfc;
+  typedef Order Page_order;
+
+  bool v_lookup(V_pfn const &virt, Phys_addr *phys,
+                Page_order *size, Attr *attribs);
+
+  L4_fpage::Rights v_delete(V_pfn virt, Order size,
+                            L4_fpage::Rights page_attribs);
+  Obj::Insert_result v_insert(Phys_addr phys, V_pfn const &virt, Order size,
+                              Attr page_attribs);
+
+  Capability lookup(Cap_index virt);
+
+private:
+  enum
+  {
+    Slots_per_dir = Config::PAGE_SIZE / sizeof(void*)
+  };
+
+  struct Cap_table { Entry e[Obj::Caps_per_page]; };
+  struct Cap_dir   { Cap_table *d[Slots_per_dir]; };
+  Cap_dir *_dir;
+
+  Ram_quota *ram_quota() const
+  {
+    assert_opt (this);
+    return SPACE::ram_quota(this);
+  }
+};
+
+
+//----------------------------------------------------------------------------
+IMPLEMENTATION:
+
+#include <cstring>
+#include <cassert>
+
+#include "atomic.h"
+#include "config.h"
+#include "cpu.h"
+#include "kmem_alloc.h"
+#include "mem.h"
+#include "mem_layout.h"
+#include "ram_quota.h"
+#include "static_assert.h"
+
+PUBLIC template< typename SPACE >
+inline NEEDS["static_assert.h"]
+Obj_space_phys<SPACE>::Obj_space_phys()
+{
+  static_assert(sizeof(Cap_dir) == Config::PAGE_SIZE, "cap_dir size mismatch");
+  _dir = (Cap_dir*)Kmem_alloc::allocator()->q_unaligned_alloc(ram_quota(), Config::PAGE_SIZE);
+  if (_dir)
+    Mem::memset_mwords(_dir, 0, Config::PAGE_SIZE / sizeof(Mword));
+}
+
+PRIVATE template< typename SPACE >
+typename Obj_space_phys<SPACE>::Entry *
+Obj_space_phys<SPACE>::get_cap(Cap_index index)
+{
+  if (EXPECT_FALSE(!_dir))
+    return 0;
+
+  unsigned d_idx = cxx::int_value<Cap_index>(index) >> Obj::Caps_per_page_ld2;
+  if (EXPECT_FALSE(d_idx >= Slots_per_dir))
+    return 0;
+
+  Cap_table *tab = _dir->d[d_idx];
+
+  if (EXPECT_FALSE(!tab))
+    return 0;
+
+  unsigned offs  = cxx::get_lsb(cxx::int_value<Cap_index>(index), Obj::Caps_per_page_ld2);
+  return &tab->e[offs];
+}
+
+PRIVATE template< typename SPACE >
+typename Obj_space_phys<SPACE>::Entry *
+Obj_space_phys<SPACE>::caps_alloc(Cap_index virt)
+{
+  static_assert(sizeof(Cap_table) == Config::PAGE_SIZE, "cap table size mismatch");
+  unsigned d_idx = cxx::int_value<Cap_index>(virt) >> Obj::Caps_per_page_ld2;
+  if (EXPECT_FALSE(d_idx >= Slots_per_dir))
+    return 0;
+
+  void *mem = Kmem_alloc::allocator()->q_unaligned_alloc(ram_quota(), Config::PAGE_SIZE);
+
+  if (!mem)
+    return 0;
+
+  Obj::add_cap_page_dbg_info(mem, SPACE::get_space(this),  cxx::int_value<Cap_index>(virt));
+
+  Mem::memset_mwords(mem, 0, Config::PAGE_SIZE / sizeof(Mword));
+
+  Cap_table *tab = _dir->d[d_idx] = (Cap_table*)mem;
+  return &tab->e[ cxx::get_lsb(cxx::int_value<Cap_index>(virt), Obj::Caps_per_page_ld2)];
+}
+
+PUBLIC template< typename SPACE >
+void
+Obj_space_phys<SPACE>::caps_free()
+{
+  if (!_dir)
+    return;
+
+  Cap_dir *d = _dir;
+  _dir = 0;
+
+  Kmem_alloc *a = Kmem_alloc::allocator();
+  for (unsigned i = 0; i < Slots_per_dir; ++i)
+    {
+      if (!d->d[i])
+        continue;
+
+      Obj::remove_cap_page_dbg_info(d->d[i]);
+      a->q_unaligned_free(ram_quota(), Config::PAGE_SIZE, d->d[i]);
+    }
+
+  a->q_unaligned_free(ram_quota(), Config::PAGE_SIZE, d);
+}
+
+//
+// Utilities for map<Obj_space_phys> and unmap<Obj_space_phys>
+//
+
+IMPLEMENT template< typename SPACE >
+inline NEEDS[Obj_space_phys::get_cap]
+bool __attribute__((__flatten__))
+Obj_space_phys<SPACE>::v_lookup(V_pfn const &virt, Phys_addr *phys,
+                                Page_order *size, Attr *attribs)
+{
+  if (size) *size = Page_order(0);
+  Entry *cap = get_cap(virt);
+
+  if (EXPECT_FALSE(!cap))
+    {
+      if (size) *size = Page_order(Obj::Caps_per_page_ld2);
+      return false;
+    }
+
+  Capability c = *cap;
+
+  Obj::set_entry(virt, cap);
+  if (phys) *phys = c.obj();
+  if (c.valid() && attribs) *attribs = cap->rights();
+  return c.valid();
+}
+
+IMPLEMENT template< typename SPACE >
+inline NEEDS [Obj_space_phys::get_cap]
+typename Obj_space_phys<SPACE>::Capability __attribute__((__flatten__))
+Obj_space_phys<SPACE>::lookup(Cap_index virt)
+{
+  Capability *c = get_cap(virt);
+
+  if (EXPECT_FALSE(!c))
+    return Capability(0); // void
+
+  return *c;
+}
+
+PUBLIC template< typename SPACE >
+inline
+Kobject_iface *
+Obj_space_phys<SPACE>::lookup_local(Cap_index virt, L4_fpage::Rights *rights)
+{
+  Entry *c = get_cap(virt);
+
+  if (EXPECT_FALSE(!c))
+    return 0;
+
+  Capability cap = *c;
+
+  if (rights)
+    *rights = L4_fpage::Rights(cap.rights());
+
+  return cap.obj();
+}
+
+
+IMPLEMENT template< typename SPACE >
+inline NEEDS[<cassert>, Obj_space_phys::get_cap]
+L4_fpage::Rights __attribute__((__flatten__))
+Obj_space_phys<SPACE>::v_delete(V_pfn virt, Page_order size,
+                                   L4_fpage::Rights page_attribs = L4_fpage::Rights::FULL())
+{
+  (void)size;
+  assert (size == Page_order(0));
+  Capability *c = get_cap(virt);
+
+  if (c && c->valid())
+    {
+      if (page_attribs & L4_fpage::Rights::R())
+        c->invalidate();
+      else
+       c->del_rights(page_attribs);
+    }
+
+  return L4_fpage::Rights(0);
+}
+
+IMPLEMENT template< typename SPACE >
+inline NEEDS[Obj_space_phys::caps_alloc]
+typename Obj::Insert_result __attribute__((__flatten__))
+Obj_space_phys<SPACE>::v_insert(Phys_addr phys, V_pfn const &virt, Page_order size,
+                                Attr page_attribs)
+{
+  (void)size;
+  assert (size == Page_order(0));
+
+  Entry *c = get_cap(virt);
+
+  if (!c && !(c = caps_alloc(virt)))
+    return Obj::Insert_err_nomem;
+
+  if (c->valid())
+    {
+      if (c->obj() == phys)
+       {
+         if (EXPECT_FALSE(c->rights() == page_attribs))
+           return Obj::Insert_warn_exists;
+
+         c->add_rights(page_attribs);
+         return Obj::Insert_warn_attrib_upgrade;
+       }
+      else
+       return Obj::Insert_err_exists;
+    }
+
+  Obj::set_entry(virt, c);
+  c->set(phys, page_attribs);
+  return Obj::Insert_ok;
+}
+
+
+PUBLIC template< typename SPACE >
+inline
+typename Obj_space_phys<SPACE>::V_pfn
+Obj_space_phys<SPACE>::obj_map_max_address() const
+{
+  return V_pfn(Slots_per_dir * Obj::Caps_per_page);
+}
+
+// ------------------------------------------------------------------------------
+IMPLEMENTATION [debug]:
+
+PUBLIC template< typename SPACE >
+typename Obj_space_phys<SPACE>::Entry *
+Obj_space_phys<SPACE>::jdb_lookup_cap(Cap_index index)
+{ return get_cap(index); }
+
diff --git a/kernel/fiasco/src/kern/obj_space_types.cpp b/kernel/fiasco/src/kern/obj_space_types.cpp
new file mode 100644 (file)
index 0000000..7122231
--- /dev/null
@@ -0,0 +1,210 @@
+INTERFACE:
+
+#include <cxx/cxx_int>
+#include <cxx/hlist>
+
+#include "config.h"
+#include "types.h"
+#include "l4_types.h"
+#include "l4_msg_item.h"
+#include "template_math.h"
+
+class Kobject_iface;
+class Kobject_mapdb;
+class Jdb_mapdb;
+
+namespace Obj {
+
+  struct Attr
+  : cxx::int_type_base<unsigned char, Attr>,
+    cxx::int_bit_ops<Attr>
+  {
+    Attr() = default;
+    explicit Attr(unsigned char r)
+    : cxx::int_type_base<unsigned char, Attr>(r) {}
+
+    Attr(L4_fpage::Rights r, unsigned char extra)
+    : cxx::int_type_base<unsigned char, Attr>(cxx::int_value<L4_fpage::Rights>(r) | extra)
+    {}
+
+
+    L4_fpage::Rights rights() const { return L4_fpage::Rights(_v & 0x0f); }
+    unsigned char extra() const { return _v & 0xf0; }
+
+    static Attr Full() { return Attr(0xff); }
+  };
+
+  class Capability
+  {
+  private:
+    Mword _obj;
+
+  public:
+    Capability() {}
+    explicit Capability(Mword v) : _obj(v) {}
+    Kobject_iface *obj() const { return (Kobject_iface *)(_obj & ~3UL); }
+    void set(Kobject_iface *obj, unsigned char rights)
+    { _obj = Mword(obj) | rights; }
+    bool valid() const { return _obj; }
+    void invalidate() { _obj = 0; }
+    unsigned char rights() const { return _obj & 3; }
+    void add_rights(unsigned char r) { _obj |= r & 3; }
+    void del_rights(L4_fpage::Rights r)
+    { _obj &= ~(cxx::int_value<L4_fpage::Rights>(r) & 3); }
+
+    bool operator == (Capability const &c) const { return _obj == c._obj; }
+  };
+
+  /**
+   * Tn the case of a flat copy model for capabilities, we have some
+   * extra mapping information directly colocated within the cap tables.
+   */
+  class Mapping : public cxx::H_list_item
+  {
+    friend class ::Kobject_mapdb;
+    friend class ::Jdb_mapdb;
+
+  public:
+    typedef cxx::H_list<Mapping> List;
+
+    enum Flag
+    {
+      Delete  = 0x08, //L4_fpage::CD
+      Ref_cnt = 0x10,
+
+      Initial_flags = Delete | Ref_cnt | L4_msg_item::C_ctl_rights
+    };
+
+  protected:
+    Mword _flags : 8;
+    Mword _pad   : 24;
+
+  public:
+    Mapping() : _flags(0) {}
+    // fake this really badly
+    Mapping *parent() { return this; }
+    Mword delete_rights() const { return _flags & Delete; }
+    Mword ref_cnt() const { return _flags & Ref_cnt; }
+
+    void put_as_root() { _flags = Initial_flags; }
+  };
+
+
+  class Entry : public Capability, public Mapping
+  {
+  public:
+    Entry() {}
+    explicit Entry(Mword v) : Capability(v) {}
+
+    Attr rights() const
+    { return Attr(Capability::rights() | (_flags & ~3)); }
+
+    void set(Kobject_iface *obj, Attr rights)
+    {
+      Capability::set(obj, cxx::int_value<Attr>(rights) & 3);
+      _flags = cxx::int_value<Attr>(rights) & 0xf8;
+    }
+    void add_rights(Attr r)
+    {
+      Capability::add_rights(cxx::int_value<Attr>(r) & 3);
+      _flags |= (cxx::int_value<Attr>(r) & 0xf8);
+    }
+
+    void del_rights(L4_fpage::Rights r)
+    {
+      Capability::del_rights(r);
+      _flags &= ~(cxx::int_value<L4_fpage::Rights>(r) & 0xf8);
+    }
+  };
+
+  struct Cap_addr
+  : public cxx::int_type_order_base<unsigned long, Cap_addr, Order, Cap_diff>
+  {
+  private:
+    typedef cxx::int_type_order_base<unsigned long, Cap_addr, Order, Cap_diff> Base;
+
+  public:
+    mutable Entry *_c;
+    Cap_addr() {}
+    Cap_addr(unsigned long a, Entry *c) : Base(a), _c(c) {}
+    explicit Cap_addr(Cap_index idx)
+    : Base(cxx::int_value<Cap_index>(idx)), _c(0)
+    {}
+
+    explicit Cap_addr(unsigned long v) : Base(v), _c(0) {}
+
+    operator Cap_index () const { return Cap_index(_v); }
+
+    void set_entry(Entry *e) const { _c = e; }
+  };
+
+  inline void set_entry(Cap_addr const &ca, Entry *e)
+  { ca.set_entry(e); }
+
+  enum Insert_result
+  {
+    Insert_ok = 0,             ///< Mapping was added successfully.
+    Insert_warn_exists,                ///< Mapping already existed
+    Insert_warn_attrib_upgrade,        ///< Mapping already existed, attribs upgrade
+    Insert_err_nomem,          ///< Couldn't alloc new page table
+    Insert_err_exists          ///< A mapping already exists at the target addr
+  };
+
+  enum
+  {
+    Caps_per_page_max = Config::PAGE_SIZE / sizeof(Obj::Entry),
+    Caps_per_page_ld2 = Tl_math::Ld<Caps_per_page_max>::Res,
+    Caps_per_page     = 1 << Caps_per_page_ld2,
+  };
+  static_assert(Caps_per_page == Caps_per_page_max, "hm, not a power of two caps on a single memory page");
+}
+
+// ------------------------------------------------------------------------
+INTERFACE [debug]:
+
+#include "dbg_page_info.h"
+#include "warn.h"
+
+class Space;
+
+namespace Obj
+{
+  struct Cap_page_dbg_info
+  {
+    Address offset;
+    Space *s;
+  };
+
+  inline void add_cap_page_dbg_info(void *p, Space *s, Address cap)
+  {
+    Dbg_page_info *info = new Dbg_page_info(Virt_addr((Address)p));
+
+    if (EXPECT_FALSE(!info))
+      {
+        WARN("oom: could not allocate debug info fo page %p\n", p);
+        return;
+      }
+
+    info->info<Cap_page_dbg_info>()->s = s;
+    info->info<Cap_page_dbg_info>()->offset = (cap / Caps_per_page) * Caps_per_page;
+    Dbg_page_info::table().insert(info);
+  }
+
+  inline void remove_cap_page_dbg_info(void *p)
+  {
+    Dbg_page_info *info = Dbg_page_info::table().remove(Virt_addr((Address)p));
+    if (info)
+      delete info;
+    else
+      WARN("could not find debug info for page %p\n", p);
+  }
+}
+
+
+// ------------------------------------------------------------------------
+INTERFACE [!debug]:
+
+namespace Obj {
+  static void add_cap_page_dbg_info(void *, void *, Address) {}
+  static void remove_cap_page_dbg_info(void *) {}
+}
diff --git a/kernel/fiasco/src/kern/obj_space_virt_util.cpp b/kernel/fiasco/src/kern/obj_space_virt_util.cpp
new file mode 100644 (file)
index 0000000..f7eb33e
--- /dev/null
@@ -0,0 +1,336 @@
+INTERFACE:
+
+#include "mem.h"
+#include "mem_space.h"
+#include "ram_quota.h"
+#include "obj_space_types.h"
+
+template<typename SPACE>
+class Obj_space_virt
+{
+public:
+  typedef Obj::Attr Attr;
+  typedef Obj::Capability Capability;
+  typedef Obj::Entry Entry;
+  typedef Kobject_iface *Phys_addr;
+
+  typedef Obj::Cap_addr V_pfn;
+  typedef Cap_diff V_pfc;
+  typedef Order Page_order;
+
+  bool v_lookup(V_pfn const &virt, Phys_addr *phys,
+                Page_order *size, Attr *attribs);
+
+  L4_fpage::Rights v_delete(V_pfn virt, Order size,
+                            L4_fpage::Rights page_attribs);
+  Obj::Insert_result v_insert(Phys_addr phys, V_pfn const &virt, Order size,
+                              Attr page_attribs);
+
+  Capability lookup(Cap_index virt);
+
+private:
+  enum
+  {
+    // do not use the virtually mapped cap table in
+    // v_lookup and v_insert, because the map logic needs the kernel
+    // address for link pointers in the map-nodes and these addresses must
+    // be valid in all address spaces.
+    Optimize_local = 0,
+
+    Whole_space = 20,
+    Map_max_address = 1UL << 20, /* 20bit obj index */
+  };
+};
+
+IMPLEMENTATION:
+
+#include <cstring>
+#include <cassert>
+
+#include "atomic.h"
+#include "config.h"
+#include "cpu.h"
+#include "kdb_ke.h"
+#include "kmem_alloc.h"
+#include "mem_layout.h"
+
+PRIVATE  template< typename SPACE >
+static inline NEEDS["mem_layout.h"]
+typename Obj_space_virt<SPACE>::Entry *
+Obj_space_virt<SPACE>::cap_virt(Cap_index index)
+{ return reinterpret_cast<Entry*>(Mem_layout::Caps_start) + cxx::int_value<Cap_index>(index); }
+
+
+
+PRIVATE template< typename SPACE >
+inline NEEDS["mem_space.h", "mem_layout.h", Obj_space_virt::cap_virt]
+typename Obj_space_virt<SPACE>::Entry *
+Obj_space_virt<SPACE>::get_cap(Cap_index index)
+{
+  Mem_space *ms = SPACE::mem_space(this);
+
+  Address phys = Address(ms->virt_to_phys((Address)cap_virt(index)));
+  if (EXPECT_FALSE(phys == ~0UL))
+    return 0;
+
+  return reinterpret_cast<Entry*>(Mem_layout::phys_to_pmem(phys));
+}
+
+PRIVATE  template< typename SPACE >
+/*inline NEEDS["kmem_alloc.h", <cstring>, "ram_quota.h",
+                     Obj_space_virt::cap_virt]*/
+typename Obj_space_virt<SPACE>::Entry *
+Obj_space_virt<SPACE>::caps_alloc(Cap_index virt)
+{
+  Address cv = (Address)cap_virt(virt);
+  void *mem = Kmem_alloc::allocator()->q_unaligned_alloc(SPACE::ram_quota(this), Config::PAGE_SIZE);
+
+  if (!mem)
+    return 0;
+
+  Obj::add_cap_page_dbg_info(mem, SPACE::get_space(this), cxx::int_value<Cap_index>(virt));
+
+  Mem::memset_mwords(mem, 0, Config::PAGE_SIZE / sizeof(Mword));
+
+  Mem_space::Status s;
+  s = SPACE::mem_space(this)->v_insert(
+      Mem_space::Phys_addr(Mem_space::kernel_space()->virt_to_phys((Address)mem)),
+      cxx::mask_lsb(Virt_addr(cv), Mem_space::Page_order(Config::PAGE_SHIFT)),
+      Mem_space::Page_order(Config::PAGE_SHIFT),
+      Mem_space::Attr(L4_fpage::Rights::RW()));
+      //| Mem_space::Page_referenced | Mem_space::Page_dirty);
+
+  switch (s)
+    {
+    case Mem_space::Insert_ok:
+      break;
+    case Mem_space::Insert_warn_exists:
+    case Mem_space::Insert_warn_attrib_upgrade:
+      assert (false);
+      break;
+    case Mem_space::Insert_err_exists:
+    case Mem_space::Insert_err_nomem:
+      Kmem_alloc::allocator()->q_unaligned_free(SPACE::ram_quota(this),
+          Config::PAGE_SIZE, mem);
+      return 0;
+    };
+
+  unsigned long cap = cv & (Config::PAGE_SIZE - 1) | (unsigned long)mem;
+
+  return reinterpret_cast<Entry*>(cap);
+}
+
+PROTECTED template< typename SPACE >
+void
+Obj_space_virt<SPACE>::caps_free()
+{
+  Mem_space *ms = SPACE::mem_space(this);
+  if (EXPECT_FALSE(!ms || !ms->dir()))
+    return;
+
+  Kmem_alloc *a = Kmem_alloc::allocator();
+  for (Cap_index i = Cap_index(0); i < obj_map_max_address();
+       i += Cap_diff(Obj::Caps_per_page))
+    {
+      Entry *c = get_cap(i);
+      if (!c)
+       continue;
+
+      Address cp = Address(ms->virt_to_phys(Address(c)));
+      assert_kdb (cp != ~0UL);
+      void *cv = (void*)Mem_layout::phys_to_pmem(cp);
+      Obj::remove_cap_page_dbg_info(cv);
+
+      a->q_unaligned_free(SPACE::ram_quota(this), Config::PAGE_SIZE, cv);
+    }
+  ms->dir()->destroy(Virt_addr(Mem_layout::Caps_start),
+                     Virt_addr(Mem_layout::Caps_end-1),
+                     Pdir::Super_level,
+                     Pdir::Depth,
+                     Kmem_alloc::q_allocator(SPACE::ram_quota(this)));
+}
+
+//
+// Utilities for map<Obj_space_virt> and unmap<Obj_space_virt>
+//
+
+IMPLEMENT  template< typename SPACE >
+inline  NEEDS[Obj_space_virt::cap_virt, Obj_space_virt::get_cap]
+bool __attribute__((__flatten__))
+Obj_space_virt<SPACE>::v_lookup(V_pfn const &virt, Phys_addr *phys,
+                                   Page_order *size, Attr *attribs)
+{
+  if (size) *size = Order(0);
+  Entry *cap;
+
+  if (Optimize_local
+      && SPACE::mem_space(this) == Mem_space::current_mem_space(current_cpu()))
+    cap = cap_virt(virt);
+  else
+    cap = get_cap(virt);
+
+  if (EXPECT_FALSE(!cap))
+    {
+      if (size) *size = Order(Obj::Caps_per_page_ld2);
+      return false;
+    }
+
+  if (Optimize_local)
+    {
+      Capability c = Mem_layout::read_special_safe((Capability*)cap);
+
+      if (phys) *phys = c.obj();
+      if (c.valid() && attribs)
+        *attribs = Attr(c.rights());
+      return c.valid();
+    }
+  else
+    {
+      Obj::set_entry(virt, cap);
+      if (phys) *phys = cap->obj();
+      if (cap->valid() && attribs)
+        *attribs = Attr(cap->rights());
+      return cap->valid();
+    }
+}
+
+IMPLEMENT template< typename SPACE >
+inline NEEDS [Obj_space_virt::cap_virt, Obj_space_virt::get_cap]
+typename Obj_space_virt<SPACE>::Capability __attribute__((__flatten__))
+Obj_space_virt<SPACE>::lookup(Cap_index virt)
+{
+  Capability *c;
+  virt &= Cap_index(~(~0UL << Whole_space));
+
+  if (SPACE::mem_space(this) == Mem_space::current_mem_space(current_cpu()))
+    c = reinterpret_cast<Capability*>(cap_virt(virt));
+  else
+    c = get_cap(virt);
+
+  if (EXPECT_FALSE(!c))
+    return Capability(0); // void
+
+  return Mem_layout::read_special_safe(c);
+}
+
+PUBLIC template< typename SPACE >
+inline NEEDS [Obj_space_virt::cap_virt]
+Kobject_iface *
+Obj_space_virt<SPACE>::lookup_local(Cap_index virt, L4_fpage::Rights *rights)
+{
+  virt &= Cap_index(~(~0UL << Whole_space));
+  Capability *c = reinterpret_cast<Capability*>(cap_virt(virt));
+  Capability cap = Mem_layout::read_special_safe(c);
+  if (rights) *rights = L4_fpage::Rights(cap.rights());
+  return cap.obj();
+}
+
+
+IMPLEMENT template< typename SPACE >
+inline NEEDS[<cassert>, Obj_space_virt::cap_virt, Obj_space_virt::get_cap]
+L4_fpage::Rights __attribute__((__flatten__))
+Obj_space_virt<SPACE>::v_delete(V_pfn virt, Order size,
+                                   L4_fpage::Rights page_attribs)
+{
+  (void)size;
+  assert (size == Order(0));
+
+  Entry *c;
+  if (Optimize_local
+      && SPACE::mem_space(this) == Mem_space::current_mem_space(current_cpu()))
+    {
+      c = cap_virt(virt);
+      if (!c)
+       return L4_fpage::Rights(0);
+
+      Capability cap = Mem_layout::read_special_safe((Capability*)c);
+      if (!cap.valid())
+       return L4_fpage::Rights(0);
+    }
+  else
+    c = get_cap(virt);
+
+  if (c && c->valid())
+    {
+      if (page_attribs & L4_fpage::Rights::R())
+        c->invalidate();
+      else
+        c->del_rights(page_attribs & L4_fpage::Rights::CWSD());
+    }
+
+  return L4_fpage::Rights(0);
+}
+
+IMPLEMENT  template< typename SPACE >
+inline NEEDS[Obj_space_virt::cap_virt, Obj_space_virt::caps_alloc,
+             Obj_space_virt::get_cap, "kdb_ke.h"]
+typename Obj::Insert_result __attribute__((__flatten__))
+Obj_space_virt<SPACE>::v_insert(Phys_addr phys, V_pfn const &virt, Order size,
+                                Attr page_attribs)
+{
+  (void)size;
+  assert (size == Order(0));
+
+  Entry *c;
+
+  if (Optimize_local
+      && SPACE::mem_space(this) == Mem_space::current_mem_space(current_cpu()))
+    {
+      c = cap_virt(virt);
+      if (!c)
+       return Obj::Insert_err_nomem;
+
+      Capability cap;
+      if (!Mem_layout::read_special_safe((Capability*)c, cap)
+         && !caps_alloc(virt))
+       return Obj::Insert_err_nomem;
+    }
+  else
+    {
+      c = get_cap(virt);
+      if (!c && !(c = caps_alloc(virt)))
+       return Obj::Insert_err_nomem;
+      Obj::set_entry(virt, c);
+    }
+
+  if (c->valid())
+    {
+      if (c->obj() == phys)
+       {
+         if (EXPECT_FALSE(c->rights() == page_attribs))
+           return Obj::Insert_warn_exists;
+
+         c->add_rights(page_attribs);
+         return Obj::Insert_warn_attrib_upgrade;
+       }
+      else
+       return Obj::Insert_err_exists;
+    }
+
+  c->set(phys, page_attribs);
+  return Obj::Insert_ok;
+}
+
+
+PUBLIC  template< typename SPACE >
+virtual inline
+typename Obj_space_virt<SPACE>::V_pfn
+Obj_space_virt<SPACE>::obj_map_max_address() const
+{
+  Mword r;
+
+  r = (Mem_layout::Caps_end - Mem_layout::Caps_start) / sizeof(Entry);
+  if (Map_max_address < r)
+    r = Map_max_address;
+
+  return V_pfn(r);
+}
+
+// ------------------------------------------------------------------------------
+IMPLEMENTATION [debug]:
+
+PUBLIC  template< typename SPACE >
+typename Obj_space_virt<SPACE>::Entry *
+Obj_space_virt<SPACE>::jdb_lookup_cap(Cap_index index)
+{ return get_cap(index); }
+
index a482d9c6e6ecdc858bfb07e5d2f404c9e3daffca..6e0374afbde7ce55054f9a7a95b1658b85ec7ece 100644 (file)
@@ -1,12 +1,15 @@
 INTERFACE:
 
 #include "types.h"
+#include "l4_msg_item.h"
+
+EXTENSION class Page
+{
+public:
 
-namespace Page {
-  
   /* These things must be defined in arch part in
      the most efficent way according to the architecture.
-  
+
   typedef int Attribs;
 
   enum Attribs_enum {
@@ -20,11 +23,42 @@ namespace Page {
     NONCACHEABLE = xxx, ///< Caching is off
     CACHEABLE    = xxx, ///< Cahe is enabled
   };
-     
-  
+
   */
+  typedef L4_msg_item::Memory_type Type;
 
+  struct Kern
+  : cxx::int_type_base<unsigned char, Kern>,
+    cxx::int_bit_ops<Kern>,
+    cxx::int_null_chk<Kern>
+  {
+    Kern() = default;
+    explicit Kern(Value v) : cxx::int_type_base<unsigned char, Kern>(v) {}
 
+    static Kern Global() { return Kern(1); }
+  };
+
+  typedef L4_fpage::Rights Rights;
+
+  struct Attr
+  {
+    Rights rights;
+    Type type;
+    Kern kern;
+
+    Attr() = default;
+    explicit Attr(Rights r, Type t = Type::Normal(), Kern k = Kern(0))
+    : rights(r), type(t), kern(k) {}
+
+    Attr apply(Attr o) const
+    {
+      Attr n = *this;
+      n.rights &= o.rights;
+      if ((o.type & Type::Set()) == Type::Set())
+        n.type = o.type & ~Type::Set();
+      return n;
+    }
+  };
 };
 
 EXTENSION class PF {
@@ -60,45 +94,28 @@ public:
 
   bool valid() const { return _a; }
 
+  Phys_mem_addr::Value
+  to_phys(void *v) const { return _a->to_phys(v); }
+
 private:
   ALLOC *_a;
 };
 
 
-class Pdir : public Ptab::Base<Pte_base, Ptab_traits_vpn, Ptab_va_vpn >
+class Pdir
+: public Ptab::Base<Pte_ptr, Ptab_traits_vpn, Ptab_va_vpn >
 {
 public:
-  enum { Super_level = Pte_base::Super_level };
-
-private:
-  static bool       _have_superpages;
-  static unsigned   _super_level;
+  enum { Super_level = Pte_ptr::Super_level };
 };
 
 IMPLEMENTATION:
 //---------------------------------------------------------------------------
 
-bool Pdir::_have_superpages;
-unsigned  Pdir::_super_level;
-
 template<typename ALLOC>
 inline Pdir_alloc_simple<ALLOC> pdir_alloc(ALLOC *a)
 { return Pdir_alloc_simple<ALLOC>(a); }
 
-PUBLIC static inline
-void
-Pdir::have_superpages(bool yes)
-{
-  _have_superpages = yes;
-  _super_level = yes ? Super_level : (Super_level + 1);
-}
-
-PUBLIC static inline
-unsigned
-Pdir::super_level()
-{ return _super_level; }
-
-
 IMPLEMENT inline NEEDS[PF::is_usermode_error]
 Mword PF::pc_to_msgword1(Address pc, Mword error)
 {
@@ -112,11 +129,12 @@ PUBLIC
 Address
 Pdir::virt_to_phys(Address virt) const
 {
-  Iter i = walk(Virt_addr(virt));
-  if (!i.e->valid())
+  Virt_addr va(virt);
+  auto i = walk(va);
+  if (!i.is_valid())
     return ~0;
 
-  return i.e->addr() | (virt & ~(~0UL << i.shift()));
+  return i.page_addr() | cxx::get_lsb(virt, i.page_order());
 }
 
 //---------------------------------------------------------------------------
@@ -126,12 +144,14 @@ PUBLIC
 Address
 Pdir::virt_to_phys(Address virt) const
 {
-  Iter i = walk(Virt_addr(virt));
+  auto i = walk(Virt_addr(virt));
 
-  if (!i.e->valid())
+  //if (!i.is_valid())
     return ~0UL;
 
+#ifdef FIX_THIS
   Address phys;
   Pte_htab::pte_lookup(i.e, &phys);
-  return phys | (virt & ~(~0UL << i.shift()));
+  return phys | (virt & ~(~0UL << i.page_order()));
+#endif
 }
index 32d53a0715d91b406f5363c38732ae27f5f24be8..ca06a6fb542c759fb47307d3148f5f6ab8a204f0 100644 (file)
@@ -1,8 +1,17 @@
+INTERFACE:
+
+template< typename T, unsigned EXTRA = 0 >
+class Per_cpu_array
+: public cxx::array<T, Cpu_number, Config::Max_num_cpus + EXTRA>
+{};
+
 INTERFACE [mp]:
 
+#include "types.h"
+
 struct Per_cpu_ctor_data
 {
-  void (*func)(void *, unsigned);
+  void (*func)(void *, Cpu_number);
   void *base;
 };
 
@@ -20,7 +29,7 @@ INTERFACE:
 #include "static_init.h"
 #include "config.h"
 #include "context_base.h"
-#include <type_traits>
+#include <cxx/type_traits>
 
 #define DEFINE_PER_CPU_P(p) \
   DEFINE_PER_CPU_CTOR_DATA(__COUNTER__) \
@@ -33,9 +42,9 @@ class Per_cpu_data
 {
 public:
   static void init_ctors();
-  static void run_ctors(unsigned cpu);
-  static void run_late_ctors(unsigned cpu);
-  static bool valid(unsigned cpu);
+  static void run_ctors(Cpu_number cpu);
+  static void run_late_ctors(Cpu_number cpu);
+  static bool valid(Cpu_number cpu);
 };
 
 template< typename T > class Per_cpu_ptr;
@@ -47,8 +56,8 @@ class Per_cpu : private Per_cpu_data
 public:
   typedef T Type;
 
-  T const &cpu(unsigned) const;
-  T &cpu(unsigned);
+  T const &cpu(Cpu_number) const;
+  T &cpu(Cpu_number);
 
   T const &current() const { return cpu(current_cpu()); }
   T &current() { return cpu(current_cpu()); }
@@ -57,13 +66,13 @@ public:
   explicit Per_cpu(bool);
 
   template<typename TEST>
-  unsigned find_cpu(TEST const &test) const
+  Cpu_number find_cpu(TEST const &test) const
   {
-    for (unsigned i = 0; i < Config::Max_num_cpus; ++i)
+    for (Cpu_number i = Cpu_number::first(); i < Config::max_num_cpus(); ++i)
       if (valid(i) && test(cpu(i)))
         return i;
 
-    return ~0U;
+    return Cpu_number::nil();
   }
 
 private:
@@ -87,7 +96,7 @@ public:
     return *this;
   }
 
-  T &cpu(unsigned cpu);
+  T &cpu(Cpu_number cpu);
   T &current() { return cpu(current_cpu()); }
 
 private:
@@ -102,23 +111,23 @@ IMPLEMENTATION [!mp]:
 
 IMPLEMENT inline
 bool
-Per_cpu_data::valid(unsigned cpu)
+Per_cpu_data::valid(Cpu_number cpu)
 {
 #if defined NDEBUG
   (void)cpu;
   return 1;
 #else
-  return cpu == 0;
+  return cpu == Cpu_number::boot_cpu();
 #endif
 }
 
 IMPLEMENT inline
 template< typename T >
-T const &Per_cpu<T>::cpu(unsigned) const { return _d; }
+T const &Per_cpu<T>::cpu(Cpu_number) const { return _d; }
 
 IMPLEMENT inline
 template< typename T >
-T &Per_cpu<T>::cpu(unsigned) { return _d; }
+T &Per_cpu<T>::cpu(Cpu_number) { return _d; }
 
 IMPLEMENT
 template< typename T >
@@ -127,12 +136,12 @@ Per_cpu<T>::Per_cpu()
 
 IMPLEMENT
 template< typename T >
-Per_cpu<T>::Per_cpu(bool) : _d(0)
+Per_cpu<T>::Per_cpu(bool) : _d(Cpu_number::boot_cpu())
 {}
 
 IMPLEMENT inline
 template< typename T >
-T &Per_cpu_ptr<T>::cpu(unsigned) { return *_p; }
+T &Per_cpu_ptr<T>::cpu(Cpu_number) { return *_p; }
 
 
 IMPLEMENT
@@ -143,7 +152,7 @@ Per_cpu_data::init_ctors()
 
 IMPLEMENT inline
 void
-Per_cpu_data::run_ctors(unsigned)
+Per_cpu_data::run_ctors(Cpu_number)
 {
   extern ctor_function_t __PER_CPU_INIT_ARRAY_START__[];
   extern ctor_function_t __PER_CPU_INIT_ARRAY_END__[];
@@ -156,7 +165,7 @@ Per_cpu_data::run_ctors(unsigned)
 
 IMPLEMENT inline
 void
-Per_cpu_data::run_late_ctors(unsigned)
+Per_cpu_data::run_late_ctors(Cpu_number)
 {
   extern ctor_function_t __PER_CPU_LATE_INIT_ARRAY_START__[];
   extern ctor_function_t __PER_CPU_LATE_INIT_ARRAY_END__[];
@@ -186,7 +195,7 @@ private:
   struct Ctor_vector
   {
   public:
-    void push_back(void (*func)(void*,unsigned), void *base);
+    void push_back(void (*func)(void*,Cpu_number), void *base);
     unsigned len() const { return _len; }
     Ctor const &operator [] (unsigned idx) const
     {
@@ -200,7 +209,9 @@ private:
 
 protected:
   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 Cpu_number num_cpus() { return Cpu_number(Num_cpus); }
+  typedef Per_cpu_array<long, 1> Offset_array;
+  static Offset_array _offsets;
   static unsigned late_ctor_start;
   static Ctor_vector ctors;
 };
@@ -213,13 +224,13 @@ IMPLEMENTATION [mp]:
 #include <construction.h>
 #include <cstring>
 
-long Per_cpu_data::_offsets[Per_cpu_data::Num_cpus];
+Per_cpu_data::Offset_array Per_cpu_data::_offsets;
 unsigned Per_cpu_data::late_ctor_start;
 Per_cpu_data::Ctor_vector Per_cpu_data::ctors;
 
 IMPLEMENT
 void
-Per_cpu_data::Ctor_vector::push_back(void (*func)(void*,unsigned), void *base)
+Per_cpu_data::Ctor_vector::push_back(void (*func)(void*,Cpu_number), void *base)
 {
   extern Ctor _per_cpu_ctor_data_start[];
   extern Ctor _per_cpu_ctor_data_end[];
@@ -235,15 +246,15 @@ Per_cpu_data::Ctor_vector::push_back(void (*func)(void*,unsigned), void *base)
 
 IMPLEMENT inline
 bool
-Per_cpu_data::valid(unsigned cpu)
-{ return cpu < Num_cpus && _offsets[cpu] != -1; }
+Per_cpu_data::valid(Cpu_number cpu)
+{ return cpu < num_cpus() && _offsets[cpu] != -1; }
 
 IMPLEMENT inline template< typename T >
-T const &Per_cpu<T>::cpu(unsigned cpu) const
+T const &Per_cpu<T>::cpu(Cpu_number cpu) const
 { return *reinterpret_cast<T const *>((char  const *)&_d + _offsets[cpu]); }
 
 IMPLEMENT inline template< typename T >
-T &Per_cpu<T>::cpu(unsigned cpu)
+T &Per_cpu<T>::cpu(Cpu_number cpu)
 { return *reinterpret_cast<T*>((char *)&_d + _offsets[cpu]); }
 
 IMPLEMENT
@@ -256,7 +267,7 @@ Per_cpu<T>::Per_cpu()
 
 IMPLEMENT
 template< typename T >
-Per_cpu<T>::Per_cpu(bool) : _d(0)
+Per_cpu<T>::Per_cpu(bool) : _d(Cpu_number::boot_cpu())
 {
   //printf("  Per_cpu<T>(bool) [this=%p])\n", this);
   ctors.push_back(&ctor_w_arg, this);
@@ -264,7 +275,7 @@ Per_cpu<T>::Per_cpu(bool) : _d(0)
 
 PRIVATE static
 template< typename T >
-void Per_cpu<T>::ctor_wo_arg(void *obj, unsigned cpu)
+void Per_cpu<T>::ctor_wo_arg(void *obj, Cpu_number cpu)
 {
   //printf("Per_cpu<T>::ctor_wo_arg(obj=%p, cpu=%u -> %p)\n", obj, cpu, &(reinterpret_cast<Per_cpu<T>*>(obj)->cpu(cpu)));
   new (&reinterpret_cast<Per_cpu<T>*>(obj)->cpu(cpu)) T;
@@ -272,7 +283,7 @@ void Per_cpu<T>::ctor_wo_arg(void *obj, unsigned cpu)
 
 PRIVATE static
 template< typename T >
-void Per_cpu<T>::ctor_w_arg(void *obj, unsigned cpu)
+void Per_cpu<T>::ctor_w_arg(void *obj, Cpu_number cpu)
 {
   //printf("Per_cpu<T>::ctor_w_arg(obj=%p, cpu=%u -> %p)\n", obj, cpu, &reinterpret_cast<Per_cpu<T>*>(obj)->cpu(cpu));
   new (&reinterpret_cast<Per_cpu<T>*>(obj)->cpu(cpu)) T(cpu);
@@ -280,26 +291,26 @@ void Per_cpu<T>::ctor_w_arg(void *obj, unsigned cpu)
 
 IMPLEMENT inline
 template< typename T >
-T &Per_cpu_ptr<T>::cpu(unsigned cpu)
+T &Per_cpu_ptr<T>::cpu(Cpu_number cpu)
 { return *reinterpret_cast<T *>(reinterpret_cast<Address>(_p) + _offsets[cpu]); }
 
 IMPLEMENT
 void
 Per_cpu_data::init_ctors()
 {
-  for (unsigned i = 0; i < Num_cpus; ++i)
-    _offsets[i] = -1;
+  for (Offset_array::iterator i = _offsets.begin(); i != _offsets.end(); ++i)
+    *i = -1;
 }
 
 IMPLEMENT inline
 void
-Per_cpu_data::run_ctors(unsigned cpu)
+Per_cpu_data::run_ctors(Cpu_number cpu)
 {
   extern ctor_function_t __PER_CPU_INIT_ARRAY_START__[];
   extern ctor_function_t __PER_CPU_INIT_ARRAY_END__[];
   extern ctor_function_t __PER_CPU_CTORS_LIST__[];
   extern ctor_function_t __PER_CPU_CTORS_END__[];
-  if (cpu == 0)
+  if (cpu == Cpu_number::boot_cpu())
     {
       run_ctor_functions(__PER_CPU_INIT_ARRAY_START__, __PER_CPU_INIT_ARRAY_END__);
       run_ctor_functions(__PER_CPU_CTORS_LIST__, __PER_CPU_CTORS_END__);
@@ -313,13 +324,13 @@ Per_cpu_data::run_ctors(unsigned cpu)
 
 IMPLEMENT inline
 void
-Per_cpu_data::run_late_ctors(unsigned cpu)
+Per_cpu_data::run_late_ctors(Cpu_number cpu)
 {
   extern ctor_function_t __PER_CPU_LATE_INIT_ARRAY_START__[];
   extern ctor_function_t __PER_CPU_LATE_INIT_ARRAY_END__[];
   extern ctor_function_t __PER_CPU_LATE_CTORS_LIST__[];
   extern ctor_function_t __PER_CPU_LATE_CTORS_END__[];
-  if (cpu == 0)
+  if (cpu == Cpu_number::boot_cpu())
     {
       run_ctor_functions(__PER_CPU_LATE_INIT_ARRAY_START__, __PER_CPU_LATE_INIT_ARRAY_END__);
       run_ctor_functions(__PER_CPU_LATE_CTORS_LIST__, __PER_CPU_LATE_CTORS_END__);
index 86224572aba06b7f5aab8a7e66373622a154dc7a..d14bfb0b45ca4217ee35fa96851bf14e54409abf 100644 (file)
@@ -5,14 +5,14 @@ INTERFACE:
 class Per_cpu_data_alloc : public Per_cpu_data
 {
 public:
-  static bool alloc(unsigned cpu);
+  static bool alloc(Cpu_number cpu);
 };
 
 
 IMPLEMENTATION [!mp]:
 
 IMPLEMENT inline
-bool Per_cpu_data_alloc::alloc(unsigned)
+bool Per_cpu_data_alloc::alloc(Cpu_number)
 { return true; }
 
 
@@ -26,9 +26,9 @@ IMPLEMENTATION [mp]:
 #include "kmem_alloc.h"
 
 IMPLEMENT
-bool Per_cpu_data_alloc::alloc(unsigned cpu)
+bool Per_cpu_data_alloc::alloc(Cpu_number cpu)
 {
-  if (cpu >= Num_cpus || valid(cpu))
+  if (cpu >= Cpu_number(Num_cpus) || valid(cpu))
     return false;
 
   extern char _per_cpu_data_start[];
@@ -36,10 +36,10 @@ bool Per_cpu_data_alloc::alloc(unsigned cpu)
 
   printf("Per_cpu_data_alloc: (orig: %p-%p)\n", _per_cpu_data_start, _per_cpu_data_end);
 
-  if (cpu == 0)
+  if (cpu == Cpu_number::boot_cpu())
     {
       // we use the master copy for CPU 0
-      _offsets[0] = 0;
+      _offsets[cpu] = 0;
       return true;
     }
 
@@ -54,7 +54,8 @@ bool Per_cpu_data_alloc::alloc(unsigned cpu)
 
   _offsets[cpu] = per_cpu - _per_cpu_data_start;
   printf("Allocate %u bytes (%uKB) for CPU[%u] local storage (offset=%lx, %p-%p)\n",
-         size, (size + 513) / 1024, cpu, _offsets[cpu],
+         size, (size + 513) / 1024, cxx::int_value<Cpu_number>(cpu),
+         _offsets[cpu],
          _per_cpu_data_start + _offsets[cpu],
          _per_cpu_data_end + _offsets[cpu]);
 
index b168041001e96da0b9ded8d3969e4c212bfbc3fa..e68662e8e928e8c8c2f92283196d41b27660fc59 100644 (file)
@@ -348,8 +348,8 @@ Pic::restore_all( Status s )
 
 IMPLEMENT inline NEEDS[<cassert>]
 void
-Pic::set_cpu(unsigned, unsigned cpu)
+Pic::set_cpu(unsigned, Cpu_number cpu)
 {
   (void)cpu;
-  assert(cpu == 0);
+  assert(cpu == Cpu_number::boot_cpu());
 }
index f98e051281e6a879e321fdf86ab50990925913be..7c9b839a5608d38248c49ddc338350e713ebf484 100644 (file)
@@ -1,5 +1,7 @@
 INTERFACE:
 
+#include <types.h>
+
 /**
  * Encapsulation of the platforms interrupt controller
  */
@@ -71,5 +73,5 @@ public:
    * @param irq IRQ.
    * @param cpu Logical CPU.
    */
-  static void set_cpu(unsigned irq, unsigned cpu);
+  static void set_cpu(unsigned irq, Cpu_number cpu);
 };
index 9780160376188fef0139575f8f938b72c7c61272..155fcb7ddf017122426863fa7fc07ab7aa6ad189 100644 (file)
@@ -1,46 +1,43 @@
 INTERFACE:
 
+#include "types.h"
+
 class Platform_control
 {
 public:
-  static void init(unsigned);
+  static void init(Cpu_number);
   static bool cpu_offline_available();
-  static int resume_cpu(unsigned cpu);
-  static int suspend_cpu(unsigned cpu);
+  static int resume_cpu(Cpu_number cpu);
+  static int suspend_cpu(Cpu_number cpu);
   static int system_suspend();
 };
 
 // ------------------------------------------------------------------------
-IMPLEMENTATION [!cpu_suspend]:
+IMPLEMENTATION:
 
 #include "l4_types.h"
 
-IMPLEMENT inline
+IMPLEMENT_DEFAULT inline
 void
-Platform_control::init(unsigned)
+Platform_control::init(Cpu_number)
 {}
 
-IMPLEMENT inline NEEDS["l4_types.h"]
+IMPLEMENT_DEFAULT inline NEEDS["l4_types.h"]
 int
 Platform_control::system_suspend()
 { return -L4_err::EBusy; }
 
-// ------------------------------------------------------------------------
-IMPLEMENTATION [!cpu_suspend || !mp]:
-
-#include "l4_types.h"
-
-IMPLEMENT inline
+IMPLEMENT_DEFAULT inline
 bool
 Platform_control::cpu_offline_available()
 { return false; }
 
-IMPLEMENT inline NEEDS["l4_types.h"]
+IMPLEMENT_DEFAULT inline NEEDS["l4_types.h"]
 int
-Platform_control::suspend_cpu(unsigned)
+Platform_control::suspend_cpu(Cpu_number)
 { return -L4_err::ENodev; }
 
-IMPLEMENT inline NEEDS["l4_types.h"]
+IMPLEMENT_DEFAULT inline NEEDS["l4_types.h"]
 int
-Platform_control::resume_cpu(unsigned)
+Platform_control::resume_cpu(Cpu_number)
 { return -L4_err::ENodev; }
index fe34754798ec350bbf6b2b9e464fa5b3aa8cd8ce..b53b09bab6220312a31dec950f382f64ad682dc2 100644 (file)
@@ -16,7 +16,7 @@ class Pfc : public Kobject_h<Pfc>
 
   Pfc() { initial_kobjects.register_obj(this, 8); }
 
-  L4_msg_tag sys_suspend_cpu(unsigned char /*rights*/, Syscall_frame *f,
+  L4_msg_tag sys_suspend_cpu(L4_fpage::Rights, Syscall_frame *f,
                              Utcb const *utcb)
   {
     if (!Platform_control::cpu_offline_available())
@@ -25,9 +25,9 @@ class Pfc : public Kobject_h<Pfc>
     if (f->tag().words() < 2)
       return commit_result(-L4_err::EInval);
 
-    unsigned cpu = utcb->values[1];
+    Cpu_number cpu = Cpu_number(utcb->values[1]);
 
-    if (cpu >= Config::Max_num_cpus || !Per_cpu_data::valid(cpu))
+    if (cpu >= Cpu::invalid() || !Per_cpu_data::valid(cpu))
       return commit_result(-L4_err::EInval);
 
     if (!Cpu::online(cpu))
@@ -38,7 +38,7 @@ class Pfc : public Kobject_h<Pfc>
   }
 
   L4_msg_tag
-  sys_resume_cpu(unsigned char /*rights*/, Syscall_frame *f,
+  sys_resume_cpu(L4_fpage::Rights, Syscall_frame *f,
                  Utcb const *utcb)
   {
     if (!Platform_control::cpu_offline_available())
@@ -47,9 +47,9 @@ class Pfc : public Kobject_h<Pfc>
     if (f->tag().words() < 2)
       return commit_result(-L4_err::EInval);
 
-    unsigned cpu = utcb->values[1];
+    Cpu_number cpu = Cpu_number(utcb->values[1]);
 
-    if (cpu >= Config::Max_num_cpus || !Per_cpu_data::valid(cpu))
+    if (cpu >= Cpu::invalid() || !Per_cpu_data::valid(cpu))
       return commit_result(-L4_err::EInval);
 
     if (Cpu::online(cpu))
@@ -60,10 +60,10 @@ class Pfc : public Kobject_h<Pfc>
   }
 
   L4_msg_tag
-  sys_suspend_system(unsigned char, Syscall_frame *, Utcb const *)
+  sys_suspend_system(L4_fpage::Rights, Syscall_frame *, Utcb const *)
   {
     unsigned c = 0;
-    for (unsigned cpu = 0; cpu < Config::Max_num_cpus; ++cpu)
+    for (Cpu_number cpu = Cpu_number::first(); cpu < Cpu::invalid(); ++cpu)
       c += Cpu::online(cpu) ? 1 : 0;
     if (c > 1)
       return commit_result(-L4_err::EBusy);
@@ -74,7 +74,7 @@ class Pfc : public Kobject_h<Pfc>
   static Pfc pfc;
 
 public:
-  L4_msg_tag kinvoke(L4_obj_ref, Mword rights, Syscall_frame *f,
+  L4_msg_tag kinvoke(L4_obj_ref, L4_fpage::Rights rights, Syscall_frame *f,
                      Utcb const *iutcb, Utcb *)
   {
 #if 0
index d98dc0a8d35654d5f1f61222219a89e6a3879999..3a4fd32d511cd5493befc8b8a82207bc79f1a0c7 100644 (file)
@@ -29,6 +29,7 @@ PUBLIC static
 Of_device *
 Boot_info::get_device(const char *name, const char *type)
 {
+  (void)name; (void)type;
 #if 0
   Of_device *dev = reinterpret_cast<Of_device *>(_mbi.drives_addr);
 
index a0df113279a9b7879995afb391b633e3fbdb0253..05e4c2f68534c131543c4fd660ba4aabe2943eb8 100644 (file)
@@ -84,7 +84,7 @@ class Chip : public Irq_chip_gen
 public:
   Chip() : Irq_chip_gen(Pic::IRQ_MAX) {}
   unsigned set_mode(Mword, unsigned) { return Irq_base::Trigger_level; }
-  void set_cpu(Mword, unsigned) {}
+  void set_cpu(Mword, Cpu_number) {}
 };
 
 PUBLIC
index a0b89c5bf92308cb1c6257cfe44ddba4924680e2..73c5006f21fce16a0763feda5e04e3df46043cc1 100644 (file)
@@ -12,11 +12,11 @@ public:
   static Per_cpu<Cpu> cpus;
   static Cpu *boot_cpu() { return _boot_cpu; }
 
-  Cpu(unsigned cpu) { set_id(cpu); }
+  Cpu(Cpu_number cpu) { set_id(cpu); }
 
 private:
   static Cpu *_boot_cpu;
-  unsigned _phys_id;
+  Cpu_phys_id _phys_id;
   static unsigned long _ns_per_cycle;
 
 };
@@ -44,6 +44,8 @@ DEFINE_PER_CPU Per_cpu<Cpu> Cpu::cpus(true);
 Cpu *Cpu::_boot_cpu;
 unsigned long Cpu::_ns_per_cycle;
 
+PUBLIC static inline unsigned Cpu::phys_bits() { return 32; }
+
 IMPLEMENT
 void
 Cpu::init(bool is_boot_cpu)
@@ -53,13 +55,13 @@ Cpu::init(bool is_boot_cpu)
       _boot_cpu = this;
       set_online(1);
     }
-  _phys_id = 0; //Proc::cpu_id();
+  _phys_id = Cpu_phys_id(0); //Proc::cpu_id();
   _ns_per_cycle = 1000000000 / Boot_info::get_time_base();
   printf("Timebase: %lu\n", Boot_info::get_time_base());
 }
 
 PUBLIC inline
-unsigned
+Cpu_phys_id
 Cpu::phys_id() const
 { return _phys_id; }
 
index 8ecbc328af9986946017f52b260502ba04b17f59..ca531acf1976b4f45ae24d0c5aed0a8bf01c7dda 100644 (file)
@@ -6,5 +6,5 @@ IMPLEMENTATION[ppc32]:
 
 PRIVATE inline NEEDS["globals.h"]
 Kernel_task::Kernel_task()
-: Task(Ram_quota::root, Kmem::kdir())
+: Task(Ram_quota::root, Kmem::kdir(), Caps::none())
 {}
index aafbc40be935ebc79e8a814c8bb84b08c765476f..9b3c99cc051c823179ff2f6df509afa98e061bea 100644 (file)
@@ -13,7 +13,6 @@ public:
   static Mword *kernel_sp();
   static void kernel_sp(Mword *);
 
-  static Mword is_tcb_page_fault( Mword pfa, Mword error );
   static Mword is_kmem_page_fault( Mword pfa, Mword error );
   static Mword is_io_bitmap_page_fault( Mword pfa );
 
@@ -26,7 +25,6 @@ private:
 //---------------------------------------------------------------------------
 IMPLEMENTATION [ppc32]:
 
-#include "mem_layout.h"
 #include "paging.h"
 #include "panic.h"
 
@@ -50,13 +48,6 @@ IMPLEMENT inline
 void Kmem::kernel_sp(Mword *sp)
 { _sp = sp; }
 
-PUBLIC static inline NEEDS["mem_layout.h", "panic.h"]
-Address Kmem::ipc_window(unsigned /*win*/)
-{
-  panic("%s not implemented", __PRETTY_FUNCTION__);
-  return 0;
-}
-
 IMPLEMENT inline NEEDS["paging.h"]
 Address Kmem::virt_to_phys(const void *addr)
 {
@@ -64,11 +55,6 @@ Address Kmem::virt_to_phys(const void *addr)
   return kdir()->virt_to_phys(a);
 }
 
-//------------------------------------------------------------------------------
-/*
- * dummy implementations 
- */
-
 IMPLEMENT inline
 Mword Kmem::is_kmem_page_fault(Mword pfa, Mword /*error*/)
 {
@@ -76,13 +62,16 @@ Mword Kmem::is_kmem_page_fault(Mword pfa, Mword /*error*/)
 }
 
 IMPLEMENT inline
-Mword Kmem::is_tcb_page_fault(Mword /*pfa*/, Mword /*error*/ )
+Mword Kmem::is_io_bitmap_page_fault( Mword /*pfa*/ )
 {
   return 0;
 }
 
-IMPLEMENT inline
-Mword Kmem::is_io_bitmap_page_fault( Mword /*pfa*/ )
+PUBLIC static
+Address
+Kmem::mmio_remap(Address phys)
 {
-  return 0;
+  (void)phys;
+  // implement me
+  return ~0UL;
 }
index a8c199dbbc19b8e43ae0d7018a624ae8a00b90d5..6ebfdfb47a52c7d7ad7f0f0893a9b8b8cdd501bf 100644 (file)
@@ -36,6 +36,15 @@ Kmem_alloc::Kmem_alloc()
     }
 }
 
+PUBLIC inline //NEEDS["kmem_space.h"]
+Address
+Kmem_alloc::to_phys(void *v) const
+{
+  (void)v;
+  //return Kmem_space::kdir()->virt_to_phys((Address)v);
+  return ~0UL;
+}
+
 //----------------------------------------------------------------------------
 IMPLEMENTATION [ppc32 && debug]:
 
index 483269b723206dbd6d9a3a4ebbc6a0911c39f82a..87407277d9753d50d3252503aec60e20054dd73b 100644 (file)
@@ -7,7 +7,8 @@ INTERFACE[ppc32]:
 EXTENSION class Mem_space
 {
 private:
-  Status v_insert_cache(Pte_base *e, Address virt, size_t size, unsigned page_attribs,
+  Status v_insert_cache(Pte_ptr *e, Address virt, size_t size,
+                        unsigned page_attribs,
                         Dir_type *dir = 0);
   unsigned long v_delete_cache(Pt_entry *e, unsigned page_attribs);
 };
@@ -18,9 +19,10 @@ IMPLEMENTATION[ppc32]:
 
 IMPLEMENT
 Mem_space::Status
-Mem_space::v_insert_cache(Pte_base *e, Address virt, size_t size,
+Mem_space::v_insert_cache(Pte_ptr *e, Address virt, size_t size,
                           unsigned page_attribs, Dir_type *dir = 0)
 {
+#ifdef FIX_THIS
   if(!dir) dir = _dir;
 
   Pdir::Iter i =
@@ -46,16 +48,21 @@ Mem_space::v_insert_cache(Pte_base *e, Address virt, size_t size,
   if(size == Config::SUPERPAGE_SIZE)
     {
       i = dir->walk(Addr(virt), Pdir::Super_level);
-      *i.e = i.e->raw() | Pte_base::Pse_bit;
+      *i.e = i.e->raw() | Pte_ptr::Pse_bit;
     }
 
   return Insert_ok;
+#else
+  (void)e; (void)virt; (void)size; (void)page_attribs; (void)dir;
+  return Insert_err_nomem;
+#endif
 }
 
 IMPLEMENT
 unsigned long
 Mem_space::v_delete_cache(Pt_entry *e, unsigned page_attribs = Page_all_attribs)
 {
+#ifdef FIX_THIS
   unsigned ret;
 
   ret = e->raw() & page_attribs;
@@ -68,4 +75,8 @@ Mem_space::v_delete_cache(Pt_entry *e, unsigned page_attribs = Page_all_attribs)
     e = 0;
 
   return ret;
+#else
+  (void)e; (void)page_attribs;
+  return 0;
+#endif
 }
index 4c0f8d61cfb46ecc54391d6fa7a10df1c798ec3e..45067009b212b8629b68613080aa6b67c620b718 100644 (file)
@@ -171,8 +171,10 @@ Mem_space::to_htab_fmt(T page_attribs)
 {
   // if page attribs has the writable bit set, make sure to erase the readable
   // bit because 0x11b is read-only on ppc
-  if(page_attribs & Page_writable)
+#ifdef FIX_THIS
+  if (page_attribs & Page_writable)
     page_attribs &= ~Page_user_accessible;
+#endif
 
   return page_attribs & (~Pt_entry::Valid & ~Pt_entry::Htab_entry);
 }
@@ -184,23 +186,28 @@ Mem_space::to_kernel_fmt(T page_attribs, bool is_htab_entry)
 {
   T attribs = page_attribs;
 
+#ifdef FIX_THIS
   attribs &= Page_all_attribs;
 
   if(!is_htab_entry)
-    attribs |=  Pte_base::Valid;
+    attribs |=  Pte_ptr::Valid;
 
   if(attribs & Page_writable)
     attribs |= Page_user_accessible;
+#endif
 
   return attribs;
 }
 
 PRIVATE
 Mem_space::Status
-Mem_space::pte_attrib_upgrade(Pte_base *e, size_t size, unsigned page_attribs)
+Mem_space::pte_attrib_upgrade(Pte_ptr *e, size_t size, unsigned page_attribs)
 {
-  Pte_base *e2 = e;
+  (void)e; (void)size; (void)page_attribs;
+
   Status ret = Insert_warn_attrib_upgrade;
+#ifdef FIX_THIS
+  Pte_ptr *e2 = e;
   page_attribs = to_htab_fmt(page_attribs);
 
   for(Address offs = 0; offs < (size / Config::PAGE_SIZE) * sizeof(Mword);
@@ -224,6 +231,7 @@ Mem_space::pte_attrib_upgrade(Pte_base *e, size_t size, unsigned page_attribs)
       else
         ret = pte_attrib_upgrade(e2->raw(), page_attribs);
     }
+#endif
 
   return ret;
 }
@@ -315,6 +323,8 @@ IMPLEMENT
 unsigned long
 Mem_space::v_delete_htab(Address pte_addr, unsigned page_attribs = Page_all_attribs)
 {
+  (void)pte_addr; (void)page_attribs;
+#ifdef FIX_THIS
   auto guard = lock_guard(cpu_lock);
   unsigned long ret;
   Pte_htab *pte_phys = Pte_htab::addr_to_pte(pte_addr);
@@ -332,6 +342,8 @@ Mem_space::v_delete_htab(Address pte_addr, unsigned page_attribs = Page_all_attr
   Mem_unit::tlb_flush(pte_phys->pte_to_ea());
   Mem_unit::sync();
   return ret;
+#endif
+  return 0;
 }
 
 IMPLEMENT inline NEEDS["kmem.h"]
index b3a81baaabf14f9b9be08b86ce5805ff7cb7b287..f0297de52c9067471d6cda9f04dc396903c09065 100644 (file)
@@ -27,20 +27,20 @@ public:
     {
       Page_no_attribs = 0,
       /// Page is writable.
-      Page_writable = Pt_entry::Writable,
+      //Page_writable = Pt_entry::Writable,
       Page_cacheable = 0,
       /// Page is noncacheable.
-      Page_noncacheable = Pt_entry::Noncacheable | Pt_entry::Write_through,
+      //Page_noncacheable = Pt_entry::Noncacheable | Pt_entry::Write_through,
       /// it's a user page.
-      Page_user_accessible = Pt_entry::User,
+      //Page_user_accessible = Pt_entry::User,
       /// Page has been referenced
-      Page_referenced = Pt_entry::Referenced,
+      //Page_referenced = Pt_entry::Referenced,
       /// Page is dirty
-      Page_dirty = Pt_entry::Dirty,
-      Page_references = Page_referenced | Page_dirty,
+      //Page_dirty = Pt_entry::Dirty,
+      //Page_references = Page_referenced | Page_dirty,
       /// A mask which contains all mask bits
-      Page_all_attribs = Page_writable | Page_noncacheable |
-                        Page_user_accessible | Page_referenced | Page_dirty,
+      //Page_all_attribs = Page_writable | Page_noncacheable |
+//                      Page_user_accessible | Page_referenced | Page_dirty,
     };
 
   // Mapping utilities
@@ -49,7 +49,6 @@ public:
     Need_insert_tlb_flush = 0,
     Map_page_size = Config::PAGE_SIZE,
     Page_shift = Config::PAGE_SHIFT,
-    Map_superpage_size = Config::SUPERPAGE_SIZE,
     Map_max_address = Mem_layout::User_max,
     Whole_space = MWORD_BITS,
     Identity_map = 0,
@@ -96,7 +95,7 @@ Mem_space::initialize()
     return false;
 
   _dir = static_cast<Dir_type*>(b);
-  _dir->clear();       // initialize to zero
+  //check//_dir->clear();      // initialize to zero
   return true; // success
 }
 
@@ -111,9 +110,10 @@ Mem_space::Mem_space(Ram_quota *q, Dir_type* pdir)
   : _quota(q), _dir(pdir)
 {
   _kernel_space = this;
-  _current.cpu(0) = this;
+  _current.cpu(Cpu_number::boot_cpu()) = this;
 }
 
+#if 0
 //XXX cbass: check;
 PUBLIC static inline
 Mword
@@ -127,15 +127,17 @@ Mem_space::xlate_flush(unsigned char rights)
 
   return a;
 }
+#endif
 
 //XXX cbass: check;
 PUBLIC static inline
-Mword
-Mem_space::is_full_flush(unsigned char rights)
+L4_fpage::Rights
+Mem_space::is_full_flush(L4_fpage::Rights rights)
 {
-  return rights & L4_fpage::RX;
+  return rights & L4_fpage::Rights::R(); // CHECK!
 }
 
+#if 0
 PUBLIC static inline
 unsigned char
 Mem_space::xlate_flush_result(Mword attribs)
@@ -149,6 +151,7 @@ Mem_space::xlate_flush_result(Mword attribs)
 
   return r;
 }
+#endif
 
 PUBLIC inline NEEDS["cpu.h"]
 static bool
@@ -168,7 +171,7 @@ Mem_space::tlb_flush(bool = false)
 
 PUBLIC inline
 bool
-Mem_space::set_attributes(Address virt, unsigned page_attribs)
+Mem_space::set_attributes(Virt_addr virt, Attr page_attribs)
 {
 /*
   Pdir::Iter i = _dir->walk(virt);
@@ -207,7 +210,7 @@ Mem_space::dir_shutdown()
   // except the ones in kernel space which are always shared
   /*
   _dir->alloc_cast<Mem_space_q_alloc>()
-    ->destroy(0, Kmem::mem_user_max, Pdir::Depth - 1,
+    ->destroy(0, Kmem::mem_user_max, 0, Pdir::Depth,
               Mem_space_q_alloc(_quota, Kmem_alloc::allocator()));
 */
   NOT_IMPL_PANIC;
@@ -215,7 +218,7 @@ Mem_space::dir_shutdown()
 
 IMPLEMENT inline
 Mem_space *
-Mem_space::current_mem_space(unsigned cpu) /// XXX: do not fix, deprecated, remove!
+Mem_space::current_mem_space(Cpu_number cpu) /// XXX: do not fix, deprecated, remove!
 {
   return _current.cpu(cpu);
 }
@@ -240,34 +243,40 @@ Mem_space::current_mem_space(unsigned cpu) /// XXX: do not fix, deprecated, remo
  */
 IMPLEMENT inline
 Mem_space::Status
-Mem_space::v_insert(Phys_addr phys, Vaddr virt, Vsize size,
-                   unsigned page_attribs, bool /*upgrade_ignore_size*/)
+Mem_space::v_insert(Phys_addr phys, Vaddr virt, Page_order size,
+                   Attr page_attribs)
 {
-  assert(size == Size(Config::PAGE_SIZE) 
-         || size == Size(Config::SUPERPAGE_SIZE));
+  //assert(size == Size(Config::PAGE_SIZE)
+  //       || size == Size(Config::SUPERPAGE_SIZE));
 /*
-  printf("v_insert: phys %08lx virt %08lx (%s) %p\n", phys, virt, 
+  printf("v_insert: phys %08lx virt %08lx (%s) %p\n", phys, virt,
          page_attribs & Page_writable?"rw":"ro", this);*/
-  Pte_base e(phys.value());
+#ifdef FIX_THIS
+  Pte_ptr e(phys.value());
   unsigned attribs = e.to_htab_entry(page_attribs);
 
-  Status status = v_insert_cache(&e, Virt_addr(virt).value(),
-                                 Virt_size(size).value(), attribs);
+  Status status = v_insert_cache(&e, cxx::int_value<Vaddr>(virt),
+                                 size, attribs);
   return status;
+#else
+  (void)phys; (void)virt; (void)size; (void)page_attribs;
+  return Insert_err_nomem;
+#endif
 }
 
 IMPLEMENT
 bool
 Mem_space::try_htab_fault(Address virt)
 {
-  bool super;
-  Evict evict;
-  Address pte_ptr, phys;
+  //bool super;
+  //Evict evict;
+  //Address pte_ptr, phys;
   Dir_type *dir = _dir;
 
   if(virt >= Mem_layout::User_max)
     dir = Kmem::kdir();
 
+#ifdef FIX_THIS
   Pdir::Iter i = dir->walk(Addr(virt), Pdir::Super_level);
 
   if(!i.e->valid())
@@ -318,6 +327,7 @@ Mem_space::try_htab_fault(Address virt)
   status  = v_insert_cache(&e, virt, Config::PAGE_SIZE, 0, dir);
 
   if(EXPECT_FALSE(status != Insert_ok))
+#endif
     return false;
 
   return true;
@@ -369,12 +379,15 @@ Mem_space::pmem_to_phys (Address virt) const
  */
 IMPLEMENT
 bool
-Mem_space::v_lookup(Vaddr virt, Phys_addr *phys = 0, Size *size = 0,
-                   unsigned *page_attribs = 0)
+Mem_space::v_lookup(Vaddr virt, Phys_addr *phys, Page_order *order,
+                    Attr *page_attribs)
 {
+  (void)virt; (void)phys; (void)order; (void)page_attribs;
+#ifdef FIX_THIS
   Pdir::Iter i = _dir->walk(virt, Pdir::Super_level);
 
-  if(size) *size = Size(1UL << i.shift());
+  if (size)
+    *size = Size(1UL << i.shift());
 
   if(!i.e->valid())
     return false;
@@ -388,18 +401,22 @@ Mem_space::v_lookup(Vaddr virt, Phys_addr *phys = 0, Size *size = 0,
   if(!i.e->valid())
     return false;
 
-  if(size) *size = Size(1UL << i.shift());
+  if (size) *size = Size(1UL << i.shift());
 
-  if(phys || page_attribs)
+  if (phys || page_attribs)
     {
       Address addr = phys->value();
       Pte_htab::pte_lookup(i.e, &addr, page_attribs);
       *phys = Phys_addr(addr);
     }
-  if(page_attribs)
+
+  if (page_attribs)
     *page_attribs = to_kernel_fmt(*page_attribs, i.e->is_htab_entry());
 
   return true;
+#else
+  return false;
+#endif
 }
 
 /** Delete page-table entries, or some of the entries' attributes.  This
@@ -412,10 +429,11 @@ Mem_space::v_lookup(Vaddr virt, Phys_addr *phys = 0, Size *size = 0,
             case of errors, ~Page_all_attribs is additionally bit-ORed in.
  */
 IMPLEMENT
-unsigned long
-Mem_space::v_delete(Vaddr virt, Vsize size,
-                   unsigned long page_attribs = Page_all_attribs)
+L4_fpage::Rights
+Mem_space::v_delete(Vaddr virt, Page_order size,
+                   L4_fpage::Rights page_attribs)
 {
+#ifdef FIX_THIS
   unsigned ret = 0;
   // delete pages from page tables
   //printf("v_delete: %lx dir: %p\n", virt, _dir);
@@ -457,9 +475,25 @@ Mem_space::v_delete(Vaddr virt, Vsize size,
   i.e = 0;
 
   return ret;
+#else
+  (void)virt; (void)size; (void)page_attribs;
+  return page_attribs;
+#endif
 }
 
 PUBLIC static inline
 Page_number
 Mem_space::canonize(Page_number v)
 { return v; }
+
+IMPLEMENT inline
+void
+Mem_space::v_set_access_flags(Vaddr, L4_fpage::Rights)
+{}
+
+PUBLIC static inline NEEDS["mem_unit.h"]
+void
+Mem_space::tlb_flush_spaces(bool all, Mem_space *s1, Mem_space *s2)
+{
+  (void)all; (void)s1; (void)s2;
+}
index 2a642691c3edaaaaffbfdbe38789f90954a58b1f..30a69064b914ee0f313e908a2a61527da03aab5d 100644 (file)
@@ -3,6 +3,7 @@ INTERFACE[ppc32]:
 #include "types.h"
 
 class PF {};
+class Page {};
 
 //------------------------------------------------------------------------------
 INTERFACE[ppc32]:
@@ -14,10 +15,9 @@ INTERFACE[ppc32]:
 
 class Paging {};
 
-class Pte_base
+class Pte_ptr
 {
-  public:
-    typedef Mword Raw;
+public:
   enum
   {
     Super_level   = 0,
@@ -37,84 +37,106 @@ class Pte_base
 //    L4_global     = 0x00000200, ///< pinned in the TLB
   };
 
-    Mword addr() const { return _raw & Pfn;}
-    bool is_super_page() const { return _raw & Pse_bit; }
-  protected:
-    Raw _raw;
+  Pte_ptr() = default;
+  Pte_ptr(void *p, unsigned char level) : pte((Mword*)p), level(level) {}
+
+  bool is_valid() const { return *pte & Valid; }
+  void clear() { *pte = 0; }
+  bool is_leaf() const
+  {
+    return !is_super_page(); // CHECK!
+  }
+
+  Mword next_level() const
+  {
+    return 0; // FIX
+  }
+
+  void set_next_level(Mword phys)
+  {
+    (void)phys; // FIX
+  }
+
+  Mword addr() const { return *pte & Pfn;}
+  bool is_super_page() const { return *pte & Pse_bit; }
+  Mword raw() const { return *pte; }
+
+protected:
+  Mword *pte;
+  unsigned char level;
 };
 
-class Pt_entry : public Pte_base
+class Pt_entry : public Pte_ptr
 {
 public:
   Mword leaf() const { return true; }
   void set(Address p, bool intermed, bool /*present*/, unsigned long attrs = 0)
   {
-    _raw = (p & Pfn)
+    *pte = (p & Pfn)
       | (intermed ? (Writable | User) : 0) | attrs;
-    _raw &= intermed ? (Mword)Cacheable_mask : ~0;
+    *pte &= intermed ? (Mword)Cacheable_mask : ~0;
   }
 };
 
-class Pd_entry : public Pte_base
+class Pd_entry : public Pte_ptr
 {
 public:
   Mword leaf() const { return false; }
   void set(Address p, bool intermed, bool present, unsigned long attrs = 0)
   {
-    _raw = (p & Pfn) | (present ? (Mword)Valid : 0)
+    *pte = (p & Pfn) | (present ? (Mword)Valid : 0)
       | (intermed ? (Writable | User) : Pse_bit) | attrs;
-    _raw &= intermed ? (Mword)Cacheable_mask : ~0;
+    *pte &= intermed ? (Mword)Cacheable_mask : ~0;
   }
 };
 
-class Pte_htab {
-  public:
-    Pte_htab(Mword, Mword, Mword);
-
-    union {
-      struct {
-       Mword valid : 1; // valid bit
-       Mword vsid  :24; // address-space id
-       Mword h     : 1; // hash-function bit
-       Mword api   : 6; // abbreviated-page index
-       Mword rpn   :20; // physical-page numer
-       Mword zero  : 3; // reserved
-       Mword r     : 1; // referenced bit
-       Mword c     : 1; // changed bit
-       Mword wimg  : 4; // cache controls
-       Mword zero1 : 1; // reserved
-       Mword pp    : 2; // protection bits
-      } pte;
-      struct {
-       Unsigned32 raw0;
-       Unsigned32 raw1;
-      } raw;
-    };
-
-    bool inline valid()
-    { return this->pte.valid; }
-
-    bool inline v_equal(Pte_htab *entry) 
-    { return this->raw.raw0 == entry->raw.raw0; }
-
-    bool inline p_equal(Pte_htab *entry)
-    { return this->raw.raw1 == entry->raw.raw1; }
-
-    Address inline virt()
-    { return this->raw.raw0; }
-
-    Address inline phys()
-    { return this->raw.raw1; }
+class Pte_htab
+{
+public:
+  Pte_htab(Mword, Mword, Mword);
+
+  union {
+    struct {
+      Mword valid : 1; // valid bit
+      Mword vsid  :24; // address-space id
+      Mword h     : 1; // hash-function bit
+      Mword api   : 6; // abbreviated-page index
+      Mword rpn   :20; // physical-page numer
+      Mword zero  : 3; // reserved
+      Mword r     : 1; // referenced bit
+      Mword c     : 1; // changed bit
+      Mword wimg  : 4; // cache controls
+      Mword zero1 : 1; // reserved
+      Mword pp    : 2; // protection bits
+    } pte;
+    struct {
+      Unsigned32 raw0;
+      Unsigned32 raw1;
+    } raw;
+  };
+
+  bool inline valid()
+  { return this->pte.valid; }
+
+  bool inline v_equal(Pte_htab *entry)
+  { return this->raw.raw0 == entry->raw.raw0; }
+
+  bool inline p_equal(Pte_htab *entry)
+  { return this->raw.raw1 == entry->raw.raw1; }
+
+  Address inline virt()
+  { return this->raw.raw0; }
+
+  Address inline phys()
+  { return this->raw.raw1; }
 };
 
-namespace Page
+EXTENSION class Page
 {
+public:
   typedef Unsigned32 Attribs;
-  enum Attribs_enum 
+  enum Attribs_enum
   {
-    KERN_RW      = 0x00000000,
-    USER_RO      = 0x00000001,
-    USER_RW      = 0x00000002,
     Cache_mask   = 0x00000078,
     CACHEABLE    = 0x00000000,
     NONCACHEABLE = 0x00000040,
@@ -123,8 +145,8 @@ namespace Page
 };
 
 
-typedef Ptab::List< Ptab::Traits<Pd_entry, 22, 10, true>,
-                    Ptab::Traits<Pt_entry, 12, 10, true> > Ptab_traits;
+typedef Ptab::List< Ptab::Traits<Unsigned32, 22, 10, true>,
+                    Ptab::Traits<Unsigned32, 12, 10, true> > Ptab_traits;
 
 typedef Ptab::Shift<Ptab_traits, Virt_addr::Shift>::List Ptab_traits_vpn;
 typedef Ptab::Page_addr_wrap<Page_number, Virt_addr::Shift> Ptab_va_vpn;
@@ -185,17 +207,12 @@ Mword PF::addr_to_msgword0(Address pfa, Mword error)
 
 //---------------------------------------------------------------------------
 
-PUBLIC
-Pte_base::Pte_base(Mword raw) : _raw(raw) {}
-
-PUBLIC
-Pte_base::Pte_base() {}
-
+#if 0
 PUBLIC inline
 Pte_base &
 Pte_base::operator = (Pte_base const &other)
 {
-  _raw = other.raw();
+  *pte = other.raw();
   return *this;
 }
 
@@ -203,7 +220,7 @@ PUBLIC inline
 Pte_base &
 Pte_base::operator = (Mword raw)
 {
-  _raw = raw;
+  *pte = raw;
   return *this;
 }
 
@@ -211,79 +228,71 @@ PUBLIC inline
 Mword
 Pte_base::raw() const
 {
-  return _raw;
-}
-
-PUBLIC inline
-void
-Pte_base::add_attr(Mword attr)
-{
-  _raw |= attr;
+  return *pte;
 }
+#endif
 
 PUBLIC inline
 void
-Pte_base::del_attr(Mword attr)
+Pte_ptr::add_attr(Page::Attr attr)
 {
-  _raw &= ~attr;
+  (void)attr;
+  // FIX
+  //*pte |= attr;
 }
 
-PUBLIC inline
-void
-Pte_base::clear()
-{ _raw = 0; }
-
-PUBLIC inline
-int
-Pte_base::valid() const
-{
-  return 
-    _raw & Valid || is_htab_entry();
-}
+//PUBLIC inline
+//void
+//Pte_base::del_attr(Mword attr)
+//{
+//*pte &= ~attr;
+//}
 
+#if 0
 PUBLIC inline
 int
 Pte_base::writable() const
 {
-  return _raw & Writable;
+  return *pte & Writable;
 }
+#endif
 
 PUBLIC inline
 bool
-Pte_base::is_htab_entry() const
+Pte_ptr::is_htab_entry() const
 {
-  return ((_raw & Htab_entry) && !(_raw & Valid));
+  return ((*pte & Htab_entry) && !(*pte & Valid));
 }
 
 PUBLIC inline
 unsigned
-Pte_base::to_htab_entry(unsigned page_attribs = 0)
+Pte_ptr::to_htab_entry(unsigned page_attribs = 0)
 {
-  _raw |= Htab_entry;
-  _raw &= ~Valid;
+  *pte |= Htab_entry;
+  *pte &= ~Valid;
   return page_attribs & ~Valid;
 }
 
 PUBLIC inline
 bool
-Pte_base::is_htab_ptr() const
+Pte_ptr::is_htab_ptr() const
 {
-  return (_raw & Valid);
+  return (*pte & Valid);
 }
 
 PUBLIC inline
 void
-Pte_base::to_htab_ptr()
+Pte_ptr::to_htab_ptr()
 {
-  _raw |= Valid;
+  *pte |= Valid;
 }
 
-PUBLIC inline
-Address
-Pt_entry::pfn() const
-{
-  return _raw & Pfn;
-}
+//PUBLIC inline
+//Address
+//Pt_entry::pfn() const
+//{
+  //return *pte & Pfn;
+//}
 
 //------------------------------------------------------------------------------
 /*
@@ -332,19 +341,19 @@ Pte_htab::pte_to_ea()
 
 
 PUBLIC static inline
-Pte_htab * 
+Pte_htab *
 Pte_htab::addr_to_pte(Address pte_addr)
 {
-  return reinterpret_cast<Pte_htab*>(pte_addr & ~Pte_base::Valid);
+  return reinterpret_cast<Pte_htab*>(pte_addr & ~Pte_ptr::Valid);
 }
 
 PUBLIC static inline
 Address
-Pte_htab::pte_to_addr(Pte_base *e)
+Pte_htab::pte_to_addr(Pte_ptr *e)
 {
   Address raw;
 
-  if(e->is_htab_entry())
+  if (e->is_htab_entry())
     raw = e->raw();
   else
     {
@@ -357,7 +366,7 @@ Pte_htab::pte_to_addr(Pte_base *e)
 
 PUBLIC static
 bool
-Pte_htab::pte_lookup(Pte_base *e, Address *phys = 0, 
+Pte_htab::pte_lookup(Pte_ptr *e, Address *phys = 0,
                      unsigned *page_attribs = 0)
 {
   auto guard = lock_guard(cpu_lock);
@@ -384,3 +393,23 @@ Pte_htab::pte_lookup(Pte_base *e, Address *phys = 0,
 
   return true;
 }
+
+PUBLIC static inline
+bool
+Pte_ptr::need_cache_write_back(bool current_pt)
+{ return current_pt; }
+
+PUBLIC inline// NEEDS["mem_unit.h"]
+void
+Pte_ptr::write_back_if(bool current_pt, Mword /*asid*/ = 0)
+{
+  (void)current_pt;
+  //  if (current_pt)
+  //        Mem_unit::clean_dcache(pte);
+}
+
+PUBLIC static inline// NEEDS["mem_unit.h"]
+void
+Pte_ptr::write_back(void *start, void *end)
+{ (void)start; (void)end; }
+
index eab74c8cd009e941f8c49e9478e59e9826b1417a..6ace81999dc5971f3aac062df6a8ea73a93f2fbb 100644 (file)
@@ -44,14 +44,14 @@ Startup::stage2()
   Per_cpu_data::init_ctors();
 
   // not really necessary for uni processor
-  Per_cpu_data_alloc::alloc(0);
-  Per_cpu_data::run_ctors(0);
-  Cpu::cpus.cpu(0).init(true);
+  Per_cpu_data_alloc::alloc(Cpu_number::boot_cpu());
+  Per_cpu_data::run_ctors(Cpu_number::boot_cpu());
+  Cpu::cpus.cpu(Cpu_number::boot_cpu()).init(true);
 
   //idle task
   Kernel_task::init();
   Pic::init();
-  Timer::init(0);
+  Timer::init(Cpu_number::boot_cpu());
   Utcb_init::init();
   puts("Startup::stage2 finished");
 }
index 22126cb2f3e7105bffd2999f29e381265b7fcdbf..82d58e335191c0ba75b6e9db4ce9045d5e68727b 100644 (file)
@@ -40,8 +40,9 @@ Sys_call_page::init()
     *(sys_calls++) = 0x44000002; //sc
 
   Kernel_task::kernel_task()
-    ->set_attributes(Mem_layout::Syscalls,
-                     Mem_space::Page_cacheable | Mem_space::Page_user_accessible);
+    ->set_attributes(Virt_addr(Mem_layout::Syscalls),
+                    Page::Attr(Page::Rights::URX(), Page::Type::Normal(),
+                               Page::Kern::Global()));
 
   //Mem_unit::flush_cache();
 }
index 482095d034f62bc1b797cf328552a8343a642f2b..c9d839bb65c903b6a5ca1641f2055b938e0a74ea 100644 (file)
@@ -53,12 +53,13 @@ IMPLEMENT
 int
 Thread::call_nested_trap_handler(Trap_state *ts)
 {
-  unsigned phys_cpu = Proc::cpu_id();
-  unsigned log_cpu = Cpu::cpus.find_cpu(Cpu::By_phys_id(phys_cpu));
-  if (log_cpu == ~0U)
+  Cpu_phys_id phys_cpu = Proc::cpu_id();
+  Cpu_number log_cpu = Cpu::cpus.find_cpu(Cpu::By_phys_id(phys_cpu));
+  if (log_cpu == Cpu_number::nil())
     {
-      printf("Trap on unknown CPU phys_id=%x\n", phys_cpu);
-      log_cpu = 0;
+      printf("Trap on unknown CPU phys_id=%x\n",
+             cxx::int_value<Cpu_phys_id>(phys_cpu));
+      log_cpu = Cpu_number::boot_cpu();
     }
 
   unsigned long &ntr = nested_trap_recover.cpu(log_cpu);
@@ -71,7 +72,7 @@ Thread::call_nested_trap_handler(Trap_state *ts)
   Mword dummy1, tmp;
   {
     register Mword _ts asm("3") = (Mword)ts;
-    register Mword _lcpu asm("r4") = log_cpu;
+    register Cpu_number _lcpu asm("r4") = log_cpu;
 
     asm volatile(
        " mr    %[origstack], %%r1        \n"
index 91618410beea49216a1caa3f3c245af9d026f9fb..63b0938c4c9f109f87706f11040d839e2fcbfb7a 100644 (file)
@@ -136,11 +136,9 @@ IMPLEMENT inline NEEDS["space.h", <cstdio>, "types.h" ,"config.h"]
 bool Thread::handle_sigma0_page_fault(Address pfa)
 {
   bool ret = (mem_space()->v_insert(Mem_space::Phys_addr(pfa & Config::PAGE_MASK),
-                                   Mem_space::Addr(pfa & Config::PAGE_MASK),
-                                   Mem_space::Size(Config::PAGE_SIZE),
-                                   Mem_space::Page_writable |
-                                   Mem_space::Page_user_accessible |
-                                   Mem_space::Page_cacheable
+                                   Virt_addr(pfa & Config::PAGE_MASK),
+                                   Virt_order(Config::PAGE_SIZE),
+                                   Mem_space::Attr(L4_fpage::Rights::URWX())
                                   )
        != Mem_space::Insert_err_nomem);
 
@@ -339,7 +337,7 @@ Thread::do_trigger_exception(Entry_frame * /*r*/, void * /*ret_handler*/)
 PRIVATE static inline
 bool FIASCO_WARN_RESULT
 Thread::copy_utcb_to_ts(L4_msg_tag const &/*tag*/, Thread * /*snd*/,
-                        Thread * /*rcv*/, unsigned char /*rights*/)
+                        Thread * /*rcv*/, L4_fpage::Rights /*rights*/)
 {
   NOT_IMPL_PANIC;
   return true;
@@ -348,7 +346,7 @@ Thread::copy_utcb_to_ts(L4_msg_tag const &/*tag*/, Thread * /*snd*/,
 PRIVATE static inline
 bool FIASCO_WARN_RESULT
 Thread::copy_ts_to_utcb(L4_msg_tag const &, Thread * /*snd*/, Thread * /*rcv*/,
-                        unsigned char /*rights*/)
+                        L4_fpage::Rights /*rights*/)
 {
   NOT_IMPL_PANIC;
   return true;
index f3904ad0b2e4037a580968d47c31fa9c07bf604a..976ee94707e08f1c976abc1eb5c96c8cf2e01e9c 100644 (file)
@@ -15,7 +15,7 @@ IMPLEMENTATION [ppc32]:
 
 IMPLEMENT inline NEEDS ["decrementer.h", "kip.h", "config.h", <cstdio>]
 void
-Timer::init(unsigned)
+Timer::init(Cpu_number)
 {
   printf("Using PowerPC decrementer for scheduling\n");
 
@@ -70,9 +70,9 @@ Timer::system_clock()
 
 IMPLEMENT inline NEEDS ["decrementer.h", "config.h", "kip.h"]
 void
-Timer::update_system_clock(unsigned cpu)
+Timer::update_system_clock(Cpu_number cpu)
 {
-  if (cpu == 0)
+  if (cpu == Cpu_number::boot_cpu())
     {
       Decrementer::d()->set();
       Kip::k()->clock += Config::Scheduler_granularity;
index 020d6c14ebc876a86a5257a6bc15a0c42ae34393..93b76697ee3805f425b4818f9874664f95e7d0ca 100644 (file)
@@ -17,7 +17,7 @@ class Trap_state : public Trap_state_regs, public Syscall_frame,
                    public Return_frame
 {
 public:
-  typedef int (*Handler)(Trap_state*, unsigned cpu);
+  typedef int (*Handler)(Trap_state*, Cpu_number::Value cpu);
   bool exclude_logging() { return false; }
 };
 
index ea47b443b15326c0024455954a0fc74016e0fb39..73958a84c1d791112ddcda8626feccc1e4b10b64 100644 (file)
@@ -1,8 +1,8 @@
 INTERFACE:
 
 #include <cassert>
-#include <dlist>
-#include <hlist>
+#include <cxx/dlist>
+#include <cxx/hlist>
 #include "member_offs.h"
 #include "spin_lock.h"
 #include "types.h"
index 2053ef1f333b0f7996012c6d670845e734c16320..3d5f04aee6eea5687a427461dce56aea4b8a9691 100644 (file)
@@ -1,6 +1,7 @@
 INTERFACE:
 
 #include "mem_layout.h"
+//#include <cstdio>
 
 namespace Ptab
 {
@@ -10,33 +11,37 @@ namespace Ptab
     static void *alloc(unsigned long) { return 0; }
     static void free(void *) {}
     static bool valid() { return false; }
+    static unsigned to_phys(void *) { return 0; }
   };
 
   template< typename _Head, typename _Tail >
-  class List
+  struct List
   {
-  public:
     typedef _Head Head;
     typedef _Tail Tail;
   };
 
+  template< typename ...T >
+  struct Tupel;
+
+  template< typename T >
+  struct Tupel<T>;
+
+  template< typename H, typename T >
+  struct Tupel<H, T> { typedef Ptab::List<H, T> List; };
+
+  template<typename T1, typename T2, typename T3, typename ...X>
+  struct Tupel<T1, T2, T3, X...>
+  { typedef Ptab::List<T1, typename Tupel<T2, T3, X...>::List > List; };
 
   template< typename _T, unsigned _Level >
-  class Level
+  struct Level
   {
-  public:
     typedef _T Traits;
 
     static unsigned shift(unsigned)
     { return Traits::Shift; }
 
-    static Address addr(unsigned, Mword entry)
-    {
-      struct E : public Traits::Entry
-      { E(Mword raw) { Traits::Entry::_raw = raw; } };
-      return E(entry).addr();
-    }
-
     static unsigned size(unsigned)
     { return Traits::Size; }
 
@@ -46,67 +51,67 @@ namespace Ptab
     static Address index(unsigned /*level*/, Address addr)
     { return (addr >> Traits::Shift) & ((1UL << Traits::Size)-1); }
 
+    static unsigned entry_size(unsigned)
+    { return sizeof(typename Traits::Entry); }
+
   };
 
   template< typename _Head, typename _Tail, unsigned _Level >
-  class Level< List<_Head, _Tail>, _Level >
+  struct Level< List<_Head, _Tail>, _Level >
   {
-  public:
-    typedef typename Level<_Tail, _Level - 1>::Traits Traits;
+    typedef Level<_Tail, _Level - 1> Next_level;
+    typedef _Head Traits;
 
     static unsigned shift(unsigned level)
     {
       if (!level)
-       return _Head::Shift;
+        return Traits::Shift;
       else
-       return Level<_Tail, _Level - 1>::shift(level - 1);
+        return Next_level::shift(level - 1);
     }
 
-    static Address addr(unsigned level, Mword entry)
+    static unsigned size(unsigned level)
     {
-      struct E : public Traits::Entry
-      { E(Mword raw) { Traits::Entry::_raw = raw; } };
       if (!level)
-       return E(entry).addr();
+        return Traits::Size;
       else
-        return Level<_Tail, _Level - 1>::addr(level - 1, entry);
+        return Next_level::size(level - 1);
     }
 
-    static unsigned size(unsigned level)
+    static unsigned length(unsigned level)
     {
       if (!level)
-       return _Head::Size;
+       return 1UL << Traits::Size;
       else
-       return Level<_Tail, _Level - 1>::size(level - 1);
+       return Next_level::length(level - 1);
     }
 
-    static unsigned length(unsigned level)
+    static Address index(unsigned level, Address addr)
     {
       if (!level)
-       return 1UL << _Head::Size;
+       return (addr >> Traits::Shift) & ((1UL << Traits::Size)-1);
       else
-       return Level<_Tail, _Level - 1>::length(level - 1);
+       return Next_level::index(level - 1, addr);
     }
 
-    static Address index(unsigned level, Address addr)
+    static unsigned entry_size(unsigned level)
     {
       if (!level)
-       return (addr >> Traits::Shift) & ((1UL << Traits::Size)-1);
+        return sizeof(typename Traits::Entry);
       else
-       return Level<_Tail, _Level - 1>::index(level - 1, addr);
+        return Next_level::entry_size(level - 1);
     }
 
   };
 
   template< typename _Head, typename _Tail>
-  class Level< List<_Head, _Tail>, 0> : public Level<_Head, 0>
+  struct Level< List<_Head, _Tail>, 0> : Level<_Head, 0>
   {
   };
 
   template< typename _Traits >
-  class Entry_vec
+  struct Entry_vec
   {
-  public:
     typedef typename _Traits::Entry Entry;
     enum
     {
@@ -122,7 +127,7 @@ namespace Ptab
     static unsigned idx(Address virt)
     {
       if (Mask)
-       return (virt >> Shift) & ~(~0UL << Size);
+       return cxx::get_lsb(virt >> Shift, (Address)Size);
       else
        return (virt >> Shift);
     }
@@ -130,41 +135,54 @@ namespace Ptab
     Entry &operator [] (unsigned idx) { return _e[idx]; }
     Entry const &operator [] (unsigned idx) const { return _e[idx]; }
 
-    void clear() { for (unsigned i=0; i < Length; ++i) _e[i].clear(); }
+    template<typename PTE_PTR>
+    void clear(unsigned level, bool force_write_back)
+    {
+      for (unsigned i=0; i < Length; ++i)
+        PTE_PTR(&_e[i], level).clear();
+
+      if (force_write_back)
+        PTE_PTR::write_back(&_e[0], &_e[Length]);
+    }
   };
 
 
-  template< typename _Last, typename Iter >
+  template< typename _Last, typename PTE_PTR, int DEPTH = 0 >
   class Walk
   {
   public:
-    enum { Depth = 0 };
+    enum { Max_depth = 0 };
+    enum { Depth = DEPTH };
     typedef _Last Level;
     typedef typename _Last::Entry Entry;
     typedef _Last Traits;
 
   private:
-    typedef Walk<_Last, Iter> This;
+    typedef Walk<_Last, PTE_PTR, DEPTH> This;
     typedef Entry_vec<Level> Vec;
     Vec _e;
 
   public:
-    void clear() { _e.clear(); }
+    void clear(bool force_write_back)
+    { _e.template clear<PTE_PTR>(Depth, force_write_back); }
 
     template< typename _Alloc >
-    Iter walk(Address virt, unsigned, _Alloc const &)
-    { return Iter(&_e[Vec::idx(virt)], Level::Shift); }
+    PTE_PTR walk(Address virt, unsigned, bool, _Alloc const &)
+    { return PTE_PTR(&_e[Vec::idx(virt)], Depth); }
 
-    void unmap(Address &start, unsigned long &size, unsigned)
+    void unmap(Address &start, unsigned long &size, unsigned, bool force_write_back)
     {
       unsigned idx = Vec::idx(start);
       unsigned cnt = size >> Traits::Shift;
       if (cnt + idx > Vec::Length)
-       cnt = Vec::Length - idx;
+        cnt = Vec::Length - idx;
       unsigned const e = idx + cnt;
 
-      for (; idx != e; ++idx)
-       _e[idx].clear();
+      for (unsigned i = idx; i != e; ++i)
+        PTE_PTR(&_e[i], Depth).clear();
+
+      if (force_write_back)
+        PTE_PTR::write_back(&_e[idx], &_e[e]);
 
       start += (unsigned long)cnt << Traits::Shift;
       size  -= (unsigned long)cnt << Traits::Shift;
@@ -172,34 +190,40 @@ namespace Ptab
 
     template< typename _Alloc >
     void map(Address &phys, Address &virt, unsigned long &size,
-       unsigned long attr, unsigned, _Alloc const &)
+             unsigned long attr, unsigned, bool force_write_back,
+             _Alloc const &)
     {
       unsigned idx = Vec::idx(virt);
       unsigned cnt = size >> Traits::Shift;
       if (cnt + idx > Vec::Length)
-       cnt = Vec::Length - idx;
+        cnt = Vec::Length - idx;
       unsigned const e = idx + cnt;
 
-      for (; idx != e; ++idx, phys += (1UL << Traits::Entry::Page_shift))
-       _e[idx].set(phys, false, true, attr);
+      for (unsigned i = idx; i != e; ++i, phys += (1ULL << (Traits::Shift + Traits::Base_shift)))
+        PTE_PTR(&_e[i], Depth).set_page(phys, attr);
+
+      if (force_write_back)
+        PTE_PTR::write_back(&_e[idx], &_e[e]);
+
       virt += (unsigned long)cnt << Traits::Shift;
       size -= (unsigned long)cnt << Traits::Shift;
     }
 
     template< typename _Alloc >
-    void destroy(Address, Address, unsigned, _Alloc const &)
+    void destroy(Address, Address, unsigned, unsigned, _Alloc const &)
     {}
 
     template< typename _Alloc >
     bool sync(Address &l_addr, This const &_r, Address &r_addr,
-       Address &size, unsigned, _Alloc const &)
+              Address &size, unsigned, bool force_write_back, _Alloc const &)
     {
       unsigned count = size >> Traits::Shift;
       unsigned const l = Vec::idx(l_addr);
       unsigned const r = Vec::idx(r_addr);
       unsigned const m = l > r ? l : r;
+
       if (m + count >= Vec::Length)
-       count = Vec::Length - m;
+        count = Vec::Length - m;
 
       Entry *le = &_e[l];
       Entry const *re = &_r._e[r];
@@ -208,9 +232,9 @@ namespace Ptab
 
       for (unsigned n = count; n > 0; --n)
        {
-         if (le[n-1].valid())
+         if (PTE_PTR(&le[n-1], Depth).is_valid())
            need_flush = true;
-
+#if 0
          // This loop seems unnecessary, but remote_update is also used for
          // updating the long IPC window.
          // Now consider following scenario with super pages:
@@ -233,7 +257,12 @@ namespace Ptab
              if (EXPECT_TRUE(le[n - 1].raw() == *rr))
                break;
            }
-       }
+#endif
+          le[n - 1] = re[n - 1];
+        }
+
+      if (force_write_back)
+        PTE_PTR::write_back(&le[0], &le[count]);
 
       l_addr += (unsigned long)count << Traits::Shift;
       r_addr += (unsigned long)count << Traits::Shift;
@@ -244,206 +273,221 @@ namespace Ptab
 
 
 
-  template< typename _Head, typename _Tail, typename Iter >
-  class Walk <List <_Head,_Tail>, Iter >
+  template< typename _Head, typename _Tail, typename PTE_PTR, int DEPTH >
+  class Walk <List <_Head,_Tail>, PTE_PTR, DEPTH >
   {
   public:
-    typedef Walk<_Tail, Iter> Next;
+    typedef Walk<_Tail, PTE_PTR, DEPTH + 1> Next;
     typedef typename Next::Level Level;
     typedef typename _Head::Entry Entry;
     typedef _Head Traits;
 
-    enum { Depth = Next::Depth + 1 };
+    enum { Max_depth = Next::Max_depth + 1 };
+    enum { Depth = DEPTH };
 
   private:
-    typedef Walk<_Head, Iter> This;
-    typedef Walk< List< _Head, _Tail >, Iter> This2;
+    typedef Walk<_Head, PTE_PTR, DEPTH> This;
+    typedef Walk< List< _Head, _Tail >, PTE_PTR, DEPTH> This2;
     typedef Entry_vec<_Head> Vec;
     Vec _e;
 
     template< typename _Alloc >
-    Next *alloc_next(Entry *e, _Alloc const &a)
+    Next *alloc_next(PTE_PTR e, _Alloc const &a, bool force_write_back)
     {
       Next *n = (Next*)a.alloc(sizeof(Next));
       if (EXPECT_FALSE(!n))
-       return 0;
+        return 0;
 
-      n->clear();
-      e->set(Mem_layout::pmem_to_phys(n), true, true);
+      n->clear(force_write_back);
+      e.set_next_level(a.to_phys(n));
+      e.write_back_if(force_write_back);
 
       return n;
     }
 
   public:
-    void clear() { _e.clear(); }
+    void clear(bool force_write_back)
+    { _e.template clear<PTE_PTR>(Depth, force_write_back); }
 
     template< typename _Alloc >
-    Iter walk(Address virt, unsigned level, _Alloc const &alloc)
+    PTE_PTR walk(Address virt, unsigned level, bool force_write_back, _Alloc const &alloc)
     {
-      Entry *e = &_e[Vec::idx(virt)];
-      if (!level)
-       return Iter(e, _Head::Shift);
-      else if (!e->valid())
-       {
-         Next *n;
-         if (alloc.valid() && (n = alloc_next(e, alloc)))
-           return n->walk(virt, level - 1, alloc);
-
-         return Iter(e, _Head::Shift);
-       }
-
+      PTE_PTR e(&_e[Vec::idx(virt)], Depth);
 
-      if (_Head::May_be_leaf && e->leaf())
-       return Iter(e, _Head::Shift);
+      if (!level)
+        return e;
+      else if (!e.is_valid())
+        {
+          Next *n;
+          if (alloc.valid() && (n = alloc_next(e, alloc, force_write_back)))
+            return n->walk(virt, level - 1, force_write_back, alloc);
+          else
+            return e;
+        }
+      else if (e.is_leaf())
+        return e;
       else
-       {
-         Next *n = (Next*)Mem_layout::phys_to_pmem(e->addr());
-         return n->walk(virt, level - 1, alloc);
-       }
+        {
+          Next *n = (Next*)Mem_layout::phys_to_pmem(e.next_level());
+          return n->walk(virt, level - 1, force_write_back, alloc);
+        }
     }
 
-    void unmap(Address &start, unsigned long &size, unsigned level)
+    void unmap(Address &start, unsigned long &size, unsigned level,
+               bool force_write_back)
     {
       if (!level)
-       {
-         reinterpret_cast<This*>(this)->unmap(start, size, 0);
-         return;
-       }
+        {
+          reinterpret_cast<This*>(this)->unmap(start, size, 0,
+                                               force_write_back);
+          return;
+        }
 
       while (size)
-       {
-         Entry *e = &_e[Vec::idx(start)];
+        {
+          PTE_PTR e(&_e[Vec::idx(start)], Depth);
 
-         if (!e->valid() || e->leaf())
-           continue;
+          if (!e.is_valid() || e.is_leaf())
+            continue;
 
-         Next *n = (Next*)Mem_layout::phys_to_pmem(e->addr());
-         n->unmap(start, size, level - 1);
-       }
+          Next *n = (Next*)Mem_layout::phys_to_pmem(e.next_level());
+          n->unmap(start, size, level - 1, force_write_back);
+        }
     }
 
     template< typename _Alloc >
     void map(Address &phys, Address &virt, unsigned long &size,
-       unsigned long attr, unsigned level, _Alloc const &alloc)
+             unsigned long attr, unsigned level, bool force_write_back,
+             _Alloc const &alloc)
     {
       if (!level)
-       {
-         reinterpret_cast<This*>(this)->map(phys, virt, size, attr, 0, alloc);
-         return;
-       }
+        {
+          reinterpret_cast<This*>(this)->map(phys, virt, size, attr, 0,
+                                             force_write_back, alloc);
+          return;
+        }
 
       while (size)
-       {
-         Entry *e = &_e[Vec::idx(virt)];
-         Next *n;
-         if (!e->valid())
-           {
-             if (alloc.valid() && (n = alloc_next(e, alloc)))
-               n->map(phys, virt, size, attr, level - 1, alloc);
-
-             continue;
-           }
-
-         if (_Head::May_be_leaf && e->leaf())
-           continue;
-
-         n = (Next*)Mem_layout::phys_to_pmem(e->addr());
-         n->map(phys, virt, size, attr, level - 1, alloc);
-       }
+        {
+          PTE_PTR e(&_e[Vec::idx(virt)], Depth);
+          Next *n;
+          if (!e.is_valid())
+            {
+              if (alloc.valid() && (n = alloc_next(e, alloc, force_write_back)))
+                n->map(phys, virt, size, attr, level - 1,
+                       force_write_back, alloc);
+
+              continue;
+            }
+
+          if (_Head::May_be_leaf && e.is_leaf())
+            continue;
+
+          n = (Next*)Mem_layout::phys_to_pmem(e.next_level());
+          n->map(phys, virt, size, attr, level - 1, force_write_back, alloc);
+        }
     }
 
     template< typename _Alloc >
-    void destroy(Address start, Address end, unsigned level, _Alloc const &alloc)
+    void destroy(Address start, Address end,
+                 unsigned start_level, unsigned end_level,
+                 _Alloc const &alloc)
     {
-      if (!alloc.valid())
-       return;
+      //printf("destroy: %*.s%lx-%lx lvl=%d:%d depth=%d\n", Depth*2, "            ", start, end, start_level, end_level, Depth);
+      if (!alloc.valid() || Depth >= end_level)
+        return;
 
       unsigned idx_start = Vec::idx(start);
-      unsigned idx_end = Vec::idx(end + (1UL << Traits::Shift) - 1);
-      unsigned idx = idx_start;
-
-      for (; idx < idx_end; ++idx)
-       {
-         Entry *e = &_e[idx];
-         if (!e->valid() || (_Head::May_be_leaf && e->leaf()))
-           continue;
-
-         Next *n = (Next*)Mem_layout::phys_to_pmem(e->addr());
-         if (level)
-           n->destroy(idx > idx_start ? 0 : start,
-                      idx + 1 < idx_end ? 1UL << Next::Traits::Shift : end,
-                      level - 1, alloc);
-
-         alloc.free(n, sizeof(Next));
-       }
+      unsigned idx_end = Vec::idx(end) + 1;
+      //printf("destroy: %*.sidx: %d:%d\n", Depth*2, "            ", idx_start, idx_end);
+
+      for (unsigned idx = idx_start; idx < idx_end; ++idx)
+        {
+          PTE_PTR e(&_e[idx], Depth);
+          if (!e.is_valid() || (_Head::May_be_leaf && e.is_leaf()))
+            continue;
+
+          Next *n = (Next*)Mem_layout::phys_to_pmem(e.next_level());
+          if (Depth < end_level)
+            n->destroy(idx > idx_start ? 0 : start,
+                       idx + 1 < idx_end ? (1UL << Traits::Shift)-1 : end,
+                       start_level, end_level, alloc);
+          if (Depth >= start_level)
+            {
+              //printf("destroy: %*.sfree: %p: %p(%d)\n", Depth*2, "            ", this, n, sizeof(Next));
+              alloc.free(n, sizeof(Next));
+            }
+        }
     }
 
     template< typename _Alloc >
     bool sync(Address &l_a, This2 const &_r, Address &r_a,
-       Address &size, unsigned level, _Alloc const &alloc)
+              Address &size, unsigned level, bool force_write_back,
+              _Alloc const &alloc)
     {
       if (!level)
-       return reinterpret_cast<This*>(this)
-         ->sync(l_a, reinterpret_cast<This const &>(_r), r_a, size, 0, alloc);
+        return reinterpret_cast<This*>(this)
+          ->sync(l_a, reinterpret_cast<This const &>(_r), r_a, size, 0,
+              force_write_back, alloc);
 
       unsigned count = size >> Traits::Shift;
-       {
-         unsigned const lx = Vec::idx(l_a);
-         unsigned const rx = Vec::idx(r_a);
-         unsigned const mx = lx > rx ? lx : rx;
-         if (mx + count >= Vec::Length)
-           count = Vec::Length - mx;
-       }
+        {
+          unsigned const lx = Vec::idx(l_a);
+          unsigned const rx = Vec::idx(r_a);
+          unsigned const mx = lx > rx ? lx : rx;
+          if (mx + count >= Vec::Length)
+            count = Vec::Length - mx;
+        }
 
       bool need_flush = false;
 
       for (unsigned i = count; size && i > 0; --i) //while (size)
-       {
-         Entry *l = &_e[Vec::idx(l_a)];
-         Entry const *r = &_r._e[Vec::idx(r_a)];
-         Next *n = 0;
-         if (!r->valid()
-             || (!l->valid() && (!alloc.valid()
-                 || !(n = alloc_next(l,alloc)))))
-           {
-             l_a += 1UL << Traits::Shift;
-             r_a += 1UL << Traits::Shift;
-             if (size > 1UL << Traits::Shift)
-               {
-                 size -= 1UL << Traits::Shift;
-                 continue;
-               }
-             break;
-           }
-
-         if (!n)
-           n = (Next*)Mem_layout::phys_to_pmem(l->addr());
-
-         Next *rn = (Next*)Mem_layout::phys_to_pmem(r->addr());
-
-         if (n->sync(l_a, *rn, r_a, size, level - 1, alloc))
-           need_flush = true;
-       }
+        {
+          PTE_PTR l(&_e[Vec::idx(l_a)], Depth);
+          PTE_PTR r(const_cast<Entry *>(&_r._e[Vec::idx(r_a)]), Depth);
+          Next *n = 0;
+          if (!r.is_valid()
+              || (!l.is_valid() && (!alloc.valid() || !(n = alloc_next(l, alloc, force_write_back)))))
+            {
+              l_a += 1UL << Traits::Shift;
+              r_a += 1UL << Traits::Shift;
+              if (size > 1UL << Traits::Shift)
+                {
+                  size -= 1UL << Traits::Shift;
+                  continue;
+                }
+              break;
+            }
+
+          if (!n)
+            n = (Next*)Mem_layout::phys_to_pmem(l.next_level());
+
+          Next *rn = (Next*)Mem_layout::phys_to_pmem(r.next_level());
+
+          if (n->sync(l_a, *rn, r_a, size, level - 1, force_write_back, alloc))
+            need_flush = true;
+        }
 
       return need_flush;
     }
 
   };
 
-  template< typename _E, unsigned _Va_shift >
-  class Iter
+  template< typename _E, typename PT >
+  struct Pte_ptr
   {
-  public:
-    Iter(_E *e, unsigned char shift) : e(e), s(shift + _Va_shift) {}
+    Pte_ptr(_E *e, unsigned char level) : e(e), l(level) {}
 
     template< typename _I2 >
-    Iter(_I2 const &o) : e(o.e), s(o.s) {}
+    Pte_ptr(_I2 const &o) : e(o.e), l(o.l) {}
+
+    unsigned char level() const { return l; }
 
-    unsigned char shift() const { return s; }
-    unsigned long addr() const { return e->addr() & (~0UL << s); }
+    unsigned page_order() const
+    { return PT::page_order_for_level(l); }
 
     _E *e;
-    unsigned char s;
+    unsigned char l;
   };
 
   template
@@ -452,41 +496,40 @@ namespace Ptab
     unsigned _Shift,
     unsigned _Size,
     bool _May_be_leaf,
-    bool _Mask = true
+    bool _Mask = true,
+    unsigned _Base_shift = 0
   >
-  class Traits
+  struct Traits
   {
-  public:
     typedef _Entry Entry;
-    typedef typename Entry::Raw Raw;
 
     enum
     {
       May_be_leaf = _May_be_leaf,
       Shift = _Shift,
       Size = _Size,
-      Mask = _Mask
+      Mask = _Mask,
+      Base_shift = _Base_shift
     };
   };
 
   template< typename _T, unsigned _Shift >
-  class Shift
+  struct Shift
   {
-  public:
     typedef _T Orig_list;
     typedef Ptab::Traits
       < typename _T::Entry,
         _T::Shift - _Shift,
         _T::Size,
         _T::May_be_leaf,
-        _T::Mask
+        _T::Mask,
+        _T::Base_shift + _Shift
       > List;
   };
 
   template< typename _Head, typename _Tail, unsigned _Shift >
-  class Shift< List<_Head, _Tail>, _Shift >
+  struct Shift< List<_Head, _Tail>, _Shift >
   {
-  public:
     typedef Ptab::List<_Head, _Tail> Orig_list;
     typedef Ptab::List
     <
@@ -495,26 +538,29 @@ namespace Ptab
     > List;
   };
 
-  class Address_wrap
+  struct Address_wrap
   {
-  public:
     enum { Shift = 0 };
     typedef Address Value_type;
     static Address val(Address a) { return a; }
   };
 
   template< typename N, int SHIFT >
-  class Page_addr_wrap
+  struct Page_addr_wrap
   {
-  public:
     enum { Shift = SHIFT };
     typedef N Value_type;
-    static Address val(N a) { return a.value(); }
+    static typename N::Value val(N a)
+    { return N::val(a); }
+
+    static typename Value_type::Diff_type::Value
+    val(typename Value_type::Diff_type a)
+    { return cxx::int_value<typename Value_type::Diff_type>(a); }
   };
 
   template
   <
-    typename _Base_entry,
+    typename PTE_PTR,
     typename _Traits,
     typename _Addr = Address_wrap
   >
@@ -522,63 +568,85 @@ namespace Ptab
   {
   public:
     typedef typename _Addr::Value_type Va;
+    typedef typename _Addr::Value_type::Diff_type Vs;
     typedef _Traits Traits;
-    typedef _Base_entry Entry;
-    typedef Ptab::Iter<Entry, _Addr::Shift> Iter;
+    typedef PTE_PTR Pte_ptr;
     typedef typename _Traits::Head L0;
 
+    enum
+    {
+      Base_shift = L0::Base_shift,
+    };
+
   private:
-    typedef Base<_Base_entry, _Traits> This;
-    typedef Ptab::Walk<_Traits, Iter> Walk;
+    typedef Ptab::Walk<_Traits, PTE_PTR> Walk;
 
   public:
-    enum { Depth = Walk::Depth };
+    enum { Depth = Walk::Max_depth };
 
-    template< typename _Alloc >
-    Iter walk(Va virt, unsigned level, _Alloc const &alloc)
-    {
-      return _base.walk(_Addr::val(virt), level, alloc);
-    }
+    typedef Level<Traits, Depth> Levels;
 
-    Iter walk(Va virt, unsigned level = 100) const
-    {
-      return const_cast<Walk&>(_base).walk(_Addr::val(virt), level, Null_alloc());
-    }
+    static unsigned lsb_for_level(unsigned level)
+    { return Levels::shift(level); }
+
+    static unsigned page_order_for_level(unsigned level)
+    { return Levels::shift(level) + Base_shift; }
+
+    static unsigned entries_at_level(unsigned level)
+    { return Levels::length(level); }
 
+    static unsigned bits_for_level(unsigned level)
+    { return Levels::size(level); }
 
     template< typename _Alloc >
-    bool sync(Va l_addr, Base< _Base_entry, _Traits, _Addr> const *_r,
-              Va r_addr, Va size, unsigned level = 100,
+    PTE_PTR walk(Va virt, unsigned level, bool force_write_back, _Alloc const &alloc)
+    { return _base.walk(_Addr::val(virt), level, force_write_back, alloc); }
+
+    PTE_PTR walk(Va virt, unsigned level = Depth) const
+    { return const_cast<Walk&>(_base).walk(_Addr::val(virt), level, false, Null_alloc()); }
+
+
+    template< typename OPTE_PTR, typename _Alloc >
+    bool sync(Va l_addr, Base< OPTE_PTR, _Traits, _Addr> const *_r,
+              Va r_addr, Vs size, unsigned level = Depth,
+              bool force_write_back = false,
               _Alloc const &alloc = _Alloc())
     {
       Address la = _Addr::val(l_addr);
       Address ra = _Addr::val(r_addr);
       Address sz = _Addr::val(size);
       return _base.sync(la, _r->_base,
-                        ra, sz, level, alloc);
+                        ra, sz, level, force_write_back,
+                        alloc);
     }
 
-    void clear() { _base.clear(); }
+    void clear(bool force_write_back)
+    { _base.clear(force_write_back); }
 
-    void unmap(Va virt, Va size, unsigned level)
+    void unmap(Va virt, Vs size, unsigned level, bool force_write_back)
     {
       Address va = _Addr::val(virt);
       unsigned long sz = _Addr::val(size);
-      _base.unmap(va, sz, level);
+      _base.unmap(va, sz, level, force_write_back);
     }
 
     template< typename _Alloc >
-    void map(Address phys, Va virt, Va size, unsigned long attr,
-       unsigned level, _Alloc const &alloc = _Alloc())
+    void map(Address phys, Va virt, Vs size, unsigned long attr,
+             unsigned level, bool force_write_back,
+             _Alloc const &alloc = _Alloc())
     {
       Address va = _Addr::val(virt);
       unsigned long sz = _Addr::val(size);
-      _base.map(phys, va, sz, attr, level, alloc);
+      _base.map(phys, va, sz, attr, level, force_write_back, alloc);
     }
 
     template< typename _Alloc >
-    void destroy(Va start, Va end, unsigned level, _Alloc const &alloc = _Alloc())
-    { _base.destroy(_Addr::val(start), _Addr::val(end), level, alloc); }
+    void destroy(Va start, Va end, unsigned start_level, unsigned end_level,
+                 _Alloc const &alloc = _Alloc())
+    {
+      _base.destroy(_Addr::val(start), _Addr::val(end),
+                    start_level, end_level, alloc);
+    }
 
 #if 0
     template< typename _New_alloc >
index 36559d26a8cc7896f74edc60bcc2af1e6d82fe13..e12fa73cf8e48d0c677295dd4354f4737c97de59 100644 (file)
@@ -3,7 +3,7 @@ INTERFACE:
 #include "spin_lock.h"
 #include "queue_item.h"
 #include "kdb_ke.h"
-#include <dlist>
+#include <cxx/dlist>
 
 class Queue
 {
index 579040fe4cc4d32966505ebddab60de5b7563939..d98f03fa3e1f5c8fa8c4e2fa59425bb03a9b5f9c 100644 (file)
@@ -1,6 +1,6 @@
 INTERFACE:
 
-#include <dlist>
+#include <cxx/dlist>
 
 class Queue;
 
index 398f0724594f4053d72d74bb6475dd7c6701135f..b8bb68fa0140b9893ef5917f0dcb34af53688d1e 100644 (file)
@@ -3,7 +3,7 @@ INTERFACE:
 #include "cpu_mask.h"
 #include "per_cpu_data.h"
 #include "spin_lock.h"
-#include <slist>
+#include <cxx/slist>
 
 class Rcu_glbl;
 class Rcu_data;
@@ -100,7 +100,7 @@ public:
   long _len;
   Rcu_list _c;
   Rcu_list _d;
-  unsigned _cpu;
+  Cpu_number _cpu;
 };
 
 
@@ -155,12 +155,12 @@ EXTENSION class Rcu
 public:
   struct Log_rcu : public Tb_entry
   {
-    unsigned cpu;
+    Cpu_number cpu;
     Rcu_item *item;
     void *cb;
     unsigned char event;
     unsigned print(int max, char *buf) const;
-  } __attribute__((packed));
+  };
 
   enum Rcu_events
   {
@@ -180,7 +180,8 @@ unsigned
 Rcu::Log_rcu::print(int max, char *buf) const
 {
   char const *events[] = { "call", "process"};
-  return snprintf(buf, max, "rcu-%s (cpu=%u) item=%p", events[event], cpu, item);
+  return snprintf(buf, max, "rcu-%s (cpu=%u) item=%p", events[event],
+                  cxx::int_value<Cpu_number>(cpu), item);
 }
 
 
@@ -226,7 +227,7 @@ Rcu_glbl::Rcu_glbl()
 {}
 
 PUBLIC
-Rcu_data::Rcu_data(unsigned cpu)
+Rcu_data::Rcu_data(Cpu_number cpu)
 : _idle(true),
   _cpu(cpu)
 {}
@@ -301,7 +302,7 @@ Rcu_glbl::start_batch()
 
 PUBLIC static inline
 void
-Rcu::enter_idle(unsigned cpu)
+Rcu::enter_idle(Cpu_number cpu)
 {
   Rcu_data *rdp = &_rcu_data.cpu(cpu);
   if (EXPECT_TRUE(!rdp->_idle))
@@ -314,7 +315,7 @@ Rcu::enter_idle(unsigned cpu)
 
 PUBLIC static inline
 void
-Rcu::leave_idle(unsigned cpu)
+Rcu::leave_idle(Cpu_number cpu)
 {
   Rcu_data *rdp = &_rcu_data.cpu(cpu);
   if (EXPECT_FALSE(rdp->_idle))
@@ -329,7 +330,7 @@ Rcu::leave_idle(unsigned cpu)
 
 PRIVATE inline NOEXPORT
 void
-Rcu_glbl::cpu_quiet(unsigned cpu)
+Rcu_glbl::cpu_quiet(Cpu_number cpu)
 {
   _cpus.clear(cpu);
   if (_cpus.empty())
@@ -489,19 +490,19 @@ Rcu::process_callbacks()
 
 PUBLIC static inline NEEDS["globals.h"]
 bool FIASCO_WARN_RESULT
-Rcu::process_callbacks(unsigned cpu)
+Rcu::process_callbacks(Cpu_number cpu)
 { return _rcu_data.cpu(cpu).process_callbacks(&_rcu); }
 
 PUBLIC static inline
 bool
-Rcu::pending(unsigned cpu)
+Rcu::pending(Cpu_number cpu)
 {
   return _rcu_data.cpu(cpu).pending(&_rcu);
 }
 
 PUBLIC static inline
 bool
-Rcu::idle(unsigned cpu)
+Rcu::idle(Cpu_number cpu)
 {
   Rcu_data const *d = &_rcu_data.cpu(cpu);
   return d->_c.empty() && !d->pending(&_rcu);
@@ -509,12 +510,12 @@ Rcu::idle(unsigned cpu)
 
 PUBLIC static inline
 void
-Rcu::inc_q_cnt(unsigned cpu)
+Rcu::inc_q_cnt(Cpu_number cpu)
 { _rcu_data.cpu(cpu)._q_passed = 1; }
 
 PUBLIC static
 void
-Rcu::schedule_callbacks(unsigned cpu, Unsigned64 clock)
+Rcu::schedule_callbacks(Cpu_number cpu, Unsigned64 clock)
 {
   Timeout *t = &_rcu_timeout.cpu(cpu);
   if (!t->is_set())
@@ -529,7 +530,7 @@ Rcu::lock()
 
 PUBLIC static inline
 bool
-Rcu::do_pending_work(unsigned cpu)
+Rcu::do_pending_work(Cpu_number cpu)
 {
   if (pending(cpu))
     {
index 6d65805d4f6000a58ad232dc993c102a877a10d2..4fc19372b75dc5d96d37179e5c4f10303e99b7fa 100644 (file)
@@ -1,7 +1,7 @@
 INTERFACE [sched_fixed_prio || sched_fp_wfq]:
 
 #include "config.h"
-#include <dlist>
+#include <cxx/dlist>
 #include "member_offs.h"
 #include "types.h"
 #include "globals.h"
index 8ce4c366d88e216ab07e488404423ee82d34a714..8c82389b6d080d8a5105eb335b06fb5d3ef782cb 100644 (file)
@@ -85,16 +85,16 @@ Receiver::caller() const
 { return reinterpret_cast<Receiver*>(_caller & ~0x03UL); }
 
 PUBLIC inline
-unsigned char
+L4_fpage::Rights
 Receiver::caller_rights() const
-{ return _caller & 0x3; }
+{ return L4_fpage::Rights(_caller & 0x3); }
 
 
 PUBLIC inline
 void
-Receiver::set_caller(Receiver *caller, unsigned char rights)
+Receiver::set_caller(Receiver *caller, L4_fpage::Rights rights)
 {
-  register Mword nv = Mword(caller) | (rights & 0x3);
+  register Mword nv = Mword(caller) | (cxx::int_value<L4_fpage::Rights>(rights) & 0x3);
   reinterpret_cast<Mword volatile &>(_caller) = nv;
 }
 /** IPC partner (sender).
index 43dd402f27ceb1b1a4db5618873a16607bae39ca..0f1b06c2fe724f99a80f07ccc28ecb8d9263e9db 100644 (file)
@@ -5,7 +5,7 @@
 
 INTERFACE [sched_fixed_prio]:
 
-#include <dlist>
+#include <cxx/dlist>
 #include "member_offs.h"
 #include "types.h"
 #include "globals.h"
index 87b651ef8113ce6d83ae92e7b1b66e184b66244c..6c79fe35f46ecb3b4da2ad411933f3bbed6f868d 100644 (file)
@@ -147,3 +147,42 @@ Sched_context::Ready_queue::deblock(Sched_context *sc, Sched_context *crs, bool
   return res;
 }
 
+INTERFACE [debug]:
+
+#include "tb_entry.h"
+
+/** logged scheduling event. */
+class Tb_entry_sched : public Tb_entry
+{
+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));
+
+
+IMPLEMENTATION [debug]:
+
+#include "kobject_dbg.h"
+
+// sched
+IMPLEMENT unsigned
+Tb_entry_sched::print(int maxlen, char *buf) const
+{
+  Mword t = Kobject_dbg::pointer_to_id(owner);
+
+  return snprintf(buf, maxlen,
+              "(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);
+}
+
+
index fa6984ee929ad115d4befee0e62492fa6abfc7c5..9959d9dbd46a1293e250f6468952eb8ba92c19e8 100644 (file)
@@ -50,10 +50,10 @@ Scheduler::Scheduler() : _irq(0)
 
 PRIVATE
 L4_msg_tag
-Scheduler::sys_run(unsigned char /*rights*/, Syscall_frame *f, Utcb const *utcb)
+Scheduler::sys_run(L4_fpage::Rights, Syscall_frame *f, Utcb const *utcb)
 {
   L4_msg_tag const tag = f->tag();
-  unsigned const curr_cpu = current_cpu();
+  Cpu_number const curr_cpu = current_cpu();
 
   Obj_space *s = current()->space();
   assert(s);
@@ -96,20 +96,23 @@ Scheduler::sys_run(unsigned char /*rights*/, Syscall_frame *f, Utcb const *utcb)
 
   Thread::Migration info;
 
-  unsigned t_cpu = thread->cpu();
+  Cpu_number const t_cpu = thread->cpu();
 
   if (Cpu::online(t_cpu) && sched_param->cpus.contains(t_cpu))
     info.cpu = t_cpu;
   else if (sched_param->cpus.contains(curr_cpu))
     info.cpu = curr_cpu;
   else
-    info.cpu = sched_param->cpus.first(Cpu::online_mask(), Config::Max_num_cpus);
+    info.cpu = sched_param->cpus.first(Cpu::online_mask(), Config::max_num_cpus());
 
   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());
+    printf("CPU[%u]: run(thread=%lx, cpu=%u (%lx,%u,%u)\n",
+           cxx::int_value<Cpu_number>(curr_cpu), thread->dbg_id(),
+           cxx::int_value<Cpu_number>(info.cpu),
+           utcb->values[2],
+           cxx::int_value<Cpu_number>(sched_param->cpus.offset()),
+           cxx::int_value<Order>(sched_param->cpus.granularity()));
 
   thread->migrate(&info);
 
@@ -118,15 +121,15 @@ Scheduler::sys_run(unsigned char /*rights*/, Syscall_frame *f, Utcb const *utcb)
 
 PRIVATE
 L4_msg_tag
-Scheduler::sys_idle_time(unsigned char,
+Scheduler::sys_idle_time(L4_fpage::Rights,
                          Syscall_frame *f, Utcb *utcb)
 {
   if (f->tag().words() < 3)
     return commit_result(-L4_err::EInval);
 
   L4_cpu_set cpus = access_once(reinterpret_cast<L4_cpu_set const *>(&utcb->values[1]));
-  Mword const cpu = cpus.first(Cpu::online_mask(), Config::Max_num_cpus);
-  if (EXPECT_FALSE(cpu == Config::Max_num_cpus))
+  Cpu_number 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::Time_val *>(utcb->values)->t
@@ -137,7 +140,7 @@ Scheduler::sys_idle_time(unsigned char,
 
 PRIVATE
 L4_msg_tag
-Scheduler::sys_info(unsigned char, Syscall_frame *f,
+Scheduler::sys_info(L4_fpage::Rights, Syscall_frame *f,
                     Utcb const *iutcb, Utcb *outcb)
 {
   if (f->tag().words() < 2)
@@ -145,17 +148,17 @@ Scheduler::sys_info(unsigned char, Syscall_frame *f,
 
   L4_cpu_set_descr const s = access_once(reinterpret_cast<L4_cpu_set_descr const*>(&iutcb->values[1]));
   Mword rm = 0;
-  Mword max = Config::Max_num_cpus;
-  Mword const offset = s.offset() << s.granularity();
+  Cpu_number max = Config::max_num_cpus();
+  Cpu_number 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 + Cpu_number(MWORD_BITS) << s.granularity())
+    max = offset + Cpu_number(MWORD_BITS) << s.granularity();
 
-  for (Mword i = 0; i < max - offset; ++i)
+  for (Cpu_number i = Cpu_number::first(); i < max - offset; ++i)
     if (Cpu::online(i + offset))
-      rm |= (1 << (i >> s.granularity()));
+      rm |= (1 << cxx::int_value<Cpu_number>(i >> s.granularity()));
 
   outcb->values[0] = rm;
   outcb->values[1] = Config::Max_num_cpus;
@@ -206,7 +209,7 @@ Scheduler::trigger_hotplug_event()
 
 PUBLIC
 L4_msg_tag
-Scheduler::kinvoke(L4_obj_ref ref, Mword rights, Syscall_frame *f,
+Scheduler::kinvoke(L4_obj_ref ref, L4_fpage::Rights rights, Syscall_frame *f,
                    Utcb const *iutcb, Utcb *outcb)
 {
   switch (f->tag().proto())
index 47bf2ba8d23a3021b8b952d4fcb05fcb7ec2cbcd..21a7e6f9b58181f55e61544fc7a96a04f5e03bea 100644 (file)
@@ -2,14 +2,13 @@ IMPLEMENTATION [io]:
 
 PUBLIC
 bool
-Sigma0_task::v_fabricate(Io_space::Addr address, Io_space::Phys_addr* phys,
-                         Io_space::Size* size, unsigned* attribs = 0)
+Sigma0_task::v_fabricate(Io_space::V_pfn address, Io_space::Phys_addr *phys,
+                         Io_space::Page_order *size, Io_space::Attr *attribs = 0)
 {
   // special-cased because we don't do lookup for sigma0
-  *phys = address.trunc(Io_space::Size(Io_space::Map_superpage_size));
-  *size = Io_space::Size(Io_space::Map_superpage_size);
+  *size = Io_space::Page_order(Io_space::Map_superpage_shift);
+  *phys = cxx::mask_lsb(address, *size);
   if (attribs)
-    *attribs = Io_space::Page_writable
-             | Io_space::Page_user_accessible;
+    *attribs = L4_fpage::Rights::FULL();
   return true;
 }
index 95cb1855401a07c9ea532bcee3c1329c1bb0be37..4a3b7bd66e9d6f750cfb192bb9beb3375e2d72f0 100644 (file)
@@ -5,9 +5,10 @@ INTERFACE:
 class Sigma0_task : public Task
 {
 public:
-  explicit Sigma0_task(Ram_quota *q) : Task(q) {}
+  explicit Sigma0_task(Ram_quota *q, Caps c) : Task(q, c) {}
   bool is_sigma0() const { return true; }
-  Address virt_to_phys_s0(void *virt) const { return (Address)virt; }
+  Address virt_to_phys_s0(void *virt) const
+  { return (Address)virt; }
 };
 
 
@@ -16,25 +17,21 @@ IMPLEMENTATION:
 PUBLIC
 bool
 Sigma0_task::v_fabricate(Mem_space::Vaddr address,
-                         Mem_space::Phys_addr* phys, Mem_space::Size* size,
-                         unsigned* attribs = 0)
+                         Mem_space::Phys_addr *phys, Mem_space::Page_order *size,
+                         Mem_space::Attr *attribs = 0)
 {
   // special-cased because we don't do ptab lookup for sigma0
-  *size = Mem_space::has_superpages()
-        ? Mem_space::Size(Config::SUPERPAGE_SIZE)
-        : Mem_space::Size(Config::PAGE_SIZE);
-  *phys = address.trunc(*size);
+  *size = static_cast<Mem_space const &>(*this).largest_page_size();
+  *phys = cxx::mask_lsb(Virt_addr(address), *size);
 
   if (attribs)
-    *attribs = Mem_space::Page_writable
-             | Mem_space::Page_user_accessible
-             | Mem_space::Page_cacheable;
+    *attribs = Mem_space::Attr(L4_fpage::Rights::URWX());
 
   return true;
 }
 
-PUBLIC inline virtual
+PUBLIC inline
 Page_number
-Sigma0_task::map_max_address() const
-{ return Page_number::create(1UL << (MWORD_BITS - Mem_space::Page_shift)); }
+Sigma0_task::mem_space_map_max_address() const
+{ return Page_number(1UL << (MWORD_BITS - Mem_space::Page_shift)); }
 
index b330f74a0b940f152c1da559d6e6d9cee1cfd584..d5e297e0f7903d9afaa33f78186b4314c2d061f8 100644 (file)
@@ -23,7 +23,7 @@ INTERFACE:
 #include "spin_lock.h"
 #include "ref_obj.h"
 #include "slab_cache.h"
-#include <slist>
+#include <cxx/slist>
 
 class Ram_quota;
 class Context;
@@ -42,7 +42,24 @@ class Space
   friend class Jdb_space;
 
 public:
-  explicit Space(Ram_quota *q) : Mem_space(q) {}
+
+  struct Caps
+  : cxx::int_type_base<unsigned char, Caps>,
+    cxx::int_bit_ops<Caps>,
+    cxx::int_null_chk<Caps>
+  {
+    Caps() = default;
+    explicit Caps(unsigned char v)
+    : cxx::int_type_base<unsigned char, Caps>(v) {}
+
+    static Caps none() { return Caps(0); }
+    static Caps mem() { return Caps(1); }
+    static Caps obj() { return Caps(2); }
+    static Caps io() { return Caps(4); }
+    static Caps all() { return Caps(7); }
+  };
+
+  explicit Space(Ram_quota *q, Caps c) : Mem_space(q), _caps(c) {}
   virtual ~Space() = 0;
 
   enum State
@@ -74,8 +91,14 @@ public:
     }
   };
 
+  Caps caps() const { return _caps; }
+
+
 protected:
-  Space(Ram_quota *q, Mem_space::Dir_type* pdir) : Mem_space(q, pdir) {}
+  Space(Ram_quota *q, Mem_space::Dir_type* pdir, Caps c)
+  : Mem_space(q, pdir), _caps(c) {}
+
+  const Caps _caps;
 
 private:
   void switchin_ldt() const;
@@ -129,7 +152,7 @@ Space::find_ku_mem(User<void>::Ptr p, unsigned size)
   return 0;
 }
 
-PUBLIC inline
+PUBLIC inline NEEDS["kdb_ke.h"]
 void
 Space::switchin_context(Space *from)
 {
index 24a64b0cc59843e7009a8bec0ce426426e1d8882..3a8c11478df2b076bc85cd210d30b05cde2fd29c 100644 (file)
@@ -83,7 +83,7 @@ class Chip : public Irq_chip_gen
 public:
   Chip() : Irq_chip_gen(Pic::IRQ_MAX) {}
   unsigned set_mode(Mword, unsigned) { return Irq_base::Trigger_level; }
-  void set_cpu(Mword, unsigned) {}
+  void set_cpu(Mword, Cpu_number) {}
 };
 
 PUBLIC
index c3c1f66fc43614627f203a808fda72b986294a13..e1aa97817a645dbec63f99d4791bdc1153a99b48 100644 (file)
@@ -12,11 +12,11 @@ public:
   static Per_cpu<Cpu> cpus;
   static Cpu *boot_cpu() { return _boot_cpu; }
 
-  Cpu(unsigned cpu) { set_id(cpu); }
+  Cpu(Cpu_number cpu) { set_id(cpu); }
 
 private:
   static Cpu *_boot_cpu;
-  unsigned _phys_id;
+  Cpu_phys_id _phys_id;
   static unsigned long _ns_per_cycle;
 
 };
@@ -44,6 +44,8 @@ DEFINE_PER_CPU Per_cpu<Cpu> Cpu::cpus(true);
 Cpu *Cpu::_boot_cpu;
 unsigned long Cpu::_ns_per_cycle;
 
+PUBLIC static inline unsigned Cpu::phys_bits() { return 32; }
+
 IMPLEMENT
 void
 Cpu::init(bool is_boot_cpu)
@@ -53,13 +55,13 @@ Cpu::init(bool is_boot_cpu)
       _boot_cpu = this;
       set_online(1);
     }
-  _phys_id = 0; //Proc::cpu_id();
+  _phys_id = Cpu_phys_id(0); //Proc::cpu_id();
   _ns_per_cycle = 0; //1000000000 / Boot_info::get_time_base();
   //printf("Timebase: %lu\n", Boot_info::get_time_base());
 }
 
 PUBLIC inline
-unsigned
+Cpu_phys_id
 Cpu::phys_id() const
 { return _phys_id; }
 
index d144d6882c89d05b019bc206614333dc2edf1d52..620411566d37a804a08b442b8cc54bc559219b20 100644 (file)
@@ -6,5 +6,5 @@ IMPLEMENTATION[sparc]:
 
 PRIVATE inline NEEDS["globals.h"]
 Kernel_task::Kernel_task()
-: Task(Ram_quota::root, Kmem::kdir())
+: Task(Ram_quota::root, Kmem::kdir(), Caps::none())
 {}
index 58295fc5f744221550e19accd029f04d919d518c..45bee45a9aae51a61b62232158effc6d2fa9fe8b 100644 (file)
@@ -17,6 +17,6 @@ void
 Kernel_thread::bootstrap_arch()
 {
   //status for kernel thread
-  Return_frame *rf = nonull_static_cast<Return_frame*>(current()->regs());
+  //Return_frame *rf = nonull_static_cast<Return_frame*>(current()->regs());
   //rf->srr1 = Msr::Msr_kernel;
 }
index 70fa47e37d0300248c06d5e656745eb4849d721b..f2bcf2db1e636a12c4957379d2a66dfbc7041f8c 100644 (file)
@@ -13,7 +13,6 @@ public:
   static Mword *kernel_sp();
   static void kernel_sp(Mword *);
 
-  static Mword is_tcb_page_fault( Mword pfa, Mword error );
   static Mword is_kmem_page_fault( Mword pfa, Mword error );
   static Mword is_io_bitmap_page_fault( Mword pfa );
 
@@ -26,7 +25,6 @@ private:
 //---------------------------------------------------------------------------
 IMPLEMENTATION [sparc]:
 
-#include "mem_layout.h"
 #include "paging.h"
 #include "panic.h"
 
@@ -50,13 +48,6 @@ IMPLEMENT inline
 void Kmem::kernel_sp(Mword *sp)
 { _sp = sp; }
 
-PUBLIC static inline NEEDS["mem_layout.h", "panic.h"]
-Address Kmem::ipc_window(unsigned /*win*/)
-{
-  panic("%s not implemented", __PRETTY_FUNCTION__);
-  return 0;
-}
-
 IMPLEMENT inline NEEDS["paging.h"]
 Address Kmem::virt_to_phys(const void *addr)
 {
@@ -64,23 +55,12 @@ Address Kmem::virt_to_phys(const void *addr)
   return kdir()->virt_to_phys(a);
 }
 
-//------------------------------------------------------------------------------
-/*
- * dummy implementations 
- */
-
 IMPLEMENT inline
 Mword Kmem::is_kmem_page_fault(Mword pfa, Mword /*error*/)
 {
   return in_kernel(pfa);
 }
 
-IMPLEMENT inline
-Mword Kmem::is_tcb_page_fault(Mword /*pfa*/, Mword /*error*/ )
-{
-  return 0;
-}
-
 IMPLEMENT inline
 Mword Kmem::is_io_bitmap_page_fault( Mword /*pfa*/ )
 {
index 4f78e4c1b2d09b6b51bf6492996eaf288ee68b17..6b0ebc567701f002ae6318c43d2a3f7f48a96b8a 100644 (file)
@@ -29,3 +29,13 @@ Kmem_alloc::Kmem_alloc()
       alloc_size -= f.size();
     }
 }
+
+PUBLIC inline
+Address
+Kmem_alloc::to_phys(void *v) const
+{
+  // FIX
+  (void)v;
+  return ~0UL;
+}
+
index 50f85eb30fad4edb9ebb802425528873c9eec64c..5c997b49c05fe042da54b27178a5f433a86ba02b 100644 (file)
@@ -9,7 +9,8 @@ EXTENSION class Mem_layout
 
 //TODO cbass: check what can be omitted
 public:
-  enum Phys_layout {
+  enum Phys_layout : Address
+  {
     Utcb_ptr_page        = 0x3000,
     Syscalls_phys        = 0x4000,
     Tbuf_status_page     = 0x5000,
@@ -66,10 +67,10 @@ Mem_layout::phys_to_pmem (Address addr)
     {
       if (kernel_srmmu_l1[i] != 0)
         {
-          Mword v_page = addr &  (0xFF << Pte_base::Pdir_shift);
-          Mword entry  = (kernel_srmmu_l1[i] & Pte_base::Ppn_mask) << Pte_base::Ppn_addr_shift;
+          Mword v_page = addr &  (0xFF << Pte_ptr::Pdir_shift);
+          Mword entry  = (kernel_srmmu_l1[i] & Pte_ptr::Ppn_mask) << Pte_ptr::Ppn_addr_shift;
           if (entry == v_page)
-            return (i << Pte_base::Pdir_shift) | (addr & ~(0xFF << Pte_base::Pdir_shift));
+            return (i << Pte_ptr::Pdir_shift) | (addr & ~(0xFF << Pte_ptr::Pdir_shift));
         }
     }
   return ~0L;
index 5c56903a8d2ebe29163160a4a8026173bf5484e7..b9b446a1f248f6d89ce93dee6888c95eb39f3a17 100644 (file)
@@ -33,14 +33,6 @@ public:
       Page_noncacheable = 0, // XXX
       /// it's a user page.
       Page_user_accessible = 0, // XXX
-      /// Page has been referenced
-      Page_referenced = Pt_entry::Referenced,
-      /// Page is dirty
-      Page_dirty = Pt_entry::Modified,
-      Page_references = Pt_entry::Referenced| Page_dirty,
-      /// A mask which contains all mask bits
-      Page_all_attribs = Page_writable | Page_noncacheable |
-                        Page_user_accessible | Page_referenced | Page_dirty,
     };
 
   // Mapping utilities
@@ -49,7 +41,6 @@ public:
     Need_insert_tlb_flush = 0,
     Map_page_size = Config::PAGE_SIZE,
     Page_shift = Config::PAGE_SHIFT,
-    Map_superpage_size = Config::SUPERPAGE_SIZE,
     Map_max_address = Mem_layout::User_max,
     Whole_space = MWORD_BITS,
     Identity_map = 0,
@@ -96,7 +87,7 @@ Mem_space::initialize()
     return false;
 
   _dir = static_cast<Dir_type*>(b);
-  _dir->clear();       // initialize to zero
+  _dir->clear(true);   // initialize to zero
   return true; // success
 }
 
@@ -105,7 +96,7 @@ Mem_space::Mem_space(Ram_quota *q, Dir_type* pdir)
   : _quota(q), _dir(pdir)
 {
   _kernel_space = this;
-  _current.cpu(0) = this;
+  _current.cpu(Cpu_number::boot_cpu()) = this;
 }
 
 IMPLEMENT inline
@@ -131,39 +122,11 @@ void Mem_space::switchin_context(Mem_space *from)
   printf("%s FIXME\n", __func__);
 }
 
-//XXX cbass: check;
 PUBLIC static inline
-Mword
-Mem_space::xlate_flush(unsigned char rights)
-{
-  Mword a = Page_references;
-  if (rights & L4_fpage::RX)
-    a |= Page_all_attribs;
-  else if (rights & L4_fpage::W)
-    a |= Page_writable;
-
-  return a;
-}
-
-PUBLIC static inline
-Mword
-Mem_space::is_full_flush(unsigned char rights)
+bool
+Mem_space::is_full_flush(L4_fpage::Rights rights)
 {
-  return rights & L4_fpage::RX;
-}
-
-PUBLIC static inline
-unsigned char
-Mem_space::xlate_flush_result(Mword attribs)
-{
-  unsigned char r = 0;
-  if (attribs & Page_referenced)
-    r |= L4_fpage::RX;
-
-  if (attribs & Page_dirty)
-    r |= L4_fpage::W;
-
-  return r;
+  return rights & L4_fpage::Rights::R();
 }
 
 PUBLIC inline NEEDS["cpu.h"]
@@ -181,6 +144,20 @@ Mem_space::tlb_flush(bool = false)
   //Mem_unit::tlb_flush();
 }
 
+PUBLIC static inline NEEDS["mem_unit.h"]
+void
+Mem_space::tlb_flush_spaces(bool all, Mem_space *s1, Mem_space *s2)
+{
+  if (all) // || !Have_asids)
+    Mem_unit::tlb_flush();
+  else
+    {
+      if (s1)
+        s1->tlb_flush(true);
+      if (s2)
+        s2->tlb_flush(true);
+    }
+}
 
 /*
 PUBLIC inline
@@ -222,7 +199,7 @@ Mem_space::dir_shutdown()
   // except the ones in kernel space which are always shared
   /*
   _dir->alloc_cast<Mem_space_q_alloc>()
-    ->destroy(0, Kmem::mem_user_max, Pdir::Depth - 1,
+    ->destroy(0, Kmem::mem_user_max, 0, Pdir::Depth,
               Mem_space_q_alloc(_quota, Kmem_alloc::allocator()));
 */
   NOT_IMPL_PANIC;
@@ -230,7 +207,7 @@ Mem_space::dir_shutdown()
 
 IMPLEMENT inline
 Mem_space *
-Mem_space::current_mem_space(unsigned cpu) /// XXX: do not fix, deprecated, remove!
+Mem_space::current_mem_space(Cpu_number cpu) /// XXX: do not fix, deprecated, remove!
 {
   return _current.cpu(cpu);
 }
@@ -255,12 +232,12 @@ Mem_space::current_mem_space(unsigned cpu) /// XXX: do not fix, deprecated, remo
  */
 IMPLEMENT inline
 Mem_space::Status
-Mem_space::v_insert(Phys_addr phys, Vaddr virt, Vsize size,
-                   unsigned page_attribs, bool /*upgrade_ignore_size*/)
+Mem_space::v_insert(Phys_addr phys, Vaddr virt, Page_order size,
+                   Attr page_attribs)
 {
   (void)phys; (void)virt; (void)page_attribs;
-  assert(size == Size(Config::PAGE_SIZE) 
-         || size == Size(Config::SUPERPAGE_SIZE));
+  assert (cxx::get_lsb(Phys_addr(phys), size) == 0);
+  assert (cxx::get_lsb(Virt_addr(virt), size) == 0);
 /*
   printf("v_insert: phys %08lx virt %08lx (%s) %p\n", phys, virt, 
          page_attribs & Page_writable?"rw":"ro", this);*/
@@ -314,10 +291,10 @@ Mem_space::pmem_to_phys (Address virt) const
  */
 IMPLEMENT
 bool
-Mem_space::v_lookup(Vaddr virt, Phys_addr *phys = 0, Size *size = 0,
-                   unsigned *page_attribs = 0)
+Mem_space::v_lookup(Vaddr virt, Phys_addr *phys, Page_order *order,
+                   Attr *page_attribs)
 {
-  (void)virt; (void)phys; (void)size; (void)page_attribs;
+  (void)virt; (void)phys; (void)order; (void)page_attribs;
   return false;
 }
 
@@ -331,16 +308,20 @@ Mem_space::v_lookup(Vaddr virt, Phys_addr *phys = 0, Size *size = 0,
             case of errors, ~Page_all_attribs is additionally bit-ORed in.
  */
 IMPLEMENT
-unsigned long
-Mem_space::v_delete(Vaddr virt, Vsize size,
-                   unsigned long page_attribs = Page_all_attribs)
+L4_fpage::Rights
+Mem_space::v_delete(Vaddr virt, Page_order size,
+                   L4_fpage::Rights page_attribs)
 {
   (void)virt; (void)size; (void)page_attribs;
-  unsigned ret = 0;
-  return ret;
+  return page_attribs;
 }
 
 PUBLIC static inline
 Page_number
 Mem_space::canonize(Page_number v)
 { return v; }
+
+IMPLEMENT inline
+void
+Mem_space::v_set_access_flags(Vaddr, L4_fpage::Rights)
+{}
index 5240ba4b8bac1c318b78e6c9a99a7944b92bf722..d074befa1fb6b20f5ba1d13d4bf2fa703b816757 100644 (file)
@@ -4,6 +4,7 @@ INTERFACE[sparc]:
 #include "config.h"
 
 class PF {};
+class Page {};
 
 //------------------------------------------------------------------------------
 INTERFACE[sparc]:
@@ -16,10 +17,44 @@ INTERFACE[sparc]:
 
 class Paging {};
 
-class Pte_base
+class Pte_ptr
 {
-  public:
-    typedef Mword Raw;
+public:
+  typedef Mword Entry;
+
+  Pte_ptr() = default;
+  Pte_ptr(void *p, unsigned char level) : pte((Mword*)p), level(level) {}
+
+  bool is_valid() const { return *pte & Valid; }
+
+  void clear() { *pte = 0; }
+
+  bool is_leaf() const
+  {
+    return false; // FIX
+  }
+
+  Mword next_level() const
+  {
+    return cxx::mask_lsb(*pte, 10); // copy'n'paste, check and fix!
+  };
+
+  void set_next_level(Mword phys)
+  {
+    write_now(pte, phys | 1); // copy'n'paste, check and fix!
+  }
+
+  unsigned char page_order() const
+  {
+    // Check and fix!
+    if (level == 0)
+      return 20;
+    return 12;
+  }
+
+  Mword page_addr() const
+  { return cxx::mask_lsb(*pte, page_order()); } // copy'n'paste, check and fix!
+
   enum
   {
     ET_ptd         = 1,           ///< PT Descriptor is PTD
@@ -48,12 +83,14 @@ class Pte_base
     Valid          = 0x3,
   };
 
-    Mword addr() const { return _raw & Ppn_mask;}
+  Mword *pte;
+  unsigned char level;
+
+  //  Mword addr() const { return _raw & Ppn_mask;}
     //bool is_super_page() const { return _raw & Pse_bit; }
-  protected:
-    Raw _raw;
 };
 
+#if 0
 class Pt_entry : public Pte_base
 {
 public:
@@ -73,25 +110,25 @@ public:
     _raw = ((p >> Ppn_addr_shift) & Ptp_mask) | ET_ptd;
   }
 };
+#endif
 
+#if 0
 namespace Page
 {
   typedef Unsigned32 Attribs;
   enum Attribs_enum
   {
-    KERN_RW      = 0x00000000,
-    USER_RO      = 0x00000001,
-    USER_RW      = 0x00000002,
     Cache_mask   = 0x00000078,
     CACHEABLE    = 0x00000000,
     NONCACHEABLE = 0x00000040,
     BUFFERED     = 0x00000080, //XXX not sure
   };
 };
+#endif
 
 
-typedef Ptab::List< Ptab::Traits<Pd_entry, 22, 10, true>,
-                    Ptab::Traits<Pt_entry, 12, 10, true> > Ptab_traits;
+typedef Ptab::List< Ptab::Traits<Unsigned32, 22, 10, true>,
+                    Ptab::Traits<Unsigned32, 12, 10, true> > Ptab_traits;
 
 typedef Ptab::Shift<Ptab_traits, Virt_addr::Shift>::List Ptab_traits_vpn;
 typedef Ptab::Page_addr_wrap<Page_number, Virt_addr::Shift> Ptab_va_vpn;
@@ -120,7 +157,6 @@ Paging::decanonize(Address addr)
   return addr;
 }
 
-//---------------------------------------------------------------------------
 IMPLEMENT inline
 Mword PF::is_translation_error(Mword error)
 {
@@ -150,119 +186,29 @@ Mword PF::addr_to_msgword0(Address pfa, Mword error)
   return a;
 }
 
-//---------------------------------------------------------------------------
-
-PUBLIC
-Pte_base::Pte_base(Mword raw) : _raw(raw) {}
-
-PUBLIC
-Pte_base::Pte_base() {}
-
-PUBLIC inline
-Pte_base &
-Pte_base::operator = (Pte_base const &other)
-{
-  _raw = other.raw();
-  return *this;
-}
-
-PUBLIC inline
-Pte_base &
-Pte_base::operator = (Mword raw)
-{
-  _raw = raw;
-  return *this;
-}
-
-PUBLIC inline
-Mword
-Pte_base::raw() const
-{
-  return _raw;
-}
-
-PUBLIC inline
-void
-Pte_base::add_attr(Mword attr)
-{
-  _raw |= attr;
-}
+PUBLIC static inline
+bool
+Pte_ptr::need_cache_write_back(bool current_pt)
+{ return true; /*current_pt;*/ (void)current_pt; }
 
-PUBLIC inline
+PUBLIC inline NEEDS["mem_unit.h"]
 void
-Pte_base::del_attr(Mword attr)
+Pte_ptr::write_back_if(bool current_pt, Mword /*asid*/ = 0)
 {
-  _raw &= ~attr;
+  (void)current_pt;
+  //if (current_pt)
+  //  Mem_unit::clean_dcache(pte);
 }
 
-PUBLIC inline
+PUBLIC static inline NEEDS["mem_unit.h"]
 void
-Pte_base::clear()
-{ _raw = 0; }
-
-PUBLIC inline
-int
-Pte_base::valid() const
-{
-  return _raw & Valid;
-}
-
-PUBLIC inline
-int
-Pte_base::writable() const
-{
-  Mword acc = ((_raw >> Accperm_shift) & Accperm_mask);
-  return (acc=1); // XXX (3 and 5 can also be valid, depending on access mode)
-}
-
-PUBLIC inline
-Address
-Pt_entry::pfn() const
-{
-  return _raw & Ppn_mask;
-}
-
-PUBLIC static inline
-Mword
-Pte_base::pdir(Address a)
-{
-  return (a & (Pdir_mask << Pdir_shift)) >> Pdir_shift;
-}
+Pte_ptr::write_back(void *start, void *end)
+{ (void)start; (void)end; }
 
 
-PUBLIC static inline
-Mword
-Pte_base::ptab1(Address a)
-{
-  return (a & (Ptab_mask << Ptab_shift1)) >> Ptab_shift1;
-}
-
-
-PUBLIC static inline
-Mword
-Pte_base::ptab2(Address a)
-{
-  return (a & (Ptab_mask << Ptab_shift2)) >> Ptab_shift2;
-}
-
-
-PUBLIC static inline
-Mword
-Pte_base::offset(Address a)
-{
-  return a & Page_offset_mask;
-}
-
-PUBLIC static inline
-void
-Paging::split_address(Address a)
-{
-  printf("%lx -> %lx : %lx : %lx : %lx\n", a,
-         Pte_base::pdir(a),  Pte_base::ptab1(a),
-         Pte_base::ptab2(a), Pte_base::offset(a));
-}
+//---------------------------------------------------------------------------
 
-Pte_base context_table[16];
+Pte_ptr context_table[16];
 Mword kernel_srmmu_l1[256] __attribute__((aligned(0x400)));
 
 PUBLIC static
@@ -296,9 +242,11 @@ Paging::init()
   Mem_unit::context(0);
 
   /* PD entry for root pdir */
+#ifdef THIS_NEED_ADAPTION
   Pd_entry root;
   root.set(Address(kernel_srmmu_l1), false, false);
   context_table[0] = root;
+#endif
 
   /*
    * Map as many 16 MB chunks (1st level page table entries)
@@ -307,6 +255,7 @@ Paging::init()
   unsigned superpage = 0xF0;
   while (memend - memstart + 1 >= (1 << 24))
     {
+#ifdef THIS_NEEDS_ADAPTION
       Pt_entry pte;
       pte.set(memstart, false, false, Pte_base::Cacheable | (0x3 << 2));
       printf("pte %08x\n", pte.raw());
@@ -315,6 +264,7 @@ Paging::init()
       kernel_srmmu_l1[superpage] = pte.raw();
       /* 1:1 mapping */
       kernel_srmmu_l1[Pte_base::pdir(memstart)] = pte.raw();
+#endif
 
       memstart += (1 << 24);
       ++superpage;
index aec1e8e3238bc15ca5bfa9a81641b48d00166370..4b94fb68f14b01bc2dcee2f9caf159f26c7f2f30 100644 (file)
@@ -42,15 +42,15 @@ Startup::stage2()
   Per_cpu_data::init_ctors();
 
   // not really necessary for uni processor
-  Per_cpu_data_alloc::alloc(0);
-  Per_cpu_data::run_ctors(0);
-  Cpu::cpus.cpu(0).init(true);
+  Per_cpu_data_alloc::alloc(Cpu_number::boot_cpu());
+  Per_cpu_data::run_ctors(Cpu_number::boot_cpu());
+  Cpu::cpus.cpu(Cpu_number::boot_cpu()).init(true);
 
   //idle task
   Kernel_task::init();
 #if 0
   Pic::init();
-  Timer::init(0);
+  Timer::init(Cpu_number::boot_cpu());
 #endif
   Utcb_init::init();
   puts("Startup::stage2 finished");
index 1f44db3ebd027ccf2b85e06e1a832a95b3cf507d..13ec02263975db206efde10ce1b2917b056f3e8a 100644 (file)
@@ -9,22 +9,6 @@ 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
@@ -36,6 +20,8 @@ private:
     Unsigned16    _error;
     Mword         _cpsr, _sp;
   };
+public:
+  unsigned print(int max, char *buf) const;
 };
 
 // --------------------------------------------------------------------
@@ -46,63 +32,6 @@ void
 Tb_entry::rdtsc()
 {}
 
-PUBLIC inline
-const char *
-Tb_entry_ke_reg::msg() const
-{
-  return payload<Payload>()->_dsc[0] == 0 && payload<Payload>()->_dsc[1] == 1
-    ? payload<Payload>()->_const_msg : payload<Payload>()->_msg;
-}
-
-PUBLIC inline
-Mword
-Tb_entry_ke_reg::val1() const
-{ return payload<Payload>()->_r3; }
-
-PUBLIC inline
-Mword
-Tb_entry_ke_reg::val2() const
-{ return payload<Payload>()->_r4; }
-
-PUBLIC inline
-Mword
-Tb_entry_ke_reg::val3() const
-{ return payload<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<Payload>()->_r3 = v1;
-  payload<Payload>()->_r4 = v2;
-  payload<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<Payload>()->_dsc[0] = 0; payload<Payload>()->_dsc[1] = 1;
-  payload<Payload>()->_const_msg = msg;
-}
-
-PUBLIC inline
-void
-Tb_entry_ke_reg::set_buf(unsigned i, char c)
-{
-  if (i < sizeof(payload<Payload>()->_msg) - 1)
-    payload<Payload>()->_msg[i] = c >= ' ' ? c : '.';
-}
-
-PUBLIC inline
-void
-Tb_entry_ke_reg::term_buf(unsigned i)
-{payload<Payload>()->_msg[i < sizeof(payload<Payload>()->_msg)-1 ? i
-  : sizeof(payload<Payload>()->_msg)-1] = '\0';}
-
 // ------------------
 PUBLIC inline
 Unsigned16
@@ -112,17 +41,17 @@ Tb_entry_trap::cs() const
 PUBLIC inline
 Unsigned8
 Tb_entry_trap::trapno() const
-{ return payload<Payload>()->_trapno; }
+{ return 0; }
 
 PUBLIC inline
 Unsigned16
 Tb_entry_trap::error() const
-{ return payload<Payload>()->_error; }
+{ return 0; }
 
 PUBLIC inline
 Mword
 Tb_entry_trap::sp() const
-{ return payload<Payload>()->_sp; }
+{ return 0; }
 
 PUBLIC inline
 Mword
@@ -138,14 +67,14 @@ PUBLIC inline NEEDS ["trap_state.h"]
 void
 Tb_entry_trap::set(Context const *ctx, Mword pc, Trap_state *)
 {
-  set_global(Tbuf_trap, ctx, pc);
-  // More...
+  (void)pc;
+  (void)ctx;
 }
 
 PUBLIC inline NEEDS ["trap_state.h"]
 void
-Tb_entry_trap::set(Context const *ctx, Mword pc, Mword )
+Tb_entry_trap::set(Context const *ctx, Mword pc, Mword)
 {
-  set_global(Tbuf_trap, ctx, pc);
+  (void)pc;
+  (void)ctx;
 }
-
index ce17d12e70f054bc9c2f4bd7bc6d6f3d36d6eb82..8b631d7019cc724e512b7167c4cb2c69dd5677e4 100644 (file)
@@ -52,12 +52,12 @@ IMPLEMENT
 int
 Thread::call_nested_trap_handler(Trap_state * /*ts*/)
 {
-  unsigned phys_cpu = Proc::cpu_id();
-  unsigned log_cpu = Cpu::cpus.find_cpu(Cpu::By_phys_id(phys_cpu));
-  if (log_cpu == ~0U)
+  Cpu_phys_id phys_cpu = Proc::cpu_id();
+  Cpu_number log_cpu = Cpu::cpus.find_cpu(Cpu::By_phys_id(phys_cpu));
+  if (log_cpu == Cpu_number::nil())
     {
-      printf("Trap on unknown CPU phys_id=%x\n", phys_cpu);
-      log_cpu = 0;
+      printf("Trap on unknown CPU phys_id=%x\n", cxx::int_value<Cpu_phys_id>(phys_cpu));
+      log_cpu = Cpu_number::boot_cpu();
     }
 
   unsigned long &ntr = nested_trap_recover.cpu(log_cpu);
index 398ba44b183b797c7ed8c774571de79521098ed5..339d361f2a084ff7dd1928d3ab3797114974c67b 100644 (file)
@@ -82,12 +82,9 @@ IMPLEMENT inline NEEDS["space.h", <cstdio>, "types.h" ,"config.h"]
 bool Thread::handle_sigma0_page_fault(Address pfa)
 {
   bool ret = (mem_space()->v_insert(Mem_space::Phys_addr(pfa & Config::PAGE_MASK),
-                                   Mem_space::Addr(pfa & Config::PAGE_MASK),
-                                   Mem_space::Size(Config::PAGE_SIZE),
-                                   Mem_space::Page_writable |
-                                   Mem_space::Page_user_accessible |
-                                   Mem_space::Page_cacheable
-                                  )
+                                   Virt_addr(pfa & Config::PAGE_MASK),
+                                   Virt_order(Config::PAGE_SIZE),
+                                   Mem_space::Attr(L4_fpage::Rights::URWX()))
        != Mem_space::Insert_err_nomem);
 
   return ret;
@@ -261,7 +258,7 @@ Thread::do_trigger_exception(Entry_frame * /*r*/, void * /*ret_handler*/)
 PRIVATE static inline
 bool FIASCO_WARN_RESULT
 Thread::copy_utcb_to_ts(L4_msg_tag const &/*tag*/, Thread * /*snd*/,
-                        Thread * /*rcv*/, unsigned char /*rights*/)
+                        Thread * /*rcv*/, L4_fpage::Rights /*rights*/)
 {
   NOT_IMPL_PANIC;
   return true;
@@ -270,7 +267,7 @@ Thread::copy_utcb_to_ts(L4_msg_tag const &/*tag*/, Thread * /*snd*/,
 PRIVATE static inline
 bool FIASCO_WARN_RESULT
 Thread::copy_ts_to_utcb(L4_msg_tag const &, Thread * /*snd*/, Thread * /*rcv*/,
-                        unsigned char /*rights*/)
+                        L4_fpage::Rights /*rights*/)
 {
   NOT_IMPL_PANIC;
   return true;
index 90d9218818e3764058cb783202c11219e43cc919..100d229a19c65da65b73c1c2991da5379291bc29 100644 (file)
@@ -15,7 +15,7 @@ IMPLEMENTATION [sparc]:
 
 IMPLEMENT inline NEEDS ["decrementer.h", "kip.h", "config.h", <cstdio>]
 void
-Timer::init(unsigned)
+Timer::init(Cpu_number)
 {
   printf("Using PowerPC decrementer for scheduling\n");
 
@@ -70,9 +70,9 @@ Timer::system_clock()
 
 IMPLEMENT inline NEEDS ["decrementer.h", "config.h", "kip.h"]
 void
-Timer::update_system_clock(unsigned cpu)
+Timer::update_system_clock(Cpu_number cpu)
 {
-  if (cpu == 0)
+  if (cpu == Cpu_number::boot_cpu())
     {
       Decrementer::d()->set();
       Kip::k()->clock += Config::Scheduler_granularity;
index 21cab3b95a109fa97125b22869f6a928bdabb68d..547ee44f9ccc9a0f86d17babb03df8491eb412ab 100644 (file)
@@ -16,7 +16,7 @@ class Trap_state : public Trap_state_regs, public Syscall_frame,
                    public Return_frame
 {
 public:
-  typedef int (*Handler)(Trap_state*, unsigned cpu);
+  typedef int (*Handler)(Trap_state*, Cpu_number cpu);
   bool exclude_logging() { return false; }
 };
 
index d861d5861729a42bb7af3d6106bd147dcfc5a27b..afffb0e14ee898a0ab80367992cae0e56c8eba18 100644 (file)
@@ -41,7 +41,7 @@ extern "C" void sys_ipc_log_wrapper(void)
       Mword dbg_id;
        {
          Obj_cap r = ipc_regs->ref();
-         unsigned char rights;
+          L4_fpage::Rights rights;
          Kobject_iface *o = r.deref(&rights, true);
          if (o)
            dbg_id = o->dbg_info()->dbg_id();
index b55ff86fb9399e59c570e26eee1a41c9b1cad65d..aa5ea9b4cf275f50af81d5bc977456dfb835138d 100644 (file)
@@ -9,12 +9,18 @@ sys_ipc_wrapper()
 {
   assert_kdb (!(current()->state() & Thread_drq_ready));
 
+#ifndef NDEBUG
+  if ((current()->state() & Thread_vcpu_enabled)
+      && (current()->vcpu_state().access()->state & Vcpu_state::F_irqs))
+    WARN("VCPU makes syscall with IRQs enabled: PC=%lx\n", current()->regs()->ip());
+#endif
+
   Thread *curr = current_thread();
   Syscall_frame *f = curr->regs();
 
   Obj_cap obj = f->ref();
   Utcb *utcb = curr->utcb().access(true);
-  unsigned char rights;
+  L4_fpage::Rights rights;
   Kobject_iface *o = obj.deref(&rights);
   L4_msg_tag e;
   if (EXPECT_TRUE(o!=0))
index 7ca15153e38e0c0db1e73afc5bba17d94653952b..ddf2719e69bb4ec6fff64b9f1f45dc53071a63a3 100644 (file)
@@ -116,45 +116,45 @@ Task::alloc_ku_mem_chunk(User<void>::Ptr u_addr, unsigned size, void **k_addr)
   // clean up utcbs
   memset(p, 0, size);
 
-  unsigned long page_size = Config::PAGE_SIZE;
+  Virt_addr base((Address)p);
+  Mem_space::Page_order page_size(Config::PAGE_SHIFT);
 
   // the following works because the size is a power of two
   // and once we have size larger than a super page we have
   // always multiples of superpages
   if (size >= Config::SUPERPAGE_SIZE)
-    page_size = Config::SUPERPAGE_SIZE;
+    page_size = Mem_space::Page_order(Config::SUPERPAGE_SHIFT);
 
-  for (unsigned long i = 0; i < size; i += page_size)
+  for (Virt_size i = Virt_size(0); i < Virt_size(size);
+       i += Virt_size(1) << page_size)
     {
-      Address kern_va = (Address)p + i;
-      Address user_va = (Address)u_addr.get() + i;
-      Address pa = pmem_to_phys(kern_va);
+      Virt_addr kern_va = base + i;
+      Virt_addr user_va = Virt_addr((Address)u_addr.get()) + i;
+      Mem_space::Phys_addr pa(pmem_to_phys(Virt_addr::val(kern_va)));
 
       // must be valid physical address
-      assert(pa != ~0UL);
+      assert(pa != Mem_space::Phys_addr(~0UL));
 
       Mem_space::Status res =
-       static_cast<Mem_space*>(this)->v_insert(Mem_space::Phys_addr(pa),
-           Mem_space::Addr(user_va), Mem_space::Size(page_size),
-           Mem_space::Page_writable | Mem_space::Page_user_accessible
-           | Mem_space::Page_cacheable);
+       static_cast<Mem_space*>(this)->v_insert(pa, user_va, page_size,
+           Mem_space::Attr(L4_fpage::Rights::URW()));
 
       switch (res)
        {
        case Mem_space::Insert_ok: break;
        case Mem_space::Insert_err_nomem:
-         free_ku_mem_chunk(p, u_addr, size, i);
+         free_ku_mem_chunk(p, u_addr, size, Virt_size::val(i));
          return -L4_err::ENomem;
 
        case Mem_space::Insert_err_exists:
-         free_ku_mem_chunk(p, u_addr, size, i);
+         free_ku_mem_chunk(p, u_addr, size, Virt_size::val(i));
          return -L4_err::EExists;
 
        default:
          printf("UTCB mapping failed: va=%p, ph=%p, res=%d\n",
-             (void*)user_va, (void*)kern_va, res);
+             (void*)Virt_addr::val(user_va), (void*)Virt_addr::val(kern_va), res);
          kdb_ke("BUG in utcb allocation");
-         free_ku_mem_chunk(p, u_addr, size, i);
+         free_ku_mem_chunk(p, u_addr, size, Virt_size::val(i));
          return 0;
        }
     }
@@ -178,7 +178,7 @@ Task::alloc_ku_mem(L4_fpage ku_area)
   if (!m)
     return -L4_err::ENomem;
 
-  User<void>::Ptr u_addr((void*)Virt_addr(ku_area.mem_address()).value());
+  User<void>::Ptr u_addr((void*)Virt_addr::val(ku_area.mem_address()));
 
   void *p;
   if (int e = alloc_ku_mem_chunk(u_addr, sz, &p))
@@ -211,19 +211,19 @@ Task::free_ku_mem_chunk(void *k_addr, User<void>::Ptr u_addr, unsigned size,
 {
 
   Kmem_alloc * const alloc = Kmem_alloc::allocator();
-  unsigned long page_size = Config::PAGE_SIZE;
+  Mem_space::Page_order page_size(Config::PAGE_SHIFT);
 
-  // the following works because the size is a poer of two
+  // the following works because the size is a power of two
   // and once we have size larger than a super page we have
   // always multiples of superpages
   if (size >= Config::SUPERPAGE_SIZE)
-    page_size = Config::SUPERPAGE_SIZE;
+    page_size = Mem_space::Page_order(Config::SUPERPAGE_SHIFT);
 
-  for (unsigned long i = 0; i < mapped_size; i += page_size)
+  for (Virt_size i = Virt_size(0); i < Virt_size(mapped_size);
+       i += Virt_size(1) << page_size)
     {
-      Address user_va = (Address)u_addr.get() + i;
-      static_cast<Mem_space*>(this)->v_delete(Mem_space::Addr(user_va),
-                            Mem_space::Size(page_size));
+      Virt_addr user_va = Virt_addr((Address)u_addr.get()) + i;
+      static_cast<Mem_space*>(this)->v_delete(user_va, page_size, L4_fpage::Rights::FULL());
     }
 
   alloc->q_unaligned_free(ram_quota(), size, k_addr);
@@ -259,7 +259,7 @@ Task::initialize()
  * \pre \a parent must be valid and exist.
  */
 PUBLIC explicit
-Task::Task(Ram_quota *q) : Space(q)
+Task::Task(Ram_quota *q, Caps c) : Space(q, c)
 {
   ux_init();
 
@@ -268,8 +268,8 @@ Task::Task(Ram_quota *q) : Space(q)
 }
 
 PROTECTED
-Task::Task(Ram_quota *q, Mem_space::Dir_type* pdir)
-: Space(q, pdir)
+Task::Task(Ram_quota *q, Mem_space::Dir_type* pdir, Caps c)
+: Space(q, pdir, c)
 {
   // increment reference counter from zero
   inc_ref(true);
@@ -318,7 +318,7 @@ Task::create(Ram_quota *quota, L4_fpage const &utcb_area)
   if (!t)
     return 0;
 
-  cxx::unique_ptr<Task> a(new (t) TARGET(quota));
+  cxx::unique_ptr<Task> a(new (t) TARGET(quota, Caps::mem() | Caps::io() | Caps::obj()));
 
   if (!a->initialize())
     return 0;
@@ -349,19 +349,19 @@ 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);
+  fpage_unmap(this, L4_fpage::all_spaces(L4_fpage::Rights::FULL()), L4_map_mask::full(), reap_list);
 }
 
 PRIVATE inline NOEXPORT
 L4_msg_tag
-Task::sys_map(unsigned char rights, Syscall_frame *f, Utcb *utcb)
+Task::sys_map(L4_fpage::Rights rights, Syscall_frame *f, Utcb *utcb)
 {
   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)))
+  if (EXPECT_FALSE(!(rights & L4_fpage::Rights::CW())))
     return commit_result(-L4_err::EPerm);
 
   L4_msg_tag const tag = f->tag();
@@ -377,10 +377,17 @@ Task::sys_map(unsigned char rights, Syscall_frame *f, Utcb *utcb)
   if (EXPECT_FALSE(!src_task.is_objpage()))
     return commit_result(-L4_err::EInval);
 
-  Task *from = Kobject::dcast<Task*>(s->lookup_local(src_task.obj_index()));
+  L4_fpage::Rights mask;
+  Task *from = Kobject::dcast<Task*>(s->lookup_local(src_task.obj_index(), &mask));
   if (!from)
     return commit_result(-L4_err::EInval);
 
+  mask &= rights;
+  mask |= L4_fpage::Rights::CD() | L4_fpage::Rights::CRW();
+
+  L4_fpage sfp(utcb->values[2]);
+  sfp.mask_rights(mask);
+
   ::Reap_list rl;
   L4_error ret;
 
@@ -395,7 +402,7 @@ Task::sys_map(unsigned char rights, Syscall_frame *f, Utcb *utcb)
 
       cpu_lock.clear();
 
-      ret = fpage_map(from, L4_fpage(utcb->values[2]), this,
+      ret = fpage_map(from, sfp, this,
                       L4_fpage::all_spaces(), L4_msg_item(utcb->values[1]), &rl);
       cpu_lock.lock();
     }
@@ -437,8 +444,11 @@ Task::sys_unmap(Syscall_frame *f, Utcb *utcb)
 
       for (unsigned i = 2; i < words; ++i)
         {
-          unsigned const flushed = fpage_unmap(this, L4_fpage(utcb->values[i]), m, rl.list());
-          utcb->values[i] = (utcb->values[i] & ~0xfUL) | flushed;
+          L4_fpage::Rights const flushed
+            = fpage_unmap(this, L4_fpage(utcb->values[i]), m, rl.list());
+
+          utcb->values[i] = (utcb->values[i] & ~0xfUL)
+                          | cxx::int_value<L4_fpage::Rights>(flushed);
         }
       cpu_lock.lock();
     }
@@ -526,7 +536,7 @@ Task::sys_cap_info(Syscall_frame *f, Utcb *utcb)
 
 PUBLIC
 void
-Task::invoke(L4_obj_ref, Mword rights, Syscall_frame *f, Utcb *utcb)
+Task::invoke(L4_obj_ref, L4_fpage::Rights rights, Syscall_frame *f, Utcb *utcb)
 {
   if (EXPECT_FALSE(f->tag().proto() != L4_msg_tag::Label_task))
     {
index 603fd61e3d297ba8a5d15ab6fb7fba8548f52d2e..f9dd6c67fe71e6175a0e22b4944239133134cd20 100644 (file)
@@ -278,36 +278,6 @@ public:
   unsigned print(int max, char *buf) const;
 };
 
-/** logged context switch. */
-class Tb_entry_ctx_sw : public Tb_entry
-{
-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
-{
-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
 {
@@ -375,7 +345,7 @@ Tb_entry::set_global(char type, Context const *ctx, Address ip)
   _ctx    = ctx;
   _ip     = ip;
   _kclock = (Unsigned32)Kip::k()->clock;
-  _cpu    = current_cpu();
+  _cpu    = cxx::int_value<Cpu_number>(current_cpu());
 }
 
 PUBLIC inline
index ab776748b1afc39591846e3c9db5d2d76549eec5..4617a1ca1da7dd92f2f5a00766e391cf26d8a10f 100644 (file)
@@ -391,59 +391,6 @@ formatter_bp(Tb_entry *tb, const char *tidstr, unsigned tidlen,
   return maxlen;
 }
 
-// context switch
-//IMPLEMENT
-unsigned
-Tb_entry_ctx_sw::print(int maxlen, char *buf) const
-{
-  char symstr[24];
-
-  Context *sctx = 0;
-  Mword sctxid = ~0UL;
-  Mword dst;
-  Mword dst_orig;
-
-  sctx = from_sched->context();
-  sctxid = static_cast<Thread*>(sctx)->dbg_id();
-
-  dst = static_cast<Thread const *>(this->dst)->dbg_id();
-  dst_orig = static_cast<Thread const *>(this->dst_orig)->dbg_id();
-
-  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, kernel_ip);
-#if 0
-  my_snprintf(buf, maxlen, "     %-*s%s '%02lx",
-      tidlen, tidstr, spcstr, e->from_prio());
-#endif
-
-  if (sctx != ctx())
-    my_snprintf(buf, maxlen, "(%lx)", sctxid);
-
-  my_snprintf(buf, maxlen, " ==> %lx ", dst);
-
-  if (dst != dst_orig || lock_cnt)
-    my_snprintf(buf, maxlen, "(");
-
-  if (dst != dst_orig)
-    my_snprintf(buf, maxlen, "want %lx", dst_orig);
-
-  if (dst != dst_orig && lock_cnt)
-    my_snprintf(buf, maxlen, " ");
-
-  if (lock_cnt)
-    my_snprintf(buf, maxlen, "lck %ld", lock_cnt);
-
-  if (dst != dst_orig || lock_cnt)
-    my_snprintf(buf, maxlen, ") ");
-
-  my_snprintf(buf, maxlen, " krnl %s", symstr);
-
-  return maxlen;
-}
-
 
 // trap
 unsigned
@@ -466,27 +413,6 @@ Tb_entry_trap::print(int maxlen, char *buf) const
   return maxlen;
 }
 
-// sched
-unsigned
-Tb_entry_sched::print(int maxlen, char *buf) const
-{
-  Thread const *_t = static_cast<Thread const *>(owner);
-  Mword t = ~0UL;
-  if (Jdb_util::is_mapped(_t))
-    t = _t->dbg_id();
-
-
-  my_snprintf(buf, maxlen, 
-              "(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;
-}
-
 // kernel event log binary data
 static
 unsigned
index 972c7d05781893a3b33d73512096420c6f367f39..43a4198e4f5ba034c0db22918dbc5157c1e6a4c5 100644 (file)
@@ -8,14 +8,14 @@ protected:
   struct Log_pf_invalid : public Tb_entry
   {
     Mword pfa;
-    Mword cap_idx;
+    Cap_index cap_idx;
     Mword err;
     unsigned print(int max, char *buf) const;
   };
 
   struct Log_exc_invalid : public Tb_entry
   {
-    Mword cap_idx;
+    Cap_index cap_idx;
     unsigned print(int max, char *buf) const;
   };
 };
@@ -39,7 +39,7 @@ protected:
   };
 
   Syscall_frame *_snd_regs;
-  unsigned char _ipc_send_rights;
+  L4_fpage::Rights _ipc_send_rights;
 };
 
 class Buf_utcb_saver
@@ -71,7 +71,7 @@ struct Ipc_remote_request
   L4_msg_tag tag;
   Thread *partner;
   Syscall_frame *regs;
-  unsigned char rights;
+  L4_fpage::Rights rights;
   bool timeout;
   bool have_rcv;
 
@@ -242,15 +242,15 @@ Thread::handle_page_fault_pager(Thread_ptr const &_pager,
 
   auto guard = lock_guard(cpu_lock);
 
-  unsigned char rights;
+  L4_fpage::Rights rights;
   Kobject_iface *pager = _pager.ptr(space(), &rights);
 
   if (!pager)
     {
       WARN("CPU%d: Pager of %lx is invalid (pfa=" L4_PTR_FMT
           ", errorcode=" L4_PTR_FMT ") to %lx (pc=%lx)\n",
-          current_cpu(), dbg_id(), pfa, error_code,
-           _pager.raw(), regs()->ip());
+          cxx::int_value<Cpu_number>(current_cpu()), dbg_id(), pfa,
+           error_code, cxx::int_value<Cap_index>(_pager.raw()), regs()->ip());
 
 
       LOG_TRACE("Page fault invalid pager", "pf", this, Log_pf_invalid,
@@ -286,7 +286,7 @@ Thread::handle_page_fault_pager(Thread_ptr const &_pager,
   r.timeout(timeout);
   r.tag(tag);
   r.from(0);
-  r.ref(L4_obj_ref(_pager.raw() << L4_obj_ref::Cap_shift, L4_obj_ref::Ipc_call_ipc));
+  r.ref(L4_obj_ref(_pager.raw(), L4_obj_ref::Ipc_call_ipc));
   pager->invoke(r.ref(), rights, &r, utcb);
 
 
@@ -457,7 +457,7 @@ void
 Thread::do_ipc(L4_msg_tag const &tag, bool have_send, Thread *partner,
                bool have_receive, Sender *sender,
                L4_timeout_pair t, Syscall_frame *regs,
-               unsigned char rights)
+               L4_fpage::Rights rights)
 {
   assert_kdb (cpu_lock.test());
   assert_kdb (this == current());
@@ -619,7 +619,7 @@ Thread::do_ipc(L4_msg_tag const &tag, bool have_send, Thread *partner,
 PRIVATE inline NEEDS [Thread::copy_utcb_to]
 bool
 Thread::transfer_msg(L4_msg_tag tag, Thread *receiver,
-                     Syscall_frame *sender_regs, unsigned char rights)
+                     Syscall_frame *sender_regs, L4_fpage::Rights rights)
 {
   Syscall_frame* dst_regs = receiver->rcv_regs();
 
@@ -677,7 +677,7 @@ Pf_msg_utcb_saver::restore(Utcb *u)
  */
 PRIVATE
 bool
-Thread::exception(Kobject_iface *handler, Trap_state *ts, Mword rights)
+Thread::exception(Kobject_iface *handler, Trap_state *ts, L4_fpage::Rights rights)
 {
   Syscall_frame r;
   L4_timeout_pair timeout(L4_timeout::Never, L4_timeout::Never);
@@ -705,7 +705,7 @@ Thread::exception(Kobject_iface *handler, Trap_state *ts, Mword rights)
   r.tag(tag);
   r.timeout(timeout);
   r.from(0);
-  r.ref(L4_obj_ref(_exc_handler.raw() << L4_obj_ref::Cap_shift, L4_obj_ref::Ipc_call_ipc));
+  r.ref(L4_obj_ref(_exc_handler.raw(), L4_obj_ref::Ipc_call_ipc));
   spill_user_state();
   handler->invoke(r.ref(), rights, &r, utcb);
   fill_user_state();
@@ -784,7 +784,7 @@ Thread::send_exception(Trap_state *ts)
   if (!send_exception_arch(ts))
     return 0; // do not send exception
 
-  unsigned char rights = 0;
+  L4_fpage::Rights rights = L4_fpage::Rights(0);
   Kobject_iface *pager = _exc_handler.ptr(space(), &rights);
 
   if (EXPECT_FALSE(!pager))
@@ -841,7 +841,7 @@ Thread::try_transfer_local_id(L4_buf_iter::Item const *const buf,
 PRIVATE static inline
 bool FIASCO_WARN_RESULT
 Thread::copy_utcb_to_utcb(L4_msg_tag const &tag, Thread *snd, Thread *rcv,
-                          unsigned char rights)
+                          L4_fpage::Rights rights)
 {
   assert (cpu_lock.test());
 
@@ -856,7 +856,7 @@ Thread::copy_utcb_to_utcb(L4_msg_tag const &tag, Thread *snd, Thread *rcv,
   if (tag.items())
     success = transfer_msg_items(tag, snd, snd_utcb, rcv, rcv_utcb, rights);
 
-  if (tag.transfer_fpu() && rcv_utcb->inherit_fpu() && (rights & L4_fpage::W))
+  if (tag.transfer_fpu() && rcv_utcb->inherit_fpu() && (rights & L4_fpage::Rights::W()))
     snd->transfer_fpu(rcv);
 
   return success;
@@ -867,7 +867,7 @@ PUBLIC inline NEEDS[Thread::copy_utcb_to_ts, Thread::copy_utcb_to_utcb,
                     Thread::copy_ts_to_utcb]
 bool FIASCO_WARN_RESULT
 Thread::copy_utcb_to(L4_msg_tag const &tag, Thread* receiver,
-                     unsigned char rights)
+                     L4_fpage::Rights rights)
 {
   // we cannot copy trap state to trap state!
   assert_kdb (!this->_utcb_handler || !receiver->_utcb_handler);
@@ -883,7 +883,7 @@ PRIVATE static
 bool
 Thread::transfer_msg_items(L4_msg_tag const &tag, Thread* snd, Utcb *snd_utcb,
                            Thread *rcv, Utcb *rcv_utcb,
-                           unsigned char rights)
+                           L4_fpage::Rights rights)
 {
   // LOG_MSG_3VAL(current(), "map bd=", rcv_utcb->buf_desc.raw(), 0, 0);
   Task *const rcv_t = nonull_static_cast<Task*>(rcv->space());
@@ -961,7 +961,7 @@ Thread::transfer_msg_items(L4_msg_tag const &tag, Thread* snd, Utcb *snd_utcb,
 
              // diminish when sending via restricted ipc gates
              if (sfp.type() == L4_fpage::Obj)
-               sfp.mask_rights(L4_fpage::Rights(rights | L4_fpage::RX));
+               sfp.mask_rights(rights | L4_fpage::Rights::CRW() | L4_fpage::Rights::CD());
 
              L4_error err;
 
@@ -1097,7 +1097,7 @@ Thread::do_send_wait(Thread *partner, L4_timeout snd_t)
 
 PRIVATE inline
 void
-Thread::set_ipc_send_rights(unsigned char c)
+Thread::set_ipc_send_rights(L4_fpage::Rights c)
 {
   _ipc_send_rights = c;
 }
@@ -1169,7 +1169,7 @@ unsigned
 Thread::remote_handshake_receiver(L4_msg_tag const &tag, Thread *partner,
                                   bool have_receive,
                                   L4_timeout snd_t, Syscall_frame *regs,
-                                  unsigned char rights)
+                                  L4_fpage::Rights rights)
 {
   // Flag that there must be no switch in the receive path.
   // This flag also prevents the receive path from accessing
@@ -1221,12 +1221,13 @@ IMPLEMENT
 unsigned
 Thread::Log_pf_invalid::print(int max, char *buf) const
 {
-  return snprintf(buf, max, "InvCap C:%lx pfa=%lx err=%lx", cap_idx, pfa, err);
+  return snprintf(buf, max, "InvCap C:%lx pfa=%lx err=%lx",
+                  cxx::int_value<Cap_index>(cap_idx), pfa, err);
 }
 
 IMPLEMENT
 unsigned
 Thread::Log_exc_invalid::print(int max, char *buf) const
 {
-  return snprintf(buf, max, "InvCap C:%lx", cap_idx);
+  return snprintf(buf, max, "InvCap C:%lx", cxx::int_value<Cap_index>(cap_idx));
 }
index c2ae77c5ca04ea17c606589be8f992fae0abe746..fea7a13795a0333942570928b4b8055e26fcbd3d 100644 (file)
@@ -34,10 +34,12 @@ int Thread::handle_page_fault (Address pfa, Mword error_code, Mword pc,
     Return_frame *regs)
 {
   //if (Config::Log_kernel_page_faults && !PF::is_usermode_error(error_code))
-  if (0 && current_cpu() != 0)
+  if (0 && current_cpu() != Cpu_number::boot_cpu())
     {
       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);
+      printf("*KP[cpu=%u, sp=%lx, pfa=%lx, pc=%lx, error=(%lx)",
+             cxx::int_value<Cpu_number>(current_cpu()),
+             Proc::stack_pointer(), pfa, pc, error_code);
       print_page_fault_error(error_code);
       printf("]\n");
     }
index 73276fd5236919e24f6b85e52393ea4f5b77429b..8d8380b0c55300d985c0fd0a0b8d1ec80cd27cc1 100644 (file)
@@ -1,9 +1,20 @@
+INTERFACE:
+EXTENSION class Thread
+{
+protected:
+  void arch_init_vcpu_state(Vcpu_state *vcpu_state, bool ext);
+};
+
 IMPLEMENTATION:
 
 #include "logdefs.h"
 #include "task.h"
 #include "vcpu.h"
 
+IMPLEMENT_DEFAULT inline
+void Thread::arch_init_vcpu_state(Vcpu_state *, bool /*ext*/) {}
+
+
 PUBLIC inline NEEDS["task.h"]
 void
 Thread::vcpu_set_user_space(Task *t)
index cf78462fd43cbd531247770ea187e625d5f8d0b9..5f911b26aee8b65e7cf168c4c99eafda71a2f10b 100644 (file)
@@ -430,7 +430,7 @@ PUBLIC inline NEEDS ["config.h", "timeout.h"]
 void
 Thread::handle_timer_interrupt()
 {
-  unsigned _cpu = cpu(true);
+  Cpu_number _cpu = cpu(true);
   // XXX: This assumes periodic timers (i.e. bogus in one-shot mode)
   if (!Config::Fine_grained_cputime)
     consume_time(Config::Scheduler_granularity);
@@ -741,9 +741,9 @@ Thread::handle_migration_helper(Drq *rq, Context *, void *p)
 {
   Migration *inf = reinterpret_cast<Migration *>(p);
   Thread *v = static_cast<Thread*>(context_of(rq));
-  unsigned target_cpu = access_once(&inf->cpu);
+  Cpu_number target_cpu = access_once(&inf->cpu);
   v->migrate_away(inf, false);
-  v->migrate_to(target_cpu);
+  v->migrate_to(target_cpu, false);
   return Drq::Need_resched | Drq::No_answer;
 }
 
@@ -788,9 +788,9 @@ Thread::do_migration()
     }
   else
     {
-      unsigned target_cpu = access_once(&inf->cpu);
+      Cpu_number target_cpu = access_once(&inf->cpu);
       migrate_away(inf, false);
-      migrate_to(target_cpu);
+      migrate_to(target_cpu, false);
     }
   return false; // we already are chosen by the scheduler...
 }
@@ -806,9 +806,9 @@ Thread::initiate_migration()
 
   spill_fpu_if_owner();
 
-  unsigned target_cpu = access_once(&inf->cpu);
+  Cpu_number target_cpu = access_once(&inf->cpu);
   migrate_away(inf, false);
-  migrate_to(target_cpu);
+  migrate_to(target_cpu, false);
   return false;
 }
 
@@ -957,7 +957,7 @@ Thread::migrate_away(Migration *inf, bool /*remote*/)
   assert_kdb (current() != this);
   assert_kdb (cpu_lock.test());
 
-  unsigned cpu = inf->cpu;
+  Cpu_number cpu = inf->cpu;
   //  LOG_MSG_3VAL(this, "MGi ", Mword(current()), (current_cpu() << 16) | cpu(), Context::current_sched());
   if (_timeout)
     _timeout->reset();
@@ -988,13 +988,13 @@ Thread::migrate_away(Migration *inf, bool /*remote*/)
 }
 
 PRIVATE inline
-void
-Thread::migrate_to(unsigned target_cpu)
+bool
+Thread::migrate_to(Cpu_number target_cpu, bool)
 {
   if (!Cpu::online(target_cpu))
     {
       handle_drq();
-      return;
+      return false;
     }
 
   auto &rq = Sched_context::rq.current();
@@ -1002,6 +1002,8 @@ Thread::migrate_to(unsigned target_cpu)
     rq.ready_enqueue(sched());
 
   enqueue_timeout_again();
+
+  return false;
 }
 
 PUBLIC
@@ -1034,8 +1036,8 @@ protected:
   {
     Mword    state;
     Address  user_ip;
-    unsigned src_cpu;
-    unsigned target_cpu;
+    Cpu_number src_cpu;
+    Cpu_number target_cpu;
 
     unsigned print(int, char *) const;
   };
@@ -1069,12 +1071,12 @@ Thread::migrate(Migration *info)
         old->in_progress = true;
     }
 
-  unsigned cpu = this->cpu();
+  Cpu_number cpu = this->cpu();
 
   if (current_cpu() == cpu || Config::Max_num_cpus == 1)
     current()->schedule_if(do_migration());
   else
-    migrate_xcpu(cpu);
+    current()->schedule_if(migrate_xcpu(cpu));
 
   cpu_lock.clear();
   // FIXME: use monitor & mwait or wfe & sev if available
@@ -1152,7 +1154,7 @@ Thread::migrate_away(Migration *inf, bool remote)
        rq.set_current_sched(current()->sched());
     }
 
-  unsigned target_cpu = inf->cpu;
+  Cpu_number target_cpu = inf->cpu;
 
     {
       Queue &q = _pending_rqq.cpu(cpu());
@@ -1186,8 +1188,8 @@ Thread::migrate_away(Migration *inf, bool remote)
 }
 
 PRIVATE inline
-void
-Thread::migrate_to(unsigned target_cpu)
+bool
+Thread::migrate_to(Cpu_number target_cpu, bool remote)
 {
   bool ipi = false;
 
@@ -1199,12 +1201,15 @@ Thread::migrate_to(unsigned target_cpu)
           && EXPECT_FALSE(!Cpu::online(target_cpu)))
         {
           handle_drq();
-          return;
+          return false;
         }
 
       // migrated meanwhile
       if (access_once(&this->_cpu) != target_cpu || _pending_rq.queued())
-        return;
+        return false;
+
+      if (remote && target_cpu == current_cpu())
+        return Sched_context::rq.current().deblock(sched(), current()->sched(), false);
 
       if (!_pending_rq.queued())
         {
@@ -1222,11 +1227,13 @@ Thread::migrate_to(unsigned target_cpu)
       //LOG_MSG_3VAL(this, "sipi", current_cpu(), cpu(), (Mword)current());
       Ipi::send(Ipi::Request, current_cpu(), target_cpu);
     }
+
+  return false;
 }
 
 PRIVATE inline
-void
-Thread::migrate_xcpu(unsigned cpu)
+bool
+Thread::migrate_xcpu(Cpu_number cpu)
 {
   bool ipi = false;
 
@@ -1236,22 +1243,21 @@ Thread::migrate_xcpu(unsigned cpu)
 
       // already migrated
       if (cpu != access_once(&this->_cpu))
-        return;
+        return false;
 
-      // now we are shure that this thread stays on 'cpu' because
+      // now we are sure 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
+            return (Mword)inf & 1; // all done, nothing to do
 
-          unsigned target_cpu = access_once(&inf->cpu);
+          Cpu_number target_cpu = access_once(&inf->cpu);
           migrate_away(inf, true);
           g.reset();
-          migrate_to(target_cpu);
-          return;
+          return migrate_to(target_cpu, true);
           // FIXME: Wie lange dauert es ready dequeue mit WFQ zu machen?
           // wird unter spinlock gemacht !!!!
         }
@@ -1267,7 +1273,8 @@ Thread::migrate_xcpu(unsigned cpu)
 
   if (ipi)
     Ipi::send(Ipi::Request, current_cpu(), cpu);
-  return;
+
+  return false;
 }
 
 //----------------------------------------------------------------------------
@@ -1278,6 +1285,6 @@ unsigned
 Thread::Migration_log::print(int maxlen, char *buf) const
 {
   return snprintf(buf, maxlen, "migrate from %u to %u (state=%lx user ip=%lx)",
-      src_cpu, target_cpu, state, user_ip);
+      cxx::int_value<Cpu_number>(src_cpu),
+      cxx::int_value<Cpu_number>(target_cpu), state, user_ip);
 }
-
index 05314efd47f2180e3c07d80604957706310142e0..4c24387417a91c4d818d97c453732022e65a42fa 100644 (file)
@@ -37,7 +37,7 @@ Obj_cap::Obj_cap(L4_obj_ref const &o) : L4_obj_ref(o) {}
 
 PUBLIC inline NEEDS["kobject.h"]
 Kobject_iface *
-Obj_cap::deref(unsigned char *rights = 0, bool dbg = false)
+Obj_cap::deref(L4_fpage::Rights *rights = 0, bool dbg = false)
 {
   Thread *current = current_thread();
   if (op() & L4_obj_ref::Ipc_reply)
@@ -45,7 +45,7 @@ Obj_cap::deref(unsigned char *rights = 0, bool dbg = false)
       if (rights) *rights = current->caller_rights();
       Thread *ca = static_cast<Thread*>(current->caller());
       if (!dbg)
-       current->set_caller(0,0);
+       current->set_caller(0, L4_fpage::Rights(0));
       return ca;
     }
 
@@ -54,7 +54,7 @@ Obj_cap::deref(unsigned char *rights = 0, bool dbg = false)
       if (!self())
        return 0;
 
-      if (rights) *rights = L4_fpage::RWX;
+      if (rights) *rights = L4_fpage::Rights::RWX();
       return current_thread();
     }
 
@@ -108,7 +108,7 @@ Thread_object::destroy(Kobject ***rl)
 
 PUBLIC
 void
-Thread_object::invoke(L4_obj_ref /*self*/, Mword rights, Syscall_frame *f, Utcb *utcb)
+Thread_object::invoke(L4_obj_ref /*self*/, L4_fpage::Rights rights, Syscall_frame *f, Utcb *utcb)
 {
   register L4_obj_ref::Operation op = f->ref().op();
   if (((op != 0) && !(op & L4_obj_ref::Ipc_send))
@@ -178,11 +178,11 @@ Thread_object::sys_vcpu_resume(L4_msg_tag const &tag, Utcb *utcb)
   L4_obj_ref user_task = vcpu->user_task;
   if (user_task.valid())
     {
-      unsigned char task_rights = 0;
+      L4_fpage::Rights task_rights = L4_fpage::Rights(0);
       Task *task = Kobject::dcast<Task*>(s->lookup_local(user_task.cap(),
                                                          &task_rights));
 
-      if (EXPECT_FALSE(task && !(task_rights & L4_fpage::W)))
+      if (EXPECT_FALSE(task && !(task_rights & L4_fpage::Rights::W())))
         return commit_result(-L4_err::EPerm);
 
       if (task != vcpu_user_space())
@@ -228,7 +228,7 @@ Thread_object::sys_vcpu_resume(L4_msg_tag const &tag, Utcb *utcb)
       assert_kdb(cpu_lock.test());
       do_ipc(L4_msg_tag(), 0, 0, true, 0,
             L4_timeout_pair(L4_timeout::Zero, L4_timeout::Zero),
-            &vcpu->_ipc_regs, 3);
+            &vcpu->_ipc_regs, L4_fpage::Rights::FULL());
 
       vcpu = vcpu_state().access(true);
 
@@ -352,14 +352,14 @@ Thread_object::sys_register_delete_irq(L4_msg_tag tag, Utcb const *in, Utcb * /*
 
   register Context *const c_thread = ::current();
   register Space *const c_space = c_thread->space();
-  unsigned char irq_rights = 0;
+  L4_fpage::Rights irq_rights = L4_fpage::Rights(0);
   Irq_base *irq
     = Irq_base::dcast(c_space->lookup_local(bind_irq.obj_index(), &irq_rights));
 
   if (!irq)
     return Kobject_iface::commit_result(-L4_err::EInval);
 
-  if (EXPECT_FALSE(!(irq_rights & L4_fpage::X)))
+  if (EXPECT_FALSE(!(irq_rights & L4_fpage::Rights::X())))
     return Kobject_iface::commit_result(-L4_err::EPerm);
 
   register_delete_irq(irq);
@@ -369,9 +369,9 @@ Thread_object::sys_register_delete_irq(L4_msg_tag tag, Utcb const *in, Utcb * /*
 
 PRIVATE inline NOEXPORT
 L4_msg_tag
-Thread_object::sys_control(unsigned char rights, L4_msg_tag const &tag, Utcb *utcb)
+Thread_object::sys_control(L4_fpage::Rights rights, L4_msg_tag const &tag, Utcb *utcb)
 {
-  if (EXPECT_FALSE(!(rights & L4_fpage::W)))
+  if (EXPECT_FALSE(!(rights & L4_fpage::Rights::W())))
     return commit_result(-L4_err::EPerm);
 
   if (EXPECT_FALSE(tag.words() < 6))
@@ -385,17 +385,17 @@ Thread_object::sys_control(unsigned char rights, L4_msg_tag const &tag, Utcb *ut
 
   Mword flags = utcb->values[0];
 
-  Mword _old_pager = _pager.raw() << L4_obj_ref::Cap_shift;
-  Mword _old_exc_handler = _exc_handler.raw() << L4_obj_ref::Cap_shift;
+  Mword _old_pager = cxx::int_value<Cap_index>(_pager.raw()) << L4_obj_ref::Cap_shift;
+  Mword _old_exc_handler = cxx::int_value<Cap_index>(_exc_handler.raw()) << L4_obj_ref::Cap_shift;
 
-  Thread_ptr _new_pager(~0UL);
-  Thread_ptr _new_exc_handler(~0UL);
+  Thread_ptr _new_pager(Thread_ptr::Invalid);
+  Thread_ptr _new_exc_handler(Thread_ptr::Invalid);
 
   if (flags & Ctl_set_pager)
-    _new_pager = Thread_ptr(utcb->values[1] >> L4_obj_ref::Cap_shift);
+    _new_pager = Thread_ptr(Cap_index(utcb->values[1] >> L4_obj_ref::Cap_shift));
 
   if (flags & Ctl_set_exc_handler)
-    _new_exc_handler = Thread_ptr(utcb->values[2] >> L4_obj_ref::Cap_shift);
+    _new_exc_handler = Thread_ptr(Cap_index(utcb->values[2] >> L4_obj_ref::Cap_shift));
 
   if (flags & Ctl_bind_task)
     {
@@ -407,10 +407,10 @@ Thread_object::sys_control(unsigned char rights, L4_msg_tag const &tag, Utcb *ut
       if (EXPECT_FALSE(!bind_task.is_objpage()))
        return commit_result(-L4_err::EInval);
 
-      unsigned char task_rights = 0;
+      L4_fpage::Rights task_rights = L4_fpage::Rights(0);
       task = Kobject::dcast<Task*>(s->lookup_local(bind_task.obj_index(), &task_rights));
 
-      if (EXPECT_FALSE(!(task_rights & L4_fpage::W)))
+      if (EXPECT_FALSE(!(task_rights & L4_fpage::Rights::W())))
        return commit_result(-L4_err::EPerm);
 
       if (!task)
@@ -457,7 +457,7 @@ Thread_object::sys_control(unsigned char rights, L4_msg_tag const &tag, Utcb *ut
 
 PRIVATE inline NOEXPORT
 L4_msg_tag
-Thread_object::sys_vcpu_control(unsigned char, L4_msg_tag const &tag,
+Thread_object::sys_vcpu_control(L4_fpage::Rights, L4_msg_tag const &tag,
                                 Utcb *utcb)
 {
   if (!space())
@@ -489,7 +489,9 @@ 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());
+      Vcpu_state *s = _vcpu_state.access();
+      arch_init_vcpu_state(s, add_state & Thread_ext_vcpu_enabled);
+      arch_update_vcpu_state(s);
     }
   else
     return commit_result(-L4_err::EInval);
index dc9cb8ad941cc0f7149939e32ab7234732cb4ac3..0a433307ba1513672dc1399f872a3c0ae5cf8ca4 100644 (file)
@@ -1,6 +1,6 @@
 INTERFACE:
 
-#include <hlist>
+#include <cxx/hlist>
 #include "l4_types.h"
 #include "per_cpu_data.h"
 
@@ -187,7 +187,7 @@ Timeout::has_hit()
 PUBLIC inline NEEDS [<cassert>, "cpu_lock.h", "lock_guard.h",
                      Timeout_q::enqueue, Timeout::is_set]
 void
-Timeout::set(Unsigned64 clock, unsigned cpu)
+Timeout::set(Unsigned64 clock, Cpu_number cpu)
 {
   // XXX uses global kernel lock
   auto guard = lock_guard(cpu_lock);
@@ -211,7 +211,7 @@ Timeout::get_timeout(Unsigned64 clock)
 PUBLIC inline NEEDS [<cassert>, "cpu_lock.h", "lock_guard.h",
                      Timeout::is_set, Timeout_q::enqueue, Timeout::has_hit]
 void
-Timeout::set_again(unsigned cpu)
+Timeout::set_again(Cpu_number cpu)
 {
   // XXX uses global kernel lock
   auto guard = lock_guard(cpu_lock);
index 76a83807dbb3577f9bf4b6f7a6e670a1d2b2510c..2e573d7ab52f9f39eefbd3954fc8ffc48d916ca2 100644 (file)
@@ -27,7 +27,7 @@ unsigned Timer::irq_mode()
 
 IMPLEMENT
 void
-Timer::init(unsigned)
+Timer::init(Cpu_number)
 {
   hpet_irq = -1;
   if (!Hpet::init())
index 017111581e8a44d2f59ed23832f5337ab2df5476..92ba33f17adc56d449e99ba72ea499b189b3a1c1 100644 (file)
@@ -12,7 +12,7 @@ public:
    * The implementation is platform specific. Two x86 implementations
    * are timer-pit and timer-rtc.
    */
-  static void init(unsigned cpu) FIASCO_INIT_CPU;
+  static void init(Cpu_number cpu) FIASCO_INIT_CPU;
 
   /**
    * Initialize the system clock.
@@ -22,7 +22,7 @@ public:
   /**
    * Advances the system clock.
    */
-  static void update_system_clock(unsigned cpu);
+  static void update_system_clock(Cpu_number cpu);
 
   /**
    * Get the current system clock.
@@ -34,13 +34,13 @@ public:
    */
   static void update_timer(Unsigned64 wakeup);
 
-  static void master_cpu(unsigned cpu) { _cpu = cpu; }
+  static void master_cpu(Cpu_number cpu) { _cpu = cpu; }
 
 private:
-  static unsigned _cpu;
+  static Cpu_number _cpu;
 };
 
 
 IMPLEMENTATION:
 
-unsigned Timer::_cpu;
+Cpu_number Timer::_cpu;
diff --git a/kernel/fiasco/src/kern/timer_tick-broadcast.cpp b/kernel/fiasco/src/kern/timer_tick-broadcast.cpp
new file mode 100644 (file)
index 0000000..bb4fe98
--- /dev/null
@@ -0,0 +1,60 @@
+INTERFACE:
+
+#include "types.h"
+
+EXTENSION class Timer_tick
+{
+public:
+  static Static_object<Timer_tick> _glbl_timer;
+};
+
+IMPLEMENTATION:
+
+#include "ipi.h"
+#include "timer.h"
+
+Static_object<Timer_tick> Timer_tick::_glbl_timer;
+
+IMPLEMENT void
+Timer_tick::setup(Cpu_number cpu)
+{
+  if (cpu == Cpu_number::boot_cpu())
+    {
+      _glbl_timer.construct(Sys_cpu);
+      if (!allocate_irq(_glbl_timer, Timer::irq()))
+        panic("Could not allocate scheduling IRQ %d\n", Timer::irq());
+      else
+        printf("Timer is at IRQ %d\n", Timer::irq());
+
+      _glbl_timer->set_mode(Timer::irq_mode());
+    }
+}
+
+IMPLEMENT
+void
+Timer_tick::enable(Cpu_number)
+{
+  _glbl_timer->chip()->unmask(_glbl_timer->pin());
+}
+
+IMPLEMENT
+void
+Timer_tick::disable(Cpu_number cpu)
+{
+  if (cpu == Cpu_number::boot_cpu())
+    _glbl_timer->chip()->mask(_glbl_timer->pin());
+  else
+    {
+      // disable IPI
+    }
+
+}
+
+PUBLIC inline NEEDS["timer.h", "ipi.h"]
+void
+Timer_tick::ack()
+{
+  Timer::acknowledge();
+  Irq_base::ack();
+  Ipi::bcast(Ipi::Timer, Cpu_number::boot_cpu());
+}
index 7bcc051f0a372f2a1ad63b5ad7f04a3c20c14261..951c45285db3f35964131b387e1df045720b21fb 100644 (file)
@@ -15,10 +15,10 @@ IMPLEMENTATION:
 Static_object<Timer_tick> Timer_tick::_glbl_timer;
 
 IMPLEMENT void
-Timer_tick::setup(unsigned cpu)
+Timer_tick::setup(Cpu_number cpu)
 {
   // all CPUs use the same timer IRQ, so initialize just on CPU 0
-  if (cpu != 0)
+  if (cpu != Cpu_number::boot_cpu())
     return;
 
   _glbl_timer.construct(Any_cpu);
@@ -30,14 +30,14 @@ Timer_tick::setup(unsigned cpu)
 
 IMPLEMENT
 void
-Timer_tick::enable(unsigned)
+Timer_tick::enable(Cpu_number)
 {
   _glbl_timer->chip()->unmask(_glbl_timer->pin());
 }
 
 IMPLEMENT
 void
-Timer_tick::disable(unsigned)
+Timer_tick::disable(Cpu_number)
 {
   _glbl_timer->chip()->mask(_glbl_timer->pin());
 }
index 80c095c0c9e227a987b03c89b561c23e3ac3799f..cf708d38391c905f49534d2102e85f84b9e24263 100644 (file)
@@ -1,6 +1,7 @@
 INTERFACE:
 
 #include "irq_chip.h"
+#include "thread.h"
 
 class Timer_tick : public Irq_base
 {
@@ -22,9 +23,9 @@ public:
       }
   }
 
-  static void setup(unsigned cpu);
-  static void enable(unsigned cpu);
-  static void disable(unsigned cpu);
+  static void setup(Cpu_number cpu);
+  static void enable(Cpu_number cpu);
+  static void disable(Cpu_number cpu);
 
 protected:
   static bool allocate_irq(Irq_base *irq, unsigned irqnum);
@@ -53,33 +54,43 @@ public:
 // ------------------------------------------------------------------------
 IMPLEMENTATION:
 
-#include "thread.h"
 #include "timer.h"
 
-PUBLIC static inline NEEDS["thread.h", "timer.h"]
+#include "kernel_console.h"
+#include "vkey.h"
+
+PRIVATE static inline NEEDS["thread.h", "timer.h", "kernel_console.h", "vkey.h"]
 void
-Timer_tick::handler_all(Irq_base *_s, Upstream_irq const *ui)
+Timer_tick::handle_timer(Irq_base *_s, Upstream_irq const *ui,
+                         Thread *t, Cpu_number cpu)
 {
   Timer_tick *self = nonull_static_cast<Timer_tick *>(_s);
   self->ack();
   ui->ack();
-  Thread *t = current_thread();
-  Timer::update_system_clock(t->cpu(true));
+  Timer::update_system_clock(cpu);
+  if (Config::esc_hack && cpu == Cpu_number::boot_cpu())
+    {
+      if (Kconsole::console()->char_avail() && !Vkey::check_())
+        kdb_ke("SERIAL_ESC");
+    }
   self->log_timer();
   t->handle_timer_interrupt();
 }
 
-PUBLIC static inline NEEDS["thread.h", "timer.h"]
+PUBLIC static inline NEEDS[Timer_tick::handle_timer]
+void
+Timer_tick::handler_all(Irq_base *_s, Upstream_irq const *ui)
+{
+  Thread *t = current_thread();
+  handle_timer(_s, ui, t, t->cpu(true));
+}
+
+PUBLIC static inline NEEDS[Timer_tick::handle_timer]
 void
 Timer_tick::handler_sys_time(Irq_base *_s, Upstream_irq const *ui)
 {
-  Timer_tick *self = nonull_static_cast<Timer_tick *>(_s);
-  self->ack();
-  ui->ack();
-  Timer::update_system_clock(0); // assume 0 to be the CPU that
-                                 // manages the system time
-  self->log_timer();
-  current_thread()->handle_timer_interrupt();
+  // assume the boot CPU to be the CPU that manages the system time
+  handle_timer(_s, ui, current_thread(), Cpu_number::boot_cpu());
 }
 
 PUBLIC static inline NEEDS["thread.h", "timer.h"]
index 9b22e6ede6b4a3e6a48d48eb5a99271cd0ca8217..552d32026f34c01ebe076350f0ef6bbd802a27b0 100644 (file)
@@ -19,7 +19,7 @@ DEFINE_PER_CPU Per_cpu<Timeout *> timeslice_timeout;
 DEFINE_PER_CPU static Per_cpu<Timeslice_timeout> the_timeslice_timeout(true);
 
 PUBLIC
-Timeslice_timeout::Timeslice_timeout(unsigned cpu)
+Timeslice_timeout::Timeslice_timeout(Cpu_number cpu)
 {
   timeslice_timeout.cpu(cpu) = this;
 }
index 85339f7ab5cc598092b550097b1510f2c3fdf1b8..95427cdac95f40cf7ed90b10d75e2254b73f71e8 100644 (file)
@@ -1,13 +1,15 @@
 IMPLEMENTATION [libuart]:
 
 #include "io_regblock.h"
+#include "kmem.h"
 
 EXTENSION class Uart
 {
   L4::Io_register_block_mmio _regs;
 };
 
-IMPLEMENT inline Uart::Uart() : _regs(base()) {}
+IMPLEMENT inline NEEDS["kmem.h"]
+Uart::Uart() : _regs(Kmem::mmio_remap(base())) {}
 
 PUBLIC bool Uart::startup()
 { return uart()->startup(&_regs); }
index ad8ef4e5609ee57e85b352a8bb849ff1d9e53927..cbc0b468fa769fce8f9ae02853fd08122d9990cd 100644 (file)
@@ -3,7 +3,9 @@
 shortcut.o:          $(TCBOFFSET)
 sighandler.o:        $(TCBOFFSET)
 entry.o:             $(TCBOFFSET)
+entry-mp.o:          $(TCBOFFSET)
 sys_call_page-asm.o: $(TCBOFFSET)
+tramp-mp.o:          $(TCBOFFSET)
 
 
 # Add future prerequisites somewhere among the list of libraries. You really
index b8d9026572c20e7b8e04b809c8a7752a4e265997..3dcaa739b117b69a0171a61746c90f17df977c6f 100644 (file)
@@ -20,7 +20,7 @@ private:
   static Mword _kern_ds asm ("KERN_DS");
   static Mword _kern_es asm ("KERN_ES");
 
-  int _tid;
+  Cpu_phys_id _tid;
 };
 
 // -----------------------------------------------------------------------
@@ -96,13 +96,14 @@ void
 Cpu::print() const
 {
   printf ("CPU[%u:%u]: %s (%X:%X:%X:%X) Model: %s at %llu MHz\n\n",
-          id(), phys_id(),
+          cxx::int_value<Cpu_number>(id()),
+          cxx::int_value<Cpu_phys_id>(phys_id()),
           vendor_str(), family(), model(), stepping(), brand(), model_str(),
           div32(frequency(), 1000000));
 }
 
 PUBLIC inline
-unsigned
+Cpu_phys_id
 Cpu::phys_id() const
 { return _tid; }
 
@@ -206,15 +207,15 @@ Cpu::get_gs()
 IMPLEMENTATION[ux && !mp]:
 
 PUBLIC static inline
-unsigned
+Cpu_phys_id
 Cpu::phys_id_direct()
-{ return 0; }
+{ return Cpu_phys_id(0); }
 
 // ------------------------------------------------------------------------
 IMPLEMENTATION[ux && mp]:
 
 PUBLIC static inline NEEDS["emulation.h"]
-unsigned
+Cpu_phys_id
 Cpu::phys_id_direct()
-{ return Emulation::gettid(); }
+{ return Cpu_phys_id(Emulation::gettid()); }
 
index 8b47c1c2a57058956402c26874bc6a94c52d0d1f..78b5d1808a22f93ace0f6862013b4c3d81056f1e 100644 (file)
@@ -13,7 +13,7 @@ IMPLEMENTATION[ux && fpu]:
 
 PRIVATE static
 void
-Fpu::init_xsave(unsigned)
+Fpu::init_xsave(Cpu_number)
 {}
 
 PRIVATE static
@@ -33,7 +33,7 @@ Fpu::save_state(Fpu_state *s)
 
   // FIXME: assume UP here (current_meme_space(0))
   ptrace(Cpu::boot_cpu()->features() & FEAT_FXSR ? PTRACE_GETFPXREGS : PTRACE_GETFPREGS,
-         Mem_space::current_mem_space(0)->pid(), NULL, s->state_buffer());
+         Mem_space::current_mem_space(Cpu_number::boot_cpu())->pid(), NULL, s->state_buffer());
 }
 
 /**
@@ -48,7 +48,7 @@ Fpu::restore_state(Fpu_state *s)
 
   // FIXME: assume UP here (current_meme_space(0))
   ptrace(Cpu::boot_cpu()->features() & FEAT_FXSR ? PTRACE_SETFPXREGS : PTRACE_SETFPREGS,
-         Mem_space::current_mem_space(0)->pid(), NULL, s->state_buffer());
+         Mem_space::current_mem_space(Cpu_number::boot_cpu())->pid(), NULL, s->state_buffer());
 }
 
 /**
index 45816af4ab05d9d9be1d9431d27da9dbe506635a..1586646d3ba0119eb8e55446df0449a627855b81 100644 (file)
@@ -7,18 +7,21 @@ int __libc_backend_outs(const char *s, size_t len)
   return write(1, s, len);
 }
 
-int __libc_backend_ins( char *s, size_t len )
+int __libc_backend_ins(char *s, size_t len)
 {
-  if(Console::stdin) {
-    size_t act = 0;
-    for(; act < len; act++) {
-      s[act]=Console::stdin->getchar();
-      if(s[act]=='\r') {
-       act++;
-       break;
-      }
-    }
-    return act;
-  } else
+  if (!Console::stdin)
     return 0;
+
+  size_t act = 0;
+  for (; act < len; act++)
+    {
+      s[act] = Console::stdin->getchar();
+      if (s[act] == '\r')
+        {
+          act++;
+          break;
+        }
+    }
+
+  return act;
 }
index 59a695509ab8f675414c540fbcbd9883ce28b03c..eebaee91c37fa06529db1d7aea996b464a14aafe 100644 (file)
@@ -40,7 +40,7 @@ Ipi::eoi(Message)
 
 PUBLIC static inline NEEDS[<cstdio>, "pic.h"]
 void
-Ipi::send(Message m, unsigned from_cpu, unsigned to_cpu)
+Ipi::send(Message m, Cpu_number from_cpu, Cpu_number to_cpu)
 {
   printf("Sending IPI:%d to cpu%d\n", m, _lcpu);
   Pic::send_ipi(_lcpu, m);
@@ -48,10 +48,10 @@ Ipi::send(Message m, unsigned from_cpu, unsigned to_cpu)
 
 PUBLIC static inline NEEDS[<cstdio>, "cpu.h", "pic.h"]
 void
-Ipi::bcast(Message m, unsigned from_cpu)
+Ipi::bcast(Message m, Cpu_number from_cpu)
 {
   printf("Bcast IPI:%d\n", m);
-  for (unsigned i = 0; i < Config::Max_num_cpus; ++i)
+  for (Cpu_number i = Cpu_number::first(); i < Config::max_num_cpus(); ++i)
     if (Cpu::online(i))
       Pic::send_ipi(i, m);
 }
index ef384dcdc3754eb119c0d5739b9400230065d458..1954259e7a3ac46f8f6fcd44d910af8906217cc8 100644 (file)
@@ -70,11 +70,9 @@ Kmem::init_mmu(Cpu const &boot_cpu)
   kdir = (Pdir*)alloc->alloc(Config::PAGE_SHIFT);
   memset (kdir, 0, Config::PAGE_SIZE);
 
-  Pdir::have_superpages(boot_cpu.superpages());
+  Pt_entry::have_superpages(boot_cpu.superpages());
   if (boot_cpu.features() & FEAT_PGE)
-    {
-      Pt_entry::enable_global();
-    }
+    Pt_entry::enable_global();
 
   // set up the kernel mapping for physical memory.  mark all pages as
   // referenced and modified (so when touching the respective pages
@@ -87,8 +85,8 @@ Kmem::init_mmu(Cpu const &boot_cpu)
   // descriptors later.)  (2) a one-to-one phys-to-virt mapping in the
   // kernel's page directory sometimes comes in handy
   kdir->map(0, Virt_addr(Mem_layout::Physmem), Virt_size(Mem_layout::pmem_size),
-      Pt_entry::Writable | Pt_entry::Referenced | Pt_entry::global(),
-      Pdir::super_level(), pdir_alloc(alloc));
+            Pt_entry::Writable | Pt_entry::Referenced | Pt_entry::global(),
+            Pt_entry::super_level(), false, pdir_alloc(alloc));
 
   // now switch to our new page table
   Emulation::set_pdir_addr (Mem_layout::pmem_to_phys (kdir));
@@ -101,29 +99,31 @@ Kmem::init_mmu(Cpu const &boot_cpu)
     {
       // can map as 4MB page because the cpu_page will land within a
       // 16-bit range from io_bitmap
-      *(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();
+      kdir->walk(Virt_addr(Mem_layout::Io_bitmap - Config::SUPERPAGE_SIZE),
+                 Pdir::Super_level, false, pdir_alloc(alloc)).
+        set_page(pmem_cpu_page & Config::SUPERPAGE_MASK,
+                 Pt_entry::Pse_bit
+                 | Pt_entry::Writable | Pt_entry::Referenced
+                 | Pt_entry::Dirty | Pt_entry::global());
 
       cpu_page_vm = (pmem_cpu_page & ~Config::SUPERPAGE_MASK)
-                 + (Mem_layout::Io_bitmap - Config::SUPERPAGE_SIZE);
+                    + (Mem_layout::Io_bitmap - Config::SUPERPAGE_SIZE);
     }
   else
     {
-      Pdir::Iter pt = kdir->walk(Virt_addr(Mem_layout::Io_bitmap - Config::PAGE_SIZE), 100, pdir_alloc(alloc));
+      auto pt = kdir->walk(Virt_addr(Mem_layout::Io_bitmap - Config::PAGE_SIZE),
+                           Pdir::Depth, false, pdir_alloc(alloc));
 
-      *pt.e = pmem_cpu_page | Pt_entry::Valid | Pt_entry::Writable
-                  | Pt_entry::Referenced | Pt_entry::Dirty
-                  | Pt_entry::global();
+      pt.set_page(pmem_cpu_page,
+                  Pt_entry::Writable
+                  | Pt_entry::Referenced | Pt_entry::Dirty
+                  | Pt_entry::global());
 
       cpu_page_vm = Mem_layout::Io_bitmap - Config::PAGE_SIZE;
     }
 
   if (mmap ((void *) cpu_page_vm, Config::PAGE_SIZE, PROT_READ 
-           | PROT_WRITE, MAP_SHARED | MAP_FIXED, Boot_info::fd(), pmem_cpu_page) 
+            | PROT_WRITE, MAP_SHARED | MAP_FIXED, Boot_info::fd(), pmem_cpu_page)
       == MAP_FAILED)
     printf ("CPU page mapping failed: %s\n", strerror (errno));
 
index 7a3e347224636487b79fd575938ab4dc34ceb90a..ba2f5eb7b28730bb7041c46d2de87ff1f34678b8 100644 (file)
@@ -11,9 +11,9 @@ IMPLEMENTATION[ux && mp]:
 #include "per_cpu_data_alloc.h"
 #include "usermode.h"
 
-int FIASCO_FASTCALL boot_ap_cpu(unsigned _cpu) __asm__("BOOT_AP_CPU");
+int FIASCO_FASTCALL boot_ap_cpu(Cpu_number _cpu) __asm__("BOOT_AP_CPU");
 
-int boot_ap_cpu(unsigned _cpu)
+int boot_ap_cpu(Cpu_number _cpu)
 {
   if (!Per_cpu_data_alloc::alloc(_cpu))
     {
index 3c4822618ef2669292ecfe21d1352d2795e2218c..cdb0e441c8e707a39e7df2616273ec2e50f67fc6 100644 (file)
@@ -135,11 +135,11 @@ Address const Mem_layout::kernel_trampoline_page =
 
 PUBLIC static inline
 User<Utcb>::Ptr &
-Mem_layout::user_utcb_ptr(unsigned cpu)
+Mem_layout::user_utcb_ptr(Cpu_number cpu)
 {
   // Allocate each CPUs utcb ptr in a different cacheline to avoid
   // false sharing.
-  return reinterpret_cast<User<Utcb>::Ptr*>(Utcb_ptr_page + (cpu << utcb_ptr_align))[0];
+  return reinterpret_cast<User<Utcb>::Ptr*>(Utcb_ptr_page + (cxx::int_value<Cpu_number>(cpu) << utcb_ptr_align))[0];
 }
 
 
index 6f4cccaf4b808d6460eccbe245f489bf7821896d..ae4b7339ebe8981ac10c7fc65b8772e343d1c2f4 100644 (file)
@@ -83,7 +83,7 @@ IMPLEMENT inline NEEDS [<asm/unistd.h>, <sys/mman.h>, "boot_info.h",
                         "cpu_lock.h", "lock_guard.h", "mem_layout.h",
                         "trampoline.h"]
 void
-Mem_space::page_map(Address phys, Address virt, Address size, unsigned attr)
+Mem_space::page_map(Address phys, Address virt, Address size, Attr attr)
 {
   auto guard = lock_guard(cpu_lock);
 
@@ -91,7 +91,7 @@ Mem_space::page_map(Address phys, Address virt, Address size, unsigned attr)
 
   *(trampoline + 1) = virt;
   *(trampoline + 2) = size;
-  *(trampoline + 3) = PROT_READ | (attr & Page_writable ? PROT_WRITE : 0);
+  *(trampoline + 3) = PROT_READ | (attr.rights & Page::Rights::W() ? PROT_WRITE : 0);
   *(trampoline + 4) = MAP_SHARED | MAP_FIXED;
   *(trampoline + 5) = Boot_info::fd();
 
@@ -141,9 +141,10 @@ T *
 Mem_space::user_to_kernel(T const *addr, bool write)
 {
   Phys_addr phys;
-  Addr virt = Addr::create((Address) addr);
-  unsigned attr, error = 0;
-  Size size;
+  Virt_addr virt = Virt_addr((Address) addr);
+  Attr attr;
+  unsigned error = 0;
+  Page_order size;
 
   for (;;)
     {
@@ -151,12 +152,12 @@ Mem_space::user_to_kernel(T const *addr, bool write)
       if (v_lookup(virt, &phys, &size, &attr))
         {
           // Add offset to frame
-          phys = phys | virt.offset(size);
+          phys = phys | cxx::get_lsb(virt, size);
 
           // See if we want to write and are not allowed to
           // Generic check because INTEL_PTE_WRITE == INTEL_PDE_WRITE
-          if (!write || (attr & Pt_entry::Writable))
-            return (T*)Mem_layout::phys_to_pmem(phys.value());
+          if (!write || (attr.rights & Page::Rights::W()))
+            return (T*)Mem_layout::phys_to_pmem(Phys_addr::val(phys));
 
           error |= PF_ERR_PRESENT;
         }
@@ -174,7 +175,7 @@ Mem_space::user_to_kernel(T const *addr, bool write)
       // Pretend open interrupts, we restore the current state afterwards.
       Cpu_lock::Status was_locked = cpu_lock.test();
 
-      thread_page_fault(virt.value(), error, 0, Proc::processor_state() | EFLAGS_IF, 0);
+      thread_page_fault(Virt_addr::val(virt), error, 0, Proc::processor_state() | EFLAGS_IF, 0);
 
       cpu_lock.set (was_locked);
     }
index d6ea74537d8f24982346260a42aad449ac80f696..90a33f980de50b657a76aa773a2d18bf9b6a3150 100644 (file)
@@ -43,11 +43,12 @@ INTERFACE[ux && mp]:
 EXTENSION class Pic
 {
 public:
-  static void send_ipi(unsigned _cpu, unsigned char data);
-  static bool setup_ipi(unsigned _cpu, int _tid);
+  static void send_ipi(Cpu_number _cpu, unsigned char data);
+  static bool setup_ipi(Cpu_number _cpu, int _tid);
 
 private:
-  static unsigned int ipi_fds[Config::Max_num_cpus];
+  typedef Per_cpu_array<unsigned> Fd_array;
+  static Fd_array ipi_fds;
 };
 
 // ------------------------------------------------------------------------
@@ -283,18 +284,18 @@ IMPLEMENTATION[ux && mp]:
 
 #include "ipi.h"
 
-unsigned int Pic::ipi_fds[Config::Max_num_cpus];
+Pic::Fd_array Pic::ipi_fds;
 
 IMPLEMENT
 void
-Pic::set_cpu(unsigned irq_num, unsigned cpu)
+Pic::set_cpu(unsigned irq_num, Cpu_number cpu)
 {
   printf("Pic::set_cpu(%d, %d)\n", irq_num, cpu);
 }
 
 IMPLEMENT static
 bool
-Pic::setup_ipi(unsigned _cpu, int _tid)
+Pic::setup_ipi(Cpu_number _cpu, int _tid)
 {
   int sockets[2], flags;
 
@@ -322,7 +323,7 @@ Pic::setup_ipi(unsigned _cpu, int _tid)
 
 IMPLEMENT
 void
-Pic::send_ipi(unsigned _cpu, unsigned char data)
+Pic::send_ipi(Cpu_number _cpu, unsigned char data)
 {
   if (ipi_fds[_cpu])
     if (write(ipi_fds[_cpu], &data, sizeof(data)) != sizeof(data))
index 642d0d74cf853bb85b764beb83b42d7e4235588e..c142d36ad7bea1565210807f39b537f897528760 100644 (file)
@@ -31,7 +31,7 @@ static void FIASCO_INIT
 startup_system1()
 {
   Kconsole::init();
-  Usermode::init(0);
+  Usermode::init(Cpu_number::boot_cpu());
   Boot_info::init();
   Config::init();
 }
@@ -46,9 +46,10 @@ startup_system2()
 
   // 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(Cpu_number::boot_cpu());
+  Per_cpu_data::run_ctors(Cpu_number::boot_cpu());
 
+  Mem_space::init_page_sizes();
   Kmem::init_mmu(*Cpu::boot_cpu());
   Kernel_task::init();         // enables current_mem_space()
   Kip_init::init_freq(*Cpu::boot_cpu());
@@ -62,10 +63,10 @@ startup_system2()
   Utcb_init::init();
   Pic::init();
   Irq_chip_ia32_pic::init();
-  Ipi::init(0);
+  Ipi::init(Cpu_number::boot_cpu());
   Idt::init();
-  Fpu::init(0);
-  Timer::init(0);
+  Fpu::init(Cpu_number::boot_cpu());
+  Timer::init(Cpu_number::boot_cpu());
   Fb::init();
   Net::init();
   Cpu::init_global_features();
index b78d35032f0b65562ab195b81e812db1df910563..728d3323b0ba081a077ceaccaf2ed7b0bb45e8ef 100644 (file)
@@ -110,11 +110,9 @@ Task::map_utcb_ptr_page()
 {
   //Mem_space::Status res =
        static_cast<Mem_space*>(this)->v_insert(
-           Mem_space::Phys_addr::create(Mem_layout::Utcb_ptr_frame),
-           Mem_space::Addr::create(Mem_layout::Utcb_ptr_page_user),
-           Mem_space::Size::create(Config::PAGE_SIZE),
-           Mem_space::Page_writable
-           | Mem_space::Page_user_accessible
-           | Mem_space::Page_cacheable);
+           Mem_space::Phys_addr(Mem_layout::Utcb_ptr_frame),
+           Virt_addr(Mem_layout::Utcb_ptr_page_user),
+           Mem_space::Page_order(Config::PAGE_SHIFT),
+           Mem_space::Attr(Page::Rights::URW()));
 }
 
index 05a7b15415961f09ab51efe0580ee389c660717c..01719c07b6aead3b1da1041894147c4633d3ef61 100644 (file)
@@ -93,13 +93,14 @@ Thread::call_nested_trap_handler(Trap_state *ts)
   // equiv of: return nested_trap_handler(ts) == 0 ? true : false;
 
   //static char nested_handler_stack [Config::PAGE_SIZE];
-  unsigned phys_cpu = Cpu::phys_id_direct();
-  unsigned log_cpu = Cpu::cpus.find_cpu(Cpu::By_phys_id(phys_cpu));
+  Cpu_phys_id phys_cpu = Cpu::phys_id_direct();
+  Cpu_number log_cpu = Cpu::cpus.find_cpu(Cpu::By_phys_id(phys_cpu));
 
-  if (log_cpu == ~0U)
+  if (log_cpu == Cpu_number::nil())
     {
-      printf("Trap on unknown CPU host-thread=%x\n", phys_cpu);
-      log_cpu = 0;
+      printf("Trap on unknown CPU host-thread=%x\n",
+             cxx::int_value<Cpu_phys_id>(phys_cpu));
+      log_cpu = Cpu_number::boot_cpu();
     }
 
   unsigned long &ntr = nested_trap_recover.cpu(log_cpu);
index 2bcce1bdd81468b9743973ba52872459b9f43688..334ce42bdde06e985b4b29a866396ec1b18a8c8b 100644 (file)
@@ -30,7 +30,7 @@ Timer::irq_mode() { return 0; }
 
 IMPLEMENT FIASCO_INIT_CPU
 void
-Timer::init(unsigned)
+Timer::init(Cpu_number)
 {
   if (Boot_info::irq0_disabled())
     return;
index 9c57df96d6f5b9667898d6a631704744c48f550f..b19ac6a8021f413b37cf2769856753c3901105fd 100644 (file)
@@ -181,16 +181,16 @@ Usermode::write_debug_register (pid_t pid, Mword reg, Mword value)
  */
 PRIVATE static
 void
-Usermode::kernel_entry (unsigned _cpu,
-                        struct ucontext *context,
-                        Mword trap,
-                        Mword xss,
-                        Mword esp,
-                        Mword efl,
-                        Mword xcs,
-                        Mword eip,
-                        Mword err,
-                        Mword cr2)
+Usermode::kernel_entry(Cpu_number _cpu,
+                       struct ucontext *context,
+                       Mword trap,
+                       Mword xss,
+                       Mword esp,
+                       Mword efl,
+                       Mword xcs,
+                       Mword eip,
+                       Mword err,
+                       Mword cr2)
 {
   Mword *kesp = (xcs & 3) == 3
               ? (Mword *) Cpu::cpus.cpu(_cpu).kernel_sp() - 5
@@ -281,8 +281,8 @@ Usermode::l4_syscall (Mword opcode)
 
 PRIVATE static inline NOEXPORT NEEDS["thread_state.h"]
 bool
-Usermode::user_exception (unsigned _cpu, pid_t pid, struct ucontext *context,
-                          struct user_regs_struct *regs)
+Usermode::user_exception(Cpu_number _cpu, pid_t pid, struct ucontext *context,
+                         struct user_regs_struct *regs)
 {
   Mword trap, error = 0, addr = 0;
 
@@ -382,9 +382,9 @@ Usermode::user_exception (unsigned _cpu, pid_t pid, struct ucontext *context,
 
 PRIVATE static inline NOEXPORT
 bool
-Usermode::user_emulation (unsigned _cpu, int stop, pid_t pid,
-                          struct ucontext *context,
-                          struct user_regs_struct *regs)
+Usermode::user_emulation(Cpu_number _cpu, int stop, pid_t pid,
+                         struct ucontext *context,
+                         struct user_regs_struct *regs)
 {
   Mword trap, error = 0;
 
@@ -451,8 +451,8 @@ Usermode::user_emulation (unsigned _cpu, int stop, pid_t pid,
  */
 PRIVATE static inline NOEXPORT
 void
-Usermode::iret_to_user_mode (unsigned _cpu,
-                             struct ucontext *context, Mword *kesp)
+Usermode::iret_to_user_mode(Cpu_number _cpu,
+                            struct ucontext *context, Mword *kesp)
 {
   struct user_regs_struct regs;
   int irq_pend;
@@ -581,7 +581,7 @@ Usermode::iret_to_kern_mode (struct ucontext *context, Mword *kesp)
  */
 PRIVATE static inline NOEXPORT
 void
-Usermode::iret (unsigned _cpu, struct ucontext *context)
+Usermode::iret(Cpu_number _cpu, struct ucontext *context)
 {
   Mword *kesp = (Mword *) context->uc_mcontext.gregs[REG_ESP];
 
@@ -609,7 +609,7 @@ Usermode::emu_handler (int, siginfo_t *, void *ctx)
   struct ucontext *context = reinterpret_cast<struct ucontext *>(ctx);
   unsigned int trap = context->uc_mcontext.gregs[REG_TRAPNO];
 
-  unsigned _cpu = Cpu::cpus.find_cpu(Cpu::By_phys_id(Cpu::phys_id_direct()));
+  Cpu_number _cpu = Cpu::cpus.find_cpu(Cpu::By_phys_id(Cpu::phys_id_direct()));
 
   if (trap == 0xd)     /* General protection fault */
     {
@@ -730,12 +730,12 @@ Usermode::set_signal (int sig)
 
 PUBLIC static FIASCO_INIT_CPU
 void
-Usermode::init(unsigned cpu)
+Usermode::init(Cpu_number cpu)
 {
   stack_t stack;
 
   /* We want signals, aka interrupts to be delivered on an alternate stack */
-  if (cpu == 0)
+  if (cpu == Cpu_number::boot_cpu())
     stack.ss_sp  = (void *) Mem_layout::phys_to_pmem
                                 (Mem_layout::Sigstack_cpu0_start_frame);
   else
@@ -753,7 +753,7 @@ Usermode::init(unsigned cpu)
 
   set_signal (SIGSEGV);
   set_signal (SIGIO);
-  if (cpu == 0)
+  if (cpu == Cpu_number::boot_cpu())
     set_signal (SIGINT);
   else
     signal (SIGINT, SIG_IGN);
index b4cfd7a61e76cf4a94cbe32e32916a188b0802ae..57d29600d03af38da865f8651ee789cb12dfb2b7 100644 (file)
@@ -208,7 +208,6 @@ Vkey::get()
 IMPLEMENTATION [!debug && serial]:
 
 #include "kernel_console.h"
-#include "kernel_uart.h"
 
 static Console *uart = Kconsole::console()->find_console(Console::UART);
 
index 96c9dbd2aef33e1c5a8004b96af8f601c5e45c9d..18318830de364e8dddd39360e5cc336d749c3de4 100644 (file)
@@ -99,14 +99,14 @@ Vlog::log_string(Syscall_frame *f, Utcb const *u)
 
 PRIVATE inline NOEXPORT
 L4_msg_tag
-Vlog::get_input(Mword rights, Syscall_frame *f, Utcb *u)
+Vlog::get_input(L4_fpage::Rights rights, Syscall_frame *f, Utcb *u)
 {
   (void)f;
 
   if (!have_receive(u))
     return commit_result(0);
 
-  if (!(rights & L4_fpage::X))
+  if (!(rights & L4_fpage::Rights::X()))
     return commit_result(-L4_err::EPerm);
 
   char *buffer = reinterpret_cast<char *>(&u->values[1]);
@@ -163,7 +163,7 @@ Vlog::icu_bind_irq(Irq *irq_o, unsigned irqnum)
 
 PRIVATE inline NOEXPORT
 L4_msg_tag
-Vlog::set_attr(Mword, Syscall_frame const *, Utcb const *u)
+Vlog::set_attr(L4_fpage::Rights, Syscall_frame const *, Utcb const *u)
 {
   _i_flags = u->values[1];
   _o_flags = u->values[2] | F_ONLCR;
@@ -179,7 +179,7 @@ Vlog::set_attr(Mword, Syscall_frame const *, Utcb const *u)
 
 PRIVATE inline NOEXPORT
 L4_msg_tag
-Vlog::get_attr(Mword, Syscall_frame *, Utcb *u)
+Vlog::get_attr(L4_fpage::Rights, Syscall_frame *, Utcb *u)
 {
   if (!have_receive(u))
     return commit_result(0);
@@ -213,7 +213,7 @@ Vlog::icu_get_info(Mword *features, Mword *num_irqs, Mword *num_msis)
 
 PUBLIC
 L4_msg_tag
-Vlog::kinvoke(L4_obj_ref ref, Mword rights, Syscall_frame *f,
+Vlog::kinvoke(L4_obj_ref ref, L4_fpage::Rights rights, Syscall_frame *f,
               Utcb const *r_msg, Utcb *s_msg)
 {
   L4_msg_tag const t = f->tag();
index 5c8d029ea07d30acd90169198222089664d9751a..207ead3ccb0b204b9584da686cd64740049842bc 100644 (file)
@@ -215,6 +215,7 @@ SECTIONS {
   .bss : AT (ADDR(.bss) - phys_offset) {
     PROVIDE(__bss_start = .);
     . = ALIGN(4);
+    *(.bss.kernel_page_dir)
     _per_cpu_ctor_data_start = .;
     KEEP (*(.bss.per_cpu_ctor_data))
     _per_cpu_ctor_data_end = .;
index 983ed2995869ff0b158966f9d89e497a912195e9..5ad6dd6e9dbf4c8180d4debce9d239c8bb8fcb73 100644 (file)
@@ -109,13 +109,3 @@ mp_cas2_arch (char *p, Mword o1, Mword o2, Mword n1, Mword n2)
 
   return ret;
 }
-
-inline
-bool
-tas (Mword *l)
-{
-  Mword tmp;
-  asm volatile ("xchg %0, %1" : "=r"(tmp) : "m"(*l), "0"(1) : "memory");
-  return tmp;
-}
-
index a0eb709ac7d8698747baddbc259896c6eb34bab8..ed6e713af5cdf00d0a0732e32558a13e2b7c2557 100644 (file)
@@ -2,82 +2,67 @@ IMPLEMENTATION [arm]:
 
 inline
 bool
-cas_unsafe( Mword *ptr, Mword oldval, Mword newval )
+cas_unsafe(Mword *ptr, Mword oldval, Mword newval)
 {
   Mword ret;
-  asm volatile ( "    mrs    r5, cpsr    \n"
-                "    mov    r6,r5       \n"
-                "    orr    r6,r6,#0x80 \n"
-                "    msr    cpsr_c, r6  \n"
-                "    \n"
-                "    ldr    r6, [%1]    \n"
-                "    cmp    r6, %2      \n"
-                "    streq  %3, [%1]    \n"
-                "    moveq  %0, #1      \n"
-                "    movne  %0, #0      \n"
-                "    msr    cpsr_c, r5  \n"
-                : "=r"(ret)
-                : "r"(ptr), "r"(oldval), "r"(newval)
-                : "r5", "r6", "memory"
-                );
+  asm volatile("    mrs    r5, cpsr    \n"
+               "    mov    r6,r5       \n"
+               "    orr    r6,r6,#0xc0 \n"
+               "    msr    cpsr_c, r6  \n"
+               ""
+               "    ldr    r6, [%1]    \n"
+               "    cmp    r6, %2      \n"
+               "    streq  %3, [%1]    \n"
+               "    moveq  %0, #1      \n"
+               "    movne  %0, #0      \n"
+               "    msr    cpsr_c, r5  \n"
+               : "=r" (ret)
+               : "r"  (ptr), "r" (oldval), "r" (newval)
+               : "r5", "r6", "memory");
   return ret;
 }
 
 inline
 bool
-cas2_unsafe( Mword *ptr, Mword *oldval, Mword *newval )
+cas2_unsafe(Mword *ptr, Mword *oldval, Mword *newval)
 {
   Mword ret;
-  asm volatile ( "    mrs    r5, cpsr    \n"
-                "    mov    r6,r5       \n"
-                "    orr    r6,r6,#128  \n"
-                "    msr    cpsr_c, r6  \n"
-                "    \n"
-                "    ldr    r6, [%1]    \n"
-                "    ldr    r7, [%1,#4] \n"
-                "    cmp    r6, %2      \n"
-                "    cmpeq  r7, %3      \n"
-                "    streq  %4, [%1]    \n"
-                "    streq  %5, [%1,#4] \n"
-                "    moveq  %0, #1      \n"
-                "    movne  %0, #0      \n"
-                "    msr    cpsr_c, r5  \n"
-                : "=r"(ret)
-                : "r"(ptr), "r"(*oldval), "r"(*(oldval+1)), "r"(*newval),
-                  "r"(*(newval+1))
-                : "r5", "r6", "r7", "memory"
-                );
-  return ret;
-}
-
-inline
-bool
-tas (Mword *l)
-{
-  Mword ret;
-  asm volatile ( "    swp %0, %2, [%1] \n "
-                : "=&r"(ret)
-                : "r"(l), "r" (1)
-                : "memory"
-                );
+  asm volatile("    mrs    r5, cpsr    \n"
+               "    mov    r6,r5       \n"
+               "    orr    r6,r6,#0xc0 \n"
+               "    msr    cpsr_c, r6  \n"
+               ""
+               "    ldr    r6, [%1]    \n"
+               "    ldr    r7, [%1,#4] \n"
+               "    cmp    r6, %2      \n"
+               "    cmpeq  r7, %3      \n"
+               "    streq  %4, [%1]    \n"
+               "    streq  %5, [%1,#4] \n"
+               "    moveq  %0, #1      \n"
+               "    movne  %0, #0      \n"
+               "    msr    cpsr_c, r5  \n"
+               : "=r" (ret)
+               : "r"  (ptr), "r" (*oldval),
+                 "r"  (*(oldval + 1)), "r" (*newval),
+                 "r"  (*(newval + 1))
+               : "r5", "r6", "r7", "memory");
   return ret;
 }
 
 inline
 void
-atomic_and (Mword *l, Mword mask)
+atomic_and(Mword *l, Mword mask)
 {
   Mword old;
   do { old = *l; }
-  while ( !cas (l, old, old & mask));
+  while (!cas(l, old, old & mask));
 }
 
 inline
 void
-atomic_or (Mword *l, Mword bits)
+atomic_or(Mword *l, Mword bits)
 {
   Mword old;
   do { old = *l; }
-  while ( !cas (l, old, old | bits));
+  while (!cas(l, old, old | bits));
 }
-
index ff4d5b10585baa20405aa9794c0f47e1e15712f4..3f8ddb83f14443b156e279eca1b3130b97a8c2dc 100644 (file)
@@ -169,14 +169,6 @@ mp_cas2_arch(char *m, Mword o1, Mword o2, Mword n1, Mword n2)
 
   return ret;
 }
-inline
-bool
-tas(Mword *l)
-{
-  Mword tmp;
-  asm volatile ("xchg %0, %1" : "=r"(tmp) : "m"(*l), "0"(1) : "memory");
-  return tmp;
-}
 
 //---------------------------------------------------------------------------
 IMPLEMENTATION[(ppc32 && !mp) || (sparc && !mp) || (arm && !armv6plus)]:
diff --git a/kernel/fiasco/src/lib/libk/cxx/bitfield b/kernel/fiasco/src/lib/libk/cxx/bitfield
new file mode 100644 (file)
index 0000000..6d79464
--- /dev/null
@@ -0,0 +1,248 @@
+// vi: ft=cpp
+/*
+ * (c) 2012 Alexander Warg <warg@os.inf.tu-dresden.de>,
+ *     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 "type_list"
+
+/** \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<typename T, unsigned LSB, unsigned MSB>
+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<unsigned BITS> 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<Unsigned_types, Cmp>::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<Bits>::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<Bits + Lsb>::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<TT>
+  {
+  public:
+    Value(TT t) : Value_base<TT>(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<TT>
+  {
+  public:
+    Value_unshifted(TT t) : Value_base<TT>(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<T&> Ref;
+  /** Value type to access the bits inside a raw bit field. */
+  typedef Value<T const> Val;
+
+  /** Reference type to access the bits inside a raw bit field (in place). */
+  typedef Value_unshifted<T&> Ref_unshifted;
+  /** Value type to access the bits inside a raw bit field (in place). */
+  typedef Value_unshifted<T const> 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<decltype(data_member), LSB, MSB> 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<decltype(data_member), LSB, MSB> 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/cxx/bits/list_basics.h b/kernel/fiasco/src/lib/libk/cxx/bits/list_basics.h
new file mode 100644 (file)
index 0000000..cfb2728
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * (c) 2011 Alexander Warg <warg@os.inf.tu-dresden.de>
+ *     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
+
+namespace cxx { namespace Bits {
+
+template< typename T >
+class List_iterator_end_ptr
+{
+private:
+  template< typename U > friend class Basic_list;
+  static void *_end;
+};
+
+template< typename T >
+void *List_iterator_end_ptr<T>::_end;
+
+template< typename VALUE_T, typename TYPE >
+struct Basic_list_policy
+{
+  typedef VALUE_T *Value_type;
+  typedef VALUE_T const *Const_value_type;
+  typedef TYPE **Type;
+  typedef TYPE *Const_type;
+  typedef TYPE *Head_type;
+
+  static Type next(Type c) { return &(*c)->_n; }
+  static Const_type next(Const_type c) { return c->_n; }
+};
+
+template< typename POLICY >
+class Basic_list
+{
+  Basic_list(Basic_list const &) = delete;
+  void operator = (Basic_list const &) = delete;
+
+public:
+  typedef typename POLICY::Value_type Value_type;
+  typedef typename POLICY::Const_value_type Const_value_type;
+
+  class End_iterator {};
+
+  class Iterator
+  {
+  private:
+    typedef typename POLICY::Type Internal_type;
+
+  public:
+    typedef typename POLICY::Value_type value_type;
+    typedef typename POLICY::Value_type Value_type;
+
+    Value_type operator * () const { return static_cast<Value_type>(*_c); }
+    Value_type operator -> () const { return static_cast<Value_type>(*_c); }
+    Iterator operator ++ () { _c = POLICY::next(_c); return *this; }
+
+    bool operator == (End_iterator const &) const { return *_c == 0; }
+    bool operator != (End_iterator const &) const { return *_c != 0; }
+    bool operator == (Iterator const &o) const { return *_c == *o._c; }
+    bool operator != (Iterator const &o) const { return !operator == (o); }
+
+    Iterator() {}
+    Iterator(End_iterator const &) : _c(__end()) {}
+
+  private:
+    friend class Basic_list;
+    static Internal_type __end()
+    {
+      union X { Internal_type l; void **v; } z;
+      z.v = &Bits::List_iterator_end_ptr<void>::_end;
+      return z.l;
+    }
+
+    explicit Iterator(Internal_type i) : _c(i) {}
+
+    Internal_type _c;
+  };
+
+  class Const_iterator
+  {
+  private:
+    typedef typename POLICY::Const_type Internal_type;
+
+  public:
+    typedef typename POLICY::Value_type value_type;
+    typedef typename POLICY::Value_type Value_type;
+
+    Value_type operator * () const { return static_cast<Value_type>(_c); }
+    Value_type operator -> () const { return static_cast<Value_type>(_c); }
+    Const_iterator operator ++ () { _c = POLICY::next(_c); return *this; }
+
+    bool operator == (End_iterator const &) const { return _c == 0; }
+    bool operator != (End_iterator const &) const { return _c != 0; }
+    bool operator == (Const_iterator const &o) const { return _c == o._c; }
+    bool operator != (Const_iterator const &o) const { return !operator == (o); }
+
+    Const_iterator() {}
+    Const_iterator(End_iterator const &) : _c(0) {}
+    Const_iterator(Iterator const &o) : _c(*o) {}
+
+  private:
+    friend class Basic_list;
+
+    explicit Const_iterator(Internal_type i) : _c(i) {}
+
+    Internal_type _c;
+  };
+
+  // BSS allocation
+  explicit Basic_list(bool) {}
+  Basic_list() : _f(0) {}
+
+  Basic_list(Basic_list &&o) : _f(o._f)
+  {
+    o.clear();
+  }
+
+  Basic_list &operator = (Basic_list &&o)
+  {
+    _f = o._f;
+    o.clear();
+    return *this;
+  }
+
+  bool empty() const { return !_f; }
+  Value_type front() const { return static_cast<Value_type>(_f); }
+
+  void clear() { _f = 0; }
+
+  Iterator begin() { return Iterator(&_f); }
+  Const_iterator begin() const { return Const_iterator(_f); }
+  static Const_iterator iter(Const_value_type c) { return Const_iterator(c); }
+  static End_iterator end() { return End_iterator(); }
+
+protected:
+  static typename POLICY::Type __get_internal(Iterator const &i) { return i._c; }
+  static Iterator __iter(typename POLICY::Type c) { return Iterator(c); }
+
+  typename POLICY::Head_type _f;
+};
+
+}}
+
diff --git a/kernel/fiasco/src/lib/libk/cxx/cxx_int b/kernel/fiasco/src/lib/libk/cxx/cxx_int
new file mode 100644 (file)
index 0000000..5ae8e56
--- /dev/null
@@ -0,0 +1,346 @@
+// vi:ft=cpp
+
+#pragma once
+#include "type_traits"
+
+namespace cxx {
+
+/**
+ * \brief Get native interger value of \a v.
+ *
+ * Currently do this for native integers direcly.
+ */
+template< typename TYPE, typename = typename cxx::enable_if<cxx::is_integral<TYPE>::value>::type > inline
+TYPE
+int_value(typename cxx::idendity<TYPE>::type const &v)
+{ return v; }
+
+/**
+ * \brief Get native interger value of \a v.
+ *
+ * Get the native value of the embedded integer of TYPE.
+ */
+template< typename TYPE > inline
+typename TYPE::Value
+int_value(TYPE const &v)
+{ return TYPE::val(v); }
+
+
+/** \brief Base class for type-safe integers.
+ *
+ * This class actually handles comparison and the storage for the integer value.
+ */
+template< typename VALUE_T, typename TYPE_T >
+class int_base
+{
+public:
+  typedef VALUE_T Value;
+  typedef TYPE_T  Target;
+  typedef int_base<VALUE_T, TYPE_T> Type;
+
+  int_base() = default;
+  explicit int_base(Value v) : _v(v) {}
+
+  TYPE_T operator = (TYPE_T const &o)
+  { _v = o._v; return *static_cast<TYPE_T*>(this); }
+
+  friend inline bool operator < (Type const &l, Type const &r) { return l._v < r._v; }
+  friend inline bool operator > (Type const &l, Type const &r) { return l._v > r._v; }
+  friend inline bool operator <= (Type const &l, Type const &r) { return l._v <= r._v; }
+  friend inline bool operator >= (Type const &l, Type const &r) { return l._v >= r._v; }
+  friend inline bool operator == (Type const &l, Type const &r) { return l._v == r._v; }
+  friend inline bool operator != (Type const &l, Type const &r) { return l._v != r._v; }
+
+  static Value val(Type const &t) { return t._v; }
+  static Value val(TYPE_T const &t) { return t._v; }
+  static Value &val(Type &t) { return t._v; }
+  static Value &val(TYPE_T &t) { return t._v; }
+
+protected:
+  Value _v;
+};
+
+
+/**
+ * Increment and decrement mixin for int_base.
+ */
+template< typename TYPE_T >
+struct int_inc_ops
+{
+  friend inline TYPE_T &operator ++ (TYPE_T &l)
+  { ++TYPE_T::val(l); return l; }
+
+  friend inline TYPE_T operator ++ (TYPE_T &l, int)
+  { TYPE_T old = l; TYPE_T::val(l)++; return old; }
+
+  friend inline TYPE_T &operator -- (TYPE_T &l)
+  { --TYPE_T::val(l); return l; }
+
+  friend inline TYPE_T operator -- (TYPE_T &l, int)
+  { TYPE_T old = l; TYPE_T::val(l)--; return old; }
+};
+
+
+/**
+ * Addition and substraction mixin for int_base.
+ *
+ * This version is actually used if there is a specific difference type
+ * for the integer type.
+ */
+template< typename TYPE_T, typename DIFF_T = TYPE_T >
+struct int_diff_ops : int_inc_ops<TYPE_T>
+{
+  typedef DIFF_T Diff_type;
+
+  friend inline DIFF_T operator - (TYPE_T const &l, TYPE_T const &r)
+  { return DIFF_T(cxx::int_value<TYPE_T>(l) - cxx::int_value<TYPE_T>(r)); }
+
+  friend inline TYPE_T operator + (TYPE_T const &l, DIFF_T const &r)
+  { return TYPE_T(cxx::int_value<TYPE_T>(l) + cxx::int_value<DIFF_T>(r)); }
+
+  friend inline TYPE_T operator + (DIFF_T const &l, TYPE_T const &r)
+  { return TYPE_T(cxx::int_value<DIFF_T>(l) + cxx::int_value<TYPE_T>(r)); }
+
+  friend inline TYPE_T &operator += (TYPE_T &l, DIFF_T const &r)
+  { TYPE_T::val(l) += cxx::int_value<DIFF_T>(r); return l; }
+
+  friend inline TYPE_T operator - (TYPE_T const &l, DIFF_T const &r)
+  { return TYPE_T(cxx::int_value<TYPE_T>(l) - cxx::int_value<DIFF_T>(r)); }
+
+  friend inline TYPE_T &operator -= (TYPE_T &l, DIFF_T const &r)
+  { TYPE_T::val(l) -= cxx::int_value<DIFF_T>(r); return l; }
+};
+
+
+/**
+ * Addition and substraction mixin for int_base.
+ *
+ * This version is actually used if there is no specific difference type
+ * for the integer type.
+ */
+template<typename TYPE_T>
+struct int_diff_ops<TYPE_T, TYPE_T> : int_inc_ops<TYPE_T>
+{
+  typedef TYPE_T Diff_type;
+
+  friend inline TYPE_T operator - (TYPE_T const &l, TYPE_T const &r)
+  { return TYPE_T(cxx::int_value<TYPE_T>(l) - cxx::int_value<TYPE_T>(r)); }
+
+  friend inline TYPE_T &operator -= (TYPE_T &l, TYPE_T const &r)
+  { TYPE_T::val(l) -= cxx::int_value<TYPE_T>(r); return l; }
+
+  friend inline TYPE_T operator + (TYPE_T const &l, TYPE_T const &r)
+  { return TYPE_T(cxx::int_value<TYPE_T>(l) + cxx::int_value<TYPE_T>(r)); }
+
+  friend inline TYPE_T &operator += (TYPE_T &l, TYPE_T const &r)
+  { TYPE_T::val(l) += cxx::int_value<TYPE_T>(r); return l; }
+};
+
+/**
+ * Basic bitwise operations for int_base types.
+ */
+template<typename TYPE_T>
+struct int_bit_ops_base
+{
+  friend inline TYPE_T operator | (TYPE_T const &l, TYPE_T const &r)
+  { return TYPE_T(cxx::int_value<TYPE_T>(l) | cxx::int_value<TYPE_T>(r)); }
+
+  friend inline TYPE_T &operator |= (TYPE_T &l, TYPE_T const &r)
+  { TYPE_T::val(l) |= cxx::int_value<TYPE_T>(r); return l; }
+
+  friend inline TYPE_T operator & (TYPE_T const &l, TYPE_T const &r)
+  { return TYPE_T(cxx::int_value<TYPE_T>(l) & cxx::int_value<TYPE_T>(r)); }
+
+  friend inline TYPE_T &operator &= (TYPE_T &l, TYPE_T const &r)
+  { TYPE_T::val(l) &= cxx::int_value<TYPE_T>(r); return l; }
+
+  friend inline TYPE_T operator ^ (TYPE_T const &l, TYPE_T const &r)
+  { return TYPE_T(cxx::int_value<TYPE_T>(l) ^ cxx::int_value<TYPE_T>(r)); }
+
+  friend inline TYPE_T &operator ^= (TYPE_T &l, TYPE_T const &r)
+  { TYPE_T::val(l) ^= cxx::int_value<TYPE_T>(r); return l; }
+
+  friend inline TYPE_T operator ~ (TYPE_T const &l)
+  { return TYPE_T(~cxx::int_value<TYPE_T>(l)); }
+};
+
+/**
+ * Bitwise mixin for int_base.
+ *
+ * This version is actually used if there is a specific difference type
+ * for the integer type.
+ */
+template<typename TYPE_T, typename DIFF_T = TYPE_T>
+struct int_bit_ops : int_bit_ops_base<TYPE_T>
+{
+  friend inline TYPE_T operator | (TYPE_T const &l, DIFF_T const &r)
+  { return TYPE_T(cxx::int_value<TYPE_T>(l) | cxx::int_value<DIFF_T>(r)); }
+
+  friend inline TYPE_T operator | (DIFF_T const &l, TYPE_T const &r)
+  { return TYPE_T(cxx::int_value<DIFF_T>(l) | cxx::int_value<TYPE_T>(r)); }
+
+  friend inline TYPE_T &operator |= (TYPE_T &l, DIFF_T const &r)
+  { TYPE_T::val(l) |= cxx::int_value<DIFF_T>(r); return l; }
+
+  friend inline DIFF_T operator & (DIFF_T const &l, TYPE_T const &r)
+  { return DIFF_T(cxx::int_value<DIFF_T>(l) & cxx::int_value<TYPE_T>(r)); }
+
+  friend inline DIFF_T operator & (TYPE_T const &l, DIFF_T const &r)
+  { return DIFF_T(cxx::int_value<TYPE_T>(l) & cxx::int_value<DIFF_T>(r)); }
+
+  friend inline TYPE_T &operator &= (TYPE_T &l, DIFF_T const &r)
+  { TYPE_T::val(l) &= cxx::int_value<DIFF_T>(r); return l; }
+
+  friend inline TYPE_T operator ^ (DIFF_T const &l, TYPE_T const &r)
+  { return TYPE_T(cxx::int_value<DIFF_T>(l) ^ cxx::int_value<TYPE_T>(r)); }
+
+  friend inline TYPE_T operator ^ (TYPE_T const &l, DIFF_T const &r)
+  { return TYPE_T(cxx::int_value<TYPE_T>(l) ^ cxx::int_value<DIFF_T>(r)); }
+
+  friend inline TYPE_T &operator ^= (TYPE_T &l, DIFF_T const &r)
+  { TYPE_T::val(l) ^= cxx::int_value<DIFF_T>(r); return l; }
+};
+
+/**
+ * Bitwise mixin for int_base.
+ *
+ * This version is actually used if there is no specific difference type
+ * for the integer type.
+ */
+template<typename TYPE_T>
+struct int_bit_ops<TYPE_T, TYPE_T> : int_bit_ops_base<TYPE_T> {};
+
+/**
+ * Shift mixin for int_base.
+ */
+template<typename TYPE_T, typename ORDER_T>
+struct int_shift_ops
+{
+  typedef ORDER_T Order_type;
+
+  friend inline TYPE_T operator << (TYPE_T const &l, ORDER_T const &r)
+  { return TYPE_T(cxx::int_value<TYPE_T>(l) << cxx::int_value<ORDER_T>(r)); }
+
+  friend inline TYPE_T &operator <<= (TYPE_T &l, ORDER_T const &r)
+  { TYPE_T::val(l) <<= cxx::int_value<ORDER_T>(r); return l; }
+
+  friend inline TYPE_T operator >> (TYPE_T const &l, ORDER_T const &r)
+  { return TYPE_T(cxx::int_value<TYPE_T>(l) >> cxx::int_value<ORDER_T>(r)); }
+
+  friend inline TYPE_T &operator >>= (TYPE_T &l, ORDER_T const &r)
+  { TYPE_T::val(l) >>= cxx::int_value<ORDER_T>(r); return l; }
+};
+
+template<typename TYPE_T>
+struct int_null_chk
+{
+  friend inline bool operator ! (TYPE_T const &v)
+  { return cxx::int_value<TYPE_T>(v) == 0; }
+
+private:
+  struct Type_conversion_error;
+
+public:
+  operator Type_conversion_error const * () const
+  { return (Type_conversion_error const *)(cxx::int_value<TYPE_T>(*static_cast<TYPE_T const *>(this)) != 0 ? 1L : 0L); }
+};
+
+template<typename VALUE_T, typename T>
+struct int_type : int_base<VALUE_T, int_type<VALUE_T, T> >, int_diff_ops<int_type<VALUE_T, T> >
+{
+  typedef VALUE_T Value;
+  int_type() = default;
+  explicit int_type(VALUE_T v) : int_base<VALUE_T, int_type<VALUE_T, T> >(v) {}
+};
+
+template<typename VALUE_T, typename T, typename ORDER_T>
+struct int_type_order
+: int_base<VALUE_T, int_type_order<VALUE_T, T, ORDER_T> >,
+  int_diff_ops<int_type_order<VALUE_T, T, ORDER_T> >,
+  int_shift_ops<int_type_order<VALUE_T, T, ORDER_T>, ORDER_T>,
+  int_bit_ops<int_type_order<VALUE_T, T, ORDER_T> >
+{
+  typedef VALUE_T Value;
+  int_type_order() = default;
+  explicit int_type_order(VALUE_T v) : int_base<VALUE_T, int_type_order<VALUE_T, T, ORDER_T> >(v) {}
+};
+
+template<typename VALUE_T, typename T, typename DIFF_T, typename ORDER_T>
+struct int_type_full
+: int_base<VALUE_T, int_type_full<VALUE_T, T, DIFF_T, ORDER_T> >,
+  int_diff_ops<int_type_full<VALUE_T, T, DIFF_T, ORDER_T>, DIFF_T>,
+  int_shift_ops<int_type_full<VALUE_T, T, DIFF_T, ORDER_T>, ORDER_T>,
+  int_bit_ops<int_type_full<VALUE_T, T, DIFF_T, ORDER_T>, DIFF_T>
+{
+  typedef VALUE_T Value;
+  int_type_full() = default;
+  explicit int_type_full(VALUE_T v) : int_base<VALUE_T, int_type_full<VALUE_T, T, DIFF_T, ORDER_T> >(v) {}
+};
+
+template<typename VALUE_T, typename TYPE_T, typename DIFF_T = TYPE_T>
+struct int_type_base : int_base<VALUE_T, TYPE_T>, int_diff_ops<TYPE_T, DIFF_T>
+{
+  int_type_base() = default;
+  explicit int_type_base(VALUE_T v) : int_base<VALUE_T, TYPE_T>(v) {}
+};
+
+template<typename VALUE_T, typename TYPE_T, typename ORDER_T, typename DIFF_T = TYPE_T>
+struct int_type_order_base : int_base<VALUE_T, TYPE_T>, int_diff_ops<TYPE_T, DIFF_T>,
+  int_shift_ops<TYPE_T, ORDER_T>, int_bit_ops<TYPE_T, DIFF_T>
+{
+  int_type_order_base() = default;
+  explicit int_type_order_base(VALUE_T v) : int_base<VALUE_T, TYPE_T>(v) {}
+};
+
+template< typename TYPE, typename ORDER > inline
+TYPE
+mask_lsb(TYPE const &v, ORDER const &o)
+{ return v & (TYPE(~0) << o); }
+
+template< typename TYPE, typename ORDER > inline
+typename TYPE::Diff_type
+get_lsb(TYPE const &v, ORDER const &o)
+{ return v & ~(typename TYPE::Diff_type(~0) << o); }
+
+template< typename TYPE, typename ORDER,
+  typename = typename cxx::enable_if<cxx::is_integral<TYPE>::value>::type > inline
+TYPE
+get_lsb(TYPE const &v, ORDER const &o)
+{ return v & ~(TYPE(~0) << o); }
+
+/**
+ * \brief Array indexed by type-safe integers.
+ */
+template< typename VALUE, typename INDEX, unsigned long SIZE >
+class array
+{
+public:
+  typedef VALUE *iterator;
+  typedef VALUE const *const_iterator;
+
+  VALUE &operator [] (INDEX const &cpu)
+  { return _d[cxx::int_value<INDEX>(cpu)]; }
+
+  VALUE const &operator [] (INDEX const &cpu) const
+  { return _d[cxx::int_value<INDEX>(cpu)]; }
+
+  iterator begin() { return &_d[0]; }
+  iterator end() { return &_d[SIZE]; }
+
+  const_iterator begin() const { return &_d[0]; }
+  const_iterator end() const { return &_d[SIZE]; }
+
+  static INDEX size() { return INDEX(SIZE); }
+
+private:
+  VALUE _d[SIZE];
+};
+
+template< typename T >
+struct underlying_type<T, typename cxx::enable_if<!cxx::is_same<typename T::Value, void>::value>::type>
+{
+  typedef typename T::Value type;
+};
+
+} // namespace cxx
+
diff --git a/kernel/fiasco/src/lib/libk/cxx/dlist b/kernel/fiasco/src/lib/libk/cxx/dlist
new file mode 100644 (file)
index 0000000..81a16da
--- /dev/null
@@ -0,0 +1,270 @@
+// vi:ft=cpp
+/*
+ * (c) 2011 Alexander Warg <warg@os.inf.tu-dresden.de>
+ *     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
+
+namespace cxx {
+
+class D_list_item
+{
+public:
+  D_list_item() : _dli_next(0) {}
+private:
+  friend struct D_list_item_policy;
+
+  D_list_item(D_list_item const &);
+  void operator = (D_list_item const &);
+
+  D_list_item *_dli_next, *_dli_prev;
+};
+
+struct D_list_item_policy
+{
+  typedef D_list_item Item;
+  static D_list_item *&prev(D_list_item *e) { return e->_dli_prev; }
+  static D_list_item *&next(D_list_item *e) { return e->_dli_next; }
+};
+
+template< typename T >
+struct Sd_list_head_policy
+{
+  typedef T *Head_type;
+  static T *head(Head_type h) { return h; }
+  static void set_head(Head_type &h, T *v) { h = v; }
+};
+
+template<
+  typename T,
+  typename C = D_list_item_policy
+>
+class D_list_cyclic
+{
+protected:
+  template< typename VALUE, typename ITEM >
+  class __Iterator
+  {
+  public:
+    typedef VALUE *Value_type;
+    typedef VALUE *value_type;
+
+    __Iterator() {}
+
+    bool operator == (__Iterator const &o) const
+    { return _c == o._c; }
+
+    bool operator != (__Iterator const &o) const
+    { return _c != o._c; }
+
+    __Iterator &operator ++ ()
+    {
+      _c = C::next(_c);
+      return *this;
+    }
+
+    __Iterator &operator -- ()
+    {
+      _c = C::prev(_c);
+      return *this;
+    }
+
+    Value_type operator * () const { return static_cast<Value_type>(_c); }
+    Value_type operator -> () const { return static_cast<Value_type>(_c); }
+
+  private:
+    friend class D_list_cyclic;
+
+    explicit __Iterator(ITEM *s) : _c(s) {}
+
+    ITEM *_c;
+  };
+
+public:
+  typedef T *Value_type;
+  typedef T *value_type;
+  typedef __Iterator<T, typename C::Item> Iterator;
+  typedef Iterator Const_iterator;
+
+  static void remove(T *e)
+  {
+    C::next(C::prev(e)) = C::next(e);
+    C::prev(C::next(e)) = C::prev(e);
+    C::next(e) = 0;
+  }
+
+  static Iterator erase(Iterator const &e)
+  {
+    typename C::Item *n = C::next(*e);
+    remove(*e);
+    return __iter(n);
+  }
+
+  static Iterator iter(T const *e) { return Iterator(const_cast<T*>(e)); }
+
+  static bool in_list(T const *e) { return C::next(const_cast<T*>(e)); }
+  static bool has_sibling(T const *e) { return C::next(const_cast<T*>(e)) != e; }
+
+  static Iterator insert_after(T *e, Iterator const &pos)
+  {
+    C::prev(e) = *pos;
+    C::next(e) = C::next(*pos);
+    C::prev(C::next(*pos)) = e;
+    C::next(*pos) = e;
+    return pos;
+  }
+
+  static Iterator insert_before(T *e, Iterator const &pos)
+  {
+    C::next(e) = *pos;
+    C::prev(e) = C::prev(*pos);
+    C::next(C::prev(*pos)) = e;
+    C::prev(*pos) = e;
+    return pos;
+  }
+
+  static T *self_insert(T *e)
+  { C::next(e) = C::prev(e) = e; return e; }
+
+  static void remove_last(T *e)
+  { C::next(e) = 0; }
+
+protected:
+  static Iterator __iter(typename C::Item *e) { return Iterator(e); }
+};
+
+template<
+  typename T,
+  typename C = D_list_item_policy,
+  typename H = Sd_list_head_policy<T>,
+  bool BSS = false
+>
+class Sd_list : public D_list_cyclic<T, C>
+{
+private:
+  typedef D_list_cyclic<T, C> Base;
+
+public:
+  typedef typename Base::Iterator Iterator;
+  enum Pos
+  { Back, Front };
+
+  Sd_list() { if (!BSS) H::set_head(_f, 0); }
+
+  bool empty() const { return !H::head(_f); }
+  T *front() const { return H::head(_f); }
+
+  void remove(T *e)
+  {
+    T *h = H::head(_f);
+    if (e == C::next(e)) // must be the last
+      {
+        Base::remove_last(e);
+        H::set_head(_f, 0);
+        return;
+      }
+
+    if (e == H::head(_f))
+      H::set_head(_f, static_cast<T*>(C::next(h)));
+
+    Base::remove(e);
+  }
+
+  Iterator erase(Iterator const &e)
+  {
+    typename C::Item *n = C::next(*e);
+    remove(*e);
+    return __iter(n);
+  }
+
+  void push(T *e, Pos pos)
+  {
+    T *h = H::head(_f);
+    if (!h)
+      H::set_head(_f, Base::self_insert(e));
+    else
+      {
+        Base::insert_before(e, this->iter(h));
+        if (pos == Front)
+          H::set_head(_f, e);
+      }
+  }
+
+  void push_back(T *e) { push(e, Back); }
+  void push_front(T *e) { push(e, Front); }
+  void rotate_to(T *h) { H::set_head(_f, h); }
+
+  typename H::Head_type const &head() const { return _f; }
+  typename H::Head_type &head() { return _f; }
+
+private:
+  Sd_list(Sd_list const &);
+  void operator = (Sd_list const &);
+
+  typename H::Head_type _f;
+};
+
+template<
+  typename T,
+  typename C = D_list_item_policy,
+  bool BSS = false
+>
+class D_list : public D_list_cyclic<T, C>
+{
+private:
+  typedef D_list_cyclic<T, C> Base;
+  typedef typename C::Item Internal_type;
+
+public:
+  enum Pos
+  { Back, Front };
+
+  typedef typename Base::Iterator Iterator;
+  typedef typename Base::Const_iterator Const_iterator;
+  typedef T* value_type;
+  typedef T* Value_type;
+
+  D_list() { this->self_insert(static_cast<T*>(&_h)); }
+
+  bool empty() const { return C::next(static_cast<T*>(&_h)) == &_h; }
+
+  void remove(T *e) { Base::remove(e); }
+  void erase(Iterator const &e) { return Base::erase(e); }
+
+  void push(T *e, Pos pos)
+  {
+    if (pos == Front)
+      Base::insert_after(e, end());
+    else
+      Base::insert_before(e, end());
+  }
+
+  void push_back(T *e) { push(e, Back); }
+  void push_front(T *e) { push(e, Front); }
+
+  Iterator begin() const { return this->__iter(C::next(const_cast<Internal_type *>(&_h))); }
+  Iterator end() const { return this->__iter(const_cast<Internal_type *>(&_h)); }
+
+private:
+  D_list(D_list const &);
+  void operator = (D_list const &);
+
+  Internal_type _h;
+};
+
+}
+
diff --git a/kernel/fiasco/src/lib/libk/cxx/hlist b/kernel/fiasco/src/lib/libk/cxx/hlist
new file mode 100644 (file)
index 0000000..187eb1c
--- /dev/null
@@ -0,0 +1,137 @@
+// vi:ft=cpp
+/*
+ * (c) 2011 Alexander Warg <warg@os.inf.tu-dresden.de>
+ *     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 "bits/list_basics.h"
+
+namespace cxx {
+
+class H_list_item
+{
+public:
+  H_list_item() : _pn(0) {}
+  ~H_list_item() { l_remove(); }
+
+private:
+  H_list_item(H_list_item const &);
+  void operator = (H_list_item const &);
+
+  template<typename T, typename P> friend class H_list;
+  template<typename T, typename X> friend struct Bits::Basic_list_policy;
+
+  void l_remove()
+  {
+    if (!_pn)
+      return;
+
+    *_pn = _n;
+    if (_n) 
+      _n->_pn = _pn;
+
+    _pn = 0;
+  }
+
+  H_list_item *_n, **_pn;
+};
+
+template< typename T, typename POLICY = Bits::Basic_list_policy< T, H_list_item > >
+class H_list : public Bits::Basic_list<POLICY> 
+{
+private:
+  typedef Bits::Basic_list<POLICY> Base;
+  H_list(H_list const &);
+  void operator = (H_list const &);
+
+public:
+  typedef typename Base::Iterator Iterator;
+
+  // BSS allocation
+  explicit H_list(bool x) : Base(x) {}
+  H_list() : Base() {}
+
+  static Iterator iter(T *c) { return Base::__iter(c->_pn); }
+
+  static bool in_list(T const *e) { return e->_pn; }
+
+  void add(T *e)
+  {
+    if (this->_f)
+      this->_f->_pn = &e->_n;
+    e->_n = this->_f;
+    e->_pn = &this->_f;
+    this->_f = e;
+  }
+
+  void push_front(T *e) { add(e); }
+
+  void insert(T *e, Iterator const &pred)
+  {
+    H_list_item **x = &this->_f;
+    if (pred != Base::end())
+      x = &(*pred)->_n;
+
+    e->_n = *x;
+
+    if (*x)
+      (*x)->_pn = &(e->_n);
+
+    e->_pn = x;
+    *x = e;
+  }
+
+  static void insert_before(T *e, Iterator const &succ)
+  {
+    H_list_item **x = Base::__get_internal(succ);
+
+    e->_n = *x;
+    e->_pn = x;
+
+    if (*x)
+      (*x)->_pn = &e->_n;
+
+    *x = e;
+  }
+
+  static void replace(T *p, T *e)
+  {
+    e->_n = p->_n;
+    e->_pn = p->_pn;
+    *(p->_pn) = e;
+    if (e->_n)
+      e->_n->_pn = &(e->_n);
+
+    p->_pn = 0;
+  }
+
+  static void remove(T *e)
+  { e->H_list_item::l_remove(); }
+
+  static Iterator erase(Iterator const &e)
+  { e->H_list_item::l_remove(); return e; }
+};
+
+template< typename T >
+class H_list_bss : public H_list<T>
+{
+public:
+  H_list_bss() : H_list<T>(true) {}
+};
+
+}
diff --git a/kernel/fiasco/src/lib/libk/cxx/slist b/kernel/fiasco/src/lib/libk/cxx/slist
new file mode 100644 (file)
index 0000000..43eaeaa
--- /dev/null
@@ -0,0 +1,181 @@
+// vi:ft=cpp
+/*
+ * (c) 2011 Alexander Warg <warg@os.inf.tu-dresden.de>
+ *     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 "bits/list_basics.h"
+
+namespace cxx {
+
+class S_list_item
+{
+public:
+  S_list_item() : _n(0) {}
+  explicit S_list_item(bool) {}
+
+private:
+  template<typename T, typename P> friend class S_list;
+  template<typename T, typename P> friend class S_list_tail;
+  template<typename T, typename X> friend struct Bits::Basic_list_policy;
+
+  S_list_item(S_list_item const &);
+  void operator = (S_list_item const &);
+
+  S_list_item *_n;
+};
+
+template< typename T, typename POLICY = Bits::Basic_list_policy< T, S_list_item > >
+class S_list : public Bits::Basic_list<POLICY>
+{
+  S_list(S_list const &) = delete;
+  void operator = (S_list const &) = delete;
+
+private:
+  typedef typename Bits::Basic_list<POLICY> Base;
+
+public:
+  typedef typename Base::Iterator Iterator;
+
+  S_list(S_list &&o) : Base(static_cast<Base&&>(o)) {}
+
+  S_list &operator = (S_list &&o)
+  {
+    Base::operator = (static_cast<Base&&>(o));
+    return *this;
+  }
+
+  // BSS allocation
+  explicit S_list(bool x) : Base(x) {}
+
+  S_list() : Base() {}
+
+  void add(T *e)
+  {
+    e->_n = this->_f;
+    this->_f = e;
+  }
+
+  template< typename CAS >
+  void add(T *e, CAS const &c)
+  {
+    do
+      {
+        e->_n = this->_f;
+      }
+    while (!c(&this->_f, e->_n, e));
+  }
+
+  void push_front(T *e) { add(e); }
+  T *pop_front()
+  {
+    T *r = this->front();
+    if (this->_f)
+      this->_f = this->_f->_n;
+    return r;
+  }
+
+  void insert(T *e, Iterator const &pred)
+  {
+    S_list_item *p = *pred;
+    e->_n = p->_n;
+    p->_n = e;
+  }
+
+  static void insert_before(T *e, Iterator const &succ)
+  {
+    S_list_item **x = Base::__get_internal(succ);
+
+    e->_n = *x;
+    *x = e;
+  }
+
+  static void replace(Iterator const &p, T*e)
+  {
+    S_list_item **x = Base::__get_internal(p);
+    e->_n = (*x)->_n;
+    *x = e;
+  }
+
+  static Iterator erase(Iterator const &e)
+  {
+    S_list_item **x = Base::__get_internal(e);
+    *x = (*x)->_n;
+    return e;
+  }
+
+};
+
+
+template< typename T >
+class S_list_bss : public S_list<T>
+{
+public:
+  S_list_bss() : S_list<T>(true) {}
+};
+
+template< typename T, typename POLICY = Bits::Basic_list_policy< T, S_list_item >  >
+class S_list_tail : public S_list<T, POLICY>
+{
+private:
+  typedef S_list<T, POLICY> Base;
+
+public:
+  S_list_tail() : Base(), _tail(&this->_f) {}
+
+  S_list_tail(S_list_tail &&t) : Base(static_cast<Base&&>(t)), _tail(t._tail)
+  {
+    t._tail = &t._f;
+  }
+
+  S_list_tail &operator = (S_list_tail &&t)
+  {
+    Base::operator = (static_cast<Base &&>(t));
+    _tail = t._tail;
+    t._tail = &t._f;
+    return *this;
+  }
+
+  void push_back(T *e)
+  {
+    e->_n = 0;
+    *_tail = e;
+    _tail = &e->_n;
+  }
+
+  void clear()
+  {
+    Base::clear();
+    _tail = &this->_f;
+  }
+
+  void append(S_list_tail &o)
+  {
+    T *x = o.front();
+    *_tail = x;
+    if (x)
+      _tail = o._tail;
+    o.clear();
+  }
+
+
+private:
+  S_list_item **_tail;
+};
+
+}
diff --git a/kernel/fiasco/src/lib/libk/cxx/type_list b/kernel/fiasco/src/lib/libk/cxx/type_list
new file mode 100644 (file)
index 0000000..8262a1d
--- /dev/null
@@ -0,0 +1,61 @@
+// vi:ft=cpp
+#pragma once
+
+/*
+ * (c) 2012 Alexander Warg <warg@os.inf.tu-dresden.de>,
+ *     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 "type_traits"
+
+namespace cxx {
+
+template< typename ...T >
+struct type_list;
+
+template<>
+struct type_list<>
+{
+  typedef false_type head;
+  typedef false_type tail;
+};
+
+template<typename HEAD, typename ...TAIL>
+struct type_list<HEAD, TAIL...>
+{
+  typedef HEAD head;
+  typedef type_list<TAIL...> tail;
+};
+
+template<typename TYPELIST, template <typename T> class PREDICATE>
+struct find_type;
+
+template<template <typename T> class PREDICATE>
+struct find_type<type_list<>, PREDICATE>
+{
+  typedef false_type type;
+};
+
+template<typename TYPELIST, template <typename T> class PREDICATE>
+struct find_type
+{
+  typedef typename conditional<PREDICATE<typename TYPELIST::head>::value,
+                               typename TYPELIST::head,
+                               typename find_type<typename TYPELIST::tail, PREDICATE>::type>::type type;
+};
+
+}
diff --git a/kernel/fiasco/src/lib/libk/cxx/type_traits b/kernel/fiasco/src/lib/libk/cxx/type_traits
new file mode 100644 (file)
index 0000000..1f5a2d8
--- /dev/null
@@ -0,0 +1,210 @@
+// vi:ft=cpp
+
+/*
+ * (c) 2008-2009 Alexander Warg <warg@os.inf.tu-dresden.de>,
+ *               Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
+ *     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
+
+#pragma GCC system_header
+
+#include "fiasco_defs.h"
+
+namespace cxx {
+
+template< typename T, T V >
+struct integral_constant
+{
+  static T const value = V;
+  typedef T value_type;
+  typedef integral_constant<T, V> type;
+};
+
+typedef integral_constant<bool, true> true_type;
+typedef integral_constant<bool, false> false_type;
+
+template< typename T > struct remove_reference;
+
+template< typename T > struct idendity { typedef T type; };
+
+template< typename T1, typename T2 > struct is_same;
+
+template< typename T > struct remove_const;
+
+template< typename T > struct remove_volatile;
+
+template< typename T > struct remove_cv;
+
+template< typename T > struct remove_pointer;
+
+
+
+template< typename, typename >
+struct is_same : public false_type {};
+
+template< typename T >
+struct is_same<T, T> : public true_type {};
+
+template< typename T >
+struct remove_reference { typedef T type; };
+
+template< typename T >
+struct remove_reference<T &> { typedef T type; };
+
+template< typename T >
+struct remove_reference<T &&> { typedef T type; };
+
+
+template< typename T > struct remove_const { typedef T type; };
+template< typename T > struct remove_const<T const> { typedef T type; };
+
+template< typename T > struct remove_volatile { typedef T type; };
+template< typename T > struct remove_volatile<T volatile> { typedef T type; };
+
+template< typename T >
+struct remove_cv { typedef typename remove_const<typename remove_volatile<T>::type>::type type; };
+
+template< typename T, typename >
+struct __remove_pointer_h { typedef T type; };
+
+template< typename T, typename I >
+struct __remove_pointer_h<T, I*> { typedef I type; };
+
+template< typename  T >
+struct remove_pointer : public __remove_pointer_h<T, typename remove_cv<T>::type> {};
+
+#if FIASCO_GCC_VERSION >= 405
+
+template< typename T >
+inline T &&
+forward(typename cxx::remove_reference<T>::type &t)
+{ return static_cast<T &&>(t); }
+
+template< typename T >
+inline T &&
+forward(typename cxx::remove_reference<T>::type &&t)
+{ return static_cast<T &&>(t); }
+
+#else
+
+template< typename T >
+inline T &&
+forward(typename cxx::idendity<T>::type &&t)
+{ return t; }
+
+#endif
+
+template< typename T >
+inline typename cxx::remove_reference<T>::type &&
+move(T &t) { return static_cast<typename cxx::remove_reference<T>::type &&>(t); }
+
+template< bool, typename T = void >
+struct enable_if {};
+
+template< typename T >
+struct enable_if<true, T> { typedef T type; };
+
+template< typename T >
+struct is_const : public false_type {};
+
+template< typename T >
+struct is_const<T const> : public true_type {};
+
+template< bool, typename, typename >
+struct conditional;
+
+template< bool C, typename T_TRUE, typename T_FALSE >
+struct conditional { typedef T_TRUE type; };
+
+template< typename T_TRUE, typename T_FALSE >
+struct conditional< false, T_TRUE, T_FALSE > { typedef T_FALSE type; };
+
+template<typename T>
+struct is_enum : integral_constant<bool, __is_enum(T)> {};
+
+
+template< typename T > struct is_integral : public false_type {};
+
+template<> struct is_integral<bool> : public true_type {};
+
+template<> struct is_integral<char> : public true_type {};
+template<> struct is_integral<signed char> : public true_type {};
+template<> struct is_integral<unsigned char> : public true_type {};
+template<> struct is_integral<short> : public true_type {};
+template<> struct is_integral<unsigned short> : public true_type {};
+template<> struct is_integral<int> : public true_type {};
+template<> struct is_integral<unsigned int> : public true_type {};
+template<> struct is_integral<long> : public true_type {};
+template<> struct is_integral<unsigned long> : public true_type {};
+template<> struct is_integral<long long> : public true_type {};
+template<> struct is_integral<unsigned long long> : public true_type {};
+
+template< typename T, bool = is_integral<T>::value || is_enum<T>::value >
+struct __is_signed_helper : integral_constant<bool, static_cast<bool>(T(-1) < T(0))> {};
+
+template< typename T >
+struct __is_signed_helper<T, false> : integral_constant<bool, false> {};
+
+template< typename T >
+struct is_signed : __is_signed_helper<T> {};
+
+
+template< int SIZE, bool SIGN = false, bool = true > struct int_type_for_size;
+
+template<> struct int_type_for_size<sizeof(char), true, true>
+{ typedef signed char type; };
+
+template<> struct int_type_for_size<sizeof(char), false, true>
+{ typedef unsigned char type; };
+
+template<> struct int_type_for_size<sizeof(short), true, (sizeof(short) > sizeof(char))>
+{ typedef short type; };
+
+template<> struct int_type_for_size<sizeof(short), false, (sizeof(short) > sizeof(char))>
+{ typedef unsigned short type; };
+
+template<> struct int_type_for_size<sizeof(int), true, (sizeof(int) > sizeof(short))>
+{ typedef int type; };
+
+template<> struct int_type_for_size<sizeof(int), false, (sizeof(int) > sizeof(short))>
+{ typedef unsigned int type; };
+
+template<> struct int_type_for_size<sizeof(long), true, (sizeof(long) > sizeof(int))>
+{ typedef long type; };
+
+template<> struct int_type_for_size<sizeof(long), false, (sizeof(long) > sizeof(int))>
+{ typedef unsigned long type; };
+
+template<> struct int_type_for_size<sizeof(long long), true, (sizeof(long long) > sizeof(long))>
+{ typedef long long type; };
+
+template<> struct int_type_for_size<sizeof(long long), false, (sizeof(long long) > sizeof(long))>
+{ typedef unsigned long long type; };
+
+template< typename T, class Enable = void > struct underlying_type {};
+
+template< typename T >
+struct underlying_type<T, typename enable_if<is_enum<T>::value>::type >
+{
+  typedef typename int_type_for_size<sizeof(T), is_signed<T>::value>::type type;
+};
+
+
+}
+
diff --git a/kernel/fiasco/src/lib/libk/cxx/union b/kernel/fiasco/src/lib/libk/cxx/union
new file mode 100644 (file)
index 0000000..68096da
--- /dev/null
@@ -0,0 +1,88 @@
+// vi:ft=cpp
+/*
+ * (c) 2012 Alexander Warg <warg@os.inf.tu-dresden.de>
+ *     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 "type_traits"
+#include <new>
+
+namespace cxx {
+
+template< typename BASE, typename ...IMPLS >
+class Union
+{
+  Union(Union const &) = delete;
+  Union &operator = (Union const &) = delete;
+
+public:
+  Union() { construct<BASE>(); }
+
+  BASE *get()
+  { return reinterpret_cast<BASE*>(_d); }
+
+  BASE const *get() const
+  { return reinterpret_cast<BASE const*>(_d); }
+
+  BASE *operator -> () { return get(); }
+  BASE &operator * () { return *get(); }
+  BASE const *operator -> () const { return get(); }
+  BASE const &operator * () const { return *get(); }
+
+  template< typename T >
+  T *construct()
+  {
+    BASE *test = reinterpret_cast<T*>(10); (void)test;
+    static_assert(sizeof(T) <= sizeof(_d), "dynamic type of union too big");
+    return new ((void*)_d) T;
+  }
+
+  template< typename T, typename ...ARGS >
+  T *construct(ARGS ...args)
+  {
+    BASE *test = reinterpret_cast<T*>(10); (void)test;
+    static_assert(sizeof(T) <= sizeof(_d), "dynamic type of union too big");
+    return new ((void*)_d) T(cxx::forward<ARGS>(args)...);
+  }
+
+  void destroy()
+  { get()->~BASE(); construct<BASE>(); }
+
+private:
+  template< unsigned ...X >
+  struct Max;
+
+  template< unsigned Z >
+  struct Max<Z> { enum { value = Z }; };
+
+  template< unsigned X, unsigned Y >
+  struct Max<X,Y> { enum { value = X > Y ? X : Y }; };
+
+  template< unsigned X, unsigned ...Y >
+  struct Max<X, Y...> { enum { value = Max<X, Max<Y...>::value>::value }; };
+
+  enum
+  {
+    Size = Max<sizeof(BASE), sizeof(IMPLS)...>::value,
+    Words = (Size + sizeof(unsigned long) - 1) / sizeof(unsigned long)
+  };
+
+  unsigned long _d[Words];
+};
+
+}
index 20b5a56b78e69a6c445bc22b3d1741ad42b9f981..ad749828824ead2c6eeaa66071dea89086e63bdf 100644 (file)
@@ -40,17 +40,6 @@ cas2_unsafe (Mword *ptr, Mword *oldval, Mword *newval)
   return ret;
 }
 
-inline 
-bool
-tas (Mword *l)
-{
-  Mword tmp;
-  asm volatile
-    ("xchg %0,%1" : "=r" (tmp) : "m" (*l), "0" (1) : "memory");
-
-  return tmp;
-}
-
 template <typename T> inline
 atomic_and (Mword *l, Mword bits)
 {
index 500f82da270b0fdb4d8f06236ffce12286acd1e5..7bf8f1f3942aea5d2c39e686efe42b742f6aed24 100644 (file)
@@ -1,5 +1,5 @@
 INTERFACE:
-#include <type_traits>
+#include <cxx/type_traits>
 
 //
 // Regular lock-guard policy, lock on ctor, unlock/reset in dtor
index 6be647bcb7a4d830f5ad4ad90e7de2f761e732aa..e7733ca3008ca90bb47fc9564f0cbda9f6255478 100644 (file)
@@ -1,8 +1,8 @@
 INTERFACE:
 
 #include <spin_lock.h>
-#include <hlist>
-#include <slist>
+#include <cxx/hlist>
+#include <cxx/slist>
 #include <auto_quota.h>
 
 // The anonymous slab allocator.  You can specialize this allocator by
index 1c64544b75e234979b0c4f4b6b2642ead23d2915..52f383deb72aec88479add797dae6e417498667c 100644 (file)
@@ -1,6 +1,6 @@
 #pragma once
 
-#include <type_traits>
+#include <cxx/type_traits>
 
 namespace cxx
 {
index 12ba823788cdf28898e011ca93346bf63061dd4a..950680d2a4984bc19253b5ff903933d8cc521be4 100644 (file)
@@ -21,6 +21,7 @@ namespace L4
     UTXH    = 0x20, // transmit buffer register (little endian, 0x23 for BE)
     URXH    = 0x24, // receive buffer register (little endian, 0x27 for BE)
     UBRDIV  = 0x28, // baud rate divisor register
+    UFRACVAL= 0x2c,
     // 64xx++
     UINTP   = 0x30, // interrupt pending register
     UINTSP  = 0x34, // interrupt source pending register
@@ -243,5 +244,27 @@ namespace L4
   {
     _regs->write<unsigned int>(UINTP, UINT_RXD);
   }
+
+  void Uart_s5pv210::save(Save_block *b) const
+  {
+    b->ubrdiv   = _regs->read<unsigned>(UBRDIV);
+    b->uintm    = _regs->read<unsigned>(UINTM);
+    b->ufracval = _regs->read<unsigned>(UFRACVAL);
+    b->umcon    = _regs->read<unsigned>(UMCON);
+    b->ufcon    = _regs->read<unsigned>(UFCON);
+    b->ucon     = _regs->read<unsigned>(UCON);
+    b->ulcon    = _regs->read<unsigned>(ULCON);
+  }
+
+  void Uart_s5pv210::restore(Save_block const *b) const
+  {
+    _regs->write<unsigned>(UINTM,    b->uintm);
+    _regs->write<unsigned>(ULCON,    b->ulcon);
+    _regs->write<unsigned>(UCON,     b->ucon);
+    _regs->write<unsigned>(UFCON,    b->ufcon);
+    _regs->write<unsigned>(UMCON,    b->umcon);
+    _regs->write<unsigned>(UBRDIV,   b->ubrdiv);
+    _regs->write<unsigned>(UFRACVAL, b->ufracval);
+  }
 };
 
index 93bca29722c102dd5ad8625b55b1f7aaaf091e5d..e443683b48f39798a07d1abf5f7fe3c61829eb11 100644 (file)
@@ -67,6 +67,22 @@ namespace L4
   public:
     Uart_s5pv210() : Uart_s3c(Type_s5pv210) {}
 
+    struct Save_block
+    {
+      unsigned ulcon;
+      unsigned ucon;
+      unsigned ufcon;
+      unsigned umcon;
+      unsigned ubrdiv;
+      unsigned ufracval;
+      unsigned uintp;
+      unsigned uintsp;
+      unsigned uintm;
+    };
+
+    void save(Save_block *) const;
+    void restore(Save_block const *) const;
+
   protected:
     void ack_rx_irq() const;
     void wait_for_empty_tx_fifo() const;
index db390428451c89059b505026bbe28784a0b2afb5..de9cec90ea49809b2fb67f0643cfb98dbd1934c5 100644 (file)
@@ -32,6 +32,7 @@ CONFIG_SCHED_FIXED_PRIO=y
 # CONFIG_SCHED_WFQ is not set
 # CONFIG_SCHED_FP_WFQ is not set
 # CONFIG_DISABLE_VIRT_OBJ_SPACE is not set
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
index d4457bde7aaf5ff912549b1aac14b506c59ea190..965db408af7c9d9b1df026daf9c86f0cb9f8247d 100644 (file)
@@ -32,6 +32,7 @@ CONFIG_SCHED_FIXED_PRIO=y
 # CONFIG_SCHED_WFQ is not set
 # CONFIG_SCHED_FP_WFQ is not set
 # CONFIG_DISABLE_VIRT_OBJ_SPACE is not set
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
index 44288e91a4bb212c1a1a3e665f84a7fa0097c9ee..d520516da37d30843b49ab3cdf3ea2f797b396ca 100644 (file)
@@ -32,6 +32,7 @@ CONFIG_SCHED_FIXED_PRIO=y
 # CONFIG_SCHED_WFQ is not set
 # CONFIG_SCHED_FP_WFQ is not set
 # CONFIG_DISABLE_VIRT_OBJ_SPACE is not set
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
index fcf191e897d6b7c4bea4ed08d8364aa66ffb007c..431773a16662e7733b66df649f969cee66d5a35f 100644 (file)
@@ -30,6 +30,7 @@ CONFIG_CONTEXT_4K=y
 CONFIG_SCHED_WFQ=y
 # CONFIG_SCHED_FP_WFQ is not set
 # CONFIG_DISABLE_VIRT_OBJ_SPACE is not set
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
index 0f07363fa5dca5ecc682dea937cb1cbcca675cdb..6eec3f0d25e8fe060f9d98206cf340cd97134ff2 100644 (file)
@@ -14,10 +14,12 @@ CONFIG_PF_REALVIEW=y
 # CONFIG_PF_S3C2410 is not set
 # CONFIG_PF_TEGRA2 is not set
 # CONFIG_PF_OMAP is not set
-# CONFIG_PF_SA1100 is not set
 # CONFIG_PF_XSCALE is not set
+# CONFIG_PF_SA1100 is not set
+# CONFIG_PF_EXYNOS is not set
 # CONFIG_PF_KIRKWOOD is not set
 # CONFIG_PF_INTEGRATOR is not set
+# CONFIG_PF_BCM2835 is not set
 CONFIG_BSP_NAME="realview"
 CONFIG_PF_REALVIEW_EB=y
 # CONFIG_PF_REALVIEW_PB11MP is not set
@@ -37,8 +39,10 @@ CONFIG_CAN_ARM_CPU_CORTEX_A9=y
 # CONFIG_ARM_CORTEX_A8 is not set
 CONFIG_ARM_CORTEX_A9=y
 # CONFIG_ARM_ALIGNMENT_CHECK is not set
-# CONFIG_ARM_TZ is not set
-CONFIG_ARM_CA9_ENABLE_SWP=y
+CONFIG_ARM_EM_STD=y
+# CONFIG_ARM_EM_NS is not set
+# CONFIG_ARM_EM_TZ is not set
+# CONFIG_ARM_ENABLE_SWP is not set
 CONFIG_FPU=y
 CONFIG_ARM_CPU_ERRATA=y
 
@@ -53,6 +57,7 @@ CONFIG_SCHED_FIXED_PRIO=y
 # CONFIG_SCHED_WFQ is not set
 # CONFIG_SCHED_FP_WFQ is not set
 # CONFIG_DISABLE_VIRT_OBJ_SPACE is not set
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
index 8f5d7915b062b087afe79ba52d91fd6f7a30dd0b..9eaf903cadb0d0a2c77c78b26293ee9975db1af0 100644 (file)
@@ -14,10 +14,12 @@ CONFIG_PF_REALVIEW=y
 # CONFIG_PF_S3C2410 is not set
 # CONFIG_PF_TEGRA2 is not set
 # CONFIG_PF_OMAP is not set
-# CONFIG_PF_SA1100 is not set
 # CONFIG_PF_XSCALE is not set
+# CONFIG_PF_SA1100 is not set
+# CONFIG_PF_EXYNOS is not set
 # CONFIG_PF_KIRKWOOD is not set
 # CONFIG_PF_INTEGRATOR is not set
+# CONFIG_PF_BCM2835 is not set
 CONFIG_BSP_NAME="realview"
 CONFIG_PF_REALVIEW_EB=y
 # CONFIG_PF_REALVIEW_PB11MP is not set
@@ -37,9 +39,12 @@ CONFIG_CAN_ARM_CPU_CORTEX_A9=y
 # CONFIG_ARM_CORTEX_A8 is not set
 CONFIG_ARM_CORTEX_A9=y
 # CONFIG_ARM_ALIGNMENT_CHECK is not set
-CONFIG_ARM_TZ=y
-# CONFIG_ARM_CA9_ENABLE_SWP is not set
+# CONFIG_ARM_EM_STD is not set
+# CONFIG_ARM_EM_NS is not set
+CONFIG_ARM_EM_TZ=y
+# CONFIG_ARM_ENABLE_SWP is not set
 CONFIG_FPU=y
+CONFIG_ARM_CPU_ERRATA=y
 
 #
 # Kernel options
@@ -52,6 +57,7 @@ CONFIG_SCHED_FIXED_PRIO=y
 # CONFIG_SCHED_WFQ is not set
 # CONFIG_SCHED_FP_WFQ is not set
 # CONFIG_DISABLE_VIRT_OBJ_SPACE is not set
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
diff --git a/kernel/fiasco/src/templates/globalconfig.out.arm-a9-mp-vexpress-1 b/kernel/fiasco/src/templates/globalconfig.out.arm-a9-mp-vexpress-1
new file mode 100644 (file)
index 0000000..2706fa1
--- /dev/null
@@ -0,0 +1,94 @@
+#
+# Automatically generated file; DO NOT EDIT.
+
+#
+# Target configuration
+#
+# CONFIG_IA32 is not set
+# CONFIG_AMD64 is not set
+CONFIG_ARM=y
+# CONFIG_PPC32 is not set
+# CONFIG_SPARC is not set
+CONFIG_PF_REALVIEW=y
+# CONFIG_PF_IMX is not set
+# CONFIG_PF_S3C2410 is not set
+# CONFIG_PF_TEGRA2 is not set
+# CONFIG_PF_OMAP is not set
+# CONFIG_PF_XSCALE is not set
+# CONFIG_PF_SA1100 is not set
+# CONFIG_PF_EXYNOS is not set
+# CONFIG_PF_KIRKWOOD is not set
+# CONFIG_PF_INTEGRATOR is not set
+# CONFIG_PF_BCM2835 is not set
+CONFIG_BSP_NAME="realview"
+# CONFIG_PF_REALVIEW_EB is not set
+# CONFIG_PF_REALVIEW_PB11MP is not set
+# CONFIG_PF_REALVIEW_PBX is not set
+CONFIG_PF_REALVIEW_VEXPRESS=y
+CONFIG_PF_REALVIEW_VEXPRESS_A9=y
+# CONFIG_PF_REALVIEW_RAM_PHYS_BASE_0x0 is not set
+CONFIG_PF_REALVIEW_RAM_PHYS_BASE_0x6=y
+CONFIG_PF_REALVIEW_RAM_PHYS_BASE=0x60000000
+CONFIG_ABI_VF=y
+CONFIG_PF_ARM_MP_CAPABLE=y
+CONFIG_CAN_ARM_CPU_CORTEX_A9=y
+CONFIG_CAN_ARM_CPU_CORTEX_A15=y
+CONFIG_ARM_CORTEX_A9=y
+# CONFIG_ARM_CORTEX_A15 is not set
+CONFIG_ARM_ALIGNMENT_CHECK=y
+CONFIG_ARM_EM_STD=y
+# CONFIG_ARM_EM_NS is not set
+# CONFIG_ARM_EM_TZ is not set
+# CONFIG_ARM_ENABLE_SWP is not set
+CONFIG_FPU=y
+CONFIG_ARM_CPU_ERRATA=y
+
+#
+# Kernel options
+#
+CONFIG_MP=y
+CONFIG_MP_MAX_CPUS=9
+CONFIG_CONTEXT_4K=y
+# CONFIG_FINE_GRAINED_CPUTIME is not set
+CONFIG_SCHED_FIXED_PRIO=y
+# CONFIG_SCHED_WFQ is not set
+# CONFIG_SCHED_FP_WFQ is not set
+# CONFIG_DISABLE_VIRT_OBJ_SPACE is not set
+CONFIG_VIRT_OBJ_SPACE=y
+
+#
+# Debugging
+#
+CONFIG_INLINE=y
+# CONFIG_NDEBUG is not set
+CONFIG_NO_FRAME_PTR=y
+# CONFIG_STACK_DEPTH is not set
+# CONFIG_LIST_ALLOC_SANITY is not set
+CONFIG_SERIAL=y
+CONFIG_JDB=y
+CONFIG_JDB_LOGGING=y
+# CONFIG_JDB_DISASM is not set
+# CONFIG_JDB_GZIP is not set
+# CONFIG_VMEM_ALLOC_TEST is not set
+# CONFIG_DEBUG_KERNEL_PAGE_FAULTS is not set
+# CONFIG_WARN_NONE is not set
+CONFIG_WARN_WARNING=y
+# CONFIG_WARN_ANY is not set
+
+#
+# Compiling
+#
+CONFIG_CC="gcc"
+CONFIG_CXX="g++"
+CONFIG_HOST_CC="gcc"
+CONFIG_HOST_CXX="g++"
+# CONFIG_MAINTAINER_MODE is not set
+CONFIG_LABEL=""
+CONFIG_EXPERIMENTAL=y
+CONFIG_PERF_CNT=y
+CONFIG_BIT32=y
+CONFIG_ARM_V7=y
+CONFIG_ARM_V6PLUS=y
+CONFIG_WARN_LEVEL=1
+CONFIG_XARCH="arm"
+CONFIG_ABI="vf"
diff --git a/kernel/fiasco/src/templates/globalconfig.out.arm-a9-mp-vexpress-2 b/kernel/fiasco/src/templates/globalconfig.out.arm-a9-mp-vexpress-2
new file mode 100644 (file)
index 0000000..0226ac1
--- /dev/null
@@ -0,0 +1,94 @@
+#
+# Automatically generated file; DO NOT EDIT.
+
+#
+# Target configuration
+#
+# CONFIG_IA32 is not set
+# CONFIG_AMD64 is not set
+CONFIG_ARM=y
+# CONFIG_PPC32 is not set
+# CONFIG_SPARC is not set
+CONFIG_PF_REALVIEW=y
+# CONFIG_PF_IMX is not set
+# CONFIG_PF_S3C2410 is not set
+# CONFIG_PF_TEGRA2 is not set
+# CONFIG_PF_OMAP is not set
+# CONFIG_PF_XSCALE is not set
+# CONFIG_PF_SA1100 is not set
+# CONFIG_PF_EXYNOS is not set
+# CONFIG_PF_KIRKWOOD is not set
+# CONFIG_PF_INTEGRATOR is not set
+# CONFIG_PF_BCM2835 is not set
+CONFIG_BSP_NAME="realview"
+# CONFIG_PF_REALVIEW_EB is not set
+# CONFIG_PF_REALVIEW_PB11MP is not set
+# CONFIG_PF_REALVIEW_PBX is not set
+CONFIG_PF_REALVIEW_VEXPRESS=y
+CONFIG_PF_REALVIEW_VEXPRESS_A15=y
+CONFIG_PF_REALVIEW_RAM_PHYS_BASE_0x8=y
+CONFIG_PF_REALVIEW_RAM_PHYS_BASE=0x80000000
+CONFIG_ABI_VF=y
+CONFIG_PF_ARM_MP_CAPABLE=y
+CONFIG_CAN_ARM_CPU_CORTEX_A9=y
+CONFIG_CAN_ARM_CPU_CORTEX_A15=y
+# CONFIG_ARM_CORTEX_A9 is not set
+CONFIG_ARM_CORTEX_A15=y
+CONFIG_ARM_ALIGNMENT_CHECK=y
+CONFIG_ARM_EM_STD=y
+# CONFIG_ARM_EM_NS is not set
+# CONFIG_ARM_EM_TZ is not set
+# CONFIG_ARM_ENABLE_SWP is not set
+CONFIG_ARM_LPAE=y
+CONFIG_FPU=y
+CONFIG_ARM_CPU_ERRATA=y
+
+#
+# Kernel options
+#
+CONFIG_MP=y
+CONFIG_MP_MAX_CPUS=9
+CONFIG_CONTEXT_4K=y
+# CONFIG_FINE_GRAINED_CPUTIME is not set
+CONFIG_SCHED_FIXED_PRIO=y
+# CONFIG_SCHED_WFQ is not set
+# CONFIG_SCHED_FP_WFQ is not set
+# CONFIG_DISABLE_VIRT_OBJ_SPACE is not set
+CONFIG_VIRT_OBJ_SPACE=y
+
+#
+# Debugging
+#
+CONFIG_INLINE=y
+# CONFIG_NDEBUG is not set
+CONFIG_NO_FRAME_PTR=y
+# CONFIG_STACK_DEPTH is not set
+# CONFIG_LIST_ALLOC_SANITY is not set
+CONFIG_SERIAL=y
+CONFIG_JDB=y
+CONFIG_JDB_LOGGING=y
+# CONFIG_JDB_DISASM is not set
+# CONFIG_JDB_GZIP is not set
+# CONFIG_VMEM_ALLOC_TEST is not set
+# CONFIG_DEBUG_KERNEL_PAGE_FAULTS is not set
+# CONFIG_WARN_NONE is not set
+CONFIG_WARN_WARNING=y
+# CONFIG_WARN_ANY is not set
+
+#
+# Compiling
+#
+CONFIG_CC="gcc"
+CONFIG_CXX="g++"
+CONFIG_HOST_CC="gcc"
+CONFIG_HOST_CXX="g++"
+# CONFIG_MAINTAINER_MODE is not set
+CONFIG_LABEL=""
+CONFIG_EXPERIMENTAL=y
+CONFIG_PERF_CNT=y
+CONFIG_BIT32=y
+CONFIG_ARM_V7=y
+CONFIG_ARM_V6PLUS=y
+CONFIG_WARN_LEVEL=1
+CONFIG_XARCH="arm"
+CONFIG_ABI="vf"
index 213aca487d9331627b31280711b119b3339480f5..5345d4d35b0ab27345fe96fb94ba59a1de3937e8 100644 (file)
@@ -12,10 +12,12 @@ CONFIG_PF_IMX=y
 # CONFIG_PF_S3C2410 is not set
 # CONFIG_PF_TEGRA2 is not set
 # CONFIG_PF_OMAP is not set
-# CONFIG_PF_SA1100 is not set
 # CONFIG_PF_XSCALE is not set
+# CONFIG_PF_SA1100 is not set
+# CONFIG_PF_EXYNOS is not set
 # CONFIG_PF_KIRKWOOD is not set
 # CONFIG_PF_INTEGRATOR is not set
+# CONFIG_PF_BCM2835 is not set
 CONFIG_BSP_NAME="imx"
 CONFIG_PF_IMX_21=y
 # CONFIG_PF_IMX_35 is not set
@@ -26,6 +28,7 @@ CONFIG_ABI_VF=y
 CONFIG_CAN_ARM_CPU_926=y
 CONFIG_ARM_926=y
 # CONFIG_ARM_ALIGNMENT_CHECK is not set
+CONFIG_ARM_EM_STD=y
 # CONFIG_FPU is not set
 CONFIG_ARM_CPU_ERRATA=y
 
index 3b5e188ab803fb373497525e344821ba84e34579..6ab4cb49ba5ad4d814fee62cc1968ac1572d1152 100644 (file)
@@ -12,10 +12,12 @@ CONFIG_PF_IMX=y
 # CONFIG_PF_S3C2410 is not set
 # CONFIG_PF_TEGRA2 is not set
 # CONFIG_PF_OMAP is not set
-# CONFIG_PF_SA1100 is not set
 # CONFIG_PF_XSCALE is not set
+# CONFIG_PF_SA1100 is not set
+# CONFIG_PF_EXYNOS is not set
 # CONFIG_PF_KIRKWOOD is not set
 # CONFIG_PF_INTEGRATOR is not set
+# CONFIG_PF_BCM2835 is not set
 CONFIG_BSP_NAME="imx"
 # CONFIG_PF_IMX_21 is not set
 CONFIG_PF_IMX_35=y
@@ -26,6 +28,7 @@ CONFIG_ABI_VF=y
 CONFIG_CAN_ARM_CPU_1136=y
 CONFIG_ARM_1136=y
 # CONFIG_ARM_ALIGNMENT_CHECK is not set
+CONFIG_ARM_EM_STD=y
 # CONFIG_FPU is not set
 CONFIG_ARM_CPU_ERRATA=y
 
@@ -35,6 +38,7 @@ CONFIG_ARM_CPU_ERRATA=y
 CONFIG_CONTEXT_4K=y
 # CONFIG_FINE_GRAINED_CPUTIME is not set
 CONFIG_SCHED_FIXED_PRIO=y
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
index 28289c10331ca5e4a1b60ce7434b87ccbc5ea8f3..8e8ceba6435d6e43e4731858f4603c9c0022bdb9 100644 (file)
@@ -12,10 +12,12 @@ CONFIG_PF_IMX=y
 # CONFIG_PF_S3C2410 is not set
 # CONFIG_PF_TEGRA2 is not set
 # CONFIG_PF_OMAP is not set
-# CONFIG_PF_SA1100 is not set
 # CONFIG_PF_XSCALE is not set
+# CONFIG_PF_SA1100 is not set
+# CONFIG_PF_EXYNOS is not set
 # CONFIG_PF_KIRKWOOD is not set
 # CONFIG_PF_INTEGRATOR is not set
+# CONFIG_PF_BCM2835 is not set
 CONFIG_BSP_NAME="imx"
 # CONFIG_PF_IMX_21 is not set
 # CONFIG_PF_IMX_35 is not set
@@ -26,6 +28,9 @@ CONFIG_ABI_VF=y
 CONFIG_CAN_ARM_CPU_CORTEX_A8=y
 CONFIG_ARM_CORTEX_A8=y
 # CONFIG_ARM_ALIGNMENT_CHECK is not set
+CONFIG_ARM_EM_STD=y
+# CONFIG_ARM_EM_NS is not set
+# CONFIG_ARM_EM_TZ is not set
 # CONFIG_FPU is not set
 CONFIG_ARM_CPU_ERRATA=y
 
@@ -35,6 +40,7 @@ CONFIG_ARM_CPU_ERRATA=y
 CONFIG_CONTEXT_4K=y
 # CONFIG_FINE_GRAINED_CPUTIME is not set
 CONFIG_SCHED_FIXED_PRIO=y
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
index 904b99264433bc458e8ae0e48cd14fa30017e09d..09116d9df5e33e4443b4bf0d353320ded5b89307 100644 (file)
@@ -12,10 +12,12 @@ CONFIG_PF_IMX=y
 # CONFIG_PF_S3C2410 is not set
 # CONFIG_PF_TEGRA2 is not set
 # CONFIG_PF_OMAP is not set
-# CONFIG_PF_SA1100 is not set
 # CONFIG_PF_XSCALE is not set
+# CONFIG_PF_SA1100 is not set
+# CONFIG_PF_EXYNOS is not set
 # CONFIG_PF_KIRKWOOD is not set
 # CONFIG_PF_INTEGRATOR is not set
+# CONFIG_PF_BCM2835 is not set
 CONFIG_BSP_NAME="imx"
 # CONFIG_PF_IMX_21 is not set
 # CONFIG_PF_IMX_35 is not set
@@ -28,7 +30,10 @@ CONFIG_CAN_ARM_CPU_CORTEX_A9=y
 CONFIG_CAN_ARM_CACHE_L2CXX0=y
 CONFIG_ARM_CORTEX_A9=y
 # CONFIG_ARM_ALIGNMENT_CHECK is not set
-# CONFIG_ARM_CA9_ENABLE_SWP is not set
+CONFIG_ARM_EM_STD=y
+# CONFIG_ARM_EM_NS is not set
+# CONFIG_ARM_EM_TZ is not set
+# CONFIG_ARM_ENABLE_SWP is not set
 CONFIG_ARM_CACHE_L2CXX0=y
 CONFIG_FPU=y
 CONFIG_ARM_CPU_ERRATA=y
@@ -41,6 +46,7 @@ CONFIG_MP_MAX_CPUS=4
 CONFIG_CONTEXT_4K=y
 # CONFIG_FINE_GRAINED_CPUTIME is not set
 CONFIG_SCHED_FIXED_PRIO=y
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
index 92976ecce807b68d8435d8c79cfbfe2c0b046ec1..d148c931823c501db544d14bc269d28aff804c40 100644 (file)
@@ -12,10 +12,12 @@ CONFIG_ARM=y
 # CONFIG_PF_S3C2410 is not set
 # CONFIG_PF_TEGRA2 is not set
 # CONFIG_PF_OMAP is not set
-# CONFIG_PF_SA1100 is not set
 # CONFIG_PF_XSCALE is not set
+# CONFIG_PF_SA1100 is not set
+# CONFIG_PF_EXYNOS is not set
 # CONFIG_PF_KIRKWOOD is not set
 CONFIG_PF_INTEGRATOR=y
+# CONFIG_PF_BCM2835 is not set
 CONFIG_BSP_NAME="integrator"
 CONFIG_ABI_VF=y
 CONFIG_CAN_ARM_CPU_926=y
@@ -23,6 +25,7 @@ CONFIG_CAN_ARM_CPU_1176=y
 CONFIG_ARM_926=y
 # CONFIG_ARM_1176 is not set
 # CONFIG_ARM_ALIGNMENT_CHECK is not set
+CONFIG_ARM_EM_STD=y
 # CONFIG_FPU is not set
 # CONFIG_ARM_CPU_ERRATA is not set
 
index 74e376d6cba4698ce7a470c4152d18e6c77e5f85..814dae0816154f8702c46d71503b933f17420191 100644 (file)
@@ -12,10 +12,12 @@ CONFIG_ARM=y
 # CONFIG_PF_S3C2410 is not set
 # CONFIG_PF_TEGRA2 is not set
 # CONFIG_PF_OMAP is not set
-# CONFIG_PF_SA1100 is not set
 # CONFIG_PF_XSCALE is not set
+# CONFIG_PF_SA1100 is not set
+# CONFIG_PF_EXYNOS is not set
 # CONFIG_PF_KIRKWOOD is not set
 CONFIG_PF_INTEGRATOR=y
+# CONFIG_PF_BCM2835 is not set
 CONFIG_BSP_NAME="integrator"
 CONFIG_ABI_VF=y
 CONFIG_CAN_ARM_CPU_926=y
@@ -23,6 +25,9 @@ CONFIG_CAN_ARM_CPU_1176=y
 # CONFIG_ARM_926 is not set
 CONFIG_ARM_1176=y
 # CONFIG_ARM_ALIGNMENT_CHECK is not set
+CONFIG_ARM_EM_STD=y
+# CONFIG_ARM_EM_NS is not set
+# CONFIG_ARM_EM_TZ is not set
 # CONFIG_FPU is not set
 # CONFIG_ARM_1176_CACHE_ALIAS_FIX is not set
 # CONFIG_ARM_CPU_ERRATA is not set
index beac9669cb6ea63418dede94ebba0c7c23610da0..4f79252c3820608f9379d6f26270523fdbe70668 100644 (file)
@@ -12,15 +12,18 @@ CONFIG_ARM=y
 # CONFIG_PF_S3C2410 is not set
 # CONFIG_PF_TEGRA2 is not set
 # CONFIG_PF_OMAP is not set
-# CONFIG_PF_SA1100 is not set
 # CONFIG_PF_XSCALE is not set
+# CONFIG_PF_SA1100 is not set
+# CONFIG_PF_EXYNOS is not set
 CONFIG_PF_KIRKWOOD=y
 # CONFIG_PF_INTEGRATOR is not set
+# CONFIG_PF_BCM2835 is not set
 CONFIG_BSP_NAME="kirkwood"
 CONFIG_ABI_VF=y
 CONFIG_CAN_ARM_CPU_926=y
 CONFIG_ARM_926=y
 # CONFIG_ARM_ALIGNMENT_CHECK is not set
+CONFIG_ARM_EM_STD=y
 # CONFIG_FPU is not set
 # CONFIG_ARM_CPU_ERRATA is not set
 
index 0d87eb9f9e4627745454b56d90b66eb198ea341f..5678cb0f32374aff0037c067799d968c75f830a3 100644 (file)
@@ -12,11 +12,13 @@ CONFIG_ARM=y
 # CONFIG_PF_S3C2410 is not set
 # CONFIG_PF_TEGRA2 is not set
 CONFIG_PF_OMAP=y
-# CONFIG_PF_SA1100 is not set
 # CONFIG_PF_XSCALE is not set
+# CONFIG_PF_SA1100 is not set
+# CONFIG_PF_EXYNOS is not set
 # CONFIG_PF_KIRKWOOD is not set
 # CONFIG_PF_INTEGRATOR is not set
-CONFIG_BSP_NAME="omap3"
+# CONFIG_PF_BCM2835 is not set
+CONFIG_BSP_NAME="omap"
 CONFIG_PF_OMAP3_OMAP35XEVM=y
 # CONFIG_PF_OMAP3_BEAGLEBOARD is not set
 # CONFIG_PF_OMAP3_AM33XX is not set
@@ -25,6 +27,9 @@ CONFIG_ABI_VF=y
 CONFIG_CAN_ARM_CPU_CORTEX_A8=y
 CONFIG_ARM_CORTEX_A8=y
 # CONFIG_ARM_ALIGNMENT_CHECK is not set
+CONFIG_ARM_EM_STD=y
+# CONFIG_ARM_EM_NS is not set
+# CONFIG_ARM_EM_TZ is not set
 CONFIG_FPU=y
 # CONFIG_ARM_CPU_ERRATA is not set
 
@@ -34,6 +39,7 @@ CONFIG_FPU=y
 CONFIG_CONTEXT_4K=y
 # CONFIG_FINE_GRAINED_CPUTIME is not set
 CONFIG_SCHED_FIXED_PRIO=y
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
index 98d21b87c60fc77a913b45e4e83a514d78977ece..884977112d137db1e570914c91c4b0eb744f6cf8 100644 (file)
@@ -14,11 +14,13 @@ CONFIG_ARM=y
 # CONFIG_PF_S3C2410 is not set
 # CONFIG_PF_TEGRA2 is not set
 CONFIG_PF_OMAP=y
-# CONFIG_PF_SA1100 is not set
 # CONFIG_PF_XSCALE is not set
+# CONFIG_PF_SA1100 is not set
+# CONFIG_PF_EXYNOS is not set
 # CONFIG_PF_KIRKWOOD is not set
 # CONFIG_PF_INTEGRATOR is not set
-CONFIG_BSP_NAME="omap3"
+# CONFIG_PF_BCM2835 is not set
+CONFIG_BSP_NAME="omap"
 # CONFIG_PF_OMAP3_OMAP35XEVM is not set
 # CONFIG_PF_OMAP3_BEAGLEBOARD is not set
 # CONFIG_PF_OMAP3_AM33XX is not set
@@ -29,8 +31,10 @@ CONFIG_CAN_ARM_CPU_CORTEX_A9=y
 CONFIG_CAN_ARM_CACHE_L2CXX0=y
 CONFIG_ARM_CORTEX_A9=y
 CONFIG_ARM_ALIGNMENT_CHECK=y
-# CONFIG_ARM_TZ is not set
-CONFIG_ARM_CA9_ENABLE_SWP=y
+CONFIG_ARM_EM_STD=y
+# CONFIG_ARM_EM_NS is not set
+# CONFIG_ARM_EM_TZ is not set
+# CONFIG_ARM_ENABLE_SWP is not set
 CONFIG_ARM_CACHE_L2CXX0=y
 CONFIG_FPU=y
 # CONFIG_ARM_CPU_ERRATA is not set
@@ -46,6 +50,7 @@ CONFIG_SCHED_FIXED_PRIO=y
 # CONFIG_SCHED_WFQ is not set
 # CONFIG_SCHED_FP_WFQ is not set
 # CONFIG_DISABLE_VIRT_OBJ_SPACE is not set
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
index 1a2f26d7a9c5cf878f869e6d6d0529ab8efdad23..92cc2966a759097f02f0972fabf373a1e11c1b7c 100644 (file)
@@ -12,15 +12,18 @@ CONFIG_ARM=y
 # CONFIG_PF_S3C2410 is not set
 # CONFIG_PF_TEGRA2 is not set
 # CONFIG_PF_OMAP is not set
-# CONFIG_PF_SA1100 is not set
 CONFIG_PF_XSCALE=y
+# CONFIG_PF_SA1100 is not set
+# CONFIG_PF_EXYNOS is not set
 # CONFIG_PF_KIRKWOOD is not set
 # CONFIG_PF_INTEGRATOR is not set
+# CONFIG_PF_BCM2835 is not set
 CONFIG_BSP_NAME="pxa"
 CONFIG_ABI_VF=y
 CONFIG_CAN_ARM_CPU_XSCALE=y
 CONFIG_ARM_PXA=y
 # CONFIG_ARM_ALIGNMENT_CHECK is not set
+CONFIG_ARM_EM_STD=y
 # CONFIG_FPU is not set
 # CONFIG_ARM_CPU_ERRATA is not set
 
index 2ed1d1b64bc618bfe9b1e8e0499561ed85188e91..dd627549c1ab5af5cea9824e8f0056021e596d7a 100644 (file)
@@ -12,10 +12,12 @@ CONFIG_PF_REALVIEW=y
 # CONFIG_PF_S3C2410 is not set
 # CONFIG_PF_TEGRA2 is not set
 # CONFIG_PF_OMAP is not set
-# CONFIG_PF_SA1100 is not set
 # CONFIG_PF_XSCALE is not set
+# CONFIG_PF_SA1100 is not set
+# CONFIG_PF_EXYNOS is not set
 # CONFIG_PF_KIRKWOOD is not set
 # CONFIG_PF_INTEGRATOR is not set
+# CONFIG_PF_BCM2835 is not set
 CONFIG_BSP_NAME="realview"
 CONFIG_PF_REALVIEW_EB=y
 # CONFIG_PF_REALVIEW_PB11MP is not set
@@ -34,6 +36,7 @@ CONFIG_ARM_926=y
 # CONFIG_ARM_CORTEX_A8 is not set
 # CONFIG_ARM_CORTEX_A9 is not set
 # CONFIG_ARM_ALIGNMENT_CHECK is not set
+CONFIG_ARM_EM_STD=y
 # CONFIG_FPU is not set
 CONFIG_ARM_CPU_ERRATA=y
 
index 9c601b9ea9e5d3dc249c32c71bb2727dcc290e43..33ad50799583387a8eb33a87c68c22316c7b4091 100644 (file)
@@ -12,10 +12,12 @@ CONFIG_PF_REALVIEW=y
 # CONFIG_PF_S3C2410 is not set
 # CONFIG_PF_TEGRA2 is not set
 # CONFIG_PF_OMAP is not set
-# CONFIG_PF_SA1100 is not set
 # CONFIG_PF_XSCALE is not set
+# CONFIG_PF_SA1100 is not set
+# CONFIG_PF_EXYNOS is not set
 # CONFIG_PF_KIRKWOOD is not set
 # CONFIG_PF_INTEGRATOR is not set
+# CONFIG_PF_BCM2835 is not set
 CONFIG_BSP_NAME="realview"
 CONFIG_PF_REALVIEW_EB=y
 # CONFIG_PF_REALVIEW_PB11MP is not set
@@ -34,6 +36,9 @@ CONFIG_ARM_1176=y
 # CONFIG_ARM_CORTEX_A8 is not set
 # CONFIG_ARM_CORTEX_A9 is not set
 # CONFIG_ARM_ALIGNMENT_CHECK is not set
+CONFIG_ARM_EM_STD=y
+# CONFIG_ARM_EM_NS is not set
+# CONFIG_ARM_EM_TZ is not set
 # CONFIG_FPU is not set
 CONFIG_ARM_1176_CACHE_ALIAS_FIX=y
 CONFIG_ARM_CPU_ERRATA=y
@@ -44,6 +49,7 @@ CONFIG_ARM_CPU_ERRATA=y
 CONFIG_CONTEXT_4K=y
 # CONFIG_FINE_GRAINED_CPUTIME is not set
 CONFIG_SCHED_FIXED_PRIO=y
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
index 2a64c966e18e93f107ff77ebc4dbd6a9e23453c9..3e7347255a2686f41d5c59ea4daff1aa420263ae 100644 (file)
@@ -12,10 +12,12 @@ CONFIG_PF_REALVIEW=y
 # CONFIG_PF_S3C2410 is not set
 # CONFIG_PF_TEGRA2 is not set
 # CONFIG_PF_OMAP is not set
-# CONFIG_PF_SA1100 is not set
 # CONFIG_PF_XSCALE is not set
+# CONFIG_PF_SA1100 is not set
+# CONFIG_PF_EXYNOS is not set
 # CONFIG_PF_KIRKWOOD is not set
 # CONFIG_PF_INTEGRATOR is not set
+# CONFIG_PF_BCM2835 is not set
 CONFIG_BSP_NAME="realview"
 CONFIG_PF_REALVIEW_EB=y
 # CONFIG_PF_REALVIEW_PB11MP is not set
@@ -36,6 +38,7 @@ CONFIG_ARM_MPCORE=y
 # CONFIG_ARM_CORTEX_A8 is not set
 # CONFIG_ARM_CORTEX_A9 is not set
 # CONFIG_ARM_ALIGNMENT_CHECK is not set
+CONFIG_ARM_EM_STD=y
 CONFIG_ARM_CACHE_L2CXX0=y
 # CONFIG_FPU is not set
 CONFIG_ARM_CPU_ERRATA=y
@@ -47,6 +50,7 @@ CONFIG_ARM_CPU_ERRATA=y
 CONFIG_CONTEXT_4K=y
 # CONFIG_FINE_GRAINED_CPUTIME is not set
 CONFIG_SCHED_FIXED_PRIO=y
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
index 6f4893a2705b15f00a5df3edbedd85baf9809241..29a746c3d21c878ed4af8676f212cd8f9d679949 100644 (file)
@@ -12,10 +12,12 @@ CONFIG_PF_REALVIEW=y
 # CONFIG_PF_S3C2410 is not set
 # CONFIG_PF_TEGRA2 is not set
 # CONFIG_PF_OMAP is not set
-# CONFIG_PF_SA1100 is not set
 # CONFIG_PF_XSCALE is not set
+# CONFIG_PF_SA1100 is not set
+# CONFIG_PF_EXYNOS is not set
 # CONFIG_PF_KIRKWOOD is not set
 # CONFIG_PF_INTEGRATOR is not set
+# CONFIG_PF_BCM2835 is not set
 CONFIG_BSP_NAME="realview"
 CONFIG_PF_REALVIEW_EB=y
 # CONFIG_PF_REALVIEW_PB11MP is not set
@@ -34,6 +36,7 @@ CONFIG_ARM_926=y
 # CONFIG_ARM_CORTEX_A8 is not set
 # CONFIG_ARM_CORTEX_A9 is not set
 # CONFIG_ARM_ALIGNMENT_CHECK is not set
+CONFIG_ARM_EM_STD=y
 # CONFIG_FPU is not set
 CONFIG_ARM_CPU_ERRATA=y
 
index 6297487fdc8d81d47cbb924af1ca5bc0edfea5e5..39dd12603ce1eb2b2b83b36dc833dc2083fc81c0 100644 (file)
@@ -12,15 +12,18 @@ CONFIG_ARM=y
 CONFIG_PF_S3C2410=y
 # CONFIG_PF_TEGRA2 is not set
 # CONFIG_PF_OMAP is not set
-# CONFIG_PF_SA1100 is not set
 # CONFIG_PF_XSCALE is not set
+# CONFIG_PF_SA1100 is not set
+# CONFIG_PF_EXYNOS is not set
 # CONFIG_PF_KIRKWOOD is not set
 # CONFIG_PF_INTEGRATOR is not set
+# CONFIG_PF_BCM2835 is not set
 CONFIG_BSP_NAME="s3c"
 CONFIG_ABI_VF=y
 CONFIG_CAN_ARM_CPU_920T=y
 CONFIG_ARM_920T=y
 # CONFIG_ARM_ALIGNMENT_CHECK is not set
+CONFIG_ARM_EM_STD=y
 # CONFIG_FPU is not set
 # CONFIG_ARM_CPU_ERRATA is not set
 
index e19e8a77b857e11b6c6aa44626b89776a70173ec..0b117918e8d94205ff2a20825638d527ce356d69 100644 (file)
@@ -12,15 +12,18 @@ CONFIG_ARM=y
 # CONFIG_PF_S3C2410 is not set
 # CONFIG_PF_TEGRA2 is not set
 # CONFIG_PF_OMAP is not set
-CONFIG_PF_SA1100=y
 # CONFIG_PF_XSCALE is not set
+CONFIG_PF_SA1100=y
+# CONFIG_PF_EXYNOS is not set
 # CONFIG_PF_KIRKWOOD is not set
 # CONFIG_PF_INTEGRATOR is not set
+# CONFIG_PF_BCM2835 is not set
 CONFIG_BSP_NAME="sa1100"
 CONFIG_ABI_VF=y
 CONFIG_CAN_ARM_CPU_SA1100=y
 CONFIG_ARM_SA=y
 # CONFIG_ARM_ALIGNMENT_CHECK is not set
+CONFIG_ARM_EM_STD=y
 # CONFIG_FPU is not set
 # CONFIG_ARM_CPU_ERRATA is not set
 
index 26505718b738ef68cd523872a74e077a044a2e15..bbcbea4deb2105b1b3cd2a2287a3b99156488d7a 100644 (file)
@@ -14,21 +14,28 @@ CONFIG_ARM=y
 # CONFIG_PF_S3C2410 is not set
 CONFIG_PF_TEGRA2=y
 # CONFIG_PF_OMAP is not set
-# CONFIG_PF_SA1100 is not set
 # CONFIG_PF_XSCALE is not set
+# CONFIG_PF_SA1100 is not set
+# CONFIG_PF_EXYNOS is not set
 # CONFIG_PF_KIRKWOOD is not set
 # CONFIG_PF_INTEGRATOR is not set
+# CONFIG_PF_BCM2835 is not set
 CONFIG_BSP_NAME="tegra2"
+CONFIG_PF_TEGRA_TIMER_MP=y
+# CONFIG_PF_TEGRA_TIMER_TMR is not set
 CONFIG_ABI_VF=y
 CONFIG_PF_ARM_MP_CAPABLE=y
 CONFIG_CAN_ARM_CPU_CORTEX_A9=y
 CONFIG_CAN_ARM_CACHE_L2CXX0=y
 CONFIG_ARM_CORTEX_A9=y
 CONFIG_ARM_ALIGNMENT_CHECK=y
-CONFIG_ARM_TZ=y
-CONFIG_ARM_CA9_ENABLE_SWP=y
+CONFIG_ARM_EM_STD=y
+# CONFIG_ARM_EM_NS is not set
+# CONFIG_ARM_EM_TZ is not set
+CONFIG_ARM_ENABLE_SWP=y
 CONFIG_ARM_CACHE_L2CXX0=y
 CONFIG_FPU=y
+# CONFIG_ARM_CPU_ERRATA is not set
 
 #
 # Kernel options
@@ -41,6 +48,7 @@ CONFIG_FINE_GRAINED_CPUTIME=y
 # CONFIG_SCHED_WFQ is not set
 CONFIG_SCHED_FP_WFQ=y
 # CONFIG_DISABLE_VIRT_OBJ_SPACE is not set
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
index 19579540feb09cf6f25ce611d155c82685c26a97..8e3b7aa538a570fa362dadf75201faf2cf1d9e48 100644 (file)
@@ -12,10 +12,12 @@ CONFIG_PF_REALVIEW=y
 # CONFIG_PF_S3C2410 is not set
 # CONFIG_PF_TEGRA2 is not set
 # CONFIG_PF_OMAP is not set
-# CONFIG_PF_SA1100 is not set
 # CONFIG_PF_XSCALE is not set
+# CONFIG_PF_SA1100 is not set
+# CONFIG_PF_EXYNOS is not set
 # CONFIG_PF_KIRKWOOD is not set
 # CONFIG_PF_INTEGRATOR is not set
+# CONFIG_PF_BCM2835 is not set
 CONFIG_BSP_NAME="realview"
 CONFIG_PF_REALVIEW_EB=y
 # CONFIG_PF_REALVIEW_PB11MP is not set
@@ -34,6 +36,9 @@ CONFIG_ARM_1176=y
 # CONFIG_ARM_CORTEX_A8 is not set
 # CONFIG_ARM_CORTEX_A9 is not set
 # CONFIG_ARM_ALIGNMENT_CHECK is not set
+CONFIG_ARM_EM_STD=y
+# CONFIG_ARM_EM_NS is not set
+# CONFIG_ARM_EM_TZ is not set
 # CONFIG_FPU is not set
 CONFIG_ARM_1176_CACHE_ALIAS_FIX=y
 CONFIG_ARM_CPU_ERRATA=y
@@ -44,6 +49,7 @@ CONFIG_ARM_CPU_ERRATA=y
 CONFIG_CONTEXT_4K=y
 # CONFIG_FINE_GRAINED_CPUTIME is not set
 CONFIG_SCHED_FIXED_PRIO=y
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
index 4c5c123f750581ed1d122c884eac006101e25683..205a568eec5d8776e57e05ca8edd9a38e2a7f47a 100644 (file)
@@ -14,10 +14,12 @@ CONFIG_PF_REALVIEW=y
 # CONFIG_PF_S3C2410 is not set
 # CONFIG_PF_TEGRA2 is not set
 # CONFIG_PF_OMAP is not set
-# CONFIG_PF_SA1100 is not set
 # CONFIG_PF_XSCALE is not set
+# CONFIG_PF_SA1100 is not set
+# CONFIG_PF_EXYNOS is not set
 # CONFIG_PF_KIRKWOOD is not set
 # CONFIG_PF_INTEGRATOR is not set
+# CONFIG_PF_BCM2835 is not set
 CONFIG_BSP_NAME="realview"
 CONFIG_PF_REALVIEW_EB=y
 # CONFIG_PF_REALVIEW_PB11MP is not set
@@ -38,6 +40,7 @@ CONFIG_ARM_MPCORE=y
 # CONFIG_ARM_CORTEX_A8 is not set
 # CONFIG_ARM_CORTEX_A9 is not set
 # CONFIG_ARM_ALIGNMENT_CHECK is not set
+CONFIG_ARM_EM_STD=y
 CONFIG_ARM_CACHE_L2CXX0=y
 CONFIG_FPU=y
 CONFIG_ARM_CPU_ERRATA=y
@@ -53,6 +56,7 @@ CONFIG_SCHED_FIXED_PRIO=y
 # CONFIG_SCHED_WFQ is not set
 # CONFIG_SCHED_FP_WFQ is not set
 # CONFIG_DISABLE_VIRT_OBJ_SPACE is not set
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
index 72d3804cf22bdbcfcac79f9d2cb2f5034044bf52..e2326df5e4f37c8ea1dc48ec09c3f7db2f25ee09 100644 (file)
@@ -14,10 +14,12 @@ CONFIG_PF_REALVIEW=y
 # CONFIG_PF_S3C2410 is not set
 # CONFIG_PF_TEGRA2 is not set
 # CONFIG_PF_OMAP is not set
-# CONFIG_PF_SA1100 is not set
 # CONFIG_PF_XSCALE is not set
+# CONFIG_PF_SA1100 is not set
+# CONFIG_PF_EXYNOS is not set
 # CONFIG_PF_KIRKWOOD is not set
 # CONFIG_PF_INTEGRATOR is not set
+# CONFIG_PF_BCM2835 is not set
 CONFIG_BSP_NAME="realview"
 # CONFIG_PF_REALVIEW_EB is not set
 CONFIG_PF_REALVIEW_PB11MP=y
@@ -32,6 +34,7 @@ CONFIG_CAN_ARM_CPU_MPCORE=y
 CONFIG_CAN_ARM_CACHE_L2CXX0=y
 CONFIG_ARM_MPCORE=y
 # CONFIG_ARM_ALIGNMENT_CHECK is not set
+CONFIG_ARM_EM_STD=y
 CONFIG_ARM_CACHE_L2CXX0=y
 CONFIG_FPU=y
 CONFIG_ARM_CPU_ERRATA=y
@@ -47,6 +50,7 @@ CONFIG_FINE_GRAINED_CPUTIME=y
 # CONFIG_SCHED_WFQ is not set
 CONFIG_SCHED_FP_WFQ=y
 # CONFIG_DISABLE_VIRT_OBJ_SPACE is not set
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
index 6644b21c97958d01d89cb2eea789e522a3a184b4..2512e4734a5a224aa49bcc225a2ce50ece0b492d 100644 (file)
@@ -12,10 +12,12 @@ CONFIG_PF_REALVIEW=y
 # CONFIG_PF_S3C2410 is not set
 # CONFIG_PF_TEGRA2 is not set
 # CONFIG_PF_OMAP is not set
-# CONFIG_PF_SA1100 is not set
 # CONFIG_PF_XSCALE is not set
+# CONFIG_PF_SA1100 is not set
+# CONFIG_PF_EXYNOS is not set
 # CONFIG_PF_KIRKWOOD is not set
 # CONFIG_PF_INTEGRATOR is not set
+# CONFIG_PF_BCM2835 is not set
 CONFIG_BSP_NAME="realview"
 CONFIG_PF_REALVIEW_EB=y
 # CONFIG_PF_REALVIEW_PB11MP is not set
@@ -34,6 +36,9 @@ CONFIG_CAN_ARM_CPU_CORTEX_A9=y
 CONFIG_ARM_CORTEX_A8=y
 # CONFIG_ARM_CORTEX_A9 is not set
 # CONFIG_ARM_ALIGNMENT_CHECK is not set
+CONFIG_ARM_EM_STD=y
+# CONFIG_ARM_EM_NS is not set
+# CONFIG_ARM_EM_TZ is not set
 # CONFIG_FPU is not set
 CONFIG_ARM_CPU_ERRATA=y
 
@@ -43,6 +48,7 @@ CONFIG_ARM_CPU_ERRATA=y
 CONFIG_CONTEXT_4K=y
 # CONFIG_FINE_GRAINED_CPUTIME is not set
 CONFIG_SCHED_FIXED_PRIO=y
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
index bf1cbe667ef6764507c1017e2ed0f9e1855ce353..8474217c217076eb1536706ca117969dc81618a6 100644 (file)
@@ -38,6 +38,7 @@ CONFIG_CONTEXT_4K=y
 # CONFIG_SYNC_TSC is not set
 # CONFIG_FINE_GRAINED_CPUTIME is not set
 CONFIG_SCHED_FIXED_PRIO=y
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
index 422df5bc606299c36576921c9b4d206199aefff9..67d54dd6a67ae2fcc06fd5aa766d822fb980a4d5 100644 (file)
@@ -44,6 +44,7 @@ CONFIG_SCHED_FIXED_PRIO=y
 # CONFIG_SCHED_WFQ is not set
 # CONFIG_SCHED_FP_WFQ is not set
 # CONFIG_DISABLE_VIRT_OBJ_SPACE is not set
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
index 5e90383697a48b2b84cc0f335dbde723dc9c9e3a..d3929853fe35f457acbe97cb94cac8ebeed7ae59 100644 (file)
@@ -38,6 +38,7 @@ CONFIG_CONTEXT_4K=y
 # CONFIG_SYNC_TSC is not set
 # CONFIG_FINE_GRAINED_CPUTIME is not set
 CONFIG_SCHED_FIXED_PRIO=y
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
index a2d41d63c75840b3e0ef6943185b47d1ae48fcf6..817e52ab24996fe57ade59d25876563027fbca7c 100644 (file)
@@ -45,6 +45,7 @@ CONFIG_SYNC_TSC=y
 # CONFIG_SCHED_WFQ is not set
 CONFIG_SCHED_FP_WFQ=y
 # CONFIG_DISABLE_VIRT_OBJ_SPACE is not set
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
index a15ed116d3f98ef72574c5b6206053dec1e2c5ee..8edcf40f54046c86321883ba92e43f3a2dd7bb17 100644 (file)
@@ -42,6 +42,7 @@ CONFIG_SCHED_FIXED_PRIO=y
 # CONFIG_SCHED_WFQ is not set
 # CONFIG_SCHED_FP_WFQ is not set
 # CONFIG_DISABLE_VIRT_OBJ_SPACE is not set
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
index e3fe5221b3e72b9ac9f1347d00379a55af7f0b3d..3432d69ce8addcc95fd4e0e51f08975beb92c326 100644 (file)
@@ -44,6 +44,7 @@ CONFIG_SCHED_FIXED_PRIO=y
 # CONFIG_SCHED_WFQ is not set
 # CONFIG_SCHED_FP_WFQ is not set
 # CONFIG_DISABLE_VIRT_OBJ_SPACE is not set
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
diff --git a/kernel/fiasco/src/templates/globalconfig.out.ppc32-1 b/kernel/fiasco/src/templates/globalconfig.out.ppc32-1
new file mode 100644 (file)
index 0000000..feb4823
--- /dev/null
@@ -0,0 +1,59 @@
+#
+# Automatically generated file; DO NOT EDIT.
+
+#
+# Target configuration
+#
+# CONFIG_IA32 is not set
+# CONFIG_AMD64 is not set
+# CONFIG_ARM is not set
+CONFIG_PPC32=y
+# CONFIG_SPARC is not set
+CONFIG_BIG_ENDIAN=y
+CONFIG_PF_MPC52XX=y
+# CONFIG_PF_QEMU is not set
+CONFIG_BSP_NAME="mpc52xx"
+CONFIG_ABI_VF=y
+CONFIG_PPC32_603e=y
+
+#
+# Kernel options
+#
+CONFIG_CONTEXT_4K=y
+# CONFIG_FINE_GRAINED_CPUTIME is not set
+CONFIG_SCHED_FIXED_PRIO=y
+# CONFIG_SCHED_WFQ is not set
+# CONFIG_SCHED_FP_WFQ is not set
+CONFIG_VIRT_OBJ_SPACE=y
+
+#
+# Debugging
+#
+CONFIG_INLINE=y
+# CONFIG_NDEBUG is not set
+# CONFIG_NO_FRAME_PTR is not set
+# CONFIG_STACK_DEPTH is not set
+# CONFIG_LIST_ALLOC_SANITY is not set
+CONFIG_SERIAL=y
+CONFIG_JDB=y
+# CONFIG_JDB_LOGGING is not set
+CONFIG_JDB_DISASM=y
+CONFIG_JDB_GZIP=y
+# CONFIG_WARN_NONE is not set
+CONFIG_WARN_WARNING=y
+# CONFIG_WARN_ANY is not set
+
+#
+# Compiling
+#
+CONFIG_CC="gcc"
+CONFIG_CXX="g++"
+CONFIG_HOST_CC="gcc"
+CONFIG_HOST_CXX="g++"
+# CONFIG_MAINTAINER_MODE is not set
+CONFIG_LABEL=""
+CONFIG_EXPERIMENTAL=y
+CONFIG_BIT32=y
+CONFIG_WARN_LEVEL=1
+CONFIG_XARCH="ppc32"
+CONFIG_ABI="vf"
diff --git a/kernel/fiasco/src/templates/globalconfig.out.sparc-1 b/kernel/fiasco/src/templates/globalconfig.out.sparc-1
new file mode 100644 (file)
index 0000000..64bc6a4
--- /dev/null
@@ -0,0 +1,57 @@
+#
+# Automatically generated file; DO NOT EDIT.
+
+#
+# Target configuration
+#
+# CONFIG_IA32 is not set
+# CONFIG_AMD64 is not set
+# CONFIG_ARM is not set
+# CONFIG_PPC32 is not set
+CONFIG_SPARC=y
+CONFIG_PF_LEON3=y
+CONFIG_BSP_NAME="leon3"
+CONFIG_ABI_VF=y
+CONFIG_LEON3=y
+
+#
+# Kernel options
+#
+CONFIG_CONTEXT_4K=y
+# CONFIG_FINE_GRAINED_CPUTIME is not set
+CONFIG_SCHED_FIXED_PRIO=y
+# CONFIG_SCHED_WFQ is not set
+# CONFIG_SCHED_FP_WFQ is not set
+CONFIG_VIRT_OBJ_SPACE=y
+
+#
+# Debugging
+#
+CONFIG_INLINE=y
+# CONFIG_NDEBUG is not set
+CONFIG_NO_FRAME_PTR=y
+# CONFIG_STACK_DEPTH is not set
+# CONFIG_LIST_ALLOC_SANITY is not set
+CONFIG_SERIAL=y
+CONFIG_JDB=y
+# CONFIG_JDB_LOGGING is not set
+CONFIG_JDB_DISASM=y
+CONFIG_JDB_GZIP=y
+# CONFIG_WARN_NONE is not set
+CONFIG_WARN_WARNING=y
+# CONFIG_WARN_ANY is not set
+
+#
+# Compiling
+#
+CONFIG_CC="gcc"
+CONFIG_CXX="g++"
+CONFIG_HOST_CC="gcc"
+CONFIG_HOST_CXX="g++"
+# CONFIG_MAINTAINER_MODE is not set
+CONFIG_LABEL=""
+CONFIG_EXPERIMENTAL=y
+CONFIG_BIT32=y
+CONFIG_WARN_LEVEL=1
+CONFIG_XARCH="sparc"
+CONFIG_ABI="vf"
index 70c8c92087d07b21ad765a88ef0226be1fef5cec..e4bedb4a6ec0a0566d6c9ec8cd0071e0d81c8efa 100644 (file)
@@ -33,6 +33,7 @@ CONFIG_CONTEXT_4K=y
 # CONFIG_UX_CON is not set
 # CONFIG_UX_NET is not set
 CONFIG_SCHED_FIXED_PRIO=y
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
index a0ba73d4b09899ed7f11c0d42bcc1b5283c6008a..da26698b3de30ac14bf3c4cbfedf6b6a46a5f3a3 100644 (file)
@@ -38,6 +38,7 @@ CONFIG_CONTEXT_4K=y
 # CONFIG_SCHED_FIXED_PRIO is not set
 CONFIG_SCHED_WFQ=y
 # CONFIG_SCHED_FP_WFQ is not set
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
@@ -64,7 +65,7 @@ CONFIG_CC="gcc"
 CONFIG_CXX="g++"
 CONFIG_HOST_CC="gcc"
 CONFIG_HOST_CXX="g++"
-# CONFIG_MAINTAINER_MODE is not set
+CONFIG_MAINTAINER_MODE=y
 CONFIG_LABEL=""
 CONFIG_EXPERIMENTAL=y
 CONFIG_PERF_CNT=y
index 81fb109a65c9b98de5a753592e9f774acf7e4846..d45dd76df79e80475689d1f77838865d6ade796e 100644 (file)
@@ -33,6 +33,7 @@ CONFIG_CONTEXT_4K=y
 # CONFIG_UX_CON is not set
 # CONFIG_UX_NET is not set
 CONFIG_SCHED_FIXED_PRIO=y
+CONFIG_VIRT_OBJ_SPACE=y
 
 #
 # Debugging
index 7f03fe2320d80ed783d656be20408ebf13bd0a44..d3f73d1f75bd6404203e6f545382927f55b12f7f 100644 (file)
@@ -23,7 +23,6 @@ using namespace std;
 #include "static_init.h"
 #include "usermode.h"
 #include "vmem_alloc.h"
-#include "mem_space_sigma0.h"
 
 IMPLEMENTATION:
 
@@ -32,17 +31,50 @@ typedef L4_fpage Test_fpage;
 class Test_space : public Space
 {
 public:
-  Test_space (Ram_quota *rq)
-    : Space (Space::Default_factory(), rq, L4_fpage::mem(0x1200000, Config::PAGE_SHIFT))
-  {}
+  Test_space(Ram_quota *rq, char const *name)
+  : Space(rq, Caps::all()), name(name)
+  {
+    initialize();
+  }
 
   void* operator new (size_t s)
   { return malloc (s); }
 
   void operator delete (void *p)
   { ::free (p); }
+
+  char const *const name;
+};
+
+class Sigma0_space : public Test_space
+{
+public:
+  explicit Sigma0_space(Ram_quota *q) : Test_space(q, "s0") {}
+  bool is_sigma0() const { return true; }
 };
 
+
+PUBLIC
+bool
+Sigma0_space::v_fabricate(Mem_space::Vaddr address,
+                          Mem_space::Phys_addr *phys, Mem_space::Page_order *size,
+                          Mem_space::Attr *attribs = 0)
+{
+  // special-cased because we don't do ptab lookup for sigma0
+  *size = static_cast<Mem_space const &>(*this).largest_page_size();
+  *phys = cxx::mask_lsb(Virt_addr(address), *size);
+
+  if (attribs)
+    *attribs = Mem_space::Attr(L4_fpage::Rights::URWX());
+
+  return true;
+}
+
+PUBLIC inline
+Page_number
+Sigma0_space::mem_space_map_max_address() const
+{ return Page_number(1UL << (MWORD_BITS - Mem_space::Page_shift)); }
+
 class Timeout;
 
 DEFINE_PER_CPU Per_cpu<Timeout *> timeslice_timeout;
@@ -51,18 +83,18 @@ STATIC_INITIALIZER_P(init2, POST_CPU_LOCAL_INIT_PRIO);
 
 static void init()
 {
-  Usermode::init(0);
+  Usermode::init(Cpu_number::boot_cpu());
   Boot_info::init();
-  Kip_init::setup_ux();
-  Kmem_alloc::base_init();
   Kip_init::init();
+  Kmem_alloc::base_init();
   Kmem_alloc::init();
 
   // 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(Cpu_number::boot_cpu());
+  Per_cpu_data::run_ctors(Cpu_number::boot_cpu());
 
+  Mem_space::init_page_sizes();
 }
 
 static void init2()
@@ -70,182 +102,180 @@ static void init2()
   Cpu::init_global_features();
   Config::init();
   Kmem::init_mmu(*Cpu::boot_cpu());
-  Vmem_alloc::init();
   Pic::init();
 }
 
-static Ram_quota rq;
-
-struct Sigma0_space_factory
+class Fake_factory : public Ram_quota
 {
-  static void create(Mem_space *v, Ram_quota *q)
-  { new (v) Mem_space_sigma0(q); }
+};
 
-  template< typename S >
-  static void create(S *v)
-  { new (v) S(); }
+extern Static_object<Mapdb> mapdb_mem;
+static Fake_factory rq;
 
-};
+static
+Mem_space *ms(Space *s) { return s; }
+
+static
+Mem_space::Vaddr
+to_vaddr(Address a)
+{ return Mem_space::Vaddr(Virt_addr(a)); }
+
+static
+Mapdb::Pfn to_pfn(Address a)
+{ return Mem_space::to_pfn(Virt_addr(a)); }
 
 int main()
 {
-  // 
-  // Create tasks
-  // 
-  Space *sigma0 = new Space (Sigma0_space_factory(), &rq, L4_fpage::mem(0x1200000, Config::PAGE_SHIFT));
+  cout << "[UTEST] *** Create tasks ***" << endl;
+
+  Space *sigma0 = new Sigma0_space(&rq);
 
   init_mapdb_mem(sigma0);
 
-  Test_space *server = new Test_space (&rq);
+  Test_space *server = new Test_space (&rq, "server");
   assert (server);
-  Test_space *client = new Test_space (&rq);
+  Test_space *client = new Test_space (&rq, "client");
   assert (client);
-  Test_space *client2 = new Test_space (&rq);
+  Test_space *client2 = new Test_space (&rq, "client2");
   assert (client2);
 
-  // 
-  // Manipulate mappings.
-  // 
-  Mapdb* mapdb = mapdb_instance();
+  cout << "[UTEST] *** Manipulate mappings ***" << endl;
+
+  Mapdb* mapdb = mapdb_mem.get();
 
-  Mem_space::Phys_addr phys;
-  Virt_size size;
-  unsigned page_attribs;
+  typedef Mem_space::Page_order Page_order;
+  typedef Mem_space::Phys_addr Phys_addr;
+  typedef Mem_space::Attr Attr;;
+
+  Phys_addr phys;
+  Page_order order;
+  Attr page_attribs;
   Mapping *m;
   Mapdb::Frame frame;
-  
-  // 
-  // s0 [0x10000] -> server [0x1000]
-  // 
-  assert (server->mem_space()->v_lookup (Virt_addr(0x1000), &phys, &size, &page_attribs) 
+
+  cout << "[UTEST] s0 [0x10000] -> server [0x1000]" << endl;
+
+  assert (ms(server)->v_lookup(to_vaddr(0x1000), &phys, &order, &page_attribs) 
          == false);
   Reap_list reap;
-  fpage_map (sigma0, 
-            Test_fpage::mem(0x10000, Config::PAGE_SHIFT, L4_fpage::RWX),
-            server,
-            L4_fpage::all_spaces(),
-            0x1000, &reap);
+  fpage_map(sigma0,
+           Test_fpage::mem(0x10000, Config::PAGE_SHIFT, L4_fpage::Rights::URWX()),
+           server,
+           L4_fpage::all_spaces(),
+           L4_msg_item(0x1000), &reap);
 
-  assert (server->mem_space()->v_lookup (Virt_addr(0x1000), &phys, &size, &page_attribs)
+  assert (ms(server)->v_lookup(to_vaddr(0x1000), &phys, &order, &page_attribs)
          == true);
-  assert (size == Virt_size(Config::PAGE_SIZE));
-  assert (phys == Virt_addr(0x10000));
-  assert (page_attribs == (Mem_space::Page_writable 
-                          | Mem_space::Page_user_accessible));
+  assert (order == Page_order(Config::PAGE_SHIFT));
+  assert (phys == Phys_addr(0x10000));
+  assert (page_attribs.rights == L4_fpage::Rights::URWX());
 
-  assert (mapdb->lookup (sigma0, Virt_addr(0x10000), Virt_addr(0x10000), &m, &frame));
+  assert (mapdb->lookup(sigma0, to_pfn(0x10000), to_pfn(0x10000), &m, &frame));
   print_node (m, frame);
   mapdb->free (frame);
 
-  // 
-  // s0 [0/superpage] -> server [0] -> should map many 4K pages and
-  // overmap previous mapping
-  // 
-  assert (server->mem_space()->v_lookup (Virt_addr(0), &phys, &size, &page_attribs)
+  cout << "[UTEST] s0 [0/superpage] -> server [0] -> should map many 4K pages and "
+          "overmap previous mapping" << endl;
+
+  assert (ms(server)->v_lookup(to_vaddr(0), &phys, &order, &page_attribs)
          == false);
 
-  fpage_map (sigma0, 
-            L4_fpage::mem(0, Config::SUPERPAGE_SHIFT, L4_fpage::RX),
-            server,
-            L4_fpage::all_spaces(),
-            0, &reap);
+  fpage_map(sigma0,
+           L4_fpage::mem(0, Config::SUPERPAGE_SHIFT, L4_fpage::Rights::URX()),
+           server,
+           L4_fpage::all_spaces(),
+           L4_msg_item(0), &reap);
 
-  assert (server->mem_space()->v_lookup (Virt_addr(0), &phys, &size, &page_attribs)
+  assert (ms(server)->v_lookup(to_vaddr(0), &phys, &order, &page_attribs)
          == true);
-  assert (size == Virt_size(Config::PAGE_SIZE));       // and not SUPERPAGE_SIZE!
-  assert (phys == Virt_addr(0));
-  assert (page_attribs == Mem_space::Page_user_accessible);
+  assert (order == Page_order(Config::PAGE_SHIFT));    // and not SUPERPAGE_SIZE!
+  assert (phys == Phys_addr(0));
+  assert (page_attribs.rights == L4_fpage::Rights::URX());
 
-  assert (mapdb->lookup (sigma0, Virt_addr(0), Virt_addr(0), &m, &frame));
+  assert (mapdb->lookup(sigma0, to_pfn(0), to_pfn(0), &m, &frame));
   print_node (m, frame);
   mapdb->free (frame);
 
   // previous mapping still there?
 
-  assert (server->mem_space()->v_lookup (Virt_addr(0x1000), &phys, &size, &page_attribs)
-         == true);
-  assert (size == Virt_size(Config::PAGE_SIZE));
+  assert (ms(server)->v_lookup(to_vaddr(0x1000), &phys, &order, &page_attribs));
+  assert (order == Page_order(Config::PAGE_SHIFT));
   // Previously, overmapping did not work and was ignored, so the
   // lookup yielded the previously established mapping:
   //   assert (phys == 0x10000);
   //   assert (page_attribs == (Mem_space::Page_writable | Mem_space::Page_user_accessible));
   // Now, the previous mapping should have been overwritten:
-  assert (phys == Virt_addr(0x1000));
-  assert (page_attribs == Mem_space::Page_user_accessible);
+  assert (phys == Phys_addr(0x1000));
+  assert (page_attribs.rights == L4_fpage::Rights::URX());
 
   // mapdb entry -- tree should now contain another mapping 
   // s0 [0x10000] -> server [0x10000]
-  assert (mapdb->lookup (sigma0, Virt_addr(0x10000), Virt_addr(0x10000), &m, &frame));
+  assert (mapdb->lookup(sigma0, to_pfn(0x10000), to_pfn(0x10000), &m, &frame));
   print_node (m, frame, 0x10000, 0x11000);
   mapdb->free (frame);
 
-  // 
-  // Partially unmap superpage s0 [0/superpage]
-  // 
-  assert (server->mem_space()->v_lookup (Virt_addr(0x101000), &phys, &size, &page_attribs)
+  cout << "[UTEST] Partially unmap superpage s0 [0/superpage]" << endl;
+
+  assert (ms(server)->v_lookup(to_vaddr(0x101000), &phys, &order, &page_attribs)
          == true);
-  assert (size == Virt_size(Config::PAGE_SIZE));
-  assert (phys == Virt_addr(0x101000));
-  assert (page_attribs == Mem_space::Page_user_accessible);
+  assert (order == Page_order(Config::PAGE_SHIFT));
+  assert (phys == Phys_addr(0x101000));
+  assert (page_attribs.rights == L4_fpage::Rights::URX());
 
-  fpage_unmap (sigma0, 
-              Test_fpage::mem(0x100000, Config::SUPERPAGE_SHIFT - 2, L4_fpage::RWX),
-              L4_map_mask(0) /*full unmap, not me too)*/, reap.list());
+  fpage_unmap(sigma0, 
+             Test_fpage::mem(0x100000, Config::SUPERPAGE_SHIFT - 2, L4_fpage::Rights::URWX()),
+             L4_map_mask(0) /*full unmap, not me too)*/, reap.list());
   
-  assert (mapdb->lookup (sigma0, Virt_addr(0x0), Virt_addr(0x0), &m, &frame));
+  assert (mapdb->lookup(sigma0, to_pfn(0x0), to_pfn(0x0), &m, &frame));
   print_node (m, frame);
   mapdb->free (frame);
-  
-  assert (! server->mem_space()->v_lookup (Virt_addr(0x101000), &phys, &size, 
-                                          &page_attribs)
-         == true);
+
+  assert (! ms(server)->v_lookup(to_vaddr(0x101000), &phys, &order, &page_attribs));
 
   // 
   // s0 [4M/superpage] -> server [8M]
   // 
-  assert (server->mem_space()->v_lookup (Virt_addr(0x800000), &phys, &size, &page_attribs)
+  assert (ms(server)->v_lookup(to_vaddr(0x800000), &phys, &order, &page_attribs)
          == false);
 
-  fpage_map (sigma0,
-            Test_fpage::mem(0x400000, Config::SUPERPAGE_SHIFT, L4_fpage::RWX),
-            server,
-            L4_fpage::mem(0x800000, Config::SUPERPAGE_SHIFT),
-            0, &reap);
+  fpage_map(sigma0,
+           Test_fpage::mem(0x400000, Config::SUPERPAGE_SHIFT, L4_fpage::Rights::URWX()),
+           server,
+           L4_fpage::mem(0x800000, Config::SUPERPAGE_SHIFT),
+           L4_msg_item(0), &reap);
 
-  assert (server->mem_space()->v_lookup (Virt_addr(0x800000), &phys, &size, &page_attribs)
+  assert (ms(server)->v_lookup(to_vaddr(0x800000), &phys, &order, &page_attribs)
          == true);
-  assert (size == Virt_size(Config::SUPERPAGE_SIZE));
+  assert (order == Page_order(Config::SUPERPAGE_SHIFT));
   assert (phys == Virt_addr(0x400000));
-  assert (page_attribs == (Mem_space::Page_writable 
-                          | Mem_space::Page_user_accessible));
+  assert (page_attribs.rights == L4_fpage::Rights::URWX());
 
-  assert (mapdb->lookup (sigma0, Virt_addr(0x400000), Virt_addr(0x400000), &m, &frame));
+  assert (mapdb->lookup(sigma0, to_pfn(0x400000), to_pfn(0x400000), &m, &frame));
   print_node (m, frame);
   mapdb->free (frame);
 
   // 
   // server [8M+4K] -> client [8K]
   // 
-  assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs)
+  assert (ms(client)->v_lookup(to_vaddr(0x8000), &phys, &order, &page_attribs)
          == false);
 
-  fpage_map (server, 
-            Test_fpage::mem(0x801000, Config::PAGE_SHIFT, L4_fpage::RWX),
-            client,
-            L4_fpage::mem(0, L4_fpage::Whole_space),
-            0x8000, &reap);
+  fpage_map(server, 
+           Test_fpage::mem(0x801000, Config::PAGE_SHIFT, L4_fpage::Rights::URWX()),
+           client,
+           L4_fpage::mem(0, L4_fpage::Whole_space),
+           L4_msg_item(0x8000), &reap);
 
-  assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs)
+  assert (ms(client)->v_lookup(to_vaddr(0x8000), &phys, &order, &page_attribs)
          == true);
-  assert (size == Virt_size(Config::PAGE_SIZE));
+  assert (order == Page_order(Config::PAGE_SHIFT));
   assert (phys == Virt_addr(0x401000));
-  assert (page_attribs == (Mem_space::Page_writable 
-                          | Mem_space::Page_user_accessible));
+  assert (page_attribs.rights == L4_fpage::Rights::URWX());
 
   // Previously, the 4K submapping is attached to the Sigma0 parent.
   // Not any more.
 
-  assert (mapdb->lookup (sigma0, Virt_addr(0x400000), Virt_addr(0x400000), &m, &frame));
+  assert (mapdb->lookup(sigma0, to_pfn(0x400000), to_pfn(0x400000), &m, &frame));
   print_node (m, frame);
   mapdb->free (frame);
 
@@ -253,18 +283,17 @@ int main()
   // Overmap a read-only page.  The writable attribute should not be
   // flushed.
   //
-  fpage_map (server,
-            Test_fpage::mem(0x801000, Config::PAGE_SHIFT, L4_fpage::RX),
-            client,
-            L4_fpage::mem(0, L4_fpage::Whole_space),
-            0x8000, &reap);
+  fpage_map(server,
+           Test_fpage::mem(0x801000, Config::PAGE_SHIFT, L4_fpage::Rights::URX()),
+           client,
+           L4_fpage::mem(0, L4_fpage::Whole_space),
+           L4_msg_item(0x8000), &reap);
 
-  assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs)
+  assert (ms(client)->v_lookup(to_vaddr(0x8000), &phys, &order, &page_attribs)
          == true);
-  assert (size == Virt_size(Config::PAGE_SIZE));
+  assert (order == Page_order(Config::PAGE_SHIFT));
   assert (phys == Virt_addr(0x401000));
-  assert (page_attribs == (Mem_space::Page_writable 
-                          | Mem_space::Page_user_accessible));  
+  assert (page_attribs.rights == L4_fpage::Rights::URWX());
 
 #if 0 // no selective unmap anymore
   // 
@@ -306,7 +335,6 @@ int main()
   print_node (m, frame);
   mapdb->free (frame);
 #endif
-  cerr << "... ";
 
 
   // 
@@ -314,68 +342,51 @@ int main()
   // 
   
   // touch page in client
-  assert (client->mem_space()->v_insert (Virt_addr(0x401000), Virt_addr(0x8000), Virt_size(Config::PAGE_SIZE), 
-                           Mem_space::Page_dirty | Mem_space::Page_referenced)
-         == Mem_space::Insert_warn_attrib_upgrade);
+  ms(client)->v_set_access_flags(to_vaddr(0x8000), L4_fpage::Rights::RW());
 
-  assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs)
+  assert (ms(client)->v_lookup(to_vaddr(0x8000), &phys, &order, &page_attribs)
          == true);
-  assert (size == Virt_size(Config::PAGE_SIZE));
+  assert (order == Page_order(Config::PAGE_SHIFT));
   assert (phys == Virt_addr(0x401000));
-  assert (page_attribs == (Mem_space::Page_writable
-                          | Mem_space::Page_user_accessible
-                          | Mem_space::Page_dirty | Mem_space::Page_referenced));
+  assert (page_attribs.rights == L4_fpage::Rights::URWX());
+  // the next would reset flags, so don't do it!!
+  // assert (ms(client)->v_delete(to_vaddr(0x8000), order, L4_fpage::Rights(0)) == L4_fpage::Rights::RW());
+
   // reset dirty from server
-  assert (fpage_unmap (server,
-                      Test_fpage::mem(0x801000, Config::PAGE_SHIFT),
-                      L4_map_mask(0), reap.list()
-                      /*no_unmap + reset_refs*/)
-         == Mem_space::Page_referenced | Mem_space::Page_dirty);
+  assert (fpage_unmap(server,
+                     Test_fpage::mem(0x801000, Config::PAGE_SHIFT),
+                     L4_map_mask(0), reap.list()
+                     /*no_unmap + reset_refs*/)
+         == L4_fpage::Rights::RW());
 
-  assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs)
+  assert (ms(client)->v_lookup(to_vaddr(0x8000), &phys, &order, &page_attribs)
          == true);
-  assert (size == Virt_size(Config::PAGE_SIZE));
+  assert (order == Page_order(Config::PAGE_SHIFT));
   assert (phys == Virt_addr(0x401000));
-  assert (page_attribs == (Mem_space::Page_writable 
-                          | Mem_space::Page_user_accessible)); // Page_dirty | Page_referecned is gone...
+  assert (ms(client)->v_delete(to_vaddr(0x8000), order, L4_fpage::Rights(0)) == L4_fpage::Rights(0));
 
-  assert (server->mem_space()->v_lookup (Virt_addr(0x801000), &phys, &size, &page_attribs)
+  assert (ms(server)->v_lookup(to_vaddr(0x801000), &phys, &order, &page_attribs)
          == true);
-  assert (size == Virt_size(Config::SUPERPAGE_SIZE));
+  assert (order == Page_order(Config::SUPERPAGE_SHIFT));
   assert (phys == Virt_addr(0x400000));
-  assert (page_attribs == (Mem_space::Page_writable 
-                          | Mem_space::Page_user_accessible
-                          | Mem_space::Page_dirty | Mem_space::Page_referenced)); // ...and went here
 
   // flush dirty and accessed from server
-  assert (fpage_unmap (server, 
-                      Test_fpage::mem(0x800000, Config::SUPERPAGE_SHIFT),
-                      L4_map_mask(0x80000000), reap.list())
-         == Mem_space::Page_dirty | Mem_space::Page_referenced);
+  assert (fpage_unmap(server,
+                     Test_fpage::mem(0x800000, Config::SUPERPAGE_SHIFT),
+                     L4_map_mask(0x80000000), reap.list())
+         == L4_fpage::Rights::RW());
 
-  assert (client->mem_space()->v_lookup (Virt_addr(0x8000), &phys, &size, &page_attribs)
+  assert (ms(client)->v_lookup(to_vaddr(0x8000), &phys, &order, &page_attribs)
          == true);
-  assert (size == Virt_size(Config::PAGE_SIZE));
+  assert (order == Page_order(Config::PAGE_SHIFT));
   assert (phys == Virt_addr(0x401000));
-  assert (page_attribs == (Mem_space::Page_writable 
-                          | Mem_space::Page_user_accessible)); // dirty/ref gone
-
-  assert (server->mem_space()->v_lookup (Virt_addr(0x800000), &phys, &size, &page_attribs)
-         == true);
-  assert (size == Virt_size(Config::SUPERPAGE_SIZE));
-  assert (phys == Virt_addr(0x400000));
-  assert (page_attribs == (Mem_space::Page_writable 
-                          | Mem_space::Page_user_accessible)); // dirty/ref gone
+  assert (ms(client)->v_delete(to_vaddr(0x8000), order, L4_fpage::Rights(0)) == L4_fpage::Rights(0));
 
-  assert (sigma0->mem_space()->v_lookup (Virt_addr(0x400000), &phys, &size, &page_attribs)
+  assert (ms(server)->v_lookup(to_vaddr(0x800000), &phys, &order, &page_attribs)
          == true);
-  assert (size == Virt_size(Config::SUPERPAGE_SIZE));
+  assert (order == Page_order(Config::SUPERPAGE_SHIFT));
   assert (phys == Virt_addr(0x400000));
-  // Be a bit more lax in checking Sigma0's address space:  It does
-  // not contain Page_writable / Page_user_accessible flags unless
-  // they are faulted in.
-  assert (page_attribs & (Mem_space::Page_dirty | Mem_space::Page_referenced));
-
+  assert (page_attribs.rights == L4_fpage::Rights::URWX());
 
   // 
   // Delete tasks
@@ -394,27 +405,55 @@ int main()
   return 0;
 }
 
+
+static
+std::ostream &operator << (std::ostream &s, Mapdb::Pfn v)
+{
+  s << cxx::int_value<Mapdb::Pfn>(v);
+  return s;
+}
+
+static
+std::ostream &operator << (std::ostream &s, Mapping::Page v)
+{
+  s << cxx::int_value<Mapping::Page>(v);
+  return s;
+}
+
+static
+std::ostream &operator << (std::ostream &s, Space const &sp)
+{
+  Test_space const *t = static_cast<Test_space const *>(&sp);
+  if (!t)
+    s << "<NULL>";
+  else
+    s << t->name;
+  return s;
+}
+
+
 static void print_node(Mapping* node, const Mapdb::Frame& frame,
                       Address va_begin = 0, Address va_end = ~0UL)
 {
   assert (node);
 
-  size_t size = Mapdb::shift(frame, node);
+  Mapdb::Order size = Mapdb::shift(frame, node);
 
-  for (Mapdb::Iterator i (frame, node, Virt_addr(va_begin), Virt_addr(va_end)); node;)
+  for (Mapdb::Iterator i (frame, node, to_pfn(va_begin), to_pfn(va_end)); node;)
     {
+      cout << "[UTEST] ";
       for (int d = node->depth(); d != 0; d--)
         cout << ' ';
 
       cout << setbase(16)
-          << "space=0x"  << (unsigned long) (node->space())
-          << " vaddr=0x" << node->page() << size
-          << " size=0x" << size;
+          << "space="  << *node->space()
+          << " vaddr=0x" << (node->page() << size)
+          << " size=0x" << (Mapdb::Pfn(1) << size);
 
       if (Mapping* p = node->parent())
        {
-         cout << " parent=0x" << (unsigned long)p->space()
-              << " p.vaddr=0x" << p->page().value() << size;
+         cout << " parent=" << *p->space()
+              << " p.vaddr=0x" << (p->page() << size);
        }
 
       cout << endl;
@@ -422,10 +461,10 @@ static void print_node(Mapping* node, const Mapdb::Frame& frame,
       node = i;
       if (node)
        {
-         size = i.shift();
+         size = i.order();
          ++i;
        }
     }
-  cout << endl;
+  cout << "[UTEST] " << endl;
 }
 
diff --git a/kernel/fiasco/src/test/unit/map_util_t.out.verify.vf b/kernel/fiasco/src/test/unit/map_util_t.out.verify.vf
new file mode 100755 (executable)
index 0000000..a5f119d
--- /dev/null
@@ -0,0 +1,1814 @@
+[UTEST] *** Create tasks ***
+[UTEST] *** Manipulate mappings ***
+[UTEST] s0 [0x10000] -> server [0x1000]
+[UTEST] space=s0 vaddr=0x0 size=0x400
+[UTEST]  space=server vaddr=0x1 size=0x1 parent=s0 p.vaddr=0x10
+[UTEST] 
+[UTEST] s0 [0/superpage] -> server [0] -> should map many 4K pages and overmap previous mapping
+[UTEST] space=s0 vaddr=0x0 size=0x400
+[UTEST]  space=server vaddr=0x0 size=0x1 parent=s0 p.vaddr=0x0
+[UTEST]  space=server vaddr=0x1 size=0x1 parent=s0 p.vaddr=0x1
+[UTEST]  space=server vaddr=0x2 size=0x1 parent=s0 p.vaddr=0x2
+[UTEST]  space=server vaddr=0x3 size=0x1 parent=s0 p.vaddr=0x3
+[UTEST]  space=server vaddr=0x4 size=0x1 parent=s0 p.vaddr=0x4
+[UTEST]  space=server vaddr=0x5 size=0x1 parent=s0 p.vaddr=0x5
+[UTEST]  space=server vaddr=0x6 size=0x1 parent=s0 p.vaddr=0x6
+[UTEST]  space=server vaddr=0x7 size=0x1 parent=s0 p.vaddr=0x7
+[UTEST]  space=server vaddr=0x8 size=0x1 parent=s0 p.vaddr=0x8
+[UTEST]  space=server vaddr=0x9 size=0x1 parent=s0 p.vaddr=0x9
+[UTEST]  space=server vaddr=0xa size=0x1 parent=s0 p.vaddr=0xa
+[UTEST]  space=server vaddr=0xb size=0x1 parent=s0 p.vaddr=0xb
+[UTEST]  space=server vaddr=0xc size=0x1 parent=s0 p.vaddr=0xc
+[UTEST]  space=server vaddr=0xd size=0x1 parent=s0 p.vaddr=0xd
+[UTEST]  space=server vaddr=0xe size=0x1 parent=s0 p.vaddr=0xe
+[UTEST]  space=server vaddr=0xf size=0x1 parent=s0 p.vaddr=0xf
+[UTEST]  space=server vaddr=0x10 size=0x1 parent=s0 p.vaddr=0x10
+[UTEST]  space=server vaddr=0x11 size=0x1 parent=s0 p.vaddr=0x11
+[UTEST]  space=server vaddr=0x12 size=0x1 parent=s0 p.vaddr=0x12
+[UTEST]  space=server vaddr=0x13 size=0x1 parent=s0 p.vaddr=0x13
+[UTEST]  space=server vaddr=0x14 size=0x1 parent=s0 p.vaddr=0x14
+[UTEST]  space=server vaddr=0x15 size=0x1 parent=s0 p.vaddr=0x15
+[UTEST]  space=server vaddr=0x16 size=0x1 parent=s0 p.vaddr=0x16
+[UTEST]  space=server vaddr=0x17 size=0x1 parent=s0 p.vaddr=0x17
+[UTEST]  space=server vaddr=0x18 size=0x1 parent=s0 p.vaddr=0x18
+[UTEST]  space=server vaddr=0x19 size=0x1 parent=s0 p.vaddr=0x19
+[UTEST]  space=server vaddr=0x1a size=0x1 parent=s0 p.vaddr=0x1a
+[UTEST]  space=server vaddr=0x1b size=0x1 parent=s0 p.vaddr=0x1b
+[UTEST]  space=server vaddr=0x1c size=0x1 parent=s0 p.vaddr=0x1c
+[UTEST]  space=server vaddr=0x1d size=0x1 parent=s0 p.vaddr=0x1d
+[UTEST]  space=server vaddr=0x1e size=0x1 parent=s0 p.vaddr=0x1e
+[UTEST]  space=server vaddr=0x1f size=0x1 parent=s0 p.vaddr=0x1f
+[UTEST]  space=server vaddr=0x20 size=0x1 parent=s0 p.vaddr=0x20
+[UTEST]  space=server vaddr=0x21 size=0x1 parent=s0 p.vaddr=0x21
+[UTEST]  space=server vaddr=0x22 size=0x1 parent=s0 p.vaddr=0x22
+[UTEST]  space=server vaddr=0x23 size=0x1 parent=s0 p.vaddr=0x23
+[UTEST]  space=server vaddr=0x24 size=0x1 parent=s0 p.vaddr=0x24
+[UTEST]  space=server vaddr=0x25 size=0x1 parent=s0 p.vaddr=0x25
+[UTEST]  space=server vaddr=0x26 size=0x1 parent=s0 p.vaddr=0x26
+[UTEST]  space=server vaddr=0x27 size=0x1 parent=s0 p.vaddr=0x27
+[UTEST]  space=server vaddr=0x28 size=0x1 parent=s0 p.vaddr=0x28
+[UTEST]  space=server vaddr=0x29 size=0x1 parent=s0 p.vaddr=0x29
+[UTEST]  space=server vaddr=0x2a size=0x1 parent=s0 p.vaddr=0x2a
+[UTEST]  space=server vaddr=0x2b size=0x1 parent=s0 p.vaddr=0x2b
+[UTEST]  space=server vaddr=0x2c size=0x1 parent=s0 p.vaddr=0x2c
+[UTEST]  space=server vaddr=0x2d size=0x1 parent=s0 p.vaddr=0x2d
+[UTEST]  space=server vaddr=0x2e size=0x1 parent=s0 p.vaddr=0x2e
+[UTEST]  space=server vaddr=0x2f size=0x1 parent=s0 p.vaddr=0x2f
+[UTEST]  space=server vaddr=0x30 size=0x1 parent=s0 p.vaddr=0x30
+[UTEST]  space=server vaddr=0x31 size=0x1 parent=s0 p.vaddr=0x31
+[UTEST]  space=server vaddr=0x32 size=0x1 parent=s0 p.vaddr=0x32
+[UTEST]  space=server vaddr=0x33 size=0x1 parent=s0 p.vaddr=0x33
+[UTEST]  space=server vaddr=0x34 size=0x1 parent=s0 p.vaddr=0x34
+[UTEST]  space=server vaddr=0x35 size=0x1 parent=s0 p.vaddr=0x35
+[UTEST]  space=server vaddr=0x36 size=0x1 parent=s0 p.vaddr=0x36
+[UTEST]  space=server vaddr=0x37 size=0x1 parent=s0 p.vaddr=0x37
+[UTEST]  space=server vaddr=0x38 size=0x1 parent=s0 p.vaddr=0x38
+[UTEST]  space=server vaddr=0x39 size=0x1 parent=s0 p.vaddr=0x39
+[UTEST]  space=server vaddr=0x3a size=0x1 parent=s0 p.vaddr=0x3a
+[UTEST]  space=server vaddr=0x3b size=0x1 parent=s0 p.vaddr=0x3b
+[UTEST]  space=server vaddr=0x3c size=0x1 parent=s0 p.vaddr=0x3c
+[UTEST]  space=server vaddr=0x3d size=0x1 parent=s0 p.vaddr=0x3d
+[UTEST]  space=server vaddr=0x3e size=0x1 parent=s0 p.vaddr=0x3e
+[UTEST]  space=server vaddr=0x3f size=0x1 parent=s0 p.vaddr=0x3f
+[UTEST]  space=server vaddr=0x40 size=0x1 parent=s0 p.vaddr=0x40
+[UTEST]  space=server vaddr=0x41 size=0x1 parent=s0 p.vaddr=0x41
+[UTEST]  space=server vaddr=0x42 size=0x1 parent=s0 p.vaddr=0x42
+[UTEST]  space=server vaddr=0x43 size=0x1 parent=s0 p.vaddr=0x43
+[UTEST]  space=server vaddr=0x44 size=0x1 parent=s0 p.vaddr=0x44
+[UTEST]  space=server vaddr=0x45 size=0x1 parent=s0 p.vaddr=0x45
+[UTEST]  space=server vaddr=0x46 size=0x1 parent=s0 p.vaddr=0x46
+[UTEST]  space=server vaddr=0x47 size=0x1 parent=s0 p.vaddr=0x47
+[UTEST]  space=server vaddr=0x48 size=0x1 parent=s0 p.vaddr=0x48
+[UTEST]  space=server vaddr=0x49 size=0x1 parent=s0 p.vaddr=0x49
+[UTEST]  space=server vaddr=0x4a size=0x1 parent=s0 p.vaddr=0x4a
+[UTEST]  space=server vaddr=0x4b size=0x1 parent=s0 p.vaddr=0x4b
+[UTEST]  space=server vaddr=0x4c size=0x1 parent=s0 p.vaddr=0x4c
+[UTEST]  space=server vaddr=0x4d size=0x1 parent=s0 p.vaddr=0x4d
+[UTEST]  space=server vaddr=0x4e size=0x1 parent=s0 p.vaddr=0x4e
+[UTEST]  space=server vaddr=0x4f size=0x1 parent=s0 p.vaddr=0x4f
+[UTEST]  space=server vaddr=0x50 size=0x1 parent=s0 p.vaddr=0x50
+[UTEST]  space=server vaddr=0x51 size=0x1 parent=s0 p.vaddr=0x51
+[UTEST]  space=server vaddr=0x52 size=0x1 parent=s0 p.vaddr=0x52
+[UTEST]  space=server vaddr=0x53 size=0x1 parent=s0 p.vaddr=0x53
+[UTEST]  space=server vaddr=0x54 size=0x1 parent=s0 p.vaddr=0x54
+[UTEST]  space=server vaddr=0x55 size=0x1 parent=s0 p.vaddr=0x55
+[UTEST]  space=server vaddr=0x56 size=0x1 parent=s0 p.vaddr=0x56
+[UTEST]  space=server vaddr=0x57 size=0x1 parent=s0 p.vaddr=0x57
+[UTEST]  space=server vaddr=0x58 size=0x1 parent=s0 p.vaddr=0x58
+[UTEST]  space=server vaddr=0x59 size=0x1 parent=s0 p.vaddr=0x59
+[UTEST]  space=server vaddr=0x5a size=0x1 parent=s0 p.vaddr=0x5a
+[UTEST]  space=server vaddr=0x5b size=0x1 parent=s0 p.vaddr=0x5b
+[UTEST]  space=server vaddr=0x5c size=0x1 parent=s0 p.vaddr=0x5c
+[UTEST]  space=server vaddr=0x5d size=0x1 parent=s0 p.vaddr=0x5d
+[UTEST]  space=server vaddr=0x5e size=0x1 parent=s0 p.vaddr=0x5e
+[UTEST]  space=server vaddr=0x5f size=0x1 parent=s0 p.vaddr=0x5f
+[UTEST]  space=server vaddr=0x60 size=0x1 parent=s0 p.vaddr=0x60
+[UTEST]  space=server vaddr=0x61 size=0x1 parent=s0 p.vaddr=0x61
+[UTEST]  space=server vaddr=0x62 size=0x1 parent=s0 p.vaddr=0x62
+[UTEST]  space=server vaddr=0x63 size=0x1 parent=s0 p.vaddr=0x63
+[UTEST]  space=server vaddr=0x64 size=0x1 parent=s0 p.vaddr=0x64
+[UTEST]  space=server vaddr=0x65 size=0x1 parent=s0 p.vaddr=0x65
+[UTEST]  space=server vaddr=0x66 size=0x1 parent=s0 p.vaddr=0x66
+[UTEST]  space=server vaddr=0x67 size=0x1 parent=s0 p.vaddr=0x67
+[UTEST]  space=server vaddr=0x68 size=0x1 parent=s0 p.vaddr=0x68
+[UTEST]  space=server vaddr=0x69 size=0x1 parent=s0 p.vaddr=0x69
+[UTEST]  space=server vaddr=0x6a size=0x1 parent=s0 p.vaddr=0x6a
+[UTEST]  space=server vaddr=0x6b size=0x1 parent=s0 p.vaddr=0x6b
+[UTEST]  space=server vaddr=0x6c size=0x1 parent=s0 p.vaddr=0x6c
+[UTEST]  space=server vaddr=0x6d size=0x1 parent=s0 p.vaddr=0x6d
+[UTEST]  space=server vaddr=0x6e size=0x1 parent=s0 p.vaddr=0x6e
+[UTEST]  space=server vaddr=0x6f size=0x1 parent=s0 p.vaddr=0x6f
+[UTEST]  space=server vaddr=0x70 size=0x1 parent=s0 p.vaddr=0x70
+[UTEST]  space=server vaddr=0x71 size=0x1 parent=s0 p.vaddr=0x71
+[UTEST]  space=server vaddr=0x72 size=0x1 parent=s0 p.vaddr=0x72
+[UTEST]  space=server vaddr=0x73 size=0x1 parent=s0 p.vaddr=0x73
+[UTEST]  space=server vaddr=0x74 size=0x1 parent=s0 p.vaddr=0x74
+[UTEST]  space=server vaddr=0x75 size=0x1 parent=s0 p.vaddr=0x75
+[UTEST]  space=server vaddr=0x76 size=0x1 parent=s0 p.vaddr=0x76
+[UTEST]  space=server vaddr=0x77 size=0x1 parent=s0 p.vaddr=0x77
+[UTEST]  space=server vaddr=0x78 size=0x1 parent=s0 p.vaddr=0x78
+[UTEST]  space=server vaddr=0x79 size=0x1 parent=s0 p.vaddr=0x79
+[UTEST]  space=server vaddr=0x7a size=0x1 parent=s0 p.vaddr=0x7a
+[UTEST]  space=server vaddr=0x7b size=0x1 parent=s0 p.vaddr=0x7b
+[UTEST]  space=server vaddr=0x7c size=0x1 parent=s0 p.vaddr=0x7c
+[UTEST]  space=server vaddr=0x7d size=0x1 parent=s0 p.vaddr=0x7d
+[UTEST]  space=server vaddr=0x7e size=0x1 parent=s0 p.vaddr=0x7e
+[UTEST]  space=server vaddr=0x7f size=0x1 parent=s0 p.vaddr=0x7f
+[UTEST]  space=server vaddr=0x80 size=0x1 parent=s0 p.vaddr=0x80
+[UTEST]  space=server vaddr=0x81 size=0x1 parent=s0 p.vaddr=0x81
+[UTEST]  space=server vaddr=0x82 size=0x1 parent=s0 p.vaddr=0x82
+[UTEST]  space=server vaddr=0x83 size=0x1 parent=s0 p.vaddr=0x83
+[UTEST]  space=server vaddr=0x84 size=0x1 parent=s0 p.vaddr=0x84
+[UTEST]  space=server vaddr=0x85 size=0x1 parent=s0 p.vaddr=0x85
+[UTEST]  space=server vaddr=0x86 size=0x1 parent=s0 p.vaddr=0x86
+[UTEST]  space=server vaddr=0x87 size=0x1 parent=s0 p.vaddr=0x87
+[UTEST]  space=server vaddr=0x88 size=0x1 parent=s0 p.vaddr=0x88
+[UTEST]  space=server vaddr=0x89 size=0x1 parent=s0 p.vaddr=0x89
+[UTEST]  space=server vaddr=0x8a size=0x1 parent=s0 p.vaddr=0x8a
+[UTEST]  space=server vaddr=0x8b size=0x1 parent=s0 p.vaddr=0x8b
+[UTEST]  space=server vaddr=0x8c size=0x1 parent=s0 p.vaddr=0x8c
+[UTEST]  space=server vaddr=0x8d size=0x1 parent=s0 p.vaddr=0x8d
+[UTEST]  space=server vaddr=0x8e size=0x1 parent=s0 p.vaddr=0x8e
+[UTEST]  space=server vaddr=0x8f size=0x1 parent=s0 p.vaddr=0x8f
+[UTEST]  space=server vaddr=0x90 size=0x1 parent=s0 p.vaddr=0x90
+[UTEST]  space=server vaddr=0x91 size=0x1 parent=s0 p.vaddr=0x91
+[UTEST]  space=server vaddr=0x92 size=0x1 parent=s0 p.vaddr=0x92
+[UTEST]  space=server vaddr=0x93 size=0x1 parent=s0 p.vaddr=0x93
+[UTEST]  space=server vaddr=0x94 size=0x1 parent=s0 p.vaddr=0x94
+[UTEST]  space=server vaddr=0x95 size=0x1 parent=s0 p.vaddr=0x95
+[UTEST]  space=server vaddr=0x96 size=0x1 parent=s0 p.vaddr=0x96
+[UTEST]  space=server vaddr=0x97 size=0x1 parent=s0 p.vaddr=0x97
+[UTEST]  space=server vaddr=0x98 size=0x1 parent=s0 p.vaddr=0x98
+[UTEST]  space=server vaddr=0x99 size=0x1 parent=s0 p.vaddr=0x99
+[UTEST]  space=server vaddr=0x9a size=0x1 parent=s0 p.vaddr=0x9a
+[UTEST]  space=server vaddr=0x9b size=0x1 parent=s0 p.vaddr=0x9b
+[UTEST]  space=server vaddr=0x9c size=0x1 parent=s0 p.vaddr=0x9c
+[UTEST]  space=server vaddr=0x9d size=0x1 parent=s0 p.vaddr=0x9d
+[UTEST]  space=server vaddr=0x9e size=0x1 parent=s0 p.vaddr=0x9e
+[UTEST]  space=server vaddr=0x9f size=0x1 parent=s0 p.vaddr=0x9f
+[UTEST]  space=server vaddr=0xa0 size=0x1 parent=s0 p.vaddr=0xa0
+[UTEST]  space=server vaddr=0xa1 size=0x1 parent=s0 p.vaddr=0xa1
+[UTEST]  space=server vaddr=0xa2 size=0x1 parent=s0 p.vaddr=0xa2
+[UTEST]  space=server vaddr=0xa3 size=0x1 parent=s0 p.vaddr=0xa3
+[UTEST]  space=server vaddr=0xa4 size=0x1 parent=s0 p.vaddr=0xa4
+[UTEST]  space=server vaddr=0xa5 size=0x1 parent=s0 p.vaddr=0xa5
+[UTEST]  space=server vaddr=0xa6 size=0x1 parent=s0 p.vaddr=0xa6
+[UTEST]  space=server vaddr=0xa7 size=0x1 parent=s0 p.vaddr=0xa7
+[UTEST]  space=server vaddr=0xa8 size=0x1 parent=s0 p.vaddr=0xa8
+[UTEST]  space=server vaddr=0xa9 size=0x1 parent=s0 p.vaddr=0xa9
+[UTEST]  space=server vaddr=0xaa size=0x1 parent=s0 p.vaddr=0xaa
+[UTEST]  space=server vaddr=0xab size=0x1 parent=s0 p.vaddr=0xab
+[UTEST]  space=server vaddr=0xac size=0x1 parent=s0 p.vaddr=0xac
+[UTEST]  space=server vaddr=0xad size=0x1 parent=s0 p.vaddr=0xad
+[UTEST]  space=server vaddr=0xae size=0x1 parent=s0 p.vaddr=0xae
+[UTEST]  space=server vaddr=0xaf size=0x1 parent=s0 p.vaddr=0xaf
+[UTEST]  space=server vaddr=0xb0 size=0x1 parent=s0 p.vaddr=0xb0
+[UTEST]  space=server vaddr=0xb1 size=0x1 parent=s0 p.vaddr=0xb1
+[UTEST]  space=server vaddr=0xb2 size=0x1 parent=s0 p.vaddr=0xb2
+[UTEST]  space=server vaddr=0xb3 size=0x1 parent=s0 p.vaddr=0xb3
+[UTEST]  space=server vaddr=0xb4 size=0x1 parent=s0 p.vaddr=0xb4
+[UTEST]  space=server vaddr=0xb5 size=0x1 parent=s0 p.vaddr=0xb5
+[UTEST]  space=server vaddr=0xb6 size=0x1 parent=s0 p.vaddr=0xb6
+[UTEST]  space=server vaddr=0xb7 size=0x1 parent=s0 p.vaddr=0xb7
+[UTEST]  space=server vaddr=0xb8 size=0x1 parent=s0 p.vaddr=0xb8
+[UTEST]  space=server vaddr=0xb9 size=0x1 parent=s0 p.vaddr=0xb9
+[UTEST]  space=server vaddr=0xba size=0x1 parent=s0 p.vaddr=0xba
+[UTEST]  space=server vaddr=0xbb size=0x1 parent=s0 p.vaddr=0xbb
+[UTEST]  space=server vaddr=0xbc size=0x1 parent=s0 p.vaddr=0xbc
+[UTEST]  space=server vaddr=0xbd size=0x1 parent=s0 p.vaddr=0xbd
+[UTEST]  space=server vaddr=0xbe size=0x1 parent=s0 p.vaddr=0xbe
+[UTEST]  space=server vaddr=0xbf size=0x1 parent=s0 p.vaddr=0xbf
+[UTEST]  space=server vaddr=0xc0 size=0x1 parent=s0 p.vaddr=0xc0
+[UTEST]  space=server vaddr=0xc1 size=0x1 parent=s0 p.vaddr=0xc1
+[UTEST]  space=server vaddr=0xc2 size=0x1 parent=s0 p.vaddr=0xc2
+[UTEST]  space=server vaddr=0xc3 size=0x1 parent=s0 p.vaddr=0xc3
+[UTEST]  space=server vaddr=0xc4 size=0x1 parent=s0 p.vaddr=0xc4
+[UTEST]  space=server vaddr=0xc5 size=0x1 parent=s0 p.vaddr=0xc5
+[UTEST]  space=server vaddr=0xc6 size=0x1 parent=s0 p.vaddr=0xc6
+[UTEST]  space=server vaddr=0xc7 size=0x1 parent=s0 p.vaddr=0xc7
+[UTEST]  space=server vaddr=0xc8 size=0x1 parent=s0 p.vaddr=0xc8
+[UTEST]  space=server vaddr=0xc9 size=0x1 parent=s0 p.vaddr=0xc9
+[UTEST]  space=server vaddr=0xca size=0x1 parent=s0 p.vaddr=0xca
+[UTEST]  space=server vaddr=0xcb size=0x1 parent=s0 p.vaddr=0xcb
+[UTEST]  space=server vaddr=0xcc size=0x1 parent=s0 p.vaddr=0xcc
+[UTEST]  space=server vaddr=0xcd size=0x1 parent=s0 p.vaddr=0xcd
+[UTEST]  space=server vaddr=0xce size=0x1 parent=s0 p.vaddr=0xce
+[UTEST]  space=server vaddr=0xcf size=0x1 parent=s0 p.vaddr=0xcf
+[UTEST]  space=server vaddr=0xd0 size=0x1 parent=s0 p.vaddr=0xd0
+[UTEST]  space=server vaddr=0xd1 size=0x1 parent=s0 p.vaddr=0xd1
+[UTEST]  space=server vaddr=0xd2 size=0x1 parent=s0 p.vaddr=0xd2
+[UTEST]  space=server vaddr=0xd3 size=0x1 parent=s0 p.vaddr=0xd3
+[UTEST]  space=server vaddr=0xd4 size=0x1 parent=s0 p.vaddr=0xd4
+[UTEST]  space=server vaddr=0xd5 size=0x1 parent=s0 p.vaddr=0xd5
+[UTEST]  space=server vaddr=0xd6 size=0x1 parent=s0 p.vaddr=0xd6
+[UTEST]  space=server vaddr=0xd7 size=0x1 parent=s0 p.vaddr=0xd7
+[UTEST]  space=server vaddr=0xd8 size=0x1 parent=s0 p.vaddr=0xd8
+[UTEST]  space=server vaddr=0xd9 size=0x1 parent=s0 p.vaddr=0xd9
+[UTEST]  space=server vaddr=0xda size=0x1 parent=s0 p.vaddr=0xda
+[UTEST]  space=server vaddr=0xdb size=0x1 parent=s0 p.vaddr=0xdb
+[UTEST]  space=server vaddr=0xdc size=0x1 parent=s0 p.vaddr=0xdc
+[UTEST]  space=server vaddr=0xdd size=0x1 parent=s0 p.vaddr=0xdd
+[UTEST]  space=server vaddr=0xde size=0x1 parent=s0 p.vaddr=0xde
+[UTEST]  space=server vaddr=0xdf size=0x1 parent=s0 p.vaddr=0xdf
+[UTEST]  space=server vaddr=0xe0 size=0x1 parent=s0 p.vaddr=0xe0
+[UTEST]  space=server vaddr=0xe1 size=0x1 parent=s0 p.vaddr=0xe1
+[UTEST]  space=server vaddr=0xe2 size=0x1 parent=s0 p.vaddr=0xe2
+[UTEST]  space=server vaddr=0xe3 size=0x1 parent=s0 p.vaddr=0xe3
+[UTEST]  space=server vaddr=0xe4 size=0x1 parent=s0 p.vaddr=0xe4
+[UTEST]  space=server vaddr=0xe5 size=0x1 parent=s0 p.vaddr=0xe5
+[UTEST]  space=server vaddr=0xe6 size=0x1 parent=s0 p.vaddr=0xe6
+[UTEST]  space=server vaddr=0xe7 size=0x1 parent=s0 p.vaddr=0xe7
+[UTEST]  space=server vaddr=0xe8 size=0x1 parent=s0 p.vaddr=0xe8
+[UTEST]  space=server vaddr=0xe9 size=0x1 parent=s0 p.vaddr=0xe9
+[UTEST]  space=server vaddr=0xea size=0x1 parent=s0 p.vaddr=0xea
+[UTEST]  space=server vaddr=0xeb size=0x1 parent=s0 p.vaddr=0xeb
+[UTEST]  space=server vaddr=0xec size=0x1 parent=s0 p.vaddr=0xec
+[UTEST]  space=server vaddr=0xed size=0x1 parent=s0 p.vaddr=0xed
+[UTEST]  space=server vaddr=0xee size=0x1 parent=s0 p.vaddr=0xee
+[UTEST]  space=server vaddr=0xef size=0x1 parent=s0 p.vaddr=0xef
+[UTEST]  space=server vaddr=0xf0 size=0x1 parent=s0 p.vaddr=0xf0
+[UTEST]  space=server vaddr=0xf1 size=0x1 parent=s0 p.vaddr=0xf1
+[UTEST]  space=server vaddr=0xf2 size=0x1 parent=s0 p.vaddr=0xf2
+[UTEST]  space=server vaddr=0xf3 size=0x1 parent=s0 p.vaddr=0xf3
+[UTEST]  space=server vaddr=0xf4 size=0x1 parent=s0 p.vaddr=0xf4
+[UTEST]  space=server vaddr=0xf5 size=0x1 parent=s0 p.vaddr=0xf5
+[UTEST]  space=server vaddr=0xf6 size=0x1 parent=s0 p.vaddr=0xf6
+[UTEST]  space=server vaddr=0xf7 size=0x1 parent=s0 p.vaddr=0xf7
+[UTEST]  space=server vaddr=0xf8 size=0x1 parent=s0 p.vaddr=0xf8
+[UTEST]  space=server vaddr=0xf9 size=0x1 parent=s0 p.vaddr=0xf9
+[UTEST]  space=server vaddr=0xfa size=0x1 parent=s0 p.vaddr=0xfa
+[UTEST]  space=server vaddr=0xfb size=0x1 parent=s0 p.vaddr=0xfb
+[UTEST]  space=server vaddr=0xfc size=0x1 parent=s0 p.vaddr=0xfc
+[UTEST]  space=server vaddr=0xfd size=0x1 parent=s0 p.vaddr=0xfd
+[UTEST]  space=server vaddr=0xfe size=0x1 parent=s0 p.vaddr=0xfe
+[UTEST]  space=server vaddr=0xff size=0x1 parent=s0 p.vaddr=0xff
+[UTEST]  space=server vaddr=0x100 size=0x1 parent=s0 p.vaddr=0x100
+[UTEST]  space=server vaddr=0x101 size=0x1 parent=s0 p.vaddr=0x101
+[UTEST]  space=server vaddr=0x102 size=0x1 parent=s0 p.vaddr=0x102
+[UTEST]  space=server vaddr=0x103 size=0x1 parent=s0 p.vaddr=0x103
+[UTEST]  space=server vaddr=0x104 size=0x1 parent=s0 p.vaddr=0x104
+[UTEST]  space=server vaddr=0x105 size=0x1 parent=s0 p.vaddr=0x105
+[UTEST]  space=server vaddr=0x106 size=0x1 parent=s0 p.vaddr=0x106
+[UTEST]  space=server vaddr=0x107 size=0x1 parent=s0 p.vaddr=0x107
+[UTEST]  space=server vaddr=0x108 size=0x1 parent=s0 p.vaddr=0x108
+[UTEST]  space=server vaddr=0x109 size=0x1 parent=s0 p.vaddr=0x109
+[UTEST]  space=server vaddr=0x10a size=0x1 parent=s0 p.vaddr=0x10a
+[UTEST]  space=server vaddr=0x10b size=0x1 parent=s0 p.vaddr=0x10b
+[UTEST]  space=server vaddr=0x10c size=0x1 parent=s0 p.vaddr=0x10c
+[UTEST]  space=server vaddr=0x10d size=0x1 parent=s0 p.vaddr=0x10d
+[UTEST]  space=server vaddr=0x10e size=0x1 parent=s0 p.vaddr=0x10e
+[UTEST]  space=server vaddr=0x10f size=0x1 parent=s0 p.vaddr=0x10f
+[UTEST]  space=server vaddr=0x110 size=0x1 parent=s0 p.vaddr=0x110
+[UTEST]  space=server vaddr=0x111 size=0x1 parent=s0 p.vaddr=0x111
+[UTEST]  space=server vaddr=0x112 size=0x1 parent=s0 p.vaddr=0x112
+[UTEST]  space=server vaddr=0x113 size=0x1 parent=s0 p.vaddr=0x113
+[UTEST]  space=server vaddr=0x114 size=0x1 parent=s0 p.vaddr=0x114
+[UTEST]  space=server vaddr=0x115 size=0x1 parent=s0 p.vaddr=0x115
+[UTEST]  space=server vaddr=0x116 size=0x1 parent=s0 p.vaddr=0x116
+[UTEST]  space=server vaddr=0x117 size=0x1 parent=s0 p.vaddr=0x117
+[UTEST]  space=server vaddr=0x118 size=0x1 parent=s0 p.vaddr=0x118
+[UTEST]  space=server vaddr=0x119 size=0x1 parent=s0 p.vaddr=0x119
+[UTEST]  space=server vaddr=0x11a size=0x1 parent=s0 p.vaddr=0x11a
+[UTEST]  space=server vaddr=0x11b size=0x1 parent=s0 p.vaddr=0x11b
+[UTEST]  space=server vaddr=0x11c size=0x1 parent=s0 p.vaddr=0x11c
+[UTEST]  space=server vaddr=0x11d size=0x1 parent=s0 p.vaddr=0x11d
+[UTEST]  space=server vaddr=0x11e size=0x1 parent=s0 p.vaddr=0x11e
+[UTEST]  space=server vaddr=0x11f size=0x1 parent=s0 p.vaddr=0x11f
+[UTEST]  space=server vaddr=0x120 size=0x1 parent=s0 p.vaddr=0x120
+[UTEST]  space=server vaddr=0x121 size=0x1 parent=s0 p.vaddr=0x121
+[UTEST]  space=server vaddr=0x122 size=0x1 parent=s0 p.vaddr=0x122
+[UTEST]  space=server vaddr=0x123 size=0x1 parent=s0 p.vaddr=0x123
+[UTEST]  space=server vaddr=0x124 size=0x1 parent=s0 p.vaddr=0x124
+[UTEST]  space=server vaddr=0x125 size=0x1 parent=s0 p.vaddr=0x125
+[UTEST]  space=server vaddr=0x126 size=0x1 parent=s0 p.vaddr=0x126
+[UTEST]  space=server vaddr=0x127 size=0x1 parent=s0 p.vaddr=0x127
+[UTEST]  space=server vaddr=0x128 size=0x1 parent=s0 p.vaddr=0x128
+[UTEST]  space=server vaddr=0x129 size=0x1 parent=s0 p.vaddr=0x129
+[UTEST]  space=server vaddr=0x12a size=0x1 parent=s0 p.vaddr=0x12a
+[UTEST]  space=server vaddr=0x12b size=0x1 parent=s0 p.vaddr=0x12b
+[UTEST]  space=server vaddr=0x12c size=0x1 parent=s0 p.vaddr=0x12c
+[UTEST]  space=server vaddr=0x12d size=0x1 parent=s0 p.vaddr=0x12d
+[UTEST]  space=server vaddr=0x12e size=0x1 parent=s0 p.vaddr=0x12e
+[UTEST]  space=server vaddr=0x12f size=0x1 parent=s0 p.vaddr=0x12f
+[UTEST]  space=server vaddr=0x130 size=0x1 parent=s0 p.vaddr=0x130
+[UTEST]  space=server vaddr=0x131 size=0x1 parent=s0 p.vaddr=0x131
+[UTEST]  space=server vaddr=0x132 size=0x1 parent=s0 p.vaddr=0x132
+[UTEST]  space=server vaddr=0x133 size=0x1 parent=s0 p.vaddr=0x133
+[UTEST]  space=server vaddr=0x134 size=0x1 parent=s0 p.vaddr=0x134
+[UTEST]  space=server vaddr=0x135 size=0x1 parent=s0 p.vaddr=0x135
+[UTEST]  space=server vaddr=0x136 size=0x1 parent=s0 p.vaddr=0x136
+[UTEST]  space=server vaddr=0x137 size=0x1 parent=s0 p.vaddr=0x137
+[UTEST]  space=server vaddr=0x138 size=0x1 parent=s0 p.vaddr=0x138
+[UTEST]  space=server vaddr=0x139 size=0x1 parent=s0 p.vaddr=0x139
+[UTEST]  space=server vaddr=0x13a size=0x1 parent=s0 p.vaddr=0x13a
+[UTEST]  space=server vaddr=0x13b size=0x1 parent=s0 p.vaddr=0x13b
+[UTEST]  space=server vaddr=0x13c size=0x1 parent=s0 p.vaddr=0x13c
+[UTEST]  space=server vaddr=0x13d size=0x1 parent=s0 p.vaddr=0x13d
+[UTEST]  space=server vaddr=0x13e size=0x1 parent=s0 p.vaddr=0x13e
+[UTEST]  space=server vaddr=0x13f size=0x1 parent=s0 p.vaddr=0x13f
+[UTEST]  space=server vaddr=0x140 size=0x1 parent=s0 p.vaddr=0x140
+[UTEST]  space=server vaddr=0x141 size=0x1 parent=s0 p.vaddr=0x141
+[UTEST]  space=server vaddr=0x142 size=0x1 parent=s0 p.vaddr=0x142
+[UTEST]  space=server vaddr=0x143 size=0x1 parent=s0 p.vaddr=0x143
+[UTEST]  space=server vaddr=0x144 size=0x1 parent=s0 p.vaddr=0x144
+[UTEST]  space=server vaddr=0x145 size=0x1 parent=s0 p.vaddr=0x145
+[UTEST]  space=server vaddr=0x146 size=0x1 parent=s0 p.vaddr=0x146
+[UTEST]  space=server vaddr=0x147 size=0x1 parent=s0 p.vaddr=0x147
+[UTEST]  space=server vaddr=0x148 size=0x1 parent=s0 p.vaddr=0x148
+[UTEST]  space=server vaddr=0x149 size=0x1 parent=s0 p.vaddr=0x149
+[UTEST]  space=server vaddr=0x14a size=0x1 parent=s0 p.vaddr=0x14a
+[UTEST]  space=server vaddr=0x14b size=0x1 parent=s0 p.vaddr=0x14b
+[UTEST]  space=server vaddr=0x14c size=0x1 parent=s0 p.vaddr=0x14c
+[UTEST]  space=server vaddr=0x14d size=0x1 parent=s0 p.vaddr=0x14d
+[UTEST]  space=server vaddr=0x14e size=0x1 parent=s0 p.vaddr=0x14e
+[UTEST]  space=server vaddr=0x14f size=0x1 parent=s0 p.vaddr=0x14f
+[UTEST]  space=server vaddr=0x150 size=0x1 parent=s0 p.vaddr=0x150
+[UTEST]  space=server vaddr=0x151 size=0x1 parent=s0 p.vaddr=0x151
+[UTEST]  space=server vaddr=0x152 size=0x1 parent=s0 p.vaddr=0x152
+[UTEST]  space=server vaddr=0x153 size=0x1 parent=s0 p.vaddr=0x153
+[UTEST]  space=server vaddr=0x154 size=0x1 parent=s0 p.vaddr=0x154
+[UTEST]  space=server vaddr=0x155 size=0x1 parent=s0 p.vaddr=0x155
+[UTEST]  space=server vaddr=0x156 size=0x1 parent=s0 p.vaddr=0x156
+[UTEST]  space=server vaddr=0x157 size=0x1 parent=s0 p.vaddr=0x157
+[UTEST]  space=server vaddr=0x158 size=0x1 parent=s0 p.vaddr=0x158
+[UTEST]  space=server vaddr=0x159 size=0x1 parent=s0 p.vaddr=0x159
+[UTEST]  space=server vaddr=0x15a size=0x1 parent=s0 p.vaddr=0x15a
+[UTEST]  space=server vaddr=0x15b size=0x1 parent=s0 p.vaddr=0x15b
+[UTEST]  space=server vaddr=0x15c size=0x1 parent=s0 p.vaddr=0x15c
+[UTEST]  space=server vaddr=0x15d size=0x1 parent=s0 p.vaddr=0x15d
+[UTEST]  space=server vaddr=0x15e size=0x1 parent=s0 p.vaddr=0x15e
+[UTEST]  space=server vaddr=0x15f size=0x1 parent=s0 p.vaddr=0x15f
+[UTEST]  space=server vaddr=0x160 size=0x1 parent=s0 p.vaddr=0x160
+[UTEST]  space=server vaddr=0x161 size=0x1 parent=s0 p.vaddr=0x161
+[UTEST]  space=server vaddr=0x162 size=0x1 parent=s0 p.vaddr=0x162
+[UTEST]  space=server vaddr=0x163 size=0x1 parent=s0 p.vaddr=0x163
+[UTEST]  space=server vaddr=0x164 size=0x1 parent=s0 p.vaddr=0x164
+[UTEST]  space=server vaddr=0x165 size=0x1 parent=s0 p.vaddr=0x165
+[UTEST]  space=server vaddr=0x166 size=0x1 parent=s0 p.vaddr=0x166
+[UTEST]  space=server vaddr=0x167 size=0x1 parent=s0 p.vaddr=0x167
+[UTEST]  space=server vaddr=0x168 size=0x1 parent=s0 p.vaddr=0x168
+[UTEST]  space=server vaddr=0x169 size=0x1 parent=s0 p.vaddr=0x169
+[UTEST]  space=server vaddr=0x16a size=0x1 parent=s0 p.vaddr=0x16a
+[UTEST]  space=server vaddr=0x16b size=0x1 parent=s0 p.vaddr=0x16b
+[UTEST]  space=server vaddr=0x16c size=0x1 parent=s0 p.vaddr=0x16c
+[UTEST]  space=server vaddr=0x16d size=0x1 parent=s0 p.vaddr=0x16d
+[UTEST]  space=server vaddr=0x16e size=0x1 parent=s0 p.vaddr=0x16e
+[UTEST]  space=server vaddr=0x16f size=0x1 parent=s0 p.vaddr=0x16f
+[UTEST]  space=server vaddr=0x170 size=0x1 parent=s0 p.vaddr=0x170
+[UTEST]  space=server vaddr=0x171 size=0x1 parent=s0 p.vaddr=0x171
+[UTEST]  space=server vaddr=0x172 size=0x1 parent=s0 p.vaddr=0x172
+[UTEST]  space=server vaddr=0x173 size=0x1 parent=s0 p.vaddr=0x173
+[UTEST]  space=server vaddr=0x174 size=0x1 parent=s0 p.vaddr=0x174
+[UTEST]  space=server vaddr=0x175 size=0x1 parent=s0 p.vaddr=0x175
+[UTEST]  space=server vaddr=0x176 size=0x1 parent=s0 p.vaddr=0x176
+[UTEST]  space=server vaddr=0x177 size=0x1 parent=s0 p.vaddr=0x177
+[UTEST]  space=server vaddr=0x178 size=0x1 parent=s0 p.vaddr=0x178
+[UTEST]  space=server vaddr=0x179 size=0x1 parent=s0 p.vaddr=0x179
+[UTEST]  space=server vaddr=0x17a size=0x1 parent=s0 p.vaddr=0x17a
+[UTEST]  space=server vaddr=0x17b size=0x1 parent=s0 p.vaddr=0x17b
+[UTEST]  space=server vaddr=0x17c size=0x1 parent=s0 p.vaddr=0x17c
+[UTEST]  space=server vaddr=0x17d size=0x1 parent=s0 p.vaddr=0x17d
+[UTEST]  space=server vaddr=0x17e size=0x1 parent=s0 p.vaddr=0x17e
+[UTEST]  space=server vaddr=0x17f size=0x1 parent=s0 p.vaddr=0x17f
+[UTEST]  space=server vaddr=0x180 size=0x1 parent=s0 p.vaddr=0x180
+[UTEST]  space=server vaddr=0x181 size=0x1 parent=s0 p.vaddr=0x181
+[UTEST]  space=server vaddr=0x182 size=0x1 parent=s0 p.vaddr=0x182
+[UTEST]  space=server vaddr=0x183 size=0x1 parent=s0 p.vaddr=0x183
+[UTEST]  space=server vaddr=0x184 size=0x1 parent=s0 p.vaddr=0x184
+[UTEST]  space=server vaddr=0x185 size=0x1 parent=s0 p.vaddr=0x185
+[UTEST]  space=server vaddr=0x186 size=0x1 parent=s0 p.vaddr=0x186
+[UTEST]  space=server vaddr=0x187 size=0x1 parent=s0 p.vaddr=0x187
+[UTEST]  space=server vaddr=0x188 size=0x1 parent=s0 p.vaddr=0x188
+[UTEST]  space=server vaddr=0x189 size=0x1 parent=s0 p.vaddr=0x189
+[UTEST]  space=server vaddr=0x18a size=0x1 parent=s0 p.vaddr=0x18a
+[UTEST]  space=server vaddr=0x18b size=0x1 parent=s0 p.vaddr=0x18b
+[UTEST]  space=server vaddr=0x18c size=0x1 parent=s0 p.vaddr=0x18c
+[UTEST]  space=server vaddr=0x18d size=0x1 parent=s0 p.vaddr=0x18d
+[UTEST]  space=server vaddr=0x18e size=0x1 parent=s0 p.vaddr=0x18e
+[UTEST]  space=server vaddr=0x18f size=0x1 parent=s0 p.vaddr=0x18f
+[UTEST]  space=server vaddr=0x190 size=0x1 parent=s0 p.vaddr=0x190
+[UTEST]  space=server vaddr=0x191 size=0x1 parent=s0 p.vaddr=0x191
+[UTEST]  space=server vaddr=0x192 size=0x1 parent=s0 p.vaddr=0x192
+[UTEST]  space=server vaddr=0x193 size=0x1 parent=s0 p.vaddr=0x193
+[UTEST]  space=server vaddr=0x194 size=0x1 parent=s0 p.vaddr=0x194
+[UTEST]  space=server vaddr=0x195 size=0x1 parent=s0 p.vaddr=0x195
+[UTEST]  space=server vaddr=0x196 size=0x1 parent=s0 p.vaddr=0x196
+[UTEST]  space=server vaddr=0x197 size=0x1 parent=s0 p.vaddr=0x197
+[UTEST]  space=server vaddr=0x198 size=0x1 parent=s0 p.vaddr=0x198
+[UTEST]  space=server vaddr=0x199 size=0x1 parent=s0 p.vaddr=0x199
+[UTEST]  space=server vaddr=0x19a size=0x1 parent=s0 p.vaddr=0x19a
+[UTEST]  space=server vaddr=0x19b size=0x1 parent=s0 p.vaddr=0x19b
+[UTEST]  space=server vaddr=0x19c size=0x1 parent=s0 p.vaddr=0x19c
+[UTEST]  space=server vaddr=0x19d size=0x1 parent=s0 p.vaddr=0x19d
+[UTEST]  space=server vaddr=0x19e size=0x1 parent=s0 p.vaddr=0x19e
+[UTEST]  space=server vaddr=0x19f size=0x1 parent=s0 p.vaddr=0x19f
+[UTEST]  space=server vaddr=0x1a0 size=0x1 parent=s0 p.vaddr=0x1a0
+[UTEST]  space=server vaddr=0x1a1 size=0x1 parent=s0 p.vaddr=0x1a1
+[UTEST]  space=server vaddr=0x1a2 size=0x1 parent=s0 p.vaddr=0x1a2
+[UTEST]  space=server vaddr=0x1a3 size=0x1 parent=s0 p.vaddr=0x1a3
+[UTEST]  space=server vaddr=0x1a4 size=0x1 parent=s0 p.vaddr=0x1a4
+[UTEST]  space=server vaddr=0x1a5 size=0x1 parent=s0 p.vaddr=0x1a5
+[UTEST]  space=server vaddr=0x1a6 size=0x1 parent=s0 p.vaddr=0x1a6
+[UTEST]  space=server vaddr=0x1a7 size=0x1 parent=s0 p.vaddr=0x1a7
+[UTEST]  space=server vaddr=0x1a8 size=0x1 parent=s0 p.vaddr=0x1a8
+[UTEST]  space=server vaddr=0x1a9 size=0x1 parent=s0 p.vaddr=0x1a9
+[UTEST]  space=server vaddr=0x1aa size=0x1 parent=s0 p.vaddr=0x1aa
+[UTEST]  space=server vaddr=0x1ab size=0x1 parent=s0 p.vaddr=0x1ab
+[UTEST]  space=server vaddr=0x1ac size=0x1 parent=s0 p.vaddr=0x1ac
+[UTEST]  space=server vaddr=0x1ad size=0x1 parent=s0 p.vaddr=0x1ad
+[UTEST]  space=server vaddr=0x1ae size=0x1 parent=s0 p.vaddr=0x1ae
+[UTEST]  space=server vaddr=0x1af size=0x1 parent=s0 p.vaddr=0x1af
+[UTEST]  space=server vaddr=0x1b0 size=0x1 parent=s0 p.vaddr=0x1b0
+[UTEST]  space=server vaddr=0x1b1 size=0x1 parent=s0 p.vaddr=0x1b1
+[UTEST]  space=server vaddr=0x1b2 size=0x1 parent=s0 p.vaddr=0x1b2
+[UTEST]  space=server vaddr=0x1b3 size=0x1 parent=s0 p.vaddr=0x1b3
+[UTEST]  space=server vaddr=0x1b4 size=0x1 parent=s0 p.vaddr=0x1b4
+[UTEST]  space=server vaddr=0x1b5 size=0x1 parent=s0 p.vaddr=0x1b5
+[UTEST]  space=server vaddr=0x1b6 size=0x1 parent=s0 p.vaddr=0x1b6
+[UTEST]  space=server vaddr=0x1b7 size=0x1 parent=s0 p.vaddr=0x1b7
+[UTEST]  space=server vaddr=0x1b8 size=0x1 parent=s0 p.vaddr=0x1b8
+[UTEST]  space=server vaddr=0x1b9 size=0x1 parent=s0 p.vaddr=0x1b9
+[UTEST]  space=server vaddr=0x1ba size=0x1 parent=s0 p.vaddr=0x1ba
+[UTEST]  space=server vaddr=0x1bb size=0x1 parent=s0 p.vaddr=0x1bb
+[UTEST]  space=server vaddr=0x1bc size=0x1 parent=s0 p.vaddr=0x1bc
+[UTEST]  space=server vaddr=0x1bd size=0x1 parent=s0 p.vaddr=0x1bd
+[UTEST]  space=server vaddr=0x1be size=0x1 parent=s0 p.vaddr=0x1be
+[UTEST]  space=server vaddr=0x1bf size=0x1 parent=s0 p.vaddr=0x1bf
+[UTEST]  space=server vaddr=0x1c0 size=0x1 parent=s0 p.vaddr=0x1c0
+[UTEST]  space=server vaddr=0x1c1 size=0x1 parent=s0 p.vaddr=0x1c1
+[UTEST]  space=server vaddr=0x1c2 size=0x1 parent=s0 p.vaddr=0x1c2
+[UTEST]  space=server vaddr=0x1c3 size=0x1 parent=s0 p.vaddr=0x1c3
+[UTEST]  space=server vaddr=0x1c4 size=0x1 parent=s0 p.vaddr=0x1c4
+[UTEST]  space=server vaddr=0x1c5 size=0x1 parent=s0 p.vaddr=0x1c5
+[UTEST]  space=server vaddr=0x1c6 size=0x1 parent=s0 p.vaddr=0x1c6
+[UTEST]  space=server vaddr=0x1c7 size=0x1 parent=s0 p.vaddr=0x1c7
+[UTEST]  space=server vaddr=0x1c8 size=0x1 parent=s0 p.vaddr=0x1c8
+[UTEST]  space=server vaddr=0x1c9 size=0x1 parent=s0 p.vaddr=0x1c9
+[UTEST]  space=server vaddr=0x1ca size=0x1 parent=s0 p.vaddr=0x1ca
+[UTEST]  space=server vaddr=0x1cb size=0x1 parent=s0 p.vaddr=0x1cb
+[UTEST]  space=server vaddr=0x1cc size=0x1 parent=s0 p.vaddr=0x1cc
+[UTEST]  space=server vaddr=0x1cd size=0x1 parent=s0 p.vaddr=0x1cd
+[UTEST]  space=server vaddr=0x1ce size=0x1 parent=s0 p.vaddr=0x1ce
+[UTEST]  space=server vaddr=0x1cf size=0x1 parent=s0 p.vaddr=0x1cf
+[UTEST]  space=server vaddr=0x1d0 size=0x1 parent=s0 p.vaddr=0x1d0
+[UTEST]  space=server vaddr=0x1d1 size=0x1 parent=s0 p.vaddr=0x1d1
+[UTEST]  space=server vaddr=0x1d2 size=0x1 parent=s0 p.vaddr=0x1d2
+[UTEST]  space=server vaddr=0x1d3 size=0x1 parent=s0 p.vaddr=0x1d3
+[UTEST]  space=server vaddr=0x1d4 size=0x1 parent=s0 p.vaddr=0x1d4
+[UTEST]  space=server vaddr=0x1d5 size=0x1 parent=s0 p.vaddr=0x1d5
+[UTEST]  space=server vaddr=0x1d6 size=0x1 parent=s0 p.vaddr=0x1d6
+[UTEST]  space=server vaddr=0x1d7 size=0x1 parent=s0 p.vaddr=0x1d7
+[UTEST]  space=server vaddr=0x1d8 size=0x1 parent=s0 p.vaddr=0x1d8
+[UTEST]  space=server vaddr=0x1d9 size=0x1 parent=s0 p.vaddr=0x1d9
+[UTEST]  space=server vaddr=0x1da size=0x1 parent=s0 p.vaddr=0x1da
+[UTEST]  space=server vaddr=0x1db size=0x1 parent=s0 p.vaddr=0x1db
+[UTEST]  space=server vaddr=0x1dc size=0x1 parent=s0 p.vaddr=0x1dc
+[UTEST]  space=server vaddr=0x1dd size=0x1 parent=s0 p.vaddr=0x1dd
+[UTEST]  space=server vaddr=0x1de size=0x1 parent=s0 p.vaddr=0x1de
+[UTEST]  space=server vaddr=0x1df size=0x1 parent=s0 p.vaddr=0x1df
+[UTEST]  space=server vaddr=0x1e0 size=0x1 parent=s0 p.vaddr=0x1e0
+[UTEST]  space=server vaddr=0x1e1 size=0x1 parent=s0 p.vaddr=0x1e1
+[UTEST]  space=server vaddr=0x1e2 size=0x1 parent=s0 p.vaddr=0x1e2
+[UTEST]  space=server vaddr=0x1e3 size=0x1 parent=s0 p.vaddr=0x1e3
+[UTEST]  space=server vaddr=0x1e4 size=0x1 parent=s0 p.vaddr=0x1e4
+[UTEST]  space=server vaddr=0x1e5 size=0x1 parent=s0 p.vaddr=0x1e5
+[UTEST]  space=server vaddr=0x1e6 size=0x1 parent=s0 p.vaddr=0x1e6
+[UTEST]  space=server vaddr=0x1e7 size=0x1 parent=s0 p.vaddr=0x1e7
+[UTEST]  space=server vaddr=0x1e8 size=0x1 parent=s0 p.vaddr=0x1e8
+[UTEST]  space=server vaddr=0x1e9 size=0x1 parent=s0 p.vaddr=0x1e9
+[UTEST]  space=server vaddr=0x1ea size=0x1 parent=s0 p.vaddr=0x1ea
+[UTEST]  space=server vaddr=0x1eb size=0x1 parent=s0 p.vaddr=0x1eb
+[UTEST]  space=server vaddr=0x1ec size=0x1 parent=s0 p.vaddr=0x1ec
+[UTEST]  space=server vaddr=0x1ed size=0x1 parent=s0 p.vaddr=0x1ed
+[UTEST]  space=server vaddr=0x1ee size=0x1 parent=s0 p.vaddr=0x1ee
+[UTEST]  space=server vaddr=0x1ef size=0x1 parent=s0 p.vaddr=0x1ef
+[UTEST]  space=server vaddr=0x1f0 size=0x1 parent=s0 p.vaddr=0x1f0
+[UTEST]  space=server vaddr=0x1f1 size=0x1 parent=s0 p.vaddr=0x1f1
+[UTEST]  space=server vaddr=0x1f2 size=0x1 parent=s0 p.vaddr=0x1f2
+[UTEST]  space=server vaddr=0x1f3 size=0x1 parent=s0 p.vaddr=0x1f3
+[UTEST]  space=server vaddr=0x1f4 size=0x1 parent=s0 p.vaddr=0x1f4
+[UTEST]  space=server vaddr=0x1f5 size=0x1 parent=s0 p.vaddr=0x1f5
+[UTEST]  space=server vaddr=0x1f6 size=0x1 parent=s0 p.vaddr=0x1f6
+[UTEST]  space=server vaddr=0x1f7 size=0x1 parent=s0 p.vaddr=0x1f7
+[UTEST]  space=server vaddr=0x1f8 size=0x1 parent=s0 p.vaddr=0x1f8
+[UTEST]  space=server vaddr=0x1f9 size=0x1 parent=s0 p.vaddr=0x1f9
+[UTEST]  space=server vaddr=0x1fa size=0x1 parent=s0 p.vaddr=0x1fa
+[UTEST]  space=server vaddr=0x1fb size=0x1 parent=s0 p.vaddr=0x1fb
+[UTEST]  space=server vaddr=0x1fc size=0x1 parent=s0 p.vaddr=0x1fc
+[UTEST]  space=server vaddr=0x1fd size=0x1 parent=s0 p.vaddr=0x1fd
+[UTEST]  space=server vaddr=0x1fe size=0x1 parent=s0 p.vaddr=0x1fe
+[UTEST]  space=server vaddr=0x1ff size=0x1 parent=s0 p.vaddr=0x1ff
+[UTEST]  space=server vaddr=0x200 size=0x1 parent=s0 p.vaddr=0x200
+[UTEST]  space=server vaddr=0x201 size=0x1 parent=s0 p.vaddr=0x201
+[UTEST]  space=server vaddr=0x202 size=0x1 parent=s0 p.vaddr=0x202
+[UTEST]  space=server vaddr=0x203 size=0x1 parent=s0 p.vaddr=0x203
+[UTEST]  space=server vaddr=0x204 size=0x1 parent=s0 p.vaddr=0x204
+[UTEST]  space=server vaddr=0x205 size=0x1 parent=s0 p.vaddr=0x205
+[UTEST]  space=server vaddr=0x206 size=0x1 parent=s0 p.vaddr=0x206
+[UTEST]  space=server vaddr=0x207 size=0x1 parent=s0 p.vaddr=0x207
+[UTEST]  space=server vaddr=0x208 size=0x1 parent=s0 p.vaddr=0x208
+[UTEST]  space=server vaddr=0x209 size=0x1 parent=s0 p.vaddr=0x209
+[UTEST]  space=server vaddr=0x20a size=0x1 parent=s0 p.vaddr=0x20a
+[UTEST]  space=server vaddr=0x20b size=0x1 parent=s0 p.vaddr=0x20b
+[UTEST]  space=server vaddr=0x20c size=0x1 parent=s0 p.vaddr=0x20c
+[UTEST]  space=server vaddr=0x20d size=0x1 parent=s0 p.vaddr=0x20d
+[UTEST]  space=server vaddr=0x20e size=0x1 parent=s0 p.vaddr=0x20e
+[UTEST]  space=server vaddr=0x20f size=0x1 parent=s0 p.vaddr=0x20f
+[UTEST]  space=server vaddr=0x210 size=0x1 parent=s0 p.vaddr=0x210
+[UTEST]  space=server vaddr=0x211 size=0x1 parent=s0 p.vaddr=0x211
+[UTEST]  space=server vaddr=0x212 size=0x1 parent=s0 p.vaddr=0x212
+[UTEST]  space=server vaddr=0x213 size=0x1 parent=s0 p.vaddr=0x213
+[UTEST]  space=server vaddr=0x214 size=0x1 parent=s0 p.vaddr=0x214
+[UTEST]  space=server vaddr=0x215 size=0x1 parent=s0 p.vaddr=0x215
+[UTEST]  space=server vaddr=0x216 size=0x1 parent=s0 p.vaddr=0x216
+[UTEST]  space=server vaddr=0x217 size=0x1 parent=s0 p.vaddr=0x217
+[UTEST]  space=server vaddr=0x218 size=0x1 parent=s0 p.vaddr=0x218
+[UTEST]  space=server vaddr=0x219 size=0x1 parent=s0 p.vaddr=0x219
+[UTEST]  space=server vaddr=0x21a size=0x1 parent=s0 p.vaddr=0x21a
+[UTEST]  space=server vaddr=0x21b size=0x1 parent=s0 p.vaddr=0x21b
+[UTEST]  space=server vaddr=0x21c size=0x1 parent=s0 p.vaddr=0x21c
+[UTEST]  space=server vaddr=0x21d size=0x1 parent=s0 p.vaddr=0x21d
+[UTEST]  space=server vaddr=0x21e size=0x1 parent=s0 p.vaddr=0x21e
+[UTEST]  space=server vaddr=0x21f size=0x1 parent=s0 p.vaddr=0x21f
+[UTEST]  space=server vaddr=0x220 size=0x1 parent=s0 p.vaddr=0x220
+[UTEST]  space=server vaddr=0x221 size=0x1 parent=s0 p.vaddr=0x221
+[UTEST]  space=server vaddr=0x222 size=0x1 parent=s0 p.vaddr=0x222
+[UTEST]  space=server vaddr=0x223 size=0x1 parent=s0 p.vaddr=0x223
+[UTEST]  space=server vaddr=0x224 size=0x1 parent=s0 p.vaddr=0x224
+[UTEST]  space=server vaddr=0x225 size=0x1 parent=s0 p.vaddr=0x225
+[UTEST]  space=server vaddr=0x226 size=0x1 parent=s0 p.vaddr=0x226
+[UTEST]  space=server vaddr=0x227 size=0x1 parent=s0 p.vaddr=0x227
+[UTEST]  space=server vaddr=0x228 size=0x1 parent=s0 p.vaddr=0x228
+[UTEST]  space=server vaddr=0x229 size=0x1 parent=s0 p.vaddr=0x229
+[UTEST]  space=server vaddr=0x22a size=0x1 parent=s0 p.vaddr=0x22a
+[UTEST]  space=server vaddr=0x22b size=0x1 parent=s0 p.vaddr=0x22b
+[UTEST]  space=server vaddr=0x22c size=0x1 parent=s0 p.vaddr=0x22c
+[UTEST]  space=server vaddr=0x22d size=0x1 parent=s0 p.vaddr=0x22d
+[UTEST]  space=server vaddr=0x22e size=0x1 parent=s0 p.vaddr=0x22e
+[UTEST]  space=server vaddr=0x22f size=0x1 parent=s0 p.vaddr=0x22f
+[UTEST]  space=server vaddr=0x230 size=0x1 parent=s0 p.vaddr=0x230
+[UTEST]  space=server vaddr=0x231 size=0x1 parent=s0 p.vaddr=0x231
+[UTEST]  space=server vaddr=0x232 size=0x1 parent=s0 p.vaddr=0x232
+[UTEST]  space=server vaddr=0x233 size=0x1 parent=s0 p.vaddr=0x233
+[UTEST]  space=server vaddr=0x234 size=0x1 parent=s0 p.vaddr=0x234
+[UTEST]  space=server vaddr=0x235 size=0x1 parent=s0 p.vaddr=0x235
+[UTEST]  space=server vaddr=0x236 size=0x1 parent=s0 p.vaddr=0x236
+[UTEST]  space=server vaddr=0x237 size=0x1 parent=s0 p.vaddr=0x237
+[UTEST]  space=server vaddr=0x238 size=0x1 parent=s0 p.vaddr=0x238
+[UTEST]  space=server vaddr=0x239 size=0x1 parent=s0 p.vaddr=0x239
+[UTEST]  space=server vaddr=0x23a size=0x1 parent=s0 p.vaddr=0x23a
+[UTEST]  space=server vaddr=0x23b size=0x1 parent=s0 p.vaddr=0x23b
+[UTEST]  space=server vaddr=0x23c size=0x1 parent=s0 p.vaddr=0x23c
+[UTEST]  space=server vaddr=0x23d size=0x1 parent=s0 p.vaddr=0x23d
+[UTEST]  space=server vaddr=0x23e size=0x1 parent=s0 p.vaddr=0x23e
+[UTEST]  space=server vaddr=0x23f size=0x1 parent=s0 p.vaddr=0x23f
+[UTEST]  space=server vaddr=0x240 size=0x1 parent=s0 p.vaddr=0x240
+[UTEST]  space=server vaddr=0x241 size=0x1 parent=s0 p.vaddr=0x241
+[UTEST]  space=server vaddr=0x242 size=0x1 parent=s0 p.vaddr=0x242
+[UTEST]  space=server vaddr=0x243 size=0x1 parent=s0 p.vaddr=0x243
+[UTEST]  space=server vaddr=0x244 size=0x1 parent=s0 p.vaddr=0x244
+[UTEST]  space=server vaddr=0x245 size=0x1 parent=s0 p.vaddr=0x245
+[UTEST]  space=server vaddr=0x246 size=0x1 parent=s0 p.vaddr=0x246
+[UTEST]  space=server vaddr=0x247 size=0x1 parent=s0 p.vaddr=0x247
+[UTEST]  space=server vaddr=0x248 size=0x1 parent=s0 p.vaddr=0x248
+[UTEST]  space=server vaddr=0x249 size=0x1 parent=s0 p.vaddr=0x249
+[UTEST]  space=server vaddr=0x24a size=0x1 parent=s0 p.vaddr=0x24a
+[UTEST]  space=server vaddr=0x24b size=0x1 parent=s0 p.vaddr=0x24b
+[UTEST]  space=server vaddr=0x24c size=0x1 parent=s0 p.vaddr=0x24c
+[UTEST]  space=server vaddr=0x24d size=0x1 parent=s0 p.vaddr=0x24d
+[UTEST]  space=server vaddr=0x24e size=0x1 parent=s0 p.vaddr=0x24e
+[UTEST]  space=server vaddr=0x24f size=0x1 parent=s0 p.vaddr=0x24f
+[UTEST]  space=server vaddr=0x250 size=0x1 parent=s0 p.vaddr=0x250
+[UTEST]  space=server vaddr=0x251 size=0x1 parent=s0 p.vaddr=0x251
+[UTEST]  space=server vaddr=0x252 size=0x1 parent=s0 p.vaddr=0x252
+[UTEST]  space=server vaddr=0x253 size=0x1 parent=s0 p.vaddr=0x253
+[UTEST]  space=server vaddr=0x254 size=0x1 parent=s0 p.vaddr=0x254
+[UTEST]  space=server vaddr=0x255 size=0x1 parent=s0 p.vaddr=0x255
+[UTEST]  space=server vaddr=0x256 size=0x1 parent=s0 p.vaddr=0x256
+[UTEST]  space=server vaddr=0x257 size=0x1 parent=s0 p.vaddr=0x257
+[UTEST]  space=server vaddr=0x258 size=0x1 parent=s0 p.vaddr=0x258
+[UTEST]  space=server vaddr=0x259 size=0x1 parent=s0 p.vaddr=0x259
+[UTEST]  space=server vaddr=0x25a size=0x1 parent=s0 p.vaddr=0x25a
+[UTEST]  space=server vaddr=0x25b size=0x1 parent=s0 p.vaddr=0x25b
+[UTEST]  space=server vaddr=0x25c size=0x1 parent=s0 p.vaddr=0x25c
+[UTEST]  space=server vaddr=0x25d size=0x1 parent=s0 p.vaddr=0x25d
+[UTEST]  space=server vaddr=0x25e size=0x1 parent=s0 p.vaddr=0x25e
+[UTEST]  space=server vaddr=0x25f size=0x1 parent=s0 p.vaddr=0x25f
+[UTEST]  space=server vaddr=0x260 size=0x1 parent=s0 p.vaddr=0x260
+[UTEST]  space=server vaddr=0x261 size=0x1 parent=s0 p.vaddr=0x261
+[UTEST]  space=server vaddr=0x262 size=0x1 parent=s0 p.vaddr=0x262
+[UTEST]  space=server vaddr=0x263 size=0x1 parent=s0 p.vaddr=0x263
+[UTEST]  space=server vaddr=0x264 size=0x1 parent=s0 p.vaddr=0x264
+[UTEST]  space=server vaddr=0x265 size=0x1 parent=s0 p.vaddr=0x265
+[UTEST]  space=server vaddr=0x266 size=0x1 parent=s0 p.vaddr=0x266
+[UTEST]  space=server vaddr=0x267 size=0x1 parent=s0 p.vaddr=0x267
+[UTEST]  space=server vaddr=0x268 size=0x1 parent=s0 p.vaddr=0x268
+[UTEST]  space=server vaddr=0x269 size=0x1 parent=s0 p.vaddr=0x269
+[UTEST]  space=server vaddr=0x26a size=0x1 parent=s0 p.vaddr=0x26a
+[UTEST]  space=server vaddr=0x26b size=0x1 parent=s0 p.vaddr=0x26b
+[UTEST]  space=server vaddr=0x26c size=0x1 parent=s0 p.vaddr=0x26c
+[UTEST]  space=server vaddr=0x26d size=0x1 parent=s0 p.vaddr=0x26d
+[UTEST]  space=server vaddr=0x26e size=0x1 parent=s0 p.vaddr=0x26e
+[UTEST]  space=server vaddr=0x26f size=0x1 parent=s0 p.vaddr=0x26f
+[UTEST]  space=server vaddr=0x270 size=0x1 parent=s0 p.vaddr=0x270
+[UTEST]  space=server vaddr=0x271 size=0x1 parent=s0 p.vaddr=0x271
+[UTEST]  space=server vaddr=0x272 size=0x1 parent=s0 p.vaddr=0x272
+[UTEST]  space=server vaddr=0x273 size=0x1 parent=s0 p.vaddr=0x273
+[UTEST]  space=server vaddr=0x274 size=0x1 parent=s0 p.vaddr=0x274
+[UTEST]  space=server vaddr=0x275 size=0x1 parent=s0 p.vaddr=0x275
+[UTEST]  space=server vaddr=0x276 size=0x1 parent=s0 p.vaddr=0x276
+[UTEST]  space=server vaddr=0x277 size=0x1 parent=s0 p.vaddr=0x277
+[UTEST]  space=server vaddr=0x278 size=0x1 parent=s0 p.vaddr=0x278
+[UTEST]  space=server vaddr=0x279 size=0x1 parent=s0 p.vaddr=0x279
+[UTEST]  space=server vaddr=0x27a size=0x1 parent=s0 p.vaddr=0x27a
+[UTEST]  space=server vaddr=0x27b size=0x1 parent=s0 p.vaddr=0x27b
+[UTEST]  space=server vaddr=0x27c size=0x1 parent=s0 p.vaddr=0x27c
+[UTEST]  space=server vaddr=0x27d size=0x1 parent=s0 p.vaddr=0x27d
+[UTEST]  space=server vaddr=0x27e size=0x1 parent=s0 p.vaddr=0x27e
+[UTEST]  space=server vaddr=0x27f size=0x1 parent=s0 p.vaddr=0x27f
+[UTEST]  space=server vaddr=0x280 size=0x1 parent=s0 p.vaddr=0x280
+[UTEST]  space=server vaddr=0x281 size=0x1 parent=s0 p.vaddr=0x281
+[UTEST]  space=server vaddr=0x282 size=0x1 parent=s0 p.vaddr=0x282
+[UTEST]  space=server vaddr=0x283 size=0x1 parent=s0 p.vaddr=0x283
+[UTEST]  space=server vaddr=0x284 size=0x1 parent=s0 p.vaddr=0x284
+[UTEST]  space=server vaddr=0x285 size=0x1 parent=s0 p.vaddr=0x285
+[UTEST]  space=server vaddr=0x286 size=0x1 parent=s0 p.vaddr=0x286
+[UTEST]  space=server vaddr=0x287 size=0x1 parent=s0 p.vaddr=0x287
+[UTEST]  space=server vaddr=0x288 size=0x1 parent=s0 p.vaddr=0x288
+[UTEST]  space=server vaddr=0x289 size=0x1 parent=s0 p.vaddr=0x289
+[UTEST]  space=server vaddr=0x28a size=0x1 parent=s0 p.vaddr=0x28a
+[UTEST]  space=server vaddr=0x28b size=0x1 parent=s0 p.vaddr=0x28b
+[UTEST]  space=server vaddr=0x28c size=0x1 parent=s0 p.vaddr=0x28c
+[UTEST]  space=server vaddr=0x28d size=0x1 parent=s0 p.vaddr=0x28d
+[UTEST]  space=server vaddr=0x28e size=0x1 parent=s0 p.vaddr=0x28e
+[UTEST]  space=server vaddr=0x28f size=0x1 parent=s0 p.vaddr=0x28f
+[UTEST]  space=server vaddr=0x290 size=0x1 parent=s0 p.vaddr=0x290
+[UTEST]  space=server vaddr=0x291 size=0x1 parent=s0 p.vaddr=0x291
+[UTEST]  space=server vaddr=0x292 size=0x1 parent=s0 p.vaddr=0x292
+[UTEST]  space=server vaddr=0x293 size=0x1 parent=s0 p.vaddr=0x293
+[UTEST]  space=server vaddr=0x294 size=0x1 parent=s0 p.vaddr=0x294
+[UTEST]  space=server vaddr=0x295 size=0x1 parent=s0 p.vaddr=0x295
+[UTEST]  space=server vaddr=0x296 size=0x1 parent=s0 p.vaddr=0x296
+[UTEST]  space=server vaddr=0x297 size=0x1 parent=s0 p.vaddr=0x297
+[UTEST]  space=server vaddr=0x298 size=0x1 parent=s0 p.vaddr=0x298
+[UTEST]  space=server vaddr=0x299 size=0x1 parent=s0 p.vaddr=0x299
+[UTEST]  space=server vaddr=0x29a size=0x1 parent=s0 p.vaddr=0x29a
+[UTEST]  space=server vaddr=0x29b size=0x1 parent=s0 p.vaddr=0x29b
+[UTEST]  space=server vaddr=0x29c size=0x1 parent=s0 p.vaddr=0x29c
+[UTEST]  space=server vaddr=0x29d size=0x1 parent=s0 p.vaddr=0x29d
+[UTEST]  space=server vaddr=0x29e size=0x1 parent=s0 p.vaddr=0x29e
+[UTEST]  space=server vaddr=0x29f size=0x1 parent=s0 p.vaddr=0x29f
+[UTEST]  space=server vaddr=0x2a0 size=0x1 parent=s0 p.vaddr=0x2a0
+[UTEST]  space=server vaddr=0x2a1 size=0x1 parent=s0 p.vaddr=0x2a1
+[UTEST]  space=server vaddr=0x2a2 size=0x1 parent=s0 p.vaddr=0x2a2
+[UTEST]  space=server vaddr=0x2a3 size=0x1 parent=s0 p.vaddr=0x2a3
+[UTEST]  space=server vaddr=0x2a4 size=0x1 parent=s0 p.vaddr=0x2a4
+[UTEST]  space=server vaddr=0x2a5 size=0x1 parent=s0 p.vaddr=0x2a5
+[UTEST]  space=server vaddr=0x2a6 size=0x1 parent=s0 p.vaddr=0x2a6
+[UTEST]  space=server vaddr=0x2a7 size=0x1 parent=s0 p.vaddr=0x2a7
+[UTEST]  space=server vaddr=0x2a8 size=0x1 parent=s0 p.vaddr=0x2a8
+[UTEST]  space=server vaddr=0x2a9 size=0x1 parent=s0 p.vaddr=0x2a9
+[UTEST]  space=server vaddr=0x2aa size=0x1 parent=s0 p.vaddr=0x2aa
+[UTEST]  space=server vaddr=0x2ab size=0x1 parent=s0 p.vaddr=0x2ab
+[UTEST]  space=server vaddr=0x2ac size=0x1 parent=s0 p.vaddr=0x2ac
+[UTEST]  space=server vaddr=0x2ad size=0x1 parent=s0 p.vaddr=0x2ad
+[UTEST]  space=server vaddr=0x2ae size=0x1 parent=s0 p.vaddr=0x2ae
+[UTEST]  space=server vaddr=0x2af size=0x1 parent=s0 p.vaddr=0x2af
+[UTEST]  space=server vaddr=0x2b0 size=0x1 parent=s0 p.vaddr=0x2b0
+[UTEST]  space=server vaddr=0x2b1 size=0x1 parent=s0 p.vaddr=0x2b1
+[UTEST]  space=server vaddr=0x2b2 size=0x1 parent=s0 p.vaddr=0x2b2
+[UTEST]  space=server vaddr=0x2b3 size=0x1 parent=s0 p.vaddr=0x2b3
+[UTEST]  space=server vaddr=0x2b4 size=0x1 parent=s0 p.vaddr=0x2b4
+[UTEST]  space=server vaddr=0x2b5 size=0x1 parent=s0 p.vaddr=0x2b5
+[UTEST]  space=server vaddr=0x2b6 size=0x1 parent=s0 p.vaddr=0x2b6
+[UTEST]  space=server vaddr=0x2b7 size=0x1 parent=s0 p.vaddr=0x2b7
+[UTEST]  space=server vaddr=0x2b8 size=0x1 parent=s0 p.vaddr=0x2b8
+[UTEST]  space=server vaddr=0x2b9 size=0x1 parent=s0 p.vaddr=0x2b9
+[UTEST]  space=server vaddr=0x2ba size=0x1 parent=s0 p.vaddr=0x2ba
+[UTEST]  space=server vaddr=0x2bb size=0x1 parent=s0 p.vaddr=0x2bb
+[UTEST]  space=server vaddr=0x2bc size=0x1 parent=s0 p.vaddr=0x2bc
+[UTEST]  space=server vaddr=0x2bd size=0x1 parent=s0 p.vaddr=0x2bd
+[UTEST]  space=server vaddr=0x2be size=0x1 parent=s0 p.vaddr=0x2be
+[UTEST]  space=server vaddr=0x2bf size=0x1 parent=s0 p.vaddr=0x2bf
+[UTEST]  space=server vaddr=0x2c0 size=0x1 parent=s0 p.vaddr=0x2c0
+[UTEST]  space=server vaddr=0x2c1 size=0x1 parent=s0 p.vaddr=0x2c1
+[UTEST]  space=server vaddr=0x2c2 size=0x1 parent=s0 p.vaddr=0x2c2
+[UTEST]  space=server vaddr=0x2c3 size=0x1 parent=s0 p.vaddr=0x2c3
+[UTEST]  space=server vaddr=0x2c4 size=0x1 parent=s0 p.vaddr=0x2c4
+[UTEST]  space=server vaddr=0x2c5 size=0x1 parent=s0 p.vaddr=0x2c5
+[UTEST]  space=server vaddr=0x2c6 size=0x1 parent=s0 p.vaddr=0x2c6
+[UTEST]  space=server vaddr=0x2c7 size=0x1 parent=s0 p.vaddr=0x2c7
+[UTEST]  space=server vaddr=0x2c8 size=0x1 parent=s0 p.vaddr=0x2c8
+[UTEST]  space=server vaddr=0x2c9 size=0x1 parent=s0 p.vaddr=0x2c9
+[UTEST]  space=server vaddr=0x2ca size=0x1 parent=s0 p.vaddr=0x2ca
+[UTEST]  space=server vaddr=0x2cb size=0x1 parent=s0 p.vaddr=0x2cb
+[UTEST]  space=server vaddr=0x2cc size=0x1 parent=s0 p.vaddr=0x2cc
+[UTEST]  space=server vaddr=0x2cd size=0x1 parent=s0 p.vaddr=0x2cd
+[UTEST]  space=server vaddr=0x2ce size=0x1 parent=s0 p.vaddr=0x2ce
+[UTEST]  space=server vaddr=0x2cf size=0x1 parent=s0 p.vaddr=0x2cf
+[UTEST]  space=server vaddr=0x2d0 size=0x1 parent=s0 p.vaddr=0x2d0
+[UTEST]  space=server vaddr=0x2d1 size=0x1 parent=s0 p.vaddr=0x2d1
+[UTEST]  space=server vaddr=0x2d2 size=0x1 parent=s0 p.vaddr=0x2d2
+[UTEST]  space=server vaddr=0x2d3 size=0x1 parent=s0 p.vaddr=0x2d3
+[UTEST]  space=server vaddr=0x2d4 size=0x1 parent=s0 p.vaddr=0x2d4
+[UTEST]  space=server vaddr=0x2d5 size=0x1 parent=s0 p.vaddr=0x2d5
+[UTEST]  space=server vaddr=0x2d6 size=0x1 parent=s0 p.vaddr=0x2d6
+[UTEST]  space=server vaddr=0x2d7 size=0x1 parent=s0 p.vaddr=0x2d7
+[UTEST]  space=server vaddr=0x2d8 size=0x1 parent=s0 p.vaddr=0x2d8
+[UTEST]  space=server vaddr=0x2d9 size=0x1 parent=s0 p.vaddr=0x2d9
+[UTEST]  space=server vaddr=0x2da size=0x1 parent=s0 p.vaddr=0x2da
+[UTEST]  space=server vaddr=0x2db size=0x1 parent=s0 p.vaddr=0x2db
+[UTEST]  space=server vaddr=0x2dc size=0x1 parent=s0 p.vaddr=0x2dc
+[UTEST]  space=server vaddr=0x2dd size=0x1 parent=s0 p.vaddr=0x2dd
+[UTEST]  space=server vaddr=0x2de size=0x1 parent=s0 p.vaddr=0x2de
+[UTEST]  space=server vaddr=0x2df size=0x1 parent=s0 p.vaddr=0x2df
+[UTEST]  space=server vaddr=0x2e0 size=0x1 parent=s0 p.vaddr=0x2e0
+[UTEST]  space=server vaddr=0x2e1 size=0x1 parent=s0 p.vaddr=0x2e1
+[UTEST]  space=server vaddr=0x2e2 size=0x1 parent=s0 p.vaddr=0x2e2
+[UTEST]  space=server vaddr=0x2e3 size=0x1 parent=s0 p.vaddr=0x2e3
+[UTEST]  space=server vaddr=0x2e4 size=0x1 parent=s0 p.vaddr=0x2e4
+[UTEST]  space=server vaddr=0x2e5 size=0x1 parent=s0 p.vaddr=0x2e5
+[UTEST]  space=server vaddr=0x2e6 size=0x1 parent=s0 p.vaddr=0x2e6
+[UTEST]  space=server vaddr=0x2e7 size=0x1 parent=s0 p.vaddr=0x2e7
+[UTEST]  space=server vaddr=0x2e8 size=0x1 parent=s0 p.vaddr=0x2e8
+[UTEST]  space=server vaddr=0x2e9 size=0x1 parent=s0 p.vaddr=0x2e9
+[UTEST]  space=server vaddr=0x2ea size=0x1 parent=s0 p.vaddr=0x2ea
+[UTEST]  space=server vaddr=0x2eb size=0x1 parent=s0 p.vaddr=0x2eb
+[UTEST]  space=server vaddr=0x2ec size=0x1 parent=s0 p.vaddr=0x2ec
+[UTEST]  space=server vaddr=0x2ed size=0x1 parent=s0 p.vaddr=0x2ed
+[UTEST]  space=server vaddr=0x2ee size=0x1 parent=s0 p.vaddr=0x2ee
+[UTEST]  space=server vaddr=0x2ef size=0x1 parent=s0 p.vaddr=0x2ef
+[UTEST]  space=server vaddr=0x2f0 size=0x1 parent=s0 p.vaddr=0x2f0
+[UTEST]  space=server vaddr=0x2f1 size=0x1 parent=s0 p.vaddr=0x2f1
+[UTEST]  space=server vaddr=0x2f2 size=0x1 parent=s0 p.vaddr=0x2f2
+[UTEST]  space=server vaddr=0x2f3 size=0x1 parent=s0 p.vaddr=0x2f3
+[UTEST]  space=server vaddr=0x2f4 size=0x1 parent=s0 p.vaddr=0x2f4
+[UTEST]  space=server vaddr=0x2f5 size=0x1 parent=s0 p.vaddr=0x2f5
+[UTEST]  space=server vaddr=0x2f6 size=0x1 parent=s0 p.vaddr=0x2f6
+[UTEST]  space=server vaddr=0x2f7 size=0x1 parent=s0 p.vaddr=0x2f7
+[UTEST]  space=server vaddr=0x2f8 size=0x1 parent=s0 p.vaddr=0x2f8
+[UTEST]  space=server vaddr=0x2f9 size=0x1 parent=s0 p.vaddr=0x2f9
+[UTEST]  space=server vaddr=0x2fa size=0x1 parent=s0 p.vaddr=0x2fa
+[UTEST]  space=server vaddr=0x2fb size=0x1 parent=s0 p.vaddr=0x2fb
+[UTEST]  space=server vaddr=0x2fc size=0x1 parent=s0 p.vaddr=0x2fc
+[UTEST]  space=server vaddr=0x2fd size=0x1 parent=s0 p.vaddr=0x2fd
+[UTEST]  space=server vaddr=0x2fe size=0x1 parent=s0 p.vaddr=0x2fe
+[UTEST]  space=server vaddr=0x2ff size=0x1 parent=s0 p.vaddr=0x2ff
+[UTEST]  space=server vaddr=0x300 size=0x1 parent=s0 p.vaddr=0x300
+[UTEST]  space=server vaddr=0x301 size=0x1 parent=s0 p.vaddr=0x301
+[UTEST]  space=server vaddr=0x302 size=0x1 parent=s0 p.vaddr=0x302
+[UTEST]  space=server vaddr=0x303 size=0x1 parent=s0 p.vaddr=0x303
+[UTEST]  space=server vaddr=0x304 size=0x1 parent=s0 p.vaddr=0x304
+[UTEST]  space=server vaddr=0x305 size=0x1 parent=s0 p.vaddr=0x305
+[UTEST]  space=server vaddr=0x306 size=0x1 parent=s0 p.vaddr=0x306
+[UTEST]  space=server vaddr=0x307 size=0x1 parent=s0 p.vaddr=0x307
+[UTEST]  space=server vaddr=0x308 size=0x1 parent=s0 p.vaddr=0x308
+[UTEST]  space=server vaddr=0x309 size=0x1 parent=s0 p.vaddr=0x309
+[UTEST]  space=server vaddr=0x30a size=0x1 parent=s0 p.vaddr=0x30a
+[UTEST]  space=server vaddr=0x30b size=0x1 parent=s0 p.vaddr=0x30b
+[UTEST]  space=server vaddr=0x30c size=0x1 parent=s0 p.vaddr=0x30c
+[UTEST]  space=server vaddr=0x30d size=0x1 parent=s0 p.vaddr=0x30d
+[UTEST]  space=server vaddr=0x30e size=0x1 parent=s0 p.vaddr=0x30e
+[UTEST]  space=server vaddr=0x30f size=0x1 parent=s0 p.vaddr=0x30f
+[UTEST]  space=server vaddr=0x310 size=0x1 parent=s0 p.vaddr=0x310
+[UTEST]  space=server vaddr=0x311 size=0x1 parent=s0 p.vaddr=0x311
+[UTEST]  space=server vaddr=0x312 size=0x1 parent=s0 p.vaddr=0x312
+[UTEST]  space=server vaddr=0x313 size=0x1 parent=s0 p.vaddr=0x313
+[UTEST]  space=server vaddr=0x314 size=0x1 parent=s0 p.vaddr=0x314
+[UTEST]  space=server vaddr=0x315 size=0x1 parent=s0 p.vaddr=0x315
+[UTEST]  space=server vaddr=0x316 size=0x1 parent=s0 p.vaddr=0x316
+[UTEST]  space=server vaddr=0x317 size=0x1 parent=s0 p.vaddr=0x317
+[UTEST]  space=server vaddr=0x318 size=0x1 parent=s0 p.vaddr=0x318
+[UTEST]  space=server vaddr=0x319 size=0x1 parent=s0 p.vaddr=0x319
+[UTEST]  space=server vaddr=0x31a size=0x1 parent=s0 p.vaddr=0x31a
+[UTEST]  space=server vaddr=0x31b size=0x1 parent=s0 p.vaddr=0x31b
+[UTEST]  space=server vaddr=0x31c size=0x1 parent=s0 p.vaddr=0x31c
+[UTEST]  space=server vaddr=0x31d size=0x1 parent=s0 p.vaddr=0x31d
+[UTEST]  space=server vaddr=0x31e size=0x1 parent=s0 p.vaddr=0x31e
+[UTEST]  space=server vaddr=0x31f size=0x1 parent=s0 p.vaddr=0x31f
+[UTEST]  space=server vaddr=0x320 size=0x1 parent=s0 p.vaddr=0x320
+[UTEST]  space=server vaddr=0x321 size=0x1 parent=s0 p.vaddr=0x321
+[UTEST]  space=server vaddr=0x322 size=0x1 parent=s0 p.vaddr=0x322
+[UTEST]  space=server vaddr=0x323 size=0x1 parent=s0 p.vaddr=0x323
+[UTEST]  space=server vaddr=0x324 size=0x1 parent=s0 p.vaddr=0x324
+[UTEST]  space=server vaddr=0x325 size=0x1 parent=s0 p.vaddr=0x325
+[UTEST]  space=server vaddr=0x326 size=0x1 parent=s0 p.vaddr=0x326
+[UTEST]  space=server vaddr=0x327 size=0x1 parent=s0 p.vaddr=0x327
+[UTEST]  space=server vaddr=0x328 size=0x1 parent=s0 p.vaddr=0x328
+[UTEST]  space=server vaddr=0x329 size=0x1 parent=s0 p.vaddr=0x329
+[UTEST]  space=server vaddr=0x32a size=0x1 parent=s0 p.vaddr=0x32a
+[UTEST]  space=server vaddr=0x32b size=0x1 parent=s0 p.vaddr=0x32b
+[UTEST]  space=server vaddr=0x32c size=0x1 parent=s0 p.vaddr=0x32c
+[UTEST]  space=server vaddr=0x32d size=0x1 parent=s0 p.vaddr=0x32d
+[UTEST]  space=server vaddr=0x32e size=0x1 parent=s0 p.vaddr=0x32e
+[UTEST]  space=server vaddr=0x32f size=0x1 parent=s0 p.vaddr=0x32f
+[UTEST]  space=server vaddr=0x330 size=0x1 parent=s0 p.vaddr=0x330
+[UTEST]  space=server vaddr=0x331 size=0x1 parent=s0 p.vaddr=0x331
+[UTEST]  space=server vaddr=0x332 size=0x1 parent=s0 p.vaddr=0x332
+[UTEST]  space=server vaddr=0x333 size=0x1 parent=s0 p.vaddr=0x333
+[UTEST]  space=server vaddr=0x334 size=0x1 parent=s0 p.vaddr=0x334
+[UTEST]  space=server vaddr=0x335 size=0x1 parent=s0 p.vaddr=0x335
+[UTEST]  space=server vaddr=0x336 size=0x1 parent=s0 p.vaddr=0x336
+[UTEST]  space=server vaddr=0x337 size=0x1 parent=s0 p.vaddr=0x337
+[UTEST]  space=server vaddr=0x338 size=0x1 parent=s0 p.vaddr=0x338
+[UTEST]  space=server vaddr=0x339 size=0x1 parent=s0 p.vaddr=0x339
+[UTEST]  space=server vaddr=0x33a size=0x1 parent=s0 p.vaddr=0x33a
+[UTEST]  space=server vaddr=0x33b size=0x1 parent=s0 p.vaddr=0x33b
+[UTEST]  space=server vaddr=0x33c size=0x1 parent=s0 p.vaddr=0x33c
+[UTEST]  space=server vaddr=0x33d size=0x1 parent=s0 p.vaddr=0x33d
+[UTEST]  space=server vaddr=0x33e size=0x1 parent=s0 p.vaddr=0x33e
+[UTEST]  space=server vaddr=0x33f size=0x1 parent=s0 p.vaddr=0x33f
+[UTEST]  space=server vaddr=0x340 size=0x1 parent=s0 p.vaddr=0x340
+[UTEST]  space=server vaddr=0x341 size=0x1 parent=s0 p.vaddr=0x341
+[UTEST]  space=server vaddr=0x342 size=0x1 parent=s0 p.vaddr=0x342
+[UTEST]  space=server vaddr=0x343 size=0x1 parent=s0 p.vaddr=0x343
+[UTEST]  space=server vaddr=0x344 size=0x1 parent=s0 p.vaddr=0x344
+[UTEST]  space=server vaddr=0x345 size=0x1 parent=s0 p.vaddr=0x345
+[UTEST]  space=server vaddr=0x346 size=0x1 parent=s0 p.vaddr=0x346
+[UTEST]  space=server vaddr=0x347 size=0x1 parent=s0 p.vaddr=0x347
+[UTEST]  space=server vaddr=0x348 size=0x1 parent=s0 p.vaddr=0x348
+[UTEST]  space=server vaddr=0x349 size=0x1 parent=s0 p.vaddr=0x349
+[UTEST]  space=server vaddr=0x34a size=0x1 parent=s0 p.vaddr=0x34a
+[UTEST]  space=server vaddr=0x34b size=0x1 parent=s0 p.vaddr=0x34b
+[UTEST]  space=server vaddr=0x34c size=0x1 parent=s0 p.vaddr=0x34c
+[UTEST]  space=server vaddr=0x34d size=0x1 parent=s0 p.vaddr=0x34d
+[UTEST]  space=server vaddr=0x34e size=0x1 parent=s0 p.vaddr=0x34e
+[UTEST]  space=server vaddr=0x34f size=0x1 parent=s0 p.vaddr=0x34f
+[UTEST]  space=server vaddr=0x350 size=0x1 parent=s0 p.vaddr=0x350
+[UTEST]  space=server vaddr=0x351 size=0x1 parent=s0 p.vaddr=0x351
+[UTEST]  space=server vaddr=0x352 size=0x1 parent=s0 p.vaddr=0x352
+[UTEST]  space=server vaddr=0x353 size=0x1 parent=s0 p.vaddr=0x353
+[UTEST]  space=server vaddr=0x354 size=0x1 parent=s0 p.vaddr=0x354
+[UTEST]  space=server vaddr=0x355 size=0x1 parent=s0 p.vaddr=0x355
+[UTEST]  space=server vaddr=0x356 size=0x1 parent=s0 p.vaddr=0x356
+[UTEST]  space=server vaddr=0x357 size=0x1 parent=s0 p.vaddr=0x357
+[UTEST]  space=server vaddr=0x358 size=0x1 parent=s0 p.vaddr=0x358
+[UTEST]  space=server vaddr=0x359 size=0x1 parent=s0 p.vaddr=0x359
+[UTEST]  space=server vaddr=0x35a size=0x1 parent=s0 p.vaddr=0x35a
+[UTEST]  space=server vaddr=0x35b size=0x1 parent=s0 p.vaddr=0x35b
+[UTEST]  space=server vaddr=0x35c size=0x1 parent=s0 p.vaddr=0x35c
+[UTEST]  space=server vaddr=0x35d size=0x1 parent=s0 p.vaddr=0x35d
+[UTEST]  space=server vaddr=0x35e size=0x1 parent=s0 p.vaddr=0x35e
+[UTEST]  space=server vaddr=0x35f size=0x1 parent=s0 p.vaddr=0x35f
+[UTEST]  space=server vaddr=0x360 size=0x1 parent=s0 p.vaddr=0x360
+[UTEST]  space=server vaddr=0x361 size=0x1 parent=s0 p.vaddr=0x361
+[UTEST]  space=server vaddr=0x362 size=0x1 parent=s0 p.vaddr=0x362
+[UTEST]  space=server vaddr=0x363 size=0x1 parent=s0 p.vaddr=0x363
+[UTEST]  space=server vaddr=0x364 size=0x1 parent=s0 p.vaddr=0x364
+[UTEST]  space=server vaddr=0x365 size=0x1 parent=s0 p.vaddr=0x365
+[UTEST]  space=server vaddr=0x366 size=0x1 parent=s0 p.vaddr=0x366
+[UTEST]  space=server vaddr=0x367 size=0x1 parent=s0 p.vaddr=0x367
+[UTEST]  space=server vaddr=0x368 size=0x1 parent=s0 p.vaddr=0x368
+[UTEST]  space=server vaddr=0x369 size=0x1 parent=s0 p.vaddr=0x369
+[UTEST]  space=server vaddr=0x36a size=0x1 parent=s0 p.vaddr=0x36a
+[UTEST]  space=server vaddr=0x36b size=0x1 parent=s0 p.vaddr=0x36b
+[UTEST]  space=server vaddr=0x36c size=0x1 parent=s0 p.vaddr=0x36c
+[UTEST]  space=server vaddr=0x36d size=0x1 parent=s0 p.vaddr=0x36d
+[UTEST]  space=server vaddr=0x36e size=0x1 parent=s0 p.vaddr=0x36e
+[UTEST]  space=server vaddr=0x36f size=0x1 parent=s0 p.vaddr=0x36f
+[UTEST]  space=server vaddr=0x370 size=0x1 parent=s0 p.vaddr=0x370
+[UTEST]  space=server vaddr=0x371 size=0x1 parent=s0 p.vaddr=0x371
+[UTEST]  space=server vaddr=0x372 size=0x1 parent=s0 p.vaddr=0x372
+[UTEST]  space=server vaddr=0x373 size=0x1 parent=s0 p.vaddr=0x373
+[UTEST]  space=server vaddr=0x374 size=0x1 parent=s0 p.vaddr=0x374
+[UTEST]  space=server vaddr=0x375 size=0x1 parent=s0 p.vaddr=0x375
+[UTEST]  space=server vaddr=0x376 size=0x1 parent=s0 p.vaddr=0x376
+[UTEST]  space=server vaddr=0x377 size=0x1 parent=s0 p.vaddr=0x377
+[UTEST]  space=server vaddr=0x378 size=0x1 parent=s0 p.vaddr=0x378
+[UTEST]  space=server vaddr=0x379 size=0x1 parent=s0 p.vaddr=0x379
+[UTEST]  space=server vaddr=0x37a size=0x1 parent=s0 p.vaddr=0x37a
+[UTEST]  space=server vaddr=0x37b size=0x1 parent=s0 p.vaddr=0x37b
+[UTEST]  space=server vaddr=0x37c size=0x1 parent=s0 p.vaddr=0x37c
+[UTEST]  space=server vaddr=0x37d size=0x1 parent=s0 p.vaddr=0x37d
+[UTEST]  space=server vaddr=0x37e size=0x1 parent=s0 p.vaddr=0x37e
+[UTEST]  space=server vaddr=0x37f size=0x1 parent=s0 p.vaddr=0x37f
+[UTEST]  space=server vaddr=0x380 size=0x1 parent=s0 p.vaddr=0x380
+[UTEST]  space=server vaddr=0x381 size=0x1 parent=s0 p.vaddr=0x381
+[UTEST]  space=server vaddr=0x382 size=0x1 parent=s0 p.vaddr=0x382
+[UTEST]  space=server vaddr=0x383 size=0x1 parent=s0 p.vaddr=0x383
+[UTEST]  space=server vaddr=0x384 size=0x1 parent=s0 p.vaddr=0x384
+[UTEST]  space=server vaddr=0x385 size=0x1 parent=s0 p.vaddr=0x385
+[UTEST]  space=server vaddr=0x386 size=0x1 parent=s0 p.vaddr=0x386
+[UTEST]  space=server vaddr=0x387 size=0x1 parent=s0 p.vaddr=0x387
+[UTEST]  space=server vaddr=0x388 size=0x1 parent=s0 p.vaddr=0x388
+[UTEST]  space=server vaddr=0x389 size=0x1 parent=s0 p.vaddr=0x389
+[UTEST]  space=server vaddr=0x38a size=0x1 parent=s0 p.vaddr=0x38a
+[UTEST]  space=server vaddr=0x38b size=0x1 parent=s0 p.vaddr=0x38b
+[UTEST]  space=server vaddr=0x38c size=0x1 parent=s0 p.vaddr=0x38c
+[UTEST]  space=server vaddr=0x38d size=0x1 parent=s0 p.vaddr=0x38d
+[UTEST]  space=server vaddr=0x38e size=0x1 parent=s0 p.vaddr=0x38e
+[UTEST]  space=server vaddr=0x38f size=0x1 parent=s0 p.vaddr=0x38f
+[UTEST]  space=server vaddr=0x390 size=0x1 parent=s0 p.vaddr=0x390
+[UTEST]  space=server vaddr=0x391 size=0x1 parent=s0 p.vaddr=0x391
+[UTEST]  space=server vaddr=0x392 size=0x1 parent=s0 p.vaddr=0x392
+[UTEST]  space=server vaddr=0x393 size=0x1 parent=s0 p.vaddr=0x393
+[UTEST]  space=server vaddr=0x394 size=0x1 parent=s0 p.vaddr=0x394
+[UTEST]  space=server vaddr=0x395 size=0x1 parent=s0 p.vaddr=0x395
+[UTEST]  space=server vaddr=0x396 size=0x1 parent=s0 p.vaddr=0x396
+[UTEST]  space=server vaddr=0x397 size=0x1 parent=s0 p.vaddr=0x397
+[UTEST]  space=server vaddr=0x398 size=0x1 parent=s0 p.vaddr=0x398
+[UTEST]  space=server vaddr=0x399 size=0x1 parent=s0 p.vaddr=0x399
+[UTEST]  space=server vaddr=0x39a size=0x1 parent=s0 p.vaddr=0x39a
+[UTEST]  space=server vaddr=0x39b size=0x1 parent=s0 p.vaddr=0x39b
+[UTEST]  space=server vaddr=0x39c size=0x1 parent=s0 p.vaddr=0x39c
+[UTEST]  space=server vaddr=0x39d size=0x1 parent=s0 p.vaddr=0x39d
+[UTEST]  space=server vaddr=0x39e size=0x1 parent=s0 p.vaddr=0x39e
+[UTEST]  space=server vaddr=0x39f size=0x1 parent=s0 p.vaddr=0x39f
+[UTEST]  space=server vaddr=0x3a0 size=0x1 parent=s0 p.vaddr=0x3a0
+[UTEST]  space=server vaddr=0x3a1 size=0x1 parent=s0 p.vaddr=0x3a1
+[UTEST]  space=server vaddr=0x3a2 size=0x1 parent=s0 p.vaddr=0x3a2
+[UTEST]  space=server vaddr=0x3a3 size=0x1 parent=s0 p.vaddr=0x3a3
+[UTEST]  space=server vaddr=0x3a4 size=0x1 parent=s0 p.vaddr=0x3a4
+[UTEST]  space=server vaddr=0x3a5 size=0x1 parent=s0 p.vaddr=0x3a5
+[UTEST]  space=server vaddr=0x3a6 size=0x1 parent=s0 p.vaddr=0x3a6
+[UTEST]  space=server vaddr=0x3a7 size=0x1 parent=s0 p.vaddr=0x3a7
+[UTEST]  space=server vaddr=0x3a8 size=0x1 parent=s0 p.vaddr=0x3a8
+[UTEST]  space=server vaddr=0x3a9 size=0x1 parent=s0 p.vaddr=0x3a9
+[UTEST]  space=server vaddr=0x3aa size=0x1 parent=s0 p.vaddr=0x3aa
+[UTEST]  space=server vaddr=0x3ab size=0x1 parent=s0 p.vaddr=0x3ab
+[UTEST]  space=server vaddr=0x3ac size=0x1 parent=s0 p.vaddr=0x3ac
+[UTEST]  space=server vaddr=0x3ad size=0x1 parent=s0 p.vaddr=0x3ad
+[UTEST]  space=server vaddr=0x3ae size=0x1 parent=s0 p.vaddr=0x3ae
+[UTEST]  space=server vaddr=0x3af size=0x1 parent=s0 p.vaddr=0x3af
+[UTEST]  space=server vaddr=0x3b0 size=0x1 parent=s0 p.vaddr=0x3b0
+[UTEST]  space=server vaddr=0x3b1 size=0x1 parent=s0 p.vaddr=0x3b1
+[UTEST]  space=server vaddr=0x3b2 size=0x1 parent=s0 p.vaddr=0x3b2
+[UTEST]  space=server vaddr=0x3b3 size=0x1 parent=s0 p.vaddr=0x3b3
+[UTEST]  space=server vaddr=0x3b4 size=0x1 parent=s0 p.vaddr=0x3b4
+[UTEST]  space=server vaddr=0x3b5 size=0x1 parent=s0 p.vaddr=0x3b5
+[UTEST]  space=server vaddr=0x3b6 size=0x1 parent=s0 p.vaddr=0x3b6
+[UTEST]  space=server vaddr=0x3b7 size=0x1 parent=s0 p.vaddr=0x3b7
+[UTEST]  space=server vaddr=0x3b8 size=0x1 parent=s0 p.vaddr=0x3b8
+[UTEST]  space=server vaddr=0x3b9 size=0x1 parent=s0 p.vaddr=0x3b9
+[UTEST]  space=server vaddr=0x3ba size=0x1 parent=s0 p.vaddr=0x3ba
+[UTEST]  space=server vaddr=0x3bb size=0x1 parent=s0 p.vaddr=0x3bb
+[UTEST]  space=server vaddr=0x3bc size=0x1 parent=s0 p.vaddr=0x3bc
+[UTEST]  space=server vaddr=0x3bd size=0x1 parent=s0 p.vaddr=0x3bd
+[UTEST]  space=server vaddr=0x3be size=0x1 parent=s0 p.vaddr=0x3be
+[UTEST]  space=server vaddr=0x3bf size=0x1 parent=s0 p.vaddr=0x3bf
+[UTEST]  space=server vaddr=0x3c0 size=0x1 parent=s0 p.vaddr=0x3c0
+[UTEST]  space=server vaddr=0x3c1 size=0x1 parent=s0 p.vaddr=0x3c1
+[UTEST]  space=server vaddr=0x3c2 size=0x1 parent=s0 p.vaddr=0x3c2
+[UTEST]  space=server vaddr=0x3c3 size=0x1 parent=s0 p.vaddr=0x3c3
+[UTEST]  space=server vaddr=0x3c4 size=0x1 parent=s0 p.vaddr=0x3c4
+[UTEST]  space=server vaddr=0x3c5 size=0x1 parent=s0 p.vaddr=0x3c5
+[UTEST]  space=server vaddr=0x3c6 size=0x1 parent=s0 p.vaddr=0x3c6
+[UTEST]  space=server vaddr=0x3c7 size=0x1 parent=s0 p.vaddr=0x3c7
+[UTEST]  space=server vaddr=0x3c8 size=0x1 parent=s0 p.vaddr=0x3c8
+[UTEST]  space=server vaddr=0x3c9 size=0x1 parent=s0 p.vaddr=0x3c9
+[UTEST]  space=server vaddr=0x3ca size=0x1 parent=s0 p.vaddr=0x3ca
+[UTEST]  space=server vaddr=0x3cb size=0x1 parent=s0 p.vaddr=0x3cb
+[UTEST]  space=server vaddr=0x3cc size=0x1 parent=s0 p.vaddr=0x3cc
+[UTEST]  space=server vaddr=0x3cd size=0x1 parent=s0 p.vaddr=0x3cd
+[UTEST]  space=server vaddr=0x3ce size=0x1 parent=s0 p.vaddr=0x3ce
+[UTEST]  space=server vaddr=0x3cf size=0x1 parent=s0 p.vaddr=0x3cf
+[UTEST]  space=server vaddr=0x3d0 size=0x1 parent=s0 p.vaddr=0x3d0
+[UTEST]  space=server vaddr=0x3d1 size=0x1 parent=s0 p.vaddr=0x3d1
+[UTEST]  space=server vaddr=0x3d2 size=0x1 parent=s0 p.vaddr=0x3d2
+[UTEST]  space=server vaddr=0x3d3 size=0x1 parent=s0 p.vaddr=0x3d3
+[UTEST]  space=server vaddr=0x3d4 size=0x1 parent=s0 p.vaddr=0x3d4
+[UTEST]  space=server vaddr=0x3d5 size=0x1 parent=s0 p.vaddr=0x3d5
+[UTEST]  space=server vaddr=0x3d6 size=0x1 parent=s0 p.vaddr=0x3d6
+[UTEST]  space=server vaddr=0x3d7 size=0x1 parent=s0 p.vaddr=0x3d7
+[UTEST]  space=server vaddr=0x3d8 size=0x1 parent=s0 p.vaddr=0x3d8
+[UTEST]  space=server vaddr=0x3d9 size=0x1 parent=s0 p.vaddr=0x3d9
+[UTEST]  space=server vaddr=0x3da size=0x1 parent=s0 p.vaddr=0x3da
+[UTEST]  space=server vaddr=0x3db size=0x1 parent=s0 p.vaddr=0x3db
+[UTEST]  space=server vaddr=0x3dc size=0x1 parent=s0 p.vaddr=0x3dc
+[UTEST]  space=server vaddr=0x3dd size=0x1 parent=s0 p.vaddr=0x3dd
+[UTEST]  space=server vaddr=0x3de size=0x1 parent=s0 p.vaddr=0x3de
+[UTEST]  space=server vaddr=0x3df size=0x1 parent=s0 p.vaddr=0x3df
+[UTEST]  space=server vaddr=0x3e0 size=0x1 parent=s0 p.vaddr=0x3e0
+[UTEST]  space=server vaddr=0x3e1 size=0x1 parent=s0 p.vaddr=0x3e1
+[UTEST]  space=server vaddr=0x3e2 size=0x1 parent=s0 p.vaddr=0x3e2
+[UTEST]  space=server vaddr=0x3e3 size=0x1 parent=s0 p.vaddr=0x3e3
+[UTEST]  space=server vaddr=0x3e4 size=0x1 parent=s0 p.vaddr=0x3e4
+[UTEST]  space=server vaddr=0x3e5 size=0x1 parent=s0 p.vaddr=0x3e5
+[UTEST]  space=server vaddr=0x3e6 size=0x1 parent=s0 p.vaddr=0x3e6
+[UTEST]  space=server vaddr=0x3e7 size=0x1 parent=s0 p.vaddr=0x3e7
+[UTEST]  space=server vaddr=0x3e8 size=0x1 parent=s0 p.vaddr=0x3e8
+[UTEST]  space=server vaddr=0x3e9 size=0x1 parent=s0 p.vaddr=0x3e9
+[UTEST]  space=server vaddr=0x3ea size=0x1 parent=s0 p.vaddr=0x3ea
+[UTEST]  space=server vaddr=0x3eb size=0x1 parent=s0 p.vaddr=0x3eb
+[UTEST]  space=server vaddr=0x3ec size=0x1 parent=s0 p.vaddr=0x3ec
+[UTEST]  space=server vaddr=0x3ed size=0x1 parent=s0 p.vaddr=0x3ed
+[UTEST]  space=server vaddr=0x3ee size=0x1 parent=s0 p.vaddr=0x3ee
+[UTEST]  space=server vaddr=0x3ef size=0x1 parent=s0 p.vaddr=0x3ef
+[UTEST]  space=server vaddr=0x3f0 size=0x1 parent=s0 p.vaddr=0x3f0
+[UTEST]  space=server vaddr=0x3f1 size=0x1 parent=s0 p.vaddr=0x3f1
+[UTEST]  space=server vaddr=0x3f2 size=0x1 parent=s0 p.vaddr=0x3f2
+[UTEST]  space=server vaddr=0x3f3 size=0x1 parent=s0 p.vaddr=0x3f3
+[UTEST]  space=server vaddr=0x3f4 size=0x1 parent=s0 p.vaddr=0x3f4
+[UTEST]  space=server vaddr=0x3f5 size=0x1 parent=s0 p.vaddr=0x3f5
+[UTEST]  space=server vaddr=0x3f6 size=0x1 parent=s0 p.vaddr=0x3f6
+[UTEST]  space=server vaddr=0x3f7 size=0x1 parent=s0 p.vaddr=0x3f7
+[UTEST]  space=server vaddr=0x3f8 size=0x1 parent=s0 p.vaddr=0x3f8
+[UTEST]  space=server vaddr=0x3f9 size=0x1 parent=s0 p.vaddr=0x3f9
+[UTEST]  space=server vaddr=0x3fa size=0x1 parent=s0 p.vaddr=0x3fa
+[UTEST]  space=server vaddr=0x3fb size=0x1 parent=s0 p.vaddr=0x3fb
+[UTEST]  space=server vaddr=0x3fc size=0x1 parent=s0 p.vaddr=0x3fc
+[UTEST]  space=server vaddr=0x3fd size=0x1 parent=s0 p.vaddr=0x3fd
+[UTEST]  space=server vaddr=0x3fe size=0x1 parent=s0 p.vaddr=0x3fe
+[UTEST]  space=server vaddr=0x3ff size=0x1 parent=s0 p.vaddr=0x3ff
+[UTEST] 
+[UTEST] space=s0 vaddr=0x0 size=0x400
+[UTEST]  space=server vaddr=0x10 size=0x1 parent=s0 p.vaddr=0x10
+[UTEST] 
+[UTEST] Partially unmap superpage s0 [0/superpage]
+[UTEST] space=s0 vaddr=0x0 size=0x400
+[UTEST]  space=server vaddr=0x0 size=0x1 parent=s0 p.vaddr=0x0
+[UTEST]  space=server vaddr=0x1 size=0x1 parent=s0 p.vaddr=0x1
+[UTEST]  space=server vaddr=0x2 size=0x1 parent=s0 p.vaddr=0x2
+[UTEST]  space=server vaddr=0x3 size=0x1 parent=s0 p.vaddr=0x3
+[UTEST]  space=server vaddr=0x4 size=0x1 parent=s0 p.vaddr=0x4
+[UTEST]  space=server vaddr=0x5 size=0x1 parent=s0 p.vaddr=0x5
+[UTEST]  space=server vaddr=0x6 size=0x1 parent=s0 p.vaddr=0x6
+[UTEST]  space=server vaddr=0x7 size=0x1 parent=s0 p.vaddr=0x7
+[UTEST]  space=server vaddr=0x8 size=0x1 parent=s0 p.vaddr=0x8
+[UTEST]  space=server vaddr=0x9 size=0x1 parent=s0 p.vaddr=0x9
+[UTEST]  space=server vaddr=0xa size=0x1 parent=s0 p.vaddr=0xa
+[UTEST]  space=server vaddr=0xb size=0x1 parent=s0 p.vaddr=0xb
+[UTEST]  space=server vaddr=0xc size=0x1 parent=s0 p.vaddr=0xc
+[UTEST]  space=server vaddr=0xd size=0x1 parent=s0 p.vaddr=0xd
+[UTEST]  space=server vaddr=0xe size=0x1 parent=s0 p.vaddr=0xe
+[UTEST]  space=server vaddr=0xf size=0x1 parent=s0 p.vaddr=0xf
+[UTEST]  space=server vaddr=0x10 size=0x1 parent=s0 p.vaddr=0x10
+[UTEST]  space=server vaddr=0x11 size=0x1 parent=s0 p.vaddr=0x11
+[UTEST]  space=server vaddr=0x12 size=0x1 parent=s0 p.vaddr=0x12
+[UTEST]  space=server vaddr=0x13 size=0x1 parent=s0 p.vaddr=0x13
+[UTEST]  space=server vaddr=0x14 size=0x1 parent=s0 p.vaddr=0x14
+[UTEST]  space=server vaddr=0x15 size=0x1 parent=s0 p.vaddr=0x15
+[UTEST]  space=server vaddr=0x16 size=0x1 parent=s0 p.vaddr=0x16
+[UTEST]  space=server vaddr=0x17 size=0x1 parent=s0 p.vaddr=0x17
+[UTEST]  space=server vaddr=0x18 size=0x1 parent=s0 p.vaddr=0x18
+[UTEST]  space=server vaddr=0x19 size=0x1 parent=s0 p.vaddr=0x19
+[UTEST]  space=server vaddr=0x1a size=0x1 parent=s0 p.vaddr=0x1a
+[UTEST]  space=server vaddr=0x1b size=0x1 parent=s0 p.vaddr=0x1b
+[UTEST]  space=server vaddr=0x1c size=0x1 parent=s0 p.vaddr=0x1c
+[UTEST]  space=server vaddr=0x1d size=0x1 parent=s0 p.vaddr=0x1d
+[UTEST]  space=server vaddr=0x1e size=0x1 parent=s0 p.vaddr=0x1e
+[UTEST]  space=server vaddr=0x1f size=0x1 parent=s0 p.vaddr=0x1f
+[UTEST]  space=server vaddr=0x20 size=0x1 parent=s0 p.vaddr=0x20
+[UTEST]  space=server vaddr=0x21 size=0x1 parent=s0 p.vaddr=0x21
+[UTEST]  space=server vaddr=0x22 size=0x1 parent=s0 p.vaddr=0x22
+[UTEST]  space=server vaddr=0x23 size=0x1 parent=s0 p.vaddr=0x23
+[UTEST]  space=server vaddr=0x24 size=0x1 parent=s0 p.vaddr=0x24
+[UTEST]  space=server vaddr=0x25 size=0x1 parent=s0 p.vaddr=0x25
+[UTEST]  space=server vaddr=0x26 size=0x1 parent=s0 p.vaddr=0x26
+[UTEST]  space=server vaddr=0x27 size=0x1 parent=s0 p.vaddr=0x27
+[UTEST]  space=server vaddr=0x28 size=0x1 parent=s0 p.vaddr=0x28
+[UTEST]  space=server vaddr=0x29 size=0x1 parent=s0 p.vaddr=0x29
+[UTEST]  space=server vaddr=0x2a size=0x1 parent=s0 p.vaddr=0x2a
+[UTEST]  space=server vaddr=0x2b size=0x1 parent=s0 p.vaddr=0x2b
+[UTEST]  space=server vaddr=0x2c size=0x1 parent=s0 p.vaddr=0x2c
+[UTEST]  space=server vaddr=0x2d size=0x1 parent=s0 p.vaddr=0x2d
+[UTEST]  space=server vaddr=0x2e size=0x1 parent=s0 p.vaddr=0x2e
+[UTEST]  space=server vaddr=0x2f size=0x1 parent=s0 p.vaddr=0x2f
+[UTEST]  space=server vaddr=0x30 size=0x1 parent=s0 p.vaddr=0x30
+[UTEST]  space=server vaddr=0x31 size=0x1 parent=s0 p.vaddr=0x31
+[UTEST]  space=server vaddr=0x32 size=0x1 parent=s0 p.vaddr=0x32
+[UTEST]  space=server vaddr=0x33 size=0x1 parent=s0 p.vaddr=0x33
+[UTEST]  space=server vaddr=0x34 size=0x1 parent=s0 p.vaddr=0x34
+[UTEST]  space=server vaddr=0x35 size=0x1 parent=s0 p.vaddr=0x35
+[UTEST]  space=server vaddr=0x36 size=0x1 parent=s0 p.vaddr=0x36
+[UTEST]  space=server vaddr=0x37 size=0x1 parent=s0 p.vaddr=0x37
+[UTEST]  space=server vaddr=0x38 size=0x1 parent=s0 p.vaddr=0x38
+[UTEST]  space=server vaddr=0x39 size=0x1 parent=s0 p.vaddr=0x39
+[UTEST]  space=server vaddr=0x3a size=0x1 parent=s0 p.vaddr=0x3a
+[UTEST]  space=server vaddr=0x3b size=0x1 parent=s0 p.vaddr=0x3b
+[UTEST]  space=server vaddr=0x3c size=0x1 parent=s0 p.vaddr=0x3c
+[UTEST]  space=server vaddr=0x3d size=0x1 parent=s0 p.vaddr=0x3d
+[UTEST]  space=server vaddr=0x3e size=0x1 parent=s0 p.vaddr=0x3e
+[UTEST]  space=server vaddr=0x3f size=0x1 parent=s0 p.vaddr=0x3f
+[UTEST]  space=server vaddr=0x40 size=0x1 parent=s0 p.vaddr=0x40
+[UTEST]  space=server vaddr=0x41 size=0x1 parent=s0 p.vaddr=0x41
+[UTEST]  space=server vaddr=0x42 size=0x1 parent=s0 p.vaddr=0x42
+[UTEST]  space=server vaddr=0x43 size=0x1 parent=s0 p.vaddr=0x43
+[UTEST]  space=server vaddr=0x44 size=0x1 parent=s0 p.vaddr=0x44
+[UTEST]  space=server vaddr=0x45 size=0x1 parent=s0 p.vaddr=0x45
+[UTEST]  space=server vaddr=0x46 size=0x1 parent=s0 p.vaddr=0x46
+[UTEST]  space=server vaddr=0x47 size=0x1 parent=s0 p.vaddr=0x47
+[UTEST]  space=server vaddr=0x48 size=0x1 parent=s0 p.vaddr=0x48
+[UTEST]  space=server vaddr=0x49 size=0x1 parent=s0 p.vaddr=0x49
+[UTEST]  space=server vaddr=0x4a size=0x1 parent=s0 p.vaddr=0x4a
+[UTEST]  space=server vaddr=0x4b size=0x1 parent=s0 p.vaddr=0x4b
+[UTEST]  space=server vaddr=0x4c size=0x1 parent=s0 p.vaddr=0x4c
+[UTEST]  space=server vaddr=0x4d size=0x1 parent=s0 p.vaddr=0x4d
+[UTEST]  space=server vaddr=0x4e size=0x1 parent=s0 p.vaddr=0x4e
+[UTEST]  space=server vaddr=0x4f size=0x1 parent=s0 p.vaddr=0x4f
+[UTEST]  space=server vaddr=0x50 size=0x1 parent=s0 p.vaddr=0x50
+[UTEST]  space=server vaddr=0x51 size=0x1 parent=s0 p.vaddr=0x51
+[UTEST]  space=server vaddr=0x52 size=0x1 parent=s0 p.vaddr=0x52
+[UTEST]  space=server vaddr=0x53 size=0x1 parent=s0 p.vaddr=0x53
+[UTEST]  space=server vaddr=0x54 size=0x1 parent=s0 p.vaddr=0x54
+[UTEST]  space=server vaddr=0x55 size=0x1 parent=s0 p.vaddr=0x55
+[UTEST]  space=server vaddr=0x56 size=0x1 parent=s0 p.vaddr=0x56
+[UTEST]  space=server vaddr=0x57 size=0x1 parent=s0 p.vaddr=0x57
+[UTEST]  space=server vaddr=0x58 size=0x1 parent=s0 p.vaddr=0x58
+[UTEST]  space=server vaddr=0x59 size=0x1 parent=s0 p.vaddr=0x59
+[UTEST]  space=server vaddr=0x5a size=0x1 parent=s0 p.vaddr=0x5a
+[UTEST]  space=server vaddr=0x5b size=0x1 parent=s0 p.vaddr=0x5b
+[UTEST]  space=server vaddr=0x5c size=0x1 parent=s0 p.vaddr=0x5c
+[UTEST]  space=server vaddr=0x5d size=0x1 parent=s0 p.vaddr=0x5d
+[UTEST]  space=server vaddr=0x5e size=0x1 parent=s0 p.vaddr=0x5e
+[UTEST]  space=server vaddr=0x5f size=0x1 parent=s0 p.vaddr=0x5f
+[UTEST]  space=server vaddr=0x60 size=0x1 parent=s0 p.vaddr=0x60
+[UTEST]  space=server vaddr=0x61 size=0x1 parent=s0 p.vaddr=0x61
+[UTEST]  space=server vaddr=0x62 size=0x1 parent=s0 p.vaddr=0x62
+[UTEST]  space=server vaddr=0x63 size=0x1 parent=s0 p.vaddr=0x63
+[UTEST]  space=server vaddr=0x64 size=0x1 parent=s0 p.vaddr=0x64
+[UTEST]  space=server vaddr=0x65 size=0x1 parent=s0 p.vaddr=0x65
+[UTEST]  space=server vaddr=0x66 size=0x1 parent=s0 p.vaddr=0x66
+[UTEST]  space=server vaddr=0x67 size=0x1 parent=s0 p.vaddr=0x67
+[UTEST]  space=server vaddr=0x68 size=0x1 parent=s0 p.vaddr=0x68
+[UTEST]  space=server vaddr=0x69 size=0x1 parent=s0 p.vaddr=0x69
+[UTEST]  space=server vaddr=0x6a size=0x1 parent=s0 p.vaddr=0x6a
+[UTEST]  space=server vaddr=0x6b size=0x1 parent=s0 p.vaddr=0x6b
+[UTEST]  space=server vaddr=0x6c size=0x1 parent=s0 p.vaddr=0x6c
+[UTEST]  space=server vaddr=0x6d size=0x1 parent=s0 p.vaddr=0x6d
+[UTEST]  space=server vaddr=0x6e size=0x1 parent=s0 p.vaddr=0x6e
+[UTEST]  space=server vaddr=0x6f size=0x1 parent=s0 p.vaddr=0x6f
+[UTEST]  space=server vaddr=0x70 size=0x1 parent=s0 p.vaddr=0x70
+[UTEST]  space=server vaddr=0x71 size=0x1 parent=s0 p.vaddr=0x71
+[UTEST]  space=server vaddr=0x72 size=0x1 parent=s0 p.vaddr=0x72
+[UTEST]  space=server vaddr=0x73 size=0x1 parent=s0 p.vaddr=0x73
+[UTEST]  space=server vaddr=0x74 size=0x1 parent=s0 p.vaddr=0x74
+[UTEST]  space=server vaddr=0x75 size=0x1 parent=s0 p.vaddr=0x75
+[UTEST]  space=server vaddr=0x76 size=0x1 parent=s0 p.vaddr=0x76
+[UTEST]  space=server vaddr=0x77 size=0x1 parent=s0 p.vaddr=0x77
+[UTEST]  space=server vaddr=0x78 size=0x1 parent=s0 p.vaddr=0x78
+[UTEST]  space=server vaddr=0x79 size=0x1 parent=s0 p.vaddr=0x79
+[UTEST]  space=server vaddr=0x7a size=0x1 parent=s0 p.vaddr=0x7a
+[UTEST]  space=server vaddr=0x7b size=0x1 parent=s0 p.vaddr=0x7b
+[UTEST]  space=server vaddr=0x7c size=0x1 parent=s0 p.vaddr=0x7c
+[UTEST]  space=server vaddr=0x7d size=0x1 parent=s0 p.vaddr=0x7d
+[UTEST]  space=server vaddr=0x7e size=0x1 parent=s0 p.vaddr=0x7e
+[UTEST]  space=server vaddr=0x7f size=0x1 parent=s0 p.vaddr=0x7f
+[UTEST]  space=server vaddr=0x80 size=0x1 parent=s0 p.vaddr=0x80
+[UTEST]  space=server vaddr=0x81 size=0x1 parent=s0 p.vaddr=0x81
+[UTEST]  space=server vaddr=0x82 size=0x1 parent=s0 p.vaddr=0x82
+[UTEST]  space=server vaddr=0x83 size=0x1 parent=s0 p.vaddr=0x83
+[UTEST]  space=server vaddr=0x84 size=0x1 parent=s0 p.vaddr=0x84
+[UTEST]  space=server vaddr=0x85 size=0x1 parent=s0 p.vaddr=0x85
+[UTEST]  space=server vaddr=0x86 size=0x1 parent=s0 p.vaddr=0x86
+[UTEST]  space=server vaddr=0x87 size=0x1 parent=s0 p.vaddr=0x87
+[UTEST]  space=server vaddr=0x88 size=0x1 parent=s0 p.vaddr=0x88
+[UTEST]  space=server vaddr=0x89 size=0x1 parent=s0 p.vaddr=0x89
+[UTEST]  space=server vaddr=0x8a size=0x1 parent=s0 p.vaddr=0x8a
+[UTEST]  space=server vaddr=0x8b size=0x1 parent=s0 p.vaddr=0x8b
+[UTEST]  space=server vaddr=0x8c size=0x1 parent=s0 p.vaddr=0x8c
+[UTEST]  space=server vaddr=0x8d size=0x1 parent=s0 p.vaddr=0x8d
+[UTEST]  space=server vaddr=0x8e size=0x1 parent=s0 p.vaddr=0x8e
+[UTEST]  space=server vaddr=0x8f size=0x1 parent=s0 p.vaddr=0x8f
+[UTEST]  space=server vaddr=0x90 size=0x1 parent=s0 p.vaddr=0x90
+[UTEST]  space=server vaddr=0x91 size=0x1 parent=s0 p.vaddr=0x91
+[UTEST]  space=server vaddr=0x92 size=0x1 parent=s0 p.vaddr=0x92
+[UTEST]  space=server vaddr=0x93 size=0x1 parent=s0 p.vaddr=0x93
+[UTEST]  space=server vaddr=0x94 size=0x1 parent=s0 p.vaddr=0x94
+[UTEST]  space=server vaddr=0x95 size=0x1 parent=s0 p.vaddr=0x95
+[UTEST]  space=server vaddr=0x96 size=0x1 parent=s0 p.vaddr=0x96
+[UTEST]  space=server vaddr=0x97 size=0x1 parent=s0 p.vaddr=0x97
+[UTEST]  space=server vaddr=0x98 size=0x1 parent=s0 p.vaddr=0x98
+[UTEST]  space=server vaddr=0x99 size=0x1 parent=s0 p.vaddr=0x99
+[UTEST]  space=server vaddr=0x9a size=0x1 parent=s0 p.vaddr=0x9a
+[UTEST]  space=server vaddr=0x9b size=0x1 parent=s0 p.vaddr=0x9b
+[UTEST]  space=server vaddr=0x9c size=0x1 parent=s0 p.vaddr=0x9c
+[UTEST]  space=server vaddr=0x9d size=0x1 parent=s0 p.vaddr=0x9d
+[UTEST]  space=server vaddr=0x9e size=0x1 parent=s0 p.vaddr=0x9e
+[UTEST]  space=server vaddr=0x9f size=0x1 parent=s0 p.vaddr=0x9f
+[UTEST]  space=server vaddr=0xa0 size=0x1 parent=s0 p.vaddr=0xa0
+[UTEST]  space=server vaddr=0xa1 size=0x1 parent=s0 p.vaddr=0xa1
+[UTEST]  space=server vaddr=0xa2 size=0x1 parent=s0 p.vaddr=0xa2
+[UTEST]  space=server vaddr=0xa3 size=0x1 parent=s0 p.vaddr=0xa3
+[UTEST]  space=server vaddr=0xa4 size=0x1 parent=s0 p.vaddr=0xa4
+[UTEST]  space=server vaddr=0xa5 size=0x1 parent=s0 p.vaddr=0xa5
+[UTEST]  space=server vaddr=0xa6 size=0x1 parent=s0 p.vaddr=0xa6
+[UTEST]  space=server vaddr=0xa7 size=0x1 parent=s0 p.vaddr=0xa7
+[UTEST]  space=server vaddr=0xa8 size=0x1 parent=s0 p.vaddr=0xa8
+[UTEST]  space=server vaddr=0xa9 size=0x1 parent=s0 p.vaddr=0xa9
+[UTEST]  space=server vaddr=0xaa size=0x1 parent=s0 p.vaddr=0xaa
+[UTEST]  space=server vaddr=0xab size=0x1 parent=s0 p.vaddr=0xab
+[UTEST]  space=server vaddr=0xac size=0x1 parent=s0 p.vaddr=0xac
+[UTEST]  space=server vaddr=0xad size=0x1 parent=s0 p.vaddr=0xad
+[UTEST]  space=server vaddr=0xae size=0x1 parent=s0 p.vaddr=0xae
+[UTEST]  space=server vaddr=0xaf size=0x1 parent=s0 p.vaddr=0xaf
+[UTEST]  space=server vaddr=0xb0 size=0x1 parent=s0 p.vaddr=0xb0
+[UTEST]  space=server vaddr=0xb1 size=0x1 parent=s0 p.vaddr=0xb1
+[UTEST]  space=server vaddr=0xb2 size=0x1 parent=s0 p.vaddr=0xb2
+[UTEST]  space=server vaddr=0xb3 size=0x1 parent=s0 p.vaddr=0xb3
+[UTEST]  space=server vaddr=0xb4 size=0x1 parent=s0 p.vaddr=0xb4
+[UTEST]  space=server vaddr=0xb5 size=0x1 parent=s0 p.vaddr=0xb5
+[UTEST]  space=server vaddr=0xb6 size=0x1 parent=s0 p.vaddr=0xb6
+[UTEST]  space=server vaddr=0xb7 size=0x1 parent=s0 p.vaddr=0xb7
+[UTEST]  space=server vaddr=0xb8 size=0x1 parent=s0 p.vaddr=0xb8
+[UTEST]  space=server vaddr=0xb9 size=0x1 parent=s0 p.vaddr=0xb9
+[UTEST]  space=server vaddr=0xba size=0x1 parent=s0 p.vaddr=0xba
+[UTEST]  space=server vaddr=0xbb size=0x1 parent=s0 p.vaddr=0xbb
+[UTEST]  space=server vaddr=0xbc size=0x1 parent=s0 p.vaddr=0xbc
+[UTEST]  space=server vaddr=0xbd size=0x1 parent=s0 p.vaddr=0xbd
+[UTEST]  space=server vaddr=0xbe size=0x1 parent=s0 p.vaddr=0xbe
+[UTEST]  space=server vaddr=0xbf size=0x1 parent=s0 p.vaddr=0xbf
+[UTEST]  space=server vaddr=0xc0 size=0x1 parent=s0 p.vaddr=0xc0
+[UTEST]  space=server vaddr=0xc1 size=0x1 parent=s0 p.vaddr=0xc1
+[UTEST]  space=server vaddr=0xc2 size=0x1 parent=s0 p.vaddr=0xc2
+[UTEST]  space=server vaddr=0xc3 size=0x1 parent=s0 p.vaddr=0xc3
+[UTEST]  space=server vaddr=0xc4 size=0x1 parent=s0 p.vaddr=0xc4
+[UTEST]  space=server vaddr=0xc5 size=0x1 parent=s0 p.vaddr=0xc5
+[UTEST]  space=server vaddr=0xc6 size=0x1 parent=s0 p.vaddr=0xc6
+[UTEST]  space=server vaddr=0xc7 size=0x1 parent=s0 p.vaddr=0xc7
+[UTEST]  space=server vaddr=0xc8 size=0x1 parent=s0 p.vaddr=0xc8
+[UTEST]  space=server vaddr=0xc9 size=0x1 parent=s0 p.vaddr=0xc9
+[UTEST]  space=server vaddr=0xca size=0x1 parent=s0 p.vaddr=0xca
+[UTEST]  space=server vaddr=0xcb size=0x1 parent=s0 p.vaddr=0xcb
+[UTEST]  space=server vaddr=0xcc size=0x1 parent=s0 p.vaddr=0xcc
+[UTEST]  space=server vaddr=0xcd size=0x1 parent=s0 p.vaddr=0xcd
+[UTEST]  space=server vaddr=0xce size=0x1 parent=s0 p.vaddr=0xce
+[UTEST]  space=server vaddr=0xcf size=0x1 parent=s0 p.vaddr=0xcf
+[UTEST]  space=server vaddr=0xd0 size=0x1 parent=s0 p.vaddr=0xd0
+[UTEST]  space=server vaddr=0xd1 size=0x1 parent=s0 p.vaddr=0xd1
+[UTEST]  space=server vaddr=0xd2 size=0x1 parent=s0 p.vaddr=0xd2
+[UTEST]  space=server vaddr=0xd3 size=0x1 parent=s0 p.vaddr=0xd3
+[UTEST]  space=server vaddr=0xd4 size=0x1 parent=s0 p.vaddr=0xd4
+[UTEST]  space=server vaddr=0xd5 size=0x1 parent=s0 p.vaddr=0xd5
+[UTEST]  space=server vaddr=0xd6 size=0x1 parent=s0 p.vaddr=0xd6
+[UTEST]  space=server vaddr=0xd7 size=0x1 parent=s0 p.vaddr=0xd7
+[UTEST]  space=server vaddr=0xd8 size=0x1 parent=s0 p.vaddr=0xd8
+[UTEST]  space=server vaddr=0xd9 size=0x1 parent=s0 p.vaddr=0xd9
+[UTEST]  space=server vaddr=0xda size=0x1 parent=s0 p.vaddr=0xda
+[UTEST]  space=server vaddr=0xdb size=0x1 parent=s0 p.vaddr=0xdb
+[UTEST]  space=server vaddr=0xdc size=0x1 parent=s0 p.vaddr=0xdc
+[UTEST]  space=server vaddr=0xdd size=0x1 parent=s0 p.vaddr=0xdd
+[UTEST]  space=server vaddr=0xde size=0x1 parent=s0 p.vaddr=0xde
+[UTEST]  space=server vaddr=0xdf size=0x1 parent=s0 p.vaddr=0xdf
+[UTEST]  space=server vaddr=0xe0 size=0x1 parent=s0 p.vaddr=0xe0
+[UTEST]  space=server vaddr=0xe1 size=0x1 parent=s0 p.vaddr=0xe1
+[UTEST]  space=server vaddr=0xe2 size=0x1 parent=s0 p.vaddr=0xe2
+[UTEST]  space=server vaddr=0xe3 size=0x1 parent=s0 p.vaddr=0xe3
+[UTEST]  space=server vaddr=0xe4 size=0x1 parent=s0 p.vaddr=0xe4
+[UTEST]  space=server vaddr=0xe5 size=0x1 parent=s0 p.vaddr=0xe5
+[UTEST]  space=server vaddr=0xe6 size=0x1 parent=s0 p.vaddr=0xe6
+[UTEST]  space=server vaddr=0xe7 size=0x1 parent=s0 p.vaddr=0xe7
+[UTEST]  space=server vaddr=0xe8 size=0x1 parent=s0 p.vaddr=0xe8
+[UTEST]  space=server vaddr=0xe9 size=0x1 parent=s0 p.vaddr=0xe9
+[UTEST]  space=server vaddr=0xea size=0x1 parent=s0 p.vaddr=0xea
+[UTEST]  space=server vaddr=0xeb size=0x1 parent=s0 p.vaddr=0xeb
+[UTEST]  space=server vaddr=0xec size=0x1 parent=s0 p.vaddr=0xec
+[UTEST]  space=server vaddr=0xed size=0x1 parent=s0 p.vaddr=0xed
+[UTEST]  space=server vaddr=0xee size=0x1 parent=s0 p.vaddr=0xee
+[UTEST]  space=server vaddr=0xef size=0x1 parent=s0 p.vaddr=0xef
+[UTEST]  space=server vaddr=0xf0 size=0x1 parent=s0 p.vaddr=0xf0
+[UTEST]  space=server vaddr=0xf1 size=0x1 parent=s0 p.vaddr=0xf1
+[UTEST]  space=server vaddr=0xf2 size=0x1 parent=s0 p.vaddr=0xf2
+[UTEST]  space=server vaddr=0xf3 size=0x1 parent=s0 p.vaddr=0xf3
+[UTEST]  space=server vaddr=0xf4 size=0x1 parent=s0 p.vaddr=0xf4
+[UTEST]  space=server vaddr=0xf5 size=0x1 parent=s0 p.vaddr=0xf5
+[UTEST]  space=server vaddr=0xf6 size=0x1 parent=s0 p.vaddr=0xf6
+[UTEST]  space=server vaddr=0xf7 size=0x1 parent=s0 p.vaddr=0xf7
+[UTEST]  space=server vaddr=0xf8 size=0x1 parent=s0 p.vaddr=0xf8
+[UTEST]  space=server vaddr=0xf9 size=0x1 parent=s0 p.vaddr=0xf9
+[UTEST]  space=server vaddr=0xfa size=0x1 parent=s0 p.vaddr=0xfa
+[UTEST]  space=server vaddr=0xfb size=0x1 parent=s0 p.vaddr=0xfb
+[UTEST]  space=server vaddr=0xfc size=0x1 parent=s0 p.vaddr=0xfc
+[UTEST]  space=server vaddr=0xfd size=0x1 parent=s0 p.vaddr=0xfd
+[UTEST]  space=server vaddr=0xfe size=0x1 parent=s0 p.vaddr=0xfe
+[UTEST]  space=server vaddr=0xff size=0x1 parent=s0 p.vaddr=0xff
+[UTEST]  space=server vaddr=0x200 size=0x1 parent=s0 p.vaddr=0x200
+[UTEST]  space=server vaddr=0x201 size=0x1 parent=s0 p.vaddr=0x201
+[UTEST]  space=server vaddr=0x202 size=0x1 parent=s0 p.vaddr=0x202
+[UTEST]  space=server vaddr=0x203 size=0x1 parent=s0 p.vaddr=0x203
+[UTEST]  space=server vaddr=0x204 size=0x1 parent=s0 p.vaddr=0x204
+[UTEST]  space=server vaddr=0x205 size=0x1 parent=s0 p.vaddr=0x205
+[UTEST]  space=server vaddr=0x206 size=0x1 parent=s0 p.vaddr=0x206
+[UTEST]  space=server vaddr=0x207 size=0x1 parent=s0 p.vaddr=0x207
+[UTEST]  space=server vaddr=0x208 size=0x1 parent=s0 p.vaddr=0x208
+[UTEST]  space=server vaddr=0x209 size=0x1 parent=s0 p.vaddr=0x209
+[UTEST]  space=server vaddr=0x20a size=0x1 parent=s0 p.vaddr=0x20a
+[UTEST]  space=server vaddr=0x20b size=0x1 parent=s0 p.vaddr=0x20b
+[UTEST]  space=server vaddr=0x20c size=0x1 parent=s0 p.vaddr=0x20c
+[UTEST]  space=server vaddr=0x20d size=0x1 parent=s0 p.vaddr=0x20d
+[UTEST]  space=server vaddr=0x20e size=0x1 parent=s0 p.vaddr=0x20e
+[UTEST]  space=server vaddr=0x20f size=0x1 parent=s0 p.vaddr=0x20f
+[UTEST]  space=server vaddr=0x210 size=0x1 parent=s0 p.vaddr=0x210
+[UTEST]  space=server vaddr=0x211 size=0x1 parent=s0 p.vaddr=0x211
+[UTEST]  space=server vaddr=0x212 size=0x1 parent=s0 p.vaddr=0x212
+[UTEST]  space=server vaddr=0x213 size=0x1 parent=s0 p.vaddr=0x213
+[UTEST]  space=server vaddr=0x214 size=0x1 parent=s0 p.vaddr=0x214
+[UTEST]  space=server vaddr=0x215 size=0x1 parent=s0 p.vaddr=0x215
+[UTEST]  space=server vaddr=0x216 size=0x1 parent=s0 p.vaddr=0x216
+[UTEST]  space=server vaddr=0x217 size=0x1 parent=s0 p.vaddr=0x217
+[UTEST]  space=server vaddr=0x218 size=0x1 parent=s0 p.vaddr=0x218
+[UTEST]  space=server vaddr=0x219 size=0x1 parent=s0 p.vaddr=0x219
+[UTEST]  space=server vaddr=0x21a size=0x1 parent=s0 p.vaddr=0x21a
+[UTEST]  space=server vaddr=0x21b size=0x1 parent=s0 p.vaddr=0x21b
+[UTEST]  space=server vaddr=0x21c size=0x1 parent=s0 p.vaddr=0x21c
+[UTEST]  space=server vaddr=0x21d size=0x1 parent=s0 p.vaddr=0x21d
+[UTEST]  space=server vaddr=0x21e size=0x1 parent=s0 p.vaddr=0x21e
+[UTEST]  space=server vaddr=0x21f size=0x1 parent=s0 p.vaddr=0x21f
+[UTEST]  space=server vaddr=0x220 size=0x1 parent=s0 p.vaddr=0x220
+[UTEST]  space=server vaddr=0x221 size=0x1 parent=s0 p.vaddr=0x221
+[UTEST]  space=server vaddr=0x222 size=0x1 parent=s0 p.vaddr=0x222
+[UTEST]  space=server vaddr=0x223 size=0x1 parent=s0 p.vaddr=0x223
+[UTEST]  space=server vaddr=0x224 size=0x1 parent=s0 p.vaddr=0x224
+[UTEST]  space=server vaddr=0x225 size=0x1 parent=s0 p.vaddr=0x225
+[UTEST]  space=server vaddr=0x226 size=0x1 parent=s0 p.vaddr=0x226
+[UTEST]  space=server vaddr=0x227 size=0x1 parent=s0 p.vaddr=0x227
+[UTEST]  space=server vaddr=0x228 size=0x1 parent=s0 p.vaddr=0x228
+[UTEST]  space=server vaddr=0x229 size=0x1 parent=s0 p.vaddr=0x229
+[UTEST]  space=server vaddr=0x22a size=0x1 parent=s0 p.vaddr=0x22a
+[UTEST]  space=server vaddr=0x22b size=0x1 parent=s0 p.vaddr=0x22b
+[UTEST]  space=server vaddr=0x22c size=0x1 parent=s0 p.vaddr=0x22c
+[UTEST]  space=server vaddr=0x22d size=0x1 parent=s0 p.vaddr=0x22d
+[UTEST]  space=server vaddr=0x22e size=0x1 parent=s0 p.vaddr=0x22e
+[UTEST]  space=server vaddr=0x22f size=0x1 parent=s0 p.vaddr=0x22f
+[UTEST]  space=server vaddr=0x230 size=0x1 parent=s0 p.vaddr=0x230
+[UTEST]  space=server vaddr=0x231 size=0x1 parent=s0 p.vaddr=0x231
+[UTEST]  space=server vaddr=0x232 size=0x1 parent=s0 p.vaddr=0x232
+[UTEST]  space=server vaddr=0x233 size=0x1 parent=s0 p.vaddr=0x233
+[UTEST]  space=server vaddr=0x234 size=0x1 parent=s0 p.vaddr=0x234
+[UTEST]  space=server vaddr=0x235 size=0x1 parent=s0 p.vaddr=0x235
+[UTEST]  space=server vaddr=0x236 size=0x1 parent=s0 p.vaddr=0x236
+[UTEST]  space=server vaddr=0x237 size=0x1 parent=s0 p.vaddr=0x237
+[UTEST]  space=server vaddr=0x238 size=0x1 parent=s0 p.vaddr=0x238
+[UTEST]  space=server vaddr=0x239 size=0x1 parent=s0 p.vaddr=0x239
+[UTEST]  space=server vaddr=0x23a size=0x1 parent=s0 p.vaddr=0x23a
+[UTEST]  space=server vaddr=0x23b size=0x1 parent=s0 p.vaddr=0x23b
+[UTEST]  space=server vaddr=0x23c size=0x1 parent=s0 p.vaddr=0x23c
+[UTEST]  space=server vaddr=0x23d size=0x1 parent=s0 p.vaddr=0x23d
+[UTEST]  space=server vaddr=0x23e size=0x1 parent=s0 p.vaddr=0x23e
+[UTEST]  space=server vaddr=0x23f size=0x1 parent=s0 p.vaddr=0x23f
+[UTEST]  space=server vaddr=0x240 size=0x1 parent=s0 p.vaddr=0x240
+[UTEST]  space=server vaddr=0x241 size=0x1 parent=s0 p.vaddr=0x241
+[UTEST]  space=server vaddr=0x242 size=0x1 parent=s0 p.vaddr=0x242
+[UTEST]  space=server vaddr=0x243 size=0x1 parent=s0 p.vaddr=0x243
+[UTEST]  space=server vaddr=0x244 size=0x1 parent=s0 p.vaddr=0x244
+[UTEST]  space=server vaddr=0x245 size=0x1 parent=s0 p.vaddr=0x245
+[UTEST]  space=server vaddr=0x246 size=0x1 parent=s0 p.vaddr=0x246
+[UTEST]  space=server vaddr=0x247 size=0x1 parent=s0 p.vaddr=0x247
+[UTEST]  space=server vaddr=0x248 size=0x1 parent=s0 p.vaddr=0x248
+[UTEST]  space=server vaddr=0x249 size=0x1 parent=s0 p.vaddr=0x249
+[UTEST]  space=server vaddr=0x24a size=0x1 parent=s0 p.vaddr=0x24a
+[UTEST]  space=server vaddr=0x24b size=0x1 parent=s0 p.vaddr=0x24b
+[UTEST]  space=server vaddr=0x24c size=0x1 parent=s0 p.vaddr=0x24c
+[UTEST]  space=server vaddr=0x24d size=0x1 parent=s0 p.vaddr=0x24d
+[UTEST]  space=server vaddr=0x24e size=0x1 parent=s0 p.vaddr=0x24e
+[UTEST]  space=server vaddr=0x24f size=0x1 parent=s0 p.vaddr=0x24f
+[UTEST]  space=server vaddr=0x250 size=0x1 parent=s0 p.vaddr=0x250
+[UTEST]  space=server vaddr=0x251 size=0x1 parent=s0 p.vaddr=0x251
+[UTEST]  space=server vaddr=0x252 size=0x1 parent=s0 p.vaddr=0x252
+[UTEST]  space=server vaddr=0x253 size=0x1 parent=s0 p.vaddr=0x253
+[UTEST]  space=server vaddr=0x254 size=0x1 parent=s0 p.vaddr=0x254
+[UTEST]  space=server vaddr=0x255 size=0x1 parent=s0 p.vaddr=0x255
+[UTEST]  space=server vaddr=0x256 size=0x1 parent=s0 p.vaddr=0x256
+[UTEST]  space=server vaddr=0x257 size=0x1 parent=s0 p.vaddr=0x257
+[UTEST]  space=server vaddr=0x258 size=0x1 parent=s0 p.vaddr=0x258
+[UTEST]  space=server vaddr=0x259 size=0x1 parent=s0 p.vaddr=0x259
+[UTEST]  space=server vaddr=0x25a size=0x1 parent=s0 p.vaddr=0x25a
+[UTEST]  space=server vaddr=0x25b size=0x1 parent=s0 p.vaddr=0x25b
+[UTEST]  space=server vaddr=0x25c size=0x1 parent=s0 p.vaddr=0x25c
+[UTEST]  space=server vaddr=0x25d size=0x1 parent=s0 p.vaddr=0x25d
+[UTEST]  space=server vaddr=0x25e size=0x1 parent=s0 p.vaddr=0x25e
+[UTEST]  space=server vaddr=0x25f size=0x1 parent=s0 p.vaddr=0x25f
+[UTEST]  space=server vaddr=0x260 size=0x1 parent=s0 p.vaddr=0x260
+[UTEST]  space=server vaddr=0x261 size=0x1 parent=s0 p.vaddr=0x261
+[UTEST]  space=server vaddr=0x262 size=0x1 parent=s0 p.vaddr=0x262
+[UTEST]  space=server vaddr=0x263 size=0x1 parent=s0 p.vaddr=0x263
+[UTEST]  space=server vaddr=0x264 size=0x1 parent=s0 p.vaddr=0x264
+[UTEST]  space=server vaddr=0x265 size=0x1 parent=s0 p.vaddr=0x265
+[UTEST]  space=server vaddr=0x266 size=0x1 parent=s0 p.vaddr=0x266
+[UTEST]  space=server vaddr=0x267 size=0x1 parent=s0 p.vaddr=0x267
+[UTEST]  space=server vaddr=0x268 size=0x1 parent=s0 p.vaddr=0x268
+[UTEST]  space=server vaddr=0x269 size=0x1 parent=s0 p.vaddr=0x269
+[UTEST]  space=server vaddr=0x26a size=0x1 parent=s0 p.vaddr=0x26a
+[UTEST]  space=server vaddr=0x26b size=0x1 parent=s0 p.vaddr=0x26b
+[UTEST]  space=server vaddr=0x26c size=0x1 parent=s0 p.vaddr=0x26c
+[UTEST]  space=server vaddr=0x26d size=0x1 parent=s0 p.vaddr=0x26d
+[UTEST]  space=server vaddr=0x26e size=0x1 parent=s0 p.vaddr=0x26e
+[UTEST]  space=server vaddr=0x26f size=0x1 parent=s0 p.vaddr=0x26f
+[UTEST]  space=server vaddr=0x270 size=0x1 parent=s0 p.vaddr=0x270
+[UTEST]  space=server vaddr=0x271 size=0x1 parent=s0 p.vaddr=0x271
+[UTEST]  space=server vaddr=0x272 size=0x1 parent=s0 p.vaddr=0x272
+[UTEST]  space=server vaddr=0x273 size=0x1 parent=s0 p.vaddr=0x273
+[UTEST]  space=server vaddr=0x274 size=0x1 parent=s0 p.vaddr=0x274
+[UTEST]  space=server vaddr=0x275 size=0x1 parent=s0 p.vaddr=0x275
+[UTEST]  space=server vaddr=0x276 size=0x1 parent=s0 p.vaddr=0x276
+[UTEST]  space=server vaddr=0x277 size=0x1 parent=s0 p.vaddr=0x277
+[UTEST]  space=server vaddr=0x278 size=0x1 parent=s0 p.vaddr=0x278
+[UTEST]  space=server vaddr=0x279 size=0x1 parent=s0 p.vaddr=0x279
+[UTEST]  space=server vaddr=0x27a size=0x1 parent=s0 p.vaddr=0x27a
+[UTEST]  space=server vaddr=0x27b size=0x1 parent=s0 p.vaddr=0x27b
+[UTEST]  space=server vaddr=0x27c size=0x1 parent=s0 p.vaddr=0x27c
+[UTEST]  space=server vaddr=0x27d size=0x1 parent=s0 p.vaddr=0x27d
+[UTEST]  space=server vaddr=0x27e size=0x1 parent=s0 p.vaddr=0x27e
+[UTEST]  space=server vaddr=0x27f size=0x1 parent=s0 p.vaddr=0x27f
+[UTEST]  space=server vaddr=0x280 size=0x1 parent=s0 p.vaddr=0x280
+[UTEST]  space=server vaddr=0x281 size=0x1 parent=s0 p.vaddr=0x281
+[UTEST]  space=server vaddr=0x282 size=0x1 parent=s0 p.vaddr=0x282
+[UTEST]  space=server vaddr=0x283 size=0x1 parent=s0 p.vaddr=0x283
+[UTEST]  space=server vaddr=0x284 size=0x1 parent=s0 p.vaddr=0x284
+[UTEST]  space=server vaddr=0x285 size=0x1 parent=s0 p.vaddr=0x285
+[UTEST]  space=server vaddr=0x286 size=0x1 parent=s0 p.vaddr=0x286
+[UTEST]  space=server vaddr=0x287 size=0x1 parent=s0 p.vaddr=0x287
+[UTEST]  space=server vaddr=0x288 size=0x1 parent=s0 p.vaddr=0x288
+[UTEST]  space=server vaddr=0x289 size=0x1 parent=s0 p.vaddr=0x289
+[UTEST]  space=server vaddr=0x28a size=0x1 parent=s0 p.vaddr=0x28a
+[UTEST]  space=server vaddr=0x28b size=0x1 parent=s0 p.vaddr=0x28b
+[UTEST]  space=server vaddr=0x28c size=0x1 parent=s0 p.vaddr=0x28c
+[UTEST]  space=server vaddr=0x28d size=0x1 parent=s0 p.vaddr=0x28d
+[UTEST]  space=server vaddr=0x28e size=0x1 parent=s0 p.vaddr=0x28e
+[UTEST]  space=server vaddr=0x28f size=0x1 parent=s0 p.vaddr=0x28f
+[UTEST]  space=server vaddr=0x290 size=0x1 parent=s0 p.vaddr=0x290
+[UTEST]  space=server vaddr=0x291 size=0x1 parent=s0 p.vaddr=0x291
+[UTEST]  space=server vaddr=0x292 size=0x1 parent=s0 p.vaddr=0x292
+[UTEST]  space=server vaddr=0x293 size=0x1 parent=s0 p.vaddr=0x293
+[UTEST]  space=server vaddr=0x294 size=0x1 parent=s0 p.vaddr=0x294
+[UTEST]  space=server vaddr=0x295 size=0x1 parent=s0 p.vaddr=0x295
+[UTEST]  space=server vaddr=0x296 size=0x1 parent=s0 p.vaddr=0x296
+[UTEST]  space=server vaddr=0x297 size=0x1 parent=s0 p.vaddr=0x297
+[UTEST]  space=server vaddr=0x298 size=0x1 parent=s0 p.vaddr=0x298
+[UTEST]  space=server vaddr=0x299 size=0x1 parent=s0 p.vaddr=0x299
+[UTEST]  space=server vaddr=0x29a size=0x1 parent=s0 p.vaddr=0x29a
+[UTEST]  space=server vaddr=0x29b size=0x1 parent=s0 p.vaddr=0x29b
+[UTEST]  space=server vaddr=0x29c size=0x1 parent=s0 p.vaddr=0x29c
+[UTEST]  space=server vaddr=0x29d size=0x1 parent=s0 p.vaddr=0x29d
+[UTEST]  space=server vaddr=0x29e size=0x1 parent=s0 p.vaddr=0x29e
+[UTEST]  space=server vaddr=0x29f size=0x1 parent=s0 p.vaddr=0x29f
+[UTEST]  space=server vaddr=0x2a0 size=0x1 parent=s0 p.vaddr=0x2a0
+[UTEST]  space=server vaddr=0x2a1 size=0x1 parent=s0 p.vaddr=0x2a1
+[UTEST]  space=server vaddr=0x2a2 size=0x1 parent=s0 p.vaddr=0x2a2
+[UTEST]  space=server vaddr=0x2a3 size=0x1 parent=s0 p.vaddr=0x2a3
+[UTEST]  space=server vaddr=0x2a4 size=0x1 parent=s0 p.vaddr=0x2a4
+[UTEST]  space=server vaddr=0x2a5 size=0x1 parent=s0 p.vaddr=0x2a5
+[UTEST]  space=server vaddr=0x2a6 size=0x1 parent=s0 p.vaddr=0x2a6
+[UTEST]  space=server vaddr=0x2a7 size=0x1 parent=s0 p.vaddr=0x2a7
+[UTEST]  space=server vaddr=0x2a8 size=0x1 parent=s0 p.vaddr=0x2a8
+[UTEST]  space=server vaddr=0x2a9 size=0x1 parent=s0 p.vaddr=0x2a9
+[UTEST]  space=server vaddr=0x2aa size=0x1 parent=s0 p.vaddr=0x2aa
+[UTEST]  space=server vaddr=0x2ab size=0x1 parent=s0 p.vaddr=0x2ab
+[UTEST]  space=server vaddr=0x2ac size=0x1 parent=s0 p.vaddr=0x2ac
+[UTEST]  space=server vaddr=0x2ad size=0x1 parent=s0 p.vaddr=0x2ad
+[UTEST]  space=server vaddr=0x2ae size=0x1 parent=s0 p.vaddr=0x2ae
+[UTEST]  space=server vaddr=0x2af size=0x1 parent=s0 p.vaddr=0x2af
+[UTEST]  space=server vaddr=0x2b0 size=0x1 parent=s0 p.vaddr=0x2b0
+[UTEST]  space=server vaddr=0x2b1 size=0x1 parent=s0 p.vaddr=0x2b1
+[UTEST]  space=server vaddr=0x2b2 size=0x1 parent=s0 p.vaddr=0x2b2
+[UTEST]  space=server vaddr=0x2b3 size=0x1 parent=s0 p.vaddr=0x2b3
+[UTEST]  space=server vaddr=0x2b4 size=0x1 parent=s0 p.vaddr=0x2b4
+[UTEST]  space=server vaddr=0x2b5 size=0x1 parent=s0 p.vaddr=0x2b5
+[UTEST]  space=server vaddr=0x2b6 size=0x1 parent=s0 p.vaddr=0x2b6
+[UTEST]  space=server vaddr=0x2b7 size=0x1 parent=s0 p.vaddr=0x2b7
+[UTEST]  space=server vaddr=0x2b8 size=0x1 parent=s0 p.vaddr=0x2b8
+[UTEST]  space=server vaddr=0x2b9 size=0x1 parent=s0 p.vaddr=0x2b9
+[UTEST]  space=server vaddr=0x2ba size=0x1 parent=s0 p.vaddr=0x2ba
+[UTEST]  space=server vaddr=0x2bb size=0x1 parent=s0 p.vaddr=0x2bb
+[UTEST]  space=server vaddr=0x2bc size=0x1 parent=s0 p.vaddr=0x2bc
+[UTEST]  space=server vaddr=0x2bd size=0x1 parent=s0 p.vaddr=0x2bd
+[UTEST]  space=server vaddr=0x2be size=0x1 parent=s0 p.vaddr=0x2be
+[UTEST]  space=server vaddr=0x2bf size=0x1 parent=s0 p.vaddr=0x2bf
+[UTEST]  space=server vaddr=0x2c0 size=0x1 parent=s0 p.vaddr=0x2c0
+[UTEST]  space=server vaddr=0x2c1 size=0x1 parent=s0 p.vaddr=0x2c1
+[UTEST]  space=server vaddr=0x2c2 size=0x1 parent=s0 p.vaddr=0x2c2
+[UTEST]  space=server vaddr=0x2c3 size=0x1 parent=s0 p.vaddr=0x2c3
+[UTEST]  space=server vaddr=0x2c4 size=0x1 parent=s0 p.vaddr=0x2c4
+[UTEST]  space=server vaddr=0x2c5 size=0x1 parent=s0 p.vaddr=0x2c5
+[UTEST]  space=server vaddr=0x2c6 size=0x1 parent=s0 p.vaddr=0x2c6
+[UTEST]  space=server vaddr=0x2c7 size=0x1 parent=s0 p.vaddr=0x2c7
+[UTEST]  space=server vaddr=0x2c8 size=0x1 parent=s0 p.vaddr=0x2c8
+[UTEST]  space=server vaddr=0x2c9 size=0x1 parent=s0 p.vaddr=0x2c9
+[UTEST]  space=server vaddr=0x2ca size=0x1 parent=s0 p.vaddr=0x2ca
+[UTEST]  space=server vaddr=0x2cb size=0x1 parent=s0 p.vaddr=0x2cb
+[UTEST]  space=server vaddr=0x2cc size=0x1 parent=s0 p.vaddr=0x2cc
+[UTEST]  space=server vaddr=0x2cd size=0x1 parent=s0 p.vaddr=0x2cd
+[UTEST]  space=server vaddr=0x2ce size=0x1 parent=s0 p.vaddr=0x2ce
+[UTEST]  space=server vaddr=0x2cf size=0x1 parent=s0 p.vaddr=0x2cf
+[UTEST]  space=server vaddr=0x2d0 size=0x1 parent=s0 p.vaddr=0x2d0
+[UTEST]  space=server vaddr=0x2d1 size=0x1 parent=s0 p.vaddr=0x2d1
+[UTEST]  space=server vaddr=0x2d2 size=0x1 parent=s0 p.vaddr=0x2d2
+[UTEST]  space=server vaddr=0x2d3 size=0x1 parent=s0 p.vaddr=0x2d3
+[UTEST]  space=server vaddr=0x2d4 size=0x1 parent=s0 p.vaddr=0x2d4
+[UTEST]  space=server vaddr=0x2d5 size=0x1 parent=s0 p.vaddr=0x2d5
+[UTEST]  space=server vaddr=0x2d6 size=0x1 parent=s0 p.vaddr=0x2d6
+[UTEST]  space=server vaddr=0x2d7 size=0x1 parent=s0 p.vaddr=0x2d7
+[UTEST]  space=server vaddr=0x2d8 size=0x1 parent=s0 p.vaddr=0x2d8
+[UTEST]  space=server vaddr=0x2d9 size=0x1 parent=s0 p.vaddr=0x2d9
+[UTEST]  space=server vaddr=0x2da size=0x1 parent=s0 p.vaddr=0x2da
+[UTEST]  space=server vaddr=0x2db size=0x1 parent=s0 p.vaddr=0x2db
+[UTEST]  space=server vaddr=0x2dc size=0x1 parent=s0 p.vaddr=0x2dc
+[UTEST]  space=server vaddr=0x2dd size=0x1 parent=s0 p.vaddr=0x2dd
+[UTEST]  space=server vaddr=0x2de size=0x1 parent=s0 p.vaddr=0x2de
+[UTEST]  space=server vaddr=0x2df size=0x1 parent=s0 p.vaddr=0x2df
+[UTEST]  space=server vaddr=0x2e0 size=0x1 parent=s0 p.vaddr=0x2e0
+[UTEST]  space=server vaddr=0x2e1 size=0x1 parent=s0 p.vaddr=0x2e1
+[UTEST]  space=server vaddr=0x2e2 size=0x1 parent=s0 p.vaddr=0x2e2
+[UTEST]  space=server vaddr=0x2e3 size=0x1 parent=s0 p.vaddr=0x2e3
+[UTEST]  space=server vaddr=0x2e4 size=0x1 parent=s0 p.vaddr=0x2e4
+[UTEST]  space=server vaddr=0x2e5 size=0x1 parent=s0 p.vaddr=0x2e5
+[UTEST]  space=server vaddr=0x2e6 size=0x1 parent=s0 p.vaddr=0x2e6
+[UTEST]  space=server vaddr=0x2e7 size=0x1 parent=s0 p.vaddr=0x2e7
+[UTEST]  space=server vaddr=0x2e8 size=0x1 parent=s0 p.vaddr=0x2e8
+[UTEST]  space=server vaddr=0x2e9 size=0x1 parent=s0 p.vaddr=0x2e9
+[UTEST]  space=server vaddr=0x2ea size=0x1 parent=s0 p.vaddr=0x2ea
+[UTEST]  space=server vaddr=0x2eb size=0x1 parent=s0 p.vaddr=0x2eb
+[UTEST]  space=server vaddr=0x2ec size=0x1 parent=s0 p.vaddr=0x2ec
+[UTEST]  space=server vaddr=0x2ed size=0x1 parent=s0 p.vaddr=0x2ed
+[UTEST]  space=server vaddr=0x2ee size=0x1 parent=s0 p.vaddr=0x2ee
+[UTEST]  space=server vaddr=0x2ef size=0x1 parent=s0 p.vaddr=0x2ef
+[UTEST]  space=server vaddr=0x2f0 size=0x1 parent=s0 p.vaddr=0x2f0
+[UTEST]  space=server vaddr=0x2f1 size=0x1 parent=s0 p.vaddr=0x2f1
+[UTEST]  space=server vaddr=0x2f2 size=0x1 parent=s0 p.vaddr=0x2f2
+[UTEST]  space=server vaddr=0x2f3 size=0x1 parent=s0 p.vaddr=0x2f3
+[UTEST]  space=server vaddr=0x2f4 size=0x1 parent=s0 p.vaddr=0x2f4
+[UTEST]  space=server vaddr=0x2f5 size=0x1 parent=s0 p.vaddr=0x2f5
+[UTEST]  space=server vaddr=0x2f6 size=0x1 parent=s0 p.vaddr=0x2f6
+[UTEST]  space=server vaddr=0x2f7 size=0x1 parent=s0 p.vaddr=0x2f7
+[UTEST]  space=server vaddr=0x2f8 size=0x1 parent=s0 p.vaddr=0x2f8
+[UTEST]  space=server vaddr=0x2f9 size=0x1 parent=s0 p.vaddr=0x2f9
+[UTEST]  space=server vaddr=0x2fa size=0x1 parent=s0 p.vaddr=0x2fa
+[UTEST]  space=server vaddr=0x2fb size=0x1 parent=s0 p.vaddr=0x2fb
+[UTEST]  space=server vaddr=0x2fc size=0x1 parent=s0 p.vaddr=0x2fc
+[UTEST]  space=server vaddr=0x2fd size=0x1 parent=s0 p.vaddr=0x2fd
+[UTEST]  space=server vaddr=0x2fe size=0x1 parent=s0 p.vaddr=0x2fe
+[UTEST]  space=server vaddr=0x2ff size=0x1 parent=s0 p.vaddr=0x2ff
+[UTEST]  space=server vaddr=0x300 size=0x1 parent=s0 p.vaddr=0x300
+[UTEST]  space=server vaddr=0x301 size=0x1 parent=s0 p.vaddr=0x301
+[UTEST]  space=server vaddr=0x302 size=0x1 parent=s0 p.vaddr=0x302
+[UTEST]  space=server vaddr=0x303 size=0x1 parent=s0 p.vaddr=0x303
+[UTEST]  space=server vaddr=0x304 size=0x1 parent=s0 p.vaddr=0x304
+[UTEST]  space=server vaddr=0x305 size=0x1 parent=s0 p.vaddr=0x305
+[UTEST]  space=server vaddr=0x306 size=0x1 parent=s0 p.vaddr=0x306
+[UTEST]  space=server vaddr=0x307 size=0x1 parent=s0 p.vaddr=0x307
+[UTEST]  space=server vaddr=0x308 size=0x1 parent=s0 p.vaddr=0x308
+[UTEST]  space=server vaddr=0x309 size=0x1 parent=s0 p.vaddr=0x309
+[UTEST]  space=server vaddr=0x30a size=0x1 parent=s0 p.vaddr=0x30a
+[UTEST]  space=server vaddr=0x30b size=0x1 parent=s0 p.vaddr=0x30b
+[UTEST]  space=server vaddr=0x30c size=0x1 parent=s0 p.vaddr=0x30c
+[UTEST]  space=server vaddr=0x30d size=0x1 parent=s0 p.vaddr=0x30d
+[UTEST]  space=server vaddr=0x30e size=0x1 parent=s0 p.vaddr=0x30e
+[UTEST]  space=server vaddr=0x30f size=0x1 parent=s0 p.vaddr=0x30f
+[UTEST]  space=server vaddr=0x310 size=0x1 parent=s0 p.vaddr=0x310
+[UTEST]  space=server vaddr=0x311 size=0x1 parent=s0 p.vaddr=0x311
+[UTEST]  space=server vaddr=0x312 size=0x1 parent=s0 p.vaddr=0x312
+[UTEST]  space=server vaddr=0x313 size=0x1 parent=s0 p.vaddr=0x313
+[UTEST]  space=server vaddr=0x314 size=0x1 parent=s0 p.vaddr=0x314
+[UTEST]  space=server vaddr=0x315 size=0x1 parent=s0 p.vaddr=0x315
+[UTEST]  space=server vaddr=0x316 size=0x1 parent=s0 p.vaddr=0x316
+[UTEST]  space=server vaddr=0x317 size=0x1 parent=s0 p.vaddr=0x317
+[UTEST]  space=server vaddr=0x318 size=0x1 parent=s0 p.vaddr=0x318
+[UTEST]  space=server vaddr=0x319 size=0x1 parent=s0 p.vaddr=0x319
+[UTEST]  space=server vaddr=0x31a size=0x1 parent=s0 p.vaddr=0x31a
+[UTEST]  space=server vaddr=0x31b size=0x1 parent=s0 p.vaddr=0x31b
+[UTEST]  space=server vaddr=0x31c size=0x1 parent=s0 p.vaddr=0x31c
+[UTEST]  space=server vaddr=0x31d size=0x1 parent=s0 p.vaddr=0x31d
+[UTEST]  space=server vaddr=0x31e size=0x1 parent=s0 p.vaddr=0x31e
+[UTEST]  space=server vaddr=0x31f size=0x1 parent=s0 p.vaddr=0x31f
+[UTEST]  space=server vaddr=0x320 size=0x1 parent=s0 p.vaddr=0x320
+[UTEST]  space=server vaddr=0x321 size=0x1 parent=s0 p.vaddr=0x321
+[UTEST]  space=server vaddr=0x322 size=0x1 parent=s0 p.vaddr=0x322
+[UTEST]  space=server vaddr=0x323 size=0x1 parent=s0 p.vaddr=0x323
+[UTEST]  space=server vaddr=0x324 size=0x1 parent=s0 p.vaddr=0x324
+[UTEST]  space=server vaddr=0x325 size=0x1 parent=s0 p.vaddr=0x325
+[UTEST]  space=server vaddr=0x326 size=0x1 parent=s0 p.vaddr=0x326
+[UTEST]  space=server vaddr=0x327 size=0x1 parent=s0 p.vaddr=0x327
+[UTEST]  space=server vaddr=0x328 size=0x1 parent=s0 p.vaddr=0x328
+[UTEST]  space=server vaddr=0x329 size=0x1 parent=s0 p.vaddr=0x329
+[UTEST]  space=server vaddr=0x32a size=0x1 parent=s0 p.vaddr=0x32a
+[UTEST]  space=server vaddr=0x32b size=0x1 parent=s0 p.vaddr=0x32b
+[UTEST]  space=server vaddr=0x32c size=0x1 parent=s0 p.vaddr=0x32c
+[UTEST]  space=server vaddr=0x32d size=0x1 parent=s0 p.vaddr=0x32d
+[UTEST]  space=server vaddr=0x32e size=0x1 parent=s0 p.vaddr=0x32e
+[UTEST]  space=server vaddr=0x32f size=0x1 parent=s0 p.vaddr=0x32f
+[UTEST]  space=server vaddr=0x330 size=0x1 parent=s0 p.vaddr=0x330
+[UTEST]  space=server vaddr=0x331 size=0x1 parent=s0 p.vaddr=0x331
+[UTEST]  space=server vaddr=0x332 size=0x1 parent=s0 p.vaddr=0x332
+[UTEST]  space=server vaddr=0x333 size=0x1 parent=s0 p.vaddr=0x333
+[UTEST]  space=server vaddr=0x334 size=0x1 parent=s0 p.vaddr=0x334
+[UTEST]  space=server vaddr=0x335 size=0x1 parent=s0 p.vaddr=0x335
+[UTEST]  space=server vaddr=0x336 size=0x1 parent=s0 p.vaddr=0x336
+[UTEST]  space=server vaddr=0x337 size=0x1 parent=s0 p.vaddr=0x337
+[UTEST]  space=server vaddr=0x338 size=0x1 parent=s0 p.vaddr=0x338
+[UTEST]  space=server vaddr=0x339 size=0x1 parent=s0 p.vaddr=0x339
+[UTEST]  space=server vaddr=0x33a size=0x1 parent=s0 p.vaddr=0x33a
+[UTEST]  space=server vaddr=0x33b size=0x1 parent=s0 p.vaddr=0x33b
+[UTEST]  space=server vaddr=0x33c size=0x1 parent=s0 p.vaddr=0x33c
+[UTEST]  space=server vaddr=0x33d size=0x1 parent=s0 p.vaddr=0x33d
+[UTEST]  space=server vaddr=0x33e size=0x1 parent=s0 p.vaddr=0x33e
+[UTEST]  space=server vaddr=0x33f size=0x1 parent=s0 p.vaddr=0x33f
+[UTEST]  space=server vaddr=0x340 size=0x1 parent=s0 p.vaddr=0x340
+[UTEST]  space=server vaddr=0x341 size=0x1 parent=s0 p.vaddr=0x341
+[UTEST]  space=server vaddr=0x342 size=0x1 parent=s0 p.vaddr=0x342
+[UTEST]  space=server vaddr=0x343 size=0x1 parent=s0 p.vaddr=0x343
+[UTEST]  space=server vaddr=0x344 size=0x1 parent=s0 p.vaddr=0x344
+[UTEST]  space=server vaddr=0x345 size=0x1 parent=s0 p.vaddr=0x345
+[UTEST]  space=server vaddr=0x346 size=0x1 parent=s0 p.vaddr=0x346
+[UTEST]  space=server vaddr=0x347 size=0x1 parent=s0 p.vaddr=0x347
+[UTEST]  space=server vaddr=0x348 size=0x1 parent=s0 p.vaddr=0x348
+[UTEST]  space=server vaddr=0x349 size=0x1 parent=s0 p.vaddr=0x349
+[UTEST]  space=server vaddr=0x34a size=0x1 parent=s0 p.vaddr=0x34a
+[UTEST]  space=server vaddr=0x34b size=0x1 parent=s0 p.vaddr=0x34b
+[UTEST]  space=server vaddr=0x34c size=0x1 parent=s0 p.vaddr=0x34c
+[UTEST]  space=server vaddr=0x34d size=0x1 parent=s0 p.vaddr=0x34d
+[UTEST]  space=server vaddr=0x34e size=0x1 parent=s0 p.vaddr=0x34e
+[UTEST]  space=server vaddr=0x34f size=0x1 parent=s0 p.vaddr=0x34f
+[UTEST]  space=server vaddr=0x350 size=0x1 parent=s0 p.vaddr=0x350
+[UTEST]  space=server vaddr=0x351 size=0x1 parent=s0 p.vaddr=0x351
+[UTEST]  space=server vaddr=0x352 size=0x1 parent=s0 p.vaddr=0x352
+[UTEST]  space=server vaddr=0x353 size=0x1 parent=s0 p.vaddr=0x353
+[UTEST]  space=server vaddr=0x354 size=0x1 parent=s0 p.vaddr=0x354
+[UTEST]  space=server vaddr=0x355 size=0x1 parent=s0 p.vaddr=0x355
+[UTEST]  space=server vaddr=0x356 size=0x1 parent=s0 p.vaddr=0x356
+[UTEST]  space=server vaddr=0x357 size=0x1 parent=s0 p.vaddr=0x357
+[UTEST]  space=server vaddr=0x358 size=0x1 parent=s0 p.vaddr=0x358
+[UTEST]  space=server vaddr=0x359 size=0x1 parent=s0 p.vaddr=0x359
+[UTEST]  space=server vaddr=0x35a size=0x1 parent=s0 p.vaddr=0x35a
+[UTEST]  space=server vaddr=0x35b size=0x1 parent=s0 p.vaddr=0x35b
+[UTEST]  space=server vaddr=0x35c size=0x1 parent=s0 p.vaddr=0x35c
+[UTEST]  space=server vaddr=0x35d size=0x1 parent=s0 p.vaddr=0x35d
+[UTEST]  space=server vaddr=0x35e size=0x1 parent=s0 p.vaddr=0x35e
+[UTEST]  space=server vaddr=0x35f size=0x1 parent=s0 p.vaddr=0x35f
+[UTEST]  space=server vaddr=0x360 size=0x1 parent=s0 p.vaddr=0x360
+[UTEST]  space=server vaddr=0x361 size=0x1 parent=s0 p.vaddr=0x361
+[UTEST]  space=server vaddr=0x362 size=0x1 parent=s0 p.vaddr=0x362
+[UTEST]  space=server vaddr=0x363 size=0x1 parent=s0 p.vaddr=0x363
+[UTEST]  space=server vaddr=0x364 size=0x1 parent=s0 p.vaddr=0x364
+[UTEST]  space=server vaddr=0x365 size=0x1 parent=s0 p.vaddr=0x365
+[UTEST]  space=server vaddr=0x366 size=0x1 parent=s0 p.vaddr=0x366
+[UTEST]  space=server vaddr=0x367 size=0x1 parent=s0 p.vaddr=0x367
+[UTEST]  space=server vaddr=0x368 size=0x1 parent=s0 p.vaddr=0x368
+[UTEST]  space=server vaddr=0x369 size=0x1 parent=s0 p.vaddr=0x369
+[UTEST]  space=server vaddr=0x36a size=0x1 parent=s0 p.vaddr=0x36a
+[UTEST]  space=server vaddr=0x36b size=0x1 parent=s0 p.vaddr=0x36b
+[UTEST]  space=server vaddr=0x36c size=0x1 parent=s0 p.vaddr=0x36c
+[UTEST]  space=server vaddr=0x36d size=0x1 parent=s0 p.vaddr=0x36d
+[UTEST]  space=server vaddr=0x36e size=0x1 parent=s0 p.vaddr=0x36e
+[UTEST]  space=server vaddr=0x36f size=0x1 parent=s0 p.vaddr=0x36f
+[UTEST]  space=server vaddr=0x370 size=0x1 parent=s0 p.vaddr=0x370
+[UTEST]  space=server vaddr=0x371 size=0x1 parent=s0 p.vaddr=0x371
+[UTEST]  space=server vaddr=0x372 size=0x1 parent=s0 p.vaddr=0x372
+[UTEST]  space=server vaddr=0x373 size=0x1 parent=s0 p.vaddr=0x373
+[UTEST]  space=server vaddr=0x374 size=0x1 parent=s0 p.vaddr=0x374
+[UTEST]  space=server vaddr=0x375 size=0x1 parent=s0 p.vaddr=0x375
+[UTEST]  space=server vaddr=0x376 size=0x1 parent=s0 p.vaddr=0x376
+[UTEST]  space=server vaddr=0x377 size=0x1 parent=s0 p.vaddr=0x377
+[UTEST]  space=server vaddr=0x378 size=0x1 parent=s0 p.vaddr=0x378
+[UTEST]  space=server vaddr=0x379 size=0x1 parent=s0 p.vaddr=0x379
+[UTEST]  space=server vaddr=0x37a size=0x1 parent=s0 p.vaddr=0x37a
+[UTEST]  space=server vaddr=0x37b size=0x1 parent=s0 p.vaddr=0x37b
+[UTEST]  space=server vaddr=0x37c size=0x1 parent=s0 p.vaddr=0x37c
+[UTEST]  space=server vaddr=0x37d size=0x1 parent=s0 p.vaddr=0x37d
+[UTEST]  space=server vaddr=0x37e size=0x1 parent=s0 p.vaddr=0x37e
+[UTEST]  space=server vaddr=0x37f size=0x1 parent=s0 p.vaddr=0x37f
+[UTEST]  space=server vaddr=0x380 size=0x1 parent=s0 p.vaddr=0x380
+[UTEST]  space=server vaddr=0x381 size=0x1 parent=s0 p.vaddr=0x381
+[UTEST]  space=server vaddr=0x382 size=0x1 parent=s0 p.vaddr=0x382
+[UTEST]  space=server vaddr=0x383 size=0x1 parent=s0 p.vaddr=0x383
+[UTEST]  space=server vaddr=0x384 size=0x1 parent=s0 p.vaddr=0x384
+[UTEST]  space=server vaddr=0x385 size=0x1 parent=s0 p.vaddr=0x385
+[UTEST]  space=server vaddr=0x386 size=0x1 parent=s0 p.vaddr=0x386
+[UTEST]  space=server vaddr=0x387 size=0x1 parent=s0 p.vaddr=0x387
+[UTEST]  space=server vaddr=0x388 size=0x1 parent=s0 p.vaddr=0x388
+[UTEST]  space=server vaddr=0x389 size=0x1 parent=s0 p.vaddr=0x389
+[UTEST]  space=server vaddr=0x38a size=0x1 parent=s0 p.vaddr=0x38a
+[UTEST]  space=server vaddr=0x38b size=0x1 parent=s0 p.vaddr=0x38b
+[UTEST]  space=server vaddr=0x38c size=0x1 parent=s0 p.vaddr=0x38c
+[UTEST]  space=server vaddr=0x38d size=0x1 parent=s0 p.vaddr=0x38d
+[UTEST]  space=server vaddr=0x38e size=0x1 parent=s0 p.vaddr=0x38e
+[UTEST]  space=server vaddr=0x38f size=0x1 parent=s0 p.vaddr=0x38f
+[UTEST]  space=server vaddr=0x390 size=0x1 parent=s0 p.vaddr=0x390
+[UTEST]  space=server vaddr=0x391 size=0x1 parent=s0 p.vaddr=0x391
+[UTEST]  space=server vaddr=0x392 size=0x1 parent=s0 p.vaddr=0x392
+[UTEST]  space=server vaddr=0x393 size=0x1 parent=s0 p.vaddr=0x393
+[UTEST]  space=server vaddr=0x394 size=0x1 parent=s0 p.vaddr=0x394
+[UTEST]  space=server vaddr=0x395 size=0x1 parent=s0 p.vaddr=0x395
+[UTEST]  space=server vaddr=0x396 size=0x1 parent=s0 p.vaddr=0x396
+[UTEST]  space=server vaddr=0x397 size=0x1 parent=s0 p.vaddr=0x397
+[UTEST]  space=server vaddr=0x398 size=0x1 parent=s0 p.vaddr=0x398
+[UTEST]  space=server vaddr=0x399 size=0x1 parent=s0 p.vaddr=0x399
+[UTEST]  space=server vaddr=0x39a size=0x1 parent=s0 p.vaddr=0x39a
+[UTEST]  space=server vaddr=0x39b size=0x1 parent=s0 p.vaddr=0x39b
+[UTEST]  space=server vaddr=0x39c size=0x1 parent=s0 p.vaddr=0x39c
+[UTEST]  space=server vaddr=0x39d size=0x1 parent=s0 p.vaddr=0x39d
+[UTEST]  space=server vaddr=0x39e size=0x1 parent=s0 p.vaddr=0x39e
+[UTEST]  space=server vaddr=0x39f size=0x1 parent=s0 p.vaddr=0x39f
+[UTEST]  space=server vaddr=0x3a0 size=0x1 parent=s0 p.vaddr=0x3a0
+[UTEST]  space=server vaddr=0x3a1 size=0x1 parent=s0 p.vaddr=0x3a1
+[UTEST]  space=server vaddr=0x3a2 size=0x1 parent=s0 p.vaddr=0x3a2
+[UTEST]  space=server vaddr=0x3a3 size=0x1 parent=s0 p.vaddr=0x3a3
+[UTEST]  space=server vaddr=0x3a4 size=0x1 parent=s0 p.vaddr=0x3a4
+[UTEST]  space=server vaddr=0x3a5 size=0x1 parent=s0 p.vaddr=0x3a5
+[UTEST]  space=server vaddr=0x3a6 size=0x1 parent=s0 p.vaddr=0x3a6
+[UTEST]  space=server vaddr=0x3a7 size=0x1 parent=s0 p.vaddr=0x3a7
+[UTEST]  space=server vaddr=0x3a8 size=0x1 parent=s0 p.vaddr=0x3a8
+[UTEST]  space=server vaddr=0x3a9 size=0x1 parent=s0 p.vaddr=0x3a9
+[UTEST]  space=server vaddr=0x3aa size=0x1 parent=s0 p.vaddr=0x3aa
+[UTEST]  space=server vaddr=0x3ab size=0x1 parent=s0 p.vaddr=0x3ab
+[UTEST]  space=server vaddr=0x3ac size=0x1 parent=s0 p.vaddr=0x3ac
+[UTEST]  space=server vaddr=0x3ad size=0x1 parent=s0 p.vaddr=0x3ad
+[UTEST]  space=server vaddr=0x3ae size=0x1 parent=s0 p.vaddr=0x3ae
+[UTEST]  space=server vaddr=0x3af size=0x1 parent=s0 p.vaddr=0x3af
+[UTEST]  space=server vaddr=0x3b0 size=0x1 parent=s0 p.vaddr=0x3b0
+[UTEST]  space=server vaddr=0x3b1 size=0x1 parent=s0 p.vaddr=0x3b1
+[UTEST]  space=server vaddr=0x3b2 size=0x1 parent=s0 p.vaddr=0x3b2
+[UTEST]  space=server vaddr=0x3b3 size=0x1 parent=s0 p.vaddr=0x3b3
+[UTEST]  space=server vaddr=0x3b4 size=0x1 parent=s0 p.vaddr=0x3b4
+[UTEST]  space=server vaddr=0x3b5 size=0x1 parent=s0 p.vaddr=0x3b5
+[UTEST]  space=server vaddr=0x3b6 size=0x1 parent=s0 p.vaddr=0x3b6
+[UTEST]  space=server vaddr=0x3b7 size=0x1 parent=s0 p.vaddr=0x3b7
+[UTEST]  space=server vaddr=0x3b8 size=0x1 parent=s0 p.vaddr=0x3b8
+[UTEST]  space=server vaddr=0x3b9 size=0x1 parent=s0 p.vaddr=0x3b9
+[UTEST]  space=server vaddr=0x3ba size=0x1 parent=s0 p.vaddr=0x3ba
+[UTEST]  space=server vaddr=0x3bb size=0x1 parent=s0 p.vaddr=0x3bb
+[UTEST]  space=server vaddr=0x3bc size=0x1 parent=s0 p.vaddr=0x3bc
+[UTEST]  space=server vaddr=0x3bd size=0x1 parent=s0 p.vaddr=0x3bd
+[UTEST]  space=server vaddr=0x3be size=0x1 parent=s0 p.vaddr=0x3be
+[UTEST]  space=server vaddr=0x3bf size=0x1 parent=s0 p.vaddr=0x3bf
+[UTEST]  space=server vaddr=0x3c0 size=0x1 parent=s0 p.vaddr=0x3c0
+[UTEST]  space=server vaddr=0x3c1 size=0x1 parent=s0 p.vaddr=0x3c1
+[UTEST]  space=server vaddr=0x3c2 size=0x1 parent=s0 p.vaddr=0x3c2
+[UTEST]  space=server vaddr=0x3c3 size=0x1 parent=s0 p.vaddr=0x3c3
+[UTEST]  space=server vaddr=0x3c4 size=0x1 parent=s0 p.vaddr=0x3c4
+[UTEST]  space=server vaddr=0x3c5 size=0x1 parent=s0 p.vaddr=0x3c5
+[UTEST]  space=server vaddr=0x3c6 size=0x1 parent=s0 p.vaddr=0x3c6
+[UTEST]  space=server vaddr=0x3c7 size=0x1 parent=s0 p.vaddr=0x3c7
+[UTEST]  space=server vaddr=0x3c8 size=0x1 parent=s0 p.vaddr=0x3c8
+[UTEST]  space=server vaddr=0x3c9 size=0x1 parent=s0 p.vaddr=0x3c9
+[UTEST]  space=server vaddr=0x3ca size=0x1 parent=s0 p.vaddr=0x3ca
+[UTEST]  space=server vaddr=0x3cb size=0x1 parent=s0 p.vaddr=0x3cb
+[UTEST]  space=server vaddr=0x3cc size=0x1 parent=s0 p.vaddr=0x3cc
+[UTEST]  space=server vaddr=0x3cd size=0x1 parent=s0 p.vaddr=0x3cd
+[UTEST]  space=server vaddr=0x3ce size=0x1 parent=s0 p.vaddr=0x3ce
+[UTEST]  space=server vaddr=0x3cf size=0x1 parent=s0 p.vaddr=0x3cf
+[UTEST]  space=server vaddr=0x3d0 size=0x1 parent=s0 p.vaddr=0x3d0
+[UTEST]  space=server vaddr=0x3d1 size=0x1 parent=s0 p.vaddr=0x3d1
+[UTEST]  space=server vaddr=0x3d2 size=0x1 parent=s0 p.vaddr=0x3d2
+[UTEST]  space=server vaddr=0x3d3 size=0x1 parent=s0 p.vaddr=0x3d3
+[UTEST]  space=server vaddr=0x3d4 size=0x1 parent=s0 p.vaddr=0x3d4
+[UTEST]  space=server vaddr=0x3d5 size=0x1 parent=s0 p.vaddr=0x3d5
+[UTEST]  space=server vaddr=0x3d6 size=0x1 parent=s0 p.vaddr=0x3d6
+[UTEST]  space=server vaddr=0x3d7 size=0x1 parent=s0 p.vaddr=0x3d7
+[UTEST]  space=server vaddr=0x3d8 size=0x1 parent=s0 p.vaddr=0x3d8
+[UTEST]  space=server vaddr=0x3d9 size=0x1 parent=s0 p.vaddr=0x3d9
+[UTEST]  space=server vaddr=0x3da size=0x1 parent=s0 p.vaddr=0x3da
+[UTEST]  space=server vaddr=0x3db size=0x1 parent=s0 p.vaddr=0x3db
+[UTEST]  space=server vaddr=0x3dc size=0x1 parent=s0 p.vaddr=0x3dc
+[UTEST]  space=server vaddr=0x3dd size=0x1 parent=s0 p.vaddr=0x3dd
+[UTEST]  space=server vaddr=0x3de size=0x1 parent=s0 p.vaddr=0x3de
+[UTEST]  space=server vaddr=0x3df size=0x1 parent=s0 p.vaddr=0x3df
+[UTEST]  space=server vaddr=0x3e0 size=0x1 parent=s0 p.vaddr=0x3e0
+[UTEST]  space=server vaddr=0x3e1 size=0x1 parent=s0 p.vaddr=0x3e1
+[UTEST]  space=server vaddr=0x3e2 size=0x1 parent=s0 p.vaddr=0x3e2
+[UTEST]  space=server vaddr=0x3e3 size=0x1 parent=s0 p.vaddr=0x3e3
+[UTEST]  space=server vaddr=0x3e4 size=0x1 parent=s0 p.vaddr=0x3e4
+[UTEST]  space=server vaddr=0x3e5 size=0x1 parent=s0 p.vaddr=0x3e5
+[UTEST]  space=server vaddr=0x3e6 size=0x1 parent=s0 p.vaddr=0x3e6
+[UTEST]  space=server vaddr=0x3e7 size=0x1 parent=s0 p.vaddr=0x3e7
+[UTEST]  space=server vaddr=0x3e8 size=0x1 parent=s0 p.vaddr=0x3e8
+[UTEST]  space=server vaddr=0x3e9 size=0x1 parent=s0 p.vaddr=0x3e9
+[UTEST]  space=server vaddr=0x3ea size=0x1 parent=s0 p.vaddr=0x3ea
+[UTEST]  space=server vaddr=0x3eb size=0x1 parent=s0 p.vaddr=0x3eb
+[UTEST]  space=server vaddr=0x3ec size=0x1 parent=s0 p.vaddr=0x3ec
+[UTEST]  space=server vaddr=0x3ed size=0x1 parent=s0 p.vaddr=0x3ed
+[UTEST]  space=server vaddr=0x3ee size=0x1 parent=s0 p.vaddr=0x3ee
+[UTEST]  space=server vaddr=0x3ef size=0x1 parent=s0 p.vaddr=0x3ef
+[UTEST]  space=server vaddr=0x3f0 size=0x1 parent=s0 p.vaddr=0x3f0
+[UTEST]  space=server vaddr=0x3f1 size=0x1 parent=s0 p.vaddr=0x3f1
+[UTEST]  space=server vaddr=0x3f2 size=0x1 parent=s0 p.vaddr=0x3f2
+[UTEST]  space=server vaddr=0x3f3 size=0x1 parent=s0 p.vaddr=0x3f3
+[UTEST]  space=server vaddr=0x3f4 size=0x1 parent=s0 p.vaddr=0x3f4
+[UTEST]  space=server vaddr=0x3f5 size=0x1 parent=s0 p.vaddr=0x3f5
+[UTEST]  space=server vaddr=0x3f6 size=0x1 parent=s0 p.vaddr=0x3f6
+[UTEST]  space=server vaddr=0x3f7 size=0x1 parent=s0 p.vaddr=0x3f7
+[UTEST]  space=server vaddr=0x3f8 size=0x1 parent=s0 p.vaddr=0x3f8
+[UTEST]  space=server vaddr=0x3f9 size=0x1 parent=s0 p.vaddr=0x3f9
+[UTEST]  space=server vaddr=0x3fa size=0x1 parent=s0 p.vaddr=0x3fa
+[UTEST]  space=server vaddr=0x3fb size=0x1 parent=s0 p.vaddr=0x3fb
+[UTEST]  space=server vaddr=0x3fc size=0x1 parent=s0 p.vaddr=0x3fc
+[UTEST]  space=server vaddr=0x3fd size=0x1 parent=s0 p.vaddr=0x3fd
+[UTEST]  space=server vaddr=0x3fe size=0x1 parent=s0 p.vaddr=0x3fe
+[UTEST]  space=server vaddr=0x3ff size=0x1 parent=s0 p.vaddr=0x3ff
+[UTEST] 
+[UTEST] space=s0 vaddr=0x400 size=0x400
+[UTEST]  space=server vaddr=0x800 size=0x400 parent=s0 p.vaddr=0x400
+[UTEST] 
+[UTEST] space=s0 vaddr=0x400 size=0x400
+[UTEST]  space=server vaddr=0x800 size=0x400 parent=s0 p.vaddr=0x400
+[UTEST]  space=client vaddr=0x8 size=0x1 parent=server p.vaddr=0x801
+[UTEST] 
index b97d60ca6d93784e7a99b1ab60fcf6213f8e7b8d..d157af7a81ba303689664bf376aed23d5350a54d 100644 (file)
@@ -30,119 +30,169 @@ static size_t page_sizes[] =
 
 static size_t page_sizes_max = 2;
 
+class Fake_factory : public Ram_quota
+{
+};
+
+class Fake_task : public Space
+{
+public:
+  Fake_task(Ram_quota *r, char const *name)
+  : Space(r, Caps::all()), name(name) {}
+
+  char const *name;
+};
+
 
 static void init_spaces()
 {
-  static Ram_quota rq;
-  L4_fpage utcb_area = L4_fpage::mem(0x1200000, Config::PAGE_SHIFT);
-  s0       = new Space(Space::Default_factory(), &rq, utcb_area);
-  other    = new Space(Space::Default_factory(), &rq, utcb_area);
-  client   = new Space(Space::Default_factory(), &rq, utcb_area);
-  father   = new Space(Space::Default_factory(), &rq, utcb_area);
-  son      = new Space(Space::Default_factory(), &rq, utcb_area);
-  daughter = new Space(Space::Default_factory(), &rq, utcb_area);
-  aunt     = new Space(Space::Default_factory(), &rq, utcb_area);
+  static Fake_factory rq;
+#define NEW_TASK(name) name = new Fake_task(&rq, #name)
+  NEW_TASK(s0);
+  NEW_TASK(other);
+  NEW_TASK(client);
+  NEW_TASK(father);
+  NEW_TASK(son);
+  NEW_TASK(daughter);
+  NEW_TASK(aunt);
+#undef NEW_TASK
+}
+
+static
+std::ostream &operator << (std::ostream &s, Mapdb::Pfn v)
+{
+  s << cxx::int_value<Mapdb::Pfn>(v);
+  return s;
+}
+
+static
+std::ostream &operator << (std::ostream &s, Mapping::Page v)
+{
+  s << cxx::int_value<Mapping::Page>(v);
+  return s;
+}
+
+static
+std::ostream &operator << (std::ostream &s, Space const &sp)
+{
+  Fake_task const *t = static_cast<Fake_task const *>(&sp);
+  if (!t)
+    s << "<NULL>";
+  else
+    s << t->name;
+  return s;
 }
 
 static void print_node(Mapping* node, const Mapdb::Frame& frame)
 {
   assert (node);
 
-  size_t shift;
-
-  for (Mapdb::Iterator i(frame, node, Virt_addr(0), Virt_addr(~0)); node;)
+  for (Mapdb::Iterator i(frame, node, Mapdb::Pfn(0), Mapdb::Pfn(~0)); node;)
     {
+      cout << "[UTEST] ";
       for (int d = node->depth(); d != 0; d--)
         cout << ' ';
 
-      shift = i.shift();
+      auto shift = i.order();
 
       cout << setbase(16)
-          << "space=0x"  << (unsigned) (node->space())
-          << " vaddr=0x" << (node->page() << shift).value()
-          << " size=0x" << (1UL << shift);
+          << "space="  << *node->space()
+          << " vaddr=0x" << (node->page() << shift)
+          << " size=0x" << (Mapdb::Pfn(1) << shift);
 
       if (Mapping* p = node->parent())
        {
-         cout << " parent=0x" << p->space()
-              << " p.vaddr=0x" << (p->page() << shift).value();
+         cout << " parent=" << *p->space()
+              << " p.vaddr=0x" << (p->page() << shift);
        }
 
       cout << endl;
 
       node = i;
       if (node)
-       {
-         shift = i.shift();
-         ++i;
-       }
+        ++i;
     }
-  cout << endl;
+  cout << "[UTEST] " << endl;
 }
 
+static
+Mapdb::Pfn to_pfn(Address a)
+{ return Mem_space::to_pfn(Mem_space::V_pfn(Virt_addr(a))); }
+
+static
+Mapdb::Pcnt to_pcnt(unsigned order)
+{ return Mem_space::to_pcnt(Mem_space::Page_order(order)); }
+
 void basic()
 {
-  Mapdb m (s0, Page_number(1U << (32 - Config::SUPERPAGE_SHIFT)), page_sizes, page_sizes_max);
+  unsigned phys_bits = 32;
+  Mapdb m (s0, Mapping::Page(1U << (phys_bits - Config::PAGE_SHIFT - page_sizes[0])), page_sizes, page_sizes_max);
 
-  Mapping *node, *sub, *subsub;
+  Mapping *node, *sub;
   Mapdb::Frame frame;
 
-  assert (! m.lookup(other, Mem_space::Addr::create(Config::PAGE_SIZE),
-                    Mem_space::Phys_addr::create(Config::PAGE_SIZE),
-                    &node, &frame));
+  typedef Mem_space SPACE;
+  typedef SPACE::V_pfn V_pfn;
+  typedef SPACE::V_pfc V_pfc;
+  typedef SPACE::Phys_addr Phys_addr;
+  typedef SPACE::Page_order Page_order;
 
-  cout << "Looking up 4M node at physaddr=0K" << endl;
-  assert (m.lookup (s0,  Mem_space::Addr::create(0),
-                   Mem_space::Phys_addr::create(0),
-                   &node, &frame));
+  assert (! m.lookup(other, to_pfn(Config::PAGE_SIZE),
+                     to_pfn(Config::PAGE_SIZE),
+                     &node, &frame));
+
+  cout << "[UTEST] Looking up 4M node at physaddr=0K" << endl;
+  assert (m.lookup (s0,  to_pfn(0),
+                    to_pfn(0),
+                    &node, &frame));
   print_node (node, frame);
 
-  cout << "Inserting submapping" << endl;
+  cout << "[UTEST] Inserting submapping" << endl;
   sub = m.insert (frame, node, other,
-                 Mem_space::Addr::create(2*Config::PAGE_SIZE),
-                 Mem_space::Phys_addr::create(Config::PAGE_SIZE),
-                 Mem_space::Size::create(Config::PAGE_SIZE));
+                 to_pfn(2*Config::PAGE_SIZE),
+                 to_pfn(Config::PAGE_SIZE),
+                 to_pcnt(Config::PAGE_SHIFT));
   print_node (node, frame);
 
   m.free (frame);
 
   //////////////////////////////////////////////////////////////////////
 
-  cout << "Looking up 4M node at physaddr=8M" << endl;
+  cout << "[UTEST] Looking up 4M node at physaddr=8M" << endl;
   assert (m.lookup (s0,
-                   Mem_space::Addr::create(2*Config::SUPERPAGE_SIZE),
-                   Mem_space::Phys_addr::create(2*Config::SUPERPAGE_SIZE),
+                   to_pfn(2*Config::SUPERPAGE_SIZE),
+                   to_pfn(2*Config::SUPERPAGE_SIZE),
                    &node, &frame));
   print_node (node, frame);
 
   // XXX broken mapdb: assert (node->size() == Config::SUPERPAGE_SIZE);
 
-  cout << "Inserting submapping" << endl;
+  cout << "[UTEST] Inserting submapping" << endl;
   sub = m.insert (frame, node, other,
-                 Mem_space::Addr::create(4*Config::SUPERPAGE_SIZE),
-                 Mem_space::Phys_addr::create(2*Config::SUPERPAGE_SIZE),
-                 Mem_space::Size::create(Config::SUPERPAGE_SIZE));
+                 to_pfn(4*Config::SUPERPAGE_SIZE),
+                 to_pfn(2*Config::SUPERPAGE_SIZE),
+                 to_pcnt(Config::SUPERPAGE_SHIFT));
   print_node (node, frame);
 
-  assert (m.shift(frame, sub) == Config::SUPERPAGE_SHIFT- Config::PAGE_SHIFT);
+  assert (m.shift(frame, sub) == Mapdb::Order(Config::SUPERPAGE_SHIFT - Config::PAGE_SHIFT));
 
   // Before we can insert new mappings, we must free the tree.
   m.free (frame);
 
-  cout << "Get that mapping again" << endl;
+  cout << "[UTEST] Get that mapping again" << endl;
   assert (m.lookup (other,
-                   Mem_space::Addr::create(4*Config::SUPERPAGE_SIZE),
-                   Mem_space::Phys_addr::create(2*Config::SUPERPAGE_SIZE),
+                   to_pfn(4*Config::SUPERPAGE_SIZE),
+                   to_pfn(2*Config::SUPERPAGE_SIZE),
                    &sub, &frame));
   print_node (sub, frame);
 
   node = sub->parent();
 
-  cout << "Inserting 4K submapping" << endl;
-  subsub = m.insert (frame, sub, client,
-                    Mem_space::Addr::create(15*Config::PAGE_SIZE),
-                    Mem_space::Phys_addr::create(2*Config::SUPERPAGE_SIZE),
-                    Mem_space::Size::create(Config::PAGE_SIZE));
+  cout << "[UTEST] Inserting 4K submapping" << endl;
+  assert ( m.insert (frame, sub, client,
+                    to_pfn(15*Config::PAGE_SIZE),
+                    to_pfn(2*Config::SUPERPAGE_SIZE),
+                    to_pcnt(Config::PAGE_SHIFT)));
   print_node (node, frame);
 
   m.free (frame);
@@ -158,81 +208,81 @@ static void print_whole_tree(Mapping *node, const Mapdb::Frame& frame)
 
 void maphole()
 {
-  Mapdb m(s0, Page_number(1U << (32 - Config::SUPERPAGE_SHIFT)),
+  Mapdb m (s0, Mapping::Page(1U << (32 - Config::PAGE_SHIFT - page_sizes[0])),
       page_sizes, page_sizes_max);
 
-  Mapping *gf_map, *f_map, *son_map, *daughter_map, *a_map;
+  Mapping *gf_map, *f_map, *son_map, *daughter_map;
   Mapdb::Frame frame;
 
-  cout << "Looking up 4K node at physaddr=0" << endl;
-  assert (m.lookup (grandfather, Mem_space::Addr::create(0),
-                   Mem_space::Phys_addr::create(0), &gf_map, &frame));
+  cout << "[UTEST] Looking up 4K node at physaddr=0" << endl;
+  assert (m.lookup (grandfather, to_pfn(0),
+                   to_pfn(0), &gf_map, &frame));
   print_whole_tree (gf_map, frame);
 
-  cout << "Inserting father mapping" << endl;
-  f_map = m.insert (frame, gf_map, father, Mem_space::Addr::create(0),
-                   Mem_space::Phys_addr::create(0),
-                   Mem_space::Size::create(Config::PAGE_SIZE));
+  cout << "[UTEST] Inserting father mapping" << endl;
+  f_map = m.insert (frame, gf_map, father, to_pfn(0),
+                   to_pfn(0),
+                   to_pcnt(Config::PAGE_SHIFT));
   print_whole_tree (gf_map, frame);
   m.free(frame);
 
 
-  cout << "Looking up father at physaddr=0" << endl;
-  assert (m.lookup (father, Mem_space::Addr::create(0),
-                   Mem_space::Phys_addr::create(0), &f_map, &frame));
+  cout << "[UTEST] Looking up father at physaddr=0" << endl;
+  assert (m.lookup (father, to_pfn(0),
+                   to_pfn(0), &f_map, &frame));
   print_whole_tree (f_map, frame);
 
-  cout << "Inserting son mapping" << endl;
-  son_map = m.insert (frame, f_map, son, Mem_space::Addr::create(0),
-                     Mem_space::Phys_addr::create(0),
-                     Mem_space::Size::create(Config::PAGE_SIZE));
+  cout << "[UTEST] Inserting son mapping" << endl;
+  son_map = m.insert (frame, f_map, son, to_pfn(0),
+                     to_pfn(0),
+                     to_pcnt(Config::PAGE_SHIFT));
   print_whole_tree (f_map, frame);
   m.free(frame);
 
 
-  cout << "Looking up father at physaddr=0" << endl;
-  assert (m.lookup (father, Mem_space::Addr::create(0),
-                   Mem_space::Phys_addr::create(0), &f_map, &frame));
+  cout << "[UTEST] Looking up father at physaddr=0" << endl;
+  assert (m.lookup (father, to_pfn(0),
+                   to_pfn(0), &f_map, &frame));
   print_whole_tree (f_map, frame);
 
-  cout << "Inserting daughter mapping" << endl;
-  daughter_map = m.insert (frame, f_map, daughter, Mem_space::Addr::create(0),
-                          Mem_space::Phys_addr::create(0),
-                          Mem_space::Size::create(Config::PAGE_SIZE));
+  cout << "[UTEST] Inserting daughter mapping" << endl;
+  daughter_map = m.insert (frame, f_map, daughter, to_pfn(0),
+                          to_pfn(0),
+                          to_pcnt(Config::PAGE_SHIFT));
   print_whole_tree (f_map, frame);
   m.free(frame);
 
 
-  cout << "Looking up son at physaddr=0" << endl;
-  assert (m.lookup(son, Mem_space::Addr::create(0),
-                  Mem_space::Phys_addr::create(0), &son_map, &frame));
+  cout << "[UTEST] Looking up son at physaddr=0" << endl;
+  assert (m.lookup(son, to_pfn(0),
+                  to_pfn(0), &son_map, &frame));
   f_map = son_map->parent();
   print_whole_tree (son_map, frame);
 
-  cout << "Son has accident on return from disco" << endl;
+  cout << "[UTEST] Son has accident on return from disco" << endl;
   m.flush(frame, son_map, L4_map_mask::full(),
-         Mem_space::Addr::create(0),
-         Mem_space::Addr::create(Config::PAGE_SIZE));
+         to_pfn(0),
+         to_pfn(Config::PAGE_SIZE));
   m.free(frame);
 
-  cout << "Lost aunt returns from holidays" << endl;
-  assert (m.lookup (grandfather, Mem_space::Addr::create(0),
-                   Mem_space::Phys_addr::create(0), &gf_map, &frame));
+  cout << "[UTEST] Lost aunt returns from holidays" << endl;
+  assert (m.lookup (grandfather, to_pfn(0),
+                   to_pfn(0), &gf_map, &frame));
   print_whole_tree (gf_map, frame);
 
-  cout << "Inserting aunt mapping" << endl;
-  a_map = m.insert (frame, gf_map, aunt, Mem_space::Addr::create(0),
-                   Mem_space::Phys_addr::create(0),
-                   Mem_space::Size::create(Config::PAGE_SIZE));
+  cout << "[UTEST] Inserting aunt mapping" << endl;
+  assert (m.insert (frame, gf_map, aunt, to_pfn(0),
+                   to_pfn(0),
+                   to_pcnt(Config::PAGE_SHIFT)));
   print_whole_tree (gf_map, frame);
   m.free(frame);
 
-  cout << "Looking up daughter at physaddr=0" << endl;
-  assert (m.lookup(daughter, Mem_space::Addr::create(0),
-                  Mem_space::Phys_addr::create(0), &daughter_map, &frame));
+  cout << "[UTEST] Looking up daughter at physaddr=0" << endl;
+  assert (m.lookup(daughter, to_pfn(0),
+                  to_pfn(0), &daughter_map, &frame));
   print_whole_tree (daughter_map, frame);
   f_map = daughter_map->parent();
-  cout << "Father of daugther is " << (unsigned)(f_map->space()) << endl;
+  cout << "[UTEST] Father of daugther is " << *f_map->space() << endl;
 
   assert(f_map->space() == father);
 
@@ -242,67 +292,69 @@ void maphole()
 
 void flushtest()
 {
-  Mapdb m(s0, Page_number(1U << (32 - Config::SUPERPAGE_SHIFT)), page_sizes, page_sizes_max);
+  Mapdb m (s0, Mapping::Page(1U << (32 - Config::PAGE_SHIFT - page_sizes[0])),
+      page_sizes, page_sizes_max);
 
-  Mapping *gf_map, *f_map, *son_map, *a_map;
+  Mapping *gf_map, *f_map;
   Mapdb::Frame frame;
 
-  cout << "Looking up 4K node at physaddr=0" << endl;
-  assert (m.lookup (grandfather, Virt_addr(0), Phys_addr(0), &gf_map, &frame));
+  cout << "[UTEST] Looking up 4K node at physaddr=0" << endl;
+  assert (m.lookup (grandfather, to_pfn(0), to_pfn(0), &gf_map, &frame));
   print_whole_tree (gf_map, frame);
 
-  cout << "Inserting father mapping" << endl;
-  f_map = m.insert (frame, gf_map, father, Virt_addr(0), Phys_addr(0), Virt_size(Config::PAGE_SIZE));
+  cout << "[UTEST] Inserting father mapping" << endl;
+  f_map = m.insert (frame, gf_map, father, to_pfn(0), to_pfn(0), to_pcnt(Config::PAGE_SHIFT));
   print_whole_tree (gf_map, frame);
   m.free(frame);
 
 
-  cout << "Looking up father at physaddr=0" << endl;
-  assert (m.lookup (father, Virt_addr(0), Phys_addr(0), &f_map, &frame));
+  cout << "[UTEST] Looking up father at physaddr=0" << endl;
+  assert (m.lookup (father, to_pfn(0), to_pfn(0), &f_map, &frame));
   print_whole_tree (f_map, frame);
 
-  cout << "Inserting son mapping" << endl;
-  son_map = m.insert (frame, f_map, son, Virt_addr(0), Phys_addr(0), Virt_size(Config::PAGE_SIZE));
+  cout << "[UTEST] Inserting son mapping" << endl;
+  assert (m.insert (frame, f_map, son, to_pfn(0), to_pfn(0), to_pcnt(Config::PAGE_SHIFT)));
   print_whole_tree (f_map, frame);
   m.free(frame);
 
-  cout << "Lost aunt returns from holidays" << endl;
-  assert (m.lookup (grandfather, Virt_addr(0), Phys_addr(0), &gf_map, &frame));
+  cout << "[UTEST] Lost aunt returns from holidays" << endl;
+  assert (m.lookup (grandfather, to_pfn(0), to_pfn(0), &gf_map, &frame));
   print_whole_tree (gf_map, frame);
 
-  cout << "Inserting aunt mapping" << endl;
-  a_map = m.insert (frame, gf_map, aunt, Virt_addr(0), Phys_addr(0), Virt_size(Config::PAGE_SIZE));
+  cout << "[UTEST] Inserting aunt mapping" << endl;
+  assert (m.insert (frame, gf_map, aunt, to_pfn(0), to_pfn(0), to_pcnt(Config::PAGE_SHIFT)));
   print_whole_tree (gf_map, frame);
   m.free(frame);
 
-  cout << "Looking up father at physaddr=0" << endl;
-  assert (m.lookup(father, Virt_addr(0), Phys_addr(0), &f_map, &frame));
+  cout << "[UTEST] Looking up father at physaddr=0" << endl;
+  assert (m.lookup(father, to_pfn(0), to_pfn(0), &f_map, &frame));
   gf_map = f_map->parent();
   print_whole_tree (gf_map, frame);
 
-  cout << "father is killed by his new love" << endl;
-  m.flush(frame, f_map, L4_map_mask::full(), Virt_addr(0), Virt_addr(Config::PAGE_SIZE));
+  cout << "[UTEST] father is killed by his new love" << endl;
+  m.flush(frame, f_map, L4_map_mask::full(), to_pfn(0), to_pfn(Config::PAGE_SIZE));
   print_whole_tree (gf_map, frame);
   m.free(frame);
 
-  cout << "Try resurrecting the killed father again" << endl;
-  assert (! m.lookup(father, Virt_addr(0), Phys_addr(0), &f_map, &frame));
+  cout << "[UTEST] Try resurrecting the killed father again" << endl;
+  assert (! m.lookup(father, to_pfn(0), to_pfn(0), &f_map, &frame));
 
-  cout << "Resurrection is impossible, as it ought to be." << endl;
+  cout << "[UTEST] Resurrection is impossible, as it ought to be." << endl;
 }
 
 void multilevel ()
 {
-  size_t three_page_sizes[] = { 30 - Config::PAGE_SHIFT,
+  size_t page_sizes[] = { 30 - Config::PAGE_SHIFT,
       22 - Config::PAGE_SHIFT,
       0};
-  Mapdb m (s0, Page_number(4), three_page_sizes, 3);
+  Mapdb m (s0, Mapping::Page(1U << (42 - Config::PAGE_SHIFT - page_sizes[0])),
+      page_sizes, sizeof(page_sizes) / sizeof(page_sizes[0]));
 
   Mapping *node /* , *sub, *subsub */;
   Mapdb::Frame frame;
 
-  cout << "Looking up 0xd2000000" << endl;
-  assert (m.lookup (s0, Virt_addr(0xd2000000), Phys_addr(0xd2000000), &node, &frame));
+  cout << "[UTEST] Looking up 0xd2000000" << endl;
+  assert (m.lookup (s0, to_pfn(0xd2000000), to_pfn(0xd2000000), &node, &frame));
 
   print_node (node, frame);
 }
@@ -316,7 +368,6 @@ void multilevel ()
 #include "per_cpu_data_alloc.h"
 #include "static_init.h"
 #include "usermode.h"
-#include "vmem_alloc.h"
 
 class Timeout;
 
@@ -326,17 +377,16 @@ STATIC_INITIALIZER_P(init2, POST_CPU_LOCAL_INIT_PRIO);
 
 static void init()
 {
-  Usermode::init(0);
+  Usermode::init(Cpu_number::boot_cpu());
   Boot_info::init();
-  Kip_init::setup_ux();
-  Kmem_alloc::base_init();
   Kip_init::init();
+  Kmem_alloc::base_init();
   Kmem_alloc::init();
 
   // 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(Cpu_number::boot_cpu());
+  Per_cpu_data::run_ctors(Cpu_number::boot_cpu());
 
 }
 
@@ -344,29 +394,27 @@ static void init2()
 {
   Cpu::init_global_features();
   Config::init();
-  Kmem::init_mmu(Cpu::cpus.cpu(0));
-  printf("ha\n");
-  Vmem_alloc::init();
+  Kmem::init_mmu(Cpu::cpus.cpu(Cpu_number::boot_cpu()));
 }
 
 int main()
 {
   init_spaces();
-  cout << "Basic test" << endl;
+  cout << "[UTEST] Basic test" << endl;
   basic();
-  cout << "########################################" << endl;
+  cout << "[UTEST] ########################################" << endl;
 
-  cout << "Hole test" << endl;
+  cout << "[UTEST] Hole test" << endl;
   maphole();
-  cout << "########################################" << endl;
+  cout << "[UTEST] ########################################" << endl;
 
-  cout << "Flush test" << endl;
+  cout << "[UTEST] Flush test" << endl;
   flushtest();
-  cout << "########################################" << endl;
+  cout << "[UTEST] ########################################" << endl;
 
   cout << "Multilevel test" << endl;
   multilevel();
-  cout << "########################################" << endl;
+  cout << "[UTEST] ########################################" << endl;
 
   cerr << "OK" << endl;
   return(0);
diff --git a/kernel/fiasco/src/test/unit/mapdb_t.out.verify.vf b/kernel/fiasco/src/test/unit/mapdb_t.out.verify.vf
new file mode 100644 (file)
index 0000000..3d2be16
--- /dev/null
@@ -0,0 +1,123 @@
+[UTEST] Basic test
+[UTEST] Looking up 4M node at physaddr=0K
+[UTEST] space=s0 vaddr=0x0 size=0x400
+[UTEST] 
+[UTEST] Inserting submapping
+[UTEST] space=s0 vaddr=0x0 size=0x1
+[UTEST]  space=other vaddr=0x800 size=0x400 parent=s0 p.vaddr=0x400
+[UTEST] 
+[UTEST] Looking up 4M node at physaddr=8M
+[UTEST] space=s0 vaddr=0x800 size=0x400
+[UTEST] 
+[UTEST] Inserting submapping
+[UTEST] space=s0 vaddr=0x800 size=0x400
+[UTEST]  space=other vaddr=0x1000 size=0x400 parent=s0 p.vaddr=0x800
+[UTEST] 
+[UTEST] Get that mapping again
+[UTEST]  space=other vaddr=0x1000 size=0x400 parent=s0 p.vaddr=0x800
+[UTEST] 
+[UTEST] Inserting 4K submapping
+[UTEST] space=s0 vaddr=0x800 size=0x400
+[UTEST]  space=other vaddr=0x4 size=0x1 parent=s0 p.vaddr=0x2
+[UTEST]  space=client vaddr=0x3c00 size=0x400 parent=other p.vaddr=0x400000
+[UTEST] 
+[UTEST] ########################################
+[UTEST] Hole test
+[UTEST] Looking up 4K node at physaddr=0
+[UTEST] space=s0 vaddr=0x0 size=0x400
+[UTEST] 
+[UTEST] Inserting father mapping
+[UTEST] space=s0 vaddr=0x0 size=0x1
+[UTEST]  space=father vaddr=0x0 size=0x400 parent=s0 p.vaddr=0x0
+[UTEST] 
+[UTEST] Looking up father at physaddr=0
+[UTEST] space=s0 vaddr=0x0 size=0x1
+[UTEST]  space=father vaddr=0x0 size=0x1 parent=s0 p.vaddr=0x0
+[UTEST] 
+[UTEST] Inserting son mapping
+[UTEST] space=s0 vaddr=0x0 size=0x1
+[UTEST]  space=father vaddr=0x0 size=0x1 parent=s0 p.vaddr=0x0
+[UTEST]   space=son vaddr=0x0 size=0x1 parent=father p.vaddr=0x0
+[UTEST] 
+[UTEST] Looking up father at physaddr=0
+[UTEST] space=s0 vaddr=0x0 size=0x1
+[UTEST]  space=father vaddr=0x0 size=0x1 parent=s0 p.vaddr=0x0
+[UTEST]   space=son vaddr=0x0 size=0x1 parent=father p.vaddr=0x0
+[UTEST] 
+[UTEST] Inserting daughter mapping
+[UTEST] space=s0 vaddr=0x0 size=0x1
+[UTEST]  space=father vaddr=0x0 size=0x1 parent=s0 p.vaddr=0x0
+[UTEST]   space=son vaddr=0x0 size=0x1 parent=father p.vaddr=0x0
+[UTEST]   space=daughter vaddr=0x0 size=0x1 parent=father p.vaddr=0x0
+[UTEST] 
+[UTEST] Looking up son at physaddr=0
+[UTEST] space=s0 vaddr=0x0 size=0x1
+[UTEST]  space=father vaddr=0x0 size=0x1 parent=s0 p.vaddr=0x0
+[UTEST]   space=son vaddr=0x0 size=0x1 parent=father p.vaddr=0x0
+[UTEST]   space=daughter vaddr=0x0 size=0x1 parent=father p.vaddr=0x0
+[UTEST] 
+[UTEST] Son has accident on return from disco
+[UTEST] Lost aunt returns from holidays
+[UTEST] space=s0 vaddr=0x0 size=0x1
+[UTEST]  space=father vaddr=0x0 size=0x1 parent=s0 p.vaddr=0x0
+[UTEST]   space=daughter vaddr=0x0 size=0x400 parent=father p.vaddr=0x0
+[UTEST] 
+[UTEST] Inserting aunt mapping
+[UTEST] space=s0 vaddr=0x0 size=0x1
+[UTEST]  space=father vaddr=0x0 size=0x1 parent=s0 p.vaddr=0x0
+[UTEST]   space=daughter vaddr=0x0 size=0x1 parent=father p.vaddr=0x0
+[UTEST]  space=aunt vaddr=0x0 size=0x400 parent=s0 p.vaddr=0x0
+[UTEST] 
+[UTEST] Looking up daughter at physaddr=0
+[UTEST] space=s0 vaddr=0x0 size=0x1
+[UTEST]  space=father vaddr=0x0 size=0x1 parent=s0 p.vaddr=0x0
+[UTEST]   space=daughter vaddr=0x0 size=0x1 parent=father p.vaddr=0x0
+[UTEST]  space=aunt vaddr=0x0 size=0x1 parent=s0 p.vaddr=0x0
+[UTEST] 
+[UTEST] Father of daugther is father
+[UTEST] ########################################
+[UTEST] Flush test
+[UTEST] Looking up 4K node at physaddr=0
+[UTEST] space=s0 vaddr=0x0 size=0x400
+[UTEST] 
+[UTEST] Inserting father mapping
+[UTEST] space=s0 vaddr=0x0 size=0x1
+[UTEST]  space=father vaddr=0x0 size=0x400 parent=s0 p.vaddr=0x0
+[UTEST] 
+[UTEST] Looking up father at physaddr=0
+[UTEST] space=s0 vaddr=0x0 size=0x1
+[UTEST]  space=father vaddr=0x0 size=0x1 parent=s0 p.vaddr=0x0
+[UTEST] 
+[UTEST] Inserting son mapping
+[UTEST] space=s0 vaddr=0x0 size=0x1
+[UTEST]  space=father vaddr=0x0 size=0x1 parent=s0 p.vaddr=0x0
+[UTEST]   space=son vaddr=0x0 size=0x1 parent=father p.vaddr=0x0
+[UTEST] 
+[UTEST] Lost aunt returns from holidays
+[UTEST] space=s0 vaddr=0x0 size=0x1
+[UTEST]  space=father vaddr=0x0 size=0x1 parent=s0 p.vaddr=0x0
+[UTEST]   space=son vaddr=0x0 size=0x400 parent=father p.vaddr=0x0
+[UTEST] 
+[UTEST] Inserting aunt mapping
+[UTEST] space=s0 vaddr=0x0 size=0x1
+[UTEST]  space=father vaddr=0x0 size=0x1 parent=s0 p.vaddr=0x0
+[UTEST]   space=son vaddr=0x0 size=0x1 parent=father p.vaddr=0x0
+[UTEST]  space=aunt vaddr=0x0 size=0x400 parent=s0 p.vaddr=0x0
+[UTEST] 
+[UTEST] Looking up father at physaddr=0
+[UTEST] space=s0 vaddr=0x0 size=0x1
+[UTEST]  space=father vaddr=0x0 size=0x1 parent=s0 p.vaddr=0x0
+[UTEST]   space=son vaddr=0x0 size=0x1 parent=father p.vaddr=0x0
+[UTEST]  space=aunt vaddr=0x0 size=0x1 parent=s0 p.vaddr=0x0
+[UTEST] 
+[UTEST] father is killed by his new love
+[UTEST] space=s0 vaddr=0x0 size=0x1
+[UTEST]  space=aunt vaddr=0x0 size=0x1 parent=s0 p.vaddr=0x0
+[UTEST] 
+[UTEST] Try resurrecting the killed father again
+[UTEST] Resurrection is impossible, as it ought to be.
+[UTEST] ########################################
+[UTEST] Looking up 0xd2000000
+[UTEST] space=s0 vaddr=0xc0000 size=0x40000
+[UTEST] 
+[UTEST] ########################################
index f4ebd75c468390a86d3f1390e1501c47e9e21c70..e101fff9f6dd5585b8a772d2c07f1c2a4d44c90b 100644 (file)
@@ -41,4 +41,11 @@ enum Address_vals
 
 typedef Unsigned64              Cpu_time;
 
+#ifdef __cplusplus
+
+#include <cxx/cxx_int>
+typedef cxx::int_type<Unsigned32, struct Cpu_phys_id_t> Cpu_phys_id;
+
+#endif
+
 #endif
index 7b5fa1b6b47b86b6c0476aa6401b50362dd09406..17e8007c70ba7ca64decfbc3390f939c8ea6ee3d 100644 (file)
@@ -41,4 +41,12 @@ enum Address_vals
 
 typedef Unsigned64             Cpu_time;
 
+#ifdef __cplusplus
+
+#include <cxx/cxx_int>
+
+typedef cxx::int_type<unsigned char, struct Cpu_phys_id_t> Cpu_phys_id;
+
+#endif
+
 #endif // TYPES_ARCH_H__
index 685519b7a86a94bb6c67a8fa85b68b86839e9c0c..e601c2f3c815671d2a4520b7fc63f62106d1f0b8 100644 (file)
@@ -40,5 +40,11 @@ enum Address_vals
 
 typedef Unsigned64 Cpu_time;
 
+#ifdef __cplusplus
+
+#include <cxx/cxx_int>
+typedef cxx::int_type<Unsigned32, struct Cpu_phys_id_t> Cpu_phys_id;
+
+#endif
 
 #endif
index 7beae91a19faf1a952493d15b8d72f2851bcb59f..bf12ea4e708d68f564c9437252ee1595cb45b66c 100644 (file)
@@ -40,5 +40,11 @@ enum Address_vals
 
 typedef Unsigned64 Cpu_time;
 
+#ifdef __cplusplus
+
+#include <cxx/cxx_int>
+typedef cxx::int_type<unsigned char, struct Cpu_phys_id_t> Cpu_phys_id;
+
+#endif
 
 #endif
index fd9cc990ed269a8c385ebf166365d16e3c356f02..3f6ae2aedfa9d513e3629362488d04a9dbeb08e2 100644 (file)
@@ -40,5 +40,12 @@ enum Address_vals
 
 typedef Unsigned64 Cpu_time;
 
+#ifdef __cplusplus
+
+#include <cxx/cxx_int>
+
+typedef cxx::int_type<unsigned char, struct Cpu_phys_id_t> Cpu_phys_id;
+
+#endif
 
 #endif
index 8207e58ae4a9005706ceda65b8bd3161e8a4a166..297ee75a34cb1729a5ee4e652d4f6a8439d1a30b 100644 (file)
@@ -7,7 +7,8 @@
 
 #ifdef __cplusplus
 
-#include <type_traits>
+#include <cxx/cxx_int>
+#include <cxx/type_traits>
 #include <new>
 
 template< typename a, typename b > inline
@@ -69,138 +70,117 @@ private:
   mutable char __attribute__((aligned(sizeof(Mword)*2))) _i[sizeof(T)];
 };
 
+typedef cxx::int_type<unsigned, struct Order_t> Order;
 
-template< typename VALUE, typename TARGET >
-class Number
-{
-public:
-  typedef VALUE Value;
-  typedef TARGET Target;
-  struct Type_conversion_error;
-
-protected:
-  Number() {}
-  explicit Number(Value v) : _v(v) {}
-
-public:
-
-  static Target create(Value v)
-  { return Target(v); }
-
-  Target operator = (Target o)
-  { _v = o._v; return *static_cast<Target*>(this); }
-
-  Value value() const { return _v; }
-  Value value() const volatile { return _v; }
-  void set_value(Value v) { _v = v; }
-
-  bool operator < (Target const &o) const { return _v < o._v; }
-  bool operator > (Target const &o) const { return _v > o._v; }
-  bool operator <= (Target const &o) const { return _v <= o._v; }
-  bool operator >= (Target const &o) const { return _v >= o._v; }
-  bool operator == (Target const &o) const { return _v == o._v; }
-  bool operator != (Target const &o) const { return _v != o._v; }
-
-  operator Type_conversion_error const * () const
-  { return (Type_conversion_error const *)_v; }
-
-  Target operator | (Target const &o) const
-  { return Target(_v | o._v); }
+namespace Addr {
 
-  Target operator & (Target const &o) const
-  { return Target(_v & o._v); }
-
-  Target operator + (Target const &o) const
-  { return Target(_v + o._v); }
+template< int SHIFT >
+struct Order : cxx::int_base<unsigned, Order<SHIFT> >, cxx::int_diff_ops<Order<SHIFT> >
+{
+  typedef cxx::int_base<unsigned, Order<SHIFT> > Base_class;
+  Order() = default;
+  explicit Order<SHIFT>(typename Base_class::Value v) : Base_class(v) {}
+};
 
-  Target operator - (Target const &o) const
-  { return Target(_v - o._v); }
 
-  Target operator << (unsigned long s) const
-  { return Target(_v << s); }
+template< int SHIFT, typename T >
+class Addr_val
+: public cxx::int_base< Address, T >,
+  public cxx::int_null_chk<T>,
+  public cxx::int_shift_ops<T, Order<SHIFT> >
+{
+private:
+  typedef cxx::int_base< Address, T > B;
 
-  Target operator >> (unsigned long s) const
-  { return Target(_v >> s); }
+  static Address __shift(Address x, int oshift)
+  { return ((SHIFT - oshift) >= 0) ? (x << (SHIFT - oshift)) : (x >> (oshift - SHIFT)); }
 
-  void operator += (Target const &o) { _v += o._v; }
-  void operator -= (Target const &o) { _v -= o._v; }
-  void operator <<= (unsigned long s) { _v <<= s; }
-  void operator >>= (unsigned long s) { _v >>= s; }
+public:
+  enum { Shift = SHIFT };
 
-  Target operator ++ () { return Target(++_v); }
-  Target operator ++ (int) { return Target(_v++); }
+  template< int OSHIFT >
+  Addr_val(Addr_val<OSHIFT, T> o)
+  : B(__shift(Addr_val<OSHIFT, T>::val(o), OSHIFT))
+  {}
 
-  Target operator -- () { return Target(--_v); }
-  Target operator -- (int) { return Target(_v--); }
+  explicit Addr_val(Address a) : B(a) {}
 
-  Target trunc(Target const &size) const
-  { return Target(_v & ~(size._v - 1)); }
+  //explicit Addr_val(::Order o) : B(Address(1) << (Order::val(o) - ARCH_PAGE_SHIFT + SHIFT)) {}
 
-  Target offset(Target const &size) const
-  { return Target(_v & (size._v - 1)); }
+  Addr_val(Addr_val const volatile &o) : B(o._v) {}
+  Addr_val(Addr_val const &)  = default;
+  Addr_val() = default;
 
-  static Target from_shift(unsigned char shift)
-  {
-    if (shift >= (int)sizeof(Value) * 8)
-      return Target(Value(1) << Value((sizeof(Value) * 8 - 1)));
-    return Target(Value(1) << Value(shift));
-  }
+  template< int OSHIFT >
+  T operator << (Order<OSHIFT> const &o) const
+  { return T(this->_v << (SHIFT + Order<OSHIFT>::val(o) - OSHIFT)); }
 
 protected:
-  Value _v;
+  Addr_val(typename B::Value v, int oshift) : B(__shift(v, oshift)) {}
 };
 
 template< int SHIFT >
-class Page_addr : public Number<Address, Page_addr<SHIFT> >
+struct Diff
+: public Addr_val< SHIFT, Diff<SHIFT> >,
+  cxx::int_diff_ops<Diff<SHIFT> >,
+  cxx::int_bit_ops<Diff<SHIFT> >
 {
-private:
-  typedef Number<Address, Page_addr<SHIFT> > B;
-
-  template< int T >
-  class Itt
-  {};
-
-  template< int SH >
-  Address __shift(Address x, Itt<true>) { return x << SH; }
-
-  template< int SH >
-  Address __shift(Address x, Itt<false>) { return x >> (-SH); }
-
-public:
-  enum { Shift = SHIFT };
+  typedef Addr_val< SHIFT, Diff<SHIFT> > Base_class;
+  Diff() = default;
+  Diff(Diff const &) = default;
+  explicit Diff(Address a) : Base_class(a) {}
+  //Diff(::Order o) : Base_class(o) {}
 
   template< int OSHIFT >
-  Page_addr(Page_addr<OSHIFT> o)
-  : B(__shift<Shift-OSHIFT>(o.value(), Itt<(OSHIFT < Shift)>()))
-  {}
-
-  explicit Page_addr(Address a) : B(a) {}
+  Diff(Diff<OSHIFT> o) : Base_class(Diff<OSHIFT>::val(o), OSHIFT) {}
+};
 
-  Page_addr(Page_addr const volatile &o) : B(o.value()) {}
-  Page_addr(Page_addr const &o) : B(o.value()) {}
+template< int SHIFT >
+struct Addr
+: public Addr_val< SHIFT, Addr<SHIFT> >,
+  cxx::int_diff_ops<Addr<SHIFT>, Diff<SHIFT> >,
+  cxx::int_bit_ops<Addr<SHIFT>, Diff<SHIFT> >
+{
+  typedef Addr_val< SHIFT, Addr<SHIFT> > Base_class;
+  Addr() = default;
+  Addr(Addr const &) = default;
+  explicit Addr(Address a) : Base_class(a) {}
 
-  Page_addr() {}
+  template< int OSHIFT >
+  Addr(Addr<OSHIFT> o) : Base_class(Addr<OSHIFT>::val(o), OSHIFT) {}
 };
 
-class Virt_addr : public Page_addr<ARCH_PAGE_SHIFT>
+} // namespace Addr
+
+class Virt_addr
+: public Addr::Addr<ARCH_PAGE_SHIFT>
 {
 public:
   template< int OSHIFT >
-  Virt_addr(Page_addr<OSHIFT> o) : Page_addr<ARCH_PAGE_SHIFT>(o) {}
+  Virt_addr(typename ::Addr::Addr<OSHIFT> const &o) : ::Addr::Addr<ARCH_PAGE_SHIFT>(o) {}
+
+  template< int OSHIFT >
+  Virt_addr(typename ::Addr::Addr<OSHIFT>::Type const &o) : ::Addr::Addr<ARCH_PAGE_SHIFT>(o) {}
+
+  explicit Virt_addr(Address a) : ::Addr::Addr<ARCH_PAGE_SHIFT>(a) {}
+  explicit Virt_addr(int a) : ::Addr::Addr<ARCH_PAGE_SHIFT>(a) {}
+  explicit Virt_addr(unsigned a) : ::Addr::Addr<ARCH_PAGE_SHIFT>(a) {}
+  explicit Virt_addr(long a) : ::Addr::Addr<ARCH_PAGE_SHIFT>(a) {}
 
-  explicit Virt_addr(unsigned int a) : Page_addr<ARCH_PAGE_SHIFT>(a) {}
-  explicit Virt_addr(int a) : Page_addr<ARCH_PAGE_SHIFT>(a) {}
-  explicit Virt_addr(long int a) : Page_addr<ARCH_PAGE_SHIFT>(a) {}
-  explicit Virt_addr(unsigned long a) : Page_addr<ARCH_PAGE_SHIFT>(a) {}
-  Virt_addr(void *a) : Page_addr<ARCH_PAGE_SHIFT>(Address(a)) {}
+  Virt_addr(void *a) : ::Addr::Addr<ARCH_PAGE_SHIFT>(Address(a)) {}
 
-  Virt_addr() {}
+  Virt_addr() = default;
 };
 
-typedef Page_addr<ARCH_PAGE_SHIFT> Virt_size;
+typedef Addr::Diff<ARCH_PAGE_SHIFT> Virt_size;
+typedef Addr::Order<ARCH_PAGE_SHIFT> Virt_order;
 
-typedef Page_addr<0> Page_number;
-typedef Page_number Page_count;
+typedef Addr::Addr<0> Page_number;
+typedef Addr::Diff<0> Page_count;
+//typedef Addr::Order<0> Page_order;
+//
+typedef Addr::Addr<ARCH_PAGE_SHIFT> Phys_mem_addr;
+typedef Addr::Diff<ARCH_PAGE_SHIFT> Phys_mem_size;
 
 template<typename T>
 struct Simple_ptr_policy
@@ -302,6 +282,18 @@ struct User
 {
   typedef Smart_ptr<T, Simple_ptr_policy, User_ptr_discr> Ptr;
 };
+
+struct Cpu_number : cxx::int_type_order_base<unsigned, Cpu_number, Order>
+{
+  Cpu_number() = default;
+  explicit Cpu_number(unsigned n) : cxx::int_type_order_base<unsigned, Cpu_number, Order>(n) {}
+
+  static Cpu_number boot_cpu() { return Cpu_number(0); }
+  static Cpu_number first()    { return Cpu_number(0); }
+  static Cpu_number second()   { return Cpu_number(1); }
+  static Cpu_number nil()      { return Cpu_number(~0); }
+};
+
 #endif
 
 /// standard size type
index 0dc19295933b48da9839ea6072abea0559037e23..423b7939f9be3cf920efb8d47ccf9c8f183c69c3 100644 (file)
@@ -41,4 +41,11 @@ enum Address_vals
 
 typedef Unsigned64             Cpu_time;
 
+#ifdef __cplusplus
+
+#include <cxx/cxx_int>
+typedef cxx::int_type<Unsigned32, struct Cpu_phys_id_t> Cpu_phys_id;
+
+#endif
+
 #endif
index cc8a266ff302d1d380839b9929a8d3f1b80ec349..614645ebec432510df3a3d8a9456e82ce24097dc 100644 (file)
@@ -1,8 +1,8 @@
 VERSION = 3
-PATCHLEVEL = 7
+PATCHLEVEL = 8
 SUBLEVEL = 0
 EXTRAVERSION =
-NAME = Terrified Chipmunk
+NAME = Unicycling Gorilla
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
@@ -124,7 +124,7 @@ $(if $(KBUILD_OUTPUT),, \
 PHONY += $(MAKECMDGOALS) sub-make
 
 $(filter-out _all sub-make $(CURDIR)/Makefile, $(MAKECMDGOALS)) _all: sub-make
-       $(Q)@:
+       @:
 
 sub-make: FORCE
        $(if $(KBUILD_VERBOSE:1=),@)$(MAKE) -C $(KBUILD_OUTPUT) \
@@ -169,7 +169,7 @@ SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
                                  -e s/arm.*/arm/ -e s/sa110/arm/ \
                                  -e s/s390x/s390/ -e s/parisc64/parisc/ \
                                  -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
-                                 -e s/sh[234].*/sh/ )
+                                 -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ )
 
 # Cross compiling and selecting different set of gcc/bin-utils
 # ---------------------------------------------------------------------------
@@ -981,6 +981,12 @@ _modinst_post: _modinst_
        $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.fwinst obj=firmware __fw_modinst
        $(call cmd,depmod)
 
+ifeq ($(CONFIG_MODULE_SIG), y)
+PHONY += modules_sign
+modules_sign:
+       $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modsign
+endif
+
 else # CONFIG_MODULES
 
 # Modules not configured
@@ -1021,11 +1027,14 @@ clean: rm-dirs  := $(CLEAN_DIRS)
 clean: rm-files := $(CLEAN_FILES)
 clean-dirs      := $(addprefix _clean_, . $(vmlinux-alldirs) Documentation samples)
 
-PHONY += $(clean-dirs) clean archclean
+PHONY += $(clean-dirs) clean archclean vmlinuxclean
 $(clean-dirs):
        $(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
 
-clean: archclean
+vmlinuxclean:
+       $(Q)$(CONFIG_SHELL) $(srctree)/scripts/link-vmlinux.sh clean
+
+clean: archclean vmlinuxclean
 
 # mrproper - Delete all generated files, including .config
 #
@@ -1252,7 +1261,6 @@ scripts: ;
 endif # KBUILD_EXTMOD
 
 clean: $(clean-dirs)
-       $(Q)$(CONFIG_SHELL) $(srctree)/scripts/link-vmlinux.sh clean
        $(call cmd,rmdirs)
        $(call cmd,rmfiles)
        @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \
index 3d87ce199d0032571691fc5e715282f2d832f85b..7c04e27841d5144545c2dd9323ff4f01c1071e55 100644 (file)
@@ -1,3 +1,3 @@
 
-kconfig taken from vanilla Linux 3.7, and slightly patched.
+kconfig taken from vanilla Linux 3.8, and slightly patched.
 
index 0be6f110cce79be4c4acd2f4dbf4ac2ce7d24057..bdf42fdf64c9adb0095a1ff0ad3437499d0ba87c 100644 (file)
@@ -266,6 +266,9 @@ $(obj)/%.dtb.S: $(obj)/%.dtb
 quiet_cmd_dtc = DTC     $@
 cmd_dtc = $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 $(DTC_FLAGS) -d $(depfile) $<
 
+$(obj)/%.dtb: $(src)/%.dts FORCE
+       $(call if_changed_dep,dtc)
+
 # Bzip2
 # ---------------------------------------------------------------------------
 
diff --git a/l4/mk/platforms/rpi_a.conf b/l4/mk/platforms/rpi_a.conf
new file mode 100644 (file)
index 0000000..3d8869d
--- /dev/null
@@ -0,0 +1,4 @@
+PLATFORM_NAME        = "Raspberry Pi, Model A"
+PLATFORM_ARCH        = arm
+PLATFORM_RAM_BASE    = 0x0
+PLATFORM_RAM_SIZE_MB = 256
diff --git a/l4/mk/platforms/rpi_b.conf b/l4/mk/platforms/rpi_b.conf
new file mode 100644 (file)
index 0000000..94ca692
--- /dev/null
@@ -0,0 +1,4 @@
+PLATFORM_NAME        = "Raspberry Pi, Model B"
+PLATFORM_ARCH        = arm
+PLATFORM_RAM_BASE    = 0x0
+PLATFORM_RAM_SIZE_MB = 512
diff --git a/l4/mk/platforms/rv_vexpress_a15.conf b/l4/mk/platforms/rv_vexpress_a15.conf
new file mode 100644 (file)
index 0000000..fc1e2e7
--- /dev/null
@@ -0,0 +1,4 @@
+PLATFORM_NAME        = "ARM Versatile Express"
+PLATFORM_ARCH        = arm
+PLATFORM_RAM_BASE    = 0x80000000
+PLATFORM_RAM_SIZE_MB = 256
index 6f1ce94246c0c95ad6f4c2dac3bbb77e92c08a11..dcc91230327e62ebe6d4219fd1ed1e2b4a66beed 100644 (file)
@@ -37,7 +37,7 @@ _start:
         * position we're linked to.
         */
        adr     r4, run         /* Running version */
-        ldr     r5, .LCrun      /* supposed to be version */
+       ldr     r5, .LCrun      /* supposed to be version */
        cmp     r4, r5          /* If equal ... */
        beq     run             /* ... go to run */
 
@@ -70,11 +70,11 @@ _start:
        str     r3, [r0], #4
        ldr     pc, .LCstart_bin
 
-3:     ldr     r6, [r4], #4
-32:     str     r6, [r5], #4
-33:     cmp     r5, r7
-34:     blt     3b
-35:     mov    pc, r9
+3:     ldr     r6, [r4], #4
+32:    str     r6, [r5], #4
+33:    cmp     r5, r7
+34:    blt     3b
+35:    mov     pc, r9
 
        /* Copy behind, copy backwards */
 move_behind:
@@ -83,7 +83,7 @@ move_behind:
        str     r6, [r7, #-4]!  /* Put bytes */
        cmp     r5, r7
        blt     3b
-       ldr     pc, .LCrun
+       ldr     pc, .LCrun
 
 
 .LCrun:       .word run
@@ -103,8 +103,16 @@ run:
        cmp     r0, r9
        beq     do_cpuid
 
-       mov     r9, #0xc00
-       orr     r9, #0x009
+        mov     r3, #0xc00
+       orr     r9, r3, #0x00f
+       cmp     r0, r9
+       beq     do_cpuid
+
+       orr     r9, r3, #0x007
+       cmp     r0, r9
+       beq     do_cpuid
+
+       orr     r9, r3, #0x009
        cmp     r0, r9
        bne     do_bootstrap               /* None matched, normal startup */
 
@@ -126,49 +134,68 @@ do_cpuid:
        orr r0, #0xd3
        msr cpsr_c, r0
 
-#if defined(PLATFORM_TYPE_rv) || defined(PLATFORM_TYPE_rv_pbx) || defined(PLATFORM_TYPE_rv_vexpress)
+#if defined(PLATFORM_TYPE_rv) || defined(PLATFORM_TYPE_rv_pbx) || \
+    defined(PLATFORM_TYPE_rv_vexpress) || defined(PLATFORM_TYPE_rv_vexpress_a15)
+
        // enable GIC CPU interface + prio mask for IRQs
+       mrc     p15, 0, r0, c0, c0, 0    // r0: cpu-id
+       and     r0, r0, #0x70
+       cmp     r0, #0x70
 
        // get board ID and retrieve MPCore-base from table
-       mov     r5, #0x10000000
-       ldr     r5, [r5]
+       movne   r7, #0x10000000
+       moveq   r7, #0x00010000
+       orreq   r7, #0x1c000000
+       ldr     r5, [r7]
        bic     r5, #0xff
-       adr     r6, .Lmpcore_base_table
+
+       adr     r6, .Lboard_data_table
 2:
        ldr     r4, [r6]
        cmp     r4, #0
-       cmpne   r4, r5
-       ldreq   r4, [r6, #4]
        beq     3f
-       add     r6, #8
+       cmp     r4, r5
+       bne     4f
+
+       ldr     r3, [r6, #4]
+       cmp     r0, r3
+       beq     3f
+       cmp     r3, #0
+       beq     3f
+4:     add     r6, #12
        b       2b
 
 3:
-       add     r4, r4, #0x100
+       ldr     r4, [r6, #8]
        mov     r0, #0x1
        str     r0, [r4, #0]
        mov     r0, #0xf0
        str     r0, [r4, #4]
 
 1:
-       mov     r5, #0x10000000
-       ldr     r6, [r5, #0x30]
+       ldr     r6, [r7, #0x30]
        cmp     r6, #0
        movne   pc, r6
-       .inst 0xe320f003 /* wfi */
+       .inst   0xe320f003 /* wfi */
        ldr     r0, [r4, #12]
        str     r0, [r4, #16]
        b       1b
 
-.Lmpcore_base_table:
+.Lboard_data_table:
        /* VExpress */
        .word   0x1190f500 /* Board ID */
-       .word   0x1e000000 /* MPCore base */
+       .word   0x00000070 /* CPU ID */
+       .word   0x2c002000 /* MPCore base */
+
+       .word   0x1190f500 /* Board ID */
+       .word   0x00000000 /* CPU ID */
+       .word   0x1e000100 /* MPCore base */
 
        /* Default value (with #0) must come last! */
        /* Realview */
        .word   0
-       .word   0x1f000000
+       .word   0
+       .word   0x1f000100
 
 #else
 1:     .word 0xe320f003 /* wfi */
@@ -176,11 +203,11 @@ do_cpuid:
 #endif
 
 do_bootstrap:
-       ldr     r3, .LCcrt0_tramppage      /* Load address of tramppage var */
-       str     sp, [r3]                   /* Store SP in variable          */
-       ldr     sp, .LCstack
+       ldr     r3, .LCcrt0_tramppage      /* Load address of tramppage var */
+       str     sp, [r3]                   /* Store SP in variable          */
+       ldr     sp, .LCstack
 
-       mov     r0, r2                     /* ATAG pointer */
+       mov     r0, r2                     /* ATAG pointer */
        bl      __main
 1:     b       1b
 
@@ -194,7 +221,7 @@ crt0_tramppage:
        .space 4
 
        .global crt0_stack_low
-        .align 3
+       .align 3
 crt0_stack_low:
        .space  8192
        .global crt0_stack_high
index 7da83ff915f9a7dd02d4ade99429ed07ff468ba5..6e5cf757f8456b059bbfa2081e9cc41fc119f580 100644 (file)
@@ -66,37 +66,12 @@ TARGET              := $(od)$(BOOTSTRAP_ELF_NAME)
 TARGET_BIN      = $(od)$(BOOTSTRAP_ELF_NAME)
 MODE            = lib
 
-SUPPORT_CC_arm-sa1000      := platform/sa1000.cc
-SUPPORT_CC_arm-pxa         := platform/pxa.cc
-SUPPORT_CC_arm-integrator  := platform/integrator.cc
-SUPPORT_CC_arm-rv          := platform/rv.cc
-SUPPORT_CC_arm-rv_pbx      := platform/rv.cc
-SUPPORT_CC_arm-rv_vexpress := platform/rv_vexpress.cc
-SUPPORT_CC_arm-omap3evm    := platform/omap.cc
-SUPPORT_CC_arm-omap3_am33xx:= platform/omap.cc
-SUPPORT_CC_arm-beagleboard := platform/omap.cc
-SUPPORT_CC_arm-pandaboard  := platform/omap.cc
-SUPPORT_CC_arm-tegra2      := platform/tegra2.cc
-SUPPORT_CC_arm-imx21       := platform/imx.cc
-SUPPORT_CC_arm-imx35       := platform/imx.cc
-SUPPORT_CC_arm-imx51       := platform/imx.cc
-SUPPORT_CC_arm-imx6        := platform/imx.cc
-SUPPORT_CC_arm-om          := platform/om.cc
-SUPPORT_CC_arm-kirkwood    := platform/kirkwood.cc
-DEFAULT_RELOC_arm-imx21    := 0x00200000  # because of blob
+include $(SRC_DIR)/Makefile.platform
 
 ifneq ($(DEFAULT_RELOC_arm-$(PLATFORM_TYPE)),)
 DEFAULT_RELOC_arm         := $(DEFAULT_RELOC_arm-$(PLATFORM_TYPE))
 endif
 
-SUPPORT_CC_ppc32-mpc5200  := platform/mpc5200.cc
-
-SUPPORT_CC_x86-pc         := platform/x86_pc.cc
-
-SUPPORT_CC_amd64-pc       := platform/x86_pc.cc
-
-SUPPORT_CC_sparc-leon3    := platform/leon3.cc
-
 SRC_C          += exec.c module.c
 SRC_CC         += region.cc startup.cc init_kip_v2.cc init_kip_v4.cc \
                    libc_support+.cc patch.cc koptions.cc
diff --git a/l4/pkg/bootstrap/server/src/Makefile.platform b/l4/pkg/bootstrap/server/src/Makefile.platform
new file mode 100644 (file)
index 0000000..a84a1ca
--- /dev/null
@@ -0,0 +1,33 @@
+
+# ARM platforms
+SUPPORT_CC_arm-sa1000          := platform/sa1000.cc
+SUPPORT_CC_arm-pxa             := platform/pxa.cc
+SUPPORT_CC_arm-integrator      := platform/integrator.cc
+SUPPORT_CC_arm-rv              := platform/rv.cc
+SUPPORT_CC_arm-rv_pbx          := platform/rv.cc
+SUPPORT_CC_arm-rv_vexpress     := platform/rv_vexpress.cc
+SUPPORT_CC_arm-rv_vexpress_a15 := platform/rv_vexpress.cc
+SUPPORT_CC_arm-omap3evm        := platform/omap.cc
+SUPPORT_CC_arm-omap3_am33xx    := platform/omap.cc
+SUPPORT_CC_arm-beagleboard     := platform/omap.cc
+SUPPORT_CC_arm-pandaboard      := platform/omap.cc
+SUPPORT_CC_arm-tegra2          := platform/tegra2.cc
+SUPPORT_CC_arm-imx21           := platform/imx.cc
+DEFAULT_RELOC_arm-imx21        := 0x00200000  # because of blob
+SUPPORT_CC_arm-imx35           := platform/imx.cc
+SUPPORT_CC_arm-imx51           := platform/imx.cc
+SUPPORT_CC_arm-imx6            := platform/imx.cc
+SUPPORT_CC_arm-om              := platform/om.cc
+SUPPORT_CC_arm-kirkwood        := platform/kirkwood.cc
+SUPPORT_CC_arm-rpi_a           := platform/rpi.cc
+SUPPORT_CC_arm-rpi_b           := platform/rpi.cc
+
+# PPC
+SUPPORT_CC_ppc32-mpc5200       := platform/mpc5200.cc
+
+# Sparc
+SUPPORT_CC_sparc-leon3         := platform/leon3.cc
+
+# x86
+SUPPORT_CC_x86-pc              := platform/x86_pc.cc
+SUPPORT_CC_amd64-pc            := platform/x86_pc.cc
diff --git a/l4/pkg/bootstrap/server/src/platform/exynos.cc b/l4/pkg/bootstrap/server/src/platform/exynos.cc
new file mode 100644 (file)
index 0000000..68f9616
--- /dev/null
@@ -0,0 +1,42 @@
+/*!
+ * \file
+ * \brief  Support for Exynos platforms
+ *
+ * \author Adam Lackorznynski <adam@os.inf.tu-dresden.de>
+ *
+ */
+/*
+ * (c) 2011-2013 Author(s)
+ *     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.
+ */
+
+#include "support.h"
+#include <l4/drivers/uart_s3c2410.h>
+
+#include <cstdio>
+
+namespace {
+class Platform_arm_exynos : public Platform_single_region_ram
+{
+public:
+  bool probe() { return true; }
+
+  void init()
+  {
+    static L4::Uart_s5pv210 _uart;
+    unsigned uart_nr = 2;
+    unsigned long uart_base = 0x12c00000;
+    unsigned long uart_offset = 0x10000;
+
+    static L4::Io_register_block_mmio r(uart_base + uart_nr * uart_offset);
+    _uart.startup(&r);
+    set_stdio_uart(&_uart);
+  }
+};
+}
+
+REGISTER_PLATFORM(Platform_arm_exynos);
index 9da67d7d25fb436cabc0cfc1f4625249c05ba086..a0792efc572db4d3b1fac6f7f31e2b84b7fe53ee 100644 (file)
@@ -3,7 +3,7 @@
  * \brief  Support for the i.MX platform
  *
  * \date   2008-02-04
- * \author Adam Lackorznynski <adam@os.inf.tu-dresden.de>
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
  *
  */
 /*
index d651e4aa230466462ef15f29b06d0ffce31c6a59..0d418e54b0377e8b5d803b12ae79333c47f6c8c7 100644 (file)
@@ -3,7 +3,7 @@
  * \brief  Support for the integrator platform
  *
  * \date   2008-01-02
- * \author Adam Lackorznynski <adam@os.inf.tu-dresden.de>
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
  *
  */
 /*
index 254b1910e3c57ee1d7effdbf9b6e7c11e9904981..4890f76bb07255ce8ee2542c569fb5777c84d8a4 100644 (file)
@@ -3,7 +3,7 @@
  * \brief  Support for the kirkwood platform
  *
  * \date   2010-11
- * \author Adam Lackorznynski <adam@os.inf.tu-dresden.de>
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
  *
  */
 /*
index 53f1cb1e70c37d6c3880f7e79fa51a345443d559..893616d2cbb863d3a5eb52a78267077bc596f543 100644 (file)
@@ -3,7 +3,7 @@
  * \brief  Support for the OpenMoko platform
  *
  * \date   2008
- * \author Adam Lackorznynski <adam@os.inf.tu-dresden.de>
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
  *
  */
 /*
index 523a5ae4b5be1a71f164a373f31c4daab951cab8..e77aa5b7db1a7a3183d0f961f031b92d6d2728b7 100644 (file)
@@ -3,7 +3,7 @@
  * \brief  Support for the Beagleboard
  *
  * \date   2009-08
- * \author Adam Lackorznynski <adam@os.inf.tu-dresden.de>
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
  *
  */
 /*
index 3ed17c0ba63c4dd7a841bc950208ffe153f5a912..93c32837059e5434d9d008559a41d72f749f2f74 100644 (file)
@@ -3,7 +3,7 @@
  * \brief  Support for the PXA platform
  *
  * \date   2008-01-04
- * \author Adam Lackorznynski <adam@os.inf.tu-dresden.de>
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
  *
  */
 /*
diff --git a/l4/pkg/bootstrap/server/src/platform/rpi.cc b/l4/pkg/bootstrap/server/src/platform/rpi.cc
new file mode 100644 (file)
index 0000000..1af3505
--- /dev/null
@@ -0,0 +1,37 @@
+/*!
+ * \file   rpi.cc
+ * \brief  Support for the Raspberry Pi
+ *
+ * \date   2013
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
+ *
+ */
+/*
+ * (c) 2013 Author(s)
+ *     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.
+ */
+
+#include "support.h"
+#include <l4/drivers/uart_pl011.h>
+
+namespace {
+
+class Platform_arm_rpi : public Platform_single_region_ram
+{
+  bool probe() { return true; }
+
+  void init()
+  {
+    static L4::Io_register_block_mmio r(0x20201000);
+    static L4::Uart_pl011 _uart(3000000);
+    _uart.startup(&r);
+    set_stdio_uart(&_uart);
+  }
+};
+}
+
+REGISTER_PLATFORM(Platform_arm_rpi);
index 6fcad0b61d230707d32f3275e46e2c89c01ac115..5f849bb635363299c71e71d1aa6c8e68ec74bd55 100644 (file)
@@ -3,7 +3,7 @@
  * \brief  Support for the rv platform
  *
  * \date   2011
- * \author Adam Lackorznynski <adam@os.inf.tu-dresden.de>
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
  *
  */
 /*
index b6565ac54331c8a8c649079a25af3c8f7fcd2ff2..7d2a0c0cfb335a9e7caa218bdb9bee9382fb5c1c 100644 (file)
@@ -3,7 +3,7 @@
  * \brief  Support for the rv platform
  *
  * \date   2011
- * \author Adam Lackorznynski <adam@os.inf.tu-dresden.de>
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
  *
  */
 /*
@@ -26,7 +26,14 @@ class Platform_arm_rv_vexpress : public Platform_single_region_ram
   bool probe() { return true; }
   void init()
   {
-    static L4::Io_register_block_mmio r(0x10009000);
+    unsigned long m;
+    unsigned long uart_base = 0x10009000;
+
+    asm volatile("mrc p15, 0, %0, c0, c0, 0" : "=r" (m));
+    if ((m & 0x00000070) == 0x70)
+      uart_base = 0x1c090000;
+
+    static L4::Io_register_block_mmio r(uart_base);
     static L4::Uart_pl011 _uart(24019200);
     _uart.startup(&r);
     set_stdio_uart(&_uart);
index e8b15317e66aef94b93370fef592d669c5001a6e..b9e65f0907b0134d42fa4ccf91b02f7a17fb1765 100644 (file)
@@ -3,7 +3,7 @@
  * \brief  Support for SA1000 platform
  *
  * \date   2008-01-02
- * \author Adam Lackorznynski <adam@os.inf.tu-dresden.de>
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
  *
  */
 /*
index 8a3ff7aa5f34531a33da2fbe2fdd4cbbe089c4dd..7a9d816c6c85211b2d4285948d0342ea600479ee 100644 (file)
@@ -3,7 +3,7 @@
  * \brief  Support for Tegra 2 platforms
  *
  * \date   2010-05
- * \author Adam Lackorznynski <adam@os.inf.tu-dresden.de>
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
  *
  */
 /*
index 428898aeff5ca6b600f50058f511eea65338f87e..abad7f3068ab48945a25cc5809a7817bb2718896 100644 (file)
@@ -3,7 +3,7 @@
  * \brief  Support for the x86 platform
  *
  * \date   2008-01-02
- * \author Adam Lackorznynski <adam@os.inf.tu-dresden.de>
+ * \author Adam Lackorzynski <adam@os.inf.tu-dresden.de>
  *
  */
 /*
@@ -276,11 +276,14 @@ int pci_handle_serial_dev(unsigned char bus, l4_uint32_t dev,
        }
     }
 
+  printf("  serial IO card: mem bars: %d   io bars: %d\n", num_membars, num_iobars);
+
   if (num_membars <= 1 && num_iobars == 1)
     {
       board->first_bar = first_port;
       board->num_ports = board->bars[first_port].len / 8;
       board->port_per_bar = false;
+      printf("   use serial IO card: bar=%d ports=%d\n", first_port, board->num_ports);
       pci_enable_io(bus, dev, subdev);
       return 1;
     }
@@ -353,9 +356,13 @@ _search_pci_serial_devs(Serial_board *board, unsigned look_for_subclass,
               unsigned vendor = pci_read(bus, dev, subdev, 0, 16);
               unsigned device = pci_read(bus, dev, subdev, 2, 16);
 
-              if ((vendor == 0xffff && device == 0xffff) ||
-                  (device == 0x0000 && device == 0x0000))
-                break;
+              if (vendor == 0xffff)
+                {
+                  if (subdev == 0)
+                    break;
+                  else
+                    continue;
+                }
 
               unsigned classcode = pci_read(bus, dev, subdev, 0x0b, 8);
               unsigned subclass  = pci_read(bus, dev, subdev, 0x0a, 8);
@@ -384,7 +391,7 @@ search_pci_serial_devs(int port_idx)
 {
   Serial_board board;
   if (!_search_pci_serial_devs(&board, 0, true)) // classes should be 7:0
-    if (!_search_pci_serial_devs(&board, 0x80, false)) // but sometimes it's 7:80
+    if (!_search_pci_serial_devs(&board, 0x80, true)) // but sometimes it's 7:80
       return 0;
 
   return board.get_port(port_idx);
index 3e9cb326bd7474bae8da186fb7f2da83a212d74b..2a4e20030471b2bd7c318667884837e2ddd60af0 100644 (file)
@@ -21,6 +21,9 @@ EXTRA_TARGET := \
   std_alloc   \
   std_ops     \
   std_tmpl    \
-  type_traits
+  type_traits \
+  type_list \
+  bitfield \
+  utils
 
 include $(L4DIR)/mk/include.mk
diff --git a/l4/pkg/cxx/lib/tl/include/bitfield b/l4/pkg/cxx/lib/tl/include/bitfield
new file mode 100644 (file)
index 0000000..deed009
--- /dev/null
@@ -0,0 +1,249 @@
+// vi: ft=cpp
+/*
+ * (c) 2012 Alexander Warg <warg@os.inf.tu-dresden.de>,
+ *     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 "type_list"
+
+/** \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<typename T, unsigned LSB, unsigned MSB>
+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<unsigned BITS> 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<Unsigned_types, Cmp>::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<Bits>::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<Bits + Lsb>::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<TT>
+  {
+  public:
+    Value(TT t) : Value_base<TT>(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<TT>
+  {
+  public:
+    Value_unshifted(TT t) : Value_base<TT>(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<T&> Ref;
+  /** Value type to access the bits inside a raw bit field. */
+  typedef Value<T const> Val;
+
+  /** Reference type to access the bits inside a raw bit field (in place). */
+  typedef Value_unshifted<T&> Ref_unshifted;
+  /** Value type to access the bits inside a raw bit field (in place). */
+  typedef Value_unshifted<T const> 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<decltype(data_member), LSB, MSB> 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<decltype(data_member), LSB, MSB> 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/l4/pkg/cxx/lib/tl/include/type_list b/l4/pkg/cxx/lib/tl/include/type_list
new file mode 100644 (file)
index 0000000..c8377a0
--- /dev/null
@@ -0,0 +1,62 @@
+// vi:ft=cpp
+#pragma once
+
+/*
+ * (c) 2012 Alexander Warg <warg@os.inf.tu-dresden.de>,
+ *     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 "type_traits"
+
+namespace cxx {
+
+template< typename ...T >
+struct type_list;
+
+template<>
+struct type_list<>
+{
+  typedef false_type head;
+  typedef false_type tail;
+};
+
+template<typename HEAD, typename ...TAIL>
+struct type_list<HEAD, TAIL...>
+{
+  typedef HEAD head;
+  typedef type_list<TAIL...> tail;
+};
+
+template<typename TYPELIST, template <typename T> class PREDICATE>
+struct find_type;
+
+template<template <typename T> class PREDICATE>
+struct find_type<type_list<>, PREDICATE>
+{
+  typedef false_type type;
+};
+
+template<typename TYPELIST, template <typename T> class PREDICATE>
+struct find_type
+{
+  typedef typename conditional<PREDICATE<typename TYPELIST::head>::value,
+                               typename TYPELIST::head,
+                               typename find_type<typename TYPELIST::tail, PREDICATE>::type>::type type;
+};
+
+}
+
index 6d8602f78b54a8fd8e1fe3e80d4a9632486ddebe..da8fd0a57a50f705087408296d1c806bfd6c0b0f 100644 (file)
@@ -125,5 +125,91 @@ struct enable_if {};
 template< typename T >
 struct enable_if<true, T> { typedef T type; };
 
+template< typename T >
+struct is_const : public false_type {};
+
+template< typename T >
+struct is_const<T const> : public true_type {};
+
+template< bool, typename, typename >
+struct conditional;
+
+template< bool C, typename T_TRUE, typename T_FALSE >
+struct conditional { typedef T_TRUE type; };
+
+template< typename T_TRUE, typename T_FALSE >
+struct conditional< false, T_TRUE, T_FALSE > { typedef T_FALSE type; };
+
+template<typename T>
+struct is_enum : integral_constant<bool, __is_enum(T)> {};
+
+
+template< typename T > struct is_integral : public false_type {};
+
+template<> struct is_integral<bool> : public true_type {};
+
+template<> struct is_integral<char> : public true_type {};
+template<> struct is_integral<signed char> : public true_type {};
+template<> struct is_integral<unsigned char> : public true_type {};
+template<> struct is_integral<short> : public true_type {};
+template<> struct is_integral<unsigned short> : public true_type {};
+template<> struct is_integral<int> : public true_type {};
+template<> struct is_integral<unsigned int> : public true_type {};
+template<> struct is_integral<long> : public true_type {};
+template<> struct is_integral<unsigned long> : public true_type {};
+template<> struct is_integral<long long> : public true_type {};
+template<> struct is_integral<unsigned long long> : public true_type {};
+
+template< typename T, bool = is_integral<T>::value || is_enum<T>::value >
+struct __is_signed_helper : integral_constant<bool, static_cast<bool>(T(-1) < T(0))> {};
+
+template< typename T >
+struct __is_signed_helper<T, false> : integral_constant<bool, false> {};
+
+template< typename T >
+struct is_signed : __is_signed_helper<T> {};
+
+
+template< int SIZE, bool SIGN = false, bool = true > struct int_type_for_size;
+
+template<> struct int_type_for_size<sizeof(char), true, true>
+{ typedef signed char type; };
+
+template<> struct int_type_for_size<sizeof(char), false, true>
+{ typedef unsigned char type; };
+
+template<> struct int_type_for_size<sizeof(short), true, (sizeof(short) > sizeof(char))>
+{ typedef short type; };
+
+template<> struct int_type_for_size<sizeof(short), false, (sizeof(short) > sizeof(char))>
+{ typedef unsigned short type; };
+
+template<> struct int_type_for_size<sizeof(int), true, (sizeof(int) > sizeof(short))>
+{ typedef int type; };
+
+template<> struct int_type_for_size<sizeof(int), false, (sizeof(int) > sizeof(short))>
+{ typedef unsigned int type; };
+
+template<> struct int_type_for_size<sizeof(long), true, (sizeof(long) > sizeof(int))>
+{ typedef long type; };
+
+template<> struct int_type_for_size<sizeof(long), false, (sizeof(long) > sizeof(int))>
+{ typedef unsigned long type; };
+
+template<> struct int_type_for_size<sizeof(long long), true, (sizeof(long long) > sizeof(long))>
+{ typedef long long type; };
+
+template<> struct int_type_for_size<sizeof(long long), false, (sizeof(long long) > sizeof(long))>
+{ typedef unsigned long long type; };
+
+template< typename T, class Enable = void > struct underlying_type {};
+
+template< typename T >
+struct underlying_type<T, typename enable_if<is_enum<T>::value>::type >
+{
+  typedef typename int_type_for_size<sizeof(T), is_signed<T>::value>::type type;
+};
+
+
 }
 
diff --git a/l4/pkg/cxx/lib/tl/include/utils b/l4/pkg/cxx/lib/tl/include/utils
new file mode 100644 (file)
index 0000000..e21cd98
--- /dev/null
@@ -0,0 +1,28 @@
+#pragma once
+
+namespace cxx {
+
+template< typename T >
+T access_once(T const *a)
+{
+#if 1
+  __asm__ __volatile__ ( "" : "=m"(*const_cast<T*>(a)));
+  T tmp = *a;
+  __asm__ __volatile__ ( "" : "=m"(*const_cast<T*>(a)));
+  return tmp;
+#else
+  return *static_cast<T const volatile *>(a);
+#endif
+}
+
+template< typename T >
+void write_now(T *a, T const &val)
+{
+  __asm__ __volatile__ ( "" : "=m"(*a));
+  *a = val;
+  __asm__ __volatile__ ( "" : : "m"(*a));
+}
+
+
+}
+
index 8dae9e384c6cbaf7affce430c345a4ccbc33ec16..01c5a75205ea19549df2bd44fb80e443ac132772 100644 (file)
@@ -64,9 +64,7 @@ namespace L4
 
     _regs->write<unsigned char>(IER, Base_ier_bits);/* disable all rs-232 interrupts */
     _regs->write<unsigned char>(MCR, 0xb);          /* out2, rts, and dtr enabled */
-    _regs->write<unsigned char>(FCR, 1);            /* enable fifo */
-    _regs->write<unsigned char>(FCR, 7);            /* clear rcv xmit fifo */
-    _regs->write<unsigned char>(FCR, 1);            /* enable fifo */
+    _regs->write<unsigned char>(FCR, 7);            /* enable fifo + clear rcv+xmit fifo */
     _regs->write<unsigned char>(LCR, 0);            /* clear line control register */
 
     /* clearall interrupts */
index 2e3d0f3f19c8a613d115de60f371e4a4b5c1f518..58e48573e561d0be2bbc60d9d08a689bf23d7f8d 100644 (file)
@@ -1,8 +1,6 @@
 PKGDIR ?= .
 L4DIR  ?= $(PKGDIR)/../..
 
-TARGET = $(filter-out ffmpeg, $(wildcard [a-z]*))
-# for now
-TARGET = sys bubble libs clntsrv fb misc dope games
+TARGET = $(wildcard [a-z]*)
 
 include $(L4DIR)/mk/subdir.mk
index a442797bc4bce84d2eeaec9138e70515b46b456b..34dc9465fd1ea3e91fcf239e67a31a6b961b3fa9 100644 (file)
@@ -4,6 +4,6 @@ L4DIR           ?= $(PKGDIR)/../..
 TARGET         = vm-tz
 SYSTEMS                = arm-l4f
 SRC_CC         = main.cc
-REQUIRES_LIBS   = libsigma0 l4re_c-util
+REQUIRES_LIBS   = libsigma0 l4re_c-util libvcpu
 
 include $(L4DIR)/mk/prog.mk
index ec7200fc03eca3c253b985027b7dc5f62329c539..29522d539d4504425458399d657b96abf0c32da3 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * (c) 2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
- *          Alexander Warg <warg@os.inf.tu-dresden.de>,
- *          Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
+ * (c) 2009-2012 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
+ *               Alexander Warg <warg@os.inf.tu-dresden.de>,
+ *               Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
  *     economic rights: Technische Universität Dresden (Germany)
  *
  * This file is part of TUD:OS and distributed under the terms of the
 #include <l4/re/util/env_ns>
 #include <l4/re/c/namespace.h>
 #include <l4/re/dataspace>
-#include <l4/re/c/rm.h>
 #include <l4/re/c/util/cap_alloc.h>
-#include <l4/sys/factory.h>
-#include <l4/sys/ipc.h>
-#include <l4/sys/types.h>
-#include <l4/sys/vm.h>
+#include <l4/re/error_helper>
+#include <l4/sys/factory>
+#include <l4/sys/vm>
 #include <l4/sigma0/sigma0.h>
 #include <l4/util/util.h>
+#include <l4/sys/cache.h>
+#include <l4/vcpu/vcpu>
+#include <l4/sys/thread>
 
 #include <cstdio>
 #include <cstdlib>
 #include <cstring>
+#include <cassert>
 
 /*
  * This is a simple example to demonstrate how to
 static void error(const char *str)
 {
   printf("%s", str);
-  exit(-1);
+  exit(1);
 }
 
-static void dump_vm_state(l4_vm_state *state)
+static void dump_vm_state(l4_vm_tz_state *s)
 {
   printf("pc:%08lx cpsr:%08lx\n",
-      state->pc, state->cpsr);
+         s->pc, s->cpsr);
   printf("r0:%08lx r1:%08lx r2:%08lx r3:%08lx\n",
-      state->r[0], state->r[1], state->r[2], state->r[3]);
+         s->r[0], s->r[1], s->r[2], s->r[3]);
   printf("r4:%08lx r5:%08lx r6:%08lx r7:%08lx\n",
-      state->r[4], state->r[5], state->r[6], state->r[7]);
+         s->r[4], s->r[5], s->r[6], s->r[7]);
   printf("r8:%08lx r9:%08lx r10:%08lx r11:%08lx\n",
-      state->r[8], state->r[9], state->r[10], state->r[11]);
+         s->r[8], s->r[9], s->r[10], s->r[11]);
   printf("r12:%08lx\n",
-      state->r[12]);
+         s->r[12]);
   printf("lr_svc:%08lx sp_svc:%08lx spsr_svc:%08lx\n",
-      state->lr_svc, state->sp_svc, state->spsr_svc);
+         s->svc.lr, s->svc.sp, s->svc.spsr);
 }
 
 
 enum {
-    Ram_base = 0x8000000, // 128 MB
-    Ram_size = 0x4000000, // 128 MB
-    Start_addr = Ram_base + 0x1000000, // +1MB
-    Atag_addr = 0x8000000,
-    Initrd_addr = Ram_base + 0x2000000, // +2MB
+    //Ram_base    = 0x60000000, //E
+    Ram_base    = 0x20000000, // T2
+    Ram_size    = 0x00100000,
+    Start_addr  = Ram_base + 0x8000,
+    Atag_addr   = Start_addr + 0x100,
+    Initrd_addr = Ram_base + 0x400000, // +2MB
 };
 
 #define ATAG_NONE      0x00000000
@@ -132,10 +135,16 @@ static struct init_tags
        { 0, ATAG_NONE }
 };
 
-int main()
+static void copyblob(l4_addr_t dst, l4_addr_t src, size_t sz)
 {
-  L4::Cap<void> sigma0_cap;
-  l4_cap_idx_t vm_cap = l4re_util_cap_alloc();
+  assert(dst > Ram_base && dst + sz <= Ram_base + Ram_size);
+  memcpy((void *)dst, (void *)src, sz);
+  l4_cache_clean_data(dst, dst + sz);
+}
+
+static void setup_linux(l4_vm_tz_state *vmstate)
+{
+  const L4Re::Env *env = L4Re::Env::env();
   L4::Cap<L4Re::Dataspace> vm_ds_cap;
   L4::Cap<L4Re::Dataspace> initrd_cap;
   l4_addr_t vm_image_addr = 0;
@@ -143,57 +152,88 @@ int main()
   l4_addr_t initrd_addr = 0;
   l4_size_t initrd_size = 0;
 
-  printf("Vmm started\n");
-
-  if (l4_ipc_error(l4_factory_create_vm(l4re_env()->factory, vm_cap), l4_utcb()))
-    error("Cannot create vm\n");
-
-  if (!(sigma0_cap = L4Re::Env::env()->get_cap<void>("sigma0")))
-    error("Cannot query sigma0 cap\n");
-
-  if (l4sigma0_map_iomem(sigma0_cap.cap(), Ram_base, Ram_base, Ram_size, 1))
-    error("Cannot map nonsecure memory\n");
-
   L4Re::Util::Env_ns ns;
   if (!(vm_ds_cap = ns.query<L4Re::Dataspace>("rom/vm-linux-image-tz")))
     error("Cannot query vm image\n");
 
   vm_image_size = vm_ds_cap->size();
 
-  if (l4re_rm_attach((void**)&vm_image_addr, l4_round_page(vm_image_size),
-               L4RE_RM_SEARCH_ADDR | L4RE_RM_READ_ONLY, vm_ds_cap.cap(), 0, 0))
+  if (env->rm()->attach(&vm_image_addr, l4_round_page(vm_image_size),
+                        L4Re::Rm::Search_addr | L4Re::Rm::Read_only,
+                        vm_ds_cap, 0, 0))
     error("Cannot attach vm image\n");
 
   if (!(initrd_cap = ns.query<L4Re::Dataspace>("rom/linux-initrd")))
       error("Cannot query initrd image\n");
 
   initrd_size = initrd_cap->size();
-  
-  if (l4re_rm_attach((void**)&initrd_addr, l4_round_page(initrd_size),
-               L4RE_RM_SEARCH_ADDR | L4RE_RM_READ_ONLY, initrd_cap.cap(), 0, 0))
+
+  if (env->rm()->attach(&initrd_addr, l4_round_page(initrd_size),
+                        L4Re::Rm::Search_addr | L4Re::Rm::Read_only,
+                        initrd_cap, 0, 0))
     error("Cannot attach initrd image\n");
 
   // fixup Initrd size in ATAG structure
   init_tags.initrd.size = initrd_size;
 
-  memcpy((void*)Start_addr, (void*)vm_image_addr, vm_image_size);
-  memcpy((void*)Initrd_addr, (void*)initrd_addr, initrd_size);
-  memcpy((void*)Atag_addr, (void*)&init_tags, sizeof(init_tags));
+  copyblob(Start_addr,  vm_image_addr, vm_image_size);
+  copyblob(Initrd_addr, initrd_addr, initrd_size);
+  copyblob(Atag_addr,   (l4_addr_t)&init_tags, sizeof(init_tags));
+
 
   // Initialize Vm state according to Linux's requirements
-  l4_vm_state *state;
-  posix_memalign((void**)&state, L4_PAGESIZE, sizeof(l4_vm_state));
-  state->pc = Start_addr;
-  state->cpsr = 0x13;
-  state->r[0] = 0;             // R0=0 according to the spec
-  state->r[1] = 827;           // R1=1 Realview machine architecture
-  state->r[2] = Atag_addr;     // R2=2 ATAG pointer
-  
+
+  vmstate->pc = Start_addr;
+  vmstate->cpsr = 0x13;
+  vmstate->r[0] = 0;            // R0=0 According to the spec
+  vmstate->r[1] = 827;         // R1=1 Machine architecture
+  vmstate->r[2] = Atag_addr;    // R2=2 ATAG pointer
+}
+
+int main()
+{
+  L4::Cap<void> sigma0_cap;
+  L4::Cap<L4::Vm> vm = L4Re::chkcap(L4Re::Util::cap_alloc.alloc<L4::Vm>());
+  const L4Re::Env *env = L4Re::Env::env();
+
+  printf("Vmm started\n");
+
+  L4Re::chksys(env->factory()->create_vm(vm));
+
+  if (!(sigma0_cap = L4Re::Env::env()->get_cap<void>("sigma0")))
+    error("Cannot query sigma0 cap\n");
+
+  l4_addr_t v = Ram_base;
+  L4Re::chksys(env->rm()->reserve_area(&v, Ram_size, L4Re::Rm::Reserved));
+
+  if (l4sigma0_map_iomem(sigma0_cap.cap(), Ram_base, Ram_base, Ram_size, 1))
+    error("Cannot map nonsecure memory\n");
+
+  L4vcpu::Vcpu *vcpu;
+  l4_addr_t _vmstate;
+
+  int r = L4vcpu::Vcpu::ext_alloc(&vcpu, &_vmstate);
+  if (r)
+    {
+      printf("Failed to allocate virtualization data structures: %d\n", r);
+      return 0;
+    }
+
+  l4_vm_tz_state *vmstate = (l4_vm_tz_state *)_vmstate;
+
+  vcpu->task(vm);
+  vcpu->state()->set(L4_VCPU_F_FPU_ENABLED);
+  vcpu->saved_state()->set(L4_VCPU_F_USER_MODE | L4_VCPU_F_FPU_ENABLED);
+
+  setup_linux(vmstate);
+
+  L4::Cap<L4::Thread> me;
+  L4Re::chksys(me->vcpu_control_ext((l4_addr_t)vcpu));
+
   while (1)
     {
       printf("VM run\n");
-      l4_umword_t label = 0;
-      int ret = l4_error_u(l4_vm_run(vm_cap, l4_fpage((unsigned long)state, 12, 0), &label), l4_utcb());
+      int ret = l4_error(me->vcpu_resume_commit(me->vcpu_resume_start()));
       if (ret < 0)
        {
          printf("VM run failed with %d\n", ret);
@@ -203,7 +243,7 @@ int main()
        printf("VM exit\n");
 
       // do nothing but dump the state and sleep a second
-      dump_vm_state((l4_vm_state *)l4_utcb_mr_u(l4_utcb()));
+      dump_vm_state(vmstate);
       l4_sleep(1000);
     }
 
index fc1756257b77e2f3ad2a26aac1315477a06963ce..bd7f67c49067850320d3ff6f20f789654894c17b 100644 (file)
@@ -51,22 +51,7 @@ static l4_cap_idx_t vm_task;
 
 L4_INLINE
 void vmwrite(void *vmcs, unsigned field, unsigned long long val)
-{
-  void *ptr = l4_vm_vmx_field_ptr(vmcs, field);
-
-  switch(l4_vm_vmx_field_len(field))
-  {
-    case 2:
-      *((l4_uint16_t *)(ptr)) = val;
-      break;
-    case 4:
-      *((l4_uint32_t *)(ptr)) = val;
-      break;
-    case 8:
-      *((l4_uint64_t *)(ptr)) = val;
-      break;
-  }
-}
+{ l4_vm_vmx_write(vmcs, field, val); }
 
 static void init_vmcs(void *vmcs)
 {
@@ -115,6 +100,9 @@ static void init_vmcs(void *vmcs)
   vmwrite(vmcs, VMX_GUEST_TR_ACCESS_RIGHTS, 0x108b);
   vmwrite(vmcs, VMX_GUEST_TR_LIMIT, 67);
   vmwrite(vmcs, VMX_GUEST_TR_BASE, 0);
+
+  vmwrite(vmcs_s, VMX_GUEST_CR0, 0x0001003b);
+
 }
 
 static int check_vmx(void)
@@ -149,11 +137,11 @@ void handle_vmexit(void)
   l4_msgtag_t tag;
   l4_uint32_t interrupt_info;
 
-  printf("iteration=%d, rip=0x%x -> 0x%x\n",
-         i, (unsigned int)old_rip,
-         *((unsigned int *)l4_vm_vmx_field_ptr(vmcs_s, VMX_GUEST_RIP)));
+  printf("iteration=%d, rip=0x%lx -> 0x%lx\n",
+         i, old_rip,
+         l4_vm_vmx_read_nat(vmcs_s, VMX_GUEST_RIP));
 
-  l4_uint32_t exit_reason = *((l4_uint32_t *)l4_vm_vmx_field_ptr(vmcs_s, VMX_EXIT_REASON));
+  l4_uint32_t exit_reason = l4_vm_vmx_read_32(vmcs_s, VMX_EXIT_REASON);
   if ((exit_reason & (1<<31)))
     printf("VM entry failure, reason %d\n", (exit_reason & 0xffff));
   else
@@ -161,8 +149,9 @@ void handle_vmexit(void)
       switch (exit_reason)
         {
         case 0:
-          printf("Exception or NMI at guest ip 0x%x, checking interrupt info\n", *((unsigned int *)l4_vm_vmx_field_ptr(vmcs_s, VMX_GUEST_RIP)));
-          interrupt_info = *((l4_uint32_t *)l4_vm_vmx_field_ptr(vmcs_s, VMX_EXIT_INTERRUPT_INFO));
+          printf("Exception or NMI at guest ip 0x%lx, checking interrupt info\n",
+                 l4_vm_vmx_read_nat(vmcs_s, VMX_GUEST_RIP));
+          interrupt_info = l4_vm_vmx_read_32(vmcs_s, VMX_EXIT_INTERRUPT_INFO);
           // check valid bit
           if (!(interrupt_info & (1<<31)))
             printf("Interrupt info not valid\n");
@@ -173,15 +162,15 @@ void handle_vmexit(void)
 
           if ((interrupt_info & (1 << 11))) // interrupt error code valid?
             printf("interrupt error=0x%x\n",
-                   *((l4_uint32_t *)l4_vm_vmx_field_ptr(vmcs_s, VMX_EXIT_INTERRUPT_ERROR)));
+                   l4_vm_vmx_read_32(vmcs_s, VMX_EXIT_INTERRUPT_ERROR));
 
-          printf("cr0=%lx\n", *((l4_umword_t *)l4_vm_vmx_field_ptr(vmcs_s, VMX_GUEST_CR0)));
+          printf("cr0=%lx\n", l4_vm_vmx_read_nat(vmcs_s, VMX_GUEST_CR0));
           printf("eax: %lx ebx: %lx esi: %lx\n", vcpu->r.ax, vcpu->r.bx, vcpu->r.si);
 
           if (((interrupt_info & 0x700)>>8) == 3 &&
               (interrupt_info & 0xff) == 14)
             {
-              l4_umword_t fault_addr = *((l4_umword_t *)l4_vm_vmx_field_ptr(vmcs_s, VMX_EXIT_QUALIFICATION));
+              l4_umword_t fault_addr = l4_vm_vmx_read_nat(vmcs_s, VMX_EXIT_QUALIFICATION);
               printf("detected pagefault @ %lx\n", fault_addr);
               tag = l4_task_map(vm_task, L4RE_THIS_TASK_CAP,
                                 l4_fpage(fault_addr & L4_PAGEMASK, L4_PAGESHIFT, L4_FPAGE_RW),
@@ -192,13 +181,31 @@ void handle_vmexit(void)
             }
 
           // increment rip to continue
-          l4_umword_t l = *((l4_uint32_t *)l4_vm_vmx_field_ptr(vmcs_s, VMX_EXIT_INSTRUCTION_LENGTH));
-          l4_umword_t ip = *((l4_umword_t *)l4_vm_vmx_field_ptr(vmcs_s, VMX_GUEST_RIP));
+          l4_umword_t l = l4_vm_vmx_read_32(vmcs_s, VMX_EXIT_INSTRUCTION_LENGTH);
+          l4_umword_t ip = l4_vm_vmx_read_nat(vmcs_s, VMX_GUEST_RIP);
+          printf("insn length: %lx new rip=%lx\n", l, ip);
           vmwrite(vmcs_s, VMX_GUEST_RIP, ip+l);
           break;
         case 1:
           printf("External interrupt\n");
           break;
+        case 48: // EPT violation
+          printf("EPT violation\n");
+          l4_umword_t q = l4_vm_vmx_read_nat(vmcs_s, VMX_EXIT_QUALIFICATION);
+          printf("  exit qualifiction: %lx\n", q);
+          printf("  guest phys = %llx,  guest linear: %lx\n", l4_vm_vmx_read_64(vmcs_s, 0x2400), l4_vm_vmx_read_nat(vmcs_s, 0x640a));
+          printf("  guest cr0 = %lx\n", l4_vm_vmx_read_nat(vmcs_s, VMX_GUEST_CR0));
+
+            {
+              l4_umword_t fault_addr = l4_vm_vmx_read_64(vmcs_s, 0x2400);
+              printf("detected pagefault @ %lx\n", fault_addr);
+              tag = l4_task_map(vm_task, L4RE_THIS_TASK_CAP,
+                                l4_fpage(fault_addr & L4_PAGEMASK, L4_PAGESHIFT, L4_FPAGE_RWX),
+                                l4_map_control(fault_addr, 0, L4_MAP_ITEM_MAP));
+              if (l4_error(tag))
+                printf("Error mapping page\n");
+            }
+          break;
         default:
           printf("Exit reason %d\n", exit_reason);
           break;
@@ -217,12 +224,13 @@ void vm_resume(void)
     printf("vm_resume failed: %s (%d)\n", l4sys_errtostr(r), r);
 
   handle_vmexit();
-  old_rip = *((l4_umword_t *)l4_vm_vmx_field_ptr(vmcs_s, VMX_GUEST_RIP));
+  old_rip = l4_vm_vmx_read_nat(vmcs_s, VMX_GUEST_RIP);
 
   if (old_rip <= test_end)
     vm_resume();
 }
 
+
 static l4_vcpu_state_t *get_state_mem(l4_addr_t *extstate)
 {
   static int done;
@@ -264,6 +272,12 @@ static l4_vcpu_state_t *get_state_mem(l4_addr_t *extstate)
 
   *extstate = ext_state;
 
+  for (unsigned i = 0x480; i < 0x48d; ++i)
+    printf("VMX: CAP MSR[%3x]: %llx\n", i, l4_vm_vmx_get_caps(vcpu, i));
+
+  for (unsigned i = 0x481; i < 0x485; ++i)
+    printf("VMX: CAP MSR[%3x]: default1: %x\n", i, l4_vm_vmx_get_caps_default1(vcpu, i));
+
   return vcpu;
 }
 
@@ -310,7 +324,7 @@ static void run_test(int ept_available)
                "    nop               \n"
                "    nop               \n"
                                 "    addl %%edx,%%eax  \n"
-               "    ud2               \n"
+//               "    ud2               \n"
                                 "    addl %%edx,%%eax  \n"
                "    int3              \n"
                "3:  nop               \n"
@@ -324,7 +338,7 @@ static void run_test(int ept_available)
                "4:                    \n"
                "    movl $1, %%eax    \n"
                                 "    addl %%edx,%%eax  \n"
-               "    ud2               \n"
+  //             "    ud2               \n"
                "1:  mov $2b, %0      \n"
                "    mov $3b, %1      \n"
                "    mov $4b, %2      \n"
@@ -363,7 +377,7 @@ static void run_test(int ept_available)
   vmwrite(vmcs_s, VMX_GUEST_RSP, (l4_umword_t)stack + STACKSIZE);
   vmwrite(vmcs_s, VMX_GUEST_RFLAGS, eflags);
   vmwrite(vmcs_s, VMX_GUEST_RIP, ip);
-  vmwrite(vmcs_s, VMX_GUEST_CR0, 0x8001003b);
+  vmwrite(vmcs_s, VMX_GUEST_CR0, 0x0001003b);
   vmwrite(vmcs_s, VMX_GUEST_CR4, 0x2690);
   vmwrite(vmcs_s, VMX_GUEST_DR7, 0x300);
   vmwrite(vmcs_s, VMX_VMCS_LINK_PTR, 0xffffffffffffffffULL);
@@ -382,13 +396,13 @@ static void run_test(int ept_available)
 
       tag = l4_task_map(vm_task, L4RE_THIS_TASK_CAP,
                         l4_fpage((((l4_umword_t)(stack)) + ofs) & L4_PAGEMASK,
-                                 L4_PAGESHIFT, L4_FPAGE_RW),
+                                 L4_PAGESHIFT, L4_FPAGE_RWX),
                         l4_map_control(((l4_umword_t)stack) +  ofs, 0,
                                        L4_MAP_ITEM_MAP));
     }
 
   tag = l4_task_map(vm_task, L4RE_THIS_TASK_CAP,
-                    l4_fpage(ip & L4_PAGEMASK, L4_PAGESHIFT, L4_FPAGE_RW),
+                    l4_fpage(ip & L4_PAGEMASK, L4_PAGESHIFT, L4_FPAGE_RWX),
                     l4_map_control(ip, 0, L4_MAP_ITEM_MAP));
 
   idt[26] = 0x80000; // #13 general protection fault
@@ -442,7 +456,7 @@ __attribute__((aligned(4096))) int main(void)
   l4_touch_rw(stack, sizeof(stack));
   l4_touch_rw(hdl_stack, sizeof(hdl_stack));
 
-  run_test(0);
+  run_test(1);
 
   printf("VM test exited\n");
 
index 5a58d8c5c0ed01204b64598f8bab065fa7986d42..871c168db7665513c47b1849c22a5cf307d966a3 100644 (file)
@@ -5,7 +5,7 @@ TARGET  = io
 SRC_CC := main.cc pci.cc res.cc phys_space.cc resource.cc hw_device.cc \
           hw_root_bus.cc device.cc vdevice.cc vproxy_dev.cc \
           vpci.cc vpci_virtual_root.cc vpci_pci_bridge.cc vbus_factory.cc \
-          vbus.cc vicu.cc \
+          vbus.cc vicu.cc gpio.cc \
           server.cc pci_iomem_root_bridge.cc vmsi.cc irqs.cc debug.cc \
           vgpio.cc lua_glue.swg.cc
 
@@ -26,11 +26,10 @@ REQUIRES_CFLAGS = libio-vbus libio-io
 PRIVATE_INCDIR += $(SRC_DIR)
 
 
-ifneq ($(filter regen_files,$(MAKECMDGOALS)),)
-
-ifneq ($(SRC_DIR),)
-regen_files:: $(SRC_DIR)/lua_glue.swg.h $(SRC_DIR)/lua_glue.swg.cc
-endif
+ifneq ($(REGEN_FILES),)
+#ifneq ($(SRC_DIR),)
+#all:: $(SRC_DIR)/lua_glue.swg.h $(SRC_DIR)/lua_glue.swg.cc
+#endif
 
 SWIG_RM_EXT_C ?= $(L4DIR)/tool/bin/swig-rm-extern-c.pl
 SWIG ?= swig
index b242bbe0390ed07fbf998c7c3081c1bdaff22eda..c69d901c88deb68ca9d83ca2ba9407cbb862106e 100644 (file)
@@ -16,6 +16,7 @@
 #include "resource.h"
 
 #include <cstdio> 
+#include <cstring>
 
 template< typename D >
 class Device_tree
@@ -138,6 +139,15 @@ public:
 
   static iterator end() { return iterator(); }
 
+  D *find_by_name(char const *name) const
+  {
+    for (iterator c = begin(0); c != end(); ++c)
+      if (strcmp((*c)->name(), name) == 0)
+        return *c;
+
+    return 0;
+  }
+
   void set_depth(int d) { return _dt.set_depth(d); }
   void set_parent(D *p) { _dt.set_parent(p); }
   void add_sibling(D *s) { _dt.add_sibling(s); }
index 57c3460b03785fdade3a3d53661eb791a5dcb8ce..511b7673cbb260bf3463760e5092eb7bc5d863c4 100644 (file)
@@ -2,7 +2,9 @@
 
 #pragma once
 
+#include "debug.h"
 #include "hw_device.h"
+#include "resource.h"
 #include <l4/vbus/vbus_gpio.h>
 
 namespace Hw {
@@ -58,3 +60,30 @@ class Gpio_device :
 };
 
 }
+
+class Gpio_resource : public Resource
+{
+public:
+  explicit Gpio_resource(Hw::Device *dev, unsigned start, unsigned end)
+  : Resource(Gpio_res | F_fixed_size | F_fixed_addr | F_relative, start, end),
+    _hw(dynamic_cast<Hw::Gpio_device*>(dev))
+  {
+    if (!_hw)
+      {
+        d_printf(DBG_ERR,
+                 "ERROR: GPIO: failed to assign GPIO-device (%p: %s) to resource\n",
+                 dev, dev ? dev->name() : "");
+        throw("ERROR: GPIO: failed to assign GPIO-device to resource");
+      }
+  }
+
+  void dump(int indent) const;
+
+  Hw::Gpio_device *provider() const { return _hw; }
+
+private:
+  Gpio_resource(Gpio_resource const &);
+  void operator = (Gpio_resource const &);
+
+  Hw::Gpio_device *_hw;
+};
index 8cd2030d5e5ff682bfb210878e0fe5b0f118624b..277d2a2e0dcb85e02a60787826698d6056e94079 100644 (file)
@@ -1,3 +1,21 @@
 #include "gpio"
 
+void
+Gpio_resource::dump(int indent) const
+{ printf("<%p>", this);
+  //bool abs = true;
+
+  //if (!valid())
+  //  return;
+
+  l4_uint64_t s, e;
+  s = start();
+  e = end();
+
+  printf("%*.s%s%c [%014llx-%014llx %llx] (dev=%p:%s)\n",
+         indent, " ",
+         "GPIO", provided() ? '*' : ' ',
+         s, e, (l4_uint64_t)size(),
+         _hw, _hw ? _hw->name() : "(NULL)");
+}
 
index 817f089291f4539c03108649f99d4034fa9e205c..d0d8ec024f254a8ba4ab92af42f33cda13d3629f 100644 (file)
@@ -10,6 +10,7 @@
 #include "vdevice.h"
 #include "vbus_factory.h"
 #include "hw_device.h"
+#include "gpio"
 
 static int is_lua_propval(lua_State *L, int idx)
 {
@@ -104,6 +105,8 @@ public:
   int add_filter(cxx::String const &, cxx::String const &);
   int add_filter(cxx::String const &, unsigned long long);
   int add_filter(cxx::String const &, unsigned long long, unsigned long long);
+
+  void dump(int) const;
 };
 
 class Dev_factory
@@ -137,6 +140,8 @@ public:
   Device *next() const;
   int depth() const;
   void plugin();
+
+  void dump(int) const;
 };
 
 class Device_factory
@@ -159,12 +164,38 @@ public:
 
     return 0;
   }
+
+  Hw::Device *__getitem(std::string const &name) const
+  {
+    for (Hw::Device::iterator c = self->begin(0);
+         c != self->end(); ++c)
+      if (name == (*c)->name())
+        return *c;
+
+    return 0;
+  }
+
+  void __setitem(std::string const &name, Hw::Device *dev)
+  {
+    dev->set_name(name);
+    self->add_child(dev);
+    if (self->parent() || self == system_bus())
+      dev->plugin();
+  }
 };
 
 Hw::Device *system_bus();
 void dump_devs(Device *d);
 int add_vbus(Vi::Device *dev);
 
+
+class Gpio_resource : public Resource
+{
+public:
+  explicit Gpio_resource(Hw::Device *dev, unsigned start, unsigned end)
+    throw(char const *);
+};
+
 %luacode {
 
 Io.Res = {}
@@ -196,7 +227,7 @@ Io.Dt = {}
 
 function Io.Dt.add_child(parent, name, dev, idx)
   parent:add_child(dev)
-  if dev.plugin and (parent:parent() or parent == Io.system_bus()) then
+  if dev.plugin and (parent:parent() or swig_equals(parent, Io.system_bus())) then
     dev:plugin()
   end
   if type(name) == "string" then
@@ -207,6 +238,26 @@ function Io.Dt.add_child(parent, name, dev, idx)
   end
 end
 
+function Io.Dt.add_children(parent, bus_func)
+  if type(bus_func) == "function" then
+    local d = {}
+    setmetatable(d, { __index = getfenv(1) })
+    setfenv(bus_func, d)
+    bus_func()
+    if type(d._res) == "table" then
+      for i, r in ipairs(d._res) do
+        Io.Dt.add_resource(parent, r)
+      end
+      d._res = nil
+    elseif type(d._res) == "userdata" then
+      Io.Dt.add_resource(parent, d._res)
+      d._res = nil
+    end
+    Io.Dt.add_device_data(parent, d)
+  end
+  return parent;
+end
+
 function Io.Dt.iterator(dev, max_depth)
   local max_d = (max_depth or 0) + dev:depth()
   local current = dev
@@ -360,6 +411,13 @@ local handle_device_member = function(dev, val, name)
   print("ERROR: cannot handle device member: " .. tostring(name) .. ": " .. tostring(val))
 end
 
+function Io.Dt.add_resource(dev, res)
+  if not Io.swig_instance_of(res, "Resource *") then
+    error("expected a resource object got: " .. tostring(res))
+  end
+  dev:add_resource(res)
+end
+
 function Io.Dt.add_device_data(dev, data)
   local maxi = 0
   for i, v in ipairs(data) do
@@ -374,13 +432,16 @@ function Io.Dt.add_device_data(dev, data)
 end
 
 local set_dev_data = Io.Dt.add_device_data
+local add_children = Io.Dt.add_children
 
 Io.Hw = {}
 
 setmetatable(Io.Hw, { __index = function (self, t)
   return function (data)
     local b = Io.Hw_dev_factory_create(t)
-    if data then
+    if type(data) == "function" then
+      add_children(b, data)
+    elseif type(data) == "table" then
       set_dev_data(b, data)
     end
     return b
@@ -404,7 +465,9 @@ Io.Vi = {}
 setmetatable(Io.Vi, { __index = function (self, t)
   return function (data)
     local b = Io.Vi_dev_factory_create(t)
-    if data then
+    if type(data) == "function" then
+      add_children(b, data)
+    elseif type(data) == "table" then
       set_dev_data(b, data)
     end
     return b
index 95e0bfb6e9fe0884750583f30139217ad0b1be94..d08c4702c4438d89bffbd4bf2f9bc39f0940096c 100644 (file)
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 2.0.7
+ * Version 2.0.8
  * 
  * This file is not intended to be easily readable and contains a number of 
  * coding conventions designed to improve portability and efficiency. Do not make
@@ -852,7 +852,7 @@ typedef struct swig_lua_class {
   const char **base_names;
 } swig_lua_class;
 
-/* this is the struct for wrappering all pointers in SwigLua
+/* this is the struct for wrapping all pointers in SwigLua
 */
 typedef struct {
   swig_type_info   *type;
@@ -860,7 +860,7 @@ typedef struct {
   void        *ptr;
 } swig_lua_userdata;
 
-/* this is the struct for wrapping arbitary packed binary data
+/* this is the struct for wrapping arbitrary packed binary data
 (currently it is only used for member function pointers)
 the data ordering is similar to swig_lua_userdata, but it is currently not possible
 to tell the two structures apart within SWIG, other than by looking at the type
@@ -944,7 +944,7 @@ SWIG_Lua_SetModule(lua_State* L, swig_module_info *module) {
  * ----------------------------------------------------------------------------- */
 
 /* this function is called when trying to set an immutable.
-default value is to print an error.
+default action is to print an error.
 This can removed with a compile flag SWIGLUA_IGNORE_SET_IMMUTABLE */
 SWIGINTERN int SWIG_Lua_set_immutable(lua_State* L)
 {
@@ -1365,7 +1365,7 @@ SWIGINTERN void SWIG_Lua_init_base_class(lua_State* L,swig_lua_class* clss)
       swig_type_info *info = SWIG_TypeQueryModule(module,module,clss->base_names[i]);
       if (info) clss->bases[i] = (swig_lua_class *) info->clientdata;
     }
-  }    
+  }
 }
 
 /* performs the entire class registration process */
@@ -1613,8 +1613,8 @@ SWIG_Lua_InstallConstants(lua_State* L, swig_lua_const_info constants[]) {
 #ifndef SWIG_DOSTRING_FAIL /* Allows redefining of error function */
 #define SWIG_DOSTRING_FAIL(S) fprintf(stderr,"%s\n",S)
 #endif
-/* Executes a C string in Lua a really simple way of calling lua from C
-Unfortunately lua keeps changing its API's, so we need a conditional compile
+/* Executes a C string in Lua which is a really simple way of calling lua from C
+Unfortunately lua keeps changing its APIs, so we need a conditional compile
 In lua 5.0.X its lua_dostring()
 In lua 5.1.X its luaL_dostring()
 */
@@ -1647,22 +1647,23 @@ SWIG_Lua_dostring(lua_State *L, const char* str) {
 #define SWIGTYPE_p_Addr swig_types[0]
 #define SWIGTYPE_p_Device swig_types[1]
 #define SWIGTYPE_p_Generic_device swig_types[2]
-#define SWIGTYPE_p_Hw__Device swig_types[3]
-#define SWIGTYPE_p_Hw__Device__Prop_val swig_types[4]
-#define SWIGTYPE_p_Hw__Device_factory swig_types[5]
-#define SWIGTYPE_p_L4Re__Rm__Auto_regionT_l4_addr_t_t swig_types[6]
-#define SWIGTYPE_p_Mmio_data_space swig_types[7]
-#define SWIGTYPE_p_Resource swig_types[8]
-#define SWIGTYPE_p_Resource_provider swig_types[9]
-#define SWIGTYPE_p_Resource_space swig_types[10]
-#define SWIGTYPE_p_Root_resource swig_types[11]
-#define SWIGTYPE_p_Size swig_types[12]
-#define SWIGTYPE_p_Vi__Dev_factory swig_types[13]
-#define SWIGTYPE_p_Vi__Device swig_types[14]
-#define SWIGTYPE_p_std__string swig_types[15]
-#define SWIGTYPE_p_std__vectorT_Resource_p_t swig_types[16]
-static swig_type_info *swig_types[18];
-static swig_module_info swig_module = {swig_types, 17, 0, 0, 0, 0};
+#define SWIGTYPE_p_Gpio_resource swig_types[3]
+#define SWIGTYPE_p_Hw__Device swig_types[4]
+#define SWIGTYPE_p_Hw__Device__Prop_val swig_types[5]
+#define SWIGTYPE_p_Hw__Device_factory swig_types[6]
+#define SWIGTYPE_p_L4Re__Rm__Auto_regionT_l4_addr_t_t swig_types[7]
+#define SWIGTYPE_p_Mmio_data_space swig_types[8]
+#define SWIGTYPE_p_Resource swig_types[9]
+#define SWIGTYPE_p_Resource_provider swig_types[10]
+#define SWIGTYPE_p_Resource_space swig_types[11]
+#define SWIGTYPE_p_Root_resource swig_types[12]
+#define SWIGTYPE_p_Size swig_types[13]
+#define SWIGTYPE_p_Vi__Dev_factory swig_types[14]
+#define SWIGTYPE_p_Vi__Device swig_types[15]
+#define SWIGTYPE_p_std__string swig_types[16]
+#define SWIGTYPE_p_std__vectorT_Resource_p_t swig_types[17]
+static swig_type_info *swig_types[19];
+static swig_module_info swig_module = {swig_types, 18, 0, 0, 0, 0};
 #define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
 #define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
 
@@ -1902,6 +1903,7 @@ inline int swig_instance_of(lua_State *L)
 #include "vdevice.h"
 #include "vbus_factory.h"
 #include "hw_device.h"
+#include "gpio"
 
 static int is_lua_propval(lua_State *L, int idx)
 {
@@ -1941,6 +1943,20 @@ SWIGINTERN Hw::Device *Hw_Device_find_by_name(Hw::Device const *self,std::string
 
     return 0;
   }
+SWIGINTERN Hw::Device *Hw_Device___getitem(Hw::Device const *self,std::string const &name){
+    for (Hw::Device::iterator c = self->begin(0);
+         c != self->end(); ++c)
+      if (name == (*c)->name())
+        return *c;
+
+    return 0;
+  }
+SWIGINTERN void Hw_Device___setitem(Hw::Device *self,std::string const &name,Hw::Device *dev){
+    dev->set_name(name);
+    self->add_child(dev);
+    if (self->parent() || self == system_bus())
+      dev->plugin();
+  }
 #ifdef __cplusplus
 // removed: extern "C" {
 #endif
@@ -2119,6 +2135,16 @@ static int _wrap_Resource_type(lua_State* L) { int SWIG_arg = 0; Resource *arg1
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Resource,0))){
     SWIG_fail_ptr("Resource_type",1,SWIGTYPE_p_Resource); }  result = (unsigned int)((Resource const *)arg1)->type();
   lua_pushinteger(L, result); SWIG_arg++; return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
+static int _wrap_Resource_lt_compare(lua_State* L) { int SWIG_arg = 0; Resource *arg1 = (Resource *) 0 ;
+  Resource *arg2 = (Resource *) 0 ; bool result; SWIG_check_num_args("Resource::lt_compare",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Resource::lt_compare",1,"Resource const *");
+  if(!SWIG_isptrtype(L,2)) SWIG_fail_arg("Resource::lt_compare",2,"Resource const *");
+  if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Resource,0))){
+    SWIG_fail_ptr("Resource_lt_compare",1,SWIGTYPE_p_Resource); } 
+  if (!SWIG_IsOK(SWIG_ConvertPtr(L,2,(void**)&arg2,SWIGTYPE_p_Resource,0))){
+    SWIG_fail_ptr("Resource_lt_compare",2,SWIGTYPE_p_Resource); } 
+  result = (bool)((Resource const *)arg1)->lt_compare((Resource const *)arg2); lua_pushboolean(L,(int)(result!=0)); SWIG_arg++;
+  return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Resource_set_empty__SWIG_0(lua_State* L) { int SWIG_arg = 0; Resource *arg1 = (Resource *) 0 ; bool arg2 ;
   SWIG_check_num_args("Resource::set_empty",2,2) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Resource::set_empty",1,"Resource *");
   if(!lua_isboolean(L,2)) SWIG_fail_arg("Resource::set_empty",2,"bool");
@@ -2456,6 +2482,7 @@ static swig_lua_method swig_Resource_methods[] = {
     {"fixed_size", _wrap_Resource_fixed_size}, 
     {"relative", _wrap_Resource_relative}, 
     {"type", _wrap_Resource_type}, 
+    {"lt_compare", _wrap_Resource_lt_compare}, 
     {"disable", _wrap_Resource_disable}, 
     {"enable", _wrap_Resource_enable}, 
     {"provided", _wrap_Resource_provided}, 
@@ -2732,6 +2759,12 @@ static int _wrap_Vi_device_add_filter(lua_State* L) { int argc; int argv[5]={ 1,
   "    Vi::Device::add_filter(cxx::String const &,cxx::String const &)\n"
   "    Vi::Device::add_filter(cxx::String const &,unsigned long long)\n"
   "    Vi::Device::add_filter(cxx::String const &,unsigned long long,unsigned long long)\n"); lua_error(L);return 0; }
+static int _wrap_Vi_device_dump(lua_State* L) { int SWIG_arg = 0; Vi::Device *arg1 = (Vi::Device *) 0 ; int arg2 ;
+  SWIG_check_num_args("Vi::Device::dump",2,2) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Vi::Device::dump",1,"Vi::Device const *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("Vi::Device::dump",2,"int");
+  if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Vi__Device,0))){
+    SWIG_fail_ptr("Vi_device_dump",1,SWIGTYPE_p_Vi__Device); }  arg2 = (int)lua_tointeger(L, 2);
+  ((Vi::Device const *)arg1)->dump(arg2); return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Vi_device_set_name(lua_State* L) { int SWIG_arg = 0; Vi::Device *arg1 = (Vi::Device *) 0 ;
   char *arg2 = (char *) 0 ; SWIG_check_num_args("Vi::Device::set_name",2,2)
   if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Vi::Device::set_name",1,"Vi::Device *");
@@ -2751,6 +2784,7 @@ static swig_lua_method swig_Vi_Device_methods[] = {
     {"next", _wrap_Vi_device_next}, 
     {"depth", _wrap_Vi_device_depth}, 
     {"add_filter", _wrap_Vi_device_add_filter}, 
+    {"dump", _wrap_Vi_device_dump}, 
     {"set_name", _wrap_Vi_device_set_name}, 
     {0,0}
 };
@@ -2905,6 +2939,12 @@ static int _wrap_Hw_device_plugin(lua_State* L) { int SWIG_arg = 0; Hw::Device *
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Hw__Device,0))){
     SWIG_fail_ptr("Hw_device_plugin",1,SWIGTYPE_p_Hw__Device); }  (arg1)->plugin(); return SWIG_arg; if(0) SWIG_fail; fail:
   lua_error(L); return SWIG_arg; }
+static int _wrap_Hw_device_dump(lua_State* L) { int SWIG_arg = 0; Hw::Device *arg1 = (Hw::Device *) 0 ; int arg2 ;
+  SWIG_check_num_args("Hw::Device::dump",2,2) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Hw::Device::dump",1,"Hw::Device const *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("Hw::Device::dump",2,"int");
+  if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Hw__Device,0))){
+    SWIG_fail_ptr("Hw_device_dump",1,SWIGTYPE_p_Hw__Device); }  arg2 = (int)lua_tointeger(L, 2);
+  ((Hw::Device const *)arg1)->dump(arg2); return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Hw_device_find_by_name(lua_State* L) { int SWIG_arg = 0; Hw::Device *arg1 = (Hw::Device *) 0 ;
   std::string *arg2 = 0 ; std::string temp2 ; Hw::Device *result = 0 ; SWIG_check_num_args("Hw::Device::find_by_name",2,2)
   if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Hw::Device::find_by_name",1,"Hw::Device const *");
@@ -2915,6 +2955,28 @@ static int _wrap_Hw_device_find_by_name(lua_State* L) { int SWIG_arg = 0; Hw::De
   result = (Hw::Device *)Hw_Device_find_by_name((Hw::Device const *)arg1,(std::string const &)*arg2);
   SWIG_NewPointerObj(L,result,SWIGTYPE_p_Hw__Device,0); SWIG_arg++;  return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L);
   return SWIG_arg; }
+static int _wrap_Hw_device___getitem(lua_State* L) { int SWIG_arg = 0; Hw::Device *arg1 = (Hw::Device *) 0 ;
+  std::string *arg2 = 0 ; std::string temp2 ; Hw::Device *result = 0 ; SWIG_check_num_args("Hw::Device::__getitem",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Hw::Device::__getitem",1,"Hw::Device const *");
+  if(!lua_isstring(L,2)) SWIG_fail_arg("Hw::Device::__getitem",2,"std::string const &");
+  if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Hw__Device,0))){
+    SWIG_fail_ptr("Hw_device___getitem",1,SWIGTYPE_p_Hw__Device); } 
+  temp2.assign(lua_tostring(L,2),lua_rawlen(L,2)); arg2=&temp2;
+  result = (Hw::Device *)Hw_Device___getitem((Hw::Device const *)arg1,(std::string const &)*arg2);
+  SWIG_NewPointerObj(L,result,SWIGTYPE_p_Hw__Device,0); SWIG_arg++;  return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L);
+  return SWIG_arg; }
+static int _wrap_Hw_device___setitem(lua_State* L) { int SWIG_arg = 0; Hw::Device *arg1 = (Hw::Device *) 0 ;
+  std::string *arg2 = 0 ; Hw::Device *arg3 = (Hw::Device *) 0 ; std::string temp2 ;
+  SWIG_check_num_args("Hw::Device::__setitem",3,3)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Hw::Device::__setitem",1,"Hw::Device *");
+  if(!lua_isstring(L,2)) SWIG_fail_arg("Hw::Device::__setitem",2,"std::string const &");
+  if(!SWIG_isptrtype(L,3)) SWIG_fail_arg("Hw::Device::__setitem",3,"Hw::Device *");
+  if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Hw__Device,0))){
+    SWIG_fail_ptr("Hw_device___setitem",1,SWIGTYPE_p_Hw__Device); } 
+  temp2.assign(lua_tostring(L,2),lua_rawlen(L,2)); arg2=&temp2;
+  if (!SWIG_IsOK(SWIG_ConvertPtr(L,3,(void**)&arg3,SWIGTYPE_p_Hw__Device,0))){
+    SWIG_fail_ptr("Hw_device___setitem",3,SWIGTYPE_p_Hw__Device); }  Hw_Device___setitem(arg1,(std::string const &)*arg2,arg3);
+  return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static void swig_delete_Hw_device(void *obj) {
 Hw::Device *arg1 = (Hw::Device *) obj;
 delete arg1;
@@ -2930,7 +2992,10 @@ static swig_lua_method swig_Hw_Device_methods[] = {
     {"next", _wrap_Hw_device_next}, 
     {"depth", _wrap_Hw_device_depth}, 
     {"plugin", _wrap_Hw_device_plugin}, 
+    {"dump", _wrap_Hw_device_dump}, 
     {"find_by_name", _wrap_Hw_device_find_by_name}, 
+    {"__getitem", _wrap_Hw_device___getitem}, 
+    {"__setitem", _wrap_Hw_device___setitem}, 
     {0,0}
 };
 static swig_lua_attribute swig_Hw_Device_attributes[] = {
@@ -2983,6 +3048,31 @@ static int _wrap_add_vbus(lua_State* L) { int SWIG_arg = 0; Vi::Device *arg1 = (
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Vi__Device,0))){
     SWIG_fail_ptr("add_vbus",1,SWIGTYPE_p_Vi__Device); }  result = (int)add_vbus(arg1); lua_pushinteger(L, result); SWIG_arg++;
   return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
+static int _wrap_new_Gpio_resource(lua_State* L) { int SWIG_arg = 0; Hw::Device *arg1 = (Hw::Device *) 0 ; unsigned int arg2 ;
+  unsigned int arg3 ; Gpio_resource *result = 0 ; SWIG_check_num_args("Gpio_resource::Gpio_resource",3,3)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Gpio_resource::Gpio_resource",1,"Hw::Device *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("Gpio_resource::Gpio_resource",2,"unsigned int");
+  if(!lua_isnumber(L,3)) SWIG_fail_arg("Gpio_resource::Gpio_resource",3,"unsigned int");
+  if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Hw__Device,0))){
+    SWIG_fail_ptr("new_Gpio_resource",1,SWIGTYPE_p_Hw__Device); }   arg2 = (unsigned int)lua_tointeger(L, 2); 
+  arg3 = (unsigned int)lua_tointeger(L, 3); try { result = (Gpio_resource *)new Gpio_resource(arg1,arg2,arg3);} 
+  catch(char const *_e) { lua_pushstring(L,_e);SWIG_fail; } 
+  SWIG_NewPointerObj(L,result,SWIGTYPE_p_Gpio_resource,1); SWIG_arg++;  return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L);
+  return SWIG_arg; }
+static void swig_delete_Gpio_resource(void *obj) {
+Gpio_resource *arg1 = (Gpio_resource *) obj;
+delete arg1;
+}
+static swig_lua_method swig_Gpio_resource_methods[] = {
+    {0,0}
+};
+static swig_lua_attribute swig_Gpio_resource_attributes[] = {
+    {0,0,0}
+};
+static swig_lua_class *swig_Gpio_resource_bases[] = {0,0};
+static const char *swig_Gpio_resource_base_names[] = {"Resource *",0};
+static swig_lua_class _wrap_class_Gpio_resource = { "Gpio_resource", &SWIGTYPE_p_Gpio_resource,_wrap_new_Gpio_resource, swig_delete_Gpio_resource, swig_Gpio_resource_methods, swig_Gpio_resource_attributes, swig_Gpio_resource_bases, swig_Gpio_resource_base_names };
+
 #ifdef __cplusplus
 // removed: }
 #endif
@@ -3008,6 +3098,7 @@ static swig_lua_const_info swig_constants[] = {
     {SWIG_LUA_CONSTTAB_INT("Resource_Mmio_res", Resource::Mmio_res)},
     {SWIG_LUA_CONSTTAB_INT("Resource_Io_res", Resource::Io_res)},
     {SWIG_LUA_CONSTTAB_INT("Resource_Bus_res", Resource::Bus_res)},
+    {SWIG_LUA_CONSTTAB_INT("Resource_Gpio_res", Resource::Gpio_res)},
     {SWIG_LUA_CONSTTAB_INT("Resource_F_type_mask", Resource::F_type_mask)},
     {SWIG_LUA_CONSTTAB_INT("Resource_F_disabled", Resource::F_disabled)},
     {SWIG_LUA_CONSTTAB_INT("Resource_F_hierarchical", Resource::F_hierarchical)},
@@ -3052,12 +3143,16 @@ static void *_p_Root_resourceTo_p_Resource(void *x, int *SWIGUNUSEDPARM(newmemor
 static void *_p_Mmio_data_spaceTo_p_Resource(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((Resource *)  ((Mmio_data_space *) x));
 }
+static void *_p_Gpio_resourceTo_p_Resource(void *x, int *SWIGUNUSEDPARM(newmemory)) {
+    return (void *)((Resource *)  ((Gpio_resource *) x));
+}
 static void *_p_Resource_providerTo_p_Resource(void *x, int *SWIGUNUSEDPARM(newmemory)) {
     return (void *)((Resource *)  ((Resource_provider *) x));
 }
 static swig_type_info _swigt__p_Addr = {"_p_Addr", "Addr *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Device = {"_p_Device", "Device *", 0, 0, (void*)&_wrap_class_Device, 0};
 static swig_type_info _swigt__p_Generic_device = {"_p_Generic_device", "Generic_device *", 0, 0, (void*)&_wrap_class_Generic_device, 0};
+static swig_type_info _swigt__p_Gpio_resource = {"_p_Gpio_resource", "Gpio_resource *", 0, 0, (void*)&_wrap_class_Gpio_resource, 0};
 static swig_type_info _swigt__p_Hw__Device = {"_p_Hw__Device", "Device *|Hw::Device *", 0, 0, (void*)&_wrap_class_Hw_Device, 0};
 static swig_type_info _swigt__p_Hw__Device__Prop_val = {"_p_Hw__Device__Prop_val", "Hw::Device::Prop_val *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Hw__Device_factory = {"_p_Hw__Device_factory", "Hw::Device_factory *", 0, 0, (void*)&_wrap_class_Hw_Device_factory, 0};
@@ -3077,6 +3172,7 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_Addr,
   &_swigt__p_Device,
   &_swigt__p_Generic_device,
+  &_swigt__p_Gpio_resource,
   &_swigt__p_Hw__Device,
   &_swigt__p_Hw__Device__Prop_val,
   &_swigt__p_Hw__Device_factory,
@@ -3096,6 +3192,7 @@ static swig_type_info *swig_type_initial[] = {
 static swig_cast_info _swigc__p_Addr[] = {  {&_swigt__p_Addr, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Device[] = {  {&_swigt__p_Generic_device, _p_Generic_deviceTo_p_Device, 0, 0},  {&_swigt__p_Device, 0, 0, 0},  {&_swigt__p_Vi__Device, _p_Vi__DeviceTo_p_Device, 0, 0},  {&_swigt__p_Hw__Device, _p_Hw__DeviceTo_p_Device, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Generic_device[] = {  {&_swigt__p_Generic_device, 0, 0, 0},  {&_swigt__p_Vi__Device, _p_Vi__DeviceTo_p_Generic_device, 0, 0},  {&_swigt__p_Hw__Device, _p_Hw__DeviceTo_p_Generic_device, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_Gpio_resource[] = {  {&_swigt__p_Gpio_resource, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Hw__Device[] = {  {&_swigt__p_Hw__Device, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Hw__Device__Prop_val[] = {  {&_swigt__p_Hw__Device__Prop_val, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Hw__Device_factory[] = {  {&_swigt__p_Hw__Device_factory, 0, 0, 0},{0, 0, 0, 0}};
@@ -3103,7 +3200,7 @@ static swig_cast_info _swigc__p_L4Re__Rm__Auto_regionT_l4_addr_t_t[] = {  {&_swi
 static swig_cast_info _swigc__p_Mmio_data_space[] = {  {&_swigt__p_Mmio_data_space, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Root_resource[] = {{&_swigt__p_Root_resource, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Resource_provider[] = {{&_swigt__p_Resource_provider, 0, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_Resource[] = {  {&_swigt__p_Resource, 0, 0, 0},  {&_swigt__p_Root_resource, _p_Root_resourceTo_p_Resource, 0, 0},  {&_swigt__p_Mmio_data_space, _p_Mmio_data_spaceTo_p_Resource, 0, 0},  {&_swigt__p_Resource_provider, _p_Resource_providerTo_p_Resource, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_Resource[] = {  {&_swigt__p_Resource, 0, 0, 0},  {&_swigt__p_Root_resource, _p_Root_resourceTo_p_Resource, 0, 0},  {&_swigt__p_Mmio_data_space, _p_Mmio_data_spaceTo_p_Resource, 0, 0},  {&_swigt__p_Gpio_resource, _p_Gpio_resourceTo_p_Resource, 0, 0},  {&_swigt__p_Resource_provider, _p_Resource_providerTo_p_Resource, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Resource_space[] = {  {&_swigt__p_Resource_space, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Size[] = {  {&_swigt__p_Size, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Vi__Dev_factory[] = {  {&_swigt__p_Vi__Dev_factory, 0, 0, 0},{0, 0, 0, 0}};
@@ -3115,6 +3212,7 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_Addr,
   _swigc__p_Device,
   _swigc__p_Generic_device,
+  _swigc__p_Gpio_resource,
   _swigc__p_Hw__Device,
   _swigc__p_Hw__Device__Prop_val,
   _swigc__p_Hw__Device_factory,
@@ -3192,8 +3290,7 @@ SWIG_InitializeModule(void *clientdata) {
   size_t i;
   swig_module_info *module_head, *iter;
   int found, init;
-
-  clientdata = clientdata;
+  (void *)clientdata;
 
   /* check to see if the circular list has been setup, if not, set it up */
   if (swig_module.next==0) {
@@ -3484,7 +3581,7 @@ const char* SWIG_LUACODE=
   "\n"
   "function Io.Dt.add_child(parent, name, dev, idx)\n"
   "  parent:add_child(dev)\n"
-  "  if dev.plugin and (parent:parent() or parent == Io.system_bus()) then\n"
+  "  if dev.plugin and (parent:parent() or swig_equals(parent, Io.system_bus())) then\n"
   "    dev:plugin()\n"
   "  end\n"
   "  if type(name) == \"string\" then\n"
@@ -3495,6 +3592,26 @@ const char* SWIG_LUACODE=
   "  end\n"
   "end\n"
   "\n"
+  "function Io.Dt.add_children(parent, bus_func)\n"
+  "  if type(bus_func) == \"function\" then\n"
+  "    local d = {}\n"
+  "    setmetatable(d, { __index = getfenv(1) })\n"
+  "    setfenv(bus_func, d)\n"
+  "    bus_func()\n"
+  "    if type(d._res) == \"table\" then\n"
+  "      for i, r in ipairs(d._res) do\n"
+  "        Io.Dt.add_resource(parent, r)\n"
+  "      end\n"
+  "      d._res = nil\n"
+  "    elseif type(d._res) == \"userdata\" then\n"
+  "      Io.Dt.add_resource(parent, d._res)\n"
+  "      d._res = nil\n"
+  "    end\n"
+  "    Io.Dt.add_device_data(parent, d)\n"
+  "  end\n"
+  "  return parent;\n"
+  "end\n"
+  "\n"
   "function Io.Dt.iterator(dev, max_depth)\n"
   "  local max_d = (max_depth or 0) + dev:depth()\n"
   "  local current = dev\n"
@@ -3648,6 +3765,13 @@ const char* SWIG_LUACODE=
   "  print(\"ERROR: cannot handle device member: \" .. tostring(name) .. \": \" .. tostring(val))\n"
   "end\n"
   "\n"
+  "function Io.Dt.add_resource(dev, res)\n"
+  "  if not Io.swig_instance_of(res, \"Resource *\") then\n"
+  "    error(\"expected a resource object got: \" .. tostring(res))\n"
+  "  end\n"
+  "  dev:add_resource(res)\n"
+  "end\n"
+  "\n"
   "function Io.Dt.add_device_data(dev, data)\n"
   "  local maxi = 0\n"
   "  for i, v in ipairs(data) do\n"
@@ -3662,13 +3786,16 @@ const char* SWIG_LUACODE=
   "end\n"
   "\n"
   "local set_dev_data = Io.Dt.add_device_data\n"
+  "local add_children = Io.Dt.add_children\n"
   "\n"
   "Io.Hw = {}\n"
   "\n"
   "setmetatable(Io.Hw, { __index = function (self, t)\n"
   "  return function (data)\n"
   "    local b = Io.Hw_dev_factory_create(t)\n"
-  "    if data then\n"
+  "    if type(data) == \"function\" then\n"
+  "      add_children(b, data)\n"
+  "    elseif type(data) == \"table\" then\n"
   "      set_dev_data(b, data)\n"
   "    end\n"
   "    return b\n"
@@ -3692,7 +3819,9 @@ const char* SWIG_LUACODE=
   "setmetatable(Io.Vi, { __index = function (self, t)\n"
   "  return function (data)\n"
   "    local b = Io.Vi_dev_factory_create(t)\n"
-  "    if data then\n"
+  "    if type(data) == \"function\" then\n"
+  "      add_children(b, data)\n"
+  "    elseif type(data) == \"table\" then\n"
   "      set_dev_data(b, data)\n"
   "    end\n"
   "    return b\n"
index 0b5b7aee4fd9358cbb7f30549c8543420ef35dc4..0a1615aad947af15aadf8ef27aefa505798ec1c3 100644 (file)
@@ -313,7 +313,7 @@ arg_init(int argc, char * const *argv, Io_config_x *cfg)
       switch (c)
         {
         case 'v':
-          _my_cfg.inc_verbosity();
+          cfg->inc_verbosity();
           break;
         case OPT_TRANSPARENT_MSI:
          d_printf(DBG_INFO, "Enabling transparent MSIs\n");
index 69f223f47adec9e04369986db870233af601722a..f65c4f204793a368d368d7281847cf1f7b0de319 100644 (file)
@@ -52,7 +52,8 @@ public:
     Irq_res     = L4VBUS_RESOURCE_IRQ,
     Mmio_res    = L4VBUS_RESOURCE_MEM,
     Io_res      = L4VBUS_RESOURCE_PORT,
-    Bus_res
+    Bus_res,
+    Gpio_res
   };
 
   enum Flags
@@ -98,6 +99,9 @@ public:
   bool relative() const { return _f & F_relative; }
   unsigned type() const { return _f & F_type_mask; }
 
+  virtual bool lt_compare(Resource const *o) const
+  { return end() < o->start(); }
+
 public:
 //private:
   void set_empty(bool empty)
index db78e3b00e76a19447cb10900ef808305d675077..9c39ba163ada436eacda9d00e118362b6e0958d6 100644 (file)
@@ -32,6 +32,9 @@
 #include "cfg.h"
 #include "vbus_factory.h"
 
+Vi::System_bus::Root_resource_factory::Factory_list
+  Vi::System_bus::Root_resource_factory::_factories;
+
 namespace {
 
 class Root_irq_rs : public Resource_space
@@ -46,7 +49,7 @@ public:
   {
     _bus->add_child(_icu);
     _bus->sw_icu(_icu);
-}
+  }
 
   bool request(Resource *parent, Device *, Resource *child, Device *)
   {
@@ -166,6 +169,11 @@ System_bus::System_bus() : _sw_icu(0)
   add_resource(new Root_resource(Resource::Mmio_res, x));
   add_resource(new Root_resource(Resource::Mmio_res | Resource::F_prefetchable, x));
   add_resource(new Root_resource(Resource::Io_res, x));
+  typedef Root_resource_factory RF;
+  for (RF::Factory_list::Const_iterator i = RF::_factories.begin();
+      i != RF::_factories.end();
+      ++i)
+    add_resource((*i)->create(this));
 }
 
 System_bus::~System_bus()
index 03344ea6024984ec101b84957572eb4986cdacba..1bb40bd4716982f30faf0254a8bd3af2bb6711c2 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <l4/cxx/avl_set>
 #include <l4/cxx/ipc_server>
+#include <l4/cxx/hlist>
 
 #include <l4/vbus/vbus_types.h>
 
@@ -22,6 +23,27 @@ class Sw_icu;
 class System_bus : public Device, public Dev_feature, public L4::Server_object
 {
 public:
+  class Root_resource_factory : public cxx::H_list_item
+  {
+  public:
+    virtual Root_resource *create(System_bus *bus) const = 0;
+    Root_resource_factory()
+    { _factories.push_front(this); }
+
+    typedef cxx::H_list<Root_resource_factory> Factory_list;
+    static Factory_list _factories;
+  };
+
+  template< unsigned TYPE, typename RS >
+  class Root_resource_factory_t : public Root_resource_factory
+  {
+  public:
+    Root_resource *create(System_bus *bus) const
+    {
+      return new Root_resource(TYPE, new RS(bus));
+    }
+  };
+
   System_bus();
   ~System_bus();
 
@@ -45,7 +67,7 @@ private:
     bool operator () (Resource const *a, Resource const *b) const
     {
       if (a->type() == b->type())
-       return a->end() < b->start();
+        return a->lt_compare(b);
       return a->type() < b->type();
     }
   };
@@ -67,6 +89,7 @@ private:
   Resource_set _resources;
   Device *_host;
   Sw_icu *_sw_icu;
+
 };
 
 }
index 5c850fee27b7cf7a539bf4e829747c8e9f925bbc..78812083b6d9c7b4432171f4d6f68f1e549f8a65 100644 (file)
@@ -100,16 +100,15 @@ public:
   Device *next() const { return _dt.next(); }
   int depth() const { return _dt.depth(); }
 
+  Device() : _name("(noname)")
+  { __devs.insert(l4vbus_device_handle_t(this)); }
+
 protected:
   // helper functions
   int get_by_hid(L4::Ipc::Iostream &ios);
   int vbus_get_device(L4::Ipc::Iostream &ios);
   Device *get_dev_by_id(l4vbus_device_handle_t id);
 
-
-  Device() : _name("(noname)")
-  { __devs.insert(l4vbus_device_handle_t(this)); }
-
   Device *get_root()
   {
     Device *d;
index 8f88b8b397c9bfd42ac8ff4bd7fbed89d771be02..a74ba3d38608ce7f5e4d7cc6df9ae0be385b12b3 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 
+#include "debug.h"
 #include "gpio"
 #include "hw_device.h"
 #include "vdevice.h"
@@ -15,6 +16,8 @@
 #include "vbus.h"
 #include "vicu.h"
 
+#include <vector>
+
 #include <l4/vbus/vbus_gpio-ops.h>
 
 #include <cerrno>
@@ -60,6 +63,11 @@ public:
     return 0;
   }
 
+  void modify_mask(l4_uint32_t enable, l4_uint32_t disable)
+  {
+    _mask = (_mask & ~disable) | enable;
+  }
+
   char const *hid() const { return "GPIO"; }
   void set_host(Device *d) { _host = d; }
   Device *host() const { return _host; }
@@ -255,6 +263,105 @@ Gpio::dispatch(l4_umword_t, l4_uint32_t func, L4::Ipc::Iostream &ios)
 
 static Dev_factory_t<Gpio, Hw::Gpio_device> __gpio_factory;
 
+class Gpio_resource : public Resource
+{
+public:
+  explicit Gpio_resource(::Gpio_resource *hr)
+  : Resource(hr->flags(), hr->start(), hr->end()), _hwr(hr) {}
+private:
+  ::Gpio_resource *_hwr;
+};
+
+class Root_gpio_rs : public Resource_space
+{
+public:
+  explicit Root_gpio_rs(System_bus *bus) : _bus(bus)
+  {}
+
+  bool request(Resource *parent, ::Device *pdev, Resource *child, ::Device *)
+  {
+    Vi::System_bus *vsb = dynamic_cast<Vi::System_bus *>(pdev);
+    if (!vsb || !parent)
+      return false;
+
+    ::Gpio_resource *r = dynamic_cast< ::Gpio_resource*>(child);
+    if (!r)
+      return false;
+
+    Hw::Gpio_device *gpio = r->provider();
+
+    Vi::Device *vbus = vsb;
+
+    for (Hw::Device *bus = system_bus(); bus != gpio; )
+      {
+        Hw::Device *d = gpio;
+        while (d->parent() != bus)
+          d = d->parent();
+
+        bus = d;
+        //printf("BUS: %p:%s\n", bus, bus->name());
+
+        Vi::Device *vd = vbus->find_by_name(bus->name());
+        if (!vd)
+          {
+            if (bus != gpio)
+              vd = new Vi::Device();
+            else
+              vd = new Gpio(gpio);
+
+            vd->name(bus->name());
+            vbus->add_child(vd);
+          }
+        // printf("VDEV=%p:%s\n", vd, vd ? vd->name() : "");
+        vbus = vd;
+      }
+
+    Gpio *vgpio = dynamic_cast<Gpio *>(vbus);
+
+    if (!vgpio)
+      {
+        d_printf(DBG_ERR, "ERROR: device: %s is not a GPIO device\n", vbus->name());
+        return false;
+      }
+
+    d_printf(DBG_DEBUG2, "Add GPIO resource to vbus: ");
+    if (dlevel(DBG_DEBUG2))
+      child->dump();
+
+
+      {
+        unsigned e = r->end() + 1;
+        unsigned s = r->start();
+        if (e > 31) e = 31;
+        if (s > 31) s = 31;
+        l4_uint32_t mask = ((1UL << (e - s)) - 1) << s;
+        vgpio->modify_mask(mask, 0);
+      }
+
+    return true;
+  }
+
+  bool alloc(Resource *parent, ::Device *, Resource *child, ::Device *, bool)
+  {
+    d_printf(DBG_DEBUG2, "Allocate virtual GPIO resource ...\n");
+    if (dlevel(DBG_DEBUG2))
+      child->dump();
+
+    if (!parent)
+      return false;
+    return false;
+  }
+
+
+private:
+  Root_gpio_rs(Root_gpio_rs const &);
+  void operator = (Root_gpio_rs const &);
+
+  System_bus *_bus;
+  std::vector<Gpio *> _gpios;
+};
+
+static System_bus::Root_resource_factory_t<Resource::Gpio_res, Root_gpio_rs> __rf;
 
 }
 }
index 73c46106b39cb92bb2b6640731a5ae83af9aec40..17967fd2d23688a9ccc874ceedcea70e14553505 100644 (file)
 #include <l4/sys/syscall_defs.h>
 
 L4_INLINE l4_msgtag_t
-l4_ipc_call(l4_cap_idx_t dest, l4_utcb_t *utcb,
-            l4_msgtag_t tag,
-            l4_timeout_t timeout) L4_NOTHROW
+l4_ipc(l4_cap_idx_t dest, l4_utcb_t *utcb,
+       l4_umword_t flags,
+       l4_umword_t slabel,
+       l4_msgtag_t tag,
+       l4_umword_t *rlabel,
+       l4_timeout_t timeout) L4_NOTHROW
 {
-  register l4_umword_t _dest     __asm__("r2") = dest | L4_SYSF_CALL;
+  register l4_umword_t _dest     __asm__("r2") = dest | flags;
   register l4_umword_t _timeout  __asm__("r3") = timeout.raw;
-  register l4_umword_t _flags    __asm__("r4") = 0;
   register l4_msgtag_t _tag      __asm__("r0") = tag;
+  register l4_umword_t _label    __asm__("r4") = slabel;
   (void)utcb;
+
   __asm__ __volatile__
-    ("@ l4_ipc_call(start) \n\t"
-     "mov     lr, pc       \n\t"
-     "mov     pc, %[sc]    \n\t"
-     "@ l4_ipc_call(end)   \n\t"
+    ("mov lr, pc    \n"
+     "mov pc, %[sc] \n"
      :
      "=r" (_dest),
      "=r" (_timeout),
-     "=r" (_flags),
+     "=r" (_label),
      "=r" (_tag)
      :
-     [sc] "i" (L4_SYSCALL_INVOKE),
      "0" (_dest),
      "1" (_timeout),
-     "2" (_flags),
-     "3" (_tag)
-     : "cc", "memory", "lr");
+     "2" (_label),
+     "3" (_tag),
+     [sc] "i" (L4_SYSCALL_INVOKE)
+     :
+     "cc", "memory", "lr");
+
+  if (rlabel)
+    *rlabel = _label;
   tag.raw = _tag.raw; // because gcc doesn't return out of registers variables
+
   return tag;
 }
 
+L4_INLINE l4_msgtag_t
+l4_ipc_call(l4_cap_idx_t dest, l4_utcb_t *utcb,
+            l4_msgtag_t tag,
+            l4_timeout_t timeout) L4_NOTHROW
+{
+  return l4_ipc(dest, utcb, L4_SYSF_CALL, 0, tag, 0, timeout);
+}
+
 L4_INLINE l4_msgtag_t
 l4_ipc_reply_and_wait(l4_utcb_t *utcb, l4_msgtag_t tag,
                       l4_umword_t *label,
                       l4_timeout_t timeout) L4_NOTHROW
 {
-  register l4_umword_t _dest     __asm__("r2") = L4_INVALID_CAP | L4_SYSF_REPLY_AND_WAIT;
-  register l4_umword_t _timeout  __asm__("r3") = timeout.raw;
-  register l4_msgtag_t _tag      __asm__("r0") = tag;
-  register l4_umword_t _flags    __asm__("r4") = 0;
-  (void)utcb;
-
-  __asm__ __volatile__
-    ("@ l4_ipc_reply_and_wait(start) \n\t"
-     "mov     lr, pc                \n\t"
-     "mov     pc, %[sc]                     \n\t"
-     "@ l4_ipc_reply_and_wait(end)   \n\t"
-     :
-     "=r" (_dest),
-     "=r" (_timeout),
-     "=r" (_flags),
-     "=r" (_tag)
-     :
-     [sc] "i" (L4_SYSCALL_INVOKE),
-     "0" (_dest),
-     "1" (_timeout),
-     "2" (_flags),
-     "3" (_tag)
-     :
-     "cc", "memory", "lr");
-  *label = _flags;
-  tag.raw = _tag.raw; // because gcc doesn't return out of registers variables
-  return tag;
+  return l4_ipc(L4_INVALID_CAP, utcb, L4_SYSF_REPLY_AND_WAIT, 0, tag, label, timeout);
 }
 
-
 L4_INLINE l4_msgtag_t
 l4_ipc_send_and_wait(l4_cap_idx_t dest, l4_utcb_t *utcb,
                      l4_msgtag_t tag,
                      l4_umword_t *src,
                      l4_timeout_t timeout) L4_NOTHROW
 {
-  register l4_umword_t _dest     __asm__("r2") = dest | L4_SYSF_SEND_AND_WAIT;
-  register l4_umword_t _timeout  __asm__("r3") = timeout.raw;
-  register l4_msgtag_t _tag      __asm__("r0") = tag;
-  register l4_umword_t _flags    __asm__("r4") = 0;
-  (void)utcb;
-
-  __asm__ __volatile__
-    ("@ l4_ipc_reply_and_wait(start) \n\t"
-     "mov     lr, pc                \n\t"
-     "mov     pc, %[sc]                     \n\t"
-     "@ l4_ipc_reply_and_wait(end)   \n\t"
-     :
-     "=r" (_dest),
-     "=r" (_timeout),
-     "=r" (_flags),
-     "=r" (_tag)
-     :
-     [sc] "i" (L4_SYSCALL_INVOKE),
-     "0" (_dest),
-     "1" (_timeout),
-     "2" (_flags),
-     "3" (_tag)
-     :
-     "cc", "memory", "lr");
-  *src = _flags;
-  tag.raw = _tag.raw; // because gcc doesn't return out of registers variables
-  return tag;
+  return l4_ipc(dest, utcb, L4_SYSF_SEND_AND_WAIT, 0, tag, src, timeout);
 }
 
 L4_INLINE l4_msgtag_t
@@ -136,145 +98,27 @@ l4_ipc_send(l4_cap_idx_t dest, l4_utcb_t *utcb,
             l4_msgtag_t tag,
             l4_timeout_t timeout) L4_NOTHROW
 {
-  register l4_umword_t _dest     __asm__("r2") = dest | L4_SYSF_SEND;
-  register l4_umword_t _timeout  __asm__("r3") = timeout.raw;
-  register l4_umword_t _flags    __asm__("r4") = 0;
-  register l4_msgtag_t _tag      __asm__("r0") = tag;
-  (void)utcb;
-
-  __asm__ __volatile__
-    ("@  l4_ipc_send(start) \n\t"
-     "mov     lr, pc         \n\t"
-     "mov     pc, %[sc]              \n\t"
-     "@  l4_ipc_send(end)   \n\t"
-     :
-     "=r" (_dest),
-     "=r" (_timeout),
-     "=r" (_flags),
-     "=r" (_tag)
-     :
-     [sc] "i" (L4_SYSCALL_INVOKE),
-     "0" (_dest),
-     "1" (_timeout),
-     "2" (_flags),
-     "3" (_tag)
-     :
-     "cc", "memory", "lr");
-  tag.raw = _tag.raw; // because gcc doesn't return out of registers variables
-  return tag;
+  return l4_ipc(dest, utcb, L4_SYSF_SEND, 0, tag, 0, timeout);
 }
 
 L4_INLINE l4_msgtag_t
 l4_ipc_wait(l4_utcb_t *utcb, l4_umword_t *src,
             l4_timeout_t timeout) L4_NOTHROW
 {
-  l4_msgtag_t rtag;
-  register l4_umword_t _r        __asm__("r2") = L4_INVALID_CAP | L4_SYSF_WAIT;
-  register l4_umword_t _timeout  __asm__("r3") = timeout.raw;
-  register l4_msgtag_t _tag      __asm__("r0");
-  register l4_umword_t _flags    __asm__("r4") = 0;
-  (void)utcb;
-  _tag.raw = 0;
-
-  __asm__ __volatile__
-    ("@ l4_ipc_wait(start) \n\t"
-     "mov     lr, pc      \n\t"
-     "mov     pc, %[sc]           \n\t"
-     "@ l4_ipc_wait(end)   \n\t"
-     :
-     "=r"(_r),
-     "=r"(_timeout),
-     "=r"(_flags),
-     "=r"(_tag)
-     :
-     [sc] "i"(L4_SYSCALL_INVOKE),
-     "0"(_r),
-     "1"(_timeout),
-     "2"(_flags),
-     "3"(_tag)
-
-     :
-     "cc", "memory", "lr");
-  *src     = _flags;
-  rtag.raw = _tag.raw; // because gcc doesn't return out of registers variables
-  return rtag;
+  l4_msgtag_t t;
+  t.raw = 0;
+  return l4_ipc(L4_INVALID_CAP, utcb, L4_SYSF_WAIT, 0, t, src, timeout);
 }
 
 L4_INLINE l4_msgtag_t
 l4_ipc_receive(l4_cap_idx_t src, l4_utcb_t *utcb,
                l4_timeout_t timeout) L4_NOTHROW
 {
-  l4_msgtag_t rtag;
-  register l4_umword_t _r        __asm__("r2") = src | L4_SYSF_RECV;
-  register l4_umword_t _timeout  __asm__("r3") = timeout.raw;
-  register l4_msgtag_t _tag      __asm__("r0");
-  register l4_umword_t _flags    __asm__("r4") = 0;
-  (void)utcb;
-
-  _tag.raw = 0;
-
-  __asm__ __volatile__
-    ("@ l4_ipc_receive(start)  \n\t"
-     "mov     lr, pc           \n\t"
-     "mov     pc, %[sc]               \n\t"
-     "@ l4_ipc_receive(end)    \n\t"
-     :
-     "=r"(_r),
-     "=r"(_timeout),
-     "=r"(_flags),
-     "=r"(_tag)
-     :
-     [sc] "i"(L4_SYSCALL_INVOKE),
-     "0"(_r),
-     "1"(_timeout),
-     "2"(_flags),
-     "3"(_tag)
-     :
-     "cc", "memory", "lr");
-  rtag.raw = _tag.raw; // because gcc doesn't return out of registers variables
-  return rtag;
+  l4_msgtag_t t;
+  t.raw = 0;
+  return l4_ipc(src, utcb, L4_SYSF_RECV, 0, t, 0, timeout);
 }
 
-// todo: let all calls above use this single call
-L4_INLINE l4_msgtag_t
-l4_ipc(l4_cap_idx_t dest, l4_utcb_t *utcb,
-       l4_umword_t flags,
-       l4_umword_t slabel,
-       l4_msgtag_t tag,
-       l4_umword_t *rlabel,
-       l4_timeout_t timeout) L4_NOTHROW
-{
-  register l4_umword_t _dest     __asm__("r2") = dest | flags;
-  register l4_umword_t _timeout  __asm__("r3") = timeout.raw;
-  register l4_msgtag_t _tag      __asm__("r0") = tag;
-  register l4_umword_t _lab      __asm__("r4") = slabel;
-  (void)utcb;
-
-  __asm__ __volatile__
-    ("@ l4_ipc_reply_and_wait(start) \n\t"
-     "mov     lr, pc                \n\t"
-     "mov     pc, %[sc]                     \n\t"
-     "@ l4_ipc_reply_and_wait(end)   \n\t"
-     :
-     "=r" (_dest),
-     "=r" (_timeout),
-     "=r" (_lab),
-     "=r" (_tag)
-     :
-     [sc] "i" (L4_SYSCALL_INVOKE),
-     "0" (_dest),
-     "1" (_timeout),
-     "2" (_lab),
-     "3" (_tag)
-     :
-     "cc", "memory", "lr");
-  *rlabel = _lab;
-  tag.raw = _tag.raw; // because gcc doesn't return out of registers variables
-  return tag;
-}
-
-
 #include <l4/sys/ipc-impl.h>
 
 #endif //__GNUC__
-
index 668e58120e68deaf571ee80f83539eeb32ebfebd..dd8ce0d7a207ee2a7e2721d57f45162f15a189b2 100644 (file)
  * invalidate any other reasons why the executable file might be covered by
  * the GNU General Public License.
  */
-
 #pragma once
 
-#include <l4/sys/capability>
-#include <l4/sys/vm.h>
-
-namespace L4 {
-
-/**
- * \brief TZ Virtual machine.
- * \ingroup l4_vm_tz_api
- */
-class Vm : public Kobject_t<Vm, Kobject, L4_PROTO_VM>
-{
-protected:
-  Vm();
-
-private:
-  Vm(Vm const &);
-  void operator = (Vm const &);
-
-public:
-  /**
-   * \copydoc l4_vm_run()
-   * \note \a dst_task is the implicit \a this pointer.
-   */
-   l4_msgtag_t run(l4_fpage_t const &fpage, l4_umword_t *label,
-                   l4_utcb_t *utcb = l4_utcb()) throw()
-   { return l4_vm_run_u(cap(), fpage, label, utcb); }
-};
-
-};
+#include <l4/sys/__vm>
index 23e2ee739a3639758cfebb97ce1f6ada660bdb2c..fbc5febd16a9f2f41d22933793374e6ee0fd863d 100644 (file)
  */
 #pragma once
 
-#include <l4/sys/ipc.h>
-#include <l4/sys/task.h>
-
 /**
  * \defgroup l4_vm_tz_api VM API for TZ
  * \brief Virtual Machine API for ARM TrustZone
  * \ingroup l4_vm_api
  */
 
+/**
+ * \internal
+ * \ingroup l4_vm_tz_api
+ */
+struct l4_vm_tz_state_mode
+{
+  l4_umword_t sp;
+  l4_umword_t lr;
+  l4_umword_t spsr;
+};
+
+struct l4_vm_tz_state_irq_inject
+{
+  l4_uint32_t group;
+  l4_uint32_t irqs[8];
+};
+
 /**
  * \brief state structure for TrustZone VMs
  * \ingroup l4_vm_tz_api
  */
-struct l4_vm_state
+struct l4_vm_tz_state
 {
   l4_umword_t r[13]; // r0 - r12
 
   l4_umword_t sp_usr;
   l4_umword_t lr_usr;
 
-  l4_umword_t sp_irq;
-  l4_umword_t lr_irq;
-  l4_umword_t spsr_irq;
+  struct l4_vm_tz_state_mode irq;
 
   l4_umword_t r_fiq[5]; // r8 - r12
-  l4_umword_t sp_fiq;
-  l4_umword_t lr_fiq;
-  l4_umword_t spsr_fiq;
-
-  l4_umword_t sp_abt;
-  l4_umword_t lr_abt;
-  l4_umword_t spsr_abt;
-
-  l4_umword_t sp_und;
-  l4_umword_t lr_und;
-  l4_umword_t spsr_und;
-
-  l4_umword_t sp_svc;
-  l4_umword_t lr_svc;
-  l4_umword_t spsr_svc;
+  struct l4_vm_tz_state_mode fiq;
+  struct l4_vm_tz_state_mode abt;
+  struct l4_vm_tz_state_mode und;
+  struct l4_vm_tz_state_mode svc;
 
   l4_umword_t pc;
   l4_umword_t cpsr;
 
   l4_umword_t pending_events;
-
-  l4_umword_t cp15_ttbr0;
-  l4_umword_t cp15_ttbr1;
-  l4_umword_t cp15_ttbc;
-  l4_umword_t cp15_vector_base;
-  l4_umword_t cp15_dfsr;
-  l4_umword_t cp15_dfar;
-  l4_umword_t cp15_ifsr;
-  l4_umword_t cp15_ifar;
-  l4_umword_t cp15_control;
-  l4_umword_t cp15_prim_region_remap;
-  l4_umword_t cp15_norm_region_remap;
-  l4_umword_t cp15_cid;    // banked
-  l4_umword_t cp15_tls[3]; // banked
+  l4_uint32_t cpacr;
   l4_umword_t cp10_fpexc;
 
   l4_umword_t pfs;
   l4_umword_t pfa;
   l4_umword_t exit_reason;
-};
-
 
-/**
- * \brief Run a VM
- * \ingroup l4_vm_tz_api
- *
- * \param vm         Capability selector for VM
- */
-L4_INLINE l4_msgtag_t
-l4_vm_run(l4_cap_idx_t vm, l4_fpage_t const vm_state_fpage,
-          l4_umword_t *label) L4_NOTHROW;
-
-/**
- * \internal
- * \ingroup l4_vm_tz_api
- */
-L4_INLINE l4_msgtag_t
-l4_vm_run_u(l4_cap_idx_t vm, l4_fpage_t const vm_state_fpage,
-            l4_umword_t *label, l4_utcb_t *u) L4_NOTHROW;
+  struct l4_vm_tz_state_irq_inject irq_inject;
+};
 
-/**
- * \internal
- * \brief Operations on task objects.
- * \ingroup l4_vm_tz_api
- */
-enum
+enum L4_vm_exit_reason
 {
-  L4_VM_RUN_OP    = 0    /* Run a VM */
+  L4_vm_exit_reason_vmm_call   = 1,
+  L4_vm_exit_reason_inst_abort = 2,
+  L4_vm_exit_reason_data_abort = 3,
+  L4_vm_exit_reason_irq        = 4,
+  L4_vm_exit_reason_fiq        = 5,
+  L4_vm_exit_reason_undef      = 6,
 };
 
+L4_INLINE int
+l4_vm_tz_irq_inject(l4_vm_tz_state *state, unsigned irq);
 
-/****** Implementations ****************/
-
-L4_INLINE l4_msgtag_t
-l4_vm_run_u(l4_cap_idx_t vm, l4_fpage_t const vm_state_fpage,
-            l4_umword_t *label, l4_utcb_t *u) L4_NOTHROW
+L4_INLINE int
+l4_vm_tz_irq_inject(l4_vm_tz_state *state, unsigned irq)
 {
-  l4_msg_regs_t *r = l4_utcb_mr_u(u);
-  r->mr[0] = L4_VM_RUN_OP;
-  r->mr[1] = vm_state_fpage.raw;
+  if (irq > sizeof(state->irq_inject.irqs) * 8)
+    return -L4_EINVAL;
 
-  return l4_ipc(vm, u, L4_SYSF_CALL, *label, l4_msgtag(L4_PROTO_TASK, 3, 0, 0), label, L4_IPC_NEVER);
-}
+  unsigned g = irq / 32;
+  state->irq_inject.group   |= 1 << g;
+  state->irq_inject.irqs[g] |= 1 << (irq & 31);
 
-L4_INLINE l4_msgtag_t
-l4_vm_run(l4_cap_idx_t vm, l4_fpage_t const vm_state_fpage,
-          l4_umword_t *label) L4_NOTHROW
-{
-  return l4_vm_run_u(vm, vm_state_fpage, label, l4_utcb());
+  return 0;
 }
index 4083bc96425b9ba5d8488bb6f942a620ca00ab20..846d1d7b9e56446119e553c04ec78e3c8f0c63c3 100644 (file)
@@ -4,8 +4,8 @@
  * \brief X86 virtualization interface.
  */
 /*
- * (c) 2010 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
- *          Alexander Warg <warg@os.inf.tu-dresden.de>
+ * (c) 2010-2013 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
+ *               Alexander Warg <warg@os.inf.tu-dresden.de>
  *     economic rights: Technische Universität Dresden (Germany)
  *
  * This file is part of TUD:OS and distributed under the terms of the
@@ -23,6 +23,8 @@
  */
 #pragma once
 
+#include <l4/sys/vcpu.h>
+
 /**
  * \defgroup l4_vm_vmx_api VM API for VMX
  * \brief Virtual machine API for VMX.
  */
 
 
+/**
+ * \brief Exported VMX capability regsiters.
+ * \ingroup l4_vm_vmx_api
+ */
+enum L4_vm_vmx_caps_regs
+{
+  L4_VM_VMX_BASIC_REG               = 0,    /**< Basic VMX capabilities */
+  L4_VM_VMX_TRUE_PINBASED_CTLS_REG  = 1,    /**< True pin-based control caps */
+  L4_VM_VMX_TRUE_PROCBASED_CTLS_REG = 2,    /**< True processor based control caps */
+  L4_VM_VMX_TRUE_EXIT_CTLS_REG      = 3,    /**< True exit control caps */
+  L4_VM_VMX_TRUE_ENTRY_CTLS_REG     = 4,    /**< True entry control caps */
+  L4_VM_VMX_MISC_REG                = 5,    /**< Misc caps */
+  L4_VM_VMX_CR0_FIXED0_REG          = 6,    /**< Fixed to 0 bits of CR0 */
+  L4_VM_VMX_CR0_FIXED1_REG          = 7,    /**< Fixed to 1 bits of CR0 */
+  L4_VM_VMX_CR4_FIXED0_REG          = 8,    /**< Fixed to 0 bits of CR4 */
+  L4_VM_VMX_CR4_FIXED1_REG          = 9,    /**< Fixed to 1 bits of CR4 */
+  L4_VM_VMX_VMCS_ENUM_REG           = 0xa,  /**< VMCS enumeration info */
+  L4_VM_VMX_PROCBASED_CTLS2_REG     = 0xb,  /**< Processor based control 2 caps */
+  L4_VM_VMX_EPT_VPID_CAP_REG        = 0xc,  /**< EPT and VPID caps */
+  L4_VM_VMX_NUM_CAPS_REGS                   /**< Total number of VMX capability registers */
+};
+
+
+/**
+ * \brief Exported VMX capability regsiters (default to 1 bits).
+ * \ingroup l4_vm_vmx_api
+ */
+enum L4_vm_vmx_dfl1_regs
+{
+  L4_VM_VMX_PINBASED_CTLS_DFL1_REG  = 0x1, /**< Default 1 bits in pin-based controls */
+  L4_VM_VMX_PROCBASED_CTLS_DFL1_REG = 0x2, /**< Default 1 bits in processor-based controls */
+  L4_VM_VMX_EXIT_CTLS_DFL1_REG      = 0x3, /**< Default 1 bits in exit controls */
+  L4_VM_VMX_ENTRY_CTLS_DFL1_REG     = 0x4, /**< Default 1 bits in entry controls */
+  L4_VM_VMX_NUM_DFL1_REGS                  /**< Total number of default on registers */
+};
+
+/**
+ * \brief Get a capability register for VMX.
+ * \ingroup l4_vm_vmx_api
+ *
+ * \param vcpu_state  Pointer to the VCPU state of the VCPU.
+ * \param cap_msr     Caps register index (\see L4_vm_vmx_caps_regs).
+ * \return The value of the capability register.
+ */
+L4_INLINE
+l4_uint64_t
+l4_vm_vmx_get_caps(void const *vcpu_state, unsigned cap_msr) L4_NOTHROW;
+
+/**
+ * \brief Get a default to one capability register for VMX.
+ * \ingroup l4_vm_vmx_api
+ *
+ * \param vcpu_state  Pointer to the VCPU state of the VCPU.
+ * \param cap_msr     Default 1 caps register index (\see L4_vm_vmx_dfl1_regs).
+ * \return The value of the capability register.
+ */
+L4_INLINE
+l4_uint32_t
+l4_vm_vmx_get_caps_default1(void const *vcpu_state, unsigned cap_msr) L4_NOTHROW;
+
+
 /**
  * \brief Additional VMCS fields.
  * \ingroup l4_vm_vmx_api
  */
 enum
 {
-  L4_VM_VMX_VMCS_CR2              = 0x6830,
+  /**
+   * \brief (virtual) VMCS offset for CR2.
+   *
+   * The CR2 register is actually not in the hardware VMCS, however our VMMs
+   * run in user mode and need to have access to this register so we put it
+   * into our version of the VMCS.
+   *
+   * \note You usually need to check this value against the value you get from
+   *       l4_vm_vmx_get_cr2_index() to make sure you are running on a
+   *       compatible kernel.
+   */
+  L4_VM_VMX_VMCS_CR2              = 0x683e,
 };
 
 /**
@@ -48,10 +122,22 @@ enum
  */
 L4_INLINE
 unsigned
-l4_vm_vmx_field_len(unsigned field);
+l4_vm_vmx_field_len(unsigned field) L4_NOTHROW;
+
+/**
+ * \brief Return length in power of two (bytes) of a VMCS field.
+ * \ingroup l4_vm_vmx_api
+ *
+ * \param field  Field number.
+ * \return Width of field in power of two (bytes).
+ */
+L4_INLINE
+unsigned
+l4_vm_vmx_field_order(unsigned field) L4_NOTHROW;
 
 /**
  * \brief Get pointer into VMCS.
+ * \internal
  * \ingroup l4_vm_vmx_api
  *
  * \param vmcs   Pointer to VMCS buffer.
@@ -61,24 +147,381 @@ l4_vm_vmx_field_len(unsigned field);
  */
 L4_INLINE
 void *
-l4_vm_vmx_field_ptr(void *vmcs, unsigned field);
+l4_vm_vmx_field_ptr(void *vmcs, unsigned field) L4_NOTHROW;
+
+/**
+ * \brief Saves cached state from the kernel VMCS to the user VMCS.
+ * \ingroup l4_vm_vmx_api
+ * \param vmcs Pointer to the kernel VMCS.
+ * \param user_vmcs Pointer to the user VMCS.
+ *
+ * This function is comparable to VMX vmclear.
+ */
+L4_INLINE
+void
+l4_vm_vmx_clear(void *vmcs, void *user_vmcs) L4_NOTHROW;
+
+/**
+ * \brief Loades the user_vmcs as the current VMCS.
+ * \ingroup l4_vm_vmx_api
+ * \param vmcs Pointer to the kernel VMCS.
+ * \param user_vmcs Pointer to the user VMCS.
+ *
+ * This function is comparable to VMX vmptrld.
+ */
+L4_INLINE
+void
+l4_vm_vmx_ptr_load(void *vmcs, void *user_vmcs) L4_NOTHROW;
+
+
+/**
+ * \brief Get the VMCS field index of the virtual CR2 register.
+ * \ingroup l4_vm_vmx_api
+ *
+ * \param vmcs  Pointer to the software VMCS.
+ * \return The field index used for the virtual CR2 register as used by the
+ *         current Fiasco.OC interface.
+ *
+ * The CR2 register is actually not in the hardware VMCS, however our VMMs run
+ * in user mode and need to have access to this register so we put it into our
+ * software version of the VMCS.
+ *
+ * \see #L4_VM_VMX_VMCS_CR2
+ */
+L4_INLINE
+l4_uint32_t
+l4_vm_vmx_get_cr2_index(void const *vmcs) L4_NOTHROW;
+
+/**
+ * \brief Read a natural width VMCS field.
+ * \ingroup l4_vm_vmx_api
+ *
+ * \param vmcs Pointer to the software VMCS.
+ * \param field The VMCS field index as used on VMX hardware.
+ * \return The value of the VMCS field with the given index.
+ */
+L4_INLINE
+l4_umword_t
+l4_vm_vmx_read_nat(void *vmcs, unsigned field) L4_NOTHROW;
+
+/**
+ * \brief Read a 16bit VMCS field.
+ * \ingroup l4_vm_vmx_api
+ *
+ * \param vmcs Pointer to the software VMCS.
+ * \param field The VMCS field index as used on VMX hardware.
+ * \return The value of the VMCS field with the given index.
+ */
+L4_INLINE
+l4_uint16_t
+l4_vm_vmx_read_16(void *vmcs, unsigned field) L4_NOTHROW;
+
+/**
+ * \brief Read a 32bit VMCS field.
+ * \ingroup l4_vm_vmx_api
+ *
+ * \param vmcs Pointer to the software VMCS.
+ * \param field The VMCS field index as used on VMX hardware.
+ * \return The value of the VMCS field with the given index.
+ */
+L4_INLINE
+l4_uint32_t
+l4_vm_vmx_read_32(void *vmcs, unsigned field) L4_NOTHROW;
+
+/**
+ * \brief Read a 64bit VMCS field.
+ * \ingroup l4_vm_vmx_api
+ *
+ * \param vmcs Pointer to the software VMCS.
+ * \param field The VMCS field index as used on VMX hardware.
+ * \return The value of the VMCS field with the given index.
+ */
+L4_INLINE
+l4_uint64_t
+l4_vm_vmx_read_64(void *vmcs, unsigned field) L4_NOTHROW;
+
+/**
+ * \brief Read any VMCS field.
+ * \ingroup l4_vm_vmx_api
+ *
+ * \param vmcs Pointer to the software VMCS.
+ * \param field The VMCS field index as used on VMX hardware.
+ * \return The value of the VMCS field with the given index.
+ */
+L4_INLINE
+l4_uint64_t
+L4_vm_vmx_read(void *vmcs, unsigned field) L4_NOTHROW;
+
+/**
+ * \brief Write to a natural width VMCS field.
+ * \ingroup l4_vm_vmx_api
+ *
+ * \param vmcs   Pointer to the software VMCS.
+ * \param field  The VMCS field index as used on VMX hardware.
+ * \param val    The value that shall be written to the given field.
+ */
+L4_INLINE
+void
+l4_vm_vmx_write_nat(void *vmcs, unsigned field, l4_umword_t val) L4_NOTHROW;
+
+/**
+ * \brief Write to a 16bit VMCS field.
+ * \ingroup l4_vm_vmx_api
+ *
+ * \param vmcs   Pointer to the software VMCS.
+ * \param field  The VMCS field index as used on VMX hardware.
+ * \param val    The value that shall be written to the given field.
+ */
+L4_INLINE
+void
+l4_vm_vmx_write_16(void *vmcs, unsigned field, l4_uint16_t val) L4_NOTHROW;
+
+/**
+ * \brief Write to a 32bit VMCS field.
+ * \ingroup l4_vm_vmx_api
+ *
+ * \param vmcs   Pointer to the software VMCS.
+ * \param field  The VMCS field index as used on VMX hardware.
+ * \param val    The value that shall be written to the given field.
+ */
+L4_INLINE
+void
+l4_vm_vmx_write_32(void *vmcs, unsigned field, l4_uint32_t val) L4_NOTHROW;
+
+/**
+ * \brief Write to a 64bit VMCS field.
+ * \ingroup l4_vm_vmx_api
+ *
+ * \param vmcs   Pointer to the software VMCS.
+ * \param field  The VMCS field index as used on VMX hardware.
+ * \param val    The value that shall be written to the given field.
+ */
+L4_INLINE
+void
+l4_vm_vmx_write_64(void *vmcs, unsigned field, l4_uint64_t val) L4_NOTHROW;
+
+/**
+ * \brief Write to an arbitrary VMCS field.
+ * \ingroup l4_vm_vmx_api
+ *
+ * \param vmcs   Pointer to the software VMCS.
+ * \param field  The VMCS field index as used on VMX hardware.
+ * \param val    The value that shall be written to the given field.
+ */
+L4_INLINE
+void
+l4_vm_vmx_write(void *vmcs, unsigned field, l4_uint64_t val) L4_NOTHROW;
 
 
 /* Implementations */
 
 L4_INLINE
 unsigned
-l4_vm_vmx_field_len(unsigned field)
+l4_vm_vmx_field_order(unsigned field) L4_NOTHROW
+{
+  switch (field >> 13)
+    {
+    case 0: return 1;
+    case 1: return 3;
+    case 2: return 2;
+    case 3: if (sizeof(l4_umword_t) == 8) return 3; else return 2;
+    default: return 0;
+    }
+}
+
+
+L4_INLINE
+unsigned
+l4_vm_vmx_field_len(unsigned field) L4_NOTHROW
+{
+  return 1 << l4_vm_vmx_field_order(field);
+}
+
+
+/* Internal VCPU state layout:
+ *
+ * VCPU State:
+ * 0 - xxx: normal IA32 VCPU state (l4_vcpu_state_t)
+ *    200h: VMX capabilities (see l4_vm_vmx_get_caps)
+ *    400h: Fiasco.OC VMCS
+ *
+ * Fiasco.OC VMCS:
+ *  0h -   7h: Reserved
+ *  8h -   Fh: ignored by kernel, stores current VMCS for l4_vm_vmx_clear...
+ * 10h -  13h: L4_VM_VMX_VMCS_CR2 value used by the kernel
+ * 14h -  1Fh: Reserved
+ * 20h -  3Fh: VMCS field offset table
+ * 40h - BFFh: Data (VMCS field data)
+ *
+ * VMCS field offset table:
+ *  0h -  2h: 3 offsets for 16bit fields:
+ *            0: Control fields, 1: read-only fields, 2: guest state
+ *            all offsets in 64byte granules relative to the start of the VMCS
+ *        3h: Reserved
+ *  4h -  7h: Index shift values for 16bit, 64bit, 32bit, and natural width fields
+ *  8h -  Ah: 3 offsets for 64bit fields
+ *  Bh -  Fh: Reserved
+ * 10h - 12h: 3 offsets for 32bit fields
+ * 13h - 17h: Reserved
+ * 18h - 1Ah: 3 offsets for natural width fields
+ *       1Bh: Reserved
+ *       1Ch: Offset of first VMCS field
+ *       1Dh: Full size of VMCS fields
+ * 1Eh - 1Fh: Reserved
+ *
+ */
+
+L4_INLINE
+unsigned
+l4_vm_vmx_field_offset(void const *vmcs, unsigned field) L4_NOTHROW
 {
-  static const char widths[4] = { 2, 8, 4, sizeof(l4_umword_t) };
-  return widths[field >> 13];
+  // the offset table is at 0x20 offset
+  enum { Si = 4 };
+  l4_uint8_t const *offsets = (l4_uint8_t const *)vmcs;
+  offsets += 0x20;
+  return (unsigned)offsets[field >> 10] * 64 + ((field & 0x3ff) << offsets[Si + (field >> 13)]);
 }
 
 L4_INLINE
 void *
-l4_vm_vmx_field_ptr(void *vmcs, unsigned field)
+l4_vm_vmx_field_ptr(void *vmcs, unsigned field) L4_NOTHROW
+{
+  return (void *)((char *)vmcs + l4_vm_vmx_field_offset(vmcs, field));
+}
+
+/**
+ * \brief Copy full vmcs state
+ * \internal
+ */
+L4_INLINE
+void
+l4_vm_vmx_copy_state(void const *vmcs, void *_dst, void const *_src) L4_NOTHROW
+{
+  l4_uint8_t const *offsets = (l4_uint8_t const *)vmcs;
+  offsets += 0x20;
+
+  unsigned offs = offsets[28] * 64;
+  unsigned size = offsets[29] * 64;
+  char *const dst = (char*)_dst + offs;
+  char const *const src = (char const *)_src + offs;
+  __builtin_memcpy(dst, src, size);
+}
+
+L4_INLINE
+void
+l4_vm_vmx_clear(void *vmcs, void *user_vmcs) L4_NOTHROW
+{
+  void **current_vmcs = (void **)((char *)vmcs + 8);
+  if (*current_vmcs != user_vmcs)
+    return;
+
+  l4_vm_vmx_copy_state(vmcs, user_vmcs, vmcs);
+  *current_vmcs = 0;
+}
+
+L4_INLINE
+void
+l4_vm_vmx_ptr_load(void *vmcs, void *user_vmcs) L4_NOTHROW
+{
+  void **current_vmcs = (void **)((char *)vmcs + 8);
+  if (*current_vmcs == user_vmcs)
+    return;
+
+  if (*current_vmcs && *current_vmcs != user_vmcs)
+    l4_vm_vmx_clear(vmcs, *current_vmcs);
+
+  *current_vmcs = user_vmcs;
+  l4_vm_vmx_copy_state(vmcs, vmcs, user_vmcs);
+}
+
+
+L4_INLINE
+l4_umword_t
+l4_vm_vmx_read_nat(void *vmcs, unsigned field) L4_NOTHROW
+{ return *(l4_umword_t*)(l4_vm_vmx_field_ptr(vmcs, field)); }
+
+L4_INLINE
+l4_uint16_t
+l4_vm_vmx_read_16(void *vmcs, unsigned field) L4_NOTHROW
+{ return *(l4_uint16_t*)(l4_vm_vmx_field_ptr(vmcs, field)); }
+
+L4_INLINE
+l4_uint32_t
+l4_vm_vmx_read_32(void *vmcs, unsigned field) L4_NOTHROW
+{ return *(l4_uint32_t*)(l4_vm_vmx_field_ptr(vmcs, field)); }
+
+L4_INLINE
+l4_uint64_t
+l4_vm_vmx_read_64(void *vmcs, unsigned field) L4_NOTHROW
+{ return *(l4_uint64_t*)(l4_vm_vmx_field_ptr(vmcs, field)); }
+
+L4_INLINE
+l4_uint64_t
+L4_vm_vmx_read(void *vmcs, unsigned field) L4_NOTHROW
+{
+  switch(field >> 13)
+    {
+    case 0: return l4_vm_vmx_read_16(vmcs, field);
+    case 1: return l4_vm_vmx_read_64(vmcs, field);
+    case 2: return l4_vm_vmx_read_32(vmcs, field);
+    case 3: return l4_vm_vmx_read_nat(vmcs, field);
+    }
+}
+
+L4_INLINE
+void
+l4_vm_vmx_write_nat(void *vmcs, unsigned field, l4_umword_t val) L4_NOTHROW
+{ *(l4_umword_t*)(l4_vm_vmx_field_ptr(vmcs, field)) = val; }
+
+L4_INLINE
+void
+l4_vm_vmx_write_16(void *vmcs, unsigned field, l4_uint16_t val) L4_NOTHROW
+{ *(l4_uint16_t*)(l4_vm_vmx_field_ptr(vmcs, field)) = val; }
+
+L4_INLINE
+void
+l4_vm_vmx_write_32(void *vmcs, unsigned field, l4_uint32_t val) L4_NOTHROW
+{ *(l4_uint32_t*)(l4_vm_vmx_field_ptr(vmcs, field)) = val; }
+
+L4_INLINE
+void
+l4_vm_vmx_write_64(void *vmcs, unsigned field, l4_uint64_t val) L4_NOTHROW
+{ *(l4_uint64_t*)(l4_vm_vmx_field_ptr(vmcs, field)) = val; }
+
+
+L4_INLINE
+void
+l4_vm_vmx_write(void *vmcs, unsigned field, l4_uint64_t val) L4_NOTHROW
+{
+  switch(field >> 13)
+    {
+    case 0: l4_vm_vmx_write_16(vmcs, field, val); break;
+    case 1: l4_vm_vmx_write_64(vmcs, field, val); break;
+    case 2: l4_vm_vmx_write_32(vmcs, field, val); break;
+    case 3: l4_vm_vmx_write_nat(vmcs, field, val); break;
+    }
+}
+
+L4_INLINE
+l4_uint64_t
+l4_vm_vmx_get_caps(void const *vcpu_state, unsigned cap_msr) L4_NOTHROW
+{
+  l4_uint64_t const *caps = (l4_uint64_t const *)((char const *)(vcpu_state) + L4_VCPU_OFFSET_EXT_INFOS);
+  return caps[cap_msr & 0xf];
+}
+
+L4_INLINE
+l4_uint32_t
+l4_vm_vmx_get_caps_default1(void const *vcpu_state, unsigned cap_msr) L4_NOTHROW
+{
+  l4_uint32_t const *caps = (l4_uint32_t const *)((char const *)(vcpu_state) + L4_VCPU_OFFSET_EXT_INFOS);
+  return caps[L4_VM_VMX_NUM_CAPS_REGS * 2 + ((cap_msr & 0xf) - L4_VM_VMX_PINBASED_CTLS_DFL1_REG)];
+}
+
+L4_INLINE
+l4_uint32_t
+l4_vm_vmx_get_cr2_index(void const *vmcs) L4_NOTHROW
 {
-  return (void *)((char *)vmcs
-                          + ((field >> 13) * 4 + ((field >> 10) & 3) + 1) * 0x80
-                          + l4_vm_vmx_field_len(field) * ((field >> 1) & 0xff));
+  l4_uint32_t const *infos = (l4_uint32_t const *)vmcs;
+  return infos[3];
 }
index 64490b9d6ce9512d2eac042dd093cee861a297f4..e4b86e994416d930b306eb49a1ccc4ffdd01102a 100644 (file)
@@ -31,7 +31,7 @@
  * \defgroup l4_irq_api IRQs
  * \ingroup  l4_kernel_object_api
  *
- * \brief The IRQ and IRQ class.
+ * \brief The IRQ and ICU class.
  *
  * <c>\#include <l4/sys/irq.h></c>
  *
index f9828651c40657932225c5f2c822a0df03d6919f..79f98260c4e425687f1c96f1b1a305b7cc316604 100644 (file)
@@ -251,11 +251,11 @@ l4_vcon_read_u(l4_cap_idx_t vcon, char *buf, int size, l4_utcb_t *utcb) L4_NOTHR
   int ret, r;
   l4_msg_regs_t *mr;
 
-  if (size <= 0)
+  if (size < 0)
     return -L4_EINVAL;
 
   mr = l4_utcb_mr_u(utcb);
-  mr->mr[0] = size << 16;
+  mr->mr[0] = (size << 16) | 1;
 
   ret = l4_error_u(l4_ipc_call(vcon, utcb,
                                l4_msgtag(L4_PROTO_LOG, 1, 0, 0),
index 8d8917bd804a22ae127f3c82a0b55a2880568480..346539f8397a3c5c65ce6799d932f6bbd5c15bd6 100644 (file)
@@ -78,4 +78,5 @@ enum L4_vcpu_sticky_flags
 enum L4_vcpu_state_offset
 {
   L4_VCPU_OFFSET_EXT_STATE = 0x400, ///< Offset where extended state begins
+  L4_VCPU_OFFSET_EXT_INFOS = 0x200, ///< Offset where extended infos begin
 };
index 58a717667b74c342880d66a9ab93db21d90657fe..4754548acb1aeb39b7a4323ed0ba31279b2e4abe 100644 (file)
@@ -1,4 +1,4 @@
 
 The dist/ directory contains the unmodified contents of
-libpng-1.6.0.tar.gz.
+libpng-1.6.1.tar.gz.
 
index b719f6683b018ddcaf83b03ec492915823d1d02a..cc2064ec731f5ff07c24162a43d4b0414a4014f2 100644 (file)
@@ -1,5 +1,5 @@
 
-Libpng 1.6.0 - February 14, 2013
+Libpng 1.6.1 - March 28, 2013
 
 This is a public release of libpng, intended for use in production codes.
 
@@ -8,452 +8,89 @@ Files available for download:
 Source files with LF line endings (for Unix/Linux) and with a
 "configure" script
 
-   libpng-1.6.0.tar.xz (LZMA-compressed, recommended)
-   libpng-1.6.0.tar.gz
+   libpng-1.6.1.tar.xz (LZMA-compressed, recommended)
+   libpng-1.6.1.tar.gz
 
 Source files with CRLF line endings (for Windows), without the
 "configure" script
 
-   lpng160.7z  (LZMA-compressed, recommended)
-   lpng160.zip
+   lpng161.7z  (LZMA-compressed, recommended)
+   lpng161.zip
 
 Other information:
 
-   libpng-1.6.0-README.txt
-   libpng-1.6.0-LICENSE.txt
+   libpng-1.6.1-README.txt
+   libpng-1.6.1-LICENSE.txt
 
-Changes since the last public release (1.5.7):
+Changes since the last public release (1.6.0):
 
-  Removed machine-generated configure files from the GIT repository (they will
-    continue to appear in the tarball distributions and in the libpng15 and
-    earlier GIT branches).
-  Restored the new 'simplified' API, which was started in libpng-1.5.7beta02
-    but later deleted from libpng-1.5.7beta05.
-  Added example programs and test program pngstest for the new 'simplified' API.
-  Added ANSI-C (C90) headers and require them, and take advantage of the
-    change. Also fixed some of the projects/* and contrib/* files that needed
-    updates for libpng16 and the move of pngvalid.c.
-    With this change the required ANSI-C header files are assumed to exist: the
-    implementation must provide float.h, limits.h, stdarg.h and stddef.h and
-    libpng relies on limits.h and stddef.h existing and behaving as defined
-    (the other two required headers aren't used).  Non-ANSI systems that don't
-    have stddef.h or limits.h will have to provide an appropriate fake
-    containing the relevant types and #defines.
-  The use of FAR/far has been eliminated and the definition of png_alloc_size_t
-    is now controlled by a flag so that 'small size_t' systems can select it
-    if necessary.  Libpng 1.6 may not currently work on such systems -- it
-    seems likely that it will ask 'malloc' for more than 65535 bytes with any
-    image that has a sufficiently large row size (rather than simply failing
-    to read such images).
-  New tools directory containing tools used to generate libpng code.
-  Fixed race conditions in parallel make builds. With higher degrees of
-    parallelism during 'make' the use of the same temporary file names such
-    as 'dfn*' can result in a race where a temporary file from one arm of the
-    build is deleted or overwritten in another arm.  This changes the
-    temporary files for suffix rules to always use $* and ensures that the
-    non-suffix rules use unique file names.
-  Correct configure builds where build and source directories are separate.
-    The include path of 'config.h' was erroneously made relative in pngvalid.c
-    in libpng 1.5.7.
-  Start-up code size improvements, error handler flexibility. These changes
-    alter how the tricky allocation of the initial png_struct and png_info
-    structures are handled. png_info is now handled in pretty much the same
-    way as everything else, except that the allocations handle NULL return
-    silently.  png_struct is changed in a similar way on allocation and on
-    deallocation a 'safety' error handler is put in place (which should never
-    be required).  The error handler itself is changed to permit mismatches
-    in the application and libpng error buffer size; however, this means a
-    silent change to the API to return the jmp_buf if the size doesn't match
-    the size from the libpng compilation; libpng now allocates the memory and
-    this may fail.  Overall these changes result in slight code size
-    reductions; however, this is a reduction in code that is always executed
-    so is particularly valuable.  Overall on a 64-bit system the libpng DLL
-    decreases in code size by 1733 bytes.  pngerror.o increases in size by
-    about 465 bytes because of the new functionality.
-  Added png_convert_to_rfc1123_buffer() and deprecated png_convert_to_rfc1123()
-    to avoid including a spurious buffer in the png_struct.
-  Regenerated configure scripts with automake-1.11.2
-  Eliminated png_info_destroy(). It is now used only in png.c and only calls
-    one other internal function and memset().
-  Enabled png_get_sCAL_fixed() if floating point APIs are enabled. Previously
-    it was disabled whenever internal fixed point arithmetic was selected,
-    which meant it didn't exist even on systems where FP was available but not
-    preferred.
-  Added pngvalid.c compile time checks for const APIs.
-  Implemented 'restrict' for png_info and png_struct. Because of the way
-    libpng works both png_info and png_struct are always accessed via a
-    single pointer.  This means adding C99 'restrict' to the pointer gives
-    the compiler some opportunity to optimize the code.  This change allows
-    that.
-  Moved AC_MSG_CHECKING([if libraries can be versioned]) later to the proper
-    location in configure.ac (Gilles Espinasse).
-  Changed png_memcpy to C assignment where appropriate. Changed all those
-    uses of png_memcpy that were doing a simple assignment to assignments
-    (all those cases where the thing being copied is a non-array C L-value).
-  Added some error checking to png_set_*() routines.
-  Removed the reference to the non-exported function png_memcpy() from
-    example.c.
-  Fixed the Visual C 64-bit build - it requires jmp_buf to be aligned, but
-    it had become misaligned.
-  Revised contrib/pngminus/pnm2png.c to avoid warnings when png_uint_32
-    and unsigned long are of different sizes.
-  Updated manual with description of the simplified API.
-  Fix bug in pngerror.c: some long warnings were being improperly truncated
-    (CVE-2011-3464, bug introduced in libpng-1.5.4).
-  Increased the formatted warning buffer to 192 bytes.
-  Fixed Min/GW uninstall to remove libpng.dll.a
-  Eliminated Intel icc/icl compiler warnings. The Intel (GCC derived)
-    compiler issues slightly different warnings from those issued by the
-    current vesions of GCC. This eliminates those warnings by
-    adding/removing casts and small code rewrites.
-  Updated configure.ac from autoupdate: added --enable-werror option.
-    Also some layout regularization and removal of introduced tab characters
-    (replaced with 3-character indentation).  Obsolete macros identified by
-    autoupdate have been removed; the replacements are all in 2.59 so
-    the pre-req hasn't been changed.  --enable-werror checks for support
-    for -Werror (or the given argument) in the compiler.  This mimics the
-    gcc configure option by allowing -Werror to be turned on safely; without
-    the option the tests written in configure itself fail compilation because
-    they cause compiler warnings.
-  Rewrote autogen.sh to run autoreconf instead of running tools one-by-one.
-  Conditionalize the install rules for MINGW and CYGWIN in CMakeLists.txt and
-    set CMAKE_LIBRARY_OUTPUT_DIRECTORY to "lib" on all platforms (C. Yapp).
-  Freeze libtool files in the 'scripts' directory. This version of autogen.sh
-    attempts to dissuade people from running it when it is not, or should not,
-    be necessary.  In fact, autogen.sh does not work when run in a libpng
-    directory extracted from a tar distribution anymore. You must run it in
-    a GIT clone instead.
-  Added two images to contrib/pngsuite (1-bit and 2-bit transparent grayscale),
-    and renamed three whose names were inconsistent with those in
-    pngsuite/README.txt.
-  Check libtool/libtoolize version number (2.4.2) in configure.ac
-  Moved automake options to AM_INIT_AUTOMAKE in configure.ac
-  Added color-tests, silent-rules (Not yet implemented in Makefile.am) and
-    version checking to configure.ac
-  Cleaned up pngpriv.h to consistently declare all functions and data.
-    Also eliminated PNG_CONST_DATA, which is apparently not needed but we
-    can't be sure until it is gone.
-  Added symbol prefixing that allows all the libpng external symbols
-    to be prefixed (suggested by Reuben Hawkins).
-  Updated "ftbb*.png" list in the owatcom and vstudio projects.
-  Added Z_SOLO for zlib-1.2.6+ and correct pngstest tests
-  Revised INSTALL information about autogen.sh.
-  Updated list of test images in CMakeLists.txt
-  Corrected estimate of error in libpng png_set_rgb_to_gray API.  The API is
-    extremely inaccurate for sRGB conversions because it uses an 8-bit
-    intermediate linear value and it does not use the sRGB transform, so it
-    suffers from the known instability in gamma transforms for values close
-    to 0 (see Poynton).  The net result is that the calculation has a maximum
-    error of 14.99/255; 0.5/255^(1/2.2).  pngstest now uses 15 for the
-    permitted 8-bit error. This may still not be enough because of arithmetic
-    error.
-  Removed some unused arrays (with #ifdef) from png_read_push_finish_row().
-  Fixed a memory overwrite bug in simplified read of RGB PNG with
-    non-linear gamma Also bugs in the error checking in pngread.c and changed
-    quite a lot of the checks in pngstest.c to be correct; either correctly
-    written or not over-optimistic.  The pngstest changes are insufficient to
-    allow all possible RGB transforms to be passed; pngstest cmppixel needs
-    to be rewritten to make it clearer which errors it allows and then changed
-    to permit known inaccuracies.
-  Removed tests for no-longer-used *_EMPTY_PLTE_SUPPORTED from pngstruct.h
-  Fixed fixed/float API export conditionals. 1) If FIXED_POINT or
-    FLOATING_POINT options were switched off, png.h ended up with lone ';'
-    characters.  This is not valid ANSI-C outside a function.  The ';'
-    characters have been moved inside the definition of PNG_FP_EXPORT and
-    PNG_FIXED_EXPORT. 2) If either option was switched off, the declaration
-    of the corresponding functions were completely omitted, even though some
-    of them are still used internally.  The result is still valid, but
-    produces warnings from gcc with some warning options (including -Wall). The
-    fix is to cause png.h to declare the functions with PNG_INTERNAL_FUNCTION
-    when png.h is included from pngpriv.h.
-  Check for invalid palette index while reading paletted PNG.  When one is
-    found, issue a warning.
-  Fixed CVE-2011-3026 buffer overrun bug.  Deal more correctly with the test
-    on iCCP chunk length. Also removed spurious casts that may hide problems
-    on 16-bit systems.
-  Eliminated redundant png_push_read_tEXt|zTXt|iTXt|unknown code from
-    pngpread.c and use the sequential png_handle_tEXt, etc., in pngrutil.c;
-    now that png_ptr->buffer is inaccessible to applications, the special
-    handling is no longer useful.
-  Added PNG_SAFE_LIMITS feature to pnglibconf.dfa, pngpriv.h, and new
-    pngusr.dfa to reset the user limits to safe ones if PNG_SAFE_LIMITS is
-    defined.  To enable, use "CPPFLAGS=-DPNG_SAFE_LIMITS_SUPPORTED=1" on the
-    configure command or put #define PNG_SAFE_LIMITS_SUPPORTED in
-    pnglibconf.h.prebuilt and pnglibconf.h.
-  Added information about the new limits in the manual.
-  Removed unused "current_text" members of png_struct and the png_free()
-    of png_ptr->current_text from pngread.c
-  Added PNG_IMAGE_FLAG_FAST for the benefit of applications that store
-    intermediate files, or intermediate in-memory data, while processing
-    image data with the simplified API.  The option makes the files larger
-    but faster to write and read.  pngstest now uses this by default; this
-    can be disabled with the --slow option.
-  Improved pngstest fine tuning of error numbers, new test file generator.
-    The generator generates images that test the full range of sample values,
-    allow the error numbers in pngstest to be tuned and checked.  makepng
-    also allows generation of images with extra chunks, although this is
-    still work-in-progress.
-  Fixed some bugs in ICC profile writing. The code should now accept
-    all potentially valid ICC profiles and reject obviously invalid ones.
-    It now uses png_error() to do so rather than casually writing a PNG
-    without the necessary color data.
-  Removed whitespace from the end of lines in all source files and scripts.
-  Added tests for invalid palette index while reading and writing.
-  Changed png_inflate() and calling routines to avoid overflow problems.
-    This is an intermediate check-in that solves the immediate problems and
-    introduces one performance improvement (avoiding a copy via png_ptr->zbuf.)
-    Further changes will be made to make ICC profile handling more secure.
-  Added contrib/libtests/tarith.c to test internal arithmetic functions from
-    png.c. This is a libpng maintainer program used to validate changes to the
-    internal arithmetic functions.
-  Made read 'inflate' handling like write 'deflate' handling. The read
-    code now claims and releases png_ptr->zstream, like the write code.
-    The bug whereby the progressive reader failed to release the zstream
-    is now fixed, all initialization is delayed, and the code checks for
-    changed parameters on deflate rather than always calling
-    deflatedEnd/deflateInit.
-  Validate the zTXt strings in pngvalid.
-  Added code to validate the windowBits value passed to deflateInit2().
-    If the call to deflateInit2() is wrong a png_warning will be issued
-    (in fact this is harmless, but the PNG data produced may be sub-optimal).
-  Fixed PNG_LIBPNG_BUILD_BASE_TYPE definition. 
-  Reject all iCCP chunks after the first, even if the first one is invalid.
-  Deflate/inflate was reworked to move common zlib calls into single
-    functions [rw]util.c.  A new shared keyword check routine was also added
-    and the 'zbuf' is no longer allocated on progressive read.  It is now
-    possible to call png_inflate() incrementally.
-  If benign errors are disabled use maximum window on ancilliary inflate.
-    This works round a bug introduced in 1.5.4 where compressed ancillary
-    chunks could end up with a too-small windowBits value in the deflate
-    header.
-  Issue a png_benign_error() instead of png_warning() about bad palette index.
-  In pngtest, treat benign errors as errors if "-strict" is present.
-  Fixed a compiler warning under Cygwin (Windows-7, 32-bit system)
-  Revised example.c to put text strings in a temporary character array
-    instead of directly assigning string constants to png_textp members.
-    This avoids compiler warnings when -Wwrite-strings is enabled.
-  Added output flushing to aid debugging under Visual Studio. Unfortunately
-    this is necessary because the VS2010 output window otherwise simply loses
-    the error messages on error (they weren't flushed to the window before
-    the process exited, apparently!)
-  Added configuration support for benign errors and changed the read
-    default. Also changed some warnings in the iCCP and sRGB handling
-    from to benign errors. Configuration now makes read benign
-    errors warnings and write benign errors to errors by default (thus
-    changing the behavior on read).  The simplified API always forces
-    read benign errors to warnings (regardless of the system default, unless
-    this is disabled in which case the simplified API can't be built.)
-  Work around for duplicate row start calls; added warning messages.
-    This turns on PNG_FLAG_DETECT_UNINITIALIZED to detect app code that
-    fails to call one of the 'start' routines (not enabled in libpng-1.5
-    because it is technically an API change, since it did normally work
-    before.)  It also makes duplicate calls to png_read_start_row (an
-    internal function called at the start of the image read) benign, as
-    they were before changes to use png_inflate_claim. Somehow webkit is
-    causing this to happen; this is probably a mis-feature in the zlib
-    changes so this commit is only a work-round.
-  Removed erroneous setting of DETECT_UNINITIALIZED and added more
-    checks. The code now does a png_error if an attempt is made to do the
-    row initialization twice; this is an application error and it has
-    serious consequences because the transform data in png_struct is
-    changed by each call.
-  Added application error reporting and added chunk names to read
-    benign errors; also added --strict to pngstest - not enabled
-    yet because a warning is produced.
-  Avoid the double gamma correction warning in the simplified API.
-    This allows the --strict option to pass in the pngstest checks
-  Changed chunk handler warnings into benign errors, incrementally load iCCP
-  Added checksum-icc.c to contrib/tools
-  Prevent PNG_EXPAND+PNG_SHIFT doing the shift twice.
-  Recognize known sRGB ICC profiles while reading; prefer writing the
-    iCCP profile over writing the sRGB chunk, controlled by the
-    PNG_sRGB_PROFILE_CHECKS option.
-  Revised png_set_text_2() to avoid potential memory corruption (fixes
-    CVE-2011-3048).
-  Revised scripts/makefile.darwin: use system zlib; remove quotes around
-    architecture list; add missing ppc architecture; add architecture options
-    to shared library link; don't try to create a shared lib based on missing
-    RELEASE variable.
-  Enable png_set_check_for_invalid_index() for both read and write.
-  Removed #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED in pngpriv.h around
-    declaration of png_handle_unknown().
-  Added -lssp_nonshared in a comment in scripts/makefile.freebsd
-    and changed deprecated NOOBJ and NOPROFILE to NO_OBJ and NO_PROFILE.
-  Removed need for -Wno-cast-align with clang.  clang correctly warns on
-    alignment increasing pointer casts when -Wcast-align is passed. This
-    fixes the cases that clang warns about either by eliminating the
-    casts from png_bytep to png_uint_16p (pngread.c), or, for pngrutil.c
-    where the cast is previously verified or pngstest.c where it is OK, by
-    introducing new png_aligncast macros to do the cast in a way that clang
-    accepts.
-  Revised CMakeLists.txt to not attempt to make a symlink under mingw.
-  Made fixes for new optimization warnings from gcc 4.7.0. The compiler
-    performs an optimization which is safe; however it then warns about it.
-    Changing the type of 'palette_number' in pngvalid.c removes the warning.
-  Do not depend upon a GCC feature macro being available for use in generating
-    the linker mapfile symbol prefix.
-  Improved performance of new do_check_palette_indexes() function (only
-    update the value when it actually increases, move test for whether
-    the check is wanted out of the function.
-  Don't check palette indexes if num_palette is 0 (as it can be in MNG files).
-  Revised png_set_keep_unknown_chunks() so num_chunks < 0 means ignore all
-    unknown chunks and all known chunks except for IHDR, PLTE, tRNS, IDAT,
-    and IEND.  Previously it only meant ignore all unknown chunks, the
-    same as num_chunks == 0. Revised png_image_skip_unused_chunks() to
-    provide a list of chunks to be processed instead of a list of chunks to
-    ignore.  Revised contrib/gregbook/readpng2.c accordingly.
-  Removed scripts/makefile.cegcc from the *.zip and *.7z distributions; it
-    depends on configure, which is not included in those archives.
-  Moved scripts/chkfmt to contrib/tools.
-  Changed "a+w" to "u+w" in Makefile.in to fix CVE-2012-3386.
-  Do not compile PNG_DEPRECATED, PNG_ALLOC and PNG_PRIVATE when __GNUC__ < 3.
-  Do not use __restrict when GNUC is <= 3.1
-  Removed references to png_zalloc() and png_zfree() from the manual.
-  Fixed configurations where floating point is completely disabled.  Because
-    of the changes to support symbol prefixing PNG_INTERNAL_FUNCTION declares
-    floating point APIs during libpng builds even if they are completely
-    disabled. This requires the png floating point types (png_double*) to be
-    declared even though the functions are never actually defined.  This
-    change provides a dummy definition so that the declarations work, yet any
-    implementation will fail to compile because of an incomplete type.
-  Re-eliminated the use of strcpy() in pngtest.c.  An unncessary use of
-    strcpy() was accidentally re-introduced in libpng16; this change replaces
-    it with strncpy().
-  Eliminated use of png_sizeof(); use sizeof() instead.
-  Use a consistent style for (sizeof type) and (sizeof (array))
-  Cleanup of png_set_filler().  This function does very different things on
-    read and write.  In libpng 1.6 the two cases can be distinguished and
-    considerable code cleanup, and extra error checking, is possible.  This
-    makes calls on the write side that have no effect be ignored with a
-    png_app_error(), which can be disabled in the app using
-    png_set_benign_errors(), and removes the spurious use of usr_channels
-    on the read side.
-  Insist on autotools 1.12.1 for git builds because there are security issues
-    with 1.12 and insisting on anything less would allow 1.12 to be used.
-  Removed info_ptr->signature[8] from WRITE-only builds.
-  Add some conditions for compiling png_fixed().  This is a small function
-    but it requires "-lm" on some platforms.
-  Cause pngtest --strict to fail on any warning from libpng (not just errors)
-    and cause it not to fail at the comparison step if libpng lacks support
-    for writing chunks that it reads from the input (currently only implemented
-    for compressed text chunks).
-  Make all three "make check" test programs work without READ or WRITE support.
-    Now "make check" will succeed even if libpng is compiled with -DPNG_NO_READ
-    or -DPNG_NO_WRITE.  The tests performed are reduced, but the basic reading
-    and writing of a PNG file is always tested by one or more of the tests.
-  Consistently use strlen(), memset(), memcpy(), and memcmp() instead of the
-    png_strlen(), png_memset(), png_memcpy(), and png_memcmp() macros.
-  Removed the png_sizeof(), png_strlen(), png_memset(), png_memcpy(), and
-    png_memcmp() macros.
-  Work around gcc 3.x and Microsoft Visual Studio 2010 complaints. Both object
-    to the split initialization of num_chunks.
-  Unknown handling fixes and clean up. This adds more correct option
-    control of the unknown handling, corrects the pre-existing bug where
-    the per-chunk 'keep' setting is ignored and makes it possible to skip
-    IDAT chunks in the sequential reader (broken in earlier 1.6 versions).
-    There is a new test program, test-unknown.c, which is a work in progress
-    (not currently part of the test suite).  Comments in the header files now
-    explain how the unknown handling works.
-  Allow fine grain control of unknown chunk APIs. This change allows
-    png_set_keep_unknown_chunks() to be turned off if not required and causes
-    both read and write to behave appropriately (on read this is only possible
-    if the user callback is used to handle unknown chunks).  The change
-    also removes the support for storing unknown chunks in the info_struct
-    if the only unknown handling enabled is via the callback, allowing libpng
-    to be configured with callback reading and none of the unnecessary code.
-  Corrected fix for unknown handling in pngtest. This reinstates the
-    libpng handling of unknown chunks other than vpAg and sTER (including
-    unsafe-to-copy chunks which were dropped before) and eliminates the
-    repositioning of vpAg and sTER in pngtest.png by changing pngtest.png
-    (so the chunks are where libpng would put them).
-  Added "tunknown" test and corrected a logic error in png_handle_unknown()
-    when SAVE support is absent.  Moved the shell test scripts for
-    contrib/libtests from the libpng top directory to contrib/libtests.
-    png_handle_unknown() must always read or skip the chunk, if
-    SAVE_UNKNOWN_CHUNKS is turned off *and* the application does not set
-    a user callback an unknown chunk will not be read, leading to a read
-    error, which was revealed by the "tunknown" test.
-  Cleaned up and corrected ICC profile handling.
-    contrib/libtests/makepng: corrected 'rgb' and 'gray' cases.  profile_error
-    messages could be truncated; made a correct buffer size calculation and
-    adjusted pngerror.c appropriately. png_icc_check_* checking improved;
-    changed the functions to receive the correct color type of the PNG on read
-    or write and check that it matches the color space of the profile (despite
-    what the comments said before, there is danger in assuming the app will
-    cope correctly with an RGB profile on a grayscale image and, since it
-    violates the PNG spec, allowing it is certain to produce inconsistent
-    app behavior and might even cause app crashes.) Check that profiles
-    contain the tags needed to process the PNG (tags all required by the ICC
-    spec). Removed unused PNG_STATIC from pngpriv.h.
-  Fixed the simplified API example programs and improved the error message
-    if the version field is not set.
-  Updated simplified API synopses and description of the png_image structure
-    in the manual.
-  Made makepng and pngtest produce identical PNGs, add "--relaxed" option
-    to pngtest. The "--relaxed" option turns off the benign errors that are
-    enabled by default in pre-RC builds. makepng can now write ICC profiles
-    where the length has not been extended to a multiple of 4, and pngtest
-    now intercepts all libpng errors, allowing the previously-introduced
-    "--strict test" on no warnings to actually work.
-  Added a work around for GCC 4.2 optimization bug.
-  Marked the broken (bad white point) original HP sRGB profiles correctly and
-    correct comments.
-  Added -DZ_SOLO to contrib/pngminim/*/makefile to work with zlib-1.2.7
-  Use /MDd for vstudio debug builds. Also added pngunkown to the vstudio
-    builds, fixed build errors and corrected a minor exit code error in
-    pngvalid if the 'touch' file name is invalid.
-  Add updated WARNING file to projects/vstudio from libpng 1.5/vstudio
-  Fixed build when using #define PNG_NO_READ_GAMMA in png_do_compose() in
-    pngrtran.c (Domani Hannes).
-  Made pngvalid so that it will build outside the libpng source tree.
-  Made PNG_NO_READ_GAMMA switch off interfaces that depend on READ_GAMMA.
-    Prior to 1.6.0 switching off READ_GAMMA did unpredictable things to the
-    interfaces that use it (specifically, png_do_background in 1.4 would
-    simply display composite for grayscale images but do composition
-    with the incorrect arithmetic for color ones). In 1.6 the semantic
-    of -DPNG_NO_READ_GAMMA is changed to simply disable any interface that
-    depends on it; this obliges people who set it to consider whether they
-    really want it off if they happen to use any of the interfaces in
-    question (typically most users who disable it won't).
-  Added the ability for contrib/libtests/makepng.c to make a PNG with just one
-    color. This is useful for debugging pngstest color inaccuracy reports.
-  Made png_user_version_check() ok to use with libpng version 1.10.x and later.
-  Fixed typo in png.c (PNG_SET_CHUNK_MALLOC_MAX should be PNG_CHUNK_MALLOC_MAX)
-    that causes the MALLOC_MAX limit not to work (John Bowler)
-  Change png_warning() to png_app_error() in pngwrite.c and comment the
-    fall-through condition.
-  Change png_warning() to png_app_warning() in png_write_tRNS().
-  Rearranged the ARM-NEON optimizations: Isolated the machine specific code
-    to the hardware subdirectory and added comments to pngrutil.c so that
-    implementors of other optimizations know what to do.
-  Fixed cases of unquoted DESTDIR in Makefile.am
-  Cleaned up whitespace in the synopsis portion of the manpage "libpng.3"
-  Disassembled the version number in scripts/options.awk (necessary for
-    building on SunOs).
-  Made default Zlib compression settings be configurable. This adds #defines to
-    pnglibconf.h to control the defaults.
-  Fixed Windows build issues, enabled ARM compilation. Various warnings issued
-    by earlier versions of GCC fixed for Cygwin and Min/GW (which both use old
-    GCCs.) ARM support is enabled by default in zlib.props (unsupported by
-    Microsoft) and ARM compilation is made possible by deleting the check for
-    x86. The test programs cannot be run because they are not signed.
-  Discontinued distributing libpng-1.x.x.tar.bz2.
-  Discontinued distributing libpng-1.7.0-1.6.0-diff.txt and similar.
-  Rebuilt Makefile.in, configure, etc., with autoconf-2.69 and automake-1.12.5.
-  Fixed 'make distcheck' on SUN OS - libpng.so was not being removed
-  Fixed conceivable but difficult to repro overflow. Also added two test
-    programs to generate and test a PNG which should have the problem.
-  Added overflow detection in png_set_sPLT() and png_set_text_2().
-  Use consistent handling of overflows in text, sPLT and unknown png_set_* APIs
-  Added png_get_palette_max() function.
-  Fixed missing dependency in --prefix builds The intermediate
-    internal 'prefix.h' file can only be generated correctly after
-    pnglibconf.h, however the dependency was not in Makefile.am.  The
-    symptoms are unpredictable depending on the order make chooses to
-    build pngprefix.h and pnglibconf.h, often the error goes unnoticed
-    because there is a system pnglibconf.h to use instead.
-  Enclosed the new png_get_palette_max in #ifdef PNG_GET_PALETTE_MAX_SUPPORTED
-    block, and revised pnglibconf.h and pnglibconf.h.prebuilt accordingly.
+  Made symbol prefixing work with the ARM neon optimizations. Also allow
+    pngpriv.h to be included for preprocessor definitions only, so it can
+    be used in non-C/C++ files. Back ported from libpng 1.7.
+  Made sRGB check numbers consistent.
+  Ported libpng 1.5 options.awk/dfn file handling to 1.6, fixed one bug.
+  Removed cc -E workround, corrected png_get_palette_max API Tested on
+    SUN OS cc 5.9, which demonstrates the tokenization problem previously
+    avoided by using /lib/cpp.  Since all .dfn output is now protected in
+    double quotes unless it is to be macro substituted the fix should
+    work everywhere.
+  Enabled parallel tests - back ported from libpng-1.7.
+  scripts/pnglibconf.dfa formatting improvements back ported from libpng17.
+  Fixed a race condition in the creation of the build 'scripts' directory
+    while building with a parallel make.
+  Use approved/supported Android method to check for NEON, use Linux/POSIX
+    1003.1 API to check /proc/self/auxv avoiding buffer allocation and other
+    library calls (ported from libpng15).
+  Use parentheses more consistently in "#if defined(MACRO)" tests.
+  Folded long lines.
+  Reenabled code to allow zero length PLTE chunks for MNG.
+  Fixed ALIGNED_MEMORY support.
+  Allow run-time ARM NEON checking to be disabled. A new configure option:
+    --enable-arm-neon=always will stop the run-time checks. New checks
+    within arm/arm_init.c will cause the code not to be compiled unless
+    __ARM_NEON__ is set. This should make it fail safe (if someone asks
+    for it on then the build will fail if it can't be done.)
+  Updated the INSTALL document.
+  Revised INSTALL to recommend using CPPFLAGS instead of INCLUDES.
+  Revised scripts/makefile.freebsd to respect ZLIBLIB and ZLIBINC.
+  Revised scripts/dfn.awk to work with the buggy MSYS awk that has trouble
+    with CRLF line endings.
+  Avoid a possible memory leak in contrib/gregbook/readpng.c
+  Better documentation of unknown handling API interactions.
+  Corrected Android builds and corrected libpng.vers with symbol
+    prefixing This adds an API to set optimization options externally,
+    providing an alternative and general solution for the non-portable
+    run-time tests used by the ARM Neon code.  It also makes those tests
+    compile and link on Android.
+  The order of settings vs options in pnglibconf.h is reversed to allow
+    settings to depend on options and options can now set (or override) the
+    defaults for settings.
+  Corrected simplified API default gamma for color-mapped output, added
+    a flag to change default. In 1.6.0 when the simplified API was used
+    to produce color-mapped output from an input image with no gamma
+    information the gamma assumed for the input could be different from
+    that assumed for non-color-mapped output.  In particular 16-bit depth
+    input files were assumed to be sRGB encoded, whereas in the 'direct'
+    case they were assumed to have linear data.  This was an error.  The
+    fix makes the simplified API treat all input files the same way and
+    adds a new flag to the png_image::flags member to allow the
+    application/user to specify that 16-bit files contain sRGB data
+    rather than the default linear.
+  Fixed bugs in the pngpixel and makepng test programs.
+  Fixed CMakelists.txt to allow building a single variant of the library
+    (Claudio Bley):
+  Introduced a PNG_LIB_TARGETS variable that lists all activated library
+    targets.  It is an error if this variable ends up empty, ie. you have
+    to build at least one library variant.
+  Made the *_COPY targets only depend on library targets actually being build.
+  Use PNG_LIB_TARGETS to unify a code path.
+  Changed the CREATE_SYMLINK macro to expect the full path to a file as the
+    first argument. When symlinking the filename component of that path is
+    determined and used as the link target.
+  Use copy_if_different in the CREATE_SYMLINK macro.
+  Eliminated two warnings from the Intel C compiler. The warnings are
+    technically valid, although a reasonable treatment of division would
+    show it to be incorrect.
 
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net
 (subscription required; visit
index b7e8cca519460aa0d8566382ca5f28665d7d83c9..38254081723876bc385c8a3d7b66b8069ac90947 100644 (file)
@@ -3672,7 +3672,8 @@ Version 1.5.6 [November 3, 2011]
   No changes.
 
 Version 1.5.7beta01 [November 4, 2011]
-  Added support for ARM processor (Mans Rullgard)
+  Added support for ARM processor, when decoding all PNG up-filtered rows
+    and any other-filtered rows with 3 or 4 bytes per pixel (Mans Rullgard).
   Fixed bug in pngvalid on early allocation failure; fixed type cast in
     pngmem.c; pngvalid would attempt to call png_error() if the allocation
     of a png_struct or png_info failed. This would probably have led to a
@@ -4381,6 +4382,97 @@ Version 1.6.0rc08 [February 10, 2013]
 Version 1.6.0 [February 14, 2013]
   No changes.
 
+Version 1.6.1beta01 [February 16, 2013]
+  Made symbol prefixing work with the ARM neon optimizations. Also allow
+    pngpriv.h to be included for preprocessor definitions only, so it can
+    be used in non-C/C++ files. Back ported from libpng 1.7.
+  Made sRGB check numbers consistent.
+  Ported libpng 1.5 options.awk/dfn file handling to 1.6, fixed one bug.
+  Removed cc -E workround, corrected png_get_palette_max API Tested on
+    SUN OS cc 5.9, which demonstrates the tokenization problem previously
+    avoided by using /lib/cpp.  Since all .dfn output is now protected in
+    double quotes unless it is to be macro substituted the fix should
+    work everywhere.
+  Enabled parallel tests - back ported from libpng-1.7.
+  scripts/pnglibconf.dfa formatting improvements back ported from libpng17.
+  Fixed a race condition in the creation of the build 'scripts' directory
+    while building with a parallel make.
+  Use approved/supported Android method to check for NEON, use Linux/POSIX
+    1003.1 API to check /proc/self/auxv avoiding buffer allocation and other
+    library calls (ported from libpng15).
+
+Version 1.6.1beta02 [February 19, 2013]
+  Use parentheses more consistently in "#if defined(MACRO)" tests.
+  Folded long lines.
+  Reenabled code to allow zero length PLTE chunks for MNG.
+
+Version 1.6.1beta03 [February 22, 2013]
+  Fixed ALIGNED_MEMORY support.
+  Allow run-time ARM NEON checking to be disabled. A new configure option:
+    --enable-arm-neon=always will stop the run-time checks. New checks
+    within arm/arm_init.c will cause the code not to be compiled unless
+    __ARM_NEON__ is set. This should make it fail safe (if someone asks
+    for it on then the build will fail if it can't be done.)
+  Updated the INSTALL document.
+
+Version 1.6.1beta04 [February 27, 2013]
+  Revised INSTALL to recommend using CPPFLAGS instead of INCLUDES.
+  Revised scripts/makefile.freebsd to respect ZLIBLIB and ZLIBINC.
+  Revised scripts/dfn.awk to work with the buggy MSYS awk that has trouble
+    with CRLF line endings.
+
+Version 1.6.1beta05 [March 1, 2013]
+  Avoid a possible memory leak in contrib/gregbook/readpng.c
+
+Version 1.6.1beta06 [March 4, 2013]
+  Better documentation of unknown handling API interactions.
+  Corrected Android builds and corrected libpng.vers with symbol
+    prefixing This adds an API to set optimization options externally,
+    providing an alternative and general solution for the non-portable
+    run-time tests used by the ARM Neon code.  It also makes those tests
+    compile and link on Android.
+  The order of settings vs options in pnglibconf.h is reversed to allow
+    settings to depend on options and options can now set (or override) the
+    defaults for settings.
+
+Version 1.6.1beta07 [March 7, 2013]
+  Corrected simplified API default gamma for color-mapped output, added
+    a flag to change default. In 1.6.0 when the simplified API was used
+    to produce color-mapped output from an input image with no gamma
+    information the gamma assumed for the input could be different from
+    that assumed for non-color-mapped output.  In particular 16-bit depth
+    input files were assumed to be sRGB encoded, whereas in the 'direct'
+    case they were assumed to have linear data.  This was an error.  The
+    fix makes the simplified API treat all input files the same way and
+    adds a new flag to the png_image::flags member to allow the
+    application/user to specify that 16-bit files contain sRGB data
+    rather than the default linear.
+  Fixed bugs in the pngpixel and makepng test programs.
+
+Version 1.6.1beta08 [March 7, 2013]
+  Fixed CMakelists.txt to allow building a single variant of the library
+    (Claudio Bley):
+  Introduced a PNG_LIB_TARGETS variable that lists all activated library
+    targets.  It is an error if this variable ends up empty, ie. you have
+    to build at least one library variant.
+  Made the *_COPY targets only depend on library targets actually being build.
+  Use PNG_LIB_TARGETS to unify a code path.
+  Changed the CREATE_SYMLINK macro to expect the full path to a file as the
+    first argument. When symlinking the filename component of that path is
+    determined and used as the link target.
+  Use copy_if_different in the CREATE_SYMLINK macro.
+
+Version 1.6.1beta09 [March 13, 2013]
+  Eliminated two warnings from the Intel C compiler. The warnings are
+    technically valid, although a reasonable treatment of division would
+    show it to be incorrect.
+
+Version 1.6.1rc01 [March 21, 2013]
+  No changes.
+
+Version 1.6.1 [March 28, 2013]
+  No changes.
+
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net
 (subscription required; visit
 https://lists.sourceforge.net/lists/listinfo/png-mng-implement
index 728a419e319c418312b98b2b5c96723f62e14c8c..1ebf0da8601b2e7d63b0ea3d1a003b00e3516fce 100644 (file)
@@ -35,7 +35,7 @@ enable_testing()
 
 set(PNGLIB_MAJOR 1)
 set(PNGLIB_MINOR 6)
-set(PNGLIB_RELEASE 0)
+set(PNGLIB_RELEASE 1)
 set(PNGLIB_NAME libpng${PNGLIB_MAJOR}${PNGLIB_MINOR})
 set(PNGLIB_VERSION ${PNGLIB_MAJOR}.${PNGLIB_MINOR}.${PNGLIB_RELEASE})
 
@@ -139,8 +139,11 @@ endif()
 # NOW BUILD OUR TARGET
 include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${ZLIB_INCLUDE_DIR})
 
+unset(PNG_LIB_TARGETS)
+
 if(PNG_SHARED)
   add_library(${PNG_LIB_NAME} SHARED ${libpng_sources})
+  set(PNG_LIB_TARGETS ${PNG_LIB_NAME})
   if(MSVC)
     # msvc does not append 'lib' - do it here to have consistent name
     set_target_properties(${PNG_LIB_NAME} PROPERTIES PREFIX "lib")
@@ -153,6 +156,7 @@ if(PNG_STATIC)
 # does not work without changing name
   set(PNG_LIB_NAME_STATIC ${PNG_LIB_NAME}_static)
   add_library(${PNG_LIB_NAME_STATIC} STATIC ${libpng_sources})
+  list(APPEND PNG_LIB_TARGETS ${PNG_LIB_NAME_STATIC})
   if(MSVC)
     # msvc does not append 'lib' - do it here to have consistent name
     set_target_properties(${PNG_LIB_NAME_STATIC} PROPERTIES PREFIX "lib")
@@ -160,6 +164,12 @@ if(PNG_STATIC)
   target_link_libraries(${PNG_LIB_NAME_STATIC} ${ZLIB_LIBRARY} ${M_LIBRARY})
 endif()
 
+if(NOT PNG_LIB_TARGETS)
+  message(SEND_ERROR
+    "No library variant selected to build. "
+    "Please enable at least one of the following options: PNG_STATIC, PNG_SHARED")
+endif()
+
 if(PNG_SHARED AND WIN32)
   set_target_properties(${PNG_LIB_NAME} PROPERTIES DEFINE_SYMBOL PNG_BUILD_DLL)
 endif()
@@ -222,14 +232,15 @@ macro(CREATE_SYMLINK SRC_FILE DEST_FILE)
   if(WIN32 AND NOT CYGWIN AND NOT MSYS)
     ADD_CUSTOM_COMMAND(
         OUTPUT ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${DEST_FILE}   ${CMAKE_CURRENT_BINARY_DIR}/${DEST_FILE}
-        COMMAND ${CMAKE_COMMAND} -E copy        ${CMAKE_CURRENT_BINARY_DIR}/${SRC_FILE} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${DEST_FILE}
-        COMMAND ${CMAKE_COMMAND} -E copy        ${CMAKE_CURRENT_BINARY_DIR}/${SRC_FILE} ${CMAKE_CURRENT_BINARY_DIR}/${DEST_FILE}
-        DEPENDS ${PNG_LIB_NAME} ${PNG_LIB_NAME_STATIC}
+        COMMAND ${CMAKE_COMMAND} -E copy_if_different  "${SRC_FILE}" ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${DEST_FILE}
+        COMMAND ${CMAKE_COMMAND} -E copy_if_different  "${SRC_FILE}" ${CMAKE_CURRENT_BINARY_DIR}/${DEST_FILE}
+        DEPENDS ${PNG_LIB_TARGETS}
         )
     ADD_CUSTOM_TARGET(${DEST_FILE}_COPY ALL DEPENDS ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${DEST_FILE})
   else(WIN32 AND NOT CYGWIN AND NOT MSYS)
-    execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ${SRC_FILE} ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${DEST_FILE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
-    execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ${SRC_FILE} ${DEST_FILE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+    get_filename_component(LINK_TARGET "${SRC_FILE}" NAME)
+    execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink "${LINK_TARGET}" ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${DEST_FILE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+    execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink "${LINK_TARGET}" ${DEST_FILE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
   endif(WIN32 AND NOT CYGWIN AND NOT MSYS)
 endmacro()
 
@@ -260,7 +271,7 @@ endif(NOT WIN32 OR CYGWIN OR MINGW)
 # SET UP LINKS
 if(PNG_SHARED)
   set_target_properties(${PNG_LIB_NAME} PROPERTIES
-#   VERSION 16.${PNGLIB_RELEASE}.1.6.0
+#   VERSION 16.${PNGLIB_RELEASE}.1.6.1
     VERSION 16.${PNGLIB_RELEASE}.0
     SOVERSION 16
     CLEAN_DIRECT_OUTPUT 1)
@@ -287,40 +298,33 @@ endif()
 
 # INSTALL
 if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL )
-  if(PNG_SHARED)
-    install(TARGETS ${PNG_LIB_NAME}
-        ${PNG_EXPORT_RULE}
-        RUNTIME DESTINATION bin
-        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
-        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
+  install(TARGETS ${PNG_LIB_TARGETS}
+      ${PNG_EXPORT_RULE}
+      RUNTIME DESTINATION bin
+      LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+      ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
 
+  if(PNG_SHARED)
     # Create a symlink for libpng.dll.a => libpng16.dll.a on Cygwin
     if(CYGWIN OR MINGW)
        get_target_property(BUILD_TARGET_LOCATION ${PNG_LIB_NAME} LOCATION_${CMAKE_BUILD_TYPE})
-       get_filename_component(BUILD_TARGET_FILE ${BUILD_TARGET_LOCATION} NAME)
-       CREATE_SYMLINK(${BUILD_TARGET_FILE} libpng${CMAKE_IMPORT_LIBRARY_SUFFIX})
+       CREATE_SYMLINK(${BUILD_TARGET_LOCATION} libpng${CMAKE_IMPORT_LIBRARY_SUFFIX})
        install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpng${CMAKE_IMPORT_LIBRARY_SUFFIX}
          DESTINATION ${CMAKE_INSTALL_LIBDIR})
     endif(CYGWIN OR MINGW)
 
     if(NOT WIN32)
       get_target_property(BUILD_TARGET_LOCATION ${PNG_LIB_NAME} LOCATION_${CMAKE_BUILD_TYPE})
-      get_filename_component(BUILD_TARGET_FILE ${BUILD_TARGET_LOCATION} NAME)
-      CREATE_SYMLINK(${BUILD_TARGET_FILE} libpng${CMAKE_SHARED_LIBRARY_SUFFIX})
+      CREATE_SYMLINK(${BUILD_TARGET_LOCATION} libpng${CMAKE_SHARED_LIBRARY_SUFFIX})
       install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpng${CMAKE_SHARED_LIBRARY_SUFFIX}
          DESTINATION ${CMAKE_INSTALL_LIBDIR})
     endif(NOT WIN32)
   endif(PNG_SHARED)
 
   if(PNG_STATIC)
-    install(TARGETS ${PNG_LIB_NAME_STATIC}
-        ${PNG_EXPORT_RULE}
-        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
-        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
     if(NOT WIN32 OR CYGWIN OR MINGW)
       get_target_property(BUILD_TARGET_LOCATION ${PNG_LIB_NAME_STATIC} LOCATION_${CMAKE_BUILD_TYPE})
-      get_filename_component(BUILD_TARGET_FILE ${BUILD_TARGET_LOCATION} NAME)
-      CREATE_SYMLINK(${BUILD_TARGET_FILE} libpng${CMAKE_STATIC_LIBRARY_SUFFIX})
+      CREATE_SYMLINK(${BUILD_TARGET_LOCATION} libpng${CMAKE_STATIC_LIBRARY_SUFFIX})
       install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpng${CMAKE_STATIC_LIBRARY_SUFFIX}
          DESTINATION ${CMAKE_INSTALL_LIBDIR})
     endif(NOT WIN32 OR CYGWIN OR MINGW)
index 2644c7a4f892e189f07b13e07b2ddc4b95cd2b9a..f987378009856bde14e8c371a6852799d2fa2d4d 100644 (file)
@@ -41,19 +41,33 @@ is not already on your system.  zlib can usually be found
 wherever you got libpng.  zlib can be placed in another directory,
 at the same level as libpng.
 
+If your system already has a preinstalled zlib you will still need
+to have access to the zlib.h and zconf.h include files that
+correspond to the version of zlib that's installed.
+
+If you wish to test with a particular zlib that is not first in the
+standard library search path, put ZLIBLIB, ZLIBINC, CPPFLAGS, LDFLAGS,
+and LD_LIBRARY_PATH in your environment before running "make test"
+or "make distcheck":
+
+ZLIBLIB=/path/to/lib export ZLIBLIB
+ZLIBINC=/path/to/include export ZLIBINC
+CPPFLAGS="-I$ZLIBINC" export CPPFLAGS
+LDFLAGS="-L$ZLIBLIB" export LDFLAGS
+LD_LIBRARY_PATH="$ZLIBLIB:$LD_LIBRARY_PATH" export LD_LIBRARY_PATH
+
+If you are using one of the makefile scripts, put ZLIBLIB and ZLIBINC
+in your environment and type "make ZLIBLIB=$ZLIBLIB ZLIBINC=$ZLIBINC test".
+
 If you want to use "cmake" (see www.cmake.org), type
 
    cmake . -DCMAKE_INSTALL_PREFIX=/path
    make
    make install
 
-If your system already has a preinstalled zlib you will still need
-to have access to the zlib.h and zconf.h include files that
-correspond to the version of zlib that's installed.
-
 You can rename the directories that you downloaded (they
-might be called "libpng-x.y.z" or "libpngNN" and "zlib-1.2.5"
-or "zlib125") so that you have directories called "zlib" and "libpng".
+might be called "libpng-x.y.z" or "libpngNN" and "zlib-1.2.7"
+or "zlib127") so that you have directories called "zlib" and "libpng".
 
 Your directory structure should look like this:
 
@@ -71,6 +85,7 @@ Your directory structure should look like this:
              depcomp, install-sh, mkinstalldirs, test-pngtest.sh
           contrib
              gregbook
+             libtests
              pngminim
              pngminus
              pngsuite
index e95d3598b4368f8ef15e6cbd0521c684a0634c5f..d86a7da262e84dc9d7f0777f6c540641831dfbf6 100644 (file)
@@ -10,7 +10,7 @@ this sentence.
 
 This code is released under the libpng license.
 
-libpng versions 1.2.6, August 15, 2004, through 1.6.0, February 14, 2013, are
+libpng versions 1.2.6, August 15, 2004, through 1.6.1, March 28, 2013, are
 Copyright (c) 2004, 2006-2012 Glenn Randers-Pehrson, and are
 distributed according to the same disclaimer and license as libpng-1.2.5
 with the following individual added to the list of Contributing Authors
@@ -108,4 +108,4 @@ certification mark of the Open Source Initiative.
 
 Glenn Randers-Pehrson
 glennrp at users.sourceforge.net
-February 14, 2013
+March 28, 2013
index ca44c68d45896321e4c0e3f5d80d3afeed272e58..a2cd2c10bb33a7c100dbe69f28235512798c8723 100644 (file)
@@ -7,24 +7,44 @@ PNGLIB_BASENAME= libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@
 ACLOCAL_AMFLAGS = -I scripts
 
 # test programs - run on make check, make distcheck
-TESTS_ENVIRONMENT= srcdir=$(srcdir)
-check_PROGRAMS= pngtest
+check_PROGRAMS= pngtest pngunknown pngstest pngvalid
+
 pngtest_SOURCES = pngtest.c
 pngtest_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
-TESTS = test-pngtest.sh
 
-# Only do the following if the contrib directory is present.
-check_PROGRAMS+= pngvalid pngstest pngunknown
 pngvalid_SOURCES = contrib/libtests/pngvalid.c
-pngstest_SOURCES = contrib/libtests/pngstest.c
-pngunknown_SOURCES = contrib/libtests/pngunknown.c
 pngvalid_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
+
+pngstest_SOURCES = contrib/libtests/pngstest.c
 pngstest_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
+
+pngunknown_SOURCES = contrib/libtests/pngunknown.c
 pngunknown_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
-TESTS += contrib/libtests/test-pngunknown.sh\
-        contrib/libtests/test-pngvalid-simple.sh\
-        contrib/libtests/test-pngvalid-full.sh\
-        contrib/libtests/test-pngstest.sh
+
+# Generally these are single line shell scripts to run a test with a particular
+# set of parameters:
+TESTS =\
+   tests/pngtest\
+   tests/pngvalid-gamma-16-to-8 tests/pngvalid-gamma-alpha-mode\
+   tests/pngvalid-gamma-background tests/pngvalid-gamma-expand16-alpha-mode\
+   tests/pngvalid-gamma-expand16-background\
+   tests/pngvalid-gamma-expand16-transform tests/pngvalid-gamma-sbit\
+   tests/pngvalid-gamma-threshold tests/pngvalid-gamma-transform\
+   tests/pngvalid-progressive-interlace-size\
+   tests/pngvalid-progressive-interlace-standard\
+   tests/pngvalid-progressive-interlace-transform\
+   tests/pngvalid-progressive-standard tests/pngvalid-standard\
+   tests/pngstest-0g01 tests/pngstest-0g02 tests/pngstest-0g04\
+   tests/pngstest-0g08 tests/pngstest-0g16 tests/pngstest-2c08\
+   tests/pngstest-2c16 tests/pngstest-3p01 tests/pngstest-3p02\
+   tests/pngstest-3p04 tests/pngstest-3p08 tests/pngstest-4a08\
+   tests/pngstest-4a16 tests/pngstest-6a08 tests/pngstest-6a16\
+   tests/pngstest-error tests/pngunknown-IDAT\
+   tests/pngunknown-discard tests/pngunknown-if-safe tests/pngunknown-sAPI\
+   tests/pngunknown-sTER tests/pngunknown-save tests/pngunknown-vpAg
+
+# These tests are expected, and required, to fail:
+XFAIL_TESTS = tests/pngstest-error
 
 # man pages
 dist_man_MANS= libpng.3 libpngpf.3 png.5
@@ -77,12 +97,14 @@ nodist_pkginclude_HEADERS= pnglibconf.h
 pkgconfigdir = @pkgconfigdir@
 pkgconfig_DATA = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.pc
 
-#extra source distribution files.
+# Extra source distribution files, '${srcdir}' is used below to stop build files
+# from those directories being included.  This only works if the configure is
+# not done in the source directory!
 EXTRA_DIST= \
        ANNOUNCE CHANGES INSTALL LICENSE README TODO \
        pngtest.png pngbar.png pngnow.png pngbar.jpg autogen.sh \
        ${srcdir}/contrib ${srcdir}/projects ${srcdir}/scripts \
-       $(TESTS) \
+       $(TESTS) $(XFAIL_TESTS) tests/pngstest \
        CMakeLists.txt example.c libpng-manual.txt
 
 SCRIPT_CLEANFILES=scripts/*.out scripts/*.chk scripts/pnglibconf.dfn
@@ -180,16 +202,14 @@ SYMBOL_CFLAGS += -DPNG_PREFIX='@PNG_PREFIX@'
 endif
 
 .dfn.out:
-       rm -f $@ $*.c $*.tf[123]
-       test -d scripts || mkdir scripts
+       rm -f $@ $*.c $*.tf[12]
+       test -d scripts || mkdir scripts || test -d scripts
        echo '#include "$<"' >$*.c
        $(DFNCPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES)\
            $(CPPFLAGS) $(SYMBOL_CFLAGS) $*.c > $*.tf1
-       $(SED) -n -e 's|^.*PNG_DEFN_MAGIC *-\(.*\)- *PNG_DEFN_END.*$$|\1|p'\
-           $*.tf1 >$*.tf2
-       $(SED) -e 's| *PNG_JOIN *||g' -e 's| *$$||' $*.tf2 >$*.tf3
-       rm -f $*.c $*.tf[12]
-       mv $*.tf3 $@
+       $(AWK) -f "${srcdir}/scripts/dfn.awk" out="$*.tf2" $*.tf1 1>&2
+       rm -f $*.c $*.tf1
+       mv $*.tf2 $@
 
 # The .dfn file for pnglibconf.h is machine generated
 pnglibconf.dfn: scripts/pnglibconf.dfa scripts/options.awk pngconf.h pngusr.dfa $(DFA_XTRA)
index 2341ab74cfc3d94db646adb144c3888530c9aa68..5cd574713f9da0e5283f113fa8ebc3c108b559ca 100644 (file)
@@ -56,8 +56,8 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
-check_PROGRAMS = pngtest$(EXEEXT) pngvalid$(EXEEXT) pngstest$(EXEEXT) \
-       pngunknown$(EXEEXT)
+check_PROGRAMS = pngtest$(EXEEXT) pngunknown$(EXEEXT) \
+       pngstest$(EXEEXT) pngvalid$(EXEEXT)
 @PNG_ARM_NEON_TRUE@am__append_1 = arm/arm_init.c\
 @PNG_ARM_NEON_TRUE@    arm/filter_neon.S
 
@@ -73,8 +73,8 @@ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
        $(top_srcdir)/configure $(am__configure_deps) \
        $(srcdir)/config.h.in $(srcdir)/libpng.pc.in \
        $(srcdir)/libpng-config.in depcomp $(dist_man_MANS) \
-       $(pkginclude_HEADERS) INSTALL README TODO config.guess \
-       config.sub install-sh missing ltmain.sh
+       $(pkginclude_HEADERS) test-driver INSTALL README TODO \
+       config.guess config.sub install-sh missing ltmain.sh
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/scripts/libtool.m4 \
        $(top_srcdir)/scripts/ltoptions.m4 \
@@ -244,7 +244,7 @@ am__define_uniq_tagged_files = \
 ETAGS = etags
 CTAGS = ctags
 CSCOPE = cscope
-AM_RECURSIVE_TARGETS = cscope
+AM_RECURSIVE_TARGETS = cscope check recheck
 am__tty_colors_dummy = \
   mgn= red= grn= lgn= blu= brg= std=; \
   am__color_tests=no
@@ -267,6 +267,160 @@ am__tty_colors = { \
     std='\e[m'; \
   fi; \
 }
+am__recheck_rx = ^[    ]*:recheck:[    ]*
+am__global_test_result_rx = ^[         ]*:global-test-result:[         ]*
+am__copy_in_global_log_rx = ^[         ]*:copy-in-global-log:[         ]*
+# A command that, given a newline-separated list of test names on the
+# standard input, print the name of the tests that are to be re-run
+# upon "make recheck".
+am__list_recheck_tests = $(AWK) '{ \
+  recheck = 1; \
+  while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+    { \
+      if (rc < 0) \
+        { \
+          if ((getline line2 < ($$0 ".log")) < 0) \
+           recheck = 0; \
+          break; \
+        } \
+      else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \
+        { \
+          recheck = 0; \
+          break; \
+        } \
+      else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \
+        { \
+          break; \
+        } \
+    }; \
+  if (recheck) \
+    print $$0; \
+  close ($$0 ".trs"); \
+  close ($$0 ".log"); \
+}'
+# A command that, given a newline-separated list of test names on the
+# standard input, create the global log from their .trs and .log files.
+am__create_global_log = $(AWK) ' \
+function fatal(msg) \
+{ \
+  print "fatal: making $@: " msg | "cat >&2"; \
+  exit 1; \
+} \
+function rst_section(header) \
+{ \
+  print header; \
+  len = length(header); \
+  for (i = 1; i <= len; i = i + 1) \
+    printf "="; \
+  printf "\n\n"; \
+} \
+{ \
+  copy_in_global_log = 1; \
+  global_test_result = "RUN"; \
+  while ((rc = (getline line < ($$0 ".trs"))) != 0) \
+    { \
+      if (rc < 0) \
+         fatal("failed to read from " $$0 ".trs"); \
+      if (line ~ /$(am__global_test_result_rx)/) \
+        { \
+          sub("$(am__global_test_result_rx)", "", line); \
+          sub("[       ]*$$", "", line); \
+          global_test_result = line; \
+        } \
+      else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \
+        copy_in_global_log = 0; \
+    }; \
+  if (copy_in_global_log) \
+    { \
+      rst_section(global_test_result ": " $$0); \
+      while ((rc = (getline line < ($$0 ".log"))) != 0) \
+      { \
+        if (rc < 0) \
+          fatal("failed to read from " $$0 ".log"); \
+        print line; \
+      }; \
+      printf "\n"; \
+    }; \
+  close ($$0 ".trs"); \
+  close ($$0 ".log"); \
+}'
+# Restructured Text title.
+am__rst_title = { sed 's/.*/   &   /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; }
+# Solaris 10 'make', and several other traditional 'make' implementations,
+# pass "-e" to $(SHELL), and POSIX 2008 even requires this.  Work around it
+# by disabling -e (using the XSI extension "set +e") if it's set.
+am__sh_e_setup = case $$- in *e*) set +e;; esac
+# Default flags passed to test drivers.
+am__common_driver_flags = \
+  --color-tests "$$am__color_tests" \
+  --enable-hard-errors "$$am__enable_hard_errors" \
+  --expect-failure "$$am__expect_failure"
+# To be inserted before the command running the test.  Creates the
+# directory for the log if needed.  Stores in $dir the directory
+# containing $f, in $tst the test, in $log the log.  Executes the
+# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and
+# passes TESTS_ENVIRONMENT.  Set up options for the wrapper that
+# will run the test scripts (or their associated LOG_COMPILER, if
+# thy have one).
+am__check_pre = \
+$(am__sh_e_setup);                                     \
+$(am__vpath_adj_setup) $(am__vpath_adj)                        \
+$(am__tty_colors);                                     \
+srcdir=$(srcdir); export srcdir;                       \
+case "$@" in                                           \
+  */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;;   \
+    *) am__odir=.;;                                    \
+esac;                                                  \
+test "x$$am__odir" = x"." || test -d "$$am__odir"      \
+  || $(MKDIR_P) "$$am__odir" || exit $$?;              \
+if test -f "./$$f"; then dir=./;                       \
+elif test -f "$$f"; then dir=;                         \
+else dir="$(srcdir)/"; fi;                             \
+tst=$$dir$$f; log='$@';                                \
+if test -n '$(DISABLE_HARD_ERRORS)'; then              \
+  am__enable_hard_errors=no;                           \
+else                                                   \
+  am__enable_hard_errors=yes;                          \
+fi;                                                    \
+case " $(XFAIL_TESTS) " in                             \
+  *[\ \        ]$$f[\ \        ]* | *[\ \      ]$$dir$$f[\ \   ]*) \
+    am__expect_failure=yes;;                           \
+  *)                                                   \
+    am__expect_failure=no;;                            \
+esac;                                                  \
+$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT)
+# A shell command to get the names of the tests scripts with any registered
+# extension removed (i.e., equivalently, the names of the test logs, with
+# the '.log' extension removed).  The result is saved in the shell variable
+# '$bases'.  This honors runtime overriding of TESTS and TEST_LOGS.  Sadly,
+# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)",
+# since that might cause problem with VPATH rewrites for suffix-less tests.
+# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'.
+am__set_TESTS_bases = \
+  bases='$(TEST_LOGS)'; \
+  bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \
+  bases=`echo $$bases`
+RECHECK_LOGS = $(TEST_LOGS)
+TEST_SUITE_LOG = test-suite.log
+TEST_EXTENSIONS = @EXEEXT@ .test
+LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
+LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS)
+am__set_b = \
+  case '$@' in \
+    */*) \
+      case '$*' in \
+        */*) b='$*';; \
+          *) b=`echo '$@' | sed 's/\.log$$//'`; \
+       esac;; \
+    *) \
+      b='$*';; \
+  esac
+am__test_logs1 = $(TESTS:=.log)
+am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
+TEST_LOGS = $(am__test_logs2:.test.log=.log)
+TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver
+TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
+       $(TEST_LOG_FLAGS)
 DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
 distdir = $(PACKAGE)-$(VERSION)
 top_distdir = $(distdir)
@@ -435,22 +589,41 @@ top_builddir = @top_builddir@
 top_srcdir = @top_srcdir@
 PNGLIB_BASENAME = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@
 ACLOCAL_AMFLAGS = -I scripts
-
-# test programs - run on make check, make distcheck
-TESTS_ENVIRONMENT = srcdir=$(srcdir)
 pngtest_SOURCES = pngtest.c
 pngtest_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
-TESTS = test-pngtest.sh contrib/libtests/test-pngunknown.sh \
-       contrib/libtests/test-pngvalid-simple.sh \
-       contrib/libtests/test-pngvalid-full.sh \
-       contrib/libtests/test-pngstest.sh
 pngvalid_SOURCES = contrib/libtests/pngvalid.c
-pngstest_SOURCES = contrib/libtests/pngstest.c
-pngunknown_SOURCES = contrib/libtests/pngunknown.c
 pngvalid_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
+pngstest_SOURCES = contrib/libtests/pngstest.c
 pngstest_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
+pngunknown_SOURCES = contrib/libtests/pngunknown.c
 pngunknown_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
 
+# Generally these are single line shell scripts to run a test with a particular
+# set of parameters:
+TESTS = \
+   tests/pngtest\
+   tests/pngvalid-gamma-16-to-8 tests/pngvalid-gamma-alpha-mode\
+   tests/pngvalid-gamma-background tests/pngvalid-gamma-expand16-alpha-mode\
+   tests/pngvalid-gamma-expand16-background\
+   tests/pngvalid-gamma-expand16-transform tests/pngvalid-gamma-sbit\
+   tests/pngvalid-gamma-threshold tests/pngvalid-gamma-transform\
+   tests/pngvalid-progressive-interlace-size\
+   tests/pngvalid-progressive-interlace-standard\
+   tests/pngvalid-progressive-interlace-transform\
+   tests/pngvalid-progressive-standard tests/pngvalid-standard\
+   tests/pngstest-0g01 tests/pngstest-0g02 tests/pngstest-0g04\
+   tests/pngstest-0g08 tests/pngstest-0g16 tests/pngstest-2c08\
+   tests/pngstest-2c16 tests/pngstest-3p01 tests/pngstest-3p02\
+   tests/pngstest-3p04 tests/pngstest-3p08 tests/pngstest-4a08\
+   tests/pngstest-4a16 tests/pngstest-6a08 tests/pngstest-6a16\
+   tests/pngstest-error tests/pngunknown-IDAT\
+   tests/pngunknown-discard tests/pngunknown-if-safe tests/pngunknown-sAPI\
+   tests/pngunknown-sTER tests/pngunknown-save tests/pngunknown-vpAg
+
+
+# These tests are expected, and required, to fail:
+XFAIL_TESTS = tests/pngstest-error
+
 # man pages
 dist_man_MANS = libpng.3 libpngpf.3 png.5
 EXTRA_SCRIPTS = libpng-config libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@-config
@@ -475,12 +648,14 @@ pkginclude_HEADERS = png.h pngconf.h
 nodist_pkginclude_HEADERS = pnglibconf.h
 pkgconfig_DATA = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.pc
 
-#extra source distribution files.
+# Extra source distribution files, '${srcdir}' is used below to stop build files
+# from those directories being included.  This only works if the configure is
+# not done in the source directory!
 EXTRA_DIST = \
        ANNOUNCE CHANGES INSTALL LICENSE README TODO \
        pngtest.png pngbar.png pngnow.png pngbar.jpg autogen.sh \
        ${srcdir}/contrib ${srcdir}/projects ${srcdir}/scripts \
-       $(TESTS) \
+       $(TESTS) $(XFAIL_TESTS) tests/pngstest \
        CMakeLists.txt example.c libpng-manual.txt
 
 SCRIPT_CLEANFILES = scripts/*.out scripts/*.chk scripts/pnglibconf.dfn
@@ -506,7 +681,7 @@ all: config.h
        $(MAKE) $(AM_MAKEFLAGS) all-am
 
 .SUFFIXES:
-.SUFFIXES: .chk .dfn .out .S .c .lo .o .obj
+.SUFFIXES: .chk .dfn .out .S .c .lo .log .o .obj .test .test$(EXEEXT) .trs
 am--refresh: Makefile
        @:
 $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
@@ -997,98 +1172,427 @@ distclean-tags:
        -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
        -rm -f cscope.out cscope.in.out cscope.po.out cscope.files
 
-check-TESTS: $(TESTS)
-       @failed=0; all=0; xfail=0; xpass=0; skip=0; \
-       srcdir=$(srcdir); export srcdir; \
-       list=' $(TESTS) '; \
-       $(am__tty_colors); \
-       if test -n "$$list"; then \
-         for tst in $$list; do \
-           if test -f ./$$tst; then dir=./; \
-           elif test -f $$tst; then dir=; \
-           else dir="$(srcdir)/"; fi; \
-           if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \
-             all=`expr $$all + 1`; \
-             case " $(XFAIL_TESTS) " in \
-             *[\ \     ]$$tst[\ \      ]*) \
-               xpass=`expr $$xpass + 1`; \
-               failed=`expr $$failed + 1`; \
-               col=$$red; res=XPASS; \
-             ;; \
-             *) \
-               col=$$grn; res=PASS; \
-             ;; \
-             esac; \
-           elif test $$? -ne 77; then \
-             all=`expr $$all + 1`; \
-             case " $(XFAIL_TESTS) " in \
-             *[\ \     ]$$tst[\ \      ]*) \
-               xfail=`expr $$xfail + 1`; \
-               col=$$lgn; res=XFAIL; \
-             ;; \
-             *) \
-               failed=`expr $$failed + 1`; \
-               col=$$red; res=FAIL; \
-             ;; \
-             esac; \
-           else \
-             skip=`expr $$skip + 1`; \
-             col=$$blu; res=SKIP; \
-           fi; \
-           echo "$${col}$$res$${std}: $$tst"; \
-         done; \
-         if test "$$all" -eq 1; then \
-           tests="test"; \
-           All=""; \
-         else \
-           tests="tests"; \
-           All="All "; \
+# Recover from deleted '.trs' file; this should ensure that
+# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create
+# both 'foo.log' and 'foo.trs'.  Break the recipe in two subshells
+# to avoid problems with "make -n".
+.log.trs:
+       rm -f $< $@
+       $(MAKE) $(AM_MAKEFLAGS) $<
+
+# Leading 'am--fnord' is there to ensure the list of targets does not
+# exand to empty, as could happen e.g. with make check TESTS=''.
+am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck)
+am--force-recheck:
+       @:
+
+$(TEST_SUITE_LOG): $(TEST_LOGS)
+       @$(am__set_TESTS_bases); \
+       am__f_ok () { test -f "$$1" && test -r "$$1"; }; \
+       redo_bases=`for i in $$bases; do \
+                     am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \
+                   done`; \
+       if test -n "$$redo_bases"; then \
+         redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \
+         redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \
+         if $(am__make_dryrun); then :; else \
+           rm -f $$redo_logs && rm -f $$redo_results || exit 1; \
          fi; \
-         if test "$$failed" -eq 0; then \
-           if test "$$xfail" -eq 0; then \
-             banner="$$All$$all $$tests passed"; \
-           else \
-             if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
-             banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
-           fi; \
-         else \
-           if test "$$xpass" -eq 0; then \
-             banner="$$failed of $$all $$tests failed"; \
+       fi; \
+       if test -n "$$am__remaking_logs"; then \
+         echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \
+              "recursion detected" >&2; \
+       else \
+         am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \
+       fi; \
+       if $(am__make_dryrun); then :; else \
+         st=0;  \
+         errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \
+         for i in $$redo_bases; do \
+           test -f $$i.trs && test -r $$i.trs \
+             || { echo "$$errmsg $$i.trs" >&2; st=1; }; \
+           test -f $$i.log && test -r $$i.log \
+             || { echo "$$errmsg $$i.log" >&2; st=1; }; \
+         done; \
+         test $$st -eq 0 || exit 1; \
+       fi
+       @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \
+       ws='[   ]'; \
+       results=`for b in $$bases; do echo $$b.trs; done`; \
+       test -n "$$results" || results=/dev/null; \
+       all=`  grep "^$$ws*:test-result:"           $$results | wc -l`; \
+       pass=` grep "^$$ws*:test-result:$$ws*PASS"  $$results | wc -l`; \
+       fail=` grep "^$$ws*:test-result:$$ws*FAIL"  $$results | wc -l`; \
+       skip=` grep "^$$ws*:test-result:$$ws*SKIP"  $$results | wc -l`; \
+       xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \
+       xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \
+       error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \
+       if test `expr $$fail + $$xpass + $$error` -eq 0; then \
+         success=true; \
+       else \
+         success=false; \
+       fi; \
+       br='==================='; br=$$br$$br$$br$$br; \
+       result_count () \
+       { \
+           if test x"$$1" = x"--maybe-color"; then \
+             maybe_colorize=yes; \
+           elif test x"$$1" = x"--no-color"; then \
+             maybe_colorize=no; \
            else \
-             if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
-             banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
+             echo "$@: invalid 'result_count' usage" >&2; exit 4; \
            fi; \
-         fi; \
-         dashes="$$banner"; \
-         skipped=""; \
-         if test "$$skip" -ne 0; then \
-           if test "$$skip" -eq 1; then \
-             skipped="($$skip test was not run)"; \
+           shift; \
+           desc=$$1 count=$$2; \
+           if test $$maybe_colorize = yes && test $$count -gt 0; then \
+             color_start=$$3 color_end=$$std; \
            else \
-             skipped="($$skip tests were not run)"; \
+             color_start= color_end=; \
            fi; \
-           test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
-             dashes="$$skipped"; \
-         fi; \
-         report=""; \
-         if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
-           report="Please report to $(PACKAGE_BUGREPORT)"; \
-           test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
-             dashes="$$report"; \
-         fi; \
-         dashes=`echo "$$dashes" | sed s/./=/g`; \
-         if test "$$failed" -eq 0; then \
-           col="$$grn"; \
-         else \
-           col="$$red"; \
-         fi; \
-         echo "$${col}$$dashes$${std}"; \
-         echo "$${col}$$banner$${std}"; \
-         test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \
-         test -z "$$report" || echo "$${col}$$report$${std}"; \
-         echo "$${col}$$dashes$${std}"; \
-         test "$$failed" -eq 0; \
-       else :; fi
+           echo "$${color_start}# $$desc $$count$${color_end}"; \
+       }; \
+       create_testsuite_report () \
+       { \
+         result_count $$1 "TOTAL:" $$all   "$$brg"; \
+         result_count $$1 "PASS: " $$pass  "$$grn"; \
+         result_count $$1 "SKIP: " $$skip  "$$blu"; \
+         result_count $$1 "XFAIL:" $$xfail "$$lgn"; \
+         result_count $$1 "FAIL: " $$fail  "$$red"; \
+         result_count $$1 "XPASS:" $$xpass "$$red"; \
+         result_count $$1 "ERROR:" $$error "$$mgn"; \
+       }; \
+       {                                                               \
+         echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" |       \
+           $(am__rst_title);                                           \
+         create_testsuite_report --no-color;                           \
+         echo;                                                         \
+         echo ".. contents:: :depth: 2";                               \
+         echo;                                                         \
+         for b in $$bases; do echo $$b; done                           \
+           | $(am__create_global_log);                                 \
+       } >$(TEST_SUITE_LOG).tmp || exit 1;                             \
+       mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG);                     \
+       if $$success; then                                              \
+         col="$$grn";                                                  \
+        else                                                           \
+         col="$$red";                                                  \
+         test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG);               \
+       fi;                                                             \
+       echo "$${col}$$br$${std}";                                      \
+       echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}";   \
+       echo "$${col}$$br$${std}";                                      \
+       create_testsuite_report --maybe-color;                          \
+       echo "$$col$$br$$std";                                          \
+       if $$success; then :; else                                      \
+         echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}";         \
+         if test -n "$(PACKAGE_BUGREPORT)"; then                       \
+           echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \
+         fi;                                                           \
+         echo "$$col$$br$$std";                                        \
+       fi;                                                             \
+       $$success || exit 1
+
+check-TESTS:
+       @list='$(RECHECK_LOGS)';           test -z "$$list" || rm -f $$list
+       @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list
+       @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+       @set +e; $(am__set_TESTS_bases); \
+       log_list=`for i in $$bases; do echo $$i.log; done`; \
+       trs_list=`for i in $$bases; do echo $$i.trs; done`; \
+       log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \
+       $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \
+       exit $$?;
+recheck: all $(check_PROGRAMS)
+       @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
+       @set +e; $(am__set_TESTS_bases); \
+       bases=`for i in $$bases; do echo $$i; done \
+                | $(am__list_recheck_tests)` || exit 1; \
+       log_list=`for i in $$bases; do echo $$i.log; done`; \
+       log_list=`echo $$log_list`; \
+       $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \
+               am__force_recheck=am--force-recheck \
+               TEST_LOGS="$$log_list"; \
+       exit $$?
+tests/pngtest.log: tests/pngtest
+       @p='tests/pngtest'; \
+       b='tests/pngtest'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngvalid-gamma-16-to-8.log: tests/pngvalid-gamma-16-to-8
+       @p='tests/pngvalid-gamma-16-to-8'; \
+       b='tests/pngvalid-gamma-16-to-8'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngvalid-gamma-alpha-mode.log: tests/pngvalid-gamma-alpha-mode
+       @p='tests/pngvalid-gamma-alpha-mode'; \
+       b='tests/pngvalid-gamma-alpha-mode'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngvalid-gamma-background.log: tests/pngvalid-gamma-background
+       @p='tests/pngvalid-gamma-background'; \
+       b='tests/pngvalid-gamma-background'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngvalid-gamma-expand16-alpha-mode.log: tests/pngvalid-gamma-expand16-alpha-mode
+       @p='tests/pngvalid-gamma-expand16-alpha-mode'; \
+       b='tests/pngvalid-gamma-expand16-alpha-mode'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngvalid-gamma-expand16-background.log: tests/pngvalid-gamma-expand16-background
+       @p='tests/pngvalid-gamma-expand16-background'; \
+       b='tests/pngvalid-gamma-expand16-background'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngvalid-gamma-expand16-transform.log: tests/pngvalid-gamma-expand16-transform
+       @p='tests/pngvalid-gamma-expand16-transform'; \
+       b='tests/pngvalid-gamma-expand16-transform'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngvalid-gamma-sbit.log: tests/pngvalid-gamma-sbit
+       @p='tests/pngvalid-gamma-sbit'; \
+       b='tests/pngvalid-gamma-sbit'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngvalid-gamma-threshold.log: tests/pngvalid-gamma-threshold
+       @p='tests/pngvalid-gamma-threshold'; \
+       b='tests/pngvalid-gamma-threshold'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngvalid-gamma-transform.log: tests/pngvalid-gamma-transform
+       @p='tests/pngvalid-gamma-transform'; \
+       b='tests/pngvalid-gamma-transform'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngvalid-progressive-interlace-size.log: tests/pngvalid-progressive-interlace-size
+       @p='tests/pngvalid-progressive-interlace-size'; \
+       b='tests/pngvalid-progressive-interlace-size'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngvalid-progressive-interlace-standard.log: tests/pngvalid-progressive-interlace-standard
+       @p='tests/pngvalid-progressive-interlace-standard'; \
+       b='tests/pngvalid-progressive-interlace-standard'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngvalid-progressive-interlace-transform.log: tests/pngvalid-progressive-interlace-transform
+       @p='tests/pngvalid-progressive-interlace-transform'; \
+       b='tests/pngvalid-progressive-interlace-transform'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngvalid-progressive-standard.log: tests/pngvalid-progressive-standard
+       @p='tests/pngvalid-progressive-standard'; \
+       b='tests/pngvalid-progressive-standard'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngvalid-standard.log: tests/pngvalid-standard
+       @p='tests/pngvalid-standard'; \
+       b='tests/pngvalid-standard'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngstest-0g01.log: tests/pngstest-0g01
+       @p='tests/pngstest-0g01'; \
+       b='tests/pngstest-0g01'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngstest-0g02.log: tests/pngstest-0g02
+       @p='tests/pngstest-0g02'; \
+       b='tests/pngstest-0g02'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngstest-0g04.log: tests/pngstest-0g04
+       @p='tests/pngstest-0g04'; \
+       b='tests/pngstest-0g04'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngstest-0g08.log: tests/pngstest-0g08
+       @p='tests/pngstest-0g08'; \
+       b='tests/pngstest-0g08'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngstest-0g16.log: tests/pngstest-0g16
+       @p='tests/pngstest-0g16'; \
+       b='tests/pngstest-0g16'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngstest-2c08.log: tests/pngstest-2c08
+       @p='tests/pngstest-2c08'; \
+       b='tests/pngstest-2c08'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngstest-2c16.log: tests/pngstest-2c16
+       @p='tests/pngstest-2c16'; \
+       b='tests/pngstest-2c16'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngstest-3p01.log: tests/pngstest-3p01
+       @p='tests/pngstest-3p01'; \
+       b='tests/pngstest-3p01'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngstest-3p02.log: tests/pngstest-3p02
+       @p='tests/pngstest-3p02'; \
+       b='tests/pngstest-3p02'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngstest-3p04.log: tests/pngstest-3p04
+       @p='tests/pngstest-3p04'; \
+       b='tests/pngstest-3p04'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngstest-3p08.log: tests/pngstest-3p08
+       @p='tests/pngstest-3p08'; \
+       b='tests/pngstest-3p08'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngstest-4a08.log: tests/pngstest-4a08
+       @p='tests/pngstest-4a08'; \
+       b='tests/pngstest-4a08'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngstest-4a16.log: tests/pngstest-4a16
+       @p='tests/pngstest-4a16'; \
+       b='tests/pngstest-4a16'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngstest-6a08.log: tests/pngstest-6a08
+       @p='tests/pngstest-6a08'; \
+       b='tests/pngstest-6a08'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngstest-6a16.log: tests/pngstest-6a16
+       @p='tests/pngstest-6a16'; \
+       b='tests/pngstest-6a16'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngstest-error.log: tests/pngstest-error
+       @p='tests/pngstest-error'; \
+       b='tests/pngstest-error'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngunknown-IDAT.log: tests/pngunknown-IDAT
+       @p='tests/pngunknown-IDAT'; \
+       b='tests/pngunknown-IDAT'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngunknown-discard.log: tests/pngunknown-discard
+       @p='tests/pngunknown-discard'; \
+       b='tests/pngunknown-discard'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngunknown-if-safe.log: tests/pngunknown-if-safe
+       @p='tests/pngunknown-if-safe'; \
+       b='tests/pngunknown-if-safe'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngunknown-sAPI.log: tests/pngunknown-sAPI
+       @p='tests/pngunknown-sAPI'; \
+       b='tests/pngunknown-sAPI'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngunknown-sTER.log: tests/pngunknown-sTER
+       @p='tests/pngunknown-sTER'; \
+       b='tests/pngunknown-sTER'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngunknown-save.log: tests/pngunknown-save
+       @p='tests/pngunknown-save'; \
+       b='tests/pngunknown-save'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+tests/pngunknown-vpAg.log: tests/pngunknown-vpAg
+       @p='tests/pngunknown-vpAg'; \
+       b='tests/pngunknown-vpAg'; \
+       $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+.test.log:
+       @p='$<'; \
+       $(am__set_b); \
+       $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+       --log-file $$b.log --trs-file $$b.trs \
+       $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+       "$$tst" $(AM_TESTS_FD_REDIRECT)
+@am__EXEEXT_TRUE@.test$(EXEEXT).log:
+@am__EXEEXT_TRUE@      @p='$<'; \
+@am__EXEEXT_TRUE@      $(am__set_b); \
+@am__EXEEXT_TRUE@      $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \
+@am__EXEEXT_TRUE@      --log-file $$b.log --trs-file $$b.trs \
+@am__EXEEXT_TRUE@      $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \
+@am__EXEEXT_TRUE@      "$$tst" $(AM_TESTS_FD_REDIRECT)
 
 distdir: $(DISTFILES)
        $(am__remove_distdir)
@@ -1278,6 +1782,9 @@ install-strip:
            "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
        fi
 mostlyclean-generic:
+       -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS)
+       -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs)
+       -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
 
 clean-generic:
        -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
@@ -1393,8 +1900,8 @@ uninstall-man: uninstall-man3 uninstall-man5
        install-ps-am install-strip installcheck installcheck-am \
        installdirs maintainer-clean maintainer-clean-generic \
        mostlyclean mostlyclean-compile mostlyclean-generic \
-       mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
-       uninstall-am uninstall-binSCRIPTS uninstall-hook \
+       mostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \
+       uninstall uninstall-am uninstall-binSCRIPTS uninstall-hook \
        uninstall-libLTLIBRARIES uninstall-man uninstall-man3 \
        uninstall-man5 uninstall-nodist_pkgincludeHEADERS \
        uninstall-pkgconfigDATA uninstall-pkgincludeHEADERS
@@ -1455,16 +1962,14 @@ contrib/libtests/pngstest.o contrib/libtests/pngvalid.o pngtest.o: pnglibconf.h
 contrib/libtests/pngunknown.o: pnglibconf.h
 
 .dfn.out:
-       rm -f $@ $*.c $*.tf[123]
-       test -d scripts || mkdir scripts
+       rm -f $@ $*.c $*.tf[12]
+       test -d scripts || mkdir scripts || test -d scripts
        echo '#include "$<"' >$*.c
        $(DFNCPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES)\
            $(CPPFLAGS) $(SYMBOL_CFLAGS) $*.c > $*.tf1
-       $(SED) -n -e 's|^.*PNG_DEFN_MAGIC *-\(.*\)- *PNG_DEFN_END.*$$|\1|p'\
-           $*.tf1 >$*.tf2
-       $(SED) -e 's| *PNG_JOIN *||g' -e 's| *$$||' $*.tf2 >$*.tf3
-       rm -f $*.c $*.tf[12]
-       mv $*.tf3 $@
+       $(AWK) -f "${srcdir}/scripts/dfn.awk" out="$*.tf2" $*.tf1 1>&2
+       rm -f $*.c $*.tf1
+       mv $*.tf2 $@
 
 # The .dfn file for pnglibconf.h is machine generated
 pnglibconf.dfn: scripts/pnglibconf.dfa scripts/options.awk pngconf.h pngusr.dfa $(DFA_XTRA)
index 295ee1f8277672b6d18f3c884784a06b98d8824f..fcf8f3fae0777d4c4a9914e98edd93a0e5f14a3a 100644 (file)
@@ -1,4 +1,4 @@
-README for libpng version 1.6.0 - February 14, 2013 (shared library 16.0)
+README for libpng version 1.6.1 - March 28, 2013 (shared library 16.0)
 See the note about version numbers near the top of png.h
 
 See INSTALL for instructions on how to install libpng.
index b6db4eb1c214d3b6da52ba74d71d0832369b04f2..decf0f56f8b7704e860dd2f881a79ca245673903 100755 (executable)
@@ -74,7 +74,7 @@ done
 #
 # The autotools generated files:
 libpng_autotools_files="Makefile.in aclocal.m4 config.guess config.h.in\
-   config.sub configure depcomp install-sh ltmain.sh missing"
+   config.sub configure depcomp install-sh ltmain.sh missing test-driver"
 #
 # These are separate because 'maintainer-clean' does not remove them.
 libpng_libtool_files="scripts/libtool.m4 scripts/ltoptions.m4\
index bce6c1171ba0dbb03d78497af04c3aace3e4f142..713869b39bb0a23b3ff19953476673ea8d46492f 100644 (file)
@@ -15,9 +15,6 @@
 /* Define to 1 if you have the `z' library (-lz). */
 #undef HAVE_LIBZ
 
-/* Define to 1 if you have the <malloc.h> header file. */
-#undef HAVE_MALLOC_H
-
 /* Define to 1 if you have the <memory.h> header file. */
 #undef HAVE_MEMORY_H
 
 /* Define to the version of this package. */
 #undef PACKAGE_VERSION
 
-/* Align row buffers */
-#undef PNG_ALIGNED_MEMORY_SUPPORTED
+/* Turn on ARM Neon optimizations at run-time */
+#undef PNG_ARM_NEON_API_SUPPORTED
+
+/* Check for ARM Neon support at run-time */
+#undef PNG_ARM_NEON_CHECK_SUPPORTED
+
+/* Enable ARM Neon optimizations */
+#undef PNG_ARM_NEON_SUPPORTED
 
-/* ARM NEON filter initialization function */
-#undef PNG_FILTER_OPTIMIZATIONS
+/* Disable ARM Neon optimizations */
+#undef PNG_NO_ARM_NEON
 
 /* Define to 1 if you have the ANSI C header files. */
 #undef STDC_HEADERS
index 2f2f5f22bdea662dc5d3d730ba0a7eb61bf8cbaf..487666acc111df3a5fc7ed6a45ef600c68991812 100755 (executable)
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for libpng 1.6.0.
+# Generated by GNU Autoconf 2.69 for libpng 1.6.1.
 #
 # Report bugs to <png-mng-implement@lists.sourceforge.net>.
 #
@@ -590,8 +590,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='libpng'
 PACKAGE_TARNAME='libpng'
-PACKAGE_VERSION='1.6.0'
-PACKAGE_STRING='libpng 1.6.0'
+PACKAGE_VERSION='1.6.1'
+PACKAGE_STRING='libpng 1.6.1'
 PACKAGE_BUGREPORT='png-mng-implement@lists.sourceforge.net'
 PACKAGE_URL=''
 
@@ -1349,7 +1349,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures libpng 1.6.0 to adapt to many kinds of systems.
+\`configure' configures libpng 1.6.1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1419,7 +1419,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of libpng 1.6.0:";;
+     short | recursive ) echo "Configuration of libpng 1.6.1:";;
    esac
   cat <<\_ACEOF
 
@@ -1443,7 +1443,13 @@ Optional Features:
   --disable-libtool-lock  avoid locking (might break parallel builds)
   --enable-werror[=OPT] Pass -Werror or the given argument to the compiler
                           if it is supported
-  --enable-arm-neon     Enable ARM NEON optimizations
+  --enable-arm-neon     Enable ARM NEON optimizations: =off, check, api, on:
+                          off: disable the optimizations; check: use internal
+                          checking code (deprecated and poorly supported);
+                          api: disable by default, enable by a call to
+                          png_set_option; on: turn on unconditionally. The
+                          default is 'on' if __ARM_NEON__ is defined,
+                          otherwise 'off'.
 
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
@@ -1541,7 +1547,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-libpng configure 1.6.0
+libpng configure 1.6.1
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -1816,97 +1822,6 @@ $as_echo "$ac_res" >&6; }
 
 } # ac_fn_c_check_func
 
-# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
-# -------------------------------------------------------
-# Tests whether HEADER exists, giving a warning if it cannot be compiled using
-# the include files in INCLUDES and setting the cache variable VAR
-# accordingly.
-ac_fn_c_check_header_mongrel ()
-{
-  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
-  if eval \${$3+:} false; then :
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
-  $as_echo_n "(cached) " >&6
-fi
-eval ac_res=\$$3
-              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-else
-  # Is the header compilable?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
-$as_echo_n "checking $2 usability... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-$4
-#include <$2>
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  ac_header_compiler=yes
-else
-  ac_header_compiler=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
-$as_echo "$ac_header_compiler" >&6; }
-
-# Is the header present?
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
-$as_echo_n "checking $2 presence... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <$2>
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-  ac_header_preproc=yes
-else
-  ac_header_preproc=no
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
-$as_echo "$ac_header_preproc" >&6; }
-
-# So?  What about this header?
-case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
-  yes:no: )
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
-$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
-    ;;
-  no:yes:* )
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
-$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
-$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
-$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
-$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
-    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
-$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
-( $as_echo "## ------------------------------------------------------ ##
-## Report this to png-mng-implement@lists.sourceforge.net ##
-## ------------------------------------------------------ ##"
-     ) | sed "s/^/$as_me: WARNING:     /" >&2
-    ;;
-esac
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
-$as_echo_n "checking for $2... " >&6; }
-if eval \${$3+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  eval "$3=\$ac_header_compiler"
-fi
-eval ac_res=\$$3
-              { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
-fi
-  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_header_mongrel
-
 # ac_fn_c_check_type LINENO TYPE VAR INCLUDES
 # -------------------------------------------
 # Tests whether TYPE exists after having included INCLUDES, setting cache
@@ -1964,7 +1879,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by libpng $as_me 1.6.0, which was
+It was created by libpng $as_me 1.6.1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2319,6 +2234,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
 # silent-rules requires automake 1.11 or later
 # dist-xz requires automake 1.11 or later
 # 1.12.2 fixes a security issue in 1.11.2 and 1.12.1
+# 1.13 is required for parallel tests
 am__api_version='1.13'
 
 ac_aux_dir=
@@ -2834,7 +2750,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='libpng'
- VERSION='1.6.0'
+ VERSION='1.6.1'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -2880,8 +2796,9 @@ am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
 
 
 
-# was:
-# AM_INIT_AUTOMAKE
+# The following line causes --disable-maintainer-mode to be the default to
+# configure, this is necessary because libpng distributions cannot rely on the
+# time stamps of the autotools generated files being correct
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
 $as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
@@ -2907,10 +2824,10 @@ fi
 
 
 
-PNGLIB_VERSION=1.6.0
+PNGLIB_VERSION=1.6.1
 PNGLIB_MAJOR=1
 PNGLIB_MINOR=6
-PNGLIB_RELEASE=0
+PNGLIB_RELEASE=1
 
 
 
@@ -4707,101 +4624,10 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
 ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
 ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
-if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}sed", so it can be a program name with args.
-set dummy ${ac_tool_prefix}sed; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_SED+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$SED"; then
-  ac_cv_prog_SED="$SED" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_SED="${ac_tool_prefix}sed"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-SED=$ac_cv_prog_SED
-if test -n "$SED"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SED" >&5
-$as_echo "$SED" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-
-fi
-if test -z "$ac_cv_prog_SED"; then
-  ac_ct_SED=$SED
-  # Extract the first word of "sed", so it can be a program name with args.
-set dummy sed; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_SED+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_SED"; then
-  ac_cv_prog_ac_ct_SED="$ac_ct_SED" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
+for ac_prog in gawk mawk nawk awk
 do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_SED="sed"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
-done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_SED=$ac_cv_prog_ac_ct_SED
-if test -n "$ac_ct_SED"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_SED" >&5
-$as_echo "$ac_ct_SED" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-  if test "x$ac_ct_SED" = x; then
-    SED=":"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    SED=$ac_ct_SED
-  fi
-else
-  SED="$ac_cv_prog_SED"
-fi
-
-if test -n "$ac_tool_prefix"; then
-  # Extract the first word of "${ac_tool_prefix}awk", so it can be a program name with args.
-set dummy ${ac_tool_prefix}awk; ac_word=$2
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
 if ${ac_cv_prog_AWK+:} false; then :
@@ -4817,7 +4643,7 @@ do
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
   if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_AWK="${ac_tool_prefix}awk"
+    ac_cv_prog_AWK="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
   fi
@@ -4837,59 +4663,8 @@ $as_echo "no" >&6; }
 fi
 
 
-fi
-if test -z "$ac_cv_prog_AWK"; then
-  ac_ct_AWK=$AWK
-  # Extract the first word of "awk", so it can be a program name with args.
-set dummy awk; ac_word=$2
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
-$as_echo_n "checking for $ac_word... " >&6; }
-if ${ac_cv_prog_ac_ct_AWK+:} false; then :
-  $as_echo_n "(cached) " >&6
-else
-  if test -n "$ac_ct_AWK"; then
-  ac_cv_prog_ac_ct_AWK="$ac_ct_AWK" # Let the user override the test.
-else
-as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
-for as_dir in $PATH
-do
-  IFS=$as_save_IFS
-  test -z "$as_dir" && as_dir=.
-    for ac_exec_ext in '' $ac_executable_extensions; do
-  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
-    ac_cv_prog_ac_ct_AWK="awk"
-    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
-    break 2
-  fi
+  test -n "$AWK" && break
 done
-  done
-IFS=$as_save_IFS
-
-fi
-fi
-ac_ct_AWK=$ac_cv_prog_ac_ct_AWK
-if test -n "$ac_ct_AWK"; then
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AWK" >&5
-$as_echo "$ac_ct_AWK" >&6; }
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-
-  if test "x$ac_ct_AWK" = x; then
-    AWK=":"
-  else
-    case $cross_compiling:$ac_tool_warned in
-yes:)
-{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
-$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
-ac_tool_warned=yes ;;
-esac
-    AWK=$ac_ct_AWK
-  fi
-else
-  AWK="$ac_cv_prog_AWK"
-fi
 
 
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
@@ -12130,48 +11905,28 @@ CC="$lt_save_CC"
 
 
 
-# On Solaris 10 and 12 CPP gets set to cc -E, however this still
-# does some input parsing.  We need strict ANSI-C style tokenization,
-# check this:
-
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a C preprocessor that does not parse its input" >&5
-$as_echo_n "checking for a C preprocessor that does not parse its input... " >&6; }
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-1.1.1 16BIT
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-  DFNCPP="$CPP"
-else
-    DFNCPP=""
-      sav_CPP="$CPP"
-      for CPP in "${CC-cc} -E" "${CC-cc} -E -traditional-cpp" "/lib/cpp" "cpp"
-      do
-         cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-1.1.1 16BIT
-_ACEOF
-if ac_fn_c_try_cpp "$LINENO"; then :
-  DFNCPP="$CPP"
-            break
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-      done
-      CPP="$sav_CPP"
-
-fi
-rm -f conftest.err conftest.i conftest.$ac_ext
-if test -n "$DFNCPP"; then
-   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DFNCPP" >&5
-$as_echo "$DFNCPP" >&6; }
-
+# Some awks crash when confronted with pnglibconf.dfa, do a test run now
+# to make sure this doesn't happen
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that AWK works" >&5
+$as_echo_n "checking that AWK works... " >&6; }
+if ${AWK} -f ${srcdir}/scripts/options.awk out="/dev/null" version=search\
+   ${srcdir}/pngconf.h ${srcdir}/scripts/pnglibconf.dfa\
+   ${srcdir}/pngusr.dfa 1>&2
+then
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
+$as_echo "ok" >&6; }
 else
    { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
-as_fn_error 1 "not found
+as_fn_error 1 "failed
 See \`config.log' for more details" "$LINENO" 5; }
 fi
 
+# This is a remnant of the old cc -E validation, where it may have been
+# necessary to use a different preprocessor for .dfn files
+DFNCPP="$CPP"
+
+
 # -Werror cannot be passed to GCC in CFLAGS because configure will fail (it
 # checks the compiler with a program that generates a warning), add the
 # following option to deal with this
@@ -12318,19 +12073,6 @@ $as_echo "#define STDC_HEADERS 1" >>confdefs.h
 
 fi
 
-for ac_header in malloc.h stdlib.h string.h strings.h
-do :
-  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
-ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
-if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
-  cat >>confdefs.h <<_ACEOF
-#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
-_ACEOF
-
-fi
-
-done
-
 
 # Checks for typedefs, structures, and compiler characteristics.
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5
@@ -12998,17 +12740,29 @@ AM_CCASFLAGS=-Wa,--noexecstack
 
 # Check whether --enable-arm-neon was given.
 if test "${enable_arm_neon+set}" = set; then :
-  enableval=$enable_arm_neon; if test "${enableval}" = "yes"; then
+  enableval=$enable_arm_neon; case "$enableval" in
+      off)
 
-$as_echo "#define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_neon" >>confdefs.h
+$as_echo "#define PNG_NO_ARM_NEON /**/" >>confdefs.h
+;;
+      check)
 
+$as_echo "#define PNG_ARM_NEON_CHECK_SUPPORTED /**/" >>confdefs.h
+;;
+      api)
 
-$as_echo "#define PNG_ALIGNED_MEMORY_SUPPORTED 1" >>confdefs.h
+$as_echo "#define PNG_ARM_NEON_API_SUPPORTED /**/" >>confdefs.h
+;;
+      on)
 
-    fi
+$as_echo "#define PNG_ARM_NEON_SUPPORTED /**/" >>confdefs.h
+;;
+      *)
+         as_fn_error $? "arm-neon: option value required (off/check/api/on)" "$LINENO" 5;;
+   esac
 fi
 
- if test "${enable_arm_neon:-no}" = yes; then
+ if test "${enable_arm_neon:-no}" != "no"; then
   PNG_ARM_NEON_TRUE=
   PNG_ARM_NEON_FALSE='#'
 else
@@ -13580,7 +13334,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by libpng $as_me 1.6.0, which was
+This file was extended by libpng $as_me 1.6.1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -13646,7 +13400,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-libpng config.status 1.6.0
+libpng config.status 1.6.1
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
index e6ff077da615d04bb2d77abbae15f5e3fb731106..1745d31787b5b8629d0311f3b1d9fa0003109287 100644 (file)
@@ -18,7 +18,7 @@ AC_PREREQ([2.68])
 
 dnl Version number stuff here:
 
-AC_INIT([libpng],[1.6.0],[png-mng-implement@lists.sourceforge.net])
+AC_INIT([libpng],[1.6.1],[png-mng-implement@lists.sourceforge.net])
 AC_CONFIG_MACRO_DIR([scripts])
 
 # libpng does not follow GNU file name conventions (hence 'foreign')
@@ -26,9 +26,11 @@ AC_CONFIG_MACRO_DIR([scripts])
 # silent-rules requires automake 1.11 or later
 # dist-xz requires automake 1.11 or later
 # 1.12.2 fixes a security issue in 1.11.2 and 1.12.1
-AM_INIT_AUTOMAKE([1.12.2 foreign dist-xz color-tests silent-rules serial-tests])
-# was:
-# AM_INIT_AUTOMAKE
+# 1.13 is required for parallel tests
+AM_INIT_AUTOMAKE([1.13 foreign dist-xz color-tests silent-rules])
+# The following line causes --disable-maintainer-mode to be the default to
+# configure, this is necessary because libpng distributions cannot rely on the
+# time stamps of the autotools generated files being correct
 AM_MAINTAINER_MODE
 
 dnl configure.ac and Makefile.am expect automake 1.11.2 or a compatible later
@@ -37,10 +39,10 @@ dnl automake, so the following is not necessary (and is not defined anyway):
 dnl AM_PREREQ([1.11.2])
 dnl stop configure from automagically running automake
 
-PNGLIB_VERSION=1.6.0
+PNGLIB_VERSION=1.6.1
 PNGLIB_MAJOR=1
 PNGLIB_MINOR=6
-PNGLIB_RELEASE=0
+PNGLIB_RELEASE=1
 
 dnl End of version number stuff
 
@@ -53,8 +55,7 @@ AC_PROG_CC
 AM_PROG_AS
 LT_PATH_LD
 AC_PROG_CPP
-AC_CHECK_TOOL(SED, sed, :)
-AC_CHECK_TOOL(AWK, awk, :)
+AC_PROG_AWK
 AC_PROG_INSTALL
 AC_PROG_LN_S
 AC_PROG_MAKE_SET
@@ -64,30 +65,23 @@ dnl compatible later version may be used
 LT_INIT([win32-dll])
 LT_PREREQ([2.4.2])
 
-# On Solaris 10 and 12 CPP gets set to cc -E, however this still
-# does some input parsing.  We need strict ANSI-C style tokenization,
-# check this:
-AC_REQUIRE_CPP
-AC_MSG_CHECKING([for a C preprocessor that does not parse its input])
-AC_PREPROC_IFELSE([AC_LANG_SOURCE([[1.1.1 16BIT]])],
-   [DFNCPP="$CPP"],
-   [  DFNCPP=""
-      sav_CPP="$CPP"
-      for CPP in "${CC-cc} -E" "${CC-cc} -E -traditional-cpp" "/lib/cpp" "cpp"
-      do
-         AC_PREPROC_IFELSE([AC_LANG_SOURCE([[1.1.1 16BIT]])],
-            [DFNCPP="$CPP"]
-            [break],,)
-      done
-      CPP="$sav_CPP"
-   ])
-if test -n "$DFNCPP"; then
-   AC_MSG_RESULT([$DFNCPP])
-   AC_SUBST(DFNCPP)
+# Some awks crash when confronted with pnglibconf.dfa, do a test run now
+# to make sure this doesn't happen
+AC_MSG_CHECKING([that AWK works])
+if ${AWK} -f ${srcdir}/scripts/options.awk out="/dev/null" version=search\
+   ${srcdir}/pngconf.h ${srcdir}/scripts/pnglibconf.dfa\
+   ${srcdir}/pngusr.dfa 1>&2
+then
+   AC_MSG_RESULT([ok])
 else
-   AC_MSG_FAILURE([not found], 1)
+   AC_MSG_FAILURE([failed], 1)
 fi
 
+# This is a remnant of the old cc -E validation, where it may have been
+# necessary to use a different preprocessor for .dfn files
+DFNCPP="$CPP"
+AC_SUBST(DFNCPP)
+
 # -Werror cannot be passed to GCC in CFLAGS because configure will fail (it
 # checks the compiler with a program that generates a warning), add the
 # following option to deal with this
@@ -115,7 +109,6 @@ AC_ARG_ENABLE(werror,
 
 # Checks for header files.
 AC_HEADER_STDC
-AC_CHECK_HEADERS([malloc.h stdlib.h string.h strings.h])
 
 # Checks for typedefs, structures, and compiler characteristics.
 AC_C_CONST
@@ -239,15 +232,29 @@ AM_CONDITIONAL([DO_PNG_PREFIX], [test "${with_libpng_prefix:-no}" != "no"])
 AC_SUBST([AM_CCASFLAGS], [-Wa,--noexecstack])
 
 AC_ARG_ENABLE([arm-neon],
-   AS_HELP_STRING([[[--enable-arm-neon]]], [Enable ARM NEON optimizations]),
-   [if test "${enableval}" = "yes"; then
-      AC_DEFINE([PNG_FILTER_OPTIMIZATIONS],
-                [png_init_filter_functions_neon],
-                [ARM NEON filter initialization function])
-      AC_DEFINE([PNG_ALIGNED_MEMORY_SUPPORTED], [1],
-                [Align row buffers])
-    fi])
-AM_CONDITIONAL([PNG_ARM_NEON], [test "${enable_arm_neon:-no}" = yes])
+   AS_HELP_STRING([[[--enable-arm-neon]]],
+      [Enable ARM NEON optimizations: =off, check, api, on:]
+      [off: disable the optimizations; check: use internal checking code]
+      [(deprecated and poorly supported); api: disable by default, enable by]
+      [a call to png_set_option; on: turn on unconditionally.  The]
+      [default is 'on' if __ARM_NEON__ is defined, otherwise 'off'.]),
+   [case "$enableval" in
+      off)
+         AC_DEFINE([PNG_NO_ARM_NEON], [],
+                   [Disable ARM Neon optimizations]);;
+      check)
+         AC_DEFINE([PNG_ARM_NEON_CHECK_SUPPORTED], [],
+                   [Check for ARM Neon support at run-time]);;
+      api)
+         AC_DEFINE([PNG_ARM_NEON_API_SUPPORTED], [],
+                   [Turn on ARM Neon optimizations at run-time]);;
+      on)
+         AC_DEFINE([PNG_ARM_NEON_SUPPORTED], [],
+                   [Enable ARM Neon optimizations]);;
+      *)
+         AC_MSG_ERROR([arm-neon: option value required (off/check/api/on)]);;
+   esac])
+AM_CONDITIONAL([PNG_ARM_NEON], [test "${enable_arm_neon:-no}" != "no"])
 
 AC_MSG_NOTICE([[Extra options for compiler: $PNG_COPTS]])
 
index 63fa15b43a666a2bef9da6ca99ef0a7eb24d1d97..4b91d865a6f50c6bdad619c376f2971f2aad0892 100644 (file)
@@ -1,6 +1,6 @@
 libpng-manual.txt - A description on how to use and modify libpng
 
- libpng version 1.6.0 - February 14, 2013
+ libpng version 1.6.1 - March 28, 2013
  Updated and distributed by Glenn Randers-Pehrson
  <glennrp at users.sourceforge.net>
  Copyright (c) 1998-2013 Glenn Randers-Pehrson
@@ -11,7 +11,7 @@ libpng-manual.txt - A description on how to use and modify libpng
 
  Based on:
 
- libpng versions 0.97, January 1998, through 1.6.0 - February 14, 2013
+ libpng versions 0.97, January 1998, through 1.6.1 - March 28, 2013
  Updated and distributed by Glenn Randers-Pehrson
  Copyright (c) 1998-2013 Glenn Randers-Pehrson
 
@@ -527,9 +527,14 @@ you can retrieve with
     png_get_user_chunk_ptr(png_ptr);
 
 If you call the png_set_read_user_chunk_fn() function, then all unknown
-chunks will be saved when read, in case your callback function will need
-one or more of them.  This behavior can be changed with the
-png_set_keep_unknown_chunks() function, described below.
+chunks which the callback does not handle will be saved when read.  You can
+cause them to be discarded by returning '1' ("handled") instead of '0'.  This
+behavior will change in libpng 1.7 and the default handling set by the
+png_set_keep_unknown_chunks() function, described below, will be used when the
+callback returns 0.  If you want the existing behavior you should set the global
+default to PNG_HANDLE_CHUNK_IF_SAFE now; this is compatible with all current
+versions of libpng and with 1.7.  Libpng 1.6 issues a warning if you keep the
+default, or PNG_HANDLE_CHUNK_NEVER, and the callback returns 0.
 
 At this point, you can set up a callback function that will be
 called after each row has been read, which you can use to control
@@ -628,15 +633,17 @@ callback function:
     ...
 
     #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
-      /* ignore all unknown chunks: */
-      png_set_keep_unknown_chunks(read_ptr, 1, NULL, 0);
+      /* ignore all unknown chunks
+       * (use global setting "2" for libpng16 and earlier):
+       */
+      png_set_keep_unknown_chunks(read_ptr, 2, NULL, 0);
 
       /* except for vpAg: */
       png_set_keep_unknown_chunks(read_ptr, 2, vpAg, 1);
 
       /* also ignore unused known chunks: */
       png_set_keep_unknown_chunks(read_ptr, 1, unused_chunks,
-         (int)sizeof(unused_chunks)/5);
+         (int)(sizeof unused_chunks)/5);
     #endif
 
 User limits
@@ -988,7 +995,7 @@ where row_pointers is an array of pointers to the pixel data for each row:
 If you know your image size and pixel size ahead of time, you can allocate
 row_pointers prior to calling png_read_png() with
 
-   if (height > PNG_UINT_32_MAX/png_sizeof(png_byte))
+   if (height > PNG_UINT_32_MAX/(sizeof (png_byte)))
       png_error (png_ptr,
           "Image is too tall to process in memory");
 
@@ -997,7 +1004,7 @@ row_pointers prior to calling png_read_png() with
           "Image is too wide to process in memory");
 
    row_pointers = png_malloc(png_ptr,
-       height*png_sizeof(png_bytep));
+       height*(sizeof (png_bytep)));
 
    for (int i=0; i<height, i++)
       row_pointers[i]=NULL;  /* security precaution */
@@ -4953,7 +4960,7 @@ The following API are now DEPRECATED:
    png_free_default()
    png_reset_zstream()
 
-The following has been removed:
+The following have been removed:
    png_get_io_chunk_name(), which has been replaced
      with png_get_io_chunk_type().  The new
      function returns a 32-bit integer instead of
@@ -4973,6 +4980,9 @@ reader now does pretty complete validation of the basic format.  Some bad
 profiles that were previously accepted are now rejected, in particular the
 very old broken Microsoft/HP sRGB profile.
 
+The library now issues an error if the application attempts to set a
+transform after it calls png_read_update_info().
+
 The library now issues a warning if both background processing and RGB to
 gray are used when gamma correction happens. As with previous versions of
 the library the results are numerically very incorrect in this case.
@@ -5134,7 +5144,8 @@ left parenthesis that follows it:
        y[i] = a(x) + (int)b;
 
 We prefer #ifdef and #ifndef to #if defined() and #if !defined()
-when there is only one macro being tested.
+when there is only one macro being tested.  We always use parentheses
+with "defined".
 
 We prefer to express integers that are used as bit masks in hex format,
 with an even number of lower-case hex digits (e.g., 0x00, 0xff, 0x0100).
@@ -5150,13 +5161,13 @@ Other rules can be inferred by inspecting the libpng source.
 
 XVI. Y2K Compliance in libpng
 
-February 14, 2013
+March 28, 2013
 
 Since the PNG Development group is an ad-hoc body, we can't make
 an official declaration.
 
 This is your unofficial assurance that libpng from version 0.71 and
-upward through 1.6.0 are Y2K compliant.  It is my belief that earlier
+upward through 1.6.1 are Y2K compliant.  It is my belief that earlier
 versions were also Y2K compliant.
 
 Libpng only has two year fields.  One is a 2-byte unsigned integer
index 11da8ceacb1b44ee81b7dbe1df7bc463cc23d3eb..e4f4e9410505ca5c9fb0b155c1e80491fec59039 100644 (file)
@@ -1,6 +1,6 @@
-.TH LIBPNG 3 "February 14, 2013"
+.TH LIBPNG 3 "March 28, 2013"
 .SH NAME
-libpng \- Portable Network Graphics (PNG) Reference Library 1.6.0
+libpng \- Portable Network Graphics (PNG) Reference Library 1.6.1
 .SH SYNOPSIS
 \fB
 #include <png.h>\fP
@@ -504,7 +504,7 @@ Following is a copy of the libpng-manual.txt file that accompanies libpng.
 .SH LIBPNG.TXT
 libpng-manual.txt - A description on how to use and modify libpng
 
- libpng version 1.6.0 - February 14, 2013
+ libpng version 1.6.1 - March 28, 2013
  Updated and distributed by Glenn Randers-Pehrson
  <glennrp at users.sourceforge.net>
  Copyright (c) 1998-2013 Glenn Randers-Pehrson
@@ -515,7 +515,7 @@ libpng-manual.txt - A description on how to use and modify libpng
 
  Based on:
 
- libpng versions 0.97, January 1998, through 1.6.0 - February 14, 2013
+ libpng versions 0.97, January 1998, through 1.6.1 - March 28, 2013
  Updated and distributed by Glenn Randers-Pehrson
  Copyright (c) 1998-2013 Glenn Randers-Pehrson
 
@@ -1031,9 +1031,14 @@ you can retrieve with
     png_get_user_chunk_ptr(png_ptr);
 
 If you call the png_set_read_user_chunk_fn() function, then all unknown
-chunks will be saved when read, in case your callback function will need
-one or more of them.  This behavior can be changed with the
-png_set_keep_unknown_chunks() function, described below.
+chunks which the callback does not handle will be saved when read.  You can
+cause them to be discarded by returning '1' ("handled") instead of '0'.  This
+behavior will change in libpng 1.7 and the default handling set by the
+png_set_keep_unknown_chunks() function, described below, will be used when the
+callback returns 0.  If you want the existing behavior you should set the global
+default to PNG_HANDLE_CHUNK_IF_SAFE now; this is compatible with all current
+versions of libpng and with 1.7.  Libpng 1.6 issues a warning if you keep the
+default, or PNG_HANDLE_CHUNK_NEVER, and the callback returns 0.
 
 At this point, you can set up a callback function that will be
 called after each row has been read, which you can use to control
@@ -1132,15 +1137,17 @@ callback function:
     ...
 
     #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
-      /* ignore all unknown chunks: */
-      png_set_keep_unknown_chunks(read_ptr, 1, NULL, 0);
+      /* ignore all unknown chunks
+       * (use global setting "2" for libpng16 and earlier):
+       */
+      png_set_keep_unknown_chunks(read_ptr, 2, NULL, 0);
 
       /* except for vpAg: */
       png_set_keep_unknown_chunks(read_ptr, 2, vpAg, 1);
 
       /* also ignore unused known chunks: */
       png_set_keep_unknown_chunks(read_ptr, 1, unused_chunks,
-         (int)sizeof(unused_chunks)/5);
+         (int)(sizeof unused_chunks)/5);
     #endif
 
 .SS User limits
@@ -1492,7 +1499,7 @@ where row_pointers is an array of pointers to the pixel data for each row:
 If you know your image size and pixel size ahead of time, you can allocate
 row_pointers prior to calling png_read_png() with
 
-   if (height > PNG_UINT_32_MAX/png_sizeof(png_byte))
+   if (height > PNG_UINT_32_MAX/(sizeof (png_byte)))
       png_error (png_ptr,
           "Image is too tall to process in memory");
 
@@ -1501,7 +1508,7 @@ row_pointers prior to calling png_read_png() with
           "Image is too wide to process in memory");
 
    row_pointers = png_malloc(png_ptr,
-       height*png_sizeof(png_bytep));
+       height*(sizeof (png_bytep)));
 
    for (int i=0; i<height, i++)
       row_pointers[i]=NULL;  /* security precaution */
@@ -5458,7 +5465,7 @@ The following API are now DEPRECATED:
    png_free_default()
    png_reset_zstream()
 
-The following has been removed:
+The following have been removed:
    png_get_io_chunk_name(), which has been replaced
      with png_get_io_chunk_type().  The new
      function returns a 32-bit integer instead of
@@ -5478,6 +5485,9 @@ reader now does pretty complete validation of the basic format.  Some bad
 profiles that were previously accepted are now rejected, in particular the
 very old broken Microsoft/HP sRGB profile.
 
+The library now issues an error if the application attempts to set a
+transform after it calls png_read_update_info().
+
 The library now issues a warning if both background processing and RGB to
 gray are used when gamma correction happens. As with previous versions of
 the library the results are numerically very incorrect in this case.
@@ -5639,7 +5649,8 @@ left parenthesis that follows it:
        y[i] = a(x) + (int)b;
 
 We prefer #ifdef and #ifndef to #if defined() and #if !defined()
-when there is only one macro being tested.
+when there is only one macro being tested.  We always use parentheses
+with "defined".
 
 We prefer to express integers that are used as bit masks in hex format,
 with an even number of lower-case hex digits (e.g., 0x00, 0xff, 0x0100).
@@ -5655,13 +5666,13 @@ Other rules can be inferred by inspecting the libpng source.
 
 .SH XVI. Y2K Compliance in libpng
 
-February 14, 2013
+March 28, 2013
 
 Since the PNG Development group is an ad-hoc body, we can't make
 an official declaration.
 
 This is your unofficial assurance that libpng from version 0.71 and
-upward through 1.6.0 are Y2K compliant.  It is my belief that earlier
+upward through 1.6.1 are Y2K compliant.  It is my belief that earlier
 versions were also Y2K compliant.
 
 Libpng only has two year fields.  One is a 2-byte unsigned integer
@@ -5869,6 +5880,8 @@ the first widely used release:
  1.6.0beta01-40      16    10600  16.so.16.0[.0]
  1.6.0rc01-08        16    10600  16.so.16.0[.0]
  1.6.0               16    10600  16.so.16.0[.0]
+ 1.6.1rc01           16    10601  16.so.16.1[.0]
+ 1.6.1               16    10601  16.so.16.1[.0]
 
 Henceforth the source version will match the shared-library minor
 and patch numbers; the shared-library major version number will be
@@ -5925,7 +5938,7 @@ possible without all of you.
 
 Thanks to Frank J. T. Wojcik for helping with the documentation.
 
-Libpng version 1.6.0 - February 14, 2013:
+Libpng version 1.6.1 - March 28, 2013:
 Initially created in 1995 by Guy Eric Schalnat, then of Group 42, Inc.
 Currently maintained by Glenn Randers-Pehrson (glennrp at users.sourceforge.net).
 
@@ -5948,7 +5961,7 @@ this sentence.
 
 This code is released under the libpng license.
 
-libpng versions 1.2.6, August 15, 2004, through 1.6.0, February 14, 2013, are
+libpng versions 1.2.6, August 15, 2004, through 1.6.1, March 28, 2013, are
 Copyright (c) 2004,2006-2007 Glenn Randers-Pehrson, and are
 distributed according to the same disclaimer and license as libpng-1.2.5
 with the following individual added to the list of Contributing Authors
@@ -6047,7 +6060,7 @@ certification mark of the Open Source Initiative.
 
 Glenn Randers-Pehrson
 glennrp at users.sourceforge.net
-February 14, 2013
+March 28, 2013
 
 .\" end of man page
 
index f06520c67d94d7403c8d450a30675ffd80350476..21b56cf9bda5b3e42898d0ea9da236276a5733ba 100644 (file)
@@ -1,6 +1,6 @@
-.TH LIBPNGPF 3 "February 14, 2013"
+.TH LIBPNGPF 3 "March 28, 2013"
 .SH NAME
-libpng \- Portable Network Graphics (PNG) Reference Library 1.6.0
+libpng \- Portable Network Graphics (PNG) Reference Library 1.6.1
 (private functions)
 .SH SYNOPSIS
 \fB#include \fI"pngpriv.h"
index 8832f8cae80d27a5f03a4650e2e4bc92f818b833..1d25bf56a45e1bbcd920572d45abdc5c189e1d05 100644 (file)
@@ -1,4 +1,4 @@
-.TH PNG 5 "February 14, 2013"
+.TH PNG 5 "March 28, 2013"
 .SH NAME
 png \- Portable Network Graphics (PNG) format
 .SH DESCRIPTION
index 59d747d9947ad43c4354f535ad58d5bbd06a1dfd..67f760e4b83d0b696485cf28346c8b4846a8a082 100644 (file)
@@ -1,7 +1,7 @@
 
 /* png.c - location for general purpose libpng functions
  *
- * Last changed in libpng 1.6.0 [February 14, 2013]
+ * Last changed in libpng 1.6.1 [March 28, 2013]
  * Copyright (c) 1998-2013 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -14,7 +14,7 @@
 #include "pngpriv.h"
 
 /* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_6_0 Your_png_h_is_not_version_1_6_0;
+typedef png_libpng_version_1_6_1 Your_png_h_is_not_version_1_6_1;
 
 /* Tells libpng that we have already handled the first "num_bytes" bytes
  * of the PNG file signature.  If the PNG data is embedded into another
@@ -768,13 +768,13 @@ png_get_copyright(png_const_structrp png_ptr)
 #else
 #  ifdef __STDC__
    return PNG_STRING_NEWLINE \
-     "libpng version 1.6.0 - February 14, 2013" PNG_STRING_NEWLINE \
+     "libpng version 1.6.1 - March 28, 2013" PNG_STRING_NEWLINE \
      "Copyright (c) 1998-2013 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
      "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
      "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
      PNG_STRING_NEWLINE;
 #  else
-      return "libpng version 1.6.0 - February 14, 2013\
+      return "libpng version 1.6.1 - March 28, 2013\
       Copyright (c) 1998-2013 Glenn Randers-Pehrson\
       Copyright (c) 1996-1997 Andreas Dilger\
       Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.";
@@ -1407,8 +1407,10 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)
       red_inverse))
       return 1;
 
-   if (!png_muldiv(&XYZ->green_X, xy->greenx, PNG_FP_1, green_inverse)) return 1;
-   if (!png_muldiv(&XYZ->green_Y, xy->greeny, PNG_FP_1, green_inverse)) return 1;
+   if (!png_muldiv(&XYZ->green_X, xy->greenx, PNG_FP_1, green_inverse))
+      return 1;
+   if (!png_muldiv(&XYZ->green_Y, xy->greeny, PNG_FP_1, green_inverse))
+      return 1;
    if (!png_muldiv(&XYZ->green_Z, PNG_FP_1 - xy->greenx - xy->greeny, PNG_FP_1,
       green_inverse))
       return 1;
@@ -1647,7 +1649,7 @@ png_colorspace_set_endpoints(png_const_structrp png_ptr,
    return 0; /* failed */
 }
 
-#if defined PNG_sRGB_SUPPORTED || defined PNG_iCCP_SUPPORTED
+#if defined(PNG_sRGB_SUPPORTED) || defined(PNG_iCCP_SUPPORTED)
 /* Error message generation */
 static char
 png_icc_tag_char(png_uint_32 byte)
@@ -2127,7 +2129,7 @@ static const struct
       PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0, 1/*broken*/,
       "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 perceptual")
 
-   PNG_ICC_CHECKSUM(0x0398f3fcUL, 0xf29e526dUL,
+   PNG_ICC_CHECKSUM(0x0398f3fc, 0xf29e526d,
       PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 1/*broken*/,
       "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 media-relative")
 };
@@ -2177,7 +2179,7 @@ png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr,
          if (length == png_sRGB_checks[i].length &&
             intent == png_sRGB_checks[i].intent)
          {
-            /* Now calculate the alder32 if not done already. */
+            /* Now calculate the adler32 if not done already. */
             if (adler == 0)
             {
                adler = adler32(0, NULL, 0);
@@ -3090,7 +3092,7 @@ png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text)
 #endif
 
 #if defined(PNG_READ_GAMMA_SUPPORTED) || \
-    defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG__READ_pHYs_SUPPORTED)
+    defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED)
 /* muldiv functions */
 /* This API takes signed arguments and rounds the result to the nearest
  * integer (or, for a fixed point number - the standard argument - to
@@ -4010,9 +4012,30 @@ png_build_gamma_table(png_structrp png_ptr, int bit_depth)
 }
 #endif /* READ_GAMMA */
 
+/* HARDWARE OPTION SUPPORT */
+#ifdef PNG_SET_OPTION_SUPPORTED
+int PNGAPI
+png_set_option(png_structrp png_ptr, int option, int onoff)
+{
+   if (png_ptr != NULL && option >= 0 && option < PNG_OPTION_NEXT &&
+      (option & 1) == 0)
+   {
+      int mask = 3 << option;
+      int setting = (2 + (onoff != 0)) << option;
+      int current = png_ptr->options;
+
+      png_ptr->options = (png_byte)((current & ~mask) | setting);
+
+      return (current & mask) >> option;
+   }
+
+   return PNG_OPTION_INVALID;
+}
+#endif
+
 /* sRGB support */
-#if defined PNG_SIMPLIFIED_READ_SUPPORTED ||\
-   defined PNG_SIMPLIFIED_WRITE_SUPPORTED
+#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
+   defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
 /* sRGB conversion tables; these are machine generated with the code in
  * contrib/tools/makesRGB.c.  The actual sRGB transfer curve defined in the
  * specification (see the article at http://en.wikipedia.org/wiki/SRGB)
@@ -4180,8 +4203,8 @@ const png_byte png_sRGB_delta[512] =
 #endif /* SIMPLIFIED READ/WRITE sRGB support */
 
 /* SIMPLIFIED READ/WRITE SUPPORT */
-#if defined PNG_SIMPLIFIED_READ_SUPPORTED ||\
-   defined PNG_SIMPLIFIED_WRITE_SUPPORTED
+#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
+   defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
 static int
 png_image_free_function(png_voidp argument)
 {
index 448fe88cdb572af0e73ace74a1fc9ecb3f88b088..0ad09eb6bc7db4dc9685bb45529e76973d3e485c 100644 (file)
@@ -1,7 +1,7 @@
 
 /* png.h - header file for PNG reference library
  *
- * libpng version 1.6.0 - February 14, 2013
+ * libpng version 1.6.1 - March 28, 2013
  * Copyright (c) 1998-2013 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -11,7 +11,7 @@
  * Authors and maintainers:
  *   libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
  *   libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger
- *   libpng versions 0.97, January 1998, through 1.6.0 - February 14, 2013: Glenn
+ *   libpng versions 0.97, January 1998, through 1.6.1 - March 28, 2013: Glenn
  *   See also "Contributing Authors", below.
  *
  * Note about libpng version numbers:
  *    1.6.0beta01-40          16    10600  16.so.16.0[.0]
  *    1.6.0rc01-08            16    10600  16.so.16.0[.0]
  *    1.6.0                   16    10600  16.so.16.0[.0]
+ *    1.6.1beta01-10          16    10601  16.so.16.1[.0]
+ *    1.6.1rc01               16    10601  16.so.16.1[.0]
+ *    1.6.1                   16    10601  16.so.16.1[.0]
  *
  *   Henceforth the source version will match the shared-library major
  *   and minor numbers; the shared-library major version number will be
  *
  * This code is released under the libpng license.
  *
- * libpng versions 1.2.6, August 15, 2004, through 1.6.0, February 14, 2013, are
+ * libpng versions 1.2.6, August 15, 2004, through 1.6.1, March 28, 2013, are
  * Copyright (c) 2004, 2006-2013 Glenn Randers-Pehrson, and are
  * distributed according to the same disclaimer and license as libpng-1.2.5
  * with the following individual added to the list of Contributing Authors:
  * Y2K compliance in libpng:
  * =========================
  *
- *    February 14, 2013
+ *    March 28, 2013
  *
  *    Since the PNG Development group is an ad-hoc body, we can't make
  *    an official declaration.
  *
  *    This is your unofficial assurance that libpng from version 0.71 and
- *    upward through 1.6.0 are Y2K compliant.  It is my belief that
+ *    upward through 1.6.1 are Y2K compliant.  It is my belief that
  *    earlier versions were also Y2K compliant.
  *
  *    Libpng only has two year fields.  One is a 2-byte unsigned integer
  */
 
 /* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.6.0"
+#define PNG_LIBPNG_VER_STRING "1.6.1"
 #define PNG_HEADER_VERSION_STRING \
-     " libpng version 1.6.0 - February 14, 2013\n"
+     " libpng version 1.6.1 - March 28, 2013\n"
 
 #define PNG_LIBPNG_VER_SONUM   16
 #define PNG_LIBPNG_VER_DLLNUM  16
 /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
 #define PNG_LIBPNG_VER_MAJOR   1
 #define PNG_LIBPNG_VER_MINOR   6
-#define PNG_LIBPNG_VER_RELEASE 0
+#define PNG_LIBPNG_VER_RELEASE 1
 
 /* This should match the numeric part of the final component of
  * PNG_LIBPNG_VER_STRING, omitting any leading zero:
  * version 1.0.0 was mis-numbered 100 instead of 10000).  From
  * version 1.0.1 it's    xxyyzz, where x=major, y=minor, z=release
  */
-#define PNG_LIBPNG_VER 10600 /* 1.6.0 */
+#define PNG_LIBPNG_VER 10601 /* 1.6.1 */
 
 /* Library configuration: these options cannot be changed after
  * the library has been built.
@@ -524,7 +527,7 @@ extern "C" {
 /* This triggers a compiler error in png.c, if png.c and png.h
  * do not agree upon the version number.
  */
-typedef char* png_libpng_version_1_6_0;
+typedef char* png_libpng_version_1_6_1;
 
 /* Basic control structions.  Read libpng-manual.txt or libpng.3 for more info.
  *
@@ -1837,7 +1840,7 @@ PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structrp));
 #endif
 
 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED
-/* This callback is called only for *unknown* chunks, if
+/* This callback is called only for *unknown* chunks.  If
  * PNG_HANDLE_AS_UNKNOWN_SUPPORTED is set then it is possible to set known
  * chunks to be treated as unknown, however in this case the callback must do
  * any processing required by the chunk (e.g. by calling the appropriate
@@ -1849,12 +1852,12 @@ PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structrp));
  * The integer return from the callback function is interpreted thus:
  *
  * negative: An error occured, png_chunk_error will be called.
- *     zero: The chunk was not handled, the chunk will be discarded unless
- *           png_set_keep_unknown_chunks has been used to set a 'keep' behavior
- *           for this particular chunk, in which case that will be used.  A
- *           critical chunk will cause an error at this point unless it is to be
- *           saved.
+ *     zero: The chunk was not handled, the chunk will be saved. A critical
+ *           chunk will cause an error at this point unless it is to be saved.
  * positive: The chunk was handled, libpng will ignore/discard it.
+ *
+ * See "INTERACTION WTIH USER CHUNK CALLBACKS" below for important notes about
+ * how this behavior will change in libpng 1.7
  */
 PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structrp png_ptr,
     png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn));
@@ -2331,8 +2334,8 @@ PNG_EXPORT(167, void, png_set_tRNS, (png_structrp png_ptr,
 #ifdef PNG_sCAL_SUPPORTED
 PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, (png_const_structrp png_ptr,
     png_const_inforp info_ptr, int *unit, double *width, double *height))
-#if (defined PNG_FLOATING_ARITHMETIC_SUPPORTED) || \
-   (defined PNG_FLOATING_POINT_SUPPORTED)
+#if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || \
+   defined(PNG_FLOATING_POINT_SUPPORTED)
 /* NOTE: this API is currently implemented using floating point arithmetic,
  * consequently it can only be used on systems with floating point support.
  * In any case the range of values supported by png_fixed_point is small and it
@@ -2372,7 +2375,7 @@ PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr,
  * READ:
  *    PNG_HANDLE_CHUNK_AS_DEFAULT:
  *       Known chunks: do normal libpng processing, do not keep the chunk (but
- *          set the comments below about PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
+ *          see the comments below about PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
  *       Unknown chunks: for a specific chunk use the global default, when used
  *          as the default discard the chunk data.
  *    PNG_HANDLE_CHUNK_NEVER:
@@ -2388,12 +2391,21 @@ PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr,
  * to specifying "NEVER", however when "AS_DEFAULT" is used for specific chunks
  * it simply resets the behavior to the libpng default.
  *
+ * INTERACTION WTIH USER CHUNK CALLBACKS:
  * The per-chunk handling is always used when there is a png_user_chunk_ptr
  * callback and the callback returns 0; the chunk is then always stored *unless*
  * it is critical and the per-chunk setting is other than ALWAYS.  Notice that
  * the global default is *not* used in this case.  (In effect the per-chunk
  * value is incremented to at least IF_SAFE.)
  *
+ * IMPORTANT NOTE: this behavior will change in libpng 1.7 - the global and
+ * per-chunk defaults will be honored.  If you want to preserve the current
+ * behavior when your callback returns 0 you must set PNG_HANDLE_CHUNK_IF_SAFE
+ * as the default - if you don't do this libpng 1.6 will issue a warning.
+ *
+ * If you want unhandled unknown chunks to be discarded in libpng 1.6 and
+ * earlier simply return '1' (handled).
+ *
  * PNG_HANDLE_AS_UNKNOWN_SUPPORTED:
  *    If this is *not* set known chunks will always be handled by libpng and
  *    will never be stored in the unknown chunk list.  Known chunks listed to
@@ -3088,6 +3100,24 @@ typedef struct
     * slight speed gain.
     */
 
+#define PNG_IMAGE_FLAG_16BIT_sRGB 0x04
+   /* On read if the image is a 16-bit per component image and there is no gAMA
+    * or sRGB chunk assume that the components are sRGB encoded.  Notice that
+    * images output by the simplified API always have gamma information; setting
+    * this flag only affects the interpretation of 16-bit images from an
+    * external source.  It is recommended that the application expose this flag
+    * to the user; the user can normally easily recognize the difference between
+    * linear and sRGB encoding.  This flag has no effect on write - the data
+    * passed to the write APIs must have the correct encoding (as defined
+    * above.)
+    *
+    * If the flag is not set (the default) input 16-bit per component data is
+    * assumed to be linear.
+    *
+    * NOTE: the flag can only be set after the png_image_begin_read_ call,
+    * because that call initializes the 'flags' field.
+    */
+
 #ifdef PNG_SIMPLIFIED_READ_SUPPORTED
 /* READ APIs
  * ---------
@@ -3138,7 +3168,7 @@ PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image,
     *    PNG_FORMAT_FLAG_LINEAR *not* set.
     *
     * For linear output removing the alpha channel is always done by compositing
-    * on black and background is ignored.:
+    * on black and background is ignored.
     *
     * colormap must be supplied when PNG_FORMAT_FLAG_COLORMAP is set.  It must
     * be at least the size (in bytes) returned by PNG_IMAGE_COLORMAP_SIZE.
@@ -3209,6 +3239,47 @@ PNG_EXPORT(243, int, png_get_palette_max, (png_const_structp png_ptr,
 #  endif
 #endif /* CHECK_FOR_INVALID_INDEX */
 
+/*******************************************************************************
+ *  IMPLEMENTATION OPTIONS
+ *******************************************************************************
+ *
+ * Support for arbitrary implementation-specific optimizations.  The API allows
+ * particular options to be turned on or off.  'Option' is the number of the
+ * option and 'onoff' is 0 (off) or non-0 (on).  The value returned is given
+ * by the PNG_OPTION_ defines below.
+ *
+ * HARDWARE: normally hardware capabilites, such as the Intel SSE instructions,
+ *           are detected at run time, however sometimes it may be impossible
+ *           to do this in user mode, in which case it is necessary to discover
+ *           the capabilities in an OS specific way.  Such capabilities are
+ *           listed here when libpng has support for them and must be turned
+ *           ON by the application if present.
+ *
+ * SOFTWARE: sometimes software optimizations actually result in performance
+ *           decrease on some architectures or systems, or with some sets of
+ *           PNG images.  'Software' options allow such optimizations to be
+ *           selected at run time.
+ */
+#ifdef PNG_SET_OPTION_SUPPORTED
+#ifdef PNG_ARM_NEON_API_SUPPORTED
+#  define PNG_ARM_NEON   0 /* HARDWARE: ARM Neon SIMD instructions supported */
+#endif
+#define PNG_OPTION_NEXT  2 /* Next option - numbers must be even */
+
+/* Return values: NOTE: there are four values and 'off' is *not* zero */
+#define PNG_OPTION_UNSET   0 /* Unset - defaults to off */
+#define PNG_OPTION_INVALID 1 /* Option number out of range */
+#define PNG_OPTION_OFF     2
+#define PNG_OPTION_ON      3
+
+PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option,
+   int onoff));
+#endif
+
+/*******************************************************************************
+ *  END OF HARDWARE OPTIONS
+ ******************************************************************************/
+
 /* Maintainer: Put new public prototypes here ^, in libpng.3, and project
  * defs, scripts/pnglibconf.h, and scripts/pnglibconf.h.prebuilt
  */
@@ -3218,7 +3289,7 @@ PNG_EXPORT(243, int, png_get_palette_max, (png_const_structp png_ptr,
  * scripts/symbols.def as well.
  */
 #ifdef PNG_EXPORT_LAST_ORDINAL
-  PNG_EXPORT_LAST_ORDINAL(243);
+  PNG_EXPORT_LAST_ORDINAL(244);
 #endif
 
 #ifdef __cplusplus
index cbfd517ddbc0c6e84bbf7194511484555a1d8e54..d9dbff0852eef963bce3b92379b95cb090dfc69b 100644 (file)
@@ -1,7 +1,7 @@
 
 /* pngconf.h - machine configurable file for libpng
  *
- * libpng version 1.6.0 - February 14, 2013
+ * libpng version 1.6.1 - March 28, 2013
  *
  * Copyright (c) 1998-2013 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
 #    define PNGCAPI __watcall
 #  endif
 
-#  if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800))
+#  if defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 800))
 #    define PNGCAPI __cdecl
 #    if PNG_API_RULE == 1
        /* If this line results in an error __stdcall is not understood and
index 18152d96c0be1e4a03ef595476047748081bfb6b..f469206ee46a115341802d05f09f46f0ebcc50e2 100644 (file)
@@ -1,7 +1,7 @@
 
 /* pngerror.c - stub functions for i/o and memory allocation
  *
- * Last changed in libpng 1.6.0 [February 14, 2013]
+ * Last changed in libpng 1.6.1 [March 28, 2013]
  * Copyright (c) 1998-2013 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -516,7 +516,7 @@ png_chunk_report(png_const_structrp png_ptr, png_const_charp message, int error)
    /* This is always supported, but for just read or just write it
     * unconditionally does the right thing.
     */
-#  if (defined PNG_READ_SUPPORTED) && (defined PNG_WRITE_SUPPORTED)
+#  if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED)
       if (png_ptr->mode & PNG_IS_READ_STRUCT)
 #  endif
 
@@ -530,7 +530,7 @@ png_chunk_report(png_const_structrp png_ptr, png_const_charp message, int error)
       }
 #  endif
 
-#  if (defined PNG_READ_SUPPORTED) && (defined PNG_WRITE_SUPPORTED)
+#  if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED)
       else if (!(png_ptr->mode & PNG_IS_READ_STRUCT))
 #  endif
 
@@ -844,8 +844,8 @@ png_set_strip_error_numbers(png_structrp png_ptr, png_uint_32 strip_mode)
 }
 #endif
 
-#if defined PNG_SIMPLIFIED_READ_SUPPORTED ||\
-   defined PNG_SIMPLIFIED_WRITE_SUPPORTED
+#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
+   defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
    /* Currently the above both depend on SETJMP_SUPPORTED, however it would be
     * possible to implement without setjmp support just so long as there is some
     * way to handle the error return here:
index 03c8c1046959cf2861bafc099c5b5c63c66e91fa..aca63a9589ce022367deddabef46e42b3b4db444 100644 (file)
@@ -1,7 +1,7 @@
 
 /* pngget.c - retrieval of values from info struct
  *
- * Last changed in libpng 1.6.0 [February 14, 2013]
+ * Last changed in libpng 1.6.1 [March 28, 2013]
  * Copyright (c) 1998-2013 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -552,14 +552,14 @@ png_get_cHRM_XYZ(png_const_structrp png_ptr, png_const_inforp info_ptr,
          *green_Z = png_float(png_ptr,
             info_ptr->colorspace.end_points_XYZ.green_Z, "cHRM green Z");
       if (blue_X != NULL)
-         *blue_X = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.blue_X,
-            "cHRM blue X");
+         *blue_X = png_float(png_ptr,
+            info_ptr->colorspace.end_points_XYZ.blue_X, "cHRM blue X");
       if (blue_Y != NULL)
-         *blue_Y = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.blue_Y,
-            "cHRM blue Y");
+         *blue_Y = png_float(png_ptr,
+            info_ptr->colorspace.end_points_XYZ.blue_Y, "cHRM blue Y");
       if (blue_Z != NULL)
-         *blue_Z = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.blue_Z,
-            "cHRM blue Z");
+         *blue_Z = png_float(png_ptr,
+            info_ptr->colorspace.end_points_XYZ.blue_Z, "cHRM blue Z");
       return (PNG_INFO_cHRM);
    }
 
@@ -844,8 +844,8 @@ png_get_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
 
 #ifdef PNG_sCAL_SUPPORTED
 #  ifdef PNG_FIXED_POINT_SUPPORTED
-#    if (defined PNG_FLOATING_ARITHMETIC_SUPPORTED) || \
-         (defined PNG_FLOATING_POINT_SUPPORTED)
+#    if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || \
+         defined(PNG_FLOATING_POINT_SUPPORTED)
 png_uint_32 PNGAPI
 png_get_sCAL_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
     int *unit, png_fixed_point *width, png_fixed_point *height)
index 90f11dabbf3f95e96d411e3eef356a2fe802be89..26bf26502cf2d9fbfe7cdef0db3fbfdea1fdd376 100644 (file)
@@ -1,11 +1,11 @@
 
 /* pnginfo.h - header file for PNG reference library
  *
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2013 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
- * Last changed in libpng 1.5.0 [January 6, 2011]
+ * Last changed in libpng 1.6.1 [March 28, 2013]
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
@@ -88,7 +88,7 @@ struct png_info_def
     * and initialize the appropriate fields below.
     */
 
-#if defined PNG_COLORSPACE_SUPPORTED || defined PNG_GAMMA_SUPPORTED
+#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
    /* png_colorspace only contains 'flags' if neither GAMMA or COLORSPACE are
     * defined.  When COLORSPACE is switched on all the colorspace-defining
     * chunks should be enabled, when GAMMA is switched on all the gamma-defining
index 22f1919b0bbebdb561ee68e59efb55c61fc53007..35e7eddd3213bfc9864e54ac5690de31f59ec95d 100644 (file)
@@ -6,7 +6,7 @@
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
- * Last changed in libpng 1.6.0 [February 14, 2013]
+ * Last changed in libpng 1.6.1 [March 28, 2013]
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
  */
 #define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */
 
+#ifndef PNG_VERSION_INFO_ONLY
 /* Standard library headers not required by png.h: */
-#include <stdlib.h>
-#include <string.h>
+#  include <stdlib.h>
+#  include <string.h>
+#endif
 
 #define PNGLIB_BUILD /*libpng is being built, not used*/
 
@@ -54,7 +56,7 @@
  * configure generated config.h.  Libpng is expected to compile without *any*
  * special build system support on a reasonably ANSI-C compliant system.
  */
-#if (defined HAVE_CONFIG_H) && !(defined PNG_NO_CONFIG_H)
+#if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H)
 #  include <config.h>
 
    /* Pick up the definition of 'restrict' from config.h if it was read: */
@@ -71,7 +73,7 @@
 #endif
 
 /* Local renames may change non-exported API functions from png.h */
-#if defined PNG_PREFIX && !defined PNGPREFIX_H
+#if defined(PNG_PREFIX) && !defined(PNGPREFIX_H)
 #  include "pngprefix.h"
 #endif
 
 #  ifndef PNG_FLOATING_POINT_SUPPORTED
 #     define PNG_FP_EXPORT(ordinal, type, name, args)\
          PNG_INTERNAL_FUNCTION(type, name, args, PNG_EMPTY);
-      typedef struct png_incomplete png_double;
-      typedef png_double*           png_doublep;
-      typedef const png_double*     png_const_doublep;
-      typedef png_double**          png_doublepp;
+#     ifndef PNG_VERSION_INFO_ONLY
+         typedef struct png_incomplete png_double;
+         typedef png_double*           png_doublep;
+         typedef const png_double*     png_const_doublep;
+         typedef png_double**          png_doublepp;
+#     endif
 #  endif
 #endif
 #ifndef PNG_FIXED_EXPORT
 #endif
 
 #include "png.h"
-#include "pngstruct.h"
-#include "pnginfo.h"
 
 /* pngconf.h does not set PNG_DLL_EXPORT unless it is required, so: */
 #ifndef PNG_DLL_EXPORT
 #  endif
 #endif
 
-/* This is used for 16 bit gamma tables -- only the top level pointers are
- * const; this could be changed:
- */
-typedef const png_uint_16p * png_const_uint_16pp;
-
 /* Moved to pngpriv.h at libpng-1.5.0 */
 /* NOTE: some of these may have been used in external applications as
  * these definitions were exposed in pngconf.h prior to 1.5.
@@ -331,6 +328,7 @@ typedef const png_uint_16p * png_const_uint_16pp;
 #  define PNGFAPI /* PRIVATE */
 #endif
 
+#ifndef PNG_VERSION_INFO_ONLY
 /* Other defines specific to compilers can go here.  Try to keep
  * them inside an appropriate ifdef/endif pair for portability.
  */
@@ -375,6 +373,7 @@ typedef const png_uint_16p * png_const_uint_16pp;
     defined(_WIN32) || defined(__WIN32__)
 #  include <windows.h>  /* defines _WINDOWS_ macro */
 #endif
+#endif /* PNG_VERSION_INFO_ONLY */
 
 /* Moved here around 1.5.0beta36 from pngconf.h */
 /* Users may want to use these so they are not private.  Any library
@@ -553,26 +552,6 @@ typedef const png_uint_16p * png_const_uint_16pp;
    abs((int)((c1).green) - (int)((c2).green)) + \
    abs((int)((c1).blue) - (int)((c2).blue)))
 
-/* Added to libpng-1.5.7: sRGB conversion tables */
-#if defined PNG_SIMPLIFIED_READ_SUPPORTED ||\
-   defined PNG_SIMPLIFIED_WRITE_SUPPORTED
-#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
-PNG_INTERNAL_DATA(const png_uint_16, png_sRGB_table, [256]);
-   /* Convert from an sRGB encoded value 0..255 to a 16-bit linear value,
-    * 0..65535.  This table gives the closest 16-bit answers (no errors).
-    */
-#endif
-
-PNG_INTERNAL_DATA(const png_uint_16, png_sRGB_base, [512]);
-PNG_INTERNAL_DATA(const png_byte, png_sRGB_delta, [512]);
-
-#define PNG_sRGB_FROM_LINEAR(linear) ((png_byte)((png_sRGB_base[(linear)>>15] +\
-   ((((linear)&0x7fff)*png_sRGB_delta[(linear)>>15])>>12)) >> 8))
-   /* Given a value 'linear' in the range 0..255*65535 calculate the 8-bit sRGB
-    * encoded value with maximum error 0.646365.  Note that the input is not a
-    * 16-bit value; it has been multiplied by 255! */
-#endif /* PNG_SIMPLIFIED_READ/WRITE */
-
 /* Added to libpng-1.6.0: scale a 16-bit value in the range 0..65535 to 0..255
  * by dividing by 257 *with rounding*.  This macro is exact for the given range.
  * See the discourse in pngrtran.c png_do_scale_16_to_8.  The values in the
@@ -707,6 +686,39 @@ PNG_INTERNAL_DATA(const png_byte, png_sRGB_delta, [512]);
 #define PNG_GAMMA_MAC_INVERSE 65909
 #define PNG_GAMMA_sRGB_INVERSE 45455
 
+/* Almost everything below is C specific; the #defines above can be used in
+ * non-C code (so long as it is C-preprocessed) the rest of this stuff cannot.
+ */
+#ifndef PNG_VERSION_INFO_ONLY
+
+#include "pngstruct.h"
+#include "pnginfo.h"
+
+/* This is used for 16 bit gamma tables -- only the top level pointers are
+ * const; this could be changed:
+ */
+typedef const png_uint_16p * png_const_uint_16pp;
+
+/* Added to libpng-1.5.7: sRGB conversion tables */
+#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
+   defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
+#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
+PNG_INTERNAL_DATA(const png_uint_16, png_sRGB_table, [256]);
+   /* Convert from an sRGB encoded value 0..255 to a 16-bit linear value,
+    * 0..65535.  This table gives the closest 16-bit answers (no errors).
+    */
+#endif
+
+PNG_INTERNAL_DATA(const png_uint_16, png_sRGB_base, [512]);
+PNG_INTERNAL_DATA(const png_byte, png_sRGB_delta, [512]);
+
+#define PNG_sRGB_FROM_LINEAR(linear) ((png_byte)((png_sRGB_base[(linear)>>15] +\
+   ((((linear)&0x7fff)*png_sRGB_delta[(linear)>>15])>>12)) >> 8))
+   /* Given a value 'linear' in the range 0..255*65535 calculate the 8-bit sRGB
+    * encoded value with maximum error 0.646365.  Note that the input is not a
+    * 16-bit value; it has been multiplied by 255! */
+#endif /* PNG_SIMPLIFIED_READ/WRITE */
+
 
 /* Inhibit C++ name-mangling for libpng functions but not for system calls. */
 #ifdef __cplusplus
@@ -757,8 +769,8 @@ PNG_INTERNAL_FUNCTION(int,png_user_version_check,(png_structrp png_ptr,
 PNG_INTERNAL_FUNCTION(png_voidp,png_malloc_base,(png_const_structrp png_ptr,
    png_alloc_size_t size),PNG_ALLOCATED);
 
-#if defined PNG_TEXT_SUPPORTED || defined PNG_sPLT_SUPPORTED ||\
-   defined PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
+#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) ||\
+   defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED)
 /* Internal array allocator, outputs no error or warning messages on failure,
  * just returns NULL.  
  */
@@ -1824,8 +1836,8 @@ PNG_INTERNAL_FUNCTION(void,png_build_gamma_table,(png_structrp png_ptr,
 #endif
 
 /* SIMPLIFIED READ/WRITE SUPPORT */
-#if defined PNG_SIMPLIFIED_READ_SUPPORTED ||\
-   defined PNG_SIMPLIFIED_WRITE_SUPPORTED
+#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
+   defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
 /* The internal structure that png_image::opaque points to. */
 typedef struct png_control
 {
@@ -1880,7 +1892,8 @@ PNG_INTERNAL_FUNCTION(void, png_image_free, (png_imagep image), PNG_EMPTY);
 #endif /* SIMPLIFIED READ/WRITE */
 
 #ifdef PNG_FILTER_OPTIMIZATIONS
-PNG_INTERNAL_FUNCTION(void, PNG_FILTER_OPTIMIZATIONS, (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, PNG_FILTER_OPTIMIZATIONS, (png_structp png_ptr,
+    unsigned int bpp), PNG_EMPTY);
    /* This is the initialization function for hardware specific optimizations,
     * one implementation (for ARM NEON machines) is contained in
     * arm/filter_neon.c.  It need not be defined - the generic code will be used
@@ -1896,4 +1909,5 @@ PNG_INTERNAL_FUNCTION(void, PNG_FILTER_OPTIMIZATIONS, (png_structp png_ptr, unsi
 }
 #endif
 
+#endif /* PNG_VERSION_INFO_ONLY */
 #endif /* PNGPRIV_H */
index 5cd20e8c39460957d13edfc4bfba13ce4adf0ade..e32f31d5416d85856dfa00ee39e06494c81aa9b4 100644 (file)
@@ -1,7 +1,7 @@
 
 /* pngread.c - read a PNG file
  *
- * Last changed in libpng 1.6.0 [February 14, 2013]
+ * Last changed in libpng 1.6.1 [March 28, 2013]
  * Copyright (c) 1998-2013 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -15,7 +15,7 @@
  */
 
 #include "pngpriv.h"
-#if defined PNG_SIMPLIFIED_READ_SUPPORTED && defined PNG_STDIO_SUPPORTED
+#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
 #  include <errno.h>
 #endif
 
@@ -877,8 +877,8 @@ png_read_destroy(png_structrp png_ptr)
    png_free(png_ptr, png_ptr->save_buffer);
 #endif
 
-#if (defined PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) &&\
-   (defined PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
+#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) &&\
+   defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
    png_free(png_ptr, png_ptr->unknown_chunk.data);
 #endif
 
@@ -2004,6 +2004,28 @@ png_image_read_colormap(png_voidp argument)
    else
       back_b = back_r = back_g = 255;
 
+   /* Default the input file gamma if required - this is necessary because
+    * libpng assumes that if no gamma information is present the data is in the
+    * output format, but the simplified API deduces the gamma from the input
+    * format.
+    */
+   if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) == 0)
+   {
+      /* Do this directly, not using the png_colorspace functions, to ensure
+       * that it happens even if the colorspace is invalid (though probably if
+       * it is the setting will be ignored)  Note that the same thing can be
+       * achieved at the application interface with png_set_gAMA.
+       */
+      if (png_ptr->bit_depth == 16 &&
+         (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0)
+         png_ptr->colorspace.gamma = PNG_GAMMA_LINEAR;
+
+      else
+         png_ptr->colorspace.gamma = PNG_GAMMA_sRGB_INVERSE;
+
+      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
+   }
+
    /* Decide what to do based on the PNG color type of the input data.  The
     * utility function png_create_colormap_entry deals with most aspects of the
     * output transformations; this code works out how to produce bytes of
@@ -3547,7 +3569,8 @@ png_image_read_direct(png_voidp argument)
       {
          png_fixed_point input_gamma_default;
 
-         if (base_format & PNG_FORMAT_FLAG_LINEAR)
+         if ((base_format & PNG_FORMAT_FLAG_LINEAR) &&
+            (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0)
             input_gamma_default = PNG_GAMMA_LINEAR;
          else
             input_gamma_default = PNG_DEFAULT_sRGB;
index a485cacc4f76dffc73c0b5a17e776c2a7a717901..626f3b0ecbefe5c2fb2bd6e764bbf1c5a21533c8 100644 (file)
@@ -1,7 +1,7 @@
 
 /* pngrtran.c - transforms the data in a row for PNG readers
  *
- * Last changed in libpng 1.6.0 [February 14, 2013]
+ * Last changed in libpng 1.6.1 [March 28, 2013]
  * Copyright (c) 1998-2013 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -1412,7 +1412,7 @@ png_init_read_transformations(png_structrp png_ptr)
 #endif
 
 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
-#if defined PNG_READ_EXPAND_SUPPORTED && defined PNG_READ_BACKGROUND_SUPPORTED
+#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
    /* Detect gray background and attempt to enable optimization for
     * gray --> RGB case.
     *
@@ -2239,8 +2239,8 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)
       png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
 #endif
 
-#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
-   (defined PNG_READ_ALPHA_MODE_SUPPORTED)
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
+   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
    if (png_ptr->transformations & PNG_COMPOSE)
       png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr);
 #endif
@@ -2251,8 +2251,8 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)
       /* Because RGB_TO_GRAY does the gamma transform. */
       !(png_ptr->transformations & PNG_RGB_TO_GRAY) &&
 #endif
-#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
-   (defined PNG_READ_ALPHA_MODE_SUPPORTED)
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
+   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
       /* Because PNG_COMPOSE does the gamma transform if there is something to
        * do (if there is an alpha channel or transparency.)
        */
@@ -3518,8 +3518,8 @@ png_build_grayscale_palette(int bit_depth, png_colorp palette)
 
 
 #ifdef PNG_READ_TRANSFORMS_SUPPORTED
-#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
-   (defined PNG_READ_ALPHA_MODE_SUPPORTED)
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
+   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
 /* Replace any alpha or transparency with the supplied background color.
  * "background" is already in the screen gamma, while "background_1" is
  * at a gamma of 1.0.  Paletted files have already been taken care of.
index e66075786e1138273640bf87e0ae90754bdf43e7..3f4474c9b9898880ca4320eb4adf987efac04d5e 100644 (file)
@@ -1,8 +1,8 @@
 
 /* pngrutil.c - utilities to read a PNG file
  *
- * Last changed in libpng 1.6.0 [(PENDING RELEASE)]
- * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.1 [March 28, 2013]
+ * Copyright (c) 1998-2013 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -2804,21 +2804,26 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr,
             {
                /* If the keep value is 'default' or 'never' override it, but
                 * still error out on critical chunks unless the keep value is
-                * 'always'  While this is weird it is the behavior in 1.4.12.  A
-                * possible improvement would be to obey the value set for the
+                * 'always'  While this is weird it is the behavior in 1.4.12.
+                * possible improvement would be to obey the value set for the
                 * chunk, but this would be an API change that would probably
                 * damage some applications.
                 *
                 * The png_app_warning below catches the case that matters, where
-                * the application has neither set specific save for this chunk
-                * or global save.
+                * the application has not set specific save or ignore for this
+                * chunk or global save or ignore.
                 */
                if (keep < PNG_HANDLE_CHUNK_IF_SAFE)
                {
 #                 ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
                      if (png_ptr->unknown_default < PNG_HANDLE_CHUNK_IF_SAFE)
+                     {
+                        png_chunk_warning(png_ptr, "Saving unknown chunk:");
                         png_app_warning(png_ptr,
- "forcing save of an unhandled chunk; please call png_set_keep_unknown_chunks");
+                           "forcing save of an unhandled chunk;"
+                           " please call png_set_keep_unknown_chunks");
+                           /* with keep = PNG_HANDLE_CHUNK_IF_SAFE */
+                     }
 #                 endif
                   keep = PNG_HANDLE_CHUNK_IF_SAFE;
                }
@@ -3350,7 +3355,7 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display)
                      png_uint_32p dp32 = png_aligncast(png_uint_32p,dp);
                      png_const_uint_32p sp32 = png_aligncastconst(
                         png_const_uint_32p, sp);
-                     unsigned int skip = (bytes_to_jump-bytes_to_copy) /
+                     size_t skip = (bytes_to_jump-bytes_to_copy) /
                         (sizeof (png_uint_32));
 
                      do
@@ -3392,7 +3397,7 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display)
                      png_uint_16p dp16 = png_aligncast(png_uint_16p, dp);
                      png_const_uint_16p sp16 = png_aligncastconst(
                         png_const_uint_16p, sp);
-                     unsigned int skip = (bytes_to_jump-bytes_to_copy) /
+                     size_t skip = (bytes_to_jump-bytes_to_copy) /
                         (sizeof (png_uint_16));
 
                      do
index 84973f5ff62917cd29853c54f409b51b0ee77def..c88d62153ca8548efb0bbf2cfc5a8ba2c4f17a63 100644 (file)
@@ -1,7 +1,7 @@
 
 /* pngset.c - storage of image information into info struct
  *
- * Last changed in libpng 1.6.0 [February 14, 2013]
+ * Last changed in libpng 1.6.1 [March 28, 2013]
  * Copyright (c) 1998-2013 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -514,7 +514,7 @@ png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr,
 
    png_debug1(1, "in %s storage function", "PLTE");
 
-   if (png_ptr == NULL || info_ptr == NULL || palette == NULL)
+   if (png_ptr == NULL || info_ptr == NULL)
       return;
 
    if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH)
@@ -529,6 +529,17 @@ png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr,
       }
    }
 
+   if ((num_palette > 0 && palette == NULL) ||
+      (num_palette == 0
+#        ifdef PNG_MNG_FEATURES_SUPPORTED
+            && (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0
+#        endif
+      ))
+   {
+      png_chunk_report(png_ptr, "Invalid palette", PNG_CHUNK_ERROR);
+      return;
+   }
+
    /* It may not actually be necessary to set png_ptr->palette here;
     * we do it for backward compatibility with the way the png_handle_tRNS
     * function used to do the allocation.
@@ -545,7 +556,8 @@ png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr,
    png_ptr->palette = png_voidcast(png_colorp, png_calloc(png_ptr,
        PNG_MAX_PALETTE_LENGTH * (sizeof (png_color))));
 
-   memcpy(png_ptr->palette, palette, num_palette * (sizeof (png_color)));
+   if (num_palette > 0)
+      memcpy(png_ptr->palette, palette, num_palette * (sizeof (png_color)));
    info_ptr->palette = png_ptr->palette;
    info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette;
 
@@ -1116,16 +1128,16 @@ png_set_unknown_chunks(png_const_structrp png_ptr,
     * code) but may be meaningless if the read or write handling of unknown
     * chunks is not compiled in.
     */
-#  if !(defined PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) && \
-      (defined PNG_READ_SUPPORTED)
+#  if !defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) && \
+      defined(PNG_READ_SUPPORTED)
       if (png_ptr->mode & PNG_IS_READ_STRUCT)
       {
          png_app_error(png_ptr, "no unknown chunk support on read");
          return;
       }
 #  endif
-#  if !(defined PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) && \
-      (defined PNG_WRITE_SUPPORTED)
+#  if !defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) && \
+      defined(PNG_WRITE_SUPPORTED)
       if (!(png_ptr->mode & PNG_IS_READ_STRUCT))
       {
          png_app_error(png_ptr, "no unknown chunk support on write");
index b8202d13a48a84f8ea407340a10c0d01d5c03df6..d58c0288449fcd85931b18f919ba4a26e912cc2e 100644 (file)
@@ -5,7 +5,7 @@
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
- * Last changed in libpng 1.6.0 [February 14, 2013]
+ * Last changed in libpng 1.6.1 [March 28, 2013]
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
@@ -100,7 +100,7 @@ typedef struct png_XYZ
 } png_XYZ;
 #endif /* COLORSPACE */
 
-#if defined PNG_COLORSPACE_SUPPORTED || defined PNG_GAMMA_SUPPORTED
+#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
 /* A colorspace is all the above plus, potentially, profile information,
  * however at present libpng does not use the profile internally so it is only
  * stored in the png_info struct (if iCCP is supported.)  The rendering intent
@@ -357,6 +357,11 @@ struct png_struct_def
    png_uint_16p inv_filter_costs;    /* 1/relative filter calculation cost */
 #endif
 
+   /* Options */
+#ifdef PNG_SET_OPTION_SUPPORTED
+   png_byte options;           /* On/off state (up to 4 options) */
+#endif
+
 #if PNG_LIBPNG_VER < 10700
 /* To do: remove this from libpng-1.7 */
 #ifdef PNG_TIME_RFC1123_SUPPORTED
@@ -471,11 +476,12 @@ struct png_struct_def
 /* New member added in libpng-1.5.6 */
    png_bytep big_prev_row;
 
+/* New member added in libpng-1.5.7 */
    void (*read_filter[PNG_FILTER_VALUE_LAST-1])(png_row_infop row_info,
       png_bytep row, png_const_bytep prev_row);
 
 #ifdef PNG_READ_SUPPORTED
-#if defined PNG_COLORSPACE_SUPPORTED || defined PNG_GAMMA_SUPPORTED
+#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
    png_colorspace   colorspace;
 #endif
 #endif
index 4787a246df3afbaec76baf3f42c0247501fe06bd..fd0e8174d1c968e89b868c8d5f032321e2a40cf0 100644 (file)
@@ -1,7 +1,7 @@
 
 /* pngtest.c - a simple test program to test libpng
  *
- * Last changed in libpng 1.6.0 [February 14, 2013]
+ * Last changed in libpng 1.6.1 [March 28, 2013]
  * Copyright (c) 1998-2013 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -1470,7 +1470,8 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
 
    /* When the unknown vpAg/sTER chunks are written by pngtest the only way to
     * do it is to write them *before* calling png_write_end.  When unknown
-    * chunks are written by libpng, however, they are written just before IEND.     * There seems to be no way round this, however vpAg/sTER are not expected
+    * chunks are written by libpng, however, they are written just before IEND.
+    * There seems to be no way round this, however vpAg/sTER are not expected
     * after IDAT.
     */
    write_chunks(write_ptr, after_IDAT);
@@ -1949,4 +1950,4 @@ main(void)
 #endif
 
 /* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_6_0 Your_png_h_is_not_version_1_6_0;
+typedef png_libpng_version_1_6_1 Your_png_h_is_not_version_1_6_1;
index aa18712fb1cabc91ff7737b8606f793acc9cb1a9..b0887bd7584ba39dfd313296dd8a42b6fe5353f3 100644 (file)
@@ -1,7 +1,7 @@
 
 /* pngwrite.c - general routines to write a PNG file
  *
- * Last changed in libpng 1.6.0 [February 14, 2013]
+ * Last changed in libpng 1.6.1 [March 28, 2013]
  * Copyright (c) 1998-2013 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -12,7 +12,7 @@
  */
 
 #include "pngpriv.h"
-#if defined PNG_SIMPLIFIED_WRITE_SUPPORTED && defined PNG_STDIO_SUPPORTED
+#if defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
 #  include <errno.h>
 #endif
 
index 907292fedc1f2ff0f8e1406dcb8afca5d7cc6d86..27b5e52f847fa96f090e4dead488b6af76945d16 100644 (file)
@@ -1,9 +1,9 @@
 
-Makefiles for  libpng version 1.6.0 - February 14, 2013
+Makefiles for  libpng version 1.6.1 - March 28, 2013
 
 pnglibconf.h.prebuilt       =>  Stores configuration settings
  makefile.linux    =>  Linux/ELF makefile
-                       (gcc, creates libpng16.so.16.1.6.0)
+                       (gcc, creates libpng16.so.16.1.6.1)
  makefile.gcc      =>  Generic makefile (gcc, creates static libpng.a)
  makefile.knr      =>  Archaic UNIX Makefile that converts files with
                        ansi2knr (Requires ansi2knr.c from
@@ -20,7 +20,7 @@ pnglibconf.h.prebuilt       =>  Stores configuration settings
  makefile.dec      =>  DEC Alpha UNIX makefile
  makefile.dj2      =>  DJGPP 2 makefile
  makefile.elf      =>  Linux/ELF makefile symbol versioning,
-                       (gcc, creates libpng16.so.16.1.6.0)
+                       (gcc, creates libpng16.so.16.1.6.1)
  makefile.freebsd  =>  FreeBSD makefile
  makefile.gcc      =>  Generic gcc makefile
  makefile.hpgcc    =>  HPUX makefile using gcc
@@ -35,12 +35,12 @@ pnglibconf.h.prebuilt       =>  Stores configuration settings
  makefile.os2      =>  OS/2 Makefile (gcc and emx, requires libpng.def)
  makefile.sco      =>  For SCO OSr5  ELF and Unixware 7 with Native cc
  makefile.sggcc    =>  Silicon Graphics (gcc,
-                       creates libpng16.so.16.1.6.0)
+                       creates libpng16.so.16.1.6.1)
  makefile.sgi      =>  Silicon Graphics IRIX makefile (cc, creates static lib)
  makefile.solaris  =>  Solaris 2.X makefile (gcc,
-                       creates libpng16.so.16.1.6.0)
+                       creates libpng16.so.16.1.6.1)
  makefile.so9      =>  Solaris 9 makefile (gcc,
-                       creates libpng16.so.16.1.6.0)
+                       creates libpng16.so.16.1.6.1)
  makefile.std      =>  Generic UNIX makefile (cc, creates static libpng.a)
  makefile.sunos    =>  Sun makefile
  makefile.32sunu   =>  Sun Ultra 32-bit makefile
index 6857dff1c9202d7361e3d9543da94999f962a57b..fe3af55e05e3486e5f71a7b6b401fc3c5c5e0133 100755 (executable)
@@ -113,6 +113,16 @@ END{
       err = 1
    }
    unexported=0
+   # Add a standard header to symbols.new:
+   print ";Version INSERT-VERSION-HERE" >of
+   print ";--------------------------------------------------------------" >of
+   print "; LIBPNG symbol list as a Win32 DEF file" >of
+   print "; Contains all the symbols that can be exported from libpng" >of
+   print ";--------------------------------------------------------------" >of
+   print "LIBRARY" >of
+   print "" >of
+   print "EXPORTS" >of
+
    for (o=1; o<=lasto; ++o) {
       if (symbol[o] == "" && removed[o] == "") {
          if (unexported == 0) unexported = o
index cac3cd8566965b4f3c93f28ca1bd3ad8700fa385..5e1dc68699bbb3cb2ed15a88ed7ec06c5bd385da 100644 (file)
@@ -8,31 +8,22 @@
  * and license in png.h
  */
 
-/* These macros exist to make the header and trailer shorter below: */
-#define S PNG_DEFN_MAGIC
-#define E PNG_DEFN_END
-
 /* Write the export file header: */
-S-;---------------------------------------------------------------E
-S-; LIBPNG module definition file for OS/2-E
-S-;---------------------------------------------------------------E
-S--E
-S-; If you give the library an explicit name one or other files-E
-S-; may need modifying to support the new name on one or more-E
-S-; systems.-E
-S-LIBRARY-E
-S-OS2 DESCRIPTION "PNG image compression library"-E
-S-OS2 CODE PRELOAD MOVEABLE DISCARDABLE-E
-S--E
-S-EXPORTS-E
-S-;Version 1.6.0-E
+PNG_DFN ";--------------------------------------------------------------"
+PNG_DFN "; LIBPNG module definition file for OS/2"
+PNG_DFN ";--------------------------------------------------------------"
+PNG_DFN ""
+PNG_DFN "; If you give the library an explicit name one or other files"
+PNG_DFN "; may need modifying to support the new name on one or more"
+PNG_DFN "; systems."
+PNG_DFN "LIBRARY"
+PNG_DFN "OS2 DESCRIPTION "PNG image compression library""
+PNG_DFN "OS2 CODE PRELOAD MOVEABLE DISCARDABLE"
+PNG_DFN ""
+PNG_DFN "EXPORTS"
+PNG_DFN ";Version 1.6.1"
 
-/* NOTE: PNG_JOIN is interpreted by the calling script as a signal to
- * join the two things on either side, so we can do symbol
- * substitution within the name, regular C ## joins the pp-tokens,
- * not their final values.
- */
 #define PNG_EXPORTA(ordinal, type, name, args, attributes)\
-       PNG_DEFN_MAGIC- SYMBOL_PREFIX PNG_JOIN name-PNG_DEFN_END
+        PNG_DFN "@" SYMBOL_PREFIX "@@" name "@"
 
 #include "../png.h"
diff --git a/l4/pkg/libpng/lib/dist/scripts/dfn.awk b/l4/pkg/libpng/lib/dist/scripts/dfn.awk
new file mode 100644 (file)
index 0000000..89b92d5
--- /dev/null
@@ -0,0 +1,203 @@
+#!/bin/awk -f
+# scripts/dfn.awk - process a .dfn file
+#
+# last changed in libpng version 1.5.14 - February 4, 2013
+#
+# Copyright (c) 2013-2013 Glenn Randers-Pehrson
+#
+# This code is released under the libpng license.
+# For conditions of distribution and use, see the disclaimer
+# and license in png.h
+
+# The output of this script is written to the file given by
+# the variable 'out', which should be set on the command line.
+# Error messages are printed to stdout and if any are printed
+# the script will exit with error code 1.
+
+BEGIN{
+   out="/dev/null"       # as a flag
+   out_count=0           # count of output lines
+   err=0                 # set if an error occured
+   sort=0                # sort the output
+   array[""]=""
+}
+
+# The output file must be specified before any input:
+NR==1 && out == "/dev/null" {
+   print "out=output.file must be given on the command line"
+   # but continue without setting the error code, this allows the
+   # script to be checked easily
+}
+
+# Output can be sorted; two lines are recognized
+$1 == "PNG_DFN_START_SORT"{
+   sort=0+$2
+   next
+}
+
+$1 ~ /^PNG_DFN_END_SORT/{
+   # Do a very simple, slow, sort; notice that blank lines won't be
+   # output by this
+   for (entry in array) {
+      while (array[entry] != "") {
+         key = entry
+         value = array[key]
+         array[key] = ""
+
+         for (alt in array) {
+            if (array[alt] != "" && alt < key) {
+               array[key] = value
+               value = array[alt]
+               key = alt
+               array[alt] = ""
+            }
+         }
+
+         print value >out
+      }
+   }
+   sort=0
+   next
+}
+
+/^[^"]*PNG_DFN *".*"[^"]*$/{
+   # A definition line, apparently correctly formated, extract the
+   # definition then replace any doubled "" that remain with a single
+   # double quote.  Notice that the original doubled double quotes
+   # may have been split by tokenization
+   #
+   # Sometimes GCC splits the PNG_DFN lines, we know this has happened
+   # if the quotes aren't closed and must read another line.  In this
+   # case it is essential to reject lines that start '#' because those
+   # are introduced #line directives.
+   orig=$0
+   line=$0
+   lineno=FNR
+   if (lineno == "") lineno=NR
+
+   if (sub(/^[^"]*PNG_DFN *"/,"",line) != 1) {
+       print "line", lineno ": processing failed:"
+       print orig
+       err=1
+       next
+   } else {
+       ++out_count
+   }
+
+   # Now examine quotes within the value:
+   #
+   #   @" - delete this and any following spaces
+   #   "@ - delete this and any preceding spaces
+   #   @' - replace this by a double quote
+   #
+   # This allows macro substitution by the C compiler thus:
+   #
+   #   #define first_name John
+   #   #define last_name Smith
+   #
+   #   PNG_DFN"#define name @'@" first_name "@ @" last_name "@@'"
+   #
+   # Might get C preprocessed to:
+   #
+   #   PNG_DFN "#define foo @'@" John "@ @" Smith "@@'"
+   #
+   # Which this script reduces to:
+   #
+   #   #define name "John Smith"
+   #
+   while (1) {
+      # While there is an @" remove it and the next "@
+      if (line ~ /@"/) {
+         if (line ~ /@".*"@/) {
+            # Do this special case first to avoid swallowing extra spaces
+            # before or after the @ stuff:
+            if (!sub(/@" *"@/, "", line)) {
+               # Ok, do it in pieces - there has to be a non-space between the
+               # two.  NOTE: really weird things happen if a leading @" is
+               # lost - the code will error out below (I believe).
+               if (!sub(/@" */, "", line) || !sub(/ *"@/, "", line)) {
+                  print "line", lineno, ": internal error:", orig
+                  exit 1
+               }
+            }
+         }
+
+         # There is no matching "@.  Assume a split line
+         else while (1) {
+            if (getline nextline) {
+               # If the line starts with '#' it is a preprocesor line directive
+               # from cc -E, skip it:
+               if (nextline !~ /^#/) {
+                  line = line " " nextline
+                  break
+               }
+            } else {
+               # This is end-of-input - probably a missig "@ on the first line:
+               print "line", lineno ": unbalanced @\" ... \"@ pair"
+               err=1
+               next
+            }
+         }
+
+         # Keep going until all the @" have gone
+         continue
+      }
+
+      # Attempt to remove a trailing " (not preceded by '@') - if this can
+      # be done stop now, if not assume a split line again
+      if (sub(/"[^"]*$/, "", line))
+         break
+
+      # Read another line
+      while (1) {
+         if (getline nextline) {
+            if (nextline !~ /^#/) {
+               line = line " " nextline
+               # Go back to stripping @" "@ pairs
+               break
+            }
+         } else {
+            print "line", lineno ": unterminated PNG_DFN string"
+            err=1
+            next
+         }
+      }
+   }
+
+   # Put any needed double quotes in (at the end, because these would otherwise
+   # interfere with the processing above.)
+   gsub(/@'/,"\"", line)
+
+   # Remove any trailing spaces (not really required, but for
+   # editorial consistency
+   sub(/ *$/, "", line)
+
+   # Remove trailing CR
+   sub(/\r$/, "", line)
+
+   if (sort) {
+      if (split(line, parts) < sort) {
+         print "line", lineno ": missing sort field:", line
+         err=1
+      } else
+         array[parts[sort]] = line
+   }
+
+   else
+      print line >out
+   next
+}
+
+/PNG_DFN/{
+   print "line", NR, "incorrectly formated PNG_DFN line:"
+   print $0
+   err = 1
+}
+
+END{
+   if (out_count > 0 || err > 0)
+       exit err
+
+   print "no definition lines found"
+   exit 1
+}
index d48d540600d447e0b6587ef966a5a15aaf07591e..790bdfee92886403280d2b950f51f5dc16ba2597 100644 (file)
  */
 
 #define PNG_INTERNAL_DATA(type, name, array)\
-       PNG_DEFN_MAGIC-name-PNG_DEFN_END
+        PNG_DFN "@" name "@"
 
 #define PNG_INTERNAL_FUNCTION(type, name, args, attributes)\
-       PNG_DEFN_MAGIC-name-PNG_DEFN_END
+        PNG_DFN "@" name "@"
 
 #define PNGPREFIX_H /* self generation */
 #include "../pngpriv.h"
index 02d74009be12093f8c3c834a1b2e545b09d51d53..9803d2e68127f24962f496cb7ea2bd55fa96f967 100755 (executable)
@@ -11,7 +11,7 @@
 
 # Modeled after libxml-config.
 
-version=1.6.0
+version=1.6.1
 prefix=""
 libdir=""
 libs=""
index 367b38c9fa94379ac3525349c5291abc8a14d529..9bdfd73f6831e384d1f9000cf555f796448a8df0 100644 (file)
@@ -5,6 +5,6 @@ includedir=@includedir@/libpng16
 
 Name: libpng
 Description: Loads and saves PNG files
-Version: 1.6.0
+Version: 1.6.1
 Libs: -L${libdir} -lpng16
 Cflags: -I${includedir}
index 820518aec741f9b4f5350a2dc5a7ff715cd39888..3912afe587f974814723849bcb9cef6aef0494f2 100644 (file)
@@ -23,7 +23,7 @@
 
 VERMAJ = 1
 VERMIN = 6
-VERMIC = 0
+VERMIC = 1
 VER = $(VERMAJ).$(VERMIN).$(VERMIC)
 NAME = libpng
 PACKAGE = $(NAME)-$(VER)
index bc033934bdbf327207897bd2d2e2931e8d26fab3..0ddf4ae4aa9e8c9a17cd85109959485c56babfbe 100644 (file)
@@ -26,19 +26,24 @@ SYMLINKS=       libpng/png.h ${INCSDIR}/../png.h \
                libpng/pngconf.h ${INCSDIR}/../pngconf.h \
                libpng/pnglibconf.h ${INCSDIR}/../pnglibconf.h
 
-LDADD+=         -lm -lz
-#LDADD+=         -lm -lz -lssp_nonshared   # for OSVERSION < 800000 ?
+# where make install finds libz.a and zlib.h
+ZLIBLIB=       /usr/lib
+ZLIBINC=       /usr/include
+
+LDADD+=        -lm -lz
+#LDADD+=       -lm -lz -lssp_nonshared   # for OSVERSION < 800000 ?
 
 DPADD+=         ${LIBM} ${LIBZ}
 
-CFLAGS+= -I.
+CFLAGS+= -I. -I${ZLIBINC}
 
 SRCS=  png.c pngset.c pngget.c pngrutil.c pngtrans.c pngwutil.c \
        pngread.c pngrio.c pngwio.c pngwrite.c pngrtran.c \
        pngwtran.c pngmem.c pngerror.c pngpread.c
 
 pngtest: pngtest.o libpng.a
-       ${CC} ${CFLAGS} -L. -static -o pngtest pngtest.o -lpng -lz -lm
+       ${CC} ${CFLAGS} -L. -static -o pngtest pngtest.o -L${ZLIBLIB} \
+       -lpng ${LDADD}
 
 CLEANFILES= pngtest pngtest.o pngout.png
 
index 6e95c878c639454be480b2f0e9323e946bec174f..4e94ce909a18083abc518b4ebf050a48ac1cdcda 100644 (file)
@@ -10,7 +10,7 @@
 # Library name:
 LIBNAME = libpng16
 PNGMAJ = 16
-RELEASE = 0
+RELEASE = 1
 
 # Shared library names:
 LIBSO=$(LIBNAME).so
index 074fb5811099aedc422ee51c34d626d531edde9e..342c91242ba9b6829992d26cb0d9422a17e23087 100644 (file)
@@ -18,7 +18,7 @@ exec_prefix=$(prefix)
 # Library name:
 LIBNAME = libpng16
 PNGMAJ = 16
-RELEASE = 0
+RELEASE = 1
 
 # Shared library names:
 LIBSO=$(LIBNAME).dll
@@ -43,7 +43,7 @@ LN_SF=ln -sf
 
 #ARCH = -march=pentium3
 #ARCH = -march=i686
-ARCH = 
+ARCH =
 CDEBUG = -g -DPNG_DEBUG=5
 LDDEBUG =
 CRELEASE = -O2
index a20bc4e6eded26c5bfcfdc02b40bab0fd7bd4604..2313dd333270729c4bfcffe09c7804194f6e9047 100644 (file)
@@ -17,7 +17,7 @@ INCSDIR=${LOCALBASE}/include/libpng16
 
 LIB=   png16
 SHLIB_MAJOR=   0
-SHLIB_MINOR=   1.6.0
+SHLIB_MINOR=   1.6.1
 SRCS=  png.c pngset.c pngget.c pngrutil.c pngtrans.c pngwutil.c \
        pngread.c pngrio.c pngwio.c pngwrite.c pngrtran.c \
        pngwtran.c pngmem.c pngerror.c pngpread.c
index 719e8c34759a79a83c1b643b0aa22c687b97fe5e..41a2e9d0b0672ce195e9e3f06dae2d0bf9160149 100644 (file)
@@ -17,7 +17,7 @@ INCSDIR=${LOCALBASE}/include
 
 LIB=   png
 SHLIB_MAJOR=   16
-SHLIB_MINOR=   1.6.0
+SHLIB_MINOR=   1.6.1
 SRCS=  png.c pngset.c pngget.c pngrutil.c pngtrans.c pngwutil.c \
        pngread.c pngrio.c pngwio.c pngwrite.c pngrtran.c \
        pngwtran.c pngmem.c pngerror.c pngpread.c
index 447b38bd44d5b5aa04b21ead470815306d50f222..2d633743fef2cf325f606145be086a80d88e0c30 100644 (file)
@@ -11,7 +11,7 @@ LIBDIR=       ${PREFIX}/lib
 MANDIR= ${PREFIX}/man/cat
 
 SHLIB_MAJOR=   16
-SHLIB_MINOR=   1.6.0
+SHLIB_MINOR=   1.6.1
 
 LIB=   png
 SRCS=  png.c pngerror.c pngget.c pngmem.c pngpread.c \
index af70328009e8c9c36391087206c97946540fb26d..419eeedf29f2b125646fb4544b8967aeb9642777 100644 (file)
@@ -39,6 +39,7 @@ CPP = $(CC) -E
 ECHO = echo
 
 DFNFLAGS = # DFNFLAGS contains -D options to use in the libpng build
+DFA_EXTRA = # extra files that can be used to control configuration
 CFLAGS=-I$(ZLIBINC) -O # -g -DPNG_DEBUG=5
 LDFLAGS=-L. -L$(ZLIBLIB) -lpng -lz -lm
 
@@ -50,23 +51,23 @@ all: libpng.a pngtest
 
 # The standard pnglibconf.h exists as scripts/pnglibconf.h.prebuilt,
 # copy this if the following doesn't work.
-pnglibconf.dfn: scripts/pnglibconf.dfa scripts/options.awk pngconf.h
-       $(RM_F) $@ dfn?.out
-       $(AWK) -f scripts/options.awk out=dfn1.out version=search pngconf.h\
-           scripts/pnglibconf.dfa $(DFA_XTRA) 1>&2
-       $(AWK) -f scripts/options.awk out=dfn2.out dfn1.out 1>&2
-       cp dfn2.out $@
-       $(RM_F) dfn?.out
-
 pnglibconf.h: pnglibconf.dfn
-       $(RM_F) $@ dfn.c dfn?.out
-       $(ECHO) '#include "pnglibconf.dfn"' >dfn.c
-       $(CPP) $(DFNFLAGS) dfn.c >dfn1.out
-       $(SED) -n -e 's|^.*PNG_DEFN_MAGIC *-\(.*\)- *PNG_DEFN_END.*$$|\1|p'\
-           dfn1.out >dfn2.out
-       $(SED) -e 's| *PNG_JOIN *||g' -e 's| *$$||' dfn2.out >dfn3.out
-       cp dfn3.out $@
-       $(RM_F) dfn.c dfn?.out
+       $(RM_F) $@ pnglibconf.c pnglibconf.out pnglibconf.tmp
+       $(ECHO) '#include "pnglibconf.dfn"' >pnglibconf.c
+       $(ECHO) "If '$(CC) -E' crashes try /lib/cpp (e.g. CPP='/lib/cpp')" >&2
+       $(CPP) $(DFNFLAGS) pnglibconf.c >pnglibconf.out
+       $(AWK) -f "scripts/dfn.awk" out="pnglibconf.tmp" pnglibconf.out 1>&2
+       mv pnglibconf.tmp $@
+
+pnglibconf.dfn: scripts/pnglibconf.dfa scripts/options.awk pngconf.h pngusr.dfa $(DFA_XTRA)
+       $(RM_F) $@ pnglibconf.pre pnglibconf.tmp
+       $(ECHO) "Calling $(AWK) from scripts/pnglibconf.mak" >&2
+       $(ECHO) "If 'awk' crashes try a better awk (e.g. AWK='nawk')" >&2
+       $(AWK) -f scripts/options.awk out="pnglibconf.pre"\
+           version=search pngconf.h scripts/pnglibconf.dfa\
+           pngusr.dfa $(DFA_XTRA) 1>&2
+       $(AWK) -f scripts/options.awk out="pnglibconf.tmp" pnglibconf.pre 1>&2
+       mv pnglibconf.tmp $@
 
 libpng.a: $(OBJS)
        $(AR_RC) $@  $(OBJS)
@@ -96,7 +97,7 @@ install: libpng.a pnglibconf.h
        chmod 644 $(DESTDIR)$(LIBPATH)/libpng.a
 
 clean:
-       $(RM_F) *.o libpng.a pngtest pngout.png pnglibconf.* dfn.c dfn?.out
+       $(RM_F) *.o libpng.a pngtest pngout.png pnglibconf.*
 
 DOCS = ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO
 writelock:
index cb8cd184583f9ade3409f782aac97634f4007a08..c3a850173d0777b6f7ae10f0dc2d9336e230f272 100755 (executable)
 # are copied to the preprocessed file).
 
 BEGIN{
-   out="/dev/null"              # intermediate, preprocessed, file
+   out=""                       # intermediate, preprocessed, file
    pre=-1                       # preprocess (first line)
    version="libpng version unknown" # version information
    version_file=""              # where to find the version
    err=0                        # in-line exit sets this
-   start="PNG_DEFN_MAGIC-"      # Arbitrary start
-   end="-PNG_DEFN_END"          # Arbitrary end
-   ct="PNG_JOIN"                # Join two tokens
-   cx= "/" ct "*"               # Open C comment for output file
-   comment=start cx             # Comment start
+   # The following definitions prevent the C preprocessor noticing the lines
+   # that will be in the final output file.  Some C preprocessors tokenise
+   # the lines, for example by inserting spaces around operators, and all
+   # C preprocessors notice lines that start with '#', most remove comments.
+   # The technique adopted here is to make the final output lines into
+   # C strings (enclosed in double quotes), preceeded by PNG_DFN.  As a
+   # consequence the output cannot contain a 'raw' double quote - instead put
+   # @' in, this will be replaced by a single " afterward.  See the parser
+   # script dfn.awk for more capabilities (not required here).  Note that if
+   # you need a " in a 'setting' in pnglibconf.dfa it must also be @'!
+   dq="@'"                      # For a single double quote
+   start=" PNG_DFN \""          # Start stuff to output (can't contain a "!)
+   end="\" "                    # End stuff to output
+   subs="@\" "                  # Substitute start (substitute a C macro)
+   sube=" \"@"                  # Substitute end
+   comment=start "/*"           # Comment start
    cend="*/" end                # Comment end
-   def=start "#define PNG_" ct  # Arbitrary define
-   sup=ct "_SUPPORTED" end      # end supported option
-   und=comment "#undef PNG_" ct # Unsupported option
-   une=ct "_SUPPORTED" cend     # end unsupported option
-   error=start "ERROR:"         # error message
+   def=start "#define PNG_"     # Arbitrary define
+   sup="_SUPPORTED" end         # end supported option
+   und=comment "#undef PNG_"    # Unsupported option
+   une="_SUPPORTED" cend        # end unsupported option
+   error=start "ERROR:"         # error message, terminate with 'end'
 
    # Variables
    deb=0                        # debug - set on command line
@@ -53,11 +64,15 @@ BEGIN{
    logunsupported=0             # write unsupported options too
 
    # Precreate arrays
+   # for each option:
    option[""] = ""    # list of all options: default enabled/disabled
    done[""] = 1       # marks option as having been output
    requires[""] = ""  # requires by option
    iffs[""] = ""      # if by option
    enabledby[""] = "" # options that enable it by option
+   sets[""] = ""      # settings set by each option
+   setval[""] = ""    # value to set (indexed: 'option sets[option]')
+   # for each setting:
    setting[""] = ""   # requires by setting
    defaults[""] = ""  # used for a defaulted value
    doneset[""] = 1    # marks setting as having been output
@@ -68,7 +83,7 @@ BEGIN{
 }
 
 # The output file must be specified before any input:
-out == "/dev/null" {
+out == "" {
    print "out=output.file must be given on the command line"
    err = 1
    exit 1
@@ -102,7 +117,6 @@ pre && version == "search" && version_file != FILENAME{
 
 pre && version == "search" && $0 ~ /^ \* libpng version/{
    version = substr($0, 4)
-   gsub(/\./, " PNG_JOIN . PNG_JOIN", version)
    print "version =", version >out
    next
 }
@@ -190,7 +204,7 @@ $1 == "com"{
    if (NF > 1) {
       # sub(/^[        ]*com[  ]*/, "")
       $1 = ""
-      print comment, $0, cend >out
+      print comment $0, cend >out
    } else
       print start end >out
    next
@@ -227,7 +241,9 @@ $1 == "file" && NF >= 2{
    next
 }
 
-# option NAME ( (requires|enables|if) NAME* | on | off | disabled )*
+# option NAME ( (requires|enables|if) NAME* | on | off | disabled |
+#                sets SETTING VALUE+ )*
+#     
 #   Declares an option 'NAME' and describes its default setting (disabled)
 #   and its relationship to other options.  The option is disabled
 #   unless *all* the options listed after 'requires' are set and at
@@ -242,46 +258,77 @@ $1 == "file" && NF >= 2{
 #   be later) entry may turn an option on or off explicitly.
 
 $1 == "option" && NF >= 2{
-   onoff = option[$2]  # records current (and the default is "", enabled)
+   opt = $2
+   sub(/,$/,"",opt)
+   onoff = option[opt]  # records current (and the default is "", enabled)
    key = ""
-   for (i=3; i<=NF; ++i) {
-      if ($(i) == "on" || $(i) == "off" || $(i) == "disabled") {
-         key = ""
-         if (onoff != $(i)) {
-            # on or off can zap disabled or enabled:
-            if (onoff == "" || (onoff == "disabled" || onoff == "enabled") && ($(i) == "on" || $(i) == "off")) {
-               # It's easy to mis-spell the option when turning it
-               # on or off, so warn about it here:
-               if (onoff == "" && ($(i) == "on" || $(i) == "off")) {
-                  print $2 ": ERROR: turning unrecognized option", $(i)
-                  # For the moment error out - it is safer
-                  err = 1 # prevent END{} running
-                  exit 1
+   istart = 3
+   do {
+      if (istart == 1) {     # continuation line
+         val = getline
+
+         if (val != 1) { # error reading it
+            if (val == 0)
+               print "option", opt ": ERROR: missing contination line"
+            else
+               print "option", opt ": ERROR: error reading continuation line"
+
+            # This is a hard error
+            err = 1 # prevent END{} running
+            exit 1
+         }
+      }
+
+      for (i=istart; i<=NF; ++i) {
+         val=$(i)
+         sub(/,$/,"",val)
+         if (val == "on" || val == "off" || val == "disabled") {
+            key = ""
+            if (onoff != val) {
+               # on or off can zap disabled or enabled:
+               if (onoff == "" || (onoff == "disabled" || onoff == "enabled") &&
+                   (val == "on" || val == "off")) {
+                  # It's easy to mis-spell the option when turning it
+                  # on or off, so warn about it here:
+                  if (onoff == "" && (val == "on" || val == "off")) {
+                     print "option", opt ": ERROR: turning unrecognized option", val
+                     # For the moment error out - it is safer
+                     err = 1 # prevent END{} running
+                     exit 1
+                  }
+                  onoff = val
+               } else {
+                  # Print a message, otherwise the error
+                  # below is incomprehensible
+                  print "option", opt ": currently", onoff ": attempt to turn", val
+                  break
                }
-               onoff = $(i)
-            } else {
-               # Print a message, otherwise the error
-               # below is incomprehensible
-               print $2 ": currently", onoff ": attempt to turn", $(i)
-               break
             }
-         }
-      } else if ($(i) == "requires" || $(i) == "if" || $(i) == "enables") {
-         key = $(i)
-      } else if (key == "requires") {
-         requires[$2] = requires[$2] " " $(i)
-      } else if (key == "if") {
-         iffs[$2] = iffs[$2] " " $(i)
-      } else if (key == "enables") {
-         enabledby[$(i)] = enabledby[$(i)] " " $2
-      } else
-         break # bad line format
-   }
+         } else if (val == "requires" || val == "if" || val == "enables" || val =="sets") {
+            key = val
+         } else if (key == "requires") {
+            requires[opt] = requires[opt] " " val
+         } else if (key == "if") {
+            iffs[opt] = iffs[opt] " " val
+         } else if (key == "enables") {
+            enabledby[val] = enabledby[val] " " opt
+         } else if (key == "sets") {
+            sets[opt] = sets[opt] " " val
+            key = "setval"
+            set = val
+         } else if (key == "setval") {
+            setval[opt " " set] = setval[opt " " set] " " val
+         } else
+            break # bad line format
+      }
+
+      istart = 1
+   } while (i > NF && $0 ~ /,$/)
 
    if (i > NF) {
       # Set the option, defaulting to 'enabled'
       if (onoff == "") onoff = "enabled"
-      option[$2] = onoff
+      option[opt] = onoff
       next
    }
    # Else fall through to the error handler
@@ -301,41 +348,62 @@ $1 == "option" && NF >= 2{
 pre != 0 && $1 == "chunk" && NF >= 2{
    # 'chunk' is handled on the first pass by writing appropriate
    # 'option' lines into the intermediate file.
+   opt = $2
+   sub(/,$/,"",opt)
    onoff = ""
    reqread = ""
    reqwrite = ""
    enables = ""
-   i = 3 # indicates format error
-   if (NF > 2) {
+   req = 0
+   istart = 3
+   do {
+      if (istart == 1) {     # continuation line
+         val = getline
+
+         if (val != 1) { # error reading it
+            if (val == 0)
+               print "chunk", opt ": ERROR: missing contination line"
+            else
+               print "chunk", opt ": ERROR: error reading continuation line"
+
+            # This is a hard error
+            err = 1 # prevent END{} running
+            exit 1
+         }
+      }
+
       # read the keywords/additional OPTS
-      req = 0
-      for (i=3; i<=NF; ++i) {
-         if ($(i) == "on" || $(i) == "off" || $(i) == "disabled") {
-            if (onoff != $(i)) {
+      for (i=istart; i<=NF; ++i) {
+         val = $(i)
+         sub(/,$/,"",val)
+         if (val == "on" || val == "off" || val == "disabled") {
+            if (onoff != val) {
                if (onoff == "")
-                  onoff = $(i)
+                  onoff = val
                else
                   break # on/off conflict
             }
             req = 0
-         } else if ($(i) == "requires")
+         } else if (val == "requires")
             req = 1
-         else if ($(i) == "enables")
+         else if (val == "enables")
             req = 2
          else if (req == 1){
-            reqread = reqread " READ_" $(i)
-            reqwrite = reqwrite " WRITE_" $(i)
+            reqread = reqread " READ_" val
+            reqwrite = reqwrite " WRITE_" val
          } else if (req == 2)
-            enables = enables " " $(i)
+            enables = enables " " val
          else
             break # bad line: handled below
       }
-   }
+
+      istart = 1
+   } while (i > NF && $0 ~ /,$/)
 
    if (i > NF) {
       # Output new 'option' lines to the intermediate file (out)
-      print "option READ_" $2, "requires READ_ANCILLARY_CHUNKS" reqread, "enables", $2 enables , onoff >out
-      print "option WRITE_" $2, "requires WRITE_ANCILLARY_CHUNKS" reqwrite, "enables", $2 enables, onoff >out
+      print "option READ_" opt, "requires READ_ANCILLARY_CHUNKS" reqread, "enables", opt enables , onoff >out
+      print "option WRITE_" opt, "requires WRITE_ANCILLARY_CHUNKS" reqwrite, "enables", opt enables, onoff >out
       next
    }
    # Else hit the error handler below - bad line format!
@@ -466,72 +534,7 @@ END{
       exit 0
    }
 
-   # Do the 'setting' values first, the algorithm the standard
-   # tree walk (O(1)) done in an O(2) while/for loop; interations
-   # settings x depth, outputing the deepest required macros
-   # first.
-   print "" >out
-   print "/* SETTINGS */" >out
-   print comment, "settings", cend >out
-   finished = 0
-   while (!finished) {
-      finished = 1
-      movement = 0 # done nothing
-      for (i in setting) if (!doneset[i]) {
-         nreqs = split(setting[i], r)
-         if (nreqs > 0) {
-            for (j=1; j<=nreqs; ++j) if (!doneset[r[j]]) {
-               break
-            }
-            if (j<=nreqs) {
-               finished = 0
-               continue # try a different setting
-            }
-         }
-
-         # All the requirements have been processed, output
-         # this setting.
-         if (deb) print "setting", i
-         print "" >out
-         print "/* setting: ", i >out
-         print " *   requires:" setting[i] >out
-         print " *   default: ", defaults[i], "*/" >out
-         if (defaults[i] == "") { # no default, only check if defined
-            print "#ifdef PNG_" i >out
-         }
-         for (j=1; j<=nreqs; ++j) {
-            print "# ifndef PNG_" r[j] >out
-            print error, i, "requires", r[j] end >out
-            print "# endif" >out
-         }
-         if (defaults[i] != "") { # default handling
-            print "#ifdef PNG_" i >out
-         }
-         print def i, "PNG_" i end >out
-         if (defaults[i] != "") {
-            print "#else /*default*/" >out
-            # And add the default definition for the benefit
-            # of later settings an options test:
-            print "# define PNG_" i defaults[i] >out
-            print def i defaults[i] end >out
-         }
-         print "#endif" >out
-
-         doneset[i] = 1
-         ++movement
-      }
-
-      if (!finished && !movement) {
-         print "setting: loop or missing setting in 'requires', cannot process:"
-         for (i in setting) if (!doneset[i]) {
-            print "  setting", i, "requires" setting[i]
-         }
-         exit 1
-      }
-   }
-   print comment, "end of settings", cend >out
-
-   # Now do the options - somewhat more complex.  The dependency
+   # Do the options first (allowing options to set settings).  The dependency
    # tree is thus:
    #
    #   name     >     name
@@ -623,6 +626,9 @@ END{
    }
    if (err) exit 1
 
+   # Sort options:
+   print "PNG_DFN_START_SORT 2" >out
+
    # option[i] is now the complete list of all the tokens we may
    # need to output, go through it as above, depth first.
    finished = 0
@@ -660,8 +666,9 @@ END{
          print "" >out
          print "/* option:", i, option[i] >out
          print " *   requires:  " requires[i] >out
-         print " *   if:      " iffs[i] >out
-         print " *   enabled-by:" enabledby[i], "*/" >out
+         print " *   if:        " iffs[i] >out
+         print " *   enabled-by:" enabledby[i] >out
+         print " *   sets:      " sets[i], "*/" >out
          print "#undef PNG_on" >out
          print "#define PNG_on 1" >out
 
@@ -744,6 +751,21 @@ END{
             print error, i, "is on: enabled by:" iffs[i] enabledby[i] ", requires" requires[i] end >out
          } else if (i !~ /^ok_/) {
             print def i sup >out
+            # Supported option, set required settings
+            nreqs = split(sets[i], r)
+            for (j=1; j<=nreqs; ++j) {
+               print "#    ifdef PNG_set_" r[j] >out
+               # Some other option has already set a value:
+               print error, i, "sets", r[j] ": duplicate setting" end >out
+               print error, "   previous value: " end "PNG_set_" r[j] >out
+               print "#    else" >out
+               # Else set the default: note that this won't accept arbitrary
+               # values, the setval string must be acceptable to all the C
+               # compilers we use.  That means it must be VERY simple; a number,
+               # a name or a string.
+               print "#     define PNG_set_" r[j], setval[i " " r[j]] >out
+               print "#    endif" >out
+            }
          }
          print "#   endif /* definition */" >out
          print "#endif /*requires, if*/" >out
@@ -774,10 +796,98 @@ END{
          exit 1
       }
    }
+   print "PNG_DFN_END_SORT" >out
    print comment, "end of options", cend >out
 
+   # Do the 'setting' values second, the algorithm the standard
+   # tree walk (O(1)) done in an O(2) while/for loop; interations
+   # settings x depth, outputing the deepest required macros
+   # first.
+   print "" >out
+   print "/* SETTINGS */" >out
+   print comment, "settings", cend >out
+   # Sort (in dfn.awk) on field 2, the setting name
+   print "PNG_DFN_START_SORT 2" >out
+   finished = 0
+   while (!finished) {
+      finished = 1
+      movement = 0 # done nothing
+      for (i in setting) if (!doneset[i]) {
+         nreqs = split(setting[i], r)
+         if (nreqs > 0) {
+            # By default assume the requires values are options, but if there
+            # is no option with that name check for a setting
+            for (j=1; j<=nreqs; ++j) if (option[r[j]] == "" && !doneset[r[j]]) {
+               break
+            }
+            if (j<=nreqs) {
+               finished = 0
+               continue # try a different setting
+            }
+         }
+
+         # All the requirements have been processed, output
+         # this setting.
+         if (deb) print "setting", i
+         deflt = defaults[i]
+         # Remove any spurious trailing spaces
+         sub(/ *$/,"",deflt)
+         # A leading @ means leave it unquoted so the preprocessor
+         # can substitute the build time value
+         if (deflt ~ /^ @/)
+            deflt = " " subs substr(deflt, 3) sube
+         print "" >out
+         print "/* setting: ", i >out
+         print " *   requires:" setting[i] >out
+         print " *   default: ", defaults[i] deflt, "*/" >out
+         for (j=1; j<=nreqs; ++j) {
+            if (option[r[j]] != "")
+               print "#ifndef PNG_" r[j] "_SUPPORTED" >out
+            else
+               print "#ifndef PNG_" r[j] >out
+            print error, i, "requires", r[j] end >out
+            print "# endif" >out
+         }
+         # The precedence is:
+         #
+         #  1) External definition; trumps:
+         #  2) Option 'sets' value; trumps:
+         #  3) Setting 'default'
+         #
+         print "#ifdef PNG_" i >out
+         # PNG_<i> is defined, so substitute the value:
+         print def i, subs "PNG_" i sube end >out
+         print "#else /* use default */" >out
+         print "# ifdef PNG_set_" i >out
+         # Value from an option 'sets' argument
+         print def i, subs "PNG_set_" i sube end >out
+         # This is so that subsequent tests on the setting work:
+         print "#  define PNG_" i, "1" >out
+         if (defaults[i] != "") {
+            print "# else /*default*/" >out
+            print def i deflt end >out
+            print "#  define PNG_" i, "1" >out
+         }
+         print "# endif /* defaults */" >out
+         print "#endif /* setting", i, "*/" >out
+
+         doneset[i] = 1
+         ++movement
+      }
+
+      if (!finished && !movement) {
+         print "setting: loop or missing setting in 'requires', cannot process:"
+         for (i in setting) if (!doneset[i]) {
+            print "  setting", i, "requires" setting[i]
+         }
+         exit 1
+      }
+   }
+   print "PNG_DFN_END_SORT" >out
+   print comment, "end of settings", cend >out
+
    # Regular end - everything looks ok
    if (protect != "") {
-      print start "#endif", cx, protect, "*/" end >out
+      print start "#endif", "/*", protect, "*/" end >out
    }
 }
index 60f6e2bb33662682ac746cac9be667865d0f2c4f..c95b10255a88f97882aaea34cd28534d5068efca 100644 (file)
@@ -27,7 +27,7 @@ file pnglibconf.h scripts/pnglibconf.dfa PNGLCONF_H
 # The syntax is detailed in scripts/options.awk; this is a summary
 # only:
 #
-# setting <name> [default]
+# setting <name> [requires ...] [default]
 #    #define PNG_<name> <value>  /* value comes from current setting */
 # option <name> [requires ...] [if ...] [enables ...] [disabled]
 #    #define PNG_<name>_SUPPORTED if the requirements are met and
@@ -39,6 +39,11 @@ file pnglibconf.h scripts/pnglibconf.dfa PNGLCONF_H
 #    used as given (e.g. enables GAMMA just expands to that on the
 #    correspond READ_name and WRITE_name lines.)
 #
+# "," may be used to separate options on an 'option' line and is ignored; it
+# doesn't change the meaning of the line.  (NOT setting, where "," becomes
+# part of the setting!)  A comma at the end of an option line causes a
+# continuation (the next line is included in the option too.)
+#
 # Note that the 'on' and 'off' keywords, while valid on both option
 # and chunk, should not be used in this file because they force the
 # relevant options on or off.
@@ -131,6 +136,12 @@ logunsupported = 1
 # - PNG_USER_VERSIONINFO_COMPANYNAME
 # - PNG_USER_VERSIONINFO_LEGALTRADEMARKS
 
+# It is necessary to include configures definitions here so that AC_DEFINE
+# in configure.ac works in a comprehensible way
+@#if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H)
+@#  include "config.h"
+@#endif
+
 @#ifdef PNG_USER_CONFIG
 @#  include "pngusr.h"
 @#endif
@@ -147,6 +158,12 @@ logunsupported = 1
 @#  endif
 @#endif
 
+# This changes the default for the ARM NEON optimizations according to
+# __ARM_NEON__
+@#ifdef __ARM_NEON__
+@#  define PNG_ARM_NEON_SUPPORTED
+@#endif
+
 # IN DEVELOPMENT
 # These are currently experimental features; define them if you want (NOTE:
 # experimental options must be disabled before they are defined in this file!)
@@ -182,6 +199,29 @@ setting PREFIX
 
 setting DEFAULT_READ_MACROS default 1
 
+# This setting allows a hardware or configuration specific filter optimization
+# function to be specified, the argument is the name of the filter initializaion
+# function to use.
+
+setting FILTER_OPTIMIZATIONS
+
+# Implementation specific control of the optimizations, enabled by those
+# hardware or software options that need it (typically when run-time choices
+# must be made by the user)
+option SET_OPTION disabled
+
+# These options are specific to the ARM NEON hardware optimizations:
+#
+# ARM_NEON: the optimization itself
+# ARM_NEON_API: allow the optimization to be switched on with png_set_hardware
+# ARM_NEON_CHECK: compile a run-time check to see if Neon extensions are
+#                 supported, this is poorly supported and deprectated - use the
+#                 png_set_hardware API.
+option ARM_NEON disabled,
+   sets FILTER_OPTIMIZATIONS png_init_filter_functions_neon
+option ARM_NEON_API disabled enables SET_OPTION ARM_NEON
+option ARM_NEON_CHECK disabled enables ARM_NEON
+
 # These settings configure the default compression level (0-9) and 'strategy';
 # strategy is as defined by the implementors of zlib, it describes the input
 # data and modifies the zlib parameters in an attempt to optimize the balance
@@ -190,13 +230,17 @@ setting DEFAULT_READ_MACROS default 1
 # because the name of the setting is prefixed by PNG_
 #
 # The TEXT values are the defaults when writing compressed text (all forms)
+#
+# Include the zlib header too, so that the defaults below are known
+@#  include <zlib.h>
 
-setting Z_DEFAULT_COMPRESSION default Z_DEFAULT_COMPRESSION
-setting Z_DEFAULT_STRATEGY default Z_FILTERED
-setting Z_DEFAULT_NOFILTER_STRATEGY default Z_DEFAULT_STRATEGY
+# The '@' here means to substitute the value when pnglibconf.h is built
+setting Z_DEFAULT_COMPRESSION default @Z_DEFAULT_COMPRESSION
+setting Z_DEFAULT_STRATEGY default @Z_FILTERED
+setting Z_DEFAULT_NOFILTER_STRATEGY default @Z_DEFAULT_STRATEGY
 
-setting TEXT_Z_DEFAULT_COMPRESSION default Z_DEFAULT_COMPRESSION
-setting TEXT_Z_DEFAULT_STRATEGY default Z_DEFAULT_STRATEGY
+setting TEXT_Z_DEFAULT_COMPRESSION default @Z_DEFAULT_COMPRESSION
+setting TEXT_Z_DEFAULT_STRATEGY default @Z_DEFAULT_STRATEGY
 
 # The alternative is to call functions to read PNG values, if
 # the functions are turned *off* the read macros must always
@@ -386,12 +430,12 @@ option READ_TRANSFORMS requires READ
 # If you handle gamma issues outside libpng then you do not need the libpng
 # gamma processing; and it is an enormous waste of space.  You just need to
 # remove the use of libpng APIs that depend on it.
-option READ_GAMMA requires READ_TRANSFORMS READ_gAMA
+option READ_GAMMA requires READ_TRANSFORMS, READ_gAMA
 
-option READ_ALPHA_MODE requires READ_TRANSFORMS READ_GAMMA
-option READ_BACKGROUND requires READ_TRANSFORMS READ_STRIP_ALPHA READ_GAMMA
+option READ_ALPHA_MODE requires READ_TRANSFORMS, READ_GAMMA
+option READ_BACKGROUND requires READ_TRANSFORMS, READ_STRIP_ALPHA, READ_GAMMA
 option READ_BGR requires READ_TRANSFORMS
-option READ_EXPAND_16 requires READ_TRANSFORMS READ_16BIT READ_EXPAND
+option READ_EXPAND_16 requires READ_TRANSFORMS, READ_16BIT, READ_EXPAND
 option READ_EXPAND requires READ_TRANSFORMS
 option READ_FILLER requires READ_TRANSFORMS
 option READ_GRAY_TO_RGB requires READ_TRANSFORMS
@@ -399,13 +443,13 @@ option READ_INVERT_ALPHA requires READ_TRANSFORMS
 option READ_INVERT requires READ_TRANSFORMS
 option READ_PACK requires READ_TRANSFORMS
 option READ_PACKSWAP requires READ_TRANSFORMS
-option READ_RGB_TO_GRAY requires READ_TRANSFORMS READ_GAMMA
+option READ_RGB_TO_GRAY requires READ_TRANSFORMS, READ_GAMMA
 option READ_SCALE_16_TO_8 requires READ_TRANSFORMS
 option READ_SHIFT requires READ_TRANSFORMS
 option READ_STRIP_16_TO_8 requires READ_TRANSFORMS
 option READ_STRIP_ALPHA requires READ_TRANSFORMS
 option READ_SWAP_ALPHA requires READ_TRANSFORMS
-option READ_SWAP requires READ_TRANSFORMS READ_16BIT
+option READ_SWAP requires READ_TRANSFORMS, READ_16BIT
 option READ_USER_TRANSFORM requires READ_TRANSFORMS
 
 option PROGRESSIVE_READ requires READ
@@ -444,7 +488,7 @@ option WRITE_TRANSFORMS requires WRITE
 option WRITE_SHIFT requires WRITE_TRANSFORMS
 option WRITE_PACK requires WRITE_TRANSFORMS
 option WRITE_BGR requires WRITE_TRANSFORMS
-option WRITE_SWAP requires WRITE_TRANSFORMS WRITE_16BIT
+option WRITE_SWAP requires WRITE_TRANSFORMS, WRITE_16BIT
 option WRITE_PACKSWAP requires WRITE_TRANSFORMS
 option WRITE_INVERT requires WRITE_TRANSFORMS
 option WRITE_FILLER requires WRITE_TRANSFORMS
@@ -466,8 +510,8 @@ option WRITE_FLUSH requires WRITE
 
 # Note: these can be turned off explicitly if not required by the
 # apps implementing the user transforms
-option USER_TRANSFORM_PTR if READ_USER_TRANSFORM WRITE_USER_TRANSFORM
-option USER_TRANSFORM_INFO if READ_USER_TRANSFORM WRITE_USER_TRANSFORM
+option USER_TRANSFORM_PTR if READ_USER_TRANSFORM, WRITE_USER_TRANSFORM
+option USER_TRANSFORM_INFO if READ_USER_TRANSFORM, WRITE_USER_TRANSFORM
 
 # This enables API to set compression parameters for compressing
 # non-IDAT chunks (zTXt, iTXt, iCCP, and unknown chunks).  This feature
@@ -568,7 +612,7 @@ setting sRGB_PROFILE_CHECKS default 2
 # but can help (in theory) on some architectures.  Only affects
 # internal structures.  Added at libpng 1.4.0
 
-option ALIGN_MEMORY
+option ALIGNED_MEMORY
 
 # Buggy compilers (e.g., gcc 2.7.2.2) need PNG_NO_POINTER_INDEXING
 # See png[wr]util.c, normally this should always be *on*
@@ -660,7 +704,7 @@ chunk bKGD
 chunk cHRM enables COLORSPACE
 chunk gAMA enables GAMMA
 chunk hIST
-chunk iCCP enables COLORSPACE GAMMA
+chunk iCCP enables COLORSPACE, GAMMA
 chunk iTXt
 chunk oFFs
 chunk pCAL
@@ -668,7 +712,7 @@ chunk pHYs
 chunk sBIT
 chunk sCAL
 chunk sPLT
-chunk sRGB enables COLORSPACE GAMMA
+chunk sRGB enables COLORSPACE, GAMMA
 chunk tEXt requires TEXT
 chunk tIME
 chunk tRNS
@@ -698,7 +742,7 @@ option WRITE_UNKNOWN_CHUNKS enables STORE_UNKNOWN_CHUNKS
 # to png_get_unknown_chunks, the application must call
 # png_set_keep_unknown_chunks to cause this to actually happen (see png.h)
 option SAVE_UNKNOWN_CHUNKS requires READ requires SET_UNKNOWN_CHUNKS
-option SAVE_UNKNOWN_CHUNKS enables READ_UNKNOWN_CHUNKS STORE_UNKNOWN_CHUNKS
+option SAVE_UNKNOWN_CHUNKS enables READ_UNKNOWN_CHUNKS, STORE_UNKNOWN_CHUNKS
 
 # The second approach is to use an application provided callback to process the
 # chunks, the callback can either handle the chunk entirely itself or request
@@ -706,8 +750,8 @@ option SAVE_UNKNOWN_CHUNKS enables READ_UNKNOWN_CHUNKS STORE_UNKNOWN_CHUNKS
 #
 # Note that there is no 'WRITE_USER_CHUNKS' so the USER_CHUNKS option is always
 # the same as READ_USER_CHUNKS at present
-option READ_USER_CHUNKS requires READ requires UNKNOWN_CHUNKS
-option READ_USER_CHUNKS enables READ_UNKNOWN_CHUNKS USER_CHUNKS
+option READ_USER_CHUNKS requires READ, UNKNOWN_CHUNKS
+option READ_USER_CHUNKS enables READ_UNKNOWN_CHUNKS, USER_CHUNKS
 
 # Two further options are provided to allow detailed control of the handling.
 # The first enables png_set_keep_unknown_chunks; this allows the default to be
@@ -774,8 +818,8 @@ option INFO_IMAGE
 
 option CHECK_FOR_INVALID_INDEX enables READ_CHECK_FOR_INVALID_INDEX
 option CHECK_FOR_INVALID_INDEX enables WRITE_CHECK_FOR_INVALID_INDEX
-option READ_CHECK_FOR_INVALID_INDEX requires READ CHECK_FOR_INVALID_INDEX
-option WRITE_CHECK_FOR_INVALID_INDEX requires WRITE CHECK_FOR_INVALID_INDEX
+option READ_CHECK_FOR_INVALID_INDEX requires READ, CHECK_FOR_INVALID_INDEX
+option WRITE_CHECK_FOR_INVALID_INDEX requires WRITE, CHECK_FOR_INVALID_INDEX
 
 # added at libpng-1.5.15
 option GET_PALETTE_MAX enables READ_GET_PALETTE_MAX WRITE_GET_PALETTE_MAX
@@ -784,12 +828,11 @@ option WRITE_GET_PALETTE_MAX requires WRITE_CHECK_FOR_INVALID_INDEX disabled
 
 # Simplified API options (added at libpng-1.6.0)
 # Read:
-option SIMPLIFIED_READ requires SEQUENTIAL_READ READ_TRANSFORMS SETJMP
-option SIMPLIFIED_READ requires BENIGN_ERRORS READ_GAMMA
-option SIMPLIFIED_READ enables READ_EXPAND READ_16BIT READ_EXPAND_16
-option SIMPLIFIED_READ enables READ_SCALE_16_TO_8 READ_RGB_TO_GRAY
-option SIMPLIFIED_READ enables READ_ALPHA_MODE READ_BACKGROUND READ_STRIP_ALPHA
-option SIMPLIFIED_READ enables READ_FILLER READ_SWAP
+option SIMPLIFIED_READ,
+   requires SEQUENTIAL_READ READ_TRANSFORMS, SETJMP, BENIGN_ERRORS READ_GAMMA,
+   enables READ_EXPAND, READ_16BIT READ_EXPAND_16, READ_SCALE_16_TO_8,
+      READ_RGB_TO_GRAY, READ_ALPHA_MODE READ_BACKGROUND READ_STRIP_ALPHA,
+      READ_FILLER, READ_SWAP
 
 option SIMPLIFIED_READ_AFIRST requires SIMPLIFIED_READ disabled
 option READ_SWAP_ALPHA enables SIMPLIFIED_READ_AFIRST
@@ -798,8 +841,9 @@ option SIMPLIFIED_READ_BGR requires SIMPLIFIED_READ disabled
 option READ_BGR enables SIMPLIFIED_READ_BGR
 
 # Write:
-option SIMPLIFIED_WRITE requires WRITE STDIO SETJMP
-option SIMPLIFIED_WRITE enables WRITE_SWAP WRITE_gAMA WRITE_sRGB WRITE_cHRM
+option SIMPLIFIED_WRITE,
+   requires WRITE STDIO, SETJMP,
+   enables WRITE_SWAP WRITE_gAMA, WRITE_sRGB WRITE_cHRM
 
 option SIMPLIFIED_WRITE_AFIRST requires SIMPLIFIED_WRITE disabled
 option WRITE_SWAP_ALPHA enables SIMPLIFIED_WRITE_AFIRST
@@ -808,5 +852,5 @@ option SIMPLIFIED_WRITE_BGR requires SIMPLIFIED_WRITE disabled
 option WRITE_BGR enables SIMPLIFIED_WRITE_BGR
 
 # Formats:
-option FORMAT_AFIRST if SIMPLIFIED_READ_AFIRST SIMPLIFIED_WRITE_AFIRST
-option FORMAT_BGR if SIMPLIFIED_READ_BGR SIMPLIFIED_WRITE_BGR
+option FORMAT_AFIRST if SIMPLIFIED_READ_AFIRST, SIMPLIFIED_WRITE_AFIRST
+option FORMAT_BGR if SIMPLIFIED_READ_BGR, SIMPLIFIED_WRITE_BGR
index b31827956459a2191d491d2bc5546a3d13def8bc..1894e2daebc470f314bb5f9a5cab2f4e164a2582 100644 (file)
@@ -1,9 +1,8 @@
-
-/* libpng STANDARD API DEFINITION */
+/* libpng 1.6.1 STANDARD API DEFINITION */
 
 /* pnglibconf.h - library build configuration */
 
-/* Libpng 1.6.0 - February 14, 2013 */
+/* Libpng version 1.6.1 - March 28, 2013 */
 
 /* Copyright (c) 1998-2013 Glenn Randers-Pehrson */
 
 /* and license in png.h */
 
 /* pnglibconf.h */
+/* Machine generated file: DO NOT EDIT */
 /* Derived from: scripts/pnglibconf.dfa */
-/* If you edit this file by hand you must obey the rules expressed in */
-/* pnglibconf.dfa with respect to the dependencies between the following */
-/* symbols.  It is much better to generate a new file using */
-/* scripts/libpngconf.mak */
-
 #ifndef PNGLCONF_H
 #define PNGLCONF_H
-/* settings */
-#define PNG_API_RULE 0
-#define PNG_CALLOC_SUPPORTED
-#define PNG_COST_SHIFT 3
-#define PNG_DEFAULT_READ_MACROS 1
-#define PNG_GAMMA_THRESHOLD_FIXED 5000
-#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE
-#define PNG_INFLATE_BUF_SIZE 1024
-#define PNG_MAX_GAMMA_8 11
-#define PNG_QUANTIZE_BLUE_BITS 5
-#define PNG_QUANTIZE_GREEN_BITS 5
-#define PNG_QUANTIZE_RED_BITS 5
-#define PNG_sCAL_PRECISION 5
-#define PNG_sRGB_PROFILE_CHECKS 2
-#define PNG_TEXT_Z_DEFAULT_COMPRESSION Z_DEFAULT_COMPRESSION
-#define PNG_TEXT_Z_DEFAULT_STRATEGY Z_DEFAULT_STRATEGY
-#define PNG_WEIGHT_SHIFT 8
-#define PNG_ZBUF_SIZE 8192
-#define PNG_Z_DEFAULT_COMPRESSION Z_DEFAULT_COMPRESSION
-#define PNG_Z_DEFAULT_NOFILTER_STRATEGY Z_DEFAULT_STRATEGY
-#define PNG_Z_DEFAULT_STRATEGY Z_FILTERED
-/* end of settings */
 /* options */
 #define PNG_16BIT_SUPPORTED
-#define PNG_ALIGN_MEMORY_SUPPORTED
+#define PNG_ALIGNED_MEMORY_SUPPORTED
+/*#undef PNG_ARM_NEON_API_SUPPORTED*/
+/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/
+/*#undef PNG_ARM_NEON_SUPPORTED*/
 #define PNG_BENIGN_ERRORS_SUPPORTED
 #define PNG_BENIGN_READ_ERRORS_SUPPORTED
 /*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/
-#define PNG_bKGD_SUPPORTED
 #define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
 #define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
-#define PNG_cHRM_SUPPORTED
 #define PNG_COLORSPACE_SUPPORTED
 #define PNG_CONSOLE_IO_SUPPORTED
 #define PNG_CONVERT_tIME_SUPPORTED
 #define PNG_FLOATING_POINT_SUPPORTED
 #define PNG_FORMAT_AFIRST_SUPPORTED
 #define PNG_FORMAT_BGR_SUPPORTED
-#define PNG_gAMA_SUPPORTED
 #define PNG_GAMMA_SUPPORTED
 #define PNG_GET_PALETTE_MAX_SUPPORTED
 #define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-#define PNG_hIST_SUPPORTED
-#define PNG_iCCP_SUPPORTED
 #define PNG_INCH_CONVERSIONS_SUPPORTED
 #define PNG_INFO_IMAGE_SUPPORTED
 #define PNG_IO_STATE_SUPPORTED
-#define PNG_iTXt_SUPPORTED
 #define PNG_MNG_FEATURES_SUPPORTED
-#define PNG_oFFs_SUPPORTED
-#define PNG_pCAL_SUPPORTED
-#define PNG_pHYs_SUPPORTED
 #define PNG_POINTER_INDEXING_SUPPORTED
 #define PNG_PROGRESSIVE_READ_SUPPORTED
 #define PNG_READ_16BIT_SUPPORTED
 #define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED
 #define PNG_READ_BACKGROUND_SUPPORTED
 #define PNG_READ_BGR_SUPPORTED
-#define PNG_READ_bKGD_SUPPORTED
 #define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
-#define PNG_READ_cHRM_SUPPORTED
 #define PNG_READ_COMPOSITE_NODIV_SUPPORTED
 #define PNG_READ_COMPRESSED_TEXT_SUPPORTED
 #define PNG_READ_EXPAND_16_SUPPORTED
 #define PNG_READ_EXPAND_SUPPORTED
 #define PNG_READ_FILLER_SUPPORTED
-#define PNG_READ_gAMA_SUPPORTED
 #define PNG_READ_GAMMA_SUPPORTED
 #define PNG_READ_GET_PALETTE_MAX_SUPPORTED
 #define PNG_READ_GRAY_TO_RGB_SUPPORTED
-#define PNG_READ_hIST_SUPPORTED
-#define PNG_READ_iCCP_SUPPORTED
 #define PNG_READ_INTERLACING_SUPPORTED
 #define PNG_READ_INT_FUNCTIONS_SUPPORTED
 #define PNG_READ_INVERT_ALPHA_SUPPORTED
 #define PNG_READ_INVERT_SUPPORTED
-#define PNG_READ_iTXt_SUPPORTED
-#define PNG_READ_oFFs_SUPPORTED
 #define PNG_READ_OPT_PLTE_SUPPORTED
-#define PNG_READ_PACK_SUPPORTED
 #define PNG_READ_PACKSWAP_SUPPORTED
-#define PNG_READ_pCAL_SUPPORTED
-#define PNG_READ_pHYs_SUPPORTED
+#define PNG_READ_PACK_SUPPORTED
 #define PNG_READ_QUANTIZE_SUPPORTED
 #define PNG_READ_RGB_TO_GRAY_SUPPORTED
-#define PNG_READ_sBIT_SUPPORTED
 #define PNG_READ_SCALE_16_TO_8_SUPPORTED
-#define PNG_READ_sCAL_SUPPORTED
 #define PNG_READ_SHIFT_SUPPORTED
-#define PNG_READ_sPLT_SUPPORTED
-#define PNG_READ_sRGB_SUPPORTED
 #define PNG_READ_STRIP_16_TO_8_SUPPORTED
 #define PNG_READ_STRIP_ALPHA_SUPPORTED
 #define PNG_READ_SUPPORTED
 #define PNG_READ_SWAP_ALPHA_SUPPORTED
 #define PNG_READ_SWAP_SUPPORTED
-#define PNG_READ_tEXt_SUPPORTED
 #define PNG_READ_TEXT_SUPPORTED
-#define PNG_READ_tIME_SUPPORTED
 #define PNG_READ_TRANSFORMS_SUPPORTED
-#define PNG_READ_tRNS_SUPPORTED
 #define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
 #define PNG_READ_USER_CHUNKS_SUPPORTED
 #define PNG_READ_USER_TRANSFORM_SUPPORTED
+#define PNG_READ_bKGD_SUPPORTED
+#define PNG_READ_cHRM_SUPPORTED
+#define PNG_READ_gAMA_SUPPORTED
+#define PNG_READ_hIST_SUPPORTED
+#define PNG_READ_iCCP_SUPPORTED
+#define PNG_READ_iTXt_SUPPORTED
+#define PNG_READ_oFFs_SUPPORTED
+#define PNG_READ_pCAL_SUPPORTED
+#define PNG_READ_pHYs_SUPPORTED
+#define PNG_READ_sBIT_SUPPORTED
+#define PNG_READ_sCAL_SUPPORTED
+#define PNG_READ_sPLT_SUPPORTED
+#define PNG_READ_sRGB_SUPPORTED
+#define PNG_READ_tEXt_SUPPORTED
+#define PNG_READ_tIME_SUPPORTED
+#define PNG_READ_tRNS_SUPPORTED
 #define PNG_READ_zTXt_SUPPORTED
 /*#undef PNG_SAFE_LIMITS_SUPPORTED*/
 #define PNG_SAVE_INT_32_SUPPORTED
 #define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
-#define PNG_sBIT_SUPPORTED
-#define PNG_sCAL_SUPPORTED
 #define PNG_SEQUENTIAL_READ_SUPPORTED
+#define PNG_SETJMP_SUPPORTED
 #define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED
 #define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
-#define PNG_SETJMP_SUPPORTED
+/*#undef PNG_SET_OPTION_SUPPORTED*/
 #define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
 #define PNG_SET_USER_LIMITS_SUPPORTED
 #define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED
 #define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
 #define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
 #define PNG_SIMPLIFIED_WRITE_SUPPORTED
-#define PNG_sPLT_SUPPORTED
-#define PNG_sRGB_SUPPORTED
 #define PNG_STDIO_SUPPORTED
 #define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
-#define PNG_tEXt_SUPPORTED
 #define PNG_TEXT_SUPPORTED
 #define PNG_TIME_RFC1123_SUPPORTED
-#define PNG_tIME_SUPPORTED
-#define PNG_tRNS_SUPPORTED
 #define PNG_UNKNOWN_CHUNKS_SUPPORTED
 #define PNG_USER_CHUNKS_SUPPORTED
 #define PNG_USER_LIMITS_SUPPORTED
 #define PNG_WRITE_16BIT_SUPPORTED
 #define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED
 #define PNG_WRITE_BGR_SUPPORTED
-#define PNG_WRITE_bKGD_SUPPORTED
 #define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
-#define PNG_WRITE_cHRM_SUPPORTED
 #define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
 #define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
 #define PNG_WRITE_FILLER_SUPPORTED
 #define PNG_WRITE_FILTER_SUPPORTED
 #define PNG_WRITE_FLUSH_SUPPORTED
-#define PNG_WRITE_gAMA_SUPPORTED
 #define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED
-#define PNG_WRITE_hIST_SUPPORTED
-#define PNG_WRITE_iCCP_SUPPORTED
 #define PNG_WRITE_INTERLACING_SUPPORTED
 #define PNG_WRITE_INT_FUNCTIONS_SUPPORTED
 #define PNG_WRITE_INVERT_ALPHA_SUPPORTED
 #define PNG_WRITE_INVERT_SUPPORTED
-#define PNG_WRITE_iTXt_SUPPORTED
-#define PNG_WRITE_oFFs_SUPPORTED
 #define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
-#define PNG_WRITE_PACK_SUPPORTED
 #define PNG_WRITE_PACKSWAP_SUPPORTED
-#define PNG_WRITE_pCAL_SUPPORTED
-#define PNG_WRITE_pHYs_SUPPORTED
-#define PNG_WRITE_sBIT_SUPPORTED
-#define PNG_WRITE_sCAL_SUPPORTED
+#define PNG_WRITE_PACK_SUPPORTED
 #define PNG_WRITE_SHIFT_SUPPORTED
-#define PNG_WRITE_sPLT_SUPPORTED
-#define PNG_WRITE_sRGB_SUPPORTED
 #define PNG_WRITE_SUPPORTED
 #define PNG_WRITE_SWAP_ALPHA_SUPPORTED
 #define PNG_WRITE_SWAP_SUPPORTED
-#define PNG_WRITE_tEXt_SUPPORTED
 #define PNG_WRITE_TEXT_SUPPORTED
-#define PNG_WRITE_tIME_SUPPORTED
 #define PNG_WRITE_TRANSFORMS_SUPPORTED
-#define PNG_WRITE_tRNS_SUPPORTED
 #define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
 #define PNG_WRITE_USER_TRANSFORM_SUPPORTED
 #define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+#define PNG_WRITE_bKGD_SUPPORTED
+#define PNG_WRITE_cHRM_SUPPORTED
+#define PNG_WRITE_gAMA_SUPPORTED
+#define PNG_WRITE_hIST_SUPPORTED
+#define PNG_WRITE_iCCP_SUPPORTED
+#define PNG_WRITE_iTXt_SUPPORTED
+#define PNG_WRITE_oFFs_SUPPORTED
+#define PNG_WRITE_pCAL_SUPPORTED
+#define PNG_WRITE_pHYs_SUPPORTED
+#define PNG_WRITE_sBIT_SUPPORTED
+#define PNG_WRITE_sCAL_SUPPORTED
+#define PNG_WRITE_sPLT_SUPPORTED
+#define PNG_WRITE_sRGB_SUPPORTED
+#define PNG_WRITE_tEXt_SUPPORTED
+#define PNG_WRITE_tIME_SUPPORTED
+#define PNG_WRITE_tRNS_SUPPORTED
 #define PNG_WRITE_zTXt_SUPPORTED
+#define PNG_bKGD_SUPPORTED
+#define PNG_cHRM_SUPPORTED
+#define PNG_gAMA_SUPPORTED
+#define PNG_hIST_SUPPORTED
+#define PNG_iCCP_SUPPORTED
+#define PNG_iTXt_SUPPORTED
+#define PNG_oFFs_SUPPORTED
+#define PNG_pCAL_SUPPORTED
+#define PNG_pHYs_SUPPORTED
+#define PNG_sBIT_SUPPORTED
+#define PNG_sCAL_SUPPORTED
+#define PNG_sPLT_SUPPORTED
+#define PNG_sRGB_SUPPORTED
+#define PNG_tEXt_SUPPORTED
+#define PNG_tIME_SUPPORTED
+#define PNG_tRNS_SUPPORTED
 #define PNG_zTXt_SUPPORTED
 /* end of options */
+/* settings */
+#define PNG_API_RULE 0
+#define PNG_CALLOC_SUPPORTED
+#define PNG_COST_SHIFT 3
+#define PNG_DEFAULT_READ_MACROS 1
+#define PNG_GAMMA_THRESHOLD_FIXED 5000
+#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE
+#define PNG_INFLATE_BUF_SIZE 1024
+#define PNG_MAX_GAMMA_8 11
+#define PNG_QUANTIZE_BLUE_BITS 5
+#define PNG_QUANTIZE_GREEN_BITS 5
+#define PNG_QUANTIZE_RED_BITS 5
+#define PNG_TEXT_Z_DEFAULT_COMPRESSION (-1)
+#define PNG_TEXT_Z_DEFAULT_STRATEGY 0
+#define PNG_WEIGHT_SHIFT 8
+#define PNG_ZBUF_SIZE 8192
+#define PNG_Z_DEFAULT_COMPRESSION (-1)
+#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0
+#define PNG_Z_DEFAULT_STRATEGY 1
+#define PNG_sCAL_PRECISION 5
+#define PNG_sRGB_PROFILE_CHECKS 2
+/* end of settings */
 #endif /* PNGLCONF_H */
index c799fb790b0888254a751c4048752bb9be192e84..c7117ddc48f7e99e9dc8052e5cd39ce23fc24e53 100755 (executable)
@@ -3,7 +3,7 @@
 #
 # These lines are copied from Makefile.am, they illustrate
 # how to automate the build of pnglibconf.h from scripts/pnglibconf.dfa
-# given 'awk' and 'sed'
+# given just 'awk', a C preprocessor and standard command line utilities
 
 # Override as appropriate, these definitions can be overridden on
 # the make command line (AWK='nawk' for example).
@@ -12,10 +12,9 @@ AWK = mawk
 AWK = nawk
 AWK = one-true-awk
 AWK = awk  # Crashes on SunOS 5.10 - use 'nawk'
-CPP = $(CC) -E # Does not work on SUN OS 5.10 - use /lib/cpp
-SED = sed
+CPP = $(CC) -E # On SUN OS 5.10 if this causes problems use /lib/cpp
 
-COPY = cp
+MOVE = mv
 DELETE = rm -f
 ECHO = echo
 DFA_XTRA = # Put your configuration file here, see scripts/pnglibconf.dfa.  Eg:
@@ -32,28 +31,24 @@ srcdir = .
 # The standard pnglibconf.h exists as scripts/pnglibconf.h.prebuilt,
 # copy this if the following doesn't work.
 pnglibconf.h: pnglibconf.dfn
-       $(DELETE) $@ dfn.c dfn1.out dfn2.out dfn3.out
-       $(ECHO) '#include "pnglibconf.dfn"' >dfn.c
-       $(CPP) $(DFNFLAGS) dfn.c >dfn1.out
-       $(ECHO) "If 'cpp -e' crashes try /lib/cpp (e.g. CPP='/lib/cpp')" >&2
-       $(SED) -n -e 's|^.*PNG_DEFN_MAGIC *-\(.*\)- *PNG_DEFN_END.*$$|\1|p'\
-           dfn1.out >dfn2.out
-       $(SED) -e 's| *PNG_JOIN *||g' -e 's| *$$||' dfn2.out >dfn3.out
-       $(COPY) dfn3.out $@
-       $(DELETE) dfn.c dfn1.out dfn2.out dfn3.out
-
-pnglibconf.dfn: $(srcdir)/scripts/pnglibconf.dfa $(srcdir)/scripts/options.awk $(srcdir)/pngconf.h $(srcdir)/pngusr.dfa
-       $(DELETE) $@ dfn1.out dfn2.out
+       $(DELETE) $@ pnglibconf.c pnglibconf.out pnglibconf.tmp
+       $(ECHO) '#include "pnglibconf.dfn"' >pnglibconf.c
+       $(ECHO) "If '$(CC) -E' crashes try /lib/cpp (e.g. CPP='/lib/cpp')" >&2
+       $(CPP) $(DFNFLAGS) pnglibconf.c >pnglibconf.out
+       $(AWK) -f "$(srcdir)/scripts/dfn.awk" out="pnglibconf.tmp" pnglibconf.out 1>&2
+       $(MOVE) pnglibconf.tmp $@
+
+pnglibconf.dfn: $(srcdir)/scripts/pnglibconf.dfa $(srcdir)/scripts/options.awk $(srcdir)/pngconf.h $(srcdir)/pngusr.dfa $(DFA_XTRA)
+       $(DELETE) $@ pnglibconf.pre pnglibconf.tmp
        $(ECHO) "Calling $(AWK) from scripts/pnglibconf.mak" >&2
        $(ECHO) "If 'awk' crashes try a better awk (e.g. AWK='nawk')" >&2
-       $(AWK) -f $(srcdir)/scripts/options.awk out=dfn1.out version=search\
-               $(srcdir)/pngconf.h $(srcdir)/scripts/pnglibconf.dfa\
-               $(srcdir)/pngusr.dfa $(DFA_XTRA) 1>&2
-       $(AWK) -f $(srcdir)/scripts/options.awk out=dfn2.out dfn1.out 1>&2
-       $(COPY) dfn2.out $@
-       $(DELETE) dfn1.out dfn2.out
+       $(AWK) -f $(srcdir)/scripts/options.awk out="pnglibconf.pre"\
+           version=search $(srcdir)/pngconf.h $(srcdir)/scripts/pnglibconf.dfa\
+           $(srcdir)/pngusr.dfa $(DFA_XTRA) 1>&2
+       $(AWK) -f $(srcdir)/scripts/options.awk out="pnglibconf.tmp" pnglibconf.pre 1>&2
+       $(MOVE) pnglibconf.tmp $@
 
 clean-pnglibconf:
-       $(DELETE) pnglibconf.h pnglibconf.dfn dfn.c dfn1.out dfn2.out dfn3.out
+       $(DELETE) pnglibconf.*
 
 clean: clean-pnglibconf
index 1e8561fd32db05ed6d0e97ce094dac71d18a40cb..0997310c56a11b4525dce5479b861dab2f904e52 100644 (file)
  */
 
 #define PNG_EXPORTA(ordinal, type, name, args, attributes)\
-       PNG_DEFN_MAGIC-name-PNG_DEFN_END
+        PNG_DFN "@" name "@"
 
 /* The configuration information *before* the additional of symbol renames,
  * the list is the C name list; no symbol prefix.
  */
 #include "pnglibconf.out"
 
+PNG_DFN_START_SORT 1
+
 #include "../png.h"
+
+PNG_DFN_END_SORT
index f4f13df08314101f30bffd78b1b510a99c6b2ac4..9ccd810fdec52f15f0ba90cf07a1d7e6c92d8011 100644 (file)
@@ -10,6 +10,6 @@
  */
 
 #define PNG_EXPORTA(ordinal, type, name, args, attributes)\
-       PNG_DEFN_MAGIC-SYMBOL_PREFIX PNG_JOIN name-PNG_DEFN_END
+        PNG_DFN "@" SYMBOL_PREFIX "@@" name "@"
 
 #include "../png.h"
index 1e150df5a3cc52f3523c63355919ab8aeb76371e..d19022c7c9cedeaa7007ff0d5b39e097457ddaf0 100644 (file)
@@ -1,3 +1,4 @@
+;Version 1.6.1
 ;--------------------------------------------------------------
 ; LIBPNG symbol list as a Win32 DEF file
 ; Contains all the symbols that can be exported from libpng
@@ -5,7 +6,6 @@
 LIBRARY
 
 EXPORTS
-;Version 1.6.0
  png_access_version_number @1
  png_set_sig_bytes @2
  png_sig_cmp @3
@@ -248,3 +248,4 @@ EXPORTS
  png_convert_to_rfc1123_buffer @241
  png_set_check_for_invalid_index @242
  png_get_palette_max @243
+ png_set_option @244
index d790929e7e7bb7b3a1fe99dc18888aa1bc249bab..6f52918d4791500acde47cbb634a87575ed2ccc3 100644 (file)
  */
 
 #define PNG_EXPORTA(ordinal, type, name, args, attributes)\
-       PNG_DEFN_MAGIC-name @ordinal-PNG_DEFN_END
+        PNG_DFN "@" name "@ @@" ordinal "@"
 #define PNG_REMOVED(ordinal, type, name, args, attributes)\
-       PNG_DEFN_MAGIC-; name @ordinal-PNG_DEFN_END
+        PNG_DFN "; @" name "@ @@" ordinal "@"
 #define PNG_EXPORT_LAST_ORDINAL(ordinal)\
-       PNG_DEFN_MAGIC-; @ordinal-PNG_DEFN_END
+        PNG_DFN "; @@" ordinal "@"
 
 /* Read the defaults, but use scripts/pnglibconf.h.prebuilt; the 'standard'
  * header file.
  * defaulted to 'off' in scripts/pnglibconf.dfa
  *
  * Maintenance: if scripts/pnglibconf.dfa options are changed
- * from, or to, 'off' this needs updating!
+ * from, or to, 'disabled' this needs updating!
  */
 #define PNG_BENIGN_ERRORS_SUPPORTED
 #define PNG_ERROR_NUMBERS_SUPPORTED
 #define PNG_READ_BIG_ENDIAN_SUPPORTED  /* should do nothing! */
 #define PNG_INCH_CONVERSIONS_SUPPORTED
 #define PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED
+#define PNG_SET_OPTION_SUPPORTED
 
 #undef PNG_H
 #include "../png.h"
index 89d5f3879e2eda8854928899fc0b88b1b7115d66..61ba7d80bc6932070158d94e580f50dd3864a97c 100644 (file)
@@ -9,18 +9,11 @@
  * and license in png.h
  */
 
-#define HEADER PNG_DEFN_MAGIC-PNGLIB_LIBNAME {global:-PNG_DEFN_END
-
-/* NOTE: PNG_JOIN is interpreted by the calling script as a signal to
- * join the two things on either side, so we can do symbol
- * substitution within the name, regular C ## joins the pp-tokens,
- * not their final values.
- */
 #define PNG_EXPORTA(ordinal, type, name, args, attributes)\
-       PNG_DEFN_MAGIC- SYMBOL_PREFIX PNG_JOIN name;-PNG_DEFN_END
+        PNG_DFN " @" SYMBOL_PREFIX "@@" name "@;"
 
-#define TRAILER PNG_DEFN_MAGIC-local: *; };-PNG_DEFN_END
+PNG_DFN "@" PNGLIB_LIBNAME "@ {global:"
 
-HEADER
 #include "../png.h"
-TRAILER
+
+PNG_DFN "local: *; };"
diff --git a/l4/pkg/libpng/lib/dist/test-driver b/l4/pkg/libpng/lib/dist/test-driver
new file mode 100644 (file)
index 0000000..53e19b8
--- /dev/null
@@ -0,0 +1,127 @@
+#! /bin/sh
+# test-driver - basic testsuite driver script.
+
+scriptversion=2012-06-27.10; # UTC
+
+# Copyright (C) 2011-2012 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+# Make unconditional expansion of undefined variables an error.  This
+# helps a lot in preventing typo-related bugs.
+set -u
+
+usage_error ()
+{
+  echo "$0: $*" >&2
+  print_usage >&2
+  exit 2
+}
+
+print_usage ()
+{
+  cat <<END
+Usage:
+  test-driver --test-name=NAME --log-file=PATH --trs-file=PATH
+              [--expect-failure={yes|no}] [--color-tests={yes|no}]
+              [--enable-hard-errors={yes|no}] [--] TEST-SCRIPT
+The '--test-name', '--log-file' and '--trs-file' options are mandatory.
+END
+}
+
+# TODO: better error handling in option parsing (in particular, ensure
+# TODO: $log_file, $trs_file and $test_name are defined).
+test_name= # Used for reporting.
+log_file=  # Where to save the output of the test script.
+trs_file=  # Where to save the metadata of the test run.
+expect_failure=no
+color_tests=no
+enable_hard_errors=yes
+while test $# -gt 0; do
+  case $1 in
+  --help) print_usage; exit $?;;
+  --version) echo "test-driver $scriptversion"; exit $?;;
+  --test-name) test_name=$2; shift;;
+  --log-file) log_file=$2; shift;;
+  --trs-file) trs_file=$2; shift;;
+  --color-tests) color_tests=$2; shift;;
+  --expect-failure) expect_failure=$2; shift;;
+  --enable-hard-errors) enable_hard_errors=$2; shift;;
+  --) shift; break;;
+  -*) usage_error "invalid option: '$1'";;
+  esac
+  shift
+done
+
+if test $color_tests = yes; then
+  # Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'.
+  red='\e[0;31m' # Red.
+  grn='\e[0;32m' # Green.
+  lgn='\e[1;32m' # Light green.
+  blu='\e[1;34m' # Blue.
+  mgn='\e[0;35m' # Magenta.
+  std='\e[m'     # No color.
+else
+  red= grn= lgn= blu= mgn= std=
+fi
+
+do_exit='rm -f $log_file $trs_file; (exit $st); exit $st'
+trap "st=129; $do_exit" 1
+trap "st=130; $do_exit" 2
+trap "st=141; $do_exit" 13
+trap "st=143; $do_exit" 15
+
+# Test script is run here.
+"$@" >$log_file 2>&1
+estatus=$?
+if test $enable_hard_errors = no && test $estatus -eq 99; then
+  estatus=1
+fi
+
+case $estatus:$expect_failure in
+  0:yes) col=$red res=XPASS recheck=yes gcopy=yes;;
+  0:*)   col=$grn res=PASS  recheck=no  gcopy=no;;
+  77:*)  col=$blu res=SKIP  recheck=no  gcopy=yes;;
+  99:*)  col=$mgn res=ERROR recheck=yes gcopy=yes;;
+  *:yes) col=$lgn res=XFAIL recheck=no  gcopy=yes;;
+  *:*)   col=$red res=FAIL  recheck=yes gcopy=yes;;
+esac
+
+# Report outcome to console.
+echo "${col}${res}${std}: $test_name"
+
+# Register the test result, and other relevant metadata.
+echo ":test-result: $res" > $trs_file
+echo ":global-test-result: $res" >> $trs_file
+echo ":recheck: $recheck" >> $trs_file
+echo ":copy-in-global-log: $gcopy" >> $trs_file
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
index 2beb5b37a2c74cbf7134c8fa26a53ca286ad4c86..7a56b008ea81f934a180c6c2d36304a23c7fb441 100644 (file)
@@ -1,6 +1,5 @@
 #pragma once
 
-#include <pthread-l4.h>
 #include <errno.h>
 
 #define SYS_MBOX_NULL NULL
index 0921788fc9ef735aeee41b128a386675f221bc67..ab4de514ffaa2fa3415a6bab2ab17ba2f076eea8 100644 (file)
@@ -1,6 +1,6 @@
 /* ----------------------------------------------------------------------------
  * This file was automatically generated by SWIG (http://www.swig.org).
- * Version 2.0.7
+ * Version 1.3.40
  * 
  * This file is not intended to be easily readable and contains a number of 
  * coding conventions designed to improve portability and efficiency. Do not make
@@ -9,8 +9,6 @@
  * ----------------------------------------------------------------------------- */
 
 #define SWIGLUA
-#define SWIG_LUA_TARGET SWIG_LUA_FLAVOR_LUA
-#define SWIG_LUA_MODULE_GLOBAL
 
 
 #ifdef __cplusplus
@@ -198,7 +196,7 @@ template <typename T> T SwigValueInit() {
 /* 
    Flags/methods for returning states.
    
-   The SWIG conversion methods, as ConvertPtr, return an integer 
+   The SWIG conversion methods, as ConvertPtr, return and integer 
    that tells if the conversion was successful or not. And if not,
    an error code can be returned (see swigerrors.swg for the codes).
    
@@ -730,6 +728,9 @@ SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) {
 #endif
 
 /* -----------------------------------------------------------------------------
+ * See the LICENSE file for information on copyright, usage and redistribution
+ * of SWIG, and the README file for authors - http://www.swig.org/release.html.
+ *
  * luarun.swg
  *
  * This file contains the runtime support for Lua modules
@@ -746,62 +747,6 @@ SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) {
 #include <stdlib.h>  /* for malloc */
 #include <assert.h>  /* for a few sanity tests */
 
-/* -----------------------------------------------------------------------------
- * Lua flavors
- * ----------------------------------------------------------------------------- */
-
-#define SWIG_LUA_FLAVOR_LUA 1
-#define SWIG_LUA_FLAVOR_ELUA 2
-#define SWIG_LUA_FLAVOR_ELUAC 3
-
-#if !defined(SWIG_LUA_TARGET)
-# error SWIG_LUA_TARGET not defined
-#endif
-
-#if (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUA) || (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUAC)
-#  define SWIG_LUA_CONSTTAB_INT(B, C) LSTRKEY(B), LNUMVAL(C)
-#  define SWIG_LUA_CONSTTAB_FLOAT(B, C) LSTRKEY(B), LNUMVAL(C)
-#  define SWIG_LUA_CONSTTAB_STRING(B, C) LSTRKEY(B), LSTRVAL(C)
-#  define SWIG_LUA_CONSTTAB_CHAR(B, C) LSTRKEY(B), LNUMVAL(C)
-#else /* SWIG_LUA_FLAVOR_LUA */
-#  define SWIG_LUA_CONSTTAB_INT(B, C) SWIG_LUA_INT, (char *)B, (long)C, 0, 0, 0
-#  define SWIG_LUA_CONSTTAB_FLOAT(B, C) SWIG_LUA_FLOAT, (char *)B, 0, (double)C, 0, 0
-#  define SWIG_LUA_CONSTTAB_STRING(B, C) SWIG_LUA_STRING, (char *)B, 0, 0, (void *)C, 0
-#  define SWIG_LUA_CONSTTAB_CHAR(B, C) SWIG_LUA_CHAR, (char *)B, (long)C, 0, 0, 0
-#endif
-
-#if (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUA) || (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUAC)
-#  define LRO_STRVAL(v) {{.p = (char *) v}, LUA_TSTRING}
-#  define LSTRVAL LRO_STRVAL
-#endif
-
-/* -----------------------------------------------------------------------------
- * compatibility defines
- * ----------------------------------------------------------------------------- */
-
-/* History of Lua C API length functions:  In Lua 5.0 (and before?)
-   there was "lua_strlen".  In Lua 5.1, this was renamed "lua_objlen",
-   but a compatibility define of "lua_strlen" was added.  In Lua 5.2,
-   this function was again renamed, to "lua_rawlen" (to emphasize that
-   it doesn't call the "__len" metamethod), and the compatibility
-   define of lua_strlen was removed.  All SWIG uses have been updated
-   to "lua_rawlen", and we add our own defines of that here for older
-   versions of Lua.  */
-#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501
-# define lua_rawlen lua_strlen
-#elif LUA_VERSION_NUM == 501
-# define lua_rawlen lua_objlen
-#endif
-
-
-/* lua_pushglobaltable is the recommended "future-proof" way to get
-   the global table for Lua 5.2 and later.  Here we define
-   lua_pushglobaltable ourselves for Lua versions before 5.2.  */
-#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 502
-# define lua_pushglobaltable(L) lua_pushvalue(L, LUA_GLOBALSINDEX)
-#endif
-
-
 /* -----------------------------------------------------------------------------
  * global swig types
  * ----------------------------------------------------------------------------- */
@@ -863,7 +808,7 @@ typedef struct {
 /* this is the struct for wrapping arbitary packed binary data
 (currently it is only used for member function pointers)
 the data ordering is similar to swig_lua_userdata, but it is currently not possible
-to tell the two structures apart within SWIG, other than by looking at the type
+to tell the two structures apart within Swig, other than by looking at the type
 */
 typedef struct {
   swig_type_info   *type;
@@ -968,24 +913,12 @@ SWIGINTERN int SWIG_Lua_module_get(lua_State* L)
    lua_tostring(L,2));
 */
   /* get the metatable */
-#if ((SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUA) || (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUAC))
-  assert(lua_isrotable(L,1)); /* just in case */
-#else
-  assert(lua_istable(L,1)); /* default Lua action */
-#endif
+  assert(lua_istable(L,1));  /* just in case */
   lua_getmetatable(L,1);  /* get the metatable */
-#if ((SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUA) || (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUAC))
-  assert(lua_isrotable(L,-1));  /* just in case */
-#else
-  assert(lua_istable(L,-1));
-#endif
+  assert(lua_istable(L,-1));  /* just in case */
   SWIG_Lua_get_table(L,".get");  /* get the .get table */
   lua_remove(L,3);  /* remove metatable */
-#if ((SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUA) || (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUAC))
-  if (lua_isrotable(L,-1))
-#else
   if (lua_istable(L,-1))
-#endif
   {
     /* look for the key in the .get table */
     lua_pushvalue(L,2);  /* key */
@@ -1000,7 +933,7 @@ SWIGINTERN int SWIG_Lua_module_get(lua_State* L)
   }
   lua_pop(L,1);  /* remove the .get */
   lua_pushnil(L);  /* return a nil */
-  return 1;
+    return 1;
 }
 
 /* the module.set method used for setting linked data */
@@ -1012,24 +945,12 @@ SWIGINTERN int SWIG_Lua_module_set(lua_State* L)
   (3) any for the new value
 */
   /* get the metatable */
-#if ((SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUA) || (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUAC))
-  assert(lua_isrotable(L,1));  /* just in case */
-#else
-  assert(lua_istable(L,1)); /* default Lua action */
-#endif
+  assert(lua_istable(L,1));  /* just in case */
   lua_getmetatable(L,1);  /* get the metatable */
-#if ((SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUA) || (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUAC))
-  assert(lua_isrotable(L,-1));  /* just in case */
-#else
-  assert(lua_istable(L,-1));
-#endif
+  assert(lua_istable(L,-1));  /* just in case */
   SWIG_Lua_get_table(L,".set");  /* get the .set table */
   lua_remove(L,4);  /* remove metatable */
-#if ((SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUA) || (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUAC))
-  if (lua_isrotable(L,-1))
-#else
   if (lua_istable(L,-1))
-#endif
   {
     /* look for the key in the .set table */
     lua_pushvalue(L,2);  /* key */
@@ -1041,11 +962,6 @@ SWIGINTERN int SWIG_Lua_module_set(lua_State* L)
       lua_call(L,1,0);
       return 0;
     }
-#if (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUA) 
-    else {
-      return 0; // Exits stoically if an invalid key is initialized.
-    }
-#endif
   }
   lua_settop(L,3);  /* reset back to start */
   /* we now have the table, key & new value, so just set directly */
@@ -1053,8 +969,7 @@ SWIGINTERN int SWIG_Lua_module_set(lua_State* L)
   return 0;
 }
 
-#if ((SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUA) && (SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUAC))
-/* registering a module in lua. Pushes the module table on the stack. */
+/* registering a module in lua */
 SWIGINTERN void  SWIG_Lua_module_begin(lua_State* L,const char* name)
 {
   assert(lua_istable(L,-1));  /* just in case */
@@ -1071,16 +986,8 @@ SWIGINTERN void  SWIG_Lua_module_begin(lua_State* L,const char* name)
   lua_newtable(L);    /* the .set table */
   lua_rawset(L,-3);  /* add .set into metatable */
   lua_setmetatable(L,-2);  /* sets meta table in module */
-#ifdef SWIG_LUA_MODULE_GLOBAL
-  /* If requested, install the module directly into the global namespace. */
   lua_rawset(L,-3);        /* add module into parent */
   SWIG_Lua_get_table(L,name);   /* get the table back out */
-#else
-  /* Do not install the module table as global name. The stack top has
-     the module table with the name below. We pop the top and replace
-     the name with it. */
-  lua_replace(L,-2);
-#endif
 }
 
 /* ending the register */
@@ -1108,7 +1015,6 @@ SWIGINTERN void SWIG_Lua_module_add_variable(lua_State* L,const char* name,lua_C
   }
   lua_pop(L,1);       /* tidy stack (remove meta) */
 }
-#endif
 
 /* adding a function module */
 SWIGINTERN void  SWIG_Lua_module_add_function(lua_State* L,const char* name,lua_CFunction fn)
@@ -1238,39 +1144,6 @@ SWIGINTERN int  SWIG_Lua_class_destruct(lua_State* L)
   return 0;
 }
 
-/* the class.__tostring method called by the interpreter and print */
-SWIGINTERN int  SWIG_Lua_class_tostring(lua_State* L)
-{
-/*  there should be 1 param passed in
-  (1) userdata (not the metatable) */
-  assert(lua_isuserdata(L,1));  /* just in case */
-  unsigned long userData = (unsigned long)lua_touserdata(L,1); /* get the userdata address for later */
-  lua_getmetatable(L,1);    /* get the meta table */
-  assert(lua_istable(L,-1));  /* just in case */
-  
-  lua_getfield(L, -1, ".type");
-  const char* className = lua_tostring(L, -1);
-  
-  char output[256];
-  sprintf(output, "<%s userdata: %lX>", className, userData);
-  
-  lua_pushstring(L, (const char*)output);
-  return 1;
-}
-
-/* to manually disown some userdata */
-SWIGINTERN int  SWIG_Lua_class_disown(lua_State* L)
-{
-/*  there should be 1 params passed in
-  (1) userdata (not the meta table) */
-  swig_lua_userdata* usr;
-  assert(lua_isuserdata(L,-1));  /* just in case */
-  usr=(swig_lua_userdata*)lua_touserdata(L,-1);  /* get it */
-  
-  usr->own = 0; /* clear our ownership */
-  return 0;
-}
-
 /* gets the swig class registry (or creates it) */
 SWIGINTERN void  SWIG_Lua_get_class_registry(lua_State* L)
 {
@@ -1396,15 +1269,11 @@ SWIGINTERN void  SWIG_Lua_class_register(lua_State* L,swig_lua_class* clss)
   /* add a table called ".fn" */
   lua_pushstring(L,".fn");
   lua_newtable(L);
-  /* add manual disown method */
-  SWIG_Lua_add_function(L,"__disown",SWIG_Lua_class_disown);
   lua_rawset(L,-3);
   /* add accessor fns for using the .get,.set&.fn */
   SWIG_Lua_add_function(L,"__index",SWIG_Lua_class_get);
   SWIG_Lua_add_function(L,"__newindex",SWIG_Lua_class_set);
   SWIG_Lua_add_function(L,"__gc",SWIG_Lua_class_destruct);
-  /* add tostring method for better output */
-  SWIG_Lua_add_function(L,"__tostring",SWIG_Lua_class_tostring);
   /* add it */
   lua_rawset(L,-3);  /* metatable into registry */
   lua_pop(L,1);      /* tidy stack (remove registry) */
@@ -1447,9 +1316,7 @@ SWIGRUNTIME void SWIG_Lua_NewPointerObj(lua_State* L,void* ptr,swig_type_info *t
   usr->ptr=ptr;  /* set the ptr */
   usr->type=type;
   usr->own=own;
-#if (SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUAC)
   _SWIG_Lua_AddMetatable(L,type); /* add metatable */
-#endif
 }
 
 /* takes a object from the lua stack & converts it into an object of the correct type
@@ -1526,7 +1393,7 @@ SWIGRUNTIME const char *SWIG_Lua_typename(lua_State *L, int tp)
   swig_lua_userdata* usr;
   if (lua_isuserdata(L,tp))
   {
-    usr=(swig_lua_userdata*)lua_touserdata(L,tp);  /* get data */
+    usr=(swig_lua_userdata*)lua_touserdata(L,1);  /* get data */
     if (usr && usr->type && usr->type->str)
       return usr->type->str;
     return "userdata (unknown type)";
@@ -1562,7 +1429,6 @@ SWIGRUNTIME int SWIG_Lua_equal(lua_State* L)
  * global variable support code: class/struct typemap functions
  * ----------------------------------------------------------------------------- */
 
-#if ((SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUA) && (SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUAC))
 /* Install Constants */
 SWIGINTERN void
 SWIG_Lua_InstallConstants(lua_State* L, swig_lua_const_info constants[]) {
@@ -1604,7 +1470,6 @@ SWIG_Lua_InstallConstants(lua_State* L, swig_lua_const_info constants[]) {
     }
   }
 }
-#endif
 
 /* -----------------------------------------------------------------------------
  * executing lua code from within the wrapper
@@ -1675,6 +1540,7 @@ static swig_module_info swig_module = {swig_types, 18, 0, 0, 0, 0};
 
 #define SWIG_LUACODE   luaopen_Mag_luacode
 
+
 namespace swig {
 typedef struct{} LANGUAGE_OBJ;
 }
@@ -1682,10 +1548,10 @@ typedef struct{} LANGUAGE_OBJ;
 
 #ifdef __cplusplus     /* generic alloc/dealloc fns*/
 #define SWIG_ALLOC_ARRAY(TYPE,LEN)     new TYPE[LEN]
-#define SWIG_FREE_ARRAY(PTR)           delete[] PTR
+#define SWIG_FREE_ARRAY(PTR)           delete[] PTR;
 #else
 #define SWIG_ALLOC_ARRAY(TYPE,LEN)     (TYPE *)malloc(LEN*sizeof(TYPE))
-#define SWIG_FREE_ARRAY(PTR)           free(PTR)
+#define SWIG_FREE_ARRAY(PTR)           free(PTR);
 #endif
 /* counting the size of arrays:*/
 SWIGINTERN int SWIG_itable_size(lua_State* L, int index)
@@ -1771,8 +1637,6 @@ SWIGINTERN int SWIG_table_size(lua_State* L, int index)
                }\
        }
 
-SWIG_DECLARE_TYPEMAP_ARR_FN(schar,signed char);
-SWIG_DECLARE_TYPEMAP_ARR_FN(uchar,unsigned char);
 SWIG_DECLARE_TYPEMAP_ARR_FN(int,int);
 SWIG_DECLARE_TYPEMAP_ARR_FN(uint,unsigned int);
 SWIG_DECLARE_TYPEMAP_ARR_FN(short,short);
@@ -1935,9 +1799,9 @@ static Mag_server::User_state *get_user_state()
 #endif
 static int _wrap_Event_stream_info_get_propbit(lua_State* L) { int SWIG_arg = 0;
   L4Re::Event_stream_info *arg1 = (L4Re::Event_stream_info *) 0 ; unsigned int arg2 ; bool result;
-  SWIG_check_num_args("L4Re::Event_stream_info::get_propbit",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("L4Re::Event_stream_info::get_propbit",1,"L4Re::Event_stream_info const *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("L4Re::Event_stream_info::get_propbit",2,"unsigned int");
+  SWIG_check_num_args("get_propbit",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("get_propbit",1,"L4Re::Event_stream_info const *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("get_propbit",2,"unsigned int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_L4Re__Event_stream_info,0))){
     SWIG_fail_ptr("Event_stream_info_get_propbit",1,SWIGTYPE_p_L4Re__Event_stream_info); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
@@ -1945,10 +1809,9 @@ static int _wrap_Event_stream_info_get_propbit(lua_State* L) { int SWIG_arg = 0;
   return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Event_stream_info_set_propbit(lua_State* L) { int SWIG_arg = 0;
   L4Re::Event_stream_info *arg1 = (L4Re::Event_stream_info *) 0 ; unsigned int arg2 ; bool arg3 ;
-  SWIG_check_num_args("L4Re::Event_stream_info::set_propbit",3,3)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("L4Re::Event_stream_info::set_propbit",1,"L4Re::Event_stream_info *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("L4Re::Event_stream_info::set_propbit",2,"unsigned int");
-  if(!lua_isboolean(L,3)) SWIG_fail_arg("L4Re::Event_stream_info::set_propbit",3,"bool");
+  SWIG_check_num_args("set_propbit",3,3) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("set_propbit",1,"L4Re::Event_stream_info *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("set_propbit",2,"unsigned int");
+  if(!lua_isboolean(L,3)) SWIG_fail_arg("set_propbit",3,"bool");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_L4Re__Event_stream_info,0))){
     SWIG_fail_ptr("Event_stream_info_set_propbit",1,SWIGTYPE_p_L4Re__Event_stream_info); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
@@ -1956,9 +1819,8 @@ static int _wrap_Event_stream_info_set_propbit(lua_State* L) { int SWIG_arg = 0;
   return SWIG_arg; }
 static int _wrap_Event_stream_info_get_evbit(lua_State* L) { int SWIG_arg = 0;
   L4Re::Event_stream_info *arg1 = (L4Re::Event_stream_info *) 0 ; unsigned int arg2 ; bool result;
-  SWIG_check_num_args("L4Re::Event_stream_info::get_evbit",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("L4Re::Event_stream_info::get_evbit",1,"L4Re::Event_stream_info const *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("L4Re::Event_stream_info::get_evbit",2,"unsigned int");
+  SWIG_check_num_args("get_evbit",2,2) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("get_evbit",1,"L4Re::Event_stream_info const *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("get_evbit",2,"unsigned int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_L4Re__Event_stream_info,0))){
     SWIG_fail_ptr("Event_stream_info_get_evbit",1,SWIGTYPE_p_L4Re__Event_stream_info); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
@@ -1966,10 +1828,9 @@ static int _wrap_Event_stream_info_get_evbit(lua_State* L) { int SWIG_arg = 0;
   return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Event_stream_info_set_evbit(lua_State* L) { int SWIG_arg = 0;
   L4Re::Event_stream_info *arg1 = (L4Re::Event_stream_info *) 0 ; unsigned int arg2 ; bool arg3 ;
-  SWIG_check_num_args("L4Re::Event_stream_info::set_evbit",3,3)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("L4Re::Event_stream_info::set_evbit",1,"L4Re::Event_stream_info *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("L4Re::Event_stream_info::set_evbit",2,"unsigned int");
-  if(!lua_isboolean(L,3)) SWIG_fail_arg("L4Re::Event_stream_info::set_evbit",3,"bool");
+  SWIG_check_num_args("set_evbit",3,3) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("set_evbit",1,"L4Re::Event_stream_info *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("set_evbit",2,"unsigned int");
+  if(!lua_isboolean(L,3)) SWIG_fail_arg("set_evbit",3,"bool");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_L4Re__Event_stream_info,0))){
     SWIG_fail_ptr("Event_stream_info_set_evbit",1,SWIGTYPE_p_L4Re__Event_stream_info); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
@@ -1977,9 +1838,9 @@ static int _wrap_Event_stream_info_set_evbit(lua_State* L) { int SWIG_arg = 0;
   return SWIG_arg; }
 static int _wrap_Event_stream_info_get_keybit(lua_State* L) { int SWIG_arg = 0;
   L4Re::Event_stream_info *arg1 = (L4Re::Event_stream_info *) 0 ; unsigned int arg2 ; bool result;
-  SWIG_check_num_args("L4Re::Event_stream_info::get_keybit",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("L4Re::Event_stream_info::get_keybit",1,"L4Re::Event_stream_info const *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("L4Re::Event_stream_info::get_keybit",2,"unsigned int");
+  SWIG_check_num_args("get_keybit",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("get_keybit",1,"L4Re::Event_stream_info const *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("get_keybit",2,"unsigned int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_L4Re__Event_stream_info,0))){
     SWIG_fail_ptr("Event_stream_info_get_keybit",1,SWIGTYPE_p_L4Re__Event_stream_info); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
@@ -1987,10 +1848,9 @@ static int _wrap_Event_stream_info_get_keybit(lua_State* L) { int SWIG_arg = 0;
   return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Event_stream_info_set_keybit(lua_State* L) { int SWIG_arg = 0;
   L4Re::Event_stream_info *arg1 = (L4Re::Event_stream_info *) 0 ; unsigned int arg2 ; bool arg3 ;
-  SWIG_check_num_args("L4Re::Event_stream_info::set_keybit",3,3)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("L4Re::Event_stream_info::set_keybit",1,"L4Re::Event_stream_info *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("L4Re::Event_stream_info::set_keybit",2,"unsigned int");
-  if(!lua_isboolean(L,3)) SWIG_fail_arg("L4Re::Event_stream_info::set_keybit",3,"bool");
+  SWIG_check_num_args("set_keybit",3,3) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("set_keybit",1,"L4Re::Event_stream_info *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("set_keybit",2,"unsigned int");
+  if(!lua_isboolean(L,3)) SWIG_fail_arg("set_keybit",3,"bool");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_L4Re__Event_stream_info,0))){
     SWIG_fail_ptr("Event_stream_info_set_keybit",1,SWIGTYPE_p_L4Re__Event_stream_info); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
@@ -1998,9 +1858,9 @@ static int _wrap_Event_stream_info_set_keybit(lua_State* L) { int SWIG_arg = 0;
   return SWIG_arg; }
 static int _wrap_Event_stream_info_get_relbit(lua_State* L) { int SWIG_arg = 0;
   L4Re::Event_stream_info *arg1 = (L4Re::Event_stream_info *) 0 ; unsigned int arg2 ; bool result;
-  SWIG_check_num_args("L4Re::Event_stream_info::get_relbit",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("L4Re::Event_stream_info::get_relbit",1,"L4Re::Event_stream_info const *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("L4Re::Event_stream_info::get_relbit",2,"unsigned int");
+  SWIG_check_num_args("get_relbit",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("get_relbit",1,"L4Re::Event_stream_info const *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("get_relbit",2,"unsigned int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_L4Re__Event_stream_info,0))){
     SWIG_fail_ptr("Event_stream_info_get_relbit",1,SWIGTYPE_p_L4Re__Event_stream_info); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
@@ -2008,10 +1868,9 @@ static int _wrap_Event_stream_info_get_relbit(lua_State* L) { int SWIG_arg = 0;
   return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Event_stream_info_set_relbit(lua_State* L) { int SWIG_arg = 0;
   L4Re::Event_stream_info *arg1 = (L4Re::Event_stream_info *) 0 ; unsigned int arg2 ; bool arg3 ;
-  SWIG_check_num_args("L4Re::Event_stream_info::set_relbit",3,3)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("L4Re::Event_stream_info::set_relbit",1,"L4Re::Event_stream_info *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("L4Re::Event_stream_info::set_relbit",2,"unsigned int");
-  if(!lua_isboolean(L,3)) SWIG_fail_arg("L4Re::Event_stream_info::set_relbit",3,"bool");
+  SWIG_check_num_args("set_relbit",3,3) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("set_relbit",1,"L4Re::Event_stream_info *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("set_relbit",2,"unsigned int");
+  if(!lua_isboolean(L,3)) SWIG_fail_arg("set_relbit",3,"bool");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_L4Re__Event_stream_info,0))){
     SWIG_fail_ptr("Event_stream_info_set_relbit",1,SWIGTYPE_p_L4Re__Event_stream_info); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
@@ -2019,9 +1878,9 @@ static int _wrap_Event_stream_info_set_relbit(lua_State* L) { int SWIG_arg = 0;
   return SWIG_arg; }
 static int _wrap_Event_stream_info_get_absbit(lua_State* L) { int SWIG_arg = 0;
   L4Re::Event_stream_info *arg1 = (L4Re::Event_stream_info *) 0 ; unsigned int arg2 ; bool result;
-  SWIG_check_num_args("L4Re::Event_stream_info::get_absbit",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("L4Re::Event_stream_info::get_absbit",1,"L4Re::Event_stream_info const *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("L4Re::Event_stream_info::get_absbit",2,"unsigned int");
+  SWIG_check_num_args("get_absbit",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("get_absbit",1,"L4Re::Event_stream_info const *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("get_absbit",2,"unsigned int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_L4Re__Event_stream_info,0))){
     SWIG_fail_ptr("Event_stream_info_get_absbit",1,SWIGTYPE_p_L4Re__Event_stream_info); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
@@ -2029,10 +1888,9 @@ static int _wrap_Event_stream_info_get_absbit(lua_State* L) { int SWIG_arg = 0;
   return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Event_stream_info_set_absbit(lua_State* L) { int SWIG_arg = 0;
   L4Re::Event_stream_info *arg1 = (L4Re::Event_stream_info *) 0 ; unsigned int arg2 ; bool arg3 ;
-  SWIG_check_num_args("L4Re::Event_stream_info::set_absbit",3,3)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("L4Re::Event_stream_info::set_absbit",1,"L4Re::Event_stream_info *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("L4Re::Event_stream_info::set_absbit",2,"unsigned int");
-  if(!lua_isboolean(L,3)) SWIG_fail_arg("L4Re::Event_stream_info::set_absbit",3,"bool");
+  SWIG_check_num_args("set_absbit",3,3) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("set_absbit",1,"L4Re::Event_stream_info *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("set_absbit",2,"unsigned int");
+  if(!lua_isboolean(L,3)) SWIG_fail_arg("set_absbit",3,"bool");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_L4Re__Event_stream_info,0))){
     SWIG_fail_ptr("Event_stream_info_set_absbit",1,SWIGTYPE_p_L4Re__Event_stream_info); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
@@ -2042,8 +1900,8 @@ static int _wrap_Event_stream_info_get_device_id(lua_State* L) { int SWIG_arg =
   L4Re::Event_stream_info *arg1 = (L4Re::Event_stream_info *) 0 ; unsigned int *arg2 = (unsigned int *) 0 ;
   unsigned int *arg3 = (unsigned int *) 0 ; unsigned int *arg4 = (unsigned int *) 0 ; unsigned int *arg5 = (unsigned int *) 0 ;
   unsigned int temp2 ; unsigned int temp3 ; unsigned int temp4 ; unsigned int temp5 ; arg2 = &temp2;  arg3 = &temp3; 
-  arg4 = &temp4;  arg5 = &temp5;  SWIG_check_num_args("L4Re::Event_stream_info::get_device_id",1,1)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("L4Re::Event_stream_info::get_device_id",1,"L4Re::Event_stream_info *");
+  arg4 = &temp4;  arg5 = &temp5;  SWIG_check_num_args("get_device_id",1,1)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("get_device_id",1,"L4Re::Event_stream_info *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_L4Re__Event_stream_info,0))){
     SWIG_fail_ptr("Event_stream_info_get_device_id",1,SWIGTYPE_p_L4Re__Event_stream_info); } 
   L4Re_Event_stream_info_get_device_id(arg1,arg2,arg3,arg4,arg5); lua_pushnumber(L, (lua_Number) *arg2); SWIG_arg++;
@@ -2080,55 +1938,54 @@ static const char *swig_L4Re_Event_stream_info_base_names[] = {0};
 static swig_lua_class _wrap_class_L4Re_Event_stream_info = { "Event_stream_info", &SWIGTYPE_p_L4Re__Event_stream_info,_wrap_new_Event_stream_info, swig_delete_Event_stream_info, swig_L4Re_Event_stream_info_methods, swig_L4Re_Event_stream_info_attributes, swig_L4Re_Event_stream_info_bases, swig_L4Re_Event_stream_info_base_names };
 
 static int _wrap_new_Axis_buf(lua_State* L) { int SWIG_arg = 0; unsigned char arg1 ; Mag_server::Axis_buf *result = 0 ;
-  SWIG_check_num_args("Mag_server::Axis_buf::Axis_buf",1,1)
-  if(!lua_isnumber(L,1)) SWIG_fail_arg("Mag_server::Axis_buf::Axis_buf",1,"unsigned char");
+  SWIG_check_num_args("Mag_server::Axis_buf",1,1)
+  if(!lua_isnumber(L,1)) SWIG_fail_arg("Mag_server::Axis_buf",1,"unsigned char");
   SWIG_contract_assert((lua_tointeger(L,1)>=0),"number must not be negative") arg1 = (unsigned char)lua_tointeger(L, 1);
   result = (Mag_server::Axis_buf *)new Mag_server::Axis_buf(arg1);
   SWIG_NewPointerObj(L,result,SWIGTYPE_p_Mag_server__Axis_buf,1); SWIG_arg++;  return SWIG_arg; if(0) SWIG_fail; fail:
   lua_error(L); return SWIG_arg; }
 static int _wrap_Axis_buf_get(lua_State* L) { int SWIG_arg = 0; Mag_server::Axis_buf *arg1 = (Mag_server::Axis_buf *) 0 ;
-  unsigned char arg2 ; l4_int32_t result; SWIG_check_num_args("Mag_server::Axis_buf::get",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_buf::get",1,"Mag_server::Axis_buf const *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Axis_buf::get",2,"unsigned char");
+  unsigned char arg2 ; l4_int32_t result; SWIG_check_num_args("get",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("get",1,"Mag_server::Axis_buf const *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("get",2,"unsigned char");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_buf,0))){
     SWIG_fail_ptr("Axis_buf_get",1,SWIGTYPE_p_Mag_server__Axis_buf); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned char)lua_tointeger(L, 2);
   result = ((Mag_server::Axis_buf const *)arg1)->get(arg2); lua_pushinteger(L, result); SWIG_arg++; return SWIG_arg;
   if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Axis_buf_set(lua_State* L) { int SWIG_arg = 0; Mag_server::Axis_buf *arg1 = (Mag_server::Axis_buf *) 0 ;
-  unsigned char arg2 ; l4_int32_t arg3 ; SWIG_check_num_args("Mag_server::Axis_buf::set",3,3)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_buf::set",1,"Mag_server::Axis_buf *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Axis_buf::set",2,"unsigned char");
-  if(!lua_isnumber(L,3)) SWIG_fail_arg("Mag_server::Axis_buf::set",3,"l4_int32_t");
+  unsigned char arg2 ; l4_int32_t arg3 ; SWIG_check_num_args("set",3,3)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("set",1,"Mag_server::Axis_buf *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("set",2,"unsigned char"); if(!lua_isnumber(L,3)) SWIG_fail_arg("set",3,"l4_int32_t");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_buf,0))){
     SWIG_fail_ptr("Axis_buf_set",1,SWIGTYPE_p_Mag_server__Axis_buf); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned char)lua_tointeger(L, 2);
   arg3 = (l4_int32_t)lua_tointeger(L, 3); (arg1)->set(arg2,arg3); return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L);
   return SWIG_arg; }
 static int _wrap_Axis_buf_copy(lua_State* L) { int SWIG_arg = 0; Mag_server::Axis_buf *arg1 = (Mag_server::Axis_buf *) 0 ;
-  unsigned char arg2 ; unsigned char arg3 ; SWIG_check_num_args("Mag_server::Axis_buf::copy",3,3)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_buf::copy",1,"Mag_server::Axis_buf *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Axis_buf::copy",2,"unsigned char");
-  if(!lua_isnumber(L,3)) SWIG_fail_arg("Mag_server::Axis_buf::copy",3,"unsigned char");
+  unsigned char arg2 ; unsigned char arg3 ; SWIG_check_num_args("copy",3,3)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("copy",1,"Mag_server::Axis_buf *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("copy",2,"unsigned char");
+  if(!lua_isnumber(L,3)) SWIG_fail_arg("copy",3,"unsigned char");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_buf,0))){
     SWIG_fail_ptr("Axis_buf_copy",1,SWIGTYPE_p_Mag_server__Axis_buf); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned char)lua_tointeger(L, 2);
   SWIG_contract_assert((lua_tointeger(L,3)>=0),"number must not be negative") arg3 = (unsigned char)lua_tointeger(L, 3);
   (arg1)->copy(arg2,arg3); return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Axis_buf___getitem(lua_State* L) { int SWIG_arg = 0; Mag_server::Axis_buf *arg1 = (Mag_server::Axis_buf *) 0 ;
-  unsigned char arg2 ; l4_int32_t result; SWIG_check_num_args("Mag_server::Axis_buf::__getitem__",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_buf::__getitem__",1,"Mag_server::Axis_buf const *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Axis_buf::__getitem__",2,"unsigned char");
+  unsigned char arg2 ; l4_int32_t result; SWIG_check_num_args("__getitem__",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("__getitem__",1,"Mag_server::Axis_buf const *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("__getitem__",2,"unsigned char");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_buf,0))){
     SWIG_fail_ptr("Axis_buf___getitem",1,SWIGTYPE_p_Mag_server__Axis_buf); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned char)lua_tointeger(L, 2);
   result = ((Mag_server::Axis_buf const *)arg1)->__getitem__(arg2); lua_pushinteger(L, result); SWIG_arg++; return SWIG_arg;
   if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Axis_buf___setitem(lua_State* L) { int SWIG_arg = 0; Mag_server::Axis_buf *arg1 = (Mag_server::Axis_buf *) 0 ;
-  unsigned char arg2 ; l4_int32_t arg3 ; SWIG_check_num_args("Mag_server::Axis_buf::__setitem__",3,3)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_buf::__setitem__",1,"Mag_server::Axis_buf *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Axis_buf::__setitem__",2,"unsigned char");
-  if(!lua_isnumber(L,3)) SWIG_fail_arg("Mag_server::Axis_buf::__setitem__",3,"l4_int32_t");
+  unsigned char arg2 ; l4_int32_t arg3 ; SWIG_check_num_args("__setitem__",3,3)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("__setitem__",1,"Mag_server::Axis_buf *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("__setitem__",2,"unsigned char");
+  if(!lua_isnumber(L,3)) SWIG_fail_arg("__setitem__",3,"l4_int32_t");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_buf,0))){
     SWIG_fail_ptr("Axis_buf___setitem",1,SWIGTYPE_p_Mag_server__Axis_buf); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned char)lua_tointeger(L, 2);
@@ -2154,8 +2011,8 @@ static const char *swig_Mag_server_Axis_buf_base_names[] = {0};
 static swig_lua_class _wrap_class_Mag_server_Axis_buf = { "Axis_buf", &SWIGTYPE_p_Mag_server__Axis_buf,_wrap_new_Axis_buf, swig_delete_Axis_buf, swig_Mag_server_Axis_buf_methods, swig_Mag_server_Axis_buf_attributes, swig_Mag_server_Axis_buf_bases, swig_Mag_server_Axis_buf_base_names };
 
 static int _wrap_new_Valuatori__SWIG_0(lua_State* L) { int SWIG_arg = 0; Mag_server::Valuator< int > *arg1 = 0 ;
-  Mag_server::Valuator< int > *result = 0 ; SWIG_check_num_args("Mag_server::Valuator< int >::Valuator",1,1)
-  if(!lua_isuserdata(L,1)) SWIG_fail_arg("Mag_server::Valuator< int >::Valuator",1,"Mag_server::Valuator< int > &");
+  Mag_server::Valuator< int > *result = 0 ; SWIG_check_num_args("Mag_server::Valuator<(int)>",1,1)
+  if(!lua_isuserdata(L,1)) SWIG_fail_arg("Mag_server::Valuator<(int)>",1,"Mag_server::Valuator< int > &");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__ValuatorT_int_t,0))){
     SWIG_fail_ptr("new_Valuatori",1,SWIGTYPE_p_Mag_server__ValuatorT_int_t); } 
   result = (Mag_server::Valuator< int > *)new Mag_server::Valuator< int >(*arg1);
@@ -2163,34 +2020,32 @@ static int _wrap_new_Valuatori__SWIG_0(lua_State* L) { int SWIG_arg = 0; Mag_ser
   lua_error(L); return SWIG_arg; }
 static int _wrap_Valuatori_swap(lua_State* L) { int SWIG_arg = 0;
   Mag_server::Valuator< int > *arg1 = (Mag_server::Valuator< int > *) 0 ; Mag_server::Valuator< int > *arg2 = 0 ;
-  SWIG_check_num_args("Mag_server::Valuator< int >::swap",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Valuator< int >::swap",1,"Mag_server::Valuator< int > *");
-  if(!lua_isuserdata(L,2)) SWIG_fail_arg("Mag_server::Valuator< int >::swap",2,"Mag_server::Valuator< int > &");
+  SWIG_check_num_args("swap",2,2) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("swap",1,"Mag_server::Valuator< int > *");
+  if(!lua_isuserdata(L,2)) SWIG_fail_arg("swap",2,"Mag_server::Valuator< int > &");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__ValuatorT_int_t,0))){
     SWIG_fail_ptr("Valuatori_swap",1,SWIGTYPE_p_Mag_server__ValuatorT_int_t); } 
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,2,(void**)&arg2,SWIGTYPE_p_Mag_server__ValuatorT_int_t,0))){
     SWIG_fail_ptr("Valuatori_swap",2,SWIGTYPE_p_Mag_server__ValuatorT_int_t); }  (arg1)->swap(*arg2); return SWIG_arg;
   if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_new_Valuatori__SWIG_1(lua_State* L) { int SWIG_arg = 0; Mag_server::Valuator< int > *result = 0 ;
-  SWIG_check_num_args("Mag_server::Valuator< int >::Valuator",0,0)
+  SWIG_check_num_args("Mag_server::Valuator<(int)>",0,0)
   result = (Mag_server::Valuator< int > *)new Mag_server::Valuator< int >();
   SWIG_NewPointerObj(L,result,SWIGTYPE_p_Mag_server__ValuatorT_int_t,1); SWIG_arg++;  return SWIG_arg; if(0) SWIG_fail; fail:
   lua_error(L); return SWIG_arg; }
 static int _wrap_Valuatori_create(lua_State* L) { int SWIG_arg = 0;
   Mag_server::Valuator< int > *arg1 = (Mag_server::Valuator< int > *) 0 ; unsigned int arg2 ; unsigned int arg3 ;
-  SWIG_check_num_args("Mag_server::Valuator< int >::create",3,3)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Valuator< int >::create",1,"Mag_server::Valuator< int > *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Valuator< int >::create",2,"unsigned int");
-  if(!lua_isnumber(L,3)) SWIG_fail_arg("Mag_server::Valuator< int >::create",3,"unsigned int");
+  SWIG_check_num_args("create",3,3) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("create",1,"Mag_server::Valuator< int > *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("create",2,"unsigned int");
+  if(!lua_isnumber(L,3)) SWIG_fail_arg("create",3,"unsigned int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__ValuatorT_int_t,0))){
     SWIG_fail_ptr("Valuatori_create",1,SWIGTYPE_p_Mag_server__ValuatorT_int_t); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
   SWIG_contract_assert((lua_tointeger(L,3)>=0),"number must not be negative") arg3 = (unsigned int)lua_tointeger(L, 3);
   (arg1)->create(arg2,arg3); return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_new_Valuatori__SWIG_2(lua_State* L) { int SWIG_arg = 0; unsigned int arg1 ; unsigned int arg2 ;
-  Mag_server::Valuator< int > *result = 0 ; SWIG_check_num_args("Mag_server::Valuator< int >::Valuator",2,2)
-  if(!lua_isnumber(L,1)) SWIG_fail_arg("Mag_server::Valuator< int >::Valuator",1,"unsigned int");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Valuator< int >::Valuator",2,"unsigned int");
+  Mag_server::Valuator< int > *result = 0 ; SWIG_check_num_args("Mag_server::Valuator<(int)>",2,2)
+  if(!lua_isnumber(L,1)) SWIG_fail_arg("Mag_server::Valuator<(int)>",1,"unsigned int");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Valuator<(int)>",2,"unsigned int");
   SWIG_contract_assert((lua_tointeger(L,1)>=0),"number must not be negative") arg1 = (unsigned int)lua_tointeger(L, 1);
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
   result = (Mag_server::Valuator< int > *)new Mag_server::Valuator< int >(arg1,arg2);
@@ -2203,20 +2058,18 @@ static int _wrap_new_Valuatori(lua_State* L) { int argc; int argv[3]={ 1,2,3} ;
       _v = lua_isnumber(L,argv[0]); }  if (_v) { { _v = lua_isnumber(L,argv[1]); }  if (_v) {
         return _wrap_new_Valuatori__SWIG_2(L);}  }  } 
   lua_pushstring(L,"Wrong arguments for overloaded function 'new_Valuatori'\n" "  Possible C/C++ prototypes are:\n"
-  "    Mag_server::Valuator< int >::Valuator(Mag_server::Valuator< int > &)\n" "    Mag_server::Valuator< int >::Valuator()\n"
-  "    Mag_server::Valuator< int >::Valuator(unsigned int,unsigned int)\n"); lua_error(L);return 0; }
+  "    Mag_server::Valuator< int >(Mag_server::Valuator< int > &)\n" "    Mag_server::Valuator< int >()\n"
+  "    Mag_server::Valuator< int >(unsigned int,unsigned int)\n"); lua_error(L);return 0; }
 static int _wrap_Valuatori_clear(lua_State* L) { int SWIG_arg = 0;
-  Mag_server::Valuator< int > *arg1 = (Mag_server::Valuator< int > *) 0 ;
-  SWIG_check_num_args("Mag_server::Valuator< int >::clear",1,1)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Valuator< int >::clear",1,"Mag_server::Valuator< int > *");
+  Mag_server::Valuator< int > *arg1 = (Mag_server::Valuator< int > *) 0 ; SWIG_check_num_args("clear",1,1)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("clear",1,"Mag_server::Valuator< int > *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__ValuatorT_int_t,0))){
     SWIG_fail_ptr("Valuatori_clear",1,SWIGTYPE_p_Mag_server__ValuatorT_int_t); }  (arg1)->clear(); return SWIG_arg;
   if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Valuatori_valid(lua_State* L) { int SWIG_arg = 0;
   Mag_server::Valuator< int > *arg1 = (Mag_server::Valuator< int > *) 0 ; unsigned int arg2 ; bool result;
-  SWIG_check_num_args("Mag_server::Valuator< int >::valid",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Valuator< int >::valid",1,"Mag_server::Valuator< int > const *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Valuator< int >::valid",2,"unsigned int");
+  SWIG_check_num_args("valid",2,2) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("valid",1,"Mag_server::Valuator< int > const *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("valid",2,"unsigned int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__ValuatorT_int_t,0))){
     SWIG_fail_ptr("Valuatori_valid",1,SWIGTYPE_p_Mag_server__ValuatorT_int_t); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
@@ -2224,9 +2077,8 @@ static int _wrap_Valuatori_valid(lua_State* L) { int SWIG_arg = 0;
   return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Valuatori_get(lua_State* L) { int SWIG_arg = 0;
   Mag_server::Valuator< int > *arg1 = (Mag_server::Valuator< int > *) 0 ; unsigned int arg2 ; Mag_server::Value< int > result;
-  SWIG_check_num_args("Mag_server::Valuator< int >::get",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Valuator< int >::get",1,"Mag_server::Valuator< int > const *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Valuator< int >::get",2,"unsigned int");
+  SWIG_check_num_args("get",2,2) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("get",1,"Mag_server::Valuator< int > const *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("get",2,"unsigned int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__ValuatorT_int_t,0))){
     SWIG_fail_ptr("Valuatori_get",1,SWIGTYPE_p_Mag_server__ValuatorT_int_t); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
@@ -2235,37 +2087,40 @@ static int _wrap_Valuatori_get(lua_State* L) { int SWIG_arg = 0;
   if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Valuatori_set(lua_State* L) { int SWIG_arg = 0;
   Mag_server::Valuator< int > *arg1 = (Mag_server::Valuator< int > *) 0 ; unsigned int arg2 ; int arg3 ;
-  SWIG_check_num_args("Mag_server::Valuator< int >::set",3,3)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Valuator< int >::set",1,"Mag_server::Valuator< int > *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Valuator< int >::set",2,"unsigned int");
-  if(!lua_isnumber(L,3)) SWIG_fail_arg("Mag_server::Valuator< int >::set",3,"int");
+  SWIG_check_num_args("set",3,3) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("set",1,"Mag_server::Valuator< int > *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("set",2,"unsigned int"); if(!lua_isnumber(L,3)) SWIG_fail_arg("set",3,"int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__ValuatorT_int_t,0))){
     SWIG_fail_ptr("Valuatori_set",1,SWIGTYPE_p_Mag_server__ValuatorT_int_t); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
   arg3 = (int)lua_tointeger(L, 3); (arg1)->set(arg2,arg3); return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L);
   return SWIG_arg; }
 static int _wrap_Valuatori_inv(lua_State* L) { int SWIG_arg = 0;
-  Mag_server::Valuator< int > *arg1 = (Mag_server::Valuator< int > *) 0 ; unsigned int arg2 ;
-  SWIG_check_num_args("Mag_server::Valuator< int >::inv",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Valuator< int >::inv",1,"Mag_server::Valuator< int > *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Valuator< int >::inv",2,"unsigned int");
+  Mag_server::Valuator< int > *arg1 = (Mag_server::Valuator< int > *) 0 ; unsigned int arg2 ; SWIG_check_num_args("inv",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("inv",1,"Mag_server::Valuator< int > *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("inv",2,"unsigned int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__ValuatorT_int_t,0))){
     SWIG_fail_ptr("Valuatori_inv",1,SWIGTYPE_p_Mag_server__ValuatorT_int_t); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
   (arg1)->inv(arg2); return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Valuatori_size(lua_State* L) { int SWIG_arg = 0;
-  Mag_server::Valuator< int > *arg1 = (Mag_server::Valuator< int > *) 0 ; unsigned int result;
-  SWIG_check_num_args("Mag_server::Valuator< int >::size",1,1)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Valuator< int >::size",1,"Mag_server::Valuator< int > const *");
+  Mag_server::Valuator< int > *arg1 = (Mag_server::Valuator< int > *) 0 ; unsigned int result; SWIG_check_num_args("size",1,1)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("size",1,"Mag_server::Valuator< int > const *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__ValuatorT_int_t,0))){
     SWIG_fail_ptr("Valuatori_size",1,SWIGTYPE_p_Mag_server__ValuatorT_int_t); } 
   result = (unsigned int)((Mag_server::Valuator< int > const *)arg1)->size(); lua_pushinteger(L, result); SWIG_arg++;
   return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
+static int _wrap_Valuatori_offset(lua_State* L) { int SWIG_arg = 0;
+  Mag_server::Valuator< int > *arg1 = (Mag_server::Valuator< int > *) 0 ; unsigned int result; SWIG_check_num_args("offset",1,1)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("offset",1,"Mag_server::Valuator< int > const *");
+  if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__ValuatorT_int_t,0))){
+    SWIG_fail_ptr("Valuatori_offset",1,SWIGTYPE_p_Mag_server__ValuatorT_int_t); } 
+  result = (unsigned int)((Mag_server::Valuator< int > const *)arg1)->offset(); lua_pushinteger(L, result); SWIG_arg++;
+  return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Valuatori___getitem(lua_State* L) { int SWIG_arg = 0;
   Mag_server::Valuator< int > *arg1 = (Mag_server::Valuator< int > *) 0 ; unsigned int arg2 ; Mag_server::Value< int > result;
-  SWIG_check_num_args("Mag_server::Valuator< int >::__getitem__",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Valuator< int >::__getitem__",1,"Mag_server::Valuator< int > const *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Valuator< int >::__getitem__",2,"unsigned int");
+  SWIG_check_num_args("__getitem__",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("__getitem__",1,"Mag_server::Valuator< int > const *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("__getitem__",2,"unsigned int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__ValuatorT_int_t,0))){
     SWIG_fail_ptr("Valuatori___getitem",1,SWIGTYPE_p_Mag_server__ValuatorT_int_t); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
@@ -2285,6 +2140,7 @@ static swig_lua_method swig_Mag_server_Valuator_Sl_int_Sg__methods[] = {
     {"set", _wrap_Valuatori_set}, 
     {"inv", _wrap_Valuatori_inv}, 
     {"size", _wrap_Valuatori_size}, 
+    {"offset", _wrap_Valuatori_offset}, 
     {"__getitem", _wrap_Valuatori___getitem}, 
     {0,0}
 };
@@ -2296,20 +2152,18 @@ static const char *swig_Mag_server_Valuator_Sl_int_Sg__base_names[] = {0};
 static swig_lua_class _wrap_class_Mag_server_Valuator_Sl_int_Sg_ = { "Valuatori", &SWIGTYPE_p_Mag_server__ValuatorT_int_t,_wrap_new_Valuatori, swig_delete_Valuatori, swig_Mag_server_Valuator_Sl_int_Sg__methods, swig_Mag_server_Valuator_Sl_int_Sg__attributes, swig_Mag_server_Valuator_Sl_int_Sg__bases, swig_Mag_server_Valuator_Sl_int_Sg__base_names };
 
 static int _wrap_new_Valuei__SWIG_0(lua_State* L) { int SWIG_arg = 0; Mag_server::Value< int > *result = 0 ;
-  SWIG_check_num_args("Mag_server::Value< int >::Value",0,0)
-  result = (Mag_server::Value< int > *)new Mag_server::Value< int >();
+  SWIG_check_num_args("Mag_server::Value<(int)>",0,0) result = (Mag_server::Value< int > *)new Mag_server::Value< int >();
   SWIG_NewPointerObj(L,result,SWIGTYPE_p_Mag_server__ValueT_int_t,1); SWIG_arg++;  return SWIG_arg; if(0) SWIG_fail; fail:
   lua_error(L); return SWIG_arg; }
 static int _wrap_new_Valuei__SWIG_1(lua_State* L) { int SWIG_arg = 0; int arg1 ; Mag_server::Value< int > *result = 0 ;
-  SWIG_check_num_args("Mag_server::Value< int >::Value",1,1)
-  if(!lua_isnumber(L,1)) SWIG_fail_arg("Mag_server::Value< int >::Value",1,"int"); arg1 = (int)lua_tointeger(L, 1);
-  result = (Mag_server::Value< int > *)new Mag_server::Value< int >(arg1);
+  SWIG_check_num_args("Mag_server::Value<(int)>",1,1) if(!lua_isnumber(L,1)) SWIG_fail_arg("Mag_server::Value<(int)>",1,"int");
+  arg1 = (int)lua_tointeger(L, 1); result = (Mag_server::Value< int > *)new Mag_server::Value< int >(arg1);
   SWIG_NewPointerObj(L,result,SWIGTYPE_p_Mag_server__ValueT_int_t,1); SWIG_arg++;  return SWIG_arg; if(0) SWIG_fail; fail:
   lua_error(L); return SWIG_arg; }
 static int _wrap_new_Valuei__SWIG_2(lua_State* L) { int SWIG_arg = 0; bool arg1 ; int arg2 ;
-  Mag_server::Value< int > *result = 0 ; SWIG_check_num_args("Mag_server::Value< int >::Value",2,2)
-  if(!lua_isboolean(L,1)) SWIG_fail_arg("Mag_server::Value< int >::Value",1,"bool");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Value< int >::Value",2,"int"); arg1 = (lua_toboolean(L, 1)!=0);
+  Mag_server::Value< int > *result = 0 ; SWIG_check_num_args("Mag_server::Value<(int)>",2,2)
+  if(!lua_isboolean(L,1)) SWIG_fail_arg("Mag_server::Value<(int)>",1,"bool");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Value<(int)>",2,"int"); arg1 = (lua_toboolean(L, 1)!=0);
   arg2 = (int)lua_tointeger(L, 2); result = (Mag_server::Value< int > *)new Mag_server::Value< int >(arg1,arg2);
   SWIG_NewPointerObj(L,result,SWIGTYPE_p_Mag_server__ValueT_int_t,1); SWIG_arg++;  return SWIG_arg; if(0) SWIG_fail; fail:
   lua_error(L); return SWIG_arg; }
@@ -2318,32 +2172,28 @@ static int _wrap_new_Valuei(lua_State* L) { int argc; int argv[3]={ 1,2,3} ; arg
       return _wrap_new_Valuei__SWIG_1(L);}  }  if (argc == 2) { int _v; { _v = lua_isboolean(L,argv[0]); }  if (_v) { {
         _v = lua_isnumber(L,argv[1]); }  if (_v) { return _wrap_new_Valuei__SWIG_2(L);}  }  } 
   lua_pushstring(L,"Wrong arguments for overloaded function 'new_Valuei'\n" "  Possible C/C++ prototypes are:\n"
-  "    Mag_server::Value< int >::Value()\n" "    Mag_server::Value< int >::Value(int)\n"
-  "    Mag_server::Value< int >::Value(bool,int)\n"); lua_error(L);return 0; }
+  "    Mag_server::Value< int >()\n" "    Mag_server::Value< int >(int)\n" "    Mag_server::Value< int >(bool,int)\n");
+  lua_error(L);return 0; }
 static int _wrap_Valuei_set(lua_State* L) { int SWIG_arg = 0; Mag_server::Value< int > *arg1 = (Mag_server::Value< int > *) 0 ;
-  int arg2 ; SWIG_check_num_args("Mag_server::Value< int >::set",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Value< int >::set",1,"Mag_server::Value< int > *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Value< int >::set",2,"int");
+  int arg2 ; SWIG_check_num_args("set",2,2) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("set",1,"Mag_server::Value< int > *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("set",2,"int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__ValueT_int_t,0))){
     SWIG_fail_ptr("Valuei_set",1,SWIGTYPE_p_Mag_server__ValueT_int_t); }  arg2 = (int)lua_tointeger(L, 2); (arg1)->set(arg2);
   return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Valuei_inv(lua_State* L) { int SWIG_arg = 0; Mag_server::Value< int > *arg1 = (Mag_server::Value< int > *) 0 ;
-  SWIG_check_num_args("Mag_server::Value< int >::inv",1,1)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Value< int >::inv",1,"Mag_server::Value< int > *");
+  SWIG_check_num_args("inv",1,1) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("inv",1,"Mag_server::Value< int > *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__ValueT_int_t,0))){
     SWIG_fail_ptr("Valuei_inv",1,SWIGTYPE_p_Mag_server__ValueT_int_t); }  (arg1)->inv(); return SWIG_arg; if(0) SWIG_fail; fail:
   lua_error(L); return SWIG_arg; }
 static int _wrap_Valuei_valid(lua_State* L) { int SWIG_arg = 0;
-  Mag_server::Value< int > *arg1 = (Mag_server::Value< int > *) 0 ; bool result;
-  SWIG_check_num_args("Mag_server::Value< int >::valid",1,1)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Value< int >::valid",1,"Mag_server::Value< int > const *");
+  Mag_server::Value< int > *arg1 = (Mag_server::Value< int > *) 0 ; bool result; SWIG_check_num_args("valid",1,1)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("valid",1,"Mag_server::Value< int > const *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__ValueT_int_t,0))){
     SWIG_fail_ptr("Valuei_valid",1,SWIGTYPE_p_Mag_server__ValueT_int_t); } 
   result = (bool)((Mag_server::Value< int > const *)arg1)->valid(); lua_pushboolean(L,(int)(result!=0)); SWIG_arg++;
   return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Valuei_val(lua_State* L) { int SWIG_arg = 0; Mag_server::Value< int > *arg1 = (Mag_server::Value< int > *) 0 ;
-  int result; SWIG_check_num_args("Mag_server::Value< int >::val",1,1)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Value< int >::val",1,"Mag_server::Value< int > const *");
+  int result; SWIG_check_num_args("val",1,1) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("val",1,"Mag_server::Value< int > const *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__ValueT_int_t,0))){
     SWIG_fail_ptr("Valuei_val",1,SWIGTYPE_p_Mag_server__ValueT_int_t); } 
   result = (int)((Mag_server::Value< int > const *)arg1)->val(); lua_pushinteger(L, result); SWIG_arg++; return SWIG_arg;
@@ -2367,110 +2217,102 @@ static const char *swig_Mag_server_Value_Sl_int_Sg__base_names[] = {0};
 static swig_lua_class _wrap_class_Mag_server_Value_Sl_int_Sg_ = { "Valuei", &SWIGTYPE_p_Mag_server__ValueT_int_t,_wrap_new_Valuei, swig_delete_Valuei, swig_Mag_server_Value_Sl_int_Sg__methods, swig_Mag_server_Value_Sl_int_Sg__attributes, swig_Mag_server_Value_Sl_int_Sg__bases, swig_Mag_server_Value_Sl_int_Sg__base_names };
 
 static int _wrap_Axis_info_value_set(lua_State* L) { int SWIG_arg = 0;
-  Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ; int arg2 ; SWIG_check_num_args("Mag_server::Axis_info::value",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_info::value",1,"Mag_server::Axis_info *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Axis_info::value",2,"int");
+  Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ; int arg2 ; SWIG_check_num_args("value",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("value",1,"Mag_server::Axis_info *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("value",2,"int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_info,0))){
     SWIG_fail_ptr("Axis_info_value_set",1,SWIGTYPE_p_Mag_server__Axis_info); }  arg2 = (int)lua_tointeger(L, 2);
   if (arg1) (arg1)->value = arg2; return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Axis_info_value_get(lua_State* L) { int SWIG_arg = 0;
-  Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ; int result;
-  SWIG_check_num_args("Mag_server::Axis_info::value",1,1)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_info::value",1,"Mag_server::Axis_info *");
+  Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ; int result; SWIG_check_num_args("value",1,1)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("value",1,"Mag_server::Axis_info *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_info,0))){
     SWIG_fail_ptr("Axis_info_value_get",1,SWIGTYPE_p_Mag_server__Axis_info); }  result = (int) ((arg1)->value);
   lua_pushinteger(L, result); SWIG_arg++; return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Axis_info_min_set(lua_State* L) { int SWIG_arg = 0; Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ;
-  int arg2 ; SWIG_check_num_args("Mag_server::Axis_info::min",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_info::min",1,"Mag_server::Axis_info *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Axis_info::min",2,"int");
+  int arg2 ; SWIG_check_num_args("min",2,2) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("min",1,"Mag_server::Axis_info *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("min",2,"int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_info,0))){
     SWIG_fail_ptr("Axis_info_min_set",1,SWIGTYPE_p_Mag_server__Axis_info); }  arg2 = (int)lua_tointeger(L, 2);
   if (arg1) (arg1)->min = arg2; return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Axis_info_min_get(lua_State* L) { int SWIG_arg = 0; Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ;
-  int result; SWIG_check_num_args("Mag_server::Axis_info::min",1,1)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_info::min",1,"Mag_server::Axis_info *");
+  int result; SWIG_check_num_args("min",1,1) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("min",1,"Mag_server::Axis_info *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_info,0))){
     SWIG_fail_ptr("Axis_info_min_get",1,SWIGTYPE_p_Mag_server__Axis_info); }  result = (int) ((arg1)->min);
   lua_pushinteger(L, result); SWIG_arg++; return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Axis_info_max_set(lua_State* L) { int SWIG_arg = 0; Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ;
-  int arg2 ; SWIG_check_num_args("Mag_server::Axis_info::max",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_info::max",1,"Mag_server::Axis_info *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Axis_info::max",2,"int");
+  int arg2 ; SWIG_check_num_args("max",2,2) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("max",1,"Mag_server::Axis_info *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("max",2,"int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_info,0))){
     SWIG_fail_ptr("Axis_info_max_set",1,SWIGTYPE_p_Mag_server__Axis_info); }  arg2 = (int)lua_tointeger(L, 2);
   if (arg1) (arg1)->max = arg2; return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Axis_info_max_get(lua_State* L) { int SWIG_arg = 0; Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ;
-  int result; SWIG_check_num_args("Mag_server::Axis_info::max",1,1)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_info::max",1,"Mag_server::Axis_info *");
+  int result; SWIG_check_num_args("max",1,1) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("max",1,"Mag_server::Axis_info *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_info,0))){
     SWIG_fail_ptr("Axis_info_max_get",1,SWIGTYPE_p_Mag_server__Axis_info); }  result = (int) ((arg1)->max);
   lua_pushinteger(L, result); SWIG_arg++; return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Axis_info_fuzz_set(lua_State* L) { int SWIG_arg = 0;
-  Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ; int arg2 ; SWIG_check_num_args("Mag_server::Axis_info::fuzz",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_info::fuzz",1,"Mag_server::Axis_info *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Axis_info::fuzz",2,"int");
+  Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ; int arg2 ; SWIG_check_num_args("fuzz",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("fuzz",1,"Mag_server::Axis_info *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("fuzz",2,"int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_info,0))){
     SWIG_fail_ptr("Axis_info_fuzz_set",1,SWIGTYPE_p_Mag_server__Axis_info); }  arg2 = (int)lua_tointeger(L, 2);
   if (arg1) (arg1)->fuzz = arg2; return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Axis_info_fuzz_get(lua_State* L) { int SWIG_arg = 0;
-  Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ; int result; SWIG_check_num_args("Mag_server::Axis_info::fuzz",1,1)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_info::fuzz",1,"Mag_server::Axis_info *");
+  Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ; int result; SWIG_check_num_args("fuzz",1,1)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("fuzz",1,"Mag_server::Axis_info *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_info,0))){
     SWIG_fail_ptr("Axis_info_fuzz_get",1,SWIGTYPE_p_Mag_server__Axis_info); }  result = (int) ((arg1)->fuzz);
   lua_pushinteger(L, result); SWIG_arg++; return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Axis_info_flat_set(lua_State* L) { int SWIG_arg = 0;
-  Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ; int arg2 ; SWIG_check_num_args("Mag_server::Axis_info::flat",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_info::flat",1,"Mag_server::Axis_info *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Axis_info::flat",2,"int");
+  Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ; int arg2 ; SWIG_check_num_args("flat",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("flat",1,"Mag_server::Axis_info *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("flat",2,"int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_info,0))){
     SWIG_fail_ptr("Axis_info_flat_set",1,SWIGTYPE_p_Mag_server__Axis_info); }  arg2 = (int)lua_tointeger(L, 2);
   if (arg1) (arg1)->flat = arg2; return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Axis_info_flat_get(lua_State* L) { int SWIG_arg = 0;
-  Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ; int result; SWIG_check_num_args("Mag_server::Axis_info::flat",1,1)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_info::flat",1,"Mag_server::Axis_info *");
+  Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ; int result; SWIG_check_num_args("flat",1,1)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("flat",1,"Mag_server::Axis_info *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_info,0))){
     SWIG_fail_ptr("Axis_info_flat_get",1,SWIGTYPE_p_Mag_server__Axis_info); }  result = (int) ((arg1)->flat);
   lua_pushinteger(L, result); SWIG_arg++; return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Axis_info_resolution_set(lua_State* L) { int SWIG_arg = 0;
-  Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ; int arg2 ;
-  SWIG_check_num_args("Mag_server::Axis_info::resolution",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_info::resolution",1,"Mag_server::Axis_info *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Axis_info::resolution",2,"int");
+  Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ; int arg2 ; SWIG_check_num_args("resolution",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("resolution",1,"Mag_server::Axis_info *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("resolution",2,"int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_info,0))){
     SWIG_fail_ptr("Axis_info_resolution_set",1,SWIGTYPE_p_Mag_server__Axis_info); }  arg2 = (int)lua_tointeger(L, 2);
   if (arg1) (arg1)->resolution = arg2; return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Axis_info_resolution_get(lua_State* L) { int SWIG_arg = 0;
-  Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ; int result;
-  SWIG_check_num_args("Mag_server::Axis_info::resolution",1,1)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_info::resolution",1,"Mag_server::Axis_info *");
+  Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ; int result; SWIG_check_num_args("resolution",1,1)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("resolution",1,"Mag_server::Axis_info *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_info,0))){
     SWIG_fail_ptr("Axis_info_resolution_get",1,SWIGTYPE_p_Mag_server__Axis_info); }  result = (int) ((arg1)->resolution);
   lua_pushinteger(L, result); SWIG_arg++; return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Axis_info_delta_set(lua_State* L) { int SWIG_arg = 0;
-  Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ; int arg2 ; SWIG_check_num_args("Mag_server::Axis_info::delta",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_info::delta",1,"Mag_server::Axis_info *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Axis_info::delta",2,"int");
+  Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ; int arg2 ; SWIG_check_num_args("delta",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("delta",1,"Mag_server::Axis_info *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("delta",2,"int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_info,0))){
     SWIG_fail_ptr("Axis_info_delta_set",1,SWIGTYPE_p_Mag_server__Axis_info); }  arg2 = (int)lua_tointeger(L, 2);
   if (arg1) (arg1)->delta = arg2; return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Axis_info_delta_get(lua_State* L) { int SWIG_arg = 0;
-  Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ; int result;
-  SWIG_check_num_args("Mag_server::Axis_info::delta",1,1)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_info::delta",1,"Mag_server::Axis_info *");
+  Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ; int result; SWIG_check_num_args("delta",1,1)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("delta",1,"Mag_server::Axis_info *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_info,0))){
     SWIG_fail_ptr("Axis_info_delta_get",1,SWIGTYPE_p_Mag_server__Axis_info); }  result = (int) ((arg1)->delta);
   lua_pushinteger(L, result); SWIG_arg++; return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Axis_info_mode_set(lua_State* L) { int SWIG_arg = 0;
-  Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ; int arg2 ; SWIG_check_num_args("Mag_server::Axis_info::mode",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_info::mode",1,"Mag_server::Axis_info *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Axis_info::mode",2,"int");
+  Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ; int arg2 ; SWIG_check_num_args("mode",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("mode",1,"Mag_server::Axis_info *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("mode",2,"int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_info,0))){
     SWIG_fail_ptr("Axis_info_mode_set",1,SWIGTYPE_p_Mag_server__Axis_info); }  arg2 = (int)lua_tointeger(L, 2);
   if (arg1) (arg1)->mode = arg2; return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Axis_info_mode_get(lua_State* L) { int SWIG_arg = 0;
-  Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ; int result; SWIG_check_num_args("Mag_server::Axis_info::mode",1,1)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_info::mode",1,"Mag_server::Axis_info *");
+  Mag_server::Axis_info *arg1 = (Mag_server::Axis_info *) 0 ; int result; SWIG_check_num_args("mode",1,1)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("mode",1,"Mag_server::Axis_info *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_info,0))){
     SWIG_fail_ptr("Axis_info_mode_get",1,SWIGTYPE_p_Mag_server__Axis_info); }  result = (int) ((arg1)->mode);
   lua_pushinteger(L, result); SWIG_arg++; return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
@@ -2501,13 +2343,13 @@ static const char *swig_Mag_server_Axis_info_base_names[] = {0};
 static swig_lua_class _wrap_class_Mag_server_Axis_info = { "Axis_info", &SWIGTYPE_p_Mag_server__Axis_info,_wrap_new_Axis_info, swig_delete_Axis_info, swig_Mag_server_Axis_info_methods, swig_Mag_server_Axis_info_attributes, swig_Mag_server_Axis_info_bases, swig_Mag_server_Axis_info_base_names };
 
 static int _wrap_new_Axis_info_vector__SWIG_0(lua_State* L) { int SWIG_arg = 0; Mag_server::Axis_info_vector *result = 0 ;
-  SWIG_check_num_args("Mag_server::Axis_info_vector::Axis_info_vector",0,0)
+  SWIG_check_num_args("Mag_server::Axis_info_vector",0,0)
   result = (Mag_server::Axis_info_vector *)new Mag_server::Axis_info_vector();
   SWIG_NewPointerObj(L,result,SWIGTYPE_p_Mag_server__Axis_info_vector,1); SWIG_arg++;  return SWIG_arg; if(0) SWIG_fail; fail:
   lua_error(L); return SWIG_arg; }
 static int _wrap_new_Axis_info_vector__SWIG_1(lua_State* L) { int SWIG_arg = 0; unsigned int arg1 ;
-  Mag_server::Axis_info_vector *result = 0 ; SWIG_check_num_args("Mag_server::Axis_info_vector::Axis_info_vector",1,1)
-  if(!lua_isnumber(L,1)) SWIG_fail_arg("Mag_server::Axis_info_vector::Axis_info_vector",1,"unsigned int");
+  Mag_server::Axis_info_vector *result = 0 ; SWIG_check_num_args("Mag_server::Axis_info_vector",1,1)
+  if(!lua_isnumber(L,1)) SWIG_fail_arg("Mag_server::Axis_info_vector",1,"unsigned int");
   SWIG_contract_assert((lua_tointeger(L,1)>=0),"number must not be negative") arg1 = (unsigned int)lua_tointeger(L, 1);
   result = (Mag_server::Axis_info_vector *)new Mag_server::Axis_info_vector(arg1);
   SWIG_NewPointerObj(L,result,SWIGTYPE_p_Mag_server__Axis_info_vector,1); SWIG_arg++;  return SWIG_arg; if(0) SWIG_fail; fail:
@@ -2516,21 +2358,19 @@ static int _wrap_new_Axis_info_vector(lua_State* L) { int argc; int argv[2]={ 1,
     return _wrap_new_Axis_info_vector__SWIG_0(L);}  if (argc == 1) { int _v; { _v = lua_isnumber(L,argv[0]); }  if (_v) {
       return _wrap_new_Axis_info_vector__SWIG_1(L);}  } 
   lua_pushstring(L,"Wrong arguments for overloaded function 'new_Axis_info_vector'\n" "  Possible C/C++ prototypes are:\n"
-  "    Mag_server::Axis_info_vector::Axis_info_vector()\n"
-  "    Mag_server::Axis_info_vector::Axis_info_vector(unsigned int)\n"); lua_error(L);return 0; }
+  "    Mag_server::Axis_info_vector()\n" "    Mag_server::Axis_info_vector(unsigned int)\n"); lua_error(L);return 0; }
 static int _wrap_Axis_info_vector_size(lua_State* L) { int SWIG_arg = 0;
-  Mag_server::Axis_info_vector *arg1 = (Mag_server::Axis_info_vector *) 0 ; unsigned int result;
-  SWIG_check_num_args("Mag_server::Axis_info_vector::size",1,1)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_info_vector::size",1,"Mag_server::Axis_info_vector const *");
+  Mag_server::Axis_info_vector *arg1 = (Mag_server::Axis_info_vector *) 0 ; unsigned int result; SWIG_check_num_args("size",1,1)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("size",1,"Mag_server::Axis_info_vector const *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_info_vector,0))){
     SWIG_fail_ptr("Axis_info_vector_size",1,SWIGTYPE_p_Mag_server__Axis_info_vector); } 
   result = (unsigned int)((Mag_server::Axis_info_vector const *)arg1)->size(); lua_pushinteger(L, result); SWIG_arg++;
   return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Axis_info_vector_get__SWIG_0(lua_State* L) { int SWIG_arg = 0;
   Mag_server::Axis_info_vector *arg1 = (Mag_server::Axis_info_vector *) 0 ; unsigned int arg2 ;
-  Mag_server::Axis_info *result = 0 ; SWIG_check_num_args("Mag_server::Axis_info_vector::get",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_info_vector::get",1,"Mag_server::Axis_info_vector const *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Axis_info_vector::get",2,"unsigned int");
+  Mag_server::Axis_info *result = 0 ; SWIG_check_num_args("get",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("get",1,"Mag_server::Axis_info_vector const *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("get",2,"unsigned int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_info_vector,0))){
     SWIG_fail_ptr("Axis_info_vector_get",1,SWIGTYPE_p_Mag_server__Axis_info_vector); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
@@ -2539,9 +2379,9 @@ static int _wrap_Axis_info_vector_get__SWIG_0(lua_State* L) { int SWIG_arg = 0;
   lua_error(L); return SWIG_arg; }
 static int _wrap_Axis_info_vector_get__SWIG_1(lua_State* L) { int SWIG_arg = 0;
   Mag_server::Axis_info_vector *arg1 = (Mag_server::Axis_info_vector *) 0 ; unsigned int arg2 ;
-  Mag_server::Axis_info *result = 0 ; SWIG_check_num_args("Mag_server::Axis_info_vector::get",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_info_vector::get",1,"Mag_server::Axis_info_vector *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Axis_info_vector::get",2,"unsigned int");
+  Mag_server::Axis_info *result = 0 ; SWIG_check_num_args("get",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("get",1,"Mag_server::Axis_info_vector *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("get",2,"unsigned int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_info_vector,0))){
     SWIG_fail_ptr("Axis_info_vector_get",1,SWIGTYPE_p_Mag_server__Axis_info_vector); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
@@ -2557,13 +2397,13 @@ static int _wrap_Axis_info_vector_get(lua_State* L) { int argc; int argv[3]={ 1,
         _v = 0; }  else { _v = 1; }  }  if (_v) { { _v = lua_isnumber(L,argv[1]); }  if (_v) {
         return _wrap_Axis_info_vector_get__SWIG_0(L);}  }  } 
   lua_pushstring(L,"Wrong arguments for overloaded function 'Axis_info_vector_get'\n" "  Possible C/C++ prototypes are:\n"
-  "    Mag_server::Axis_info_vector::get(unsigned int) const\n" "    Mag_server::Axis_info_vector::get(unsigned int)\n");
+  "    get(Mag_server::Axis_info_vector const *,unsigned int)\n" "    get(Mag_server::Axis_info_vector *,unsigned int)\n");
   lua_error(L);return 0; }
 static int _wrap_Axis_info_vector_create(lua_State* L) { int SWIG_arg = 0;
   Mag_server::Axis_info_vector *arg1 = (Mag_server::Axis_info_vector *) 0 ; unsigned int arg2 ;
-  Mag_server::Axis_info *result = 0 ; SWIG_check_num_args("Mag_server::Axis_info_vector::create",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_info_vector::create",1,"Mag_server::Axis_info_vector *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Axis_info_vector::create",2,"unsigned int");
+  Mag_server::Axis_info *result = 0 ; SWIG_check_num_args("create",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("create",1,"Mag_server::Axis_info_vector *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("create",2,"unsigned int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_info_vector,0))){
     SWIG_fail_ptr("Axis_info_vector_create",1,SWIGTYPE_p_Mag_server__Axis_info_vector); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
@@ -2572,11 +2412,10 @@ static int _wrap_Axis_info_vector_create(lua_State* L) { int SWIG_arg = 0;
   lua_error(L); return SWIG_arg; }
 static int _wrap_Axis_info_vector_set(lua_State* L) { int SWIG_arg = 0;
   Mag_server::Axis_info_vector *arg1 = (Mag_server::Axis_info_vector *) 0 ; unsigned int arg2 ;
-  Mag_server::Axis_info *arg3 = (Mag_server::Axis_info *) 0 ; bool result;
-  SWIG_check_num_args("Mag_server::Axis_info_vector::set",3,3)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_info_vector::set",1,"Mag_server::Axis_info_vector *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Axis_info_vector::set",2,"unsigned int");
-  if(!SWIG_isptrtype(L,3)) SWIG_fail_arg("Mag_server::Axis_info_vector::set",3,"Mag_server::Axis_info *");
+  Mag_server::Axis_info *arg3 = (Mag_server::Axis_info *) 0 ; bool result; SWIG_check_num_args("set",3,3)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("set",1,"Mag_server::Axis_info_vector *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("set",2,"unsigned int");
+  if(!SWIG_isptrtype(L,3)) SWIG_fail_arg("set",3,"Mag_server::Axis_info *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_info_vector,0))){
     SWIG_fail_ptr("Axis_info_vector_set",1,SWIGTYPE_p_Mag_server__Axis_info_vector); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
@@ -2585,9 +2424,9 @@ static int _wrap_Axis_info_vector_set(lua_State* L) { int SWIG_arg = 0;
   lua_pushboolean(L,(int)(result!=0)); SWIG_arg++; return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Axis_info_vector___getitem(lua_State* L) { int SWIG_arg = 0;
   Mag_server::Axis_info_vector *arg1 = (Mag_server::Axis_info_vector *) 0 ; unsigned int arg2 ;
-  Mag_server::Axis_info *result = 0 ; SWIG_check_num_args("Mag_server::Axis_info_vector::__getitem__",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Axis_info_vector::__getitem__",1,"Mag_server::Axis_info_vector *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Axis_info_vector::__getitem__",2,"unsigned int");
+  Mag_server::Axis_info *result = 0 ; SWIG_check_num_args("__getitem__",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("__getitem__",1,"Mag_server::Axis_info_vector *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("__getitem__",2,"unsigned int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Axis_info_vector,0))){
     SWIG_fail_ptr("Axis_info_vector___getitem",1,SWIGTYPE_p_Mag_server__Axis_info_vector); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
@@ -2615,13 +2454,13 @@ static swig_lua_class _wrap_class_Mag_server_Axis_info_vector = { "Axis_info_vec
 
 static int _wrap_new_Hid_report(lua_State* L) { int SWIG_arg = 0; l4_umword_t arg1 ; unsigned int arg2 ; unsigned int arg3 ;
   unsigned int arg4 ; unsigned int arg5 ; unsigned int arg6 ; Mag_server::Hid_report *result = 0 ;
-  SWIG_check_num_args("Mag_server::Hid_report::Hid_report",6,6)
-  if(!lua_isnumber(L,1)) SWIG_fail_arg("Mag_server::Hid_report::Hid_report",1,"l4_umword_t");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Hid_report::Hid_report",2,"unsigned int");
-  if(!lua_isnumber(L,3)) SWIG_fail_arg("Mag_server::Hid_report::Hid_report",3,"unsigned int");
-  if(!lua_isnumber(L,4)) SWIG_fail_arg("Mag_server::Hid_report::Hid_report",4,"unsigned int");
-  if(!lua_isnumber(L,5)) SWIG_fail_arg("Mag_server::Hid_report::Hid_report",5,"unsigned int");
-  if(!lua_isnumber(L,6)) SWIG_fail_arg("Mag_server::Hid_report::Hid_report",6,"unsigned int");
+  SWIG_check_num_args("Mag_server::Hid_report",6,6)
+  if(!lua_isnumber(L,1)) SWIG_fail_arg("Mag_server::Hid_report",1,"l4_umword_t");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Hid_report",2,"unsigned int");
+  if(!lua_isnumber(L,3)) SWIG_fail_arg("Mag_server::Hid_report",3,"unsigned int");
+  if(!lua_isnumber(L,4)) SWIG_fail_arg("Mag_server::Hid_report",4,"unsigned int");
+  if(!lua_isnumber(L,5)) SWIG_fail_arg("Mag_server::Hid_report",5,"unsigned int");
+  if(!lua_isnumber(L,6)) SWIG_fail_arg("Mag_server::Hid_report",6,"unsigned int");
   SWIG_contract_assert((lua_tointeger(L,1)>=0),"number must not be negative") arg1 = (l4_umword_t)lua_tointeger(L, 1);
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
   SWIG_contract_assert((lua_tointeger(L,3)>=0),"number must not be negative") arg3 = (unsigned int)lua_tointeger(L, 3);
@@ -2632,11 +2471,10 @@ static int _wrap_new_Hid_report(lua_State* L) { int SWIG_arg = 0; l4_umword_t ar
   SWIG_NewPointerObj(L,result,SWIGTYPE_p_Mag_server__Hid_report,1); SWIG_arg++;  return SWIG_arg; if(0) SWIG_fail; fail:
   lua_error(L); return SWIG_arg; }
 static int _wrap_Hid_report_get(lua_State* L) { int SWIG_arg = 0; Mag_server::Hid_report *arg1 = (Mag_server::Hid_report *) 0 ;
-  unsigned char arg2 ; unsigned int arg3 ; int *arg4 = 0 ; bool result; SWIG_check_num_args("Mag_server::Hid_report::get",4,4)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Hid_report::get",1,"Mag_server::Hid_report const *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Hid_report::get",2,"unsigned char");
-  if(!lua_isnumber(L,3)) SWIG_fail_arg("Mag_server::Hid_report::get",3,"unsigned int");
-  if(!lua_isuserdata(L,4)) SWIG_fail_arg("Mag_server::Hid_report::get",4,"int &");
+  unsigned char arg2 ; unsigned int arg3 ; int *arg4 = 0 ; bool result; SWIG_check_num_args("get",4,4)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("get",1,"Mag_server::Hid_report const *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("get",2,"unsigned char"); if(!lua_isnumber(L,3)) SWIG_fail_arg("get",3,"unsigned int");
+  if(!lua_isuserdata(L,4)) SWIG_fail_arg("get",4,"int &");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Hid_report,0))){
     SWIG_fail_ptr("Hid_report_get",1,SWIGTYPE_p_Mag_server__Hid_report); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned char)lua_tointeger(L, 2);
@@ -2645,11 +2483,10 @@ static int _wrap_Hid_report_get(lua_State* L) { int SWIG_arg = 0; Mag_server::Hi
   result = (bool)((Mag_server::Hid_report const *)arg1)->get(arg2,arg3,*arg4); lua_pushboolean(L,(int)(result!=0)); SWIG_arg++;
   return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Hid_report_set(lua_State* L) { int SWIG_arg = 0; Mag_server::Hid_report *arg1 = (Mag_server::Hid_report *) 0 ;
-  unsigned char arg2 ; unsigned int arg3 ; int arg4 ; SWIG_check_num_args("Mag_server::Hid_report::set",4,4)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Hid_report::set",1,"Mag_server::Hid_report *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Hid_report::set",2,"unsigned char");
-  if(!lua_isnumber(L,3)) SWIG_fail_arg("Mag_server::Hid_report::set",3,"unsigned int");
-  if(!lua_isnumber(L,4)) SWIG_fail_arg("Mag_server::Hid_report::set",4,"int");
+  unsigned char arg2 ; unsigned int arg3 ; int arg4 ; SWIG_check_num_args("set",4,4)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("set",1,"Mag_server::Hid_report *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("set",2,"unsigned char"); if(!lua_isnumber(L,3)) SWIG_fail_arg("set",3,"unsigned int");
+  if(!lua_isnumber(L,4)) SWIG_fail_arg("set",4,"int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Hid_report,0))){
     SWIG_fail_ptr("Hid_report_set",1,SWIGTYPE_p_Mag_server__Hid_report); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned char)lua_tointeger(L, 2);
@@ -2658,11 +2495,10 @@ static int _wrap_Hid_report_set(lua_State* L) { int SWIG_arg = 0; Mag_server::Hi
   return SWIG_arg; }
 static int _wrap_Hid_report_mt_get(lua_State* L) { int SWIG_arg = 0;
   Mag_server::Hid_report *arg1 = (Mag_server::Hid_report *) 0 ; unsigned int arg2 ; unsigned int arg3 ; int *arg4 = 0 ;
-  bool result; SWIG_check_num_args("Mag_server::Hid_report::mt_get",4,4)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Hid_report::mt_get",1,"Mag_server::Hid_report const *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Hid_report::mt_get",2,"unsigned int");
-  if(!lua_isnumber(L,3)) SWIG_fail_arg("Mag_server::Hid_report::mt_get",3,"unsigned int");
-  if(!lua_isuserdata(L,4)) SWIG_fail_arg("Mag_server::Hid_report::mt_get",4,"int &");
+  bool result; SWIG_check_num_args("mt_get",4,4)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("mt_get",1,"Mag_server::Hid_report const *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("mt_get",2,"unsigned int");
+  if(!lua_isnumber(L,3)) SWIG_fail_arg("mt_get",3,"unsigned int"); if(!lua_isuserdata(L,4)) SWIG_fail_arg("mt_get",4,"int &");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Hid_report,0))){
     SWIG_fail_ptr("Hid_report_mt_get",1,SWIGTYPE_p_Mag_server__Hid_report); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
@@ -2671,28 +2507,24 @@ static int _wrap_Hid_report_mt_get(lua_State* L) { int SWIG_arg = 0;
   result = (bool)((Mag_server::Hid_report const *)arg1)->mt_get(arg2,arg3,*arg4);
   lua_pushboolean(L,(int)(result!=0)); SWIG_arg++; return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Hid_report_mt_set(lua_State* L) { int SWIG_arg = 0;
-  Mag_server::Hid_report *arg1 = (Mag_server::Hid_report *) 0 ; unsigned int arg2 ; int arg3 ;
-  SWIG_check_num_args("Mag_server::Hid_report::mt_set",3,3)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Hid_report::mt_set",1,"Mag_server::Hid_report *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Hid_report::mt_set",2,"unsigned int");
-  if(!lua_isnumber(L,3)) SWIG_fail_arg("Mag_server::Hid_report::mt_set",3,"int");
+  Mag_server::Hid_report *arg1 = (Mag_server::Hid_report *) 0 ; unsigned int arg2 ; int arg3 ; SWIG_check_num_args("mt_set",3,3)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("mt_set",1,"Mag_server::Hid_report *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("mt_set",2,"unsigned int"); if(!lua_isnumber(L,3)) SWIG_fail_arg("mt_set",3,"int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Hid_report,0))){
     SWIG_fail_ptr("Hid_report_mt_set",1,SWIGTYPE_p_Mag_server__Hid_report); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
   arg3 = (int)lua_tointeger(L, 3); (arg1)->mt_set(arg2,arg3); return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L);
   return SWIG_arg; }
 static int _wrap_Hid_report_submit_mt(lua_State* L) { int SWIG_arg = 0;
-  Mag_server::Hid_report *arg1 = (Mag_server::Hid_report *) 0 ; bool result;
-  SWIG_check_num_args("Mag_server::Hid_report::submit_mt",1,1)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Hid_report::submit_mt",1,"Mag_server::Hid_report *");
+  Mag_server::Hid_report *arg1 = (Mag_server::Hid_report *) 0 ; bool result; SWIG_check_num_args("submit_mt",1,1)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("submit_mt",1,"Mag_server::Hid_report *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Hid_report,0))){
     SWIG_fail_ptr("Hid_report_submit_mt",1,SWIGTYPE_p_Mag_server__Hid_report); }  result = (bool)(arg1)->submit_mt();
   lua_pushboolean(L,(int)(result!=0)); SWIG_arg++; return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Hid_report_get_vals__SWIG_0(lua_State* L) { int SWIG_arg = 0;
   Mag_server::Hid_report *arg1 = (Mag_server::Hid_report *) 0 ; unsigned char arg2 ; Mag_server::Valuator< int > *result = 0 ;
-  SWIG_check_num_args("Mag_server::Hid_report::get_vals",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Hid_report::get_vals",1,"Mag_server::Hid_report const *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Hid_report::get_vals",2,"unsigned char");
+  SWIG_check_num_args("get_vals",2,2) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("get_vals",1,"Mag_server::Hid_report const *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("get_vals",2,"unsigned char");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Hid_report,0))){
     SWIG_fail_ptr("Hid_report_get_vals",1,SWIGTYPE_p_Mag_server__Hid_report); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned char)lua_tointeger(L, 2);
@@ -2701,9 +2533,8 @@ static int _wrap_Hid_report_get_vals__SWIG_0(lua_State* L) { int SWIG_arg = 0;
   lua_error(L); return SWIG_arg; }
 static int _wrap_Hid_report_get_vals__SWIG_1(lua_State* L) { int SWIG_arg = 0;
   Mag_server::Hid_report *arg1 = (Mag_server::Hid_report *) 0 ; unsigned char arg2 ; Mag_server::Valuator< int > *result = 0 ;
-  SWIG_check_num_args("Mag_server::Hid_report::get_vals",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Hid_report::get_vals",1,"Mag_server::Hid_report *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Hid_report::get_vals",2,"unsigned char");
+  SWIG_check_num_args("get_vals",2,2) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("get_vals",1,"Mag_server::Hid_report *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("get_vals",2,"unsigned char");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Hid_report,0))){
     SWIG_fail_ptr("Hid_report_get_vals",1,SWIGTYPE_p_Mag_server__Hid_report); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned char)lua_tointeger(L, 2);
@@ -2719,13 +2550,13 @@ static int _wrap_Hid_report_get_vals(lua_State* L) { int argc; int argv[3]={ 1,2
         _v = 0; }  else { _v = 1; }  }  if (_v) { { _v = lua_isnumber(L,argv[1]); }  if (_v) {
         return _wrap_Hid_report_get_vals__SWIG_0(L);}  }  } 
   lua_pushstring(L,"Wrong arguments for overloaded function 'Hid_report_get_vals'\n" "  Possible C/C++ prototypes are:\n"
-  "    Mag_server::Hid_report::get_vals(unsigned char) const\n" "    Mag_server::Hid_report::get_vals(unsigned char)\n");
+  "    get_vals(Mag_server::Hid_report const *,unsigned char)\n" "    get_vals(Mag_server::Hid_report *,unsigned char)\n");
   lua_error(L);return 0; }
 static int _wrap_Hid_report_get_mt_vals(lua_State* L) { int SWIG_arg = 0;
   Mag_server::Hid_report *arg1 = (Mag_server::Hid_report *) 0 ; unsigned int arg2 ; Mag_server::Valuator< int > *result = 0 ;
-  SWIG_check_num_args("Mag_server::Hid_report::get_mt_vals",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Hid_report::get_mt_vals",1,"Mag_server::Hid_report const *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Hid_report::get_mt_vals",2,"unsigned int");
+  SWIG_check_num_args("get_mt_vals",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("get_mt_vals",1,"Mag_server::Hid_report const *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("get_mt_vals",2,"unsigned int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Hid_report,0))){
     SWIG_fail_ptr("Hid_report_get_mt_vals",1,SWIGTYPE_p_Mag_server__Hid_report); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
@@ -2734,19 +2565,17 @@ static int _wrap_Hid_report_get_mt_vals(lua_State* L) { int SWIG_arg = 0;
   lua_error(L); return SWIG_arg; }
 static int _wrap_Hid_report_add_key(lua_State* L) { int SWIG_arg = 0;
   Mag_server::Hid_report *arg1 = (Mag_server::Hid_report *) 0 ; int arg2 ; int arg3 ; bool result;
-  SWIG_check_num_args("Mag_server::Hid_report::add_key",3,3)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Hid_report::add_key",1,"Mag_server::Hid_report *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Hid_report::add_key",2,"int");
-  if(!lua_isnumber(L,3)) SWIG_fail_arg("Mag_server::Hid_report::add_key",3,"int");
+  SWIG_check_num_args("add_key",3,3) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("add_key",1,"Mag_server::Hid_report *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("add_key",2,"int"); if(!lua_isnumber(L,3)) SWIG_fail_arg("add_key",3,"int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Hid_report,0))){
     SWIG_fail_ptr("Hid_report_add_key",1,SWIGTYPE_p_Mag_server__Hid_report); }  arg2 = (int)lua_tointeger(L, 2);
   arg3 = (int)lua_tointeger(L, 3); result = (bool)(arg1)->add_key(arg2,arg3); lua_pushboolean(L,(int)(result!=0)); SWIG_arg++;
   return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Hid_report_get_key_event(lua_State* L) { int SWIG_arg = 0;
   Mag_server::Hid_report *arg1 = (Mag_server::Hid_report *) 0 ; unsigned int arg2 ;
-  Mag_server::Hid_report::Key_event *result = 0 ; SWIG_check_num_args("Mag_server::Hid_report::get_key_event",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Hid_report::get_key_event",1,"Mag_server::Hid_report const *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Hid_report::get_key_event",2,"unsigned int");
+  Mag_server::Hid_report::Key_event *result = 0 ; SWIG_check_num_args("get_key_event",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("get_key_event",1,"Mag_server::Hid_report const *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("get_key_event",2,"unsigned int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Hid_report,0))){
     SWIG_fail_ptr("Hid_report_get_key_event",1,SWIGTYPE_p_Mag_server__Hid_report); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned int)lua_tointeger(L, 2);
@@ -2755,54 +2584,50 @@ static int _wrap_Hid_report_get_key_event(lua_State* L) { int SWIG_arg = 0;
   fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Hid_report_find_key_event(lua_State* L) { int SWIG_arg = 0;
   Mag_server::Hid_report *arg1 = (Mag_server::Hid_report *) 0 ; int arg2 ; Mag_server::Hid_report::Key_event *result = 0 ;
-  SWIG_check_num_args("Mag_server::Hid_report::find_key_event",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Hid_report::find_key_event",1,"Mag_server::Hid_report const *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Hid_report::find_key_event",2,"int");
+  SWIG_check_num_args("find_key_event",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("find_key_event",1,"Mag_server::Hid_report const *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("find_key_event",2,"int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Hid_report,0))){
     SWIG_fail_ptr("Hid_report_find_key_event",1,SWIGTYPE_p_Mag_server__Hid_report); }  arg2 = (int)lua_tointeger(L, 2);
   result = (Mag_server::Hid_report::Key_event *)((Mag_server::Hid_report const *)arg1)->find_key_event(arg2); if (result) {
     lua_pushinteger(L, result->code); lua_pushinteger(L, result->value); SWIG_arg += 2; }  return SWIG_arg; if(0) SWIG_fail;
   fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Hid_report_remove_key_event(lua_State* L) { int SWIG_arg = 0;
-  Mag_server::Hid_report *arg1 = (Mag_server::Hid_report *) 0 ; int arg2 ;
-  SWIG_check_num_args("Mag_server::Hid_report::remove_key_event",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Hid_report::remove_key_event",1,"Mag_server::Hid_report *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Hid_report::remove_key_event",2,"int");
+  Mag_server::Hid_report *arg1 = (Mag_server::Hid_report *) 0 ; int arg2 ; SWIG_check_num_args("remove_key_event",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("remove_key_event",1,"Mag_server::Hid_report *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("remove_key_event",2,"int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Hid_report,0))){
     SWIG_fail_ptr("Hid_report_remove_key_event",1,SWIGTYPE_p_Mag_server__Hid_report); }  arg2 = (int)lua_tointeger(L, 2);
   (arg1)->remove_key_event(arg2); return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Hid_report_sync(lua_State* L) { int SWIG_arg = 0; Mag_server::Hid_report *arg1 = (Mag_server::Hid_report *) 0 ;
-  long long arg2 ; SWIG_check_num_args("Mag_server::Hid_report::sync",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Hid_report::sync",1,"Mag_server::Hid_report *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Hid_report::sync",2,"long long");
+  long long arg2 ; SWIG_check_num_args("sync",2,2) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("sync",1,"Mag_server::Hid_report *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("sync",2,"long long");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Hid_report,0))){
     SWIG_fail_ptr("Hid_report_sync",1,SWIGTYPE_p_Mag_server__Hid_report); }  arg2 = (long long)lua_tonumber(L, 2);
   (arg1)->sync(arg2); return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Hid_report_time(lua_State* L) { int SWIG_arg = 0; Mag_server::Hid_report *arg1 = (Mag_server::Hid_report *) 0 ;
-  long long result; SWIG_check_num_args("Mag_server::Hid_report::time",1,1)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Hid_report::time",1,"Mag_server::Hid_report const *");
+  long long result; SWIG_check_num_args("time",1,1)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("time",1,"Mag_server::Hid_report const *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Hid_report,0))){
     SWIG_fail_ptr("Hid_report_time",1,SWIGTYPE_p_Mag_server__Hid_report); } 
   result = (long long)((Mag_server::Hid_report const *)arg1)->time(); lua_pushnumber(L, (lua_Number) result); SWIG_arg++;
   return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Hid_report_clear(lua_State* L) { int SWIG_arg = 0;
-  Mag_server::Hid_report *arg1 = (Mag_server::Hid_report *) 0 ; SWIG_check_num_args("Mag_server::Hid_report::clear",1,1)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Hid_report::clear",1,"Mag_server::Hid_report *");
+  Mag_server::Hid_report *arg1 = (Mag_server::Hid_report *) 0 ; SWIG_check_num_args("clear",1,1)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("clear",1,"Mag_server::Hid_report *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Hid_report,0))){
     SWIG_fail_ptr("Hid_report_clear",1,SWIGTYPE_p_Mag_server__Hid_report); }  (arg1)->clear(); return SWIG_arg; if(0) SWIG_fail;
   fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Hid_report_device_id(lua_State* L) { int SWIG_arg = 0;
-  Mag_server::Hid_report *arg1 = (Mag_server::Hid_report *) 0 ; l4_umword_t result;
-  SWIG_check_num_args("Mag_server::Hid_report::device_id",1,1)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Hid_report::device_id",1,"Mag_server::Hid_report const *");
+  Mag_server::Hid_report *arg1 = (Mag_server::Hid_report *) 0 ; l4_umword_t result; SWIG_check_num_args("device_id",1,1)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("device_id",1,"Mag_server::Hid_report const *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Hid_report,0))){
     SWIG_fail_ptr("Hid_report_device_id",1,SWIGTYPE_p_Mag_server__Hid_report); } 
   result = ((Mag_server::Hid_report const *)arg1)->device_id(); lua_pushinteger(L, result); SWIG_arg++; return SWIG_arg;
   if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Hid_report_abs_infos__SWIG_0(lua_State* L) { int SWIG_arg = 0;
   Mag_server::Hid_report *arg1 = (Mag_server::Hid_report *) 0 ; Mag_server::Axis_info_vector *result = 0 ;
-  SWIG_check_num_args("Mag_server::Hid_report::abs_infos",1,1)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Hid_report::abs_infos",1,"Mag_server::Hid_report const *");
+  SWIG_check_num_args("abs_infos",1,1) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("abs_infos",1,"Mag_server::Hid_report const *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Hid_report,0))){
     SWIG_fail_ptr("Hid_report_abs_infos",1,SWIGTYPE_p_Mag_server__Hid_report); } 
   result = (Mag_server::Axis_info_vector *)((Mag_server::Hid_report const *)arg1)->abs_infos();
@@ -2810,8 +2635,7 @@ static int _wrap_Hid_report_abs_infos__SWIG_0(lua_State* L) { int SWIG_arg = 0;
   lua_error(L); return SWIG_arg; }
 static int _wrap_Hid_report_abs_infos__SWIG_1(lua_State* L) { int SWIG_arg = 0;
   Mag_server::Hid_report *arg1 = (Mag_server::Hid_report *) 0 ; Mag_server::Axis_info_vector *result = 0 ;
-  SWIG_check_num_args("Mag_server::Hid_report::abs_infos",1,1)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Hid_report::abs_infos",1,"Mag_server::Hid_report *");
+  SWIG_check_num_args("abs_infos",1,1) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("abs_infos",1,"Mag_server::Hid_report *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Hid_report,0))){
     SWIG_fail_ptr("Hid_report_abs_infos",1,SWIGTYPE_p_Mag_server__Hid_report); } 
   result = (Mag_server::Axis_info_vector *)(arg1)->abs_infos();
@@ -2825,13 +2649,12 @@ static int _wrap_Hid_report_abs_infos(lua_State* L) { int argc; int argv[2]={ 1,
       if (SWIG_isptrtype(L,argv[0])==0 || SWIG_ConvertPtr(L,argv[0], (void **) &ptr, SWIGTYPE_p_Mag_server__Hid_report, 0)) {
         _v = 0; }  else { _v = 1; }  }  if (_v) { return _wrap_Hid_report_abs_infos__SWIG_0(L);}  } 
   lua_pushstring(L,"Wrong arguments for overloaded function 'Hid_report_abs_infos'\n" "  Possible C/C++ prototypes are:\n"
-  "    Mag_server::Hid_report::abs_infos() const\n" "    Mag_server::Hid_report::abs_infos()\n"); lua_error(L);return 0; }
+  "    abs_infos(Mag_server::Hid_report const *)\n" "    abs_infos(Mag_server::Hid_report *)\n"); lua_error(L);return 0; }
 static int _wrap_Hid_report_set_abs_info(lua_State* L) { int SWIG_arg = 0;
   Mag_server::Hid_report *arg1 = (Mag_server::Hid_report *) 0 ;
-  Mag_server::Axis_info_vector *arg2 = (Mag_server::Axis_info_vector *) 0 ;
-  SWIG_check_num_args("Mag_server::Hid_report::set_abs_info",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Hid_report::set_abs_info",1,"Mag_server::Hid_report *");
-  if(!SWIG_isptrtype(L,2)) SWIG_fail_arg("Mag_server::Hid_report::set_abs_info",2,"Mag_server::Axis_info_vector *");
+  Mag_server::Axis_info_vector *arg2 = (Mag_server::Axis_info_vector *) 0 ; SWIG_check_num_args("set_abs_info",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("set_abs_info",1,"Mag_server::Hid_report *");
+  if(!SWIG_isptrtype(L,2)) SWIG_fail_arg("set_abs_info",2,"Mag_server::Axis_info_vector *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Hid_report,0))){
     SWIG_fail_ptr("Hid_report_set_abs_info",1,SWIGTYPE_p_Mag_server__Hid_report); } 
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,2,(void**)&arg2,SWIGTYPE_p_Mag_server__Axis_info_vector,0))){
@@ -2839,9 +2662,8 @@ static int _wrap_Hid_report_set_abs_info(lua_State* L) { int SWIG_arg = 0;
   return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Hid_report___getitem(lua_State* L) { int SWIG_arg = 0;
   Mag_server::Hid_report *arg1 = (Mag_server::Hid_report *) 0 ; unsigned char arg2 ; Mag_server::Valuator< int > *result = 0 ;
-  SWIG_check_num_args("Mag_server::Hid_report::__getitem__",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Hid_report::__getitem__",1,"Mag_server::Hid_report *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::Hid_report::__getitem__",2,"unsigned char");
+  SWIG_check_num_args("__getitem__",2,2) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("__getitem__",1,"Mag_server::Hid_report *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("__getitem__",2,"unsigned char");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Hid_report,0))){
     SWIG_fail_ptr("Hid_report___getitem",1,SWIGTYPE_p_Mag_server__Hid_report); } 
   SWIG_contract_assert((lua_tointeger(L,2)>=0),"number must not be negative") arg2 = (unsigned char)lua_tointeger(L, 2);
@@ -2882,20 +2704,18 @@ static swig_lua_class _wrap_class_Mag_server_Hid_report = { "Hid_report", &SWIGT
 
 static int _wrap_User_state_set_pointer(lua_State* L) { int SWIG_arg = 0;
   Mag_server::User_state *arg1 = (Mag_server::User_state *) 0 ; int arg2 ; int arg3 ; bool arg4 ;
-  SWIG_check_num_args("Mag_server::User_state::set_pointer",4,4)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::User_state::set_pointer",1,"Mag_server::User_state *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::User_state::set_pointer",2,"int");
-  if(!lua_isnumber(L,3)) SWIG_fail_arg("Mag_server::User_state::set_pointer",3,"int");
-  if(!lua_isboolean(L,4)) SWIG_fail_arg("Mag_server::User_state::set_pointer",4,"bool");
+  SWIG_check_num_args("set_pointer",4,4) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("set_pointer",1,"Mag_server::User_state *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("set_pointer",2,"int"); if(!lua_isnumber(L,3)) SWIG_fail_arg("set_pointer",3,"int");
+  if(!lua_isboolean(L,4)) SWIG_fail_arg("set_pointer",4,"bool");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__User_state,0))){
     SWIG_fail_ptr("User_state_set_pointer",1,SWIGTYPE_p_Mag_server__User_state); }  arg2 = (int)lua_tointeger(L, 2);
   arg3 = (int)lua_tointeger(L, 3); arg4 = (lua_toboolean(L, 4)!=0); (arg1)->set_pointer(arg2,arg3,arg4); return SWIG_arg;
   if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_User_state_set_kbd_focus(lua_State* L) { int SWIG_arg = 0;
   Mag_server::User_state *arg1 = (Mag_server::User_state *) 0 ; Mag_server::View_proxy *arg2 = (Mag_server::View_proxy *) 0 ;
-  bool result; SWIG_check_num_args("Mag_server::User_state::set_kbd_focus",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::User_state::set_kbd_focus",1,"Mag_server::User_state *");
-  if(!SWIG_isptrtype(L,2)) SWIG_fail_arg("Mag_server::User_state::set_kbd_focus",2,"Mag_server::View_proxy *");
+  bool result; SWIG_check_num_args("set_kbd_focus",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("set_kbd_focus",1,"Mag_server::User_state *");
+  if(!SWIG_isptrtype(L,2)) SWIG_fail_arg("set_kbd_focus",2,"Mag_server::View_proxy *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__User_state,0))){
     SWIG_fail_ptr("User_state_set_kbd_focus",1,SWIGTYPE_p_Mag_server__User_state); } 
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,2,(void**)&arg2,SWIGTYPE_p_Mag_server__View_proxy,0))){
@@ -2904,13 +2724,11 @@ static int _wrap_User_state_set_kbd_focus(lua_State* L) { int SWIG_arg = 0;
   return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_User_state_post_event(lua_State* L) { int SWIG_arg = 0;
   Mag_server::User_state *arg1 = (Mag_server::User_state *) 0 ; Mag_server::View_proxy *arg2 = (Mag_server::View_proxy *) 0 ;
-  Mag_server::Hid_report *arg3 = (Mag_server::Hid_report *) 0 ; bool arg4 ; bool arg5 ;
-  SWIG_check_num_args("Mag_server::User_state::post_event",5,5)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::User_state::post_event",1,"Mag_server::User_state *");
-  if(!SWIG_isptrtype(L,2)) SWIG_fail_arg("Mag_server::User_state::post_event",2,"Mag_server::View_proxy *");
-  if(!SWIG_isptrtype(L,3)) SWIG_fail_arg("Mag_server::User_state::post_event",3,"Mag_server::Hid_report *");
-  if(!lua_isboolean(L,4)) SWIG_fail_arg("Mag_server::User_state::post_event",4,"bool");
-  if(!lua_isboolean(L,5)) SWIG_fail_arg("Mag_server::User_state::post_event",5,"bool");
+  Mag_server::Hid_report *arg3 = (Mag_server::Hid_report *) 0 ; bool arg4 ; bool arg5 ; SWIG_check_num_args("post_event",5,5)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("post_event",1,"Mag_server::User_state *");
+  if(!SWIG_isptrtype(L,2)) SWIG_fail_arg("post_event",2,"Mag_server::View_proxy *");
+  if(!SWIG_isptrtype(L,3)) SWIG_fail_arg("post_event",3,"Mag_server::Hid_report *");
+  if(!lua_isboolean(L,4)) SWIG_fail_arg("post_event",4,"bool"); if(!lua_isboolean(L,5)) SWIG_fail_arg("post_event",5,"bool");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__User_state,0))){
     SWIG_fail_ptr("User_state_post_event",1,SWIGTYPE_p_Mag_server__User_state); } 
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,2,(void**)&arg2,SWIGTYPE_p_Mag_server__View_proxy,0))){
@@ -2921,18 +2739,17 @@ static int _wrap_User_state_post_event(lua_State* L) { int SWIG_arg = 0;
   fail: lua_error(L); return SWIG_arg; }
 static int _wrap_User_state_toggle_mode(lua_State* L) { int SWIG_arg = 0;
   Mag_server::User_state *arg1 = (Mag_server::User_state *) 0 ; Mag_server::Mode::Mode_flag arg2 ;
-  SWIG_check_num_args("Mag_server::User_state::toggle_mode",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::User_state::toggle_mode",1,"Mag_server::User_state *");
-  if(!lua_isnumber(L,2)) SWIG_fail_arg("Mag_server::User_state::toggle_mode",2,"Mag_server::Mode::Mode_flag");
+  SWIG_check_num_args("toggle_mode",2,2) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("toggle_mode",1,"Mag_server::User_state *");
+  if(!lua_isnumber(L,2)) SWIG_fail_arg("toggle_mode",2,"Mag_server::Mode::Mode_flag");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__User_state,0))){
     SWIG_fail_ptr("User_state_toggle_mode",1,SWIGTYPE_p_Mag_server__User_state); } 
   arg2 = (Mag_server::Mode::Mode_flag)(int)lua_tointeger(L, 2); Mag_server_User_state_toggle_mode(arg1,arg2); return SWIG_arg;
   if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_User_state_find_pointed_view(lua_State* L) { int SWIG_arg = 0;
   Mag_server::User_state *arg1 = (Mag_server::User_state *) 0 ; Mag_server::View_proxy *arg2 = (Mag_server::View_proxy *) 0 ;
-  SWIG_check_num_args("Mag_server::User_state::find_pointed_view",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::User_state::find_pointed_view",1,"Mag_server::User_state *");
-  if(!SWIG_isptrtype(L,2)) SWIG_fail_arg("Mag_server::User_state::find_pointed_view",2,"Mag_server::View_proxy *");
+  SWIG_check_num_args("find_pointed_view",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("find_pointed_view",1,"Mag_server::User_state *");
+  if(!SWIG_isptrtype(L,2)) SWIG_fail_arg("find_pointed_view",2,"Mag_server::View_proxy *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__User_state,0))){
     SWIG_fail_ptr("User_state_find_pointed_view",1,SWIGTYPE_p_Mag_server__User_state); } 
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,2,(void**)&arg2,SWIGTYPE_p_Mag_server__View_proxy,0))){
@@ -2940,8 +2757,8 @@ static int _wrap_User_state_find_pointed_view(lua_State* L) { int SWIG_arg = 0;
   Mag_server_User_state_find_pointed_view(arg1,arg2); return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_User_state_screen_size(lua_State* L) { int SWIG_arg = 0;
   Mag_server::User_state *arg1 = (Mag_server::User_state *) 0 ; int *arg2 = (int *) 0 ; int *arg3 = (int *) 0 ; int temp2 ;
-  int temp3 ; arg2 = &temp2;  arg3 = &temp3;  SWIG_check_num_args("Mag_server::User_state::screen_size",1,1)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::User_state::screen_size",1,"Mag_server::User_state *");
+  int temp3 ; arg2 = &temp2;  arg3 = &temp3;  SWIG_check_num_args("screen_size",1,1)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("screen_size",1,"Mag_server::User_state *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__User_state,0))){
     SWIG_fail_ptr("User_state_screen_size",1,SWIGTYPE_p_Mag_server__User_state); } 
   Mag_server_User_state_screen_size(arg1,arg2,arg3); lua_pushnumber(L, (lua_Number) *arg2); SWIG_arg++;
@@ -2967,17 +2784,17 @@ static const char *swig_Mag_server_User_state_base_names[] = {0};
 static swig_lua_class _wrap_class_Mag_server_User_state = { "User_state", &SWIGTYPE_p_Mag_server__User_state,0, swig_delete_User_state, swig_Mag_server_User_state_methods, swig_Mag_server_User_state_attributes, swig_Mag_server_User_state_bases, swig_Mag_server_User_state_base_names };
 
 static int _wrap_new_View_proxy(lua_State* L) { int SWIG_arg = 0; Mag_server::User_state *arg1 = (Mag_server::User_state *) 0 ;
-  Mag_server::View_proxy *result = 0 ; SWIG_check_num_args("Mag_server::View_proxy::View_proxy",1,1)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::View_proxy::View_proxy",1,"Mag_server::User_state *");
+  Mag_server::View_proxy *result = 0 ; SWIG_check_num_args("Mag_server::View_proxy",1,1)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::View_proxy",1,"Mag_server::User_state *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__User_state,0))){
     SWIG_fail_ptr("new_View_proxy",1,SWIGTYPE_p_Mag_server__User_state); } 
   result = (Mag_server::View_proxy *)new Mag_server::View_proxy(arg1);
   SWIG_NewPointerObj(L,result,SWIGTYPE_p_Mag_server__View_proxy,1); SWIG_arg++;  return SWIG_arg; if(0) SWIG_fail; fail:
   lua_error(L); return SWIG_arg; }
 static int _wrap_View_proxy_set(lua_State* L) { int SWIG_arg = 0; Mag_server::View_proxy *arg1 = (Mag_server::View_proxy *) 0 ;
-  Mag_server::View_proxy *arg2 = (Mag_server::View_proxy *) 0 ; SWIG_check_num_args("Mag_server::View_proxy::set",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::View_proxy::set",1,"Mag_server::View_proxy *");
-  if(!SWIG_isptrtype(L,2)) SWIG_fail_arg("Mag_server::View_proxy::set",2,"Mag_server::View_proxy *");
+  Mag_server::View_proxy *arg2 = (Mag_server::View_proxy *) 0 ; SWIG_check_num_args("set",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("set",1,"Mag_server::View_proxy *");
+  if(!SWIG_isptrtype(L,2)) SWIG_fail_arg("set",2,"Mag_server::View_proxy *");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__View_proxy,0))){
     SWIG_fail_ptr("View_proxy_set",1,SWIGTYPE_p_Mag_server__View_proxy); } 
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,2,(void**)&arg2,SWIGTYPE_p_Mag_server__View_proxy,0))){
@@ -3000,10 +2817,10 @@ static swig_lua_class _wrap_class_Mag_server_View_proxy = { "View_proxy", &SWIGT
 
 static int _wrap_Input_source_get_stream_info(lua_State* L) { int SWIG_arg = 0;
   Mag_server::Input_source *arg1 = (Mag_server::Input_source *) 0 ; l4_umword_t arg2 ;
-  L4Re::Event_stream_info **arg3 = (L4Re::Event_stream_info **) 0 ; L4Re::Event_stream_info *temp3 ; int result;
-  temp3 = (L4Re::Event_stream_info *)0; arg3 = &temp3;  SWIG_check_num_args("Mag_server::Input_source::get_stream_info",2,2)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Input_source::get_stream_info",1,"Mag_server::Input_source *");
-  if(!lua_isuserdata(L,2)) SWIG_fail_arg("Mag_server::Input_source::get_stream_info",2,"l4_umword_t");
+  L4Re::Event_stream_info **arg3 = (L4Re::Event_stream_info **) 0 ; L4Re::Event_stream_info *temp3 ; int result; arg3 = &temp3; 
+  SWIG_check_num_args("get_stream_info",2,2)
+  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("get_stream_info",1,"Mag_server::Input_source *");
+  if(!lua_isuserdata(L,2)) SWIG_fail_arg("get_stream_info",2,"l4_umword_t");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Input_source,0))){
     SWIG_fail_ptr("Input_source_get_stream_info",1,SWIGTYPE_p_Mag_server__Input_source); } 
   arg2 = (l4_umword_t)lua_touserdata(L, 2);  result = (int)Mag_server_Input_source_get_stream_info(arg1,arg2,arg3);
@@ -3011,11 +2828,10 @@ static int _wrap_Input_source_get_stream_info(lua_State* L) { int SWIG_arg = 0;
   return SWIG_arg; if(0) SWIG_fail; fail: lua_error(L); return SWIG_arg; }
 static int _wrap_Input_source_get_abs_info(lua_State* L) { int SWIG_arg = 0;
   Mag_server::Input_source *arg1 = (Mag_server::Input_source *) 0 ; l4_umword_t arg2 ; unsigned int arg3 ;
-  Mag_server::Axis_info **arg4 = (Mag_server::Axis_info **) 0 ; Mag_server::Axis_info *temp4 ; int result;
-  temp4 = (Mag_server::Axis_info *)0; arg4 = &temp4;  SWIG_check_num_args("Mag_server::Input_source::get_abs_info",3,3)
-  if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("Mag_server::Input_source::get_abs_info",1,"Mag_server::Input_source *");
-  if(!lua_isuserdata(L,2)) SWIG_fail_arg("Mag_server::Input_source::get_abs_info",2,"l4_umword_t");
-  if(!lua_isnumber(L,3)) SWIG_fail_arg("Mag_server::Input_source::get_abs_info",3,"unsigned int");
+  Mag_server::Axis_info **arg4 = (Mag_server::Axis_info **) 0 ; Mag_server::Axis_info *temp4 ; int result; arg4 = &temp4; 
+  SWIG_check_num_args("get_abs_info",3,3) if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("get_abs_info",1,"Mag_server::Input_source *");
+  if(!lua_isuserdata(L,2)) SWIG_fail_arg("get_abs_info",2,"l4_umword_t");
+  if(!lua_isnumber(L,3)) SWIG_fail_arg("get_abs_info",3,"unsigned int");
   if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_Mag_server__Input_source,0))){
     SWIG_fail_ptr("Input_source_get_abs_info",1,SWIGTYPE_p_Mag_server__Input_source); } 
   arg2 = (l4_umword_t)lua_touserdata(L, 2);  SWIG_contract_assert((lua_tointeger(L,3)>=0),"number must not be negative")
@@ -3046,7 +2862,7 @@ static int _wrap_get_user_state(lua_State* L) { int SWIG_arg = 0; Mag_server::Us
 // removed: }
 #endif
 
-static const struct luaL_Reg swig_commands[] = {
+static const struct luaL_reg swig_commands[] = {
     { "get_user_state", _wrap_get_user_state},
     {0,0}
 };
@@ -3391,24 +3207,16 @@ void SWIG_init_user(lua_State* L );
 #endif
 /* this is the initialization function
   added at the very end of the code
-  the function is always called SWIG_init, but an earlier #define will rename it
+  the function is always called SWIG_init, but an eariler #define will rename it
 */
-#if ((SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUA) || (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUAC))
-LUALIB_API int SWIG_init(lua_State* L)
-#else
-SWIGEXPORT int SWIG_init(lua_State* L) /* default Lua action */
-#endif
+SWIGEXPORT int SWIG_init(lua_State* L)
 {
-#if (SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUAC) /* valid for both Lua and eLua */
   int i;
   /* start with global table */
-  lua_pushglobaltable (L);
+  lua_pushvalue(L,LUA_GLOBALSINDEX);
   /* SWIG's internal initalisation */
   SWIG_InitializeModule((void*)L);
   SWIG_PropagateClientData();
-#endif
-
-#if ((SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUA) && (SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUAC))
   /* add a global fn */
   SWIG_Lua_add_function(L,"swig_type",SWIG_Lua_type);
   SWIG_Lua_add_function(L,"swig_equals",SWIG_Lua_equal);
@@ -3422,10 +3230,7 @@ SWIGEXPORT int SWIG_init(lua_State* L) /* default Lua action */
   for (i = 0; swig_variables[i].name; i++){
     SWIG_Lua_module_add_variable(L,swig_variables[i].name,swig_variables[i].get,swig_variables[i].set);
   }
-#endif
-
-#if (SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUAC)
-  /* set up base class pointers (the hierarchy) */
+  /* set up base class pointers (the hierachy) */
   for (i = 0; swig_types[i]; i++){
     if (swig_types[i]->clientdata){
       SWIG_Lua_init_base_class(L,(swig_lua_class*)(swig_types[i]->clientdata));
@@ -3437,24 +3242,14 @@ SWIGEXPORT int SWIG_init(lua_State* L) /* default Lua action */
       SWIG_Lua_class_register(L,(swig_lua_class*)(swig_types[i]->clientdata));
     }
   }
-#endif
-
-#if ((SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUA) && (SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUAC))
   /* constants */
   SWIG_Lua_InstallConstants(L,swig_constants);
-#endif
-
-#if (SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUAC)
   /* invoke user-specific initialization */
   SWIG_init_user(L);
   /* end module */
-  /* Note: We do not clean up the stack here (Lua will do this for us). At this
-     point, we have the globals table and out module table on the stack. Returning
-     one value makes the module table the result of the require command. */
+  lua_pop(L,1);  /* tidy stack (remove module table)*/
+  lua_pop(L,1);  /* tidy stack (remove global table)*/
   return 1;
-#else
-  return 0;
-#endif
 }
 
 #ifdef __cplusplus
index 838800cdd3b8c782928333e087f8f6b32de997bd..c1bb45d091ec2fb112efc9f09a3b19cc705bf73d 100644 (file)
@@ -1,4 +1,4 @@
 requires: libudis86 stdlibs libiniparser cxx_io libio-vbus libstdc++ 
-           libvcpu libloader liblwip_netif_ankh zlib
+           libvcpu libloader zlib
 provides: romain libpthread_rep libuu libevbuf_c
 maintainer: doebel@os.inf.tu-dresden.de
index f0cb249027a1e0175639cd12580775afaec0cef5..8d5a6fbce19b2c6ebe4781a6be96dfd9d0bdbad3 100644 (file)
@@ -26,11 +26,20 @@ fas_uint(volatile unsigned int *lock, unsigned int val)
 }
 
 
+#ifdef PT_SOLO
+#include <l4/util/util.h>
+static inline void
+stall(void)
+{
+       l4_thread_yield();
+}
+#else
 static inline void
 stall(void)
 {
        asm volatile ("ud2" ::: "memory");
 }
+#endif
 
 
 enum {
@@ -66,11 +75,24 @@ typedef struct {
 } lock_info;
 
 /* Compile-time assertion: lock_info must fit into a page) */
-char __lock_info_size_valid[!!(sizeof(lock_info) <= L4_PAGESIZE)-1];
+static char __lock_info_size_valid[!!(sizeof(lock_info) <= L4_PAGESIZE)-1];
 
-lock_info* get_lock_info(void);
-lock_info* get_lock_info(void) {
-       return (lock_info*)LOCK_INFO_ADDR;
+static inline lock_info* get_lock_info(void)
+{
+       static lock_info* __lip_address = (lock_info*)LOCK_INFO_ADDR;
+#ifdef PT_SOLO
+       static lock_info lip;
+       static int init = 0;
+       if (!init) {
+               init = 1;
+               lip.replica_count = 1;
+               memset(&lip.trampolines, 0, NUM_TRAMPOLINES * TRAMPOLINE_SIZE);
+               lip.locks[0].owner    = 0xDEADBEEF;
+               lip.locks[0].lockdesc = 0xFAFAFAFA;
+       }
+       __lip_address = &lip;
+#endif
+       return __lip_address;
 }
 
 
index 22e585f49aee5addd264507309759bb8c80a0d4c..4658b64616a4d694ac91ae2c57f627b7dabcdc7e 100644 (file)
@@ -44,7 +44,7 @@ PRIVATE_INCDIR = -I- $(SRC_DIR) $(ORIGDIR) $(INCDIR-$(ARCH)) $(CONTRIBDIR)/ldso/
 
 DEFINES   := -DL4_THREAD_SAFE -D__USE_XOPEN2K -D_POSIX_C_SOURCE=200112L \
              -D_GNU_SOURCE=1 -D__NO_WEAK_PTHREAD_ALIASES=1 \
-            -D_LIBC=1 -DIS_IN_libpthread=1 -DNOT_IN_libc=1
+                -D_LIBC=1 -DIS_IN_libpthread=1 -DNOT_IN_libc=1 #-DPT_SOLO
 
 DEFINES_x86-l4f   := -DUSE___THREAD=1 
 #DEFINES_amd64-l4f := -DUSE___THREAD=1 
index d2967fba158efaa50b5171448be679aa259e45a6..388ea6152ce2bc2cdc8dbe125a7bfb924f128ec6 100644 (file)
@@ -36,6 +36,8 @@
 int pthread_mutex_lock_rep(pthread_mutex_t * mutex);
 int pthread_mutex_unlock_rep(pthread_mutex_t * mutex);
 
+lock_info* __lip_address = LOCK_INFO_ADDR;
+
 
 #define LOCKli(li, mtx) (li)->locks[(mtx)->__m_reserved]
 #define ACQ(li, mtx)    lock_li(  (li), (mtx)->__m_reserved)
@@ -63,6 +65,7 @@ int pthread_mutex_unlock_rep(pthread_mutex_t * mutex);
  */
 static inline void rep_function_save_regs(void)
 {
+#if 0
   BARRIER();
   asm volatile ("mov %%ebx, %0\t\n"
                 "mov %%ecx, %1\t\n"
@@ -78,13 +81,15 @@ static inline void rep_function_save_regs(void)
                 :
                 : "memory"
   );
+  BARRIER();
+#endif
 }
 
 
 static inline void rep_function_restore_regs(void)
 {
-  
   BARRIER();
+#if 0
   asm volatile ("mov %0, %%ebx\t\n"
                 "mov %1, %%ecx\t\n"
                 "mov %2, %%edx\t\n"
@@ -99,14 +104,25 @@ static inline void rep_function_restore_regs(void)
                   "m" (thread_self()->edi)*/
                 : "memory"
   );
+#else
+  asm volatile ("mov $0, %%ebx\t\n"
+                "mov $0, %%ecx\t\n"
+                "mov $0, %%edx\t\n"
+                ::: "memory");
+#endif
+  BARRIER();
 }
 
+#ifdef PT_SOLO
+#define yield stall
+#else
 static inline void yield()
 {
        rep_function_restore_regs();
        asm volatile ("ud2" : : : "edx", "ecx", "ebx", "memory");
        rep_function_save_regs();
 }
+#endif
 
 
 static inline void lock_rep_wait(pthread_mutex_t* mutex)
@@ -207,6 +223,7 @@ int
 attribute_hidden
 pthread_mutex_lock_rep(pthread_mutex_t * mutex)
 {
+
   rep_function_save_regs();
   
        /*
@@ -286,7 +303,7 @@ pthread_mutex_unlock_rep(pthread_mutex_t * mutex)
       LOCKli(li, mutex).owner = lock_unowned;
   }
 
-  EVENT(mutex, 5, LOCKli(li, mutex).owner, thread_self()->p_epoch);
+  EVENT(mutex, 5, thread_self()->p_epoch, LOCKli(li, mutex).owner);
 
   REL(li, mutex);
 
index 48f4adbf34bc927ee55cb6304f023135dbed3065..83b40dc4c943e48a871ba50f0b7ec66d1f0af189 100644 (file)
@@ -62,8 +62,7 @@ l4_addr_t Romain::App_model::local_attach_ds(Romain::App_model::Const_dataspace
        }
        Romain::Region_handler handler(ds, L4_INVALID_CAP, offset, 0,
                                    Romain::Region(0, 0));
-       l4_addr_t ret = (l4_addr_t)rm()->attach_locally((void*)0xdeadbeef,
-                                                       size, &handler, flags);
+       l4_addr_t ret = (l4_addr_t)rm()->attach_locally((void*)0, size, &handler, flags);
        return ret;
 }
 
index b68f74b39f2df59c1e3a23c13d49927178a74375..7653c62d8597cfda81fe729012c9c0d387789406 100644 (file)
@@ -279,13 +279,22 @@ Romain::Thread_group::control(Romain::App_thread *t, l4_utcb_t *utcb, Romain::Ap
                l4_addr_t utcb_remote = l4_utcb_mr_u(utcb)->mr[L4_THREAD_CONTROL_MR_IDX_BIND_UTCB];
                DEBUG() << "Setting remote UTCB to " << (void*)utcb_remote;
 
-               Romain::App_model::Dataspace ds = am->alloc_ds(L4_PAGESIZE); // thread info page
-               l4_addr_t local_addr = am->local_attach_ds(ds, L4_PAGESIZE, 0);
+               L4::Cap<L4Re::Dataspace> mem;
+               Romain::Region_map::allocate_ds(&mem, L4_PAGESIZE);
+               l4_addr_t local_addr = Romain::Region_map::allocate_and_attach(&mem, L4_PAGESIZE, 0, 0);
                DEBUG() << "Attached TIP to " << (void*)local_addr;
 
+               /* store UTCB address in TIP */
                *reinterpret_cast<l4_umword_t*>(local_addr) = utcb_remote;
-               void* tip_addr = am->prog_attach_ds(0, L4_PAGESIZE, ds, 0,
-                                                                                       L4Re::Rm::Search_addr, "thread info page", local_addr);
+
+               am->rm()->activate(0);
+               void* tip_addr = (void*)0x10000;
+               tip_addr = am->rm()->attach(tip_addr, L4_PAGESIZE,
+                                           Romain::Region_handler(mem, L4_INVALID_CAP, 0,
+                                                                  0, Romain::Region(local_addr, local_addr + L4_PAGESIZE - 1)),
+                                           L4Re::Rm::Search_addr, L4_PAGESHIFT, false);
+               am->rm()->release();
+
                DEBUG() << "Remote TIP address: " << tip_addr;
 
                for (unsigned i = 0; i < threads.size(); ++i) {
index 87c230e91c996470b67ce5415c2b4b56fbaafb0c..de1b00c764f483e13eb198db440d008d03179a0e 100644 (file)
@@ -22,6 +22,8 @@ EXTERN_C_BEGIN
 #include <l4/plr/pthread_rep.h>
 EXTERN_C_END
 
+lock_info* __lip_address = reinterpret_cast<lock_info*>(LOCK_INFO_ADDR);
+
 namespace Romain
 {
        /*
index 2492ffb1204e5e24de60a7d2b92b08a9fd2310a4..14d4798a3833ecab1ab424ec6957c1161fe93f85 100644 (file)
@@ -99,6 +99,7 @@ Romain::PageFaultObserver::notify(Romain::App_instance *i, Romain::App_thread *t
                enter_kdebug("unhandled pf");
        }
 
+       Romain::Observer::ObserverReturnVal retVal = Romain::Observer::Finished;
        L4vcpu::Vcpu *vcpu = t->vcpu();
 
        bool write_pf = vcpu->r()->err & 0x2;
@@ -119,8 +120,7 @@ Romain::PageFaultObserver::notify(Romain::App_instance *i, Romain::App_thread *t
        Romain::Region_map::Base::Node n = a->rm()->find(pfa);
        MSGt(t) << "rm_find(" << std::hex << pfa << ") = " << n;
        if (n) {
-               a->rm()->lazy_map_region(n, i->id());
-
+               const_cast<Romain::Region_handler&>(n->second).count_pf();
                /*
                 * Lazily establish region handlers for replicas
                 */
@@ -154,37 +154,69 @@ Romain::PageFaultObserver::notify(Romain::App_instance *i, Romain::App_thread *t
                        ++pf_mapped;
 
                        Romain::Region_handler const * rh   = &n->second;
-                       Romain::Region const * localregion  = &rh->local_region(i->id());
                        L4Re::Util::Region const * remote   = &n->first;
-
-                       /*
-                        * We try to map the largest possible flexpage to reduce the
-                        * total number of mappings.
-                        */
-                       l4_addr_t offset_in_region = l4_trunc_page(pfa - remote->start());
-                       l4_umword_t align = fit_alignment(localregion, remote, offset_in_region, t);
-                       MSGt(t) << "fitting align " << align;
-
-                       /* Calculate the map base addresses for the given alignment */
-                       l4_addr_t localbase = localregion->start() + offset_in_region;
-                       localbase  = localbase  - (localbase  & ((1 << align) - 1));
-
-                       l4_addr_t remotebase = remote->start() + offset_in_region;
-                       remotebase = remotebase - (remotebase & ((1 << align) - 1));
-
-                       MSGt(t) << std::hex << "map: " << localbase << " -> "
-                               << remotebase << " size " << (1 << align);
-
-                       //enter_kdebug("pf");
-                       
-                       // set flags properly, only check ro(), because else we'd already ended
-                       // up in the emulation branch above
-                       unsigned pageflags           = rh->is_ro() ? L4_FPAGE_RO : L4_FPAGE_RW;
-
-                       ev->data.pf.localbase  = localregion->start() + offset_in_region;
-                       ev->data.pf.remotebase = remote->start() + offset_in_region;
-
-                       i->map_aligned(localbase, remotebase, align, pageflags);
+                       l4_addr_t offset_in_region          = l4_trunc_page(pfa - remote->start());
+                       l4_addr_t remotebase                = remote->start() + offset_in_region;
+                       unsigned pageflags                  = rh->is_ro() ? L4_FPAGE_RO : L4_FPAGE_RW;
+
+                       for (l4_umword_t instID = 0;
+                            instID < Romain::_the_instance_manager->instance_count();
+                            ++instID) {
+
+                               a->rm()->lazy_map_region(n, instID, write_pf);
+
+                               Romain::Region const * localregion  = &rh->local_region(instID);
+                               /*
+                                * We try to map the largest possible flexpage to reduce the
+                                * total number of mappings.
+                                */
+                               l4_umword_t align = fit_alignment(localregion, remote, offset_in_region, t);
+
+                               /*
+                                * For replicas we unfortunately only have the guarantee that they
+                                * are aligned to rh->alignment(). Apart from this, the replica's region
+                                * copies may be aligned differently in the master.
+                                *
+                                * Example:
+                                *   - rh->alignment() = 64kB
+                                *   - replica1.alignment = 128 kB
+                                *   - replica2.alignment = 2 MB
+                                *
+                                * ==> Here, we may encounter a situation where a page fault can be
+                                *     serviced with a 256 kB mapping for replica 1 and a 1 MB mapping
+                                *     for replica 2. The replicas will thereafter diverge.
+                                *
+                                * Quickfix: we make sure that memory mappings are at most rh->alignment().
+                                *
+                                * Better fix: the PF observer should walk over all replicas and determine
+                                *             the minimum possible alignment for this specific mapping.
+                                */
+                               if (align > rh->alignment()) {
+                                       align = rh->alignment();
+                               }
+                               MSGt(t) << "fitting align " << align;
+
+                               /* Calculate the map base addresses for the given alignment */
+                               l4_addr_t localbase = localregion->start() + offset_in_region;
+                               localbase  = localbase  - (localbase  & ((1 << align) - 1));
+
+                               remotebase = remotebase - (remotebase & ((1 << align) - 1));
+
+                               MSGt(t) << std::hex << "map: " << localbase << " -> "
+                                               << remotebase << " size " << (1 << align);
+
+                               //enter_kdebug("pf");
+                               
+                               // set flags properly, only check ro(), because else we'd already ended
+                               // up in the emulation branch above
+                               ev->data.pf.localbase  = localregion->start() + offset_in_region;
+                               ev->data.pf.remotebase = remote->start() + offset_in_region;
+
+                               Romain::_the_instance_manager->instance(instID)->map_aligned(localbase,
+                                                                                                                                                        remotebase,
+                                                                                                                                                        align, pageflags);
+                       }
+                       retVal = Romain::Observer::Replicatable;
                }
 
        } else if ((a->prog_info()->kip <= pfa) && (pfa < a->prog_info()->kip + L4_PAGESIZE)) {
@@ -206,7 +238,7 @@ Romain::PageFaultObserver::notify(Romain::App_instance *i, Romain::App_thread *t
         */
        MSGt(t) << "Page faults so far: mapped " << pf_mapped << " write emu " << pf_write << " kip " << pf_kip;
 
-       return Romain::Observer::Finished;
+       return retVal;
 }
 
 
index 2371c840dab94b3af5a2487e62518c77685db41d..4a2874e02dc65dd9b29362a1610a239de9e7bb75 100644 (file)
@@ -36,6 +36,8 @@ void *to_thread(void *arg)
        if (o->want_cancel())
                return NULL;
 
+       l4_debugger_set_object_name(pthread_getl4cap(pthread_self()), "romain::timout");
+
        Measurements::GenericEvent* ev = Romain::_the_instance_manager->logbuf()->next();
        ev->header.tsc                 = Romain::_the_instance_manager->logbuf()->getTime(Romain::Log::logLocalTSC);
        ev->header.vcpu                = (l4_uint32_t)0xDEADBEEF;
index d614881826d2f097eb91b2bd5b6c98cf6388ffee..e59714175f413250440d748e595e854f08bbb3f7 100644 (file)
@@ -267,6 +267,7 @@ Romain::RegionManagingHandler::handle(Romain::App_instance* i,
                Romain::Rm_guard r(a->rm(), i->id());
                L4::Ipc::Iostream ios(utcb);
                L4Re::Util::region_map_server<Romain::Region_map_server>(a->rm(), ios);
+               t->vcpu()->r()->ax = 0;
        }
 
        //t->print_vcpu_state();
index 8e3602af35b25d3d6725eb659d29893fc426e33f..e4e2ef26e060b47d83e5144e1cffa2c918b688e6 100644 (file)
@@ -61,6 +61,8 @@ namespace Romain
 
                static void* topology_scanner(void* data)
                {
+                       l4_debugger_set_object_name(pthread_getl4cap(pthread_self()), "romain::topscan");
+
                        for (unsigned cpu = 0; cpu < CPUID::num_cpus(); ++cpu) {
                                Romain::LogicalCPUMap *m = reinterpret_cast<Romain::LogicalCPUMap*>(data);
 
@@ -87,6 +89,11 @@ namespace Romain
                        int ret = pthread_create(&p, 0, Romain::LogicalCPUMap::topology_scanner, this);
                        _check(ret != 0, "error creating topology scanner");
                        ret = pthread_join(p, 0);
+
+                       for (unsigned i = CPUID::num_cpus(); i < MAX_CPUS; ++i) {
+                               _fiasco_cpus[i].apic_id = 0xDEADBEEF;
+                       }
+
                        INFO() << "Topology scan completed.";
                }
 
@@ -303,6 +310,9 @@ namespace Romain
                                logdump();
                        }
 
+                       Romain::App_instance* instance(unsigned idx)
+                       { return _instances[idx]; }
+
                        static void VCPU_handler(Romain::InstanceManager *m, Romain::App_instance *i, Romain::App_thread *t, Romain::Thread_group* tg, Romain::App_model *a);
                        static void VCPU_startup(Romain::InstanceManager *m, Romain::App_instance *i, Romain::App_thread *t, Romain::Thread_group* tg, Romain::App_model *a);
 
index 4d8c38d2fa4f7ed57d9ee437e800393479e421ab..b8cfda3ed40c060b2975c0256b5db9dd62221e42 100644 (file)
@@ -196,9 +196,11 @@ void Romain::InstanceManager::configure_logbuf(int sizeMB)
 
        L4::Cap<L4Re::Dataspace> ds;
 
-       l4_addr_t addr = Romain::Region_map::allocate_and_attach(&ds, size_in_bytes, 0, L4_SUPERPAGESHIFT);
+       l4_addr_t addr = Romain::Region_map::allocate_and_attach(&ds, size_in_bytes,
+                                                                                                                        0, 0, L4_SUPERPAGESHIFT);
     INFO() << "Log buffer attached to 0x" << std::hex << addr;
 
+    memset((void*)addr, 0, size_in_bytes);
     _logBuf->set_buffer(reinterpret_cast<unsigned char*>(addr), size_in_bytes);
 }
 
@@ -480,17 +482,38 @@ Romain::InstanceManager::create_thread(l4_umword_t eip, l4_umword_t esp,
                        
                        /* XXX Threads assigned RR to CPUs */
                        static int threadcount = 0;
-                       logCPU = logicalToCPU(threadcount % _num_cpu);
-                       threadcount++;
-
-                       /* XXX The hard-coded placement map */
-                       //int cpumap[12] = {0, 1, 2,
-                       //                  0, 0, 0,
-                       //                  3, 4, 5,
-                       //                  0, 0, 0};
-                       //logCPU = logicalToCPU(cpumap[threadcount]);
+                       //logCPU = logicalToCPU(threadcount % _num_cpu);
                        //threadcount++;
 
+                       /* XXX The hard-coded placement map:
+                        * Manual optimization for pthreads applications. In our scenarios,
+                        * pthreads starts a manager as the second thread and this manager
+                        * often does nothing. Therefore, instead of placing each idle manager
+                        * replica on its own CPU, we simply put them onto CPU0 where they
+                        * don't hurt anyone.
+                        */
+                       int cpumap[3][15] = { // single -> 1:1 mapping
+                                             {0, 1, 2,
+                                              3, 4, 5,
+                                              6, 7, 8,
+                                              9, 10, 11,
+                                              0, 1, 2},
+                                                                 // DMR
+                                             {0, 1, 0,
+                                              0, 2, 3,
+                                              4, 5, 6,
+                                              7, 8, 9,
+                                             10, 11, 0},
+                                                                 // TMR
+                                             {0, 1, 2,
+                                              0, 0, 0,
+                                              3, 4, 5,
+                                              6, 7, 8,
+                                              9, 10, 11}
+                                            };
+                       logCPU = logicalToCPU(cpumap[instance_count()-1][threadcount]);
+                       threadcount++;
+
                        at->cpu(logCPU);
                } else {
                        at->cpu(0);
index 07d282a9fbe1e77aebc42d8b3359d01d68a6ee56..c592fda762b110a2008edf029d245f37297f6543 100644 (file)
@@ -28,6 +28,7 @@
 #include <l4/re/util/region_mapping>
 #include <l4/re/util/dataspace_svr>
 #include <l4/util/bitops.h>
+#include <l4/util/rdtsc.h>
 
 #include <l4/sys/kdebug.h>
 
@@ -146,23 +147,26 @@ namespace Romain
                        };
 
                private:
-                       l4_cap_idx_t             _cap;       // capability of the underlying dataspace
+                       l4_cap_idx_t             _cap;        // capability of the underlying dataspace
                        Romain::Region            _local_regions[Romain::MAX_REPLICAS]; // replicated regions (writable regions exist in
                                                                                            // multiple instances)
-                       l4_addr_t                _offs;      // offset in DS
+                       l4_addr_t                _offs;       // offset in DS
                        DS                       _mem[Romain::MAX_REPLICAS]; // DS capabilities of underlying dataspaces
-                       unsigned char            _flags;     // region flags
-                       RegionWritableType       _row;       // rw state
-                       bool                     _shared;    // is DS shared across all replicas
-                                                            // (true for internal determinism's lock info page)
-                       l4_umword_t              _alignment; // alignment of this DS within master
+                       unsigned char            _flags;      // region flags
+                       RegionWritableType       _row;        // rw state
+                       bool                     _shared;     // is DS shared across all replicas
+                                                             // (true for internal determinism's lock info page)
+                       l4_umword_t              _alignment;  // alignment of this DS within master
+                       l4_umword_t              _align_diff; // diff between alignment and real start address
+                                                             // (see Region_map::attach_locally() for an explanation)
+                       l4_umword_t              _numpf;      // page faults seen on this region
 
                public:
 
                        Region_handler_template()
                                : _cap(L4_INVALID_CAP),  _offs(0), _flags(),
                              _row(Romain::Region_handler_template<DS, OPS>::Read_only),
-                             _shared(false), _alignment(L4_PAGESHIFT)
+                             _shared(false), _alignment(L4_PAGESHIFT), _align_diff(0), _numpf(0)
                        {}
 
 
@@ -172,7 +176,9 @@ namespace Romain
                                  _flags(o.flags()),
                                  _row(o.writable()),
                                  _shared(o.shared()),
-                                 _alignment(o.alignment())
+                                 _alignment(o.alignment()),
+                                 _align_diff(o.align_diff()),
+                                 _numpf(o.numpf())
                        {
                                for (unsigned i = 0; i < o.local_region_count(); ++i) {
                                        _local_regions[i] = o.local_region(i);
@@ -182,7 +188,8 @@ namespace Romain
 
                        Region_handler_template(DSCAP cap, l4_cap_idx_t client_cap = L4_INVALID_CAP, l4_addr_t offset = 0,
                                                unsigned flags = 0, Romain::Region local_reg = Romain::Region(0,0))
-                               : _cap(client_cap), _offs(offset), _flags(flags), _shared(false), _alignment(L4_PAGESHIFT)
+                               : _cap(client_cap), _offs(offset), _flags(flags), _shared(false),
+                                 _alignment(L4_PAGESHIFT), _align_diff(0), _numpf(0)
                        {
                                _local_regions[0] = local_reg;
                                _mem[0]           = cap;
@@ -229,7 +236,10 @@ namespace Romain
 
                        bool         shared() const throw()                 { return _shared; }
                        void         shared(bool yn) { _shared = yn; }
-                       l4_umword_t  alignment() const throw()                          { return _alignment; }
+                       l4_addr_t    alignment() const throw()                          { return _alignment; }
+                       l4_addr_t    align_diff() const throw()             { return _align_diff; }
+                       l4_umword_t  numpf() const throw()                  { return _numpf; }
+                       void         count_pf() throw()                     { _numpf++; }
 
                        /* Compute the target alignment for attaching locally.
                         *
@@ -240,19 +250,36 @@ namespace Romain
                         */
                        void alignToAddressAndSize(l4_addr_t address, l4_size_t size)
                        {
-                               _alignment = l4util_bsf(address);
-                               DEBUG() << std::hex << address << " --> target alignment: "
-                                       << _alignment;
-                               if (_alignment > L4_SUPERPAGESHIFT) {
-                                       _alignment = L4_SUPERPAGESHIFT;
+                               enum {
+                                       MIN_ALIGNMENT = 
+                                       //12, /* 4 kB -> minimum! */
+                                       //16, /* 64 kB */
+                                           //19, /* 512 kB */
+                                       22, /* 4 MB */
+                               };
+
+                               DEBUG() << "alignToAddressAndSize(" << std::hex << address
+                                       << ", " << size << ")";
+
+                               l4_addr_t min_align = MIN_ALIGNMENT;
+                               if (size < (1 << MIN_ALIGNMENT)) {
+                                       min_align = l4util_bsr(size);
                                }
-                               DEBUG() << std::hex << address << " --> [max: super page] alignment: "
-                                       << _alignment;
-                               if (_alignment > l4util_bsr(size)) {
-                                       _alignment = l4util_bsr(size);
+                               DEBUG() << "Minimum alignment: " << std::hex << min_align;
+
+                               if (min_align > L4_SUPERPAGESHIFT) {
+                                       min_align = L4_SUPERPAGESHIFT;
                                }
-                               DEBUG() << std::hex << address << " --> [max: size " << size
-                                       << "] alignment: " << _alignment;
+                               DEBUG() << std::hex << address
+                                       << " --> [max: super page] alignment: "
+                                       << min_align;
+
+                               _alignment             = min_align;
+                               l4_umword_t align_mask = (1 << _alignment) - 1;
+                               _align_diff            = address & align_mask;
+                               DEBUG() << std::hex << address << " --> align diff =  "
+                                       << align_diff();
+
                        }
 
                        void         take() const                           { Ops::take(this); }
@@ -306,12 +333,14 @@ namespace Romain
                : public L4Re::Util::Region_map<Romain::Region_handler,
                                                Romain::Allocator>
        {
+               pthread_mutex_t _mtx;
                public:
                        typedef L4Re::Util::Region_map<Romain::Region_handler, Romain::Allocator> Base;
                        enum { Invalid_inst = ~0U };
 
                        void activate(unsigned inst)
                        {
+                               pthread_mutex_lock(&_mtx);
                                _check(_active_instance != Invalid_inst, "rm already used, lock!!!");
                                _active_instance = inst;
                        }
@@ -319,6 +348,7 @@ namespace Romain
                        void release()
                        {
                                _active_instance = Invalid_inst;
+                               pthread_mutex_unlock(&_mtx);
                        }
 
                        /*
@@ -343,20 +373,31 @@ namespace Romain
 
                        bool copy_existing_mapping(Romain::Region_handler& r,
                                                   unsigned orig_id,
-                                                  unsigned inst_id) const
+                                                  unsigned inst_id,
+                                                  bool writepf = false) const
                        {
                                if (orig_id == inst_id) return true;
 
                                L4::Cap<L4Re::Dataspace> mem;
                                unsigned long size = r.local_region(orig_id).size();
 
-                               l4_addr_t a = Romain::Region_map::allocate_and_attach(&mem, size, 0, r.alignment());
+                               DEBUG() << "copy existing: " << std::hex << r.alignment()
+                                       << " diff " << r.align_diff();
+                               l4_addr_t a = Romain::Region_map::allocate_and_attach(&mem, size,
+                                                                                 0,  0,
+                                                                                 r.alignment(),
+                                                                                 r.align_diff());
                                _check(a == 0, "DS allocation failed");
 
+#if 0
+                               DEBUG() << "COPY: DS " << std::hex << mem.cap() << " SIZE " << size
+                                       << " attached @ " << a;
+                               DEBUG() << "memcpy(" << (void*)a << ", "
+                                       << (void*)r.local_region(orig_id).start()
+                                       << ", " << size << ")";
+#endif
                                memcpy((void*)a, (void*)r.local_region(orig_id).start(), size);
 
-                               //DEBUG() << "COPY: DS " << std::hex << mem.cap() << " SIZE " << size
-                               //      << " attached @ " << a;
                                r.set_local_region(inst_id, Romain::Region(a, a+size-1));
                                r.memory(inst_id, mem);
 
@@ -370,28 +411,66 @@ namespace Romain
                        static void
                        allocate_ds(L4::Cap<L4Re::Dataspace> *cap, unsigned size)
                        {
+                               unsigned long flags = 0;
+                               if (size >= L4_SUPERPAGESIZE) {
+                                       flags |= L4Re::Mem_alloc::Super_pages;
+                                       flags |= L4Re::Mem_alloc::Continuous;
+                               }
+                               
                                *cap = L4Re::Util::cap_alloc.alloc<L4Re::Dataspace>();
                                _check(!cap->is_valid(), "error allocating DS capability");
 
-                               int error = L4Re::Env::env()->mem_alloc()->alloc(size, *cap);
+                               int error = L4Re::Env::env()->mem_alloc()->alloc(size, *cap, flags);
                                _check(error != 0, "error allocating memory");
                        }
 
 
+                       static l4_addr_t
+                       attach_aligned(L4::Cap<L4Re::Dataspace> const * ds, unsigned size,
+                                      unsigned offs = 0, unsigned flags = 0,
+                                      unsigned align = L4_PAGESHIFT, unsigned aligndiff = 0)
+                       {
+                               l4_addr_t a           = 0;
+                               l4_addr_t search_size = size + aligndiff;
+
+                               l4_umword_t r = L4Re::Env::env()->rm()->reserve_area(&a, search_size,
+                                                                                    L4Re::Rm::Search_addr | flags,
+                                                                                    align);
+                               _check(r != 0, "reserve area failed");
+                               DEBUG() << std::hex << "Reserved area at " << a << " and will attach to "
+                                       << a + aligndiff;
+
+                               a += aligndiff;
+                               l4_addr_t tmp_a = a;
+
+                               r = L4Re::Env::env()->rm()->attach(&a, size, L4Re::Rm::In_area | L4Re::Rm::Eager_map | flags,
+                                                                  *ds, offs);
+                               _check(r != 0, "attach error");
+                               _check(a != tmp_a, "did not attach to correct location");
+
+                               DEBUG() << "att: " << (void*)a;
+
+                               r = L4Re::Env::env()->rm()->free_area(a);
+                               _check(r != 0, "free area failed");
+
+                               return a;
+                       }
+
+
                        /*
                         * Allocate and attach a master-local dataspace object.
                         */
                        static l4_addr_t
                        allocate_and_attach(L4::Cap<L4Re::Dataspace> *cap, unsigned size,
-                                               unsigned offs = 0, unsigned align = L4_PAGESHIFT)
+                                               unsigned offs = 0, unsigned flags = 0,
+                                               unsigned align = L4_PAGESHIFT,
+                                               unsigned aligndiff = 0)
                        {
                                Romain::Region_map::allocate_ds(cap, size);
 
-                               l4_addr_t a = 0;
-                               int error = L4Re::Env::env()->rm()->attach(&a, size, L4Re::Rm::Search_addr, *cap, offs, align);
-                               _check(error != 0, "attach failed");
-
-                               return a;
+                               return Romain::Region_map::attach_aligned(cap, size, offs,
+                                                                         flags, align,
+                                                                         aligndiff);
                        }
 
 
@@ -399,7 +478,7 @@ namespace Romain
                         * Check if a node already has a mapping to one of the replicas. If so,
                         * take a shortcut mapping to the next one (determined by inst parameter).
                         */
-                       bool lazy_map_region(Romain::Region_map::Base::Node &n, unsigned inst);
+                       bool lazy_map_region(Romain::Region_map::Base::Node &n, unsigned inst, bool writepf=false);
 
                private:
                        unsigned _active_instance;
@@ -430,6 +509,9 @@ namespace Romain
                        void *attach(void* addr, unsigned long size, Romain::Region_handler const &hdlr,
                                     unsigned flags = None, unsigned char align=L4_PAGESHIFT, bool shared = false);
 
+                       int detach(void* addr, unsigned long size, unsigned flags,
+                       L4Re::Util::Region* reg, Romain::Region_handler* h);
+
                        /*
                         * Copy the content of all writable regions of instance 'from' to
                         * the respective regions of instance 'to'.
index 8677d1807f2efbd7890a8a940610f6dfb924ba9a..01a89676fad4d13355ed4273254079a105732cab 100644 (file)
@@ -66,6 +66,8 @@ void Romain::Region_ops::release(Region_handler const* h)
 Romain::Region_map::Region_map()
        : Base(0,0), _active_instance(Invalid_inst)
 {
+       pthread_mutex_init(&_mtx, 0);
+
        l4_kernel_info_t *kip = l4re_kip();
        MSG() << "kip found at 0x" << std::hex << kip
              << " having " << L4::Kip::Mem_desc::count(kip)
@@ -109,7 +111,50 @@ Romain::Region_map::Region_map()
  * if necessary (e.g., setting debug breakpoints on read-only code).
  *
  * For writable dataspaces, the master simply attaches the same region that has
- * already been attached to the replica AS into its own address space.
+ * already been attached to the replica AS into its own address space and maintains
+ * a copy for every replica.
+ *
+ * The replica copies lead to another problem: to reduce replication overhead, we
+ * would like to handle page faults using as few memory mappings as possible. To
+ * be able to do so, we however need to make sure that all replica copies are
+ * aligned to the same start address. The Romain::Master does this by ensuring
+ * that the replica address as well as the master-local addresses of the copies
+ * are aligned to the same offset within a minimally aligned region. The minimum
+ * alignment is defined by the Region_handler()'s MIN_ALIGNMENT member (XXX and
+ * should at some point become a configurable feature).
+ *
+ * The layout looks like this:
+ *
+ *  REPLICA:
+ *
+ * (1)      (2)                         (3)
+ *  +- - - - +---------------------------+
+ *  |        |                           |
+ *  +- - - - +---------------------------+
+ *
+ *  MASTER (per copy):
+ *
+ * (A)      (B)                         (C)
+ *  +- - - - +---------------------------+
+ *  |        |                           |
+ *  +- - - - +---------------------------+ 
+ *
+ *   (1)  correct minimum alignment
+ *   (2)  region.start()
+ *   (3)  region.end()
+ *
+ *   (A)  address aligned similar to (1)
+ *   (B)  local_region[inst]->start()
+ *   (C)  local_region[inst]->end()
+ *
+ *   MIN_ALIGNMENT_MASK := (1 << MIN_ALIGNMENT) - 1
+ *   (1) := (2) - [(2) & MIN_ALIGNMENT_MASK]
+ *   (A) := (B) - [(B) & MIN_ALIGNMENT_MASK]
+ *
+ *  Attaching then works by first reserving an area with the RM
+ *  that has the size (C) - (A). Then we attach the dataspace to
+ *  (B) and free the reserved area so that the remaining memory
+ *  can again be freely used.
  */
 void *Romain::Region_map::attach_locally(void* addr, unsigned long size,
                                          Romain::Region_handler *hdlr,
@@ -215,11 +260,10 @@ void *Romain::Region_map::attach_locally(void* addr, unsigned long size,
         */
        flags &= ~L4Re::Rm::In_area;
 
-       l4_addr_t a = 0;
-       r = L4Re::Env::env()->rm()->attach(&a, eff_size,
-                                          L4Re::Rm::Search_addr | flags,
-                                          *ds, page_base, align);
-       _check(r != 0, "attach error");
+       l4_addr_t a = Romain::Region_map::attach_aligned(ds, eff_size,
+                                                        page_base, flags,
+                                                        hdlr->alignment(),
+                                                        hdlr->align_diff());
 
        Romain::Region reg(a, a+eff_size - 1);
        reg.touch_rw();
@@ -236,6 +280,8 @@ void *Romain::Region_map::attach(void* addr, unsigned long size,
 {
        void *ret = 0;
 
+       DEBUG() << std::hex << addr << " " << size << " " << (int)align;
+
        /*
         * XXX: the only reason for this Region_handler to exist is to copy
         *      the shared parameter into the handler. Shouldn't the caller
@@ -250,7 +296,13 @@ void *Romain::Region_map::attach(void* addr, unsigned long size,
         * that the memory alignment of the local mapping matches the remote
         * alignment. This allows us to play mapping tricks later.
         */
+       if ((size > L4_SUPERPAGESIZE) and (align < L4_LOG2_SUPERPAGESIZE)) {
+               align = L4_LOG2_SUPERPAGESIZE;
+               size  = l4_round_size(size, L4_SUPERPAGESHIFT);
+       }
+
        ret = Base::attach(addr, size, _handler, flags, align);
+       DEBUG() << "Base::attach = " << std::hex << ret;
 
        /*
         * The node is now present in the region map. This means we now need
@@ -286,19 +338,19 @@ void *Romain::Region_map::attach(void* addr, unsigned long size,
 
 
 
-#if 0
+#if 1
 int Romain::Region_map::detach(void* addr, unsigned long size, unsigned flags,
-                            L4Re::Util::Region* reg, Romain::Region_handler* h)
+                              L4Re::Util::Region* reg, Romain::Region_handler* h)
 {
        MSG() << "addr " << std::hex << l4_addr_t(addr) << " " << size
              << " " << flags;
        MSG() << "active instance: " << _active_instance;
-       enter_kdebug("detach");
+       //enter_kdebug("detach");
        return -1;
 }
 #endif
 
-bool Romain::Region_map::lazy_map_region(Romain::Region_map::Base::Node &n, unsigned inst)
+bool Romain::Region_map::lazy_map_region(Romain::Region_map::Base::Node &n, unsigned inst, bool iswritepf)
 {
        /* already mapped? */
        if (n->second.local_region(inst).start())
@@ -333,9 +385,9 @@ bool Romain::Region_map::lazy_map_region(Romain::Region_map::Base::Node &n, unsi
                rh->set_local_region(inst, n->second.local_region(existing));
                rh->memory(inst, n->second.memory(existing));
        } else {
-               DEBUGf(Romain::Log::Memory) << "Copying existing mapping.";
-               bool b = copy_existing_mapping(*rh, existing, inst);
-               _check(!b, "error creating rw copy");
+                       DEBUGf(Romain::Log::Memory) << "Copying existing mapping.";
+                       bool b = copy_existing_mapping(*rh, existing, inst, iswritepf);
+                       _check(!b, "error creating rw copy");
        }
        return true;
 }
index 67ef8897435eeac941fbc84e8a1faa21621b77b5..231979b5d144cac29d1b74b4b9017b0d38a90b0e 100644 (file)
@@ -121,6 +121,7 @@ struct GateAgent
                int err         = pthread_create(&listener, 0,
                                                 listener_function, (void*)this);
                _check(err != 0, "error creating listener thread");
+               l4_thread_yield();
 
                listener_cap    = L4::Cap<L4::Thread>(pthread_getl4cap(listener));
                _check(!listener_cap.is_valid(), "could not get listener pthread cap?");
index 1b36523c86a332f80d44288920c6f331239c0b96..cd76ef5ec99bc5f437a3f082e6dd532c631faf77 100644 (file)
@@ -38,7 +38,7 @@
 
 l4_uint32_t system_time_offs_rel_1970;
 
-int
+static int
 l4rtc_if_get_offset_component(l4_uint32_t *offset)
 {
 #if defined ARCH_x86 || defined ARCH_amd64
@@ -49,7 +49,7 @@ l4rtc_if_get_offset_component(l4_uint32_t *offset)
   return 1;
 }
 
-int
+static int
 l4rtc_if_get_linux_tsc_scaler_component(l4_uint32_t *scaler)
 {
 #if defined ARCH_x86 || defined ARCH_amd64
@@ -121,8 +121,9 @@ main()
       if (get_base_time())
         return 1;
 
-
-      L4::Cap<L4::Ipc_gate> cap = L4Re::Env::env()->get_cap<L4::Ipc_gate>("rtc");
+      L4::Cap<L4::Ipc_gate> cap;
+      cap = L4Re::chkcap(L4Re::Env::env()->get_cap<L4::Ipc_gate>("rtc"),
+                         "Did not find server cap 'rtc'");
       L4Re::chksys(cap->bind_thread(L4Re::Env::env()->main_thread(), 0x1230),
                    "bind to rtc server gate");
     }
index c65f0132d41038600acb01e8efd156dad550cca8..6b9d539be08f1b8b05b3fc4a33256d06faf50b75 100644 (file)
@@ -1,7 +1,7 @@
 
 
 The contrib directory contains the nearly unmodified contents of
-sqlite-autoconf-3071502.tar.gz
+sqlite-autoconf-3071601.tar.gz
 
 The current change is to undef HAVE_POSIX_FALLOCATE in case of uclibc
 because uclibc does not have it.
index 807578d1f4ceb634fbe528c58c3ba33030d79f10..48205bbca479d6ceba9d86ca55ae4b429a2e995f 100755 (executable)
@@ -1,13 +1,11 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.68 for sqlite 3.7.15.2.
+# Generated by GNU Autoconf 2.69 for sqlite 3.7.16.1.
 #
 # Report bugs to <http://www.sqlite.org>.
 #
 #
-# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software
-# Foundation, Inc.
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
 #
 #
 # This configure script is free software; the Free Software Foundation
@@ -136,6 +134,31 @@ export LANGUAGE
 # CDPATH.
 (unset CDPATH) >/dev/null 2>&1 && unset CDPATH
 
+# Use a proper internal environment variable to ensure we don't fall
+  # into an infinite loop, continuously re-executing ourselves.
+  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+    _as_can_reexec=no; export _as_can_reexec;
+    # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+  fi
+  # We don't want this to propagate to other subprocesses.
+          { _as_can_reexec=; unset _as_can_reexec;}
 if test "x$CONFIG_SHELL" = x; then
   as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
   emulate sh
@@ -169,7 +192,8 @@ if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
 else
   exitcode=1; echo positional parameters were not saved.
 fi
-test x\$exitcode = x0 || exit 1"
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
   as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
   as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
   eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
@@ -214,21 +238,25 @@ IFS=$as_save_IFS
 
 
       if test "x$CONFIG_SHELL" != x; then :
-  # We cannot yet assume a decent shell, so we have to provide a
-       # neutralization value for shells without unset; and this also
-       # works around shells that cannot unset nonexistent variables.
-       # Preserve -v and -x to the replacement shell.
-       BASH_ENV=/dev/null
-       ENV=/dev/null
-       (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
-       export CONFIG_SHELL
-       case $- in # ((((
-         *v*x* | *x*v* ) as_opts=-vx ;;
-         *v* ) as_opts=-v ;;
-         *x* ) as_opts=-x ;;
-         * ) as_opts= ;;
-       esac
-       exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"}
+  export CONFIG_SHELL
+             # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
 fi
 
     if test x$as_have_required = xno; then :
@@ -331,6 +359,14 @@ $as_echo X"$as_dir" |
 
 
 } # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
 # as_fn_append VAR VALUE
 # ----------------------
 # Append the text in VALUE to the end of the definition contained in VAR. Take
@@ -452,6 +488,10 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits
   chmod +x "$as_me.lineno" ||
     { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
 
+  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+  # already done that, so ensure we don't try to do so again and fall
+  # in an infinite loop.  This has already happened in practice.
+  _as_can_reexec=no; export _as_can_reexec
   # Don't try to exec as it changes $[0], causing all sort of problems
   # (the dirname of $[0] is not the place where we might find the
   # original and so on.  Autoconf is especially sensitive to this).
@@ -486,16 +526,16 @@ if (echo >conf$$.file) 2>/dev/null; then
     # ... but there are two gotchas:
     # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
     # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
-    # In both cases, we have to default to `cp -p'.
+    # In both cases, we have to default to `cp -pR'.
     ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
-      as_ln_s='cp -p'
+      as_ln_s='cp -pR'
   elif ln conf$$.file conf$$ 2>/dev/null; then
     as_ln_s=ln
   else
-    as_ln_s='cp -p'
+    as_ln_s='cp -pR'
   fi
 else
-  as_ln_s='cp -p'
+  as_ln_s='cp -pR'
 fi
 rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
 rmdir conf$$.dir 2>/dev/null
@@ -507,28 +547,8 @@ else
   as_mkdir_p=false
 fi
 
-if test -x / >/dev/null 2>&1; then
-  as_test_x='test -x'
-else
-  if ls -dL / >/dev/null 2>&1; then
-    as_ls_L_option=L
-  else
-    as_ls_L_option=
-  fi
-  as_test_x='
-    eval sh -c '\''
-      if test -d "$1"; then
-       test -d "$1/.";
-      else
-       case $1 in #(
-       -*)set "./$1";;
-       esac;
-       case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
-       ???[sx]*):;;*)false;;esac;fi
-    '\'' sh
-  '
-fi
-as_executable_p=$as_test_x
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
 
 # Sed expression to map a string onto a valid CPP name.
 as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -714,8 +734,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='sqlite'
 PACKAGE_TARNAME='sqlite'
-PACKAGE_VERSION='3.7.15.2'
-PACKAGE_STRING='sqlite 3.7.15.2'
+PACKAGE_VERSION='3.7.16.1'
+PACKAGE_STRING='sqlite 3.7.16.1'
 PACKAGE_BUGREPORT='http://www.sqlite.org'
 PACKAGE_URL=''
 
@@ -1350,8 +1370,6 @@ target=$target_alias
 if test "x$host_alias" != x; then
   if test "x$build_alias" = x; then
     cross_compiling=maybe
-    $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host.
-    If a cross compiler is detected then cross compile mode will be used" >&2
   elif test "x$build_alias" != "x$host_alias"; then
     cross_compiling=yes
   fi
@@ -1437,7 +1455,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures sqlite 3.7.15.2 to adapt to many kinds of systems.
+\`configure' configures sqlite 3.7.16.1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1507,7 +1525,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of sqlite 3.7.15.2:";;
+     short | recursive ) echo "Configuration of sqlite 3.7.16.1:";;
    esac
   cat <<\_ACEOF
 
@@ -1617,10 +1635,10 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-sqlite configure 3.7.15.2
-generated by GNU Autoconf 2.68
+sqlite configure 3.7.16.1
+generated by GNU Autoconf 2.69
 
-Copyright (C) 2010 Free Software Foundation, Inc.
+Copyright (C) 2012 Free Software Foundation, Inc.
 This configure script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it.
 _ACEOF
@@ -1696,7 +1714,7 @@ $as_echo "$ac_try_echo"; } >&5
         test ! -s conftest.err
        } && test -s conftest$ac_exeext && {
         test "$cross_compiling" = yes ||
-        $as_test_x conftest$ac_exeext
+        test -x conftest$ac_exeext
        }; then :
   ac_retval=0
 else
@@ -2085,7 +2103,7 @@ $as_echo "$ac_try_echo"; } >&5
         test ! -s conftest.err
        } && test -s conftest$ac_exeext && {
         test "$cross_compiling" = yes ||
-        $as_test_x conftest$ac_exeext
+        test -x conftest$ac_exeext
        }; then :
   ac_retval=0
 else
@@ -2169,7 +2187,7 @@ $as_echo "$ac_try_echo"; } >&5
         test ! -s conftest.err
        } && test -s conftest$ac_exeext && {
         test "$cross_compiling" = yes ||
-        $as_test_x conftest$ac_exeext
+        test -x conftest$ac_exeext
        }; then :
   ac_retval=0
 else
@@ -2237,8 +2255,8 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by sqlite $as_me 3.7.15.2, which was
-generated by GNU Autoconf 2.68.  Invocation command line was
+It was created by sqlite $as_me 3.7.16.1, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
 
@@ -2655,7 +2673,7 @@ case $as_dir/ in #((
     # by default.
     for ac_prog in ginstall scoinst install; do
       for ac_exec_ext in '' $ac_executable_extensions; do
-       if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+       if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
          if test $ac_prog = install &&
            grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
            # AIX install.  It has an incompatible calling convention.
@@ -2824,7 +2842,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_AWK="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2906,7 +2924,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='sqlite'
- VERSION='3.7.15.2'
+ VERSION='3.7.16.1'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -2958,7 +2976,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_STRIP="${ac_tool_prefix}strip"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -2998,7 +3016,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_STRIP="strip"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3136,7 +3154,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="${ac_tool_prefix}gcc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3176,7 +3194,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CC="gcc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3229,7 +3247,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="${ac_tool_prefix}cc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3270,7 +3288,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
        ac_prog_rejected=yes
        continue
@@ -3328,7 +3346,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3372,7 +3390,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CC="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -3818,8 +3836,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 #include <stdarg.h>
 #include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
+struct stat;
 /* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
 struct buf { int x; };
 FILE * (*rcsopen) (struct buf *, struct stat *, int);
@@ -4210,6 +4227,8 @@ _ACEOF
 esac
 rm -rf conftest*
   fi
+
+
 fi
 
 
@@ -4236,7 +4255,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="${ac_tool_prefix}gcc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -4276,7 +4295,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CC="gcc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -4329,7 +4348,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="${ac_tool_prefix}cc"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -4370,7 +4389,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
        ac_prog_rejected=yes
        continue
@@ -4428,7 +4447,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -4472,7 +4491,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CC="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -4668,8 +4687,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 #include <stdarg.h>
 #include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
+struct stat;
 /* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
 struct buf { int x; };
 FILE * (*rcsopen) (struct buf *, struct stat *, int);
@@ -4880,7 +4898,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -4920,7 +4938,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_RANLIB="ranlib"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -5171,7 +5189,7 @@ do
     for ac_prog in grep ggrep; do
     for ac_exec_ext in '' $ac_executable_extensions; do
       ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
-      { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+      as_fn_executable_p "$ac_path_GREP" || continue
 # Check for GNU ac_path_GREP and select it if it is found.
   # Check for GNU $ac_path_GREP
 case `"$ac_path_GREP" --version 2>&1` in
@@ -5237,7 +5255,7 @@ do
     for ac_prog in egrep; do
     for ac_exec_ext in '' $ac_executable_extensions; do
       ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
-      { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+      as_fn_executable_p "$ac_path_EGREP" || continue
 # Check for GNU ac_path_EGREP and select it if it is found.
   # Check for GNU $ac_path_EGREP
 case `"$ac_path_EGREP" --version 2>&1` in
@@ -5704,7 +5722,7 @@ ia64-*-hpux*)
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 5707 "configure"' > conftest.$ac_ext
+  echo '#line 5725 "configure"' > conftest.$ac_ext
   if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -6165,7 +6183,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -6209,7 +6227,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_CXX="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -6649,7 +6667,7 @@ ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5'
 ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
 ac_compiler_gnu=$ac_cv_f77_compiler_gnu
 if test -n "$ac_tool_prefix"; then
-  for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgfortran pgf95 lf95 ftn
+  for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgfortran pgf95 lf95 ftn nagfor
   do
     # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
 set dummy $ac_tool_prefix$ac_prog; ac_word=$2
@@ -6667,7 +6685,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_F77="$ac_tool_prefix$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -6693,7 +6711,7 @@ fi
 fi
 if test -z "$F77"; then
   ac_ct_F77=$F77
-  for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgfortran pgf95 lf95 ftn
+  for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgfortran pgf95 lf95 ftn nagfor
 do
   # Extract the first word of "$ac_prog", so it can be a program name with args.
 set dummy $ac_prog; ac_word=$2
@@ -6711,7 +6729,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_F77="$ac_prog"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7273,7 +7291,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_AR="${ac_tool_prefix}ar"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7313,7 +7331,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_AR="ar"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7365,7 +7383,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7405,7 +7423,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_RANLIB="ranlib"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7457,7 +7475,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_STRIP="${ac_tool_prefix}strip"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7497,7 +7515,7 @@ do
   IFS=$as_save_IFS
   test -z "$as_dir" && as_dir=.
     for ac_exec_ext in '' $ac_executable_extensions; do
-  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
     ac_cv_prog_ac_ct_STRIP="strip"
     $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
     break 2
@@ -7810,11 +7828,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:7813: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:7831: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:7817: \$? = $ac_status" >&5
+   echo "$as_me:7835: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -8078,11 +8096,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:8081: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8099: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:8085: \$? = $ac_status" >&5
+   echo "$as_me:8103: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -8182,11 +8200,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:8185: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8203: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:8189: \$? = $ac_status" >&5
+   echo "$as_me:8207: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -10151,7 +10169,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 10154 "configure"
+#line 10172 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -10251,7 +10269,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 10254 "configure"
+#line 10272 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -12527,11 +12545,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:12530: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:12548: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:12534: \$? = $ac_status" >&5
+   echo "$as_me:12552: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -12631,11 +12649,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:12634: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:12652: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:12638: \$? = $ac_status" >&5
+   echo "$as_me:12656: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -14201,11 +14219,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:14204: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:14222: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:14208: \$? = $ac_status" >&5
+   echo "$as_me:14226: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -14305,11 +14323,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:14308: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:14326: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:14312: \$? = $ac_status" >&5
+   echo "$as_me:14330: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -16457,11 +16475,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:16460: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:16478: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:16464: \$? = $ac_status" >&5
+   echo "$as_me:16482: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -16725,11 +16743,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:16728: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:16746: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:16732: \$? = $ac_status" >&5
+   echo "$as_me:16750: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings other than the usual output.
@@ -16829,11 +16847,11 @@ else
    -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:16832: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:16850: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:16836: \$? = $ac_status" >&5
+   echo "$as_me:16854: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -19446,7 +19464,7 @@ do
   test -z "$as_dir" && as_dir=.
     for ac_prog in mkdir gmkdir; do
         for ac_exec_ext in '' $ac_executable_extensions; do
-          { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue
+          as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue
           case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
             'mkdir (GNU coreutils) '* | \
             'mkdir (coreutils) '* | \
@@ -20376,16 +20394,16 @@ if (echo >conf$$.file) 2>/dev/null; then
     # ... but there are two gotchas:
     # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
     # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
-    # In both cases, we have to default to `cp -p'.
+    # In both cases, we have to default to `cp -pR'.
     ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
-      as_ln_s='cp -p'
+      as_ln_s='cp -pR'
   elif ln conf$$.file conf$$ 2>/dev/null; then
     as_ln_s=ln
   else
-    as_ln_s='cp -p'
+    as_ln_s='cp -pR'
   fi
 else
-  as_ln_s='cp -p'
+  as_ln_s='cp -pR'
 fi
 rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
 rmdir conf$$.dir 2>/dev/null
@@ -20445,28 +20463,16 @@ else
   as_mkdir_p=false
 fi
 
-if test -x / >/dev/null 2>&1; then
-  as_test_x='test -x'
-else
-  if ls -dL / >/dev/null 2>&1; then
-    as_ls_L_option=L
-  else
-    as_ls_L_option=
-  fi
-  as_test_x='
-    eval sh -c '\''
-      if test -d "$1"; then
-       test -d "$1/.";
-      else
-       case $1 in #(
-       -*)set "./$1";;
-       esac;
-       case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #((
-       ???[sx]*):;;*)false;;esac;fi
-    '\'' sh
-  '
-fi
-as_executable_p=$as_test_x
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
 
 # Sed expression to map a string onto a valid CPP name.
 as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
@@ -20487,8 +20493,8 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by sqlite $as_me 3.7.15.2, which was
-generated by GNU Autoconf 2.68.  Invocation command line was
+This file was extended by sqlite $as_me 3.7.16.1, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
   CONFIG_HEADERS  = $CONFIG_HEADERS
@@ -20544,11 +20550,11 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-sqlite config.status 3.7.15.2
-configured by $0, generated by GNU Autoconf 2.68,
+sqlite config.status 3.7.16.1
+configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
-Copyright (C) 2010 Free Software Foundation, Inc.
+Copyright (C) 2012 Free Software Foundation, Inc.
 This config.status script is free software; the Free Software Foundation
 gives unlimited permission to copy, distribute and modify it."
 
@@ -20628,7 +20634,7 @@ fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 if \$ac_cs_recheck; then
-  set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
   shift
   \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
   CONFIG_SHELL='$SHELL'
index 000da90d413a9e79ae8b313b19ccf84c0f31e337..9560f914750402017f621098cc030edf26f73c8d 100644 (file)
@@ -8,7 +8,7 @@
 #
 
 AC_PREREQ(2.61)
-AC_INIT(sqlite, 3.7.15.2, http://www.sqlite.org)
+AC_INIT(sqlite, 3.7.16.1, http://www.sqlite.org)
 AC_CONFIG_SRCDIR([sqlite3.c])
 
 # Use automake.
index 7dd741b2d7fa2f467c96125dd61892cfbd2c1ca4..c6d7fa3d536605324a19a07ac8c9c08d8b356db0 100644 (file)
@@ -90,7 +90,8 @@ static int enableTimer = 0;
 #define IsDigit(X)  isdigit((unsigned char)X)
 #define ToLower(X)  (char)tolower((unsigned char)X)
 
-#if !defined(_WIN32) && !defined(WIN32) && !defined(_WRS_KERNEL)
+#if !defined(_WIN32) && !defined(WIN32) && !defined(_WRS_KERNEL) \
+ && !defined(__minux)
 #include <sys/time.h>
 #include <sys/resource.h>
 
@@ -1479,6 +1480,18 @@ static void open_db(struct callback_data *p){
     }
 #ifndef SQLITE_OMIT_LOAD_EXTENSION
     sqlite3_enable_load_extension(p->db, 1);
+#endif
+#ifdef SQLITE_ENABLE_REGEXP
+    {
+      extern int sqlite3_add_regexp_func(sqlite3*);
+      sqlite3_add_regexp_func(db);
+    }
+#endif
+#ifdef SQLITE_ENABLE_SPELLFIX
+    {
+      extern int sqlite3_spellfix1_register(sqlite3*);
+      sqlite3_spellfix1_register(db);
+    }
 #endif
   }
 }
@@ -1525,17 +1538,18 @@ static void resolve_backslashes(char *z){
 ** Interpret zArg as a boolean value.  Return either 0 or 1.
 */
 static int booleanValue(char *zArg){
-  int val = atoi(zArg);
-  int j;
-  for(j=0; zArg[j]; j++){
-    zArg[j] = ToLower(zArg[j]);
+  int i;
+  for(i=0; zArg[i]>='0' && zArg[i]<='9'; i++){}
+  if( i>0 && zArg[i]==0 ) return atoi(zArg);
+  if( sqlite3_stricmp(zArg, "on")==0 || sqlite3_stricmp(zArg,"yes")==0 ){
+    return 1;
   }
-  if( strcmp(zArg,"on")==0 ){
-    val = 1;
-  }else if( strcmp(zArg,"yes")==0 ){
-    val = 1;
+  if( sqlite3_stricmp(zArg, "off")==0 || sqlite3_stricmp(zArg,"no")==0 ){
+    return 0;
   }
-  return val;
+  fprintf(stderr, "ERROR: Not a boolean value: \"%s\". Assuming \"no\".\n",
+          zArg);
+  return 0;
 }
 
 /*
@@ -1623,24 +1637,50 @@ static int do_meta_command(char *zLine, struct callback_data *p){
   if( nArg==0 ) return 0; /* no tokens, no error */
   n = strlen30(azArg[0]);
   c = azArg[0][0];
-  if( c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0 && nArg>1 && nArg<4){
-    const char *zDestFile;
-    const char *zDb;
+  if( c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0 ){
+    const char *zDestFile = 0;
+    const char *zDb = 0;
+    const char *zKey = 0;
     sqlite3 *pDest;
     sqlite3_backup *pBackup;
-    if( nArg==2 ){
-      zDestFile = azArg[1];
-      zDb = "main";
-    }else{
-      zDestFile = azArg[2];
-      zDb = azArg[1];
+    int j;
+    for(j=1; j<nArg; j++){
+      const char *z = azArg[j];
+      if( z[0]=='-' ){
+        while( z[0]=='-' ) z++;
+        if( strcmp(z,"key")==0 && j<nArg-1 ){
+          zKey = azArg[++j];
+        }else
+        {
+          fprintf(stderr, "unknown option: %s\n", azArg[j]);
+          return 1;
+        }
+      }else if( zDestFile==0 ){
+        zDestFile = azArg[j];
+      }else if( zDb==0 ){
+        zDb = zDestFile;
+        zDestFile = azArg[j];
+      }else{
+        fprintf(stderr, "too many arguments to .backup\n");
+        return 1;
+      }
+    }
+    if( zDestFile==0 ){
+      fprintf(stderr, "missing FILENAME argument on .backup\n");
+      return 1;
     }
+    if( zDb==0 ) zDb = "main";
     rc = sqlite3_open(zDestFile, &pDest);
     if( rc!=SQLITE_OK ){
       fprintf(stderr, "Error: cannot open \"%s\"\n", zDestFile);
       sqlite3_close(pDest);
       return 1;
     }
+#ifdef SQLITE_HAS_CODEC
+    sqlite3_key(pDest, zKey, (int)strlen(zKey));
+#else
+    (void)zKey;
+#endif
     open_db(p);
     pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
     if( pBackup==0 ){
@@ -1742,7 +1782,8 @@ static int do_meta_command(char *zLine, struct callback_data *p){
     p->echoOn = booleanValue(azArg[1]);
   }else
 
-  if( c=='e' && strncmp(azArg[0], "exit", n)==0  && nArg==1 ){
+  if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){
+    if( nArg>1 && (rc = atoi(azArg[1]))!=0 ) exit(rc);
     rc = 2;
   }else
 
index 26bae0a1f911ddf31938583e7ef78d2949d5c1da..7b957a8aa74f9e2e1c898180515a5112b7927b30 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
 ** This file is an amalgamation of many separate C source files from SQLite
-** version 3.7.15.2.  By combining all the individual C code files into this 
+** version 3.7.16.1.  By combining all the individual C code files into this 
 ** single large file, the entire code can be compiled as a single translation
 ** unit.  This allows many compilers to do optimizations that would not be
 ** possible if the files were compiled separately.  Performance improvements
 # define _GNU_SOURCE
 #endif
 
+#if defined(__OpenBSD__) && !defined(_BSD_SOURCE)
+# define _BSD_SOURCE
+#endif
+
 /*
 ** Include standard header files as necessary
 */
 **
 ** See also ticket #2741.
 */
-#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) && !defined(__APPLE__) && SQLITE_THREADSAFE
+#if !defined(_XOPEN_SOURCE) && !defined(__DARWIN__) \
+ && !defined(__APPLE__) && SQLITE_THREADSAFE
 #  define _XOPEN_SOURCE 500  /* Needed to enable pthread recursive mutexes */
 #endif
 
@@ -673,9 +678,9 @@ extern "C" {
 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
 ** [sqlite_version()] and [sqlite_source_id()].
 */
-#define SQLITE_VERSION        "3.7.15.2"
-#define SQLITE_VERSION_NUMBER 3007015
-#define SQLITE_SOURCE_ID      "2013-01-09 11:53:05 c0e09560d26f0a6456be9dd3447f5311eb4f238f"
+#define SQLITE_VERSION        "3.7.16.1"
+#define SQLITE_VERSION_NUMBER 3007016
+#define SQLITE_SOURCE_ID      "2013-03-29 13:44:34 527231bc67285f01fb18d4451b28f61da3c4e39d"
 
 /*
 ** CAPI3REF: Run-Time Library Version Numbers
@@ -854,7 +859,7 @@ typedef sqlite_uint64 sqlite3_uint64;
 ** [sqlite3_blob_close | close] all [BLOB handles], and 
 ** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
 ** with the [sqlite3] object prior to attempting to close the object.  ^If
-** sqlite3_close() is called on a [database connection] that still has
+** sqlite3_close_v2() is called on a [database connection] that still has
 ** outstanding [prepared statements], [BLOB handles], and/or
 ** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation
 ** of resources is deferred until all [prepared statements], [BLOB handles],
@@ -1049,7 +1054,17 @@ SQLITE_API int sqlite3_exec(
 #define SQLITE_CORRUPT_VTAB            (SQLITE_CORRUPT | (1<<8))
 #define SQLITE_READONLY_RECOVERY       (SQLITE_READONLY | (1<<8))
 #define SQLITE_READONLY_CANTLOCK       (SQLITE_READONLY | (2<<8))
+#define SQLITE_READONLY_ROLLBACK       (SQLITE_READONLY | (3<<8))
 #define SQLITE_ABORT_ROLLBACK          (SQLITE_ABORT | (2<<8))
+#define SQLITE_CONSTRAINT_CHECK        (SQLITE_CONSTRAINT | (1<<8))
+#define SQLITE_CONSTRAINT_COMMITHOOK   (SQLITE_CONSTRAINT | (2<<8))
+#define SQLITE_CONSTRAINT_FOREIGNKEY   (SQLITE_CONSTRAINT | (3<<8))
+#define SQLITE_CONSTRAINT_FUNCTION     (SQLITE_CONSTRAINT | (4<<8))
+#define SQLITE_CONSTRAINT_NOTNULL      (SQLITE_CONSTRAINT | (5<<8))
+#define SQLITE_CONSTRAINT_PRIMARYKEY   (SQLITE_CONSTRAINT | (6<<8))
+#define SQLITE_CONSTRAINT_TRIGGER      (SQLITE_CONSTRAINT | (7<<8))
+#define SQLITE_CONSTRAINT_UNIQUE       (SQLITE_CONSTRAINT | (8<<8))
+#define SQLITE_CONSTRAINT_VTAB         (SQLITE_CONSTRAINT | (9<<8))
 
 /*
 ** CAPI3REF: Flags For File Open Operations
@@ -3236,7 +3251,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 **     sqlite3_open_v2(). ^Setting the cache parameter to "private" is 
 **     equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
 **     ^If sqlite3_open_v2() is used and the "cache" parameter is present in
-**     a URI filename, its value overrides any behaviour requested by setting
+**     a URI filename, its value overrides any behavior requested by setting
 **     SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
 ** </ul>
 **
@@ -4554,7 +4569,8 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*);
 SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
 SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void);
 SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void);
-SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64);
+SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
+                      void*,sqlite3_int64);
 #endif
 
 /*
@@ -4634,14 +4650,17 @@ SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
 ** In those cases, sqlite3_aggregate_context() might be called for the
 ** first time from within xFinal().)^
 **
-** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer if N is
-** less than or equal to zero or if a memory allocate error occurs.
+** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer 
+** when first called if N is less than or equal to zero or if a memory
+** allocate error occurs.
 **
 ** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
 ** determined by the N parameter on first successful call.  Changing the
 ** value of N in subsequent call to sqlite3_aggregate_context() within
 ** the same aggregate function instance will not resize the memory
-** allocation.)^
+** allocation.)^  Within the xFinal callback, it is customary to set
+** N=0 in calls to sqlite3_aggregate_context(C,N) so that no 
+** pointless memory allocations occur.
 **
 ** ^SQLite automatically frees the memory allocated by 
 ** sqlite3_aggregate_context() when the aggregate query concludes.
@@ -6935,7 +6954,7 @@ struct sqlite3_pcache_page {
 ** parameter to help it determined what action to take:
 **
 ** <table border=1 width=85% align=center>
-** <tr><th> createFlag <th> Behaviour when page is not already in cache
+** <tr><th> createFlag <th> Behavior when page is not already in cache
 ** <tr><td> 0 <td> Do not allocate a new page.  Return NULL.
 ** <tr><td> 1 <td> Allocate a new page if it easy and convenient to do so.
 **                 Otherwise return NULL.
@@ -7740,7 +7759,7 @@ struct sqlite3_rtree_geometry {
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** This is the header file for the generic hash-table implemenation
+** This is the header file for the generic hash-table implementation
 ** used in SQLite.
 */
 #ifndef _SQLITE_HASH_H_
@@ -8240,6 +8259,11 @@ struct BusyHandler {
 */
 #define ArraySize(X)    ((int)(sizeof(X)/sizeof(X[0])))
 
+/*
+** Determine if the argument is a power of two
+*/
+#define IsPowerOfTwo(X) (((X)&((X)-1))==0)
+
 /*
 ** The following value as a destructor means to use sqlite3DbFree().
 ** The sqlite3DbFree() routine requires two parameters instead of the 
@@ -10015,7 +10039,7 @@ struct sqlite3 {
 #define SQLITE_SqlTrace       0x00000040  /* Debug print SQL as it executes */
 #define SQLITE_VdbeListing    0x00000080  /* Debug listings of VDBE programs */
 #define SQLITE_WriteSchema    0x00000100  /* OK to update SQLITE_MASTER */
-                         /*   0x00000200  Unused */
+#define SQLITE_VdbeAddopTrace 0x00000200  /* Trace sqlite3VdbeAddOp() calls */
 #define SQLITE_IgnoreChecks   0x00000400  /* Do not enforce check constraints */
 #define SQLITE_ReadUncommitted 0x0000800  /* For shared-cache mode */
 #define SQLITE_LegacyFileFmt  0x00001000  /* Create new databases in format 1 */
@@ -10044,6 +10068,7 @@ struct sqlite3 {
 #define SQLITE_CoverIdxScan   0x0040   /* Covering index scans */
 #define SQLITE_OrderByIdxJoin 0x0080   /* ORDER BY of joins via index */
 #define SQLITE_SubqCoroutine  0x0100   /* Evaluate subqueries as coroutines */
+#define SQLITE_Transitive     0x0200   /* Transitive constraints */
 #define SQLITE_AllOpts        0xffff   /* All optimizations */
 
 /*
@@ -10555,20 +10580,20 @@ struct UnpackedRecord {
 ** element.
 */
 struct Index {
-  char *zName;     /* Name of this index */
-  int *aiColumn;   /* Which columns are used by this index.  1st is 0 */
-  tRowcnt *aiRowEst; /* Result of ANALYZE: Est. rows selected by each column */
-  Table *pTable;   /* The SQL table being indexed */
-  char *zColAff;   /* String defining the affinity of each column */
-  Index *pNext;    /* The next index associated with the same table */
-  Schema *pSchema; /* Schema containing this index */
-  u8 *aSortOrder;  /* Array of size Index.nColumn. True==DESC, False==ASC */
-  char **azColl;   /* Array of collation sequence names for index */
-  int nColumn;     /* Number of columns in the table used by this index */
-  int tnum;        /* Page containing root of this index in database file */
-  u8 onError;      /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
-  u8 autoIndex;    /* True if is automatically created (ex: by UNIQUE) */
-  u8 bUnordered;   /* Use this index for == or IN queries only */
+  char *zName;             /* Name of this index */
+  int *aiColumn;           /* Which columns are used by this index.  1st is 0 */
+  tRowcnt *aiRowEst;       /* From ANALYZE: Est. rows selected by each column */
+  Table *pTable;           /* The SQL table being indexed */
+  char *zColAff;           /* String defining the affinity of each column */
+  Index *pNext;            /* The next index associated with the same table */
+  Schema *pSchema;         /* Schema containing this index */
+  u8 *aSortOrder;          /* for each column: True==DESC, False==ASC */
+  char **azColl;           /* Array of collation sequence names for index */
+  int tnum;                /* DB Page containing root of this index */
+  u16 nColumn;             /* Number of columns in table used by this index */
+  u8 onError;              /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
+  unsigned autoIndex:2;    /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
+  unsigned bUnordered:1;   /* Use this index for == or IN queries only */
 #ifdef SQLITE_ENABLE_STAT3
   int nSample;             /* Number of elements in aSample[] */
   tRowcnt avgEq;           /* Average nEq value for key values not in aSample */
@@ -10842,18 +10867,27 @@ struct Expr {
 ** list of "ID = expr" items in an UPDATE.  A list of expressions can
 ** also be used as the argument to a function, in which case the a.zName
 ** field is not used.
+**
+** By default the Expr.zSpan field holds a human-readable description of
+** the expression that is used in the generation of error messages and
+** column labels.  In this case, Expr.zSpan is typically the text of a
+** column expression as it exists in a SELECT statement.  However, if
+** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name
+** of the result column in the form: DATABASE.TABLE.COLUMN.  This later
+** form is used for name resolution with nested FROM clauses.
 */
 struct ExprList {
   int nExpr;             /* Number of expressions on the list */
   int iECursor;          /* VDBE Cursor associated with this ExprList */
   struct ExprList_item { /* For each expression in the list */
-    Expr *pExpr;           /* The list of expressions */
-    char *zName;           /* Token associated with this expression */
-    char *zSpan;           /* Original text of the expression */
-    u8 sortOrder;          /* 1 for DESC or 0 for ASC */
-    u8 done;               /* A flag to indicate when processing is finished */
-    u16 iOrderByCol;       /* For ORDER BY, column number in result set */
-    u16 iAlias;            /* Index into Parse.aAlias[] for zName */
+    Expr *pExpr;            /* The list of expressions */
+    char *zName;            /* Token associated with this expression */
+    char *zSpan;            /* Original text of the expression */
+    u8 sortOrder;           /* 1 for DESC or 0 for ASC */
+    unsigned done :1;       /* A flag to indicate when processing is finished */
+    unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */
+    u16 iOrderByCol;        /* For ORDER BY, column number in result set */
+    u16 iAlias;             /* Index into Parse.aAlias[] for zName */
   } *a;                  /* Alloc a power of two greater or equal to nExpr */
 };
 
@@ -11021,6 +11055,7 @@ struct WhereLevel {
       struct InLoop {
         int iCur;              /* The VDBE cursor used by this IN operator */
         int addrInTop;         /* Top of the IN loop */
+        u8 eEndLoopOp;         /* IN Loop terminator. OP_Next or OP_Prev */
       } *aInLoop;           /* Information about each nested IN operator */
     } in;                 /* Used when plan.wsFlags&WHERE_IN_ABLE */
     Index *pCovidx;       /* Possible covering index for WHERE_MULTI_OR */
@@ -11173,6 +11208,7 @@ struct Select {
 #define SF_UseSorter       0x0040  /* Sort using a sorter */
 #define SF_Values          0x0080  /* Synthesized from VALUES clause */
 #define SF_Materialize     0x0100  /* Force materialization of views */
+#define SF_NestedFrom      0x0200  /* Part of a parenthesized FROM clause */
 
 
 /*
@@ -11885,13 +11921,13 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*
 SQLITE_PRIVATE void sqlite3DropIndex(Parse*, SrcList*, int);
 SQLITE_PRIVATE int sqlite3Select(Parse*, Select*, SelectDest*);
 SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
-                         Expr*,ExprList*,int,Expr*,Expr*);
+                         Expr*,ExprList*,u16,Expr*,Expr*);
 SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*);
 SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*);
 SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int);
 SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
 #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
-SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, Expr *, Expr *, char *);
+SQLITE_PRIVATE Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,Expr*,char*);
 #endif
 SQLITE_PRIVATE void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
 SQLITE_PRIVATE void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
@@ -11959,7 +11995,7 @@ SQLITE_PRIVATE int sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
 SQLITE_PRIVATE void sqlite3BeginWriteOperation(Parse*, int, int);
 SQLITE_PRIVATE void sqlite3MultiWrite(Parse*);
 SQLITE_PRIVATE void sqlite3MayAbort(Parse*);
-SQLITE_PRIVATE void sqlite3HaltConstraint(Parse*, int, char*, int);
+SQLITE_PRIVATE void sqlite3HaltConstraint(Parse*, int, int, char*, int);
 SQLITE_PRIVATE Expr *sqlite3ExprDup(sqlite3*,Expr*,int);
 SQLITE_PRIVATE ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
 SQLITE_PRIVATE SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
@@ -12072,8 +12108,11 @@ SQLITE_PRIVATE int sqlite3VarintLen(u64 v);
 **     x = putVarint32( A, B );
 **
 */
-#define getVarint32(A,B)  (u8)((*(A)<(u8)0x80) ? ((B) = (u32)*(A)),1 : sqlite3GetVarint32((A), (u32 *)&(B)))
-#define putVarint32(A,B)  (u8)(((u32)(B)<(u32)0x80) ? (*(A) = (unsigned char)(B)),1 : sqlite3PutVarint32((A), (B)))
+#define getVarint32(A,B)  \
+  (u8)((*(A)<(u8)0x80)?((B)=(u32)*(A)),1:sqlite3GetVarint32((A),(u32 *)&(B)))
+#define putVarint32(A,B)  \
+  (u8)(((u32)(B)<(u32)0x80)?(*(A)=(unsigned char)(B)),1:\
+  sqlite3PutVarint32((A),(B)))
 #define getVarint    sqlite3GetVarint
 #define putVarint    sqlite3PutVarint
 
@@ -12142,6 +12181,7 @@ SQLITE_PRIVATE void sqlite3NestedParse(Parse*, const char*, ...);
 SQLITE_PRIVATE void sqlite3ExpirePreparedStatements(sqlite3*);
 SQLITE_PRIVATE int sqlite3CodeSubselect(Parse *, Expr *, int, int);
 SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*);
+SQLITE_PRIVATE int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
 SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*);
 SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
 SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
@@ -12280,8 +12320,10 @@ SQLITE_PRIVATE   FKey *sqlite3FkReferences(Table *);
 #endif
 #ifndef SQLITE_OMIT_FOREIGN_KEY
 SQLITE_PRIVATE   void sqlite3FkDelete(sqlite3 *, Table*);
+SQLITE_PRIVATE   int sqlite3FkLocateIndex(Parse*,Table*,FKey*,Index**,int**);
 #else
   #define sqlite3FkDelete(a,b)
+  #define sqlite3FkLocateIndex(a,b,c,d,e)
 #endif
 
 
@@ -12306,7 +12348,8 @@ SQLITE_PRIVATE   void sqlite3EndBenignMalloc(void);
 
 #define IN_INDEX_ROWID           1
 #define IN_INDEX_EPH             2
-#define IN_INDEX_INDEX           3
+#define IN_INDEX_INDEX_ASC       3
+#define IN_INDEX_INDEX_DESC      4
 SQLITE_PRIVATE int sqlite3FindInIndex(Parse *, Expr *, int*);
 
 #ifdef SQLITE_ENABLE_ATOMIC_WRITE
@@ -12906,9 +12949,6 @@ static const char * const azCompileOpt[] = {
 #ifdef SQLITE_OMIT_MEMORYDB
   "OMIT_MEMORYDB",
 #endif
-#ifdef SQLITE_OMIT_MERGE_SORT
-  "OMIT_MERGE_SORT",
-#endif
 #ifdef SQLITE_OMIT_OR_OPTIMIZATION
   "OMIT_OR_OPTIMIZATION",
 #endif
@@ -13191,7 +13231,7 @@ struct VdbeFrame {
   VdbeCursor **apCsr;     /* Array of Vdbe cursors for parent frame */
   void *token;            /* Copy of SubProgram.token */
   i64 lastRowid;          /* Last insert rowid (sqlite3.lastRowid) */
-  u16 nCursor;            /* Number of entries in apCsr */
+  int nCursor;            /* Number of entries in apCsr */
   int pc;                 /* Program Counter in parent (calling) frame */
   int nOp;                /* Size of aOp array */
   int nMem;               /* Number of entries in aMem */
@@ -13377,7 +13417,7 @@ struct Vdbe {
   int nLabel;             /* Number of labels used */
   int *aLabel;            /* Space to hold the labels */
   u16 nResColumn;         /* Number of columns in one row of the result set */
-  u16 nCursor;            /* Number of slots in apCsr[] */
+  int nCursor;            /* Number of slots in apCsr[] */
   u32 magic;              /* Magic number for sanity checking */
   char *zErrMsg;          /* Error message written here */
   Vdbe *pPrev,*pNext;     /* Linked list of VDBEs with the same Vdbe.db */
@@ -13497,15 +13537,6 @@ SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *);
 SQLITE_PRIVATE void sqlite3VdbeMemStoreType(Mem *pMem);
 SQLITE_PRIVATE int sqlite3VdbeTransferError(Vdbe *p);
 
-#ifdef SQLITE_OMIT_MERGE_SORT
-# define sqlite3VdbeSorterInit(Y,Z)      SQLITE_OK
-# define sqlite3VdbeSorterWrite(X,Y,Z)   SQLITE_OK
-# define sqlite3VdbeSorterClose(Y,Z)
-# define sqlite3VdbeSorterRowkey(Y,Z)    SQLITE_OK
-# define sqlite3VdbeSorterRewind(X,Y,Z)  SQLITE_OK
-# define sqlite3VdbeSorterNext(X,Y,Z)    SQLITE_OK
-# define sqlite3VdbeSorterCompare(X,Y,Z) SQLITE_OK
-#else
 SQLITE_PRIVATE int sqlite3VdbeSorterInit(sqlite3 *, VdbeCursor *);
 SQLITE_PRIVATE void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
 SQLITE_PRIVATE int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
@@ -13513,7 +13544,6 @@ SQLITE_PRIVATE int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *);
 SQLITE_PRIVATE int sqlite3VdbeSorterRewind(sqlite3 *, const VdbeCursor *, int *);
 SQLITE_PRIVATE int sqlite3VdbeSorterWrite(sqlite3 *, const VdbeCursor *, Mem *);
 SQLITE_PRIVATE int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int *);
-#endif
 
 #if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
 SQLITE_PRIVATE   void sqlite3VdbeEnter(Vdbe*);
@@ -21297,7 +21327,7 @@ SQLITE_API int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){
 */
 SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
 #ifndef SQLITE_OMIT_FLOATING_POINT
-  int incr = (enc==SQLITE_UTF8?1:2);
+  int incr;
   const char *zEnd = z + length;
   /* sign * significand * (10 ^ (esign * exponent)) */
   int sign = 1;    /* sign of significand */
@@ -21308,10 +21338,22 @@ SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 en
   int eValid = 1;  /* True exponent is either not used or is well-formed */
   double result;
   int nDigits = 0;
+  int nonNum = 0;
 
+  assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
   *pResult = 0.0;   /* Default return value, in case of an error */
 
-  if( enc==SQLITE_UTF16BE ) z++;
+  if( enc==SQLITE_UTF8 ){
+    incr = 1;
+  }else{
+    int i;
+    incr = 2;
+    assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
+    for(i=3-enc; i<length && z[i]==0; i+=2){}
+    nonNum = i<length;
+    zEnd = z+i+enc-3;
+    z += (enc&1);
+  }
 
   /* skip leading spaces */
   while( z<zEnd && sqlite3Isspace(*z) ) z+=incr;
@@ -21444,7 +21486,7 @@ do_atof_calc:
   *pResult = result;
 
   /* return true if number and no extra non-whitespace chracters after */
-  return z>=zEnd && nDigits>0 && eValid;
+  return z>=zEnd && nDigits>0 && eValid && nonNum==0;
 #else
   return !sqlite3Atoi64(z, pResult, length, enc);
 #endif /* SQLITE_OMIT_FLOATING_POINT */
@@ -21493,21 +21535,33 @@ static int compare2pow63(const char *zNum, int incr){
 ** signed 64-bit integer, its negative -9223372036854665808 can be.
 **
 ** If zNum is too big for a 64-bit integer and is not
-** 9223372036854665808 then return 1.
+** 9223372036854665808  or if zNum contains any non-numeric text,
+** then return 1.
 **
 ** length is the number of bytes in the string (bytes, not characters).
 ** The string is not necessarily zero-terminated.  The encoding is
 ** given by enc.
 */
 SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc){
-  int incr = (enc==SQLITE_UTF8?1:2);
+  int incr;
   u64 u = 0;
   int neg = 0; /* assume positive */
   int i;
   int c = 0;
+  int nonNum = 0;
   const char *zStart;
   const char *zEnd = zNum + length;
-  if( enc==SQLITE_UTF16BE ) zNum++;
+  assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
+  if( enc==SQLITE_UTF8 ){
+    incr = 1;
+  }else{
+    incr = 2;
+    assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
+    for(i=3-enc; i<length && zNum[i]==0; i+=2){}
+    nonNum = i<length;
+    zEnd = zNum+i+enc-3;
+    zNum += (enc&1);
+  }
   while( zNum<zEnd && sqlite3Isspace(*zNum) ) zNum+=incr;
   if( zNum<zEnd ){
     if( *zNum=='-' ){
@@ -21532,7 +21586,7 @@ SQLITE_PRIVATE int sqlite3Atoi64(const char *zNum, i64 *pNum, int length, u8 enc
   testcase( i==18 );
   testcase( i==19 );
   testcase( i==20 );
-  if( (c!=0 && &zNum[i]<zEnd) || (i==0 && zStart==zNum) || i>19*incr ){
+  if( (c!=0 && &zNum[i]<zEnd) || (i==0 && zStart==zNum) || i>19*incr || nonNum ){
     /* zNum is empty or contains non-numeric text or is longer
     ** than 19 digits (thus guaranteeing that it is too large) */
     return 1;
@@ -23217,7 +23271,7 @@ static int openDirectory(const char*, int*);
 ** to all overrideable system calls.
 */
 static struct unix_syscall {
-  const char *zName;            /* Name of the sytem call */
+  const char *zName;            /* Name of the system call */
   sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
   sqlite3_syscall_ptr pDefault; /* Default value */
 } aSyscall[] = {
@@ -23292,11 +23346,7 @@ static struct unix_syscall {
 #define osPwrite64  ((ssize_t(*)(int,const void*,size_t,off_t))\
                     aSyscall[13].pCurrent)
 
-#if SQLITE_ENABLE_LOCKING_STYLE
   { "fchmod",       (sqlite3_syscall_ptr)fchmod,     0  },
-#else
-  { "fchmod",       (sqlite3_syscall_ptr)0,          0  },
-#endif
 #define osFchmod    ((int(*)(int,mode_t))aSyscall[14].pCurrent)
 
 #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE
@@ -23321,9 +23371,6 @@ static struct unix_syscall {
   { "fchown",       (sqlite3_syscall_ptr)posixFchown,     0 },
 #define osFchown    ((int(*)(int,uid_t,gid_t))aSyscall[20].pCurrent)
 
-  { "umask",        (sqlite3_syscall_ptr)umask,           0 },
-#define osUmask     ((mode_t(*)(mode_t))aSyscall[21].pCurrent)
-
 }; /* End of the overrideable system calls */
 
 /*
@@ -23428,14 +23475,7 @@ static const char *unixNextSystemCall(sqlite3_vfs *p, const char *zName){
 */
 static int robust_open(const char *z, int f, mode_t m){
   int fd;
-  mode_t m2;
-  mode_t origM = 0;
-  if( m==0 ){
-    m2 = SQLITE_DEFAULT_FILE_PERMISSIONS;
-  }else{
-    m2 = m;
-    origM = osUmask(0);
-  }
+  mode_t m2 = m ? m : SQLITE_DEFAULT_FILE_PERMISSIONS;
   do{
 #if defined(O_CLOEXEC)
     fd = osOpen(z,f|O_CLOEXEC,m2);
@@ -23443,12 +23483,20 @@ static int robust_open(const char *z, int f, mode_t m){
     fd = osOpen(z,f,m2);
 #endif
   }while( fd<0 && errno==EINTR );
-  if( m ){
-    osUmask(origM);
-  }
+  if( fd>=0 ){
+    if( m!=0 ){
+      struct stat statbuf;
+      if( osFstat(fd, &statbuf)==0 
+       && statbuf.st_size==0
+       && (statbuf.st_mode&0777)!=m 
+      ){
+        osFchmod(fd, m);
+      }
+    }
 #if defined(FD_CLOEXEC) && (!defined(O_CLOEXEC) || O_CLOEXEC==0)
-  if( fd>=0 ) osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
+    osFcntl(fd, F_SETFD, osFcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
 #endif
+  }
   return fd;
 }
 
@@ -24795,7 +24843,7 @@ static int nolockClose(sqlite3_file *id) {
 /******************************************************************************
 ************************* Begin dot-file Locking ******************************
 **
-** The dotfile locking implementation uses the existance of separate lock
+** The dotfile locking implementation uses the existence of separate lock
 ** files (really a directory) to control access to the database.  This works
 ** on just about every filesystem imaginable.  But there are serious downsides:
 **
@@ -24810,7 +24858,7 @@ static int nolockClose(sqlite3_file *id) {
 **
 ** Dotfile locking works by creating a subdirectory in the same directory as
 ** the database and with the same name but with a ".lock" extension added.
-** The existance of a lock directory implies an EXCLUSIVE lock.  All other
+** The existence of a lock directory implies an EXCLUSIVE lock.  All other
 ** lock types (SHARED, RESERVED, PENDING) are mapped into EXCLUSIVE.
 */
 
@@ -26299,7 +26347,7 @@ static int unixSync(sqlite3_file *id, int flags){
   }
 
   /* Also fsync the directory containing the file if the DIRSYNC flag
-  ** is set.  This is a one-time occurrance.  Many systems (examples: AIX)
+  ** is set.  This is a one-time occurrence.  Many systems (examples: AIX)
   ** are unable to fsync a directory, so ignore errors on the fsync.
   */
   if( pFile->ctrlFlags & UNIXFILE_DIRSYNC ){
@@ -27641,7 +27689,7 @@ static int fillInUnixFile(
                            "psow", SQLITE_POWERSAFE_OVERWRITE) ){
     pNew->ctrlFlags |= UNIXFILE_PSOW;
   }
-  if( memcmp(pVfs->zName,"unix-excl",10)==0 ){
+  if( strcmp(pVfs->zName,"unix-excl")==0 ){
     pNew->ctrlFlags |= UNIXFILE_EXCL;
   }
 
@@ -27673,7 +27721,7 @@ static int fillInUnixFile(
     unixEnterMutex();
     rc = findInodeInfo(pNew, &pNew->pInode);
     if( rc!=SQLITE_OK ){
-      /* If an error occured in findInodeInfo(), close the file descriptor
+      /* If an error occurred in findInodeInfo(), close the file descriptor
       ** immediately, before releasing the mutex. findInodeInfo() may fail
       ** in two scenarios:
       **
@@ -28311,7 +28359,7 @@ static int unixDelete(
 }
 
 /*
-** Test the existance of or access permissions of file zPath. The
+** Test the existence of or access permissions of file zPath. The
 ** test performed depends on the value of flags:
 **
 **     SQLITE_ACCESS_EXISTS: Return 1 if the file exists
@@ -29874,7 +29922,7 @@ SQLITE_API int sqlite3_os_init(void){
 
   /* Double-check that the aSyscall[] array has been constructed
   ** correctly.  See ticket [bb3a86e890c8e96ab] */
-  assert( ArraySize(aSyscall)==22 );
+  assert( ArraySize(aSyscall)==21 );
 
   /* Register all VFSes defined in the aVfs[] array */
   for(i=0; i<(sizeof(aVfs)/sizeof(sqlite3_vfs)); i++){
@@ -30415,7 +30463,7 @@ static int sqlite3_os_type = 0;
 ** to all overrideable system calls.
 */
 static struct win_syscall {
-  const char *zName;            /* Name of the sytem call */
+  const char *zName;            /* Name of the system call */
   sqlite3_syscall_ptr pCurrent; /* Current value of the system call */
   sqlite3_syscall_ptr pDefault; /* Default value */
 } aSyscall[] = {
@@ -31095,7 +31143,7 @@ static const char *winNextSystemCall(sqlite3_vfs *p, const char *zName){
 ** (if available).
 */
 
-SQLITE_API void sqlite3_win32_write_debug(char *zBuf, int nBuf){
+SQLITE_API void sqlite3_win32_write_debug(const char *zBuf, int nBuf){
   char zDbgBuf[SQLITE_WIN32_DBG_BUF_SIZE];
   int nMin = MIN(nBuf, (SQLITE_WIN32_DBG_BUF_SIZE - 1)); /* may be negative. */
   if( nMin<-1 ) nMin = -1; /* all negative values become -1. */
@@ -31728,9 +31776,10 @@ static void logIoerr(int nRetry){
 /*************************************************************************
 ** This section contains code for WinCE only.
 */
+#if !defined(SQLITE_MSVC_LOCALTIME_API) || !SQLITE_MSVC_LOCALTIME_API
 /*
-** Windows CE does not have a localtime() function.  So create a
-** substitute.
+** The MSVC CRT on Windows CE may not have a localtime() function.  So
+** create a substitute.
 */
 /* #include <time.h> */
 struct tm *__cdecl localtime(const time_t *t)
@@ -31754,6 +31803,7 @@ struct tm *__cdecl localtime(const time_t *t)
   y.tm_sec = pTm.wSecond;
   return &y;
 }
+#endif
 
 #define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,h)]
 
@@ -31775,15 +31825,17 @@ static void winceMutexAcquire(HANDLE h){
 ** Create the mutex and shared memory used for locking in the file
 ** descriptor pFile
 */
-static BOOL winceCreateLock(const char *zFilename, winFile *pFile){
+static int winceCreateLock(const char *zFilename, winFile *pFile){
   LPWSTR zTok;
   LPWSTR zName;
+  DWORD lastErrno;
+  BOOL bLogged = FALSE;
   BOOL bInit = TRUE;
 
   zName = utf8ToUnicode(zFilename);
   if( zName==0 ){
     /* out of memory */
-    return FALSE;
+    return SQLITE_IOERR_NOMEM;
   }
 
   /* Initialize the local lockdata */
@@ -31800,9 +31852,10 @@ static BOOL winceCreateLock(const char *zFilename, winFile *pFile){
   pFile->hMutex = osCreateMutexW(NULL, FALSE, zName);
   if (!pFile->hMutex){
     pFile->lastErrno = osGetLastError();
-    winLogError(SQLITE_ERROR, pFile->lastErrno, "winceCreateLock1", zFilename);
+    winLogError(SQLITE_IOERR, pFile->lastErrno,
+                "winceCreateLock1", zFilename);
     sqlite3_free(zName);
-    return FALSE;
+    return SQLITE_IOERR;
   }
 
   /* Acquire the mutex before continuing */
@@ -31819,41 +31872,49 @@ static BOOL winceCreateLock(const char *zFilename, winFile *pFile){
 
   /* Set a flag that indicates we're the first to create the memory so it 
   ** must be zero-initialized */
-  if (osGetLastError() == ERROR_ALREADY_EXISTS){
+  lastErrno = osGetLastError();
+  if (lastErrno == ERROR_ALREADY_EXISTS){
     bInit = FALSE;
   }
 
   sqlite3_free(zName);
 
   /* If we succeeded in making the shared memory handle, map it. */
-  if (pFile->hShared){
+  if( pFile->hShared ){
     pFile->shared = (winceLock*)osMapViewOfFile(pFile->hShared, 
              FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(winceLock));
     /* If mapping failed, close the shared memory handle and erase it */
-    if (!pFile->shared){
+    if( !pFile->shared ){
       pFile->lastErrno = osGetLastError();
-      winLogError(SQLITE_ERROR, pFile->lastErrno,
-               "winceCreateLock2", zFilename);
+      winLogError(SQLITE_IOERR, pFile->lastErrno,
+                  "winceCreateLock2", zFilename);
+      bLogged = TRUE;
       osCloseHandle(pFile->hShared);
       pFile->hShared = NULL;
     }
   }
 
   /* If shared memory could not be created, then close the mutex and fail */
-  if (pFile->hShared == NULL){
+  if( pFile->hShared==NULL ){
+    if( !bLogged ){
+      pFile->lastErrno = lastErrno;
+      winLogError(SQLITE_IOERR, pFile->lastErrno,
+                  "winceCreateLock3", zFilename);
+      bLogged = TRUE;
+    }
     winceMutexRelease(pFile->hMutex);
     osCloseHandle(pFile->hMutex);
     pFile->hMutex = NULL;
-    return FALSE;
+    return SQLITE_IOERR;
   }
   
   /* Initialize the shared memory if we're supposed to */
-  if (bInit) {
+  if( bInit ){
     memset(pFile->shared, 0, sizeof(winceLock));
   }
 
   winceMutexRelease(pFile->hMutex);
-  return TRUE;
+  return SQLITE_OK;
 }
 
 /*
@@ -31932,7 +31993,8 @@ static BOOL winceLockFile(
   }
 
   /* Want a pending lock? */
-  else if (dwFileOffsetLow == (DWORD)PENDING_BYTE && nNumberOfBytesToLockLow == 1){
+  else if (dwFileOffsetLow == (DWORD)PENDING_BYTE
+           && nNumberOfBytesToLockLow == 1){
     /* If no pending lock has been acquired, then acquire it */
     if (pFile->shared->bPending == 0) {
       pFile->shared->bPending = TRUE;
@@ -31942,7 +32004,8 @@ static BOOL winceLockFile(
   }
 
   /* Want a reserved lock? */
-  else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE && nNumberOfBytesToLockLow == 1){
+  else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE
+           && nNumberOfBytesToLockLow == 1){
     if (pFile->shared->bReserved == 0) {
       pFile->shared->bReserved = TRUE;
       pFile->local.bReserved = TRUE;
@@ -31985,7 +32048,8 @@ static BOOL winceUnlockFile(
 
     /* Did we just have a reader lock? */
     else if (pFile->local.nReaders){
-      assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE || nNumberOfBytesToUnlockLow == 1);
+      assert(nNumberOfBytesToUnlockLow == (DWORD)SHARED_SIZE
+             || nNumberOfBytesToUnlockLow == 1);
       pFile->local.nReaders --;
       if (pFile->local.nReaders == 0)
       {
@@ -31996,7 +32060,8 @@ static BOOL winceUnlockFile(
   }
 
   /* Releasing a pending lock */
-  else if (dwFileOffsetLow == (DWORD)PENDING_BYTE && nNumberOfBytesToUnlockLow == 1){
+  else if (dwFileOffsetLow == (DWORD)PENDING_BYTE
+           && nNumberOfBytesToUnlockLow == 1){
     if (pFile->local.bPending){
       pFile->local.bPending = FALSE;
       pFile->shared->bPending = FALSE;
@@ -32004,7 +32069,8 @@ static BOOL winceUnlockFile(
     }
   }
   /* Releasing a reserved lock */
-  else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE && nNumberOfBytesToUnlockLow == 1){
+  else if (dwFileOffsetLow == (DWORD)RESERVED_BYTE
+           && nNumberOfBytesToUnlockLow == 1){
     if (pFile->local.bReserved) {
       pFile->local.bReserved = FALSE;
       pFile->shared->bReserved = FALSE;
@@ -32114,7 +32180,7 @@ static int seekWinFile(winFile *pFile, sqlite3_int64 iOffset){
   ** containing the lower 32-bits of the new file-offset. Or, if it fails,
   ** it returns INVALID_SET_FILE_POINTER. However according to MSDN, 
   ** INVALID_SET_FILE_POINTER may also be a valid new offset. So to determine 
-  ** whether an error has actually occured, it is also necessary to call 
+  ** whether an error has actually occurred, it is also necessary to call 
   ** GetLastError().
   */
   dwRet = osSetFilePointer(pFile->h, lowerBits, &upperBits, FILE_BEGIN);
@@ -32170,6 +32236,7 @@ static int winClose(sqlite3_file *id){
   assert( pFile->pShm==0 );
 #endif
   OSTRACE(("CLOSE %d\n", pFile->h));
+  assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE );
   do{
     rc = osCloseHandle(pFile->h);
     /* SimulateIOError( rc=0; cnt=MX_CLOSE_ATTEMPT; ); */
@@ -32259,7 +32326,7 @@ static int winWrite(
   int amt,                        /* Number of bytes to write */
   sqlite3_int64 offset            /* Offset into the file to begin writing at */
 ){
-  int rc = 0;                     /* True if error has occured, else false */
+  int rc = 0;                     /* True if error has occurred, else false */
   winFile *pFile = (winFile*)id;  /* File handle */
   int nRetry = 0;                 /* Number of retries */
 
@@ -32862,7 +32929,7 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
       return SQLITE_OK;
     }
     case SQLITE_FCNTL_TEMPFILENAME: {
-      char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname );
+      char *zTFile = sqlite3MallocZero( pFile->pVfs->mxPathname );
       if( zTFile ){
         getTempname(pFile->pVfs->mxPathname, zTFile);
         *(char**)pArg = zTFile;
@@ -33086,7 +33153,7 @@ static void winShmPurge(sqlite3_vfs *pVfs, int deleteFlag){
                  (int)osGetCurrentProcessId(), i,
                  bRc ? "ok" : "failed"));
       }
-      if( p->hFile.h != INVALID_HANDLE_VALUE ){
+      if( p->hFile.h!=NULL && p->hFile.h!=INVALID_HANDLE_VALUE ){
         SimulateIOErrorBenign(1);
         winClose((sqlite3_file *)&p->hFile);
         SimulateIOErrorBenign(0);
@@ -33166,7 +33233,7 @@ static int winOpenSharedMemory(winFile *pDbFd){
     rc = winOpen(pDbFd->pVfs,
                  pShmNode->zFilename,             /* Name of the file (UTF-8) */
                  (sqlite3_file*)&pShmNode->hFile,  /* File handle here */
-                 SQLITE_OPEN_WAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, /* Mode flags */
+                 SQLITE_OPEN_WAL | SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
                  0);
     if( SQLITE_OK!=rc ){
       goto shm_open_err;
@@ -33781,8 +33848,9 @@ static int winOpen(
        || eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
   );
 
-  assert( id!=0 );
-  UNUSED_PARAMETER(pVfs);
+  assert( pFile!=0 );
+  memset(pFile, 0, sizeof(winFile));
+  pFile->h = INVALID_HANDLE_VALUE;
 
 #if SQLITE_OS_WINRT
   if( !sqlite3_temp_directory ){
@@ -33791,13 +33859,12 @@ static int winOpen(
   }
 #endif
 
-  pFile->h = INVALID_HANDLE_VALUE;
-
   /* If the second argument to this function is NULL, generate a 
   ** temporary file name to use 
   */
   if( !zUtf8Name ){
     assert(isDelete && !isOpenJournal);
+    memset(zTmpname, 0, MAX_PATH+2);
     rc = getTempname(MAX_PATH+2, zTmpname);
     if( rc!=SQLITE_OK ){
       return rc;
@@ -33920,7 +33987,9 @@ static int winOpen(
     sqlite3_free(zConverted);
     if( isReadWrite && !isExclusive ){
       return winOpen(pVfs, zName, id, 
-             ((flags|SQLITE_OPEN_READONLY)&~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)), pOutFlags);
+         ((flags|SQLITE_OPEN_READONLY) &
+                     ~(SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE)),
+         pOutFlags);
     }else{
       return SQLITE_CANTOPEN_BKPT;
     }
@@ -33934,26 +34003,13 @@ static int winOpen(
     }
   }
 
-  memset(pFile, 0, sizeof(*pFile));
-  pFile->pMethod = &winIoMethod;
-  pFile->h = h;
-  pFile->lastErrno = NO_ERROR;
-  pFile->pVfs = pVfs;
-#ifndef SQLITE_OMIT_WAL
-  pFile->pShm = 0;
-#endif
-  pFile->zPath = zName;
-  if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
-    pFile->ctrlFlags |= WINFILE_PSOW;
-  }
-
 #if SQLITE_OS_WINCE
   if( isReadWrite && eType==SQLITE_OPEN_MAIN_DB
-       && !winceCreateLock(zName, pFile)
+       && (rc = winceCreateLock(zName, pFile))!=SQLITE_OK
   ){
     osCloseHandle(h);
     sqlite3_free(zConverted);
-    return SQLITE_CANTOPEN_BKPT;
+    return rc;
   }
   if( isTemp ){
     pFile->zDeleteOnClose = zConverted;
@@ -33963,6 +34019,15 @@ static int winOpen(
     sqlite3_free(zConverted);
   }
 
+  pFile->pMethod = &winIoMethod;
+  pFile->pVfs = pVfs;
+  pFile->h = h;
+  if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
+    pFile->ctrlFlags |= WINFILE_PSOW;
+  }
+  pFile->lastErrno = NO_ERROR;
+  pFile->zPath = zName;
+
   OpenCounter(+1);
   return rc;
 }
@@ -34007,7 +34072,8 @@ static int winDelete(
         attr = sAttrData.dwFileAttributes;
       }else{
         lastErrno = osGetLastError();
-        if( lastErrno==ERROR_FILE_NOT_FOUND || lastErrno==ERROR_PATH_NOT_FOUND ){
+        if( lastErrno==ERROR_FILE_NOT_FOUND
+         || lastErrno==ERROR_PATH_NOT_FOUND ){
           rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
         }else{
           rc = SQLITE_ERROR;
@@ -34019,7 +34085,8 @@ static int winDelete(
 #endif
       if ( attr==INVALID_FILE_ATTRIBUTES ){
         lastErrno = osGetLastError();
-        if( lastErrno==ERROR_FILE_NOT_FOUND || lastErrno==ERROR_PATH_NOT_FOUND ){
+        if( lastErrno==ERROR_FILE_NOT_FOUND
+         || lastErrno==ERROR_PATH_NOT_FOUND ){
           rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
         }else{
           rc = SQLITE_ERROR;
@@ -34046,7 +34113,8 @@ static int winDelete(
       attr = osGetFileAttributesA(zConverted);
       if ( attr==INVALID_FILE_ATTRIBUTES ){
         lastErrno = osGetLastError();
-        if( lastErrno==ERROR_FILE_NOT_FOUND || lastErrno==ERROR_PATH_NOT_FOUND ){
+        if( lastErrno==ERROR_FILE_NOT_FOUND
+         || lastErrno==ERROR_PATH_NOT_FOUND ){
           rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */
         }else{
           rc = SQLITE_ERROR;
@@ -34080,7 +34148,7 @@ static int winDelete(
 }
 
 /*
-** Check the existance and status of a file.
+** Check the existence and status of a file.
 */
 static int winAccess(
   sqlite3_vfs *pVfs,         /* Not used on win32 */
@@ -34214,16 +34282,12 @@ static int winFullPathname(
     */
     char zOut[MAX_PATH+1];
     memset(zOut, 0, MAX_PATH+1);
-    cygwin_conv_to_win32_path(zRelative, zOut); /* POSIX to Win32 */
+    cygwin_conv_path(CCP_POSIX_TO_WIN_A|CCP_RELATIVE, zRelative, zOut,
+                     MAX_PATH+1);
     sqlite3_snprintf(MIN(nFull, pVfs->mxPathname), zFull, "%s\\%s",
                      sqlite3_data_directory, zOut);
   }else{
-    /*
-    ** NOTE: The Cygwin docs state that the maximum length needed
-    **       for the buffer passed to cygwin_conv_to_full_win32_path
-    **       is MAX_PATH.
-    */
-    cygwin_conv_to_full_win32_path(zRelative, zFull);
+    cygwin_conv_path(CCP_POSIX_TO_WIN_A, zRelative, zFull, nFull);
   }
   return SQLITE_OK;
 #endif
@@ -34381,9 +34445,9 @@ static void winDlError(sqlite3_vfs *pVfs, int nBuf, char *zBufOut){
   UNUSED_PARAMETER(pVfs);
   getLastErrorMsg(osGetLastError(), nBuf, zBufOut);
 }
-static void (*winDlSym(sqlite3_vfs *pVfs, void *pHandle, const char *zSymbol))(void){
+static void (*winDlSym(sqlite3_vfs *pVfs,void *pH,const char *zSym))(void){
   UNUSED_PARAMETER(pVfs);
-  return (void(*)(void))osGetProcAddressA((HANDLE)pHandle, zSymbol);
+  return (void(*)(void))osGetProcAddressA((HANDLE)pH, zSym);
 }
 static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
   UNUSED_PARAMETER(pVfs);
@@ -34481,7 +34545,8 @@ static int winCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *piNow){
 #endif
   /* 2^32 - to avoid use of LL and warnings in gcc */
   static const sqlite3_int64 max32BitValue = 
-      (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 + (sqlite3_int64)294967296;
+      (sqlite3_int64)2000000000 + (sqlite3_int64)2000000000 +
+      (sqlite3_int64)294967296;
 
 #if SQLITE_OS_WINCE
   SYSTEMTIME time;
@@ -34692,7 +34757,7 @@ SQLITE_API int sqlite3_os_end(void){
 /*
 ** A bitmap is an instance of the following structure.
 **
-** This bitmap records the existance of zero or more bits
+** This bitmap records the existence of zero or more bits
 ** with values between 1 and iSize, inclusive.
 **
 ** There are three possible representations of the bitmap.
@@ -37594,7 +37659,7 @@ int sqlite3PagerTrace=1;  /* True to enable tracing */
 **    * A write transaction is active.
 **    * An EXCLUSIVE or greater lock is held on the database file.
 **    * All writing and syncing of journal and database data has finished.
-**      If no error occured, all that remains is to finalize the journal to
+**      If no error occurred, all that remains is to finalize the journal to
 **      commit the transaction. If an error did occur, the caller will need
 **      to rollback the transaction. 
 **
@@ -37842,7 +37907,7 @@ struct PagerSavepoint {
 **
 ** doNotSpill, doNotSyncSpill
 **
-**   These two boolean variables control the behaviour of cache-spills
+**   These two boolean variables control the behavior of cache-spills
 **   (calls made by the pcache module to the pagerStress() routine to
 **   write cached data to the file-system in order to free up memory).
 **
@@ -38720,7 +38785,7 @@ static int writeJournalHdr(Pager *pPager){
     memset(zHeader, 0, sizeof(aJournalMagic)+4);
   }
 
-  /* The random check-hash initialiser */ 
+  /* The random check-hash initializer */ 
   sqlite3_randomness(sizeof(pPager->cksumInit), &pPager->cksumInit);
   put32bits(&zHeader[sizeof(aJournalMagic)+4], pPager->cksumInit);
   /* The initial database size */
@@ -39159,6 +39224,8 @@ static int pager_error(Pager *pPager, int rc){
   return rc;
 }
 
+static int pager_truncate(Pager *pPager, Pgno nPage);
+
 /*
 ** This routine ends a transaction. A transaction is usually ended by 
 ** either a COMMIT or a ROLLBACK operation. This routine may be called 
@@ -39212,7 +39279,7 @@ static int pager_error(Pager *pPager, int rc){
 ** to the first error encountered (the journal finalization one) is
 ** returned.
 */
-static int pager_end_transaction(Pager *pPager, int hasMaster){
+static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
   int rc = SQLITE_OK;      /* Error code from journal finalization operation */
   int rc2 = SQLITE_OK;     /* Error code from db file unlock operation */
 
@@ -39298,7 +39365,17 @@ static int pager_end_transaction(Pager *pPager, int hasMaster){
     */
     rc2 = sqlite3WalEndWriteTransaction(pPager->pWal);
     assert( rc2==SQLITE_OK );
+  }else if( rc==SQLITE_OK && bCommit && pPager->dbFileSize>pPager->dbSize ){
+    /* This branch is taken when committing a transaction in rollback-journal
+    ** mode if the database file on disk is larger than the database image.
+    ** At this point the journal has been finalized and the transaction 
+    ** successfully committed, but the EXCLUSIVE lock is still held on the
+    ** file. So it is safe to truncate the database file to its minimum
+    ** required size.  */
+    assert( pPager->eLock==EXCLUSIVE_LOCK );
+    rc = pager_truncate(pPager, pPager->dbSize);
   }
+
   if( !pPager->exclusiveMode 
    && (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
   ){
@@ -39337,7 +39414,7 @@ static void pagerUnlockAndRollback(Pager *pPager){
       sqlite3EndBenignMalloc();
     }else if( !pPager->exclusiveMode ){
       assert( pPager->eState==PAGER_READER );
-      pager_end_transaction(pPager, 0);
+      pager_end_transaction(pPager, 0, 0);
     }
   }
   pager_unlock(pPager);
@@ -40112,7 +40189,7 @@ end_playback:
     rc = sqlite3PagerSync(pPager);
   }
   if( rc==SQLITE_OK ){
-    rc = pager_end_transaction(pPager, zMaster[0]!='\0');
+    rc = pager_end_transaction(pPager, zMaster[0]!='\0', 0);
     testcase( rc!=SQLITE_OK );
   }
   if( rc==SQLITE_OK && zMaster[0] && res ){
@@ -41040,7 +41117,7 @@ static int pager_wait_on_lock(Pager *pPager, int locktype){
 ** dirty page were to be discarded from the cache via the pagerStress()
 ** routine, pagerStress() would not write the current page content to
 ** the database file. If a savepoint transaction were rolled back after
-** this happened, the correct behaviour would be to restore the current
+** this happened, the correct behavior would be to restore the current
 ** content of the page. However, since this content is not present in either
 ** the database file or the portion of the rollback journal and 
 ** sub-journal rolled back the content could not be restored and the
@@ -41064,12 +41141,26 @@ static void assertTruncateConstraint(Pager *pPager){
 ** function does not actually modify the database file on disk. It 
 ** just sets the internal state of the pager object so that the 
 ** truncation will be done when the current transaction is committed.
+**
+** This function is only called right before committing a transaction.
+** Once this function has been called, the transaction must either be
+** rolled back or committed. It is not safe to call this function and
+** then continue writing to the database.
 */
 SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager *pPager, Pgno nPage){
   assert( pPager->dbSize>=nPage );
   assert( pPager->eState>=PAGER_WRITER_CACHEMOD );
   pPager->dbSize = nPage;
-  assertTruncateConstraint(pPager);
+
+  /* At one point the code here called assertTruncateConstraint() to
+  ** ensure that all pages being truncated away by this operation are,
+  ** if one or more savepoints are open, present in the savepoint 
+  ** journal so that they can be restored if the savepoint is rolled
+  ** back. This is no longer necessary as this function is now only
+  ** called right before committing a transaction. So although the 
+  ** Pager object may still have open savepoints (Pager.nSavepoint!=0), 
+  ** they cannot be rolled back. So the assertTruncateConstraint() call
+  ** is no longer correct. */
 }
 
 
@@ -42122,6 +42213,11 @@ SQLITE_PRIVATE int sqlite3PagerSharedLock(Pager *pPager){
       goto failed;
     }
     if( bHotJournal ){
+      if( pPager->readOnly ){
+        rc = SQLITE_READONLY_ROLLBACK;
+        goto failed;
+      }
+
       /* Get an EXCLUSIVE lock on the database file. At this point it is
       ** important that a RESERVED lock is not obtained on the way to the
       ** EXCLUSIVE lock. If it were, another process might open the
@@ -43206,36 +43302,6 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
   #endif
       if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
   
-      /* If this transaction has made the database smaller, then all pages
-      ** being discarded by the truncation must be written to the journal
-      ** file.
-      **
-      ** Before reading the pages with page numbers larger than the 
-      ** current value of Pager.dbSize, set dbSize back to the value
-      ** that it took at the start of the transaction. Otherwise, the
-      ** calls to sqlite3PagerGet() return zeroed pages instead of 
-      ** reading data from the database file.
-      */
-      if( pPager->dbSize<pPager->dbOrigSize 
-       && pPager->journalMode!=PAGER_JOURNALMODE_OFF
-      ){
-        Pgno i;                                   /* Iterator variable */
-        const Pgno iSkip = PAGER_MJ_PGNO(pPager); /* Pending lock page */
-        const Pgno dbSize = pPager->dbSize;       /* Database image size */ 
-        pPager->dbSize = pPager->dbOrigSize;
-        for( i=dbSize+1; i<=pPager->dbOrigSize; i++ ){
-          if( !sqlite3BitvecTest(pPager->pInJournal, i) && i!=iSkip ){
-            PgHdr *pPage;             /* Page to journal */
-            rc = sqlite3PagerGet(pPager, i, &pPage);
-            if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
-            rc = sqlite3PagerWrite(pPage);
-            sqlite3PagerUnref(pPage);
-            if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
-          }
-        }
-        pPager->dbSize = dbSize;
-      } 
-  
       /* Write the master journal name into the journal file. If a master 
       ** journal file name has already been written to the journal file, 
       ** or if zMaster is NULL (no master journal), then this call is a no-op.
@@ -43263,11 +43329,14 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseOne(
         goto commit_phase_one_exit;
       }
       sqlite3PcacheCleanAll(pPager->pPCache);
-  
-      /* If the file on disk is not the same size as the database image,
-      ** then use pager_truncate to grow or shrink the file here.
-      */
-      if( pPager->dbSize!=pPager->dbFileSize ){
+
+      /* If the file on disk is smaller than the database image, use 
+      ** pager_truncate to grow the file here. This can happen if the database
+      ** image was extended as part of the current transaction and then the
+      ** last page in the db image moved to the free-list. In this case the
+      ** last page is never written out to disk, leaving the database file
+      ** undersized. Fix this now if it is the case.  */
+      if( pPager->dbSize>pPager->dbFileSize ){
         Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager));
         assert( pPager->eState==PAGER_WRITER_DBMOD );
         rc = pager_truncate(pPager, nNew);
@@ -43340,7 +43409,7 @@ SQLITE_PRIVATE int sqlite3PagerCommitPhaseTwo(Pager *pPager){
   }
 
   PAGERTRACE(("COMMIT %d\n", PAGERID(pPager)));
-  rc = pager_end_transaction(pPager, pPager->setMaster);
+  rc = pager_end_transaction(pPager, pPager->setMaster, 1);
   return pager_error(pPager, rc);
 }
 
@@ -43385,11 +43454,11 @@ SQLITE_PRIVATE int sqlite3PagerRollback(Pager *pPager){
   if( pagerUseWal(pPager) ){
     int rc2;
     rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1);
-    rc2 = pager_end_transaction(pPager, pPager->setMaster);
+    rc2 = pager_end_transaction(pPager, pPager->setMaster, 0);
     if( rc==SQLITE_OK ) rc = rc2;
   }else if( !isOpen(pPager->jfd) || pPager->eState==PAGER_WRITER_LOCKED ){
     int eState = pPager->eState;
-    rc = pager_end_transaction(pPager, 0);
+    rc = pager_end_transaction(pPager, 0, 0);
     if( !MEMDB && eState>PAGER_WRITER_LOCKED ){
       /* This can happen using journal_mode=off. Move the pager to the error 
       ** state to indicate that the contents of the cache may not be trusted.
@@ -43787,7 +43856,8 @@ SQLITE_PRIVATE int sqlite3PagerMovepage(Pager *pPager, DbPage *pPg, Pgno pgno, i
   */
   if( (pPg->flags&PGHDR_NEED_SYNC) && !isCommit ){
     needSyncPgno = pPg->pgno;
-    assert( pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize );
+    assert( pPager->journalMode==PAGER_JOURNALMODE_OFF ||
+            pageInJournal(pPg) || pPg->pgno>pPager->dbOrigSize );
     assert( pPg->flags&PGHDR_DIRTY );
   }
 
@@ -47791,6 +47861,7 @@ struct BtShared {
 #ifndef SQLITE_OMIT_AUTOVACUUM
   u8 autoVacuum;        /* True if auto-vacuum is enabled */
   u8 incrVacuum;        /* True if incr-vacuum is enabled */
+  u8 bDoTruncate;       /* True to truncate db on commit */
 #endif
   u8 inTransaction;     /* Transaction state */
   u8 max1bytePayload;   /* Maximum first byte of cell for a 1-byte payload */
@@ -48357,6 +48428,25 @@ int sqlite3BtreeTrace=1;  /* True to enable tracing */
 */
 #define get2byteNotZero(X)  (((((int)get2byte(X))-1)&0xffff)+1)
 
+/*
+** Values passed as the 5th argument to allocateBtreePage()
+*/
+#define BTALLOC_ANY   0           /* Allocate any page */
+#define BTALLOC_EXACT 1           /* Allocate exact page if possible */
+#define BTALLOC_LE    2           /* Allocate any page <= the parameter */
+
+/*
+** Macro IfNotOmitAV(x) returns (x) if SQLITE_OMIT_AUTOVACUUM is not 
+** defined, or 0 if it is. For example:
+**
+**   bIncrVacuum = IfNotOmitAV(pBtShared->incrVacuum);
+*/
+#ifndef SQLITE_OMIT_AUTOVACUUM
+#define IfNotOmitAV(expr) (expr)
+#else
+#define IfNotOmitAV(expr) 0
+#endif
+
 #ifndef SQLITE_OMIT_SHARED_CACHE
 /*
 ** A list of BtShared objects that are eligible for participation
@@ -48870,6 +48960,19 @@ static void btreeClearHasContent(BtShared *pBt){
   pBt->pHasContent = 0;
 }
 
+/*
+** Release all of the apPage[] pages for a cursor.
+*/
+static void btreeReleaseAllCursorPages(BtCursor *pCur){
+  int i;
+  for(i=0; i<=pCur->iPage; i++){
+    releasePage(pCur->apPage[i]);
+    pCur->apPage[i] = 0;
+  }
+  pCur->iPage = -1;
+}
+
+
 /*
 ** Save the current cursor position in the variables BtCursor.nKey 
 ** and BtCursor.pKey. The cursor's state is set to CURSOR_REQUIRESEEK.
@@ -48909,12 +49012,7 @@ static int saveCursorPosition(BtCursor *pCur){
   assert( !pCur->apPage[0]->intKey || !pCur->pKey );
 
   if( rc==SQLITE_OK ){
-    int i;
-    for(i=0; i<=pCur->iPage; i++){
-      releasePage(pCur->apPage[i]);
-      pCur->apPage[i] = 0;
-    }
-    pCur->iPage = -1;
+    btreeReleaseAllCursorPages(pCur);
     pCur->eState = CURSOR_REQUIRESEEK;
   }
 
@@ -48932,11 +49030,15 @@ static int saveAllCursors(BtShared *pBt, Pgno iRoot, BtCursor *pExcept){
   assert( sqlite3_mutex_held(pBt->mutex) );
   assert( pExcept==0 || pExcept->pBt==pBt );
   for(p=pBt->pCursor; p; p=p->pNext){
-    if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) && 
-        p->eState==CURSOR_VALID ){
-      int rc = saveCursorPosition(p);
-      if( SQLITE_OK!=rc ){
-        return rc;
+    if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ){
+      if( p->eState==CURSOR_VALID ){
+        int rc = saveCursorPosition(p);
+        if( SQLITE_OK!=rc ){
+          return rc;
+        }
+      }else{
+        testcase( p->iPage>0 );
+        btreeReleaseAllCursorPages(p);
       }
     }
   }
@@ -50524,7 +50626,7 @@ SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree *p){
 ** known that the shared b-tree mutex is held, but the mutex on the 
 ** database handle that owns *p is not. In this case if sqlite3BtreeEnter()
 ** were to be called, it might collide with some other operation on the
-** database handle that owns *p, causing undefined behaviour.
+** database handle that owns *p, causing undefined behavior.
 */
 SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p){
   assert( sqlite3_mutex_held(p->pBt->mutex) );
@@ -50909,6 +51011,7 @@ SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag){
   if( p->inTrans==TRANS_WRITE || (p->inTrans==TRANS_READ && !wrflag) ){
     goto trans_begun;
   }
+  assert( IfNotOmitAV(pBt->bDoTruncate)==0 );
 
   /* Write transactions are not possible on a read-only database */
   if( (pBt->btsFlags & BTS_READ_ONLY)!=0 && wrflag ){
@@ -51225,24 +51328,23 @@ static int relocatePage(
 static int allocateBtreePage(BtShared *, MemPage **, Pgno *, Pgno, u8);
 
 /*
-** Perform a single step of an incremental-vacuum. If successful,
-** return SQLITE_OK. If there is no work to do (and therefore no
-** point in calling this function again), return SQLITE_DONE.
+** Perform a single step of an incremental-vacuum. If successful, return
+** SQLITE_OK. If there is no work to do (and therefore no point in 
+** calling this function again), return SQLITE_DONE. Or, if an error 
+** occurs, return some other error code.
+**
+** More specificly, this function attempts to re-organize the database so 
+** that the last page of the file currently in use is no longer in use.
 **
-** More specificly, this function attempts to re-organize the 
-** database so that the last page of the file currently in use
-** is no longer in use.
+** Parameter nFin is the number of pages that this database would contain
+** were this function called until it returns SQLITE_DONE.
 **
-** If the nFin parameter is non-zero, this function assumes
-** that the caller will keep calling incrVacuumStep() until
-** it returns SQLITE_DONE or an error, and that nFin is the
-** number of pages the database file will contain after this 
-** process is complete.  If nFin is zero, it is assumed that
-** incrVacuumStep() will be called a finite amount of times
-** which may or may not empty the freelist.  A full autovacuum
-** has nFin>0.  A "PRAGMA incremental_vacuum" has nFin==0.
+** If the bCommit parameter is non-zero, this function assumes that the 
+** caller will keep calling incrVacuumStep() until it returns SQLITE_DONE 
+** or an error. bCommit is passed true for an auto-vacuum-on-commmit 
+** operation, or false for an incremental vacuum.
 */
-static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
+static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg, int bCommit){
   Pgno nFreeList;           /* Number of pages still on the free-list */
   int rc;
 
@@ -51267,15 +51369,15 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
     }
 
     if( eType==PTRMAP_FREEPAGE ){
-      if( nFin==0 ){
+      if( bCommit==0 ){
         /* Remove the page from the files free-list. This is not required
-        ** if nFin is non-zero. In that case, the free-list will be
+        ** if bCommit is non-zero. In that case, the free-list will be
         ** truncated to zero after this function returns, so it doesn't 
         ** matter if it still contains some garbage entries.
         */
         Pgno iFreePg;
         MemPage *pFreePg;
-        rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iLastPg, 1);
+        rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iLastPg, BTALLOC_EXACT);
         if( rc!=SQLITE_OK ){
           return rc;
         }
@@ -51285,34 +51387,37 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
     } else {
       Pgno iFreePg;             /* Index of free page to move pLastPg to */
       MemPage *pLastPg;
+      u8 eMode = BTALLOC_ANY;   /* Mode parameter for allocateBtreePage() */
+      Pgno iNear = 0;           /* nearby parameter for allocateBtreePage() */
 
       rc = btreeGetPage(pBt, iLastPg, &pLastPg, 0);
       if( rc!=SQLITE_OK ){
         return rc;
       }
 
-      /* If nFin is zero, this loop runs exactly once and page pLastPg
+      /* If bCommit is zero, this loop runs exactly once and page pLastPg
       ** is swapped with the first free page pulled off the free list.
       **
-      ** On the other hand, if nFin is greater than zero, then keep
+      ** On the other hand, if bCommit is greater than zero, then keep
       ** looping until a free-page located within the first nFin pages
       ** of the file is found.
       */
+      if( bCommit==0 ){
+        eMode = BTALLOC_LE;
+        iNear = nFin;
+      }
       do {
         MemPage *pFreePg;
-        rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, 0, 0);
+        rc = allocateBtreePage(pBt, &pFreePg, &iFreePg, iNear, eMode);
         if( rc!=SQLITE_OK ){
           releasePage(pLastPg);
           return rc;
         }
         releasePage(pFreePg);
-      }while( nFin!=0 && iFreePg>nFin );
+      }while( bCommit && iFreePg>nFin );
       assert( iFreePg<iLastPg );
       
-      rc = sqlite3PagerWrite(pLastPg->pDbPage);
-      if( rc==SQLITE_OK ){
-        rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, nFin!=0);
-      }
+      rc = relocatePage(pBt, pLastPg, eType, iPtrPage, iFreePg, bCommit);
       releasePage(pLastPg);
       if( rc!=SQLITE_OK ){
         return rc;
@@ -51320,29 +51425,39 @@ static int incrVacuumStep(BtShared *pBt, Pgno nFin, Pgno iLastPg){
     }
   }
 
-  if( nFin==0 ){
-    iLastPg--;
-    while( iLastPg==PENDING_BYTE_PAGE(pBt)||PTRMAP_ISPAGE(pBt, iLastPg) ){
-      if( PTRMAP_ISPAGE(pBt, iLastPg) ){
-        MemPage *pPg;
-        rc = btreeGetPage(pBt, iLastPg, &pPg, 0);
-        if( rc!=SQLITE_OK ){
-          return rc;
-        }
-        rc = sqlite3PagerWrite(pPg->pDbPage);
-        releasePage(pPg);
-        if( rc!=SQLITE_OK ){
-          return rc;
-        }
-      }
+  if( bCommit==0 ){
+    do {
       iLastPg--;
-    }
-    sqlite3PagerTruncateImage(pBt->pPager, iLastPg);
+    }while( iLastPg==PENDING_BYTE_PAGE(pBt) || PTRMAP_ISPAGE(pBt, iLastPg) );
+    pBt->bDoTruncate = 1;
     pBt->nPage = iLastPg;
   }
   return SQLITE_OK;
 }
 
+/*
+** The database opened by the first argument is an auto-vacuum database
+** nOrig pages in size containing nFree free pages. Return the expected 
+** size of the database in pages following an auto-vacuum operation.
+*/
+static Pgno finalDbSize(BtShared *pBt, Pgno nOrig, Pgno nFree){
+  int nEntry;                     /* Number of entries on one ptrmap page */
+  Pgno nPtrmap;                   /* Number of PtrMap pages to be freed */
+  Pgno nFin;                      /* Return value */
+
+  nEntry = pBt->usableSize/5;
+  nPtrmap = (nFree-nOrig+PTRMAP_PAGENO(pBt, nOrig)+nEntry)/nEntry;
+  nFin = nOrig - nFree - nPtrmap;
+  if( nOrig>PENDING_BYTE_PAGE(pBt) && nFin<PENDING_BYTE_PAGE(pBt) ){
+    nFin--;
+  }
+  while( PTRMAP_ISPAGE(pBt, nFin) || nFin==PENDING_BYTE_PAGE(pBt) ){
+    nFin--;
+  }
+
+  return nFin;
+}
+
 /*
 ** A write-transaction must be opened before calling this function.
 ** It performs a single unit of work towards an incremental vacuum.
@@ -51360,11 +51475,21 @@ SQLITE_PRIVATE int sqlite3BtreeIncrVacuum(Btree *p){
   if( !pBt->autoVacuum ){
     rc = SQLITE_DONE;
   }else{
-    invalidateAllOverflowCache(pBt);
-    rc = incrVacuumStep(pBt, 0, btreePagecount(pBt));
-    if( rc==SQLITE_OK ){
-      rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
-      put4byte(&pBt->pPage1->aData[28], pBt->nPage);
+    Pgno nOrig = btreePagecount(pBt);
+    Pgno nFree = get4byte(&pBt->pPage1->aData[36]);
+    Pgno nFin = finalDbSize(pBt, nOrig, nFree);
+
+    if( nOrig<nFin ){
+      rc = SQLITE_CORRUPT_BKPT;
+    }else if( nFree>0 ){
+      invalidateAllOverflowCache(pBt);
+      rc = incrVacuumStep(pBt, nFin, nOrig, 0);
+      if( rc==SQLITE_OK ){
+        rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
+        put4byte(&pBt->pPage1->aData[28], pBt->nPage);
+      }
+    }else{
+      rc = SQLITE_DONE;
     }
   }
   sqlite3BtreeLeave(p);
@@ -51391,9 +51516,7 @@ static int autoVacuumCommit(BtShared *pBt){
   if( !pBt->incrVacuum ){
     Pgno nFin;         /* Number of pages in database after autovacuuming */
     Pgno nFree;        /* Number of pages on the freelist initially */
-    Pgno nPtrmap;      /* Number of PtrMap pages to be freed */
     Pgno iFree;        /* The next page to be freed */
-    int nEntry;        /* Number of entries on one ptrmap page */
     Pgno nOrig;        /* Database size before freeing */
 
     nOrig = btreePagecount(pBt);
@@ -51406,26 +51529,18 @@ static int autoVacuumCommit(BtShared *pBt){
     }
 
     nFree = get4byte(&pBt->pPage1->aData[36]);
-    nEntry = pBt->usableSize/5;
-    nPtrmap = (nFree-nOrig+PTRMAP_PAGENO(pBt, nOrig)+nEntry)/nEntry;
-    nFin = nOrig - nFree - nPtrmap;
-    if( nOrig>PENDING_BYTE_PAGE(pBt) && nFin<PENDING_BYTE_PAGE(pBt) ){
-      nFin--;
-    }
-    while( PTRMAP_ISPAGE(pBt, nFin) || nFin==PENDING_BYTE_PAGE(pBt) ){
-      nFin--;
-    }
+    nFin = finalDbSize(pBt, nOrig, nFree);
     if( nFin>nOrig ) return SQLITE_CORRUPT_BKPT;
 
     for(iFree=nOrig; iFree>nFin && rc==SQLITE_OK; iFree--){
-      rc = incrVacuumStep(pBt, nFin, iFree);
+      rc = incrVacuumStep(pBt, nFin, iFree, 1);
     }
     if( (rc==SQLITE_DONE || rc==SQLITE_OK) && nFree>0 ){
       rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
       put4byte(&pBt->pPage1->aData[32], 0);
       put4byte(&pBt->pPage1->aData[36], 0);
       put4byte(&pBt->pPage1->aData[28], nFin);
-      sqlite3PagerTruncateImage(pBt->pPager, nFin);
+      pBt->bDoTruncate = 1;
       pBt->nPage = nFin;
     }
     if( rc!=SQLITE_OK ){
@@ -51480,6 +51595,9 @@ SQLITE_PRIVATE int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){
         return rc;
       }
     }
+    if( pBt->bDoTruncate ){
+      sqlite3PagerTruncateImage(pBt->pPager, pBt->nPage);
+    }
 #endif
     rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, 0);
     sqlite3BtreeLeave(p);
@@ -51495,6 +51613,9 @@ static void btreeEndTransaction(Btree *p){
   BtShared *pBt = p->pBt;
   assert( sqlite3BtreeHoldsMutex(p) );
 
+#ifndef SQLITE_OMIT_AUTOVACUUM
+  pBt->bDoTruncate = 0;
+#endif
   btreeClearHasContent(pBt);
   if( p->inTrans>TRANS_NONE && p->db->activeVdbeCnt>1 ){
     /* If there are other active statements that belong to this database
@@ -53167,21 +53288,23 @@ SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
 ** an error.  *ppPage and *pPgno are undefined in the event of an error.
 ** Do not invoke sqlite3PagerUnref() on *ppPage if an error is returned.
 **
-** If the "nearby" parameter is not 0, then a (feeble) effort is made to 
+** If the "nearby" parameter is not 0, then an effort is made to 
 ** locate a page close to the page number "nearby".  This can be used in an
 ** attempt to keep related pages close to each other in the database file,
 ** which in turn can make database access faster.
 **
-** If the "exact" parameter is not 0, and the page-number nearby exists 
-** anywhere on the free-list, then it is guarenteed to be returned. This
-** is only used by auto-vacuum databases when allocating a new table.
+** If the eMode parameter is BTALLOC_EXACT and the nearby page exists
+** anywhere on the free-list, then it is guaranteed to be returned.  If
+** eMode is BTALLOC_LT then the page returned will be less than or equal
+** to nearby if any such page exists.  If eMode is BTALLOC_ANY then there
+** are no restrictions on which page is returned.
 */
 static int allocateBtreePage(
-  BtShared *pBt, 
-  MemPage **ppPage, 
-  Pgno *pPgno, 
-  Pgno nearby,
-  u8 exact
+  BtShared *pBt,         /* The btree */
+  MemPage **ppPage,      /* Store pointer to the allocated page here */
+  Pgno *pPgno,           /* Store the page number here */
+  Pgno nearby,           /* Search for a page near this one */
+  u8 eMode               /* BTALLOC_EXACT, BTALLOC_LT, or BTALLOC_ANY */
 ){
   MemPage *pPage1;
   int rc;
@@ -53192,6 +53315,7 @@ static int allocateBtreePage(
   Pgno mxPage;     /* Total size of the database file */
 
   assert( sqlite3_mutex_held(pBt->mutex) );
+  assert( eMode==BTALLOC_ANY || (nearby>0 && IfNotOmitAV(pBt->autoVacuum)) );
   pPage1 = pBt->pPage1;
   mxPage = btreePagecount(pBt);
   n = get4byte(&pPage1->aData[36]);
@@ -53204,21 +53328,24 @@ static int allocateBtreePage(
     Pgno iTrunk;
     u8 searchList = 0; /* If the free-list must be searched for 'nearby' */
     
-    /* If the 'exact' parameter was true and a query of the pointer-map
+    /* If eMode==BTALLOC_EXACT and a query of the pointer-map
     ** shows that the page 'nearby' is somewhere on the free-list, then
     ** the entire-list will be searched for that page.
     */
 #ifndef SQLITE_OMIT_AUTOVACUUM
-    if( exact && nearby<=mxPage ){
-      u8 eType;
-      assert( nearby>0 );
-      assert( pBt->autoVacuum );
-      rc = ptrmapGet(pBt, nearby, &eType, 0);
-      if( rc ) return rc;
-      if( eType==PTRMAP_FREEPAGE ){
-        searchList = 1;
+    if( eMode==BTALLOC_EXACT ){
+      if( nearby<=mxPage ){
+        u8 eType;
+        assert( nearby>0 );
+        assert( pBt->autoVacuum );
+        rc = ptrmapGet(pBt, nearby, &eType, 0);
+        if( rc ) return rc;
+        if( eType==PTRMAP_FREEPAGE ){
+          searchList = 1;
+        }
       }
-      *pPgno = nearby;
+    }else if( eMode==BTALLOC_LE ){
+      searchList = 1;
     }
 #endif
 
@@ -53231,7 +53358,8 @@ static int allocateBtreePage(
 
     /* The code within this loop is run only once if the 'searchList' variable
     ** is not true. Otherwise, it runs once for each trunk-page on the
-    ** free-list until the page 'nearby' is located.
+    ** free-list until the page 'nearby' is located (eMode==BTALLOC_EXACT)
+    ** or until a page less than 'nearby' is located (eMode==BTALLOC_LT)
     */
     do {
       pPrevTrunk = pTrunk;
@@ -53273,11 +53401,13 @@ static int allocateBtreePage(
         rc = SQLITE_CORRUPT_BKPT;
         goto end_allocate_page;
 #ifndef SQLITE_OMIT_AUTOVACUUM
-      }else if( searchList && nearby==iTrunk ){
+      }else if( searchList 
+            && (nearby==iTrunk || (iTrunk<nearby && eMode==BTALLOC_LE)) 
+      ){
         /* The list is being searched and this trunk page is the page
         ** to allocate, regardless of whether it has leaves.
         */
-        assert( *pPgno==iTrunk );
+        *pPgno = iTrunk;
         *ppPage = pTrunk;
         searchList = 0;
         rc = sqlite3PagerWrite(pTrunk->pDbPage);
@@ -53340,14 +53470,24 @@ static int allocateBtreePage(
         unsigned char *aData = pTrunk->aData;
         if( nearby>0 ){
           u32 i;
-          int dist;
           closest = 0;
-          dist = sqlite3AbsInt32(get4byte(&aData[8]) - nearby);
-          for(i=1; i<k; i++){
-            int d2 = sqlite3AbsInt32(get4byte(&aData[8+i*4]) - nearby);
-            if( d2<dist ){
-              closest = i;
-              dist = d2;
+          if( eMode==BTALLOC_LE ){
+            for(i=0; i<k; i++){
+              iPage = get4byte(&aData[8+i*4]);
+              if( iPage<=nearby ){
+                closest = i;
+                break;
+              }
+            }
+          }else{
+            int dist;
+            dist = sqlite3AbsInt32(get4byte(&aData[8]) - nearby);
+            for(i=1; i<k; i++){
+              int d2 = sqlite3AbsInt32(get4byte(&aData[8+i*4]) - nearby);
+              if( d2<dist ){
+                closest = i;
+                dist = d2;
+              }
             }
           }
         }else{
@@ -53361,7 +53501,9 @@ static int allocateBtreePage(
           goto end_allocate_page;
         }
         testcase( iPage==mxPage );
-        if( !searchList || iPage==nearby ){
+        if( !searchList 
+         || (iPage==nearby || (iPage<nearby && eMode==BTALLOC_LE)) 
+        ){
           int noContent;
           *pPgno = iPage;
           TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d"
@@ -53388,8 +53530,26 @@ static int allocateBtreePage(
       pPrevTrunk = 0;
     }while( searchList );
   }else{
-    /* There are no pages on the freelist, so create a new page at the
-    ** end of the file */
+    /* There are no pages on the freelist, so append a new page to the
+    ** database image.
+    **
+    ** Normally, new pages allocated by this block can be requested from the
+    ** pager layer with the 'no-content' flag set. This prevents the pager
+    ** from trying to read the pages content from disk. However, if the
+    ** current transaction has already run one or more incremental-vacuum
+    ** steps, then the page we are about to allocate may contain content
+    ** that is required in the event of a rollback. In this case, do
+    ** not set the no-content flag. This causes the pager to load and journal
+    ** the current page content before overwriting it.
+    **
+    ** Note that the pager will not actually attempt to load or journal 
+    ** content for any page that really does lie past the end of the database
+    ** file on disk. So the effects of disabling the no-content optimization
+    ** here are confined to those pages that lie between the end of the
+    ** database image and the end of the database file.
+    */
+    int bNoContent = (0==IfNotOmitAV(pBt->bDoTruncate));
+
     rc = sqlite3PagerWrite(pBt->pPage1->pDbPage);
     if( rc ) return rc;
     pBt->nPage++;
@@ -53404,7 +53564,7 @@ static int allocateBtreePage(
       MemPage *pPg = 0;
       TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage));
       assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) );
-      rc = btreeGetPage(pBt, pBt->nPage, &pPg, 1);
+      rc = btreeGetPage(pBt, pBt->nPage, &pPg, bNoContent);
       if( rc==SQLITE_OK ){
         rc = sqlite3PagerWrite(pPg->pDbPage);
         releasePage(pPg);
@@ -53418,7 +53578,7 @@ static int allocateBtreePage(
     *pPgno = pBt->nPage;
 
     assert( *pPgno!=PENDING_BYTE_PAGE(pBt) );
-    rc = btreeGetPage(pBt, *pPgno, ppPage, 1);
+    rc = btreeGetPage(pBt, *pPgno, ppPage, bNoContent);
     if( rc ) return rc;
     rc = sqlite3PagerWrite((*ppPage)->pDbPage);
     if( rc!=SQLITE_OK ){
@@ -53746,7 +53906,7 @@ static int fillInCell(
       ** If this is the first overflow page, then write a partial entry 
       ** to the pointer-map. If we write nothing to this pointer-map slot,
       ** then the optimistic overflow chain processing in clearCell()
-      ** may misinterpret the uninitialised values and delete the
+      ** may misinterpret the uninitialized values and delete the
       ** wrong pages from the database.
       */
       if( pBt->autoVacuum && rc==SQLITE_OK ){
@@ -55219,7 +55379,7 @@ SQLITE_PRIVATE int sqlite3BtreeInsert(
   insertCell(pPage, idx, newCell, szNew, 0, 0, &rc);
   assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 );
 
-  /* If no error has occured and pPage has an overflow cell, call balance() 
+  /* If no error has occurred and pPage has an overflow cell, call balance() 
   ** to redistribute the cells within the tree. Since balance() may move
   ** the cursor, zero the BtCursor.info.nSize and BtCursor.validNKey
   ** variables.
@@ -55433,7 +55593,7 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
     ** be moved to the allocated page (unless the allocated page happens
     ** to reside at pgnoRoot).
     */
-    rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, 1);
+    rc = allocateBtreePage(pBt, &pPageMove, &pgnoMove, pgnoRoot, BTALLOC_EXACT);
     if( rc!=SQLITE_OK ){
       return rc;
     }
@@ -56340,7 +56500,7 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(
   }
   i = PENDING_BYTE_PAGE(pBt);
   if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i);
-  sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), 20000);
+  sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
   sCheck.errMsg.useMalloc = 2;
 
   /* Check the integrity of the freelist
@@ -56875,7 +57035,12 @@ static int isFatalError(int rc){
 ** page iSrcPg from the source database. Copy this data into the 
 ** destination database.
 */
-static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){
+static int backupOnePage(
+  sqlite3_backup *p,              /* Backup handle */
+  Pgno iSrcPg,                    /* Source database page to backup */
+  const u8 *zSrcData,             /* Source database page data */
+  int bUpdate                     /* True for an update, false otherwise */
+){
   Pager * const pDestPager = sqlite3BtreePager(p->pDest);
   const int nSrcPgsz = sqlite3BtreeGetPageSize(p->pSrc);
   int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest);
@@ -56948,6 +57113,9 @@ static int backupOnePage(sqlite3_backup *p, Pgno iSrcPg, const u8 *zSrcData){
       */
       memcpy(zOut, zIn, nCopy);
       ((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0;
+      if( iOff==0 && bUpdate==0 ){
+        sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc));
+      }
     }
     sqlite3PagerUnref(pDestPg);
   }
@@ -57054,7 +57222,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
         DbPage *pSrcPg;                             /* Source page object */
         rc = sqlite3PagerGet(pSrcPager, iSrcPg, &pSrcPg);
         if( rc==SQLITE_OK ){
-          rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg));
+          rc = backupOnePage(p, iSrcPg, sqlite3PagerGetData(pSrcPg), 0);
           sqlite3PagerUnref(pSrcPg);
         }
       }
@@ -57117,7 +57285,6 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
           nDestTruncate = nSrcPage * (pgszSrc/pgszDest);
         }
         assert( nDestTruncate>0 );
-        sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
 
         if( pgszSrc<pgszDest ){
           /* If the source page-size is smaller than the destination page-size,
@@ -57131,6 +57298,8 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
           */
           const i64 iSize = (i64)pgszSrc * (i64)nSrcPage;
           sqlite3_file * const pFile = sqlite3PagerFile(pDestPager);
+          Pgno iPg;
+          int nDstPage;
           i64 iOff;
           i64 iEnd;
 
@@ -57141,13 +57310,26 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
              && iSize>=PENDING_BYTE && iSize<=PENDING_BYTE+pgszDest
           ));
 
-          /* This call ensures that all data required to recreate the original
+          /* This block ensures that all data required to recreate the original
           ** database has been stored in the journal for pDestPager and the
           ** journal synced to disk. So at this point we may safely modify
           ** the database file in any way, knowing that if a power failure
           ** occurs, the original database will be reconstructed from the 
           ** journal file.  */
-          rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1);
+          sqlite3PagerPagecount(pDestPager, &nDstPage);
+          for(iPg=nDestTruncate; rc==SQLITE_OK && iPg<=(Pgno)nDstPage; iPg++){
+            if( iPg!=PENDING_BYTE_PAGE(p->pDest->pBt) ){
+              DbPage *pPg;
+              rc = sqlite3PagerGet(pDestPager, iPg, &pPg);
+              if( rc==SQLITE_OK ){
+                rc = sqlite3PagerWrite(pPg);
+                sqlite3PagerUnref(pPg);
+              }
+            }
+          }
+          if( rc==SQLITE_OK ){
+            rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 1);
+          }
 
           /* Write the extra pages and truncate the database file as required */
           iEnd = MIN(PENDING_BYTE + pgszDest, iSize);
@@ -57174,6 +57356,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
             rc = sqlite3PagerSync(pDestPager);
           }
         }else{
+          sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
           rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0);
         }
     
@@ -57302,7 +57485,7 @@ SQLITE_PRIVATE void sqlite3BackupUpdate(sqlite3_backup *pBackup, Pgno iPage, con
       int rc;
       assert( p->pDestDb );
       sqlite3_mutex_enter(p->pDestDb->mutex);
-      rc = backupOnePage(p, iPage, aData);
+      rc = backupOnePage(p, iPage, aData, 1);
       sqlite3_mutex_leave(p->pDestDb->mutex);
       assert( rc!=SQLITE_BUSY && rc!=SQLITE_LOCKED );
       if( rc!=SQLITE_OK ){
@@ -57425,7 +57608,9 @@ copy_finished:
 ** between formats.
 */
 SQLITE_PRIVATE int sqlite3VdbeChangeEncoding(Mem *pMem, int desiredEnc){
+#ifndef SQLITE_OMIT_UTF16
   int rc;
+#endif
   assert( (pMem->flags&MEM_RowSet)==0 );
   assert( desiredEnc==SQLITE_UTF8 || desiredEnc==SQLITE_UTF16LE
            || desiredEnc==SQLITE_UTF16BE );
@@ -58570,18 +58755,6 @@ SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){
 ** But that file was getting too big so this subroutines were split out.
 */
 
-
-
-/*
-** When debugging the code generator in a symbolic debugger, one can
-** set the sqlite3VdbeAddopTrace to 1 and all opcodes will be printed
-** as they are added to the instruction stream.
-*/
-#ifdef SQLITE_DEBUG
-SQLITE_PRIVATE int sqlite3VdbeAddopTrace = 0;
-#endif
-
-
 /*
 ** Create a new virtual database engine.
 */
@@ -58711,7 +58884,9 @@ SQLITE_PRIVATE int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
   pOp->p4type = P4_NOTUSED;
 #ifdef SQLITE_DEBUG
   pOp->zComment = 0;
-  if( sqlite3VdbeAddopTrace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]);
+  if( p->db->flags & SQLITE_VdbeAddopTrace ){
+    sqlite3VdbePrintOp(0, i, &p->aOp[i]);
+  }
 #endif
 #ifdef VDBE_PROFILE
   pOp->cycles = 0;
@@ -58930,7 +59105,7 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
      || (opcode==OP_FkCounter && pOp->p1==0 && pOp->p2==1) 
 #endif
      || ((opcode==OP_Halt || opcode==OP_HaltIfNull) 
-      && (pOp->p1==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
+      && ((pOp->p1&0xff)==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
     ){
       hasAbort = 1;
       break;
@@ -58938,7 +59113,7 @@ SQLITE_PRIVATE int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
   }
   sqlite3DbFree(v->db, sIter.apSub);
 
-  /* Return true if hasAbort==mayAbort. Or if a malloc failure occured.
+  /* Return true if hasAbort==mayAbort. Or if a malloc failure occurred.
   ** If malloc failed, then the while() loop above may not have iterated
   ** through all opcodes and hasAbort may be set incorrectly. Return
   ** true for this case to prevent the assert() in the callers frame
@@ -59065,7 +59240,7 @@ SQLITE_PRIVATE int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp)
       pOut->p5 = 0;
 #ifdef SQLITE_DEBUG
       pOut->zComment = 0;
-      if( sqlite3VdbeAddopTrace ){
+      if( p->db->flags & SQLITE_VdbeAddopTrace ){
         sqlite3VdbePrintOp(0, i+addr, &p->aOp[i+addr]);
       }
 #endif
@@ -60091,7 +60266,7 @@ SQLITE_PRIVATE void sqlite3VdbeMakeReady(
     zEnd = &zCsr[nByte];
   }while( nByte && !db->mallocFailed );
 
-  p->nCursor = (u16)nCursor;
+  p->nCursor = nCursor;
   p->nOnceFlag = nOnce;
   if( p->aVar ){
     p->nVar = (ynVar)nVar;
@@ -60333,7 +60508,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
   if( needXcommit && db->xCommitCallback ){
     rc = db->xCommitCallback(db->pCommitArg);
     if( rc ){
-      return SQLITE_CONSTRAINT;
+      return SQLITE_CONSTRAINT_COMMITHOOK;
     }
   }
 
@@ -60570,7 +60745,7 @@ SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
 
   /* If p->iStatement is greater than zero, then this Vdbe opened a 
   ** statement transaction that should be closed here. The only exception
-  ** is that an IO error may have occured, causing an emergency rollback.
+  ** is that an IO error may have occurred, causing an emergency rollback.
   ** In this case (db->nStatement==0), and there is nothing to do.
   */
   if( db->nStatement && p->iStatement ){
@@ -60625,14 +60800,14 @@ SQLITE_PRIVATE int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){
 ** violations, return SQLITE_ERROR. Otherwise, SQLITE_OK.
 **
 ** If there are outstanding FK violations and this function returns 
-** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT and write
-** an error message to it. Then return SQLITE_ERROR.
+** SQLITE_ERROR, set the result of the VM to SQLITE_CONSTRAINT_FOREIGNKEY
+** and write an error message to it. Then return SQLITE_ERROR.
 */
 #ifndef SQLITE_OMIT_FOREIGN_KEY
 SQLITE_PRIVATE int sqlite3VdbeCheckFk(Vdbe *p, int deferred){
   sqlite3 *db = p->db;
   if( (deferred && db->nDeferredCons>0) || (!deferred && p->nFkConstraint>0) ){
-    p->rc = SQLITE_CONSTRAINT;
+    p->rc = SQLITE_CONSTRAINT_FOREIGNKEY;
     p->errorAction = OE_Abort;
     sqlite3SetString(&p->zErrMsg, db, "foreign key constraint failed");
     return SQLITE_ERROR;
@@ -60706,7 +60881,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
       **
       ** Even if the statement is read-only, it is important to perform
       ** a statement or transaction rollback operation. If the error 
-      ** occured while writing to the journal, sub-journal or database
+      ** occurred while writing to the journal, sub-journal or database
       ** file as part of an effort to free up cache space (see function
       ** pagerStress() in pager.c), the rollback is required to restore 
       ** the pager to a consistent state.
@@ -60747,7 +60922,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
             sqlite3VdbeLeave(p);
             return SQLITE_ERROR;
           }
-          rc = SQLITE_CONSTRAINT;
+          rc = SQLITE_CONSTRAINT_FOREIGNKEY;
         }else{ 
           /* The auto-commit flag is true, the vdbe program was successful 
           ** or hit an 'OR FAIL' constraint and there are no deferred foreign
@@ -60790,7 +60965,7 @@ SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe *p){
     if( eStatementOp ){
       rc = sqlite3VdbeCloseStatement(p, eStatementOp);
       if( rc ){
-        if( p->rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT ){
+        if( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT ){
           p->rc = rc;
           sqlite3DbFree(db, p->zErrMsg);
           p->zErrMsg = 0;
@@ -61031,7 +61206,7 @@ SQLITE_PRIVATE void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
   sqlite3DbFree(db, p->zSql);
   sqlite3DbFree(db, p->pFree);
 #if defined(SQLITE_ENABLE_TREE_EXPLAIN)
-  sqlite3_free(p->zExplain);
+  sqlite3DbFree(db, p->zExplain);
   sqlite3DbFree(db, p->pExplain);
 #endif
 }
@@ -61120,7 +61295,7 @@ SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor *p){
 ** the blob of data that it corresponds to. In a table record, all serial
 ** types are stored at the start of the record, and the blobs of data at
 ** the end. Hence these functions allow the caller to handle the
-** serial-type and data blob seperately.
+** serial-type and data blob separately.
 **
 ** The following table describes the various storage classes for data:
 **
@@ -62260,7 +62435,7 @@ end_of_step:
   assert( p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE );
   if( p->isPrepareV2 && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
     /* If this statement was prepared using sqlite3_prepare_v2(), and an
-    ** error has occured, then return the error code in p->rc to the
+    ** error has occurred, then return the error code in p->rc to the
     ** caller. Set the error code in the database handle to the same value.
     */ 
     rc = sqlite3VdbeTransferError(p);
@@ -63013,7 +63188,7 @@ SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nNa
   if( zName ){
     for(i=0; i<p->nzVar; i++){
       const char *z = p->azVar[i];
-      if( z && memcmp(z,zName,nName)==0 && z[nName]==0 ){
+      if( z && strncmp(z,zName,nName)==0 && z[nName]==0 ){
         return i+1;
       }
     }
@@ -63550,11 +63725,7 @@ SQLITE_API int sqlite3_found_count = 0;
        && sqlite3VdbeMemMakeWriteable(P) ){ goto no_mem;}
 
 /* Return true if the cursor was opened using the OP_OpenSorter opcode. */
-#ifdef SQLITE_OMIT_MERGE_SORT
-# define isSorter(x) 0
-#else
 # define isSorter(x) ((x)->pSorter!=0)
-#endif
 
 /*
 ** Argument pMem points at a register that will be passed to a
@@ -64787,7 +64958,7 @@ case OP_Halt: {
   if( rc==SQLITE_BUSY ){
     p->rc = rc = SQLITE_BUSY;
   }else{
-    assert( rc==SQLITE_OK || p->rc==SQLITE_CONSTRAINT );
+    assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT );
     assert( rc==SQLITE_OK || db->nDeferredCons>0 );
     rc = p->rc ? SQLITE_ERROR : SQLITE_DONE;
   }
@@ -67291,17 +67462,12 @@ case OP_SorterOpen: {
   VdbeCursor *pCx;
 #endif /* local variables moved into u.ba */
 
-#ifndef SQLITE_OMIT_MERGE_SORT
   u.ba.pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, 1);
   if( u.ba.pCx==0 ) goto no_mem;
   u.ba.pCx->pKeyInfo = pOp->p4.pKeyInfo;
   u.ba.pCx->pKeyInfo->enc = ENC(p->db);
   u.ba.pCx->isSorter = 1;
   rc = sqlite3VdbeSorterInit(db, u.ba.pCx);
-#else
-  pOp->opcode = OP_OpenEphemeral;
-  pc--;
-#endif
   break;
 }
 
@@ -68206,15 +68372,10 @@ case OP_SorterData: {
   VdbeCursor *pC;
 #endif /* local variables moved into u.bl */
 
-#ifndef SQLITE_OMIT_MERGE_SORT
   pOut = &aMem[pOp->p2];
   u.bl.pC = p->apCsr[pOp->p1];
   assert( u.bl.pC->isSorter );
   rc = sqlite3VdbeSorterRowkey(u.bl.pC, pOut);
-#else
-  pOp->opcode = OP_RowKey;
-  pc--;
-#endif
   break;
 }
 
@@ -68421,9 +68582,6 @@ case OP_Last: {        /* jump */
 ** correctly optimizing out sorts.
 */
 case OP_SorterSort:    /* jump */
-#ifdef SQLITE_OMIT_MERGE_SORT
-  pOp->opcode = OP_Sort;
-#endif
 case OP_Sort: {        /* jump */
 #ifdef SQLITE_TEST
   sqlite3_sort_count++;
@@ -68504,9 +68662,6 @@ case OP_Rewind: {        /* jump */
 ** number P5-1 in the prepared statement is incremented.
 */
 case OP_SorterNext:    /* jump */
-#ifdef SQLITE_OMIT_MERGE_SORT
-  pOp->opcode = OP_Next;
-#endif
 case OP_Prev:          /* jump */
 case OP_Next: {        /* jump */
 #if 0  /* local variables moved into u.br */
@@ -68559,9 +68714,6 @@ case OP_Next: {        /* jump */
 ** for tables is OP_Insert.
 */
 case OP_SorterInsert:       /* in2 */
-#ifdef SQLITE_OMIT_MERGE_SORT
-  pOp->opcode = OP_IdxInsert;
-#endif
 case OP_IdxInsert: {        /* in2 */
 #if 0  /* local variables moved into u.bs */
   VdbeCursor *pC;
@@ -69830,7 +69982,7 @@ case OP_VOpen: {
     /* Initialize sqlite3_vtab_cursor base class */
     u.cm.pVtabCursor->pVtab = u.cm.pVtab;
 
-    /* Initialise vdbe cursor object */
+    /* Initialize vdbe cursor object */
     u.cm.pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
     if( u.cm.pCur ){
       u.cm.pCur->pVtabCursor = u.cm.pVtabCursor;
@@ -70119,7 +70271,7 @@ case OP_VUpdate: {
       assert( u.cr.nArg>1 && u.cr.apArg[0] && (u.cr.apArg[0]->flags&MEM_Null) );
       db->lastRowid = lastRowid = u.cr.rowid;
     }
-    if( rc==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
+    if( (rc&0xff)==SQLITE_CONSTRAINT && pOp->p4.pVtab->bConstraint ){
       if( pOp->p5==OE_Ignore ){
         rc = SQLITE_OK;
       }else{
@@ -70812,7 +70964,6 @@ SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){
 */
 
 
-#ifndef SQLITE_OMIT_MERGE_SORT
 
 typedef struct VdbeSorterIter VdbeSorterIter;
 typedef struct SorterRecord SorterRecord;
@@ -71832,8 +71983,6 @@ SQLITE_PRIVATE int sqlite3VdbeSorterCompare(
   return SQLITE_OK;
 }
 
-#endif /* #ifndef SQLITE_OMIT_MERGE_SORT */
-
 /************** End of vdbesort.c ********************************************/
 /************** Begin file journal.c *****************************************/
 /*
@@ -71896,6 +72045,14 @@ static int createFile(JournalFile *p){
         assert(p->iSize<=p->nBuf);
         rc = sqlite3OsWrite(p->pReal, p->zBuf, p->iSize, 0);
       }
+      if( rc!=SQLITE_OK ){
+        /* If an error occurred while writing to the file, close it before
+        ** returning. This way, SQLite uses the in-memory journal data to 
+        ** roll back changes made to the internal page-cache before this
+        ** function was called.  */
+        sqlite3OsClose(pReal);
+        p->pReal = 0;
+      }
     }
   }
   return rc;
@@ -72642,6 +72799,35 @@ static int nameInUsingClause(IdList *pUsing, const char *zCol){
   return 0;
 }
 
+/*
+** Subqueries stores the original database, table and column names for their
+** result sets in ExprList.a[].zSpan, in the form "DATABASE.TABLE.COLUMN".
+** Check to see if the zSpan given to this routine matches the zDb, zTab,
+** and zCol.  If any of zDb, zTab, and zCol are NULL then those fields will
+** match anything.
+*/
+SQLITE_PRIVATE int sqlite3MatchSpanName(
+  const char *zSpan,
+  const char *zCol,
+  const char *zTab,
+  const char *zDb
+){
+  int n;
+  for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
+  if( zDb && (sqlite3StrNICmp(zSpan, zDb, n)!=0 || zDb[n]!=0) ){
+    return 0;
+  }
+  zSpan += n+1;
+  for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
+  if( zTab && (sqlite3StrNICmp(zSpan, zTab, n)!=0 || zTab[n]!=0) ){
+    return 0;
+  }
+  zSpan += n+1;
+  if( zCol && sqlite3StrICmp(zSpan, zCol)!=0 ){
+    return 0;
+  }
+  return 1;
+}
 
 /*
 ** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
@@ -72698,6 +72884,20 @@ static int lookupName(
   pExpr->pTab = 0;
   ExprSetIrreducible(pExpr);
 
+  /* Translate the schema name in zDb into a pointer to the corresponding
+  ** schema.  If not found, pSchema will remain NULL and nothing will match
+  ** resulting in an appropriate error message toward the end of this routine
+  */
+  if( zDb ){
+    for(i=0; i<db->nDb; i++){
+      assert( db->aDb[i].zName );
+      if( sqlite3StrICmp(db->aDb[i].zName,zDb)==0 ){
+        pSchema = db->aDb[i].pSchema;
+        break;
+      }
+    }
+  }
+
   /* Start at the inner-most context and move outward until a match is found */
   while( pNC && cnt==0 ){
     ExprList *pEList;
@@ -72706,31 +72906,36 @@ static int lookupName(
     if( pSrcList ){
       for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
         Table *pTab;
-        int iDb;
         Column *pCol;
   
         pTab = pItem->pTab;
         assert( pTab!=0 && pTab->zName!=0 );
-        iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
         assert( pTab->nCol>0 );
-        if( zTab ){
-          if( pItem->zAlias ){
-            char *zTabName = pItem->zAlias;
-            if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
-          }else{
-            char *zTabName = pTab->zName;
-            if( NEVER(zTabName==0) || sqlite3StrICmp(zTabName, zTab)!=0 ){
-              continue;
-            }
-            if( zDb!=0 && sqlite3StrICmp(db->aDb[iDb].zName, zDb)!=0 ){
-              continue;
+        if( pItem->pSelect && (pItem->pSelect->selFlags & SF_NestedFrom)!=0 ){
+          int hit = 0;
+          pEList = pItem->pSelect->pEList;
+          for(j=0; j<pEList->nExpr; j++){
+            if( sqlite3MatchSpanName(pEList->a[j].zSpan, zCol, zTab, zDb) ){
+              cnt++;
+              cntTab = 2;
+              pMatch = pItem;
+              pExpr->iColumn = j;
+              hit = 1;
             }
           }
+          if( hit || zTab==0 ) continue;
+        }
+        if( zDb && pTab->pSchema!=pSchema ){
+          continue;
+        }
+        if( zTab ){
+          const char *zTabName = pItem->zAlias ? pItem->zAlias : pTab->zName;
+          assert( zTabName!=0 );
+          if( sqlite3StrICmp(zTabName, zTab)!=0 ){
+            continue;
+          }
         }
         if( 0==(cntTab++) ){
-          pExpr->iTable = pItem->iCursor;
-          pExpr->pTab = pTab;
-          pSchema = pTab->pSchema;
           pMatch = pItem;
         }
         for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
@@ -72744,17 +72949,19 @@ static int lookupName(
               if( nameInUsingClause(pItem->pUsing, zCol) ) continue;
             }
             cnt++;
-            pExpr->iTable = pItem->iCursor;
-            pExpr->pTab = pTab;
             pMatch = pItem;
-            pSchema = pTab->pSchema;
             /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
             pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j;
             break;
           }
         }
       }
-    }
+      if( pMatch ){
+        pExpr->iTable = pMatch->iCursor;
+        pExpr->pTab = pMatch->pTab;
+        pSchema = pExpr->pTab->pSchema;
+      }
+    } /* if( pSrcList ) */
 
 #ifndef SQLITE_OMIT_TRIGGER
     /* If we have not already resolved the name, then maybe 
@@ -73089,7 +73296,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
         sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
         pNC->nErr++;
         is_agg = 0;
-      }else if( no_such_func ){
+      }else if( no_such_func && pParse->db->init.busy==0 ){
         sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
         pNC->nErr++;
       }else if( wrong_num_args ){
@@ -73525,23 +73732,6 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
       return WRC_Abort;
     }
   
-    /* Set up the local name-context to pass to sqlite3ResolveExprNames() to
-    ** resolve the result-set expression list.
-    */
-    sNC.ncFlags = NC_AllowAgg;
-    sNC.pSrcList = p->pSrc;
-    sNC.pNext = pOuterNC;
-  
-    /* Resolve names in the result set. */
-    pEList = p->pEList;
-    assert( pEList!=0 );
-    for(i=0; i<pEList->nExpr; i++){
-      Expr *pX = pEList->a[i].pExpr;
-      if( sqlite3ResolveExprNames(&sNC, pX) ){
-        return WRC_Abort;
-      }
-    }
-  
     /* Recursively resolve names in all subqueries
     */
     for(i=0; i<p->pSrc->nSrc; i++){
@@ -73569,6 +73759,23 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
       }
     }
   
+    /* Set up the local name-context to pass to sqlite3ResolveExprNames() to
+    ** resolve the result-set expression list.
+    */
+    sNC.ncFlags = NC_AllowAgg;
+    sNC.pSrcList = p->pSrc;
+    sNC.pNext = pOuterNC;
+  
+    /* Resolve names in the result set. */
+    pEList = p->pEList;
+    assert( pEList!=0 );
+    for(i=0; i<pEList->nExpr; i++){
+      Expr *pX = pEList->a[i].pExpr;
+      if( sqlite3ResolveExprNames(&sNC, pX) ){
+        return WRC_Abort;
+      }
+    }
+  
     /* If there are no aggregate functions in the result-set, and no GROUP BY 
     ** expression, do not allow aggregates in any of the other expressions.
     */
@@ -74409,7 +74616,7 @@ SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
       */
       ynVar i;
       for(i=0; i<pParse->nzVar; i++){
-        if( pParse->azVar[i] && memcmp(pParse->azVar[i],z,n+1)==0 ){
+        if( pParse->azVar[i] && strcmp(pParse->azVar[i],z)==0 ){
           pExpr->iColumn = x = (ynVar)i+1;
           break;
         }
@@ -75227,10 +75434,11 @@ SQLITE_PRIVATE int sqlite3CodeOnce(Parse *pParse){
 **
 ** The returned value of this function indicates the b-tree type, as follows:
 **
-**   IN_INDEX_ROWID - The cursor was opened on a database table.
-**   IN_INDEX_INDEX - The cursor was opened on a database index.
-**   IN_INDEX_EPH -   The cursor was opened on a specially created and
-**                    populated epheremal table.
+**   IN_INDEX_ROWID      - The cursor was opened on a database table.
+**   IN_INDEX_INDEX_ASC  - The cursor was opened on an ascending index.
+**   IN_INDEX_INDEX_DESC - The cursor was opened on a descending index.
+**   IN_INDEX_EPH        - The cursor was opened on a specially created and
+**                         populated epheremal table.
 **
 ** An existing b-tree might be used if the RHS expression pX is a simple
 ** subquery such as:
@@ -75353,7 +75561,8 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
           sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
                                pKey,P4_KEYINFO_HANDOFF);
           VdbeComment((v, "%s", pIdx->zName));
-          eType = IN_INDEX_INDEX;
+          assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 );
+          eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0];
 
           sqlite3VdbeJumpHere(v, iAddr);
           if( prNotFound && !pTab->aCol[iCol].notNull ){
@@ -76706,7 +76915,8 @@ SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target)
         sqlite3VdbeAddOp4(
             v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0);
       }else{
-        sqlite3HaltConstraint(pParse, pExpr->affinity, pExpr->u.zToken, 0);
+        sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_TRIGGER,
+                              pExpr->affinity, pExpr->u.zToken, 0);
       }
 
       break;
@@ -77052,6 +77262,12 @@ SQLITE_PRIVATE void sqlite3ExplainExprList(Vdbe *pOut, ExprList *pList){
       sqlite3ExplainPush(pOut);
       sqlite3ExplainExpr(pOut, pList->a[i].pExpr);
       sqlite3ExplainPop(pOut);
+      if( pList->a[i].zName ){
+        sqlite3ExplainPrintf(pOut, " AS %s", pList->a[i].zName);
+      }
+      if( pList->a[i].bSpanIsTab ){
+        sqlite3ExplainPrintf(pOut, " (%s)", pList->a[i].zSpan);
+      }
       if( i<pList->nExpr-1 ){
         sqlite3ExplainNL(pOut);
       }
@@ -77304,7 +77520,7 @@ SQLITE_PRIVATE void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int
   int r1, r2;
 
   assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 );
-  if( NEVER(v==0) )     return;  /* Existance of VDBE checked by caller */
+  if( NEVER(v==0) )     return;  /* Existence of VDBE checked by caller */
   if( NEVER(pExpr==0) ) return;  /* No way this can happen */
   op = pExpr->op;
   switch( op ){
@@ -77424,7 +77640,7 @@ SQLITE_PRIVATE void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int
   int r1, r2;
 
   assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 );
-  if( NEVER(v==0) ) return; /* Existance of VDBE checked by caller */
+  if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */
   if( pExpr==0 )    return;
 
   /* The value of pExpr->op and op are related as follows:
@@ -79259,7 +79475,7 @@ static void analyzeOneTable(
     /* Do not gather statistics on views or virtual tables */
     return;
   }
-  if( memcmp(pTab->zName, "sqlite_", 7)==0 ){
+  if( sqlite3_strnicmp(pTab->zName, "sqlite_", 7)==0 ){
     /* Do not gather statistics on system tables */
     return;
   }
@@ -79669,7 +79885,7 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
     if( pIndex==0 ) break;
     pIndex->aiRowEst[i] = v;
     if( *z==' ' ) z++;
-    if( memcmp(z, "unordered", 10)==0 ){
+    if( strcmp(z, "unordered")==0 ){
       pIndex->bUnordered = 1;
       break;
     }
@@ -80021,7 +80237,7 @@ static void attachFunc(
     }
   }
 
-  /* Allocate the new entry in the db->aDb[] array and initialise the schema
+  /* Allocate the new entry in the db->aDb[] array and initialize the schema
   ** hash tables.
   */
   if( db->aDb==db->aDbStatic ){
@@ -80038,7 +80254,7 @@ static void attachFunc(
 
   /* Open the database file. If the btree is successfully opened, use
   ** it to obtain the database schema. At this point the schema may
-  ** or may not be initialised.
+  ** or may not be initialized.
   */
   flags = db->openFlags;
   rc = sqlite3ParseUri(db->pVfs->zName, zFile, &flags, &pVfs, &zPath, &zErr);
@@ -82824,7 +83040,7 @@ SQLITE_PRIVATE void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, in
   /* Drop all SQLITE_MASTER table and index entries that refer to the
   ** table. The program name loops through the master table and deletes
   ** every row that refers to a table of the same name as the one being
-  ** dropped. Triggers are handled seperately because a trigger can be
+  ** dropped. Triggers are handled separately because a trigger can be
   ** created in the temp database that refers to a table in another
   ** database.
   */
@@ -83116,9 +83332,6 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
   int tnum;                      /* Root page of index */
   Vdbe *v;                       /* Generate code into this virtual machine */
   KeyInfo *pKey;                 /* KeyInfo for index */
-#ifdef SQLITE_OMIT_MERGE_SORT
-  int regIdxKey;                 /* Registers containing the index key */
-#endif
   int regRecord;                 /* Register holding assemblied index record */
   sqlite3 *db = pParse->db;      /* The database connection */
   int iDb = sqlite3SchemaToIndex(db, pIndex->pSchema);
@@ -83146,13 +83359,9 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
                     (char *)pKey, P4_KEYINFO_HANDOFF);
   sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));
 
-#ifndef SQLITE_OMIT_MERGE_SORT
   /* Open the sorter cursor if we are to use one. */
   iSorter = pParse->nTab++;
   sqlite3VdbeAddOp4(v, OP_SorterOpen, iSorter, 0, 0, (char*)pKey, P4_KEYINFO);
-#else
-  iSorter = iTab;
-#endif
 
   /* Open the table. Loop through all rows of the table, inserting index
   ** records into the sorter. */
@@ -83160,7 +83369,6 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
   addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
   regRecord = sqlite3GetTempReg(pParse);
 
-#ifndef SQLITE_OMIT_MERGE_SORT
   sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
   sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
   sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1);
@@ -83171,8 +83379,8 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
     sqlite3VdbeAddOp2(v, OP_Goto, 0, j2);
     addr2 = sqlite3VdbeCurrentAddr(v);
     sqlite3VdbeAddOp3(v, OP_SorterCompare, iSorter, j2, regRecord);
-    sqlite3HaltConstraint(
-        pParse, OE_Abort, "indexed columns are not unique", P4_STATIC
+    sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE,
+        OE_Abort, "indexed columns are not unique", P4_STATIC
     );
   }else{
     addr2 = sqlite3VdbeCurrentAddr(v);
@@ -83180,30 +83388,6 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
   sqlite3VdbeAddOp2(v, OP_SorterData, iSorter, regRecord);
   sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1);
   sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
-#else
-  regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1);
-  addr2 = addr1 + 1;
-  if( pIndex->onError!=OE_None ){
-    const int regRowid = regIdxKey + pIndex->nColumn;
-    const int j2 = sqlite3VdbeCurrentAddr(v) + 2;
-    void * const pRegKey = SQLITE_INT_TO_PTR(regIdxKey);
-
-    /* The registers accessed by the OP_IsUnique opcode were allocated
-    ** using sqlite3GetTempRange() inside of the sqlite3GenerateIndexKey()
-    ** call above. Just before that function was freed they were released
-    ** (made available to the compiler for reuse) using 
-    ** sqlite3ReleaseTempRange(). So in some ways having the OP_IsUnique
-    ** opcode use the values stored within seems dangerous. However, since
-    ** we can be sure that no other temp registers have been allocated
-    ** since sqlite3ReleaseTempRange() was called, it is safe to do so.
-    */
-    sqlite3VdbeAddOp4(v, OP_IsUnique, iIdx, j2, regRowid, pRegKey, P4_INT32);
-    sqlite3HaltConstraint(
-        pParse, OE_Abort, "indexed columns are not unique", P4_STATIC);
-  }
-  sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 0);
-  sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
-#endif
   sqlite3ReleaseTempReg(pParse, regRecord);
   sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2);
   sqlite3VdbeJumpHere(v, addr1);
@@ -83318,7 +83502,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
   assert( pTab!=0 );
   assert( pParse->nErr==0 );
   if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 
-       && memcmp(&pTab->zName[7],"altertab_",9)!=0 ){
+       && sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0 ){
     sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
     goto exit_create_index;
   }
@@ -83563,7 +83747,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
           ** However the ON CONFLICT clauses are different. If both this 
           ** constraint and the previous equivalent constraint have explicit
           ** ON CONFLICT clauses this is an error. Otherwise, use the
-          ** explicitly specified behaviour for the index.
+          ** explicitly specified behavior for the index.
           */
           if( !(pIdx->onError==OE_Default || pIndex->onError==OE_Default) ){
             sqlite3ErrorMsg(pParse, 
@@ -84416,12 +84600,19 @@ SQLITE_PRIVATE void sqlite3MayAbort(Parse *pParse){
 ** error. The onError parameter determines which (if any) of the statement
 ** and/or current transaction is rolled back.
 */
-SQLITE_PRIVATE void sqlite3HaltConstraint(Parse *pParse, int onError, char *p4, int p4type){
+SQLITE_PRIVATE void sqlite3HaltConstraint(
+  Parse *pParse,    /* Parsing context */
+  int errCode,      /* extended error code */
+  int onError,      /* Constraint type */
+  char *p4,         /* Error message */
+  int p4type        /* P4_STATIC or P4_TRANSIENT */
+){
   Vdbe *v = sqlite3GetVdbe(pParse);
+  assert( (errCode&0xff)==SQLITE_CONSTRAINT );
   if( onError==OE_Abort ){
     sqlite3MayAbort(pParse);
   }
-  sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, p4, p4type);
+  sqlite3VdbeAddOp4(v, OP_Halt, errCode, onError, 0, p4, p4type);
 }
 
 /*
@@ -85166,30 +85357,28 @@ SQLITE_PRIVATE void sqlite3MaterializeView(
   int iCur             /* Cursor number for ephemerial table */
 ){
   SelectDest dest;
-  Select *pDup;
+  Select *pSel;
+  SrcList *pFrom;
   sqlite3 *db = pParse->db;
+  int iDb = sqlite3SchemaToIndex(db, pView->pSchema);
 
-  pDup = sqlite3SelectDup(db, pView->pSelect, 0);
-  if( pWhere ){
-    SrcList *pFrom;
-    
-    pWhere = sqlite3ExprDup(db, pWhere, 0);
-    pFrom = sqlite3SrcListAppend(db, 0, 0, 0);
-    if( pFrom ){
-      assert( pFrom->nSrc==1 );
-      pFrom->a[0].zAlias = sqlite3DbStrDup(db, pView->zName);
-      pFrom->a[0].pSelect = pDup;
-      assert( pFrom->a[0].pOn==0 );
-      assert( pFrom->a[0].pUsing==0 );
-    }else{
-      sqlite3SelectDelete(db, pDup);
-    }
-    pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
-    if( pDup ) pDup->selFlags |= SF_Materialize;
+  pWhere = sqlite3ExprDup(db, pWhere, 0);
+  pFrom = sqlite3SrcListAppend(db, 0, 0, 0);
+
+  if( pFrom ){
+    assert( pFrom->nSrc==1 );
+    pFrom->a[0].zName = sqlite3DbStrDup(db, pView->zName);
+    pFrom->a[0].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName);
+    assert( pFrom->a[0].pOn==0 );
+    assert( pFrom->a[0].pUsing==0 );
   }
+
+  pSel = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
+  if( pSel ) pSel->selFlags |= SF_Materialize;
+
   sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
-  sqlite3Select(pParse, pDup, &dest);
-  sqlite3SelectDelete(db, pDup);
+  sqlite3Select(pParse, pSel, &dest);
+  sqlite3SelectDelete(db, pSel);
 }
 #endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */
 
@@ -86690,6 +86879,62 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
   }
 }
 
+/*
+** The unicode() function.  Return the integer unicode code-point value
+** for the first character of the input string. 
+*/
+static void unicodeFunc(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  const unsigned char *z = sqlite3_value_text(argv[0]);
+  (void)argc;
+  if( z && z[0] ) sqlite3_result_int(context, sqlite3Utf8Read(&z));
+}
+
+/*
+** The char() function takes zero or more arguments, each of which is
+** an integer.  It constructs a string where each character of the string
+** is the unicode character for the corresponding integer argument.
+*/
+static void charFunc(
+  sqlite3_context *context,
+  int argc,
+  sqlite3_value **argv
+){
+  unsigned char *z, *zOut;
+  int i;
+  zOut = z = sqlite3_malloc( argc*4 );
+  if( z==0 ){
+    sqlite3_result_error_nomem(context);
+    return;
+  }
+  for(i=0; i<argc; i++){
+    sqlite3_int64 x;
+    unsigned c;
+    x = sqlite3_value_int64(argv[i]);
+    if( x<0 || x>0x10ffff ) x = 0xfffd;
+    c = (unsigned)(x & 0x1fffff);
+    if( c<0x00080 ){
+      *zOut++ = (u8)(c&0xFF);
+    }else if( c<0x00800 ){
+      *zOut++ = 0xC0 + (u8)((c>>6)&0x1F);
+      *zOut++ = 0x80 + (u8)(c & 0x3F);
+    }else if( c<0x10000 ){
+      *zOut++ = 0xE0 + (u8)((c>>12)&0x0F);
+      *zOut++ = 0x80 + (u8)((c>>6) & 0x3F);
+      *zOut++ = 0x80 + (u8)(c & 0x3F);
+    }else{
+      *zOut++ = 0xF0 + (u8)((c>>18) & 0x07);
+      *zOut++ = 0x80 + (u8)((c>>12) & 0x3F);
+      *zOut++ = 0x80 + (u8)((c>>6) & 0x3F);
+      *zOut++ = 0x80 + (u8)(c & 0x3F);
+    }                                                    \
+  }
+  sqlite3_result_text(context, (char*)z, (int)(zOut-z), sqlite3_free);
+}
+
 /*
 ** The hex() function.  Interpret the argument as a blob.  Return
 ** a hexadecimal rendering as text.
@@ -87317,6 +87562,8 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
     FUNCTION(instr,              2, 0, 0, instrFunc        ),
     FUNCTION(substr,             2, 0, 0, substrFunc       ),
     FUNCTION(substr,             3, 0, 0, substrFunc       ),
+    FUNCTION(unicode,            1, 0, 0, unicodeFunc      ),
+    FUNCTION(char,              -1, 0, 0, charFunc         ),
     FUNCTION(abs,                1, 0, 0, absFunc          ),
 #ifndef SQLITE_OMIT_FLOATING_POINT
     FUNCTION(round,              1, 0, 0, roundFunc        ),
@@ -87408,8 +87655,9 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
 ** --------------------------
 **
 ** Foreign keys in SQLite come in two flavours: deferred and immediate.
-** If an immediate foreign key constraint is violated, SQLITE_CONSTRAINT
-** is returned and the current statement transaction rolled back. If a 
+** If an immediate foreign key constraint is violated,
+** SQLITE_CONSTRAINT_FOREIGNKEY is returned and the current
+** statement transaction rolled back. If a 
 ** deferred foreign key constraint is violated, no action is taken 
 ** immediately. However if the application attempts to commit the 
 ** transaction before fixing the constraint violation, the attempt fails.
@@ -87473,7 +87721,8 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
 ** Immediate constraints are usually handled similarly. The only difference 
 ** is that the counter used is stored as part of each individual statement
 ** object (struct Vdbe). If, after the statement has run, its immediate
-** constraint counter is greater than zero, it returns SQLITE_CONSTRAINT
+** constraint counter is greater than zero,
+** it returns SQLITE_CONSTRAINT_FOREIGNKEY
 ** and the statement transaction is rolled back. An exception is an INSERT
 ** statement that inserts a single row only (no triggers). In this case,
 ** instead of using a counter, an exception is thrown immediately if the
@@ -87529,7 +87778,7 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
 ** A foreign key constraint requires that the key columns in the parent
 ** table are collectively subject to a UNIQUE or PRIMARY KEY constraint.
 ** Given that pParent is the parent table for foreign key constraint pFKey, 
-** search the schema a unique index on the parent key columns. 
+** search the schema for a unique index on the parent key columns. 
 **
 ** If successful, zero is returned. If the parent key is an INTEGER PRIMARY 
 ** KEY column, then output variable *ppIdx is set to NULL. Otherwise, *ppIdx 
@@ -87565,7 +87814,7 @@ SQLITE_PRIVATE void sqlite3RegisterGlobalFunctions(void){
 ** into pParse. If an OOM error occurs, non-zero is returned and the
 ** pParse->db->mallocFailed flag is set.
 */
-static int locateFkeyIndex(
+SQLITE_PRIVATE int sqlite3FkLocateIndex(
   Parse *pParse,                  /* Parse context to store any error in */
   Table *pParent,                 /* Parent table of FK constraint pFKey */
   FKey *pFKey,                    /* Foreign key to find index for */
@@ -87662,7 +87911,9 @@ static int locateFkeyIndex(
 
   if( !pIdx ){
     if( !pParse->disableTriggers ){
-      sqlite3ErrorMsg(pParse, "foreign key mismatch");
+      sqlite3ErrorMsg(pParse,
+           "foreign key mismatch - \"%w\" referencing \"%w\"",
+           pFKey->pFrom->zName, pFKey->zTo);
     }
     sqlite3DbFree(pParse->db, aiCol);
     return 1;
@@ -87811,8 +88062,8 @@ static void fkLookupParent(
     ** incrementing a counter. This is necessary as the VM code is being
     ** generated for will not open a statement transaction.  */
     assert( nIncr==1 );
-    sqlite3HaltConstraint(
-        pParse, OE_Abort, "foreign key constraint failed", P4_STATIC
+    sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
+        OE_Abort, "foreign key constraint failed", P4_STATIC
     );
   }else{
     if( nIncr>0 && pFKey->isDeferred==0 ){
@@ -88052,8 +88303,8 @@ SQLITE_PRIVATE void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTa
     ** any modifications to the schema are made. This is because statement
     ** transactions are not able to rollback schema changes.  */
     sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2);
-    sqlite3HaltConstraint(
-        pParse, OE_Abort, "foreign key constraint failed", P4_STATIC
+    sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
+        OE_Abort, "foreign key constraint failed", P4_STATIC
     );
 
     if( iSkip ){
@@ -88123,7 +88374,7 @@ SQLITE_PRIVATE void sqlite3FkCheck(
     }else{
       pTo = sqlite3LocateTable(pParse, 0, pFKey->zTo, zDb);
     }
-    if( !pTo || locateFkeyIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){
+    if( !pTo || sqlite3FkLocateIndex(pParse, pTo, pFKey, &pIdx, &aiFree) ){
       assert( isIgnoreErrors==0 || (regOld!=0 && regNew==0) );
       if( !isIgnoreErrors || db->mallocFailed ) return;
       if( pTo==0 ){
@@ -88203,7 +88454,7 @@ SQLITE_PRIVATE void sqlite3FkCheck(
       continue;
     }
 
-    if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
+    if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
       if( !isIgnoreErrors || db->mallocFailed ) return;
       continue;
     }
@@ -88258,7 +88509,7 @@ SQLITE_PRIVATE u32 sqlite3FkOldmask(
     }
     for(p=sqlite3FkReferences(pTab); p; p=p->pNextTo){
       Index *pIdx = 0;
-      locateFkeyIndex(pParse, pTab, p, &pIdx, 0);
+      sqlite3FkLocateIndex(pParse, pTab, p, &pIdx, 0);
       if( pIdx ){
         for(i=0; i<pIdx->nColumn; i++) mask |= COLUMN_MASK(pIdx->aiColumn[i]);
       }
@@ -88384,7 +88635,7 @@ static Trigger *fkActionTrigger(
     int i;                        /* Iterator variable */
     Expr *pWhen = 0;              /* WHEN clause for the trigger */
 
-    if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0;
+    if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ) return 0;
     assert( aiCol || pFKey->nCol==1 );
 
     for(i=0; i<pFKey->nCol; i++){
@@ -89857,7 +90108,7 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
       case OE_Fail: {
         char *zMsg;
         sqlite3VdbeAddOp3(v, OP_HaltIfNull,
-                                  SQLITE_CONSTRAINT, onError, regData+i);
+                          SQLITE_CONSTRAINT_NOTNULL, onError, regData+i);
         zMsg = sqlite3MPrintf(db, "%s.%s may not be NULL",
                               pTab->zName, pTab->aCol[i].zName);
         sqlite3VdbeChangeP4(v, -1, zMsg, P4_DYNAMIC);
@@ -89897,7 +90148,8 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
         }else{
           zConsName = 0;
         }
-        sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC);
+        sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_CHECK,
+                              onError, zConsName, P4_DYNAMIC);
       }
       sqlite3VdbeResolveLabel(v, allOk);
     }
@@ -89928,8 +90180,8 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
       case OE_Rollback:
       case OE_Abort:
       case OE_Fail: {
-        sqlite3HaltConstraint(
-          pParse, onError, "PRIMARY KEY must be unique", P4_STATIC);
+        sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_PRIMARYKEY,
+           onError, "PRIMARY KEY must be unique", P4_STATIC);
         break;
       }
       case OE_Replace: {
@@ -90056,7 +90308,8 @@ SQLITE_PRIVATE void sqlite3GenerateConstraintChecks(
         sqlite3StrAccumAppend(&errMsg,
             pIdx->nColumn>1 ? " are not unique" : " is not unique", -1);
         zErr = sqlite3StrAccumFinish(&errMsg);
-        sqlite3HaltConstraint(pParse, onError, zErr, 0);
+        sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE,
+                              onError, zErr, 0);
         sqlite3DbFree(errMsg.db, zErr);
         break;
       }
@@ -90464,8 +90717,8 @@ static int xferOptimization(
   if( pDest->iPKey>=0 ){
     addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
     addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
-    sqlite3HaltConstraint(
-        pParse, onError, "PRIMARY KEY must be unique", P4_STATIC);
+    sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_PRIMARYKEY,
+        onError, "PRIMARY KEY must be unique", P4_STATIC);
     sqlite3VdbeJumpHere(v, addr2);
     autoIncStep(pParse, regAutoinc, regRowid);
   }else if( pDest->pIndex==0 ){
@@ -90922,6 +91175,20 @@ struct sqlite3_api_routines {
   int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
   int (*vtab_config)(sqlite3*,int op,...);
   int (*vtab_on_conflict)(sqlite3*);
+  /* Version 3.7.16 and later */
+  int (*close_v2)(sqlite3*);
+  const char *(*db_filename)(sqlite3*,const char*);
+  int (*db_readonly)(sqlite3*,const char*);
+  int (*db_release_memory)(sqlite3*);
+  const char *(*errstr)(int);
+  int (*stmt_busy)(sqlite3_stmt*);
+  int (*stmt_readonly)(sqlite3_stmt*);
+  int (*stricmp)(const char*,const char*);
+  int (*uri_boolean)(const char*,const char*,int);
+  sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
+  const char *(*uri_parameter)(const char*,const char*);
+  char *(*vsnprintf)(int,char*,const char*,va_list);
+  int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
 };
 
 /*
@@ -91125,6 +91392,20 @@ struct sqlite3_api_routines {
 #define sqlite3_blob_reopen            sqlite3_api->blob_reopen
 #define sqlite3_vtab_config            sqlite3_api->vtab_config
 #define sqlite3_vtab_on_conflict       sqlite3_api->vtab_on_conflict
+/* Version 3.7.16 and later */
+#define sqlite3_close_v2               sqlite3_api->close_v2
+#define sqlite3_db_filename            sqlite3_api->db_filename
+#define sqlite3_db_readonly            sqlite3_api->db_readonly
+#define sqlite3_db_release_memory      sqlite3_api->db_release_memory
+#define sqlite3_errstr                 sqlite3_api->errstr
+#define sqlite3_stmt_busy              sqlite3_api->stmt_busy
+#define sqlite3_stmt_readonly          sqlite3_api->stmt_readonly
+#define sqlite3_stricmp                sqlite3_api->stricmp
+#define sqlite3_uri_boolean            sqlite3_api->uri_boolean
+#define sqlite3_uri_int64              sqlite3_api->uri_int64
+#define sqlite3_uri_parameter          sqlite3_api->uri_parameter
+#define sqlite3_uri_vsnprintf          sqlite3_api->vsnprintf
+#define sqlite3_wal_checkpoint_v2      sqlite3_api->wal_checkpoint_v2
 #endif /* SQLITE_CORE */
 
 #define SQLITE_EXTENSION_INIT1     const sqlite3_api_routines *sqlite3_api = 0;
@@ -91494,6 +91775,19 @@ static const sqlite3_api_routines sqlite3Apis = {
   sqlite3_blob_reopen,
   sqlite3_vtab_config,
   sqlite3_vtab_on_conflict,
+  sqlite3_close_v2,
+  sqlite3_db_filename,
+  sqlite3_db_readonly,
+  sqlite3_db_release_memory,
+  sqlite3_errstr,
+  sqlite3_stmt_busy,
+  sqlite3_stmt_readonly,
+  sqlite3_stricmp,
+  sqlite3_uri_boolean,
+  sqlite3_uri_int64,
+  sqlite3_uri_parameter,
+  sqlite3_vsnprintf,
+  sqlite3_wal_checkpoint_v2
 };
 
 /*
@@ -91960,6 +92254,9 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){
     { "sql_trace",                SQLITE_SqlTrace      },
     { "vdbe_listing",             SQLITE_VdbeListing   },
     { "vdbe_trace",               SQLITE_VdbeTrace     },
+    { "vdbe_addoptrace",          SQLITE_VdbeAddopTrace},
+    { "vdbe_debug",    SQLITE_SqlTrace | SQLITE_VdbeListing
+                               | SQLITE_VdbeTrace      },
 #endif
 #ifndef SQLITE_OMIT_CHECK
     { "ignore_check_constraints", SQLITE_IgnoreChecks  },
@@ -92724,11 +93021,14 @@ SQLITE_PRIVATE void sqlite3Pragma(
     if( sqlite3ReadSchema(pParse) ) goto pragma_out;
     pTab = sqlite3FindTable(db, zRight, zDb);
     if( pTab ){
-      int i;
+      int i, k;
       int nHidden = 0;
       Column *pCol;
+      Index *pPk;
+      for(pPk=pTab->pIndex; pPk && pPk->autoIndex!=2; pPk=pPk->pNext){}
       sqlite3VdbeSetNumCols(v, 6);
       pParse->nMem = 6;
+      sqlite3CodeVerifySchema(pParse, iDb);
       sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "cid", SQLITE_STATIC);
       sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
       sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "type", SQLITE_STATIC);
@@ -92751,8 +93051,14 @@ SQLITE_PRIVATE void sqlite3Pragma(
         }else{
           sqlite3VdbeAddOp2(v, OP_Null, 0, 5);
         }
-        sqlite3VdbeAddOp2(v, OP_Integer,
-                            (pCol->colFlags&COLFLAG_PRIMKEY)!=0, 6);
+        if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){
+          k = 0;
+        }else if( pPk==0 ){
+          k = 1;
+        }else{
+          for(k=1; ALWAYS(k<=pTab->nCol) && pPk->aiColumn[k-1]!=i; k++){}
+        }
+        sqlite3VdbeAddOp2(v, OP_Integer, k, 6);
         sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
       }
     }
@@ -92768,6 +93074,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
       pTab = pIdx->pTable;
       sqlite3VdbeSetNumCols(v, 3);
       pParse->nMem = 3;
+      sqlite3CodeVerifySchema(pParse, iDb);
       sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", SQLITE_STATIC);
       sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", SQLITE_STATIC);
       sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", SQLITE_STATIC);
@@ -92794,6 +93101,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
         int i = 0; 
         sqlite3VdbeSetNumCols(v, 3);
         pParse->nMem = 3;
+        sqlite3CodeVerifySchema(pParse, iDb);
         sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
         sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
         sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
@@ -92857,6 +93165,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
         int i = 0; 
         sqlite3VdbeSetNumCols(v, 8);
         pParse->nMem = 8;
+        sqlite3CodeVerifySchema(pParse, iDb);
         sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "id", SQLITE_STATIC);
         sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "seq", SQLITE_STATIC);
         sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "table", SQLITE_STATIC);
@@ -92890,6 +93199,122 @@ SQLITE_PRIVATE void sqlite3Pragma(
   }else
 #endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
 
+#ifndef SQLITE_OMIT_FOREIGN_KEY
+#ifndef SQLITE_OMIT_TRIGGER
+  if( sqlite3StrICmp(zLeft, "foreign_key_check")==0 ){
+    FKey *pFK;             /* A foreign key constraint */
+    Table *pTab;           /* Child table contain "REFERENCES" keyword */
+    Table *pParent;        /* Parent table that child points to */
+    Index *pIdx;           /* Index in the parent table */
+    int i;                 /* Loop counter:  Foreign key number for pTab */
+    int j;                 /* Loop counter:  Field of the foreign key */
+    HashElem *k;           /* Loop counter:  Next table in schema */
+    int x;                 /* result variable */
+    int regResult;         /* 3 registers to hold a result row */
+    int regKey;            /* Register to hold key for checking the FK */
+    int regRow;            /* Registers to hold a row from pTab */
+    int addrTop;           /* Top of a loop checking foreign keys */
+    int addrOk;            /* Jump here if the key is OK */
+    int *aiCols;           /* child to parent column mapping */
+
+    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
+    regResult = pParse->nMem+1;
+    pParse->nMem += 4;
+    regKey = ++pParse->nMem;
+    regRow = ++pParse->nMem;
+    v = sqlite3GetVdbe(pParse);
+    sqlite3VdbeSetNumCols(v, 4);
+    sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC);
+    sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "rowid", SQLITE_STATIC);
+    sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "parent", SQLITE_STATIC);
+    sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "fkid", SQLITE_STATIC);
+    sqlite3CodeVerifySchema(pParse, iDb);
+    k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash);
+    while( k ){
+      if( zRight ){
+        pTab = sqlite3LocateTable(pParse, 0, zRight, zDb);
+        k = 0;
+      }else{
+        pTab = (Table*)sqliteHashData(k);
+        k = sqliteHashNext(k);
+      }
+      if( pTab==0 || pTab->pFKey==0 ) continue;
+      sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
+      if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
+      sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
+      sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName,
+                        P4_TRANSIENT);
+      for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
+        pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
+        if( pParent==0 ) break;
+        pIdx = 0;
+        sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName);
+        x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0);
+        if( x==0 ){
+          if( pIdx==0 ){
+            sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead);
+          }else{
+            KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
+            sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb);
+            sqlite3VdbeChangeP4(v, -1, (char*)pKey, P4_KEYINFO_HANDOFF);
+          }
+        }else{
+          k = 0;
+          break;
+        }
+      }
+      if( pFK ) break;
+      if( pParse->nTab<i ) pParse->nTab = i;
+      addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0);
+      for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
+        pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
+        assert( pParent!=0 );
+        pIdx = 0;
+        aiCols = 0;
+        x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
+        assert( x==0 );
+        addrOk = sqlite3VdbeMakeLabel(v);
+        if( pIdx==0 ){
+          int iKey = pFK->aCol[0].iFrom;
+          assert( iKey>=0 && iKey<pTab->nCol );
+          if( iKey!=pTab->iPKey ){
+            sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow);
+            sqlite3ColumnDefault(v, pTab, iKey, regRow);
+            sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk);
+            sqlite3VdbeAddOp2(v, OP_MustBeInt, regRow,
+               sqlite3VdbeCurrentAddr(v)+3);
+          }else{
+            sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow);
+          }
+          sqlite3VdbeAddOp3(v, OP_NotExists, i, 0, regRow);
+          sqlite3VdbeAddOp2(v, OP_Goto, 0, addrOk);
+          sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
+        }else{
+          for(j=0; j<pFK->nCol; j++){
+            sqlite3ExprCodeGetColumnOfTable(v, pTab, 0,
+                            aiCols ? aiCols[j] : pFK->aCol[0].iFrom, regRow+j);
+            sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk);
+          }
+          sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey);
+          sqlite3VdbeChangeP4(v, -1,
+                   sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT);
+          sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
+        }
+        sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
+        sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0, 
+                          pFK->zTo, P4_TRANSIENT);
+        sqlite3VdbeAddOp2(v, OP_Integer, i-1, regResult+3);
+        sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4);
+        sqlite3VdbeResolveLabel(v, addrOk);
+        sqlite3DbFree(db, aiCols);
+      }
+      sqlite3VdbeAddOp2(v, OP_Next, 0, addrTop+1);
+      sqlite3VdbeJumpHere(v, addrTop);
+    }
+  }else
+#endif /* !defined(SQLITE_OMIT_TRIGGER) */
+#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */
+
 #ifndef NDEBUG
   if( sqlite3StrICmp(zLeft, "parser_trace")==0 ){
     if( zRight ){
@@ -93387,7 +93812,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
   }else
 #endif
 #if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
-  if( sqlite3StrICmp(zLeft, "activate_extensions")==0 ){
+  if( sqlite3StrICmp(zLeft, "activate_extensions")==0 && zRight ){
 #ifdef SQLITE_HAS_CODEC
     if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){
       sqlite3_activate_see(&zRight[4]);
@@ -93604,7 +94029,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
 
   /* zMasterSchema and zInitScript are set to point at the master schema
   ** and initialisation script appropriate for the database being
-  ** initialised. zMasterName is the name of the master table.
+  ** initialized. zMasterName is the name of the master table.
   */
   if( !OMIT_TEMPDB && iDb==1 ){
     zMasterSchema = temp_master_schema;
@@ -93684,11 +94109,15 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
   */
   if( meta[BTREE_TEXT_ENCODING-1] ){  /* text encoding */
     if( iDb==0 ){
+#ifndef SQLITE_OMIT_UTF16
       u8 encoding;
       /* If opening the main database, set ENC(db). */
       encoding = (u8)meta[BTREE_TEXT_ENCODING-1] & 3;
       if( encoding==0 ) encoding = SQLITE_UTF8;
       ENC(db) = encoding;
+#else
+      ENC(db) = SQLITE_UTF8;
+#endif
     }else{
       /* If opening an attached database, the encoding much match ENC(db) */
       if( meta[BTREE_TEXT_ENCODING-1]!=ENC(db) ){
@@ -93825,7 +94254,7 @@ SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){
     }
   }
 
-  /* Once all the other databases have been initialised, load the schema
+  /* Once all the other databases have been initialized, load the schema
   ** for the TEMP database. This is loaded last, as the TEMP database
   ** schema may contain references to objects in other databases.
   */
@@ -93848,7 +94277,7 @@ SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){
 }
 
 /*
-** This routine is a no-op if the database schema is already initialised.
+** This routine is a no-op if the database schema is already initialized.
 ** Otherwise, the schema is loaded. An error code is returned.
 */
 SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse){
@@ -94346,7 +94775,7 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
   ExprList *pGroupBy,   /* the GROUP BY clause */
   Expr *pHaving,        /* the HAVING clause */
   ExprList *pOrderBy,   /* the ORDER BY clause */
-  int isDistinct,       /* true if the DISTINCT keyword is present */
+  u16 selFlags,         /* Flag parameters, such as SF_Distinct */
   Expr *pLimit,         /* LIMIT value.  NULL means not used */
   Expr *pOffset         /* OFFSET value.  NULL means no offset */
 ){
@@ -94370,7 +94799,7 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
   pNew->pGroupBy = pGroupBy;
   pNew->pHaving = pHaving;
   pNew->pOrderBy = pOrderBy;
-  pNew->selFlags = isDistinct ? SF_Distinct : 0;
+  pNew->selFlags = selFlags;
   pNew->op = TK_SELECT;
   pNew->pLimit = pLimit;
   pNew->pOffset = pOffset;
@@ -95627,8 +96056,6 @@ static int selectColumnsFromExprList(
     /* Get an appropriate name for the column
     */
     p = sqlite3ExprSkipCollate(pEList->a[i].pExpr);
-    assert( p->pRight==0 || ExprHasProperty(p->pRight, EP_IntValue)
-               || p->pRight->u.zToken==0 || p->pRight->u.zToken[0]!=0 );
     if( (zName = pEList->a[i].zName)!=0 ){
       /* If the column contains an "AS <name>" phrase, use <name> as the name */
       zName = sqlite3DbStrDup(db, zName);
@@ -95666,6 +96093,9 @@ static int selectColumnsFromExprList(
     for(j=cnt=0; j<i; j++){
       if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){
         char *zNewName;
+        int k;
+        for(k=nName-1; k>1 && sqlite3Isdigit(zName[k]); k--){}
+        if( zName[k]==':' ) nName = k;
         zName[nName] = 0;
         zNewName = sqlite3MPrintf(db, "%s:%d", zName, ++cnt);
         sqlite3DbFree(db, zName);
@@ -95997,6 +96427,8 @@ static int multiSelect(
       int addr = 0;
       int nLimit;
       assert( !pPrior->pLimit );
+      pPrior->iLimit = p->iLimit;
+      pPrior->iOffset = p->iOffset;
       pPrior->pLimit = p->pLimit;
       pPrior->pOffset = p->pOffset;
       explainSetInteger(iSub1, pParse->iNextSelectId);
@@ -96654,7 +97086,8 @@ static int multiSelectOrderBy(
   }else{
     int nExpr = p->pEList->nExpr;
     assert( nOrderBy>=nExpr || db->mallocFailed );
-    regPrev = sqlite3GetTempRange(pParse, nExpr+1);
+    regPrev = pParse->nMem+1;
+    pParse->nMem += nExpr+1;
     sqlite3VdbeAddOp2(v, OP_Integer, 0, regPrev);
     pKeyDup = sqlite3DbMallocZero(db,
                   sizeof(*pKeyDup) + nExpr*(sizeof(CollSeq*)+1) );
@@ -96836,12 +97269,6 @@ static int multiSelectOrderBy(
   sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE);
   sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB);
 
-  /* Release temporary registers
-  */
-  if( regPrev ){
-    sqlite3ReleaseTempRange(pParse, regPrev, nOrderBy+1);
-  }
-
   /* Jump to the this point in order to terminate the query.
   */
   sqlite3VdbeResolveLabel(v, labelEnd);
@@ -97253,12 +97680,15 @@ static int flattenSubquery(
     Select *pNew;
     ExprList *pOrderBy = p->pOrderBy;
     Expr *pLimit = p->pLimit;
+    Expr *pOffset = p->pOffset;
     Select *pPrior = p->pPrior;
     p->pOrderBy = 0;
     p->pSrc = 0;
     p->pPrior = 0;
     p->pLimit = 0;
+    p->pOffset = 0;
     pNew = sqlite3SelectDup(db, p, 0);
+    p->pOffset = pOffset;
     p->pLimit = pLimit;
     p->pOrderBy = pOrderBy;
     p->pSrc = pSrc;
@@ -97451,34 +97881,43 @@ static int flattenSubquery(
 #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
 
 /*
-** Analyze the SELECT statement passed as an argument to see if it
-** is a min() or max() query. Return WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX if 
-** it is, or 0 otherwise. At present, a query is considered to be
-** a min()/max() query if:
+** Based on the contents of the AggInfo structure indicated by the first
+** argument, this function checks if the following are true:
 **
-**   1. There is a single object in the FROM clause.
+**    * the query contains just a single aggregate function,
+**    * the aggregate function is either min() or max(), and
+**    * the argument to the aggregate function is a column value.
 **
-**   2. There is a single expression in the result set, and it is
-**      either min(x) or max(x), where x is a column reference.
+** If all of the above are true, then WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX
+** is returned as appropriate. Also, *ppMinMax is set to point to the 
+** list of arguments passed to the aggregate before returning.
+**
+** Or, if the conditions above are not met, *ppMinMax is set to 0 and
+** WHERE_ORDERBY_NORMAL is returned.
 */
-static u8 minMaxQuery(Select *p){
-  Expr *pExpr;
-  ExprList *pEList = p->pEList;
+static u8 minMaxQuery(AggInfo *pAggInfo, ExprList **ppMinMax){
+  int eRet = WHERE_ORDERBY_NORMAL;          /* Return value */
 
-  if( pEList->nExpr!=1 ) return WHERE_ORDERBY_NORMAL;
-  pExpr = pEList->a[0].pExpr;
-  if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
-  if( NEVER(ExprHasProperty(pExpr, EP_xIsSelect)) ) return 0;
-  pEList = pExpr->x.pList;
-  if( pEList==0 || pEList->nExpr!=1 ) return 0;
-  if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return WHERE_ORDERBY_NORMAL;
-  assert( !ExprHasProperty(pExpr, EP_IntValue) );
-  if( sqlite3StrICmp(pExpr->u.zToken,"min")==0 ){
-    return WHERE_ORDERBY_MIN;
-  }else if( sqlite3StrICmp(pExpr->u.zToken,"max")==0 ){
-    return WHERE_ORDERBY_MAX;
+  *ppMinMax = 0;
+  if( pAggInfo->nFunc==1 ){
+    Expr *pExpr = pAggInfo->aFunc[0].pExpr; /* Aggregate function */
+    ExprList *pEList = pExpr->x.pList;      /* Arguments to agg function */
+
+    assert( pExpr->op==TK_AGG_FUNCTION );
+    if( pEList && pEList->nExpr==1 && pEList->a[0].pExpr->op==TK_AGG_COLUMN ){
+      const char *zFunc = pExpr->u.zToken;
+      if( sqlite3StrICmp(zFunc, "min")==0 ){
+        eRet = WHERE_ORDERBY_MIN;
+        *ppMinMax = pEList;
+      }else if( sqlite3StrICmp(zFunc, "max")==0 ){
+        eRet = WHERE_ORDERBY_MAX;
+        *ppMinMax = pEList;
+      }
+    }
   }
-  return WHERE_ORDERBY_NORMAL;
+
+  assert( *ppMinMax==0 || (*ppMinMax)->nExpr==1 );
+  return eRet;
 }
 
 /*
@@ -97573,14 +98012,16 @@ static int selectExpander(Walker *pWalker, Select *p){
   ExprList *pEList;
   struct SrcList_item *pFrom;
   sqlite3 *db = pParse->db;
+  Expr *pE, *pRight, *pExpr;
+  u16 selFlags = p->selFlags;
 
+  p->selFlags |= SF_Expanded;
   if( db->mallocFailed  ){
     return WRC_Abort;
   }
-  if( NEVER(p->pSrc==0) || (p->selFlags & SF_Expanded)!=0 ){
+  if( NEVER(p->pSrc==0) || (selFlags & SF_Expanded)!=0 ){
     return WRC_Prune;
   }
-  p->selFlags |= SF_Expanded;
   pTabList = p->pSrc;
   pEList = p->pEList;
 
@@ -97623,6 +98064,12 @@ static int selectExpander(Walker *pWalker, Select *p){
       assert( pFrom->pTab==0 );
       pFrom->pTab = pTab = sqlite3LocateTableItem(pParse, 0, pFrom);
       if( pTab==0 ) return WRC_Abort;
+      if( pTab->nRef==0xffff ){
+        sqlite3ErrorMsg(pParse, "too many references to \"%s\": max 65535",
+           pTab->zName);
+        pFrom->pTab = 0;
+        return WRC_Abort;
+      }
       pTab->nRef++;
 #if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
       if( pTab->pSelect || IsVirtual(pTab) ){
@@ -97658,7 +98105,7 @@ static int selectExpander(Walker *pWalker, Select *p){
   ** that need expanding.
   */
   for(k=0; k<pEList->nExpr; k++){
-    Expr *pE = pEList->a[k].pExpr;
+    pE = pEList->a[k].pExpr;
     if( pE->op==TK_ALL ) break;
     assert( pE->op!=TK_DOT || pE->pRight!=0 );
     assert( pE->op!=TK_DOT || (pE->pLeft!=0 && pE->pLeft->op==TK_ID) );
@@ -97676,10 +98123,18 @@ static int selectExpander(Walker *pWalker, Select *p){
     int longNames = (flags & SQLITE_FullColNames)!=0
                       && (flags & SQLITE_ShortColNames)==0;
 
+    /* When processing FROM-clause subqueries, it is always the case
+    ** that full_column_names=OFF and short_column_names=ON.  The
+    ** sqlite3ResultSetOfSelect() routine makes it so. */
+    assert( (p->selFlags & SF_NestedFrom)==0
+          || ((flags & SQLITE_FullColNames)==0 &&
+              (flags & SQLITE_ShortColNames)!=0) );
+
     for(k=0; k<pEList->nExpr; k++){
-      Expr *pE = a[k].pExpr;
-      assert( pE->op!=TK_DOT || pE->pRight!=0 );
-      if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pE->pRight->op!=TK_ALL) ){
+      pE = a[k].pExpr;
+      pRight = pE->pRight;
+      assert( pE->op!=TK_DOT || pRight!=0 );
+      if( pE->op!=TK_ALL && (pE->op!=TK_DOT || pRight->op!=TK_ALL) ){
         /* This particular expression does not need to be expanded.
         */
         pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr);
@@ -97694,32 +98149,43 @@ static int selectExpander(Walker *pWalker, Select *p){
         /* This expression is a "*" or a "TABLE.*" and needs to be
         ** expanded. */
         int tableSeen = 0;      /* Set to 1 when TABLE matches */
-        char *zTName;            /* text of name of TABLE */
+        char *zTName = 0;       /* text of name of TABLE */
         if( pE->op==TK_DOT ){
           assert( pE->pLeft!=0 );
           assert( !ExprHasProperty(pE->pLeft, EP_IntValue) );
           zTName = pE->pLeft->u.zToken;
-        }else{
-          zTName = 0;
         }
         for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
           Table *pTab = pFrom->pTab;
+          Select *pSub = pFrom->pSelect;
           char *zTabName = pFrom->zAlias;
+          const char *zSchemaName = 0;
+          int iDb;
           if( zTabName==0 ){
             zTabName = pTab->zName;
           }
           if( db->mallocFailed ) break;
-          if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
-            continue;
+          if( pSub==0 || (pSub->selFlags & SF_NestedFrom)==0 ){
+            pSub = 0;
+            if( zTName && sqlite3StrICmp(zTName, zTabName)!=0 ){
+              continue;
+            }
+            iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+            zSchemaName = iDb>=0 ? db->aDb[iDb].zName : "*";
           }
-          tableSeen = 1;
           for(j=0; j<pTab->nCol; j++){
-            Expr *pExpr, *pRight;
             char *zName = pTab->aCol[j].zName;
             char *zColname;  /* The computed column name */
             char *zToFree;   /* Malloced string that needs to be freed */
             Token sColname;  /* Computed column name as a token */
 
+            assert( zName );
+            if( zTName && pSub
+             && sqlite3MatchSpanName(pSub->pEList->a[j].zSpan, 0, zTName, 0)==0
+            ){
+              continue;
+            }
+
             /* If a column is marked as 'hidden' (currently only possible
             ** for virtual tables), do not include it in the expanded
             ** result-set list.
@@ -97728,6 +98194,7 @@ static int selectExpander(Walker *pWalker, Select *p){
               assert(IsVirtual(pTab));
               continue;
             }
+            tableSeen = 1;
 
             if( i>0 && zTName==0 ){
               if( (pFrom->jointype & JT_NATURAL)!=0
@@ -97750,6 +98217,10 @@ static int selectExpander(Walker *pWalker, Select *p){
               Expr *pLeft;
               pLeft = sqlite3Expr(db, TK_ID, zTabName);
               pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
+              if( zSchemaName ){
+                pLeft = sqlite3Expr(db, TK_ID, zSchemaName);
+                pExpr = sqlite3PExpr(pParse, TK_DOT, pLeft, pExpr, 0);
+              }
               if( longNames ){
                 zColname = sqlite3MPrintf(db, "%s.%s", zTabName, zName);
                 zToFree = zColname;
@@ -97761,6 +98232,18 @@ static int selectExpander(Walker *pWalker, Select *p){
             sColname.z = zColname;
             sColname.n = sqlite3Strlen30(zColname);
             sqlite3ExprListSetName(pParse, pNew, &sColname, 0);
+            if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){
+              struct ExprList_item *pX = &pNew->a[pNew->nExpr-1];
+              if( pSub ){
+                pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan);
+                testcase( pX->zSpan==0 );
+              }else{
+                pX->zSpan = sqlite3MPrintf(db, "%s.%s.%s",
+                                           zSchemaName, zTabName, zColname);
+                testcase( pX->zSpan==0 );
+              }
+              pX->bSpanIsTab = 1;
+            }
             sqlite3DbFree(db, zToFree);
           }
         }
@@ -97899,6 +98382,7 @@ SQLITE_PRIVATE void sqlite3SelectPrep(
   sqlite3 *db;
   if( NEVER(p==0) ) return;
   db = pParse->db;
+  if( db->mallocFailed ) return;
   if( p->selFlags & SF_HasTypeInfo ) return;
   sqlite3SelectExpand(pParse, p);
   if( pParse->nErr || db->mallocFailed ) return;
@@ -98806,7 +99290,7 @@ SQLITE_PRIVATE int sqlite3Select(
         ** value of x, the only row required).
         **
         ** A special flag must be passed to sqlite3WhereBegin() to slightly
-        ** modify behaviour as follows:
+        ** modify behavior as follows:
         **
         **   + If the query is a "SELECT min(x)", then the loop coded by
         **     where.c should not iterate over any values with a NULL value
@@ -98818,11 +99302,17 @@ SQLITE_PRIVATE int sqlite3Select(
         **     Refer to code and comments in where.c for details.
         */
         ExprList *pMinMax = 0;
-        u8 flag = minMaxQuery(p);
+        u8 flag = WHERE_ORDERBY_NORMAL;
+        
+        assert( p->pGroupBy==0 );
+        assert( flag==0 );
+        if( p->pHaving==0 ){
+          flag = minMaxQuery(&sAggInfo, &pMinMax);
+        }
+        assert( flag==0 || (pMinMax!=0 && pMinMax->nExpr==1) );
+
         if( flag ){
-          assert( !ExprHasProperty(p->pEList->a[0].pExpr, EP_xIsSelect) );
-          assert( p->pEList->a[0].pExpr->x.pList->nExpr==1 );
-          pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->x.pList,0);
+          pMinMax = sqlite3ExprListDup(db, pMinMax, 0);
           pDel = pMinMax;
           if( pMinMax && !db->mallocFailed ){
             pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0;
@@ -98978,7 +99468,10 @@ SQLITE_PRIVATE void sqlite3ExplainSelect(Vdbe *pVdbe, Select *p){
     sqlite3ExplainPrintf(pVdbe, "(null-select)");
     return;
   }
-  while( p->pPrior ) p = p->pPrior;
+  while( p->pPrior ){
+    p->pPrior->pNext = p;
+    p = p->pPrior;
+  }
   sqlite3ExplainPush(pVdbe);
   while( p ){
     explainOneSelect(pVdbe, p);
@@ -100790,7 +101283,7 @@ SQLITE_PRIVATE void sqlite3Update(
 
     /* The row-trigger may have deleted the row being updated. In this
     ** case, jump to the next row. No updates or AFTER triggers are 
-    ** required. This behaviour - what happens when the row being updated
+    ** required. This behavior - what happens when the row being updated
     ** is deleted or renamed by a BEFORE trigger - is left undefined in the
     ** documentation.
     */
@@ -102555,8 +103048,8 @@ struct WhereTerm {
   int leftCursor;         /* Cursor number of X in "X <op> <expr>" */
   union {
     int leftColumn;         /* Column number of X in "X <op> <expr>" */
-    WhereOrInfo *pOrInfo;   /* Extra information if eOperator==WO_OR */
-    WhereAndInfo *pAndInfo; /* Extra information if eOperator==WO_AND */
+    WhereOrInfo *pOrInfo;   /* Extra information if (eOperator & WO_OR)!=0 */
+    WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
   } u;
   u16 eOperator;          /* A WO_xx value describing <op> */
   u8 wtFlags;             /* TERM_xxx bit flags.  See below */
@@ -102597,7 +103090,6 @@ struct WhereTerm {
 struct WhereClause {
   Parse *pParse;           /* The parser context */
   WhereMaskSet *pMaskSet;  /* Mapping of table cursor numbers to bitmasks */
-  Bitmask vmask;           /* Bitmask identifying virtual table cursors */
   WhereClause *pOuter;     /* Outer conjunction */
   u8 op;                   /* Split operator.  TK_AND or TK_OR */
   u16 wctrlFlags;          /* Might include WHERE_AND_ONLY */
@@ -102684,6 +103176,7 @@ struct WhereCost {
 #define WO_ISNULL 0x080
 #define WO_OR     0x100       /* Two or more OR-connected terms */
 #define WO_AND    0x200       /* Two or more AND-connected terms */
+#define WO_EQUIV  0x400       /* Of the form A==B, both columns */
 #define WO_NOOP   0x800       /* This term does not restrict search space */
 
 #define WO_ALL    0xfff       /* Mask of all possible WO_* values */
@@ -102710,7 +103203,7 @@ struct WhereCost {
 #define WHERE_COLUMN_NULL  0x00080000  /* x IS NULL */
 #define WHERE_INDEXED      0x000f0000  /* Anything that uses an index */
 #define WHERE_NOT_FULLSCAN 0x100f3000  /* Does not do a full table scan */
-#define WHERE_IN_ABLE      0x000f1000  /* Able to support an IN operator */
+#define WHERE_IN_ABLE      0x080f1000  /* Able to support an IN operator */
 #define WHERE_TOP_LIMIT    0x00100000  /* x<EXPR or x<=EXPR constraint */
 #define WHERE_BTM_LIMIT    0x00200000  /* x>EXPR or x>=EXPR constraint */
 #define WHERE_BOTH_LIMIT   0x00300000  /* Both x>EXPR and x<EXPR */
@@ -102719,6 +103212,8 @@ struct WhereCost {
 #define WHERE_REVERSE      0x01000000  /* Scan in reverse order */
 #define WHERE_UNIQUE       0x02000000  /* Selects no more than one row */
 #define WHERE_ALL_UNIQUE   0x04000000  /* This and all prior have one row */
+#define WHERE_OB_UNIQUE    0x00004000  /* Values in ORDER BY columns are 
+                                       ** different for every output row */
 #define WHERE_VIRTUALTABLE 0x08000000  /* Use virtual-table processing */
 #define WHERE_MULTI_OR     0x10000000  /* OR using multiple indices */
 #define WHERE_TEMP_INDEX   0x20000000  /* Uses an ephemeral index */
@@ -102773,7 +103268,6 @@ static void whereClauseInit(
   pWC->nTerm = 0;
   pWC->nSlot = ArraySize(pWC->aStatic);
   pWC->a = pWC->aStatic;
-  pWC->vmask = 0;
   pWC->wctrlFlags = wctrlFlags;
 }
 
@@ -103020,7 +103514,7 @@ static int allowedOp(int op){
 ** Commute a comparison operator.  Expressions of the form "X op Y"
 ** are converted into "Y op X".
 **
-** If left/right precendence rules come into play when determining the
+** If left/right precedence rules come into play when determining the
 ** collating
 ** side of the comparison, it remains associated with the same side after
 ** the commutation. So "Y collate NOCASE op X" becomes 
@@ -103086,6 +103580,23 @@ static u16 operatorMask(int op){
 ** where X is a reference to the iColumn of table iCur and <op> is one of
 ** the WO_xx operator codes specified by the op parameter.
 ** Return a pointer to the term.  Return 0 if not found.
+**
+** The term returned might by Y=<expr> if there is another constraint in
+** the WHERE clause that specifies that X=Y.  Any such constraints will be
+** identified by the WO_EQUIV bit in the pTerm->eOperator field.  The
+** aEquiv[] array holds X and all its equivalents, with each SQL variable
+** taking up two slots in aEquiv[].  The first slot is for the cursor number
+** and the second is for the column number.  There are 22 slots in aEquiv[]
+** so that means we can look for X plus up to 10 other equivalent values.
+** Hence a search for X will return <expr> if X=A1 and A1=A2 and A2=A3
+** and ... and A9=A10 and A10=<expr>.
+**
+** If there are multiple terms in the WHERE clause of the form "X <op> <expr>"
+** then try for the one with no dependencies on <expr> - in other words where
+** <expr> is a constant expression of some kind.  Only return entries of
+** the form "X <op> Y" where Y is a column in another table if no terms of
+** the form "X <op> <const-expr>" exist.   If no terms with a constant RHS
+** exist, try to return a term that does not use WO_EQUIV.
 */
 static WhereTerm *findTerm(
   WhereClause *pWC,     /* The WHERE clause to be searched */
@@ -103095,45 +103606,85 @@ static WhereTerm *findTerm(
   u32 op,               /* Mask of WO_xx values describing operator */
   Index *pIdx           /* Must be compatible with this index, if not NULL */
 ){
-  WhereTerm *pTerm;
-  int k;
+  WhereTerm *pTerm;            /* Term being examined as possible result */
+  WhereTerm *pResult = 0;      /* The answer to return */
+  WhereClause *pWCOrig = pWC;  /* Original pWC value */
+  int j, k;                    /* Loop counters */
+  Expr *pX;                /* Pointer to an expression */
+  Parse *pParse;           /* Parsing context */
+  int iOrigCol = iColumn;  /* Original value of iColumn */
+  int nEquiv = 2;          /* Number of entires in aEquiv[] */
+  int iEquiv = 2;          /* Number of entries of aEquiv[] processed so far */
+  int aEquiv[22];          /* iCur,iColumn and up to 10 other equivalents */
+
   assert( iCur>=0 );
-  op &= WO_ALL;
-  for(; pWC; pWC=pWC->pOuter){
-    for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
-      if( pTerm->leftCursor==iCur
-         && (pTerm->prereqRight & notReady)==0
-         && pTerm->u.leftColumn==iColumn
-         && (pTerm->eOperator & op)!=0
-      ){
-        if( iColumn>=0 && pIdx && pTerm->eOperator!=WO_ISNULL ){
-          Expr *pX = pTerm->pExpr;
-          CollSeq *pColl;
-          char idxaff;
-          int j;
-          Parse *pParse = pWC->pParse;
-  
-          idxaff = pIdx->pTable->aCol[iColumn].affinity;
-          if( !sqlite3IndexAffinityOk(pX, idxaff) ) continue;
-  
-          /* Figure out the collation sequence required from an index for
-          ** it to be useful for optimising expression pX. Store this
-          ** value in variable pColl.
-          */
-          assert(pX->pLeft);
-          pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
-          if( pColl==0 ) pColl = pParse->db->pDfltColl;
-  
-          for(j=0; pIdx->aiColumn[j]!=iColumn; j++){
-            if( NEVER(j>=pIdx->nColumn) ) return 0;
+  aEquiv[0] = iCur;
+  aEquiv[1] = iColumn;
+  for(;;){
+    for(pWC=pWCOrig; pWC; pWC=pWC->pOuter){
+      for(pTerm=pWC->a, k=pWC->nTerm; k; k--, pTerm++){
+        if( pTerm->leftCursor==iCur
+          && pTerm->u.leftColumn==iColumn
+        ){
+          if( (pTerm->prereqRight & notReady)==0
+           && (pTerm->eOperator & op & WO_ALL)!=0
+          ){
+            if( iOrigCol>=0 && pIdx && (pTerm->eOperator & WO_ISNULL)==0 ){
+              CollSeq *pColl;
+              char idxaff;
+      
+              pX = pTerm->pExpr;
+              pParse = pWC->pParse;
+              idxaff = pIdx->pTable->aCol[iOrigCol].affinity;
+              if( !sqlite3IndexAffinityOk(pX, idxaff) ){
+                continue;
+              }
+      
+              /* Figure out the collation sequence required from an index for
+              ** it to be useful for optimising expression pX. Store this
+              ** value in variable pColl.
+              */
+              assert(pX->pLeft);
+              pColl = sqlite3BinaryCompareCollSeq(pParse,pX->pLeft,pX->pRight);
+              if( pColl==0 ) pColl = pParse->db->pDfltColl;
+      
+              for(j=0; pIdx->aiColumn[j]!=iOrigCol; j++){
+                if( NEVER(j>=pIdx->nColumn) ) return 0;
+              }
+              if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ){
+                continue;
+              }
+            }
+            if( pTerm->prereqRight==0 ){
+              pResult = pTerm;
+              goto findTerm_success;
+            }else if( pResult==0 ){
+              pResult = pTerm;
+            }
+          }
+          if( (pTerm->eOperator & WO_EQUIV)!=0
+           && nEquiv<ArraySize(aEquiv)
+          ){
+            pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight);
+            assert( pX->op==TK_COLUMN );
+            for(j=0; j<nEquiv; j+=2){
+              if( aEquiv[j]==pX->iTable && aEquiv[j+1]==pX->iColumn ) break;
+            }
+            if( j==nEquiv ){
+              aEquiv[j] = pX->iTable;
+              aEquiv[j+1] = pX->iColumn;
+              nEquiv += 2;
+            }
           }
-          if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue;
         }
-        return pTerm;
       }
     }
+    if( iEquiv>=nEquiv ) break;
+    iCur = aEquiv[iEquiv++];
+    iColumn = aEquiv[iEquiv++];
   }
-  return 0;
+findTerm_success:
+  return pResult;
 }
 
 /* Forward reference */
@@ -103319,7 +103870,7 @@ static void transferJoinMarkings(Expr *pDerived, Expr *pBase){
 **
 ** CASE 1:
 **
-** If all subterms are of the form T.C=expr for some single column of C
+** If all subterms are of the form T.C=expr for some single column of C and
 ** a single table T (as shown in example B above) then create a new virtual
 ** term that is an equivalent IN expression.  In other words, if the term
 ** being analyzed is:
@@ -103407,11 +103958,10 @@ static void exprAnalyzeOrTerm(
   ** Compute the set of tables that might satisfy cases 1 or 2.
   */
   indexable = ~(Bitmask)0;
-  chngToIN = ~(pWC->vmask);
+  chngToIN = ~(Bitmask)0;
   for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){
     if( (pOrTerm->eOperator & WO_SINGLE)==0 ){
       WhereAndInfo *pAndInfo;
-      assert( pOrTerm->eOperator==0 );
       assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 );
       chngToIN = 0;
       pAndInfo = sqlite3DbMallocRaw(db, sizeof(*pAndInfo));
@@ -103450,7 +104000,7 @@ static void exprAnalyzeOrTerm(
         b |= getMask(pMaskSet, pOther->leftCursor);
       }
       indexable &= b;
-      if( pOrTerm->eOperator!=WO_EQ ){
+      if( (pOrTerm->eOperator & WO_EQ)==0 ){
         chngToIN = 0;
       }else{
         chngToIN &= b;
@@ -103501,7 +104051,7 @@ static void exprAnalyzeOrTerm(
     for(j=0; j<2 && !okToChngToIN; j++){
       pOrTerm = pOrWc->a;
       for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){
-        assert( pOrTerm->eOperator==WO_EQ );
+        assert( pOrTerm->eOperator & WO_EQ );
         pOrTerm->wtFlags &= ~TERM_OR_OK;
         if( pOrTerm->leftCursor==iCursor ){
           /* This is the 2-bit case and we are on the second iteration and
@@ -103527,7 +104077,7 @@ static void exprAnalyzeOrTerm(
         /* No candidate table+column was found.  This can only occur
         ** on the second iteration */
         assert( j==1 );
-        assert( (chngToIN&(chngToIN-1))==0 );
+        assert( IsPowerOfTwo(chngToIN) );
         assert( chngToIN==getMask(pMaskSet, iCursor) );
         break;
       }
@@ -103537,7 +104087,7 @@ static void exprAnalyzeOrTerm(
       ** table and column is common to every term in the OR clause */
       okToChngToIN = 1;
       for(; i>=0 && okToChngToIN; i--, pOrTerm++){
-        assert( pOrTerm->eOperator==WO_EQ );
+        assert( pOrTerm->eOperator & WO_EQ );
         if( pOrTerm->leftCursor!=iCursor ){
           pOrTerm->wtFlags &= ~TERM_OR_OK;
         }else if( pOrTerm->u.leftColumn!=iColumn ){
@@ -103573,7 +104123,7 @@ static void exprAnalyzeOrTerm(
 
       for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){
         if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue;
-        assert( pOrTerm->eOperator==WO_EQ );
+        assert( pOrTerm->eOperator & WO_EQ );
         assert( pOrTerm->leftCursor==iCursor );
         assert( pOrTerm->u.leftColumn==iColumn );
         pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
@@ -103603,7 +104153,6 @@ static void exprAnalyzeOrTerm(
 }
 #endif /* !SQLITE_OMIT_OR_OPTIMIZATION && !SQLITE_OMIT_SUBQUERY */
 
-
 /*
 ** The input to this routine is an WhereTerm structure with only the
 ** "pExpr" field filled in.  The job of this routine is to analyze the
@@ -103672,17 +104221,19 @@ static void exprAnalyze(
   pTerm->leftCursor = -1;
   pTerm->iParent = -1;
   pTerm->eOperator = 0;
-  if( allowedOp(op) && (pTerm->prereqRight & prereqLeft)==0 ){
+  if( allowedOp(op) ){
     Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft);
     Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
+    u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV;
     if( pLeft->op==TK_COLUMN ){
       pTerm->leftCursor = pLeft->iTable;
       pTerm->u.leftColumn = pLeft->iColumn;
-      pTerm->eOperator = operatorMask(op);
+      pTerm->eOperator = operatorMask(op) & opMask;
     }
     if( pRight && pRight->op==TK_COLUMN ){
       WhereTerm *pNew;
       Expr *pDup;
+      u16 eExtraOp = 0;        /* Extra bits for pNew->eOperator */
       if( pTerm->leftCursor>=0 ){
         int idxNew;
         pDup = sqlite3ExprDup(db, pExpr, 0);
@@ -103697,6 +104248,13 @@ static void exprAnalyze(
         pTerm = &pWC->a[idxTerm];
         pTerm->nChild = 1;
         pTerm->wtFlags |= TERM_COPIED;
+        if( pExpr->op==TK_EQ
+         && !ExprHasProperty(pExpr, EP_FromJoin)
+         && OptimizationEnabled(db, SQLITE_Transitive)
+        ){
+          pTerm->eOperator |= WO_EQUIV;
+          eExtraOp = WO_EQUIV;
+        }
       }else{
         pDup = pExpr;
         pNew = pTerm;
@@ -103708,7 +104266,7 @@ static void exprAnalyze(
       testcase( (prereqLeft | extraRight) != prereqLeft );
       pNew->prereqRight = prereqLeft | extraRight;
       pNew->prereqAll = prereqAll;
-      pNew->eOperator = operatorMask(pDup->op);
+      pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask;
     }
   }
 
@@ -104167,7 +104725,7 @@ static void bestOrClauseIndex(WhereBestIdx *p){
 
   /* Search the WHERE clause terms for a usable WO_OR term. */
   for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
-    if( pTerm->eOperator==WO_OR 
+    if( (pTerm->eOperator & WO_OR)!=0
      && ((pTerm->prereqAll & ~maskSrc) & p->notReady)==0
      && (pTerm->u.pOrInfo->indexable & maskSrc)!=0 
     ){
@@ -104188,7 +104746,7 @@ static void bestOrClauseIndex(WhereBestIdx *p){
         WHERETRACE(("... Multi-index OR testing for term %d of %d....\n", 
           (pOrTerm - pOrWC->a), (pTerm - pWC->a)
         ));
-        if( pOrTerm->eOperator==WO_AND ){
+        if( (pOrTerm->eOperator& WO_AND)!=0 ){
           sBOI.pWC = &pOrTerm->u.pAndInfo->wc;
           bestIndex(&sBOI);
         }else if( pOrTerm->leftCursor==iCur ){
@@ -104249,7 +104807,7 @@ static int termCanDriveIndex(
 ){
   char aff;
   if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
-  if( pTerm->eOperator!=WO_EQ ) return 0;
+  if( (pTerm->eOperator & WO_EQ)==0 ) return 0;
   if( (pTerm->prereqRight & notReady)!=0 ) return 0;
   aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity;
   if( !sqlite3IndexAffinityOk(pTerm->pExpr, aff) ) return 0;
@@ -104511,10 +105069,10 @@ static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
   ** to this virtual table */
   for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
     if( pTerm->leftCursor != pSrc->iCursor ) continue;
-    assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
-    testcase( pTerm->eOperator==WO_IN );
-    testcase( pTerm->eOperator==WO_ISNULL );
-    if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
+    assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
+    testcase( pTerm->eOperator & WO_IN );
+    testcase( pTerm->eOperator & WO_ISNULL );
+    if( pTerm->eOperator & (WO_ISNULL) ) continue;
     if( pTerm->wtFlags & TERM_VNULL ) continue;
     nTerm++;
   }
@@ -104562,15 +105120,18 @@ static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
                                                                    pUsage;
 
   for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
+    u8 op;
     if( pTerm->leftCursor != pSrc->iCursor ) continue;
-    assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
-    testcase( pTerm->eOperator==WO_IN );
-    testcase( pTerm->eOperator==WO_ISNULL );
-    if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
+    assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) );
+    testcase( pTerm->eOperator & WO_IN );
+    testcase( pTerm->eOperator & WO_ISNULL );
+    if( pTerm->eOperator & (WO_ISNULL) ) continue;
     if( pTerm->wtFlags & TERM_VNULL ) continue;
     pIdxCons[j].iColumn = pTerm->u.leftColumn;
     pIdxCons[j].iTermOffset = i;
-    pIdxCons[j].op = (u8)pTerm->eOperator;
+    op = (u8)pTerm->eOperator & WO_ALL;
+    if( op==WO_IN ) op = WO_EQ;
+    pIdxCons[j].op = op;
     /* The direct assignment in the previous line is possible only because
     ** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical.  The
     ** following asserts verify this fact. */
@@ -104580,7 +105141,7 @@ static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
     assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
     assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
     assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH );
-    assert( pTerm->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
+    assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
     j++;
   }
   for(i=0; i<nOrderBy; i++){
@@ -104664,8 +105225,10 @@ static void bestVirtualIndex(WhereBestIdx *p){
   struct sqlite3_index_constraint *pIdxCons;
   struct sqlite3_index_constraint_usage *pUsage;
   WhereTerm *pTerm;
-  int i, j;
+  int i, j, k;
   int nOrderBy;
+  int sortOrder;                  /* Sort order for IN clauses */
+  int bAllowIN;                   /* Allow IN optimizations */
   double rCost;
 
   /* Make sure wsFlags is initialized to some sane value. Otherwise, if the 
@@ -104700,59 +105263,96 @@ static void bestVirtualIndex(WhereBestIdx *p){
   assert( pTab->azModuleArg && pTab->azModuleArg[0] );
   assert( sqlite3GetVTable(pParse->db, pTab) );
 
-  /* Set the aConstraint[].usable fields and initialize all 
-  ** output variables to zero.
-  **
-  ** aConstraint[].usable is true for constraints where the right-hand
-  ** side contains only references to tables to the left of the current
-  ** table.  In other words, if the constraint is of the form:
-  **
-  **           column = expr
-  **
-  ** and we are evaluating a join, then the constraint on column is 
-  ** only valid if all tables referenced in expr occur to the left
-  ** of the table containing column.
-  **
-  ** The aConstraints[] array contains entries for all constraints
-  ** on the current table.  That way we only have to compute it once
-  ** even though we might try to pick the best index multiple times.
-  ** For each attempt at picking an index, the order of tables in the
-  ** join might be different so we have to recompute the usable flag
-  ** each time.
-  */
-  pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
-  pUsage = pIdxInfo->aConstraintUsage;
-  for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
-    j = pIdxCons->iTermOffset;
-    pTerm = &pWC->a[j];
-    pIdxCons->usable = (pTerm->prereqRight&p->notReady) ? 0 : 1;
-  }
-  memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
-  if( pIdxInfo->needToFreeIdxStr ){
-    sqlite3_free(pIdxInfo->idxStr);
-  }
-  pIdxInfo->idxStr = 0;
-  pIdxInfo->idxNum = 0;
-  pIdxInfo->needToFreeIdxStr = 0;
-  pIdxInfo->orderByConsumed = 0;
-  /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */
-  pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2);
-  nOrderBy = pIdxInfo->nOrderBy;
-  if( !p->pOrderBy ){
-    pIdxInfo->nOrderBy = 0;
-  }
-
-  if( vtabBestIndex(pParse, pTab, pIdxInfo) ){
-    return;
-  }
+  /* Try once or twice.  On the first attempt, allow IN optimizations.
+  ** If an IN optimization is accepted by the virtual table xBestIndex
+  ** method, but the  pInfo->aConstrainUsage.omit flag is not set, then
+  ** the query will not work because it might allow duplicate rows in
+  ** output.  In that case, run the xBestIndex method a second time
+  ** without the IN constraints.  Usually this loop only runs once.
+  ** The loop will exit using a "break" statement.
+  */
+  for(bAllowIN=1; 1; bAllowIN--){
+    assert( bAllowIN==0 || bAllowIN==1 );
 
-  pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
-  for(i=0; i<pIdxInfo->nConstraint; i++){
-    if( pUsage[i].argvIndex>0 ){
-      p->cost.used |= pWC->a[pIdxCons[i].iTermOffset].prereqRight;
+    /* Set the aConstraint[].usable fields and initialize all 
+    ** output variables to zero.
+    **
+    ** aConstraint[].usable is true for constraints where the right-hand
+    ** side contains only references to tables to the left of the current
+    ** table.  In other words, if the constraint is of the form:
+    **
+    **           column = expr
+    **
+    ** and we are evaluating a join, then the constraint on column is 
+    ** only valid if all tables referenced in expr occur to the left
+    ** of the table containing column.
+    **
+    ** The aConstraints[] array contains entries for all constraints
+    ** on the current table.  That way we only have to compute it once
+    ** even though we might try to pick the best index multiple times.
+    ** For each attempt at picking an index, the order of tables in the
+    ** join might be different so we have to recompute the usable flag
+    ** each time.
+    */
+    pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
+    pUsage = pIdxInfo->aConstraintUsage;
+    for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
+      j = pIdxCons->iTermOffset;
+      pTerm = &pWC->a[j];
+      if( (pTerm->prereqRight&p->notReady)==0
+       && (bAllowIN || (pTerm->eOperator & WO_IN)==0)
+      ){
+        pIdxCons->usable = 1;
+      }else{
+        pIdxCons->usable = 0;
+      }
+    }
+    memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
+    if( pIdxInfo->needToFreeIdxStr ){
+      sqlite3_free(pIdxInfo->idxStr);
+    }
+    pIdxInfo->idxStr = 0;
+    pIdxInfo->idxNum = 0;
+    pIdxInfo->needToFreeIdxStr = 0;
+    pIdxInfo->orderByConsumed = 0;
+    /* ((double)2) In case of SQLITE_OMIT_FLOATING_POINT... */
+    pIdxInfo->estimatedCost = SQLITE_BIG_DBL / ((double)2);
+    nOrderBy = pIdxInfo->nOrderBy;
+    if( !p->pOrderBy ){
+      pIdxInfo->nOrderBy = 0;
     }
+  
+    if( vtabBestIndex(pParse, pTab, pIdxInfo) ){
+      return;
+    }
+  
+    sortOrder = SQLITE_SO_ASC;
+    pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
+    for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
+      if( pUsage[i].argvIndex>0 ){
+        j = pIdxCons->iTermOffset;
+        pTerm = &pWC->a[j];
+        p->cost.used |= pTerm->prereqRight;
+        if( (pTerm->eOperator & WO_IN)!=0 ){
+          if( pUsage[i].omit==0 ){
+            /* Do not attempt to use an IN constraint if the virtual table
+            ** says that the equivalent EQ constraint cannot be safely omitted.
+            ** If we do attempt to use such a constraint, some rows might be
+            ** repeated in the output. */
+            break;
+          }
+          for(k=0; k<pIdxInfo->nOrderBy; k++){
+            if( pIdxInfo->aOrderBy[k].iColumn==pIdxCons->iColumn ){
+              sortOrder = pIdxInfo->aOrderBy[k].desc;
+              break;
+            }
+          }
+        }
+      }
+    }
+    if( i>=pIdxInfo->nConstraint ) break;
   }
-
+  
   /* If there is an ORDER BY clause, and the selected virtual table index
   ** does not satisfy it, increase the cost of the scan accordingly. This
   ** matches the processing for non-virtual tables in bestBtreeIndex().
@@ -104776,7 +105376,8 @@ static void bestVirtualIndex(WhereBestIdx *p){
   }
   p->cost.plan.u.pVtabIdx = pIdxInfo;
   if( pIdxInfo->orderByConsumed ){
-    p->cost.plan.wsFlags |= WHERE_ORDERED;
+    assert( sortOrder==0 || sortOrder==1 );
+    p->cost.plan.wsFlags |= WHERE_ORDERED + sortOrder*WHERE_REVERSE;
     p->cost.plan.nOBSat = nOrderBy;
   }else{
     p->cost.plan.nOBSat = p->i ? p->aLevel[p->i-1].plan.nOBSat : 0;
@@ -105047,24 +105648,24 @@ static int whereRangeScanEst(
     if( pLower ){
       Expr *pExpr = pLower->pExpr->pRight;
       rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal);
-      assert( pLower->eOperator==WO_GT || pLower->eOperator==WO_GE );
+      assert( (pLower->eOperator & (WO_GT|WO_GE))!=0 );
       if( rc==SQLITE_OK
        && whereKeyStats(pParse, p, pRangeVal, 0, a)==SQLITE_OK
       ){
         iLower = a[0];
-        if( pLower->eOperator==WO_GT ) iLower += a[1];
+        if( (pLower->eOperator & WO_GT)!=0 ) iLower += a[1];
       }
       sqlite3ValueFree(pRangeVal);
     }
     if( rc==SQLITE_OK && pUpper ){
       Expr *pExpr = pUpper->pExpr->pRight;
       rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal);
-      assert( pUpper->eOperator==WO_LT || pUpper->eOperator==WO_LE );
+      assert( (pUpper->eOperator & (WO_LT|WO_LE))!=0 );
       if( rc==SQLITE_OK
        && whereKeyStats(pParse, p, pRangeVal, 1, a)==SQLITE_OK
       ){
         iUpper = a[0];
-        if( pUpper->eOperator==WO_LE ) iUpper += a[1];
+        if( (pUpper->eOperator & WO_LE)!=0 ) iUpper += a[1];
       }
       sqlite3ValueFree(pRangeVal);
     }
@@ -105254,7 +105855,8 @@ static int isSortingIndex(
   WhereBestIdx *p,    /* Best index search context */
   Index *pIdx,        /* The index we are testing */
   int base,           /* Cursor number for the table to be sorted */
-  int *pbRev          /* Set to 1 for reverse-order scan of pIdx */
+  int *pbRev,         /* Set to 1 for reverse-order scan of pIdx */
+  int *pbObUnique     /* ORDER BY column values will different in every row */
 ){
   int i;                        /* Number of pIdx terms used */
   int j;                        /* Number of ORDER BY terms satisfied */
@@ -105268,12 +105870,16 @@ static int isSortingIndex(
   int nPriorSat;                /* ORDER BY terms satisfied by outer loops */
   int seenRowid = 0;            /* True if an ORDER BY rowid term is seen */
   int uniqueNotNull;            /* pIdx is UNIQUE with all terms are NOT NULL */
+  int outerObUnique;            /* Outer loops generate different values in
+                                ** every row for the ORDER BY columns */
 
   if( p->i==0 ){
     nPriorSat = 0;
+    outerObUnique = 1;
   }else{
+    u32 wsFlags = p->aLevel[p->i-1].plan.wsFlags;
     nPriorSat = p->aLevel[p->i-1].plan.nOBSat;
-    if( (p->aLevel[p->i-1].plan.wsFlags & WHERE_ORDERED)==0 ){
+    if( (wsFlags & WHERE_ORDERED)==0 ){
       /* This loop cannot be ordered unless the next outer loop is
       ** also ordered */
       return nPriorSat;
@@ -105283,6 +105889,9 @@ static int isSortingIndex(
       ** optimization is disabled */
       return nPriorSat;
     }
+    testcase( wsFlags & WHERE_OB_UNIQUE );
+    testcase( wsFlags & WHERE_ALL_UNIQUE );
+    outerObUnique = (wsFlags & (WHERE_OB_UNIQUE|WHERE_ALL_UNIQUE))!=0;
   }
   pOrderBy = p->pOrderBy;
   assert( pOrderBy!=0 );
@@ -105372,12 +105981,9 @@ static int isSortingIndex(
                            WO_EQ|WO_ISNULL|WO_IN, pIdx);
     if( pConstraint==0 ){
       isEq = 0;
-    }else if( pConstraint->eOperator==WO_IN ){
-      /* Constraints of the form: "X IN ..." cannot be used with an ORDER BY
-      ** because we do not know in what order the values on the RHS of the IN
-      ** operator will occur. */
-      break;
-    }else if( pConstraint->eOperator==WO_ISNULL ){
+    }else if( (pConstraint->eOperator & WO_IN)!=0 ){
+      isEq = 0;
+    }else if( (pConstraint->eOperator & WO_ISNULL)!=0 ){
       uniqueNotNull = 0;
       isEq = 1;  /* "X IS NULL" means X has only a single value */
     }else if( pConstraint->prereqRight==0 ){
@@ -105427,11 +106033,26 @@ static int isSortingIndex(
       uniqueNotNull = 0;
     }
   }
+  if( seenRowid ){
+    uniqueNotNull = 1;
+  }else if( uniqueNotNull==0 || i<pIdx->nColumn ){
+    uniqueNotNull = 0;
+  }
 
   /* If we have not found at least one ORDER BY term that matches the
   ** index, then show no progress. */
   if( pOBItem==&pOrderBy->a[nPriorSat] ) return nPriorSat;
 
+  /* Either the outer queries must generate rows where there are no two
+  ** rows with the same values in all ORDER BY columns, or else this
+  ** loop must generate just a single row of output.  Example:  Suppose
+  ** the outer loops generate A=1 and A=1, and this loop generates B=3
+  ** and B=4.  Then without the following test, ORDER BY A,B would 
+  ** generate the wrong order output: 1,3 1,4 1,3 1,4
+  */
+  if( outerObUnique==0 && uniqueNotNull==0 ) return nPriorSat;
+  *pbObUnique = uniqueNotNull;
+
   /* Return the necessary scan order back to the caller */
   *pbRev = sortOrder & 1;
 
@@ -105439,7 +106060,7 @@ static int isSortingIndex(
   ** possible for a single row from this table to match, then skip over
   ** any additional ORDER BY terms dealing with this table.
   */
-  if( seenRowid || (uniqueNotNull && i>=pIdx->nColumn) ){
+  if( uniqueNotNull ){
     /* Advance j over additional ORDER BY terms associated with base */
     WhereMaskSet *pMS = p->pWC->pMaskSet;
     Bitmask m = ~getMask(pMS, base);
@@ -105680,8 +106301,8 @@ static void bestBtreeIndex(WhereBestIdx *p){
     ** indicate this to the caller.
     **
     ** Otherwise, if the search may find more than one row, test to see if
-    ** there is a range constraint on indexed column (pc.plan.nEq+1) that can be 
-    ** optimized using the index. 
+    ** there is a range constraint on indexed column (pc.plan.nEq+1) that
+    ** can be optimized using the index. 
     */
     if( pc.plan.nEq==pProbe->nColumn && pProbe->onError!=OE_None ){
       testcase( pc.plan.wsFlags & WHERE_COLUMN_IN );
@@ -105723,12 +106344,14 @@ static void bestBtreeIndex(WhereBestIdx *p){
     ** variable.  */
     if( bSort && (pSrc->jointype & JT_LEFT)==0 ){
       int bRev = 2;
-      WHERETRACE(("      --> before isSortingIndex: nPriorSat=%d\n",nPriorSat));
-      pc.plan.nOBSat = isSortingIndex(p, pProbe, iCur, &bRev);
-      WHERETRACE(("      --> after  isSortingIndex: bRev=%d nOBSat=%d\n",
-                  bRev, pc.plan.nOBSat));
+      int bObUnique = 0;
+      WHERETRACE(("      --> before isSortIndex: nPriorSat=%d\n",nPriorSat));
+      pc.plan.nOBSat = isSortingIndex(p, pProbe, iCur, &bRev, &bObUnique);
+      WHERETRACE(("      --> after  isSortIndex: bRev=%d bObU=%d nOBSat=%d\n",
+                  bRev, bObUnique, pc.plan.nOBSat));
       if( nPriorSat<pc.plan.nOBSat || (pc.plan.wsFlags & WHERE_ALL_UNIQUE)!=0 ){
         pc.plan.wsFlags |= WHERE_ORDERED;
+        if( bObUnique ) pc.plan.wsFlags |= WHERE_OB_UNIQUE;
       }
       if( nOrderBy==pc.plan.nOBSat ){
         bSort = 0;
@@ -105790,12 +106413,13 @@ static void bestBtreeIndex(WhereBestIdx *p){
      && pFirstTerm!=0 && aiRowEst[1]>1 ){
       assert( (pFirstTerm->eOperator & (WO_EQ|WO_ISNULL|WO_IN))!=0 );
       if( pFirstTerm->eOperator & (WO_EQ|WO_ISNULL) ){
-        testcase( pFirstTerm->eOperator==WO_EQ );
-        testcase( pFirstTerm->eOperator==WO_ISNULL );
+        testcase( pFirstTerm->eOperator & WO_EQ );
+        testcase( pFirstTerm->eOperator & WO_EQUIV );
+        testcase( pFirstTerm->eOperator & WO_ISNULL );
         whereEqualScanEst(pParse, pProbe, pFirstTerm->pExpr->pRight,
                           &pc.plan.nRow);
       }else if( bInEst==0 ){
-        assert( pFirstTerm->eOperator==WO_IN );
+        assert( pFirstTerm->eOperator & WO_IN );
         whereInScanEst(pParse, pProbe, pFirstTerm->pExpr->x.pList,
                        &pc.plan.nRow);
       }
@@ -105821,7 +106445,8 @@ static void bestBtreeIndex(WhereBestIdx *p){
     ** So this computation assumes table records are about twice as big
     ** as index records
     */
-    if( (pc.plan.wsFlags&~(WHERE_REVERSE|WHERE_ORDERED))==WHERE_IDX_ONLY
+    if( (pc.plan.wsFlags&~(WHERE_REVERSE|WHERE_ORDERED|WHERE_OB_UNIQUE))
+                                                              ==WHERE_IDX_ONLY
      && (pWC->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
      && sqlite3GlobalConfig.bUseCis
      && OptimizationEnabled(pParse->db, SQLITE_CoverIdxScan)
@@ -105942,7 +106567,7 @@ static void bestBtreeIndex(WhereBestIdx *p){
             ** selective in practice, on average. */
             pc.plan.nRow /= 3;
           }
-        }else if( pTerm->eOperator!=WO_NOOP ){
+        }else if( (pTerm->eOperator & WO_NOOP)==0 ){
           /* Any other expression lowers the output row count by half */
           pc.plan.nRow /= 2;
         }
@@ -105981,7 +106606,7 @@ static void bestBtreeIndex(WhereBestIdx *p){
   /* If there is no ORDER BY clause and the SQLITE_ReverseOrder flag
   ** is set, then reverse the order that the index will be scanned
   ** in. This is used for application testing, to help find cases
-  ** where application behaviour depends on the (undefined) order that
+  ** where application behavior depends on the (undefined) order that
   ** SQLite outputs rows in in the absence of an ORDER BY clause.  */
   if( !p->pOrderBy && pParse->db->flags & SQLITE_ReverseOrder ){
     p->cost.plan.wsFlags |= WHERE_REVERSE;
@@ -105994,8 +106619,9 @@ static void bestBtreeIndex(WhereBestIdx *p){
        || p->cost.plan.u.pIdx==pSrc->pIndex 
   );
 
-  WHERETRACE(("   best index is: %s\n",
-         p->cost.plan.u.pIdx ? p->cost.plan.u.pIdx->zName : "ipk"));
+  WHERETRACE(("   best index is %s cost=%.1f\n",
+         p->cost.plan.u.pIdx ? p->cost.plan.u.pIdx->zName : "ipk",
+         p->cost.rCost));
   
   bestOrClauseIndex(p);
   bestAutomaticIndex(p);
@@ -106020,7 +106646,8 @@ static void bestIndex(WhereBestIdx *p){
     sqlite3_index_info *pIdxInfo = 0;
     p->ppIdxInfo = &pIdxInfo;
     bestVirtualIndex(p);
-    if( pIdxInfo->needToFreeIdxStr ){
+    assert( pIdxInfo!=0 || p->pParse->db->mallocFailed );
+    if( pIdxInfo && pIdxInfo->needToFreeIdxStr ){
       sqlite3_free(pIdxInfo->idxStr);
     }
     sqlite3DbFree(p->pParse->db, pIdxInfo);
@@ -106126,7 +106753,8 @@ static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){
 static int codeEqualityTerm(
   Parse *pParse,      /* The parsing context */
   WhereTerm *pTerm,   /* The term of the WHERE clause to be coded */
-  WhereLevel *pLevel, /* When level of the FROM clause we are working on */
+  WhereLevel *pLevel, /* The level of the FROM clause we are working on */
+  int iEq,            /* Index of the equality term within this level */
   int iTarget         /* Attempt to leave results in this register */
 ){
   Expr *pX = pTerm->pExpr;
@@ -106144,12 +106772,26 @@ static int codeEqualityTerm(
     int eType;
     int iTab;
     struct InLoop *pIn;
+    u8 bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0;
 
+    if( (pLevel->plan.wsFlags & WHERE_INDEXED)!=0 
+      && pLevel->plan.u.pIdx->aSortOrder[iEq]
+    ){
+      testcase( iEq==0 );
+      testcase( iEq==pLevel->plan.u.pIdx->nColumn-1 );
+      testcase( iEq>0 && iEq+1<pLevel->plan.u.pIdx->nColumn );
+      testcase( bRev );
+      bRev = !bRev;
+    }
     assert( pX->op==TK_IN );
     iReg = iTarget;
     eType = sqlite3FindInIndex(pParse, pX, 0);
+    if( eType==IN_INDEX_INDEX_DESC ){
+      testcase( bRev );
+      bRev = !bRev;
+    }
     iTab = pX->iTable;
-    sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
+    sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
     assert( pLevel->plan.wsFlags & WHERE_IN_ABLE );
     if( pLevel->u.in.nIn==0 ){
       pLevel->addrNxt = sqlite3VdbeMakeLabel(v);
@@ -106167,6 +106809,7 @@ static int codeEqualityTerm(
       }else{
         pIn->addrInTop = sqlite3VdbeAddOp3(v, OP_Column, iTab, 0, iReg);
       }
+      pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
       sqlite3VdbeAddOp1(v, OP_IsNull, iReg);
     }else{
       pLevel->u.in.nIn = 0;
@@ -106261,7 +106904,7 @@ static int codeAllEqualityTerms(
     ** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */
     testcase( (pTerm->wtFlags & TERM_CODED)!=0 );
     testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
-    r1 = codeEqualityTerm(pParse, pTerm, pLevel, regBase+j);
+    r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, regBase+j);
     if( r1!=regBase+j ){
       if( nReg==1 ){
         sqlite3ReleaseTempReg(pParse, regBase);
@@ -106521,6 +107164,7 @@ static Bitmask codeOneLoopStart(
     **          to access the data.
     */
     int iReg;   /* P3 Value for OP_VFilter */
+    int addrNotFound;
     sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx;
     int nConstraint = pVtabIdx->nConstraint;
     struct sqlite3_index_constraint_usage *aUsage =
@@ -106530,11 +107174,18 @@ static Bitmask codeOneLoopStart(
 
     sqlite3ExprCachePush(pParse);
     iReg = sqlite3GetTempRange(pParse, nConstraint+2);
+    addrNotFound = pLevel->addrBrk;
     for(j=1; j<=nConstraint; j++){
       for(k=0; k<nConstraint; k++){
         if( aUsage[k].argvIndex==j ){
-          int iTerm = aConstraint[k].iTermOffset;
-          sqlite3ExprCode(pParse, pWC->a[iTerm].pExpr->pRight, iReg+j+1);
+          int iTarget = iReg+j+1;
+          pTerm = &pWC->a[aConstraint[k].iTermOffset];
+          if( pTerm->eOperator & WO_IN ){
+            codeEqualityTerm(pParse, pTerm, pLevel, k, iTarget);
+            addrNotFound = pLevel->addrNxt;
+          }else{
+            sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget);
+          }
           break;
         }
       }
@@ -106542,7 +107193,7 @@ static Bitmask codeOneLoopStart(
     }
     sqlite3VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg);
     sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1);
-    sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrBrk, iReg, pVtabIdx->idxStr,
+    sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pVtabIdx->idxStr,
                       pVtabIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC);
     pVtabIdx->needToFreeIdxStr = 0;
     for(j=0; j<nConstraint; j++){
@@ -106569,13 +107220,13 @@ static Bitmask codeOneLoopStart(
     pTerm = findTerm(pWC, iCur, -1, notReady, WO_EQ|WO_IN, 0);
     assert( pTerm!=0 );
     assert( pTerm->pExpr!=0 );
-    assert( pTerm->leftCursor==iCur );
     assert( omitTable==0 );
     testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */
-    iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, iReleaseReg);
+    iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, iReleaseReg);
     addrNxt = pLevel->addrNxt;
     sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt);
     sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg);
+    sqlite3ExprCacheAffinityChange(pParse, iRowidReg, 1);
     sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
     VdbeComment((v, "pk"));
     pLevel->op = OP_Noop;
@@ -106960,7 +107611,7 @@ static Bitmask codeOneLoopStart(
    
     pTerm = pLevel->plan.u.pTerm;
     assert( pTerm!=0 );
-    assert( pTerm->eOperator==WO_OR );
+    assert( pTerm->eOperator & WO_OR );
     assert( (pTerm->wtFlags & TERM_ORINFO)!=0 );
     pOrWc = &pTerm->u.pOrInfo->wc;
     pLevel->op = OP_Return;
@@ -107033,7 +107684,7 @@ static Bitmask codeOneLoopStart(
 
     for(ii=0; ii<pOrWc->nTerm; ii++){
       WhereTerm *pOrTerm = &pOrWc->a[ii];
-      if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){
+      if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
         WhereInfo *pSubWInfo;          /* Info for single OR-term scan */
         Expr *pOrExpr = pOrTerm->pExpr;
         if( pAndExpr ){
@@ -107411,24 +108062,13 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
   ** bitmask for all tables to the left of the join.  Knowing the bitmask
   ** for all tables to the left of a left join is important.  Ticket #3015.
   **
-  ** Configure the WhereClause.vmask variable so that bits that correspond
-  ** to virtual table cursors are set. This is used to selectively disable 
-  ** the OR-to-IN transformation in exprAnalyzeOrTerm(). It is not helpful 
-  ** with virtual tables.
-  **
   ** Note that bitmasks are created for all pTabList->nSrc tables in
   ** pTabList, not just the first nTabList tables.  nTabList is normally
   ** equal to pTabList->nSrc but might be shortened to 1 if the
   ** WHERE_ONETABLE_ONLY flag is set.
   */
-  assert( sWBI.pWC->vmask==0 && pMaskSet->n==0 );
   for(ii=0; ii<pTabList->nSrc; ii++){
     createMask(pMaskSet, pTabList->a[ii].iCursor);
-#ifndef SQLITE_OMIT_VIRTUALTABLE
-    if( ALWAYS(pTabList->a[ii].pTab) && IsVirtual(pTabList->a[ii].pTab) ){
-      sWBI.pWC->vmask |= ((Bitmask)1 << ii);
-    }
-#endif
   }
 #ifndef NDEBUG
   {
@@ -107488,6 +108128,7 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
     int bestJ = -1;             /* The value of j */
     Bitmask m;                  /* Bitmask value for j or bestJ */
     int isOptimal;              /* Iterator for optimal/non-optimal search */
+    int ckOptimal;              /* Do the optimal scan check */
     int nUnconstrained;         /* Number tables without INDEXED BY */
     Bitmask notIndexed;         /* Mask of tables that cannot use an index */
 
@@ -107522,10 +108163,8 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
     ** strategies were found by the first iteration. This second iteration
     ** is used to search for the lowest cost scan overall.
     **
-    ** Previous versions of SQLite performed only the second iteration -
-    ** the next outermost loop was always that with the lowest overall
-    ** cost. However, this meant that SQLite could select the wrong plan
-    ** for scripts such as the following:
+    ** Without the optimal scan step (the first iteration) a suboptimal
+    ** plan might be chosen for queries like this:
     **   
     **   CREATE TABLE t1(a, b); 
     **   CREATE TABLE t2(c, d);
@@ -107540,17 +108179,41 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
     */
     nUnconstrained = 0;
     notIndexed = 0;
-    for(isOptimal=(iFrom<nTabList-1); isOptimal>=0 && bestJ<0; isOptimal--){
+
+    /* The optimal scan check only occurs if there are two or more tables
+    ** available to be reordered */
+    if( iFrom==nTabList-1 ){
+      ckOptimal = 0;  /* Common case of just one table in the FROM clause */
+    }else{
+      ckOptimal = -1;
       for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; j<nTabList; j++, sWBI.pSrc++){
-        int doNotReorder;    /* True if this table should not be reordered */
-  
-        doNotReorder =  (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0;
-        if( j!=iFrom && doNotReorder ) break;
         m = getMask(pMaskSet, sWBI.pSrc->iCursor);
         if( (m & sWBI.notValid)==0 ){
           if( j==iFrom ) iFrom++;
           continue;
         }
+        if( j>iFrom && (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0 ) break;
+        if( ++ckOptimal ) break;
+        if( (sWBI.pSrc->jointype & JT_LEFT)!=0 ) break;
+      }
+    }
+    assert( ckOptimal==0 || ckOptimal==1 );
+
+    for(isOptimal=ckOptimal; isOptimal>=0 && bestJ<0; isOptimal--){
+      for(j=iFrom, sWBI.pSrc=&pTabList->a[j]; j<nTabList; j++, sWBI.pSrc++){
+        if( j>iFrom && (sWBI.pSrc->jointype & (JT_LEFT|JT_CROSS))!=0 ){
+          /* This break and one like it in the ckOptimal computation loop
+          ** above prevent table reordering across LEFT and CROSS JOINs.
+          ** The LEFT JOIN case is necessary for correctness.  The prohibition
+          ** against reordering across a CROSS JOIN is an SQLite feature that
+          ** allows the developer to control table reordering */
+          break;
+        }
+        m = getMask(pMaskSet, sWBI.pSrc->iCursor);
+        if( (m & sWBI.notValid)==0 ){
+          assert( j>iFrom );
+          continue;
+        }
         sWBI.notReady = (isOptimal ? m : sWBI.notValid);
         if( sWBI.pSrc->pIndex==0 ) nUnconstrained++;
   
@@ -107579,8 +108242,8 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
         }
         if( isOptimal ){
           pWInfo->a[j].rOptCost = sWBI.cost.rCost;
-        }else if( iFrom<nTabList-1 ){
-          /* If two or more tables have nearly the same outer loop cost,
+        }else if( ckOptimal ){
+          /* If two or more tables have nearly the same outer loop cost, but
           ** very different inner loop (optimal) cost, we want to choose
           ** for the outer loop that table which benefits the least from
           ** being in the inner loop.  The following code scales the 
@@ -107625,11 +108288,19 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
           bestPlan = sWBI.cost;
           bestJ = j;
         }
-        if( doNotReorder ) break;
+
+        /* In a join like "w JOIN x LEFT JOIN y JOIN z"  make sure that
+        ** table y (and not table z) is always the next inner loop inside
+        ** of table x. */
+        if( (sWBI.pSrc->jointype & JT_LEFT)!=0 ) break;
       }
     }
     assert( bestJ>=0 );
     assert( sWBI.notValid & getMask(pMaskSet, pTabList->a[bestJ].iCursor) );
+    assert( bestJ==iFrom || (pTabList->a[iFrom].jointype & JT_LEFT)==0 );
+    testcase( bestJ>iFrom && (pTabList->a[iFrom].jointype & JT_CROSS)!=0 );
+    testcase( bestJ>iFrom && bestJ<nTabList-1
+                          && (pTabList->a[bestJ+1].jointype & JT_LEFT)!=0 );
     WHERETRACE(("*** Optimizer selects table %d (%s) for loop %d with:\n"
                 "    cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=0x%08x\n",
                 bestJ, pTabList->a[bestJ].pTab->zName,
@@ -107881,7 +108552,7 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
       sqlite3VdbeResolveLabel(v, pLevel->addrNxt);
       for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){
         sqlite3VdbeJumpHere(v, pIn->addrInTop+1);
-        sqlite3VdbeAddOp2(v, OP_Next, pIn->iCur, pIn->addrInTop);
+        sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
         sqlite3VdbeJumpHere(v, pIn->addrInTop-1);
       }
       sqlite3DbFree(db, pLevel->u.in.aInLoop);
@@ -108189,6 +108860,7 @@ typedef union {
   IdList* yy180;
   struct {int value; int mask;} yy207;
   u8 yy258;
+  u16 yy305;
   struct LikeOp yy318;
   TriggerStep* yy327;
   ExprSpan yy342;
@@ -110139,8 +110811,6 @@ static void yy_reduce(
       case 86: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */ yytestcase(yyruleno==86);
       case 98: /* defer_subclause_opt ::= */ yytestcase(yyruleno==98);
       case 109: /* ifexists ::= */ yytestcase(yyruleno==109);
-      case 120: /* distinct ::= ALL */ yytestcase(yyruleno==120);
-      case 121: /* distinct ::= */ yytestcase(yyruleno==121);
       case 221: /* between_op ::= BETWEEN */ yytestcase(yyruleno==221);
       case 224: /* in_op ::= IN */ yytestcase(yyruleno==224);
 {yygotominor.yy392 = 0;}
@@ -110150,7 +110820,6 @@ static void yy_reduce(
       case 70: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==70);
       case 85: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */ yytestcase(yyruleno==85);
       case 108: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==108);
-      case 119: /* distinct ::= DISTINCT */ yytestcase(yyruleno==119);
       case 222: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==222);
       case 225: /* in_op ::= NOT IN */ yytestcase(yyruleno==225);
 {yygotominor.yy392 = 1;}
@@ -110390,9 +111059,16 @@ static void yy_reduce(
         break;
       case 118: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
 {
-  yygotominor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy392,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset);
+  yygotominor.yy159 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy442,yymsp[-5].minor.yy347,yymsp[-4].minor.yy122,yymsp[-3].minor.yy442,yymsp[-2].minor.yy122,yymsp[-1].minor.yy442,yymsp[-7].minor.yy305,yymsp[0].minor.yy64.pLimit,yymsp[0].minor.yy64.pOffset);
 }
         break;
+      case 119: /* distinct ::= DISTINCT */
+{yygotominor.yy305 = SF_Distinct;}
+        break;
+      case 120: /* distinct ::= ALL */
+      case 121: /* distinct ::= */ yytestcase(yyruleno==121);
+{yygotominor.yy305 = 0;}
+        break;
       case 122: /* sclp ::= selcollist COMMA */
       case 246: /* idxlist_opt ::= LP idxlist RP */ yytestcase(yyruleno==246);
 {yygotominor.yy442 = yymsp[-1].minor.yy442;}
@@ -110461,10 +111137,20 @@ static void yy_reduce(
 {
     if( yymsp[-6].minor.yy347==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy122==0 && yymsp[0].minor.yy180==0 ){
       yygotominor.yy347 = yymsp[-4].minor.yy347;
+    }else if( yymsp[-4].minor.yy347->nSrc==1 ){
+      yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
+      if( yygotominor.yy347 ){
+        struct SrcList_item *pNew = &yygotominor.yy347->a[yygotominor.yy347->nSrc-1];
+        struct SrcList_item *pOld = yymsp[-4].minor.yy347->a;
+        pNew->zName = pOld->zName;
+        pNew->zDatabase = pOld->zDatabase;
+        pOld->zName = pOld->zDatabase = 0;
+      }
+      sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy347);
     }else{
       Select *pSubquery;
       sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy347);
-      pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,0,0,0);
+      pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy347,0,0,0,0,SF_NestedFrom,0,0);
       yygotominor.yy347 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy347,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy122,yymsp[0].minor.yy180);
     }
   }
@@ -110697,7 +111383,7 @@ static void yy_reduce(
   }
   yygotominor.yy342.pExpr = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy442, &yymsp[-4].minor.yy0);
   spanSet(&yygotominor.yy342,&yymsp[-4].minor.yy0,&yymsp[0].minor.yy0);
-  if( yymsp[-2].minor.yy392 && yygotominor.yy342.pExpr ){
+  if( yymsp[-2].minor.yy305 && yygotominor.yy342.pExpr ){
     yygotominor.yy342.pExpr->flags |= EP_Distinct;
   }
 }
@@ -113515,7 +114201,7 @@ SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
 
   /* If we reach this point, it means that the database connection has
   ** closed all sqlite3_stmt and sqlite3_backup objects and has been
-  ** pased to sqlite3_close (meaning that it is a zombie).  Therefore,
+  ** passed to sqlite3_close (meaning that it is a zombie).  Therefore,
   ** go ahead and free all resources.
   */
 
@@ -113632,7 +114318,7 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){
   sqlite3VtabRollback(db);
   sqlite3EndBenignMalloc();
 
-  if( db->flags&SQLITE_InternChanges ){
+  if( (db->flags&SQLITE_InternChanges)!=0 && db->init.busy==0 ){
     sqlite3ExpirePreparedStatements(db);
     sqlite3ResetAllSchemasOfConnection(db);
   }
@@ -116567,7 +117253,7 @@ struct sqlite3_tokenizer_module {
   ** This method should return either SQLITE_OK (0), or an SQLite error 
   ** code. If SQLITE_OK is returned, then *ppTokenizer should be set
   ** to point at the newly created tokenizer structure. The generic
-  ** sqlite3_tokenizer.pModule variable should not be initialised by
+  ** sqlite3_tokenizer.pModule variable should not be initialized by
   ** this callback. The caller will do so.
   */
   int (*xCreate)(
@@ -116672,7 +117358,7 @@ int fts3_term_cnt(int iTerm, int iCol);
 **    May you share freely, never taking more than you give.
 **
 *************************************************************************
-** This is the header file for the generic hash-table implemenation
+** This is the header file for the generic hash-table implementation
 ** used in SQLite.  We've modified it slightly to serve as a standalone
 ** hash table implementation for the full-text indexing module.
 **
@@ -118579,7 +119265,7 @@ static int fts3CursorSeek(sqlite3_context *pContext, Fts3Cursor *pCsr){
       }else{
         rc = sqlite3_reset(pCsr->pStmt);
         if( rc==SQLITE_OK && ((Fts3Table *)pCsr->base.pVtab)->zContentTbl==0 ){
-          /* If no row was found and no error has occured, then the %_content
+          /* If no row was found and no error has occurred, then the %_content
           ** table is missing a row that is present in the full-text index.
           ** The data structures are corrupt.  */
           rc = FTS_CORRUPT_VTAB;
@@ -119819,7 +120505,7 @@ static void fts3SegReaderCursorFree(Fts3MultiSegReader *pSegcsr){
 }
 
 /*
-** This function retreives the doclist for the specified term (or term
+** This function retrieves the doclist for the specified term (or term
 ** prefix) from the database.
 */
 static int fts3TermSelect(
@@ -120570,7 +121256,7 @@ SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule(sqlite3_tokenizer_module const
 #endif
 
 /*
-** Initialise the fts3 extension. If this extension is built as part
+** Initialize the fts3 extension. If this extension is built as part
 ** of the sqlite library, then this function is called directly by
 ** SQLite. If fts3 is built as a dynamically loadable extension, this
 ** function is called by the sqlite3_extension_init() entry point.
@@ -120604,7 +121290,7 @@ SQLITE_PRIVATE int sqlite3Fts3Init(sqlite3 *db){
   sqlite3Fts3SimpleTokenizerModule(&pSimple);
   sqlite3Fts3PorterTokenizerModule(&pPorter);
 
-  /* Allocate and initialise the hash-table used to store tokenizers. */
+  /* Allocate and initialize the hash-table used to store tokenizers. */
   pHash = sqlite3_malloc(sizeof(Fts3Hash));
   if( !pHash ){
     rc = SQLITE_NOMEM;
@@ -122203,7 +122889,7 @@ SQLITE_PRIVATE int sqlite3Fts3EvalPhraseStats(
 ** of the current row. 
 **
 ** More specifically, the returned buffer contains 1 varint for each 
-** occurence of the phrase in the column, stored using the normal (delta+2) 
+** occurrence of the phrase in the column, stored using the normal (delta+2) 
 ** compression and is terminated by either an 0x01 or 0x00 byte. For example,
 ** if the requested column contains "a b X c d X X" and the position-list
 ** for 'X' is requested, the buffer returned may contain:
@@ -122942,7 +123628,7 @@ struct ParseContext {
 ** This function is equivalent to the standard isspace() function. 
 **
 ** The standard isspace() can be awkward to use safely, because although it
-** is defined to accept an argument of type int, its behaviour when passed
+** is defined to accept an argument of type int, its behavior when passed
 ** an integer that falls outside of the range of the unsigned char type
 ** is undefined (and sometimes, "undefined" means segfault). This wrapper
 ** is defined to accept an argument of type char, and always returns 0 for
@@ -125310,7 +125996,7 @@ static void intTestFunc(
 /*
 ** Set up SQL objects in database db used to access the contents of
 ** the hash table pointed to by argument pHash. The hash table must
-** been initialised to use string keys, and to take a private copy 
+** been initialized to use string keys, and to take a private copy 
 ** of the key when a value is inserted. i.e. by a call similar to:
 **
 **    sqlite3Fts3HashInit(pHash, FTS3_HASH_STRING, 1);
@@ -127089,6 +127775,7 @@ static int fts3SegReaderNextDocid(
       *pnOffsetList = (int)(p - pReader->pOffsetList - 1);
     }
 
+    /* List may have been edited in place by fts3EvalNearTrim() */
     while( p<pEnd && *p==0 ) p++;
   
     /* If there are no more entries in the doclist, set pOffsetList to
@@ -128104,9 +128791,13 @@ static int fts3DeleteSegdir(
 **
 ** If there are no entries in the input position list for column iCol, then
 ** *pnList is set to zero before returning.
+**
+** If parameter bZero is non-zero, then any part of the input list following
+** the end of the output list is zeroed before returning.
 */
 static void fts3ColumnFilter(
   int iCol,                       /* Column to filter on */
+  int bZero,                      /* Zero out anything following *ppList */
   char **ppList,                  /* IN/OUT: Pointer to position list */
   int *pnList                     /* IN/OUT: Size of buffer *ppList in bytes */
 ){
@@ -128135,6 +128826,9 @@ static void fts3ColumnFilter(
     p += sqlite3Fts3GetVarint32(p, &iCurrent);
   }
 
+  if( bZero && &pList[nList]!=pEnd ){
+    memset(&pList[nList], 0, pEnd - &pList[nList]);
+  }
   *ppList = pList;
   *pnList = nList;
 }
@@ -128208,19 +128902,19 @@ SQLITE_PRIVATE int sqlite3Fts3MsrIncrNext(
       if( rc!=SQLITE_OK ) return rc;
       fts3SegReaderSort(pMsr->apSegment, nMerge, j, xCmp);
 
+      if( nList>0 && fts3SegReaderIsPending(apSegment[0]) ){
+        rc = fts3MsrBufferData(pMsr, pList, nList+1);
+        if( rc!=SQLITE_OK ) return rc;
+        assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 );
+        pList = pMsr->aBuffer;
+      }
+
       if( pMsr->iColFilter>=0 ){
-        fts3ColumnFilter(pMsr->iColFilter, &pList, &nList);
+        fts3ColumnFilter(pMsr->iColFilter, 1, &pList, &nList);
       }
 
       if( nList>0 ){
-        if( fts3SegReaderIsPending(apSegment[0]) ){
-          rc = fts3MsrBufferData(pMsr, pList, nList+1);
-          if( rc!=SQLITE_OK ) return rc;
-          *paPoslist = pMsr->aBuffer;
-          assert( (pMsr->aBuffer[nList] & 0xFE)==0x00 );
-        }else{
-          *paPoslist = pList;
-        }
+        *paPoslist = pList;
         *piDocid = iDocid;
         *pnPoslist = nList;
         break;
@@ -128463,7 +129157,7 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderStep(
         }
 
         if( isColFilter ){
-          fts3ColumnFilter(pFilter->iCol, &pList, &nList);
+          fts3ColumnFilter(pFilter->iCol, 0, &pList, &nList);
         }
 
         if( !isIgnoreEmpty || nList>0 ){
@@ -131400,9 +132094,9 @@ static int fts3SnippetFindPositions(Fts3Expr *pExpr, int iPhrase, void *ctx){
 ** is the snippet with the highest score, where scores are calculated
 ** by adding:
 **
-**   (a) +1 point for each occurence of a matchable phrase in the snippet.
+**   (a) +1 point for each occurrence of a matchable phrase in the snippet.
 **
-**   (b) +1000 points for the first occurence of each matchable phrase in 
+**   (b) +1000 points for the first occurrence of each matchable phrase in 
 **       the snippet for which the corresponding mCovered bit is not set.
 **
 ** The selected snippet parameters are stored in structure *pFragment before
@@ -132657,7 +133351,7 @@ static int unicodeDestroy(sqlite3_tokenizer *pTokenizer){
 **
 ** If a standalone diacritic mark (one that sqlite3FtsUnicodeIsdiacritic()
 ** identifies as a diacritic) occurs in the zIn/nIn string it is ignored.
-** It is not possible to change the behaviour of the tokenizer with respect
+** It is not possible to change the behavior of the tokenizer with respect
 ** to these codepoints.
 */
 static int unicodeAddExceptions(
@@ -135960,7 +136654,7 @@ static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){
   RtreeNode *pRoot;               /* Root node of rtree structure */
 
 
-  /* Obtain a reference to the root node to initialise Rtree.iDepth */
+  /* Obtain a reference to the root node to initialize Rtree.iDepth */
   rc = nodeAcquire(pRtree, 1, 0, &pRoot);
 
   /* Obtain a reference to the leaf node that contains the entry 
@@ -136344,7 +137038,8 @@ static int getIntFromStmt(sqlite3 *db, const char *zSql, int *piVal){
 static int getNodeSize(
   sqlite3 *db,                    /* Database handle */
   Rtree *pRtree,                  /* Rtree handle */
-  int isCreate                    /* True for xCreate, false for xConnect */
+  int isCreate,                   /* True for xCreate, false for xConnect */
+  char **pzErr                    /* OUT: Error message, if any */
 ){
   int rc;
   char *zSql;
@@ -136357,6 +137052,8 @@ static int getNodeSize(
       if( (4+pRtree->nBytesPerCell*RTREE_MAXCELLS)<pRtree->iNodeSize ){
         pRtree->iNodeSize = 4+pRtree->nBytesPerCell*RTREE_MAXCELLS;
       }
+    }else{
+      *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
     }
   }else{
     zSql = sqlite3_mprintf(
@@ -136364,6 +137061,9 @@ static int getNodeSize(
         pRtree->zDb, pRtree->zName
     );
     rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize);
+    if( rc!=SQLITE_OK ){
+      *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
+    }
   }
 
   sqlite3_free(zSql);
@@ -136427,7 +137127,7 @@ static int rtreeInit(
   memcpy(pRtree->zName, argv[2], nName);
 
   /* Figure out the node size to use. */
-  rc = getNodeSize(db, pRtree, isCreate);
+  rc = getNodeSize(db, pRtree, isCreate, pzErr);
 
   /* Create/Connect to the underlying relational database schema. If
   ** that is successful, call sqlite3_declare_vtab() to configure
index 4f0ce8b1b617216d68f20eaa532e54d4fbf2c386..1332eb162895f03945e070c041cee71a8fccd1ae 100644 (file)
@@ -107,9 +107,9 @@ extern "C" {
 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
 ** [sqlite_version()] and [sqlite_source_id()].
 */
-#define SQLITE_VERSION        "3.7.15.2"
-#define SQLITE_VERSION_NUMBER 3007015
-#define SQLITE_SOURCE_ID      "2013-01-09 11:53:05 c0e09560d26f0a6456be9dd3447f5311eb4f238f"
+#define SQLITE_VERSION        "3.7.16.1"
+#define SQLITE_VERSION_NUMBER 3007016
+#define SQLITE_SOURCE_ID      "2013-03-29 13:44:34 527231bc67285f01fb18d4451b28f61da3c4e39d"
 
 /*
 ** CAPI3REF: Run-Time Library Version Numbers
@@ -288,7 +288,7 @@ typedef sqlite_uint64 sqlite3_uint64;
 ** [sqlite3_blob_close | close] all [BLOB handles], and 
 ** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
 ** with the [sqlite3] object prior to attempting to close the object.  ^If
-** sqlite3_close() is called on a [database connection] that still has
+** sqlite3_close_v2() is called on a [database connection] that still has
 ** outstanding [prepared statements], [BLOB handles], and/or
 ** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation
 ** of resources is deferred until all [prepared statements], [BLOB handles],
@@ -483,7 +483,17 @@ SQLITE_API int sqlite3_exec(
 #define SQLITE_CORRUPT_VTAB            (SQLITE_CORRUPT | (1<<8))
 #define SQLITE_READONLY_RECOVERY       (SQLITE_READONLY | (1<<8))
 #define SQLITE_READONLY_CANTLOCK       (SQLITE_READONLY | (2<<8))
+#define SQLITE_READONLY_ROLLBACK       (SQLITE_READONLY | (3<<8))
 #define SQLITE_ABORT_ROLLBACK          (SQLITE_ABORT | (2<<8))
+#define SQLITE_CONSTRAINT_CHECK        (SQLITE_CONSTRAINT | (1<<8))
+#define SQLITE_CONSTRAINT_COMMITHOOK   (SQLITE_CONSTRAINT | (2<<8))
+#define SQLITE_CONSTRAINT_FOREIGNKEY   (SQLITE_CONSTRAINT | (3<<8))
+#define SQLITE_CONSTRAINT_FUNCTION     (SQLITE_CONSTRAINT | (4<<8))
+#define SQLITE_CONSTRAINT_NOTNULL      (SQLITE_CONSTRAINT | (5<<8))
+#define SQLITE_CONSTRAINT_PRIMARYKEY   (SQLITE_CONSTRAINT | (6<<8))
+#define SQLITE_CONSTRAINT_TRIGGER      (SQLITE_CONSTRAINT | (7<<8))
+#define SQLITE_CONSTRAINT_UNIQUE       (SQLITE_CONSTRAINT | (8<<8))
+#define SQLITE_CONSTRAINT_VTAB         (SQLITE_CONSTRAINT | (9<<8))
 
 /*
 ** CAPI3REF: Flags For File Open Operations
@@ -2670,7 +2680,7 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
 **     sqlite3_open_v2(). ^Setting the cache parameter to "private" is 
 **     equivalent to setting the SQLITE_OPEN_PRIVATECACHE bit.
 **     ^If sqlite3_open_v2() is used and the "cache" parameter is present in
-**     a URI filename, its value overrides any behaviour requested by setting
+**     a URI filename, its value overrides any behavior requested by setting
 **     SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
 ** </ul>
 **
@@ -3988,7 +3998,8 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*);
 SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
 SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void);
 SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void);
-SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),void*,sqlite3_int64);
+SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
+                      void*,sqlite3_int64);
 #endif
 
 /*
@@ -4068,14 +4079,17 @@ SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
 ** In those cases, sqlite3_aggregate_context() might be called for the
 ** first time from within xFinal().)^
 **
-** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer if N is
-** less than or equal to zero or if a memory allocate error occurs.
+** ^The sqlite3_aggregate_context(C,N) routine returns a NULL pointer 
+** when first called if N is less than or equal to zero or if a memory
+** allocate error occurs.
 **
 ** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
 ** determined by the N parameter on first successful call.  Changing the
 ** value of N in subsequent call to sqlite3_aggregate_context() within
 ** the same aggregate function instance will not resize the memory
-** allocation.)^
+** allocation.)^  Within the xFinal callback, it is customary to set
+** N=0 in calls to sqlite3_aggregate_context(C,N) so that no 
+** pointless memory allocations occur.
 **
 ** ^SQLite automatically frees the memory allocated by 
 ** sqlite3_aggregate_context() when the aggregate query concludes.
@@ -6369,7 +6383,7 @@ struct sqlite3_pcache_page {
 ** parameter to help it determined what action to take:
 **
 ** <table border=1 width=85% align=center>
-** <tr><th> createFlag <th> Behaviour when page is not already in cache
+** <tr><th> createFlag <th> Behavior when page is not already in cache
 ** <tr><td> 0 <td> Do not allocate a new page.  Return NULL.
 ** <tr><td> 1 <td> Allocate a new page if it easy and convenient to do so.
 **                 Otherwise return NULL.
index 5abcde2c8f45460c4b63880d6cf30b6960c6e09e..a465b8eccc542c2623817c17c76d72d3cc73c289 100644 (file)
@@ -236,6 +236,20 @@ struct sqlite3_api_routines {
   int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
   int (*vtab_config)(sqlite3*,int op,...);
   int (*vtab_on_conflict)(sqlite3*);
+  /* Version 3.7.16 and later */
+  int (*close_v2)(sqlite3*);
+  const char *(*db_filename)(sqlite3*,const char*);
+  int (*db_readonly)(sqlite3*,const char*);
+  int (*db_release_memory)(sqlite3*);
+  const char *(*errstr)(int);
+  int (*stmt_busy)(sqlite3_stmt*);
+  int (*stmt_readonly)(sqlite3_stmt*);
+  int (*stricmp)(const char*,const char*);
+  int (*uri_boolean)(const char*,const char*,int);
+  sqlite3_int64 (*uri_int64)(const char*,const char*,sqlite3_int64);
+  const char *(*uri_parameter)(const char*,const char*);
+  char *(*vsnprintf)(int,char*,const char*,va_list);
+  int (*wal_checkpoint_v2)(sqlite3*,const char*,int,int*,int*);
 };
 
 /*
@@ -439,6 +453,20 @@ struct sqlite3_api_routines {
 #define sqlite3_blob_reopen            sqlite3_api->blob_reopen
 #define sqlite3_vtab_config            sqlite3_api->vtab_config
 #define sqlite3_vtab_on_conflict       sqlite3_api->vtab_on_conflict
+/* Version 3.7.16 and later */
+#define sqlite3_close_v2               sqlite3_api->close_v2
+#define sqlite3_db_filename            sqlite3_api->db_filename
+#define sqlite3_db_readonly            sqlite3_api->db_readonly
+#define sqlite3_db_release_memory      sqlite3_api->db_release_memory
+#define sqlite3_errstr                 sqlite3_api->errstr
+#define sqlite3_stmt_busy              sqlite3_api->stmt_busy
+#define sqlite3_stmt_readonly          sqlite3_api->stmt_readonly
+#define sqlite3_stricmp                sqlite3_api->stricmp
+#define sqlite3_uri_boolean            sqlite3_api->uri_boolean
+#define sqlite3_uri_int64              sqlite3_api->uri_int64
+#define sqlite3_uri_parameter          sqlite3_api->uri_parameter
+#define sqlite3_uri_vsnprintf          sqlite3_api->vsnprintf
+#define sqlite3_wal_checkpoint_v2      sqlite3_api->wal_checkpoint_v2
 #endif /* SQLITE_CORE */
 
 #define SQLITE_EXTENSION_INIT1     const sqlite3_api_routines *sqlite3_api = 0;
index a7d86c2df30edc360bfe828c24be1084710af7a0..cec66776ee8f6bd336ca556895f136959e9fceb4 100644 (file)
@@ -25,6 +25,12 @@ sub get_command_and_cmdline($)
   ($file, $full);
 }
 
+sub error($)
+{
+  print STDERR shift;
+  exit(1);
+}
+
 # extract an entry with modules from a modules.list file
 sub get_module_entry($$)
 {
@@ -46,7 +52,7 @@ sub get_module_entry($$)
     );
   }
 
-  open(M, $mod_file) || die "Cannot open $mod_file!: $!";
+  open(M, $mod_file) || error "Cannot open $mod_file!: $!\n";
 
   # preseed first 3 modules
   $mods[0] = { command => 'fiasco',   cmdline => 'fiasco',   type => 'bin'};
@@ -125,7 +131,7 @@ sub get_module_entry($$)
                        'bootstrap', 'roottask', 'kernel', 'sigma0',
                         'module-perl', 'module-shell', 'module-glob',
                        'module-group', 'moe', 'initrd', 'set');
-    die "$line: Invalid type \"$type\""
+    error "$mod_file:$line: Invalid type \"$type\"\n"
       unless grep(/^$type$/, @valid_types);
 
     @m = ( $remaining );
@@ -141,7 +147,7 @@ sub get_module_entry($$)
       $type = 'bin';
     } elsif ($type eq 'module-shell') {
       @m = split /\n/, `$remaining`;
-      die "Shell command on line $line failed\n" if $?;
+      error "$mod_file:$line: Shell command failed\n" if $?;
       $type = 'bin';
     } elsif ($type eq 'module-glob') {
       @m = glob $remaining;
@@ -149,7 +155,7 @@ sub get_module_entry($$)
     } elsif ($type eq 'module-group') {
       @m = ();
       foreach (split /\s+/, $remaining) {
-       die "Unknown group '$_'" unless defined $groups{$_};
+       error "$mod_file:$line: Unknown group '$_'\n" unless defined $groups{$_};
         push @m, @{$groups{$_}};
       }
       $type = 'bin';
@@ -193,19 +199,19 @@ sub get_module_entry($$)
     } elsif ($process_mode eq 'group') {
       push @{$groups{$current_group_name}}, @m;
     } else {
-      die "Invalid mode '$process_mode'";
+      error "$mod_file:$line: Invalid mode '$process_mode'\n";
     }
   }
 
   close M;
 
-  die "Unknown entry \"$entry_to_pick\"!" unless $found_entry;
-  die "'modaddr' not set" unless $modaddr_title || $modaddr_global;
+  error "$mod_file: Unknown entry \"$entry_to_pick\"!\n" unless $found_entry;
+  error "$mod_file: 'modaddr' not set\n" unless $modaddr_title || $modaddr_global;
 
   my $m = $modaddr_title || $modaddr_global;
   if (defined $is_mode_linux)
     {
-      die "No Linux kernel image defined" unless defined $mods[0]{cmdline};
+      error "No Linux kernel image defined\n" unless defined $mods[0]{cmdline};
       print STDERR "Entry '$entry_to_pick' is a Linux type entry\n";
       my @files;
       # @files is actually redundant but eases file selection for entry
@@ -265,7 +271,7 @@ sub get_entries($)
   my ($mod_file) = @_;
   my @entry_list;
 
-  open(M, $mod_file) || die "Cannot open $mod_file!: $!";
+  open(M, $mod_file) || error "Cannot open $mod_file!: $!\n";
 
   while (<M>) {
     chomp;
@@ -302,7 +308,7 @@ sub search_file_or_die($$)
   my $file = shift;
   my $paths = shift;
   my $f = search_file($file, $paths);
-  die "Could not find '$file' with path '$paths'" unless defined $f;
+  error "Could not find '$file' with path '$paths'\n" unless defined $f;
   $f;
 }
 
@@ -315,7 +321,7 @@ sub get_or_copy_file_uncompressed_or_die($$$$)
 
   my $fp = L4::ModList::search_file_or_die($command, $paths);
 
-  open F, $fp || die "connot open '$fp': $!";
+  open F, $fp || error "Cannot open '$fp': $!\n";
   my $buf;
   read F, $buf, 2;
   close F;
diff --git a/repomgr b/repomgr
index 88eea37ea93e62f793e953f8175fda61901f574d..444001dedbdd9e172cb8cf00d226bf8a16e9a67f 100755 (executable)
--- a/repomgr
+++ b/repomgr
@@ -387,7 +387,7 @@ sub do_checkout(%)
 
       foreach my $pe (@path_elems)
         {
-          if (! -d "$path/$pe/.svn")
+          if (! -d "$path/$pe")
             {
               # if we find something from path_roots then switch to that
               my $changed_path = convert_path("$path/$pe", 0,
@@ -417,7 +417,7 @@ sub do_checkout(%)
                   }
                 else
                   {
-                    my $cmd = "cd $path && svn update -r '$svnrev' --depth empty $pe";
+                    my $cmd = "cd $path && svn update -q -r '$svnrev' --depth empty $pe";
                     #print "cmd: $cmd\n";
                     system($cmd);
                     die "svn update failed" if $?;