$(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"; \
.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 \
$(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:"
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
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
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
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
Choose this if you have a LEON3 CPU.
endchoice
-
-
config CPU_VIRT
bool "Enable CPU virtualization (SVM and VT)"
depends on PF_PC
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
config ARM_CPU_ERRATA
bool "Enable CPU errata workarounds"
- depends on ARM && !ARM_TZ
+ depends on ARM
endmenu # target
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.
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
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.
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
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
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
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
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:
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
@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
%.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
%.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)
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
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
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
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
endif
ifeq ("$(CONFIG_SCHED_HPET)","y")
timer_IMPL += timer-hpet
+ timer_tick_IMPL += timer_tick-single-vector timer_tick-ia32
INTERFACES_KERNEL += hpet
endif
#
# 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 \
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
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
#
# 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
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
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
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), \
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)
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 \
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
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
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
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
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
#
# 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 \
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 \
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 \
# UNITTEST subsystem
#
# disabled until unittests fixed
-ifeq (1,2)
+ifeq (0,1)
SUBSYSTEMS += UNITTEST
VPATH += test/unit
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; }
INTERFACE:
#include "types.h"
-#include <bitfield>
+#include <cxx/bitfield>
/**
* Description of the mapping buffer registers contained in the UTCB
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.
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.
* \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.
* \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); }
/**
* 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); }
/**
* 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); }
/**
* \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.
* 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).
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 */
CXX_BITFIELD_MEMBER(12, MWORD_BITS-1, adr, _raw);
public:
+
+ Rights rights() const { return Rights(_rights()); }
+
/**
* Rights bits for flex pages.
*
* 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); }
};
#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.
*
* 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,
* \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.
* \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).
* \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.
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
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;
}
$(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
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,
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
-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
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
#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,
- };
};
//---------------------------------------------------------------------------
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]:
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)
#endif
}
-
// ---------------------------------------------------------------------------
IMPLEMENTATION [arm && (pxa || sa1100 || 926)]:
" 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())
);
}
}
" 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())
);
}
}
" 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)]:
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();
{
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");
}
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();
" 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();
" 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();
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());
}
//-----------------------------------------------------------------------------
" 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"
);
}
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"
);
}
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]:
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)
);
}
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"
"=r" (dummy2)
:
"0" (Flush_area),
- "1" (Ram?2048:1024)
+ "1" (Ram ? 2048 : 1024)
);
}
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"
:
"=r" (dummy2)
:
"0" (Flush_area),
- "1" (Ram?2048:1024)
+ "1" (Ram ? 2048 : 1024)
);
}
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()
// 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)
);
}
-
-
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,
};
};
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;
}
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
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
}
//----------------------------------------------------------------
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;
-}
-
#include "types.h"
/**
- * PC I/O port API.
+ * I/O API.
*/
class Io
{
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]:
void Io::write(T value, Address address)
{ *(volatile T *)address = value; }
+// ----------------------------------------------------------------------
IMPLEMENTATION:
IMPLEMENT inline
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);
+}
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();
}
--- /dev/null
+// 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;
+};
public:
//disable power savings mode
static Mword wake(Mword);
- static unsigned cpu_id();
+ static Cpu_phys_id cpu_id();
};
/// Unblock external inetrrupts
IMPLEMENTATION [ppc32 && !mpcore]:
IMPLEMENT static inline
-unsigned Proc::cpu_id()
-{ return 0; }
+Cpu_phys_id Proc::cpu_id()
+{ return Cpu_phys_id(0); }
public:
//disable power savings mode
static Mword wake(Mword);
- static unsigned cpu_id();
+ static Cpu_phys_id cpu_id();
};
/// Unblock external interrupts
IMPLEMENTATION [sparc && !mpcore]:
IMPLEMENT static inline
-unsigned Proc::cpu_id()
-{ return 0; }
+Cpu_phys_id Proc::cpu_id()
+{ return Cpu_phys_id(0); }
scratch3 = ier();
ier(scratch);
- return (scratch2 == 0x00 && scratch3 == 0x0f);
+ return scratch2 == 0x00 && scratch3 == 0x0f;
}
IMPLEMENT
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 */
#include "mem_unit.h"
#include "static_init.h"
#include "watchdog.h"
+#include "cxx/cxx_int"
STATIC_INITIALIZE_P(Jdb, JDB_INIT_PRIO);
// 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
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;
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];
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);
{
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;
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));
}
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
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;
}
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()
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);
"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());
}
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]:
#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)
// -----------------------------------------------------------------------
-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
}
// -----------------------------------------------------------------------
-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;
}
}
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));
+ }
+}
-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"
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();
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);
// 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"
: "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);
#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);
- }
-}
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())
{
}
-#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()
// 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())
{
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.
// 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))
{
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
{
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)
// 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;
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;
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;
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);
// 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);
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;
{
// 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;
// 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)
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);
}
}
{
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];
// 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;
*/
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);
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
IMPLEMENT
bool
-Jdb::handle_debug_traps(unsigned cpu)
+Jdb::handle_debug_traps(Cpu_number cpu)
{
bool really_break = true;
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;
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);
}
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))
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))
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)
is_current.tid = tid;
is_current.c = 0;
- is_current.cpu = 0;
+ is_current.cpu = Cpu_number::boot_cpu();
Jdb::foreach_cpu(is_current);
{
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
{
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);
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());
}
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);
}
{
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); }
};
* 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);
};
//---------------------------------------------------------------------------
IMPLEMENT
Thread *
-Jdb::get_thread(unsigned cpu)
+Jdb::get_thread(Cpu_number cpu)
{
Jdb_entry_frame *c = get_entry_frame(cpu);
PUBLIC
static void
-Jdb::get_current(unsigned cpu)
+Jdb::get_current(Cpu_number cpu)
{
current_active = get_thread(cpu);
}
{
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
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:
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;
PUBLIC static
bool
-Jdb::cpu_in_jdb(unsigned cpu)
+Jdb::cpu_in_jdb(Cpu_number cpu)
{ return Cpu::online(cpu) && running.cpu(cpu); }
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;
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;
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))
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
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
{
PUBLIC static inline
Jdb_entry_frame*
-Jdb::get_entry_frame(unsigned cpu)
+Jdb::get_entry_frame(Cpu_number cpu)
{
return entry_frame.cpu(cpu);
}
PUBLIC static inline
Space *
-Jdb::get_task(unsigned cpu)
+Jdb::get_task(Cpu_number cpu)
{
if (!get_thread(cpu))
return 0;
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())
{
"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;
}
PRIVATE static
bool
-Jdb::stop_all_cpus(unsigned /*current_cpu*/)
+Jdb::stop_all_cpus(Cpu_number)
{ return true; }
PRIVATE
PRIVATE static inline
int
-Jdb::remote_work_ipi_process(unsigned)
+Jdb::remote_work_ipi_process(Cpu_number)
{ return 1; }
{
// 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;
};
//--------------------------------------------------------------------------
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;
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:
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))
{
}
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)
{
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;
// 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);
}
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)))
{
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;
}
// 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)
{
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)
{
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();
}
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;
{
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);
}
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);
}
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));
}
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 };
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);
}
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
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();
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,
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);
{
// 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();
INTERFACE:
#include "jdb_module.h"
-#include <slist>
+#include <cxx/slist>
class Jdb_kern_info_module;
#include "jdb_module.h"
#include "jdb_list.h"
#include "kobject.h"
-#include <slist>
+#include <cxx/slist>
class Kobject;
class Jdb_kobject_handler;
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;
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: "
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)
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;
}
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++)
{
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 ' ':
fmt = " port: " L4_FRAME_INPUT_FMT;
break;
#endif
-
- case 'o':
- fmt = " object: %x";
- break;
- }
+ }
which_mapdb = subcmd;
args = &pagenum;
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;
}
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 },
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");
INTERFACE:
#include <cstdarg>
-#include <hlist>
-#include <slist>
+#include <cxx/hlist>
+#include <cxx/slist>
#include "initcalls.h"
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)
{
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);
" 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))
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);
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);
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);
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);
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;
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
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;
INTERFACE:
-#include <hlist>
+#include <cxx/hlist>
class Jdb_prompt_ext : public cxx::H_list_item
{
-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);
-}
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;
: 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
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
{
Thread *th = Kobject::dcast<Thread_object*>(o);
if (!th || !th->space())
- return false;
+ return false;
t = th->space();
}
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;
}
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)
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("");
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)
#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__;
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
{
Mword i;
- for (i=0; i<_max_entries; i++)
+ for (i = 0; i < _max_entries; i++)
buffer()[i].clear();
_tbuf_act = buffer();
Mword cnt = 0;
- for (Mword idx=0; idx<unfiltered_entries(); idx++)
+ for (Mword idx = 0; idx<unfiltered_entries(); idx++)
if (!buffer()[idx].hidden())
cnt++;
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
/** 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
if (!_filter_enabled)
return unfiltered_lookup(look_idx);
- for (Mword idx=0;; idx++)
+ for (Mword idx = 0;; idx++)
{
Tb_entry *e = unfiltered_lookup(idx);
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 (;;)
{
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;
{
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++;
/** 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;
* @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;
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;
status_line:
for (bool redraw=false; !redraw;)
{
-
Smword c;
Unsigned8 d = 0; // default search direction is forward
}
}
- 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];
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;
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;
}
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))
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(),
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());
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;
}
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 : "");
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
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)
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());
}
//
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;
private:
static char subcmd;
static char long_output;
- static unsigned cpu;
+ static Cpu_number cpu;
private:
static int _mode;
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
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
Jdb_kobject::print_uid(t, 5);
- printf(" %-3u ", t->cpu());
+ printf(" %-3u ", cxx::int_value<Cpu_number>(t->cpu()));
print_thread_name(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;
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())
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();
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();
}
}
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;
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]:
// 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();
}
// 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
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;
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];
// 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();
}
// 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
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;
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];
Space *
Jdb::translate_task(Address addr, Space * task)
{
+ (void)addr;
// return (Kmem::is_kmem_page_fault(addr, 0)) ? 0 : task;
return task;
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)
IMPLEMENT inline
void
-Jdb::enter_trap_handler(unsigned /*cpu*/)
+Jdb::enter_trap_handler(Cpu_number)
{
conf_screen();
IMPLEMENT inline
void
-Jdb::leave_trap_handler(unsigned)
+Jdb::leave_trap_handler(Cpu_number)
{
// Restore terminal mode
leave_getchar();
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
// 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);
}
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);
}
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;
}
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;
}
IMPLEMENT
bool
-Jdb::handle_debug_traps(unsigned cpu)
+Jdb::handle_debug_traps(Cpu_number cpu)
{
switch (entry_frame.cpu(cpu)->_trapno)
{
IMPLEMENT inline
bool
-Jdb::handle_conditional_breakpoint(unsigned /*cpu*/)
+Jdb::handle_conditional_breakpoint(Cpu_number)
{ return false; }
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)
{
// 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;
}
}
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
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;
}
static
void
-Jdb::send_nmi(unsigned /*cpu*/)
+Jdb::send_nmi(Cpu_number)
{
}
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)
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))
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));
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();
# 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 $<,$+)
clean-KERNEL:
+
+kernel.arm.lds: globalconfig.h
+
--- /dev/null
+#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
#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()
{
: : : "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
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)
;
--- /dev/null
+# PF: BCM2835
+# PFDESCR: Broadcom 2835
+# PFSELECT: CAN_ARM_CPU_1176
+# PFDEPENDS: ARM
--- /dev/null
+# 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
--- /dev/null
+INTERFACE [arm && bcm2835]:
+namespace Bootstrap {
+enum {
+ Cache_flush_area = 0xe0000000,
+};
+}
--- /dev/null
+INTERFACE [arm && bcm2835]:
+
+#define TARGET_NAME "Broadcom 2835"
--- /dev/null
+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();
+}
--- /dev/null
+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,
+ };
+};
--- /dev/null
+// ---------------------------------------------------------------------
+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"; }
--- /dev/null
+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 (;;)
+ ;
+}
--- /dev/null
+// --------------------------------------------------------------------------
+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;
+}
--- /dev/null
+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;
+}
--- /dev/null
+# 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.
--- /dev/null
+# 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
--- /dev/null
+INTERFACE [arm && exynos]:
+
+namespace Bootstrap {
+enum { Cache_flush_area = 0, };
+}
+
--- /dev/null
+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
+ };
+};
--- /dev/null
+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);
+}
--- /dev/null
+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);
+}
+
--- /dev/null
+//--------------------------------------------------------------------------
+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();
+}
--- /dev/null
+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();
+}
--- /dev/null
+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,
+ };
+};
--- /dev/null
+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;
+}
--- /dev/null
+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"; }
--- /dev/null
+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; }
+
--- /dev/null
+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);
+}
--- /dev/null
+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)
+ ;
+}
--- /dev/null
+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,
+ };
+};
--- /dev/null
+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)
+{}
--- /dev/null
+//-----------------------------------------------------------------------------
+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);
+}
--- /dev/null
+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;
+}
--- /dev/null
+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);
+}
--- /dev/null
+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();
+}
--- /dev/null
+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;
+}
+
--- /dev/null
+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);
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
//-----------------------------------------------------------------------------
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 };
}
+
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,
};
};
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,
};
};
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,
};
};
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
};
};
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
};
};
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,
};
};
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
- };
};
// ---------------------------------------------------------------------
#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 */ }
};
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
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
}
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;
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
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]
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;
IMPLEMENTATION [arm && pic_gic && mp && imx6]:
PUBLIC static
-void Pic::init_ap(unsigned)
+void Pic::init_ap(Cpu_number)
{
gic->init_ap();
}
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);
}
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 (;;)
;
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);
}
// ------------------------------------------------------------------------
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 (;;)
;
#include "kmem.h"
#include "irq_chip.h"
+#include "mmio_register_block.h"
+
EXTENSION class Timer
{
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;
};
// ----------------------------------------------------------------------
#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
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]
// --------------------------------------------------------------------------
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;
};
// ------------------------------------------------------------------------
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
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
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,
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;
}
--- /dev/null
+// --------------------------------------------------------------------------
+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);
+}
+
#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; }
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
//-----------------------------------------------------------------------------
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);
}
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,
};
};
// ---------------------------------------------------------------------
-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
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
}
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;
void Pic::init()
{
Irq_mgr::mgr = mgr.construct();
-
- Io::write(0xffffffff, IRQ_ENABLE_CLEAR);
- Io::write(0xffffffff, FIQ_ENABLE_CLEAR);
}
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"
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 (;;)
;
// --------------------------------------------------------------------------
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,
TIMER_CTRL_PERIODIC = 1 << 6,
TIMER_CTRL_ENABLE = 1 << 7,
};
+
+ static Static_object<Timer> _timer;
};
// ----------------------------------------------------------------------
#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*/)
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
#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; }
# 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
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);
}
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);
}
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,
};
};
-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 */ }
};
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
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;
{
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
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;
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);
}
#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 (;;)
;
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,
Reload_value = 200000,
};
+
+ static Static_object<Timer> _timer;
};
// ----------------------------------------------------------------------
#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
void
Timer::acknowledge()
{
- Io::clear<Unsigned32>(Timer0_bridge_num, Bridge_cause);
+ _timer->modify<Unsigned32>(0, Timer0_bridge_num, Bridge_cause);
}
IMPLEMENT inline
--- /dev/null
+# 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
--- /dev/null
+# 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
--- /dev/null
+INTERFACE [arm && omap]:
+
+namespace Bootstrap {
+enum { Cache_flush_area = 0 };
+}
--- /dev/null
+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"
--- /dev/null
+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();
+}
--- /dev/null
+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,
+ };
+};
--- /dev/null
+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;
+}
--- /dev/null
+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();
+}
--- /dev/null
+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"; }
--- /dev/null
+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);
+ }
+}
+
--- /dev/null
+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 (;;)
+ ;
+}
--- /dev/null
+// --------------------------------------------------------------------------
+INTERFACE [arm && mptimer && omap4_pandaboard]:
+
+EXTENSION class Timer
+{
+private:
+ static Mword interval() { return 499999; }
+};
--- /dev/null
+// --------------------------------------------------------------------------
+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;
+}
--- /dev/null
+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);
+}
+
+
+
--- /dev/null
+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);
+}
--- /dev/null
+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;
+}
{
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,
};
};
{
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
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
}
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);
}
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;
};
#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
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) )
//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;
}
# 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
//-----------------------------------------------------------------------------
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);
}
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);
}
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,
};
};
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 (;;)
;
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"
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
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),)
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
#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
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);
}
+
#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;
};
Clock::Counter
Clock::read_counter() const
{
- return Io::read<Mword>(SYS_24MHZ);
+ return Platform::sys->read<Mword>(Platform::Sys::Cnt_24mhz);
}
IMPLEMENT inline
{
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,
};
};
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,
};
};
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,
};
};
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,
};
};
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,
};
};
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
#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();
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
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());
}
PUBLIC static
-void Pic::init_ap(unsigned)
+void Pic::init_ap(Cpu_number)
{
gic->init_ap();
}
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();
}
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));
+}
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());
}
#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
}
// ------------------------------------------------------------------------
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)
}
// ------------------------------------------------------------------------
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
}
// ------------------------------------------------------------------------
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 (;;)
// --------------------------------------------------------------------------
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;
}
// --------------------------------------------------------------------------
-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,
- };
};
// -----------------------------------------------------------------------
#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
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
#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()
{
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
//-----------------------------------------------------------------------------
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);
}
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,
};
};
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
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
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
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
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
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
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
}
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)
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);
}
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)
-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"
#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
(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;
}
#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; }
# 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
//---------------------------------------------------------------------------
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);
}
+
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);
}
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,
};
};
#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 (;;)
;
}
# 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
# 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
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
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);
}
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);
}
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,
};
};
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
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;
IMPLEMENTATION [arm && mp && pic_gic && tegra2]:
PUBLIC static
-void Pic::init_ap(unsigned)
+void Pic::init_ap(Cpu_number)
{
gic->init_ap();
}
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;
IMPLEMENTATION [arm && mp && tegra2]:
#include "io.h"
+#include "kmem.h"
#include <cstdlib>
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
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));
}
+// ------------------------------------------------------------------------
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 (;;)
;
}
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;
+}
/* 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
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,
};
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,
};
+// -----------------------------------------------------------------------
+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]:
Cp15_c1_high_vector = 1 << 13,
};
- Cpu(unsigned id) { set_id(id); }
+ Cpu(Cpu_number id) { set_id(id); }
struct Ids {
private:
static Cpu *_boot_cpu;
- unsigned _phys_id;
+ Cpu_phys_id _phys_id;
Ids _cpu_id;
};
| 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
void bsp_init(bool) {}
};
-//---------------------------------------------------------------------------
-INTERFACE [arm && (mpcore || armca9) && !bsp_cpu]:
-
-EXTENSION class Scu
-{
-public:
- enum { Bsp_enable_bits = 0 };
-};
-
//-------------------------------------------------------------------------
IMPLEMENTATION [arm]:
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
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]
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();
#include <panic.h>
#include "io.h"
-#include "pagetable.h"
+#include "paging.h"
#include "kmem_space.h"
#include "kmem_alloc.h"
#include "mem_unit.h"
:
: "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();
{
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; }
: : "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]:
}
//---------------------------------------------------------------------------
-IMPLEMENTATION [arm && !tz]:
+IMPLEMENTATION [arm && !arm_em_tz]:
PRIVATE static inline
void
{}
//---------------------------------------------------------------------------
-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>
{
// 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"
"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
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]:
INTERFACE [arm && fpu]:
+#include <cxx/bitfield>
+
EXTENSION class Fpu
{
public:
Mword fpinst2;
};
- Mword fpsid() const { return _fpsid; }
-
enum
{
FPEXC_EN = 1 << 30,
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;
};
// ------------------------------------------------------------------------
{
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;
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();
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,
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,
};
};
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 }; };
//-------------------------------------------------------------------
#include "io.h"
#include "irq_chip_generic.h"
#include "panic.h"
+#include "processor.h"
PUBLIC inline NEEDS["io.h"]
unsigned
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
{
if (!primary_gic)
{
- init_ap();
+ cpu_init();
return 0;
}
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;
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)
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;
}
printf("Number of IRQs available at this GIC: %d\n", num);
Irq_chip_gen::init(num);
-
- //enable_tz_support();
}
/**
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"]
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]:
#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);
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);
#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
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
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 */
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 !!! */
*/
swi_entry:
switch_to_kernel 0 0 0
+ exceptionframe
enter_sys_call no_sys_call
no_sys_call:
- exceptionframe
enter_slowtrap 0x00200000
.align 4
* 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
/*****************************************************************************/
/* 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"
/**********************************************************************
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
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
stmia r0!, {sp, lr}
mrs r1, spsr
stmia r0!, {r1}
-
+
// fiq
cps #0x11
stmia r0!, {r8 - r12, sp, lr}
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}
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
ldmia r0!, {sp, lr}
ldmia r0!, {r1}
msr spsr, r1
-
+
// fiq
cps #0x11
ldmia r0!, {r8 - r12, sp, lr}
cps #0x17
ldmia r0!, {sp, lr}
ldmia r0!, {r1}
- mrs r1, spsr
+ msr spsr, r1
// und
cps #0x1b
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
*/
.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
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
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
*
*/
go_secure:
- SAVE_NONSECURE_STATE 16
+ SAVE_NONSECURE_STATE 20
RESTORE_SECURE_STATE
mov lr, r3
.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 ---------------------------*/
#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);
}
//---------------------------------------------------------------------------
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())
{}
IMPLEMENTATION [mp]:
#include "io.h"
-#include "pagetable.h"
#include "platform_control.h"
#include "outer_cache.h"
-
+#include "paging.h"
#include <cstdio>
static void
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));
}
#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.
{
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);
+}
#include "mem_unit.h"
#include "kmem_space.h"
-#include "pagetable.h"
#include "ram_quota.h"
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()
{
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();
}
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;
};
//---------------------------------------------------------------------------
#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;
+
+
+
#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"
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
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,
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
};
};
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)];
};
#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);
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));
-IMPLEMENT inline NEEDS[<config.h>]
+IMPLEMENT inline ALWAYS_INLINE NEEDS[<config.h>]
void
Mem_layout::add_pmem(Address phys, Address virt, unsigned long size)
{
phys += Config::SUPERPAGE_SIZE;
virt += Config::SUPERPAGE_SIZE;
}
-
}
+
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)
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));
}
}
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;
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;
}
}
#include "member_offs.h"
#include "paging.h"
#include "types.h"
-#include "pagetable.h"
#include "ram_quota.h"
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,
static void kernel_space(Mem_space *);
- static bool has_superpages() { return true; }
-
private:
// DATA
Dir_type *_dir;
+ Phys_mem_addr _dir_phys;
};
//---------------------------------------------------------------------------
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
{
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
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)
make_current();
else
tlb_flush(true);
-#if 0
- _dir->invalidate((void*)Kmem::ipc_window(0), Config::SUPERPAGE_SIZE * 4,
- c_asid());
-#endif
-
}
_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;
}
}
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]
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.
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);
}
}
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;
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
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]:
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");
}
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;
PRIVATE inline static
unsigned long
-Mem_space::next_asid(unsigned cpu)
+Mem_space::next_asid(Cpu_number cpu)
{
return _next_free_asid.cpu(cpu)++;
}
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);
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
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);
}
//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
// 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);
}
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];
}
}
-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;
}
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);
};
//---------------------------------------------------------------------------
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" );
-}
-
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,
};
// ------------------------------------------------------------------------
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();
}
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;
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)
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)
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
// 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
// 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]:
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 )
{
{
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,
};
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; }
};
// ------------------------------------------------------------------------
// ------------------------------------------------------------------------
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);
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)]:
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();
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);
+}
--- /dev/null
+
+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);
+}
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();
}
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();
}
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;
}
EXTENSION class Thread
{
public:
- static void init_per_cpu(unsigned cpu);
+ static void init_per_cpu(Cpu_number cpu);
private:
bool _in_exception;
IMPLEMENT_DEFAULT inline
void
-Thread::init_per_cpu(unsigned)
+Thread::init_per_cpu(Cpu_number)
{}
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;
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);
}
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;
}
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
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();
}
}
- 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);
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;
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);
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]:
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;
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);
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"
// --------------------------------------------------------------------------
INTERFACE [arm && mptimer]:
-#include "irq_chip.h"
#include "kmem.h"
+#include "cpu.h"
EXTENSION class Timer
{
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,
#include <cstdio>
#include "config.h"
-#include "io.h"
-#include "irq_chip.h"
#include "kip.h"
#include "globals.h"
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;
}
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
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
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();
--- /dev/null
+// --------------------------------------------------------------------------
+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); }
+};
+
+
.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
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
#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]
.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:
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
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
-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"
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"
#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
}
// --------------------------------------------------------------------------
-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"
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)
{}
--- /dev/null
+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;
+}
IMPLEMENTATION [arm]:
#include "mem.h"
-#include "pagetable.h"
+#include "paging.h"
#include "mem_space.h"
#include "kmem_alloc.h"
#include "config.h"
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)
INTERFACE:
#include <cstddef>
-#include <slist>
-#include <type_traits>
+#include <cxx/slist>
+#include <cxx/type_traits>
class Boot_alloced
{
INTERFACE:
#include <cassert>
-#include <hlist>
+#include <cxx/hlist>
#include "bitmap.h"
#include "config.h"
{
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)
{
public:
typedef Unsigned64 Time;
- Clock(unsigned cpu);
+ Clock(Cpu_number cpu);
Time delta();
private:
- unsigned _cpu_id;
+ Cpu_number _cpu_id;
Counter _last_value;
Counter read_counter() const;
IMPLEMENTATION:
IMPLEMENT inline
-Clock::Clock(unsigned cpu)
+Clock::Clock(Cpu_number cpu)
: _cpu_id(cpu), _last_value(read_counter())
{}
#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;
static const int serial_esc = 0;
};
+
+//---------------------------------------------------------------------------
+INTERFACE [!virtual_space_iface]:
+
+#define FIASCO_SPACE_VIRTUAL
+
+//---------------------------------------------------------------------------
+INTERFACE [virtual_space_iface]:
+
+#define FIASCO_SPACE_VIRTUAL virtual
+
//---------------------------------------------------------------------------
IMPLEMENTATION:
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;
};
{
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 >
struct Migration
{
- unsigned cpu;
+ Cpu_number cpu;
L4_sched_param const *sp;
bool in_progress;
&& (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())
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;
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());
// 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
{
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;
}
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; }
// 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
// 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();
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());
#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)
{}
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); }
/**
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());
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);
_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);
PUBLIC inline
-unsigned
+Cpu_number
Context::cpu(bool running = false) const
{
(void)running;
{
Mem_space **s = (Mem_space **)_s;
Mem_space::tlb_flush_spaces((bool)s[0], s[1], s[2]);
+
return 0;
}
{
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);
}
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]:
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;
}
+
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;
};
{ 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()); }
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(); }
};
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;
/**
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();
{
private:
- void set_id(unsigned id) { _id = id; }
- unsigned _id;
+ void set_id(Cpu_number id) { _id = id; }
+ Cpu_number _id;
};
//--------------------------------------------------------------------------
EXTENSION class Cpu
{
private:
- void set_id(unsigned) {}
+ void set_id(Cpu_number) {}
};
#include "kdb_ke.h"
IMPLEMENT inline
-unsigned
+Cpu_number
Cpu::id() const
{ return _id; }
IMPLEMENT static inline NEEDS["kdb_ke.h"]
bool
-Cpu::online(unsigned _cpu)
+Cpu::online(Cpu_number _cpu)
{ return _online_mask.get(_cpu); }
IMPLEMENTATION [!mp]:
IMPLEMENT inline
-unsigned
+Cpu_number
Cpu::id() const
-{ return 0; }
+{ return Cpu_number::boot_cpu(); }
IMPLEMENT inline
bool
IMPLEMENT static inline
bool
-Cpu::online(unsigned _cpu)
-{ return _cpu == 0; }
+Cpu::online(Cpu_number _cpu)
+{ return _cpu == Cpu_number::boot_cpu(); }
#include "bitmap.h"
#include "config.h"
+#include "types.h"
template<unsigned MAX_NUM_CPUS>
class Cpu_mask_t
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;
#include "lock_guard.h"
#include "spin_lock.h"
#include "slab_cache.h"
-#include <slist>
+#include <cxx/slist>
class Dbg_page_info_table;
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; }
};
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;
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
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();
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()))
//----------------------------------------------------------------------------
-IMPLEMENTATION [svm || vmx]:
+IMPLEMENTATION [svm || vmx || arm_em_tz]:
#include "vm_factory.h"
+#include "vm.h"
PRIVATE inline NOEXPORT
Kobject_iface *
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 *
struct Log_entry : public Tb_entry
{
Smword op;
- Mword buffer;
+ Cap_index buffer;
Mword id;
Mword ram;
Mword newo;
_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);
}
{
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();
{ return 1; }
IMPLEMENT
-void Fpu::init(unsigned)
+void Fpu::init(Cpu_number)
{}
IMPLEMENT inline
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);
_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:
#include "ptab_base.h"
class PF {};
+class Page {};
-class Pte_base
+class Pt_entry
{
public:
- typedef Mword Raw;
-
enum
{
Super_level = 0,
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;
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()));
}
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();
// 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
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;
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;
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
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
#include "ptab_base.h"
class PF {};
+class Page {};
-class Pte_base
+
+class Pt_entry
{
public:
- typedef Mword Raw;
-
enum
{
Super_level = 2,
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;
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();
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
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();
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;
{
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
}
PUBLIC static
-unsigned
+Cpu_number
Apic::find_cpu(Unsigned32 phys_id)
{
return apic.find_cpu(By_id(phys_id));
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
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; }
};
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);
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()
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
{
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));
{
#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
IMPLEMENT
void
-Fpu::init(unsigned cpu)
+Fpu::init(Cpu_number cpu)
{
// Mark FPU busy, so that first FPU operation will yield an exception
disable();
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 " : "");
PRIVATE static
void
-Fpu::init_xsave(unsigned cpu)
+Fpu::init_xsave(Cpu_number cpu)
{
Unsigned32 eax, ebx, ecx, edx;
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);
}
#include "initcalls.h"
#include <spin_lock.h>
#include "irq_chip_ia32.h"
-#include <bitfield>
+#include <cxx/bitfield>
class Acpi_madt;
PUBLIC static FIASCO_INIT
bool
-Io_apic::init(unsigned cpu)
+Io_apic::init(Cpu_number cpu)
{
_madt = Acpi::find<Acpi_madt const *>("APIC");
}
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());
}
*/
IMPLEMENT static inline NEEDS["apic.h"]
void
-Ipi::init(unsigned cpu)
+Ipi::init(Cpu_number cpu)
{
_ipi.cpu(cpu)._apic_id = Apic::get_id();
}
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);
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);
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);
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;
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
PUBLIC
void
-Irq_chip_ia32_pic::set_cpu(Mword, unsigned)
+Irq_chip_ia32_pic::set_cpu(Mword, Cpu_number)
{}
{ 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
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))
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);
}
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)
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)
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);
// 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);
{
// 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);
{
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;
}
#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()
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();
}
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;
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();
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"
* 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);
}
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
// 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*/)
-{}
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,
void page_map (Address phys, Address virt,
- Address size, unsigned page_attribs);
+ Address size, Attr);
void page_unmap (Address virt, Address size);
return false;
_dir = static_cast<Dir_type*>(b);
- _dir->clear(); // initialize to zero
+ _dir->clear(false); // initialize to zero
return true; // success
}
: _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"]
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;
}
{
// 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);
}
/**
*/
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);
}
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;
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"]
{
_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
+}
#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,
};
};
-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
*/
PUBLIC static inline
Unsigned32
-Pte_base::global()
-{
- return _cpu_global;
-}
+Pt_entry::global()
+{ return _cpu_global; }
//--------------------------------------------------------------------------
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))
// 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;
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)
{
}
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();
}
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;
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;
}
}
+//----------------------------------------------------------------------------
+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]:
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)
{
//---------------------------------------------------------------------------
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]:
#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;
}
IMPLEMENT
void
-Timer::init(unsigned)
+Timer::init(Cpu_number)
{
Apic::timer_assign_irq_vector(Config::Apic_timer_vector);
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;
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;
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;
}
IMPLEMENT
void
-Timer::init(unsigned)
+Timer::init(Cpu_number)
{
printf("Using the PIT (i8254) on IRQ %d for scheduling\n", irq());
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
void
thread_timer_interrupt_slow(void)
{
- if (!current_cpu())
+ if (current_cpu() == Cpu_number::boot_cpu())
{
if (Config::esc_hack)
{
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();
IMPLEMENT
void
-Timer_tick::disable(unsigned)
+Timer_tick::disable(Cpu_number)
{
Apic::timer_disable_irq();
}
mov %edx, %edi
mov $0xc0000080, %ecx
rdmsr
- bts $8,%eax
+ or $0x900,%eax // LME+NXE
wrmsr
mov %edi, %edx
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;
};
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 >
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; }
#include "vm_svm.h"
#include "vmx.h"
#include "vm_vmx.h"
+#include "vm_vmx_ept.h"
PRIVATE static inline
template< typename 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;
}
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
{
// 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))
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
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)));
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>
+{
};
//----------------------------------------------------------------------------
#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
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)
{
}
}
-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)
{
}
}
-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)
{
}
}
-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)
{
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);
// 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);
}
-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);
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
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);
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());
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())
#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?
{
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);
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);
--- /dev/null
+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);
+
+
+
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)
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:
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
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; }
}
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); }
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:
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,
F_host_sysenter_cs = 0x4c00,
- F_guest_cr2 = 0x6830,
+ F_sw_guest_cr2 = 0x683e,
+
F_host_cr0 = 0x6c00,
F_host_cr3 = 0x6c02,
F_host_sysenter_esp = 0x6c10,
F_host_sysenter_eip = 0x6c12,
F_host_rip = 0x6c16,
+
};
enum Pin_based_ctls
PRB2_enable_ept = 1,
PRB2_enable_vpid = 5,
};
-
};
INTERFACE [vmx]:
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)
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;
// 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);
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
}
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;
}
{
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;
}
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");
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;
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
}
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
// 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);
}
+/*
+ * 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
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)
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;
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)
{
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)
{
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,
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.
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
#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()
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;
}
}
// 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);
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)));
}
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
@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)
{
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)
{
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)
{
/** 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);
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));
{
*port |= get_port_bit(port_number);
addto_io_counter(-1);
-
- return Page_writable | Page_user_accessible;
}
-
- return 0;
}
template< typename SPACE >
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; }
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());
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);
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;
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);
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();
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());
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);
}
INTERFACE:
+#include "types.h"
+
class Ipi
{
public:
- static void init(unsigned cpu);
+ static void init(Cpu_number cpu);
};
INTERFACE[!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; }
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; }
// ------------------------------------------------------------------------
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++; }
// 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!
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();
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();
* \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;
};
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"; }
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; }
#include "types.h"
#include "irq_chip.h"
-#include <type_traits>
+#include <cxx/type_traits>
/**
* Interface used to manage harware IRQs on a platform.
*/
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;
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));
}
PRIVATE inline NEEDS["globals.h"]
Kernel_task::Kernel_task()
-: Task(Ram_quota::root, Kmem::kdir)
+: Task(Ram_quota::root, Kmem::kdir, Caps::none())
{}
#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
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)
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));
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));
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)
// 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();
// 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();
// 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
INTERFACE:
#include <auto_quota.h>
-#include <slist>
+#include <cxx/slist>
#include "spin_lock.h"
#include "lock_guard.h"
_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;
#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
{
#include "lock.h"
#include "obj_space.h"
-#include <hlist>
+#include <cxx/hlist>
class Kobject_mappable
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)
{
#include "spin_lock.h"
#include "lock_guard.h"
-#include <dlist>
-#include <hlist>
+#include <cxx/dlist>
+#include <cxx/hlist>
class Kobject;
#include "kobject.h"
#include "thread.h"
-#include <type_traits>
+#include <cxx/type_traits>
class Kobject_helper_base
{
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))
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:
// 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;
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; }
};
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
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();
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())
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;
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
@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.
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);
}
+
#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,
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;
// 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)
{
{
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;
}
}
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
+ }
+}
}
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);
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:
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); }
//-------------------------------------------------------------------------
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:
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());
}
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
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;
}
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;
*/
// 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;
// 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
// 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;
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
// 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
// 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
// (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)
{
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);
}
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;
}
//----------------------------------------------------------------------------
}
inline
-unsigned
+L4_fpage::Rights
io_fpage_unmap(Space * /*space*/, L4_fpage const &/*fp*/, L4_map_mask)
{
- return 0;
+ return L4_fpage::Rights(0);
}
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;
Physframe* frame;
public:
- inline Page_number vaddr(Mapping* m) const;
+ inline Pfn vaddr(Mapping* m) const;
+ inline Order page_shift() const;
};
private:
#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"
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
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)
{
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)
{
{
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)));
}
}
}
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
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);
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));
}
}
}
//
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),
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));
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;
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;
}
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();
}
PUBLIC inline
-size_t
+Treemap::Order
Treemap::page_shift() const
{
return _page_shift;
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();
}
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))
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;
{
// 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;
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
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)
{
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;
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;
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());
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));
}
*/
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;
}
_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++ ()
{
// 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;
}
_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;
}
// 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;)
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);
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()
*/
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);
}
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()
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.
}
PUBLIC static inline NEEDS[Treemap::vaddr]
-Page_number
+Mapdb::Pfn
Mapdb::vaddr(const Mapdb::Frame& f, Mapping* m)
{
return f.treemap->vaddr(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
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;
{
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;
}
--- /dev/null
+#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;
+}
+
INTERFACE:
#include "types.h"
+#include "mapdb_types.h"
class Space;
/** Represents one mapping in a mapping tree.
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
@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. */
// 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,
// 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,
class Base_mappable
{
public:
+ typedef Mapping_tree::Page Page;
// DATA
cxx::unique_ptr<Mapping_tree> tree;
typedef ::Lock Lock;
}
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
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");
}
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());
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);
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;
PUBLIC inline
Mapping *
-Mapping_tree::lookup(Space *space, Page_number page)
+Mapping_tree::lookup(Space *space, Page page)
{
Mapping *m;
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();
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)
// 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;
}
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)
#include "per_cpu_data.h"
#include "ram_quota.h"
#include "types.h"
+#include "mapdb_types.h"
class 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);
* 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.
*
* 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.
*
* @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();
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;
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;
};
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 *
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
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();
}
};
//----------------------------------------------------------------------------
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; }
#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; }
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 >
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
{
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,
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 *)
-{}
--- /dev/null
+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); }
+
--- /dev/null
+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 *) {}
+}
--- /dev/null
+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); }
+
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 {
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 {
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)
{
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());
}
//---------------------------------------------------------------------------
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
}
+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;
};
#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__) \
{
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;
public:
typedef T Type;
- T const &cpu(unsigned) const;
- T &cpu(unsigned);
+ T const &cpu(Cpu_number) const;
+ T &cpu(Cpu_number);
T const ¤t() const { return cpu(current_cpu()); }
T ¤t() { return cpu(current_cpu()); }
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:
return *this;
}
- T &cpu(unsigned cpu);
+ T &cpu(Cpu_number cpu);
T ¤t() { return cpu(current_cpu()); }
private:
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 >
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
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__[];
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__[];
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
{
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;
};
#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[];
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
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);
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;
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);
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__);
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__);
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; }
#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[];
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;
}
_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]);
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());
}
INTERFACE:
+#include <types.h>
+
/**
* Encapsulation of the platforms interrupt controller
*/
* @param irq IRQ.
* @param cpu Logical CPU.
*/
- static void set_cpu(unsigned irq, unsigned cpu);
+ static void set_cpu(unsigned irq, Cpu_number cpu);
};
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; }
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())
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))
}
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())
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))
}
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);
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
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);
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
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;
};
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)
_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; }
PRIVATE inline NEEDS["globals.h"]
Kernel_task::Kernel_task()
-: Task(Ram_quota::root, Kmem::kdir())
+: Task(Ram_quota::root, Kmem::kdir(), Caps::none())
{}
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 );
//---------------------------------------------------------------------------
IMPLEMENTATION [ppc32]:
-#include "mem_layout.h"
#include "paging.h"
#include "panic.h"
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)
{
return kdir()->virt_to_phys(a);
}
-//------------------------------------------------------------------------------
-/*
- * dummy implementations
- */
-
IMPLEMENT inline
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;
}
}
}
+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]:
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);
};
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 =
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;
e = 0;
return ret;
+#else
+ (void)e; (void)page_attribs;
+ return 0;
+#endif
}
{
// 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);
}
{
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);
else
ret = pte_attrib_upgrade(e2->raw(), page_attribs);
}
+#endif
return ret;
}
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);
Mem_unit::tlb_flush(pte_phys->pte_to_ea());
Mem_unit::sync();
return ret;
+#endif
+ return 0;
}
IMPLEMENT inline NEEDS["kmem.h"]
{
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
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,
return false;
_dir = static_cast<Dir_type*>(b);
- _dir->clear(); // initialize to zero
+ //check//_dir->clear(); // initialize to zero
return true; // success
}
: _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
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)
return r;
}
+#endif
PUBLIC inline NEEDS["cpu.h"]
static bool
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);
// 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;
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);
}
*/
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())
status = v_insert_cache(&e, virt, Config::PAGE_SIZE, 0, dir);
if(EXPECT_FALSE(status != Insert_ok))
+#endif
return false;
return true;
*/
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;
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
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);
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;
+}
#include "types.h"
class PF {};
+class Page {};
//------------------------------------------------------------------------------
INTERFACE[ppc32]:
class Paging {};
-class Pte_base
+class Pte_ptr
{
- public:
- typedef Mword Raw;
+public:
enum
{
Super_level = 0,
// 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,
};
-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;
//---------------------------------------------------------------------------
-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;
}
Pte_base &
Pte_base::operator = (Mword raw)
{
- _raw = raw;
+ *pte = raw;
return *this;
}
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;
+//}
//------------------------------------------------------------------------------
/*
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
{
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);
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; }
+
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");
}
*(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();
}
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);
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"
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);
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;
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;
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");
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;
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; }
};
INTERFACE:
#include <cassert>
-#include <dlist>
-#include <hlist>
+#include <cxx/dlist>
+#include <cxx/hlist>
#include "member_offs.h"
#include "spin_lock.h"
#include "types.h"
INTERFACE:
#include "mem_layout.h"
+//#include <cstdio>
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; }
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
{
static unsigned idx(Address virt)
{
if (Mask)
- return (virt >> Shift) & ~(~0UL << Size);
+ return cxx::get_lsb(virt >> Shift, (Address)Size);
else
return (virt >> Shift);
}
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;
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];
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:
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;
- 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
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
<
> 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
>
{
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 >
#include "spin_lock.h"
#include "queue_item.h"
#include "kdb_ke.h"
-#include <dlist>
+#include <cxx/dlist>
class Queue
{
INTERFACE:
-#include <dlist>
+#include <cxx/dlist>
class Queue;
#include "cpu_mask.h"
#include "per_cpu_data.h"
#include "spin_lock.h"
-#include <slist>
+#include <cxx/slist>
class Rcu_glbl;
class Rcu_data;
long _len;
Rcu_list _c;
Rcu_list _d;
- unsigned _cpu;
+ Cpu_number _cpu;
};
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
{
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);
}
{}
PUBLIC
-Rcu_data::Rcu_data(unsigned cpu)
+Rcu_data::Rcu_data(Cpu_number cpu)
: _idle(true),
_cpu(cpu)
{}
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))
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))
PRIVATE inline NOEXPORT
void
-Rcu_glbl::cpu_quiet(unsigned cpu)
+Rcu_glbl::cpu_quiet(Cpu_number cpu)
{
_cpus.clear(cpu);
if (_cpus.empty())
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);
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())
PUBLIC static inline
bool
-Rcu::do_pending_work(unsigned cpu)
+Rcu::do_pending_work(Cpu_number cpu)
{
if (pending(cpu))
{
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"
{ 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).
INTERFACE [sched_fixed_prio]:
-#include <dlist>
+#include <cxx/dlist>
#include "member_offs.h"
#include "types.h"
#include "globals.h"
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);
+}
+
+
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);
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);
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
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)
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;
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())
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;
}
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; }
};
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)); }
#include "spin_lock.h"
#include "ref_obj.h"
#include "slab_cache.h"
-#include <slist>
+#include <cxx/slist>
class Ram_quota;
class Context;
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
}
};
+ 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;
return 0;
}
-PUBLIC inline
+PUBLIC inline NEEDS["kdb_ke.h"]
void
Space::switchin_context(Space *from)
{
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
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;
};
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)
_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; }
PRIVATE inline NEEDS["globals.h"]
Kernel_task::Kernel_task()
-: Task(Ram_quota::root, Kmem::kdir())
+: Task(Ram_quota::root, Kmem::kdir(), Caps::none())
{}
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;
}
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 );
//---------------------------------------------------------------------------
IMPLEMENTATION [sparc]:
-#include "mem_layout.h"
#include "paging.h"
#include "panic.h"
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)
{
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*/ )
{
alloc_size -= f.size();
}
}
+
+PUBLIC inline
+Address
+Kmem_alloc::to_phys(void *v) const
+{
+ // FIX
+ (void)v;
+ return ~0UL;
+}
+
//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,
{
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;
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
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,
return false;
_dir = static_cast<Dir_type*>(b);
- _dir->clear(); // initialize to zero
+ _dir->clear(true); // initialize to zero
return true; // success
}
: _quota(q), _dir(pdir)
{
_kernel_space = this;
- _current.cpu(0) = this;
+ _current.cpu(Cpu_number::boot_cpu()) = this;
}
IMPLEMENT inline
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"]
//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
// 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;
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);
}
*/
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);*/
*/
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;
}
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)
+{}
#include "config.h"
class PF {};
+class Page {};
//------------------------------------------------------------------------------
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
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:
_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;
return addr;
}
-//---------------------------------------------------------------------------
IMPLEMENT inline
Mword PF::is_translation_error(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
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)
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());
kernel_srmmu_l1[superpage] = pte.raw();
/* 1:1 mapping */
kernel_srmmu_l1[Pte_base::pdir(memstart)] = pte.raw();
+#endif
memstart += (1 << 24);
++superpage;
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");
};
};
-/** 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
Unsigned16 _error;
Mword _cpsr, _sp;
};
+public:
+ unsigned print(int max, char *buf) const;
};
// --------------------------------------------------------------------
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
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
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;
}
-
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);
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;
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;
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;
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");
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;
public Return_frame
{
public:
- typedef int (*Handler)(Trap_state*, unsigned cpu);
+ typedef int (*Handler)(Trap_state*, Cpu_number cpu);
bool exclude_logging() { return false; }
};
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();
{
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))
// 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;
}
}
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))
{
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);
* \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();
}
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);
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;
{
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();
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;
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();
}
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();
}
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))
{
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
{
_ctx = ctx;
_ip = ip;
_kclock = (Unsigned32)Kip::k()->clock;
- _cpu = current_cpu();
+ _cpu = cxx::int_value<Cpu_number>(current_cpu());
}
PUBLIC inline
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
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
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;
};
};
};
Syscall_frame *_snd_regs;
- unsigned char _ipc_send_rights;
+ L4_fpage::Rights _ipc_send_rights;
};
class Buf_utcb_saver
L4_msg_tag tag;
Thread *partner;
Syscall_frame *regs;
- unsigned char rights;
+ L4_fpage::Rights rights;
bool timeout;
bool have_rcv;
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,
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);
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());
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();
*/
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);
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();
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))
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());
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;
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);
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());
// 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;
PRIVATE inline
void
-Thread::set_ipc_send_rights(unsigned char c)
+Thread::set_ipc_send_rights(L4_fpage::Rights c)
{
_ipc_send_rights = c;
}
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
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));
}
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");
}
+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)
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);
{
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;
}
}
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...
}
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;
}
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();
}
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();
rq.ready_enqueue(sched());
enqueue_timeout_again();
+
+ return false;
}
PUBLIC
{
Mword state;
Address user_ip;
- unsigned src_cpu;
- unsigned target_cpu;
+ Cpu_number src_cpu;
+ Cpu_number target_cpu;
unsigned print(int, char *) const;
};
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
rq.set_current_sched(current()->sched());
}
- unsigned target_cpu = inf->cpu;
+ Cpu_number target_cpu = inf->cpu;
{
Queue &q = _pending_rqq.cpu(cpu());
}
PRIVATE inline
-void
-Thread::migrate_to(unsigned target_cpu)
+bool
+Thread::migrate_to(Cpu_number target_cpu, bool remote)
{
bool ipi = false;
&& 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())
{
//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;
// 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 !!!!
}
if (ipi)
Ipi::send(Ipi::Request, current_cpu(), cpu);
- return;
+
+ return false;
}
//----------------------------------------------------------------------------
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);
}
-
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)
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;
}
if (!self())
return 0;
- if (rights) *rights = L4_fpage::RWX;
+ if (rights) *rights = L4_fpage::Rights::RWX();
return current_thread();
}
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))
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())
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);
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);
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))
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)
{
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)
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())
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);
INTERFACE:
-#include <hlist>
+#include <cxx/hlist>
#include "l4_types.h"
#include "per_cpu_data.h"
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);
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);
IMPLEMENT
void
-Timer::init(unsigned)
+Timer::init(Cpu_number)
{
hpet_irq = -1;
if (!Hpet::init())
* 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.
/**
* Advances the system clock.
*/
- static void update_system_clock(unsigned cpu);
+ static void update_system_clock(Cpu_number cpu);
/**
* Get the current system clock.
*/
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;
--- /dev/null
+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());
+}
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);
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());
}
INTERFACE:
#include "irq_chip.h"
+#include "thread.h"
class Timer_tick : public Irq_base
{
}
}
- 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);
// ------------------------------------------------------------------------
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"]
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;
}
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); }
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
static Mword _kern_ds asm ("KERN_DS");
static Mword _kern_es asm ("KERN_ES");
- int _tid;
+ Cpu_phys_id _tid;
};
// -----------------------------------------------------------------------
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; }
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()); }
PRIVATE static
void
-Fpu::init_xsave(unsigned)
+Fpu::init_xsave(Cpu_number)
{}
PRIVATE static
// 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());
}
/**
// 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());
}
/**
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;
}
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);
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);
}
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
// 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));
{
// 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));
#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))
{
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];
}
"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);
*(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();
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 (;;)
{
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;
}
// 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);
}
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;
};
// ------------------------------------------------------------------------
#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;
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))
startup_system1()
{
Kconsole::init();
- Usermode::init(0);
+ Usermode::init(Cpu_number::boot_cpu());
Boot_info::init();
Config::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();
Kmem::init_mmu(*Cpu::boot_cpu());
Kernel_task::init(); // enables current_mem_space()
Kip_init::init_freq(*Cpu::boot_cpu());
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();
{
//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()));
}
// 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);
IMPLEMENT FIASCO_INIT_CPU
void
-Timer::init(unsigned)
+Timer::init(Cpu_number)
{
if (Boot_info::irq0_disabled())
return;
*/
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
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;
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;
*/
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;
*/
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];
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 */
{
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
set_signal (SIGSEGV);
set_signal (SIGIO);
- if (cpu == 0)
+ if (cpu == Cpu_number::boot_cpu())
set_signal (SIGINT);
else
signal (SIGINT, SIG_IGN);
IMPLEMENTATION [!debug && serial]:
#include "kernel_console.h"
-#include "kernel_uart.h"
static Console *uart = Kconsole::console()->find_console(Console::UART);
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]);
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;
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);
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();
.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 = .;
return ret;
}
-
-inline
-bool
-tas (Mword *l)
-{
- Mword tmp;
- asm volatile ("xchg %0, %1" : "=r"(tmp) : "m"(*l), "0"(1) : "memory");
- return tmp;
-}
-
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));
}
-
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)]:
--- /dev/null
+// 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; } \
+ /** @} */
+
+}
--- /dev/null
+/*
+ * (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;
+};
+
+}}
+
--- /dev/null
+// 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
+
--- /dev/null
+// 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;
+};
+
+}
+
--- /dev/null
+// 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) {}
+};
+
+}
--- /dev/null
+// 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;
+};
+
+}
--- /dev/null
+// 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;
+};
+
+}
--- /dev/null
+// 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;
+};
+
+
+}
+
--- /dev/null
+// 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];
+};
+
+}
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)
{
INTERFACE:
-#include <type_traits>
+#include <cxx/type_traits>
//
// Regular lock-guard policy, lock on ctor, unlock/reset in dtor
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
#pragma once
-#include <type_traits>
+#include <cxx/type_traits>
namespace cxx
{
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
{
_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);
+ }
};
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;
# 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_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_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_SCHED_WFQ=y
# CONFIG_SCHED_FP_WFQ is not set
# CONFIG_DISABLE_VIRT_OBJ_SPACE is not set
+CONFIG_VIRT_OBJ_SPACE=y
#
# Debugging
# 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
# 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
# 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_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
# 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
# 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
--- /dev/null
+#
+# 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"
--- /dev/null
+#
+# 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"
# 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
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
# 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
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
CONFIG_CONTEXT_4K=y
# CONFIG_FINE_GRAINED_CPUTIME is not set
CONFIG_SCHED_FIXED_PRIO=y
+CONFIG_VIRT_OBJ_SPACE=y
#
# Debugging
# 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
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
CONFIG_CONTEXT_4K=y
# CONFIG_FINE_GRAINED_CPUTIME is not set
CONFIG_SCHED_FIXED_PRIO=y
+CONFIG_VIRT_OBJ_SPACE=y
#
# Debugging
# 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
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
CONFIG_CONTEXT_4K=y
# CONFIG_FINE_GRAINED_CPUTIME is not set
CONFIG_SCHED_FIXED_PRIO=y
+CONFIG_VIRT_OBJ_SPACE=y
#
# Debugging
# 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
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
# 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
# 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
# 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
# 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
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
CONFIG_CONTEXT_4K=y
# CONFIG_FINE_GRAINED_CPUTIME is not set
CONFIG_SCHED_FIXED_PRIO=y
+CONFIG_VIRT_OBJ_SPACE=y
#
# Debugging
# 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
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
# 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_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
# 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
# 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
# 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
# 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
CONFIG_CONTEXT_4K=y
# CONFIG_FINE_GRAINED_CPUTIME is not set
CONFIG_SCHED_FIXED_PRIO=y
+CONFIG_VIRT_OBJ_SPACE=y
#
# Debugging
# 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
# 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
CONFIG_CONTEXT_4K=y
# CONFIG_FINE_GRAINED_CPUTIME is not set
CONFIG_SCHED_FIXED_PRIO=y
+CONFIG_VIRT_OBJ_SPACE=y
#
# Debugging
# 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
# 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
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
# 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
# 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
# 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
# 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
# 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
CONFIG_CONTEXT_4K=y
# CONFIG_FINE_GRAINED_CPUTIME is not set
CONFIG_SCHED_FIXED_PRIO=y
+CONFIG_VIRT_OBJ_SPACE=y
#
# Debugging
# 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
# 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
# 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_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
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
# 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
# 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
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
CONFIG_CONTEXT_4K=y
# CONFIG_FINE_GRAINED_CPUTIME is not set
CONFIG_SCHED_FIXED_PRIO=y
+CONFIG_VIRT_OBJ_SPACE=y
#
# Debugging
# CONFIG_SYNC_TSC is not set
# CONFIG_FINE_GRAINED_CPUTIME is not set
CONFIG_SCHED_FIXED_PRIO=y
+CONFIG_VIRT_OBJ_SPACE=y
#
# Debugging
# 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_SYNC_TSC is not set
# CONFIG_FINE_GRAINED_CPUTIME is not set
CONFIG_SCHED_FIXED_PRIO=y
+CONFIG_VIRT_OBJ_SPACE=y
#
# Debugging
# 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
# 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_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
--- /dev/null
+#
+# 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"
--- /dev/null
+#
+# 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"
# CONFIG_UX_CON is not set
# CONFIG_UX_NET is not set
CONFIG_SCHED_FIXED_PRIO=y
+CONFIG_VIRT_OBJ_SPACE=y
#
# Debugging
# CONFIG_SCHED_FIXED_PRIO is not set
CONFIG_SCHED_WFQ=y
# CONFIG_SCHED_FP_WFQ is not set
+CONFIG_VIRT_OBJ_SPACE=y
#
# Debugging
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
# CONFIG_UX_CON is not set
# CONFIG_UX_NET is not set
CONFIG_SCHED_FIXED_PRIO=y
+CONFIG_VIRT_OBJ_SPACE=y
#
# Debugging
#include "static_init.h"
#include "usermode.h"
#include "vmem_alloc.h"
-#include "mem_space_sigma0.h"
IMPLEMENTATION:
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;
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()
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);
// 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
//
print_node (m, frame);
mapdb->free (frame);
#endif
- cerr << "... ";
//
//
// 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
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;
node = i;
if (node)
{
- size = i.shift();
+ size = i.order();
++i;
}
}
- cout << endl;
+ cout << "[UTEST] " << endl;
}
--- /dev/null
+[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]
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);
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);
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);
}
#include "per_cpu_data_alloc.h"
#include "static_init.h"
#include "usermode.h"
-#include "vmem_alloc.h"
class Timeout;
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());
}
{
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);
--- /dev/null
+[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] ########################################
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
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__
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
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
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
#ifdef __cplusplus
-#include <type_traits>
+#include <cxx/cxx_int>
+#include <cxx/type_traits>
#include <new>
template< typename a, typename b > inline
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
{
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
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
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"
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) \
-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
# ---------------------------------------------------------------------------
$(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
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
#
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) \
-kconfig taken from vanilla Linux 3.7, and slightly patched.
+kconfig taken from vanilla Linux 3.8, and slightly patched.
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
# ---------------------------------------------------------------------------
--- /dev/null
+PLATFORM_NAME = "Raspberry Pi, Model A"
+PLATFORM_ARCH = arm
+PLATFORM_RAM_BASE = 0x0
+PLATFORM_RAM_SIZE_MB = 256
--- /dev/null
+PLATFORM_NAME = "Raspberry Pi, Model B"
+PLATFORM_ARCH = arm
+PLATFORM_RAM_BASE = 0x0
+PLATFORM_RAM_SIZE_MB = 512
--- /dev/null
+PLATFORM_NAME = "ARM Versatile Express"
+PLATFORM_ARCH = arm
+PLATFORM_RAM_BASE = 0x80000000
+PLATFORM_RAM_SIZE_MB = 256
* 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 */
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:
str r6, [r7, #-4]! /* Put bytes */
cmp r5, r7
blt 3b
- ldr pc, .LCrun
+ ldr pc, .LCrun
.LCrun: .word 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 */
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 */
#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
.space 4
.global crt0_stack_low
- .align 3
+ .align 3
crt0_stack_low:
.space 8192
.global crt0_stack_high
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
--- /dev/null
+
+# 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
--- /dev/null
+/*!
+ * \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);
* \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>
*
*/
/*
* \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>
*
*/
/*
* \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>
*
*/
/*
* \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>
*
*/
/*
* \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>
*
*/
/*
* \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>
*
*/
/*
--- /dev/null
+/*!
+ * \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);
* \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>
*
*/
/*
* \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>
*
*/
/*
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);
* \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>
*
*/
/*
* \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>
*
*/
/*
* \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>
*
*/
/*
}
}
+ 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;
}
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);
{
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);
std_alloc \
std_ops \
std_tmpl \
- type_traits
+ type_traits \
+ type_list \
+ bitfield \
+ utils
include $(L4DIR)/mk/include.mk
--- /dev/null
+// 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; } \
+ /** @} */
+
+}
+
--- /dev/null
+// 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;
+};
+
+}
+
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;
+};
+
+
}
--- /dev/null
+#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));
+}
+
+
+}
+
_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 */
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
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
/*
- * (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
{ 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;
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);
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);
}
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)
{
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)
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
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");
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),
}
// 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;
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;
*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;
}
" nop \n"
" nop \n"
" addl %%edx,%%eax \n"
- " ud2 \n"
+// " ud2 \n"
" addl %%edx,%%eax \n"
" int3 \n"
"3: nop \n"
"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"
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);
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
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");
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
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
#include "resource.h"
#include <cstdio>
+#include <cstring>
template< typename D >
class Device_tree
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); }
#pragma once
+#include "debug.h"
#include "hw_device.h"
+#include "resource.h"
#include <l4/vbus/vbus_gpio.h>
namespace Hw {
};
}
+
+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;
+};
#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)");
+}
#include "vdevice.h"
#include "vbus_factory.h"
#include "hw_device.h"
+#include "gpio"
static int is_lua_propval(lua_State *L, int idx)
{
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
Device *next() const;
int depth() const;
void plugin();
+
+ void dump(int) const;
};
class Device_factory
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 = {}
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
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
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
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
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
/* ----------------------------------------------------------------------------
* 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
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;
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
* ----------------------------------------------------------------------------- */
/* 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)
{
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 */
#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()
*/
#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)
#include "vdevice.h"
#include "vbus_factory.h"
#include "hw_device.h"
+#include "gpio"
static int is_lua_propval(lua_State *L, int idx)
{
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
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");
{"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},
" 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 *");
{"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}
};
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 *");
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;
{"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[] = {
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
{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)},
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};
&_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,
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}};
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}};
_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,
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) {
"\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"
" 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"
" 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"
"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"
"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"
switch (c)
{
case 'v':
- _my_cfg.inc_verbosity();
+ cfg->inc_verbosity();
break;
case OPT_TRANSPARENT_MSI:
d_printf(DBG_INFO, "Enabling transparent MSIs\n");
Irq_res = L4VBUS_RESOURCE_IRQ,
Mmio_res = L4VBUS_RESOURCE_MEM,
Io_res = L4VBUS_RESOURCE_PORT,
- Bus_res
+ Bus_res,
+ Gpio_res
};
enum Flags
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)
#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
{
_bus->add_child(_icu);
_bus->sw_icu(_icu);
-}
+ }
bool request(Resource *parent, Device *, Resource *child, Device *)
{
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()
#include <l4/cxx/avl_set>
#include <l4/cxx/ipc_server>
+#include <l4/cxx/hlist>
#include <l4/vbus/vbus_types.h>
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();
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();
}
};
Resource_set _resources;
Device *_host;
Sw_icu *_sw_icu;
+
};
}
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;
*/
+#include "debug.h"
#include "gpio"
#include "hw_device.h"
#include "vdevice.h"
#include "vbus.h"
#include "vicu.h"
+#include <vector>
+
#include <l4/vbus/vbus_gpio-ops.h>
#include <cerrno>
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; }
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;
}
}
#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
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__
-
* 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>
*/
#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;
}
* \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
*/
#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,
};
/**
*/
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.
*/
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];
}
* \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>
*
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),
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
};
The dist/ directory contains the unmodified contents of
-libpng-1.6.0.tar.gz.
+libpng-1.6.1.tar.gz.
-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.
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
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
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
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})
# 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")
# 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")
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()
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()
# 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)
# 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)
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:
depcomp, install-sh, mkinstalldirs, test-pngtest.sh
contrib
gregbook
+ libtests
pngminim
pngminus
pngsuite
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
Glenn Randers-Pehrson
glennrp at users.sourceforge.net
-February 14, 2013
+March 28, 2013
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
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
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)
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
$(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 \
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
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)
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
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
$(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)
-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)
"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)
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
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)
-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.
#
# 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\
/* 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
#! /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>.
#
# 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=''
# 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]...
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
--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]
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.
} # 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
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 $@
# 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=
# Define the identity of the package.
PACKAGE='libpng'
- VERSION='1.6.0'
+ VERSION='1.6.1'
cat >>confdefs.h <<_ACEOF
-# 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; }
-PNGLIB_VERSION=1.6.0
+PNGLIB_VERSION=1.6.1
PNGLIB_MAJOR=1
PNGLIB_MINOR=6
-PNGLIB_RELEASE=0
+PNGLIB_RELEASE=1
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 :
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
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
-# 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
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
# 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
# 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
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\\"
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')
# 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
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
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
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
# 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
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]])
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
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
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
...
#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
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");
"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 */
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
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.
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).
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
-.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
.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
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
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
...
#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
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");
"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 */
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
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.
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).
.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
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
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).
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
Glenn Randers-Pehrson
glennrp at users.sourceforge.net
-February 14, 2013
+March 28, 2013
.\" end of man page
-.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"
-.TH PNG 5 "February 14, 2013"
+.TH PNG 5 "March 28, 2013"
.SH NAME
png \- Portable Network Graphics (PNG) format
.SH DESCRIPTION
/* 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.)
#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
#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.";
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;
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)
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")
};
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);
#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
}
#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)
#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)
{
/* 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.)
* 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.
/* 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.
*
#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
* 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));
#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
* 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:
* 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
* 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
* ---------
* 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.
# 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
*/
* scripts/symbols.def as well.
*/
#ifdef PNG_EXPORT_LAST_ORDINAL
- PNG_EXPORT_LAST_ORDINAL(243);
+ PNG_EXPORT_LAST_ORDINAL(244);
#endif
#ifdef __cplusplus
/* 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
/* 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.)
/* 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
}
# 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
}
#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:
/* 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.)
*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);
}
#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)
/* 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
* 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
* (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*/
* 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: */
#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.
# 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.
*/
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
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
#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
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.
*/
#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
{
#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
}
#endif
+#endif /* PNG_VERSION_INFO_ONLY */
#endif /* PNGPRIV_H */
/* 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.)
*/
#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
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
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
{
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;
/* 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.)
#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.
*
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
/* 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.)
*/
#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.
/* 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.)
*
{
/* 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.
+ * A 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;
}
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
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
/* 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.)
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)
}
}
+ 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.
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;
* 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");
* (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
} 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
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
/* 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
/* 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.)
/* 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);
#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;
/* 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.)
*/
#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
-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
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
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
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
* 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"
--- /dev/null
+#!/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
+}
*/
#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"
# Modeled after libxml-config.
-version=1.6.0
+version=1.6.1
prefix=""
libdir=""
libs=""
Name: libpng
Description: Loads and saves PNG files
-Version: 1.6.0
+Version: 1.6.1
Libs: -L${libdir} -lpng16
Cflags: -I${includedir}
VERMAJ = 1
VERMIN = 6
-VERMIC = 0
+VERMIC = 1
VER = $(VERMAJ).$(VERMIN).$(VERMIC)
NAME = libpng
PACKAGE = $(NAME)-$(VER)
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
# Library name:
LIBNAME = libpng16
PNGMAJ = 16
-RELEASE = 0
+RELEASE = 1
# Shared library names:
LIBSO=$(LIBNAME).so
# Library name:
LIBNAME = libpng16
PNGMAJ = 16
-RELEASE = 0
+RELEASE = 1
# Shared library names:
LIBSO=$(LIBNAME).dll
#ARCH = -march=pentium3
#ARCH = -march=i686
-ARCH =
+ARCH =
CDEBUG = -g -DPNG_DEBUG=5
LDDEBUG =
CRELEASE = -O2
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
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
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 \
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
# 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)
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:
# 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
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
}
# 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
pre && version == "search" && $0 ~ /^ \* libpng version/{
version = substr($0, 4)
- gsub(/\./, " PNG_JOIN . PNG_JOIN", version)
print "version =", version >out
next
}
if (NF > 1) {
# sub(/^[ ]*com[ ]*/, "")
$1 = ""
- print comment, $0, cend >out
+ print comment $0, cend >out
} else
print start end >out
next
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
# 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
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!
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
}
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
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
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
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
}
}
# 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
# 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.
# - 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
@# 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!)
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
# 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
# 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
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
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
# 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
# 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*
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
chunk sBIT
chunk sCAL
chunk sPLT
-chunk sRGB enables COLORSPACE GAMMA
+chunk sRGB enables COLORSPACE, GAMMA
chunk tEXt requires TEXT
chunk tIME
chunk tRNS
# 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
#
# 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
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
# 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
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
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
-
-/* 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 */
#
# 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).
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:
# 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
*/
#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
*/
#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"
+;Version 1.6.1
;--------------------------------------------------------------
; LIBPNG symbol list as a Win32 DEF file
; Contains all the symbols that can be exported from libpng
LIBRARY
EXPORTS
-;Version 1.6.0
png_access_version_number @1
png_set_sig_bytes @2
png_sig_cmp @3
png_convert_to_rfc1123_buffer @241
png_set_check_for_invalid_index @242
png_get_palette_max @243
+ png_set_option @244
*/
#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"
* 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: *; };"
--- /dev/null
+#! /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:
#pragma once
-#include <pthread-l4.h>
#include <errno.h>
#define SYS_MBOX_NULL NULL
/* ----------------------------------------------------------------------------
* 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
* ----------------------------------------------------------------------------- */
#define SWIGLUA
-#define SWIG_LUA_TARGET SWIG_LUA_FLAVOR_LUA
-#define SWIG_LUA_MODULE_GLOBAL
#ifdef __cplusplus
/*
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).
#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
#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
* ----------------------------------------------------------------------------- */
/* 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;
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 */
}
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 */
(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 */
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 */
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 */
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 */
}
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)
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)
{
/* 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) */
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
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)";
* 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[]) {
}
}
}
-#endif
/* -----------------------------------------------------------------------------
* executing lua code from within the wrapper
#define SWIG_LUACODE luaopen_Mag_luacode
+
namespace swig {
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)
}\
}
-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);
#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);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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++;
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);
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);
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);
_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);
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);
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);
{"set", _wrap_Valuatori_set},
{"inv", _wrap_Valuatori_inv},
{"size", _wrap_Valuatori_size},
+ {"offset", _wrap_Valuatori_offset},
{"__getitem", _wrap_Valuatori___getitem},
{0,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; }
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;
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; }
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:
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);
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);
_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);
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);
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);
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);
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);
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);
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);
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);
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);
_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);
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);
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();
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();
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))){
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);
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))){
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))){
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))){
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++;
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))){
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);
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")
// 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}
};
#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);
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));
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
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
}
+#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 {
} 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;
}
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
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)
*/
static inline void rep_function_save_regs(void)
{
+#if 0
BARRIER();
asm volatile ("mov %%ebx, %0\t\n"
"mov %%ecx, %1\t\n"
:
: "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"
"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)
attribute_hidden
pthread_mutex_lock_rep(pthread_mutex_t * mutex)
{
+
rep_function_save_regs();
/*
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);
}
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;
}
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) {
#include <l4/plr/pthread_rep.h>
EXTERN_C_END
+lock_info* __lip_address = reinterpret_cast<lock_info*>(LOCK_INFO_ADDR);
+
namespace Romain
{
/*
enter_kdebug("unhandled pf");
}
+ Romain::Observer::ObserverReturnVal retVal = Romain::Observer::Finished;
L4vcpu::Vcpu *vcpu = t->vcpu();
bool write_pf = vcpu->r()->err & 0x2;
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
*/
++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)) {
*/
MSGt(t) << "Page faults so far: mapped " << pf_mapped << " write emu " << pf_write << " kip " << pf_kip;
- return Romain::Observer::Finished;
+ return retVal;
}
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;
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();
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);
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.";
}
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);
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);
}
/* 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);
#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>
};
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)
{}
_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);
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;
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.
*
*/
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); }
: 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;
}
void release()
{
_active_instance = Invalid_inst;
+ pthread_mutex_unlock(&_mtx);
}
/*
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);
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);
}
* 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;
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'.
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)
* 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,
*/
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();
{
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
* 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
-#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())
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;
}
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?");
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
return 1;
}
-int
+static int
l4rtc_if_get_linux_tsc_scaler_component(l4_uint32_t *scaler)
{
#if defined ARCH_x86 || defined ARCH_amd64
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");
}
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.
#! /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
# 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
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'\" &&
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 :
} # 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
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).
# ... 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
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'"
# 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=''
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
# 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]...
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
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
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
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
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
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 $@
# 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.
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
# Define the identity of the package.
PACKAGE='sqlite'
- VERSION='3.7.15.2'
+ VERSION='3.7.16.1'
cat >>confdefs.h <<_ACEOF
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
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
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
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
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
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
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
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
/* 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);
esac
rm -rf conftest*
fi
+
+
fi
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
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
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
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
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
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
/* 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);
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
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
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
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
;;
*-*-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=$?
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
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
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
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
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
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
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
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
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
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
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
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
-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.
-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.
-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
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
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
-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.
-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
-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.
-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
-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.
-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.
-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
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) '* | \
# ... 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
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'"
# 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
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."
_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'
#
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.
#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>
}
#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
}
}
** 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;
}
/*
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 ){
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
/******************************************************************************
** 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
** [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
** [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],
#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
** 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>
**
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
/*
** 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.
** 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.
** 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_
*/
#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
#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 */
#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 */
/*
** 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 */
** 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 */
};
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 */
#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 */
/*
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);
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);
** 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
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*);
#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
#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
#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
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 */
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 */
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 *);
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*);
*/
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 */
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;
*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 */
** 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=='-' ){
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;
** 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[] = {
#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
{ "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 */
/*
*/
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);
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;
}
/******************************************************************************
************************* 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:
**
**
** 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.
*/
}
/* 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 ){
"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;
}
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:
**
}
/*
-** 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
/* 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++){
** 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[] = {
** (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. */
/*************************************************************************
** 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)
y.tm_sec = pTm.wSecond;
return &y;
}
+#endif
#define HANDLE_TO_WINFILE(a) (winFile*)&((char*)a)[-(int)offsetof(winFile,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 */
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 */
/* 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;
}
/*
}
/* 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;
}
/* 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;
/* 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)
{
}
/* 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;
}
}
/* 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;
** 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);
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; ); */
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 */
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;
(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);
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;
|| 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 ){
}
#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;
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;
}
}
}
- 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;
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;
}
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;
#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;
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;
}
/*
-** 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 */
*/
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
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);
#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;
/*
** 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.
** * 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.
**
**
** 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).
**
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 */
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
** 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 */
*/
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))
){
sqlite3EndBenignMalloc();
}else if( !pPager->exclusiveMode ){
assert( pPager->eState==PAGER_READER );
- pager_end_transaction(pPager, 0);
+ pager_end_transaction(pPager, 0, 0);
}
}
pager_unlock(pPager);
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 ){
** 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
** 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. */
}
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
#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.
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);
}
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);
}
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.
*/
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 );
}
#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 */
*/
#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
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.
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;
}
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);
}
}
}
** 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) );
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 ){
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;
}
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;
}
} 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;
}
}
- 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.
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);
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);
}
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 ){
return rc;
}
}
+ if( pBt->bDoTruncate ){
+ sqlite3PagerTruncateImage(pBt->pPager, pBt->nPage);
+ }
#endif
rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, 0);
sqlite3BtreeLeave(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
** 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;
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]);
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
/* 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;
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);
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{
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"
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++;
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);
*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 ){
** 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 ){
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.
** 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;
}
}
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
** 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);
*/
memcpy(zOut, zIn, nCopy);
((u8 *)sqlite3PagerGetExtra(pDestPg))[0] = 0;
+ if( iOff==0 && bUpdate==0 ){
+ sqlite3Put4byte(&zOut[28], sqlite3BtreeLastPage(p->pSrc));
+ }
}
sqlite3PagerUnref(pDestPg);
}
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);
}
}
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,
*/
const i64 iSize = (i64)pgszSrc * (i64)nSrcPage;
sqlite3_file * const pFile = sqlite3PagerFile(pDestPager);
+ Pgno iPg;
+ int nDstPage;
i64 iOff;
i64 iEnd;
&& 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);
rc = sqlite3PagerSync(pDestPager);
}
}else{
+ sqlite3PagerTruncateImage(pDestPager, nDestTruncate);
rc = sqlite3PagerCommitPhaseOne(pDestPager, 0, 0);
}
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 ){
** 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 );
** 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.
*/
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;
|| (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;
}
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
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
zEnd = &zCsr[nByte];
}while( nByte && !db->mallocFailed );
- p->nCursor = (u16)nCursor;
+ p->nCursor = nCursor;
p->nOnceFlag = nOnce;
if( p->aVar ){
p->nVar = (ynVar)nVar;
if( needXcommit && db->xCommitCallback ){
rc = db->xCommitCallback(db->pCommitArg);
if( rc ){
- return SQLITE_CONSTRAINT;
+ return SQLITE_CONSTRAINT_COMMITHOOK;
}
}
/* 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 ){
** 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;
**
** 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.
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
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;
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
}
** 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:
**
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);
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;
}
}
&& 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
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;
}
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;
}
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;
}
** 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++;
** 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 */
** 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;
/* 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;
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{
*/
-#ifndef SQLITE_OMIT_MERGE_SORT
typedef struct VdbeSorterIter VdbeSorterIter;
typedef struct SorterRecord SorterRecord;
return SQLITE_OK;
}
-#endif /* #ifndef SQLITE_OMIT_MERGE_SORT */
-
/************** End of vdbesort.c ********************************************/
/************** Begin file journal.c *****************************************/
/*
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;
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
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;
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++){
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
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 ){
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++){
}
}
+ /* 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.
*/
*/
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;
}
**
** 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:
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 ){
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;
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);
}
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 ){
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:
/* 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;
}
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;
}
}
}
- /* 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 ){
/* 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);
/* 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.
*/
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);
(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. */
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);
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);
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);
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;
}
** 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,
** 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);
}
/*
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) */
}
}
+/*
+** 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.
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 ),
** --------------------------
**
** 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.
** 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
** 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
** 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 */
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;
** 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 ){
** 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 ){
}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 ){
continue;
}
- if( locateFkeyIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
+ if( sqlite3FkLocateIndex(pParse, pTab, pFKey, &pIdx, &aiCol) ){
if( !isIgnoreErrors || db->mallocFailed ) return;
continue;
}
}
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]);
}
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++){
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);
}else{
zConsName = 0;
}
- sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC);
+ sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_CHECK,
+ onError, zConsName, P4_DYNAMIC);
}
sqlite3VdbeResolveLabel(v, allOk);
}
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: {
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;
}
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 ){
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*);
};
/*
#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;
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
};
/*
{ "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 },
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);
}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);
}
}
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);
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);
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);
}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 ){
}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]);
/* 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;
*/
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) ){
}
}
- /* 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.
*/
}
/*
-** 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){
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 */
){
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;
/* 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);
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);
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);
}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) );
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);
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;
#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;
}
/*
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;
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) ){
** 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) );
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);
/* 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.
assert(IsVirtual(pTab));
continue;
}
+ tableSeen = 1;
if( i>0 && zTName==0 ){
if( (pFrom->jointype & JT_NATURAL)!=0
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;
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);
}
}
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;
** 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
** 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;
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);
/* 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.
*/
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 */
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 */
#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 */
#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 */
#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 */
pWC->nTerm = 0;
pWC->nSlot = ArraySize(pWC->aStatic);
pWC->a = pWC->aStatic;
- pWC->vmask = 0;
pWC->wctrlFlags = wctrlFlags;
}
** 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
** 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 */
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 */
**
** 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:
** 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));
b |= getMask(pMaskSet, pOther->leftCursor);
}
indexable &= b;
- if( pOrTerm->eOperator!=WO_EQ ){
+ if( (pOrTerm->eOperator & WO_EQ)==0 ){
chngToIN = 0;
}else{
chngToIN &= b;
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
/* 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;
}
** 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 ){
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);
}
#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
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);
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;
testcase( (prereqLeft | extraRight) != prereqLeft );
pNew->prereqRight = prereqLeft | extraRight;
pNew->prereqAll = prereqAll;
- pNew->eOperator = operatorMask(pDup->op);
+ pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask;
}
}
/* 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
){
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 ){
){
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;
** 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++;
}
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. */
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++){
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
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().
}
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;
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);
}
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 */
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;
** 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 );
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 ){
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;
** 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);
** 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 );
** 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;
&& 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);
}
** 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)
** 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;
}
/* 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;
|| 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);
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);
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;
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);
}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;
** 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);
** 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 =
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;
}
}
}
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++){
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;
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;
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 ){
** 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
{
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 */
** 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);
*/
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++;
}
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
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,
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);
IdList* yy180;
struct {int value; int mask;} yy207;
u8 yy258;
+ u16 yy305;
struct LikeOp yy318;
TriggerStep* yy327;
ExprSpan yy342;
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;}
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;}
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;}
{
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);
}
}
}
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;
}
}
/* 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.
*/
sqlite3VtabRollback(db);
sqlite3EndBenignMalloc();
- if( db->flags&SQLITE_InternChanges ){
+ if( (db->flags&SQLITE_InternChanges)!=0 && db->init.busy==0 ){
sqlite3ExpirePreparedStatements(db);
sqlite3ResetAllSchemasOfConnection(db);
}
** 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)(
** 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.
**
}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;
}
/*
-** 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(
#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.
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;
** 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:
** 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
/*
** 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);
*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
**
** 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 */
){
p += sqlite3Fts3GetVarint32(p, &iCurrent);
}
+ if( bZero && &pList[nList]!=pEnd ){
+ memset(&pList[nList], 0, pEnd - &pList[nList]);
+ }
*ppList = pList;
*pnList = nList;
}
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;
}
if( isColFilter ){
- fts3ColumnFilter(pFilter->iCol, &pList, &nList);
+ fts3ColumnFilter(pFilter->iCol, 0, &pList, &nList);
}
if( !isIgnoreEmpty || nList>0 ){
** 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
**
** 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(
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
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;
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(
pRtree->zDb, pRtree->zName
);
rc = getIntFromStmt(db, zSql, &pRtree->iNodeSize);
+ if( rc!=SQLITE_OK ){
+ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
+ }
}
sqlite3_free(zSql);
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
** [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
** [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],
#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
** 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>
**
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
/*
** 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.
** 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.
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*);
};
/*
#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;
($file, $full);
}
+sub error($)
+{
+ print STDERR shift;
+ exit(1);
+}
+
# extract an entry with modules from a modules.list file
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'};
'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 );
$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;
} 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';
} 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
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;
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;
}
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;
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,
}
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 $?;