From 5bbb823c13f3ab1ab58878f96b35433a29882676 Mon Sep 17 00:00:00 2001 From: Darwin Date: Fri, 31 Aug 2018 05:44:42 +0000 Subject: [PATCH] xnu-4570.51.1 Imported from https://opensource.apple.com/tarballs/xnu/xnu-4570.51.1.tar.gz --- Makefile | 12 +- README.md | 10 +- bsd/bsm/audit_kevents.h | 1 - bsd/conf/files | 3 +- bsd/dev/arm/cpu_in_cksum.s | 29 +- bsd/dev/arm64/cpu_in_cksum.s | 29 +- bsd/dev/chud/chud_process.c | 36 - bsd/dev/dtrace/dtrace.c | 62 +- bsd/dev/dtrace/dtrace_glue.c | 54 +- bsd/dev/dtrace/fbt.c | 20 + bsd/dev/dtrace/sdt.c | 4 +- bsd/dev/dtrace/sdt_subr.c | 10 + bsd/dev/i386/fbt_x86.c | 14 + bsd/dev/monotonic.c | 4 +- bsd/kern/bsd_init.c | 8 + bsd/kern/kdebug.c | 44 +- bsd/kern/kern_authorization.c | 4 +- bsd/kern/kern_cs.c | 87 + bsd/kern/kern_descrip.c | 19 + bsd/kern/kern_event.c | 65 +- bsd/kern/kern_exec.c | 30 +- bsd/kern/kern_exit.c | 5 +- bsd/kern/kern_malloc.c | 26 +- bsd/kern/kern_memorystatus.c | 516 +++-- bsd/kern/kern_mib.c | 17 +- bsd/kern/kern_mman.c | 19 +- bsd/kern/kern_persona.c | 53 +- bsd/kern/kern_proc.c | 15 +- bsd/kern/kern_shutdown.c | 9 +- bsd/kern/kern_sig.c | 283 ++- bsd/kern/kern_sysctl.c | 70 +- bsd/kern/mach_loader.c | 20 +- bsd/kern/mach_loader.h | 4 +- bsd/kern/policy_check.c | 2 - bsd/kern/proc_info.c | 64 +- bsd/kern/pthread_shims.c | 9 +- bsd/kern/subr_eventhandler.c | 84 +- bsd/kern/sys_persona.c | 12 +- bsd/kern/sys_work_interval.c | 16 +- bsd/kern/trace_codes | 5 + bsd/kern/tty_dev.c | 52 +- bsd/kern/tty_ptmx.c | 1 + bsd/kern/uipc_mbuf.c | 59 +- bsd/kern/uipc_mbuf2.c | 50 +- bsd/kern/uipc_socket.c | 9 + bsd/kern/uipc_socket2.c | 6 +- bsd/libkern/crc16.c | 44 +- bsd/libkern/libkern.h | 23 + bsd/man/man2/fcntl.2 | 38 +- bsd/man/man2/fs_snapshot_create.2 | 12 +- bsd/man/man2/getattrlistbulk.2 | 3 + bsd/man/man2/getdirentries.2 | 6 +- bsd/miscfs/specfs/spec_vnops.c | 37 +- bsd/net/Makefile | 1 + bsd/net/bpf.c | 11 +- bsd/net/classq/classq_fq_codel.c | 30 +- bsd/net/classq/classq_fq_codel.h | 3 +- bsd/net/classq/classq_subr.c | 7 + bsd/net/classq/if_classq.h | 3 +- bsd/net/dlil.c | 228 +- bsd/net/dlil.h | 4 +- bsd/net/if.c | 179 +- bsd/net/if.h | 49 +- bsd/net/if_fake.c | 36 +- bsd/net/if_fake_var.h | 7 + bsd/net/if_gif.c | 6 +- bsd/net/if_ipsec.c | 148 +- bsd/net/if_ports_used.c | 675 ++++++ bsd/net/if_ports_used.h | 113 + bsd/net/if_stf.c | 14 +- bsd/net/if_utun.c | 140 +- bsd/net/if_var.h | 7 +- bsd/net/kpi_interface.c | 22 +- bsd/net/necp.c | 14 +- bsd/net/necp.h | 12 +- bsd/net/necp_client.c | 251 ++- bsd/net/net_stubs.c | 9 +- bsd/net/network_agent.c | 25 +- bsd/net/ntstat.c | 2 - bsd/net/pf.c | 5 +- bsd/net/pktsched/pktsched_tcq.c | 4 +- bsd/net/route.c | 49 +- bsd/net/route.h | 7 +- bsd/net/rtsock.c | 21 +- bsd/netinet/in_gif.c | 12 +- bsd/netinet/in_pcb.c | 11 +- bsd/netinet/in_pcblist.c | 9 +- bsd/netinet/in_tclass.c | 33 +- bsd/netinet/ip_divert.c | 12 +- bsd/netinet/ip_icmp.c | 25 +- bsd/netinet/ip_input.c | 11 +- bsd/netinet/kpi_ipfilter.c | 18 +- bsd/netinet/mp_pcb.c | 4 +- bsd/netinet/mptcp.c | 116 +- bsd/netinet/mptcp_opt.c | 30 +- bsd/netinet/mptcp_subr.c | 245 +- bsd/netinet/mptcp_timer.c | 11 +- bsd/netinet/mptcp_usrreq.c | 62 +- bsd/netinet/mptcp_var.h | 9 + bsd/netinet/raw_ip.c | 11 +- bsd/netinet/tcp.h | 2 + bsd/netinet/tcp_cache.c | 5 +- bsd/netinet/tcp_input.c | 10 +- bsd/netinet/tcp_output.c | 32 +- bsd/netinet/tcp_subr.c | 27 +- bsd/netinet/tcp_timer.c | 1 + bsd/netinet/tcp_usrreq.c | 53 +- bsd/netinet/udp_usrreq.c | 12 +- bsd/netinet6/icmp6.c | 24 +- bsd/netinet6/in6_pcb.c | 10 +- bsd/netinet6/in6_src.c | 89 +- bsd/netinet6/ip6_input.c | 21 +- bsd/netinet6/ipsec.c | 21 +- bsd/netinet6/nd6.c | 32 +- bsd/netinet6/nd6_nbr.c | 40 +- bsd/netinet6/nd6_rtr.c | 12 +- bsd/netinet6/raw_ip6.c | 9 +- bsd/netinet6/udp6_output.c | 9 +- bsd/netkey/key.c | 11 +- bsd/nfs/krpc_subr.c | 11 +- bsd/nfs/nfs_boot.c | 35 +- bsd/nfs/nfs_socket.c | 11 +- bsd/nfs/nfs_vfsops.c | 2 + bsd/security/audit/audit_bsd.c | 7 +- bsd/sys/bsdtask_info.h | 3 - bsd/sys/cdefs.h | 8 +- bsd/sys/codesign.h | 5 + bsd/sys/cprotect.h | 1 + bsd/sys/dtrace_glue.h | 3 - bsd/sys/eventhandler.h | 33 +- bsd/sys/kdebug.h | 21 +- bsd/sys/mbuf.h | 1 + bsd/sys/persona.h | 3 +- bsd/sys/priv.h | 4 +- bsd/sys/proc.h | 3 +- bsd/sys/proc_info.h | 9 +- bsd/sys/proc_internal.h | 4 + bsd/sys/reason.h | 1 + bsd/sys/socket.h | 1 + bsd/sys/socketvar.h | 1 - bsd/sys/sockio.h | 6 +- bsd/sys/sysctl.h | 39 +- bsd/sys/syslog.h | 2 +- bsd/sys/systm.h | 1 + bsd/sys/work_interval.h | 7 +- bsd/vfs/vfs_cluster.c | 18 +- bsd/vfs/vfs_cprotect.c | 41 +- bsd/vfs/vfs_subr.c | 15 +- bsd/vfs/vfs_syscalls.c | 62 +- bsd/vm/vm_unix.c | 205 +- config/IOKit.exports | 1 + config/IOKit.x86_64.exports | 1 - config/Libkern.exports | 7 + config/MASTER.arm | 6 +- config/MASTER.arm64 | 6 +- config/Mach.exports | 1 + config/MasterVersion | 2 +- config/Private.exports | 12 +- config/Private.x86_64.exports | 3 - iokit/IOKit/IOBufferMemoryDescriptor.h | 2 + iokit/IOKit/IOCPU.h | 4 +- iokit/IOKit/IOCommandGate.h | 2 + iokit/IOKit/IOFilterInterruptEventSource.h | 2 + iokit/IOKit/IOHibernatePrivate.h | 52 +- iokit/IOKit/IOInterruptController.h | 4 +- iokit/IOKit/IOInterruptEventSource.h | 2 + iokit/IOKit/IOKitKeysPrivate.h | 9 +- iokit/IOKit/IOKitServer.h | 78 + iokit/IOKit/IONVRAM.h | 1 + iokit/IOKit/IOPlatformExpert.h | 16 +- iokit/IOKit/IOPolledInterface.h | 9 +- iokit/IOKit/IOService.h | 2 + iokit/IOKit/IOTimerEventSource.h | 2 + iokit/IOKit/IOUserClient.h | 42 + iokit/IOKit/pwr_mgt/IOPM.h | 10 + .../IOKit/system_management/IOWatchDogTimer.h | 2 + iokit/Kernel/IOCommandQueue.cpp | 2 +- iokit/Kernel/IOHibernateIO.cpp | 361 +-- iokit/Kernel/IOHibernateInternal.h | 4 +- iokit/Kernel/IOInterruptController.cpp | 2 - iokit/Kernel/IOKitKernelInternal.h | 11 +- iokit/Kernel/IOMemoryDescriptor.cpp | 35 +- iokit/Kernel/IONVRAM.cpp | 124 +- iokit/Kernel/IOPMrootDomain.cpp | 68 +- iokit/Kernel/IOPlatformExpert.cpp | 9 +- iokit/Kernel/IOPolledInterface.cpp | 54 +- iokit/Kernel/IORangeAllocator.cpp | 3 +- iokit/Kernel/IOService.cpp | 10 +- iokit/Kernel/IOUserClient.cpp | 140 +- iokit/Tests/Tests.cpp | 2 +- iokit/bsddev/IOKitBSDInit.cpp | 3 +- libkdd/kcdata.h | 30 +- libkdd/kcdtypes.c | 9 +- libkdd/kdd.framework/Info.plist | 26 + libkdd/kdd.framework/module.modulemap | 7 + libkdd/kdd.frameworkTests/Info.plist | 22 + libkdd/kdd.h | 5 +- libkdd/kdd.xcodeproj/project.pbxproj | 227 ++ libkdd/tests/Tests.swift | 4 + .../stackshot-sample-delta-thread-policy | Bin 0 -> 832 bytes ...ckshot-sample-delta-thread-policy.plist.gz | Bin 0 -> 912 bytes libkern/c++/OSMetaClass.cpp | 2 +- libkern/c++/OSSerializeBinary.cpp | 2 +- libkern/c++/OSString.cpp | 2 +- libkern/c++/OSUnserializeXML.cpp | 2 +- libkern/c++/OSUnserializeXML.y | 2 +- libkern/conf/Makefile.template | 2 +- libkern/crypto/corecrypto_rand.c | 5 + libkern/crypto/corecrypto_sha2.c | 28 +- libkern/crypto/register_crypto.c | 5 +- libkern/libkern/c++/OSKext.h | 2 - libkern/libkern/c++/OSMetaClass.h | 8 +- libkern/libkern/crypto/Makefile | 4 +- libkern/libkern/crypto/rand.h | 15 +- libkern/libkern/kext_panic_report.h | 4 - libsa/bootstrap.cpp | 6 +- libsyscall/wrappers/libproc/libproc.c | 8 +- libsyscall/wrappers/libproc/libproc.h | 2 + libsyscall/wrappers/work_interval.c | 2 + makedefs/MakeInc.def | 33 +- makedefs/MakeInc.top | 1 - osfmk/arm/cpu_common.c | 6 - osfmk/arm/cpu_data_internal.h | 2 +- osfmk/arm/cpu_internal.h | 8 +- osfmk/arm/locore.s | 322 +-- osfmk/arm/machine_routines.c | 5 - osfmk/arm/machine_routines.h | 28 +- osfmk/arm/machine_routines_common.c | 20 +- osfmk/arm/model_dep.c | 2 +- osfmk/arm/pmap.c | 80 +- osfmk/arm/proc_reg.h | 5 +- osfmk/arm/trap.c | 3 - osfmk/arm/trap.h | 6 - osfmk/arm64/caches_asm.s | 23 +- osfmk/arm64/locore.s | 44 +- osfmk/arm64/machine_routines.c | 5 - osfmk/arm64/pcb.c | 362 +-- osfmk/arm64/platform_tests.c | 19 + osfmk/arm64/proc_reg.h | 2 - osfmk/arm64/sleh.c | 6 +- osfmk/arm64/start.s | 54 +- osfmk/atm/atm.c | 12 +- osfmk/chud/chud_cpu.c | 109 - osfmk/chud/chud_glue.c | 38 - osfmk/chud/chud_memory.c | 68 - osfmk/chud/chud_osfmk_callback.c | 86 - osfmk/chud/chud_thread.c | 121 - osfmk/chud/chud_thread.h | 35 - osfmk/chud/chud_xnu.h | 233 -- osfmk/chud/chud_xnu_glue.h | 35 - osfmk/chud/chud_xnu_private.h | 44 - osfmk/chud/i386/chud_cpu_i386.c | 165 -- osfmk/chud/i386/chud_osfmk_callback_i386.c | 516 ----- osfmk/chud/i386/chud_thread_i386.c | 725 ------ osfmk/chud/i386/chud_xnu_glue.h | 28 - osfmk/chud/i386/chud_xnu_private.h | 62 - osfmk/conf/Makefile.template | 7 - osfmk/conf/files | 9 - osfmk/conf/files.arm | 1 - osfmk/conf/files.arm64 | 1 - osfmk/conf/files.x86_64 | 4 - osfmk/corpses/task_corpse.h | 2 - osfmk/device/device.defs | 6 + osfmk/device/iokit_rpc.c | 162 +- osfmk/i386/AT386/model_dep.c | 44 +- osfmk/i386/acpi.c | 7 +- osfmk/i386/bsd_i386.c | 1 - osfmk/i386/cpu_data.h | 18 +- osfmk/i386/cpu_threads.c | 19 +- osfmk/i386/cpu_topology.c | 18 +- osfmk/i386/locks_i386.c | 3 +- osfmk/i386/machine_routines.c | 7 +- osfmk/i386/misc_protos.h | 3 - osfmk/i386/mp.c | 28 +- osfmk/i386/mp_events.h | 2 - osfmk/i386/pcb.c | 30 +- osfmk/i386/pmCPU.c | 1 + osfmk/i386/rtclock_asm.h | 2 +- osfmk/i386/trap.c | 29 - osfmk/i386/trap.h | 6 - osfmk/ipc/ipc_kmsg.c | 2 +- osfmk/kdp/kdp_core.c | 7 + osfmk/kdp/ml/x86_64/kdp_vm.c | 4 +- osfmk/kern/Makefile | 3 +- osfmk/kern/ast.h | 4 +- osfmk/kern/bsd_kern.c | 16 +- osfmk/kern/coalition.c | 18 +- osfmk/kern/debug.c | 2 +- osfmk/kern/debug.h | 14 +- osfmk/kern/ipc_kobject.c | 2 +- osfmk/kern/ipc_kobject.h | 8 +- osfmk/kern/kalloc.c | 235 +- osfmk/kern/kcdata.h | 30 +- osfmk/kern/kern_cdata.c | 15 +- osfmk/kern/kern_stackshot.c | 57 +- osfmk/kern/kpc_common.c | 8 +- osfmk/kern/machine.h | 1 + osfmk/kern/priority.c | 4 +- osfmk/kern/sched_multiq.c | 30 +- osfmk/kern/sched_prim.c | 223 +- osfmk/kern/sched_prim.h | 2 +- osfmk/kern/startup.c | 4 +- osfmk/kern/syscall_subr.c | 4 +- osfmk/kern/task.c | 148 +- osfmk/kern/task.h | 38 +- osfmk/kern/task_policy.c | 7 +- osfmk/kern/thread.c | 72 +- osfmk/kern/thread.h | 2 + osfmk/kern/thread_act.c | 2 +- osfmk/kern/thread_policy.c | 31 +- osfmk/kern/timer_call.c | 18 +- osfmk/kern/work_interval.c | 24 +- osfmk/kern/work_interval.h | 2 +- osfmk/kern/zalloc.c | 182 +- osfmk/kperf/callstack.c | 1060 ++++++++- osfmk/kperf/kperf_timer.c | 18 +- osfmk/kperf/kperf_timer.h | 4 + osfmk/kperf/sample.h | 6 +- osfmk/kperf/thread_samplers.c | 4 +- osfmk/mach/Makefile | 1 + osfmk/mach/branch_predicates.h | 4 +- osfmk/mach/coalition.h | 4 + osfmk/mach/host_special_ports.h | 18 +- osfmk/mach/mach_host.defs | 23 + osfmk/mach/task_info.h | 1 + osfmk/mach/vm32_map.defs | 5 + osfmk/mach/vm_map.defs | 5 + osfmk/mach/vm_statistics.h | 5 + osfmk/mach_debug/mach_debug_types.defs | 4 +- osfmk/mach_debug/zone_info.h | 15 +- osfmk/vm/bsd_vm.c | 70 +- osfmk/vm/vm32_user.c | 15 + osfmk/vm/vm_compressor.c | 10 +- osfmk/vm/vm_compressor.h | 4 + osfmk/vm/vm_compressor_algorithms.c | 2 +- osfmk/vm/vm_compressor_backing_store.c | 4 + osfmk/vm/vm_map.c | 446 +++- osfmk/vm/vm_map.h | 54 +- osfmk/vm/vm_object.c | 74 +- osfmk/vm/vm_object.h | 3 +- osfmk/vm/vm_pageout.c | 11 +- osfmk/vm/vm_protos.h | 6 + osfmk/vm/vm_purgeable.c | 238 +- osfmk/vm/vm_purgeable_internal.h | 5 +- osfmk/vm/vm_user.c | 15 + osfmk/x86_64/bcopy.s | 2 +- osfmk/x86_64/idt64.s | 63 +- osfmk/x86_64/kpc_x86.c | 4 - osfmk/x86_64/lowglobals.h | 2 +- osfmk/x86_64/lowmem_vectors.c | 2 - osfmk/x86_64/pmap.c | 11 +- pexpert/arm/pe_consistent_debug.c | 29 +- pexpert/arm/pe_serial.c | 7 +- pexpert/i386/pe_serial.c | 85 +- pexpert/pexpert/AppleBoot.h | 2 +- pexpert/pexpert/arm/consistent_debug.h | 30 +- pexpert/pexpert/arm64/arm64_common.h | 42 +- pexpert/pexpert/pexpert.h | 2 + san/Kasan_kasan.exports | 3 + san/Makefile | 5 +- san/conf/Makefile.template | 2 +- san/kasan-arm64.c | 63 +- san/kasan-blacklist | 9 + san/kasan-blacklist-arm64 | 9 +- san/kasan-blacklist-dynamic | 16 + san/kasan-blacklist-x86_64 | 3 - san/kasan-fakestack.c | 69 +- san/kasan-memintrinsics.c | 69 +- san/kasan-test.c | 13 +- san/kasan-x86_64.c | 55 +- san/kasan.c | 715 +++--- san/kasan.h | 76 +- san/kasan_dynamic_blacklist.c | 148 +- san/kasan_internal.h | 85 +- san/tools/generate_dynamic_blacklist.py | 19 +- san/tools/validate_blacklist.sh | 28 + security/mac_policy.h | 5 +- tools/lldbmacros/Makefile | 3 +- tools/lldbmacros/README.md | 2 +- tools/lldbmacros/kasan.py | 18 +- tools/lldbmacros/kcdata.py | 45 +- tools/lldbmacros/process.py | 12 +- tools/lldbmacros/xnu.py | 1 + tools/lldbmacros/zonetriage.py | 124 + tools/reindent.sh | 2 +- tools/tests/darwintests/Makefile | 38 +- tools/tests/darwintests/atm_diagnostic_flag.c | 78 + tools/tests/darwintests/data_protection.c | 70 +- tools/tests/darwintests/drop_priv.c | 59 + .../darwintests/freebsd_waitpid_nohang.c | 62 + .../darwintests/jumbo_va_spaces_28530648.c | 2 +- .../darwintests/memorystatus_vm_map_fork.c | 467 ++++ .../darwintests/memorystatus_zone_test.c | 297 ++- tools/tests/darwintests/net_tun_pr_35136664.c | 63 + tools/tests/darwintests/net_tuntests.c | 544 +++++ tools/tests/darwintests/netbsd_utimensat.c | 51 +- .../darwintests/network_entitlements.plist | 10 + tools/tests/darwintests/no32exec_35914211.c | 23 + .../darwintests/no32exec_35914211_helper.c | 6 + tools/tests/darwintests/perf_compressor.c | 302 ++- .../poll_select_kevent_paired_fds.c | 13 +- tools/tests/darwintests/proc_info.c | 2000 ++++++++++++++++- tools/tests/darwintests/proc_info_udata.c | 47 + .../tests/darwintests/settimeofday_29193041.c | 79 +- .../settimeofday_29193041_entitled.c | 79 +- .../tests/darwintests/socket_bind_35243417.c | 9 - .../tests/darwintests/socket_bind_35685803.c | 205 ++ tools/tests/darwintests/stackshot.m | 97 +- .../stackshot_block_owner_14362384.m | 194 +- tools/tests/darwintests/task_info.c | 215 ++ .../darwintests/thread_group_set_32261625.c | 14 +- tools/tests/darwintests/utimensat.c | 6 + .../tests/darwintests/verify_kalloc_config.c | 68 + .../xnu_quick_test_getsetpriority.c | 40 + tools/tests/libMicro/AppleReadMe | 231 -- tools/tests/libMicro/Makefile | 120 - tools/tests/libMicro/Makefile.Aix | 41 - tools/tests/libMicro/Makefile.Darwin | 84 - tools/tests/libMicro/Makefile.Linux | 43 - tools/tests/libMicro/Makefile.SunOS | 61 - tools/tests/libMicro/Makefile.benchmarks | 137 -- tools/tests/libMicro/Makefile.com | 128 -- tools/tests/libMicro/Makefile.com.Darwin | 142 -- tools/tests/libMicro/OPENSOLARIS.LICENSE | 385 ---- tools/tests/libMicro/README | 125 -- tools/tests/libMicro/apple/Makefile | 46 - tools/tests/libMicro/apple/Makefile.Darwin | 85 - .../tests/libMicro/apple/Makefile.benchmarks | 70 - .../tests/libMicro/apple/Makefile.com.Darwin | 61 - tools/tests/libMicro/apple/create_file.c | 247 -- .../libMicro/apple/geekbench_stdlib_write.c | 223 -- tools/tests/libMicro/apple/getaddrinfo_host.c | 244 -- tools/tests/libMicro/apple/getaddrinfo_port.c | 157 -- tools/tests/libMicro/apple/getgrent.c | 163 -- tools/tests/libMicro/apple/getgrgid.c | 228 -- tools/tests/libMicro/apple/getgrnam.c | 231 -- tools/tests/libMicro/apple/getppid.c | 67 - tools/tests/libMicro/apple/getpwent.c | 163 -- tools/tests/libMicro/apple/getpwnam.c | 262 --- tools/tests/libMicro/apple/getpwuid.c | 256 --- tools/tests/libMicro/apple/lb_mmtest.c | 601 ----- tools/tests/libMicro/apple/lm_null_call.c | 185 -- .../tests/libMicro/apple/lmbench_bw_file_rd.c | 322 --- tools/tests/libMicro/apple/lmbench_bw_mem.c | 658 ------ .../tests/libMicro/apple/lmbench_bw_mmap_rd.c | 378 ---- tools/tests/libMicro/apple/lmbench_bw_unix.c | 355 --- tools/tests/libMicro/apple/lmbench_fstat.c | 133 -- tools/tests/libMicro/apple/lmbench_lat_ctx.c | 634 ------ .../libMicro/apple/lmbench_lat_sig_catch.c | 226 -- .../libMicro/apple/lmbench_lat_sig_install.c | 221 -- .../libMicro/apple/lmbench_lat_sig_prot.c | 281 --- .../libMicro/apple/lmbench_lat_sig_send.c | 219 -- .../tests/libMicro/apple/lmbench_openclose.c | 106 - tools/tests/libMicro/apple/lmbench_read.c | 156 -- .../libMicro/apple/lmbench_select_file.c | 408 ---- .../tests/libMicro/apple/lmbench_select_tcp.c | 622 ----- tools/tests/libMicro/apple/lmbench_stat.c | 106 - tools/tests/libMicro/apple/lmbench_write.c | 167 -- .../libMicro/apple/mbr_check_membership.c | 254 --- .../apple/mbr_check_service_membership.c | 281 --- .../apple/od_query_create_with_node.c | 381 ---- tools/tests/libMicro/apple/posix_spawn.c | 105 - tools/tests/libMicro/apple/posix_spawn_bin.c | 70 - tools/tests/libMicro/apple/trivial.c | 263 --- tools/tests/libMicro/apple/vm_allocate.c | 239 -- tools/tests/libMicro/atomic.c | 74 - tools/tests/libMicro/bench.sh | 811 ------- tools/tests/libMicro/benchDS.sh | 324 --- tools/tests/libMicro/benchmark_fini.c | 46 - tools/tests/libMicro/benchmark_finibatch.c | 46 - tools/tests/libMicro/benchmark_finirun.c | 45 - tools/tests/libMicro/benchmark_finiworker.c | 46 - tools/tests/libMicro/benchmark_init.c | 46 - tools/tests/libMicro/benchmark_initbatch.c | 47 - tools/tests/libMicro/benchmark_initrun.c | 45 - tools/tests/libMicro/benchmark_initworker.c | 46 - tools/tests/libMicro/benchmark_optswitch.c | 46 - tools/tests/libMicro/benchmark_result.c | 47 - tools/tests/libMicro/bind.c | 163 -- tools/tests/libMicro/cachetocache.c | 222 -- tools/tests/libMicro/cascade_cond.c | 283 --- tools/tests/libMicro/cascade_fcntl.c | 237 -- tools/tests/libMicro/cascade_flock.c | 233 -- tools/tests/libMicro/cascade_lockf.c | 228 -- tools/tests/libMicro/cascade_mutex.c | 232 -- tools/tests/libMicro/chdir.c | 132 -- tools/tests/libMicro/close.c | 141 -- tools/tests/libMicro/close_tcp.c | 241 -- tools/tests/libMicro/connection.c | 305 --- tools/tests/libMicro/coreos_bench.sh | 829 ------- tools/tests/libMicro/create_stuff.sh | 6 - tools/tests/libMicro/dup.c | 139 -- tools/tests/libMicro/elided.c | 59 - tools/tests/libMicro/embd_bench.sh | 815 ------- tools/tests/libMicro/exec.c | 101 - tools/tests/libMicro/exec_bin.c | 65 - tools/tests/libMicro/exit.c | 160 -- tools/tests/libMicro/exp.c | 92 - tools/tests/libMicro/fcntl.c | 99 - tools/tests/libMicro/fcntl_ndelay.c | 100 - tools/tests/libMicro/file_lock.c | 106 - tools/tests/libMicro/fork.c | 131 -- tools/tests/libMicro/getcontext.c | 74 - tools/tests/libMicro/getenv.c | 126 -- tools/tests/libMicro/getpeername.c | 163 -- tools/tests/libMicro/getpid.c | 64 - tools/tests/libMicro/getrusage.c | 73 - tools/tests/libMicro/getsockname.c | 125 -- tools/tests/libMicro/gettimeofday.c | 72 - tools/tests/libMicro/isatty.c | 110 - tools/tests/libMicro/libmicro.c | 1608 ------------- tools/tests/libMicro/libmicro.h | 255 --- tools/tests/libMicro/libmicro_main.c | 44 - tools/tests/libMicro/listen.c | 127 -- tools/tests/libMicro/localtime_r.c | 75 - tools/tests/libMicro/log.c | 92 - tools/tests/libMicro/longjmp.c | 70 - tools/tests/libMicro/lrand48.c | 71 - tools/tests/libMicro/lseek.c | 130 -- tools/tests/libMicro/malloc.c | 140 -- tools/tests/libMicro/memcpy.c | 160 -- tools/tests/libMicro/memmove.c | 160 -- tools/tests/libMicro/memrand.c | 146 -- tools/tests/libMicro/memset.c | 172 -- tools/tests/libMicro/mk_tarball | 28 - tools/tests/libMicro/mktime.c | 112 - tools/tests/libMicro/mmap.c | 198 -- tools/tests/libMicro/mprotect.c | 205 -- tools/tests/libMicro/msync.c | 190 -- tools/tests/libMicro/multiview.sh | 201 -- tools/tests/libMicro/munmap.c | 192 -- tools/tests/libMicro/mutex.c | 194 -- tools/tests/libMicro/nop.c | 63 - tools/tests/libMicro/od_account_create.sh | 129 -- tools/tests/libMicro/od_account_delete.sh | 98 - tools/tests/libMicro/open.c | 138 -- tools/tests/libMicro/pipe.c | 565 ----- tools/tests/libMicro/poll.c | 218 -- tools/tests/libMicro/pread.c | 142 -- tools/tests/libMicro/pthread_create.c | 160 -- tools/tests/libMicro/pwrite.c | 154 -- tools/tests/libMicro/read.c | 143 -- tools/tests/libMicro/realpath.c | 85 - tools/tests/libMicro/recurse.c | 98 - tools/tests/libMicro/recurse2.c | 46 - tools/tests/libMicro/select.c | 214 -- tools/tests/libMicro/semop.c | 103 - tools/tests/libMicro/setcontext.c | 67 - tools/tests/libMicro/setsockopt.c | 99 - tools/tests/libMicro/sigaction.c | 95 - tools/tests/libMicro/siglongjmp.c | 73 - tools/tests/libMicro/signal.c | 100 - tools/tests/libMicro/sigprocmask.c | 84 - tools/tests/libMicro/socket.c | 157 -- tools/tests/libMicro/socketpair.c | 118 - tools/tests/libMicro/stat.c | 88 - tools/tests/libMicro/strcasecmp.c | 150 -- tools/tests/libMicro/strchr.c | 144 -- tools/tests/libMicro/strcmp.c | 147 -- tools/tests/libMicro/strcpy.c | 145 -- tools/tests/libMicro/strftime.c | 129 -- tools/tests/libMicro/strlen.c | 143 -- tools/tests/libMicro/strtol.c | 67 - tools/tests/libMicro/system.c | 98 - tools/tests/libMicro/tattle.c | 154 -- tools/tests/libMicro/time.c | 69 - tools/tests/libMicro/times.c | 73 - tools/tests/libMicro/wrapper.sh | 37 - tools/tests/libMicro/write.c | 154 -- tools/tests/libMicro/writev.c | 149 -- tools/trace/bridgetime.lua | 97 + 571 files changed, 14678 insertions(+), 35280 deletions(-) delete mode 100644 bsd/dev/chud/chud_process.c create mode 100644 bsd/net/if_ports_used.c create mode 100644 bsd/net/if_ports_used.h create mode 100644 libkdd/kdd.framework/Info.plist create mode 100644 libkdd/kdd.framework/module.modulemap create mode 100644 libkdd/kdd.frameworkTests/Info.plist create mode 100644 libkdd/tests/stackshot-sample-delta-thread-policy create mode 100644 libkdd/tests/stackshot-sample-delta-thread-policy.plist.gz delete mode 100644 osfmk/chud/chud_cpu.c delete mode 100644 osfmk/chud/chud_glue.c delete mode 100644 osfmk/chud/chud_memory.c delete mode 100644 osfmk/chud/chud_osfmk_callback.c delete mode 100644 osfmk/chud/chud_thread.c delete mode 100644 osfmk/chud/chud_thread.h delete mode 100644 osfmk/chud/chud_xnu.h delete mode 100644 osfmk/chud/chud_xnu_glue.h delete mode 100644 osfmk/chud/chud_xnu_private.h delete mode 100644 osfmk/chud/i386/chud_cpu_i386.c delete mode 100644 osfmk/chud/i386/chud_osfmk_callback_i386.c delete mode 100644 osfmk/chud/i386/chud_thread_i386.c delete mode 100644 osfmk/chud/i386/chud_xnu_glue.h delete mode 100644 osfmk/chud/i386/chud_xnu_private.h create mode 100644 san/kasan-blacklist-dynamic create mode 100755 san/tools/validate_blacklist.sh create mode 100755 tools/lldbmacros/zonetriage.py create mode 100644 tools/tests/darwintests/atm_diagnostic_flag.c create mode 100644 tools/tests/darwintests/drop_priv.c create mode 100644 tools/tests/darwintests/freebsd_waitpid_nohang.c create mode 100644 tools/tests/darwintests/memorystatus_vm_map_fork.c create mode 100644 tools/tests/darwintests/net_tun_pr_35136664.c create mode 100644 tools/tests/darwintests/net_tuntests.c create mode 100644 tools/tests/darwintests/network_entitlements.plist create mode 100644 tools/tests/darwintests/no32exec_35914211.c create mode 100644 tools/tests/darwintests/no32exec_35914211_helper.c create mode 100644 tools/tests/darwintests/proc_info_udata.c create mode 100644 tools/tests/darwintests/socket_bind_35685803.c create mode 100644 tools/tests/darwintests/verify_kalloc_config.c create mode 100644 tools/tests/darwintests/xnu_quick_test_getsetpriority.c delete mode 100755 tools/tests/libMicro/AppleReadMe delete mode 100644 tools/tests/libMicro/Makefile delete mode 100644 tools/tests/libMicro/Makefile.Aix delete mode 100644 tools/tests/libMicro/Makefile.Darwin delete mode 100644 tools/tests/libMicro/Makefile.Linux delete mode 100644 tools/tests/libMicro/Makefile.SunOS delete mode 100644 tools/tests/libMicro/Makefile.benchmarks delete mode 100644 tools/tests/libMicro/Makefile.com delete mode 100644 tools/tests/libMicro/Makefile.com.Darwin delete mode 100644 tools/tests/libMicro/OPENSOLARIS.LICENSE delete mode 100644 tools/tests/libMicro/README delete mode 100644 tools/tests/libMicro/apple/Makefile delete mode 100644 tools/tests/libMicro/apple/Makefile.Darwin delete mode 100644 tools/tests/libMicro/apple/Makefile.benchmarks delete mode 100644 tools/tests/libMicro/apple/Makefile.com.Darwin delete mode 100644 tools/tests/libMicro/apple/create_file.c delete mode 100644 tools/tests/libMicro/apple/geekbench_stdlib_write.c delete mode 100644 tools/tests/libMicro/apple/getaddrinfo_host.c delete mode 100644 tools/tests/libMicro/apple/getaddrinfo_port.c delete mode 100644 tools/tests/libMicro/apple/getgrent.c delete mode 100644 tools/tests/libMicro/apple/getgrgid.c delete mode 100644 tools/tests/libMicro/apple/getgrnam.c delete mode 100644 tools/tests/libMicro/apple/getppid.c delete mode 100644 tools/tests/libMicro/apple/getpwent.c delete mode 100644 tools/tests/libMicro/apple/getpwnam.c delete mode 100644 tools/tests/libMicro/apple/getpwuid.c delete mode 100644 tools/tests/libMicro/apple/lb_mmtest.c delete mode 100644 tools/tests/libMicro/apple/lm_null_call.c delete mode 100644 tools/tests/libMicro/apple/lmbench_bw_file_rd.c delete mode 100644 tools/tests/libMicro/apple/lmbench_bw_mem.c delete mode 100644 tools/tests/libMicro/apple/lmbench_bw_mmap_rd.c delete mode 100644 tools/tests/libMicro/apple/lmbench_bw_unix.c delete mode 100644 tools/tests/libMicro/apple/lmbench_fstat.c delete mode 100644 tools/tests/libMicro/apple/lmbench_lat_ctx.c delete mode 100644 tools/tests/libMicro/apple/lmbench_lat_sig_catch.c delete mode 100644 tools/tests/libMicro/apple/lmbench_lat_sig_install.c delete mode 100644 tools/tests/libMicro/apple/lmbench_lat_sig_prot.c delete mode 100644 tools/tests/libMicro/apple/lmbench_lat_sig_send.c delete mode 100644 tools/tests/libMicro/apple/lmbench_openclose.c delete mode 100644 tools/tests/libMicro/apple/lmbench_read.c delete mode 100644 tools/tests/libMicro/apple/lmbench_select_file.c delete mode 100644 tools/tests/libMicro/apple/lmbench_select_tcp.c delete mode 100644 tools/tests/libMicro/apple/lmbench_stat.c delete mode 100644 tools/tests/libMicro/apple/lmbench_write.c delete mode 100644 tools/tests/libMicro/apple/mbr_check_membership.c delete mode 100644 tools/tests/libMicro/apple/mbr_check_service_membership.c delete mode 100644 tools/tests/libMicro/apple/od_query_create_with_node.c delete mode 100644 tools/tests/libMicro/apple/posix_spawn.c delete mode 100644 tools/tests/libMicro/apple/posix_spawn_bin.c delete mode 100644 tools/tests/libMicro/apple/trivial.c delete mode 100644 tools/tests/libMicro/apple/vm_allocate.c delete mode 100644 tools/tests/libMicro/atomic.c delete mode 100755 tools/tests/libMicro/bench.sh delete mode 100755 tools/tests/libMicro/benchDS.sh delete mode 100644 tools/tests/libMicro/benchmark_fini.c delete mode 100644 tools/tests/libMicro/benchmark_finibatch.c delete mode 100644 tools/tests/libMicro/benchmark_finirun.c delete mode 100644 tools/tests/libMicro/benchmark_finiworker.c delete mode 100644 tools/tests/libMicro/benchmark_init.c delete mode 100644 tools/tests/libMicro/benchmark_initbatch.c delete mode 100644 tools/tests/libMicro/benchmark_initrun.c delete mode 100644 tools/tests/libMicro/benchmark_initworker.c delete mode 100644 tools/tests/libMicro/benchmark_optswitch.c delete mode 100644 tools/tests/libMicro/benchmark_result.c delete mode 100644 tools/tests/libMicro/bind.c delete mode 100644 tools/tests/libMicro/cachetocache.c delete mode 100644 tools/tests/libMicro/cascade_cond.c delete mode 100644 tools/tests/libMicro/cascade_fcntl.c delete mode 100644 tools/tests/libMicro/cascade_flock.c delete mode 100644 tools/tests/libMicro/cascade_lockf.c delete mode 100644 tools/tests/libMicro/cascade_mutex.c delete mode 100644 tools/tests/libMicro/chdir.c delete mode 100644 tools/tests/libMicro/close.c delete mode 100644 tools/tests/libMicro/close_tcp.c delete mode 100644 tools/tests/libMicro/connection.c delete mode 100755 tools/tests/libMicro/coreos_bench.sh delete mode 100755 tools/tests/libMicro/create_stuff.sh delete mode 100644 tools/tests/libMicro/dup.c delete mode 100644 tools/tests/libMicro/elided.c delete mode 100755 tools/tests/libMicro/embd_bench.sh delete mode 100644 tools/tests/libMicro/exec.c delete mode 100644 tools/tests/libMicro/exec_bin.c delete mode 100644 tools/tests/libMicro/exit.c delete mode 100644 tools/tests/libMicro/exp.c delete mode 100644 tools/tests/libMicro/fcntl.c delete mode 100644 tools/tests/libMicro/fcntl_ndelay.c delete mode 100644 tools/tests/libMicro/file_lock.c delete mode 100644 tools/tests/libMicro/fork.c delete mode 100644 tools/tests/libMicro/getcontext.c delete mode 100644 tools/tests/libMicro/getenv.c delete mode 100644 tools/tests/libMicro/getpeername.c delete mode 100644 tools/tests/libMicro/getpid.c delete mode 100644 tools/tests/libMicro/getrusage.c delete mode 100644 tools/tests/libMicro/getsockname.c delete mode 100644 tools/tests/libMicro/gettimeofday.c delete mode 100644 tools/tests/libMicro/isatty.c delete mode 100644 tools/tests/libMicro/libmicro.c delete mode 100644 tools/tests/libMicro/libmicro.h delete mode 100644 tools/tests/libMicro/libmicro_main.c delete mode 100644 tools/tests/libMicro/listen.c delete mode 100644 tools/tests/libMicro/localtime_r.c delete mode 100644 tools/tests/libMicro/log.c delete mode 100644 tools/tests/libMicro/longjmp.c delete mode 100644 tools/tests/libMicro/lrand48.c delete mode 100644 tools/tests/libMicro/lseek.c delete mode 100644 tools/tests/libMicro/malloc.c delete mode 100644 tools/tests/libMicro/memcpy.c delete mode 100644 tools/tests/libMicro/memmove.c delete mode 100644 tools/tests/libMicro/memrand.c delete mode 100644 tools/tests/libMicro/memset.c delete mode 100755 tools/tests/libMicro/mk_tarball delete mode 100644 tools/tests/libMicro/mktime.c delete mode 100644 tools/tests/libMicro/mmap.c delete mode 100644 tools/tests/libMicro/mprotect.c delete mode 100644 tools/tests/libMicro/msync.c delete mode 100755 tools/tests/libMicro/multiview.sh delete mode 100644 tools/tests/libMicro/munmap.c delete mode 100644 tools/tests/libMicro/mutex.c delete mode 100644 tools/tests/libMicro/nop.c delete mode 100755 tools/tests/libMicro/od_account_create.sh delete mode 100755 tools/tests/libMicro/od_account_delete.sh delete mode 100644 tools/tests/libMicro/open.c delete mode 100644 tools/tests/libMicro/pipe.c delete mode 100644 tools/tests/libMicro/poll.c delete mode 100644 tools/tests/libMicro/pread.c delete mode 100644 tools/tests/libMicro/pthread_create.c delete mode 100644 tools/tests/libMicro/pwrite.c delete mode 100644 tools/tests/libMicro/read.c delete mode 100644 tools/tests/libMicro/realpath.c delete mode 100644 tools/tests/libMicro/recurse.c delete mode 100644 tools/tests/libMicro/recurse2.c delete mode 100644 tools/tests/libMicro/select.c delete mode 100644 tools/tests/libMicro/semop.c delete mode 100644 tools/tests/libMicro/setcontext.c delete mode 100644 tools/tests/libMicro/setsockopt.c delete mode 100644 tools/tests/libMicro/sigaction.c delete mode 100644 tools/tests/libMicro/siglongjmp.c delete mode 100644 tools/tests/libMicro/signal.c delete mode 100644 tools/tests/libMicro/sigprocmask.c delete mode 100644 tools/tests/libMicro/socket.c delete mode 100644 tools/tests/libMicro/socketpair.c delete mode 100644 tools/tests/libMicro/stat.c delete mode 100644 tools/tests/libMicro/strcasecmp.c delete mode 100644 tools/tests/libMicro/strchr.c delete mode 100644 tools/tests/libMicro/strcmp.c delete mode 100644 tools/tests/libMicro/strcpy.c delete mode 100644 tools/tests/libMicro/strftime.c delete mode 100644 tools/tests/libMicro/strlen.c delete mode 100644 tools/tests/libMicro/strtol.c delete mode 100644 tools/tests/libMicro/system.c delete mode 100644 tools/tests/libMicro/tattle.c delete mode 100644 tools/tests/libMicro/time.c delete mode 100644 tools/tests/libMicro/times.c delete mode 100755 tools/tests/libMicro/wrapper.sh delete mode 100644 tools/tests/libMicro/write.c delete mode 100644 tools/tests/libMicro/writev.c create mode 100755 tools/trace/bridgetime.lua diff --git a/Makefile b/Makefile index fa9f39132..1660223f5 100644 --- a/Makefile +++ b/Makefile @@ -238,7 +238,7 @@ endif # CURRENT_BUILD_CONFIG endif # all other RC_ProjectName -installhdrs_libkdd install_libkdd: +installapi_libkdd installhdrs_libkdd install_libkdd: cd libkdd; \ xcodebuild -target libkdd $(subst _libkdd,,$@) \ "SRCROOT=$(SRCROOT)/libkdd" \ @@ -248,6 +248,16 @@ installhdrs_libkdd install_libkdd: "SDKROOT=$(SDKROOT)" +installapi_libkdd_host installhdrs_libkdd_host install_libkdd_host: + cd libkdd; \ + xcodebuild -target kdd.framework $(subst _libkdd_host,,$@) \ + "SRCROOT=$(SRCROOT)/libkdd" \ + "OBJROOT=$(OBJROOT)" \ + "SYMROOT=$(SYMROOT)" \ + "DSTROOT=$(DSTROOT)" \ + "SDKROOT=$(SDKROOT)" + + # "xnu_tests" and "testbots" are targets that can be invoked via a standalone # "make xnu_tests" or via buildit/XBS with the RC_ProjectName=xnu_tests. # Define the target here in the outermost scope of the initial Makefile diff --git a/README.md b/README.md index b285c1a6a..dc1bbbae6 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ What is XNU? =========== -XNU kernel is part of the Darwin operating system for use in OS X and iOS operating systems. XNU is an acronym for XNU is Not Unix. +XNU kernel is part of the Darwin operating system for use in macOS and iOS operating systems. XNU is an acronym for X is Not Unix. XNU is a hybrid kernel combining the Mach kernel developed at Carnegie Mellon University with components from FreeBSD and C++ API for writing drivers called IOKit. -XNU runs on I386, X86_64 for both single processor and multi-processor configurations. +XNU runs on x86_64 for both single processor and multi-processor configurations. XNU Source Tree =============== @@ -35,9 +35,9 @@ Here is the syntax: Where: - * \: path to MacOS SDK on disk. (defaults to `/`) + * \: path to macOS SDK on disk. (defaults to `/`) * \: can be `debug`, `development`, `release`, `profile` and configures compilation flags and asserts throughout kernel code. - * \ : can be valid arch to build for. (E.g. `i386` or `X86_64`) + * \ : can be valid arch to build for. (E.g. `X86_64`) To build a kernel for the same architecture as running OS, just type @@ -69,7 +69,7 @@ Building FAT kernel binary Define architectures in your environment or when running a make command. - $ make ARCH_CONFIGS="I386 X86_64" exporthdrs all + $ make ARCH_CONFIGS="X86_64" exporthdrs all Other makefile options ---------------------- diff --git a/bsd/bsm/audit_kevents.h b/bsd/bsm/audit_kevents.h index cd7142d60..391425f91 100644 --- a/bsd/bsm/audit_kevents.h +++ b/bsd/bsm/audit_kevents.h @@ -700,7 +700,6 @@ #define AUE_BSDTHREADCREATE AUE_NULL #define AUE_BSDTHREADTERMINATE AUE_NULL #define AUE_BSDTHREADREGISTER AUE_NULL -#define AUE_CHUD AUE_NULL #define AUE_CSOPS AUE_NULL #define AUE_DUP AUE_NULL #define AUE_FDATASYNC AUE_NULL diff --git a/bsd/conf/files b/bsd/conf/files index 104c577ef..4bf42f392 100644 --- a/bsd/conf/files +++ b/bsd/conf/files @@ -217,6 +217,7 @@ bsd/net/ntstat.c optional networking bsd/net/net_perf.c optional networking bsd/net/if_gif.c optional gif bsd/net/if_stf.c optional stf +bsd/net/if_ports_used.c optional networking bsd/net/kpi_interface.c optional networking bsd/net/kpi_protocol.c optional networking bsd/net/kpi_interfacefilter.c optional networking @@ -488,8 +489,6 @@ bsd/uxkern/ux_exception.c standard bsd/conf/param.c standard ./ioconf.c standard -bsd/dev/chud/chud_process.c standard - bsd/kern/imageboot.c optional config_imageboot osfmk/kperf/kperfbsd.c optional kperf diff --git a/bsd/dev/arm/cpu_in_cksum.s b/bsd/dev/arm/cpu_in_cksum.s index 28f648183..e819fd625 100644 --- a/bsd/dev/arm/cpu_in_cksum.s +++ b/bsd/dev/arm/cpu_in_cksum.s @@ -1,12 +1,29 @@ /* - * Copyright (c) 2009-2017 Apple Inc. All rights reserved. + * Copyright (c) 2009-2018 Apple Inc. All rights reserved. * - * This document is the property of Apple Inc. - * It is considered confidential and proprietary. + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * - * This document may not be reproduced or transmitted in any form, - * in whole or in part, without the express written permission of - * Apple Inc. + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* $NetBSD: cpu_in_cksum.S,v 1.2 2008/01/27 16:58:05 chris Exp $ */ diff --git a/bsd/dev/arm64/cpu_in_cksum.s b/bsd/dev/arm64/cpu_in_cksum.s index b01b27172..00a00c667 100644 --- a/bsd/dev/arm64/cpu_in_cksum.s +++ b/bsd/dev/arm64/cpu_in_cksum.s @@ -1,12 +1,29 @@ /* - * Copyright (c) 2012-2017 Apple Inc. All rights reserved. + * Copyright (c) 2012-2018 Apple Inc. All rights reserved. * - * This document is the property of Apple Inc. - * It is considered confidential and proprietary. + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * - * This document may not be reproduced or transmitted in any form, - * in whole or in part, without the express written permission of - * Apple Inc. + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* diff --git a/bsd/dev/chud/chud_process.c b/bsd/dev/chud/chud_process.c deleted file mode 100644 index f71987299..000000000 --- a/bsd/dev/chud/chud_process.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#include -#include -#include // vn_getpath() -#include -#include - -int chudxnu_current_pid(void); - diff --git a/bsd/dev/dtrace/dtrace.c b/bsd/dev/dtrace/dtrace.c index 75fc4d38d..587a8b438 100644 --- a/bsd/dev/dtrace/dtrace.c +++ b/bsd/dev/dtrace/dtrace.c @@ -105,6 +105,8 @@ #include #endif /* MONOTONIC */ +#include + #include extern uint32_t pmap_find_phys(void *, uint64_t); extern boolean_t pmap_valid_page(uint32_t); @@ -12155,57 +12157,61 @@ dtrace_dof_copyin_from_proc(proc_t* p, user_addr_t uarg, int *errp) return (dof); } +static void +dtrace_dof_destroy(dof_hdr_t *dof) +{ + dt_kmem_free_aligned(dof, dof->dofh_loadsz); +} + static dof_hdr_t * dtrace_dof_property(const char *name) { - uchar_t *buf; - uint64_t loadsz; - unsigned int len, i; + unsigned int len; dof_hdr_t *dof; - /* - * Unfortunately, array of values in .conf files are always (and - * only) interpreted to be integer arrays. We must read our DOF - * as an integer array, and then squeeze it into a byte array. - */ - if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dtrace_devi, 0, - name, (int **)&buf, &len) != DDI_PROP_SUCCESS) - return (NULL); + if (dtrace_is_restricted() && !dtrace_are_restrictions_relaxed()) { + return NULL; + } - for (i = 0; i < len; i++) - buf[i] = (uchar_t)(((int *)buf)[i]); + if (!PEReadNVRAMProperty(name, NULL, &len)) { + return NULL; + } + + dof = dt_kmem_alloc_aligned(len, 8, KM_SLEEP); + + if (!PEReadNVRAMProperty(name, dof, &len)) { + dtrace_dof_destroy(dof); + dtrace_dof_error(NULL, "unreadable DOF"); + return NULL; + } if (len < sizeof (dof_hdr_t)) { - ddi_prop_free(buf); + dtrace_dof_destroy(dof); dtrace_dof_error(NULL, "truncated header"); return (NULL); } - if (len < (loadsz = ((dof_hdr_t *)buf)->dofh_loadsz)) { - ddi_prop_free(buf); + if (len < dof->dofh_loadsz) { + dtrace_dof_destroy(dof); dtrace_dof_error(NULL, "truncated DOF"); return (NULL); } - if (loadsz >= (uint64_t)dtrace_dof_maxsize) { - ddi_prop_free(buf); - dtrace_dof_error(NULL, "oversized DOF"); + if (len != dof->dofh_loadsz) { + dtrace_dof_destroy(dof); + dtrace_dof_error(NULL, "invalid DOF size"); return (NULL); } - dof = dt_kmem_alloc_aligned(loadsz, 8, KM_SLEEP); - bcopy(buf, dof, loadsz); - ddi_prop_free(buf); + if (dof->dofh_loadsz >= (uint64_t)dtrace_dof_maxsize) { + dtrace_dof_destroy(dof); + dtrace_dof_error(NULL, "oversized DOF"); + return (NULL); + } return (dof); } -static void -dtrace_dof_destroy(dof_hdr_t *dof) -{ - dt_kmem_free_aligned(dof, dof->dofh_loadsz); -} - /* * Return the dof_sec_t pointer corresponding to a given section index. If the * index is not valid, dtrace_dof_error() is called and NULL is returned. If diff --git a/bsd/dev/dtrace/dtrace_glue.c b/bsd/dev/dtrace/dtrace_glue.c index 57f0f3207..d47102fe6 100644 --- a/bsd/dev/dtrace/dtrace_glue.c +++ b/bsd/dev/dtrace/dtrace_glue.c @@ -586,63 +586,13 @@ ddi_report_dev(dev_info_t *devi) #pragma unused(devi) } - -static unsigned int gRegisteredProps = 0; -static struct { - char name[32]; /* enough for "dof-data-" + digits */ - int *data; - uint_t nelements; -} gPropTable[16]; - kern_return_t _dtrace_register_anon_DOF(char *, uchar_t *, uint_t); kern_return_t _dtrace_register_anon_DOF(char *name, uchar_t *data, uint_t nelements) { - if (gRegisteredProps < sizeof(gPropTable)/sizeof(gPropTable[0])) { - int *p = (int *)_MALLOC(nelements*sizeof(int), M_TEMP, M_WAITOK); - - if (NULL == p) - return KERN_FAILURE; - - strlcpy(gPropTable[gRegisteredProps].name, name, sizeof(gPropTable[0].name)); - gPropTable[gRegisteredProps].nelements = nelements; - gPropTable[gRegisteredProps].data = p; - - while (nelements-- > 0) { - *p++ = (int)(*data++); - } - - gRegisteredProps++; - return KERN_SUCCESS; - } - else - return KERN_FAILURE; -} - -int -ddi_prop_lookup_int_array(dev_t match_dev, dev_info_t *dip, uint_t flags, - const char *name, int **data, uint_t *nelements) -{ -#pragma unused(match_dev,dip,flags) - unsigned int i; - for (i = 0; i < gRegisteredProps; ++i) - { - if (0 == strncmp(name, gPropTable[i].name, - sizeof(gPropTable[i].name))) { - *data = gPropTable[i].data; - *nelements = gPropTable[i].nelements; - return DDI_SUCCESS; - } - } - return DDI_FAILURE; -} - -int -ddi_prop_free(void *buf) -{ - _FREE(buf, M_TEMP); - return DDI_SUCCESS; +#pragma unused(name, data, nelements) + return KERN_FAILURE; } int diff --git a/bsd/dev/dtrace/fbt.c b/bsd/dev/dtrace/fbt.c index 25f052f1a..d90a7b15d 100644 --- a/bsd/dev/dtrace/fbt.c +++ b/bsd/dev/dtrace/fbt.c @@ -50,6 +50,7 @@ #include #include +#include /* #include */ struct savearea_t; /* Used anonymously */ @@ -467,6 +468,14 @@ fbt_excluded(const char* name) return TRUE; } +#if KASAN + if (LIT_STRNSTART(name, "kasan") || + LIT_STRNSTART(name, "__kasan") || + LIT_STRNSTART(name, "__asan")) { + return TRUE; + } +#endif + /* * Place no probes that could be hit on the way to a panic. */ @@ -560,6 +569,13 @@ fbt_enable(void *arg, dtrace_id_t id, void *parg) } if (fbt->fbtp_currentval != fbt->fbtp_patchval) { +#if KASAN + /* Since dtrace probes can call into KASan and vice versa, things can get + * very slow if we have a lot of probes. This call will disable the KASan + * fakestack after a threshold of probes is reached. */ + kasan_fakestack_suspend(); +#endif + (void)ml_nofault_copy( (vm_offset_t)&fbt->fbtp_patchval, (vm_offset_t)fbt->fbtp_patchpoint, sizeof(fbt->fbtp_patchval)); /* @@ -607,6 +623,10 @@ fbt_disable(void *arg, dtrace_id_t id, void *parg) fbt->fbtp_currentval = fbt->fbtp_savedval; ASSERT(ctl->mod_nenabled > 0); ctl->mod_nenabled--; + +#if KASAN + kasan_fakestack_resume(); +#endif } } dtrace_membar_consumer(); diff --git a/bsd/dev/dtrace/sdt.c b/bsd/dev/dtrace/sdt.c index 2923bf644..35937cdf3 100644 --- a/bsd/dev/dtrace/sdt.c +++ b/bsd/dev/dtrace/sdt.c @@ -554,10 +554,10 @@ void sdt_init( void ) * that symbol names the function containing the sdt probe. */ for (j = 0; j < orig_st->nsyms; j++) { - uint8_t jn_type = sym[j].n_type & (N_TYPE | N_EXT); + uint8_t jn_type = sym[j].n_type & N_TYPE; char *jname = strings + sym[j].n_un.n_strx; - if (((N_SECT | N_EXT) != jn_type && (N_ABS | N_EXT) != jn_type)) + if ((N_SECT != jn_type && N_ABS != jn_type)) continue; if (0 == sym[j].n_un.n_strx) /* iff a null, "", name. */ diff --git a/bsd/dev/dtrace/sdt_subr.c b/bsd/dev/dtrace/sdt_subr.c index ad71d1ffe..3fc2b9aa0 100644 --- a/bsd/dev/dtrace/sdt_subr.c +++ b/bsd/dev/dtrace/sdt_subr.c @@ -946,6 +946,16 @@ sdt_argdesc_t sdt_args[] = { { "mptcp", "disconnectx", 2, 2, "sae_connid_t", "sae_connid_t" }, { "mptcp", "disconnectx", 3, 3, "struct socket *", "sockinfo_t *" }, { "mptcp", "disconnectx", 4, 4, "struct mptcb *", "mptsinfo_t *" }, + {"vminfo", "kalloc", 0, 0, "vm_size_t", "vm_size_t" }, + {"vminfo", "kalloc", 1, 1, "vm_size_t", "vm_size_t" }, + {"vminfo", "kalloc", 2, 2, "void*", "void*" }, + {"vminfo", "kfree", 0, 0, "vm_size_t", "vm_size_t" }, + {"vminfo", "kfree", 1, 1, "vm_size_t", "vm_size_t" }, + {"vminfo", "kfree", 2, 2, "void*", "void*" }, + {"vminfo", "zalloc", 0, 0, "zone_t", "zone_t" }, + {"vminfo", "zalloc", 1, 1, "void*", "void*" }, + {"vminfo", "zfree", 0, 0, "zone_t", "zone_t" }, + {"vminfo", "zfree", 1, 1, "void*", "void*" }, { NULL, NULL, 0, 0, NULL, NULL } }; diff --git a/bsd/dev/i386/fbt_x86.c b/bsd/dev/i386/fbt_x86.c index 6553c2412..2ff70daee 100644 --- a/bsd/dev/i386/fbt_x86.c +++ b/bsd/dev/i386/fbt_x86.c @@ -56,6 +56,8 @@ #include +#include + #define DTRACE_INVOP_NOP_SKIP 1 #define DTRACE_INVOP_MOVL_ESP_EBP 10 #define DTRACE_INVOP_MOVL_ESP_EBP_SKIP 2 @@ -226,6 +228,18 @@ fbt_perfCallback( pDst--) *pDst = pDst[-delta]; +#if KASAN + /* + * The above has moved stack objects so they are no longer in sync + * with the shadow. + */ + uintptr_t base = (uintptr_t)((uint32_t *)old_sp - delta); + uintptr_t size = (uintptr_t)fp - base; + if (base >= VM_MIN_KERNEL_AND_KEXT_ADDRESS) { + kasan_unpoison_stack(base, size); + } +#endif + /* Track the stack lift in "saved_state". */ saved_state = (x86_saved_state64_t *) (((uintptr_t)saved_state) + (delta << 2)); /* Adjust the stack pointer utilized by the trampolines */ diff --git a/bsd/dev/monotonic.c b/bsd/dev/monotonic.c index 91ef1f2bd..19a7cf3a6 100644 --- a/bsd/dev/monotonic.c +++ b/bsd/dev/monotonic.c @@ -338,13 +338,13 @@ mt_sysctl SYSCTL_HANDLER_ARGS switch ((enum mt_sysctl)arg1) { case MT_SUPPORTED: - return sysctl_io_number(req, mt_core_supported, sizeof(mt_core_supported), NULL, NULL); + return sysctl_io_number(req, (int)mt_core_supported, sizeof(int), NULL, NULL); case MT_PMIS: return sysctl_io_number(req, mt_pmis, sizeof(mt_pmis), NULL, NULL); case MT_RETROGRADE: return sysctl_io_number(req, mt_retrograde, sizeof(mt_retrograde), NULL, NULL); case MT_TASK_THREAD: - return sysctl_io_number(req, mt_core_supported, sizeof(mt_core_supported), NULL, NULL); + return sysctl_io_number(req, (int)mt_core_supported, sizeof(int), NULL, NULL); case MT_DEBUG: { int value = mt_debug; diff --git a/bsd/kern/bsd_init.c b/bsd/kern/bsd_init.c index 22a932314..36b5db056 100644 --- a/bsd/kern/bsd_init.c +++ b/bsd/kern/bsd_init.c @@ -293,6 +293,9 @@ void bsd_exec_setup(int); #if __arm64__ __private_extern__ int bootarg_no64exec = 0; #endif +#if __x86_64__ +__private_extern__ int bootarg_no32exec = 0; +#endif __private_extern__ int bootarg_vnode_cache_defeat = 0; #if CONFIG_JETSAM && (DEVELOPMENT || DEBUG) @@ -1195,6 +1198,11 @@ parse_bsd_args(void) if (PE_parse_boot_argn("-no64exec", namep, sizeof (namep))) bootarg_no64exec = 1; #endif +#if __x86_64__ + /* disable 32 bit grading */ + if (PE_parse_boot_argn("-no32exec", namep, sizeof (namep))) + bootarg_no32exec = 1; +#endif /* disable vnode_cache_is_authorized() by setting vnode_cache_defeat */ if (PE_parse_boot_argn("-vnode_cache_defeat", namep, sizeof (namep))) diff --git a/bsd/kern/kdebug.c b/bsd/kern/kdebug.c index 978b02c49..5b424e719 100644 --- a/bsd/kern/kdebug.c +++ b/bsd/kern/kdebug.c @@ -1342,6 +1342,10 @@ static_assert(SIMPLE_STR_LEN % sizeof(uintptr_t) == 0); void kernel_debug_string_simple(uint32_t eventid, const char *str) { + if (!kdebug_enable) { + return; + } + /* array of uintptr_ts simplifies emitting the string as arguments */ uintptr_t str_buf[(SIMPLE_STR_LEN / sizeof(uintptr_t)) + 1] = { 0 }; size_t len = strlcpy((char *)str_buf, str, SIMPLE_STR_LEN + 1); @@ -3477,12 +3481,12 @@ kdbg_control(int *name, u_int namelen, user_addr_t where, size_t *sizep) if (name[0] == KERN_KDWRITETR || name[0] == KERN_KDWRITETR_V3) { number = nkdbufs * sizeof(kd_buf); - KDBG(TRACE_WRITING_EVENTS | DBG_FUNC_START); + KDBG_RELEASE(TRACE_WRITING_EVENTS | DBG_FUNC_START); if (name[0] == KERN_KDWRITETR_V3) ret = kdbg_read(0, &number, vp, &context, RAW_VERSION3); else ret = kdbg_read(0, &number, vp, &context, RAW_VERSION1); - KDBG(TRACE_WRITING_EVENTS | DBG_FUNC_END, number); + KDBG_RELEASE(TRACE_WRITING_EVENTS | DBG_FUNC_END, number); *sizep = number; } else { @@ -3911,7 +3915,7 @@ kdbg_test(size_t flavor) } void -kdebug_init(unsigned int n_events, char *filter_desc) +kdebug_init(unsigned int n_events, char *filter_desc, boolean_t wrapping) { assert(filter_desc != NULL); @@ -3931,7 +3935,7 @@ kdebug_init(unsigned int n_events, char *filter_desc) n_events = 200000; } - kdebug_trace_start(n_events, filter_desc, FALSE); + kdebug_trace_start(n_events, filter_desc, wrapping, FALSE); } static void @@ -4005,10 +4009,8 @@ kdbg_set_typefilter_string(const char *filter_desc) */ void kdebug_trace_start(unsigned int n_events, const char *filter_desc, - boolean_t at_wake) + boolean_t wrapping, boolean_t at_wake) { - uint32_t old1, old2; - if (!n_events) { kd_early_done = true; return; @@ -4033,7 +4035,10 @@ kdebug_trace_start(unsigned int n_events, const char *filter_desc, * Wrapping is disabled because boot and wake tracing is interested in * the earliest events, at the expense of later ones. */ - (void)disable_wrap(&old1, &old2); + if (!wrapping) { + uint32_t old1, old2; + (void)disable_wrap(&old1, &old2); + } if (filter_desc && filter_desc[0] != '\0') { if (kdbg_initialize_typefilter(NULL) == KERN_SUCCESS) { @@ -4103,7 +4108,7 @@ kdbg_dump_trace_to_file(const char *filename) goto out; } - KDBG(TRACE_WRITING_EVENTS | DBG_FUNC_START); + KDBG_RELEASE(TRACE_WRITING_EVENTS | DBG_FUNC_START); kdebug_enable = 0; kd_ctrl_page.enabled = 0; @@ -4153,27 +4158,6 @@ kdbg_dump_trace_to_file(const char *filename) ktrace_unlock(); } -/* Helper function for filling in the BSD name for an address space - * Defined here because the machine bindings know only Mach threads - * and nothing about BSD processes. - * - * FIXME: need to grab a lock during this? - */ -void kdbg_get_task_name(char* name_buf, int len, task_t task) -{ - proc_t proc; - - /* Note: we can't use thread->task (and functions that rely on it) here - * because it hasn't been initialized yet when this function is called. - * We use the explicitly-passed task parameter instead. - */ - proc = get_bsdtask_info(task); - if (proc != PROC_NULL) - snprintf(name_buf, len, "%s/%d", proc->p_comm, proc->p_pid); - else - snprintf(name_buf, len, "%p [!bsd]", task); -} - static int kdbg_sysctl_continuous SYSCTL_HANDLER_ARGS { diff --git a/bsd/kern/kern_authorization.c b/bsd/kern/kern_authorization.c index 630a4c100..d6bf9cf91 100644 --- a/bsd/kern/kern_authorization.c +++ b/bsd/kern/kern_authorization.c @@ -132,7 +132,7 @@ static int kauth_authorize_generic_callback(kauth_cred_t _credential, void *_ida uintptr_t arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3); kauth_scope_t kauth_scope_fileop; -extern int cansignal(struct proc *, kauth_cred_t, struct proc *, int, int); +extern int cansignal(struct proc *, kauth_cred_t, struct proc *, int); extern char * get_pathbuff(void); extern void release_pathbuff(char *path); @@ -484,7 +484,7 @@ kauth_authorize_process_callback(kauth_cred_t credential, __unused void *idata, /* arg0 - process to signal * arg1 - signal to send the process */ - if (cansignal(current_proc(), credential, (struct proc *)arg0, (int)arg1, 0)) + if (cansignal(current_proc(), credential, (struct proc *)arg0, (int)arg1)) return(KAUTH_RESULT_ALLOW); break; case KAUTH_PROCESS_CANTRACE: diff --git a/bsd/kern/kern_cs.c b/bsd/kern/kern_cs.c index 0bf850955..92d1c43be 100644 --- a/bsd/kern/kern_cs.c +++ b/bsd/kern/kern_cs.c @@ -808,6 +808,93 @@ csfg_get_prod_signed(struct fileglob *fg) return prod_signed; } +/* + * Function: csfg_get_identity + * + * Description: This function returns the codesign identity + * for the fileglob + */ +const char * +csfg_get_identity(struct fileglob *fg, off_t offset) +{ + vnode_t vp; + struct cs_blob *csblob = NULL; + + if (FILEGLOB_DTYPE(fg) != DTYPE_VNODE) + return NULL; + + vp = (struct vnode *)fg->fg_data; + if (vp == NULL) + return NULL; + + csblob = ubc_cs_blob_get(vp, -1, offset); + if (csblob == NULL) + return NULL; + + return csblob_get_identity(csblob); +} + +/* + * Function: csfg_get_platform_identifier + * + * Description: This function returns the codesign platform + * identifier for the fileglob. Assumes the fileproc + * is being held busy to keep the fileglob consistent. + */ +uint8_t +csfg_get_platform_identifier(struct fileglob *fg, off_t offset) +{ + vnode_t vp; + + if (FILEGLOB_DTYPE(fg) != DTYPE_VNODE) + return 0; + + vp = (struct vnode *)fg->fg_data; + if (vp == NULL) + return 0; + + return csvnode_get_platform_identifier(vp, offset); +} + +/* + * Function: csvnode_get_platform_identifier + * + * Description: This function returns the codesign platform + * identifier for the vnode. Assumes a vnode reference + * is held. + */ +uint8_t +csvnode_get_platform_identifier(struct vnode *vp, off_t offset) +{ + struct cs_blob *csblob; + const CS_CodeDirectory *code_dir; + + csblob = ubc_cs_blob_get(vp, -1, offset); + if (csblob == NULL) + return 0; + + code_dir = csblob->csb_cd; + if (code_dir == NULL || ntohl(code_dir->length) < 8) + return 0; + + return code_dir->platform; +} + +/* + * Function: csproc_get_platform_identifier + * + * Description: This function returns the codesign platform + * identifier for the proc. Assumes proc will remain + * valid through call. + */ +uint8_t +csproc_get_platform_identifier(struct proc *p) +{ + if (NULL == p->p_textvp) + return 0; + + return csvnode_get_platform_identifier(p->p_textvp, p->p_textoff); +} uint32_t cs_entitlement_flags(struct proc *p) diff --git a/bsd/kern/kern_descrip.c b/bsd/kern/kern_descrip.c index 06f9b82a6..48904239e 100644 --- a/bsd/kern/kern_descrip.c +++ b/bsd/kern/kern_descrip.c @@ -87,6 +87,7 @@ #include #include #include +#include #include #include #include @@ -158,6 +159,18 @@ extern kauth_scope_t kauth_scope_fileop; /* Conflict wait queue for when selects collide (opaque type) */ extern struct waitq select_conflict_queue; +#ifndef HFS_GET_BOOT_INFO +#define HFS_GET_BOOT_INFO (FCNTL_FS_SPECIFIC_BASE + 0x00004) +#endif + +#ifndef HFS_SET_BOOT_INFO +#define HFS_SET_BOOT_INFO (FCNTL_FS_SPECIFIC_BASE + 0x00005) +#endif + +#ifndef APFSIOC_REVERT_TO_SNAPSHOT +#define APFSIOC_REVERT_TO_SNAPSHOT _IOW('J', 1, u_int64_t) +#endif + #define f_flag f_fglob->fg_flag #define f_type f_fglob->fg_ops->fo_type #define f_msgcount f_fglob->fg_msgcount @@ -2540,6 +2553,12 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, int32_t *retval) /* Catch any now-invalid fcntl() selectors */ switch (uap->cmd) { + case (int)APFSIOC_REVERT_TO_SNAPSHOT: + case (int)FSIOC_FIOSEEKHOLE: + case (int)FSIOC_FIOSEEKDATA: + case HFS_GET_BOOT_INFO: + case HFS_SET_BOOT_INFO: + case FIOPINSWAP: case F_MARKDEPENDENCY: error = EINVAL; goto out; diff --git a/bsd/kern/kern_event.c b/bsd/kern/kern_event.c index 12885133e..f07aa6d17 100644 --- a/bsd/kern/kern_event.c +++ b/bsd/kern/kern_event.c @@ -3039,51 +3039,51 @@ kqueue_dealloc(struct kqueue *kq) p = kq->kq_p; fdp = p->p_fd; - proc_fdlock(p); - for (i = 0; i < fdp->fd_knlistsize; i++) { - kn = SLIST_FIRST(&fdp->fd_knlist[i]); - while (kn != NULL) { - if (kq == knote_get_kq(kn)) { - assert((kq->kq_state & KQ_WORKLOOP) == 0); - kqlock(kq); - proc_fdunlock(p); - /* drop it ourselves or wait */ - if (kqlock2knotedrop(kq, kn)) { - knote_drop(kn, p); - } - proc_fdlock(p); - /* start over at beginning of list */ - kn = SLIST_FIRST(&fdp->fd_knlist[i]); - continue; - } - kn = SLIST_NEXT(kn, kn_link); - } - } - knhash_lock(p); - proc_fdunlock(p); - - if (fdp->fd_knhashmask != 0) { - for (i = 0; i < (int)fdp->fd_knhashmask + 1; i++) { - kn = SLIST_FIRST(&fdp->fd_knhash[i]); + if ((kq->kq_state & KQ_WORKLOOP) == 0) { + proc_fdlock(p); + for (i = 0; i < fdp->fd_knlistsize; i++) { + kn = SLIST_FIRST(&fdp->fd_knlist[i]); while (kn != NULL) { if (kq == knote_get_kq(kn)) { - assert((kq->kq_state & KQ_WORKLOOP) == 0); kqlock(kq); - knhash_unlock(p); + proc_fdunlock(p); /* drop it ourselves or wait */ if (kqlock2knotedrop(kq, kn)) { knote_drop(kn, p); } - knhash_lock(p); + proc_fdlock(p); /* start over at beginning of list */ - kn = SLIST_FIRST(&fdp->fd_knhash[i]); + kn = SLIST_FIRST(&fdp->fd_knlist[i]); continue; } kn = SLIST_NEXT(kn, kn_link); } } + knhash_lock(p); + proc_fdunlock(p); + + if (fdp->fd_knhashmask != 0) { + for (i = 0; i < (int)fdp->fd_knhashmask + 1; i++) { + kn = SLIST_FIRST(&fdp->fd_knhash[i]); + while (kn != NULL) { + if (kq == knote_get_kq(kn)) { + kqlock(kq); + knhash_unlock(p); + /* drop it ourselves or wait */ + if (kqlock2knotedrop(kq, kn)) { + knote_drop(kn, p); + } + knhash_lock(p); + /* start over at beginning of list */ + kn = SLIST_FIRST(&fdp->fd_knhash[i]); + continue; + } + kn = SLIST_NEXT(kn, kn_link); + } + } + } + knhash_unlock(p); } - knhash_unlock(p); if (kq->kq_state & KQ_WORKLOOP) { struct kqworkloop *kqwl = (struct kqworkloop *)kq; @@ -4274,6 +4274,9 @@ kevent_internal(struct proc *p, if ((flags & (KEVENT_FLAG_DYNAMIC_KQUEUE | KEVENT_FLAG_WORKLOOP)) == KEVENT_FLAG_DYNAMIC_KQUEUE) return EINVAL; + if ((flags & (KEVENT_FLAG_WORKLOOP)) && (flags & (KEVENT_FLAG_WORKQ))) + return EINVAL; + if (flags & (KEVENT_FLAG_WORKLOOP_SERVICER_ATTACH | KEVENT_FLAG_WORKLOOP_SERVICER_DETACH | KEVENT_FLAG_DYNAMIC_KQ_MUST_EXIST | KEVENT_FLAG_DYNAMIC_KQ_MUST_NOT_EXIST | KEVENT_FLAG_WORKLOOP_NO_WQ_THREAD)) { diff --git a/bsd/kern/kern_exec.c b/bsd/kern/kern_exec.c index 90334a790..e5ac6b2c7 100644 --- a/bsd/kern/kern_exec.c +++ b/bsd/kern/kern_exec.c @@ -973,6 +973,13 @@ exec_mach_imgact(struct image_params *imgp) exec_failure_reason = os_reason_create(OS_REASON_EXEC, EXEC_EXIT_REASON_UPX); exec_failure_reason->osr_flags |= OS_REASON_FLAG_GENERATE_CRASH_REPORT; exec_failure_reason->osr_flags |= OS_REASON_FLAG_CONSISTENT_FAILURE; + } else if (lret == LOAD_BADARCH_X86) { + /* set anything that might be useful in the crash report */ + set_proc_name(imgp, p); + + exec_failure_reason = os_reason_create(OS_REASON_EXEC, EXEC_EXIT_REASON_NO32EXEC); + exec_failure_reason->osr_flags |= OS_REASON_FLAG_GENERATE_CRASH_REPORT; + exec_failure_reason->osr_flags |= OS_REASON_FLAG_CONSISTENT_FAILURE; } else { exec_failure_reason = os_reason_create(OS_REASON_EXEC, EXEC_EXIT_REASON_BAD_MACHO); } @@ -1234,12 +1241,7 @@ exec_mach_imgact(struct image_params *imgp) #endif if (kdebug_enable) { - long dbg_arg1, dbg_arg2, dbg_arg3, dbg_arg4; - - /* - * Collect the pathname for tracing - */ - kdbg_trace_string(p, &dbg_arg1, &dbg_arg2, &dbg_arg3, &dbg_arg4); + long args[4] = {}; uintptr_t fsid = 0, fileid = 0; if (imgp->ip_vattr) { @@ -1251,10 +1253,15 @@ exec_mach_imgact(struct image_params *imgp) fsid = fileid = 0; } } - KERNEL_DEBUG_CONSTANT1(TRACE_DATA_EXEC | DBG_FUNC_NONE, - p->p_pid , fsid, fileid, 0, (uintptr_t)thread_tid(thread)); - KERNEL_DEBUG_CONSTANT1(TRACE_STRING_EXEC | DBG_FUNC_NONE, - dbg_arg1, dbg_arg2, dbg_arg3, dbg_arg4, (uintptr_t)thread_tid(thread)); + KERNEL_DEBUG_CONSTANT_IST1(TRACE_DATA_EXEC, p->p_pid, fsid, fileid, 0, + (uintptr_t)thread_tid(thread)); + + /* + * Collect the pathname for tracing + */ + kdbg_trace_string(p, &args[0], &args[1], &args[2], &args[3]); + KERNEL_DEBUG_CONSTANT_IST1(TRACE_STRING_EXEC, args[0], args[1], + args[2], args[3], (uintptr_t)thread_tid(thread)); } /* @@ -5195,13 +5202,14 @@ load_init_program(proc_t p) * EIO An I/O error occurred * EBADEXEC The executable is corrupt/unknown */ -static int +static int load_return_to_errno(load_return_t lrtn) { switch (lrtn) { case LOAD_SUCCESS: return 0; case LOAD_BADARCH: + case LOAD_BADARCH_X86: return EBADARCH; case LOAD_BADMACHO: case LOAD_BADMACHO_UPX: diff --git a/bsd/kern/kern_exit.c b/bsd/kern/kern_exit.c index f5ee01dc1..b2e226f06 100644 --- a/bsd/kern/kern_exit.c +++ b/bsd/kern/kern_exit.c @@ -337,6 +337,7 @@ populate_corpse_crashinfo(proc_t p, task_t corpse_task, struct rusage_superset * } } + static_assert(sizeof(struct proc_uniqidentifierinfo) == sizeof(struct crashinfo_proc_uniqidentifierinfo)); if (KERN_SUCCESS == kcdata_get_memory_addr(crash_info_ptr, TASK_CRASHINFO_BSDINFOWITHUNIQID, sizeof(struct proc_uniqidentifierinfo), &uaddr)) { proc_piduniqidentifierinfo(p, &p_uniqidinfo); @@ -2181,7 +2182,7 @@ waitid_nocancel(proc_t q, struct waitid_nocancel_args *uap, * make process 'parent' the new parent of process 'child'. */ void -proc_reparentlocked(proc_t child, proc_t parent, int cansignal, int locked) +proc_reparentlocked(proc_t child, proc_t parent, int signallable, int locked) { proc_t oldparent = PROC_NULL; @@ -2214,7 +2215,7 @@ proc_reparentlocked(proc_t child, proc_t parent, int cansignal, int locked) proc_list_unlock(); - if ((cansignal != 0) && (initproc == parent) && (child->p_stat == SZOMB)) + if ((signallable != 0) && (initproc == parent) && (child->p_stat == SZOMB)) psignal(initproc, SIGCHLD); if (locked == 1) proc_list_lock(); diff --git a/bsd/kern/kern_malloc.c b/bsd/kern/kern_malloc.c index e5ae62f3f..6e28f3f77 100644 --- a/bsd/kern/kern_malloc.c +++ b/bsd/kern/kern_malloc.c @@ -785,19 +785,41 @@ sysctl_zone_map_jetsam_limit SYSCTL_HANDLER_ARGS SYSCTL_PROC(_kern, OID_AUTO, zone_map_jetsam_limit, CTLTYPE_INT|CTLFLAG_RW, 0, 0, sysctl_zone_map_jetsam_limit, "I", "Zone map jetsam limit"); + +extern void get_zone_map_size(uint64_t *current_size, uint64_t *capacity); + +static int +sysctl_zone_map_size_and_capacity SYSCTL_HANDLER_ARGS +{ +#pragma unused(oidp, arg1, arg2) + uint64_t zstats[2]; + get_zone_map_size(&zstats[0], &zstats[1]); + + return SYSCTL_OUT(req, &zstats, sizeof(zstats)); +} + +SYSCTL_PROC(_kern, OID_AUTO, zone_map_size_and_capacity, + CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, + 0, 0, &sysctl_zone_map_size_and_capacity, "Q", "Current size and capacity of the zone map"); + + extern boolean_t run_zone_test(void); static int sysctl_run_zone_test SYSCTL_HANDLER_ARGS { #pragma unused(oidp, arg1, arg2) - int ret_val = run_zone_test(); + /* require setting this sysctl to prevent sysctl -a from running this */ + if (!req->newptr) { + return 0; + } + int ret_val = run_zone_test(); return SYSCTL_OUT(req, &ret_val, sizeof(ret_val)); } SYSCTL_PROC(_kern, OID_AUTO, run_zone_test, - CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MASKED | CTLFLAG_LOCKED, + CTLTYPE_INT | CTLFLAG_WR | CTLFLAG_MASKED | CTLFLAG_LOCKED, 0, 0, &sysctl_run_zone_test, "I", "Test zone allocator KPI"); #endif /* DEBUG || DEVELOPMENT */ diff --git a/bsd/kern/kern_memorystatus.c b/bsd/kern/kern_memorystatus.c index 54e431d05..a2de71f0f 100644 --- a/bsd/kern/kern_memorystatus.c +++ b/bsd/kern/kern_memorystatus.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2006-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -317,7 +317,11 @@ unsigned int jetsam_aging_policy = kJetsamAgingPolicyLegacy; extern int corpse_for_fatal_memkill; extern unsigned long total_corpses_count(void) __attribute__((pure)); extern void task_purge_all_corpses(void); -boolean_t memorystatus_allowed_vm_map_fork(__unused task_t); +extern uint64_t vm_purgeable_purge_task_owned(task_t task); +boolean_t memorystatus_allowed_vm_map_fork(task_t); +#if DEVELOPMENT || DEBUG +void memorystatus_abort_vm_map_fork(task_t); +#endif #if 0 @@ -626,7 +630,7 @@ static uint32_t memorystatus_build_state(proc_t p); static boolean_t memorystatus_kill_top_process(boolean_t any, boolean_t sort_flag, uint32_t cause, os_reason_t jetsam_reason, int32_t *priority, uint32_t *errors); static boolean_t memorystatus_kill_top_process_aggressive(uint32_t cause, int aggr_count, int32_t priority_max, uint32_t *errors); static boolean_t memorystatus_kill_elevated_process(uint32_t cause, os_reason_t jetsam_reason, int aggr_count, uint32_t *errors); -static boolean_t memorystatus_kill_hiwat_proc(uint32_t *errors); +static boolean_t memorystatus_kill_hiwat_proc(uint32_t *errors, boolean_t *purged); static boolean_t memorystatus_kill_process_async(pid_t victim_pid, uint32_t cause); @@ -3379,14 +3383,18 @@ memorystatus_action_needed(void) static boolean_t memorystatus_act_on_hiwat_processes(uint32_t *errors, uint32_t *hwm_kill, boolean_t *post_snapshot, __unused boolean_t *is_critical) { - boolean_t killed = memorystatus_kill_hiwat_proc(errors); + boolean_t purged = FALSE; + boolean_t killed = memorystatus_kill_hiwat_proc(errors, &purged); if (killed) { *hwm_kill = *hwm_kill + 1; *post_snapshot = TRUE; return TRUE; } else { - memorystatus_hwm_candidates = FALSE; + if (purged == FALSE) { + /* couldn't purge and couldn't kill */ + memorystatus_hwm_candidates = FALSE; + } } #if CONFIG_JETSAM @@ -4123,6 +4131,10 @@ memorystatus_get_task_memory_region_count(task_t task, uint64_t *count) *count = get_task_memory_region_count(task); } + +#define MEMORYSTATUS_VM_MAP_FORK_ALLOWED 0x100000000 +#define MEMORYSTATUS_VM_MAP_FORK_NOT_ALLOWED 0x200000000 + #if DEVELOPMENT || DEBUG /* @@ -4130,11 +4142,15 @@ memorystatus_get_task_memory_region_count(task_t task, uint64_t *count) * set a new pidwatch value * or * get the current pidwatch value + * + * The pidwatch_val starts out with a PID to watch for in the map_fork path. + * Its value is: + * - OR'd with MEMORYSTATUS_VM_MAP_FORK_ALLOWED if we allow the map_fork. + * - OR'd with MEMORYSTATUS_VM_MAP_FORK_NOT_ALLOWED if we disallow the map_fork. + * - set to -1ull if the map_fork() is aborted for other reasons. */ uint64_t memorystatus_vm_map_fork_pidwatch_val = 0; -#define MEMORYSTATUS_VM_MAP_FORK_ALLOWED 0x100000000 -#define MEMORYSTATUS_VM_MAP_FORK_NOT_ALLOWED 0x200000000 static int sysctl_memorystatus_vm_map_fork_pidwatch SYSCTL_HANDLER_ARGS { #pragma unused(oidp, arg1, arg2) @@ -4172,30 +4188,40 @@ SYSCTL_PROC(_kern, OID_AUTO, memorystatus_vm_map_fork_pidwatch, CTLTYPE_QUAD | C 0, 0, sysctl_memorystatus_vm_map_fork_pidwatch, "Q", "get/set pid watched for in vm_map_fork"); -#define SET_VM_MAP_FORK_PIDWATCH_ALLOWED(task) \ -MACRO_BEGIN \ -if (memorystatus_vm_map_fork_pidwatch_val != 0) { \ - proc_t p = get_bsdtask_info(task); \ - if (p && (memorystatus_vm_map_fork_pidwatch_val == (uint64_t)p->p_pid)) { \ - memorystatus_vm_map_fork_pidwatch_val |= MEMORYSTATUS_VM_MAP_FORK_ALLOWED; \ - } \ -} \ -MACRO_END +/* + * Record if a watched process fails to qualify for a vm_map_fork(). + */ +void +memorystatus_abort_vm_map_fork(task_t task) +{ + if (memorystatus_vm_map_fork_pidwatch_val != 0) { + proc_t p = get_bsdtask_info(task); + if (p != NULL && memorystatus_vm_map_fork_pidwatch_val == (uint64_t)p->p_pid) { + memorystatus_vm_map_fork_pidwatch_val = -1ull; + } + } +} -#define SET_VM_MAP_FORK_PIDWATCH_NOT_ALLOWED(task) \ -MACRO_BEGIN \ -if (memorystatus_vm_map_fork_pidwatch_val != 0) { \ - proc_t p = get_bsdtask_info(task); \ - if (p && (memorystatus_vm_map_fork_pidwatch_val == (uint64_t)p->p_pid)) { \ - memorystatus_vm_map_fork_pidwatch_val |= MEMORYSTATUS_VM_MAP_FORK_NOT_ALLOWED; \ - } \ -} \ -MACRO_END +static void +set_vm_map_fork_pidwatch(task_t task, uint64_t x) +{ + if (memorystatus_vm_map_fork_pidwatch_val != 0) { + proc_t p = get_bsdtask_info(task); + if (p && (memorystatus_vm_map_fork_pidwatch_val == (uint64_t)p->p_pid)) { + memorystatus_vm_map_fork_pidwatch_val |= x; + } + } +} #else /* DEVELOPMENT || DEBUG */ -#define SET_VM_MAP_FORK_PIDWATCH_ALLOWED(task) -#define SET_VM_MAP_FORK_PIDWATCH_NOT_ALLOWED(task) + +static void +set_vm_map_fork_pidwatch(task_t task, uint64_t x) +{ +#pragma unused(task) +#pragma unused(x) +} #endif /* DEVELOPMENT || DEBUG */ @@ -4221,18 +4247,18 @@ MACRO_END * munch memory up to the system-wide task limit. */ boolean_t -memorystatus_allowed_vm_map_fork(__unused task_t task) +memorystatus_allowed_vm_map_fork(task_t task) { boolean_t is_allowed = TRUE; /* default */ #if CONFIG_EMBEDDED - uint64_t footprint_in_bytes = 0; - uint64_t purgeable_in_bytes = 0; - uint64_t max_allowed_bytes = 0; + uint64_t footprint_in_bytes; + uint64_t purgeable_in_bytes; + uint64_t max_allowed_bytes; if (max_task_footprint_mb == 0) { - SET_VM_MAP_FORK_PIDWATCH_ALLOWED(task); + set_vm_map_fork_pidwatch(task, MEMORYSTATUS_VM_MAP_FORK_ALLOWED); return (is_allowed); } @@ -4242,28 +4268,22 @@ memorystatus_allowed_vm_map_fork(__unused task_t task) /* * Maximum is half the system-wide task limit. */ - max_allowed_bytes = ((((uint64_t)max_task_footprint_mb) * 1024ULL * 1024ULL) >> 1); + max_allowed_bytes = ((uint64_t)max_task_footprint_mb * 1024 * 1024) >> 1; if (footprint_in_bytes > purgeable_in_bytes) { footprint_in_bytes -= purgeable_in_bytes; } - if (footprint_in_bytes <= max_allowed_bytes) { - SET_VM_MAP_FORK_PIDWATCH_ALLOWED(task); - return (is_allowed); - } else { + if (footprint_in_bytes > max_allowed_bytes) { printf("memorystatus disallowed vm_map_fork %lld %lld\n", footprint_in_bytes, max_allowed_bytes); - SET_VM_MAP_FORK_PIDWATCH_NOT_ALLOWED(task); + set_vm_map_fork_pidwatch(task, MEMORYSTATUS_VM_MAP_FORK_NOT_ALLOWED); return (!is_allowed); } +#endif /* CONFIG_EMBEDDED */ -#else /* CONFIG_EMBEDDED */ - - SET_VM_MAP_FORK_PIDWATCH_ALLOWED(task); + set_vm_map_fork_pidwatch(task, MEMORYSTATUS_VM_MAP_FORK_ALLOWED); return (is_allowed); -#endif /* CONFIG_EMBEDDED */ - } static void @@ -4631,7 +4651,7 @@ memorystatus_init_snapshot_vmstats(memorystatus_jetsam_snapshot_t *snapshot) mach_msg_type_number_t count = HOST_VM_INFO64_COUNT; vm_statistics64_data_t vm_stat; - if ((kr = host_statistics64(host_self(), HOST_VM_INFO64, (host_info64_t)&vm_stat, &count) != KERN_SUCCESS)) { + if ((kr = host_statistics64(host_self(), HOST_VM_INFO64, (host_info64_t)&vm_stat, &count)) != KERN_SUCCESS) { printf("memorystatus_init_jetsam_snapshot_stats: host_statistics64 failed with %d\n", kr); memset(&snapshot->stats, 0, sizeof(snapshot->stats)); } else { @@ -4784,6 +4804,137 @@ memorystatus_cmd_test_jetsam_sort(int priority, int sort_order) { #endif /* DEVELOPMENT || DEBUG */ +/* + * Prepare the process to be killed (set state, update snapshot) and kill it. + */ +static uint64_t memorystatus_purge_before_jetsam_success = 0; + +static boolean_t +memorystatus_kill_proc(proc_t p, uint32_t cause, os_reason_t jetsam_reason, boolean_t *killed) +{ + pid_t aPid = 0; + uint32_t aPid_ep = 0; + + uint64_t killtime = 0; + clock_sec_t tv_sec; + clock_usec_t tv_usec; + uint32_t tv_msec; + boolean_t retval = FALSE; + uint64_t num_pages_purged = 0; + + aPid = p->p_pid; + aPid_ep = p->p_memstat_effectivepriority; + + if (cause != kMemorystatusKilledVnodes && cause != kMemorystatusKilledZoneMapExhaustion) { + /* + * Genuine memory pressure and not other (vnode/zone) resource exhaustion. + */ + boolean_t success = FALSE; + + networking_memstatus_callout(p, cause); + num_pages_purged = vm_purgeable_purge_task_owned(p->task); + + if (num_pages_purged) { + /* + * We actually purged something and so let's + * check if we need to continue with the kill. + */ + if (cause == kMemorystatusKilledHiwat) { + uint64_t footprint_in_bytes = get_task_phys_footprint(p->task); + uint64_t memlimit_in_bytes = (((uint64_t)p->p_memstat_memlimit) * 1024ULL * 1024ULL); /* convert MB to bytes */ + success = (footprint_in_bytes <= memlimit_in_bytes); + } else { + success = (memorystatus_avail_pages_below_pressure() == FALSE); + } + + if (success) { + + memorystatus_purge_before_jetsam_success++; + + os_log_with_startup_serial(OS_LOG_DEFAULT, "memorystatus: purged %llu pages from pid %d [%s] and avoided %s\n", + num_pages_purged, aPid, (*p->p_name ? p->p_name : "unknown"), memorystatus_kill_cause_name[cause]); + + *killed = FALSE; + + return TRUE; + } + } + } + +#if CONFIG_JETSAM && (DEVELOPMENT || DEBUG) + MEMORYSTATUS_DEBUG(1, "jetsam: %s pid %d [%s] - %lld Mb > 1 (%d Mb)\n", + (memorystatus_jetsam_policy & kPolicyDiagnoseActive) ? "suspending": "killing", + aPid, (*p->p_name ? p->p_name : "unknown"), + (footprint_in_bytes / (1024ULL * 1024ULL)), /* converted bytes to MB */ + p->p_memstat_memlimit); +#endif /* CONFIG_JETSAM && (DEVELOPMENT || DEBUG) */ + + killtime = mach_absolute_time(); + absolutetime_to_microtime(killtime, &tv_sec, &tv_usec); + tv_msec = tv_usec / 1000; + +#if CONFIG_JETSAM && (DEVELOPMENT || DEBUG) + if (memorystatus_jetsam_policy & kPolicyDiagnoseActive) { + if (cause == kMemorystatusKilledHiwat) { + MEMORYSTATUS_DEBUG(1, "jetsam: suspending pid %d [%s] for diagnosis - memorystatus_available_pages: %d\n", + aPid, (*p->p_name ? p->p_name: "(unknown)"), memorystatus_available_pages); + } else { + int activeProcess = p->p_memstat_state & P_MEMSTAT_FOREGROUND; + if (activeProcess) { + MEMORYSTATUS_DEBUG(1, "jetsam: suspending pid %d [%s] (active) for diagnosis - memorystatus_available_pages: %d\n", + aPid, (*p->p_name ? p->p_name: "(unknown)"), memorystatus_available_pages); + + if (memorystatus_jetsam_policy & kPolicyDiagnoseFirst) { + jetsam_diagnostic_suspended_one_active_proc = 1; + printf("jetsam: returning after suspending first active proc - %d\n", aPid); + } + } + } + + memorystatus_update_jetsam_snapshot_entry_locked(p, kMemorystatusKilledDiagnostic, killtime); + p->p_memstat_state |= P_MEMSTAT_DIAG_SUSPENDED; + + if (p) { + task_suspend(p->task); + *killed = TRUE; + } + } else +#endif /* CONFIG_JETSAM && (DEVELOPMENT || DEBUG) */ + { + memorystatus_update_jetsam_snapshot_entry_locked(p, cause, killtime); + + char kill_reason_string[128]; + + if (cause == kMemorystatusKilledHiwat) { + strlcpy(kill_reason_string, "killing_highwater_process", 128); + } else { + if (aPid_ep == JETSAM_PRIORITY_IDLE) { + strlcpy(kill_reason_string, "killing_idle_process", 128); + } else { + strlcpy(kill_reason_string, "killing_top_process", 128); + } + } + + os_log_with_startup_serial(OS_LOG_DEFAULT, "%lu.%03d memorystatus: %s pid %d [%s] (%s %d) - memorystatus_available_pages: %llu\n", + (unsigned long)tv_sec, tv_msec, kill_reason_string, + aPid, (*p->p_name ? p->p_name : "unknown"), + memorystatus_kill_cause_name[cause], aPid_ep, (uint64_t)memorystatus_available_pages); + + /* + * memorystatus_do_kill drops a reference, so take another one so we can + * continue to use this exit reason even after memorystatus_do_kill() + * returns + */ + os_reason_ref(jetsam_reason); + + retval = memorystatus_do_kill(p, cause, jetsam_reason); + + *killed = retval; + } + + return retval; +} + /* * Jetsam the first process in the queue. */ @@ -4793,14 +4944,9 @@ memorystatus_kill_top_process(boolean_t any, boolean_t sort_flag, uint32_t cause { pid_t aPid; proc_t p = PROC_NULL, next_p = PROC_NULL; - boolean_t new_snapshot = FALSE, force_new_snapshot = FALSE, killed = FALSE; - int kill_count = 0; + boolean_t new_snapshot = FALSE, force_new_snapshot = FALSE, killed = FALSE, freed_mem = FALSE; unsigned int i = 0; uint32_t aPid_ep; - uint64_t killtime = 0; - clock_sec_t tv_sec; - clock_usec_t tv_usec; - uint32_t tv_msec; int32_t local_max_kill_prio = JETSAM_PRIORITY_IDLE; #ifndef CONFIG_FREEZE @@ -4859,7 +5005,6 @@ memorystatus_kill_top_process(boolean_t any, boolean_t sort_flag, uint32_t cause next_p = memorystatus_get_first_proc_locked(&i, TRUE); while (next_p && (next_p->p_memstat_effectivepriority <= local_max_kill_prio)) { #if DEVELOPMENT || DEBUG - int activeProcess; int procSuspendedForDiagnosis; #endif /* DEVELOPMENT || DEBUG */ @@ -4867,7 +5012,6 @@ memorystatus_kill_top_process(boolean_t any, boolean_t sort_flag, uint32_t cause next_p = memorystatus_get_next_proc_locked(&i, p, TRUE); #if DEVELOPMENT || DEBUG - activeProcess = p->p_memstat_state & P_MEMSTAT_FOREGROUND; procSuspendedForDiagnosis = p->p_memstat_state & P_MEMSTAT_DIAG_SUSPENDED; #endif /* DEVELOPMENT || DEBUG */ @@ -4915,6 +5059,28 @@ memorystatus_kill_top_process(boolean_t any, boolean_t sort_flag, uint32_t cause } else #endif { + if (proc_ref_locked(p) == p) { + /* + * Mark as terminated so that if exit1() indicates success, but the process (for example) + * is blocked in task_exception_notify(), it'll be skipped if encountered again - see + * . This is cheaper than examining P_LEXIT, which requires the + * acquisition of the proc lock. + */ + p->p_memstat_state |= P_MEMSTAT_TERMINATED; + + proc_list_unlock(); + } else { + /* + * We need to restart the search again because + * proc_ref_locked _can_ drop the proc_list lock + * and we could have lost our stored next_p via + * an exit() on another core. + */ + i = 0; + next_p = memorystatus_get_first_proc_locked(&i, TRUE); + continue; + } + /* * Capture a snapshot if none exists and: * - we are forcing a new snapshot creation, either because: @@ -4928,101 +5094,36 @@ memorystatus_kill_top_process(boolean_t any, boolean_t sort_flag, uint32_t cause memorystatus_init_jetsam_snapshot_locked(NULL,0); new_snapshot = TRUE; } - - /* - * Mark as terminated so that if exit1() indicates success, but the process (for example) - * is blocked in task_exception_notify(), it'll be skipped if encountered again - see - * . This is cheaper than examining P_LEXIT, which requires the - * acquisition of the proc lock. - */ - p->p_memstat_state |= P_MEMSTAT_TERMINATED; - killtime = mach_absolute_time(); - absolutetime_to_microtime(killtime, &tv_sec, &tv_usec); - tv_msec = tv_usec / 1000; - -#if CONFIG_JETSAM && (DEVELOPMENT || DEBUG) - if ((memorystatus_jetsam_policy & kPolicyDiagnoseActive) && activeProcess) { - MEMORYSTATUS_DEBUG(1, "jetsam: suspending pid %d [%s] (active) for diagnosis - memory_status_level: %d\n", - aPid, (*p->p_name ? p->p_name: "(unknown)"), memorystatus_level); - memorystatus_update_jetsam_snapshot_entry_locked(p, kMemorystatusKilledDiagnostic, killtime); - p->p_memstat_state |= P_MEMSTAT_DIAG_SUSPENDED; - if (memorystatus_jetsam_policy & kPolicyDiagnoseFirst) { - jetsam_diagnostic_suspended_one_active_proc = 1; - printf("jetsam: returning after suspending first active proc - %d\n", aPid); - } - - p = proc_ref_locked(p); - proc_list_unlock(); - if (p) { - task_suspend(p->task); + freed_mem = memorystatus_kill_proc(p, cause, jetsam_reason, &killed); /* purged and/or killed 'p' */ + /* Success? */ + if (freed_mem) { + if (killed) { if (priority) { *priority = aPid_ep; } - proc_rele(p); - killed = TRUE; - } - - goto exit; - } else -#endif /* CONFIG_JETSAM && (DEVELOPMENT || DEBUG) */ - { - /* Shift queue, update stats */ - memorystatus_update_jetsam_snapshot_entry_locked(p, cause, killtime); - - if (proc_ref_locked(p) == p) { - proc_list_unlock(); - os_log_with_startup_serial(OS_LOG_DEFAULT, "%lu.%03d memorystatus: %s pid %d [%s] (%s %d) - memorystatus_available_pages: %llu\n", - (unsigned long)tv_sec, tv_msec, - ((aPid_ep == JETSAM_PRIORITY_IDLE) ? "killing_idle_process" : "killing_top_process"), - aPid, (*p->p_name ? p->p_name : "unknown"), - memorystatus_kill_cause_name[cause], aPid_ep, (uint64_t)memorystatus_available_pages); - - /* - * memorystatus_do_kill() drops a reference, so take another one so we can - * continue to use this exit reason even after memorystatus_do_kill() - * returns. - */ - os_reason_ref(jetsam_reason); - - killed = memorystatus_do_kill(p, cause, jetsam_reason); - - /* Success? */ - if (killed) { - if (priority) { - *priority = aPid_ep; - } - proc_rele(p); - kill_count++; - goto exit; - } - - /* - * Failure - first unwind the state, - * then fall through to restart the search. - */ + } else { + /* purged */ proc_list_lock(); - proc_rele_locked(p); p->p_memstat_state &= ~P_MEMSTAT_TERMINATED; - p->p_memstat_state |= P_MEMSTAT_ERROR; - *errors += 1; + proc_list_unlock(); } - - /* - * Failure - restart the search. - * - * We might have raced with "p" exiting on another core, resulting in no - * ref on "p". Or, we may have failed to kill "p". - * - * Either way, we fall thru to here, leaving the proc in the - * P_MEMSTAT_TERMINATED state. - * - * And, we hold the the proc_list_lock at this point. - */ - - i = 0; - next_p = memorystatus_get_first_proc_locked(&i, TRUE); + proc_rele(p); + goto exit; } + + /* + * Failure - first unwind the state, + * then fall through to restart the search. + */ + proc_list_lock(); + proc_rele_locked(p); + p->p_memstat_state &= ~P_MEMSTAT_TERMINATED; + p->p_memstat_state |= P_MEMSTAT_ERROR; + *errors += 1; + + i = 0; + next_p = memorystatus_get_first_proc_locked(&i, TRUE); } } @@ -5039,7 +5140,7 @@ memorystatus_kill_top_process(boolean_t any, boolean_t sort_flag, uint32_t cause } KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_MEMSTAT, BSD_MEMSTAT_JETSAM) | DBG_FUNC_END, - memorystatus_available_pages, killed ? aPid : 0, kill_count, 0, 0); + memorystatus_available_pages, killed ? aPid : 0, 0, 0, 0); return killed; } @@ -5283,18 +5384,13 @@ memorystatus_kill_top_process_aggressive(uint32_t cause, int aggr_count, } static boolean_t -memorystatus_kill_hiwat_proc(uint32_t *errors) +memorystatus_kill_hiwat_proc(uint32_t *errors, boolean_t *purged) { pid_t aPid = 0; proc_t p = PROC_NULL, next_p = PROC_NULL; - boolean_t new_snapshot = FALSE, killed = FALSE; - int kill_count = 0; + boolean_t new_snapshot = FALSE, killed = FALSE, freed_mem = FALSE; unsigned int i = 0; uint32_t aPid_ep; - uint64_t killtime = 0; - clock_sec_t tv_sec; - clock_usec_t tv_usec; - uint32_t tv_msec; os_reason_t jetsam_reason = OS_REASON_NULL; KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_MEMSTAT, BSD_MEMSTAT_JETSAM_HIWAT) | DBG_FUNC_START, memorystatus_available_pages, 0, 0, 0, 0); @@ -5352,93 +5448,61 @@ memorystatus_kill_hiwat_proc(uint32_t *errors) if (skip) { continue; } else { -#if CONFIG_JETSAM && (DEVELOPMENT || DEBUG) - MEMORYSTATUS_DEBUG(1, "jetsam: %s pid %d [%s] - %lld Mb > 1 (%d Mb)\n", - (memorystatus_jetsam_policy & kPolicyDiagnoseActive) ? "suspending": "killing", - aPid, (*p->p_name ? p->p_name : "unknown"), - (footprint_in_bytes / (1024ULL * 1024ULL)), /* converted bytes to MB */ - p->p_memstat_memlimit); -#endif /* CONFIG_JETSAM && (DEVELOPMENT || DEBUG) */ - + if (memorystatus_jetsam_snapshot_count == 0) { memorystatus_init_jetsam_snapshot_locked(NULL,0); - new_snapshot = TRUE; - } - - p->p_memstat_state |= P_MEMSTAT_TERMINATED; + new_snapshot = TRUE; + } + + if (proc_ref_locked(p) == p) { + /* + * Mark as terminated so that if exit1() indicates success, but the process (for example) + * is blocked in task_exception_notify(), it'll be skipped if encountered again - see + * . This is cheaper than examining P_LEXIT, which requires the + * acquisition of the proc lock. + */ + p->p_memstat_state |= P_MEMSTAT_TERMINATED; - killtime = mach_absolute_time(); - absolutetime_to_microtime(killtime, &tv_sec, &tv_usec); - tv_msec = tv_usec / 1000; - -#if CONFIG_JETSAM && (DEVELOPMENT || DEBUG) - if (memorystatus_jetsam_policy & kPolicyDiagnoseActive) { - MEMORYSTATUS_DEBUG(1, "jetsam: pid %d suspended for diagnosis - memorystatus_available_pages: %d\n", aPid, memorystatus_available_pages); - memorystatus_update_jetsam_snapshot_entry_locked(p, kMemorystatusKilledDiagnostic, killtime); - p->p_memstat_state |= P_MEMSTAT_DIAG_SUSPENDED; - - p = proc_ref_locked(p); proc_list_unlock(); - if (p) { - task_suspend(p->task); - proc_rele(p); - killed = TRUE; - } - - goto exit; - } else -#endif /* CONFIG_JETSAM && (DEVELOPMENT || DEBUG) */ - { - memorystatus_update_jetsam_snapshot_entry_locked(p, kMemorystatusKilledHiwat, killtime); - - if (proc_ref_locked(p) == p) { - proc_list_unlock(); - - os_log_with_startup_serial(OS_LOG_DEFAULT, "%lu.%03d memorystatus: killing_highwater_process pid %d [%s] (highwater %d) - memorystatus_available_pages: %llu\n", - (unsigned long)tv_sec, tv_msec, aPid, (*p->p_name ? p->p_name : "unknown"), aPid_ep, (uint64_t)memorystatus_available_pages); - - /* - * memorystatus_do_kill drops a reference, so take another one so we can - * continue to use this exit reason even after memorystatus_do_kill() - * returns - */ - os_reason_ref(jetsam_reason); - - killed = memorystatus_do_kill(p, kMemorystatusKilledHiwat, jetsam_reason); + } else { + /* + * We need to restart the search again because + * proc_ref_locked _can_ drop the proc_list lock + * and we could have lost our stored next_p via + * an exit() on another core. + */ + i = 0; + next_p = memorystatus_get_first_proc_locked(&i, TRUE); + continue; + } + + freed_mem = memorystatus_kill_proc(p, kMemorystatusKilledHiwat, jetsam_reason, &killed); /* purged and/or killed 'p' */ - /* Success? */ - if (killed) { - proc_rele(p); - kill_count++; - goto exit; - } + /* Success? */ + if (freed_mem) { + if (killed == FALSE) { + /* purged 'p'..don't reset HWM candidate count */ + *purged = TRUE; - /* - * Failure - first unwind the state, - * then fall through to restart the search. - */ proc_list_lock(); - proc_rele_locked(p); p->p_memstat_state &= ~P_MEMSTAT_TERMINATED; - p->p_memstat_state |= P_MEMSTAT_ERROR; - *errors += 1; + proc_list_unlock(); } - - /* - * Failure - restart the search. - * - * We might have raced with "p" exiting on another core, resulting in no - * ref on "p". Or, we may have failed to kill "p". - * - * Either way, we fall thru to here, leaving the proc in the - * P_MEMSTAT_TERMINATED state. - * - * And, we hold the the proc_list_lock at this point. - */ - - i = 0; - next_p = memorystatus_get_first_proc_locked(&i, TRUE); + proc_rele(p); + goto exit; } + /* + * Failure - first unwind the state, + * then fall through to restart the search. + */ + proc_list_lock(); + proc_rele_locked(p); + p->p_memstat_state &= ~P_MEMSTAT_TERMINATED; + p->p_memstat_state |= P_MEMSTAT_ERROR; + *errors += 1; + + i = 0; + next_p = memorystatus_get_first_proc_locked(&i, TRUE); } } @@ -5455,7 +5519,7 @@ memorystatus_kill_hiwat_proc(uint32_t *errors) } KERNEL_DEBUG_CONSTANT(BSDDBG_CODE(DBG_BSD_MEMSTAT, BSD_MEMSTAT_JETSAM_HIWAT) | DBG_FUNC_END, - memorystatus_available_pages, killed ? aPid : 0, kill_count, 0, 0); + memorystatus_available_pages, killed ? aPid : 0, 0, 0, 0); return killed; } @@ -7253,7 +7317,7 @@ memorystatus_get_priority_list(memorystatus_priority_entry_t **list_ptr, size_t } *list_ptr = (memorystatus_priority_entry_t*)kalloc(*list_size); - if (!list_ptr) { + if (!*list_ptr) { return ENOMEM; } diff --git a/bsd/kern/kern_mib.c b/bsd/kern/kern_mib.c index d3a9e2c06..35115e557 100644 --- a/bsd/kern/kern_mib.c +++ b/bsd/kern/kern_mib.c @@ -2,7 +2,7 @@ * Copyright (c) 2000-2007 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in @@ -11,10 +11,10 @@ * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. - * + * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -22,7 +22,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /*- @@ -154,6 +154,9 @@ SYSCTL_NODE(, CTL_MACHDEP, machdep, CTLFLAG_RW|CTLFLAG_LOCKED, 0, SYSCTL_NODE(, CTL_USER, user, CTLFLAG_RW|CTLFLAG_LOCKED, 0, "user-level"); +SYSCTL_NODE(_kern, OID_AUTO, bridge, CTLFLAG_RW|CTLFLAG_LOCKED, 0, + "bridge"); + #define SYSCTL_RETURN(r, x) SYSCTL_OUT(r, &x, sizeof(x)) /****************************************************************************** @@ -171,7 +174,7 @@ SYSCTL_NODE(, CTL_USER, user, CTLFLAG_RW|CTLFLAG_LOCKED, 0, /* - * Supporting some variables requires us to do "real" work. We + * Supporting some variables requires us to do "real" work. We * gather some of that here. */ static int @@ -405,7 +408,7 @@ SYSCTL_INT (_hw, OID_AUTO, packages, CTLFLAG_RD | CTLFLAG_KERN | CTLFLAG_LOC * * If the feature is not present, the node should either not be registered, * or it should return -1. If the feature is present, the node should return - * 0. If the feature is present and its use is advised, the node should + * 0. If the feature is present and its use is advised, the node should * return 1. */ SYSCTL_NODE(_hw, OID_AUTO, optional, CTLFLAG_RW|CTLFLAG_LOCKED, NULL, "optional features"); @@ -457,7 +460,7 @@ sysctl_cpu_capability { uint64_t mask = (uint64_t) (uintptr_t) arg1; boolean_t is_capable = (_get_cpu_capabilities() & mask) != 0; - + return SYSCTL_OUT(req, &is_capable, sizeof(is_capable)); } diff --git a/bsd/kern/kern_mman.c b/bsd/kern/kern_mman.c index 1c6979473..f373a0c79 100644 --- a/bsd/kern/kern_mman.c +++ b/bsd/kern/kern_mman.c @@ -301,7 +301,8 @@ mmap(proc_t p, struct mmap_args *uap, user_addr_t *retval) */ alloc_flags = fd & (VM_FLAGS_ALIAS_MASK | VM_FLAGS_SUPERPAGE_MASK | - VM_FLAGS_PURGABLE); + VM_FLAGS_PURGABLE | + VM_FLAGS_4GB_CHUNK); if (alloc_flags != fd) { /* reject if there are any extra flags */ return EINVAL; @@ -607,6 +608,14 @@ mmap(proc_t p, struct mmap_args *uap, user_addr_t *retval) /* strictly limit access to "prot" */ maxprot &= prot; } + + vm_object_offset_t end_pos = 0; + if (os_add_overflow(user_size, file_pos, &end_pos)) { + vnode_put(vp); + error = EINVAL; + goto bad; + } + result = vm_map_enter_mem_object_control(user_map, &user_addr, user_size, 0, alloc_flags, vmk_flags, @@ -1012,14 +1021,14 @@ mincore(__unused proc_t p, struct mincore_args *uap, __unused int32_t *retval) vm_map_t map = VM_MAP_NULL; user_addr_t vec = 0; int error = 0; - int vecindex = 0, lastvecindex = 0; + int lastvecindex = 0; int mincoreinfo=0; int pqueryinfo = 0; unsigned int pqueryinfo_vec_size = 0; vm_page_info_basic_t info = NULL; mach_msg_type_number_t count = 0; char *kernel_vec = NULL; - int req_vec_size_pages = 0, cur_vec_size_pages = 0; + unsigned int req_vec_size_pages = 0, cur_vec_size_pages = 0, vecindex = 0; kern_return_t kr = KERN_SUCCESS; map = current_map(); @@ -1045,7 +1054,7 @@ mincore(__unused proc_t p, struct mincore_args *uap, __unused int32_t *retval) */ req_vec_size_pages = (end - addr) >> PAGE_SHIFT; - cur_vec_size_pages = MIN(req_vec_size_pages, (int)(MAX_PAGE_RANGE_QUERY >> PAGE_SHIFT)); + cur_vec_size_pages = MIN(req_vec_size_pages, (MAX_PAGE_RANGE_QUERY >> PAGE_SHIFT)); kernel_vec = (void*) _MALLOC(cur_vec_size_pages * sizeof(char), M_TEMP, M_WAITOK | M_ZERO); @@ -1129,7 +1138,7 @@ mincore(__unused proc_t p, struct mincore_args *uap, __unused int32_t *retval) */ vec += cur_vec_size_pages * sizeof(char); req_vec_size_pages = (end - addr) >> PAGE_SHIFT; - cur_vec_size_pages = MIN(req_vec_size_pages, (int)(MAX_PAGE_RANGE_QUERY >> PAGE_SHIFT)); + cur_vec_size_pages = MIN(req_vec_size_pages, (MAX_PAGE_RANGE_QUERY >> PAGE_SHIFT)); first_addr = addr; } diff --git a/bsd/kern/kern_persona.c b/bsd/kern/kern_persona.c index 7d641675d..37df0b5a0 100644 --- a/bsd/kern/kern_persona.c +++ b/bsd/kern/kern_persona.c @@ -284,29 +284,6 @@ struct persona *persona_alloc(uid_t id, const char *login, int type, int *error) return NULL; } -int persona_invalidate(struct persona *persona) -{ - int error = 0; - if (!persona) - return EINVAL; - - lock_personas(); - persona_lock(persona); - - if (!persona_valid(persona)) - panic("Double-invalidation of persona %p", persona); - - LIST_REMOVE(persona, pna_list); - if (hw_atomic_add(&g_total_personas, -1) == UINT_MAX) - panic("persona ref count underflow!\n"); - persona_mkinvalid(persona); - - persona_unlock(persona); - unlock_personas(); - - return error; -} - static struct persona *persona_get_locked(struct persona *persona) { if (persona->pna_refcount) { @@ -353,12 +330,14 @@ void persona_put(struct persona *persona) /* remove it from the global list and decrement the count */ lock_personas(); + persona_lock(persona); if (persona_valid(persona)) { LIST_REMOVE(persona, pna_list); if (hw_atomic_add(&g_total_personas, -1) == UINT_MAX) panic("persona count underflow!\n"); persona_mkinvalid(persona); } + persona_unlock(persona); unlock_personas(); assert(LIST_EMPTY(&persona->pna_members)); @@ -398,6 +377,34 @@ struct persona *persona_lookup(uid_t id) return persona; } +struct persona *persona_lookup_and_invalidate(uid_t id) +{ + struct persona *persona, *entry, *tmp; + + persona = NULL; + + lock_personas(); + LIST_FOREACH_SAFE(entry, &all_personas, pna_list, tmp) { + persona_lock(entry); + if (entry->pna_id == id) { + if (persona_valid(entry)) { + persona = persona_get_locked(entry); + assert(persona != NULL); + LIST_REMOVE(persona, pna_list); + if (hw_atomic_add(&g_total_personas, -1) == UINT_MAX) + panic("persona ref count underflow!\n"); + persona_mkinvalid(persona); + } + persona_unlock(entry); + break; + } + persona_unlock(entry); + } + unlock_personas(); + + return persona; +} + int persona_find(const char *login, uid_t uid, struct persona **persona, size_t *plen) { diff --git a/bsd/kern/kern_proc.c b/bsd/kern/kern_proc.c index 249d8c355..f25390cb4 100644 --- a/bsd/kern/kern_proc.c +++ b/bsd/kern/kern_proc.c @@ -184,11 +184,13 @@ __XNU_PRIVATE_EXTERN char corefilename[MAXPATHLEN+1] = {"/cores/core.%P"}; #include #endif +typedef uint64_t unaligned_u64 __attribute__((aligned(1))); + static void orphanpg(struct pgrp * pg); void proc_name_kdp(task_t t, char * buf, int size); void * proc_get_uthread_uu_threadlist(void * uthread_v); int proc_threadname_kdp(void * uth, char * buf, size_t size); -void proc_starttime_kdp(void * p, uint64_t * tv_sec, uint64_t * tv_usec, uint64_t * abstime); +void proc_starttime_kdp(void * p, unaligned_u64 *tv_sec, unaligned_u64 *tv_usec, unaligned_u64 *abstime); char * proc_name_address(void * p); /* TODO: make a header that's exported and usable in osfmk */ @@ -915,23 +917,20 @@ proc_threadname_kdp(void * uth, char * buf, size_t size) return 0; } + /* note that this function is generally going to be called from stackshot, * and the arguments will be coming from a struct which is declared packed * thus the input arguments will in general be unaligned. We have to handle * that here. */ void -proc_starttime_kdp(void *p, uint64_t *tv_sec, uint64_t *tv_usec, uint64_t *abstime) +proc_starttime_kdp(void *p, unaligned_u64 *tv_sec, unaligned_u64 *tv_usec, unaligned_u64 *abstime) { proc_t pp = (proc_t)p; - struct uint64p { - uint64_t val; - } __attribute__((packed)); - if (pp != PROC_NULL) { if (tv_sec != NULL) - ((struct uint64p *)tv_sec)->val = pp->p_start.tv_sec; + *tv_sec = pp->p_start.tv_sec; if (tv_usec != NULL) - ((struct uint64p *)tv_usec)->val = pp->p_start.tv_usec; + *tv_usec = pp->p_start.tv_usec; if (abstime != NULL) { if (pp->p_stats != NULL) *abstime = pp->p_stats->ps_start; diff --git a/bsd/kern/kern_shutdown.c b/bsd/kern/kern_shutdown.c index 2be1a1310..48f912800 100644 --- a/bsd/kern/kern_shutdown.c +++ b/bsd/kern/kern_shutdown.c @@ -68,6 +68,7 @@ #include /* abused for sync() */ #include /* for delay_for_interval() */ #include +#include #include @@ -83,7 +84,6 @@ static int sd_closelog(vfs_context_t); static void sd_log(vfs_context_t, const char *, ...); static void proc_shutdown(void); static void kernel_hwm_panic_info(void); -extern void IOSystemShutdownNotification(void); extern void halt_log_enter(const char * what, const void * pc, uint64_t time); #if DEVELOPMENT || DEBUG @@ -157,10 +157,9 @@ reboot_kernel(int howto, char *message) return (EBUSY); } /* - * Temporary hack to notify the power management root domain - * that the system will shut down. + * Notify the power management root domain that the system will shut down. */ - IOSystemShutdownNotification(); + IOSystemShutdownNotification(kIOSystemShutdownNotificationStageProcessExit); if ((howto&RB_QUICK)==RB_QUICK) { printf("Quick reboot...\n"); @@ -201,6 +200,8 @@ reboot_kernel(int howto, char *message) halt_log_enter("shutdown.trace", 0, mach_absolute_time() - startTime); } + IOSystemShutdownNotification(kIOSystemShutdownNotificationStageRootUnmount); + /* * Unmount filesystems */ diff --git a/bsd/kern/kern_sig.c b/bsd/kern/kern_sig.c index d390ded07..849562cca 100644 --- a/bsd/kern/kern_sig.c +++ b/bsd/kern/kern_sig.c @@ -140,7 +140,8 @@ extern void doexception(int exc, mach_exception_code_t code, mach_exception_subcode_t sub); static void stop(proc_t, proc_t); -int cansignal(proc_t, kauth_cred_t, proc_t, int, int); +static int cansignal_nomac(proc_t, kauth_cred_t, proc_t, int); +int cansignal(proc_t, kauth_cred_t, proc_t, int); int killpg1(proc_t, int, int, int, int); kern_return_t do_bsdexception(int, int, int); void __posix_sem_syscall_return(kern_return_t); @@ -168,19 +169,18 @@ SECURITY_READ_ONLY_EARLY(struct filterops) sig_filtops = { /* structures and fns for killpg1 iterartion callback and filters */ struct killpg1_filtargs { - int posix; - proc_t cp; + bool posix; + proc_t curproc; }; struct killpg1_iterargs { - proc_t cp; + proc_t curproc; kauth_cred_t uc; int signum; - int * nfoundp; - int zombie; + int nfound; }; -static int killpg1_filt(proc_t p, void * arg); +static int killpg1_allfilt(proc_t p, void * arg); static int killpg1_pgrpfilt(proc_t p, __unused void * arg); static int killpg1_callback(proc_t p, void * arg); @@ -291,75 +291,87 @@ signal_setast(thread_t sig_actthread) act_set_astbsd(sig_actthread); } -/* - * Can process p, with ucred uc, send the signal signum to process q? - * uc is refcounted by the caller so internal fileds can be used safely - * when called with zombie arg, list lock is held - */ -int -cansignal(proc_t p, kauth_cred_t uc, proc_t q, int signum, int zombie) +static int +cansignal_nomac(proc_t src, kauth_cred_t uc_src, proc_t dst, int signum) { - kauth_cred_t my_cred; - struct session * p_sessp = SESSION_NULL; - struct session * q_sessp = SESSION_NULL; -#if CONFIG_MACF - int error; - - error = mac_proc_check_signal(p, q, signum); - if (error) - return (0); -#endif - /* you can signal yourself */ - if (p == q) - return(1); + if (src == dst) { + return 1; + } - /* you can't send launchd SIGKILL, even if root */ - if (signum == SIGKILL && q == initproc) - return(0); + /* you can't send the init proc SIGKILL, even if root */ + if (signum == SIGKILL && dst == initproc) { + return 0; + } - if (!suser(uc, NULL)) - return (1); /* root can always signal */ + /* otherwise, root can always signal */ + if (kauth_cred_issuser(uc_src)) { + return 1; + } - if (zombie == 0) + /* processes in the same session can send SIGCONT to each other */ + { + struct session *sess_src = SESSION_NULL; + struct session *sess_dst = SESSION_NULL; + + /* The session field is protected by the list lock. */ proc_list_lock(); - if (p->p_pgrp != PGRP_NULL) - p_sessp = p->p_pgrp->pg_session; - if (q->p_pgrp != PGRP_NULL) - q_sessp = q->p_pgrp->pg_session; + if (src->p_pgrp != PGRP_NULL) { + sess_src = src->p_pgrp->pg_session; + } + if (dst->p_pgrp != PGRP_NULL) { + sess_dst = dst->p_pgrp->pg_session; + } + proc_list_unlock(); - if (signum == SIGCONT && q_sessp == p_sessp) { - if (zombie == 0) - proc_list_unlock(); - return (1); /* SIGCONT in session */ + /* allow SIGCONT within session and for processes without session */ + if (signum == SIGCONT && sess_src == sess_dst) { + return 1; + } } - if (zombie == 0) - proc_list_unlock(); + /* the source process must be authorized to signal the target */ + { + int allowed = 0; + kauth_cred_t uc_dst = NOCRED, uc_ref = NOCRED; - /* - * If the real or effective UID of the sender matches the real - * or saved UID of the target, permit the signal to - * be sent. - */ - if (zombie == 0) - my_cred = kauth_cred_proc_ref(q); - else - my_cred = proc_ucred(q); + uc_dst = uc_ref = kauth_cred_proc_ref(dst); - if (kauth_cred_getruid(uc) == kauth_cred_getruid(my_cred) || - kauth_cred_getruid(uc) == kauth_cred_getsvuid(my_cred) || - kauth_cred_getuid(uc) == kauth_cred_getruid(my_cred) || - kauth_cred_getuid(uc) == kauth_cred_getsvuid(my_cred)) { - if (zombie == 0) - kauth_cred_unref(&my_cred); - return (1); + /* + * If the real or effective UID of the sender matches the real or saved + * UID of the target, allow the signal to be sent. + */ + if (kauth_cred_getruid(uc_src) == kauth_cred_getruid(uc_dst) || + kauth_cred_getruid(uc_src) == kauth_cred_getsvuid(uc_dst) || + kauth_cred_getuid(uc_src) == kauth_cred_getruid(uc_dst) || + kauth_cred_getuid(uc_src) == kauth_cred_getsvuid(uc_dst)) { + allowed = 1; + } + + if (uc_ref != NOCRED) { + kauth_cred_unref(&uc_ref); + uc_ref = NOCRED; + } + + return allowed; } +} - if (zombie == 0) - kauth_cred_unref(&my_cred); +/* + * Can process `src`, with ucred `uc_src`, send the signal `signum` to process + * `dst`? The ucred is referenced by the caller so internal fileds can be used + * safely. + */ +int +cansignal(proc_t src, kauth_cred_t uc_src, proc_t dst, int signum) +{ +#if CONFIG_MACF + if (mac_proc_check_signal(src, dst, signum)) { + return 0; + } +#endif - return (0); + return cansignal_nomac(src, uc_src, dst, signum); } /* @@ -1462,8 +1474,8 @@ kill(proc_t cp, struct kill_args *uap, __unused int32_t *retval) kauth_cred_t uc = kauth_cred_get(); int posix = uap->posix; /* !0 if posix behaviour desired */ - AUDIT_ARG(pid, uap->pid); - AUDIT_ARG(signum, uap->signum); + AUDIT_ARG(pid, uap->pid); + AUDIT_ARG(signum, uap->signum); if ((u_int)uap->signum >= NSIG) return (EINVAL); @@ -1472,15 +1484,15 @@ kill(proc_t cp, struct kill_args *uap, __unused int32_t *retval) if ((p = proc_find(uap->pid)) == NULL) { if ((p = pzfind(uap->pid)) != NULL) { /* - * IEEE Std 1003.1-2001: return success - * when killing a zombie. + * POSIX 1003.1-2001 requires returning success when killing a + * zombie; see Rationale for kill(2). */ return (0); } return (ESRCH); } AUDIT_ARG(process, p); - if (!cansignal(cp, uc, p, uap->signum, 0)) { + if (!cansignal(cp, uc, p, uap->signum)) { proc_rele(p); return(EPERM); } @@ -1490,11 +1502,11 @@ kill(proc_t cp, struct kill_args *uap, __unused int32_t *retval) return (0); } switch (uap->pid) { - case -1: /* broadcast signal */ + case -1: /* broadcast signal */ return (killpg1(cp, uap->signum, 0, 1, posix)); - case 0: /* signal own process group */ + case 0: /* signal own process group */ return (killpg1(cp, uap->signum, 0, 0, posix)); - default: /* negative explicit process group */ + default: /* negative explicit process group */ return (killpg1(cp, uap->signum, -(uap->pid), 0, posix)); } /* NOTREACHED */ @@ -1661,7 +1673,7 @@ terminate_with_payload_internal(struct proc *cur_proc, int target_pid, uint32_t AUDIT_ARG(process, target_proc); - if (!cansignal(cur_proc, cur_cred, target_proc, SIGKILL, 0)) { + if (!cansignal(cur_proc, cur_cred, target_proc, SIGKILL)) { proc_rele(target_proc); return EPERM; } @@ -1698,108 +1710,85 @@ terminate_with_payload(struct proc *cur_proc, struct terminate_with_payload_args } static int -killpg1_filt(proc_t p, void * arg) +killpg1_allfilt(proc_t p, void * arg) { struct killpg1_filtargs * kfargp = (struct killpg1_filtargs *)arg; - proc_t cp = kfargp->cp; - int posix = kfargp->posix; - - if (p->p_pid <= 1 || p->p_flag & P_SYSTEM || - (!posix && p == cp)) - return(0); - else - return(1); + /* + * Don't signal initproc, a system process, or the current process if POSIX + * isn't specified. + */ + return (p->p_pid > 1 && !(p->p_flag & P_SYSTEM) && + (kfargp->posix ? true : p != kfargp->curproc)); } - static int killpg1_pgrpfilt(proc_t p, __unused void * arg) { - if (p->p_pid <= 1 || p->p_flag & P_SYSTEM || - (p->p_stat == SZOMB)) - return(0); - else - return(1); + /* XXX shouldn't this allow signalling zombies? */ + return (p->p_pid > 1 && !(p->p_flag & P_SYSTEM) && p->p_stat != SZOMB); } - - static int -killpg1_callback(proc_t p, void * arg) -{ - struct killpg1_iterargs * kargp = (struct killpg1_iterargs *)arg; - proc_t cp = kargp->cp; - kauth_cred_t uc = kargp->uc; /* refcounted by the caller safe to use internal fields */ - int signum = kargp->signum; - int * nfoundp = kargp->nfoundp; - int n; - int zombie = 0; - int error = 0; - - if ((kargp->zombie != 0) && ((p->p_listflag & P_LIST_EXITED) == P_LIST_EXITED)) - zombie = 1; +killpg1_callback(proc_t p, void *arg) +{ + struct killpg1_iterargs *kargp = (struct killpg1_iterargs *)arg; + int signum = kargp->signum; - if (zombie != 0) { - proc_list_lock(); - error = cansignal(cp, uc, p, signum, zombie); - proc_list_unlock(); - - if (error != 0 && nfoundp != NULL) { - n = *nfoundp; - *nfoundp = n+1; + if ((p->p_listflag & P_LIST_EXITED) == P_LIST_EXITED) { + /* + * Count zombies as found for the purposes of signalling, since POSIX + * 1003.1-2001 sees signalling zombies as successful. If killpg(2) or + * kill(2) with pid -1 only finds zombies that can be signalled, it + * shouldn't return ESRCH. See the Rationale for kill(2). + * + * Don't call into MAC -- it's not expecting signal checks for exited + * processes. + */ + if (cansignal_nomac(kargp->curproc, kargp->uc, p, signum)) { + kargp->nfound++; } - } else { - if (cansignal(cp, uc, p, signum, 0) == 0) - return(PROC_RETURNED); + } else if (cansignal(kargp->curproc, kargp->uc, p, signum)) { + kargp->nfound++; - if (nfoundp != NULL) { - n = *nfoundp; - *nfoundp = n+1; - } - if (signum != 0) + if (signum != 0) { psignal(p, signum); + } } - return(PROC_RETURNED); + return PROC_RETURNED; } /* * Common code for kill process group/broadcast kill. - * cp is calling process. */ int -killpg1(proc_t cp, int signum, int pgid, int all, int posix) +killpg1(proc_t curproc, int signum, int pgid, int all, int posix) { kauth_cred_t uc; struct pgrp *pgrp; - int nfound = 0; - struct killpg1_iterargs karg; - struct killpg1_filtargs kfarg; int error = 0; - - uc = kauth_cred_proc_ref(cp); - if (all) { - /* - * broadcast - */ - kfarg.posix = posix; - kfarg.cp = cp; - - karg.cp = cp; - karg.uc = uc; - karg.nfoundp = &nfound; - karg.signum = signum; - karg.zombie = 1; - proc_iterate((PROC_ALLPROCLIST | PROC_ZOMBPROCLIST), killpg1_callback, &karg, killpg1_filt, (void *)&kfarg); + uc = kauth_cred_proc_ref(curproc); + struct killpg1_iterargs karg = { + .curproc = curproc, .uc = uc, .nfound = 0, .signum = signum + }; + if (all) { + /* + * Broadcast to all processes that the user can signal (pid was -1). + */ + struct killpg1_filtargs kfarg = { + .posix = posix, .curproc = curproc + }; + proc_iterate(PROC_ALLPROCLIST | PROC_ZOMBPROCLIST, killpg1_callback, + &karg, killpg1_allfilt, &kfarg); } else { if (pgid == 0) { - /* - * zero pgid means send to my process group. + /* + * Send to current the current process' process group. */ - pgrp = proc_pgrp(cp); + pgrp = proc_pgrp(curproc); } else { pgrp = pgfind(pgid); if (pgrp == NULL) { @@ -1808,24 +1797,16 @@ killpg1(proc_t cp, int signum, int pgid, int all, int posix) } } - karg.nfoundp = &nfound; - karg.uc = uc; - karg.signum = signum; - karg.cp = cp; - karg.zombie = 0; - - /* PGRP_DROPREF drops the pgrp refernce */ pgrp_iterate(pgrp, PGRP_DROPREF, killpg1_callback, &karg, - killpg1_pgrpfilt, NULL); + killpg1_pgrpfilt, NULL); } - error = (nfound ? 0 : (posix ? EPERM : ESRCH)); + error = (karg.nfound > 0 ? 0 : (posix ? EPERM : ESRCH)); out: kauth_cred_unref(&uc); return (error); } - /* * Send a signal to a process group. */ diff --git a/bsd/kern/kern_sysctl.c b/bsd/kern/kern_sysctl.c index 63bcc0443..f6ed41035 100644 --- a/bsd/kern/kern_sysctl.c +++ b/bsd/kern/kern_sysctl.c @@ -1691,6 +1691,28 @@ SYSCTL_PROC(_kern, KERN_OSVERSION, osversion, osversion, 256 /* OSVERSIZE*/, sysctl_osversion, "A", ""); +static uint64_t osproductversion_string[48]; + +STATIC int +sysctl_osproductversion(__unused struct sysctl_oid *oidp, void *arg1, int arg2, struct sysctl_req *req) +{ + if (req->newptr != 0) { + /* + * Can only ever be set by launchd, and only once at boot. + */ + if (req->p->p_pid != 1 || osproductversion_string[0] != '\0') { + return EPERM; + } + } + + return sysctl_handle_string(oidp, arg1, arg2, req); +} + +SYSCTL_PROC(_kern, OID_AUTO, osproductversion, + CTLFLAG_RW | CTLFLAG_KERN | CTLTYPE_STRING | CTLFLAG_LOCKED, + osproductversion_string, sizeof(osproductversion_string), + sysctl_osproductversion, "A", "The ProductVersion from SystemVersion.plist"); + static uint64_t osvariant_status = 0; STATIC int @@ -1818,6 +1840,10 @@ extern int sched_smt_balance; SYSCTL_INT(_kern, OID_AUTO, sched_smt_balance, CTLFLAG_KERN| CTLFLAG_RW| CTLFLAG_LOCKED, &sched_smt_balance, 0, ""); +extern int sched_allow_rt_smt; +SYSCTL_INT(_kern, OID_AUTO, sched_allow_rt_smt, + CTLFLAG_KERN| CTLFLAG_RW| CTLFLAG_LOCKED, + &sched_allow_rt_smt, 0, ""); #if __arm__ || __arm64__ extern uint32_t perfcontrol_requested_recommended_cores; SYSCTL_UINT(_kern, OID_AUTO, sched_recommended_cores, @@ -2193,7 +2219,7 @@ SYSCTL_NODE(_kern_timer, OID_AUTO, longterm, CTLFLAG_RW | CTLFLAG_LOCKED, 0, "lo enum { THRESHOLD, QCOUNT, ENQUEUES, DEQUEUES, ESCALATES, SCANS, PREEMPTS, - LATENCY, LATENCY_MIN, LATENCY_MAX, SCAN_LIMIT, PAUSES + LATENCY, LATENCY_MIN, LATENCY_MAX, SCAN_LIMIT, SCAN_INTERVAL, PAUSES }; extern uint64_t timer_sysctl_get(int); extern int timer_sysctl_set(int, uint64_t); @@ -2221,9 +2247,17 @@ SYSCTL_PROC(_kern_timer_longterm, OID_AUTO, threshold, SYSCTL_PROC(_kern_timer_longterm, OID_AUTO, scan_limit, CTLTYPE_QUAD | CTLFLAG_RW | CTLFLAG_LOCKED, (void *) SCAN_LIMIT, 0, sysctl_timer, "Q", ""); +SYSCTL_PROC(_kern_timer_longterm, OID_AUTO, scan_interval, + CTLTYPE_QUAD | CTLFLAG_RW | CTLFLAG_LOCKED, + (void *) SCAN_INTERVAL, 0, sysctl_timer, "Q", ""); + SYSCTL_PROC(_kern_timer_longterm, OID_AUTO, qlen, CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_LOCKED, (void *) QCOUNT, 0, sysctl_timer, "Q", ""); +SYSCTL_PROC(_kern_timer_longterm, OID_AUTO, scan_pauses, + CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_LOCKED, + (void *) PAUSES, 0, sysctl_timer, "Q", ""); + #if DEBUG SYSCTL_PROC(_kern_timer_longterm, OID_AUTO, enqueues, CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_LOCKED, @@ -2249,9 +2283,6 @@ SYSCTL_PROC(_kern_timer_longterm, OID_AUTO, latency_min, SYSCTL_PROC(_kern_timer_longterm, OID_AUTO, latency_max, CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_LOCKED, (void *) LATENCY_MAX, 0, sysctl_timer, "Q", ""); -SYSCTL_PROC(_kern_timer_longterm, OID_AUTO, scan_pauses, - CTLTYPE_QUAD | CTLFLAG_RD | CTLFLAG_LOCKED, - (void *) PAUSES, 0, sysctl_timer, "Q", ""); #endif /* DEBUG */ STATIC int @@ -3332,37 +3363,6 @@ SYSCTL_PROC(_kern, OID_AUTO, darkboot, 0, 0, sysctl_darkboot, "I", ""); #endif -/* - * This is set by core audio to tell tailspin (ie background tracing) how long - * its smallest buffer is. Background tracing can then try to make a reasonable - * decisions to try to avoid introducing so much latency that the buffers will - * underflow. - */ - -int min_audio_buffer_usec; - -STATIC int -sysctl_audio_buffer SYSCTL_HANDLER_ARGS -{ -#pragma unused(oidp, arg1, arg2) - int err = 0, value = 0, changed = 0; - err = sysctl_io_number(req, min_audio_buffer_usec, sizeof(int), &value, &changed); - if (err) goto exit; - - if (changed) { - /* writing is protected by an entitlement */ - if (priv_check_cred(kauth_cred_get(), PRIV_AUDIO_LATENCY, 0) != 0) { - err = EPERM; - goto exit; - } - min_audio_buffer_usec = value; - } -exit: - return err; -} - -SYSCTL_PROC(_kern, OID_AUTO, min_audio_buffer_usec, CTLFLAG_RW | CTLFLAG_ANYBODY, 0, 0, sysctl_audio_buffer, "I", "Minimum audio buffer size, in microseconds"); - #if DEVELOPMENT || DEBUG #include /* This should result in a fatal exception, verifying that "sysent" is diff --git a/bsd/kern/mach_loader.c b/bsd/kern/mach_loader.c index f84a814cb..c63a8d8cd 100644 --- a/bsd/kern/mach_loader.c +++ b/bsd/kern/mach_loader.c @@ -83,11 +83,15 @@ #include #include #include -#include +#include #include /* for kIOReturnNotPrivileged */ #include +#if __x86_64__ +extern int bootarg_no32exec; /* bsd_init.c */ +#endif + /* * XXX vm/pmap.h should not treat these prototypes as MACH_KERNEL_PRIVATE * when KERNEL is defined. @@ -623,14 +627,20 @@ parse_machfile( * Check to see if right machine type. */ if (((cpu_type_t)(header->cputype & ~CPU_ARCH_MASK) != (cpu_type() & ~CPU_ARCH_MASK)) || - !grade_binary(header->cputype, + !grade_binary(header->cputype, header->cpusubtype & ~CPU_SUBTYPE_MASK)) return(LOAD_BADARCH); - + +#if __x86_64__ + if (bootarg_no32exec && (header->cputype == CPU_TYPE_X86)) { + return(LOAD_BADARCH_X86); + } +#endif + abi64 = ((header->cputype & CPU_ARCH_ABI64) == CPU_ARCH_ABI64); - + switch (header->filetype) { - + case MH_EXECUTE: if (depth != 1) { return (LOAD_FAILURE); diff --git a/bsd/kern/mach_loader.h b/bsd/kern/mach_loader.h index d58ae5a4a..b564d1201 100644 --- a/bsd/kern/mach_loader.h +++ b/bsd/kern/mach_loader.h @@ -63,7 +63,7 @@ typedef struct _load_result { mach_vm_address_t all_image_info_addr; mach_vm_size_t all_image_info_size; - + int thread_count; unsigned int /* boolean_t */ unixproc :1, @@ -104,5 +104,7 @@ load_return_t load_machfile( #define LOAD_IOERROR 9 /* IO error */ #define LOAD_DECRYPTFAIL 10 /* FP decrypt failure */ #define LOAD_BADMACHO_UPX 11 /* malformed mach-o file */ +#define LOAD_BADARCH_X86 12 /* -no32exec boot-arg + attempted load + of 32bit x86 binary */ #endif /* _BSD_KERN_MACH_LOADER_H_ */ diff --git a/bsd/kern/policy_check.c b/bsd/kern/policy_check.c index 75b2bb722..52a91f33b 100644 --- a/bsd/kern/policy_check.c +++ b/bsd/kern/policy_check.c @@ -471,8 +471,6 @@ const static struct mac_policy_ops policy_ops = { CHECK_SET_HOOK(iokit_check_set_properties) - CHECK_SET_HOOK(system_check_chud) - CHECK_SET_HOOK(vnode_check_searchfs) CHECK_SET_HOOK(priv_check) diff --git a/bsd/kern/proc_info.c b/bsd/kern/proc_info.c index 1f88ae54e..52eaeda02 100644 --- a/bsd/kern/proc_info.c +++ b/bsd/kern/proc_info.c @@ -174,6 +174,10 @@ int __attribute__ ((noinline)) proc_pidoriginatorpid_uuid(uuid_t uuid, uint32_t int __attribute__ ((noinline)) proc_pidlistuptrs(proc_t p, user_addr_t buffer, uint32_t buffersize, int32_t *retval); int __attribute__ ((noinline)) proc_piddynkqueueinfo(pid_t pid, int flavor, kqueue_id_t id, user_addr_t buffer, uint32_t buffersize, int32_t *retval); +#if !CONFIG_EMBEDDED +int __attribute__ ((noinline)) proc_udata_info(pid_t pid, int flavor, user_addr_t buffer, uint32_t buffersize, int32_t *retval); +#endif + /* protos for proc_pidfdinfo calls */ int __attribute__ ((noinline)) pid_vnodeinfo(vnode_t vp, uint32_t vid, struct fileproc * fp,proc_t proc, int fd, user_addr_t buffer, uint32_t buffersize, int32_t * retval); int __attribute__ ((noinline)) pid_vnodeinfopath(vnode_t vp, uint32_t vid, struct fileproc * fp,proc_t proc, int fd, user_addr_t buffer, uint32_t buffersize, int32_t * retval); @@ -194,7 +198,7 @@ static void munge_vinfo_stat(struct stat64 *sbp, struct vinfo_stat *vsbp); static int proc_piduuidinfo(pid_t pid, uuid_t uuid_buf, uint32_t buffersize); int proc_pidpathinfo_internal(proc_t p, __unused uint64_t arg, char *buf, uint32_t buffersize, __unused int32_t *retval); -extern int cansignal(struct proc *, kauth_cred_t, struct proc *, int, int); +extern int cansignal(struct proc *, kauth_cred_t, struct proc *, int); extern int proc_get_rusage(proc_t proc, int flavor, user_addr_t buffer, int is_zombie); #define CHECK_SAME_USER TRUE @@ -272,6 +276,10 @@ proc_info_internal(int callnum, int pid, int flavor, uint64_t arg, user_addr_t b return proc_can_use_foreground_hw(pid, buffer, buffersize, retval); case PROC_INFO_CALL_PIDDYNKQUEUEINFO: return proc_piddynkqueueinfo(pid, flavor, (kqueue_id_t)arg, buffer, buffersize, retval); +#if !CONFIG_EMBEDDED + case PROC_INFO_CALL_UDATA_INFO: + return proc_udata_info(pid, flavor, buffer, buffersize, retval); +#endif /* !CONFIG_EMBEDDED */ default: return EINVAL; } @@ -2828,7 +2836,7 @@ proc_dirtycontrol(int pid, int flavor, uint64_t arg, int32_t *retval) { case PROC_DIRTYCONTROL_SET: { /* Check privileges; use cansignal() here since the process could be terminated */ - if (!cansignal(current_proc(), my_cred, target_p, SIGKILL, 0)) { + if (!cansignal(current_proc(), my_cred, target_p, SIGKILL)) { error = EPERM; goto out; } @@ -2849,7 +2857,7 @@ proc_dirtycontrol(int pid, int flavor, uint64_t arg, int32_t *retval) { case PROC_DIRTYCONTROL_CLEAR: { /* Check privileges; use cansignal() here since the process could be terminated */ - if (!cansignal(current_proc(), my_cred, target_p, SIGKILL, 0)) { + if (!cansignal(current_proc(), my_cred, target_p, SIGKILL)) { error = EPERM; goto out; } @@ -2912,7 +2920,7 @@ proc_terminate(int pid, int32_t *retval) #endif /* Check privileges; if SIGKILL can be issued, then SIGTERM is also OK */ - if (!cansignal(current_proc(), uc, p, SIGKILL, 0)) { + if (!cansignal(current_proc(), uc, p, SIGKILL)) { error = EPERM; goto out; } @@ -3206,3 +3214,51 @@ proc_piddynkqueueinfo(int pid, int flavor, kqueue_id_t kq_id, return err; } + +#if !CONFIG_EMBEDDED +int +proc_udata_info(int pid, int flavor, user_addr_t buffer, uint32_t bufsize, int32_t *retval) +{ + int err = 0; + proc_t p; + + p = proc_find(pid); + if (p == PROC_NULL) { + return ESRCH; + } + + /* + * Only support calls against oneself for the moment. + */ + if (p->p_pid != proc_selfpid()) { + err = EACCES; + goto out; + } + + if (bufsize != sizeof (p->p_user_data)) { + err = EINVAL; + goto out; + } + + switch (flavor) { + case PROC_UDATA_INFO_SET: + err = copyin(buffer, &p->p_user_data, sizeof (p->p_user_data)); + break; + case PROC_UDATA_INFO_GET: + err = copyout(&p->p_user_data, buffer, sizeof (p->p_user_data)); + break; + default: + err = ENOTSUP; + break; + } + +out: + proc_rele(p); + + if (err == 0) { + *retval = 0; + } + + return err; +} +#endif /* !CONFIG_EMBEDDED */ diff --git a/bsd/kern/pthread_shims.c b/bsd/kern/pthread_shims.c index c8e42fc8c..66fa1d73e 100644 --- a/bsd/kern/pthread_shims.c +++ b/bsd/kern/pthread_shims.c @@ -146,6 +146,13 @@ pthread_returning_to_userspace(void) thread_exception_return(); } +__attribute__((noreturn)) +static void +pthread_bootstrap_return(void) +{ + thread_bootstrap_return(); +} + static uint32_t get_task_threadmax(void) { return task_threadmax; @@ -616,7 +623,7 @@ static const struct pthread_callbacks_s pthread_callbacks = { .uthread_is_cancelled = uthread_is_cancelled, .thread_exception_return = pthread_returning_to_userspace, - .thread_bootstrap_return = thread_bootstrap_return, + .thread_bootstrap_return = pthread_bootstrap_return, .unix_syscall_return = unix_syscall_return, .absolutetime_to_microtime = absolutetime_to_microtime, diff --git a/bsd/kern/subr_eventhandler.c b/bsd/kern/subr_eventhandler.c index 65c5975e3..276dd4b87 100644 --- a/bsd/kern/subr_eventhandler.c +++ b/bsd/kern/subr_eventhandler.c @@ -72,7 +72,7 @@ SYSCTL_NODE(_kern, OID_AUTO, eventhandler, CTLFLAG_RW | CTLFLAG_LOCKED, SYSCTL_INT(_kern_eventhandler, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_LOCKED, &evh_debug, 0, "Eventhandler debug mode"); -struct eventhandler_entry_arg eventhandler_entry_dummy_arg = {{0}}; +struct eventhandler_entry_arg eventhandler_entry_dummy_arg = { { 0 }, { 0 } }; /* List of 'slow' lists */ static struct eventhandler_lists_ctxt evthdlr_lists_ctxt_glb; @@ -80,6 +80,12 @@ static lck_grp_attr_t *eventhandler_mutex_grp_attr; static lck_grp_t *eventhandler_mutex_grp; static lck_attr_t *eventhandler_mutex_attr; +static unsigned int eg_size; /* size of eventhandler_entry_generic */ +static struct mcache *eg_cache; /* mcache for eventhandler_entry_generic */ + +static unsigned int el_size; /* size of eventhandler_list */ +static struct mcache *el_cache; /* mcache for eventhandler_list */ + static lck_grp_attr_t *el_lock_grp_attr; lck_grp_t *el_lock_grp; lck_attr_t *el_lock_attr; @@ -121,6 +127,21 @@ eventhandler_init(void) el_lock_attr = lck_attr_alloc_init(); eventhandler_lists_ctxt_init(&evthdlr_lists_ctxt_glb); + + eg_size = sizeof (struct eventhandler_entry_generic); + eg_cache = mcache_create("eventhdlr_generic", eg_size, + sizeof (uint64_t), 0, MCR_SLEEP); + + el_size = sizeof (struct eventhandler_list); + el_cache = mcache_create("eventhdlr_list", el_size, + sizeof (uint64_t), 0, MCR_SLEEP); +} + +void +eventhandler_reap_caches(boolean_t purge) +{ + mcache_reap_now(eg_cache, purge); + mcache_reap_now(el_cache, purge); } /* @@ -136,6 +157,8 @@ eventhandler_register_internal( struct eventhandler_list *new_list; struct eventhandler_entry *ep; + VERIFY(strlen(name) <= (sizeof (new_list->el_name) - 1)); + if (evthdlr_lists_ctxt == NULL) evthdlr_lists_ctxt = &evthdlr_lists_ctxt_glb; @@ -143,7 +166,7 @@ eventhandler_register_internal( VERIFY(epn != NULL); /* cannot register NULL event */ /* lock the eventhandler lists */ - lck_mtx_lock(&evthdlr_lists_ctxt->eventhandler_mutex); + lck_mtx_lock_spin(&evthdlr_lists_ctxt->eventhandler_mutex); /* Do we need to find/create the (slow) list? */ if (list == NULL) { @@ -152,27 +175,16 @@ eventhandler_register_internal( /* Do we need to create the list? */ if (list == NULL) { - lck_mtx_unlock(&evthdlr_lists_ctxt->eventhandler_mutex); - - MALLOC(new_list, struct eventhandler_list *, - sizeof(struct eventhandler_list) + strlen(name) + 1, - M_EVENTHANDLER, M_WAITOK); - - /* If someone else created it already, then use that one. */ - lck_mtx_lock(&evthdlr_lists_ctxt->eventhandler_mutex); - list = _eventhandler_find_list(evthdlr_lists_ctxt, name); - if (list != NULL) { - FREE(new_list, M_EVENTHANDLER); - } else { - evhlog((LOG_DEBUG, "%s: creating list \"%s\"", __func__, name)); - list = new_list; - list->el_flags = 0; - list->el_runcount = 0; - bzero(&list->el_lock, sizeof(list->el_lock)); - list->el_name = (char *)list + sizeof(struct eventhandler_list); - strlcpy(list->el_name, name, strlen(name) + 1); - TAILQ_INSERT_HEAD(&evthdlr_lists_ctxt->eventhandler_lists, list, el_link); - } + lck_mtx_convert_spin(&evthdlr_lists_ctxt->eventhandler_mutex); + new_list = mcache_alloc(el_cache, MCR_SLEEP); + bzero(new_list, el_size); + evhlog((LOG_DEBUG, "%s: creating list \"%s\"", __func__, name)); + list = new_list; + list->el_flags = 0; + list->el_runcount = 0; + bzero(&list->el_lock, sizeof(list->el_lock)); + (void) snprintf(list->el_name, sizeof (list->el_name), "%s", name); + TAILQ_INSERT_HEAD(&evthdlr_lists_ctxt->eventhandler_lists, list, el_link); } } if (!(list->el_flags & EHL_INITTED)) { @@ -210,10 +222,8 @@ eventhandler_register(struct eventhandler_lists_ctxt *evthdlr_lists_ctxt, struct eventhandler_entry_generic *eg; /* allocate an entry for this handler, populate it */ - MALLOC(eg, struct eventhandler_entry_generic *, - sizeof(struct eventhandler_entry_generic), - M_EVENTHANDLER, M_WAITOK | M_ZERO); - + eg = mcache_alloc(eg_cache, MCR_SLEEP); + bzero(eg, eg_size); eg->func = func; eg->ee.ee_arg = arg; eg->ee.ee_priority = priority; @@ -239,7 +249,8 @@ eventhandler_deregister(struct eventhandler_list *list, eventhandler_tag tag) */ if (!TAILQ_EMPTY(&list->el_entries)) TAILQ_REMOVE(&list->el_entries, ep, ee_link); - FREE(ep, M_EVENTHANDLER); + EHL_LOCK_CONVERT(list); + mcache_free(eg_cache, ep); } else { evhlog((LOG_DEBUG, "%s: marking item %p from \"%s\" as dead", __func__, VM_KERNEL_ADDRPERM(ep), list->el_name)); @@ -250,10 +261,11 @@ eventhandler_deregister(struct eventhandler_list *list, eventhandler_tag tag) if (list->el_runcount == 0) { evhlog((LOG_DEBUG, "%s: removing all items from \"%s\"", __func__, list->el_name)); + EHL_LOCK_CONVERT(list); while (!TAILQ_EMPTY(&list->el_entries)) { ep = TAILQ_FIRST(&list->el_entries); TAILQ_REMOVE(&list->el_entries, ep, ee_link); - FREE(ep, M_EVENTHANDLER); + mcache_free(eg_cache, ep); } } else { evhlog((LOG_DEBUG, "%s: marking all items from \"%s\" as dead", @@ -263,7 +275,7 @@ eventhandler_deregister(struct eventhandler_list *list, eventhandler_tag tag) } } while (list->el_runcount > 0) - msleep((caddr_t)list, &list->el_lock, 0, "evhrm", 0); + msleep((caddr_t)list, &list->el_lock, PSPIN, "evhrm", 0); EHL_UNLOCK(list); } @@ -302,10 +314,12 @@ eventhandler_find_list(struct eventhandler_lists_ctxt *evthdlr_lists_ctxt, return(NULL); /* scan looking for the requested list */ - lck_mtx_lock(&evthdlr_lists_ctxt->eventhandler_mutex); + lck_mtx_lock_spin(&evthdlr_lists_ctxt->eventhandler_mutex); list = _eventhandler_find_list(evthdlr_lists_ctxt, name); - if (list != NULL) - EHL_LOCK(list); + if (list != NULL) { + lck_mtx_convert_spin(&evthdlr_lists_ctxt->eventhandler_mutex); + EHL_LOCK_SPIN(list); + } lck_mtx_unlock(&evthdlr_lists_ctxt->eventhandler_mutex); return(list); @@ -325,7 +339,7 @@ eventhandler_prune_list(struct eventhandler_list *list) TAILQ_FOREACH_SAFE(ep, &list->el_entries, ee_link, en) { if (ep->ee_priority == EHE_DEAD_PRIORITY) { TAILQ_REMOVE(&list->el_entries, ep, ee_link); - FREE(ep, M_EVENTHANDLER); + mcache_free(eg_cache, ep); pruned++; } } @@ -350,7 +364,7 @@ eventhandler_lists_ctxt_destroy(struct eventhandler_lists_ctxt *evthdlr_lists_ct el_link, list_next) { VERIFY(TAILQ_EMPTY(&list->el_entries)); EHL_LOCK_DESTROY(list); - FREE(list, M_EVENTHANDLER); + mcache_free(el_cache, list); } lck_mtx_unlock(&evthdlr_lists_ctxt->eventhandler_mutex); lck_mtx_destroy(&evthdlr_lists_ctxt->eventhandler_mutex, diff --git a/bsd/kern/sys_persona.c b/bsd/kern/sys_persona.c index 792043d8d..7f33f6769 100644 --- a/bsd/kern/sys_persona.c +++ b/bsd/kern/sys_persona.c @@ -144,7 +144,7 @@ static int kpersona_alloc_syscall(user_addr_t infop, user_addr_t idp) static int kpersona_dealloc_syscall(user_addr_t idp) { - int error; + int error = 0; uid_t persona_id; struct persona *persona; @@ -155,19 +155,17 @@ static int kpersona_dealloc_syscall(user_addr_t idp) if (error) return error; - persona = persona_lookup(persona_id); + /* invalidate the persona (deny subsequent spawn/fork) */ + persona = persona_lookup_and_invalidate(persona_id); + if (!persona) return ESRCH; - /* invalidate the persona (deny subsequent spawn/fork) */ - error = persona_invalidate(persona); - /* one reference from the _lookup() */ persona_put(persona); /* one reference from the _alloc() */ - if (!error) - persona_put(persona); + persona_put(persona); return error; } diff --git a/bsd/kern/sys_work_interval.c b/bsd/kern/sys_work_interval.c index 561a1a0bb..bbfdd5e61 100644 --- a/bsd/kern/sys_work_interval.c +++ b/bsd/kern/sys_work_interval.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -46,7 +47,6 @@ work_interval_ctl(__unused proc_t p, struct work_interval_ctl_args *uap, kern_return_t kret = KERN_SUCCESS; struct work_interval_notification notification; - /* Two different structs, because headers are complicated */ struct work_interval_create_params create_params; struct kern_work_interval_create_args create_args; @@ -59,15 +59,12 @@ work_interval_ctl(__unused proc_t p, struct work_interval_ctl_args *uap, if (uap->len < sizeof(create_params)) return EINVAL; - /* - * Privilege check performed up-front, and then the work - * ID is allocated for use by the thread - */ - if ((error = priv_check_cred(kauth_cred_get(), PRIV_WORK_INTERVAL, 0))) + if ((error = copyin(uap->arg, &create_params, sizeof(create_params)))) return error; - if ((error = copyin(uap->arg, &create_params, sizeof(create_params)))) + if ((error = priv_check_cred(kauth_cred_get(), PRIV_WORK_INTERVAL, 0)) != 0) { return error; + } create_args = (struct kern_work_interval_create_args) { .wica_id = create_params.wicp_id, @@ -95,9 +92,10 @@ work_interval_ctl(__unused proc_t p, struct work_interval_ctl_args *uap, .wicp_create_flags = create_args.wica_create_flags, }; - if ((error = copyout(&create_params, uap->arg, sizeof(create_params)))) + if ((error = copyout(&create_params, uap->arg, sizeof(create_params)))) { + kern_work_interval_destroy(current_thread(), create_args.wica_id); return error; - + } break; case WORK_INTERVAL_OPERATION_DESTROY: if (uap->arg != USER_ADDR_NULL || uap->work_interval_id == 0) { diff --git a/bsd/kern/trace_codes b/bsd/kern/trace_codes index 2e174231c..21efaac43 100644 --- a/bsd/kern/trace_codes +++ b/bsd/kern/trace_codes @@ -865,6 +865,7 @@ 0x30A00F8 SMB_smbfs_get_max_access 0x30A00FC SMB_smbfs_lookup 0x30A0100 SMB_smbfs_notify +0x30B0000 VFS_MountRoot 0x3110004 OpenThrottleWindow 0x3110008 CauseIOThrottle 0x311000C IO_THROTTLE_DISABLE @@ -1178,6 +1179,9 @@ 0x531027C CPUPM_PST_PLIMIT_UIB 0x5310280 CPUPM_IO 0x5310284 CPUPM_FI +0x5310290 CPUPM_URGENCY +0x5310294 CPUPM_IDLE_EXIT1 +0x5310298 CPUPM_PST_QOS_CONT 0x5330000 HIBERNATE 0x5330004 HIBERNATE_WRITE_IMAGE 0x5330008 HIBERNATE_MACHINE_INIT @@ -1204,6 +1208,7 @@ 0x7010008 TRACE_STRING_EXEC 0x701000c TRACE_STRING_PROC_EXIT 0x7010010 TRACE_STRING_THREADNAME +0x7010014 TRACE_STRING_THREADNAME_PREV 0x7020000 TRACE_PANIC 0x7020004 TRACE_TIMESTAMPS 0x7020008 TRACE_LOST_EVENTS diff --git a/bsd/kern/tty_dev.c b/bsd/kern/tty_dev.c index dac57968b..1e1fe83f4 100644 --- a/bsd/kern/tty_dev.c +++ b/bsd/kern/tty_dev.c @@ -318,7 +318,7 @@ ptsclose(dev_t dev, int flag, __unused int mode, __unused proc_t p) struct tty_dev_t *driver; struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, &driver); struct tty *tp; - + if (pti == NULL) return (ENXIO); @@ -328,9 +328,16 @@ ptsclose(dev_t dev, int flag, __unused int mode, __unused proc_t p) save_timeout = tp->t_timeout; tp->t_timeout = 60; #endif + /* + * Close the line discipline and backing TTY structures. + */ err = (*linesw[tp->t_line].l_close)(tp, flag); - ptsstop(tp, FREAD|FWRITE); - (void) ttyclose(tp); + (void)ttyclose(tp); + + /* + * Flush data and notify any waiters on the master side of this PTY. + */ + ptsstop(tp, FREAD | FWRITE); #ifdef FIX_VSX_HANG tp->t_timeout = save_timeout; #endif @@ -556,29 +563,46 @@ ptcclose(dev_t dev, __unused int flags, __unused int fmt, __unused proc_t p) struct tty_dev_t *driver; struct ptmx_ioctl *pti = pty_get_ioctl(dev, 0, &driver); struct tty *tp; + struct knote *kn; + + if (!pti) { + return ENXIO; + } - if (pti == NULL) - return (ENXIO); tp = pti->pt_tty; tty_lock(tp); - (void)(*linesw[tp->t_line].l_modem)(tp, 0); - /* - * XXX MDMBUF makes no sense for ptys but would inhibit the above - * l_modem(). CLOCAL makes sense but isn't supported. Special - * l_modem()s that ignore carrier drop make no sense for ptys but - * may be in use because other parts of the line discipline make - * sense for ptys. Recover by doing everything that a normal - * ttymodem() would have done except for sending a SIGHUP. + * XXX MDMBUF makes no sense for PTYs, but would inhibit an `l_modem`. + * CLOCAL makes sense but isn't supported. Special `l_modem`s that ignore + * carrier drop make no sense for PTYs but may be in use because other parts + * of the line discipline make sense for PTYs. Recover by doing everything + * that a normal `ttymodem` would have done except for sending SIGHUP. */ + (void)(*linesw[tp->t_line].l_modem)(tp, 0); if (tp->t_state & TS_ISOPEN) { tp->t_state &= ~(TS_CARR_ON | TS_CONNECTED); tp->t_state |= TS_ZOMBIE; ttyflush(tp, FREAD | FWRITE); } - tp->t_oproc = 0; /* mark closed */ + /* + * Null out the backing TTY struct's open procedure to prevent starting + * slaves through `ptsstart`. + */ + tp->t_oproc = NULL; + + /* + * Clear any select or kevent waiters under the lock. + */ + SLIST_FOREACH(kn, &pti->pt_selr.si_note, kn_selnext) { + KNOTE_DETACH(&pti->pt_selr.si_note, kn); + } + selthreadclear(&pti->pt_selr); + SLIST_FOREACH(kn, &pti->pt_selw.si_note, kn_selnext) { + KNOTE_DETACH(&pti->pt_selw.si_note, kn); + } + selthreadclear(&pti->pt_selw); tty_unlock(tp); diff --git a/bsd/kern/tty_ptmx.c b/bsd/kern/tty_ptmx.c index aa583d857..8e81ab669 100644 --- a/bsd/kern/tty_ptmx.c +++ b/bsd/kern/tty_ptmx.c @@ -823,6 +823,7 @@ ptmx_kqops_common(struct knote *kn, struct ptmx_ioctl *pti, struct tty *tp) /* disconnects should force a wakeup (EOF) */ if (!(tp->t_state & TS_CONNECTED)) { + kn->kn_flags |= EV_EOF; return 1; } diff --git a/bsd/kern/uipc_mbuf.c b/bsd/kern/uipc_mbuf.c index ca8fde048..c0b051922 100644 --- a/bsd/kern/uipc_mbuf.c +++ b/bsd/kern/uipc_mbuf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2017 Apple Inc. All rights reserved. + * Copyright (c) 1998-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -93,6 +93,8 @@ #include #include +#include + #include #include @@ -634,7 +636,6 @@ typedef struct { #define m_minlimit(c) mbuf_table[c].mtbl_minlimit #define m_maxlimit(c) mbuf_table[c].mtbl_maxlimit #define m_wantpurge(c) mbuf_table[c].mtbl_wantpurge -#define m_avgtotal(c) mbuf_table[c].mtbl_avgtotal #define m_cname(c) mbuf_table[c].mtbl_stats->mbcl_cname #define m_size(c) mbuf_table[c].mtbl_stats->mbcl_size #define m_total(c) mbuf_table[c].mtbl_stats->mbcl_total @@ -680,6 +681,13 @@ static mbuf_table_t mbuf_table[] = { #define NELEM(a) (sizeof (a) / sizeof ((a)[0])) + +static uint32_t +m_avgtotal(mbuf_class_t c) +{ + return (mbuf_table[c].mtbl_avgtotal); +} + static void *mb_waitchan = &mbuf_table; /* wait channel for all caches */ static int mb_waiters; /* number of waiters */ @@ -5304,6 +5312,16 @@ m_pullup(struct mbuf *n, int len) int count; int space; + /* check invalid arguments */ + if (n == NULL) { + panic("%s: n == NULL", __func__); + } + if (len < 0) { + os_log_info(OS_LOG_DEFAULT, "%s: failed negative len %d", + __func__, len); + goto bad; + } + /* * If first mbuf has no cluster, and has room for len bytes * without shifting current data, pullup into it, @@ -6527,7 +6545,7 @@ mbuf_sleep(mbuf_class_t class, unsigned int num, int wait) mb_waiters++; m_region_expand(class) += m_total(class) + num; /* wake up the worker thread */ - if (class > MC_MBUF && mbuf_worker_ready && + if (mbuf_worker_ready && mbuf_worker_needs_wakeup) { wakeup((caddr_t)&mbuf_worker_needs_wakeup); mbuf_worker_needs_wakeup = FALSE; @@ -6573,8 +6591,8 @@ mbuf_worker_thread(void) } m_region_expand(MC_CL) = 0; - if (n > 0 && freelist_populate(MC_CL, n, M_WAIT) > 0) - mbuf_expand++; + if (n > 0) + freelist_populate(MC_CL, n, M_WAIT); } if (m_region_expand(MC_BIGCL) > 0) { int n; @@ -6589,8 +6607,8 @@ mbuf_worker_thread(void) } m_region_expand(MC_BIGCL) = 0; - if (n > 0 && freelist_populate(MC_BIGCL, n, M_WAIT) > 0) - mbuf_expand++; + if (n > 0) + freelist_populate(MC_BIGCL, n, M_WAIT); } if (m_region_expand(MC_16KCL) > 0) { int n; @@ -6615,13 +6633,11 @@ mbuf_worker_thread(void) * mbufs -- otherwise we could have a large number of useless * clusters allocated. */ - if (mbuf_expand) { - while (m_total(MC_MBUF) < - (m_total(MC_BIGCL) + m_total(MC_CL))) { - mb_expand_cnt++; - if (freelist_populate(MC_MBUF, 1, M_WAIT) == 0) - break; - } + while (m_total(MC_MBUF) < + (m_total(MC_BIGCL) + m_total(MC_CL) + m_total(MC_16KCL))) { + mb_expand_cnt++; + if (freelist_populate(MC_MBUF, 1, M_WAIT) == 0) + break; } mbuf_worker_needs_wakeup = TRUE; @@ -8219,20 +8235,23 @@ static int mbtest_running; static void mbtest_thread(__unused void *arg) { int i; - + int scale_down = 1; + int iterations = 250; + int allocations = nmbclusters; + iterations = iterations / scale_down; + allocations = allocations / scale_down; printf("%s thread starting\n", __func__); - - for (i = 0; i < 1000; i++) { - unsigned int needed = 100000; + for (i = 0; i < iterations; i++) { + unsigned int needed = allocations; struct mbuf *m1, *m2, *m3; if (njcl > 0) { - needed = 100000; + needed = allocations; m3 = m_getpackets_internal(&needed, 0, M_DONTWAIT, 0, M16KCLBYTES); m_freem_list(m3); } - needed = 100000; + needed = allocations; m2 = m_getpackets_internal(&needed, 0, M_DONTWAIT, 0, MBIGCLBYTES); m_freem_list(m2); diff --git a/bsd/kern/uipc_mbuf2.c b/bsd/kern/uipc_mbuf2.c index fc22ee904..31edbc0ce 100644 --- a/bsd/kern/uipc_mbuf2.c +++ b/bsd/kern/uipc_mbuf2.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2017 Apple Inc. All rights reserved. + * Copyright (c) 2000-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -130,9 +130,9 @@ struct mbuf * m_pulldown(struct mbuf *m, int off, int len, int *offp) { - struct mbuf *n, *o; - int hlen, tlen, olen; - int sharedcluster; + struct mbuf *n = NULL, *o = NULL; + int hlen = 0, tlen = 0, olen = 0; + int sharedcluster = 0; #if defined(PULLDOWN_STAT) && INET6 static struct mbuf *prev = NULL; int prevlen = 0, prevmlen = 0; @@ -222,15 +222,24 @@ m_pulldown(struct mbuf *m, int off, int len, int *offp) } #endif n = m; + + /* + * Iterate and make n point to the mbuf + * within which the first byte at length + * offset is contained from the start of + * mbuf chain. + */ while (n != NULL && off > 0) { if (n->m_len > off) break; off -= n->m_len; n = n->m_next; } + /* be sure to point non-empty mbuf */ while (n != NULL && n->m_len == 0) n = n->m_next; + if (!n) { m_freem(m); return NULL; /* mbuf chain too short */ @@ -239,6 +248,16 @@ m_pulldown(struct mbuf *m, int off, int len, int *offp) /* * the target data is on . * if we got enough data on the mbuf "n", we're done. + * + * It should be noted, that we should only do this either + * when offset is 0, i.e. data is pointing to the start + * or when the caller specifies an out argument to get + * the offset value in the mbuf to work with data pointer + * correctly. + * + * If offset is not 0 and caller did not provide out-argument + * to get offset, we should split the mbuf even when the length + * is contained in current mbuf. */ if ((off == 0 || offp) && len <= n->m_len - off) goto ok; @@ -248,12 +267,12 @@ m_pulldown(struct mbuf *m, int off, int len, int *offp) #endif /* - * when len < n->m_len - off and off != 0, it is a special case. + * when len <= n->m_len - off and off != 0, it is a special case. * len bytes from sits in single mbuf, but the caller does * not like the starting position (off). * chop the current mbuf into two pieces, set off to 0. */ - if (len < n->m_len - off) { + if (len <= n->m_len - off) { o = m_copym(n, off, n->m_len - off, M_DONTWAIT); if (o == NULL) { m_freem(m); @@ -271,6 +290,8 @@ m_pulldown(struct mbuf *m, int off, int len, int *offp) * we need to take hlen from and tlen from m_next, 0>, * and construct contiguous mbuf with m_len == len. * note that hlen + tlen == len, and tlen > 0. + * + * Read these variables as head length and tail length */ hlen = n->m_len - off; tlen = len - hlen; @@ -301,6 +322,12 @@ m_pulldown(struct mbuf *m, int off, int len, int *offp) else sharedcluster = 0; } + + /* + * If we have enough space left in current mbuf to accomodate + * tail length, copy tail length worth of data starting with next mbuf + * and adjust the length of next one accordingly. + */ if ((off == 0 || offp) && M_TRAILINGSPACE(n) >= tlen && !sharedcluster) { m_copydata(n->m_next, 0, tlen, mtod(n, caddr_t) + n->m_len); @@ -308,8 +335,15 @@ m_pulldown(struct mbuf *m, int off, int len, int *offp) m_adj(n->m_next, tlen); goto ok; } - if ((off == 0 || offp) && M_LEADINGSPACE(n->m_next) >= hlen - && !sharedcluster) { + + /* + * If have enough leading space in next mbuf to accomodate head length + * of current mbuf, and total resulting length of next mbuf is greater + * than or equal to requested len bytes, then just copy hlen from + * current to the next one and adjust sizes accordingly. + */ + if ((off == 0 || offp) && M_LEADINGSPACE(n->m_next) >= hlen && + (n->m_next->m_len + hlen) >= len && !sharedcluster) { n->m_next->m_data -= hlen; n->m_next->m_len += hlen; bcopy(mtod(n, caddr_t) + off, mtod(n->m_next, caddr_t), hlen); diff --git a/bsd/kern/uipc_socket.c b/bsd/kern/uipc_socket.c index 7d744eff9..bd6b3030f 100644 --- a/bsd/kern/uipc_socket.c +++ b/bsd/kern/uipc_socket.c @@ -5128,6 +5128,15 @@ sosetoptlock(struct socket *so, struct sockopt *sopt, int dolock) so->so_flags |= SOF_PRIVILEGED_TRAFFIC_CLASS; break; +#if (DEVELOPMENT || DEBUG) + case SO_DEFUNCTIT: + error = sosetdefunct(current_proc(), so, 0, FALSE); + if (error == 0) + error = sodefunct(current_proc(), so, 0); + + break; +#endif /* (DEVELOPMENT || DEBUG) */ + case SO_DEFUNCTOK: error = sooptcopyin(sopt, &optval, sizeof (optval), sizeof (optval)); diff --git a/bsd/kern/uipc_socket2.c b/bsd/kern/uipc_socket2.c index ce89864cc..87d06ad39 100644 --- a/bsd/kern/uipc_socket2.c +++ b/bsd/kern/uipc_socket2.c @@ -1434,7 +1434,7 @@ sbappendstream_rcvdemux(struct socket *so, struct mbuf *m, uint32_t seqnum, ret = sbappendmsgstream_rcv(&so->so_rcv, m, seqnum, unordered); } #if MPTCP - else if (so->so_flags & SOF_MPTCP_TRUE) { + else if (so->so_flags & SOF_MP_SUBFLOW) { ret = sbappendmptcpstream_rcv(&so->so_rcv, m); } #endif /* MPTCP */ @@ -1457,8 +1457,8 @@ sbappendmptcpstream_rcv(struct sockbuf *sb, struct mbuf *m) if (m == NULL || m_pktlen(m) == 0 || (sb->sb_flags & SB_DROP) || (so->so_state & SS_CANTRCVMORE)) { - if (m && m_pktlen(m) == 0 && - (m->m_flags & M_PKTHDR) && + if (m && (m->m_flags & M_PKTHDR) && + m_pktlen(m) == 0 && (m->m_pkthdr.pkt_flags & PKTF_MPTCP_DFIN)) { mptcp_input(tptomptp(sototcpcb(so))->mpt_mpte, m); return (1); diff --git a/bsd/libkern/crc16.c b/bsd/libkern/crc16.c index d0358dd0d..9424dee87 100644 --- a/bsd/libkern/crc16.c +++ b/bsd/libkern/crc16.c @@ -1,15 +1,29 @@ /* - * Copyright (C) 2016 Apple Inc. All rights reserved. + * Copyright (c) 2016-2018 Apple Inc. All rights reserved. * - * This document is the property of Apple Inc. - * It is considered confidential and proprietary. + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * - * This document may not be reproduced or transmitted in any form, - * in whole or in part, without the express written permission of - * Apple Inc. + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. * - * CRC-16-ANSI (aka CRC-16-IBM) Polynomial: x^16 + x^15 + x^2 + 1 - * Derived from Craig Marciniak's "Craig's Portable CRC16 Library." + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ #include @@ -62,3 +76,17 @@ crc16(uint16_t crc, const void *buf, size_t size) return crc; } + +#if KASAN +uint16_t +__nosan_crc16(uint16_t crc, const void *buf, size_t size) +{ + const uint8_t *p = buf; + + while (size--) { + crc = crc16_tab[(crc ^ (*p++)) & 0xFF] ^ (crc >> 8); + } + + return crc; +} +#endif diff --git a/bsd/libkern/libkern.h b/bsd/libkern/libkern.h index e2a47fdef..fa8317325 100644 --- a/bsd/libkern/libkern.h +++ b/bsd/libkern/libkern.h @@ -179,6 +179,15 @@ int _consume_printf_args(int, ...); uint16_t crc16(uint16_t crc, const void *bufp, size_t len); uint32_t crc32(uint32_t crc, const void *bufp, size_t len); +#if XNU_KERNEL_PRIVATE +#if KASAN +uint16_t __nosan_crc16(uint16_t crc, const void *bufp, size_t len); +#else +static inline uint16_t +__nosan_crc16(uint16_t crc, const void *bufp, size_t len) { return crc16(crc, bufp, len); } +#endif +#endif + int copystr(const void *kfaddr, void *kdaddr, size_t len, size_t *done); int copyinstr(const user_addr_t uaddr, void *kaddr, size_t len, size_t *done); int copyoutstr(const void *kaddr, user_addr_t udaddr, size_t len, size_t *done); @@ -229,6 +238,20 @@ clz(unsigned int num) #endif } +#if XNU_KERNEL_PRIVATE + +/* + * Define a function that for whatever reason needs to exist, but must never be + * called. + */ +#define UNSUPPORTED_API(funcname, ...) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wunused-parameter\"") \ + funcname(__VA_ARGS__) { panic(__func__ ": unsupported API\n"); } \ + _Pragma("clang diagnostic pop") + +#endif + __END_DECLS #endif /* _LIBKERN_LIBKERN_H_ */ diff --git a/bsd/man/man2/fcntl.2 b/bsd/man/man2/fcntl.2 index b55972bd9..0ea25179c 100644 --- a/bsd/man/man2/fcntl.2 +++ b/bsd/man/man2/fcntl.2 @@ -56,7 +56,7 @@ .\" .\" @(#)fcntl.2 8.2 (Berkeley) 1/12/94 .\" -.Dd February 17, 2011 +.Dd August 24, 2017 .Dt FCNTL 2 .Os BSD 4.2 .Sh NAME @@ -153,8 +153,10 @@ The argument must be a buffer of size or greater. .It Dv F_PREALLOCATE Preallocate file storage space. Note: upon success, -the space that is allocated can be the same size or -larger than the space requested. +the space that is allocated can be the size requested, +larger than the size requested, or (if the +.Dv F_ALLOCATEALL +flag is not provided) smaller than the space requested. .It Dv F_PUNCHHOLE Deallocate a region and replace it with a hole. Subsequent reads of the affected region will return bytes of zeros that are usually not backed by @@ -779,6 +781,31 @@ or and satisfying the lock or unlock request would result in the number of locked regions in the system exceeding a system-imposed limit. .\" ========== +.It Bq Er ENOSPC +The argument +.Fa cmd +is +.Dv F_PREALLOCATE +and either there is no space available on the volume containing +.Fa fildes +or +.Fa fst_flags +contains +.Dv F_ALLOCATEALL +and there is not enough space available on the volume containing +.Fa fildes +to satisfy the entire request. +.Pp +The argument +.Fa cmd +is +.Dv F_PUNCHHOLE +and there is not enough space available on the volume containing +.Fa fildes +to satisfy the request. As an example, a filesystem that supports +cloned files may return this error if punching a hole requires the +creation of a clone and there is not enough space available to do so. +.\" ========== .It Bq Er EOVERFLOW A return value would overflow its representation. For example, @@ -788,6 +815,11 @@ and the smallest (or, if l_len is non-zero, the largest) offset of a byte in the requested segment will not fit in an object of type off_t. .\" ========== +.It Bq Er EPERM +The argument cmd is +.Dv F_PUNCHHOLE +and the calling process does not have file write permission. +.\" ========== .It Bq Er ESRCH .Fa Cmd is diff --git a/bsd/man/man2/fs_snapshot_create.2 b/bsd/man/man2/fs_snapshot_create.2 index 57e3b3d34..d9b740f67 100644 --- a/bsd/man/man2/fs_snapshot_create.2 +++ b/bsd/man/man2/fs_snapshot_create.2 @@ -48,9 +48,9 @@ The .Fn fs_snapshot_create function, for supported Filesystems, causes a snapshot of the Filesystem to be created. A snapshot is a read only copy -of the filesystem frozen at a point in time. The Filesystem is identified by the the +of the filesystem frozen at a point in time. The Filesystem is identified by the .Fa dirfd -parameter which should be a file descriptor associated with the root directory of the filesystem for the snapshot is to be created. +parameter which should be a file descriptor associated with the root directory of the filesystem for which the snapshot is to be created. .Fa name can be any valid name for a component name (except . and ..). . @@ -94,11 +94,13 @@ Upon successful completion, .Fn fs_snapshot_create , .Fn fs_snapshot_delete -, -.Fn fs_snapshot_rename and -.Fn fs_snapshot_list +.Fn fs_snapshot_rename returns 0. Otherwise, a value of -1 is returned and errno is set to indicate the error. +.Fn fs_snapshot_list +returns the number of entries successfully read. A return value of 0 indicates there are no more entries. +Otherwise, a value of -1 is returned and errno is set to indicate the error. Return values are the same as +.Xr getattrlistbulk 2 . .Pp .Sh COMPATIBILITY Not all volumes support snapshots. A volume can be tested for snapshot support diff --git a/bsd/man/man2/getattrlistbulk.2 b/bsd/man/man2/getattrlistbulk.2 index 4c7b0ede8..aaf91dd5a 100644 --- a/bsd/man/man2/getattrlistbulk.2 +++ b/bsd/man/man2/getattrlistbulk.2 @@ -39,6 +39,9 @@ each directory entry like Note: when .Fn getattrlistbulk returns information about a symbolic link, the information returned is about the link itself, not the target of the link. +The order of the directory entries (and their associated metadata) vended by +.Fn getattrlistbulk +is not specified. Some file systems may return entries in lexicographic sort order and others may not. .Pp The function reads directory entries from the directory referenced by the file descriptor diff --git a/bsd/man/man2/getdirentries.2 b/bsd/man/man2/getdirentries.2 index 7e04d0df5..f465c5790 100644 --- a/bsd/man/man2/getdirentries.2 +++ b/bsd/man/man2/getdirentries.2 @@ -68,7 +68,11 @@ with buffers smaller than this size. The data in the buffer is a series of .Em dirent structures (see -.Xr dir 5 ) +.Xr dir 5) +The order of the directory entries vended out via +.Fn getdirentries +is not specified. Some filesystems may return entries in lexicographic sort order +and others may not. .Pp The .Fa d_fileno diff --git a/bsd/miscfs/specfs/spec_vnops.c b/bsd/miscfs/specfs/spec_vnops.c index 11c3ac25e..6e0c09d1c 100644 --- a/bsd/miscfs/specfs/spec_vnops.c +++ b/bsd/miscfs/specfs/spec_vnops.c @@ -1925,6 +1925,11 @@ void throttle_set_thread_io_policy(int policy) proc_set_thread_policy(current_thread(), TASK_POLICY_INTERNAL, TASK_POLICY_IOPOL, policy); } +int throttle_get_thread_effective_io_policy() +{ + return proc_get_effective_thread_policy(current_thread(), TASK_POLICY_IO); +} + void throttle_info_reset_window(uthread_t ut) { struct _throttle_io_info_t *info; @@ -2709,21 +2714,35 @@ spec_knote_select_and_link(struct knote *kn) rlptr = (void *)&rsvd_arg; /* - * Trick selrecord() into hooking kqueue's wait queue set - * set into device's selinfo wait queue + * Trick selrecord() into hooking kqueue's wait queue set into the device's + * selinfo wait queue. */ old_wqs = uth->uu_wqset; uth->uu_wqset = &(knote_get_kq(kn)->kq_wqs); + /* + * Now these are the laws of VNOP_SELECT, as old and as true as the sky, + * And the device that shall keep it may prosper, but the device that shall + * break it must receive ENODEV: + * + * 1. Take a lock to protect against other selects on the same vnode. + * 2. Return 1 if data is ready to be read. + * 3. Return 0 and call `selrecord` on a handy `selinfo` structure if there + * is no data. + * 4. Call `selwakeup` when the vnode has an active `selrecord` and data + * can be read or written (depending on the seltype). + * 5. If there's a `selrecord` and no corresponding `selwakeup`, but the + * vnode is going away, call `selthreadclear`. + */ selres = VNOP_SELECT(vp, knote_get_seltype(kn), 0, rlptr, ctx); uth->uu_wqset = old_wqs; /* - * make sure to cleanup the reserved link - this guards against + * Make sure to cleanup the reserved link - this guards against * drivers that may not actually call selrecord(). */ waitq_link_release(rsvd); if (rsvd != rsvd_arg) { - /* the driver / handler called selrecord() */ + /* The driver / handler called selrecord() */ struct waitq *wq; memcpy(&wq, rlptr, sizeof(void *)); @@ -2748,8 +2767,14 @@ spec_knote_select_and_link(struct knote *kn) * device won't go away while we get this ID. */ kn->kn_hook_data = waitq_get_prepost_id(wq); - } else { - assert(selres != 0); + } else if (selres == 0) { + /* + * The device indicated that there's no data to read, but didn't call + * `selrecord`. Nothing will be notified of changes to this vnode, so + * return an error back to user space, to make it clear that the knote + * is not attached. + */ + knote_set_error(kn, ENODEV); } vnode_put(vp); diff --git a/bsd/net/Makefile b/bsd/net/Makefile index 98db2444f..a2e90264f 100644 --- a/bsd/net/Makefile +++ b/bsd/net/Makefile @@ -46,6 +46,7 @@ PRIVATE_DATAFILES = \ if_media.h \ if_mib.h \ if_pflog.h \ + if_ports_used.h \ if_ppp.h \ if_utun.h \ if_var.h \ diff --git a/bsd/net/bpf.c b/bsd/net/bpf.c index 1448fc02b..70b69823b 100644 --- a/bsd/net/bpf.c +++ b/bsd/net/bpf.c @@ -547,6 +547,7 @@ bpf_detachd(struct bpf_d *d, int closing) struct bpf_if *bp; struct ifnet *ifp; + int bpf_closed = d->bd_flags & BPF_CLOSING; /* * Some other thread already detached */ @@ -615,6 +616,9 @@ bpf_detachd(struct bpf_d *d, int closing) */ d->bd_flags &= ~BPF_DETACHING; d->bd_flags |= BPF_DETACHED; + + /* Refresh the local variable as d could have been modified */ + bpf_closed = d->bd_flags & BPF_CLOSING; /* * Note that We've kept the reference because we may have dropped * the lock when turning off promiscuous mode @@ -631,7 +635,7 @@ bpf_detachd(struct bpf_d *d, int closing) /* * Let the caller know the bpf_d is closed */ - if ((d->bd_flags & BPF_CLOSING)) + if (bpf_closed) return (1); else return (0); @@ -1508,7 +1512,7 @@ bpfioctl(dev_t dev, u_long cmd, caddr_t addr, __unused int flags, * Set buffer length. */ case BIOCSBLEN: /* u_int */ - if (d->bd_bif != 0) + if (d->bd_bif != 0 || (d->bd_flags & BPF_DETACHING)) error = EINVAL; else { u_int size; @@ -2585,6 +2589,9 @@ catchpacket(struct bpf_d *d, struct bpf_packet * pkt, if (totlen > d->bd_bufsize) totlen = d->bd_bufsize; + if (hdrlen > totlen) + return; + /* * Round up the end of the previous packet to the next longword. */ diff --git a/bsd/net/classq/classq_fq_codel.c b/bsd/net/classq/classq_fq_codel.c index f762add42..f004be340 100644 --- a/bsd/net/classq/classq_fq_codel.c +++ b/bsd/net/classq/classq_fq_codel.c @@ -47,7 +47,8 @@ #include #include -static struct zone *flowq_zone = NULL; +static uint32_t flowq_size; /* size of flowq */ +static struct mcache *flowq_cache = NULL; /* mcache for flowq */ #define FQ_ZONE_MAX (32 * 1024) /* across all interfaces */ @@ -58,30 +59,35 @@ static struct zone *flowq_zone = NULL; void fq_codel_init(void) { - if (flowq_zone != NULL) + if (flowq_cache != NULL) return; - flowq_zone = zinit(sizeof (struct flowq), - FQ_ZONE_MAX * sizeof (struct flowq), 0, "flowq_zone"); - if (flowq_zone == NULL) { - panic("%s: failed to allocate flowq_zone", __func__); + flowq_size = sizeof (fq_t); + flowq_cache = mcache_create("fq.flowq", flowq_size, sizeof (uint64_t), + 0, MCR_SLEEP); + if (flowq_cache == NULL) { + panic("%s: failed to allocate flowq_cache", __func__); /* NOTREACHED */ } - zone_change(flowq_zone, Z_EXPAND, TRUE); - zone_change(flowq_zone, Z_CALLERACCT, TRUE); +} + +void +fq_codel_reap_caches(boolean_t purge) +{ + mcache_reap_now(flowq_cache, purge); } fq_t * fq_alloc(classq_pkt_type_t ptype) { fq_t *fq = NULL; - fq = zalloc(flowq_zone); + fq = mcache_alloc(flowq_cache, MCR_SLEEP); if (fq == NULL) { - log(LOG_ERR, "%s: unable to allocate from flowq_zone\n"); + log(LOG_ERR, "%s: unable to allocate from flowq_cache\n"); return (NULL); } - bzero(fq, sizeof (*fq)); + bzero(fq, flowq_size); fq->fq_ptype = ptype; if (ptype == QP_MBUF) { MBUFQ_INIT(&fq->fq_mbufq); @@ -95,7 +101,7 @@ fq_destroy(fq_t *fq) VERIFY(fq_empty(fq)); VERIFY(!(fq->fq_flags & (FQF_NEW_FLOW | FQF_OLD_FLOW))); VERIFY(fq->fq_bytes == 0); - zfree(flowq_zone, fq); + mcache_free(flowq_cache, fq); } static void diff --git a/bsd/net/classq/classq_fq_codel.h b/bsd/net/classq/classq_fq_codel.h index 6683256c1..6db259bb7 100644 --- a/bsd/net/classq/classq_fq_codel.h +++ b/bsd/net/classq/classq_fq_codel.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017 Apple Inc. All rights reserved. + * Copyright (c) 2016-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -87,6 +87,7 @@ struct fq_if_classq; /* Function definitions */ extern void fq_codel_init(void); +extern void fq_codel_reap_caches(boolean_t); extern fq_t *fq_alloc(classq_pkt_type_t); extern void fq_destroy(fq_t *); extern int fq_addq(struct fq_codel_sched_data *, pktsched_pkt_t *, diff --git a/bsd/net/classq/classq_subr.c b/bsd/net/classq/classq_subr.c index 669e45ad6..7c93bc65e 100644 --- a/bsd/net/classq/classq_subr.c +++ b/bsd/net/classq/classq_subr.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -793,3 +794,9 @@ ifclassq_calc_update_interval(u_int64_t *update_interval) *update_interval = uint; } + +void +ifclassq_reap_caches(boolean_t purge) +{ + fq_codel_reap_caches(purge); +} diff --git a/bsd/net/classq/if_classq.h b/bsd/net/classq/if_classq.h index 148426903..18e9bc7f8 100644 --- a/bsd/net/classq/if_classq.h +++ b/bsd/net/classq/if_classq.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 Apple Inc. All rights reserved. + * Copyright (c) 2011-2017 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -365,6 +365,7 @@ extern void ifclassq_calc_target_qdelay(struct ifnet *ifp, extern void ifclassq_calc_update_interval(u_int64_t *update_interval); extern void ifclassq_set_packet_metadata(struct ifclassq *ifq, struct ifnet *ifp, void *p, classq_pkt_type_t ptype); +extern void ifclassq_reap_caches(boolean_t); #endif /* BSD_KERNEL_PRIVATE */ #endif /* PRIVATE */ diff --git a/bsd/net/dlil.c b/bsd/net/dlil.c index 9219ab940..c4acddac2 100644 --- a/bsd/net/dlil.c +++ b/bsd/net/dlil.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2017 Apple Inc. All rights reserved. + * Copyright (c) 1999-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -75,6 +75,7 @@ #include #include #include +#include #if INET #include @@ -322,7 +323,8 @@ static void dlil_if_trace(struct dlil_ifnet *, int); static void if_proto_ref(struct if_proto *); static void if_proto_free(struct if_proto *); static struct if_proto *find_attached_proto(struct ifnet *, u_int32_t); -static int dlil_ifp_proto_count(struct ifnet *); +static u_int32_t dlil_ifp_protolist(struct ifnet *ifp, protocol_family_t *list, + u_int32_t list_count); static void if_flt_monitor_busy(struct ifnet *); static void if_flt_monitor_unbusy(struct ifnet *); static void if_flt_monitor_enter(struct ifnet *); @@ -432,7 +434,6 @@ static int sysctl_rcvq_maxlen SYSCTL_HANDLER_ARGS; static int sysctl_hwcksum_dbg_mode SYSCTL_HANDLER_ARGS; static int sysctl_hwcksum_dbg_partial_rxoff_forced SYSCTL_HANDLER_ARGS; static int sysctl_hwcksum_dbg_partial_rxoff_adj SYSCTL_HANDLER_ARGS; -static int sysctl_get_ports_used SYSCTL_HANDLER_ARGS; struct chain_len_stats tx_chain_len_stats; static int sysctl_tx_chain_len_stats SYSCTL_HANDLER_ARGS; @@ -519,12 +520,6 @@ struct timespec dlil_dbgrate = { 1, 0 }; SYSCTL_DECL(_net_link_generic_system); -#if CONFIG_MACF -SYSCTL_INT(_net_link_generic_system, OID_AUTO, dlil_lladdr_ckreq, - CTLFLAG_RW | CTLFLAG_LOCKED, &dlil_lladdr_ckreq, 0, - "Require MACF system info check to expose link-layer address"); -#endif - SYSCTL_INT(_net_link_generic_system, OID_AUTO, dlil_verbose, CTLFLAG_RW | CTLFLAG_LOCKED, &dlil_verbose, 0, "Log DLIL error messages"); @@ -734,9 +729,6 @@ uint32_t tx_chain_len_count = 0; SYSCTL_UINT(_net_link_generic_system, OID_AUTO, tx_chain_len_count, CTLFLAG_RW | CTLFLAG_LOCKED, &tx_chain_len_count, 0, ""); -SYSCTL_NODE(_net_link_generic_system, OID_AUTO, get_ports_used, - CTLFLAG_RD | CTLFLAG_LOCKED, sysctl_get_ports_used, ""); - static uint32_t threshold_notify = 1; /* enable/disable */ SYSCTL_UINT(_net_link_generic_system, OID_AUTO, threshold_notify, CTLFLAG_RW | CTLFLAG_LOCKED, &threshold_notify, 0, ""); @@ -910,13 +902,24 @@ if_proto_free(struct if_proto *proto) */ ifnet_lock_shared(ifp); ev_pr_data.proto_family = proto_family; - ev_pr_data.proto_remaining_count = dlil_ifp_proto_count(ifp); + ev_pr_data.proto_remaining_count = dlil_ifp_protolist(ifp, NULL, 0); ifnet_lock_done(ifp); dlil_post_msg(ifp, KEV_DL_SUBCLASS, KEV_DL_PROTO_DETACHED, (struct net_event_data *)&ev_pr_data, sizeof (struct kev_dl_proto_data)); + if (ev_pr_data.proto_remaining_count == 0) { + /* + * The protocol count has gone to zero, mark the interface down. + * This used to be done by configd.KernelEventMonitor, but that + * is inherently prone to races (rdar://problem/30810208). + */ + (void) ifnet_set_flags(ifp, 0, IFF_UP); + (void) ifnet_ioctl(ifp, 0, SIOCSIFFLAGS, NULL); + dlil_post_sifflags_msg(ifp); + } + zfree(dlif_proto_zone, proto); } @@ -1038,12 +1041,20 @@ ifnet_head_assert_exclusive(void) } /* - * Caller must already be holding ifnet lock. + * dlil_ifp_protolist + * - get the list of protocols attached to the interface, or just the number + * of attached protocols + * - if the number returned is greater than 'list_count', truncation occurred + * + * Note: + * - caller must already be holding ifnet lock. */ -static int -dlil_ifp_proto_count(struct ifnet *ifp) +static u_int32_t +dlil_ifp_protolist(struct ifnet *ifp, protocol_family_t *list, + u_int32_t list_count) { - int i, count = 0; + u_int32_t count = 0; + int i; ifnet_lock_assert(ifp, IFNET_LCK_ASSERT_OWNED); @@ -1053,6 +1064,9 @@ dlil_ifp_proto_count(struct ifnet *ifp) for (i = 0; i < PROTO_HASH_SLOTS; i++) { struct if_proto *proto; SLIST_FOREACH(proto, &ifp->if_proto_hash[i], next_hash) { + if (list != NULL && count < list_count) { + list[count] = proto->protocol_family; + } count++; } } @@ -1060,6 +1074,21 @@ dlil_ifp_proto_count(struct ifnet *ifp) return (count); } +__private_extern__ u_int32_t +if_get_protolist(struct ifnet * ifp, u_int32_t *protolist, u_int32_t count) +{ + ifnet_lock_shared(ifp); + count = dlil_ifp_protolist(ifp, protolist, count); + ifnet_lock_done(ifp); + return (count); +} + +__private_extern__ void +if_free_protolist(u_int32_t *list) +{ + _FREE(list, M_TEMP); +} + __private_extern__ void dlil_post_msg(struct ifnet *ifp, u_int32_t event_subclass, u_int32_t event_code, struct net_event_data *event_data, @@ -1684,6 +1713,9 @@ dlil_init(void) /* Initialize the service class to dscp map */ net_qos_map_init(); + /* Initialize the interface port list */ + if_ports_used_init(); + #if DEBUG || DEVELOPMENT /* Run self-tests */ dlil_verify_sum16(); @@ -2697,7 +2729,8 @@ dlil_input_handler(struct ifnet *ifp, struct mbuf *m_head, if (inp == dlil_main_input_thread) dlil_input_stats_sync(ifp, inp); - if (qlen(&inp->rcvq_pkts) >= dlil_rcv_mit_pkts_min && + if (inp->input_mit_tcall && + qlen(&inp->rcvq_pkts) >= dlil_rcv_mit_pkts_min && qlen(&inp->rcvq_pkts) < dlil_rcv_mit_pkts_max && (ifp->if_family == IFNET_FAMILY_ETHERNET || ifp->if_type == IFT_CELLULAR) @@ -4006,6 +4039,27 @@ dlil_post_complete_msg(struct ifnet *ifp, struct kev_msg *event) return (kev_post_msg(event)); } +__private_extern__ void +dlil_post_sifflags_msg(struct ifnet * ifp) +{ + struct kev_msg ev_msg; + struct net_event_data ev_data; + + bzero(&ev_data, sizeof (ev_data)); + bzero(&ev_msg, sizeof (ev_msg)); + ev_msg.vendor_code = KEV_VENDOR_APPLE; + ev_msg.kev_class = KEV_NETWORK_CLASS; + ev_msg.kev_subclass = KEV_DL_SUBCLASS; + ev_msg.event_code = KEV_DL_SIFFLAGS; + strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ); + ev_data.if_family = ifp->if_family; + ev_data.if_unit = (u_int32_t) ifp->if_unit; + ev_msg.dv[0].data_length = sizeof(struct net_event_data); + ev_msg.dv[0].data_ptr = &ev_data; + ev_msg.dv[1].data_length = 0; + dlil_post_complete_msg(ifp, &ev_msg); +} + #define TMP_IF_PROTO_ARR_SIZE 10 static int dlil_event_internal(struct ifnet *ifp, struct kev_msg *event, bool update_generation) @@ -4048,7 +4102,7 @@ dlil_event_internal(struct ifnet *ifp, struct kev_msg *event, bool update_genera * therefore we are avoiding embedded pointers here. */ ifnet_lock_shared(ifp); - if_proto_count = dlil_ifp_proto_count(ifp); + if_proto_count = dlil_ifp_protolist(ifp, NULL, 0); if (if_proto_count) { int i; VERIFY(ifp->if_proto_hash != NULL); @@ -5198,7 +5252,8 @@ dlil_attach_protocol_internal(struct if_proto *proto, * (subject to change) */ ev_pr_data.proto_family = proto->protocol_family; - ev_pr_data.proto_remaining_count = dlil_ifp_proto_count(ifp); + ev_pr_data.proto_remaining_count = dlil_ifp_protolist(ifp, NULL, 0); + ifnet_lock_done(ifp); dlil_post_msg(ifp, KEV_DL_SUBCLASS, KEV_DL_PROTO_ATTACHED, @@ -5265,6 +5320,14 @@ ifnet_attach_protocol(ifnet_t ifp, protocol_family_t protocol, } ifnet_head_done(); if (retval == 0) { + /* + * A protocol has been attached, mark the interface up. + * This used to be done by configd.KernelEventMonitor, but that + * is inherently prone to races (rdar://problem/30810208). + */ + (void) ifnet_set_flags(ifp, IFF_UP, IFF_UP); + (void) ifnet_ioctl(ifp, 0, SIOCSIFFLAGS, NULL); + dlil_post_sifflags_msg(ifp); } else if (ifproto != NULL) { zfree(dlif_proto_zone, ifproto); } @@ -5326,6 +5389,14 @@ ifnet_attach_protocol_v2(ifnet_t ifp, protocol_family_t protocol, } ifnet_head_done(); if (retval == 0) { + /* + * A protocol has been attached, mark the interface up. + * This used to be done by configd.KernelEventMonitor, but that + * is inherently prone to races (rdar://problem/30810208). + */ + (void) ifnet_set_flags(ifp, IFF_UP, IFF_UP); + (void) ifnet_ioctl(ifp, 0, SIOCSIFFLAGS, NULL); + dlil_post_sifflags_msg(ifp); } else if (ifproto != NULL) { zfree(dlif_proto_zone, ifproto); } @@ -6705,43 +6776,66 @@ ifp_if_event(struct ifnet *ifp, const struct kev_msg *e) #pragma unused(ifp, e) } -__private_extern__ int dlil_if_acquire(u_int32_t family, const void *uniqueid, - size_t uniqueid_len, struct ifnet **ifp) + size_t uniqueid_len, const char *ifxname, struct ifnet **ifp) { struct ifnet *ifp1 = NULL; struct dlil_ifnet *dlifp1 = NULL; void *buf, *base, **pbuf; int ret = 0; + VERIFY(*ifp == NULL); dlil_if_lock(); + /* + * We absolutely can't have an interface with the same name + * in in-use state. + * To make sure of that list has to be traversed completely + */ TAILQ_FOREACH(dlifp1, &dlil_ifnet_head, dl_if_link) { ifp1 = (struct ifnet *)dlifp1; if (ifp1->if_family != family) continue; + /* + * If interface is in use, return EBUSY if either unique id + * or interface extended names are the same + */ lck_mtx_lock(&dlifp1->dl_if_lock); - /* same uniqueid and same len or no unique id specified */ - if ((uniqueid_len == dlifp1->dl_if_uniqueid_len) && - bcmp(uniqueid, dlifp1->dl_if_uniqueid, uniqueid_len) == 0) { - /* check for matching interface in use */ + if (strncmp(ifxname, ifp1->if_xname, IFXNAMSIZ) == 0) { if (dlifp1->dl_if_flags & DLIF_INUSE) { - if (uniqueid_len) { - ret = EBUSY; + lck_mtx_unlock(&dlifp1->dl_if_lock); + ret = EBUSY; + goto end; + } + } + + if (uniqueid_len) { + if (uniqueid_len == dlifp1->dl_if_uniqueid_len && + bcmp(uniqueid, dlifp1->dl_if_uniqueid, uniqueid_len) == 0) { + if (dlifp1->dl_if_flags & DLIF_INUSE) { lck_mtx_unlock(&dlifp1->dl_if_lock); + ret = EBUSY; goto end; + } else { + dlifp1->dl_if_flags |= (DLIF_INUSE|DLIF_REUSE); + /* Cache the first interface that can be recycled */ + if (*ifp == NULL) + *ifp = ifp1; + /* + * XXX Do not break or jump to end as we have to traverse + * the whole list to ensure there are no name collisions + */ } - } else { - dlifp1->dl_if_flags |= (DLIF_INUSE|DLIF_REUSE); - lck_mtx_unlock(&dlifp1->dl_if_lock); - *ifp = ifp1; - goto end; } } lck_mtx_unlock(&dlifp1->dl_if_lock); } + /* If there's an interface that can be recycled, use that */ + if (*ifp != NULL) + goto end; + /* no interface found, allocate a new one */ buf = zalloc(dlif_zone); if (buf == NULL) { @@ -8660,74 +8754,6 @@ dlil_kev_dl_code_str(u_int32_t event_code) return (""); } -/* - * Mirror the arguments of ifnet_get_local_ports_extended() - * ifindex - * protocol - * flags - */ -static int -sysctl_get_ports_used SYSCTL_HANDLER_ARGS -{ -#pragma unused(oidp) - int *name = (int *)arg1; - int namelen = arg2; - int error = 0; - int idx; - protocol_family_t protocol; - u_int32_t flags; - ifnet_t ifp = NULL; - u_int8_t *bitfield = NULL; - - if (req->newptr != USER_ADDR_NULL) { - error = EPERM; - goto done; - } - if (namelen != 3) { - error = ENOENT; - goto done; - } - - if (req->oldptr == USER_ADDR_NULL) { - req->oldidx = bitstr_size(65536); - goto done; - } - if (req->oldlen < bitstr_size(65536)) { - error = ENOMEM; - goto done; - } - - idx = name[0]; - protocol = name[1]; - flags = name[2]; - - ifnet_head_lock_shared(); - if (!IF_INDEX_IN_RANGE(idx)) { - ifnet_head_done(); - error = ENOENT; - goto done; - } - ifp = ifindex2ifnet[idx]; - ifnet_head_done(); - - bitfield = _MALLOC(bitstr_size(65536), M_TEMP, M_WAITOK | M_ZERO); - if (bitfield == NULL) { - error = ENOMEM; - goto done; - } - error = ifnet_get_local_ports_extended(ifp, protocol, flags, bitfield); - if (error != 0) { - printf("%s: ifnet_get_local_ports_extended() error %d\n", - __func__, error); - goto done; - } - error = SYSCTL_OUT(req, bitfield, bitstr_size(65536)); -done: - if (bitfield != NULL) - _FREE(bitfield, M_TEMP); - return (error); -} - static void dlil_dt_tcall_fn(thread_call_param_t arg0, thread_call_param_t arg1) { diff --git a/bsd/net/dlil.h b/bsd/net/dlil.h index 5a6c669e4..526e82f46 100644 --- a/bsd/net/dlil.h +++ b/bsd/net/dlil.h @@ -326,6 +326,8 @@ extern void dlil_proto_unplumb_all(ifnet_t); extern void dlil_post_msg(struct ifnet *, u_int32_t, u_int32_t, struct net_event_data *, u_int32_t); +extern void dlil_post_sifflags_msg(struct ifnet *); + extern int dlil_post_complete_msg(struct ifnet *, struct kev_msg *); extern int dlil_alloc_local_stats(struct ifnet *); @@ -334,7 +336,7 @@ extern int dlil_alloc_local_stats(struct ifnet *); /* * dlil_if_acquire is obsolete. Use ifnet_allocate. */ -extern int dlil_if_acquire(u_int32_t, const void *, size_t, struct ifnet **); +extern int dlil_if_acquire(u_int32_t, const void *, size_t, const char *, struct ifnet **); /* * dlil_if_release is obsolete. The equivalent is called automatically when * an interface is detached. diff --git a/bsd/net/if.c b/bsd/net/if.c index acd1ac75c..33e626245 100644 --- a/bsd/net/if.c +++ b/bsd/net/if.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2017 Apple Inc. All rights reserved. + * Copyright (c) 2000-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -330,6 +330,7 @@ if_attach_ifa_common(struct ifnet *ifp, struct ifaddr *ifa, int link) if (ifa->ifa_attached != NULL) (*ifa->ifa_attached)(ifa); + } __private_extern__ void @@ -696,8 +697,7 @@ if_clone_list(int count, int *ret_total, user_addr_t dst) for (ifc = LIST_FIRST(&if_cloners); ifc != NULL && count != 0; ifc = LIST_NEXT(ifc, ifc_list), count--, dst += IFNAMSIZ) { bzero(outbuf, sizeof(outbuf)); - strlcpy(outbuf, ifc->ifc_name, - min(strlen(ifc->ifc_name), IFNAMSIZ)); + strlcpy(outbuf, ifc->ifc_name, IFNAMSIZ); error = copyout(outbuf, dst, IFNAMSIZ); if (error) break; @@ -1665,7 +1665,8 @@ ifioctl_linkparams(struct ifnet *ifp, u_long cmd, caddr_t data, struct proc *p) struct tb_profile tb = { 0, 0, 0 }; if ((error = proc_suser(p)) != 0) - break; + break; + IFCQ_LOCK(ifq); if (!IFCQ_IS_READY(ifq)) { @@ -1939,6 +1940,30 @@ if_delete_netagent(struct ifnet *ifp, uuid_t remove_agent_uuid) return (error); } +boolean_t +if_check_netagent(struct ifnet *ifp, uuid_t find_agent_uuid) +{ + boolean_t found = FALSE; + + if (!ifp || uuid_is_null(find_agent_uuid)) + return FALSE; + + ifnet_lock_shared(ifp); + + if (ifp->if_agentids != NULL) { + for (uint32_t index = 0; index < ifp->if_agentcount; index++) { + if (uuid_compare(ifp->if_agentids[index], find_agent_uuid) == 0) { + found = TRUE; + break; + } + } + } + + ifnet_lock_done(ifp); + + return found; +} + static __attribute__((noinline)) int ifioctl_netagent(struct ifnet *ifp, u_long cmd, caddr_t data, struct proc *p) { @@ -2146,7 +2171,7 @@ ifioctl_iforder(u_long cmd, caddr_t data) case SIOCSIFORDER: { /* struct if_order */ struct if_order *ifo = (struct if_order *)(void *)data; - if (ifo->ifo_count == 0 || ifo->ifo_count > (u_int32_t)if_index) { + if (ifo->ifo_count > (u_int32_t)if_index) { error = EINVAL; break; } @@ -2168,20 +2193,22 @@ ifioctl_iforder(u_long cmd, caddr_t data) if (error != 0) { break; } - } - /* ordered_indices should not contain duplicates */ - bool found_duplicate = FALSE; - for (uint32_t i = 0; i < (ifo->ifo_count - 1) && !found_duplicate ; i++){ - for (uint32_t j = i + 1; j < ifo->ifo_count && !found_duplicate ; j++){ - if (ordered_indices[j] == ordered_indices[i]){ - error = EINVAL; - found_duplicate = TRUE; - break; + + /* ordered_indices should not contain duplicates */ + bool found_duplicate = FALSE; + for (uint32_t i = 0; i < (ifo->ifo_count - 1) && !found_duplicate ; i++){ + for (uint32_t j = i + 1; j < ifo->ifo_count && !found_duplicate ; j++){ + if (ordered_indices[j] == ordered_indices[i]){ + error = EINVAL; + found_duplicate = TRUE; + break; + } } } + if (found_duplicate) { + break; + } } - if (found_duplicate) - break; error = ifnet_reset_order(ordered_indices, ifo->ifo_count); @@ -2311,6 +2338,89 @@ ifioctl_nat64prefix(struct ifnet *ifp, u_long cmd, caddr_t data) #endif +static int +ifioctl_get_protolist(struct ifnet *ifp, u_int32_t * ret_count, + user_addr_t ifpl) +{ + u_int32_t actual_count; + u_int32_t count; + int error = 0; + u_int32_t *list = NULL; + + /* find out how many */ + count = if_get_protolist(ifp, NULL, 0); + if (ifpl == USER_ADDR_NULL) { + goto done; + } + + /* copy out how many there's space for */ + if (*ret_count < count) { + count = *ret_count; + } + if (count == 0) { + goto done; + } + list = _MALLOC(count * sizeof(*list), M_TEMP, M_WAITOK); + if (list == NULL) { + error = ENOMEM; + goto done; + } + actual_count = if_get_protolist(ifp, list, count); + if (actual_count < count) { + count = actual_count; + } + if (count != 0) { + error = copyout((caddr_t)list, ifpl, count * sizeof(*list)); + } + + done: + if (list != NULL) { + if_free_protolist(list); + } + *ret_count = count; + return (error); +} + +static __attribute__((noinline)) int +ifioctl_protolist(struct ifnet *ifp, u_long cmd, caddr_t data) +{ + int error = 0; + + switch (cmd) { + case SIOCGIFPROTOLIST32: { /* struct if_protolistreq32 */ + struct if_protolistreq32 ifpl; + + bcopy(data, &ifpl, sizeof(ifpl)); + if (ifpl.ifpl_reserved != 0) { + error = EINVAL; + break; + } + error = ifioctl_get_protolist(ifp, &ifpl.ifpl_count, + CAST_USER_ADDR_T(ifpl.ifpl_list)); + bcopy(&ifpl, data, sizeof(ifpl)); + break; + } + case SIOCGIFPROTOLIST64: { /* struct if_protolistreq64 */ + struct if_protolistreq64 ifpl; + + bcopy(data, &ifpl, sizeof(ifpl)); + if (ifpl.ifpl_reserved != 0) { + error = EINVAL; + break; + } + error = ifioctl_get_protolist(ifp, &ifpl.ifpl_count, + ifpl.ifpl_list); + bcopy(&ifpl, data, sizeof(ifpl)); + break; + } + default: + VERIFY(0); + /* NOTREACHED */ + } + + return (error); +} + /* * List the ioctl()s we can perform on restricted INTCOPROC interfaces. */ @@ -2382,6 +2492,8 @@ ifioctl_restrict_intcoproc(unsigned long cmd, const char *ifname, case SIOCGNBRINFO_IN6: case SIOCGIFALIFETIME_IN6: case SIOCGIFNETMASK_IN6: + case SIOCGIFPROTOLIST32: + case SIOCGIFPROTOLIST64: return (false); default: #if (DEBUG || DEVELOPMENT) @@ -2629,6 +2741,12 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p) ifp = ifunit(ifname); break; + case SIOCGIFPROTOLIST32: /* struct if_protolistreq32 */ + case SIOCGIFPROTOLIST64: /* struct if_protolistreq64 */ + bcopy(((struct if_protolistreq *)(void *)data)->ifpl_name, + ifname, IFNAMSIZ); + ifp = ifunit(ifname); + break; default: /* * This is a bad assumption, but the code seems to @@ -2718,6 +2836,12 @@ ifioctl(struct socket *so, u_long cmd, caddr_t data, struct proc *p) error = ifioctl_nat64prefix(ifp, cmd, data); break; #endif + + case SIOCGIFPROTOLIST32: /* struct if_protolistreq32 */ + case SIOCGIFPROTOLIST64: /* struct if_protolistreq64 */ + error = ifioctl_protolist(ifp, cmd, data); + break; + default: if (so->so_proto == NULL) { error = EOPNOTSUPP; @@ -2871,18 +2995,7 @@ ifioctl_ifreq(struct socket *so, u_long cmd, struct ifreq *ifr, struct proc *p) * Send the event even upon error from the driver because * we changed the flags. */ - ev_msg.vendor_code = KEV_VENDOR_APPLE; - ev_msg.kev_class = KEV_NETWORK_CLASS; - ev_msg.kev_subclass = KEV_DL_SUBCLASS; - - ev_msg.event_code = KEV_DL_SIFFLAGS; - strlcpy(&ev_data.if_name[0], ifp->if_name, IFNAMSIZ); - ev_data.if_family = ifp->if_family; - ev_data.if_unit = (u_int32_t) ifp->if_unit; - ev_msg.dv[0].data_length = sizeof(struct net_event_data); - ev_msg.dv[0].data_ptr = &ev_data; - ev_msg.dv[1].data_length = 0; - dlil_post_complete_msg(ifp, &ev_msg); + dlil_post_sifflags_msg(ifp); ifnet_touch_lastchange(ifp); break; @@ -5021,17 +5134,13 @@ ifioctl_cassert(void) case SIOCSQOSMARKINGENABLED: case SIOCGQOSMARKINGMODE: case SIOCGQOSMARKINGENABLED: + + case SIOCGIFPROTOLIST32: + case SIOCGIFPROTOLIST64: ; } } -/* - * XXX: This API is only used by BSD stack and for now will always return 0. - * For Skywalk native drivers, preamble space need not be allocated in mbuf - * as the preamble will be reserved in the translated skywalk packet - * which is transmitted to the driver. - * For Skywalk compat drivers currently headroom is always set to zero. - */ uint32_t ifnet_mbuf_packetpreamblelen(struct ifnet *ifp) { diff --git a/bsd/net/if.h b/bsd/net/if.h index 2bb7c6655..2583ef5e7 100644 --- a/bsd/net/if.h +++ b/bsd/net/if.h @@ -780,6 +780,7 @@ struct if_linkparamsreq { u_int32_t iflpr_output_sched; u_int64_t iflpr_output_tbr_rate; u_int32_t iflpr_output_tbr_percent; + u_int64_t iflpr_input_tbr_rate; struct if_bandwidths iflpr_output_bw; struct if_bandwidths iflpr_input_bw; struct if_latencies iflpr_output_lt; @@ -882,17 +883,6 @@ struct if_agentidsreq { uuid_t *ifar_uuids; /* array of agent UUIDs */ }; -/* - * Structure for SIOCGIFNEXUS - */ -struct if_nexusreq { - char ifnr_name[IFNAMSIZ]; /* interface name */ - uint64_t ifnr_flags; /* unused, must be zero */ - uuid_t ifnr_netif; /* netif nexus instance UUID */ - uuid_t ifnr_multistack; /* multistack nexus UUID */ - uint64_t ifnr_reserved[5]; -}; - #ifdef BSD_KERNEL_PRIVATE struct if_agentidsreq32 { char ifar_name[IFNAMSIZ]; @@ -906,6 +896,17 @@ struct if_agentidsreq64 { }; #endif /* BSD_KERNEL_PRIVATE */ +/* + * Structure for SIOCGIFNEXUS + */ +struct if_nexusreq { + char ifnr_name[IFNAMSIZ]; /* interface name */ + uint64_t ifnr_flags; /* unused, must be zero */ + uuid_t ifnr_netif; /* netif nexus instance UUID */ + uuid_t ifnr_multistack; /* multistack nexus UUID */ + uint64_t ifnr_reserved[5]; +}; + #define DLIL_MODIDLEN 20 /* same as IFNET_MODIDLEN */ #define DLIL_MODARGLEN 12 /* same as IFNET_MODARGLEN */ @@ -1007,6 +1008,32 @@ struct if_tdmreq64 { }; #endif +/* + * Structure for SIOCGIFPROTOLIST. + */ +struct if_protolistreq { + char ifpl_name[IFNAMSIZ]; + u_int32_t ifpl_count; + u_int32_t ifpl_reserved; /* must be zero */ + u_int32_t *ifpl_list; +}; + +#ifdef BSD_KERNEL_PRIVATE +struct if_protolistreq32 { + char ifpl_name[IFNAMSIZ]; + u_int32_t ifpl_count; + u_int32_t ifpl_reserved; /* must be zero */ + user32_addr_t ifpl_list; +}; + +struct if_protolistreq64 { + char ifpl_name[IFNAMSIZ]; + u_int32_t ifpl_count; + u_int32_t ifpl_reserved; /* must be zero */ + user64_addr_t ifpl_list; +}; +#endif /* BSD_KERNEL_PRIVATE */ + #endif /* PRIVATE */ #ifdef KERNEL diff --git a/bsd/net/if_fake.c b/bsd/net/if_fake.c index 3af936b87..a4c7a69cb 100644 --- a/bsd/net/if_fake.c +++ b/bsd/net/if_fake.c @@ -156,6 +156,18 @@ feth_is_detaching(if_fake_ref fakeif) return ((fakeif->iff_flags & IFF_FLAGS_DETACHING) != 0); } +static int +feth_enable_dequeue_stall(ifnet_t ifp, uint32_t enable) +{ + int error; + + if (enable != 0) + error = ifnet_disable_output(ifp); + else + error = ifnet_enable_output(ifp); + + return (error); +} #define M_FAKE M_DEVBUF @@ -713,14 +725,10 @@ feth_config(ifnet_t ifp, ifnet_t peer) /* generate link status event if we connect or disconnect */ if (connected) { - ifnet_set_flags(ifp, IFF_RUNNING, IFF_RUNNING); - ifnet_set_flags(peer, IFF_RUNNING, IFF_RUNNING); interface_link_event(ifp, KEV_DL_LINK_ON); interface_link_event(peer, KEV_DL_LINK_ON); } else if (disconnected) { - ifnet_set_flags(ifp, 0, IFF_RUNNING); - ifnet_set_flags(peer, 0, IFF_RUNNING); interface_link_event(ifp, KEV_DL_LINK_OFF); interface_link_event(peer, KEV_DL_LINK_OFF); } @@ -823,6 +831,14 @@ feth_set_drvspec(ifnet_t ifp, uint32_t cmd, u_int32_t len, } error = feth_set_media(ifp, &iffr); break; + case IF_FAKE_S_CMD_SET_DEQUEUE_STALL: + error = if_fake_request_copyin(user_addr, &iffr, len); + if (error != 0) { + break; + } + error = feth_enable_dequeue_stall(ifp, + iffr.iffr_dequeue_stall); + break; default: error = EOPNOTSUPP; break; @@ -980,7 +996,17 @@ feth_ioctl(ifnet_t ifp, u_long cmd, void * data) break; case SIOCSIFFLAGS: - error = 0; + if ((ifp->if_flags & IFF_UP) != 0) { + /* marked up, set running if not already set */ + if ((ifp->if_flags & IFF_RUNNING) == 0) { + /* set running */ + error = ifnet_set_flags(ifp, IFF_RUNNING, + IFF_RUNNING); + } + } else if ((ifp->if_flags & IFF_RUNNING) != 0) { + /* marked down, clear running */ + error = ifnet_set_flags(ifp, 0, IFF_RUNNING); + } break; case SIOCADDMULTI: diff --git a/bsd/net/if_fake_var.h b/bsd/net/if_fake_var.h index b6b147070..1b8aaf4b1 100644 --- a/bsd/net/if_fake_var.h +++ b/bsd/net/if_fake_var.h @@ -43,6 +43,7 @@ enum { IF_FAKE_S_CMD_NONE = 0, IF_FAKE_S_CMD_SET_PEER = 1, IF_FAKE_S_CMD_SET_MEDIA = 2, + IF_FAKE_S_CMD_SET_DEQUEUE_STALL = 3, }; /* @@ -68,9 +69,15 @@ struct if_fake_request { char iffru_buf[128]; /* stable size */ struct if_fake_media iffru_media; char iffru_peer_name[IFNAMSIZ]; /* if name, e.g. "en0" */ + /* + * control dequeue stall. 0: disable dequeue stall, else + * enable dequeue stall. + */ + uint32_t iffru_dequeue_stall; } iffr_u; #define iffr_peer_name iffr_u.iffru_peer_name #define iffr_media iffr_u.iffru_media +#define iffr_dequeue_stall iffr_u.iffru_dequeue_stall }; #endif /* _NET_IF_FAKE_VAR_H_ */ diff --git a/bsd/net/if_gif.c b/bsd/net/if_gif.c index 9e2e6c6ea..bb9d156d0 100644 --- a/bsd/net/if_gif.c +++ b/bsd/net/if_gif.c @@ -630,11 +630,13 @@ gif_input( * it occurs more times than we thought, we may change the policy * again. */ + int32_t pktlen = m->m_pkthdr.len; if (proto_input(protocol_family, m) != 0) { ifnet_stat_increment_in(ifp, 0, 0, 1); m_freem(m); - } else - ifnet_stat_increment_in(ifp, 1, m->m_pkthdr.len, 0); + } else { + ifnet_stat_increment_in(ifp, 1, pktlen, 0); + } return (0); } diff --git a/bsd/net/if_ipsec.c b/bsd/net/if_ipsec.c index 4c330d639..7bf02edb9 100644 --- a/bsd/net/if_ipsec.c +++ b/bsd/net/if_ipsec.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2017 Apple Inc. All rights reserved. + * Copyright (c) 2012-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -58,7 +58,6 @@ extern int net_qos_policy_restricted; extern int net_qos_policy_restrict_avapps; -extern unsigned int if_enable_netagent; /* Kernel Control functions */ static errno_t ipsec_ctl_bind(kern_ctl_ref kctlref, struct sockaddr_ctl *sac, @@ -108,12 +107,13 @@ SYSCTL_NODE(_net, OID_AUTO, ipsec, CTLFLAG_RW | CTLFLAG_LOCKED, 0, "IPsec"); static int if_ipsec_verify_interface_creation = 0; SYSCTL_INT(_net_ipsec, OID_AUTO, verify_interface_creation, CTLFLAG_RW | CTLFLAG_LOCKED, &if_ipsec_verify_interface_creation, 0, ""); -#define IPSEC_IF_VERIFY(_e) if (unlikely(if_ipsec_verify_interface_creation)) { VERIFY(_e); } +#define IPSEC_IF_VERIFY(_e) if (__improbable(if_ipsec_verify_interface_creation)) { VERIFY(_e); } #define IPSEC_IF_DEFAULT_SLOT_SIZE 2048 #define IPSEC_IF_DEFAULT_RING_SIZE 64 #define IPSEC_IF_DEFAULT_TX_FSW_RING_SIZE 64 #define IPSEC_IF_DEFAULT_RX_FSW_RING_SIZE 128 +#define IPSEC_IF_DEFAULT_BUF_SEG_SIZE skmem_usr_buf_seg_size #define IPSEC_IF_MIN_RING_SIZE 16 #define IPSEC_IF_MAX_RING_SIZE 1024 @@ -183,8 +183,10 @@ struct ipsec_pcb { uuid_t ipsec_kpipe_uuid; void * ipsec_kpipe_rxring; void * ipsec_kpipe_txring; + kern_pbufpool_t ipsec_kpipe_pp; kern_nexus_t ipsec_netif_nexus; + kern_pbufpool_t ipsec_netif_pp; void * ipsec_netif_rxring; void * ipsec_netif_txring; uint64_t ipsec_netif_txring_size; @@ -719,7 +721,7 @@ ipsec_kpipe_sync_rx(kern_nexus_provider_t nxprov, kern_nexus_t nexus, // Allocate rx packet kern_packet_t rx_ph = 0; error = kern_pbufpool_alloc_nosleep(rx_pp, 1, &rx_ph); - if (unlikely(error != 0)) { + if (__improbable(error != 0)) { printf("ipsec_kpipe_sync_rx %s: failed to allocate packet\n", pcb->ipsec_ifp->if_xname); break; @@ -732,6 +734,7 @@ ipsec_kpipe_sync_rx(kern_nexus_provider_t nxprov, kern_nexus_t nexus, tx_slot = kern_channel_get_next_slot(tx_ring, tx_slot, NULL); if (tx_ph == 0) { + kern_pbufpool_free(rx_pp, rx_ph); continue; } @@ -1151,7 +1154,7 @@ ipsec_netif_sync_rx(kern_nexus_provider_t nxprov, kern_nexus_t nexus, // Allocate rx packet kern_packet_t rx_ph = 0; errno_t error = kern_pbufpool_alloc_nosleep(rx_pp, 1, &rx_ph); - if (unlikely(error != 0)) { + if (__improbable(error != 0)) { STATS_INC(nifs, NETIF_STATS_NOMEM_PKT); STATS_INC(nifs, NETIF_STATS_DROPPED); lck_mtx_unlock(&pcb->ipsec_input_chain_lock); @@ -1370,7 +1373,7 @@ ipsec_netif_sync_rx(kern_nexus_provider_t nxprov, kern_nexus_t nexus, // Allocate rx packet kern_packet_t rx_ph = 0; error = kern_pbufpool_alloc_nosleep(rx_pp, 1, &rx_ph); - if (unlikely(error != 0)) { + if (__improbable(error != 0)) { STATS_INC(nifs, NETIF_STATS_NOMEM_PKT); STATS_INC(nifs, NETIF_STATS_DROPPED); break; @@ -1383,6 +1386,7 @@ ipsec_netif_sync_rx(kern_nexus_provider_t nxprov, kern_nexus_t nexus, tx_slot = kern_channel_get_next_slot(tx_ring, tx_slot, NULL); if (tx_ph == 0) { + kern_pbufpool_free(rx_pp, rx_ph); continue; } @@ -1570,10 +1574,11 @@ ipsec_nexus_ifattach(struct ipsec_pcb *pcb, errno_t err; nexus_controller_t controller = kern_nexus_shared_controller(); struct kern_nexus_net_init net_init; + struct kern_pbufpool_init pp_init; nexus_name_t provider_name; snprintf((char *)provider_name, sizeof(provider_name), - "com.apple.netif.ipsec%d", pcb->ipsec_unit); + "com.apple.netif.%s", pcb->ipsec_if_xname); struct kern_nexus_provider_init prov_init = { .nxpi_version = KERN_NEXUS_DOMAIN_PROVIDER_CURRENT_VERSION, @@ -1613,6 +1618,21 @@ ipsec_nexus_ifattach(struct ipsec_pcb *pcb, pcb->ipsec_netif_txring_size = ring_size; + bzero(&pp_init, sizeof (pp_init)); + pp_init.kbi_version = KERN_PBUFPOOL_CURRENT_VERSION; + pp_init.kbi_packets = pcb->ipsec_netif_ring_size * 2; + pp_init.kbi_bufsize = pcb->ipsec_slot_size; + pp_init.kbi_buf_seg_size = IPSEC_IF_DEFAULT_BUF_SEG_SIZE; + pp_init.kbi_max_frags = 1; + (void) snprintf((char *)pp_init.kbi_name, sizeof (pp_init.kbi_name), + "%s", provider_name); + + err = kern_pbufpool_create(&pp_init, &pp_init, &pcb->ipsec_netif_pp, NULL); + if (err != 0) { + printf("%s pbufbool create failed, error %d\n", __func__, err); + goto failed; + } + err = kern_nexus_controller_register_provider(controller, ipsec_nx_dom_prov, provider_name, @@ -1633,6 +1653,7 @@ ipsec_nexus_ifattach(struct ipsec_pcb *pcb, net_init.nxneti_eparams = init_params; net_init.nxneti_lladdr = NULL; net_init.nxneti_prepare = ipsec_netif_prepare; + net_init.nxneti_tx_pbufpool = pcb->ipsec_netif_pp; err = kern_nexus_controller_alloc_net_provider_instance(controller, pcb->ipsec_nx.if_provider, pcb, @@ -1653,6 +1674,10 @@ ipsec_nexus_ifattach(struct ipsec_pcb *pcb, if (nxa) { kern_nexus_attr_destroy(nxa); } + if (err && pcb->ipsec_netif_pp != NULL) { + kern_pbufpool_destroy(pcb->ipsec_netif_pp); + pcb->ipsec_netif_pp = NULL; + } return (err); } @@ -1683,8 +1708,9 @@ ipsec_detach_provider_and_instance(uuid_t provider, uuid_t instance) } static void -ipsec_nexus_detach(ipsec_nx_t nx) +ipsec_nexus_detach(struct ipsec_pcb *pcb) { + ipsec_nx_t nx = &pcb->ipsec_nx; nexus_controller_t controller = kern_nexus_shared_controller(); errno_t err; @@ -1713,6 +1739,11 @@ ipsec_nexus_detach(ipsec_nx_t nx) ipsec_detach_provider_and_instance(nx->ms_provider, nx->ms_instance); + if (pcb->ipsec_netif_pp != NULL) { + kern_pbufpool_destroy(pcb->ipsec_netif_pp); + pcb->ipsec_netif_pp = NULL; + + } memset(nx, 0, sizeof(*nx)); } @@ -1858,7 +1889,7 @@ ipsec_multistack_attach(struct ipsec_pcb *pcb) return (0); failed: - ipsec_nexus_detach(nx); + ipsec_nexus_detach(pcb); errno_t detach_error = 0; if ((detach_error = ifnet_detach(pcb->ipsec_ifp)) != 0) { @@ -2006,6 +2037,10 @@ ipsec_disable_channel(struct ipsec_pcb *pcb) } if (!result) { + if (pcb->ipsec_kpipe_pp != NULL) { + kern_pbufpool_destroy(pcb->ipsec_kpipe_pp); + pcb->ipsec_kpipe_pp = NULL; + } ipsec_unregister_kernel_pipe_nexus(); } @@ -2016,6 +2051,7 @@ static errno_t ipsec_enable_channel(struct ipsec_pcb *pcb, struct proc *proc) { struct kern_nexus_init init; + struct kern_pbufpool_init pp_init; errno_t result; result = ipsec_register_kernel_pipe_nexus(); @@ -2027,14 +2063,38 @@ ipsec_enable_channel(struct ipsec_pcb *pcb, struct proc *proc) lck_rw_lock_exclusive(&pcb->ipsec_pcb_lock); + /* ipsec driver doesn't support channels without a netif */ + if (!pcb->ipsec_use_netif) { + result = EOPNOTSUPP; + goto done; + } + if (pcb->ipsec_kpipe_enabled) { result = EEXIST; // return success instead? goto done; } + bzero(&pp_init, sizeof (pp_init)); + pp_init.kbi_version = KERN_PBUFPOOL_CURRENT_VERSION; + pp_init.kbi_packets = pcb->ipsec_netif_ring_size * 2; + pp_init.kbi_bufsize = pcb->ipsec_slot_size; + pp_init.kbi_buf_seg_size = IPSEC_IF_DEFAULT_BUF_SEG_SIZE; + pp_init.kbi_max_frags = 1; + pp_init.kbi_flags |= KBIF_QUANTUM; + (void) snprintf((char *)pp_init.kbi_name, sizeof (pp_init.kbi_name), + "com.apple.kpipe.%s", pcb->ipsec_if_xname); + + result = kern_pbufpool_create(&pp_init, &pp_init, &pcb->ipsec_kpipe_pp, + NULL); + if (result != 0) { + printf("%s pbufbool create failed, error %d\n", __func__, result); + goto done; + } + VERIFY(uuid_is_null(pcb->ipsec_kpipe_uuid)); bzero(&init, sizeof (init)); init.nxi_version = KERN_NEXUS_CURRENT_VERSION; + init.nxi_tx_pbufpool = pcb->ipsec_kpipe_pp; result = kern_nexus_controller_alloc_provider_instance(ipsec_ncd, ipsec_kpipe_uuid, pcb, &pcb->ipsec_kpipe_uuid, &init); if (result) { @@ -2058,6 +2118,10 @@ ipsec_enable_channel(struct ipsec_pcb *pcb, struct proc *proc) lck_rw_unlock_exclusive(&pcb->ipsec_pcb_lock); if (result) { + if (pcb->ipsec_kpipe_pp != NULL) { + kern_pbufpool_destroy(pcb->ipsec_kpipe_pp); + pcb->ipsec_kpipe_pp = NULL; + } ipsec_unregister_kernel_pipe_nexus(); } @@ -2460,10 +2524,14 @@ ipsec_ctl_disconnect(__unused kern_ctl_ref kctlref, if (!uuid_is_null(kpipe_uuid)) { if (kern_nexus_controller_free_provider_instance(ipsec_ncd, kpipe_uuid) == 0) { + if (pcb->ipsec_kpipe_pp != NULL) { + kern_pbufpool_destroy(pcb->ipsec_kpipe_pp); + pcb->ipsec_kpipe_pp = NULL; + } ipsec_unregister_kernel_pipe_nexus(); } } - ipsec_nexus_detach(&pcb->ipsec_nx); + ipsec_nexus_detach(pcb); /* Decrement refcnt to finish detaching and freeing */ ifnet_decr_iorefcnt(ifp); @@ -2475,6 +2543,10 @@ ipsec_ctl_disconnect(__unused kern_ctl_ref kctlref, #if IPSEC_NEXUS if (!uuid_is_null(kpipe_uuid)) { if (kern_nexus_controller_free_provider_instance(ipsec_ncd, kpipe_uuid) == 0) { + if (pcb->ipsec_kpipe_pp != NULL) { + kern_pbufpool_destroy(pcb->ipsec_kpipe_pp); + pcb->ipsec_kpipe_pp = NULL; + } ipsec_unregister_kernel_pipe_nexus(); } } @@ -2673,18 +2745,19 @@ ipsec_ctl_setopt(__unused kern_ctl_ref kctlref, result = EINVAL; break; } - if (!if_enable_netagent) { + if (!if_is_netagent_enabled()) { result = ENOTSUP; break; } + if (uuid_is_null(pcb->ipsec_nx.ms_agent)) { + result = ENOENT; + break; + } + if (*(int *)data) { - if (!uuid_is_null(pcb->ipsec_nx.ms_agent)) { if_add_netagent(pcb->ipsec_ifp, pcb->ipsec_nx.ms_agent); - } } else { - if (!uuid_is_null(pcb->ipsec_nx.ms_agent)) { if_delete_netagent(pcb->ipsec_ifp, pcb->ipsec_nx.ms_agent); - } } break; } @@ -2715,7 +2788,9 @@ ipsec_ctl_setopt(__unused kern_ctl_ref kctlref, result = EINVAL; break; } - pcb->ipsec_use_netif = true; + lck_rw_lock_exclusive(&pcb->ipsec_pcb_lock); + pcb->ipsec_use_netif = !!(*(int *)data); + lck_rw_unlock_exclusive(&pcb->ipsec_pcb_lock); break; } case IPSEC_OPT_SLOT_SIZE: { @@ -2855,6 +2930,38 @@ ipsec_ctl_getopt(__unused kern_ctl_ref kctlref, } #if IPSEC_NEXUS + + case IPSEC_OPT_ENABLE_CHANNEL: { + if (*len != sizeof(int)) { + result = EMSGSIZE; + } else { + lck_rw_lock_shared(&pcb->ipsec_pcb_lock); + *(int *)data = pcb->ipsec_kpipe_enabled; + lck_rw_unlock_shared(&pcb->ipsec_pcb_lock); + } + break; + } + + case IPSEC_OPT_ENABLE_FLOWSWITCH: { + if (*len != sizeof(int)) { + result = EMSGSIZE; + } else { + *(int *)data = if_check_netagent(pcb->ipsec_ifp, pcb->ipsec_nx.ms_agent); + } + break; + } + + case IPSEC_OPT_ENABLE_NETIF: { + if (*len != sizeof(int)) { + result = EMSGSIZE; + } else { + lck_rw_lock_shared(&pcb->ipsec_pcb_lock); + *(int *)data = !!pcb->ipsec_use_netif; + lck_rw_unlock_shared(&pcb->ipsec_pcb_lock); + } + break; + } + case IPSEC_OPT_GET_CHANNEL_UUID: { lck_rw_lock_shared(&pcb->ipsec_pcb_lock); if (uuid_is_null(pcb->ipsec_kpipe_uuid)) { @@ -3190,12 +3297,12 @@ ipsec_ioctl(ifnet_t interface, u_long command, void *data) { - struct ipsec_pcb *pcb = ifnet_softc(interface); errno_t result = 0; switch(command) { case SIOCSIFMTU: { #if IPSEC_NEXUS + struct ipsec_pcb *pcb = ifnet_softc(interface); if (pcb->ipsec_use_netif) { // Make sure we can fit packets in the channel buffers if (((uint64_t)((struct ifreq*)data)->ifr_mtu) > pcb->ipsec_slot_size) { @@ -3253,14 +3360,15 @@ ipsec_proto_input(ifnet_t interface, af = AF_INET6; } bpf_tap_in(interface, DLT_NULL, m, &af, sizeof(af)); + pktap_input(interface, protocol, m, NULL); } - pktap_input(interface, protocol, m, NULL); + int32_t pktlen = m->m_pkthdr.len; if (proto_input(protocol, m) != 0) { ifnet_stat_increment_in(interface, 0, 0, 1); m_freem(m); } else { - ifnet_stat_increment_in(interface, 1, m->m_pkthdr.len, 0); + ifnet_stat_increment_in(interface, 1, pktlen, 0); } return 0; @@ -3304,9 +3412,9 @@ errno_t ipsec_inject_inbound_packet(ifnet_t interface, mbuf_t packet) { +#if IPSEC_NEXUS struct ipsec_pcb *pcb = ifnet_softc(interface); -#if IPSEC_NEXUS if (pcb->ipsec_use_netif) { lck_rw_lock_shared(&pcb->ipsec_pcb_lock); diff --git a/bsd/net/if_ports_used.c b/bsd/net/if_ports_used.c new file mode 100644 index 000000000..f5f7f9c11 --- /dev/null +++ b/bsd/net/if_ports_used.c @@ -0,0 +1,675 @@ +/* + * Copyright (c) 2017-2018 Apple Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include + +#include + + +#include + +#include + +extern bool IOPMCopySleepWakeUUIDKey(char *buffer, size_t buf_len); + +SYSCTL_DECL(_net_link_generic_system); + +SYSCTL_NODE(_net_link_generic_system, OID_AUTO, port_used, + CTLFLAG_RW | CTLFLAG_LOCKED, 0, "if port used"); + +static uuid_t current_wakeuuid; +SYSCTL_OPAQUE(_net_link_generic_system_port_used, OID_AUTO, current_wakeuuid, + CTLFLAG_RD|CTLFLAG_LOCKED, + current_wakeuuid, sizeof(uuid_t), "S,uuid_t", ""); + +static int sysctl_net_port_info_list SYSCTL_HANDLER_ARGS; +SYSCTL_PROC(_net_link_generic_system_port_used, OID_AUTO, list, + CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED, 0, 0, + sysctl_net_port_info_list, "S,xnpigen", ""); + +static int use_test_wakeuuid = 0; +static uuid_t test_wakeuuid; + +#if (DEVELOPMENT || DEBUG) +SYSCTL_INT(_net_link_generic_system_port_used, OID_AUTO, use_test_wakeuuid, + CTLFLAG_RW | CTLFLAG_LOCKED, + &use_test_wakeuuid, 0, ""); + +int sysctl_new_test_wakeuuid SYSCTL_HANDLER_ARGS; +SYSCTL_PROC(_net_link_generic_system_port_used, OID_AUTO, new_test_wakeuuid, + CTLTYPE_STRUCT | CTLFLAG_RW | CTLFLAG_LOCKED, 0, 0, + sysctl_new_test_wakeuuid, "S,uuid_t", ""); + +int sysctl_clear_test_wakeuuid SYSCTL_HANDLER_ARGS; +SYSCTL_PROC(_net_link_generic_system_port_used, OID_AUTO, clear_test_wakeuuid, + CTLTYPE_STRUCT | CTLFLAG_RW | CTLFLAG_LOCKED, 0, 0, + sysctl_clear_test_wakeuuid, "S,uuid_t", ""); + +SYSCTL_OPAQUE(_net_link_generic_system_port_used, OID_AUTO, test_wakeuuid, + CTLFLAG_RD|CTLFLAG_LOCKED, + test_wakeuuid, sizeof(uuid_t), "S,uuid_t", ""); +#endif /* (DEVELOPMENT || DEBUG) */ + +static int sysctl_get_ports_used SYSCTL_HANDLER_ARGS; +SYSCTL_NODE(_net_link_generic_system, OID_AUTO, get_ports_used, + CTLFLAG_RD | CTLFLAG_LOCKED, + sysctl_get_ports_used, ""); + +static uint32_t net_port_entry_count = 0; +SYSCTL_UINT(_net_link_generic_system_port_used, OID_AUTO, entry_count, + CTLFLAG_RW | CTLFLAG_LOCKED, + &net_port_entry_count, 0, ""); + +static uint32_t net_port_entry_gen = 0; +SYSCTL_UINT(_net_link_generic_system_port_used, OID_AUTO, entry_gen, + CTLFLAG_RW | CTLFLAG_LOCKED, + &net_port_entry_gen, 0, ""); + +static int if_ports_used_verbose = 0; +SYSCTL_INT(_net_link_generic_system_port_used, OID_AUTO, verbose, + CTLFLAG_RW | CTLFLAG_LOCKED, + &if_ports_used_verbose, 0, ""); + +static unsigned long wakeuuid_not_set_count = 0; +SYSCTL_ULONG(_net_link_generic_system_port_used, OID_AUTO, + wakeuuid_not_set_count, CTLFLAG_RD | CTLFLAG_LOCKED, + &wakeuuid_not_set_count, 0); + +struct timeval wakeuuid_not_set_last_time; +int sysctl_wakeuuid_not_set_last_time SYSCTL_HANDLER_ARGS; +static SYSCTL_PROC(_net_link_generic_system_port_used, OID_AUTO, + wakeuuid_not_set_last_time, CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_LOCKED, + 0, 0, sysctl_wakeuuid_not_set_last_time, "S,timeval", ""); + +char wakeuuid_not_set_last_if [IFXNAMSIZ]; +int sysctl_wakeuuid_not_set_last_if SYSCTL_HANDLER_ARGS; +static SYSCTL_PROC(_net_link_generic_system_port_used, OID_AUTO, + wakeuuid_not_set_last_if, CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_LOCKED, + 0, 0, sysctl_wakeuuid_not_set_last_if, "A", ""); + + +static int if_ports_used_inited = 0; + +decl_lck_mtx_data(static, net_port_entry_head_lock); +static lck_grp_t *net_port_entry_head_lock_group; + +struct net_port_entry { + SLIST_ENTRY(net_port_entry) npe_next; + struct net_port_info npe_npi; +}; + +static struct zone *net_port_entry_zone = NULL; + +#define NET_PORT_ENTRY_ZONE_MAX 128 +#define NET_PORT_ENTRY_ZONE_NAME "net_port_entry" + +static SLIST_HEAD(net_port_entry_list, net_port_entry) net_port_entry_list = + SLIST_HEAD_INITIALIZER(&net_port_entry_list); + +struct timeval wakeuiid_last_check; + +void +if_ports_used_init(void) +{ + if (if_ports_used_inited == 0) { + lck_grp_attr_t *lck_grp_attributes = NULL; + lck_attr_t *lck_attributes = NULL; + + timerclear(&wakeuiid_last_check); + uuid_clear(current_wakeuuid); + uuid_clear(test_wakeuuid); + + lck_grp_attributes = lck_grp_attr_alloc_init(); + net_port_entry_head_lock_group = lck_grp_alloc_init( + "net port entry lock", lck_grp_attributes); + + lck_attributes = lck_attr_alloc_init(); + if (lck_attributes == NULL) { + panic("%s: lck_attr_alloc_init() failed", __func__); + } + lck_mtx_init(&net_port_entry_head_lock, + net_port_entry_head_lock_group, + lck_attributes); + + net_port_entry_count = 0; + net_port_entry_zone = zinit(sizeof(struct net_port_entry), + NET_PORT_ENTRY_ZONE_MAX * sizeof(struct net_port_entry), + 0, NET_PORT_ENTRY_ZONE_NAME); + if (net_port_entry_zone == NULL) { + panic("%s: zinit(%s) failed", __func__, + NET_PORT_ENTRY_ZONE_NAME); + } + zone_change(net_port_entry_zone, Z_EXPAND, TRUE); + zone_change(net_port_entry_zone, Z_CALLERACCT, FALSE); + + if_ports_used_inited = 1; + + lck_attr_free(lck_attributes); + lck_grp_attr_free(lck_grp_attributes); + } +} + +static void +net_port_entry_list_clear(void) +{ + struct net_port_entry *npe; + + LCK_MTX_ASSERT(&net_port_entry_head_lock, LCK_MTX_ASSERT_OWNED); + + while ((npe = SLIST_FIRST(&net_port_entry_list)) != NULL) { + SLIST_REMOVE_HEAD(&net_port_entry_list, npe_next); + + zfree(net_port_entry_zone, npe); + } + net_port_entry_count = 0; + net_port_entry_gen++; +} + +static bool +get_test_wake_uuid(uuid_t wakeuuid) +{ + if (__improbable(use_test_wakeuuid)) { + if (!uuid_is_null(test_wakeuuid)) { + if (wakeuuid != NULL) { + uuid_copy(wakeuuid, test_wakeuuid); + } + return (true); + } else { + return (false); + } + } else { + return (false); + } +} + +static bool +is_wakeuuid_set(void) +{ + /* + * IOPMCopySleepWakeUUIDKey() tells if SleepWakeUUID is currently set + * That means we are currently in a sleep/wake cycle + */ + return (get_test_wake_uuid(NULL) || IOPMCopySleepWakeUUIDKey(NULL, 0)); +} + +void +if_ports_used_update_wakeuuid(struct ifnet *ifp) +{ + uuid_t wakeuuid; + bool wakeuuid_is_set = false; + bool updated = false; + + if (__improbable(use_test_wakeuuid)) { + wakeuuid_is_set = get_test_wake_uuid(wakeuuid); + } else { + uuid_string_t wakeuuid_str; + + wakeuuid_is_set = IOPMCopySleepWakeUUIDKey(wakeuuid_str, + sizeof(wakeuuid_str)); + if (wakeuuid_is_set) { + uuid_parse(wakeuuid_str, wakeuuid); + } + } + + if (!wakeuuid_is_set) { + if (if_ports_used_verbose > 0) { + os_log_info(OS_LOG_DEFAULT, + "%s: SleepWakeUUID not set, " + "don't update the port list for %s\n", + __func__, ifp != NULL ? if_name(ifp) : ""); + } + wakeuuid_not_set_count += 1; + if (ifp != NULL) { + microtime(&wakeuuid_not_set_last_time); + strlcpy(wakeuuid_not_set_last_if, if_name(ifp), + sizeof(wakeuuid_not_set_last_if)); + } + return; + } + + lck_mtx_lock(&net_port_entry_head_lock); + if (uuid_compare(wakeuuid, current_wakeuuid) != 0) { + net_port_entry_list_clear(); + uuid_copy(current_wakeuuid, wakeuuid); + updated = true; + } + /* + * Record the time last checked + */ + microuptime(&wakeuiid_last_check); + lck_mtx_unlock(&net_port_entry_head_lock); + + if (updated && if_ports_used_verbose > 0) { + uuid_string_t uuid_str; + + uuid_unparse(current_wakeuuid, uuid_str); + log(LOG_ERR, "%s: current wakeuuid %s\n", + __func__, + uuid_str); + } +} + +static bool +net_port_info_equal(const struct net_port_info *x, + const struct net_port_info *y) +{ + ASSERT(x != NULL && y != NULL); + + if (x->npi_if_index == y->npi_if_index && + x->npi_local_port == y->npi_local_port && + x->npi_foreign_port == y->npi_foreign_port && + x->npi_owner_pid == y->npi_owner_pid && + x->npi_effective_pid == y->npi_effective_pid && + x->npi_flags == y->npi_flags && + memcmp(&x->npi_local_addr_, &y->npi_local_addr_, + sizeof(union in_addr_4_6)) == 0 && + memcmp(&x->npi_foreign_addr_, &y->npi_foreign_addr_, + sizeof(union in_addr_4_6)) == 0) { + return (true); + } + return (false); +} + +static bool +net_port_info_has_entry(const struct net_port_info *npi) +{ + struct net_port_entry *npe; + + LCK_MTX_ASSERT(&net_port_entry_head_lock, LCK_MTX_ASSERT_OWNED); + + SLIST_FOREACH(npe, &net_port_entry_list, npe_next) { + if (net_port_info_equal(&npe->npe_npi, npi)) { + return (true); + } + } + + return (false); +} + +static bool +net_port_info_add_entry(const struct net_port_info *npi) +{ + struct net_port_entry *npe = NULL; + uint32_t num = 0; + bool entry_added = false; + + ASSERT(npi != NULL); + + if (__improbable(is_wakeuuid_set() == false)) { + if (if_ports_used_verbose > 0) { + log(LOG_ERR, "%s: wakeuuid not set %u not adding " + "port: %u flags: 0x%xif: %u pid: %u epid %u\n", + __func__, + ntohs(npi->npi_local_port), + npi->npi_flags, + npi->npi_if_index, + npi->npi_owner_pid, + npi->npi_effective_pid); + } + return (0); + } + + npe = zalloc(net_port_entry_zone); + if (__improbable(npe == NULL)) { + log(LOG_ERR, "%s: zalloc() failed for " + "port: %u flags: 0x%x if: %u pid: %u epid %u\n", + __func__, + ntohs(npi->npi_local_port), + npi->npi_flags, + npi->npi_if_index, + npi->npi_owner_pid, + npi->npi_effective_pid); + return (0); + } + bzero(npe, sizeof(struct net_port_entry)); + + memcpy(&npe->npe_npi, npi, sizeof(npe->npe_npi)); + + lck_mtx_lock(&net_port_entry_head_lock); + + if (net_port_info_has_entry(npi) == false) { + SLIST_INSERT_HEAD(&net_port_entry_list, npe, npe_next); + num = net_port_entry_count++; + entry_added = true; + + if (if_ports_used_verbose > 0) { + log(LOG_ERR, "%s: num %u for " + "port: %u flags: 0x%x if: %u pid: %u epid %u\n", + __func__, + num, + ntohs(npi->npi_local_port), + npi->npi_flags, + npi->npi_if_index, + npi->npi_owner_pid, + npi->npi_effective_pid); + } + } else { + if (if_ports_used_verbose > 0) { + log(LOG_ERR, "%s: entry already added " + "port: %u flags: 0x%x if: %u pid: %u epid %u\n", + __func__, + ntohs(npi->npi_local_port), + npi->npi_flags, + npi->npi_if_index, + npi->npi_owner_pid, + npi->npi_effective_pid); + } + } + + lck_mtx_unlock(&net_port_entry_head_lock); + + if (entry_added == false) { + zfree(net_port_entry_zone, npe); + npe = NULL; + } + return (entry_added); +} + +#if (DEVELOPMENT || DEBUG) +int +sysctl_new_test_wakeuuid SYSCTL_HANDLER_ARGS +{ +#pragma unused(oidp, arg1, arg2) + int error = 0; + + if (kauth_cred_issuser(kauth_cred_get()) == 0) { + return (EPERM); + } + if (req->oldptr == USER_ADDR_NULL) { + req->oldidx = sizeof(uuid_t); + return (0); + } + if (req->newptr != USER_ADDR_NULL) { + uuid_generate(test_wakeuuid); + } + error = SYSCTL_OUT(req, test_wakeuuid, + MIN(sizeof(uuid_t), req->oldlen)); + + return (error); +} + +int +sysctl_clear_test_wakeuuid SYSCTL_HANDLER_ARGS +{ +#pragma unused(oidp, arg1, arg2) + int error = 0; + + if (kauth_cred_issuser(kauth_cred_get()) == 0) { + return (EPERM); + } + if (req->oldptr == USER_ADDR_NULL) { + req->oldidx = sizeof(uuid_t); + return (0); + } + if (req->newptr != USER_ADDR_NULL) { + uuid_clear(test_wakeuuid); + } + error = SYSCTL_OUT(req, test_wakeuuid, + MIN(sizeof(uuid_t), req->oldlen)); + + return (error); +} + +#endif /* (DEVELOPMENT || DEBUG) */ + +int +sysctl_wakeuuid_not_set_last_time SYSCTL_HANDLER_ARGS +{ +#pragma unused(oidp, arg1, arg2) + + if (proc_is64bit(req->p)) { + struct user64_timeval tv; + + tv.tv_sec = wakeuuid_not_set_last_time.tv_sec; + tv.tv_usec = wakeuuid_not_set_last_time.tv_usec; + return SYSCTL_OUT(req, &tv, sizeof(tv)); + } else { + struct user32_timeval tv; + + tv.tv_sec = wakeuuid_not_set_last_time.tv_sec; + tv.tv_usec = wakeuuid_not_set_last_time.tv_usec; + return SYSCTL_OUT(req, &tv, sizeof(tv)); + } +} + +int +sysctl_wakeuuid_not_set_last_if SYSCTL_HANDLER_ARGS +{ +#pragma unused(oidp, arg1, arg2) + + return SYSCTL_OUT(req, &wakeuuid_not_set_last_if, + strlen(wakeuuid_not_set_last_if) + 1); +} + +static int +sysctl_net_port_info_list SYSCTL_HANDLER_ARGS +{ +#pragma unused(oidp, arg1, arg2) + int error = 0; + struct xnpigen xnpigen; + struct net_port_entry *npe; + + if ((error = priv_check_cred(kauth_cred_get(), + PRIV_NET_PRIVILEGED_NETWORK_STATISTICS, 0)) != 0) { + return (EPERM); + } + lck_mtx_lock(&net_port_entry_head_lock); + + if (req->oldptr == USER_ADDR_NULL) { + /* Add a 25 % cushion */ + uint32_t cnt = net_port_entry_count; + cnt += cnt >> 4; + req->oldidx = sizeof(struct xnpigen) + + cnt * sizeof(struct net_port_info); + goto done; + } + + memset(&xnpigen, 0, sizeof(struct xnpigen)); + xnpigen.xng_len = sizeof(struct xnpigen); + xnpigen.xng_gen = net_port_entry_gen; + uuid_copy(xnpigen.xng_wakeuuid, current_wakeuuid); + xnpigen.xng_npi_count = net_port_entry_count; + xnpigen.xng_npi_size = sizeof(struct net_port_info); + error = SYSCTL_OUT(req, &xnpigen, sizeof (xnpigen)); + if (error != 0) { + printf("%s: SYSCTL_OUT(xnpigen) error %d\n", + __func__, error); + goto done; + } + + SLIST_FOREACH(npe, &net_port_entry_list, npe_next) { + error = SYSCTL_OUT(req, &npe->npe_npi, + sizeof(struct net_port_info)); + if (error != 0) { + printf("%s: SYSCTL_OUT(npi) error %d\n", + __func__, error); + goto done; + } + } +done: + lck_mtx_unlock(&net_port_entry_head_lock); + + return (error); +} + +/* + * Mirror the arguments of ifnet_get_local_ports_extended() + * ifindex + * protocol + * flags + */ +static int +sysctl_get_ports_used SYSCTL_HANDLER_ARGS +{ +#pragma unused(oidp) + int *name = (int *)arg1; + int namelen = arg2; + int error = 0; + int idx; + protocol_family_t protocol; + u_int32_t flags; + ifnet_t ifp = NULL; + u_int8_t *bitfield = NULL; + + if (req->newptr != USER_ADDR_NULL) { + error = EPERM; + goto done; + } + /* + * 3 is the required number of parameters: ifindex, protocol and flags + */ + if (namelen != 3) { + error = ENOENT; + goto done; + } + + if (req->oldptr == USER_ADDR_NULL) { + req->oldidx = bitstr_size(IP_PORTRANGE_SIZE); + goto done; + } + if (req->oldlen < bitstr_size(IP_PORTRANGE_SIZE)) { + error = ENOMEM; + goto done; + } + + idx = name[0]; + protocol = name[1]; + flags = name[2]; + + ifnet_head_lock_shared(); + if (!IF_INDEX_IN_RANGE(idx)) { + ifnet_head_done(); + error = ENOENT; + goto done; + } + ifp = ifindex2ifnet[idx]; + ifnet_head_done(); + + bitfield = _MALLOC(bitstr_size(IP_PORTRANGE_SIZE), M_TEMP, + M_WAITOK | M_ZERO); + if (bitfield == NULL) { + error = ENOMEM; + goto done; + } + error = ifnet_get_local_ports_extended(ifp, protocol, flags, bitfield); + if (error != 0) { + printf("%s: ifnet_get_local_ports_extended() error %d\n", + __func__, error); + goto done; + } + error = SYSCTL_OUT(req, bitfield, bitstr_size(IP_PORTRANGE_SIZE)); +done: + if (bitfield != NULL) + _FREE(bitfield, M_TEMP); + return (error); +} + +__private_extern__ void +if_ports_used_add_inpcb(const uint32_t ifindex, const struct inpcb *inp) +{ + struct net_port_info npi; + struct socket *so = inp->inp_socket; + + bzero(&npi, sizeof(struct net_port_info)); + + npi.npi_if_index = ifindex; + + npi.npi_flags |= NPIF_SOCKET; + + npi.npi_timestamp.tv_sec = wakeuiid_last_check.tv_sec; + npi.npi_timestamp.tv_usec = wakeuiid_last_check.tv_usec; + + if (SOCK_PROTO(so) == IPPROTO_TCP) { + npi.npi_flags |= NPIF_TCP; + } else if (SOCK_PROTO(so) == IPPROTO_UDP) { + npi.npi_flags |= NPIF_UDP; + } else { + panic("%s: unexpected protocol %u for inp %p\n", __func__, + SOCK_PROTO(inp->inp_socket), inp); + } + + uuid_copy(npi.npi_flow_uuid, inp->necp_client_uuid); + + npi.npi_local_port = inp->inp_lport; + npi.npi_foreign_port = inp->inp_fport; + + if (inp->inp_vflag & INP_IPV4) { + npi.npi_flags |= NPIF_IPV4; + npi.npi_local_addr_in = inp->inp_laddr; + npi.npi_foreign_addr_in = inp->inp_faddr; + } else { + npi.npi_flags |= NPIF_IPV6; + memcpy(&npi.npi_local_addr_in6, + &inp->in6p_laddr, sizeof (struct in6_addr)); + memcpy(&npi.npi_foreign_addr_in6, + &inp->in6p_faddr, sizeof (struct in6_addr)); + } + + npi.npi_owner_pid = so->last_pid; + + if (so->last_pid != 0) { + proc_name(so->last_pid, npi.npi_owner_pname, + sizeof(npi.npi_owner_pname)); + } + + if (so->so_flags & SOF_DELEGATED) { + npi.npi_flags |= NPIF_DELEGATED; + npi.npi_effective_pid = so->e_pid; + if (so->e_pid != 0) { + proc_name(so->e_pid, npi.npi_effective_pname, + sizeof(npi.npi_effective_pname)); + } + } else { + npi.npi_effective_pid = so->last_pid; + if (so->last_pid != 0) { + strlcpy(npi.npi_effective_pname, npi.npi_owner_pname, + sizeof(npi.npi_effective_pname)); + } + } + + (void) net_port_info_add_entry(&npi); +} + diff --git a/bsd/net/if_ports_used.h b/bsd/net/if_ports_used.h new file mode 100644 index 000000000..dc11a1052 --- /dev/null +++ b/bsd/net/if_ports_used.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2017-2018 Apple Inc. All rights reserved. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ + */ + + +#ifndef _NET_IF_PORT_USED_H_ +#define _NET_IF_PORT_USED_H_ + +#ifdef PRIVATE + +#include +#include +#include +#include +#include +#include +#include + +#define IP_PORTRANGE_SIZE 65536 + +/* + * The sysctl "net.link.generic.system.port_used.list" returns: + * - one "struct xnpigen" as a preamble + * - zero or more "struct net_port_info" according to xng_npi_count + * + * The list may contain information several interfaces if several drivers + * queried the list of port to offload + * + * The same local port may have more than one "struct net_port_info" on + * a given interface, for example when a local server has mutiple clients + * connections + */ + +struct xnpigen { + uint32_t xng_len; /* length of this data structure */ + uint32_t xng_gen; /* how many times the list was built */ + uint32_t xng_npi_count; /* number of net_port_info following */ + uint32_t xng_npi_size; /* number of struct net_port_info */ + uuid_t xng_wakeuuid; /* WakeUUID when list was built */ +}; + +union in_addr_4_6 { + struct in_addr _in_a_4; + struct in6_addr _in_a_6; +}; + +#define NPIF_IPV4 0x00000001 +#define NPIF_IPV6 0x00000002 +#define NPIF_TCP 0x00000004 +#define NPIF_UDP 0x00000008 +#define NPIF_DELEGATED 0x00000010 +#define NPIF_SOCKET 0x00000020 +#define NPIF_CHANNEL 0x00000040 + +struct net_port_info { + uint16_t npi_if_index; + uint16_t npi_flags; + struct timeval32 npi_timestamp; /* when passed to driver */ + uuid_t npi_flow_uuid; + in_port_t npi_local_port; /* network byte order */ + in_port_t npi_foreign_port; /* network byte order */ + union in_addr_4_6 npi_local_addr_; + union in_addr_4_6 npi_foreign_addr_; + pid_t npi_owner_pid; + pid_t npi_effective_pid; + char npi_owner_pname[MAXCOMLEN+1]; + char npi_effective_pname[MAXCOMLEN+1]; +}; + +#define npi_local_addr_in npi_local_addr_._in_a_4 +#define npi_foreign_addr_in npi_foreign_addr_._in_a_4 + +#define npi_local_addr_in6 npi_local_addr_._in_a_6 +#define npi_foreign_addr_in6 npi_foreign_addr_._in_a_6 + +#ifdef XNU_KERNEL_PRIVATE + +void if_ports_used_init(void); + +void if_ports_used_update_wakeuuid(struct ifnet *); + +struct inpcb; +void if_ports_used_add_inpcb(const uint32_t ifindex, const struct inpcb *inp); + + +#endif /* XNU_KERNEL_PRIVATE */ +#endif /* PRIVATE */ + +#endif /* _NET_IF_PORT_USED_H_ */ diff --git a/bsd/net/if_stf.c b/bsd/net/if_stf.c index ac4950dd1..c4fce0074 100644 --- a/bsd/net/if_stf.c +++ b/bsd/net/if_stf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2017 Apple Inc. All rights reserved. + * Copyright (c) 2000-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -526,10 +526,14 @@ stf_pre_output( struct ip6_hdr *ip6; struct in6_ifaddr *ia6; struct sockaddr_in *dst4; - struct ip_out_args ipoa = - { IFSCOPE_NONE, { 0 }, IPOAF_SELECT_SRCIF, 0, - SO_TC_UNSPEC, _NET_SERVICE_TYPE_UNSPEC }; - errno_t result = 0; + struct ip_out_args ipoa; + errno_t result = 0; + + bzero(&ipoa, sizeof(ipoa)); + ipoa.ipoa_boundif = IFSCOPE_NONE; + ipoa.ipoa_flags = IPOAF_SELECT_SRCIF; + ipoa.ipoa_sotc = SO_TC_UNSPEC; + ipoa.ipoa_netsvctype = _NET_SERVICE_TYPE_UNSPEC; sc = ifnet_softc(ifp); dst6 = (const struct sockaddr_in6 *)(const void *)dst; diff --git a/bsd/net/if_utun.c b/bsd/net/if_utun.c index ffaa1124c..ac64bab88 100644 --- a/bsd/net/if_utun.c +++ b/bsd/net/if_utun.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2017 Apple Inc. All rights reserved. + * Copyright (c) 2008-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -57,8 +57,6 @@ This kernel control will register an interface for every client that connects. #define UTUN_NEXUS 0 -extern unsigned int if_enable_netagent; - #if UTUN_NEXUS static nexus_controller_t utun_ncd; static int utun_ncd_refcount; @@ -103,8 +101,10 @@ struct utun_pcb { uuid_t utun_kpipe_uuid; void * utun_kpipe_rxring; void * utun_kpipe_txring; + kern_pbufpool_t utun_kpipe_pp; kern_nexus_t utun_netif_nexus; + kern_pbufpool_t utun_netif_pp; void * utun_netif_rxring; void * utun_netif_txring; uint64_t utun_netif_txring_size; @@ -163,6 +163,7 @@ static errno_t utun_pkt_input(struct utun_pcb *pcb, mbuf_t m); #define UTUN_IF_DEFAULT_RING_SIZE 64 #define UTUN_IF_DEFAULT_TX_FSW_RING_SIZE 64 #define UTUN_IF_DEFAULT_RX_FSW_RING_SIZE 128 +#define UTUN_IF_DEFAULT_BUF_SEG_SIZE skmem_usr_buf_seg_size #define UTUN_IF_HEADROOM_SIZE 32 #define UTUN_IF_MIN_RING_SIZE 16 @@ -588,7 +589,7 @@ utun_netif_sync_rx(kern_nexus_provider_t nxprov, kern_nexus_t nexus, // Allocate rx packet kern_packet_t rx_ph = 0; errno_t error = kern_pbufpool_alloc_nosleep(rx_pp, 1, &rx_ph); - if (unlikely(error != 0)) { + if (__improbable(error != 0)) { STATS_INC(nifs, NETIF_STATS_NOMEM_PKT); STATS_INC(nifs, NETIF_STATS_DROPPED); lck_mtx_unlock(&pcb->utun_input_chain_lock); @@ -710,8 +711,11 @@ utun_netif_sync_rx(kern_nexus_provider_t nxprov, kern_nexus_t nexus, continue; } + /* XXX We could try this alloc before advancing the slot to avoid + * dropping the packet on failure to allocate. + */ errno_t error = kern_pbufpool_alloc_nosleep(rx_pp, 1, &rx_ph); - if (unlikely(error != 0)) { + if (__improbable(error != 0)) { STATS_INC(nifs, NETIF_STATS_NOMEM_PKT); STATS_INC(nifs, NETIF_STATS_DROPPED); break; @@ -809,10 +813,11 @@ utun_nexus_ifattach(struct utun_pcb *pcb, errno_t err; nexus_controller_t controller = kern_nexus_shared_controller(); struct kern_nexus_net_init net_init; + struct kern_pbufpool_init pp_init; nexus_name_t provider_name; snprintf((char *)provider_name, sizeof(provider_name), - "com.apple.netif.utun%d", pcb->utun_unit); + "com.apple.netif.%s", pcb->utun_if_xname); struct kern_nexus_provider_init prov_init = { .nxpi_version = KERN_NEXUS_DOMAIN_PROVIDER_CURRENT_VERSION, @@ -851,6 +856,21 @@ utun_nexus_ifattach(struct utun_pcb *pcb, pcb->utun_netif_txring_size = ring_size; + bzero(&pp_init, sizeof (pp_init)); + pp_init.kbi_version = KERN_PBUFPOOL_CURRENT_VERSION; + pp_init.kbi_packets = pcb->utun_netif_ring_size * 2; + pp_init.kbi_bufsize = pcb->utun_slot_size; + pp_init.kbi_buf_seg_size = UTUN_IF_DEFAULT_BUF_SEG_SIZE; + pp_init.kbi_max_frags = 1; + (void) snprintf((char *)pp_init.kbi_name, sizeof (pp_init.kbi_name), + "%s", provider_name); + + err = kern_pbufpool_create(&pp_init, &pp_init, &pcb->utun_netif_pp, NULL); + if (err != 0) { + printf("%s pbufbool create failed, error %d\n", __func__, err); + goto failed; + } + err = kern_nexus_controller_register_provider(controller, utun_nx_dom_prov, provider_name, @@ -870,6 +890,7 @@ utun_nexus_ifattach(struct utun_pcb *pcb, net_init.nxneti_eparams = init_params; net_init.nxneti_lladdr = NULL; net_init.nxneti_prepare = utun_netif_prepare; + net_init.nxneti_tx_pbufpool = pcb->utun_netif_pp; err = kern_nexus_controller_alloc_net_provider_instance(controller, pcb->utun_nx.if_provider, pcb, @@ -889,6 +910,10 @@ utun_nexus_ifattach(struct utun_pcb *pcb, if (nxa) { kern_nexus_attr_destroy(nxa); } + if (err && pcb->utun_netif_pp != NULL) { + kern_pbufpool_destroy(pcb->utun_netif_pp); + pcb->utun_netif_pp = NULL; + } return (err); } @@ -919,8 +944,9 @@ utun_detach_provider_and_instance(uuid_t provider, uuid_t instance) } static void -utun_nexus_detach(utun_nx_t nx) +utun_nexus_detach(struct utun_pcb *pcb) { + utun_nx_t nx = &pcb->utun_nx; nexus_controller_t controller = kern_nexus_shared_controller(); errno_t err; @@ -949,6 +975,11 @@ utun_nexus_detach(utun_nx_t nx) utun_detach_provider_and_instance(nx->ms_provider, nx->ms_instance); + if (pcb->utun_netif_pp != NULL) { + kern_pbufpool_destroy(pcb->utun_netif_pp); + pcb->utun_netif_pp = NULL; + + } memset(nx, 0, sizeof(*nx)); } @@ -1090,7 +1121,7 @@ utun_multistack_attach(struct utun_pcb *pcb) return (0); failed: - utun_nexus_detach(nx); + utun_nexus_detach(pcb); errno_t detach_error = 0; if ((detach_error = ifnet_detach(pcb->utun_ifp)) != 0) { @@ -1236,6 +1267,10 @@ utun_disable_channel(struct utun_pcb *pcb) } if (!result) { + if (pcb->utun_kpipe_pp != NULL) { + kern_pbufpool_destroy(pcb->utun_kpipe_pp); + pcb->utun_kpipe_pp = NULL; + } utun_unregister_kernel_pipe_nexus(); } @@ -1246,6 +1281,7 @@ static errno_t utun_enable_channel(struct utun_pcb *pcb, struct proc *proc) { struct kern_nexus_init init; + struct kern_pbufpool_init pp_init; errno_t result; result = utun_register_kernel_pipe_nexus(); @@ -1271,9 +1307,27 @@ utun_enable_channel(struct utun_pcb *pcb, struct proc *proc) goto done; } + bzero(&pp_init, sizeof (pp_init)); + pp_init.kbi_version = KERN_PBUFPOOL_CURRENT_VERSION; + pp_init.kbi_packets = pcb->utun_netif_ring_size * 2; + pp_init.kbi_bufsize = pcb->utun_slot_size; + pp_init.kbi_buf_seg_size = UTUN_IF_DEFAULT_BUF_SEG_SIZE; + pp_init.kbi_max_frags = 1; + pp_init.kbi_flags |= KBIF_QUANTUM; + (void) snprintf((char *)pp_init.kbi_name, sizeof (pp_init.kbi_name), + "com.apple.kpipe.%s", pcb->utun_if_xname); + + result = kern_pbufpool_create(&pp_init, &pp_init, &pcb->utun_kpipe_pp, + NULL); + if (result != 0) { + printf("%s pbufbool create failed, error %d\n", __func__, result); + goto done; + } + VERIFY(uuid_is_null(pcb->utun_kpipe_uuid)); bzero(&init, sizeof (init)); init.nxi_version = KERN_NEXUS_CURRENT_VERSION; + init.nxi_tx_pbufpool = pcb->utun_kpipe_pp; result = kern_nexus_controller_alloc_provider_instance(utun_ncd, utun_kpipe_uuid, pcb, &pcb->utun_kpipe_uuid, &init); if (result) { @@ -1297,6 +1351,10 @@ utun_enable_channel(struct utun_pcb *pcb, struct proc *proc) lck_rw_unlock_exclusive(&pcb->utun_pcb_lock); if (result) { + if (pcb->utun_kpipe_pp != NULL) { + kern_pbufpool_destroy(pcb->utun_kpipe_pp); + pcb->utun_kpipe_pp = NULL; + } utun_unregister_kernel_pipe_nexus(); } @@ -1786,10 +1844,14 @@ utun_ctl_disconnect(__unused kern_ctl_ref kctlref, if (!uuid_is_null(kpipe_uuid)) { if (kern_nexus_controller_free_provider_instance(utun_ncd, kpipe_uuid) == 0) { + if (pcb->utun_kpipe_pp != NULL) { + kern_pbufpool_destroy(pcb->utun_kpipe_pp); + pcb->utun_kpipe_pp = NULL; + } utun_unregister_kernel_pipe_nexus(); } } - utun_nexus_detach(&pcb->utun_nx); + utun_nexus_detach(pcb); /* Decrement refcnt to finish detaching and freeing */ ifnet_decr_iorefcnt(ifp); @@ -1801,6 +1863,10 @@ utun_ctl_disconnect(__unused kern_ctl_ref kctlref, #if UTUN_NEXUS if (!uuid_is_null(kpipe_uuid)) { if (kern_nexus_controller_free_provider_instance(utun_ncd, kpipe_uuid) == 0) { + if (pcb->utun_kpipe_pp != NULL) { + kern_pbufpool_destroy(pcb->utun_kpipe_pp); + pcb->utun_kpipe_pp = NULL; + } utun_unregister_kernel_pipe_nexus(); } } @@ -2006,7 +2072,7 @@ utun_ctl_setopt(__unused kern_ctl_ref kctlref, result = EINVAL; break; } - if (!if_enable_netagent) { + if (!if_is_netagent_enabled()) { result = ENOTSUP; break; } @@ -2032,7 +2098,9 @@ utun_ctl_setopt(__unused kern_ctl_ref kctlref, result = EINVAL; break; } - pcb->utun_use_netif = true; + lck_rw_lock_exclusive(&pcb->utun_pcb_lock); + pcb->utun_use_netif = !!(*(int *)data); + lck_rw_unlock_exclusive(&pcb->utun_pcb_lock); break; } case UTUN_OPT_SLOT_SIZE: { @@ -2168,6 +2236,37 @@ utun_ctl_getopt(__unused kern_ctl_ref kctlref, } #if UTUN_NEXUS + case UTUN_OPT_ENABLE_CHANNEL: { + if (*len != sizeof(int)) { + result = EMSGSIZE; + } else { + lck_rw_lock_shared(&pcb->utun_pcb_lock); + *(int *)data = pcb->utun_kpipe_enabled; + lck_rw_unlock_shared(&pcb->utun_pcb_lock); + } + break; + } + + case UTUN_OPT_ENABLE_FLOWSWITCH: { + if (*len != sizeof(int)) { + result = EMSGSIZE; + } else { + *(int *)data = if_check_netagent(pcb->utun_ifp, pcb->utun_nx.ms_agent); + } + break; + } + + case UTUN_OPT_ENABLE_NETIF: { + if (*len != sizeof(int)) { + result = EMSGSIZE; + } else { + lck_rw_lock_shared(&pcb->utun_pcb_lock); + *(int *)data = !!pcb->utun_use_netif; + lck_rw_unlock_shared(&pcb->utun_pcb_lock); + } + break; + } + case UTUN_OPT_GET_CHANNEL_UUID: { lck_rw_lock_shared(&pcb->utun_pcb_lock); if (uuid_is_null(pcb->utun_kpipe_uuid)) { @@ -2386,10 +2485,6 @@ utun_demux(__unused ifnet_t interface, __unused char *frame_header, protocol_family_t *protocol) { - struct utun_pcb *pcb = ifnet_softc(interface); - struct ip *ip; - u_int ip_version; - while (data != NULL && mbuf_len(data) < 1) { data = mbuf_next(data); } @@ -2399,6 +2494,10 @@ utun_demux(__unused ifnet_t interface, } #if UTUN_NEXUS + struct utun_pcb *pcb = ifnet_softc(interface); + struct ip *ip; + u_int ip_version; + if (pcb->utun_use_netif) { ip = mtod(data, struct ip *); ip_version = ip->ip_v; @@ -2488,12 +2587,12 @@ utun_ioctl(ifnet_t interface, u_long command, void *data) { - struct utun_pcb *pcb = ifnet_softc(interface); errno_t result = 0; - + switch(command) { case SIOCSIFMTU: { #if UTUN_NEXUS + struct utun_pcb *pcb = ifnet_softc(interface); if (pcb->utun_use_netif) { // Make sure we can fit packets in the channel buffers // Allow for the headroom in the slot @@ -2544,6 +2643,7 @@ utun_proto_input(__unused ifnet_t interface, { mbuf_adj(m, UTUN_HEADER_SIZE(pcb)); } + int32_t pktlen = m->m_pkthdr.len; if (proto_input(protocol, m) != 0) { m_freem(m); #if UTUN_NEXUS @@ -2557,7 +2657,7 @@ utun_proto_input(__unused ifnet_t interface, if (!pcb->utun_use_netif) #endif // UTUN_NEXUS { - ifnet_stat_increment_in(interface, 1, m->m_pkthdr.len, 0); + ifnet_stat_increment_in(interface, 1, pktlen, 0); } } @@ -2978,7 +3078,7 @@ utun_kpipe_sync_rx(kern_nexus_provider_t nxprov, kern_nexus_t nexus, // Allocate rx packet kern_packet_t rx_ph = 0; errno_t error = kern_pbufpool_alloc_nosleep(rx_pp, 1, &rx_ph); - if (unlikely(error != 0)) { + if (__improbable(error != 0)) { printf("utun_kpipe_sync_rx %s: failed to allocate packet\n", pcb->utun_ifp->if_xname); break; @@ -3134,7 +3234,7 @@ utun_kpipe_sync_rx(kern_nexus_provider_t nxprov, kern_nexus_t nexus, // Allocate rx packet kern_packet_t rx_ph = 0; errno_t error = kern_pbufpool_alloc_nosleep(rx_pp, 1, &rx_ph); - if (unlikely(error != 0)) { + if (__improbable(error != 0)) { printf("utun_kpipe_sync_rx %s: failed to allocate packet\n", pcb->utun_ifp->if_xname); break; diff --git a/bsd/net/if_var.h b/bsd/net/if_var.h index 60aa09b8f..835a4535b 100644 --- a/bsd/net/if_var.h +++ b/bsd/net/if_var.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2017 Apple Inc. All rights reserved. + * Copyright (c) 2000-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -1722,6 +1722,9 @@ __private_extern__ struct rtentry *ifnet_cached_rtlookup_inet6(struct ifnet *, struct in6_addr *); #endif /* INET6 */ +__private_extern__ u_int32_t if_get_protolist(struct ifnet * ifp, + u_int32_t *protolist, u_int32_t count); +__private_extern__ void if_free_protolist(u_int32_t *list); __private_extern__ errno_t if_state_update(struct ifnet *, struct if_interface_state *); __private_extern__ void if_get_state(struct ifnet *, @@ -1770,6 +1773,8 @@ __private_extern__ u_int32_t ifnet_get_generation(struct ifnet *); /* Adding and deleting netagents will take ifnet lock */ __private_extern__ int if_add_netagent(struct ifnet *, uuid_t); __private_extern__ int if_delete_netagent(struct ifnet *, uuid_t); +__private_extern__ boolean_t if_check_netagent(struct ifnet *, uuid_t); + extern int if_set_qosmarking_mode(struct ifnet *, u_int32_t); __private_extern__ uint32_t ifnet_mbuf_packetpreamblelen(struct ifnet *); diff --git a/bsd/net/kpi_interface.c b/bsd/net/kpi_interface.c index 05e7cfc57..c5f268213 100644 --- a/bsd/net/kpi_interface.c +++ b/bsd/net/kpi_interface.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2017 Apple Inc. All rights reserved. + * Copyright (c) 2004-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -225,16 +226,18 @@ ifnet_allocate_extended(const struct ifnet_init_eparams *einit0, } } + + /* Initialize external name (name + unit) */ + (void) snprintf(if_xname, sizeof (if_xname), "%s%d", + einit.name, einit.unit); + if (einit.uniqueid == NULL) { - /* Initialize external name (name + unit) */ - (void) snprintf(if_xname, sizeof (if_xname), "%s%d", - einit.name, einit.unit); einit.uniqueid = if_xname; einit.uniqueid_len = strlen(if_xname); } error = dlil_if_acquire(einit.family, einit.uniqueid, - einit.uniqueid_len, &ifp); + einit.uniqueid_len, if_xname, &ifp); if (error == 0) { u_int64_t br; @@ -279,7 +282,7 @@ ifnet_allocate_extended(const struct ifnet_init_eparams *einit0, /* Initialize external name (name + unit) */ snprintf(__DECONST(char *, ifp->if_xname), IFXNAMSIZ, - "%s%d", ifp->if_name, ifp->if_unit); + "%s", if_xname); /* * On embedded, framer() is already in the extended form; @@ -2612,7 +2615,10 @@ ifnet_get_local_ports_extended(ifnet_t ifp, protocol_family_t protocol, } /* bit string is long enough to hold 16-bit port values */ - bzero(bitfield, bitstr_size(65536)); + bzero(bitfield, bitstr_size(IP_PORTRANGE_SIZE)); + + if_ports_used_update_wakeuuid(ifp); + inp_flags |= ((flags & IFNET_GET_LOCAL_PORTS_WILDCARDOK) ? INPCB_GET_PORTS_USED_WILDCARDOK : 0); @@ -2625,7 +2631,6 @@ ifnet_get_local_ports_extended(ifnet_t ifp, protocol_family_t protocol, inp_flags |= ((flags & IFNET_GET_LOCAL_PORTS_ACTIVEONLY) ? INPCB_GET_PORTS_USED_ACTIVEONLY : 0); - ifindex = (ifp != NULL) ? ifp->if_index : 0; if (!(flags & IFNET_GET_LOCAL_PORTS_TCPONLY)) @@ -2635,6 +2640,7 @@ ifnet_get_local_ports_extended(ifnet_t ifp, protocol_family_t protocol, if (!(flags & IFNET_GET_LOCAL_PORTS_UDPONLY)) tcp_get_ports_used(ifindex, protocol, inp_flags, bitfield); + return (0); } diff --git a/bsd/net/necp.c b/bsd/net/necp.c index 22f5afbd5..1e6a5dcd2 100644 --- a/bsd/net/necp.c +++ b/bsd/net/necp.c @@ -6539,8 +6539,20 @@ necp_application_find_policy_match_internal(proc_t proc, is_local = TRUE; } else if (returned_result->routed_interface_index != 0 && !no_remote_addr) { + // Clean up the address before comparison with interface addresses + + // Transform remote_addr into the ifaddr form + // IPv6 Scope IDs are always embedded in the ifaddr list + struct sockaddr_storage remote_address_sanitized; + u_int ifscope = IFSCOPE_NONE; + (void)sa_copy(&remote_addr.sa, &remote_address_sanitized, &ifscope); + SIN(&remote_address_sanitized)->sin_port = 0; + if (remote_address_sanitized.ss_family == AF_INET6) { + SIN6(&remote_address_sanitized)->sin6_scope_id = 0; + } + // Check if remote address is an interface address - struct ifaddr *ifa = ifa_ifwithaddr(&remote_addr.sa); + struct ifaddr *ifa = ifa_ifwithaddr((struct sockaddr *)&remote_address_sanitized); if (ifa != NULL && ifa->ifa_ifp != NULL) { u_int if_index_for_remote_addr = ifa->ifa_ifp->if_index; if (if_index_for_remote_addr == returned_result->routed_interface_index || diff --git a/bsd/net/necp.h b/bsd/net/necp.h index 63a9fe967..d20124f67 100644 --- a/bsd/net/necp.h +++ b/bsd/net/necp.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017 Apple Inc. All rights reserved. + * Copyright (c) 2013-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -278,6 +278,8 @@ struct necp_stat_counts u_int32_t necp_stat_avg_rtt; u_int32_t necp_stat_var_rtt; +#define NECP_STAT_ROUTE_FLAGS 1 + u_int32_t necp_stat_route_flags; }; // Note, some metadata is implicit in the necp client itself: @@ -927,7 +929,9 @@ extern void necp_client_early_close(uuid_t client_id); // Cause a single client extern void necp_set_client_as_background(proc_t proc, struct fileproc *fp, bool background); // Set all clients for an fp as background or not -extern void necp_defunct_client(proc_t proc, struct fileproc *fp); // Set all clients for an fp as defunct +struct necp_fd_data; +extern void necp_fd_memstatus(proc_t proc, uint32_t status, struct necp_fd_data *client_fd); // Purge memory of clients for the process +extern void necp_fd_defunct(proc_t proc, struct necp_fd_data *client_fd); // Set all clients for an process as defunct extern int necp_client_register_socket_flow(pid_t pid, uuid_t client_id, struct inpcb *inp); @@ -999,6 +1003,10 @@ struct necp_client_flow { size_t assigned_results_length; u_int8_t *assigned_results; }; + +extern void necp_client_reap_caches(boolean_t); + + #endif /* BSD_KERNEL_PRIVATE */ #ifndef KERNEL diff --git a/bsd/net/necp_client.c b/bsd/net/necp_client.c index 83666005b..9341db09b 100644 --- a/bsd/net/necp_client.c +++ b/bsd/net/necp_client.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017 Apple Inc. All rights reserved. + * Copyright (c) 2015-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -272,6 +272,7 @@ struct necp_client_nexus_flow_header { u_int8_t tfo_cookie_value[NECP_TFO_COOKIE_LEN_MAX]; } __attribute__((__packed__)); + struct necp_client { RB_ENTRY(necp_client) link; RB_ENTRY(necp_client) global_link; @@ -363,6 +364,7 @@ struct necp_client_update { struct necp_client_observer_update update; }; + struct necp_fd_data { u_int8_t necp_fd_type; LIST_ENTRY(necp_fd_data) chain; @@ -392,8 +394,9 @@ static struct zone *necp_client_fd_zone; /* zone for necp_fd_data */ #define NECP_FLOW_ZONE_MAX 512 #define NECP_FLOW_ZONE_NAME "necp.flow" -static unsigned int necp_flow_size; /* size of zone element */ -static struct zone *necp_flow_zone; /* zone for necp_client_flow */ +static unsigned int necp_flow_size; /* size of necp_client_flow */ +static struct mcache *necp_flow_cache; /* cache for necp_client_flow */ + static lck_grp_attr_t *necp_fd_grp_attr = NULL; static lck_attr_t *necp_fd_mtx_attr = NULL; @@ -695,6 +698,10 @@ necp_set_client_defunct(struct necp_client *client) (void)necp_buffer_write_tlv_if_different(client->result, NECP_CLIENT_RESULT_FLAGS, sizeof(flags), &flags, &updated, client->result, sizeof(client->result)); + + if (updated) { + client->result_read = FALSE; + } } return (updated); @@ -704,6 +711,8 @@ static void necp_defunct_client_for_policy(struct necp_client *client, struct _necp_client_defunct_list *defunct_list) { + NECP_CLIENT_ASSERT_LOCKED(client); + if (!client->defunct) { bool needs_defunct = false; struct necp_client_flow *search_flow = NULL; @@ -958,7 +967,7 @@ necp_destroy_client(struct necp_client *client, pid_t pid, bool abort) } else { OSDecrementAtomic(&necp_if_flow_count); } - zfree(necp_flow_zone, search_flow); + mcache_free(necp_flow_cache, search_flow); } // Remove agent assertions @@ -1088,7 +1097,7 @@ necp_find_fd_data(int fd, struct necp_fd_data **fd_data) static void necp_client_add_socket_flow(struct necp_client *client, struct inpcb *inp) { - struct necp_client_flow *new_flow = zalloc(necp_flow_zone); + struct necp_client_flow *new_flow = mcache_alloc(necp_flow_cache, MCR_SLEEP); if (new_flow == NULL) { NECPLOG0(LOG_ERR, "Failed to allocate socket flow"); return; @@ -1108,7 +1117,7 @@ necp_client_add_socket_flow(struct necp_client *client, struct inpcb *inp) static void necp_client_add_interface_flow(struct necp_client *client, uint32_t interface_index) { - struct necp_client_flow *new_flow = zalloc(necp_flow_zone); + struct necp_client_flow *new_flow = mcache_alloc(necp_flow_cache, MCR_SLEEP); if (new_flow == NULL) { NECPLOG0(LOG_ERR, "Failed to allocate interface flow"); return; @@ -1170,8 +1179,13 @@ necp_client_flow_is_viable(proc_t proc, struct necp_client *client, } static bool -necp_client_update_flows(proc_t proc, struct necp_client *client) +necp_client_update_flows(proc_t proc, + struct necp_client *client, + struct _necp_client_defunct_list *defunct_list, + bool *defuncted_by_flow) { + NECP_CLIENT_ASSERT_LOCKED(client); + bool client_updated = FALSE; struct necp_client_flow *flow = NULL; struct necp_client_flow *temp_flow = NULL; @@ -1205,6 +1219,8 @@ necp_client_update_flows(proc_t proc, struct necp_client *client) // check again the flags after the callback. } + (void)defunct_list; + (void)defuncted_by_flow; // Handle flows that no longer match if (!flow->viable || flow->invalid) { @@ -1221,7 +1237,7 @@ necp_client_update_flows(proc_t proc, struct necp_client *client) } else { OSDecrementAtomic(&necp_if_flow_count); } - zfree(necp_flow_zone, flow); + mcache_free(necp_flow_cache, flow); } } } @@ -1775,7 +1791,7 @@ necp_client_unregister_socket_flow(uuid_t client_id, void *handle) client_updated = TRUE; LIST_REMOVE(search_flow, flow_chain); OSDecrementAtomic(&necp_socket_flow_count); - zfree(necp_flow_zone, search_flow); + mcache_free(necp_flow_cache, search_flow); } } @@ -2013,7 +2029,13 @@ necp_update_flow_protoctl_event(uuid_t netagent_uuid, uuid_t client_id, } static bool -necp_assign_client_result_locked(struct proc *proc, struct necp_fd_data *client_fd, struct necp_client *client, uuid_t netagent_uuid, u_int8_t *assigned_results, size_t assigned_results_length) +necp_assign_client_result_locked(struct proc *proc, + struct necp_fd_data *client_fd, + struct necp_client *client, + uuid_t netagent_uuid, + u_int8_t *assigned_results, + size_t assigned_results_length, + bool notify_fd) { bool client_updated = FALSE; @@ -2048,7 +2070,7 @@ necp_assign_client_result_locked(struct proc *proc, struct necp_fd_data *client_ } } - if (client_updated) { + if (client_updated && notify_fd) { necp_fd_notify(client_fd, true); } @@ -2079,7 +2101,8 @@ necp_assign_client_result(uuid_t netagent_uuid, uuid_t client_id, // Found the right client! found_client = TRUE; - if (necp_assign_client_result_locked(proc, client_fd, client, netagent_uuid, assigned_results, assigned_results_length)) { + if (necp_assign_client_result_locked(proc, client_fd, client, netagent_uuid, + assigned_results, assigned_results_length, true)) { client_updated = TRUE; } @@ -2422,8 +2445,14 @@ necp_update_client_result(proc_t proc, } // Update flow viability/flags - if (necp_client_update_flows(proc, client)) { + bool defuncted_by_flow = FALSE; + if (necp_client_update_flows(proc, client, defunct_list, &defuncted_by_flow)) { updated = TRUE; + if (defuncted_by_flow && client->defunct) { + // Reset initial TLV + flags |= NECP_CLIENT_RESULT_FLAG_DEFUNCT; + (void)necp_buffer_write_tlv_if_different(client->result, NECP_CLIENT_RESULT_FLAGS, sizeof(flags), &flags, &updated, client->result, sizeof(client->result)); + } } if (updated) { @@ -2436,12 +2465,14 @@ necp_update_client_result(proc_t proc, } static inline void -necp_defunct_client_fd_locked(struct necp_fd_data *client_fd, struct _necp_client_defunct_list *defunct_list) +necp_defunct_client_fd_locked(struct necp_fd_data *client_fd, struct _necp_client_defunct_list *defunct_list, struct proc *proc) { +#pragma unused(proc) bool updated_result = FALSE; struct necp_client *client = NULL; NECP_FD_ASSERT_LOCKED(client_fd); + RB_FOREACH(client, _necp_client_tree, &client_fd->clients) { NECP_CLIENT_LOCK(client); if (!client->defunct) { @@ -2469,6 +2500,8 @@ necp_defunct_client_fd_locked(struct necp_fd_data *client_fd, struct _necp_clien } NECP_CLIENT_UNLOCK(client); } + + if (updated_result) { necp_fd_notify(client_fd, true); } @@ -2536,7 +2569,10 @@ necp_update_all_clients_callout(__unused thread_call_param_t dummy, client_defunct->proc_pid, NETAGENT_MESSAGE_TYPE_ABORT_NEXUS); if (netagent_error != 0) { - NECPLOG((netagent_error == ENOENT ? LOG_DEBUG : LOG_ERR), "necp_update_client abort nexus error (%d)", netagent_error); + char namebuf[MAXCOMLEN+1]; + (void) strlcpy(namebuf, "unknown", sizeof (namebuf)); + proc_name(client_defunct->proc_pid, namebuf, sizeof (namebuf)); + NECPLOG((netagent_error == ENOENT ? LOG_DEBUG : LOG_ERR), "necp_update_client abort nexus error (%d) for pid %d %s", netagent_error, client_defunct->proc_pid, namebuf); } } LIST_REMOVE(client_defunct, chain); @@ -2622,26 +2658,24 @@ necp_set_client_as_background(proc_t proc, } void -necp_defunct_client(proc_t proc, - struct fileproc *fp) +necp_fd_memstatus(proc_t proc, uint32_t status, + struct necp_fd_data *client_fd) { - struct _necp_client_defunct_list defunct_list; +#pragma unused(proc, status, client_fd) + ASSERT(proc != PROC_NULL); + ASSERT(client_fd != NULL); - if (proc == PROC_NULL) { - NECPLOG0(LOG_ERR, "NULL proc passed to set as background"); - return; - } + // Nothing to reap for the process or client for now, + // but this is where we would trigger that in future. +} - if (fp == NULL) { - NECPLOG0(LOG_ERR, "NULL fp passed to set as background"); - return; - } +void +necp_fd_defunct(proc_t proc, struct necp_fd_data *client_fd) +{ + struct _necp_client_defunct_list defunct_list; - struct necp_fd_data *client_fd = (struct necp_fd_data *)fp->f_fglob->fg_data; - if (client_fd == NULL) { - NECPLOG0(LOG_ERR, "Could not find client structure for backgrounded client"); - return; - } + ASSERT(proc != PROC_NULL); + ASSERT(client_fd != NULL); if (client_fd->necp_fd_type != necp_fd_type_client) { // Not a client fd, ignore @@ -2653,7 +2687,7 @@ necp_defunct_client(proc_t proc, // Need to hold lock so ntstats defunct the same set of clients NECP_FD_LOCK(client_fd); - necp_defunct_client_fd_locked(client_fd, &defunct_list); + necp_defunct_client_fd_locked(client_fd, &defunct_list, proc); NECP_FD_UNLOCK(client_fd); if (!LIST_EMPTY(&defunct_list)) { @@ -3307,7 +3341,7 @@ necp_client_remove(struct necp_fd_data *fd_data, struct necp_client_action_args { int error = 0; struct necp_client *client = NULL; - struct necp_client *temp_client = NULL; + struct necp_client find = {}; uuid_t client_id = {}; struct ifnet_stats_per_flow flow_ifnet_stats = {}; @@ -3326,33 +3360,36 @@ necp_client_remove(struct necp_fd_data *fd_data, struct necp_client_action_args error = copyin(uap->buffer, &flow_ifnet_stats, uap->buffer_size); if (error) { NECPLOG(LOG_ERR, "necp_client_remove flow_ifnet_stats copyin error (%d)", error); - // Not fatal + // Not fatal; make sure to zero-out stats in case of partial copy + memset(&flow_ifnet_stats, 0, sizeof (flow_ifnet_stats)); + error = 0; } } else if (uap->buffer != 0) { NECPLOG(LOG_ERR, "necp_client_remove unexpected parameters length (%zu)", uap->buffer_size); } - struct _necp_client_tree clients_to_close; - RB_INIT(&clients_to_close); NECP_FD_LOCK(fd_data); + pid_t pid = fd_data->proc_pid; - RB_FOREACH_SAFE(client, _necp_client_tree, &fd_data->clients, temp_client) { - if (uuid_compare(client->client_id, client_id) == 0) { - NECP_CLIENT_TREE_LOCK_EXCLUSIVE(); - RB_REMOVE(_necp_client_global_tree, &necp_client_global_tree, client); - NECP_CLIENT_TREE_UNLOCK(); - RB_REMOVE(_necp_client_tree, &fd_data->clients, client); - RB_INSERT(_necp_client_tree, &clients_to_close, client); - } + uuid_copy(find.client_id, client_id); + client = RB_FIND(_necp_client_tree, &fd_data->clients, &find); + if (client != NULL) { + NECP_CLIENT_TREE_LOCK_EXCLUSIVE(); + RB_REMOVE(_necp_client_global_tree, &necp_client_global_tree, client); + NECP_CLIENT_TREE_UNLOCK(); + RB_REMOVE(_necp_client_tree, &fd_data->clients, client); } - NECP_FD_UNLOCK(fd_data); - RB_FOREACH_SAFE(client, _necp_client_tree, &clients_to_close, temp_client) { - RB_REMOVE(_necp_client_tree, &clients_to_close, client); + if (client != NULL) { + ASSERT(error == 0); necp_destroy_client(client, pid, true); + } else { + error = ENOENT; + NECPLOG(LOG_ERR, "necp_client_remove invalid client_id (%d)", error); } + done: *retval = error; @@ -3646,7 +3683,6 @@ static int necp_client_copy(struct necp_fd_data *fd_data, struct necp_client_action_args *uap, int *retval) { int error = 0; - struct necp_client *find_client = NULL; struct necp_client *client = NULL; uuid_t client_id; uuid_clear(client_id); @@ -3679,28 +3715,34 @@ necp_client_copy(struct necp_fd_data *fd_data, struct necp_client_action_args *u } } + const bool is_wildcard = (bool)uuid_is_null(client_id); + NECP_FD_LOCK(fd_data); - RB_FOREACH(find_client, _necp_client_tree, &fd_data->clients) { - NECP_CLIENT_LOCK(find_client); - if ((uap->action == NECP_CLIENT_ACTION_COPY_RESULT || uap->action == NECP_CLIENT_ACTION_COPY_UPDATED_RESULT) && - uuid_is_null(client_id)) { - if (!find_client->result_read || !find_client->flow_result_read) { - client = find_client; + + if (is_wildcard) { + if (uap->action == NECP_CLIENT_ACTION_COPY_RESULT || uap->action == NECP_CLIENT_ACTION_COPY_UPDATED_RESULT) { + struct necp_client *find_client = NULL; + RB_FOREACH(find_client, _necp_client_tree, &fd_data->clients) { + NECP_CLIENT_LOCK(find_client); + if (!find_client->result_read || !find_client->flow_result_read) { + client = find_client; + // Leave the client locked, and break + break; + } + NECP_CLIENT_UNLOCK(find_client); } - } else if (uuid_compare(find_client->client_id, client_id) == 0) { - client = find_client; - } - NECP_CLIENT_UNLOCK(find_client); - if (client != NULL) { - break; } + } else { + client = necp_client_fd_find_client_and_lock(fd_data, client_id); } if (client != NULL) { + // If client is set, it is locked error = necp_client_copy_internal(client, FALSE, uap, retval); + NECP_CLIENT_UNLOCK(client); } - // Unlock our own client before moving on or returning + // Unlock our own fd before moving on or returning NECP_FD_UNLOCK(fd_data); if (client == NULL) { @@ -4016,6 +4058,7 @@ necp_client_agent_action(struct necp_fd_data *fd_data, struct necp_client_action if (uap->client_id == 0 || uap->client_id_len != sizeof(uuid_t) || uap->buffer_size == 0 || uap->buffer == 0) { + NECPLOG0(LOG_ERR, "necp_client_agent_action invalid parameters"); error = EINVAL; goto done; } @@ -4027,6 +4070,7 @@ necp_client_agent_action(struct necp_fd_data *fd_data, struct necp_client_action } if ((parameters = _MALLOC(uap->buffer_size, M_NECP, M_WAITOK | M_ZERO)) == NULL) { + NECPLOG0(LOG_ERR, "necp_client_agent_action malloc failed"); error = ENOMEM; goto done; } @@ -4313,21 +4357,22 @@ necp_client_copy_route_statistics(__unused struct necp_fd_data *fd_data, struct client = necp_client_fd_find_client_and_lock(fd_data, client_id); if (client != NULL) { NECP_CLIENT_ROUTE_LOCK(client); - struct nstat_counts route_stats = {}; + struct necp_stat_counts route_stats = {}; if (client->current_route != NULL && client->current_route->rt_stats != NULL) { struct nstat_counts *rt_stats = client->current_route->rt_stats; - atomic_get_64(route_stats.nstat_rxpackets, &rt_stats->nstat_rxpackets); - atomic_get_64(route_stats.nstat_rxbytes, &rt_stats->nstat_rxbytes); - atomic_get_64(route_stats.nstat_txpackets, &rt_stats->nstat_txpackets); - atomic_get_64(route_stats.nstat_txbytes, &rt_stats->nstat_txbytes); - route_stats.nstat_rxduplicatebytes = rt_stats->nstat_rxduplicatebytes; - route_stats.nstat_rxoutoforderbytes = rt_stats->nstat_rxoutoforderbytes; - route_stats.nstat_txretransmit = rt_stats->nstat_txretransmit; - route_stats.nstat_connectattempts = rt_stats->nstat_connectattempts; - route_stats.nstat_connectsuccesses = rt_stats->nstat_connectsuccesses; - route_stats.nstat_min_rtt = rt_stats->nstat_min_rtt; - route_stats.nstat_avg_rtt = rt_stats->nstat_avg_rtt; - route_stats.nstat_var_rtt = rt_stats->nstat_var_rtt; + atomic_get_64(route_stats.necp_stat_rxpackets, &rt_stats->nstat_rxpackets); + atomic_get_64(route_stats.necp_stat_rxbytes, &rt_stats->nstat_rxbytes); + atomic_get_64(route_stats.necp_stat_txpackets, &rt_stats->nstat_txpackets); + atomic_get_64(route_stats.necp_stat_txbytes, &rt_stats->nstat_txbytes); + route_stats.necp_stat_rxduplicatebytes = rt_stats->nstat_rxduplicatebytes; + route_stats.necp_stat_rxoutoforderbytes = rt_stats->nstat_rxoutoforderbytes; + route_stats.necp_stat_txretransmit = rt_stats->nstat_txretransmit; + route_stats.necp_stat_connectattempts = rt_stats->nstat_connectattempts; + route_stats.necp_stat_connectsuccesses = rt_stats->nstat_connectsuccesses; + route_stats.necp_stat_min_rtt = rt_stats->nstat_min_rtt; + route_stats.necp_stat_avg_rtt = rt_stats->nstat_avg_rtt; + route_stats.necp_stat_var_rtt = rt_stats->nstat_var_rtt; + route_stats.necp_stat_route_flags = client->current_route->rt_flags; } // Unlock before copying out @@ -4828,6 +4873,7 @@ necp_inpcb_remove_cb(struct inpcb *inp) void necp_inpcb_dispose(struct inpcb *inp) { + necp_inpcb_remove_cb(inp); // Clear out socket registrations if not yet done if (inp->inp_necp_attributes.inp_domain != NULL) { FREE(inp->inp_necp_attributes.inp_domain, M_NECP); inp->inp_necp_attributes.inp_domain = NULL; @@ -4852,27 +4898,22 @@ necp_mppcb_dispose(struct mppcb *mpp) errno_t necp_client_init(void) { - errno_t result = 0; - necp_fd_grp_attr = lck_grp_attr_alloc_init(); if (necp_fd_grp_attr == NULL) { - NECPLOG0(LOG_ERR, "lck_grp_attr_alloc_init failed"); - result = ENOMEM; - goto done; + panic("lck_grp_attr_alloc_init failed\n"); + /* NOTREACHED */ } necp_fd_mtx_grp = lck_grp_alloc_init("necp_fd", necp_fd_grp_attr); if (necp_fd_mtx_grp == NULL) { - NECPLOG0(LOG_ERR, "lck_grp_alloc_init failed"); - result = ENOMEM; - goto done; + panic("lck_grp_alloc_init failed\n"); + /* NOTREACHED */ } necp_fd_mtx_attr = lck_attr_alloc_init(); if (necp_fd_mtx_attr == NULL) { - NECPLOG0(LOG_ERR, "lck_attr_alloc_init failed"); - result = ENOMEM; - goto done; + panic("lck_attr_alloc_init failed\n"); + /* NOTREACHED */ } necp_client_fd_size = sizeof(struct necp_fd_data); @@ -4880,19 +4921,15 @@ necp_client_init(void) NECP_CLIENT_FD_ZONE_MAX * necp_client_fd_size, 0, NECP_CLIENT_FD_ZONE_NAME); if (necp_client_fd_zone == NULL) { - NECPLOG0(LOG_ERR, "zinit(necp_client_fd) failed"); - result = ENOMEM; - goto done; + panic("zinit(necp_client_fd) failed\n"); + /* NOTREACHED */ } necp_flow_size = sizeof(struct necp_client_flow); - necp_flow_zone = zinit(necp_flow_size, - NECP_FLOW_ZONE_MAX * necp_flow_size, - 0, NECP_FLOW_ZONE_NAME); - if (necp_flow_zone == NULL) { - NECPLOG0(LOG_ERR, "zinit(necp_flow) failed"); - result = ENOMEM; - goto done; + necp_flow_cache = mcache_create(NECP_FLOW_ZONE_NAME, necp_flow_size, sizeof (uint64_t), 0, MCR_SLEEP); + if (necp_flow_cache == NULL) { + panic("mcache_create(necp_flow_cache) failed\n"); + /* NOTREACHED */ } necp_client_update_tcall = thread_call_allocate_with_options(necp_update_all_clients_callout, NULL, @@ -4910,20 +4947,12 @@ necp_client_init(void) RB_INIT(&necp_client_global_tree); -done: - if (result != 0) { - if (necp_fd_mtx_attr != NULL) { - lck_attr_free(necp_fd_mtx_attr); - necp_fd_mtx_attr = NULL; - } - if (necp_fd_mtx_grp != NULL) { - lck_grp_free(necp_fd_mtx_grp); - necp_fd_mtx_grp = NULL; - } - if (necp_fd_grp_attr != NULL) { - lck_grp_attr_free(necp_fd_grp_attr); - necp_fd_grp_attr = NULL; - } - } - return (result); + return (0); +} + +void +necp_client_reap_caches(boolean_t purge) +{ + mcache_reap_now(necp_flow_cache, purge); } + diff --git a/bsd/net/net_stubs.c b/bsd/net/net_stubs.c index 137682285..36385a019 100644 --- a/bsd/net/net_stubs.c +++ b/bsd/net/net_stubs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 Apple Inc. All rights reserved. + * Copyright (c) 2012-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -28,8 +28,6 @@ #include -#if !NETWORKING - #define STUB(name) \ int name(void); \ int name(void) \ @@ -38,6 +36,8 @@ return (0); \ } +#if !NETWORKING + STUB(bpf_attach); STUB(bpf_tap_in); STUB(bpf_tap_out); @@ -467,4 +467,7 @@ void m_drain(void) return; } +#else /* NETWORKING */ + + #endif /* !NETWORKING */ diff --git a/bsd/net/network_agent.c b/bsd/net/network_agent.c index 14fe6dc99..392665f18 100644 --- a/bsd/net/network_agent.c +++ b/bsd/net/network_agent.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2017 Apple Inc. All rights reserved. + * Copyright (c) 2014-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -811,7 +811,7 @@ netagent_handle_register_setopt(struct netagent_session *session, u_int8_t *payl } if (payload_length < sizeof(struct netagent)) { - NETAGENTLOG(LOG_ERR, "Register message size too small for agent: (%d < %d)", + NETAGENTLOG(LOG_ERR, "Register message size too small for agent: (%u < %lu)", payload_length, sizeof(struct netagent)); response_error = EINVAL; goto done; @@ -825,7 +825,7 @@ netagent_handle_register_setopt(struct netagent_session *session, u_int8_t *payl } if (payload_length != (sizeof(struct netagent) + data_size)) { - NETAGENTLOG(LOG_ERR, "Mismatch between data size and payload length (%u != %u)", (sizeof(struct netagent) + data_size), payload_length); + NETAGENTLOG(LOG_ERR, "Mismatch between data size and payload length (%lu != %u)", (sizeof(struct netagent) + data_size), payload_length); response_error = EINVAL; goto done; } @@ -877,7 +877,7 @@ netagent_handle_register_message(struct netagent_session *session, u_int32_t mes } if (payload_length < sizeof(struct netagent)) { - NETAGENTLOG(LOG_ERR, "Register message size too small for agent: (%d < %d)", + NETAGENTLOG(LOG_ERR, "Register message size too small for agent: (%u < %lu)", payload_length, sizeof(struct netagent)); response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA; goto fail; @@ -1158,7 +1158,7 @@ netagent_handle_update_setopt(struct netagent_session *session, u_int8_t *payloa } if (payload_length < sizeof(struct netagent)) { - NETAGENTLOG(LOG_ERR, "Update message size too small for agent: (%d < %d)", + NETAGENTLOG(LOG_ERR, "Update message size too small for agent: (%u < %lu)", payload_length, sizeof(struct netagent)); response_error = EINVAL; goto done; @@ -1172,7 +1172,7 @@ netagent_handle_update_setopt(struct netagent_session *session, u_int8_t *payloa } if (payload_length != (sizeof(struct netagent) + data_size)) { - NETAGENTLOG(LOG_ERR, "Mismatch between data size and payload length (%u != %u)", (sizeof(struct netagent) + data_size), payload_length); + NETAGENTLOG(LOG_ERR, "Mismatch between data size and payload length (%lu != %u)", (sizeof(struct netagent) + data_size), payload_length); response_error = EINVAL; goto done; } @@ -1225,7 +1225,7 @@ netagent_handle_update_message(struct netagent_session *session, u_int32_t messa } if (payload_length < sizeof(struct netagent)) { - NETAGENTLOG(LOG_ERR, "Update message size too small for agent: (%d < %d)", + NETAGENTLOG(LOG_ERR, "Update message size too small for agent: (%u < %lu)", payload_length, sizeof(struct netagent)); response_error = NETAGENT_MESSAGE_ERROR_INVALID_DATA; goto fail; @@ -1526,7 +1526,7 @@ netagent_handle_use_count_setopt(struct netagent_session *session, u_int8_t *pay } if (payload_length != sizeof(use_count)) { - NETAGENTLOG(LOG_ERR, "Payload length is invalid (%u)", payload_length); + NETAGENTLOG(LOG_ERR, "Payload length is invalid (%lu)", payload_length); response_error = EINVAL; goto done; } @@ -1569,7 +1569,7 @@ netagent_handle_use_count_getopt(struct netagent_session *session, u_int8_t *buf } if (*buffer_length != sizeof(use_count)) { - NETAGENTLOG(LOG_ERR, "Buffer length is invalid (%u)", buffer_length); + NETAGENTLOG(LOG_ERR, "Buffer length is invalid (%lu)", *buffer_length); response_error = EINVAL; goto done; } @@ -1985,6 +1985,11 @@ netagent_client_message_with_params(uuid_t agent_uuid, } } NETAGENTLOG(((error && error != ENOENT) ? LOG_ERR : LOG_INFO), "Send message %d for client (error %d)", message_type, error); + if (message_type == NETAGENT_MESSAGE_TYPE_CLIENT_TRIGGER) { + uuid_string_t uuid_str; + uuid_unparse(agent_uuid, uuid_str); + NETAGENTLOG(LOG_NOTICE, "Triggered network agent %s, error = %d", uuid_str, error); + } done: if (should_unlock) { lck_rw_done(&netagent_lock); @@ -2065,7 +2070,7 @@ netagent_trigger(struct proc *p, struct netagent_trigger_args *uap, int32_t *ret if (uap->agent_uuid) { if (uap->agent_uuidlen != sizeof(uuid_t)) { - NETAGENTLOG(LOG_ERR, "Incorrect length (got %d, expected %d)", + NETAGENTLOG(LOG_ERR, "Incorrect length (got %llu, expected %lu)", uap->agent_uuidlen, sizeof(uuid_t)); return (ERANGE); } diff --git a/bsd/net/ntstat.c b/bsd/net/ntstat.c index 1d51a92e7..e370d7c93 100644 --- a/bsd/net/ntstat.c +++ b/bsd/net/ntstat.c @@ -77,8 +77,6 @@ #include #include -extern unsigned int if_enable_netagent; - __private_extern__ int nstat_collect = 1; #if (DEBUG || DEVELOPMENT) diff --git a/bsd/net/pf.c b/bsd/net/pf.c index 6ce23690e..0ddbf167a 100644 --- a/bsd/net/pf.c +++ b/bsd/net/pf.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2007-2017 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ @@ -2961,7 +2961,8 @@ pf_step_out_of_anchor(int *depth, struct pf_ruleset **rs, int n, if (f->child->match || (match != NULL && *match)) { f->r->anchor->match = 1; - *match = 0; + if (match) + *match = 0; } f->child = RB_NEXT(pf_anchor_node, f->parent, f->child); if (f->child != NULL) { diff --git a/bsd/net/pktsched/pktsched_tcq.c b/bsd/net/pktsched/pktsched_tcq.c index d83fbb253..01a6c7cc9 100644 --- a/bsd/net/pktsched/pktsched_tcq.c +++ b/bsd/net/pktsched/pktsched_tcq.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2016 Apple Inc. All rights reserved. + * Copyright (c) 2011-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -543,7 +543,7 @@ tcq_addq(struct tcq_class *cl, pktsched_pkt_t *pkt, struct pf_mtag *t) #if PF_ECN if (cl->cl_flags & TQCF_CLEARDSCP) - /* not supported for skywalk packets */ + /* not supported for non-BSD stack packets */ VERIFY(pkt->pktsched_ptype == QP_MBUF); write_dsfield(m, t, 0); #endif /* PF_ECN */ diff --git a/bsd/net/route.c b/bsd/net/route.c index 80d336a40..69fdd5937 100644 --- a/bsd/net/route.c +++ b/bsd/net/route.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2017 Apple Inc. All rights reserved. + * Copyright (c) 2000-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -74,6 +74,7 @@ #include #include #include +#include #include #include #include @@ -1485,8 +1486,14 @@ rtredirect(struct ifnet *ifp, struct sockaddr *dst, struct sockaddr *gateway, done: if (rt != NULL) { RT_LOCK_ASSERT_NOTHELD(rt); - if (rtp && !error) - *rtp = rt; + if (!error) { + /* Enqueue event to refresh flow route entries */ + route_event_enqueue_nwk_wq_entry(rt, NULL, ROUTE_ENTRY_REFRESH, NULL, FALSE); + if (rtp) + *rtp = rt; + else + rtfree_locked(rt); + } else rtfree_locked(rt); } @@ -4364,4 +4371,38 @@ route_event2str(int route_event) return route_event_str; } - +int +route_op_entitlement_check(struct socket *so, + kauth_cred_t cred, + int route_op_type, + boolean_t allow_root) +{ + if (so != NULL) { + if (route_op_type == ROUTE_OP_READ) { + /* + * If needed we can later extend this for more + * granular entitlements and return a bit set of + * allowed accesses. + */ + if (soopt_cred_check(so, PRIV_NET_RESTRICTED_ROUTE_NC_READ, + allow_root) == 0) + return (0); + else + return (-1); + } + } else if (cred != NULL) { + uid_t uid = kauth_cred_getuid(cred); + + /* uid is 0 for root */ + if (uid != 0 || !allow_root) { + if (route_op_type == ROUTE_OP_READ) { + if (priv_check_cred(cred, + PRIV_NET_RESTRICTED_ROUTE_NC_READ, 0) == 0) + return (0); + else + return (-1); + } + } + } + return (-1); +} diff --git a/bsd/net/route.h b/bsd/net/route.h index 1e01812ec..141381e0a 100644 --- a/bsd/net/route.h +++ b/bsd/net/route.h @@ -272,6 +272,12 @@ EVENTHANDLER_DECLARE(route_event, route_event_fn); ((_rt)->rt_tree_genid != NULL && \ *(_rt)->rt_tree_genid != (_rt)->rt_genid) +enum { + ROUTE_OP_READ, + ROUTE_OP_WRITE, +}; + +extern int route_op_entitlement_check(struct socket *, kauth_cred_t, int, boolean_t); #endif /* BSD_KERNEL_PRIVATE */ #define RTF_UP 0x1 /* route usable */ @@ -677,6 +683,5 @@ extern void route_event_init(struct route_event *p_route_ev, struct rtentry *rt, extern int route_event_walktree(struct radix_node *rn, void *arg); extern void route_event_enqueue_nwk_wq_entry(struct rtentry *, struct rtentry *, uint32_t, eventhandler_tag, boolean_t); - #endif /* BSD_KERNEL_PRIVATE */ #endif /* _NET_ROUTE_H_ */ diff --git a/bsd/net/rtsock.c b/bsd/net/rtsock.c index 8c4387a47..dff054212 100644 --- a/bsd/net/rtsock.c +++ b/bsd/net/rtsock.c @@ -548,9 +548,17 @@ route_output(struct mbuf *m, struct socket *so) switch (rtm->rtm_type) { case RTM_GET: { kauth_cred_t cred; + kauth_cred_t* credp; struct ifaddr *ifa2; report: cred = kauth_cred_proc_ref(current_proc()); + + if (rt->rt_ifp == lo_ifp || + route_op_entitlement_check(so, NULL, ROUTE_OP_READ, TRUE) != 0) + credp = &cred; + else + credp = NULL; + ifa2 = NULL; RT_LOCK_ASSERT_HELD(rt); info.rti_info[RTAX_DST] = rt_key(rt); @@ -579,7 +587,7 @@ route_output(struct mbuf *m, struct socket *so) } if (ifa2 != NULL) IFA_LOCK(ifa2); - len = rt_msg2(rtm->rtm_type, &info, NULL, NULL, &cred); + len = rt_msg2(rtm->rtm_type, &info, NULL, NULL, credp); if (ifa2 != NULL) IFA_UNLOCK(ifa2); struct rt_msghdr *out_rtm; @@ -674,7 +682,6 @@ route_output(struct mbuf *m, struct socket *so) } RT_UNLOCK(rt); break; - default: senderr(EOPNOTSUPP); } @@ -1512,8 +1519,14 @@ sysctl_dumpentry(struct radix_node *rn, void *vw) int error = 0, size; struct rt_addrinfo info; kauth_cred_t cred; + kauth_cred_t *credp; cred = kauth_cred_proc_ref(current_proc()); + if (rt->rt_ifp == lo_ifp || + route_op_entitlement_check(NULL, cred, ROUTE_OP_READ, TRUE) != 0) + credp = &cred; + else + credp = NULL; RT_LOCK(rt); if (w->w_op == NET_RT_FLAGS && !(rt->rt_flags & w->w_arg)) @@ -1525,7 +1538,7 @@ sysctl_dumpentry(struct radix_node *rn, void *vw) info.rti_info[RTAX_GENMASK] = rt->rt_genmask; if (w->w_op != NET_RT_DUMP2) { - size = rt_msg2(RTM_GET, &info, NULL, w, &cred); + size = rt_msg2(RTM_GET, &info, NULL, w, credp); if (w->w_req != NULL && w->w_tmem != NULL) { struct rt_msghdr *rtm = (struct rt_msghdr *)(void *)w->w_tmem; @@ -1541,7 +1554,7 @@ sysctl_dumpentry(struct radix_node *rn, void *vw) error = SYSCTL_OUT(w->w_req, (caddr_t)rtm, size); } } else { - size = rt_msg2(RTM_GET2, &info, NULL, w, &cred); + size = rt_msg2(RTM_GET2, &info, NULL, w, credp); if (w->w_req != NULL && w->w_tmem != NULL) { struct rt_msghdr2 *rtm = (struct rt_msghdr2 *)(void *)w->w_tmem; diff --git a/bsd/netinet/in_gif.c b/bsd/netinet/in_gif.c index 345440463..86a2b9920 100644 --- a/bsd/netinet/in_gif.c +++ b/bsd/netinet/in_gif.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2016 Apple Inc. All rights reserved. + * Copyright (c) 2000-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -110,9 +110,13 @@ in_gif_output( struct ip iphdr; /* capsule IP header, host byte ordered */ int proto, error; u_int8_t tos; - struct ip_out_args ipoa = - { IFSCOPE_NONE, { 0 }, IPOAF_SELECT_SRCIF, 0, SO_TC_UNSPEC, - _NET_SERVICE_TYPE_UNSPEC }; + struct ip_out_args ipoa; + + bzero(&ipoa, sizeof(ipoa)); + ipoa.ipoa_boundif = IFSCOPE_NONE; + ipoa.ipoa_flags = IPOAF_SELECT_SRCIF; + ipoa.ipoa_sotc = SO_TC_UNSPEC; + ipoa.ipoa_netsvctype = _NET_SERVICE_TYPE_UNSPEC; GIF_LOCK_ASSERT(sc); diff --git a/bsd/netinet/in_pcb.c b/bsd/netinet/in_pcb.c index b3ff42cf9..b74b0af2f 100644 --- a/bsd/netinet/in_pcb.c +++ b/bsd/netinet/in_pcb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2016 Apple Inc. All rights reserved. + * Copyright (c) 2000-2017 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -728,8 +728,6 @@ in_pcbbind(struct inpcb *inp, struct sockaddr *nam, struct proc *p) if (TAILQ_EMPTY(&in_ifaddrhead)) /* XXX broken! */ return (EADDRNOTAVAIL); - if (inp->inp_lport != 0 || inp->inp_laddr.s_addr != INADDR_ANY) - return (EINVAL); if (!(so->so_options & (SO_REUSEADDR|SO_REUSEPORT))) wild = 1; @@ -737,9 +735,14 @@ in_pcbbind(struct inpcb *inp, struct sockaddr *nam, struct proc *p) socket_unlock(so, 0); /* keep reference on socket */ lck_rw_lock_exclusive(pcbinfo->ipi_lock); + if (inp->inp_lport != 0 || inp->inp_laddr.s_addr != INADDR_ANY) { + /* another thread completed the bind */ + lck_rw_done(pcbinfo->ipi_lock); + socket_lock(so, 0); + return (EINVAL); + } if (nam != NULL) { - if (nam->sa_len != sizeof (struct sockaddr_in)) { lck_rw_done(pcbinfo->ipi_lock); socket_lock(so, 0); diff --git a/bsd/netinet/in_pcblist.c b/bsd/netinet/in_pcblist.c index c67d76635..266754acc 100644 --- a/bsd/netinet/in_pcblist.c +++ b/bsd/netinet/in_pcblist.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2014 Apple Inc. All rights reserved. + * Copyright (c) 2010-2017 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -71,6 +71,7 @@ #include #include +#include #include #include @@ -446,6 +447,10 @@ inpcb_get_ports_used(uint32_t ifindex, int protocol, uint32_t flags, (protocol == PF_INET6 && (inp->inp_vflag & INP_IPV6)))) continue; + if (SOCK_PROTO(inp->inp_socket) != IPPROTO_UDP && + SOCK_PROTO(inp->inp_socket) != IPPROTO_TCP) + continue; + iswildcard = (((inp->inp_vflag & INP_IPV4) && inp->inp_laddr.s_addr == INADDR_ANY) || ((inp->inp_vflag & INP_IPV6) && @@ -524,6 +529,8 @@ inpcb_get_ports_used(uint32_t ifindex, int protocol, uint32_t flags, if (port == 0) continue; bitstr_set(bitfield, port); + + if_ports_used_add_inpcb(ifindex, inp); } lck_rw_done(pcbinfo->ipi_lock); } diff --git a/bsd/netinet/in_tclass.c b/bsd/netinet/in_tclass.c index 81595da9b..21fc03f44 100644 --- a/bsd/netinet/in_tclass.c +++ b/bsd/netinet/in_tclass.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2017 Apple Inc. All rights reserved. + * Copyright (c) 2009-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -1463,11 +1463,13 @@ set_netsvctype_dscp_map(size_t in_count, case NET_SERVICE_TYPE_AV: case NET_SERVICE_TYPE_OAM: case NET_SERVICE_TYPE_RD: { - int sotcix; + size_t sotcix; sotcix = sotc_index(sotc_by_netservicetype[netsvctype]); - net_qos_dscp_map->sotc_to_dscp[sotcix] = - netsvctype_dscp_map[netsvctype].dscp; + if (sotcix != SIZE_T_MAX) { + net_qos_dscp_map->sotc_to_dscp[sotcix] = + netsvctype_dscp_map[netsvctype].dscp; + } break; } case NET_SERVICE_TYPE_SIG: @@ -1619,7 +1621,7 @@ set_packet_qos(struct mbuf *m, struct ifnet *ifp, boolean_t qos_allowed, * We still want to prioritize control traffic on the interface * so we do not change the mbuf service class for SO_TC_CTL */ - if (netsvctype != _NET_SERVICE_TYPE_UNSPEC && + if (IS_VALID_NET_SERVICE_TYPE(netsvctype) && netsvctype != NET_SERVICE_TYPE_BE) { dscp = default_net_qos_dscp_map.netsvctype_to_dscp[netsvctype]; @@ -1630,17 +1632,18 @@ set_packet_qos(struct mbuf *m, struct ifnet *ifp, boolean_t qos_allowed, if (sotc != SO_TC_CTL) m_set_service_class(m, MBUF_SC_BE); } - } else { + } else if (sotc != SO_TC_UNSPEC) { size_t sotcix = sotc_index(sotc); - - dscp = default_net_qos_dscp_map.sotc_to_dscp[sotcix]; - - if (qos_allowed == FALSE && sotc != SO_TC_BE && - sotc != SO_TC_BK && sotc != SO_TC_BK_SYS && - sotc != SO_TC_CTL) { - dscp = _DSCP_DF; - if (sotc != SO_TC_CTL) - m_set_service_class(m, MBUF_SC_BE); + if (sotcix != SIZE_T_MAX) { + dscp = default_net_qos_dscp_map.sotc_to_dscp[sotcix]; + + if (qos_allowed == FALSE && sotc != SO_TC_BE && + sotc != SO_TC_BK && sotc != SO_TC_BK_SYS && + sotc != SO_TC_CTL) { + dscp = _DSCP_DF; + if (sotc != SO_TC_CTL) + m_set_service_class(m, MBUF_SC_BE); + } } } if (net_qos_verbose != 0) diff --git a/bsd/netinet/ip_divert.c b/bsd/netinet/ip_divert.c index 4981eb25e..74efc18df 100644 --- a/bsd/netinet/ip_divert.c +++ b/bsd/netinet/ip_divert.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2016 Apple Inc. All rights reserved. + * Copyright (c) 2000-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -374,12 +374,16 @@ div_output(struct socket *so, struct mbuf *m, struct sockaddr_in *sin, /* Reinject packet into the system as incoming or outgoing */ if (!sin || sin->sin_addr.s_addr == 0) { - struct ip_out_args ipoa = - { IFSCOPE_NONE, { 0 }, IPOAF_SELECT_SRCIF, 0, SO_TC_UNSPEC, - _NET_SERVICE_TYPE_UNSPEC }; + struct ip_out_args ipoa; struct route ro; struct ip_moptions *imo; + bzero(&ipoa, sizeof(ipoa)); + ipoa.ipoa_boundif = IFSCOPE_NONE; + ipoa.ipoa_flags = IPOAF_SELECT_SRCIF; + ipoa.ipoa_sotc = SO_TC_UNSPEC; + ipoa.ipoa_netsvctype = _NET_SERVICE_TYPE_UNSPEC; + /* * Don't allow both user specified and setsockopt options, * and don't allow packet length sizes that will crash diff --git a/bsd/netinet/ip_icmp.c b/bsd/netinet/ip_icmp.c index ab1b0452e..e67b329ca 100644 --- a/bsd/netinet/ip_icmp.c +++ b/bsd/netinet/ip_icmp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2017 Apple Inc. All rights reserved. + * Copyright (c) 2000-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -263,7 +263,13 @@ icmp_error( (n = m_pullup(n, (oiphlen + sizeof(struct tcphdr)))) == NULL) goto freeit; + /* + * Reinit pointers derived from mbuf data pointer + * as things might have moved around with m_pullup + */ + oip = mtod(n, struct ip *); th = (struct tcphdr *)(void *)((caddr_t)oip + oiphlen); + if (th != ((struct tcphdr *)P2ROUNDDOWN(th, sizeof(u_int32_t)))) goto freeit; @@ -278,6 +284,13 @@ icmp_error( (n = m_pullup(n, (oiphlen + tcphlen))) == NULL) goto freeit; + /* + * Reinit pointers derived from mbuf data pointer + * as things might have moved around with m_pullup + */ + oip = mtod(n, struct ip *); + th = (struct tcphdr *)(void *)((caddr_t)oip + oiphlen); + icmpelen = max(tcphlen, min(icmp_datalen, (oip->ip_len - oiphlen))); } else @@ -919,9 +932,13 @@ icmp_send(struct mbuf *m, struct mbuf *opts) int hlen; struct icmp *icp; struct route ro; - struct ip_out_args ipoa = { IFSCOPE_NONE, { 0 }, - IPOAF_SELECT_SRCIF | IPOAF_BOUND_SRCADDR, 0, - SO_TC_UNSPEC, _NET_SERVICE_TYPE_UNSPEC }; + struct ip_out_args ipoa; + + bzero(&ipoa, sizeof(ipoa)); + ipoa.ipoa_boundif = IFSCOPE_NONE; + ipoa.ipoa_flags = IPOAF_SELECT_SRCIF | IPOAF_BOUND_SRCADDR; + ipoa.ipoa_sotc = SO_TC_UNSPEC; + ipoa.ipoa_netsvctype = _NET_SERVICE_TYPE_UNSPEC; if (!(m->m_pkthdr.pkt_flags & PKTF_LOOP) && m->m_pkthdr.rcvif != NULL) { ipoa.ipoa_boundif = m->m_pkthdr.rcvif->if_index; diff --git a/bsd/netinet/ip_input.c b/bsd/netinet/ip_input.c index 1298ab28e..97750ef57 100644 --- a/bsd/netinet/ip_input.c +++ b/bsd/netinet/ip_input.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2017 Apple Inc. All rights reserved. + * Copyright (c) 2000-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -3835,9 +3835,14 @@ ip_forward(struct mbuf *m, int srcrt, struct sockaddr_in *next_hop) n_long dest; struct in_addr pkt_dst; u_int32_t nextmtu = 0, len; - struct ip_out_args ipoa = { IFSCOPE_NONE, { 0 }, 0, 0, - SO_TC_UNSPEC, _NET_SERVICE_TYPE_UNSPEC }; + struct ip_out_args ipoa; struct ifnet *rcvifp = m->m_pkthdr.rcvif; + + bzero(&ipoa, sizeof(ipoa)); + ipoa.ipoa_boundif = IFSCOPE_NONE; + ipoa.ipoa_sotc = SO_TC_UNSPEC; + ipoa.ipoa_netsvctype = _NET_SERVICE_TYPE_UNSPEC; + #if IPSEC struct secpolicy *sp = NULL; int ipsecerror; diff --git a/bsd/netinet/kpi_ipfilter.c b/bsd/netinet/kpi_ipfilter.c index 2186c63ba..ea54abae4 100644 --- a/bsd/netinet/kpi_ipfilter.c +++ b/bsd/netinet/kpi_ipfilter.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2017 Apple Inc. All rights reserved. + * Copyright (c) 2004-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -333,8 +333,12 @@ ipf_injectv4_out(mbuf_t data, ipfilter_t filter_ref, ipf_pktopts_t options) errno_t error = 0; struct m_tag *mtag = NULL; struct ip_moptions *imo = NULL; - struct ip_out_args ipoa = { IFSCOPE_NONE, { 0 }, 0, 0, - SO_TC_UNSPEC, _NET_SERVICE_TYPE_UNSPEC }; + struct ip_out_args ipoa; + + bzero(&ipoa, sizeof(ipoa)); + ipoa.ipoa_boundif = IFSCOPE_NONE; + ipoa.ipoa_sotc = SO_TC_UNSPEC; + ipoa.ipoa_netsvctype = _NET_SERVICE_TYPE_UNSPEC; /* Make the IP header contiguous in the mbuf */ if ((size_t)m->m_len < sizeof (struct ip)) { @@ -410,8 +414,12 @@ ipf_injectv6_out(mbuf_t data, ipfilter_t filter_ref, ipf_pktopts_t options) errno_t error = 0; struct m_tag *mtag = NULL; struct ip6_moptions *im6o = NULL; - struct ip6_out_args ip6oa = { IFSCOPE_NONE, { 0 }, 0, 0, - SO_TC_UNSPEC, _NET_SERVICE_TYPE_UNSPEC }; + struct ip6_out_args ip6oa; + + bzero(&ip6oa, sizeof(ip6oa)); + ip6oa.ip6oa_boundif = IFSCOPE_NONE; + ip6oa.ip6oa_sotc = SO_TC_UNSPEC; + ip6oa.ip6oa_netsvctype = _NET_SERVICE_TYPE_UNSPEC; /* Make the IP header contiguous in the mbuf */ if ((size_t)m->m_len < sizeof(struct ip6_hdr)) { diff --git a/bsd/netinet/mp_pcb.c b/bsd/netinet/mp_pcb.c index 288f29c71..254e2a167 100644 --- a/bsd/netinet/mp_pcb.c +++ b/bsd/netinet/mp_pcb.c @@ -335,7 +335,7 @@ mp_getsockaddr(struct socket *mp_so, struct sockaddr **nam) if (mpte->mpte_src.sa_family == AF_INET || mpte->mpte_src.sa_family == 0) return mp_getaddr_v4(mp_so, nam, false); - else if (mpte->mpte_src.sa_family == AF_INET) + else if (mpte->mpte_src.sa_family == AF_INET6) return mp_getaddr_v6(mp_so, nam, false); else return (EINVAL); @@ -348,7 +348,7 @@ mp_getpeeraddr(struct socket *mp_so, struct sockaddr **nam) if (mpte->mpte_src.sa_family == AF_INET || mpte->mpte_src.sa_family == 0) return mp_getaddr_v4(mp_so, nam, true); - else if (mpte->mpte_src.sa_family == AF_INET) + else if (mpte->mpte_src.sa_family == AF_INET6) return mp_getaddr_v6(mp_so, nam, true); else return (EINVAL); diff --git a/bsd/netinet/mptcp.c b/bsd/netinet/mptcp.c index 8cf437f64..55829e0a1 100644 --- a/bsd/netinet/mptcp.c +++ b/bsd/netinet/mptcp.c @@ -383,11 +383,30 @@ mptcp_input(struct mptses *mpte, struct mbuf *m) fallback: mptcp_sbrcv_grow(mp_tp); - for (iter = m; iter; iter = iter->m_next) { + iter = m; + while (iter) { if ((iter->m_flags & M_PKTHDR) && (iter->m_pkthdr.pkt_flags & PKTF_MPTCP_DFIN)) { mb_dfin = 1; - break; + } + + if ((iter->m_flags & M_PKTHDR) && m_pktlen(iter) == 0) { + /* Don't add zero-length packets, so jump it! */ + if (prev == NULL) { + m = iter->m_next; + m_free(iter); + iter = m; + } else { + prev->m_next = iter->m_next; + m_free(iter); + iter = prev->m_next; + } + + /* It was a zero-length packet so next one must be a pkthdr */ + VERIFY(iter == NULL || iter->m_flags & M_PKTHDR); + } else { + prev = iter; + iter = iter->m_next; } } @@ -547,15 +566,15 @@ mptcp_input(struct mptses *mpte, struct mbuf *m) sorwakeup(mp_so); } -static boolean_t -mptcp_can_send_more(struct mptcb *mp_tp) +boolean_t +mptcp_can_send_more(struct mptcb *mp_tp, boolean_t ignore_reinject) { struct socket *mp_so = mptetoso(mp_tp->mpt_mpte); /* * Always send if there is data in the reinject-queue. */ - if (mp_tp->mpt_mpte->mpte_reinjectq) + if (!ignore_reinject && mp_tp->mpt_mpte->mpte_reinjectq) return (TRUE); /* @@ -611,7 +630,7 @@ mptcp_output(struct mptses *mpte) MPTCP_SENDER_DBG, MPTCP_LOGLVL_VERBOSE); old_snd_nxt = mp_tp->mpt_sndnxt; - while (mptcp_can_send_more(mp_tp)) { + while (mptcp_can_send_more(mp_tp, FALSE)) { /* get the "best" subflow to be used for transmission */ mpts = mptcp_get_subflow(mpte, NULL, &preferred_mpts); if (mpts == NULL) { @@ -667,9 +686,10 @@ mptcp_output(struct mptses *mpte) mpts->mpts_flags |= MPTSF_FAILINGOVER; mpts->mpts_flags &= ~MPTSF_ACTIVE; mpts_tried = mpts; - mptcplog((LOG_ERR, "%s: Error = %d mpts_flags %#x\n", __func__, - error, mpts->mpts_flags), - MPTCP_SENDER_DBG, MPTCP_LOGLVL_ERR); + if (error != ECANCELED) + mptcplog((LOG_ERR, "%s: Error = %d mpts_flags %#x\n", __func__, + error, mpts->mpts_flags), + MPTCP_SENDER_DBG, MPTCP_LOGLVL_ERR); break; } /* The model is to have only one active flow at a time */ @@ -710,6 +730,12 @@ mptcp_output(struct mptses *mpte) } } + if (mp_tp->mpt_state > MPTCPS_CLOSE_WAIT) { + if (mp_tp->mpt_sndnxt + 1 == mp_tp->mpt_sndmax && + mp_tp->mpt_snduna == mp_tp->mpt_sndnxt) + mptcp_finish_usrclosed(mpte); + } + mptcp_handle_deferred_upcalls(mpte->mpte_mppcb, MPP_WUPCALL); /* subflow errors should not be percolated back up */ @@ -1010,7 +1036,7 @@ mptcp_close_fsm(struct mptcb *mp_tp, uint32_t event) switch (mp_tp->mpt_state) { case MPTCPS_CLOSED: case MPTCPS_LISTEN: - mp_tp->mpt_state = MPTCPS_CLOSED; + mp_tp->mpt_state = MPTCPS_TERMINATE; break; case MPTCPS_ESTABLISHED: @@ -1226,7 +1252,7 @@ mptcp_input_csum(struct tcpcb *tp, struct mbuf *m, uint64_t dsn, uint32_t sseq, uint32_t mptcp_output_csum(struct mbuf *m, uint64_t dss_val, uint32_t sseq, uint16_t dlen) { - u_int32_t sum = 0; + uint32_t sum = 0; if (dlen) sum = m_sum16(m, 0, dlen); @@ -1314,13 +1340,14 @@ mptcp_handle_deferred_upcalls(struct mppcb *mpp, uint32_t flag) } } -static void +void mptcp_ask_for_nat64(struct ifnet *ifp) { in6_post_msg(ifp, KEV_INET6_REQUEST_NAT64_PREFIX, NULL, NULL); - mptcplog((LOG_DEBUG, "%s: asked for NAT64-prefix on %s\n", - __func__, ifp->if_name), MPTCP_SOCKET_DBG, MPTCP_LOGLVL_VERBOSE); + os_log_info(mptcp_log_handle, + "%s: asked for NAT64-prefix on %s\n", __func__, + ifp->if_name); } static void @@ -1344,11 +1371,6 @@ mptcp_session_necp_cb(void *handle, int action, struct necp_client_flow *flow) ifindex = flow->interface_index; VERIFY(ifindex != IFSCOPE_NONE); - /* ToDo - remove after rdar://problem/32007628 */ - if (!IF_INDEX_IN_RANGE(ifindex)) - printf("%s 1 ifindex %u not in range of flow %p action %d\n", - __func__, ifindex, flow, action); - /* About to be garbage-collected (see note about MPTCP/NECP interactions) */ if (mp->mpp_socket->so_usecount == 0) return; @@ -1362,12 +1384,13 @@ mptcp_session_necp_cb(void *handle, int action, struct necp_client_flow *flow) goto out; } + mpte_lock_assert_held(mpte); + mp_tp = mpte->mpte_mptcb; mp_so = mptetoso(mpte); - mptcplog((LOG_DEBUG, "%s, action: %u ifindex %u usecount %u mpt_flags %#x state %u\n", - __func__, action, ifindex, mp->mpp_socket->so_usecount, mp_tp->mpt_flags, mp_tp->mpt_state), - MPTCP_SOCKET_DBG, MPTCP_LOGLVL_VERBOSE); + os_log_debug(mptcp_log_handle, "%s, action: %u ifindex %u usecount %u mpt_flags %#x state %u\n", + __func__, action, ifindex, mp->mpp_socket->so_usecount, mp_tp->mpt_flags, mp_tp->mpt_state); /* No need on fallen back sockets */ if (mp_tp->mpt_flags & MPTCPF_FALLBACK_TO_TCP) @@ -1382,23 +1405,15 @@ mptcp_session_necp_cb(void *handle, int action, struct necp_client_flow *flow) mptcp_sched_create_subflows(mpte); } else if (action == NECP_CLIENT_CBACTION_VIABLE || action == NECP_CLIENT_CBACTION_INITIAL) { - int found_empty = 0, empty_index = -1; + int found_slot = 0, slot_index = -1; + boolean_t has_v4 = !!(flow->necp_flow_flags & NECP_CLIENT_RESULT_FLAG_HAS_IPV4); + boolean_t has_v6 = !!(flow->necp_flow_flags & NECP_CLIENT_RESULT_FLAG_HAS_IPV6); struct ifnet *ifp; - /* ToDo - remove after rdar://problem/32007628 */ - if (!IF_INDEX_IN_RANGE(ifindex)) - printf("%s 2 ifindex %u not in range of flow %p action %d\n", - __func__, ifindex, flow, action); - ifnet_head_lock_shared(); ifp = ifindex2ifnet[ifindex]; ifnet_head_done(); - /* ToDo - remove after rdar://problem/32007628 */ - if (!IF_INDEX_IN_RANGE(ifindex)) - printf("%s 3 ifindex %u not in range of flow %p action %d\n", - __func__, ifindex, flow, action); - if (ifp == NULL) goto out; @@ -1410,14 +1425,31 @@ mptcp_session_necp_cb(void *handle, int action, struct necp_client_flow *flow) (mp_so->so_restrictions & SO_RESTRICT_DENY_CELLULAR)) goto out; + /* Look for the slot on where to store/update the interface-info. */ for (i = 0; i < mpte->mpte_itfinfo_size; i++) { + /* Found a potential empty slot where we can put it */ if (mpte->mpte_itfinfo[i].ifindex == 0) { - found_empty = 1; - empty_index = i; + found_slot = 1; + slot_index = i; + } + + /* + * The interface is already in our array. Check if we + * need to update it. + */ + if (mpte->mpte_itfinfo[i].ifindex == ifindex && + (mpte->mpte_itfinfo[i].has_v4_conn != has_v4 || + mpte->mpte_itfinfo[i].has_v6_conn != has_v6)) { + found_slot = 1; + slot_index = i; + break; } if (mpte->mpte_itfinfo[i].ifindex == ifindex) { - /* Ok, it's already there */ + /* + * Ok, it's already there and we don't need + * to update it + */ goto out; } } @@ -1429,7 +1461,7 @@ mptcp_session_necp_cb(void *handle, int action, struct necp_client_flow *flow) goto out; } - if (found_empty == 0) { + if (found_slot == 0) { int new_size = mpte->mpte_itfinfo_size * 2; struct mpt_itf_info *info = _MALLOC(sizeof(*info) * new_size, M_TEMP, M_ZERO); @@ -1445,7 +1477,7 @@ mptcp_session_necp_cb(void *handle, int action, struct necp_client_flow *flow) _FREE(mpte->mpte_itfinfo, M_TEMP); /* We allocated a new one, thus the first must be empty */ - empty_index = mpte->mpte_itfinfo_size; + slot_index = mpte->mpte_itfinfo_size; mpte->mpte_itfinfo = info; mpte->mpte_itfinfo_size = new_size; @@ -1454,10 +1486,10 @@ mptcp_session_necp_cb(void *handle, int action, struct necp_client_flow *flow) MPTCP_SOCKET_DBG, MPTCP_LOGLVL_VERBOSE); } - VERIFY(empty_index >= 0 && empty_index < (int)mpte->mpte_itfinfo_size); - mpte->mpte_itfinfo[empty_index].ifindex = ifindex; - mpte->mpte_itfinfo[empty_index].has_v4_conn = !!(flow->necp_flow_flags & NECP_CLIENT_RESULT_FLAG_HAS_IPV4); - mpte->mpte_itfinfo[empty_index].has_v6_conn = !!(flow->necp_flow_flags & NECP_CLIENT_RESULT_FLAG_HAS_IPV6); + VERIFY(slot_index >= 0 && slot_index < (int)mpte->mpte_itfinfo_size); + mpte->mpte_itfinfo[slot_index].ifindex = ifindex; + mpte->mpte_itfinfo[slot_index].has_v4_conn = has_v4; + mpte->mpte_itfinfo[slot_index].has_v6_conn = has_v6; mptcp_sched_create_subflows(mpte); } diff --git a/bsd/netinet/mptcp_opt.c b/bsd/netinet/mptcp_opt.c index 40007851a..6da8235e8 100644 --- a/bsd/netinet/mptcp_opt.c +++ b/bsd/netinet/mptcp_opt.c @@ -459,6 +459,8 @@ mptcp_setup_opts(struct tcpcb *tp, int32_t off, u_char *opt, if (sndfin) { \ dsn_opt.mdss_copt.mdss_flags |= MDSS_F; \ dsn_opt.mdss_data_len += 1; \ + if (do_csum) \ + dss_csum = in_addword(dss_csum, 1); \ } \ } @@ -755,12 +757,24 @@ mptcp_setup_opts(struct tcpcb *tp, int32_t off, u_char *opt, } if (tp->t_mpflags & TMPF_SEND_DFIN) { + unsigned int dssoptlen = sizeof(struct mptcp_dss_ack_opt); struct mptcp_dss_ack_opt dss_ack_opt; - unsigned int dssoptlen = sizeof (struct mptcp_dss_ack_opt); + uint16_t dss_csum; + + if (do_csum) { + uint64_t dss_val = mptcp_hton64(mp_tp->mpt_sndmax - 1); + uint16_t dlen = htons(1); + uint32_t sseq = 0; + uint32_t sum; + - if (do_csum) dssoptlen += 2; + sum = in_pseudo64(dss_val, sseq, dlen); + ADDCARRY(sum); + dss_csum = ~sum & 0xffff; + } + CHECK_OPTLEN; bzero(&dss_ack_opt, sizeof (dss_ack_opt)); @@ -769,7 +783,7 @@ mptcp_setup_opts(struct tcpcb *tp, int32_t off, u_char *opt, * Data FIN occupies one sequence space. * Don't send it if it has been Acked. */ - if (((mp_tp->mpt_sndnxt + 1) != mp_tp->mpt_sndmax) || + if ((mp_tp->mpt_sndnxt + 1 != mp_tp->mpt_sndmax) || (mp_tp->mpt_snduna == mp_tp->mpt_sndmax)) goto ret_optlen; @@ -780,11 +794,14 @@ mptcp_setup_opts(struct tcpcb *tp, int32_t off, u_char *opt, dss_ack_opt.mdss_ack = htonl(MPTCP_DATAACK_LOW32(mp_tp->mpt_rcvnxt)); dss_ack_opt.mdss_dsn = - htonl(MPTCP_DATASEQ_LOW32(mp_tp->mpt_sndnxt)); + htonl(MPTCP_DATASEQ_LOW32(mp_tp->mpt_sndmax - 1)); dss_ack_opt.mdss_subflow_seqn = 0; dss_ack_opt.mdss_data_len = 1; dss_ack_opt.mdss_data_len = htons(dss_ack_opt.mdss_data_len); memcpy(opt + optlen, &dss_ack_opt, sizeof (dss_ack_opt)); + if (do_csum) + *((uint16_t *)(void *)(opt + optlen + sizeof (dss_ack_opt))) = dss_csum; + optlen += dssoptlen; } @@ -937,7 +954,6 @@ mptcp_do_mpcapable_opt(struct tcpcb *tp, u_char *cp, struct tcphdr *th, } tcp_heuristic_mptcp_success(tp); tp->t_mpflags |= (TMPF_SND_KEYS | TMPF_MPTCP_TRUE); - tp->t_inpcb->inp_socket->so_flags |= SOF_MPTCP_TRUE; } @@ -1021,9 +1037,7 @@ mptcp_validate_join_hmac(struct tcpcb *tp, u_char* hmac, int mac_len) void mptcp_data_ack_rcvd(struct mptcb *mp_tp, struct tcpcb *tp, u_int64_t full_dack) { - u_int64_t acked = 0; - - acked = full_dack - mp_tp->mpt_snduna; + u_int64_t acked = full_dack - mp_tp->mpt_snduna; if (acked) { struct socket *mp_so = mptetoso(mp_tp->mpt_mpte); diff --git a/bsd/netinet/mptcp_subr.c b/bsd/netinet/mptcp_subr.c index 590fa2c46..a4a61beb2 100644 --- a/bsd/netinet/mptcp_subr.c +++ b/bsd/netinet/mptcp_subr.c @@ -189,6 +189,11 @@ SYSCTL_INT(_net_inet_mptcp, OID_AUTO, dbg_level, CTLFLAG_RW | CTLFLAG_LOCKED, SYSCTL_UINT(_net_inet_mptcp, OID_AUTO, pcbcount, CTLFLAG_RD|CTLFLAG_LOCKED, &mtcbinfo.mppi_count, 0, "Number of active PCBs"); + +static int mptcp_alternate_port = 0; +SYSCTL_INT(_net_inet_mptcp, OID_AUTO, alternate_port, CTLFLAG_RW | CTLFLAG_LOCKED, + &mptcp_alternate_port, 0, "Set alternate port for MPTCP connections"); + static struct protosw mptcp_subflow_protosw; static struct pr_usrreqs mptcp_subflow_usrreqs; #if INET6 @@ -270,6 +275,8 @@ static mptsub_ev_entry_t mpsub_ev_entry_tbl [] = { }, }; +os_log_t mptcp_log_handle; + /* * Protocol pr_init callback. */ @@ -392,6 +399,8 @@ mptcp_init(struct protosw *pp, struct domain *dp) zone_change(mpt_subauth_zone, Z_EXPAND, TRUE); mptcp_last_cellicon_set = tcp_now; + + mptcp_log_handle = os_log_create("com.apple.xnu.net.mptcp", "mptcp"); } int @@ -490,6 +499,9 @@ mptcp_sescreate(struct mppcb *mpp) mpte->mpte_itfinfo = &mpte->_mpte_itfinfo[0]; mpte->mpte_itfinfo_size = MPTE_ITFINFO_SIZE; + if (mptcp_alternate_port) + mpte->mpte_alternate_port = htons(mptcp_alternate_port); + /* MPTCP Protocol Control Block */ bzero(mp_tp, sizeof (*mp_tp)); mp_tp->mpt_mpte = mpte; @@ -743,9 +755,9 @@ mptcp_synthesize_nat64(struct in6_addr *addr, uint32_t len, struct in_addr *addr panic("NAT64-prefix len is wrong: %u\n", len); } - mptcplog((LOG_DEBUG, "%s: nat64prefix-len %u synthesized %s\n", __func__, - len, inet_ntop(AF_INET6, (void *)addr, buf, sizeof(buf))), - MPTCP_SOCKET_DBG, MPTCP_LOGLVL_VERBOSE); + os_log_info(mptcp_log_handle, "%s: nat64prefix-len %u synthesized %s\n", + __func__, len, + inet_ntop(AF_INET6, (void *)addr, buf, sizeof(buf))); return (0); } @@ -781,7 +793,8 @@ mptcp_check_subflows_and_add(struct mptses *mpte) continue; if (ifp->if_index == ifindex && - !(mpts->mpts_socket->so_state & SS_ISDISCONNECTED)) { + !(mpts->mpts_socket->so_state & SS_ISDISCONNECTED) && + sototcpcb(mpts->mpts_socket)->t_state != TCPS_CLOSED) { /* * We found a subflow on this interface. * No need to create a new one. @@ -881,6 +894,17 @@ mptcp_check_subflows_and_add(struct mptses *mpte) dst = (struct sockaddr *)&nat64pre; } + /* Initial subflow started on a NAT64'd address? */ + if (mpte->mpte_dst.sa_family == AF_INET6 && + mpte->mpte_dst_v4_nat64.sin_family == AF_INET) { + dst = (struct sockaddr *)&mpte->mpte_dst_v4_nat64; + } + + if (dst->sa_family == AF_INET && !info->has_v4_conn) + continue; + if (dst->sa_family == AF_INET6 && !info->has_v6_conn) + continue; + mptcp_subflow_add(mpte, NULL, dst, ifindex, NULL); } } @@ -1525,12 +1549,29 @@ mptcp_subflow_soconnectx(struct mptses *mpte, struct mptsub *mpts) struct mptcb *mp_tp; struct sockaddr *dst; struct proc *p; - int af, error; - - mpte_lock_assert_held(mpte); /* same as MP socket lock */ + int af, error, dport; mp_so = mptetoso(mpte); mp_tp = mpte->mpte_mptcb; + so = mpts->mpts_socket; + af = mpts->mpts_dst.sa_family; + dst = &mpts->mpts_dst; + + VERIFY((mpts->mpts_flags & (MPTSF_CONNECTING|MPTSF_CONNECTED)) == MPTSF_CONNECTING); + VERIFY(mpts->mpts_socket != NULL); + VERIFY(af == AF_INET || af == AF_INET6); + + if (af == AF_INET) { + inet_ntop(af, &SIN(dst)->sin_addr.s_addr, dbuf, sizeof (dbuf)); + dport = ntohs(SIN(dst)->sin_port); + } else { + inet_ntop(af, &SIN6(dst)->sin6_addr, dbuf, sizeof (dbuf)); + dport = ntohs(SIN6(dst)->sin6_port); + } + + os_log_info(mptcp_log_handle, + "%s: ifindex %u dst %s:%d pended %u\n", __func__, mpts->mpts_ifscope, + dbuf, dport, !!(mpts->mpts_flags & MPTSF_CONNECT_PENDING)); p = proc_find(mp_so->last_pid); if (p == PROC_NULL) { @@ -1540,24 +1581,6 @@ mptcp_subflow_soconnectx(struct mptses *mpte, struct mptsub *mpts) return (ESRCH); } - so = mpts->mpts_socket; - af = mpts->mpts_dst.sa_family; - - VERIFY((mpts->mpts_flags & (MPTSF_CONNECTING|MPTSF_CONNECTED)) == MPTSF_CONNECTING); - VERIFY(mpts->mpts_socket != NULL); - VERIFY(af == AF_INET || af == AF_INET6); - - dst = &mpts->mpts_dst; - mptcplog((LOG_DEBUG, "%s: connectx mp_so 0x%llx dst %s[%d] cid %d [pended %s]\n", - __func__, (u_int64_t)VM_KERNEL_ADDRPERM(mp_so), - inet_ntop(af, ((af == AF_INET) ? (void *)&SIN(dst)->sin_addr.s_addr : - (void *)&SIN6(dst)->sin6_addr), - dbuf, sizeof (dbuf)), - ((af == AF_INET) ? ntohs(SIN(dst)->sin_port) : ntohs(SIN6(dst)->sin6_port)), - mpts->mpts_connid, - ((mpts->mpts_flags & MPTSF_CONNECT_PENDING) ? "YES" : "NO")), - MPTCP_SOCKET_DBG, MPTCP_LOGLVL_VERBOSE); - mpts->mpts_flags &= ~MPTSF_CONNECT_PENDING; mptcp_attach_to_subf(so, mpte->mpte_mptcb, mpte->mpte_addrid_last); @@ -2243,7 +2266,7 @@ mptcp_subflow_disconnect(struct mptses *mpte, struct mptsub *mpts) if (!(so->so_state & (SS_ISDISCONNECTING | SS_ISDISCONNECTED)) && (so->so_state & SS_ISCONNECTED)) { - mptcplog((LOG_DEBUG, "MPTCP Socket %s: cid %d fin %d\n", + mptcplog((LOG_DEBUG, "%s: cid %d fin %d\n", __func__, mpts->mpts_connid, send_dfin), MPTCP_SOCKET_DBG, MPTCP_LOGLVL_VERBOSE); @@ -2400,6 +2423,27 @@ mptcp_subflow_wupcall(struct socket *so, void *arg, int waitf) mptcp_output(mpte); } +static boolean_t +mptcp_search_seq_in_sub(struct mbuf *m, struct socket *so) +{ + struct mbuf *so_m = so->so_snd.sb_mb; + uint64_t dsn = m->m_pkthdr.mp_dsn; + + while (so_m) { + VERIFY(so_m->m_flags & M_PKTHDR); + VERIFY(so_m->m_pkthdr.pkt_flags & PKTF_MPTCP); + + /* Part of the segment is covered, don't reinject here */ + if (so_m->m_pkthdr.mp_dsn <= dsn && + so_m->m_pkthdr.mp_dsn + so_m->m_pkthdr.mp_rlen > dsn) + return TRUE; + + so_m = so_m->m_next; + } + + return FALSE; +} + /* * Subflow socket output. * @@ -2467,9 +2511,14 @@ mptcp_subflow_output(struct mptses *mpte, struct mptsub *mpts, int flags) sb_mb = mp_so->so_snd.sb_mb; if (sb_mb == NULL) { - mptcplog((LOG_ERR, "%s: No data in MPTCP-sendbuffer! smax %u snxt %u suna %u\n", - __func__, (uint32_t)mp_tp->mpt_sndmax, (uint32_t)mp_tp->mpt_sndnxt, (uint32_t)mp_tp->mpt_snduna), + mptcplog((LOG_ERR, "%s: No data in MPTCP-sendbuffer! smax %u snxt %u suna %u state %u flags %#x\n", + __func__, (uint32_t)mp_tp->mpt_sndmax, (uint32_t)mp_tp->mpt_sndnxt, + (uint32_t)mp_tp->mpt_snduna, mp_tp->mpt_state, mp_so->so_flags1), MPTCP_SENDER_DBG, MPTCP_LOGLVL_ERR); + + /* Fix it to prevent looping */ + if (MPTCP_SEQ_LT(mp_tp->mpt_sndnxt, mp_tp->mpt_snduna)) + mp_tp->mpt_sndnxt = mp_tp->mpt_snduna; goto out; } @@ -2545,6 +2594,7 @@ mptcp_subflow_output(struct mptses *mpte, struct mptsub *mpts, int flags) if (mpte->mpte_reinjectq) sb_mb = mpte->mpte_reinjectq; else +dont_reinject: sb_mb = mp_so->so_snd.sb_mb; if (sb_mb == NULL) { mptcplog((LOG_ERR, "%s send-buffer is still empty\n", __func__), @@ -2552,8 +2602,20 @@ mptcp_subflow_output(struct mptses *mpte, struct mptsub *mpts, int flags) goto out; } - if (mpte->mpte_reinjectq) { + if (sb_mb == mpte->mpte_reinjectq) { sb_cc = sb_mb->m_pkthdr.mp_rlen; + off = 0; + + if (mptcp_search_seq_in_sub(sb_mb, so)) { + if (mptcp_can_send_more(mp_tp, TRUE)) { + goto dont_reinject; + } + + error = ECANCELED; + goto out; + } + + reinjected = TRUE; } else if (flags & MPTCP_SUBOUT_PROBING) { sb_cc = sb_mb->m_pkthdr.mp_rlen; off = 0; @@ -2593,13 +2655,13 @@ mptcp_subflow_output(struct mptses *mpte, struct mptsub *mpts, int flags) * Create a DSN mapping for the data we are about to send. It all * has the same mapping. */ - if (mpte->mpte_reinjectq) + if (reinjected) mpt_dsn = sb_mb->m_pkthdr.mp_dsn; else mpt_dsn = mp_tp->mpt_snduna + off; mpt_mbuf = sb_mb; - while (mpt_mbuf && mpte->mpte_reinjectq == NULL && + while (mpt_mbuf && reinjected == FALSE && (mpt_mbuf->m_pkthdr.mp_rlen == 0 || mpt_mbuf->m_pkthdr.mp_rlen <= (uint32_t)off)) { off -= mpt_mbuf->m_pkthdr.mp_rlen; @@ -2665,9 +2727,7 @@ mptcp_subflow_output(struct mptses *mpte, struct mptsub *mpts, int flags) mpt_mbuf = mpt_mbuf->m_next; } - if (mpte->mpte_reinjectq) { - reinjected = TRUE; - + if (reinjected) { if (sb_cc < sb_mb->m_pkthdr.mp_rlen) { struct mbuf *n = sb_mb; @@ -3022,7 +3082,7 @@ mptcp_clean_reinjectq(struct mptses *mpte) struct mbuf *m = mpte->mpte_reinjectq; if (MPTCP_SEQ_GEQ(m->m_pkthdr.mp_dsn, mp_tp->mpt_snduna) || - MPTCP_SEQ_GEQ(m->m_pkthdr.mp_dsn + m->m_pkthdr.mp_rlen, mp_tp->mpt_snduna)) + MPTCP_SEQ_GT(m->m_pkthdr.mp_dsn + m->m_pkthdr.mp_rlen, mp_tp->mpt_snduna)) break; mpte->mpte_reinjectq = m->m_nextpkt; @@ -3318,6 +3378,89 @@ mptcp_subflow_ifdenied_ev(struct mptses *mpte, struct mptsub *mpts, return (MPTS_EVRET_DELETE); } +/* + * https://tools.ietf.org/html/rfc6052#section-2 + * https://tools.ietf.org/html/rfc6147#section-5.2 + */ +static boolean_t +mptcp_desynthesize_ipv6_addr(const struct in6_addr *addr, + const struct ipv6_prefix *prefix, + struct in_addr *addrv4) +{ + char buf[MAX_IPv4_STR_LEN]; + char *ptrv4 = (char *)addrv4; + const char *ptr = (const char *)addr; + + if (memcmp(addr, &prefix->ipv6_prefix, prefix->prefix_len) != 0) + return false; + + switch (prefix->prefix_len) { + case NAT64_PREFIX_LEN_96: + memcpy(ptrv4, ptr + 12, 4); + break; + case NAT64_PREFIX_LEN_64: + memcpy(ptrv4, ptr + 9, 4); + break; + case NAT64_PREFIX_LEN_56: + memcpy(ptrv4, ptr + 7, 1); + memcpy(ptrv4 + 1, ptr + 9, 3); + break; + case NAT64_PREFIX_LEN_48: + memcpy(ptrv4, ptr + 6, 2); + memcpy(ptrv4 + 2, ptr + 9, 2); + break; + case NAT64_PREFIX_LEN_40: + memcpy(ptrv4, ptr + 5, 3); + memcpy(ptrv4 + 3, ptr + 9, 1); + break; + case NAT64_PREFIX_LEN_32: + memcpy(ptrv4, ptr + 4, 4); + break; + default: + panic("NAT64-prefix len is wrong: %u\n", + prefix->prefix_len); + } + + os_log_info(mptcp_log_handle, "%s desynthesized to %s\n", __func__, + inet_ntop(AF_INET, (void *)addrv4, buf, sizeof(buf))); + + return true; +} + +static void +mptcp_handle_ipv6_connection(struct mptses *mpte, const struct mptsub *mpts) +{ + struct ipv6_prefix nat64prefixes[NAT64_MAX_NUM_PREFIXES]; + struct socket *so = mpts->mpts_socket; + struct ifnet *ifp; + int j; + + ifp = sotoinpcb(so)->inp_last_outifp; + + if (ifnet_get_nat64prefix(ifp, nat64prefixes) == ENOENT) { + mptcp_ask_for_nat64(ifp); + return; + } + + + for (j = 0; j < NAT64_MAX_NUM_PREFIXES; j++) { + int success; + + if (nat64prefixes[j].prefix_len == 0) + continue; + + success = mptcp_desynthesize_ipv6_addr(&mpte->__mpte_dst_v6.sin6_addr, + &nat64prefixes[j], + &mpte->mpte_dst_v4_nat64.sin_addr); + if (success) { + mpte->mpte_dst_v4_nat64.sin_len = sizeof(mpte->mpte_dst_v4_nat64); + mpte->mpte_dst_v4_nat64.sin_family = AF_INET; + mpte->mpte_dst_v4_nat64.sin_port = mpte->__mpte_dst_v6.sin6_port; + break; + } + } +} + /* * Handle SO_FILT_HINT_CONNECTED subflow socket event. */ @@ -3422,6 +3565,8 @@ mptcp_subflow_connected_ev(struct mptses *mpte, struct mptsub *mpts, in6_getsockaddr_s(so, &mpte->__mpte_src_v6); } + mpts->mpts_flags |= MPTSF_ACTIVE; + /* case (a) above */ if (!mpok) { tcpstat.tcps_mpcap_fallback++; @@ -3435,11 +3580,12 @@ mptcp_subflow_connected_ev(struct mptses *mpte, struct mptsub *mpts, } else { mpts->mpts_flags |= MPTSF_PREFERRED; } - mpts->mpts_flags |= MPTSF_ACTIVE; - mpts->mpts_flags |= MPTSF_MPCAP_CTRSET; mpte->mpte_nummpcapflows++; + if (SOCK_DOM(so) == AF_INET6) + mptcp_handle_ipv6_connection(mpte, mpts); + mptcp_check_subflows_and_add(mpte); if (IFNET_IS_CELLULAR(inp->inp_last_outifp)) @@ -3482,13 +3628,26 @@ mptcp_subflow_connected_ev(struct mptses *mpte, struct mptsub *mpts, } else { unsigned int i; - /* Mark this interface as non-MPTCP */ - for (i = 0; i < mpte->mpte_itfinfo_size; i++) { - struct mpt_itf_info *info = &mpte->mpte_itfinfo[i]; + /* Should we try the alternate port? */ + if (mpte->mpte_alternate_port && + inp->inp_fport != mpte->mpte_alternate_port) { + union sockaddr_in_4_6 dst; + struct sockaddr_in *dst_in = (struct sockaddr_in *)&dst; - if (inp->inp_last_outifp->if_index == info->ifindex) { - info->no_mptcp_support = 1; - break; + memcpy(&dst, &mpts->mpts_dst, mpts->mpts_dst.sa_len); + + dst_in->sin_port = mpte->mpte_alternate_port; + + mptcp_subflow_add(mpte, NULL, (struct sockaddr *)&dst, + mpts->mpts_ifscope , NULL); + } else { /* Else, we tried all we could, mark this interface as non-MPTCP */ + for (i = 0; i < mpte->mpte_itfinfo_size; i++) { + struct mpt_itf_info *info = &mpte->mpte_itfinfo[i]; + + if (inp->inp_last_outifp->if_index == info->ifindex) { + info->no_mptcp_support = 1; + break; + } } } diff --git a/bsd/netinet/mptcp_timer.c b/bsd/netinet/mptcp_timer.c index 0f427e184..969ceddf8 100644 --- a/bsd/netinet/mptcp_timer.c +++ b/bsd/netinet/mptcp_timer.c @@ -82,8 +82,7 @@ mptcp_timer_demux(struct mptses *mpte, uint32_t now_msecs) break; if ((now_msecs - mp_tp->mpt_rxtstart) > (mptcp_rto*hz)) { - if (MPTCP_SEQ_GT(mp_tp->mpt_snduna, - mp_tp->mpt_rtseq)) { + if (MPTCP_SEQ_GT(mp_tp->mpt_snduna, mp_tp->mpt_rtseq)) { mp_tp->mpt_timer_vals = 0; mp_tp->mpt_rtseq = 0; break; @@ -94,10 +93,10 @@ mptcp_timer_demux(struct mptses *mpte, uint32_t now_msecs) DTRACE_MPTCP1(error, struct mptcb *, mp_tp); } else { mp_tp->mpt_sndnxt = mp_tp->mpt_rtseq; - mptcplog((LOG_DEBUG, "MPTCP Socket: " - "%s: REXMT %d times.\n", - __func__, mp_tp->mpt_rxtshift), - MPTCP_SOCKET_DBG, MPTCP_LOGLVL_LOG); + os_log_info(mptcp_log_handle, + "%s: REXMT %d sndnxt %u\n", + __func__, mp_tp->mpt_rxtshift, + (uint32_t)mp_tp->mpt_sndnxt); mptcp_output(mpte); } } else { diff --git a/bsd/netinet/mptcp_usrreq.c b/bsd/netinet/mptcp_usrreq.c index fb199c658..8749d1a0a 100644 --- a/bsd/netinet/mptcp_usrreq.c +++ b/bsd/netinet/mptcp_usrreq.c @@ -693,8 +693,7 @@ mptcp_disconnect(struct mptses *mpte) mp_so = mptetoso(mpte); mp_tp = mpte->mpte_mptcb; - mptcplog((LOG_DEBUG, "MPTCP Socket: " - "%s: mp_so 0x%llx %d\n", __func__, + mptcplog((LOG_DEBUG, "%s: mp_so 0x%llx %d\n", __func__, (u_int64_t)VM_KERNEL_ADDRPERM(mp_so), mp_so->so_error), MPTCP_SOCKET_DBG, MPTCP_LOGLVL_LOG); @@ -758,27 +757,19 @@ mptcp_usr_disconnectx(struct socket *mp_so, sae_associd_t aid, sae_connid_t cid) return (mptcp_usr_disconnect(mp_so)); } -/* - * User issued close, and wish to trail thru shutdown states. - */ -static struct mptses * -mptcp_usrclosed(struct mptses *mpte) +void +mptcp_finish_usrclosed(struct mptses *mpte) { - struct socket *mp_so; - struct mptcb *mp_tp; - struct mptsub *mpts; - - mpte_lock_assert_held(mpte); /* same as MP socket lock */ - mp_so = mptetoso(mpte); - mp_tp = mpte->mpte_mptcb; - - mptcp_close_fsm(mp_tp, MPCE_CLOSE); + struct mptcb *mp_tp = mpte->mpte_mptcb; + struct socket *mp_so = mptetoso(mpte); if (mp_tp->mpt_state == MPTCPS_CLOSED) { mpte = mptcp_close(mpte, mp_tp); } else if (mp_tp->mpt_state >= MPTCPS_FIN_WAIT_2) { soisdisconnected(mp_so); } else { + struct mptsub *mpts; + TAILQ_FOREACH(mpts, &mpte->mpte_subflows, mpts_entry) { if ((mp_so->so_state & (SS_CANTRCVMORE|SS_CANTSENDMORE)) == (SS_CANTRCVMORE | SS_CANTSENDMORE)) @@ -787,6 +778,23 @@ mptcp_usrclosed(struct mptses *mpte) mptcp_subflow_shutdown(mpte, mpts); } } +} + +/* + * User issued close, and wish to trail thru shutdown states. + */ +static struct mptses * +mptcp_usrclosed(struct mptses *mpte) +{ + struct mptcb *mp_tp = mpte->mpte_mptcb; + + mptcp_close_fsm(mp_tp, MPCE_CLOSE); + + /* Not everything has been acknowledged - don't close the subflows! */ + if (mp_tp->mpt_sndnxt + 1 != mp_tp->mpt_sndmax) + return (mpte); + + mptcp_finish_usrclosed(mpte); return (mpte); } @@ -1457,6 +1465,21 @@ mptcp_setopt(struct mptses *mpte, struct sockopt *sopt) mpte->mpte_flags |= MPTE_SVCTYPE_CHECKED; + goto out; + case MPTCP_ALTERNATE_PORT: + /* record at MPTCP level */ + error = sooptcopyin(sopt, &optval, sizeof(optval), + sizeof(optval)); + if (error) + goto out; + + if (optval < 0 || optval > UINT16_MAX) { + error = EINVAL; + goto out; + } + + mpte->mpte_alternate_port = optval; + goto out; default: /* not eligible */ @@ -1567,6 +1590,7 @@ mptcp_getopt(struct mptses *mpte, struct sockopt *sopt) case TCP_ADAPTIVE_WRITE_TIMEOUT: case TCP_NOTSENT_LOWAT: case MPTCP_SERVICE_TYPE: + case MPTCP_ALTERNATE_PORT: /* eligible; get the default value just in case */ error = mptcp_default_tcp_optval(mpte, sopt, &optval); break; @@ -1586,6 +1610,9 @@ mptcp_getopt(struct mptses *mpte, struct sockopt *sopt) case MPTCP_SERVICE_TYPE: optval = mpte->mpte_svctype; goto out; + case MPTCP_ALTERNATE_PORT: + optval = mpte->mpte_alternate_port; + goto out; } /* @@ -1634,6 +1661,7 @@ mptcp_default_tcp_optval(struct mptses *mpte, struct sockopt *sopt, int *optval) case TCP_ADAPTIVE_READ_TIMEOUT: case TCP_ADAPTIVE_WRITE_TIMEOUT: case MPTCP_SERVICE_TYPE: + case MPTCP_ALTERNATE_PORT: *optval = 0; break; @@ -1806,6 +1834,8 @@ mptcp_sopt2str(int level, int optname) return ("ADAPTIVE_WRITE_TIMEOUT"); case MPTCP_SERVICE_TYPE: return ("MPTCP_SERVICE_TYPE"); + case MPTCP_ALTERNATE_PORT: + return ("MPTCP_ALTERNATE_PORT"); } break; diff --git a/bsd/netinet/mptcp_var.h b/bsd/netinet/mptcp_var.h index 1ff155f54..d09642033 100644 --- a/bsd/netinet/mptcp_var.h +++ b/bsd/netinet/mptcp_var.h @@ -41,6 +41,7 @@ #include #include #include +#include struct mpt_itf_info { uint32_t ifindex; @@ -79,6 +80,10 @@ struct mptses { struct sockaddr_in6 __mpte_dst_v6; }; + struct sockaddr_in mpte_dst_v4_nat64; + + uint16_t mpte_alternate_port; /* Alternate port for subflow establishment (network-byte-order) */ + struct mptsub *mpte_active_sub; /* ptr to last active subf */ uint8_t mpte_flags; /* per mptcp session flags */ #define MPTE_SND_REM_ADDR 0x01 /* Send Remove_addr option */ @@ -481,6 +486,7 @@ SYSCTL_DECL(_net_inet_mptcp); extern struct mppcbinfo mtcbinfo; extern struct pr_usrreqs mptcp_usrreqs; +extern os_log_t mptcp_log_handle; /* Encryption algorithm related definitions */ #define SHA1_TRUNCATED 8 @@ -586,6 +592,7 @@ extern void mptcp_subflow_workloop(struct mptses *); extern void mptcp_sched_create_subflows(struct mptses *); +extern void mptcp_finish_usrclosed(struct mptses *mpte); extern struct mptopt *mptcp_sopt_alloc(int); extern const char *mptcp_sopt2str(int, int); extern void mptcp_sopt_free(struct mptopt *); @@ -609,6 +616,7 @@ extern int mptcp_subflow_sogetopt(struct mptses *, struct socket *, struct mptopt *); extern void mptcp_input(struct mptses *, struct mbuf *); +extern boolean_t mptcp_can_send_more(struct mptcb *mp_tp, boolean_t ignore_reinject); extern int mptcp_output(struct mptses *); extern void mptcp_close_fsm(struct mptcb *, uint32_t); @@ -645,6 +653,7 @@ extern int mptcp_notsent_lowat_check(struct socket *so); extern void mptcp_ask_symptoms(struct mptses *mpte); extern void mptcp_control_register(void); extern int mptcp_is_wifi_unusable(void); +extern void mptcp_ask_for_nat64(struct ifnet *ifp); extern void mptcp_session_necp_cb(void *, int, struct necp_client_flow *); extern void mptcp_set_restrictions(struct socket *mp_so); extern int mptcp_freeq(struct mptcb *); diff --git a/bsd/netinet/raw_ip.c b/bsd/netinet/raw_ip.c index cb4e31a22..30c5e8e33 100644 --- a/bsd/netinet/raw_ip.c +++ b/bsd/netinet/raw_ip.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2016 Apple Inc. All rights reserved. + * Copyright (c) 2000-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -355,13 +355,18 @@ rip_output( struct ip *ip; struct inpcb *inp = sotoinpcb(so); int flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST; - struct ip_out_args ipoa = - { IFSCOPE_NONE, { 0 }, IPOAF_SELECT_SRCIF, 0, 0, 0 }; + struct ip_out_args ipoa; struct ip_moptions *imo; int error = 0; + + bzero(&ipoa, sizeof(ipoa)); + ipoa.ipoa_boundif = IFSCOPE_NONE; + ipoa.ipoa_flags = IPOAF_SELECT_SRCIF; + int sotc = SO_TC_UNSPEC; int netsvctype = _NET_SERVICE_TYPE_UNSPEC; + if (control != NULL) { sotc = so_tc_from_control(control, &netsvctype); diff --git a/bsd/netinet/tcp.h b/bsd/netinet/tcp.h index d960c1f77..a51294468 100644 --- a/bsd/netinet/tcp.h +++ b/bsd/netinet/tcp.h @@ -297,6 +297,8 @@ struct tcp_notify_ack_complete { #define TCP_RXT_MINIMUM_TIMEOUT_LIMIT (5 * 60) /* Limit is 5 minutes */ +#define MPTCP_ALTERNATE_PORT 0x216 + /* * The TCP_INFO socket option is a private API and is subject to change */ diff --git a/bsd/netinet/tcp_cache.c b/bsd/netinet/tcp_cache.c index 293a0fc0c..d746db8c5 100644 --- a/bsd/netinet/tcp_cache.c +++ b/bsd/netinet/tcp_cache.c @@ -401,8 +401,9 @@ static void tcp_cache_set_cookie_common(struct tcp_cache_key_src *tcks, u_char * if (tpcache == NULL) return; - tpcache->tc_tfo_cookie_len = len; - memcpy(tpcache->tc_tfo_cookie, cookie, len); + tpcache->tc_tfo_cookie_len = len > TFO_COOKIE_LEN_MAX ? + TFO_COOKIE_LEN_MAX : len; + memcpy(tpcache->tc_tfo_cookie, cookie, tpcache->tc_tfo_cookie_len); tcp_cache_unlock(head); } diff --git a/bsd/netinet/tcp_input.c b/bsd/netinet/tcp_input.c index 139984932..216814cff 100644 --- a/bsd/netinet/tcp_input.c +++ b/bsd/netinet/tcp_input.c @@ -4120,7 +4120,6 @@ tcp_input(struct mbuf *m, int off0) ~TMPF_PREESTABLISHED; tp->t_mpflags |= TMPF_MPTCP_TRUE; - so->so_flags |= SOF_MPTCP_TRUE; mptcplog((LOG_DEBUG, "MPTCP " "Sockets: %s \n",__func__), MPTCP_SOCKET_DBG, @@ -4942,7 +4941,8 @@ tcp_input(struct mbuf *m, int off0) } } else { if ((so->so_flags & SOF_MP_SUBFLOW) && tlen == 0 && - (m->m_pkthdr.pkt_flags & PKTF_MPTCP_DFIN)) { + (m->m_pkthdr.pkt_flags & PKTF_MPTCP_DFIN) && + (m->m_pkthdr.pkt_flags & PKTF_MPTCP)) { m_adj(m, drop_hdrlen); /* delayed header drop */ mptcp_input(tptomptp(tp)->mpt_mpte, m); tp->t_flags |= TF_ACKNOW; @@ -5865,6 +5865,8 @@ tcp_mss(struct tcpcb *tp, int offer, unsigned int input_ifscope) } tp->t_maxseg = mss; + ASSERT(tp->t_maxseg); + /* * Update MSS using recommendation from link status report. This is * temporary @@ -6338,9 +6340,9 @@ tcp_getstat SYSCTL_HANDLER_ARGS proc_rele(caller_parent); } - if ((escape_str(command_name, strlen(command_name), + if ((escape_str(command_name, strlen(command_name) + 1, sizeof(command_name)) == 0) && - (escape_str(parent_name, strlen(parent_name), + (escape_str(parent_name, strlen(parent_name) + 1, sizeof(parent_name)) == 0)) { kern_asl_msg(LOG_DEBUG, "messagetracer", 5, diff --git a/bsd/netinet/tcp_output.c b/bsd/netinet/tcp_output.c index 88ced34e9..52884d357 100644 --- a/bsd/netinet/tcp_output.c +++ b/bsd/netinet/tcp_output.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2017 Apple Inc. All rights reserved. + * Copyright (c) 2000-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -1259,7 +1259,7 @@ tcp_output(struct tcpcb *tp) * space. So we have to be able to go backwards and announce a smaller * window. */ - if (!(so->so_flags & SOF_MPTCP_TRUE) && + if (!(so->so_flags & SOF_MP_SUBFLOW) && recwin < (int32_t)(tp->rcv_adv - tp->rcv_nxt)) recwin = (int32_t)(tp->rcv_adv - tp->rcv_nxt); @@ -2607,9 +2607,14 @@ tcp_output(struct tcpcb *tp) TCP_PKTLIST_CLEAR(tp); if (error == ENOBUFS) { + /* + * Set retransmit timer if not currently set + * when we failed to send a segment that can be + * retransmitted (i.e. not pure ack or rst) + */ if (!tp->t_timer[TCPT_REXMT] && !tp->t_timer[TCPT_PERSIST] && - (SEQ_GT(tp->snd_max, tp->snd_una) || + (len != 0 || (flags & (TH_SYN | TH_FIN)) != 0 || so->so_snd.sb_cc > 0)) tp->t_timer[TCPT_REXMT] = OFFSET_FROM_START(tp, tp->t_rxtcur); @@ -2677,16 +2682,25 @@ tcp_ip_output(struct socket *so, struct tcpcb *tp, struct mbuf *pkt, boolean_t unlocked = FALSE; boolean_t ifdenied = FALSE; struct inpcb *inp = tp->t_inpcb; - struct ip_out_args ipoa = - { IFSCOPE_NONE, { 0 }, IPOAF_SELECT_SRCIF|IPOAF_BOUND_SRCADDR, 0, - SO_TC_UNSPEC, _NET_SERVICE_TYPE_UNSPEC }; + struct ip_out_args ipoa; struct route ro; struct ifnet *outif = NULL; + + bzero(&ipoa, sizeof(ipoa)); + ipoa.ipoa_boundif = IFSCOPE_NONE; + ipoa.ipoa_flags = IPOAF_SELECT_SRCIF | IPOAF_BOUND_SRCADDR; + ipoa.ipoa_sotc = SO_TC_UNSPEC; + ipoa.ipoa_netsvctype = _NET_SERVICE_TYPE_UNSPEC; #if INET6 - struct ip6_out_args ip6oa = - { IFSCOPE_NONE, { 0 }, IP6OAF_SELECT_SRCIF|IP6OAF_BOUND_SRCADDR, 0, - SO_TC_UNSPEC, _NET_SERVICE_TYPE_UNSPEC }; + struct ip6_out_args ip6oa; struct route_in6 ro6; + + bzero(&ip6oa, sizeof(ip6oa)); + ip6oa.ip6oa_boundif = IFSCOPE_NONE; + ip6oa.ip6oa_flags = IP6OAF_SELECT_SRCIF | IP6OAF_BOUND_SRCADDR; + ip6oa.ip6oa_sotc = SO_TC_UNSPEC; + ip6oa.ip6oa_netsvctype = _NET_SERVICE_TYPE_UNSPEC; + struct flowadv *adv = (isipv6 ? &ip6oa.ip6oa_flowadv : &ipoa.ipoa_flowadv); #else /* INET6 */ diff --git a/bsd/netinet/tcp_subr.c b/bsd/netinet/tcp_subr.c index 2d6d4d1bf..363dea99f 100644 --- a/bsd/netinet/tcp_subr.c +++ b/bsd/netinet/tcp_subr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2017 Apple Inc. All rights reserved. + * Copyright (c) 2000-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -484,7 +484,8 @@ tcp_init(struct protosw *pp, struct domain *dp) /* expose initial uptime/now via systcl for utcp to keep time sync */ tcp_now_init = tcp_now; - tcp_microuptime_init = tcp_uptime.tv_sec * 1000 + tcp_uptime.tv_usec; + tcp_microuptime_init = + tcp_uptime.tv_usec + (tcp_uptime.tv_sec * USEC_PER_SEC); SYSCTL_SKMEM_UPDATE_FIELD(tcp.microuptime_init, tcp_microuptime_init); SYSCTL_SKMEM_UPDATE_FIELD(tcp.now_init, tcp_now_init); @@ -953,9 +954,12 @@ tcp_respond(struct tcpcb *tp, void *ipgen, struct tcphdr *th, struct mbuf *m, #if INET6 if (isipv6) { - struct ip6_out_args ip6oa = { tra->ifscope, { 0 }, - IP6OAF_SELECT_SRCIF | IP6OAF_BOUND_SRCADDR, 0, - SO_TC_UNSPEC, _NET_SERVICE_TYPE_UNSPEC}; + struct ip6_out_args ip6oa; + bzero(&ip6oa, sizeof(ip6oa)); + ip6oa.ip6oa_boundif = tra->ifscope; + ip6oa.ip6oa_flags = IP6OAF_SELECT_SRCIF | IP6OAF_BOUND_SRCADDR; + ip6oa.ip6oa_sotc = SO_TC_UNSPEC; + ip6oa.ip6oa_netsvctype = _NET_SERVICE_TYPE_UNSPEC; if (tra->ifscope != IFSCOPE_NONE) ip6oa.ip6oa_flags |= IP6OAF_BOUND_IF; @@ -987,9 +991,12 @@ tcp_respond(struct tcpcb *tp, void *ipgen, struct tcphdr *th, struct mbuf *m, } else #endif /* INET6 */ { - struct ip_out_args ipoa = { tra->ifscope, { 0 }, - IPOAF_SELECT_SRCIF | IPOAF_BOUND_SRCADDR, 0, - SO_TC_UNSPEC, _NET_SERVICE_TYPE_UNSPEC }; + struct ip_out_args ipoa; + bzero(&ipoa, sizeof(ipoa)); + ipoa.ipoa_boundif = tra->ifscope; + ipoa.ipoa_flags = IPOAF_SELECT_SRCIF | IPOAF_BOUND_SRCADDR; + ipoa.ipoa_sotc = SO_TC_UNSPEC; + ipoa.ipoa_netsvctype = _NET_SERVICE_TYPE_UNSPEC; if (tra->ifscope != IFSCOPE_NONE) ipoa.ipoa_flags |= IPOAF_BOUND_IF; @@ -2141,7 +2148,7 @@ tcp_get_ports_used(uint32_t ifindex, int protocol, uint32_t flags, { inpcb_get_ports_used(ifindex, protocol, flags, bitfield, &tcbinfo); -} + } __private_extern__ uint32_t tcp_count_opportunistic(unsigned int ifindex, u_int32_t flags) @@ -2672,6 +2679,8 @@ tcp_mtudisc( tp->t_maxseg = mss; + ASSERT(tp->t_maxseg); + /* * Reset the slow-start flight size as it may depends on the * new MSS diff --git a/bsd/netinet/tcp_timer.c b/bsd/netinet/tcp_timer.c index 2c861120e..417b61b89 100644 --- a/bsd/netinet/tcp_timer.c +++ b/bsd/netinet/tcp_timer.c @@ -842,6 +842,7 @@ tcp_pmtud_revert_segment_size(struct tcpcb *tp) optlen = tp->t_maxopd - tp->t_maxseg; tp->t_maxopd = tp->t_pmtud_saved_maxopd; tp->t_maxseg = tp->t_maxopd - optlen; + /* * Reset the slow-start flight size as it * may depend on the new MSS diff --git a/bsd/netinet/tcp_usrreq.c b/bsd/netinet/tcp_usrreq.c index 3c368cb52..1af338ade 100644 --- a/bsd/netinet/tcp_usrreq.c +++ b/bsd/netinet/tcp_usrreq.c @@ -412,15 +412,6 @@ tcp_connect_complete(struct socket *so) struct inpcb *inp = sotoinpcb(so); int error = 0; -#if NECP - /* Update NECP client with connected five-tuple */ - if (!uuid_is_null(inp->necp_client_uuid)) { - socket_unlock(so, 0); - necp_client_assign_from_socket(so->last_pid, inp->necp_client_uuid, inp); - socket_lock(so, 0); - } -#endif /* NECP */ - /* TFO delays the tcp_output until later, when the app calls write() */ if (so->so_flags1 & SOF1_PRECONNECT_DATA) { if (!necp_socket_is_allowed_to_send_recv(sotoinpcb(so), NULL, NULL)) @@ -433,6 +424,15 @@ tcp_connect_complete(struct socket *so) error = tcp_output(tp); } +#if NECP + /* Update NECP client with connected five-tuple */ + if (error == 0 && !uuid_is_null(inp->necp_client_uuid)) { + socket_unlock(so, 0); + necp_client_assign_from_socket(so->last_pid, inp->necp_client_uuid, inp); + socket_lock(so, 0); + } +#endif /* NECP */ + return (error); } @@ -601,6 +601,9 @@ tcp_usr_connectx_common(struct socket *so, int af, *pcid = 1; /* there is only one connection in regular TCP */ done: + if (error && error != EINPROGRESS) + so->so_flags1 &= ~SOF1_PRECONNECT_DATA; + inp->inp_flags2 &= ~INP2_CONNECT_IN_PROGRESS; return (error); } @@ -1784,9 +1787,9 @@ tcp_sysctl_info(__unused struct sysctl_oid *oidp, __unused void *arg1, __unused proc_rele(caller_parent); } - if ((escape_str(command_name, strlen(command_name), + if ((escape_str(command_name, strlen(command_name) + 1, sizeof(command_name)) == 0) && - (escape_str(parent_name, strlen(parent_name), + (escape_str(parent_name, strlen(parent_name) + 1, sizeof(parent_name)) == 0)) { kern_asl_msg(LOG_DEBUG, "messagetracer", 5, @@ -1838,30 +1841,30 @@ tcp_lookup_peer_pid_locked(struct socket *so, pid_t *out_pid) uint16_t lport = inp->inp_lport; uint16_t fport = inp->inp_fport; struct inpcb *finp = NULL; + struct in6_addr laddr6, faddr6; + struct in_addr laddr4, faddr4; if (inp->inp_vflag & INP_IPV6) { - struct in6_addr laddr6 = inp->in6p_laddr; - struct in6_addr faddr6 = inp->in6p_faddr; - socket_unlock(so, 0); + laddr6 = inp->in6p_laddr; + faddr6 = inp->in6p_faddr; + } else if (inp->inp_vflag & INP_IPV4) { + laddr4 = inp->inp_laddr; + faddr4 = inp->inp_faddr; + } + + socket_unlock(so, 0); + if (inp->inp_vflag & INP_IPV6) { finp = in6_pcblookup_hash(&tcbinfo, &laddr6, lport, &faddr6, fport, 0, NULL); - socket_lock(so, 0); } else if (inp->inp_vflag & INP_IPV4) { - struct in_addr laddr4 = inp->inp_laddr; - struct in_addr faddr4 = inp->inp_faddr; - socket_unlock(so, 0); finp = in_pcblookup_hash(&tcbinfo, laddr4, lport, faddr4, fport, 0, NULL); - socket_lock(so, 0); } if (finp) { *out_pid = finp->inp_socket->last_pid; error = 0; - /* Avoid deadlock due to same inpcb for loopback socket */ - if (inp == finp) - in_pcb_checkstate(finp, WNT_RELEASE, 1); - else - in_pcb_checkstate(finp, WNT_RELEASE, 0); + in_pcb_checkstate(finp, WNT_RELEASE, 0); } + socket_lock(so, 0); return error; } @@ -2758,10 +2761,10 @@ tcp_usrclosed(struct tcpcb *tp) case TCPS_CLOSED: case TCPS_LISTEN: + case TCPS_SYN_SENT: tp = tcp_close(tp); break; - case TCPS_SYN_SENT: case TCPS_SYN_RECEIVED: tp->t_flags |= TF_NEEDFIN; break; diff --git a/bsd/netinet/udp_usrreq.c b/bsd/netinet/udp_usrreq.c index 0c4945e79..a04bfcca4 100644 --- a/bsd/netinet/udp_usrreq.c +++ b/bsd/netinet/udp_usrreq.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2017 Apple Inc. All rights reserved. + * Copyright (c) 2000-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -1311,7 +1311,7 @@ udp_get_ports_used(uint32_t ifindex, int protocol, uint32_t flags, { inpcb_get_ports_used(ifindex, protocol, flags, bitfield, &udbinfo); -} + } __private_extern__ uint32_t udp_count_opportunistic(unsigned int ifindex, u_int32_t flags) @@ -1414,8 +1414,12 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr, struct mbuf *inpopts; struct ip_moptions *mopts; struct route ro; - struct ip_out_args ipoa = - { IFSCOPE_NONE, { 0 }, IPOAF_SELECT_SRCIF, 0, 0, 0 }; + struct ip_out_args ipoa; + + bzero(&ipoa, sizeof(ipoa)); + ipoa.ipoa_boundif = IFSCOPE_NONE; + ipoa.ipoa_flags = IPOAF_SELECT_SRCIF; + struct ifnet *outif = NULL; struct flowadv *adv = &ipoa.ipoa_flowadv; int sotc = SO_TC_UNSPEC; diff --git a/bsd/netinet6/icmp6.c b/bsd/netinet6/icmp6.c index f80a4154a..853d97702 100644 --- a/bsd/netinet6/icmp6.c +++ b/bsd/netinet6/icmp6.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2017 Apple Inc. All rights reserved. + * Copyright (c) 2000-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -2138,10 +2138,14 @@ icmp6_reflect(struct mbuf *m, size_t off) struct sockaddr_in6 sa6_src, sa6_dst; struct nd_ifinfo *ndi = NULL; u_int32_t oflow; - struct ip6_out_args ip6oa = { IFSCOPE_NONE, { 0 }, - IP6OAF_SELECT_SRCIF | IP6OAF_BOUND_SRCADDR | - IP6OAF_INTCOPROC_ALLOWED | IP6OAF_AWDL_UNRESTRICTED, 0, - SO_TC_UNSPEC, _NET_SERVICE_TYPE_UNSPEC }; + struct ip6_out_args ip6oa; + + bzero(&ip6oa, sizeof(ip6oa)); + ip6oa.ip6oa_boundif = IFSCOPE_NONE; + ip6oa.ip6oa_flags = IP6OAF_SELECT_SRCIF | IP6OAF_BOUND_SRCADDR | + IP6OAF_INTCOPROC_ALLOWED | IP6OAF_AWDL_UNRESTRICTED; + ip6oa.ip6oa_sotc = SO_TC_UNSPEC; + ip6oa.ip6oa_netsvctype = _NET_SERVICE_TYPE_UNSPEC; if (!(m->m_pkthdr.pkt_flags & PKTF_LOOP) && m->m_pkthdr.rcvif != NULL) { ip6oa.ip6oa_boundif = m->m_pkthdr.rcvif->if_index; @@ -2569,9 +2573,13 @@ icmp6_redirect_output(struct mbuf *m0, struct rtentry *rt) u_char *p; struct ifnet *outif = NULL; struct sockaddr_in6 src_sa; - struct ip6_out_args ip6oa = { IFSCOPE_NONE, { 0 }, - IP6OAF_SELECT_SRCIF | IP6OAF_BOUND_SRCADDR, 0, - SO_TC_UNSPEC, _NET_SERVICE_TYPE_UNSPEC }; + struct ip6_out_args ip6oa; + + bzero(&ip6oa, sizeof(ip6oa)); + ip6oa.ip6oa_boundif = IFSCOPE_NONE; + ip6oa.ip6oa_flags = IP6OAF_SELECT_SRCIF | IP6OAF_BOUND_SRCADDR; + ip6oa.ip6oa_sotc = SO_TC_UNSPEC; + ip6oa.ip6oa_netsvctype = _NET_SERVICE_TYPE_UNSPEC; icmp6_errcount(&icmp6stat.icp6s_outerrhist, ND_REDIRECT, 0); diff --git a/bsd/netinet6/in6_pcb.c b/bsd/netinet6/in6_pcb.c index 29cbedd50..3118b7bae 100644 --- a/bsd/netinet6/in6_pcb.c +++ b/bsd/netinet6/in6_pcb.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2013 Apple Inc. All rights reserved. + * Copyright (c) 2003-2017 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -198,13 +198,17 @@ in6_pcbbind(struct inpcb *inp, struct sockaddr *nam, struct proc *p) if (!in6_ifaddrs) /* XXX broken! */ return (EADDRNOTAVAIL); - if (inp->inp_lport || !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) - return (EINVAL); if (!(so->so_options & (SO_REUSEADDR|SO_REUSEPORT))) wild = 1; socket_unlock(so, 0); /* keep reference */ lck_rw_lock_exclusive(pcbinfo->ipi_lock); + if (inp->inp_lport || !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) { + /* another thread completed the bind */ + lck_rw_done(pcbinfo->ipi_lock); + socket_lock(so, 0); + return (EINVAL); + } bzero(&sin6, sizeof (sin6)); if (nam != NULL) { diff --git a/bsd/netinet6/in6_src.c b/bsd/netinet6/in6_src.c index a987f4250..42fe27ad4 100644 --- a/bsd/netinet6/in6_src.c +++ b/bsd/netinet6/in6_src.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2016 Apple Inc. All rights reserved. + * Copyright (c) 2000-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -554,13 +554,18 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, struct ifnet *ifp = NULL; struct in6_pktinfo *pi = NULL; struct ip6_moptions *mopts; - struct ip6_out_args ip6oa = { ifscope, { 0 }, IP6OAF_SELECT_SRCIF, 0, - SO_TC_UNSPEC, _NET_SERVICE_TYPE_UNSPEC }; + struct ip6_out_args ip6oa; boolean_t inp_debug = FALSE; uint32_t hint_mask = 0; int prefer_tempaddr = 0; struct ifnet *sifp = NULL; + bzero(&ip6oa, sizeof(ip6oa)); + ip6oa.ip6oa_boundif = ifscope; + ip6oa.ip6oa_flags = IP6OAF_SELECT_SRCIF; + ip6oa.ip6oa_sotc = SO_TC_UNSPEC; + ip6oa.ip6oa_netsvctype = _NET_SERVICE_TYPE_UNSPEC; + *errorp = 0; if (ifpp != NULL) *ifpp = NULL; @@ -1365,13 +1370,15 @@ int in6_pcbsetport(struct in6_addr *laddr, struct inpcb *inp, struct proc *p, int locked) { -#pragma unused(laddr) struct socket *so = inp->inp_socket; u_int16_t lport = 0, first, last, *lastport; int count, error = 0, wild = 0; + boolean_t counting_down; bool found; struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; kauth_cred_t cred; + + (void)laddr; if (!locked) { /* Make sure we don't run into a deadlock: 4052373 */ if (!lck_rw_try_lock_exclusive(pcbinfo->ipi_lock)) { socket_unlock(inp->inp_socket, 0); @@ -1423,63 +1430,43 @@ in6_pcbsetport(struct in6_addr *laddr, struct inpcb *inp, struct proc *p, /* * Simple check to ensure all ports are not used up causing * a deadlock here. - * - * We split the two cases (up and down) so that the direction - * is not being tested on each round of the loop. */ + found = false; if (first > last) { - /* - * counting down - */ + /* counting down */ count = first - last; - found = false; - - do { - if (count-- < 0) { /* completely used? */ - /* - * Undo any address bind that may have - * occurred above. - */ - inp->in6p_laddr = in6addr_any; - inp->in6p_last_outifp = NULL; - if (!locked) - lck_rw_done(pcbinfo->ipi_lock); - return (EAGAIN); - } - --*lastport; - if (*lastport > first || *lastport < last) - *lastport = first; - lport = htons(*lastport); - - found = in6_pcblookup_local(pcbinfo, &inp->in6p_laddr, - lport, wild) == NULL; - } while (!found); + counting_down = TRUE; } else { /* counting up */ count = last - first; - found = false; - - do { - if (count-- < 0) { /* completely used? */ - /* - * Undo any address bind that may have - * occurred above. - */ - inp->in6p_laddr = in6addr_any; - inp->in6p_last_outifp = NULL; - if (!locked) - lck_rw_done(pcbinfo->ipi_lock); - return (EAGAIN); + counting_down = FALSE; + } + do { + if (count-- < 0) { /* completely used? */ + /* + * Undo any address bind that may have + * occurred above. + */ + inp->in6p_laddr = in6addr_any; + inp->in6p_last_outifp = NULL; + if (!locked) + lck_rw_done(pcbinfo->ipi_lock); + return (EAGAIN); + } + if (counting_down) { + --*lastport; + if (*lastport > first || *lastport < last) { + *lastport = first; } + } else { ++*lastport; if (*lastport < first || *lastport > last) *lastport = first; - lport = htons(*lastport); - - found = in6_pcblookup_local(pcbinfo, &inp->in6p_laddr, - lport, wild) == NULL; - } while (!found); - } + } + lport = htons(*lastport); + found = (in6_pcblookup_local(pcbinfo, &inp->in6p_laddr, + lport, wild) == NULL); + } while (!found); inp->inp_lport = lport; inp->inp_flags |= INP_ANONPORT; diff --git a/bsd/netinet6/ip6_input.c b/bsd/netinet6/ip6_input.c index b3c2bcfcd..6ca8bba66 100644 --- a/bsd/netinet6/ip6_input.c +++ b/bsd/netinet6/ip6_input.c @@ -1030,6 +1030,12 @@ ip6_input(struct mbuf *m) if (ip6->ip6_nxt == IPPROTO_HOPOPTS) { struct ip6_hbh *hbh; + /* + * Mark the packet to imply that HBH option has been checked. + * This can only be true is the packet came in unfragmented + * or if the option is in the first fragment + */ + m->m_pkthdr.pkt_flags |= PKTF_HBH_CHKED; if (ip6_hopopts_input(&plen, &rtalert, &m, &off)) { #if 0 /* touches NULL pointer */ in6_ifstat_inc(inifp, ifs6_in_discard); @@ -1177,6 +1183,20 @@ ip6_input(struct mbuf *m) struct ipfilter *filter; int (*pr_input)(struct mbuf **, int *, int); + /* + * This would imply either IPPROTO_HOPOPTS was not the first + * option or it did not come in the first fragment. + */ + if (nxt == IPPROTO_HOPOPTS && + (m->m_pkthdr.pkt_flags & PKTF_HBH_CHKED) == 0) { + /* + * This implies that HBH option was not contained + * in the first fragment + */ + ip6stat.ip6s_badoptions++; + goto bad; + } + if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) { ip6stat.ip6s_toomanyhdr++; goto bad; @@ -1192,7 +1212,6 @@ ip6_input(struct mbuf *m) goto bad; } - #if IPSEC /* * enforce IPsec policy checking if we are seeing last header. diff --git a/bsd/netinet6/ipsec.c b/bsd/netinet6/ipsec.c index 1ba068011..283158d58 100644 --- a/bsd/netinet6/ipsec.c +++ b/bsd/netinet6/ipsec.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2016 Apple Inc. All rights reserved. + * Copyright (c) 2008-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -3689,8 +3689,13 @@ ipsec6_output_tunnel_internal(struct ipsec_output_state *state, struct secasvar struct sockaddr_in* dst4; struct route *ro4 = NULL; struct route ro4_copy; - struct ip_out_args ipoa = { IFSCOPE_NONE, { 0 }, IPOAF_SELECT_SRCIF, 0, - SO_TC_UNSPEC, _NET_SERVICE_TYPE_UNSPEC }; + struct ip_out_args ipoa; + + bzero(&ipoa, sizeof(ipoa)); + ipoa.ipoa_boundif = IFSCOPE_NONE; + ipoa.ipoa_flags = IPOAF_SELECT_SRCIF; + ipoa.ipoa_sotc = SO_TC_UNSPEC; + ipoa.ipoa_netsvctype = _NET_SERVICE_TYPE_UNSPEC; if (must_be_last) *must_be_last = 1; @@ -4680,12 +4685,16 @@ ipsec_send_natt_keepalive( struct mbuf *m; struct ip *ip; int error; - struct ip_out_args ipoa = - { IFSCOPE_NONE, { 0 }, IPOAF_SELECT_SRCIF, 0, - SO_TC_UNSPEC, _NET_SERVICE_TYPE_UNSPEC }; + struct ip_out_args ipoa; struct route ro; int keepalive_interval = natt_keepalive_interval; + bzero(&ipoa, sizeof(ipoa)); + ipoa.ipoa_boundif = IFSCOPE_NONE; + ipoa.ipoa_flags = IPOAF_SELECT_SRCIF; + ipoa.ipoa_sotc = SO_TC_UNSPEC; + ipoa.ipoa_netsvctype = _NET_SERVICE_TYPE_UNSPEC; + LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_NOTOWNED); if ((esp_udp_encap_port & 0xFFFF) == 0 || sav->remote_ike_port == 0) return FALSE; diff --git a/bsd/netinet6/nd6.c b/bsd/netinet6/nd6.c index 495a3b304..0b150814a 100644 --- a/bsd/netinet6/nd6.c +++ b/bsd/netinet6/nd6.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2017 Apple Inc. All rights reserved. + * Copyright (c) 2000-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -811,7 +811,8 @@ nd6_service(void *arg) * resolved, however right now we do not install more than one default * route per interface in the routing table. */ - if (send_nc_failure_kev && ifp->if_addrlen == IF_LLREACH_MAXLEN) { + if (send_nc_failure_kev && ifp != NULL && + ifp->if_addrlen == IF_LLREACH_MAXLEN) { struct kev_msg ev_msg; struct kev_nd6_ndfailure nd6_ndfailure; bzero(&ev_msg, sizeof(ev_msg)); @@ -1234,6 +1235,7 @@ nd6_service(void *arg) addrloop: lck_rw_lock_exclusive(&in6_ifaddr_rwlock); for (ia6 = in6_ifaddrs; ia6; ia6 = nia6) { + int oldflags = ia6->ia6_flags; ap->found++; nia6 = ia6->ia_next; IFA_LOCK(&ia6->ia_ifa); @@ -1305,21 +1307,21 @@ nd6_service(void *arg) ap->aging_lazy++; IFA_LOCK_ASSERT_HELD(&ia6->ia_ifa); if (IFA6_IS_DEPRECATED(ia6, timenow)) { - int oldflags = ia6->ia6_flags; ia6->ia6_flags |= IN6_IFF_DEPRECATED; - /* - * Only enqueue the Deprecated event when the address just - * becomes deprecated. - * Keep it limited to the stable address it is common for - * older temporary addresses to get deprecated while we generate - * new ones. - */ - if((oldflags & IN6_IFF_DEPRECATED) == 0 && - (ia6->ia6_flags & IN6_IFF_TEMPORARY) == 0) { - in6_event_enqueue_nwk_wq_entry(IN6_ADDR_MARKED_DEPRECATED, - ia6->ia_ifa.ifa_ifp, &ia6->ia_addr.sin6_addr, - 0); + if((oldflags & IN6_IFF_DEPRECATED) == 0) { + /* + * Only enqueue the Deprecated event when the address just + * becomes deprecated. + * Keep it limited to the stable address as it is common for + * older temporary addresses to get deprecated while we generate + * new ones. + */ + if ((ia6->ia6_flags & IN6_IFF_TEMPORARY) == 0) { + in6_event_enqueue_nwk_wq_entry(IN6_ADDR_MARKED_DEPRECATED, + ia6->ia_ifa.ifa_ifp, &ia6->ia_addr.sin6_addr, + 0); + } } /* * If a temporary address has just become deprecated, diff --git a/bsd/netinet6/nd6_nbr.c b/bsd/netinet6/nd6_nbr.c index 855b65e4c..4ef91c84c 100644 --- a/bsd/netinet6/nd6_nbr.c +++ b/bsd/netinet6/nd6_nbr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2017 Apple Inc. All rights reserved. + * Copyright (c) 2000-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -572,18 +572,20 @@ nd6_ns_output( int flags; caddr_t mac; struct route_in6 ro; - struct ip6_out_args ip6oa = { IFSCOPE_NONE, { 0 }, - IP6OAF_SELECT_SRCIF | IP6OAF_BOUND_SRCADDR | - IP6OAF_AWDL_UNRESTRICTED | IP6OAF_INTCOPROC_ALLOWED, 0, - SO_TC_UNSPEC, _NET_SERVICE_TYPE_UNSPEC }; + struct ip6_out_args ip6oa; u_int32_t rtflags = 0; if ((ifp->if_eflags & IFEF_IPV6_ND6ALT) || IN6_IS_ADDR_MULTICAST(taddr6)) return; bzero(&ro, sizeof(ro)); - + bzero(&ip6oa, sizeof(ip6oa)); ip6oa.ip6oa_boundif = ifp->if_index; + ip6oa.ip6oa_flags = IP6OAF_SELECT_SRCIF | IP6OAF_BOUND_SRCADDR | + IP6OAF_AWDL_UNRESTRICTED | IP6OAF_INTCOPROC_ALLOWED; + ip6oa.ip6oa_sotc = SO_TC_UNSPEC; + ip6oa.ip6oa_netsvctype = _NET_SERVICE_TYPE_UNSPEC; + ip6oa.ip6oa_flags |= IP6OAF_BOUND_IF; /* estimate the size of message */ @@ -1173,16 +1175,17 @@ nd6_na_input(struct mbuf *m, int off, int icmp6len) * issue a callback for LLENTRY changed. */ /* Enqueue work item to invoke callback for this route entry */ - route_event_enqueue_nwk_wq_entry(rt, NULL, - ROUTE_LLENTRY_CHANGED, NULL, TRUE); + if (llchange) { + route_event_enqueue_nwk_wq_entry(rt, NULL, + ROUTE_LLENTRY_CHANGED, NULL, TRUE); + } /* - * If the entry is no longer a router, the logic post this processing - * gets rid of all the route entries having the current entry as a next - * hop. - * So only walk the tree here when there's no such change. + * If the router's link-layer address has changed, + * notify routes using this as gateway so they can + * update any cached information. */ - if (ln->ln_router && is_router) { + if (ln->ln_router && is_router && llchange) { struct radix_node_head *rnh = NULL; struct route_event rt_ev; route_event_init(&rt_ev, rt, NULL, ROUTE_LLENTRY_CHANGED); @@ -1342,16 +1345,19 @@ nd6_na_output( struct sockaddr_in6 dst_sa; int icmp6len, maxlen, error; struct ifnet *outif = NULL; - struct ip6_out_args ip6oa = { IFSCOPE_NONE, { 0 }, - IP6OAF_SELECT_SRCIF | IP6OAF_BOUND_SRCADDR | - IP6OAF_AWDL_UNRESTRICTED | IP6OAF_INTCOPROC_ALLOWED, 0, - SO_TC_UNSPEC, _NET_SERVICE_TYPE_UNSPEC }; + struct ip6_out_args ip6oa; bzero(&ro, sizeof(ro)); daddr6 = *daddr6_0; /* make a local copy for modification */ + bzero(&ip6oa, sizeof(ip6oa)); ip6oa.ip6oa_boundif = ifp->if_index; + ip6oa.ip6oa_flags = IP6OAF_SELECT_SRCIF | IP6OAF_BOUND_SRCADDR | + IP6OAF_AWDL_UNRESTRICTED | IP6OAF_INTCOPROC_ALLOWED; + ip6oa.ip6oa_sotc = SO_TC_UNSPEC; + ip6oa.ip6oa_netsvctype = _NET_SERVICE_TYPE_UNSPEC; + ip6oa.ip6oa_flags |= IP6OAF_BOUND_IF; /* estimate the size of message */ diff --git a/bsd/netinet6/nd6_rtr.c b/bsd/netinet6/nd6_rtr.c index 8502334ea..f54c20f54 100644 --- a/bsd/netinet6/nd6_rtr.c +++ b/bsd/netinet6/nd6_rtr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2017 Apple Inc. All rights reserved. + * Copyright (c) 2003-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -3072,10 +3072,12 @@ pfxlist_onlink_check(void) } else { NDPR_UNLOCK(ndpr); IFA_LOCK(&ifa->ia_ifa); - ifa->ia6_flags |= IN6_IFF_DETACHED; - in6_event_enqueue_nwk_wq_entry(IN6_ADDR_MARKED_DETACHED, - ifa->ia_ifa.ifa_ifp, &ifa->ia_addr.sin6_addr, - 0); + if ((ifa->ia6_flags & IN6_IFF_DETACHED) == 0) { + ifa->ia6_flags |= IN6_IFF_DETACHED; + in6_event_enqueue_nwk_wq_entry(IN6_ADDR_MARKED_DETACHED, + ifa->ia_ifa.ifa_ifp, &ifa->ia_addr.sin6_addr, + 0); + } IFA_UNLOCK(&ifa->ia_ifa); } NDPR_REMREF(ndpr); diff --git a/bsd/netinet6/raw_ip6.c b/bsd/netinet6/raw_ip6.c index d7c6f689f..ec7f823fb 100644 --- a/bsd/netinet6/raw_ip6.c +++ b/bsd/netinet6/raw_ip6.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2016 Apple Inc. All rights reserved. + * Copyright (c) 2000-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -349,12 +349,15 @@ rip6_output( int type = 0, code = 0; /* for ICMPv6 output statistics only */ int sotc = SO_TC_UNSPEC; int netsvctype = _NET_SERVICE_TYPE_UNSPEC; - struct ip6_out_args ip6oa = - { IFSCOPE_NONE, { 0 }, IP6OAF_SELECT_SRCIF, 0, 0, 0 }; + struct ip6_out_args ip6oa; int flags = IPV6_OUTARGS; in6p = sotoin6pcb(so); + bzero(&ip6oa, sizeof(ip6oa)); + ip6oa.ip6oa_boundif = IFSCOPE_NONE; + ip6oa.ip6oa_flags = IP6OAF_SELECT_SRCIF; + if (in6p == NULL #if NECP || (necp_socket_should_use_flow_divert(in6p)) diff --git a/bsd/netinet6/udp6_output.c b/bsd/netinet6/udp6_output.c index 3db74ee52..fdda7e512 100644 --- a/bsd/netinet6/udp6_output.c +++ b/bsd/netinet6/udp6_output.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2017 Apple Inc. All rights reserved. + * Copyright (c) 2000-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -161,13 +161,16 @@ udp6_output(struct in6pcb *in6p, struct mbuf *m, struct sockaddr *addr6, struct in6_addr storage; int sotc = SO_TC_UNSPEC; int netsvctype = _NET_SERVICE_TYPE_UNSPEC; - struct ip6_out_args ip6oa = - { IFSCOPE_NONE, { 0 }, IP6OAF_SELECT_SRCIF, 0, 0, 0 }; + struct ip6_out_args ip6oa; struct flowadv *adv = &ip6oa.ip6oa_flowadv; struct socket *so = in6p->in6p_socket; struct route_in6 ro; int flowadv = 0; + bzero(&ip6oa, sizeof(ip6oa)); + ip6oa.ip6oa_boundif = IFSCOPE_NONE; + ip6oa.ip6oa_flags = IP6OAF_SELECT_SRCIF; + /* Enable flow advisory only when connected */ flowadv = (so->so_state & SS_ISCONNECTED) ? 1 : 0; diff --git a/bsd/netkey/key.c b/bsd/netkey/key.c index a7935a5f2..5272fa8df 100644 --- a/bsd/netkey/key.c +++ b/bsd/netkey/key.c @@ -1171,12 +1171,17 @@ key_do_allocsa_policy( if (candidate->lft_c->sadb_lifetime_addtime < sav->lft_c->sadb_lifetime_addtime) { d = candidate; - if ((sav->flags & SADB_X_EXT_NATT_MULTIPLEUSERS) != 0) + if ((sah->saidx.mode == IPSEC_MODE_TUNNEL && + ((sav->flags & SADB_X_EXT_NATT) != 0)) || + (sah->saidx.mode == IPSEC_MODE_TRANSPORT && + ((sav->flags & SADB_X_EXT_NATT_MULTIPLEUSERS) != 0))) { natt_candidate = sav; - else + } else { no_natt_candidate = sav; - } else + } + } else { d = sav; + } /* * prepared to delete the SA when there is more diff --git a/bsd/nfs/krpc_subr.c b/bsd/nfs/krpc_subr.c index 20fa08bd8..7ae7758e0 100644 --- a/bsd/nfs/krpc_subr.c +++ b/bsd/nfs/krpc_subr.c @@ -126,6 +126,7 @@ struct rpc_reply { }; #define MIN_REPLY_HDR 16 /* xid, dir, astat, errno */ +#define REPLY_SIZE 24 /* xid, dir, astat, rpu_ok */ /* * What is the longest we will wait before re-sending a request? @@ -492,8 +493,16 @@ krpc_call( goto out; } + + if (mbuf_len(m) < REPLY_SIZE) { + error = RPC_SYSTEM_ERR; + } + else { + error = ntohl(reply->rp_u.rpu_ok.rp_rstatus); + } + /* Did the call succeed? */ - if ((error = ntohl(reply->rp_u.rpu_ok.rp_rstatus)) != 0) { + if (error != 0) { printf("rpc status=%d\n", error); /* convert rpc error to errno */ switch (error) { diff --git a/bsd/nfs/nfs_boot.c b/bsd/nfs/nfs_boot.c index c0c5877f6..56d3be664 100644 --- a/bsd/nfs/nfs_boot.c +++ b/bsd/nfs/nfs_boot.c @@ -460,6 +460,7 @@ bp_whoami(struct sockaddr_in *bpsin, size_t msg_len, cn_len, dn_len; u_char *p; int32_t *lp; + size_t encapsulated_size; /* * Get message buffer of sufficient size. @@ -508,8 +509,10 @@ bp_whoami(struct sockaddr_in *bpsin, bpsin->sin_addr.s_addr = sin.sin_addr.s_addr; /* length of encapsulated results */ - if (msg_len < (ntohl(*lp) + sizeof(*lp))) + if (os_add_overflow((size_t) ntohl(*lp), sizeof(*lp), &encapsulated_size) + || msg_len < encapsulated_size) { goto bad; + } msg_len = ntohl(*lp++); p = (u_char*)lp; @@ -518,7 +521,7 @@ bp_whoami(struct sockaddr_in *bpsin, goto bad; str = (struct rpc_string *)p; cn_len = ntohl(str->len); - if (msg_len < cn_len) + if ((msg_len - 4) < cn_len) goto bad; if (cn_len >= MAXHOSTNAMELEN) goto bad; @@ -533,7 +536,7 @@ bp_whoami(struct sockaddr_in *bpsin, goto bad; str = (struct rpc_string *)p; dn_len = ntohl(str->len); - if (msg_len < dn_len) + if ((msg_len - 4) < dn_len) goto bad; if (dn_len >= MAXHOSTNAMELEN) goto bad; @@ -585,8 +588,8 @@ bp_getfile(struct sockaddr_in *bpsin, struct bp_inaddr *bia; struct sockaddr_in *sin; u_char *p, *q; - int error, msg_len; - int cn_len, key_len, sn_len, path_len; + int error; + size_t msg_len, cn_len, key_len, sn_len, path_len; /* * Get message buffer of sufficient size. @@ -628,11 +631,11 @@ bp_getfile(struct sockaddr_in *bpsin, msg_len = mbuf_len(m); /* server name */ - if (msg_len < (int)sizeof(*str)) + if (msg_len < sizeof(*str)) goto bad; str = (struct rpc_string *)p; sn_len = ntohl(str->len); - if (msg_len < sn_len) + if ((msg_len - 4) < sn_len) goto bad; if (sn_len >= MAXHOSTNAMELEN) goto bad; @@ -642,7 +645,7 @@ bp_getfile(struct sockaddr_in *bpsin, msg_len -= RPC_STR_SIZE(sn_len); /* server IP address (mountd) */ - if (msg_len < (int)sizeof(*bia)) + if (msg_len < sizeof(*bia)) goto bad; bia = (struct bp_inaddr *)p; if (bia->atype != htonl(1)) @@ -660,11 +663,11 @@ bp_getfile(struct sockaddr_in *bpsin, msg_len -= sizeof(*bia); /* server pathname */ - if (msg_len < (int)sizeof(*str)) + if (msg_len < sizeof(*str)) goto bad; str = (struct rpc_string *)p; path_len = ntohl(str->len); - if (msg_len < path_len) + if ((msg_len - 4) < path_len) goto bad; if (path_len >= MAXPATHLEN) goto bad; @@ -702,7 +705,8 @@ md_mount(struct sockaddr_in *mdsin, /* mountd server address */ u_char data[NFSX_V3FHMAX + sizeof(u_int32_t)]; } *rdata; mbuf_t m; - int error, mlen, slen; + size_t mlen; + int error, slen; int mntversion = v3 ? RPCMNT_VER3 : RPCMNT_VER1; int proto = (sotype == SOCK_STREAM) ? IPPROTO_TCP : IPPROTO_UDP; in_port_t mntport, nfsport; @@ -742,7 +746,7 @@ md_mount(struct sockaddr_in *mdsin, /* mountd server address */ * + a v3 filehandle length + a v3 filehandle */ mlen = mbuf_len(m); - if (mlen < (int)sizeof(u_int32_t)) + if (mlen < sizeof(u_int32_t)) goto bad; rdata = mbuf_data(m); error = ntohl(rdata->errno); @@ -751,16 +755,17 @@ md_mount(struct sockaddr_in *mdsin, /* mountd server address */ if (v3) { u_int32_t fhlen; u_char *fh; - if (mlen < (int)sizeof(u_int32_t)*2) + if (mlen < sizeof(u_int32_t)*2) goto bad; fhlen = ntohl(*(u_int32_t*)rdata->data); fh = rdata->data + sizeof(u_int32_t); - if (mlen < (int)(sizeof(u_int32_t)*2 + fhlen)) + if (mlen < (sizeof(u_int32_t)*2 + fhlen) + || fhlen >= (NFSX_V3FHMAX + sizeof(u_int32_t))) goto bad; bcopy(fh, fhp, fhlen); *fhlenp = fhlen; } else { - if (mlen < ((int)sizeof(u_int32_t) + NFSX_V2FH)) + if (mlen < (sizeof(u_int32_t) + NFSX_V2FH)) goto bad; bcopy(rdata->data, fhp, NFSX_V2FH); *fhlenp = NFSX_V2FH; diff --git a/bsd/nfs/nfs_socket.c b/bsd/nfs/nfs_socket.c index 5ade6666b..917927c01 100644 --- a/bsd/nfs/nfs_socket.c +++ b/bsd/nfs/nfs_socket.c @@ -3247,6 +3247,7 @@ nfs_send(struct nfsreq *req, int wait) case ECONNREFUSED: case EHOSTDOWN: case EHOSTUNREACH: + /* case ECANCELED??? */ needrecon = 1; break; } @@ -3281,7 +3282,15 @@ nfs_send(struct nfsreq *req, int wait) /* only allow the following errors to be returned */ if ((error != EINTR) && (error != ERESTART) && (error != EIO) && (error != ENXIO) && (error != ETIMEDOUT)) - error = 0; + /* + * We got some error we don't know what do do with, + * i.e., we're not reconnecting, we map it to + * EIO. Presumably our send failed and we better tell + * the caller so they don't wait for a reply that is + * never going to come. If we are reconnecting we + * return 0 and the request will be resent. + */ + error = needrecon ? 0 : EIO; return (error); } diff --git a/bsd/nfs/nfs_vfsops.c b/bsd/nfs/nfs_vfsops.c index 89f6ca956..4ba5bf1cd 100644 --- a/bsd/nfs/nfs_vfsops.c +++ b/bsd/nfs/nfs_vfsops.c @@ -4458,6 +4458,7 @@ nfs_mount_zombie(struct nfsmount *nmp, int nm_state_flags) if ((nmp->nm_vers >= NFS_VER4) && nmp->nm_renew_timer) { thread_call_cancel(nmp->nm_renew_timer); thread_call_free(nmp->nm_renew_timer); + nmp->nm_renew_timer = NULL; } lck_mtx_unlock(&nmp->nm_lock); @@ -4483,6 +4484,7 @@ nfs_mount_zombie(struct nfsmount *nmp, int nm_state_flags) if (nmp->nm_longid->nci_id) FREE(nmp->nm_longid->nci_id, M_TEMP); FREE(nmp->nm_longid, M_TEMP); + nmp->nm_longid = NULL; lck_mtx_unlock(nfs_global_mutex); } diff --git a/bsd/security/audit/audit_bsd.c b/bsd/security/audit/audit_bsd.c index a08ab453d..64b4e9f05 100644 --- a/bsd/security/audit/audit_bsd.c +++ b/bsd/security/audit/audit_bsd.c @@ -51,6 +51,8 @@ #include #include +#include + extern void ipc_port_release_send(ipc_port_t port); #if CONFIG_AUDIT @@ -182,7 +184,10 @@ _audit_malloc(size_t size, au_malloc_type_t *type, int flags) #endif { struct mhdr *hdr; - size_t memsize = sizeof (*hdr) + size; + size_t memsize; + if (os_add_overflow(sizeof(*hdr), size, &memsize)) { + return (NULL); + } if (size == 0) return (NULL); diff --git a/bsd/sys/bsdtask_info.h b/bsd/sys/bsdtask_info.h index c6df6786c..74c747bfe 100644 --- a/bsd/sys/bsdtask_info.h +++ b/bsd/sys/bsdtask_info.h @@ -100,9 +100,6 @@ struct proc_regioninfo_internal { #define PROC_REGION_SUBMAP 1 #define PROC_REGION_SHARED 2 -void vm_map_region_top_walk(vm_map_entry_t entry, vm_region_top_info_t top); -void vm_map_region_walk(vm_map_t map, vm_map_offset_t a, vm_map_entry_t entry, vm_object_offset_t offset, vm_object_size_t range, vm_region_extended_info_t extended); -kern_return_t vnode_pager_get_object_vnode(memory_object_t mem_obj, uintptr_t * vnodeaddr, uint32_t * vid); extern uint32_t vnode_vid(void *vp); #if CONFIG_IOSCHED kern_return_t vnode_pager_get_object_devvp(memory_object_t mem_obj, uintptr_t *devvp); diff --git a/bsd/sys/cdefs.h b/bsd/sys/cdefs.h index 68b4d22d9..4339caf7b 100644 --- a/bsd/sys/cdefs.h +++ b/bsd/sys/cdefs.h @@ -782,9 +782,11 @@ * c99 still want long longs. While not perfect, we allow long longs for * g++. */ -#define __DARWIN_NO_LONG_LONG (defined(__STRICT_ANSI__) \ - && (__STDC_VERSION__-0 < 199901L) \ - && !defined(__GNUG__)) +#if (defined(__STRICT_ANSI__) && (__STDC_VERSION__-0 < 199901L) && !defined(__GNUG__)) +#define __DARWIN_NO_LONG_LONG 1 +#else +#define __DARWIN_NO_LONG_LONG 0 +#endif /***************************************** * Public darwin-specific feature macros diff --git a/bsd/sys/codesign.h b/bsd/sys/codesign.h index 15a39365b..f56878e73 100644 --- a/bsd/sys/codesign.h +++ b/bsd/sys/codesign.h @@ -131,8 +131,13 @@ int csfg_get_platform_binary(struct fileglob *); uint8_t * csfg_get_cdhash(struct fileglob *, uint64_t, size_t *); int csfg_get_prod_signed(struct fileglob *); unsigned int csfg_get_signer_type(struct fileglob *); +const char *csfg_get_identity(struct fileglob *fg, off_t offset); unsigned int csproc_get_signer_type(struct proc *); +uint8_t csfg_get_platform_identifier(struct fileglob *, off_t); +uint8_t csvnode_get_platform_identifier(struct vnode *, off_t); +uint8_t csproc_get_platform_identifier(struct proc *); + extern int cs_debug; #ifdef XNU_KERNEL_PRIVATE diff --git a/bsd/sys/cprotect.h b/bsd/sys/cprotect.h index f2d613213..cfd4c79f8 100644 --- a/bsd/sys/cprotect.h +++ b/bsd/sys/cprotect.h @@ -158,6 +158,7 @@ typedef int backup_key_t(cp_cred_t access, const cp_wrapped_key_t wrapped_key_in cpx_t cpx_alloc(size_t key_size); void cpx_init(cpx_t, size_t key_len); void cpx_free(cpx_t); +void cpx_writeprotect(cpx_t cpx); __attribute__((const)) size_t cpx_size(size_t key_size); __attribute__((pure)) bool cpx_is_sep_wrapped_key(const struct cpx *); void cpx_set_is_sep_wrapped_key(struct cpx *, bool); diff --git a/bsd/sys/dtrace_glue.h b/bsd/sys/dtrace_glue.h index d8a65de0c..077e1f3d9 100644 --- a/bsd/sys/dtrace_glue.h +++ b/bsd/sys/dtrace_glue.h @@ -369,9 +369,6 @@ extern void ddi_report_dev(dev_info_t *); int ddi_getprop(dev_t dev, dev_info_t *dip, int flags, const char *name, int defvalue); -extern int ddi_prop_free(void *); -extern int ddi_prop_lookup_int_array(dev_t, dev_info_t *, uint_t, const char *, int **, uint_t *); - extern int ddi_driver_major(dev_info_t *); extern int ddi_create_minor_node(dev_info_t *, const char *, int, minor_t, const char *, int); diff --git a/bsd/sys/eventhandler.h b/bsd/sys/eventhandler.h index 794aa9acd..79ed93512 100644 --- a/bsd/sys/eventhandler.h +++ b/bsd/sys/eventhandler.h @@ -74,26 +74,10 @@ struct eventhandler_lists_ctxt { }; struct eventhandler_entry_arg { - union { - /* Generic cookie object reference */ - void *ee_voidptr; - /* Skywalk ids */ - struct { - pid_t ee_fe_pid; - uuid_t ee_fe_uuid; - uuid_t ee_nx_uuid; - } sk_ids; - /* Generic UUID */ - uuid_t ee_uuid; - } ee_arg; + uuid_t ee_fmc_uuid; /* Flow manager UUID */ + uuid_t ee_fr_uuid; /* Flow route UUID */ }; -#define ee_voidptr ee_arg.ee_voidptr -#define ee_fe_pid ee_arg.sk_ids.ee_fe_pid -#define ee_fe_uuid ee_arg.sk_ids.ee_fe_uuid -#define ee_nx_uuid ee_arg.sk_ids.ee_nx_uuid -#define ee_uuid ee_arg.ee_uuid - struct eventhandler_entry { TAILQ_ENTRY(eventhandler_entry) ee_link; int ee_priority; @@ -101,8 +85,10 @@ struct eventhandler_entry { struct eventhandler_entry_arg ee_arg; }; +#define EVENTHANDLER_MAX_NAME 32 + struct eventhandler_list { - char *el_name; + char el_name[EVENTHANDLER_MAX_NAME]; int el_flags; #define EHL_INITTED (1<<0) u_int el_runcount; @@ -115,6 +101,8 @@ typedef struct eventhandler_entry *eventhandler_tag; #define EHL_LOCK_INIT(p) lck_mtx_init(&(p)->el_lock, el_lock_grp, el_lock_attr) #define EHL_LOCK(p) lck_mtx_lock(&(p)->el_lock) +#define EHL_LOCK_SPIN(p) lck_mtx_lock_spin(&(p)->el_lock) +#define EHL_LOCK_CONVERT(p) lck_mtx_convert_spin(&(p)->el_lock) #define EHL_UNLOCK(p) lck_mtx_unlock(&(p)->el_lock) #define EHL_LOCK_ASSERT(p, x) LCK_MTX_ASSERT(&(p)->el_lock, x) #define EHL_LOCK_DESTROY(p) lck_mtx_destroy(&(p)->el_lock, el_lock_grp) @@ -140,14 +128,16 @@ typedef struct eventhandler_entry *eventhandler_tag; evhlog((LOG_DEBUG, "eventhandler_invoke: executing %p", \ VM_KERNEL_UNSLIDE((void *)_t->eh_func))); \ _t->eh_func(_ep->ee_arg , ## __VA_ARGS__); \ - EHL_LOCK((list)); \ + EHL_LOCK_SPIN((list)); \ } \ } \ KASSERT((list)->el_runcount > 0, \ ("eventhandler_invoke: runcount underflow")); \ (list)->el_runcount--; \ - if ((list)->el_runcount == 0) \ + if ((list)->el_runcount == 0) { \ + EHL_LOCK_CONVERT((list)); \ eventhandler_prune_list(list); \ + } \ EHL_UNLOCK((list)); \ } while (0) @@ -203,6 +193,7 @@ do { \ } while(0) void eventhandler_init(void); +extern void eventhandler_reap_caches(boolean_t); eventhandler_tag eventhandler_register(struct eventhandler_lists_ctxt *evthdlr_lists_ctxt, struct eventhandler_list *list, const char *name, void *func, struct eventhandler_entry_arg arg, int priority); void eventhandler_deregister(struct eventhandler_list *list, diff --git a/bsd/sys/kdebug.h b/bsd/sys/kdebug.h index 15527d926..132698775 100644 --- a/bsd/sys/kdebug.h +++ b/bsd/sys/kdebug.h @@ -685,6 +685,7 @@ extern void kdebug_reset(void); #define DBG_HFS 0x8 /* HFS-specific events; see the hfs project */ #define DBG_APFS 0x9 /* APFS-specific events; see the apfs project */ #define DBG_SMB 0xA /* SMB-specific events; see the smb project */ +#define DBG_MOUNT 0xB /* Mounting/unmounting operations */ #define DBG_EXFAT 0xE /* ExFAT-specific events; see the exfat project */ #define DBG_MSDOS 0xF /* FAT-specific events; see the msdosfs project */ #define DBG_ACFS 0x10 /* Xsan-specific events; see the XsanFS project */ @@ -1155,11 +1156,19 @@ extern unsigned int kdebug_enable; do { \ if (KDBG_IMPROBABLE(kdebug_enable & (type))) { \ kernel_debug((x), (uintptr_t)(a), (uintptr_t)(b), (uintptr_t)(c), \ - (uintptr_t)(d), (uintptr_t)(e)); \ + (uintptr_t)(d), 0); \ } \ } while (0) +#define KERNEL_DEBUG_CONSTANT_IST1(x, a, b, c, d, e) \ + do { \ + if (KDBG_IMPROBABLE(kdebug_enable)) { \ + kernel_debug1((x), (uintptr_t)(a), (uintptr_t)(b), (uintptr_t)(c), \ + (uintptr_t)(d), (uintptr_t)(e)); \ + } \ + } while (0) #else /* (KDEBUG_LEVEL >= KDEBUG_LEVEL_IST) */ #define KERNEL_DEBUG_CONSTANT_IST(type, x, a, b, c, d, e) do {} while (0) +#define KERNEL_DEBUG_CONSTANT_IST1(x, a, b, c, d, e) do {} while (0) #endif /* (KDEBUG_LEVEL >= KDEBUG_LEVEL_IST) */ #if NO_KDEBUG @@ -1395,11 +1404,11 @@ void kdbg_trace_data(struct proc *proc, long *arg_pid, long *arg_uniqueid); void kdbg_trace_string(struct proc *proc, long *arg1, long *arg2, long *arg3, long *arg4); void kdbg_dump_trace_to_file(const char *); -void kdebug_init(unsigned int n_events, char *filterdesc); -void kdebug_trace_start(unsigned int n_events, const char *filterdesc, boolean_t at_wake); +void kdebug_init(unsigned int n_events, char *filterdesc, boolean_t wrapping); +void kdebug_trace_start(unsigned int n_events, const char *filterdesc, + boolean_t wrapping, boolean_t at_wake); void kdebug_free_early_buf(void); struct task; -void kdbg_get_task_name(char*, int, struct task *task); boolean_t disable_wrap(uint32_t *old_slowcheck, uint32_t *old_flags); void enable_wrap(uint32_t old_slowcheck, boolean_t lostevents); void release_storage_unit(int cpu, uint32_t storage_unit); @@ -1468,12 +1477,12 @@ kdbg_set_timestamp_and_cpu(kd_buf *kp, uint64_t thetime, int cpu) static inline void kdbg_set_cpu(kd_buf *kp, int cpu) { - kp->cpuid = cpu; + kp->cpuid = (unsigned int)cpu; } static inline int kdbg_get_cpu(kd_buf *kp) { - return kp->cpuid; + return (int)kp->cpuid; } static inline void kdbg_set_timestamp(kd_buf *kp, uint64_t thetime) diff --git a/bsd/sys/mbuf.h b/bsd/sys/mbuf.h index 3cac39def..8dafca387 100644 --- a/bsd/sys/mbuf.h +++ b/bsd/sys/mbuf.h @@ -505,6 +505,7 @@ struct pkthdr { #define PKTF_LAST_PKT 0x10000000 /* last packet in the flow */ #define PKTF_MPTCP_REINJ 0x20000000 /* Packet has been reinjected for MPTCP */ #define PKTF_MPTCP_DFIN 0x40000000 /* Packet is a data-fin */ +#define PKTF_HBH_CHKED 0x80000000 /* HBH option is checked */ /* flags related to flow control/advisory and identification */ #define PKTF_FLOW_MASK \ diff --git a/bsd/sys/persona.h b/bsd/sys/persona.h index 0744283f2..4e3d71f46 100644 --- a/bsd/sys/persona.h +++ b/bsd/sys/persona.h @@ -322,7 +322,8 @@ void personas_bootstrap(void); struct persona *persona_alloc(uid_t id, const char *login, int type, int *error); -int persona_invalidate(struct persona *persona); + +struct persona *persona_lookup_and_invalidate(uid_t id); static inline int proc_has_persona(proc_t p) { diff --git a/bsd/sys/priv.h b/bsd/sys/priv.h index 58f568b4b..1933800d2 100644 --- a/bsd/sys/priv.h +++ b/bsd/sys/priv.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2014 Apple Inc. All rights reserved. + * Copyright (c) 2010-2017 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -116,6 +116,8 @@ #define PRIV_NET_PRIVILEGED_MULTIPATH 10009 /* Multipath usage */ #define PRIV_NET_RESTRICTED_MULTIPATH_EXTENDED 10010 /* Extended multipath (more aggressive on cell) */ +#define PRIV_NET_RESTRICTED_ROUTE_NC_READ 10011 /* Enable route neighbhor cache read operations */ + /* * IPv4 and IPv6 privileges. */ diff --git a/bsd/sys/proc.h b/bsd/sys/proc.h index f275e9f92..652cc74b9 100644 --- a/bsd/sys/proc.h +++ b/bsd/sys/proc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2016 Apple Computer, Inc. All rights reserved. + * Copyright (c) 2000-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -372,6 +372,7 @@ extern void proc_log_32bit_telemetry(proc_t p); #ifdef KERNEL_PRIVATE extern vnode_t proc_getexecutablevnode(proc_t); /* Returned with iocount, use vnode_put() to drop */ +extern int networking_memstatus_callout(proc_t p, uint32_t); #endif __END_DECLS diff --git a/bsd/sys/proc_info.h b/bsd/sys/proc_info.h index 01c7d8b0a..f28ae3d10 100644 --- a/bsd/sys/proc_info.h +++ b/bsd/sys/proc_info.h @@ -681,7 +681,7 @@ struct appletalk_fdinfo { struct appletalk_info appletalkinfo; }; - +typedef uint64_t proc_info_udata_t; /* defns of process file desc type */ #define PROX_FDTYPE_ATALK 0 @@ -872,6 +872,10 @@ struct proc_fileportinfo { #define PROC_DIRTY_IS_DIRTY 0x4 #define PROC_DIRTY_LAUNCH_IS_IN_PROGRESS 0x8 +/* Flavors for proc_udata_info */ +#define PROC_UDATA_INFO_GET 1 +#define PROC_UDATA_INFO_SET 2 + #ifdef PRIVATE /* Flavors for proc_pidoriginatorinfo */ @@ -905,12 +909,10 @@ struct proc_fileportinfo { #define PROC_FGHW_ERROR 99 /* syscall parameter/permissions error */ /* flavors for proc_piddynkqueueinfo */ -#ifdef PRIVATE #define PROC_PIDDYNKQUEUE_INFO 0 #define PROC_PIDDYNKQUEUE_INFO_SIZE (sizeof(struct kqueue_dyninfo)) #define PROC_PIDDYNKQUEUE_EXTINFO 1 #define PROC_PIDDYNKQUEUE_EXTINFO_SIZE (sizeof(struct kevent_extinfo)) -#endif /* __proc_info() call numbers */ #define PROC_INFO_CALL_LISTPIDS 0x1 @@ -926,6 +928,7 @@ struct proc_fileportinfo { #define PROC_INFO_CALL_LISTCOALITIONS 0xb #define PROC_INFO_CALL_CANUSEFGHW 0xc #define PROC_INFO_CALL_PIDDYNKQUEUEINFO 0xd +#define PROC_INFO_CALL_UDATA_INFO 0xe #endif /* PRIVATE */ diff --git a/bsd/sys/proc_internal.h b/bsd/sys/proc_internal.h index b6d40d6ee..7119591d2 100644 --- a/bsd/sys/proc_internal.h +++ b/bsd/sys/proc_internal.h @@ -409,6 +409,10 @@ struct proc { _Atomic uint32_t p_user_faults; /* count the number of user faults generated */ struct os_reason *p_exit_reason; + +#if !CONFIG_EMBEDDED + uint64_t p_user_data; /* general-purpose storage for userland-provided data */ +#endif /* !CONFIG_EMBEDDED */ }; #define PGRPID_DEAD 0xdeaddead diff --git a/bsd/sys/reason.h b/bsd/sys/reason.h index a7dc43f69..81792a1b9 100644 --- a/bsd/sys/reason.h +++ b/bsd/sys/reason.h @@ -232,6 +232,7 @@ int terminate_with_payload(int pid, uint32_t reason_namespace, uint64_t reason_c #define EXEC_EXIT_REASON_FAIRPLAY_DECRYPT 10 #define EXEC_EXIT_REASON_DECRYPT 11 #define EXEC_EXIT_REASON_UPX 12 +#define EXEC_EXIT_REASON_NO32EXEC 13 __END_DECLS diff --git a/bsd/sys/socket.h b/bsd/sys/socket.h index 2bdccabf6..3602f7764 100644 --- a/bsd/sys/socket.h +++ b/bsd/sys/socket.h @@ -302,6 +302,7 @@ #define SO_TRAFFIC_CLASS_DBG 0x1088 /* Debug traffic class (struct so_tcdbg) */ #define SO_TRAFFIC_CLASS_STATS 0x1089 /* Traffic class statistics */ #define SO_PRIVILEGED_TRAFFIC_CLASS 0x1090 /* Privileged traffic class (bool) */ +#define SO_DEFUNCTIT 0x1091 /* Defunct a socket (only in internal builds) */ #define SO_DEFUNCTOK 0x1100 /* can be defunct'd */ #define SO_ISDEFUNCT 0x1101 /* get defunct status */ diff --git a/bsd/sys/socketvar.h b/bsd/sys/socketvar.h index 17e1e2c35..b0be72420 100644 --- a/bsd/sys/socketvar.h +++ b/bsd/sys/socketvar.h @@ -275,7 +275,6 @@ struct socket { #define SOF_ENABLE_MSGS 0x00400000 /* TCP must enable message delivery */ #define SOF_FLOW_DIVERT 0x00800000 /* Flow Divert is enabled */ #define SOF_MP_SUBFLOW 0x01000000 /* is a multipath subflow socket */ -#define SOF_MPTCP_TRUE 0x02000000 /* Established e2e MPTCP connection */ #define SOF_MP_SEC_SUBFLOW 0x04000000 /* Set up secondary flow */ #define SOF_MP_TRYFAILOVER 0x08000000 /* Failing subflow */ #define SOF_DELEGATED 0x10000000 /* on behalf of another process */ diff --git a/bsd/sys/sockio.h b/bsd/sys/sockio.h index 78f3b6a7f..be5cfba2e 100644 --- a/bsd/sys/sockio.h +++ b/bsd/sys/sockio.h @@ -309,7 +309,11 @@ #define SIOCSIFNAT64PREFIX _IOWR('i', 194, struct if_nat64req) #endif #define SIOCGIFNEXUS _IOWR('i', 195, struct if_nexusreq) - +#define SIOCGIFPROTOLIST _IOWR('i', 196, struct if_protolistreq) /* get list of attached protocols */ +#ifdef BSD_KERNEL_PRIVATE +#define SIOCGIFPROTOLIST32 _IOWR('i', 196, struct if_protolistreq32) +#define SIOCGIFPROTOLIST64 _IOWR('i', 196, struct if_protolistreq64) +#endif /* BSD_KERNEL_PRIVATE */ #endif /* PRIVATE */ #endif /* !_SYS_SOCKIO_H_ */ diff --git a/bsd/sys/sysctl.h b/bsd/sys/sysctl.h index 3acef8603..ff17198ca 100644 --- a/bsd/sys/sysctl.h +++ b/bsd/sys/sysctl.h @@ -2,7 +2,7 @@ * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in @@ -11,10 +11,10 @@ * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. - * + * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -22,7 +22,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ @@ -108,7 +108,7 @@ /* * Each subsystem defined by sysctl defines a list of variables - * for that subsystem. Each name is either a node with further + * for that subsystem. Each name is either a node with further * levels defined below it, or it is a leaf of some particular * type given below. Each sysctl level defines a set of name/type * pairs to be used by sysctl(1) in manipulating the subsystem. @@ -297,10 +297,10 @@ __END_DECLS #define SYSCTL_LINKER_SET_ENTRY(a, b) #endif /* - * Macros to define sysctl entries. Which to use? Pure data that are + * Macros to define sysctl entries. Which to use? Pure data that are * returned without modification, SYSCTL_ is for you, like * SYSCTL_QUAD for a 64-bit value. When you want to run a handler of your - * own, SYSCTL_PROC. + * own, SYSCTL_PROC. * * parent: parent in name hierarchy (e.g. _kern for "kern") * nbr: ID. Almost certainly OID_AUTO ("pick one for me") for you. @@ -396,7 +396,7 @@ __END_DECLS ptr, sizeof(struct type), sysctl_handle_opaque, \ "S," #type, descr) -/* +/* * Oid for a procedure. Specified by a pointer and an arg. * CTLTYPE_* macros can determine how the "sysctl" tool deals with * input (e.g. converting to int). @@ -404,8 +404,8 @@ __END_DECLS #define SYSCTL_PROC(parent, nbr, name, access, ptr, arg, handler, fmt, descr) \ SYSCTL_OID(parent, nbr, name, access, \ ptr, arg, handler, fmt, descr) - - + + extern struct sysctl_oid_list sysctl__children; SYSCTL_DECL(_kern); SYSCTL_DECL(_sysctl); @@ -418,6 +418,7 @@ SYSCTL_DECL(_machdep); SYSCTL_DECL(_user); #ifdef PRIVATE +SYSCTL_DECL(_kern_bridge); SYSCTL_DECL(_hw_features); #endif @@ -565,7 +566,7 @@ SYSCTL_DECL(_hw_features); * sysctl(8) to pick up your changes. */ -#if COUNT_SYSCALLS && defined(KERNEL) +#if COUNT_SYSCALLS && defined(KERNEL) #define KERN_COUNT_SYSCALLS (KERN_OSTYPE + 1000) /* keep called count for each bsd syscall */ #endif @@ -704,7 +705,7 @@ SYSCTL_DECL(_hw_features); { "vfsconf", CTLTYPE_STRUCT } \ } -/* +/* * KERN_PROC subtypes */ #define KERN_PROC_ALL 0 /* everything */ @@ -716,8 +717,8 @@ SYSCTL_DECL(_hw_features); #define KERN_PROC_RUID 6 /* by real uid */ #define KERN_PROC_LCID 7 /* by login context id */ -#if defined(XNU_KERNEL_PRIVATE) || !defined(KERNEL) -/* +#if defined(XNU_KERNEL_PRIVATE) || !defined(KERNEL) +/* * KERN_PROC subtype ops return arrays of augmented proc structures: */ @@ -772,7 +773,7 @@ struct kinfo_proc { #ifdef BSD_KERNEL_PRIVATE #include -/* LP64 version of _pcred. all pointers +/* LP64 version of _pcred. all pointers * grow when we're dealing with a 64-bit process. * WARNING - keep in sync with _pcred */ @@ -796,7 +797,7 @@ struct user64_pcred { int p_refcnt; /* Number of references. */ }; -/* LP64 version of kinfo_proc. all pointers +/* LP64 version of kinfo_proc. all pointers * grow when we're dealing with a 64-bit process. * WARNING - keep in sync with kinfo_proc */ @@ -873,7 +874,7 @@ struct user64_kinfo_proc { /* * Note: "3" was skipped sometime ago and should probably remain unused * to avoid any new entry from being accepted by older kernels... - */ + */ #define VM_MACHFACTOR 4 /* struct loadavg with mach factor*/ #define VM_SWAPUSAGE 5 /* total swap usage */ #define VM_MAXID 6 /* number of valid vm ids */ @@ -1036,7 +1037,7 @@ struct user64_loadavg { * * hw.packages - Gives the number of processor packages. * - * These are the selectors for optional processor features for specific processors. Selectors that return errors are not support + * These are the selectors for optional processor features for specific processors. Selectors that return errors are not support * on the system. Supported features will return 1 if they are recommended or 0 if they are supported but are not expected to help . * performance. Future versions of these selectors may return larger values as necessary so it is best to test for non zero. * @@ -1053,7 +1054,7 @@ struct user64_loadavg { * hw.optional.dcbtstreams - Data Cache Block Touch Steams Instruction Form * * For x86 Architecture: - * + * * hw.optional.floatingpoint - Floating Point Instructions * hw.optional.mmx - Original MMX vector instructions * hw.optional.sse - Streaming SIMD Extensions diff --git a/bsd/sys/syslog.h b/bsd/sys/syslog.h index af3705e2b..48f91cd1b 100644 --- a/bsd/sys/syslog.h +++ b/bsd/sys/syslog.h @@ -230,7 +230,7 @@ void closelog(void); void openlog(const char *, int, int); int setlogmask(int); #if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __DARWIN_C_LEVEL >= __DARWIN_C_FULL -void syslog(int, const char *, ...) __printflike(2, 3) __not_tail_called __DARWIN_ALIAS_STARTING(__MAC_10_13, __IPHONE_NA, __DARWIN_EXTSN(syslog)); +void syslog(int, const char *, ...) __DARWIN_ALIAS_STARTING(__MAC_10_13, __IPHONE_NA, __DARWIN_EXTSN(syslog)) __printflike(2, 3) __not_tail_called; #else void syslog(int, const char *, ...) __printflike(2, 3) __not_tail_called; #endif diff --git a/bsd/sys/systm.h b/bsd/sys/systm.h index fb2badf23..98dc4dd52 100644 --- a/bsd/sys/systm.h +++ b/bsd/sys/systm.h @@ -229,6 +229,7 @@ void throttle_info_release(void *throttle_info); void throttle_info_update(void *throttle_info, int flags); uint32_t throttle_lowpri_io(int sleep_amount); void throttle_set_thread_io_policy(int policy); +int throttle_get_thread_effective_io_policy(void); typedef struct __throttle_info_handle *throttle_info_handle_t; int throttle_info_ref_by_mask(uint64_t throttle_mask, throttle_info_handle_t *throttle_info_handle); diff --git a/bsd/sys/work_interval.h b/bsd/sys/work_interval.h index f7e46ec08..ae881a0f9 100644 --- a/bsd/sys/work_interval.h +++ b/bsd/sys/work_interval.h @@ -115,11 +115,14 @@ __BEGIN_DECLS #define WORK_INTERVAL_TYPE_DEFAULT (0x0 << 28) #define WORK_INTERVAL_TYPE_COREAUDIO (0x1 << 28) #define WORK_INTERVAL_TYPE_COREANIMATION (0x2 << 28) +#define WORK_INTERVAL_TYPE_CA_RENDER_SERVER (0x2 << 28) +#define WORK_INTERVAL_TYPE_CA_CLIENT (0x3 << 28) #define WORK_INTERVAL_TYPE_LAST (0xF << 28) #ifndef KERNEL typedef struct work_interval *work_interval_t; +typedef struct work_interval_instance *work_interval_instance_t; /* * Create a new work interval handle. @@ -150,6 +153,7 @@ typedef struct work_interval *work_interval_t; */ int work_interval_create(work_interval_t *interval_handle, uint32_t flags); + /* * Notify the power management subsystem that the work for a current interval has completed * @@ -213,8 +217,6 @@ int work_interval_join_port(mach_port_t port); */ int work_interval_leave(void); -/* TODO: complexity measure */ - #endif /* !KERNEL */ #if PRIVATE @@ -242,6 +244,7 @@ struct work_interval_create_params { uint32_t wicp_create_flags; }; + int __work_interval_ctl(uint32_t operation, uint64_t work_interval_id, void *arg, size_t len); #endif /* PRIVATE */ diff --git a/bsd/vfs/vfs_cluster.c b/bsd/vfs/vfs_cluster.c index 32fc807ff..60807acea 100644 --- a/bsd/vfs/vfs_cluster.c +++ b/bsd/vfs/vfs_cluster.c @@ -3320,17 +3320,27 @@ cluster_write_copy(vnode_t vp, struct uio *uio, u_int32_t io_req_size, off_t old if (retval == 0) { int cl_index; int ret_cluster_try_push; + int do_zeroing = 1; - io_size += start_offset; + + io_size += start_offset; + - if (newEOF >= oldEOF && (upl_f_offset + io_size) >= newEOF && (u_int)io_size < upl_size) { - /* + /* Force more restrictive zeroing behavior only on APFS */ + if ((vnode_tag(vp) == VT_APFS) && (newEOF < oldEOF)) { + do_zeroing = 0; + } + + + if (do_zeroing && (upl_f_offset + io_size) >= newEOF && (u_int)io_size < upl_size) { + + /* * if we're extending the file with this write * we'll zero fill the rest of the page so that * if the file gets extended again in such a way as to leave a * hole starting at this EOF, we'll have zero's in the correct spot */ - cluster_zero(upl, io_size, upl_size - io_size, NULL); + cluster_zero(upl, io_size, upl_size - io_size, NULL); } /* * release the upl now if we hold one since... diff --git a/bsd/vfs/vfs_cprotect.c b/bsd/vfs/vfs_cprotect.c index d28679623..ff53ee1a3 100644 --- a/bsd/vfs/vfs_cprotect.c +++ b/bsd/vfs/vfs_cprotect.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Apple Inc. All rights reserved. + * Copyright (c) 2015-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -89,14 +89,40 @@ size_t cpx_sizex(const struct cpx *cpx) cpx_t cpx_alloc(size_t key_len) { cpx_t cpx; - + +#if TARGET_OS_OSX + /* + * Macs only use 1 key per volume, so force it into its own page. + * This way, we can write-protect as needed. + */ + size_t cpsize = cpx_size (key_len); + if (cpsize < PAGE_SIZE) { + MALLOC(cpx, cpx_t, PAGE_SIZE, M_TEMP, M_WAITOK); + } + else { + panic ("cpx_size too large ! (%lu)", cpsize); + } +#else MALLOC(cpx, cpx_t, cpx_size(key_len), M_TEMP, M_WAITOK); - +#endif cpx_init(cpx, key_len); return cpx; } +/* this is really a void function */ +void cpx_writeprotect (cpx_t cpx) +{ +#if TARGET_OS_OSX + void *cpxstart = (void*)cpx; + void *cpxend = (void*)((uint8_t*)cpx + PAGE_SIZE); + vm_map_protect (kernel_map, cpxstart, cpxend, (VM_PROT_READ), FALSE); +#else + (void) cpx; +#endif + return; +} + #if DEBUG static const uint32_t cpx_magic1 = 0x7b787063; // cpx{ static const uint32_t cpx_magic2 = 0x7870637d; // }cpx @@ -104,10 +130,19 @@ static const uint32_t cpx_magic2 = 0x7870637d; // }cpx void cpx_free(cpx_t cpx) { + #if DEBUG assert(cpx->cpx_magic1 == cpx_magic1); assert(*PTR_ADD(uint32_t *, cpx, cpx_sizex(cpx) - 4) == cpx_magic2); #endif + +#if TARGET_OS_OSX + /* unprotect the page before bzeroing */ + void *cpxstart = (void*)cpx; + void *cpxend = (void*)((uint8_t*)cpx + PAGE_SIZE); + vm_map_protect (kernel_map, cpxstart, cpxend, (VM_PROT_DEFAULT), FALSE); +#endif + bzero(cpx->cpx_cached_key, cpx->cpx_max_key_len); FREE(cpx, M_TEMP); } diff --git a/bsd/vfs/vfs_subr.c b/bsd/vfs/vfs_subr.c index dc434d049..4da9d4535 100644 --- a/bsd/vfs/vfs_subr.c +++ b/bsd/vfs/vfs_subr.c @@ -1027,6 +1027,7 @@ vfs_rootmountalloc(const char *fstypename, const char *devname, mount_t *mpp) return (ENOMEM); } +#define DBG_MOUNTROOT (FSDBG_CODE(DBG_MOUNT, 0)) /* * Find an appropriate filesystem to use for the root. If a filesystem @@ -1049,15 +1050,20 @@ vfs_mountroot(void) mount_t mp; vnode_t bdevvp_rootvp; + KDBG_RELEASE(DBG_MOUNTROOT | DBG_FUNC_START); if (mountroot != NULL) { /* * used for netboot which follows a different set of rules */ error = (*mountroot)(); + + KDBG_RELEASE(DBG_MOUNTROOT | DBG_FUNC_END, error, 0); return (error); } if ((error = bdevvp(rootdev, &rootvp))) { printf("vfs_mountroot: can't setup bdevvp\n"); + + KDBG_RELEASE(DBG_MOUNTROOT | DBG_FUNC_END, error, 1); return (error); } /* @@ -1170,8 +1176,10 @@ vfs_mountroot(void) vnode_put(rootvp); #if CONFIG_MACF - if ((vfs_flags(mp) & MNT_MULTILABEL) == 0) + if ((vfs_flags(mp) & MNT_MULTILABEL) == 0) { + KDBG_RELEASE(DBG_MOUNTROOT | DBG_FUNC_END, 0, 2); return (0); + } error = VFS_ROOT(mp, &vp, ctx); if (error) { @@ -1193,16 +1201,18 @@ vfs_mountroot(void) goto fail; } #endif + KDBG_RELEASE(DBG_MOUNTROOT | DBG_FUNC_END, 0, 3); return (0); } #if CONFIG_MACF fail: #endif vfs_rootmountfailed(mp); - + if (error != EINVAL) printf("%s_mountroot failed: %d\n", vfsp->vfc_name, error); } + KDBG_RELEASE(DBG_MOUNTROOT | DBG_FUNC_END, error ? error : ENODEV, 4); return (ENODEV); } @@ -8782,7 +8792,6 @@ vfs_setcompoundopen(mount_t mp) mount_unlock(mp); } - void vnode_setswapmount(vnode_t vp) { diff --git a/bsd/vfs/vfs_syscalls.c b/bsd/vfs/vfs_syscalls.c index b2209d58d..dccc77bd6 100644 --- a/bsd/vfs/vfs_syscalls.c +++ b/bsd/vfs/vfs_syscalls.c @@ -145,6 +145,18 @@ FREE_ZONE((x), MAXPATHLEN, M_NAMEI); #endif /* CONFIG_FSE */ +#ifndef HFS_GET_BOOT_INFO +#define HFS_GET_BOOT_INFO (FCNTL_FS_SPECIFIC_BASE + 0x00004) +#endif + +#ifndef HFS_SET_BOOT_INFO +#define HFS_SET_BOOT_INFO (FCNTL_FS_SPECIFIC_BASE + 0x00005) +#endif + +#ifndef APFSIOC_REVERT_TO_SNAPSHOT +#define APFSIOC_REVERT_TO_SNAPSHOT _IOW('J', 1, u_int64_t) +#endif + extern void disk_conditioner_unmount(mount_t mp); /* struct for checkdirs iteration */ @@ -162,8 +174,8 @@ static int getfsstat_callback(mount_t mp, void * arg); static int getutimes(user_addr_t usrtvp, struct timespec *tsp); static int setutimes(vfs_context_t ctx, vnode_t vp, const struct timespec *ts, int nullflag); static int sync_callback(mount_t, void *); -static void sync_thread(void *, __unused wait_result_t); -static int sync_async(int); +static void hibernate_sync_thread(void *, __unused wait_result_t); +static int hibernate_sync_async(int); static int munge_statfs(struct mount *mp, struct vfsstatfs *sfsp, user_addr_t bufp, int *sizep, boolean_t is_64_bit, boolean_t partial_copy); @@ -2313,6 +2325,7 @@ int syncprt = 0; int print_vmpage_stat=0; int sync_timeout = 60; // Sync time limit (sec) + static int sync_callback(mount_t mp, __unused void *arg) { @@ -2346,7 +2359,7 @@ sync(__unused proc_t p, __unused struct sync_args *uap, __unused int32_t *retval } static void -sync_thread(void *arg, __unused wait_result_t wr) +hibernate_sync_thread(void *arg, __unused wait_result_t wr) { int *timeout = (int *) arg; @@ -2368,20 +2381,20 @@ sync_thread(void *arg, __unused wait_result_t wr) * Sync in a separate thread so we can time out if it blocks. */ static int -sync_async(int timeout) +hibernate_sync_async(int timeout) { thread_t thd; int error; struct timespec ts = {timeout, 0}; lck_mtx_lock(sync_mtx_lck); - if (kernel_thread_start(sync_thread, &timeout, &thd) != KERN_SUCCESS) { - printf("sync_thread failed\n"); + if (kernel_thread_start(hibernate_sync_thread, &timeout, &thd) != KERN_SUCCESS) { + printf("hibernate_sync_thread failed\n"); lck_mtx_unlock(sync_mtx_lck); return (0); } - error = msleep((caddr_t) &timeout, sync_mtx_lck, (PVFS | PDROP | PCATCH), "sync_thread", &ts); + error = msleep((caddr_t) &timeout, sync_mtx_lck, (PVFS | PDROP | PCATCH), "hibernate_sync_thread", &ts); if (error) { printf("sync timed out: %d sec\n", timeout); } @@ -2396,7 +2409,7 @@ sync_async(int timeout) __private_extern__ int sync_internal(void) { - (void) sync_async(sync_timeout); + (void) hibernate_sync_async(sync_timeout); return 0; } /* end of sync_internal call */ @@ -10444,6 +10457,34 @@ fsctl_internal(proc_t p, vnode_t *arg_vp, u_long cmd, user_addr_t udata, u_long break; default: { + /* other, known commands shouldn't be passed down here */ + switch (cmd) { + case F_PUNCHHOLE: + case F_TRIM_ACTIVE_FILE: + case F_RDADVISE: + case F_TRANSCODEKEY: + case F_GETPROTECTIONLEVEL: + case F_GETDEFAULTPROTLEVEL: + case F_MAKECOMPRESSED: + case F_SET_GREEDY_MODE: + case F_SETSTATICCONTENT: + case F_SETIOTYPE: + case F_SETBACKINGSTORE: + case F_GETPATH_MTMINFO: + case APFSIOC_REVERT_TO_SNAPSHOT: + case FSIOC_FIOSEEKHOLE: + case FSIOC_FIOSEEKDATA: + case HFS_GET_BOOT_INFO: + case HFS_SET_BOOT_INFO: + case FIOPINSWAP: + case F_CHKCLEAN: + case F_FULLFSYNC: + case F_BARRIERFSYNC: + case F_FREEZE_FS: + case F_THAW_FS: + error = EINVAL; + goto outdrop; + } /* Invoke the filesystem-specific code */ error = VNOP_IOCTL(vp, cmd, data, options, ctx); } @@ -10457,6 +10498,7 @@ fsctl_internal(proc_t p, vnode_t *arg_vp, u_long cmd, user_addr_t udata, u_long if (error == 0 && (cmd & IOC_OUT) && size) error = copyout(data, udata, size); +outdrop: if (memp) { kfree(memp, size); } @@ -11712,10 +11754,6 @@ snapshot_revert(int dirfd, user_addr_t name, __unused uint32_t flags, } -#ifndef APFSIOC_REVERT_TO_SNAPSHOT -#define APFSIOC_REVERT_TO_SNAPSHOT _IOW('J', 1, u_int64_t) -#endif - error = VNOP_IOCTL(namend.ni_vp, APFSIOC_REVERT_TO_SNAPSHOT, (caddr_t) NULL, 0, ctx); diff --git a/bsd/vm/vm_unix.c b/bsd/vm/vm_unix.c index 8048a6b80..e94cb60c8 100644 --- a/bsd/vm/vm_unix.c +++ b/bsd/vm/vm_unix.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2017 Apple Inc. All rights reserved. + * Copyright (c) 2000-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -141,7 +141,32 @@ SYSCTL_PROC(_vm, OID_AUTO, kmem_alloc_contig, CTLTYPE_INT|CTLFLAG_WR|CTLFLAG_LOC 0, 0, &sysctl_kmem_alloc_contig, "I", ""); extern int vm_region_footprint; -SYSCTL_INT(_vm, OID_AUTO, region_footprint, CTLFLAG_RW | CTLFLAG_LOCKED, &vm_region_footprint, 0, ""); +SYSCTL_INT(_vm, OID_AUTO, region_footprint, CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_LOCKED, &vm_region_footprint, 0, ""); +static int +sysctl_vm_self_region_footprint SYSCTL_HANDLER_ARGS +{ +#pragma unused(arg1, arg2, oidp) + int error = 0; + int value; + + value = task_self_region_footprint(); + error = SYSCTL_OUT(req, &value, sizeof (int)); + if (error) { + return error; + } + + if (!req->newptr) { + return 0; + } + + error = SYSCTL_IN(req, &value, sizeof (int)); + if (error) { + return (error); + } + task_self_region_footprint_set(value); + return 0; +} +SYSCTL_PROC(_vm, OID_AUTO, self_region_footprint, CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_ANYBODY|CTLFLAG_LOCKED|CTLFLAG_MASKED, 0, 0, &sysctl_vm_self_region_footprint, "I", ""); #endif /* DEVELOPMENT || DEBUG */ @@ -768,8 +793,9 @@ task_for_pid( user_addr_t task_addr = args->t; proc_t p = PROC_NULL; task_t t1 = TASK_NULL; + task_t task = TASK_NULL; mach_port_name_t tret = MACH_PORT_NULL; - ipc_port_t tfpport; + ipc_port_t tfpport = MACH_PORT_NULL; void * sright; int error = 0; @@ -807,60 +833,86 @@ task_for_pid( goto tfpout; } - if (p->task != TASK_NULL) { - /* If we aren't root and target's task access port is set... */ - if (!kauth_cred_issuser(kauth_cred_get()) && - p != current_proc() && - (task_get_task_access_port(p->task, &tfpport) == 0) && - (tfpport != IPC_PORT_NULL)) { + if (p->task == TASK_NULL) { + error = KERN_SUCCESS; + goto tfpout; + } - if (tfpport == IPC_PORT_DEAD) { - error = KERN_PROTECTION_FAILURE; - goto tfpout; - } +#if CONFIG_MACF + error = mac_proc_check_get_task(kauth_cred_get(), p); + if (error) { + error = KERN_FAILURE; + goto tfpout; + } +#endif - /* Call up to the task access server */ - error = __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__(tfpport, proc_selfpid(), kauth_getgid(), pid); + /* Grab a task reference since the proc ref might be dropped if an upcall to task access server is made */ + task = p->task; + task_reference(task); - if (error != MACH_MSG_SUCCESS) { - if (error == MACH_RCV_INTERRUPTED) - error = KERN_ABORTED; - else - error = KERN_FAILURE; - goto tfpout; - } - } -#if CONFIG_MACF - error = mac_proc_check_get_task(kauth_cred_get(), p); - if (error) { - error = KERN_FAILURE; + /* If we aren't root and target's task access port is set... */ + if (!kauth_cred_issuser(kauth_cred_get()) && + p != current_proc() && + (task_get_task_access_port(task, &tfpport) == 0) && + (tfpport != IPC_PORT_NULL)) { + + if (tfpport == IPC_PORT_DEAD) { + error = KERN_PROTECTION_FAILURE; goto tfpout; } -#endif - /* Grant task port access */ - task_reference(p->task); - extmod_statistics_incr_task_for_pid(p->task); + /* + * Drop the proc_find proc ref before making an upcall + * to taskgated, since holding a proc_find + * ref while making an upcall can cause deadlock. + */ + proc_rele(p); + p = PROC_NULL; - sright = (void *) convert_task_to_port(p->task); + /* Call up to the task access server */ + error = __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__(tfpport, proc_selfpid(), kauth_getgid(), pid); - /* Check if the task has been corpsified */ - if (is_corpsetask(p->task)) { - ipc_port_release_send(sright); - error = KERN_FAILURE; + if (error != MACH_MSG_SUCCESS) { + if (error == MACH_RCV_INTERRUPTED) + error = KERN_ABORTED; + else + error = KERN_FAILURE; goto tfpout; } + } + + /* Grant task port access */ + extmod_statistics_incr_task_for_pid(task); + sright = (void *) convert_task_to_port(task); + + /* Check if the task has been corpsified */ + if (is_corpsetask(task)) { + /* task ref consumed by convert_task_to_port */ + task = TASK_NULL; + ipc_port_release_send(sright); + error = KERN_FAILURE; + goto tfpout; + } + + /* task ref consumed by convert_task_to_port */ + task = TASK_NULL; + tret = ipc_port_copyout_send( + sright, + get_task_ipcspace(current_task())); - tret = ipc_port_copyout_send( - sright, - get_task_ipcspace(current_task())); - } error = KERN_SUCCESS; tfpout: task_deallocate(t1); AUDIT_ARG(mach_port2, tret); (void) copyout((char *) &tret, task_addr, sizeof(mach_port_name_t)); + + if (tfpport != IPC_PORT_NULL) { + ipc_port_release_send(tfpport); + } + if (task != TASK_NULL) { + task_deallocate(task); + } if (p != PROC_NULL) proc_rele(p); AUDIT_MACH_SYSCALL_EXIT(error); @@ -1201,38 +1253,90 @@ pid_hibernate(struct proc *p __unused, struct pid_hibernate_args *args, int *ret #endif /* CONFIG_EMBEDDED */ #if SOCKETS +int +networking_memstatus_callout(proc_t p, uint32_t status) +{ + struct filedesc *fdp; + int i; + + /* + * proc list lock NOT held + * proc lock NOT held + * a reference on the proc has been held / shall be dropped by the caller. + */ + LCK_MTX_ASSERT(proc_list_mlock, LCK_MTX_ASSERT_NOTOWNED); + LCK_MTX_ASSERT(&p->p_mlock, LCK_MTX_ASSERT_NOTOWNED); + + proc_fdlock(p); + fdp = p->p_fd; + for (i = 0; i < fdp->fd_nfiles; i++) { + struct fileproc *fp; + + fp = fdp->fd_ofiles[i]; + if (fp == NULL || (fdp->fd_ofileflags[i] & UF_RESERVED) != 0) { + continue; + } + switch (FILEGLOB_DTYPE(fp->f_fglob)) { +#if NECP + case DTYPE_NETPOLICY: + necp_fd_memstatus(p, status, + (struct necp_fd_data *)fp->f_fglob->fg_data); + break; +#endif /* NECP */ + default: + break; + } + } + proc_fdunlock(p); + + return (1); +} + + static int -shutdown_sockets_callout(proc_t p, void *arg) +networking_defunct_callout(proc_t p, void *arg) { struct pid_shutdown_sockets_args *args = arg; int pid = args->pid; int level = args->level; struct filedesc *fdp; - struct fileproc *fp; int i; proc_fdlock(p); fdp = p->p_fd; for (i = 0; i < fdp->fd_nfiles; i++) { - fp = fdp->fd_ofiles[i]; + struct fileproc *fp = fdp->fd_ofiles[i]; + struct fileglob *fg; + if (fp == NULL || (fdp->fd_ofileflags[i] & UF_RESERVED) != 0) { continue; } - if (FILEGLOB_DTYPE(fp->f_fglob) == DTYPE_SOCKET) { - struct socket *so = (struct socket *)fp->f_fglob->fg_data; + + fg = fp->f_fglob; + switch (FILEGLOB_DTYPE(fg)) { + case DTYPE_SOCKET: { + struct socket *so = (struct socket *)fg->fg_data; if (p->p_pid == pid || so->last_pid == pid || ((so->so_flags & SOF_DELEGATED) && so->e_pid == pid)) { /* Call networking stack with socket and level */ (void) socket_defunct(p, so, level); } + break; } #if NECP - else if (FILEGLOB_DTYPE(fp->f_fglob) == DTYPE_NETPOLICY && - p->p_pid == pid) { - necp_defunct_client(p, fp); - } + case DTYPE_NETPOLICY: + /* first pass: defunct necp and get stats for ntstat */ + if (p->p_pid == pid) { + necp_fd_defunct(p, + (struct necp_fd_data *)fg->fg_data); + } + break; #endif /* NECP */ + default: + break; + } } + proc_fdunlock(p); return (PROC_RETURNED); @@ -1271,7 +1375,8 @@ pid_shutdown_sockets(struct proc *p __unused, struct pid_shutdown_sockets_args * goto out; } - proc_iterate(PROC_ALLPROCLIST | PROC_NOWAITTRANS, shutdown_sockets_callout, args, NULL, NULL); + proc_iterate(PROC_ALLPROCLIST | PROC_NOWAITTRANS, + networking_defunct_callout, args, NULL, NULL); out: if (targetproc != PROC_NULL) diff --git a/config/IOKit.exports b/config/IOKit.exports index be6ca8013..0f0678d3d 100644 --- a/config/IOKit.exports +++ b/config/IOKit.exports @@ -642,6 +642,7 @@ __ZN17IOBigMemoryCursorC2Ev __ZN17IOBigMemoryCursorD0Ev __ZN17IOBigMemoryCursorD2Ev __ZN17IOPolledInterface10gMetaClassE +__ZN17IOPolledInterface16setEncryptionKeyEPKhm __ZN17IOPolledInterfaceC2EPK11OSMetaClass __ZN17IOPolledInterfaceD2Ev __ZN17IOPowerConnection10gMetaClassE diff --git a/config/IOKit.x86_64.exports b/config/IOKit.x86_64.exports index d050685e3..1f7734ca8 100644 --- a/config/IOKit.x86_64.exports +++ b/config/IOKit.x86_64.exports @@ -190,7 +190,6 @@ __ZN16IORangeAllocator9withRangeEyyjj __ZN17IOBigMemoryCursor13outputSegmentEN14IOMemoryCursor15PhysicalSegmentEPvj __ZN17IOBigMemoryCursor17withSpecificationEyyy __ZN17IOBigMemoryCursor21initWithSpecificationEyyy -__ZN17IOPolledInterface27_RESERVEDIOPolledInterface0Ev __ZN17IOPolledInterface27_RESERVEDIOPolledInterface1Ev __ZN17IOPolledInterface27_RESERVEDIOPolledInterface2Ev __ZN17IOPolledInterface27_RESERVEDIOPolledInterface3Ev diff --git a/config/Libkern.exports b/config/Libkern.exports index 6769ed75b..173707504 100644 --- a/config/Libkern.exports +++ b/config/Libkern.exports @@ -44,9 +44,15 @@ _OSlibkernInit _SHA1Final _SHA1Init _SHA1Update +_SHA256_Final +_SHA256_Init +_SHA256_Update _SHA384_Final _SHA384_Init _SHA384_Update +_SHA512_Final +_SHA512_Init +_SHA512_Update _STRDUP __Z13OSUnserializePKcPP8OSString __Z16OSUnserializeXMLPKcPP8OSString @@ -709,6 +715,7 @@ _page_shift _page_size _panic _printf +_random_buf _sha1_init:_SHA1Init _sha1_loop:_SHA1Update _sha1_result:_SHA1Final_r diff --git a/config/MASTER.arm b/config/MASTER.arm index b534c3569..8deb4e445 100644 --- a/config/MASTER.arm +++ b/config/MASTER.arm @@ -1,7 +1,7 @@ # # Mach Operating System # Copyright (c) 1986 Carnegie-Mellon University -# Copyright 2001-2016 Apple Inc. +# Copyright 2001-2018 Apple Inc. # # All rights reserved. The CMU software License Agreement # specifies the terms and conditions for use and redistribution. @@ -29,10 +29,6 @@ # FILESYS_DEV = [ FILESYS_BASE fdesc ] # FILESYS_DEBUG = [ FILESYS_BASE fdesc ] # NFS = [ nfsclient nfsserver ] -# SKYWALK_BASE = [ skywalk config_nexus_user_pipe config_nexus_kernel_pipe config_nexus_monitor config_nexus_flowswitch config_nexus_netif ] -# SKYWALK_RELEASE = [ SKYWALK_BASE ] -# SKYWALK_DEV = [ SKYWALK_BASE ] -# SKYWALK_DEBUG = [ SKYWALK_BASE ] # NETWORKING = [ inet tcpdrop_synfin bpfilter inet6 ipv6send if_bridge traffic_mgt dummynet ah_all_crypto if_fake ] # VPN = [ ipsec flow_divert necp content_filter ] # PF = [ pf ] diff --git a/config/MASTER.arm64 b/config/MASTER.arm64 index ae4eb4903..a6636b773 100644 --- a/config/MASTER.arm64 +++ b/config/MASTER.arm64 @@ -1,7 +1,7 @@ # # Mach Operating System # Copyright (c) 1986 Carnegie-Mellon University -# Copyright 2001-2016 Apple Inc. +# Copyright 2001-2018 Apple Inc. # # All rights reserved. The CMU software License Agreement # specifies the terms and conditions for use and redistribution. @@ -29,10 +29,6 @@ # FILESYS_DEV = [ FILESYS_BASE fdesc ] # FILESYS_DEBUG = [ FILESYS_BASE fdesc ] # NFS = [ nfsclient nfsserver ] -# SKYWALK_BASE = [ skywalk config_nexus_user_pipe config_nexus_kernel_pipe config_nexus_monitor config_nexus_flowswitch config_nexus_netif ] -# SKYWALK_RELEASE = [ SKYWALK_BASE ] -# SKYWALK_DEV = [ SKYWALK_BASE ] -# SKYWALK_DEBUG = [ SKYWALK_BASE ] # NETWORKING = [ inet tcpdrop_synfin bpfilter inet6 ipv6send if_bridge traffic_mgt dummynet ah_all_crypto packet_mangler if_fake ] # VPN = [ ipsec flow_divert necp content_filter ] # PF = [ pf ] diff --git a/config/Mach.exports b/config/Mach.exports index a33253ff5..439e238c6 100644 --- a/config/Mach.exports +++ b/config/Mach.exports @@ -4,6 +4,7 @@ _assert_wait _assert_wait_deadline _assert_wait_timeout _clock_absolutetime_interval_to_deadline +_clock_continuoustime_interval_to_deadline _clock_delay_until _clock_get_calendar_microtime _clock_get_calendar_nanotime diff --git a/config/MasterVersion b/config/MasterVersion index 7efb2c146..0996d29e7 100644 --- a/config/MasterVersion +++ b/config/MasterVersion @@ -1,4 +1,4 @@ -17.4.0 +17.5.0 # The first line of this file contains the master version number for the kernel. # All other instances of the kernel version in xnu are derived from this file. diff --git a/config/Private.exports b/config/Private.exports index 5ce2ff9c6..5630d2a50 100644 --- a/config/Private.exports +++ b/config/Private.exports @@ -7,6 +7,9 @@ __ZNK18IODTPlatformExpert* __ZTV18IODTPlatformExpert __ZN5IOCPU* __ZNK5IOCPU* +__ZN12IOUserClient27copyObjectForPortNameInTaskEP4taskjPP8OSObject +__ZN12IOUserClient27copyPortNameForObjectInTaskEP4taskP8OSObjectPj +__ZN12IOUserClient30adjustPortNameReferencesInTaskEP4taskji __ZTV5IOCPU __ZN24IOCPUInterruptController* __ZNK24IOCPUInterruptController* @@ -49,7 +52,6 @@ _bufattr_setcpx _bufattr_throttled _cdevsw _cdevsw_setkqueueok -_chudxnu_platform_ptr _clalloc _clfree _cluster_unlock_direct_read @@ -85,6 +87,7 @@ _cpx_size _cpx_sizex _cpx_use_offset_for_iv _cpx_synthetic_offset_for_iv +_cpx_writeprotect _cs_blob_reset_cache _cs_debug _cs_enforcement @@ -111,18 +114,22 @@ _csblob_get_teamid _csblob_get_signer_type _csblob_get_size _csfg_get_cdhash +_csfg_get_identity _csfg_get_path _csfg_get_platform_binary +_csfg_get_platform_identifier _csfg_get_prod_signed _csfg_get_signer_type _csfg_get_teamid _csproc_get_blob _csproc_get_platform_binary +_csproc_get_platform_identifier _csproc_get_prod_signed _csproc_get_signer_type _csproc_get_teamid _csvnode_get_blob _csvnode_get_teamid +_csvnode_get_platform_identifier _csvnode_print_debug _ctl_enqueuembuf_list _ctl_id_by_name @@ -393,8 +400,10 @@ _thread_call_allocate_with_priority _thread_call_allocate_with_qos _thread_call_cancel_wait _thread_clear_eager_preempt +_thread_clear_honor_qlimit _thread_dispatchqaddr _thread_set_eager_preempt +_thread_set_honor_qlimit _thread_set_mach_voucher _thread_set_pending_block_hint _throttle_info_create @@ -410,6 +419,7 @@ _throttle_info_update_by_mask _throttle_lowpri_io _throttle_lowpri_window _throttle_set_thread_io_policy +_throttle_get_thread_effective_io_policy _timeout _timeout_with_leeway _tk_nin diff --git a/config/Private.x86_64.exports b/config/Private.x86_64.exports index 5341bdbfe..52902c403 100644 --- a/config/Private.x86_64.exports +++ b/config/Private.x86_64.exports @@ -1,9 +1,6 @@ _IOGetBootKeyStoreData _IOGetAPFSKeyStoreData _IOSetAPFSKeyStoreData -_SHA256_Final -_SHA256_Init -_SHA256_Update __ZN14IOPMrootDomain20claimSystemWakeEventEP9IOServicejPKcP8OSObject __ZN14IOPMrootDomain20restartWithStackshotEv __ZN22IOInterruptEventSource7warmCPUEy diff --git a/iokit/IOKit/IOBufferMemoryDescriptor.h b/iokit/IOKit/IOBufferMemoryDescriptor.h index 6e6f051b9..4b218498b 100644 --- a/iokit/IOKit/IOBufferMemoryDescriptor.h +++ b/iokit/IOKit/IOBufferMemoryDescriptor.h @@ -70,6 +70,7 @@ class IOBufferMemoryDescriptor : public IOGeneralMemoryDescriptor /*! @var reserved Reserved for future use. (Internal use only) */ + APPLE_KEXT_WSHADOW_PUSH; ExpansionData * reserved; protected: @@ -80,6 +81,7 @@ class IOBufferMemoryDescriptor : public IOGeneralMemoryDescriptor private: uintptr_t _internalReserved; unsigned _internalFlags; + APPLE_KEXT_WSHADOW_POP; private: #ifndef __LP64__ diff --git a/iokit/IOKit/IOCPU.h b/iokit/IOKit/IOCPU.h index 1ee373c3e..7b1e219c5 100644 --- a/iokit/IOKit/IOCPU.h +++ b/iokit/IOKit/IOCPU.h @@ -66,7 +66,7 @@ class IOCPU : public IOService ipi_handler_t ipi_handler; struct ExpansionData { }; - ExpansionData *reserved; + ExpansionData *iocpu_reserved; virtual void setCPUNumber(UInt32 cpuNumber); virtual void setCPUState(UInt32 cpuState); @@ -124,7 +124,7 @@ class IOCPUInterruptController : public IOInterruptController int numSources; struct ExpansionData { }; - ExpansionData *reserved; + ExpansionData *iocpuic_reserved; public: virtual IOReturn initCPUInterruptController(int sources); diff --git a/iokit/IOKit/IOCommandGate.h b/iokit/IOKit/IOCommandGate.h index ce4851284..4bc13d299 100644 --- a/iokit/IOKit/IOCommandGate.h +++ b/iokit/IOKit/IOCommandGate.h @@ -91,7 +91,9 @@ member function's parameter list. /*! @var reserved Reserved for future use. (Internal use only) */ + APPLE_KEXT_WSHADOW_PUSH; ExpansionData *reserved; + APPLE_KEXT_WSHADOW_POP; public: /*! @function commandGate diff --git a/iokit/IOKit/IOFilterInterruptEventSource.h b/iokit/IOKit/IOFilterInterruptEventSource.h index 13ef854d8..3cf68bf11 100644 --- a/iokit/IOKit/IOFilterInterruptEventSource.h +++ b/iokit/IOKit/IOFilterInterruptEventSource.h @@ -90,7 +90,9 @@ class IOFilterInterruptEventSource : public IOInterruptEventSource /*! @var reserved Reserved for future use. (Internal use only) */ + APPLE_KEXT_WSHADOW_PUSH; ExpansionData *reserved; + APPLE_KEXT_WSHADOW_POP; public: /*! @function filterInterruptEventSource diff --git a/iokit/IOKit/IOHibernatePrivate.h b/iokit/IOKit/IOHibernatePrivate.h index cf8aa46df..b6f3b7f62 100644 --- a/iokit/IOKit/IOHibernatePrivate.h +++ b/iokit/IOKit/IOHibernatePrivate.h @@ -2,7 +2,7 @@ * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in @@ -11,10 +11,10 @@ * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. - * + * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -22,7 +22,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ @@ -54,14 +54,14 @@ struct IOHibernateImageHeader { uint64_t imageSize; uint64_t image1Size; - + uint32_t restore1CodePhysPage; uint32_t reserved1; uint64_t restore1CodeVirt; uint32_t restore1PageCount; uint32_t restore1CodeOffset; uint32_t restore1StackOffset; - + uint32_t pageCount; uint32_t bitmapSize; @@ -86,7 +86,7 @@ struct IOHibernateImageHeader uint32_t performanceDataStart; uint32_t performanceDataSize; - + uint64_t encryptStart __attribute__ ((packed)); uint64_t machineSignature __attribute__ ((packed)); @@ -105,7 +105,9 @@ struct IOHibernateImageHeader uint32_t sleepTime; uint32_t compression; - uint32_t reserved[58]; // make sizeof == 512 + uint8_t bridgeBootSessionUUID[16]; + + uint32_t reserved[54]; // make sizeof == 512 uint32_t booterTime0; uint32_t booterTime1; uint32_t booterTime2; @@ -138,6 +140,7 @@ enum kIOHibernateOptionColor = 0x00000002, kIOHibernateOptionProgress = 0x00000004, kIOHibernateOptionDarkWake = 0x00000008, + kIOHibernateOptionHWEncrypt = 0x00000010, }; struct hibernate_bitmap_t @@ -175,7 +178,7 @@ typedef struct hibernate_cryptvars_t hibernate_cryptvars_t; #endif /* defined(_AES_H) */ -enum +enum { kIOHibernateHandoffType = 0x686f0000, kIOHibernateHandoffTypeEnd = kIOHibernateHandoffType + 0, @@ -185,6 +188,7 @@ enum kIOHibernateHandoffTypeDeviceTree = kIOHibernateHandoffType + 4, kIOHibernateHandoffTypeDeviceProperties = kIOHibernateHandoffType + 5, kIOHibernateHandoffTypeKeyStore = kIOHibernateHandoffType + 6, + kIOHibernateHandoffTypeVolumeCryptKey = kIOHibernateHandoffType + 7, }; struct IOHibernateHandoff @@ -195,7 +199,7 @@ struct IOHibernateHandoff }; typedef struct IOHibernateHandoff IOHibernateHandoff; -enum +enum { kIOHibernateProgressCount = 19, kIOHibernateProgressWidth = 7, @@ -326,28 +330,28 @@ vm_compressor_do_warmup(void); hibernate_page_list_t * hibernate_page_list_allocate(boolean_t log); -kern_return_t +kern_return_t hibernate_alloc_page_lists( hibernate_page_list_t ** page_list_ret, hibernate_page_list_t ** page_list_wired_ret, hibernate_page_list_t ** page_list_pal_ret); -kern_return_t +kern_return_t hibernate_setup(IOHibernateImageHeader * header, boolean_t vmflush, hibernate_page_list_t * page_list, hibernate_page_list_t * page_list_wired, hibernate_page_list_t * page_list_pal); -kern_return_t +kern_return_t hibernate_teardown(hibernate_page_list_t * page_list, hibernate_page_list_t * page_list_wired, hibernate_page_list_t * page_list_pal); -kern_return_t +kern_return_t hibernate_pin_swap(boolean_t begin); -kern_return_t +kern_return_t hibernate_processor_setup(IOHibernateImageHeader * header); void @@ -374,11 +378,11 @@ void hibernate_page_list_setall(hibernate_page_list_t * page_list, hibernate_page_list_t * page_list_wired, hibernate_page_list_t * page_list_pal, - boolean_t preflight, + boolean_t preflight, boolean_t discard_all, uint32_t * pagesOut); -// mark pages to be saved, or pages not to be saved but available +// mark pages to be saved, or pages not to be saved but available // for scratch usage during restore void hibernate_page_list_setall_machine(hibernate_page_list_t * page_list, @@ -402,10 +406,10 @@ void hibernate_set_page_state(hibernate_page_list_t * page_list, hibernate_page_list_t * page_list_wired, vm_offset_t ppnum, vm_offset_t count, uint32_t kind); -void +void hibernate_page_bitset(hibernate_page_list_t * list, boolean_t set, uint32_t page); -boolean_t +boolean_t hibernate_page_bittst(hibernate_page_list_t * list, uint32_t page); hibernate_bitmap_t * @@ -414,7 +418,7 @@ hibernate_page_bitmap_pin(hibernate_page_list_t * list, uint32_t * page); uint32_t hibernate_page_bitmap_count(hibernate_bitmap_t * bitmap, uint32_t set, uint32_t page); -uintptr_t +uintptr_t hibernate_restore_phys_page(uint64_t src, uint64_t dst, uint32_t len, uint32_t procFlags); void @@ -428,7 +432,7 @@ hibernate_machine_entrypoint(uint32_t p1, uint32_t p2, uint32_t p3, uint32_t p4) long hibernate_kernel_entrypoint(uint32_t p1, uint32_t p2, uint32_t p3, uint32_t p4); void -hibernate_newruntime_map(void * map, vm_size_t map_size, +hibernate_newruntime_map(void * map, vm_size_t map_size, uint32_t system_table_offset); @@ -538,8 +542,8 @@ enum { enum { - kIOPreviewImageIndexDesktop = 0, - kIOPreviewImageIndexLockScreen = 1, + kIOPreviewImageIndexDesktop = 0, + kIOPreviewImageIndexLockScreen = 1, kIOPreviewImageCount = 2 }; @@ -549,7 +553,7 @@ enum kIOScreenLockUnlocked = 2, kIOScreenLockLocked = 3, kIOScreenLockFileVaultDialog = 4, -}; +}; #define kIOScreenLockStateKey "IOScreenLockState" #define kIOBooterScreenLockStateKey "IOBooterScreenLockState" diff --git a/iokit/IOKit/IOInterruptController.h b/iokit/IOKit/IOInterruptController.h index 0a634b056..eca74ce9c 100644 --- a/iokit/IOKit/IOInterruptController.h +++ b/iokit/IOKit/IOInterruptController.h @@ -74,7 +74,7 @@ class IOInterruptController : public IOService IOSimpleLock *controllerLock; struct ExpansionData { }; - ExpansionData *reserved; + ExpansionData *ioic_reserved; public: virtual IOReturn registerInterrupt(IOService *nub, int source, @@ -135,7 +135,7 @@ class IOSharedInterruptController : public IOInterruptController bool sourceIsLevel; struct ExpansionData { }; - ExpansionData *reserved; + ExpansionData *iosic_reserved __unused; public: virtual IOReturn initInterruptController(IOInterruptController *parentController, OSData *parentSource); diff --git a/iokit/IOKit/IOInterruptEventSource.h b/iokit/IOKit/IOInterruptEventSource.h index 693fb800e..6acde040b 100644 --- a/iokit/IOKit/IOInterruptEventSource.h +++ b/iokit/IOKit/IOInterruptEventSource.h @@ -104,7 +104,9 @@ class IOInterruptEventSource : public IOEventSource /*! @var reserved Reserved for future use. (Internal use only) */ + APPLE_KEXT_WSHADOW_PUSH; ExpansionData *reserved; + APPLE_KEXT_WSHADOW_POP; /*! @function free @abstract Sub-class implementation of free method, disconnects from the interrupt source. */ diff --git a/iokit/IOKit/IOKitKeysPrivate.h b/iokit/IOKit/IOKitKeysPrivate.h index 146968d7e..5ecf86f08 100644 --- a/iokit/IOKit/IOKitKeysPrivate.h +++ b/iokit/IOKit/IOKitKeysPrivate.h @@ -2,7 +2,7 @@ * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * + * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in @@ -11,10 +11,10 @@ * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. - * + * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. - * + * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, @@ -22,7 +22,7 @@ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. - * + * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ @@ -54,6 +54,7 @@ // IODeviceTree:chosen properties #define kIOProgressBackbufferKey "IOProgressBackbuffer" /* value is OSData */ #define kIOProgressColorThemeKey "IOProgressColorTheme" /* value is OSNumber */ +#define kIOBridgeBootSessionUUIDKey "bridge-boot-session-uuid" /* value is OSData */ // interest type #define kIOConsoleSecurityInterest "IOConsoleSecurityInterest" diff --git a/iokit/IOKit/IOKitServer.h b/iokit/IOKit/IOKitServer.h index 48ff9580d..927ad8cb2 100644 --- a/iokit/IOKit/IOKitServer.h +++ b/iokit/IOKit/IOKitServer.h @@ -113,5 +113,83 @@ enum { kIOCatalogServiceTerminate }; + +#ifdef XNU_KERNEL_PRIVATE + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include + +/* + * Functions in iokit:IOUserClient.cpp + */ + +extern void iokit_add_reference( io_object_t obj, ipc_kobject_type_t type ); + +extern ipc_port_t iokit_port_for_object( io_object_t obj, + ipc_kobject_type_t type ); + +extern kern_return_t iokit_client_died( io_object_t obj, + ipc_port_t port, ipc_kobject_type_t type, mach_port_mscount_t * mscount ); + +extern kern_return_t +iokit_client_memory_for_type( + io_object_t connect, + unsigned int type, + unsigned int * flags, + vm_address_t * address, + vm_size_t * size ); + +/* + * Functions in osfmk:iokit_rpc.c + */ + +extern ipc_port_t iokit_alloc_object_port( io_object_t obj, + ipc_kobject_type_t type ); + +extern kern_return_t iokit_destroy_object_port( ipc_port_t port ); + +extern mach_port_name_t iokit_make_send_right( task_t task, + io_object_t obj, ipc_kobject_type_t type ); + +extern kern_return_t iokit_mod_send_right( task_t task, mach_port_name_t name, mach_port_delta_t delta ); + +extern io_object_t iokit_lookup_object_with_port_name(mach_port_name_t name, ipc_kobject_type_t type, task_t task); + +extern io_object_t iokit_lookup_connect_ref_current_task(mach_port_name_t name); + +extern void iokit_retain_port( ipc_port_t port ); +extern void iokit_release_port( ipc_port_t port ); +extern void iokit_release_port_send( ipc_port_t port ); + +extern void iokit_lock_port(ipc_port_t port); +extern void iokit_unlock_port(ipc_port_t port); + +extern kern_return_t iokit_switch_object_port( ipc_port_t port, io_object_t obj, ipc_kobject_type_t type ); + +/* + * Functions imported by iokit:IOMemoryDescriptor.cpp + */ + +extern ppnum_t IOGetLastPageNumber(void); + +extern kern_return_t IOMapPages(vm_map_t map, mach_vm_address_t va, mach_vm_address_t pa, + mach_vm_size_t length, unsigned int mapFlags); + +extern kern_return_t IOUnmapPages(vm_map_t map, mach_vm_address_t va, mach_vm_size_t length); + +extern kern_return_t IOProtectCacheMode(vm_map_t map, mach_vm_address_t va, + mach_vm_size_t length, unsigned int options); + +extern unsigned int IODefaultCacheBits(addr64_t pa); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* MACH_KERNEL_PRIVATE */ + #endif /* ! _IOKIT_IOKITSERVER_H */ diff --git a/iokit/IOKit/IONVRAM.h b/iokit/IOKit/IONVRAM.h index 31d5e0967..b58ea8490 100644 --- a/iokit/IOKit/IONVRAM.h +++ b/iokit/IOKit/IONVRAM.h @@ -136,6 +136,7 @@ class IODTNVRAM : public IOService void initNVRAMImage(void); void initProxyData(void); + IOReturn syncVariables(void); public: virtual bool init(IORegistryEntry *old, const IORegistryPlane *plane) APPLE_KEXT_OVERRIDE; diff --git a/iokit/IOKit/IOPlatformExpert.h b/iokit/IOKit/IOPlatformExpert.h index 63029bb1d..4f5c8067f 100644 --- a/iokit/IOKit/IOPlatformExpert.h +++ b/iokit/IOKit/IOPlatformExpert.h @@ -73,6 +73,14 @@ enum { extern int (*PE_halt_restart)(unsigned int type); extern int PEHaltRestart(unsigned int type); +#ifdef XNU_KERNEL_PRIVATE +enum { + kIOSystemShutdownNotificationStageProcessExit = 0, + kIOSystemShutdownNotificationStageRootUnmount = 1, +}; +extern void IOSystemShutdownNotification(int stage); +#endif /* XNU_KERNEL_PRIVATE */ + // Save the Panic Info. Returns the number of bytes saved. extern UInt32 PESavePanicInfo(UInt8 *buffer, UInt32 length); extern void PESavePanicInfoAction(void *buffer, UInt32 offset, UInt32 length); @@ -141,7 +149,7 @@ class IOPlatformExpert : public IOService int numInstancesRegistered; struct ExpansionData { }; - ExpansionData *reserved; + ExpansionData *iope_reserved __unused; virtual void setBootROMType(long peBootROMType); virtual void setChipSetType(long peChipSetType); @@ -236,7 +244,7 @@ class IODTPlatformExpert : public IOPlatformExpert IODTNVRAM *dtNVRAM; struct ExpansionData { }; - ExpansionData *reserved; + ExpansionData *iodtpe_reserved; public: virtual IOService * probe( IOService * provider, @@ -313,7 +321,7 @@ class IOPlatformExpertDevice : public IOService IOWorkLoop *workLoop; struct ExpansionData { }; - ExpansionData *reserved; + ExpansionData *ioped_reserved __unused; public: virtual bool initWithArgs( void * p1, void * p2, @@ -345,7 +353,7 @@ class IOPlatformDevice : public IOService OSDeclareDefaultStructors(IOPlatformDevice) struct ExpansionData { }; - ExpansionData *reserved; + ExpansionData *iopd_reserved; public: virtual bool compareName( OSString * name, OSString ** matched = 0 ) const APPLE_KEXT_OVERRIDE; diff --git a/iokit/IOKit/IOPolledInterface.h b/iokit/IOKit/IOPolledInterface.h index cd1ba5986..84d27043b 100644 --- a/iokit/IOKit/IOPolledInterface.h +++ b/iokit/IOKit/IOPolledInterface.h @@ -91,7 +91,9 @@ class IOPolledInterface : public OSObject virtual IOReturn checkForWork(void) = 0; - OSMetaClassDeclareReservedUnused(IOPolledInterface, 0); + virtual IOReturn setEncryptionKey(const uint8_t * key, size_t keySize); + + OSMetaClassDeclareReservedUsed(IOPolledInterface, 0); OSMetaClassDeclareReservedUnused(IOPolledInterface, 1); OSMetaClassDeclareReservedUnused(IOPolledInterface, 2); OSMetaClassDeclareReservedUnused(IOPolledInterface, 3); @@ -177,7 +179,7 @@ IOReturn IOPolledFileOpen(const char * filename, void * write_file_addr, size_t write_file_len, IOPolledFileIOVars ** fileVars, OSData ** imagePath, - uint8_t * volumeCryptKey, size_t keySize); + uint8_t * volumeCryptKey, size_t * keySize); IOReturn IOPolledFileClose(IOPolledFileIOVars ** pVars, off_t write_offset, void * addr, size_t write_length, @@ -210,6 +212,9 @@ extern __C IOReturn IOPolledFilePollersOpen(IOPolledFileIOVars * vars, uint32_t extern __C IOReturn IOPolledFilePollersClose(IOPolledFileIOVars * vars, uint32_t state); +extern __C IOReturn IOPolledFilePollersSetEncryptionKey(IOPolledFileIOVars * vars, + const uint8_t * key, size_t keySize); + extern __C IOPolledFileIOVars * gCoreFileVars; #ifdef _SYS_CONF_H_ diff --git a/iokit/IOKit/IOService.h b/iokit/IOKit/IOService.h index 89ce8909d..20ad4e6ab 100644 --- a/iokit/IOKit/IOService.h +++ b/iokit/IOKit/IOService.h @@ -319,7 +319,9 @@ class IOService : public IORegistryEntry /*! @var reserved Reserved for future use. (Internal use only) */ + APPLE_KEXT_WSHADOW_PUSH; ExpansionData * reserved; + APPLE_KEXT_WSHADOW_POP; private: IOService * __provider; diff --git a/iokit/IOKit/IOTimerEventSource.h b/iokit/IOKit/IOTimerEventSource.h index 49b5f257b..91ab47cf0 100644 --- a/iokit/IOKit/IOTimerEventSource.h +++ b/iokit/IOKit/IOTimerEventSource.h @@ -130,7 +130,9 @@ class IOTimerEventSource : public IOEventSource /*! @var reserved Reserved for future use. (Internal use only) */ + APPLE_KEXT_WSHADOW_PUSH; ExpansionData *reserved; + APPLE_KEXT_WSHADOW_POP; /*! @function timeout @abstract Function that routes the call from the OS' timeout mechanism into a work-loop context. diff --git a/iokit/IOKit/IOUserClient.h b/iokit/IOKit/IOUserClient.h index 2aa05be08..6a7149827 100644 --- a/iokit/IOKit/IOUserClient.h +++ b/iokit/IOKit/IOUserClient.h @@ -195,7 +195,9 @@ class IOUserClient : public IOService /*! @var reserved Reserved for future use. (Internal use only) */ + APPLE_KEXT_WSHADOW_PUSH; ExpansionData * reserved; + APPLE_KEXT_WSHADOW_POP; bool reserve(); @@ -386,6 +388,46 @@ class IOUserClient : public IOService virtual IOReturn exportObjectToClient(task_t task, OSObject *obj, io_object_t *clientObj); +#if KERNEL_PRIVATE + + /*! + @function copyPortNameForObjectInTask + Make an arbitrary OSObject available to the client task as a port name. + The port does not respond to any IOKit IPC calls. + @param task The task. + @param object The object we want to export to the client. + The port holds a reference on the object, this function does not consume any reference on the object. + @param port_name Returned value is the task's port name. It has one send right created by this function. + @result A return code. + */ + static IOReturn copyPortNameForObjectInTask(task_t task, OSObject *object, + mach_port_name_t * port_name); + + /*! + @function copyObjectForPortNameInTask + Look up an OSObject given a task's port name created with copyPortNameForObjectInTask(). + @param task The task. + @param port_name The task's port name. This function does not consume any reference on the port name. + @param object If the port name is valid, a reference to the object is returned. It should be released by the caller. + @result A return code. + */ + static IOReturn copyObjectForPortNameInTask(task_t task, mach_port_name_t port_name, + OSObject **object); + + /*! + @function adjustPortNameReferencesInTask + Adjust the send rights for a port name created with copyPortNameForObjectInTask(). + @param task The task. + @param port_name The task's port name. + @param delta Signed value change to the number of user references. + @result A return code. + */ + static IOReturn adjustPortNameReferencesInTask(task_t task, mach_port_name_t port_name, mach_port_delta_t delta); + +#define IOUC_COPYPORTNAMEFOROBJECTINTASK 1 + +#endif /* KERNEL_PRIVATE */ + // Old methods for accessing method vector backward compatiblility only virtual IOExternalMethod * getExternalMethodForIndex( UInt32 index ) diff --git a/iokit/IOKit/pwr_mgt/IOPM.h b/iokit/IOKit/pwr_mgt/IOPM.h index 3fc00ebae..c83933543 100644 --- a/iokit/IOKit/pwr_mgt/IOPM.h +++ b/iokit/IOKit/pwr_mgt/IOPM.h @@ -614,7 +614,9 @@ enum { #define kIOPMPSAdapterDetailsPMUConfigurationKey "PMUConfiguration" #define kIOPMPSAdapterDetailsVoltage "AdapterVoltage" #define kIOPMPSAdapterDetailsSourceIDKey "SourceID" +#define kIOPMPSAdapterDetailsErrorFlagsKey "ErrorFlags" #define kIOPMPSAdapterDetailsSharedSourceKey "SharedSource" +#define kIOPMPSAdapterDetailsCloakedKey "CloakedSource" // values for kIOPSPowerAdapterFamilyKey enum { @@ -636,6 +638,14 @@ enum { kIOPSFamilyCodeExternal4 = iokit_family_err(sub_iokit_pmu, 4), }; +// values for kIOPMPSAdapterDetailsErrorFlagsKey +enum { + kIOPSAdapterErrorFlagNoErrors = 0, + kIOPSAdapterErrorFlagInsufficientAvailablePower = (1 << 1), + kIOPSAdapterErrorFlagForeignObjectDetected = (1 << 2), + kIOPSAdapterErrorFlagDeviceNeedsToBeRepositioned = (1 << 3), +}; + // Battery's time remaining estimate is invalid this long (seconds) after a wake #define kIOPMPSInvalidWakeSecondsKey "BatteryInvalidWakeSeconds" diff --git a/iokit/IOKit/system_management/IOWatchDogTimer.h b/iokit/IOKit/system_management/IOWatchDogTimer.h index ef5db4353..fe031ce42 100644 --- a/iokit/IOKit/system_management/IOWatchDogTimer.h +++ b/iokit/IOKit/system_management/IOWatchDogTimer.h @@ -38,7 +38,9 @@ class IOWatchDogTimer : public IOService protected: IONotifier *notifier; struct ExpansionData { }; + APPLE_KEXT_WSHADOW_PUSH; ExpansionData *reserved; + APPLE_KEXT_WSHADOW_POP; public: virtual bool start(IOService *provider) APPLE_KEXT_OVERRIDE; diff --git a/iokit/Kernel/IOCommandQueue.cpp b/iokit/Kernel/IOCommandQueue.cpp index 1b4f3ce23..532cd57c0 100644 --- a/iokit/Kernel/IOCommandQueue.cpp +++ b/iokit/Kernel/IOCommandQueue.cpp @@ -229,7 +229,7 @@ IOCommandQueue::enqueueCommand(bool gotoSleep, /* * Make sure that we update the current producer entry before we * increment the producer pointer. This avoids a nasty race as the - * as the test for work is producerIndex != consumerIndex and a signal. + * test for work is producerIndex != consumerIndex and a signal. */ { commandEntryT *q = (commandEntryT *) queue; diff --git a/iokit/Kernel/IOHibernateIO.cpp b/iokit/Kernel/IOHibernateIO.cpp index 4ceb8cc0f..efe918ad4 100644 --- a/iokit/Kernel/IOHibernateIO.cpp +++ b/iokit/Kernel/IOHibernateIO.cpp @@ -32,10 +32,10 @@ - PMRootDomain calls IOHibernateSystemSleep() before system sleep (devices awake, normal execution context) -- IOHibernateSystemSleep opens the hibernation file (or partition) at the bsd level, +- IOHibernateSystemSleep opens the hibernation file (or partition) at the bsd level, grabs its extents and searches for a polling driver willing to work with that IOMedia. The BSD code makes an ioctl to the storage driver to get the partition base offset to - the disk, and other ioctls to get the transfer constraints + the disk, and other ioctls to get the transfer constraints If successful, the file is written to make sure its initially not bootable (in case of later failure) and nvram set to point to the first block of the file. (Has to be done here so blocking is possible in nvram support). @@ -45,7 +45,7 @@ pages for eviction. It also copies processor flags needed for the restore path and sets a flag in the boot processor proc info. gIOHibernateState = kIOHibernateStateHibernating. -- Regular sleep progresses - some drivers may inspect the root domain property +- Regular sleep progresses - some drivers may inspect the root domain property kIOHibernateStateKey to modify behavior. The platform driver saves state to memory as usual but leaves motherboard I/O on. - Eventually the platform calls ml_ppc_sleep() in the shutdown context on the last cpu, @@ -57,17 +57,17 @@ by hibernate_page_list_setall(), avoiding having to find arch dependent low level bits. The image header and block list are written. The header includes the second file extent so only the header block is needed to read the file, regardless of filesystem. - The kernel segment "__HIB" is written uncompressed to the image. This segment of code and data + The kernel segment "__HIB" is written uncompressed to the image. This segment of code and data (only) is used to decompress the image during wake/boot. Some additional pages are removed from the bitmaps - the buffers used for hibernation. The bitmaps are written to the image. - More areas are removed from the bitmaps (after they have been written to the image) - the + More areas are removed from the bitmaps (after they have been written to the image) - the segment "__HIB" pages and interrupt stack. - Each wired page is compressed and written and then each non-wired page. Compression and + Each wired page is compressed and written and then each non-wired page. Compression and disk writes are in parallel. The image header is written to the start of the file and the polling driver closed. The machine powers down (or sleeps). - + Boot/Wake: - BootX sees the boot-image nvram variable containing the device and block number of the image, @@ -76,8 +76,8 @@ Boot/Wake: in the OF memory environment, and the image is decrypted. There is no decompression in BootX, that is in the kernel's __HIB section. - BootX copies the "__HIB" section to its correct position in memory, quiesces and calls its entry - hibernate_kernel_entrypoint(), passing the location of the image in memory. Translation is off, - only code & data in that section is safe to call since all the other wired pages are still + hibernate_kernel_entrypoint(), passing the location of the image in memory. Translation is off, + only code & data in that section is safe to call since all the other wired pages are still compressed in the image. - hibernate_kernel_entrypoint() removes pages occupied by the raw image from the page bitmaps. It uses the bitmaps to work out which pages can be uncompressed from the image to their final @@ -87,11 +87,11 @@ Boot/Wake: is used to get pages into place for 64bit. - the reset vector is called (at least on ppc), the kernel proceeds on a normal wake, with some changes conditional on the per proc flag - before VM is turned on the boot cpu, all mappings - are removed from the software strutures, and the hash table is reinitialized. + are removed from the software strutures, and the hash table is reinitialized. - After the platform CPU init code is called, hibernate_machine_init() is called to restore the rest of memory, using the polled mode driver, before other threads can run or any devices are turned on. This reduces the memory usage for BootX and allows decompression in parallel with disk reads, - for the remaining non wired pages. + for the remaining non wired pages. - The polling driver is closed down and regular wake proceeds. When the kernel calls iokit to wake (normal execution context) hibernate_teardown() in osmfk is called to release any memory, the file is closed via bsd. @@ -106,7 +106,7 @@ partition) that the image is going to live, looking for polled interface propert one the IOMedia object is passed to a "probe" call for the interface to accept or reject. All the interfaces found are kept in an ordered list. -There is an Open/Close pair of calls made to each of the interfaces at various stages since there are +There is an Open/Close pair of calls made to each of the interfaces at various stages since there are few different contexts things happen in: - there is an Open/Close (Preflight) made before any part of the system has slept (I/O is all @@ -116,7 +116,7 @@ immediately wakes back up for the image write. - there is an Open/Close (BeforeSleep) pair made around the image write operations that happen immediately before sleep. These can't block or allocate memory - the I/O system is asleep apart -from the low level bits (motherboard I/O etc). There is only one thread running. The close can be +from the low level bits (motherboard I/O etc). There is only one thread running. The close can be used to flush and set the disk to sleep. - there is an Open/Close (AfterSleep) pair made around the image read operations that happen @@ -146,6 +146,7 @@ to restrict I/O ops. #include #include #include +#include #include "RootDomainUserClient.h" #include #include "IOPMPowerStateQueue.h" @@ -189,6 +190,9 @@ extern uint32_t gIOHibernateState; uint32_t gIOHibernateMode; static char gIOHibernateBootSignature[256+1]; static char gIOHibernateFilename[MAXPATHLEN+1]; + +static uuid_string_t gIOHibernateBridgeBootSessionUUIDString; + static uint32_t gIOHibernateFreeRatio = 0; // free page target (percent) uint32_t gIOHibernateFreeTime = 0*1000; // max time to spend freeing pages (ms) static uint64_t gIOHibernateCompression = 0x80; // default compression 50% @@ -198,6 +202,8 @@ static IODTNVRAM * gIOOptionsEntry; static IORegistryEntry * gIOChosenEntry; static const OSSymbol * gIOHibernateBootImageKey; +static const OSSymbol * gIOHibernateBootSignatureKey; +static const OSSymbol * gIOBridgeBootSessionUUIDKey; #if defined(__i386__) || defined(__x86_64__) @@ -224,7 +230,7 @@ static hibernate_graphics_t * gIOHibernateGraphicsInfo = &_hibernateGraphics static hibernate_statistics_t _hibernateStats; static hibernate_statistics_t * gIOHibernateStats = &_hibernateStats; -enum +enum { kFSIdle = 0, kFSOpening = 2, @@ -410,7 +416,7 @@ IOHibernateSystemSleep(void) { if (kIOHibernateModeSleep & gIOHibernateMode) // default to discard clean for safe sleep - gIOHibernateMode ^= (kIOHibernateModeDiscardCleanInactive + gIOHibernateMode ^= (kIOHibernateModeDiscardCleanInactive | kIOHibernateModeDiscardCleanActive); } @@ -454,7 +460,7 @@ IOHibernateSystemSleep(void) vars->srcBuffer = IOBufferMemoryDescriptor::withOptions(kIODirectionOutIn, 2 * page_size + WKdm_SCRATCH_BUF_SIZE_INTERNAL, page_size); - vars->handoffBuffer = IOBufferMemoryDescriptor::withOptions(kIODirectionOutIn, + vars->handoffBuffer = IOBufferMemoryDescriptor::withOptions(kIODirectionOutIn, ptoa_64(gIOHibernateHandoffPageCount), page_size); if (!vars->srcBuffer || !vars->handoffBuffer) @@ -484,7 +490,7 @@ IOHibernateSystemSleep(void) gIOHibernateCurrentHeader->signature = kIOHibernateHeaderInvalidSignature; vmflush = ((kOSBooleanTrue == IOService::getPMRootDomain()->getProperty(kIOPMDeepSleepEnabledKey))); - err = hibernate_alloc_page_lists(&vars->page_list, + err = hibernate_alloc_page_lists(&vars->page_list, &vars->page_list_wired, &vars->page_list_pal); if (KERN_SUCCESS != err) break; @@ -512,18 +518,18 @@ IOHibernateSystemSleep(void) + (consoleInfo.v_width * consoleInfo.v_height * 8); enum { setFileRound = 1024*1024ULL }; setFileSize = ((setFileSize + setFileRound) & ~(setFileRound - 1)); - - HIBLOG("hibernate_page_list_setall preflight pageCount %d est comp %qd setfile %qd min %qd\n", + + HIBLOG("hibernate_page_list_setall preflight pageCount %d est comp %qd setfile %qd min %qd\n", pageCount, (100ULL * gIOHibernateCompression) >> 8, setFileSize, vars->fileMinSize); if (!(kIOHibernateModeFileResize & gIOHibernateMode) && (setFileSize < vars->fileMinSize)) - { + { setFileSize = vars->fileMinSize; } } - + // Invalidate the image file if (gDebugImageLock) { IOLockLock(gDebugImageLock); @@ -534,10 +540,11 @@ IOHibernateSystemSleep(void) IOLockUnlock(gDebugImageLock); } + vars->volumeCryptKeySize = sizeof(vars->volumeCryptKey); err = IOPolledFileOpen(gIOHibernateFilename, setFileSize, 0, gIOHibernateCurrentHeader, sizeof(gIOHibernateCurrentHeader), - &vars->fileVars, &nvramData, - &vars->volumeCryptKey[0], sizeof(vars->volumeCryptKey)); + &vars->fileVars, &nvramData, + &vars->volumeCryptKey[0], &vars->volumeCryptKeySize); if (KERN_SUCCESS != err) { @@ -559,7 +566,7 @@ IOHibernateSystemSleep(void) if (KERN_SUCCESS != err) break; clock_get_uptime(&startTime); - err = hibernate_setup(gIOHibernateCurrentHeader, + err = hibernate_setup(gIOHibernateCurrentHeader, vmflush, vars->page_list, vars->page_list_wired, vars->page_list_pal); clock_get_uptime(&endTime); @@ -586,11 +593,11 @@ IOHibernateSystemSleep(void) #if defined(__i386__) || defined(__x86_64__) - if (!uuid_is_null(vars->volumeCryptKey) && + if (vars->volumeCryptKeySize && (kOSBooleanTrue != IOService::getPMRootDomain()->getProperty(kIOPMDestroyFVKeyOnStandbyKey))) { uintptr_t smcVars[2]; - smcVars[0] = sizeof(vars->volumeCryptKey); + smcVars[0] = vars->volumeCryptKeySize; smcVars[1] = (uintptr_t)(void *) &gIOHibernateVars.volumeCryptKey[0]; IOService::getPMRootDomain()->setProperty(kIOHibernateSMCVariablesKey, smcVars, sizeof(smcVars)); @@ -599,8 +606,8 @@ IOHibernateSystemSleep(void) #endif - if (encryptedswap || !uuid_is_null(vars->volumeCryptKey)) - gIOHibernateMode ^= kIOHibernateModeEncrypt; + if (encryptedswap || vars->volumeCryptKeySize) + gIOHibernateMode ^= kIOHibernateModeEncrypt; if (kIOHibernateOptionProgress & gIOHibernateCurrentHeader->options) { @@ -640,7 +647,7 @@ IOHibernateSystemSleep(void) bcopy(&vars->wiredCryptKey[0], &rtcVars.wiredCryptKey[0], sizeof(rtcVars.wiredCryptKey)); if (gIOChosenEntry - && (data = OSDynamicCast(OSData, gIOChosenEntry->getProperty(kIOHibernateBootSignatureKey))) + && (data = OSDynamicCast(OSData, gIOChosenEntry->getProperty(gIOHibernateBootSignatureKey))) && (sizeof(rtcVars.booterSignature) <= data->getLength())) { bcopy(data->getBytesNoCopy(), &rtcVars.booterSignature[0], sizeof(rtcVars.booterSignature)); @@ -673,7 +680,7 @@ IOHibernateSystemSleep(void) } data = OSData::withBytes(&rtcVars, sizeof(rtcVars)); if (data) - { + { if (gIOHibernateRTCVariablesKey) IOService::getPMRootDomain()->setProperty(gIOHibernateRTCVariablesKey, data); data->release(); @@ -687,7 +694,7 @@ IOHibernateSystemSleep(void) { OSData * fileData = 0; data = OSDynamicCast(OSData, gIOChosenEntry->getProperty("boot-device-path")); - if (data->getLength() >= 4) fileData = OSDynamicCast(OSData, gIOChosenEntry->getProperty("boot-file-path")); + if (data && data->getLength() >= 4) fileData = OSDynamicCast(OSData, gIOChosenEntry->getProperty("boot-file-path")); if (data) { // AppleNVRAM_EFI_LOAD_OPTION @@ -799,7 +806,7 @@ IOSetBootImageNVRAM(OSData * data) } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -/* +/* * Writes header to disk with signature, block size and file extents data. * If there are more than 2 extents, then they are written on second block. */ @@ -830,14 +837,14 @@ IOWriteExtentsToFile(IOPolledFileIOVars * vars, uint32_t signature) if (hdr.fileExtentMapSize > sizeof(hdr.fileExtentMap)) { count = hdr.fileExtentMapSize - sizeof(hdr.fileExtentMap); - rc = kern_write_file(vars->fileRef, vars->blockSize, - (caddr_t)(((uint8_t *)fileExtents) + sizeof(hdr.fileExtentMap)), + rc = kern_write_file(vars->fileRef, vars->blockSize, + (caddr_t)(((uint8_t *)fileExtents) + sizeof(hdr.fileExtentMap)), count, IO_SKIP_ENCRYPTION); if (rc != 0) { HIBLOG("kern_write_file returned %d\n", rc); err = kIOReturnIOError; goto exit; - } + } } hdr.signature = signature; hdr.deviceBlockSize = vars->blockSize; @@ -939,11 +946,11 @@ ProgressInit(hibernate_graphics_t * display, uint8_t * screen, uint8_t * saveund rowBytes = display->rowBytes; pixelShift = display->depth >> 4; if (pixelShift < 1) return; - + screen += ((display->width - kIOHibernateProgressCount * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << (pixelShift - 1)) + (display->height - kIOHibernateProgressOriginY - kIOHibernateProgressHeight) * rowBytes; - + for (y = 0; y < kIOHibernateProgressHeight; y++) { out = screen + y * rowBytes; @@ -1000,7 +1007,7 @@ ProgressUpdate(hibernate_graphics_t * display, uint8_t * screen, int32_t firstBl rowBytes = display->rowBytes; - screen += ((display->width + screen += ((display->width - kIOHibernateProgressCount * (kIOHibernateProgressWidth + kIOHibernateProgressSpacing)) << (pixelShift - 1)) + (display->height - kIOHibernateProgressOriginY - kIOHibernateProgressHeight) * rowBytes; @@ -1088,8 +1095,8 @@ IOHibernateSystemHasSlept(void) } if ((kIOHibernateOptionProgress & gIOHibernateCurrentHeader->options) - && vars->previewBuffer - && (data = OSDynamicCast(OSData, + && vars->previewBuffer + && (data = OSDynamicCast(OSData, IOService::getPMRootDomain()->getProperty(kIOHibernatePreviewActiveKey)))) { UInt32 flags = *((UInt32 *)data->getBytesNoCopy()); @@ -1111,7 +1118,7 @@ IOHibernateSystemHasSlept(void) vars->consoleMapping = (uint8_t *) consoleInfo.v_baseAddr; HIBPRINT("video %p %d %d %d\n", - vars->consoleMapping, graphicsInfo->depth, + vars->consoleMapping, graphicsInfo->depth, graphicsInfo->width, graphicsInfo->height); if (vars->consoleMapping) ProgressInit(graphicsInfo, vars->consoleMapping, @@ -1178,6 +1185,9 @@ IOHibernateSystemWake(void) static IOReturn IOHibernateDone(IOHibernateVars * vars) { + IOReturn err; + OSData * data; + hibernate_teardown(vars->page_list, vars->page_list_wired, vars->page_list_pal); if (vars->videoMapping) @@ -1198,7 +1208,7 @@ IOHibernateDone(IOHibernateVars * vars) if (kIOHibernateStateWakingFromHibernate == gIOHibernateState) { - IOService::getPMRootDomain()->setProperty(kIOHibernateOptionsKey, + IOService::getPMRootDomain()->setProperty(kIOHibernateOptionsKey, gIOHibernateCurrentHeader->options, 32); } else @@ -1209,7 +1219,7 @@ IOHibernateDone(IOHibernateVars * vars) if ((kIOHibernateStateWakingFromHibernate == gIOHibernateState) && (kIOHibernateGfxStatusUnknown != gIOHibernateGraphicsInfo->gfxStatus)) { - IOService::getPMRootDomain()->setProperty(kIOHibernateGfxStatusKey, + IOService::getPMRootDomain()->setProperty(kIOHibernateGfxStatusKey, &gIOHibernateGraphicsInfo->gfxStatus, sizeof(gIOHibernateGraphicsInfo->gfxStatus)); } @@ -1274,7 +1284,7 @@ IOHibernateDone(IOHibernateVars * vars) case kIOHibernateHandoffTypeDeviceTree: MergeDeviceTree((DeviceTreeNode *) data, IOService::getServiceRoot()); break; - + case kIOHibernateHandoffTypeKeyStore: #if defined(__i386__) || defined(__x86_64__) { @@ -1287,16 +1297,42 @@ IOHibernateDone(IOHibernateVars * vars) } #endif break; - + default: done = (kIOHibernateHandoffType != (handoff->type & 0xFFFF0000)); break; - } + } } +#if defined(__i386__) || defined(__x86_64__) + if (vars->volumeCryptKeySize) + { + IOBufferMemoryDescriptor * + bmd = IOBufferMemoryDescriptor::withBytes(&vars->volumeCryptKey[0], + vars->volumeCryptKeySize, kIODirectionOutIn); + if (!bmd) panic("IOBufferMemoryDescriptor"); + IOSetAPFSKeyStoreData(bmd); + bzero(&vars->volumeCryptKey[0], sizeof(vars->volumeCryptKey)); + } +#endif + } vars->handoffBuffer->release(); } + if (gIOChosenEntry + && (data = OSDynamicCast(OSData, gIOChosenEntry->getProperty(gIOBridgeBootSessionUUIDKey))) + && (sizeof(gIOHibernateBridgeBootSessionUUIDString) <= data->getLength())) + { + bcopy(data->getBytesNoCopy(), &gIOHibernateBridgeBootSessionUUIDString[0], + sizeof(gIOHibernateBridgeBootSessionUUIDString)); + } + + if (vars->hwEncrypt) + { + err = IOPolledFilePollersSetEncryptionKey(vars->fileVars, NULL, 0); + HIBLOG("IOPolledFilePollersSetEncryptionKey(0,%x)\n", err); + } + bzero(vars, sizeof(*vars)); // gIOHibernateState = kIOHibernateStateInactive; // leave it for post wake code to see @@ -1375,18 +1411,21 @@ uint32_t IOHibernateWasScreenLocked(void) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -SYSCTL_STRING(_kern, OID_AUTO, hibernatefile, +SYSCTL_STRING(_kern, OID_AUTO, hibernatefile, CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, gIOHibernateFilename, sizeof(gIOHibernateFilename), ""); -SYSCTL_STRING(_kern, OID_AUTO, bootsignature, +SYSCTL_STRING(_kern, OID_AUTO, bootsignature, CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, gIOHibernateBootSignature, sizeof(gIOHibernateBootSignature), ""); -SYSCTL_UINT(_kern, OID_AUTO, hibernatemode, +SYSCTL_UINT(_kern, OID_AUTO, hibernatemode, CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, &gIOHibernateMode, 0, ""); SYSCTL_STRUCT(_kern, OID_AUTO, hibernatestatistics, CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, &_hibernateStats, hibernate_statistics_t, ""); +SYSCTL_STRING(_kern_bridge, OID_AUTO, bootsessionuuid, + CTLFLAG_RD | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_LOCKED, + gIOHibernateBridgeBootSessionUUIDString, sizeof(gIOHibernateBridgeBootSessionUUIDString), ""); SYSCTL_UINT(_kern, OID_AUTO, hibernategraphicsready, CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_ANYBODY, @@ -1401,11 +1440,12 @@ SYSCTL_UINT(_kern, OID_AUTO, hibernatehidready, CTLFLAG_RW | CTLFLAG_NOAUTO | CTLFLAG_KERN | CTLFLAG_ANYBODY, &_hibernateStats.hidReadyTime, 0, ""); - void IOHibernateSystemInit(IOPMrootDomain * rootDomain) { - gIOHibernateBootImageKey = OSSymbol::withCStringNoCopy(kIOHibernateBootImageKey); + gIOHibernateBootImageKey = OSSymbol::withCStringNoCopy(kIOHibernateBootImageKey); + gIOHibernateBootSignatureKey = OSSymbol::withCStringNoCopy(kIOHibernateBootSignatureKey); + gIOBridgeBootSessionUUIDKey = OSSymbol::withCStringNoCopy(kIOBridgeBootSessionUUIDKey); #if defined(__i386__) || defined(__x86_64__) gIOHibernateRTCVariablesKey = OSSymbol::withCStringNoCopy(kIOHibernateRTCVariablesKey); @@ -1437,12 +1477,20 @@ IOHibernateSystemInit(IOPMrootDomain * rootDomain) gIOChosenEntry = IORegistryEntry::fromPath("/chosen", gIODTPlane); + if (gIOChosenEntry + && (data = OSDynamicCast(OSData, gIOChosenEntry->getProperty(gIOBridgeBootSessionUUIDKey))) + && (sizeof(gIOHibernateBridgeBootSessionUUIDString) <= data->getLength())) + { + sysctl_register_oid(&sysctl__kern_bridge_bootsessionuuid); + bcopy(data->getBytesNoCopy(), &gIOHibernateBridgeBootSessionUUIDString[0], sizeof(gIOHibernateBridgeBootSessionUUIDString)); + } + gFSLock = IOLockAlloc(); } /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -static IOReturn +static IOReturn IOHibernatePolledFileWrite(IOPolledFileIOVars * vars, const uint8_t * bytes, IOByteCount size, IOPolledFileCryptVars * cryptvars) @@ -1531,7 +1579,7 @@ hibernate_write_image(void) static const unsigned char first_iv[AES_BLOCK_SIZE] = { 0xa3, 0x63, 0x65, 0xa9, 0x0b, 0x71, 0x7b, 0x1c, 0xdf, 0x9e, 0x5f, 0x32, 0xd7, 0x61, 0x63, 0xda }; - + cryptvars = &gIOHibernateCryptWakeContext; bzero(cryptvars, sizeof(IOPolledFileCryptVars)); aes_encrypt_key(vars->cryptKey, @@ -1545,7 +1593,6 @@ hibernate_write_image(void) bzero(cryptvars, sizeof(IOPolledFileCryptVars)); for (pageCount = 0; pageCount < sizeof(vars->wiredCryptKey); pageCount++) vars->wiredCryptKey[pageCount] ^= vars->volumeCryptKey[pageCount]; - bzero(&vars->volumeCryptKey[0], sizeof(vars->volumeCryptKey)); aes_encrypt_key(vars->wiredCryptKey, kIOHibernateAESKeySize, &cryptvars->ctx.encrypt); @@ -1561,7 +1608,7 @@ hibernate_write_image(void) vars->page_list_pal, false /* !preflight */, /* discard_all */ - ((0 == (kIOHibernateModeSleep & gIOHibernateMode)) + ((0 == (kIOHibernateModeSleep & gIOHibernateMode)) && (0 != ((kIOHibernateModeDiscardCleanActive | kIOHibernateModeDiscardCleanInactive) & gIOHibernateMode))), &pageCount); @@ -1573,7 +1620,7 @@ hibernate_write_image(void) count = vars->fileExtents->getLength() / sizeof(IOPolledFileExtent); for (page = 0; page < count; page++) { - HIBLOG("fileExtents[%d] %qx, %qx (%qx)\n", page, + HIBLOG("fileExtents[%d] %qx, %qx (%qx)\n", page, fileExtents[page].start, fileExtents[page].length, fileExtents[page].start + fileExtents[page].length); } @@ -1584,9 +1631,9 @@ hibernate_write_image(void) compBytes = 0; clock_get_uptime(&allTime); - IOService::getPMRootDomain()->pmStatsRecordEvent( + IOService::getPMRootDomain()->pmStatsRecordEvent( kIOPMStatsHibernateImageWrite | kIOPMStatsEventStartFlag, allTime); - do + do { compressedSize = 0; uncompressedSize = 0; @@ -1594,8 +1641,8 @@ hibernate_write_image(void) zvPageCount = 0; IOPolledFileSeek(vars->fileVars, vars->fileVars->blockSize); - - HIBLOG("IOHibernatePollerOpen, ml_get_interrupts_enabled %d\n", + + HIBLOG("IOHibernatePollerOpen, ml_get_interrupts_enabled %d\n", ml_get_interrupts_enabled()); err = IOPolledFilePollersOpen(vars->fileVars, kIOPolledBeforeSleepState, // abortable if not low battery @@ -1604,9 +1651,18 @@ hibernate_write_image(void) pollerOpen = (kIOReturnSuccess == err); if (!pollerOpen) break; - + + if (vars->volumeCryptKeySize) + { + err = IOPolledFilePollersSetEncryptionKey(vars->fileVars, &vars->volumeCryptKey[0], vars->volumeCryptKeySize); + HIBLOG("IOPolledFilePollersSetEncryptionKey(%x)\n", err); + vars->hwEncrypt = (kIOReturnSuccess == err); + bzero(&vars->volumeCryptKey[0], sizeof(vars->volumeCryptKey)); + if (vars->hwEncrypt) header->options |= kIOHibernateOptionHWEncrypt; + } + // copy file block extent list if larger than header - + count = vars->fileVars->fileExtents->getLength(); if (count > sizeof(header->fileExtentMap)) { @@ -1640,6 +1696,11 @@ hibernate_write_image(void) header->restore1CodeOffset = ((uintptr_t) &hibernate_machine_entrypoint) - hibernateBase; header->restore1StackOffset = ((uintptr_t) &gIOHibernateRestoreStackEnd[0]) - 64 - hibernateBase; + if (uuid_parse(&gIOHibernateBridgeBootSessionUUIDString[0], &header->bridgeBootSessionUUID[0])) + { + bzero(&header->bridgeBootSessionUUID[0], sizeof(header->bridgeBootSessionUUID)); + } + // sum __HIB seg, with zeros for the stack src = (uint8_t *) trunc_page(hibernateBase); for (page = 0; page < count; page++) @@ -1651,7 +1712,7 @@ hibernate_write_image(void) src += page_size; } sum1 = restore1Sum; - + // write the __HIB seg, with zeros for the stack src = (uint8_t *) trunc_page(hibernateBase); @@ -1662,7 +1723,7 @@ hibernate_write_image(void) if (kIOReturnSuccess != err) break; } - err = IOHibernatePolledFileWrite(vars->fileVars, + err = IOHibernatePolledFileWrite(vars->fileVars, (uint8_t *) 0, &gIOHibernateRestoreStackEnd[0] - &gIOHibernateRestoreStack[0], cryptvars); @@ -1677,7 +1738,7 @@ hibernate_write_image(void) break; } - if (kIOHibernateModeEncrypt & gIOHibernateMode) + if (!vars->hwEncrypt && (kIOHibernateModeEncrypt & gIOHibernateMode)) { vars->fileVars->encryptStart = (vars->fileVars->position & ~(AES_BLOCK_SIZE - 1)); vars->fileVars->encryptEnd = UINT64_MAX; @@ -1695,8 +1756,8 @@ hibernate_write_image(void) phys64 = vars->previewBuffer->getPhysicalSegment(count, &segLen, kIOMemoryMapperNone); pageAndCount[0] = atop_64(phys64); pageAndCount[1] = atop_32(segLen); - err = IOHibernatePolledFileWrite(vars->fileVars, - (const uint8_t *) &pageAndCount, sizeof(pageAndCount), + err = IOHibernatePolledFileWrite(vars->fileVars, + (const uint8_t *) &pageAndCount, sizeof(pageAndCount), cryptvars); if (kIOReturnSuccess != err) break; @@ -1733,35 +1794,35 @@ hibernate_write_image(void) (phys64 = ioBuffer->getPhysicalSegment(count, &segLen, kIOMemoryMapperNone)); count += segLen) { - hibernate_set_page_state(vars->page_list, vars->page_list_wired, + hibernate_set_page_state(vars->page_list, vars->page_list_wired, atop_64(phys64), atop_32(segLen), kIOHibernatePageStateFree); pageCount -= atop_32(segLen); } - + for (count = 0; (phys64 = vars->srcBuffer->getPhysicalSegment(count, &segLen, kIOMemoryMapperNone)); count += segLen) { - hibernate_set_page_state(vars->page_list, vars->page_list_wired, + hibernate_set_page_state(vars->page_list, vars->page_list_wired, atop_64(phys64), atop_32(segLen), kIOHibernatePageStateFree); pageCount -= atop_32(segLen); } // copy out bitmap of pages available for trashing during restore - + bitmap_size = vars->page_list_wired->list_size; src = (uint8_t *) vars->page_list_wired; err = IOHibernatePolledFileWrite(vars->fileVars, src, bitmap_size, cryptvars); if (kIOReturnSuccess != err) break; - // mark more areas for no save, but these are not available + // mark more areas for no save, but these are not available // for trashing during restore hibernate_page_list_set_volatile(vars->page_list, vars->page_list_wired, &pageCount); - + page = atop_32(KERNEL_IMAGE_TO_PHYS(hibernateBase)); count = atop_32(round_page(KERNEL_IMAGE_TO_PHYS(hibernateEnd))) - page; @@ -1774,7 +1835,7 @@ hibernate_write_image(void) (phys64 = vars->previewBuffer->getPhysicalSegment(count, &segLen, kIOMemoryMapperNone)); count += segLen) { - hibernate_set_page_state(vars->page_list, vars->page_list_wired, + hibernate_set_page_state(vars->page_list, vars->page_list_wired, atop_64(phys64), atop_32(segLen), kIOHibernatePageStateFree); pageCount -= atop_32(segLen); @@ -1784,7 +1845,7 @@ hibernate_write_image(void) (phys64 = vars->handoffBuffer->getPhysicalSegment(count, &segLen, kIOMemoryMapperNone)); count += segLen) { - hibernate_set_page_state(vars->page_list, vars->page_list_wired, + hibernate_set_page_state(vars->page_list, vars->page_list_wired, atop_64(phys64), atop_32(segLen), kIOHibernatePageStateFree); pageCount -= atop_32(segLen); @@ -1806,14 +1867,14 @@ hibernate_write_image(void) pagesDone = 0; lastBlob = 0; - - HIBLOG("bitmap_size 0x%x, previewSize 0x%x, writing %d pages @ 0x%llx\n", + + HIBLOG("bitmap_size 0x%x, previewSize 0x%x, writing %d pages @ 0x%llx\n", bitmap_size, header->previewSize, pageCount, vars->fileVars->position); enum // pageType - { + { kWired = 0x02, kEncrypt = 0x01, kWiredEncrypt = kWired | kEncrypt, @@ -1835,14 +1896,14 @@ hibernate_write_image(void) vars->fileVars->encryptEnd = UINT64_MAX; HIBLOG("encryptStart %qx\n", vars->fileVars->encryptStart); } - bcopy(&cryptvars->aes_iv[0], - &gIOHibernateCryptWakeContext.aes_iv[0], + bcopy(&cryptvars->aes_iv[0], + &gIOHibernateCryptWakeContext.aes_iv[0], sizeof(cryptvars->aes_iv)); cryptvars = &gIOHibernateCryptWakeContext; } for (iterDone = false, ppnum = 0; !iterDone; ) { - count = hibernate_page_list_iterate((kWired & pageType) + count = hibernate_page_list_iterate((kWired & pageType) ? vars->page_list_wired : vars->page_list, &ppnum); // kprintf("[%d](%x : %x)\n", pageType, ppnum, count); @@ -1852,7 +1913,7 @@ hibernate_write_image(void) { uint32_t checkIndex; for (checkIndex = 0; - (checkIndex < count) + (checkIndex < count) && (((kEncrypt & pageType) == 0) == _pmap_is_noencrypt(ppnum + checkIndex)); checkIndex++) {} @@ -1870,19 +1931,19 @@ hibernate_write_image(void) case kWiredClear: wiredPagesClear += count; break; case kUnwiredEncrypt: dirtyPagesEncrypted += count; break; } - + if (iterDone && (kWiredEncrypt == pageType)) {/* not yet end of wired list */} else { pageAndCount[0] = ppnum; pageAndCount[1] = count; - err = IOHibernatePolledFileWrite(vars->fileVars, - (const uint8_t *) &pageAndCount, sizeof(pageAndCount), + err = IOHibernatePolledFileWrite(vars->fileVars, + (const uint8_t *) &pageAndCount, sizeof(pageAndCount), cryptvars); if (kIOReturnSuccess != err) break; } - + for (page = ppnum; page < (ppnum + count); page++) { err = IOMemoryDescriptorWriteFromPhysical(vars->srcBuffer, 0, ptoa_64(page), page_size); @@ -1891,16 +1952,16 @@ hibernate_write_image(void) HIBLOG("IOMemoryDescriptorWriteFromPhysical %d [%ld] %x\n", __LINE__, (long)page, err); break; } - + sum = hibernate_sum_page(src, page); if (kWired & pageType) sum1 += sum; else sum2 += sum; - + clock_get_uptime(&startTime); wkresult = WKdm_compress_new((const WK_word*) src, - (WK_word*) compressed, + (WK_word*) compressed, (WK_word*) scratch, page_size - 4); @@ -1911,7 +1972,7 @@ hibernate_write_image(void) compBytes += page_size; pageCompressedSize = (-1 == wkresult) ? page_size : wkresult; - if (pageCompressedSize == 0) + if (pageCompressedSize == 0) { pageCompressedSize = 4; data = src; @@ -1921,27 +1982,27 @@ hibernate_write_image(void) else zvPageCount++; } - else + else { if (pageCompressedSize != page_size) data = compressed; else data = src; } - + tag = pageCompressedSize | kIOHibernateTagSignature; err = IOHibernatePolledFileWrite(vars->fileVars, (const uint8_t *) &tag, sizeof(tag), cryptvars); if (kIOReturnSuccess != err) break; - + err = IOHibernatePolledFileWrite(vars->fileVars, data, (pageCompressedSize + 3) & ~3, cryptvars); if (kIOReturnSuccess != err) break; - + compressedSize += pageCompressedSize; uncompressedSize += page_size; pagesDone++; - + if (vars->consoleMapping && (0 == (1023 & pagesDone))) { blob = ((pagesDone * kIOHibernateProgressCount) / pageCount); @@ -2012,12 +2073,12 @@ hibernate_write_image(void) } // Header: - + header->imageSize = vars->fileVars->position; header->image1Size = image1Size; header->bitmapSize = bitmap_size; header->pageCount = pageCount; - + header->restore1Sum = restore1Sum; header->image1Sum = sum1; header->image2Sum = sum2; @@ -2025,7 +2086,7 @@ hibernate_write_image(void) header->compression = (compressedSize << 8) / uncompressedSize; gIOHibernateCompression = header->compression; - + count = vars->fileVars->fileExtents->getLength(); if (count > sizeof(header->fileExtentMap)) { @@ -2038,20 +2099,20 @@ hibernate_write_image(void) header->deviceBase = vars->fileVars->block0; header->deviceBlockSize = vars->fileVars->blockSize; - + IOPolledFileSeek(vars->fileVars, 0); err = IOHibernatePolledFileWrite(vars->fileVars, - (uint8_t *) header, sizeof(IOHibernateImageHeader), + (uint8_t *) header, sizeof(IOHibernateImageHeader), cryptvars); if (kIOReturnSuccess != err) break; err = IOHibernatePolledFileWrite(vars->fileVars, 0, 0, cryptvars); } while (false); - + clock_get_uptime(&endTime); - IOService::getPMRootDomain()->pmStatsRecordEvent( + IOService::getPMRootDomain()->pmStatsRecordEvent( kIOPMStatsHibernateImageWrite | kIOPMStatsEventStopFlag, endTime); SUB_ABSOLUTETIME(&endTime, &allTime); @@ -2059,31 +2120,31 @@ hibernate_write_image(void) HIBLOG("all time: %qd ms, ", nsec / 1000000ULL); absolutetime_to_nanoseconds(compTime, &nsec); - HIBLOG("comp bytes: %qd time: %qd ms %qd Mb/s, ", - compBytes, + HIBLOG("comp bytes: %qd time: %qd ms %qd Mb/s, ", + compBytes, nsec / 1000000ULL, nsec ? (((compBytes * 1000000000ULL) / 1024 / 1024) / nsec) : 0); absolutetime_to_nanoseconds(vars->fileVars->cryptTime, &nsec); - HIBLOG("crypt bytes: %qd time: %qd ms %qd Mb/s, ", - vars->fileVars->cryptBytes, - nsec / 1000000ULL, + HIBLOG("crypt bytes: %qd time: %qd ms %qd Mb/s, ", + vars->fileVars->cryptBytes, + nsec / 1000000ULL, nsec ? (((vars->fileVars->cryptBytes * 1000000000ULL) / 1024 / 1024) / nsec) : 0); - HIBLOG("\nimage %qd (%lld%%), uncompressed %qd (%d), compressed %qd (%d%%), sum1 %x, sum2 %x\n", + HIBLOG("\nimage %qd (%lld%%), uncompressed %qd (%d), compressed %qd (%d%%), sum1 %x, sum2 %x\n", header->imageSize, (header->imageSize * 100) / vars->fileVars->fileSize, uncompressedSize, atop_32(uncompressedSize), compressedSize, uncompressedSize ? ((int) ((compressedSize * 100ULL) / uncompressedSize)) : 0, sum1, sum2); - HIBLOG("svPageCount %d, zvPageCount %d, wiredPagesEncrypted %d, wiredPagesClear %d, dirtyPagesEncrypted %d\n", + HIBLOG("svPageCount %d, zvPageCount %d, wiredPagesEncrypted %d, wiredPagesClear %d, dirtyPagesEncrypted %d\n", svPageCount, zvPageCount, wiredPagesEncrypted, wiredPagesClear, dirtyPagesEncrypted); if (pollerOpen) IOPolledFilePollersClose(vars->fileVars, (kIOReturnSuccess == err) ? kIOPolledBeforeSleepState : kIOPolledBeforeSleepStateAborted ); if (vars->consoleMapping) - ProgressUpdate(gIOHibernateGraphicsInfo, + ProgressUpdate(gIOHibernateGraphicsInfo, vars->consoleMapping, 0, kIOHibernateProgressCount); HIBLOG("hibernate_write_image done(%x)\n", err); @@ -2123,7 +2184,7 @@ hibernate_write_image(void) /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -extern "C" void +extern "C" void hibernate_machine_init(void) { IOReturn err; @@ -2155,7 +2216,7 @@ hibernate_machine_init(void) } HIBPRINT("diag %x %x %x %x\n", - gIOHibernateCurrentHeader->diag[0], gIOHibernateCurrentHeader->diag[1], + gIOHibernateCurrentHeader->diag[0], gIOHibernateCurrentHeader->diag[1], gIOHibernateCurrentHeader->diag[2], gIOHibernateCurrentHeader->diag[3]); #define t40ms(x) (tmrCvt((((uint64_t)(x)) << 8), tscFCvtt2n) / 1000000) @@ -2179,7 +2240,7 @@ hibernate_machine_init(void) gIOHibernateStats->booterStart, gIOHibernateStats->booterDuration, gIOHibernateStats->trampolineDuration); - HIBLOG("booter start at %d ms smc %d ms, [%d, %d, %d] total %d ms, dsply %d, %d ms, tramp %d ms\n", + HIBLOG("booter start at %d ms smc %d ms, [%d, %d, %d] total %d ms, dsply %d, %d ms, tramp %d ms\n", gIOHibernateStats->booterStart, gIOHibernateStats->smcStart, gIOHibernateStats->booterDuration0, @@ -2194,7 +2255,7 @@ hibernate_machine_init(void) gIOHibernateState, pagesDone, sum, gIOHibernateStats->imageSize, gIOHibernateStats->image1Size, gIOHibernateCurrentHeader->conflictCount, gIOHibernateCurrentHeader->nextFree); - if ((0 != (kIOHibernateModeSleep & gIOHibernateMode)) + if ((0 != (kIOHibernateModeSleep & gIOHibernateMode)) && (0 != ((kIOHibernateModeDiscardCleanActive | kIOHibernateModeDiscardCleanInactive) & gIOHibernateMode))) { hibernate_page_list_discard(vars->page_list); @@ -2206,8 +2267,9 @@ hibernate_machine_init(void) panic("handoff overflow"); IOHibernateHandoff * handoff; - bool done = false; - bool foundCryptData = false; + bool done = false; + bool foundCryptData = false; + bool foundVolumeEncryptData = false; for (handoff = (IOHibernateHandoff *) vars->handoffBuffer->getBytesNoCopy(); !done; @@ -2239,18 +2301,27 @@ hibernate_machine_init(void) bzero(data, handoff->bytecount); break; + case kIOHibernateHandoffTypeVolumeCryptKey: + if (handoff->bytecount == vars->volumeCryptKeySize) + { + bcopy(data, &vars->volumeCryptKey[0], vars->volumeCryptKeySize); + foundVolumeEncryptData = true; + } + else panic("kIOHibernateHandoffTypeVolumeCryptKey(%d)", handoff->bytecount); + break; + case kIOHibernateHandoffTypeMemoryMap: clock_get_uptime(&allTime); - hibernate_newruntime_map(data, handoff->bytecount, + hibernate_newruntime_map(data, handoff->bytecount, gIOHibernateCurrentHeader->systemTableOffset); clock_get_uptime(&endTime); - + SUB_ABSOLUTETIME(&endTime, &allTime); absolutetime_to_nanoseconds(endTime, &nsec); - + HIBLOG("hibernate_newruntime_map time: %qd ms, ", nsec / 1000000ULL); break; @@ -2265,30 +2336,33 @@ hibernate_machine_init(void) default: done = (kIOHibernateHandoffType != (handoff->type & 0xFFFF0000)); break; - } + } } - if (cryptvars && !foundCryptData) - panic("hibernate handoff"); + + if (vars->hwEncrypt && !foundVolumeEncryptData) + panic("no volumeCryptKey"); + else if (cryptvars && !foundCryptData) + panic("hibernate handoff"); HIBPRINT("video 0x%llx %d %d %d status %x\n", - gIOHibernateGraphicsInfo->physicalAddress, gIOHibernateGraphicsInfo->depth, - gIOHibernateGraphicsInfo->width, gIOHibernateGraphicsInfo->height, gIOHibernateGraphicsInfo->gfxStatus); + gIOHibernateGraphicsInfo->physicalAddress, gIOHibernateGraphicsInfo->depth, + gIOHibernateGraphicsInfo->width, gIOHibernateGraphicsInfo->height, gIOHibernateGraphicsInfo->gfxStatus); if (vars->videoMapping && gIOHibernateGraphicsInfo->physicalAddress) { - vars->videoMapSize = round_page(gIOHibernateGraphicsInfo->height + vars->videoMapSize = round_page(gIOHibernateGraphicsInfo->height * gIOHibernateGraphicsInfo->rowBytes); if (vars->videoMapSize > vars->videoAllocSize) vars->videoMapSize = 0; else { - IOMapPages(kernel_map, + IOMapPages(kernel_map, vars->videoMapping, gIOHibernateGraphicsInfo->physicalAddress, vars->videoMapSize, kIOMapInhibitCache ); } } if (vars->videoMapSize) - ProgressUpdate(gIOHibernateGraphicsInfo, + ProgressUpdate(gIOHibernateGraphicsInfo, (uint8_t *) vars->videoMapping, 0, kIOHibernateProgressCount); uint8_t * src = (uint8_t *) vars->srcBuffer->getBytesNoCopy(); @@ -2308,6 +2382,14 @@ hibernate_machine_init(void) absolutetime_to_nanoseconds(endTime, &nsec); HIBLOG("IOPolledFilePollersOpen(%x) %qd ms\n", err, nsec / 1000000ULL); + if (vars->hwEncrypt) + { + err = IOPolledFilePollersSetEncryptionKey(vars->fileVars, + &vars->volumeCryptKey[0], vars->volumeCryptKeySize); + HIBLOG("IOPolledFilePollersSetEncryptionKey(%x)\n", err); + if (kIOReturnSuccess != err) panic("IOPolledFilePollersSetEncryptionKey(0x%x)", err); + } + IOPolledFileSeek(vars->fileVars, gIOHibernateCurrentHeader->image1Size); // kick off the read ahead @@ -2371,14 +2453,14 @@ hibernate_machine_init(void) if (compressedSize == 4) { int i; uint32_t *s, *d; - + s = (uint32_t *)src; d = (uint32_t *)(uintptr_t)compressed; for (i = 0; i < (int)(PAGE_SIZE / sizeof(int32_t)); i++) *d++ = *s; } - else + else WKdm_decompress_new((WK_word*) src, (WK_word*) compressed, (WK_word*) scratch, compressedSize); clock_get_uptime(&endTime); ADD_ABSOLUTETIME(&compTime, &endTime); @@ -2408,7 +2490,7 @@ hibernate_machine_init(void) if (progressStamp != lastProgressStamp) { lastProgressStamp = progressStamp; - HIBPRINT("pages %d (%d%%)\n", pagesDone, + HIBPRINT("pages %d (%d%%)\n", pagesDone, (100 * pagesDone) / gIOHibernateCurrentHeader->pageCount); } } @@ -2429,9 +2511,9 @@ hibernate_machine_init(void) clock_get_uptime(&endTime); - IOService::getPMRootDomain()->pmStatsRecordEvent( + IOService::getPMRootDomain()->pmStatsRecordEvent( kIOPMStatsHibernateImageRead | kIOPMStatsEventStartFlag, allTime); - IOService::getPMRootDomain()->pmStatsRecordEvent( + IOService::getPMRootDomain()->pmStatsRecordEvent( kIOPMStatsHibernateImageRead | kIOPMStatsEventStopFlag, endTime); SUB_ABSOLUTETIME(&endTime, &allTime); @@ -2443,20 +2525,20 @@ hibernate_machine_init(void) gIOHibernateStats->kernelImageReadDuration = nsec / 1000000ULL; gIOHibernateStats->imagePages = pagesDone; - HIBLOG("hibernate_machine_init pagesDone %d sum2 %x, time: %d ms, disk(0x%x) %qd Mb/s, ", + HIBLOG("hibernate_machine_init pagesDone %d sum2 %x, time: %d ms, disk(0x%x) %qd Mb/s, ", pagesDone, sum, gIOHibernateStats->kernelImageReadDuration, kDefaultIOSize, nsecIO ? ((((gIOHibernateCurrentHeader->imageSize - gIOHibernateCurrentHeader->image1Size) * 1000000000ULL) / 1024 / 1024) / nsecIO) : 0); absolutetime_to_nanoseconds(compTime, &nsec); - HIBLOG("comp bytes: %qd time: %qd ms %qd Mb/s, ", - compBytes, + HIBLOG("comp bytes: %qd time: %qd ms %qd Mb/s, ", + compBytes, nsec / 1000000ULL, nsec ? (((compBytes * 1000000000ULL) / 1024 / 1024) / nsec) : 0); absolutetime_to_nanoseconds(vars->fileVars->cryptTime, &nsec); - HIBLOG("crypt bytes: %qd time: %qd ms %qd Mb/s\n", - vars->fileVars->cryptBytes, - nsec / 1000000ULL, + HIBLOG("crypt bytes: %qd time: %qd ms %qd Mb/s\n", + vars->fileVars->cryptBytes, + nsec / 1000000ULL, nsec ? (((vars->fileVars->cryptBytes * 1000000000ULL) / 1024 / 1024) / nsec) : 0); KDBG(IOKDBG_CODE(DBG_HIBERNATE, 2), pagesRead, pagesDone); @@ -2523,6 +2605,3 @@ void IOHibernateSystemRestart(void) if (noteProp) noteProp->release(); if (sym) sym->release(); } - - - diff --git a/iokit/Kernel/IOHibernateInternal.h b/iokit/Kernel/IOHibernateInternal.h index 0c800aec5..7fd0ec461 100644 --- a/iokit/Kernel/IOHibernateInternal.h +++ b/iokit/Kernel/IOHibernateInternal.h @@ -53,9 +53,11 @@ struct IOHibernateVars uint8_t * consoleMapping; uint8_t haveFastBoot; uint8_t saveBootAudioVolume; + uint8_t hwEncrypt; uint8_t wiredCryptKey[kIOHibernateAESKeySize / 8]; uint8_t cryptKey[kIOHibernateAESKeySize / 8]; - uint8_t volumeCryptKey[kIOHibernateAESKeySize / 8]; + size_t volumeCryptKeySize; + uint8_t volumeCryptKey[64]; }; typedef struct IOHibernateVars IOHibernateVars; diff --git a/iokit/Kernel/IOInterruptController.cpp b/iokit/Kernel/IOInterruptController.cpp index 81f07dcab..2ee2e1466 100644 --- a/iokit/Kernel/IOInterruptController.cpp +++ b/iokit/Kernel/IOInterruptController.cpp @@ -466,8 +466,6 @@ IOReturn IOSharedInterruptController::initInterruptController(IOInterruptControl { int cnt, interruptType; IOReturn error; - - reserved = NULL; if (!super::init()) return kIOReturnNoResources; diff --git a/iokit/Kernel/IOKitKernelInternal.h b/iokit/Kernel/IOKitKernelInternal.h index 85507aa65..fc75dc6cc 100644 --- a/iokit/Kernel/IOKitKernelInternal.h +++ b/iokit/Kernel/IOKitKernelInternal.h @@ -38,6 +38,7 @@ __BEGIN_DECLS #include #include #include +#include /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ @@ -97,16 +98,6 @@ IOMemoryMapTracking(IOTrackingUser * tracking, task_t * task, extern vm_size_t debug_iomallocpageable_size; -// osfmk/device/iokit_rpc.c -extern kern_return_t IOMapPages(vm_map_t map, mach_vm_address_t va, mach_vm_address_t pa, - mach_vm_size_t length, unsigned int mapFlags); -extern kern_return_t IOUnmapPages(vm_map_t map, mach_vm_address_t va, mach_vm_size_t length); - -extern kern_return_t IOProtectCacheMode(vm_map_t map, mach_vm_address_t va, - mach_vm_size_t length, unsigned int mapFlags); - -extern ppnum_t IOGetLastPageNumber(void); - extern ppnum_t gIOLastPage; extern IOSimpleLock * gIOPageAllocLock; diff --git a/iokit/Kernel/IOMemoryDescriptor.cpp b/iokit/Kernel/IOMemoryDescriptor.cpp index ce2963317..9dfb2f322 100644 --- a/iokit/Kernel/IOMemoryDescriptor.cpp +++ b/iokit/Kernel/IOMemoryDescriptor.cpp @@ -68,10 +68,6 @@ __BEGIN_DECLS extern ppnum_t pmap_find_phys(pmap_t pmap, addr64_t va); extern void ipc_port_release_send(ipc_port_t port); -// osfmk/device/iokit_rpc.c -unsigned int IODefaultCacheBits(addr64_t pa); -unsigned int IOTranslateCacheBits(struct phys_entry *pp); - __END_DECLS #define kIOMapperWaitSystem ((IOMapper *) 1) @@ -2075,6 +2071,8 @@ IOReturn IOGeneralMemoryDescriptor::dmaCommandOperation(DMACommandOps op, void * keepMap = (data->fMapper == gIOSystemMapper); keepMap &= ((data->fOffset == 0) && (data->fLength == _length)); + if ((data->fMapper == gIOSystemMapper) && _prepareLock) IOLockLock(_prepareLock); + remap = (!keepMap); remap |= (dataP->fDMAMapNumAddressBits < 64) && ((dataP->fMappedBase + _length) > (1ULL << dataP->fDMAMapNumAddressBits)); @@ -2099,6 +2097,8 @@ IOReturn IOGeneralMemoryDescriptor::dmaCommandOperation(DMACommandOps op, void * md->dmaMapRecord(data->fMapper, data->fCommand, dataP->fMappedLength); } data->fMapContig = !dataP->fDiscontig; + + if ((data->fMapper == gIOSystemMapper) && _prepareLock) IOLockUnlock(_prepareLock); } return (err); } @@ -4708,16 +4708,17 @@ void * IOMemoryDescriptor::getVirtualSegment(IOByteCount offset, bool IOGeneralMemoryDescriptor::serialize(OSSerialize * s) const { - OSSymbol const *keys[2]; - OSObject *values[2]; + OSSymbol const *keys[2] = {0}; + OSObject *values[2] = {0}; OSArray * array; + vm_size_t vcopy_size; struct SerData { user_addr_t address; user_size_t length; - } *vcopy; + } *vcopy = NULL; unsigned int index, nRanges; - bool result; + bool result = false; IOOptionBits type = _flags & kIOMemoryTypeMask; @@ -4727,17 +4728,19 @@ bool IOGeneralMemoryDescriptor::serialize(OSSerialize * s) const if (!array) return (false); nRanges = _rangesCount; - vcopy = (SerData *) IOMalloc(sizeof(SerData) * nRanges); - if (vcopy == 0) return false; + if (os_mul_overflow(sizeof(SerData), nRanges, &vcopy_size)) { + result = false; + goto bail; + } + vcopy = (SerData *) IOMalloc(vcopy_size); + if (vcopy == 0) { + result = false; + goto bail; + } keys[0] = OSSymbol::withCString("address"); keys[1] = OSSymbol::withCString("length"); - result = false; - values[0] = values[1] = 0; - - // From this point on we can go to bail. - // Copy the volatile data so we don't have to allocate memory // while the lock is held. LOCK; @@ -4797,7 +4800,7 @@ bool IOGeneralMemoryDescriptor::serialize(OSSerialize * s) const if (keys[1]) keys[1]->release(); if (vcopy) - IOFree(vcopy, sizeof(SerData) * nRanges); + IOFree(vcopy, vcopy_size); return result; } diff --git a/iokit/Kernel/IONVRAM.cpp b/iokit/Kernel/IONVRAM.cpp index bf7a07032..94d6b75dd 100644 --- a/iokit/Kernel/IONVRAM.cpp +++ b/iokit/Kernel/IONVRAM.cpp @@ -118,7 +118,9 @@ void IODTNVRAM::registerNVRAMController(IONVRAMController *nvram) _nvramController->read(0, _nvramImage, kIODTNVRAMImageSize); initNVRAMImage(); } else { - syncOFVariables(); + IOLockLock(_ofLock); + (void) syncVariables(); + IOLockUnlock(_ofLock); } } @@ -383,14 +385,13 @@ bool IODTNVRAM::setProperty(const OSSymbol *aKey, OSObject *anObject) bool result; UInt32 propType, propPerm; OSString *tmpString; - OSObject *propObject = 0; - + OSObject *propObject = 0, *oldObject; + if (_ofDict == 0) return false; - + // Verify permissions. propPerm = getOFVariablePerm(aKey); - result = IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege); - if (result != kIOReturnSuccess) { + if (IOUserClient::clientHasPrivilege(current_task(), kIONVRAMPrivilege) != kIOReturnSuccess) { if (propPerm != kOFVariablePermUserWrite) return false; } if (propPerm == kOFVariablePermKernelOnly && current_task() != kernel_task) return 0; @@ -410,15 +411,15 @@ bool IODTNVRAM::setProperty(const OSSymbol *aKey, OSObject *anObject) case kOFVariableTypeBoolean : propObject = OSDynamicCast(OSBoolean, anObject); break; - + case kOFVariableTypeNumber : propObject = OSDynamicCast(OSNumber, anObject); break; - + case kOFVariableTypeString : propObject = OSDynamicCast(OSString, anObject); break; - + case kOFVariableTypeData : propObject = OSDynamicCast(OSData, anObject); if (propObject == 0) { @@ -430,17 +431,36 @@ bool IODTNVRAM::setProperty(const OSSymbol *aKey, OSObject *anObject) } break; } - + if (propObject == 0) return false; IOLockLock(_ofLock); + + oldObject = _ofDict->getObject(aKey); + if (oldObject) { + oldObject->retain(); + } result = _ofDict->setObject(aKey, propObject); - IOLockUnlock(_ofLock); if (result) { - syncOFVariables(); + if (syncVariables() != kIOReturnSuccess) { + if (oldObject) { + _ofDict->setObject(aKey, oldObject); + } + else { + _ofDict->removeObject(aKey); + } + (void) syncVariables(); + result = false; + } } - + + if (oldObject) { + oldObject->release(); + } + + IOLockUnlock(_ofLock); + return result; } @@ -475,11 +495,12 @@ void IODTNVRAM::removeProperty(const OSSymbol *aKey) if (result) { _ofDict->removeObject(aKey); } - IOLockUnlock(_ofLock); if (result) { - syncOFVariables(); + (void) syncVariables(); } + + IOLockUnlock(_ofLock); } IOReturn IODTNVRAM::setProperties(OSObject *properties) @@ -757,6 +778,11 @@ IOReturn IODTNVRAM::initOFVariables(void) } IOReturn IODTNVRAM::syncOFVariables(void) +{ + return kIOReturnUnsupported; +} + +IOReturn IODTNVRAM::syncVariables(void) { bool ok; UInt32 length, maxLength; @@ -764,29 +790,30 @@ IOReturn IODTNVRAM::syncOFVariables(void) const OSSymbol *tmpSymbol; OSObject *tmpObject; OSCollectionIterator *iter; - + + IOLockAssert(_ofLock, kIOLockAssertOwned); + if ((_ofImage == 0) || (_ofDict == 0) || _systemPaniced) return kIOReturnNotReady; - + buffer = tmpBuffer = IONew(UInt8, _ofPartitionSize); if (buffer == 0) return kIOReturnNoMemory; bzero(buffer, _ofPartitionSize); - + ok = true; maxLength = _ofPartitionSize; - IOLockLock(_ofLock); iter = OSCollectionIterator::withCollection(_ofDict); if (iter == 0) ok = false; - + while (ok) { tmpSymbol = OSDynamicCast(OSSymbol, iter->getNextObject()); if (tmpSymbol == 0) break; - + // Don't save 'aapl,panic-info'. if (tmpSymbol->isEqualTo(kIODTNVRAMPanicInfoKey)) continue; - + tmpObject = _ofDict->getObject(tmpSymbol); - + length = maxLength; ok = convertObjectToProp(tmpBuffer, &length, tmpSymbol, tmpObject); if (ok) { @@ -795,21 +822,20 @@ IOReturn IODTNVRAM::syncOFVariables(void) } } iter->release(); - IOLockUnlock(_ofLock); - + if (ok) { bcopy(buffer, _ofImage, _ofPartitionSize); } - + IODelete(buffer, UInt8, _ofPartitionSize); - + if (!ok) return kIOReturnBadArgument; - + if (_nvramController != 0) { - _nvramController->write(0, _nvramImage, kIODTNVRAMImageSize); + return _nvramController->write(0, _nvramImage, kIODTNVRAMImageSize); } - - return kIOReturnSuccess; + + return kIOReturnNotReady; } struct OFVariable { @@ -1376,7 +1402,7 @@ IOReturn IODTNVRAM::writeNVRAMPropertyType1(IORegistryEntry *entry, const OSSymbol *propName, OSData *value) { - OSData *oldData; + OSData *oldData, *escapedData; OSData *data = 0; const UInt8 *startPtr; const UInt8 *propStart; @@ -1400,9 +1426,10 @@ IOReturn IODTNVRAM::writeNVRAMPropertyType1(IORegistryEntry *entry, oldData = OSDynamicCast(OSData, _ofDict->getObject(_registryPropertiesKey)); if (oldData) { + startPtr = (const UInt8 *) oldData->getBytesNoCopy(); endPtr = startPtr + oldData->getLength(); - + propStart = startPtr; wherePtr = startPtr; while (wherePtr < endPtr) { @@ -1430,7 +1457,7 @@ IOReturn IODTNVRAM::writeNVRAMPropertyType1(IORegistryEntry *entry, nvPath = 0; nvName = 0; } - + startPtr = wherePtr; } } @@ -1476,22 +1503,39 @@ IOReturn IODTNVRAM::writeNVRAMPropertyType1(IORegistryEntry *entry, // append prop name ok &= data->appendBytes(propName->getCStringNoCopy(), propName->getLength() + 1); - + // append escaped data - oldData = escapeDataToData(value); - ok &= (oldData != 0); - if (ok) ok &= data->appendBytes(oldData); + escapedData = escapeDataToData(value); + ok &= (escapedData != 0); + if (ok) ok &= data->appendBytes(escapedData); } while (false); + oldData->retain(); if (ok) { ok = _ofDict->setObject(_registryPropertiesKey, data); } - IOLockUnlock(_ofLock); if (data) data->release(); - if (ok) syncOFVariables(); + if (ok) { + if (syncVariables() != kIOReturnSuccess) { + if (oldData) { + _ofDict->setObject(_registryPropertiesKey, oldData); + } + else { + _ofDict->removeObject(_registryPropertiesKey); + } + (void) syncVariables(); + ok = false; + } + } + + if (oldData) { + oldData->release(); + } + + IOLockUnlock(_ofLock); return ok ? kIOReturnSuccess : kIOReturnNoMemory; } diff --git a/iokit/Kernel/IOPMrootDomain.cpp b/iokit/Kernel/IOPMrootDomain.cpp index bf8ecc94f..be3dabe71 100644 --- a/iokit/Kernel/IOPMrootDomain.cpp +++ b/iokit/Kernel/IOPMrootDomain.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2008 Apple Inc. All rights reserved. + * Copyright (c) 1998-2017 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -640,7 +640,7 @@ halt_log_enter(const char * what, const void * pc, uint64_t time) if (!gHaltLog) return; absolutetime_to_nanoseconds(time, &nano); - millis = nano / 1000000ULL; + millis = nano / NSEC_PER_MSEC; if (millis < 100) return; IOLockLock(gHaltLogLock); @@ -659,10 +659,28 @@ halt_log_enter(const char * what, const void * pc, uint64_t time) extern uint32_t gFSState; -extern "C" void IOSystemShutdownNotification(void) +extern "C" void IOSystemShutdownNotification(int stage) { uint64_t startTime; + if (kIOSystemShutdownNotificationStageRootUnmount == stage) + { +#if !CONFIG_EMBEDDED + uint64_t nano, millis; + startTime = mach_absolute_time(); + IOService::getPlatform()->waitQuiet(30 * NSEC_PER_SEC); + absolutetime_to_nanoseconds(mach_absolute_time() - startTime, &nano); + millis = nano / NSEC_PER_MSEC; + if (gHaltTimeMaxLog && (millis >= gHaltTimeMaxLog)) + { + printf("waitQuiet() for unmount %qd ms\n", millis); + } +#endif + return; + } + + assert(kIOSystemShutdownNotificationStageProcessExit == stage); + IOLockLock(gHaltLogLock); if (!gHaltLog) { @@ -888,7 +906,7 @@ static UInt32 computeDeltaTimeMS( const AbsoluteTime * startTime, AbsoluteTime * *elapsedTime = endTime; } - return (UInt32)(nano / 1000000ULL); + return (UInt32)(nano / NSEC_PER_MSEC); } //****************************************************************************** @@ -3257,6 +3275,40 @@ void IOPMrootDomain::handlePublishSleepWakeUUID( bool shouldPublish ) } } +//****************************************************************************** +// IOPMGetSleepWakeUUIDKey +// +// Return the truth value of gSleepWakeUUIDIsSet and optionally copy the key. +// To get the full key -- a C string -- the buffer must large enough for +// the end-of-string character. +// The key is expected to be an UUID string +//****************************************************************************** + +extern "C" bool +IOPMCopySleepWakeUUIDKey(char *buffer, size_t buf_len) +{ + if (!gSleepWakeUUIDIsSet) { + return (false); + } + + if (buffer != NULL) { + OSString *string; + + string = (OSString *) + gRootDomain->copyProperty(kIOPMSleepWakeUUIDKey); + + if (string == NULL) { + *buffer = '\0'; + } else { + strlcpy(buffer, string->getCStringNoCopy(), buf_len); + + string->release(); + } + } + + return (true); +} + //****************************************************************************** // initializeBootSessionUUID // @@ -5644,7 +5696,7 @@ void IOPMrootDomain::overridePowerChangeForUIService( absolutetime_to_nanoseconds(now, &nsec); if (kIOLogPMRootDomain & gIOKitDebug) MSG("Graphics suppressed %u ms\n", - ((int)((nsec) / 1000000ULL))); + ((int)((nsec) / NSEC_PER_MSEC))); } graphicsSuppressed = true; } @@ -7528,7 +7580,7 @@ void IOPMrootDomain::requestFullWake( FullWakeReason reason ) absolutetime_to_nanoseconds(now, &nsec); MSG("full wake %s (reason %u) %u ms\n", promotion ? "promotion" : "request", - fullWakeReason, ((int)((nsec) / 1000000ULL))); + fullWakeReason, ((int)((nsec) / NSEC_PER_MSEC))); } } @@ -7685,7 +7737,7 @@ void IOPMrootDomain::pmStatsRecordEvent( if (stopping) { delta = gPMStats.hibWrite.stop - gPMStats.hibWrite.start; - IOLog("PMStats: Hibernate write took %qd ms\n", delta/1000000ULL); + IOLog("PMStats: Hibernate write took %qd ms\n", delta/NSEC_PER_MSEC); } break; case kIOPMStatsHibernateImageRead: @@ -7696,7 +7748,7 @@ void IOPMrootDomain::pmStatsRecordEvent( if (stopping) { delta = gPMStats.hibRead.stop - gPMStats.hibRead.start; - IOLog("PMStats: Hibernate read took %qd ms\n", delta/1000000ULL); + IOLog("PMStats: Hibernate read took %qd ms\n", delta/NSEC_PER_MSEC); publishPMStats = OSData::withBytes(&gPMStats, sizeof(gPMStats)); setProperty(kIOPMSleepStatisticsKey, publishPMStats); diff --git a/iokit/Kernel/IOPlatformExpert.cpp b/iokit/Kernel/IOPlatformExpert.cpp index 59c36062e..7372f799a 100644 --- a/iokit/Kernel/IOPlatformExpert.cpp +++ b/iokit/Kernel/IOPlatformExpert.cpp @@ -59,6 +59,7 @@ extern "C" { #if !CONFIG_EMBEDDED boolean_t coprocessor_cross_panic_enabled = TRUE; +#define APPLE_SECURE_BOOT_VARIABLE_GUID "94b73556-2197-4702-82a8-3e1337dafbfb" #endif /* !CONFIG_EMBEDDED */ void printDictionaryKeys (OSDictionary * inDictionary, char * inMsg); @@ -869,7 +870,10 @@ int PEHaltRestart(unsigned int type) if (type == kPEPanicRestartCPU) { // Notify any listeners that we're done collecting // panic data before we call through to do the restart - IOCPURunPlatformPanicActions(kPEPanicEnd); +#if !CONFIG_EMBEDDED + if (coprocessor_cross_panic_enabled) +#endif + IOCPURunPlatformPanicActions(kPEPanicEnd); // Callout to shutdown the disk driver once we've returned from the // kPEPanicEnd callback (and we know all core dumps on this system @@ -1192,7 +1196,7 @@ void IOPlatformExpert::registerNVRAMController(IONVRAMController * caller) entry = IORegistryEntry::fromPath( "/options", gIODTPlane ); if ( entry ) { - data = OSDynamicCast( OSData, entry->getProperty( "EffectiveProductionStatus" ) ); + data = OSDynamicCast( OSData, entry->getProperty( APPLE_SECURE_BOOT_VARIABLE_GUID":EffectiveProductionStatus" ) ); if ( data && ( data->getLength( ) == sizeof( UInt8 ) ) ) { UInt8 *isProdFused = (UInt8 *) data->getBytesNoCopy( ); UInt32 debug_flags = 0; @@ -1619,7 +1623,6 @@ IOPlatformExpertDevice::initWithArgs( if( !ok) return( false); - reserved = NULL; workLoop = IOWorkLoop::workLoop(); if (!workLoop) return false; diff --git a/iokit/Kernel/IOPolledInterface.cpp b/iokit/Kernel/IOPolledInterface.cpp index 821bbc81b..780d64cd8 100644 --- a/iokit/Kernel/IOPolledInterface.cpp +++ b/iokit/Kernel/IOPolledInterface.cpp @@ -44,7 +44,7 @@ OSDefineMetaClassAndAbstractStructors(IOPolledInterface, OSObject); -OSMetaClassDefineReservedUnused(IOPolledInterface, 0); +OSMetaClassDefineReservedUsed(IOPolledInterface, 0); OSMetaClassDefineReservedUnused(IOPolledInterface, 1); OSMetaClassDefineReservedUnused(IOPolledInterface, 2); OSMetaClassDefineReservedUnused(IOPolledInterface, 3); @@ -293,6 +293,38 @@ IOPolledFilePollersClose(IOPolledFileIOVars * filevars, uint32_t state) return (err); } + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +IOReturn IOPolledInterface::setEncryptionKey(const uint8_t * key, size_t keySize) +{ + return (kIOReturnUnsupported); +} + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +IOReturn +IOPolledFilePollersSetEncryptionKey(IOPolledFileIOVars * filevars, + const uint8_t * key, size_t keySize) +{ + IOReturn ret = kIOReturnUnsupported; + IOReturn err; + int32_t idx; + IOPolledFilePollers * vars = filevars->pollers; + IOPolledInterface * poller; + + for (idx = 0; + (poller = (IOPolledInterface *) vars->pollers->getObject(idx)); + idx++) + { + poller = (IOPolledInterface *) vars->pollers->getObject(idx); + err = poller->setEncryptionKey(key, keySize); + if (kIOReturnSuccess == err) ret = err; + } + + return (ret); +} + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ IOMemoryDescriptor * @@ -471,7 +503,7 @@ IOCopyMediaForDev(dev_t device) static IOReturn IOGetVolumeCryptKey(dev_t block_dev, OSString ** pKeyUUID, - uint8_t * volumeCryptKey, size_t keySize) + uint8_t * volumeCryptKey, size_t * keySize) { IOReturn err; IOService * part; @@ -488,9 +520,15 @@ IOGetVolumeCryptKey(dev_t block_dev, OSString ** pKeyUUID, // Try APFS first { uuid_t volUuid = {0}; - size_t sizeOut = 0; - err = part->callPlatformFunction(APFSMEDIA_GETHIBERKEY, false, &volUuid, volumeCryptKey, &keySize, &sizeOut); - if (err == kIOReturnSuccess) + err = part->callPlatformFunction(APFSMEDIA_GETHIBERKEY, false, &volUuid, volumeCryptKey, keySize, keySize); + if (kIOReturnBadArgument == err) + { + // apfs fails on buffer size >32 + *keySize = 32; + err = part->callPlatformFunction(APFSMEDIA_GETHIBERKEY, false, &volUuid, volumeCryptKey, keySize, keySize); + } + if (err != kIOReturnSuccess) *keySize = 0; + else { // No need to create uuid string if it's not requested if (pKeyUUID) @@ -524,8 +562,8 @@ IOGetVolumeCryptKey(dev_t block_dev, OSString ** pKeyUUID, IOLog("volume key err 0x%x\n", err); else { - if (vek.key.keybytecount < keySize) keySize = vek.key.keybytecount; - bcopy(&vek.key.keybytes[0], volumeCryptKey, keySize); + if (vek.key.keybytecount < *keySize) *keySize = vek.key.keybytecount; + bcopy(&vek.key.keybytes[0], volumeCryptKey, *keySize); } bzero(&vek, sizeof(vek)); @@ -548,7 +586,7 @@ IOPolledFileOpen(const char * filename, void * write_file_addr, size_t write_file_len, IOPolledFileIOVars ** fileVars, OSData ** imagePath, - uint8_t * volumeCryptKey, size_t keySize) + uint8_t * volumeCryptKey, size_t * keySize) { IOReturn err = kIOReturnSuccess; IOPolledFileIOVars * vars; diff --git a/iokit/Kernel/IORangeAllocator.cpp b/iokit/Kernel/IORangeAllocator.cpp index 12804d24a..393a9c03b 100644 --- a/iokit/Kernel/IORangeAllocator.cpp +++ b/iokit/Kernel/IORangeAllocator.cpp @@ -142,7 +142,8 @@ bool IORangeAllocator::allocElement( UInt32 index ) if( ((numElements == capacity) && capacityIncrement) || (!elements)) { - newCapacity = capacity + capacityIncrement; + if (os_add_overflow(capacity, capacityIncrement, &newCapacity)) + return( false ); newElements = IONew( IORangeAllocatorElement, newCapacity ); if( !newElements) return( false ); diff --git a/iokit/Kernel/IOService.cpp b/iokit/Kernel/IOService.cpp index 207c8dc29..5395c1dc3 100644 --- a/iokit/Kernel/IOService.cpp +++ b/iokit/Kernel/IOService.cpp @@ -2278,16 +2278,20 @@ void IOService::scheduleTerminatePhase2( IOOptionBits options ) terminateWorker( options ); wait = (0 != (__state[1] & kIOServiceBusyStateMask)); if( wait) { - // wait for the victim to go non-busy + /* wait for the victim to go non-busy */ if( !haveDeadline) { clock_interval_to_deadline( 15, kSecondScale, &deadline ); haveDeadline = true; } + /* let others do work while we wait */ + gIOTerminateThread = 0; + IOLockWakeup( gJobsLock, (event_t) &gIOTerminateThread, /* one-thread */ false); waitResult = IOLockSleepDeadline( gJobsLock, &gIOTerminateWork, deadline, THREAD_UNINT ); - if(__improbable(waitResult == THREAD_TIMED_OUT)) { + if (__improbable(waitResult == THREAD_TIMED_OUT)) { panic("%s[0x%qx]::terminate(kIOServiceSynchronous) timeout\n", getName(), getRegistryEntryID()); - } + } + waitToBecomeTerminateThread(); } } while(gIOTerminateWork || (wait && (waitResult != THREAD_TIMED_OUT))); diff --git a/iokit/Kernel/IOUserClient.cpp b/iokit/Kernel/IOUserClient.cpp index ad83881ca..d331cb2b0 100644 --- a/iokit/Kernel/IOUserClient.cpp +++ b/iokit/Kernel/IOUserClient.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -124,45 +125,13 @@ do { \ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -// definitions we should get from osfmk - -//typedef struct ipc_port * ipc_port_t; -typedef natural_t ipc_kobject_type_t; - -#define IKOT_IOKIT_SPARE 27 -#define IKOT_IOKIT_CONNECT 29 -#define IKOT_IOKIT_OBJECT 30 - extern "C" { -extern ipc_port_t iokit_alloc_object_port( io_object_t obj, - ipc_kobject_type_t type ); - -extern kern_return_t iokit_destroy_object_port( ipc_port_t port ); - -extern mach_port_name_t iokit_make_send_right( task_t task, - io_object_t obj, ipc_kobject_type_t type ); - -extern kern_return_t iokit_mod_send_right( task_t task, mach_port_name_t name, mach_port_delta_t delta ); - -extern io_object_t iokit_lookup_connect_ref(io_object_t clientRef, ipc_space_t task); - -extern io_object_t iokit_lookup_connect_ref_current_task(io_object_t clientRef); - -extern ipc_port_t master_device_port; - -extern void iokit_retain_port( ipc_port_t port ); -extern void iokit_release_port( ipc_port_t port ); -extern void iokit_release_port_send( ipc_port_t port ); - -extern kern_return_t iokit_switch_object_port( ipc_port_t port, io_object_t obj, ipc_kobject_type_t type ); - #include #include } /* extern "C" */ - /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ // IOMachPort maps OSObjects to ports, avoiding adding an ivar to OSObject. @@ -202,17 +171,28 @@ static IOLock * gIOObjectPortLock; // not in dictForType() for debugging ease static OSDictionary * gIOObjectPorts; static OSDictionary * gIOConnectPorts; +static OSDictionary * gIOIdentifierPorts; OSDictionary * IOMachPort::dictForType( ipc_kobject_type_t type ) { OSDictionary ** dict; - if( IKOT_IOKIT_OBJECT == type ) - dict = &gIOObjectPorts; - else if( IKOT_IOKIT_CONNECT == type ) - dict = &gIOConnectPorts; - else - return( 0 ); + switch (type) + { + case IKOT_IOKIT_OBJECT: + dict = &gIOObjectPorts; + break; + case IKOT_IOKIT_CONNECT: + dict = &gIOConnectPorts; + break; + case IKOT_IOKIT_IDENT: + dict = &gIOIdentifierPorts; + break; + default: + panic("dictForType %d", type); + dict = NULL; + break; + } if( 0 == *dict) *dict = OSDictionary::withCapacity( 1 ); @@ -507,10 +487,19 @@ extern "C" { // functions called from osfmk/device/iokit_rpc.c void -iokit_add_reference( io_object_t obj ) +iokit_add_reference( io_object_t obj, ipc_kobject_type_t type ) { - if( obj) - obj->retain(); + IOUserClient * uc; + + if (!obj) return; + + if ((IKOT_IOKIT_CONNECT == type) + && (uc = OSDynamicCast(IOUserClient, obj))) + { + OSIncrementAtomic(&uc->__ipc); + } + + obj->retain(); } void @@ -520,18 +509,6 @@ iokit_remove_reference( io_object_t obj ) obj->release(); } -void -iokit_add_connect_reference( io_object_t obj ) -{ - IOUserClient * uc; - - if (!obj) return; - - if ((uc = OSDynamicCast(IOUserClient, obj))) OSIncrementAtomic(&uc->__ipc); - - obj->retain(); -} - void iokit_remove_connect_reference( io_object_t obj ) { @@ -1661,9 +1638,41 @@ IOReturn IOUserClient::exportObjectToClient(task_t task, name = IOMachPort::makeSendRightForTask( task, obj, IKOT_IOKIT_OBJECT ); *(mach_port_name_t *)clientObj = name; + + if (obj) obj->release(); + return kIOReturnSuccess; } +IOReturn IOUserClient::copyPortNameForObjectInTask(task_t task, + OSObject *obj, mach_port_name_t * port_name) +{ + mach_port_name_t name; + + name = IOMachPort::makeSendRightForTask( task, obj, IKOT_IOKIT_IDENT ); + + *(mach_port_name_t *) port_name = name; + + return kIOReturnSuccess; +} + +IOReturn IOUserClient::copyObjectForPortNameInTask(task_t task, mach_port_name_t port_name, + OSObject **obj) +{ + OSObject * object; + + object = iokit_lookup_object_with_port_name(port_name, IKOT_IOKIT_IDENT, task); + + *obj = object; + + return (object ? kIOReturnSuccess : kIOReturnIPCError); +} + +IOReturn IOUserClient::adjustPortNameReferencesInTask(task_t task, mach_port_name_t port_name, mach_port_delta_t delta) +{ + return (iokit_mod_send_right(task, port_name, delta)); +} + IOExternalMethod * IOUserClient::getExternalMethodForIndex( UInt32 /* index */) { return( 0 ); @@ -3620,6 +3629,7 @@ kern_return_t is_io_connect_map_memory_into_task mach_port_name_t name __unused = IOMachPort::makeSendRightForTask( into_task, map, IKOT_IOKIT_OBJECT ); + map->release(); } else { // keep it with the user client @@ -3730,7 +3740,11 @@ kern_return_t is_io_connect_unmap_memory_from_task mach_port_name_t name = 0; if (from_task != current_task()) + { name = IOMachPort::makeSendRightForTask( from_task, map, IKOT_IOKIT_OBJECT ); + map->release(); + } + if (name) { map->userClientUnmap(); @@ -5237,7 +5251,7 @@ kern_return_t iokit_user_client_trap(struct iokit_user_client_trap_args *args) IOUserClient *userClient; if ((userClient = OSDynamicCast(IOUserClient, - iokit_lookup_connect_ref_current_task((OSObject *)(args->userClientRef))))) { + iokit_lookup_connect_ref_current_task((mach_port_name_t)(uintptr_t)args->userClientRef)))) { IOExternalTrap *trap; IOService *target = NULL; @@ -5259,6 +5273,24 @@ kern_return_t iokit_user_client_trap(struct iokit_user_client_trap_args *args) return result; } +/* Routine io_device_tree_entry_exists_with_name */ +kern_return_t is_io_device_tree_entry_exists_with_name( + mach_port_t master_port, + io_name_t name, + boolean_t *exists ) +{ + OSCollectionIterator *iter; + + if (master_port != master_device_port) + return (kIOReturnNotPrivileged); + + iter = IODTFindMatchingEntries(IORegistryEntry::getRegistryRoot(), kIODTRecursive, name); + *exists = iter && iter->getNextObject(); + OSSafeReleaseNULL(iter); + + return kIOReturnSuccess; +} + } /* extern "C" */ IOReturn IOUserClient::externalMethod( uint32_t selector, IOExternalMethodArguments * args, diff --git a/iokit/Tests/Tests.cpp b/iokit/Tests/Tests.cpp index 173cad671..d1ba499d8 100644 --- a/iokit/Tests/Tests.cpp +++ b/iokit/Tests/Tests.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved. + * Copyright (c) 1998-2018 Apple Computer, Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * diff --git a/iokit/bsddev/IOKitBSDInit.cpp b/iokit/bsddev/IOKitBSDInit.cpp index 890b89946..27ef74433 100644 --- a/iokit/bsddev/IOKitBSDInit.cpp +++ b/iokit/bsddev/IOKitBSDInit.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2011 Apple Inc. All rights reserved. + * Copyright (c) 1998-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -940,6 +940,7 @@ IOBSDMountChange(struct mount * mp, uint32_t op) #endif /* IOPOLLED_COREFILE */ } + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ extern "C" boolean_t diff --git a/libkdd/kcdata.h b/libkdd/kcdata.h index e358b4ec8..702bfacbc 100644 --- a/libkdd/kcdata.h +++ b/libkdd/kcdata.h @@ -456,7 +456,7 @@ struct kcdata_type_definition { #define STACKSHOT_KCTYPE_DELTA_SINCE_TIMESTAMP 0x912u /* timestamp used for the delta stackshot */ #define STACKSHOT_KCTYPE_TASK_DELTA_SNAPSHOT 0x940u /* task_delta_snapshot_v2 */ -#define STACKSHOT_KCTYPE_THREAD_DELTA_SNAPSHOT 0x941u /* thread_delta_snapshot_v2 */ +#define STACKSHOT_KCTYPE_THREAD_DELTA_SNAPSHOT 0x941u /* thread_delta_snapshot_v* */ #define STACKSHOT_KCTYPE_KERN_STACKLR 0x913u /* uint32_t */ #define STACKSHOT_KCTYPE_KERN_STACKLR64 0x914u /* uint64_t */ @@ -704,6 +704,23 @@ struct thread_delta_snapshot_v2 { uint8_t tds_io_tier; } __attribute__ ((packed)); +struct thread_delta_snapshot_v3 { + uint64_t tds_thread_id; + uint64_t tds_voucher_identifier; + uint64_t tds_ss_flags; + uint64_t tds_last_made_runnable_time; + uint32_t tds_state; + uint32_t tds_sched_flags; + int16_t tds_base_priority; + int16_t tds_sched_priority; + uint8_t tds_eqos; + uint8_t tds_rqos; + uint8_t tds_rqos_override; + uint8_t tds_io_tier; + uint64_t tds_requested_policy; + uint64_t tds_effective_policy; +} __attribute__ ((packed)); + struct io_stats_snapshot { /* @@ -805,13 +822,22 @@ typedef struct stackshot_thread_waitinfo { /* FIXME some of these types aren't clean (fixed width, packed, and defined *here*) */ +struct crashinfo_proc_uniqidentifierinfo { + uint8_t p_uuid[16]; /* UUID of the main executable */ + uint64_t p_uniqueid; /* 64 bit unique identifier for process */ + uint64_t p_puniqueid; /* unique identifier for process's parent */ + uint64_t p_reserve2; /* reserved for future use */ + uint64_t p_reserve3; /* reserved for future use */ + uint64_t p_reserve4; /* reserved for future use */ +} __attribute__((packed)); + #define TASK_CRASHINFO_BEGIN KCDATA_BUFFER_BEGIN_CRASHINFO #define TASK_CRASHINFO_STRING_DESC KCDATA_TYPE_STRING_DESC #define TASK_CRASHINFO_UINT32_DESC KCDATA_TYPE_UINT32_DESC #define TASK_CRASHINFO_UINT64_DESC KCDATA_TYPE_UINT64_DESC #define TASK_CRASHINFO_EXTMODINFO 0x801 -#define TASK_CRASHINFO_BSDINFOWITHUNIQID 0x802 /* struct proc_uniqidentifierinfo */ +#define TASK_CRASHINFO_BSDINFOWITHUNIQID 0x802 /* struct crashinfo_proc_uniqidentifierinfo */ #define TASK_CRASHINFO_TASKDYLD_INFO 0x803 #define TASK_CRASHINFO_UUID 0x804 #define TASK_CRASHINFO_PID 0x805 diff --git a/libkdd/kcdtypes.c b/libkdd/kcdtypes.c index 73cbeb918..0a36b5aa7 100644 --- a/libkdd/kcdtypes.c +++ b/libkdd/kcdtypes.c @@ -29,7 +29,6 @@ #include #include #include -#include /*! * @function kcdata_get_typedescription @@ -347,6 +346,8 @@ kcdata_get_typedescription(unsigned type_id, uint8_t * buffer, uint32_t buffer_s _SUBTYPE(KC_ST_UINT8, struct thread_delta_snapshot_v2, tds_rqos); _SUBTYPE(KC_ST_UINT8, struct thread_delta_snapshot_v2, tds_rqos_override); _SUBTYPE(KC_ST_UINT8, struct thread_delta_snapshot_v2, tds_io_tier); + _SUBTYPE(KC_ST_UINT64, struct thread_delta_snapshot_v3, tds_requested_policy); + _SUBTYPE(KC_ST_UINT64, struct thread_delta_snapshot_v3, tds_effective_policy); setup_type_definition(retval, type_id, i, "thread_delta_snapshot"); @@ -468,9 +469,9 @@ kcdata_get_typedescription(unsigned type_id, uint8_t * buffer, uint32_t buffer_s /* crashinfo types */ case TASK_CRASHINFO_BSDINFOWITHUNIQID: { i = 0; - _SUBTYPE_ARRAY(KC_ST_UINT8, struct proc_uniqidentifierinfo, p_uuid, 16); - _SUBTYPE(KC_ST_UINT64, struct proc_uniqidentifierinfo, p_uniqueid); - _SUBTYPE(KC_ST_UINT64, struct proc_uniqidentifierinfo, p_puniqueid); + _SUBTYPE_ARRAY(KC_ST_UINT8, struct crashinfo_proc_uniqidentifierinfo, p_uuid, 16); + _SUBTYPE(KC_ST_UINT64, struct crashinfo_proc_uniqidentifierinfo, p_uniqueid); + _SUBTYPE(KC_ST_UINT64, struct crashinfo_proc_uniqidentifierinfo, p_puniqueid); /* Ignore the p_reserve fields */ setup_type_definition(retval, type_id, i, "proc_uniqidentifierinfo"); break; diff --git a/libkdd/kdd.framework/Info.plist b/libkdd/kdd.framework/Info.plist new file mode 100644 index 000000000..453e6757c --- /dev/null +++ b/libkdd/kdd.framework/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSHumanReadableCopyright + Copyright © 2017 Apple Inc. All rights reserved. + NSPrincipalClass + + + diff --git a/libkdd/kdd.framework/module.modulemap b/libkdd/kdd.framework/module.modulemap new file mode 100644 index 000000000..cda3d529f --- /dev/null +++ b/libkdd/kdd.framework/module.modulemap @@ -0,0 +1,7 @@ +framework module kdd { + header "kcdata.h" + module kdd_kdd { + requires objc + header "kdd.h" + } +} diff --git a/libkdd/kdd.frameworkTests/Info.plist b/libkdd/kdd.frameworkTests/Info.plist new file mode 100644 index 000000000..6c40a6cd0 --- /dev/null +++ b/libkdd/kdd.frameworkTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/libkdd/kdd.h b/libkdd/kdd.h index c7f528035..8a2a75dd6 100644 --- a/libkdd/kdd.h +++ b/libkdd/kdd.h @@ -29,9 +29,8 @@ #ifndef _KDD_H_ #define _KDD_H_ -#include - #import +#import /*! * @class KCDataType @@ -123,7 +122,7 @@ NSMutableDictionary * _Nullable parseKCDataArray(kcdata_iter_t iter, NSError * _ * */ -NSMutableDictionary * _Nullable parseKCDataContainer(kcdata_iter_t * _Nonnull iter_p, NSError * _Nullable * _Nullable error) NS_RETURNS_RETAINED; +NSMutableDictionary * _Nullable parseKCDataContainer(kcdata_iter_t * _Nonnull iter, NSError * _Nullable * _Nullable error) NS_RETURNS_RETAINED; /*! * @function parseKCDataBuffer diff --git a/libkdd/kdd.xcodeproj/project.pbxproj b/libkdd/kdd.xcodeproj/project.pbxproj index e36cc086c..f9e1e5425 100644 --- a/libkdd/kdd.xcodeproj/project.pbxproj +++ b/libkdd/kdd.xcodeproj/project.pbxproj @@ -15,6 +15,7 @@ 081EDD391C23855700A1C138 /* stackshot-sample-cputime.plist.gz in Resources */ = {isa = PBXBuildFile; fileRef = 081EDD371C23854500A1C138 /* stackshot-sample-cputime.plist.gz */; }; 08238A3B1BFEB5450053190C /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 08F1501D1BFEA7AC00F2C89C /* libz.dylib */; }; 0834719E1BF7D05400D67253 /* kcdata.h in Headers */ = {isa = PBXBuildFile; fileRef = 0834719D1BF7D05400D67253 /* kcdata.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 084085AC1FA3CE3D005BAD16 /* kdd.h in Headers */ = {isa = PBXBuildFile; fileRef = 084085AA1FA3CE32005BAD16 /* kdd.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0843EE921BF6AFC600CD4150 /* stackshot-sample in Resources */ = {isa = PBXBuildFile; fileRef = 0843EE911BF6AFB700CD4150 /* stackshot-sample */; }; 0843EE941BF6BAC100CD4150 /* stackshot-sample.plist.gz in Resources */ = {isa = PBXBuildFile; fileRef = 0843EE931BF6BAB400CD4150 /* stackshot-sample.plist.gz */; }; 08603F371BF69EDE007D3784 /* Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 08603F361BF69EDE007D3784 /* Tests.swift */; }; @@ -23,6 +24,14 @@ 0860F87B1BFC3857007E1301 /* stackshot-sample-tailspin-2.plist.gz in Resources */ = {isa = PBXBuildFile; fileRef = 0860F8791BFC3845007E1301 /* stackshot-sample-tailspin-2.plist.gz */; }; 086395B51BF5655D005ED913 /* kdd_main.m in Sources */ = {isa = PBXBuildFile; fileRef = 086395B41BF5655D005ED913 /* kdd_main.m */; }; 086395B91BF565A2005ED913 /* libkdd.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C91C93C71ACB58B700119B60 /* libkdd.a */; }; + 0864FD081FA3C127001B7B0B /* kcdata.h in Headers */ = {isa = PBXBuildFile; fileRef = 0834719D1BF7D05400D67253 /* kcdata.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 0864FD0A1FA3C2A9001B7B0B /* kcdtypes.c in Sources */ = {isa = PBXBuildFile; fileRef = C9C5C68B1ACDAFDB00BE0E5E /* kcdtypes.c */; }; + 0864FD0B1FA3C2A9001B7B0B /* kcdata_core.m in Sources */ = {isa = PBXBuildFile; fileRef = C9DE39131ACB5A540020F4A3 /* kcdata_core.m */; }; + 0864FD0D1FA3C2A9001B7B0B /* KCDBasicTypeDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = C91C93E11ACB598700119B60 /* KCDBasicTypeDescription.m */; }; + 0864FD0F1FA3C2A9001B7B0B /* KCDStructTypeDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = C91C93E31ACB598700119B60 /* KCDStructTypeDescription.m */; }; + 0864FD111FA3C2A9001B7B0B /* KCDEmbeddedBufferDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 08A4C94B1C4701B800D5F010 /* KCDEmbeddedBufferDescription.m */; }; + 0864FD131FA3C2A9001B7B0B /* kdd.m in Sources */ = {isa = PBXBuildFile; fileRef = C91C93CC1ACB58B700119B60 /* kdd.m */; }; + 0864FD141FA3C2B9001B7B0B /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 08F1501D1BFEA7AC00F2C89C /* libz.dylib */; }; 088C36E01EF323C300ABB2E0 /* stackshot-sample-thread-policy in Resources */ = {isa = PBXBuildFile; fileRef = 088C36DF1EF323AE00ABB2E0 /* stackshot-sample-thread-policy */; }; 088C36E11EF323C300ABB2E0 /* stackshot-sample-thread-policy.plist.gz in Resources */ = {isa = PBXBuildFile; fileRef = 088C36DE1EF323AE00ABB2E0 /* stackshot-sample-thread-policy.plist.gz */; }; 08A4C94C1C4701B800D5F010 /* KCDEmbeddedBufferDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = 08A4C94B1C4701B800D5F010 /* KCDEmbeddedBufferDescription.m */; }; @@ -46,6 +55,8 @@ 08CF18FF1BF9B7B100D05813 /* stackshot-sample-tailspin in Resources */ = {isa = PBXBuildFile; fileRef = 08CF18FD1BF9B79E00D05813 /* stackshot-sample-tailspin */; }; 08CF19001BF9B7B100D05813 /* stackshot-sample-tailspin.plist.gz in Resources */ = {isa = PBXBuildFile; fileRef = 08CF18FE1BF9B79E00D05813 /* stackshot-sample-tailspin.plist.gz */; }; 08F1501E1BFEA7AC00F2C89C /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 08F1501D1BFEA7AC00F2C89C /* libz.dylib */; }; + 08F2AC0A1FA136EB00271A11 /* stackshot-sample-delta-thread-policy in Resources */ = {isa = PBXBuildFile; fileRef = 08F2AC081FA136EB00271A11 /* stackshot-sample-delta-thread-policy */; }; + 08F2AC0B1FA136EB00271A11 /* stackshot-sample-delta-thread-policy.plist.gz in Resources */ = {isa = PBXBuildFile; fileRef = 08F2AC091FA136EB00271A11 /* stackshot-sample-delta-thread-policy.plist.gz */; }; 1368F0851C87E06A00940FC6 /* exitreason-codesigning.plist.gz in Resources */ = {isa = PBXBuildFile; fileRef = 1368F0841C87E06300940FC6 /* exitreason-codesigning.plist.gz */; }; 1368F0861C87E06C00940FC6 /* exitreason-codesigning in Resources */ = {isa = PBXBuildFile; fileRef = 1368F0831C87E06300940FC6 /* exitreason-codesigning */; }; 13A79CAA1CF8C5D600FFC181 /* stackshot-with-kcid in Resources */ = {isa = PBXBuildFile; fileRef = 13A79CA81CF8C5D200FFC181 /* stackshot-with-kcid */; }; @@ -117,6 +128,8 @@ 081EDD361C23854500A1C138 /* stackshot-sample-cputime */ = {isa = PBXFileReference; lastKnownFileType = file; name = "stackshot-sample-cputime"; path = "tests/stackshot-sample-cputime"; sourceTree = SOURCE_ROOT; }; 081EDD371C23854500A1C138 /* stackshot-sample-cputime.plist.gz */ = {isa = PBXFileReference; lastKnownFileType = archive.gzip; name = "stackshot-sample-cputime.plist.gz"; path = "tests/stackshot-sample-cputime.plist.gz"; sourceTree = SOURCE_ROOT; }; 0834719D1BF7D05400D67253 /* kcdata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = kcdata.h; path = ../osfmk/kern/kcdata.h; sourceTree = ""; }; + 084085AA1FA3CE32005BAD16 /* kdd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kdd.h; sourceTree = BUILT_PRODUCTS_DIR; }; + 084085AE1FA3D156005BAD16 /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = ""; }; 0843EE911BF6AFB700CD4150 /* stackshot-sample */ = {isa = PBXFileReference; lastKnownFileType = text; name = "stackshot-sample"; path = "tests/stackshot-sample"; sourceTree = SOURCE_ROOT; }; 0843EE931BF6BAB400CD4150 /* stackshot-sample.plist.gz */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = archive.gzip; name = "stackshot-sample.plist.gz"; path = "tests/stackshot-sample.plist.gz"; sourceTree = SOURCE_ROOT; }; 08603F341BF69EDE007D3784 /* tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -127,6 +140,10 @@ 0860F8791BFC3845007E1301 /* stackshot-sample-tailspin-2.plist.gz */ = {isa = PBXFileReference; lastKnownFileType = archive.gzip; name = "stackshot-sample-tailspin-2.plist.gz"; path = "tests/stackshot-sample-tailspin-2.plist.gz"; sourceTree = SOURCE_ROOT; }; 086395B21BF5655D005ED913 /* kdd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = kdd; sourceTree = BUILT_PRODUCTS_DIR; }; 086395B41BF5655D005ED913 /* kdd_main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = kdd_main.m; sourceTree = ""; }; + 0864FCEF1FA3C0B7001B7B0B /* kdd.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = kdd.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 0864FCF21FA3C0B7001B7B0B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 0864FCFC1FA3C0B7001B7B0B /* kdd_frameworkTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = kdd_frameworkTests.m; sourceTree = ""; }; + 0864FCFE1FA3C0B7001B7B0B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 088C36DE1EF323AE00ABB2E0 /* stackshot-sample-thread-policy.plist.gz */ = {isa = PBXFileReference; lastKnownFileType = archive.gzip; path = "stackshot-sample-thread-policy.plist.gz"; sourceTree = ""; }; 088C36DF1EF323AE00ABB2E0 /* stackshot-sample-thread-policy */ = {isa = PBXFileReference; lastKnownFileType = file; path = "stackshot-sample-thread-policy"; sourceTree = ""; }; 08A4C94A1C47019E00D5F010 /* KCDEmbeddedBufferDescription.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KCDEmbeddedBufferDescription.h; sourceTree = ""; }; @@ -151,6 +168,8 @@ 08CF18FD1BF9B79E00D05813 /* stackshot-sample-tailspin */ = {isa = PBXFileReference; lastKnownFileType = file; name = "stackshot-sample-tailspin"; path = "tests/stackshot-sample-tailspin"; sourceTree = SOURCE_ROOT; }; 08CF18FE1BF9B79E00D05813 /* stackshot-sample-tailspin.plist.gz */ = {isa = PBXFileReference; lastKnownFileType = archive.gzip; name = "stackshot-sample-tailspin.plist.gz"; path = "tests/stackshot-sample-tailspin.plist.gz"; sourceTree = SOURCE_ROOT; }; 08F1501D1BFEA7AC00F2C89C /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/usr/lib/libz.dylib; sourceTree = DEVELOPER_DIR; }; + 08F2AC081FA136EB00271A11 /* stackshot-sample-delta-thread-policy */ = {isa = PBXFileReference; lastKnownFileType = file; path = "stackshot-sample-delta-thread-policy"; sourceTree = ""; }; + 08F2AC091FA136EB00271A11 /* stackshot-sample-delta-thread-policy.plist.gz */ = {isa = PBXFileReference; lastKnownFileType = archive.gzip; path = "stackshot-sample-delta-thread-policy.plist.gz"; sourceTree = ""; }; 1368F0831C87E06300940FC6 /* exitreason-codesigning */ = {isa = PBXFileReference; lastKnownFileType = file; name = "exitreason-codesigning"; path = "tests/exitreason-codesigning"; sourceTree = SOURCE_ROOT; }; 1368F0841C87E06300940FC6 /* exitreason-codesigning.plist.gz */ = {isa = PBXFileReference; lastKnownFileType = archive.gzip; name = "exitreason-codesigning.plist.gz"; path = "tests/exitreason-codesigning.plist.gz"; sourceTree = SOURCE_ROOT; }; 13A79CA81CF8C5D200FFC181 /* stackshot-with-kcid */ = {isa = PBXFileReference; lastKnownFileType = file; name = "stackshot-with-kcid"; path = "tests/stackshot-with-kcid"; sourceTree = SOURCE_ROOT; }; @@ -205,6 +224,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 0864FCEB1FA3C0B7001B7B0B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 0864FD141FA3C2B9001B7B0B /* libz.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; C91C93C41ACB58B700119B60 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -218,6 +245,8 @@ 08603F351BF69EDE007D3784 /* tests */ = { isa = PBXGroup; children = ( + 08F2AC081FA136EB00271A11 /* stackshot-sample-delta-thread-policy */, + 08F2AC091FA136EB00271A11 /* stackshot-sample-delta-thread-policy.plist.gz */, 18C577C51F96DB7100C67EB3 /* stackshot-sample-thread-groups-flags.plist.gz */, 18C577C11F96DB5100C67EB3 /* stackshot-sample-thread-groups-flags */, C9DCEF001F01C3790000BD02 /* stackshot-sample-instrs-cycles */, @@ -279,6 +308,31 @@ path = tests; sourceTree = ""; }; + 0864FCF01FA3C0B7001B7B0B /* kdd.framework */ = { + isa = PBXGroup; + children = ( + 084085AE1FA3D156005BAD16 /* module.modulemap */, + 0864FCF21FA3C0B7001B7B0B /* Info.plist */, + ); + path = kdd.framework; + sourceTree = ""; + }; + 0864FCFB1FA3C0B7001B7B0B /* kdd.frameworkTests */ = { + isa = PBXGroup; + children = ( + 0864FCFC1FA3C0B7001B7B0B /* kdd_frameworkTests.m */, + 0864FCFE1FA3C0B7001B7B0B /* Info.plist */, + ); + path = kdd.frameworkTests; + sourceTree = ""; + }; + 0864FD061FA3C0C8001B7B0B /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; 08DE68351BFFB70900BC682F /* libkdd */ = { isa = PBXGroup; children = ( @@ -291,6 +345,7 @@ 08A4C94A1C47019E00D5F010 /* KCDEmbeddedBufferDescription.h */, 08A4C94B1C4701B800D5F010 /* KCDEmbeddedBufferDescription.m */, C91C93CA1ACB58B700119B60 /* kdd.h */, + 084085AA1FA3CE32005BAD16 /* kdd.h */, C91C93CC1ACB58B700119B60 /* kdd.m */, ); name = libkdd; @@ -313,7 +368,10 @@ 0834719D1BF7D05400D67253 /* kcdata.h */, 08B480871BF92DFB00B4AAE0 /* kcdata.py */, 08603F351BF69EDE007D3784 /* tests */, + 0864FCF01FA3C0B7001B7B0B /* kdd.framework */, + 0864FCFB1FA3C0B7001B7B0B /* kdd.frameworkTests */, C91C93C81ACB58B700119B60 /* Products */, + 0864FD061FA3C0C8001B7B0B /* Frameworks */, ); sourceTree = ""; }; @@ -323,6 +381,7 @@ C91C93C71ACB58B700119B60 /* libkdd.a */, 086395B21BF5655D005ED913 /* kdd */, 08603F341BF69EDE007D3784 /* tests.xctest */, + 0864FCEF1FA3C0B7001B7B0B /* kdd.framework */, ); name = Products; sourceTree = ""; @@ -330,6 +389,15 @@ /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ + 0864FCEC1FA3C0B7001B7B0B /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 084085AC1FA3CE3D005BAD16 /* kdd.h in Headers */, + 0864FD081FA3C127001B7B0B /* kcdata.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; C91C93C51ACB58B700119B60 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -380,6 +448,25 @@ productReference = 086395B21BF5655D005ED913 /* kdd */; productType = "com.apple.product-type.tool"; }; + 0864FCEE1FA3C0B7001B7B0B /* kdd.framework */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0864FD041FA3C0B7001B7B0B /* Build configuration list for PBXNativeTarget "kdd.framework" */; + buildPhases = ( + 084085AD1FA3CE5A005BAD16 /* ShellScript */, + 0864FCEA1FA3C0B7001B7B0B /* Sources */, + 0864FCEB1FA3C0B7001B7B0B /* Frameworks */, + 0864FCEC1FA3C0B7001B7B0B /* Headers */, + 0864FCED1FA3C0B7001B7B0B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = kdd.framework; + productName = kdd.framework; + productReference = 0864FCEF1FA3C0B7001B7B0B /* kdd.framework */; + productType = "com.apple.product-type.framework"; + }; C91C93C61ACB58B700119B60 /* libkdd */ = { isa = PBXNativeTarget; buildConfigurationList = C91C93DA1ACB58B700119B60 /* Build configuration list for PBXNativeTarget "libkdd" */; @@ -414,6 +501,10 @@ 086395B11BF5655D005ED913 = { CreatedOnToolsVersion = 7.3; }; + 0864FCEE1FA3C0B7001B7B0B = { + CreatedOnToolsVersion = 9.1; + ProvisioningStyle = Automatic; + }; C91C93C61ACB58B700119B60 = { CreatedOnToolsVersion = 7.0; }; @@ -434,6 +525,7 @@ C91C93C61ACB58B700119B60 /* libkdd */, 086395B11BF5655D005ED913 /* kdd */, 08603F331BF69EDE007D3784 /* tests */, + 0864FCEE1FA3C0B7001B7B0B /* kdd.framework */, ); }; /* End PBXProject section */ @@ -443,6 +535,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 08F2AC0A1FA136EB00271A11 /* stackshot-sample-delta-thread-policy in Resources */, 18C577C61F96DB7100C67EB3 /* stackshot-sample-thread-groups-flags.plist.gz in Resources */, 18C577C31F96DB5200C67EB3 /* stackshot-sample-thread-groups-flags in Resources */, C9DCEF011F01C3810000BD02 /* stackshot-sample-instrs-cycles in Resources */, @@ -458,6 +551,7 @@ 13D6C5D01C4DDDB6005E617C /* corpse-twr-sample in Resources */, C9D7B5401D1B41D700F1019D /* xnupost_testconfig-sample in Resources */, 081725D51C3F476500371A54 /* stackshot-sample-duration in Resources */, + 08F2AC0B1FA136EB00271A11 /* stackshot-sample-delta-thread-policy.plist.gz in Resources */, 081725D61C3F476500371A54 /* stackshot-sample-duration.plist.gz in Resources */, 081EDD381C23855700A1C138 /* stackshot-sample-cputime in Resources */, 081EDD391C23855700A1C138 /* stackshot-sample-cputime.plist.gz in Resources */, @@ -501,8 +595,33 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 0864FCED1FA3C0B7001B7B0B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 084085AD1FA3CE5A005BAD16 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "$(SRCROOT)/kdd.h", + ); + outputPaths = ( + "$(BUILT_PRODUCTS_DIR)/kdd.h", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "perl -pe 's:kcdata.h:kdd/kcdata.h:' ${SRCROOT}/kdd.h >${SCRIPT_OUTPUT_FILE_0}"; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 08603F301BF69EDE007D3784 /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -520,6 +639,19 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 0864FCEA1FA3C0B7001B7B0B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0864FD0A1FA3C2A9001B7B0B /* kcdtypes.c in Sources */, + 0864FD0B1FA3C2A9001B7B0B /* kcdata_core.m in Sources */, + 0864FD0D1FA3C2A9001B7B0B /* KCDBasicTypeDescription.m in Sources */, + 0864FD0F1FA3C2A9001B7B0B /* KCDStructTypeDescription.m in Sources */, + 0864FD111FA3C2A9001B7B0B /* KCDEmbeddedBufferDescription.m in Sources */, + 0864FD131FA3C2A9001B7B0B /* kdd.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; C91C93C31ACB58B700119B60 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -606,6 +738,92 @@ }; name = Release; }; + 0864FD001FA3C0B7001B7B0B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = kdd.framework/Info.plist; + INSTALLHDRS_SCRIPT_PHASE = YES; + INSTALL_PATH = /AppleInternal/Ariadne/Frameworks/; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.13; + MODULEMAP_FILE = "$(SRCROOT)/kdd.framework/module.modulemap"; + PRODUCT_BUNDLE_IDENTIFIER = "test.kdd-framework"; + PRODUCT_NAME = kdd; + SDKROOT = macosx.internal; + SKIP_INSTALL = NO; + SUPPORTS_TEXT_BASED_API = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 0864FD011FA3C0B7001B7B0B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "-"; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_VERSION = A; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = kdd.framework/Info.plist; + INSTALLHDRS_SCRIPT_PHASE = YES; + INSTALL_PATH = /AppleInternal/Ariadne/Frameworks/; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.13; + MODULEMAP_FILE = "$(SRCROOT)/kdd.framework/module.modulemap"; + PRODUCT_BUNDLE_IDENTIFIER = "test.kdd-framework"; + PRODUCT_NAME = kdd; + SDKROOT = macosx.internal; + SKIP_INSTALL = NO; + SUPPORTS_TEXT_BASED_API = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; C91C93D81ACB58B700119B60 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -727,6 +945,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 0864FD041FA3C0B7001B7B0B /* Build configuration list for PBXNativeTarget "kdd.framework" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0864FD001FA3C0B7001B7B0B /* Debug */, + 0864FD011FA3C0B7001B7B0B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; C91C93C21ACB58B700119B60 /* Build configuration list for PBXProject "kdd" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/libkdd/tests/Tests.swift b/libkdd/tests/Tests.swift index 0886e0251..7a8a6ffee 100644 --- a/libkdd/tests/Tests.swift +++ b/libkdd/tests/Tests.swift @@ -1370,6 +1370,10 @@ class Tests: XCTestCase { self.testSampleStackshot("stackshot-sample-thread-policy") } + func testDeltaStackshotWithThreadPolicy() { + self.testSampleStackshot("stackshot-sample-delta-thread-policy") + } + func testStackshotWithInstrsCycles() { self.testSampleStackshot("stackshot-sample-instrs-cycles") } diff --git a/libkdd/tests/stackshot-sample-delta-thread-policy b/libkdd/tests/stackshot-sample-delta-thread-policy new file mode 100644 index 0000000000000000000000000000000000000000..a34c83b0b43dc993f956fb9e8eb98de59078c829 GIT binary patch literal 832 zcmbQWRQw(T5Hx@YAYcMw10e1Jae$z>Br!R=I3vF#J~J;qEhjO(7$OcMxfNJpOfZdC ze?evnieey#5lw&@$OqZq0TnN)u zNG#%Q#UZfUFZ_k7Lk literal 0 HcmV?d00001 diff --git a/libkdd/tests/stackshot-sample-delta-thread-policy.plist.gz b/libkdd/tests/stackshot-sample-delta-thread-policy.plist.gz new file mode 100644 index 0000000000000000000000000000000000000000..c372cbb6c36aaa1be426df9b2b3f5ce09f079890 GIT binary patch literal 912 zcmV;B18@8viwFqi)V{?O5Axn?MkKcD};pJ?6SxD&nY3QYli@TB`HVC$xdJSs4S_UE;c5-yyz% zVX2+8O)L4qaRhVD%+Ac2G5D9?=SlyGFix}dLeU4B(kE${MKqmWDEH$}=dN-&JoDdO zf4Lfe8{PEtgmTdz-G98hz3MCHs`??%6QZiuz(GV3_{#+j zXFSe?ua@_~WNo^#o#QYL@B`11LXbevIoa6te3}X}C2Xi$u4d~9*}8*}uWl}HD7GFp z9%&k`sNl{#m+)yCd_2SLvTi$$W9afj=XgqJ+V0$OT`7+9y+){K*)m-Dp?Se`l15Og zA{9p-d)6Do>$pnl6&Vi}(F>7VA;3%f?ezE->Hruq2%Qy7=n8>S9K4)S)}f7~b+$M7Rs%0dq(QqZy-O zSq-ByYZ`gk!O3JoLP4K^BTHx~VQ?)3xiC6t_Ec5Lq#Q&uC<$ThxJF-AmCOZ*G9m#h z(iA@=dwZ^41lO``$FelXbTkhk9TuOQni1$PUUo)TI&@RloQ`a;mt>;^1sVJdU@&No z&Iu1=2)Z#Rj=;XWhuQ|zVUEi!CrPm!wH8f%22>(NjZwP8K4k?QmIcqVoK6n!zN&Oz zp+x7kO4K#v7)Enj93sVzzW;xvXq&Fp5ujX(U9SIaDRwkbw-hbSYwXrPtVYK$J7(Tn z%ki`rPmA%*7UP?!(duw{QsYUDCpG>}HQF6D{w-?s)!h^1?t10Fk`W$`L%x2?NAfI; mTV8V^&GnFHTaImbo>6&wc`WWTSX!6#xJkytS+V literal 0 HcmV?d00001 diff --git a/libkern/c++/OSMetaClass.cpp b/libkern/c++/OSMetaClass.cpp index 3d7c2f6e4..71b316c8c 100644 --- a/libkern/c++/OSMetaClass.cpp +++ b/libkern/c++/OSMetaClass.cpp @@ -466,7 +466,7 @@ OSMetaClass::~OSMetaClass() if (myKext) { sAllClassesDict->removeObject(className); } else { - sAllClassesDict->removeObject((char *)className); + sAllClassesDict->removeObject((const char *)className); } } IOLockUnlock(sAllClassesLock); diff --git a/libkern/c++/OSSerializeBinary.cpp b/libkern/c++/OSSerializeBinary.cpp index 08cf1654c..ffaef6a68 100644 --- a/libkern/c++/OSSerializeBinary.cpp +++ b/libkern/c++/OSSerializeBinary.cpp @@ -411,7 +411,7 @@ OSUnserializeBinary(const char *buffer, size_t bufferSize, OSString **errorStrin sym = OSDynamicCast(OSSymbol, sym); if (!sym && (str = OSDynamicCast(OSString, str))) { - sym = (OSSymbol *) OSSymbol::withString(str); + sym = const_cast(OSSymbol::withString(str)); ok = (sym != 0); if (!ok) break; } diff --git a/libkern/c++/OSString.cpp b/libkern/c++/OSString.cpp index 835e5f25e..346f7ffc1 100644 --- a/libkern/c++/OSString.cpp +++ b/libkern/c++/OSString.cpp @@ -280,7 +280,7 @@ bool OSString::isEqualTo(const OSData *obj) const return false; unsigned int dataLen = obj->getLength ();; - char * dataPtr = (char *) obj->getBytesNoCopy (); + const char * dataPtr = (const char *) obj->getBytesNoCopy (); if (dataLen != length) { diff --git a/libkern/c++/OSUnserializeXML.cpp b/libkern/c++/OSUnserializeXML.cpp index e44bee927..60f1bb238 100644 --- a/libkern/c++/OSUnserializeXML.cpp +++ b/libkern/c++/OSUnserializeXML.cpp @@ -2774,7 +2774,7 @@ buildSymbol(parser_state_t *state, object_t *o) { OSSymbol *symbol; - symbol = (OSSymbol *)OSSymbol::withCString(o->string); + symbol = const_cast(OSSymbol::withCString(o->string)); if (o->idref >= 0) rememberObject(state, o->idref, symbol); free(o->string); diff --git a/libkern/c++/OSUnserializeXML.y b/libkern/c++/OSUnserializeXML.y index 23e64137c..5bd216770 100644 --- a/libkern/c++/OSUnserializeXML.y +++ b/libkern/c++/OSUnserializeXML.y @@ -1158,7 +1158,7 @@ buildSymbol(parser_state_t *state, object_t *o) { OSSymbol *symbol; - symbol = (OSSymbol *)OSSymbol::withCString(o->string); + symbol = const_cast(OSSymbol::withCString(o->string)); if (o->idref >= 0) rememberObject(state, o->idref, symbol); free(o->string); diff --git a/libkern/conf/Makefile.template b/libkern/conf/Makefile.template index 5291268bc..c448bb853 100644 --- a/libkern/conf/Makefile.template +++ b/libkern/conf/Makefile.template @@ -21,7 +21,7 @@ SFLAGS+= -include meta_features.h # Objects that don't want -Wcast-align warning (8474835) OSKextLib.cpo_CXXWARNFLAGS_ADD = -Wno-cast-align -OSKext.cpo_CXXWARNFLAGS_ADD = -Wno-cast-align +OSKext.cpo_CXXWARNFLAGS_ADD = -Wno-cast-align -Wno-cast-qual OSMetaClass.cpo_CXXWARNFLAGS_ADD = -Wno-cast-align OSRuntime.cpo_CXXWARNFLAGS_ADD += -Wno-missing-prototypes OSUnserialize.cpo_CXXWARNFLAGS_ADD = -Wno-cast-align -Wno-unreachable-code-break diff --git a/libkern/crypto/corecrypto_rand.c b/libkern/crypto/corecrypto_rand.c index 332b48d7d..115f2d082 100644 --- a/libkern/crypto/corecrypto_rand.c +++ b/libkern/crypto/corecrypto_rand.c @@ -45,3 +45,8 @@ cc_rand_generate(void *out, size_t outlen) return error; } + +int random_buf(void *buf, size_t buflen) +{ + return cc_rand_generate(buf, buflen); +} diff --git a/libkern/crypto/corecrypto_sha2.c b/libkern/crypto/corecrypto_sha2.c index 786a895b2..78975d48b 100644 --- a/libkern/crypto/corecrypto_sha2.c +++ b/libkern/crypto/corecrypto_sha2.c @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -120,22 +121,17 @@ void SHA512_Final(void *digest, SHA512_CTX *ctx) #else -/* As these are part of the KPI, we need to stub them out for any kernle cofiguration that does not support SHA2. */ - -void SHA384_Init(__unused SHA384_CTX *ctx) -{ - panic("SHA384_Init"); -} - -void SHA384_Update(__unused SHA384_CTX *ctx, __unused const void *data, __unused size_t len) -{ - panic("SHA384_Update"); -} - -void SHA384_Final(__unused void *digest, __unused SHA384_CTX *ctx) -{ - panic("SHA384_Final"); -} +/* As these are part of the KPI, we need to stub them out for any kernel configuration that does not support SHA2. */ + +void UNSUPPORTED_API(SHA256_Init, SHA256_CTX *ctx); +void UNSUPPORTED_API(SHA384_Init, SHA384_CTX *ctx); +void UNSUPPORTED_API(SHA512_Init, SHA512_CTX *ctx); +void UNSUPPORTED_API(SHA256_Update, SHA256_CTX *ctx, const void *data, size_t len); +void UNSUPPORTED_API(SHA384_Update, SHA384_CTX *ctx, const void *data, size_t len); +void UNSUPPORTED_API(SHA512_Update, SHA512_CTX *ctx, const void *data, size_t len); +void UNSUPPORTED_API(SHA256_Final, void *digest, SHA256_CTX *ctx); +void UNSUPPORTED_API(SHA384_Final, void *digest, SHA384_CTX *ctx); +void UNSUPPORTED_API(SHA512_Final, void *digest, SHA512_CTX *ctx); #endif diff --git a/libkern/crypto/register_crypto.c b/libkern/crypto/register_crypto.c index 4f08156f7..51d399a82 100644 --- a/libkern/crypto/register_crypto.c +++ b/libkern/crypto/register_crypto.c @@ -26,11 +26,12 @@ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ - +#include #include #include +#include -crypto_functions_t g_crypto_funcs = NULL; +SECURITY_READ_ONLY_LATE(crypto_functions_t) g_crypto_funcs = NULL; int register_crypto_functions(const crypto_functions_t funcs) { diff --git a/libkern/libkern/c++/OSKext.h b/libkern/libkern/c++/OSKext.h index 581c07b54..2930a5fc7 100644 --- a/libkern/libkern/c++/OSKext.h +++ b/libkern/libkern/c++/OSKext.h @@ -86,7 +86,6 @@ void OSKextVLog( #ifdef XNU_KERNEL_PRIVATE void OSKextRemoveKextBootstrap(void); -void IOSystemShutdownNotification(void); kern_return_t OSRuntimeInitializeCPP( kmod_info_t * kmodInfo, @@ -183,7 +182,6 @@ class OSKext : public OSObject va_list srcArgList); friend void OSKextRemoveKextBootstrap(void); - friend void IOSystemShutdownNotification(void); friend OSReturn OSKextUnloadKextWithLoadTag(uint32_t); friend kern_return_t kext_request( diff --git a/libkern/libkern/c++/OSMetaClass.h b/libkern/libkern/c++/OSMetaClass.h index 322e5238a..6098d6b79 100644 --- a/libkern/libkern/c++/OSMetaClass.h +++ b/libkern/libkern/c++/OSMetaClass.h @@ -114,6 +114,12 @@ class OSCollection; #define APPLE_KEXT_COMPATIBILITY_OVERRIDE #endif +#define APPLE_KEXT_WSHADOW_PUSH _Pragma("clang diagnostic push"); \ + _Pragma("clang diagnostic ignored \"-Wunknown-warning-option\"") \ + _Pragma("clang diagnostic ignored \"-Wshadow-field\"") + +#define APPLE_KEXT_WSHADOW_POP _Pragma("clang diagnostic pop") + /*! * @class OSMetaClassBase @@ -1677,7 +1683,7 @@ class OSMetaClass : private OSMetaClassBase virtual const OSMetaClass * getMetaClass() const APPLE_KEXT_OVERRIDE; \ protected: \ className (const OSMetaClass *); \ - virtual ~ className () + virtual ~ className () APPLE_KEXT_OVERRIDE /*! diff --git a/libkern/libkern/crypto/Makefile b/libkern/libkern/crypto/Makefile index 0fdcb6258..f5544e8cf 100644 --- a/libkern/libkern/crypto/Makefile +++ b/libkern/libkern/crypto/Makefile @@ -6,9 +6,9 @@ export MakeInc_dir=${SRCROOT}/makedefs/MakeInc.dir include $(MakeInc_cmd) include $(MakeInc_def) -DATAFILES = md5.h sha1.h +DATAFILES = md5.h rand.h sha1.h -PRIVATE_DATAFILES = register_crypto.h sha2.h des.h aes.h aesxts.h rand.h rsa.h chacha20poly1305.h +PRIVATE_DATAFILES = register_crypto.h sha2.h des.h aes.h aesxts.h rsa.h chacha20poly1305.h INSTALL_KF_MI_LIST = ${DATAFILES} diff --git a/libkern/libkern/crypto/rand.h b/libkern/libkern/crypto/rand.h index 08778f4cd..8d99cf7b9 100644 --- a/libkern/libkern/crypto/rand.h +++ b/libkern/libkern/crypto/rand.h @@ -29,15 +29,16 @@ #ifndef _RAND_H #define _RAND_H -#if defined(__cplusplus) -extern "C" -{ -#endif +#include + +__BEGIN_DECLS +#if XNU_KERNEL_PRIVATE int cc_rand_generate(void *out, size_t outlen); +#endif /* XNU_KERNEL_PRIVATE */ -#if defined(__cplusplus) -} -#endif +int random_buf(void *buf, size_t buflen); + +__END_DECLS #endif diff --git a/libkern/libkern/kext_panic_report.h b/libkern/libkern/kext_panic_report.h index 1eb4f384f..5aa4cdea6 100644 --- a/libkern/libkern/kext_panic_report.h +++ b/libkern/libkern/kext_panic_report.h @@ -70,10 +70,6 @@ subs_entry_t kext_identifier_substring_subs[] = { { "Controller", 'C' }, { "Bluetooth", 'B' }, { "Intel", 'I' }, - - // CHUD kexts, typically not on user installs - { "Profile", 'P' }, - { "Action", 'a' }, // maybe K if we want to stick to all-caps { (char *)0, '\0' } }; diff --git a/libsa/bootstrap.cpp b/libsa/bootstrap.cpp index 80a7508f3..a73df0946 100644 --- a/libsa/bootstrap.cpp +++ b/libsa/bootstrap.cpp @@ -384,7 +384,7 @@ KLDBootstrap::readPrelinkedExtensions( panic("kernelcacheUUID length is %d, expected %lu", kernelcacheUUID->getLength(), sizeof(kernelcache_uuid)); } else { - memcpy((void *)&kernelcache_uuid, (void *)kernelcacheUUID->getBytesNoCopy(), kernelcacheUUID->getLength()); + memcpy((void *)&kernelcache_uuid, (const void *)kernelcacheUUID->getBytesNoCopy(), kernelcacheUUID->getLength()); } #endif /* CONFIG_EMBEDDED */ @@ -481,8 +481,8 @@ KLDBootstrap::readPrelinkedExtensions( int badSlideAddr = 0; int badSlideTarget = 0; - kaslrPackedOffsets * myOffsets = NULL; - myOffsets = (kaslrPackedOffsets *) kaslrOffsets->getBytesNoCopy(); + const kaslrPackedOffsets * myOffsets = NULL; + myOffsets = (const kaslrPackedOffsets *) kaslrOffsets->getBytesNoCopy(); for (uint32_t j = 0; j < myOffsets->count; j++) { diff --git a/libsyscall/wrappers/libproc/libproc.c b/libsyscall/wrappers/libproc/libproc.c index 255664d9c..39958a1a5 100644 --- a/libsyscall/wrappers/libproc/libproc.c +++ b/libsyscall/wrappers/libproc/libproc.c @@ -182,6 +182,12 @@ proc_piddynkqueueinfo(int pid, int flavor, kqueue_id_t kq_id, void *buffer, int return ret; } +int +proc_udata_info(int pid, int flavor, void *buffer, int buffersize) +{ + return (__proc_info(PROC_INFO_CALL_UDATA_INFO, pid, flavor, 0, buffer, buffersize)); +} + int proc_name(int pid, void * buffer, uint32_t buffersize) { @@ -218,7 +224,7 @@ proc_regionfilename(int pid, uint64_t address, void * buffer, uint32_t buffersiz return(0); } - retval = proc_pidinfo(pid, PROC_PIDREGIONPATHINFO, (uint64_t)address, ®info, sizeof(struct proc_regionwithpathinfo)); + retval = proc_pidinfo(pid, PROC_PIDREGIONPATHINFO2, (uint64_t)address, ®info, sizeof(struct proc_regionwithpathinfo)); if (retval != -1) { return ((int)(strlcpy(buffer, reginfo.prp_vip.vip_path, MAXPATHLEN))); } diff --git a/libsyscall/wrappers/libproc/libproc.h b/libsyscall/wrappers/libproc/libproc.h index ccf413fc3..61b69d9b6 100644 --- a/libsyscall/wrappers/libproc/libproc.h +++ b/libsyscall/wrappers/libproc/libproc.h @@ -145,6 +145,8 @@ int proc_piddynkqueueinfo(int pid, int flavor, kqueue_id_t kq_id, void *buffer, int buffersize); #endif /* PRIVATE */ +int proc_udata_info(int pid, int flavor, void *buffer, int buffersize); + __END_DECLS #endif /*_LIBPROC_H_ */ diff --git a/libsyscall/wrappers/work_interval.c b/libsyscall/wrappers/work_interval.c index 96ca9ef83..32b43da06 100644 --- a/libsyscall/wrappers/work_interval.c +++ b/libsyscall/wrappers/work_interval.c @@ -30,6 +30,7 @@ #include #include +#include struct work_interval { uint64_t thread_id; @@ -113,6 +114,7 @@ work_interval_notify_simple(work_interval_t interval_handle, uint64_t start, deadline, next_start, 0); } + int work_interval_destroy(work_interval_t interval_handle) { diff --git a/makedefs/MakeInc.def b/makedefs/MakeInc.def index 8c49bd74b..dcba4ab78 100644 --- a/makedefs/MakeInc.def +++ b/makedefs/MakeInc.def @@ -103,18 +103,8 @@ endif # Shared C/C++ warning flags WARNFLAGS_STD := \ -Weverything \ - -Wextra \ + -Wno-pedantic \ $(WERROR) \ - -Wpointer-arith \ - -Wreturn-type \ - -Wcast-qual \ - -Wwrite-strings \ - -Wswitch \ - -Wcast-align \ - -Wchar-subscripts \ - -Wredundant-decls \ - -Wextra-tokens \ - -Wunreachable-code \ -Wno-assign-enum \ -Wno-bad-function-cast \ -Wno-c++98-compat \ @@ -141,7 +131,6 @@ WARNFLAGS_STD := \ -Wno-packed \ -Wno-padded \ -Wno-partial-availability \ - -Wno-pedantic \ -Wno-shift-sign-overflow \ -Wno-switch-enum \ -Wno-undef \ @@ -151,13 +140,13 @@ WARNFLAGS_STD := \ -Wno-vla \ -Wno-zero-length-array +WARNFLAGS_STD := $(WARNFLAGS_STD) \ + -Wno-unknown-warning-option \ + -Wno-error=shadow-field \ + -Wno-error=cast-qual + CWARNFLAGS_STD = \ - $(WARNFLAGS_STD) \ - -Wstrict-prototypes \ - -Wmissing-prototypes \ - -Wshadow \ - -Winline \ - -Wnested-externs + $(WARNFLAGS_STD) # Can be overridden in Makefile.template or Makefile.$arch export CWARNFLAGS ?= $(CWARNFLAGS_STD) @@ -171,10 +160,8 @@ CXXWARNFLAGS_STD = \ -Wno-c++98-compat-pedantic \ -Wno-exit-time-destructors \ -Wno-global-constructors \ - -Wno-old-style-cast - -# overloaded-virtual warnings are non-fatal (9000888) -CXXWARNFLAGS_STD += -Wno-error=overloaded-virtual + -Wno-old-style-cast \ + -Wno-zero-as-null-pointer-constant # Can be overridden in Makefile.template or Makefile.$arch export CXXWARNFLAGS ?= $(CXXWARNFLAGS_STD) @@ -519,7 +506,7 @@ SUPPORTS_CTFCONVERT = 0 ifeq ($(USE_LTO),1) CFLAGS_GEN += -flto CXXFLAGS_GEN += -flto -LDFLAGS_KERNEL_GEN += -Wl,-mllvm,-inline-threshold=125 -Wl,-object_path_lto,$(TARGET)/lto.o # -Wl,-mllvm -Wl,-disable-fp-elim +LDFLAGS_KERNEL_GEN += -Wl,-mllvm,-inline-threshold=100 -Wl,-object_path_lto,$(TARGET)/lto.o LDFLAGS_NOSTRIP_FLAG = -rdynamic CFLAGS_NOLTO_FLAG = -fno-lto NEEDS_CTF_MACHOS = 1 diff --git a/makedefs/MakeInc.top b/makedefs/MakeInc.top index c552c108a..76fd8500a 100644 --- a/makedefs/MakeInc.top +++ b/makedefs/MakeInc.top @@ -545,7 +545,6 @@ CLEAN_RM_DIRS= $(OBJROOT) $(SYMROOT) $(DSTROOT) \ CLEAN_ACTION_DIRS= $(SRCROOT)/tools/tests/MPMMTest \ $(SRCROOT)/tools/tests/TLBcoherency \ $(SRCROOT)/tools/tests/kqueue_tests \ - $(SRCROOT)/tools/tests/libMicro \ $(SRCROOT)/tools/tests/mktimer \ $(SRCROOT)/tools/tests/zero-to-n \ $(SRCROOT)/tools/tests/personas diff --git a/osfmk/arm/cpu_common.c b/osfmk/arm/cpu_common.c index ac41435d4..2b9b0a261 100644 --- a/osfmk/arm/cpu_common.c +++ b/osfmk/arm/cpu_common.c @@ -54,8 +54,6 @@ #include #include #include -#include -#include #if KPERF void kperf_signal_handler(unsigned int cpu_number); @@ -406,10 +404,6 @@ cpu_signal_handler_internal(boolean_t disable_signal) (void)hw_atomic_and(&cpu_data_ptr->cpu_signal, ~SIGPdec); rtclock_intr(FALSE); } - if (cpu_signal & SIGPchud) { - (void)hw_atomic_and(&cpu_data_ptr->cpu_signal, ~SIGPchud); - chudxnu_cpu_signal_handler(); - } #if KPERF if (cpu_signal & SIGPkptimer) { (void)hw_atomic_and(&cpu_data_ptr->cpu_signal, ~SIGPkptimer); diff --git a/osfmk/arm/cpu_data_internal.h b/osfmk/arm/cpu_data_internal.h index ecef9f939..e660c1e36 100644 --- a/osfmk/arm/cpu_data_internal.h +++ b/osfmk/arm/cpu_data_internal.h @@ -76,6 +76,7 @@ extern reset_handler_data_t ResetHandlerData; #define CPUWINDOWS_BASE_MASK 0xFFFFFFFFFFF00000UL #define CPUWINDOWS_BASE (VM_MAX_KERNEL_ADDRESS & CPUWINDOWS_BASE_MASK) #endif +#define CPUWINDOWS_TOP (CPUWINDOWS_BASE + (MAX_CPUS * CPUWINDOWS_MAX * PAGE_SIZE)) typedef struct cpu_data_entry { void *cpu_data_paddr; /* Cpu data physical address */ @@ -182,7 +183,6 @@ typedef struct cpu_data void *cpu_tbd_hardware_val; void *cpu_console_buf; - void *cpu_chud; void *cpu_idle_notify; uint64_t cpu_idle_latency; diff --git a/osfmk/arm/cpu_internal.h b/osfmk/arm/cpu_internal.h index 227863b4c..c7c846d75 100644 --- a/osfmk/arm/cpu_internal.h +++ b/osfmk/arm/cpu_internal.h @@ -57,7 +57,7 @@ extern void cpu_signal_cancel( #define SIGPnop 0x00000000U /* Send IPI with no service */ #define SIGPdec 0x00000001U /* Request decremeter service */ -#define SIGPchud 0x00000002U /* CHUD CPU Signal request types */ +/* 0x2U unused */ #define SIGPxcall 0x00000004U /* Call a function on a processor */ #define SIGPast 0x00000008U /* Request AST check */ #define SIGPdebug 0x00000010U /* Request Debug call */ @@ -67,12 +67,6 @@ extern void cpu_signal_cancel( #define SIGPdisabled 0x80000000U /* Signal disabled */ -extern void * chudxnu_cpu_alloc( - boolean_t boot_processor); - -extern void chudxnu_cpu_free( - void *per_proc_chud); - extern unsigned int real_ncpus; diff --git a/osfmk/arm/locore.s b/osfmk/arm/locore.s index 5af8c2a79..233166b55 100644 --- a/osfmk/arm/locore.s +++ b/osfmk/arm/locore.s @@ -244,22 +244,99 @@ LEXT(fleh_reset) .align 2 .globl EXT(fleh_undef) -LEXT(fleh_undef) - mrs sp, spsr // Check the previous mode +/* + * Ensures the stack is safely aligned, usually in preparation for an external branch + * arg0: temp register for storing the stack offset + * arg1: temp register for storing the previous stack pointer + */ +.macro ALIGN_STACK +/* + * For armv7k ABI, the stack needs to be 16-byte aligned + */ +#if __BIGGEST_ALIGNMENT__ > 4 + and $0, sp, #0x0F // sp mod 16-bytes + cmp $0, #4 // need space for the sp on the stack + addlt $0, $0, #0x10 // make room if needed, but keep stack aligned + mov $1, sp // get current sp + sub sp, sp, $0 // align stack + str $1, [sp] // store previous sp on stack +#endif +.endmacro + +/* + * Restores the stack pointer to its previous value following an ALIGN_STACK call + */ +.macro UNALIGN_STACK +#if __BIGGEST_ALIGNMENT__ > 4 + ldr sp, [sp] +#endif +.endmacro + +/* + * Checks that cpu is currently in the expected mode, panics if not. + * arg0: the expected mode, should be one of the PSR_*_MODE defines + */ +.macro VERIFY_EXCEPTION_MODE + mrs sp, cpsr // Read cpsr + and sp, sp, #PSR_MODE_MASK // Extract current mode + cmp sp, $0 // Check specified mode + movne r0, sp + bne EXT(ExceptionVectorPanic) +.endmacro + +/* + * Checks previous processor mode. If usermode, will execute the code + * following the macro to handle the userspace exception. Otherwise, + * will branch to a ELSE_IF_KERNELMODE_EXCEPTION call with the same + * argument. + * arg0: arbitrary string indicating the exception class, e.g. 'dataabt' + */ +.macro IF_USERMODE_EXCEPTION + mrs sp, spsr + and sp, sp, #PSR_MODE_MASK // Is it from user? + cmp sp, #PSR_USER_MODE + beq $0_from_user + cmp sp, #PSR_IRQ_MODE + beq $0_from_irq + cmp sp, #PSR_FIQ_MODE + beq $0_from_fiq + bne $0_from_svc +$0_from_user: +.endmacro + +/* + * Handles an exception taken from kernelmode (IRQ/FIQ/SVC/etc). + * Places the processor into the correct mode and executes the + * code following the macro to handle the kernel exception. + * Intended to be paired with a prior call to IF_USERMODE_EXCEPTION. + * arg0: arbitrary string indicating the exception class, e.g. 'dataabt' + */ +.macro ELSE_IF_KERNELMODE_EXCEPTION +$0_from_irq: + cpsid i, #PSR_IRQ_MODE + b $0_from_kernel +$0_from_fiq: + cpsid i, #PSR_FIQ_MODE + b $0_from_kernel +$0_from_svc: + cpsid i, #PSR_SVC_MODE +$0_from_kernel: +.endmacro + +LEXT(fleh_undef) +VERIFY_EXCEPTION_MODE PSR_UND_MODE + mrs sp, spsr // For check the previous mode tst sp, #PSR_TF // Is it Thumb? subeq lr, lr, #4 subne lr, lr, #2 - tst sp, #0x0f // Is it from user? - bne undef_from_kernel - -undef_from_user: +IF_USERMODE_EXCEPTION undef mrc p15, 0, sp, c13, c0, 4 // Read TPIDRPRW add sp, sp, ACT_PCBDATA // Get current thread PCB pointer stmia sp, {r0-r12, sp, lr}^ // Save user context on PCB mov r7, #0 // Zero the frame pointer nop - + mov r0, sp // Store arm_saved_state pointer // for argument @@ -268,7 +345,6 @@ undef_from_user: mrs r4, spsr str r4, [sp, SS_CPSR] // Save user mode cpsr - mrs r4, cpsr // Read cpsr cpsid i, #PSR_SVC_MODE mrs r3, cpsr // Read cpsr msr spsr_cxsf, r3 // Set spsr(svc mode cpsr) @@ -281,9 +357,6 @@ undef_from_user: mcr p15, 0, r3, c13, c0, 1 // Set CONTEXTIDR isb #endif - and r0, r4, #PSR_MODE_MASK // Extract current mode - cmp r0, #PSR_UND_MODE // Check undef mode - bne EXT(ExceptionVectorPanic) mvn r0, #0 str r0, [r9, TH_IOTIER_OVERRIDE] // Reset IO tier override to -1 before handling abort from userspace @@ -309,36 +382,11 @@ undef_from_user: // sleh will enable interrupt b load_and_go_user -undef_from_kernel: - mrs sp, cpsr // Read cpsr - and sp, sp, #PSR_MODE_MASK // Extract current mode - cmp sp, #PSR_UND_MODE // Check undef mode - movne r0, sp - bne EXT(ExceptionVectorPanic) - mrs sp, spsr // Check the previous mode - +ELSE_IF_KERNELMODE_EXCEPTION undef /* * We have a kernel stack already, and I will use it to save contexts * IRQ is disabled */ - -#if CONFIG_DTRACE - /* - * See if we came here from IRQ or SVC mode, and go back to that mode - */ - - and sp, sp, #PSR_MODE_MASK - cmp sp, #PSR_IRQ_MODE - bne undef_from_kernel_svc - - cpsid i, #PSR_IRQ_MODE - b handle_undef -#endif - -undef_from_kernel_svc: - cpsid i, #PSR_SVC_MODE - -handle_undef: #if CONFIG_DTRACE // We need a frame for backtracing. The LR here is the LR of supervisor mode, not the location where the exception // took place. We'll store that later after we switch to undef mode and pull out the LR from there. @@ -356,31 +404,13 @@ handle_undef: #if CONFIG_DTRACE add r7, sp, EXC_CTX_SIZE // Save frame pointer #endif - - mov ip, sp // Stack transfer - - cpsid i, #PSR_UND_MODE - - str lr, [ip, SS_PC] // Save complete - mrs r4, spsr - str r4, [ip, SS_CPSR] - -#if CONFIG_DTRACE - /* - * Go back to previous mode for mode specific regs - */ - and r4, r4, #PSR_MODE_MASK - cmp r4, #PSR_IRQ_MODE - bne handle_undef_from_svc - - cpsid i, #PSR_IRQ_MODE - b handle_undef2 -#endif -handle_undef_from_svc: - cpsid i, #PSR_SVC_MODE + mrs r4, lr_und + str r4, [sp, SS_PC] // Save complete + mrs r4, spsr_und + str r4, [sp, SS_CPSR] -handle_undef2: + mov ip, sp /* sp - stack pointer @@ -431,23 +461,9 @@ handle_undef2: #endif mov r0, sp // Argument -/* - * For armv7k ABI, the stack needs to be 16-byte aligned - */ -#if __BIGGEST_ALIGNMENT__ > 4 - and r1, sp, #0x0F // sp mod 16-bytes - cmp r1, #4 // need space for the sp on the stack - addlt r1, r1, #0x10 // make room if needed, but keep stack aligned - mov r2, sp // get current sp - sub sp, sp, r1 // align stack - str r2, [sp] // store previous sp on stack -#endif - + ALIGN_STACK r2, r3 bl EXT(sleh_undef) // Call second level handler - -#if __BIGGEST_ALIGNMENT__ > 4 - ldr sp, [sp] // restore stack -#endif + UNALIGN_STACK #if __ARM_USER_PROTECT__ mrc p15, 0, r9, c13, c0, 4 // Read TPIDRPRW @@ -500,6 +516,7 @@ swi_from_kernel: str r0, [sp, SS_SP] // Save supervisor mode sp str lr, [sp, SS_LR] // Save supervisor mode lr + ALIGN_STACK r0, r1 adr r0, L_kernel_swi_panic_str // Load panic messages and panic() blx EXT(panic) b . @@ -785,6 +802,7 @@ cache_trap_error: mov r1, sp str r2, [sp] str r3, [sp, #4] + ALIGN_STACK r2, r3 mov r2, #2 bl EXT(exception_triage) b . @@ -817,13 +835,10 @@ L_kernel_swi_panic_str: .globl EXT(fleh_prefabt) LEXT(fleh_prefabt) +VERIFY_EXCEPTION_MODE PSR_ABT_MODE sub lr, lr, #4 - - mrs sp, spsr // For check the previous mode - tst sp, #0x0f // Is it from user? - bne prefabt_from_kernel -prefabt_from_user: +IF_USERMODE_EXCEPTION prefabt mrc p15, 0, sp, c13, c0, 4 // Read TPIDRPRW add sp, sp, ACT_PCBDATA // Get User PCB @@ -842,7 +857,6 @@ prefabt_from_user: mrs r4, spsr str r4, [sp, SS_CPSR] // Save user mode cpsr - mrs r4, cpsr // Read cpsr cpsid i, #PSR_SVC_MODE mrs r3, cpsr // Read cpsr msr spsr_cxsf, r3 // Set spsr(svc mode cpsr) @@ -862,9 +876,6 @@ prefabt_from_user: mcr p15, 0, r3, c13, c0, 1 // Set CONTEXTIDR isb #endif - and r0, r4, #PSR_MODE_MASK // Extract current mode - cmp r0, #PSR_ABT_MODE // Check abort mode - bne EXT(ExceptionVectorPanic) mvn r0, #0 str r0, [r9, TH_IOTIER_OVERRIDE] // Reset IO tier override to -1 before handling abort from userspace @@ -880,14 +891,7 @@ prefabt_from_user: // Sleh will enable interrupt b load_and_go_user -prefabt_from_kernel: - mrs sp, cpsr // Read cpsr - and sp, sp, #PSR_MODE_MASK // Extract current mode - cmp sp, #PSR_ABT_MODE // Check abort mode - movne r0, sp - bne EXT(ExceptionVectorPanic) - mrs sp, spsr // Check the previous mode - +ELSE_IF_KERNELMODE_EXCEPTION prefabt /* * We have a kernel stack already, and I will use it to save contexts: * ------------------ @@ -898,8 +902,6 @@ prefabt_from_kernel: * * IRQ is disabled */ - cpsid i, #PSR_SVC_MODE - sub sp, sp, EXC_CTX_SIZE stmia sp, {r0-r12} add r0, sp, EXC_CTX_SIZE @@ -929,42 +931,23 @@ prefabt_from_kernel: mcr p15, 0, r3, c13, c0, 1 // Set CONTEXTIDR isb #endif - mov ip, sp - cpsid i, #PSR_ABT_MODE - - str lr, [ip, SS_PC] // Save pc to pc and + mrs r4, lr_abt + str r4, [sp, SS_PC] // Save pc mrc p15, 0, r5, c6, c0, 2 // Read IFAR - str r5, [ip, SS_VADDR] // and fault address of pcb + str r5, [sp, SS_VADDR] // and fault address of pcb mrc p15, 0, r5, c5, c0, 1 // Read (instruction) Fault Status - str r5, [ip, SS_STATUS] // Save fault status register to pcb - - mrs r4, spsr - str r4, [ip, SS_CPSR] - - cpsid i, #PSR_SVC_MODE + str r5, [sp, SS_STATUS] // Save fault status register to pcb - mov r0, sp - -/* - * For armv7k ABI, the stack needs to be 16-byte aligned - */ -#if __BIGGEST_ALIGNMENT__ > 4 - and r1, sp, #0x0F // sp mod 16-bytes - cmp r1, #4 // need space for the sp on the stack - addlt r1, r1, #0x10 // make room if needed, but keep stack aligned - mov r2, sp // get current sp - sub sp, sp, r1 // align stack - str r2, [sp] // store previous sp on stack -#endif + mrs r4, spsr_abt + str r4, [sp, SS_CPSR] + mov r0, sp + ALIGN_STACK r1, r2 mov r1, T_PREFETCH_ABT // Pass abort type bl EXT(sleh_abort) // Call second level handler - -#if __BIGGEST_ALIGNMENT__ > 4 - ldr sp, [sp] // restore stack -#endif + UNALIGN_STACK mrc p15, 0, r9, c13, c0, 4 // Read TPIDRPRW #if __ARM_USER_PROTECT__ @@ -992,13 +975,9 @@ prefabt_from_kernel: .globl EXT(fleh_dataabt) LEXT(fleh_dataabt) +VERIFY_EXCEPTION_MODE PSR_ABT_MODE sub lr, lr, #8 - - mrs sp, spsr // For check the previous mode - tst sp, #0x0f // Is it from kernel? - bne dataabt_from_kernel - -dataabt_from_user: +IF_USERMODE_EXCEPTION dataabt mrc p15, 0, sp, c13, c0, 4 // Read TPIDRPRW add sp, sp, ACT_PCBDATA // Get User PCB @@ -1019,7 +998,6 @@ dataabt_from_user: str r5, [sp, SS_STATUS] // Save fault status register to pcb str r6, [sp, SS_VADDR] // Save fault address to pcb - mrs r4, cpsr // Read cpsr cpsid i, #PSR_SVC_MODE mrs r3, cpsr // Read cpsr msr spsr_cxsf, r3 // Set spsr(svc mode cpsr) @@ -1039,9 +1017,6 @@ dataabt_from_user: mcr p15, 0, r3, c13, c0, 1 // Set CONTEXTIDR isb #endif - and r0, r4, #PSR_MODE_MASK // Extract current mode - cmp r0, #PSR_ABT_MODE // Check abort mode - bne EXT(ExceptionVectorPanic) mvn r0, #0 str r0, [r9, TH_IOTIER_OVERRIDE] // Reset IO tier override to -1 before handling abort from userspace @@ -1057,14 +1032,7 @@ dataabt_from_user: // Sleh will enable irq b load_and_go_user -dataabt_from_kernel: - mrs sp, cpsr // Read cpsr - and sp, sp, #PSR_MODE_MASK // Extract current mode - cmp sp, #PSR_ABT_MODE // Check abort mode - movne r0, sp - bne EXT(ExceptionVectorPanic) - mrs sp, spsr // Check the previous mode - +ELSE_IF_KERNELMODE_EXCEPTION dataabt /* * We have a kernel stack already, and I will use it to save contexts: * ------------------ @@ -1075,8 +1043,6 @@ dataabt_from_kernel: * * IRQ is disabled */ - cpsid i, #PSR_SVC_MODE - sub sp, sp, EXC_CTX_SIZE stmia sp, {r0-r12} add r0, sp, EXC_CTX_SIZE @@ -1095,15 +1061,10 @@ dataabt_from_kernel: fmxr fpscr, r4 // And shove it into FPSCR #endif - mov ip, sp - - cpsid i, #PSR_ABT_MODE - - str lr, [ip, SS_PC] - mrs r4, spsr - str r4, [ip, SS_CPSR] - - cpsid i, #PSR_SVC_MODE + mrs r4, lr_abt + str r4, [sp, SS_PC] + mrs r4, spsr_abt + str r4, [sp, SS_CPSR] #if __ARM_USER_PROTECT__ mrc p15, 0, r10, c2, c0, 0 // Get TTBR0 @@ -1123,25 +1084,10 @@ dataabt_from_kernel: str r6, [sp, SS_VADDR] // Save fault address to pcb mov r0, sp // Argument - -/* - * For armv7k ABI, the stack needs to be 16-byte aligned - */ -#if __BIGGEST_ALIGNMENT__ > 4 - and r1, sp, #0x0F // sp mod 16-bytes - cmp r1, #4 // need space for the sp on the stack - addlt r1, r1, #0x10 // make room if needed, but keep stack aligned - mov r2, sp // get current sp - sub sp, sp, r1 // align stack - str r2, [sp] // store previous sp on stack -#endif - + ALIGN_STACK r1, r2 mov r1, T_DATA_ABT // Pass abort type bl EXT(sleh_abort) // Call second level handler - -#if __BIGGEST_ALIGNMENT__ > 4 - ldr sp, [sp] // restore stack (removed align padding) -#endif + UNALIGN_STACK mrc p15, 0, r9, c13, c0, 4 // Read TPIDRPRW #if __ARM_USER_PROTECT__ @@ -1188,24 +1134,9 @@ load_and_go_sys: ldr lr, [sp, SS_LR] // Restore the link register stmfd sp!, {r7, lr} // Push a fake frame - /* TODO: Should this be setting r7? I think so. */ - mov r7, sp // Set the frame pointer - -#if __BIGGEST_ALIGNMENT__ > 4 - and r2, sp, #0x0F // sp mod 16-bytes - cmp r2, #4 // need space for the sp on the stack - addlt r2, r2, #0x10 // make room if needed, but keep stack aligned - mov r3, sp // get current sp - sub sp, sp, r2 // align stack - str r3, [sp] // store previous sp on stack -#endif - + ALIGN_STACK r2, r3 bl EXT(ast_taken_kernel) // Handle AST_URGENT - -#if __BIGGEST_ALIGNMENT__ > 4 - ldr sp, [sp] -#endif - + UNALIGN_STACK ldmfd sp!, {r7, lr} // Pop the fake frame mrc p15, 0, r9, c13, c0, 4 // Reload r9 from TPIDRPRW @@ -1786,11 +1717,14 @@ LEXT(fleh_dec) mcr p15, 0, r3, c13, c0, 1 // Set CONTEXTIDR isb #endif + + ALIGN_STACK r0, r1 mov r0, r8 // Get current cpu in arg 0 mov r1, SIGPdec // Decrementer signal in arg1 mov r2, #0 mov r3, #0 bl EXT(cpu_signal) // Call cpu_signal + UNALIGN_STACK mrc p15, 0, r9, c13, c0, 4 // Read TPIDRPRW @@ -1818,6 +1752,7 @@ LEXT(fleh_dec) cpsid i, #PSR_IRQ_MODE cpsie f mov sp, r6 // Restore the stack pointer + ALIGN_STACK r2, r3 msr spsr_cxsf, r4 // Restore the spsr ldr r2, [r9, ACT_PREEMPT_CNT] // Load preemption count add r2, r2, #1 // Increment count @@ -1864,6 +1799,7 @@ LEXT(fleh_dec) movs r4, r4 COND_EXTERN_BLNE(interrupt_trace_exit) #endif + UNALIGN_STACK mrc p15, 0, r9, c13, c0, 4 // Reload r9 from TPIDRPRW @@ -1924,21 +1860,8 @@ load_and_go_user: cmp r5, #0 // Test if ASTs pending beq return_to_user_now // Branch if no ASTs -#if __BIGGEST_ALIGNMENT__ > 4 - and r2, sp, #0x0F // sp mod 16-bytes - cmp r2, #4 // need space for the sp on the stack - addlt r2, r2, #0x10 // make room if needed, but keep stack aligned - mov r3, sp // get current sp - sub sp, sp, r2 // align stack - str r3, [sp] // store previous sp on stack -#endif - bl EXT(ast_taken_user) // Handle all ASTs (may continue via thread_exception_return) -#if __BIGGEST_ALIGNMENT__ > 4 - ldr sp, [sp] // Restore the stack pointer -#endif - mrc p15, 0, r9, c13, c0, 4 // Reload r9 from TPIDRPRW b load_and_go_user // Loop back @@ -2028,6 +1951,7 @@ L_evimpanic_str: LEXT(ExceptionVectorPanic) cpsid i, #PSR_SVC_MODE + ALIGN_STACK r1, r2 mov r1, r0 adr r0, L_evimpanic_str blx EXT(panic) diff --git a/osfmk/arm/machine_routines.c b/osfmk/arm/machine_routines.c index bc3e4f8eb..83e607540 100644 --- a/osfmk/arm/machine_routines.c +++ b/osfmk/arm/machine_routines.c @@ -544,9 +544,6 @@ ml_processor_register( this_cpu_datap->cpu_id = in_processor_info->cpu_id; - this_cpu_datap->cpu_chud = chudxnu_cpu_alloc(is_boot_cpu); - if (this_cpu_datap->cpu_chud == (void *)NULL) - goto processor_register_error; this_cpu_datap->cpu_console_buf = console_cpu_alloc(is_boot_cpu); if (this_cpu_datap->cpu_console_buf == (void *)(NULL)) goto processor_register_error; @@ -604,8 +601,6 @@ ml_processor_register( #if KPC kpc_unregister_cpu(this_cpu_datap); #endif - if (this_cpu_datap->cpu_chud != (void *)NULL) - chudxnu_cpu_free(this_cpu_datap->cpu_chud); if (!is_boot_cpu) cpu_data_free(this_cpu_datap); return KERN_FAILURE; diff --git a/osfmk/arm/machine_routines.h b/osfmk/arm/machine_routines.h index 3e46c61e1..cee6477b1 100644 --- a/osfmk/arm/machine_routines.h +++ b/osfmk/arm/machine_routines.h @@ -629,6 +629,26 @@ struct perfcontrol_work_interval { }; typedef struct perfcontrol_work_interval *perfcontrol_work_interval_t; +typedef enum { + WORK_INTERVAL_START, + WORK_INTERVAL_UPDATE, + WORK_INTERVAL_FINISH +} work_interval_ctl_t; + +struct perfcontrol_work_interval_instance { + work_interval_ctl_t ctl; + uint32_t create_flags; + uint64_t complexity; + uint64_t thread_id; + uint64_t work_interval_id; + uint64_t instance_id; /* out: start, in: update/finish */ + uint64_t start; + uint64_t finish; + uint64_t deadline; + uint64_t thread_group_id; + void *thread_group_data; +}; +typedef struct perfcontrol_work_interval_instance *perfcontrol_work_interval_instance_t; /* * Structure to export per-CPU counters as part of the CLPC callout. @@ -727,6 +747,11 @@ typedef void (*sched_perfcontrol_max_runnable_latency_t)(perfcontrol_max_runnabl */ typedef void (*sched_perfcontrol_work_interval_notify_t)(perfcontrol_state_t, perfcontrol_work_interval_t); +/* + * Start, update and finish work interval instance with optional complexity estimate. + */ +typedef void (*sched_perfcontrol_work_interval_ctl_t)(perfcontrol_state_t, perfcontrol_work_interval_instance_t); + /* * These callbacks are used when thread groups are added, removed or properties * updated. @@ -778,7 +803,6 @@ typedef void (*sched_perfcontrol_state_update_t)( perfcontrol_event event, uint32_t cpu_id, uint64_t timestamp, uint32_t flags, struct perfcontrol_thread_data *thr_data, __unused void *unused); - /* * Callers should always use the CURRENT version so that the kernel can detect both older * and newer structure layouts. New callbacks should always be added at the end of the @@ -794,6 +818,7 @@ typedef void (*sched_perfcontrol_state_update_t)( #define SCHED_PERFCONTROL_CALLBACKS_VERSION_4 (4) /* up-to deadline_passed */ #define SCHED_PERFCONTROL_CALLBACKS_VERSION_5 (5) /* up-to state_update */ #define SCHED_PERFCONTROL_CALLBACKS_VERSION_6 (6) /* up-to thread_group_flags_update */ +#define SCHED_PERFCONTROL_CALLBACKS_VERSION_7 (7) /* up-to work_interval_ctl */ #define SCHED_PERFCONTROL_CALLBACKS_VERSION_CURRENT SCHED_PERFCONTROL_CALLBACKS_VERSION_6 struct sched_perfcontrol_callbacks { @@ -809,6 +834,7 @@ struct sched_perfcontrol_callbacks { sched_perfcontrol_csw_t csw; sched_perfcontrol_state_update_t state_update; sched_perfcontrol_thread_group_flags_update_t thread_group_flags_update; + sched_perfcontrol_work_interval_ctl_t work_interval_ctl; }; typedef struct sched_perfcontrol_callbacks *sched_perfcontrol_callbacks_t; diff --git a/osfmk/arm/machine_routines_common.c b/osfmk/arm/machine_routines_common.c index 764fb97e0..9afa6a74f 100644 --- a/osfmk/arm/machine_routines_common.c +++ b/osfmk/arm/machine_routines_common.c @@ -81,7 +81,14 @@ sched_perfcontrol_max_runnable_latency_default(perfcontrol_max_runnable_latency_ } static void -sched_perfcontrol_work_interval_notify_default(perfcontrol_state_t thread_state __unused, perfcontrol_work_interval_t work_interval __unused) +sched_perfcontrol_work_interval_notify_default(perfcontrol_state_t thread_state __unused, + perfcontrol_work_interval_t work_interval __unused) +{ +} + +static void +sched_perfcontrol_work_interval_ctl_default(perfcontrol_state_t thread_state __unused, + perfcontrol_work_interval_instance_t instance __unused) { } @@ -115,6 +122,7 @@ sched_perfcontrol_thread_group_deinit_t sched_perfcontrol_thread_group_d sched_perfcontrol_thread_group_flags_update_t sched_perfcontrol_thread_group_flags_update = sched_perfcontrol_thread_group_default; sched_perfcontrol_max_runnable_latency_t sched_perfcontrol_max_runnable_latency = sched_perfcontrol_max_runnable_latency_default; sched_perfcontrol_work_interval_notify_t sched_perfcontrol_work_interval_notify = sched_perfcontrol_work_interval_notify_default; +sched_perfcontrol_work_interval_ctl_t sched_perfcontrol_work_interval_ctl = sched_perfcontrol_work_interval_ctl_default; sched_perfcontrol_deadline_passed_t sched_perfcontrol_deadline_passed = sched_perfcontrol_deadline_passed_default; sched_perfcontrol_csw_t sched_perfcontrol_csw = sched_perfcontrol_csw_default; sched_perfcontrol_state_update_t sched_perfcontrol_state_update = sched_perfcontrol_state_update_default; @@ -131,6 +139,14 @@ sched_perfcontrol_register_callbacks(sched_perfcontrol_callbacks_t callbacks, un if (callbacks) { + if (callbacks->version >= SCHED_PERFCONTROL_CALLBACKS_VERSION_7) { + if (callbacks->work_interval_ctl != NULL) { + sched_perfcontrol_work_interval_ctl = callbacks->work_interval_ctl; + } else { + sched_perfcontrol_work_interval_ctl = sched_perfcontrol_work_interval_ctl_default; + } + } + if (callbacks->version >= SCHED_PERFCONTROL_CALLBACKS_VERSION_5) { if (callbacks->csw != NULL) { sched_perfcontrol_csw = callbacks->csw; @@ -192,6 +208,7 @@ sched_perfcontrol_register_callbacks(sched_perfcontrol_callbacks_t callbacks, un sched_perfcontrol_thread_group_flags_update = sched_perfcontrol_thread_group_default; sched_perfcontrol_max_runnable_latency = sched_perfcontrol_max_runnable_latency_default; sched_perfcontrol_work_interval_notify = sched_perfcontrol_work_interval_notify_default; + sched_perfcontrol_work_interval_ctl = sched_perfcontrol_work_interval_ctl_default; sched_perfcontrol_csw = sched_perfcontrol_csw_default; sched_perfcontrol_state_update = sched_perfcontrol_state_update_default; } @@ -432,6 +449,7 @@ machine_work_interval_notify(thread_t thread, sched_perfcontrol_work_interval_notify(state, &work_interval); } + void machine_perfcontrol_deadline_passed(uint64_t deadline) { diff --git a/osfmk/arm/model_dep.c b/osfmk/arm/model_dep.c index ad9fd23ea..1ae4b3c55 100644 --- a/osfmk/arm/model_dep.c +++ b/osfmk/arm/model_dep.c @@ -330,7 +330,7 @@ do_print_all_backtraces( #if defined(XNU_TARGET_OS_BRIDGE) paniclog_append_noflush("PCIeUp link state: "); if (PE_pcie_stashed_link_state != UINT32_MAX) { - paniclog_append_noflush("0x%x", PE_pcie_stashed_link_state); + paniclog_append_noflush("0x%x\n", PE_pcie_stashed_link_state); } else { paniclog_append_noflush("not available\n"); } diff --git a/osfmk/arm/pmap.c b/osfmk/arm/pmap.c index 990ab667d..a62fd171e 100644 --- a/osfmk/arm/pmap.c +++ b/osfmk/arm/pmap.c @@ -2988,6 +2988,11 @@ pmap_bootstrap( &pmap_stats_assert, sizeof (pmap_stats_assert)); #endif /* MACH_ASSERT */ + +#if KASAN + /* Shadow the CPU copy windows, as they fall outside of the physical aperture */ + kasan_map_shadow(CPUWINDOWS_BASE, CPUWINDOWS_TOP - CPUWINDOWS_BASE, true); +#endif /* KASAN */ } @@ -4319,7 +4324,8 @@ pmap_remove_range_options( /* sanity checks... */ #if MACH_ASSERT if (pmap->stats.internal < num_internal) { - if ((! pmap_stats_assert) || + if ((! pmap_stats_assert || + ! pmap->pmap_stats_assert) || (pmap->stats.internal + pmap->stats.reusable) == (num_internal + num_reusable)) { num_reusable_mismatch++; @@ -5524,16 +5530,17 @@ pmap_enter_options_internal( boolean_t wired, unsigned int options) { - pmap_paddr_t pa = ptoa(pn); - pt_entry_t pte; - pt_entry_t spte; - pt_entry_t *pte_p; - pv_entry_t *pve_p; - boolean_t set_NX; - boolean_t set_XO = FALSE; - boolean_t refcnt_updated; - unsigned int wimg_bits; - boolean_t was_compressed, was_alt_compressed; + pmap_paddr_t pa = ptoa(pn); + pt_entry_t pte; + pt_entry_t spte; + pt_entry_t *pte_p; + pv_entry_t *pve_p; + boolean_t set_NX; + boolean_t set_XO = FALSE; + boolean_t refcnt_updated; + boolean_t wiredcnt_updated; + unsigned int wimg_bits; + boolean_t was_compressed, was_alt_compressed; if ((v) & PAGE_MASK) { panic("pmap_enter_options() pmap %p v 0x%llx\n", @@ -5562,6 +5569,7 @@ pmap_enter_options_internal( assert(pn != vm_page_fictitious_addr); refcnt_updated = FALSE; + wiredcnt_updated = FALSE; pve_p = PV_ENTRY_NULL; was_compressed = FALSE; was_alt_compressed = FALSE; @@ -5757,16 +5765,17 @@ pmap_enter_options_internal( pte |= ARM_PTE_AF; volatile uint16_t *refcnt = NULL; + volatile uint16_t *wiredcnt = NULL; if (pmap != kernel_pmap) { refcnt = &(ptep_get_ptd(pte_p)->pt_cnt[ARM_PT_DESC_INDEX(pte_p)].refcnt); - /* Mark the PT page active to keep it from being reclaimed. We need this because + wiredcnt = &(ptep_get_ptd(pte_p)->pt_cnt[ARM_PT_DESC_INDEX(pte_p)].wiredcnt); + /* Bump the wired count to keep the PTE page from being reclaimed. We need this because * we may drop the PVH and pmap locks later in pmap_enter() if we need to allocate - * a new PV entry. Note that setting this high bit (0x4000) can temporarily - * prevent the refcount underflow checks in pmap_page_protect() and pmap_remove() from - * working. If an underflow should happen during this window, we'll instead get a - * refcount along the lines of 0x3FFF, which will produce a later panic on non-zero - * refcount in pmap_pages_reclaim() or pmap_tt_deallocate(). */ - OSBitOrAtomic16(PT_DESC_REFCOUNT, refcnt); + * a new PV entry. */ + if (!wiredcnt_updated) { + OSAddAtomic16(1, (volatile int16_t*)wiredcnt); + wiredcnt_updated = TRUE; + } if (!refcnt_updated) { OSAddAtomic16(1, (volatile int16_t*)refcnt); refcnt_updated = TRUE; @@ -5794,7 +5803,7 @@ pmap_enter_options_internal( */ if (refcnt != NULL) { assert(refcnt_updated); - if (OSAddAtomic16(-1, (volatile int16_t*)refcnt) <= (int16_t)PT_DESC_REFCOUNT) + if (OSAddAtomic16(-1, (volatile int16_t*)refcnt) <= 0) panic("pmap_enter(): over-release of ptdp %p for pte %p\n", ptep_get_ptd(pte_p), pte_p); } UNLOCK_PVH(pai); @@ -5802,7 +5811,7 @@ pmap_enter_options_internal( } else if (pte_to_pa(*pte_p) == pa) { if (refcnt != NULL) { assert(refcnt_updated); - if (OSAddAtomic16(-1, (volatile int16_t*)refcnt) <= (int16_t)PT_DESC_REFCOUNT) + if (OSAddAtomic16(-1, (volatile int16_t*)refcnt) <= 0) panic("pmap_enter(): over-release of ptdp %p for pte %p\n", ptep_get_ptd(pte_p), pte_p); } pmap_enter_pte(pmap, pte_p, pte, v); @@ -5974,19 +5983,20 @@ pmap_enter_options_internal( Pmap_enter_return: #if CONFIG_PGTRACE - if (pgtrace_enabled) { - // Clone and invalidate original mapping if eligible - for (int i = 0; i < PAGE_RATIO; i++) { - pmap_pgtrace_enter_clone(pmap, v + ARM_PGBYTES*i, 0, 0); - } - } + if (pgtrace_enabled) { + // Clone and invalidate original mapping if eligible + for (int i = 0; i < PAGE_RATIO; i++) { + pmap_pgtrace_enter_clone(pmap, v + ARM_PGBYTES*i, 0, 0); + } + } #endif if (pve_p != PV_ENTRY_NULL) pv_free(pve_p); - if (refcnt != NULL) - OSBitAndAtomic16(~PT_DESC_REFCOUNT, refcnt); // clear active marker + if (wiredcnt_updated && (OSAddAtomic16(-1, (volatile int16_t*)wiredcnt) <= 0)) + panic("pmap_enter(): over-unwire of ptdp %p for pte %p\n", ptep_get_ptd(pte_p), pte_p); + PMAP_UNLOCK(pmap); return KERN_SUCCESS; @@ -9142,12 +9152,18 @@ vm_map_offset_t pmap_max_offset( max_offset_ret = min_max_offset; } } else if (option == ARM_PMAP_MAX_OFFSET_JUMBO) { - max_offset_ret = 0x0000000518000000ULL; // Max offset is 20.375GB for pmaps with special "jumbo" blessing + if (arm64_pmap_max_offset_default) { + // Allow the boot-arg to override jumbo size + max_offset_ret = arm64_pmap_max_offset_default; + } else { + max_offset_ret = MACH_VM_MAX_ADDRESS; // Max offset is MACH_VM_MAX_ADDRESS for pmaps with special "jumbo" blessing + } } else { panic("pmap_max_offset illegal option 0x%x\n", option); } assert(max_offset_ret >= min_max_offset); + assert(max_offset_ret <= MACH_VM_MAX_ADDRESS); return max_offset_ret; #else if (option == ARM_PMAP_MAX_OFFSET_DEFAULT) { @@ -9168,6 +9184,7 @@ vm_map_offset_t pmap_max_offset( panic("pmap_max_offset illegal option 0x%x\n", option); } + assert(max_offset_ret <= VM_MAX_ADDRESS); return max_offset_ret; #endif } @@ -9605,7 +9622,8 @@ pmap_check_ledgers( } if (do_panic) { - if (pmap_ledgers_panic) { + if (pmap_ledgers_panic && + pmap->pmap_stats_assert) { panic("pmap_destroy(%p) %d[%s] has imbalanced ledgers\n", pmap, pid, procname); } else { @@ -10624,7 +10642,7 @@ pmap_query_page_info_internal( pve_p = pvh_list(pv_h); while (pve_p != PV_ENTRY_NULL && pve_get_ptep(pve_p) != pte) { - pve_p = pvh_list(pv_h); + pve_p = PVE_NEXT_PTR(pve_next(pve_p)); } } if (IS_ALTACCT_PAGE(pai, pve_p)) { diff --git a/osfmk/arm/proc_reg.h b/osfmk/arm/proc_reg.h index 9dc5e2ec8..28a99e3f5 100644 --- a/osfmk/arm/proc_reg.h +++ b/osfmk/arm/proc_reg.h @@ -1028,6 +1028,9 @@ #define ARM_DBG_CR_SECURITY_STATE_BOTH (0 << 14) #define ARM_DBG_CR_SECURITY_STATE_NONSECURE (1 << 14) #define ARM_DBG_CR_SECURITY_STATE_SECURE (2 << 14) +#define ARM_DBG_CR_HIGHER_MODE_MASK (1 << 13) /* BCR & WCR */ +#define ARM_DBG_CR_HIGHER_MODE_ENABLE (1 << 13) +#define ARM_DBG_CR_HIGHER_MODE_DISABLE (0 << 13) #define ARM_DBGWCR_BYTE_ADDRESS_SELECT_MASK 0x00001FE0 /* WCR only */ #define ARM_DBG_CR_BYTE_ADDRESS_SELECT_MASK 0x000001E0 /* BCR & WCR */ #define ARM_DBGWCR_ACCESS_CONTROL_MASK (3 << 3) /* WCR only */ @@ -1036,7 +1039,7 @@ #define ARM_DBCWCR_ACCESS_CONTROL_ANY (3 << 3) #define ARM_DBG_CR_MODE_CONTROL_MASK (3 << 1) /* BCR & WCR */ #define ARM_DBG_CR_MODE_CONTROL_U_S_S (0 << 1) /* BCR only */ -#define ARM_DBG_CR_MODE_CONTROL_PRIVILEDGED (1 << 1) /* BCR & WCR */ +#define ARM_DBG_CR_MODE_CONTROL_PRIVILEGED (1 << 1) /* BCR & WCR */ #define ARM_DBG_CR_MODE_CONTROL_USER (2 << 1) /* BCR & WCR */ #define ARM_DBG_CR_MODE_CONTROL_ANY (3 << 1) /* BCR & WCR */ #define ARM_DBG_CR_ENABLE_MASK (1 << 0) /* BCR & WCR */ diff --git a/osfmk/arm/trap.c b/osfmk/arm/trap.c index 617c652ab..a2c691c74 100644 --- a/osfmk/arm/trap.c +++ b/osfmk/arm/trap.c @@ -103,9 +103,6 @@ void sleh_abort(struct arm_saved_state *, int); static kern_return_t sleh_alignment(struct arm_saved_state *); static void panic_with_thread_kernel_state(const char *msg, arm_saved_state_t *regs); - -volatile perfCallback perfTrapHook = NULL; /* Pointer to CHUD trap hook routine */ - int sleh_alignment_count = 0; int trap_on_alignment_fault = 0; diff --git a/osfmk/arm/trap.h b/osfmk/arm/trap.h index fe15c2733..a4caeaa5a 100644 --- a/osfmk/arm/trap.h +++ b/osfmk/arm/trap.h @@ -273,12 +273,6 @@ typedef kern_return_t (*perfCallback)( uintptr_t *, int); -typedef kern_return_t (*perfASTCallback)(ast_t reasons, ast_t *myast); - -extern volatile perfCallback perfTrapHook; -extern volatile perfASTCallback perfASTHook; -extern volatile perfCallback perfIntHook; - #endif /* !ASSEMBLER && MACH_KERNEL */ #endif /* _ARM_TRAP_H_ */ diff --git a/osfmk/arm64/caches_asm.s b/osfmk/arm64/caches_asm.s index 463d39067..ac50fd037 100644 --- a/osfmk/arm64/caches_asm.s +++ b/osfmk/arm64/caches_asm.s @@ -222,7 +222,28 @@ LEXT(CleanPoC_DcacheRegion) .align 2 .globl EXT(CleanPoC_DcacheRegion_Force) LEXT(CleanPoC_DcacheRegion_Force) - b EXT(CleanPoC_DcacheRegion_internal) +#if defined(APPLE_ARM64_ARCH_FAMILY) + PUSH_FRAME + stp x0, x1, [sp, #-16]! + bl EXT(_disable_preemption) + isb sy + ARM64_IS_PCORE x15 + ARM64_READ_EP_SPR x15, x14, ARM64_REG_EHID4, ARM64_REG_HID4 + and x14, x14, (~ARM64_REG_HID4_DisDcMVAOps) + ARM64_WRITE_EP_SPR x15, x14, ARM64_REG_EHID4, ARM64_REG_HID4 + isb sy + ldp x0, x1, [sp], #16 + bl EXT(CleanPoC_DcacheRegion_internal) + isb sy + orr x14, x14, ARM64_REG_HID4_DisDcMVAOps + ARM64_WRITE_EP_SPR x15, x14, ARM64_REG_EHID4, ARM64_REG_HID4 + isb sy + bl EXT(_enable_preemption) + POP_FRAME + ret +#else + b EXT(CleanPoC_DcacheRegion_internal) +#endif // APPLE_ARM64_ARCH_FAMILY /* * void FlushPoC_Dcache(void) diff --git a/osfmk/arm64/locore.s b/osfmk/arm64/locore.s index ea33d6b42..4430d3b5c 100644 --- a/osfmk/arm64/locore.s +++ b/osfmk/arm64/locore.s @@ -199,7 +199,7 @@ .endmacro #if __ARM_KERNEL_PROTECT__ - .data + .text .align 3 .globl EXT(exc_vectors_table) LEXT(exc_vectors_table) @@ -564,12 +564,38 @@ fleh_dispatch64: /* Save arm_saved_state64 */ SPILL_REGISTERS - /* If exception is from userspace, zero lr */ - ldr w21, [x0, SS64_CPSR] - and x21, x21, #(PSR64_MODE_EL_MASK) - cmp x21, #(PSR64_MODE_EL0) + /* If exception is from userspace, zero unused registers */ + and x23, x23, #(PSR64_MODE_EL_MASK) + cmp x23, #(PSR64_MODE_EL0) bne 1f - mov lr, #0 + + mov x2, xzr + mov x3, xzr + mov x4, xzr + mov x5, xzr + mov x6, xzr + mov x7, xzr + mov x8, xzr + mov x9, xzr + mov x10, xzr + mov x11, xzr + mov x12, xzr + mov x13, xzr + mov x14, xzr + mov x15, xzr + mov x16, xzr + mov x17, xzr + mov x18, xzr + mov x19, xzr + mov x20, xzr + /* x21, x22 cleared in common case below */ + mov x23, xzr + mov x24, xzr + mov x25, xzr + mov x26, xzr + mov x27, xzr + mov x28, xzr + /* fp/lr already cleared by EL0_64_VECTOR */ 1: mov x21, x0 // Copy arm_context_t pointer to x21 @@ -885,9 +911,9 @@ check_user_asts: exception_return: - msr DAIFSet, #(DAIFSC_IRQF | DAIFSC_FIQF) // Disable interrupts - mrs x3, TPIDR_EL1 // Load thread pointer - mov sp, x21 // Reload the pcb pointer + msr DAIFSet, #DAIFSC_ALL // Disable exceptions + mrs x3, TPIDR_EL1 // Load thread pointer + mov sp, x21 // Reload the pcb pointer /* ARM64_TODO Reserve x18 until we decide what to do with it */ ldr x0, [x3, TH_CTH_DATA] // Load cthread data pointer diff --git a/osfmk/arm64/machine_routines.c b/osfmk/arm64/machine_routines.c index defb3f837..f6a5db38c 100644 --- a/osfmk/arm64/machine_routines.c +++ b/osfmk/arm64/machine_routines.c @@ -942,9 +942,6 @@ ml_processor_register( this_cpu_datap->cpu_id = in_processor_info->cpu_id; - this_cpu_datap->cpu_chud = chudxnu_cpu_alloc(is_boot_cpu); - if (this_cpu_datap->cpu_chud == (void *)NULL) - goto processor_register_error; this_cpu_datap->cpu_console_buf = console_cpu_alloc(is_boot_cpu); if (this_cpu_datap->cpu_console_buf == (void *)(NULL)) goto processor_register_error; @@ -1020,8 +1017,6 @@ ml_processor_register( #if KPC kpc_unregister_cpu(this_cpu_datap); #endif - if (this_cpu_datap->cpu_chud != (void *)NULL) - chudxnu_cpu_free(this_cpu_datap->cpu_chud); if (!is_boot_cpu) cpu_data_free(this_cpu_datap); diff --git a/osfmk/arm64/pcb.c b/osfmk/arm64/pcb.c index 55d5fe4d9..a6fa9154b 100644 --- a/osfmk/arm64/pcb.c +++ b/osfmk/arm64/pcb.c @@ -367,14 +367,69 @@ call_continuation( Call_continuation(continuation, parameter, wresult, current_thread()->machine.kstackptr); } +/* Setting breakpoints in EL1 is effectively a KTRR bypass. The ability to do so is + * controlled by MDSCR.KDE. The MSR to set MDSCR must be present to allow + * self-hosted user mode debug. Any checks before the MRS can be skipped with ROP, + * so we need to put the checks after the MRS where they can't be skipped. That + * still leaves a small window if a breakpoint is set on the instruction + * immediately after the MRS. To handle that, we also do a check and then set of + * the breakpoint control registers. This allows us to guarantee that a given + * core will never have both KDE set and a breakpoint targeting EL1. + * + * If KDE gets set, unset it and then panic */ +static void +update_mdscr(uint64_t clear, uint64_t set) +{ + uint64_t result = 0; + uint64_t tmp1, tmp2; + __asm__ volatile( + "mrs %[reg], MDSCR_EL1\n" + "bic %[reg], %[reg], %[clear]\n" + "orr %[reg], %[reg], %[set]\n" + "1:\n" + "bic %[reg], %[reg], #0x2000\n" + "msr MDSCR_EL1, %[reg]\n" +#if defined(CONFIG_KERNEL_INTEGRITY) + /* verify KDE didn't get set (including via ROP) + * If set, clear it and then panic */ + "ands %[tmp], %[reg], #0x2000\n" + "orr %[res], %[res], %[tmp]\n" + "bne 1b\n" +#endif + : [res] "+r" (result), [tmp] "=r" (tmp1), [reg] "=r" (tmp2) + : [clear] "r" (clear), [set] "r" (set) : "x0"); +#if defined(CONFIG_KERNEL_INTEGRITY) + if (result) + panic("MDSCR.KDE was set: %llx %llx %llx", tmp1, tmp2, result); +#endif +} + +#define SET_DBGBCRn(n, value, accum) \ + __asm__ volatile( \ + "msr DBGBCR" #n "_EL1, %[val]\n" \ + "orr %[result], %[result], %[val]\n" \ + : [result] "+r"(accum) : [val] "r"((value))) + +#define SET_DBGBVRn(n, value) \ + __asm__ volatile("msr DBGBVR" #n "_EL1, %0" : : "r"(value)) + +#define SET_DBGWCRn(n, value, accum) \ + __asm__ volatile( \ + "msr DBGWCR" #n "_EL1, %[val]\n" \ + "orr %[result], %[result], %[val]\n" \ + : [result] "+r"(accum) : [val] "r"((value))) + +#define SET_DBGWVRn(n, value) \ + __asm__ volatile("msr DBGWVR" #n "_EL1, %0" : : "r"(value)) + void arm_debug_set32(arm_debug_state_t *debug_state) { struct cpu_data *cpu_data_ptr; arm_debug_info_t *debug_info = arm_debug_info(); - volatile uint64_t state; boolean_t intr, set_mde = 0; arm_debug_state_t off_state; uint32_t i; + uint64_t all_ctrls = 0; intr = ml_set_interrupts_enabled(FALSE); cpu_data_ptr = getCpuDatap(); @@ -389,110 +444,116 @@ void arm_debug_set32(arm_debug_state_t *debug_state) switch (debug_info->num_breakpoint_pairs) { case 16: - __asm__ volatile("msr DBGBVR15_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bvr[15])); - __asm__ volatile("msr DBGBCR15_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bcr[15])); + SET_DBGBVRn(15, (uint64_t)debug_state->uds.ds32.bvr[15]); + SET_DBGBCRn(15, (uint64_t)debug_state->uds.ds32.bcr[15], all_ctrls); case 15: - __asm__ volatile("msr DBGBVR14_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bvr[14])); - __asm__ volatile("msr DBGBCR14_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bcr[14])); + SET_DBGBVRn(14, (uint64_t)debug_state->uds.ds32.bvr[14]); + SET_DBGBCRn(14, (uint64_t)debug_state->uds.ds32.bcr[14], all_ctrls); case 14: - __asm__ volatile("msr DBGBVR13_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bvr[13])); - __asm__ volatile("msr DBGBCR13_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bcr[13])); + SET_DBGBVRn(13, (uint64_t)debug_state->uds.ds32.bvr[13]); + SET_DBGBCRn(13, (uint64_t)debug_state->uds.ds32.bcr[13], all_ctrls); case 13: - __asm__ volatile("msr DBGBVR12_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bvr[12])); - __asm__ volatile("msr DBGBCR12_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bcr[12])); + SET_DBGBVRn(12, (uint64_t)debug_state->uds.ds32.bvr[12]); + SET_DBGBCRn(12, (uint64_t)debug_state->uds.ds32.bcr[12], all_ctrls); case 12: - __asm__ volatile("msr DBGBVR11_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bvr[11])); - __asm__ volatile("msr DBGBCR11_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bcr[11])); + SET_DBGBVRn(11, (uint64_t)debug_state->uds.ds32.bvr[11]); + SET_DBGBCRn(11, (uint64_t)debug_state->uds.ds32.bcr[11], all_ctrls); case 11: - __asm__ volatile("msr DBGBVR10_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bvr[10])); - __asm__ volatile("msr DBGBCR10_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bcr[10])); + SET_DBGBVRn(10, (uint64_t)debug_state->uds.ds32.bvr[10]); + SET_DBGBCRn(10, (uint64_t)debug_state->uds.ds32.bcr[10], all_ctrls); case 10: - __asm__ volatile("msr DBGBVR9_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bvr[9])); - __asm__ volatile("msr DBGBCR9_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bcr[9])); + SET_DBGBVRn(9, (uint64_t)debug_state->uds.ds32.bvr[9]); + SET_DBGBCRn(9, (uint64_t)debug_state->uds.ds32.bcr[9], all_ctrls); case 9: - __asm__ volatile("msr DBGBVR8_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bvr[8])); - __asm__ volatile("msr DBGBCR8_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bcr[8])); + SET_DBGBVRn(8, (uint64_t)debug_state->uds.ds32.bvr[8]); + SET_DBGBCRn(8, (uint64_t)debug_state->uds.ds32.bcr[8], all_ctrls); case 8: - __asm__ volatile("msr DBGBVR7_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bvr[7])); - __asm__ volatile("msr DBGBCR7_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bcr[7])); + SET_DBGBVRn(7, (uint64_t)debug_state->uds.ds32.bvr[7]); + SET_DBGBCRn(7, (uint64_t)debug_state->uds.ds32.bcr[7], all_ctrls); case 7: - __asm__ volatile("msr DBGBVR6_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bvr[6])); - __asm__ volatile("msr DBGBCR6_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bcr[6])); + SET_DBGBVRn(6, (uint64_t)debug_state->uds.ds32.bvr[6]); + SET_DBGBCRn(6, (uint64_t)debug_state->uds.ds32.bcr[6], all_ctrls); case 6: - __asm__ volatile("msr DBGBVR5_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bvr[5])); - __asm__ volatile("msr DBGBCR5_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bcr[5])); + SET_DBGBVRn(5, (uint64_t)debug_state->uds.ds32.bvr[5]); + SET_DBGBCRn(5, (uint64_t)debug_state->uds.ds32.bcr[5], all_ctrls); case 5: - __asm__ volatile("msr DBGBVR4_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bvr[4])); - __asm__ volatile("msr DBGBCR4_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bcr[4])); + SET_DBGBVRn(4, (uint64_t)debug_state->uds.ds32.bvr[4]); + SET_DBGBCRn(4, (uint64_t)debug_state->uds.ds32.bcr[4], all_ctrls); case 4: - __asm__ volatile("msr DBGBVR3_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bvr[3])); - __asm__ volatile("msr DBGBCR3_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bcr[3])); + SET_DBGBVRn(3, (uint64_t)debug_state->uds.ds32.bvr[3]); + SET_DBGBCRn(3, (uint64_t)debug_state->uds.ds32.bcr[3], all_ctrls); case 3: - __asm__ volatile("msr DBGBVR2_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bvr[2])); - __asm__ volatile("msr DBGBCR2_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bcr[2])); + SET_DBGBVRn(2, (uint64_t)debug_state->uds.ds32.bvr[2]); + SET_DBGBCRn(2, (uint64_t)debug_state->uds.ds32.bcr[2], all_ctrls); case 2: - __asm__ volatile("msr DBGBVR1_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bvr[1])); - __asm__ volatile("msr DBGBCR1_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bcr[1])); + SET_DBGBVRn(1, (uint64_t)debug_state->uds.ds32.bvr[1]); + SET_DBGBCRn(1, (uint64_t)debug_state->uds.ds32.bcr[1], all_ctrls); case 1: - __asm__ volatile("msr DBGBVR0_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bvr[0])); - __asm__ volatile("msr DBGBCR0_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.bcr[0])); + SET_DBGBVRn(0, (uint64_t)debug_state->uds.ds32.bvr[0]); + SET_DBGBCRn(0, (uint64_t)debug_state->uds.ds32.bcr[0], all_ctrls); default: break; } switch (debug_info->num_watchpoint_pairs) { case 16: - __asm__ volatile("msr DBGWVR15_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wvr[15])); - __asm__ volatile("msr DBGWCR15_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wcr[15])); + SET_DBGWVRn(15, (uint64_t)debug_state->uds.ds32.wvr[15]); + SET_DBGWCRn(15, (uint64_t)debug_state->uds.ds32.wcr[15], all_ctrls); case 15: - __asm__ volatile("msr DBGWVR14_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wvr[14])); - __asm__ volatile("msr DBGWCR14_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wcr[14])); + SET_DBGWVRn(14, (uint64_t)debug_state->uds.ds32.wvr[14]); + SET_DBGWCRn(14, (uint64_t)debug_state->uds.ds32.wcr[14], all_ctrls); case 14: - __asm__ volatile("msr DBGWVR13_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wvr[13])); - __asm__ volatile("msr DBGWCR13_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wcr[13])); + SET_DBGWVRn(13, (uint64_t)debug_state->uds.ds32.wvr[13]); + SET_DBGWCRn(13, (uint64_t)debug_state->uds.ds32.wcr[13], all_ctrls); case 13: - __asm__ volatile("msr DBGWVR12_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wvr[12])); - __asm__ volatile("msr DBGWCR12_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wcr[12])); + SET_DBGWVRn(12, (uint64_t)debug_state->uds.ds32.wvr[12]); + SET_DBGWCRn(12, (uint64_t)debug_state->uds.ds32.wcr[12], all_ctrls); case 12: - __asm__ volatile("msr DBGWVR11_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wvr[11])); - __asm__ volatile("msr DBGWCR11_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wcr[11])); + SET_DBGWVRn(11, (uint64_t)debug_state->uds.ds32.wvr[11]); + SET_DBGWCRn(11, (uint64_t)debug_state->uds.ds32.wcr[11], all_ctrls); case 11: - __asm__ volatile("msr DBGWVR10_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wvr[10])); - __asm__ volatile("msr DBGWCR10_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wcr[10])); + SET_DBGWVRn(10, (uint64_t)debug_state->uds.ds32.wvr[10]); + SET_DBGWCRn(10, (uint64_t)debug_state->uds.ds32.wcr[10], all_ctrls); case 10: - __asm__ volatile("msr DBGWVR9_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wvr[9])); - __asm__ volatile("msr DBGWCR9_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wcr[9])); + SET_DBGWVRn(9, (uint64_t)debug_state->uds.ds32.wvr[9]); + SET_DBGWCRn(9, (uint64_t)debug_state->uds.ds32.wcr[9], all_ctrls); case 9: - __asm__ volatile("msr DBGWVR8_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wvr[8])); - __asm__ volatile("msr DBGWCR8_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wcr[8])); + SET_DBGWVRn(8, (uint64_t)debug_state->uds.ds32.wvr[8]); + SET_DBGWCRn(8, (uint64_t)debug_state->uds.ds32.wcr[8], all_ctrls); case 8: - __asm__ volatile("msr DBGWVR7_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wvr[7])); - __asm__ volatile("msr DBGWCR7_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wcr[7])); + SET_DBGWVRn(7, (uint64_t)debug_state->uds.ds32.wvr[7]); + SET_DBGWCRn(7, (uint64_t)debug_state->uds.ds32.wcr[7], all_ctrls); case 7: - __asm__ volatile("msr DBGWVR6_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wvr[6])); - __asm__ volatile("msr DBGWCR6_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wcr[6])); + SET_DBGWVRn(6, (uint64_t)debug_state->uds.ds32.wvr[6]); + SET_DBGWCRn(6, (uint64_t)debug_state->uds.ds32.wcr[6], all_ctrls); case 6: - __asm__ volatile("msr DBGWVR5_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wvr[5])); - __asm__ volatile("msr DBGWCR5_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wcr[5])); + SET_DBGWVRn(5, (uint64_t)debug_state->uds.ds32.wvr[5]); + SET_DBGWCRn(5, (uint64_t)debug_state->uds.ds32.wcr[5], all_ctrls); case 5: - __asm__ volatile("msr DBGWVR4_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wvr[4])); - __asm__ volatile("msr DBGWCR4_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wcr[4])); + SET_DBGWVRn(4, (uint64_t)debug_state->uds.ds32.wvr[4]); + SET_DBGWCRn(4, (uint64_t)debug_state->uds.ds32.wcr[4], all_ctrls); case 4: - __asm__ volatile("msr DBGWVR3_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wvr[3])); - __asm__ volatile("msr DBGWCR3_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wcr[3])); + SET_DBGWVRn(3, (uint64_t)debug_state->uds.ds32.wvr[3]); + SET_DBGWCRn(3, (uint64_t)debug_state->uds.ds32.wcr[3], all_ctrls); case 3: - __asm__ volatile("msr DBGWVR2_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wvr[2])); - __asm__ volatile("msr DBGWCR2_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wcr[2])); + SET_DBGWVRn(2, (uint64_t)debug_state->uds.ds32.wvr[2]); + SET_DBGWCRn(2, (uint64_t)debug_state->uds.ds32.wcr[2], all_ctrls); case 2: - __asm__ volatile("msr DBGWVR1_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wvr[1])); - __asm__ volatile("msr DBGWCR1_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wcr[1])); + SET_DBGWVRn(1, (uint64_t)debug_state->uds.ds32.wvr[1]); + SET_DBGWCRn(1, (uint64_t)debug_state->uds.ds32.wcr[1], all_ctrls); case 1: - __asm__ volatile("msr DBGWVR0_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wvr[0])); - __asm__ volatile("msr DBGWCR0_EL1, %0" : : "r"((uint64_t)debug_state->uds.ds32.wcr[0])); + SET_DBGWVRn(0, (uint64_t)debug_state->uds.ds32.wvr[0]); + SET_DBGWCRn(0, (uint64_t)debug_state->uds.ds32.wcr[0], all_ctrls); default: break; } +#if defined(CONFIG_KERNEL_INTEGRITY) + if ((all_ctrls & (ARM_DBG_CR_MODE_CONTROL_PRIVILEGED | ARM_DBG_CR_HIGHER_MODE_ENABLE)) != 0) { + panic("sorry, self-hosted debug is not supported: 0x%llx", all_ctrls); + } +#endif + for (i = 0; i < debug_info->num_breakpoint_pairs; i++) { if (0 != debug_state->uds.ds32.bcr[i]) { set_mde = 1; @@ -511,36 +572,23 @@ void arm_debug_set32(arm_debug_state_t *debug_state) * Breakpoint/Watchpoint Enable */ if (set_mde) { - - __asm__ volatile("mrs %0, MDSCR_EL1" : "=r"(state)); - state |= 0x8000; // MDSCR_EL1[MDE] - __asm__ volatile("msr MDSCR_EL1, %0" : : "r"(state)); - + update_mdscr(0, 0x8000); // MDSCR_EL1[MDE] } else { - - __asm__ volatile("mrs %0, MDSCR_EL1" : "=r"(state)); - state &= ~0x8000; - __asm__ volatile("msr MDSCR_EL1, %0" : : "r"(state)); - + update_mdscr(0x8000, 0); } /* * Software debug single step enable */ if (debug_state->uds.ds32.mdscr_el1 & 0x1) { - - __asm__ volatile("mrs %0, MDSCR_EL1" : "=r"(state)); - state = (state & ~0x8000) | 0x1; // ~MDE | SS : no brk/watch while single stepping (which we've set) - __asm__ volatile("msr MDSCR_EL1, %0" : : "r"(state)); + update_mdscr(0x8000, 1); // ~MDE | SS : no brk/watch while single stepping (which we've set) set_saved_state_cpsr((current_thread()->machine.upcb), get_saved_state_cpsr((current_thread()->machine.upcb)) | PSR64_SS); } else { - __asm__ volatile("mrs %0, MDSCR_EL1" : "=r"(state)); - state &= ~0x1; - __asm__ volatile("msr MDSCR_EL1, %0" : : "r"(state)); + update_mdscr(0x1, 0); #if SINGLE_STEP_RETIRE_ERRATA // Workaround for radar 20619637 @@ -557,10 +605,10 @@ void arm_debug_set64(arm_debug_state_t *debug_state) { struct cpu_data *cpu_data_ptr; arm_debug_info_t *debug_info = arm_debug_info(); - volatile uint64_t state; boolean_t intr, set_mde = 0; arm_debug_state_t off_state; uint32_t i; + uint64_t all_ctrls = 0; intr = ml_set_interrupts_enabled(FALSE); cpu_data_ptr = getCpuDatap(); @@ -575,110 +623,116 @@ void arm_debug_set64(arm_debug_state_t *debug_state) switch (debug_info->num_breakpoint_pairs) { case 16: - __asm__ volatile("msr DBGBVR15_EL1, %0" : : "r"(debug_state->uds.ds64.bvr[15])); - __asm__ volatile("msr DBGBCR15_EL1, %0" : : "r"(debug_state->uds.ds64.bcr[15])); + SET_DBGBVRn(15, debug_state->uds.ds64.bvr[15]); + SET_DBGBCRn(15, (uint64_t)debug_state->uds.ds64.bcr[15], all_ctrls); case 15: - __asm__ volatile("msr DBGBVR14_EL1, %0" : : "r"(debug_state->uds.ds64.bvr[14])); - __asm__ volatile("msr DBGBCR14_EL1, %0" : : "r"(debug_state->uds.ds64.bcr[14])); + SET_DBGBVRn(14, debug_state->uds.ds64.bvr[14]); + SET_DBGBCRn(14, (uint64_t)debug_state->uds.ds64.bcr[14], all_ctrls); case 14: - __asm__ volatile("msr DBGBVR13_EL1, %0" : : "r"(debug_state->uds.ds64.bvr[13])); - __asm__ volatile("msr DBGBCR13_EL1, %0" : : "r"(debug_state->uds.ds64.bcr[13])); + SET_DBGBVRn(13, debug_state->uds.ds64.bvr[13]); + SET_DBGBCRn(13, (uint64_t)debug_state->uds.ds64.bcr[13], all_ctrls); case 13: - __asm__ volatile("msr DBGBVR12_EL1, %0" : : "r"(debug_state->uds.ds64.bvr[12])); - __asm__ volatile("msr DBGBCR12_EL1, %0" : : "r"(debug_state->uds.ds64.bcr[12])); + SET_DBGBVRn(12, debug_state->uds.ds64.bvr[12]); + SET_DBGBCRn(12, (uint64_t)debug_state->uds.ds64.bcr[12], all_ctrls); case 12: - __asm__ volatile("msr DBGBVR11_EL1, %0" : : "r"(debug_state->uds.ds64.bvr[11])); - __asm__ volatile("msr DBGBCR11_EL1, %0" : : "r"(debug_state->uds.ds64.bcr[11])); + SET_DBGBVRn(11, debug_state->uds.ds64.bvr[11]); + SET_DBGBCRn(11, (uint64_t)debug_state->uds.ds64.bcr[11], all_ctrls); case 11: - __asm__ volatile("msr DBGBVR10_EL1, %0" : : "r"(debug_state->uds.ds64.bvr[10])); - __asm__ volatile("msr DBGBCR10_EL1, %0" : : "r"(debug_state->uds.ds64.bcr[10])); + SET_DBGBVRn(10, debug_state->uds.ds64.bvr[10]); + SET_DBGBCRn(10, (uint64_t)debug_state->uds.ds64.bcr[10], all_ctrls); case 10: - __asm__ volatile("msr DBGBVR9_EL1, %0" : : "r"(debug_state->uds.ds64.bvr[9])); - __asm__ volatile("msr DBGBCR9_EL1, %0" : : "r"(debug_state->uds.ds64.bcr[9])); + SET_DBGBVRn(9, debug_state->uds.ds64.bvr[9]); + SET_DBGBCRn(9, (uint64_t)debug_state->uds.ds64.bcr[9], all_ctrls); case 9: - __asm__ volatile("msr DBGBVR8_EL1, %0" : : "r"(debug_state->uds.ds64.bvr[8])); - __asm__ volatile("msr DBGBCR8_EL1, %0" : : "r"(debug_state->uds.ds64.bcr[8])); + SET_DBGBVRn(8, debug_state->uds.ds64.bvr[8]); + SET_DBGBCRn(8, (uint64_t)debug_state->uds.ds64.bcr[8], all_ctrls); case 8: - __asm__ volatile("msr DBGBVR7_EL1, %0" : : "r"(debug_state->uds.ds64.bvr[7])); - __asm__ volatile("msr DBGBCR7_EL1, %0" : : "r"(debug_state->uds.ds64.bcr[7])); + SET_DBGBVRn(7, debug_state->uds.ds64.bvr[7]); + SET_DBGBCRn(7, (uint64_t)debug_state->uds.ds64.bcr[7], all_ctrls); case 7: - __asm__ volatile("msr DBGBVR6_EL1, %0" : : "r"(debug_state->uds.ds64.bvr[6])); - __asm__ volatile("msr DBGBCR6_EL1, %0" : : "r"(debug_state->uds.ds64.bcr[6])); + SET_DBGBVRn(6, debug_state->uds.ds64.bvr[6]); + SET_DBGBCRn(6, (uint64_t)debug_state->uds.ds64.bcr[6], all_ctrls); case 6: - __asm__ volatile("msr DBGBVR5_EL1, %0" : : "r"(debug_state->uds.ds64.bvr[5])); - __asm__ volatile("msr DBGBCR5_EL1, %0" : : "r"(debug_state->uds.ds64.bcr[5])); + SET_DBGBVRn(5, debug_state->uds.ds64.bvr[5]); + SET_DBGBCRn(5, (uint64_t)debug_state->uds.ds64.bcr[5], all_ctrls); case 5: - __asm__ volatile("msr DBGBVR4_EL1, %0" : : "r"(debug_state->uds.ds64.bvr[4])); - __asm__ volatile("msr DBGBCR4_EL1, %0" : : "r"(debug_state->uds.ds64.bcr[4])); + SET_DBGBVRn(4, debug_state->uds.ds64.bvr[4]); + SET_DBGBCRn(4, (uint64_t)debug_state->uds.ds64.bcr[4], all_ctrls); case 4: - __asm__ volatile("msr DBGBVR3_EL1, %0" : : "r"(debug_state->uds.ds64.bvr[3])); - __asm__ volatile("msr DBGBCR3_EL1, %0" : : "r"(debug_state->uds.ds64.bcr[3])); + SET_DBGBVRn(3, debug_state->uds.ds64.bvr[3]); + SET_DBGBCRn(3, (uint64_t)debug_state->uds.ds64.bcr[3], all_ctrls); case 3: - __asm__ volatile("msr DBGBVR2_EL1, %0" : : "r"(debug_state->uds.ds64.bvr[2])); - __asm__ volatile("msr DBGBCR2_EL1, %0" : : "r"(debug_state->uds.ds64.bcr[2])); + SET_DBGBVRn(2, debug_state->uds.ds64.bvr[2]); + SET_DBGBCRn(2, (uint64_t)debug_state->uds.ds64.bcr[2], all_ctrls); case 2: - __asm__ volatile("msr DBGBVR1_EL1, %0" : : "r"(debug_state->uds.ds64.bvr[1])); - __asm__ volatile("msr DBGBCR1_EL1, %0" : : "r"(debug_state->uds.ds64.bcr[1])); + SET_DBGBVRn(1, debug_state->uds.ds64.bvr[1]); + SET_DBGBCRn(1, (uint64_t)debug_state->uds.ds64.bcr[1], all_ctrls); case 1: - __asm__ volatile("msr DBGBVR0_EL1, %0" : : "r"(debug_state->uds.ds64.bvr[0])); - __asm__ volatile("msr DBGBCR0_EL1, %0" : : "r"(debug_state->uds.ds64.bcr[0])); + SET_DBGBVRn(0, debug_state->uds.ds64.bvr[0]); + SET_DBGBCRn(0, (uint64_t)debug_state->uds.ds64.bcr[0], all_ctrls); default: break; } switch (debug_info->num_watchpoint_pairs) { case 16: - __asm__ volatile("msr DBGWVR15_EL1, %0" : : "r"(debug_state->uds.ds64.wvr[15])); - __asm__ volatile("msr DBGWCR15_EL1, %0" : : "r"(debug_state->uds.ds64.wcr[15])); + SET_DBGWVRn(15, debug_state->uds.ds64.wvr[15]); + SET_DBGWCRn(15, (uint64_t)debug_state->uds.ds64.wcr[15], all_ctrls); case 15: - __asm__ volatile("msr DBGWVR14_EL1, %0" : : "r"(debug_state->uds.ds64.wvr[14])); - __asm__ volatile("msr DBGWCR14_EL1, %0" : : "r"(debug_state->uds.ds64.wcr[14])); + SET_DBGWVRn(14, debug_state->uds.ds64.wvr[14]); + SET_DBGWCRn(14, (uint64_t)debug_state->uds.ds64.wcr[14], all_ctrls); case 14: - __asm__ volatile("msr DBGWVR13_EL1, %0" : : "r"(debug_state->uds.ds64.wvr[13])); - __asm__ volatile("msr DBGWCR13_EL1, %0" : : "r"(debug_state->uds.ds64.wcr[13])); + SET_DBGWVRn(13, debug_state->uds.ds64.wvr[13]); + SET_DBGWCRn(13, (uint64_t)debug_state->uds.ds64.wcr[13], all_ctrls); case 13: - __asm__ volatile("msr DBGWVR12_EL1, %0" : : "r"(debug_state->uds.ds64.wvr[12])); - __asm__ volatile("msr DBGWCR12_EL1, %0" : : "r"(debug_state->uds.ds64.wcr[12])); + SET_DBGWVRn(12, debug_state->uds.ds64.wvr[12]); + SET_DBGWCRn(12, (uint64_t)debug_state->uds.ds64.wcr[12], all_ctrls); case 12: - __asm__ volatile("msr DBGWVR11_EL1, %0" : : "r"(debug_state->uds.ds64.wvr[11])); - __asm__ volatile("msr DBGWCR11_EL1, %0" : : "r"(debug_state->uds.ds64.wcr[11])); + SET_DBGWVRn(11, debug_state->uds.ds64.wvr[11]); + SET_DBGWCRn(11, (uint64_t)debug_state->uds.ds64.wcr[11], all_ctrls); case 11: - __asm__ volatile("msr DBGWVR10_EL1, %0" : : "r"(debug_state->uds.ds64.wvr[10])); - __asm__ volatile("msr DBGWCR10_EL1, %0" : : "r"(debug_state->uds.ds64.wcr[10])); + SET_DBGWVRn(10, debug_state->uds.ds64.wvr[10]); + SET_DBGWCRn(10, (uint64_t)debug_state->uds.ds64.wcr[10], all_ctrls); case 10: - __asm__ volatile("msr DBGWVR9_EL1, %0" : : "r"(debug_state->uds.ds64.wvr[9])); - __asm__ volatile("msr DBGWCR9_EL1, %0" : : "r"(debug_state->uds.ds64.wcr[9])); + SET_DBGWVRn(9, debug_state->uds.ds64.wvr[9]); + SET_DBGWCRn(9, (uint64_t)debug_state->uds.ds64.wcr[9], all_ctrls); case 9: - __asm__ volatile("msr DBGWVR8_EL1, %0" : : "r"(debug_state->uds.ds64.wvr[8])); - __asm__ volatile("msr DBGWCR8_EL1, %0" : : "r"(debug_state->uds.ds64.wcr[8])); + SET_DBGWVRn(8, debug_state->uds.ds64.wvr[8]); + SET_DBGWCRn(8, (uint64_t)debug_state->uds.ds64.wcr[8], all_ctrls); case 8: - __asm__ volatile("msr DBGWVR7_EL1, %0" : : "r"(debug_state->uds.ds64.wvr[7])); - __asm__ volatile("msr DBGWCR7_EL1, %0" : : "r"(debug_state->uds.ds64.wcr[7])); + SET_DBGWVRn(7, debug_state->uds.ds64.wvr[7]); + SET_DBGWCRn(7, (uint64_t)debug_state->uds.ds64.wcr[7], all_ctrls); case 7: - __asm__ volatile("msr DBGWVR6_EL1, %0" : : "r"(debug_state->uds.ds64.wvr[6])); - __asm__ volatile("msr DBGWCR6_EL1, %0" : : "r"(debug_state->uds.ds64.wcr[6])); + SET_DBGWVRn(6, debug_state->uds.ds64.wvr[6]); + SET_DBGWCRn(6, (uint64_t)debug_state->uds.ds64.wcr[6], all_ctrls); case 6: - __asm__ volatile("msr DBGWVR5_EL1, %0" : : "r"(debug_state->uds.ds64.wvr[5])); - __asm__ volatile("msr DBGWCR5_EL1, %0" : : "r"(debug_state->uds.ds64.wcr[5])); + SET_DBGWVRn(5, debug_state->uds.ds64.wvr[5]); + SET_DBGWCRn(5, (uint64_t)debug_state->uds.ds64.wcr[5], all_ctrls); case 5: - __asm__ volatile("msr DBGWVR4_EL1, %0" : : "r"(debug_state->uds.ds64.wvr[4])); - __asm__ volatile("msr DBGWCR4_EL1, %0" : : "r"(debug_state->uds.ds64.wcr[4])); + SET_DBGWVRn(4, debug_state->uds.ds64.wvr[4]); + SET_DBGWCRn(4, (uint64_t)debug_state->uds.ds64.wcr[4], all_ctrls); case 4: - __asm__ volatile("msr DBGWVR3_EL1, %0" : : "r"(debug_state->uds.ds64.wvr[3])); - __asm__ volatile("msr DBGWCR3_EL1, %0" : : "r"(debug_state->uds.ds64.wcr[3])); + SET_DBGWVRn(3, debug_state->uds.ds64.wvr[3]); + SET_DBGWCRn(3, (uint64_t)debug_state->uds.ds64.wcr[3], all_ctrls); case 3: - __asm__ volatile("msr DBGWVR2_EL1, %0" : : "r"(debug_state->uds.ds64.wvr[2])); - __asm__ volatile("msr DBGWCR2_EL1, %0" : : "r"(debug_state->uds.ds64.wcr[2])); + SET_DBGWVRn(2, debug_state->uds.ds64.wvr[2]); + SET_DBGWCRn(2, (uint64_t)debug_state->uds.ds64.wcr[2], all_ctrls); case 2: - __asm__ volatile("msr DBGWVR1_EL1, %0" : : "r"(debug_state->uds.ds64.wvr[1])); - __asm__ volatile("msr DBGWCR1_EL1, %0" : : "r"(debug_state->uds.ds64.wcr[1])); + SET_DBGWVRn(1, debug_state->uds.ds64.wvr[1]); + SET_DBGWCRn(1, (uint64_t)debug_state->uds.ds64.wcr[1], all_ctrls); case 1: - __asm__ volatile("msr DBGWVR0_EL1, %0" : : "r"(debug_state->uds.ds64.wvr[0])); - __asm__ volatile("msr DBGWCR0_EL1, %0" : : "r"(debug_state->uds.ds64.wcr[0])); + SET_DBGWVRn(0, debug_state->uds.ds64.wvr[0]); + SET_DBGWCRn(0, (uint64_t)debug_state->uds.ds64.wcr[0], all_ctrls); default: break; } +#if defined(CONFIG_KERNEL_INTEGRITY) + if ((all_ctrls & (ARM_DBG_CR_MODE_CONTROL_PRIVILEGED | ARM_DBG_CR_HIGHER_MODE_ENABLE)) != 0) { + panic("sorry, self-hosted debug is not supported: 0x%llx", all_ctrls); + } +#endif + for (i = 0; i < debug_info->num_breakpoint_pairs; i++) { if (0 != debug_state->uds.ds64.bcr[i]) { set_mde = 1; @@ -697,11 +751,7 @@ void arm_debug_set64(arm_debug_state_t *debug_state) * Breakpoint/Watchpoint Enable */ if (set_mde) { - - __asm__ volatile("mrs %0, MDSCR_EL1" : "=r"(state)); - state |= 0x8000; // MDSCR_EL1[MDE] - __asm__ volatile("msr MDSCR_EL1, %0" : : "r"(state)); - + update_mdscr(0, 0x8000); // MDSCR_EL1[MDE] } /* @@ -709,18 +759,14 @@ void arm_debug_set64(arm_debug_state_t *debug_state) */ if (debug_state->uds.ds64.mdscr_el1 & 0x1) { - __asm__ volatile("mrs %0, MDSCR_EL1" : "=r"(state)); - state = (state & ~0x8000) | 0x1; // ~MDE | SS : no brk/watch while single stepping (which we've set) - __asm__ volatile("msr MDSCR_EL1, %0" : : "r"(state)); + update_mdscr(0x8000, 1); // ~MDE | SS : no brk/watch while single stepping (which we've set) set_saved_state_cpsr((current_thread()->machine.upcb), get_saved_state_cpsr((current_thread()->machine.upcb)) | PSR64_SS); } else { - __asm__ volatile("mrs %0, MDSCR_EL1" : "=r"(state)); - state &= ~0x1; - __asm__ volatile("msr MDSCR_EL1, %0" : : "r"(state)); + update_mdscr(0x1, 0); #if SINGLE_STEP_RETIRE_ERRATA // Workaround for radar 20619637 diff --git a/osfmk/arm64/platform_tests.c b/osfmk/arm64/platform_tests.c index d5391b327..61b627419 100644 --- a/osfmk/arm64/platform_tests.c +++ b/osfmk/arm64/platform_tests.c @@ -425,6 +425,7 @@ static kern_return_t lt_test_trylocks() { boolean_t success; + extern unsigned int real_ncpus; /* * First mtx try lock succeeds, second fails. @@ -512,9 +513,15 @@ lt_test_trylocks() lt_start_trylock_thread(lt_trylock_hw_lock_with_to); success = hw_lock_to(<_hw_lock, 100); T_ASSERT_NOTNULL(success, "First spin lock with timeout should succeed"); + if (real_ncpus == 1) { + mp_enable_preemption(); /* if we re-enable preemption, the other thread can timeout and exit */ + } OSIncrementAtomic((volatile SInt32*)<_thread_lock_grabbed); lt_wait_for_lock_test_threads(); T_ASSERT_NULL(lt_thread_lock_success, "Second spin lock with timeout should fail and timeout"); + if (real_ncpus == 1) { + mp_disable_preemption(); /* don't double-enable when we unlock */ + } hw_lock_unlock(<_hw_lock); lt_reset(); @@ -524,9 +531,15 @@ lt_test_trylocks() OSMemoryBarrier(); lt_start_trylock_thread(lt_trylock_hw_lock_with_to); hw_lock_lock(<_hw_lock); + if (real_ncpus == 1) { + mp_enable_preemption(); /* if we re-enable preemption, the other thread can timeout and exit */ + } OSIncrementAtomic((volatile SInt32*)<_thread_lock_grabbed); lt_wait_for_lock_test_threads(); T_ASSERT_NULL(lt_thread_lock_success, "after taking a spin lock, lock attempt with timeout should fail"); + if (real_ncpus == 1) { + mp_disable_preemption(); /* don't double-enable when we unlock */ + } hw_lock_unlock(<_hw_lock); success = lck_spin_try_lock(<_lck_spin_t); @@ -541,9 +554,15 @@ lt_test_trylocks() lt_target_done_threads = 1; lt_start_trylock_thread(lt_trylock_spin_try_lock); lck_spin_lock(<_lck_spin_t); + if (real_ncpus == 1) { + mp_enable_preemption(); /* if we re-enable preemption, the other thread can timeout and exit */ + } OSIncrementAtomic((volatile SInt32*)<_thread_lock_grabbed); lt_wait_for_lock_test_threads(); T_ASSERT_NULL(lt_thread_lock_success, "spin trylock attempt of previously held lock should fail"); + if (real_ncpus == 1) { + mp_disable_preemption(); /* don't double-enable when we unlock */ + } lck_spin_unlock(<_lck_spin_t); return KERN_SUCCESS; diff --git a/osfmk/arm64/proc_reg.h b/osfmk/arm64/proc_reg.h index ce62e62bd..a6971fa74 100644 --- a/osfmk/arm64/proc_reg.h +++ b/osfmk/arm64/proc_reg.h @@ -518,8 +518,6 @@ * Aff1 Cluster ID * Aff0 CPU ID */ -#define MPIDR_PNE_SHIFT 16 // pcore not ecore -#define MPIDR_PNE (1 << MPIDR_PNE_SHIFT) #define MPIDR_AFF0_MASK 0xFF #define MPIDR_AFF1_MASK 0xFF00 #define MPIDR_AFF2_MASK 0xFF0000 diff --git a/osfmk/arm64/sleh.c b/osfmk/arm64/sleh.c index 6e65c7598..cf022d32f 100644 --- a/osfmk/arm64/sleh.c +++ b/osfmk/arm64/sleh.c @@ -154,8 +154,6 @@ unix_syscall(struct arm_saved_state * regs, thread_t thread_act, extern void mach_syscall(struct arm_saved_state*); -volatile perfCallback perfTrapHook = NULL; /* Pointer to CHUD trap hook routine */ - #if CONFIG_DTRACE extern kern_return_t dtrace_user_probe(arm_saved_state_t* regs); extern boolean_t dtrace_tally_fault(user_addr_t); @@ -498,7 +496,7 @@ sleh_synchronous(arm_context_t *context, uint32_t esr, vm_offset_t far) break; case ESR_EC_BKPT_REG_MATCH_EL1: - if (FSC_DEBUG_FAULT == ISS_SSDE_FSC(esr)) { + if (!PE_i_can_has_debugger(NULL) && FSC_DEBUG_FAULT == ISS_SSDE_FSC(esr)) { kprintf("Hardware Breakpoint Debug exception from kernel. Hanging here (by design).\n"); for (;;); @@ -523,7 +521,7 @@ sleh_synchronous(arm_context_t *context, uint32_t esr, vm_offset_t far) break; case ESR_EC_SW_STEP_DEBUG_EL1: - if (FSC_DEBUG_FAULT == ISS_SSDE_FSC(esr)) { + if (!PE_i_can_has_debugger(NULL) && FSC_DEBUG_FAULT == ISS_SSDE_FSC(esr)) { kprintf("Software Step Debug exception from kernel. Hanging here (by design).\n"); for (;;); diff --git a/osfmk/arm64/start.s b/osfmk/arm64/start.s index ad181f705..24a6dba7f 100644 --- a/osfmk/arm64/start.s +++ b/osfmk/arm64/start.s @@ -713,16 +713,25 @@ common_start: mov x0, #0 msr TPIDR_EL1, x0 // Set thread register +#if defined(APPLE_ARM64_ARCH_FAMILY) + // Initialization common to all Apple targets + ARM64_IS_PCORE x15 + ARM64_READ_EP_SPR x15, x12, ARM64_REG_EHID4, ARM64_REG_HID4 + orr x12, x12, ARM64_REG_HID4_DisDcMVAOps + orr x12, x12, ARM64_REG_HID4_DisDcSWL2Ops + ARM64_WRITE_EP_SPR x15, x12, ARM64_REG_EHID4, ARM64_REG_HID4 +#endif // APPLE_ARM64_ARCH_FAMILY + #if defined(APPLECYCLONE) || defined(APPLETYPHOON) // // Cyclone/Typhoon-Specific initialization - // For tunable summary, see Alcatraz/H6: Confirm Cyclone CPU tunables have been set + // For tunable summary, see // // // Disable LSP flush with context switch to work around bug in LSP // that can cause Cyclone to wedge when CONTEXTIDR is written. - // Innsbruck11A175: panic(cpu 0 caller 0xffffff800024e30c): "wait queue deadlock - wq=0xffffff805a7a63c0, cpu=0\n" + // // mrs x12, ARM64_REG_HID0 @@ -740,15 +749,6 @@ common_start: orr x12, x12, ARM64_REG_HID3_DisXmonSnpEvictTriggerL2StarvationMode msr ARM64_REG_HID3, x12 - // Do not disable cache ops -- XNU's cache operations already are no-op'ed for Cyclone, but explicit _Force variants are provided - // for when we really do need the L2 cache to be cleaned: Innsbruck11A416: Panic logs not preserved on h6 -/* - mrs x12, ARM64_REG_HID4 - orr x12, x12, ARM64_REG_HID4_DisDcMVAOps - orr x12, x12, ARM64_REG_HID4_DisDcSWL2Ops - msr ARM64_REG_HID4, x12 -*/ - mrs x12, ARM64_REG_HID5 and x12, x12, (~ARM64_REG_HID5_DisHwpLd) and x12, x12, (~ARM64_REG_HID5_DisHwpSt) @@ -765,20 +765,37 @@ common_start: #endif // APPLECYCLONE || APPLETYPHOON #if defined(APPLETWISTER) - mrs x12, ARM64_REG_HID11 - and x12, x12, (~ARM64_REG_HID11_DisFillC1BubOpt) - msr ARM64_REG_HID11, x12 + + // rdar://problem/36112905: Set CYC_CFG:skipInit to pull in isAlive by one DCLK + // to work around potential hang. Must only be applied to Maui C0. + mrs x12, MIDR_EL1 + ubfx x13, x12, #MIDR_EL1_PNUM_SHIFT, #12 + cmp x13, #4 // Part number 4 => Maui, 5 => Malta/Elba + bne Lskip_isalive + ubfx x13, x12, #MIDR_EL1_VAR_SHIFT, #4 + cmp x13, #2 // variant 2 => Maui C0 + b.lt Lskip_isalive + + mrs x12, ARM64_REG_CYC_CFG + orr x12, x12, ARM64_REG_CYC_CFG_skipInit + msr ARM64_REG_CYC_CFG, x12 + +Lskip_isalive: + + mrs x12, ARM64_REG_HID11 + and x12, x12, (~ARM64_REG_HID11_DisFillC1BubOpt) + msr ARM64_REG_HID11, x12 // Change the default memcache data set ID from 0 to 15 for all agents mrs x12, ARM64_REG_HID8 orr x12, x12, (ARM64_REG_HID8_DataSetID0_VALUE | ARM64_REG_HID8_DataSetID1_VALUE) - orr x12, x12, (ARM64_REG_HID8_DataSetID2_VALUE | ARM64_REG_HID8_DataSetID3_VALUE) + orr x12, x12, (ARM64_REG_HID8_DataSetID2_VALUE | ARM64_REG_HID8_DataSetID3_VALUE) msr ARM64_REG_HID8, x12 // Use 4-cycle MUL latency to avoid denormal stalls - mrs x12, ARM64_REG_HID7 - orr x12, x12, #ARM64_REG_HID7_disNexFastFmul - msr ARM64_REG_HID7, x12 + mrs x12, ARM64_REG_HID7 + orr x12, x12, #ARM64_REG_HID7_disNexFastFmul + msr ARM64_REG_HID7, x12 // disable reporting of TLB-multi-hit-error // @@ -814,7 +831,6 @@ common_start: #if defined(ARM64_BOARD_CONFIG_T8011) // Clear DisDcZvaCmdOnly // Per Myst A0/B0 tunables document - // https://seg-docs.csg.apple.com/projects/myst//release/UserManual/tunables_a0/ACC.html // Myst: Confirm ACC Per-CPU Tunables mrs x12, ARM64_REG_HID3 and x12, x12, ~ARM64_REG_HID3_DisDcZvaCmdOnly diff --git a/osfmk/atm/atm.c b/osfmk/atm/atm.c index 009035687..fcf59e3d3 100644 --- a/osfmk/atm/atm.c +++ b/osfmk/atm/atm.c @@ -725,11 +725,9 @@ atm_send_user_notification( return KERN_FAILURE; } - /* Set the honor queue limit option on the thread. */ - th->options |= TH_OPT_HONOR_QLIMIT; + thread_set_honor_qlimit(th); kr = atm_collect_trace_info(user_port, aid, sub_aid, flags, buffers_array, count, sizes_array, count); - /* Make sure that honor queue limit option is unset on the thread. */ - th->options &= (~TH_OPT_HONOR_QLIMIT); + thread_clear_honor_qlimit(th); if (kr != KERN_SUCCESS) { ipc_port_release_send(user_port); @@ -793,11 +791,9 @@ atm_send_proc_inspect_notification( return KERN_FAILURE; } - /* Set the honor queue limit option on the thread. */ - th->options |= TH_OPT_HONOR_QLIMIT; + thread_set_honor_qlimit(th); kr = atm_inspect_process_buffer(user_port, traced_pid, traced_uniqueid, buffer_size, memory_port); - /* Make sure that honor queue limit option is unset on the thread. */ - th->options &= (~TH_OPT_HONOR_QLIMIT); + thread_clear_honor_qlimit(th); if (kr != KERN_SUCCESS) { ipc_port_release_send(user_port); diff --git a/osfmk/chud/chud_cpu.c b/osfmk/chud/chud_cpu.c deleted file mode 100644 index c21a40eb2..000000000 --- a/osfmk/chud/chud_cpu.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2003-2007 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -#include -#include - -#include -#include -#include -#include -#include - -#include - -#if 0 -#pragma mark **** cpu count **** -#endif - -__private_extern__ int -chudxnu_logical_cpu_count(void) -{ - return machine_info.logical_cpu_max; -} - -__private_extern__ int -chudxnu_phys_cpu_count(void) -{ - host_basic_info_data_t hinfo; - kern_return_t kr; - mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT; - - kr = host_info(host_self(), HOST_BASIC_INFO, (integer_t *)&hinfo, &count); - if(kr == KERN_SUCCESS) { - return hinfo.max_cpus; - } else { - return 1; // fall back to 1, 0 doesn't make sense at all - } -} - -__private_extern__ int -chudxnu_cpu_number(void) -{ - return cpu_number(); -} - -#if 0 -#pragma mark **** interrupts enable/disable **** -#endif - -__private_extern__ boolean_t -chudxnu_set_interrupts_enabled(boolean_t enable) -{ - return ml_set_interrupts_enabled(enable); -} - -__private_extern__ void -chudxnu_cause_interrupt(void) -{ - ml_cause_interrupt(); -} - -#if 0 -#pragma mark **** preemption enable/disable **** -#endif - -__private_extern__ void -chudxnu_enable_preemption(void) -{ - enable_preemption(); -} - -__private_extern__ void -chudxnu_disable_preemption(void) -{ - disable_preemption(); -} - -__private_extern__ int -chudxnu_get_preemption_level(void) -{ - return get_preemption_level(); -} - diff --git a/osfmk/chud/chud_glue.c b/osfmk/chud/chud_glue.c deleted file mode 100644 index a721a7313..000000000 --- a/osfmk/chud/chud_glue.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2003-2007 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -void *chudxnu_platform_ptr(void); - -void * -chudxnu_platform_ptr(void) -{ - return (void *)0; -} - - diff --git a/osfmk/chud/chud_memory.c b/osfmk/chud/chud_memory.c deleted file mode 100644 index 21209b074..000000000 --- a/osfmk/chud/chud_memory.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2003-2007 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#include -#include -#include - -extern unsigned int IODefaultCacheBits(addr64_t pa); -extern unsigned int vm_page_free_count; -extern unsigned int vm_page_inactive_count; - -__private_extern__ uint64_t -chudxnu_avail_memory_size(void) -{ - return max_mem; -} - -__private_extern__ uint64_t -chudxnu_phys_memory_size(void) -{ - return mem_actual; -} - -/* - * This function is not intended to be valid for any amount of time, - * it is just an instantaneous snapshot of the current free memory size. - */ -__private_extern__ -uint64_t chudxnu_free_memory_size(void) -{ - return (uint64_t)vm_page_free_count * (uint64_t)page_size; -} - -/* - * This function is not intended to be valid for any amount of time, - * it is just an instantaneous snapshot of the current inactive memory size. - */ -__private_extern__ -uint64_t chudxnu_inactive_memory_size(void) -{ - return (uint64_t)vm_page_inactive_count * (uint64_t)page_size; -} - diff --git a/osfmk/chud/chud_osfmk_callback.c b/osfmk/chud/chud_osfmk_callback.c deleted file mode 100644 index 98e1fcee1..000000000 --- a/osfmk/chud/chud_osfmk_callback.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2003-2007 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include - -#if 0 -#pragma mark **** timer **** -#endif - -__private_extern__ chud_timer_t -chudxnu_timer_alloc(chudxnu_timer_callback_func_t func, thread_call_param_t param0) -{ - return (chud_timer_t)thread_call_allocate((thread_call_func_t)func, param0); -} - -__private_extern__ kern_return_t -chudxnu_timer_callback_enter( - chud_timer_t timer, - thread_call_param_t param1, - uint32_t time, - uint32_t units) -{ - uint64_t t_delay; - clock_interval_to_deadline(time, units, &t_delay); - thread_call_enter1_delayed((thread_call_t)timer, param1, t_delay); - return KERN_SUCCESS; -} - -__private_extern__ kern_return_t -chudxnu_timer_callback_cancel(chud_timer_t timer) -{ - thread_call_cancel((thread_call_t)timer); - return KERN_SUCCESS; -} - -__private_extern__ kern_return_t -chudxnu_timer_free(chud_timer_t timer) -{ - thread_call_cancel((thread_call_t)timer); - thread_call_free((thread_call_t)timer); - return KERN_SUCCESS; -} - - diff --git a/osfmk/chud/chud_thread.c b/osfmk/chud/chud_thread.c deleted file mode 100644 index 2b804af7a..000000000 --- a/osfmk/chud/chud_thread.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2003-2009 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include - -#if KPC -#include -#endif - -#if KPERF -#include -#endif - -// include the correct file to find real_ncpus -#if defined(__i386__) || defined(__x86_64__) -# include -#elif defined(__arm__) || defined (__arm64__) -# include -#else -// fall back on declaring it extern. The linker will sort us out. -extern unsigned int real_ncpus; -#endif - -// Mask for supported options -#define T_CHUD_BIND_OPT_MASK (-1UL) - -#if 0 -#pragma mark **** thread binding **** -#endif - -/* - * This method will bind a given thread to the requested CPU starting at the - * next time quantum. If the thread is the current thread, this method will - * force a thread_block(). The result is that if you call this method on the - * current thread, you will be on the requested CPU when this method returns. - */ -__private_extern__ kern_return_t -chudxnu_bind_thread(thread_t thread, int cpu, __unused int options) -{ - processor_t proc = NULL; - - if(cpu < 0 || (unsigned int)cpu >= real_ncpus) // sanity check - return KERN_FAILURE; - - // temporary restriction until after phase 2 of the scheduler - if(thread != current_thread()) - return KERN_FAILURE; - - proc = cpu_to_processor(cpu); - - /* - * Potentially racey, but mainly to prevent bind to shutdown - * processor. - */ - if(proc && !(proc->state == PROCESSOR_OFF_LINE) && - !(proc->state == PROCESSOR_SHUTDOWN)) { - - thread_bind(proc); - - /* - * If we're trying to bind the current thread, and - * we're not on the target cpu, and not at interrupt - * context, block the current thread to force a - * reschedule on the target CPU. - */ - if(thread == current_thread() && - !ml_at_interrupt_context() && cpu_number() != cpu) { - (void)thread_block(THREAD_CONTINUE_NULL); - } - return KERN_SUCCESS; - } - return KERN_FAILURE; -} - -__private_extern__ kern_return_t -chudxnu_unbind_thread(thread_t thread, __unused int options) -{ - if(thread == current_thread()) - thread_bind(PROCESSOR_NULL); - return KERN_SUCCESS; -} diff --git a/osfmk/chud/chud_thread.h b/osfmk/chud/chud_thread.h deleted file mode 100644 index 86976de11..000000000 --- a/osfmk/chud/chud_thread.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2007-2009 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#ifndef _CHUD_THREAD_H_ -#define _CHUD_THREAD_H_ - - -#include - -#endif /* _CHUD_THREAD_H_ */ diff --git a/osfmk/chud/chud_xnu.h b/osfmk/chud/chud_xnu.h deleted file mode 100644 index 56c7e6591..000000000 --- a/osfmk/chud/chud_xnu.h +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) 2003-2008 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#ifndef _CHUD_XNU_H_ -#define _CHUD_XNU_H_ - -#include -#include -#include -#include - -/* Unslide the provided pointer if it's a kernel address. */ -static inline uint64_t -chudxnu_vm_unslide( uint64_t ptr, int kaddr ) -{ - if( !kaddr ) - return ptr; - - return VM_KERNEL_UNSLIDE(ptr); -} - -#if 0 -#pragma mark **** version **** -#endif -extern uint32_t chudxnu_version(void); - -#if 0 -#pragma mark **** task **** -#endif -// ******************************************************************************** -// task -// ******************************************************************************** -extern kern_return_t chudxnu_task_read(task_t task, void *kernaddr, uint64_t usraddr, vm_size_t size); -extern kern_return_t chudxnu_task_write(task_t task, uint64_t useraddr, void *kernaddr, vm_size_t size); -extern kern_return_t chudxnu_kern_read(void *destaddr, vm_offset_t srcaddr, vm_size_t size); -extern kern_return_t chudxnu_kern_write(vm_offset_t destaddr, void *srcaddr, vm_size_t size); - -extern boolean_t chudxnu_is_64bit_task(task_t task); - -#if 0 -#pragma mark **** thread **** -#endif -// ******************************************************************************** -// thread -// ******************************************************************************** -extern kern_return_t chudxnu_bind_thread(thread_t thread, int cpu, int options); -extern kern_return_t chudxnu_unbind_thread(thread_t thread, int options); - -extern kern_return_t chudxnu_thread_get_state(thread_t thread, thread_flavor_t flavor, thread_state_t tstate, mach_msg_type_number_t *count, boolean_t user_only); -extern kern_return_t chudxnu_thread_set_state(thread_t thread, thread_flavor_t flavor, thread_state_t tstate, mach_msg_type_number_t count, boolean_t user_only); - -extern kern_return_t chudxnu_thread_get_callstack64(thread_t thread, uint64_t *callStack, mach_msg_type_number_t *count, boolean_t user_only); -extern kern_return_t chudxnu_thread_get_callstack64_kperf(thread_t thread, uint64_t *callStack, mach_msg_type_number_t *count, boolean_t user_only); - -#if 0 -#pragma mark **** memory **** -#endif -// ******************************************************************************** -// memory -// ******************************************************************************** - -extern uint64_t chudxnu_avail_memory_size(void); -extern uint64_t chudxnu_phys_memory_size(void); -extern uint64_t chudxnu_free_memory_size(void); -extern uint64_t chudxnu_inactive_memory_size(void); - -#if 0 -#pragma mark **** cpu **** -#endif -// ******************************************************************************** -// cpu -// ******************************************************************************** -extern int chudxnu_logical_cpu_count(void); -extern int chudxnu_phys_cpu_count(void); -extern int chudxnu_cpu_number(void); - -extern kern_return_t chudxnu_enable_cpu(int cpu, boolean_t enable); - -extern boolean_t chudxnu_set_interrupts_enabled(boolean_t enable); -extern void chudxnu_cause_interrupt(void); - -extern void chudxnu_enable_preemption(void); -extern void chudxnu_disable_preemption(void); -extern int chudxnu_get_preemption_level(void); - -extern kern_return_t chudxnu_perfmon_acquire_facility(task_t); -extern kern_return_t chudxnu_perfmon_release_facility(task_t); - -typedef struct { - uint32_t hwResets; - uint32_t hwMachineChecks; - uint32_t hwDSIs; - uint32_t hwISIs; - uint32_t hwExternals; - uint32_t hwAlignments; - uint32_t hwPrograms; - uint32_t hwFloatPointUnavailable; - uint32_t hwDecrementers; - uint32_t hwIOErrors; - uint32_t hwSystemCalls; - uint32_t hwTraces; - uint32_t hwFloatingPointAssists; - uint32_t hwPerformanceMonitors; - uint32_t hwAltivecs; - uint32_t hwInstBreakpoints; - uint32_t hwSystemManagements; - uint32_t hwAltivecAssists; - uint32_t hwThermal; - uint32_t hwSoftPatches; - uint32_t hwMaintenances; - uint32_t hwInstrumentations; -} interrupt_counters_t; - -extern kern_return_t chudxnu_get_cpu_interrupt_counters(int cpu, interrupt_counters_t *rupts); -extern kern_return_t chudxnu_clear_cpu_interrupt_counters(int cpu); - -#if 0 -#pragma mark **** callbacks **** -#endif -// ******************************************************************************** -// callbacks -// ******************************************************************************** - -extern void chudxnu_cancel_all_callbacks(void); - -// cpu timer - each cpu has its own callback -typedef kern_return_t (*chudxnu_cpu_timer_callback_func_t)(thread_flavor_t flavor, thread_state_t tstate, mach_msg_type_number_t count); -extern kern_return_t chudxnu_cpu_timer_callback_enter(chudxnu_cpu_timer_callback_func_t func, uint32_t time, uint32_t units); // callback is entered on current cpu -extern kern_return_t chudxnu_cpu_timer_callback_cancel(void); // callback is cleared on current cpu -extern kern_return_t chudxnu_cpu_timer_callback_cancel_all(void); // callback is cleared on all cpus - -enum { - PPC_TRAP_PROGRAM = 0x700, - PPC_TRAP_TRACE = 0xD00, - PPC_TRAP_PERFMON = 0xF00, -}; - -enum { - X86_TRAP_DEBUG = 0x1, -}; - -// trap callback - one callback for system -typedef kern_return_t (*chudxnu_trap_callback_func_t)(uint32_t trapentry, thread_flavor_t flavor, thread_state_t tstate, mach_msg_type_number_t count); -extern kern_return_t chudxnu_trap_callback_enter(chudxnu_trap_callback_func_t func); -extern kern_return_t chudxnu_trap_callback_cancel(void); - -enum { - PPC_INTERRUPT_DECREMENTER = 0x900, - PPC_INTERRUPT_INTERRUPT = 0x500, - PPC_INTERRUPT_CPU_SIGNAL = 0x2200, -}; - -enum { - X86_INTERRUPT_PERFMON = 0xB, -}; - -// interrupt callback - one callback for system -typedef kern_return_t (*chudxnu_interrupt_callback_func_t)(uint32_t trapentry, thread_flavor_t flavor, thread_state_t tstate, mach_msg_type_number_t count); -extern kern_return_t chudxnu_interrupt_callback_enter(chudxnu_interrupt_callback_func_t func); -extern kern_return_t chudxnu_interrupt_callback_cancel(void); - -// ast callback - one callback for system -typedef kern_return_t (*chudxnu_perfmon_ast_callback_func_t)(thread_flavor_t flavor, thread_state_t tstate, mach_msg_type_number_t count); -extern kern_return_t chudxnu_perfmon_ast_callback_enter(chudxnu_perfmon_ast_callback_func_t func); -extern kern_return_t chudxnu_perfmon_ast_callback_cancel(void); -extern kern_return_t chudxnu_perfmon_ast_send_urgent(boolean_t urgent); - -// cpusig callback - one callback for system -typedef kern_return_t (*chudxnu_cpusig_callback_func_t)(int request, thread_flavor_t flavor, thread_state_t tstate, mach_msg_type_number_t count); -extern kern_return_t chudxnu_cpusig_callback_enter(chudxnu_cpusig_callback_func_t func); -extern kern_return_t chudxnu_cpusig_callback_cancel(void); -extern kern_return_t chudxnu_cpusig_send(int otherCPU, uint32_t request); - -// kdebug callback - one callback for system -typedef kern_return_t (*chudxnu_kdebug_callback_func_t)(uint32_t debugid, uintptr_t arg0, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4); -extern kern_return_t chudxnu_kdebug_callback_enter(chudxnu_kdebug_callback_func_t func); -extern kern_return_t chudxnu_kdebug_callback_cancel(void); - -// timer callback - multiple callbacks -typedef kern_return_t (*chudxnu_timer_callback_func_t)(thread_call_param_t param0, thread_call_param_t param1); -typedef void * chud_timer_t; -extern chud_timer_t chudxnu_timer_alloc(chudxnu_timer_callback_func_t func, thread_call_param_t param0); -extern kern_return_t chudxnu_timer_callback_enter(chud_timer_t timer, thread_call_param_t param1, uint32_t time, uint32_t units); -extern kern_return_t chudxnu_timer_callback_cancel(chud_timer_t timer); -extern kern_return_t chudxnu_timer_free(chud_timer_t timer); - -// CHUD systemcall callback - one callback for system -typedef kern_return_t (*chudxnu_syscall_callback_func_t)(uint64_t code, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5); -extern kern_return_t chudxnu_syscall_callback_enter(chudxnu_syscall_callback_func_t func); -extern kern_return_t chudxnu_syscall_callback_cancel(void); - -// ******************************************************************************** -// DEPRECATED -// ******************************************************************************** -extern kern_return_t chudxnu_thread_get_callstack(thread_t thread, uint32_t *callStack, mach_msg_type_number_t *count, boolean_t user_only); - -extern kern_return_t chudxnu_set_shadowed_spr(int cpu, int spr, uint32_t val); -extern kern_return_t chudxnu_set_shadowed_spr64(int cpu, int spr, uint64_t val); - -extern kern_return_t chudxnu_enable_cpu_nap(int cpu, boolean_t enable); -extern boolean_t chudxnu_cpu_nap_enabled(int cpu); - -extern kern_return_t chudxnu_read_spr(int cpu, int spr, uint32_t *val_p); -extern kern_return_t chudxnu_read_spr64(int cpu, int spr, uint64_t *val_p); -extern kern_return_t chudxnu_write_spr(int cpu, int spr, uint32_t val); -extern kern_return_t chudxnu_write_spr64(int cpu, int spr, uint64_t val); - -#endif /* _CHUD_XNU_H_ */ diff --git a/osfmk/chud/chud_xnu_glue.h b/osfmk/chud/chud_xnu_glue.h deleted file mode 100644 index f595ffef4..000000000 --- a/osfmk/chud/chud_xnu_glue.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2003-2007 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#if defined (__i386__) || defined (__x86_64__) -#include "i386/chud_xnu_glue.h" -#elif defined (__arm__)|| defined (__arm64__) -#include "arm/chud_xnu_glue.h" -#else -#error architecture not supported -#endif diff --git a/osfmk/chud/chud_xnu_private.h b/osfmk/chud/chud_xnu_private.h deleted file mode 100644 index 5a712aceb..000000000 --- a/osfmk/chud/chud_xnu_private.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2003-2007 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#ifndef _CHUD_XNU_PRIVATE_H_ -#define _CHUD_XNU_PRIVATE_H_ - -#include -#include -#include - -#if defined (__i386__) || defined (__x86_64__) -#include "chud/i386/chud_xnu_private.h" -#elif defined (__arm__) || defined (__arm64__) -#include "chud/arm/chud_xnu_private.h" -#else -#error architecture not supported -#endif - -#endif /* _CHUD_XNU_PRIVATE_H_ */ diff --git a/osfmk/chud/i386/chud_cpu_i386.c b/osfmk/chud/i386/chud_cpu_i386.c deleted file mode 100644 index 564a82c4a..000000000 --- a/osfmk/chud/i386/chud_cpu_i386.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2003-2009 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#if 0 -#pragma mark **** cpu enable/disable **** -#endif - -extern kern_return_t processor_start(processor_t processor); // osfmk/kern/processor.c -extern kern_return_t processor_exit(processor_t processor); // osfmk/kern/processor.c - -__private_extern__ -kern_return_t chudxnu_enable_cpu(int cpu, boolean_t enable) -{ - chudxnu_unbind_thread(current_thread(), 0); - - if(cpu < 0 || (unsigned int)cpu >= real_ncpus) // sanity check - return KERN_FAILURE; - - if((cpu_data_ptr[cpu] != NULL) && cpu != master_cpu) { - processor_t processor = cpu_to_processor(cpu); - - if(processor == master_processor) // don't mess with the boot processor - return KERN_FAILURE; - - if(enable) { - return processor_start(processor); - } else { - return processor_exit(processor); - } - } - return KERN_FAILURE; -} - -#if 0 -#pragma mark **** perfmon facility **** -#endif - -__private_extern__ kern_return_t -chudxnu_perfmon_acquire_facility(task_t task __unused) -{ - return KERN_SUCCESS; -} - -__private_extern__ kern_return_t -chudxnu_perfmon_release_facility(task_t task __unused) -{ - return KERN_SUCCESS; -} - -#if 0 -#pragma mark **** interrupt counters **** -#endif - -__private_extern__ kern_return_t -chudxnu_get_cpu_interrupt_counters(int cpu, interrupt_counters_t *rupts) -{ - if(cpu < 0 || (unsigned int)cpu >= real_ncpus) { // sanity check - return KERN_FAILURE; - } - - if(rupts) { - boolean_t oldlevel = ml_set_interrupts_enabled(FALSE); - cpu_data_t *per_proc; - - per_proc = cpu_data_ptr[cpu]; - // For now, we'll call an NMI a 'reset' interrupt - rupts->hwResets = per_proc->cpu_hwIntCnt[T_NMI]; - rupts->hwMachineChecks = per_proc->cpu_hwIntCnt[T_MACHINE_CHECK]; - rupts->hwDSIs = 0; - rupts->hwISIs = 0; - // we could accumulate 0x20-0x7f, but that'd likely overflow... - rupts->hwExternals = 0; - // This appears to be wrong. - rupts->hwAlignments = 0; //per_proc->cpu_hwIntCnt[0x11]; - rupts->hwPrograms = 0; - rupts->hwFloatPointUnavailable = per_proc->cpu_hwIntCnt[T_NO_FPU]; - // osfmk/i386/mp.h - rupts->hwDecrementers = per_proc->cpu_hwIntCnt[LAPIC_VECTOR(TIMER)]; - // LAPIC_ERROR == IO ERROR?? - rupts->hwIOErrors = per_proc->cpu_hwIntCnt[LAPIC_VECTOR(ERROR)]; - - // accumulate all system call types - // osfmk/mach/i386/syscall_sw.h - rupts->hwSystemCalls = per_proc->cpu_hwIntCnt[UNIX_INT] + - per_proc->cpu_hwIntCnt[MACH_INT] + - per_proc->cpu_hwIntCnt[MACHDEP_INT] + - per_proc->cpu_hwIntCnt[DIAG_INT]; - - rupts->hwTraces = per_proc->cpu_hwIntCnt[T_DEBUG]; // single steps == traces?? - rupts->hwFloatingPointAssists = 0; - // osfmk/i386/mp.h - rupts->hwPerformanceMonitors = - per_proc->cpu_hwIntCnt[LAPIC_VECTOR(PERFCNT)]; - rupts->hwAltivecs = 0; - rupts->hwInstBreakpoints = per_proc->cpu_hwIntCnt[T_INT3]; - rupts->hwSystemManagements = 0; - rupts->hwAltivecAssists = 0; - rupts->hwThermal = per_proc->cpu_hwIntCnt[LAPIC_VECTOR(THERMAL)]; - rupts->hwSoftPatches = 0; - rupts->hwMaintenances = 0; - // Watchpoint == instrumentation - rupts->hwInstrumentations = per_proc->cpu_hwIntCnt[T_WATCHPOINT]; - - ml_set_interrupts_enabled(oldlevel); - return KERN_SUCCESS; - } else { - return KERN_FAILURE; - } -} - -__private_extern__ kern_return_t -chudxnu_clear_cpu_interrupt_counters(int cpu) -{ - if(cpu < 0 || (unsigned int)cpu >= real_ncpus) { // sanity check - return KERN_FAILURE; - } - cpu_data_t *per_proc; - - per_proc = cpu_data_ptr[cpu]; - - bzero((char *)per_proc->cpu_hwIntCnt, sizeof(uint32_t)*256); - - return KERN_SUCCESS; -} - diff --git a/osfmk/chud/i386/chud_osfmk_callback_i386.c b/osfmk/chud/i386/chud_osfmk_callback_i386.c deleted file mode 100644 index f9b5243bc..000000000 --- a/osfmk/chud/i386/chud_osfmk_callback_i386.c +++ /dev/null @@ -1,516 +0,0 @@ -/* - * Copyright (c) 2003-2009 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include -#define CHUD_TIMER_CALLBACK_CANCEL 0 -#define CHUD_TIMER_CALLBACK_ENTER 1 -#define CHUD_TIMER_CALLBACK 2 -#define CHUD_AST_SEND 3 -#define CHUD_AST_CALLBACK 4 -#define CHUD_CPUSIG_SEND 5 -#define CHUD_CPUSIG_CALLBACK 6 - -__private_extern__ -void chudxnu_cancel_all_callbacks(void) -{ - chudxnu_cpusig_callback_cancel(); - chudxnu_cpu_timer_callback_cancel_all(); - chudxnu_interrupt_callback_cancel(); - chudxnu_perfmon_ast_callback_cancel(); -} - -static lck_grp_t chud_request_lck_grp; -static lck_grp_attr_t chud_request_lck_grp_attr; -static lck_attr_t chud_request_lck_attr; - - -static chudcpu_data_t chudcpu_boot_cpu; -void * -chudxnu_cpu_alloc(boolean_t boot_processor) -{ - chudcpu_data_t *chud_proc_info; - - if (boot_processor) { - chud_proc_info = &chudcpu_boot_cpu; - - lck_attr_setdefault(&chud_request_lck_attr); - lck_grp_attr_setdefault(&chud_request_lck_grp_attr); - lck_grp_init(&chud_request_lck_grp, "chud_request", &chud_request_lck_grp_attr); - - } else { - chud_proc_info = (chudcpu_data_t *) - kalloc(sizeof(chudcpu_data_t)); - if (chud_proc_info == (chudcpu_data_t *)NULL) { - return (void *)NULL; - } - } - bzero((char *)chud_proc_info, sizeof(chudcpu_data_t)); - chud_proc_info->t_deadline = 0xFFFFFFFFFFFFFFFFULL; - - mpqueue_init(&chud_proc_info->cpu_request_queue, &chud_request_lck_grp, &chud_request_lck_attr); - - /* timer_call_cancel() can be called before first usage, so init here: */ - timer_call_setup(&(chud_proc_info->cpu_timer_call), NULL, NULL); - - - return (void *)chud_proc_info; -} - -void -chudxnu_cpu_free(void *cp) -{ - if (cp == NULL || cp == (void *)&chudcpu_boot_cpu) { - return; - } else { - kfree(cp,sizeof(chudcpu_data_t)); - } -} - -static void -chudxnu_private_cpu_timer_callback( - timer_call_param_t param0, - timer_call_param_t param1) -{ -#pragma unused (param0) -#pragma unused (param1) - chudcpu_data_t *chud_proc_info; - boolean_t oldlevel; - x86_thread_state_t state; - mach_msg_type_number_t count; - chudxnu_cpu_timer_callback_func_t fn; - - oldlevel = ml_set_interrupts_enabled(FALSE); - chud_proc_info = (chudcpu_data_t *)(current_cpu_datap()->cpu_chud); - - count = x86_THREAD_STATE_COUNT; - if (chudxnu_thread_get_state(current_thread(), - x86_THREAD_STATE, - (thread_state_t)&state, - &count, - FALSE) == KERN_SUCCESS) { - fn = chud_proc_info->cpu_timer_callback_fn; - if (fn) { - (fn)( - x86_THREAD_STATE, - (thread_state_t)&state, - count); - } - } - - ml_set_interrupts_enabled(oldlevel); -} - -__private_extern__ kern_return_t -chudxnu_cpu_timer_callback_enter( - chudxnu_cpu_timer_callback_func_t func, - uint32_t time, - uint32_t units) -{ - chudcpu_data_t *chud_proc_info; - boolean_t oldlevel; - - oldlevel = ml_set_interrupts_enabled(FALSE); - chud_proc_info = (chudcpu_data_t *)(current_cpu_datap()->cpu_chud); - - // cancel any existing callback for this cpu - timer_call_cancel(&(chud_proc_info->cpu_timer_call)); - - chud_proc_info->cpu_timer_callback_fn = func; - - clock_interval_to_deadline(time, units, &(chud_proc_info->t_deadline)); - timer_call_setup(&(chud_proc_info->cpu_timer_call), - chudxnu_private_cpu_timer_callback, NULL); - timer_call_enter(&(chud_proc_info->cpu_timer_call), - chud_proc_info->t_deadline, - TIMER_CALL_SYS_CRITICAL|TIMER_CALL_LOCAL); - - ml_set_interrupts_enabled(oldlevel); - return KERN_SUCCESS; -} - -__private_extern__ kern_return_t -chudxnu_cpu_timer_callback_cancel(void) -{ - chudcpu_data_t *chud_proc_info; - boolean_t oldlevel; - - oldlevel = ml_set_interrupts_enabled(FALSE); - chud_proc_info = (chudcpu_data_t *)(current_cpu_datap()->cpu_chud); - - timer_call_cancel(&(chud_proc_info->cpu_timer_call)); - - // set to max value: - chud_proc_info->t_deadline |= ~(chud_proc_info->t_deadline); - chud_proc_info->cpu_timer_callback_fn = NULL; - - ml_set_interrupts_enabled(oldlevel); - return KERN_SUCCESS; -} - -__private_extern__ kern_return_t -chudxnu_cpu_timer_callback_cancel_all(void) -{ - unsigned int cpu; - chudcpu_data_t *chud_proc_info; - - for(cpu=0; cpu < real_ncpus; cpu++) { - chud_proc_info = (chudcpu_data_t *) cpu_data_ptr[cpu]->cpu_chud; - if (chud_proc_info == NULL) - continue; - timer_call_cancel(&(chud_proc_info->cpu_timer_call)); - chud_proc_info->t_deadline |= ~(chud_proc_info->t_deadline); - chud_proc_info->cpu_timer_callback_fn = NULL; - } - return KERN_SUCCESS; -} - -#if 0 -#pragma mark **** ast **** -#endif -static kern_return_t chud_null_ast(thread_flavor_t flavor, thread_state_t tstate, - mach_msg_type_number_t count); -static chudxnu_perfmon_ast_callback_func_t perfmon_ast_callback_fn = chud_null_ast; - -static kern_return_t chud_null_ast(thread_flavor_t flavor __unused, - thread_state_t tstate __unused, mach_msg_type_number_t count __unused) { - return KERN_FAILURE; -} - -static kern_return_t -chudxnu_private_chud_ast_callback(ast_t reasons, ast_t *myast) -{ - boolean_t oldlevel = ml_set_interrupts_enabled(FALSE); - kern_return_t retval = KERN_FAILURE; - chudxnu_perfmon_ast_callback_func_t fn = perfmon_ast_callback_fn; - - if (fn) { - if ((*myast & AST_CHUD_URGENT) && (reasons & (AST_URGENT | AST_CHUD_URGENT))) { // Only execute urgent callbacks if reasons specifies an urgent context. - *myast &= ~AST_CHUD_URGENT; - - if (AST_URGENT == *myast) { // If the only flag left is AST_URGENT, we can clear it; we know that we set it, but if there are also other bits set in reasons then someone else might still need AST_URGENT, so we'll leave it set. The normal machinery in ast_taken will ensure it gets cleared eventually, as necessary. - *myast = AST_NONE; - } - - retval = KERN_SUCCESS; - } - - if ((*myast & AST_CHUD) && (reasons & AST_CHUD)) { // Only execute non-urgent callbacks if reasons actually specifies AST_CHUD. This implies non-urgent callbacks since the only time this'll happen is if someone either calls ast_taken with AST_CHUD explicitly (not done at time of writing, but possible) or with AST_ALL, which of course includes AST_CHUD. - *myast &= ~AST_CHUD; - retval = KERN_SUCCESS; - } - - if (KERN_SUCCESS == retval) { - x86_thread_state_t state; - mach_msg_type_number_t count = x86_THREAD_STATE_COUNT; - thread_t thread = current_thread(); - - if (KERN_SUCCESS == chudxnu_thread_get_state(thread, - x86_THREAD_STATE, - (thread_state_t)&state, - &count, - (thread->task != kernel_task))) { - (fn)(x86_THREAD_STATE, (thread_state_t)&state, count); - } - } - } - - ml_set_interrupts_enabled(oldlevel); - return retval; -} - -volatile perfASTCallback perfASTHook; - -__private_extern__ kern_return_t -chudxnu_perfmon_ast_callback_enter(chudxnu_perfmon_ast_callback_func_t func) -{ - if(OSCompareAndSwapPtr(NULL, chudxnu_private_chud_ast_callback, - (void * volatile *)&perfASTHook)) { - chudxnu_perfmon_ast_callback_func_t old = perfmon_ast_callback_fn; - - while(!OSCompareAndSwapPtr(old, func, - (void * volatile *)&perfmon_ast_callback_fn)) { - old = perfmon_ast_callback_fn; - } - - return KERN_SUCCESS; - } - return KERN_FAILURE; -} - -__private_extern__ kern_return_t -chudxnu_perfmon_ast_callback_cancel(void) -{ - if(OSCompareAndSwapPtr(chudxnu_private_chud_ast_callback, NULL, - (void * volatile *)&perfASTHook)) { - chudxnu_perfmon_ast_callback_func_t old = perfmon_ast_callback_fn; - - while(!OSCompareAndSwapPtr(old, chud_null_ast, - (void * volatile *)&perfmon_ast_callback_fn)) { - old = perfmon_ast_callback_fn; - } - - return KERN_SUCCESS; - } - return KERN_FAILURE; -} - -__private_extern__ kern_return_t -chudxnu_perfmon_ast_send_urgent(boolean_t urgent) -{ - boolean_t oldlevel = ml_set_interrupts_enabled(FALSE); - ast_t *myast = ast_pending(); - - if(urgent) { - *myast |= (AST_CHUD_URGENT | AST_URGENT); - } else { - *myast |= (AST_CHUD); - } - - ml_set_interrupts_enabled(oldlevel); - return KERN_SUCCESS; -} - -#if 0 -#pragma mark **** interrupt **** -#endif -static kern_return_t chud_null_int(uint32_t trapentry, thread_flavor_t flavor, - thread_state_t tstate, mach_msg_type_number_t count); -static chudxnu_interrupt_callback_func_t interrupt_callback_fn = chud_null_int; - -static kern_return_t chud_null_int(uint32_t trapentry __unused, thread_flavor_t flavor __unused, - thread_state_t tstate __unused, mach_msg_type_number_t count __unused) { - return KERN_FAILURE; -} - -static void -chudxnu_private_interrupt_callback(void *foo) __attribute__((used)); - -static void -chudxnu_private_interrupt_callback(void *foo) -{ -#pragma unused (foo) - chudxnu_interrupt_callback_func_t fn = interrupt_callback_fn; - - if(fn) { - boolean_t oldlevel; - x86_thread_state_t state; - mach_msg_type_number_t count; - - oldlevel = ml_set_interrupts_enabled(FALSE); - - count = x86_THREAD_STATE_COUNT; - if(chudxnu_thread_get_state(current_thread(), - x86_THREAD_STATE, - (thread_state_t)&state, - &count, - FALSE) == KERN_SUCCESS) { - (fn)( - X86_INTERRUPT_PERFMON, - x86_THREAD_STATE, - (thread_state_t)&state, - count); - } - ml_set_interrupts_enabled(oldlevel); - } -} - -__private_extern__ kern_return_t -chudxnu_interrupt_callback_enter(chudxnu_interrupt_callback_func_t func) -{ - if(OSCompareAndSwapPtr(chud_null_int, func, - (void * volatile *)&interrupt_callback_fn)) { - lapic_set_pmi_func((i386_intr_func_t)chudxnu_private_interrupt_callback); - return KERN_SUCCESS; - } - return KERN_FAILURE; -} - -__private_extern__ kern_return_t -chudxnu_interrupt_callback_cancel(void) -{ - chudxnu_interrupt_callback_func_t old = interrupt_callback_fn; - - while(!OSCompareAndSwapPtr(old, chud_null_int, - (void * volatile *)&interrupt_callback_fn)) { - old = interrupt_callback_fn; - } - - lapic_set_pmi_func(NULL); - return KERN_SUCCESS; -} - -#if 0 -#pragma mark **** cpu signal **** -#endif -static chudxnu_cpusig_callback_func_t cpusig_callback_fn = NULL; - -static kern_return_t -chudxnu_private_cpu_signal_handler(int request) -{ - chudxnu_cpusig_callback_func_t fn = cpusig_callback_fn; - - if (fn) { - x86_thread_state_t state; - mach_msg_type_number_t count = x86_THREAD_STATE_COUNT; - - if (chudxnu_thread_get_state(current_thread(), - x86_THREAD_STATE, - (thread_state_t) &state, &count, - FALSE) == KERN_SUCCESS) { - return (fn)( - request, x86_THREAD_STATE, - (thread_state_t) &state, count); - } else { - return KERN_FAILURE; - } - } - return KERN_SUCCESS; //ignored -} -/* - * chudxnu_cpu_signal_handler() is called from the IPI handler - * when a CHUD signal arrives from another processor. - */ -__private_extern__ void -chudxnu_cpu_signal_handler(void) -{ - chudcpu_signal_request_t *reqp; - chudcpu_data_t *chudinfop; - - chudinfop = (chudcpu_data_t *) current_cpu_datap()->cpu_chud; - - mpdequeue_head(&(chudinfop->cpu_request_queue), - (queue_entry_t *) &reqp); - while (reqp != NULL) { - chudxnu_private_cpu_signal_handler(reqp->req_code); - reqp->req_sync = 0; - mpdequeue_head(&(chudinfop->cpu_request_queue), - (queue_entry_t *) &reqp); - } -} - -__private_extern__ kern_return_t -chudxnu_cpusig_callback_enter(chudxnu_cpusig_callback_func_t func) -{ - if(OSCompareAndSwapPtr(NULL, func, - (void * volatile *)&cpusig_callback_fn)) { - return KERN_SUCCESS; - } - return KERN_FAILURE; -} - -__private_extern__ kern_return_t -chudxnu_cpusig_callback_cancel(void) -{ - chudxnu_cpusig_callback_func_t old = cpusig_callback_fn; - - while(!OSCompareAndSwapPtr(old, NULL, - (void * volatile *)&cpusig_callback_fn)) { - old = cpusig_callback_fn; - } - - return KERN_SUCCESS; -} - -__private_extern__ kern_return_t -chudxnu_cpusig_send(int otherCPU, uint32_t request_code) -{ - int thisCPU; - kern_return_t retval = KERN_FAILURE; - chudcpu_signal_request_t request; - uint64_t deadline; - chudcpu_data_t *target_chudp; - boolean_t old_level; - - disable_preemption(); - // force interrupts on for a cross CPU signal. - old_level = chudxnu_set_interrupts_enabled(TRUE); - thisCPU = cpu_number(); - - if ((unsigned) otherCPU < real_ncpus && - thisCPU != otherCPU && - cpu_data_ptr[otherCPU]->cpu_running) { - - target_chudp = (chudcpu_data_t *) - cpu_data_ptr[otherCPU]->cpu_chud; - - /* Fill out request */ - request.req_sync = 0xFFFFFFFF; /* set sync flag */ - //request.req_type = CPRQchud; /* set request type */ - request.req_code = request_code; /* set request */ - - /* - * Insert the new request in the target cpu's request queue - * and signal target cpu. - */ - mpenqueue_tail(&target_chudp->cpu_request_queue, - &request.req_entry); - i386_signal_cpu(otherCPU, MP_CHUD, ASYNC); - - /* Wait for response or timeout */ - deadline = mach_absolute_time() + LockTimeOut; - while (request.req_sync != 0) { - if (mach_absolute_time() > deadline) { - panic("chudxnu_cpusig_send(%d,%d) timed out\n", - otherCPU, request_code); - } - cpu_pause(); - } - retval = KERN_SUCCESS; - } else { - retval = KERN_INVALID_ARGUMENT; - } - - chudxnu_set_interrupts_enabled(old_level); - enable_preemption(); - return retval; -} diff --git a/osfmk/chud/i386/chud_thread_i386.c b/osfmk/chud/i386/chud_thread_i386.c deleted file mode 100644 index ba2a18786..000000000 --- a/osfmk/chud/i386/chud_thread_i386.c +++ /dev/null @@ -1,725 +0,0 @@ -/* - * Copyright (c) 2003-2007 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -#include - -#if 0 -#pragma mark **** thread state **** -#endif - -__private_extern__ kern_return_t -chudxnu_thread_get_state( - thread_t thread, - thread_flavor_t flavor, - thread_state_t tstate, - mach_msg_type_number_t *count, - boolean_t user_only) -{ - if (user_only) { - /* We can't get user state for kernel threads */ - if (thread->task == kernel_task) - return KERN_FAILURE; - /* this properly handles deciding whether or not the thread is 64 bit or not */ - return machine_thread_get_state(thread, flavor, tstate, count); - } else { - // i386 machine_thread_get_kern_state() is different from the PPC version which returns - // the previous save area - user or kernel - rather than kernel or NULL if no kernel - // interrupt state available - - // the real purpose of this branch is the following: - // the user doesn't care if the thread states are user or kernel, he - // just wants the thread state, so we need to determine the proper one - // to return, kernel or user, for the given thread. - if(thread == current_thread() && current_cpu_datap()->cpu_int_state) { - // the above are conditions where we possibly can read the kernel - // state. we still need to determine if this interrupt happened in - // kernel or user context - if(USER_STATE(thread) == current_cpu_datap()->cpu_int_state && - current_cpu_datap()->cpu_interrupt_level == 1) { - // interrupt happened in user land - return machine_thread_get_state(thread, flavor, tstate, count); - } else { - // kernel interrupt. - return machine_thread_get_kern_state(thread, flavor, tstate, count); - } - } else { - // get the user-mode thread state - return machine_thread_get_state(thread, flavor, tstate, count); - } - } -} - -__private_extern__ kern_return_t -chudxnu_thread_set_state( - thread_t thread, - thread_flavor_t flavor, - thread_state_t tstate, - mach_msg_type_number_t count, - boolean_t user_only) -{ -#pragma unused (user_only) - return machine_thread_set_state(thread, flavor, tstate, count); -} - -#if 0 -#pragma mark **** task memory read/write **** -#endif - -__private_extern__ kern_return_t -chudxnu_task_read( - task_t task, - void *kernaddr, - uint64_t usraddr, - vm_size_t size) -{ - kern_return_t ret = KERN_SUCCESS; - boolean_t old_level; - - if(ml_at_interrupt_context()) { - return KERN_FAILURE; // Can't look at tasks on interrupt stack - } - - /* - * pmap layer requires interrupts to be on - */ - old_level = ml_set_interrupts_enabled(TRUE); - - if(current_task()==task) { - - if(copyin(usraddr, kernaddr, size)) { - ret = KERN_FAILURE; - } - } else { - vm_map_t map = get_task_map(task); - ret = vm_map_read_user(map, usraddr, kernaddr, size); - } - - ml_set_interrupts_enabled(old_level); - - return ret; -} - -__private_extern__ kern_return_t -chudxnu_task_write( - task_t task, - uint64_t useraddr, - void *kernaddr, - vm_size_t size) -{ - kern_return_t ret = KERN_SUCCESS; - boolean_t old_level; - - if(ml_at_interrupt_context()) { - return KERN_FAILURE; // can't poke into tasks on interrupt stack - } - - /* - * pmap layer requires interrupts to be on - */ - old_level = ml_set_interrupts_enabled(TRUE); - - if(current_task()==task) { - - if(copyout(kernaddr, useraddr, size)) { - ret = KERN_FAILURE; - } - } else { - vm_map_t map = get_task_map(task); - ret = vm_map_write_user(map, kernaddr, useraddr, size); - } - - ml_set_interrupts_enabled(old_level); - - return ret; -} - -__private_extern__ kern_return_t -chudxnu_kern_read(void *dstaddr, vm_offset_t srcaddr, vm_size_t size) -{ - return (ml_nofault_copy(srcaddr, (vm_offset_t) dstaddr, size) == size ? - KERN_SUCCESS: KERN_FAILURE); -} - -__private_extern__ kern_return_t -chudxnu_kern_write( - vm_offset_t dstaddr, - void *srcaddr, - vm_size_t size) -{ - return (ml_nofault_copy((vm_offset_t) srcaddr, dstaddr, size) == size ? - KERN_SUCCESS: KERN_FAILURE); -} - -#define VALID_STACK_ADDRESS(supervisor, addr, minKernAddr, maxKernAddr) (supervisor ? (addr>=minKernAddr && addr<=maxKernAddr) : TRUE) -// don't try to read in the hole -#define VALID_STACK_ADDRESS64(supervisor, addr, minKernAddr, maxKernAddr) \ -(supervisor ? ((uint64_t)addr >= minKernAddr && (uint64_t)addr <= maxKernAddr) : \ -((uint64_t)addr != 0ULL && ((uint64_t)addr <= 0x00007FFFFFFFFFFFULL || (uint64_t)addr >= 0xFFFF800000000000ULL))) - -typedef struct _cframe64_t { - uint64_t prevFP; // can't use a real pointer here until we're a 64 bit kernel - uint64_t caller; - uint64_t args[0]; -}cframe64_t; - - -typedef struct _cframe_t { - uint32_t prev; // this is really a user32-space pointer to the previous frame - uint32_t caller; - uint32_t args[0]; -} cframe_t; - -extern void * find_user_regs(thread_t); -extern x86_saved_state32_t *find_kern_regs(thread_t); - -static kern_return_t do_backtrace32( - task_t task, - thread_t thread, - x86_saved_state32_t *regs, - uint64_t *frames, - mach_msg_type_number_t *start_idx, - mach_msg_type_number_t max_idx, - boolean_t supervisor) -{ - uint32_t tmpWord = 0UL; - uint64_t currPC = (uint64_t) regs->eip; - uint64_t currFP = (uint64_t) regs->ebp; - uint64_t prevPC = 0ULL; - uint64_t prevFP = 0ULL; - uint64_t kernStackMin = thread->kernel_stack; - uint64_t kernStackMax = kernStackMin + kernel_stack_size; - mach_msg_type_number_t ct = *start_idx; - kern_return_t kr = KERN_FAILURE; - - if(ct >= max_idx) - return KERN_RESOURCE_SHORTAGE; // no frames traced - - frames[ct++] = chudxnu_vm_unslide(currPC, supervisor); - - // build a backtrace of this 32 bit state. - while(VALID_STACK_ADDRESS(supervisor, currFP, kernStackMin, kernStackMax)) { - cframe_t *fp = (cframe_t *) (uintptr_t) currFP; - - if(!currFP) { - currPC = 0; - break; - } - - if(ct >= max_idx) { - *start_idx = ct; - return KERN_RESOURCE_SHORTAGE; - } - - /* read our caller */ - if(supervisor) { - kr = chudxnu_kern_read(&tmpWord, (vm_offset_t) &fp->caller, sizeof(uint32_t)); - } else { - kr = chudxnu_task_read(task, &tmpWord, (vm_offset_t) &fp->caller, sizeof(uint32_t)); - } - - if(kr != KERN_SUCCESS) { - currPC = 0ULL; - break; - } - - currPC = (uint64_t) tmpWord; // promote 32 bit address - - /* - * retrive contents of the frame pointer and advance to the next stack - * frame if it's valid - */ - prevFP = 0; - if(supervisor) { - kr = chudxnu_kern_read(&tmpWord, (vm_offset_t)&fp->prev, sizeof(uint32_t)); - } else { - kr = chudxnu_task_read(task, &tmpWord, (vm_offset_t)&fp->prev, sizeof(uint32_t)); - } - prevFP = (uint64_t) tmpWord; // promote 32 bit address - - if(prevFP) { - frames[ct++] = chudxnu_vm_unslide(currPC, supervisor); - prevPC = currPC; - } - if(prevFP < currFP) { - break; - } else { - currFP = prevFP; - } - } - - *start_idx = ct; - return KERN_SUCCESS; -} - -static kern_return_t do_backtrace64( - task_t task, - thread_t thread, - x86_saved_state64_t *regs, - uint64_t *frames, - mach_msg_type_number_t *start_idx, - mach_msg_type_number_t max_idx, - boolean_t supervisor) -{ - uint64_t currPC = regs->isf.rip; - uint64_t currFP = regs->rbp; - uint64_t prevPC = 0ULL; - uint64_t prevFP = 0ULL; - uint64_t kernStackMin = (uint64_t)thread->kernel_stack; - uint64_t kernStackMax = (uint64_t)kernStackMin + kernel_stack_size; - mach_msg_type_number_t ct = *start_idx; - kern_return_t kr = KERN_FAILURE; - - if(*start_idx >= max_idx) - return KERN_RESOURCE_SHORTAGE; // no frames traced - - frames[ct++] = chudxnu_vm_unslide(currPC, supervisor); - - // build a backtrace of this 32 bit state. - while(VALID_STACK_ADDRESS64(supervisor, currFP, kernStackMin, kernStackMax)) { - // this is the address where caller lives in the user thread - uint64_t caller = currFP + sizeof(uint64_t); - - if(!currFP) { - currPC = 0; - break; - } - - if(ct >= max_idx) { - *start_idx = ct; - return KERN_RESOURCE_SHORTAGE; - } - - /* read our caller */ - if(supervisor) { - kr = chudxnu_kern_read(&currPC, (vm_offset_t)caller, sizeof(uint64_t)); - } else { - kr = chudxnu_task_read(task, &currPC, caller, sizeof(uint64_t)); - } - - if(kr != KERN_SUCCESS) { - currPC = 0ULL; - break; - } - - /* - * retrive contents of the frame pointer and advance to the next stack - * frame if it's valid - */ - prevFP = 0; - if(supervisor) { - kr = chudxnu_kern_read(&prevFP, (vm_offset_t)currFP, sizeof(uint64_t)); - } else { - kr = chudxnu_task_read(task, &prevFP, currFP, sizeof(uint64_t)); - } - - if(VALID_STACK_ADDRESS64(supervisor, prevFP, kernStackMin, kernStackMax)) { - frames[ct++] = chudxnu_vm_unslide(currPC, supervisor); - prevPC = currPC; - } - if(prevFP < currFP) { - break; - } else { - currFP = prevFP; - } - } - - *start_idx = ct; - return KERN_SUCCESS; -} - -static kern_return_t do_kernel_backtrace( - thread_t thread, - struct x86_kernel_state *regs, - uint64_t *frames, - mach_msg_type_number_t *start_idx, - mach_msg_type_number_t max_idx) -{ - uint64_t kernStackMin = (uint64_t)thread->kernel_stack; - uint64_t kernStackMax = (uint64_t)kernStackMin + kernel_stack_size; - mach_msg_type_number_t ct = *start_idx; - kern_return_t kr = KERN_FAILURE; - -#if __LP64__ - uint64_t currPC = 0ULL; - uint64_t currFP = 0ULL; - uint64_t prevPC = 0ULL; - uint64_t prevFP = 0ULL; - if(KERN_SUCCESS != chudxnu_kern_read(&currPC, (vm_offset_t)&(regs->k_rip), sizeof(uint64_t))) { - return KERN_FAILURE; - } - if(KERN_SUCCESS != chudxnu_kern_read(&currFP, (vm_offset_t)&(regs->k_rbp), sizeof(uint64_t))) { - return KERN_FAILURE; - } -#else - uint32_t currPC = 0U; - uint32_t currFP = 0U; - uint32_t prevPC = 0U; - uint32_t prevFP = 0U; - if(KERN_SUCCESS != chudxnu_kern_read(&currPC, (vm_offset_t)&(regs->k_eip), sizeof(uint32_t))) { - return KERN_FAILURE; - } - if(KERN_SUCCESS != chudxnu_kern_read(&currFP, (vm_offset_t)&(regs->k_ebp), sizeof(uint32_t))) { - return KERN_FAILURE; - } -#endif - - if(*start_idx >= max_idx) - return KERN_RESOURCE_SHORTAGE; // no frames traced - - if(!currPC) { - return KERN_FAILURE; - } - - frames[ct++] = chudxnu_vm_unslide((uint64_t)currPC, 1); - - // build a backtrace of this kernel state -#if __LP64__ - while(VALID_STACK_ADDRESS64(TRUE, currFP, kernStackMin, kernStackMax)) { - // this is the address where caller lives in the user thread - uint64_t caller = currFP + sizeof(uint64_t); -#else - while(VALID_STACK_ADDRESS(TRUE, currFP, kernStackMin, kernStackMax)) { - uint32_t caller = (uint32_t)currFP + sizeof(uint32_t); -#endif - - if(!currFP || !currPC) { - currPC = 0; - break; - } - - if(ct >= max_idx) { - *start_idx = ct; - return KERN_RESOURCE_SHORTAGE; - } - - /* read our caller */ - kr = chudxnu_kern_read(&currPC, (vm_offset_t)caller, sizeof(currPC)); - - if(kr != KERN_SUCCESS || !currPC) { - currPC = 0UL; - break; - } - - /* - * retrive contents of the frame pointer and advance to the next stack - * frame if it's valid - */ - prevFP = 0; - kr = chudxnu_kern_read(&prevFP, (vm_offset_t)currFP, sizeof(currPC)); - -#if __LP64__ - if(VALID_STACK_ADDRESS64(TRUE, prevFP, kernStackMin, kernStackMax)) { -#else - if(VALID_STACK_ADDRESS(TRUE, prevFP, kernStackMin, kernStackMax)) { -#endif - frames[ct++] = chudxnu_vm_unslide((uint64_t)currPC, 1); - prevPC = currPC; - } - if(prevFP <= currFP) { - break; - } else { - currFP = prevFP; - } - } - - *start_idx = ct; - return KERN_SUCCESS; -} - -static -kern_return_t chudxnu_thread_get_callstack64_internal( - thread_t thread, - uint64_t *callstack, - mach_msg_type_number_t *count, - boolean_t user_only, - boolean_t kern_only) -{ - kern_return_t kr = KERN_FAILURE; - task_t task = thread->task; - uint64_t currPC = 0ULL; - boolean_t supervisor = FALSE; - mach_msg_type_number_t bufferIndex = 0; - mach_msg_type_number_t bufferMaxIndex = *count; - x86_saved_state_t *tagged_regs = NULL; // kernel register state - x86_saved_state64_t *regs64 = NULL; - x86_saved_state32_t *regs32 = NULL; - x86_saved_state32_t *u_regs32 = NULL; - x86_saved_state64_t *u_regs64 = NULL; - struct x86_kernel_state *kregs = NULL; - - if(ml_at_interrupt_context()) { - - if(user_only) { - /* can't backtrace user state on interrupt stack. */ - return KERN_FAILURE; - } - - /* backtracing at interrupt context? */ - if(thread == current_thread() && current_cpu_datap()->cpu_int_state) { - /* - * Locate the registers for the interrupted thread, assuming it is - * current_thread(). - */ - tagged_regs = current_cpu_datap()->cpu_int_state; - - if(is_saved_state64(tagged_regs)) { - /* 64 bit registers */ - regs64 = saved_state64(tagged_regs); - supervisor = ((regs64->isf.cs & SEL_PL) != SEL_PL_U); - } else { - /* 32 bit registers */ - regs32 = saved_state32(tagged_regs); - supervisor = ((regs32->cs & SEL_PL) != SEL_PL_U); - } - } - } - - if(!ml_at_interrupt_context() && kernel_task == task) { - - if(!thread->kernel_stack) { - return KERN_FAILURE; - } - - // Kernel thread not at interrupt context - kregs = (struct x86_kernel_state *)NULL; - - // nofault read of the thread->kernel_stack pointer - if(KERN_SUCCESS != chudxnu_kern_read(&kregs, (vm_offset_t)&(thread->kernel_stack), sizeof(void *))) { - return KERN_FAILURE; - } - - // Adjust to find the saved kernel state - kregs = STACK_IKS((vm_offset_t)(uintptr_t)kregs); - - supervisor = TRUE; - } else if(!tagged_regs) { - /* - * not at interrupt context, or tracing a different thread than - * current_thread() at interrupt context - */ - tagged_regs = USER_STATE(thread); - if(is_saved_state64(tagged_regs)) { - /* 64 bit registers */ - regs64 = saved_state64(tagged_regs); - supervisor = ((regs64->isf.cs & SEL_PL) != SEL_PL_U); - } else { - /* 32 bit registers */ - regs32 = saved_state32(tagged_regs); - supervisor = ((regs32->cs & SEL_PL) != SEL_PL_U); - } - } - - *count = 0; - - if(supervisor) { - // the caller only wants a user callstack. - if(user_only) { - // bail - we've only got kernel state - return KERN_FAILURE; - } - } else { - // regs32(64) is not in supervisor mode. - u_regs32 = regs32; - u_regs64 = regs64; - regs32 = NULL; - regs64 = NULL; - } - - if (user_only) { - /* we only want to backtrace the user mode */ - if(!(u_regs32 || u_regs64)) { - /* no user state to look at */ - return KERN_FAILURE; - } - } - - /* - * Order of preference for top of stack: - * 64 bit kernel state (not likely) - * 32 bit kernel state - * 64 bit user land state - * 32 bit user land state - */ - - if(kregs) { - /* - * nofault read of the registers from the kernel stack (as they can - * disappear on the fly). - */ - -#if __LP64__ - if(KERN_SUCCESS != chudxnu_kern_read(&currPC, (vm_offset_t)&(kregs->k_rip), sizeof(uint64_t))) { - return KERN_FAILURE; - } -#else - uint32_t tmp; - if(KERN_SUCCESS != chudxnu_kern_read(&tmp, (vm_offset_t)&(kregs->k_eip), sizeof(uint32_t))) { - return KERN_FAILURE; - } - currPC = (uint64_t)tmp; -#endif - } else if(regs64) { - currPC = regs64->isf.rip; - } else if(regs32) { - currPC = (uint64_t) regs32->eip; - } else if(u_regs64) { - currPC = u_regs64->isf.rip; - } else if(u_regs32) { - currPC = (uint64_t) u_regs32->eip; - } - - if(!currPC) { - /* no top of the stack, bail out */ - return KERN_FAILURE; - } - - bufferIndex = 0; - - if(bufferMaxIndex < 1) { - *count = 0; - return KERN_RESOURCE_SHORTAGE; - } - - /* backtrace kernel */ - if(kregs) { - addr64_t address = 0ULL; - size_t size = 0UL; - - // do the backtrace - kr = do_kernel_backtrace(thread, kregs, callstack, &bufferIndex, bufferMaxIndex); - - // and do a nofault read of (r|e)sp -#if __LP64__ - uint64_t rsp = 0ULL; - size = sizeof(uint64_t); - - if(KERN_SUCCESS != chudxnu_kern_read(&address, (vm_offset_t)&(kregs->k_rsp), size)) { - address = 0ULL; - } -#else - uint32_t rsp = 0ULL, tmp = 0ULL; - size = sizeof(uint32_t); - - if(KERN_SUCCESS != chudxnu_kern_read(&tmp, (vm_offset_t)&(kregs->k_esp), size)) { - address = 0ULL; - } else { - address = (addr64_t)tmp; - } -#endif - - if(address && KERN_SUCCESS == chudxnu_kern_read(&rsp, (vm_offset_t)address, size) && bufferIndex < bufferMaxIndex) { - callstack[bufferIndex++] = (uint64_t)rsp; - } - } else if(regs64) { - uint64_t rsp = 0ULL; - - // backtrace the 64bit side. - kr = do_backtrace64(task, thread, regs64, callstack, &bufferIndex, - bufferMaxIndex - 1, TRUE); - - if(KERN_SUCCESS == chudxnu_kern_read(&rsp, (vm_offset_t) regs64->isf.rsp, sizeof(uint64_t)) && - bufferIndex < bufferMaxIndex) { - callstack[bufferIndex++] = rsp; - } - - } else if(regs32) { - uint32_t esp = 0UL; - - // backtrace the 32bit side. - kr = do_backtrace32(task, thread, regs32, callstack, &bufferIndex, - bufferMaxIndex - 1, TRUE); - - if(KERN_SUCCESS == chudxnu_kern_read(&esp, (vm_offset_t) regs32->uesp, sizeof(uint32_t)) && - bufferIndex < bufferMaxIndex) { - callstack[bufferIndex++] = (uint64_t) esp; - } - } else if(u_regs64 && !kern_only) { - /* backtrace user land */ - uint64_t rsp = 0ULL; - - kr = do_backtrace64(task, thread, u_regs64, callstack, &bufferIndex, - bufferMaxIndex - 1, FALSE); - - if(KERN_SUCCESS == chudxnu_task_read(task, &rsp, (addr64_t) u_regs64->isf.rsp, sizeof(uint64_t)) && - bufferIndex < bufferMaxIndex) { - callstack[bufferIndex++] = rsp; - } - - } else if(u_regs32 && !kern_only) { - uint32_t esp = 0UL; - - kr = do_backtrace32(task, thread, u_regs32, callstack, &bufferIndex, - bufferMaxIndex - 1, FALSE); - - if(KERN_SUCCESS == chudxnu_task_read(task, &esp, (addr64_t) u_regs32->uesp, sizeof(uint32_t)) && - bufferIndex < bufferMaxIndex) { - callstack[bufferIndex++] = (uint64_t) esp; - } - } - - *count = bufferIndex; - return kr; -} - -__private_extern__ -kern_return_t chudxnu_thread_get_callstack64_kperf( - thread_t thread, - uint64_t *callstack, - mach_msg_type_number_t *count, - boolean_t is_user) -{ - return chudxnu_thread_get_callstack64_internal(thread, callstack, count, is_user, !is_user); -} - -__private_extern__ -kern_return_t chudxnu_thread_get_callstack64( - thread_t thread, - uint64_t *callstack, - mach_msg_type_number_t *count, - boolean_t user_only) -{ - return chudxnu_thread_get_callstack64_internal(thread, callstack, count, user_only, 0); -} - diff --git a/osfmk/chud/i386/chud_xnu_glue.h b/osfmk/chud/i386/chud_xnu_glue.h deleted file mode 100644 index 7145052d0..000000000 --- a/osfmk/chud/i386/chud_xnu_glue.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2003-2008 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - diff --git a/osfmk/chud/i386/chud_xnu_private.h b/osfmk/chud/i386/chud_xnu_private.h deleted file mode 100644 index 4d0a30383..000000000 --- a/osfmk/chud/i386/chud_xnu_private.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2003-2007 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#ifndef _I386_CHUD_XNU_PRIVATE_H_ -#define _I386_CHUD_XNU_PRIVATE_H_ - -#include - -#if 0 -#pragma mark **** cpu timer **** -#endif - -/* - * Cross-cpu signal request entries are queued on the target cpu's - * chudcpu_data_t struct. This differs from PPC because i386 doesn't - * support sending arguments with cross-cpu signals. Hence we have - * to do it ourselves. - */ -typedef struct { - struct queue_entry req_entry; /* Must be first */ - uint32_t req_type; - uint32_t req_code; - volatile uint32_t req_sync; -} chudcpu_signal_request_t; - -typedef struct { - void *cpu_chud_fn_tablep; - timer_call_data_t cpu_timer_call; - uint64_t t_deadline; - chudxnu_cpu_timer_callback_func_t cpu_timer_callback_fn; - mpqueue_head_t cpu_request_queue; -} chudcpu_data_t; -/* NB: cpu_chud_fn_tablep is expected to be the first member, at offset 0 */ - -extern void chudxnu_cpu_signal_handler(void); - -#endif /* _I386_CHUD_XNU_PRIVATE_H_ */ diff --git a/osfmk/conf/Makefile.template b/osfmk/conf/Makefile.template index b1f41bbc2..d533b91a5 100644 --- a/osfmk/conf/Makefile.template +++ b/osfmk/conf/Makefile.template @@ -23,8 +23,6 @@ SFLAGS+= -include meta_features.h OBJS_NO_CAST_ALIGN = \ atm_notification_user.o \ model_dep.o \ - chud_thread.o \ - chud_thread_arm.o \ video_console.o \ kdp_udp.o \ kdp_machdep.o \ @@ -92,11 +90,6 @@ OBJS_NO_SIGN_COMPARE = \ $(foreach file,$(OBJS_NO_CAST_ALIGN),$(eval $(call add_perfile_cflags,$(file),-Wno-cast-align))) $(foreach file,$(OBJS_NO_SIGN_COMPARE),$(eval $(call add_perfile_cflags,$(file),-Wno-sign-compare))) -# -# Do not provide CTF symbolic these files -# -chud_glue.o_SKIP_CTFCONVERT = 1 - # # XXX: INCFLAGS to include libsa prototypes # diff --git a/osfmk/conf/files b/osfmk/conf/files index befcee59c..53078380e 100644 --- a/osfmk/conf/files +++ b/osfmk/conf/files @@ -270,15 +270,6 @@ osfmk/kern/kmod.c standard # osfmk/device/subrs.c standard -# -# MI CHUD: -# -osfmk/chud/chud_cpu.c standard -osfmk/chud/chud_glue.c standard -osfmk/chud/chud_memory.c standard -osfmk/chud/chud_osfmk_callback.c standard -osfmk/chud/chud_thread.c standard - # Kernel performance monitoring osfmk/kperf/kperf.c optional kperf osfmk/kperf/action.c optional kperf diff --git a/osfmk/conf/files.arm b/osfmk/conf/files.arm index d79408fda..208781e47 100644 --- a/osfmk/conf/files.arm +++ b/osfmk/conf/files.arm @@ -61,7 +61,6 @@ osfmk/arm/commpage/commpage.c standard osfmk/kdp/ml/arm/kdp_machdep.c optional mach_kdp osfmk/kdp/ml/arm/kdp_vm.c optional mach_kdp - # DUMMIES TO FORCE GENERATION OF .h FILES osfmk/OPTIONS/ln optional ln osfmk/OPTIONS/eisa optional eisa diff --git a/osfmk/conf/files.arm64 b/osfmk/conf/files.arm64 index e5234f0d9..61e470322 100644 --- a/osfmk/conf/files.arm64 +++ b/osfmk/conf/files.arm64 @@ -65,7 +65,6 @@ osfmk/arm/commpage/commpage.c standard osfmk/kdp/ml/arm/kdp_machdep.c optional mach_kdp osfmk/kdp/ml/arm/kdp_vm.c optional mach_kdp - # DUMMIES TO FORCE GENERATION OF .h FILES osfmk/OPTIONS/ln optional ln osfmk/OPTIONS/eisa optional eisa diff --git a/osfmk/conf/files.x86_64 b/osfmk/conf/files.x86_64 index 7fe01580c..e663bd3ee 100644 --- a/osfmk/conf/files.x86_64 +++ b/osfmk/conf/files.x86_64 @@ -97,10 +97,6 @@ osfmk/kdp/ml/i386/kdp_x86_common.c optional mach_kdp osfmk/i386/hibernate_i386.c optional hibernation osfmk/i386/hibernate_restore.c optional hibernation -osfmk/chud/i386/chud_osfmk_callback_i386.c standard -osfmk/chud/i386/chud_cpu_i386.c standard -osfmk/chud/i386/chud_thread_i386.c standard - osfmk/i386/ucode.c standard osfmk/i386/vmx/vmx_cpu.c optional config_vmx diff --git a/osfmk/corpses/task_corpse.h b/osfmk/corpses/task_corpse.h index d3d43107b..59ab07592 100644 --- a/osfmk/corpses/task_corpse.h +++ b/osfmk/corpses/task_corpse.h @@ -100,8 +100,6 @@ extern kern_return_t task_duplicate_map_and_threads( int *size, int *num_udata); -extern boolean_t task_allowed_vm_map_fork(task_t task __unused); - extern kern_return_t task_enqueue_exception_with_corpse( task_t task, exception_type_t etype, diff --git a/osfmk/device/device.defs b/osfmk/device/device.defs index 4948c08a4..0d3b24380 100644 --- a/osfmk/device/device.defs +++ b/osfmk/device/device.defs @@ -808,6 +808,12 @@ routine io_registry_entry_from_path_ool( #endif +routine io_device_tree_entry_exists_with_name( + master_port : mach_port_t; + in name : io_name_t; + out exists : boolean_t + ); + #endif /* IOKIT */ /* vim: set ft=c : */ diff --git a/osfmk/device/iokit_rpc.c b/osfmk/device/iokit_rpc.c index d44eea33c..75650da7b 100644 --- a/osfmk/device/iokit_rpc.c +++ b/osfmk/device/iokit_rpc.c @@ -66,83 +66,17 @@ #if defined(__arm__) || defined(__arm64__) #include #endif -#include +#include #define EXTERN #define MIGEXTERN -/* - * Functions in iokit:IOUserClient.cpp - */ - -extern void iokit_add_reference( io_object_t obj ); -extern void iokit_add_connect_reference( io_object_t obj ); - -extern ipc_port_t iokit_port_for_object( io_object_t obj, - ipc_kobject_type_t type ); - -extern kern_return_t iokit_client_died( io_object_t obj, - ipc_port_t port, ipc_kobject_type_t type, mach_port_mscount_t * mscount ); - -extern kern_return_t -iokit_client_memory_for_type( - io_object_t connect, - unsigned int type, - unsigned int * flags, - vm_address_t * address, - vm_size_t * size ); - - -extern ppnum_t IOGetLastPageNumber(void); - -/* - * Functions imported by iokit:IOUserClient.cpp - */ - -extern ipc_port_t iokit_alloc_object_port( io_object_t obj, - ipc_kobject_type_t type ); - -extern kern_return_t iokit_destroy_object_port( ipc_port_t port ); - -extern mach_port_name_t iokit_make_send_right( task_t task, - io_object_t obj, ipc_kobject_type_t type ); - -extern kern_return_t iokit_mod_send_right( task_t task, mach_port_name_t name, mach_port_delta_t delta ); - -extern io_object_t iokit_lookup_connect_ref(io_object_t clientRef, ipc_space_t task); - -extern io_object_t iokit_lookup_connect_ref_current_task(io_object_t clientRef); - -extern void iokit_retain_port( ipc_port_t port ); -extern void iokit_release_port( ipc_port_t port ); -extern void iokit_release_port_send( ipc_port_t port ); - -extern void iokit_lock_port(ipc_port_t port); -extern void iokit_unlock_port(ipc_port_t port); - -extern kern_return_t iokit_switch_object_port( ipc_port_t port, io_object_t obj, ipc_kobject_type_t type ); - -/* - * Functions imported by iokit:IOMemoryDescriptor.cpp - */ - -extern kern_return_t IOMapPages(vm_map_t map, mach_vm_address_t va, mach_vm_address_t pa, - mach_vm_size_t length, unsigned int mapFlags); - -extern kern_return_t IOUnmapPages(vm_map_t map, mach_vm_address_t va, mach_vm_size_t length); - -extern kern_return_t IOProtectCacheMode(vm_map_t map, mach_vm_address_t va, - mach_vm_size_t length, unsigned int options); - -extern unsigned int IODefaultCacheBits(addr64_t pa); - /* * Lookup a device by its port. * Doesn't consume the naked send right; produces a device reference. */ -MIGEXTERN io_object_t -iokit_lookup_object_port( - ipc_port_t port) +static io_object_t +iokit_lookup_io_object(ipc_port_t port, ipc_kobject_type_t type) { io_object_t obj; @@ -150,9 +84,9 @@ iokit_lookup_object_port( return (NULL); iokit_lock_port(port); - if (ip_active(port) && (ip_kotype(port) == IKOT_IOKIT_OBJECT)) { + if (ip_active(port) && (ip_kotype(port) == type)) { obj = (io_object_t) port->ip_kobject; - iokit_add_reference( obj ); + iokit_add_reference( obj, type ); } else obj = NULL; @@ -163,37 +97,29 @@ iokit_lookup_object_port( } MIGEXTERN io_object_t -iokit_lookup_connect_port( +iokit_lookup_object_port( ipc_port_t port) { - io_object_t obj; - - if (!IP_VALID(port)) - return (NULL); - - iokit_lock_port(port); - if (ip_active(port) && (ip_kotype(port) == IKOT_IOKIT_CONNECT)) { - obj = (io_object_t) port->ip_kobject; - iokit_add_connect_reference( obj ); - } - else - obj = NULL; - - iokit_unlock_port(port); + return (iokit_lookup_io_object(port, IKOT_IOKIT_OBJECT)); +} - return( obj ); +MIGEXTERN io_object_t +iokit_lookup_connect_port( + ipc_port_t port) +{ + return (iokit_lookup_io_object(port, IKOT_IOKIT_CONNECT)); } -EXTERN io_object_t -iokit_lookup_connect_ref(io_object_t connectRef, ipc_space_t space) +static io_object_t +iokit_lookup_object_in_space_with_port_name(mach_port_name_t name, ipc_kobject_type_t type, ipc_space_t space) { io_object_t obj = NULL; - if (connectRef && MACH_PORT_VALID(CAST_MACH_PORT_TO_NAME(connectRef))) { + if (name && MACH_PORT_VALID(name)) { ipc_port_t port; kern_return_t kr; - kr = ipc_object_translate(space, CAST_MACH_PORT_TO_NAME(connectRef), MACH_PORT_RIGHT_SEND, (ipc_object_t *)&port); + kr = ipc_object_translate(space, name, MACH_PORT_RIGHT_SEND, (ipc_object_t *)&port); if (kr == KERN_SUCCESS) { assert(IP_VALID(port)); @@ -202,9 +128,9 @@ iokit_lookup_connect_ref(io_object_t connectRef, ipc_space_t space) ip_unlock(port); iokit_lock_port(port); - if (ip_active(port) && (ip_kotype(port) == IKOT_IOKIT_CONNECT)) { + if (ip_active(port) && (ip_kotype(port) == type)) { obj = (io_object_t) port->ip_kobject; - iokit_add_connect_reference(obj); + iokit_add_reference(obj, type); } iokit_unlock_port(port); @@ -216,9 +142,15 @@ iokit_lookup_connect_ref(io_object_t connectRef, ipc_space_t space) } EXTERN io_object_t -iokit_lookup_connect_ref_current_task(io_object_t connectRef) +iokit_lookup_object_with_port_name(mach_port_name_t name, ipc_kobject_type_t type, task_t task) { - return iokit_lookup_connect_ref(connectRef, current_space()); + return (iokit_lookup_object_in_space_with_port_name(name, type, task->itk_space)); +} + +EXTERN io_object_t +iokit_lookup_connect_ref_current_task(mach_port_name_t name) +{ + return (iokit_lookup_object_in_space_with_port_name(name, IKOT_IOKIT_CONNECT, current_space())); } EXTERN void @@ -257,9 +189,9 @@ iokit_unlock_port( __unused ipc_port_t port ) * Get the port for a device. * Consumes a device reference; produces a naked send right. */ -MIGEXTERN ipc_port_t -iokit_make_object_port( - io_object_t obj ) + +static ipc_port_t +iokit_make_port_of_type(io_object_t obj, ipc_kobject_type_t type) { ipc_port_t port; ipc_port_t sendPort; @@ -267,7 +199,7 @@ iokit_make_object_port( if( obj == NULL) return IP_NULL; - port = iokit_port_for_object( obj, IKOT_IOKIT_OBJECT ); + port = iokit_port_for_object( obj, type ); if( port) { sendPort = ipc_port_make_send( port); iokit_release_port( port ); @@ -280,25 +212,17 @@ iokit_make_object_port( } MIGEXTERN ipc_port_t -iokit_make_connect_port( +iokit_make_object_port( io_object_t obj ) { - ipc_port_t port; - ipc_port_t sendPort; - - if( obj == NULL) - return IP_NULL; - - port = iokit_port_for_object( obj, IKOT_IOKIT_CONNECT ); - if( port) { - sendPort = ipc_port_make_send( port); - iokit_release_port( port ); - } else - sendPort = IP_NULL; - - iokit_remove_reference( obj ); + return (iokit_make_port_of_type(obj, IKOT_IOKIT_OBJECT)); +} - return( sendPort); +MIGEXTERN ipc_port_t +iokit_make_connect_port( + io_object_t obj ) +{ + return (iokit_make_port_of_type(obj, IKOT_IOKIT_CONNECT)); } int gIOKitPortCount; @@ -317,7 +241,6 @@ iokit_alloc_object_port( io_object_t obj, ipc_kobject_type_t type ) continue; /* set kobject & type */ -// iokit_add_reference( obj ); ipc_kobject_set( port, (ipc_kobject_t) obj, type); /* Request no-senders notifications on the port. */ @@ -389,8 +312,6 @@ iokit_make_send_right( task_t task, io_object_t obj, ipc_kobject_type_t type ) else if ( sendPort == IP_DEAD) name = MACH_PORT_DEAD; - iokit_remove_reference( obj ); - return( name ); } @@ -423,8 +344,9 @@ iokit_no_senders( mach_no_senders_notification_t * notification ) obj = (io_object_t) port->ip_kobject; type = ip_kotype( port ); if( (IKOT_IOKIT_OBJECT == type) - || (IKOT_IOKIT_CONNECT == type)) - iokit_add_reference( obj ); + || (IKOT_IOKIT_CONNECT == type) + || (IKOT_IOKIT_IDENT == type)) + iokit_add_reference( obj, IKOT_IOKIT_OBJECT ); else obj = NULL; } diff --git a/osfmk/i386/AT386/model_dep.c b/osfmk/i386/AT386/model_dep.c index 10b4c4c3f..614b310eb 100644 --- a/osfmk/i386/AT386/model_dep.c +++ b/osfmk/i386/AT386/model_dep.c @@ -905,11 +905,42 @@ RecordPanicStackshot() } kdp_snapshot_preflight(-1, (void *) stackshot_begin_loc, bytes_remaining, - (STACKSHOT_KCDATA_FORMAT | STACKSHOT_NO_IO_STATS | STACKSHOT_SAVE_KEXT_LOADINFO | - STACKSHOT_ACTIVE_KERNEL_THREADS_ONLY | STACKSHOT_FROM_PANIC | STACKSHOT_THREAD_WAITINFO), &kc_panic_data, 0); + (STACKSHOT_SAVE_KEXT_LOADINFO | STACKSHOT_SAVE_LOADINFO | STACKSHOT_KCDATA_FORMAT | + STACKSHOT_ENABLE_BT_FAULTING | STACKSHOT_ENABLE_UUID_FAULTING | STACKSHOT_FROM_PANIC | + STACKSHOT_NO_IO_STATS | STACKSHOT_THREAD_WAITINFO), &kc_panic_data, 0); err = do_stackshot(NULL); bytes_traced = (int) kdp_stack_snapshot_bytes_traced(); - if (bytes_traced > 0 && !err) { + bytes_used = (int) kcdata_memory_get_used_bytes(&kc_panic_data); + + if ((err != KERN_SUCCESS) && (bytes_used > 0)) { + /* + * We ran out of space while trying to capture a stackshot, try again without user frames. + * It's not safe to log from here, but append a flag to the panic flags. + */ + panic_info->mph_panic_flags |= MACOS_PANIC_HEADER_FLAG_STACKSHOT_KERNEL_ONLY; + panic_stackshot_reset_state(); + + /* Erase the stackshot data (this region is pre-populated with the NULL character) */ + memset(stackshot_begin_loc, '\0', bytes_used); + + err = kcdata_memory_static_init(&kc_panic_data, (mach_vm_address_t)stackshot_begin_loc, + KCDATA_BUFFER_BEGIN_STACKSHOT, bytes_remaining, KCFLAG_USE_MEMCOPY); + if (err != KERN_SUCCESS) { + panic_info->mph_panic_flags |= MACOS_PANIC_HEADER_FLAG_STACKSHOT_FAILED_ERROR; + panic_info->mph_other_log_offset = PE_get_offset_into_panic_region(debug_buf_ptr); + kdb_printf("Failed to re-initialize kcdata buffer for kernel only in-memory panic stackshot, skipping ...\n"); + return; + } + + kdp_snapshot_preflight(-1, (void *) stackshot_begin_loc, bytes_remaining, (STACKSHOT_KCDATA_FORMAT | + STACKSHOT_NO_IO_STATS | STACKSHOT_SAVE_KEXT_LOADINFO | STACKSHOT_ACTIVE_KERNEL_THREADS_ONLY | + STACKSHOT_FROM_PANIC | STACKSHOT_THREAD_WAITINFO), &kc_panic_data, 0); + err = do_stackshot(NULL); + bytes_traced = (int) kdp_stack_snapshot_bytes_traced(); + bytes_used = (int) kcdata_memory_get_used_bytes(&kc_panic_data); + } + + if (err == KERN_SUCCESS) { debug_buf_ptr += bytes_traced; panic_info->mph_panic_flags |= MACOS_PANIC_HEADER_FLAG_STACKSHOT_SUCCEEDED; panic_info->mph_stackshot_offset = PE_get_offset_into_panic_region(stackshot_begin_loc); @@ -918,10 +949,9 @@ RecordPanicStackshot() panic_info->mph_other_log_offset = PE_get_offset_into_panic_region(debug_buf_ptr); kdb_printf("\n** In Memory Panic Stackshot Succeeded ** Bytes Traced %d **\n", bytes_traced); } else { - bytes_used = (int) kcdata_memory_get_used_bytes(&kc_panic_data); if (bytes_used > 0) { - /* Zero out the stackshot data */ - bzero(stackshot_begin_loc, bytes_used); + /* Erase the stackshot data (this region is pre-populated with the NULL character) */ + memset(stackshot_begin_loc, '\0', bytes_used); panic_info->mph_panic_flags |= MACOS_PANIC_HEADER_FLAG_STACKSHOT_FAILED_INCOMPLETE; panic_info->mph_other_log_offset = PE_get_offset_into_panic_region(debug_buf_ptr); @@ -937,7 +967,7 @@ RecordPanicStackshot() } #if DEVELOPMENT || DEBUG if (panic_stackshot_buf != 0) { - // We're going to try to take another stackshot, reset the state. + /* We're going to try to take another stackshot, reset the state. */ panic_stackshot_reset_state(); } #endif /* DEVELOPMENT || DEBUG */ diff --git a/osfmk/i386/acpi.c b/osfmk/i386/acpi.c index 8d4ac8040..927e94005 100644 --- a/osfmk/i386/acpi.c +++ b/osfmk/i386/acpi.c @@ -164,7 +164,8 @@ acpi_hibernate(void *refcon) extern void slave_pstart(void); extern void hibernate_rebuild_vm_structs(void); -extern unsigned int wake_nkdbufs; +extern unsigned int wake_nkdbufs; +extern unsigned int trace_wrap; void acpi_sleep_kernel(acpi_sleep_callback func, void *refcon) @@ -332,7 +333,7 @@ acpi_sleep_kernel(acpi_sleep_callback func, void *refcon) if (kdebug_enable == 0) { if (wake_nkdbufs) { start = mach_absolute_time(); - kdebug_trace_start(wake_nkdbufs, NULL, TRUE); + kdebug_trace_start(wake_nkdbufs, NULL, trace_wrap != 0, TRUE); elapsed_trace_start += mach_absolute_time() - start; } } @@ -460,7 +461,7 @@ acpi_idle_kernel(acpi_sleep_callback func, void *refcon) if (kdebug_enable == 0) { if (wake_nkdbufs) { __kdebug_only uint64_t start = mach_absolute_time(); - kdebug_trace_start(wake_nkdbufs, NULL, TRUE); + kdebug_trace_start(wake_nkdbufs, NULL, trace_wrap != 0, TRUE); KDBG(IOKDBG_CODE(DBG_HIBERNATE, 15), start); } } diff --git a/osfmk/i386/bsd_i386.c b/osfmk/i386/bsd_i386.c index 9dd47783c..b855d1c66 100644 --- a/osfmk/i386/bsd_i386.c +++ b/osfmk/i386/bsd_i386.c @@ -728,7 +728,6 @@ find_user_regs(thread_t thread) #if CONFIG_DTRACE /* * DTrace would like to have a peek at the kernel interrupt state, if available. - * Based on osfmk/chud/i386/chud_thread_i386.c:chudxnu_thread_get_state(), which see. */ x86_saved_state_t *find_kern_regs(thread_t); diff --git a/osfmk/i386/cpu_data.h b/osfmk/i386/cpu_data.h index 618389fd9..ff08d7493 100644 --- a/osfmk/i386/cpu_data.h +++ b/osfmk/i386/cpu_data.h @@ -177,22 +177,22 @@ typedef struct cpu_data }; volatile task_map_t cpu_task_map; volatile addr64_t cpu_task_cr3; - volatile addr64_t cpu_ucr3; addr64_t cpu_kernel_cr3; + volatile addr64_t cpu_ucr3; boolean_t cpu_pagezero_mapped; cpu_uber_t cpu_uber; - /* Double-mapped per-CPU exception stack address */ +/* Double-mapped per-CPU exception stack address */ uintptr_t cd_estack; - /* Address of shadowed, partially mirrored CPU data structures located - * in the double mapped PML4 - */ +/* Address of shadowed, partially mirrored CPU data structures located + * in the double mapped PML4 + */ void *cd_shadow; struct processor *cpu_processor; #if NCOPY_WINDOWS > 0 struct cpu_pmap *cpu_pmap; #endif - struct cpu_desc_table *cpu_desc_tablep; struct real_descriptor *cpu_ldtp; + struct cpu_desc_table *cpu_desc_tablep; cpu_desc_index_t cpu_desc_index; int cpu_ldt; #if NCOPY_WINDOWS > 0 @@ -279,7 +279,6 @@ typedef struct cpu_data int cpu_plri; plrecord_t plrecords[MAX_PREEMPTION_RECORDS]; #endif - void *cpu_chud; void *cpu_console_buf; struct x86_lcpu lcpu; int cpu_phys_number; /* Physical CPU */ @@ -611,6 +610,11 @@ cpu_datap(int cpu) { return cpu_data_ptr[cpu]; } +static inline int +cpu_is_running(int cpu) { + return ((cpu_datap(cpu) != NULL) && (cpu_datap(cpu)->cpu_running)); +} + #ifdef MACH_KERNEL_PRIVATE static inline cpu_data_t * cpu_shadowp(int cpu) { diff --git a/osfmk/i386/cpu_threads.c b/osfmk/i386/cpu_threads.c index 5447514d8..92f34b8fd 100644 --- a/osfmk/i386/cpu_threads.c +++ b/osfmk/i386/cpu_threads.c @@ -1019,20 +1019,15 @@ x86_validate_topology(void) debug_topology_print(); /* - * XXX - * - * Right now this only works if the number of CPUs started is the total - * number of CPUs. However, when specifying cpus=n the topology is only - * partially constructed and the checks below will fail. - * - * We should *always* build the complete topology and only start the CPUs - * indicated by cpus=n. Until that happens, this code will not check the - * topology if the number of cpus defined is < that described the the - * topology parameters. + * Called after processors are registered but before non-boot processors + * are started: + * - real_ncpus: number of registered processors driven from MADT + * - max_ncpus: max number of processors that will be started */ nCPUs = topoParms.nPackages * topoParms.nLThreadsPerPackage; - if (nCPUs > real_ncpus) - return; + if (nCPUs != real_ncpus) + panic("x86_validate_topology() %d threads but %d registered from MADT", + nCPUs, real_ncpus); pkg = x86_pkgs; while (pkg != NULL) { diff --git a/osfmk/i386/cpu_topology.c b/osfmk/i386/cpu_topology.c index e079e6e38..a4a460893 100644 --- a/osfmk/i386/cpu_topology.c +++ b/osfmk/i386/cpu_topology.c @@ -37,6 +37,7 @@ #include #include #include +#include __private_extern__ void qsort( void * array, @@ -64,15 +65,14 @@ static void cpu_shadow_sort(int ncpus) { } /* - * cpu_topology_sort() is called after all processors have been registered - * but before any non-boot processor id started. - * We establish canonical logical processor numbering - logical cpus must be - * contiguous, zero-based and assigned in physical (local apic id) order. - * This step is required because the discovery/registration order is - * non-deterministic - cores are registered in differing orders over boots. - * Enforcing canonical numbering simplifies identification - * of processors - in particular, for stopping/starting from CHUD. - */ + * cpu_topology_sort() is called after all processors have been registered but + * before any non-boot processor id started. We establish canonical logical + * processor numbering - logical cpus must be contiguous, zero-based and + * assigned in physical (local apic id) order. This step is required because + * the discovery/registration order is non-deterministic - cores are registered + * in differing orders over boots. Enforcing canonical numbering simplifies + * identification of processors. + */ void cpu_topology_sort(int ncpus) { diff --git a/osfmk/i386/locks_i386.c b/osfmk/i386/locks_i386.c index 2b2ff9695..039584749 100644 --- a/osfmk/i386/locks_i386.c +++ b/osfmk/i386/locks_i386.c @@ -418,7 +418,7 @@ uint32_t spinlock_timeout_NMI(uintptr_t thread_addr) { uint32_t i; for (i = 0; i < real_ncpus; i++) { - if ((uintptr_t)cpu_data_ptr[i]->cpu_active_thread == thread_addr) { + if ((cpu_data_ptr[i] != NULL) && ((uintptr_t)cpu_data_ptr[i]->cpu_active_thread == thread_addr)) { spinlock_owner_cpu = i; if ((uint32_t) cpu_number() != i) { /* Cause NMI and panic on the owner's cpu */ @@ -1362,6 +1362,7 @@ lck_rw_unlock_shared( { lck_rw_type_t ret; + assertf(lck->lck_rw_shared_count > 0, "lck %p has shared_count=0x%x", lck, lck->lck_rw_shared_count); ret = lck_rw_done(lck); if (ret != LCK_RW_TYPE_SHARED) diff --git a/osfmk/i386/machine_routines.c b/osfmk/i386/machine_routines.c index cfe895601..68f9f7819 100644 --- a/osfmk/i386/machine_routines.c +++ b/osfmk/i386/machine_routines.c @@ -413,10 +413,6 @@ register_cpu( if (this_cpu_datap->cpu_console_buf == NULL) goto failed; - this_cpu_datap->cpu_chud = chudxnu_cpu_alloc(boot_cpu); - if (this_cpu_datap->cpu_chud == NULL) - goto failed; - #if KPC if (kpc_register_cpu(this_cpu_datap) != TRUE) goto failed; @@ -452,11 +448,10 @@ register_cpu( #if NCOPY_WINDOWS > 0 pmap_cpu_free(this_cpu_datap->cpu_pmap); #endif - chudxnu_cpu_free(this_cpu_datap->cpu_chud); console_cpu_free(this_cpu_datap->cpu_console_buf); #if KPC kpc_unregister_cpu(this_cpu_datap); -#endif +#endif /* KPC */ return KERN_FAILURE; } diff --git a/osfmk/i386/misc_protos.h b/osfmk/i386/misc_protos.h index 3e57debe3..178af299d 100644 --- a/osfmk/i386/misc_protos.h +++ b/osfmk/i386/misc_protos.h @@ -108,9 +108,6 @@ extern void dcache_incoherent_io_store64(addr64_t pa, unsigned int count); extern processor_t cpu_processor_alloc(boolean_t is_boot_cpu); extern void cpu_processor_free(processor_t proc); -extern void *chudxnu_cpu_alloc(boolean_t is_boot_cpu); -extern void chudxnu_cpu_free(void *); - extern void sysclk_gettime_interrupts_disabled( mach_timespec_t *cur_time); diff --git a/osfmk/i386/mp.c b/osfmk/i386/mp.c index 1c11d9601..3b7232687 100644 --- a/osfmk/i386/mp.c +++ b/osfmk/i386/mp.c @@ -77,9 +77,6 @@ #endif #include -#include -#include - #include #include @@ -552,10 +549,6 @@ cpu_signal_handler(x86_saved_state_t *regs) DBGLOG(cpu_handle,my_cpu,MP_TLB_FLUSH); i_bit_clear(MP_TLB_FLUSH, my_word); pmap_update_interrupt(); - } else if (i_bit(MP_CHUD, my_word)) { - DBGLOG(cpu_handle,my_cpu,MP_CHUD); - i_bit_clear(MP_CHUD, my_word); - chudxnu_cpu_signal_handler(); } else if (i_bit(MP_CALL, my_word)) { DBGLOG(cpu_handle,my_cpu,MP_CALL); i_bit_clear(MP_CALL, my_word); @@ -699,7 +692,7 @@ NMI_cpus(void) intrs_enabled = ml_set_interrupts_enabled(FALSE); for (cpu = 0; cpu < real_ncpus; cpu++) { - if (!cpu_datap(cpu)->cpu_running) + if (!cpu_is_running(cpu)) continue; cpu_datap(cpu)->cpu_NMI_acknowledged = FALSE; cpu_NMI_interrupt(cpu); @@ -1293,7 +1286,7 @@ mp_cpus_call1( } for (cpu = 0; cpu < (cpu_t) real_ncpus; cpu++) { if (((cpu_to_cpumask(cpu) & cpus) == 0) || - !cpu_datap(cpu)->cpu_running) + !cpu_is_running(cpu)) continue; tsc_spin_start = rdtsc64(); if (cpu == (cpu_t) cpu_number()) { @@ -1461,7 +1454,7 @@ mp_cpus_kick(cpumask_t cpus) for (cpu = 0; cpu < (cpu_t) real_ncpus; cpu++) { if ((cpu == (cpu_t) cpu_number()) || ((cpu_to_cpumask(cpu) & cpus) == 0) - || (!cpu_datap(cpu)->cpu_running)) + || !cpu_is_running(cpu)) { continue; } @@ -1619,7 +1612,7 @@ mp_kdp_enter(boolean_t proceed_on_failure) DBG("mp_kdp_enter() signaling other processors\n"); if (force_immediate_debugger_NMI == FALSE) { for (cpu = 0; cpu < real_ncpus; cpu++) { - if (cpu == my_cpu || !cpu_datap(cpu)->cpu_running) + if (cpu == my_cpu || !cpu_is_running(cpu)) continue; ncpus++; i386_signal_cpu(cpu, MP_KDP, ASYNC); @@ -1655,12 +1648,15 @@ mp_kdp_enter(boolean_t proceed_on_failure) NMIPI_enable(TRUE); } if (mp_kdp_ncpus != ncpus) { + cpumask_t cpus_NMI_pending = 0; DBG("mp_kdp_enter() timed-out on cpu %d, NMI-ing\n", my_cpu); for (cpu = 0; cpu < real_ncpus; cpu++) { - if (cpu == my_cpu || !cpu_datap(cpu)->cpu_running) + if (cpu == my_cpu || !cpu_is_running(cpu)) continue; - if (cpu_signal_pending(cpu, MP_KDP)) + if (cpu_signal_pending(cpu, MP_KDP)) { + cpus_NMI_pending |= cpu_to_cpumask(cpu); cpu_NMI_interrupt(cpu); + } } /* Wait again for the same timeout */ tsc_timeout = rdtsc64() + (LockTimeOutTSC); @@ -1669,13 +1665,13 @@ mp_kdp_enter(boolean_t proceed_on_failure) cpu_pause(); } if (mp_kdp_ncpus != ncpus) { - panic("mp_kdp_enter() timed-out waiting after NMI"); + kdb_printf("mp_kdp_enter(): %llu, %lu, %u TIMED-OUT WAITING FOR NMI-ACK, PROCEEDING\n", cpus_NMI_pending, mp_kdp_ncpus, ncpus); } } } else for (cpu = 0; cpu < real_ncpus; cpu++) { - if (cpu == my_cpu || !cpu_datap(cpu)->cpu_running) + if (cpu == my_cpu || !cpu_is_running(cpu)) continue; cpu_NMI_interrupt(cpu); } @@ -2024,7 +2020,7 @@ mp_interrupt_watchdog(void) cpu < (cpu_t) real_ncpus && !machine_timeout_suspended(); cpu++) { if ((cpu == (cpu_t) cpu_number()) || - (!cpu_datap(cpu)->cpu_running)) + (!cpu_is_running(cpu))) continue; cpu_int_event_time = cpu_datap(cpu)->cpu_int_event_time; if (cpu_int_event_time == 0) diff --git a/osfmk/i386/mp_events.h b/osfmk/i386/mp_events.h index 59c661e7a..6fd14ed44 100644 --- a/osfmk/i386/mp_events.h +++ b/osfmk/i386/mp_events.h @@ -41,7 +41,6 @@ typedef enum { MP_AST, MP_IDLE, MP_UNIDLE, - MP_CHUD, MP_CALL, MP_CALL_PM, MP_LAST @@ -55,7 +54,6 @@ const char *mp_event_name[] = { \ "MP_AST", \ "MP_IDLE", \ "MP_UNIDLE", \ - "MP_CHUD", \ "MP_CALL", \ "MP_CALL_PM", \ "MP_LAST" \ diff --git a/osfmk/i386/pcb.c b/osfmk/i386/pcb.c index 5fb9112ea..9a2ca4390 100644 --- a/osfmk/i386/pcb.c +++ b/osfmk/i386/pcb.c @@ -270,33 +270,32 @@ debug_state_is_valid64(x86_debug_state64_t *ds) static kern_return_t set_debug_state32(thread_t thread, x86_debug_state32_t *ds) { - x86_debug_state32_t *ids; + x86_debug_state32_t *new_ids; pcb_t pcb; pcb = THREAD_TO_PCB(thread); - ids = pcb->ids; if (debug_state_is_valid32(ds) != TRUE) { return KERN_INVALID_ARGUMENT; } - if (ids == NULL) { - ids = zalloc(ids_zone); - bzero(ids, sizeof *ids); + if (pcb->ids == NULL) { + new_ids = zalloc(ids_zone); + bzero(new_ids, sizeof *new_ids); simple_lock(&pcb->lock); /* make sure it wasn't already alloc()'d elsewhere */ if (pcb->ids == NULL) { - pcb->ids = ids; + pcb->ids = new_ids; simple_unlock(&pcb->lock); } else { simple_unlock(&pcb->lock); - zfree(ids_zone, ids); + zfree(ids_zone, new_ids); } } - copy_debug_state32(ds, ids, FALSE); + copy_debug_state32(ds, pcb->ids, FALSE); return (KERN_SUCCESS); } @@ -304,19 +303,18 @@ set_debug_state32(thread_t thread, x86_debug_state32_t *ds) static kern_return_t set_debug_state64(thread_t thread, x86_debug_state64_t *ds) { - x86_debug_state64_t *ids; + x86_debug_state64_t *new_ids; pcb_t pcb; pcb = THREAD_TO_PCB(thread); - ids = pcb->ids; if (debug_state_is_valid64(ds) != TRUE) { return KERN_INVALID_ARGUMENT; } - if (ids == NULL) { - ids = zalloc(ids_zone); - bzero(ids, sizeof *ids); + if (pcb->ids == NULL) { + new_ids = zalloc(ids_zone); + bzero(new_ids, sizeof *new_ids); #if HYPERVISOR if (thread->hv_thread_target) { @@ -328,15 +326,15 @@ set_debug_state64(thread_t thread, x86_debug_state64_t *ds) simple_lock(&pcb->lock); /* make sure it wasn't already alloc()'d elsewhere */ if (pcb->ids == NULL) { - pcb->ids = ids; + pcb->ids = new_ids; simple_unlock(&pcb->lock); } else { simple_unlock(&pcb->lock); - zfree(ids_zone, ids); + zfree(ids_zone, new_ids); } } - copy_debug_state64(ds, ids, FALSE); + copy_debug_state64(ds, pcb->ids, FALSE); return (KERN_SUCCESS); } diff --git a/osfmk/i386/pmCPU.c b/osfmk/i386/pmCPU.c index c9be4ab8b..de55ad8dd 100644 --- a/osfmk/i386/pmCPU.c +++ b/osfmk/i386/pmCPU.c @@ -811,6 +811,7 @@ machine_work_interval_notify(__unused thread_t thread, { } + void machine_switch_perfcontrol_context(__unused perfcontrol_event event, __unused uint64_t timestamp, __unused uint32_t flags, diff --git a/osfmk/i386/rtclock_asm.h b/osfmk/i386/rtclock_asm.h index 9a380be1e..dba69a6e7 100644 --- a/osfmk/i386/rtclock_asm.h +++ b/osfmk/i386/rtclock_asm.h @@ -54,7 +54,7 @@ #define NANOTIME \ movq %gs:CPU_NANOTIME,%rdi ; \ PAL_RTC_NANOTIME_READ_FAST() -/* TODO nobarrier */ + /* * Add 64-bit delta in register reg to timer pointed to by register treg. */ diff --git a/osfmk/i386/trap.c b/osfmk/i386/trap.c index bb1f9a17e..d0ac3be95 100644 --- a/osfmk/i386/trap.c +++ b/osfmk/i386/trap.c @@ -119,8 +119,6 @@ static void user_page_fault_continue(kern_return_t kret); static void panic_trap(x86_saved_state64_t *saved_state, uint32_t pl, kern_return_t fault_result); static void set_recovery_ip(x86_saved_state64_t *saved_state, vm_offset_t ip); -volatile perfCallback perfTrapHook = NULL; /* Pointer to CHUD trap hook routine */ - #if CONFIG_DTRACE /* See */ perfCallback tempDTraceTrapHook = NULL; /* Pointer to DTrace fbt trap hook routine */ @@ -498,7 +496,6 @@ kernel_trap( kern_return_t result = KERN_FAILURE; kern_return_t fault_result = KERN_SUCCESS; thread_t thread; - ast_t *myast; boolean_t intr; vm_prot_t prot; struct recovery *rp; @@ -524,18 +521,8 @@ kernel_trap( intr = (saved_state->isf.rflags & EFL_IF) != 0; /* state of ints at trap */ kern_ip = (vm_offset_t)saved_state->isf.rip; - myast = ast_pending(); - is_user = (vaddr < VM_MAX_USER_PAGE_ADDRESS); - perfASTCallback astfn = perfASTHook; - if (__improbable(astfn != NULL)) { - if (*myast & AST_CHUD_ALL) - astfn(AST_CHUD_ALL, myast); - } else - *myast &= ~AST_CHUD_ALL; - - #if CONFIG_DTRACE /* * Is there a DTrace hook? @@ -885,7 +872,6 @@ user_trap( user_addr_t vaddr; vm_prot_t prot; thread_t thread = current_thread(); - ast_t *myast; kern_return_t kret; user_addr_t rip; unsigned long dr6 = 0; /* 32 bit for i386, 64 bit for x86_64 */ @@ -939,21 +925,6 @@ user_trap( subcode = 0; exc = 0; - perfASTCallback astfn = perfASTHook; - if (__improbable(astfn != NULL)) { - myast = ast_pending(); - if (*myast & AST_CHUD_ALL) { - astfn(AST_CHUD_ALL, myast); - } - } - - /* Is there a hook? */ - perfCallback fn = perfTrapHook; - if (__improbable(fn != NULL)) { - if (fn(type, saved_state, 0, 0) == KERN_SUCCESS) - return; /* If it succeeds, we are done... */ - } - #if CONFIG_DTRACE /* * DTrace does not consume all user traps, only INT_3's for now. diff --git a/osfmk/i386/trap.h b/osfmk/i386/trap.h index 33676cf75..6966aeca2 100644 --- a/osfmk/i386/trap.h +++ b/osfmk/i386/trap.h @@ -141,12 +141,6 @@ typedef kern_return_t (*perfCallback)( uintptr_t *lo_spp, int); -typedef kern_return_t (*perfASTCallback)(ast_t reasons, ast_t *myast); - -extern volatile perfCallback perfTrapHook; -extern volatile perfASTCallback perfASTHook; -extern volatile perfCallback perfIntHook; - extern void panic_i386_backtrace(void *, int, const char *, boolean_t, x86_saved_state_t *); extern void print_one_backtrace(pmap_t pmap, vm_offset_t topfp, const char *cur_marker, boolean_t is_64_bit); extern void print_thread_num_that_crashed(task_t task); diff --git a/osfmk/ipc/ipc_kmsg.c b/osfmk/ipc/ipc_kmsg.c index e5445a290..736fe824c 100644 --- a/osfmk/ipc/ipc_kmsg.c +++ b/osfmk/ipc/ipc_kmsg.c @@ -720,7 +720,7 @@ void ipc_kmsg_trace_send(ipc_kmsg_t kmsg, case IKOT_MASTER_DEVICE: case IKOT_IOKIT_CONNECT: case IKOT_IOKIT_OBJECT: - case IKOT_IOKIT_SPARE: + case IKOT_IOKIT_IDENT: msg_flags |= KMSG_TRACE_FLAG_IOKIT; break; default: diff --git a/osfmk/kdp/kdp_core.c b/osfmk/kdp/kdp_core.c index ac71c8061..c3ea1037c 100644 --- a/osfmk/kdp/kdp_core.c +++ b/osfmk/kdp/kdp_core.c @@ -862,6 +862,13 @@ pmap_traverse_present_mappings(pmap_t __unused pmap, /* send previous run */ ret = callback(vcurstart, vcur, context); } + +#if KASAN + if (ret == KERN_SUCCESS) { + ret = kasan_traverse_mappings(callback, context); + } +#endif + return (ret); } diff --git a/osfmk/kdp/ml/x86_64/kdp_vm.c b/osfmk/kdp/ml/x86_64/kdp_vm.c index 244ac7d07..8f5403edf 100644 --- a/osfmk/kdp/ml/x86_64/kdp_vm.c +++ b/osfmk/kdp/ml/x86_64/kdp_vm.c @@ -100,9 +100,7 @@ kern_collectth_state(thread_t thread, void *buffer, uint64_t size, void ** iter) /* Locate and obtain the non-volatile register context * for this kernel thread. This should ideally be - * encapsulated in machine_thread_get_kern_state() - * but that routine appears to have been co-opted - * by CHUD to obtain pre-interrupt state. + * encapsulated in machine_thread_get_kern_state(). */ if (thread_flavor_array[i].flavor == x86_THREAD_STATE64) { x86_thread_state64_t *tstate = (x86_thread_state64_t *) ((uintptr_t)buffer + hoffset); diff --git a/osfmk/kern/Makefile b/osfmk/kern/Makefile index e0480272f..dcde0c50e 100644 --- a/osfmk/kern/Makefile +++ b/osfmk/kern/Makefile @@ -1,3 +1,4 @@ + export MakeInc_cmd=${SRCROOT}/makedefs/MakeInc.cmd export MakeInc_def=${SRCROOT}/makedefs/MakeInc.def export MakeInc_rule=${SRCROOT}/makedefs/MakeInc.rule @@ -79,7 +80,7 @@ INSTALL_KF_MI_LCL_LIST = ${DATAFILES} ${PRIVATE_DATAFILES} ${EXPORT_FILES} ${PRI INSTALL_MI_DIR = kern -EXPORT_MI_LIST = ${DATAFILES} ${PRIVATE_DATAFILES} ${EXPORT_FILES} +EXPORT_MI_LIST = ${DATAFILES} ${PRIVATE_DATAFILES} ${EXPORT_FILES} ipc_kobject.h EXPORT_MI_DIR = kern diff --git a/osfmk/kern/ast.h b/osfmk/kern/ast.h index 4710f64ed..d41821e2d 100644 --- a/osfmk/kern/ast.h +++ b/osfmk/kern/ast.h @@ -118,8 +118,7 @@ typedef uint32_t ast_t; #define AST_BSD 0x80 #define AST_KPERF 0x100 /* kernel profiling */ #define AST_MACF 0x200 /* MACF user ret pending */ -#define AST_CHUD 0x400 -#define AST_CHUD_URGENT 0x800 +/* 0x400, 0x800 unused */ #define AST_GUARD 0x1000 #define AST_TELEMETRY_USER 0x2000 /* telemetry sample requested on interrupt from userspace */ #define AST_TELEMETRY_KERNEL 0x4000 /* telemetry sample requested on interrupt from kernel */ @@ -135,7 +134,6 @@ typedef uint32_t ast_t; #define AST_SCHEDULING (AST_PREEMPTION | AST_YIELD | AST_HANDOFF) #define AST_PREEMPTION (AST_PREEMPT | AST_QUANTUM | AST_URGENT) -#define AST_CHUD_ALL (AST_CHUD_URGENT|AST_CHUD) #define AST_TELEMETRY_ALL (AST_TELEMETRY_USER | AST_TELEMETRY_KERNEL | AST_TELEMETRY_IO) /* Per-thread ASTs follow the thread at context-switch time. */ diff --git a/osfmk/kern/bsd_kern.c b/osfmk/kern/bsd_kern.c index 7196cc5c6..f70820520 100644 --- a/osfmk/kern/bsd_kern.c +++ b/osfmk/kern/bsd_kern.c @@ -1032,20 +1032,20 @@ fill_task_qos_rusage(task_t task, rusage_info_current *ri) assert(task != TASK_NULL); task_lock(task); - /* Rollup Qos time of all the threads to task */ + /* Rollup QoS time of all the threads to task */ queue_iterate(&task->threads, thread, thread_t, task_threads) { if (thread->options & TH_OPT_IDLE_THREAD) continue; thread_update_qos_cpu_time(thread); } - ri->ri_cpu_time_qos_default = task->cpu_time_qos_stats.cpu_time_qos_default; - ri->ri_cpu_time_qos_maintenance = task->cpu_time_qos_stats.cpu_time_qos_maintenance; - ri->ri_cpu_time_qos_background = task->cpu_time_qos_stats.cpu_time_qos_background; - ri->ri_cpu_time_qos_utility = task->cpu_time_qos_stats.cpu_time_qos_utility; - ri->ri_cpu_time_qos_legacy = task->cpu_time_qos_stats.cpu_time_qos_legacy; - ri->ri_cpu_time_qos_user_initiated = task->cpu_time_qos_stats.cpu_time_qos_user_initiated; - ri->ri_cpu_time_qos_user_interactive = task->cpu_time_qos_stats.cpu_time_qos_user_interactive; + ri->ri_cpu_time_qos_default = task->cpu_time_eqos_stats.cpu_time_qos_default; + ri->ri_cpu_time_qos_maintenance = task->cpu_time_eqos_stats.cpu_time_qos_maintenance; + ri->ri_cpu_time_qos_background = task->cpu_time_eqos_stats.cpu_time_qos_background; + ri->ri_cpu_time_qos_utility = task->cpu_time_eqos_stats.cpu_time_qos_utility; + ri->ri_cpu_time_qos_legacy = task->cpu_time_eqos_stats.cpu_time_qos_legacy; + ri->ri_cpu_time_qos_user_initiated = task->cpu_time_eqos_stats.cpu_time_qos_user_initiated; + ri->ri_cpu_time_qos_user_interactive = task->cpu_time_eqos_stats.cpu_time_qos_user_interactive; task_unlock(task); return (0); diff --git a/osfmk/kern/coalition.c b/osfmk/kern/coalition.c index 9db2789ef..ed24958c1 100644 --- a/osfmk/kern/coalition.c +++ b/osfmk/kern/coalition.c @@ -167,6 +167,12 @@ static int i_coal_resource_get_taskrole(coalition_t coal, task_t task) static void i_coal_resource_iterate_tasks(coalition_t coal, void *ctx, void (*callback)(coalition_t, void *, task_t)); +/* + * Ensure COALITION_NUM_THREAD_QOS_TYPES defined in mach/coalition.h still + * matches THREAD_QOS_LAST defined in mach/thread_policy.h + */ +static_assert(COALITION_NUM_THREAD_QOS_TYPES == THREAD_QOS_LAST); + struct i_resource_coalition { ledger_t ledger; uint64_t bytesread; @@ -178,6 +184,8 @@ struct i_resource_coalition { uint64_t logical_invalidated_writes; uint64_t logical_metadata_writes; uint64_t cpu_ptime; + uint64_t cpu_time_eqos[COALITION_NUM_THREAD_QOS_TYPES]; /* cpu time per effective QoS class */ + uint64_t cpu_time_rqos[COALITION_NUM_THREAD_QOS_TYPES]; /* cpu time per requested QoS class */ uint64_t task_count; /* tasks that have started in this coalition */ uint64_t dead_task_count; /* tasks that have exited in this coalition; @@ -424,6 +432,7 @@ i_coal_resource_remove_task(coalition_t coal, task_t task) cr->logical_invalidated_writes += task->task_invalidated_writes; cr->logical_metadata_writes += task->task_metadata_writes; cr->cpu_ptime += task_cpu_ptime(task); + task_update_cpu_time_qos_stats(task, cr->cpu_time_eqos, cr->cpu_time_rqos); } /* remove the task from the coalition's list */ @@ -509,7 +518,10 @@ coalition_resource_usage_internal(coalition_t coal, struct coalition_resource_us int64_t energy_billed_to_me = 0; int64_t energy_billed_to_others = 0; uint64_t cpu_ptime = coal->r.cpu_ptime; - + uint64_t cpu_time_eqos[COALITION_NUM_THREAD_QOS_TYPES]; + memcpy(cpu_time_eqos, coal->r.cpu_time_eqos, sizeof(cpu_time_eqos)); + uint64_t cpu_time_rqos[COALITION_NUM_THREAD_QOS_TYPES]; + memcpy(cpu_time_rqos, coal->r.cpu_time_rqos, sizeof(cpu_time_rqos)); /* * Add to that all the active tasks' ledgers. Tasks cannot deallocate * out from under us, since we hold the coalition lock. @@ -537,6 +549,7 @@ coalition_resource_usage_internal(coalition_t coal, struct coalition_resource_us logical_invalidated_writes += task->task_invalidated_writes; logical_metadata_writes += task->task_metadata_writes; cpu_ptime += task_cpu_ptime(task); + task_update_cpu_time_qos_stats(task, cpu_time_eqos, cpu_time_rqos); } kr = ledger_get_balance(sum_ledger, task_ledgers.cpu_time_billed_to_me, (int64_t *)&cpu_time_billed_to_me); @@ -603,7 +616,8 @@ coalition_resource_usage_internal(coalition_t coal, struct coalition_resource_us cru_out->logical_invalidated_writes = logical_invalidated_writes; cru_out->logical_metadata_writes = logical_metadata_writes; cru_out->cpu_ptime = cpu_ptime; - + cru_out->cpu_time_eqos_len = COALITION_NUM_THREAD_QOS_TYPES; + memcpy(cru_out->cpu_time_eqos, cpu_time_eqos, sizeof(cru_out->cpu_time_eqos)); ledger_dereference(sum_ledger); sum_ledger = LEDGER_NULL; diff --git a/osfmk/kern/debug.c b/osfmk/kern/debug.c index a84f86d75..313c979b5 100644 --- a/osfmk/kern/debug.c +++ b/osfmk/kern/debug.c @@ -684,7 +684,7 @@ panic_trap_to_debugger(const char *panic_format_str, va_list *panic_args, unsign if (write_trace_on_panic && kdebug_enable) { if (get_preemption_level() == 0 && !ml_at_interrupt_context()) { ml_set_interrupts_enabled(TRUE); - KDBG(TRACE_PANIC); + KDBG_RELEASE(TRACE_PANIC); kdbg_dump_trace_to_file(KDBG_TRACE_PANIC_FILENAME); } } diff --git a/osfmk/kern/debug.h b/osfmk/kern/debug.h index 6289eeecd..860824c04 100644 --- a/osfmk/kern/debug.h +++ b/osfmk/kern/debug.h @@ -276,10 +276,15 @@ struct embedded_panic_header { uint32_t eph_stackshot_len; /* length of the panic stackshot (0 if not valid ) */ uint32_t eph_other_log_offset; /* Offset of the other log (any logging subsequent to the stackshot) from the beginning of the header */ uint32_t eph_other_log_len; /* length of the other log */ - uint64_t eph_x86_power_state:8, - eph_x86_efi_boot_state:8, - eph_x86_system_state:8, - eph_x86_unused_bits:40; + union { + struct { + uint64_t eph_x86_power_state:8, + eph_x86_efi_boot_state:8, + eph_x86_system_state:8, + eph_x86_unused_bits:40; + }; // anonymous struct to group the bitfields together. + uint64_t eph_x86_do_not_use; /* Used for offsetof/sizeof when parsing header */ + }; } __attribute__((packed)); #define EMBEDDED_PANIC_HEADER_FLAG_COREDUMP_COMPLETE 0x01 @@ -324,6 +329,7 @@ struct macos_panic_header { #define MACOS_PANIC_HEADER_FLAG_STACKSHOT_FAILED_NESTED 0x80 #define MACOS_PANIC_HEADER_FLAG_COREDUMP_COMPLETE 0x100 #define MACOS_PANIC_HEADER_FLAG_COREDUMP_FAILED 0x200 +#define MACOS_PANIC_HEADER_FLAG_STACKSHOT_KERNEL_ONLY 0x400 #endif /* __APPLE_API_UNSTABLE */ #endif /* __APPLE_API_PRIVATE */ diff --git a/osfmk/kern/ipc_kobject.c b/osfmk/kern/ipc_kobject.c index 1acc81c4a..181bb0383 100644 --- a/osfmk/kern/ipc_kobject.c +++ b/osfmk/kern/ipc_kobject.c @@ -700,7 +700,7 @@ ipc_kobject_notify( #ifdef IOKIT case IKOT_IOKIT_OBJECT: case IKOT_IOKIT_CONNECT: - case IKOT_IOKIT_SPARE: + case IKOT_IOKIT_IDENT: { return iokit_notify(request_header); } diff --git a/osfmk/kern/ipc_kobject.h b/osfmk/kern/ipc_kobject.h index 74c4768c0..52431b60e 100644 --- a/osfmk/kern/ipc_kobject.h +++ b/osfmk/kern/ipc_kobject.h @@ -69,8 +69,10 @@ * Declarations for letting a port represent a kernel object. */ +#ifdef MACH_KERNEL_PRIVATE #include #include +#endif /* MACH_KERNEL_PRIVATE */ #ifndef _KERN_IPC_KOBJECT_H_ #define _KERN_IPC_KOBJECT_H_ @@ -114,7 +116,7 @@ typedef natural_t ipc_kobject_type_t; #define IKOT_LOCK_SET 24 #define IKOT_CLOCK 25 #define IKOT_CLOCK_CTRL 26 -#define IKOT_IOKIT_SPARE 27 +#define IKOT_IOKIT_IDENT 27 #define IKOT_NAMED_ENTRY 28 #define IKOT_IOKIT_CONNECT 29 #define IKOT_IOKIT_OBJECT 30 @@ -138,6 +140,8 @@ typedef natural_t ipc_kobject_type_t; #define is_ipc_kobject(ikot) ((ikot) != IKOT_NONE) +#ifdef MACH_KERNEL_PRIVATE + /* * Define types of kernel objects that use page lists instead * of entry lists for copyin of out of line memory. @@ -165,6 +169,8 @@ extern void ipc_kobject_destroy( #define null_conversion(port) (port) +#endif /* MACH_KERNEL_PRIVATE */ + #endif /* KERNEL_PRIVATE */ #endif /* _KERN_IPC_KOBJECT_H_ */ diff --git a/osfmk/kern/kalloc.c b/osfmk/kern/kalloc.c index fa13463fe..65e9df392 100644 --- a/osfmk/kern/kalloc.c +++ b/osfmk/kern/kalloc.c @@ -67,6 +67,7 @@ #include #include +#include #include #include #include @@ -128,129 +129,95 @@ KALLOC_ZINFO_SFREE(vm_size_t bytes) } /* - * All allocations of size less than kalloc_max are rounded to the - * next nearest sized zone. This allocator is built on top of - * the zone allocator. A zone is created for each potential size - * that we are willing to get in small blocks. + * All allocations of size less than kalloc_max are rounded to the next nearest + * sized zone. This allocator is built on top of the zone allocator. A zone + * is created for each potential size that we are willing to get in small + * blocks. * - * We assume that kalloc_max is not greater than 64K; + * We assume that kalloc_max is not greater than 64K; * - * Note that kalloc_max is somewhat confusingly named. - * It represents the first power of two for which no zone exists. - * kalloc_max_prerounded is the smallest allocation size, before - * rounding, for which no zone exists. + * Note that kalloc_max is somewhat confusingly named. It represents the first + * power of two for which no zone exists. kalloc_max_prerounded is the + * smallest allocation size, before rounding, for which no zone exists. * - * Also if the allocation size is more than kalloc_kernmap_size - * then allocate from kernel map rather than kalloc_map. + * Also if the allocation size is more than kalloc_kernmap_size then allocate + * from kernel map rather than kalloc_map. */ -#if KALLOC_MINSIZE == 16 && KALLOC_LOG2_MINALIGN == 4 +#define KALLOC_MINALIGN (1 << KALLOC_LOG2_MINALIGN) +#define KiB(x) (1024 * (x)) -#define K_ZONE_SIZES \ - 16, \ - 32, \ - 48, \ - 64, /* 2^6 */ \ - 80, \ - 96, \ - 128, /* 2^7 */ \ - 160, \ - 192, \ - 224, \ - 256, /* 2^8 */ \ - 288, \ - 368, \ - 400, \ - 512, /* 2^9 */\ - 576, \ - 768, \ - 1024, /* 2^10 */ \ - 1152, \ - 1280, \ - 1664, \ - 2048, /* 2^11 */ \ - 4096, /* 2^12 */ \ - 6144 - -#define K_ZONE_NAMES \ - "kalloc.16", \ - "kalloc.32", \ - "kalloc.48", \ - "kalloc.64", /* 2^6 */ \ - "kalloc.80", \ - "kalloc.96", \ - "kalloc.128", /* 2^7 */ \ - "kalloc.160", \ - "kalloc.192", \ - "kalloc.224", \ - "kalloc.256", /* 2^8 */\ - "kalloc.288", \ - "kalloc.368", \ - "kalloc.400", \ - "kalloc.512", /* 2^9 */ \ - "kalloc.576", \ - "kalloc.768", \ - "kalloc.1024", /* 2^10 */ \ - "kalloc.1152", \ - "kalloc.1280", \ - "kalloc.1664", \ - "kalloc.2048", /* 2^11 */ \ - "kalloc.4096", /* 2^12 */ \ - "kalloc.6144" +static const struct kalloc_zone_config { + int kzc_size; + const char *kzc_name; +} k_zone_config[] = { +#define KZC_ENTRY(SIZE) { .kzc_size = (SIZE), .kzc_name = "kalloc." #SIZE } +#if KALLOC_MINSIZE == 16 && KALLOC_LOG2_MINALIGN == 4 + /* 64-bit targets, generally */ + KZC_ENTRY(16), + KZC_ENTRY(32), + KZC_ENTRY(48), + KZC_ENTRY(64), + KZC_ENTRY(80), + KZC_ENTRY(96), + KZC_ENTRY(128), + KZC_ENTRY(160), + KZC_ENTRY(192), + KZC_ENTRY(224), + KZC_ENTRY(256), + KZC_ENTRY(288), + KZC_ENTRY(368), + KZC_ENTRY(400), + KZC_ENTRY(512), + KZC_ENTRY(576), + KZC_ENTRY(768), + KZC_ENTRY(1024), + KZC_ENTRY(1152), + KZC_ENTRY(1280), + KZC_ENTRY(1664), + KZC_ENTRY(2048), #elif KALLOC_MINSIZE == 8 && KALLOC_LOG2_MINALIGN == 3 - -/* - * Tweaked for ARM (and x64) in 04/2011 - */ - -#define K_ZONE_SIZES \ -/* 3 */ 8, \ - 16, 24, \ - 32, 40, 48, \ -/* 6 */ 64, 72, 88, 112, \ - 128, 192, \ - 256, 288, 384, 440, \ -/* 9 */ 512, 576, 768, \ - 1024, 1152, 1536, \ - 2048, 2128, 3072, \ - 4096, 6144 - -#define K_ZONE_NAMES \ -/* 3 */ "kalloc.8", \ - "kalloc.16", "kalloc.24", \ - "kalloc.32", "kalloc.40", "kalloc.48", \ -/* 6 */ "kalloc.64", "kalloc.72", "kalloc.88", "kalloc.112", \ - "kalloc.128", "kalloc.192", \ - "kalloc.256", "kalloc.288", "kalloc.384", "kalloc.440", \ -/* 9 */ "kalloc.512", "kalloc.576", "kalloc.768", \ - "kalloc.1024", "kalloc.1152", "kalloc.1536", \ - "kalloc.2048", "kalloc.2128", "kalloc.3072", \ - "kalloc.4096", "kalloc.6144" - + /* 32-bit targets, generally */ + KZC_ENTRY(8), + KZC_ENTRY(16), + KZC_ENTRY(24), + KZC_ENTRY(32), + KZC_ENTRY(40), + KZC_ENTRY(48), + KZC_ENTRY(64), + KZC_ENTRY(72), + KZC_ENTRY(88), + KZC_ENTRY(112), + KZC_ENTRY(128), + KZC_ENTRY(192), + KZC_ENTRY(256), + KZC_ENTRY(288), + KZC_ENTRY(384), + KZC_ENTRY(440), + KZC_ENTRY(512), + KZC_ENTRY(576), + KZC_ENTRY(768), + KZC_ENTRY(1024), + KZC_ENTRY(1152), + KZC_ENTRY(1536), + KZC_ENTRY(2048), + KZC_ENTRY(2128), + KZC_ENTRY(3072), #else #error missing or invalid zone size parameters for kalloc #endif -#define KALLOC_MINALIGN (1 << KALLOC_LOG2_MINALIGN) -#define KiB(x) (1024 * (x)) - -static const int k_zone_size[] = { - K_ZONE_SIZES, - KiB(8), - KiB(16), - KiB(32) -}; - -#define MAX_K_ZONE (sizeof (k_zone_size) / sizeof (k_zone_size[0])) - -static const char *k_zone_name[MAX_K_ZONE] = { - K_ZONE_NAMES, - "kalloc.8192", - "kalloc.16384", - "kalloc.32768" + /* all configurations get these zones */ + KZC_ENTRY(4096), + KZC_ENTRY(6144), + KZC_ENTRY(8192), + KZC_ENTRY(16384), + KZC_ENTRY(32768), +#undef KZC_ENTRY }; +#define MAX_K_ZONE (int)(sizeof(k_zone_config) / sizeof(k_zone_config[0])) /* * Many kalloc() allocations are for small structures containing a few @@ -316,7 +283,6 @@ kalloc_init( kern_return_t retval; vm_offset_t min; vm_size_t size, kalloc_map_size; - int i; vm_map_kernel_flags_t vmk_flags; /* @@ -348,10 +314,10 @@ kalloc_init( kalloc_map_max = min + kalloc_map_size - 1; /* - * Create zones up to a least 2 pages because small page-multiples are common - * allocations. Also ensure that zones up to size 8192 bytes exist. This is - * desirable because messages are allocated with kalloc(), and messages up - * through size 8192 are common. + * Create zones up to a least 4 pages because small page-multiples are + * common allocations. Also ensure that zones up to size 16KB bytes exist. + * This is desirable because messages are allocated with kalloc(), and + * messages up through size 8192 are common. */ kalloc_max = PAGE_SIZE << 2; if (kalloc_max < KiB(16)) { @@ -365,12 +331,15 @@ kalloc_init( kalloc_largest_allocated = kalloc_kernmap_size; /* - * Allocate a zone for each size we are going to handle. Don't charge the - * caller for the allocation, as we aren't sure how the memory will be - * handled. + * Allocate a zone for each size we are going to handle. */ - for (i = 0; i < (int)MAX_K_ZONE && (size = k_zone_size[i]) < kalloc_max; i++) { - k_zone[i] = zinit(size, size, size, k_zone_name[i]); + for (int i = 0; i < MAX_K_ZONE && (size = k_zone_config[i].kzc_size) < kalloc_max; i++) { + k_zone[i] = zinit(size, size, size, k_zone_config[i].kzc_name); + + /* + * Don't charge the caller for the allocation, as we aren't sure how + * the memory will be handled. + */ zone_change(k_zone[i], Z_CALLERACCT, FALSE); #if VM_MAX_TAG_ZONES if (zone_tagging_on) zone_change(k_zone[i], Z_TAGS_ENABLED, TRUE); @@ -381,10 +350,11 @@ kalloc_init( /* * Build the Direct LookUp Table for small allocations */ - for (i = 0, size = 0; i <= N_K_ZDLUT; i++, size += KALLOC_MINALIGN) { + size = 0; + for (int i = 0; i <= N_K_ZDLUT; i++, size += KALLOC_MINALIGN) { int zindex = 0; - while ((vm_size_t)k_zone_size[zindex] < size) + while ((vm_size_t)k_zone_config[zindex].kzc_size < size) zindex++; if (i == N_K_ZDLUT) { @@ -403,8 +373,8 @@ kalloc_init( * Useful when debugging/tweaking the array of zone sizes. * Cache misses probably more critical than compare-branches! */ - for (i = 0; i < (int)MAX_K_ZONE; i++) { - vm_size_t testsize = (vm_size_t)k_zone_size[i] - 1; + for (int i = 0; i < MAX_K_ZONE; i++) { + vm_size_t testsize = (vm_size_t)k_zone_config[i].kzc_size - 1; int compare = 0; int zindex; @@ -419,7 +389,7 @@ kalloc_init( compare += 2; /* 'if' (F), 'if' (T) */ zindex = k_zindex_start; - while ((vm_size_t)k_zone_size[zindex] < testsize) { + while ((vm_size_t)k_zone_config[zindex].kzc_size < testsize) { zindex++; compare++; /* 'while' (T) */ } @@ -454,18 +424,18 @@ get_zone_dlut(vm_size_t size) return (k_zone[zindex]); } -/* As above, but linear search k_zone_size[] for the next zone that fits. */ +/* As above, but linear search k_zone_config[] for the next zone that fits. */ static __inline zone_t get_zone_search(vm_size_t size, int zindex) { assert(size < kalloc_max_prerounded); - while ((vm_size_t)k_zone_size[zindex] < size) + while ((vm_size_t)k_zone_config[zindex].kzc_size < size) zindex++; - assert((unsigned)zindex < MAX_K_ZONE && - (vm_size_t)k_zone_size[zindex] < kalloc_max); + assert(zindex < MAX_K_ZONE && + (vm_size_t)k_zone_config[zindex].kzc_size < kalloc_max); return (k_zone[zindex]); } @@ -574,6 +544,7 @@ kfree_addr( size = zone_element_size(addr, &z); if (size) { + DTRACE_VM3(kfree, vm_size_t, -1, vm_size_t, z->elem_size, void*, addr); zfree(z, addr); return size; } @@ -600,6 +571,7 @@ kfree_addr( addr, map, ret); } vm_map_unlock(map); + DTRACE_VM3(kfree, vm_size_t, -1, vm_size_t, size, void*, addr); kalloc_spin_lock(); kalloc_large_total -= size; @@ -699,6 +671,7 @@ kalloc_canblock( #else *psize = round_page(size); #endif + DTRACE_VM3(kalloc, vm_size_t, size, vm_size_t, *psize, void*, addr); return(addr); } #ifdef KALLOC_DEBUG @@ -729,6 +702,7 @@ kalloc_canblock( *psize = z->elem_size; #endif + DTRACE_VM3(kalloc, vm_size_t, size, vm_size_t, *psize, void*, addr); return addr; } @@ -808,6 +782,10 @@ kfree( kalloc_unlock(); +#if !KASAN_KALLOC + DTRACE_VM3(kfree, vm_size_t, size, vm_size_t, size, void*, data); +#endif + KALLOC_ZINFO_SFREE(size); return; } @@ -819,6 +797,7 @@ kfree( z, z->zone_name, (unsigned long)size); #endif assert(size <= z->elem_size); + DTRACE_VM3(kfree, vm_size_t, size, vm_size_t, z->elem_size, void*, data); zfree(z, data); } diff --git a/osfmk/kern/kcdata.h b/osfmk/kern/kcdata.h index e358b4ec8..702bfacbc 100644 --- a/osfmk/kern/kcdata.h +++ b/osfmk/kern/kcdata.h @@ -456,7 +456,7 @@ struct kcdata_type_definition { #define STACKSHOT_KCTYPE_DELTA_SINCE_TIMESTAMP 0x912u /* timestamp used for the delta stackshot */ #define STACKSHOT_KCTYPE_TASK_DELTA_SNAPSHOT 0x940u /* task_delta_snapshot_v2 */ -#define STACKSHOT_KCTYPE_THREAD_DELTA_SNAPSHOT 0x941u /* thread_delta_snapshot_v2 */ +#define STACKSHOT_KCTYPE_THREAD_DELTA_SNAPSHOT 0x941u /* thread_delta_snapshot_v* */ #define STACKSHOT_KCTYPE_KERN_STACKLR 0x913u /* uint32_t */ #define STACKSHOT_KCTYPE_KERN_STACKLR64 0x914u /* uint64_t */ @@ -704,6 +704,23 @@ struct thread_delta_snapshot_v2 { uint8_t tds_io_tier; } __attribute__ ((packed)); +struct thread_delta_snapshot_v3 { + uint64_t tds_thread_id; + uint64_t tds_voucher_identifier; + uint64_t tds_ss_flags; + uint64_t tds_last_made_runnable_time; + uint32_t tds_state; + uint32_t tds_sched_flags; + int16_t tds_base_priority; + int16_t tds_sched_priority; + uint8_t tds_eqos; + uint8_t tds_rqos; + uint8_t tds_rqos_override; + uint8_t tds_io_tier; + uint64_t tds_requested_policy; + uint64_t tds_effective_policy; +} __attribute__ ((packed)); + struct io_stats_snapshot { /* @@ -805,13 +822,22 @@ typedef struct stackshot_thread_waitinfo { /* FIXME some of these types aren't clean (fixed width, packed, and defined *here*) */ +struct crashinfo_proc_uniqidentifierinfo { + uint8_t p_uuid[16]; /* UUID of the main executable */ + uint64_t p_uniqueid; /* 64 bit unique identifier for process */ + uint64_t p_puniqueid; /* unique identifier for process's parent */ + uint64_t p_reserve2; /* reserved for future use */ + uint64_t p_reserve3; /* reserved for future use */ + uint64_t p_reserve4; /* reserved for future use */ +} __attribute__((packed)); + #define TASK_CRASHINFO_BEGIN KCDATA_BUFFER_BEGIN_CRASHINFO #define TASK_CRASHINFO_STRING_DESC KCDATA_TYPE_STRING_DESC #define TASK_CRASHINFO_UINT32_DESC KCDATA_TYPE_UINT32_DESC #define TASK_CRASHINFO_UINT64_DESC KCDATA_TYPE_UINT64_DESC #define TASK_CRASHINFO_EXTMODINFO 0x801 -#define TASK_CRASHINFO_BSDINFOWITHUNIQID 0x802 /* struct proc_uniqidentifierinfo */ +#define TASK_CRASHINFO_BSDINFOWITHUNIQID 0x802 /* struct crashinfo_proc_uniqidentifierinfo */ #define TASK_CRASHINFO_TASKDYLD_INFO 0x803 #define TASK_CRASHINFO_UUID 0x804 #define TASK_CRASHINFO_PID 0x805 diff --git a/osfmk/kern/kern_cdata.c b/osfmk/kern/kern_cdata.c index 6070cdc26..97bee226c 100644 --- a/osfmk/kern/kern_cdata.c +++ b/osfmk/kern/kern_cdata.c @@ -186,23 +186,24 @@ static kern_return_t kcdata_get_memory_addr_with_flavor( mach_vm_address_t *user_addr) { struct kcdata_item info; - uint32_t total_size; - - if (user_addr == NULL || data == NULL) { - return KERN_INVALID_ARGUMENT; - } + uint32_t orig_size = size; /* make sure 16 byte aligned */ size += kcdata_calc_padding(size); + uint32_t total_size = size + sizeof(info); + + if (user_addr == NULL || data == NULL || total_size + sizeof(info) < orig_size) { + return KERN_INVALID_ARGUMENT; + } bzero(&info, sizeof(info)); info.type = type; info.size = size; info.flags = flags; - total_size = size + sizeof(info); /* check available memory, including trailer size for KCDATA_TYPE_BUFFER_END */ - if (data->kcd_length < ((data->kcd_addr_end - data->kcd_addr_begin) + total_size + sizeof(info))) { + if (total_size + sizeof(info) > data->kcd_length || + data->kcd_length - (total_size + sizeof(info)) < data->kcd_addr_end - data->kcd_addr_begin) { return KERN_RESOURCE_SHORTAGE; } diff --git a/osfmk/kern/kern_stackshot.c b/osfmk/kern/kern_stackshot.c index be6088138..0c1e07bf1 100644 --- a/osfmk/kern/kern_stackshot.c +++ b/osfmk/kern/kern_stackshot.c @@ -1079,6 +1079,25 @@ kcdata_record_task_iostats(kcdata_descriptor_t kcd, task_t task) return error; } +#if MONOTONIC +static kern_return_t +kcdata_record_task_instrs_cycles(kcdata_descriptor_t kcd, task_t task) +{ + uint64_t instrs = 0, cycles = 0; + mt_stackshot_task(task, &instrs, &cycles); + + kern_return_t error = KERN_SUCCESS; + mach_vm_address_t out_addr = 0; + kcd_exit_on_error(kcdata_get_memory_addr(kcd, STACKSHOT_KCTYPE_INSTRS_CYCLES, sizeof(struct instrs_cycles_snapshot), &out_addr)); + struct instrs_cycles_snapshot *instrs_cycles = (struct instrs_cycles_snapshot *)out_addr; + instrs_cycles->ics_instructions = instrs; + instrs_cycles->ics_cycles = cycles; + +error_exit: + return error; +} +#endif /* MONOTONIC */ + static kern_return_t kcdata_record_task_snapshot(kcdata_descriptor_t kcd, task_t task, uint32_t trace_flags, boolean_t have_pmap, unaligned_u64 **task_snap_ss_flags) { @@ -1154,13 +1173,7 @@ kcdata_record_task_snapshot(kcdata_descriptor_t kcd, task_t task, uint32_t trace #if MONOTONIC if (collect_instrs_cycles) { - uint64_t instrs = 0, cycles = 0; - mt_stackshot_task(task, &instrs, &cycles); - - kcd_exit_on_error(kcdata_get_memory_addr(kcd, STACKSHOT_KCTYPE_INSTRS_CYCLES, sizeof(struct instrs_cycles_snapshot), &out_addr)); - struct instrs_cycles_snapshot *instrs_cycles = (struct instrs_cycles_snapshot *)out_addr; - instrs_cycles->ics_instructions = instrs; - instrs_cycles->ics_cycles = cycles; + kcd_exit_on_error(kcdata_record_task_instrs_cycles(kcd, task)); } #endif /* MONOTONIC */ @@ -1169,11 +1182,16 @@ kcdata_record_task_snapshot(kcdata_descriptor_t kcd, task_t task, uint32_t trace } static kern_return_t -kcdata_record_task_delta_snapshot(kcdata_descriptor_t kcd, task_t task, boolean_t have_pmap, unaligned_u64 **task_snap_ss_flags) +kcdata_record_task_delta_snapshot(kcdata_descriptor_t kcd, task_t task, uint32_t trace_flags, boolean_t have_pmap, unaligned_u64 **task_snap_ss_flags) { kern_return_t error = KERN_SUCCESS; struct task_delta_snapshot_v2 * cur_tsnap = NULL; mach_vm_address_t out_addr = 0; +#if MONOTONIC + boolean_t collect_instrs_cycles = ((trace_flags & STACKSHOT_INSTRS_CYCLES) != 0); +#else + (void)trace_flags; +#endif /* MONOTONIC */ uint64_t task_uniqueid = get_task_uniqueid(task); assert(task_snap_ss_flags != NULL); @@ -1206,6 +1224,12 @@ kcdata_record_task_delta_snapshot(kcdata_descriptor_t kcd, task_t task, boolean_ ? LATENCY_QOS_TIER_UNSPECIFIED : ((0xFF << 16) | task-> effective_policy.tep_latency_qos); +#if MONOTONIC + if (collect_instrs_cycles) { + kcd_exit_on_error(kcdata_record_task_instrs_cycles(kcd, task)); + } +#endif /* MONOTONIC */ + error_exit: return error; } @@ -1453,7 +1477,7 @@ kcdata_record_thread_snapshot( } static int -kcdata_record_thread_delta_snapshot(struct thread_delta_snapshot_v2 * cur_thread_snap, thread_t thread, boolean_t thread_on_core) +kcdata_record_thread_delta_snapshot(struct thread_delta_snapshot_v3 * cur_thread_snap, thread_t thread, boolean_t thread_on_core) { cur_thread_snap->tds_thread_id = thread_tid(thread); if (IPC_VOUCHER_NULL != thread->ith_voucher) @@ -1485,6 +1509,11 @@ kcdata_record_thread_delta_snapshot(struct thread_delta_snapshot_v2 * cur_thread cur_thread_snap->tds_rqos_override = thread->requested_policy.thrp_qos_override; cur_thread_snap->tds_io_tier = proc_get_effective_thread_policy(thread, TASK_POLICY_IO); + static_assert(sizeof(thread->effective_policy) == sizeof(uint64_t)); + static_assert(sizeof(thread->requested_policy) == sizeof(uint64_t)); + cur_thread_snap->tds_requested_policy = *(unaligned_u64 *) &thread->requested_policy; + cur_thread_snap->tds_effective_policy = *(unaligned_u64 *) &thread->effective_policy; + return 0; } @@ -1760,7 +1789,7 @@ kdp_stackshot_kcdata_format(int pid, uint32_t trace_flags, uint32_t * pBytesTrac if (minimize_nonrunnables) { // delay taking the task snapshot. If there are no runnable threads we'll skip it. } else { - kcd_exit_on_error(kcdata_record_task_delta_snapshot(stackshot_kcdata_p, task, have_pmap, &task_snap_ss_flags)); + kcd_exit_on_error(kcdata_record_task_delta_snapshot(stackshot_kcdata_p, task, trace_flags, have_pmap, &task_snap_ss_flags)); } } @@ -1815,7 +1844,7 @@ kdp_stackshot_kcdata_format(int pid, uint32_t trace_flags, uint32_t * pBytesTrac if (task_delta_stackshot && minimize_nonrunnables) { if (some_thread_ran || num_delta_thread_snapshots > 0) { - kcd_exit_on_error(kcdata_record_task_delta_snapshot(stackshot_kcdata_p, task, have_pmap, &task_snap_ss_flags)); + kcd_exit_on_error(kcdata_record_task_delta_snapshot(stackshot_kcdata_p, task, trace_flags, have_pmap, &task_snap_ss_flags)); } else { kcd_exit_on_error(kcdata_undo_add_container_begin(stackshot_kcdata_p)); @@ -1831,14 +1860,14 @@ kdp_stackshot_kcdata_format(int pid, uint32_t trace_flags, uint32_t * pBytesTrac } } - struct thread_delta_snapshot_v2 * delta_snapshots = NULL; + struct thread_delta_snapshot_v3 * delta_snapshots = NULL; int current_delta_snapshot_index = 0; if (num_delta_thread_snapshots > 0) { kcd_exit_on_error(kcdata_get_memory_addr_for_array(stackshot_kcdata_p, STACKSHOT_KCTYPE_THREAD_DELTA_SNAPSHOT, - sizeof(struct thread_delta_snapshot_v2), + sizeof(struct thread_delta_snapshot_v3), num_delta_thread_snapshots, &out_addr)); - delta_snapshots = (struct thread_delta_snapshot_v2 *)out_addr; + delta_snapshots = (struct thread_delta_snapshot_v3 *)out_addr; } uint64_t * nonrunnable_tids = NULL; diff --git a/osfmk/kern/kpc_common.c b/osfmk/kern/kpc_common.c index 21fbbbf34..96455de01 100644 --- a/osfmk/kern/kpc_common.c +++ b/osfmk/kern/kpc_common.c @@ -45,8 +45,6 @@ #include #include -#include - uint32_t kpc_actionid[KPC_MAX_COUNTERS]; #define COUNTERBUF_SIZE_PER_CPU (KPC_MAX_COUNTERS * sizeof(uint64_t)) @@ -152,9 +150,9 @@ kpc_task_set_forced_all_ctrs(task_t task, boolean_t state) task_lock(task); if (state) - task->t_chud |= TASK_KPC_FORCED_ALL_CTRS; + task->t_kpc |= TASK_KPC_FORCED_ALL_CTRS; else - task->t_chud &= ~TASK_KPC_FORCED_ALL_CTRS; + task->t_kpc &= ~TASK_KPC_FORCED_ALL_CTRS; task_unlock(task); } @@ -162,7 +160,7 @@ static boolean_t kpc_task_get_forced_all_ctrs(task_t task) { assert(task); - return task->t_chud & TASK_KPC_FORCED_ALL_CTRS ? TRUE : FALSE; + return task->t_kpc & TASK_KPC_FORCED_ALL_CTRS ? TRUE : FALSE; } int diff --git a/osfmk/kern/machine.h b/osfmk/kern/machine.h index 1f5c7816a..a4d4cbcdb 100644 --- a/osfmk/kern/machine.h +++ b/osfmk/kern/machine.h @@ -146,6 +146,7 @@ extern void machine_max_runnable_latency(uint64_t bg_max_latency, extern void machine_work_interval_notify(thread_t thread, struct kern_work_interval_args* kwi_args); + extern void machine_perfcontrol_deadline_passed(uint64_t deadline); extern void machine_switch_perfcontrol_context(perfcontrol_event event, diff --git a/osfmk/kern/priority.c b/osfmk/kern/priority.c index d61fb3584..29ee2506f 100644 --- a/osfmk/kern/priority.c +++ b/osfmk/kern/priority.c @@ -394,7 +394,7 @@ lightweight_update_priority(thread_t thread) (uintptr_t)thread_tid(thread), thread->base_pri, thread->sched_pri, - 0, /* eventually, 'reason' */ + thread->sched_usage, 0); } } @@ -582,7 +582,7 @@ update_priority( (uintptr_t)thread_tid(thread), thread->base_pri, thread->sched_pri, - 0, /* eventually, 'reason' */ + thread->sched_usage, 0); if (removed) diff --git a/osfmk/kern/sched_multiq.c b/osfmk/kern/sched_multiq.c index 24df80d88..fd945ba1c 100644 --- a/osfmk/kern/sched_multiq.c +++ b/osfmk/kern/sched_multiq.c @@ -287,6 +287,9 @@ sched_multiq_processor_queue_shutdown(processor_t processor); static sched_mode_t sched_multiq_initial_thread_sched_mode(task_t parent_task); +static bool +sched_multiq_thread_avoid_processor(processor_t processor, thread_t thread); + const struct sched_dispatch_table sched_multiq_dispatch = { .sched_name = "multiq", .init = sched_multiq_init, @@ -319,8 +322,8 @@ const struct sched_dispatch_table sched_multiq_dispatch = { .direct_dispatch_to_idle_processors = FALSE, .multiple_psets_enabled = FALSE, .sched_groups_enabled = TRUE, - .avoid_processor_enabled = FALSE, - .thread_avoid_processor = NULL, + .avoid_processor_enabled = TRUE, + .thread_avoid_processor = sched_multiq_thread_avoid_processor, .processor_balance = sched_SMT_balance, .rt_runq = sched_rtglobal_runq, @@ -1197,6 +1200,10 @@ sched_multiq_processor_csw_check(processor_t processor) boolean_t has_higher; int pri; + if (sched_multiq_thread_avoid_processor(processor, current_thread())) { + return (AST_PREEMPT | AST_URGENT); + } + entry_queue_t main_entryq = multiq_main_entryq(processor); run_queue_t bound_runq = multiq_bound_runq(processor); @@ -1468,3 +1475,22 @@ sched_multiq_thread_update_scan(sched_update_scan_context_t scan_context) } while (restart_needed); } + +extern int sched_allow_rt_smt; + +/* Return true if this thread should not continue running on this processor */ +static bool +sched_multiq_thread_avoid_processor(processor_t processor, thread_t thread) +{ + if (processor->processor_primary != processor) { + /* + * This is a secondary SMT processor. If the primary is running + * a realtime thread, only allow realtime threads on the secondary. + */ + if ((processor->processor_primary->current_pri >= BASEPRI_RTQUEUES) && ((thread->sched_pri < BASEPRI_RTQUEUES) || !sched_allow_rt_smt)) { + return true; + } + } + + return false; +} diff --git a/osfmk/kern/sched_prim.c b/osfmk/kern/sched_prim.c index 5f7be7132..508c83bdb 100644 --- a/osfmk/kern/sched_prim.c +++ b/osfmk/kern/sched_prim.c @@ -1777,6 +1777,10 @@ sched_SMT_balance(__unused processor_t cprocessor, processor_set_t cpset) } #endif /* __SMP__ */ +static processor_t choose_processor_for_realtime_thread(processor_set_t pset); +static bool all_available_primaries_are_running_realtime_threads(processor_set_t pset); +int sched_allow_rt_smt = 1; + /* * thread_select: * @@ -1825,9 +1829,19 @@ thread_select(thread_t thread, * An exception is that bound threads are dispatched to a processor without going through * choose_processor(), so in those cases we should continue trying to dequeue work. */ - if (!SCHED(processor_bound_count)(processor) && - !queue_empty(&pset->idle_queue) && !rt_runq_count(pset)) { - goto idle; + if (!SCHED(processor_bound_count)(processor)) { + if (!queue_empty(&pset->idle_queue)) { + goto idle; + } + + /* There are no idle primaries */ + + if (processor->processor_primary->current_pri >= BASEPRI_RTQUEUES) { + bool secondary_can_run_realtime_thread = sched_allow_rt_smt && rt_runq_count(pset) && all_available_primaries_are_running_realtime_threads(pset); + if (!secondary_can_run_realtime_thread) { + goto idle; + } + } } } @@ -1888,8 +1902,22 @@ thread_select(thread_t thread, processor->deadline = thread->realtime.deadline; sched_update_pset_load_average(pset); + + processor_t next_rt_processor = PROCESSOR_NULL; + sched_ipi_type_t next_rt_ipi_type = SCHED_IPI_NONE; + + if (rt_runq_count(pset) > 0) { + next_rt_processor = choose_processor_for_realtime_thread(pset); + if (next_rt_processor) { + next_rt_ipi_type = sched_ipi_action(next_rt_processor, NULL, false, SCHED_IPI_EVENT_PREEMPT); + } + } pset_unlock(pset); + if (next_rt_processor) { + sched_ipi_perform(next_rt_processor, next_rt_ipi_type); + } + return (thread); } @@ -1916,27 +1944,55 @@ thread_select(thread_t thread, if (rt_runq_count(pset) > 0) { rt_lock_lock(pset); - + if (rt_runq_count(pset) > 0) { - thread_t next_rt = qe_queue_first(&SCHED(rt_runq)(pset)->queue, struct thread, runq_links); + thread_t next_rt = qe_queue_first(&SCHED(rt_runq)(pset)->queue, struct thread, runq_links); - if (__probable((next_rt->bound_processor == PROCESSOR_NULL || - (next_rt->bound_processor == processor)))) { + if (__probable((next_rt->bound_processor == PROCESSOR_NULL || + (next_rt->bound_processor == processor)))) { pick_new_rt_thread: - new_thread = qe_dequeue_head(&SCHED(rt_runq)(pset)->queue, struct thread, runq_links); + new_thread = qe_dequeue_head(&SCHED(rt_runq)(pset)->queue, struct thread, runq_links); - new_thread->runq = PROCESSOR_NULL; - SCHED_STATS_RUNQ_CHANGE(&SCHED(rt_runq)(pset)->runq_stats, rt_runq_count(pset)); - rt_runq_count_decr(pset); + new_thread->runq = PROCESSOR_NULL; + SCHED_STATS_RUNQ_CHANGE(&SCHED(rt_runq)(pset)->runq_stats, rt_runq_count(pset)); + rt_runq_count_decr(pset); - processor->deadline = new_thread->realtime.deadline; + processor->deadline = new_thread->realtime.deadline; + processor_state_update_from_thread(processor, new_thread); - rt_lock_unlock(pset); - sched_update_pset_load_average(pset); - pset_unlock(pset); + rt_lock_unlock(pset); + sched_update_pset_load_average(pset); + + processor_t ast_processor = PROCESSOR_NULL; + processor_t next_rt_processor = PROCESSOR_NULL; + sched_ipi_type_t ipi_type = SCHED_IPI_NONE; + sched_ipi_type_t next_rt_ipi_type = SCHED_IPI_NONE; + + if (processor->processor_secondary != NULL) { + processor_t sprocessor = processor->processor_secondary; + if ((sprocessor->state == PROCESSOR_RUNNING) || (sprocessor->state == PROCESSOR_DISPATCHING)) { + ipi_type = sched_ipi_action(sprocessor, NULL, false, SCHED_IPI_EVENT_SMT_REBAL); + ast_processor = sprocessor; + } + } + if (rt_runq_count(pset) > 0) { + next_rt_processor = choose_processor_for_realtime_thread(pset); + if (next_rt_processor) { + next_rt_ipi_type = sched_ipi_action(next_rt_processor, NULL, false, SCHED_IPI_EVENT_PREEMPT); + } + } + pset_unlock(pset); + + if (ast_processor) { + sched_ipi_perform(ast_processor, ipi_type); + } - return (new_thread); - } + if (next_rt_processor) { + sched_ipi_perform(next_rt_processor, next_rt_ipi_type); + } + + return (new_thread); + } } rt_lock_unlock(pset); @@ -1947,6 +2003,7 @@ thread_select(thread_t thread, /* No RT threads, so let's look at the regular threads. */ if ((new_thread = SCHED(choose_thread)(processor, MINPRI, *reason)) != THREAD_NULL) { sched_update_pset_load_average(pset); + processor_state_update_from_thread(processor, new_thread); pset_unlock(pset); return (new_thread); } @@ -3736,12 +3793,14 @@ choose_processor( */ integer_t lowest_priority = MAXPRI + 1; + integer_t lowest_secondary_priority = MAXPRI + 1; integer_t lowest_unpaired_primary_priority = MAXPRI + 1; integer_t lowest_count = INT_MAX; uint64_t furthest_deadline = 1; processor_t lp_processor = PROCESSOR_NULL; processor_t lp_unpaired_primary_processor = PROCESSOR_NULL; processor_t lp_unpaired_secondary_processor = PROCESSOR_NULL; + processor_t lp_paired_secondary_processor = PROCESSOR_NULL; processor_t lc_processor = PROCESSOR_NULL; processor_t fd_processor = PROCESSOR_NULL; @@ -3767,12 +3826,15 @@ choose_processor( * Choose an idle processor, in pset traversal order */ qe_foreach_element(processor, &cset->idle_queue, processor_queue) { + if (bit_test(cset->pending_AST_cpu_mask, processor->cpu_id)) { + continue; + } if (processor->is_recommended) return processor; } /* - * Otherwise, enumerate active and idle processors to find candidates + * Otherwise, enumerate active and idle processors to find primary candidates * with lower priority/etc. */ @@ -3781,11 +3843,21 @@ choose_processor( if (!processor->is_recommended) { continue; } + if (bit_test(cset->pending_AST_cpu_mask, processor->cpu_id)) { + continue; + } integer_t cpri = processor->current_pri; - if (cpri < lowest_priority) { - lowest_priority = cpri; - lp_processor = processor; + if (processor->processor_primary != processor) { + if (cpri < lowest_secondary_priority) { + lowest_secondary_priority = cpri; + lp_paired_secondary_processor = processor; + } + } else { + if (cpri < lowest_priority) { + lowest_priority = cpri; + lp_processor = processor; + } } if ((cpri >= BASEPRI_RTQUEUES) && (processor->deadline > furthest_deadline)) { @@ -3812,6 +3884,10 @@ choose_processor( processor_t cprimary = processor->processor_primary; + if (bit_test(cset->pending_AST_cpu_mask, cprimary->cpu_id)) { + continue; + } + /* If the primary processor is offline or starting up, it's not a candidate for this path */ if (cprimary->state == PROCESSOR_RUNNING || cprimary->state == PROCESSOR_DISPATCHING) { integer_t primary_pri = cprimary->current_pri; @@ -3844,6 +3920,9 @@ choose_processor( re_queue_tail(&cset->active_queue, &lp_processor->processor_queue); return lp_processor; } + if (sched_allow_rt_smt && (thread->sched_pri > lowest_secondary_priority)) { + return lp_paired_secondary_processor; + } if (thread->realtime.deadline < furthest_deadline) return fd_processor; @@ -3903,6 +3982,9 @@ choose_processor( if (lp_unpaired_secondary_processor != PROCESSOR_NULL) { processor = lp_unpaired_secondary_processor; lp_unpaired_secondary_processor = PROCESSOR_NULL; + } else if (lp_paired_secondary_processor != PROCESSOR_NULL) { + processor = lp_paired_secondary_processor; + lp_paired_secondary_processor = PROCESSOR_NULL; } else if (lc_processor != PROCESSOR_NULL) { processor = lc_processor; lc_processor = PROCESSOR_NULL; @@ -4055,10 +4137,10 @@ thread_setrun( realtime_setrun(processor, thread); } else { processor_setrun(processor, thread, options); - /* pset is now unlocked */ - if (thread->bound_processor == PROCESSOR_NULL) { - SCHED(check_spill)(pset, thread); - } + } + /* pset is now unlocked */ + if (thread->bound_processor == PROCESSOR_NULL) { + SCHED(check_spill)(pset, thread); } } @@ -4224,7 +4306,7 @@ set_sched_pri( (uintptr_t)thread_tid(thread), thread->base_pri, thread->sched_pri, - 0, /* eventually, 'reason' */ + thread->sched_usage, 0); if (is_current_thread) { @@ -4513,7 +4595,7 @@ processor_idle( if (bit_test(pset->pending_deferred_AST_cpu_mask, processor->cpu_id)) break; #endif - if (processor->is_recommended) { + if (processor->is_recommended && (processor->processor_primary == processor)) { if (rt_runq_count(pset)) break; } else { @@ -4575,7 +4657,7 @@ processor_idle( if ((new_thread != THREAD_NULL) && (SCHED(processor_queue_has_priority)(processor, new_thread->sched_pri, FALSE) || (rt_runq_count(pset) > 0)) ) { - /* Something higher priority has popped up on the runqueue - redispatch this thread elsewhere */ + /* Something higher priority has popped up on the runqueue - redispatch this thread elsewhere */ processor_state_update_idle(processor); processor->deadline = UINT64_MAX; @@ -5605,3 +5687,88 @@ sched_update_pset_load_average(processor_set_t pset) #if (DEVELOPMENT || DEBUG) #endif } + +/* pset is locked */ +static processor_t +choose_processor_for_realtime_thread(processor_set_t pset) +{ + uint64_t cpu_map = (pset->cpu_bitmask & pset->recommended_bitmask & ~pset->pending_AST_cpu_mask); + + for (int cpuid = lsb_first(cpu_map); cpuid >= 0; cpuid = lsb_next(cpu_map, cpuid)) { + processor_t processor = processor_array[cpuid]; + + if (processor->processor_primary != processor) { + continue; + } + + if (processor->state == PROCESSOR_IDLE) { + return processor; + } + + if ((processor->state != PROCESSOR_RUNNING) && (processor->state != PROCESSOR_DISPATCHING)) { + continue; + } + + if (processor->current_pri >= BASEPRI_RTQUEUES) { + continue; + } + + return processor; + + } + + if (!sched_allow_rt_smt) { + return PROCESSOR_NULL; + } + + /* Consider secondary processors */ + for (int cpuid = lsb_first(cpu_map); cpuid >= 0; cpuid = lsb_next(cpu_map, cpuid)) { + processor_t processor = processor_array[cpuid]; + + if (processor->processor_primary == processor) { + continue; + } + + if (processor->state == PROCESSOR_IDLE) { + return processor; + } + + if ((processor->state != PROCESSOR_RUNNING) && (processor->state != PROCESSOR_DISPATCHING)) { + continue; + } + + if (processor->current_pri >= BASEPRI_RTQUEUES) { + continue; + } + + return processor; + + } + + return PROCESSOR_NULL; +} + +/* pset is locked */ +static bool +all_available_primaries_are_running_realtime_threads(processor_set_t pset) +{ + uint64_t cpu_map = (pset->cpu_bitmask & pset->recommended_bitmask); + + for (int cpuid = lsb_first(cpu_map); cpuid >= 0; cpuid = lsb_next(cpu_map, cpuid)) { + processor_t processor = processor_array[cpuid]; + + if (processor->processor_primary != processor) { + continue; + } + + if ((processor->state != PROCESSOR_RUNNING) && (processor->state != PROCESSOR_DISPATCHING)) { + continue; + } + + if (processor->current_pri < BASEPRI_RTQUEUES) { + return false; + } + } + + return true; +} diff --git a/osfmk/kern/sched_prim.h b/osfmk/kern/sched_prim.h index c0014e86b..c6361a9ca 100644 --- a/osfmk/kern/sched_prim.h +++ b/osfmk/kern/sched_prim.h @@ -467,7 +467,7 @@ extern kern_return_t clear_wait( wait_result_t result); /* Start thread running */ -extern void thread_bootstrap_return(void); +extern void thread_bootstrap_return(void) __attribute__((noreturn)); /* Return from exception (BSD-visible interface) */ extern void thread_exception_return(void) __dead2; diff --git a/osfmk/kern/startup.c b/osfmk/kern/startup.c index a1a9c563c..7685299bd 100644 --- a/osfmk/kern/startup.c +++ b/osfmk/kern/startup.c @@ -203,6 +203,7 @@ unsigned int new_nkdbufs = 0; unsigned int wake_nkdbufs = 0; unsigned int write_trace_on_panic = 0; static char trace_typefilter[64] = { 0 }; +unsigned int trace_wrap = 0; boolean_t trace_serial = FALSE; boolean_t early_boot_complete = FALSE; @@ -265,6 +266,7 @@ kernel_bootstrap(void) PE_parse_boot_argn("trace_wake", &wake_nkdbufs, sizeof (wake_nkdbufs)); PE_parse_boot_argn("trace_panic", &write_trace_on_panic, sizeof(write_trace_on_panic)); PE_parse_boot_arg_str("trace_typefilter", trace_typefilter, sizeof(trace_typefilter)); + PE_parse_boot_argn("trace_wrap", &trace_wrap, sizeof(trace_wrap)); scale_setup(); @@ -530,7 +532,7 @@ kernel_bootstrap_thread(void) kernel_bootstrap_thread_log("ktrace_init"); ktrace_init(); - kdebug_init(new_nkdbufs, trace_typefilter); + kdebug_init(new_nkdbufs, trace_typefilter, trace_wrap); kernel_bootstrap_log("prng_init"); prng_cpu_init(master_cpu); diff --git a/osfmk/kern/syscall_subr.c b/osfmk/kern/syscall_subr.c index e944c79d9..27961d85c 100644 --- a/osfmk/kern/syscall_subr.c +++ b/osfmk/kern/syscall_subr.c @@ -492,7 +492,7 @@ thread_depress_abstime( (uintptr_t)thread_tid(self), self->base_pri, self->sched_pri, - 0, /* eventually, 'reason' */ + self->sched_usage, 0); myprocessor->current_pri = self->sched_pri; @@ -596,7 +596,7 @@ thread_poll_yield( (uintptr_t)thread_tid(self), self->base_pri, self->sched_pri, - 0, /* eventually, 'reason' */ + self->sched_usage, 0); myprocessor->current_pri = self->sched_pri; diff --git a/osfmk/kern/task.c b/osfmk/kern/task.c index cb3a359b5..873779ca9 100644 --- a/osfmk/kern/task.c +++ b/osfmk/kern/task.c @@ -288,7 +288,12 @@ extern int kevent_proc_copy_uptrs(void *proc, uint64_t *buf, int bufsize); extern void proc_memstat_terminated(struct proc* p, boolean_t set); extern void memorystatus_on_ledger_footprint_exceeded(int warning, boolean_t memlimit_is_active, boolean_t memlimit_is_fatal); extern void memorystatus_log_exception(const int max_footprint_mb, boolean_t memlimit_is_active, boolean_t memlimit_is_fatal); -extern boolean_t memorystatus_allowed_vm_map_fork(__unused task_t task); +extern boolean_t memorystatus_allowed_vm_map_fork(task_t task); + +#if DEVELOPMENT || DEBUG +extern void memorystatus_abort_vm_map_fork(task_t); +#endif + #endif /* CONFIG_MEMORYSTATUS */ #endif /* MACH_BSD */ @@ -390,6 +395,30 @@ task_set_platform_binary( task_unlock(task); } +/* + * Set or clear per-task TF_CA_CLIENT_WI flag according to specified argument. + * Returns "false" if flag is already set, and "true" in other cases. + */ +bool +task_set_ca_client_wi( + task_t task, + boolean_t set_or_clear) +{ + bool ret = true; + task_lock(task); + if (set_or_clear) { + /* Tasks can have only one CA_CLIENT work interval */ + if (task->t_flags & TF_CA_CLIENT_WI) + ret = false; + else + task->t_flags |= TF_CA_CLIENT_WI; + } else { + task->t_flags &= ~TF_CA_CLIENT_WI; + } + task_unlock(task); + return ret; +} + void task_set_dyld_info( task_t task, @@ -475,7 +504,7 @@ task_clear_return_wait(task_t task) task_unlock(task); } -void +void __attribute__((noreturn)) task_wait_to_return(void) { task_t task; @@ -1105,7 +1134,7 @@ task_create_internal( new_task->affinity_space = NULL; - new_task->t_chud = 0; + new_task->t_kpc = 0; new_task->pidsuspended = FALSE; new_task->frozen = FALSE; @@ -1227,7 +1256,8 @@ task_create_internal( assert(new_task->task_io_stats != NULL); bzero(new_task->task_io_stats, sizeof(struct io_stat_info)); - bzero(&(new_task->cpu_time_qos_stats), sizeof(struct _cpu_time_qos_stats)); + bzero(&(new_task->cpu_time_eqos_stats), sizeof(new_task->cpu_time_eqos_stats)); + bzero(&(new_task->cpu_time_rqos_stats), sizeof(new_task->cpu_time_rqos_stats)); bzero(&new_task->extmod_statistics, sizeof(new_task->extmod_statistics)); @@ -1318,6 +1348,10 @@ task_create_internal( new_task->task_nonvolatile_objects = 0; new_task->task_purgeable_disowning = FALSE; new_task->task_purgeable_disowned = FALSE; + queue_init(&new_task->task_objq); + task_objq_lock_init(new_task); + + new_task->task_region_footprint = FALSE; #if CONFIG_SECLUDED_MEMORY new_task->task_can_use_secluded_mem = FALSE; @@ -1372,7 +1406,8 @@ task_rollup_accounting_info(task_t to_task, task_t from_task) to_task->purged_memory_critical = from_task->purged_memory_critical; to_task->low_mem_privileged_listener = from_task->low_mem_privileged_listener; *to_task->task_io_stats = *from_task->task_io_stats; - to_task->cpu_time_qos_stats = from_task->cpu_time_qos_stats; + to_task->cpu_time_eqos_stats = from_task->cpu_time_eqos_stats; + to_task->cpu_time_rqos_stats = from_task->cpu_time_rqos_stats; to_task->task_timer_wakeups_bin_1 = from_task->task_timer_wakeups_bin_1; to_task->task_timer_wakeups_bin_2 = from_task->task_timer_wakeups_bin_2; to_task->task_gpu_ns = from_task->task_gpu_ns; @@ -1568,6 +1603,8 @@ task_deallocate( } #endif + assert(queue_empty(&task->task_objq)); + zfree(task_zone, task); } @@ -1997,12 +2034,15 @@ task_duplicate_map_and_threads( * * Skip it. */ +#if DEVELOPMENT || DEBUG + memorystatus_abort_vm_map_fork(task); +#endif task_resume_internal(task); return KERN_FAILURE; } /* Check with VM if vm_map_fork is allowed for this task */ - if (task_allowed_vm_map_fork(task)) { + if (memorystatus_allowed_vm_map_fork(task)) { /* Setup new task's vmmap, switch from parent task's map to it COW map */ oldmap = new_task->map; @@ -2106,16 +2146,6 @@ task_duplicate_map_and_threads( return kr; } -/* - * Place holder function to be filled by VM to return - * TRUE if vm_map_fork is allowed on the given task. - */ -boolean_t -task_allowed_vm_map_fork(task_t task __unused) -{ - return memorystatus_allowed_vm_map_fork(task); -} - #if CONFIG_SECLUDED_MEMORY extern void task_set_can_use_secluded_mem_locked( task_t task, @@ -2330,11 +2360,11 @@ task_terminate_internal( */ thread_interrupt_level(interrupt_save); -#if KPERF +#if KPC /* force the task to release all ctrs */ - if (task->t_chud & TASK_KPC_FORCED_ALL_CTRS) + if (task->t_kpc & TASK_KPC_FORCED_ALL_CTRS) kpc_force_all_ctrs(task, 0); -#endif +#endif /* KPC */ #if CONFIG_COALITIONS /* @@ -4353,6 +4383,8 @@ task_info( if (task->itk_space){ dbg_info->ipc_space_size = task->itk_space->is_table_size; } + + dbg_info->suspend_count = task->suspend_count; error = KERN_SUCCESS; *task_info_count = TASK_DEBUG_INFO_INTERNAL_COUNT; @@ -4565,6 +4597,52 @@ task_cpu_ptime( } +/* This function updates the cpu time in the arrays for each + * effective and requested QoS class + */ +void +task_update_cpu_time_qos_stats( + task_t task, + uint64_t *eqos_stats, + uint64_t *rqos_stats) +{ + if (!eqos_stats && !rqos_stats) { + return; + } + + task_lock(task); + thread_t thread; + queue_iterate(&task->threads, thread, thread_t, task_threads) { + if (thread->options & TH_OPT_IDLE_THREAD) { + continue; + } + + thread_update_qos_cpu_time(thread); + } + + if (eqos_stats) { + eqos_stats[THREAD_QOS_DEFAULT] += task->cpu_time_eqos_stats.cpu_time_qos_default; + eqos_stats[THREAD_QOS_MAINTENANCE] += task->cpu_time_eqos_stats.cpu_time_qos_maintenance; + eqos_stats[THREAD_QOS_BACKGROUND] += task->cpu_time_eqos_stats.cpu_time_qos_background; + eqos_stats[THREAD_QOS_UTILITY] += task->cpu_time_eqos_stats.cpu_time_qos_utility; + eqos_stats[THREAD_QOS_LEGACY] += task->cpu_time_eqos_stats.cpu_time_qos_legacy; + eqos_stats[THREAD_QOS_USER_INITIATED] += task->cpu_time_eqos_stats.cpu_time_qos_user_initiated; + eqos_stats[THREAD_QOS_USER_INTERACTIVE] += task->cpu_time_eqos_stats.cpu_time_qos_user_interactive; + } + + if (rqos_stats) { + rqos_stats[THREAD_QOS_DEFAULT] += task->cpu_time_rqos_stats.cpu_time_qos_default; + rqos_stats[THREAD_QOS_MAINTENANCE] += task->cpu_time_rqos_stats.cpu_time_qos_maintenance; + rqos_stats[THREAD_QOS_BACKGROUND] += task->cpu_time_rqos_stats.cpu_time_qos_background; + rqos_stats[THREAD_QOS_UTILITY] += task->cpu_time_rqos_stats.cpu_time_qos_utility; + rqos_stats[THREAD_QOS_LEGACY] += task->cpu_time_rqos_stats.cpu_time_qos_legacy; + rqos_stats[THREAD_QOS_USER_INITIATED] += task->cpu_time_rqos_stats.cpu_time_qos_user_initiated; + rqos_stats[THREAD_QOS_USER_INTERACTIVE] += task->cpu_time_rqos_stats.cpu_time_qos_user_interactive; + } + + task_unlock(task); +} + kern_return_t task_purgable_info( task_t task, @@ -6109,3 +6187,35 @@ task_copy_fields_for_exec(task_t dst_task, task_t src_task) { dst_task->vtimers = src_task->vtimers; } + +#if DEVELOPMENT || DEBUG +int vm_region_footprint = 0; +#endif /* DEVELOPMENT || DEBUG */ + +boolean_t +task_self_region_footprint(void) +{ +#if DEVELOPMENT || DEBUG + if (vm_region_footprint) { + /* system-wide override */ + return TRUE; + } +#endif /* DEVELOPMENT || DEBUG */ + return current_task()->task_region_footprint; +} + +void +task_self_region_footprint_set( + boolean_t newval) +{ + task_t curtask; + + curtask = current_task(); + task_lock(curtask); + if (newval) { + curtask->task_region_footprint = TRUE; + } else { + curtask->task_region_footprint = FALSE; + } + task_unlock(curtask); +} diff --git a/osfmk/kern/task.h b/osfmk/kern/task.h index 352c50450..f0cbdff1d 100644 --- a/osfmk/kern/task.h +++ b/osfmk/kern/task.h @@ -256,6 +256,7 @@ struct task { #define TF_LRETURNWAIT 0x00000100 /* task is waiting for fork/posix_spawn/exec to complete */ #define TF_LRETURNWAITER 0x00000200 /* task is waiting for TF_LRETURNWAIT to get cleared */ #define TF_PLATFORM 0x00000400 /* task is a platform binary */ +#define TF_CA_CLIENT_WI 0x00000800 /* task has CA_CLIENT work interval */ #define task_has_64BitAddr(task) \ (((task)->t_flags & TF_64B_ADDR) != 0) @@ -301,12 +302,10 @@ struct task { mach_vm_address_t all_image_info_addr; /* dyld __all_image_info */ mach_vm_size_t all_image_info_size; /* section location and size */ -#if KPERF -#define TASK_PMC_FLAG 0x1 /* Bit in "t_chud" signifying PMC interest */ -#define TASK_KPC_FORCED_ALL_CTRS 0x2 /* Bit in "t_chud" signifying KPC forced all counters */ - - uint32_t t_chud; /* CHUD flags, used for Shark */ -#endif +#if KPC +#define TASK_KPC_FORCED_ALL_CTRS 0x2 /* Bit in "t_kpc" signifying this task forced all counters */ + uint32_t t_kpc; /* kpc flags */ +#endif /* KPC */ boolean_t pidsuspended; /* pid_suspend called; no threads can execute */ boolean_t frozen; /* frozen; private resident pages committed to swap */ @@ -371,7 +370,8 @@ struct task { /* * The cpu_time_qos_stats fields are protected by the task lock */ - struct _cpu_time_qos_stats cpu_time_qos_stats; + struct _cpu_time_qos_stats cpu_time_eqos_stats; + struct _cpu_time_qos_stats cpu_time_rqos_stats; /* Statistics accumulated for terminated threads from this task */ uint32_t task_timer_wakeups_bin_1; @@ -390,6 +390,10 @@ struct task { int task_nonvolatile_objects; boolean_t task_purgeable_disowning; boolean_t task_purgeable_disowned; + queue_head_t task_objq; + decl_lck_mtx_data(,task_objq_lock) /* protects "task_objq" */ + + boolean_t task_region_footprint; /* * A task's coalition set is "adopted" in task_create_internal @@ -426,6 +430,12 @@ struct task { #define task_lock_try(task) lck_mtx_try_lock(&(task)->lock) #define task_unlock(task) lck_mtx_unlock(&(task)->lock) +#define task_objq_lock_init(task) lck_mtx_init(&(task)->task_objq_lock, &vm_object_lck_grp, &vm_object_lck_attr) +#define task_objq_lock(task) lck_mtx_lock(&(task)->task_objq_lock) +#define task_objq_lock_assert_owned(task) LCK_MTX_ASSERT(&(task)->task_objq_lock, LCK_MTX_ASSERT_OWNED) +#define task_objq_lock_try(task) lck_mtx_try_lock(&(task)->task_objq_lock) +#define task_objq_unlock(task) lck_mtx_unlock(&(task)->task_objq_lock) + #define itk_lock_init(task) lck_mtx_init(&(task)->itk_lock_data, &ipc_lck_grp, &ipc_lck_attr) #define itk_lock_destroy(task) lck_mtx_destroy(&(task)->itk_lock_data, &ipc_lck_grp) #define itk_lock(task) lck_mtx_lock(&(task)->itk_lock_data) @@ -468,7 +478,6 @@ extern void init_task_ledgers(void); extern lck_attr_t task_lck_attr; extern lck_grp_t task_lck_grp; - #else /* MACH_KERNEL_PRIVATE */ __BEGIN_DECLS @@ -592,6 +601,10 @@ extern uint64_t task_energy( extern uint64_t task_cpu_ptime( task_t task); +extern void task_update_cpu_time_qos_stats( + task_t task, + uint64_t *eqos_stats, + uint64_t *rqos_stats); extern void task_vtimer_set( task_t task, @@ -617,6 +630,9 @@ extern void task_set_64bit( extern void task_set_platform_binary( task_t task, boolean_t is_platform); +extern bool task_set_ca_client_wi( + task_t task, + boolean_t ca_client_wi); extern void task_backing_store_privileged( task_t task); @@ -752,7 +768,7 @@ extern void task_set_32bit_log_flag(task_t task); extern boolean_t task_is_active(task_t task); extern boolean_t task_is_halting(task_t task); extern void task_clear_return_wait(task_t task); -extern void task_wait_to_return(void); +extern void task_wait_to_return(void) __attribute__((noreturn)); extern event_t task_get_return_wait_event(task_t task); extern void task_atm_reset(task_t task); @@ -833,6 +849,10 @@ extern void task_inspect_deallocate( extern void task_suspension_token_deallocate( task_suspension_token_t token); + +extern boolean_t task_self_region_footprint(void); +extern void task_self_region_footprint_set(boolean_t newval); + __END_DECLS #endif /* _KERN_TASK_H_ */ diff --git a/osfmk/kern/task_policy.c b/osfmk/kern/task_policy.c index f876182a5..ca3e83f18 100644 --- a/osfmk/kern/task_policy.c +++ b/osfmk/kern/task_policy.c @@ -3709,16 +3709,13 @@ send_resource_violation(typeof(send_cpu_usage_violation) sendfunc, HOST_RESOURCE_NOTIFY_PORT, &dstport); if (kr) goto finish; - /* TH_OPT_HONOR_QLIMIT causes ipc_kmsg_send() to respect the - * queue limit. It also unsets this flag, but this code also - * unsets it for clarity and in case that code changes. */ - curthread->options |= TH_OPT_HONOR_QLIMIT; + thread_set_honor_qlimit(curthread); kr = sendfunc(dstport, procname, pid, proc_path, timestamp, linfo->lei_balance, linfo->lei_last_refill, linfo->lei_limit, linfo->lei_refill_period, flags); - curthread->options &= (~TH_OPT_HONOR_QLIMIT); + thread_clear_honor_qlimit(curthread); ipc_port_release_send(dstport); diff --git a/osfmk/kern/thread.c b/osfmk/kern/thread.c index ce815db9e..433a1ae90 100644 --- a/osfmk/kern/thread.c +++ b/osfmk/kern/thread.c @@ -542,18 +542,22 @@ thread_terminate_self(void) bank_swap_thread_bank_ledger(thread, NULL); + if (kdebug_enable && bsd_hasthreadname(thread->uthread)) { + char threadname[MAXTHREADNAMESIZE]; + bsd_getthreadname(thread->uthread, threadname); + kernel_debug_string_simple(TRACE_STRING_THREADNAME_PREV, threadname); + } + task = thread->task; uthread_cleanup(task, thread->uthread, task->bsd_info); - if (task->bsd_info && !task_is_exec_copy(task)) { + if (kdebug_enable && task->bsd_info && !task_is_exec_copy(task)) { /* trace out pid before we sign off */ long dbg_arg1 = 0; - long dbg_arg2 = 0; - - kdbg_trace_data(thread->task->bsd_info, &dbg_arg1, &dbg_arg2); + long dbg_arg2 = 0; - KERNEL_DEBUG_CONSTANT(TRACE_DATA_THREAD_TERMINATE_PID | DBG_FUNC_NONE, - dbg_arg1, 0, 0, 0, 0); + kdbg_trace_data(thread->task->bsd_info, &dbg_arg1, &dbg_arg2); + KDBG_RELEASE(TRACE_DATA_THREAD_TERMINATE_PID, dbg_arg1, dbg_arg2); } /* @@ -571,14 +575,11 @@ thread_terminate_self(void) */ if (threadcnt == 0 && task->bsd_info != NULL && !task_is_exec_copy(task)) { mach_exception_data_type_t subcode = 0; - { + if (kdebug_enable) { /* since we're the last thread in this process, trace out the command name too */ - long dbg_arg1 = 0, dbg_arg2 = 0, dbg_arg3 = 0, dbg_arg4 = 0; - - kdbg_trace_string(thread->task->bsd_info, &dbg_arg1, &dbg_arg2, &dbg_arg3, &dbg_arg4); - - KERNEL_DEBUG_CONSTANT(TRACE_STRING_PROC_EXIT | DBG_FUNC_NONE, - dbg_arg1, dbg_arg2, dbg_arg3, dbg_arg4, 0); + long args[4] = {}; + kdbg_trace_string(thread->task->bsd_info, &args[0], &args[1], &args[2], &args[3]); + KDBG_RELEASE(TRACE_STRING_PROC_EXIT, args[0], args[1], args[2], args[3]); } /* Get the exit reason before proc_exit */ @@ -703,14 +704,14 @@ thread_deallocate( task = thread->task; -#ifdef MACH_BSD +#ifdef MACH_BSD { void *ut = thread->uthread; thread->uthread = NULL; uthread_zone_free(ut); } -#endif /* MACH_BSD */ +#endif /* MACH_BSD */ if (thread->t_ledger) ledger_dereference(thread->t_ledger); @@ -979,7 +980,7 @@ void thread_terminate_enqueue( thread_t thread) { - KERNEL_DEBUG_CONSTANT(TRACE_DATA_THREAD_TERMINATE | DBG_FUNC_NONE, thread->thread_id, 0, 0, 0, 0); + KDBG_RELEASE(TRACE_DATA_THREAD_TERMINATE, thread->thread_id); simple_lock(&thread_terminate_lock); enqueue_tail(&thread_terminate_queue, &thread->runq_links); @@ -1341,10 +1342,10 @@ thread_create_internal( new_thread->corpse_dup = FALSE; *out_thread = new_thread; - { - long dbg_arg1, dbg_arg2, dbg_arg3, dbg_arg4; + if (kdebug_enable) { + long args[4] = {}; - kdbg_trace_data(parent_task->bsd_info, &dbg_arg2, &dbg_arg4); + kdbg_trace_data(parent_task->bsd_info, &args[1], &args[3]); /* * Starting with 26604425, exec'ing creates a new task/thread. @@ -1352,26 +1353,23 @@ thread_create_internal( * NEWTHREAD in the current process has two possible meanings: * * 1) Create a new thread for this process. - * 2) Create a new thread for the future process this will become in an exec. + * 2) Create a new thread for the future process this will become in an + * exec. * * To disambiguate these, arg3 will be set to TRUE for case #2. * * The value we need to find (TPF_EXEC_COPY) is stable in the case of a * task exec'ing. The read of t_procflags does not take the proc_lock. */ - dbg_arg3 = (task_is_exec_copy(parent_task)) ? TRUE : 0; + args[2] = task_is_exec_copy(parent_task) ? 1 : 0; + KDBG_RELEASE(TRACE_DATA_NEWTHREAD, (uintptr_t)thread_tid(new_thread), + args[1], args[2], args[3]); - KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, - TRACE_DATA_NEWTHREAD | DBG_FUNC_NONE, - (vm_address_t)(uintptr_t)thread_tid(new_thread), dbg_arg2, dbg_arg3, dbg_arg4, 0); - - kdbg_trace_string(parent_task->bsd_info, - &dbg_arg1, &dbg_arg2, &dbg_arg3, &dbg_arg4); - - KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, - TRACE_STRING_NEWTHREAD | DBG_FUNC_NONE, - dbg_arg1, dbg_arg2, dbg_arg3, dbg_arg4, 0); + kdbg_trace_string(parent_task->bsd_info, &args[0], &args[1], + &args[2], &args[3]); + KDBG_RELEASE(TRACE_STRING_NEWTHREAD, args[0], args[1], args[2], + args[3]); } DTRACE_PROC1(lwp__create, thread_t, *out_thread); @@ -3038,6 +3036,18 @@ thread_set_thread_name(thread_t th, const char* name) } } +void +thread_set_honor_qlimit(thread_t thread) +{ + thread->options |= TH_OPT_HONOR_QLIMIT; +} + +void +thread_clear_honor_qlimit(thread_t thread) +{ + thread->options &= (~TH_OPT_HONOR_QLIMIT); +} + /* * thread_enable_send_importance - set/clear the SEND_IMPORTANCE thread option bit. */ diff --git a/osfmk/kern/thread.h b/osfmk/kern/thread.h index 4601a9ebb..ca2217584 100644 --- a/osfmk/kern/thread.h +++ b/osfmk/kern/thread.h @@ -1190,6 +1190,8 @@ extern kern_return_t kernel_thread_start( #ifdef KERNEL_PRIVATE void thread_set_eager_preempt(thread_t thread); void thread_clear_eager_preempt(thread_t thread); +void thread_set_honor_qlimit(thread_t thread); +void thread_clear_honor_qlimit(thread_t thread); extern ipc_port_t convert_thread_to_port(thread_t); extern ipc_port_t convert_thread_inspect_to_port(thread_inspect_t); extern boolean_t is_vm_privileged(void); diff --git a/osfmk/kern/thread_act.c b/osfmk/kern/thread_act.c index 3bd8b5182..9c7aa300c 100644 --- a/osfmk/kern/thread_act.c +++ b/osfmk/kern/thread_act.c @@ -893,7 +893,7 @@ thread_suspended(__unused void *parameter, wait_result_t result) (uintptr_t)thread_tid(thread), thread->base_pri, thread->sched_pri, - 0, /* eventually, 'reason' */ + thread->sched_usage, 0); } thread_unlock(thread); diff --git a/osfmk/kern/thread_policy.c b/osfmk/kern/thread_policy.c index add093661..6ede110d1 100644 --- a/osfmk/kern/thread_policy.c +++ b/osfmk/kern/thread_policy.c @@ -777,20 +777,35 @@ thread_update_qos_cpu_time_locked(thread_t thread) uint64_t* task_counter = NULL; - /* Update the task-level qos stats atomically, because we don't have the task lock. */ + /* Update the task-level effective and requested qos stats atomically, because we don't have the task lock. */ switch (thread->effective_policy.thep_qos) { - case THREAD_QOS_DEFAULT: task_counter = &task->cpu_time_qos_stats.cpu_time_qos_default; break; - case THREAD_QOS_MAINTENANCE: task_counter = &task->cpu_time_qos_stats.cpu_time_qos_maintenance; break; - case THREAD_QOS_BACKGROUND: task_counter = &task->cpu_time_qos_stats.cpu_time_qos_background; break; - case THREAD_QOS_UTILITY: task_counter = &task->cpu_time_qos_stats.cpu_time_qos_utility; break; - case THREAD_QOS_LEGACY: task_counter = &task->cpu_time_qos_stats.cpu_time_qos_legacy; break; - case THREAD_QOS_USER_INITIATED: task_counter = &task->cpu_time_qos_stats.cpu_time_qos_user_initiated; break; - case THREAD_QOS_USER_INTERACTIVE: task_counter = &task->cpu_time_qos_stats.cpu_time_qos_user_interactive; break; + case THREAD_QOS_DEFAULT: task_counter = &task->cpu_time_eqos_stats.cpu_time_qos_default; break; + case THREAD_QOS_MAINTENANCE: task_counter = &task->cpu_time_eqos_stats.cpu_time_qos_maintenance; break; + case THREAD_QOS_BACKGROUND: task_counter = &task->cpu_time_eqos_stats.cpu_time_qos_background; break; + case THREAD_QOS_UTILITY: task_counter = &task->cpu_time_eqos_stats.cpu_time_qos_utility; break; + case THREAD_QOS_LEGACY: task_counter = &task->cpu_time_eqos_stats.cpu_time_qos_legacy; break; + case THREAD_QOS_USER_INITIATED: task_counter = &task->cpu_time_eqos_stats.cpu_time_qos_user_initiated; break; + case THREAD_QOS_USER_INTERACTIVE: task_counter = &task->cpu_time_eqos_stats.cpu_time_qos_user_interactive; break; default: panic("unknown effective QoS: %d", thread->effective_policy.thep_qos); } OSAddAtomic64(timer_delta, task_counter); + + /* Update the task-level qos stats atomically, because we don't have the task lock. */ + switch (thread->requested_policy.thrp_qos) { + case THREAD_QOS_DEFAULT: task_counter = &task->cpu_time_rqos_stats.cpu_time_qos_default; break; + case THREAD_QOS_MAINTENANCE: task_counter = &task->cpu_time_rqos_stats.cpu_time_qos_maintenance; break; + case THREAD_QOS_BACKGROUND: task_counter = &task->cpu_time_rqos_stats.cpu_time_qos_background; break; + case THREAD_QOS_UTILITY: task_counter = &task->cpu_time_rqos_stats.cpu_time_qos_utility; break; + case THREAD_QOS_LEGACY: task_counter = &task->cpu_time_rqos_stats.cpu_time_qos_legacy; break; + case THREAD_QOS_USER_INITIATED: task_counter = &task->cpu_time_rqos_stats.cpu_time_qos_user_initiated; break; + case THREAD_QOS_USER_INTERACTIVE: task_counter = &task->cpu_time_rqos_stats.cpu_time_qos_user_interactive; break; + default: + panic("unknown requested QoS: %d", thread->requested_policy.thrp_qos); + } + + OSAddAtomic64(timer_delta, task_counter); } /* diff --git a/osfmk/kern/timer_call.c b/osfmk/kern/timer_call.c index 93c347ddd..86bd1a8df 100644 --- a/osfmk/kern/timer_call.c +++ b/osfmk/kern/timer_call.c @@ -108,12 +108,13 @@ lck_grp_attr_t timer_longterm_lck_grp_attr; #endif /* - * The scan limit throttles processing of the longterm queue. + * The scan_limit throttles processing of the longterm queue. * If the scan time exceeds this limit, we terminate, unlock - * and repeat after this same interval. This prevents unbounded holding of + * and defer for scan_interval. This prevents unbounded holding of * timer queue locks with interrupts masked. */ -#define TIMER_LONGTERM_SCAN_LIMIT (1ULL * NSEC_PER_MSEC) /* 1 msec */ +#define TIMER_LONGTERM_SCAN_LIMIT (100ULL * NSEC_PER_USEC) /* 100 us */ +#define TIMER_LONGTERM_SCAN_INTERVAL (100ULL * NSEC_PER_USEC) /* 100 us */ /* Sentinel for "scan limit exceeded": */ #define TIMER_LONGTERM_SCAN_AGAIN 0 @@ -141,11 +142,13 @@ typedef struct { uint64_t scan_time; /* last time the list was scanned */ threshold_t threshold; /* longterm timer threshold */ uint64_t scan_limit; /* maximum scan time */ + uint64_t scan_interval; /* interval between LT "escalation" scans */ uint64_t scan_pauses; /* num scans exceeding time limit */ } timer_longterm_t; timer_longterm_t timer_longterm = { .scan_limit = TIMER_LONGTERM_SCAN_LIMIT, + .scan_interval = TIMER_LONGTERM_SCAN_INTERVAL, }; static mpqueue_head_t *timer_longterm_queue = NULL; @@ -1492,7 +1495,7 @@ timer_longterm_update_locked(timer_longterm_t *tlp) } /* Throttle next scan time */ - uint64_t scan_clamp = mach_absolute_time() + tlp->scan_limit; + uint64_t scan_clamp = mach_absolute_time() + tlp->scan_interval; if (tlp->threshold.deadline_set < scan_clamp) tlp->threshold.deadline_set = scan_clamp; @@ -1577,7 +1580,7 @@ timer_longterm_init(void) enum { THRESHOLD, QCOUNT, ENQUEUES, DEQUEUES, ESCALATES, SCANS, PREEMPTS, - LATENCY, LATENCY_MIN, LATENCY_MAX, SCAN_LIMIT, PAUSES + LATENCY, LATENCY_MIN, LATENCY_MAX, SCAN_LIMIT, SCAN_INTERVAL, PAUSES }; uint64_t timer_sysctl_get(int oid) @@ -1608,6 +1611,8 @@ timer_sysctl_get(int oid) return tlp->threshold.latency_max; case SCAN_LIMIT: return tlp->scan_limit; + case SCAN_INTERVAL: + return tlp->scan_interval; case PAUSES: return tlp->scan_pauses; default: @@ -1745,6 +1750,9 @@ timer_sysctl_set(int oid, uint64_t value) case SCAN_LIMIT: timer_longterm.scan_limit = value; return KERN_SUCCESS; + case SCAN_INTERVAL: + timer_longterm.scan_interval = value; + return KERN_SUCCESS; default: return KERN_INVALID_ARGUMENT; } diff --git a/osfmk/kern/work_interval.c b/osfmk/kern/work_interval.c index 2f4cd62a1..9e9e189e7 100644 --- a/osfmk/kern/work_interval.c +++ b/osfmk/kern/work_interval.c @@ -37,6 +37,8 @@ #include #include #include +#include +#include #include #include @@ -371,6 +373,20 @@ kern_work_interval_create(thread_t thread, uint32_t create_flags = create_params->wica_create_flags; task_t creating_task = current_task(); + if ((create_flags & WORK_INTERVAL_TYPE_MASK) == WORK_INTERVAL_TYPE_CA_CLIENT) { + /* + * CA_CLIENT work intervals do not create new thread groups + * and are non-joinable. + * There can only be one CA_CLIENT work interval (created by UIKit) + * per each application task + */ + if (create_flags & (WORK_INTERVAL_FLAG_JOINABLE | WORK_INTERVAL_FLAG_GROUP)) + return (KERN_FAILURE); + if (!task_is_app(creating_task)) + return (KERN_NOT_SUPPORTED); + if (task_set_ca_client_wi(creating_task, true) == false) + return (KERN_FAILURE); + } *work_interval = (struct work_interval) { .wi_id = work_interval_id, @@ -406,13 +422,12 @@ kern_work_interval_create(thread_t thread, } create_params->wica_id = work_interval_id; - return KERN_SUCCESS; } + kern_return_t -kern_work_interval_destroy(thread_t thread, - uint64_t work_interval_id) +kern_work_interval_destroy(thread_t thread, uint64_t work_interval_id) { if (work_interval_id == 0) return KERN_INVALID_ARGUMENT; @@ -454,6 +469,3 @@ kern_work_interval_join(thread_t thread, return KERN_SUCCESS; } - - - diff --git a/osfmk/kern/work_interval.h b/osfmk/kern/work_interval.h index 31f009bfa..baa2311ba 100644 --- a/osfmk/kern/work_interval.h +++ b/osfmk/kern/work_interval.h @@ -63,12 +63,12 @@ struct kern_work_interval_create_args { */ extern kern_return_t kern_work_interval_create(thread_t thread, struct kern_work_interval_create_args *create_params); + extern kern_return_t kern_work_interval_destroy(thread_t thread, uint64_t work_interval_id); extern kern_return_t kern_work_interval_join(thread_t thread, mach_port_name_t port_name); - extern kern_return_t kern_work_interval_notify(thread_t thread, struct kern_work_interval_args* kwi_args); diff --git a/osfmk/kern/zalloc.c b/osfmk/kern/zalloc.c index 0a21dda6a..8da4fe3c8 100644 --- a/osfmk/kern/zalloc.c +++ b/osfmk/kern/zalloc.c @@ -72,6 +72,7 @@ #include #include #include +#include #include #include @@ -445,6 +446,7 @@ struct zone_page_metadata { /* Magic value to indicate empty element free list */ #define PAGE_METADATA_EMPTY_FREELIST ((uint32_t)(~0)) +boolean_t get_zone_info(zone_t z, mach_zone_name_t *zn, mach_zone_info_t *zi); boolean_t is_zone_map_nearing_exhaustion(void); extern void vm_pageout_garbage_collect(int collect); @@ -3339,6 +3341,8 @@ zalloc_internal( } #endif + DTRACE_VM2(zalloc, zone_t, zone, void*, addr); + return((void *)addr); } @@ -3478,6 +3482,7 @@ zfree( #endif /* VM_MAX_TAG_ZONES */ assert(zone != ZONE_NULL); + DTRACE_VM2(zfree, zone_t, zone, void*, addr); #if KASAN_ZALLOC /* @@ -3868,6 +3873,48 @@ consider_zone_gc(boolean_t consider_jetsams) zone_gc(consider_jetsams); } + +boolean_t +get_zone_info( + zone_t z, + mach_zone_name_t *zn, + mach_zone_info_t *zi) +{ + struct zone zcopy; + + assert(z != ZONE_NULL); + lock_zone(z); + if (!z->zone_valid) { + unlock_zone(z); + return FALSE; + } + zcopy = *z; + unlock_zone(z); + + if (zn != NULL) { + /* assuming here the name data is static */ + (void) __nosan_strlcpy(zn->mzn_name, zcopy.zone_name, + strlen(zcopy.zone_name)+1); + } + + if (zi != NULL) { + zi->mzi_count = (uint64_t)zcopy.count; + zi->mzi_cur_size = ptoa_64(zcopy.page_count); + zi->mzi_max_size = (uint64_t)zcopy.max_size; + zi->mzi_elem_size = (uint64_t)zcopy.elem_size; + zi->mzi_alloc_size = (uint64_t)zcopy.alloc_size; + zi->mzi_sum_size = zcopy.sum_count * zcopy.elem_size; + zi->mzi_exhaustible = (uint64_t)zcopy.exhaustible; + zi->mzi_collectable = 0; + if (zcopy.collectable) { + SET_MZI_COLLECTABLE_BYTES(zi->mzi_collectable, ((uint64_t)zcopy.count_all_free_pages * PAGE_SIZE)); + SET_MZI_COLLECTABLE_FLAG(zi->mzi_collectable, TRUE); + } + } + + return TRUE; +} + kern_return_t task_zone_info( __unused task_t task, @@ -3916,7 +3963,6 @@ mach_memory_info( unsigned int num_info; unsigned int max_zones, used_zones, i; - zone_t z; mach_zone_name_t *zn; mach_zone_info_t *zi; kern_return_t kr; @@ -3963,40 +4009,26 @@ mach_memory_info( used_zones = max_zones; for (i = 0; i < max_zones; i++) { - struct zone zcopy; - z = &(zone_array[i]); - assert(z != ZONE_NULL); - - lock_zone(z); - if (!z->zone_valid) { - unlock_zone(z); + if (!get_zone_info(&(zone_array[i]), zn, zi)) { used_zones--; continue; } - zcopy = *z; - unlock_zone(z); - - /* assuming here the name data is static */ - (void) __nosan_strncpy(zn->mzn_name, zcopy.zone_name, - sizeof zn->mzn_name); - zn->mzn_name[sizeof zn->mzn_name - 1] = '\0'; - - zi->mzi_count = (uint64_t)zcopy.count; - zi->mzi_cur_size = ptoa_64(zcopy.page_count); - zi->mzi_max_size = (uint64_t)zcopy.max_size; - zi->mzi_elem_size = (uint64_t)zcopy.elem_size; - zi->mzi_alloc_size = (uint64_t)zcopy.alloc_size; - zi->mzi_sum_size = zcopy.sum_count * zcopy.elem_size; - zi->mzi_exhaustible = (uint64_t)zcopy.exhaustible; - zi->mzi_collectable = (uint64_t)zcopy.collectable; - zones_collectable_bytes += ((uint64_t)zcopy.count_all_free_pages * PAGE_SIZE); + zones_collectable_bytes += GET_MZI_COLLECTABLE_BYTES(zi->mzi_collectable); zn++; zi++; } used = used_zones * sizeof *names; - if (used != names_size) - bzero((char *) (names_addr + used), names_size - used); + if (used != names_size) { + vm_offset_t names_addr_end = names_addr + used; + vm_size_t free_size = names_size - (round_page(names_addr_end) - names_addr); + + if (free_size >= PAGE_SIZE) { + kmem_free(ipc_kernel_map, + round_page(names_addr_end), free_size); + } + bzero((char *) names_addr_end, round_page(names_addr_end) - names_addr_end); + } kr = vm_map_copyin(ipc_kernel_map, (vm_map_address_t)names_addr, (vm_map_size_t)used, TRUE, ©); @@ -4006,9 +4038,16 @@ mach_memory_info( *namesCntp = used_zones; used = used_zones * sizeof *info; + if (used != info_size) { + vm_offset_t info_addr_end = info_addr + used; + vm_size_t free_size = info_size - (round_page(info_addr_end) - info_addr); - if (used != info_size) - bzero((char *) (info_addr + used), info_size - used); + if (free_size >= PAGE_SIZE) { + kmem_free(ipc_kernel_map, + round_page(info_addr_end), free_size); + } + bzero((char *) info_addr_end, round_page(info_addr_end) - info_addr_end); + } kr = vm_map_copyin(ipc_kernel_map, (vm_map_address_t)info_addr, (vm_map_size_t)used, TRUE, ©); @@ -4028,10 +4067,6 @@ mach_memory_info( kr = kmem_alloc_pageable(ipc_kernel_map, &memory_info_addr, memory_info_vmsize, VM_KERN_MEMORY_IPC); if (kr != KERN_SUCCESS) { - kmem_free(ipc_kernel_map, - names_addr, names_size); - kmem_free(ipc_kernel_map, - info_addr, info_size); return kr; } @@ -4056,24 +4091,91 @@ mach_memory_info( return KERN_SUCCESS; } +kern_return_t +mach_zone_info_for_zone( + host_priv_t host, + mach_zone_name_t name, + mach_zone_info_t *infop) +{ + unsigned int max_zones, i; + zone_t zone_ptr; + + if (host == HOST_NULL) + return KERN_INVALID_HOST; +#if CONFIG_DEBUGGER_FOR_ZONE_INFO + if (!PE_i_can_has_debugger(NULL)) + return KERN_INVALID_HOST; +#endif + + if (infop == NULL) { + return KERN_INVALID_ARGUMENT; + } + + simple_lock(&all_zones_lock); + max_zones = (unsigned int)(num_zones); + simple_unlock(&all_zones_lock); + + zone_ptr = ZONE_NULL; + for (i = 0; i < max_zones; i++) { + zone_t z = &(zone_array[i]); + assert(z != ZONE_NULL); + + /* Find the requested zone by name */ + if (!strncmp(name.mzn_name, z->zone_name, strlen(z->zone_name))) { + zone_ptr = z; + break; + } + } + + /* No zones found with the requested zone name */ + if (zone_ptr == ZONE_NULL) { + return KERN_INVALID_ARGUMENT; + } + + if (get_zone_info(zone_ptr, NULL, infop)) { + return KERN_SUCCESS; + } + return KERN_FAILURE; +} + +kern_return_t +mach_zone_info_for_largest_zone( + host_priv_t host, + mach_zone_name_t *namep, + mach_zone_info_t *infop) +{ + if (host == HOST_NULL) + return KERN_INVALID_HOST; +#if CONFIG_DEBUGGER_FOR_ZONE_INFO + if (!PE_i_can_has_debugger(NULL)) + return KERN_INVALID_HOST; +#endif + + if (namep == NULL || infop == NULL) { + return KERN_INVALID_ARGUMENT; + } + + if (get_zone_info(zone_find_largest(), namep, infop)) { + return KERN_SUCCESS; + } + return KERN_FAILURE; +} + uint64_t get_zones_collectable_bytes(void) { - zone_t z; unsigned int i, max_zones; uint64_t zones_collectable_bytes = 0; + mach_zone_info_t zi; simple_lock(&all_zones_lock); max_zones = (unsigned int)(num_zones); simple_unlock(&all_zones_lock); for (i = 0; i < max_zones; i++) { - z = &(zone_array[i]); - assert(z != ZONE_NULL); - - lock_zone(z); - zones_collectable_bytes += ((uint64_t)z->count_all_free_pages * PAGE_SIZE); - unlock_zone(z); + if (get_zone_info(&(zone_array[i]), NULL, &zi)) { + zones_collectable_bytes += GET_MZI_COLLECTABLE_BYTES(zi.mzi_collectable); + } } return zones_collectable_bytes; diff --git a/osfmk/kperf/callstack.c b/osfmk/kperf/callstack.c index 7c8f0a7e7..2fe676882 100644 --- a/osfmk/kperf/callstack.c +++ b/osfmk/kperf/callstack.c @@ -28,7 +28,6 @@ /* Collect kernel callstacks */ -#include #include #include #include @@ -257,6 +256,10 @@ kperf_backtrace_sample(struct callstack *cs, struct kperf_context *context) BUF_VERB(PERF_CS_BACKTRACE | DBG_FUNC_END, cs->nframes); } +kern_return_t chudxnu_thread_get_callstack64_kperf(thread_t thread, + uint64_t *callStack, mach_msg_type_number_t *count, + boolean_t user_only); + void kperf_kcallstack_sample(struct callstack *cs, struct kperf_context *context) { @@ -437,3 +440,1058 @@ kperf_ucallstack_pend(struct kperf_context * context, uint32_t depth) return did_pend; } + +static kern_return_t +chudxnu_kern_read(void *dstaddr, vm_offset_t srcaddr, vm_size_t size) +{ + return ((ml_nofault_copy(srcaddr, (vm_offset_t)dstaddr, size) == size) ? + KERN_SUCCESS : KERN_FAILURE); +} + +static kern_return_t +chudxnu_task_read( + task_t task, + void *kernaddr, + uint64_t usraddr, + vm_size_t size) +{ + //ppc version ported to arm + kern_return_t ret = KERN_SUCCESS; + + if (ml_at_interrupt_context()) { + return KERN_FAILURE; // can't look at tasks on interrupt stack + } + + if (current_task() == task) { + thread_t cur_thr = current_thread(); + vm_offset_t recover_handler = cur_thr->recover; + + if (copyin(usraddr, kernaddr, size)) { + ret = KERN_FAILURE; + } + cur_thr->recover = recover_handler; + } else { + vm_map_t map = get_task_map(task); + ret = vm_map_read_user(map, usraddr, kernaddr, size); + } + + return ret; +} + +static inline uint64_t +chudxnu_vm_unslide( uint64_t ptr, int kaddr ) +{ + if (!kaddr) + return ptr; + + return VM_KERNEL_UNSLIDE(ptr); +} + +#if __arm__ +#define ARM_SUPERVISOR_MODE(cpsr) ((((cpsr) & PSR_MODE_MASK) != PSR_USER_MODE) ? TRUE : FALSE) +#define CS_FLAG_EXTRASP 1 // capture extra sp register +static kern_return_t +chudxnu_thread_get_callstack64_internal( + thread_t thread, + uint64_t *callStack, + mach_msg_type_number_t *count, + boolean_t user_only, + int flags) +{ + kern_return_t kr; + task_t task; + uint64_t currPC=0ULL, currLR=0ULL, currSP=0ULL; + uint64_t prevPC = 0ULL; + uint32_t kernStackMin = thread->kernel_stack; + uint32_t kernStackMax = kernStackMin + kernel_stack_size; + uint64_t *buffer = callStack; + uint32_t frame[2]; + int bufferIndex = 0; + int bufferMaxIndex = 0; + boolean_t supervisor = FALSE; + struct arm_saved_state *state = NULL; + uint32_t *fp=NULL, *nextFramePointer=NULL, *topfp=NULL; + uint64_t pc = 0ULL; + + task = get_threadtask(thread); + + bufferMaxIndex = *count; + //get thread state + if (user_only) + state = find_user_regs(thread); + else + state = find_kern_regs(thread); + + if (!state) { + *count = 0; + return KERN_FAILURE; + } + + /* make sure it is safe to dereference before you do it */ + supervisor = ARM_SUPERVISOR_MODE(state->cpsr); + + /* can't take a kernel callstack if we've got a user frame */ + if( !user_only && !supervisor ) + return KERN_FAILURE; + + /* + * Reserve space for saving LR (and sometimes SP) at the end of the + * backtrace. + */ + if (flags & CS_FLAG_EXTRASP) { + bufferMaxIndex -= 2; + } else { + bufferMaxIndex -= 1; + } + + if (bufferMaxIndex < 2) { + *count = 0; + return KERN_RESOURCE_SHORTAGE; + } + + currPC = (uint64_t)state->pc; /* r15 */ + if (state->cpsr & PSR_TF) + currPC |= 1ULL; /* encode thumb mode into low bit of PC */ + + currLR = (uint64_t)state->lr; /* r14 */ + currSP = (uint64_t)state->sp; /* r13 */ + + fp = (uint32_t *)state->r[7]; /* frame pointer */ + topfp = fp; + + bufferIndex = 0; // start with a stack of size zero + buffer[bufferIndex++] = chudxnu_vm_unslide(currPC, supervisor); // save PC in position 0. + + // Now, fill buffer with stack backtraces. + while (bufferIndex < bufferMaxIndex) { + pc = 0ULL; + /* + * Below the frame pointer, the following values are saved: + * -> FP + */ + + /* + * Note that we read the pc even for the first stack frame + * (which, in theory, is always empty because the callee fills + * it in just before it lowers the stack. However, if we + * catch the program in between filling in the return address + * and lowering the stack, we want to still have a valid + * backtrace. FixupStack correctly disregards this value if + * necessary. + */ + + if((uint32_t)fp == 0 || ((uint32_t)fp & 0x3) != 0) { + /* frame pointer is invalid - stop backtracing */ + pc = 0ULL; + break; + } + + if (supervisor) { + if (((uint32_t)fp > kernStackMax) || + ((uint32_t)fp < kernStackMin)) { + kr = KERN_FAILURE; + } else { + kr = chudxnu_kern_read(&frame, + (vm_offset_t)fp, + (vm_size_t)sizeof(frame)); + if (kr == KERN_SUCCESS) { + pc = (uint64_t)frame[1]; + nextFramePointer = (uint32_t *) (frame[0]); + } else { + pc = 0ULL; + nextFramePointer = 0ULL; + kr = KERN_FAILURE; + } + } + } else { + kr = chudxnu_task_read(task, + &frame, + (((uint64_t)(uint32_t)fp) & 0x00000000FFFFFFFFULL), + sizeof(frame)); + if (kr == KERN_SUCCESS) { + pc = (uint64_t) frame[1]; + nextFramePointer = (uint32_t *) (frame[0]); + } else { + pc = 0ULL; + nextFramePointer = 0ULL; + kr = KERN_FAILURE; + } + } + + if (kr != KERN_SUCCESS) { + pc = 0ULL; + break; + } + + if (nextFramePointer) { + buffer[bufferIndex++] = chudxnu_vm_unslide(pc, supervisor); + prevPC = pc; + } + + if (nextFramePointer < fp) + break; + else + fp = nextFramePointer; + } + + if (bufferIndex >= bufferMaxIndex) { + bufferIndex = bufferMaxIndex; + kr = KERN_RESOURCE_SHORTAGE; + } else { + kr = KERN_SUCCESS; + } + + // Save link register and R13 (sp) at bottom of stack (used for later fixup). + buffer[bufferIndex++] = chudxnu_vm_unslide(currLR, supervisor); + if( flags & CS_FLAG_EXTRASP ) + buffer[bufferIndex++] = chudxnu_vm_unslide(currSP, supervisor); + + *count = bufferIndex; + return kr; + + +} + +kern_return_t +chudxnu_thread_get_callstack64_kperf( + thread_t thread, + uint64_t *callStack, + mach_msg_type_number_t *count, + boolean_t user_only) +{ + return chudxnu_thread_get_callstack64_internal( thread, callStack, count, user_only, 0 ); +} +#elif __arm64__ +// chudxnu_thread_get_callstack gathers a raw callstack along with any information needed to +// fix it up later (in case we stopped program as it was saving values into prev stack frame, etc.) +// after sampling has finished. +// +// For an N-entry callstack: +// +// [0] current pc +// [1..N-3] stack frames (including current one) +// [N-2] current LR (return value if we're in a leaf function) +// [N-1] current r0 (in case we've saved LR in r0) (optional) +// +// +#define ARM_SUPERVISOR_MODE(cpsr) ((((cpsr) & PSR_MODE_MASK) != PSR_USER_MODE) ? TRUE : FALSE) + +#define CS_FLAG_EXTRASP 1 // capture extra sp register + +static kern_return_t +chudxnu_thread_get_callstack64_internal( + thread_t thread, + uint64_t *callStack, + mach_msg_type_number_t *count, + boolean_t user_only, + int flags) +{ + kern_return_t kr = KERN_SUCCESS; + task_t task; + uint64_t currPC=0ULL, currLR=0ULL, currSP=0ULL; + uint64_t prevPC = 0ULL; + uint64_t kernStackMin = thread->kernel_stack; + uint64_t kernStackMax = kernStackMin + kernel_stack_size; + uint64_t *buffer = callStack; + int bufferIndex = 0; + int bufferMaxIndex = 0; + boolean_t kernel = FALSE; + struct arm_saved_state *sstate = NULL; + uint64_t pc = 0ULL; + + task = get_threadtask(thread); + bufferMaxIndex = *count; + //get thread state + if (user_only) + sstate = find_user_regs(thread); + else + sstate = find_kern_regs(thread); + + if (!sstate) { + *count = 0; + return KERN_FAILURE; + } + + if (is_saved_state64(sstate)) { + struct arm_saved_state64 *state = NULL; + uint64_t *fp=NULL, *nextFramePointer=NULL, *topfp=NULL; + uint64_t frame[2]; + + state = saved_state64(sstate); + + /* make sure it is safe to dereference before you do it */ + kernel = PSR64_IS_KERNEL(state->cpsr); + + /* can't take a kernel callstack if we've got a user frame */ + if( !user_only && !kernel ) + return KERN_FAILURE; + + /* + * Reserve space for saving LR (and sometimes SP) at the end of the + * backtrace. + */ + if (flags & CS_FLAG_EXTRASP) { + bufferMaxIndex -= 2; + } else { + bufferMaxIndex -= 1; + } + + if (bufferMaxIndex < 2) { + *count = 0; + return KERN_RESOURCE_SHORTAGE; + } + + currPC = state->pc; + currLR = state->lr; + currSP = state->sp; + + fp = (uint64_t *)state->fp; /* frame pointer */ + topfp = fp; + + bufferIndex = 0; // start with a stack of size zero + buffer[bufferIndex++] = chudxnu_vm_unslide(currPC, kernel); // save PC in position 0. + + BUF_VERB(PERF_CS_BACKTRACE | DBG_FUNC_START, kernel, 0); + + // Now, fill buffer with stack backtraces. + while (bufferIndex < bufferMaxIndex) { + pc = 0ULL; + /* + * Below the frame pointer, the following values are saved: + * -> FP + */ + + /* + * Note that we read the pc even for the first stack frame + * (which, in theory, is always empty because the callee fills + * it in just before it lowers the stack. However, if we + * catch the program in between filling in the return address + * and lowering the stack, we want to still have a valid + * backtrace. FixupStack correctly disregards this value if + * necessary. + */ + + if((uint64_t)fp == 0 || ((uint64_t)fp & 0x3) != 0) { + /* frame pointer is invalid - stop backtracing */ + pc = 0ULL; + break; + } + + if (kernel) { + if (((uint64_t)fp > kernStackMax) || + ((uint64_t)fp < kernStackMin)) { + kr = KERN_FAILURE; + } else { + kr = chudxnu_kern_read(&frame, + (vm_offset_t)fp, + (vm_size_t)sizeof(frame)); + if (kr == KERN_SUCCESS) { + pc = frame[1]; + nextFramePointer = (uint64_t *)frame[0]; + } else { + pc = 0ULL; + nextFramePointer = 0ULL; + kr = KERN_FAILURE; + } + } + } else { + kr = chudxnu_task_read(task, + &frame, + (vm_offset_t)fp, + (vm_size_t)sizeof(frame)); + if (kr == KERN_SUCCESS) { + pc = frame[1]; + nextFramePointer = (uint64_t *)(frame[0]); + } else { + pc = 0ULL; + nextFramePointer = 0ULL; + kr = KERN_FAILURE; + } + } + + if (kr != KERN_SUCCESS) { + pc = 0ULL; + break; + } + + if (nextFramePointer) { + buffer[bufferIndex++] = chudxnu_vm_unslide(pc, kernel); + prevPC = pc; + } + + if (nextFramePointer < fp) + break; + else + fp = nextFramePointer; + } + + BUF_VERB(PERF_CS_BACKTRACE | DBG_FUNC_END, bufferIndex); + + if (bufferIndex >= bufferMaxIndex) { + bufferIndex = bufferMaxIndex; + kr = KERN_RESOURCE_SHORTAGE; + } else { + kr = KERN_SUCCESS; + } + + // Save link register and SP at bottom of stack (used for later fixup). + buffer[bufferIndex++] = chudxnu_vm_unslide(currLR, kernel); + if( flags & CS_FLAG_EXTRASP ) + buffer[bufferIndex++] = chudxnu_vm_unslide(currSP, kernel); + } else { + struct arm_saved_state32 *state = NULL; + uint32_t *fp=NULL, *nextFramePointer=NULL, *topfp=NULL; + + /* 64-bit kernel stacks, 32-bit user stacks */ + uint64_t frame[2]; + uint32_t frame32[2]; + + state = saved_state32(sstate); + + /* make sure it is safe to dereference before you do it */ + kernel = ARM_SUPERVISOR_MODE(state->cpsr); + + /* can't take a kernel callstack if we've got a user frame */ + if( !user_only && !kernel ) + return KERN_FAILURE; + + /* + * Reserve space for saving LR (and sometimes SP) at the end of the + * backtrace. + */ + if (flags & CS_FLAG_EXTRASP) { + bufferMaxIndex -= 2; + } else { + bufferMaxIndex -= 1; + } + + if (bufferMaxIndex < 2) { + *count = 0; + return KERN_RESOURCE_SHORTAGE; + } + + currPC = (uint64_t)state->pc; /* r15 */ + if (state->cpsr & PSR_TF) + currPC |= 1ULL; /* encode thumb mode into low bit of PC */ + + currLR = (uint64_t)state->lr; /* r14 */ + currSP = (uint64_t)state->sp; /* r13 */ + + fp = (uint32_t *)(uintptr_t)state->r[7]; /* frame pointer */ + topfp = fp; + + bufferIndex = 0; // start with a stack of size zero + buffer[bufferIndex++] = chudxnu_vm_unslide(currPC, kernel); // save PC in position 0. + + BUF_VERB(PERF_CS_BACKTRACE | DBG_FUNC_START, kernel, 1); + + // Now, fill buffer with stack backtraces. + while (bufferIndex < bufferMaxIndex) { + pc = 0ULL; + /* + * Below the frame pointer, the following values are saved: + * -> FP + */ + + /* + * Note that we read the pc even for the first stack frame + * (which, in theory, is always empty because the callee fills + * it in just before it lowers the stack. However, if we + * catch the program in between filling in the return address + * and lowering the stack, we want to still have a valid + * backtrace. FixupStack correctly disregards this value if + * necessary. + */ + + if((uint32_t)fp == 0 || ((uint32_t)fp & 0x3) != 0) { + /* frame pointer is invalid - stop backtracing */ + pc = 0ULL; + break; + } + + if (kernel) { + if (((uint32_t)fp > kernStackMax) || + ((uint32_t)fp < kernStackMin)) { + kr = KERN_FAILURE; + } else { + kr = chudxnu_kern_read(&frame, + (vm_offset_t)fp, + (vm_size_t)sizeof(frame)); + if (kr == KERN_SUCCESS) { + pc = (uint64_t)frame[1]; + nextFramePointer = (uint32_t *) (frame[0]); + } else { + pc = 0ULL; + nextFramePointer = 0ULL; + kr = KERN_FAILURE; + } + } + } else { + kr = chudxnu_task_read(task, + &frame32, + (((uint64_t)(uint32_t)fp) & 0x00000000FFFFFFFFULL), + sizeof(frame32)); + if (kr == KERN_SUCCESS) { + pc = (uint64_t)frame32[1]; + nextFramePointer = (uint32_t *)(uintptr_t)(frame32[0]); + } else { + pc = 0ULL; + nextFramePointer = 0ULL; + kr = KERN_FAILURE; + } + } + + if (kr != KERN_SUCCESS) { + pc = 0ULL; + break; + } + + if (nextFramePointer) { + buffer[bufferIndex++] = chudxnu_vm_unslide(pc, kernel); + prevPC = pc; + } + + if (nextFramePointer < fp) + break; + else + fp = nextFramePointer; + } + + BUF_VERB(PERF_CS_BACKTRACE | DBG_FUNC_END, bufferIndex); + + /* clamp callstack size to max */ + if (bufferIndex >= bufferMaxIndex) { + bufferIndex = bufferMaxIndex; + kr = KERN_RESOURCE_SHORTAGE; + } else { + /* ignore all other failures */ + kr = KERN_SUCCESS; + } + + // Save link register and R13 (sp) at bottom of stack (used for later fixup). + buffer[bufferIndex++] = chudxnu_vm_unslide(currLR, kernel); + if( flags & CS_FLAG_EXTRASP ) + buffer[bufferIndex++] = chudxnu_vm_unslide(currSP, kernel); + } + + *count = bufferIndex; + return kr; +} + +kern_return_t +chudxnu_thread_get_callstack64_kperf( + thread_t thread, + uint64_t *callStack, + mach_msg_type_number_t *count, + boolean_t user_only) +{ + return chudxnu_thread_get_callstack64_internal( thread, callStack, count, user_only, 0 ); +} +#elif __x86_64__ + +#define VALID_STACK_ADDRESS(supervisor, addr, minKernAddr, maxKernAddr) (supervisor ? (addr>=minKernAddr && addr<=maxKernAddr) : TRUE) +// don't try to read in the hole +#define VALID_STACK_ADDRESS64(supervisor, addr, minKernAddr, maxKernAddr) \ +(supervisor ? ((uint64_t)addr >= minKernAddr && (uint64_t)addr <= maxKernAddr) : \ +((uint64_t)addr != 0ULL && ((uint64_t)addr <= 0x00007FFFFFFFFFFFULL || (uint64_t)addr >= 0xFFFF800000000000ULL))) + +typedef struct _cframe64_t { + uint64_t prevFP; // can't use a real pointer here until we're a 64 bit kernel + uint64_t caller; + uint64_t args[0]; +}cframe64_t; + + +typedef struct _cframe_t { + uint32_t prev; // this is really a user32-space pointer to the previous frame + uint32_t caller; + uint32_t args[0]; +} cframe_t; + +extern void * find_user_regs(thread_t); +extern x86_saved_state32_t *find_kern_regs(thread_t); + +static kern_return_t do_kernel_backtrace( + thread_t thread, + struct x86_kernel_state *regs, + uint64_t *frames, + mach_msg_type_number_t *start_idx, + mach_msg_type_number_t max_idx) +{ + uint64_t kernStackMin = (uint64_t)thread->kernel_stack; + uint64_t kernStackMax = (uint64_t)kernStackMin + kernel_stack_size; + mach_msg_type_number_t ct = *start_idx; + kern_return_t kr = KERN_FAILURE; + +#if __LP64__ + uint64_t currPC = 0ULL; + uint64_t currFP = 0ULL; + uint64_t prevPC = 0ULL; + uint64_t prevFP = 0ULL; + if(KERN_SUCCESS != chudxnu_kern_read(&currPC, (vm_offset_t)&(regs->k_rip), sizeof(uint64_t))) { + return KERN_FAILURE; + } + if(KERN_SUCCESS != chudxnu_kern_read(&currFP, (vm_offset_t)&(regs->k_rbp), sizeof(uint64_t))) { + return KERN_FAILURE; + } +#else + uint32_t currPC = 0U; + uint32_t currFP = 0U; + uint32_t prevPC = 0U; + uint32_t prevFP = 0U; + if(KERN_SUCCESS != chudxnu_kern_read(&currPC, (vm_offset_t)&(regs->k_eip), sizeof(uint32_t))) { + return KERN_FAILURE; + } + if(KERN_SUCCESS != chudxnu_kern_read(&currFP, (vm_offset_t)&(regs->k_ebp), sizeof(uint32_t))) { + return KERN_FAILURE; + } +#endif + + if(*start_idx >= max_idx) + return KERN_RESOURCE_SHORTAGE; // no frames traced + + if(!currPC) { + return KERN_FAILURE; + } + + frames[ct++] = chudxnu_vm_unslide((uint64_t)currPC, 1); + + // build a backtrace of this kernel state +#if __LP64__ + while(VALID_STACK_ADDRESS64(TRUE, currFP, kernStackMin, kernStackMax)) { + // this is the address where caller lives in the user thread + uint64_t caller = currFP + sizeof(uint64_t); +#else + while(VALID_STACK_ADDRESS(TRUE, currFP, kernStackMin, kernStackMax)) { + uint32_t caller = (uint32_t)currFP + sizeof(uint32_t); +#endif + + if(!currFP || !currPC) { + currPC = 0; + break; + } + + if(ct >= max_idx) { + *start_idx = ct; + return KERN_RESOURCE_SHORTAGE; + } + + /* read our caller */ + kr = chudxnu_kern_read(&currPC, (vm_offset_t)caller, sizeof(currPC)); + + if(kr != KERN_SUCCESS || !currPC) { + currPC = 0UL; + break; + } + + /* + * retrive contents of the frame pointer and advance to the next stack + * frame if it's valid + */ + prevFP = 0; + kr = chudxnu_kern_read(&prevFP, (vm_offset_t)currFP, sizeof(currPC)); + +#if __LP64__ + if(VALID_STACK_ADDRESS64(TRUE, prevFP, kernStackMin, kernStackMax)) { +#else + if(VALID_STACK_ADDRESS(TRUE, prevFP, kernStackMin, kernStackMax)) { +#endif + frames[ct++] = chudxnu_vm_unslide((uint64_t)currPC, 1); + prevPC = currPC; + } + if(prevFP <= currFP) { + break; + } else { + currFP = prevFP; + } + } + + *start_idx = ct; + return KERN_SUCCESS; +} + + + +static kern_return_t do_backtrace32( + task_t task, + thread_t thread, + x86_saved_state32_t *regs, + uint64_t *frames, + mach_msg_type_number_t *start_idx, + mach_msg_type_number_t max_idx, + boolean_t supervisor) +{ + uint32_t tmpWord = 0UL; + uint64_t currPC = (uint64_t) regs->eip; + uint64_t currFP = (uint64_t) regs->ebp; + uint64_t prevPC = 0ULL; + uint64_t prevFP = 0ULL; + uint64_t kernStackMin = thread->kernel_stack; + uint64_t kernStackMax = kernStackMin + kernel_stack_size; + mach_msg_type_number_t ct = *start_idx; + kern_return_t kr = KERN_FAILURE; + + if(ct >= max_idx) + return KERN_RESOURCE_SHORTAGE; // no frames traced + + frames[ct++] = chudxnu_vm_unslide(currPC, supervisor); + + // build a backtrace of this 32 bit state. + while(VALID_STACK_ADDRESS(supervisor, currFP, kernStackMin, kernStackMax)) { + cframe_t *fp = (cframe_t *) (uintptr_t) currFP; + + if(!currFP) { + currPC = 0; + break; + } + + if(ct >= max_idx) { + *start_idx = ct; + return KERN_RESOURCE_SHORTAGE; + } + + /* read our caller */ + if(supervisor) { + kr = chudxnu_kern_read(&tmpWord, (vm_offset_t) &fp->caller, sizeof(uint32_t)); + } else { + kr = chudxnu_task_read(task, &tmpWord, (vm_offset_t) &fp->caller, sizeof(uint32_t)); + } + + if(kr != KERN_SUCCESS) { + currPC = 0ULL; + break; + } + + currPC = (uint64_t) tmpWord; // promote 32 bit address + + /* + * retrive contents of the frame pointer and advance to the next stack + * frame if it's valid + */ + prevFP = 0; + if(supervisor) { + kr = chudxnu_kern_read(&tmpWord, (vm_offset_t)&fp->prev, sizeof(uint32_t)); + } else { + kr = chudxnu_task_read(task, &tmpWord, (vm_offset_t)&fp->prev, sizeof(uint32_t)); + } + prevFP = (uint64_t) tmpWord; // promote 32 bit address + + if(prevFP) { + frames[ct++] = chudxnu_vm_unslide(currPC, supervisor); + prevPC = currPC; + } + if(prevFP < currFP) { + break; + } else { + currFP = prevFP; + } + } + + *start_idx = ct; + return KERN_SUCCESS; +} + +static kern_return_t do_backtrace64( + task_t task, + thread_t thread, + x86_saved_state64_t *regs, + uint64_t *frames, + mach_msg_type_number_t *start_idx, + mach_msg_type_number_t max_idx, + boolean_t supervisor) +{ + uint64_t currPC = regs->isf.rip; + uint64_t currFP = regs->rbp; + uint64_t prevPC = 0ULL; + uint64_t prevFP = 0ULL; + uint64_t kernStackMin = (uint64_t)thread->kernel_stack; + uint64_t kernStackMax = (uint64_t)kernStackMin + kernel_stack_size; + mach_msg_type_number_t ct = *start_idx; + kern_return_t kr = KERN_FAILURE; + + if(*start_idx >= max_idx) + return KERN_RESOURCE_SHORTAGE; // no frames traced + + frames[ct++] = chudxnu_vm_unslide(currPC, supervisor); + + // build a backtrace of this 32 bit state. + while(VALID_STACK_ADDRESS64(supervisor, currFP, kernStackMin, kernStackMax)) { + // this is the address where caller lives in the user thread + uint64_t caller = currFP + sizeof(uint64_t); + + if(!currFP) { + currPC = 0; + break; + } + + if(ct >= max_idx) { + *start_idx = ct; + return KERN_RESOURCE_SHORTAGE; + } + + /* read our caller */ + if(supervisor) { + kr = chudxnu_kern_read(&currPC, (vm_offset_t)caller, sizeof(uint64_t)); + } else { + kr = chudxnu_task_read(task, &currPC, caller, sizeof(uint64_t)); + } + + if(kr != KERN_SUCCESS) { + currPC = 0ULL; + break; + } + + /* + * retrive contents of the frame pointer and advance to the next stack + * frame if it's valid + */ + prevFP = 0; + if(supervisor) { + kr = chudxnu_kern_read(&prevFP, (vm_offset_t)currFP, sizeof(uint64_t)); + } else { + kr = chudxnu_task_read(task, &prevFP, currFP, sizeof(uint64_t)); + } + + if(VALID_STACK_ADDRESS64(supervisor, prevFP, kernStackMin, kernStackMax)) { + frames[ct++] = chudxnu_vm_unslide(currPC, supervisor); + prevPC = currPC; + } + if(prevFP < currFP) { + break; + } else { + currFP = prevFP; + } + } + + *start_idx = ct; + return KERN_SUCCESS; +} + +static kern_return_t +chudxnu_thread_get_callstack64_internal( + thread_t thread, + uint64_t *callstack, + mach_msg_type_number_t *count, + boolean_t user_only, + boolean_t kern_only) +{ + kern_return_t kr = KERN_FAILURE; + task_t task = thread->task; + uint64_t currPC = 0ULL; + boolean_t supervisor = FALSE; + mach_msg_type_number_t bufferIndex = 0; + mach_msg_type_number_t bufferMaxIndex = *count; + x86_saved_state_t *tagged_regs = NULL; // kernel register state + x86_saved_state64_t *regs64 = NULL; + x86_saved_state32_t *regs32 = NULL; + x86_saved_state32_t *u_regs32 = NULL; + x86_saved_state64_t *u_regs64 = NULL; + struct x86_kernel_state *kregs = NULL; + + if(ml_at_interrupt_context()) { + + if(user_only) { + /* can't backtrace user state on interrupt stack. */ + return KERN_FAILURE; + } + + /* backtracing at interrupt context? */ + if(thread == current_thread() && current_cpu_datap()->cpu_int_state) { + /* + * Locate the registers for the interrupted thread, assuming it is + * current_thread(). + */ + tagged_regs = current_cpu_datap()->cpu_int_state; + + if(is_saved_state64(tagged_regs)) { + /* 64 bit registers */ + regs64 = saved_state64(tagged_regs); + supervisor = ((regs64->isf.cs & SEL_PL) != SEL_PL_U); + } else { + /* 32 bit registers */ + regs32 = saved_state32(tagged_regs); + supervisor = ((regs32->cs & SEL_PL) != SEL_PL_U); + } + } + } + + if(!ml_at_interrupt_context() && kernel_task == task) { + + if(!thread->kernel_stack) { + return KERN_FAILURE; + } + + // Kernel thread not at interrupt context + kregs = (struct x86_kernel_state *)NULL; + + // nofault read of the thread->kernel_stack pointer + if(KERN_SUCCESS != chudxnu_kern_read(&kregs, (vm_offset_t)&(thread->kernel_stack), sizeof(void *))) { + return KERN_FAILURE; + } + + // Adjust to find the saved kernel state + kregs = STACK_IKS((vm_offset_t)(uintptr_t)kregs); + + supervisor = TRUE; + } else if(!tagged_regs) { + /* + * not at interrupt context, or tracing a different thread than + * current_thread() at interrupt context + */ + tagged_regs = USER_STATE(thread); + if(is_saved_state64(tagged_regs)) { + /* 64 bit registers */ + regs64 = saved_state64(tagged_regs); + supervisor = ((regs64->isf.cs & SEL_PL) != SEL_PL_U); + } else { + /* 32 bit registers */ + regs32 = saved_state32(tagged_regs); + supervisor = ((regs32->cs & SEL_PL) != SEL_PL_U); + } + } + + *count = 0; + + if(supervisor) { + // the caller only wants a user callstack. + if(user_only) { + // bail - we've only got kernel state + return KERN_FAILURE; + } + } else { + // regs32(64) is not in supervisor mode. + u_regs32 = regs32; + u_regs64 = regs64; + regs32 = NULL; + regs64 = NULL; + } + + if (user_only) { + /* we only want to backtrace the user mode */ + if(!(u_regs32 || u_regs64)) { + /* no user state to look at */ + return KERN_FAILURE; + } + } + + /* + * Order of preference for top of stack: + * 64 bit kernel state (not likely) + * 32 bit kernel state + * 64 bit user land state + * 32 bit user land state + */ + + if(kregs) { + /* + * nofault read of the registers from the kernel stack (as they can + * disappear on the fly). + */ + + if(KERN_SUCCESS != chudxnu_kern_read(&currPC, (vm_offset_t)&(kregs->k_rip), sizeof(uint64_t))) { + return KERN_FAILURE; + } + } else if(regs64) { + currPC = regs64->isf.rip; + } else if(regs32) { + currPC = (uint64_t) regs32->eip; + } else if(u_regs64) { + currPC = u_regs64->isf.rip; + } else if(u_regs32) { + currPC = (uint64_t) u_regs32->eip; + } + + if(!currPC) { + /* no top of the stack, bail out */ + return KERN_FAILURE; + } + + bufferIndex = 0; + + if(bufferMaxIndex < 1) { + *count = 0; + return KERN_RESOURCE_SHORTAGE; + } + + /* backtrace kernel */ + if(kregs) { + addr64_t address = 0ULL; + size_t size = 0UL; + + // do the backtrace + kr = do_kernel_backtrace(thread, kregs, callstack, &bufferIndex, bufferMaxIndex); + + // and do a nofault read of (r|e)sp + uint64_t rsp = 0ULL; + size = sizeof(uint64_t); + + if(KERN_SUCCESS != chudxnu_kern_read(&address, (vm_offset_t)&(kregs->k_rsp), size)) { + address = 0ULL; + } + + if(address && KERN_SUCCESS == chudxnu_kern_read(&rsp, (vm_offset_t)address, size) && bufferIndex < bufferMaxIndex) { + callstack[bufferIndex++] = (uint64_t)rsp; + } + } else if(regs64) { + uint64_t rsp = 0ULL; + + // backtrace the 64bit side. + kr = do_backtrace64(task, thread, regs64, callstack, &bufferIndex, + bufferMaxIndex - 1, TRUE); + + if(KERN_SUCCESS == chudxnu_kern_read(&rsp, (vm_offset_t) regs64->isf.rsp, sizeof(uint64_t)) && + bufferIndex < bufferMaxIndex) { + callstack[bufferIndex++] = rsp; + } + + } else if(regs32) { + uint32_t esp = 0UL; + + // backtrace the 32bit side. + kr = do_backtrace32(task, thread, regs32, callstack, &bufferIndex, + bufferMaxIndex - 1, TRUE); + + if(KERN_SUCCESS == chudxnu_kern_read(&esp, (vm_offset_t) regs32->uesp, sizeof(uint32_t)) && + bufferIndex < bufferMaxIndex) { + callstack[bufferIndex++] = (uint64_t) esp; + } + } else if(u_regs64 && !kern_only) { + /* backtrace user land */ + uint64_t rsp = 0ULL; + + kr = do_backtrace64(task, thread, u_regs64, callstack, &bufferIndex, + bufferMaxIndex - 1, FALSE); + + if(KERN_SUCCESS == chudxnu_task_read(task, &rsp, (addr64_t) u_regs64->isf.rsp, sizeof(uint64_t)) && + bufferIndex < bufferMaxIndex) { + callstack[bufferIndex++] = rsp; + } + + } else if(u_regs32 && !kern_only) { + uint32_t esp = 0UL; + + kr = do_backtrace32(task, thread, u_regs32, callstack, &bufferIndex, + bufferMaxIndex - 1, FALSE); + + if(KERN_SUCCESS == chudxnu_task_read(task, &esp, (addr64_t) u_regs32->uesp, sizeof(uint32_t)) && + bufferIndex < bufferMaxIndex) { + callstack[bufferIndex++] = (uint64_t) esp; + } + } + + *count = bufferIndex; + return kr; +} + +__private_extern__ +kern_return_t chudxnu_thread_get_callstack64_kperf( + thread_t thread, + uint64_t *callstack, + mach_msg_type_number_t *count, + boolean_t is_user) +{ + return chudxnu_thread_get_callstack64_internal(thread, callstack, count, is_user, !is_user); +} +#else /* !__arm__ && !__arm64__ && !__x86_64__ */ +#error kperf: unsupported architecture +#endif /* !__arm__ && !__arm64__ && !__x86_64__ */ diff --git a/osfmk/kperf/kperf_timer.c b/osfmk/kperf/kperf_timer.c index a6cf3c2e3..86ed35d87 100644 --- a/osfmk/kperf/kperf_timer.c +++ b/osfmk/kperf/kperf_timer.c @@ -105,8 +105,6 @@ static void kperf_sample_cpu(struct kperf_timer *timer, bool system_sample, bool only_system) { - struct kperf_context ctx; - assert(timer != NULL); /* Always cut a tracepoint to show a sample event occurred */ @@ -115,15 +113,18 @@ kperf_sample_cpu(struct kperf_timer *timer, bool system_sample, int ncpu = cpu_number(); struct kperf_sample *intbuf = kperf_intr_sample_buffer(); +#if DEVELOPMENT || DEBUG + intbuf->sample_time = mach_absolute_time(); +#endif /* DEVELOPMENT || DEBUG */ /* On a timer, we can see the "real" current thread */ - ctx.cur_thread = current_thread(); + struct kperf_context ctx = { + .cur_thread = current_thread(), + .trigger_type = TRIGGER_TYPE_TIMER, + .trigger_id = (unsigned int)(timer - kperf_timerv), + }; ctx.cur_pid = task_pid(get_threadtask(ctx.cur_thread)); - /* who fired */ - ctx.trigger_type = TRIGGER_TYPE_TIMER; - ctx.trigger_id = (unsigned int)(timer - kperf_timerv); - if (ctx.trigger_id == pet_timer_id && ncpu < machine_info.logical_cpu_max) { kperf_tid_on_cpus[ncpu] = thread_tid(ctx.cur_thread); } @@ -169,6 +170,9 @@ kperf_timer_handler(void *param0, __unused void *param1) } timer->active = 1; +#if DEVELOPMENT || DEBUG + timer->fire_time = mach_absolute_time(); +#endif /* DEVELOPMENT || DEBUG */ /* along the lines of do not ipi if we are all shutting down */ if (kperf_sampling_status() == KPERF_SAMPLING_SHUTDOWN) { diff --git a/osfmk/kperf/kperf_timer.h b/osfmk/kperf/kperf_timer.h index 946cc21c0..fcc642217 100644 --- a/osfmk/kperf/kperf_timer.h +++ b/osfmk/kperf/kperf_timer.h @@ -45,6 +45,10 @@ struct kperf_timer { * timers. */ bitmap_t pending_cpus; + +#if DEVELOPMENT || DEBUG + uint64_t fire_time; +#endif /* DEVELOPMENT || DEBUG */ }; extern struct kperf_timer *kperf_timerv; diff --git a/osfmk/kperf/sample.h b/osfmk/kperf/sample.h index 35175294f..35e186ebb 100644 --- a/osfmk/kperf/sample.h +++ b/osfmk/kperf/sample.h @@ -49,7 +49,11 @@ struct kperf_sample { #if KPC struct kpcdata kpcdata; -#endif +#endif /* KPC */ + +#if DEVELOPMENT || DEBUG + uint64_t sample_time; +#endif /* DEVELOPMENT || DEBUG */ }; /* cache of threads on each CPU during a timer fire */ diff --git a/osfmk/kperf/thread_samplers.c b/osfmk/kperf/thread_samplers.c index e62f8934d..176520f0c 100644 --- a/osfmk/kperf/thread_samplers.c +++ b/osfmk/kperf/thread_samplers.c @@ -91,12 +91,12 @@ kperf_thread_info_runmode_legacy(thread_t thread) kperf_state |= KPERF_TI_IDLE; } -#if !TARGET_OS_EMBEDDED +#if !CONFIG_EMBEDDED /* on desktop, if state is blank, leave not idle set */ if (kperf_state == 0) { return (TH_IDLE << 16); } -#endif /* !TARGET_OS_EMBEDDED */ +#endif /* !CONFIG_EMBEDDED */ /* high two bytes are inverted mask, low two bytes are normal */ return (((~kperf_state & 0xffff) << 16) | (kperf_state & 0xffff)); diff --git a/osfmk/mach/Makefile b/osfmk/mach/Makefile index 815aa22d9..9c293a5ce 100644 --- a/osfmk/mach/Makefile +++ b/osfmk/mach/Makefile @@ -166,6 +166,7 @@ INSTALL_MI_LIST = \ # installed into System.framework's PrivateHeaders/mach subdirectory PRIVATE_DATAFILES = \ bootstrap.h \ + branch_predicates.h \ coalition.h \ coalition_notification.defs \ host_info.h \ diff --git a/osfmk/mach/branch_predicates.h b/osfmk/mach/branch_predicates.h index 0882d3e1e..a551970dc 100644 --- a/osfmk/mach/branch_predicates.h +++ b/osfmk/mach/branch_predicates.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2009 Apple Inc. All rights reserved. + * Copyright (c) 2000-2018 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -31,5 +31,7 @@ #define _MACH_BRANCH_PREDICATES_H #define __probable(x) __builtin_expect(!!((long)(x)), 1L) + #define __improbable(x) __builtin_expect(!!((long)(x)), 0L) + #endif /* _MACH_BRANCH_PREDICATES_H */ diff --git a/osfmk/mach/coalition.h b/osfmk/mach/coalition.h index 40824547e..f7a24ef19 100644 --- a/osfmk/mach/coalition.h +++ b/osfmk/mach/coalition.h @@ -99,6 +99,8 @@ #define COALITION_NUM_SORT (6) +#define COALITION_NUM_THREAD_QOS_TYPES 7 + /* Coalition Efficiency Interface Support */ /* Flags for coalition efficiency */ @@ -139,6 +141,8 @@ struct coalition_resource_usage { uint64_t energy_billed_to_me; uint64_t energy_billed_to_others; uint64_t cpu_ptime; + uint64_t cpu_time_eqos_len; /* Stores the number of thread QoS types */ + uint64_t cpu_time_eqos[COALITION_NUM_THREAD_QOS_TYPES]; }; #ifdef PRIVATE diff --git a/osfmk/mach/host_special_ports.h b/osfmk/mach/host_special_ports.h index 73efdc4f4..82ed8d003 100644 --- a/osfmk/mach/host_special_ports.h +++ b/osfmk/mach/host_special_ports.h @@ -88,7 +88,7 @@ #define HOST_KTRACE_BACKGROUND_PORT (6 + HOST_MAX_SPECIAL_KERNEL_PORT) #define HOST_SEATBELT_PORT (7 + HOST_MAX_SPECIAL_KERNEL_PORT) #define HOST_KEXTD_PORT (8 + HOST_MAX_SPECIAL_KERNEL_PORT) -#define HOST_CHUD_PORT (9 + HOST_MAX_SPECIAL_KERNEL_PORT) +#define HOST_LAUNCHCTL_PORT (9 + HOST_MAX_SPECIAL_KERNEL_PORT) #define HOST_UNFREED_PORT (10 + HOST_MAX_SPECIAL_KERNEL_PORT) #define HOST_AMFID_PORT (11 + HOST_MAX_SPECIAL_KERNEL_PORT) #define HOST_GSSD_PORT (12 + HOST_MAX_SPECIAL_KERNEL_PORT) @@ -105,6 +105,9 @@ #define HOST_MAX_SPECIAL_PORT HOST_CLOSURED_PORT /* MAX = last since rdar://19421223 */ +/* obsolete name */ +#define HOST_CHUD_PORT HOST_LAUNCHCTL_PORT + /* * Special node identifier to always represent the local node. */ @@ -177,11 +180,14 @@ #define host_set_kextd_port(host, port) \ (host_set_special_port((host), HOST_KEXTD_PORT, (port))) -#define host_get_chud_port(host, port) \ - (host_get_special_port((host), \ - HOST_LOCAL_NODE, HOST_CHUD_PORT, (port))) -#define host_set_chud_port(host, port) \ - (host_set_special_port((host), HOST_CHUD_PORT, (port))) +#define host_get_launchctl_port(host, port) \ + (host_get_special_port((host), HOST_LOCAL_NODE, HOST_LAUNCHCTL_PORT, \ + (port))) +#define host_set_launchctl_port(host, port) \ + (host_set_special_port((host), HOST_LAUNCHCTL_PORT, (port))) + +#define host_get_chud_port(host, port) host_get_launchctl_port(host, port) +#define host_set_chud_port(host, port) host_set_launchctl_port(host, port) #define host_get_unfreed_port(host, port) \ (host_get_special_port((host), \ diff --git a/osfmk/mach/mach_host.defs b/osfmk/mach/mach_host.defs index 0f1e2c46d..5ca0e125e 100644 --- a/osfmk/mach/mach_host.defs +++ b/osfmk/mach/mach_host.defs @@ -352,4 +352,27 @@ routine host_check_multiuser_mode( skip; #endif // !KERNEL && LIBSYSCALL_INTERFACE +/* + * Returns information about a specific zone. + * The zone name is passed in via the argument name, + * info returns the zone info. + */ +routine mach_zone_info_for_zone( + host : host_priv_t; + name : mach_zone_name_t; + out info : mach_zone_info_t); + +#ifdef PRIVATE +/* + * Returns information about the largest zone. + * name returns the zone name, info returns the zone info. + */ +routine mach_zone_info_for_largest_zone( + host : host_priv_t; + out name : mach_zone_name_t; + out info : mach_zone_info_t); +#else +skip; +#endif + /* vim: set ft=c : */ diff --git a/osfmk/mach/task_info.h b/osfmk/mach/task_info.h index b06cf4170..58e4e7554 100644 --- a/osfmk/mach/task_info.h +++ b/osfmk/mach/task_info.h @@ -485,6 +485,7 @@ typedef struct task_flags_info * task_flags_info_t; #ifdef PRIVATE struct task_debug_info_internal { + integer_t suspend_count; uint64_t ipc_space_size; }; typedef struct task_debug_info_internal *task_debug_info_internal_t; diff --git a/osfmk/mach/vm32_map.defs b/osfmk/mach/vm32_map.defs index 04e7c0ad5..c4ed1d7cd 100644 --- a/osfmk/mach/vm32_map.defs +++ b/osfmk/mach/vm32_map.defs @@ -279,6 +279,11 @@ routine purgable_control( control : vm_purgable_t; inout state : int); + +routine _map_exec_lockdown( + target_task : vm_map_t); + + #endif /* VM32_SUPPORT */ /* vim: set ft=c : */ diff --git a/osfmk/mach/vm_map.defs b/osfmk/mach/vm_map.defs index c6bda2cbb..7caa92639 100644 --- a/osfmk/mach/vm_map.defs +++ b/osfmk/mach/vm_map.defs @@ -502,4 +502,9 @@ routine PREFIX(vm_purgable_control) ( control : vm_purgable_t; inout state : int); + +routine vm_map_exec_lockdown( + target_task : vm_map_t); + + /* vim: set ft=c : */ diff --git a/osfmk/mach/vm_statistics.h b/osfmk/mach/vm_statistics.h index fa0560559..04fafe640 100644 --- a/osfmk/mach/vm_statistics.h +++ b/osfmk/mach/vm_statistics.h @@ -275,6 +275,9 @@ typedef struct pmap_statistics *pmap_statistics_t; * VM_FLAGS_PURGABLE * Create a purgable VM object for that new VM region. * + * VM_FLAGS_4GB_CHUNK + * The new VM region will be chunked up into 4GB sized pieces. + * * VM_FLAGS_NO_PMAP_CHECK * (for DEBUG kernel config only, ignored for other configs) * Do not check that there is no stale pmap mapping for the new VM region. @@ -294,6 +297,7 @@ typedef struct pmap_statistics *pmap_statistics_t; #define VM_FLAGS_FIXED 0x0000 #define VM_FLAGS_ANYWHERE 0x0001 #define VM_FLAGS_PURGABLE 0x0002 +#define VM_FLAGS_4GB_CHUNK 0x0004 #define VM_FLAGS_RANDOM_ADDR 0x0008 #define VM_FLAGS_NO_CACHE 0x0010 #define VM_FLAGS_RESILIENT_CODESIGN 0x0020 @@ -320,6 +324,7 @@ typedef struct pmap_statistics *pmap_statistics_t; #define VM_FLAGS_USER_ALLOCATE (VM_FLAGS_FIXED | \ VM_FLAGS_ANYWHERE | \ VM_FLAGS_PURGABLE | \ + VM_FLAGS_4GB_CHUNK | \ VM_FLAGS_RANDOM_ADDR | \ VM_FLAGS_NO_CACHE | \ VM_FLAGS_OVERWRITE | \ diff --git a/osfmk/mach_debug/mach_debug_types.defs b/osfmk/mach_debug/mach_debug_types.defs index b4faebbbf..be15db509 100644 --- a/osfmk/mach_debug/mach_debug_types.defs +++ b/osfmk/mach_debug/mach_debug_types.defs @@ -76,8 +76,8 @@ type mach_zone_name_array_t = array[] of mach_zone_name_t; type mach_zone_info_t = struct[8] of uint64_t; type mach_zone_info_array_t = array[] of mach_zone_info_t; -type task_zone_info_t = struct[11] of uint64_t; -type task_zone_info_array_t = array[] of task_zone_info_t; +type task_zone_info_t = struct[11] of uint64_t; /* deprecated */ +type task_zone_info_array_t = array[] of task_zone_info_t; /* deprecated */ type hash_info_bucket_t = struct[1] of natural_t; type hash_info_bucket_array_t = array[] of hash_info_bucket_t; diff --git a/osfmk/mach_debug/zone_info.h b/osfmk/mach_debug/zone_info.h index c54a4c5b3..81bd7badf 100644 --- a/osfmk/mach_debug/zone_info.h +++ b/osfmk/mach_debug/zone_info.h @@ -113,11 +113,24 @@ typedef struct mach_zone_info_data { uint64_t mzi_alloc_size; /* size used for more memory */ uint64_t mzi_sum_size; /* sum of all allocs (life of zone) */ uint64_t mzi_exhaustible; /* merely return if empty? */ - uint64_t mzi_collectable; /* garbage collect elements? */ + uint64_t mzi_collectable; /* garbage collect elements? and how much? */ } mach_zone_info_t; typedef mach_zone_info_t *mach_zone_info_array_t; +/* + * The lowest bit of mzi_collectable indicates whether or not the zone + * is collectable by zone_gc(). The higher bits contain the size in bytes + * that can be collected. + */ +#define GET_MZI_COLLECTABLE_BYTES(val) ((val) >> 1) +#define GET_MZI_COLLECTABLE_FLAG(val) ((val) & 1) + +#define SET_MZI_COLLECTABLE_BYTES(val, size) \ + (val) = ((val) & 1) | ((size) << 1) +#define SET_MZI_COLLECTABLE_FLAG(val, flag) \ + (val) = (flag) ? ((val) | 1) : (val) + typedef struct task_zone_info_data { uint64_t tzi_count; /* count of elements in use */ uint64_t tzi_cur_size; /* current memory utilization */ diff --git a/osfmk/vm/bsd_vm.c b/osfmk/vm/bsd_vm.c index b9d138421..af3985f95 100644 --- a/osfmk/vm/bsd_vm.c +++ b/osfmk/vm/bsd_vm.c @@ -41,6 +41,7 @@ #include #include +#include #include #include @@ -969,6 +970,7 @@ fill_procregioninfo(task_t task, uint64_t arg, struct proc_regioninfo_internal * vm_map_offset_t start; vm_region_extended_info_data_t extended; vm_region_top_info_data_t top; + boolean_t do_region_footprint; task_lock(task); map = task->map; @@ -979,15 +981,75 @@ fill_procregioninfo(task_t task, uint64_t arg, struct proc_regioninfo_internal * } vm_map_reference(map); task_unlock(task); - + + do_region_footprint = task_self_region_footprint(); + vm_map_lock_read(map); start = address; + if (!vm_map_lookup_entry(map, start, &tmp_entry)) { if ((entry = tmp_entry->vme_next) == vm_map_to_entry(map)) { + if (do_region_footprint && + address == tmp_entry->vme_end) { + ledger_amount_t nonvol, nonvol_compressed; + + /* + * This request is right after the last valid + * memory region; instead of reporting the + * end of the address space, report a fake + * memory region to account for non-volatile + * purgeable memory owned by this task. + */ + + ledger_get_balance( + task->ledger, + task_ledgers.purgeable_nonvolatile, + &nonvol); + ledger_get_balance( + task->ledger, + task_ledgers.purgeable_nonvolatile_compressed, + &nonvol_compressed); + if (nonvol + nonvol_compressed == 0) { + /* nothing to report */ + vm_map_unlock_read(map); + vm_map_deallocate(map); + return 0; + } + /* provide fake region for purgeable */ + pinfo->pri_offset = address; + pinfo->pri_protection = VM_PROT_DEFAULT; + pinfo->pri_max_protection = VM_PROT_DEFAULT; + pinfo->pri_inheritance = VM_INHERIT_NONE; + pinfo->pri_behavior = VM_BEHAVIOR_DEFAULT; + pinfo->pri_user_wired_count = 0; + pinfo->pri_user_tag = -1; + pinfo->pri_pages_resident = + (uint32_t) (nonvol / PAGE_SIZE); + pinfo->pri_pages_shared_now_private = 0; + pinfo->pri_pages_swapped_out = + (uint32_t) (nonvol_compressed / PAGE_SIZE); + pinfo->pri_pages_dirtied = + (uint32_t) (nonvol / PAGE_SIZE); + pinfo->pri_ref_count = 1; + pinfo->pri_shadow_depth = 0; + pinfo->pri_share_mode = SM_PRIVATE; + pinfo->pri_private_pages_resident = + (uint32_t) (nonvol / PAGE_SIZE); + pinfo->pri_shared_pages_resident = 0; + pinfo->pri_obj_id = INFO_MAKE_FAKE_OBJECT_ID(map, task_ledgers.purgeable_nonvolatile); + pinfo->pri_address = address; + pinfo->pri_size = + (uint64_t) (nonvol + nonvol_compressed); + pinfo->pri_depth = 0; + + vm_map_unlock_read(map); + vm_map_deallocate(map); + return 1; + } vm_map_unlock_read(map); - vm_map_deallocate(map); - return(0); + vm_map_deallocate(map); + return 0; } } else { entry = tmp_entry; @@ -1020,7 +1082,7 @@ fill_procregioninfo(task_t task, uint64_t arg, struct proc_regioninfo_internal * extended.external_pager = 0; extended.shadow_depth = 0; - vm_map_region_walk(map, start, entry, VME_OFFSET(entry), entry->vme_end - start, &extended); + vm_map_region_walk(map, start, entry, VME_OFFSET(entry), entry->vme_end - start, &extended, TRUE, VM_REGION_EXTENDED_INFO_COUNT); if (extended.external_pager && extended.ref_count == 2 && extended.share_mode == SM_SHARED) extended.share_mode = SM_PRIVATE; diff --git a/osfmk/vm/vm32_user.c b/osfmk/vm/vm32_user.c index f68d9c5aa..c8f3343f1 100644 --- a/osfmk/vm/vm32_user.c +++ b/osfmk/vm/vm32_user.c @@ -555,4 +555,19 @@ vm32__task_wire( return(KERN_SUCCESS); } +kern_return_t +vm32__map_exec_lockdown( + vm_map_t map) +{ + if (map == VM_MAP_NULL) + return(KERN_INVALID_ARGUMENT); + + vm_map_lock(map); + map->map_disallow_new_exec = TRUE; + vm_map_unlock(map); + + return(KERN_SUCCESS); +} + + #endif /* VM32_SUPPORT */ diff --git a/osfmk/vm/vm_compressor.c b/osfmk/vm/vm_compressor.c index 919dbe8b2..f474385b7 100644 --- a/osfmk/vm/vm_compressor.c +++ b/osfmk/vm/vm_compressor.c @@ -849,7 +849,7 @@ c_seg_need_delayed_compaction(c_segment_t c_seg, boolean_t c_list_lock_held) } assert(c_seg->c_state != C_IS_FILLING); - if (!c_seg->c_on_minorcompact_q && !(C_SEG_IS_ONDISK(c_seg))) { + if (!c_seg->c_on_minorcompact_q && !(C_SEG_IS_ON_DISK_OR_SOQ(c_seg))) { queue_enter(&c_minor_list_head, c_seg, c_segment_t, c_list); c_seg->c_on_minorcompact_q = 1; c_minor_count++; @@ -953,6 +953,7 @@ c_seg_do_minor_compaction_and_unlock(c_segment_t c_seg, boolean_t clear_busy, bo int c_seg_freed; assert(c_seg->c_busy); + assert(!C_SEG_IS_ON_DISK_OR_SOQ(c_seg)); /* * check for the case that can occur when we are not swapping @@ -2999,14 +3000,14 @@ c_current_seg_filled(c_segment_t c_seg, c_segment_t *current_chead) lck_mtx_lock_spin_always(c_list_lock); + c_seg->c_generation_id = c_generation_id++; + c_seg_switch_state(c_seg, new_state, FALSE); + #if CONFIG_FREEZE if (c_seg->c_state == C_ON_SWAPOUT_Q) c_freezer_swapout_count++; #endif /* CONFIG_FREEZE */ - c_seg->c_generation_id = c_generation_id++; - c_seg_switch_state(c_seg, new_state, FALSE); - if (c_seg->c_state == C_ON_AGE_Q && C_SEG_UNUSED_BYTES(c_seg) >= PAGE_SIZE) c_seg_need_delayed_compaction(c_seg, TRUE); @@ -3781,6 +3782,7 @@ c_decompress_page(char *dst, volatile c_slot_mapping_t slot_ptr, int flags, int } else if (c_seg->c_on_minorcompact_q) { assert(c_seg->c_state != C_ON_BAD_Q); + assert(!C_SEG_IS_ON_DISK_OR_SOQ(c_seg)); if (C_SEG_SHOULD_MINORCOMPACT_NOW(c_seg)) { c_seg_try_minor_compaction_and_unlock(c_seg); diff --git a/osfmk/vm/vm_compressor.h b/osfmk/vm/vm_compressor.h index ad2f586fe..4b0883873 100644 --- a/osfmk/vm/vm_compressor.h +++ b/osfmk/vm/vm_compressor.h @@ -65,6 +65,7 @@ #endif + #if DEBUG || COMPRESSOR_INTEGRITY_CHECKS #define ENABLE_SWAP_CHECKS 1 #define ENABLE_COMPRESSOR_CHECKS 1 @@ -219,6 +220,9 @@ extern vm_offset_t c_buffers; #define C_SEG_ONDISK_IS_SPARSE(cseg) ((cseg->c_bytes_used < cseg->c_bytes_unused) ? 1 : 0) #define C_SEG_IS_ONDISK(cseg) ((cseg->c_state == C_ON_SWAPPEDOUT_Q || cseg->c_state == C_ON_SWAPPEDOUTSPARSE_Q)) +#define C_SEG_IS_ON_DISK_OR_SOQ(cseg) ((cseg->c_state == C_ON_SWAPPEDOUT_Q || \ + cseg->c_state == C_ON_SWAPPEDOUTSPARSE_Q || \ + cseg->c_state == C_ON_SWAPOUT_Q)) #define C_SEG_WAKEUP_DONE(cseg) \ diff --git a/osfmk/vm/vm_compressor_algorithms.c b/osfmk/vm/vm_compressor_algorithms.c index 3af35c8ec..9411412c6 100644 --- a/osfmk/vm/vm_compressor_algorithms.c +++ b/osfmk/vm/vm_compressor_algorithms.c @@ -417,7 +417,7 @@ void vm_compressor_algorithm_init(void) { PE_parse_boot_argn("vm_compressor_codec", &new_codec, sizeof(new_codec)); assertf(((new_codec == VM_COMPRESSOR_DEFAULT_CODEC) || (new_codec == CMODE_WK) || - (new_codec == CMODE_LZ4) || (new_codec = CMODE_HYB)), + (new_codec == CMODE_LZ4) || (new_codec == CMODE_HYB)), "Invalid VM compression codec: %u", new_codec); #if defined(__arm__)||defined(__arm64__) diff --git a/osfmk/vm/vm_compressor_backing_store.c b/osfmk/vm/vm_compressor_backing_store.c index 4a2eb0fea..f4ec70ce5 100644 --- a/osfmk/vm/vm_compressor_backing_store.c +++ b/osfmk/vm/vm_compressor_backing_store.c @@ -1337,6 +1337,10 @@ vm_swap_put(vm_offset_t addr, uint64_t *f_offset, uint64_t size, c_segment_t c_s return KERN_FAILURE; done: + assert(c_seg->c_busy_swapping); + assert(c_seg->c_busy); + assert(!c_seg->c_on_minorcompact_q); + error = vm_swapfile_io(swf->swp_vp, file_offset, addr, (int) (size / PAGE_SIZE_64), SWAP_WRITE); lck_mtx_lock(&vm_swap_data_lock); diff --git a/osfmk/vm/vm_map.c b/osfmk/vm/vm_map.c index 28aa94218..f6a8e5e5c 100644 --- a/osfmk/vm/vm_map.c +++ b/osfmk/vm/vm_map.c @@ -220,20 +220,6 @@ static boolean_t vm_map_fork_copy( vm_map_t new_map, int vm_map_copyin_flags); -void vm_map_region_top_walk( - vm_map_entry_t entry, - vm_region_top_info_t top); - -void vm_map_region_walk( - vm_map_t map, - vm_map_offset_t va, - vm_map_entry_t entry, - vm_object_offset_t offset, - vm_object_size_t range, - vm_region_extended_info_t extended, - boolean_t look_for_pages, - mach_msg_type_number_t count); - static kern_return_t vm_map_wire_nested( vm_map_t map, vm_map_offset_t start, @@ -1052,6 +1038,7 @@ vm_map_create( result->disable_vmentry_reuse = FALSE; result->map_disallow_data_exec = FALSE; result->is_nested_map = FALSE; + result->map_disallow_new_exec = FALSE; result->highest_entry_end = 0; result->first_free = vm_map_to_entry(result); result->hint = vm_map_to_entry(result); @@ -2015,9 +2002,20 @@ vm_map_enter( kern_return_t kr; boolean_t clear_map_aligned = FALSE; vm_map_entry_t hole_entry; + vm_map_size_t chunk_size = 0; assertf(vmk_flags.__vmkf_unused == 0, "vmk_flags unused=0x%x\n", vmk_flags.__vmkf_unused); + if (flags & VM_FLAGS_4GB_CHUNK) { +#if defined(__LP64__) + chunk_size = (4ULL * 1024 * 1024 * 1024); /* max. 4GB chunks for the new allocation */ +#else /* __LP64__ */ + chunk_size = ANON_CHUNK_SIZE; +#endif /* __LP64__ */ + } else { + chunk_size = ANON_CHUNK_SIZE; + } + if (superpage_size) { switch (superpage_size) { /* @@ -2055,6 +2053,16 @@ vm_map_enter( } #endif /* CONFIG_EMBEDDED */ + /* + * If the task has requested executable lockdown, + * deny any new executable mapping. + */ + if (map->map_disallow_new_exec == TRUE) { + if (cur_protection & VM_PROT_EXECUTE) { + return KERN_PROTECTION_FAILURE; + } + } + if (resilient_codesign || resilient_media) { if ((cur_protection & (VM_PROT_WRITE | VM_PROT_EXECUTE)) || (max_protection & (VM_PROT_WRITE | VM_PROT_EXECUTE))) { @@ -2655,25 +2663,22 @@ StartAgain: ; tmp2_end = tmp2_start + step; /* * Create a new entry - * LP64todo - for now, we can only allocate 4GB internal objects - * because the default pager can't page bigger ones. Remove this - * when it can. * * XXX FBDP * The reserved "page zero" in each process's address space can - * be arbitrarily large. Splitting it into separate 4GB objects and + * be arbitrarily large. Splitting it into separate objects and * therefore different VM map entries serves no purpose and just * slows down operations on the VM map, so let's not split the - * allocation into 4GB chunks if the max protection is NONE. That + * allocation into chunks if the max protection is NONE. That * memory should never be accessible, so it will never get to the * default pager. */ tmp_start = tmp2_start; if (object == VM_OBJECT_NULL && - size > (vm_map_size_t)ANON_CHUNK_SIZE && + size > chunk_size && max_protection != VM_PROT_NONE && superpage_size == 0) - tmp_end = tmp_start + (vm_map_size_t)ANON_CHUNK_SIZE; + tmp_end = tmp_start + chunk_size; else tmp_end = tmp2_end; do { @@ -2831,8 +2836,8 @@ StartAgain: ; } } while (tmp_end != tmp2_end && (tmp_start = tmp_end) && - (tmp_end = (tmp2_end - tmp_end > (vm_map_size_t)ANON_CHUNK_SIZE) ? - tmp_end + (vm_map_size_t)ANON_CHUNK_SIZE : tmp2_end)); + (tmp_end = (tmp2_end - tmp_end > chunk_size) ? + tmp_end + chunk_size : tmp2_end)); } new_mapping_established = TRUE; @@ -3096,6 +3101,16 @@ vm_map_enter_fourk( } #endif /* CONFIG_EMBEDDED */ + /* + * If the task has requested executable lockdown, + * deny any new executable mapping. + */ + if (map->map_disallow_new_exec == TRUE) { + if (cur_protection & VM_PROT_EXECUTE) { + return KERN_PROTECTION_FAILURE; + } + } + if (is_submap) { return KERN_NOT_SUPPORTED; } @@ -5494,6 +5509,20 @@ vm_map_protect( } #endif + /* + * If the task has requested executable lockdown, + * deny both: + * - adding executable protections OR + * - adding write protections to an existing executable mapping. + */ + if (map->map_disallow_new_exec == TRUE) { + if ((new_prot & VM_PROT_EXECUTE) || + ((current->protection & VM_PROT_EXECUTE) && (new_prot & VM_PROT_WRITE))) { + vm_map_unlock(map); + return(KERN_PROTECTION_FAILURE); + } + } + prev = current->vme_end; current = current->vme_next; } @@ -7634,6 +7663,7 @@ vm_map_delete( (entry->vme_end - entry->vme_start)); entry->iokit_acct = FALSE; + entry->use_pmap = FALSE; } /* @@ -8388,6 +8418,8 @@ vm_map_copy_overwrite_nested( vm_map_clip_start( dst_map, entry, sub_start); assert(!entry->use_pmap); + assert(!entry->iokit_acct); + entry->use_pmap = TRUE; entry->is_sub_map = FALSE; vm_map_deallocate( VME_SUBMAP(entry)); @@ -9460,6 +9492,13 @@ vm_map_copy_overwrite_aligned( } } + if (entry->iokit_acct) { + /* keep using iokit accounting */ + entry->use_pmap = FALSE; + } else { + /* use pmap accounting */ + entry->use_pmap = TRUE; + } entry->is_sub_map = FALSE; VME_OBJECT_SET(entry, VME_OBJECT(copy_entry)); object = VME_OBJECT(entry); @@ -10726,6 +10765,19 @@ vm_map_copyin_internal( if (new_entry->is_sub_map) { /* clr address space specifics */ new_entry->use_pmap = FALSE; + } else { + /* + * We're dealing with a copy-on-write operation, + * so the resulting mapping should not inherit the + * original mapping's accounting settings. + * "iokit_acct" should have been cleared in + * vm_map_entry_copy(). + * "use_pmap" should be reset to its default (TRUE) + * so that the new mapping gets accounted for in + * the task's memory footprint. + */ + assert(!new_entry->iokit_acct); + new_entry->use_pmap = TRUE; } /* @@ -10735,8 +10787,7 @@ vm_map_copyin_internal( if (src_destroy && (src_object == VM_OBJECT_NULL || (src_object->internal && - src_object->copy_strategy != MEMORY_OBJECT_COPY_DELAY && - !src_object->true_share && + src_object->copy_strategy == MEMORY_OBJECT_COPY_SYMMETRIC && !map_share))) { /* * If we are destroying the source, and the object @@ -10844,7 +10895,6 @@ vm_map_copyin_internal( &VME_OBJECT(new_entry)); VME_OFFSET_SET(new_entry, 0); new_entry->needs_copy = FALSE; - } else if (src_object->copy_strategy == MEMORY_OBJECT_COPY_SYMMETRIC && (entry_was_shared || map_share)) { @@ -10864,7 +10914,7 @@ vm_map_copyin_internal( new_entry->needs_copy = TRUE; assert(!new_entry->iokit_acct); assert(new_object->purgable == VM_PURGABLE_DENY); - new_entry->use_pmap = TRUE; + assertf(new_entry->use_pmap, "src_map %p new_entry %p\n", src_map, new_entry); result = KERN_SUCCESS; } else { @@ -10912,6 +10962,8 @@ vm_map_copyin_internal( } vm_object_unlock(new_object); new_object = VM_OBJECT_NULL; + /* no pmap accounting for purgeable objects */ + new_entry->use_pmap = FALSE; } if (result != KERN_SUCCESS && @@ -10955,7 +11007,8 @@ vm_map_copyin_internal( if (result != KERN_MEMORY_RESTART_COPY) { vm_object_deallocate(VME_OBJECT(new_entry)); VME_OBJECT_SET(new_entry, VM_OBJECT_NULL); - assert(!new_entry->iokit_acct); + /* reset accounting state */ + new_entry->iokit_acct = FALSE; new_entry->use_pmap = TRUE; } RETURN(KERN_INVALID_ADDRESS); @@ -11445,6 +11498,7 @@ vm_map_fork_share( VME_OFFSET_SET(old_entry, 0); VME_OBJECT_SET(old_entry, object); old_entry->use_pmap = TRUE; +// assert(!old_entry->needs_copy); } else if (object->copy_strategy != MEMORY_OBJECT_COPY_SYMMETRIC) { @@ -11619,6 +11673,15 @@ vm_map_fork_share( old_entry->is_shared = TRUE; new_entry->is_shared = TRUE; + /* + * We're dealing with a shared mapping, so the resulting mapping + * should inherit some of the original mapping's accounting settings. + * "iokit_acct" should have been cleared in vm_map_entry_copy(). + * "use_pmap" should stay the same as before (if it hasn't been reset + * to TRUE when we cleared "iokit_acct"). + */ + assert(!new_entry->iokit_acct); + /* * If old entry's inheritence is VM_INHERIT_NONE, * the new entry is for corpse fork, remove the @@ -11832,6 +11895,19 @@ vm_map_fork( if (new_entry->is_sub_map) { /* clear address space specifics */ new_entry->use_pmap = FALSE; + } else { + /* + * We're dealing with a copy-on-write operation, + * so the resulting mapping should not inherit + * the original mapping's accounting settings. + * "iokit_acct" should have been cleared in + * vm_map_entry_copy(). + * "use_pmap" should be reset to its default + * (TRUE) so that the new mapping gets + * accounted for in the task's memory footprint. + */ + assert(!new_entry->iokit_acct); + new_entry->use_pmap = TRUE; } if (! vm_object_copy_quickly( @@ -12186,6 +12262,8 @@ vm_map_lookup_locked( submap_entry->vme_start)); VME_OBJECT_SET(submap_entry, sub_object); VME_OFFSET_SET(submap_entry, 0); + assert(!submap_entry->is_sub_map); + assert(submap_entry->use_pmap); } local_start = local_vaddr - (cow_parent_vaddr - old_start); @@ -12477,6 +12555,7 @@ vm_map_lookup_locked( (vm_map_size_t)(entry->vme_end - entry->vme_start))); VME_OFFSET_SET(entry, 0); + assert(entry->use_pmap); vm_map_lock_write_to_read(map); } @@ -12565,10 +12644,6 @@ vm_map_verify( * */ -#if DEVELOPMENT || DEBUG -int vm_region_footprint = 0; -#endif /* DEVELOPMENT || DEBUG */ - kern_return_t vm_map_region_recurse_64( vm_map_t map, @@ -12625,6 +12700,7 @@ vm_map_region_recurse_64( boolean_t look_for_pages; vm_region_submap_short_info_64_t short_info; + boolean_t do_region_footprint; if (map == VM_MAP_NULL) { /* no address space to work on */ @@ -12640,6 +12716,7 @@ vm_map_region_recurse_64( return KERN_INVALID_ARGUMENT; } + do_region_footprint = task_self_region_footprint(); original_count = *count; if (original_count < VM_REGION_SUBMAP_INFO_V0_COUNT_64) { @@ -12829,14 +12906,17 @@ vm_map_region_recurse_64( curr_entry = NULL; } +// LP64todo: all the current tools are 32bit, obviously never worked for 64b +// so probably should be a real 32b ID vs. ptr. +// Current users just check for equality + if (curr_entry == NULL) { /* no VM region contains the address... */ -#if DEVELOPMENT || DEBUG - if (vm_region_footprint && /* we want footprint numbers */ - look_for_pages && /* & we want page counts */ + + if (do_region_footprint && /* we want footprint numbers */ next_entry == NULL && /* & there are no more regions */ /* & we haven't already provided our fake region: */ - user_address == vm_map_last_entry(map)->vme_end) { + user_address <= vm_map_last_entry(map)->vme_end) { ledger_amount_t nonvol, nonvol_compressed; /* * Add a fake memory region to account for @@ -12855,33 +12935,50 @@ vm_map_region_recurse_64( &nonvol_compressed); if (nonvol + nonvol_compressed == 0) { /* no purgeable memory usage to report */ - return KERN_FAILURE; + return KERN_INVALID_ADDRESS; } /* fake region to show nonvolatile footprint */ - submap_info->protection = VM_PROT_DEFAULT; - submap_info->max_protection = VM_PROT_DEFAULT; - submap_info->inheritance = VM_INHERIT_DEFAULT; - submap_info->offset = 0; - submap_info->user_tag = 0; - submap_info->pages_resident = (unsigned int) (nonvol / PAGE_SIZE); - submap_info->pages_shared_now_private = 0; - submap_info->pages_swapped_out = (unsigned int) (nonvol_compressed / PAGE_SIZE); - submap_info->pages_dirtied = submap_info->pages_resident; - submap_info->ref_count = 1; - submap_info->shadow_depth = 0; - submap_info->external_pager = 0; - submap_info->share_mode = SM_PRIVATE; - submap_info->is_submap = 0; - submap_info->behavior = VM_BEHAVIOR_DEFAULT; - submap_info->object_id = 0x11111111; - submap_info->user_wired_count = 0; - submap_info->pages_reusable = 0; + if (look_for_pages) { + submap_info->protection = VM_PROT_DEFAULT; + submap_info->max_protection = VM_PROT_DEFAULT; + submap_info->inheritance = VM_INHERIT_DEFAULT; + submap_info->offset = 0; + submap_info->user_tag = -1; + submap_info->pages_resident = (unsigned int) (nonvol / PAGE_SIZE); + submap_info->pages_shared_now_private = 0; + submap_info->pages_swapped_out = (unsigned int) (nonvol_compressed / PAGE_SIZE); + submap_info->pages_dirtied = submap_info->pages_resident; + submap_info->ref_count = 1; + submap_info->shadow_depth = 0; + submap_info->external_pager = 0; + submap_info->share_mode = SM_PRIVATE; + submap_info->is_submap = 0; + submap_info->behavior = VM_BEHAVIOR_DEFAULT; + submap_info->object_id = INFO_MAKE_FAKE_OBJECT_ID(map, task_ledgers.purgeable_nonvolatile); + submap_info->user_wired_count = 0; + submap_info->pages_reusable = 0; + } else { + short_info->user_tag = -1; + short_info->offset = 0; + short_info->protection = VM_PROT_DEFAULT; + short_info->inheritance = VM_INHERIT_DEFAULT; + short_info->max_protection = VM_PROT_DEFAULT; + short_info->behavior = VM_BEHAVIOR_DEFAULT; + short_info->user_wired_count = 0; + short_info->is_submap = 0; + short_info->object_id = INFO_MAKE_FAKE_OBJECT_ID(map, task_ledgers.purgeable_nonvolatile); + short_info->external_pager = 0; + short_info->shadow_depth = 0; + short_info->share_mode = SM_PRIVATE; + short_info->ref_count = 1; + } *nesting_depth = 0; *size = (vm_map_size_t) (nonvol + nonvol_compressed); - *address = user_address; +// *address = user_address; + *address = vm_map_last_entry(map)->vme_end; return KERN_SUCCESS; } -#endif /* DEVELOPMENT || DEBUG */ + if (next_entry == NULL) { /* ... and no VM region follows it either */ return KERN_INVALID_ADDRESS; @@ -13350,6 +13447,9 @@ vm_map_region_walk( int ref_count; struct vm_object *shadow_object; int shadow_depth; + boolean_t do_region_footprint; + + do_region_footprint = task_self_region_footprint(); if ((VME_OBJECT(entry) == 0) || (entry->is_sub_map) || @@ -13381,53 +13481,60 @@ vm_map_region_walk( for (last_offset = offset + range; offset < last_offset; offset += PAGE_SIZE_64, va += PAGE_SIZE) { -#if DEVELOPMENT || DEBUG - if (vm_region_footprint) { + + if (do_region_footprint) { + int disp; + + disp = 0; + pmap_query_page_info(map->pmap, va, &disp); + if (disp & PMAP_QUERY_PAGE_PRESENT) { + extended->pages_resident++; + if (disp & PMAP_QUERY_PAGE_REUSABLE) { + extended->pages_reusable++; + } else if (!(disp & PMAP_QUERY_PAGE_INTERNAL) || + (disp & PMAP_QUERY_PAGE_ALTACCT)) { + /* alternate accounting */ + } else { + extended->pages_dirtied++; + } + } else if (disp & PMAP_QUERY_PAGE_COMPRESSED) { + if (disp & PMAP_QUERY_PAGE_COMPRESSED_ALTACCT) { + /* alternate accounting */ + } else { + extended->pages_swapped_out++; + } + } + /* deal with alternate accounting */ if (obj->purgable != VM_PURGABLE_DENY) { - /* alternate accounting */ + /* + * Pages from purgeable objects + * will be reported as dirty + * appropriately in an extra + * fake memory region at the end of + * the address space. + */ } else if (entry->iokit_acct) { - /* alternate accounting */ - extended->pages_resident++; + /* + * IOKit mappings are considered + * as fully dirty for footprint's + * sake. + */ extended->pages_dirtied++; - } else { - int disp; - - disp = 0; - pmap_query_page_info(map->pmap, va, &disp); - if (disp & PMAP_QUERY_PAGE_PRESENT) { - extended->pages_resident++; - if (disp & PMAP_QUERY_PAGE_REUSABLE) { - extended->pages_reusable++; - } else if (!(disp & PMAP_QUERY_PAGE_INTERNAL) || - (disp & PMAP_QUERY_PAGE_ALTACCT)) { - /* alternate accounting */ - } else { - extended->pages_dirtied++; - } - } else if (disp & PMAP_QUERY_PAGE_COMPRESSED) { - if (disp & PMAP_QUERY_PAGE_COMPRESSED_ALTACCT) { - /* alternate accounting */ - } else { - extended->pages_swapped_out++; - } - } } continue; } -#endif /* DEVELOPMENT || DEBUG */ + vm_map_region_look_for_page(map, va, obj, offset, ref_count, 0, extended, count); } -#if DEVELOPMENT || DEBUG - if (vm_region_footprint) { + + if (do_region_footprint) { goto collect_object_info; } -#endif /* DEVELOPMENT || DEBUG */ + } else { -#if DEVELOPMENT || DEBUG collect_object_info: -#endif /* DEVELOPMENT || DEBUG */ shadow_object = obj->shadow; shadow_depth = 0; @@ -14681,6 +14788,11 @@ vm_map_entry_insert( assert(insp_entry != (vm_map_entry_t)0); +#if DEVELOPMENT || DEBUG + vm_object_offset_t end_offset = 0; + assertf(!os_add_overflow(end - start, offset, &end_offset), "size 0x%llx, offset 0x%llx caused overflow", (uint64_t)(end - start), offset); +#endif /* DEVELOPMENT || DEBUG */ + new_entry = vm_map_entry_create(map, !map->hdr.entries_pageable); if (VM_MAP_PAGE_SHIFT(map) != PAGE_SHIFT) { @@ -14804,6 +14916,8 @@ vm_map_remap_extract( vm_map_version_t version; boolean_t src_needs_copy; boolean_t new_entry_needs_copy; + vm_map_entry_t saved_src_entry; + boolean_t src_entry_was_wired; assert(map != VM_MAP_NULL); assert(size != 0); @@ -14881,19 +14995,36 @@ vm_map_remap_extract( * Purgeable objects have their own accounting: * no pmap accounting for them. */ - assert(!src_entry->use_pmap); + assertf(!src_entry->use_pmap, + "map=%p src_entry=%p [0x%llx:0x%llx] 0x%x/0x%x %d", + map, + src_entry, + (uint64_t)src_entry->vme_start, + (uint64_t)src_entry->vme_end, + src_entry->protection, + src_entry->max_protection, + VME_ALIAS(src_entry)); } else { /* * Not IOKit or purgeable: * must be accounted by pmap stats. */ - assert(src_entry->use_pmap); + assertf(src_entry->use_pmap, + "map=%p src_entry=%p [0x%llx:0x%llx] 0x%x/0x%x %d", + map, + src_entry, + (uint64_t)src_entry->vme_start, + (uint64_t)src_entry->vme_end, + src_entry->protection, + src_entry->max_protection, + VME_ALIAS(src_entry)); } if (object == VM_OBJECT_NULL) { object = vm_object_allocate(entry_size); VME_OFFSET_SET(src_entry, 0); VME_OBJECT_SET(src_entry, object); + assert(src_entry->use_pmap); } else if (object->copy_strategy != MEMORY_OBJECT_COPY_SYMMETRIC) { /* @@ -14908,6 +15039,7 @@ vm_map_remap_extract( object->vo_size > entry_size)) { VME_OBJECT_SHADOW(src_entry, entry_size); + assert(src_entry->use_pmap); if (!src_entry->needs_copy && (src_entry->protection & VM_PROT_WRITE)) { @@ -14963,7 +15095,19 @@ vm_map_remap_extract( if (new_entry->is_sub_map) { /* clr address space specifics */ new_entry->use_pmap = FALSE; + } else if (copy) { + /* + * We're dealing with a copy-on-write operation, + * so the resulting mapping should not inherit the + * original mapping's accounting settings. + * "use_pmap" should be reset to its default (TRUE) + * so that the new mapping gets accounted for in + * the task's memory footprint. + */ + new_entry->use_pmap = TRUE; } + /* "iokit_acct" was cleared in vm_map_entry_copy() */ + assert(!new_entry->iokit_acct); new_entry->map_aligned = FALSE; @@ -15019,6 +15163,7 @@ vm_map_remap_extract( new_entry->needs_copy = new_entry_needs_copy; new_entry->is_shared = FALSE; + assertf(new_entry->use_pmap, "map %p new_entry %p\n", map, new_entry); /* * Handle copy_on_write semantics. @@ -15056,6 +15201,11 @@ vm_map_remap_extract( } else { new_entry->is_shared = FALSE; + assertf(new_entry->use_pmap, "map %p new_entry %p\n", map, new_entry); + + src_entry_was_wired = (src_entry->wired_count > 0); + saved_src_entry = src_entry; + src_entry = VM_MAP_ENTRY_NULL; /* * The map can be safely unlocked since we @@ -15070,7 +15220,7 @@ vm_map_remap_extract( /* * Perform the copy. */ - if (src_entry->wired_count > 0) { + if (src_entry_was_wired > 0) { vm_object_lock(object); result = vm_object_copy_slowly( object, @@ -15126,12 +15276,16 @@ vm_map_remap_extract( * Retry the lookup and verify that the * same object/offset are still present. */ + saved_src_entry = VM_MAP_ENTRY_NULL; vm_object_deallocate(VME_OBJECT(new_entry)); _vm_map_entry_dispose(map_header, new_entry); if (result == KERN_MEMORY_RESTART_COPY) result = KERN_SUCCESS; continue; } + /* map hasn't changed: src_entry is still valid */ + src_entry = saved_src_entry; + saved_src_entry = VM_MAP_ENTRY_NULL; if (result == KERN_MEMORY_RESTART_COPY) { vm_object_reference(object); @@ -15961,6 +16115,7 @@ vm_map_page_range_info_internal( vm_page_info_basic_t basic_info = 0; vm_map_offset_t offset_in_page = 0, offset_in_object = 0, curr_offset_in_object = 0; vm_map_offset_t start = 0, end = 0, curr_s_offset = 0, curr_e_offset = 0; + boolean_t do_region_footprint; switch (flavor) { case VM_PAGE_INFO_BASIC: @@ -15978,6 +16133,7 @@ vm_map_page_range_info_internal( return KERN_INVALID_ARGUMENT; } + do_region_footprint = task_self_region_footprint(); disposition = 0; ref_count = 0; depth = 0; @@ -16001,6 +16157,58 @@ vm_map_page_range_info_internal( ref_count = 0; depth = 0; + if (do_region_footprint && + curr_s_offset >= vm_map_last_entry(map)->vme_end) { + ledger_amount_t nonvol_compressed; + + /* + * Request for "footprint" info about a page beyond + * the end of address space: this must be for + * the fake region vm_map_region_recurse_64() + * reported to account for non-volatile purgeable + * memory owned by this task. + */ + disposition = 0; + nonvol_compressed = 0; + ledger_get_balance( + map->pmap->ledger, + task_ledgers.purgeable_nonvolatile_compressed, + &nonvol_compressed); + if (curr_s_offset - vm_map_last_entry(map)->vme_end <= + (unsigned) nonvol_compressed) { + /* + * We haven't reported all the "non-volatile + * compressed" pages yet, so report this fake + * page as "compressed". + */ + disposition |= VM_PAGE_QUERY_PAGE_PAGED_OUT; + } else { + /* + * We've reported all the non-volatile + * compressed page but not all the non-volatile + * pages , so report this fake page as + * "resident dirty". + */ + disposition |= VM_PAGE_QUERY_PAGE_PRESENT; + disposition |= VM_PAGE_QUERY_PAGE_DIRTY; + disposition |= VM_PAGE_QUERY_PAGE_REF; + } + switch (flavor) { + case VM_PAGE_INFO_BASIC: + basic_info = (vm_page_info_basic_t) (((uintptr_t) info) + (info_idx * sizeof(struct vm_page_info_basic))); + basic_info->disposition = disposition; + basic_info->ref_count = 1; + basic_info->object_id = INFO_MAKE_FAKE_OBJECT_ID(map, task_ledgers.purgeable_nonvolatile); + basic_info->offset = 0; + basic_info->depth = 0; + + info_idx++; + break; + } + curr_s_offset += PAGE_SIZE; + continue; + } + /* * First, find the map entry covering "curr_s_offset", going down * submaps if necessary. @@ -16129,6 +16337,58 @@ vm_map_page_range_info_internal( continue; } + if (do_region_footprint) { + int pmap_disp; + + disposition = 0; + pmap_disp = 0; + pmap_query_page_info(map->pmap, curr_s_offset, &pmap_disp); + if (map_entry->iokit_acct && + object->internal && + object->purgable == VM_PURGABLE_DENY) { + /* + * Non-purgeable IOKit memory: phys_footprint + * includes the entire virtual mapping. + */ + assertf(!map_entry->use_pmap, "offset 0x%llx map_entry %p", (uint64_t) curr_s_offset, map_entry); + disposition |= VM_PAGE_QUERY_PAGE_PRESENT; + disposition |= VM_PAGE_QUERY_PAGE_DIRTY; + } else if (pmap_disp & (PMAP_QUERY_PAGE_ALTACCT | + PMAP_QUERY_PAGE_COMPRESSED_ALTACCT)) { + /* alternate accounting */ + assertf(!map_entry->use_pmap, "offset 0x%llx map_entry %p", (uint64_t) curr_s_offset, map_entry); + pmap_disp = 0; + } else { + if (pmap_disp & PMAP_QUERY_PAGE_PRESENT) { + assertf(map_entry->use_pmap, "offset 0x%llx map_entry %p", (uint64_t) curr_s_offset, map_entry); + disposition |= VM_PAGE_QUERY_PAGE_PRESENT; + disposition |= VM_PAGE_QUERY_PAGE_REF; + if (pmap_disp & PMAP_QUERY_PAGE_INTERNAL) { + disposition |= VM_PAGE_QUERY_PAGE_DIRTY; + } else { + disposition |= VM_PAGE_QUERY_PAGE_EXTERNAL; + } + } else if (pmap_disp & PMAP_QUERY_PAGE_COMPRESSED) { + assertf(map_entry->use_pmap, "offset 0x%llx map_entry %p", (uint64_t) curr_s_offset, map_entry); + disposition |= VM_PAGE_QUERY_PAGE_PAGED_OUT; + } + } + switch (flavor) { + case VM_PAGE_INFO_BASIC: + basic_info = (vm_page_info_basic_t) (((uintptr_t) info) + (info_idx * sizeof(struct vm_page_info_basic))); + basic_info->disposition = disposition; + basic_info->ref_count = 1; + basic_info->object_id = INFO_MAKE_FAKE_OBJECT_ID(map, task_ledgers.purgeable_nonvolatile); + basic_info->offset = 0; + basic_info->depth = 0; + + info_idx++; + break; + } + curr_s_offset += PAGE_SIZE; + continue; + } + vm_object_reference(object); /* * Shared mode -- so we can allow other readers diff --git a/osfmk/vm/vm_map.h b/osfmk/vm/vm_map.h index f8e1aa623..23592b8e4 100644 --- a/osfmk/vm/vm_map.h +++ b/osfmk/vm/vm_map.h @@ -238,6 +238,7 @@ struct vm_map_links { vm_object_shadow(&__object, &__offset, (length)); \ if (__object != VME_OBJECT((entry))) { \ VME_OBJECT_SET((entry), __object); \ + (entry)->use_pmap = TRUE; \ } \ if (__offset != VME_OFFSET((entry))) { \ VME_OFFSET_SET((entry), __offset); \ @@ -253,6 +254,35 @@ struct vm_map_links { (entry)->vme_offset = __offset | ((alias) & VME_ALIAS_MASK); \ MACRO_END +/* + * FOOTPRINT ACCOUNTING: + * The "memory footprint" is better described in the pmap layer. + * + * At the VM level, these 2 vm_map_entry_t fields are relevant: + * iokit_mapped: + * For an "iokit_mapped" entry, we add the size of the entry to the + * footprint when the entry is entered into the map and we subtract that + * size when the entry is removed. No other accounting should take place. + * "use_pmap" should be FALSE but is not taken into account. + * use_pmap: (only when is_sub_map is FALSE) + * This indicates if we should ask the pmap layer to account for pages + * in this mapping. If FALSE, we expect that another form of accounting + * is being used (e.g. "iokit_mapped" or the explicit accounting of + * non-volatile purgable memory). + * + * So the logic is mostly: + * if entry->is_sub_map == TRUE + * anything in a submap does not count for the footprint + * else if entry->iokit_mapped == TRUE + * footprint includes the entire virtual size of this entry + * else if entry->use_pmap == FALSE + * tell pmap NOT to account for pages being pmap_enter()'d from this + * mapping (i.e. use "alternate accounting") + * else + * pmap will account for pages being pmap_enter()'d from this mapping + * as it sees fit (only if anonymous, etc...) + */ + struct vm_map_entry { struct vm_map_links links; /* links to other entries */ #define vme_prev links.prev @@ -431,7 +461,8 @@ struct _vm_map { /* boolean_t */ map_disallow_data_exec:1, /* Disallow execution from data pages on exec-permissive architectures */ /* boolean_t */ holelistenabled:1, /* boolean_t */ is_nested_map:1, - /* reserved */ pad:23; + /* boolean_t */ map_disallow_new_exec:1, /* Disallow new executable code */ + /* reserved */ pad:22; unsigned int timestamp; /* Version number */ unsigned int color_rr; /* next color (not protected by a lock) */ @@ -1018,6 +1049,19 @@ extern kern_return_t vm_map_set_cache_attr( extern int override_nx(vm_map_t map, uint32_t user_tag); +extern void vm_map_region_top_walk( + vm_map_entry_t entry, + vm_region_top_info_t top); +extern void vm_map_region_walk( + vm_map_t map, + vm_map_offset_t va, + vm_map_entry_t entry, + vm_object_offset_t offset, + vm_object_size_t range, + vm_region_extended_info_t extended, + boolean_t look_for_pages, + mach_msg_type_number_t count); + #endif /* MACH_KERNEL_PRIVATE */ __BEGIN_DECLS @@ -1502,6 +1546,14 @@ extern kern_return_t vm_map_freeze( __END_DECLS +/* + * In some cases, we don't have a real VM object but still want to return a + * unique ID (to avoid a memory region looking like shared memory), so build + * a fake pointer based on the map's ledger and the index of the ledger being + * reported. + */ +#define INFO_MAKE_FAKE_OBJECT_ID(map,ledger_id) ((uint32_t)(uintptr_t)VM_KERNEL_ADDRPERM((int*)((map)->pmap->ledger)+(ledger_id))) + #endif /* KERNEL_PRIVATE */ #endif /* _VM_VM_MAP_H_ */ diff --git a/osfmk/vm/vm_object.c b/osfmk/vm/vm_object.c index a7820e3b0..821929f88 100644 --- a/osfmk/vm/vm_object.c +++ b/osfmk/vm/vm_object.c @@ -542,6 +542,8 @@ vm_object_bootstrap(void) vm_object_template.objq.next = NULL; vm_object_template.objq.prev = NULL; + vm_object_template.task_objq.next = NULL; + vm_object_template.task_objq.prev = NULL; vm_object_template.purgeable_queue_type = PURGEABLE_Q_TYPE_MAX; vm_object_template.purgeable_queue_group = 0; @@ -1008,11 +1010,10 @@ vm_object_cache_remove_locked( vm_object_t object) { assert(object->purgable == VM_PURGABLE_DENY); - assert(object->wired_page_count == 0); - queue_remove(&vm_object_cached_list, object, vm_object_t, objq); - object->objq.next = NULL; - object->objq.prev = NULL; + queue_remove(&vm_object_cached_list, object, vm_object_t, cached_list); + object->cached_list.next = NULL; + object->cached_list.prev = NULL; vm_object_cached_count--; } @@ -1023,7 +1024,8 @@ vm_object_cache_remove( { vm_object_cache_lock_spin(); - if (object->objq.next || object->objq.prev) + if (object->cached_list.next && + object->cached_list.prev) vm_object_cache_remove_locked(object); vm_object_cache_unlock(); @@ -1037,7 +1039,6 @@ vm_object_cache_add( clock_nsec_t nsec; assert(object->purgable == VM_PURGABLE_DENY); - assert(object->wired_page_count == 0); if (object->resident_page_count == 0) return; @@ -1045,8 +1046,9 @@ vm_object_cache_add( vm_object_cache_lock_spin(); - if (object->objq.next == NULL && object->objq.prev == NULL) { - queue_enter(&vm_object_cached_list, object, vm_object_t, objq); + if (object->cached_list.next == NULL && + object->cached_list.prev == NULL) { + queue_enter(&vm_object_cached_list, object, vm_object_t, cached_list); object->vo_cache_ts = sec + EVICT_AGE; object->vo_cache_pages_to_scan = object->resident_page_count; @@ -1110,7 +1112,7 @@ vm_object_cache_evict( while (!queue_end(&vm_object_cached_list, (queue_entry_t)next_obj) && object_cnt++ < max_objects_to_examine) { object = next_obj; - next_obj = (vm_object_t)queue_next(&next_obj->objq); + next_obj = (vm_object_t)queue_next(&next_obj->cached_list); assert(object->purgable == VM_PURGABLE_DENY); assert(object->wired_page_count == 0); @@ -1351,7 +1353,9 @@ vm_object_terminate( object->terminating = TRUE; object->alive = FALSE; - if ( !object->internal && (object->objq.next || object->objq.prev)) + if (!object->internal && + object->cached_list.next && + object->cached_list.prev) vm_object_cache_remove(object); /* @@ -1452,7 +1456,8 @@ vm_object_reap( object->purgable != VM_PURGABLE_DENY) { vm_purgeable_accounting(object, object->purgable, - TRUE); /* disown */ + TRUE, /* disown */ + FALSE); /* task_objq locked? */ } pager = object->pager; @@ -1533,8 +1538,17 @@ vm_object_reap( panic("object %p in unexpected purgeable state 0x%x\n", object, object->purgable); } - assert(object->objq.next == NULL); - assert(object->objq.prev == NULL); + if (object->transposed && + object->cached_list.next != NULL && + object->cached_list.prev == NULL) { + /* + * object->cached_list.next "points" to the + * object that was transposed with this object. + */ + } else { + assert(object->cached_list.next == NULL); + } + assert(object->cached_list.prev == NULL); } if (object->pageout) { @@ -5466,17 +5480,17 @@ vm_object_lock_request( * On entry the object must be locked and it must be * purgeable with no delayed copies pending. */ -void +uint64_t vm_object_purge(vm_object_t object, int flags) { - unsigned int object_page_count = 0; - unsigned int pgcount = 0; + unsigned int object_page_count = 0, pgcount = 0; + uint64_t total_purged_pgcount = 0; boolean_t skipped_object = FALSE; vm_object_lock_assert_exclusive(object); if (object->purgable == VM_PURGABLE_DENY) - return; + return 0; assert(object->copy == VM_OBJECT_NULL); assert(object->copy_strategy == MEMORY_OBJECT_COPY_NONE); @@ -5522,6 +5536,12 @@ vm_object_purge(vm_object_t object, int flags) vm_object_reap_pages(object, REAP_PURGEABLE); + if (object->resident_page_count >= object_page_count) { + total_purged_pgcount = 0; + } else { + total_purged_pgcount = object_page_count - object->resident_page_count; + } + if (object->pager != NULL) { assert(VM_CONFIG_COMPRESSOR_IS_PRESENT); @@ -5575,13 +5595,16 @@ vm_object_purge(vm_object_t object, int flags) vm_object_lock_assert_exclusive(object); + total_purged_pgcount += pgcount; + KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, (MACHDBG_CODE(DBG_MACH_VM, OBJECT_PURGE_ONE)), VM_KERNEL_UNSLIDE_OR_PERM(object), /* purged object */ object_page_count, - pgcount, + total_purged_pgcount, skipped_object, 0); + return total_purged_pgcount; } @@ -5785,7 +5808,8 @@ vm_object_purgable_control( * non-volatile ledgers. */ vm_purgeable_accounting(object, VM_PURGABLE_VOLATILE, - FALSE); + FALSE, /* disown */ + FALSE); /* task_objq locked? */ } break; @@ -5913,8 +5937,10 @@ vm_object_purgable_control( }; vm_purgeable_object_add(object, queue, (*state&VM_VOLATILE_GROUP_MASK)>>VM_VOLATILE_GROUP_SHIFT ); if (old_state == VM_PURGABLE_NONVOLATILE) { - vm_purgeable_accounting(object, VM_PURGABLE_NONVOLATILE, - FALSE); + vm_purgeable_accounting(object, + VM_PURGABLE_NONVOLATILE, + FALSE, /* disown */ + FALSE); /* task_objq locked? */ } assert(queue->debug_count_objects>=0); @@ -5963,8 +5989,10 @@ vm_object_purgable_control( * "non-volatile" and now need to be accounted as * "volatile". */ - vm_purgeable_accounting(object, VM_PURGABLE_NONVOLATILE, - FALSE); + vm_purgeable_accounting(object, + VM_PURGABLE_NONVOLATILE, + FALSE, /* disown */ + FALSE); /* task_objq locked? */ /* * Set to VM_PURGABLE_EMPTY because the pages are no * longer accounted in the "non-volatile" ledger diff --git a/osfmk/vm/vm_object.h b/osfmk/vm/vm_object.h index 1ef57792d..247437571 100644 --- a/osfmk/vm/vm_object.h +++ b/osfmk/vm/vm_object.h @@ -385,6 +385,7 @@ struct vm_object { #endif /* VM_PIP_DEBUG */ queue_chain_t objq; /* object queue - currently used for purgable queues */ + queue_chain_t task_objq; /* objects owned by task - protected by task lock */ #if DEBUG void *purgeable_owner_bt[16]; @@ -671,7 +672,7 @@ __private_extern__ void vm_object_reuse_pages( vm_object_offset_t end_offset, boolean_t allow_partial_reuse); -__private_extern__ void vm_object_purge( +__private_extern__ uint64_t vm_object_purge( vm_object_t object, int flags); diff --git a/osfmk/vm/vm_pageout.c b/osfmk/vm/vm_pageout.c index ada634f90..20eac579d 100644 --- a/osfmk/vm/vm_pageout.c +++ b/osfmk/vm/vm_pageout.c @@ -3236,14 +3236,14 @@ vm_pageout_scan(void) VM_DEBUG_CONSTANT_EVENT(vm_pageout_jetsam, VM_PAGEOUT_JETSAM, DBG_FUNC_START, vm_page_active_count, vm_page_inactive_count, vm_page_free_count, vm_page_free_count); - /* Kill first suitable process */ - if (memorystatus_kill_on_VM_page_shortage(FALSE) == FALSE) { - panic("vm_pageout_scan: Jetsam request failed\n"); + /* Kill first suitable process. If this call returned FALSE, we might have simply purged a process instead. */ + if (memorystatus_kill_on_VM_page_shortage(FALSE) == TRUE) { + vm_pageout_inactive_external_forced_jetsam_count++; } - VM_DEBUG_CONSTANT_EVENT(vm_pageout_jetsam, VM_PAGEOUT_JETSAM, DBG_FUNC_END, 0, 0, 0, 0); + VM_DEBUG_CONSTANT_EVENT(vm_pageout_jetsam, VM_PAGEOUT_JETSAM, DBG_FUNC_END, + vm_page_active_count, vm_page_inactive_count, vm_page_free_count, vm_page_free_count); - vm_pageout_inactive_external_forced_jetsam_count++; vm_page_lock_queues(); delayed_unlock = 1; } @@ -5898,6 +5898,7 @@ vm_map_create_upl( (entry->vme_end - entry->vme_start))); VME_OFFSET_SET(entry, 0); + assert(entry->use_pmap); vm_map_lock_write_to_read(map); } diff --git a/osfmk/vm/vm_protos.h b/osfmk/vm/vm_protos.h index de4756f67..54781267b 100644 --- a/osfmk/vm/vm_protos.h +++ b/osfmk/vm/vm_protos.h @@ -109,6 +109,12 @@ extern kern_return_t vm_map_purgable_control( vm_purgable_t control, int *state); +extern kern_return_t +vnode_pager_get_object_vnode( + memory_object_t mem_obj, + uintptr_t * vnodeaddr, + uint32_t * vid); + #if CONFIG_COREDUMP extern boolean_t coredumpok(vm_map_t map, vm_offset_t va); #endif diff --git a/osfmk/vm/vm_purgeable.c b/osfmk/vm/vm_purgeable.c index a58b75001..84abed964 100644 --- a/osfmk/vm/vm_purgeable.c +++ b/osfmk/vm/vm_purgeable.c @@ -40,6 +40,20 @@ #include +/* + * LOCK ORDERING for task-owned purgeable objects + * + * Whenever we need to hold multiple locks while adding to, removing from, + * or scanning a task's task_objq list of VM objects it owns, locks should + * be taken in this order: + * + * VM object ==> vm_purgeable_queue_lock ==> owner_task->task_objq_lock + * + * If one needs to acquire the VM object lock after any of the other 2 locks, + * one needs to use vm_object_lock_try() and, if that fails, release the + * other locks and retake them all in the correct order. + */ + extern vm_pressure_level_t memorystatus_vm_pressure_level; struct token { @@ -1249,63 +1263,11 @@ vm_purgeable_account( } #endif /* DEVELOPMENT || DEBUG */ -static void -vm_purgeable_volatile_queue_disown( - purgeable_q_t queue, - int group, - task_t task) -{ - vm_object_t object; - int collisions; - - collisions = 0; - -again: - LCK_MTX_ASSERT(&vm_purgeable_queue_lock, LCK_MTX_ASSERT_OWNED); - - for (object = (vm_object_t) queue_first(&queue->objq[group]); - !queue_end(&queue->objq[group], (queue_entry_t) object); - object = (vm_object_t) queue_next(&object->objq)) { -#if MACH_ASSERT - /* - * Sanity check: let's scan the entire queues to - * make sure we don't leave any purgeable objects - * pointing back at a dead task. If the counters - * are off, we would fail to assert that they go - * back to 0 after disowning is done. - */ -#else /* MACH_ASSERT */ - if (task->task_volatile_objects == 0) { - /* no more volatile objects owned by "task" */ - break; - } -#endif /* MACH_ASSERT */ - if (object->vo_purgeable_owner == task) { - if (! vm_object_lock_try(object)) { - lck_mtx_unlock(&vm_purgeable_queue_lock); - mutex_pause(collisions++); - lck_mtx_lock(&vm_purgeable_queue_lock); - goto again; - } - assert(object->purgable == VM_PURGABLE_VOLATILE); - if (object->vo_purgeable_owner == task) { - vm_purgeable_accounting(object, - object->purgable, - TRUE); /* disown */ - assert(object->vo_purgeable_owner == NULL); - } - vm_object_unlock(object); - } - } -} - void vm_purgeable_disown( task_t task) { - purgeable_q_t volatile_q; - int group; - queue_head_t *nonvolatile_q; + vm_object_t next_object; vm_object_t object; int collisions; @@ -1313,8 +1275,6 @@ vm_purgeable_disown( return; } - task->task_purgeable_disowning = TRUE; - /* * Scan the purgeable objects queues for objects owned by "task". * This has to be done "atomically" under the "vm_purgeable_queue" @@ -1335,73 +1295,55 @@ vm_purgeable_disown( assert(task->task_nonvolatile_objects == 0); return; } + lck_mtx_lock(&vm_purgeable_queue_lock); + task_objq_lock(task); - nonvolatile_q = &purgeable_nonvolatile_queue; - for (object = (vm_object_t) queue_first(nonvolatile_q); - !queue_end(nonvolatile_q, (queue_entry_t) object); - object = (vm_object_t) queue_next(&object->objq)) { -#if MACH_ASSERT - /* - * Sanity check: let's scan the entire queues to - * make sure we don't leave any purgeable objects - * pointing back at a dead task. If the counters - * are off, we would fail to assert that they go - * back to 0 after disowning is done. - */ -#else /* MACH_ASSERT */ - if (task->task_nonvolatile_objects == 0) { - /* no more non-volatile objects owned by "task" */ + task->task_purgeable_disowning = TRUE; + + for (object = (vm_object_t) queue_first(&task->task_objq); + !queue_end(&task->task_objq, (queue_entry_t) object); + object = next_object) { + if (task->task_nonvolatile_objects == 0 && + task->task_volatile_objects == 0) { + /* no more purgeable objects owned by "task" */ break; } -#endif /* MACH_ASSERT */ + + next_object = (vm_object_t) queue_next(&object->task_objq); + if (object->purgable == VM_PURGABLE_DENY) { + /* not a purgeable object: skip */ + continue; + } + #if DEBUG assert(object->vo_purgeable_volatilizer == NULL); #endif /* DEBUG */ - if (object->vo_purgeable_owner == task) { - if (!vm_object_lock_try(object)) { - lck_mtx_unlock(&vm_purgeable_queue_lock); - mutex_pause(collisions++); - goto again; - } - if (object->vo_purgeable_owner == task) { - vm_purgeable_accounting(object, - object->purgable, - TRUE); /* disown */ - assert(object->vo_purgeable_owner == NULL); - } - vm_object_unlock(object); + assert(object->vo_purgeable_owner == task); + if (!vm_object_lock_try(object)) { + lck_mtx_unlock(&vm_purgeable_queue_lock); + task_objq_unlock(task); + mutex_pause(collisions++); + goto again; } + vm_purgeable_accounting(object, + object->purgable, + TRUE, /* disown */ + TRUE);/* task_objq_lock is locked */ + assert(object->vo_purgeable_owner == NULL); + vm_object_unlock(object); } - lck_mtx_yield(&vm_purgeable_queue_lock); - - /* - * Scan volatile queues for objects owned by "task". - */ - - volatile_q = &purgeable_queues[PURGEABLE_Q_TYPE_OBSOLETE]; - vm_purgeable_volatile_queue_disown(volatile_q, 0, task); - lck_mtx_yield(&vm_purgeable_queue_lock); - - volatile_q = &purgeable_queues[PURGEABLE_Q_TYPE_FIFO]; - for (group = 0; group < NUM_VOLATILE_GROUPS; group++) { - vm_purgeable_volatile_queue_disown(volatile_q, group, task); - lck_mtx_yield(&vm_purgeable_queue_lock); - } - - volatile_q = &purgeable_queues[PURGEABLE_Q_TYPE_LIFO]; - for (group = 0; group < NUM_VOLATILE_GROUPS; group++) { - vm_purgeable_volatile_queue_disown(volatile_q, group, task); - lck_mtx_yield(&vm_purgeable_queue_lock); - } - - if (task->task_volatile_objects != 0 || - task->task_nonvolatile_objects != 0) { - /* some purgeable objects sneaked into a queue: find them */ - lck_mtx_unlock(&vm_purgeable_queue_lock); - mutex_pause(collisions++); - goto again; + if (__improbable(task->task_volatile_objects != 0 || + task->task_nonvolatile_objects != 0)) { + panic("%s(%p): volatile=%d nonvolatile=%d q=%p q_first=%p q_last=%p", + __FUNCTION__, + task, + task->task_volatile_objects, + task->task_nonvolatile_objects, + &task->task_objq, + queue_first(&task->task_objq), + queue_last(&task->task_objq)); } /* there shouldn't be any purgeable objects owned by task now */ @@ -1413,34 +1355,31 @@ vm_purgeable_disown( task->task_purgeable_disowned = TRUE; lck_mtx_unlock(&vm_purgeable_queue_lock); + task_objq_unlock(task); } -#if notyet -static int +static uint64_t vm_purgeable_queue_purge_task_owned( purgeable_q_t queue, int group, task_t task) { - vm_object_t object; - int num_objects; - int collisions; - int num_objects_purged; + vm_object_t object = VM_OBJECT_NULL; + int collisions = 0; + uint64_t num_pages_purged = 0; - num_objects_purged = 0; + num_pages_purged = 0; collisions = 0; look_again: lck_mtx_lock(&vm_purgeable_queue_lock); - num_objects = 0; for (object = (vm_object_t) queue_first(&queue->objq[group]); !queue_end(&queue->objq[group], (queue_entry_t) object); object = (vm_object_t) queue_next(&object->objq)) { - if (object->vo_purgeable_owner != task && - object->vo_purgeable_owner != NULL) { + if (object->vo_purgeable_owner != task) { continue; } @@ -1459,6 +1398,8 @@ vm_purgeable_queue_purge_task_owned( vm_object_t, objq); object->objq.next = NULL; object->objq.prev = NULL; + object->purgeable_queue_type = PURGEABLE_Q_TYPE_MAX; + object->purgeable_queue_group = 0; /* one less volatile object for this object's owner */ assert(object->vo_purgeable_owner == task); vm_purgeable_volatile_owner_update(task, -1); @@ -1486,11 +1427,11 @@ vm_purgeable_queue_purge_task_owned( } /* purge the object */ - (void) vm_object_purge(object, 0); + num_pages_purged += vm_object_purge(object, 0); + assert(object->purgable == VM_PURGABLE_EMPTY); /* no change for purgeable accounting */ vm_object_unlock(object); - num_objects_purged++; /* we unlocked the purgeable queues, so start over */ goto look_again; @@ -1498,39 +1439,38 @@ vm_purgeable_queue_purge_task_owned( lck_mtx_unlock(&vm_purgeable_queue_lock); - return num_objects_purged; + return num_pages_purged; } -int +uint64_t vm_purgeable_purge_task_owned( task_t task) { - purgeable_q_t queue; - int group; - int num_objects_purged; + purgeable_q_t queue = NULL; + int group = 0; + uint64_t num_pages_purged = 0; - num_objects_purged = 0; + num_pages_purged = 0; queue = &purgeable_queues[PURGEABLE_Q_TYPE_OBSOLETE]; - num_objects_purged += vm_purgeable_queue_purge_task_owned(queue, + num_pages_purged += vm_purgeable_queue_purge_task_owned(queue, 0, task); queue = &purgeable_queues[PURGEABLE_Q_TYPE_FIFO]; for (group = 0; group < NUM_VOLATILE_GROUPS; group++) - num_objects_purged += vm_purgeable_queue_purge_task_owned(queue, + num_pages_purged += vm_purgeable_queue_purge_task_owned(queue, group, task); queue = &purgeable_queues[PURGEABLE_Q_TYPE_LIFO]; for (group = 0; group < NUM_VOLATILE_GROUPS; group++) - num_objects_purged += vm_purgeable_queue_purge_task_owned(queue, + num_pages_purged += vm_purgeable_queue_purge_task_owned(queue, group, task); - return num_objects_purged; + return num_pages_purged; } -#endif void vm_purgeable_nonvolatile_enqueue( @@ -1556,6 +1496,11 @@ vm_purgeable_nonvolatile_enqueue( #if DEBUG object->vo_purgeable_volatilizer = NULL; #endif /* DEBUG */ + if (owner != NULL) { + task_objq_lock(owner); + queue_enter(&owner->task_objq, object, vm_object_t, task_objq); + task_objq_unlock(owner); + } #if DEBUG OSBacktrace(&object->purgeable_owner_bt[0], 16); @@ -1606,7 +1551,8 @@ vm_purgeable_nonvolatile_dequeue( */ vm_purgeable_accounting(object, object->purgable, - TRUE); /* disown */ + TRUE, /* disown */ + FALSE); /* is task_objq locked? */ } lck_mtx_lock(&vm_purgeable_queue_lock); @@ -1628,7 +1574,8 @@ void vm_purgeable_accounting( vm_object_t object, vm_purgable_t old_state, - boolean_t disown) + boolean_t disown, + boolean_t task_objq_locked) { task_t owner; int resident_page_count; @@ -1693,6 +1640,15 @@ vm_purgeable_accounting( vm_purgeable_volatile_owner_update(owner, -1); } /* no more accounting for this dead object */ + owner = object->vo_purgeable_owner; + if (! task_objq_locked) { + task_objq_lock(owner); + } + task_objq_lock_assert_owned(owner); + queue_remove(&owner->task_objq, object, vm_object_t, task_objq); + if (! task_objq_locked) { + task_objq_unlock(owner); + } object->vo_purgeable_owner = NULL; #if DEBUG object->vo_purgeable_volatilizer = NULL; @@ -1748,6 +1704,14 @@ vm_purgeable_accounting( } vm_purgeable_nonvolatile_owner_update(owner, -1); /* no more accounting for this dead object */ + if (! task_objq_locked) { + task_objq_lock(owner); + } + task_objq_lock_assert_owned(owner); + queue_remove(&owner->task_objq, object, vm_object_t, task_objq); + if (! task_objq_locked) { + task_objq_unlock(owner); + } object->vo_purgeable_owner = NULL; #if DEBUG object->vo_purgeable_volatilizer = NULL; diff --git a/osfmk/vm/vm_purgeable_internal.h b/osfmk/vm/vm_purgeable_internal.h index c982a6307..010c2ee22 100644 --- a/osfmk/vm/vm_purgeable_internal.h +++ b/osfmk/vm/vm_purgeable_internal.h @@ -119,12 +119,13 @@ void vm_purgeable_stats(vm_purgeable_info_t info, task_t target_task); kern_return_t vm_purgeable_account(task_t task, pvm_account_info_t acnt_info); #endif /* DEVELOPMENT || DEBUG */ -int vm_purgeable_purge_task_owned(task_t task); +uint64_t vm_purgeable_purge_task_owned(task_t task); void vm_purgeable_nonvolatile_enqueue(vm_object_t object, task_t task); void vm_purgeable_nonvolatile_dequeue(vm_object_t object); void vm_purgeable_accounting(vm_object_t object, vm_purgable_t old_state, - boolean_t disown); + boolean_t disown, + boolean_t task_objq_locked); void vm_purgeable_compressed_update(vm_object_t object, int delta); diff --git a/osfmk/vm/vm_user.c b/osfmk/vm/vm_user.c index 2f9bdc101..f199dd4fe 100644 --- a/osfmk/vm/vm_user.c +++ b/osfmk/vm/vm_user.c @@ -2912,6 +2912,7 @@ mach_make_memory_entry_64( (VME_OFFSET(next_entry->vme_prev) + (next_entry->vme_prev->vme_end - next_entry->vme_prev->vme_start))); + next_entry->use_pmap = TRUE; next_entry->needs_copy = FALSE; } else { panic("mach_make_memory_entry_64:" @@ -3248,6 +3249,20 @@ task_wire( return(KERN_SUCCESS); } +kern_return_t +vm_map_exec_lockdown( + vm_map_t map) +{ + if (map == VM_MAP_NULL) + return(KERN_INVALID_ARGUMENT); + + vm_map_lock(map); + map->map_disallow_new_exec = TRUE; + vm_map_unlock(map); + + return(KERN_SUCCESS); +} + __private_extern__ kern_return_t mach_memory_entry_allocate( vm_named_entry_t *user_entry_p, diff --git a/osfmk/x86_64/bcopy.s b/osfmk/x86_64/bcopy.s index 8cd909bbb..3ed02246f 100644 --- a/osfmk/x86_64/bcopy.s +++ b/osfmk/x86_64/bcopy.s @@ -63,7 +63,7 @@ /* * Note: memcpy does not support overlapping copies */ - /* TODO: movsb */ + ENTRY(memcpy) movq %rdi, %rax /* return destination */ movq %rdx,%rcx diff --git a/osfmk/x86_64/idt64.s b/osfmk/x86_64/idt64.s index 13f3f0218..0996137ba 100644 --- a/osfmk/x86_64/idt64.s +++ b/osfmk/x86_64/idt64.s @@ -237,13 +237,33 @@ Entry(idt64_mc) * This may or may not be fatal but extreme care is required * because it may fall when control was already in another trampoline. * - * We get here on IST2 stack which is used for NMIs only. + * We get here on IST2 stack which is used exclusively for NMIs. + * Machine checks, doublefaults and similar use IST1 */ Entry(idt64_nmi) - push %rax /* save RAX to ISF64_ERR */ - push %rcx /* save RCX to ISF64_TRAPFN */ - push %rdx /* save RDX to ISF64_TRAPNO */ - jmp L_dispatch + /* Synthesize common interrupt stack frame */ + pushq $0 + pushq $(HNDL_ALLINTRS) + pushq $(T_NMI) + /* Spill prior to RDMSR */ + push %rax + push %rcx + push %rdx + mov $(MSR_IA32_GS_BASE), %ecx + rdmsr /* Check contents of GSBASE MSR */ + test $0x80000000, %edx /* MSB set? Already swapped to kernel's */ + jnz 44f + swapgs /* Either direct from user or within trampolines */ +44: + pop %rdx + pop %rcx + + leaq EXT(idt64_hndl_table0)(%rip), %rax + mov 16(%rax), %rax /* Offset of per-CPU shadow */ + mov %gs:CPU_KERNEL_CR3(%rax), %rax + mov %rax, %cr3 /* Unconditionally switch to primary kernel pagetables */ + leaq EXT(idt64_hndl_table0)(%rip), %rax + jmp *(%rax) Entry(idt64_double_fault) pushq $(HNDL_DOUBLE_FAULT) @@ -474,6 +494,17 @@ L_dispatch_64bit: mov %r13, R64_R13(%r15) mov %r14, R64_R14(%r15) + /* Zero unused GPRs. BX/DX/SI are clobbered elsewhere across the exception handler, and are skipped. */ + xor %ecx, %ecx + xor %edi, %edi + xor %r8, %r8 + xor %r9, %r9 + xor %r10, %r10 + xor %r11, %r11 + xor %r12, %r12 + xor %r13, %r13 + xor %r14, %r14 + /* cr2 is significant only for page-faults */ mov %cr2, %rax mov %rax, R64_CR2(%r15) @@ -528,6 +559,16 @@ L_dispatch_U32: /* 32-bit user task */ /* Unconditionally save cr2; only meaningful on page faults */ mov %cr2, %rax mov %eax, R32_CR2(%r15) + /* Zero unused GPRs. BX/DX/SI/R15 are clobbered elsewhere across the exception handler, and are skipped. */ + xor %ecx, %ecx + xor %edi, %edi + xor %r8, %r8 + xor %r9, %r9 + xor %r10, %r10 + xor %r11, %r11 + xor %r12, %r12 + xor %r13, %r13 + xor %r14, %r14 /* * Copy registers already saved in the machine state @@ -606,6 +647,13 @@ L_common_dispatch: 5: incl %gs:hwIntCnt(,%ebx,4) // Bump the trap/intr count /* Dispatch the designated handler */ + cmp EXT(dblmap_base)(%rip), %rsp + jb 66f + cmp EXT(dblmap_max)(%rip), %rsp + jge 66f + subq EXT(dblmap_dist)(%rip), %rsp + subq EXT(dblmap_dist)(%rip), %r15 +66: leaq EXT(idt64_hndl_table1)(%rip), %rax jmp *(%rax, %rdx, 8) @@ -749,6 +797,7 @@ L_32bit_return: mov %r15, %rsp /* Set the PCB as the stack */ swapgs + /* Zero 64-bit-exclusive GPRs to prevent data leaks */ xor %r8, %r8 xor %r9, %r9 xor %r10, %r10 @@ -1510,13 +1559,9 @@ Entry(hndl_diag_scall64) /* TODO assert at all 'C' entry points that we're never operating on the fault stack's alias mapping */ Entry(hndl_machine_check) /* Adjust SP and savearea to their canonical, non-aliased addresses */ - subq EXT(dblmap_dist)(%rip), %rsp - subq EXT(dblmap_dist)(%rip), %r15 CCALL1(panic_machine_check64, %r15) hlt Entry(hndl_double_fault) - subq EXT(dblmap_dist)(%rip), %rsp - subq EXT(dblmap_dist)(%rip), %r15 CCALL1(panic_double_fault64, %r15) hlt diff --git a/osfmk/x86_64/kpc_x86.c b/osfmk/x86_64/kpc_x86.c index 4da5d9809..a34b77fb3 100644 --- a/osfmk/x86_64/kpc_x86.c +++ b/osfmk/x86_64/kpc_x86.c @@ -43,10 +43,6 @@ #include #include -#include - - - /* Fixed counter mask -- three counters, each with OS and USER */ #define IA32_FIXED_CTR_ENABLE_ALL_CTRS_ALL_RINGS (0x333) #define IA32_FIXED_CTR_ENABLE_ALL_PMI (0x888) diff --git a/osfmk/x86_64/lowglobals.h b/osfmk/x86_64/lowglobals.h index cde29d955..4ed3792b8 100644 --- a/osfmk/x86_64/lowglobals.h +++ b/osfmk/x86_64/lowglobals.h @@ -53,7 +53,7 @@ typedef struct lowglo { uint64_t lgZero; /* 0xffffff8000002008 Double constant 0 */ uint64_t lgStext; /* 0xffffff8000002010 Start of kernel text */ uint64_t lgRsv018; /* 0xffffff8000002018 Reserved */ - uint64_t lgCHUDXNUfnStart; /* 0xffffff8000002020 CHUD XNU function glue table */ + uint64_t lgRsv020; /* 0xffffff8000002020 Reserved */ uint64_t lgRsv028; /* 0xffffff8000002028 Reserved */ uint64_t lgVersion; /* 0xffffff8000002030 Pointer to kernel version string */ uint64_t lgRsv038[280]; /* 0xffffff8000002038 Reserved */ diff --git a/osfmk/x86_64/lowmem_vectors.c b/osfmk/x86_64/lowmem_vectors.c index 190edafc1..09bd405e4 100644 --- a/osfmk/x86_64/lowmem_vectors.c +++ b/osfmk/x86_64/lowmem_vectors.c @@ -76,8 +76,6 @@ lowglo lowGlo __attribute__ ((aligned(PAGE_SIZE))) = { .lgVerCode = { 'C','a','t','f','i','s','h',' ' }, - .lgCHUDXNUfnStart = 0, - .lgVersion = (uint64_t) &version, .lgKmodptr = (uint64_t) &kmod, diff --git a/osfmk/x86_64/pmap.c b/osfmk/x86_64/pmap.c index ce64b82db..852b7618d 100644 --- a/osfmk/x86_64/pmap.c +++ b/osfmk/x86_64/pmap.c @@ -331,6 +331,7 @@ pmap_cpu_init(void) * Initialize the per-cpu, TLB-related fields. */ cdp->cpu_kernel_cr3 = kernel_pmap->pm_cr3; + cpu_shadowp(cdp->cpu_number)->cpu_kernel_cr3 = cdp->cpu_kernel_cr3; cdp->cpu_active_cr3 = kernel_pmap->pm_cr3; cdp->cpu_tlb_invalid = FALSE; cdp->cpu_task_map = TASK_MAP_64BIT; @@ -421,7 +422,7 @@ pmap_bootstrap( pmap_pcid_initialize_kernel(kernel_pmap); - current_cpu_datap()->cpu_kernel_cr3 = (addr64_t) kernel_pmap->pm_cr3; + current_cpu_datap()->cpu_kernel_cr3 = cpu_shadowp(cpu_number())->cpu_kernel_cr3 = (addr64_t) kernel_pmap->pm_cr3; nkpt = NKPT; OSAddAtomic(NKPT, &inuse_ptepages_count); @@ -2518,7 +2519,7 @@ pmap_flush( cpus_to_signal &= ~cpu_bit; - if (!cpu_datap(cpu)->cpu_running) + if (!cpu_is_running(cpu)) continue; if (pfc->pfc_invalid_global & cpu_bit) @@ -2563,7 +2564,7 @@ pmap_flush( * as appropriate in the PCID case. */ if ((cpus_to_respond & cpu_bit) != 0) { - if (!cpu_datap(cpu)->cpu_running || + if (!cpu_is_running(cpu) || cpu_datap(cpu)->cpu_tlb_invalid == FALSE || !CPU_CR3_IS_ACTIVE(cpu)) { cpus_to_respond &= ~cpu_bit; @@ -2678,7 +2679,7 @@ pmap_flush_tlbs(pmap_t pmap, vm_map_offset_t startv, vm_map_offset_t endv, int o mfence(); } for (cpu = 0, cpu_bit = 1; cpu < real_ncpus; cpu++, cpu_bit <<= 1) { - if (!cpu_datap(cpu)->cpu_running) + if (!cpu_is_running(cpu)) continue; uint64_t cpu_active_cr3 = CPU_GET_ACTIVE_CR3(cpu); uint64_t cpu_task_cr3 = CPU_GET_TASK_CR3(cpu); @@ -2764,7 +2765,7 @@ pmap_flush_tlbs(pmap_t pmap, vm_map_offset_t startv, vm_map_offset_t endv, int o * as appropriate in the PCID case. */ if ((cpus_to_respond & cpu_bit) != 0) { - if (!cpu_datap(cpu)->cpu_running || + if (!cpu_is_running(cpu) || cpu_datap(cpu)->cpu_tlb_invalid == FALSE || !CPU_CR3_IS_ACTIVE(cpu)) { cpus_to_respond &= ~cpu_bit; diff --git a/pexpert/arm/pe_consistent_debug.c b/pexpert/arm/pe_consistent_debug.c index 103a1bb90..28732b8b5 100644 --- a/pexpert/arm/pe_consistent_debug.c +++ b/pexpert/arm/pe_consistent_debug.c @@ -1,12 +1,29 @@ /* - * Copyright (C) 2011-2013 Apple Inc. All rights reserved. + * Copyright (c) 2011-2018 Apple Inc. All rights reserved. * - * This document is the property of Apple Inc. - * It is considered confidential and proprietary. + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * - * This document may not be reproduced or transmitted in any form, - * in whole or in part, without the express written permission of - * Apple Inc. + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ #include diff --git a/pexpert/arm/pe_serial.c b/pexpert/arm/pe_serial.c index ff4a301e2..6b9000117 100644 --- a/pexpert/arm/pe_serial.c +++ b/pexpert/arm/pe_serial.c @@ -644,10 +644,9 @@ static void dockchannel_uart_init(void) // Setup DRAIN timer rDOCKCHANNELS_DEV_DRAIN_CFG(DOCKCHANNEL_UART_CHANNEL) = max_dockchannel_drain_period; - // Drain timer doesnt get loaded with value from drain period register if fifo - // is already full. Drop a character from the fifo. - // Refer https://seg-docs.ecs.apple.com/projects/cayman//release/specs/Apple/DockChannels/DockChannels_Specification.pdf - // Chapter 8 for more details. + // Drain timer doesn't get loaded with value from drain period register if fifo + // is already full. Drop a character from the fifo. See chapter 8 of the Cayman + // DockChannels specification for more details. rDOCKCHANNELS_DOCK_RDATA1(DOCKCHANNEL_UART_CHANNEL); } diff --git a/pexpert/i386/pe_serial.c b/pexpert/i386/pe_serial.c index 91a10f867..94818a614 100644 --- a/pexpert/i386/pe_serial.c +++ b/pexpert/i386/pe_serial.c @@ -48,6 +48,12 @@ static struct pe_serial_functions *gPESF; static int uart_initted = 0; /* 1 if init'ed */ +static unsigned int legacy_uart_enabled = 0; /* 1 Legacy IO based UART is supported on platform */ + +static boolean_t lpss_uart_supported = 0; /* 1 if LPSS UART is supported on platform */ +static unsigned int lpss_uart_enabled = 0; /* 1 if it is LPSS UART is in D0 state */ +static void lpss_uart_re_init (void); + #define DEFAULT_UART_BAUD_RATE 115200 static unsigned uart_baud_rate = DEFAULT_UART_BAUD_RATE; @@ -103,6 +109,11 @@ enum { UART_LSR_THRE = 0x20 }; +enum { + UART_CLK_125M_1 = 0x60002, + UART_CLK_125M_2 = 0x80060003, +}; + static int legacy_uart_probe( void ) { @@ -207,8 +218,9 @@ static struct pe_serial_functions legacy_uart_serial_functions = { // MMIO UART (using PCH LPSS UART2) // ============================================================================= -#define MMIO_UART2_BASE_LEGACY 0xFE034000 -#define MMIO_UART2_BASE 0xFE036000 +#define MMIO_UART2_BASE_LEGACY 0xFE034000 /* Legacy MMIO Config space */ +#define MMIO_UART2_BASE 0xFE036000 /* MMIO Config space */ +#define PCI_UART2 0xFE037000 /* PCI Config Space */ #define MMIO_WRITE(r, v) ml_phys_write_word(mmio_uart_base + MMIO_UART_##r, v) #define MMIO_READ(r) ml_phys_read_word(mmio_uart_base + MMIO_UART_##r) @@ -223,7 +235,9 @@ enum { MMIO_UART_LCR = 0xc, /* line control register */ MMIO_UART_MCR = 0x10, /* modem control register */ MMIO_UART_LSR = 0x14, /* line status register */ - MMIO_UART_SCR = 0x1c /* scratch register */ + MMIO_UART_SCR = 0x1c, /* scratch register */ + MMIO_UART_CLK = 0x200, /* clocks register */ + MMIO_UART_RST = 0x204 /* Reset register */ }; static vm_offset_t mmio_uart_base = 0; @@ -235,7 +249,6 @@ mmio_uart_present( void ) if (MMIO_READ(SCR) != 0x5a) return 0; MMIO_WRITE( SCR, 0xa5 ); if (MMIO_READ(SCR) != 0xa5) return 0; - return 1; } @@ -348,6 +361,63 @@ mmio_uart_rr0( void ) return (lsr & UART_LSR_DR); } +void lpss_uart_enable( boolean_t on_off ) +{ + unsigned int pmcs_reg; + + if (!lpss_uart_supported) { + return; + } + + pmcs_reg = ml_phys_read_byte (PCI_UART2 + 0x84); + if (on_off == FALSE) { + pmcs_reg |= 0x03; + lpss_uart_enabled = 0; + } else { + pmcs_reg &= ~(0x03); + } + + ml_phys_write_byte (PCI_UART2 + 0x84, pmcs_reg); + pmcs_reg = ml_phys_read_byte (PCI_UART2 + 0x84); + + if (on_off == TRUE) { + lpss_uart_re_init(); + lpss_uart_enabled = 1; + } +} + +static void lpss_uart_re_init( void ) +{ + uint32_t register_read; + + MMIO_WRITE (RST, 0x7); /* LPSS UART2 controller out ot reset */ + register_read = MMIO_READ (RST); + + MMIO_WRITE (LCR, UART_LCR_DLAB); /* Set DLAB bit to enable reading/writing of DLL, DLH */ + register_read = MMIO_READ (LCR); + + MMIO_WRITE (DLL, 1); /* Divisor Latch Low Register */ + register_read = MMIO_READ (DLL); + + MMIO_WRITE (DLM, 0); /* Divisor Latch High Register */ + register_read = MMIO_READ (DLM); + + MMIO_WRITE (FCR, 1); /* Enable FIFO */ + register_read = MMIO_READ (FCR); + + MMIO_WRITE (LCR, UART_LCR_8BITS); /* Set 8 bits, clear DLAB */ + register_read = MMIO_READ (LCR); + + MMIO_WRITE (MCR, UART_MCR_RTS); /* Request to send */ + register_read = MMIO_READ (MCR); + + MMIO_WRITE (CLK, UART_CLK_125M_1); /* 1.25M Clock speed */ + register_read = MMIO_READ (CLK); + + MMIO_WRITE (CLK, UART_CLK_125M_2); /* 1.25M Clock speed */ + register_read = MMIO_READ (CLK); +} + static int mmio_uart_rd0( void ) { @@ -384,12 +454,15 @@ serial_init( void ) { gPESF = &mmio_uart_serial_functions; gPESF->uart_init(); + lpss_uart_supported = 1; + lpss_uart_enabled = 1; return 1; } else if ( legacy_uart_probe() ) { gPESF = &legacy_uart_serial_functions; gPESF->uart_init(); + legacy_uart_enabled = 1; return 1; } else @@ -402,7 +475,7 @@ serial_init( void ) static void uart_putc(char c) { - if (uart_initted) { + if (uart_initted && (legacy_uart_enabled || lpss_uart_enabled)) { while (!gPESF->tr0()); /* Wait until THR is empty. */ gPESF->td0(c); } @@ -411,7 +484,7 @@ uart_putc(char c) static int uart_getc(void) { - if (uart_initted) { + if (uart_initted && (legacy_uart_enabled || lpss_uart_enabled)) { if (!gPESF->rr0()) return -1; return gPESF->rd0(); diff --git a/pexpert/pexpert/AppleBoot.h b/pexpert/pexpert/AppleBoot.h index 44b1fd4da..e1c6e6073 100644 --- a/pexpert/pexpert/AppleBoot.h +++ b/pexpert/pexpert/AppleBoot.h @@ -26,7 +26,7 @@ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* - * appleboot.h - Apple logo shown durring boot + * appleboot.h - Apple logo shown during boot * * Copyright (c) 2002 Apple Computer, Inc. * diff --git a/pexpert/pexpert/arm/consistent_debug.h b/pexpert/pexpert/arm/consistent_debug.h index 97cf27cf0..3697cd093 100644 --- a/pexpert/pexpert/arm/consistent_debug.h +++ b/pexpert/pexpert/arm/consistent_debug.h @@ -1,13 +1,31 @@ /* - * Copyright (C) 2011-2012 Apple Inc. All rights reserved. + * Copyright (c) 2011-2018 Apple Inc. All rights reserved. * - * This document is the property of Apple Inc. - * It is considered confidential and proprietary. + * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * - * This document may not be reproduced or transmitted in any form, - * in whole or in part, without the express written permission of - * Apple Inc. + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. The rights granted to you under the License + * may not be used to create, or enable the creation or redistribution of, + * unlawful or unlicensed copies of an Apple operating system, or to + * circumvent, violate, or enable the circumvention or violation of, any + * terms of an Apple operating system software license agreement. + * + * Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ + #ifndef PE_CONSISTENT_DEBUG_H #define PE_CONSISTENT_DEBUG_H diff --git a/pexpert/pexpert/arm64/arm64_common.h b/pexpert/pexpert/arm64/arm64_common.h index 51ff2c59a..7b24690b9 100644 --- a/pexpert/pexpert/arm64/arm64_common.h +++ b/pexpert/pexpert/arm64/arm64_common.h @@ -34,6 +34,8 @@ #define ARM64_REG_EHID3_DisDcZvaCmdOnly (1<<25) #define ARM64_REG_HID4 S3_0_c15_c4_0 +#define ARM64_REG_EHID4 S3_0_c15_c4_1 + #define ARM64_REG_HID4_DisDcMVAOps (1<<11) #define ARM64_REG_HID4_DisSpecLnchRead (1<<33) #define ARM64_REG_HID4_ForceNsOrdLdReqNoOlderLd (1<<39) @@ -81,6 +83,7 @@ #if defined(APPLECYCLONE) || defined(APPLETYPHOON) || defined(APPLETWISTER) #define ARM64_REG_CYC_CFG S3_5_c15_c4_0 +#define ARM64_REG_CYC_CFG_skipInit (1ULL<<30) #define ARM64_REG_CYC_CFG_deepSleep (1ULL<<24) #else #define ARM64_REG_ACC_OVRD S3_5_c15_c6_0 @@ -147,11 +150,48 @@ - #endif /* APPLE_ARM64_ARCH_FAMILY */ +#define MPIDR_PNE_SHIFT 16 // pcore not ecore +#define MPIDR_PNE (1 << MPIDR_PNE_SHIFT) + +#ifdef ASSEMBLER + +/* + * arg0: register in which to store result + * 0=>not a p-core, non-zero=>p-core + */ +.macro ARM64_IS_PCORE +.endmacro + +/* + * reads a special purpose register, using a different msr for e- vs. p-cores + * arg0: register indicating the current core type, see ARM64_IS_PCORE + * arg1: register in which to store the result of the read + * arg2: SPR to use for e-core + * arg3: SPR to use for p-core or non-AMP architecture + */ +.macro ARM64_READ_EP_SPR + mrs $1, $3 +2: +.endmacro + +/* + * writes a special purpose register, using a different msr for e- vs. p-cores + * arg0: register indicating the current core type, see ARM64_IS_PCORE + * arg1: register containing the value to write + * arg2: SPR to use for e-core + * arg3: SPR to use for p-core or non-AMP architecture + */ +.macro ARM64_WRITE_EP_SPR + msr $3, $1 +2: +.endmacro + +#endif /* ASSEMBLER */ + #endif /* ! _PEXPERT_ARM_ARM64_H */ diff --git a/pexpert/pexpert/pexpert.h b/pexpert/pexpert/pexpert.h index 61ac16c9c..eac7336cf 100644 --- a/pexpert/pexpert/pexpert.h +++ b/pexpert/pexpert/pexpert.h @@ -70,6 +70,8 @@ extern struct macos_panic_header *panic_info; #endif /* CONFIG_EMBEDDED */ #endif /* XNU_KERNEL_PRIVATE */ +extern void lpss_uart_enable (boolean_t on_off); + void PE_enter_debugger( const char *cause); diff --git a/san/Kasan_kasan.exports b/san/Kasan_kasan.exports index 122be1c84..864ea9424 100644 --- a/san/Kasan_kasan.exports +++ b/san/Kasan_kasan.exports @@ -91,11 +91,14 @@ ___asan_alloca_poison ___asan_allocas_unpoison ___asan_register_globals ___asan_unregister_globals +___asan_register_elf_globals +___asan_unregister_elf_globals ___asan_register_image_globals ___asan_unregister_image_globals ___asan_version_mismatch_check_v8 ___asan_version_mismatch_check_apple_802 ___asan_version_mismatch_check_apple_900 +___asan_version_mismatch_check_apple_902 ___asan_init ___asan_memcpy ___asan_memmove diff --git a/san/Makefile b/san/Makefile index a2f25e8bc..75a98ec4c 100644 --- a/san/Makefile +++ b/san/Makefile @@ -30,12 +30,13 @@ INSTALL_MI_DIR = san EXPORT_MI_DIR = san COMP_SUBDIRS = conf +.DELETE_ON_ERROR: $(OBJROOT)/san/kasan-blacklist-%: $(SOURCE)/kasan-blacklist $(SOURCE)/kasan-blacklist-% @echo "$(ColorH)GENERATING$(Color0) $(ColorLF)$(notdir $@)$(Color0)" $(_v)sed -e 's,^src:\./,src:'"$(SRCROOT)/," $^ > $@ + $(_v)$(SOURCE)/tools/validate_blacklist.sh "$@" -do_build_setup:: $(OBJROOT)/san/kasan-blacklist-x86_64 - +do_build_setup:: $(OBJROOT)/san/kasan-blacklist-x86_64 $(OBJROOT)/san/kasan-blacklist-arm64 # # Kasan System.kext plugin diff --git a/san/conf/Makefile.template b/san/conf/Makefile.template index 03e60fa81..5edceed17 100644 --- a/san/conf/Makefile.template +++ b/san/conf/Makefile.template @@ -13,7 +13,7 @@ export MakeInc_dir=${SRCROOT}/makedefs/MakeInc.dir include $(MakeInc_cmd) include $(MakeInc_def) -CFLAGS+= +CFLAGS += -Wassign-enum -Wswitch-enum # # Directories for mig generated files diff --git a/san/kasan-arm64.c b/san/kasan-arm64.c index 22bb738a1..77ee449a8 100644 --- a/san/kasan-arm64.c +++ b/san/kasan-arm64.c @@ -69,10 +69,6 @@ extern vm_offset_t excepstack, excepstack_top; void kasan_bootstrap(boot_args *, vm_offset_t pgtable); void flush_mmu_tlb(void); -#ifndef __ARM_16K_PG__ -#error "Unsupported HW config: Assuming 16K pages" -#endif - #define KASAN_SHIFT_ARM64 0xdffffff800000000ULL /* Defined in makedefs/MakeInc.def */ #define KASAN_SHADOW_MIN 0xfffffff400000000ULL #define KASAN_SHADOW_MAX 0xfffffff680000000ULL @@ -115,25 +111,18 @@ align_to_page(vm_offset_t *addrp, vm_offset_t *sizep) static void kasan_map_shadow_internal(vm_offset_t address, vm_size_t size, bool is_zero, bool back_page) { - align_to_page(&address, &size); - - vm_size_t j; - uint64_t *pte; + vm_offset_t shadow_base = vm_map_trunc_page(SHADOW_FOR_ADDRESS(address), ARM_PGMASK); + vm_offset_t shadow_top = vm_map_round_page(SHADOW_FOR_ADDRESS(address + size), ARM_PGMASK); - /* XXX: this could be more efficient by walking through the shadow pages - * instead of the source pages */ - - for (j = 0; j < size; j += ARM_PGBYTES) { - vm_offset_t virt_shadow_target = (vm_offset_t)SHADOW_FOR_ADDRESS(address + j); - - assert(virt_shadow_target >= KASAN_SHADOW_MIN); - assert(virt_shadow_target < KASAN_SHADOW_MAX); + assert(shadow_base >= KASAN_SHADOW_MIN && shadow_top <= KASAN_SHADOW_MAX); + for (; shadow_base < shadow_top; shadow_base += ARM_PGBYTES) { uint64_t *base = cpu_tte; + uint64_t *pte; #if !__ARM64_TWO_LEVEL_PMAP__ /* lookup L1 entry */ - pte = base + ((virt_shadow_target & ARM_TT_L1_INDEX_MASK) >> ARM_TT_L1_SHIFT); + pte = base + ((shadow_base & ARM_TT_L1_INDEX_MASK) >> ARM_TT_L1_SHIFT); if (*pte & ARM_TTE_VALID) { assert((*pte & ARM_TTE_TYPE_MASK) == ARM_TTE_TYPE_TABLE); } else { @@ -144,7 +133,7 @@ kasan_map_shadow_internal(vm_offset_t address, vm_size_t size, bool is_zero, boo #endif /* lookup L2 entry */ - pte = base + ((virt_shadow_target & ARM_TT_L2_INDEX_MASK) >> ARM_TT_L2_SHIFT); + pte = base + ((shadow_base & ARM_TT_L2_INDEX_MASK) >> ARM_TT_L2_SHIFT); if (*pte & ARM_TTE_VALID) { assert((*pte & ARM_TTE_TYPE_MASK) == ARM_TTE_TYPE_TABLE); } else { @@ -158,7 +147,7 @@ kasan_map_shadow_internal(vm_offset_t address, vm_size_t size, bool is_zero, boo } /* lookup L3 entry */ - pte = base + ((virt_shadow_target & ARM_TT_L3_INDEX_MASK) >> ARM_TT_L3_SHIFT); + pte = base + ((shadow_base & ARM_TT_L3_INDEX_MASK) >> ARM_TT_L3_SHIFT); if ((*pte & ARM_PTE_TYPE_VALID) && ((((*pte) & ARM_PTE_APMASK) != ARM_PTE_AP(AP_RONA)) || is_zero)) { /* nothing to do - page already mapped and we are not @@ -274,8 +263,6 @@ kasan_map_shadow_early(vm_offset_t address, vm_size_t size, bool is_zero) void kasan_arch_init(void) { - assert(KASAN_SHADOW_MIN >= VM_MAX_KERNEL_ADDRESS); - /* Map the physical aperture */ kasan_map_shadow(kernel_vtop, physmap_vtop - kernel_vtop, true); @@ -331,3 +318,37 @@ kasan_bootstrap(boot_args *args, vm_offset_t pgtable) kasan_map_shadow_early(intstack_virt, intstack_size, false); kasan_map_shadow_early(excepstack_virt, excepstack_size, false); } + +bool +kasan_is_shadow_mapped(uintptr_t shadowp) +{ + uint64_t *pte; + uint64_t *base = cpu_tte; + + assert(shadowp >= KASAN_SHADOW_MIN); + assert(shadowp < KASAN_SHADOW_MAX); + +#if !__ARM64_TWO_LEVEL_PMAP__ + /* lookup L1 entry */ + pte = base + ((shadowp & ARM_TT_L1_INDEX_MASK) >> ARM_TT_L1_SHIFT); + if (!(*pte & ARM_TTE_VALID)) { + return false; + } + base = (uint64_t *)phystokv(*pte & ARM_TTE_TABLE_MASK); +#endif + + /* lookup L2 entry */ + pte = base + ((shadowp & ARM_TT_L2_INDEX_MASK) >> ARM_TT_L2_SHIFT); + if (!(*pte & ARM_TTE_VALID)) { + return false; + } + base = (uint64_t *)phystokv(*pte & ARM_TTE_TABLE_MASK); + + /* lookup L3 entry */ + pte = base + ((shadowp & ARM_TT_L3_INDEX_MASK) >> ARM_TT_L3_SHIFT); + if (!(*pte & ARM_PTE_TYPE_VALID)) { + return false; + } + + return true; +} diff --git a/san/kasan-blacklist b/san/kasan-blacklist index 5832fc0e1..cbef48e41 100644 --- a/san/kasan-blacklist +++ b/san/kasan-blacklist @@ -14,10 +14,19 @@ src:./san/kasan-x86_64.c src:./san/kasan-memintrinsics.c src:./san/kasan_dynamic_blacklist.c +# Blanket ignore non-sanitized functions +fun:__nosan_* + # Try really hard to avoid panicing while debugging src:./osfmk/kdp/* src:./osfmk/kern/debug.c +# Exclude dtrace function that does weird stack manipulations +fun:fbt_perfCallback + +# Exclude leak detection code that reads all memory +fun:_ZL18IOTrackingLeakScanPv + # Exclude KASAN dependencies # XXX: could this be relaxed since fakestack is reentrant? src:./osfmk/kern/zalloc.c diff --git a/san/kasan-blacklist-arm64 b/san/kasan-blacklist-arm64 index d91dac4a8..9ef0c3aab 100644 --- a/san/kasan-blacklist-arm64 +++ b/san/kasan-blacklist-arm64 @@ -3,8 +3,9 @@ # Exclude KASan runtime src:./san/kasan-arm64.c -# Uses a local to work out if we're on the interrupt stack, but ends up with a -# fakestack allocation +# These use a local variable to work out which stack we're on, but can end up with +# a fakestack allocation. fun:ml_at_interrupt_context - - +fun:ml_stack_remaining +fun:ml_stack_base +fun:ml_stack_size diff --git a/san/kasan-blacklist-dynamic b/san/kasan-blacklist-dynamic new file mode 100644 index 000000000..fea2f1c50 --- /dev/null +++ b/san/kasan-blacklist-dynamic @@ -0,0 +1,16 @@ +# entry = :: +# +# = [ kfree zfree fsfree memr memw strr strw read write rw free mem str poison ] +# See kasan_internal.h for descriptions of the types +# +# = last component of kext bundle ID. Use '__kernel__' for xnu proper. +# +# Any field can be empty, which matches everything + + +# OSKext::copyInfo copies the whole cstrings section +__kernel__:_ZN6OSKext8copyInfoEP7OSArray:memr + +# For unit-testing KASan +__kernel__:test_blacklist:test +__kernel__:test_blacklist_str:memr diff --git a/san/kasan-blacklist-x86_64 b/san/kasan-blacklist-x86_64 index 9313e4003..bd1704d30 100644 --- a/san/kasan-blacklist-x86_64 +++ b/san/kasan-blacklist-x86_64 @@ -21,9 +21,6 @@ src:./osfmk/i386/vmx/vmx_cpu.c src:./osfmk/kern/locks.c src:./osfmk/prng/random.c src:./osfmk/x86_64/loose_ends.c -src:./osfmk/x86_64/xcpm/xcpm_dvfs.c -src:./osfmk/x86_64/xcpm/xcpm_idle.c -src:./osfmk/x86_64/xcpm/xcpm_ioctl.c src:./pexpert/gen/bootargs.c src:./pexpert/gen/device_tree.c src:./pexpert/gen/pe_gen.c diff --git a/san/kasan-fakestack.c b/san/kasan-fakestack.c index 12869e512..b023ded1c 100644 --- a/san/kasan-fakestack.c +++ b/san/kasan-fakestack.c @@ -42,6 +42,7 @@ #include int __asan_option_detect_stack_use_after_return = 0; +int fakestack_enabled = 0; #define FAKESTACK_HEADER_SZ 64 #define FAKESTACK_NUM_SZCLASS 7 @@ -69,28 +70,40 @@ static const unsigned long fakestack_min = 1 << 6; static const unsigned long __unused fakestack_max = 1 << 16; /* - * Mark the current thread as being in a fakestack operation, to avoid reentrancy - * issues. If set, disable fakestack allocation. + * Enter a fakestack critical section in a reentrant-safe fashion. Returns true on + * success with the kasan lock held. */ -static boolean_t -thread_enter_fakestack(void) +static bool +thread_enter_fakestack(boolean_t *flags) { - thread_t thread = current_thread(); - if (thread) { - return OSIncrementAtomic(&kasan_get_thread_data(current_thread())->in_fakestack); - } else { - return 0; + thread_t cur = current_thread(); + if (cur && kasan_lock_held(cur)) { + /* current thread is already in kasan - fail */ + return false; } + kasan_lock(flags); + return true; } -static boolean_t -thread_exit_fakestack(void) +static volatile long suspend_count; +static const long suspend_threshold = 20; + +void +kasan_fakestack_suspend(void) { - thread_t thread = current_thread(); - if (thread) { - return OSDecrementAtomic(&kasan_get_thread_data(current_thread())->in_fakestack); - } else { - return 0; + if (OSIncrementAtomicLong(&suspend_count) == suspend_threshold) { + __asan_option_detect_stack_use_after_return = 0; + } +} + +void +kasan_fakestack_resume(void) +{ + long orig = OSDecrementAtomicLong(&suspend_count); + assert(orig >= 0); + + if (fakestack_enabled && orig == suspend_threshold) { + __asan_option_detect_stack_use_after_return = 1; } } @@ -155,24 +168,21 @@ kasan_fakestack_alloc(int sz_class, size_t realsz) return 0; } - boolean_t flags; uptr ret = 0; size_t sz = fakestack_min << sz_class; assert(realsz <= sz); assert(sz <= fakestack_max); zone_t zone = fakestack_zones[sz_class]; - if (thread_enter_fakestack()) { + boolean_t flags; + if (!thread_enter_fakestack(&flags)) { return 0; } - kasan_lock(&flags); kasan_fakestack_gc(current_thread()); /* XXX: optimal? */ ret = (uptr)zget(zone); - thread_exit_fakestack(); - if (ret) { size_t leftrz = 32 + FAKESTACK_HEADER_SZ; size_t validsz = realsz - 32 - 16; /* remove redzones */ @@ -204,7 +214,6 @@ kasan_fakestack_free(int sz_class, uptr dst, size_t realsz) } assert(realsz <= (fakestack_min << sz_class)); - assert(__asan_option_detect_stack_use_after_return); vm_size_t sz = fakestack_min << sz_class; zone_t zone = fakestack_zones[sz_class]; @@ -234,14 +243,10 @@ kasan_fakestack_free(int sz_class, uptr dst, size_t realsz) void NOINLINE kasan_unpoison_fakestack(thread_t thread) { - if (!__asan_option_detect_stack_use_after_return) { - return; - } - boolean_t flags; - kasan_lock(&flags); - - thread_enter_fakestack(); + if (!thread_enter_fakestack(&flags)) { + panic("expected success entering fakestack\n"); + } struct fakestack_header_list *head = &kasan_get_thread_data(thread)->fakestack_head; struct fakestack_header *cur; @@ -252,7 +257,6 @@ kasan_unpoison_fakestack(thread_t thread) } kasan_fakestack_gc(thread); - thread_exit_fakestack(); kasan_unlock(flags); } @@ -283,7 +287,9 @@ kasan_init_fakestack(void) } /* globally enable */ - __asan_option_detect_stack_use_after_return = 1; + if (fakestack_enabled) { + __asan_option_detect_stack_use_after_return = 1; + } } #else /* FAKESTACK */ @@ -318,7 +324,6 @@ kasan_fakestack_free(int __unused sz_class, uptr __unused dst, size_t __unused r void kasan_init_thread(struct kasan_thread_data *td) { - td->in_fakestack = 0; LIST_INIT(&td->fakestack_head); } diff --git a/san/kasan-memintrinsics.c b/san/kasan-memintrinsics.c index c95207cf2..2bbed97e3 100644 --- a/san/kasan-memintrinsics.c +++ b/san/kasan-memintrinsics.c @@ -36,123 +36,92 @@ #include #include -#if MEMINTRINSICS -static bool check_intrinsics = true; -#else -static bool check_intrinsics = false; -#endif - void __asan_bcopy(const void *src, void *dst, size_t sz) { - if (check_intrinsics) { - kasan_check_range(src, sz, TYPE_MEMLD); - kasan_check_range(dst, sz, TYPE_MEMSTR); - } + kasan_check_range(src, sz, TYPE_MEMR); + kasan_check_range(dst, sz, TYPE_MEMW); __nosan_bcopy(src, dst, sz); } void * __asan_memmove(void *src, const void *dst, size_t sz) { - if (check_intrinsics) { - kasan_check_range(src, sz, TYPE_MEMLD); - kasan_check_range(dst, sz, TYPE_MEMSTR); - } + kasan_check_range(src, sz, TYPE_MEMR); + kasan_check_range(dst, sz, TYPE_MEMW); return __nosan_memmove(src, dst, sz); } void * __asan_memcpy(void *dst, const void *src, size_t sz) { - if (check_intrinsics) { - kasan_check_range(src, sz, TYPE_MEMLD); - kasan_check_range(dst, sz, TYPE_MEMSTR); - } + kasan_check_range(src, sz, TYPE_MEMR); + kasan_check_range(dst, sz, TYPE_MEMW); return __nosan_memcpy(dst, src, sz); } void * __asan_memset(void *dst, int c, size_t sz) { - if (check_intrinsics) { - kasan_check_range(dst, sz, TYPE_MEMSTR); - } + kasan_check_range(dst, sz, TYPE_MEMW); return __nosan_memset(dst, c, sz); } void __asan_bzero(void *dst, size_t sz) { - if (check_intrinsics) { - kasan_check_range(dst, sz, TYPE_MEMSTR); - } + kasan_check_range(dst, sz, TYPE_MEMW); __nosan_bzero(dst, sz); } int __asan_bcmp(const void *a, const void *b, size_t len) { - if (check_intrinsics) { - kasan_check_range(a, len, TYPE_MEMLD); - kasan_check_range(b, len, TYPE_MEMLD); - } + kasan_check_range(a, len, TYPE_MEMR); + kasan_check_range(b, len, TYPE_MEMR); return __nosan_bcmp(a, b, len); } int __asan_memcmp(const void *a, const void *b, size_t n) { - if (check_intrinsics) { - kasan_check_range(a, n, TYPE_MEMLD); - kasan_check_range(b, n, TYPE_MEMLD); - } + kasan_check_range(a, n, TYPE_MEMR); + kasan_check_range(b, n, TYPE_MEMR); return __nosan_memcmp(a, b, n); } size_t __asan_strlcpy(char *dst, const char *src, size_t sz) { - if (check_intrinsics) { - kasan_check_range(dst, sz, TYPE_STRINGSTR); - } + kasan_check_range(dst, sz, TYPE_STRW); return __nosan_strlcpy(dst, src, sz); } size_t __asan_strlcat(char *dst, const char *src, size_t sz) { - if (check_intrinsics) { - kasan_check_range(dst, sz, TYPE_STRINGSTR); - } + kasan_check_range(dst, sz, TYPE_STRW); return __nosan_strlcat(dst, src, sz); } char * __asan_strncpy(char *dst, const char *src, size_t sz) { - if (check_intrinsics) { - kasan_check_range(dst, sz, TYPE_STRINGSTR); - } + kasan_check_range(dst, sz, TYPE_STRW); return __nosan_strncpy(dst, src, sz); } char * __asan_strncat(char *dst, const char *src, size_t sz) { - if (check_intrinsics) { - kasan_check_range(dst, strlen(dst) + sz + 1, TYPE_STRINGSTR); - } + kasan_check_range(dst, strlen(dst) + sz + 1, TYPE_STRW); return __nosan_strncat(dst, src, sz); } size_t __asan_strnlen(const char *src, size_t sz) { - if (check_intrinsics) { - kasan_check_range(src, sz, TYPE_STRINGLD); - } - + kasan_check_range(src, sz, TYPE_STRR); return __nosan_strnlen(src, sz); } @@ -160,8 +129,6 @@ size_t __asan_strlen(const char *src) { size_t sz = __nosan_strlen(src); - if (check_intrinsics) { - kasan_check_range(src, sz + 1, TYPE_STRINGLD); - } + kasan_check_range(src, sz + 1, TYPE_STRR); return sz; } diff --git a/san/kasan-test.c b/san/kasan-test.c index 820af1b7f..6dc379c1a 100644 --- a/san/kasan-test.c +++ b/san/kasan-test.c @@ -434,12 +434,14 @@ static int test_strncat(struct kasan_test *t) } /* we ignore the top *two* frames in backtrace - so add an extra one */ -static int NOINLINE test_blacklist_helper(void) +static int __attribute__((noinline)) +test_blacklist_helper(void) { return kasan_is_blacklisted(TYPE_TEST); } -static int NOINLINE test_blacklist(struct kasan_test *t) +static int __attribute__((noinline)) +test_blacklist(struct kasan_test *t) { TEST_START(t); int res = (int)!test_blacklist_helper(); @@ -447,12 +449,13 @@ static int NOINLINE test_blacklist(struct kasan_test *t) return 0; } -static int NOINLINE test_blacklist_str(struct kasan_test *t) +static int __attribute__((noinline)) +test_blacklist_str(struct kasan_test *t) { TEST_START(t); char a1[8]; - strlcpy(a1, "looooooooonnnnggg", 9); + bcopy("123456", a1, 8); TEST_DONE(t, 0); /* success */ return 0; @@ -557,7 +560,7 @@ kasan_run_test(struct kasan_test *test_list, int testno, int fail) /* Triggering a KASan violation will return here by longjmp, bypassing * stack unpoisoning, so do it here explicitly. We just hope that * fakestack free will happen later... */ - kasan_unpoison_curstack(); + kasan_unpoison_curstack(true); if (t->result) { /* faulted, but at the wrong place */ diff --git a/san/kasan-x86_64.c b/san/kasan-x86_64.c index 93e8e416e..e2cb6d3bd 100644 --- a/san/kasan-x86_64.c +++ b/san/kasan-x86_64.c @@ -194,14 +194,12 @@ kasan_map_shadow_superpage_zero(vm_offset_t address, vm_size_t size) void kasan_map_shadow(vm_offset_t address, vm_size_t size, bool is_zero) { - size = vm_map_round_page(size, PAGE_MASK); - vm_size_t j; - - for (j = 0; j < size; j += I386_PGBYTES) { + vm_offset_t shadow_base = vm_map_trunc_page(SHADOW_FOR_ADDRESS(address), PAGE_MASK); + vm_offset_t shadow_top = vm_map_round_page(SHADOW_FOR_ADDRESS(address + size), PAGE_MASK); - vm_offset_t virt_shadow_target = (vm_offset_t)SHADOW_FOR_ADDRESS(address + j); + for (; shadow_base < shadow_top; shadow_base += I386_PGBYTES) { - split_addr_t addr = split_address(virt_shadow_target); + split_addr_t addr = split_address(shadow_base); assert(addr.pml4 == 507 || addr.pml4 == 508); uint64_t *L3; @@ -260,10 +258,10 @@ kasan_map_shadow(vm_offset_t address, vm_size_t size, bool is_zero) L1[addr.pt] = newpte | INTEL_PTE_VALID | INTEL_PTE_NX; - } - /* adding a new entry, this is not strictly required */ - invlpg(virt_shadow_target); + /* adding a new entry, this is not strictly required */ + invlpg(shadow_base); + } } } @@ -334,3 +332,42 @@ kasan_reserve_memory(void *_args) panic("KASAN: could not reserve memory"); } +bool +kasan_is_shadow_mapped(uintptr_t shadowp) +{ + split_addr_t addr = split_address(shadowp); + assert(addr.pml4 == 507 || addr.pml4 == 508); + + uint64_t *L3; + uint64_t *L2; + uint64_t *L1; + + L3 = (uint64_t *)(IdlePML4[addr.pml4] & ~PAGE_MASK); + if (L3 == NULL) { + return false; + } + L3 = (uint64_t *)phys2virt(L3); + + L2 = (uint64_t *)(L3[addr.pdpt] & ~PAGE_MASK); + if (L2 == NULL) { + return false; + } + L2 = (uint64_t *)phys2virt(L2); + + uint64_t pde = L2[addr.pd]; + if ((pde & (INTEL_PTE_VALID|INTEL_PTE_PS)) == (INTEL_PTE_VALID|INTEL_PTE_PS)) { + /* mapped as superpage */ + return true; + } + L1 = (uint64_t *)(pde & ~PAGE_MASK); + if (L1 == NULL) { + return false; + } + L1 = (uint64_t *)phys2virt(L1); + + if (L1[addr.pt] & INTEL_PTE_VALID) { + return true; + } + + return false; +} diff --git a/san/kasan.c b/san/kasan.c index 1723fcef1..01faa3801 100644 --- a/san/kasan.c +++ b/san/kasan.c @@ -55,58 +55,44 @@ #include #include -#if !KASAN_DEBUG -# undef NOINLINE -# define NOINLINE -#endif - const uintptr_t __asan_shadow_memory_dynamic_address = KASAN_SHIFT; -static long kexts_loaded; - -long shadow_pages_total; -long shadow_pages_used; +static unsigned kexts_loaded; +unsigned shadow_pages_total; +unsigned shadow_pages_used; vm_offset_t kernel_vbase; vm_offset_t kernel_vtop; -static bool kasan_initialized; -static int kasan_enabled; -static int quarantine_enabled = 1; +static unsigned kasan_enabled; +static unsigned quarantine_enabled; +static unsigned enabled_checks = TYPE_ALL; /* bitmask of enabled checks */ +static unsigned report_ignored; /* issue non-fatal report for disabled/blacklisted checks */ +static unsigned free_yield = 0; /* ms yield after each free */ + +/* forward decls */ +static void kasan_crash_report(uptr p, uptr width, access_t access, violation_t reason); +static void kasan_log_report(uptr p, uptr width, access_t access, violation_t reason); -static void kasan_crash_report(uptr p, uptr width, unsigned access_type); +/* imported osfmk functions */ extern vm_offset_t ml_stack_base(void); extern vm_size_t ml_stack_size(void); -#define ABI_UNSUPPORTED do { panic("KASan: unsupported ABI: %s\n", __func__); } while (0) +/* + * unused: expected to be called, but (currently) does nothing + */ +#define UNUSED_ABI(func, ...) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wunused-parameter\"") \ + void func(__VA_ARGS__); \ + void func(__VA_ARGS__) {}; \ + _Pragma("clang diagnostic pop") \ -#define BACKTRACE_MAXFRAMES 16 +static const size_t BACKTRACE_BITS = 4; +static const size_t BACKTRACE_MAXFRAMES = (1UL << BACKTRACE_BITS) - 1; decl_simple_lock_data(, kasan_vm_lock); - -_Atomic int unsafe_count = 0; - -void -kasan_unsafe_start(void) -{ - if (__c11_atomic_fetch_add(&unsafe_count, 1, memory_order_relaxed) == 128) { - panic("kasan_unsafe_start overflow"); - } -} - -void -kasan_unsafe_end(void) -{ - if (__c11_atomic_fetch_sub(&unsafe_count, 1, memory_order_relaxed) == 0) { - panic("kasan_unsafe_end underflow"); - } -} - -static bool -kasan_in_unsafe(void) -{ - return atomic_load_explicit(&unsafe_count, memory_order_relaxed) != 0; -} +static thread_t kasan_lock_holder; /* * kasan is called from the interrupt path, so we need to disable interrupts to @@ -117,15 +103,47 @@ kasan_lock(boolean_t *b) { *b = ml_set_interrupts_enabled(false); simple_lock(&kasan_vm_lock); + kasan_lock_holder = current_thread(); } void kasan_unlock(boolean_t b) { + kasan_lock_holder = THREAD_NULL; simple_unlock(&kasan_vm_lock); ml_set_interrupts_enabled(b); } +/* Return true if 'thread' holds the kasan lock. Only safe if 'thread' == current + * thread */ +bool +kasan_lock_held(thread_t thread) +{ + return thread && thread == kasan_lock_holder; +} + +static inline bool +kasan_check_enabled(access_t access) +{ + return kasan_enabled && (enabled_checks & access) && !kasan_is_blacklisted(access); +} + +static inline bool +kasan_poison_active(uint8_t flags) +{ + switch (flags) { + case ASAN_GLOBAL_RZ: + return kasan_check_enabled(TYPE_POISON_GLOBAL); + case ASAN_HEAP_RZ: + case ASAN_HEAP_LEFT_RZ: + case ASAN_HEAP_RIGHT_RZ: + case ASAN_HEAP_FREED: + return kasan_check_enabled(TYPE_POISON_HEAP); + default: + return true; + }; +} + /* * poison redzones in the shadow map */ @@ -144,7 +162,7 @@ kasan_poison(vm_offset_t base, vm_size_t size, vm_size_t leftrz, vm_size_t right assert((leftrz & 0x07) == 0); assert((total & 0x07) == 0); - if (!kasan_enabled || !kasan_initialized) { + if (!kasan_enabled || !kasan_poison_active(flags)) { return; } @@ -170,7 +188,7 @@ kasan_poison(vm_offset_t base, vm_size_t size, vm_size_t leftrz, vm_size_t right shadow[i] = l_flags; } for (; i < leftrz + size; i++) { - shadow[i] = ASAN_VALID; /* not strictly necessary */ + shadow[i] = ASAN_VALID; /* XXX: should not be necessary */ } if (partial && (i < total)) { shadow[i] = partial; @@ -179,8 +197,6 @@ kasan_poison(vm_offset_t base, vm_size_t size, vm_size_t leftrz, vm_size_t right for (; i < total; i++) { shadow[i] = r_flags; } - - asm volatile("" ::: "memory"); /* compiler barrier XXX: is this needed? */ } void @@ -204,12 +220,19 @@ kasan_unpoison_stack(vm_offset_t base, vm_size_t size) { assert(base); assert(size); + + /* align base and size to 8 bytes */ + vm_offset_t align = base & 0x7; + base -= align; + size += align; + size = (size + 7) & ~0x7; + kasan_unpoison((void *)base, size); } /* * write junk into the redzones -*/ + */ static void NOINLINE kasan_rz_clobber(vm_offset_t base, vm_size_t size, vm_size_t leftrz, vm_size_t rightrz) { @@ -241,30 +264,43 @@ kasan_rz_clobber(vm_offset_t base, vm_size_t size, vm_size_t leftrz, vm_size_t r #endif } -void NOINLINE -kasan_check_range(const void *x, size_t sz, unsigned access_type) +/* + * Report a violation that may be disabled and/or blacklisted. This can only be + * called for dynamic checks (i.e. where the fault is recoverable). Use + * kasan_crash_report() for static (unrecoverable) violations. + * + * access: what we were trying to do when the violation occured + * reason: what failed about the access + */ +static void +kasan_violation(uintptr_t addr, size_t size, access_t access, violation_t reason) { - vm_offset_t invalid; - - if (kasan_in_unsafe()) { + assert(__builtin_popcount(access) == 1); + if (!kasan_check_enabled(access)) { + if (report_ignored) { + kasan_log_report(addr, size, access, reason); + } return; } + kasan_crash_report(addr, size, access, reason); +} - if (kasan_range_poisoned((vm_offset_t)x, sz, &invalid)) { - if (kasan_is_blacklisted(access_type)) { - return; - } - kasan_crash_report(invalid, sz, access_type); - /* NOTREACHED */ +void NOINLINE +kasan_check_range(const void *x, size_t sz, access_t access) +{ + uintptr_t invalid; + uintptr_t ptr = (uintptr_t)x; + if (kasan_range_poisoned(ptr, sz, &invalid)) { + size_t remaining = sz - (invalid - ptr); + kasan_violation(invalid, remaining, access, 0); } } /* - * Check that [base, base+sz) has shadow value `shadow' - * If not, report a KASan-violation on `addr' + * Return true if [base, base+sz) is unpoisoned or has given shadow value. */ -static void -kasan_assert_shadow(vm_address_t base, vm_size_t sz, vm_address_t addr, uint8_t shadow) +static bool +kasan_check_shadow(vm_address_t base, vm_size_t sz, uint8_t shadow) { sz -= 8 - (base % 8); base += 8 - (base % 8); @@ -273,11 +309,12 @@ kasan_assert_shadow(vm_address_t base, vm_size_t sz, vm_address_t addr, uint8_t while (base < end) { uint8_t *sh = SHADOW_FOR_ADDRESS(base); - if (*sh != shadow) { - __asan_report_load1(addr); + if (*sh && *sh != shadow) { + return false; } base += 8; } + return true; } /* @@ -287,16 +324,16 @@ kasan_assert_shadow(vm_address_t base, vm_size_t sz, vm_address_t addr, uint8_t */ static const char * -access_type_str(unsigned type) +access_str(access_t type) { - if (type & TYPE_LOAD_ALL) { - return "load"; - } else if (type & TYPE_STORE_ALL) { - return "store"; + if (type & TYPE_READ) { + return "load from"; + } else if (type & TYPE_WRITE) { + return "store to"; } else if (type & TYPE_FREE) { - return "free"; + return "free of"; } else { - return "access"; + return "access of"; } } @@ -328,43 +365,59 @@ static size_t kasan_shadow_crashlog(uptr p, char *buf, size_t len) { int i,j; - size_t l = 0; + size_t n = 0; int before = CRASH_CONTEXT_BEFORE; int after = CRASH_CONTEXT_AFTER; uptr shadow = (uptr)SHADOW_FOR_ADDRESS(p); uptr shadow_p = shadow; + uptr shadow_page = vm_map_round_page(shadow_p, PAGE_MASK); /* rewind to start of context block */ shadow &= ~((uptr)0xf); shadow -= 16 * before; + n += snprintf(buf+n, len-n, + " Shadow 0 1 2 3 4 5 6 7 8 9 a b c d e f\n"); + for (i = 0; i < 1 + before + after; i++, shadow += 16) { - if (vm_map_round_page(shadow, PAGE_MASK) != vm_map_round_page(shadow_p, PAGE_MASK)) { - /* don't cross a page boundary, in case the shadow is unmapped */ - /* XXX: ideally we check instead of ignore */ + if ((vm_map_round_page(shadow, PAGE_MASK) != shadow_page) && !kasan_is_shadow_mapped(shadow)) { + /* avoid unmapped shadow when crossing page boundaries */ continue; } - l += snprintf(buf+l, len-l, " %#16lx: ", shadow); + n += snprintf(buf+n, len-n, " %16lx:", shadow); + + char *left = " "; + char *right; for (j = 0; j < 16; j++) { uint8_t *x = (uint8_t *)(shadow + j); - l += snprintf(buf+l, len-l, "%02x ", (unsigned)*x); + + right = " "; + if ((uptr)x == shadow_p) { + left = "["; + right = "]"; + } else if ((uptr)(x + 1) == shadow_p) { + right = ""; + } + + n += snprintf(buf+n, len-n, "%s%02x%s", left, (unsigned)*x, right); + left = ""; } - l += snprintf(buf+l, len-l, "\n"); + n += snprintf(buf+n, len-n, "\n"); } - l += snprintf(buf+l, len-l, "\n"); - return l; + n += snprintf(buf+n, len-n, "\n"); + return n; } -static void NOINLINE -kasan_crash_report(uptr p, uptr width, unsigned access_type) +static void +kasan_report_internal(uptr p, uptr width, access_t access, violation_t reason, bool dopanic) { const size_t len = 4096; static char buf[len]; - size_t l = 0; + size_t n = 0; uint8_t *shadow_ptr = SHADOW_FOR_ADDRESS(p); uint8_t shadow_type = *shadow_ptr; @@ -372,28 +425,66 @@ kasan_crash_report(uptr p, uptr width, unsigned access_type) if (!shadow_str) { shadow_str = ""; } + buf[0] = '\0'; + + if (reason == REASON_MOD_OOB || reason == REASON_BAD_METADATA) { + n += snprintf(buf+n, len-n, "KASan: free of corrupted/invalid object %#lx\n", p); + } else if (reason == REASON_MOD_AFTER_FREE) { + n += snprintf(buf+n, len-n, "KASan: UaF of quarantined object %#lx\n", p); + } else { + n += snprintf(buf+n, len-n, "KASan: invalid %lu-byte %s %#lx [%s]\n", + width, access_str(access), p, shadow_str); + } + n += kasan_shadow_crashlog(p, buf+n, len-n); + if (dopanic) { + panic("%s", buf); + } else { + printf("%s", buf); + } +} + +static void NOINLINE OS_NORETURN +kasan_crash_report(uptr p, uptr width, access_t access, violation_t reason) +{ kasan_handle_test(); + kasan_report_internal(p, width, access, reason, true); + __builtin_unreachable(); /* we cant handle this returning anyway */ +} - buf[0] = '\0'; - l += snprintf(buf+l, len-l, - "KASan: invalid %lu-byte %s @ %#lx [%s]\n" - "Shadow %#02x @ %#lx\n\n", - width, access_type_str(access_type), p, shadow_str, - (unsigned)shadow_type, (unsigned long)shadow_ptr); +static void +kasan_log_report(uptr p, uptr width, access_t access, violation_t reason) +{ + const size_t len = 256; + char buf[len]; + size_t l = 0; + uint32_t nframes = 14; + uintptr_t frames[nframes]; + uintptr_t *bt = frames; + + kasan_report_internal(p, width, access, reason, false); + + /* + * print a backtrace + */ - l += kasan_shadow_crashlog(p, buf+l, len-l); + nframes = backtrace_frame(bt, nframes, __builtin_frame_address(0)); /* ignore current frame */ - panic("%s", buf); + buf[0] = '\0'; + l += snprintf(buf+l, len-l, "Backtrace: "); + for (uint32_t i = 0; i < nframes; i++) { + l += snprintf(buf+l, len-l, "%lx,", VM_KERNEL_UNSLIDE(bt[i])); + } + l += snprintf(buf+l, len-l, "\n"); + + printf("%s", buf); } #define REPORT_DECLARE(n) \ - void __asan_report_load##n(uptr p) { kasan_crash_report(p, n, TYPE_LOAD); } \ - void __asan_report_store##n(uptr p) { kasan_crash_report(p, n, TYPE_STORE); } \ - void __asan_report_exp_load##n(uptr, int32_t); \ - void __asan_report_exp_store##n(uptr, int32_t); \ - void __asan_report_exp_load##n(uptr __unused p, int32_t __unused e) { ABI_UNSUPPORTED; } \ - void __asan_report_exp_store##n(uptr __unused p, int32_t __unused e) { ABI_UNSUPPORTED; } + void OS_NORETURN __asan_report_load##n(uptr p) { kasan_crash_report(p, n, TYPE_LOAD, 0); } \ + void OS_NORETURN __asan_report_store##n(uptr p) { kasan_crash_report(p, n, TYPE_STORE, 0); } \ + void UNSUPPORTED_API(__asan_report_exp_load##n, uptr a, int32_t b); \ + void UNSUPPORTED_API(__asan_report_exp_store##n, uptr a, int32_t b); REPORT_DECLARE(1) REPORT_DECLARE(2) @@ -401,21 +492,32 @@ REPORT_DECLARE(4) REPORT_DECLARE(8) REPORT_DECLARE(16) -void __asan_report_load_n(uptr p, unsigned long sz) { kasan_crash_report(p, sz, TYPE_LOAD); } -void __asan_report_store_n(uptr p, unsigned long sz) { kasan_crash_report(p, sz, TYPE_STORE); } +void OS_NORETURN __asan_report_load_n(uptr p, unsigned long sz) { kasan_crash_report(p, sz, TYPE_LOAD, 0); } +void OS_NORETURN __asan_report_store_n(uptr p, unsigned long sz) { kasan_crash_report(p, sz, TYPE_STORE, 0); } /* unpoison the current stack */ -/* XXX: as an optimization, we could unpoison only up to the current stack depth */ void NOINLINE -kasan_unpoison_curstack(void) +kasan_unpoison_curstack(bool whole_stack) { - kasan_unpoison_stack(ml_stack_base(), ml_stack_size()); + uintptr_t base = ml_stack_base(); + size_t sz = ml_stack_size(); + uintptr_t cur = (uintptr_t)&base; + + if (whole_stack) { + cur = base; + } + + if (cur >= base && cur < base + sz) { + /* unpoison from current stack depth to the top */ + size_t unused = cur - base; + kasan_unpoison_stack(cur, sz - unused); + } } void NOINLINE __asan_handle_no_return(void) { - kasan_unpoison_curstack(); + kasan_unpoison_curstack(false); kasan_unpoison_fakestack(current_thread()); } @@ -425,7 +527,7 @@ kasan_range_poisoned(vm_offset_t base, vm_size_t size, vm_offset_t *first_invali uint8_t *shadow; vm_size_t i; - if (!kasan_initialized || !kasan_enabled) { + if (!kasan_enabled) { return false; } @@ -474,16 +576,16 @@ kasan_load_kext(vm_offset_t base, vm_size_t __unused size, const void *bundleid) unsigned long sectsz; void *sect; +#if KASAN_DYNAMIC_BLACKLIST + kasan_dybl_load_kext(base, bundleid); +#endif + /* find the kasan globals segment/section */ sect = getsectdatafromheader((void *)base, KASAN_GLOBAL_SEGNAME, KASAN_GLOBAL_SECTNAME, §sz); if (sect) { kasan_init_globals((vm_address_t)sect, (vm_size_t)sectsz); kexts_loaded++; } - -#if KASAN_DYNAMIC_BLACKLIST - kasan_dybl_load_kext(base, bundleid); -#endif } void NOINLINE @@ -504,11 +606,18 @@ kasan_unload_kext(vm_offset_t base, vm_size_t size) #endif } +/* + * Turn off as much as possible for panic path etc. There's no way to turn it back + * on. + */ void NOINLINE kasan_disable(void) { __asan_option_detect_stack_use_after_return = 0; + fakestack_enabled = 0; kasan_enabled = 0; + quarantine_enabled = 0; + enabled_checks = 0; } static void NOINLINE @@ -522,21 +631,21 @@ kasan_init_xnu_globals(void) kernel_mach_header_t *header = (kernel_mach_header_t *)&_mh_execute_header; if (!header) { - printf("KASAN: failed to find kernel mach header\n"); - printf("KASAN: redzones for globals not poisoned\n"); + printf("KASan: failed to find kernel mach header\n"); + printf("KASan: redzones for globals not poisoned\n"); return; } globals = (vm_offset_t)getsectdatafromheader(header, seg, sect, &_size); if (!globals) { - printf("KASAN: failed to find segment %s section %s\n", seg, sect); - printf("KASAN: redzones for globals not poisoned\n"); + printf("KASan: failed to find segment %s section %s\n", seg, sect); + printf("KASan: redzones for globals not poisoned\n"); return; } size = (vm_size_t)_size; - printf("KASAN: found (%s,%s) at %#lx + %lu\n", seg, sect, globals, size); - printf("KASAN: poisoning redzone for %lu globals\n", size / sizeof(struct asan_global)); + printf("KASan: found (%s,%s) at %#lx + %lu\n", seg, sect, globals, size); + printf("KASan: poisoning redzone for %lu globals\n", size / sizeof(struct asan_global)); kasan_init_globals(globals, size); } @@ -544,12 +653,12 @@ kasan_init_xnu_globals(void) void NOINLINE kasan_late_init(void) { - kasan_init_fakestack(); - kasan_init_xnu_globals(); - #if KASAN_DYNAMIC_BLACKLIST kasan_init_dybl(); #endif + + kasan_init_fakestack(); + kasan_init_xnu_globals(); } void NOINLINE @@ -584,6 +693,8 @@ kasan_debug_touch_mappings(vm_offset_t base, vm_size_t sz) void NOINLINE kasan_init(void) { + unsigned arg; + simple_lock_init(&kasan_vm_lock, 0); /* Map all of the kernel text and data */ @@ -591,7 +702,39 @@ kasan_init(void) kasan_arch_init(); - kasan_initialized = 1; + /* + * handle KASan boot-args + */ + + if (PE_parse_boot_argn("kasan.checks", &arg, sizeof(arg))) { + enabled_checks = arg; + } + + if (PE_parse_boot_argn("kasan", &arg, sizeof(arg))) { + if (arg & KASAN_ARGS_FAKESTACK) { + fakestack_enabled = 1; + } + if (arg & KASAN_ARGS_REPORTIGNORED) { + report_ignored = 1; + } + if (arg & KASAN_ARGS_NODYCHECKS) { + enabled_checks &= ~TYPE_DYNAMIC; + } + if (arg & KASAN_ARGS_NOPOISON_HEAP) { + enabled_checks &= ~TYPE_POISON_HEAP; + } + if (arg & KASAN_ARGS_NOPOISON_GLOBAL) { + enabled_checks &= ~TYPE_POISON_GLOBAL; + } + } + + if (PE_parse_boot_argn("kasan.free_yield_ms", &arg, sizeof(arg))) { + free_yield = arg; + } + + /* kasan.bl boot-arg handled in kasan_init_dybl() */ + + quarantine_enabled = 1; kasan_enabled = 1; } @@ -600,7 +743,7 @@ kasan_notify_address_internal(vm_offset_t address, vm_size_t size, bool is_zero) { assert(address < VM_MAX_KERNEL_ADDRESS); - if (!kasan_initialized || !kasan_enabled) { + if (!kasan_enabled) { return; } @@ -643,12 +786,13 @@ kasan_notify_address_nopoison(vm_offset_t address, vm_size_t size) */ struct kasan_alloc_header { - uint32_t magic; + uint16_t magic; + uint16_t crc; uint32_t alloc_size; uint32_t user_size; struct { - uint32_t left_rz : 28; - uint32_t frames : 4; + uint32_t left_rz : 32 - BACKTRACE_BITS; + uint32_t frames : BACKTRACE_BITS; }; }; _Static_assert(sizeof(struct kasan_alloc_header) <= KASAN_GUARD_SIZE, "kasan alloc header exceeds guard size"); @@ -658,11 +802,18 @@ struct kasan_alloc_footer { }; _Static_assert(sizeof(struct kasan_alloc_footer) <= KASAN_GUARD_SIZE, "kasan alloc footer exceeds guard size"); -#define MAGIC_XOR ((uint32_t)0xA110C8ED) -static uint32_t -magic_for_addr(vm_offset_t addr) +#define LIVE_XOR ((uint16_t)0x3a65) +#define FREE_XOR ((uint16_t)0xf233) + +static uint16_t +magic_for_addr(vm_offset_t addr, uint16_t magic_xor) { - return (uint32_t)addr ^ MAGIC_XOR; + uint16_t magic = addr & 0xFFFF; + magic ^= (addr >> 16) & 0xFFFF; + magic ^= (addr >> 32) & 0xFFFF; + magic ^= (addr >> 48) & 0xFFFF; + magic ^= magic_xor; + return magic; } static struct kasan_alloc_header * @@ -731,6 +882,25 @@ kasan_alloc_bt(uint32_t *ptr, vm_size_t sz, vm_size_t skip) return frames; } +/* addr: user address of allocation */ +static uint16_t +kasan_alloc_crc(vm_offset_t addr) +{ + struct kasan_alloc_header *h = header_for_user_addr(addr); + vm_size_t rightrz = h->alloc_size - h->user_size - h->left_rz; + + uint16_t crc_orig = h->crc; + h->crc = 0; + + uint16_t crc = 0; + crc = __nosan_crc16(crc, (void *)(addr - h->left_rz), h->left_rz); + crc = __nosan_crc16(crc, (void *)(addr + h->user_size), rightrz); + + h->crc = crc_orig; + + return crc; +} + /* * addr: base address of full allocation (including redzones) * size: total size of allocation (include redzones) @@ -757,7 +927,7 @@ kasan_alloc(vm_offset_t addr, vm_size_t size, vm_size_t req, vm_size_t leftrz) /* stash the allocation sizes in the left redzone */ struct kasan_alloc_header *h = header_for_user_addr(addr); - h->magic = magic_for_addr(addr); + h->magic = magic_for_addr(addr, LIVE_XOR); h->left_rz = leftrz; h->alloc_size = size; h->user_size = req; @@ -767,6 +937,9 @@ kasan_alloc(vm_offset_t addr, vm_size_t size, vm_size_t req, vm_size_t leftrz) struct kasan_alloc_footer *f = footer_for_user_addr(addr, &fsize); h->frames = kasan_alloc_bt(f->backtrace, fsize, 2); + /* checksum the whole object, minus the user part */ + h->crc = kasan_alloc_crc(addr); + return addr; } @@ -780,10 +953,6 @@ kasan_dealloc(vm_offset_t addr, vm_size_t *size) { assert(size && addr); struct kasan_alloc_header *h = header_for_user_addr(addr); - if (h->magic != magic_for_addr(addr)) { - /* no point blacklisting here - this is fatal */ - kasan_crash_report(addr, *size, TYPE_FREE); - } *size = h->alloc_size; return addr - h->left_rz; } @@ -796,7 +965,7 @@ vm_size_t kasan_user_size(vm_offset_t addr) { struct kasan_alloc_header *h = header_for_user_addr(addr); - assert(h->magic == magic_for_addr(addr)); + assert(h->magic == magic_for_addr(addr, LIVE_XOR)); return h->user_size; } @@ -809,36 +978,30 @@ kasan_check_free(vm_offset_t addr, vm_size_t size, unsigned heap_type) struct kasan_alloc_header *h = header_for_user_addr(addr); /* map heap type to an internal access type */ - unsigned type; - if (heap_type == KASAN_HEAP_KALLOC) { - type = TYPE_KFREE; - } else if (heap_type == KASAN_HEAP_ZALLOC) { - type = TYPE_ZFREE; - } else if (heap_type == KASAN_HEAP_FAKESTACK) { - type = TYPE_FSFREE; - } + access_t type = heap_type == KASAN_HEAP_KALLOC ? TYPE_KFREE : + heap_type == KASAN_HEAP_ZALLOC ? TYPE_ZFREE : + heap_type == KASAN_HEAP_FAKESTACK ? TYPE_FSFREE : 0; - /* check the magic matches */ - if (h->magic != magic_for_addr(addr)) { - if (kasan_is_blacklisted(type)) { - return; - } - kasan_crash_report(addr, size, type); + /* check the magic and crc match */ + if (h->magic != magic_for_addr(addr, LIVE_XOR)) { + kasan_violation(addr, size, type, REASON_BAD_METADATA); + } + if (h->crc != kasan_alloc_crc(addr)) { + kasan_violation(addr, size, type, REASON_MOD_OOB); } /* check the freed size matches what we recorded at alloc time */ if (h->user_size != size) { - if (kasan_is_blacklisted(type)) { - return; - } - kasan_crash_report(addr, size, type); + kasan_violation(addr, size, type, REASON_INVALID_SIZE); } vm_size_t rightrz_sz = h->alloc_size - h->left_rz - h->user_size; /* Check that the redzones are valid */ - kasan_assert_shadow(addr - h->left_rz, h->left_rz, addr, ASAN_HEAP_LEFT_RZ); - kasan_assert_shadow(addr + h->user_size, rightrz_sz, addr, ASAN_HEAP_RIGHT_RZ); + if (!kasan_check_shadow(addr - h->left_rz, h->left_rz, ASAN_HEAP_LEFT_RZ) || + !kasan_check_shadow(addr + h->user_size, rightrz_sz, ASAN_HEAP_RIGHT_RZ)) { + kasan_violation(addr, size, type, REASON_BAD_METADATA); + } /* Check the allocated range is not poisoned */ kasan_check_range((void *)addr, size, type); @@ -851,15 +1014,15 @@ kasan_check_free(vm_offset_t addr, vm_size_t size, unsigned heap_type) */ struct freelist_entry { - uint32_t magic; - uint32_t checksum; + uint16_t magic; + uint16_t crc; STAILQ_ENTRY(freelist_entry) list; union { struct { vm_size_t size : 28; vm_size_t user_size : 28; - vm_size_t frames : 4; /* number of frames in backtrace */ - vm_size_t __unused : 4; + vm_size_t frames : BACKTRACE_BITS; /* number of frames in backtrace */ + vm_size_t __unused : 8 - BACKTRACE_BITS; }; uint64_t bits; }; @@ -868,13 +1031,6 @@ struct freelist_entry { }; _Static_assert(sizeof(struct freelist_entry) <= KASAN_GUARD_PAD, "kasan freelist header exceeds padded size"); -#define FREELIST_MAGIC_XOR ((uint32_t)0xF23333D) -static uint32_t -freelist_magic(vm_offset_t addr) -{ - return (uint32_t)addr ^ FREELIST_MAGIC_XOR; -} - struct quarantine { STAILQ_HEAD(freelist_head, freelist_entry) freelist; unsigned long entries; @@ -889,6 +1045,12 @@ struct quarantine quarantines[] = { { STAILQ_HEAD_INITIALIZER((quarantines[KASAN_HEAP_FAKESTACK].freelist)), 0, QUARANTINE_ENTRIES, 0, QUARANTINE_MAXSIZE } }; +static uint16_t +fle_crc(struct freelist_entry *fle) +{ + return __nosan_crc16(0, &fle->bits, fle->size - offsetof(struct freelist_entry, bits)); +} + /* * addr, sizep: pointer/size of full allocation including redzone */ @@ -927,7 +1089,7 @@ kasan_free_internal(void **addrp, vm_size_t *sizep, int type, /* create a new freelist entry */ fle = (struct freelist_entry *)addr; - fle->magic = freelist_magic((vm_offset_t)fle); + fle->magic = magic_for_addr((vm_offset_t)fle, FREE_XOR); fle->size = size; fle->user_size = user_size; fle->frames = 0; @@ -936,7 +1098,9 @@ kasan_free_internal(void **addrp, vm_size_t *sizep, int type, fle->zone = *zone; } if (type != KASAN_HEAP_FAKESTACK) { + /* don't do expensive things on the fakestack path */ fle->frames = kasan_alloc_bt(fle->backtrace, fle->size - sizeof(struct freelist_entry), 3); + fle->crc = fle_crc(fle); } boolean_t flg; @@ -976,12 +1140,17 @@ kasan_free_internal(void **addrp, vm_size_t *sizep, int type, size = tofree->size; addr = (vm_offset_t)tofree; - if (tofree->magic != freelist_magic(addr)) { - kasan_crash_report(addr, size, TYPE_FREE); + + /* check the magic and crc match */ + if (tofree->magic != magic_for_addr(addr, FREE_XOR)) { + kasan_violation(addr, size, TYPE_UAF, REASON_MOD_AFTER_FREE); + } + if (type != KASAN_HEAP_FAKESTACK && tofree->crc != fle_crc(tofree)) { + kasan_violation(addr, size, TYPE_UAF, REASON_MOD_AFTER_FREE); } /* clobber the quarantine header */ - kasan_rz_clobber(addr, 0, sizeof(struct freelist_entry), 0); + __nosan_bzero((void *)addr, sizeof(struct freelist_entry)); } else { /* quarantine is not full - don't really free anything */ @@ -1006,6 +1175,10 @@ kasan_free(void **addrp, vm_size_t *sizep, int type, zone_t *zone, vm_size_t user_size, bool quarantine) { kasan_free_internal(addrp, sizep, type, zone, user_size, 0, quarantine); + + if (free_yield) { + thread_yield_internal(free_yield); + } } uptr @@ -1028,12 +1201,11 @@ __asan_poison_cxx_array_cookie(uptr p) *shadow = ASAN_ARRAY_COOKIE; } -#define ACCESS_CHECK_DECLARE(type, sz, access_type) \ +#define ACCESS_CHECK_DECLARE(type, sz, access) \ void __asan_##type##sz(uptr addr) { \ - kasan_check_range((const void *)addr, sz, access_type); \ + kasan_check_range((const void *)addr, sz, access); \ } \ - void __asan_exp_##type##sz(uptr, int32_t); \ - void __asan_exp_##type##sz(uptr __unused addr, int32_t __unused e) { ABI_UNSUPPORTED; } + void UNSUPPORTED_API(__asan_exp_##type##sz, uptr a, int32_t b); ACCESS_CHECK_DECLARE(load, 1, TYPE_LOAD); ACCESS_CHECK_DECLARE(load, 2, TYPE_LOAD); @@ -1058,16 +1230,6 @@ __asan_storeN(uptr addr, size_t sz) kasan_check_range((const void *)addr, sz, TYPE_STORE); } -void __asan_exp_loadN(uptr, size_t, int32_t); -void __asan_exp_storeN(uptr, size_t, int32_t); -void __asan_exp_loadN(uptr __unused addr, size_t __unused sz, int32_t __unused e) { ABI_UNSUPPORTED; } -void __asan_exp_storeN(uptr __unused addr, size_t __unused sz, int32_t __unused e) { ABI_UNSUPPORTED; } - -void __asan_report_exp_load_n(uptr, unsigned long, int32_t); -void __asan_report_exp_store_n(uptr, unsigned long, int32_t); -void __asan_report_exp_load_n(uptr __unused p, unsigned long __unused sz, int32_t __unused e) { ABI_UNSUPPORTED; } -void __asan_report_exp_store_n(uptr __unused p, unsigned long __unused sz, int32_t __unused e) { ABI_UNSUPPORTED; } - static void kasan_set_shadow(uptr addr, size_t sz, uint8_t val) { @@ -1086,115 +1248,76 @@ SET_SHADOW_DECLARE(f3) SET_SHADOW_DECLARE(f5) SET_SHADOW_DECLARE(f8) + /* - * XXX: implement these + * Call 'cb' for each contiguous range of the shadow map. This could be more + * efficient by walking the page table directly. */ - -void __asan_alloca_poison(uptr addr, uptr size) -{ - (void)addr; - (void)size; -} - -void __asan_allocas_unpoison(uptr top, uptr bottom) +int +kasan_traverse_mappings(pmap_traverse_callback cb, void *ctx) { - (void)top; - (void)bottom; -} - -void -__sanitizer_ptr_sub(uptr a, uptr b) -{ - (void)a; - (void)b; -} - -void -__sanitizer_ptr_cmp(uptr a, uptr b) -{ - (void)a; - (void)b; -} - -void -__asan_poison_stack_memory(uptr addr, size_t size) -{ - (void)addr; - (void)size; -} + uintptr_t shadow_base = (uintptr_t)SHADOW_FOR_ADDRESS(VM_MIN_KERNEL_AND_KEXT_ADDRESS); + uintptr_t shadow_top = (uintptr_t)SHADOW_FOR_ADDRESS(VM_MAX_KERNEL_ADDRESS); + shadow_base = vm_map_trunc_page(shadow_base, PAGE_MASK); + shadow_top = vm_map_round_page(shadow_top, PAGE_MASK); + + uintptr_t start = 0, end = 0; + + for (uintptr_t addr = shadow_base; addr < shadow_top; addr += PAGE_SIZE) { + if (kasan_is_shadow_mapped(addr)) { + if (start == 0) { + start = addr; + } + end = addr + PAGE_SIZE; + } else if (start && end) { + cb(start, end, ctx); + start = end = 0; + } + } -void -__asan_unpoison_stack_memory(uptr addr, size_t size) -{ - (void)addr; - (void)size; -} + if (start && end) { + cb(start, end, ctx); + } -void -__sanitizer_annotate_contiguous_container(const void *beg, - const void *end, - const void *old_mid, - const void *new_mid) -{ - (void)beg; - (void)end; - (void)old_mid; - (void)new_mid; + return 0; } /* + * XXX: implement these */ -void -__asan_init(void) -{ -} - -#define VERSION_DECLARE(v) \ - void __asan_version_mismatch_check_##v(void); \ - void __asan_version_mismatch_check_##v(void) {} - -VERSION_DECLARE(v8) -VERSION_DECLARE(apple_802) -VERSION_DECLARE(apple_900) - -void -__asan_register_globals(uptr __unused a, uptr __unused b) -{ - ABI_UNSUPPORTED; -} - -void -__asan_unregister_globals(uptr __unused a, uptr __unused b) -{ - ABI_UNSUPPORTED; -} - -void -__asan_register_image_globals(uptr __unused ptr) -{ -} - -void -__asan_unregister_image_globals(uptr __unused ptr) -{ -} - -void -__asan_init_v5(void) -{ -} - -void -__asan_before_dynamic_init(uptr __unused arg) -{ -} +UNUSED_ABI(__asan_alloca_poison, uptr addr, uptr size); +UNUSED_ABI(__asan_allocas_unpoison, uptr top, uptr bottom); +UNUSED_ABI(__sanitizer_ptr_sub, uptr a, uptr b); +UNUSED_ABI(__sanitizer_ptr_cmp, uptr a, uptr b); +UNUSED_ABI(__sanitizer_annotate_contiguous_container, const void *a, const void *b, const void *c, const void *d); +UNUSED_ABI(__asan_poison_stack_memory, uptr addr, size_t size); +UNUSED_ABI(__asan_unpoison_stack_memory, uptr a, uptr b); -void -__asan_after_dynamic_init(void) -{ -} +/* + * Miscellaneous unimplemented asan ABI + */ +UNUSED_ABI(__asan_init, void); +UNUSED_ABI(__asan_register_image_globals, uptr a); +UNUSED_ABI(__asan_unregister_image_globals, uptr a); +UNUSED_ABI(__asan_before_dynamic_init, uptr a); +UNUSED_ABI(__asan_after_dynamic_init, void); +UNUSED_ABI(__asan_version_mismatch_check_v8, void); +UNUSED_ABI(__asan_version_mismatch_check_apple_802, void); +UNUSED_ABI(__asan_version_mismatch_check_apple_900, void); +UNUSED_ABI(__asan_version_mismatch_check_apple_902, void); + +void UNSUPPORTED_API(__asan_init_v5, void); +void UNSUPPORTED_API(__asan_register_globals, uptr a, uptr b); +void UNSUPPORTED_API(__asan_unregister_globals, uptr a, uptr b); +void UNSUPPORTED_API(__asan_register_elf_globals, uptr a, uptr b, uptr c); +void UNSUPPORTED_API(__asan_unregister_elf_globals, uptr a, uptr b, uptr c); + +void UNSUPPORTED_API(__asan_exp_loadN, uptr addr, size_t sz, int32_t e); +void UNSUPPORTED_API(__asan_exp_storeN, uptr addr, size_t sz, int32_t e); +void UNSUPPORTED_API(__asan_report_exp_load_n, uptr addr, unsigned long b, int32_t c); +void UNSUPPORTED_API(__asan_report_exp_store_n, uptr addr, unsigned long b, int32_t c); /* * @@ -1217,22 +1340,40 @@ sysctl_kasan_test(__unused struct sysctl_oid *oidp, __unused void *arg1, int arg return err; } +static int +sysctl_fakestack_enable(__unused struct sysctl_oid *oidp, __unused void *arg1, int __unused arg2, struct sysctl_req *req) +{ + int ch, err, val; + + err = sysctl_io_number(req, fakestack_enabled, sizeof(fakestack_enabled), &val, &ch); + if (err == 0 && ch) { + fakestack_enabled = !!val; + __asan_option_detect_stack_use_after_return = !!val; + } + + return err; +} + SYSCTL_DECL(kasan); SYSCTL_NODE(_kern, OID_AUTO, kasan, CTLFLAG_RW | CTLFLAG_LOCKED, 0, ""); SYSCTL_COMPAT_INT(_kern_kasan, OID_AUTO, available, CTLFLAG_RD, NULL, KASAN, ""); -SYSCTL_INT(_kern_kasan, OID_AUTO, enabled, CTLFLAG_RD, &kasan_enabled, 0, ""); -SYSCTL_INT(_kern_kasan, OID_AUTO, quarantine, CTLFLAG_RW, &quarantine_enabled, 0, ""); -SYSCTL_LONG(_kern_kasan, OID_AUTO, memused, CTLFLAG_RD, &shadow_pages_used, ""); -SYSCTL_LONG(_kern_kasan, OID_AUTO, memtotal, CTLFLAG_RD, &shadow_pages_total, ""); -SYSCTL_LONG(_kern_kasan, OID_AUTO, kexts, CTLFLAG_RD, &kexts_loaded, ""); - -SYSCTL_COMPAT_INT(_kern_kasan, OID_AUTO, debug, CTLFLAG_RD, NULL, KASAN_DEBUG, ""); -SYSCTL_COMPAT_INT(_kern_kasan, OID_AUTO, zalloc, CTLFLAG_RD, NULL, KASAN_ZALLOC, ""); -SYSCTL_COMPAT_INT(_kern_kasan, OID_AUTO, kalloc, CTLFLAG_RD, NULL, KASAN_KALLOC, ""); -SYSCTL_COMPAT_INT(_kern_kasan, OID_AUTO, fakestack, CTLFLAG_RD, NULL, FAKESTACK, ""); -SYSCTL_COMPAT_INT(_kern_kasan, OID_AUTO, dynamicbl, CTLFLAG_RD, NULL, KASAN_DYNAMIC_BLACKLIST, ""); -SYSCTL_COMPAT_INT(_kern_kasan, OID_AUTO, memintrinsics, CTLFLAG_RD, NULL, MEMINTRINSICS, ""); +SYSCTL_UINT(_kern_kasan, OID_AUTO, enabled, CTLFLAG_RD, &kasan_enabled, 0, ""); +SYSCTL_UINT(_kern_kasan, OID_AUTO, checks, CTLFLAG_RW, &enabled_checks, 0, ""); +SYSCTL_UINT(_kern_kasan, OID_AUTO, quarantine, CTLFLAG_RW, &quarantine_enabled, 0, ""); +SYSCTL_UINT(_kern_kasan, OID_AUTO, report_ignored, CTLFLAG_RW, &report_ignored, 0, ""); +SYSCTL_UINT(_kern_kasan, OID_AUTO, free_yield_ms, CTLFLAG_RW, &free_yield, 0, ""); +SYSCTL_UINT(_kern_kasan, OID_AUTO, memused, CTLFLAG_RD, &shadow_pages_used, 0, ""); +SYSCTL_UINT(_kern_kasan, OID_AUTO, memtotal, CTLFLAG_RD, &shadow_pages_total, 0, ""); +SYSCTL_UINT(_kern_kasan, OID_AUTO, kexts, CTLFLAG_RD, &kexts_loaded, 0, ""); +SYSCTL_COMPAT_UINT(_kern_kasan, OID_AUTO, debug, CTLFLAG_RD, NULL, KASAN_DEBUG, ""); +SYSCTL_COMPAT_UINT(_kern_kasan, OID_AUTO, zalloc, CTLFLAG_RD, NULL, KASAN_ZALLOC, ""); +SYSCTL_COMPAT_UINT(_kern_kasan, OID_AUTO, kalloc, CTLFLAG_RD, NULL, KASAN_KALLOC, ""); +SYSCTL_COMPAT_UINT(_kern_kasan, OID_AUTO, dynamicbl, CTLFLAG_RD, NULL, KASAN_DYNAMIC_BLACKLIST, ""); + +SYSCTL_PROC(_kern_kasan, OID_AUTO, fakestack, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, + 0, 0, sysctl_fakestack_enable, "I", ""); SYSCTL_PROC(_kern_kasan, OID_AUTO, test, CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, diff --git a/san/kasan.h b/san/kasan.h index bb048d860..102a31468 100644 --- a/san/kasan.h +++ b/san/kasan.h @@ -95,17 +95,28 @@ void kasan_notify_stolen(vm_offset_t top); void kasan_load_kext(vm_offset_t base, vm_size_t size, const void *bundleid); void kasan_unload_kext(vm_offset_t base, vm_size_t size); +void kasan_unpoison(void *base, vm_size_t size); void kasan_poison_range(vm_offset_t base, vm_size_t sz, uint8_t flags); void kasan_notify_address(vm_offset_t address, vm_size_t size); void kasan_notify_address_nopoison(vm_offset_t address, vm_size_t size); void kasan_unpoison_stack(vm_offset_t stack, vm_size_t size); +void kasan_unpoison_curstack(bool whole_stack); void kasan_unpoison_fakestack(thread_t thread); +void kasan_fakestack_suspend(void); +void kasan_fakestack_resume(void); + struct kasan_test; void __kasan_runtests(struct kasan_test *, int numtests); + +typedef int (*pmap_traverse_callback)(vm_map_offset_t start, + vm_map_offset_t end, + void *context); +int kasan_traverse_mappings(pmap_traverse_callback, void *context); + #if XNU_KERNEL_PRIVATE -extern long shadow_pages_total; +extern unsigned shadow_pages_total; #if __arm64__ void kasan_notify_address_zero(vm_offset_t, vm_size_t); @@ -132,7 +143,6 @@ __END_DECLS /* thread interface */ struct kasan_thread_data { - int in_fakestack; LIST_HEAD(fakestack_header_list, fakestack_header) fakestack_head; }; struct kasan_thread_data *kasan_get_thread_data(thread_t); @@ -146,19 +156,6 @@ void kasan_init_thread(struct kasan_thread_data *); # define NOKASAN #endif -/* - * Delimit areas of code that may do kasan-unsafe operations - */ -__BEGIN_DECLS -#if KASAN -void kasan_unsafe_start(void); -void kasan_unsafe_end(void); -#else -static inline void kasan_unsafe_start(void) {} -static inline void kasan_unsafe_end(void) {} -#endif -__END_DECLS - /* * ASAN callbacks - inserted by the compiler */ @@ -166,17 +163,24 @@ __END_DECLS extern int __asan_option_detect_stack_use_after_return; extern const uintptr_t __asan_shadow_memory_dynamic_address; +#define KASAN_DECLARE_FOREACH_WIDTH(ret, func, ...) \ + ret func ## 1(__VA_ARGS__); \ + ret func ## 2(__VA_ARGS__); \ + ret func ## 4(__VA_ARGS__); \ + ret func ## 8(__VA_ARGS__); \ + ret func ## 16(__VA_ARGS__); \ + __BEGIN_DECLS -void __asan_report_load1(uptr p); -void __asan_report_load2(uptr p); -void __asan_report_load4(uptr p); -void __asan_report_load8(uptr p); -void __asan_report_load16(uptr p); -void __asan_report_store1(uptr p); -void __asan_report_store2(uptr p); -void __asan_report_store4(uptr p); -void __asan_report_store8(uptr p); -void __asan_report_store16(uptr p); + +KASAN_DECLARE_FOREACH_WIDTH(void, __asan_report_load, uptr); +KASAN_DECLARE_FOREACH_WIDTH(void, __asan_report_store, uptr); +KASAN_DECLARE_FOREACH_WIDTH(void, __asan_store, uptr); +KASAN_DECLARE_FOREACH_WIDTH(void, __asan_report_exp_load, uptr, int32_t); +KASAN_DECLARE_FOREACH_WIDTH(void, __asan_report_exp_store, uptr, int32_t); +KASAN_DECLARE_FOREACH_WIDTH(void, __asan_exp_load, uptr, int32_t); +KASAN_DECLARE_FOREACH_WIDTH(void, __asan_exp_store, uptr, int32_t); +KASAN_DECLARE_FOREACH_WIDTH(void, __asan_load, uptr); + void __asan_report_load_n(uptr p, unsigned long size); void __asan_report_store_n(uptr p, unsigned long size); void __asan_handle_no_return(void); @@ -208,22 +212,17 @@ void __asan_poison_stack_memory(uptr addr, size_t size); void __asan_unpoison_stack_memory(uptr addr, size_t size); void __asan_alloca_poison(uptr addr, uptr size); void __asan_allocas_unpoison(uptr top, uptr bottom); -void __asan_load1(uptr); -void __asan_load2(uptr); -void __asan_load4(uptr); -void __asan_load8(uptr); -void __asan_load16(uptr); void __asan_loadN(uptr, size_t); -void __asan_store1(uptr); -void __asan_store2(uptr); -void __asan_store4(uptr); -void __asan_store8(uptr); -void __asan_store16(uptr); void __asan_storeN(uptr, size_t); void __sanitizer_ptr_sub(uptr a, uptr b); void __sanitizer_ptr_cmp(uptr a, uptr b); void __sanitizer_annotate_contiguous_container(const void *beg, const void *end, const void *old_mid, const void *new_mid); +void __asan_exp_loadN(uptr addr, size_t sz, int32_t e); +void __asan_exp_storeN(uptr addr, size_t sz, int32_t e); +void __asan_report_exp_load_n(uptr addr, unsigned long b, int32_t c); +void __asan_report_exp_store_n(uptr addr, unsigned long b, int32_t c); + void __asan_set_shadow_00(uptr, size_t); void __asan_set_shadow_f1(uptr, size_t); void __asan_set_shadow_f2(uptr, size_t); @@ -232,10 +231,13 @@ void __asan_set_shadow_f5(uptr, size_t); void __asan_set_shadow_f8(uptr, size_t); void __asan_init_v5(void); +void __asan_register_globals(uptr a, uptr b); +void __asan_unregister_globals(uptr a, uptr b); +void __asan_register_elf_globals(uptr a, uptr b, uptr c); +void __asan_unregister_elf_globals(uptr a, uptr b, uptr c); + void __asan_before_dynamic_init(uptr); void __asan_after_dynamic_init(void); -void __asan_unregister_globals(uptr a, uptr b); -void __asan_register_globals(uptr a, uptr b); void __asan_init(void); void __asan_unregister_image_globals(uptr); void __asan_register_image_globals(uptr); diff --git a/san/kasan_dynamic_blacklist.c b/san/kasan_dynamic_blacklist.c index 97fc3a561..f4ad0fa05 100644 --- a/san/kasan_dynamic_blacklist.c +++ b/san/kasan_dynamic_blacklist.c @@ -27,16 +27,17 @@ struct blacklist_entry { const char *kext_name; const char *func_name; - const unsigned type_mask; + access_t type_mask; /* internal */ uint64_t count; }; #include "kasan_blacklist_dynamic.h" -static const size_t blacklist_entries = sizeof(blacklist)/sizeof(blacklist[0]); +/* defines 'blacklist' and 'blacklist_entries' */ decl_simple_lock_data(static, _dybl_lock); +static access_t blacklisted_types; /* bitmap of access types with blacklist entries */ static void dybl_lock(boolean_t *b) @@ -349,19 +350,27 @@ addr_to_func(uintptr_t addr, const kernel_mach_header_t *mh) return cur_name; } -bool NOINLINE -kasan_is_blacklisted(unsigned mask) +bool __attribute__((noinline)) +kasan_is_blacklisted(access_t type) { uint32_t nframes = 0; uintptr_t frames[MAX_FRAMES]; uintptr_t *bt = frames; - nframes = backtrace(bt, MAX_FRAMES); + + assert(__builtin_popcount(type) == 1); + + if ((type & blacklisted_types) == 0) { + /* early exit for types with no blacklist entries */ + return false; + } + + nframes = backtrace_frame(bt, MAX_FRAMES, __builtin_frame_address(0)); boolean_t flag; - if (nframes >= 2) { - /* ignore self and direct caller */ - nframes -= 2; - bt += 2; + if (nframes >= 1) { + /* ignore direct caller */ + nframes -= 1; + bt += 1; } struct blacklist_hash_entry *blhe = NULL; @@ -372,7 +381,7 @@ kasan_is_blacklisted(unsigned mask) for (uint32_t i = 0; i < nframes; i++) { blhe = blacklist_hash_lookup(bt[i]); if (blhe) { - if ((blhe->ble->type_mask & mask) != mask) { + if ((blhe->ble->type_mask & type) != type) { /* wrong type */ continue; } @@ -419,7 +428,7 @@ kasan_is_blacklisted(unsigned mask) struct blacklist_entry *ble = &blacklist[j]; uint64_t count; - if ((ble->type_mask & mask) != mask) { + if ((ble->type_mask & type) != type) { /* wrong type */ continue; } @@ -443,7 +452,7 @@ kasan_is_blacklisted(unsigned mask) if (count == 0) { printf("KASan: ignoring blacklisted violation (%s:%s [0x%lx] %d 0x%x)\n", - kextname, funcname, VM_KERNEL_UNSLIDE(bt[i]), i, mask); + kextname, funcname, VM_KERNEL_UNSLIDE(bt[i]), i, type); } return true; @@ -454,11 +463,124 @@ kasan_is_blacklisted(unsigned mask) return false; } +static void +add_blacklist_entry(const char *kext, const char *func, access_t type) +{ + assert(kext || func); + struct blacklist_entry *ble = &blacklist[blacklist_entries++]; + + if (blacklist_entries > blacklist_max_entries) { + panic("KASan: dynamic blacklist entries exhausted\n"); + } + + if (kext) { + size_t sz = __nosan_strlen(kext) + 1; + if (sz > 1) { + char *s = kalloc(sz); + __nosan_strlcpy(s, kext, sz); + ble->kext_name = s; + } + } + + if (func) { + size_t sz = __nosan_strlen(func) + 1; + if (sz > 1) { + char *s = kalloc(sz); + __nosan_strlcpy(s, func, sz); + ble->func_name = s; + } + } + + ble->type_mask = type; +} + +#define TS(x) { .type = TYPE_##x, .str = #x } + +static const struct { + const access_t type; + const char * const str; +} typemap[] = { + TS(LOAD), + TS(STORE), + TS(MEMR), + TS(MEMW), + TS(STRR), + TS(STRW), + TS(KFREE), + TS(ZFREE), + TS(FSFREE), + TS(UAF), + TS(POISON_GLOBAL), + TS(POISON_HEAP), + TS(MEM), + TS(STR), + TS(READ), + TS(WRITE), + TS(RW), + TS(FREE), + TS(NORMAL), + TS(DYNAMIC), + TS(POISON), + TS(ALL), + + /* convenience aliases */ + { .type = TYPE_POISON_GLOBAL, .str = "GLOB" }, + { .type = TYPE_POISON_HEAP, .str = "HEAP" }, +}; +static size_t typemap_sz = sizeof(typemap)/sizeof(typemap[0]); + +static inline access_t +map_type(const char *str) +{ + if (strlen(str) == 0) { + return TYPE_NORMAL; + } + + /* convert type string to integer ID */ + for (size_t i = 0; i < typemap_sz; i++) { + if (strcasecmp(str, typemap[i].str) == 0) { + return typemap[i].type; + } + } + + printf("KASan: unknown blacklist type `%s', assuming `normal'\n", str); + return TYPE_NORMAL; +} + void kasan_init_dybl(void) { simple_lock_init(&_dybl_lock, 0); + /* + * dynamic blacklist entries via boot-arg. Syntax is: + * kasan.bl=kext1:func1:type1,kext2:func2:type2,... + */ + char buf[256] = {}; + char *bufp = buf; + if (PE_parse_boot_arg_str("kasan.bl", bufp, sizeof(buf))) { + char *kext; + while ((kext = strsep(&bufp, ",")) != NULL) { + access_t type = TYPE_NORMAL; + char *func = strchr(kext, ':'); + if (func) { + *func++ = 0; + } + char *typestr = strchr(func, ':'); + if (typestr) { + *typestr++ = 0; + type = map_type(typestr); + } + add_blacklist_entry(kext, func, type); + } + } + + /* collect bitmask of blacklisted types */ + for (size_t j = 0; j < blacklist_entries; j++) { + struct blacklist_entry *ble = &blacklist[j]; + blacklisted_types |= ble->type_mask; + } + /* add the fake kernel kext */ kasan_dybl_load_kext((uintptr_t)&_mh_execute_header, "__kernel__"); } @@ -466,7 +588,7 @@ kasan_init_dybl(void) #else /* KASAN_DYNAMIC_BLACKLIST */ bool -kasan_is_blacklisted(unsigned __unused mask) +kasan_is_blacklisted(access_t __unused type) { return false; } diff --git a/san/kasan_internal.h b/san/kasan_internal.h index 805255178..c696abe92 100644 --- a/san/kasan_internal.h +++ b/san/kasan_internal.h @@ -40,9 +40,8 @@ typedef uintptr_t uptr; /* * KASAN features and config */ -#define KASAN_DEBUG 1 +#define KASAN_DEBUG 0 #define FAKESTACK 1 -#define MEMINTRINSICS 1 /* KASAN_KALLOC defined in kasan.h */ /* KASAN_ZALLOC defined in kasan.h */ #define FAKESTACK_QUARANTINE (1 && FAKESTACK) @@ -63,6 +62,13 @@ typedef uintptr_t uptr; # define STOLEN_MEM_BYTES 0 #endif +/* boot-args */ +#define KASAN_ARGS_FAKESTACK 0x0010U +#define KASAN_ARGS_REPORTIGNORED 0x0020U +#define KASAN_ARGS_NODYCHECKS 0x0100U +#define KASAN_ARGS_NOPOISON_HEAP 0x0200U +#define KASAN_ARGS_NOPOISON_GLOBAL 0x0400U + #ifndef KASAN # error KASAN undefined #endif @@ -74,61 +80,86 @@ typedef uintptr_t uptr; #define ADDRESS_FOR_SHADOW(x) (((x) - KASAN_SHIFT) << 3) #define SHADOW_FOR_ADDRESS(x) (uint8_t *)(((x) >> 3) + KASAN_SHIFT) -#define NOINLINE __attribute__ ((noinline)) +#if KASAN_DEBUG +# define NOINLINE __attribute__ ((noinline)) +#else +# define NOINLINE +#endif #define ALWAYS_INLINE inline __attribute__((always_inline)) #define CLANG_MIN_VERSION(x) (defined(__apple_build_version__) && (__apple_build_version__ >= (x))) #define BIT(x) (1U << (x)) -enum kasan_access_type { - /* exactly one of these bits must be set */ - TYPE_LOAD = BIT(0), - TYPE_STORE = BIT(1), - TYPE_KFREE = BIT(2), - TYPE_ZFREE = BIT(3), - TYPE_FSFREE = BIT(4), /* fakestack free */ - TYPE_MEMLD = BIT(5), /* memory intrinsic - load */ - TYPE_MEMSTR = BIT(6), /* memory intrinsic - store */ - TYPE_STRINGLD = BIT(7), /* string intrinsic - load */ - TYPE_STRINGSTR = BIT(8), /* string intrinsic - store */ - TYPE_TEST = BIT(15), +enum __attribute__((flag_enum)) kasan_access_types { + TYPE_LOAD = BIT(0), /* regular memory load */ + TYPE_STORE = BIT(1), /* regular store */ + TYPE_MEMR = BIT(2), /* memory intrinsic (read) */ + TYPE_MEMW = BIT(3), /* memory intrinsic (write) */ + TYPE_STRR = BIT(4), /* string intrinsic (read) */ + TYPE_STRW = BIT(5), /* string intrinsic (write) */ + TYPE_KFREE = BIT(6), /* kfree() */ + TYPE_ZFREE = BIT(7), /* zfree() */ + TYPE_FSFREE = BIT(8), /* fakestack free */ + + TYPE_UAF = BIT(12), + TYPE_POISON_GLOBAL = BIT(13), + TYPE_POISON_HEAP = BIT(14), + /* no TYPE_POISON_STACK, because the runtime does not control stack poisoning */ + TYPE_TEST = BIT(15), /* masks */ - TYPE_LDSTR = TYPE_LOAD|TYPE_STORE, /* regular loads and stores */ - TYPE_FREE = TYPE_KFREE|TYPE_ZFREE|TYPE_FSFREE, - TYPE_MEM = TYPE_MEMLD|TYPE_MEMSTR, - TYPE_STRING = TYPE_STRINGLD|TYPE_STRINGSTR, - TYPE_LOAD_ALL = TYPE_LOAD|TYPE_MEMLD|TYPE_STRINGLD, - TYPE_STORE_ALL = TYPE_STORE|TYPE_MEMSTR|TYPE_STRINGSTR, - TYPE_ALL = ~0U + TYPE_MEM = TYPE_MEMR|TYPE_MEMW, /* memory intrinsics */ + TYPE_STR = TYPE_STRR|TYPE_STRW, /* string intrinsics */ + TYPE_READ = TYPE_LOAD|TYPE_MEMR|TYPE_STRR, /* all reads */ + TYPE_WRITE = TYPE_STORE|TYPE_MEMW|TYPE_STRW, /* all writes */ + TYPE_RW = TYPE_READ|TYPE_WRITE, /* reads and writes */ + TYPE_FREE = TYPE_KFREE|TYPE_ZFREE|TYPE_FSFREE, + TYPE_NORMAL = TYPE_RW|TYPE_FREE, + TYPE_DYNAMIC = TYPE_NORMAL|TYPE_UAF, + TYPE_POISON = TYPE_POISON_GLOBAL|TYPE_POISON_HEAP, + TYPE_ALL = ~0U, }; +enum kasan_violation_types { + REASON_POISONED = 0, /* read or write of poisoned data */ + REASON_BAD_METADATA = 1, /* incorrect kasan metadata */ + REASON_INVALID_SIZE = 2, /* free size did not match alloc size */ + REASON_MOD_AFTER_FREE = 3, /* object modified after free */ + REASON_MOD_OOB = 4, /* out of bounds modification of object */ +}; + +typedef enum kasan_access_types access_t; +typedef enum kasan_violation_types violation_t; + bool kasan_range_poisoned(vm_offset_t base, vm_size_t size, vm_offset_t *first_invalid); -void kasan_check_range(const void *x, size_t sz, unsigned access_type); +void kasan_check_range(const void *x, size_t sz, access_t); void kasan_test(int testno, int fail); void kasan_handle_test(void); -void kasan_unpoison_curstack(void); void kasan_free_internal(void **addrp, vm_size_t *sizep, int type, zone_t *, vm_size_t user_size, int locked, bool doquarantine); void kasan_poison(vm_offset_t base, vm_size_t size, vm_size_t leftrz, vm_size_t rightrz, uint8_t flags); -void kasan_unpoison(void *base, vm_size_t size); void kasan_lock(boolean_t *b); void kasan_unlock(boolean_t b); +bool kasan_lock_held(thread_t thread); void kasan_init_fakestack(void); /* dynamic blacklist */ void kasan_init_dybl(void); -bool kasan_is_blacklisted(unsigned type); +bool kasan_is_blacklisted(access_t); void kasan_dybl_load_kext(uintptr_t addr, const char *kextname); void kasan_dybl_unload_kext(uintptr_t addr); /* arch-specific interface */ void kasan_arch_init(void); +bool kasan_is_shadow_mapped(uintptr_t shadowp); extern vm_address_t kernel_vbase; extern vm_address_t kernel_vtop; -extern long shadow_pages_used; +extern unsigned shadow_pages_used; + +/* boot-arg configurable */ +extern int fakestack_enabled; /* Describes the source location where a global is defined. */ struct asan_global_source_location { diff --git a/san/tools/generate_dynamic_blacklist.py b/san/tools/generate_dynamic_blacklist.py index 3f4c06bed..c71d9c4fb 100755 --- a/san/tools/generate_dynamic_blacklist.py +++ b/san/tools/generate_dynamic_blacklist.py @@ -8,6 +8,8 @@ def type_map(x): re_comments=re.compile(r'#.*$') +nentries = 0 +extra_entries = 5 bl = file(sys.argv[1]) print r'struct blacklist_entry blacklist[] = {' @@ -35,12 +37,27 @@ def type_map(x): func = '"' + func + '"' if ty == "": - ty = "all"; + ty = "normal"; print """ {{ .kext_name = {}, .func_name = {}, .type_mask = {}, }},""".format(kext, func, type_map(ty)) + nentries += 1 + +# add space for new entries added at runtime +print '' +print r' /* Unused entries that can be populated at runtime */' +for i in xrange(0, extra_entries): + print """ {{ + .kext_name = {}, + .func_name = {}, + .type_mask = {}, + }},""".format("NULL", "NULL", 0) print r'};' +print + +print 'static size_t blacklist_entries = {};'.format(nentries) +print 'static const size_t blacklist_max_entries = {};'.format(nentries + extra_entries) diff --git a/san/tools/validate_blacklist.sh b/san/tools/validate_blacklist.sh new file mode 100755 index 000000000..8045241ed --- /dev/null +++ b/san/tools/validate_blacklist.sh @@ -0,0 +1,28 @@ +#!/bin/bash + +# Ensure all blacklisted files exist. Paths with wildcards are ignored. +# Run against a blacklist with fully-qualified paths. + +IFS=$'\n' + +blacklist_files=`sed -n -e ' + # ignore paths with wildcards + /\*/ d + + # strip leading 'src:' + /^src/ { + s/^src:// + p + } +' $1` + +ret=0 + +for f in $blacklist_files ; do + if ! [[ -e $f ]] ; then + echo "KASan: blacklisted file $f not found" >&2 + ret=1 + fi +done + +exit $ret diff --git a/security/mac_policy.h b/security/mac_policy.h index e656f8393..5cae62529 100644 --- a/security/mac_policy.h +++ b/security/mac_policy.h @@ -3841,13 +3841,14 @@ typedef int mpo_system_check_auditon_t( @param cred Subject credential Determine whether the subject identified by the credential can perform - performance-related tasks using the CHUD system call. + performance-related tasks using the CHUD system call. This interface is + deprecated. @return Return 0 if access is granted, otherwise an appropriate value for errno should be returned. */ typedef int mpo_system_check_chud_t( - kauth_cred_t cred + kauth_cred_t cred ); /** @brief Access control check for obtaining the host control port diff --git a/tools/lldbmacros/Makefile b/tools/lldbmacros/Makefile index afb3d6b88..30383a3db 100644 --- a/tools/lldbmacros/Makefile +++ b/tools/lldbmacros/Makefile @@ -68,7 +68,8 @@ LLDBMACROS_PYTHON_FILES = $(LLDBMACROS_USERDEBUG_FILES) \ usertaskgdbserver.py \ waitq.py \ pgtrace.py \ - xnutriage.py + xnutriage.py \ + zonetriage.py ifneq ($(PLATFORM),MacOSX) LLDBMACROS_PYTHON_FILES+= \ diff --git a/tools/lldbmacros/README.md b/tools/lldbmacros/README.md index 53a03fdf5..ccff5196f 100644 --- a/tools/lldbmacros/README.md +++ b/tools/lldbmacros/README.md @@ -199,7 +199,7 @@ D. Kernel type summaries. ========================== i. Using summaries ------------------ -The lldb debugger provides ways for user to customize how a particular type of object be decsribed when printed. These are very useful in displaying complex and large structures +The lldb debugger provides ways for user to customize how a particular type of object be described when printed. These are very useful in displaying complex and large structures where only certain fields are important based on some flag or value in some field or variable. The way it works is every time lldb wants to print an object it checks for registered summaries. We can define python functions and hook it up with lldb as callbacks for type summaries. For example. diff --git a/tools/lldbmacros/kasan.py b/tools/lldbmacros/kasan.py index 2142fa7ac..d4bec35c4 100755 --- a/tools/lldbmacros/kasan.py +++ b/tools/lldbmacros/kasan.py @@ -113,6 +113,14 @@ def print_alloc_free_entry(addr, orig_ptr): alloc_header_sz = 16 +def magic_for_addr(addr, xor): + magic = addr & 0xffff + magic ^= (addr >> 16) & 0xffff + magic ^= (addr >> 32) & 0xffff + magic ^= (addr >> 48) & 0xffff + magic ^= xor + return magic + def print_alloc_info(_addr): addr = (_addr & ~0x7) @@ -144,10 +152,7 @@ def print_alloc_info(_addr): print "No allocation found at 0x{:x} (found shadow {:x})".format(_addr, shbyte) return - live_magic = (addr & 0xffffffff) ^ 0xA110C8ED - free_magic = (addr & 0xffffffff) ^ 0xF23333D - - if live_magic == unsigned(liveh.magic): + if magic_for_addr(addr, 0x3a65) == unsigned(liveh.magic): usz = unsigned(liveh.user_size) asz = unsigned(liveh.alloc_size) leftrz = unsigned(liveh.left_rz) @@ -156,11 +161,12 @@ def print_alloc_info(_addr): if _addr >= base and _addr < base + asz: footer = kern.GetValueFromAddress(addr + usz, 'struct kasan_alloc_footer *') rightrz = asz - usz - leftrz + offset = _addr - addr print "Live heap object" print "Valid range: 0x{:x} -- 0x{:x} ({} bytes)".format(addr, addr + usz - 1, usz) print "Total range: 0x{:x} -- 0x{:x} ({} bytes)".format(base, base + asz - 1, asz) - print "Offset: {} bytes (shadow: 0x{:02x} {})".format(_addr - addr, _shbyte, _shstr) + print "Offset: {} bytes (shadow: 0x{:02x} {}, remaining: {} bytes)".format(offset, _shbyte, _shstr, usz - offset) print "Redzone: {} / {} bytes".format(leftrz, rightrz) btframes = unsigned(liveh.frames) @@ -174,7 +180,7 @@ def print_alloc_info(_addr): print_hexdump(base, asz, 0) return - elif free_magic == unsigned(freeh.magic): + elif magic_for_addr(addr, 0xf233) == unsigned(freeh.magic): asz = unsigned(freeh.size) if _addr >= addr and _addr < addr + asz: print_alloc_free_entry(addr, _addr) diff --git a/tools/lldbmacros/kcdata.py b/tools/lldbmacros/kcdata.py index 8732d5e94..12a996c69 100755 --- a/tools/lldbmacros/kcdata.py +++ b/tools/lldbmacros/kcdata.py @@ -200,12 +200,14 @@ def FromBinaryTypeData(byte_data): return KCSubTypeElement(st_name, st_type, st_size, st_offset, st_flag) @staticmethod - def FromBasicCtype(st_name, st_type, st_offset=0): + def FromBasicCtype(st_name, st_type, st_offset=0, legacy_size=None): if st_type <= 0 or st_type > KCSUBTYPE_TYPE.KC_ST_UINT64: raise ValueError("Invalid type passed %d" % st_type) st_size = struct.calcsize(KCSubTypeElement._unpack_formats[st_type]) st_flag = 0 retval = KCSubTypeElement(st_name, st_type, st_size, st_offset, st_flag, KCSubTypeElement._get_naked_element_value) + if legacy_size: + retval.legacy_size = legacy_size return retval @staticmethod @@ -295,7 +297,8 @@ def __init__(self, t_type_id, t_elements=[], t_name='anon', custom_repr=None, le self.name = t_name self.totalsize = 0 self.custom_JsonRepr = custom_repr - self.legacy_size = legacy_size + if legacy_size: + self.legacy_size = legacy_size self.merge = merge for e in self.elements: self.totalsize += e.GetTotalSize() @@ -317,7 +320,8 @@ def __str__(self): @staticmethod def FromKCTypeDescription(other, t_type_id, t_name): - retval = KCTypeDescription(t_type_id, other.elements, t_name, other.custom_JsonRepr) + retval = KCTypeDescription(t_type_id, other.elements, t_name, other.custom_JsonRepr, + legacy_size=getattr(other, 'legacy_size', None)) return retval def ShouldMerge(self): @@ -328,7 +332,7 @@ def GetJsonRepr(self, base_data, flags): padding = (flags & KCDATA_FLAGS_STRUCT_PADDING_MASK) if padding: base_data = base_data[:-padding] - elif self.legacy_size and len(base_data) == self.legacy_size + ((-self.legacy_size) & 0xf): + elif hasattr(self, 'legacy_size') and len(base_data) == self.legacy_size + ((-self.legacy_size) & 0xf): base_data = base_data[:self.legacy_size] if self.custom_JsonRepr: return self.custom_JsonRepr([e.GetValue(base_data) for e in self.elements]) @@ -497,10 +501,8 @@ def ParseData(self): element_arr = [] for i in range(u_d[1]): e = KCSubTypeElement.FromBinaryTypeData(self.i_data[40+(i*40):]) - #print str(e) element_arr.append(e) type_desc = KCTypeDescription(u_d[0], element_arr, self.obj['name']) - #print str(type_desc) self.obj['fields'] = [str(e) for e in element_arr] KNOWN_TYPES_COLLECTION[type_desc.GetTypeID()] = type_desc logging.info("0x%08x: %s%s" % (self.offset, INDENT(), self.i_name)) @@ -511,9 +513,9 @@ def ParseData(self): if e_t not in LEGAL_OLD_STYLE_ARRAY_TYPES: raise Exception, "illegal old-style array type: %s (0x%x)" % (GetTypeNameForKey(e_t), e_t) e_c = self.i_flags & 0xffffffff - e_s = KNOWN_TYPES_COLLECTION[e_t].sizeof() + e_s = KNOWN_TYPES_COLLECTION[e_t].legacy_size if e_s * e_c > self.i_size: - raise Excpetion, "array too small for its count" + raise Exception("array too small for its count") self.obj['typeID'] = e_t self.i_name = GetTypeNameForKey(e_t) self.i_type = e_t @@ -824,8 +826,11 @@ def _get_data_element(elementValues): KCSubTypeElement.FromBasicCtype('tds_rqos', KCSUBTYPE_TYPE.KC_ST_UINT8, 45), KCSubTypeElement.FromBasicCtype('tds_rqos_override', KCSUBTYPE_TYPE.KC_ST_UINT8, 46), KCSubTypeElement.FromBasicCtype('tds_io_tier', KCSUBTYPE_TYPE.KC_ST_UINT8, 47), + KCSubTypeElement.FromBasicCtype('tds_requested_policy', KCSUBTYPE_TYPE.KC_ST_UINT64, 48), + KCSubTypeElement.FromBasicCtype('tds_effective_policy', KCSUBTYPE_TYPE.KC_ST_UINT64, 56), ), - 'thread_delta_snapshot' + 'thread_delta_snapshot', + legacy_size = 48 ) KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_TASK_DELTA_SNAPSHOT')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_TASK_DELTA_SNAPSHOT'), ( @@ -855,14 +860,16 @@ def _get_data_element(elementValues): KCSubTypeElement('imageLoadAddress', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0), KCSubTypeElement('imageUUID', KCSUBTYPE_TYPE.KC_ST_UINT8, KCSubTypeElement.GetSizeForArray(16, 1), 8, 1) ), - 'dyld_load_info' + 'dyld_load_info', + legacy_size = 24 ) KNOWN_TYPES_COLLECTION[GetTypeForName('KCDATA_TYPE_LIBRARY_LOADINFO')] = KCTypeDescription(GetTypeForName('KCDATA_TYPE_LIBRARY_LOADINFO'), ( KCSubTypeElement('imageLoadAddress', KCSUBTYPE_TYPE.KC_ST_UINT32, 4, 0, 0), KCSubTypeElement('imageUUID', KCSUBTYPE_TYPE.KC_ST_UINT8, KCSubTypeElement.GetSizeForArray(16, 1), 4, 1) ), - 'dyld_load_info' + 'dyld_load_info', + legacy_size = 20 ) KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_SHAREDCACHE_LOADINFO')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_SHAREDCACHE_LOADINFO'), ( @@ -882,7 +889,7 @@ def _get_data_element(elementValues): ) KNOWN_TYPES_COLLECTION[0x33] = KCSubTypeElement('mach_absolute_time', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0, KCSubTypeElement._get_naked_element_value) -KNOWN_TYPES_COLLECTION[0x907] = KCSubTypeElement.FromBasicCtype('donating_pids', KCSUBTYPE_TYPE.KC_ST_INT32) +KNOWN_TYPES_COLLECTION[0x907] = KCSubTypeElement.FromBasicCtype('donating_pids', KCSUBTYPE_TYPE.KC_ST_INT32, legacy_size=4) KNOWN_TYPES_COLLECTION[GetTypeForName('KCDATA_TYPE_USECS_SINCE_EPOCH')] = KCSubTypeElement('usecs_since_epoch', KCSUBTYPE_TYPE.KC_ST_UINT64, 8, 0, 0, KCSubTypeElement._get_naked_element_value) @@ -890,7 +897,8 @@ def _get_data_element(elementValues): KCSubTypeElement.FromBasicCtype('lr', KCSUBTYPE_TYPE.KC_ST_UINT32), KCSubTypeElement.FromBasicCtype('sp', KCSUBTYPE_TYPE.KC_ST_UINT32, 4) ), - 'kernel_stack_frames' + 'kernel_stack_frames', + legacy_size = 8 ) KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_KERN_STACKLR')] = KCTypeDescription(GetTypeForName('STACKSHOT_KCTYPE_KERN_STACKLR'), ( @@ -916,7 +924,8 @@ def _get_data_element(elementValues): KCSubTypeElement.FromBasicCtype('lr', KCSUBTYPE_TYPE.KC_ST_UINT64), KCSubTypeElement.FromBasicCtype('sp', KCSUBTYPE_TYPE.KC_ST_UINT64, 8) ), - 'kernel_stack_frames' + 'kernel_stack_frames', + legacy_size = 16 ) KNOWN_TYPES_COLLECTION[GetTypeForName('STACKSHOT_KCTYPE_USER_STACKFRAME64')] = KCTypeDescription.FromKCTypeDescription( @@ -1281,7 +1290,7 @@ def formatWaitInfo(info): else: s += "unknown port" elif type == kThreadWaitSemaphore: - s += "semaphore port %x" % context + s += "semaphore port %x " % context if owner: s += "owned by pid %d" % owner else: @@ -1294,13 +1303,13 @@ def formatWaitInfo(info): s += "krwlock %x for upgrading" % context elif type == kThreadWaitUserLock: if owner: - s += "unfair lock %x owned by pid %d" % (context, owner) + s += "unfair lock %x owned by thread %d" % (context, owner) else: s += "spin lock %x" % context elif type == kThreadWaitPThreadMutex: s += "pthread mutex %x" % context if owner: - s += " owned by pid %d" % owner + s += " owned by thread %d" % owner else: s += " with unknown owner" elif type == kThreadWaitPThreadRWLockRead: @@ -1645,6 +1654,8 @@ def prettify(data): value = '%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X' % tuple(value) elif 'address' in key.lower() and isinstance(value, (int, long)): value = '0x%X' % value + elif key == 'thread_waitinfo': + value = map(formatWaitInfo, value) else: value = prettify(value); newdata[key] = value diff --git a/tools/lldbmacros/process.py b/tools/lldbmacros/process.py index 1010c6eb3..b86e1a80d 100755 --- a/tools/lldbmacros/process.py +++ b/tools/lldbmacros/process.py @@ -171,8 +171,6 @@ def GetASTSummary(ast): B - AST_BSD K - AST_KPERF M - AST_MACF - C - AST_CHUD - C - AST_CHUD_URGENT G - AST_GUARD T - AST_TELEMETRY_USER T - AST_TELEMETRY_KERNEL @@ -185,7 +183,7 @@ def GetASTSummary(ast): out_string = "" state = int(ast) thread_state_chars = {0x0:'', 0x1:'P', 0x2:'Q', 0x4:'U', 0x8:'H', 0x10:'Y', 0x20:'A', - 0x40:'L', 0x80:'B', 0x100:'K', 0x200:'M', 0x400:'C', 0x800:'C', + 0x40:'L', 0x80:'B', 0x100:'K', 0x200:'M', 0x1000:'G', 0x2000:'T', 0x4000:'T', 0x8000:'T', 0x10000:'S', 0x20000: 'D', 0x40000: 'I', 0x80000: 'E'} state_str = '' @@ -451,6 +449,14 @@ def GetResourceCoalitionSummary(coal, verbose=False): out_string += "\n\t total_tasks {0: +atm_diagnostic_flag: OTHER_CFLAGS += drop_priv.c + avx: INVALID_ARCHS = i386 avx: OTHER_CFLAGS += -mavx512f -mavx512bw -mavx512vl avx: OTHER_CFLAGS += -I$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders @@ -41,18 +43,20 @@ avx: CONFIG_FLAGS := $(filter-out -O%,$(CONFIG_FLAGS)) # Level 2 optimization must be used to prevent compiler from generating # invalid instructions when compiling with AVX-512 flags. avx: CONFIG_FLAGS += -O2 +# Disable vzeroupper insertion to work around rdar://problem/35035096 +avx: CONFIG_FLAGS += -mllvm -x86-use-vzeroupper=0 ifneq (osx,$(TARGET_NAME)) EXCLUDED_SOURCES += avx.c endif backtracing: OTHER_LDFLAGS += -framework CoreSymbolication -data_protection: OTHER_LDFLAGS += -framework IOKit +data_protection: OTHER_LDFLAGS += -ldarwintest_utils -framework IOKit kdebug: INVALID_ARCHS = i386 kdebug: OTHER_LDFLAGS = -framework ktrace -EXCLUDED_SOURCES += kperf_helpers.c xnu_quick_test_helpers.c +EXCLUDED_SOURCES += drop_priv.c kperf_helpers.c xnu_quick_test_helpers.c ifeq ($(PLATFORM),iPhoneOS) CONFIG_FREEZE_DEFINE:= -DCONFIG_FREEZE @@ -62,6 +66,7 @@ EXCLUDED_SOURCES += jumbo_va_spaces_28530648.c endif perf_compressor: OTHER_CFLAGS += $(CONFIG_FREEZE_DEFINE) +perf_compressor: OTHER_LDFLAGS += -ldarwintest_utils perf_compressor: CODE_SIGN_ENTITLEMENTS=./private_entitlement.plist stackshot: OTHER_LDFLAGS += -lkdd -framework Foundation @@ -119,9 +124,19 @@ stackshot_idle_25570396: OTHER_LDFLAGS += -lkdd -framework Foundation stackshot_block_owner_14362384: INVALID_ARCHS = i386 stackshot_block_owner_14362384: OTHER_LDFLAGS += -framework Foundation -lpthread -lkdd +ifeq ($(PLATFORM),MacOSX) +stackshot_block_owner_14362384: OTHER_LDFLAGS += -lpcre +endif + +all: $(DSTROOT)/usr/local/bin/kcdata + +$(DSTROOT)/usr/local/bin/kcdata: $(SRCROOT)/../../lldbmacros/kcdata.py + mkdir -p $(dir $@) + cp $< $@ + chmod a+x $@ xnu_quick_test: OTHER_CFLAGS += xnu_quick_test_helpers.c - + ifeq ($(PLATFORM),iPhoneOS) OTHER_TEST_TARGETS += jumbo_va_spaces_28530648_unentitled jumbo_va_spaces_28530648: CODE_SIGN_ENTITLEMENTS = jumbo_va_spaces_28530648.entitlements @@ -135,6 +150,9 @@ endif task_info_28439149: CODE_SIGN_ENTITLEMENTS = ./task_for_pid_entitlement.plist +proc_info: CODE_SIGN_ENTITLEMENTS = ./task_for_pid_entitlement.plist +proc_info: OTHER_LDFLAGS += -ldarwintest_utils + disk_mount_conditioner: disk_mount_conditioner* disk_mount_conditioner: CODE_SIGN_ENTITLEMENTS=./disk_mount_conditioner-entitlements.plist disk_mount_conditioner: OTHER_LDFLAGS += -ldarwintest_utils @@ -148,10 +166,24 @@ disk_mount_conditioner_unentitled: disk_mount_conditioner.c work_interval_test: CODE_SIGN_ENTITLEMENTS = work_interval_test.entitlements work_interval_test: OTHER_CFLAGS += -DENTITLED=1 +settimeofday_29193041: OTHER_CFLAGS += drop_priv.c + settimeofday_29193041_entitled: CODE_SIGN_ENTITLEMENTS = settimeofday_29193041.entitlements +settimeofday_29193041_entitled: OTHER_CFLAGS += drop_priv.c + thread_group_set_32261625: OTHER_LDFLAGS = -framework ktrace thread_group_set_32261625: INVALID_ARCHS = i386 task_info: CODE_SIGN_ENTITLEMENTS = task_for_pid_entitlement.plist +socket_bind_35243417: CODE_SIGN_ENTITLEMENTS = network_entitlements.plist +socket_bind_35685803: CODE_SIGN_ENTITLEMENTS = network_entitlements.plist + +ifneq (osx,$(TARGET_NAME)) +EXCLUDED_SOURCES += no32exec_35914211.c no32exec_35914211_helper.c +endif + +no32exec_35914211_helper: INVALID_ARCHS = x86_64 +no32exec_35914211: INVALID_ARCHS = i386 + include $(DEVELOPER_DIR)/AppleInternal/Makefiles/darwintest/Makefile.targets diff --git a/tools/tests/darwintests/atm_diagnostic_flag.c b/tools/tests/darwintests/atm_diagnostic_flag.c new file mode 100644 index 000000000..864ffd643 --- /dev/null +++ b/tools/tests/darwintests/atm_diagnostic_flag.c @@ -0,0 +1,78 @@ +#include + +#include +#include + +T_GLOBAL_META(T_META_NAMESPACE("xnu.debugging")); + +/* + * The low 8 bits may be in use, so modify one + * of the upper 8 bits to ensure round-tripping. + */ +#define LIBTRACE_PRIVATE_DATA 0x01000000 + +extern void drop_priv(void); + +static bool _needs_reset; +static uint32_t _original; + +static uint32_t +_save_atm_diagnostic_flag(void) +{ + kern_return_t kr; + kr = host_get_atm_diagnostic_flag(mach_host_self(), &_original); + T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "host_get_atm_diagnostic_flag()"); + T_LOG("Original ATM diagnostic flag: 0x%08x", _original); + return _original; +} + +static kern_return_t +_mutate_atm_diagnostic_flag(uint32_t v) +{ + T_LOG("Try to set ATM diagnostic flag to: 0x%08x", v); + kern_return_t kr = host_set_atm_diagnostic_flag(mach_host_self(), v); + if (kr == KERN_SUCCESS) _needs_reset = true; + return kr; +} + +static void +_reset_atm_diagnostic_flag(void) +{ + if (!_needs_reset) return; + T_LOG("Reset ATM diagnostic flag to: 0x%08x", _original); + kern_return_t kr; + kr = host_set_atm_diagnostic_flag(mach_host_self(), _original); + if (kr != KERN_SUCCESS) { + T_ASSERT_FAIL("host_set_atm_diagnostic_flag() failed: %s", + mach_error_string(kr)); + } +} + +T_DECL(toggle_atm_diagnostic_flag, + "change the atm_diagnostic_flag, which should use the commpage", + T_META_ASROOT(true)) +{ + T_ATEND(_reset_atm_diagnostic_flag); + uint32_t f = _save_atm_diagnostic_flag(); + f ^= LIBTRACE_PRIVATE_DATA; + kern_return_t kr = _mutate_atm_diagnostic_flag(f); + if (kr == KERN_NOT_SUPPORTED) { + T_SKIP("Seems ATM is disabled on this platform. " + "Ignoring host_set_atm_diagnostic_flag functionality. " + "Bailing gracefully."); + } + T_EXPECT_MACH_SUCCESS(kr, "Set atm_diagnostic_flag"); +} + +T_DECL(unprivileged_atm_diagnostic_flag, + "expect to fail to set the atm_diagnostic_flag", + T_META_ASROOT(false)) +{ + drop_priv(); + T_ATEND(_reset_atm_diagnostic_flag); + uint32_t f = _save_atm_diagnostic_flag(); + f ^= LIBTRACE_PRIVATE_DATA; + kern_return_t kr = _mutate_atm_diagnostic_flag(f); + T_EXPECT_MACH_ERROR(KERN_INVALID_ARGUMENT, kr, + "Deny change to atm_diagnostic_flag"); +} diff --git a/tools/tests/darwintests/data_protection.c b/tools/tests/darwintests/data_protection.c index 331c4809f..c9a69fee7 100644 --- a/tools/tests/darwintests/data_protection.c +++ b/tools/tests/darwintests/data_protection.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -577,10 +578,10 @@ setup(void) { T_SKIP("Data protection not supported on this system"); } - T_ASSERT_NE( + T_ASSERT_EQ( has_passcode(), - -1, - "No passcode set" + 0, + "Device should not have existing passcode" ); T_ASSERT_EQ( @@ -1043,55 +1044,32 @@ apple_key_store(uint32_t command, } /* - * Just a wrapper around fork/exec for separate - * cmds that may require entitlements. + * Helper function for launching tools */ int spawn_proc(char * const command[]) { - int child_result = -1; - int result = -1; - pid_t child = -1; - - T_LOG("Spawning %s", command[0]); - - child = fork(); - - if(child == -1) { - T_LOG("%s(%s): fork() failed", __func__, command[0]); + pid_t pid = 0; + int launch_tool_ret = 0; + bool waitpid_ret = true; + int status = 0; + int signal = 0; + int timeout = 30; + + launch_tool_ret = dt_launch_tool(&pid, command, false, NULL, NULL); + T_EXPECT_EQ(launch_tool_ret, 0, "launch tool: %s", command[0]); + if(launch_tool_ret != 0) { return 1; - } else if(child == 0) { - /* - * TODO: This keeps keystorectl from bombarding us with key - * state changes, but there must be a better way of doing - * this; killing stderr is a bit nasty, and if keystorectl - * fails, we want all the information we can get. - */ - fclose(stderr); - fclose(stdin); - - /* - * Use the first argument in 'command' array as the path to - * execute, as it could be invoking keystorectl OR keybagdTest - * depending on whether or not we need to apply a grace period. - * In the "lock" case we must use keybagdTest to ensure it's - * giving people the grace period. - */ - execv(command[0], command); - T_WITH_ERRNO; - T_ASSERT_FAIL("child failed to execv %s", command[0]); } - if(waitpid(child, &child_result, 0) != child) { - T_LOG( - "%s(%s): waitpid(%d) failed", - __func__, command[0], child - ); - return 1; - } else if(WEXITSTATUS(child_result)) { - T_LOG( - "%s(%s): child exited %d", - __func__, command[0], WEXITSTATUS(child_result) - ); + waitpid_ret = dt_waitpid(pid, &status, &signal, timeout); + T_EXPECT_TRUE(waitpid_ret, "%s should succeed", command[0]); + if(waitpid_ret == false) { + if(status != 0) { + T_LOG("%s exited %d", command[0], status); + } + if(signal != 0) { + T_LOG("%s received signal %d", command[0], signal); + } return 1; } diff --git a/tools/tests/darwintests/drop_priv.c b/tools/tests/darwintests/drop_priv.c new file mode 100644 index 000000000..7bb499c53 --- /dev/null +++ b/tools/tests/darwintests/drop_priv.c @@ -0,0 +1,59 @@ +#include + +#include +#include +#include +#include +#include +#include +#include + +#if !TARGET_OS_OSX +#include +#include +#include +#endif + +#if TARGET_OS_OSX +#define INVOKER_UID "SUDO_UID" +#define INVOKER_GID "SUDO_GID" +#define ID_MAX (unsigned long)UINT_MAX +static unsigned +_get_sudo_invoker(const char *var) +{ + char *value_str = getenv(var); + T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(value_str, + "Not running under sudo, getenv(\"%s\") failed", var); + T_QUIET; T_ASSERT_NE_CHAR(*value_str, '\0', + "getenv(\"%s\") returned an empty string", var); + + char *endp; + unsigned long value = strtoul(value_str, &endp, 10); + T_QUIET; T_WITH_ERRNO; T_ASSERT_EQ_CHAR(*endp, '\0', + "strtoul(\"%s\") not called on a valid number", value_str); + T_QUIET; T_WITH_ERRNO; T_ASSERT_NE_ULONG(value, ULONG_MAX, + "strtoul(\"%s\") overflow", value_str); + + T_QUIET; T_ASSERT_NE_ULONG(value, 0ul, "%s invalid", var); + T_QUIET; T_ASSERT_LT_ULONG(value, ID_MAX, "%s invalid", var); + return (unsigned)value; +} +#endif /* TARGET_OS_OSX */ + +void +drop_priv(void); +void +drop_priv(void) +{ +#if TARGET_OS_OSX + uid_t lower_uid = _get_sudo_invoker(INVOKER_UID); + gid_t lower_gid = _get_sudo_invoker(INVOKER_GID); +#else + struct passwd *pw = getpwnam("mobile"); + T_QUIET; T_WITH_ERRNO; T_ASSERT_NOTNULL(pw, "getpwnam(\"mobile\")"); + uid_t lower_uid = pw->pw_uid; + gid_t lower_gid = pw->pw_gid; +#endif + T_ASSERT_POSIX_SUCCESS(setgid(lower_gid), "Change group to %u", lower_gid); + T_ASSERT_POSIX_SUCCESS(setuid(lower_uid), "Change user to %u", lower_uid); +} diff --git a/tools/tests/darwintests/freebsd_waitpid_nohang.c b/tools/tests/darwintests/freebsd_waitpid_nohang.c new file mode 100644 index 000000000..9aa55e19e --- /dev/null +++ b/tools/tests/darwintests/freebsd_waitpid_nohang.c @@ -0,0 +1,62 @@ +/*- + * Copyright (c) 2016 Jilles Tjoelker + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#include +#include +#include + +T_DECL(waitpid_nohang, "FreeBSDarwin--waitpid_nohang") +{ + pid_t child, pid; + int status, r; + siginfo_t siginfo; + + child = fork(); + T_ASSERT_POSIX_SUCCESS(child, "child forked successfully"); + if (child == 0) { + sleep(10); + _exit(1); + } + + status = 42; + pid = waitpid(child, &status, WNOHANG); + T_ASSERT_POSIX_ZERO(pid, "waitpid call is successful"); + T_EXPECT_EQ(status, 42, "status is unaffected as expected"); + + r = kill(child, SIGTERM); + T_ASSERT_POSIX_ZERO(r, "signal sent successfully"); + r = waitid(P_PID, (id_t)child, &siginfo, WEXITED | WNOWAIT); + T_ASSERT_POSIX_SUCCESS(r, "waitid call successful"); + + status = -1; + pid = waitpid(child, &status, WNOHANG); + T_ASSERT_EQ(pid, child, "waitpid returns correct pid"); + T_EXPECT_EQ(WIFSIGNALED(status), true, "child was signaled"); + T_EXPECT_EQ(WTERMSIG(status), SIGTERM, "child was sent SIGTERM"); +} diff --git a/tools/tests/darwintests/jumbo_va_spaces_28530648.c b/tools/tests/darwintests/jumbo_va_spaces_28530648.c index eaf6745bb..aa081f3d8 100644 --- a/tools/tests/darwintests/jumbo_va_spaces_28530648.c +++ b/tools/tests/darwintests/jumbo_va_spaces_28530648.c @@ -15,7 +15,7 @@ * allocate at least this many GB of VA space. i.e. with the entitlement, n GB * must be allocatable; whereas without it, it must be less. */ -#define ALLOC_TEST_GB 12 +#define ALLOC_TEST_GB 54 T_DECL(jumbo_va_spaces_28530648, "Verify that the \"dynamic-codesigning\" entitlement is required to utilize an extra-large " diff --git a/tools/tests/darwintests/memorystatus_vm_map_fork.c b/tools/tests/darwintests/memorystatus_vm_map_fork.c new file mode 100644 index 000000000..dc92e5c11 --- /dev/null +++ b/tools/tests/darwintests/memorystatus_vm_map_fork.c @@ -0,0 +1,467 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +T_GLOBAL_META( + T_META_NAMESPACE("xnu.vm"), + T_META_CHECK_LEAKS(false) +); + +extern char **environ; + +/* + * This test file contains two sub-tests which attempt to verify + * the allowing or not allowing of a corpse for crashreporter when + * a task exceeds its memory allocation limit. vm_map_fork() is the + * kernel routine used to generate a corpse task. + * + * A corpse is allowed to be taken if a task's memory resource limit that + * is exceeded is less than 1/2 of the system wide task limit. + * If the amount exceeds 1/2 the sytem wide limit, then the corpse is disallowed. + * + * If the device under test is already under pressure, the test + * could fail due to jetsam cutting in and killing the parent, child or + * other necessary testing processes. + */ + +/* Test variants */ +#define TEST_ALLOWED 0x1 +#define TEST_NOT_ALLOWED 0x2 + +/* + * Values which the kernel OR's into the PID when a corpse + * is either allowed or disallowed for the + * kern.memorystatus_vm_map_fork_pidwatch sysctl. + */ +#define MEMORYSTATUS_VM_MAP_FORK_ALLOWED 0x100000000ul +#define MEMORYSTATUS_VM_MAP_FORK_NOT_ALLOWED 0x200000000ul + +/* + * The memory allocation happens in a child process, this + * is stuff to deal with creating and managing the child. + * The child will only execute the T_HELPER_DECL. + */ +static char testpath[PATH_MAX]; +static uint32_t testpath_size = sizeof(testpath); +#define LIMIT_DELTA_MB 5 /* an arbitrary limit delta */ +#define MEGABYTE (1024 * 1024) + +/* + * The child process communicates back to parent via an exit() code. + */ +enum child_exits { + NORMAL_EXIT = 0, + NO_MEMSIZE_ARG, + INVALID_MEMSIZE, + MALLOC_FAILED, + NUM_CHILD_EXIT +}; +static char *child_exit_why[] = { + "normal exit", + "no memsize argument to child", + "invalid memsize argument to child", + "malloc() failed", +}; + +/* + * Corpse collection only happens in development kernels. + * So we need this to detect if the test is relevant. + */ +static boolean_t +is_development_kernel(void) +{ + int ret; + int dev = 0; + size_t dev_size = sizeof(dev); + + ret = sysctlbyname("kern.development", &dev, &dev_size, NULL, 0); + if (ret != 0) { + return FALSE; + } + + return (dev != 0); +} + +/* + * Set/Get the sysctl used to determine if corpse collection occurs. + * This is done by the kernel checking for a specific PID. + */ +static void +set_memorystatus_vm_map_fork_pidwatch(pid_t pid) +{ + uint64_t new_value = (uint64_t)pid; + size_t new_len = sizeof(new_value); + int err; + + err = sysctlbyname("kern.memorystatus_vm_map_fork_pidwatch", NULL, NULL, &new_value, new_len); + T_QUIET; + T_ASSERT_POSIX_SUCCESS(err, "set sysctlbyname(kern.memorystatus_vm_map_fork_pidwatch...) failed"); + return; +} + +static uint64_t +get_memorystatus_vm_map_fork_pidwatch() +{ + uint64_t value = 0; + size_t val_len = sizeof(value); + int err; + + err = sysctlbyname("kern.memorystatus_vm_map_fork_pidwatch", &value, &val_len, NULL, 0); + T_QUIET; + T_ASSERT_POSIX_SUCCESS(err, "get sysctlbyname(kern.memorystatus_vm_map_fork_pidwatch...) failed"); + + return value; +} + +/* + * We want to avoid jetsam giving us bad results, if possible. So check if there's + * enough memory for the test to run, waiting briefly for some to free up. + */ +static void +wait_for_free_mem(int need_mb) +{ + int64_t memsize; + int memorystatus_level; + size_t size; + int64_t avail; + int err; + int try; + + /* + * get amount of memory in the machine + */ + size = sizeof(memsize); + err = sysctlbyname("hw.memsize", &memsize, &size, NULL, 0); + T_QUIET; T_ASSERT_POSIX_SUCCESS(err, "sysctlbyname(hw.memsize...) failed"); + + /* + * Use a loop to briefly sleep and recheck if short on memory. + */ + try = 1; + for (;;) { + + /* + * memorystatus_level is a percentage of memory available. For example 20 means 1/5 of memory. + * It currently doesn't exist on macOS but neither does jetsam, so pass the test there. + */ + size = sizeof(memorystatus_level); + if (sysctlbyname("kern.memorystatus_level", &memorystatus_level, &size, NULL, 0) != 0) + return; + T_QUIET; T_ASSERT_LE(memorystatus_level, 100, "memorystatus_level too high"); + T_QUIET; T_ASSERT_GT(memorystatus_level, 0, "memorystatus_level negative"); + + /* + * jetsam kicks in at memory status level of 15%, so subtract that much out of what's available. + */ + avail = MAX(0, (memsize * (memorystatus_level - 15)) / 100); + + /* + * We're good to go if there's more than enough available. + */ + if ((int64_t)need_mb * MEGABYTE < avail) + return; + + /* + * issue a message to log and sleep briefly to see if we can get more memory + */ + if (try-- == 0) + break; + T_LOG("Need %d MB, only %d MB available. sleeping 5 seconds for more to free. memorystatus_level %d", + need_mb, (int)(avail / MEGABYTE), memorystatus_level); + sleep(5); + } + T_SKIP("Needed %d MB, but only %d MB available. Skipping test to avoid jetsam issues.", + need_mb, (int)(avail / MEGABYTE)); +} + + +/* + * The main test calls this to spawn child process which will run and + * exceed some memory limit. The child is initially suspended so that + * we can do the sysctl calls before it runs. + * Since this is a libdarwintest, the "-n" names the T_HELPER_DECL() that + * we want to run. The arguments specific to the test follow a "--". + */ +static pid_t +spawn_child_process( + char * const executable, + char * const memlimit, + short flags, + int priority, + int active_limit_mb, + int inactive_limit_mb) +{ + posix_spawnattr_t spawn_attrs; + int err; + pid_t child_pid; + char * const argv_child[] = { executable, "-n", "child_process", "--", memlimit, NULL }; + + err = posix_spawnattr_init(&spawn_attrs); + T_QUIET; T_ASSERT_POSIX_SUCCESS(err, " posix_spawnattr_init() failed"); + + err = posix_spawnattr_setflags(&spawn_attrs, POSIX_SPAWN_START_SUSPENDED); + T_QUIET; T_ASSERT_POSIX_SUCCESS(err, " posix_spawnattr_setflags() failed"); + + err = posix_spawnattr_setjetsam_ext(&spawn_attrs, flags, priority, active_limit_mb, inactive_limit_mb); + T_QUIET; T_ASSERT_POSIX_SUCCESS(err, " posix_spawnattr_setjetsam_ext() failed"); + + err = posix_spawn(&child_pid, executable, NULL, &spawn_attrs, argv_child, environ); + T_QUIET; T_ASSERT_POSIX_SUCCESS(err, " posix_spawn() failed"); + + return child_pid; +} + + +/* + * The parent calls this to continue the suspended child, then wait for its result. + * We collect its resource usage to vefiry the expected amount allocated. + */ +static void +test_child_process(pid_t child_pid, int *status, struct rusage *ru) +{ + int err = 0; + pid_t got_pid; + + T_LOG(" continuing child[%d]\n", child_pid); + + err = kill(child_pid, SIGCONT); + T_QUIET; T_ASSERT_POSIX_SUCCESS(err, " kill(%d, SIGCONT) failed", child_pid); + + T_LOG(" waiting for child[%d] to exit", child_pid); + + got_pid = wait4(child_pid, status, 0, ru); + T_QUIET; T_ASSERT_EQ(child_pid, got_pid, " wait4(%d, ...) returned %d", child_pid, got_pid); +} + +/* + * The child process executes this code. The easiest way, with given darwintest infrastructure, + * it has to return information is via exit status. + */ +T_HELPER_DECL(child_process, "child allocates memory to failure") +{ +#define BYTESPERALLOC MEGABYTE +#define BYTESINEXCESS (2 * MEGABYTE) /* 2 MB - arbitrary */ + char *limit; + long limit_mb = 0; + long max_bytes_to_munch, bytes_remaining, bytes_this_munch; + void *mem = NULL; + + /* + * This helper is run in a child process. The helper sees one argument + * as a string which is the amount of memory in megabytes to allocate. + */ + if (argc != 1) + exit(NO_MEMSIZE_ARG); + + limit = argv[0]; + errno = 0; + limit_mb = strtol(limit, NULL, 10); + if (errno != 0 || limit_mb <= 0) + exit(INVALID_MEMSIZE); + + /* Compute in excess of assigned limit */ + max_bytes_to_munch = limit_mb * MEGABYTE; + max_bytes_to_munch += BYTESINEXCESS; + + for (bytes_remaining = max_bytes_to_munch; bytes_remaining > 0; bytes_remaining -= bytes_this_munch) { + bytes_this_munch = MIN(bytes_remaining, BYTESPERALLOC); + + mem = malloc((size_t)bytes_this_munch); + if (mem == NULL) + exit(MALLOC_FAILED); + arc4random_buf(mem, (size_t)bytes_this_munch); + } + + /* We chewed up all the memory we were asked to. */ + exit(NORMAL_EXIT); +} + + +/* + * Actual test body. + */ +static void +memorystatus_vm_map_fork_parent(int test_variant) +{ + int max_task_pmem = 0; /* MB */ + size_t size = 0; + int active_limit_mb = 0; + int inactive_limit_mb = 0; + short flags = 0; + char memlimit_str[16]; + pid_t child_pid; + int child_status; + uint64_t kernel_pidwatch_val; + uint64_t expected_pidwatch_val; + int ret; + struct rusage ru; + enum child_exits exit_val; + + /* + * The code to set/get the pidwatch sysctl is only in + * development kernels. Skip the test if not on one. + */ + if (!is_development_kernel()) { + T_SKIP("Can't test on release kernel"); + } + + /* + * Determine a memory limit based on system having one or not. + */ + size = sizeof(max_task_pmem); + (void)sysctlbyname("kern.max_task_pmem", &max_task_pmem, &size, NULL, 0); + if (max_task_pmem <= 0) + max_task_pmem = 0; + + if (test_variant == TEST_ALLOWED) { + + /* + * Tell the child to allocate less than 1/2 the system wide limit. + */ + if (max_task_pmem / 2 - LIMIT_DELTA_MB <= 0) { + active_limit_mb = LIMIT_DELTA_MB; + } else { + active_limit_mb = max_task_pmem / 2 - LIMIT_DELTA_MB; + } + expected_pidwatch_val = MEMORYSTATUS_VM_MAP_FORK_ALLOWED; + + } else { /* TEST_NOT_ALLOWED */ + + /* + * Tell the child to allocate more than 1/2 the system wide limit. + */ + active_limit_mb = (max_task_pmem / 2) + LIMIT_DELTA_MB; + if (max_task_pmem == 0) { + expected_pidwatch_val = MEMORYSTATUS_VM_MAP_FORK_ALLOWED; + } else { + expected_pidwatch_val = MEMORYSTATUS_VM_MAP_FORK_NOT_ALLOWED; + } + + } + inactive_limit_mb = active_limit_mb; + T_LOG("using limit of %d Meg", active_limit_mb); + + /* + * When run as part of a larger suite, a previous test + * may have left the system temporarily with too little + * memory to run this test. We try to detect if there is + * enough free memory to proceed, waiting a little bit + * for memory to free up. + */ + wait_for_free_mem(active_limit_mb); + +#if defined(__x86_64__) + /* + * vm_map_fork() is always allowed on desktop. + */ + expected_pidwatch_val = MEMORYSTATUS_VM_MAP_FORK_ALLOWED; +#endif + + /* + * Prepare the arguments needed to spawn the child process. + */ + memset (memlimit_str, 0, sizeof(memlimit_str)); + (void)sprintf(memlimit_str, "%d", active_limit_mb); + + ret = _NSGetExecutablePath(testpath, &testpath_size); + T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "_NSGetExecutablePath(%s, ...)", testpath); + + /* + * We put the child process in FOREGROUND to try and keep jetsam's hands off it. + */ + child_pid = spawn_child_process(testpath, memlimit_str, flags, + JETSAM_PRIORITY_FOREGROUND, active_limit_mb, inactive_limit_mb); + + expected_pidwatch_val |= (uint64_t)child_pid; + + /* + * We only reach here if parent successfully spawned child process. + */ + T_LOG(" spawned child_pid[%d] with memlimit %s (%d)MB\n", + child_pid, memlimit_str, active_limit_mb); + + /* + * Set the kernel's pidwatch to look for the child. + */ + (void)set_memorystatus_vm_map_fork_pidwatch((pid_t)0); + (void)set_memorystatus_vm_map_fork_pidwatch(child_pid); + + /* + * Let the child run and wait for it to finish. + */ + test_child_process(child_pid, &child_status, &ru); + T_LOG("Child exited with max_rss of %ld", ru.ru_maxrss); + + /* + * Retrieve the kernel's pidwatch value. This should now indicate + * if the corpse was allowed or not. + */ + kernel_pidwatch_val = get_memorystatus_vm_map_fork_pidwatch(); + (void)set_memorystatus_vm_map_fork_pidwatch((pid_t)0); + + /* + * If the child died abnormally, the test is invalid. + */ + if (!WIFEXITED(child_status)) { + if (WIFSIGNALED(child_status)) { + /* jetsam kills a process with SIGKILL */ + if (WTERMSIG(child_status) == SIGKILL) + T_LOG("Child appears to have been a jetsam victim"); + T_SKIP("Child terminated by signal %d test result invalid", WTERMSIG(child_status)); + } + T_SKIP("child did not exit normally (status=%d) test result invalid", child_status); + } + + /* + * We don't expect the child to exit for any other reason than success + */ + exit_val = (enum child_exits)WEXITSTATUS(child_status); + T_QUIET; T_ASSERT_EQ(exit_val, NORMAL_EXIT, "child exit due to: %s", + (0 < exit_val && exit_val < NUM_CHILD_EXIT) ? child_exit_why[exit_val] : "unknown"); + + /* + * If the kernel aborted generating a corpse for other reasons, the test is invalid. + */ + if (kernel_pidwatch_val == -1ull) { + T_SKIP("corpse generation was aborted by kernel"); + } + + /* + * We should always have made it through the vm_map_fork() checks in the kernel for this test. + */ + T_QUIET; T_ASSERT_NE_ULLONG(kernel_pidwatch_val, (uint64_t)child_pid, "child didn't trigger corpse generation"); + + T_EXPECT_EQ(kernel_pidwatch_val, expected_pidwatch_val, "kernel value 0x%llx - expected 0x%llx", + kernel_pidwatch_val, expected_pidwatch_val); +} + +/* + * The order of these 2 test functions is important. They will be executed by the test framwork in order. + * + * We test "not allowed first", then "allowed". If it were the other way around, the corpse from the "allowed" + * test would likely cause memory pressure and jetsam would likely kill the "not allowed" test. + */ +T_DECL(memorystatus_vm_map_fork_test_not_allowed, "test that corpse generation was not allowed") +{ + memorystatus_vm_map_fork_parent(TEST_NOT_ALLOWED); +} + +T_DECL(memorystatus_vm_map_fork_test_allowed, "test corpse generation allowed") +{ + + memorystatus_vm_map_fork_parent(TEST_ALLOWED); +} diff --git a/tools/tests/darwintests/memorystatus_zone_test.c b/tools/tests/darwintests/memorystatus_zone_test.c index 1d0223a15..f652725bb 100644 --- a/tools/tests/darwintests/memorystatus_zone_test.c +++ b/tools/tests/darwintests/memorystatus_zone_test.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -21,25 +22,29 @@ T_GLOBAL_META( T_META_CHECK_LEAKS(false) ); -#define TIMEOUT_SECS 1500 +#define TIMEOUT_SECS 1500 #if TARGET_OS_EMBEDDED -#define ALLOCATION_SIZE_VM_REGION (16*1024) /* 16 KB */ -#define ALLOCATION_SIZE_VM_OBJECT ALLOCATION_SIZE_VM_REGION +#define ALLOCATION_SIZE_VM_REGION (16*1024) /* 16 KB */ +#define ALLOCATION_SIZE_VM_OBJECT ALLOCATION_SIZE_VM_REGION #else -#define ALLOCATION_SIZE_VM_REGION (1024*1024*100) /* 100 MB */ -#define ALLOCATION_SIZE_VM_OBJECT (16*1024) /* 16 KB */ +#define ALLOCATION_SIZE_VM_REGION (1024*1024*100) /* 100 MB */ +#define ALLOCATION_SIZE_VM_OBJECT (16*1024) /* 16 KB */ #endif -#define MAX_CHILD_PROCS 100 +#define MAX_CHILD_PROCS 100 -#define ZONEMAP_JETSAM_LIMIT_SYSCTL "kern.zone_map_jetsam_limit=60" +#define ZONEMAP_JETSAM_LIMIT_SYSCTL "kern.zone_map_jetsam_limit=60" -#define VME_ZONE_TEST_OPT "allocate_vm_regions" -#define VM_OBJECTS_ZONE_TEST_OPT "allocate_vm_objects" -#define GENERIC_ZONE_TEST_OPT "allocate_from_generic_zone" +#define VME_ZONE_TEST_OPT "allocate_vm_regions" +#define VM_OBJECTS_ZONE_TEST_OPT "allocate_vm_objects" +#define GENERIC_ZONE_TEST_OPT "allocate_from_generic_zone" -#define VM_TAG1 100 -#define VM_TAG2 101 +#define VME_ZONE "VM map entries" +#define VMOBJECTS_ZONE "vm objects" +#define VMENTRY_TO_VMOBJECT_COMPARISON_RATIO 98 + +#define VM_TAG1 100 +#define VM_TAG2 101 enum { VME_ZONE_TEST = 0, @@ -47,13 +52,26 @@ enum { GENERIC_ZONE_TEST, }; -static int current_test_index = 0; +typedef struct test_config_struct { + int test_index; + int num_zones; + const char *helper_func; + mach_zone_name_array_t zone_names; +} test_config_struct; + +static test_config_struct current_test; static int num_children = 0; static bool test_ending = false; -static bool within_dispatch_source_handler = false; +static bool within_dispatch_signal_handler = false; +static bool within_dispatch_timer_handler = false; static dispatch_source_t ds_signal = NULL; +static dispatch_source_t ds_timer = NULL; static ktrace_session_t session = NULL; +static mach_zone_info_array_t zone_info_array = NULL; +static mach_zone_name_t largest_zone_name; +static mach_zone_info_t largest_zone_info; + static char testpath[PATH_MAX]; static pid_t child_pids[MAX_CHILD_PROCS]; static pthread_mutex_t test_ending_mtx; @@ -64,9 +82,19 @@ static void allocate_from_generic_zone(void); static void cleanup_and_end_test(void); static void setup_ktrace_session(void); static void spawn_child_process(void); -static void run_test_for_zone(int index); +static void run_test(void); +static bool verify_generic_jetsam_criteria(void); +static bool vme_zone_compares_to_vm_objects(void); +static void print_zone_map_size(void); +static void query_zone_info(void); +static void print_zone_info(mach_zone_name_t *zn, mach_zone_info_t *zi); extern void mach_zone_force_gc(host_t host); +extern kern_return_t mach_zone_info_for_largest_zone( + host_priv_t host, + mach_zone_name_t *name, + mach_zone_info_t *info +); static void allocate_vm_regions(void) { @@ -144,6 +172,76 @@ static void allocate_from_generic_zone(void) } } +static void print_zone_info(mach_zone_name_t *zn, mach_zone_info_t *zi) +{ + T_LOG("ZONE NAME: %-35sSIZE: %-25lluELEMENTS: %llu", + zn->mzn_name, zi->mzi_cur_size, zi->mzi_count); +} + +static void query_zone_info(void) +{ + int i; + kern_return_t kr; + static uint64_t num_calls = 0; + + for (i = 0; i < current_test.num_zones; i++) { + kr = mach_zone_info_for_zone(mach_host_self(), current_test.zone_names[i], &(zone_info_array[i])); + T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "mach_zone_info_for_zone(%s) returned %d [%s]", current_test.zone_names[i].mzn_name, kr, mach_error_string(kr)); + } + kr = mach_zone_info_for_largest_zone(mach_host_self(), &largest_zone_name, &largest_zone_info); + T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "mach_zone_info_for_largest_zone returned %d [%s]", kr, mach_error_string(kr)); + + num_calls++; + if (num_calls % 10 != 0) { + return; + } + + /* Print out size and element count for zones relevant to the test */ + for (i = 0; i < current_test.num_zones; i++) { + print_zone_info(&(current_test.zone_names[i]), &(zone_info_array[i])); + } +} + +static bool vme_zone_compares_to_vm_objects(void) +{ + int i; + uint64_t vm_object_element_count = 0, vm_map_entry_element_count = 0; + + T_LOG("Comparing element counts of \"VM map entries\" and \"vm objects\" zones"); + for (i = 0; i < current_test.num_zones; i++) { + if (!strcmp(current_test.zone_names[i].mzn_name, VME_ZONE)) { + vm_map_entry_element_count = zone_info_array[i].mzi_count; + } else if (!strcmp(current_test.zone_names[i].mzn_name, VMOBJECTS_ZONE)) { + vm_object_element_count = zone_info_array[i].mzi_count; + } + print_zone_info(&(current_test.zone_names[i]), &(zone_info_array[i])); + } + + T_LOG("# VM map entries as percentage of # vm objects = %llu", (vm_map_entry_element_count * 100)/ vm_object_element_count); + if (vm_map_entry_element_count >= ((vm_object_element_count * VMENTRY_TO_VMOBJECT_COMPARISON_RATIO) / 100)) { + T_LOG("Number of VM map entries is comparable to vm objects\n\n"); + return true; + } + T_LOG("Number of VM map entries is NOT comparable to vm objects\n\n"); + return false; +} + +static bool verify_generic_jetsam_criteria(void) +{ + T_LOG("Largest zone info"); + print_zone_info(&largest_zone_name, &largest_zone_info); + + /* If VM map entries is not the largest zone */ + if (strcmp(largest_zone_name.mzn_name, VME_ZONE)) { + /* If vm objects is the largest zone and the VM map entries zone had comparable # of elements, return false */ + if (!strcmp(largest_zone_name.mzn_name, VMOBJECTS_ZONE) && vme_zone_compares_to_vm_objects()) { + return false; + } + return true; + } + return false; +} + static void cleanup_and_end_test(void) { int i; @@ -163,8 +261,13 @@ static void cleanup_and_end_test(void) T_LOG("Number of processes spawned: %d", num_children); T_LOG("Cleaning up..."); + /* Disable the timer that queries and prints zone info periodically */ + if (ds_timer != NULL && !within_dispatch_timer_handler) { + dispatch_source_cancel(ds_timer); + } + /* Disable signal handler that spawns child processes, only if we're not in the event handler's context */ - if (ds_signal != NULL && !within_dispatch_source_handler) { + if (ds_signal != NULL && !within_dispatch_signal_handler) { dispatch_source_cancel_and_wait(ds_signal); } @@ -187,6 +290,10 @@ static void cleanup_and_end_test(void) if (session != NULL) { ktrace_end(session, 1); } + + for (i = 0; i < current_test.num_zones; i++) { + print_zone_info(&(current_test.zone_names[i]), &(zone_info_array[i])); + } } static void setup_ktrace_session(void) @@ -197,6 +304,8 @@ static void setup_ktrace_session(void) session = ktrace_session_create(); T_QUIET; T_ASSERT_NOTNULL(session, "ktrace_session_create"); + ktrace_set_interactive(session); + ktrace_set_completion_handler(session, ^{ ktrace_session_destroy(session); T_END; @@ -209,11 +318,17 @@ static void setup_ktrace_session(void) /* We don't care about jetsams for any other reason except zone-map-exhaustion */ if (event->arg2 == kMemorystatusKilledZoneMapExhaustion) { - T_LOG("[memorystatus_do_kill] jetsam reason: zone-map-exhaustion, pid: %lu", event->arg1); - if (current_test_index == VME_ZONE_TEST || current_test_index == VM_OBJECTS_ZONE_TEST) { + cleanup_and_end_test(); + T_LOG("[memorystatus_do_kill] jetsam reason: zone-map-exhaustion, pid: %lu\n\n", event->arg1); + if (current_test.test_index == VME_ZONE_TEST || current_test.test_index == VM_OBJECTS_ZONE_TEST) { /* * For the VM map entries zone we try to kill the leaking process. * Verify that we jetsammed one of the processes we spawned. + * + * For the vm objects zone we pick the leaking process via the VM map entries + * zone, if the number of vm objects and VM map entries are comparable. + * The test simulates this scenario, we should see a targeted jetsam for the + * vm objects zone too. */ for (i = 0; i < num_children; i++) { if (child_pids[i] == (pid_t)event->arg1) { @@ -221,12 +336,18 @@ static void setup_ktrace_session(void) break; } } + /* + * If we didn't see a targeted jetsam, verify that the largest zone actually + * fulfilled the criteria for generic jetsams. + */ + if (!received_jetsam_event && verify_generic_jetsam_criteria()) { + received_jetsam_event = true; + } } else { received_jetsam_event = true; } - T_ASSERT_TRUE(received_jetsam_event, "Received jetsam event as expected"); - cleanup_and_end_test(); + T_ASSERT_TRUE(received_jetsam_event, "Received zone-map-exhaustion jetsam event as expected"); } }); T_QUIET; T_ASSERT_POSIX_ZERO(ret, "ktrace_events_single"); @@ -235,26 +356,32 @@ static void setup_ktrace_session(void) T_QUIET; T_ASSERT_POSIX_ZERO(ret, "ktrace_start"); } +static void print_zone_map_size(void) +{ + int ret; + uint64_t zstats[2]; + size_t zstats_size = sizeof(zstats); + + ret = sysctlbyname("kern.zone_map_size_and_capacity", &zstats, &zstats_size, NULL, 0); + T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "sysctl kern.zone_map_size_and_capacity failed"); + + T_LOG("Zone map capacity: %-30lldZone map size: %lld [%lld%% full]", zstats[1], zstats[0], (zstats[0] * 100)/zstats[1]); +} + static void spawn_child_process(void) { pid_t pid = -1; + char helper_func[50]; char *launch_tool_args[4]; - within_dispatch_source_handler = true; T_QUIET; T_ASSERT_LT(num_children, MAX_CHILD_PROCS, "Spawned %d children. Timing out...", MAX_CHILD_PROCS); + strlcpy(helper_func, current_test.helper_func, sizeof(helper_func)); launch_tool_args[0] = testpath; launch_tool_args[1] = "-n"; + launch_tool_args[2] = helper_func; launch_tool_args[3] = NULL; - if (current_test_index == VME_ZONE_TEST) { - launch_tool_args[2] = VME_ZONE_TEST_OPT; - } else if (current_test_index == VM_OBJECTS_ZONE_TEST) { - launch_tool_args[2] = VM_OBJECTS_ZONE_TEST_OPT; - } else if (current_test_index == GENERIC_ZONE_TEST) { - launch_tool_args[2] = GENERIC_ZONE_TEST_OPT; - } - /* Spawn the child process */ int rc = dt_launch_tool(&pid, launch_tool_args, false, NULL, NULL); if (rc != 0) { @@ -263,30 +390,50 @@ static void spawn_child_process(void) T_QUIET; T_ASSERT_POSIX_SUCCESS(pid, "dt_launch_tool"); child_pids[num_children++] = pid; - within_dispatch_source_handler = false; } -static void run_test_for_zone(int index) +static void run_test(void) { - int ret, dev; - size_t dev_size = sizeof(dev); - uint32_t testpath_buf_size = sizeof(testpath); + uint64_t mem; + uint32_t testpath_buf_size, pages; + int ret, dev, pgsz; + size_t sysctl_size; T_ATEND(cleanup_and_end_test); T_SETUPBEGIN; - current_test_index = index; - - ret = sysctlbyname("kern.development", &dev, &dev_size, NULL, 0); + dev = 0; + sysctl_size = sizeof(dev); + ret = sysctlbyname("kern.development", &dev, &sysctl_size, NULL, 0); T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "sysctl kern.development failed"); if (dev == 0) { T_SKIP("Skipping test on release kernel"); } + testpath_buf_size = sizeof(testpath); ret = _NSGetExecutablePath(testpath, &testpath_buf_size); T_QUIET; T_ASSERT_POSIX_ZERO(ret, "_NSGetExecutablePath"); T_LOG("Executable path: %s", testpath); + sysctl_size = sizeof(mem); + ret = sysctlbyname("hw.memsize", &mem, &sysctl_size, NULL, 0); + T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "sysctl hw.memsize failed"); + T_LOG("hw.memsize: %llu", mem); + + sysctl_size = sizeof(pgsz); + ret = sysctlbyname("vm.pagesize", &pgsz, &sysctl_size, NULL, 0); + T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "sysctl vm.pagesize failed"); + T_LOG("vm.pagesize: %d", pgsz); + + sysctl_size = sizeof(pages); + ret = sysctlbyname("vm.pages", &pages, &sysctl_size, NULL, 0); + T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "sysctl vm.pages failed"); + T_LOG("vm.pages: %d", pages); + + zone_info_array = (mach_zone_info_array_t) calloc((unsigned long)current_test.num_zones, sizeof *zone_info_array); + + print_zone_map_size(); + /* * If the timeout specified by T_META_TIMEOUT is hit, the atend handler does not get called. * So we're queueing a dispatch block to fire after TIMEOUT_SECS seconds, so we can exit cleanly. @@ -302,15 +449,31 @@ static void run_test_for_zone(int index) */ signal(SIGUSR1, SIG_IGN); ds_signal = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGUSR1, 0, dispatch_get_main_queue()); - T_QUIET; T_ASSERT_NOTNULL(ds_signal, "dispatch_source_create"); + T_QUIET; T_ASSERT_NOTNULL(ds_signal, "dispatch_source_create: signal"); dispatch_source_set_event_handler(ds_signal, ^{ + within_dispatch_signal_handler = true; + print_zone_map_size(); + /* Wait a few seconds before spawning another child. Keeps us from allocating too aggressively */ sleep(5); spawn_child_process(); + within_dispatch_signal_handler = false; }); dispatch_activate(ds_signal); + /* Timer to query jetsam-relevant zone info every second. Print it every 10 seconds. */ + ds_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_queue_create("timer_queue", NULL)); + T_QUIET; T_ASSERT_NOTNULL(ds_timer, "dispatch_source_create: timer"); + dispatch_source_set_timer(ds_timer, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC), NSEC_PER_SEC, 0); + + dispatch_source_set_event_handler(ds_timer, ^{ + within_dispatch_timer_handler = true; + query_zone_info(); + within_dispatch_timer_handler = false; + }); + dispatch_activate(ds_timer); + /* Set up a ktrace session to listen for jetsam events */ setup_ktrace_session(); @@ -323,17 +486,7 @@ static void run_test_for_zone(int index) dispatch_main(); } -T_HELPER_DECL(allocate_vm_regions, "allocates VM regions") -{ - allocate_vm_regions(); -} - -T_HELPER_DECL(allocate_vm_objects, "allocates VM objects and VM regions") -{ - allocate_vm_objects(); -} - -T_HELPER_DECL(allocate_from_generic_zone, "allocates from a generic zone") +static void move_to_idle_band(void) { memorystatus_priority_properties_t props; @@ -341,6 +494,8 @@ T_HELPER_DECL(allocate_from_generic_zone, "allocates from a generic zone") * We want to move the processes we spawn into the idle band, so that jetsam can target them first. * This prevents other important BATS tasks from getting killed, specially in LTE where we have very few * processes running. + * + * This is only needed for tests which (are likely to) lead us down the generic jetsam path. */ props.priority = JETSAM_PRIORITY_IDLE; props.user_data = 0; @@ -349,7 +504,22 @@ T_HELPER_DECL(allocate_from_generic_zone, "allocates from a generic zone") printf("memorystatus call to change jetsam priority failed\n"); exit(-1); } +} + +T_HELPER_DECL(allocate_vm_regions, "allocates VM regions") +{ + allocate_vm_regions(); +} + +T_HELPER_DECL(allocate_vm_objects, "allocates VM objects and VM regions") +{ + move_to_idle_band(); + allocate_vm_objects(); +} +T_HELPER_DECL(allocate_from_generic_zone, "allocates from a generic zone") +{ + move_to_idle_band(); allocate_from_generic_zone(); } @@ -367,7 +537,15 @@ T_DECL( memorystatus_vme_zone_test, */ T_META_SYSCTL_INT(ZONEMAP_JETSAM_LIMIT_SYSCTL)) { - run_test_for_zone(VME_ZONE_TEST); + current_test = (test_config_struct) { + .test_index = VME_ZONE_TEST, + .helper_func = VME_ZONE_TEST_OPT, + .num_zones = 1, + .zone_names = (mach_zone_name_t []){ + { .mzn_name = VME_ZONE } + } + }; + run_test(); } T_DECL( memorystatus_vm_objects_zone_test, @@ -378,7 +556,16 @@ T_DECL( memorystatus_vm_objects_zone_test, */ T_META_SYSCTL_INT(ZONEMAP_JETSAM_LIMIT_SYSCTL)) { - run_test_for_zone(VM_OBJECTS_ZONE_TEST); + current_test = (test_config_struct) { + .test_index = VM_OBJECTS_ZONE_TEST, + .helper_func = VM_OBJECTS_ZONE_TEST_OPT, + .num_zones = 2, + .zone_names = (mach_zone_name_t []){ + { .mzn_name = VME_ZONE }, + { .mzn_name = VMOBJECTS_ZONE} + } + }; + run_test(); } T_DECL( memorystatus_generic_zone_test, @@ -389,5 +576,11 @@ T_DECL( memorystatus_generic_zone_test, */ T_META_SYSCTL_INT(ZONEMAP_JETSAM_LIMIT_SYSCTL)) { - run_test_for_zone(GENERIC_ZONE_TEST); + current_test = (test_config_struct) { + .test_index = GENERIC_ZONE_TEST, + .helper_func = GENERIC_ZONE_TEST_OPT, + .num_zones = 0, + .zone_names = NULL + }; + run_test(); } diff --git a/tools/tests/darwintests/net_tun_pr_35136664.c b/tools/tests/darwintests/net_tun_pr_35136664.c new file mode 100644 index 000000000..366f066bd --- /dev/null +++ b/tools/tests/darwintests/net_tun_pr_35136664.c @@ -0,0 +1,63 @@ + +#include +#include +#include +#include + +#include +#include + +#include +#include + +T_GLOBAL_META(T_META_NAMESPACE("xnu.net")); + +T_DECL(PR_35136664_utun, + "This bind a utun and close it without connecting") +{ + int tunsock; + struct ctl_info kernctl_info; + struct sockaddr_ctl kernctl_addr; + + T_ASSERT_POSIX_SUCCESS(tunsock = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL), NULL); + + memset(&kernctl_info, 0, sizeof(kernctl_info)); + strlcpy(kernctl_info.ctl_name, UTUN_CONTROL_NAME, sizeof(kernctl_info.ctl_name)); + T_ASSERT_POSIX_ZERO(ioctl(tunsock, CTLIOCGINFO, &kernctl_info), NULL); + + memset(&kernctl_addr, 0, sizeof(kernctl_addr)); + kernctl_addr.sc_len = sizeof(kernctl_addr); + kernctl_addr.sc_family = AF_SYSTEM; + kernctl_addr.ss_sysaddr = AF_SYS_CONTROL; + kernctl_addr.sc_id = kernctl_info.ctl_id; + kernctl_addr.sc_unit = 0; + + T_ASSERT_POSIX_ZERO(bind(tunsock, (struct sockaddr *)&kernctl_addr, sizeof(kernctl_addr)), NULL); + + T_ASSERT_POSIX_ZERO(close(tunsock), NULL); +} + +T_DECL(PR_35136664_ipsec, + "This bind a ipsec and close it without connecting") +{ + int tunsock; + struct ctl_info kernctl_info; + struct sockaddr_ctl kernctl_addr; + + T_ASSERT_POSIX_SUCCESS(tunsock = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL), NULL); + + memset(&kernctl_info, 0, sizeof(kernctl_info)); + strlcpy(kernctl_info.ctl_name, IPSEC_CONTROL_NAME, sizeof(kernctl_info.ctl_name)); + T_ASSERT_POSIX_ZERO(ioctl(tunsock, CTLIOCGINFO, &kernctl_info), NULL); + + memset(&kernctl_addr, 0, sizeof(kernctl_addr)); + kernctl_addr.sc_len = sizeof(kernctl_addr); + kernctl_addr.sc_family = AF_SYSTEM; + kernctl_addr.ss_sysaddr = AF_SYS_CONTROL; + kernctl_addr.sc_id = kernctl_info.ctl_id; + kernctl_addr.sc_unit = 0; + + T_ASSERT_POSIX_ZERO(bind(tunsock, (struct sockaddr *)&kernctl_addr, sizeof(kernctl_addr)), NULL); + + T_ASSERT_POSIX_ZERO(close(tunsock), NULL); +} diff --git a/tools/tests/darwintests/net_tuntests.c b/tools/tests/darwintests/net_tuntests.c new file mode 100644 index 000000000..6b5fd97b8 --- /dev/null +++ b/tools/tests/darwintests/net_tuntests.c @@ -0,0 +1,544 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include // for SK_FEATURE_* + +T_GLOBAL_META(T_META_NAMESPACE("xnu.net.tun")); + +#if 0 +static void +log_hexdump(const void *inp, size_t len) +{ + unsigned i, off = 0; + char buf[9+16*3+1]; + for (i = 0; i < len; i++) { + if (i % 16 == 0) + off = (unsigned)snprintf(buf, sizeof(buf), "%08x:", i); + off += (unsigned)snprintf(buf+off, sizeof(buf)-off, " %02x", (((const uint8_t *)inp)[i]) & 0xff); + if (i % 16 == 15) + T_LOG("%s", buf); + } + if (len % 16) + T_LOG("%s", buf); +} +#endif + +static uint64_t +get_skywalk_features(void) +{ + uint64_t features = 0; + size_t len = sizeof(features); + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(sysctlbyname("kern.skywalk.features", &features, &len, NULL, 0), NULL); + T_QUIET; T_ASSERT_EQ(len, sizeof(features), NULL); + T_QUIET; T_ASSERT_TRUE(features & SK_FEATURE_SKYWALK, NULL); + return features; +} + +static bool g_is_ipsec_test; +static bool g_is_utun_test; +static int g_OPT_ENABLE_NETIF = -1; +static int g_OPT_ENABLE_FLOWSWITCH = -1; +static int g_OPT_ENABLE_CHANNEL = -1; +static int g_OPT_GET_CHANNEL_UUID = -1; +static int g_OPT_IFNAME = -1; +static char *g_CONTROL_NAME = NULL; + +static void +setup_ipsec_test(void) +{ + T_LOG("Configuring for ipsec tests"); + g_OPT_ENABLE_NETIF = IPSEC_OPT_ENABLE_NETIF; + g_OPT_ENABLE_FLOWSWITCH = IPSEC_OPT_ENABLE_FLOWSWITCH; + g_OPT_ENABLE_CHANNEL = IPSEC_OPT_ENABLE_CHANNEL; + g_OPT_GET_CHANNEL_UUID = IPSEC_OPT_GET_CHANNEL_UUID; + g_OPT_IFNAME = IPSEC_OPT_IFNAME; + g_CONTROL_NAME = IPSEC_CONTROL_NAME; + g_is_ipsec_test = true; +} + +static void +setup_utun_test(void) +{ + T_LOG("Configuring for utun tests"); + g_OPT_ENABLE_NETIF = UTUN_OPT_ENABLE_NETIF; + g_OPT_ENABLE_FLOWSWITCH = UTUN_OPT_ENABLE_FLOWSWITCH; + g_OPT_ENABLE_CHANNEL = UTUN_OPT_ENABLE_CHANNEL; + g_OPT_GET_CHANNEL_UUID = UTUN_OPT_GET_CHANNEL_UUID; + g_OPT_IFNAME = UTUN_OPT_IFNAME; + g_CONTROL_NAME = UTUN_CONTROL_NAME; + g_is_utun_test = true; +} + +static void +check_enables(int tunsock, int enable_netif, int enable_flowswitch, int enable_channel, uuid_t uuid) +{ + int scratch; + socklen_t scratchlen, uuidlen; + uuid_t scratchuuid; + if (!uuid) { + uuid = scratchuuid; + } + + //T_LOG("checking tunsock %d", tunsock); + + scratchlen = sizeof(scratch); + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_NETIF, + &scratch, &scratchlen), NULL); + T_QUIET; T_EXPECT_EQ_ULONG((unsigned long )scratchlen, sizeof(scratch), NULL); + T_QUIET; T_EXPECT_EQ(scratch, enable_netif, NULL); + + scratchlen = sizeof(scratch); + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_FLOWSWITCH, + &scratch, &scratchlen), NULL); + T_QUIET; T_EXPECT_EQ_ULONG((unsigned long )scratchlen, sizeof(scratch), NULL); + if (get_skywalk_features() & SK_FEATURE_NETNS) { + if (enable_netif) { + T_QUIET; T_EXPECT_EQ(scratch, enable_flowswitch, NULL); + } else { + T_QUIET; T_EXPECT_EQ(scratch, 0, NULL); + } + } else { + T_QUIET; T_EXPECT_EQ(scratch, 0, NULL); + } + + scratchlen = sizeof(scratch); + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_CHANNEL, + &scratch, &scratchlen), NULL); + T_QUIET; T_EXPECT_EQ_ULONG((unsigned long )scratchlen, sizeof(scratch), NULL); + if (g_is_ipsec_test && !enable_netif) { + T_QUIET; T_EXPECT_EQ(scratch, 0, NULL); + } else { + T_QUIET; T_EXPECT_EQ(scratch, enable_channel, NULL); + } + + if (scratch) { + uuid_clear(uuid); + uuidlen = sizeof(uuid_t); + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_GET_CHANNEL_UUID, + uuid, &uuidlen), NULL); + T_QUIET; T_EXPECT_EQ_ULONG((unsigned long )uuidlen, sizeof(uuid_t), NULL); + T_QUIET; T_EXPECT_FALSE(uuid_is_null(uuid), NULL); + } else { + uuid_clear(uuid); + uuidlen = sizeof(uuid_t); + T_QUIET; T_EXPECT_POSIX_FAILURE(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_GET_CHANNEL_UUID, + uuid, &uuidlen), ENXIO, NULL); + T_QUIET; T_EXPECT_EQ_ULONG((unsigned long )uuidlen, sizeof(uuid_t), NULL); + T_QUIET; T_EXPECT_TRUE(uuid_is_null(uuid), NULL); + } +} + +static void +tunsock_get_ifname(int s, char ifname[IFXNAMSIZ]) +{ + socklen_t optlen = IFXNAMSIZ; + T_QUIET; T_WITH_ERRNO; T_ASSERT_POSIX_ZERO(getsockopt(s, SYSPROTO_CONTROL, g_OPT_IFNAME, ifname, &optlen), NULL); + T_QUIET; T_ASSERT_TRUE(optlen > 0, NULL); + T_QUIET; T_ASSERT_TRUE(ifname[optlen-1] == '\0', NULL); + T_QUIET; T_ASSERT_TRUE(strlen(ifname)+1 == optlen, "got ifname \"%s\" len %zd expected %u", ifname, strlen(ifname), optlen); +} + +static short +ifnet_get_flags(int s, const char ifname[IFNAMSIZ]) +{ + struct ifreq ifr; + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr), NULL); + return ifr.ifr_flags; +} + +static void +ifnet_add_addr4(const char ifname[IFNAMSIZ], struct in_addr *addr, struct in_addr *mask, struct in_addr *broadaddr) +{ + struct sockaddr_in *sin; + struct in_aliasreq ifra; + int s; + + T_QUIET; T_EXPECT_POSIX_SUCCESS(s = socket(AF_INET, SOCK_DGRAM, 0), NULL); + + memset(&ifra, 0, sizeof(ifra)); + strlcpy(ifra.ifra_name, ifname, sizeof(ifra.ifra_name)); + + if (addr != NULL) { + sin = &ifra.ifra_addr; + sin->sin_len = sizeof(*sin); + sin->sin_family = AF_INET; + sin->sin_addr = *addr; + } + + if (mask != NULL) { + sin = &ifra.ifra_mask; + sin->sin_len = sizeof(*sin); + sin->sin_family = AF_INET; + sin->sin_addr = *mask; + } + + if (broadaddr != NULL || (addr != NULL && + (ifnet_get_flags(s, ifname) & IFF_POINTOPOINT) != 0)) { + sin = &ifra.ifra_broadaddr; + sin->sin_len = sizeof(*sin); + sin->sin_family = AF_INET; + sin->sin_addr = (broadaddr != NULL) ? *broadaddr : *addr; + } + + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(ioctl(s, SIOCAIFADDR, &ifra), NULL); + + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(s), NULL); +} + +static int g_pfkeyso = -1; +static struct in_addr g_addr1, g_addr2; + +static void +create_sa(const char ifname[IFXNAMSIZ], uint8_t type, uint32_t spi, struct in_addr *src, struct in_addr *dst) +{ + if (g_pfkeyso == -1) { + T_QUIET; T_EXPECT_POSIX_SUCCESS(g_pfkeyso = socket(PF_KEY, SOCK_RAW, PF_KEY_V2), NULL); + } + + /* + + */ + + struct { + struct sadb_msg msg __attribute((aligned(sizeof (uint64_t)))); + struct sadb_key key __attribute((aligned(sizeof (uint64_t)))); + struct sadb_sa sa __attribute((aligned(sizeof (uint64_t)))); + struct sadb_x_sa2 sa2 __attribute((aligned(sizeof (uint64_t)))); + struct sadb_x_ipsecif ipsecif __attribute((aligned(sizeof (uint64_t)))); + struct { + struct sadb_address addr __attribute((aligned(sizeof (uint64_t)))); + struct sockaddr_in saddr __attribute((aligned(sizeof (uint64_t)))); + } src; + struct { + struct sadb_address addr __attribute((aligned(sizeof (uint64_t)))); + struct sockaddr_in saddr __attribute((aligned(sizeof (uint64_t)))); + } dst; + } addcmd; + + memset(&addcmd, 0, sizeof(addcmd)); + + addcmd.msg.sadb_msg_version = PF_KEY_V2; + addcmd.msg.sadb_msg_type = type; + addcmd.msg.sadb_msg_errno = 0; + addcmd.msg.sadb_msg_satype = SADB_SATYPE_ESP; + addcmd.msg.sadb_msg_len = PFKEY_UNIT64(sizeof(addcmd)); + addcmd.msg.sadb_msg_reserved = 0; + addcmd.msg.sadb_msg_seq = 0; + addcmd.msg.sadb_msg_pid = (unsigned)getpid(); + + addcmd.key.sadb_key_len = PFKEY_UNIT64(sizeof(addcmd.key)); + addcmd.key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT; + addcmd.key.sadb_key_bits = 0; + addcmd.key.sadb_key_reserved = 0; + + addcmd.sa.sadb_sa_len = PFKEY_UNIT64(sizeof(addcmd.sa)); + addcmd.sa.sadb_sa_exttype = SADB_EXT_SA; + addcmd.sa.sadb_sa_spi = htonl(spi); + addcmd.sa.sadb_sa_replay = 0; + addcmd.sa.sadb_sa_state = 0; + addcmd.sa.sadb_sa_auth = SADB_AALG_NONE; + addcmd.sa.sadb_sa_encrypt = SADB_EALG_NULL; + addcmd.sa.sadb_sa_flags = SADB_X_EXT_CYCSEQ; + + addcmd.sa2.sadb_x_sa2_len = PFKEY_UNIT64(sizeof(addcmd.sa2)); + addcmd.sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2; + addcmd.sa2.sadb_x_sa2_mode = IPSEC_MODE_ANY; + addcmd.sa2.sadb_x_sa2_alwaysexpire = 1; + addcmd.sa2.sadb_x_sa2_flags = SADB_X_EXT_SA2_DELETE_ON_DETACH; + addcmd.sa2.sadb_x_sa2_sequence = 0; + addcmd.sa2.sadb_x_sa2_reqid = 0; + + addcmd.ipsecif.sadb_x_ipsecif_len = PFKEY_UNIT64(sizeof(addcmd.ipsecif)); + addcmd.ipsecif.sadb_x_ipsecif_exttype = SADB_X_EXT_IPSECIF; + memset(addcmd.ipsecif.sadb_x_ipsecif_internal_if, 0, sizeof(addcmd.ipsecif.sadb_x_ipsecif_internal_if)); + memset(addcmd.ipsecif.sadb_x_ipsecif_outgoing_if, 0, sizeof(addcmd.ipsecif.sadb_x_ipsecif_outgoing_if)); + strlcpy(addcmd.ipsecif.sadb_x_ipsecif_ipsec_if, ifname, sizeof(addcmd.ipsecif.sadb_x_ipsecif_ipsec_if)); + addcmd.ipsecif.sadb_x_ipsecif_init_disabled = 0; + addcmd.ipsecif.reserved = 0; + + addcmd.src.addr.sadb_address_len = PFKEY_UNIT64(sizeof(addcmd.src)); + addcmd.src.addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC; + addcmd.src.addr.sadb_address_proto = IPSEC_ULPROTO_ANY; + addcmd.src.addr.sadb_address_prefixlen = sizeof(struct in_addr) << 3; //XXX Why? + addcmd.src.addr.sadb_address_reserved = 0; + addcmd.src.saddr.sin_len = sizeof(addcmd.src.saddr); + addcmd.src.saddr.sin_family = AF_INET; + addcmd.src.saddr.sin_port = htons(0); + addcmd.src.saddr.sin_addr = *src; + + addcmd.dst.addr.sadb_address_len = PFKEY_UNIT64(sizeof(addcmd.dst)); + addcmd.dst.addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST; + addcmd.dst.addr.sadb_address_proto = IPSEC_ULPROTO_ANY; + addcmd.dst.addr.sadb_address_prefixlen = sizeof(struct in_addr) << 3; //XXX Why? + addcmd.dst.addr.sadb_address_reserved = 0; + addcmd.dst.saddr.sin_len = sizeof(addcmd.dst.saddr); + addcmd.dst.saddr.sin_family = AF_INET; + addcmd.dst.saddr.sin_port = htons(0); + addcmd.dst.saddr.sin_addr = *dst; + + //log_hexdump(&addcmd, sizeof(addcmd)); + + ssize_t slen; + T_QUIET; T_EXPECT_POSIX_SUCCESS(slen = send(g_pfkeyso, &addcmd, sizeof(addcmd), 0), NULL); + T_QUIET; T_EXPECT_EQ(slen, (ssize_t)sizeof(addcmd), NULL); +} + +/* Unfortunately, connect can return EBUSY due to: + * Always return EBUSY if interface with the same name is in delayed detach even if the unique ID is different. + * + * We should fix that so we don't return EBUSY when we aren't + * requesting a specific interface name, but until then workaround it + * in the test. + */ + +static int +try_connect(int socket, const struct sockaddr *address, socklen_t address_len) +{ + int ret; + while (1) { + ret = connect(socket, address, address_len); + if (ret != -1 || errno != EBUSY) + return ret; + sleep(1); + } +} + +static int +create_tunsock(int enable_netif, int enable_flowswitch, int enable_channel) +{ + int tunsock; + struct ctl_info kernctl_info; + struct sockaddr_ctl kernctl_addr; + uuid_t uuid; + socklen_t uuidlen; + + T_QUIET; T_EXPECT_POSIX_SUCCESS(tunsock = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL), NULL); + + memset(&kernctl_info, 0, sizeof(kernctl_info)); + strlcpy(kernctl_info.ctl_name, g_CONTROL_NAME, sizeof(kernctl_info.ctl_name)); + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(ioctl(tunsock, CTLIOCGINFO, &kernctl_info), NULL); + + memset(&kernctl_addr, 0, sizeof(kernctl_addr)); + kernctl_addr.sc_len = sizeof(kernctl_addr); + kernctl_addr.sc_family = AF_SYSTEM; + kernctl_addr.ss_sysaddr = AF_SYS_CONTROL; + kernctl_addr.sc_id = kernctl_info.ctl_id; + kernctl_addr.sc_unit = 0; + + //T_LOG("enable_netif = %d, enable_flowswitch = %d, enable_channel = %d", + //enable_netif, enable_channel, enable_flowswitch); + + T_QUIET; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_NETIF, + &enable_netif, sizeof(enable_netif)), EINVAL, NULL); + T_QUIET; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_FLOWSWITCH, + &enable_flowswitch, sizeof(enable_flowswitch)), EINVAL, NULL); + T_QUIET; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_CHANNEL, + &enable_channel, sizeof(enable_channel)), EINVAL, NULL); + uuid_clear(uuid); + uuidlen = sizeof(uuid_t); + T_QUIET; T_EXPECT_POSIX_FAILURE(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_GET_CHANNEL_UUID, + uuid, &uuidlen), EINVAL, NULL); + T_QUIET; T_EXPECT_EQ_ULONG((unsigned long )uuidlen, sizeof(uuid_t), NULL); + T_QUIET; T_EXPECT_TRUE(uuid_is_null(uuid), NULL); + + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(bind(tunsock, (struct sockaddr *)&kernctl_addr, sizeof(kernctl_addr)), NULL); + + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_NETIF, + &enable_netif, sizeof(enable_netif)), NULL); + T_QUIET; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_FLOWSWITCH, + &enable_flowswitch, sizeof(enable_flowswitch)), EINVAL, NULL); + T_QUIET; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_CHANNEL, + &enable_channel, sizeof(enable_channel)), EINVAL, NULL); + uuid_clear(uuid); + uuidlen = sizeof(uuid_t); + T_QUIET; T_EXPECT_POSIX_FAILURE(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_GET_CHANNEL_UUID, + uuid, &uuidlen), ENXIO, NULL); + T_QUIET; T_EXPECT_EQ_ULONG((unsigned long )uuidlen, sizeof(uuid_t), NULL); + T_QUIET; T_EXPECT_TRUE(uuid_is_null(uuid), NULL); + + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(try_connect(tunsock, (struct sockaddr *)&kernctl_addr, sizeof(kernctl_addr)), NULL); + + T_QUIET; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_NETIF, + &enable_netif, sizeof(enable_netif)), EINVAL, NULL); + + if (get_skywalk_features() & SK_FEATURE_NETNS) { + if (enable_netif) { + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_FLOWSWITCH, + &enable_flowswitch, sizeof(enable_flowswitch)), NULL); + } else { + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_FLOWSWITCH, + &enable_flowswitch, sizeof(enable_flowswitch)), ENOENT, NULL); + } + } else { + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_FLOWSWITCH, + &enable_flowswitch, sizeof(enable_flowswitch)), ENOTSUP, NULL); + } + + if (enable_channel) { + if (g_is_ipsec_test && !enable_netif) { + /* ipsec doesn't support channels without a netif */ + T_QUIET; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_CHANNEL, + &enable_channel, sizeof(enable_channel)), EOPNOTSUPP, NULL); + uuid_clear(uuid); + uuidlen = sizeof(uuid_t); + T_QUIET; T_EXPECT_POSIX_FAILURE(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_GET_CHANNEL_UUID, + uuid, &uuidlen), ENXIO, NULL); + T_QUIET; T_EXPECT_EQ_ULONG((unsigned long )uuidlen, sizeof(uuid_t), NULL); + T_QUIET; T_EXPECT_TRUE(uuid_is_null(uuid), NULL); + } else { + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_CHANNEL, + &enable_channel, sizeof(enable_channel)), NULL); + uuid_clear(uuid); + uuidlen = sizeof(uuid_t); + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_GET_CHANNEL_UUID, + uuid, &uuidlen), NULL); + T_QUIET; T_EXPECT_EQ_ULONG((unsigned long )uuidlen, sizeof(uuid_t), NULL); + T_QUIET; T_EXPECT_FALSE(uuid_is_null(uuid), NULL); + } + } else { + T_QUIET; T_EXPECT_POSIX_FAILURE(setsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_ENABLE_CHANNEL, + &enable_channel, sizeof(enable_channel)), ENXIO, NULL); + uuid_clear(uuid); + uuidlen = sizeof(uuid_t); + T_QUIET; T_EXPECT_POSIX_FAILURE(getsockopt(tunsock, SYSPROTO_CONTROL, g_OPT_GET_CHANNEL_UUID, + uuid, &uuidlen), ENXIO, NULL); + T_QUIET; T_EXPECT_EQ_ULONG((unsigned long )uuidlen, sizeof(uuid_t), NULL); + T_QUIET; T_EXPECT_TRUE(uuid_is_null(uuid), NULL); + } + + check_enables(tunsock, enable_netif, enable_flowswitch, enable_channel, uuid); + + //T_LOG("Returning tunsock %d", tunsock); + + return tunsock; +} + +#if 0 +static void +ipsec_stats(void) +{ + struct ifmibdata ifmd; + + len = sizeof(struct ifmibdata); + name[3] = IFMIB_IFDATA; + name[4] = interesting_row; + name[5] = IpFDATA_GENERAL; + if (sysctl(name, 6, &ifmd, &len, (void *)0, 0) == -1) + err(1, "sysctl IFDATA_GENERAL %d", interesting_row); +} +#endif + +static void +permute_enables(void) +{ + int tunsock; + T_EXPECT_GE(tunsock = create_tunsock(false, false, false), 0, NULL); + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(tunsock), NULL); + T_EXPECT_GE(tunsock = create_tunsock(false, false, true), 0, NULL); + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(tunsock), NULL); + T_EXPECT_GE(tunsock = create_tunsock(false, true, false), 0, NULL); + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(tunsock), NULL); + T_EXPECT_GE(tunsock = create_tunsock(false, true, true), 0, NULL); + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(tunsock), NULL); + T_EXPECT_GE(tunsock = create_tunsock(true, false, false), 0, NULL); + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(tunsock), NULL); + T_EXPECT_GE(tunsock = create_tunsock(true, false, true), 0, NULL); + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(tunsock), NULL); + T_EXPECT_GE(tunsock = create_tunsock(true, true, false), 0, NULL); + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(tunsock), NULL); + T_EXPECT_GE(tunsock = create_tunsock(true, true, true), 0, NULL); + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(tunsock), NULL); +} + +T_DECL(ipsec_enables, "This test checks combinations of netif/channel/flowswitch on ipsec") +{ + setup_ipsec_test(); + permute_enables(); +} + +T_DECL(utun_enables, "This test checks combinations of netif/channel/flowswitch on utun") +{ + setup_utun_test(); + permute_enables(); +} + +static int g_tunsock = -1; + +static void +cleanup_tunsock(void) +{ + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(g_tunsock), NULL); + T_QUIET; T_EXPECT_POSIX_FAILURE(close(g_tunsock), EBADF, NULL); + if (g_is_ipsec_test) { + T_QUIET; T_WITH_ERRNO; T_EXPECT_POSIX_ZERO(close(g_pfkeyso), NULL); + T_QUIET; T_EXPECT_POSIX_FAILURE(close(g_pfkeyso), EBADF, NULL); + } +} + +static void +setup_tunsock(void) +{ + T_ASSERT_GE(g_tunsock = create_tunsock(true, false, true), 0, NULL); + T_ATEND(cleanup_tunsock); + + char ifname[IFXNAMSIZ]; + tunsock_get_ifname(g_tunsock, ifname); + + T_LOG("Created interface %s", ifname); + + uint32_t ifaddr = (10 << 24) | ((unsigned)getpid()&0xffff) << 8 | 160; + struct in_addr mask; + g_addr1.s_addr = htonl(ifaddr); + g_addr2.s_addr = htonl(ifaddr+1); + mask.s_addr = htonl(0xffffffff); + + ifnet_add_addr4(ifname, &g_addr1, &mask, &g_addr2); + + if (g_is_ipsec_test) { + create_sa(ifname, SADB_ADD, 12345, &g_addr1, &g_addr2); + create_sa(ifname, SADB_ADD, 12346, &g_addr2, &g_addr1); + } +} + +T_DECL(setup_ipsec, "This test sets up an ipsec interface") +{ + setup_ipsec_test(); + setup_tunsock(); +} + +T_DECL(setup_utun, "This test sets up a utun interface") +{ + setup_utun_test(); + setup_tunsock(); +} diff --git a/tools/tests/darwintests/netbsd_utimensat.c b/tools/tests/darwintests/netbsd_utimensat.c index 87f0657d1..c14f92a6f 100644 --- a/tools/tests/darwintests/netbsd_utimensat.c +++ b/tools/tests/darwintests/netbsd_utimensat.c @@ -45,8 +45,8 @@ __RCSID("$NetBSD: t_utimensat.c,v 1.6 2017/01/10 15:13:56 christos Exp $"); #include #include -#define DIR "dir" -#define FILE "dir/utimensat" +#define DIRPATH "dir" +#define FILEPATH "dir/utimensat" #define BASEFILE "utimensat" #define LINK "dir/symlink" #define BASELINK "symlink" @@ -63,9 +63,16 @@ static void chtmpdir(void) T_ASSERT_POSIX_ZERO(chdir(dt_tmpdir()), NULL); // dt_tmpdir() should guarantee a clean directory for each run - unlink(FILE); + unlink(FILEPATH); unlink(LINK); - rmdir(DIR); + rmdir(DIRPATH); + + // Skip the test if the current working directory is not on APFS. + struct statfs sfs = { 0 }; + T_QUIET; T_ASSERT_POSIX_SUCCESS(statfs(".", &sfs), NULL); + if (memcmp(&sfs.f_fstypename[0], "apfs", strlen("apfs")) != 0) { + T_SKIP("utimensat is APFS-only, but working directory is non-APFS"); + } T_SETUPEND; } @@ -78,15 +85,15 @@ T_DECL(netbsd_utimensat_fd, "See that utimensat works with fd") int fd; struct stat st; - T_ASSERT_POSIX_ZERO(mkdir(DIR, 0755), NULL); - T_ASSERT_POSIX_SUCCESS((fd = open(FILE, O_CREAT|O_RDWR, 0644)), NULL); + T_ASSERT_POSIX_ZERO(mkdir(DIRPATH, 0755), NULL); + T_ASSERT_POSIX_SUCCESS((fd = open(FILEPATH, O_CREAT|O_RDWR, 0644)), NULL); T_ASSERT_POSIX_ZERO(close(fd), NULL); - T_ASSERT_POSIX_SUCCESS((dfd = open(DIR, O_RDONLY, 0)), NULL); + T_ASSERT_POSIX_SUCCESS((dfd = open(DIRPATH, O_RDONLY, 0)), NULL); T_ASSERT_POSIX_ZERO(utimensat(dfd, BASEFILE, tptr, 0), NULL); T_ASSERT_POSIX_ZERO(close(dfd), NULL); - T_ASSERT_POSIX_ZERO(stat(FILE, &st), NULL); + T_ASSERT_POSIX_ZERO(stat(FILEPATH, &st), NULL); T_ASSERT_EQ(st.st_atimespec.tv_sec, tptr[0].tv_sec, NULL); T_ASSERT_EQ(st.st_atimespec.tv_nsec, tptr[0].tv_nsec, NULL); T_ASSERT_EQ(st.st_mtimespec.tv_sec, tptr[1].tv_sec, NULL); @@ -100,11 +107,11 @@ T_DECL(netbsd_utimensat_fdcwd, "See that utimensat works with fd as AT_FDCWD") int fd; struct stat st; - T_ASSERT_POSIX_ZERO(mkdir(DIR, 0755), NULL); - T_ASSERT_POSIX_SUCCESS((fd = open(FILE, O_CREAT|O_RDWR, 0644)), NULL); + T_ASSERT_POSIX_ZERO(mkdir(DIRPATH, 0755), NULL); + T_ASSERT_POSIX_SUCCESS((fd = open(FILEPATH, O_CREAT|O_RDWR, 0644)), NULL); T_ASSERT_POSIX_ZERO(close(fd), NULL); - T_ASSERT_POSIX_ZERO(chdir(DIR), NULL); + T_ASSERT_POSIX_ZERO(chdir(DIRPATH), NULL); T_ASSERT_POSIX_ZERO(utimensat(AT_FDCWD, BASEFILE, tptr, 0), NULL); T_ASSERT_POSIX_ZERO(stat(BASEFILE, &st), NULL); @@ -118,7 +125,7 @@ T_DECL(netbsd_utimensat_fdcwderr, "See that utimensat fails with fd as AT_FDCWD { chtmpdir(); - T_ASSERT_POSIX_ZERO(mkdir(DIR, 0755), NULL); + T_ASSERT_POSIX_ZERO(mkdir(DIRPATH, 0755), NULL); T_ASSERT_EQ(utimensat(AT_FDCWD, FILEERR, tptr, 0), -1, NULL); } @@ -128,8 +135,8 @@ T_DECL(netbsd_utimensat_fderr1, "See that utimensat fail with bad path") int dfd; - T_ASSERT_POSIX_ZERO(mkdir(DIR, 0755), NULL); - T_ASSERT_POSIX_SUCCESS((dfd = open(DIR, O_RDONLY, 0)), NULL); + T_ASSERT_POSIX_ZERO(mkdir(DIRPATH, 0755), NULL); + T_ASSERT_POSIX_SUCCESS((dfd = open(DIRPATH, O_RDONLY, 0)), NULL); T_ASSERT_EQ(utimensat(dfd, FILEERR, tptr, 0), -1, NULL); T_ASSERT_POSIX_ZERO(close(dfd), NULL); } @@ -142,8 +149,8 @@ T_DECL(netbsd_utimensat_fderr2, "See that utimensat fails with bad fdat") int fd; char cwd[MAXPATHLEN]; - T_ASSERT_POSIX_ZERO(mkdir(DIR, 0755), NULL); - T_ASSERT_POSIX_SUCCESS((fd = open(FILE, O_CREAT|O_RDWR, 0644)), NULL); + T_ASSERT_POSIX_ZERO(mkdir(DIRPATH, 0755), NULL); + T_ASSERT_POSIX_SUCCESS((fd = open(FILEPATH, O_CREAT|O_RDWR, 0644)), NULL); T_ASSERT_POSIX_ZERO(close(fd), NULL); T_ASSERT_POSIX_SUCCESS((dfd = open(getcwd(cwd, MAXPATHLEN), O_RDONLY, 0)), NULL); @@ -157,11 +164,11 @@ T_DECL(netbsd_utimensat_fderr3, "See that utimensat fails with fd as -1") int fd; - T_ASSERT_POSIX_ZERO(mkdir(DIR, 0755), NULL); - T_ASSERT_POSIX_SUCCESS((fd = open(FILE, O_CREAT|O_RDWR, 0644)), NULL); + T_ASSERT_POSIX_ZERO(mkdir(DIRPATH, 0755), NULL); + T_ASSERT_POSIX_SUCCESS((fd = open(FILEPATH, O_CREAT|O_RDWR, 0644)), NULL); T_ASSERT_POSIX_ZERO(close(fd), NULL); - T_ASSERT_EQ(utimensat(-1, FILE, tptr, 0), -1, NULL); + T_ASSERT_EQ(utimensat(-1, FILEPATH, tptr, 0), -1, NULL); } T_DECL(netbsd_utimensat_fdlink, "See that utimensat works on symlink") @@ -171,10 +178,10 @@ T_DECL(netbsd_utimensat_fdlink, "See that utimensat works on symlink") int dfd; struct stat st; - T_ASSERT_POSIX_ZERO(mkdir(DIR, 0755), NULL); - T_ASSERT_POSIX_ZERO(symlink(FILE, LINK), NULL); /* NB: FILE does not exists */ + T_ASSERT_POSIX_ZERO(mkdir(DIRPATH, 0755), NULL); + T_ASSERT_POSIX_ZERO(symlink(FILEPATH, LINK), NULL); /* NB: FILE does not exists */ - T_ASSERT_POSIX_SUCCESS((dfd = open(DIR, O_RDONLY, 0)), NULL); + T_ASSERT_POSIX_SUCCESS((dfd = open(DIRPATH, O_RDONLY, 0)), NULL); T_ASSERT_EQ(utimensat(dfd, BASELINK, tptr, 0), -1, NULL); T_ASSERT_EQ(errno, ENOENT, NULL); diff --git a/tools/tests/darwintests/network_entitlements.plist b/tools/tests/darwintests/network_entitlements.plist new file mode 100644 index 000000000..c326c8341 --- /dev/null +++ b/tools/tests/darwintests/network_entitlements.plist @@ -0,0 +1,10 @@ + + + + + com.apple.security.network.client + + com.apple.security.network.server + + + diff --git a/tools/tests/darwintests/no32exec_35914211.c b/tools/tests/darwintests/no32exec_35914211.c new file mode 100644 index 000000000..ea36703aa --- /dev/null +++ b/tools/tests/darwintests/no32exec_35914211.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include +#include + +T_DECL(no32exec_bootarg, "make sure the no32exec boot-arg is honored", T_META_BOOTARGS_SET("-no32exec")) +{ + int spawn_ret, pid; + char path[1024]; + uint32_t size = sizeof(path); + + T_ASSERT_EQ(_NSGetExecutablePath(path, &size), 0, NULL); + T_ASSERT_LT(strlcat(path, "_helper", size), size, NULL); + + spawn_ret = posix_spawn(&pid, path, NULL, NULL, NULL, NULL); + if (spawn_ret == 0) { + int wait_ret = 0; + waitpid(pid, &wait_ret, 0); + T_ASSERT_FALSE(WIFEXITED(wait_ret), "i386 helper should not run"); + } + T_ASSERT_EQ(spawn_ret, EBADARCH, NULL); +} diff --git a/tools/tests/darwintests/no32exec_35914211_helper.c b/tools/tests/darwintests/no32exec_35914211_helper.c new file mode 100644 index 000000000..99fb6be2f --- /dev/null +++ b/tools/tests/darwintests/no32exec_35914211_helper.c @@ -0,0 +1,6 @@ +#include + +T_DECL(null_test, "nothing to see here") +{ + T_SKIP("nothing to see here"); +} diff --git a/tools/tests/darwintests/perf_compressor.c b/tools/tests/darwintests/perf_compressor.c index b0c6fa112..1d3b23d2c 100644 --- a/tools/tests/darwintests/perf_compressor.c +++ b/tools/tests/darwintests/perf_compressor.c @@ -1,13 +1,13 @@ +#include +#include +#include +#include + #ifdef T_NAMESPACE #undef T_NAMESPACE #endif #include - -#include -#include -#include -#include -#include +#include T_GLOBAL_META( T_META_NAMESPACE("xnu.vm.perf"), @@ -21,12 +21,38 @@ enum { TYPICAL }; +#define CREATE_LIST(X) \ + X(SUCCESS) \ + X(TOO_FEW_ARGUMENTS) \ + X(SYSCTL_VM_PAGESIZE_FAILED) \ + X(VM_PAGESIZE_IS_ZERO) \ + X(UNKNOWN_PAGE_TYPE) \ + X(DISPATCH_SOURCE_CREATE_FAILED) \ + X(INITIAL_SIGNAL_TO_PARENT_FAILED) \ + X(SIGNAL_TO_PARENT_FAILED) \ + X(EXIT_CODE_MAX) + +#define EXIT_CODES_ENUM(VAR) VAR, +enum exit_codes_num { + CREATE_LIST(EXIT_CODES_ENUM) +}; + +#define EXIT_CODES_STRING(VAR) #VAR, +static const char *exit_codes_str[] = { + CREATE_LIST(EXIT_CODES_STRING) +}; + + +static pid_t pid = -1; +static dt_stat_t r; +static dt_stat_time_t s; + void allocate_zero_pages(char **buf, int num_pages, int vmpgsize); void allocate_mostly_zero_pages(char **buf, int num_pages, int vmpgsize); void allocate_random_pages(char **buf, int num_pages, int vmpgsize); void allocate_representative_pages(char **buf, int num_pages, int vmpgsize); -void allocate_pages(int size_mb, int page_type); void run_compressor_test(int size_mb, int page_type); +void freeze_helper_process(void); void allocate_zero_pages(char **buf, int num_pages, int vmpgsize) { int i; @@ -68,26 +94,158 @@ void allocate_representative_pages(char **buf, int num_pages, int vmpgsize) { val = 0; for (i = 0; i < vmpgsize; i += 16) { memset(&buf[j][i], val, 16); - if (i < 3700 * (vmpgsize / 4096)) { + if (i < 3400 * (vmpgsize / 4096)) { val++; } } } } -void allocate_pages(int size_mb, int page_type) { - int num_pages = 0; - int vmpgsize, i, j; - char **buf; +void freeze_helper_process(void) { + int ret; + int64_t compressed_before, compressed_after, input_before, input_after; + size_t length; + + /* + * Wait a bit after the pages have been allocated/accessed before trying to freeze. + * The sleeps are not needed, they just separate the operations into three logical chunks: + * touch a few pages, freeze them, thaw them (and repeat). + */ + usleep(100); + length = sizeof(compressed_before); + T_QUIET; T_ASSERT_POSIX_SUCCESS(sysctlbyname("vm.compressor_compressed_bytes", &compressed_before, &length, NULL, 0), + "failed to query vm.compressor_compressed_bytes"); + length = sizeof(input_before); + T_QUIET; T_ASSERT_POSIX_SUCCESS(sysctlbyname("vm.compressor_input_bytes", &input_before, &length, NULL, 0), + "failed to query vm.compressor_input_bytes"); + + T_STAT_MEASURE(s) { + ret = sysctlbyname("kern.memorystatus_freeze", NULL, NULL, &pid, sizeof(pid)); + }; + + length = sizeof(compressed_after); + T_QUIET; T_ASSERT_POSIX_SUCCESS(sysctlbyname("vm.compressor_compressed_bytes", &compressed_after, &length, NULL, 0), + "failed to query vm.compressor_compressed_bytes"); + length = sizeof(input_after); + T_QUIET; T_ASSERT_POSIX_SUCCESS(sysctlbyname("vm.compressor_input_bytes", &input_after, &length, NULL, 0), + "failed to query vm.compressor_input_bytes"); + + T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "sysctl kern.memorystatus_freeze failed on pid %d", pid); + + dt_stat_add(r, (double)(input_after - input_before)/(double)(compressed_after - compressed_before)); + + /* Wait a bit after freezing before trying to thaw */ + usleep(100); + ret = sysctlbyname("kern.memorystatus_thaw", NULL, NULL, &pid, sizeof(pid)); + T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "sysctl kern.memorystatus_thaw failed on pid %d", pid); + + /* Wait a bit after thawing before pages can be re-accessed */ + usleep(100); + T_QUIET; T_ASSERT_POSIX_SUCCESS(kill(pid, SIGUSR1), "failed to send SIGUSR1 to child process [%d]", pid); +} + +void run_compressor_test(int size_mb, int page_type) { + int ret; + char sz_str[50]; + char pt_str[50]; + char **launch_tool_args; + char testpath[PATH_MAX]; + uint32_t testpath_buf_size; + dispatch_source_t ds_freeze, ds_proc; + +#ifndef CONFIG_FREEZE + T_SKIP("Task freeze not supported."); +#endif + + r = dt_stat_create("(input bytes / compressed bytes)", "compression_ratio"); + s = dt_stat_time_create("compressor_latency"); + + signal(SIGUSR1, SIG_IGN); + ds_freeze = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGUSR1, 0, dispatch_get_main_queue()); + T_QUIET; T_ASSERT_NOTNULL(ds_freeze, "dispatch_source_create (ds_freeze)"); + + dispatch_source_set_event_handler(ds_freeze, ^{ + if (!dt_stat_stable(s)) { + freeze_helper_process(); + } else { + dt_stat_finalize(s); + dt_stat_finalize(r); + + kill(pid, SIGKILL); + dispatch_source_cancel(ds_freeze); + } + }); + dispatch_activate(ds_freeze); + + testpath_buf_size = sizeof(testpath); + ret = _NSGetExecutablePath(testpath, &testpath_buf_size); + T_QUIET; T_ASSERT_POSIX_ZERO(ret, "_NSGetExecutablePath"); + T_LOG("Executable path: %s", testpath); + + sprintf(sz_str, "%d", size_mb); + sprintf(pt_str, "%d", page_type); + launch_tool_args = (char *[]){ + testpath, + "-n", + "allocate_pages", + "--", + sz_str, + pt_str, + NULL + }; + + /* Spawn the child process. Suspend after launch until the exit proc handler has been set up. */ + ret = dt_launch_tool(&pid, launch_tool_args, true, NULL, NULL); + if (ret != 0) { + T_LOG("dt_launch tool returned %d with error code %d", ret, errno); + } + T_QUIET; T_ASSERT_POSIX_SUCCESS(pid, "dt_launch_tool"); + + ds_proc = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, (uintptr_t)pid, DISPATCH_PROC_EXIT, dispatch_get_main_queue()); + T_QUIET; T_ASSERT_NOTNULL(ds_proc, "dispatch_source_create (ds_proc)"); + + dispatch_source_set_event_handler(ds_proc, ^{ + int status = 0, code = 0; + pid_t rc = waitpid(pid, &status, 0); + T_QUIET; T_ASSERT_EQ(rc, pid, "waitpid"); + code = WEXITSTATUS(status); + + if (code == 0) { + T_END; + } else if (code > 0 && code < EXIT_CODE_MAX) { + T_ASSERT_FAIL("Child exited with %s", exit_codes_str[code]); + } else { + T_ASSERT_FAIL("Child exited with unknown exit code %d", code); + } + }); + dispatch_activate(ds_proc); + + T_QUIET; T_ASSERT_POSIX_SUCCESS(kill(pid, SIGCONT), "failed to send SIGCONT to child process [%d]", pid); + dispatch_main(); +} + +T_HELPER_DECL(allocate_pages, "allocates pages to compress") { + int i, j, ret, size_mb, page_type, vmpgsize; size_t vmpgsize_length; + __block int num_pages; + __block char **buf; + dispatch_source_t ds_signal; vmpgsize_length = sizeof(vmpgsize); - T_QUIET; T_ASSERT_POSIX_SUCCESS(sysctlbyname("vm.pagesize", &vmpgsize, &vmpgsize_length, NULL, 0), - "failed to query vm.pagesize"); + ret = sysctlbyname("vm.pagesize", &vmpgsize, &vmpgsize_length, NULL, 0); + if (ret != 0) { + exit(SYSCTL_VM_PAGESIZE_FAILED); + } if (vmpgsize == 0) { - T_FAIL("vm.pagesize set to zero"); + exit(VM_PAGESIZE_IS_ZERO); + } + + if (argc < 2) { + exit(TOO_FEW_ARGUMENTS); } + size_mb = atoi(argv[0]); + page_type = atoi(argv[1]); num_pages = size_mb * 1024 * 1024 / vmpgsize; buf = (char**)malloc(sizeof(char*) * (size_t)num_pages); @@ -106,103 +264,41 @@ void allocate_pages(int size_mb, int page_type) { allocate_representative_pages(buf, num_pages, vmpgsize); break; default: - T_FAIL("unknown page type"); - break; + exit(UNKNOWN_PAGE_TYPE); } - for(j = 0; j < num_pages; j++) { - i = buf[j][1]; + for (j = 0; j < num_pages; j++) { + i = buf[j][0]; } -} - - -void run_compressor_test(int size_mb, int page_type) { - -#ifndef CONFIG_FREEZE - T_SKIP("Task freeze not supported."); -#endif - - dt_stat_t r = dt_stat_create("(input bytes / compressed bytes)", "compression_ratio"); - dt_stat_time_t s = dt_stat_time_create("compressor_latency"); - - while (!dt_stat_stable(s)) { - pid_t pid; - int parent_pipe[2], child_pipe[2]; - - T_QUIET; T_ASSERT_POSIX_SUCCESS(pipe(parent_pipe), "pipe failed"); - T_QUIET; T_ASSERT_POSIX_SUCCESS(pipe(child_pipe), "pipe failed"); - - pid = fork(); - T_QUIET; T_ASSERT_POSIX_SUCCESS(pid, "fork failed with %d", errno); - if (pid == 0) { - int val = 1; - - close(child_pipe[0]); - close(parent_pipe[1]); - allocate_pages(size_mb, page_type); - - // Indicates to the parent that the child has finished allocating pages - write(child_pipe[1], &val, sizeof(val)); - - // Parent is done with the freeze, ok to exit now - read(parent_pipe[0], &val, sizeof(val)); - if (val != 2) { - T_FAIL("pipe read error"); - } - close(child_pipe[1]); - close(parent_pipe[0]); - exit(0); - - } else { - int val, ret; - int64_t compressed_before, compressed_after, input_before, input_after; - dt_stat_token start_token; - size_t length = sizeof(compressed_before); - - close(child_pipe[1]); - close(parent_pipe[0]); - - // Wait for the child to finish allocating pages - read(child_pipe[0], &val, sizeof(val)); - if (val != 1) { - T_FAIL("pipe read error"); - } - // Just to be extra sure that the child has finished allocating all of its pages - usleep(100); - - T_LOG("attempting to freeze pid %d\n", pid); - - T_QUIET; T_ASSERT_POSIX_SUCCESS(sysctlbyname("vm.compressor_compressed_bytes", &compressed_before, &length, NULL, 0), - "failed to query vm.compressor_compressed_bytes"); - T_QUIET; T_ASSERT_POSIX_SUCCESS(sysctlbyname("vm.compressor_input_bytes", &input_before, &length, NULL, 0), - "failed to query vm.compressor_input_bytes"); - - start_token = dt_stat_time_begin(s); - ret = sysctlbyname("kern.memorystatus_freeze", NULL, NULL, &pid, (size_t)sizeof(int)); - dt_stat_time_end(s, start_token); - - T_QUIET; T_ASSERT_POSIX_SUCCESS(sysctlbyname("vm.compressor_compressed_bytes", &compressed_after, &length, NULL, 0), - "failed to query vm.compressor_compressed_bytes"); - T_QUIET; T_ASSERT_POSIX_SUCCESS(sysctlbyname("vm.compressor_input_bytes", &input_after, &length, NULL, 0), - "failed to query vm.compressor_input_bytes"); - - T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "sysctl kern.memorystatus_freeze failed on pid %d", pid); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC), dispatch_get_main_queue(), ^{ + /* Signal to the parent that we're done allocating and it's ok to freeze us */ + printf("Sending initial signal to parent to begin freezing\n"); + if (kill(getppid(), SIGUSR1) != 0) { + exit(INITIAL_SIGNAL_TO_PARENT_FAILED); + } + }); - dt_stat_add(r, (double)(input_after - input_before)/(double)(compressed_after - compressed_before)); + signal(SIGUSR1, SIG_IGN); + ds_signal = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGUSR1, 0, dispatch_get_main_queue()); + if (ds_signal == NULL) { + exit(DISPATCH_SOURCE_CREATE_FAILED); + } - val = 2; - // Ok for the child to exit now - write(parent_pipe[1], &val, sizeof(val)); - usleep(100); + dispatch_source_set_event_handler(ds_signal, ^{ + volatile int tmp; - close(child_pipe[0]); - close(parent_pipe[1]); + /* Make sure all the pages are accessed before trying to freeze again */ + for (int x = 0; x < num_pages; x++) { + tmp = buf[x][0]; } - } + if (kill(getppid(), SIGUSR1) != 0) { + exit(SIGNAL_TO_PARENT_FAILED); + } + }); + dispatch_activate(ds_signal); - dt_stat_finalize(s); - dt_stat_finalize(r); + dispatch_main(); } // Numbers for 10MB and above are fairly reproducible. Anything smaller shows a lot of variation. diff --git a/tools/tests/darwintests/poll_select_kevent_paired_fds.c b/tools/tests/darwintests/poll_select_kevent_paired_fds.c index 169c698c7..bd9a5e727 100644 --- a/tools/tests/darwintests/poll_select_kevent_paired_fds.c +++ b/tools/tests/darwintests/poll_select_kevent_paired_fds.c @@ -517,12 +517,11 @@ handle_reading(enum fd_pair fd_pair, int fd) T_QUIET; T_ASSERT_LE(final_length, EXPECTED_LEN, "should not read more from file than what can be sent"); - /* FIFOs don't (and TTYs may not) send EOF when the write side closes */ + /* FIFOs don't send EOF when the write side closes */ if (final_length == strlen(EXPECTED_STRING) && - (fd_pair == FIFO_PAIR || fd_pair == PTY_PAIR)) + (fd_pair == FIFO_PAIR)) { - T_LOG("read all expected bytes from %s", - fd_pair == FIFO_PAIR ? "FIFO" : "PTY"); + T_LOG("read all expected bytes from FIFO"); return false; } return true; @@ -611,12 +610,6 @@ read_from_fd(int fd, enum fd_pair fd_pair, enum read_mode mode) "select waited for %d seconds and timed out", READ_TIMEOUT_SECS); - if (fd_pair == PTY_PAIR) { - /* - * XXX sometimes a PTY doesn't send EOF when the writer closes - */ - T_MAYFAIL; - } /* didn't fail or time out, therefore data is ready */ T_QUIET; T_ASSERT_NE(FD_ISSET(fd, &read_fd), 0, "select should show reading fd as readable"); diff --git a/tools/tests/darwintests/proc_info.c b/tools/tests/darwintests/proc_info.c index 9c2e16f05..3a1e73820 100644 --- a/tools/tests/darwintests/proc_info.c +++ b/tools/tests/darwintests/proc_info.c @@ -1,40 +1,1831 @@ +#define PRIVATE +#include #include +#include +#include +#include #include +#include #include +#include +#include #include #include +#include +#include #include +#include #include #include +#include +#include +#include +#include #include -#include +#include #include - -#define PRIVATE -#include -#include -#include #undef PRIVATE -T_GLOBAL_META(T_META_NAMESPACE("xnu.all")); +#define ACT_CHANGE_UID 1 +#define ACT_CHANGE_RUID 2 +#define ACT_EXIT 127 + +#define ACT_PHASE2 2 +#define ACT_PHASE3 3 +#define ACT_PHASE4 4 +#define ACT_PHASE5 5 + +#define PIPE_IN 0 +#define PIPE_OUT 1 + +#define CONF_THREAD_NAME "test_child_thread" +#define CONF_CMD_NAME getprogname() +#define CONF_PROC_COUNT 20 +#define CONF_BLK_SIZE 4096 +#define CONF_UID_VAL 999U +#define CONF_RUID_VAL 998U +#define CONF_GID_VAL 997U +#define CONF_NICE_VAL 5 +#define CONF_NUM_THREADS 2 + +#define BASEPRI_DEFAULT 31 +#define MAXPRI_USER 63 + +#define CONF_OPN_FILE_COUNT 3 +#define CONF_TMP_FILE_PATH "/tmp/testfile" + +uint32_t get_tty_dev(void); + +#define WAIT_FOR_CHILDREN(pipefd, action, child_count) \ + do { \ + long ret; \ + if (child_count == 1) { \ + int child_ret_action = 999; \ + while (child_ret_action != action) { \ + ret = read(pipefd, &child_ret_action, sizeof(child_ret_action)); \ + } \ + } else { \ + int child_ready_count = child_count * (int)sizeof(action); \ + \ + action = 0; \ + while (child_ready_count) { \ + ret = read(pipefd, &action, (int)sizeof(action)); \ + if (ret != -1) { \ + child_ready_count -= ret; \ + } else { \ + T_FAIL("ERROR: Could not read from pipe() : %d", errno); \ + } \ + if (action) { \ + T_FAIL("ERROR: Child action failed with error %d", action); \ + } \ + } \ + } \ + } while (0) + +#define PROC_INFO_CALL(struct_name, pid, flavor, proc_arg) \ + do { \ + struct struct_name * struct_var = malloc(sizeof(struct struct_name)); \ + T_QUIET; \ + T_ASSERT_NOTNULL(struct_var, "malloc() for " #flavor); \ + retval = __proc_info(PROC_INFO_CALL_PIDINFO, pid, flavor, (uint64_t)proc_arg, (user_addr_t)struct_var, \ + (uint32_t)sizeof(struct struct_name)); \ + \ + T_QUIET; \ + T_EXPECT_POSIX_SUCCESS(retval, "__proc_info call for " #flavor); \ + T_ASSERT_EQ_INT(retval, (int)sizeof(struct struct_name), "__proc_info call for " #flavor); \ + ret_structs[i] = (void *)struct_var; \ + i++; \ + } while (0) + +uint32_t +get_tty_dev() +{ + struct stat buf; + stat(ttyname(1), &buf); + return ((uint32_t)buf.st_rdev); +} + +/* + * Defined in libsyscall/wrappers/libproc/libproc.c + * For API test only. For normal use, please use the libproc API instead. + * DO NOT COPY + */ +extern int __proc_info(int32_t callnum, int32_t pid, uint32_t flavor, uint64_t arg, user_addr_t buffer, int32_t buffersize); +struct proc_config_s { + int parent_pipe[2]; + int child_count; + pid_t proc_grp_id; + int child_pipe[CONF_PROC_COUNT][2]; + int child_pids[CONF_PROC_COUNT]; + void * cow_map; /* memory for cow test */ +}; +typedef struct proc_config_s * proc_config_t; + +typedef void (^child_action_handler_t)(proc_config_t proc_config, int child_id); + +enum proc_info_opt { + P_UNIQIDINFO = 0x01, + C_UNIQIDINFO = 0x02, + PBSD_OLD = 0x04, + PBSD = 0x08, + PBSD_SHORT = 0x10, + PBSD_UNIQID = 0x20, + P_TASK_INFO = 0x40, + P_TASK_INFO_NEW = 0x80, + PALL = 0x100, + THREAD_ADDR = 0x200, + PTHINFO_OLD = 0x400, + PTHINFO = 0x800, + PTHINFO_64 = 0x1000, + PINFO_PATH = 0x2000, + PAI = 0x4000, + PREGINFO = 0x8000, + PREGINFO_PATH = 0x10000, + PREGINFO_PATH_2 = 0x20000, + PREGINFO_PATH_3 = 0x40000, + PVNINFO = 0x80000 +}; + +static int tmp_fd = -1; + +static child_action_handler_t proc_info_listpids_handler = ^void(proc_config_t proc_config, int child_id) { + close(proc_config->parent_pipe[PIPE_IN]); + close(proc_config->child_pipe[child_id][PIPE_OUT]); + long retval = 0; + int child_action = 0; + retval = write(proc_config->parent_pipe[PIPE_OUT], &child_action, sizeof(child_action)); + if (retval != -1) { + while (child_action != ACT_EXIT) { + retval = read(proc_config->child_pipe[child_id][PIPE_IN], &child_action, sizeof(child_action)); + if (retval == 0 || (retval == -1 && errno == EAGAIN)) { + continue; + } + if (retval != -1) { + switch (child_action) { + case ACT_CHANGE_UID: + /* + * Change uid + */ + retval = setuid(CONF_UID_VAL); + break; + case ACT_CHANGE_RUID: + /* + * Change ruid + */ + retval = setreuid(CONF_RUID_VAL, (uid_t)-1); + break; + case ACT_EXIT: + /* + * Exit + */ + break; + } + } + if (child_action != ACT_EXIT) { + retval = write(proc_config->parent_pipe[PIPE_OUT], &retval, sizeof(retval)); + if (retval == -1) + break; + } + } + } + close(proc_config->parent_pipe[PIPE_OUT]); + close(proc_config->child_pipe[child_id][PIPE_IN]); + exit(0); +}; + +static child_action_handler_t proc_info_call_pidinfo_handler = ^void(proc_config_t proc_config, int child_id) { + close(proc_config->parent_pipe[PIPE_IN]); + close(proc_config->child_pipe[child_id][PIPE_OUT]); + int action = 0; + long retval = 0; + int i; + void * tmp_map = NULL; + dispatch_queue_t q = NULL; + dispatch_semaphore_t sem = NULL; + /* + * PHASE 1: Child ready and waits for parent to send next action + */ + T_LOG("Child ready to accept action from parent"); + retval = write(proc_config->parent_pipe[PIPE_OUT], &action, sizeof(action)); + if (retval != -1) { + while (action != ACT_EXIT) { + retval = read(proc_config->child_pipe[child_id][PIPE_IN], &action, sizeof(action)); + + if (retval != -1) { + retval = 0; + switch (action) { + case ACT_PHASE2: { + /* + * Change uid, euid, guid, rgid, nice value + * Also change the svuid and svgid + */ + T_LOG("Child changing uid, euid, rguid, svuid, svgid and nice value"); + retval = nice(CONF_NICE_VAL); + if (retval == -1) { + T_LOG("(child) ERROR: nice() failed"); + break; + } + retval = setgid(CONF_GID_VAL); + if (retval == -1) { + T_LOG("(child) ERROR: setgid() failed"); + break; + } + retval = setreuid((uid_t)-1, CONF_RUID_VAL); + if (retval == -1) { + T_LOG("(child) ERROR: setreuid() failed"); + break; + } + break; + } + case ACT_PHASE3: { + /* + * Allocate a page of memory + * Copy on write shared memory + */ + T_LOG("Child allocating a page of memory, and causing a copy-on-write"); + retval = 0; + tmp_map = mmap(0, PAGE_SIZE, PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); + if (tmp_map == MAP_FAILED) { + T_LOG("(child) ERROR: mmap() failed"); + retval = 1; + break; + } + /* + * Get the page allocated + */ + int * map_ptr = (int *)tmp_map; + for (i = 0; i < (int)(PAGE_SIZE / sizeof(int)); i++) { + *map_ptr++ = i; + } + /* + * Cause copy on write to the page + */ + *((int *)(proc_config->cow_map)) = 20; + + break; + } + case ACT_PHASE4: { + T_LOG("Child spending CPU cycles and changing thread name"); + retval = 0; + int number = 1000; + unsigned long long factorial = 1; + int j; + for (j = 1; j <= number; j++) { + factorial *= (unsigned long long)j; + } + sysctlbyname("kern.threadname", NULL, 0, CONF_THREAD_NAME, strlen(CONF_THREAD_NAME)); + break; + } + case ACT_PHASE5: { + /* + * Dispatch for Workq test + */ + T_LOG("Child creating a dispatch queue, and dispatching blocks on it"); + q = dispatch_queue_create("com.apple.test_proc_info.workqtest", + DISPATCH_QUEUE_CONCURRENT); // dispatch_get_global_queue(0, 0); + sem = dispatch_semaphore_create(0); + + for (i = 0; i < CONF_NUM_THREADS; i++) { + dispatch_async(q, ^{ + /* + * Block the thread, do nothing + */ + dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER); + }); + } + break; + } + case ACT_EXIT: { + /* + * Exit + */ + if (sem) { + for (i = 0; i < CONF_NUM_THREADS; i++) { + dispatch_semaphore_signal(sem); + } + } + + if (tmp_map) + munmap(tmp_map, PAGE_SIZE); + + if (proc_config->cow_map) + munmap(proc_config->cow_map, PAGE_SIZE); + + break; + } + } + } + if (action != ACT_EXIT) { + retval = write(proc_config->parent_pipe[PIPE_OUT], &action, sizeof(action)); + if (retval == -1) + break; + } + } + close(proc_config->parent_pipe[PIPE_OUT]); + close(proc_config->child_pipe[child_id][PIPE_IN]); + exit(0); + } +}; + +static void +free_proc_config(proc_config_t proc_config) +{ + free(proc_config); +} + +static void +send_action_to_child_processes(proc_config_t proc_config, int action) +{ + long err; + for (int i = 0; i < proc_config->child_count; i++) { + err = write(proc_config->child_pipe[i][PIPE_OUT], &action, sizeof(action)); + T_QUIET; + T_ASSERT_POSIX_SUCCESS(err, "write() to child in send_action"); + } + if (action != ACT_EXIT) { + WAIT_FOR_CHILDREN(proc_config->parent_pipe[PIPE_IN], action, proc_config->child_count); + } +} + +static void +kill_child_processes(proc_config_t proc_config) +{ + int ret = 0; + T_LOG("Killing child processes"); + send_action_to_child_processes(proc_config, ACT_EXIT); + for (int child_id = 0; child_id < proc_config->child_count; child_id++) { + close(proc_config->child_pipe[child_id][PIPE_OUT]); + dt_waitpid(proc_config->child_pids[child_id], NULL, NULL, 5); + T_QUIET; + T_ASSERT_POSIX_SUCCESS(ret, "killed child %d", child_id); + } + close(proc_config->parent_pipe[PIPE_IN]); + munmap(proc_config->cow_map, PAGE_SIZE); + T_LOG("Killed child processes"); +} + +static proc_config_t +spawn_child_processes(int child_count, child_action_handler_t child_handler) +{ + /* + * Spawn procs for Tests 1.2 and 1.3 + */ + T_LOG("Spawning child processes..."); + proc_config_t proc_config = malloc(sizeof(*proc_config)); + int action = 0; + int err; + + setpgid(0, 0); + proc_config->proc_grp_id = getpgid(0); + + proc_config->child_count = child_count; + + err = pipe(proc_config->parent_pipe); + T_QUIET; + T_ASSERT_POSIX_SUCCESS(err, "pipe() call"); + + /* + * Needed for ACT_PHASE3 tests + */ + proc_config->cow_map = mmap(0, PAGE_SIZE, PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); + T_QUIET; + T_ASSERT_NE_PTR(proc_config->cow_map, MAP_FAILED, "cow_map mmap()"); + *((int *)(proc_config->cow_map)) = 10; + + pid_t child_pid; + int i; + int child_id; + for (i = 0; i < child_count; i++) { + err = pipe(proc_config->child_pipe[i]); + T_QUIET; + T_ASSERT_POSIX_SUCCESS(err, "pipe() call"); + + child_pid = fork(); + child_id = i; + T_QUIET; + T_ASSERT_POSIX_SUCCESS(child_pid, "fork() in parent process for child %d", child_id); + + if (child_pid == 0) { + child_handler(proc_config, child_id); + } else { + proc_config->child_pids[child_id] = child_pid; + } + close(proc_config->child_pipe[child_id][PIPE_IN]); + } + /* + * Wait for the children processes to spawn + */ + close(proc_config->parent_pipe[PIPE_OUT]); + WAIT_FOR_CHILDREN(proc_config->parent_pipe[PIPE_IN], action, child_count); + + return proc_config; +} + +/* + * All PROC_INFO_CALL_PIDINFO __proc_info calls fire from this function. + * T_DECLs require different combinations of structs and different actions + * must occur in the child to get the data. Instead of performing the setup + * in each T_DECL, this function accepts a bitmap and performs the necessary setup + * and cleanup work + */ + +static void +proc_info_caller(int proc_info_opts, void ** ret_structs, int * ret_child_pid) +{ + int retval, i = 0; + uint64_t * thread_addr = NULL; + void * map_tmp = NULL; + + proc_config_t proc_config = spawn_child_processes(1, proc_info_call_pidinfo_handler); + int child_pid = proc_config->child_pids[0]; + /* + * These tests only require one child. + * Some DECLs need to know the child pid, so we pass that back if applicable + */ + if (ret_child_pid != NULL) { + *ret_child_pid = child_pid; + } + + if (proc_info_opts & P_UNIQIDINFO) { + PROC_INFO_CALL(proc_uniqidentifierinfo, getpid(), PROC_PIDUNIQIDENTIFIERINFO, 0); + } + if (proc_info_opts & C_UNIQIDINFO) { + PROC_INFO_CALL(proc_uniqidentifierinfo, child_pid, PROC_PIDUNIQIDENTIFIERINFO, 0); + } + if (proc_info_opts & PBSD_OLD) { + PROC_INFO_CALL(proc_bsdinfo, child_pid, PROC_PIDTBSDINFO, 0); + } + + /* + * Child Phase 2 Fires if opts require it + * Small nap after call to give child time to receive and execute the action + */ + + if (proc_info_opts >= PBSD) { + send_action_to_child_processes(proc_config, ACT_PHASE2); + } + + if (proc_info_opts & PBSD) { + PROC_INFO_CALL(proc_bsdinfo, child_pid, PROC_PIDTBSDINFO, 0); + } + + if (proc_info_opts & PBSD_SHORT) { + PROC_INFO_CALL(proc_bsdshortinfo, child_pid, PROC_PIDT_SHORTBSDINFO, 0); + } + + if (proc_info_opts & PBSD_UNIQID) { + PROC_INFO_CALL(proc_bsdinfowithuniqid, child_pid, PROC_PIDT_BSDINFOWITHUNIQID, 0); + } + if (proc_info_opts & P_TASK_INFO) { + PROC_INFO_CALL(proc_taskinfo, child_pid, PROC_PIDTASKINFO, 0); + } + + /* + * Child Phase 3 Fires + */ + if (proc_info_opts >= P_TASK_INFO_NEW) { + send_action_to_child_processes(proc_config, ACT_PHASE3); + } + + if (proc_info_opts & P_TASK_INFO_NEW) { + PROC_INFO_CALL(proc_taskinfo, child_pid, PROC_PIDTASKINFO, 0); + } + + if (proc_info_opts & PALL) { + PROC_INFO_CALL(proc_taskallinfo, child_pid, PROC_PIDTASKALLINFO, 0); + } + /* + * This case breaks the pattern in that its proc_info call requires PALL, + * its value is required in some other proc_info calls + * and we never put the retval into our ret_structs + */ + if (proc_info_opts & THREAD_ADDR || proc_info_opts & PTHINFO_OLD || proc_info_opts & PTHINFO || proc_info_opts & PINFO_PATH) { + struct proc_taskallinfo * pall = malloc(sizeof(struct proc_taskallinfo)); + T_QUIET; + T_ASSERT_NOTNULL(pall, "malloc() for PROC_TASKALLINFO"); + + retval = __proc_info(PROC_INFO_CALL_PIDINFO, child_pid, PROC_PIDTASKALLINFO, (uint32_t)0, (user_addr_t)pall, + (uint32_t)sizeof(struct proc_taskallinfo)); + T_QUIET; + T_ASSERT_EQ_INT(retval, (int)sizeof(struct proc_taskallinfo), "__proc_info call for PROC_PIDTASKALLINFO in THREAD_ADDR"); + + thread_addr = malloc(sizeof(uint64_t) * (unsigned long)(pall->ptinfo.pti_threadnum + 1)); + memset(thread_addr, 0, sizeof(uint64_t) * (unsigned long)(pall->ptinfo.pti_threadnum + 1)); + T_QUIET; + T_ASSERT_NOTNULL(thread_addr, "malloc() for PROC_PIDLISTTHREADS"); + + retval = __proc_info(PROC_INFO_CALL_PIDINFO, child_pid, PROC_PIDLISTTHREADS, (uint32_t)0, (user_addr_t)thread_addr, + (int32_t)(sizeof(uint64_t) * (unsigned long)(pall->ptinfo.pti_threadnum + 1))); + T_LOG("(int)((unsigned long)retval / PROC_PIDLISTTHREADS_SIZE: %d", + (int)((unsigned long)retval / PROC_PIDLISTTHREADS_SIZE)); + T_ASSERT_GE_INT((int)((unsigned long)retval / PROC_PIDLISTTHREADS_SIZE), pall->ptinfo.pti_threadnum, + "__proc_info call for PROC_PIDLISTTHREADS"); + + free(pall); + } + if (proc_info_opts & PTHINFO_OLD) { + PROC_INFO_CALL(proc_threadinfo, child_pid, PROC_PIDTHREADINFO, thread_addr[0]); + } + + /* + * Child Phase 4 Fires + */ + if (proc_info_opts >= PTHINFO) { + send_action_to_child_processes(proc_config, ACT_PHASE4); + } + + if (proc_info_opts & PTHINFO) { + PROC_INFO_CALL(proc_threadinfo, child_pid, PROC_PIDTHREADINFO, thread_addr[0]); + } + if (proc_info_opts & PTHINFO_64) { + mach_port_name_t child_task = MACH_PORT_NULL; + thread_array_t child_threads = NULL; + mach_msg_type_number_t child_thread_count; + thread_identifier_info_data_t child_thread_threadinfo; + mach_msg_type_number_t thread_info_count = THREAD_IDENTIFIER_INFO_COUNT; + struct proc_threadinfo * pthinfo_64 = malloc(sizeof(struct proc_threadinfo)); + T_QUIET; + T_ASSERT_NOTNULL(pthinfo_64, "malloc() for PROC_THREADINFO"); + + retval = task_for_pid(mach_task_self(), child_pid, &child_task); + T_ASSERT_EQ_INT(retval, 0, "task_for_pid for PROC_PIDTHREADID64INFO"); + + retval = task_threads(child_task, &child_threads, &child_thread_count); + T_ASSERT_MACH_SUCCESS(retval, "task_threads() call for PROC_PIDTHREADID64INFO"); + + retval = thread_info(child_threads[0], THREAD_IDENTIFIER_INFO, (thread_info_t)&child_thread_threadinfo, &thread_info_count); + T_ASSERT_MACH_SUCCESS(retval, "thread_info call for PROC_PIDTHREADID64INFO"); + + retval = __proc_info(PROC_INFO_CALL_PIDINFO, child_pid, PROC_PIDTHREADID64INFO, (uint64_t)child_thread_threadinfo.thread_id, + (user_addr_t)pthinfo_64, (uint32_t)sizeof(struct proc_threadinfo)); + T_ASSERT_EQ_INT(retval, (int)sizeof(struct proc_threadinfo), "__proc_info call for PROC_PIDTHREADID64INFO"); + + ret_structs[i] = (void *)pthinfo_64; + i++; + + mach_port_deallocate(mach_task_self(), child_task); + mach_port_deallocate(mach_task_self(), child_threads[0]); + child_threads[0] = MACH_PORT_NULL; + child_task = MACH_PORT_NULL; + } + if (proc_info_opts & PINFO_PATH) { + PROC_INFO_CALL(proc_threadwithpathinfo, child_pid, PROC_PIDTHREADPATHINFO, thread_addr[0]); + } + + if (proc_info_opts & PAI) { + PROC_INFO_CALL(proc_archinfo, getpid(), PROC_PIDARCHINFO, 0); + } + + if ((proc_info_opts & PREGINFO) | (proc_info_opts & PREGINFO_PATH) | (proc_info_opts & PREGINFO_PATH_2) | + (proc_info_opts & PREGINFO_PATH_3)) { + tmp_fd = open(CONF_TMP_FILE_PATH, O_RDWR | O_CREAT); + + for (int j = 0; j < 100; j++) { + char buf[50]; + write(tmp_fd, buf, sizeof(buf)); + } + retval = fsync(tmp_fd); + T_QUIET; + T_ASSERT_POSIX_SUCCESS(retval, "file fsync()"); + + map_tmp = mmap(0, PAGE_SIZE, PROT_WRITE, MAP_PRIVATE, tmp_fd, (off_t)PAGE_SIZE); + T_ASSERT_NE_PTR(map_tmp, MAP_FAILED, "mmap() for PROC_PIDREGIONINFO"); + + T_LOG("file: %s is opened as fd %d and mapped at %llx with size %lu", CONF_TMP_FILE_PATH, tmp_fd, (uint64_t)map_tmp, + (unsigned long)PAGE_SIZE); + } + + if (proc_info_opts & PREGINFO) { + PROC_INFO_CALL(proc_regioninfo, getpid(), PROC_PIDREGIONINFO, map_tmp); + ret_structs[i] = map_tmp; + i++; + } + if (proc_info_opts & PREGINFO_PATH) { + PROC_INFO_CALL(proc_regionwithpathinfo, getpid(), PROC_PIDREGIONPATHINFO, map_tmp); + ret_structs[i] = map_tmp; + i++; + } + if (proc_info_opts & PREGINFO_PATH_2) { + PROC_INFO_CALL(proc_regionwithpathinfo, getpid(), PROC_PIDREGIONPATHINFO2, map_tmp); + ret_structs[i] = map_tmp; + i++; + } + + if (proc_info_opts & PREGINFO_PATH_3) { + struct proc_regionwithpathinfo * preginfo_path = malloc(sizeof(struct proc_regionwithpathinfo)); + + retval = __proc_info(PROC_INFO_CALL_PIDINFO, getpid(), PROC_PIDREGIONPATHINFO2, (uint64_t)map_tmp, + (user_addr_t)preginfo_path, (uint32_t)sizeof(struct proc_regionwithpathinfo)); + + T_ASSERT_EQ_INT(retval, (int)sizeof(struct proc_regionwithpathinfo), "__proc_info call for PROC_PIDREGIONPATHINFO2"); + + T_LOG("preginfo_path.prp_vip.vip_vi.vi_fsid.val 0: %d", preginfo_path->prp_vip.vip_vi.vi_fsid.val[0]); + T_LOG("preginfo_path.prp_vip.vip_vi.vi_fsid.val 1: %d", preginfo_path->prp_vip.vip_vi.vi_fsid.val[1]); + + retval = __proc_info(PROC_INFO_CALL_PIDINFO, getpid(), PROC_PIDREGIONPATHINFO3, + (uint64_t)(*(uint32_t *)(preginfo_path->prp_vip.vip_vi.vi_fsid.val)), (user_addr_t)preginfo_path, + (uint32_t)sizeof(struct proc_regionwithpathinfo)); + T_ASSERT_EQ_INT(retval, (int)sizeof(struct proc_regionwithpathinfo), "__proc_info call for PROC_PIDREGIONPATHWITHINFO3"); + ret_structs[i] = (void *)preginfo_path; + i++; + } + + if (proc_info_opts & PVNINFO) { + PROC_INFO_CALL(proc_vnodepathinfo, getpid(), PROC_PIDVNODEPATHINFO, 0); + } + + kill_child_processes(proc_config); + free_proc_config(proc_config); + free(thread_addr); + thread_addr = NULL; + close(tmp_fd); + tmp_fd = -1; +} + +static void +free_proc_info(void ** proc_info, int num) +{ + for (int i = 0; i < num; i++) { + free(proc_info[i]); + } + + return; +} + +/* + * Start DECLs + */ + +T_DECL(proc_info_listpids_all_pids, + "proc_info API test to verify PROC_INFO_CALL_LISTPIDS", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + /* + * Get the value of nprocs with no buffer sent in + */ + int num_procs; + num_procs = __proc_info(PROC_INFO_CALL_LISTPIDS, PROC_ALL_PIDS, (uint32_t)getpid(), (uint32_t)0, (user_addr_t)0, (uint32_t)0); + T_ASSERT_GE_INT(num_procs, 1, "verify valid value for nprocs: %d", num_procs); + + proc_config_t proc_config = spawn_child_processes(CONF_PROC_COUNT, proc_info_listpids_handler); + + num_procs = __proc_info(PROC_INFO_CALL_LISTPIDS, PROC_ALL_PIDS, (uint32_t)getpid(), (uint32_t)0, (user_addr_t)0, (uint32_t)0); + + int proc_count = num_procs / (int)sizeof(pid_t); + int proc_count_all = num_procs / (int)sizeof(pid_t); + if (proc_count > (CONF_PROC_COUNT + 1)) { + proc_count = CONF_PROC_COUNT + 1; + } + pid_t * proc_ids = malloc(sizeof(pid_t) * (unsigned long)proc_count); + num_procs = __proc_info(PROC_INFO_CALL_LISTPIDS, PROC_ALL_PIDS, (uint32_t)getpid(), (uint32_t)0, (user_addr_t)proc_ids, + (int32_t)(proc_count * (int)sizeof(pid_t))); + num_procs = num_procs / (int)sizeof(pid_t); + T_ASSERT_GE_INT(num_procs, proc_count, "Valid number of pids obtained for PROC_ALL_PIDS."); + + free(proc_ids); + + /* + * Grab list of all procs and make sure our spawned children are in the list. + */ + + proc_ids = malloc(sizeof(pid_t) * (unsigned long)proc_count_all); + num_procs = __proc_info(PROC_INFO_CALL_LISTPIDS, PROC_ALL_PIDS, (uint32_t)getpid(), (uint32_t)0, (user_addr_t)proc_ids, + (int32_t)(proc_count_all * (int)sizeof(pid_t))); + num_procs = num_procs / (int)sizeof(pid_t); + + int pid_match = 1; + + for (int i = 0; i < (CONF_PROC_COUNT - 1); i++) { + for (int j = 0; j < num_procs; j++) { + if (proc_ids[j] == proc_config->child_pids[i]) { + break; + } else if (j == (num_procs - 1)) { + pid_match = 0; + break; + } + } + + if (!pid_match) { + break; + } + } + + T_ASSERT_EQ(pid_match, 1, "PROC_INFO_CALL_LISTPIDS contains our spawned children's pids"); + + free(proc_ids); + + kill_child_processes(proc_config); + free_proc_config(proc_config); + + errno = 0; + num_procs = __proc_info(PROC_INFO_CALL_LISTPIDS, PROC_ALL_PIDS, (uint32_t)getpid(), (uint32_t)0, (user_addr_t)proc_ids, + (uint32_t)(sizeof(pid_t) - 1)); + T_EXPECT_POSIX_ERROR(errno, ENOMEM, "Valid proc_info behavior when bufsize < sizeof(pid_t)."); +} + +T_DECL(proc_info_listpids_pgrp_only, + "proc_info API test to verify PROC_INFO_CALL_LISTPIDS", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + proc_config_t proc_config = spawn_child_processes(CONF_PROC_COUNT, proc_info_listpids_handler); + T_LOG("Test to verify PROC_PGRP_ONLY returns correct value"); + /* + * The number of obtained pids depends on size of buffer. + * count = childCount + 1(parent) + * So, we set it to one more than expected to capture any error. + */ + int proc_count = CONF_PROC_COUNT + 2; + pid_t * proc_ids = malloc(sizeof(*proc_ids) * (unsigned long)proc_count); + int num_procs = __proc_info(PROC_INFO_CALL_LISTPIDS, PROC_PGRP_ONLY, (uint32_t)proc_config->proc_grp_id, (uint32_t)0, + (user_addr_t)proc_ids, (int32_t)(proc_count * (int)sizeof(*proc_ids))); + num_procs = num_procs / (int)sizeof(pid_t); + T_ASSERT_EQ_INT(num_procs, CONF_PROC_COUNT + 1, "Valid number of pids obtained for PROC_PGRP_ONLY."); + kill_child_processes(proc_config); + free_proc_config(proc_config); + free(proc_ids); +} + +T_DECL(proc_info_listpids_ppid_only, + "proc_info API test to verify PROC_INFO_CALL_LISTPIDS", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + proc_config_t proc_config = spawn_child_processes(CONF_PROC_COUNT, proc_info_listpids_handler); + T_LOG("Test to verify PROC_PPID_ONLY returns correct value"); + /* + * Pass in the same (bigger) buffer but expect only the pids where ppid is pid of current proc. + */ + int proc_count = CONF_PROC_COUNT + 2; + pid_t * proc_ids = malloc(sizeof(*proc_ids) * (unsigned long)proc_count); + int num_procs = __proc_info(PROC_INFO_CALL_LISTPIDS, PROC_PPID_ONLY, (uint32_t)getpid(), (uint32_t)0, (user_addr_t)proc_ids, + (int32_t)(proc_count * (int)sizeof(*proc_ids))); + num_procs = num_procs / (int)sizeof(pid_t); + T_ASSERT_EQ_INT(num_procs, CONF_PROC_COUNT, "Valid number of pids obtained for PROC_PPID_ONLY."); + kill_child_processes(proc_config); + free_proc_config(proc_config); + free(proc_ids); +} + +T_DECL(proc_info_listpids_uid_only, + "proc_info API test to verify PROC_INFO_CALL_LISTPIDS", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + proc_config_t proc_config = spawn_child_processes(CONF_PROC_COUNT, proc_info_listpids_handler); + T_LOG("Test to verify PROC_UID_ONLY returns correct value"); + int proc_count = CONF_PROC_COUNT + 2; + pid_t * proc_ids = malloc(sizeof(*proc_ids) * (unsigned long)proc_count); + send_action_to_child_processes(proc_config, ACT_CHANGE_UID); + usleep(10000); + int num_procs = __proc_info(PROC_INFO_CALL_LISTPIDS, PROC_UID_ONLY, CONF_UID_VAL, (uint32_t)0, (user_addr_t)proc_ids, + (int32_t)(proc_count * (int)sizeof(*proc_ids))); + T_ASSERT_GE_ULONG((unsigned long)num_procs / sizeof(pid_t), (unsigned long)CONF_PROC_COUNT, + "Valid number of pids obtained for PROC_UID_ONLY."); + kill_child_processes(proc_config); + free_proc_config(proc_config); + free(proc_ids); +} + +T_DECL(proc_info_listpids_ruid_only, + "proc_info API test to verify PROC_INFO_CALL_LISTPIDS", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + proc_config_t proc_config = spawn_child_processes(CONF_PROC_COUNT, proc_info_listpids_handler); + T_LOG("Test to verify PROC_RUID_ONLY returns correct value"); + int proc_count = CONF_PROC_COUNT + 2; + pid_t * proc_ids = malloc(sizeof(*proc_ids) * (unsigned long)proc_count); + send_action_to_child_processes(proc_config, ACT_CHANGE_RUID); + usleep(10000); + int num_procs = __proc_info(PROC_INFO_CALL_LISTPIDS, PROC_RUID_ONLY, CONF_RUID_VAL, (uint32_t)0, (user_addr_t)proc_ids, + (int32_t)(proc_count * (int)sizeof(*proc_ids))); + T_ASSERT_GE_ULONG((unsigned long)num_procs / sizeof(pid_t), (unsigned long)CONF_PROC_COUNT, + "Valid number of pids obtained for PROC_RUID_ONLY."); + kill_child_processes(proc_config); + free_proc_config(proc_config); + free(proc_ids); +} + +T_DECL(proc_info_listpids_tty_only, + "proc_info API test to verify PROC_INFO_CALL_LISTPIDS", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + int ret = isatty(STDOUT_FILENO); + if (ret != 1) { + T_SKIP("Not connected to tty...skipping test"); + } + + proc_config_t proc_config = spawn_child_processes(CONF_PROC_COUNT, proc_info_listpids_handler); + + T_LOG("Test to verify PROC_TTY_ONLY returns correct value"); + int proc_count = CONF_PROC_COUNT + 2; + pid_t * proc_ids = malloc(sizeof(*proc_ids) * (unsigned long)proc_count); + int num_procs = __proc_info(PROC_INFO_CALL_LISTPIDS, PROC_TTY_ONLY, get_tty_dev(), (uint32_t)0, (user_addr_t)proc_ids, + (int32_t)(proc_count * (int)sizeof(*proc_ids))); + num_procs = num_procs / (int)sizeof(pid_t); + T_ASSERT_GE_INT(num_procs, 0, "Valid number of pids returned by PROC_TTY_ONLY."); + kill_child_processes(proc_config); + free_proc_config(proc_config); + free(proc_ids); +} + +/* + * Most of the following PROC_INFO_CALL_PIDINFO tests rely on a helper function (proc_info_caller) to make the necessary proc_info + * calls on their behalf + * In a previous iteration, these tests were all in one giant T_DECL and the helper function handles inter-DECL dependencies such as + * a proc_info call relying on the results of a previous proc_info call or an assumed state that a child should be in. + */ + +T_DECL(proc_info_pidinfo_proc_piduniqidentifierinfo, + "Test to identify PROC_PIDUNIQIDENTIFIERINFO returns correct unique identifiers for process", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + void * proc_info[2]; + proc_info_caller(P_UNIQIDINFO | C_UNIQIDINFO, proc_info, NULL); + struct proc_uniqidentifierinfo * p_uniqidinfo = (struct proc_uniqidentifierinfo *)proc_info[0]; + struct proc_uniqidentifierinfo * c_uniqidinfo = (struct proc_uniqidentifierinfo *)proc_info[1]; + + T_EXPECT_NE_ULLONG(c_uniqidinfo->p_uniqueid, p_uniqidinfo->p_uniqueid, "p_uniqueid not unique for the process"); + + for (size_t i = 0; i < 16; i++) { + T_EXPECT_EQ_UCHAR(c_uniqidinfo->p_uuid[i], p_uniqidinfo->p_uuid[i], "p_uuid should be the same unique id"); + } + T_EXPECT_EQ_ULLONG(c_uniqidinfo->p_puniqueid, p_uniqidinfo->p_uniqueid, + "p_puniqueid of child should be same as p_uniqueid for parent"); + + free_proc_info(proc_info, 2); +} + +T_DECL(proc_info_pidinfo_proc_pidtbsdinfo, + "Test to verify PROC_PIDTBSDINFO returns valid information about the process", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + void * proc_info[2]; + int child_pid = 0; + proc_info_caller(PBSD_OLD | PBSD, proc_info, &child_pid); + struct proc_bsdinfo * pbsd_old = (struct proc_bsdinfo *)proc_info[0]; + struct proc_bsdinfo * pbsd = (struct proc_bsdinfo *)proc_info[1]; + + T_EXPECT_EQ_UINT((unsigned int)SRUN, pbsd->pbi_status, "PROC_PIDTBSDINFO shows Correct status"); + T_EXPECT_EQ_UINT(0U, pbsd->pbi_xstatus, "PROC_PIDTBSDINFO show Correct xstatus (exit status)"); + T_EXPECT_EQ_UINT(pbsd->pbi_pid, (unsigned int)child_pid, "PROC_PIDTBSDINFO returns valid pid"); + T_EXPECT_EQ_UINT(pbsd->pbi_ppid, (unsigned int)getpid(), "PROC_PIDTBSDINFO returns valid ppid"); + T_EXPECT_EQ_UINT(pbsd->pbi_uid, CONF_RUID_VAL, "PROC_PIDTBSDINFO returns valid uid"); + T_EXPECT_EQ_UINT(pbsd->pbi_gid, CONF_GID_VAL, "PROC_PIDTBSDINFO returns valid gid"); + T_EXPECT_EQ_UINT(pbsd->pbi_ruid, 0U, "PROC_PIDTBSDINFO returns valid ruid"); + T_EXPECT_EQ_UINT(pbsd->pbi_rgid, CONF_GID_VAL, "PROC_PIDTBSDINFO returns valid rgid"); + T_EXPECT_EQ_UINT(pbsd->pbi_svuid, CONF_RUID_VAL, "PROC_PIDTBSDINFO returns valid svuid"); + T_EXPECT_EQ_UINT(pbsd->pbi_svgid, CONF_GID_VAL, "PROC_PIDTBSDINFO returns valid svgid"); + T_EXPECT_EQ_UINT(pbsd->pbi_nice, CONF_NICE_VAL, "PROC_PIDTBSDINFO returns valid nice value"); + T_EXPECT_EQ_STR(pbsd->pbi_comm, CONF_CMD_NAME, "PROC_PIDTBSDINFO returns valid p_comm name"); + T_EXPECT_EQ_STR(pbsd->pbi_name, CONF_CMD_NAME, "PROC_PIDTBSDINFO returns valid p_name name"); + T_EXPECT_EQ_UINT(pbsd->pbi_flags, (pbsd_old->pbi_flags | PROC_FLAG_PSUGID), "PROC_PIDTBSDINFO returns valid flags"); + T_EXPECT_EQ_UINT(pbsd->pbi_nfiles, pbsd_old->pbi_nfiles, "PROC_PIDTBSDINFO returned valid pbi_nfiles"); + T_EXPECT_EQ_UINT(pbsd->pbi_pgid, (uint32_t)getpgid(getpid()), "PROC_PIDTBSDINFO returned valid pbi_pgid"); + T_EXPECT_EQ_UINT(pbsd->pbi_pjobc, pbsd->pbi_pjobc, "PROC_PIDTBSDINFO returned valid pbi_pjobc"); + T_EXPECT_NE_UINT(pbsd->e_tdev, 0U, "PROC_PIDTBSDINFO returned valid e_tdev"); + + free_proc_info(proc_info, 2); +} + +T_DECL(proc_info_pidt_shortbsdinfo, + "Test to verify PROC_PIDT_SHORTBSDINFO returns valid information about the process", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + void * proc_info[2]; + int child_pid = 0; + proc_info_caller(PBSD | PBSD_SHORT, proc_info, &child_pid); + struct proc_bsdinfo * pbsd = (struct proc_bsdinfo *)proc_info[0]; + struct proc_bsdshortinfo * pbsd_short = (struct proc_bsdshortinfo *)proc_info[1]; + + T_EXPECT_EQ_UINT(pbsd_short->pbsi_pid, (unsigned int)child_pid, "PROC_PIDT_SHORTBSDINFO returns valid pid"); + T_EXPECT_EQ_UINT(pbsd_short->pbsi_ppid, (unsigned int)getpid(), "PROC_PIDT_SHORTBSDINFO returns valid ppid"); + T_EXPECT_EQ_UINT(pbsd_short->pbsi_pgid, (uint32_t)getpgid(getpid()), "PROC_PIDT_SHORTBSDINFO returned valid pbi_pgid"); + T_EXPECT_EQ_UINT((unsigned int)SRUN, pbsd_short->pbsi_status, "PROC_PIDT_SHORTBSDINFO shows Correct status"); + T_EXPECT_EQ_STR(pbsd_short->pbsi_comm, CONF_CMD_NAME, "PROC_PIDT_SHORTBSDINFO returns valid p_comm name"); + /* + * The short variant returns all flags except session flags, hence ignoring them here. + */ + T_EXPECT_EQ_UINT(pbsd_short->pbsi_flags, (pbsd->pbi_flags & (unsigned int)(~PROC_FLAG_CTTY)), + "PROC_PIDT_SHORTBSDINFO returns valid flags"); + T_EXPECT_EQ_UINT(pbsd_short->pbsi_uid, CONF_RUID_VAL, "PROC_PIDT_SHORTBSDINFO returns valid uid"); + T_EXPECT_EQ_UINT(pbsd_short->pbsi_gid, CONF_GID_VAL, "PROC_PIDT_SHORTBSDINFO returns valid gid"); + T_EXPECT_EQ_UINT(pbsd_short->pbsi_ruid, 0U, "PROC_PIDT_SHORTBSDINFO returns valid ruid"); + T_EXPECT_EQ_UINT(pbsd_short->pbsi_svuid, CONF_RUID_VAL, "PROC_PIDT_SHORTBSDINFO returns valid svuid"); + T_EXPECT_EQ_UINT(pbsd_short->pbsi_svgid, CONF_GID_VAL, "PROC_PIDT_SHORTBSDINFO returns valid svgid"); + + free_proc_info(proc_info, 2); +} + +T_DECL(proc_info_pidt_bsdinfowithuniqid, + "Test to verify PROC_PIDT_BSDINFOWITHUNIQID returns valid information about the process", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + void * proc_info[4]; + int child_pid = 0; + proc_info_caller(P_UNIQIDINFO | PBSD_OLD | PBSD | PBSD_UNIQID, proc_info, &child_pid); + struct proc_uniqidentifierinfo * p_uniqidinfo = (struct proc_uniqidentifierinfo *)proc_info[0]; + struct proc_bsdinfo * pbsd_old = (struct proc_bsdinfo *)proc_info[1]; + struct proc_bsdinfo * pbsd = (struct proc_bsdinfo *)proc_info[2]; + struct proc_bsdinfowithuniqid * pbsd_uniqid = (struct proc_bsdinfowithuniqid *)proc_info[3]; + + T_EXPECT_EQ_UINT((unsigned int)SRUN, pbsd->pbi_status, "PROC_PIDT_BSDINFOWITHUNIQID shows Correct status"); + T_EXPECT_EQ_UINT(0U, pbsd->pbi_xstatus, "PROC_PIDT_BSDINFOWITHUNIQID show Correct xstatus"); + T_EXPECT_EQ_UINT(pbsd_uniqid->pbsd.pbi_pid, (unsigned int)child_pid, "PROC_PIDT_BSDINFOWITHUNIQID returns valid pid"); + T_EXPECT_EQ_UINT(pbsd_uniqid->pbsd.pbi_ppid, (unsigned int)getpid(), "PROC_PIDT_BSDINFOWITHUNIQID returns valid ppid"); + T_EXPECT_EQ_UINT(pbsd_uniqid->pbsd.pbi_uid, CONF_RUID_VAL, "PROC_PIDT_BSDINFOWITHUNIQID returns valid uid"); + T_EXPECT_EQ_UINT(pbsd_uniqid->pbsd.pbi_gid, CONF_GID_VAL, "PROC_PIDT_BSDINFOWITHUNIQID returns valid gid"); + T_EXPECT_EQ_UINT(pbsd_uniqid->pbsd.pbi_ruid, 0U, "PROC_PIDT_BSDINFOWITHUNIQID returns valid ruid"); + T_EXPECT_EQ_UINT(pbsd_uniqid->pbsd.pbi_rgid, CONF_GID_VAL, "PROC_PIDT_BSDINFOWITHUNIQID returns valid rgid"); + T_EXPECT_EQ_UINT(pbsd_uniqid->pbsd.pbi_svuid, CONF_RUID_VAL, "PROC_PIDT_BSDINFOWITHUNIQID returns valid svuid"); + T_EXPECT_EQ_UINT(pbsd_uniqid->pbsd.pbi_svgid, CONF_GID_VAL, "PROC_PIDT_BSDINFOWITHUNIQID returns valid svgid"); + T_EXPECT_EQ_UINT(pbsd_uniqid->pbsd.pbi_nice, CONF_NICE_VAL, "PROC_PIDT_BSDINFOWITHUNIQID returns valid nice value"); + T_EXPECT_EQ_STR(pbsd_uniqid->pbsd.pbi_comm, CONF_CMD_NAME, "PROC_PIDT_BSDINFOWITHUNIQID returns valid p_comm name"); + T_EXPECT_EQ_STR(pbsd_uniqid->pbsd.pbi_name, CONF_CMD_NAME, "PROC_PIDT_BSDINFOWITHUNIQID returns valid p_name name"); + T_EXPECT_EQ_UINT(pbsd_uniqid->pbsd.pbi_flags, (pbsd_old->pbi_flags | PROC_FLAG_PSUGID), + "PROC_PIDT_BSDINFOWITHUNIQID returns valid flags"); + T_EXPECT_EQ_UINT(pbsd_uniqid->pbsd.pbi_nfiles, pbsd_old->pbi_nfiles, "PROC_PIDT_BSDINFOWITHUNIQID returned valid pbi_nfiles"); + T_EXPECT_EQ_UINT(pbsd_uniqid->pbsd.pbi_pgid, (uint32_t)getpgid(getpid()), + "PROC_PIDT_BSDINFOWITHUNIQID returned valid pbi_pgid"); + T_EXPECT_EQ_UINT(pbsd_uniqid->pbsd.pbi_pjobc, pbsd->pbi_pjobc, "PROC_PIDT_BSDINFOWITHUNIQID returned valid pbi_pjobc"); + T_EXPECT_NE_UINT(pbsd_uniqid->pbsd.e_tdev, 0U, "PROC_PIDT_BSDINFOWITHUNIQID returned valid e_tdev"); + T_EXPECT_NE_ULLONG(pbsd_uniqid->p_uniqidentifier.p_uniqueid, p_uniqidinfo->p_uniqueid, + "PROC_PIDT_BSDINFOWITHUNIQID returned valid p_uniqueid"); + for (int i = 0; i < 16; i++) { + T_EXPECT_EQ_UCHAR(pbsd_uniqid->p_uniqidentifier.p_uuid[i], p_uniqidinfo->p_uuid[i], + "PROC_PIDT_BSDINFOWITHUNIQID reported valid p_uniqueid"); + } + T_EXPECT_EQ_ULLONG(pbsd_uniqid->p_uniqidentifier.p_puniqueid, p_uniqidinfo->p_uniqueid, + "p_puniqueid of child should be same as p_uniqueid for parent"); + + free_proc_info(proc_info, 4); +} + +T_DECL(proc_info_proc_pidtask_info, + "Test to verify PROC_PIDTASKINFO returns valid information about the process", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + void * proc_info[2]; + proc_info_caller(P_TASK_INFO | P_TASK_INFO_NEW, proc_info, NULL); + struct proc_taskinfo * p_task_info = (struct proc_taskinfo *)proc_info[0]; + struct proc_taskinfo * p_task_info_new = (struct proc_taskinfo *)proc_info[1]; + + T_EXPECT_GE_ULLONG((p_task_info_new->pti_virtual_size - p_task_info->pti_virtual_size), (unsigned long long)PAGE_SIZE, + "PROC_PIDTASKINFO returned valid value for pti_virtual_size"); + T_EXPECT_GE_ULLONG((p_task_info_new->pti_resident_size - p_task_info->pti_resident_size), (unsigned long long)PAGE_SIZE, + "PROC_PIDTASKINFO returned valid value for pti_virtual_size"); + T_EXPECT_EQ_INT(p_task_info_new->pti_policy, POLICY_TIMESHARE, "PROC_PIDTASKINFO returned valid value for pti_virtual_size"); + T_EXPECT_GE_ULLONG(p_task_info->pti_threads_user, 1ULL, "PROC_PIDTASKINFO returned valid value for pti_threads_user"); +#if defined(__arm__) || defined(__arm64__) + T_EXPECT_GE_ULLONG(p_task_info->pti_threads_system, 0ULL, "PROC_PIDTASKINFO returned valid value for pti_threads_system"); + T_EXPECT_GE_ULLONG((p_task_info_new->pti_total_system - p_task_info->pti_total_system), 0ULL, + "PROC_PIDTASKINFO returned valid value for pti_total_system"); +#else + T_EXPECT_GE_ULLONG(p_task_info->pti_threads_system, 1ULL, "PROC_PIDTASKINFO returned valid value for pti_threads_system"); + T_EXPECT_GT_ULLONG((p_task_info_new->pti_total_system - p_task_info->pti_total_system), 0ULL, + "PROC_PIDTASKINFO returned valid value for pti_total_system"); +#endif + T_EXPECT_GT_ULLONG((p_task_info_new->pti_total_user - p_task_info->pti_total_user), 0ULL, + "PROC_PIDTASKINFO returned valid value for pti_total_user"); + T_EXPECT_GE_INT((p_task_info_new->pti_faults - p_task_info->pti_faults), 1, + "PROC_PIDTASKINFO returned valid value for pti_faults"); + T_EXPECT_GE_INT((p_task_info_new->pti_cow_faults - p_task_info->pti_cow_faults), 1, + "PROC_PIDTASKINFO returned valid value for pti_cow_faults"); + T_EXPECT_GE_INT((p_task_info_new->pti_syscalls_mach - p_task_info->pti_syscalls_mach), 0, + "PROC_PIDTASKINFO returned valid value for pti_syscalls_mach"); + T_EXPECT_GE_INT((p_task_info_new->pti_syscalls_unix - p_task_info->pti_syscalls_unix), 2, + "PROC_PIDTASKINFO returned valid value for pti_syscalls_unix"); + T_EXPECT_EQ_INT((p_task_info_new->pti_messages_sent - p_task_info->pti_messages_sent), 0, + "PROC_PIDTASKINFO returned valid value for pti_messages_sent"); + T_EXPECT_EQ_INT((p_task_info_new->pti_messages_received - p_task_info->pti_messages_received), 0, + "PROC_PIDTASKINFO returned valid value for pti_messages_received"); + T_EXPECT_EQ_INT(p_task_info_new->pti_priority, p_task_info->pti_priority, + "PROC_PIDTASKINFO returned valid value for pti_priority"); + T_EXPECT_GE_INT(p_task_info_new->pti_threadnum, 1, "PROC_PIDTASKINFO returned valid value for pti_threadnum"); + + if (p_task_info_new->pti_threadnum > 1) { + T_LOG("WARN: PROC_PIDTASKINFO returned threadnum greater than 1"); + } + T_EXPECT_GE_INT(p_task_info_new->pti_numrunning, 0, "PROC_PIDTASKINFO returned valid value for pti_numrunning"); + T_EXPECT_GE_INT(p_task_info_new->pti_pageins, 0, "PROC_PIDTASKINFO returned valid value for pti_pageins"); + + if (p_task_info_new->pti_pageins > 0) { + T_LOG("WARN: PROC_PIDTASKINFO returned pageins greater than 0"); + } + + T_EXPECT_GE_INT(p_task_info_new->pti_csw, p_task_info->pti_csw, "PROC_PIDTASKINFO returned valid value for pti_csw"); + + free_proc_info(proc_info, 2); +} + +T_DECL(proc_info_proc_pidtaskallinfo, + "Test to verify PROC_PIDTASKALLINFO returns valid information about the process", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + void * proc_info[4]; + int child_pid = 0; + proc_info_caller(PBSD | PBSD_OLD | P_TASK_INFO | PALL, proc_info, &child_pid); + struct proc_bsdinfo * pbsd = (struct proc_bsdinfo *)proc_info[0]; + struct proc_bsdinfo * pbsd_old = (struct proc_bsdinfo *)proc_info[1]; + struct proc_taskinfo * p_task_info = (struct proc_taskinfo *)proc_info[2]; + struct proc_taskallinfo * pall = (struct proc_taskallinfo *)proc_info[3]; + + T_EXPECT_EQ_UINT((unsigned int)SRUN, pbsd->pbi_status, "PROC_PIDTASKALLINFO shows Correct status"); + T_EXPECT_EQ_UINT(0U, pbsd->pbi_xstatus, "PROC_PIDTASKALLINFO show Correct xstatus"); + T_EXPECT_EQ_UINT(pall->pbsd.pbi_pid, (unsigned int)child_pid, "PROC_PIDTASKALLINFO returns valid pid"); + T_EXPECT_EQ_UINT(pall->pbsd.pbi_ppid, (unsigned int)getpid(), "PROC_PIDTASKALLINFO returns valid ppid"); + T_EXPECT_EQ_UINT(pall->pbsd.pbi_uid, CONF_RUID_VAL, "PROC_PIDTASKALLINFO returns valid uid"); + T_EXPECT_EQ_UINT(pall->pbsd.pbi_gid, CONF_GID_VAL, "PROC_PIDTASKALLINFO returns valid gid"); + T_EXPECT_EQ_UINT(pall->pbsd.pbi_ruid, 0U, "PROC_PIDTASKALLINFO returns valid ruid"); + T_EXPECT_EQ_UINT(pall->pbsd.pbi_rgid, CONF_GID_VAL, "PROC_PIDTASKALLINFO returns valid rgid"); + T_EXPECT_EQ_UINT(pall->pbsd.pbi_svuid, CONF_RUID_VAL, "PROC_PIDTASKALLINFO returns valid svuid"); + T_EXPECT_EQ_UINT(pall->pbsd.pbi_svgid, CONF_GID_VAL, "PROC_PIDTASKALLINFO returns valid svgid"); + T_EXPECT_EQ_INT(pall->pbsd.pbi_nice, CONF_NICE_VAL, "PROC_PIDTASKALLINFO returns valid nice value"); + T_EXPECT_EQ_STR(pall->pbsd.pbi_comm, CONF_CMD_NAME, "PROC_PIDTASKALLINFO returns valid p_comm name"); + T_EXPECT_EQ_STR(pall->pbsd.pbi_name, CONF_CMD_NAME, "PROC_PIDTASKALLINFO returns valid p_name name"); + T_EXPECT_EQ_UINT(pall->pbsd.pbi_flags, (pbsd_old->pbi_flags | PROC_FLAG_PSUGID), "PROC_PIDTASKALLINFO returns valid flags"); + T_EXPECT_EQ_UINT(pall->pbsd.pbi_nfiles, pbsd_old->pbi_nfiles, "PROC_PIDTASKALLINFO returned valid pbi_nfiles"); + T_EXPECT_EQ_UINT(pall->pbsd.pbi_pgid, (uint32_t)getpgid(getpid()), "PROC_PIDTASKALLINFO returned valid pbi_pgid"); + T_EXPECT_EQ_UINT(pall->pbsd.pbi_pjobc, pbsd->pbi_pjobc, "PROC_PIDTASKALLINFO returned valid pbi_pjobc"); + T_EXPECT_NE_UINT(pall->pbsd.e_tdev, 0U, "PROC_PIDTASKALLINFO returned valid e_tdev"); + +#if defined(__arm__) || defined(__arm64__) + T_EXPECT_GE_ULLONG(pall->ptinfo.pti_threads_system, 0ULL, "PROC_PIDTASKALLINFO returned valid value for pti_threads_system"); + T_EXPECT_GE_ULLONG((pall->ptinfo.pti_total_system - p_task_info->pti_total_system), 0ULL, + "PROC_PIDTASKALLINFO returned valid value for pti_total_system"); +#else + T_EXPECT_GE_ULLONG(pall->ptinfo.pti_threads_system, 1ULL, "PROC_PIDTASKALLINFO returned valid value for pti_threads_system"); + T_EXPECT_GT_ULLONG((pall->ptinfo.pti_total_system - p_task_info->pti_total_system), 0ULL, + "PROC_PIDTASKALLINFO returned valid value for pti_total_system"); +#endif /* ARM */ + + T_EXPECT_GE_ULLONG((pall->ptinfo.pti_virtual_size - p_task_info->pti_virtual_size), (unsigned long long)PAGE_SIZE, + "PROC_PIDTASKALLINFO returned valid value for pti_virtual_size"); + T_EXPECT_GE_ULLONG((pall->ptinfo.pti_resident_size - p_task_info->pti_resident_size), (unsigned long long)PAGE_SIZE, + "PROC_PIDTASKALLINFO returned valid value for pti_virtual_size"); + T_EXPECT_EQ_INT(pall->ptinfo.pti_policy, POLICY_TIMESHARE, "PROC_PIDTASKALLINFO returned valid value for pti_virtual_size"); + T_EXPECT_GE_ULLONG(pall->ptinfo.pti_threads_user, 1ULL, "PROC_PIDTASKALLINFO returned valid value for pti_threads_user "); + T_EXPECT_GT_ULLONG((pall->ptinfo.pti_total_user - p_task_info->pti_total_user), 0ULL, + "PROC_PIDTASKALLINFO returned valid value for pti_total_user"); + T_EXPECT_GE_INT((pall->ptinfo.pti_faults - p_task_info->pti_faults), 1, + "PROC_PIDTASKALLINFO returned valid value for pti_faults"); + T_EXPECT_GE_INT((pall->ptinfo.pti_cow_faults - p_task_info->pti_cow_faults), 1, + "PROC_PIDTASKALLINFO returned valid value for pti_cow_faults"); + T_EXPECT_GE_INT((pall->ptinfo.pti_syscalls_mach - p_task_info->pti_syscalls_mach), 0, + "PROC_PIDTASKALLINFO returned valid value for pti_syscalls_mach"); + T_EXPECT_GE_INT((pall->ptinfo.pti_syscalls_unix - p_task_info->pti_syscalls_unix), 2, + "PROC_PIDTASKALLINFO returned valid value for pti_syscalls_unix"); + T_EXPECT_EQ_INT((pall->ptinfo.pti_messages_sent - p_task_info->pti_messages_sent), 0, + "PROC_PIDTASKALLINFO returned valid value for pti_messages_sent"); + T_EXPECT_EQ_INT((pall->ptinfo.pti_messages_received - p_task_info->pti_messages_received), 0, + "PROC_PIDTASKALLINFO returned valid value for pti_messages_received"); + T_EXPECT_EQ_INT(pall->ptinfo.pti_priority, p_task_info->pti_priority, + "PROC_PIDTASKALLINFO returned valid value for pti_priority"); + T_EXPECT_GE_INT(pall->ptinfo.pti_threadnum, 1, "PROC_PIDTASKALLINFO returned valid value for pti_threadnum"); + if (pall->ptinfo.pti_threadnum > 1) { + T_LOG("WARN: PROC_PIDTASKALLINFO returned threadnum greater than 1"); + } + T_EXPECT_GE_INT(pall->ptinfo.pti_numrunning, 0, "PROC_PIDTASKALLINFO returned valid value for pti_numrunning"); + T_EXPECT_GE_INT(pall->ptinfo.pti_pageins, 0, "PROC_PIDTASKALLINFO returned valid value for pti_pageins"); + if (pall->ptinfo.pti_pageins > 0) { + T_LOG("WARN: PROC_PIDTASKALLINFO returned pageins greater than 0"); + } + T_EXPECT_GE_INT(pall->ptinfo.pti_csw, p_task_info->pti_csw, "PROC_PIDTASKALLINFO returned valid value for pti_csw"); + + free_proc_info(proc_info, 4); +} + +T_DECL(proc_info_proc_pidlistthreads, + "Test to verify PROC_PIDLISTTHREADS returns valid information about process", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + void * proc_info[1]; + proc_info_caller(THREAD_ADDR, proc_info, NULL); +} + +T_DECL(proc_info_proc_pidthreadinfo, + "Test to verify PROC_PIDTHREADINFO returns valid information about the process", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + void * proc_info[2]; + int child_pid = 0; + proc_info_caller(PTHINFO_OLD | PTHINFO, proc_info, &child_pid); + struct proc_threadinfo * pthinfo_old = (struct proc_threadinfo *)proc_info[0]; + struct proc_threadinfo * pthinfo = (struct proc_threadinfo *)proc_info[1]; + + T_EXPECT_GT_ULLONG((pthinfo->pth_user_time - pthinfo_old->pth_user_time), 0ULL, + "PROC_PIDTHREADINFO returns valid value for pth_user_time"); + T_EXPECT_GE_ULLONG((pthinfo->pth_system_time - pthinfo_old->pth_system_time), 0ULL, + "PROC_PIDTHREADINFO returns valid value for pth_system_time"); + /* + * This is the scaled cpu usage percentage, since we are not + * doing a really long CPU bound task, it is (nearly) zero + */ + T_EXPECT_GE_INT(pthinfo->pth_cpu_usage, 0, "PROC_PIDTHREADINFO returns valid value for pth_cpu_usage"); + T_EXPECT_EQ_INT(pthinfo->pth_policy, POLICY_TIMESHARE, "PROC_PIDTHREADINFO returns valid value for pth_policy"); + if (!(pthinfo->pth_run_state == TH_STATE_WAITING) && !(pthinfo->pth_run_state == TH_STATE_RUNNING)) { + T_EXPECT_EQ_INT(pthinfo->pth_run_state, -1, "PROC_PIDTHREADINFO returns valid value for pth_run_state"); + } + /* + * This value is hardcoded to 0 in the source, hence it will always + * unconditionally return 0 + */ + T_EXPECT_EQ_INT(pthinfo->pth_sleep_time, 0, "PROC_PIDTHREADINFO returns valid value for pth_sleep_time"); + T_EXPECT_LE_INT(pthinfo->pth_curpri, (BASEPRI_DEFAULT - CONF_NICE_VAL), + "PROC_PIDTHREADINFO returns valid value for pth_curpri"); + T_EXPECT_EQ_INT(pthinfo->pth_priority, (BASEPRI_DEFAULT - CONF_NICE_VAL), + "PROC_PIDTHREADINFO returns valid value for pth_priority"); + T_EXPECT_EQ_INT(pthinfo->pth_maxpriority, MAXPRI_USER, "PROC_PIDTHREADINFO returns valid value for pth_maxpriority"); + T_EXPECT_EQ_STR(pthinfo->pth_name, CONF_THREAD_NAME, "PROC_PIDTHREADINFO returns valid value for pth_name"); + + free_proc_info(proc_info, 2); +} + +T_DECL(proc_info_proc_threadid64info, + "Test to verify PROC_PIDTHREADID64INFO returns valid information about the process", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + void * proc_info[2]; + proc_info_caller(PTHINFO | PTHINFO_64, proc_info, NULL); + struct proc_threadinfo pthinfo = *((struct proc_threadinfo *)proc_info[0]); + struct proc_threadinfo pthinfo_64 = *((struct proc_threadinfo *)proc_info[1]); + T_EXPECT_GE_ULLONG(pthinfo_64.pth_user_time, pthinfo.pth_user_time, + "PROC_PIDTHREADID64INFO returns valid value for pth_user_time"); + T_EXPECT_GE_ULLONG(pthinfo_64.pth_system_time, pthinfo.pth_system_time, + "PROC_PIDTHREADID64INFO returns valid value for pth_system_time"); + T_EXPECT_GE_INT(pthinfo_64.pth_cpu_usage, pthinfo.pth_cpu_usage, + "PROC_PIDTHREADID64INFO returns valid value for pth_cpu_usage"); + T_EXPECT_EQ_INT(pthinfo_64.pth_policy, POLICY_TIMESHARE, "PROC_PIDTHREADID64INFO returns valid value for pth_policy"); + if (!(pthinfo_64.pth_run_state == TH_STATE_WAITING) && !(pthinfo_64.pth_run_state == TH_STATE_RUNNING)) { + T_EXPECT_EQ_INT(pthinfo_64.pth_run_state, -1, "PROC_PIDTHREADID64INFO returns valid value for pth_run_state"); + } + T_EXPECT_EQ_INT(pthinfo_64.pth_sleep_time, 0, "PROC_PIDTHREADID64INFO returns valid value for pth_sleep_time"); + T_EXPECT_EQ_INT(pthinfo_64.pth_curpri, pthinfo.pth_curpri, "PROC_PIDTHREADID64INFO returns valid value for pth_curpri"); + T_EXPECT_EQ_INT(pthinfo_64.pth_priority, pthinfo.pth_priority, "PROC_PIDTHREADID64INFO returns valid value for pth_priority"); + T_EXPECT_EQ_INT(pthinfo_64.pth_maxpriority, pthinfo.pth_maxpriority, + "PROC_PIDTHREADID64INFO returns valid value for pth_maxpriority"); + T_EXPECT_EQ_STR(pthinfo_64.pth_name, CONF_THREAD_NAME, "PROC_PIDTHREADID64INFO returns valid value for pth_name"); + + free_proc_info(proc_info, 2); +} + +T_DECL(proc_info_proc_pidthreadpathinfo, + "Test to verify PROC_PIDTHREADPATHINFO returns valid information about the process", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + void * proc_info[2]; + proc_info_caller(PTHINFO | PINFO_PATH, proc_info, NULL); + struct proc_threadinfo pthinfo = *((struct proc_threadinfo *)proc_info[0]); + struct proc_threadwithpathinfo pinfo_path = *((struct proc_threadwithpathinfo *)proc_info[1]); + + T_EXPECT_GE_ULLONG(pinfo_path.pt.pth_user_time, pthinfo.pth_user_time, + "PROC_PIDTHREADPATHINFO returns valid value for pth_user_time"); + T_EXPECT_GE_ULLONG(pinfo_path.pt.pth_system_time, pthinfo.pth_system_time, + "PROC_PIDTHREADPATHINFO returns valid value for pth_system_time"); + T_EXPECT_GE_INT(pinfo_path.pt.pth_cpu_usage, pthinfo.pth_cpu_usage, + "PROC_PIDTHREADPATHINFO returns valid value for pth_cpu_usage"); + T_EXPECT_EQ_INT(pinfo_path.pt.pth_policy, POLICY_TIMESHARE, "PROC_PIDTHREADPATHINFO returns valid value for pth_policy"); + if (!(pinfo_path.pt.pth_run_state == TH_STATE_WAITING) && !(pinfo_path.pt.pth_run_state == TH_STATE_RUNNING)) { + T_EXPECT_EQ_INT(pinfo_path.pt.pth_run_state, -1, "PROC_PIDTHREADPATHINFO returns valid value for pth_run_state"); + } + T_EXPECT_EQ_INT(pinfo_path.pt.pth_sleep_time, 0, "PROC_PIDTHREADPATHINFO returns valid value for pth_sleep_time"); + T_EXPECT_EQ_INT(pinfo_path.pt.pth_curpri, pthinfo.pth_curpri, "PROC_PIDTHREADPATHINFO returns valid value for pth_curpri"); + T_EXPECT_EQ_INT(pinfo_path.pt.pth_priority, pthinfo.pth_priority, + "PROC_PIDTHREADPATHINFO returns valid value for pth_priority"); + T_EXPECT_EQ_INT(pinfo_path.pt.pth_maxpriority, pthinfo.pth_maxpriority, + "PROC_PIDTHREADPATHINFO returns valid value for pth_maxpriority"); + T_EXPECT_EQ_STR(pinfo_path.pt.pth_name, CONF_THREAD_NAME, "PROC_PIDTHREADPATHINFO returns valid value for pth_name"); + T_EXPECT_EQ_INT(pinfo_path.pvip.vip_vi.vi_type, VNON, "PROC_PIDTHREADPATHINFO valid vnode information"); + + free_proc_info(proc_info, 2); +} + +T_DECL(proc_info_proc_pidarchinfo, + "Test to verify PROC_PIDARCHINFO returns valid information about the process", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + void * proc_info[1]; + proc_info_caller(PAI, proc_info, NULL); + struct proc_archinfo pai = *((struct proc_archinfo *)proc_info[0]); + +#if defined(__arm__) || defined(__arm64__) + if (!((pai.p_cputype & CPU_TYPE_ARM) == CPU_TYPE_ARM) && !((pai.p_cputype & CPU_TYPE_ARM64) == CPU_TYPE_ARM64)) { + T_EXPECT_EQ_INT(pai.p_cputype, CPU_TYPE_ARM, "PROC_PIDARCHINFO returned valid value for p_cputype"); + } + T_EXPECT_EQ_INT((pai.p_cpusubtype & CPU_SUBTYPE_ARM_ALL), CPU_SUBTYPE_ARM_ALL, + "PROC_PIDARCHINFO returned valid value for p_cpusubtype"); +#else + if (!((pai.p_cputype & CPU_TYPE_X86) == CPU_TYPE_X86) && !((pai.p_cputype & CPU_TYPE_X86_64) == CPU_TYPE_X86_64)) { + T_EXPECT_EQ_INT(pai.p_cputype, CPU_TYPE_X86, "PROC_PIDARCHINFO returned valid value for p_cputype"); + } +#endif + free_proc_info(proc_info, 1); +} + +T_DECL(proc_info_proc_pidregioninfo, + "Test to verify PROC_PIDREGIONINFO returns valid information about the process", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + void * proc_info[2]; + void * map_tmp = NULL; + proc_info_caller(PREGINFO, proc_info, NULL); + + struct proc_regioninfo preginfo = *((struct proc_regioninfo *)proc_info[0]); + /* + * map_tmp isn't a struct like the rest of our ret_structs, but we sneak it back because we need it + */ + map_tmp = proc_info[1]; + + T_EXPECT_EQ_ULLONG(preginfo.pri_offset, (unsigned long long)PAGE_SIZE, "PROC_PIDREGIONINFO returns valid value for pri_offset"); + T_EXPECT_EQ_UINT((preginfo.pri_protection ^ (VM_PROT_READ | VM_PROT_WRITE)), 0U, + "PROC_PIDREGIONINFO returns valid value for pri_protection, expected read/write only"); + T_EXPECT_EQ_UINT((preginfo.pri_max_protection & (VM_PROT_READ | VM_PROT_WRITE)), (unsigned int)(VM_PROT_READ | VM_PROT_WRITE), + "PROC_PIDREGIONINFO returns valid value for pri_max_protection"); + T_EXPECT_EQ_UINT((preginfo.pri_inheritance ^ VM_INHERIT_COPY), 0U, + "PROC_PIDREGIONINFO returns valid value for pri_inheritance"); + T_EXPECT_EQ_UINT((preginfo.pri_behavior ^ VM_BEHAVIOR_DEFAULT), 0U, "PROC_PIDREGIONINFO returns valid value for pri_behavior"); + T_EXPECT_EQ_UINT(preginfo.pri_user_wired_count, 0U, "PROC_PIDREGIONINFO returns valid value for pri_user_wired_count"); + T_EXPECT_EQ_UINT(preginfo.pri_user_tag, 0U, "PROC_PIDREGIONINFO returns valid value for pri_user_tag"); + T_EXPECT_NE_UINT((preginfo.pri_flags ^ (PROC_REGION_SUBMAP | PROC_REGION_SHARED)), 0U, + "PROC_PIDREGIONINFO returns valid value for pri_flags"); + T_EXPECT_EQ_UINT(preginfo.pri_pages_resident, 0U, "PROC_PIDREGIONINFO returns valid value for pri_pages_resident"); + T_EXPECT_EQ_UINT(preginfo.pri_pages_shared_now_private, 0U, + "PROC_PIDREGIONINFO returns valid value for pri_pages_shared_now_private"); + T_EXPECT_EQ_UINT(preginfo.pri_pages_swapped_out, 0U, "PROC_PIDREGIONINFO returns valid value for pri_pages_swapped_out"); + T_EXPECT_EQ_UINT(preginfo.pri_pages_dirtied, 0U, "PROC_PIDREGIONINFO returns valid value for pri_pages_dirtied"); + T_EXPECT_EQ_UINT(preginfo.pri_ref_count, 2U, "PROC_PIDREGIONINFO returns valid value for pri_ref_count"); + T_EXPECT_EQ_UINT(preginfo.pri_shadow_depth, 1U, "PROC_PIDREGIONINFO returns valid value for pri_shadow_depth"); + T_EXPECT_EQ_UINT(preginfo.pri_share_mode, (unsigned int)SM_COW, "PROC_PIDREGIONINFO returns valid value for pri_share_mode"); + T_EXPECT_EQ_UINT(preginfo.pri_private_pages_resident, 0U, + "PROC_PIDREGIONINFO returns valid value for pri_private_pages_resident"); + T_EXPECT_GE_UINT(preginfo.pri_shared_pages_resident, 1U, + "PROC_PIDREGIONINFO returns valid value for pri_shared_pages_resident"); + T_EXPECT_EQ_ULLONG(preginfo.pri_address, (uint64_t)map_tmp, "PROC_PIDREGIONINFO returns valid value for pri_addr"); + T_EXPECT_NE_UINT(preginfo.pri_obj_id, 0U, "PROC_PIDREGIONINFO returns valid value for pri_obj_id"); + T_EXPECT_EQ_ULLONG(preginfo.pri_size, (unsigned long long)PAGE_SIZE, "PROC_PIDREGIONINFO returns valid value for pri_size"); + T_EXPECT_EQ_UINT(preginfo.pri_depth, 0U, "PROC_PIDREGIONINFO returns valid value for pri_depth"); + + int ret = 0; + ret = munmap(map_tmp, PAGE_SIZE); + T_QUIET; + T_EXPECT_POSIX_SUCCESS(ret, "munmap of map_tmp"); + free_proc_info(proc_info, 1); +} + +T_DECL(proc_info_proc_pidregionpathinfo, + "Test to verify PROC_PIDREGIONPATHINFO returns valid information about the process", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_INSTALLEDUSEROS)) +{ + void * proc_info[2]; + void * map_tmp = NULL; + proc_info_caller(PREGINFO_PATH, proc_info, NULL); + + struct proc_regionwithpathinfo preginfo_path = *((struct proc_regionwithpathinfo *)proc_info[0]); + /* + * map_tmp isn't a struct like the rest of our ret_structs, but we sneak it back because we need it + */ + map_tmp = proc_info[1]; + + T_EXPECT_EQ_ULLONG(preginfo_path.prp_prinfo.pri_offset, (uint64_t)PAGE_SIZE, + "PROC_PIDREGIONPATHINFO returns valid value for pri_offset"); + T_EXPECT_EQ_UINT((preginfo_path.prp_prinfo.pri_protection ^ (VM_PROT_READ | VM_PROT_WRITE)), 0U, + "PROC_PIDREGIONPATHINFO returns valid value for pri_protection, expected read/write only"); + T_EXPECT_EQ_UINT((preginfo_path.prp_prinfo.pri_max_protection & (VM_PROT_READ | VM_PROT_WRITE)), + (unsigned int)(VM_PROT_READ | VM_PROT_WRITE), + "PROC_PIDREGIONPATHINFO returns valid value for pri_max_protection"); + T_EXPECT_EQ_UINT((preginfo_path.prp_prinfo.pri_inheritance ^ VM_INHERIT_COPY), 0U, + "PROC_PIDREGIONPATHINFO returns valid value for pri_inheritance"); + T_EXPECT_EQ_UINT((preginfo_path.prp_prinfo.pri_behavior ^ VM_BEHAVIOR_DEFAULT), 0U, + "PROC_PIDREGIONPATHINFO returns valid value for pri_behavior"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_user_wired_count, 0U, + "PROC_PIDREGIONPATHINFO returns valid value for pri_user_wired_count"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_user_tag, 0U, "PROC_PIDREGIONPATHINFO returns valid value for pri_user_tag"); + T_EXPECT_NE_UINT((preginfo_path.prp_prinfo.pri_flags ^ (PROC_REGION_SUBMAP | PROC_REGION_SHARED)), 0U, + "PROC_PIDREGIONPATHINFO returns valid value for pri_flags"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_pages_resident, 0U, + "PROC_PIDREGIONPATHINFO returns valid value for pri_pages_resident"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_pages_shared_now_private, 0U, + "PROC_PIDREGIONPATHINFO returns valid value for pri_pages_shared_now_private"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_pages_swapped_out, 0U, + "PROC_PIDREGIONPATHINFO returns valid value for pri_pages_swapped_out"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_pages_dirtied, 0U, + "PROC_PIDREGIONPATHINFO returns valid value for pri_pages_dirtied"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_ref_count, 2U, "PROC_PIDREGIONPATHINFO returns valid value for pri_ref_count"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_shadow_depth, 1U, + "PROC_PIDREGIONPATHINFO returns valid value for pri_shadow_depth"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_share_mode, (unsigned int)SM_COW, + "PROC_PIDREGIONPATHINFO returns valid value for pri_share_mode"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_private_pages_resident, 0U, + "PROC_PIDREGIONPATHINFO returns valid value for pri_private_pages_resident"); + T_EXPECT_GE_UINT(preginfo_path.prp_prinfo.pri_shared_pages_resident, 1U, + "PROC_PIDREGIONPATHINFO returns valid value for pri_shared_pages_resident"); + T_EXPECT_EQ_ULLONG(preginfo_path.prp_prinfo.pri_address, (uint64_t)map_tmp, + "PROC_PIDREGIONPATHINFO returns valid value for pri_addr"); + T_EXPECT_NE_UINT(preginfo_path.prp_prinfo.pri_obj_id, 0U, "PROC_PIDREGIONPATHINFO returns valid value for pri_obj_id"); + T_EXPECT_EQ_ULLONG(preginfo_path.prp_prinfo.pri_size, (uint64_t)PAGE_SIZE, + "PROC_PIDREGIONPATHINFO returns valid value for pri_size"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_depth, 0U, "PROC_PIDREGIONPATHINFO returns valid value for pri_depth"); + T_EXPECT_EQ_INT(preginfo_path.prp_vip.vip_vi.vi_type, VREG, "PROC_PIDREGIONPATHINFO returns valid value for vi_type"); + T_EXPECT_EQ_INT(preginfo_path.prp_vip.vip_vi.vi_pad, 0, "PROC_PIDREGIONPATHINFO returns valid value for vi_pad"); + T_EXPECT_NE_INT(preginfo_path.prp_vip.vip_vi.vi_fsid.val[0], 0, + "PROC_PIDREGIONPATHINFO returns valid value for vi_fsid.val[0]"); + T_EXPECT_NE_INT(preginfo_path.prp_vip.vip_vi.vi_fsid.val[1], 0, + "PROC_PIDREGIONPATHINFO returns valid value for vi_fsid.val[1]"); + T_EXPECT_NE_PTR((void *)(strcasestr(preginfo_path.prp_vip.vip_path, CONF_TMP_FILE_PATH)), NULL, + "PROC_PIDREGIONPATHINFO returns valid value for vi_path"); + /* + * Basic sanity checks for vnode stat returned by the API + */ + T_EXPECT_NE_UINT(preginfo_path.prp_vip.vip_vi.vi_stat.vst_dev, 0U, "PROC_PIDREGIONPATHINFO returns valid value for vst_dev"); + T_EXPECT_EQ_INT(((preginfo_path.prp_vip.vip_vi.vi_stat.vst_mode & S_IFMT) ^ S_IFREG), 0, + "PROC_PIDREGIONPATHINFO returns valid value for vst_mode"); + T_EXPECT_EQ_USHORT(preginfo_path.prp_vip.vip_vi.vi_stat.vst_nlink, (unsigned short)1, + "PROC_PIDREGIONPATHINFO returns valid value for vst_nlink"); + T_EXPECT_NE_ULLONG(preginfo_path.prp_vip.vip_vi.vi_stat.vst_ino, 0ULL, + "PROC_PIDREGIONPATHINFO returns valid value for vst_ino"); + T_EXPECT_EQ_UINT(preginfo_path.prp_vip.vip_vi.vi_stat.vst_uid, 0U, "PROC_PIDREGIONPATHINFO returns valid value for vst_uid"); + T_EXPECT_EQ_UINT(preginfo_path.prp_vip.vip_vi.vi_stat.vst_gid, 0U, "PROC_PIDREGIONPATHINFO returns valid value for vst_gid"); + T_EXPECT_GE_LLONG(preginfo_path.prp_vip.vip_vi.vi_stat.vst_size, (off_t)CONF_BLK_SIZE, + "PROC_PIDREGIONPATHINFO returns valid value for vst_size"); + T_EXPECT_GE_LLONG(preginfo_path.prp_vip.vip_vi.vi_stat.vst_blocks, 1LL, + "PROC_PIDREGIONPATHINFO returns valid value for vst_blocks"); + T_EXPECT_GE_INT(preginfo_path.prp_vip.vip_vi.vi_stat.vst_blksize, CONF_BLK_SIZE, + "PROC_PIDREGIONPATHINFO returns valid value for vst_blksize"); + + int ret = 0; + ret = munmap(map_tmp, PAGE_SIZE); + T_QUIET; + T_EXPECT_POSIX_SUCCESS(ret, "munmap of map_tmp"); + free_proc_info(proc_info, 1); +} + +T_DECL(proc_info_proc_pidregionpathinfo2, + "Test to verify PROC_PIDREGIONPATHINFO2 returns valid information about the process", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_INSTALLEDUSEROS)) +{ + void * proc_info[2]; + void * map_tmp = NULL; + proc_info_caller(PREGINFO_PATH_2, proc_info, NULL); + + struct proc_regionwithpathinfo preginfo_path = *((struct proc_regionwithpathinfo *)proc_info[0]); + /* + * map_tmp isn't a struct like the rest of our ret_structs, but we sneak it back because we need it + */ + map_tmp = proc_info[1]; + + T_EXPECT_EQ_ULLONG(preginfo_path.prp_prinfo.pri_offset, (uint64_t)PAGE_SIZE, + "PROC_PIDREGIONPATHINFO2 returns valid value for pri_offset"); + T_EXPECT_EQ_UINT((preginfo_path.prp_prinfo.pri_protection ^ (VM_PROT_READ | VM_PROT_WRITE)), 0U, + "PROC_PIDREGIONPATHINFO2 returns valid value for pri_protection, expected read/write only"); + T_EXPECT_EQ_UINT((preginfo_path.prp_prinfo.pri_max_protection & (VM_PROT_READ | VM_PROT_WRITE)), + (unsigned int)(VM_PROT_READ | VM_PROT_WRITE), + "PROC_PIDREGIONPATHINFO2 returns valid value for pri_max_protection"); + T_EXPECT_EQ_UINT((preginfo_path.prp_prinfo.pri_inheritance ^ VM_INHERIT_COPY), 0U, + "PROC_PIDREGIONPATHINFO2 returns valid value for pri_inheritance"); + T_EXPECT_EQ_UINT((preginfo_path.prp_prinfo.pri_behavior ^ VM_BEHAVIOR_DEFAULT), 0U, + "PROC_PIDREGIONPATHINFO2 returns valid value for pri_behavior"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_user_wired_count, 0U, + "PROC_PIDREGIONPATHINFO2 returns valid value for pri_user_wired_count"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_user_tag, 0U, "PROC_PIDREGIONPATHINFO2 returns valid value for pri_user_tag"); + T_EXPECT_NE_UINT((preginfo_path.prp_prinfo.pri_flags ^ (PROC_REGION_SUBMAP | PROC_REGION_SHARED)), 0U, + "PROC_PIDREGIONPATHINFO2 returns valid value for pri_flags"); + /* + * Following values are hard-coded to be zero in source + */ + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_pages_resident, 0U, + "PROC_PIDREGIONPATHINFO2 returns valid value for pri_pages_resident"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_pages_shared_now_private, 0U, + "PROC_PIDREGIONPATHINFO2 returns valid value for pri_pages_shared_now_private"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_pages_swapped_out, 0U, + "PROC_PIDREGIONPATHINFO2 returns valid value for pri_pages_swapped_out"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_pages_dirtied, 0U, + "PROC_PIDREGIONPATHINFO2 returns valid value for pri_pages_dirtied"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_ref_count, 0U, "PROC_PIDREGIONPATHINFO2 returns valid value for pri_ref_count"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_shadow_depth, 0U, + "PROC_PIDREGIONPATHINFO2 returns valid value for pri_shadow_depth"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_share_mode, 0U, "PROC_PIDREGIONPATHINFO2 returns valid value for pri_share_mode"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_private_pages_resident, 0U, + "PROC_PIDREGIONPATHINFO2 returns valid value for pri_private_pages_resident"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_shared_pages_resident, 0U, + "PROC_PIDREGIONPATHINFO2 returns valid value for pri_shared_pages_resident"); + T_EXPECT_EQ_ULLONG(preginfo_path.prp_prinfo.pri_address, (uint64_t)map_tmp, + "PROC_PIDREGIONPATHINFO2 returns valid value for pri_addr"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_obj_id, 0U, "PROC_PIDREGIONPATHINFO2 returns valid value for pri_obj_id"); + T_EXPECT_EQ_ULLONG(preginfo_path.prp_prinfo.pri_size, (unsigned long long)PAGE_SIZE, + "PROC_PIDREGIONPATHINFO2 returns valid value for pri_size"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_depth, 0U, "PROC_PIDREGIONPATHINFO2 returns valid value for pri_depth"); + + T_EXPECT_EQ_INT(preginfo_path.prp_vip.vip_vi.vi_type, VREG, "PROC_PIDREGIONPATHINFO2 returns valid value for vi_type"); + T_EXPECT_EQ_INT(preginfo_path.prp_vip.vip_vi.vi_pad, 0, "PROC_PIDREGIONPATHINFO2 returns valid value for vi_pad"); + T_EXPECT_NE_INT(preginfo_path.prp_vip.vip_vi.vi_fsid.val[0], 0, + "PROC_PIDREGIONPATHINFO2 returns valid value for vi_fsid.val[0]:%d", + preginfo_path.prp_vip.vip_vi.vi_fsid.val[0]); + T_EXPECT_NE_INT(preginfo_path.prp_vip.vip_vi.vi_fsid.val[1], 0, + "PROC_PIDREGIONPATHINFO2 returns valid value for vi_fsid.val[1]:%d", + preginfo_path.prp_vip.vip_vi.vi_fsid.val[1]); + T_EXPECT_NE_PTR((void *)(strcasestr(preginfo_path.prp_vip.vip_path, CONF_TMP_FILE_PATH)), NULL, + "PROC_PIDREGIONPATHINFO2 returns valid value for vi_path"); + /* + * Basic sanity checks for vnode stat returned by the API + */ + T_EXPECT_NE_UINT(preginfo_path.prp_vip.vip_vi.vi_stat.vst_dev, 0U, "PROC_PIDREGIONPATHINFO2 returns valid value for vst_dev"); + T_EXPECT_EQ_UINT(((preginfo_path.prp_vip.vip_vi.vi_stat.vst_mode & S_IFMT) ^ S_IFREG), 0, + "PROC_PIDREGIONPATHINFO2 returns valid value for vst_mode"); + T_EXPECT_EQ_USHORT(preginfo_path.prp_vip.vip_vi.vi_stat.vst_nlink, (unsigned short)1, + "PROC_PIDREGIONPATHINFO2 returns valid value for vst_nlink"); + T_EXPECT_NE_ULLONG(preginfo_path.prp_vip.vip_vi.vi_stat.vst_ino, 0ULL, + "PROC_PIDREGIONPATHINFO2 returns valid value for vst_ino"); + T_EXPECT_EQ_UINT(preginfo_path.prp_vip.vip_vi.vi_stat.vst_uid, 0U, "PROC_PIDREGIONPATHINFO2 returns valid value for vst_uid"); + T_EXPECT_EQ_UINT(preginfo_path.prp_vip.vip_vi.vi_stat.vst_gid, 0U, "PROC_PIDREGIONPATHINFO2 returns valid value for vst_gid"); + T_EXPECT_GE_LLONG(preginfo_path.prp_vip.vip_vi.vi_stat.vst_size, (off_t)CONF_BLK_SIZE, + "PROC_PIDREGIONPATHINFO2 returns valid value for vst_size"); + T_EXPECT_GE_LLONG(preginfo_path.prp_vip.vip_vi.vi_stat.vst_blocks, 1LL, + "PROC_PIDREGIONPATHINFO2 returns valid value for vst_blocks"); + T_EXPECT_GE_UINT(preginfo_path.prp_vip.vip_vi.vi_stat.vst_blksize, CONF_BLK_SIZE, + "PROC_PIDREGIONPATHINFO2 returns valid value for vst_blksize"); + + int ret = 0; + ret = munmap(map_tmp, PAGE_SIZE); + T_QUIET; + T_EXPECT_POSIX_SUCCESS(ret, "munmap of map_tmp"); + free_proc_info(proc_info, 1); +} + +T_DECL(proc_info_proc_pidregionpathinfo3, + "Test to verify PROC_PIDREGIONPATHINFO3 returns valid information about the process", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_INSTALLEDUSEROS)) +{ + void * proc_info[1]; + proc_info_caller(PREGINFO_PATH_3, proc_info, NULL); + + struct proc_regionwithpathinfo preginfo_path = *((struct proc_regionwithpathinfo *)proc_info[0]); + + T_EXPECT_GE_ULLONG(preginfo_path.prp_prinfo.pri_offset, (uint64_t)PAGE_SIZE, + "PROC_PIDREGIONPATHINFO3 returns valid value for pri_offset"); + T_EXPECT_NE_UINT((preginfo_path.prp_prinfo.pri_protection ^ (VM_PROT_WRITE | VM_PROT_EXECUTE)), 0U, + "PROC_PIDREGIONPATHINFO3 returns valid value for pri_protection"); +#if defined(__arm__) || defined(__arm64__) + T_EXPECT_GT_UINT(preginfo_path.prp_prinfo.pri_max_protection, 0U, + "PROC_PIDREGIONPATHINFO3 returns valid value for pri_max_protection"); +#else + T_EXPECT_EQ_UINT((preginfo_path.prp_prinfo.pri_max_protection ^ VM_PROT_ALL), 0U, + "PROC_PIDREGIONPATHINFO3 returns valid value for pri_max_protection"); +#endif + T_EXPECT_EQ_UINT((preginfo_path.prp_prinfo.pri_inheritance ^ VM_INHERIT_COPY), 0U, + "PROC_PIDREGIONPATHINFO3 returns valid value for pri_inheritance"); + T_EXPECT_EQ_UINT((preginfo_path.prp_prinfo.pri_behavior ^ VM_BEHAVIOR_DEFAULT), 0U, + "PROC_PIDREGIONPATHINFO3 returns valid value for pri_behavior"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_user_wired_count, 0U, + "PROC_PIDREGIONPATHINFO3 returns valid value for pri_user_wired_count"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_user_tag, 0U, "PROC_PIDREGIONPATHINFO3 returns valid value for pri_user_tag"); + T_EXPECT_NE_UINT((preginfo_path.prp_prinfo.pri_flags ^ (PROC_REGION_SUBMAP | PROC_REGION_SHARED)), 0U, + "PROC_PIDREGIONPATHINFO3 returns valid value for pri_flags"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_pages_resident, 0U, + "PROC_PIDREGIONPATHINFO3 returns valid value for pri_pages_resident"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_pages_shared_now_private, 0U, + "PROC_PIDREGIONPATHINFO3 returns valid value for pri_pages_shared_now_private"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_pages_swapped_out, 0U, + "PROC_PIDREGIONPATHINFO3 returns valid value for pri_pages_swapped_out"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_pages_dirtied, 0U, + "PROC_PIDREGIONPATHINFO3 returns valid value for pri_pages_dirtied"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_ref_count, 0U, "PROC_PIDREGIONPATHINFO3 returns valid value for pri_ref_count"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_shadow_depth, 0U, + "PROC_PIDREGIONPATHINFO3 returns valid value for pri_shadow_depth"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_share_mode, 0U, "PROC_PIDREGIONPATHINFO3 returns valid value for pri_share_mode"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_private_pages_resident, 0U, + "PROC_PIDREGIONPATHINFO3 returns valid value for pri_private_pages_resident"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_shared_pages_resident, 0U, + "PROC_PIDREGIONPATHINFO3 returns valid value for pri_shared_pages_resident"); + T_EXPECT_NE_ULLONG(preginfo_path.prp_prinfo.pri_address, 0ULL, "PROC_PIDREGIONPATHINFO3 returns valid value for pri_addr"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_obj_id, 0U, "PROC_PIDREGIONPATHINFO3 returns valid value for pri_obj_id"); + T_EXPECT_GE_ULLONG(preginfo_path.prp_prinfo.pri_size, (uint64_t)PAGE_SIZE, + "PROC_PIDREGIONPATHINFO3 returns valid value for pri_size"); + T_EXPECT_EQ_UINT(preginfo_path.prp_prinfo.pri_depth, 0U, "PROC_PIDREGIONPATHINFO3 returns valid value for pri_depth"); + + T_EXPECT_EQ_INT(preginfo_path.prp_vip.vip_vi.vi_type, VREG, "PROC_PIDREGIONPATHINFO3 returns valid value for vi_type"); + T_EXPECT_EQ_INT(preginfo_path.prp_vip.vip_vi.vi_pad, 0, "PROC_PIDREGIONPATHINFO3 returns valid value for vi_pad"); + T_EXPECT_NE_INT(preginfo_path.prp_vip.vip_vi.vi_fsid.val[0], 0, + "PROC_PIDREGIONPATHINFO3 returns valid value for vi_fsid.val[0]"); + T_EXPECT_NE_INT(preginfo_path.prp_vip.vip_vi.vi_fsid.val[1], 0, + "PROC_PIDREGIONPATHINFO3 returns valid value for vi_fsid.val[1]"); + /* + * Basic sanity checks for vnode stat returned by the API + */ + T_EXPECT_NE_UINT(preginfo_path.prp_vip.vip_vi.vi_stat.vst_dev, 0U, "PROC_PIDREGIONPATHINFO3 returns valid value for vst_dev"); + T_EXPECT_EQ_UINT(((preginfo_path.prp_vip.vip_vi.vi_stat.vst_mode & S_IFMT) ^ S_IFREG), 0, + "PROC_PIDREGIONPATHINFO3 returns valid value for vst_mode"); + T_EXPECT_EQ_USHORT(preginfo_path.prp_vip.vip_vi.vi_stat.vst_nlink, (unsigned short)1, + "PROC_PIDREGIONPATHINFO3 returns valid value for vst_nlink"); + T_EXPECT_NE_ULLONG(preginfo_path.prp_vip.vip_vi.vi_stat.vst_ino, 0ULL, + "PROC_PIDREGIONPATHINFO3 returns valid value for vst_ino"); + /* + * No way to confirm actual ownership or binary. Just log the value + */ + T_EXPECT_GE_UINT(preginfo_path.prp_vip.vip_vi.vi_stat.vst_uid, 0U, "PROC_PIDREGIONPATHINFO3 returns valid value for vst_uid"); + T_EXPECT_GE_UINT(preginfo_path.prp_vip.vip_vi.vi_stat.vst_gid, 0U, "PROC_PIDREGIONPATHINFO3 returns valid value for vst_gid"); + T_EXPECT_GE_LLONG(preginfo_path.prp_vip.vip_vi.vi_stat.vst_size, (off_t)CONF_BLK_SIZE, + "PROC_PIDREGIONPATHINFO3 returns valid value for vst_size"); + T_EXPECT_GE_LLONG(preginfo_path.prp_vip.vip_vi.vi_stat.vst_blocks, 1LL, + "PROC_PIDREGIONPATHINFO3 returns valid value for vst_blocks"); + T_EXPECT_GE_UINT(preginfo_path.prp_vip.vip_vi.vi_stat.vst_blksize, CONF_BLK_SIZE, + "PROC_PIDREGIONPATHINFO3 returns valid value for vst_blksize"); + + free_proc_info(proc_info, 1); +} + +T_DECL(proc_info_proc_pidvnodepathinfo, + "Test to verify PROC_PIDVNODEPATHINFO returns valid information about the process", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + void * proc_info[1]; + proc_info_caller(PVNINFO, proc_info, NULL); + struct proc_vnodepathinfo pvninfo = *((struct proc_vnodepathinfo *)proc_info[0]); + + T_EXPECT_EQ_INT(pvninfo.pvi_cdir.vip_vi.vi_type, VDIR, "PROC_PIDVNODEPATHINFO returns valid value for vi_type"); + T_EXPECT_EQ_INT(pvninfo.pvi_cdir.vip_vi.vi_pad, 0, "PROC_PIDVNODEPATHINFO returns valid value for vi_pad"); + T_EXPECT_NE_INT(pvninfo.pvi_cdir.vip_vi.vi_fsid.val[0], 0, "PROC_PIDVNODEPATHINFO returns valid value for vi_fsid.val[0]"); + T_EXPECT_NE_INT(pvninfo.pvi_cdir.vip_vi.vi_fsid.val[1], 0, "PROC_PIDVNODEPATHINFO returns valid value for vi_fsid.val[1]"); + /* + * Basic sanity checks for vnode stat returned by the API + */ + T_EXPECT_NE_UINT(pvninfo.pvi_cdir.vip_vi.vi_stat.vst_dev, 0U, "PROC_PIDVNODEPATHINFO returns valid value for vst_dev"); + T_EXPECT_EQ_INT(((pvninfo.pvi_cdir.vip_vi.vi_stat.vst_mode & S_IFMT) ^ S_IFDIR), 0, + "PROC_PIDVNODEPATHINFO returns valid value for vst_mode"); + T_EXPECT_GE_USHORT(pvninfo.pvi_cdir.vip_vi.vi_stat.vst_nlink, (unsigned short)2, + "PROC_PIDVNODEPATHINFO returns valid value for vst_nlink"); + T_EXPECT_NE_ULLONG(pvninfo.pvi_cdir.vip_vi.vi_stat.vst_ino, 0ULL, "PROC_PIDVNODEPATHINFO returns valid value for vst_ino"); + T_EXPECT_GE_UINT(pvninfo.pvi_cdir.vip_vi.vi_stat.vst_uid, 0U, "PROC_PIDREGIONPATHINFO3 returns valid value for vst_uid"); + T_EXPECT_GE_UINT(pvninfo.pvi_cdir.vip_vi.vi_stat.vst_gid, 0U, "PROC_PIDREGIONPATHINFO3 returns valid value for vst_gid"); + T_EXPECT_GT_LLONG(pvninfo.pvi_cdir.vip_vi.vi_stat.vst_size, 0LL, "PROC_PIDVNODEPATHINFO returns valid value for vst_size"); + T_EXPECT_GE_LLONG(pvninfo.pvi_cdir.vip_vi.vi_stat.vst_blocks, 0LL, "PROC_PIDVNODEPATHINFO returns valid value for vst_blocks"); + T_EXPECT_GE_UINT(pvninfo.pvi_cdir.vip_vi.vi_stat.vst_blksize, CONF_BLK_SIZE, + "PROC_PIDVNODEPATHINFO returns valid value for vst_blksize"); + + free_proc_info(proc_info, 1); +} +/* + * The remaining tests break from the pattern of the other PROC_INFO_CALL_PIDINFO tests. + * We call proc_info directly as it's more efficient + */ + +T_DECL(proc_info_pidinfo_proc_pidlistfds, + "proc_info API tests to verify PROC_INFO_CALL_PIDINFO/PROC_PIDLISTFDS", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + int retval; + int orig_nfiles = 0; + struct proc_fdinfo * fd_info = NULL; + + T_LOG("Test to verify PROC_PIDLISTFDS returns sane number of open files"); + retval = __proc_info(PROC_INFO_CALL_PIDINFO, getpid(), PROC_PIDLISTFDS, (uint32_t)0, (user_addr_t)0, (uint32_t)0); + orig_nfiles = retval / (int)sizeof(struct proc_fdinfo); + T_EXPECT_GE_INT(orig_nfiles, CONF_OPN_FILE_COUNT, "The number of open files is lower than expected."); + + /* + * Allocate a buffer of expected size + 1 to ensure that + * the API still returns expected size + * i.e. 3 + 1 = 4 open fds + */ + T_LOG("Test to verify PROC_PIDLISTFDS returns valid fd information"); + fd_info = malloc(sizeof(*fd_info) * 5); + tmp_fd = open(CONF_TMP_FILE_PATH, O_RDONLY | O_CREAT); + T_LOG("tmp_fd val:%d", tmp_fd); + T_QUIET; + T_EXPECT_POSIX_SUCCESS(tmp_fd, "open() for PROC_PIDLISTFDS"); + + retval = __proc_info(PROC_INFO_CALL_PIDINFO, getpid(), PROC_PIDLISTFDS, (uint32_t)0, (user_addr_t)fd_info, + (uint32_t)(sizeof(*fd_info) * 5)); + retval = retval / (int)sizeof(struct proc_fdinfo); + + close(tmp_fd); + + for (int i = 0; i < retval; i++) { + /* + * Check only for the fd that we control. + */ + if (tmp_fd != fd_info[i].proc_fd) { + continue; + } + T_EXPECT_EQ_UINT(fd_info[i].proc_fdtype, (unsigned int)PROX_FDTYPE_VNODE, "Correct proc_fdtype for returned fd"); + } + + T_EXPECT_GE_INT(retval, 4, "Correct number of fds was returned."); + + tmp_fd = -1; + free(fd_info); + fd_info = NULL; +} + +T_DECL(proc_info_proc_pidpathinfo, + "Test to verify PROC_PIDPATHINFO returns valid information about the process", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + char * pid_path = NULL; + pid_path = malloc(sizeof(char) * PROC_PIDPATHINFO_MAXSIZE); + T_EXPECT_NOTNULL(pid_path, "malloc for PROC_PIDPATHINFO"); + int retval = __proc_info(PROC_INFO_CALL_PIDINFO, getpid(), PROC_PIDPATHINFO, (uint64_t)0, (user_addr_t)pid_path, + (uint32_t)PROC_PIDPATHINFO_MAXSIZE); + T_EXPECT_EQ_INT(retval, 0, "__proc_info call for PROC_PIDPATHINFO"); + + T_EXPECT_NE_PTR((void *)(strcasestr(pid_path, CONF_CMD_NAME)), NULL, "PROC_PIDPATHINFOreturns valid value for pid_path"); + free(pid_path); + pid_path = NULL; +} + +T_DECL(proc_info_proc_pidlistfileports, + "Test to verify PROC_PIDLISTFILEPORTS returns valid information about the process", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + struct proc_fileportinfo * fileport_info = NULL; + mach_port_t tmp_file_port = MACH_PORT_NULL; + proc_config_t proc_config = spawn_child_processes(1, proc_info_call_pidinfo_handler); + int child_pid = proc_config->child_pids[0]; + + /* + * Create a file port + */ + tmp_fd = open(CONF_TMP_FILE_PATH, O_RDWR | O_CREAT); + int retval = fileport_makeport(tmp_fd, &tmp_file_port); + T_EXPECT_POSIX_SUCCESS(retval, "fileport_makeport() for PROC_PIDLISTFILEPORTS"); + + /* + * Like the other APIs, this returns the actual count + 20. Hence we expect it to be atleast 1 (that we created) + */ + retval = __proc_info(PROC_INFO_CALL_PIDINFO, getpid(), PROC_PIDLISTFILEPORTS, (uint64_t)0, (user_addr_t)0, (uint32_t)0); + T_EXPECT_GE_INT(retval / (int)sizeof(fileport_info), 1, + "__proc_info call for PROC_PIDLISTFILEPORTS to get total ports in parent"); + + /* + * Child doesn't have any fileports, should return zero + */ + retval = __proc_info(PROC_INFO_CALL_PIDINFO, child_pid, PROC_PIDLISTFILEPORTS, (uint64_t)0, (user_addr_t)0, (uint32_t)0); + T_EXPECT_EQ_INT(retval / (int)sizeof(fileport_info), 0, + "__proc_info call for PROC_PIDLISTFILEPORTS to get total ports in child"); + + fileport_info = malloc(sizeof(*fileport_info) * (size_t)retval); + retval = __proc_info(PROC_INFO_CALL_PIDINFO, getpid(), PROC_PIDLISTFILEPORTS, (uint64_t)0, (user_addr_t)fileport_info, + (uint32_t)sizeof(*fileport_info)); + T_EXPECT_EQ_INT(retval, (int)sizeof(*fileport_info), "__proc_info call for PROC_PIDLISTFILEPORTS"); + + T_EXPECT_NE_UINT(fileport_info->proc_fileport, (uint32_t)0, "PROC_PIDLISTFILEPORTS returns valid value for proc_fileport"); + T_EXPECT_EQ_UINT(fileport_info->proc_fdtype, (uint32_t)PROX_FDTYPE_VNODE, + "PROC_PIDLISTFILEPORTS returns valid value for proc_fdtype"); + + /* + * Cleanup for the fileport + */ + mach_port_deallocate(mach_task_self(), tmp_file_port); + tmp_file_port = MACH_PORT_NULL; + free(fileport_info); + fileport_info = NULL; + close(tmp_fd); + tmp_fd = -1; + free_proc_config(proc_config); +} + +T_DECL(proc_info_proc_pidcoalitioninfo, + "Test to verify PROC_PIDCOALITIONINFO returns valid information about the process", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + proc_config_t proc_config = spawn_child_processes(1, proc_info_call_pidinfo_handler); + int child_pid = proc_config->child_pids[0]; + + struct proc_pidcoalitioninfo pci_parent; + struct proc_pidcoalitioninfo pci_child; + int retval = __proc_info(PROC_INFO_CALL_PIDINFO, getpid(), PROC_PIDCOALITIONINFO, (uint64_t)0, (user_addr_t)&pci_parent, + (uint32_t)sizeof(pci_parent)); + T_EXPECT_EQ_INT(retval, (int)sizeof(pci_parent), "__proc_info call for PROC_PIDCOALITIONINFO (parent)"); + retval = __proc_info(PROC_INFO_CALL_PIDINFO, child_pid, PROC_PIDCOALITIONINFO, (uint64_t)0, (user_addr_t)&pci_child, + (uint32_t)sizeof(pci_child)); + T_EXPECT_EQ_INT(retval, (int)sizeof(pci_child), "__proc_info call for PROC_PIDCOALITIONINFO (child)"); + + /* + * Coalition IDs should match for child and parent + */ + for (int i = 0; i < COALITION_NUM_TYPES; i++) { + T_EXPECT_EQ_ULLONG(pci_parent.coalition_id[i], pci_child.coalition_id[i], + "PROC_PIDCOALITIONINFO returns valid value for coalition_id"); + } + + free_proc_config(proc_config); +} + +T_DECL(proc_info_proc_pidworkqueueinfo, + "Test to verify PROC_PIDWORKQUEUEINFO returns valid information about the process", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + proc_config_t proc_config = spawn_child_processes(1, proc_info_call_pidinfo_handler); + int child_pid = proc_config->child_pids[0]; + send_action_to_child_processes(proc_config, ACT_PHASE5); + + struct proc_workqueueinfo pwqinfo; + usleep(10000); + int retval = __proc_info(PROC_INFO_CALL_PIDINFO, child_pid, PROC_PIDWORKQUEUEINFO, (uint64_t)0, (user_addr_t)&pwqinfo, + (uint32_t)sizeof(pwqinfo)); + T_EXPECT_EQ_INT(retval, (int)sizeof(pwqinfo), "__proc_info call for PROC_PIDWORKQUEUEINFO"); + + int ncpu = 0; + size_t ncpu_size = sizeof(ncpu); + retval = sysctlbyname("hw.ncpu", (void *)&ncpu, &ncpu_size, NULL, 0); + T_EXPECT_EQ_INT(retval, 0, "sysctl() for PROC_PIDWORKQUEUEINFO"); + T_EXPECT_GE_UINT(pwqinfo.pwq_nthreads, (uint32_t)1, "PROC_PIDWORKQUEUEINFO returns valid value for pwq_nthreads"); + T_EXPECT_GE_UINT(pwqinfo.pwq_blockedthreads + pwqinfo.pwq_runthreads, (uint32_t)1, + "PROC_PIDWORKQUEUEINFO returns valid value for pwqinfo.pwq_runthreads/pwq_blockedthreads"); + T_EXPECT_EQ_UINT(pwqinfo.pwq_state, (uint32_t)0, "PROC_PIDWORKQUEUEINFO returns valid value for pwq_state"); + + kill_child_processes(proc_config); + free_proc_config(proc_config); +} +T_DECL(proc_info_proc_pidnoteexit, + "Test to verify PROC_PIDNOTEEXIT returns valid information about the process", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + /* + * Ask the child to close pipe and quit, cleanup pipes for parent + */ + proc_config_t proc_config = spawn_child_processes(1, proc_info_call_pidinfo_handler); + int child_pid = proc_config->child_pids[0]; + send_action_to_child_processes(proc_config, ACT_EXIT); + + uint32_t exit_data = 0; + int retval = __proc_info(PROC_INFO_CALL_PIDINFO, child_pid, PROC_PIDNOTEEXIT, (uint64_t)(NOTE_EXITSTATUS | NOTE_EXIT_DETAIL), + (user_addr_t)&exit_data, (uint32_t)sizeof(exit_data)); + T_EXPECT_EQ_INT(retval, (int)sizeof(exit_data), "__proc_info call for PROC_PIDNOTEEXIT"); + + T_EXPECT_EQ_UINT(exit_data, 0U, "PROC_PIDNOTEEXIT returned valid value for exit_data"); + + free_proc_config(proc_config); +} + +T_DECL(proc_info_negative_tests, + "Test to validate PROC_INFO_CALL_PIDINFO for invalid arguments", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + proc_config_t proc_config = spawn_child_processes(1, proc_info_call_pidinfo_handler); + int child_pid = proc_config->child_pids[0]; + uint32_t exit_data = 0; + + int retval = + __proc_info(PROC_INFO_CALL_PIDINFO, child_pid, PROC_PIDNOTEEXIT, (uint64_t)0, (user_addr_t)&exit_data, (uint32_t)0); + T_EXPECT_EQ_INT(errno, ENOMEM, "PROC_INFO_CALL_PIDINFO call should fail with ENOMEM if buffersize is zero"); + retval = __proc_info(PROC_INFO_CALL_PIDINFO, child_pid, PROC_PIDPATHINFO, (uint64_t)0, (user_addr_t)&exit_data, + (uint32_t)PROC_PIDPATHINFO_MAXSIZE + 1); + T_EXPECT_EQ_INT(errno, EOVERFLOW, + "PROC_INFO_CALL_PIDINFO call should fail with EOVERFLOW if buffersize is larger than PROC_PIDPATHINFO_MAXSIZE"); + retval = __proc_info(PROC_INFO_CALL_PIDINFO, -1, PROC_PIDNOTEEXIT, (uint64_t)0, (user_addr_t)&exit_data, + (uint32_t)sizeof(exit_data)); + T_EXPECT_EQ_INT(errno, ESRCH, "PROC_INFO_CALL_PIDINFO call should fail with ESRCH for invalid process id"); + retval = __proc_info(PROC_INFO_CALL_PIDINFO, child_pid, -1U, (uint64_t)0, (user_addr_t)&exit_data, (uint32_t)sizeof(exit_data)); + T_EXPECT_EQ_INT(errno, EINVAL, "PROC_INFO_CALL_PIDINFO call should fail with EINVAL for invalid flavor"); + retval = __proc_info(PROC_INFO_CALL_PIDINFO, 0, PROC_PIDWORKQUEUEINFO, (uint64_t)0, (user_addr_t)0, (uint32_t)0); + T_EXPECT_EQ_INT(errno, EINVAL, + "PROC_INFO_CALL_PIDINFO call should fail with EINVAL if flavor is PROC_PIDWORKQUEUEINFO and pid=0"); + + free_proc_config(proc_config); +} + +/* + * END PROC_INFO_CALL_PIDINFO DECLs + */ #pragma mark proc_list_uptrs #define NUPTRS 4 -static uint64_t uptrs[NUPTRS] = { - 0x1122334455667788ULL, - 0x99aabbccddeeff00ULL, - 0xaabbaaddccaaffeeULL, - 0xcc000011ccaa7755ULL -}; +static uint64_t uptrs[NUPTRS] = {0x1122334455667788ULL, 0x99aabbccddeeff00ULL, 0xaabbaaddccaaffeeULL, 0xcc000011ccaa7755ULL}; -static const char *uptr_names[NUPTRS]; +static const char * uptr_names[NUPTRS]; static void -print_uptrs(int argc, char * const *argv) +print_uptrs(int argc, char * const * argv) { for (int i = 0; i < argc; i++) { - char *end; + char * end; unsigned long pid = strtoul(argv[i], &end, 0); if (pid > INT_MAX) { printf("error: pid '%lu' would overflow an integer\n", pid); @@ -52,11 +1843,10 @@ print_uptrs(int argc, char * const *argv) /* extra space */ unsigned int uptrs_len = (unsigned int)uptrs_count + 32; - uint64_t *uptrs_alloc = malloc(sizeof(uint64_t) * uptrs_len); + uint64_t * uptrs_alloc = malloc(sizeof(uint64_t) * uptrs_len); os_assert(uptrs_alloc != NULL); - uptrs_count = proc_list_uptrs((int)pid, uptrs_alloc, - (uint32_t)(sizeof(uint64_t) * uptrs_len)); + uptrs_count = proc_list_uptrs((int)pid, uptrs_alloc, (uint32_t)(sizeof(uint64_t) * uptrs_len)); printf("process %d has %d uptrs:\n", (int)pid, uptrs_count); if (uptrs_count > (int)uptrs_len) { uptrs_count = (int)uptrs_len; @@ -67,9 +1857,7 @@ print_uptrs(int argc, char * const *argv) } } -T_DECL(proc_list_uptrs, - "the kernel should return any up-pointers it knows about", - T_META_ALL_VALID_ARCHS(YES)) +T_DECL(proc_list_uptrs, "the kernel should return any up-pointers it knows about", T_META_ALL_VALID_ARCHS(YES)) { if (argc > 0) { print_uptrs(argc, argv); @@ -79,7 +1867,8 @@ T_DECL(proc_list_uptrs, unsigned int cur_uptr = 0; int kq = kqueue(); - T_QUIET; T_ASSERT_POSIX_SUCCESS(kq, "kqueue"); + T_QUIET; + T_ASSERT_POSIX_SUCCESS(kq, "kqueue"); /* * Should find uptrs on file-type knotes and generic knotes (two @@ -89,47 +1878,42 @@ T_DECL(proc_list_uptrs, memset(events, 0, sizeof(events)); uptr_names[cur_uptr] = "kqueue file-backed knote"; - events[0].filter = EVFILT_WRITE; - events[0].ident = STDOUT_FILENO; - events[0].flags = EV_ADD; - events[0].udata = uptrs[cur_uptr++]; + events[0].filter = EVFILT_WRITE; + events[0].ident = STDOUT_FILENO; + events[0].flags = EV_ADD; + events[0].udata = uptrs[cur_uptr++]; uptr_names[cur_uptr] = "kqueue non-file-backed knote"; - events[1].filter = EVFILT_USER; - events[1].ident = 1; - events[1].flags = EV_ADD; - events[1].udata = uptrs[cur_uptr++]; + events[1].filter = EVFILT_USER; + events[1].ident = 1; + events[1].flags = EV_ADD; + events[1].udata = uptrs[cur_uptr++]; - int kev_err = kevent64(kq, events, sizeof(events) / sizeof(events[0]), NULL, - 0, KEVENT_FLAG_IMMEDIATE, NULL); + int kev_err = kevent64(kq, events, sizeof(events) / sizeof(events[0]), NULL, 0, KEVENT_FLAG_IMMEDIATE, NULL); T_ASSERT_POSIX_SUCCESS(kev_err, "register events with kevent64"); /* * Should find uptrs both on a kevent_id kqueue and in a workloop * kqueue's knote's udata field. */ - uptr_names[cur_uptr] = "dynamic kqueue non-file-backed knote"; - struct kevent_qos_s events_id[] = {{ - .filter = EVFILT_USER, - .ident = 1, - .flags = EV_ADD, - .udata = uptrs[cur_uptr++] - }}; + uptr_names[cur_uptr] = "dynamic kqueue non-file-backed knote"; + struct kevent_qos_s events_id[] = {{.filter = EVFILT_USER, .ident = 1, .flags = EV_ADD, .udata = uptrs[cur_uptr++]}}; uptr_names[cur_uptr] = "dynamic kqueue ID"; - kev_err = kevent_id(uptrs[cur_uptr++], events_id, 1, NULL, 0, NULL, NULL, - KEVENT_FLAG_WORKLOOP | KEVENT_FLAG_IMMEDIATE); + kev_err = kevent_id(uptrs[cur_uptr++], events_id, 1, NULL, 0, NULL, NULL, KEVENT_FLAG_WORKLOOP | KEVENT_FLAG_IMMEDIATE); T_ASSERT_POSIX_SUCCESS(kev_err, "register event with kevent_id"); - errno = 0; + errno = 0; int uptrs_count = proc_list_uptrs(getpid(), NULL, 0); - T_QUIET; T_ASSERT_POSIX_SUCCESS(uptrs_count, "proc_list_uptrs"); - T_QUIET; T_EXPECT_EQ(uptrs_count, NUPTRS, - "should see correct number of up-pointers"); + T_QUIET; + T_ASSERT_POSIX_SUCCESS(uptrs_count, "proc_list_uptrs"); + T_QUIET; + T_EXPECT_EQ(uptrs_count, NUPTRS, "should see correct number of up-pointers"); - uint64_t uptrs_obs[NUPTRS] = { 0 }; - uptrs_count = proc_list_uptrs(getpid(), uptrs_obs, sizeof(uptrs_obs)); - T_QUIET; T_ASSERT_POSIX_SUCCESS(uptrs_count, "proc_list_uptrs"); + uint64_t uptrs_obs[NUPTRS] = {0}; + uptrs_count = proc_list_uptrs(getpid(), uptrs_obs, sizeof(uptrs_obs)); + T_QUIET; + T_ASSERT_POSIX_SUCCESS(uptrs_count, "proc_list_uptrs"); for (int i = 0; i < uptrs_count; i++) { int found = -1; @@ -140,7 +1924,7 @@ T_DECL(proc_list_uptrs, } } T_FAIL("unexpected up-pointer found: %#" PRIx64, uptrs_obs[i]); -next:; + next:; if (found != -1) { T_PASS("found up-pointer for %s", uptr_names[found]); } @@ -153,7 +1937,7 @@ next:; #pragma mark dynamic kqueue info -#define EXPECTED_ID UINT64_C(0x1122334455667788) +#define EXPECTED_ID UINT64_C(0x1122334455667788) #define EXPECTED_UDATA UINT64_C(0x99aabbccddeeff00) #ifndef KQ_WORKLOOP #define KQ_WORKLOOP 0x80 @@ -162,35 +1946,31 @@ next:; static void setup_kevent_id(kqueue_id_t id) { - struct kevent_qos_s events_id[] = {{ - .filter = EVFILT_USER, - .ident = 1, - .flags = EV_ADD, - .udata = EXPECTED_UDATA - }}; + struct kevent_qos_s events_id[] = {{.filter = EVFILT_USER, .ident = 1, .flags = EV_ADD, .udata = EXPECTED_UDATA}}; - int err = kevent_id(id, events_id, 1, NULL, 0, NULL, NULL, - KEVENT_FLAG_WORKLOOP | KEVENT_FLAG_IMMEDIATE); + int err = kevent_id(id, events_id, 1, NULL, 0, NULL, NULL, KEVENT_FLAG_WORKLOOP | KEVENT_FLAG_IMMEDIATE); T_ASSERT_POSIX_SUCCESS(err, "register event with kevent_id"); } static kqueue_id_t * -list_kqids(pid_t pid, int *nkqids_out) +list_kqids(pid_t pid, int * nkqids_out) { int kqids_len = 256; int nkqids; - kqueue_id_t *kqids = NULL; + kqueue_id_t * kqids = NULL; uint32_t kqids_size; retry: if (os_mul_overflow(sizeof(kqueue_id_t), kqids_len, &kqids_size)) { - T_QUIET; T_ASSERT_GT(kqids_len, PROC_PIDDYNKQUEUES_MAX, NULL); + T_QUIET; + T_ASSERT_GT(kqids_len, PROC_PIDDYNKQUEUES_MAX, NULL); kqids_len = PROC_PIDDYNKQUEUES_MAX; goto retry; } if (!kqids) { kqids = malloc(kqids_size); - T_QUIET; T_ASSERT_NOTNULL(kqids, "malloc(%" PRIu32 ")", kqids_size); + T_QUIET; + T_ASSERT_NOTNULL(kqids, "malloc(%" PRIu32 ")", kqids_size); } nkqids = proc_list_dynkqueueids(pid, kqids, kqids_size); @@ -208,15 +1988,13 @@ list_kqids(pid_t pid, int *nkqids_out) return kqids; } -T_DECL(list_dynamic_kqueues, - "the kernel should list IDs of dynamic kqueues", - T_META_ALL_VALID_ARCHS(true)) +T_DECL(list_dynamic_kqueues, "the kernel should list IDs of dynamic kqueues", T_META_ALL_VALID_ARCHS(true)) { int nkqids; bool found = false; setup_kevent_id(EXPECTED_ID); - kqueue_id_t *kqids = list_kqids(getpid(), &nkqids); + kqueue_id_t * kqids = list_kqids(getpid(), &nkqids); T_ASSERT_GE(nkqids, 1, "at least one dynamic kqueue is listed"); for (int i = 0; i < nkqids; i++) { if (kqids[i] == EXPECTED_ID) { @@ -234,93 +2012,81 @@ T_DECL(list_dynamic_kqueues, free(kqids); } -T_DECL(dynamic_kqueue_basic_info, - "the kernel should report valid basic dynamic kqueue info", - T_META_ALL_VALID_ARCHS(true)) +T_DECL(dynamic_kqueue_basic_info, "the kernel should report valid basic dynamic kqueue info", T_META_ALL_VALID_ARCHS(true)) { struct kqueue_info kqinfo; int ret; setup_kevent_id(EXPECTED_ID); - ret = proc_piddynkqueueinfo(getpid(), PROC_PIDDYNKQUEUE_INFO, EXPECTED_ID, - &kqinfo, sizeof(kqinfo)); - T_ASSERT_POSIX_SUCCESS(ret, - "proc_piddynkqueueinfo(... PROC_PIDDYNKQUEUE_INFO ...)"); - T_QUIET; T_ASSERT_GE(ret, (int)sizeof(kqinfo), - "PROC_PIDDYNKQUEUE_INFO should return the right size"); + ret = proc_piddynkqueueinfo(getpid(), PROC_PIDDYNKQUEUE_INFO, EXPECTED_ID, &kqinfo, sizeof(kqinfo)); + T_ASSERT_POSIX_SUCCESS(ret, "proc_piddynkqueueinfo(... PROC_PIDDYNKQUEUE_INFO ...)"); + T_QUIET; + T_ASSERT_GE(ret, (int)sizeof(kqinfo), "PROC_PIDDYNKQUEUE_INFO should return the right size"); - T_EXPECT_NE(kqinfo.kq_state & KQ_WORKLOOP, 0U, - "kqueue info should be for a workloop kqueue"); - T_EXPECT_EQ(kqinfo.kq_stat.vst_ino, EXPECTED_ID, - "inode field should be the kqueue's ID"); + T_EXPECT_NE(kqinfo.kq_state & KQ_WORKLOOP, 0U, "kqueue info should be for a workloop kqueue"); + T_EXPECT_EQ(kqinfo.kq_stat.vst_ino, EXPECTED_ID, "inode field should be the kqueue's ID"); } -T_DECL(dynamic_kqueue_extended_info, - "the kernel should report valid extended dynamic kqueue info", - T_META_ALL_VALID_ARCHS(true)) +T_DECL(dynamic_kqueue_extended_info, "the kernel should report valid extended dynamic kqueue info", T_META_ALL_VALID_ARCHS(true)) { struct kevent_extinfo kqextinfo[1]; int ret; setup_kevent_id(EXPECTED_ID); - ret = proc_piddynkqueueinfo(getpid(), PROC_PIDDYNKQUEUE_EXTINFO, - EXPECTED_ID, kqextinfo, sizeof(kqextinfo)); - T_ASSERT_POSIX_SUCCESS(ret, - "proc_piddynkqueueinfo(... PROC_PIDDYNKQUEUE_EXTINFO ...)"); - T_QUIET; T_ASSERT_EQ(ret, 1, - "PROC_PIDDYNKQUEUE_EXTINFO should return a single knote"); + ret = proc_piddynkqueueinfo(getpid(), PROC_PIDDYNKQUEUE_EXTINFO, EXPECTED_ID, kqextinfo, sizeof(kqextinfo)); + T_ASSERT_POSIX_SUCCESS(ret, "proc_piddynkqueueinfo(... PROC_PIDDYNKQUEUE_EXTINFO ...)"); + T_QUIET; + T_ASSERT_EQ(ret, 1, "PROC_PIDDYNKQUEUE_EXTINFO should return a single knote"); - T_EXPECT_EQ(kqextinfo[0].kqext_kev.ident, 1ULL, - "kevent identifier matches what was configured"); - T_EXPECT_EQ(kqextinfo[0].kqext_kev.filter, (short)EVFILT_USER, - "kevent filter matches what was configured"); - T_EXPECT_EQ(kqextinfo[0].kqext_kev.udata, EXPECTED_UDATA, - "kevent udata matches what was configured"); + T_EXPECT_EQ(kqextinfo[0].kqext_kev.ident, 1ULL, "kevent identifier matches what was configured"); + T_EXPECT_EQ(kqextinfo[0].kqext_kev.filter, (short)EVFILT_USER, "kevent filter matches what was configured"); + T_EXPECT_EQ(kqextinfo[0].kqext_kev.udata, EXPECTED_UDATA, "kevent udata matches what was configured"); } #pragma mark proc_listpids -T_DECL(list_kdebug_pids, - "the kernel should report processes that are filtered by kdebug", - T_META_ASROOT(YES)) +T_DECL(list_kdebug_pids, "the kernel should report processes that are filtered by kdebug", T_META_ASROOT(YES)) { - int mib[4] = { CTL_KERN, KERN_KDEBUG }; + int mib[4] = {CTL_KERN, KERN_KDEBUG}; int npids; int pids[1]; int ret; - kd_regtype reg = {}; + kd_regtype reg; size_t regsize = sizeof(reg); mib[2] = KERN_KDREMOVE; - ret = sysctl(mib, 3, NULL, NULL, NULL, 0); - T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "KERN_KDREMOVE sysctl"); + ret = sysctl(mib, 3, NULL, NULL, NULL, 0); + T_QUIET; + T_ASSERT_POSIX_SUCCESS(ret, "KERN_KDREMOVE sysctl"); - mib[2] = KERN_KDSETBUF; mib[3] = 100000; - ret = sysctl(mib, 4, NULL, NULL, NULL, 0); - T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "KERN_KDSETBUF sysctl"); + mib[2] = KERN_KDSETBUF; + mib[3] = 100000; + ret = sysctl(mib, 4, NULL, NULL, NULL, 0); + T_QUIET; + T_ASSERT_POSIX_SUCCESS(ret, "KERN_KDSETBUF sysctl"); mib[2] = KERN_KDSETUP; - ret = sysctl(mib, 3, NULL, NULL, NULL, 0); - T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "KERN_KDSETUP sysctl"); + ret = sysctl(mib, 3, NULL, NULL, NULL, 0); + T_QUIET; + T_ASSERT_POSIX_SUCCESS(ret, "KERN_KDSETUP sysctl"); npids = proc_listpids(PROC_KDBG_ONLY, 0, pids, sizeof(pids)); T_EXPECT_EQ(npids, 0, "no processes should be filtered initially"); - reg.type = KDBG_TYPENONE; - reg.value1 = getpid(); + reg.type = KDBG_TYPENONE; + reg.value1 = (unsigned int)getpid(); reg.value2 = 1; /* set the pid in the filter */ - mib[2] = KERN_KDPIDTR; - ret = sysctl(mib, 3, ®, ®size, NULL, 0); - T_ASSERT_POSIX_SUCCESS(ret, - "KERN_KDPIDTR sysctl to set a pid in the filter"); + mib[2] = KERN_KDPIDTR; + ret = sysctl(mib, 3, ®, ®size, NULL, 0); + T_ASSERT_POSIX_SUCCESS(ret, "KERN_KDPIDTR sysctl to set a pid in the filter"); npids = proc_listpids(PROC_KDBG_ONLY, 0, pids, sizeof(pids)); npids /= 4; T_EXPECT_EQ(npids, 1, "a process should be filtered"); - T_EXPECT_EQ(pids[0], getpid(), - "process filtered should be the one that was set"); + T_EXPECT_EQ(pids[0], getpid(), "process filtered should be the one that was set"); mib[2] = KERN_KDREMOVE; - ret = sysctl(mib, 3, NULL, NULL, NULL, 0); - T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "KERN_KDREMOVE sysctl"); + ret = sysctl(mib, 3, NULL, NULL, NULL, 0); + T_QUIET; + T_ASSERT_POSIX_SUCCESS(ret, "KERN_KDREMOVE sysctl"); } diff --git a/tools/tests/darwintests/proc_info_udata.c b/tools/tests/darwintests/proc_info_udata.c new file mode 100644 index 000000000..f814be4e3 --- /dev/null +++ b/tools/tests/darwintests/proc_info_udata.c @@ -0,0 +1,47 @@ +#include +#include "../../../bsd/sys/proc_info.h" +#include "../../../libsyscall/wrappers/libproc/libproc.h" +#include +#include + +T_DECL(proc_udata_info, "Get and set a proc udata token"){ + uint64_t token = mach_absolute_time(); + proc_info_udata_t udata; + int ret; + + udata = token; + ret = proc_udata_info(getpid(), PROC_UDATA_INFO_SET, &udata, sizeof (udata)); + +#if CONFIG_EMBEDDED + T_WITH_ERRNO; + T_ASSERT_EQ_INT(ret, -1, "proc_udata_info PROC_UDATA_INFO_SET returns error on non-macOS"); + T_SKIP("Remaining tests are only supported on macOS"); +#endif /* CONFIG_EMBEDDED */ + + T_WITH_ERRNO; + T_ASSERT_EQ_INT(ret, 0, "proc_udata_info PROC_UDATA_INFO_SET"); + + T_LOG("udata set to %#llx", udata); + + bzero(&udata, sizeof (udata)); + ret = proc_udata_info(getpid(), PROC_UDATA_INFO_GET, &udata, sizeof (udata)); + T_WITH_ERRNO; + T_ASSERT_EQ_INT(ret, 0, "proc_udata_info PROC_UDATA_INFO_GET"); + + T_ASSERT_EQ_ULLONG(token, udata, "proc_udata_info(): retrieved value matches token"); + + ret = proc_udata_info(getpid(), PROC_UDATA_INFO_SET, &udata, sizeof (uint32_t)); + T_WITH_ERRNO; + T_ASSERT_EQ_INT(ret, -1, "proc_udata_info PROC_UDATA_INFO_SET with invalid size returned -1"); + T_ASSERT_EQ_INT(errno, EINVAL, "proc_udata_info PROC_UDATA_INFO_SET with invalid size returned EINVAL"); + + ret = proc_udata_info(getppid(), PROC_UDATA_INFO_GET, &udata, sizeof (udata)); + T_WITH_ERRNO; + T_ASSERT_EQ_INT(ret, -1, "proc_udata_info PROC_UDATA_INFO_GET returned -1 on attempt against non-self pid"); + T_ASSERT_EQ_INT(errno, EACCES, "proc_udata_info PROC_UDATA_INFO_GET set errno to EACCES on attempt against non-self pid"); + + ret = proc_udata_info(getppid(), PROC_UDATA_INFO_SET, &udata, sizeof (udata)); + T_WITH_ERRNO; + T_ASSERT_EQ_INT(ret, -1, "proc_udata_info PROC_UDATA_INFO_SET returned -1 on attempt against non-self pid"); + T_ASSERT_EQ_INT(errno, EACCES, "proc_udata_info PROC_UDATA_INFO_SET set errno to EACCES on attempt against non-self pid"); +} diff --git a/tools/tests/darwintests/settimeofday_29193041.c b/tools/tests/darwintests/settimeofday_29193041.c index ae6d68b88..6bb495ddb 100644 --- a/tools/tests/darwintests/settimeofday_29193041.c +++ b/tools/tests/darwintests/settimeofday_29193041.c @@ -15,8 +15,6 @@ #include #endif -#define EXIT_FAIL() exit((__LINE__ % 255) + 1) - /* * This test expects the entitlement or root privileges for a process to * set the time using settimeofday syscall. @@ -24,74 +22,9 @@ #define DAY 86400 //1 day in sec -/* - * To run without root privileges - * libdarwintest should run leaks even without root - */ -static void drop_priv(void){ - /* determine the less-privileged UID and GID */ - - unsigned long lower_uid = 0; - unsigned long lower_gid = 0; - -#if CONFIG_EMBEDDED - struct passwd *pw = getpwnam("mobile"); - if (!pw) { - printf("child: error: get_pwname(\"mobile\") failed %d: %s\n", errno, strerror(errno)); - EXIT_FAIL(); - } - - lower_uid = pw->pw_uid; - lower_gid = pw->pw_gid; -#else - char *sudo_gid_str = getenv("SUDO_GID"); - if (!sudo_gid_str) { - printf("child: error: SUDO_GID environment variable unset (not run under sudo)\n"); - EXIT_FAIL(); - } - - char *sudo_uid_str = getenv("SUDO_UID"); - if (!sudo_uid_str) { - printf("child: error: SUDO_UID environment variable unset (not run under sudo)\n"); - EXIT_FAIL(); - } - - char *end = sudo_gid_str; - lower_gid = strtoul(sudo_gid_str, &end, 10); - if (sudo_gid_str == end && sudo_gid_str[0] != '\0') { - printf("child: error: SUDO_GID (%s) could not be converted to an integer\n", sudo_gid_str); - EXIT_FAIL(); - } - if (lower_gid == 0) { - printf("child: error: less-privileged GID invalid\n"); - EXIT_FAIL(); - } - - end = sudo_uid_str; - lower_uid = strtoul(sudo_uid_str, &end, 10); - if (sudo_uid_str == end && sudo_uid_str[0] != '\0') { - printf("child: error: SUDO_UID (%s) could not be converted to an integer\n", sudo_uid_str); - EXIT_FAIL(); - } - if (lower_gid == 0) { - printf("child: error: less-privileged UID invalid\n"); - EXIT_FAIL(); - } -#endif - - if (setgid(lower_gid) == -1) { - printf("child: error: could not change group to %lu\n", lower_gid); - EXIT_FAIL(); - } - if (setuid(lower_uid) == -1) { - printf("child: error: could not change user to %lu\n", lower_uid); - EXIT_FAIL(); - } -} - T_DECL(settime_32089962_not_entitled_root, "Verify that root privileges can allow to change the time", - T_META_ASROOT(true), T_META_CHECK_LEAKS(NO)) + T_META_ASROOT(true), T_META_CHECK_LEAKS(false)) { struct timeval settimeofdaytime; struct timeval adj_time; @@ -120,15 +53,13 @@ T_DECL(settime_32089962_not_entitled_root, T_DECL(settime_32089962_not_entitled_not_root, "Verify that the \"com.apple.settime\" entitlement can allow to change the time", - T_META_ASROOT(false), T_META_CHECK_LEAKS(NO)) + T_META_ASROOT(false), T_META_CHECK_LEAKS(false)) { struct timeval settimeofdaytime; struct timeval adj_time; struct timex ntptime; int res; - drop_priv(); - if (geteuid() == 0){ T_SKIP("settimeofday_29193041 test requires no root privileges to run."); } @@ -159,7 +90,7 @@ T_DECL(settime_32089962_not_entitled_not_root, T_DECL(settimeofday_29193041_not_entitled_root, "Verify that root privileges can allow to change the time", - T_META_ASROOT(true), T_META_CHECK_LEAKS(NO)) + T_META_ASROOT(true), T_META_CHECK_LEAKS(false)) { struct timeval time; long new_time; @@ -189,13 +120,11 @@ T_DECL(settimeofday_29193041_not_entitled_root, T_DECL(settimeofday_29193041_not_entitled_not_root, "Verify that the \"com.apple.settime\" entitlement can allow to change the time", - T_META_ASROOT(false), T_META_CHECK_LEAKS(NO)) + T_META_ASROOT(false), T_META_CHECK_LEAKS(false)) { struct timeval time; long new_time; - drop_priv(); - if (geteuid() == 0){ T_SKIP("settimeofday_29193041 test requires no root privileges to run."); } diff --git a/tools/tests/darwintests/settimeofday_29193041_entitled.c b/tools/tests/darwintests/settimeofday_29193041_entitled.c index a68c6cac8..51ca5a5ed 100644 --- a/tools/tests/darwintests/settimeofday_29193041_entitled.c +++ b/tools/tests/darwintests/settimeofday_29193041_entitled.c @@ -15,8 +15,6 @@ #include #endif -#define EXIT_FAIL() exit((__LINE__ % 255) + 1) - /* * This test expects the entitlement or root privileges for a process to * set the time using settimeofday syscall. @@ -24,74 +22,9 @@ #define DAY 86400 //1 day in sec -/* - * To run without root privileges - * libdarwintest should run leaks even without root - */ -static void drop_priv(void){ - /* determine the less-privileged UID and GID */ - - unsigned long lower_uid = 0; - unsigned long lower_gid = 0; - -#if CONFIG_EMBEDDED - struct passwd *pw = getpwnam("mobile"); - if (!pw) { - printf("child: error: get_pwname(\"mobile\") failed %d: %s\n", errno, strerror(errno)); - EXIT_FAIL(); - } - - lower_uid = pw->pw_uid; - lower_gid = pw->pw_gid; -#else - char *sudo_gid_str = getenv("SUDO_GID"); - if (!sudo_gid_str) { - printf("child: error: SUDO_GID environment variable unset (not run under sudo)\n"); - EXIT_FAIL(); - } - - char *sudo_uid_str = getenv("SUDO_UID"); - if (!sudo_uid_str) { - printf("child: error: SUDO_UID environment variable unset (not run under sudo)\n"); - EXIT_FAIL(); - } - - char *end = sudo_gid_str; - lower_gid = strtoul(sudo_gid_str, &end, 10); - if (sudo_gid_str == end && sudo_gid_str[0] != '\0') { - printf("child: error: SUDO_GID (%s) could not be converted to an integer\n", sudo_gid_str); - EXIT_FAIL(); - } - if (lower_gid == 0) { - printf("child: error: less-privileged GID invalid\n"); - EXIT_FAIL(); - } - - end = sudo_uid_str; - lower_uid = strtoul(sudo_uid_str, &end, 10); - if (sudo_uid_str == end && sudo_uid_str[0] != '\0') { - printf("child: error: SUDO_UID (%s) could not be converted to an integer\n", sudo_uid_str); - EXIT_FAIL(); - } - if (lower_gid == 0) { - printf("child: error: less-privileged UID invalid\n"); - EXIT_FAIL(); - } -#endif - - if (setgid(lower_gid) == -1) { - printf("child: error: could not change group to %lu\n", lower_gid); - EXIT_FAIL(); - } - if (setuid(lower_uid) == -1) { - printf("child: error: could not change user to %lu\n", lower_uid); - EXIT_FAIL(); - } -} - T_DECL(settime_32089962_entitled_root, "Verify that root privileges can allow to change the time", - T_META_ASROOT(true), T_META_CHECK_LEAKS(NO)) + T_META_ASROOT(true), T_META_CHECK_LEAKS(false)) { struct timeval settimeofdaytime; struct timeval adj_time; @@ -120,15 +53,13 @@ T_DECL(settime_32089962_entitled_root, T_DECL(settime_32089962_entitled_not_root, "Verify that the \"com.apple.settime\" entitlement can allow to change the time", - T_META_ASROOT(false), T_META_CHECK_LEAKS(NO)) + T_META_ASROOT(false), T_META_CHECK_LEAKS(false)) { struct timeval settimeofdaytime; struct timeval adj_time; struct timex ntptime; - drop_priv(); - if (geteuid() == 0){ T_SKIP("settime_32089962_entitled_root test requires no root privileges to run."); } @@ -153,7 +84,7 @@ T_DECL(settime_32089962_entitled_not_root, T_DECL(settimeofday_29193041_entitled_root, "Verify that root privileges can allow to change the time", - T_META_ASROOT(true), T_META_CHECK_LEAKS(NO)) + T_META_ASROOT(true), T_META_CHECK_LEAKS(false)) { struct timeval time; long new_time; @@ -183,13 +114,11 @@ T_DECL(settimeofday_29193041_entitled_root, T_DECL(settimeofday_29193041_entitled_not_root, "Verify that the \"com.apple.settime\" entitlement can allow to change the time", - T_META_ASROOT(false), T_META_CHECK_LEAKS(NO)) + T_META_ASROOT(false), T_META_CHECK_LEAKS(false)) { struct timeval time; long new_time; - drop_priv(); - if (geteuid() == 0){ T_SKIP("settimeofday_29193041 test requires no root privileges to run."); } diff --git a/tools/tests/darwintests/socket_bind_35243417.c b/tools/tests/darwintests/socket_bind_35243417.c index de5eed5d5..cb44aa53f 100644 --- a/tools/tests/darwintests/socket_bind_35243417.c +++ b/tools/tests/darwintests/socket_bind_35243417.c @@ -7,7 +7,6 @@ #include #include #include -#include static int sockv6_open(void) @@ -97,20 +96,12 @@ T_DECL(socket_bind_35243417, T_META_ASROOT(false), T_META_CHECK_LEAKS(false)) { -#if TARGET_OS_WATCH - T_SKIP("socket_bind_35243417 can't run on watch."); -#else alloc_and_bind_ports(1, 65534, 10); -#endif } T_DECL(socket_bind_35243417_root, "bind IPv6 only UDP socket, then bind IPv6 socket.", T_META_ASROOT(true)) { -#if TARGET_OS_WATCH - T_SKIP("socket_bind_35243417_root can't run on watch."); -#else alloc_and_bind_ports(1, 65534, 10); -#endif } diff --git a/tools/tests/darwintests/socket_bind_35685803.c b/tools/tests/darwintests/socket_bind_35685803.c new file mode 100644 index 000000000..d0e22a941 --- /dev/null +++ b/tools/tests/darwintests/socket_bind_35685803.c @@ -0,0 +1,205 @@ +/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static bool debug; + +static int +sock_open_common(int pf, int type) +{ + int s; + + s = socket(pf, type, 0); + T_QUIET; + T_ASSERT_POSIX_SUCCESS(s, "socket(%d, %d, 0)", pf, type); + return (s); +} + +static int +sock_open(int type) +{ + return (sock_open_common(PF_INET, type)); +} + +static int +sock_bind(int s, int port) +{ + struct sockaddr_in sin = { + .sin_len = sizeof(sin), + .sin_family = AF_INET, + }; + + sin.sin_port = htons(port); + return (bind(s, (const struct sockaddr *)&sin, sizeof(sin))); +} + +static int +sockv6_open(int type) +{ + return (sock_open_common(PF_INET6, type)); +} + +static int +sockv6_bind(int s, int port) +{ + struct sockaddr_in6 sin6 = { + .sin6_len = sizeof(sin6), + .sin6_family = AF_INET6, + }; + + sin6.sin6_port = htons(port); + return (bind(s, (const struct sockaddr *)&sin6, sizeof(sin6))); +} + +static uint16_t +sock_get_port(int sockfd) +{ + int error; + uint16_t p; + union sockaddr_in_4_6 sin; + socklen_t sin_len; + + sin_len = sizeof(sin); + bzero(&sin, sin_len); + error = getsockname(sockfd, (struct sockaddr *)&sin, &sin_len); + T_QUIET; + T_EXPECT_POSIX_ZERO(error, "getsockname(%d)", sockfd); + if (error != 0) { + return (0); + } + switch (sin.sa.sa_family) { + case AF_INET: + p = sin.sin.sin_port; + break; + case AF_INET6: + p = sin.sin6.sin6_port; + break; + default: + T_ASSERT_FAIL("unknown address family %d\n", + sin.sa.sa_family); + p = 0; + break; + } + return (p); +} + +typedef struct { + bool v6; + int socket_count; + int * socket_list; +} SocketInfo, * SocketInfoRef; + +static void +bind_sockets(SocketInfoRef info, const char * msg) +{ + for (int i = 0; i < info->socket_count; i++) { + int error; + uint16_t port; + + if (info->v6) { + error = sockv6_bind(info->socket_list[i], 0); + } + else { + error = sock_bind(info->socket_list[i], 0); + } + port = sock_get_port(info->socket_list[i]); + if (debug) { + T_LOG( "%s: fd %d port is %d error %d", + msg, info->socket_list[i], ntohs(port), error); + } + } + return; +} + +static void * +second_thread(void * arg) +{ + SocketInfoRef info = (SocketInfoRef)arg; + + bind_sockets(info, "second"); + return (NULL); +} + +static void +multithreaded_bind_test(bool v6, int socket_count) +{ + int error; + SocketInfo info; + int socket_list[socket_count]; + pthread_t thread; + + info.v6 = v6; + for (int i = 0; i < socket_count; i++) { + if (v6) { + socket_list[i] = sockv6_open(SOCK_STREAM); + } else { + socket_list[i] = sock_open(SOCK_STREAM); + } + } + info.socket_count = socket_count; + info.socket_list = socket_list; + error = pthread_create(&thread, NULL, second_thread, &info); + T_QUIET; + T_ASSERT_POSIX_ZERO(error, "pthread_create"); + + /* compete with second thread */ + bind_sockets(&info, "main"); + error = pthread_join(thread, NULL); + T_QUIET; + T_ASSERT_POSIX_ZERO(error, "pthread_join"); + + for (int i = 0; i < socket_count; i++) { + error = close(socket_list[i]); + T_QUIET; + T_ASSERT_POSIX_ZERO(error, "close socket %d", socket_list[i]); + } +} + +static void +run_multithreaded_bind_test(int number_of_runs, bool v6, int socket_count) +{ + for (int i = 0; i < number_of_runs; i++) { + multithreaded_bind_test(v6, socket_count); + } + T_PASS("multithreaded_bind_test %s", v6 ? "IPv6" : "IPv4"); +} + +T_DECL(socket_bind_35685803, + "multithreaded bind IPv4 socket as root", + T_META_ASROOT(false), + T_META_CHECK_LEAKS(false)) +{ + run_multithreaded_bind_test(100, false, 100); +} + +T_DECL(socket_bind_35685803_root, + "multithreaded bind IPv4 socket", + T_META_ASROOT(true)) +{ + run_multithreaded_bind_test(100, false, 100); +} + +T_DECL(socket_bind_35685803_v6, + "multithreaded bind IPv6 socket as root", + T_META_ASROOT(false), + T_META_CHECK_LEAKS(false)) +{ + run_multithreaded_bind_test(100, true, 100); +} + +T_DECL(socket_bind_35685803_v6_root, + "multithreaded bind IPv6 socket", + T_META_ASROOT(true)) +{ + run_multithreaded_bind_test(100, true, 100); +} diff --git a/tools/tests/darwintests/stackshot.m b/tools/tests/darwintests/stackshot.m index 8c6219ab7..2c5b37d5c 100644 --- a/tools/tests/darwintests/stackshot.m +++ b/tools/tests/darwintests/stackshot.m @@ -219,16 +219,111 @@ }); } +static void +expect_instrs_cycles_in_stackshot(void *ssbuf, size_t sslen) +{ + kcdata_iter_t iter = kcdata_iter(ssbuf, sslen); + + bool in_task = false; + bool in_thread = false; + bool saw_instrs_cycles = false; + iter = kcdata_iter_next(iter); + + KCDATA_ITER_FOREACH(iter) { + switch (kcdata_iter_type(iter)) { + case KCDATA_TYPE_CONTAINER_BEGIN: + switch (kcdata_iter_container_type(iter)) { + case STACKSHOT_KCCONTAINER_TASK: + in_task = true; + saw_instrs_cycles = false; + break; + + case STACKSHOT_KCCONTAINER_THREAD: + in_thread = true; + saw_instrs_cycles = false; + break; + + default: + break; + } + break; + + case STACKSHOT_KCTYPE_INSTRS_CYCLES: + saw_instrs_cycles = true; + break; + + case KCDATA_TYPE_CONTAINER_END: + if (in_thread) { + T_QUIET; T_EXPECT_TRUE(saw_instrs_cycles, "saw instructions and cycles in thread"); + in_thread = false; + } else if (in_task) { + T_QUIET; T_EXPECT_TRUE(saw_instrs_cycles, "saw instructions and cycles in task"); + in_task = false; + } + + default: + break; + } + } +} + +static void +skip_if_monotonic_unsupported(void) +{ + int supported = 0; + size_t supported_size = sizeof(supported); + int ret = sysctlbyname("kern.monotonic.supported", &supported, &supported_size, 0, 0); + if (ret < 0 || !supported) { + T_SKIP("monotonic is unsupported"); + } +} + T_DECL(instrs_cycles, "test a getting instructions and cycles in stackshot") { + skip_if_monotonic_unsupported(); + struct scenario scenario = { .flags = (STACKSHOT_SAVE_LOADINFO | STACKSHOT_INSTRS_CYCLES | STACKSHOT_KCDATA_FORMAT) }; - T_LOG("attempting to take stackshot with kernel-only flag"); + T_LOG("attempting to take stackshot with instructions and cycles"); + take_stackshot(&scenario, ^(void *ssbuf, size_t sslen) { + parse_stackshot(false, ssbuf, sslen); + expect_instrs_cycles_in_stackshot(ssbuf, sslen); + }); +} + +T_DECL(delta_instrs_cycles, "test delta stackshots with instructions and cycles") +{ + skip_if_monotonic_unsupported(); + + struct scenario scenario = { + .flags = (STACKSHOT_SAVE_LOADINFO | STACKSHOT_INSTRS_CYCLES + | STACKSHOT_KCDATA_FORMAT) + }; + + initialize_thread(); + T_LOG("taking full stackshot"); take_stackshot(&scenario, ^(void *ssbuf, size_t sslen) { + uint64_t stackshot_time = stackshot_timestamp(ssbuf, sslen); + + T_LOG("taking delta stackshot since time %" PRIu64, stackshot_time); + parse_stackshot(false, ssbuf, sslen); + expect_instrs_cycles_in_stackshot(ssbuf, sslen); + + struct scenario delta_scenario = { + .flags = (STACKSHOT_SAVE_LOADINFO | STACKSHOT_INSTRS_CYCLES + | STACKSHOT_KCDATA_FORMAT + | STACKSHOT_COLLECT_DELTA_SNAPSHOT), + .since_timestamp = stackshot_time + }; + + take_stackshot(&delta_scenario, ^(void *dssbuf, size_t dsslen) { + parse_stackshot(true, dssbuf, dsslen); + expect_instrs_cycles_in_stackshot(dssbuf, dsslen); + }); }); } diff --git a/tools/tests/darwintests/stackshot_block_owner_14362384.m b/tools/tests/darwintests/stackshot_block_owner_14362384.m index a1395618c..bf4f3ae57 100644 --- a/tools/tests/darwintests/stackshot_block_owner_14362384.m +++ b/tools/tests/darwintests/stackshot_block_owner_14362384.m @@ -21,6 +21,12 @@ #include #include #include +#include + +#if !TARGET_OS_EMBEDDED +#include +#endif + T_GLOBAL_META( T_META_NAMESPACE("xnu.scheduler"), @@ -56,8 +62,8 @@ static void * take_stackshot(uint32_t extra_flags, uint64_t since_timestamp) { - void * stackshot; - int ret, retries; + void * stackshot = NULL; + int ret = 0; uint32_t stackshot_flags = STACKSHOT_SAVE_LOADINFO | STACKSHOT_GET_GLOBAL_MEM_STATS | STACKSHOT_SAVE_IMP_DONATION_PIDS | @@ -82,7 +88,7 @@ T_QUIET; T_ASSERT_POSIX_ZERO(ret, "Setting prev snapshot time on stackshot config"); } - for (retries = NUMRETRIES; retries > 0; retries--) { + for (int retries = NUMRETRIES; retries > 0; retries--) { ret = stackshot_capture_with_config(stackshot); T_QUIET; T_ASSERT_TRUE(ret == 0 || ret == EBUSY || ret == ETIMEDOUT, "Attempting to take stackshot (error %d)...", ret); @@ -94,16 +100,74 @@ return stackshot; } +static void +save_stackshot(void *stackshot, const char *filename) +{ + void *buf = stackshot_config_get_stackshot_buffer(stackshot); + T_QUIET; T_ASSERT_NOTNULL(buf, "buf"); + size_t size = stackshot_config_get_stackshot_size(stackshot); + FILE *f = fopen(filename, "w"); + T_QUIET; T_ASSERT_NOTNULL(f, "f"); + fwrite(buf, size, 1, f); + fclose(f); +} + +static +void check_python(void *stackshot, const char *fmt, ...) +{ + save_stackshot(stackshot, "/tmp/ss"); + +#if !TARGET_OS_EMBEDDED + va_list args; + va_start(args, fmt); + char *re_string = NULL; + vasprintf(&re_string, fmt, args); + va_end(args); + T_QUIET; T_ASSERT_NOTNULL(re_string, "vasprintf"); + + const char *pcreErrorStr; + int pcreErrorOffset; + pcre *re = pcre_compile(re_string, 0, &pcreErrorStr, &pcreErrorOffset, NULL); + T_QUIET; T_ASSERT_NOTNULL(re, "pcre_compile"); + + bool found = false; + FILE *p = popen("/usr/local/bin/kcdata --pretty /tmp/ss", "r"); + T_QUIET; T_ASSERT_NOTNULL(p, "popen"); + while (1) { + char *line = NULL; + size_t linecap = 0; + ssize_t linesize = getline(&line, &linecap, p); + if (linesize < 0) { + if (line) + free(line); + break; + } + int pcre_ret = pcre_exec(re, NULL, line, strlen(line), 0, 0, NULL, 0); + if (pcre_ret == 0){ + T_LOG("line: %s", line); + found = true; + } + free(line); + } + T_EXPECT_TRUE(found, "found the waitinfo in kcdata.py output"); + pclose(p); + pcre_free(re); + free(re_string); +#endif +} + + // waitinfo can be NULL, but len must be non-null and point to the length of the waitinfo array. // when the function returns, len will be set to the number of waitinfo structs found in the stackshot. static void find_blocking_info(void * stackshot, struct stackshot_thread_waitinfo *waitinfo, int *len) { - void *buf; - uint32_t t, buflen; + void *buf = NULL; + uint32_t t = 0; + uint32_t buflen = 0; NSError *error = nil; - NSMutableDictionary *parsed_container; - NSArray *parsed_waitinfo; + NSMutableDictionary *parsed_container = nil; + NSArray *parsed_waitinfo = nil; T_QUIET; T_ASSERT_NOTNULL(len, "Length pointer shouldn't be NULL"); int oldlen = *len; @@ -164,7 +228,7 @@ * returns 1. */ static int kmutex_action(int action) { - int ret; + int ret = 0; if (action == KMUTEX_SYSCTL_CHECK_EXISTS) { ret = sysctlbyname(krwlck_ctl, NULL, NULL, NULL, 0); return !(ret == -1); @@ -197,8 +261,8 @@ static int kmutex_action(int action) static void sysctl_kmutex_test_match(uint64_t context) { - int ret; - unsigned long long unslid_kmutex_address; + int ret = 0; + unsigned long long unslid_kmutex_address = 0; size_t addrsize = sizeof(unslid_kmutex_address); ret = sysctlbyname(kmutex_ctl, &unslid_kmutex_address, &addrsize, NULL, 0); @@ -242,7 +306,7 @@ static int kmutex_action(int action) static void msg_recv_helper(mach_port_t local_port) { - int ret; + int ret = 0; mach_msg_size_t size = 2*PAGE_SIZE; mach_msg_header_t * msg = NULL; ret = vm_allocate(mach_task_self(), @@ -272,7 +336,7 @@ static int kmutex_action(int action) static int krwlck_action(int action) { - int ret; + int ret = 0; if (action == KRWLCK_SYSCTL_CHECK_EXISTS) { ret = sysctlbyname(krwlck_ctl, NULL, NULL, NULL, 0); return !(ret == -1); @@ -311,8 +375,8 @@ static int kmutex_action(int action) static void sysctl_krwlck_test_match(uint64_t context) { - int ret; - unsigned long long unslid_krwlck_address; + int ret = 0; + unsigned long long unslid_krwlck_address = 0; size_t addrsize = sizeof(unslid_krwlck_address); ret = sysctlbyname(krwlck_ctl, &unslid_krwlck_address, &addrsize, NULL, 0); @@ -425,10 +489,10 @@ static int kmutex_action(int action) static void test_kmutex_blocking(void) { - int ret; + int ret = 0; int len = 2; - struct stackshot_thread_waitinfo waitinfo[len]; - uint64_t thread_id; + struct stackshot_thread_waitinfo waitinfo[2] = { { 0 }, { 0 } }; + uint64_t thread_id = 0; pthread_t grabbing, waiting; T_LOG("Starting %s", __FUNCTION__); @@ -440,6 +504,12 @@ static int kmutex_action(int action) sleep(3); // give (lots of) time for thread to give up spinning on lock void * stackshot = take_stackshot(STACKSHOT_THREAD_WAITINFO, 0); + + ret = pthread_threadid_np(waiting, &thread_id); // this is the thread that currently holds the kernel mutex + T_QUIET; T_ASSERT_POSIX_ZERO(ret, "Getting integer value of thread id"); + + check_python(stackshot, "thread \\d+: semaphore port \\w+ with unknown owner"); + find_blocking_info(stackshot, (struct stackshot_thread_waitinfo *)&waitinfo, &len); T_EXPECT_EQ(len, 2, "There should only be two blocking threads"); @@ -448,10 +518,10 @@ static int kmutex_action(int action) if (curr->wait_type == kThreadWaitSemaphore) continue; T_EXPECT_EQ(curr->wait_type, kThreadWaitKernelMutex, "Wait type should match expected KernelMutex value"); - ret = pthread_threadid_np(waiting, &thread_id); // this is the thread that currently holds the kernel mutex - T_QUIET; T_ASSERT_POSIX_ZERO(ret, "Getting integer value of thread id"); T_EXPECT_EQ(curr->owner, thread_id, "Thread ID of blocking thread should match 'owner' field in stackshot"); sysctl_kmutex_test_match(curr->context); + + check_python(stackshot, "thread \\d+: kernel mutex %llx owned by thread %lld", curr->context, thread_id); } kmutex_action(KMUTEX_SYSCTL_SIGNAL); // waiting thread should now unblock. @@ -467,11 +537,11 @@ static int kmutex_action(int action) static void test_semaphore_blocking(void) { - int ret; + int ret = 0; semaphore_t sem; - struct stackshot_thread_waitinfo waitinfo; + struct stackshot_thread_waitinfo waitinfo = { 0 }; int len = 1; - uint64_t pid; + uint64_t pid = 0; T_LOG("Starting %s", __FUNCTION__); ret = semaphore_create(mach_task_self(), &sem, SYNC_POLICY_FIFO, 0); @@ -490,6 +560,8 @@ static int kmutex_action(int action) pid = (uint64_t)getpid(); T_EXPECT_EQ(waitinfo.owner, pid, "Owner value should match process ID"); + check_python(stackshot, "thread \\d+: semaphore port \\w+ owned by pid %d", (int)pid); + ret = semaphore_signal(sem); T_QUIET; T_ASSERT_MACH_SUCCESS(ret, "Signalling semaphore"); ret = pthread_join(tid, NULL); @@ -503,10 +575,10 @@ static int kmutex_action(int action) static void test_mach_msg_blocking(void) { - int ret; + int ret = 0; pthread_t tid; - void *stackshot; - struct stackshot_thread_waitinfo waitinfo; + void *stackshot = NULL; + struct stackshot_thread_waitinfo waitinfo = { 0 }; int len = 1; T_LOG("Starting %s", __FUNCTION__); @@ -528,6 +600,9 @@ static int kmutex_action(int action) T_EXPECT_EQ(len, 1, "Only one blocking thread should exist"); T_EXPECT_EQ(waitinfo.wait_type, kThreadWaitPortReceive, "Wait type should match expected PortReceive value"); + + check_python(stackshot, "thread \\d+: mach_msg receive on port \\w+ name %llx", (long long)send); + stackshot_config_dealloc(stackshot); msg_send_helper(send); // ping! msg_blocking_thread will now try to send us stuff, and block until we receive. @@ -537,6 +612,9 @@ static int kmutex_action(int action) find_blocking_info(stackshot, (struct stackshot_thread_waitinfo *)&waitinfo, &len); T_EXPECT_EQ(len, 1, "Only one blocking thread should exist"); T_EXPECT_EQ(waitinfo.wait_type, kThreadWaitPortSend, "Wait type should match expected PortSend value"); + + check_python(stackshot, "thread \\d+: mach_msg send on port \\w+ owned by pid %d", (int)getpid()); + stackshot_config_dealloc(stackshot); msg_recv_helper(recv); // thread should block until we receive one of its messages @@ -547,13 +625,13 @@ static int kmutex_action(int action) static void test_ulock_blocking(void) { - int ret; - void *stackshot; - uint64_t thread_id; + int ret = 0; + void *stackshot = NULL; + uint64_t thread_id = 0; pthread_t tid; struct os_unfair_lock_s ouls = OS_UNFAIR_LOCK_INIT; os_unfair_lock_t oul = &ouls; - struct stackshot_thread_waitinfo waitinfo; + struct stackshot_thread_waitinfo waitinfo = { 0 }; int len = 1; T_LOG("Starting %s", __FUNCTION__); @@ -563,10 +641,10 @@ static int kmutex_action(int action) sleep(3); // give time for thread to spawn, fall back to kernel for contention, and block stackshot = take_stackshot(STACKSHOT_THREAD_WAITINFO, 0); + find_blocking_info(stackshot, (struct stackshot_thread_waitinfo *)&waitinfo, &len); T_EXPECT_EQ(len, 1, "Only one blocking thread should exist"); T_EXPECT_EQ(waitinfo.wait_type, kThreadWaitUserLock, "Wait type should match expected UserLock value"); - stackshot_config_dealloc(stackshot); os_unfair_lock_unlock(oul); ret = pthread_join(tid, NULL); // wait for thread to unblock and exit @@ -575,18 +653,21 @@ static int kmutex_action(int action) ret = pthread_threadid_np(NULL, &thread_id); // this thread is the "owner" of the ulock T_QUIET; T_ASSERT_POSIX_ZERO(ret, "Getting integer value of thread id"); T_EXPECT_EQ(waitinfo.owner, thread_id, "Thread ID of blocking thread should match 'owner' field in stackshot"); + + check_python(stackshot, "thread \\d+: unfair lock \\w+ owned by thread %lld", thread_id); + stackshot_config_dealloc(stackshot); return; } static void test_krwlock_blocking(void) { - int ret; - void *stackshot; - uint64_t thread_id; + int ret = 0; + void *stackshot = NULL; + uint64_t thread_id = 0; pthread_t waiting, grabbing; int len = 2; - struct stackshot_thread_waitinfo waitinfo[len]; + struct stackshot_thread_waitinfo waitinfo[2] = { { 0 }, { 0 } }; T_LOG("Starting %s", __FUNCTION__); // this thread should spawn, acquire a kernel rwlock for write, and then wait on a semaphore @@ -599,6 +680,9 @@ static int kmutex_action(int action) sleep(1); // give time for thread to block stackshot = take_stackshot(STACKSHOT_THREAD_WAITINFO, 0); + + check_python(stackshot, "thread \\d+: semaphore port \\w+ with unknown owner"); + find_blocking_info(stackshot, (struct stackshot_thread_waitinfo *)&waitinfo, &len); T_EXPECT_EQ(len, 2, "There should only be two blocking threads"); @@ -609,10 +693,14 @@ static int kmutex_action(int action) T_EXPECT_EQ(curr->wait_type, kThreadWaitKernelRWLockRead, "Wait type should match expected KRWLockRead value"); sysctl_krwlck_test_match(curr->context); + check_python(stackshot, "thread \\d+: krwlock %llx for reading", curr->context); + #if KRWLCK_STORES_EXCL_OWNER /* A future planned enhancement */ ret = pthread_threadid_np(waiting, &thread_id); // this is the thread that currently holds the kernel mutex T_QUIET; T_ASSERT_POSIX_ZERO(ret, "Getting integer value of thread id"); T_EXPECT_EQ(curr->owner, thread_id, "Thread ID of blocking thread should match 'owner' field in stackshot"); +#else + (void)thread_id; // suppress compiler warning about unused variable #endif /* RWLCK_STORES_EXCL_OWNER */ } @@ -625,25 +713,32 @@ static int kmutex_action(int action) stackshot_config_dealloc(stackshot); } + static void test_pthread_mutex_blocking(void) { - int ret; - void *stackshot; - uint64_t thread_id; + int ret = 0; + void *stackshot = NULL; + uint64_t thread_id = 0; pthread_t tid; - struct stackshot_thread_waitinfo waitinfo; + struct stackshot_thread_waitinfo waitinfo = { 0 }; pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; int len = 1; T_LOG("Starting %s", __FUNCTION__); + ret = pthread_threadid_np(NULL, &thread_id); // this thread is the "owner" of the mutex + T_QUIET; T_ASSERT_POSIX_ZERO(ret, "Getting integer value of thread id"); + pthread_mutex_lock(&mtx); ret = pthread_create(&tid, NULL, pthread_mutex_blocking_thread, (void*)&mtx); T_QUIET; T_ASSERT_POSIX_ZERO(ret, "Creating pthread mutex blocking thread"); sleep(2); // give time for thread to block stackshot = take_stackshot(STACKSHOT_THREAD_WAITINFO, 0); + + check_python(stackshot, "thread \\d+: pthread mutex %llx owned by thread %lld", &mtx, thread_id); + find_blocking_info(stackshot, (struct stackshot_thread_waitinfo *)&waitinfo, &len); T_EXPECT_EQ(len, 1, "Only one blocking thread should exist"); T_EXPECT_EQ(waitinfo.wait_type, kThreadWaitPThreadMutex, @@ -653,8 +748,7 @@ static int kmutex_action(int action) pthread_mutex_unlock(&mtx); ret = pthread_join(tid, NULL); // wait for thread to unblock and exit - ret = pthread_threadid_np(NULL, &thread_id); // this thread is the "owner" of the mutex - T_QUIET; T_ASSERT_POSIX_ZERO(ret, "Getting integer value of thread id"); + T_EXPECT_EQ(waitinfo.owner, thread_id, "Thread ID of blocking thread should match 'owner' field in stackshot"); T_EXPECT_EQ(waitinfo.context, (uint64_t)&mtx, @@ -664,10 +758,10 @@ static int kmutex_action(int action) static void test_pthread_rwlck_blocking(void) { - int ret; - void *stackshot; + int ret = 0; + void *stackshot = NULL; pthread_t tid; - struct stackshot_thread_waitinfo waitinfo; + struct stackshot_thread_waitinfo waitinfo = { 0 }; pthread_rwlock_t rwlck = PTHREAD_RWLOCK_INITIALIZER; int len = 1; @@ -678,6 +772,9 @@ static int kmutex_action(int action) sleep(2); stackshot = take_stackshot(STACKSHOT_THREAD_WAITINFO, 0); + + check_python(stackshot, "thread \\d+: pthread rwlock %llx for reading", (long long)&rwlck); + find_blocking_info(stackshot, (struct stackshot_thread_waitinfo *)&waitinfo, &len); T_EXPECT_EQ(len, 1, "Only one blocking thread should exist"); T_EXPECT_EQ(waitinfo.wait_type, kThreadWaitPThreadRWLockRead, @@ -690,14 +787,16 @@ static int kmutex_action(int action) "Userspace address of rwlck should match 'context' field in stackshot"); } + + static void test_pthread_cond_blocking(void) { - int ret; - void *stackshot; + int ret = 0; + void *stackshot = NULL; pthread_t tid; pthread_cond_t cond = PTHREAD_COND_INITIALIZER; - struct stackshot_thread_waitinfo waitinfo; + struct stackshot_thread_waitinfo waitinfo = { 0 }; int len = 1; T_LOG("Starting %s", __FUNCTION__); @@ -706,6 +805,9 @@ static int kmutex_action(int action) sleep(2); stackshot = take_stackshot(STACKSHOT_THREAD_WAITINFO, 0); + + check_python(stackshot, "thread \\d+: pthread condvar %llx", (long long)&cond); + find_blocking_info(stackshot, (struct stackshot_thread_waitinfo *)&waitinfo, &len); T_EXPECT_EQ(len, 1, "Only one blocking thread should exist"); T_EXPECT_EQ(waitinfo.wait_type, kThreadWaitPThreadCondVar, diff --git a/tools/tests/darwintests/task_info.c b/tools/tests/darwintests/task_info.c index 906243a56..cb77c304f 100644 --- a/tools/tests/darwintests/task_info.c +++ b/tools/tests/darwintests/task_info.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -712,6 +713,220 @@ test_task_basic_info(enum info_kind kind) #undef AFTER } +T_DECL(test_sigcont_task_suspend_resume, + "test to verify that SIGCONT on task_suspend()-ed process works", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + T_SETUPBEGIN; + int is_dev = is_development_kernel(); + T_QUIET; + T_ASSERT_TRUE(is_dev, "verify development kernel is running"); + T_SETUPEND; + + mach_task_basic_info_data_t mach_basic_info_data; + task_info_t info_data = (task_info_t)&mach_basic_info_data; + + task_debug_info_internal_data_t debug_info; + mach_msg_type_number_t debug_count = TASK_DEBUG_INFO_INTERNAL_COUNT; + + kern_return_t kr; + int posix_ret; + mach_msg_type_number_t count = MACH_TASK_BASIC_INFO_COUNT; + task_flavor_t flavor = MACH_TASK_BASIC_INFO; + integer_t suspend_count; + integer_t debug_suspend_count; + pid_t child_pid = 0; + mach_port_name_t child_task; + /*for dt_waitpid*/ + int timeout = 5; + int exit_status = 0; + int signal_no = 0; + + child_pid = fork(); + + T_ASSERT_POSIX_SUCCESS(child_pid, "verify process can be forked"); + + if (child_pid == 0) { + /* + * This will suspend the child process. + */ + kr = task_suspend(mach_task_self()); + + /* + * When child resumes, it exits immediately + */ + + exit(kr); + } + + /* + * Wait for the child process to suspend itself. + */ + sleep(1); + + kr = task_for_pid(mach_task_self(), child_pid, &child_task); + T_ASSERT_MACH_SUCCESS(kr, "verify task_for_pid succeeded. check sudo if failed"); + + /* + * Verify the suspend_count for child and resume it. + */ + + kr = task_info(child_task, flavor, info_data, &count); + T_ASSERT_MACH_SUCCESS(kr, "verify task_info call succeeded"); + + suspend_count = (integer_t)(info_get(INFO_MACH, GET_SUSPEND_COUNT, info_data)); + T_ASSERT_EQ(suspend_count, 1, "verify task_info shows correct suspend_count (1) (actually user stop count) "); + + kr = task_info(child_task, TASK_DEBUG_INFO_INTERNAL, (task_info_t)&debug_info, &debug_count); + T_ASSERT_MACH_SUCCESS(kr, "verify task_info call succeeded"); + + debug_suspend_count = debug_info.suspend_count; + T_ASSERT_EQ(debug_info.suspend_count, 1, "verify debug_info shows correct suspend_count(1)"); + + posix_ret = kill(child_pid, SIGCONT); + T_ASSERT_POSIX_SUCCESS(posix_ret, "verify signal call succeeded"); + + /* + * reap kr from task_suspend call in child + */ + dt_waitpid(child_pid, &exit_status, &signal_no, timeout); + + T_ASSERT_EQ(signal_no, 0, "child should be resumed and exit without signal"); + T_ASSERT_EQ(exit_status, 0, "child should exit with 0"); + +} + +T_DECL(test_sigcont_task_suspend2_resume, + "test to verify that SIGCONT on task_suspend2()-ed process doesn't work", + T_META_ASROOT(true), + T_META_LTEPHASE(LTE_POSTINIT)) +{ + T_SETUPBEGIN; + int is_dev = is_development_kernel(); + T_QUIET; + T_ASSERT_TRUE(is_dev, "verify development kernel is running"); + T_SETUPEND; + + mach_task_basic_info_data_t mach_basic_info_data; + task_info_t info_data = (task_info_t)&mach_basic_info_data; + + task_debug_info_internal_data_t debug_info; + mach_msg_type_number_t debug_count = TASK_DEBUG_INFO_INTERNAL_COUNT; + + kern_return_t kr; + int posix_ret; + mach_msg_type_number_t count = MACH_TASK_BASIC_INFO_COUNT; + task_flavor_t flavor = MACH_TASK_BASIC_INFO; + integer_t suspend_count = 0; + integer_t debug_suspend_count = 0; + pid_t child_pid = 0; + mach_port_name_t child_task; + task_suspension_token_t child_token = 0xFFFFF; + + /* + * for dt_waitpid + * We expect the test to fail right now, so I've set timeout to + * be shorter than we may want it to be when the issue is fixed + */ + int timeout = 1; + int exit_status = 0; + int signal_no = 0; + + /* for pipe */ + int fd[2]; + pipe(fd); + int pipe_msg = 0; + + child_pid = fork(); + + T_ASSERT_POSIX_SUCCESS(child_pid, "verify process can be forked %d", child_pid); + + if (child_pid == 0) { + close(fd[1]); + T_LOG("Waiting to read from parent..."); + read(fd[0], &pipe_msg, sizeof(pipe_msg)); + T_LOG("Done reading from parent, about to exit..."); + exit(0); + } + /* + * Wait for child to fork and block on read + */ + sleep(1); + + close(fd[0]); + + kr = task_for_pid(mach_task_self(), child_pid, &child_task); + T_ASSERT_MACH_SUCCESS(kr, "verify task_for_pid succeeded. check sudo if failed"); + + kr = task_info(child_task, TASK_DEBUG_INFO_INTERNAL, (task_info_t)&debug_info, &debug_count); + T_ASSERT_MACH_SUCCESS(kr, "verify task_info call succeeded"); + + debug_suspend_count = debug_info.suspend_count; + T_EXPECT_EQ(debug_suspend_count, 0, "verify debug_info shows correct (true) suspend_count(0)"); + + kr = task_suspend2(child_task, &child_token); + T_ASSERT_MACH_SUCCESS(kr, "verify task_suspend2 call succeeded"); + + kr = task_info(child_task, TASK_DEBUG_INFO_INTERNAL, (task_info_t)&debug_info, &debug_count); + T_ASSERT_MACH_SUCCESS(kr, "verify task_info call succeeded"); + + debug_suspend_count = debug_info.suspend_count; + T_ASSERT_EQ(debug_suspend_count, 1, "verify debug_info shows correct (true) suspend_count(1)"); + + /* + * Verify the suspend_count for child and resume it. + */ + + kr = task_info(child_task, flavor, info_data, &count); + T_ASSERT_MACH_SUCCESS(kr, "verify task_info call succeeded"); + + suspend_count = (integer_t)(info_get(INFO_MACH, GET_SUSPEND_COUNT, info_data)); + T_EXPECT_EQ(suspend_count, 1, "verify task_info shows correct (user_stop_count) suspend_count (1)"); + + posix_ret = kill(child_pid, SIGCONT); + T_ASSERT_POSIX_SUCCESS(posix_ret, "verify signal call succeeded"); + + kr = task_info(child_task, TASK_DEBUG_INFO_INTERNAL, (task_info_t)&debug_info, &debug_count); + T_EXPECT_MACH_SUCCESS(kr, "verify task_info call succeeded"); + + debug_suspend_count = debug_info.suspend_count; + T_EXPECTFAIL_WITH_RADAR(33166654); + T_EXPECT_EQ(debug_suspend_count, 1, "verify debug_info shows correct (true) suspend_count (1)"); + + suspend_count = (integer_t)(info_get(INFO_MACH, GET_SUSPEND_COUNT, info_data)); + T_ASSERT_EQ(suspend_count, 1, "verify task_info shows correct (user_stop_count) suspend_count (1) after SIG_CONT"); + + kr = task_resume(child_task); + T_EXPECTFAIL_WITH_RADAR(33166654); + T_EXPECT_MACH_SUCCESS(kr, "verify task_resume succeeded"); + + /* + * reap kr from task_suspend call in child + */ + + dt_waitpid(child_pid, &exit_status, &signal_no, timeout); + + T_ASSERT_EQ(signal_no, SIG_DT_TIMEOUT, "dt_waitpid timed out as expected"); + + // Resume properly using token and then wait + + kr = task_resume2(child_token); + T_EXPECTFAIL_WITH_RADAR(33166654); + T_ASSERT_MACH_SUCCESS(kr, "verify task_resume2 succeeded"); + + write(fd[1], &pipe_msg, sizeof(pipe_msg)); + + /* + * reap kr from task_suspend call in child + */ + dt_waitpid(child_pid, &exit_status, &signal_no, timeout); + + T_ASSERT_EQ(signal_no, 0, "child should be resumed and no signal should be returned"); + T_ASSERT_EQ(exit_status, 0, "child should exit with 0"); + +} + uint64_t info_get(enum info_kind kind, enum info_get get, void * data) { diff --git a/tools/tests/darwintests/thread_group_set_32261625.c b/tools/tests/darwintests/thread_group_set_32261625.c index cebd042d0..1c7eb3f6c 100644 --- a/tools/tests/darwintests/thread_group_set_32261625.c +++ b/tools/tests/darwintests/thread_group_set_32261625.c @@ -21,26 +21,25 @@ T_DECL(thread_group_set, "Checks that new threads get a THREAD_GROUP_SET tracepo __block int seen_new_thread = 0, __block seen_thread_group_set = 0; ktrace_machine_t machine = ktrace_machine_create_current(); - T_ASSERT_NOTNULL(machine, "ktrace_get_machine"); + T_WITH_ERRNO; T_ASSERT_NOTNULL(machine, "ktrace_get_machine"); bool has_tg = false; if (ktrace_machine_has_thread_groups(machine, &has_tg) || !has_tg) { T_SKIP("thread groups not supported on this system"); } + ktrace_machine_destroy(machine); ktrace_session_t session = ktrace_session_create(); - T_ASSERT_NOTNULL(session, "ktrace_session_create"); + T_WITH_ERRNO; T_ASSERT_NOTNULL(session, "ktrace_session_create"); ktrace_set_interactive(session); ktrace_set_completion_handler(session, ^{ + ktrace_session_destroy(session); T_ASSERT_TRUE(seen_new_thread, "seen new thread tracepoint"); T_END; }); - T_EXPECT_POSIX_SUCCESS(pthread_create(&thread, NULL, newthread, NULL), "pthread_create"); - T_EXPECT_POSIX_SUCCESS(pthread_detach(thread), "pthread_detach"); - ktrace_events_single(session, TEST_EVENTID, ^(__unused ktrace_event_t e) { T_EXPECT_TRUE(seen_thread_group_set, "seen THREAD_GROUP_SET tracepoint"); seen_new_thread = 1; @@ -48,7 +47,7 @@ T_DECL(thread_group_set, "Checks that new threads get a THREAD_GROUP_SET tracepo }); ktrace_events_single(session, MACHDBG_CODE(DBG_MACH_THREAD_GROUP, MACH_THREAD_GROUP_SET), ^(ktrace_event_t e) { - T_EXPECT_GT(e->arg3, 0, "tid on THREAD_GROUP_SET"); + T_EXPECT_GT(e->arg3, (uintptr_t)0, "tid on THREAD_GROUP_SET"); seen_thread_group_set = 1; }); @@ -58,5 +57,8 @@ T_DECL(thread_group_set, "Checks that new threads get a THREAD_GROUP_SET tracepo T_ASSERT_POSIX_SUCCESS(ktrace_start(session, dispatch_get_main_queue()), "ktrace_start"); + T_EXPECT_POSIX_SUCCESS(pthread_create(&thread, NULL, newthread, NULL), "pthread_create"); + T_EXPECT_POSIX_SUCCESS(pthread_detach(thread), "pthread_detach"); + dispatch_main(); } diff --git a/tools/tests/darwintests/utimensat.c b/tools/tests/darwintests/utimensat.c index bcda28f9e..d5baad67f 100644 --- a/tools/tests/darwintests/utimensat.c +++ b/tools/tests/darwintests/utimensat.c @@ -34,6 +34,12 @@ T_DECL(utimensat, "Try various versions of utimensat") { T_SETUPBEGIN; T_ASSERT_POSIX_ZERO(chdir(dt_tmpdir()), NULL); + // Skip the test if the current working directory is not on APFS. + struct statfs sfs = { 0 }; + T_QUIET; T_ASSERT_POSIX_SUCCESS(statfs(".", &sfs), NULL); + if (memcmp(&sfs.f_fstypename[0], "apfs", strlen("apfs")) != 0) { + T_SKIP("utimensat is APFS-only, but working directory is non-APFS"); + } T_SETUPEND; struct stat pre_st, post_st; diff --git a/tools/tests/darwintests/verify_kalloc_config.c b/tools/tests/darwintests/verify_kalloc_config.c new file mode 100644 index 000000000..14ce3c974 --- /dev/null +++ b/tools/tests/darwintests/verify_kalloc_config.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include + +T_GLOBAL_META( + T_META_NAMESPACE("xnu.vm"), + T_META_CHECK_LEAKS(false) +); + +static void run_test(void); + +static void run_test(void) +{ + kern_return_t kr; + uint64_t size, i; + mach_zone_name_t *name = NULL; + unsigned int nameCnt = 0; + mach_zone_info_t *info = NULL; + unsigned int infoCnt = 0; + mach_memory_info_t *wiredInfo = NULL; + unsigned int wiredInfoCnt = 0; + const char kalloc_str[] = "kalloc."; + + kr = mach_memory_info(mach_host_self(), + &name, &nameCnt, &info, &infoCnt, + &wiredInfo, &wiredInfoCnt); + T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "mach_memory_info"); + T_QUIET; T_ASSERT_EQ(nameCnt, infoCnt, "zone name and info counts don't match"); + + /* Match the names of the kalloc zones against their element sizes. */ + for (i = 0; i < nameCnt; i++) { + if (strncmp(name[i].mzn_name, kalloc_str, strlen(kalloc_str)) == 0) { + size = strtoul(&(name[i].mzn_name[strlen(kalloc_str)]), NULL, 10); + T_LOG("ZONE NAME: %-25s ELEMENT SIZE: %llu", name[i].mzn_name, size); + T_QUIET; T_ASSERT_EQ(size, info[i].mzi_elem_size, "kalloc zone name and element size don't match"); + } + } + + if ((name != NULL) && (nameCnt != 0)) { + kr = vm_deallocate(mach_task_self(), (vm_address_t) name, + (vm_size_t) (nameCnt * sizeof *name)); + T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_deallocate name"); + } + + if ((info != NULL) && (infoCnt != 0)) { + kr = vm_deallocate(mach_task_self(), (vm_address_t) info, + (vm_size_t) (infoCnt * sizeof *info)); + T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_deallocate info"); + } + + if ((wiredInfo != NULL) && (wiredInfoCnt != 0)) { + kr = vm_deallocate(mach_task_self(), (vm_address_t) wiredInfo, + (vm_size_t) (wiredInfoCnt * sizeof *wiredInfo)); + T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_deallocate wiredInfo"); + } + + T_END; +} + +T_DECL( verify_kalloc_config, + "verifies that the kalloc zones are configured correctly", + T_META_ASROOT(true)) +{ + run_test(); +} + diff --git a/tools/tests/darwintests/xnu_quick_test_getsetpriority.c b/tools/tests/darwintests/xnu_quick_test_getsetpriority.c new file mode 100644 index 000000000..ec62af549 --- /dev/null +++ b/tools/tests/darwintests/xnu_quick_test_getsetpriority.c @@ -0,0 +1,40 @@ +#include + +#include +#include +#include +#include + +T_GLOBAL_META(T_META_NAMESPACE("xnu.quicktest"), T_META_CHECK_LEAKS(false)); + +T_DECL(getpriority_setpriority, "Tests getpriority and setpriority system calls", T_META_ASROOT(true)) +{ + int my_priority; + int my_new_priority; + + /* getpriority returns scheduling priority so -1 is a valid value */ + errno = 0; + my_priority = getpriority(PRIO_PROCESS, 0); + + T_WITH_ERRNO; + T_ASSERT_FALSE(my_priority == -1 && errno != 0, "Verify getpriority is successful", NULL); + + /* change scheduling priority*/ + my_new_priority = (my_priority == PRIO_MIN) ? (my_priority + 10) : (PRIO_MIN); + + T_WITH_ERRNO; + T_ASSERT_POSIX_SUCCESS(setpriority(PRIO_PROCESS, 0, my_new_priority), "Change scheduling priority", NULL); + + /* verify change */ + errno = 0; + my_priority = getpriority(PRIO_PROCESS, 0); + T_WITH_ERRNO; + T_ASSERT_FALSE(my_priority == -1 && errno != 0, "Verify getpriority change is successful", NULL); + + T_WITH_ERRNO; + T_ASSERT_EQ(my_priority, my_new_priority, "Verify setpriority correctly set scheduling priority", NULL); + + /* reset scheduling priority */ + T_WITH_ERRNO; + T_ASSERT_POSIX_SUCCESS(setpriority(PRIO_PROCESS, 0, 0), "Reset scheduling priority", NULL); +} diff --git a/tools/tests/libMicro/AppleReadMe b/tools/tests/libMicro/AppleReadMe deleted file mode 100755 index 8b3834586..000000000 --- a/tools/tests/libMicro/AppleReadMe +++ /dev/null @@ -1,231 +0,0 @@ -Mac OS X specific notes - -*** Instructions before Starting libMicro *** - -# Disable Open directory and LDAP using Directory Utility app -# Turn off airport -# Turn off spotlight. In terminal, execute the following: - launchctl unload /System/Library/LaunchDaemons/com.apple.metadata.mds.plist -# Turn off Time Machine in System Preferences -# Wait at least 2 minutes after boot to desktop for boot cache to settle down - -*** Make and run quickstart *** - - make - ./bench >output.txt -runs the libMicro test suite excluding the lmbench tests and gives you a text file named output.txt with the results of one run. - - - ./multiview output1.txt output2.txt >compare.html -gives you a html file comparing two runs. - -*** To run libMicro testsuite with stepper disabled *** -*** For Desktop use coreos_bench script*** - -To get a more consistent result of libMicro benchmark run, we need to disable the -stepper to prevent it from causing wide variations in results. See rdar://6243819 -for details. - -So to run libMicro test suite with stepper disabled, use 'coreos_bench' script -instead of 'bench' script. - -For example: -./coreos_bench > output.txt -runs the libMicro test suite excluding the lmbench tests and gives you a text file named output.txt with the results of one run, with stepper disabled. - -Note: -1) We need '/usr/local/bin/pstates' to disable the stepper. Install AppleInternal package -which provides '/usr/local/bin/pstates'. - -2) 'coreos_bench' script is used exactly like the 'bench' script. All the usage examples for -'bench' script in this readme file also holds true for 'coreos_bench' script. - - - - - -*** Makefile *** - -The Makefile invokes Makefile.Darwin which invokes Makefile.com.Darwin. -Just invoke make, with options if necessary, and everything should -build correctly. The binaries are placed in a directory called -bin-ARCH where ARCH is the default or specified when building via -the ARCH flag. - -Note: -1) The binaries of apple added tests are placed in a directory called - apple/bin-ARCH - -2) All the binaries under bin-ARCH and apple/bin-ARCH are code signed - during build. - -options for invoking Makefile are: -ARCH defaults to i386 - - to build fat/multi architecture, specify - make ARCH=fat - the makefile will automatically build with ARCH_FLAG="-arch i386 -arch x86_64" and put the results in bin-fat - - to build for ARM architecture, - first set an environment variable 'SDKROOT' to point to iPhone internal sdk - For example: - $export SDKROOT="/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.Internal.sdk/" - to build use: - make ARCH=ARM_ARCH where ARM_ARCH can be for e.g. armv6, armv7 - this will put the results in bin-ARM_ARCH - - to build with only two of the architectures see below - -ARCH_FLAG defaults to -arch $(ARCH) - to build fat/multi architecture, specify - make ARCH_FLAG="-arch i386" ARCH=fat - this will put the results in bin-fat - -OPT_FLAG defaults to -g - to build optimized, specify make OPT_FLAG=-Os - -SEMOP_FLAG defaults to -DUSE_SEMOP - to eliminate SEMOP usage, specify make SEMOP_FLAG= - this is needed on some lower-end systems (e.g. M63) - -These can be combined, e.g. - make ARCH=i386 SEMOP_FLAG= - -*** Before running benchmarks *** - -The shell script create_stuff should be run before any benchmarking - -this script takes care of raising the process limits which would -otherwise cause several of the tests to fail - if not you will see: - Running: pipe_pst1 - fork: Resource temporarily unavailable -in your stderr during the runs. After you run create_stuff, the -system then needs to be rebooted. - -*** running the benchmarks *** - -The shell script "bench" will run all the benchmarks, or you can -pass it a parameter to run a single benchmark, e.g. - -*** To run libMicro on the embedded platform, use "embd_bench" script. 'embd_bench' script is used exactly like the 'bench' script. All the usage examples for -'bench' script in this readme file also holds true for 'embd_bench' script. *** - - bench lmbench_bw_unix - -By default the script will run only the libMicro testsuite excluding the lmbench tests. -To run the libmicro testsuite with the lmbench tests included, just pass the -l parameter. e.g, - - bench -l -To run only the lmbench testsuite - - bench lmbench - -To display the usage, just do - bench -h - -Watch for: - # WARNINGS - # Quantization error likely;increase batch size (-B option) 4X to avoid. -in the output -To see an example run the supplied testbench script - -Add or adjust the -B parameter for any benchmark that fails. The -Quantization error will refer to the benchmark preceding the error, -not the one following... - -A typical run: - $ make clean - $ make - $ ./create_stuff - $ ./bench > output1 - Running: getpid - for 0.13353 seconds - Running: getppid - for 3.65609 seconds - Running: getenv - for 0.20924 seconds - Running: getenvT2 - for 0.37437 seconds - Running: gettimeofday - for 0.58077 seconds - etc... - -Use the supplied multiview script to compare runs like: - -multiview output1 output2 > compare.html -open compare.html (safari launches) -will show output2 results as a percentage change from the output1 results - -*** Adding additional benchmark tests *** - -Look at the sample file trivial.c. This demonstrates how to do -argument passing, the flow of control of a benchmark, etc. for the -trivial case. The tests starting with "lmbench_" were ported from -the lmbench suite, so they might be good examples as well. - -*** A note regarding future changes in bench.sh script *** -coreos_bench.sh script is almost identical to bench.sh script, except that it -has additional code to disable the stepper during libmicro benchmark run. - -In future, if bench.sh script is modified, make sure the changes reflect -in coreos_bench.sh script also. - -*** Things to do *** - -* port the rest of the lmbench benchmarks into this framework - -* create website that will allow easy ability to compare many builds -across many machines with historical repository of runs - -* document better how to write a benchmark for this framework -(started in trivial.c) - -* check this into xnu/test - -* create new benchmarks - -*** Leopard notes *** - -Due to rdar://4654956 and its original, rdar://2588252 you cannot -run these tests on Leopard without removing the cascade_lockf test. -There may be other tests which panic a Leopard system. - -*** benchDS notes *** - -From rdar://problem/7468995 add the ability to benchmark the key APIs -for server daemons. In particular, a test binary is added for each of: - - ODQueryCreateWithNode() (standard User, Groups, and Hosts records) - getaddrinfo() (hosts and ports) - mbr_check_service_membership() - mbr_check_membership() - getpwnam() - getpwuid() - getgrgid() - getpwent() - getgrent() - getgrnam() - -The script benchDS is provided to run a standard set of tests presuming -that the tests are run by root on a system configured with an OD binding. -The OD server (local or remote) must have a set of accounts created with -od_acount_create shell script. This script must also be run as root, -and passed a single argument of the number of users to create. It creates -od_test_{1..N}, and all belong to a ds_test_group1(gid 1211). In addition, -ds_test_group2(gid 1212) is created which has no users as members. User ids are -set sequentially from 5000. In order to administer the OD server, it assumes -user 'diradmin' and password 'admin' are the OD admin. - -Also, these tests consult the APIs listed, which can be run against the local -account info, or even Active Directory. - -Thus, the quick recipe is: - Install X Server - Enable OD, and create directory admin user 'diradmin' with password 'admin' - As root run: od_account_create 1000 - Now run the test, as root: ./benchDS 1000 > output-file - - -In addition, od_account_delete 1000 will delete the 1000 users created with od_account_create. - - diff --git a/tools/tests/libMicro/Makefile b/tools/tests/libMicro/Makefile deleted file mode 100644 index 3eecede2f..000000000 --- a/tools/tests/libMicro/Makefile +++ /dev/null @@ -1,120 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms -# of the Common Development and Distribution License -# (the "License"). You may not use this file except -# in compliance with the License. -# -# You can obtain a copy of the license at -# src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing -# permissions and limitations under the License. -# -# When distributing Covered Code, include this CDDL -# HEADER in each file and include the License file at -# usr/src/OPENSOLARIS.LICENSE. If applicable, -# add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your -# own identifying information: Portions Copyright [yyyy] -# [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - - -include Makefile.benchmarks - -ARCH = i386 - -BINS= $(ALL:%=bin-$(ARCH)/%) bin-$(ARCH)/tattle - -# TARBALL_CONTENTS = \ - Makefile.benchmarks \ - Makefile.SunOS \ - Makefile.Linux \ - Makefile.Aix \ - Makefile.com \ - Makefile \ - $(ALL:%=%.c) \ - elided.c \ - exec_bin.c \ - libmicro.c \ - libmicro_main.c \ - libmicro.h \ - recurse2.c \ - benchmark_finibatch.c \ - benchmark_initbatch.c \ - benchmark_optswitch.c \ - benchmark_fini.c \ - benchmark_init.c \ - benchmark_result.c \ - benchmark_finirun.c \ - benchmark_initrun.c \ - benchmark_initworker.c \ - benchmark_finiworker.c \ - bench \ - bench.sh \ - coreos_bench \ - coreos_bench.sh \ - mk_tarball \ - multiview \ - multiview.sh \ - OPENSOLARIS.LICENSE \ - tattle.c \ - wrapper \ - wrapper.sh \ - README - -ifeq "$(Embedded)" "YES" -SEMOP_FLAG= -endif - -default $(ALL) run cstyle lint tattle: $(BINS) - @cp bench.sh bench - @cp coreos_bench.sh coreos_bench - @cp embd_bench.sh embd_bench - @cp multiview.sh multiview - @cp wrapper.sh wrapper - @cp create_stuff.sh create_stuff - @cp benchDS.sh benchDS - @cp od_account_create.sh od_account_create - @cp od_account_delete.sh od_account_delete - @chmod +x bench coreos_bench embd_bench create_stuff multiview wrapper benchDS od_account_create od_account_delete - @mkdir -p bin-$(ARCH); cd bin-$(ARCH); MACH=$(ARCH) $(MAKE) -f ../Makefile.`uname -s` ARCH=$(ARCH) UNAME_RELEASE=`uname -r | sed 's/\./_/g'` $@ - @echo "code signing all the binaries under bin-$(ARCH) and apple/bin-$(ARCH)" - @for file in $(abspath bin-$(ARCH)/*) $(abspath apple/bin-$(ARCH)/*);do \ - if test -x $$file;then \ - codesign -s - $$file 1>& /dev/null ; \ - fi; \ - done; - @echo "done" - -.PHONY: clean clean_subdirs clean_$(SUBDIRS) - -clean: clean_subdirs - rm -rf bin bin-* wrapper multiview create_stuff bench tattle benchDS od_account_create od_account_delete coreos_bench embd_bench - -clean_subdirs: - for dir in $(SUBDIRS); do $(MAKE) -C $$dir clean; done - -bin: - @mkdir -p bin-$(ARCH) - -$(BINS): bin - @cp wrapper.sh wrapper - @chmod +x wrapper - @ln -sf ../wrapper $@ - -# commenting the lbMicro.tar as it is not being used. -# libMicro.tar: FORCE -# @chmod +x ./mk_tarball wrapper -# @./mk_tarball $(TARBALL_CONTENTS) - -# FORCE: diff --git a/tools/tests/libMicro/Makefile.Aix b/tools/tests/libMicro/Makefile.Aix deleted file mode 100644 index 9e4dc4224..000000000 --- a/tools/tests/libMicro/Makefile.Aix +++ /dev/null @@ -1,41 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms -# of the Common Development and Distribution License -# (the "License"). You may not use this file except -# in compliance with the License. -# -# You can obtain a copy of the license at -# src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing -# permissions and limitations under the License. -# -# When distributing Covered Code, include this CDDL -# HEADER in each file and include the License file at -# usr/src/OPENSOLARIS.LICENSE. If applicable, -# add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your -# own identifying information: Portions Copyright [yyyy] -# [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - - -CFLAGS= -O3 - -CPPFLAGS = -D_REENTRANT - -include ../Makefile.com - -NSLLIB= -lnsl -SOCKLIB= - -.KEEP_STATE: diff --git a/tools/tests/libMicro/Makefile.Darwin b/tools/tests/libMicro/Makefile.Darwin deleted file mode 100644 index 5bb7da2dd..000000000 --- a/tools/tests/libMicro/Makefile.Darwin +++ /dev/null @@ -1,84 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms -# of the Common Development and Distribution License -# (the "License"). You may not use this file except -# in compliance with the License. -# -# You can obtain a copy of the license at -# src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing -# permissions and limitations under the License. -# -# When distributing Covered Code, include this CDDL -# HEADER in each file and include the License file at -# usr/src/OPENSOLARIS.LICENSE. If applicable, -# add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your -# own identifying information: Portions Copyright [yyyy] -# [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "@(#)Makefile.Darwin 1.5 05/08/04 SMI" -# - -SDKROOT ?= / -Product=$(shell tconf --product) -Embedded=$(shell tconf --test TARGET_OS_EMBEDDED) - -ifeq "$(Embedded)" "YES" -SDKPATH = $(shell xcodebuild -sdk $(SDKROOT) -version Path) -CFLAGS += -isysroot $(SDKPATH) -endif - -CC = $(shell xcrun -sdk "$(SDKROOT)" -find gcc) -#NOPIC= -mdynamic-no-pic -ARCH= i386 - -ifeq "$(strip $(ARCH))" "fat" -ARCH_FLAG= -arch i386 -arch x86_64 -else -ARCH_FLAG= -arch $(ARCH) -endif - -### OPT_FLAG value was modified from '-g' to '-Os' as part of the fix for radar 7508837 -OPT_FLAG= -Os -SEMOP_FLAG= -DUSE_SEMOP - -ifeq "$(Embedded)" "YES" -SEMOP_FLAG= -endif - -### -###CFLAGS= -Os -DUSE_SEMOP -fno-builtin $(NOPIC) $(ARCH_FLAG) -Wall -###extra_CFLAGS= -Os -DUSE_SEMOP -fno-builtin $(NOPIC) $(ARCH_FLAG) -Wall -### -CFLAGS+= $(OPT_FLAG) $(SEMOP_FLAG) -DUSE_GETHRTIME -fno-builtin $(NOPIC) $(ARCH_FLAG) -Wall - -ifeq "$(Embedded)" "YES" -#CFLAGS+= $(OPT_FLAG) -DUSE_GETHRTIME -fno-builtin $(NOPIC) $(ARCH_FLAG) -Wall -CFLAGS+= -g -I $(SDKPATH)/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders/ -F/AppleInternal/Library/Frameworks/ $(MORECFLAGS) -endif - - - -extra_CFLAGS= $(OPT_FLAG) $(SEMOP_FLAG) -fno-builtin $(NOPIC) $(ARCH_FLAG) -Wall -CPPFLAGS= $(SEMOP_FLAG) -D_REENTRANT -Wall -MATHLIB= -lm - -ELIDED_BENCHMARKS= \ - cachetocache \ - atomic \ - getcontext \ - setcontext \ - - -include ../Makefile.com.Darwin diff --git a/tools/tests/libMicro/Makefile.Linux b/tools/tests/libMicro/Makefile.Linux deleted file mode 100644 index ca12d1561..000000000 --- a/tools/tests/libMicro/Makefile.Linux +++ /dev/null @@ -1,43 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms -# of the Common Development and Distribution License -# (the "License"). You may not use this file except -# in compliance with the License. -# -# You can obtain a copy of the license at -# src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing -# permissions and limitations under the License. -# -# When distributing Covered Code, include this CDDL -# HEADER in each file and include the License file at -# usr/src/OPENSOLARIS.LICENSE. If applicable, -# add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your -# own identifying information: Portions Copyright [yyyy] -# [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - - -CC= gcc - -#CFLAGS= -O -DUSE_SEMOP -CPPFLAGS= -DUSE_SEMOP -D_REENTRANT -MATHLIB= -lm - -ELIDED_BENCHMARKS= \ - cachetocache \ - atomic - - -include ../Makefile.com diff --git a/tools/tests/libMicro/Makefile.SunOS b/tools/tests/libMicro/Makefile.SunOS deleted file mode 100644 index 4fc726975..000000000 --- a/tools/tests/libMicro/Makefile.SunOS +++ /dev/null @@ -1,61 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms -# of the Common Development and Distribution License -# (the "License"). You may not use this file except -# in compliance with the License. -# -# You can obtain a copy of the license at -# src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing -# permissions and limitations under the License. -# -# When distributing Covered Code, include this CDDL -# HEADER in each file and include the License file at -# usr/src/OPENSOLARIS.LICENSE. If applicable, -# add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your -# own identifying information: Portions Copyright [yyyy] -# [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - - -CPPFLAGS= -DUSE_GETHRTIME -D_REENTRANT - -CFLAGS = -O $(extra_CFLAGS) - -# -# These defines allow libmicro to be compiled against older Solaris -# releases by turning off the tests which don't work there. -# -# This is a little contorted-- UNAME_RELEASE is set as an environment -# variable for us by the invoking make process (see Makefile)-- it is -# the output of uname -r | sed 's/\./_/g'. -# -# We couldn't find any other gmake/unix make portable way to make this -# work. -# -ELIDED_BENCHMARKS_5_8=atomic cachetocache -ELIDED_BENCHMARKS_5_9=atomic - -ELIDED_BENCHMARKS_CMN=cascade_flock - -ELIDED_BENCHMARKS=$(ELIDED_BENCHMARKS_CMN) $(ELIDED_BENCHMARKS_$(UNAME_RELEASE)) - -include ../Makefile.com - -NSLLIB= -lnsl -SOCKLIB= -lsocket -UCBLIB= -lc -L/usr/ucblib -lucb -R/usr/ucblib -MATHLIB= -lm - -.KEEP_STATE: diff --git a/tools/tests/libMicro/Makefile.benchmarks b/tools/tests/libMicro/Makefile.benchmarks deleted file mode 100644 index 96c105f76..000000000 --- a/tools/tests/libMicro/Makefile.benchmarks +++ /dev/null @@ -1,137 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms -# of the Common Development and Distribution License -# (the "License"). You may not use this file except -# in compliance with the License. -# -# You can obtain a copy of the license at -# src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing -# permissions and limitations under the License. -# -# When distributing Covered Code, include this CDDL -# HEADER in each file and include the License file at -# usr/src/OPENSOLARIS.LICENSE. If applicable, -# add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your -# own identifying information: Portions Copyright [yyyy] -# [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -SUBDIRS = apple - -ALL= \ - atomic \ - bind \ - cachetocache \ - cascade_mutex \ - cascade_cond \ - cascade_lockf \ - cascade_fcntl \ - cascade_flock \ - chdir \ - close \ - close_tcp \ - connection \ - dup \ - exec \ - exit \ - exp \ - fcntl \ - fcntl_ndelay \ - file_lock \ - fork \ - getcontext \ - getenv \ - gettimeofday \ - getpeername \ - getpid \ - getrusage \ - getsockname \ - isatty \ - listen \ - localtime_r \ - log \ - longjmp \ - lrand48 \ - lseek \ - malloc \ - memcpy \ - memmove \ - memrand \ - memset \ - mktime \ - mprotect \ - mmap \ - msync \ - munmap \ - mutex \ - nop \ - open \ - pipe \ - poll \ - pread \ - pthread_create \ - pwrite \ - read \ - realpath \ - recurse \ - select \ - semop \ - setcontext \ - setsockopt \ - sigaction \ - siglongjmp \ - signal \ - sigprocmask \ - socket \ - socketpair \ - stat \ - strcasecmp \ - strchr \ - strcmp \ - strcpy \ - strftime \ - strlen \ - strtol \ - system \ - time \ - times \ - write \ - writev - -ALL_APPLE = \ - create_file \ - getppid \ - lb_mmtest \ - lm_null_call \ - lmbench_bw_file_rd \ - lmbench_bw_mem \ - lmbench_bw_mmap_rd \ - lmbench_bw_unix \ - lmbench_fstat \ - lmbench_lat_sig_catch \ - lmbench_lat_sig_install \ - lmbench_lat_sig_prot \ - lmbench_lat_sig_send \ - lmbench_openclose \ - lmbench_read \ - lmbench_select_file \ - lmbench_select_tcp \ - lmbench_stat \ - lmbench_write \ - posix_spawn \ - trivial \ - vm_allocate - - diff --git a/tools/tests/libMicro/Makefile.com b/tools/tests/libMicro/Makefile.com deleted file mode 100644 index 5cb92a10e..000000000 --- a/tools/tests/libMicro/Makefile.com +++ /dev/null @@ -1,128 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms -# of the Common Development and Distribution License -# (the "License"). You may not use this file except -# in compliance with the License. -# -# You can obtain a copy of the license at -# src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing -# permissions and limitations under the License. -# -# When distributing Covered Code, include this CDDL -# HEADER in each file and include the License file at -# usr/src/OPENSOLARIS.LICENSE. If applicable, -# add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your -# own identifying information: Portions Copyright [yyyy] -# [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -include ../Makefile.benchmarks - -EXTRA_CFILES= \ - exec_bin.c \ - elided.c \ - tattle.c - -# -# some definitions to make getting compiler versions possible - avoid quotes -# -COMPILER_VERSION_CMD_cc=cc -V 2>&1 | egrep Sun -COMPILER_VERSION_CMD_gcc=gcc -dumpversion -COMPILER_VERSION_CMD=$(COMPILER_VERSION_CMD_$(CC)) - -default: $(ALL) tattle - -cstyle: - for file in $(ALL:%=../%.c) $(EXTRA_CFILES:%=../%) ; \ - do cstyle -p $$file ;\ - done - - -lint: libmicro.ln $(ALL:%=%.lint) $(EXTRA_CFILES:%.c=%.lint) - - -$(EXTRA_CFILES:%.c=%.lint): - $(LINT) ../$(@:%.lint=%.c) -I. -mu -lc libmicro.ln -lm - -%.lint: ../%.c libmicro.ln - $(LINT) -mu $(CPPFLAGS) $< libmicro.ln -lpthread -lsocket -lnsl -lm - -%.o: ../%.c - $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ - -libmicro.ln: ../libmicro.c ../libmicro_main.c ../libmicro.h ../benchmark_*.c - $(LINT) -muc $(CPPFLAGS) ../libmicro.c ../libmicro_main.c ../benchmark_*.c - -CPPFLAGS+= -D_REENTRANT - -bind_EXTRA_LIBS=$(NSLLIB) $(SOCKLIB) -cascade_flock_EXTRA_LIBS=$(UCBLIB) -close_tcp_EXTRA_LIBS=$(NSLLIB) $(SOCKLIB) -connection_EXTRA_LIBS=$(NSLLIB) $(SOCKLIB) -fcntl_ndelay_EXTRA_LIBS=$(SOCKLIB) -getpeername_EXTRA_LIBS=$(NSLLIB) $(SOCKLIB) -getsockname_EXTRA_LIBS=$(NSLLIB) $(SOCKLIB) -listen_EXTRA_LIBS=$(NSLLIB) $(SOCKLIB) -log_EXTRA_LIBS=$(MATHLIB) -pipe_EXTRA_LIBS=$(NSLLIB) $(SOCKLIB) -poll_EXTRA_LIBS=$(SOCKLIB) -select_EXTRA_LIBS=$(SOCKLIB) -setsockopt_EXTRA_LIBS=$(NSLLIB) $(SOCKLIB) -socket_EXTRA_LIBS=$(SOCKLIB) -socketpair_EXTRA_LIBS=$(SOCKLIB) - -BENCHMARK_FUNCS= \ - benchmark_init.o \ - benchmark_fini.o \ - benchmark_initrun.o \ - benchmark_finirun.o \ - benchmark_initbatch.o \ - benchmark_finibatch.o \ - benchmark_initworker.o \ - benchmark_finiworker.o \ - benchmark_optswitch.o \ - benchmark_result.o - -recurse_EXTRA_DEPS=recurse2.o - - -recurse: $(recurse_EXTRA_DEPS) - -libmicro.a: libmicro.o libmicro_main.o $(BENCHMARK_FUNCS) - $(AR) -cr libmicro.a libmicro.o libmicro_main.o $(BENCHMARK_FUNCS) - -tattle: ../tattle.c libmicro.a - echo "char * compiler_version = \""`$(COMPILER_VERSION_CMD)`"\";" > tattle.h - echo "char * CC = \""$(CC)"\";" >> tattle.h - echo "char * extra_compiler_flags = \""$(extra_CFLAGS)"\";" >> tattle.h - $(CC) -o tattle $(CFLAGS) -I. ../tattle.c libmicro.a -lrt -lm - cp tattle ../tattle - -$(ELIDED_BENCHMARKS): ../elided.c - $(CC) -o $(@) ../elided.c - -%: libmicro.a %.o - $(CC) -o $(@) $(@).o $($(@)_EXTRA_DEPS) $(CFLAGS) libmicro.a $($(@)_EXTRA_LIBS) $(EXTRA_LIBS) -lpthread -lm - -exec: exec_bin - -exec_bin: exec_bin.o - $(CC) -o exec_bin $(CFLAGS) exec_bin.o - -FORCE: - - -._KEEP_STATE: - diff --git a/tools/tests/libMicro/Makefile.com.Darwin b/tools/tests/libMicro/Makefile.com.Darwin deleted file mode 100644 index eb942dbe2..000000000 --- a/tools/tests/libMicro/Makefile.com.Darwin +++ /dev/null @@ -1,142 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms -# of the Common Development and Distribution License -# (the "License"). You may not use this file except -# in compliance with the License. -# -# You can obtain a copy of the license at -# src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing -# permissions and limitations under the License. -# -# When distributing Covered Code, include this CDDL -# HEADER in each file and include the License file at -# usr/src/OPENSOLARIS.LICENSE. If applicable, -# add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your -# own identifying information: Portions Copyright [yyyy] -# [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "@(#)Makefile.com.Darwin 1.10 05/08/04 SMI" -# - -include ../Makefile.benchmarks - -EXTRA_CFILES= \ - exec_bin.c \ - elided.c \ - tattle.c - -# -# some definitions to make getting compiler versions possible - avoid quotes -# -COMPILER_VERSION_CMD_cc=cc -V 2>&1 | egrep Sun -COMPILER_VERSION_CMD_gcc=gcc -dumpversion -COMPILER_VERSION_CMD=$(COMPILER_VERSION_CMD_$(CC)) - -default: $(ALL) subdirs tattle - -cstyle: - for file in $(ALL:%=../%.c) $(EXTRA_CFILES:%=../%) ; \ - do cstyle -p $$file ;\ - done - - -lint: libmicro.ln $(ALL:%=%.lint) $(EXTRA_CFILES:%.c=%.lint) - - -$(EXTRA_CFILES:%.c=%.lint): - $(LINT) ../$(@:%.lint=%.c) -I. -mu -lc libmicro.ln -lm - -%.lint: ../%.c libmicro.ln - $(LINT) -mu $(CPPFLAGS) $< libmicro.ln -lpthread -lsocket -lnsl -lm - -%.o: ../%.c - $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ - -libmicro.ln: ../libmicro.c ../libmicro_main.c ../libmicro.h ../benchmark_*.c - $(LINT) -muc $(CPPFLAGS) ../libmicro.c ../libmicro_main.c ../benchmark_*.c - -CPPFLAGS+= -D_REENTRANT - -bind_EXTRA_LIBS=$(NSLLIB) $(SOCKLIB) -cascade_flock_EXTRA_LIBS=$(UCBLIB) -close_tcp_EXTRA_LIBS=$(NSLLIB) $(SOCKLIB) -connection_EXTRA_LIBS=$(NSLLIB) $(SOCKLIB) -fcntl_ndelay_EXTRA_LIBS=$(SOCKLIB) -getpeername_EXTRA_LIBS=$(NSLLIB) $(SOCKLIB) -getsockname_EXTRA_LIBS=$(NSLLIB) $(SOCKLIB) -listen_EXTRA_LIBS=$(NSLLIB) $(SOCKLIB) -log_EXTRA_LIBS=$(MATHLIB) -pipe_EXTRA_LIBS=$(NSLLIB) $(SOCKLIB) -poll_EXTRA_LIBS=$(SOCKLIB) -select_EXTRA_LIBS=$(SOCKLIB) -setsockopt_EXTRA_LIBS=$(NSLLIB) $(SOCKLIB) -socket_EXTRA_LIBS=$(SOCKLIB) -socketpair_EXTRA_LIBS=$(SOCKLIB) - -BENCHMARK_FUNCS= \ - benchmark_init.o \ - benchmark_fini.o \ - benchmark_initrun.o \ - benchmark_finirun.o \ - benchmark_initbatch.o \ - benchmark_finibatch.o \ - benchmark_initworker.o \ - benchmark_finiworker.o \ - benchmark_optswitch.o \ - benchmark_result.o - -recurse_EXTRA_DEPS=recurse2.o - - -recurse: $(recurse_EXTRA_DEPS) - -libmicro.a: libmicro.o libmicro_main.o $(BENCHMARK_FUNCS) - $(AR) -cr libmicro.a libmicro.o libmicro_main.o $(BENCHMARK_FUNCS) - ranlib libmicro.a - -tattle: ../tattle.c libmicro.a - echo "char * compiler_version = \""`$(COMPILER_VERSION_CMD)`"\";" > tattle.h - echo "char * CC = \""$(CC)"\";" >> tattle.h - echo "char * extra_compiler_flags = \""$(extra_CFLAGS)"\";" >> tattle.h - $(CC) -o tattle $(CFLAGS) -I. ../tattle.c libmicro.a -lSystem -lm - cp tattle ../tattle - -$(ELIDED_BENCHMARKS): ../elided.c - $(CC) $(CFLAGS) -o $(@) ../elided.c - -%: libmicro.a %.o - $(CC) -o $(@) $(@).o $($(@)_EXTRA_DEPS) $(CFLAGS) libmicro.a $($(@)_EXTRA_LIBS) $(EXTRA_LIBS) -lpthread -lm - -exec: exec_bin - -exec_bin: exec_bin.o - $(CC) -o exec_bin $(CFLAGS) exec_bin.o - -# for apple added tests - -.PHONY: subdirs $(SUBDIRS) - -subdirs: $(SUBDIRS) - -$(SUBDIRS): - cd ..; $(MAKE) -C $@ ARCH=$(ARCH) - - - -FORCE: - - -._KEEP_STATE: - diff --git a/tools/tests/libMicro/OPENSOLARIS.LICENSE b/tools/tests/libMicro/OPENSOLARIS.LICENSE deleted file mode 100644 index 535dec222..000000000 --- a/tools/tests/libMicro/OPENSOLARIS.LICENSE +++ /dev/null @@ -1,385 +0,0 @@ -Unless otherwise noted, all files in this distribution are released -under the Common Development and Distribution License (CDDL), -Version 1.0 only. Exceptions are noted within the associated -source files. - --------------------------------------------------------------------- - - -COMMON DEVELOPMENT AND DISTRIBUTION LICENSE Version 1.0 - -1. Definitions. - - 1.1. "Contributor" means each individual or entity that creates - or contributes to the creation of Modifications. - - 1.2. "Contributor Version" means the combination of the Original - Software, prior Modifications used by a Contributor (if any), - and the Modifications made by that particular Contributor. - - 1.3. "Covered Software" means (a) the Original Software, or (b) - Modifications, or (c) the combination of files containing - Original Software with files containing Modifications, in - each case including portions thereof. - - 1.4. "Executable" means the Covered Software in any form other - than Source Code. - - 1.5. "Initial Developer" means the individual or entity that first - makes Original Software available under this License. - - 1.6. "Larger Work" means a work which combines Covered Software or - portions thereof with code not governed by the terms of this - License. - - 1.7. "License" means this document. - - 1.8. "Licensable" means having the right to grant, to the maximum - extent possible, whether at the time of the initial grant or - subsequently acquired, any and all of the rights conveyed - herein. - - 1.9. "Modifications" means the Source Code and Executable form of - any of the following: - - A. Any file that results from an addition to, deletion from or - modification of the contents of a file containing Original - Software or previous Modifications; - - B. Any new file that contains any part of the Original - Software or previous Modifications; or - - C. Any new file that is contributed or otherwise made - available under the terms of this License. - - 1.10. "Original Software" means the Source Code and Executable - form of computer software code that is originally released - under this License. - - 1.11. "Patent Claims" means any patent claim(s), now owned or - hereafter acquired, including without limitation, method, - process, and apparatus claims, in any patent Licensable by - grantor. - - 1.12. "Source Code" means (a) the common form of computer software - code in which modifications are made and (b) associated - documentation included in or with such code. - - 1.13. "You" (or "Your") means an individual or a legal entity - exercising rights under, and complying with all of the terms - of, this License. For legal entities, "You" includes any - entity which controls, is controlled by, or is under common - control with You. For purposes of this definition, - "control" means (a) the power, direct or indirect, to cause - the direction or management of such entity, whether by - contract or otherwise, or (b) ownership of more than fifty - percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants. - - 2.1. The Initial Developer Grant. - - Conditioned upon Your compliance with Section 3.1 below and - subject to third party intellectual property claims, the Initial - Developer hereby grants You a world-wide, royalty-free, - non-exclusive license: - - (a) under intellectual property rights (other than patent or - trademark) Licensable by Initial Developer, to use, - reproduce, modify, display, perform, sublicense and - distribute the Original Software (or portions thereof), - with or without Modifications, and/or as part of a Larger - Work; and - - (b) under Patent Claims infringed by the making, using or - selling of Original Software, to make, have made, use, - practice, sell, and offer for sale, and/or otherwise - dispose of the Original Software (or portions thereof). - - (c) The licenses granted in Sections 2.1(a) and (b) are - effective on the date Initial Developer first distributes - or otherwise makes the Original Software available to a - third party under the terms of this License. - - (d) Notwithstanding Section 2.1(b) above, no patent license is - granted: (1) for code that You delete from the Original - Software, or (2) for infringements caused by: (i) the - modification of the Original Software, or (ii) the - combination of the Original Software with other software - or devices. - - 2.2. Contributor Grant. - - Conditioned upon Your compliance with Section 3.1 below and - subject to third party intellectual property claims, each - Contributor hereby grants You a world-wide, royalty-free, - non-exclusive license: - - (a) under intellectual property rights (other than patent or - trademark) Licensable by Contributor to use, reproduce, - modify, display, perform, sublicense and distribute the - Modifications created by such Contributor (or portions - thereof), either on an unmodified basis, with other - Modifications, as Covered Software and/or as part of a - Larger Work; and - - (b) under Patent Claims infringed by the making, using, or - selling of Modifications made by that Contributor either - alone and/or in combination with its Contributor Version - (or portions of such combination), to make, use, sell, - offer for sale, have made, and/or otherwise dispose of: - (1) Modifications made by that Contributor (or portions - thereof); and (2) the combination of Modifications made by - that Contributor with its Contributor Version (or portions - of such combination). - - (c) The licenses granted in Sections 2.2(a) and 2.2(b) are - effective on the date Contributor first distributes or - otherwise makes the Modifications available to a third - party. - - (d) Notwithstanding Section 2.2(b) above, no patent license is - granted: (1) for any code that Contributor has deleted - from the Contributor Version; (2) for infringements caused - by: (i) third party modifications of Contributor Version, - or (ii) the combination of Modifications made by that - Contributor with other software (except as part of the - Contributor Version) or other devices; or (3) under Patent - Claims infringed by Covered Software in the absence of - Modifications made by that Contributor. - -3. Distribution Obligations. - - 3.1. Availability of Source Code. - - Any Covered Software that You distribute or otherwise make - available in Executable form must also be made available in Source - Code form and that Source Code form must be distributed only under - the terms of this License. You must include a copy of this - License with every copy of the Source Code form of the Covered - Software You distribute or otherwise make available. You must - inform recipients of any such Covered Software in Executable form - as to how they can obtain such Covered Software in Source Code - form in a reasonable manner on or through a medium customarily - used for software exchange. - - 3.2. Modifications. - - The Modifications that You create or to which You contribute are - governed by the terms of this License. You represent that You - believe Your Modifications are Your original creation(s) and/or - You have sufficient rights to grant the rights conveyed by this - License. - - 3.3. Required Notices. - - You must include a notice in each of Your Modifications that - identifies You as the Contributor of the Modification. You may - not remove or alter any copyright, patent or trademark notices - contained within the Covered Software, or any notices of licensing - or any descriptive text giving attribution to any Contributor or - the Initial Developer. - - 3.4. Application of Additional Terms. - - You may not offer or impose any terms on any Covered Software in - Source Code form that alters or restricts the applicable version - of this License or the recipients' rights hereunder. You may - choose to offer, and to charge a fee for, warranty, support, - indemnity or liability obligations to one or more recipients of - Covered Software. However, you may do so only on Your own behalf, - and not on behalf of the Initial Developer or any Contributor. - You must make it absolutely clear that any such warranty, support, - indemnity or liability obligation is offered by You alone, and You - hereby agree to indemnify the Initial Developer and every - Contributor for any liability incurred by the Initial Developer or - such Contributor as a result of warranty, support, indemnity or - liability terms You offer. - - 3.5. Distribution of Executable Versions. - - You may distribute the Executable form of the Covered Software - under the terms of this License or under the terms of a license of - Your choice, which may contain terms different from this License, - provided that You are in compliance with the terms of this License - and that the license for the Executable form does not attempt to - limit or alter the recipient's rights in the Source Code form from - the rights set forth in this License. If You distribute the - Covered Software in Executable form under a different license, You - must make it absolutely clear that any terms which differ from - this License are offered by You alone, not by the Initial - Developer or Contributor. You hereby agree to indemnify the - Initial Developer and every Contributor for any liability incurred - by the Initial Developer or such Contributor as a result of any - such terms You offer. - - 3.6. Larger Works. - - You may create a Larger Work by combining Covered Software with - other code not governed by the terms of this License and - distribute the Larger Work as a single product. In such a case, - You must make sure the requirements of this License are fulfilled - for the Covered Software. - -4. Versions of the License. - - 4.1. New Versions. - - Sun Microsystems, Inc. is the initial license steward and may - publish revised and/or new versions of this License from time to - time. Each version will be given a distinguishing version number. - Except as provided in Section 4.3, no one other than the license - steward has the right to modify this License. - - 4.2. Effect of New Versions. - - You may always continue to use, distribute or otherwise make the - Covered Software available under the terms of the version of the - License under which You originally received the Covered Software. - If the Initial Developer includes a notice in the Original - Software prohibiting it from being distributed or otherwise made - available under any subsequent version of the License, You must - distribute and make the Covered Software available under the terms - of the version of the License under which You originally received - the Covered Software. Otherwise, You may also choose to use, - distribute or otherwise make the Covered Software available under - the terms of any subsequent version of the License published by - the license steward. - - 4.3. Modified Versions. - - When You are an Initial Developer and You want to create a new - license for Your Original Software, You may create and use a - modified version of this License if You: (a) rename the license - and remove any references to the name of the license steward - (except to note that the license differs from this License); and - (b) otherwise make it clear that the license contains terms which - differ from this License. - -5. DISCLAIMER OF WARRANTY. - - COVERED SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" - BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, - INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED - SOFTWARE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR - PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND - PERFORMANCE OF THE COVERED SOFTWARE IS WITH YOU. SHOULD ANY - COVERED SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE - INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY - NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF - WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF - ANY COVERED SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS - DISCLAIMER. - -6. TERMINATION. - - 6.1. This License and the rights granted hereunder will terminate - automatically if You fail to comply with terms herein and fail to - cure such breach within 30 days of becoming aware of the breach. - Provisions which, by their nature, must remain in effect beyond - the termination of this License shall survive. - - 6.2. If You assert a patent infringement claim (excluding - declaratory judgment actions) against Initial Developer or a - Contributor (the Initial Developer or Contributor against whom You - assert such claim is referred to as "Participant") alleging that - the Participant Software (meaning the Contributor Version where - the Participant is a Contributor or the Original Software where - the Participant is the Initial Developer) directly or indirectly - infringes any patent, then any and all rights granted directly or - indirectly to You by such Participant, the Initial Developer (if - the Initial Developer is not the Participant) and all Contributors - under Sections 2.1 and/or 2.2 of this License shall, upon 60 days - notice from Participant terminate prospectively and automatically - at the expiration of such 60 day notice period, unless if within - such 60 day period You withdraw Your claim with respect to the - Participant Software against such Participant either unilaterally - or pursuant to a written agreement with Participant. - - 6.3. In the event of termination under Sections 6.1 or 6.2 above, - all end user licenses that have been validly granted by You or any - distributor hereunder prior to termination (excluding licenses - granted to You by any distributor) shall survive termination. - -7. LIMITATION OF LIABILITY. - - UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT - (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE - INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF - COVERED SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE - LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR - CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT - LIMITATION, DAMAGES FOR LOST PROFITS, LOSS OF GOODWILL, WORK - STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER - COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN - INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF - LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL - INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT - APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO - NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR - CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT - APPLY TO YOU. - -8. U.S. GOVERNMENT END USERS. - - The Covered Software is a "commercial item," as that term is - defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial - computer software" (as that term is defined at 48 - C.F.R. 252.227-7014(a)(1)) and "commercial computer software - documentation" as such terms are used in 48 C.F.R. 12.212 - (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 - C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all - U.S. Government End Users acquire Covered Software with only those - rights set forth herein. This U.S. Government Rights clause is in - lieu of, and supersedes, any other FAR, DFAR, or other clause or - provision that addresses Government rights in computer software - under this License. - -9. MISCELLANEOUS. - - This License represents the complete agreement concerning subject - matter hereof. If any provision of this License is held to be - unenforceable, such provision shall be reformed only to the extent - necessary to make it enforceable. This License shall be governed - by the law of the jurisdiction specified in a notice contained - within the Original Software (except to the extent applicable law, - if any, provides otherwise), excluding such jurisdiction's - conflict-of-law provisions. Any litigation relating to this - License shall be subject to the jurisdiction of the courts located - in the jurisdiction and venue specified in a notice contained - within the Original Software, with the losing party responsible - for costs, including, without limitation, court costs and - reasonable attorneys' fees and expenses. The application of the - United Nations Convention on Contracts for the International Sale - of Goods is expressly excluded. Any law or regulation which - provides that the language of a contract shall be construed - against the drafter shall not apply to this License. You agree - that You alone are responsible for compliance with the United - States export administration regulations (and the export control - laws and regulation of any other countries) when You use, - distribute or otherwise make available any Covered Software. - -10. RESPONSIBILITY FOR CLAIMS. - - As between Initial Developer and the Contributors, each party is - responsible for claims and damages arising, directly or - indirectly, out of its utilization of rights under this License - and You agree to work with Initial Developer and Contributors to - distribute such responsibility on an equitable basis. Nothing - herein is intended or shall be deemed to constitute any admission - of liability. - --------------------------------------------------------------------- - -NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND -DISTRIBUTION LICENSE (CDDL) - -For Covered Software in this distribution, this License shall -be governed by the laws of the State of California (excluding -conflict-of-law provisions). - -Any litigation relating to this License shall be subject to the -jurisdiction of the Federal Courts of the Northern District of -California and the state courts of the State of California, with -venue lying in Santa Clara County, California. diff --git a/tools/tests/libMicro/README b/tools/tests/libMicro/README deleted file mode 100644 index 9db9f814c..000000000 --- a/tools/tests/libMicro/README +++ /dev/null @@ -1,125 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms -# of the Common Development and Distribution License -# (the "License"). You may not use this file except -# in compliance with the License. -# -# You can obtain a copy of the license at -# src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing -# permissions and limitations under the License. -# -# When distributing Covered Code, include this CDDL -# HEADER in each file and include the License file at -# usr/src/OPENSOLARIS.LICENSE. If applicable, -# add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your -# own identifying information: Portions Copyright [yyyy] -# [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -Building the tarball --------------------- -As long as cc is in your path, (gcc on Linux), - -% tar xf libMicro.tar -% make - -will build the benchmark suite. - -Running the benchmarks ------------------------ - -A set of generic scripts to invoke each micro benchmark -are created in the bin directory; these may be invoked -directly. Note that the actual binaries are created in -OS-specific directories; this allows one to build for -all varients (x86/sparc/Solaris/Linux) in one place. - -To collect a complete set of benchmarks, use the bench -script and redirect its output to a file. - -% ./bench > output - -To compare the output of two or more runs, use multiview in the src -directory: - -% ./multiview reference compare1 compare2 compare2 > compare.html -% - -where the reference and compare files contain the output of different -libmicro runs. - -The compare.html file will allow quick comparisons to be drawn, -allowing a variety of experiments to be quickly analyzed. - -All benchmarks support the following options: - - [-1] (single process; overrides -P > 1) - [-A] (align with clock) - [-B batch-size (default 10)] - [-C minimum number of samples (default 0)] - [-D duration in msecs (default 10s)] - [-E (echo name to stderr)] - [-H] (suppress headers) - [-I] specify approx. time per op in nsecs - [-L] (print argument line) - [-M] (reports mean rather than median) - [-N test-name ] - [-P processes (default 1)] - [-S] (print detailed stats) - [-T threads (default 1)] - [-V] (print the libMicro version and exit) - [-W] (flag possible benchmark problems) - - -Apple-added Benchmarks ------------------------ - - create_file - geekbench_stdlib_write - getaddrinfo_port - getaddrinfo_host - getgrgid - getgrent - getgrnam - getppid - getpwnam - getpwuid - getpwent - lb_mmtest - lm_null_call - lmbench_bw_file_rd - lmbench_bw_mem - lmbench_bw_mmap_rd - lmbench_bw_unix - lmbench_fstat - lmbench_lat_ctx - lmbench_lat_sig_catch - lmbench_lat_sig_install - lmbench_lat_sig_prot - lmbench_lat_sig_send - lmbench_openclose - lmbench_read - lmbench_select_file - lmbench_select_tcp - lmbench_stat - lmbench_write - mbr_check_service_membership - mbr_check_membership - od_query_create_with_node - trivial - vm_allocate - -Also, please read AppleReadMe for further information. - diff --git a/tools/tests/libMicro/apple/Makefile b/tools/tests/libMicro/apple/Makefile deleted file mode 100644 index 906ef9618..000000000 --- a/tools/tests/libMicro/apple/Makefile +++ /dev/null @@ -1,46 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms -# of the Common Development and Distribution License -# (the "License"). You may not use this file except -# in compliance with the License. -# -# You can obtain a copy of the license at -# src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing -# permissions and limitations under the License. -# -# When distributing Covered Code, include this CDDL -# HEADER in each file and include the License file at -# usr/src/OPENSOLARIS.LICENSE. If applicable, -# add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your -# own identifying information: Portions Copyright [yyyy] -# [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -include Makefile.benchmarks - -ARCH= i386 - -BINS= $(ALL:%=../bin-$(ARCH)/%) - -default $(ALL): $(BINS) - @mkdir -p bin-$(ARCH); cd bin-$(ARCH); MACH=$(ARCH) $(MAKE) -f ../Makefile.`uname -s` ARCH=$(ARCH) UNAME_RELEASE=`uname -r | sed 's/\./_/g'` $@ - -clean: - rm -rf bin bin-* - -bin: - @mkdir -p ../bin-$(ARCH) - -$(BINS): bin diff --git a/tools/tests/libMicro/apple/Makefile.Darwin b/tools/tests/libMicro/apple/Makefile.Darwin deleted file mode 100644 index ff1f4a668..000000000 --- a/tools/tests/libMicro/apple/Makefile.Darwin +++ /dev/null @@ -1,85 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms -# of the Common Development and Distribution License -# (the "License"). You may not use this file except -# in compliance with the License. -# -# You can obtain a copy of the license at -# src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing -# permissions and limitations under the License. -# -# When distributing Covered Code, include this CDDL -# HEADER in each file and include the License file at -# usr/src/OPENSOLARIS.LICENSE. If applicable, -# add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your -# own identifying information: Portions Copyright [yyyy] -# [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "@(#)Makefile.Darwin 1.5 05/08/04 SMI" -# - -SDKROOT ?= / -Product=$(shell tconf --product) -Embedded=$(shell tconf --test TARGET_OS_EMBEDDED) - -ifeq "$(Embedded)" "YES" -SDKPATH = $(shell xcodebuild -sdk "$(SDKROOT)" -version Path) -CFLAGS += -isysroot $(SDKPATH) -EmbeddedOS=yes -endif - -CC = $(shell xcrun -sdk "$(SDKROOT)" -find gcc) -#NOPIC= -mdynamic-no-pic -ARCH= i386 - -ifeq "$(strip $(ARCH))" "fat" -ARCH_FLAG= -arch i386 -arch x86_64 -else -ARCH_FLAG= -arch $(ARCH) -endif - -### OPT_FLAG value was modified from '-g' to '-Os' as part of the fix for radar 7508837 -OPT_FLAG= -Os -SEMOP_FLAG= -DUSE_SEMOP -ifeq "$(Embedded)" "YES" -SEMOP_FLAG= -endif - -### -###CFLAGS= -Os -DUSE_SEMOP -fno-builtin $(NOPIC) $(ARCH_FLAG) -Wall -###extra_CFLAGS= -Os -DUSE_SEMOP -fno-builtin $(NOPIC) $(ARCH_FLAG) -Wall -### -CFLAGS+= $(OPT_FLAG) $(SEMOP_FLAG) -DUSE_GETHRTIME -fno-builtin $(NOPIC) $(ARCH_FLAG) -Wall - -ifeq "$(Embedded)" "YES" -#CFLAGS+= $(OPT_FLAG) -DUSE_GETHRTIME -fno-builtin $(NOPIC) $(ARCH_FLAG) -Wall -CFLAGS+= -g -I $(SDKPATH)/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders/ -F/AppleInternal/Library/Frameworks/ $(MORECFLAGS) -endif - -extra_CFLAGS= $(OPT_FLAG) $(SEMOP_FLAG) -DUSE_GETHRTIME -fno-builtin $(NOPIC) $(ARCH_FLAG) -Wall -CPPFLAGS= $(SEMOP_FLAG) -D_REENTRANT -Wall -MATHLIB= -lm - -ELIDED_BENCHMARKS= \ - cachetocache \ - atomic \ - getcontext \ - setcontext \ - fork \ - exit \ - connection - - -include ../Makefile.com.Darwin diff --git a/tools/tests/libMicro/apple/Makefile.benchmarks b/tools/tests/libMicro/apple/Makefile.benchmarks deleted file mode 100644 index 5fd65660d..000000000 --- a/tools/tests/libMicro/apple/Makefile.benchmarks +++ /dev/null @@ -1,70 +0,0 @@ -# -# The contents of this file are subject to the terms -# of the Common Development and Distribution License -# (the "License"). You may not use this file except -# in compliance with the License. -# -# You can obtain a copy of the license at -# src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing -# permissions and limitations under the License. -# -# When distributing Covered Code, include this CDDL -# HEADER in each file and include the License file at -# usr/src/OPENSOLARIS.LICENSE. If applicable, -# add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your -# own identifying information: Portions Copyright [yyyy] -# [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -Embedded=$(shell tconf --test TARGET_OS_EMBEDDED) - -ALL = \ - create_file \ - geekbench_stdlib_write \ - getppid \ - lb_mmtest \ - lm_null_call \ - lmbench_bw_file_rd \ - lmbench_bw_mem \ - lmbench_bw_mmap_rd \ - lmbench_bw_unix \ - lmbench_fstat \ - lmbench_lat_ctx \ - lmbench_lat_sig_catch \ - lmbench_lat_sig_install \ - lmbench_lat_sig_prot \ - lmbench_lat_sig_send \ - lmbench_openclose \ - lmbench_read \ - lmbench_select_file \ - lmbench_select_tcp \ - lmbench_stat \ - lmbench_write \ - posix_spawn \ - trivial \ - vm_allocate \ - mbr_check_service_membership \ - getpwnam \ - mbr_check_membership \ - getpwuid \ - getgrgid \ - getpwent \ - getgrent \ - getaddrinfo_host \ - getaddrinfo_port \ - getgrnam - -# Compile the following test on desktop platform only -ifeq "$(Embedded)" "NO" -ALL += od_query_create_with_node -endif diff --git a/tools/tests/libMicro/apple/Makefile.com.Darwin b/tools/tests/libMicro/apple/Makefile.com.Darwin deleted file mode 100644 index a72a31657..000000000 --- a/tools/tests/libMicro/apple/Makefile.com.Darwin +++ /dev/null @@ -1,61 +0,0 @@ -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms -# of the Common Development and Distribution License -# (the "License"). You may not use this file except -# in compliance with the License. -# -# You can obtain a copy of the license at -# src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing -# permissions and limitations under the License. -# -# When distributing Covered Code, include this CDDL -# HEADER in each file and include the License file at -# usr/src/OPENSOLARIS.LICENSE. If applicable, -# add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your -# own identifying information: Portions Copyright [yyyy] -# [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# ident "@(#)Makefile.com.Darwin 1.10 05/08/04 SMI" -# - -include ../Makefile.benchmarks - -EXTRA_CFILES= \ - exec_bin.c \ - elided.c \ - tattle.c - -# -# some definitions to make getting compiler versions possible - avoid quotes -# -COMPILER_VERSION_CMD_cc=cc -V 2>&1 | egrep Sun -COMPILER_VERSION_CMD_gcc=gcc -dumpversion -COMPILER_VERSION_CMD=$(COMPILER_VERSION_CMD_$(CC)) - -default: $(ALL) - -%.o: ../%.c - $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ - -%: %.o - $(CC) -o $(@) $(@).o $($(@)_EXTRA_DEPS) $(CFLAGS) ../../bin-$(ARCH)/libmicro.a $($(@)_EXTRA_LIBS) $(EXTRA_LIBS) -lpthread -lm; cp $@ ../../bin-$(ARCH)/ - -posix_spawn: posix_spawn_bin - -posix_spawn_bin: posix_spawn_bin.o - $(CC) -o posix_spawn_bin $(CFLAGS) posix_spawn_bin.o - -od_query_create_with_node: od_query_create_with_node.o - $(CC) -o $(@) $(@).o $($(@)_EXTRA_DEPS) $(CFLAGS) ../../bin-$(ARCH)/libmicro.a $($(@)_EXTRA_LIBS) $(EXTRA_LIBS) -lpthread -lm -framework CoreFoundation -framework OpenDirectory; cp $@ ../../bin-$(ARCH)/ diff --git a/tools/tests/libMicro/apple/create_file.c b/tools/tests/libMicro/apple/create_file.c deleted file mode 100644 index f4e5abf34..000000000 --- a/tools/tests/libMicro/apple/create_file.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -/* - * Order of Execution - * - * benchmark_init - * - * benchmark_optswitch - * - * benchmark_initrun - * - * benchmark_initworker - * benchmark_initbatch - * benchmark - * benchmark_finibatch - * benchmark_initbatch - * benchmark - * benchmark_finibatch, etc. - * benchmark_finiworker - * - * benchmark_result - * - * benchmark_finirun - * - * benchmark_fini - */ - - - -#ifdef __sun -#pragma ident "@(#)trivial.c 1.0 08/17/06 Apple Inc." -#endif - - - -#include -#include -#include -#include -#include -// add additional headers needed here. -#include - -#include "../libmicro.h" - -#if DEBUG -# define debug(fmt, args...) (void) fprintf(stderr, fmt "\n" , ##args) -#else -# define debug(fmt, args...) -#endif - -#define MAXPATHLEN 1024 -/* - * Your state variables should live in the tsd_t struct below - */ -typedef struct { - int ts_once; -} tsd_t; - -/* - * You can have any lower-case option you want to define. - * options are specified in the lm_optstr as either a - * single lower-case letter, or a single lower case letter - * with a colon after it. In this example, you can optionally - * specify -c {str} -e or -t {number} - * -c takes a string (quote the string if blanks) - * -e is a boolean - * -t takes a numeric - * argument. - */ -static char * optf; // allocated in benchmark_init, freed in benchmark_fini. - - -int -benchmark_init() -{ - debug("benchmark_init\n"); - /* - * the lm_optstr must be defined here or no options for you - * - * ...and the framework will throw an error - * - */ - (void) sprintf(lm_optstr, "f:"); - /* - * tsd_t is the state info struct that we pass around - * - * lm_tsdsize will allocate the space we need for this - * structure throughout the rest of the framework - */ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_usage, - " -f filename\n" - "notes: measures file creation using open(2)\n"); - - optf = malloc(MAXPATHLEN); - sprintf(optf, "/tmp/create_file_%d", getpid()); - return (0); -} - -/* - * This is where you parse your lower-case arguments. - * the format was defined in the lm_optstr assignment - * in benchmark_init - */ -int -benchmark_optswitch(int opt, char *optarg) -{ - debug("benchmark_optswitch\n"); - - switch (opt) { - case 'f': - strncpy(optf, optarg, 20); - (void)fprintf(stderr, "optf = %s\n", optf); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initrun() -{ - debug("benchmark_initrun\n"); - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - /* - * initialize your state variables here first - */ -// tsd_t *ts = (tsd_t *)tsd; -// debug("benchmark_initworker: ts_once = %i\n",ts->ts_once); - return (0); -} - -/*ARGSUSED*/ -int -benchmark_initbatch(void *tsd) -{ - /* - * initialize your state variables here second - */ - tsd_t *ts = (tsd_t *)tsd; - // useless code to show what you can do. - ts->ts_once++; - ts->ts_once--; - debug("benchmark_initbatch: ts_once = %i\n",ts->ts_once); - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - /* - * try not to initialize things here. This is the main - * loop of things to get timed. Start a server in - * benchmark_initbatch - */ -// tsd_t *ts = (tsd_t *)tsd; - int i; - - debug("in to benchmark - optB = %i : ts_once = %i\n", lm_optB, ts->ts_once); - for (i = 0; i < lm_optB; i++) { - if (!open(optf, O_CREAT)) - res->re_errors++; - } - res->re_count = i; - debug("out of benchmark - optB = %i : ts_once = %i\n", lm_optB, ts->ts_once); - - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ -// tsd_t *ts = (tsd_t *)tsd; -// debug("benchmark_finibatch: ts_once = %i\n",ts->ts_once); - return (0); -} - -int -benchmark_finiworker(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - // useless code to show what you can do. - ts->ts_once++; - ts->ts_once--; - debug("benchmark_finiworker: ts_once = %i\n",ts->ts_once); - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - debug("benchmark_result\n"); - return (&result); -} - -int -benchmark_finirun() -{ - debug("benchmark_finirun\n"); - return (0); -} - - -int -benchmark_fini() -{ - debug("benchmark_fini\n"); - free(optf); - return (0); -} - diff --git a/tools/tests/libMicro/apple/geekbench_stdlib_write.c b/tools/tests/libMicro/apple/geekbench_stdlib_write.c deleted file mode 100644 index 65bcee95e..000000000 --- a/tools/tests/libMicro/apple/geekbench_stdlib_write.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -/* - * Order of Execution - * - * benchmark_init - * - * benchmark_optswitch - * - * benchmark_initrun - * - * benchmark_initworker - * benchmark_initbatch - * benchmark - * benchmark_finibatch - * benchmark_initbatch - * benchmark - * benchmark_finibatch, etc. - * benchmark_finiworker - * - * benchmark_result - * - * benchmark_finirun - * - * benchmark_fini - */ - - - -#ifdef __sun -#pragma ident "@(#)geekbench_stdlib_write.c 1.0 08/17/06 Apple Inc." -#endif - - - -#include -#include -#include -#include - -#include "../libmicro.h" - -/* - * Your state variables should live in the tsd_t struct below - */ -typedef struct { - int ts_once; -} tsd_t; - -unsigned char * arena; -unsigned int arenaSize = 1048576; - -static int optt = 1; - -/*ARGSUSED*/ -int -benchmark_initbatch(void *tsd) -{ - /* - * initialize your state variables here second - */ - //tsd_t *ts = (tsd_t *)tsd; - //(void) fprintf(stderr, "benchmark_initbatch: ts_once = %i\n",ts->ts_once); - return (0); -} - -int -benchmark_finirun() -{ - (void) fprintf(stderr, "benchmark_finirun\n"); - return (0); -} - -int -benchmark_init() -{ - (void) fprintf(stderr, "benchmark_init\n"); - /* - * the lm_optstr must be defined here or no options for you - * - * ...and the framework will throw an error - * - */ - (void) sprintf(lm_optstr, "t:"); - /* - * working hypothesis: - * - * tsd_t is the struct that we can pass around our - * state info in - * - * lm_tsdsize will allocate the space we need for this - * structure throughout the rest of the framework - */ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_usage, - " [-t int (default 1)]\n" - "notes: measures nothing\n"); - return (0); -} - -int -benchmark_fini() -{ - (void) fprintf(stderr, "benchmark_fini\n"); - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - /* - * more proof of state passing - */ - ts->ts_once = optt; - //(void) fprintf(stderr, "benchmark_finibatch: ts_once = %i\n",ts->ts_once); - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - (void) fprintf(stderr, "benchmark_result\n"); - return (&result); -} - -int -benchmark_finiworker(void *tsd) -{ - //tsd_t *ts = (tsd_t *)tsd; - //(void) fprintf(stderr, "benchmark_finiworker: ts_once = %i\n",ts->ts_once); - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - (void) fprintf(stderr, "benchmark_optswitch\n"); - - switch (opt) { - case 't': - optt = sizetoint(optarg); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - /* - * initialize your state variables here first - */ - //tsd_t *ts = (tsd_t *)tsd; - //ts->ts_once = optt; - //(void) fprintf(stderr, "benchmark_initworker: ts_once = %i\n",ts->ts_once); - arena = ( unsigned char * )malloc( arenaSize); - return (0); -} - -int -benchmark_initrun() -{ - //(void) fprintf(stderr, "benchmark_initrun\n"); - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - /* - * initialize your state variables here last - * - * and realize that you are paying for your initialization here - * and it is really a bad idea - */ - //tsd_t *ts = (tsd_t *)tsd; - int i; - - //(void) fprintf(stderr, "in to benchmark - optB = %i : ts_once = %i\n", lm_optB, ts->ts_once); - for (i = 0; i < lm_optB; i++) { - /* - * just to show that ts really contains state - */ - //(void) fprintf(stderr, "i is %i\n",i); - memset( arena, 0, arenaSize ); - } - res->re_count = i; - //(void) fprintf(stderr, "out of benchmark - optB = %i : ts_once = %i\n", lm_optB, ts->ts_once); - - return (0); -} diff --git a/tools/tests/libMicro/apple/getaddrinfo_host.c b/tools/tests/libMicro/apple/getaddrinfo_host.c deleted file mode 100644 index a7041753f..000000000 --- a/tools/tests/libMicro/apple/getaddrinfo_host.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#include -#include -#include -#include -#include -#include -#include - -// add additional headers needed here. - -#include "../libmicro.h" - -#if DEBUG -# define debug(fmt, args...) (void) fprintf(stderr, fmt "\n" , ##args) -#else -# define debug(fmt, args...) -#endif - - -// -// Correct use case -// -// getaddrinfo_host -E -L -S -W -B 200 -C 100 -s "server%d" -// -// libMicro default benchmark run options are "-E -L -S -W -C 200" -// -// -B is batch size: loop iteration per each benchmark run. Needs to match # of -// real lookups. This is total number of lookups to issue. -// -C is min sample number: how many benchmark needs to run to get proper sample -// 1 is mimumum, but you get at least 3 benchmark run -// samples. Do not set to zero. Default is 200 for most -// runs in libMicro. -// -h is hostname format: for example, "server-%d.performance.rack" -// this is C language string format that can include %d -// -r hostname digit range in the form of "min-max". For example, -r 100-112 -// With -h and -r, resulting hostnames are -// server-100.performance.rack - server-112.performance.rack -// - -extern int gL1CacheEnabled; - -/* - * Your state variables should live in the tsd_t struct below - */ -typedef struct { -} tsd_t; - -#define HOSTNAME_LEN 125 -static int host_min=-1, host_range=0; -static char *hostname_format=NULL; -static char *hostname_list=NULL; - -int -benchmark_init() -{ - debug("benchmark_init"); - (void) sprintf(lm_optstr, "l:h:r:"); - - lm_tsdsize = sizeof (tsd_t); - lm_defB = 100; - - (void) sprintf(lm_usage, - "\n ------- getaddrinfo_host specific options (default: *)\n" - " [-h \"hostname format\"]. ie. \"server-%%d.perf\"\n" - " [-r min-max]\n" - "\n" ); - - return (0); -} - - -int -parse_range(int *min, int *offset, char *buf) -{ - char *value, *tmp_ptr = strdup(buf); - int range=0; - debug("parse_range"); - - value = strsep(&tmp_ptr, "-"); - *min = atoi(value); - debug("min = %d", *min); - if (tmp_ptr) { - value = strsep(&tmp_ptr, "-"); - range = atoi(value); - if (range < *min) { - printf("max id should be larger than min id\n"); - return -1; - } - *offset = range - *min + 1; // 1-based - debug("range = %d", *offset); - } - else { - printf("argument should be in the form of min-max\n"); - return -1; - } - - return 0; - -} - -/* - * This is where you parse your lower-case arguments. - */ -int -benchmark_optswitch(int opt, char *optarg) -{ - debug("benchmark_optswitch"); - - switch (opt) { - case 'h': // hostname string format - hostname_format = strdup(optarg); - debug ("hostname format: %s", hostname_format); - break; - - case 'l': - gL1CacheEnabled = atoi(optarg); - break; - - case 'r': // UID range - return parse_range( &host_min, &host_range, optarg); - break; - - default: - return -1; - } - - - - return 0; -} - - -// Initialize all structures that will be used in benchmark() -// -int -benchmark_initrun() -{ - int i; - - debug("\nbenchmark_initrun"); - - if (host_min == -1) { - printf("-r min-max needs to be specified\n"); - exit (1); - } - - if (!hostname_format) { - printf("-h hostname_format needs to be specified\n"); - exit (1); - } - - hostname_list = malloc ( host_range * HOSTNAME_LEN ); - if (!hostname_list) { - debug("malloc error"); - exit (1); - } - - for (i = 0; i < host_range; i++) { - sprintf( &hostname_list[i*HOSTNAME_LEN], hostname_format, i+host_min); - // debug("hostname: %s", &hostname_list[i*HOSTNAME_LEN]); - } - return (0); -} - - -int -benchmark(void *tsd, result_t *res) -{ - int i, index, err; - struct addrinfo *addi; - - res->re_errors = 0; - - debug("in to benchmark - optB = %i", lm_optB); - srandom(getpid()); - - for (i = 0; i < lm_optB; i++) { - index = HOSTNAME_LEN * (random() % host_range); - - err = getaddrinfo( &hostname_list[index], NULL, NULL, &addi); - - if (err) { - debug("%s: error: %s", &hostname_list[index], gai_strerror(err)); - res->re_errors++; - } - else { - debug("host %s done", &hostname_list[index]); - } - - freeaddrinfo (addi); - } - res->re_count = i; - - return (0); -} - -// We need to release all the structures we allocated in benchmark_initrun() -int -benchmark_finirun(void *tsd) -{ - // tsd_t *ts = (tsd_t *)tsd; - debug("benchmark_finirun "); - - free(hostname_list); - - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - debug("benchmark_result"); - return (&result); -} - diff --git a/tools/tests/libMicro/apple/getaddrinfo_port.c b/tools/tests/libMicro/apple/getaddrinfo_port.c deleted file mode 100644 index 846486faa..000000000 --- a/tools/tests/libMicro/apple/getaddrinfo_port.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#include -#include -#include -#include -#include -#include -#include - -// add additional headers needed here. - -#include "../libmicro.h" - -#if DEBUG -# define debug(fmt, args...) (void) fprintf(stderr, fmt "\n" , ##args) -#else -# define debug(fmt, args...) -#endif - - -// This exercises "ssh" port -// -// Correct use case -// -// getaddrinfo_port -E -L -S -W -B 200 -C 100 -// -// libMicro default benchmark run options are "-E -L -S -W -C 200" -// -// -B is batch size: loop iteration per each benchmark run. Needs to match # of -// real lookups. This is total number of lookups to issue. -// -C is min sample number: how many benchmark needs to run to get proper sample -// 1 is mimumum, but you get at least 3 benchmark run -// samples. Do not set to zero. Default is 200 for most -// runs in libMicro. -// - -extern int gL1CacheEnabled; - -/* - * Your state variables should live in the tsd_t struct below - */ -typedef struct { -} tsd_t; - - -int -benchmark_init() -{ - debug("benchmark_init"); - - (void) sprintf(lm_optstr, "l:"); - lm_tsdsize = sizeof (tsd_t); - lm_defB = 100; - - return (0); -} - - -/* - * This is where you parse your lower-case arguments. - */ -int -benchmark_optswitch(int opt, char *optarg) -{ - debug("benchmark_optswitch"); - - switch (opt) { - case 'l': - gL1CacheEnabled = atoi(optarg); - break; - } - - return 0; -} - - -// Initialize all structures that will be used in benchmark() -// -int -benchmark_initrun() -{ - debug("\nbenchmark_initrun"); - - return (0); -} - - -int -benchmark(void *tsd, result_t *res) -{ - int i, err; - struct addrinfo *addi; - - res->re_errors = 0; - - debug("in to benchmark - optB = %i", lm_optB); - for (i = 0; i < lm_optB; i++) { - - err = getaddrinfo(NULL, "ssh", NULL, &addi); - - if (err) { - debug("error: %s", gai_strerror(err)); - res->re_errors++; - } - - freeaddrinfo (addi); - } - res->re_count = i; - - return (0); -} - -// We need to release all the structures we allocated in benchmark_initrun() -int -benchmark_finirun(void *tsd) -{ - // tsd_t *ts = (tsd_t *)tsd; - debug("benchmark_finirun "); - - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - debug("benchmark_result"); - return (&result); -} - diff --git a/tools/tests/libMicro/apple/getgrent.c b/tools/tests/libMicro/apple/getgrent.c deleted file mode 100644 index 321bbed87..000000000 --- a/tools/tests/libMicro/apple/getgrent.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#include -#include -#include -#include -#include -#include - -// add additional headers needed here. - -#include "../libmicro.h" -#include - -#if DEBUG -# define debug(fmt, args...) (void) fprintf(stderr, fmt "\n" , ##args) -#else -# define debug(fmt, args...) -#endif - - -// Correct use case -// -// getgrent -E -L -S -W -B 200 -C 100 -// -// libMicro default benchmark run options are "-E -L -S -W -C 200" -// -// -B is batch size: loop iteration per each benchmark run. Needs to match # of -// real lookups. This is total number of lookups to issue. -// -C is min sample number: how many benchmark needs to run to get proper sample -// 1 is mimumum, but you get at least 3 benchmark run -// samples. Do not set to zero. Default is 200 for most -// runs in libMicro. -// - -extern int gL1CacheEnabled; - -/* - * Your state variables should live in the tsd_t struct below - */ -typedef struct { -} tsd_t; - - -int -benchmark_init() -{ - debug("benchmark_init"); - - (void) sprintf(lm_optstr, "l:"); - lm_tsdsize = sizeof (tsd_t); - lm_defB = 100; - - return (0); -} - - -/* - * This is where you parse your lower-case arguments. - */ -int -benchmark_optswitch(int opt, char *optarg) -{ - debug("benchmark_optswitch"); - - switch (opt) { - case 'l': - gL1CacheEnabled = atoi(optarg); - break; - } - - return 0; -} - - -// Initialize all structures that will be used in benchmark() -// -int -benchmark_initrun() -{ - debug("\nbenchmark_initrun"); - - return (0); -} - - -int -benchmark(void *tsd, result_t *res) -{ - int i; - struct group *grp; - - res->re_errors = 0; - - debug("in to benchmark - optB = %i", lm_optB); - for (i = 0; i < lm_optB; i++) { - - errno = 0; // this is needed explicitly due to getgrent() design - grp = getgrent(); - - if (!grp) { - if (errno) { - debug("error: %s", strerror(errno)); - res->re_errors++; - } - else { - // will not be counted as error - setgroupent(1); // rewind to the beginning of passwd file - } - } - else { - debug("gr_name: %s", grp->gr_name); - } - } - res->re_count = i; - - return (0); -} - -// We need to release all the structures we allocated in benchmark_initrun() -int -benchmark_finirun(void *tsd) -{ - // tsd_t *ts = (tsd_t *)tsd; - debug("benchmark_finirun "); - - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - debug("benchmark_result"); - return (&result); -} - diff --git a/tools/tests/libMicro/apple/getgrgid.c b/tools/tests/libMicro/apple/getgrgid.c deleted file mode 100644 index f49925d18..000000000 --- a/tools/tests/libMicro/apple/getgrgid.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#include -#include -#include -#include -#include -#include - -// add additional headers needed here. - -#include "../libmicro.h" -#include -#include - -#if DEBUG -# define debug(fmt, args...) (void) fprintf(stderr, fmt "\n" , ##args) -#else -# define debug(fmt, args...) -#endif - - -// Correct use case -// -// getgrgid -E -L -S -W -B 200 -C 10 -g 1211-1213 -// -// libMicro default benchmark run options are "-E -L -S -W -C 200" -// -// -B is batch size: loop iteration per each benchmark run. Needs to match # of -// real lookups. This is total number of lookups to issue. -// -C is min sample number: how many benchmark needs to run to get proper sample -// 1 is mimumum, but you get at least 3 benchmark run -// samples. Do not set to zero. Default is 200 for most -// runs in libMicro. -// -g gid range in the form of "min-max". For example, -g 1211-1213 -// - -extern int gL1CacheEnabled; - -/* - * Your state variables should live in the tsd_t struct below - */ -typedef struct { -} tsd_t; - -// temporary buffer size -#define BUFSIZE 200 -#define INVALID_ID -1 - -static gid_t gid_min = INVALID_ID; -static int gid_range = 0; // gid_max = gid_min + gid_range - -int -benchmark_init() -{ - debug("benchmark_init"); - (void) sprintf(lm_optstr, "l:g:"); - - lm_tsdsize = sizeof (tsd_t); - lm_defB = 100; - - (void) sprintf(lm_usage, - "\n ------- getgrgid specific options (default: *)\n" - " [-g GID range (min-max)]\n" - "\n" ); - return (0); -} - - -int -parse_range(gid_t *min, int *offset, char *buf) -{ - char *value, *tmp_ptr = strdup(buf); - int range=0; - debug("parse_range"); - - value = strsep(&tmp_ptr, "-"); - *min = atoi(value); - debug("min = %d", *min); - if (tmp_ptr) { - value = strsep(&tmp_ptr, "-"); - range = atoi(value); - if (range < *min) { - printf("max id should be larger than min id\n"); - return -1; - } - *offset = range - *min + 1; - debug("range = %d", *offset); - } - else { - printf("argument should be in the form of min-max\n"); - return -1; - } - - return 0; - -} - -/* - * This is where you parse your lower-case arguments. - */ -int -benchmark_optswitch(int opt, char *optarg) -{ - debug("benchmark_optswitch"); - - switch (opt) { - case 'l': - gL1CacheEnabled = atoi(optarg); - break; - - case 'g': // GID range - return parse_range( &gid_min, &gid_range, optarg); - break; - - default: - return -1; - } - - return 0; -} - - -// Initialize all structures that will be used in benchmark() -// moved template init from benchmark_initworker -> benchmark_initrun -// -int -benchmark_initrun() -{ - debug("\nbenchmark_initrun"); - - return (0); -} - - -int -benchmark(void *tsd, result_t *res) -{ - int i, err; - struct group *grp = NULL; - - res->re_errors = 0; - - debug("in to benchmark - optB = %i", lm_optB); - for (i = 0; i < lm_optB; i++) { - gid_t gid = gid_min + random() % gid_range ; - - if (lm_optT > 1) { - struct group gd; - struct group *grp_ptr = &gd; - struct group *tmp_ptr; - char gbuf[BUFSIZE]; - - err = getgrgid_r( gid, grp_ptr, gbuf, BUFSIZE, &tmp_ptr); - if (err) { - debug("error: GID %d -> %s", gid, strerror(err)); - res->re_errors++; - } - else if (!tmp_ptr) { - debug("not found: GID %d", gid); - res->re_errors++; - } - } - else { - errno = 0; - grp = getgrgid( gid ); - - if (!grp) { - if (errno) { - debug("error: GID %d -> %s", gid, strerror(errno)); - res->re_errors++; - } - else { - debug("not found: GID %d", gid); - res->re_errors++; - } - } - } - } - res->re_count = i; - - return (0); -} - -// We need to release all the structures we allocated in benchmark_initrun() -int -benchmark_finirun(void *tsd) -{ - // tsd_t *ts = (tsd_t *)tsd; - debug("benchmark_finirun "); - - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - debug("benchmark_result"); - return (&result); -} - diff --git a/tools/tests/libMicro/apple/getgrnam.c b/tools/tests/libMicro/apple/getgrnam.c deleted file mode 100644 index 7d50a488b..000000000 --- a/tools/tests/libMicro/apple/getgrnam.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#include -#include -#include -#include -#include -#include - -// add additional headers needed here. - -#include "../libmicro.h" -#include -#include - -#if DEBUG -# define debug(fmt, args...) (void) fprintf(stderr, fmt "\n" , ##args) -#else -# define debug(fmt, args...) -#endif - - -// Correct use case -// -// getgrnam -E -L -S -W -B 200 -C 10 -r 10 -// -// libMicro default benchmark run options are "-E -L -S -W -C 200" -// -// -B is batch size: loop iteration per each benchmark run. Needs to match # of -// real lookups. This is total number of lookups to issue. -// -C is min sample number: how many benchmark needs to run to get proper sample -// 1 is mimumum, but you get at least 3 benchmark run -// samples. Do not set to zero. Default is 200 for most -// runs in libMicro. -// -r is the number of total groups (from "local_test_group1" to "local_test_group#") - -extern int gL1CacheEnabled; - -/* - * Your state variables should live in the tsd_t struct below - */ -typedef struct { -} tsd_t; - -// temporary buffer size -#define BUFSIZE 200 - -// the number of record lookup to issue is covered by standard option optB -static int optRecords = 10; // the number of total records - -// This will use local users (local_test_*) -static char *default_gprefix = "ds_test_group"; - -#define GROUPNAME_LEN 30 -static char *grpname_list; - -int -benchmark_init() -{ - debug("benchmark_init"); - (void) sprintf(lm_optstr, "l:r:g:"); - - lm_tsdsize = sizeof (tsd_t); - lm_defB = 100; - - (void) sprintf(lm_usage, - "\n ------- getgrnam specific options (default: *)\n" - " [-r total number of group records (10*)]\n" - " [-g group prefix(ds_test_group)]\n" - "\n" ); - return (0); -} - -/* - * This is where you parse your lower-case arguments. - */ -int -benchmark_optswitch(int opt, char *optarg) -{ - debug("benchmark_optswitch"); - - switch (opt) { - case 'r': // total number of records. default is 100 - optRecords = atoi(optarg); - debug("optRecords = %d\n", optRecords); - break; - - case 'l': - gL1CacheEnabled = atoi(optarg); - break; - - case 'g': // base name for the groups to use - default_gprefix = strdup(optarg); - debug("default_gprefix = %s\n", default_gprefix); - break; - - default: - return -1; - } - - return 0; -} - - -// Initialize all structures that will be used in benchmark() -// moved template init from benchmark_initworker -> benchmark_initrun -// since username_list is static across threads and processes -// -int -benchmark_initrun() -{ - int i; - - debug("\nbenchmark_initrun"); - - // create an array of usernames to use in benchmark before their use - // realtime generation in benchmark effects performance measurements - grpname_list = malloc( optRecords * GROUPNAME_LEN ); - if (!grpname_list) { - debug ("malloc error"); - exit (1); - } - - for (i = 0; i < optRecords; i++) { - sprintf(&grpname_list[i*GROUPNAME_LEN], "%s%d", default_gprefix, i+1); - debug("creating group name %s", &grpname_list[i*GROUPNAME_LEN]); - } - - return (0); -} - - -int -benchmark(void *tsd, result_t *res) -{ - int i, err; - struct group *grp = NULL; - - res->re_errors = 0; - - debug("in to benchmark - optB = %i", lm_optB); - srandom(getpid()); - - for (i = 0; i < lm_optB; i++) { - int index = (random() % optRecords) * GROUPNAME_LEN; - - if (lm_optT > 1) { - struct group gd; - struct group *grp_ptr = &gd; - struct group *tmp_ptr; - char gbuf[BUFSIZE]; - - err = getgrnam_r( &grpname_list[index], grp_ptr, gbuf, BUFSIZE, &tmp_ptr); - // non-NULL err means failure and NULL result ptr means no matching - // entry - if (err) { - debug("error: %s -> %s", &grpname_list[index], strerror(err)); - res->re_errors++; - } - else if ( !tmp_ptr) { - debug("not found: %s", &grpname_list[index] ); - res->re_errors++; - } - } - else { - errno = 0; - grp = getgrnam( &grpname_list[index] ); - - if (!grp) { - if (errno) { - debug("error: %s -> %s", &grpname_list[index], strerror(errno)); - res->re_errors++; - } - else { - debug("not found: %s", &grpname_list[index] ); - res->re_errors++; - } - } - } - } - res->re_count = i; - - return (0); -} - -// We need to release all the structures we allocated in benchmark_initrun() -int -benchmark_finirun(void *tsd) -{ - // tsd_t *ts = (tsd_t *)tsd; - debug("benchmark_finiworker: deallocating structures"); - - free (grpname_list); - - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - debug("benchmark_result"); - return (&result); -} - diff --git a/tools/tests/libMicro/apple/getppid.c b/tools/tests/libMicro/apple/getppid.c deleted file mode 100644 index ac775eb70..000000000 --- a/tools/tests/libMicro/apple/getppid.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -#ifdef __sun -#pragma ident "@(#)getppid.c 1.0 06/20/06 Apple Inc." -#endif - -/* - * getpid - */ - - -#include -#include -#include - -#include "../libmicro.h" - -int -benchmark_init() -{ - (void) sprintf(lm_usage, "note: measures getppid()"); - - lm_tsdsize = 0; - - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - - for (i = 0; i < lm_optB; i ++) { - (void) getppid(); - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/apple/getpwent.c b/tools/tests/libMicro/apple/getpwent.c deleted file mode 100644 index 49df77e21..000000000 --- a/tools/tests/libMicro/apple/getpwent.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#include -#include -#include -#include -#include -#include - -// add additional headers needed here. - -#include "../libmicro.h" -#include - -#if DEBUG -# define debug(fmt, args...) (void) fprintf(stderr, fmt "\n" , ##args) -#else -# define debug(fmt, args...) -#endif - - -// Correct use case -// -// getpwent -E -L -S -W -B 200 -C 100 -// -// libMicro default benchmark run options are "-E -L -S -W -C 200" -// -// -B is batch size: loop iteration per each benchmark run. Needs to match # of -// real lookups. This is total number of lookups to issue. -// -C is min sample number: how many benchmark needs to run to get proper sample -// 1 is mimumum, but you get at least 3 benchmark run -// samples. Do not set to zero. Default is 200 for most -// runs in libMicro. -// - -extern int gL1CacheEnabled; - -/* - * Your state variables should live in the tsd_t struct below - */ -typedef struct { -} tsd_t; - - -int -benchmark_init() -{ - debug("benchmark_init"); - - (void) sprintf(lm_optstr, "l:"); - lm_tsdsize = sizeof (tsd_t); - lm_defB = 100; - - return (0); -} - - -/* - * This is where you parse your lower-case arguments. - */ -int -benchmark_optswitch(int opt, char *optarg) -{ - debug("benchmark_optswitch"); - - switch (opt) { - case 'l': - gL1CacheEnabled = atoi(optarg); - break; - } - - return 0; -} - - -// Initialize all structures that will be used in benchmark() -// -int -benchmark_initrun() -{ - debug("\nbenchmark_initrun"); - - return (0); -} - - -int -benchmark(void *tsd, result_t *res) -{ - int i; - struct passwd *passwd; - - res->re_errors = 0; - - debug("in to benchmark - optB = %i", lm_optB); - for (i = 0; i < lm_optB; i++) { - - errno = 0; // this is needed explicitly due to getpwent() design - passwd = getpwent(); - - if (!passwd) { - if (errno) { - debug("error: %s", strerror(errno)); - res->re_errors++; - } - else { - // will not counted toward libmicro error - setpassent(1); // rewind to the beginning of passwd file - } - } - else { - debug("pw_name: %s", passwd->pw_name); - } - } - res->re_count = i; - - return (0); -} - -// We need to release all the structures we allocated in benchmark_initrun() -int -benchmark_finirun(void *tsd) -{ - // tsd_t *ts = (tsd_t *)tsd; - debug("benchmark_finirun "); - - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - debug("benchmark_result"); - return (&result); -} - diff --git a/tools/tests/libMicro/apple/getpwnam.c b/tools/tests/libMicro/apple/getpwnam.c deleted file mode 100644 index 3db5e6ca4..000000000 --- a/tools/tests/libMicro/apple/getpwnam.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#include -#include -#include -#include -#include -#include - -// add additional headers needed here. - -#include "../libmicro.h" -#include -#include -#include - -#if DEBUG -# define debug(fmt, args...) (void) fprintf(stderr, fmt "\n" , ##args) -#else -# define debug(fmt, args...) -#endif - - -// Correct use case -// -// getpwnam -E -L -S -W -B 200 -C 10 -c 100 -r 300 -U test_user_ -// -// libMicro default benchmark run options are "-E -L -S -W -C 200" -// -// -B is batch size: loop iteration per each benchmark run. Needs to match # of -// real lookups. This is total number of lookups to issue. -// -C is min sample number: how many benchmark needs to run to get proper sample -// 1 is mimumum, but you get at least 3 benchmark run -// samples. Do not set to zero. Default is 200 for most -// runs in libMicro. -// -r is the number of total users -// -c is the cache hit rate for lookup. set to 10%, you need -c 10. -// ie. -B 100 -c 50 -r 1000 -C 200 (out of 1000 records, I want 50% -// lookup, and batch size is 100. -// To get 50% cache hit rate, you need 500 record lookups. -// Batch size will be adjusted to 500 to get 500 record -// lookup in each benchmark. If -r size is smaller than -B, -// then -B will not be adjusted. -// -u prefix: the user name prefix to use in front the user number as the -// login name to lookup - -extern int gL1CacheEnabled; - -/* - * Your state variables should live in the tsd_t struct below - */ -typedef struct { -} tsd_t; - -// temporary buffer size -#define BUFSIZE 200 - -// the number of record lookup to issue is covered by standard option optB -static int optRecords = 100; // the number of total records -static int optCachehit = 100; // specify cache hit rate (% of record re-lookup) - -// This will use local users (local_test_*) -static char *default_uprefix = "local_test_"; - -#define USERNAME_LEN 20 -static char *username_list; - -int -benchmark_init() -{ - debug("benchmark_init"); - (void) sprintf(lm_optstr, "l:c:r:u:"); - - lm_tsdsize = sizeof (tsd_t); - lm_defB = 100; - - (void) sprintf(lm_usage, - "\n ------- getpwnam specific options (default: *)\n" - " [-c hitrate%% (100%%*)]\n" - " [-r total number of records (100*)]\n" - " [-u username_prefix (local_test_)]\n" - "\n" ); - return (0); -} - -/* - * This is where you parse your lower-case arguments. - */ -int -benchmark_optswitch(int opt, char *optarg) -{ - debug("benchmark_optswitch"); - - switch (opt) { - case 'c': // cache hit rate. 100% means lookup the same records over and over - optCachehit = atoi(optarg); - debug("optCachehit = %d\n", optCachehit); - if (optCachehit > 100 || optCachehit < 0) { - printf("cache hit rate should be in between 0%% and 100%%"); - return (-1); - } - break; - - case 'l': - gL1CacheEnabled = atoi(optarg); - break; - - case 'r': // total number of records. default is 100 - optRecords = atoi(optarg); - debug("optRecords = %d\n", optRecords); - break; - - case 'u': - default_uprefix = strdup(optarg); - debug("default_uprefix = %s\n", default_uprefix); - break; - - default: - return -1; - } - - return 0; -} - - -// Initialize all structures that will be used in benchmark() -// moved template init from benchmark_initworker -> benchmark_initrun -// since username_list is static across threads and processes -// - -int -benchmark_initrun() -{ - int i; - - debug("\nbenchmark_initrun"); - - // Adjust # of record lookups to reflect cache hit rate - if (optCachehit < 100) { - optRecords = (int) ((float) optRecords * ((float) optCachehit / 100)); - debug("# of records adjusted to %d for cache hit rate %d%%\n", optRecords, optCachehit); - } - - // if batch size (one benchmark run) is less than the number records, adjust - // it to match the number record lookups in one batch run - if (lm_optB < optRecords) { - lm_optB = optRecords; - debug("Adjusting batch size to %d to match the lookups required in benchmark run\n", lm_optB); - } - - // create an array of usernames to use in benchmark before their use - // realtime generation in benchmark effects performance measurements - username_list = malloc( optRecords * USERNAME_LEN ); - if (!username_list) { - debug ("malloc error"); - exit (1); - } - - for (i = 0; i < optRecords; i++) { - sprintf(&username_list[i*USERNAME_LEN], "%s%d", default_uprefix, i+1); - // debug("creating username %s", &username_list[i*USERNAME_LEN]); - } - - return (0); -} - - -int -benchmark(void *tsd, result_t *res) -{ - int i, err; - struct passwd *passwd = NULL; - - res->re_errors = 0; - - debug("in to benchmark - optB = %i", lm_optB); - for (i = 0; i < lm_optB; i++) { - int index = (random() % optRecords) * USERNAME_LEN; - - if (lm_optT > 1) { - struct passwd pd; - struct passwd *pwd_ptr = &pd; - struct passwd *tmp_ptr; - char pbuf[BUFSIZE]; - - err = getpwnam_r( &username_list[index], pwd_ptr, pbuf, BUFSIZE, &tmp_ptr); - if (err) { - printf("error: %s -> %s", &username_list[index], strerror(err)); - res->re_errors++; - } - else if (!tmp_ptr) { - debug("not found: %s", &username_list[index]); - res->re_errors++; - } - } - else { - errno = 0; - passwd = getpwnam( &username_list[index] ); - - if (!passwd) { - if (errno) { - debug("error: %s -> %s", &username_list[index], strerror(errno)); - res->re_errors++; - } - else { - debug("not found: %s", &username_list[index]); - res->re_errors++; - } - } - } - } - res->re_count = i; - - return (0); -} - -// We need to release all the structures we allocated in benchmark_initrun() -int -benchmark_finirun(void *tsd) -{ - // tsd_t *ts = (tsd_t *)tsd; - debug("benchmark_finirun: deallocating structures"); - - free (username_list); - - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - debug("benchmark_result"); - return (&result); -} - diff --git a/tools/tests/libMicro/apple/getpwuid.c b/tools/tests/libMicro/apple/getpwuid.c deleted file mode 100644 index c33149125..000000000 --- a/tools/tests/libMicro/apple/getpwuid.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#include -#include -#include -#include -#include -#include - -// add additional headers needed here. - -#include "../libmicro.h" -#include - -#if DEBUG -# define debug(fmt, args...) (void) fprintf(stderr, fmt "\n" , ##args) -#else -# define debug(fmt, args...) -#endif - - -// Correct use case -// -// getpwuid -E -L -S -W -B 200 -C 10 -c 100 -u 5000-5200 -// -// libMicro default benchmark run options are "-E -L -S -W -C 200" -// -// -B is batch size: loop iteration per each benchmark run. Needs to match # of -// real lookups. This is total number of lookups to issue. -// -C is min sample number: how many benchmark needs to run to get proper sample -// 1 is mimumum, but you get at least 3 benchmark run -// samples. Do not set to zero. Default is 200 for most -// runs in libMicro. -// -c is the cache hit rate for lookup. set to 10%, you need -c 10. -// ie. -B 100 -c 50 -u 5000-5199 -// out of 200 UIDs, I want 50% cache hit, and batch size is 100. -// -u uid range in the form of "min-max". For example, -u 5000-5200 -// - -extern int gL1CacheEnabled; - -/* - * Your state variables should live in the tsd_t struct below - */ -typedef struct { -} tsd_t; - -// temporary buffer size -#define BUFSIZE 200 -#define INVALID_ID -1 - -static uid_t uid_min = INVALID_ID; -static int uid_range = 0; // uid_max = uid_min + uid_range - -// the number of record lookup to issue is covered by standard option optB -static int optCachehit = 100; // specify cache hit rate (% of record re-lookup) - -int -benchmark_init() -{ - debug("benchmark_init"); - (void) sprintf(lm_optstr, "l:c:u:"); - - lm_tsdsize = sizeof (tsd_t); - lm_defB = 100; - - (void) sprintf(lm_usage, - "\n ------- getpwuid specific options (default: *)\n" - " [-c hitrate%% (100%%*)]\n" - " [-u UID range (min-max)]\n" - " [-l]\n" - "\n" ); - return (0); -} - -int -parse_range(uid_t *min, int *offset, char *buf) -{ - char *value, *tmp_ptr = strdup(buf); - int range=0; - debug("parse_range"); - - value = strsep(&tmp_ptr, "-"); - *min = atoi(value); - debug("min = %d", *min); - if (tmp_ptr) { - value = strsep(&tmp_ptr, "-"); - range = atoi(value); - if (range < *min) { - printf("max id should be larger than min id\n"); - return -1; - } - *offset = range - *min + 1; - debug("range = %d", *offset); - } - else { - printf("argument should be in the form of min-max\n"); - return -1; - } - - return 0; -} - -/* - * This is where you parse your lower-case arguments. - */ -int -benchmark_optswitch(int opt, char *optarg) -{ - debug("benchmark_optswitch"); - - switch (opt) { - case 'c': // cache hit rate. 100% means lookup the same records over and over - optCachehit = atoi(optarg); - debug("optCachehit = %d\n", optCachehit); - if (optCachehit > 100 || optCachehit < 0) { - printf("cache hit rate should be in between 0%% and 100%%"); - return (-1); - } - break; - - case 'l': - gL1CacheEnabled = atoi(optarg); - break; - - case 'u': // UID range - return parse_range( &uid_min, &uid_range, optarg); - break; - - default: - return -1; - } - - return 0; -} - - -// Initialize all structures that will be used in benchmark() -// moved template init from benchmark_initworker -> benchmark_initrun -// since username_list is static across threads and processes -// -int -benchmark_initrun() -{ - uid_t i, range; - struct passwd *passwd = NULL; - - debug("\nbenchmark_initrun"); - - // To satisfy cache hit rate, lookup cachehit percentage of the UIDs here - if (optCachehit < 100) { - - range = (int) ((float) uid_range * ((float) optCachehit / 100)); - for (i = uid_min; i < uid_min+range; i++) - passwd = getpwuid( i ); - } - - return (0); -} - - -int -benchmark(void *tsd, result_t *res) -{ - int i, err; - struct passwd *passwd = NULL; - - res->re_errors = 0; - - debug("in to benchmark - optB = %i", lm_optB); - for (i = 0; i < lm_optB; i++) { - uid_t uid = uid_min + random() % uid_range ; - - // XXX No need to use getpwuid_r() since getpwuid() is already thread-safe - // so it depends on what you want to exercise - if (lm_optT > 1) { - struct passwd pd; - struct passwd *pwd_ptr = &pd; - struct passwd *tmp_ptr; - char pbuf[BUFSIZE]; - - err = getpwuid_r( uid, pwd_ptr, pbuf, BUFSIZE, &tmp_ptr ); - if (err) { - debug("error: %s", strerror(err)); - res->re_errors++; - } - else if (!tmp_ptr) { - debug("not found: UID %d", uid); - res->re_errors++; - } - } - else { - errno = 0; - passwd = getpwuid( uid ); - - if (!passwd) { - if (errno) { - debug("error: %s", strerror(errno)); - res->re_errors++; - } - else { - debug("not found: UID %d", uid); - res->re_errors++; - } - } - } - } - res->re_count = i; - - return (0); -} - -// We need to release all the structures we allocated in benchmark_initrun() -int -benchmark_finirun(void *tsd) -{ - // tsd_t *ts = (tsd_t *)tsd; - debug("benchmark_finirun "); - - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - debug("benchmark_result"); - return (&result); -} - diff --git a/tools/tests/libMicro/apple/lb_mmtest.c b/tools/tests/libMicro/apple/lb_mmtest.c deleted file mode 100644 index 2629ebe34..000000000 --- a/tools/tests/libMicro/apple/lb_mmtest.c +++ /dev/null @@ -1,601 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -/* - * Order of Execution - * - * benchmark_init - * - * benchmark_optswitch - * - * benchmark_initrun - * - * benchmark_initworker - * benchmark_initbatch - * benchmark - * benchmark_finibatch - * benchmark_initbatch - * benchmark - * benchmark_finibatch, etc. - * benchmark_finiworker - * - * benchmark_result - * - * benchmark_finirun - * - * benchmark_fini - */ - - - -#ifdef __sun -#pragma ident "@(#)lb_mmtest.c 1.0 08/21/06 Apple Inc." -#endif - - - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../libmicro.h" - -/* - * Your state variables should live in the tsd_t struct below - */ -typedef struct { - int server_mode; - boolean_t verbose; - boolean_t oneway; - int overwrite; - int msg_type; - int num_ints; - int num_msgs; - const char *server_port_name; - mach_port_t server_port; - mach_port_t reply_port; - int request_msg_size; - void *request_msg; - int reply_msg_size; - void *reply_msg; - void *ints; - long pid; -} tsd_t; - -static boolean_t opt_verbose; -static boolean_t opt_oneway; -static int opt_num_msgs; -static int opt_msg_type; -static int opt_num_ints; -static char * opt_server_port_name; - -#pragma mark *** definitions from MMTest.c -/* - * These variables were taken from MMtest.c - */ -typedef struct { - mach_msg_header_t header; - mach_msg_trailer_t trailer; // subtract this when sending -} ipc_trivial_message; - -typedef struct { - mach_msg_header_t header; - u_int32_t numbers[0]; - mach_msg_trailer_t trailer; // subtract this when sending -} ipc_inline_message; - -typedef struct { - mach_msg_header_t header; - mach_msg_body_t body; - mach_msg_ool_descriptor_t descriptor; - mach_msg_trailer_t trailer; // subtract this when sending -} ipc_complex_message; - -void signal_handler(int sig) { -} - -enum { - msg_type_trivial = 0, - msg_type_inline = 1, - msg_type_complex = 2 -}; - -void server(void *tsd); -void client(void *tsd); - -#pragma mark *** routines from MMTest.c -/* - * These routines were taken from MMtest.c - */ - -void server(void *tsd) { - mach_msg_header_t *request; - mach_msg_header_t *reply; - mach_msg_option_t option; - kern_return_t ret; - - tsd_t *ts = (tsd_t *)tsd; - - request = (mach_msg_header_t *)ts->request_msg; - - reply = (mach_msg_header_t *)ts->reply_msg; - -#ifndef OPTIMIZED_SERVER - for (;;) { -#endif /* !OPTIMIZED_SERVER */ - - if (ts->verbose) printf("Awaiting message\n"); - option = MACH_RCV_MSG|MACH_RCV_INTERRUPT|MACH_RCV_LARGE; - ret = mach_msg(request, - option, - 0, - ts->request_msg_size, - ts->server_port, - MACH_MSG_TIMEOUT_NONE, - MACH_PORT_NULL); - -#ifdef OPTIMIZED_SERVER - for (;;) { - mach_msg_header_t *tmp; -#endif /* OPTIMIZED_SERVER */ - - if (MACH_MSG_SUCCESS != ret) - break; - if (ts->verbose) printf("Received message\n"); - if (request->msgh_bits & MACH_MSGH_BITS_COMPLEX) { - ipc_complex_message *complex_request; - - complex_request = (ipc_complex_message *)ts->request_msg; - ret = vm_deallocate(mach_task_self(), - (vm_address_t)complex_request->descriptor.address, - complex_request->descriptor.size); - } - if (1 == request->msgh_id) { - if (ts->verbose) printf("Sending reply\n"); - reply->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0); - reply->msgh_size = ts->reply_msg_size; - reply->msgh_remote_port = request->msgh_remote_port; - reply->msgh_local_port = MACH_PORT_NULL; - reply->msgh_id = 2; - -#ifdef OPTIMIZED_SERVER - option = MACH_SEND_MSG|MACH_RCV_MSG|MACH_RCV_INTERRUPT|MACH_RCV_LARGE; - } else { - option = MACH_RCV_MSG|MACH_RCV_INTERRUPT|MACH_RCV_LARGE; - } - - ret = mach_msg( reply, - option, - ts->reply_msg_size, - ts->request_msg_size, - ts->server_port, - MACH_MSG_TIMEOUT_NONE, - MACH_PORT_NULL); - tmp = reply; - reply = request; - request = tmp; -#else /* !OPTIMIZED_SERVER */ - ret = mach_msg(reply, - MACH_SEND_MSG, - ts->reply_msg_size, - 0, - MACH_PORT_NULL, - MACH_MSG_TIMEOUT_NONE, - MACH_PORT_NULL); - if (ret != MACH_MSG_SUCCESS) - break; - } -#endif /* !OPTIMIZED_SERVER */ - } - - if (MACH_RCV_INTERRUPTED != ret) { - mach_error("mach_msg: ", ret); - exit(1); - } -} - -void client(void *tsd) { - mach_msg_header_t *request; - mach_msg_header_t *reply; - mach_msg_option_t option; - kern_return_t ret; - int idx; - - tsd_t *ts = (tsd_t *)tsd; - -#ifdef SWAP_BUFFERS - mach_msg_header_t *tmp; -#endif - - request = (mach_msg_header_t *)ts->request_msg; - reply = (mach_msg_header_t *)ts->reply_msg; - - for (idx = 0; idx < ts->num_msgs; idx++) { - request->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, - MACH_MSG_TYPE_MAKE_SEND_ONCE); - request->msgh_size = ts->request_msg_size; - request->msgh_remote_port = ts->server_port; - request->msgh_local_port = ts->reply_port; - - if (ts->msg_type == msg_type_complex) { - ipc_complex_message *complexmsg = (ipc_complex_message *)request; - - request->msgh_bits |= MACH_MSGH_BITS_COMPLEX; - complexmsg->body.msgh_descriptor_count = 1; - complexmsg->descriptor.address = ts->ints; - complexmsg->descriptor.size = ts->num_ints * sizeof(u_int32_t); - complexmsg->descriptor.deallocate = FALSE; - complexmsg->descriptor.copy = MACH_MSG_VIRTUAL_COPY; - complexmsg->descriptor.type = MACH_MSG_OOL_DESCRIPTOR; - } - - if (ts->oneway) { - request->msgh_id = 0; - option = MACH_SEND_MSG; - } else { - request->msgh_id = 1; - option = MACH_SEND_MSG|MACH_RCV_MSG; - } - - if (ts->verbose) printf("Sending request\n"); -#ifdef SWAP_BUFFERS - ret = mach_msg( request, - option, - ts->request_msg_size, - ts->reply_msg_size, - ts->reply_port, - MACH_MSG_TIMEOUT_NONE, - MACH_PORT_NULL); - if (MACH_MSG_SUCCESS != ret) { - mach_error("client: mach_msg: ", ret); - fprintf(stderr, "bailing after %u iterations\n", idx); - exit(1); - } - tmp = request; - request = reply; - reply = tmp; -#else - ret = mach_msg_overwrite(request, - option, - ts->request_msg_size, - ts->reply_msg_size, - ts->reply_port, - MACH_MSG_TIMEOUT_NONE, - MACH_PORT_NULL, - reply, - 0); - if (MACH_MSG_SUCCESS != ret) { - mach_error("client: mach_msg_overwrite: ", ret); - fprintf(stderr, "bailing after %u iterations\n", idx); - exit(1); - } -#endif - if (ts->verbose && !ts->oneway) printf("Received reply\n"); - } -} - - -#pragma mark *** Darbench routines - -/* - * These routines are required by darbench - */ - -/*ARGSUSED*/ -int -benchmark_initbatch(void *tsd) -{ - /* - * initialize your state variables here second - */ - long pid; - tsd_t *ts = (tsd_t *)tsd; - - ts->server_mode = -1; - ts->verbose = opt_verbose; - ts->oneway = opt_oneway; - ts->overwrite = 0; - ts->msg_type = opt_msg_type; - ts->num_ints = opt_num_ints; - ts->num_msgs = opt_num_msgs; - ts->server_port_name = opt_server_port_name; - ts->server_port = MACH_PORT_NULL; - ts->reply_port = MACH_PORT_NULL; - ts->request_msg = NULL; - ts->request_msg_size = 0; - ts->reply_msg = NULL; - ts->reply_msg_size = 0; - - switch (ts->msg_type) { - case msg_type_trivial: - ts->request_msg_size = sizeof(ipc_trivial_message); - break; - - case msg_type_inline: - ts->request_msg_size = sizeof(ipc_inline_message) + - sizeof(u_int32_t) * ts->num_ints; - break; - - case msg_type_complex: - ts->request_msg_size = sizeof(ipc_complex_message); - ts->ints = malloc(sizeof(u_int32_t) * ts->num_ints); - break; - } - - ts->request_msg = malloc(ts->request_msg_size); - ts->reply_msg = malloc(ts->reply_msg_size); - - if (ts->server_mode) { - kern_return_t ret = 0; - mach_port_t bsport; - - ts->reply_msg_size -= sizeof(mach_msg_trailer_t); - ret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, - &(ts->server_port)); - if (KERN_SUCCESS != ret) { - mach_error("mach_port_allocate(): ", ret); - exit(1); - } - ret = mach_port_insert_right(mach_task_self(), ts->server_port, - ts->server_port, MACH_MSG_TYPE_MAKE_SEND); - if (KERN_SUCCESS != ret) { - mach_error("mach_port_insert_right(): ", ret); - exit(1); - } - ret = task_get_bootstrap_port(mach_task_self(), &bsport); - if (KERN_SUCCESS != ret) { - mach_error("task_get_bootstrap_port(): ", ret); - exit(1); - } - ret = bootstrap_check_in(bsport, (char *)ts->server_port_name, - &ts->server_port); - if (KERN_SUCCESS != ret) { - mach_error("bootstrap_register(): ", ret); - exit(1); - } - } else { /* client mode */ - kern_return_t ret = 0; - mach_port_t bsport; - - ts->request_msg_size -= sizeof(mach_msg_trailer_t); - - ret = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, - &(ts->reply_port)); - if (KERN_SUCCESS != ret) { - mach_error("mach_port_allocate(): ", ret); - exit(1); - } - - ret = task_get_bootstrap_port(mach_task_self(), &bsport); - if (KERN_SUCCESS != ret) { - mach_error("task_get_bootstrap_port(): ", ret); - exit(1); - } - ret = bootstrap_look_up(bsport, (char *)ts->server_port_name, - &(ts->server_port)); - if (KERN_SUCCESS != ret) { - mach_error("bootstrap_look_up(): ", ret); - exit(1); - } - } - - if (ts->verbose) { - if (ts->server_mode) { - printf("Server waiting for IPC messages from client on port '%s'.\n", - ts->server_port_name); - } else { - printf("Client sending %d %s IPC messages to port '%s' in %s mode.\n", - ts->num_msgs, (ts->msg_type == msg_type_inline) ? "inline" : - ((ts->msg_type == msg_type_complex) ? "complex" : "trivial"), - ts->server_port_name, (ts->oneway ? "oneway" : "rpc")); - } - } - - pid = fork(); - switch (pid) { - case 0: - server(tsd); - exit(0); - break; - case -1: - return (-1); - default: - ts->pid = pid; - break; - } - return (0); -} - -int -benchmark_finirun() -{ - (void) fprintf(stderr, "benchmark_finirun\n"); - return (0); -} - -int -benchmark_init() -{ - /* - * the lm_optstr must be defined here or no options for you - * ...and the framework will throw an error - * lm_optstr has two kinds of arguments, boolean (single - * lower case character) and with an argument (single lower - * case character plus a :, indicating the next option is - * the argument) - * - */ - (void) sprintf(lm_optstr, "voc:t:n:p:"); - /* - * tsd_t is the struct that we can pass around our - * state info in - * - * lm_tsdsize will allocate the space we need for this - * structure throughout the rest of the framework - */ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_usage, - " -v\t\tbe verbose\n" - " -o\t\tdo not request return reply (client)\n" - " -c num\t\tnumber of messages to send (client)\n" - " -t trivial|inline|complex\ttype of messages to send (client)\n" - " -n num\tnumber of 32-bit ints to send in messages\n" - "\t\t\t(client's value must be <= the server's)\n" - " -p portname\tname of port on which to communicate\n" - "\t\t\t(client and server must use the same value)\n"); - - opt_verbose = FALSE; - opt_oneway = FALSE; - opt_num_msgs = 10000; - opt_msg_type = msg_type_trivial; - opt_num_ints = 64; - opt_server_port_name = malloc(32); - strcpy(opt_server_port_name, "TEST"); - - return (0); -} - -int -benchmark_fini() -{ - free(opt_server_port_name); - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - kill(ts->pid, SIGKILL); - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - (void) fprintf(stderr, "benchmark_result\n"); - return (&result); -} - -int -benchmark_finiworker(void *tsd) -{ -// tsd_t *ts = (tsd_t *)tsd; - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - (void) fprintf(stderr, "benchmark_optswitch\n"); - - switch (opt) { - case 'v': - opt_verbose = TRUE; - break; - case 'o': - opt_oneway = TRUE; - break; - case 'c': - opt_num_msgs = sizetoint(optarg); - break; - case 't': - if ( 0 == strcmp("trivial", optarg) ) - opt_msg_type = msg_type_trivial; - else if ( 0 == strcmp("inline", optarg) ) - opt_msg_type = msg_type_inline; - else if ( 0 == strcmp("complex", optarg) ) - opt_msg_type = msg_type_complex; - else { - (void) fprintf(stderr, "incorrect argument for message type %s\n", optarg); - return (-1); - } - break; - case 'n': - opt_num_ints = sizetoint(optarg); - break; - case 'p': - strncpy(opt_server_port_name, optarg, 32); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - /* - * initialize your state variables here first - */ -// tsd_t *ts = (tsd_t *)tsd; - return (0); -} - -int -benchmark_initrun() -{ - (void) fprintf(stderr, "benchmark_initrun\n"); - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - /* - * initialize your state variables here last - * - * and realize that you are paying for your initialization here - * and it is really a bad idea - */ -// tsd_t *ts = (tsd_t *)tsd; - int i; - - for (i = 0; i < lm_optB; i++) { - client(tsd); - } - - return (0); -} diff --git a/tools/tests/libMicro/apple/lm_null_call.c b/tools/tests/libMicro/apple/lm_null_call.c deleted file mode 100644 index 825c14c7d..000000000 --- a/tools/tests/libMicro/apple/lm_null_call.c +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -/* - * Order of Execution - * - * benchmark_init - * - * benchmark_optswitch - * - * benchmark_initrun - * - * benchmark_initworker - * benchmark_initbatch - * benchmark - * benchmark_finibatch - * benchmark_initbatch - * benchmark - * benchmark_finibatch, etc. - * benchmark_finiworker - * - * benchmark_result - * - * benchmark_finirun - * - * benchmark_fini - */ - - - -#ifdef __sun -#pragma ident "@(#)socket.c 1.3 05/08/04 Apple Inc." -#endif - - - -#include -#include -#include - -#include "../libmicro.h" - -/* - * Your state variables should live in the tsd_t struct below - */ -typedef struct { - int fd; - char* file; -} tsd_t; - -/*ARGSUSED*/ -int -benchmark_initbatch(void *tsd) -{ - return (0); -} - -int -benchmark_finirun() -{ - return (0); -} - -int -benchmark_init() -{ - /* - * the lm_optstr must be defined here or no options for you - * - * ...and the framework will throw an error - * - */ - (void) sprintf(lm_optstr, "t:"); - /* - * working hypothesis: - * - * tsd_t is the struct that we can pass around our - * state info in - * - * will allocate the space we need for this - * structure throughout the rest of the framework - */ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_usage, - " [-t int (default 1)]\n" - "notes: measures nothing\n"); - return (0); -} - -int -benchmark_fini() -{ - (void) fprintf(stderr, "benchmark_fini\n"); - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - (void) fprintf(stderr, "null_call (getppid)\n"); - return (&result); -} - -int -benchmark_finiworker(void *tsd) -{ - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - /* - * initialize your state variables here first - */ - return (0); -} - -int -benchmark_initrun() -{ - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - /* - * initialize your state variables here last - * - * and realize that you are paying for your initialization here - * and it is really a bad idea - */ - int i; - - for (i = 0; i < lm_optB; i++) { - /* - * just to show that ts really contains state - */ - getppid(); - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/apple/lmbench_bw_file_rd.c b/tools/tests/libMicro/apple/lmbench_bw_file_rd.c deleted file mode 100644 index d5a4f9561..000000000 --- a/tools/tests/libMicro/apple/lmbench_bw_file_rd.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -/* - * Order of Execution - * - * benchmark_init - * - * benchmark_optswitch - * - * benchmark_initrun - * - * benchmark_initworker - * benchmark_initbatch - * benchmark - * benchmark_finibatch - * benchmark_initbatch - * benchmark - * benchmark_finibatch, etc. - * benchmark_finiworker - * - * benchmark_result - * - * benchmark_finirun - * - * benchmark_fini - */ - - - -#ifdef __sun -#pragma ident "@(#)lmbench_bw_file_rd.c 1.0 08/17/06 Apple Inc." -#endif - - - -#include -#include -#include -#include -#include -// add additional headers needed here. -#include - -#include "../libmicro.h" - -#if DEBUG -# define debug(fmt, args...) (void) fprintf(stderr, fmt "\n" , ##args) -#else -# define debug(fmt, args...) -#endif - -/* - * Your state variables should live in the tsd_t struct below - */ -typedef struct { - char filename[256]; - int fd; - int clone; - bool open_read_close; -} tsd_t; - -/* - * You can have any lower-case option you want to define. - * options are specified in the lm_optstr as either a - * single lower-case letter, or a single lower case letter - * with a colon after it. In this example, you can optionally - * specify -c {str} -e or -t {number} - * -c takes a string (quote the string if blanks) - * -e is a boolean - * -t takes a numeric - * argument. - */ -static char optf[256]; -static bool opti = false; // io_only or read and i/o (default read and i/o) - -#define CHK(x) if ((int)(x) == -1) { perror(#x); exit(1); } -#ifndef MIN -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#endif - -#define TYPE int -#define MINSZ (sizeof(TYPE) * 128) - -void *buf; /* do the I/O here */ -size_t xfersize; /* do it in units of this */ -size_t count; /* bytes to move (can't be modified) */ - -/* analogous to bzero, bcopy, etc., except that it just reads - * data into the processor - */ -long -bread(void* buf, long nbytes) -{ - long sum = 0; - register long *p, *next; - register char *end; - - p = (long*)buf; - end = (char*)buf + nbytes; - for (next = p + 128; (void*)next <= (void*)end; p = next, next += 128) { - sum += - p[0]+p[1]+p[2]+p[3]+p[4]+p[5]+p[6]+p[7]+ - p[8]+p[9]+p[10]+p[11]+p[12]+p[13]+p[14]+ - p[15]+p[16]+p[17]+p[18]+p[19]+p[20]+p[21]+ - p[22]+p[23]+p[24]+p[25]+p[26]+p[27]+p[28]+ - p[29]+p[30]+p[31]+p[32]+p[33]+p[34]+p[35]+ - p[36]+p[37]+p[38]+p[39]+p[40]+p[41]+p[42]+ - p[43]+p[44]+p[45]+p[46]+p[47]+p[48]+p[49]+ - p[50]+p[51]+p[52]+p[53]+p[54]+p[55]+p[56]+ - p[57]+p[58]+p[59]+p[60]+p[61]+p[62]+p[63]+ - p[64]+p[65]+p[66]+p[67]+p[68]+p[69]+p[70]+ - p[71]+p[72]+p[73]+p[74]+p[75]+p[76]+p[77]+ - p[78]+p[79]+p[80]+p[81]+p[82]+p[83]+p[84]+ - p[85]+p[86]+p[87]+p[88]+p[89]+p[90]+p[91]+ - p[92]+p[93]+p[94]+p[95]+p[96]+p[97]+p[98]+ - p[99]+p[100]+p[101]+p[102]+p[103]+p[104]+ - p[105]+p[106]+p[107]+p[108]+p[109]+p[110]+ - p[111]+p[112]+p[113]+p[114]+p[115]+p[116]+ - p[117]+p[118]+p[119]+p[120]+p[121]+p[122]+ - p[123]+p[124]+p[125]+p[126]+p[127]; - } - for (next = p + 16; (void*)next <= (void*)end; p = next, next += 16) { - sum += - p[0]+p[1]+p[2]+p[3]+p[4]+p[5]+p[6]+p[7]+ - p[8]+p[9]+p[10]+p[11]+p[12]+p[13]+p[14]+ - p[15]; - } - for (next = p + 1; (void*)next <= (void*)end; p = next, next++) { - sum += *p; - } - return sum; -} - -void doit(int fd) -{ - size_t size, chunk; - - size = count; - chunk = xfersize; - while (size >= 0) { - if (size < chunk) chunk = size; - if (read(fd, buf, MIN(size, chunk)) <= 0) { - break; - } - bread(buf, MIN(size, xfersize)); - size -= chunk; - } -} - - -int -benchmark_init() -{ - debug("benchmark_init"); - /* - * the lm_optstr must be defined here or no options for you - * - * ...and the framework will throw an error - * - */ - (void) sprintf(lm_optstr, "f:i"); - /* - * tsd_t is the state info struct that we pass around - * - * lm_tsdsize will allocate the space we need for this - * structure throughout the rest of the framework - */ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_usage, - " [-f filename]\n" - " [-i] io_only (no open/close)\n" - "notes: read and sum file via read(2) interface"); - sprintf(optf, "/tmp/%d", (int)getpid()); - return (0); -} - -/* - * This is where you parse your lower-case arguments. - * the format was defined in the lm_optstr assignment - * in benchmark_init - */ -int -benchmark_optswitch(int opt, char *optarg) -{ - debug("benchmark_optswitch"); - - switch (opt) { - case 'f': - strncpy(optf, optarg, 255); - debug("optf = %s\n", optf); - break; - case 'i': - opti = true; - debug("opti = %s\n", opte? "true": "false"); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initrun() -{ - debug("benchmark_initrun"); - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - /* - * initialize your state variables here first - */ - tsd_t *ts = (tsd_t *)tsd; - strncpy(ts->filename, optf, 255); - ts->open_read_close = opti; - debug("benchmark_initworker: ts_once = %i\n",ts->ts_once); - return (0); -} - -/*ARGSUSED*/ -int -benchmark_initbatch(void *tsd) -{ - debug("benchmark_initbatch"); - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - /* - * try not to initialize things here. This is the main - * loop of things to get timed. Start a server in - * benchmark_initbatch - */ - tsd_t *ts = (tsd_t *)tsd; - int i; - int fd; - - debug("in to benchmark - optB = %i", lm_optB); - for (i = 0; i < lm_optB; i++) { - if (ts->open_read_close) { - fd = open(ts->filename, O_RDONLY); - doit(fd); - close(fd); - } else { - doit(fd); - } - } - res->re_count = i; - debug("out of benchmark - optB = %i", lm_optB); - - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - debug("benchmark_finibatch"); - return (0); -} - -int -benchmark_finiworker(void *tsd) -{ - debug("benchmark_finiworker"); - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - debug("benchmark_result"); - return (&result); -} - -int -benchmark_finirun() -{ - debug("benchmark_finirun"); - return (0); -} - - -int -benchmark_fini() -{ - debug("benchmark_fini"); - return (0); -} - diff --git a/tools/tests/libMicro/apple/lmbench_bw_mem.c b/tools/tests/libMicro/apple/lmbench_bw_mem.c deleted file mode 100644 index 9963fe637..000000000 --- a/tools/tests/libMicro/apple/lmbench_bw_mem.c +++ /dev/null @@ -1,658 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -/* - * Order of Execution - * - * benchmark_init - * - * benchmark_optswitch - * - * benchmark_initrun - * - * benchmark_initworker - * benchmark_initbatch - * benchmark - * benchmark_finibatch - * benchmark_initbatch - * benchmark - * benchmark_finibatch, etc. - * benchmark_finiworker - * - * benchmark_result - * - * benchmark_finirun - * - * benchmark_fini - */ - -/* - * To port to libmicro, I had to add options for - * some items which were just arguments before. - * -s is the size (more than 512) - * -x is the command to execute (rd wr rdwr cp fwr frd fcp bzero bcopy) - * see usage string for command options. - */ - -#ifdef __sun -#pragma ident "@(#)lmbench_bw_mem.c 1.0 20060814 Apple Inc." -#endif - - -#include -#include -#include -#include -#include - -#include "../libmicro.h" - -#define TRIES 11 // value from bench.h in lmbench -#define TYPE int - -/* Added as part of the fix for */ -static volatile u_int64_t use_result_dummy; -void use_int(int result) { use_result_dummy += result; } - -/* - * rd - 4 byte read, 32 byte stride - * wr - 4 byte write, 32 byte stride - * rdwr - 4 byte read followed by 4 byte write to same place, 32 byte stride - * cp - 4 byte read then 4 byte write to different place, 32 byte stride - * fwr - write every 4 byte word - * frd - read every 4 byte word - * fcp - copy every 4 byte word - * - * All tests do 512 byte chunks in a loop. - * - * XXX - do a 64bit version of this. - */ -void rd(iter_t iterations, void *cookie); -void wr(iter_t iterations, void *cookie); -void rdwr(iter_t iterations, void *cookie); -void mcp(iter_t iterations, void *cookie); -void fwr(iter_t iterations, void *cookie); -void frd(iter_t iterations, void *cookie); -void fcp(iter_t iterations, void *cookie); -void loop_bzero(iter_t iterations, void *cookie); -void loop_bcopy(iter_t iterations, void *cookie); -void init_overhead(iter_t iterations, void *cookie); -void init_loop(iter_t iterations, void *cookie); -void cleanup(iter_t iterations, void *cookie); - -typedef struct _state { - double overhead; - size_t nbytes; - int need_buf2; - int aligned; - TYPE *buf; - TYPE *buf2; - TYPE *buf2_orig; - TYPE *lastone; - size_t N; -} state_t; - - -/* - * Your state variables should live in the tsd_t struct below - */ -typedef struct { - double overhead; - size_t nbytes; - int need_buf2; - int aligned; - TYPE *buf; - TYPE *buf2; - TYPE *buf2_orig; - TYPE *lastone; - size_t N; - int parallel; - int warmup; - int repetitions; -} tsd_t; - - -static int optp = 1; -static int optw = 0; -static int optn = TRIES; -static int opt_size = 0; -static char *opt_what; // maximum "what" command string size - -void -init_overhead(iter_t iterations, void *cookie) -{ -} - -void -init_loop(iter_t iterations, void *cookie) -{ - tsd_t *ts = (tsd_t *)cookie; - - if (iterations) return; - - ts->buf = (TYPE *)valloc(ts->nbytes); - ts->buf2_orig = NULL; - ts->lastone = (TYPE*)ts->buf - 1; - ts->lastone = (TYPE*)((char *)ts->buf + ts->nbytes - 512); - ts->N = ts->nbytes; - - if (!ts->buf) { - perror("malloc"); - exit(1); - } - bzero((void*)ts->buf, ts->nbytes); - - if (ts->need_buf2 == 1) { - ts->buf2_orig = ts->buf2 = (TYPE *)valloc(ts->nbytes + 2048); - if (!ts->buf2) { - perror("malloc"); - exit(1); - } - - /* default is to have stuff unaligned wrt each other */ - /* XXX - this is not well tested or thought out */ - if (ts->aligned) { - char *tmp = (char *)ts->buf2; - - tmp += 2048 - 128; - ts->buf2 = (TYPE *)tmp; - } - } -} - -void -cleanup(iter_t iterations, void *cookie) -{ - tsd_t *ts = (tsd_t *)cookie; - - if (iterations) return; - - free(ts->buf); - if (ts->buf2_orig) free(ts->buf2_orig); -} - -void -rd(iter_t iterations, void *cookie) -{ - tsd_t *ts = (tsd_t *)cookie; - register TYPE *lastone = ts->lastone; - register int sum = 0; - - while (iterations-- > 0) { - register TYPE *p = ts->buf; - while (p <= lastone) { - sum += -#define DOIT(i) p[i]+ - DOIT(0) DOIT(4) DOIT(8) DOIT(12) DOIT(16) DOIT(20) DOIT(24) - DOIT(28) DOIT(32) DOIT(36) DOIT(40) DOIT(44) DOIT(48) DOIT(52) - DOIT(56) DOIT(60) DOIT(64) DOIT(68) DOIT(72) DOIT(76) - DOIT(80) DOIT(84) DOIT(88) DOIT(92) DOIT(96) DOIT(100) - DOIT(104) DOIT(108) DOIT(112) DOIT(116) DOIT(120) - p[124]; - p += 128; - } - } - use_int(sum); -} -#undef DOIT - -void -wr(iter_t iterations, void *cookie) -{ - tsd_t *ts = (tsd_t *)cookie; - register TYPE *lastone = ts->lastone; - - while (iterations-- > 0) { - register TYPE *p = ts->buf; - while (p <= lastone) { -#define DOIT(i) p[i] = 1; - DOIT(0) DOIT(4) DOIT(8) DOIT(12) DOIT(16) DOIT(20) DOIT(24) - DOIT(28) DOIT(32) DOIT(36) DOIT(40) DOIT(44) DOIT(48) DOIT(52) - DOIT(56) DOIT(60) DOIT(64) DOIT(68) DOIT(72) DOIT(76) - DOIT(80) DOIT(84) DOIT(88) DOIT(92) DOIT(96) DOIT(100) - DOIT(104) DOIT(108) DOIT(112) DOIT(116) DOIT(120) DOIT(124); - p += 128; - } - } -} -#undef DOIT - -void -rdwr(iter_t iterations, void *cookie) -{ - tsd_t *ts = (tsd_t *)cookie; - register TYPE *lastone = ts->lastone; - register int sum = 0; - - while (iterations-- > 0) { - register TYPE *p = ts->buf; - while (p <= lastone) { -#define DOIT(i) sum += p[i]; p[i] = 1; - DOIT(0) DOIT(4) DOIT(8) DOIT(12) DOIT(16) DOIT(20) DOIT(24) - DOIT(28) DOIT(32) DOIT(36) DOIT(40) DOIT(44) DOIT(48) DOIT(52) - DOIT(56) DOIT(60) DOIT(64) DOIT(68) DOIT(72) DOIT(76) - DOIT(80) DOIT(84) DOIT(88) DOIT(92) DOIT(96) DOIT(100) - DOIT(104) DOIT(108) DOIT(112) DOIT(116) DOIT(120) DOIT(124); - p += 128; - } - } - use_int(sum); -} -#undef DOIT - -void -mcp(iter_t iterations, void *cookie) -{ - tsd_t *ts = (tsd_t *)cookie; - register TYPE *lastone = ts->lastone; - TYPE* p_save = NULL; - - while (iterations-- > 0) { - register TYPE *p = ts->buf; - register TYPE *dst = ts->buf2; - while (p <= lastone) { -#define DOIT(i) dst[i] = p[i]; - DOIT(0) DOIT(4) DOIT(8) DOIT(12) DOIT(16) DOIT(20) DOIT(24) - DOIT(28) DOIT(32) DOIT(36) DOIT(40) DOIT(44) DOIT(48) DOIT(52) - DOIT(56) DOIT(60) DOIT(64) DOIT(68) DOIT(72) DOIT(76) - DOIT(80) DOIT(84) DOIT(88) DOIT(92) DOIT(96) DOIT(100) - DOIT(104) DOIT(108) DOIT(112) DOIT(116) DOIT(120) DOIT(124); - p += 128; - dst += 128; - } - p_save = p; - } -} -#undef DOIT - -void -fwr(iter_t iterations, void *cookie) -{ - tsd_t *ts = (tsd_t *)cookie; - register TYPE *lastone = ts->lastone; - TYPE* p_save = NULL; - - while (iterations-- > 0) { - register TYPE *p = ts->buf; - while (p <= lastone) { -#define DOIT(i) p[i]= - DOIT(0) DOIT(1) DOIT(2) DOIT(3) DOIT(4) DOIT(5) DOIT(6) - DOIT(7) DOIT(8) DOIT(9) DOIT(10) DOIT(11) DOIT(12) - DOIT(13) DOIT(14) DOIT(15) DOIT(16) DOIT(17) DOIT(18) - DOIT(19) DOIT(20) DOIT(21) DOIT(22) DOIT(23) DOIT(24) - DOIT(25) DOIT(26) DOIT(27) DOIT(28) DOIT(29) DOIT(30) - DOIT(31) DOIT(32) DOIT(33) DOIT(34) DOIT(35) DOIT(36) - DOIT(37) DOIT(38) DOIT(39) DOIT(40) DOIT(41) DOIT(42) - DOIT(43) DOIT(44) DOIT(45) DOIT(46) DOIT(47) DOIT(48) - DOIT(49) DOIT(50) DOIT(51) DOIT(52) DOIT(53) DOIT(54) - DOIT(55) DOIT(56) DOIT(57) DOIT(58) DOIT(59) DOIT(60) - DOIT(61) DOIT(62) DOIT(63) DOIT(64) DOIT(65) DOIT(66) - DOIT(67) DOIT(68) DOIT(69) DOIT(70) DOIT(71) DOIT(72) - DOIT(73) DOIT(74) DOIT(75) DOIT(76) DOIT(77) DOIT(78) - DOIT(79) DOIT(80) DOIT(81) DOIT(82) DOIT(83) DOIT(84) - DOIT(85) DOIT(86) DOIT(87) DOIT(88) DOIT(89) DOIT(90) - DOIT(91) DOIT(92) DOIT(93) DOIT(94) DOIT(95) DOIT(96) - DOIT(97) DOIT(98) DOIT(99) DOIT(100) DOIT(101) DOIT(102) - DOIT(103) DOIT(104) DOIT(105) DOIT(106) DOIT(107) - DOIT(108) DOIT(109) DOIT(110) DOIT(111) DOIT(112) - DOIT(113) DOIT(114) DOIT(115) DOIT(116) DOIT(117) - DOIT(118) DOIT(119) DOIT(120) DOIT(121) DOIT(122) - DOIT(123) DOIT(124) DOIT(125) DOIT(126) DOIT(127) 1; - p += 128; - } - p_save = p; - } -} -#undef DOIT - -void -frd(iter_t iterations, void *cookie) -{ - tsd_t *ts = (tsd_t *)cookie; - register int sum = 0; - register TYPE *lastone = ts->lastone; - - while (iterations-- > 0) { - register TYPE *p = ts->buf; - while (p <= lastone) { - sum += -#define DOIT(i) p[i]+ - DOIT(0) DOIT(1) DOIT(2) DOIT(3) DOIT(4) DOIT(5) DOIT(6) - DOIT(7) DOIT(8) DOIT(9) DOIT(10) DOIT(11) DOIT(12) - DOIT(13) DOIT(14) DOIT(15) DOIT(16) DOIT(17) DOIT(18) - DOIT(19) DOIT(20) DOIT(21) DOIT(22) DOIT(23) DOIT(24) - DOIT(25) DOIT(26) DOIT(27) DOIT(28) DOIT(29) DOIT(30) - DOIT(31) DOIT(32) DOIT(33) DOIT(34) DOIT(35) DOIT(36) - DOIT(37) DOIT(38) DOIT(39) DOIT(40) DOIT(41) DOIT(42) - DOIT(43) DOIT(44) DOIT(45) DOIT(46) DOIT(47) DOIT(48) - DOIT(49) DOIT(50) DOIT(51) DOIT(52) DOIT(53) DOIT(54) - DOIT(55) DOIT(56) DOIT(57) DOIT(58) DOIT(59) DOIT(60) - DOIT(61) DOIT(62) DOIT(63) DOIT(64) DOIT(65) DOIT(66) - DOIT(67) DOIT(68) DOIT(69) DOIT(70) DOIT(71) DOIT(72) - DOIT(73) DOIT(74) DOIT(75) DOIT(76) DOIT(77) DOIT(78) - DOIT(79) DOIT(80) DOIT(81) DOIT(82) DOIT(83) DOIT(84) - DOIT(85) DOIT(86) DOIT(87) DOIT(88) DOIT(89) DOIT(90) - DOIT(91) DOIT(92) DOIT(93) DOIT(94) DOIT(95) DOIT(96) - DOIT(97) DOIT(98) DOIT(99) DOIT(100) DOIT(101) DOIT(102) - DOIT(103) DOIT(104) DOIT(105) DOIT(106) DOIT(107) - DOIT(108) DOIT(109) DOIT(110) DOIT(111) DOIT(112) - DOIT(113) DOIT(114) DOIT(115) DOIT(116) DOIT(117) - DOIT(118) DOIT(119) DOIT(120) DOIT(121) DOIT(122) - DOIT(123) DOIT(124) DOIT(125) DOIT(126) p[127]; - p += 128; - } - } - use_int(sum); -} -#undef DOIT - -void -fcp(iter_t iterations, void *cookie) -{ - tsd_t *ts = (tsd_t *)cookie; - register TYPE *lastone = ts->lastone; - - while (iterations-- > 0) { - register TYPE *p = ts->buf; - register TYPE *dst = ts->buf2; - while (p <= lastone) { -#define DOIT(i) dst[i]=p[i]; - DOIT(0) DOIT(1) DOIT(2) DOIT(3) DOIT(4) DOIT(5) DOIT(6) - DOIT(7) DOIT(8) DOIT(9) DOIT(10) DOIT(11) DOIT(12) - DOIT(13) DOIT(14) DOIT(15) DOIT(16) DOIT(17) DOIT(18) - DOIT(19) DOIT(20) DOIT(21) DOIT(22) DOIT(23) DOIT(24) - DOIT(25) DOIT(26) DOIT(27) DOIT(28) DOIT(29) DOIT(30) - DOIT(31) DOIT(32) DOIT(33) DOIT(34) DOIT(35) DOIT(36) - DOIT(37) DOIT(38) DOIT(39) DOIT(40) DOIT(41) DOIT(42) - DOIT(43) DOIT(44) DOIT(45) DOIT(46) DOIT(47) DOIT(48) - DOIT(49) DOIT(50) DOIT(51) DOIT(52) DOIT(53) DOIT(54) - DOIT(55) DOIT(56) DOIT(57) DOIT(58) DOIT(59) DOIT(60) - DOIT(61) DOIT(62) DOIT(63) DOIT(64) DOIT(65) DOIT(66) - DOIT(67) DOIT(68) DOIT(69) DOIT(70) DOIT(71) DOIT(72) - DOIT(73) DOIT(74) DOIT(75) DOIT(76) DOIT(77) DOIT(78) - DOIT(79) DOIT(80) DOIT(81) DOIT(82) DOIT(83) DOIT(84) - DOIT(85) DOIT(86) DOIT(87) DOIT(88) DOIT(89) DOIT(90) - DOIT(91) DOIT(92) DOIT(93) DOIT(94) DOIT(95) DOIT(96) - DOIT(97) DOIT(98) DOIT(99) DOIT(100) DOIT(101) DOIT(102) - DOIT(103) DOIT(104) DOIT(105) DOIT(106) DOIT(107) - DOIT(108) DOIT(109) DOIT(110) DOIT(111) DOIT(112) - DOIT(113) DOIT(114) DOIT(115) DOIT(116) DOIT(117) - DOIT(118) DOIT(119) DOIT(120) DOIT(121) DOIT(122) - DOIT(123) DOIT(124) DOIT(125) DOIT(126) DOIT(127) - p += 128; - dst += 128; - } - } -} - -void -loop_bzero(iter_t iterations, void *cookie) -{ - tsd_t *ts = (tsd_t *)cookie; - register TYPE *p = ts->buf; - register size_t N = ts->N; - - while (iterations-- > 0) { - bzero(p, N); - } -} - -void -loop_bcopy(iter_t iterations, void *cookie) -{ - tsd_t *ts = (tsd_t *)cookie; - register TYPE *p = ts->buf; - register TYPE *dst = ts->buf2; - register size_t N = ts->N; - - while (iterations-- > 0) { - bcopy(p,dst,N); - } -} - -#pragma mark libmicro routines - -/*ARGSUSED*/ -int -benchmark_initbatch(void *tsd) -{ - /* - * initialize your state variables here second - */ - tsd_t *ts = (tsd_t *)tsd; - ts->buf = (TYPE *)valloc(ts->nbytes); - ts->buf2_orig = NULL; - ts->lastone = (TYPE*)ts->buf - 1; - ts->lastone = (TYPE*)((char *)ts->buf + ts->nbytes - 512); - ts->N = ts->nbytes; - - if (!ts->buf) { - perror("malloc"); - exit(1); - } - bzero((void*)ts->buf, ts->nbytes); - - if (ts->need_buf2 == 1) { - ts->buf2_orig = ts->buf2 = (TYPE *)valloc(ts->nbytes + 2048); - if (!ts->buf2) { - perror("malloc"); - exit(1); - } - - /* default is to have stuff unaligned wrt each other */ - /* XXX - this is not well tested or thought out */ - if (ts->aligned) { - char *tmp = (char *)ts->buf2; - - tmp += 2048 - 128; - ts->buf2 = (TYPE *)tmp; - } - } - return (0); -} - -int -benchmark_finirun() -{ - return (0); -} - -int -benchmark_init() -{ - /* - * the lm_optstr must be defined here or no options for you - * - * ...and the framework will throw an error - * - */ - (void) sprintf(lm_optstr, "p:w:n:s:x:"); - /* - * working hypothesis: - * - * tsd_t is the struct that we can pass around our - * state info in - * - * lm_tsdsize will allocate the space we need for this - * structure throughout the rest of the framework - */ - lm_tsdsize = sizeof (tsd_t); - opt_what = (char *)malloc(30); - - (void) sprintf(lm_usage, - " [-p ]\n" - " [-w ]\n" - " [-n ]\n" - " -s \n" - " must be larger than 512" - " -x what\n" - " what: rd wr rdwr cp fwr frd fcp bzero bcopy\n" - " [conflict] -- unknown option?\n" - ); - return (0); -} - -int -benchmark_fini() -{ - free(opt_what); - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - return (&result); -} - -int -benchmark_finiworker(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - free(ts->buf); - if (ts->buf2_orig) free(ts->buf2_orig); - return (0); -} - -/* return -1 to display usage (i.e. if can't parse arguments */ -int -benchmark_optswitch(int opt, char *optarg) -{ - - switch (opt) { - case 'p': - optp = sizetoint(optarg); - if (optp <= 0) - return (-1); - break; - case 'w': - optw = sizetoint(optarg); - break; - case 'n': - optn = sizetoint(optarg); - break; - case 's': - opt_size = sizetoint(optarg); - break; - case 'x': - strcpy(opt_what, optarg); - break; - default: - return(-1); - break; - } -// (void) fprintf(stderr, "optp = %i optw = %i optn = %i opt_size = %i\n", -// optp, optw, optn, opt_size); -// (void) fprintf(stderr, "opt_what = %s\n", opt_what); - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - /* - * initialize your state variables here first - */ - tsd_t *ts = (tsd_t *)tsd; - ts->parallel = optp; - ts->warmup = optw; - ts->repetitions = optn; - return (0); -} - -int -benchmark_initrun() -{ - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - /* - * initialize your state variables here last - * - * and realize that you are paying for your initialization here - * and it is really a bad idea - */ - tsd_t *ts = (tsd_t *)tsd; - size_t nbytes; - int i; - - ts->overhead = 0; - - - /* should have two, possibly three [indicates align] arguments left */ - ts->aligned = ts->need_buf2 = 0; - - nbytes = ts->nbytes = opt_size; - if (ts->nbytes < 512) { /* this is the number of bytes in the loop */ - return(-1); - } - - if (STREQ(opt_what, "cp") || - STREQ(opt_what, "fcp") || STREQ(opt_what, "bcopy")) { - ts->need_buf2 = 1; - } - - for (i = 0 ; i < lm_optB ; i++) - { - if (STREQ(opt_what, "rd")) { - rd( ts->repetitions, tsd ); - } else if (STREQ(opt_what, "wr")) { - wr( ts->repetitions, tsd ); - } else if (STREQ(opt_what, "rdwr")) { - rdwr( ts->repetitions, tsd ); - } else if (STREQ(opt_what, "cp")) { - mcp( ts->repetitions, tsd ); - } else if (STREQ(opt_what, "frd")) { - frd( ts->repetitions, tsd ); - } else if (STREQ(opt_what, "fwr")) { - fwr( ts->repetitions, tsd ); - } else if (STREQ(opt_what, "fcp")) { - fcp( ts->repetitions, tsd ); - } else if (STREQ(opt_what, "bzero")) { - loop_bzero( ts->repetitions, tsd ); - } else if (STREQ(opt_what, "bcopy")) { - loop_bcopy( ts->repetitions, tsd ); - } else { - return(-1); - } - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/apple/lmbench_bw_mmap_rd.c b/tools/tests/libMicro/apple/lmbench_bw_mmap_rd.c deleted file mode 100644 index 656bbb114..000000000 --- a/tools/tests/libMicro/apple/lmbench_bw_mmap_rd.c +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -/* - * Order of Execution - * - * benchmark_init - * - * benchmark_optswitch - * - * benchmark_initrun - * - * benchmark_initworker - * benchmark_initbatch - * benchmark - * benchmark_finibatch - * benchmark_initbatch - * benchmark - * benchmark_finibatch, etc. - * benchmark_finiworker - * - * benchmark_result - * - * benchmark_finirun - * - * benchmark_fini - */ - - - -#ifdef __sun -#pragma ident "@(#)lmbench_bw_mmap_rd.c 1.0 08/17/06 Apple Inc." -#endif - - - -#include -#include -#include -#include -#include -// add additional headers needed here. -#include -#include -#include - -#include "../libmicro.h" - -#if DEBUG -# define debug(fmt, args...) (void) fprintf(stderr, fmt "\n" , ##args) -#else -# define debug(fmt, args...) -#endif - -/* - * Your state variables should live in the tsd_t struct below - */ -typedef struct { - size_t nbytes; - char filename[_POSIX_PATH_MAX]; - int fd; - int clone; - void *buf; - bool open_read_close; -} tsd_t; - -/* - * You can have any lower-case option you want to define. - * options are specified in the lm_optstr as either a - * single lower-case letter, or a single lower case letter - * with a colon after it. In this example, you can optionally - * specify -c {str} -e or -t {number} - * -c takes a string (quote the string if blanks) - * -e is a boolean - * -t takes a numeric - * argument. - */ -static char optf[_POSIX_PATH_MAX]; -static int opts = 1024; -static bool opti = false; // io_only or read and i/o (default read and i/o) - -#ifdef MAP_FILE -# define MMAP_FLAGS MAP_FILE|MAP_SHARED -#else -# define MMAP_FLAGS MAP_SHARED -#endif - -#define CHK(x) if ((int)(x) == -1) { perror(#x); exit(1); } -#ifndef MIN -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#endif - -#define TYPE int -#define MINSZ (sizeof(TYPE) * 128) - -void *buf; /* do the I/O here */ -size_t xfersize; /* do it in units of this */ -size_t count; /* bytes to move (can't be modified) */ - -/* analogous to bzero, bcopy, etc., except that it just reads - * data into the processor - */ -long -bread(void* buf, long nbytes) -{ - long sum = 0; - register long *p, *next; - register char *end; - - p = (long*)buf; - end = (char*)buf + nbytes; - for (next = p + 128; (void*)next <= (void*)end; p = next, next += 128) { - sum += - p[0]+p[1]+p[2]+p[3]+p[4]+p[5]+p[6]+p[7]+ - p[8]+p[9]+p[10]+p[11]+p[12]+p[13]+p[14]+ - p[15]+p[16]+p[17]+p[18]+p[19]+p[20]+p[21]+ - p[22]+p[23]+p[24]+p[25]+p[26]+p[27]+p[28]+ - p[29]+p[30]+p[31]+p[32]+p[33]+p[34]+p[35]+ - p[36]+p[37]+p[38]+p[39]+p[40]+p[41]+p[42]+ - p[43]+p[44]+p[45]+p[46]+p[47]+p[48]+p[49]+ - p[50]+p[51]+p[52]+p[53]+p[54]+p[55]+p[56]+ - p[57]+p[58]+p[59]+p[60]+p[61]+p[62]+p[63]+ - p[64]+p[65]+p[66]+p[67]+p[68]+p[69]+p[70]+ - p[71]+p[72]+p[73]+p[74]+p[75]+p[76]+p[77]+ - p[78]+p[79]+p[80]+p[81]+p[82]+p[83]+p[84]+ - p[85]+p[86]+p[87]+p[88]+p[89]+p[90]+p[91]+ - p[92]+p[93]+p[94]+p[95]+p[96]+p[97]+p[98]+ - p[99]+p[100]+p[101]+p[102]+p[103]+p[104]+ - p[105]+p[106]+p[107]+p[108]+p[109]+p[110]+ - p[111]+p[112]+p[113]+p[114]+p[115]+p[116]+ - p[117]+p[118]+p[119]+p[120]+p[121]+p[122]+ - p[123]+p[124]+p[125]+p[126]+p[127]; - } - for (next = p + 16; (void*)next <= (void*)end; p = next, next += 16) { - sum += - p[0]+p[1]+p[2]+p[3]+p[4]+p[5]+p[6]+p[7]+ - p[8]+p[9]+p[10]+p[11]+p[12]+p[13]+p[14]+ - p[15]; - } - for (next = p + 1; (void*)next <= (void*)end; p = next, next++) { - sum += *p; - } - return sum; -} - -int -cp(char* src, char* dst, mode_t mode) -{ - int sfd, dfd; - char buf[8192]; - ssize_t size; - - if ((sfd = open(src, O_RDONLY)) < 0) { - return -1; - } - if ((dfd = open(dst, O_CREAT|O_TRUNC|O_RDWR, mode)) < 0) { - return -1; - } - while ((size = read(sfd, buf, 8192)) > 0) { - if (write(dfd, buf, size) < size) return -1; - } - fsync(dfd); - close(sfd); - close(dfd); - return 0; -} - - -int -benchmark_init() -{ - debug("benchmark_init"); - /* - * the lm_optstr must be defined here or no options for you - * - * ...and the framework will throw an error - * - */ - (void) sprintf(lm_optstr, "f:is:"); - /* - * tsd_t is the state info struct that we pass around - * - * lm_tsdsize will allocate the space we need for this - * structure throughout the rest of the framework - */ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_usage, - " -f filename\n" - " -s size\n" - " [-i] io_only (no open/close)\n" - "notes: read and sum file via memory mapping mmap(2) interface"); - sprintf(optf, "/tmp/%d", (int)getpid()); - opts = 1024; - return (0); -} - -/* - * This is where you parse your lower-case arguments. - * the format was defined in the lm_optstr assignment - * in benchmark_init - */ -int -benchmark_optswitch(int opt, char *optarg) -{ - debug("benchmark_optswitch"); - - switch (opt) { - case 'f': - strncpy(optf, optarg, 255); - debug("optf = %s\n", optf); - break; - case 'i': - opti = true; - debug("opti = %s\n", opti? "true": "false"); - break; - case 's': - opts = sizetoint(optarg); - debug("opts = %d\n", opts); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initrun() -{ - debug("benchmark_initrun"); - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - /* - * initialize your state variables here first - */ - tsd_t *state = (tsd_t *)tsd; - - strncpy(state->filename, optf, 255); - state->nbytes = opts; - state->open_read_close = opti; - - debug("benchmark_initworker\n"); - return (0); -} - -/*ARGSUSED*/ -int -benchmark_initbatch(void *tsd) -{ - tsd_t *state = (tsd_t *)tsd; - state->fd = -1; - state->buf = NULL; - - if (state->clone) { - char buf[8192]; - char* s; - - /* copy original file into a process-specific one */ - sprintf(buf, "/tmp/%d", (int)getpid()); - s = (char*)malloc(strlen(state->filename) + strlen(buf) + 1); - sprintf(s, "/tmp/%s%d", state->filename, (int)getpid()); - if (cp(state->filename, s, S_IREAD|S_IWRITE) < 0) { - perror("creating private tempfile"); - unlink(s); - exit(1); - } - strcpy(state->filename, s); - } - - CHK(state->fd = open(state->filename, 0)); - CHK(state->buf = mmap(0, state->nbytes, PROT_READ, - MMAP_FLAGS, state->fd, 0)); - debug("benchmark_initbatch"); - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - /* - * try not to initialize things here. This is the main - * loop of things to get timed. Start a server in - * benchmark_initbatch - */ - tsd_t *state = (tsd_t *)tsd; - int i; - int fd; - void *p; - - debug("in to benchmark - optB = %i", lm_optB); - for (i = 0; i < lm_optB; i++) { - if (state->open_read_close) { - CHK(fd = open(state->filename, 0)); - CHK(p = mmap(0, state->nbytes, PROT_READ, MMAP_FLAGS, fd, 0)); - bread(p, state->nbytes); - close(fd); - munmap(p, state->nbytes); - } else { - bread(state->buf, state->nbytes); - } - } - res->re_count = i; - debug("out of benchmark - optB = %i", lm_optB); - - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - tsd_t *state = (tsd_t *)tsd; - if (state->buf) munmap(state->buf, state->nbytes); - if (state->fd >= 0) close(state->fd); - if (state->clone) unlink(state->filename); - debug("benchmark_finibatch"); - return (0); -} - -int -benchmark_finiworker(void *tsd) -{ - debug("benchmark_finiworker"); - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - debug("benchmark_result"); - return (&result); -} - -int -benchmark_finirun() -{ - debug("benchmark_finirun"); - return (0); -} - - -int -benchmark_fini() -{ - debug("benchmark_fini"); - return (0); -} - diff --git a/tools/tests/libMicro/apple/lmbench_bw_unix.c b/tools/tests/libMicro/apple/lmbench_bw_unix.c deleted file mode 100644 index 9c86510e8..000000000 --- a/tools/tests/libMicro/apple/lmbench_bw_unix.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -/* - * Order of Execution - * - * benchmark_init - * - * benchmark_optswitch - * - * benchmark_initrun - * - * benchmark_initworker - * benchmark_initbatch - * benchmark - * benchmark_finibatch - * benchmark_initbatch - * benchmark - * benchmark_finibatch, etc. - * benchmark_finiworker - * - * benchmark_result - * - * benchmark_finirun - * - * benchmark_fini - */ - - - -#ifdef __sun -#pragma ident "@(#)trivial.c 1.0 08/17/06 Apple Inc." -#endif - - - -#include -#include -#include -#include -#include -// add additional headers needed here. -#include -#include - -#include "../libmicro.h" - -void writer(int controlfd, int writefd, char* buf, void* cookie); -void touch(char *buf, int nbytes); - -#if DEBUG -# define debug(fmt, args...) (void) fprintf(stderr, fmt "\n" , ##args) -#else -# define debug(fmt, args...) -#endif - -/* - * Your state variables should live in the tsd_t struct below - */ -typedef struct { - int pid; - size_t xfer; /* bytes to read/write per "packet" */ - size_t bytes; /* bytes to read/write in one iteration */ - char *buf; /* buffer memory space */ - int pipes[2]; - int control[2]; - int initerr; - int parallel; - int warmup; - int repetitions; -} tsd_t; - -size_t XFER = 10*1024*1024; -#ifndef XFERSIZE -#define XFERSIZE (64*1024) /* all bandwidth I/O should use this */ -#endif - -/* - * You can have any lower-case option you want to define. - * options are specified in the lm_optstr as either a - * single lower-case letter, or a single lower case letter - * with a colon after it. In this example, you can optionally - * specify -c {str} -e or -t {number} - * -c takes a string (quote the string if blanks) - * -e is a boolean - * -t takes a numeric - * argument. - */ -static int optm = XFERSIZE; -static int opts = 10*1024*1024; -static int optw = 0; - -int -benchmark_init() -{ - debug("benchmark_init\n"); - /* - * the lm_optstr must be defined here or no options for you - * - * ...and the framework will throw an error - * - */ - (void) sprintf(lm_optstr, "m:s:w:"); - /* - * - * tsd_t is the state_information struct - * - * lm_tsdsize will allocate the space we need for this - * structure throughout the rest of the framework - */ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_usage, - " [-m ]\n" - " [-s ]\n" - " [-w ]\n"); - - return (0); -} - -/* - * This is where you parse your lower-case arguments. - * the format was defined in the lm_optstr assignment - * in benchmark_init - */ -int -benchmark_optswitch(int opt, char *optarg) -{ - debug("benchmark_optswitch\n"); - - switch (opt) { - case 'm': - optm = atoi(optarg); - break; - case 's': - opts = atoi(optarg); - break; - case 'w': - optw = atoi(optarg); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initrun() -{ - debug("benchmark_initrun\n"); - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - /* - * initialize your state variables here first - */ - tsd_t *state = (tsd_t *)tsd; - state->xfer = optm; - state->bytes = opts; - state->parallel = lm_optP; - state->warmup = optw; - state->repetitions = lm_optB; - debug("benchmark_initworker: repetitions = %i\n",state->repetitions); - return (0); -} - -/*ARGSUSED*/ -int -benchmark_initbatch(void *tsd) -{ - tsd_t *state = (tsd_t *)tsd; - - state->buf = valloc(XFERSIZE); - touch(state->buf, XFERSIZE); - state->initerr = 0; - if (socketpair(AF_UNIX, SOCK_STREAM, 0, state->pipes) == -1) { - perror("socketpair"); - state->initerr = 1; - return(0); - } - if (pipe(state->control) == -1) { - perror("pipe"); - state->initerr = 2; - return(0); - } -// handle_scheduler(benchmp_childid(), 0, 1); - switch (state->pid = fork()) { - case 0: -// handle_scheduler(benchmp_childid(), 1, 1); - close(state->control[1]); - close(state->pipes[0]); - writer(state->control[0], state->pipes[1], state->buf, state); - return (0); - /*NOTREACHED*/ - - case -1: - perror("fork"); - state->initerr = 3; - return (0); - /*NOTREACHED*/ - - default: - break; - } - close(state->control[0]); - close(state->pipes[1]); - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - /* - * try not to initialize things here. This is the main - * loop of things to get timed. Start a server in - * benchmark_initbatch - */ - tsd_t *state = (tsd_t *)tsd; - size_t done, n; - size_t todo = state->bytes; - int i; - - debug("in to benchmark - optB = %i : repetitions = %i\n", lm_optB, state->repetitions); - for (i = 0; i < lm_optB; i++) { - write(state->control[1], &todo, sizeof(todo)); - for (done = 0; done < todo; done += n) { - if ((n = read(state->pipes[0], state->buf, state->xfer)) <= 0) { - /* error! */ - debug("error (n = %d) exiting now\n", n); - exit(1); - } - } - } - res->re_count = i; - debug("out of benchmark - optB = %i : repetitions = %i\n", lm_optB, state->repetitions); - - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - tsd_t *state = (tsd_t *)tsd; - - close(state->control[1]); - close(state->pipes[0]); - if (state->pid > 0) { - kill(state->pid, SIGKILL); - waitpid(state->pid, NULL, 0); - } - state->pid = 0; - return (0); -} - -int -benchmark_finiworker(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - // useless code to show what you can do. - ts->repetitions++; - ts->repetitions--; - debug("benchmark_finiworker: repetitions = %i\n",ts->repetitions); - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - debug("benchmark_result\n"); - return (&result); -} - -int -benchmark_finirun() -{ - debug("benchmark_finirun\n"); - return (0); -} - - -int -benchmark_fini() -{ - debug("benchmark_fini\n"); - return (0); -} - -/* - * functions from bw_unix.c - */ -void -writer(int controlfd, int writefd, char* buf, void* cookie) -{ - size_t todo, n, done; - tsd_t *state = (tsd_t *)cookie; - - for ( ;; ) { - read(controlfd, &todo, sizeof(todo)); - for (done = 0; done < todo; done += n) { -#ifdef TOUCH - touch(buf, XFERSIZE); -#endif - if ((n = write(writefd, buf, state->xfer)) < 0) { - /* error! */ - exit(1); - } - } - } -} - -void -touch(char *buf, int nbytes) -{ - static int psize; - - if (!psize) { - psize = getpagesize(); - } - while (nbytes > 0) { - *buf = 1; - buf += psize; - nbytes -= psize; - } -} - diff --git a/tools/tests/libMicro/apple/lmbench_fstat.c b/tools/tests/libMicro/apple/lmbench_fstat.c deleted file mode 100644 index f417005e5..000000000 --- a/tools/tests/libMicro/apple/lmbench_fstat.c +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -#ifdef __sun -#pragma ident "@(#)lmbench_fstat.c 1.4 06/21/06 Apple Inc." -#endif - - -#include -#include -#include -#include -#include -#include - -#include "../libmicro.h" - -typedef struct { - char *ts_buf; - int ts_fd; -} tsd_t; - - -#define DEFF "/dev/null" -#define DEFS 1024 - -static char *optf = DEFF; -// static long long opts = DEFS; - -int -benchmark_init() -{ - - (void) sprintf(lm_optstr, "f:"); - - lm_tsdsize = 0; - - (void) sprintf(lm_usage, - " [-f file-to-stat (default %s)]\n" - "notes: measures lmbench_fstat()\n", - DEFF); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'f': - optf = optarg; - break; - default: - return (-1); - } - return (0); -} - -/* - * This initbatch stolen from lmbench_read.c - */ -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - - if (ts->ts_buf == NULL) { - /* ts->ts_buf = malloc(opts); */ - ts->ts_fd = open(optf, O_RDONLY); - } - - /* (void) lseek(ts->ts_fd, 0, SEEK_SET); */ - - return (0); -} - - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - struct stat sbuf; - tsd_t *ts = (tsd_t *)tsd; - - res->re_errors = 0; - -/* - * The libmicro test uses a for loop as below: - * for (i = 0; i < lm_optB; i++) { - * - * we can probably get away with using lm_optB - * in the while loop below - * - */ - i = 0; - -// while (i++ < lm_optB) { - for (i = 0; i < lm_optB; i++) { - if (fstat(ts->ts_fd, &sbuf) == -1) - res->re_errors++; - } - - res->re_count += lm_optB; - - return (0); -} diff --git a/tools/tests/libMicro/apple/lmbench_lat_ctx.c b/tools/tests/libMicro/apple/lmbench_lat_ctx.c deleted file mode 100644 index 2cbe790c2..000000000 --- a/tools/tests/libMicro/apple/lmbench_lat_ctx.c +++ /dev/null @@ -1,634 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -/* - * Order of Execution - * - * benchmark_init - * - * benchmark_optswitch - * - * benchmark_initrun - * - * benchmark_initworker - * benchmark_initbatch - * benchmark - * benchmark_finibatch - * benchmark_initbatch - * benchmark - * benchmark_finibatch, etc. - * benchmark_finiworker - * - * benchmark_result - * - * benchmark_finirun - * - * benchmark_fini - */ - - - -#ifdef __sun -#pragma ident "@(#)trivial.c 1.0 08/17/06 Apple Inc." -#endif - - - -#include -#include -#include - -#include -#include - -#include -#include "../libmicro.h" - -#if 1 -# define debug(fmt, args...) (void) fprintf(stderr, fmt "\n" , ##args) -#else -# define debug(fmt, args...) -#endif - - -#define MAXPROC 2048 -#define CHUNK (4<<10) -#define TRIPS 5 -#ifndef max -#define max(a, b) ((a) > (b) ? (a) : (b)) -#endif - - -/* - * Your state variables should live in the tsd_t struct below - */ -typedef struct { - int process_size; - double overhead; - int procs; - pid_t* pids; - int **p; - void* data; -} tsd_t; - -static int opts = 1; - -void doit(int rd, int wr, int process_size); -int create_pipes(int **p, int procs); -int create_daemons(int **p, pid_t *pids, int procs, int process_size); -void initialize_overhead(void* tsd); -void cleanup_overhead(void* tsd); -void benchmark_overhead(void* tsd); -void initialize(void* tsd); -void cleanup(void* tsd); -long bread(void* buf, long nbytes); - - -#pragma mark *** lmbench routines - -/* - * lmbench routines, etc. brought over for this benchmark - */ - -void -morefds(void) -{ -#ifdef RLIMIT_NOFILE - struct rlimit r; - - getrlimit(RLIMIT_NOFILE, &r); - r.rlim_cur = r.rlim_max; - setrlimit(RLIMIT_NOFILE, &r); -#endif -} - -void -doit(int rd, int wr, int process_size) -{ - int msg; - void* data = NULL; - - if (process_size) { - data = malloc(process_size); - if (data) bzero(data, process_size); - } - for ( ;; ) { - if (read(rd, &msg, sizeof(msg)) != sizeof(msg)) { - debug("read/write on pipe"); - break; - } - bread(data, process_size); - if (write(wr, &msg, sizeof(msg)) != sizeof(msg)) { - debug("read/write on pipe"); - break; - } - } - exit(0); -} - -/* - * Return the number of processors in this host - */ -int -sched_ncpus() -{ -#ifdef MP_NPROCS - /* SGI IRIX interface */ - return sysmp(MP_NPROCS); -#elif defined(HAVE_MPCTL) - /* HP-UX interface */ - return mpctl(MPC_GETNUMSPUS_SYS, 0, 0); -#elif defined(_SC_NPROCESSORS_ONLN) - /* AIX, Solaris, and Linux interface */ - return sysconf(_SC_NPROCESSORS_ONLN); -#elif __APPLE__ - char *name="hw.activecpu"; - int cpus, retval; - size_t len = 4; - retval=sysctlbyname(name, &cpus, &len, NULL, 0); - /* Check retval here */ - debug("cpus = %d retval = %d", cpus, retval); - return cpus; -#endif - return 1; -} - -/* - * Use to get sequentially created processes "far" away from - * each other in an SMP. - * - * XXX: probably doesn't work for NCPUS not a power of two. - */ -int -reverse_bits(int cpu) -{ - int i; - int nbits; - int max = sched_ncpus() - 1; - int cpu_reverse = 0; - - for (i = max>>1, nbits = 1; i > 0; i >>= 1, nbits++) - ; - /* now reverse the bits */ - for (i = 0; i < nbits; i++) { - if (cpu & (1<pids = NULL; - pState->p = (int**)malloc(pState->procs * (sizeof(int*) + 2 * sizeof(int))); - p = (int*)&pState->p[pState->procs]; - for (i = 0; i < pState->procs; ++i) { - pState->p[i] = p; - p += 2; - } - - pState->data = (pState->process_size > 0) ? malloc(pState->process_size) : NULL; - if (pState->data) - bzero(pState->data, pState->process_size); - - procs = create_pipes(pState->p, pState->procs); - if (procs < pState->procs) { - debug("procs < pState->procs"); - cleanup_overhead(cookie); - exit(1); - } -} - -void -cleanup_overhead(void* tsd) -{ - int i; - tsd_t *ts = (tsd_t *)tsd; - - for (i = 0; i < ts->procs; ++i) { - close(ts->p[i][0]); - close(ts->p[i][1]); - } - - free(ts->p); - if (ts->data) free(ts->data); -} - -void -cleanup(void* cookie) -{ - int i; - tsd_t *pState = (tsd_t *)cookie; - - - /* - * Close the pipes and kill the children. - */ - cleanup_overhead(cookie); - for (i = 1; pState->pids && i < pState->procs; ++i) { - if (pState->pids[i] > 0) { - kill(pState->pids[i], SIGKILL); - waitpid(pState->pids[i], NULL, 0); - } - } - if (pState->pids) - free(pState->pids); - pState->pids = NULL; -} - -void -benchmark_overhead(void* tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i = 0; - int msg = 1; - - for (i = 0; i < lm_optB; i++) { - if (write(ts->p[i][1], &msg, sizeof(msg)) != sizeof(msg)) { - debug("read/write on pipe"); - exit(1); - } - if (read(ts->p[i][0], &msg, sizeof(msg)) != sizeof(msg)) { - debug("read/write on pipe"); - exit(1); - } - if (++i == ts->procs) { - i = 0; - } - bread(ts->data, ts->process_size); - } -} - -/* analogous to bzero, bcopy, etc., except that it just reads - * data into the processor - */ -long -bread(void* buf, long nbytes) -{ - long sum = 0; - register long *p, *next; - register char *end; - - p = (long*)buf; - end = (char*)buf + nbytes; - for (next = p + 128; (void*)next <= (void*)end; p = next, next += 128) { - sum += - p[0]+p[1]+p[2]+p[3]+p[4]+p[5]+p[6]+p[7]+ - p[8]+p[9]+p[10]+p[11]+p[12]+p[13]+p[14]+ - p[15]+p[16]+p[17]+p[18]+p[19]+p[20]+p[21]+ - p[22]+p[23]+p[24]+p[25]+p[26]+p[27]+p[28]+ - p[29]+p[30]+p[31]+p[32]+p[33]+p[34]+p[35]+ - p[36]+p[37]+p[38]+p[39]+p[40]+p[41]+p[42]+ - p[43]+p[44]+p[45]+p[46]+p[47]+p[48]+p[49]+ - p[50]+p[51]+p[52]+p[53]+p[54]+p[55]+p[56]+ - p[57]+p[58]+p[59]+p[60]+p[61]+p[62]+p[63]+ - p[64]+p[65]+p[66]+p[67]+p[68]+p[69]+p[70]+ - p[71]+p[72]+p[73]+p[74]+p[75]+p[76]+p[77]+ - p[78]+p[79]+p[80]+p[81]+p[82]+p[83]+p[84]+ - p[85]+p[86]+p[87]+p[88]+p[89]+p[90]+p[91]+ - p[92]+p[93]+p[94]+p[95]+p[96]+p[97]+p[98]+ - p[99]+p[100]+p[101]+p[102]+p[103]+p[104]+ - p[105]+p[106]+p[107]+p[108]+p[109]+p[110]+ - p[111]+p[112]+p[113]+p[114]+p[115]+p[116]+ - p[117]+p[118]+p[119]+p[120]+p[121]+p[122]+ - p[123]+p[124]+p[125]+p[126]+p[127]; - } - for (next = p + 16; (void*)next <= (void*)end; p = next, next += 16) { - sum += - p[0]+p[1]+p[2]+p[3]+p[4]+p[5]+p[6]+p[7]+ - p[8]+p[9]+p[10]+p[11]+p[12]+p[13]+p[14]+ - p[15]; - } - for (next = p + 1; (void*)next <= (void*)end; p = next, next++) { - sum += *p; - } - return sum; -} - -#pragma mark *** darbench routines - - -/*ARGSUSED*/ -int -benchmark_initbatch(void *tsd) -{ - /* - * initialize your state variables here second - */ - tsd_t *ts = (tsd_t *)tsd; - int procs; - - initialize_overhead(tsd); - - ts->pids = (pid_t*)malloc(ts->procs * sizeof(pid_t)); - if (ts->pids == NULL) - exit(1); - bzero((void*)ts->pids, ts->procs * sizeof(pid_t)); - procs = create_daemons(ts->p, ts->pids, - ts->procs, ts->process_size); - if (procs < ts->procs) { - cleanup(tsd); - exit(1); - } - return (0); -} - -int -benchmark_finirun() -{ - return (0); -} - -int -benchmark_init() -{ - /* - * the lm_optstr must be defined here or no options for you - * - * ...and the framework will throw an error - * - */ - (void) sprintf(lm_optstr, "s:"); - /* - * working hypothesis: - * - * tsd_t is the struct that we can pass around our - * state info in - * - * lm_tsdsize will allocate the space we need for this - * structure throughout the rest of the framework - */ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_usage, - " [-s kbytes]\n" - " processes [processes ...]\n"); - - return (0); -} - -int -benchmark_fini() -{ - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - /* - * Close the pipes and kill the children. - */ - cleanup_overhead(tsd); - for (i = 1; ts->pids && i < ts->procs; ++i) { - if (ts->pids[i] > 0) { - kill(ts->pids[i], SIGKILL); - waitpid(ts->pids[i], NULL, 0); - } - } - if (ts->pids) - free(ts->pids); - ts->pids = NULL; - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - return (&result); -} - -int -benchmark_finiworker(void *tsd) -{ - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - - switch (opt) { - case 's': - opts = sizetoint(optarg); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - - ts->process_size = opts; - - return (0); -} - -int -benchmark_initrun() -{ - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - /* - * initialize your state variables here last - * - * and realize that you are paying for your initialization here - * and it is really a bad idea - */ - tsd_t *ts = (tsd_t *)tsd; - int i; - int msg=1; - - for (i = 0; i < lm_optB; i++) { - if (write(ts->p[0][1], &msg, sizeof(msg)) != - sizeof(msg)) { - debug("read/write on pipe"); - exit(1); - } - if (read(ts->p[ts->procs-1][0], &msg, sizeof(msg)) != sizeof(msg)) { - debug("read/write on pipe"); - exit(1); - } - bread(ts->data, ts->process_size); - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/apple/lmbench_lat_sig_catch.c b/tools/tests/libMicro/apple/lmbench_lat_sig_catch.c deleted file mode 100644 index edca677ee..000000000 --- a/tools/tests/libMicro/apple/lmbench_lat_sig_catch.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -/* - * Order of Execution - * - * benchmark_init - * - * benchmark_optswitch - * - * benchmark_initrun - * - * benchmark_initworker - * benchmark_initbatch - * benchmark - * benchmark_finibatch - * benchmark_initbatch - * benchmark - * benchmark_finibatch, etc. - * benchmark_finiworker - * - * benchmark_result - * - * benchmark_finirun - * - * benchmark_fini - */ - - - -#ifdef __sun -#pragma ident "@(#)lmbench_lat_sig_catch.c 1.0 08/16/06 Apple Inc." -#endif - - - -#include -#include -#include -#include -#include - -#include "../libmicro.h" - -/* - * Your state variables should live in the tsd_t struct below - */ - -static int optp = 1; -static int optw = 0; -static int optn = -1; - -u_int64_t caught, n; -double adj; -void handler(int s) { } -jmp_buf prot_env; - -typedef struct { - int pid; -} tsd_t; - -/*ARGSUSED*/ -int -benchmark_initbatch(void *tsd) -{ - /* - * initialize your state variables here second - */ - return (0); -} - -int -benchmark_finirun() -{ - return (0); -} - -int -benchmark_init() -{ - /* - * the lm_optstr must be defined here or no options for you - * - * ...and the framework will throw an error - * - */ - (void) sprintf(lm_optstr, "p:w:n"); - /* - * working hypothesis: - * - * tsd_t is the struct that we can pass around our - * state info in - * - * lm_tsdsize will allocate the space we need for this - * structure throughout the rest of the framework - */ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_usage, - " [-p ]\n" - " [-w ]\n" - " [-n ]\n" - "notes: measures lmbench lat_sig install\n"); - lm_defB = 1; - return (0); -} - -int -benchmark_fini() -{ - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - /* - * more proof of state passing - */ - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - (void) fprintf(stderr, "benchmark_result\n"); - return (&result); -} - -int -benchmark_finiworker(void *tsd) -{ - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - - switch (opt) { - case 'w': - optw = sizetoint(optarg); - break; - case 'n': - optn = sizetoint(optarg); - break; - case 'p': - optp = sizetoint(optarg); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - /* - * initialize your state variables here first - */ - tsd_t* ts = (tsd_t*)tsd; - struct sigaction sa, old; - - sa.sa_handler = handler; - (void) sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - (void) sigaction(SIGUSR1, &sa, &old); - - ts->pid = getpid(); - return (0); -} - -int -benchmark_initrun() -{ - - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - /* - * initialize your state variables here last - * - * and realize that you are paying for your initialization here - * and it is really a bad idea - */ - int i; - tsd_t* ts = (tsd_t*)tsd; - - for (i = 0; i < lm_optB; i++) { - (void) kill(ts->pid, SIGUSR1); - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/apple/lmbench_lat_sig_install.c b/tools/tests/libMicro/apple/lmbench_lat_sig_install.c deleted file mode 100644 index ee1acd697..000000000 --- a/tools/tests/libMicro/apple/lmbench_lat_sig_install.c +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -/* - * Order of Execution - * - * benchmark_init - * - * benchmark_optswitch - * - * benchmark_initrun - * - * benchmark_initworker - * benchmark_initbatch - * benchmark - * benchmark_finibatch - * benchmark_initbatch - * benchmark - * benchmark_finibatch, etc. - * benchmark_finiworker - * - * benchmark_result - * - * benchmark_finirun - * - * benchmark_fini - */ - - - -#ifdef __sun -#pragma ident "@(#)lmbench_lat_sig_install.c 1.0 08/16/06 Apple Inc." -#endif - - - -#include -#include -#include -#include -#include - -#include "../libmicro.h" - -/* - * Your state variables should live in the tsd_t struct below - */ - -static int optp = 1; -static int optw = 0; -static int optn = -1; - -u_int64_t caught, n; -double adj; -void handler(int s) { } -jmp_buf prot_env; - -typedef struct { - int ts_once; -} tsd_t; - -/*ARGSUSED*/ -int -benchmark_initbatch(void *tsd) -{ - /* - * initialize your state variables here second - */ - return (0); -} - -int -benchmark_finirun() -{ - return (0); -} - -int -benchmark_init() -{ - /* - * the lm_optstr must be defined here or no options for you - * - * ...and the framework will throw an error - * - */ - (void) sprintf(lm_optstr, "t:"); - /* - * working hypothesis: - * - * tsd_t is the struct that we can pass around our - * state info in - * - * lm_tsdsize will allocate the space we need for this - * structure throughout the rest of the framework - */ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_usage, - " [-p ]\n" - " [-w ]\n" - " [-n ]\n" - "notes: measures lmbench lat_sig install\n"); - lm_defB = 1; - return (0); -} - -int -benchmark_fini() -{ - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - /* - * more proof of state passing - */ - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - (void) fprintf(stderr, "benchmark_result\n"); - return (&result); -} - -int -benchmark_finiworker(void *tsd) -{ - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - - switch (opt) { - case 'w': - optw = sizetoint(optarg); - break; - case 'n': - optn = sizetoint(optarg); - break; - case 'p': - optp = sizetoint(optarg); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - /* - * initialize your state variables here first - */ - - - return (0); -} - -int -benchmark_initrun() -{ - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - /* - * initialize your state variables here last - * - * and realize that you are paying for your initialization here - * and it is really a bad idea - */ - struct sigaction sa, old; - int i; - - for (i = 0; i < lm_optB; i++) { - sa.sa_handler = handler; - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - sigaction(SIGUSR1, &sa, &old); - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/apple/lmbench_lat_sig_prot.c b/tools/tests/libMicro/apple/lmbench_lat_sig_prot.c deleted file mode 100644 index b2612e9a4..000000000 --- a/tools/tests/libMicro/apple/lmbench_lat_sig_prot.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -/* - * Order of Execution - * - * benchmark_init - * - * benchmark_optswitch - * - * benchmark_initrun - * - * benchmark_initworker - * benchmark_initbatch - * benchmark - * benchmark_finibatch - * benchmark_initbatch - * benchmark - * benchmark_finibatch, etc. - * benchmark_finiworker - * - * benchmark_result - * - * benchmark_finirun - * - * benchmark_fini - */ - - - -#ifdef __sun -#pragma ident "@(#)lmbench_lat_sig_prot.c 1.0 08/16/06 Apple Inc." -#endif - - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#include "../libmicro.h" - -/* - * Your state variables should live in the tsd_t struct below - */ - -static int optp = 1; -static int optw = 0; -static int optn = -1; -static char *optf = "/Volumes/data/darbench/bin-i386/lmbench_lat_sig_prot"; -static int *mappedfile; -jmp_buf jumper; - -u_int64_t caught, n; -double adj; -void handler(int s) { } -jmp_buf prot_env; - -typedef struct { - char* fname; - char* where; -} tsd_t; - - -void -prot(int s) -{ - _longjmp(jumper, s); - -} - - -/*ARGSUSED*/ -int -benchmark_initbatch(void *tsd) -{ - /* - * initialize your state variables here second - */ - (void) fprintf(stderr, "benchmark_initbatch: entry\n"); - - return (0); -} - -int -benchmark_finirun() -{ - return (0); -} - -int -benchmark_init() -{ - /* - * the lm_optstr must be defined here or no options for you - * - * ...and the framework will throw an error - * - */ - (void) sprintf(lm_optstr, "p:w:n:f"); - /* - * working hypothesis: - * - * tsd_t is the struct that we can pass around our - * state info in - * - * lm_tsdsize will allocate the space we need for this - * structure throughout the rest of the framework - */ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_usage, - " [-p ]\n" - " [-w ]\n" - " [-n ]\n" - " [-f ]\n" - "notes: measures lmbench lat_sig prot\n"); - (void) fprintf(stderr, "benchmark_init: entry\n"); - lm_defB = 1; - return (0); -} - -int -benchmark_fini() -{ - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - /* - * more proof of state passing - */ - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - (void) fprintf(stderr, "benchmark_result\n"); - return (&result); -} - -int -benchmark_finiworker(void *tsd) -{ - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - (void) fprintf(stderr, "benchmark_optswitch: entry\n"); - - switch (opt) { - case 'w': - optw = sizetoint(optarg); - break; - case 'n': - optn = sizetoint(optarg); - break; - case 'p': - optp = sizetoint(optarg); - break; - case 'f': - (void) fprintf(stderr, "benchmark_optswitch: FILENAME entry = %s\n",optf); - //strcpy(optf, optarg); - (void) fprintf(stderr, "benchmark_optswitch: FILENAME exit\n"); - break; - default: - return (-1); - } - (void) fprintf(stderr, "benchmark_optswitch: exit\n"); - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - /* - * initialize your state variables here first - */ - tsd_t* ts = (tsd_t*)tsd; - int fd; - struct sigaction sa; - (void) fprintf(stderr, "benchmark_initworker: entry = %s\n",optf); - - ts->fname = optf; - fd = open(ts->fname, 0); - (void) fprintf(stderr, "benchmark_initworker: open result is %i\n",fd); - (void) fprintf(stderr, "benchmark_initworker: errno result is %d - \"%s\"\n",errno, strerror(errno)); - - ts->where = mmap(0,4096, PROT_READ, MAP_SHARED, fd, 0); - (void) fprintf(stderr, "benchmark_initworker: mmap result is %i\n",ts->where); - *mappedfile = (int) ts->where; - (void) fprintf(stderr, "benchmark_initworker: mappedfile result is %i\n",*mappedfile); - - if ((long)ts->where == -1) { - perror("mmap"); - exit(1); - } - - sa.sa_handler = prot; - sigemptyset(&sa.sa_mask); - sa.sa_flags = 0; - sigaction(SIGSEGV, &sa, 0); - sigaction(SIGBUS, &sa, 0); - - - caught = 0; - n = lm_optB; - return (0); -} - -int -benchmark_initrun() -{ - (void) fprintf(stderr, "benchmark_initrun: entry\n"); - - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - /* - * initialize your state variables here last - * - * and realize that you are paying for your initialization here - * and it is really a bad idea - */ - int i; - //tsd_t* ts = (tsd_t*)tsd; - (void) fprintf(stderr, "benchmark: lm_optB = %i\n",lm_optB); - for (i = 0; i < lm_optB; i++) { - if (_setjmp(jumper) == 0) { - - *mappedfile= 1; - } - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/apple/lmbench_lat_sig_send.c b/tools/tests/libMicro/apple/lmbench_lat_sig_send.c deleted file mode 100644 index 9797bc42f..000000000 --- a/tools/tests/libMicro/apple/lmbench_lat_sig_send.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -/* - * Order of Execution - * - * benchmark_init - * - * benchmark_optswitch - * - * benchmark_initrun - * - * benchmark_initworker - * benchmark_initbatch - * benchmark - * benchmark_finibatch - * benchmark_initbatch - * benchmark - * benchmark_finibatch, etc. - * benchmark_finiworker - * - * benchmark_result - * - * benchmark_finirun - * - * benchmark_fini - */ - - - -#ifdef __sun -#pragma ident "@(#)lmbench_lat_sig_catch.c 1.0 08/16/06 Apple Inc." -#endif - - - -#include -#include -#include -#include -#include - -#include "../libmicro.h" - -/* - * Your state variables should live in the tsd_t struct below - */ - -static int optp = 1; -static int optw = 0; -static int optn = -1; - -u_int64_t caught, n; -double adj; -void handler(int s) { } -jmp_buf prot_env; - -typedef struct { - int pid; -} tsd_t; - -/*ARGSUSED*/ -int -benchmark_initbatch(void *tsd) -{ - /* - * initialize your state variables here second - */ - return (0); -} - -int -benchmark_finirun() -{ - return (0); -} - -int -benchmark_init() -{ - /* - * the lm_optstr must be defined here or no options for you - * - * ...and the framework will throw an error - * - */ - (void) sprintf(lm_optstr, "p:w:n"); - /* - * working hypothesis: - * - * tsd_t is the struct that we can pass around our - * state info in - * - * lm_tsdsize will allocate the space we need for this - * structure throughout the rest of the framework - */ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_usage, - " [-p ]\n" - " [-w ]\n" - " [-n ]\n" - "notes: measures lmbench lat_sig install\n"); - lm_defB = 1; - return (0); -} - -int -benchmark_fini() -{ - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - /* - * more proof of state passing - */ - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - (void) fprintf(stderr, "benchmark_result\n"); - return (&result); -} - -int -benchmark_finiworker(void *tsd) -{ - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - - switch (opt) { - case 'w': - optw = sizetoint(optarg); - break; - case 'n': - optn = sizetoint(optarg); - break; - case 'p': - optp = sizetoint(optarg); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - /* - * initialize your state variables here first - */ - tsd_t* ts = (tsd_t*)tsd; - ts->pid = getpid(); - return (0); -} - -int -benchmark_initrun() -{ - - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - /* - * initialize your state variables here last - * - * and realize that you are paying for your initialization here - * and it is really a bad idea - */ - int i; - tsd_t* ts = (tsd_t*)tsd; - - for (i = 0; i < lm_optB; i++) { - (void) kill(ts->pid, 0); - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/apple/lmbench_openclose.c b/tools/tests/libMicro/apple/lmbench_openclose.c deleted file mode 100644 index f25154cd6..000000000 --- a/tools/tests/libMicro/apple/lmbench_openclose.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -#ifdef __sun -#pragma ident "@(#)lmbench_openclose.c 1.4 06/21/06 Apple Inc." -#endif - - -#include -#include -#include -#include -#include -#include - -#include "../libmicro.h" - -#define DEFF "/dev/null" -static char *optf = DEFF; - -int -benchmark_init() -{ - - (void) sprintf(lm_optstr, "f:"); - - lm_tsdsize = 0; - - (void) sprintf(lm_usage, - " [-f file-to-stat (default %s)]\n" - "notes: measures stat()\n", - DEFF); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'f': - optf = optarg; - break; - default: - return (-1); - } - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - int fd; - - res->re_errors = 0; - -/* - * The libmicro test uses a for loop as below: - * for (i = 0; i < lm_optB; i++) { - * - * we can probably get away with using lm_optB - * in the while loop below - * - */ - i = 0; - - while (i++ < lm_optB) { - fd = open(optf, 0); - if (fd == -1) { - res->re_errors++; - } - close(fd); - } - - res->re_count += lm_optB; - - return (0); -} diff --git a/tools/tests/libMicro/apple/lmbench_read.c b/tools/tests/libMicro/apple/lmbench_read.c deleted file mode 100644 index 15225ddcd..000000000 --- a/tools/tests/libMicro/apple/lmbench_read.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -#ifdef __sun -#pragma ident "@(#)lmbench_read.c 1.5 05/08/04 Apple Inc." -#endif - - -#ifdef linux -#define _XOPEN_SOURCE 500 -#endif - -#include -#include -#include -#include - -#include "../libmicro.h" - -typedef struct { - char *ts_buf; - int ts_fd; -} tsd_t; - -#define DEFF "/dev/zero" -#define DEFS 1024 - -static char *optf = DEFF; -static long long opts = DEFS; -int optw = 0; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "f:s:w"); - - (void) sprintf(lm_usage, - " [-f file-to-read (default %s)]\n" - " [-s buffer-size (default %d)]\n" - " [-w (store a byte to each page after read)]\n" - "notes: measures lmbench_read()\n", - DEFF, DEFS); - - (void) sprintf(lm_header, "%8s", "size"); - - lm_defB = 1; - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'w': - optw = getpagesize(); - break; - case 'f': - optf = optarg; - break; - case 's': - opts = sizetoll(optarg); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initrun() -{ - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - - if (ts->ts_buf == NULL) { - ts->ts_buf = malloc(opts); - ts->ts_fd = open(optf, O_RDONLY); - } - - (void) lseek(ts->ts_fd, 0, SEEK_SET); - - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - int j; -/* - * The libmicro test uses a for loop as below: - * for (i = 0; i < lm_optB; i++) { - * - * we can probably get away with using lm_optB - * in the while loop below - * - */ - i = 0; - - while (i++ < lm_optB) { - if (read(ts->ts_fd, ts->ts_buf, opts) != opts) { - res->re_errors++; - } - if (optw) - for (j = 0; j < opts; j += optw) - ts->ts_buf[j] = 0; - } - res->re_count = i; - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - - (void) sprintf(result, "%8lld", opts); - - return (result); -} diff --git a/tools/tests/libMicro/apple/lmbench_select_file.c b/tools/tests/libMicro/apple/lmbench_select_file.c deleted file mode 100644 index cdad43ec1..000000000 --- a/tools/tests/libMicro/apple/lmbench_select_file.c +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -/* - * Order of Execution - * - * benchmark_init - * - * benchmark_optswitch - * - * benchmark_initrun - * - * benchmark_initworker - * benchmark_initbatch - * benchmark - * benchmark_finibatch - * benchmark_initbatch - * benchmark - * benchmark_finibatch, etc. - * benchmark_finiworker - * - * benchmark_result - * - * benchmark_finirun - * - * benchmark_fini - */ - - - -#ifdef __sun -#pragma ident "@(#)socket.c 1.3 05/08/04 Apple Inc." -#endif - - - -#include -#include -#include -#include -#include -#include - -#include "../libmicro.h" - -/* - * lmbench routines, etc. brought over for this benchmark - */ -int open_file(void* tsd); -void server(void* tsd); - - -typedef int (*open_f)(void* tsd); -/* - * end of lmbench support routines - */ - -/* - * Your state variables should live in the tsd_t struct below - */ -typedef struct { - char fname[L_tmpnam]; - open_f fid_f; - pid_t pid; - int sock; - int fid; - int num; - int max; - fd_set set; -} tsd_t; - -static int optt = 1; -static int optn = -1; -static int optp = 1; -static int optw = 0; - -/* - * lmbench routines, etc. brought over for this benchmark - */ - -void -morefds(void) -{ -#ifdef RLIMIT_NOFILE - struct rlimit r; - - getrlimit(RLIMIT_NOFILE, &r); - r.rlim_cur = r.rlim_max; - setrlimit(RLIMIT_NOFILE, &r); -#endif -} - -int -open_file(void* tsd) -{ - tsd_t* ts = (tsd_t*)tsd; - //(void) fprintf(stderr, "open_file: ts->fname = %s\n",ts->fname); - return (int) open(ts->fname, O_RDONLY); -} - -void -server(void* tsd) -{ - int pid; - tsd_t* ts = (tsd_t*)tsd; - - pid = getpid(); - ts->pid = 0; - //(void) fprintf(stderr, "server: state->fid_f = %i\n",ts->fid_f); - - if (ts->fid_f == open_file) { - /* Create a temporary file for clients to open */ - sprintf(ts->fname, "/tmp/lat_selectXXXXXX"); - //(void) fprintf(stderr, "server: ts->fname = %s\n",ts->fname); - ts->fid = mkstemp(ts->fname); - //(void) fprintf(stderr, "server: ts->fname = %s: ts->fid = %d\n",ts->fname, ts->fid); - - if (ts->fid <= 0) { - char buf[L_tmpnam+128]; - sprintf(buf, "lat_select: Could not create temp file %s", ts->fname); - perror(buf); - exit(1); - } - close(ts->fid); - return; - } -// -// this is all for the tcp version of this test only -// -// /* Create a socket for clients to connect to */ -// state->sock = tcp_server(TCP_SELECT, SOCKOPT_REUSE); -// if (state->sock <= 0) { -// perror("lat_select: Could not open tcp server socket"); -// exit(1); -// } - - /* Start a server process to accept client connections */ -// switch(state->pid = fork()) { -// case 0: -// /* child server process */ -// while (pid == getppid()) { -// int newsock = tcp_accept(state->sock, SOCKOPT_NONE); -// read(newsock, &state->fid, 1); -// close(newsock); -// } -// exit(0); -// case -1: -// /* error */ -// perror("lat_select::server(): fork() failed"); -// exit(1); -// default: -// break; -// } -} - - -/* - * end of lmbench support routines - */ - -/*ARGSUSED*/ -int -benchmark_initbatch(void *tsd) -{ - /* - * initialize your state variables here second - */ - return (0); -} - -int -benchmark_finirun() -{ - //(void) fprintf(stderr, "benchmark_finirun\n"); - return (0); -} - -int -benchmark_init() -{ - //(void) fprintf(stderr, "benchmark_init\n"); - /* - * the lm_optstr must be defined here or no options for you - * - * ...and the framework will throw an error - * - */ - (void) sprintf(lm_optstr, "p:w:n:t:"); - /* - * working hypothesis: - * - * tsd_t is the struct that we can pass around our - * state info in - * - * lm_tsdsize will allocate the space we need for this - * structure throughout the rest of the framework - */ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_usage, - " [-p parallelism (default 1)]\n" - " [-w warmup (default 0)]\n" - " [-n number of descriptors (default 1)]\n" - " [-t int (default 1)]\n" - "notes: measures lmbench_select_file\n"); - lm_defB = 1; - return (0); -} - -int -benchmark_fini() -{ - //(void) fprintf(stderr, "benchmark_fini\n"); - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - //(void) fprintf(stderr, "benchmark_result\n"); - return (&result); -} - -int -benchmark_finiworker(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - // pulls in the lmbench cleanup code - //(void) fprintf(stderr, "benchmark_finiworker\n"); - for (i = 0; i <= ts->max; ++i) { - if (FD_ISSET(i, &(ts->set))) - close(i); - } - FD_ZERO(&(ts->set)); - unlink(ts->fname); - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - //(void) fprintf(stderr, "benchmark_optswitch\n"); - - switch (opt) { - case 't': - optt = sizetoint(optarg); - break; - case 'n': - optn = sizetoint(optarg); - break; - case 'p': - optp = sizetoint(optarg); - break; - case 'w': - optw = sizetoint(optarg); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - // pulls in code from lmbench main and initialize - int n = 0; - /* - * initialize your state variables here first - */ - tsd_t *ts = (tsd_t *)tsd; - int N, fid, fd; - - /* - * default number of file descriptors - */ - //(void) fprintf(stderr, "benchmark_initworker\n"); - ts->num = 200; - if (optn > 0) { - ts->num = optn; - } - N = ts->num; - //(void) fprintf(stderr, "benchmark_initworker ts->num is %i\n",ts->num); - - /* - * grab more file descriptors - */ - - morefds(); - - ts->fid_f = open_file; - server(ts); - //(void) fprintf(stderr, "benchmark_initworker: returned from server call\n"); - /* - * Initialize function from lmbench - * for this test - */ - fid = (*ts->fid_f)(ts); - //(void) fprintf(stderr, "initworker: fid is %i\n",fid); - if (fid <= 0) { - perror("Could not open device"); - exit(1); - } - ts->max = 0; - FD_ZERO(&(ts->set)); - //(void) fprintf(stderr, "initworker FD_ZERO: ts->set result is %i\n",ts->set); - //(void) fprintf(stderr, "initworker: N is %i\n",N); - for (n = 0; n < N; n++) { - //(void) fprintf(stderr, "benchmark_initworker: in the loop - N is %i: n is %i\n",N, n); - fd = dup(fid); - //(void) fprintf(stderr, "benchmark_initworker: dup result is %i\n",fd); - //(void) fprintf(stderr, "benchmark_initworker: errno result is %d - \"%s\"\n",errno, strerror(errno)); - - if (fd == -1) break; - if (fd > ts->max) - ts->max = fd; - FD_SET(fd, &(ts->set)); - //(void) fprintf(stderr, "initworker FD_SET: ts->set result is %i\n",ts->set); - - } - //(void) fprintf(stderr, "benchmark_initworker: after second macro/loop\n"); - - ts->max++; - close(fid); - //(void) fprintf(stderr, "benchmark_initworker: N is %i: n is %i\n",N, n); - if (n != N) - exit(1); - /* end of initialize function */ - //(void) fprintf(stderr, "benchmark_initworker: about to exit\n"); - return (0); -} - -int -benchmark_initrun() -{ - //(void) fprintf(stderr, "benchmark_initrun\n"); - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - /* - * initialize your state variables here last - * - * and realize that you are paying for your initialization here - * and it is really a bad idea - */ - tsd_t *ts = (tsd_t *)tsd; - fd_set nosave; - static struct timeval tv; - - //(void) fprintf(stderr, "benchmark\n"); - - int i; - //int sel_res; - tv.tv_sec = 0; - tv.tv_usec = 0; - - - for (i = 0; i < lm_optB; i++) { - nosave = ts->set; - //(void) fprintf(stderr, "benchmark: nosave is %i\n", nosave); - - select(ts->num, 0, &nosave, 0, &tv); - //(void) fprintf(stderr, "benchmark: select result is %i\n",sel_res); - //(void) fprintf(stderr, "benchmark: errno result is %d - \"%s\"\n",errno, strerror(errno)); - - - } - res->re_count = i; - return (0); -} - diff --git a/tools/tests/libMicro/apple/lmbench_select_tcp.c b/tools/tests/libMicro/apple/lmbench_select_tcp.c deleted file mode 100644 index aea77dae1..000000000 --- a/tools/tests/libMicro/apple/lmbench_select_tcp.c +++ /dev/null @@ -1,622 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -/* - * Order of Execution - * - * benchmark_init - * - * benchmark_optswitch - * - * benchmark_initrun - * - * benchmark_initworker - * benchmark_initbatch - * benchmark - * benchmark_finibatch - * benchmark_initbatch - * benchmark - * benchmark_finibatch, etc. - * benchmark_finiworker - * - * benchmark_result - * - * benchmark_finirun - * - * benchmark_fini - */ - - - -#ifdef __sun -#pragma ident "@(#)socket.c 1.3 05/08/04 Apple Inc." -#endif - - - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../libmicro.h" - -/* - * lmbench routines, etc. brought over for this benchmark - */ -int open_file(void* tsd); -void server(void* tsd); -int tcp_accept(int sock, int rdwr); -void sock_optimize(int sock, int flags); -int sockport(int s); -int tcp_server(int prog, int rdwr); -int tcp_connect(char *host, int prog, int rdwr); -int open_socket(void *tsd); - - -typedef int (*open_f)(void* tsd); -/* - * end of lmbench support routines - */ - -/* - * Your state variables should live in the tsd_t struct below - */ -typedef struct { - char fname[L_tmpnam]; - open_f fid_f; - pid_t pid; - int sock; - int fid; - int num; - int max; - fd_set set; -} tsd_t; - -static int optt = 1; -static int optn = -1; -static int optp = 1; -static int optw = 0; - -/* - * lmbench routines, etc. brought over for this benchmark - */ - -void -morefds(void) -{ -#ifdef RLIMIT_NOFILE - struct rlimit r; - - getrlimit(RLIMIT_NOFILE, &r); - r.rlim_cur = r.rlim_max; - setrlimit(RLIMIT_NOFILE, &r); -#endif -} - -int -open_file(void* tsd) -{ - tsd_t* ts = (tsd_t*)tsd; - return (int) open(ts->fname, O_RDONLY); -} - -int -open_socket(void* tsd) -{ - return tcp_connect("localhost", TCP_SELECT, SOCKOPT_NONE); -} - -void -server(void* tsd) -{ - int pid; - tsd_t *ts = (tsd_t *)tsd; - - pid = getpid(); - ts->pid = 0; - - if (ts->fid_f == open_file) { - /* Create a temporary file for clients to open */ - sprintf(ts->fname, "lat_selectXXXXXX"); - ts->fid = mkstemp(ts->fname); - if (ts->fid <= 0) { - char buf[L_tmpnam+128]; - sprintf(buf, "lat_select: Could not create temp file %s", ts->fname); - perror(buf); - exit(1); - } - close(ts->fid); - return; - } - - /* Create a socket for clients to connect to */ - ts->sock = tcp_server(TCP_SELECT, SOCKOPT_REUSE); - if (ts->sock <= 0) { - perror("lat_select: Could not open tcp server socket"); - exit(1); - } - - /* Start a server process to accept client connections */ - switch(ts->pid = fork()) { - case 0: - /* child server process */ - while (pid == getppid()) { - int newsock = tcp_accept(ts->sock, SOCKOPT_NONE); - read(newsock, &ts->fid, 1); - close(newsock); - } - exit(0); - case -1: - /* error */ - perror("lat_select::server(): fork() failed"); - exit(1); - default: - break; - } -} - - -/* - * Accept a connection and return it - */ -int -tcp_accept(int sock, int rdwr) -{ - struct sockaddr_in s; - int newsock; - socklen_t namelen; - - namelen = sizeof(s); - bzero((void*)&s, namelen); - -retry: - if ((newsock = accept(sock, (struct sockaddr*)&s, &namelen)) < 0) { - if (errno == EINTR) - goto retry; - perror("accept"); - exit(6); - } -#ifdef LIBTCP_VERBOSE - fprintf(stderr, "Server newsock port %d\n", sockport(newsock)); -#endif - sock_optimize(newsock, rdwr); - return (newsock); -} - -void -sock_optimize(int sock, int flags) -{ - if (flags & SOCKOPT_READ) { - int sockbuf = SOCKBUF; - - while (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &sockbuf, - sizeof(int))) { - sockbuf >>= 1; - } -#ifdef LIBTCP_VERBOSE - fprintf(stderr, "sockopt %d: RCV: %dK\n", sock, sockbuf>>10); -#endif - } - if (flags & SOCKOPT_WRITE) { - int sockbuf = SOCKBUF; - - while (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sockbuf, - sizeof(int))) { - sockbuf >>= 1; - } -#ifdef LIBTCP_VERBOSE - fprintf(stderr, "sockopt %d: SND: %dK\n", sock, sockbuf>>10); -#endif - } - if (flags & SOCKOPT_REUSE) { - int val = 1; - if (setsockopt(sock, SOL_SOCKET, - SO_REUSEADDR, &val, sizeof(val)) == -1) { - perror("SO_REUSEADDR"); - } - } -} - -int -sockport(int s) -{ - socklen_t namelen; - struct sockaddr_in sin; - - namelen = sizeof(sin); - if (getsockname(s, (struct sockaddr *)&sin, &namelen) < 0) { - perror("getsockname"); - return(-1); - } - return ((int)ntohs(sin.sin_port)); -} - -/* - * Get a TCP socket, bind it, figure out the port, - * and advertise the port as program "prog". - * - * XXX - it would be nice if you could advertise ascii strings. - */ -int -tcp_server(int prog, int rdwr) -{ - int sock; - struct sockaddr_in s; - -#ifdef LIBTCP_VERBOSE - fprintf(stderr, "tcp_server(%u, %u)\n", prog, rdwr); -#endif - if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { - perror("socket"); - exit(1); - } - sock_optimize(sock, rdwr); - bzero((void*)&s, sizeof(s)); - s.sin_family = AF_INET; - if (prog < 0) { - s.sin_port = htons(-prog); - } - if (bind(sock, (struct sockaddr*)&s, sizeof(s)) < 0) { - perror("bind"); - exit(2); - } - if (listen(sock, 100) < 0) { - perror("listen"); - exit(4); - } - if (prog > 0) { -#ifdef LIBTCP_VERBOSE - fprintf(stderr, "Server port %d\n", sockport(sock)); -#endif - (void)pmap_unset((u_long)prog, (u_long)1); - if (!pmap_set((u_long)prog, (u_long)1, (u_long)IPPROTO_TCP, - (unsigned short)sockport(sock))) { - perror("pmap_set"); - exit(5); - } - } - return (sock); -} - - -/* - * Connect to the TCP socket advertised as "prog" on "host" and - * return the connected socket. - * - * Hacked Thu Oct 27 1994 to cache pmap_getport calls. This saves - * about 4000 usecs in loopback lat_connect calls. I suppose we - * should time gethostbyname() & pmap_getprot(), huh? - */ -int -tcp_connect(char *host, int prog, int rdwr) -{ - static struct hostent *h; - static struct sockaddr_in s; - static u_short save_port; - static u_long save_prog; - static char *save_host; - int sock; - static int tries = 0; - - if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { - perror("socket"); - exit(1); - } - if (rdwr & SOCKOPT_PID) { - static unsigned short port; - struct sockaddr_in sin; - - if (!port) { - port = (unsigned short)(getpid() << 4); - if (port < 1024) { - port += 1024; - } - } - do { - port++; - bzero((void*)&sin, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_port = htons(port); - } while (bind(sock, (struct sockaddr*)&sin, sizeof(sin)) == -1); - } -#ifdef LIBTCP_VERBOSE - else { - struct sockaddr_in sin; - - bzero((void*)&sin, sizeof(sin)); - sin.sin_family = AF_INET; - if (bind(sock, (struct sockaddr*)&sin, sizeof(sin)) < 0) { - perror("bind"); - exit(2); - } - } - fprintf(stderr, "Client port %d\n", sockport(sock)); -#endif - sock_optimize(sock, rdwr); - if (!h || host != save_host || prog != save_prog) { - save_host = host; /* XXX - counting on them not - * changing it - benchmark only. - */ - save_prog = prog; - if (!(h = gethostbyname(host))) { - perror(host); - exit(2); - } - bzero((void *) &s, sizeof(s)); - s.sin_family = AF_INET; - bcopy((void*)h->h_addr, (void *)&s.sin_addr, h->h_length); - if (prog > 0) { - save_port = pmap_getport(&s, prog, - (u_long)1, IPPROTO_TCP); - if (!save_port) { - perror("lib TCP: No port found"); - exit(3); - } -#ifdef LIBTCP_VERBOSE - fprintf(stderr, "Server port %d\n", save_port); -#endif - s.sin_port = htons(save_port); - } else { - s.sin_port = htons(-prog); - } - } - if (connect(sock, (struct sockaddr*)&s, sizeof(s)) < 0) { - if (errno == ECONNRESET - || errno == ECONNREFUSED - || errno == EAGAIN) { - close(sock); - if (++tries > 10) return(-1); - return (tcp_connect(host, prog, rdwr)); - } - perror("connect"); - exit(4); - } - tries = 0; - return (sock); -} - - -/* - * end of lmbench support routines - */ - -/*ARGSUSED*/ -int -benchmark_initbatch(void *tsd) -{ - /* - * initialize your state variables here second - */ - return (0); -} - -int -benchmark_finirun() -{ - return (0); -} - -int -benchmark_init() -{ - /* - * the lm_optstr must be defined here or no options for you - * - * ...and the framework will throw an error - * - */ - (void) sprintf(lm_optstr, "p:w:n:t:"); - /* - * working hypothesis: - * - * tsd_t is the struct that we can pass around our - * state info in - * - * lm_tsdsize will allocate the space we need for this - * structure throughout the rest of the framework - */ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_usage, - " [-p parallelism (default 1)]\n" - " [-w warmup (default 0)]\n" - " [-n number of descriptors (default 1)]\n" - " [-t int (default 1)]\n" - "notes: measures lmbench_select_file\n"); - lm_defB = 1; - return (0); -} - -int -benchmark_fini() -{ - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - return (&result); -} - -int -benchmark_finiworker(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - // pulls in the lmbench cleanup code - for (i = 0; i <= ts->max; ++i) { - if (FD_ISSET(i, &(ts->set))) - close(i); - } - FD_ZERO(&(ts->set)); - unlink(ts->fname); - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - - switch (opt) { - case 't': - optt = sizetoint(optarg); - break; - case 'n': - optn = sizetoint(optarg); - break; - case 'p': - optp = sizetoint(optarg); - break; - case 'w': - optw = sizetoint(optarg); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - // pulls in code from lmbench main and initialize - int n = 0; - /* - * initialize your state variables here first - */ - tsd_t *ts = (tsd_t *)tsd; - int N, fid, fd; - - /* - * default number of file descriptors - */ - ts->num = 200; - if (optn > 0) { - ts->num = optn; - } - N = ts->num; - - /* - * grab more file descriptors - */ - - morefds(); - - ts->fid_f = open_socket; - server(ts); - /* - * Initialize function from lmbench - * for this test - */ - fid = (*ts->fid_f)(ts); - if (fid <= 0) { - perror("Could not open device"); - exit(1); - } - ts->max = 0; - FD_ZERO(&(ts->set)); - for (n = 0; n < N; n++) { - fd = dup(fid); - //(void) fprintf(stderr, "benchmark_initworker: errno result is %d - \"%s\"\n",errno, strerror(errno)); - - if (fd == -1) break; - if (fd > ts->max) - ts->max = fd; - FD_SET(fd, &(ts->set)); - //(void) fprintf(stderr, "initworker FD_SET: ts->set result is %i\n",ts->set); - - } - //(void) fprintf(stderr, "benchmark_initworker: after second macro/loop\n"); - - ts->max++; - close(fid); - if (n != N) - exit(1); - /* end of initialize function */ - return (0); -} - -int -benchmark_initrun() -{ - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - /* - * initialize your state variables here last - * - * and realize that you are paying for your initialization here - * and it is really a bad idea - */ - tsd_t *ts = (tsd_t *)tsd; - fd_set nosave; - static struct timeval tv; - - //(void) fprintf(stderr, "benchmark\n"); - - int i; - //int sel_res; - tv.tv_sec = 0; - tv.tv_usec = 0; - - - for (i = 0; i < lm_optB; i++) { - nosave = ts->set; - //(void) fprintf(stderr, "benchmark: nosave is %i\n", nosave); - - select(ts->num, 0, &nosave, 0, &tv); - - } - res->re_count = i; - return (0); -} - diff --git a/tools/tests/libMicro/apple/lmbench_stat.c b/tools/tests/libMicro/apple/lmbench_stat.c deleted file mode 100644 index b20b0251e..000000000 --- a/tools/tests/libMicro/apple/lmbench_stat.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -/* - * Portions Copyright (c) 2006, Apple Inc. - */ - -#ifdef __sun -#pragma ident "@(#)lmbench_stat.c 1.4 06/21/06 Apple Inc." -#endif - - -#include -#include -#include -#include -#include - -#include "../libmicro.h" - -#define DEFF "/dev/null" -static char *optf = DEFF; - -int -benchmark_init() -{ - - (void) sprintf(lm_optstr, "f:"); - - lm_tsdsize = 0; - - (void) sprintf(lm_usage, - " [-f file-to-stat (default %s)]\n" - "notes: measures stat()\n", - DEFF); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'f': - optf = optarg; - break; - default: - return (-1); - } - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - struct stat sbuf; - - res->re_errors = 0; - -/* - * The libmicro test uses a for loop as below: - * for (i = 0; i < lm_optB; i++) { - * - * we can probably get away with using lm_optB - * in the while loop below - * - */ - i = 0; - - while (i++ < lm_optB) { - if (stat(optf, &sbuf) == -1) - res->re_errors++; - } - - res->re_count += lm_optB; - - return (0); -} diff --git a/tools/tests/libMicro/apple/lmbench_write.c b/tools/tests/libMicro/apple/lmbench_write.c deleted file mode 100644 index 3224d4d20..000000000 --- a/tools/tests/libMicro/apple/lmbench_write.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -#ifdef __sun -#pragma ident "@(#)write.c 1.3 05/08/04 Apple Inc." -#endif - -#ifdef linux -#define _XOPEN_SOURCE 500 -#endif - -#include -#include -#include -#include - -#include "../libmicro.h" - -typedef struct { - char *ts_buf; - int ts_fd; -} tsd_t; - -#define DEFF "/dev/null" -#define DEFS 1024 - -static int optc = 0; -static char *optf = DEFF; -static long long opts = DEFS; -static int optd; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "cdf:s:"); - - (void) sprintf(lm_usage, - " [-f file-to-write (default %s)]\n" - " [-s buffer-size (default %d)]\n" - " [-c ] (make sure buffer is in cache)\n" -#ifdef __sun - " [-d ] use directio" -#endif - "notes: measures lmbench_write()\n", - DEFF, DEFS); - - (void) sprintf(lm_header, "%8s", "size"); - - lm_defB = 1; - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - - case 'd': - optd++; - break; - case 'c': - optc++; - break; - case 'f': - optf = optarg; - break; - case 's': - opts = sizetoll(optarg); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - if (ts->ts_buf == NULL) { - ts->ts_buf = malloc(opts); - ts->ts_fd = open(optf, O_WRONLY); - -#ifdef __sun - if (optd) - (void) directio(ts->ts_fd, DIRECTIO_ON); -#endif - /* - * bring buf into cache if specified. - */ - - if (optc) - for (i = 0; i < opts; i++) - ts->ts_buf[i] = 0; - } - - (void) lseek(ts->ts_fd, 0, SEEK_SET); - - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - -/* - * The libmicro test uses a for loop as below: - * for (i = 0; i < lm_optB; i++) { - * - * we can probably get away with using lm_optB - * in the while loop below - * - */ - i = 0; - - while (i++ < lm_optB) { - if (write(ts->ts_fd, ts->ts_buf, opts) != opts) { - res->re_errors++; - } - } - res->re_count = i; - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - - (void) sprintf(result, "%8lld", opts); - - return (result); -} diff --git a/tools/tests/libMicro/apple/mbr_check_membership.c b/tools/tests/libMicro/apple/mbr_check_membership.c deleted file mode 100644 index 91fbffeca..000000000 --- a/tools/tests/libMicro/apple/mbr_check_membership.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#include -#include -#include -#include -#include -#include - -// add additional headers needed here. - -#include "../libmicro.h" -#include -#include -#include - -#if DEBUG -# define debug(fmt, args...) (void) fprintf(stderr, fmt "\n" , ##args) -#else -# define debug(fmt, args...) -#endif - - -// Correct use case -// -// mbr_check_membership -E -L -S -W -B 200 -C 10 -g 1211-1213 -u 5000-5200 -// -// libMicro default benchmark run options are "-E -C 200 -L -S -W" -// -// -B is batch size: loop iteration per each benchmark run. (default: 100) -// -C is min sample number: how many benchmark needs to run to get proper sample -// 1 is mimumum, but you get at least 3 benchmark run -// samples. Do not set to zero. Default is 200 for most -// runs in libMicro. -// -u uid range in the form of "min-max". For example, -u 5000-5200 -// -g gid range or gid - -/* - * Your state variables should live in the tsd_t struct below - */ -typedef struct { -} tsd_t; - -#define INVALID_ID -1 - -static uid_t uid_min = INVALID_ID; -static gid_t gid_min = INVALID_ID;; - -static int uid_range = 0; // uid_max = uid_min + uid_range -static int gid_range = 0; // gid_max = gid_min + gid_range - -static uuid_t *u_uuid_list = NULL; // user uuid list -static uuid_t *g_uuid_list = NULL; // group uuid list - -int -benchmark_init() -{ - debug("benchmark_init"); - (void) sprintf(lm_optstr, "g:u:"); - - lm_tsdsize = sizeof(tsd_t); - lm_defB = 100; - - (void) sprintf(lm_usage, - "\n ------- mbr_check_membership specific options\n" - " [-u UID range (min-max)]\n" - " [-g GID or GID range (gid or min-max)]\n" - "\n" ); - return (0); -} - -int -parse_range(uint *min, int *offset, char *buf) -{ - char *value, *tmp_ptr = strdup(buf); - int range=0; - debug("parse_range"); - - value = strsep(&tmp_ptr, "-"); - *min = atoi(value); - debug("min = %d", *min); - if (tmp_ptr) { - value = strsep(&tmp_ptr, "-"); - range = atoi(value); - if (range < *min) { - printf("max id should be larger than min id\n"); - return -1; - } - *offset = range - *min; - debug("range = %d", *offset); - } - - return 0; - -} - -/* - * This is where you parse your lower-case arguments. - */ -int -benchmark_optswitch(int opt, char *optarg) -{ - debug("benchmark_optswitch"); - - switch (opt) { - case 'g': // GID or GID range - return parse_range( &gid_min, &gid_range, optarg); - break; - - case 'u': // UID range - return parse_range( &uid_min, &uid_range, optarg); - break; - default: - return -1; - } - - return 0; -} - - -// Initialize all structures that will be used in benchmark() -// 1. make local or network node for OD query -// 2. create user key -int -benchmark_initrun(void *tsd) -{ - int i; - //tsd_t *ts = (tsd_t *)tsd; - - debug("benchmark_initrun"); - - if (uid_min == INVALID_ID || gid_min == INVALID_ID) { - printf("Both -u and -g need to be specified\n"); - return -1; - } - - // create an array of usernames to use in benchmark before their use - // realtime generation in benchmark effects performance measurements - - u_uuid_list = malloc( sizeof(*u_uuid_list) * (uid_range+1) ); - g_uuid_list = malloc( sizeof(*g_uuid_list) * (gid_range+1) ); - - for (i = 0; i <= uid_range; i++) { - - if (mbr_uid_to_uuid(uid_min+i, u_uuid_list[i])) { - printf("error converting uid %d to UUID\n", uid_min+i); - return -1; - } - } - - for (i = 0; i <= gid_range; i++) { - - if (mbr_gid_to_uuid(gid_min+i, g_uuid_list[i])) { - printf("error converting gid %d to UUID\n", gid_min+i); - return -1; - } - } - - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - int i, index, gindex, err, isMember=0; - //tsd_t *ts = (tsd_t *)tsd; - -#ifdef DEBUG - uid_t uid; - int id_type; -#endif - - res->re_errors = 0; - - // debug("in to benchmark - optB = %i", lm_optB); - - for (i = 0; i < lm_optB; i++) { - - index = random() % (uid_range+1); - gindex = random() % (gid_range+1); - err = mbr_check_membership(u_uuid_list[index], g_uuid_list[gindex], &isMember); - -#ifdef DEBUG - //mbr_uuid_to_id(u_uuid_list[index], &uid, &id_type); - //debug ("loop %d: uid %d is %s (gindex %d)", i, uid, (isMember)?"member":"not a member", gindex); -#endif - - if (err) { - if (err == EIO) { - debug("mbr_check_membership returned EIO. Unable to communicate with DS daemon"); - } - else if (err == ENOENT) { - debug("mbr_check_membership returned ENOENT. User not found"); - } - else { - debug("error: %s", strerror(err)); - } - res->re_errors++; - } - } - res->re_count = i; - - return (0); -} - - -// We need to release all the structures we allocated in benchmark_initrun() -int -benchmark_finirun(void *tsd) -{ - //tsd_t *ts = (tsd_t *)tsd; - - debug("benchmark_result: deallocating structures"); - - free(u_uuid_list); - free(g_uuid_list); - - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - debug("benchmark_result"); - return (&result); -} - diff --git a/tools/tests/libMicro/apple/mbr_check_service_membership.c b/tools/tests/libMicro/apple/mbr_check_service_membership.c deleted file mode 100644 index 47e3267fa..000000000 --- a/tools/tests/libMicro/apple/mbr_check_service_membership.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#include -#include -#include -#include -#include -#include - -// add additional headers needed here. - -#include "../libmicro.h" -#include -#include -#include - -#if DEBUG -# define debug(fmt, args...) (void) fprintf(stderr, fmt "\n" , ##args) -#else -# define debug(fmt, args...) -#endif - - -// Correct use case -// -// mbr_check_service_membership -E -L -S -W -B 200 -C 10 -r 100 -s "SACL" -u user_prefix -// -// libMicro default benchmark run options are "-E -C 200 -L -S -W" -// -// -B is batch size: loop iteration per each benchmark run. Needs to match # of -// real lookups. This is total number of lookups to issue. -// -C is min sample number: how many benchmark needs to run to get proper sample -// 1 is mimumum, but you get at least 3 benchmark run -// samples. Do not set to zero. Default is 200 for most -// runs in libMicro. -// -r is the number of total records. -// -s is SACL string: ie. "ssh" -// -u user_prefix that preceeds the user number - -typedef struct { - uuid_t *uuid_list; -} tsd_t; - -// the number of record lookup to issue is covered by standard option optB -static int optRecords = 100; // the number of total records -static int optSACL = 0; // option SACL specified? - -static char **sacl = NULL; -static char *default_sacl[] = { "com.apple.access_dsproxy", - "com.apple.access_screensharing", - "com.apple.access_ssh", - ""}; -static int numSACL = 3; // number of SACLs - - -// This will use local users (local_test_*) -static char *default_uprefix = "local_test_"; - -int -benchmark_init() -{ - debug("benchmark_init"); - (void) sprintf(lm_optstr, "r:s:u:"); - - lm_tsdsize = sizeof(tsd_t); - lm_defB = 100; - - (void) sprintf(lm_usage, - "\n ------- mbr_check_service_membership specific options (default: *)\n" - " [-r total number of records (100*)]\n" - " [-s SACL]\n" - " [-u user_prefix]\n" - "\n" ); - return (0); -} - -/* - * This is where you parse your lower-case arguments. - */ -int -benchmark_optswitch(int opt, char *optarg) -{ - debug("benchmark_optswitch"); - - switch (opt) { - case 'r': // total number of records. default is 100 - optRecords = atoi(optarg); - debug("optRecords = %d\n", optRecords); - break; - - case 's': // SACL - if (optSACL) { - printf("SACL already specified. Skipping"); - break; - } - sacl = malloc(2 * sizeof(char *)); - if (!sacl) { - printf("Error: no memory available for strdup\n"); - return -1; - } - sacl[0] = strdup(optarg); - sacl[1] = ""; - optSACL = 1; - numSACL = 1; - - break; - - case 'u': - default_uprefix = strdup(optarg); - debug("default_uprefix = %s\n", default_uprefix); - break; - - default: - return -1; - } - - return 0; -} - - -int -benchmark_initrun() -{ - int i; - debug("benchmark_initrun"); - - if (!sacl) { - sacl = default_sacl; - } - - for (i=0; strcmp(sacl[i], "") && i <= numSACL; i++) { - debug("SACL = %s", sacl[i]); - } - - return (0); -} - -// Initialize all structures that will be used in benchmark() -// 1. make local or network node for OD query -// 2. create user key -int -benchmark_initworker(void *tsd) -{ - int i; - tsd_t *ts = (tsd_t *)tsd; - char *uprefix = default_uprefix; // local user is default - char username[30] = ""; - struct passwd *info = NULL; - - debug("benchmark_initworker"); - - // create an array of usernames to use in benchmark before their use - // realtime generation in benchmark effects performance measurements - - ts->uuid_list = calloc(optRecords, sizeof(uuid_t)); - - for (i = 0; i < optRecords; i++) { - - sprintf(username, "%s%d", uprefix, i+1); - info = getpwnam(username); - if (!info) { - debug ("error converting username %s to uuid", username); - exit (1); - } - - (void) mbr_uid_to_uuid(info->pw_uid, ts->uuid_list[i]); - -#if DEBUG - char buf[30]; - uid_t uid; - int id_type; - uuid_unparse(ts->uuid_list[i], buf); - mbr_uuid_to_id(ts->uuid_list[i], &uid, &id_type); - debug ("username (%s), uid %d, uuid %s, back to uid %d", username, info->pw_uid, buf, uid); -#endif - } - - // if batch size (one benchmark run) is less than the number records, adjust - // it to match the number record lookups in one batch run - if (optRecords < lm_optB) { - lm_optB = optRecords; - debug("Reducing batch size to %d to match the record #\n", lm_optB); - } - - debug("benchmark_initworker"); - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - int err; - int isMember=0; - char *sacl_chosen; - -#ifdef DEBUG - uid_t uid; - int id_type; -#endif - - res->re_errors = 0; - - debug("in to benchmark - optB = %i", lm_optB); - for (i = 0; i < lm_optB; i++) { - - sacl_chosen = sacl[random() % numSACL]; - err = mbr_check_service_membership(ts->uuid_list[i], sacl_chosen, &isMember); - -#ifdef DEBUG - mbr_uuid_to_id(ts->uuid_list[i], &uid, &id_type); - debug ("loop %d: uid %d is %s a member of %s", i, uid, (isMember) ? "" : "not", sacl_chosen); -#endif - - if (err) { - debug("error: %s", strerror(err)); - res->re_errors++; - } - } - res->re_count = i; - - return (0); -} - - -// We need to release all the structures we allocated in benchmark_initworker() -int -benchmark_finiworker(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - debug("benchmark_result: deallocating structures"); - - free(ts->uuid_list); - - return (0); -} - -int -benchmark_finirun(void *tsd) -{ - if (optSACL) - free(sacl); - - return 0; -} - -char * -benchmark_result() -{ - static char result = '\0'; - debug("benchmark_result"); - return (&result); -} - diff --git a/tools/tests/libMicro/apple/od_query_create_with_node.c b/tools/tests/libMicro/apple/od_query_create_with_node.c deleted file mode 100644 index 7cf18ce6d..000000000 --- a/tools/tests/libMicro/apple/od_query_create_with_node.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#include -#include -#include -#include -#include - -// add additional headers needed here. - -#include "../libmicro.h" -#include -#include -#include -#include -#include - -#if DEBUG -# define debug(fmt, args...) (void) fprintf(stderr, fmt , ##args) -// # define debug(fmt, args...) (void) fprintf(stderr, fmt "\n" , ##args) -#else -# define debug(fmt, args...) -#endif - - -// Correct use case -// -// od_query_create_with_node -E -L -S -W -B 200 -C 10 -c 100 -r 300 -// -// libMicro default benchmark run options are "-E -C 200 -L -S -W" -// -// -B is batch size: loop iteration per each benchmark run. Needs to match # of -// real lookups. This is total number of lookups to issue. -// -C is min sample number: how many benchmark needs to run to get proper sample -// 1 is mimumum, but you get at least 3 benchmark run -// samples. Do not set to zero. Default is 200 for most -// runs in libMicro. -// -r is the number of total records. -// -c is the cache hit rate for lookup. set to 10%, you need -c 10. -// ie. -B 100 -c 50 -r 1000 -C 200 (out of 1000 records, I want 50% -// lookup, and batch size is 100. -// To get 50% cache hit rate, you need 500 record lookups. -// Batch size will be adjusted to 500 to get 500 record -// lookup in each benchmark. If -r size is smaller than -B, -// then -B will not be adjusted. - -// Defining prefix for user and group name -// make sure that these match the ones in LDAP records -// ie. local_test_1 , od_test_4525, od_test_group_43, od_test_host_63 -#define LOCAL_U_PREFIX CFSTR("local_test_") -#define OD_U_PREFIX CFSTR("od_test_") -#define LOCAL_G_PREFIX CFSTR("local_test_group_") -#define OD_G_PREFIX CFSTR("od_test_group_") -#define LOCAL_H_PREFIX CFSTR("local_test_host_") -#define OD_H_PREFIX CFSTR("od_test_host_") - -/* - * Your state variables should live in the tsd_t struct below - */ -typedef struct { - ODNodeRef node; -} tsd_t; - -// dsRecTypeStandard type dictionary -enum {rectype_users=0, rectype_groups, rectype_hosts}; -CFStringRef rectype_dict[] = { CFSTR(kDSStdRecordTypeUsers), - CFSTR(kDSStdRecordTypeGroups), - CFSTR(kDSStdRecordTypeHosts) }; - -// the number of record lookup to issue is covered by standard option optB -static int optRecords = 100; // the number of total records -static int optCachehit = 100; // specify cache hit rate (% of record re-lookup) -static bool optNodeLocal = 1; // which node to search. Local node is default -static int optType = rectype_users; // dsRecType to search for. "Users"" is the default -static const char *nodename = "/LDAPv3/127.0.0.1"; - -static CFStringRef *key; // username array - -// parse -t option and return enum type: user, group, and host -// called by benchmark_optswitch() -int -ds_rec_type(char *name) -{ - if (strcasecmp("u", name) == 0) { - return (rectype_users); - } else if (strcasecmp("g", name) == 0) { - return (rectype_groups); - } else if (strcasecmp("h", name) == 0) { - return (rectype_hosts); - } - - return (-1); -} - -int -benchmark_init() -{ - debug("benchmark_init"); - (void) sprintf(lm_optstr, "c:n:r:t:"); - - lm_tsdsize = sizeof (tsd_t); - lm_defB = 1000; - - (void) sprintf(lm_usage, - "\n ------- od_query_create_with_node specific options (default: *)\n" - " [-c hitrate%% (100%%*)]\n" - " [-r total number of records (100*)]\n" - " [-n nodename] node name to use for test\n" - " [-t record type: 'u'sers, 'g'roups, 'h'osts]\n" - " use -B option to specify total number of record lookups to issue" - "\n" ); - return (0); -} - -/* - * This is where you parse your lower-case arguments. - */ -int -benchmark_optswitch(int opt, char *optarg) -{ - debug("benchmark_optswitch"); - - switch (opt) { - case 'c': // cache hit rate. 100% means lookup the same records over and over - optCachehit = atoi(optarg); - debug("optCachehit = %d\n", optCachehit); - if (optCachehit > 100 || optCachehit < 0) { - printf("cache hit rate should be in between 0%% and 100%%"); - return (-1); - } - break; - - case 'r': // total number of records. default is 100 - optRecords = atoi(optarg); - debug("optRecords = %d\n", optRecords); - break; - - case 'n': // node - nodename = optarg; - break; - - case 't': // dsRecType: user, group, hots - optType = ds_rec_type(optarg); - debug("optType = %d\n", optType); - - if (optType == -1) { - printf("wrong -t record type option\n"); - return (-1); - } - break; - - default: - return (-1); - } - - return (0); -} - - -int -benchmark_initrun() -{ - int i; - CFStringRef prefix; // local user is default - - debug("benchmark_initrun\n"); - - // Adjust # of record lookups to reflect cache hit rate - if (optCachehit < 100) { - optRecords = (int) ((float) optRecords * ((float) optCachehit / 100)); - debug("# of records adjusted to %d for cache hit rate %d%%\n", optRecords, optCachehit); - } - - // if batch size (one benchmark run) is less than the number records, adjust - // it to match the number record lookups in one batch run - if (lm_optB < optRecords) { - lm_optB = optRecords; - debug("Adjusting batch size to %d to match the lookups required in benchmark run\n", lm_optB); - } - - switch (optType) { - case rectype_users: - prefix = (optNodeLocal) ? LOCAL_U_PREFIX : OD_U_PREFIX; - break; - case rectype_groups: - prefix = (optNodeLocal) ? LOCAL_G_PREFIX : OD_G_PREFIX; - break; - case rectype_hosts: - prefix = (optNodeLocal) ? LOCAL_H_PREFIX : OD_H_PREFIX; - break; - } - // create an array of usernames to use in benchmark before their use - // realtime generation in benchmark effects performance measurements - - key = malloc(sizeof(CFStringRef) * optRecords); - - // user, group, hosts key to lookup - switch (optType) { - - case rectype_users: // users query - case rectype_groups: // groups query - case rectype_hosts: // hosts query - for (i = 0; i < optRecords; i++) { - key[i] = CFStringCreateWithFormat( kCFAllocatorDefault, - NULL, - CFSTR("%@%d"), - prefix, - i+1); - // CFShow(key[i]); // print user name to check - } - break; - } - - return (0); -} - - -// Initialize all structures that will be used in benchmark() -// 1. make local or network node for OD query -// 2. create user key -int -benchmark_initworker(void *tsd) -{ - CFErrorRef error; - tsd_t *ts = (tsd_t *)tsd; - - debug("benchmark_initworker: %s", (optNodeLocal) ? "local" : "network"); - - - // create OD node for local or OD query - if (optNodeLocal) { - ts->node = ODNodeCreateWithNodeType(NULL, kODSessionDefault, kODNodeTypeLocalNodes, &error); - } - else { - CFStringRef nodenameStr = CFStringCreateWithCString(kCFAllocatorDefault, nodename, kCFStringEncodingUTF8); - ts->node = ODNodeCreateWithName(NULL, kODSessionDefault, nodenameStr, &error); - CFRelease(nodenameStr); - } - - if (!ts->node) { - debug("error calling ODNodeCreateWithNodeType\n"); - exit(1); - } - - CFRetain (ts->node); - - debug("benchmark_initworker: ODNodeRef = 0x%lx\n", ts->node); - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - - tsd_t *ts = (tsd_t *)tsd; - int i; - ODNodeRef node; - CFErrorRef error; - CFArrayRef results; - ODQueryRef query; - - res->re_errors = 0; - node = ts->node; - - debug("in to benchmark - optB = %i, node = 0x%lx \n", lm_optB, node); - for (i = 0; i < lm_optB; i++) { - - debug("loop %d: querying\n", i); - query = ODQueryCreateWithNode(NULL, - node, // inNode - rectype_dict[optType], // inRecordTypeOrList - CFSTR(kDSNAttrRecordName), // inAttribute - kODMatchInsensitiveEqualTo, // inMatchType - key[i % optRecords], // inQueryValueOrList - NULL, // inReturnAttributeOrList - 1, // inMaxResults - &error); - - if (query) { - // we do not want to factually fetch the result in benchmark run - // debug("loop %d: calling ODQueryCopyResults\n", i); - results = ODQueryCopyResults(query, FALSE, &error); - CFRelease(query); - if (results) { -#if DEBUG - int c; - c = CFArrayGetCount(results); - if (c > 0) { - debug("Successful run: %d results, ", c); - } - else { - debug("no result for "); - } - CFShow (key[i % optRecords]); - debug("\n"); -#endif - CFRelease(results); - } - else { - debug("loop %d: ODQueryCopyResults returned empty result for ", i); - res->re_errors++; - CFShow (key[i % optRecords]); - debug("\n"); - } // if (results) - - } // if (query) - else { - res->re_errors++; - } - } - res->re_count = i; - - return (0); -} - - -// We need to release all the structures we allocated in benchmark_initworker() -int -benchmark_finiworker(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - - debug("benchmark_result: deallocating structures\n"); - - // free the node - if (ts->node) - CFRelease (ts->node); - ts->node = NULL; - - return (0); -} - -int -benchmark_finirun() -{ - int i; - - for (i = 0; i < optRecords; i++){ - CFRelease(key[i]); - } - - free(key); - - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - debug("\n\n# of records adjusted to %d for cache hit rate %d%%\n", optRecords, optCachehit); - debug("benchmark_result\n"); - return (&result); -} - diff --git a/tools/tests/libMicro/apple/posix_spawn.c b/tools/tests/libMicro/apple/posix_spawn.c deleted file mode 100644 index dc5167ef6..000000000 --- a/tools/tests/libMicro/apple/posix_spawn.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2008 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -#ifdef __sun -#pragma ident "@(#)posix_spawn.c 1.0 08/21/08 Apple Inc." -#endif - -/* - * posix_spawn benchmark - */ - -#include -#include -#include -#include -#include -#include - -#include "../libmicro.h" - -static char exec_path[1024]; -static char *argv[3]; - -int -benchmark_init() -{ - lm_defB = 128; - lm_tsdsize = 0; - - (void) sprintf(lm_usage, - "notes: measures posix_spawn time of simple process()\n"); - - return (0); -} - -/*ARGSUSED*/ -int -benchmark_initbatch(void *tsd) -{ - char buffer[80]; - - (void) strcpy(exec_path, lm_procpath); - (void) strcat(exec_path, "/posix_spawn_bin"); - - (void) sprintf(buffer, "%d", lm_optB); - argv[0] = exec_path; - argv[1] = strdup(buffer); - argv[2] = NULL; - - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int c; - int pid; - int status; - - if (( c = posix_spawn(&pid, exec_path, NULL, NULL, argv, NULL) != 0)) - { - res->re_errors++; - } - - if (waitpid(pid, &status, 0) < 0) - { - res->re_errors++; - } - - if (WIFEXITED(status) && WEXITSTATUS(status) != 0) - { - res->re_errors++; - } - - res->re_count = lm_optB; - - return (0); -} diff --git a/tools/tests/libMicro/apple/posix_spawn_bin.c b/tools/tests/libMicro/apple/posix_spawn_bin.c deleted file mode 100644 index a5173367d..000000000 --- a/tools/tests/libMicro/apple/posix_spawn_bin.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2008 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -#ifdef __sun -#pragma ident "@(#)posix_spawn_bin.c 1.0 08/21/08 Apple Inc." -#endif - -/* - * time program to recursively test posix_spawn time - */ - -#include -#include -#include -#include -#include - -int -main(int argc, char *argv[]) -{ - int left; - int pid; - - if (argc == 1) { - exit(1); - } - - left = atoi(argv[1]); - - left--; - - if (left <= 0) { - exit(0); - } else { - char buffer[80]; - (void) sprintf(buffer, "%d", left); - argv[1] = buffer; - if (posix_spawn(&pid, argv[0], NULL, NULL, argv, NULL)) { - exit(2); - } - } - - return (0); -} diff --git a/tools/tests/libMicro/apple/trivial.c b/tools/tests/libMicro/apple/trivial.c deleted file mode 100644 index 97a051b26..000000000 --- a/tools/tests/libMicro/apple/trivial.c +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -/* - * Order of Execution - * - * benchmark_init - * - * benchmark_optswitch - * - * benchmark_initrun - * - * benchmark_initworker - * benchmark_initbatch - * benchmark - * benchmark_finibatch - * benchmark_initbatch - * benchmark - * benchmark_finibatch, etc. - * benchmark_finiworker - * - * benchmark_result - * - * benchmark_finirun - * - * benchmark_fini - */ - - - -#ifdef __sun -#pragma ident "@(#)trivial.c 1.0 08/17/06 Apple Inc." -#endif - - - -#include -#include -#include -#include -#include -// add additional headers needed here. - -#include "../libmicro.h" - -#if DEBUG -# define debug(fmt, args...) (void) fprintf(stderr, fmt "\n" , ##args) -#else -# define debug(fmt, args...) -#endif - -/* - * Your state variables should live in the tsd_t struct below - */ -typedef struct { - int ts_once; -} tsd_t; - -/* - * You can have any lower-case option you want to define. - * options are specified in the lm_optstr as either a - * single lower-case letter, or a single lower case letter - * with a colon after it. In this example, you can optionally - * specify -c {str} -e or -t {number} - * -c takes a string (quote the string if blanks) - * -e is a boolean - * -t takes a numeric - * argument. - */ -static char * optc; // allocated in benchmark_init, freed in benchmark_fini. -static bool opte = false; -static int optt = 1; - - -int -benchmark_init() -{ - debug("benchmark_init\n"); - /* - * the lm_optstr must be defined here or no options for you - * - * ...and the framework will throw an error - * - */ - (void) sprintf(lm_optstr, "c:et:"); - /* - * tsd_t is the state info struct that we pass around - * - * lm_tsdsize will allocate the space we need for this - * structure throughout the rest of the framework - */ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_usage, - " [-c string]\n" - " [-e] optional parameter\n" - " [-t int (default 1)]\n" - "notes: measures nothing\n"); - - optc = malloc(20); - return (0); -} - -/* - * This is where you parse your lower-case arguments. - * the format was defined in the lm_optstr assignment - * in benchmark_init - */ -int -benchmark_optswitch(int opt, char *optarg) -{ - debug("benchmark_optswitch\n"); - - switch (opt) { - case 'c': - strncpy(optc, optarg, 20); - debug("optc = %s\n", optc); - break; - case 'e': - opte = true; - debug("opte = %s\n", opte? "true": "false"); - break; - case 't': - optt = sizetoint(optarg); - debug("optt = %d\n", optt); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initrun() -{ - debug("benchmark_initrun\n"); - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - /* - * initialize your state variables here first - */ - tsd_t *ts = (tsd_t *)tsd; - ts->ts_once = optt; - debug("benchmark_initworker: ts_once = %i\n",ts->ts_once); - return (0); -} - -/*ARGSUSED*/ -int -benchmark_initbatch(void *tsd) -{ - /* - * initialize your state variables here second - */ - tsd_t *ts = (tsd_t *)tsd; - // useless code to show what you can do. - ts->ts_once++; - ts->ts_once--; - debug("benchmark_initbatch: ts_once = %i\n",ts->ts_once); - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - /* - * try not to initialize things here. This is the main - * loop of things to get timed. Start a server in - * benchmark_initbatch - */ - tsd_t *ts = (tsd_t *)tsd; - int i; - - debug("in to benchmark - optB = %i : ts_once = %i\n", lm_optB, ts->ts_once); - for (i = 0; i < lm_optB; i++) { - /* - * just to show that ts really contains state - */ - ts->ts_once++; - } - res->re_count = i; - debug("out of benchmark - optB = %i : ts_once = %i\n", lm_optB, ts->ts_once); - - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - /* - * more proof of state passing - */ - ts->ts_once = optt; - debug("benchmark_finibatch: ts_once = %i\n",ts->ts_once); - return (0); -} - -int -benchmark_finiworker(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - // useless code to show what you can do. - ts->ts_once++; - ts->ts_once--; - debug("benchmark_finiworker: ts_once = %i\n",ts->ts_once); - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - debug("benchmark_result\n"); - return (&result); -} - -int -benchmark_finirun() -{ - debug("benchmark_finirun\n"); - return (0); -} - - -int -benchmark_fini() -{ - debug("benchmark_fini\n"); - free(optc); - return (0); -} - diff --git a/tools/tests/libMicro/apple/vm_allocate.c b/tools/tests/libMicro/apple/vm_allocate.c deleted file mode 100644 index 0450f7a44..000000000 --- a/tools/tests/libMicro/apple/vm_allocate.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (c) 2006 Apple Inc. All Rights Reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - - -/* - * Order of Execution - * - * benchmark_init - * - * benchmark_optswitch - * - * benchmark_initrun - * - * benchmark_initworker - * benchmark_initbatch - * benchmark - * benchmark_finibatch - * benchmark_initbatch - * benchmark - * benchmark_finibatch, etc. - * benchmark_finiworker - * - * benchmark_result - * - * benchmark_finirun - * - * benchmark_fini - */ - - - -#ifdef __sun -#pragma ident "@(#)vm_allocate.c 1.0 09/17/06 Apple Inc." -#endif - - - -#include -#include -#include -#include -#include - -#include "../libmicro.h" - -/* - * Your state variables should live in the tsd_t struct below - */ -typedef struct { - int ts_once; -} tsd_t; - -unsigned char * arena; -unsigned int arenaSize = 1; - -static int optt = 0; - -/*ARGSUSED*/ -int -benchmark_initbatch(void *tsd) -{ - /* - * initialize your state variables here second - */ - //tsd_t *ts = (tsd_t *)tsd; - //(void) fprintf(stderr, "benchmark_initbatch: ts_once = %i\n",ts->ts_once); - return (0); -} - -int -benchmark_finirun() -{ - (void) fprintf(stderr, "benchmark_finirun\n"); - return (0); -} - -int -benchmark_init() -{ - (void) fprintf(stderr, "benchmark_init\n"); - /* - * the lm_optstr must be defined here or no options for you - * - * ...and the framework will throw an error - * - */ - (void) sprintf(lm_optstr, "t:"); - /* - * working hypothesis: - * - * tsd_t is the struct that we can pass around our - * state info in - * - * lm_tsdsize will allocate the space we need for this - * structure throughout the rest of the framework - */ - lm_tsdsize = sizeof (tsd_t); - lm_defB = 1; - - - (void) sprintf(lm_usage, - " [-t int (default 1)]\n" - "notes: measures nothing\n"); - return (0); -} - -int -benchmark_fini() -{ - (void) fprintf(stderr, "benchmark_fini\n"); - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - /* - * more proof of state passing - */ - ts->ts_once = optt; - //(void) fprintf(stderr, "benchmark_finibatch: ts_once = %i\n",ts->ts_once); - return (0); -} - -char * -benchmark_result() -{ - static char result = '\0'; - (void) fprintf(stderr, "benchmark_result\n"); - return (&result); -} - -int -benchmark_finiworker(void *tsd) -{ - //tsd_t *ts = (tsd_t *)tsd; - //(void) fprintf(stderr, "benchmark_finiworker: ts_once = %i\n",ts->ts_once); - //vm_deallocate( mach_task_self(), (vm_address_t) arena, arenaSize * vm_page_size); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - (void) fprintf(stderr, "benchmark_optswitch\n"); - - switch (opt) { - case 't': - optt = sizetoint(optarg); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - /* - * initialize your state variables here first - */ - //tsd_t *ts = (tsd_t *)tsd; - //ts->ts_once = optt; - //(void) fprintf(stderr, "benchmark_initworker: ts_once = %i\n",ts->ts_once); - if ( optt > 0 ) { - arenaSize = optt; - } - // warmup - vm_allocate( mach_task_self(), (vm_address_t *) &arena, arenaSize * vm_page_size, 1); - - vm_deallocate( mach_task_self(), (vm_address_t) arena, arenaSize * vm_page_size); - //arena = ( unsigned char * )malloc( arenaSize); - return (0); -} - -int -benchmark_initrun() -{ - //(void) fprintf(stderr, "benchmark_initrun\n"); - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - /* - * initialize your state variables here last - * - * and realize that you are paying for your initialization here - * and it is really a bad idea - */ - //tsd_t *ts = (tsd_t *)tsd; - int i; - - //(void) fprintf(stderr, "in to benchmark - optB = %i\n", lm_optB); - for (i = 0; i < lm_optB; i++) { - /* - * just to show that ts really contains state - */ - //(void) fprintf(stderr, "i is %i\n",i); - if (vm_allocate( mach_task_self(), (vm_address_t *) &arena, arenaSize * vm_page_size, 1)) - abort(); - if (vm_deallocate( mach_task_self(), (vm_address_t) arena, arenaSize * vm_page_size)) - abort(); - - } - res->re_count = i; - //(void) fprintf(stderr, "out of benchmark - optB = %i : ts_once = %i\n", lm_optB, ts->ts_once); - - return (0); -} diff --git a/tools/tests/libMicro/atomic.c b/tools/tests/libMicro/atomic.c deleted file mode 100644 index e005b4632..000000000 --- a/tools/tests/libMicro/atomic.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * benchmarks atomic add on Solaris - useful for platform comparisons. - */ - -#include -#include -#include -#include - -#include "libmicro.h" - -int -benchmark_init() -{ - (void) sprintf(lm_usage, "note: measures atomic_add_32_nv()"); - - lm_tsdsize = 0; - - return (0); -} - -static unsigned int value = 0; - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - unsigned int i; - for (i = 0; i < lm_optB; i += 10) { - (void) atomic_add_32_nv(&value, 1); - (void) atomic_add_32_nv(&value, 1); - (void) atomic_add_32_nv(&value, 1); - (void) atomic_add_32_nv(&value, 1); - (void) atomic_add_32_nv(&value, 1); - (void) atomic_add_32_nv(&value, 1); - (void) atomic_add_32_nv(&value, 1); - (void) atomic_add_32_nv(&value, 1); - (void) atomic_add_32_nv(&value, 1); - (void) atomic_add_32_nv(&value, 1); - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/bench.sh b/tools/tests/libMicro/bench.sh deleted file mode 100755 index de0582b41..000000000 --- a/tools/tests/libMicro/bench.sh +++ /dev/null @@ -1,811 +0,0 @@ -#!/bin/sh -# -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms -# of the Common Development and Distribution License -# (the "License"). You may not use this file except -# in compliance with the License. -# -# You can obtain a copy of the license at -# src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing -# permissions and limitations under the License. -# -# When distributing Covered Code, include this CDDL -# HEADER in each file and include the License file at -# usr/src/OPENSOLARIS.LICENSE. If applicable, -# add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your -# own identifying information: Portions Copyright [yyyy] -# [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - - -# usage function - defines all the options that can be given to this script. -function usage { - echo "Usage" - echo "$0 [-l] [-h] [name of test]" - echo "-l : This option runs the lmbench tests along with the default libmicro tests." - echo "-h : Help. This option displays information on how to run the script. " - echo "[name of test] : This option runs only the test that is specified" - echo "" - echo "Examples" - echo "$0 : This is the defualt execution. This will run only the default libmicro tests." - echo "$0 -l : This will run the lmbench tests too " - echo "$0 getppid : This will run only the getppid tests" - exit - -} - -if [ $# -eq 1 ] -then - lmbench=2 # to check if only a single test is to be run. e.g, ./bench.sh getppid -else - lmbench=0 # to run the default libMicro tests, without the lmbench tests. -fi - -while getopts "lh" OPT_LIST -do - case $OPT_LIST in - l) lmbench=1;; # to run the libmicro tests including the lmbench tests. - h) usage;; - *) usage;; - esac -done - - - -tattle="./tattle" - -bench_version=0.4.0 -libmicro_version=`$tattle -V` - -case $libmicro_version in -$bench_version) - ;; -*) - echo "ERROR: libMicro version doesn't match 'bench' script version" - exit 1 -esac - -TMPROOT=/private/tmp/libmicro.$$ -VARROOT=/private/var/tmp/libmicro.$$ -mkdir -p $TMPROOT -mkdir -p $VARROOT -trap "rm -rf $TMPROOT $VARROOT && exit" 0 2 - -TFILE=$TMPROOT/data -IFILE=$TMPROOT/ifile -TDIR1=$TMPROOT/0/1/2/3/4/5/6/7/8/9 -TDIR2=$TMPROOT/1/2/3/4/5/6/7/8/9/0 -VFILE=$VARROOT/data -VDIR1=$VARROOT/0/1/2/3/4/5/6/7/8/9 -VDIR2=$VARROOT/1/2/3/4/5/6/7/8/9/0 - - -OPTS="-E -C 200 -L -S -W" - -dd if=/dev/zero of=$TFILE bs=1024k count=10 2>/dev/null -dd if=/dev/zero of=$VFILE bs=1024k count=10 2>/dev/null -mkdir -p $TDIR1 $TDIR2 -mkdir -p $VDIR1 $VDIR2 - -touch $IFILE -/usr/bin/touch /private/var/tmp/lmbench - - -# produce benchmark header for easier comparisons - -hostname=`uname -n` - -if [ -f /usr/sbin/psrinfo ]; then - p_count=`psrinfo|wc -l` - p_mhz=`psrinfo -v | awk '/operates/{print $6 "MHz"; exit }'` - p_type=`psrinfo -vp 2>/dev/null | awk '{if (NR == 3) {print $0; exit}}'` - p_ipaddr=`getent hosts $hostname | awk '{print $1}'` -fi - -if [ -f /proc/cpuinfo ]; then - p_count=`egrep processor /proc/cpuinfo | wc -l` - p_mhz=`awk -F: '/cpu MHz/{printf("%5.0f00Mhz\n",$2/100); exit}' /proc/cpuinfo` - p_type=`awk -F: '/model name/{print $2; exit}' /proc/cpuinfo` - p_ipaddr=`getent hosts $hostname | awk '{print $1}'` -else -## Mac OS X specific stuff -# first, get ugly output, in case pretty output isn't available -# - p_count=`sysctl -n hw.physicalcpu` - p_mhz=`sysctl -n hw.cpufrequency` - p_type=`sysctl -n hw.model` - -if [ -x /usr/sbin/system_profiler ]; then - # requires this hunk of work-around - # grep the XML for the characteristic we need. The key appears twice, so grep for the useful key (with 'string') - # use sed to strip off the and the tabs in front of the string. So much work for so little result. - # - p_mhz=`system_profiler -xml -detailLevel mini SPHardwareDataType | \ - grep -A1 current_processor_speed | grep string | \ - sed -E 's/(.+)<\/string>/\1/' | sed 's- --g'` - p_type=`system_profiler -xml -detailLevel mini SPHardwareDataType | \ - grep -A1 cpu_type | grep string | \ - sed -E 's/(.+)<\/string>/\1/' | sed 's- --g'` -fi - -# look for en0 (usually ethernet) if that isn't there try en1 (usually wireless) else give up - p_ipaddr=`ipconfig getpacket en0 | grep yiaddr | tr "= " "\n" | grep [0-9]` - if [ ! $p_ipaddr ]; then - p_ipaddr=`ipconfig getpacket en1 | grep yiaddr | tr "= " "\n" | grep [0-9]` - elif [ ! $p_ipaddr ]; then - p_ipaddr="unknown" - fi -fi - -printf "\n\n!Libmicro_#: %30s\n" $libmicro_version -printf "!Options: %30s\n" "$OPTS" -printf "!Machine_name: %30s\n" "$hostname" -printf "!OS_name: %30s\n" `uname -s` -printf "!OS_release: %30s\n" `sw_vers -productVersion` -printf "!OS_build: %30.18s\n" "`sw_vers -buildVersion`" -printf "!Kernel: %30.50s\n" "`uname -v|cut -d ' ' -f 11`" -printf "!Processor: %30s\n" `arch` -printf "!#CPUs: %30s\n" $p_count -printf "!CPU_MHz: %30s\n" "$p_mhz" -printf "!CPU_NAME: %30s\n" "$p_type" -printf "!IP_address: %30s\n" "$p_ipaddr" -printf "!Run_by: %30s\n" $LOGNAME -printf "!Date: %30s\n" "`date '+%D %R'`" -printf "!Compiler: %30s\n" `$tattle -c` -printf "!Compiler Ver.:%30s\n" "`$tattle -v`" -printf "!sizeof(long): %30s\n" `$tattle -s` -printf "!extra_CFLAGS: %30s\n" "`$tattle -f`" -printf "!TimerRes: %30s\n\n\n" "`$tattle -r`" - -bin_dir="$TMPROOT/bin" - -mkdir -p $bin_dir -cp bin-*/exec_bin $bin_dir/$A - -cp ./apple/bin-*/posix_spawn_bin $bin_dir/$A - -newline=0 - -# -# Everything below the while loop is input for the while loop if -# you have any tests which can't run in the while loop, put -# them above this comment -# -while read A B -do - # $A contains the command, $B contains the arguments - # we echo blank lines and comments - # we skip anything which fails to match *$1* (useful if - # we only want to test one case, but a nasty hack) - - case $A in - \#*) - echo "$A $B" - newline=1 - continue - ;; - - "") - if [ $newline -eq 1 ] - then - newline=0 - echo - echo - fi - - continue - ;; - - *$1*) - # Default execution without the lmbench tests. - # checks if there is no argument passed by the user. - if [ $lmbench -eq 0 ] - then - string=lmbench - if [ "${A:0:7}" == "$string" ] - then - continue - fi - fi - - ;; - - *) - if [ $lmbench -ne 1 ] - then - continue - fi - ;; - esac - - if [ ! -f $bin_dir/$A ] - then - cp bin-*/$A $bin_dir/$A - fi - - echo - - (cd $TMPROOT && eval "bin/$A $B") - - echo - echo -done <<. - -# -# Obligatory null system call: use very short time -# for default since SuSe implements this "syscall" in userland -# - -getpid $OPTS -N "getpid" -I 5 -getppid $OPTS -N "getppid" -I 5 - -getenv $OPTS -N "getenv" -s 100 -I 100 -getenv $OPTS -N "getenvT2" -s 100 -I 100 -T 2 - -gettimeofday $OPTS -N "gettimeofday" - -log $OPTS -N "log" -I 20 -B 300000 -exp $OPTS -N "exp" -I 20 -B 100000 -lrand48 $OPTS -N "lrand48" - -memset $OPTS -N "memset_10" -s 10 -I 10 -memset $OPTS -N "memset_256" -s 256 -I 20 -memset $OPTS -N "memset_256_u" -s 256 -a 1 -I 20 -memset $OPTS -N "memset_1k" -s 1k -I 100 -B 2000 -memset $OPTS -N "memset_4k" -s 4k -I 250 -B 500 -memset $OPTS -N "memset_4k_uc" -s 4k -u -I 400 - -memset $OPTS -N "memset_10k" -s 10k -I 600 -B 500 -memset $OPTS -N "memset_1m" -s 1m -I 200000 -memset $OPTS -N "memset_10m" -s 10m -I 2000000 -memset $OPTS -N "memsetP2_10m" -s 10m -P 2 -I 2000000 - -memrand $OPTS -N "memrand" -s 40m -B 10000 - -# This is an elided test and is not ported yet. -# Check Makefile.darwin for list of elided tests -# cachetocache $OPTS -N "cachetocache" -s 100k -T 2 -I 200 - -isatty $OPTS -N "isatty_yes" -isatty $OPTS -N "isatty_no" -f $IFILE - -malloc $OPTS -N "malloc_10" -s 10 -g 10 -I 50 -malloc $OPTS -N "malloc_100" -s 100 -g 10 -I 50 -malloc $OPTS -N "malloc_1k" -s 1k -g 10 -I 50 -malloc $OPTS -N "malloc_10k" -s 10k -g 10 -I 50 -malloc $OPTS -N "malloc_100k" -s 100k -g 10 -I 2000 - -malloc $OPTS -N "mallocT2_10" -s 10 -g 10 -T 2 -I 200 -malloc $OPTS -N "mallocT2_100" -s 100 -g 10 -T 2 -I 200 -malloc $OPTS -N "mallocT2_1k" -s 1k -g 10 -T 2 -I 200 -malloc $OPTS -N "mallocT2_10k" -s 10k -g 10 -T 2 -I 200 -malloc $OPTS -N "mallocT2_100k" -s 100k -g 10 -T 2 -I 10000 - -close $OPTS -N "close_bad" -B 96 -b -close $OPTS -N "close_tmp" -B 64 -f $TFILE -close $OPTS -N "close_usr" -B 64 -f $VFILE -close $OPTS -N "close_zero" -B 64 -f /dev/zero -close_tcp $OPTS -N "close_tcp" -B 32 - -memcpy $OPTS -N "memcpy_10" -s 10 -I 10 -memcpy $OPTS -N "memcpy_1k" -s 1k -I 50 -memcpy $OPTS -N "memcpy_10k" -s 10k -I 800 -memcpy $OPTS -N "memcpy_1m" -s 1m -I 500000 -memcpy $OPTS -N "memcpy_10m" -s 10m -I 5000000 - -strcpy $OPTS -N "strcpy_10" -s 10 -I 5 -strcpy $OPTS -N "strcpy_1k" -s 1k -I 100 - -strlen $OPTS -N "strlen_10" -s 10 -I 5 -strlen $OPTS -N "strlen_1k" -s 1k -I 100 - -strchr $OPTS -N "strchr_10" -s 10 -I 5 -strchr $OPTS -N "strchr_1k" -s 1k -I 200 -strcmp $OPTS -N "strcmp_10" -s 10 -I 10 -strcmp $OPTS -N "strcmp_1k" -s 1k -I 200 - -strcasecmp $OPTS -N "scasecmp_10" -s 10 -I 50 -B 2000 -strcasecmp $OPTS -N "scasecmp_1k" -s 1k -I 20000 -B 100 - -strtol $OPTS -N "strtol" -I 20 - -# This is an elided test and is not ported yet. -# Check Makefile.darwin for list of elided tests -# getcontext $OPTS -N "getcontext" -I 100 - -# This is an elided test and is not ported yet. -# Check Makefile.darwin for list of elided tests -# setcontext $OPTS -N "setcontext" -I 100 - -mutex $OPTS -N "mutex_st" -I 10 -mutex $OPTS -N "mutex_mt" -t -I 10 -mutex $OPTS -N "mutex_T2" -T 2 -I 100 - -longjmp $OPTS -N "longjmp" -I 10 -siglongjmp $OPTS -N "siglongjmp" -I 20 - -getrusage $OPTS -N "getrusage" -I 200 - -times $OPTS -N "times" -I 200 -time $OPTS -N "time" -I 50 -localtime_r $OPTS -N "localtime_r" -I 200 -strftime $OPTS -N "strftime" -I 10000 -B 100 - -mktime $OPTS -N "mktime" -I 500 -mktime $OPTS -N "mktimeT2" -T 2 -I 1000 - -cascade_mutex $OPTS -N "c_mutex_1" -I 50 -cascade_mutex $OPTS -N "c_mutex_10" -T 10 -I 5000 -cascade_mutex $OPTS -N "c_mutex_200" -T 200 -I 2000000 - -cascade_cond $OPTS -N "c_cond_1" -I 100 -cascade_cond $OPTS -N "c_cond_10" -T 10 -I 3000 -cascade_cond $OPTS -N "c_cond_200" -T 200 -I 2000000 - -cascade_lockf $OPTS -N "c_lockf_1" -I 1000 -cascade_lockf $OPTS -N "c_lockf_10" -P 10 -I 50000 -cascade_lockf $OPTS -N "c_lockf_200" -P 200 -I 5000000 - -cascade_flock $OPTS -N "c_flock" -I 1000 -cascade_flock $OPTS -N "c_flock_10" -P 10 -I 50000 -cascade_flock $OPTS -N "c_flock_200" -P 200 -I 5000000 - -cascade_fcntl $OPTS -N "c_fcntl_1" -I 2000 -cascade_fcntl $OPTS -N "c_fcntl_10" -P 10 -I 20000 -cascade_fcntl $OPTS -N "c_fcntl_200" -P 200 -I 5000000 - -file_lock $OPTS -N "file_lock" -I 1000 - -getsockname $OPTS -N "getsockname" -I 100 -getpeername $OPTS -N "getpeername" -I 100 - -chdir $OPTS -N "chdir_tmp" -I 2000 $TDIR1 $TDIR2 -chdir $OPTS -N "chdir_usr" -I 2000 $VDIR1 $VDIR2 - -chdir $OPTS -N "chgetwd_tmp" -I 3000 -g $TDIR1 $TDIR2 -chdir $OPTS -N "chgetwd_usr" -I 3000 -g $VDIR1 $VDIR2 - -realpath $OPTS -N "realpath_tmp" -I 3000 -f $TDIR1 -realpath $OPTS -N "realpath_usr" -I 3000 -f $VDIR1 - -stat $OPTS -N "stat_tmp" -I 1000 -f $TFILE -stat $OPTS -N "stat_usr" -I 1000 -f $VFILE - -lmbench_stat $OPTS -N "lmbench_stat_tmp" -I 1000 -f $TFILE -lmbench_stat $OPTS -N "lmbench_stat_usr" -I 10000 -B 100 -f /private/var/tmp/lmbench - -# -# lmbench uses a touched empty file in /private/var/tmp -# libMicro uses a 1M file in a directory off /private/var/tmp -# performance difference is ~ 0.2 usecs/call -# -# why? - walking the dir tree, empty file vs. non-empty file, non-empty dir -# in the case of libMicro, etc., etc. -# - -lmbench_stat $OPTS -N "lmbench_stat_usr - Default" -I 10000 -B 100 -f /private/var/tmp/lmbench - -lmbench_fstat $OPTS -N "lmbench_fstat_tmp" -I 1000 -f $TFILE -lmbench_fstat $OPTS -N "lmbench_fstat_usr" -I 10000 -B 100 -f /private/var/tmp/lmbench - -# see stat test to understand why we are using /private/var/tmp/lmbench - -lmbench_fstat $OPTS -N "lmbench_fstat_usr - Default" -I 10000 -B 100 -f /private/var/tmp/lmbench - -lmbench_openclose $OPTS -N "lmbench_openclose - Default" -I 10000 -B 100 -f /private/var/tmp/lmbench - -lmbench_select_file $OPTS -N "lmbench_select_file_10" -n 10 -B 100 -lmbench_select_file $OPTS -N "lmbench_select_file_100" -n 100 -B 100 -lmbench_select_file $OPTS -N "lmbench_select_file_250" -n 250 -B 100 -lmbench_select_file $OPTS -N "lmbench_select_file_500" -n 500 -B 100 - -lmbench_select_tcp $OPTS -N "lmbench_select_tcp_10" -n 10 -B 100 -lmbench_select_tcp $OPTS -N "lmbench_select_tcp_100" -n 100 -B 100 -lmbench_select_tcp $OPTS -N "lmbench_select_tcp_250" -n 250 -B 100 -lmbench_select_tcp $OPTS -N "lmbench_select_tcp_500" -n 500 -B 100 - -fcntl $OPTS -N "fcntl_tmp" -I 100 -f $TFILE -fcntl $OPTS -N "fcntl_usr" -I 100 -f $VFILE -fcntl_ndelay $OPTS -N "fcntl_ndelay" -I 100 - -lseek $OPTS -N "lseek_t8k" -s 8k -I 50 -f $TFILE -lseek $OPTS -N "lseek_u8k" -s 8k -I 50 -f $VFILE - -open $OPTS -N "open_tmp" -B 256 -f $TFILE -open $OPTS -N "open_usr" -B 256 -f $VFILE -open $OPTS -N "open_zero" -B 256 -f /dev/zero - -dup $OPTS -N "dup" -B 512 - -socket $OPTS -N "socket_u" -B 256 -socket $OPTS -N "socket_i" -B 256 -f PF_INET - -socketpair $OPTS -N "socketpair" -B 256 - -setsockopt $OPTS -N "setsockopt" -I 200 - -bind $OPTS -N "bind" -B 100 - -listen $OPTS -N "listen" -B 100 - -#connection $OPTS -N "connection" -B 256 - -poll $OPTS -N "poll_10" -n 10 -I 500 -poll $OPTS -N "poll_100" -n 100 -I 1000 -poll $OPTS -N "poll_1000" -n 1000 -I 5000 - -poll $OPTS -N "poll_w10" -n 10 -I 500 -w 1 -poll $OPTS -N "poll_w100" -n 100 -I 2000 -w 10 -poll $OPTS -N "poll_w1000" -n 1000 -I 40000 -w 100 - -select $OPTS -N "select_10" -n 10 -I 500 -select $OPTS -N "select_100" -n 100 -I 1000 -select $OPTS -N "select_1000" -n 1000 -I 5000 - -select $OPTS -N "select_w10" -n 10 -I 500 -w 1 -select $OPTS -N "select_w100" -n 100 -I 2000 -w 10 -select $OPTS -N "select_w1000" -n 1000 -I 40000 -w 100 - -semop $OPTS -N "semop" -I 200 - -sigaction $OPTS -N "sigaction" -I 100 -signal $OPTS -N "signal" -I 1000 -sigprocmask $OPTS -N "sigprocmask" -I 200 - -lmbench_lat_sig_install $OPTS -N "lmbench_siginstall" -# sigcatch and sigsend need to be evaluated together -# lmbench framework will allow multiple measurements within the same -# benchmark test which allow them to factor out the cost of sending -# a signal from catching one -# -# for our purposes sigcatch results - sigsend results yield -# lmbench sig handler overhead measurements -lmbench_lat_sig_catch $OPTS -N "lmbench_sigcatch" -lmbench_lat_sig_send $OPTS -N "lmbench_sigsend" - - -pthread_create $OPTS -N "pthread_8" -B 8 -pthread_create $OPTS -N "pthread_32" -B 32 -pthread_create $OPTS -N "pthread_128" -B 128 -pthread_create $OPTS -N "pthread_512" -B 512 - -fork $OPTS -N "fork_10" -B 10 -fork $OPTS -N "fork_100" -B 100 -C 100 - -#fork $OPTS -N "fork_1000" -B 1000 -C 50 - -exit $OPTS -N "exit_10" -B 10 -exit $OPTS -N "exit_100" -B 100 - -#exit $OPTS -N "exit_1000" -B 1000 -C 50 - -exit $OPTS -N "exit_10_nolibc" -e -B 10 - -exec $OPTS -N "exec" -B 10 - -posix_spawn $OPTS -N "posix_spawn" -B 10 - -system $OPTS -N "system" -I 1000000 - -recurse $OPTS -N "recurse" -B 512 - -read $OPTS -N "read_t1k" -s 1k -B 50 -f $TFILE -read $OPTS -N "read_t10k" -s 10k -B 16 -f $TFILE -read $OPTS -N "read_t100k" -s 100k -B 4 -f $TFILE - -read $OPTS -N "read_u1k" -s 1k -B 50 -f $VFILE -read $OPTS -N "read_u10k" -s 10k -B 16 -f $VFILE -read $OPTS -N "read_u100k" -s 100k -B 4 -f $VFILE - -read $OPTS -N "read_z1k" -s 1k -B 100 -f /dev/zero -read $OPTS -N "read_z10k" -s 10k -B 30 -f /dev/zero -read $OPTS -N "read_z100k" -s 100k -B 4 -f /dev/zero -read $OPTS -N "read_zw100k" -s 100k -B 4 -w -f /dev/zero - -lmbench_read $OPTS -N "read_t1b" -s 1 -B 50 -f $TFILE -lmbench_read $OPTS -N "read_t1k" -s 1k -B 50 -f $TFILE -lmbench_read $OPTS -N "read_t10k" -s 10k -B 16 -f $TFILE -lmbench_read $OPTS -N "read_t100k" -s 100k -B 4 -f $TFILE - -lmbench_read $OPTS -N "read_u1b" -s 1 -B 50 -f $VFILE -lmbench_read $OPTS -N "read_u1k" -s 1k -B 50 -f $VFILE -lmbench_read $OPTS -N "read_u10k" -s 10k -B 16 -f $VFILE -lmbench_read $OPTS -N "read_u100k" -s 100k -B 4 -f $VFILE - -lmbench_read $OPTS -N "read_z1b - Default" -s 1 -B 100 -f /dev/zero -lmbench_read $OPTS -N "read_z1k" -s 1k -B 100 -f /dev/zero -lmbench_read $OPTS -N "read_z10k" -s 10k -B 30 -f /dev/zero -lmbench_read $OPTS -N "read_z100k" -s 100k -B 4 -f /dev/zero -lmbench_read $OPTS -N "read_zw100k" -s 100k -B 4 -w -f /dev/zero - -write $OPTS -N "write_t1k" -s 1k -B 50 -f $TFILE -write $OPTS -N "write_t10k" -s 10k -B 25 -f $TFILE -write $OPTS -N "write_t100k" -s 100k -B 4 -f $TFILE - -write $OPTS -N "write_u1k" -s 1k -B 50 -f $VFILE -write $OPTS -N "write_u10k" -s 10k -B 25 -f $VFILE -write $OPTS -N "write_u100k" -s 100k -B 4 -f $VFILE - -write $OPTS -N "write_n1k" -s 1k -I 100 -B 0 -f /dev/null -write $OPTS -N "write_n10k" -s 10k -I 100 -B 0 -f /dev/null -write $OPTS -N "write_n100k" -s 100k -I 100 -B 0 -f /dev/null - -lmbench_write $OPTS -N "lmbench_write_t1b" -s 1 -B 50 -f $TFILE -lmbench_write $OPTS -N "lmbench_write_t1k" -s 1k -B 50 -f $TFILE -lmbench_write $OPTS -N "lmbench_write_t10k" -s 10k -B 25 -f $TFILE -lmbench_write $OPTS -N "lmbench_write_t100k" -s 100k -B 4 -f $TFILE - -lmbench_write $OPTS -N "lmbench_write_u1b" -s 1 -B 50 -f $VFILE -lmbench_write $OPTS -N "lmbench_write_u1k" -s 1k -B 50 -f $VFILE -lmbench_write $OPTS -N "lmbench_write_u10k" -s 10k -B 25 -f $VFILE -lmbench_write $OPTS -N "lmbench_write_u100k" -s 100k -B 4 -f $VFILE - -lmbench_write $OPTS -N "lmbench_write_n1b - Default" -s 1 -I 100 -B 0 -f /dev/null -lmbench_write $OPTS -N "lmbench_write_n1k" -s 1k -I 100 -B 0 -f /dev/null -lmbench_write $OPTS -N "lmbench_write_n10k" -s 10k -I 100 -B 0 -f /dev/null -lmbench_write $OPTS -N "lmbench_write_n100k" -s 100k -I 100 -B 0 -f /dev/null - -writev $OPTS -N "writev_t1k" -s 1k -B 20 -f $TFILE -writev $OPTS -N "writev_t10k" -s 10k -B 4 -f $TFILE -writev $OPTS -N "writev_t100k" -s 100k -f $TFILE - -writev $OPTS -N "writev_u1k" -s 1k -B 20 -f $VFILE -writev $OPTS -N "writev_u10k" -s 10k -B 4 -f $VFILE -writev $OPTS -N "writev_u100k" -s 100k -f $VFILE - -writev $OPTS -N "writev_n1k" -s 1k -I 100 -B 0 -f /dev/null -writev $OPTS -N "writev_n10k" -s 10k -I 100 -B 0 -f /dev/null -writev $OPTS -N "writev_n100k" -s 100k -I 100 -B 0 -f /dev/null - -pread $OPTS -N "pread_t1k" -s 1k -I 300 -f $TFILE -pread $OPTS -N "pread_t10k" -s 10k -I 1000 -f $TFILE -pread $OPTS -N "pread_t100k" -s 100k -I 10000 -f $TFILE - -pread $OPTS -N "pread_u1k" -s 1k -I 300 -f $VFILE -pread $OPTS -N "pread_u10k" -s 10k -I 1000 -f $VFILE -pread $OPTS -N "pread_u100k" -s 100k -I 10000 -f $VFILE - -pread $OPTS -N "pread_z1k" -s 1k -I 300 -f /dev/zero -pread $OPTS -N "pread_z10k" -s 10k -I 1000 -f /dev/zero -pread $OPTS -N "pread_z100k" -s 100k -I 2000 -f /dev/zero -pread $OPTS -N "pread_zw100k" -s 100k -w -I 10000 -f /dev/zero - -pwrite $OPTS -N "pwrite_t1k" -s 1k -I 500 -f $TFILE -pwrite $OPTS -N "pwrite_t10k" -s 10k -I 1000 -f $TFILE -pwrite $OPTS -N "pwrite_t100k" -s 100k -I 10000 -f $TFILE - -pwrite $OPTS -N "pwrite_u1k" -s 1k -I 500 -f $VFILE -pwrite $OPTS -N "pwrite_u10k" -s 10k -I 1000 -f $VFILE -pwrite $OPTS -N "pwrite_u100k" -s 100k -I 20000 -f $VFILE - -pwrite $OPTS -N "pwrite_n1k" -s 1k -I 100 -f /dev/null -pwrite $OPTS -N "pwrite_n10k" -s 10k -I 100 -f /dev/null -pwrite $OPTS -N "pwrite_n100k" -s 100k -I 100 -f /dev/null - -mmap $OPTS -N "mmap_z8k" -l 8k -I 1000 -B 50 -f /dev/zero -mmap $OPTS -N "mmap_z128k" -l 128k -I 2000 -B 100 -f /dev/zero -mmap $OPTS -N "mmap_t8k" -l 8k -I 1000 -f $TFILE -mmap $OPTS -N "mmap_t128k" -l 128k -I 1000 -f $TFILE -mmap $OPTS -N "mmap_u8k" -l 8k -I 1000 -f $VFILE -mmap $OPTS -N "mmap_u128k" -l 128k -I 1000 -f $VFILE -mmap $OPTS -N "mmap_a8k" -l 8k -I 200 -f MAP_ANON -mmap $OPTS -N "mmap_a128k" -l 128k -I 200 -f MAP_ANON - - -mmap $OPTS -N "mmap_rz8k" -l 8k -I 2000 -r -f /dev/zero -mmap $OPTS -N "mmap_rz128k" -l 128k -I 2000 -r -f /dev/zero -mmap $OPTS -N "mmap_rt8k" -l 8k -I 2000 -r -f $TFILE -mmap $OPTS -N "mmap_rt128k" -l 128k -I 20000 -r -f $TFILE -mmap $OPTS -N "mmap_ru8k" -l 8k -I 2000 -r -f $VFILE -mmap $OPTS -N "mmap_ru128k" -l 128k -I 20000 -r -f $VFILE -mmap $OPTS -N "mmap_ra8k" -l 8k -I 2000 -r -f MAP_ANON -mmap $OPTS -N "mmap_ra128k" -l 128k -I 20000 -r -f MAP_ANON - -mmap $OPTS -N "mmap_wz8k" -l 8k -I 5000 -w -B 50 -f /dev/zero -mmap $OPTS -N "mmap_wz128k" -l 128k -I 50000 -w -B 50 -f /dev/zero -mmap $OPTS -N "mmap_wt8k" -l 8k -I 5000 -w -f $TFILE -mmap $OPTS -N "mmap_wt128k" -l 128k -I 50000 -w -f $TFILE -mmap $OPTS -N "mmap_wu8k" -l 8k -I 5000 -w -f $VFILE -mmap $OPTS -N "mmap_wu128k" -l 128k -I 500000 -w -f $VFILE -mmap $OPTS -N "mmap_wa8k" -l 8k -I 3000 -w -f MAP_ANON -mmap $OPTS -N "mmap_wa128k" -l 128k -I 50000 -w -f MAP_ANON - -munmap $OPTS -N "unmap_z8k" -l 8k -I 500 -f /dev/zero -munmap $OPTS -N "unmap_z128k" -l 128k -I 500 -B 100 -f /dev/zero -munmap $OPTS -N "unmap_t8k" -l 8k -I 500 -f $TFILE -munmap $OPTS -N "unmap_t128k" -l 128k -I 500 -f $TFILE -munmap $OPTS -N "unmap_u8k" -l 8k -I 500 -f $VFILE -munmap $OPTS -N "unmap_u128k" -l 128k -I 500 -f $VFILE -munmap $OPTS -N "unmap_a8k" -l 8k -I 500 -f MAP_ANON -munmap $OPTS -N "unmap_a128k" -l 128k -I 500 -f MAP_ANON - -munmap $OPTS -N "unmap_rz8k" -l 8k -I 1000 -r -f /dev/zero -munmap $OPTS -N "unmap_rz128k" -l 128k -I 2000 -r -B 100 -f /dev/zero -munmap $OPTS -N "unmap_rt8k" -l 8k -I 1000 -r -f $TFILE -munmap $OPTS -N "unmap_rt128k" -l 128k -I 3000 -r -f $TFILE -munmap $OPTS -N "unmap_ru8k" -l 8k -I 1000 -r -f $VFILE -munmap $OPTS -N "unmap_ru128k" -l 128k -I 3000 -r -f $VFILE -munmap $OPTS -N "unmap_ra8k" -l 8k -I 1000 -r -f MAP_ANON -munmap $OPTS -N "unmap_ra128k" -l 128k -I 2000 -r -f MAP_ANON - -connection $OPTS -N "conn_connect" -B 256 -c - -munmap $OPTS -N "unmap_wz8k" -l 8k -I 1000 -w -f /dev/zero -munmap $OPTS -N "unmap_wz128k" -l 128k -I 8000 -w -B 100 -f /dev/zero -munmap $OPTS -N "unmap_wt8k" -l 8k -I 1000 -w -f $TFILE -munmap $OPTS -N "unmap_wt128k" -l 128k -I 10000 -w -f $TFILE -munmap $OPTS -N "unmap_wu8k" -l 8k -I 1000 -w -f $VFILE -munmap $OPTS -N "unmap_wu128k" -l 128k -I 50000 -w -B 10 -f $VFILE -munmap $OPTS -N "unmap_wa8k" -l 8k -I 1000 -w -f MAP_ANON -munmap $OPTS -N "unmap_wa128k" -l 128k -I 10000 -w -f MAP_ANON - - -mprotect $OPTS -N "mprot_z8k" -l 8k -I 300 -f /dev/zero -mprotect $OPTS -N "mprot_z128k" -l 128k -I 500 -f /dev/zero -mprotect $OPTS -N "mprot_wz8k" -l 8k -I 500 -w -f /dev/zero -mprotect $OPTS -N "mprot_wz128k" -l 128k -I 1000 -w -f /dev/zero -mprotect $OPTS -N "mprot_twz8k" -l 8k -I 1000 -w -t -f /dev/zero -mprotect $OPTS -N "mprot_tw128k" -l 128k -I 2000 -w -t -f /dev/zero -mprotect $OPTS -N "mprot_tw4m" -l 4m -w -t -B 1 -f /dev/zero - -pipe $OPTS -N "pipe_pst1" -s 1 -I 1000 -x pipe -m st -pipe $OPTS -N "pipe_pmt1" -s 1 -I 8000 -x pipe -m mt -pipe $OPTS -N "pipe_pmp1" -s 1 -I 8000 -x pipe -m mp -pipe $OPTS -N "pipe_pst4k" -s 4k -I 1000 -x pipe -m st -pipe $OPTS -N "pipe_pmt4k" -s 4k -I 8000 -x pipe -m mt -pipe $OPTS -N "pipe_pmp4k" -s 4k -I 8000 -x pipe -m mp - -pipe $OPTS -N "pipe_sst1" -s 1 -I 1000 -x sock -m st -pipe $OPTS -N "pipe_smt1" -s 1 -I 8000 -x sock -m mt -pipe $OPTS -N "pipe_smp1" -s 1 -I 8000 -x sock -m mp -pipe $OPTS -N "pipe_sst4k" -s 4k -I 1000 -x sock -m st -pipe $OPTS -N "pipe_smt4k" -s 4k -I 8000 -x sock -m mt -pipe $OPTS -N "pipe_smp4k" -s 4k -I 8000 -x sock -m mp - -pipe $OPTS -N "pipe_tst1" -s 1 -I 1000 -x tcp -m st -pipe $OPTS -N "pipe_tmt1" -s 1 -I 8000 -x tcp -m mt -pipe $OPTS -N "pipe_tmp1" -s 1 -I 8000 -x tcp -m mp -pipe $OPTS -N "pipe_tst4k" -s 4k -I 1000 -x tcp -m st -pipe $OPTS -N "pipe_tmt4k" -s 4k -I 8000 -x tcp -m mt -pipe $OPTS -N "pipe_tmp4k" -s 4k -I 8000 -x tcp -m mp - -#connection $OPTS -N "conn_accept" -B 256 -a - -lmbench_bw_unix -B 11 -L -W - -lmbench_bw_mem $OPTS -N lmbench_bcopy_512 -s 512 -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_1k -s 1k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_2k -s 2k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_4k -s 4k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_8k -s 8k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_16k -s 16k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_32k -s 32k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_64k -s 64k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_128k -s 128k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_256k -s 256k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_512k -s 512k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_1m -s 1m -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bzero_512 -s 512 -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_1k -s 1k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_2k -s 2k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_4k -s 4k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_8k -s 8k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_16k -s 16k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_32k -s 32k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_64k -s 64k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_128k -s 128k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_256k -s 256k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_512k -s 512k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_1m -s 1m -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_512 -s 512 -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_1k -s 1k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_2k -s 2k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_4k -s 4k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_8k -s 8k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_16k -s 16k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_32k -s 32k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_64k -s 64k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_128k -s 128k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_256k -s 256k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_512k -s 512k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_1m -s 1m -x fcp -lmbench_bw_mem $OPTS -N lmbench_cp_512 -s 512 -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_1k -s 1k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_2k -s 2k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_4k -s 4k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_8k -s 8k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_16k -s 16k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_32k -s 32k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_64k -s 64k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_128k -s 128k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_256k -s 256k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_512k -s 512k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_1m -s 1m -x cp -lmbench_bw_mem $OPTS -N lmbench_frd_512 -s 512 -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_1k -s 1k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_2k -s 2k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_4k -s 4k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_8k -s 8k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_16k -s 16k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_32k -s 32k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_64k -s 64k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_128k -s 128k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_256k -s 256k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_512k -s 512k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_1m -s 1m -x frd -lmbench_bw_mem $OPTS -N lmbench_rd_512 -s 512 -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_1k -s 1k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_2k -s 2k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_4k -s 4k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_8k -s 8k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_16k -s 16k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_32k -s 32k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_64k -s 64k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_128k -s 128k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_256k -s 256k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_512k -s 512k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_1m -s 1m -x rd -lmbench_bw_mem $OPTS -N lmbench_fwr_512 -s 512 -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_1k -s 1k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_2k -s 2k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_4k -s 4k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_8k -s 8k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_16k -s 16k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_32k -s 32k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_64k -s 64k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_128k -s 128k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_256k -s 256k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_512k -s 512k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_1m -s 1m -x fwr -lmbench_bw_mem $OPTS -N lmbench_wr_512 -s 512 -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_1k -s 1k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_2k -s 2k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_4k -s 4k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_8k -s 8k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_16k -s 16k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_32k -s 32k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_64k -s 64k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_128k -s 128k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_256k -s 256k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_512k -s 512k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_1m -s 1m -x wr -lmbench_bw_mem $OPTS -N lmbench_rdwr_512 -s 512 -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_1k -s 1k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_2k -s 2k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_4k -s 4k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_8k -s 8k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_16k -s 16k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_32k -s 32k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_64k -s 64k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_128k -s 128k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_256k -s 256k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_512k -s 512k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_1m -s 1m -x rdwr - -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_512 -s 512 -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_1k -s 1k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_2k -s 2k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_4k -s 4k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_8k -s 8k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_16k -s 16k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_32k -s 32k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_64k -s 64k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_128k -s 128k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_256k -s 256k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_512k -s 512k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_1m -s 1m -f $TFILE - -. diff --git a/tools/tests/libMicro/benchDS.sh b/tools/tests/libMicro/benchDS.sh deleted file mode 100755 index cb583001b..000000000 --- a/tools/tests/libMicro/benchDS.sh +++ /dev/null @@ -1,324 +0,0 @@ -#!/bin/sh -# -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms -# of the Common Development and Distribution License -# (the "License"). You may not use this file except -# in compliance with the License. -# -# You can obtain a copy of the license at -# src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing -# permissions and limitations under the License. -# -# When distributing Covered Code, include this CDDL -# HEADER in each file and include the License file at -# usr/src/OPENSOLARIS.LICENSE. If applicable, -# add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your -# own identifying information: Portions Copyright [yyyy] -# [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -function usage { - echo "Usage" - echo "$0 [-l] [-h] <#-of-users> nodename [test match pattern]" - echo "-l : disable libinfo L1 cache" - echo "-h : Help. This option displays information on how to run the script. " - echo "[test match pattern] : This option runs only the test that is specified" - echo - echo "You must have set up users, groups, and SACLs with od_account_create" - echo "with the same number of user accounts." - echo "Supply a pattern to match to run a subset of tests" - exit 1 -} - -# default to libinfo cache enabled -L1CACHE="1" - -while getopts "lh" OPT_LIST -do - case $OPT_LIST in - l) L1CACHE="0";; # to run the libmicro tests with l1cache disabled - h) usage;; - *) usage;; - esac -done - -shift `expr $OPTIND - 1` - -if [ $# -lt 2 -o $# -gt 3 ]; then - usage -fi - -tattle="./tattle" - -bench_version=0.4.0 -libmicro_version=`$tattle -V` - -case $libmicro_version in -$bench_version) - ;; -*) - echo "ERROR: libMicro version doesn't match 'bench' script version" - exit 1 -esac - -TMPROOT=/private/tmp/libmicro.$$ -VARROOT=/private/var/tmp/libmicro.$$ -mkdir -p $TMPROOT -mkdir -p $VARROOT -trap "rm -rf $TMPROOT $VARROOT && exit" 0 2 - -TFILE=$TMPROOT/data -IFILE=$TMPROOT/ifile -TDIR1=$TMPROOT/0/1/2/3/4/5/6/7/8/9 -TDIR2=$TMPROOT/1/2/3/4/5/6/7/8/9/0 -VFILE=$VARROOT/data -VDIR1=$VARROOT/0/1/2/3/4/5/6/7/8/9 -VDIR2=$VARROOT/1/2/3/4/5/6/7/8/9/0 - -OPTS="-E -C 200 -L -S -W" - -dd if=/dev/zero of=$TFILE bs=1024k count=10 2>/dev/null -dd if=/dev/zero of=$VFILE bs=1024k count=10 2>/dev/null -mkdir -p $TDIR1 $TDIR2 -mkdir -p $VDIR1 $VDIR2 - -touch $IFILE -/usr/bin/touch /private/var/tmp/lmbench - - -# produce benchmark header for easier comparisons - -hostname=`uname -n` - -if [ -f /usr/sbin/psrinfo ]; then - p_count=`psrinfo|wc -l` - p_mhz=`psrinfo -v | awk '/operates/{print $6 "MHz"; exit }'` - p_type=`psrinfo -vp 2>/dev/null | awk '{if (NR == 3) {print $0; exit}}'` - p_ipaddr=`getent hosts $hostname | awk '{print $1}'` -fi - -if [ -f /proc/cpuinfo ]; then - p_count=`egrep processor /proc/cpuinfo | wc -l` - p_mhz=`awk -F: '/cpu MHz/{printf("%5.0f00Mhz\n",$2/100); exit}' /proc/cpuinfo` - p_type=`awk -F: '/model name/{print $2; exit}' /proc/cpuinfo` - p_ipaddr=`getent hosts $hostname | awk '{print $1}'` -else -## Mac OS X specific stuff -# first, get ugly output, in case pretty output isn't available -# - p_count=`sysctl -n hw.physicalcpu` - p_mhz=`sysctl -n hw.cpufrequency` - p_type=`sysctl -n hw.model` - -if [ -x /usr/sbin/system_profiler ]; then - # requires this hunk of work-around - # grep the XML for the characteristic we need. The key appears twice, so grep for the useful key (with 'string') - # use sed to strip off the and the tabs in front of the string. So much work for so little result. - # - p_mhz=`system_profiler -xml -detailLevel mini SPHardwareDataType | \ - grep -A1 current_processor_speed | grep string | \ - sed -E 's/(.+)<\/string>/\1/' | sed 's- --g'` - p_type=`system_profiler -xml -detailLevel mini SPHardwareDataType | \ - grep -A1 cpu_type | grep string | \ - sed -E 's/(.+)<\/string>/\1/' | sed 's- --g'` -fi - -# look for en0 (usually ethernet) if that isn't there try en1 (usually wireless) else give up - p_ipaddr=`ipconfig getpacket en0 | grep yiaddr | tr "= " "\n" | grep [0-9]` - if [ ! $p_ipaddr ]; then - p_ipaddr=`ipconfig getpacket en1 | grep yiaddr | tr "= " "\n" | grep [0-9]` - elif [ ! $p_ipaddr ]; then - p_ipaddr="unknown" - fi -fi - -printf "\n\n!Libmicro_#: %30s\n" $libmicro_version -printf "!Options: %30s\n" "$OPTS" -printf "!Machine_name: %30s\n" "$hostname" -printf "!OS_name: %30s\n" `uname -s` -printf "!OS_release: %30s\n" `sw_vers -productVersion` -printf "!OS_build: %30.18s\n" "`sw_vers -buildVersion`" -printf "!Processor: %30s\n" `arch` -printf "!#CPUs: %30s\n" $p_count -printf "!CPU_MHz: %30s\n" "$p_mhz" -printf "!CPU_NAME: %30s\n" "$p_type" -printf "!IP_address: %30s\n" "$p_ipaddr" -printf "!Run_by: %30s\n" $LOGNAME -printf "!Date: %30s\n" "`date '+%D %R'`" -printf "!Compiler: %30s\n" `$tattle -c` -printf "!Compiler Ver.:%30s\n" "`$tattle -v`" -printf "!sizeof(long): %30s\n" `$tattle -s` -printf "!extra_CFLAGS: %30s\n" "`$tattle -f`" -printf "!TimerRes: %30s\n\n\n" "`$tattle -r`" - -bin_dir="$TMPROOT/bin" - -mkdir -p $bin_dir -cp bin-*/exec_bin $bin_dir/$A - -cp ./apple/bin-*/posix_spawn_bin $bin_dir/$A - -newline=0 - -# We commonly want to adjust this script for the number of users -# and configuration of the accounts and configuration being tested. -# -# Users: -NUSERS=$1 -NODENAME=$2 -UID_BASE=5000 -UID_END=`expr $UID_BASE + $NUSERS - 1` -USER_PREFIX=od_test_ -# -# Groups: -GID_ALL_USERS=1211 -GID_NO_USERS=1212 -GROUP_BASE=od_test_group -# -# getaddrinfo on hosts: -HOST_BASE=sfs0 -HOST_RANGE=1-8 - -# -# Everything below the while loop is input for the while loop if -# you have any tests which can't run in the while loop, put -# them above this comment -# -while read A B -do - # $A contains the command, $B contains the arguments - # we echo blank lines and comments - # we skip anything which fails to match *$1* (useful if - # we only want to test one case, but a nasty hack) - - case $A in - \#*) - echo "$A $B" - newline=1 - continue - ;; - - "") - if [ $newline -eq 1 ] - then - newline=0 - echo - echo - fi - - continue - ;; - - *$3*) - ;; - - *) - continue - ;; - esac - - if [ ! -f $bin_dir/$A ] - then - cp bin-*/$A $bin_dir/$A - fi - - echo - - (cd $TMPROOT && eval "bin/$A $B") - - echo - echo -done <<. - -# -P <# procs> -# -T <# threads> - exclusive! - -# mbr_check_service_membership() -mbr_check_service_membership $OPTS -N "mbr_check_service_membership" -s libMicro -u ${USER_PREFIX} -r ${NUSERS} -mbr_check_service_membership $OPTS -N "mbr_check_service_membership_t2" -T 2 -s libMicro -u ${USER_PREFIX} -r ${NUSERS} -mbr_check_service_membership $OPTS -N "mbr_check_service_membership_t4" -T 4 -s libMicro -u ${USER_PREFIX} -r ${NUSERS} -mbr_check_service_membership $OPTS -N "mbr_check_service_membership_p2" -P 2 -s libMicro -u ${USER_PREFIX} -r ${NUSERS} -mbr_check_service_membership $OPTS -N "mbr_check_service_membership_p4" -P 4 -s libMicro -u ${USER_PREFIX} -r ${NUSERS} - -# getpwnam() -getpwnam $OPTS -N "getpwnam" -l ${L1CACHE} -r ${NUSERS} -u ${USER_PREFIX} -getpwnam $OPTS -N "getpwnam_t2" -T 2 -l ${L1CACHE} -r ${NUSERS} -u ${USER_PREFIX} -getpwnam $OPTS -N "getpwnam_p2" -P 2 -l ${L1CACHE} -r ${NUSERS} -u ${USER_PREFIX} - -# mbr_check_membership() -mbr_check_membership $OPTS -N "mbr_check_membership" -u ${UID_BASE}-${UID_END} -g ${GID_ALL_USERS}-${GID_NO_USERS} -mbr_check_membership $OPTS -N "mbr_check_membership_t2" -u ${UID_BASE}-${UID_END} -g ${GID_ALL_USERS}-${GID_NO_USERS} -T 2 -mbr_check_membership $OPTS -N "mbr_check_membership_t4" -u ${UID_BASE}-${UID_END} -g ${GID_ALL_USERS}-${GID_NO_USERS} -T 4 -mbr_check_membership $OPTS -N "mbr_check_membership_p2" -u ${UID_BASE}-${UID_END} -g ${GID_ALL_USERS}-${GID_NO_USERS} -P 2 -mbr_check_membership $OPTS -N "mbr_check_membership_p4" -u ${UID_BASE}-${UID_END} -g ${GID_ALL_USERS}-${GID_NO_USERS} -P 4 - -# getpwuid() -getpwuid $OPTS -N "getpwuid" -l ${L1CACHE} -u ${UID_BASE}-${UID_END} -getpwuid $OPTS -N "getpwuid_t2" -l ${L1CACHE} -u ${UID_BASE}-${UID_END} -T 2 -getpwuid $OPTS -N "getpwuid_t4" -l ${L1CACHE} -u ${UID_BASE}-${UID_END} -T 4 -getpwuid $OPTS -N "getpwuid_p2" -l ${L1CACHE} -u ${UID_BASE}-${UID_END} -P 2 -getpwuid $OPTS -N "getpwuid_p4" -l ${L1CACHE} -u ${UID_BASE}-${UID_END} -P 4 - -# getgrgid() -getgrgid $OPTS -N "getgrgid" -l ${L1CACHE} -g ${GID_ALL_USERS}-${GID_NO_USERS} -getgrgid $OPTS -N "getgrgid_t2" -l ${L1CACHE} -g ${GID_ALL_USERS}-${GID_NO_USERS} -T 2 -getgrgid $OPTS -N "getgrgid_t4" -l ${L1CACHE} -g ${GID_ALL_USERS}-${GID_NO_USERS} -T 4 -getgrgid $OPTS -N "getgrgid_p2" -l ${L1CACHE} -g ${GID_ALL_USERS}-${GID_NO_USERS} -P 2 -getgrgid $OPTS -N "getgrgid_p4" -l ${L1CACHE} -g ${GID_ALL_USERS}-${GID_NO_USERS} -P 4 - -# getpwent() -getpwent $OPTS -N "getpwent" -l ${L1CACHE} -getpwent $OPTS -N "getpwent_t2" -l ${L1CACHE} -T 2 -getpwent $OPTS -N "getpwent_t4" -l ${L1CACHE} -T 4 -getpwent $OPTS -N "getpwent_p2" -l ${L1CACHE} -P 2 -getpwent $OPTS -N "getpwent_p4" -l ${L1CACHE} -P 4 - -# getgrent() -getgrent $OPTS -N "getgrent" -l ${L1CACHE} -getgrent $OPTS -N "getgrent_t2" -l ${L1CACHE} -T 2 -getgrent $OPTS -N "getgrent_t4" -l ${L1CACHE} -T 4 -getgrent $OPTS -N "getgrent_p2" -l ${L1CACHE} -P 2 -getgrent $OPTS -N "getgrent_p4" -l ${L1CACHE} -P 4 - -# getaddrinfo() host -#getaddrinfo_host $OPTS -N "getaddrinfo_host" -r ${HOST_RANGE} -h ${HOST_BASE}%d -#getaddrinfo_host $OPTS -N "getaddrinfo_host_t2" -r ${HOST_RANGE} -h ${HOST_BASE}%d -T 2 -#getaddrinfo_host $OPTS -N "getaddrinfo_host_t4" -r ${HOST_RANGE} -h ${HOST_BASE}%d -T 4 -#getaddrinfo_host $OPTS -N "getaddrinfo_host_p2" -r ${HOST_RANGE} -h ${HOST_BASE}%d -P 2 -#getaddrinfo_host $OPTS -N "getaddrinfo_host_p4" -r ${HOST_RANGE} -h ${HOST_BASE}%d -P 4 - -# getaddrinfo() port -getaddrinfo_port $OPTS -N "getaddrinfo_port" -l ${L1CACHE} -getaddrinfo_port $OPTS -N "getaddrinfo_port_t2" -l ${L1CACHE} -T 2 -getaddrinfo_port $OPTS -N "getaddrinfo_port_t4" -l ${L1CACHE} -T 4 -getaddrinfo_port $OPTS -N "getaddrinfo_port_p2" -l ${L1CACHE} -P 2 -getaddrinfo_port $OPTS -N "getaddrinfo_port_p4" -l ${L1CACHE} -P 4 - -# getgrnam() -getgrnam $OPTS -N "getgrnam" -l ${L1CACHE} -g ${GROUP_BASE} -r 2 -getgrnam $OPTS -N "getgrnam_t2" -l ${L1CACHE} -T 2 -g ${GROUP_BASE} -r 2 -getgrnam $OPTS -N "getgrnam_t4" -l ${L1CACHE} -T 4 -g ${GROUP_BASE} -r 2 -getgrnam $OPTS -N "getgrnam_p2" -l ${L1CACHE} -P 2 -g ${GROUP_BASE} -r 2 -getgrnam $OPTS -N "getgrnam_p4" -l ${L1CACHE} -P 4 -g ${GROUP_BASE} -r 2 - -# ODQueryCreateWithNode() -od_query_create_with_node $OPTS -N "ODQueryCreateWithNode_cache_${NUSERS}u" -c 50 -r ${NUSERS} -t u -B 50 -n ${NODENAME} -od_query_create_with_node $OPTS -N "ODQueryCreateWithNode_cache_${NUSERS}u_t2" -T 2 -c 50 -r ${NUSERS} -t u -B 50 -n ${NODENAME} -od_query_create_with_node $OPTS -N "ODQueryCreateWithNode_cache_${NUSERS}u_t4" -T 4 -c 50 -r ${NUSERS} -t u -B 50 -n ${NODENAME} -od_query_create_with_node $OPTS -N "ODQueryCreateWithNode_cache_${NUSERS}u_p2" -P 2 -c 50 -r ${NUSERS} -t u -B 50 -n ${NODENAME} -od_query_create_with_node $OPTS -N "ODQueryCreateWithNode_cache_${NUSERS}u_p4" -P 4 -c 50 -r ${NUSERS} -t u -B 50 -n ${NODENAME} - -. diff --git a/tools/tests/libMicro/benchmark_fini.c b/tools/tests/libMicro/benchmark_fini.c deleted file mode 100644 index 4952a9ac0..000000000 --- a/tools/tests/libMicro/benchmark_fini.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * default implementation (nop) of benchmark_fini - */ - - -#include -#include -#include - -#include "libmicro.h" - -int -benchmark_fini() -{ - return (0); -} diff --git a/tools/tests/libMicro/benchmark_finibatch.c b/tools/tests/libMicro/benchmark_finibatch.c deleted file mode 100644 index 482258c7b..000000000 --- a/tools/tests/libMicro/benchmark_finibatch.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * default implementation (nop) of benchmark_finibatch - */ - -#include -#include -#include - -#include "libmicro.h" - -/*ARGSUSED*/ -int -benchmark_finibatch(void *tsd) -{ - return (0); -} diff --git a/tools/tests/libMicro/benchmark_finirun.c b/tools/tests/libMicro/benchmark_finirun.c deleted file mode 100644 index 52a582274..000000000 --- a/tools/tests/libMicro/benchmark_finirun.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * default implementation (nop) of benchmark_finirun - */ - -#include -#include -#include - -#include "libmicro.h" - -int -benchmark_finirun() -{ - return (0); -} diff --git a/tools/tests/libMicro/benchmark_finiworker.c b/tools/tests/libMicro/benchmark_finiworker.c deleted file mode 100644 index 53161eae0..000000000 --- a/tools/tests/libMicro/benchmark_finiworker.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * default implementation (nop) of benchmark_finiworker - */ - -#include -#include -#include - -#include "libmicro.h" - -/*ARGSUSED*/ -int -benchmark_finiworker(void *tsd) -{ - return (0); -} diff --git a/tools/tests/libMicro/benchmark_init.c b/tools/tests/libMicro/benchmark_init.c deleted file mode 100644 index 83cec2bf2..000000000 --- a/tools/tests/libMicro/benchmark_init.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * default implementation (nop) of benchmark_init - */ - - -#include -#include -#include - -#include "libmicro.h" - -int -benchmark_init() -{ - return (0); -} diff --git a/tools/tests/libMicro/benchmark_initbatch.c b/tools/tests/libMicro/benchmark_initbatch.c deleted file mode 100644 index 0a8cddd11..000000000 --- a/tools/tests/libMicro/benchmark_initbatch.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * default implementation (nop) of benchmark_initbatch - */ - - -#include -#include -#include - -#include "libmicro.h" - -/*ARGSUSED*/ -int -benchmark_initbatch(void *tsd) -{ - return (0); -} diff --git a/tools/tests/libMicro/benchmark_initrun.c b/tools/tests/libMicro/benchmark_initrun.c deleted file mode 100644 index ac437d4c2..000000000 --- a/tools/tests/libMicro/benchmark_initrun.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * default implementation (nop) of benchmark_initrun - */ - -#include -#include -#include - -#include "libmicro.h" - -int -benchmark_initrun() -{ - return (0); -} diff --git a/tools/tests/libMicro/benchmark_initworker.c b/tools/tests/libMicro/benchmark_initworker.c deleted file mode 100644 index 29b487c6a..000000000 --- a/tools/tests/libMicro/benchmark_initworker.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * default implementation (nop) of benchmark_initworker - */ - -#include -#include -#include - -#include "libmicro.h" - -/*ARGSUSED*/ -int -benchmark_initworker(void *tsd) -{ - return (0); -} diff --git a/tools/tests/libMicro/benchmark_optswitch.c b/tools/tests/libMicro/benchmark_optswitch.c deleted file mode 100644 index d46ee2fb6..000000000 --- a/tools/tests/libMicro/benchmark_optswitch.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * default implementation (nop) of benchmark_optswitch - */ - -#include -#include -#include - -#include "libmicro.h" - -/*ARGSUSED*/ -int -benchmark_optswitch(int opt, char *optarg) -{ - return (0); -} diff --git a/tools/tests/libMicro/benchmark_result.c b/tools/tests/libMicro/benchmark_result.c deleted file mode 100644 index c8ab2f209..000000000 --- a/tools/tests/libMicro/benchmark_result.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * default implementation (nop) of benchmark_result - */ - -#include -#include -#include - -#include "libmicro.h" - -char * -benchmark_result() -{ - static char result = '\0'; - - return (&result); -} diff --git a/tools/tests/libMicro/bind.c b/tools/tests/libMicro/bind.c deleted file mode 100644 index bd8e43b13..000000000 --- a/tools/tests/libMicro/bind.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * benchmark for bind... keep in mind tcp hash chain effects - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libmicro.h" - -#define FIRSTPORT 12345 - -typedef struct { - int *ts_lsns; - struct sockaddr_in *ts_adds; -} tsd_t; - -static int optz = -0; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - lm_defB = 256; - (void) sprintf(lm_optstr, "z"); - - (void) sprintf(lm_usage, - " [-z bind to port 0 rather than seq. number\n" - "notes: measures bind() on TCP"); - - return (0); -} - -int -benchmark_initrun() -{ - (void) setfdlimit(lm_optB * lm_optT + 10); - - return (0); -} - -/*ARGSUSED*/ -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'z': - optz = 1; - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i, j; - int opt = 1; - struct hostent *host; - int errors = 0; - - ts->ts_lsns = (int *)malloc(lm_optB * sizeof (int)); - if (ts->ts_lsns == NULL) - errors ++; - - ts->ts_adds = (struct sockaddr_in *)malloc(lm_optB * - sizeof (struct sockaddr_in)); - if (ts->ts_adds == NULL) - errors ++; - - j = FIRSTPORT; - for (i = 0; i < lm_optB; i++) { - if ((ts->ts_lsns[i] = socket(PF_INET, SOCK_STREAM, 0)) == -1) - errors ++; - - if (setsockopt(ts->ts_lsns[i], SOL_SOCKET, SO_REUSEADDR, - &opt, sizeof (int)) == -1) - errors ++; - - if ((host = gethostbyname("localhost")) == NULL) - errors ++; - - (void) memset(&ts->ts_adds[i], 0, - sizeof (struct sockaddr_in)); - ts->ts_adds[i].sin_family = AF_INET; - ts->ts_adds[i].sin_port = (optz ? 0 : htons(j++)); - (void) memcpy(&ts->ts_adds[i].sin_addr.s_addr, - host->h_addr_list[0], sizeof (struct in_addr)); - } - return (errors); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - for (i = 0; i < lm_optB; i++) { - if ((bind(ts->ts_lsns[i], - (struct sockaddr *)&ts->ts_adds[i], - sizeof (struct sockaddr_in)) != 0) && - (errno != EADDRINUSE)) - res->re_errors ++; - } - res->re_count = i; - - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - for (i = 0; i < lm_optB; i++) - (void) close(ts->ts_lsns[i]); - return (0); -} diff --git a/tools/tests/libMicro/cachetocache.c b/tools/tests/libMicro/cachetocache.c deleted file mode 100644 index ffe9ddf7a..000000000 --- a/tools/tests/libMicro/cachetocache.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * routine to benchmark cache-to-cache transfer times... uses - * solaris features to find and bind to cpus in the current - * processor set, so not likely to work elsewhere. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libmicro.h" - -static long opts = 1024*512; - -typedef struct { - long **ts_data; - long ts_result; - pthread_mutex_t ts_lock; -} tsd_t; - -static unsigned int ncpu = 1024; - -static tsd_t *thread_data[1024]; -static processorid_t cpus[1024]; - -int traverse_ptrchain(long **, int, int); - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "s:"); - - (void) sprintf(lm_usage, - " [-s size] size of access area in bytes" - " (default %ld)\n" - "notes: measures cache to cache transfer times on Solaris\n", - opts); - - (void) sprintf(lm_header, "%8s", "size"); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 's': - opts = sizetoint(optarg); - break; - default: - return (-1); - } - - return (0); -} - -int -benchmark_initrun() -{ - if (pset_info(PS_MYID, NULL, &ncpu, cpus) < 0) { - perror("pset_info"); - return (1); - } - - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i, j; - processorid_t cpu; - - ts->ts_data = malloc(opts); - - if (ts->ts_data == NULL) { - return (1); - } - - (void) pthread_mutex_init(&ts->ts_lock, NULL); - - - if (processor_bind(P_LWPID, P_MYID, - cpu = cpus[(pthread_self() - 1) % ncpu], - NULL) < 0) { - perror("processor_bind:"); - return (1); - } - - (void) printf("# thread %d using processor %d\n", pthread_self(), cpu); - - /* - * use lmbench style backwards stride - */ - - for (i = 0; i < opts / sizeof (long); i++) { - j = i - 128; - if (j < 0) - j = j + opts / sizeof (long); - ts->ts_data[i] = (long *)&(ts->ts_data[j]); - } - - thread_data[pthread_self() - 1] = ts; - - return (0); -} - -/* - * here we go in order for each thread, causing inherent serialization - * this is normally not a good idea, but in this case we're trying to - * measure cache-to-cache transfer times, and if we run threads in - * parallel we're likely to see saturation effects rather than cache-to-cache, - * esp. on wimpy memory platforms like P4. - */ - - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts; - int i, j; - int count = opts / 128 / sizeof (long); - - for (j = 0; j < lm_optB; j++) - for (i = 0; i < lm_optT; i++) { - ts = thread_data[i]; - (void) pthread_mutex_lock(&ts->ts_lock); - ts->ts_result += traverse_ptrchain( - (long **)ts->ts_data, count, 0); - (void) pthread_mutex_unlock(&ts->ts_lock); - } - - res->re_count = lm_optB * lm_optT * count; - - return (0); -} - -int -traverse_ptrchain(long **ptr, int count, int value) -{ - int i; - - for (i = 0; i < count; i += 10) { - *ptr = *ptr + value; - ptr = (long **)*ptr; - *ptr = *ptr + value; - ptr = (long **)*ptr; - *ptr = *ptr + value; - ptr = (long **)*ptr; - *ptr = *ptr + value; - ptr = (long **)*ptr; - *ptr = *ptr + value; - ptr = (long **)*ptr; - *ptr = *ptr + value; - ptr = (long **)*ptr; - *ptr = *ptr + value; - ptr = (long **)*ptr; - *ptr = *ptr + value; - ptr = (long **)*ptr; - *ptr = *ptr + value; - ptr = (long **)*ptr; - *ptr = *ptr + value; - ptr = (long **)*ptr; - *ptr = *ptr + value; - } - return ((int)*ptr); /* bogus return */ -} - - -char * -benchmark_result() -{ - static char result[256]; - - (void) sprintf(result, "%8ld ", opts); - - - return (result); -} diff --git a/tools/tests/libMicro/cascade_cond.c b/tools/tests/libMicro/cascade_cond.c deleted file mode 100644 index 350e3d6d8..000000000 --- a/tools/tests/libMicro/cascade_cond.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * The "cascade" test case is a multiprocess/multithread batten-passing model - * using lock primitives alone for synchronisation. Threads are arranged in a - * ring. Each thread has two locks of its own on which it blocks, and is able - * to manipulate the two locks belonging to the thread which follows it in the - * ring. - * - * The number of threads (nthreads) is specified by the generic libMicro -P/-T - * options. With nthreads == 1 (the default) the uncontended case can be timed. - * - * The main logic is generic and allows any simple blocking API to be tested. - * The API-specific component is clearly indicated. - */ - -#include -#include -#include -#include -#include - -#include "libmicro.h" - -typedef struct { - int ts_once; - int ts_id; - int ts_us0; /* our lock indices */ - int ts_us1; - int ts_them0; /* their lock indices */ - int ts_them1; -} tsd_t; - -static int nthreads; - -/* - * API-specific code BEGINS here - */ - -static int opto = 0; -static int opts = 0; -static int nlocks; -static pthread_mutex_t *mxs; -static pthread_cond_t *cvs; -static int *conds; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "os"); - - lm_defN = "cscd_cond"; - - (void) sprintf(lm_usage, - " [-o] (do signal outside mutex)\n" - " [-s] (force PTHREAD_PROCESS_SHARED)\n" - "notes: thread cascade using pthread_conds\n"); - - return (0); -} - -/*ARGSUSED*/ -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'o': - opto = 1; - break; - case 's': - opts = 1; - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initrun() -{ - int i; - int e = 0; - pthread_mutexattr_t ma; - pthread_condattr_t ca; - - nthreads = lm_optP * lm_optT; - nlocks = nthreads * 2; - /*LINTED*/ - mxs = (pthread_mutex_t *)mmap(NULL, - nlocks * sizeof (pthread_mutex_t), - PROT_READ | PROT_WRITE, - MAP_ANON | MAP_SHARED, - -1, 0L); - if (mxs == MAP_FAILED) { - return (1); - } - - /*LINTED*/ - cvs = (pthread_cond_t *)mmap(NULL, - nlocks * sizeof (pthread_cond_t), - PROT_READ | PROT_WRITE, - MAP_ANON | MAP_SHARED, - -1, 0L); - if (cvs == MAP_FAILED) { - return (1); - } - - /*LINTED*/ - conds = (int *)mmap(NULL, - nlocks * sizeof (pthread_cond_t), - PROT_READ | PROT_WRITE, - MAP_ANON | MAP_SHARED, - -1, 0L); - if (conds == MAP_FAILED) { - return (1); - } - - (void) pthread_mutexattr_init(&ma); - (void) pthread_condattr_init(&ca); - if (lm_optP > 1 || opts) { - (void) pthread_mutexattr_setpshared(&ma, - PTHREAD_PROCESS_SHARED); - (void) pthread_condattr_setpshared(&ca, - PTHREAD_PROCESS_SHARED); - } else { - (void) pthread_mutexattr_setpshared(&ma, - PTHREAD_PROCESS_PRIVATE); - (void) pthread_condattr_setpshared(&ca, - PTHREAD_PROCESS_PRIVATE); - } - - for (i = 0; i < nlocks; i++) { - (void) pthread_mutex_init(&mxs[i], &ma); - (void) pthread_cond_init(&cvs[i], &ca); - conds[i] = 0; - } - - return (e); -} - -int -block(int index) -{ - (void) pthread_mutex_lock(&mxs[index]); - while (conds[index] != 0) { - (void) pthread_cond_wait(&cvs[index], &mxs[index]); - } - conds[index] = 1; - (void) pthread_mutex_unlock(&mxs[index]); - - return (0); -} - -int -unblock(int index) -{ - (void) pthread_mutex_lock(&mxs[index]); - conds[index] = 0; - if (opto) { - (void) pthread_mutex_unlock(&mxs[index]); - (void) pthread_cond_signal(&cvs[index]); - } else { - (void) pthread_cond_signal(&cvs[index]); - (void) pthread_mutex_unlock(&mxs[index]); - } - return (0); -} - -/* - * API-specific code ENDS here - */ - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int e = 0; - - if (ts->ts_once == 0) { - int us, them; - -#if !defined(__APPLE__) - us = (getpindex() * lm_optT) + gettindex(); -#else - us = gettsdindex(tsd); -#endif /* __APPLE__ */ - - them = (us + 1) % (lm_optP * lm_optT); - - ts->ts_id = us; - - /* lock index asignment for us and them */ - ts->ts_us0 = (us * 2); - ts->ts_us1 = (us * 2) + 1; - if (us < nthreads - 1) { - /* straight-thru connection to them */ - ts->ts_them0 = (them * 2); - ts->ts_them1 = (them * 2) + 1; - } else { - /* cross-over connection to them */ - ts->ts_them0 = (them * 2) + 1; - ts->ts_them1 = (them * 2); - } - - ts->ts_once = 1; - } - - /* block their first move */ - e += block(ts->ts_them0); - - return (e); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - int e = 0; - - /* wait to be unblocked (id == 0 will not block) */ - e += block(ts->ts_us0); - - for (i = 0; i < lm_optB; i += 2) { - /* allow them to block us again */ - e += unblock(ts->ts_us0); - - /* block their next + 1 move */ - e += block(ts->ts_them1); - - /* unblock their next move */ - e += unblock(ts->ts_them0); - - /* wait for them to unblock us */ - e += block(ts->ts_us1); - - /* repeat with locks reversed */ - e += unblock(ts->ts_us1); - e += block(ts->ts_them0); - e += unblock(ts->ts_them1); - e += block(ts->ts_us0); - } - - /* finish batch with nothing blocked */ - e += unblock(ts->ts_them0); - e += unblock(ts->ts_us0); - - res->re_count = i; - res->re_errors = e; - - return (0); -} diff --git a/tools/tests/libMicro/cascade_fcntl.c b/tools/tests/libMicro/cascade_fcntl.c deleted file mode 100644 index b9bde5d14..000000000 --- a/tools/tests/libMicro/cascade_fcntl.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * The "cascade" test case is a multiprocess/multithread batten-passing model - * using lock primitives alone for synchronisation. Threads are arranged in a - * ring. Each thread has two locks of its own on which it blocks, and is able - * to manipulate the two locks belonging to the thread which follows it in the - * ring. - * - * The number of threads (nthreads) is specified by the generic libMicro -P/-T - * options. With nthreads == 1 (the default) the uncontended case can be timed. - * - * The main logic is generic and allows any simple blocking API to be tested. - * The API-specific component is clearly indicated. - */ - -#include -#include -#include -#include - -#include "libmicro.h" - -typedef struct { - int ts_once; - int ts_id; - int ts_us0; /* our lock indices */ - int ts_us1; - int ts_them0; /* their lock indices */ - int ts_them1; -} tsd_t; - -static int nthreads; - -/* - * API-specific code BEGINS here - */ - -#define DEFD "/private/tmp" - -static char *optd = DEFD; -static int file; -static int nlocks; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "d:"); - - lm_defN = "cscd_fcntl"; - - (void) sprintf(lm_usage, - " [-d directory for temp file (default %s)]\n" - "notes: thread cascade using fcntl region locking\n", - DEFD); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'd': - optd = optarg; - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initrun() -{ - int errors = 0; - char fname[1024]; - - nthreads = lm_optP * lm_optT; - nlocks = nthreads * 2; - - (void) sprintf(fname, "%s/cascade.%ld", optd, getpid()); - - file = open(fname, O_CREAT | O_TRUNC | O_RDWR, 0600); - if (file == -1) { - errors++; - } - - if (unlink(fname)) { - errors++; - } - - if (ftruncate(file, nlocks * 3) == -1) { - errors++; - } - - return (errors); -} - -int -block(int index) -{ - struct flock fl; - - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - fl.l_start = index; - fl.l_len = 1; - return (fcntl(file, F_SETLKW, &fl) == -1); -} - -int -unblock(int index) -{ - struct flock fl; - - fl.l_type = F_UNLCK; - fl.l_whence = SEEK_SET; - fl.l_start = index; - fl.l_len = 1; - return (fcntl(file, F_SETLK, &fl) == -1); -} - -/* - * API-specific code ENDS here - */ - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int e = 0; - - if (ts->ts_once == 0) { - int us, them; - -#if !defined(__APPLE__) - us = (getpindex() * lm_optT) + gettindex(); -#else - us = gettsdindex(tsd); -#endif /* __APPLE__ */ - - them = (us + 1) % (lm_optP * lm_optT); - - ts->ts_id = us; - - /* lock index asignment for us and them */ - ts->ts_us0 = (us * 4); - ts->ts_us1 = (us * 4) + 2; - if (us < nthreads - 1) { - /* straight-thru connection to them */ - ts->ts_them0 = (them * 4); - ts->ts_them1 = (them * 4) + 2; - } else { - /* cross-over connection to them */ - ts->ts_them0 = (them * 4) + 2; - ts->ts_them1 = (them * 4); - } - - ts->ts_once = 1; - } - - /* block their first move */ - e += block(ts->ts_them0); - - return (e); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - int e = 0; - - /* wait to be unblocked (id == 0 will not block) */ - e += block(ts->ts_us0); - - for (i = 0; i < lm_optB; i += 2) { - /* allow them to block us again */ - e += unblock(ts->ts_us0); - - /* block their next + 1 move */ - e += block(ts->ts_them1); - - /* unblock their next move */ - e += unblock(ts->ts_them0); - - /* wait for them to unblock us */ - e += block(ts->ts_us1); - - /* repeat with locks reversed */ - e += unblock(ts->ts_us1); - e += block(ts->ts_them0); - e += unblock(ts->ts_them1); - e += block(ts->ts_us0); - } - - /* finish batch with nothing blocked */ - e += unblock(ts->ts_them0); - e += unblock(ts->ts_us0); - - res->re_count = i; - res->re_errors = e; - - return (0); -} diff --git a/tools/tests/libMicro/cascade_flock.c b/tools/tests/libMicro/cascade_flock.c deleted file mode 100644 index e225b4076..000000000 --- a/tools/tests/libMicro/cascade_flock.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * The "cascade" test case is a multiprocess/multithread batten-passing model - * using lock primitives alone for synchronisation. Threads are arranged in a - * ring. Each thread has two locks of its own on which it blocks, and is able - * to manipulate the two locks belonging to the thread which follows it in the - * ring. - * - * The number of threads (nthreads) is specified by the generic libMicro -P/-T - * options. With nthreads == 1 (the default) the uncontended case can be timed. - * - * The main logic is generic and allows any simple blocking API to be tested. - * The API-specific component is clearly indicated. - */ - -#include -#include -#include -#include - -#include "libmicro.h" - -#ifndef LOCK_EX -#include "/usr/ucbinclude/sys/file.h" -extern int flock(int fd, int operation); -#endif - -typedef struct { - int ts_once; - int ts_id; - int ts_us0; /* our lock indices */ - int ts_us1; - int ts_them0; /* their lock indices */ - int ts_them1; -} tsd_t; - -static int nthreads; - -/* - * API-specific code BEGINS here - */ - -#define DEFD "/private/tmp" - -static char *optd = DEFD; -static int nfiles; -static int *files; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "d:"); - - lm_defN = "cscd_flock"; - - (void) sprintf(lm_usage, - " [-d directory for temp files (default %s)]\n" - "notes: thread cascade using flock file locking\n", - DEFD); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'd': - optd = optarg; - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initrun() -{ - int i; - int errors = 0; - char fname[1024]; - - nthreads = lm_optP * lm_optT; - nfiles = nthreads * 2; - (void) setfdlimit(nfiles + 10); - files = (int *)malloc(nfiles * sizeof (int)); - if (files == NULL) { - return (1); - } - - (void) sprintf(fname, "%s/cascade.%ld", optd, getpid()); - - for (i = 0; i < nfiles; i++) { - files[i] = open(fname, O_CREAT | O_TRUNC | O_RDWR, 0600); - if (files[i] == -1) { - errors++; - } - if (unlink(fname)) { - errors++; - } - } - - return (errors); -} - -int -block(int index) -{ - return (flock(files[index], LOCK_EX) == -1); -} - -int -unblock(int index) -{ - return (flock(files[index], LOCK_UN) == -1); -} - -/* - * API-specific code ENDS here - */ - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int e = 0; - - if (ts->ts_once == 0) { - int us, them; - -#if !defined(__APPLE__) - us = (getpindex() * lm_optT) + gettindex(); -#else - us = gettsdindex(tsd); -#endif /* __APPLE__ */ - - them = (us + 1) % (lm_optP * lm_optT); - - ts->ts_id = us; - - /* lock index asignment for us and them */ - ts->ts_us0 = (us * 2); - ts->ts_us1 = (us * 2) + 1; - if (us < nthreads - 1) { - /* straight-thru connection to them */ - ts->ts_them0 = (them * 2); - ts->ts_them1 = (them * 2) + 1; - } else { - /* cross-over connection to them */ - ts->ts_them0 = (them * 2) + 1; - ts->ts_them1 = (them * 2); - } - - ts->ts_once = 1; - } - - /* block their first move */ - e += block(ts->ts_them0); - - return (e); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - int e = 0; - - /* wait to be unblocked (id == 0 will not block) */ - e += block(ts->ts_us0); - - for (i = 0; i < lm_optB; i += 2) { - /* allow them to block us again */ - e += unblock(ts->ts_us0); - - /* block their next + 1 move */ - e += block(ts->ts_them1); - - /* unblock their next move */ - e += unblock(ts->ts_them0); - - /* wait for them to unblock us */ - e += block(ts->ts_us1); - - /* repeat with locks reversed */ - e += unblock(ts->ts_us1); - e += block(ts->ts_them0); - e += unblock(ts->ts_them1); - e += block(ts->ts_us0); - } - - /* finish batch with nothing blocked */ - e += unblock(ts->ts_them0); - e += unblock(ts->ts_us0); - - res->re_count = i; - res->re_errors = e; - - return (0); -} diff --git a/tools/tests/libMicro/cascade_lockf.c b/tools/tests/libMicro/cascade_lockf.c deleted file mode 100644 index 1792c0932..000000000 --- a/tools/tests/libMicro/cascade_lockf.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * The "cascade" test case is a multiprocess/multithread batten-passing model - * using lock primitives alone for synchronisation. Threads are arranged in a - * ring. Each thread has two locks of its own on which it blocks, and is able - * to manipulate the two locks belonging to the thread which follows it in the - * ring. - * - * The number of threads (nthreads) is specified by the generic libMicro -P/-T - * options. With nthreads == 1 (the default) the uncontended case can be timed. - * - * The main logic is generic and allows any simple blocking API to be tested. - * The API-specific component is clearly indicated. - */ - -#include -#include -#include -#include - -#include "libmicro.h" - -typedef struct { - int ts_once; - int ts_id; - int ts_us0; /* our lock indices */ - int ts_us1; - int ts_them0; /* their lock indices */ - int ts_them1; -} tsd_t; - -static int nthreads; - -/* - * API-specific code BEGINS here - */ - -#define DEFD "/private/tmp" - -static char *optd = DEFD; -static int nfiles; -static int *files; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "d:"); - - lm_defN = "cscd_lockf"; - - (void) sprintf(lm_usage, - " [-d directory for temp files (default %s)]\n" - "notes: thread cascade using lockf file locking\n", - DEFD); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'd': - optd = optarg; - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initrun() -{ - int i; - int errors = 0; - char fname[1024]; - - nthreads = lm_optP * lm_optT; - nfiles = nthreads * 2; - (void) setfdlimit(nfiles + 10); - files = (int *)malloc(nfiles * sizeof (int)); - if (files == NULL) { - return (1); - } - - (void) sprintf(fname, "%s/cascade.%ld", optd, getpid()); - - for (i = 0; i < nfiles; i++) { - files[i] = open(fname, O_CREAT | O_TRUNC | O_RDWR, 0600); - if (files[i] == -1) { - errors++; - } - if (unlink(fname)) { - errors++; - } - } - - return (errors); -} - -int -block(int index) -{ - return (lockf(files[index], F_LOCK, 0) == -1); -} - -int -unblock(int index) -{ - return (lockf(files[index], F_ULOCK, 0) == -1); -} - -/* - * API-specific code ENDS here - */ - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int e = 0; - - if (ts->ts_once == 0) { - int us, them; - -#if !defined(__APPLE__) - us = (getpindex() * lm_optT) + gettindex(); -#else - us = gettsdindex(tsd); -#endif /* __APPLE__ */ - - them = (us + 1) % (lm_optP * lm_optT); - - ts->ts_id = us; - - /* lock index asignment for us and them */ - ts->ts_us0 = (us * 2); - ts->ts_us1 = (us * 2) + 1; - if (us < nthreads - 1) { - /* straight-thru connection to them */ - ts->ts_them0 = (them * 2); - ts->ts_them1 = (them * 2) + 1; - } else { - /* cross-over connection to them */ - ts->ts_them0 = (them * 2) + 1; - ts->ts_them1 = (them * 2); - } - - ts->ts_once = 1; - } - - /* block their first move */ - e += block(ts->ts_them0); - - return (e); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - int e = 0; - - /* wait to be unblocked (id == 0 will not block) */ - e += block(ts->ts_us0); - - for (i = 0; i < lm_optB; i += 2) { - /* allow them to block us again */ - e += unblock(ts->ts_us0); - - /* block their next + 1 move */ - e += block(ts->ts_them1); - - /* unblock their next move */ - e += unblock(ts->ts_them0); - - /* wait for them to unblock us */ - e += block(ts->ts_us1); - - /* repeat with locks reversed */ - e += unblock(ts->ts_us1); - e += block(ts->ts_them0); - e += unblock(ts->ts_them1); - e += block(ts->ts_us0); - } - - /* finish batch with nothing blocked */ - e += unblock(ts->ts_them0); - e += unblock(ts->ts_us0); - - res->re_count = i; - res->re_errors = e; - - return (0); -} diff --git a/tools/tests/libMicro/cascade_mutex.c b/tools/tests/libMicro/cascade_mutex.c deleted file mode 100644 index 4f5807414..000000000 --- a/tools/tests/libMicro/cascade_mutex.c +++ /dev/null @@ -1,232 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * The "cascade" test case is a multiprocess/multithread batten-passing model - * using lock primitives alone for synchronisation. Threads are arranged in a - * ring. Each thread has two locks of its own on which it blocks, and is able - * to manipulate the two locks belonging to the thread which follows it in the - * ring. - * - * The number of threads (nthreads) is specified by the generic libMicro -P/-T - * options. With nthreads == 1 (the default) the uncontended case can be timed. - * - * The main logic is generic and allows any simple blocking API to be tested. - * The API-specific component is clearly indicated. - */ - -#include -#include -#include -#include -#include - -#include "libmicro.h" - -typedef struct { - int ts_once; - int ts_id; - int ts_us0; /* our lock indices */ - int ts_us1; - int ts_them0; /* their lock indices */ - int ts_them1; -} tsd_t; - -static int nthreads; - -/* - * API-specific code BEGINS here - */ - -static int opts = 0; -static int nlocks; -static pthread_mutex_t *locks; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "s"); - - lm_defN = "cscd_mutex"; - - (void) sprintf(lm_usage, - " [-s] (force PTHREAD_PROCESS_SHARED)\n" - "notes: thread cascade using pthread_mutexes\n"); - - return (0); -} - -/*ARGSUSED*/ -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 's': - opts = 1; - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initrun() -{ - int i; - int e = 0; - pthread_mutexattr_t ma; - - nthreads = lm_optP * lm_optT; - nlocks = nthreads * 2; - /*LINTED*/ - locks = (pthread_mutex_t *)mmap(NULL, - nlocks * sizeof (pthread_mutex_t), - PROT_READ | PROT_WRITE, - MAP_ANON | MAP_SHARED, - -1, 0L); - if (locks == MAP_FAILED) { - return (1); - } - - (void) pthread_mutexattr_init(&ma); - if (lm_optP > 1 || opts) { - (void) pthread_mutexattr_setpshared(&ma, - PTHREAD_PROCESS_SHARED); - } else { - (void) pthread_mutexattr_setpshared(&ma, - PTHREAD_PROCESS_PRIVATE); - } - - for (i = 0; i < nlocks; i++) { - (void) pthread_mutex_init(&locks[i], &ma); - } - - return (e); -} - -int -block(int index) -{ - return (pthread_mutex_lock(&locks[index]) == -1); -} - -int -unblock(int index) -{ - return (pthread_mutex_unlock(&locks[index]) == -1); -} - -/* - * API-specific code ENDS here - */ - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int e = 0; - - if (ts->ts_once == 0) { - int us, them; - -#if !defined(__APPLE__) - us = (getpindex() * lm_optT) + gettindex(); -#else - us = gettsdindex(tsd); -#endif /* __APPLE__ */ - - them = (us + 1) % (lm_optP * lm_optT); - - ts->ts_id = us; - - /* lock index asignment for us and them */ - ts->ts_us0 = (us * 2); - ts->ts_us1 = (us * 2) + 1; - if (us < nthreads - 1) { - /* straight-thru connection to them */ - ts->ts_them0 = (them * 2); - ts->ts_them1 = (them * 2) + 1; - } else { - /* cross-over connection to them */ - ts->ts_them0 = (them * 2) + 1; - ts->ts_them1 = (them * 2); - } - - ts->ts_once = 1; - } - - /* block their first move */ - e += block(ts->ts_them0); - - return (e); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - int e = 0; - - /* wait to be unblocked (id == 0 will not block) */ - e += block(ts->ts_us0); - - for (i = 0; i < lm_optB; i += 2) { - /* allow them to block us again */ - e += unblock(ts->ts_us0); - - /* block their next + 1 move */ - e += block(ts->ts_them1); - - /* unblock their next move */ - e += unblock(ts->ts_them0); - - /* wait for them to unblock us */ - e += block(ts->ts_us1); - - /* repeat with locks reversed */ - e += unblock(ts->ts_us1); - e += block(ts->ts_them0); - e += unblock(ts->ts_them1); - e += block(ts->ts_us0); - } - - /* finish batch with nothing blocked */ - e += unblock(ts->ts_them0); - e += unblock(ts->ts_us0); - - res->re_count = i; - res->re_errors = e; - - return (0); -} diff --git a/tools/tests/libMicro/chdir.c b/tools/tests/libMicro/chdir.c deleted file mode 100644 index a9ff379ca..000000000 --- a/tools/tests/libMicro/chdir.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * change directory benchmark - */ - -#include -#include -#include - -#include "libmicro.h" - -#define DEFAULTDIR "/" -#define MAXPATHLEN 1024 - -static int optg = 0; - -static int dircount; -static char ** dirlist; - -int -benchmark_init() -{ - (void) sprintf(lm_optstr, "g"); - lm_tsdsize = 0; - - (void) sprintf(lm_usage, - " [-g] (do getcwd() also)\n" - " directory ... (default = %s)\n" - "notes: measures chdir() and (optionally) getcwd()", - DEFAULTDIR); - - (void) sprintf(lm_header, "%5s %5s", "dirs", "gets"); - - return (0); -} - -/*ARGSUSED*/ -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'g': - optg = 1; - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initrun() -{ - extern int optind; - int i; - - dircount = lm_argc - optind; - if (dircount <= 0) { - dirlist = (char **)malloc(sizeof (char *)); - dirlist[0] = DEFAULTDIR; - dircount = 1; - } else { - dirlist = (char **)malloc(dircount * sizeof (char *)); - for (i = 0; i < dircount; i++) { - dirlist[i] = lm_argv[optind++]; - } - } - - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i, j; - char buf[MAXPATHLEN]; - - j = 0; - for (i = 0; i < lm_optB; i++) { - if (chdir(dirlist[j]) == -1) - res->re_errors++; - j++; - j %= dircount; - - if (optg && (getcwd(buf, MAXPATHLEN) == NULL)) { - res->re_errors++; - } - } - res->re_count = i; - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - - (void) sprintf(result, "%5d %5s", dircount, optg ? "y" : "n"); - - return (result); -} diff --git a/tools/tests/libMicro/close.c b/tools/tests/libMicro/close.c deleted file mode 100644 index 6050bcd50..000000000 --- a/tools/tests/libMicro/close.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * benchmark for close - */ - -#include -#include -#include -#include - -#include "libmicro.h" - -#define DEFF "/dev/null" -static char *optf = DEFF; -static int optb = 0; - -typedef struct { - int *ts_fds; -} tsd_t; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - lm_defB = 256; - - (void) sprintf(lm_optstr, "f:b"); - - (void) sprintf(lm_usage, - " [-f file-to-close (default %s)]\n" - " [-b] (try to close an unopened fd)\n" - "notes: measures close()", - DEFF); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'f': - optf = optarg; - break; - case 'b': - optb = 1; - break; - default: - return (-1); - } - - return (0); -} - -int -benchmark_initrun() -{ - (void) setfdlimit(lm_optB * lm_optT + 10); - - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - - ts->ts_fds = (int *)malloc(lm_optB * sizeof (int)); - if (ts->ts_fds == NULL) { - return (1); - } - return (0); -} - -/* - * don't need a finiworker; we're exiting anyway - */ - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - int errors = 0; - - for (i = 0; i < lm_optB; i++) { - ts->ts_fds[i] = ((optb == 0) ? - open(optf, O_RDONLY) : i + 1024); - if (ts->ts_fds[i] == -1) { - errors++; - } - } - - return (errors); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - for (i = 0; i < lm_optB; i++) { - if (close(ts->ts_fds[i]) == -1 && !optb) { - res->re_errors++; - } - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/close_tcp.c b/tools/tests/libMicro/close_tcp.c deleted file mode 100644 index 6bce7a73d..000000000 --- a/tools/tests/libMicro/close_tcp.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * benchmark to measure time to close a local tcp connection - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libmicro.h" - -#define FIRSTPORT 12345 - -typedef struct { - int *ts_lsns; - int *ts_accs; - int *ts_cons; - struct sockaddr_in *ts_adds; -} tsd_t; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - lm_defB = 256; - - (void) sprintf(lm_usage, - "notes: measures close() on local TCP connections"); - - return (0); -} - -int -benchmark_initrun() -{ - (void) setfdlimit(3 * lm_optB * lm_optT + 10); - - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i, j; - int opt = 1; - struct hostent *host; - int errors = 0; - - ts->ts_lsns = (int *)malloc(lm_optB * sizeof (int)); - if (ts->ts_lsns == NULL) { - errors ++; - } - ts->ts_accs = (int *)malloc(lm_optB * sizeof (int)); - if (ts->ts_accs == NULL) { - errors ++; - } - ts->ts_cons = (int *)malloc(lm_optB * sizeof (int)); - if (ts->ts_cons == NULL) { - errors ++; - } - ts->ts_adds = (struct sockaddr_in *)malloc(lm_optB * - sizeof (struct sockaddr_in)); - if (ts->ts_adds == NULL) { - errors ++; - } - - j = FIRSTPORT; - for (i = 0; i < lm_optB; i++) { - ts->ts_lsns[i] = socket(AF_INET, SOCK_STREAM, 0); - if (ts->ts_lsns[i] == -1) { - perror("socket"); - errors ++; - } - - if (setsockopt(ts->ts_lsns[i], SOL_SOCKET, SO_REUSEADDR, - &opt, sizeof (int)) == -1) { - perror("setsockopt"); - errors ++; - } - - if ((host = gethostbyname("localhost")) == NULL) { - errors ++; - } - - for (;;) { - (void) memset(&ts->ts_adds[i], 0, - sizeof (struct sockaddr_in)); - ts->ts_adds[i].sin_family = AF_INET; - ts->ts_adds[i].sin_port = htons(j++); - (void) memcpy(&ts->ts_adds[i].sin_addr.s_addr, - host->h_addr_list[0], sizeof (struct in_addr)); - - if (bind(ts->ts_lsns[i], - (struct sockaddr *)&ts->ts_adds[i], - sizeof (struct sockaddr_in)) == 0) { - break; - } - - if (errno != EADDRINUSE) { - perror("bind"); - errors ++; - } - } - - if (listen(ts->ts_lsns[i], 5) == -1) { - perror("listen"); - errors ++; - } - - } - return (errors); -} - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - int result; - struct sockaddr_in addr; - socklen_t size; - int errors = 0; - - for (i = 0; i < lm_optB; i++) { - ts->ts_cons[i] = socket(AF_INET, SOCK_STREAM, 0); - if (ts->ts_cons[i] == -1) { - perror("socket"); - errors ++; - continue; - } - - if (fcntl(ts->ts_cons[i], F_SETFL, O_NDELAY) == -1) { - perror("fcnt"); - errors ++; - continue; - } - - result = connect(ts->ts_cons[i], - (struct sockaddr *)&ts->ts_adds[i], - sizeof (struct sockaddr_in)); - - if ((result == -1) && (errno != EINPROGRESS)) { - perror("connect"); - errors ++; - continue; - } - - size = sizeof (struct sockaddr); - result = accept(ts->ts_lsns[i], (struct sockaddr *)&addr, - &size); - if (result == -1) { - perror("accept"); - errors ++; - continue; - } - ts->ts_accs[i] = result; - } - - return (errors); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - for (i = 0; i < lm_optB; i++) { - if (close(ts->ts_accs[i]) == -1) { - res->re_errors ++; - } - } - res->re_count = i; - - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - for (i = 0; i < lm_optB; i++) { - (void) close(ts->ts_cons[i]); - } - - return (0); -} - -int -benchmark_finiworker(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - for (i = 0; i < lm_optB; i++) { - (void) close(ts->ts_lsns[i]); - } - return (0); -} diff --git a/tools/tests/libMicro/connection.c b/tools/tests/libMicro/connection.c deleted file mode 100644 index 67239f9dd..000000000 --- a/tools/tests/libMicro/connection.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libmicro.h" - -#define FIRSTPORT 12345 - -typedef struct { - int ts_once; - int *ts_lsns; - int *ts_accs; - int *ts_cons; - struct sockaddr_in *ts_adds; -} tsd_t; - -static int opta = 0; -static int optc = 0; -static struct hostent *host; - -int -benchmark_init() -{ - lm_defB = 256; - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "ac"); - - (void) sprintf(lm_usage, - " [-a] (measure accept() only)\n" - " [-c] (measure connect() only)\n" - "notes: measures connect()/accept()\n"); - - return (0); -} - -/*ARGSUSED*/ -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'a': - opta = 1; - break; - case 'c': - optc = 1; - break; - default: - return (-1); - } - - if (opta && optc) { - (void) printf("warning: -a overrides -c\n"); - optc = 0; - } - - return (0); -} - -int -benchmark_initrun() -{ - (void) setfdlimit(3 * lm_optB * lm_optT + 10); - - return (0); -} - -int -benchmark_initbatch_once(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i, j; - - int errors = 0; - - ts->ts_lsns = (int *)malloc(lm_optB * sizeof (int)); - if (ts->ts_lsns == NULL) { - errors ++; - } - ts->ts_accs = (int *)malloc(lm_optB * sizeof (int)); - if (ts->ts_accs == NULL) { - errors ++; - } - ts->ts_cons = (int *)malloc(lm_optB * sizeof (int)); - if (ts->ts_cons == NULL) { - errors ++; - } - ts->ts_adds = - (struct sockaddr_in *)malloc(lm_optB * - sizeof (struct sockaddr_in)); - if (ts->ts_accs == NULL) { - errors ++; - } - - j = FIRSTPORT; - for (i = 0; i < lm_optB; i++) { - ts->ts_lsns[i] = socket(AF_INET, SOCK_STREAM, 0); - if (ts->ts_lsns[i] == -1) { - perror("socket"); - errors ++; - } - - /* - * make accept socket non-blocking so in case of errors - * we don't hang - */ - - if (fcntl(ts->ts_lsns[i], F_SETFL, O_NDELAY) == -1) { - perror("fcntl"); - errors ++; - } - - - if ((host = gethostbyname("localhost")) == NULL) { - errors ++; - } - - for (;;) { - (void) memset(&ts->ts_adds[i], 0, - sizeof (struct sockaddr_in)); - ts->ts_adds[i].sin_family = AF_INET; - ts->ts_adds[i].sin_port = htons(j++); - (void) memcpy(&ts->ts_adds[i].sin_addr.s_addr, - host->h_addr_list[0], sizeof (struct in_addr)); - - if (bind(ts->ts_lsns[i], - (struct sockaddr *)&ts->ts_adds[i], - sizeof (struct sockaddr_in)) == 0) { - break; - } - - if (errno != EADDRINUSE) { - errors ++; - } - } - - if (listen(ts->ts_lsns[i], 5) == -1) { - perror("listen"); - errors ++; - } - } - return (errors); -} - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - int errors = 0; - int result; - - if (ts->ts_once++ == 0) { - if (errors += benchmark_initbatch_once(tsd) == -1) { - return (-1); - } - } - - - for (i = 0; i < lm_optB; i++) { - ts->ts_cons[i] = socket(AF_INET, SOCK_STREAM, 0); - if (ts->ts_cons[i] == -1) { - perror("init:socket"); - errors ++; - } - - if (fcntl(ts->ts_cons[i], F_SETFL, O_NDELAY) == -1) { - perror("init:fcntl"); - errors ++; - } - - if (opta) { - result = connect(ts->ts_cons[i], - (struct sockaddr *)&ts->ts_adds[i], - sizeof (struct sockaddr_in)); - if ((result == -1) && (errno != EINPROGRESS)) { - perror("init:connect"); - errors ++; - } - } - } - - return (errors); -} - -int -benchmark(void *tsd, result_t *res) - - - -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - int result; - struct sockaddr_in addr; - socklen_t size; - - for (i = 0; i < lm_optB; i++) { - if (!opta) { - again: - result = connect(ts->ts_cons[i], - (struct sockaddr *)&ts->ts_adds[i], - sizeof (struct sockaddr_in)); - if (result != 0 && errno != EISCONN) { - if (errno == EINPROGRESS) { - struct pollfd pollfd; - if (optc) - continue; - pollfd.fd = ts->ts_cons[i]; - pollfd.events = POLLOUT; - if (poll(&pollfd, 1, -1) == 1) - goto again; - } - - res->re_errors ++; - perror("benchmark:connect"); - continue; - } - } - - if (!optc) { - size = sizeof (struct sockaddr); - for (;;) { - struct pollfd pollfd; - result = accept(ts->ts_lsns[i], - (struct sockaddr *)&addr, &size); - if (result > 0 || (result == -1 && - errno != EAGAIN)) - break; - pollfd.fd = ts->ts_lsns[i]; - pollfd.events = POLLIN; - if (poll(&pollfd, 1, -1) != 1) - break; - } - - ts->ts_accs[i] = result; - if (result == -1) { - res->re_errors ++; - perror("benchmark:accept"); - continue; - } - } - } - res->re_count = i; - - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - for (i = 0; i < lm_optB; i++) { - - if (!optc) { - (void) close(ts->ts_accs[i]); - } - (void) close(ts->ts_cons[i]); - } - - return (0); -} diff --git a/tools/tests/libMicro/coreos_bench.sh b/tools/tests/libMicro/coreos_bench.sh deleted file mode 100755 index a89205025..000000000 --- a/tools/tests/libMicro/coreos_bench.sh +++ /dev/null @@ -1,829 +0,0 @@ -#!/bin/sh -# -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms -# of the Common Development and Distribution License -# (the "License"). You may not use this file except -# in compliance with the License. -# -# You can obtain a copy of the license at -# src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing -# permissions and limitations under the License. -# -# When distributing Covered Code, include this CDDL -# HEADER in each file and include the License file at -# usr/src/OPENSOLARIS.LICENSE. If applicable, -# add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your -# own identifying information: Portions Copyright [yyyy] -# [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# usage function - defines all the options that can be given to this script. -function usage { - echo "Usage" - echo "$0 [-l] [-h] [name of test]" - echo "-l : This option runs the lmbench tests along with the default libmicro tests." - echo "-h : Help. This option displays information on how to run the script. " - echo "[name of test] : This option runs only the test that is specified" - echo "" - echo "Examples" - echo "$0 : This is the defualt execution. This will run only the default libmicro tests." - echo "$0 -l : This will run the lmbench tests too " - echo "$0 getppid : This will run only the getppid tests" - exit - -} - -if [ $# -eq 1 ] -then - lmbench=2 # to check if only a single test is to be run. e.g, ./coreos_bench.sh getppid -else - lmbench=0 # to run the default libMicro tests, without the lmbench tests. -fi - -while getopts "lh" OPT_LIST -do - case $OPT_LIST in - l) lmbench=1;; # to run the libmicro tests including the lmbench tests. - h) usage;; - *) usage;; - esac -done - - -tattle="./tattle" - -bench_version=0.4.0 -libmicro_version=`$tattle -V` - -case $libmicro_version in -$bench_version) - ;; -*) - echo "ERROR: libMicro version doesn't match 'coreos_bench' script version" - exit 1 -esac - -TMPROOT=/private/tmp/libmicro.$$ -VARROOT=/private/var/tmp/libmicro.$$ -mkdir -p $TMPROOT -mkdir -p $VARROOT - -#if 1 /* Apple modified code */ - -# If the testsuite finish completely or if it is interrupted before -# completion, re-enable stepper for normal operation of the machine -# see rdar://6243819 for details -trap "rm -rf $TMPROOT $VARROOT && sudo pstates -e && exit" 0 2 - -#else -trap "rm -rf $TMPROOT $VARROOT && exit" 0 2 -#endif /* End of Apple modified code - -TFILE=$TMPROOT/data -IFILE=$TMPROOT/ifile -TDIR1=$TMPROOT/0/1/2/3/4/5/6/7/8/9 -TDIR2=$TMPROOT/1/2/3/4/5/6/7/8/9/0 -VFILE=$VARROOT/data -VDIR1=$VARROOT/0/1/2/3/4/5/6/7/8/9 -VDIR2=$VARROOT/1/2/3/4/5/6/7/8/9/0 - - -OPTS="-E -C 200 -L -S -W" - -dd if=/dev/zero of=$TFILE bs=1024k count=10 2>/dev/null -dd if=/dev/zero of=$VFILE bs=1024k count=10 2>/dev/null -mkdir -p $TDIR1 $TDIR2 -mkdir -p $VDIR1 $VDIR2 - -touch $IFILE -/usr/bin/touch /private/var/tmp/lmbench - - -# produce benchmark header for easier comparisons - -hostname=`uname -n` - -if [ -f /usr/sbin/psrinfo ]; then - p_count=`psrinfo|wc -l` - p_mhz=`psrinfo -v | awk '/operates/{print $6 "MHz"; exit }'` - p_type=`psrinfo -vp 2>/dev/null | awk '{if (NR == 3) {print $0; exit}}'` - p_ipaddr=`getent hosts $hostname | awk '{print $1}'` -fi - -if [ -f /proc/cpuinfo ]; then - p_count=`egrep processor /proc/cpuinfo | wc -l` - p_mhz=`awk -F: '/cpu MHz/{printf("%5.0f00Mhz\n",$2/100); exit}' /proc/cpuinfo` - p_type=`awk -F: '/model name/{print $2; exit}' /proc/cpuinfo` - p_ipaddr=`getent hosts $hostname | awk '{print $1}'` -else -## Mac OS X specific stuff -# first, get ugly output, in case pretty output isn't available -# - p_count=`sysctl -n hw.physicalcpu` - p_mhz=`sysctl -n hw.cpufrequency` - p_type=`sysctl -n hw.model` - -if [ -x /usr/sbin/system_profiler ]; then - # requires this hunk of work-around - # grep the XML for the characteristic we need. The key appears twice, so grep for the useful key (with 'string') - # use sed to strip off the and the tabs in front of the string. So much work for so little result. - # - p_mhz=`system_profiler -xml -detailLevel mini SPHardwareDataType | \ - grep -A1 current_processor_speed | grep string | \ - sed -E 's/(.+)<\/string>/\1/' | sed 's- --g'` - p_type=`system_profiler -xml -detailLevel mini SPHardwareDataType | \ - grep -A1 cpu_type | grep string | \ - sed -E 's/(.+)<\/string>/\1/' | sed 's- --g'` -fi - -# look for en0 (usually ethernet) if that isn't there try en1 (usually wireless) else give up - p_ipaddr=`ipconfig getpacket en0 | grep yiaddr | tr "= " "\n" | grep [0-9]` - if [ ! $p_ipaddr ]; then - p_ipaddr=`ipconfig getpacket en1 | grep yiaddr | tr "= " "\n" | grep [0-9]` - elif [ ! $p_ipaddr ]; then - p_ipaddr="unknown" - fi -fi - -printf "\n\n!Libmicro_#: %30s\n" $libmicro_version -printf "!Options: %30s\n" "$OPTS" -printf "!Machine_name: %30s\n" "$hostname" -printf "!OS_name: %30s\n" `uname -s` -printf "!OS_release: %30s\n" `sw_vers -productVersion` -printf "!OS_build: %30.18s\n" "`sw_vers -buildVersion`" -printf "!Processor: %30s\n" `arch` -printf "!#CPUs: %30s\n" $p_count -printf "!CPU_MHz: %30s\n" "$p_mhz" -printf "!CPU_NAME: %30s\n" "$p_type" -printf "!IP_address: %30s\n" "$p_ipaddr" -printf "!Run_by: %30s\n" $LOGNAME -printf "!Date: %30s\n" "`date '+%D %R'`" -printf "!Compiler: %30s\n" `$tattle -c` -printf "!Compiler Ver.:%30s\n" "`$tattle -v`" -printf "!sizeof(long): %30s\n" `$tattle -s` -printf "!extra_CFLAGS: %30s\n" "`$tattle -f`" -printf "!TimerRes: %30s\n\n\n" "`$tattle -r`" - -bin_dir="$TMPROOT/bin" - -mkdir -p $bin_dir -cp bin-*/exec_bin $bin_dir/$A - -cp ./apple/bin-*/posix_spawn_bin $bin_dir/$A - -newline=0 - -#if 1 /* Apple added code */ - -# We need to disable the stepper to prevent it from causing -# wide variations in results; see rdar://6243819 for details - -pstates=/usr/local/bin/pstates -if [ -x $pstates ]; then - echo "Disabling stepper to provide more consistent results of benchmark run" - sudo $pstates -d; sudo pstates -p 0 -else - echo "ERROR: No $pstates found; To disable stepper we need $pstates" 1>&2 - echo "Install AppleInternal package which provides $pstates and execute 'coreos_bench' again" 1>&2 - echo 1>&2 - echo "Note: If you cannot install AppleInternal package which provides $pstates, then use 'bench' script to run libMicro testsuite" 1>&2 - exit 1 -fi - -#endif /* End of Apple code */ - -# -# Everything below the while loop is input for the while loop if -# you have any tests which can't run in the while loop, put -# them above this comment -# -while read A B -do - # $A contains the command, $B contains the arguments - # we echo blank lines and comments - # we skip anything which fails to match *$1* (useful if - # we only want to test one case, but a nasty hack) - - case $A in - \#*) - echo "$A $B" - newline=1 - continue - ;; - - "") - if [ $newline -eq 1 ] - then - newline=0 - echo - echo - fi - - continue - ;; - - *$1*) - # Default execution without the lmbench tests. - # checks if there is no argument passed by the user. - if [ $lmbench -eq 0 ] - then - string=lmbench - if [ "${A:0:7}" == "$string" ] - then - continue - fi - fi - - ;; - - *) - if [ $lmbench -ne 1 ] - then - continue - fi - ;; - esac - - if [ ! -f $bin_dir/$A ] - then - cp bin-*/$A $bin_dir/$A - fi - - echo - - (cd $TMPROOT && eval "bin/$A $B") - - echo - echo -done <<. - -# -# Obligatory null system call: use very short time -# for default since SuSe implements this "syscall" in userland -# - -getpid $OPTS -N "getpid" -I 5 -getppid $OPTS -N "getppid" -I 5 - -getenv $OPTS -N "getenv" -s 100 -I 100 -getenv $OPTS -N "getenvT2" -s 100 -I 100 -T 2 - -gettimeofday $OPTS -N "gettimeofday" - -log $OPTS -N "log" -I 20 -B 300000 -exp $OPTS -N "exp" -I 20 -B 100000 -lrand48 $OPTS -N "lrand48" - -memset $OPTS -N "memset_10" -s 10 -I 10 -memset $OPTS -N "memset_256" -s 256 -I 20 -memset $OPTS -N "memset_256_u" -s 256 -a 1 -I 20 -memset $OPTS -N "memset_1k" -s 1k -I 100 -B 2000 -memset $OPTS -N "memset_4k" -s 4k -I 250 -B 500 -memset $OPTS -N "memset_4k_uc" -s 4k -u -I 400 - -memset $OPTS -N "memset_10k" -s 10k -I 600 -B 500 -memset $OPTS -N "memset_1m" -s 1m -I 200000 -memset $OPTS -N "memset_10m" -s 10m -I 2000000 -memset $OPTS -N "memsetP2_10m" -s 10m -P 2 -I 2000000 - -memrand $OPTS -N "memrand" -s 40m -B 10000 - -# This is an elided test and is not ported yet. -# Check Makefile.darwin for list of elided tests -# cachetocache $OPTS -N "cachetocache" -s 100k -T 2 -I 200 - -isatty $OPTS -N "isatty_yes" -isatty $OPTS -N "isatty_no" -f $IFILE - -malloc $OPTS -N "malloc_10" -s 10 -g 10 -I 50 -malloc $OPTS -N "malloc_100" -s 100 -g 10 -I 50 -malloc $OPTS -N "malloc_1k" -s 1k -g 10 -I 50 -malloc $OPTS -N "malloc_10k" -s 10k -g 10 -I 50 -malloc $OPTS -N "malloc_100k" -s 100k -g 10 -I 2000 - -malloc $OPTS -N "mallocT2_10" -s 10 -g 10 -T 2 -I 200 -malloc $OPTS -N "mallocT2_100" -s 100 -g 10 -T 2 -I 200 -malloc $OPTS -N "mallocT2_1k" -s 1k -g 10 -T 2 -I 200 -malloc $OPTS -N "mallocT2_10k" -s 10k -g 10 -T 2 -I 200 -malloc $OPTS -N "mallocT2_100k" -s 100k -g 10 -T 2 -I 10000 - -close $OPTS -N "close_bad" -B 96 -b -close $OPTS -N "close_tmp" -B 64 -f $TFILE -close $OPTS -N "close_usr" -B 64 -f $VFILE -close $OPTS -N "close_zero" -B 64 -f /dev/zero -close_tcp $OPTS -N "close_tcp" -B 32 - -memcpy $OPTS -N "memcpy_10" -s 10 -I 10 -memcpy $OPTS -N "memcpy_1k" -s 1k -I 50 -memcpy $OPTS -N "memcpy_10k" -s 10k -I 800 -memcpy $OPTS -N "memcpy_1m" -s 1m -I 500000 -memcpy $OPTS -N "memcpy_10m" -s 10m -I 5000000 - -strcpy $OPTS -N "strcpy_10" -s 10 -I 5 -strcpy $OPTS -N "strcpy_1k" -s 1k -I 100 - -strlen $OPTS -N "strlen_10" -s 10 -I 5 -strlen $OPTS -N "strlen_1k" -s 1k -I 100 - -strchr $OPTS -N "strchr_10" -s 10 -I 5 -strchr $OPTS -N "strchr_1k" -s 1k -I 200 -strcmp $OPTS -N "strcmp_10" -s 10 -I 10 -strcmp $OPTS -N "strcmp_1k" -s 1k -I 200 - -strcasecmp $OPTS -N "scasecmp_10" -s 10 -I 50 -B 2000 -strcasecmp $OPTS -N "scasecmp_1k" -s 1k -I 20000 -B 100 - -strtol $OPTS -N "strtol" -I 20 - -# This is an elided test and is not ported yet. -# Check Makefile.darwin for list of elided tests -# getcontext $OPTS -N "getcontext" -I 100 - -# This is an elided test and is not ported yet. -# Check Makefile.darwin for list of elided tests -# setcontext $OPTS -N "setcontext" -I 100 - -mutex $OPTS -N "mutex_st" -I 10 -mutex $OPTS -N "mutex_mt" -t -I 10 -mutex $OPTS -N "mutex_T2" -T 2 -I 100 - -longjmp $OPTS -N "longjmp" -I 10 -siglongjmp $OPTS -N "siglongjmp" -I 20 - -getrusage $OPTS -N "getrusage" -I 200 - -times $OPTS -N "times" -I 200 -time $OPTS -N "time" -I 50 -localtime_r $OPTS -N "localtime_r" -I 200 -strftime $OPTS -N "strftime" -I 10000 -B 100 - -mktime $OPTS -N "mktime" -I 500 -mktime $OPTS -N "mktimeT2" -T 2 -I 1000 - -cascade_mutex $OPTS -N "c_mutex_1" -I 50 -cascade_mutex $OPTS -N "c_mutex_10" -T 10 -I 5000 -cascade_mutex $OPTS -N "c_mutex_200" -T 200 -I 2000000 - -cascade_cond $OPTS -N "c_cond_1" -I 100 -cascade_cond $OPTS -N "c_cond_10" -T 10 -I 3000 -cascade_cond $OPTS -N "c_cond_200" -T 200 -I 2000000 - -cascade_lockf $OPTS -N "c_lockf_1" -I 1000 -cascade_lockf $OPTS -N "c_lockf_10" -P 10 -I 50000 -cascade_lockf $OPTS -N "c_lockf_200" -P 200 -I 5000000 - -cascade_flock $OPTS -N "c_flock" -I 1000 -cascade_flock $OPTS -N "c_flock_10" -P 10 -I 50000 -cascade_flock $OPTS -N "c_flock_200" -P 200 -I 5000000 - -cascade_fcntl $OPTS -N "c_fcntl_1" -I 2000 -cascade_fcntl $OPTS -N "c_fcntl_10" -P 10 -I 20000 -cascade_fcntl $OPTS -N "c_fcntl_200" -P 200 -I 5000000 - -file_lock $OPTS -N "file_lock" -I 1000 - -getsockname $OPTS -N "getsockname" -I 100 -getpeername $OPTS -N "getpeername" -I 100 - -chdir $OPTS -N "chdir_tmp" -I 2000 $TDIR1 $TDIR2 -chdir $OPTS -N "chdir_usr" -I 2000 $VDIR1 $VDIR2 - -chdir $OPTS -N "chgetwd_tmp" -I 3000 -g $TDIR1 $TDIR2 -chdir $OPTS -N "chgetwd_usr" -I 3000 -g $VDIR1 $VDIR2 - -realpath $OPTS -N "realpath_tmp" -I 3000 -f $TDIR1 -realpath $OPTS -N "realpath_usr" -I 3000 -f $VDIR1 - -stat $OPTS -N "stat_tmp" -I 1000 -f $TFILE -stat $OPTS -N "stat_usr" -I 1000 -f $VFILE - -lmbench_stat $OPTS -N "lmbench_stat_tmp" -I 1000 -f $TFILE -lmbench_stat $OPTS -N "lmbench_stat_usr" -I 10000 -B 100 -f /private/var/tmp/lmbench - -# -# lmbench uses a touched empty file in /private/var/tmp -# libMicro uses a 1M file in a directory off /private/var/tmp -# performance difference is ~ 0.2 usecs/call -# -# why? - walking the dir tree, empty file vs. non-empty file, non-empty dir -# in the case of libMicro, etc., etc. -# - -lmbench_stat $OPTS -N "lmbench_stat_usr - Default" -I 10000 -B 100 -f /private/var/tmp/lmbench - -lmbench_fstat $OPTS -N "lmbench_fstat_tmp" -I 1000 -f $TFILE -lmbench_fstat $OPTS -N "lmbench_fstat_usr" -I 10000 -B 100 -f /private/var/tmp/lmbench - -# see stat test to understand why we are using /private/var/tmp/lmbench - -lmbench_fstat $OPTS -N "lmbench_fstat_usr - Default" -I 10000 -B 100 -f /private/var/tmp/lmbench - -lmbench_openclose $OPTS -N "lmbench_openclose - Default" -I 10000 -B 100 -f /private/var/tmp/lmbench - -lmbench_select_file $OPTS -N "lmbench_select_file_10" -n 10 -B 100 -lmbench_select_file $OPTS -N "lmbench_select_file_100" -n 100 -B 100 -lmbench_select_file $OPTS -N "lmbench_select_file_250" -n 250 -B 100 -lmbench_select_file $OPTS -N "lmbench_select_file_500" -n 500 -B 100 - -lmbench_select_tcp $OPTS -N "lmbench_select_tcp_10" -n 10 -B 100 -lmbench_select_tcp $OPTS -N "lmbench_select_tcp_100" -n 100 -B 100 -lmbench_select_tcp $OPTS -N "lmbench_select_tcp_250" -n 250 -B 100 -lmbench_select_tcp $OPTS -N "lmbench_select_tcp_500" -n 500 -B 100 - -fcntl $OPTS -N "fcntl_tmp" -I 100 -f $TFILE -fcntl $OPTS -N "fcntl_usr" -I 100 -f $VFILE -fcntl_ndelay $OPTS -N "fcntl_ndelay" -I 100 - -lseek $OPTS -N "lseek_t8k" -s 8k -I 50 -f $TFILE -lseek $OPTS -N "lseek_u8k" -s 8k -I 50 -f $VFILE - -open $OPTS -N "open_tmp" -B 256 -f $TFILE -open $OPTS -N "open_usr" -B 256 -f $VFILE -open $OPTS -N "open_zero" -B 256 -f /dev/zero - -dup $OPTS -N "dup" -B 512 - -socket $OPTS -N "socket_u" -B 256 -socket $OPTS -N "socket_i" -B 256 -f PF_INET - -socketpair $OPTS -N "socketpair" -B 256 - -setsockopt $OPTS -N "setsockopt" -I 200 - -bind $OPTS -N "bind" -B 100 - -listen $OPTS -N "listen" -B 100 - -#connection $OPTS -N "connection" -B 256 - -poll $OPTS -N "poll_10" -n 10 -I 500 -poll $OPTS -N "poll_100" -n 100 -I 1000 -poll $OPTS -N "poll_1000" -n 1000 -I 5000 - -poll $OPTS -N "poll_w10" -n 10 -I 500 -w 1 -poll $OPTS -N "poll_w100" -n 100 -I 2000 -w 10 -poll $OPTS -N "poll_w1000" -n 1000 -I 40000 -w 100 - -select $OPTS -N "select_10" -n 10 -I 500 -select $OPTS -N "select_100" -n 100 -I 1000 -select $OPTS -N "select_1000" -n 1000 -I 5000 - -select $OPTS -N "select_w10" -n 10 -I 500 -w 1 -select $OPTS -N "select_w100" -n 100 -I 2000 -w 10 -select $OPTS -N "select_w1000" -n 1000 -I 40000 -w 100 - -semop $OPTS -N "semop" -I 200 - -sigaction $OPTS -N "sigaction" -I 100 -signal $OPTS -N "signal" -I 1000 -sigprocmask $OPTS -N "sigprocmask" -I 200 - -lmbench_lat_sig_install $OPTS -N "lmbench_siginstall" -# sigcatch and sigsend need to be evaluated together -# lmbench framework will allow multiple measurements within the same -# benchmark test which allow them to factor out the cost of sending -# a signal from catching one -# -# for our purposes sigcatch results - sigsend results yield -# lmbench sig handler overhead measurements -lmbench_lat_sig_catch $OPTS -N "lmbench_sigcatch" -lmbench_lat_sig_send $OPTS -N "lmbench_sigsend" - - -pthread_create $OPTS -N "pthread_8" -B 8 -pthread_create $OPTS -N "pthread_32" -B 32 -pthread_create $OPTS -N "pthread_128" -B 128 -pthread_create $OPTS -N "pthread_512" -B 512 - -fork $OPTS -N "fork_10" -B 10 -fork $OPTS -N "fork_100" -B 100 -C 100 - -#fork $OPTS -N "fork_1000" -B 1000 -C 50 - -exit $OPTS -N "exit_10" -B 10 -exit $OPTS -N "exit_100" -B 100 - -#exit $OPTS -N "exit_1000" -B 1000 -C 50 - -exit $OPTS -N "exit_10_nolibc" -e -B 10 - -exec $OPTS -N "exec" -B 10 - -posix_spawn $OPTS -N "posix_spawn" -B 10 - -system $OPTS -N "system" -I 1000000 - -recurse $OPTS -N "recurse" -B 512 - -read $OPTS -N "read_t1k" -s 1k -B 50 -f $TFILE -read $OPTS -N "read_t10k" -s 10k -B 16 -f $TFILE -read $OPTS -N "read_t100k" -s 100k -B 4 -f $TFILE - -read $OPTS -N "read_u1k" -s 1k -B 50 -f $VFILE -read $OPTS -N "read_u10k" -s 10k -B 16 -f $VFILE -read $OPTS -N "read_u100k" -s 100k -B 4 -f $VFILE - -read $OPTS -N "read_z1k" -s 1k -B 100 -f /dev/zero -read $OPTS -N "read_z10k" -s 10k -B 30 -f /dev/zero -read $OPTS -N "read_z100k" -s 100k -B 4 -f /dev/zero -read $OPTS -N "read_zw100k" -s 100k -B 4 -w -f /dev/zero - -lmbench_read $OPTS -N "read_t1b" -s 1 -B 50 -f $TFILE -lmbench_read $OPTS -N "read_t1k" -s 1k -B 50 -f $TFILE -lmbench_read $OPTS -N "read_t10k" -s 10k -B 16 -f $TFILE -lmbench_read $OPTS -N "read_t100k" -s 100k -B 4 -f $TFILE - -lmbench_read $OPTS -N "read_u1b" -s 1 -B 50 -f $VFILE -lmbench_read $OPTS -N "read_u1k" -s 1k -B 50 -f $VFILE -lmbench_read $OPTS -N "read_u10k" -s 10k -B 16 -f $VFILE -lmbench_read $OPTS -N "read_u100k" -s 100k -B 4 -f $VFILE - -lmbench_read $OPTS -N "read_z1b - Default" -s 1 -B 100 -f /dev/zero -lmbench_read $OPTS -N "read_z1k" -s 1k -B 100 -f /dev/zero -lmbench_read $OPTS -N "read_z10k" -s 10k -B 30 -f /dev/zero -lmbench_read $OPTS -N "read_z100k" -s 100k -B 4 -f /dev/zero -lmbench_read $OPTS -N "read_zw100k" -s 100k -B 4 -w -f /dev/zero - -write $OPTS -N "write_t1k" -s 1k -B 50 -f $TFILE -write $OPTS -N "write_t10k" -s 10k -B 25 -f $TFILE -write $OPTS -N "write_t100k" -s 100k -B 4 -f $TFILE - -write $OPTS -N "write_u1k" -s 1k -B 50 -f $VFILE -write $OPTS -N "write_u10k" -s 10k -B 25 -f $VFILE -write $OPTS -N "write_u100k" -s 100k -B 4 -f $VFILE - -write $OPTS -N "write_n1k" -s 1k -I 100 -B 0 -f /dev/null -write $OPTS -N "write_n10k" -s 10k -I 100 -B 0 -f /dev/null -write $OPTS -N "write_n100k" -s 100k -I 100 -B 0 -f /dev/null - -lmbench_write $OPTS -N "lmbench_write_t1b" -s 1 -B 50 -f $TFILE -lmbench_write $OPTS -N "lmbench_write_t1k" -s 1k -B 50 -f $TFILE -lmbench_write $OPTS -N "lmbench_write_t10k" -s 10k -B 25 -f $TFILE -lmbench_write $OPTS -N "lmbench_write_t100k" -s 100k -B 4 -f $TFILE - -lmbench_write $OPTS -N "lmbench_write_u1b" -s 1 -B 50 -f $VFILE -lmbench_write $OPTS -N "lmbench_write_u1k" -s 1k -B 50 -f $VFILE -lmbench_write $OPTS -N "lmbench_write_u10k" -s 10k -B 25 -f $VFILE -lmbench_write $OPTS -N "lmbench_write_u100k" -s 100k -B 4 -f $VFILE - -lmbench_write $OPTS -N "lmbench_write_n1b - Default" -s 1 -I 100 -B 0 -f /dev/null -lmbench_write $OPTS -N "lmbench_write_n1k" -s 1k -I 100 -B 0 -f /dev/null -lmbench_write $OPTS -N "lmbench_write_n10k" -s 10k -I 100 -B 0 -f /dev/null -lmbench_write $OPTS -N "lmbench_write_n100k" -s 100k -I 100 -B 0 -f /dev/null - -writev $OPTS -N "writev_t1k" -s 1k -B 20 -f $TFILE -writev $OPTS -N "writev_t10k" -s 10k -B 4 -f $TFILE -writev $OPTS -N "writev_t100k" -s 100k -f $TFILE - -writev $OPTS -N "writev_u1k" -s 1k -B 20 -f $VFILE -writev $OPTS -N "writev_u10k" -s 10k -B 4 -f $VFILE -writev $OPTS -N "writev_u100k" -s 100k -f $VFILE - -writev $OPTS -N "writev_n1k" -s 1k -I 100 -B 0 -f /dev/null -writev $OPTS -N "writev_n10k" -s 10k -I 100 -B 0 -f /dev/null -writev $OPTS -N "writev_n100k" -s 100k -I 100 -B 0 -f /dev/null - -pread $OPTS -N "pread_t1k" -s 1k -I 300 -f $TFILE -pread $OPTS -N "pread_t10k" -s 10k -I 1000 -f $TFILE -pread $OPTS -N "pread_t100k" -s 100k -I 10000 -f $TFILE - -pread $OPTS -N "pread_u1k" -s 1k -I 300 -f $VFILE -pread $OPTS -N "pread_u10k" -s 10k -I 1000 -f $VFILE -pread $OPTS -N "pread_u100k" -s 100k -I 10000 -f $VFILE - -pread $OPTS -N "pread_z1k" -s 1k -I 300 -f /dev/zero -pread $OPTS -N "pread_z10k" -s 10k -I 1000 -f /dev/zero -pread $OPTS -N "pread_z100k" -s 100k -I 2000 -f /dev/zero -pread $OPTS -N "pread_zw100k" -s 100k -w -I 10000 -f /dev/zero - -pwrite $OPTS -N "pwrite_t1k" -s 1k -I 500 -f $TFILE -pwrite $OPTS -N "pwrite_t10k" -s 10k -I 1000 -f $TFILE -pwrite $OPTS -N "pwrite_t100k" -s 100k -I 10000 -f $TFILE - -pwrite $OPTS -N "pwrite_u1k" -s 1k -I 500 -f $VFILE -pwrite $OPTS -N "pwrite_u10k" -s 10k -I 1000 -f $VFILE -pwrite $OPTS -N "pwrite_u100k" -s 100k -I 20000 -f $VFILE - -pwrite $OPTS -N "pwrite_n1k" -s 1k -I 100 -f /dev/null -pwrite $OPTS -N "pwrite_n10k" -s 10k -I 100 -f /dev/null -pwrite $OPTS -N "pwrite_n100k" -s 100k -I 100 -f /dev/null - -mmap $OPTS -N "mmap_t8k" -l 8k -I 1000 -f $TFILE -mmap $OPTS -N "mmap_t128k" -l 128k -I 1000 -f $TFILE -mmap $OPTS -N "mmap_u8k" -l 8k -I 1000 -f $VFILE -mmap $OPTS -N "mmap_u128k" -l 128k -I 1000 -f $VFILE -mmap $OPTS -N "mmap_a8k" -l 8k -I 200 -f MAP_ANON -mmap $OPTS -N "mmap_a128k" -l 128k -I 200 -f MAP_ANON - - - -mmap $OPTS -N "mmap_rt8k" -l 8k -I 2000 -r -f $TFILE -mmap $OPTS -N "mmap_rt128k" -l 128k -I 20000 -r -f $TFILE -mmap $OPTS -N "mmap_ru8k" -l 8k -I 2000 -r -f $VFILE -mmap $OPTS -N "mmap_ru128k" -l 128k -I 20000 -r -f $VFILE -mmap $OPTS -N "mmap_ra8k" -l 8k -I 2000 -r -f MAP_ANON -mmap $OPTS -N "mmap_ra128k" -l 128k -I 20000 -r -f MAP_ANON - - -mmap $OPTS -N "mmap_wt8k" -l 8k -I 5000 -w -f $TFILE -mmap $OPTS -N "mmap_wt128k" -l 128k -I 50000 -w -f $TFILE -mmap $OPTS -N "mmap_wu8k" -l 8k -I 5000 -w -f $VFILE -mmap $OPTS -N "mmap_wu128k" -l 128k -I 500000 -w -f $VFILE -mmap $OPTS -N "mmap_wa8k" -l 8k -I 3000 -w -f MAP_ANON -mmap $OPTS -N "mmap_wa128k" -l 128k -I 50000 -w -f MAP_ANON - - -munmap $OPTS -N "unmap_t8k" -l 8k -I 500 -f $TFILE -munmap $OPTS -N "unmap_t128k" -l 128k -I 500 -f $TFILE -munmap $OPTS -N "unmap_u8k" -l 8k -I 500 -f $VFILE -munmap $OPTS -N "unmap_u128k" -l 128k -I 500 -f $VFILE -munmap $OPTS -N "unmap_a8k" -l 8k -I 500 -f MAP_ANON -munmap $OPTS -N "unmap_a128k" -l 128k -I 500 -f MAP_ANON - - -munmap $OPTS -N "unmap_rt8k" -l 8k -I 1000 -r -f $TFILE -munmap $OPTS -N "unmap_rt128k" -l 128k -I 3000 -r -f $TFILE -munmap $OPTS -N "unmap_ru8k" -l 8k -I 1000 -r -f $VFILE -munmap $OPTS -N "unmap_ru128k" -l 128k -I 3000 -r -f $VFILE -munmap $OPTS -N "unmap_ra8k" -l 8k -I 1000 -r -f MAP_ANON -munmap $OPTS -N "unmap_ra128k" -l 128k -I 2000 -r -f MAP_ANON - -connection $OPTS -N "conn_connect" -B 256 -c - - -munmap $OPTS -N "unmap_wt8k" -l 8k -I 1000 -w -f $TFILE -munmap $OPTS -N "unmap_wt128k" -l 128k -I 10000 -w -f $TFILE -munmap $OPTS -N "unmap_wu8k" -l 8k -I 1000 -w -f $VFILE -munmap $OPTS -N "unmap_wu128k" -l 128k -I 50000 -w -B 10 -f $VFILE -munmap $OPTS -N "unmap_wa8k" -l 8k -I 1000 -w -f MAP_ANON -munmap $OPTS -N "unmap_wa128k" -l 128k -I 10000 -w -f MAP_ANON - -mprotect $OPTS -N "mprot_z8k" -l 8k -I 300 -f /dev/zero -mprotect $OPTS -N "mprot_z128k" -l 128k -I 500 -f /dev/zero -mprotect $OPTS -N "mprot_wz8k" -l 8k -I 500 -w -f /dev/zero -mprotect $OPTS -N "mprot_wz128k" -l 128k -I 1000 -w -f /dev/zero -mprotect $OPTS -N "mprot_twz8k" -l 8k -I 1000 -w -t -f /dev/zero -mprotect $OPTS -N "mprot_tw128k" -l 128k -I 2000 -w -t -f /dev/zero -mprotect $OPTS -N "mprot_tw4m" -l 4m -w -t -B 1 -f /dev/zero - -pipe $OPTS -N "pipe_pst1" -s 1 -I 1000 -x pipe -m st -pipe $OPTS -N "pipe_pmt1" -s 1 -I 8000 -x pipe -m mt -pipe $OPTS -N "pipe_pmp1" -s 1 -I 8000 -x pipe -m mp -pipe $OPTS -N "pipe_pst4k" -s 4k -I 1000 -x pipe -m st -pipe $OPTS -N "pipe_pmt4k" -s 4k -I 8000 -x pipe -m mt -pipe $OPTS -N "pipe_pmp4k" -s 4k -I 8000 -x pipe -m mp - -pipe $OPTS -N "pipe_sst1" -s 1 -I 1000 -x sock -m st -pipe $OPTS -N "pipe_smt1" -s 1 -I 8000 -x sock -m mt -pipe $OPTS -N "pipe_smp1" -s 1 -I 8000 -x sock -m mp -pipe $OPTS -N "pipe_sst4k" -s 4k -I 1000 -x sock -m st -pipe $OPTS -N "pipe_smt4k" -s 4k -I 8000 -x sock -m mt -pipe $OPTS -N "pipe_smp4k" -s 4k -I 8000 -x sock -m mp - -pipe $OPTS -N "pipe_tst1" -s 1 -I 1000 -x tcp -m st -pipe $OPTS -N "pipe_tmt1" -s 1 -I 8000 -x tcp -m mt -pipe $OPTS -N "pipe_tmp1" -s 1 -I 8000 -x tcp -m mp -pipe $OPTS -N "pipe_tst4k" -s 4k -I 1000 -x tcp -m st -pipe $OPTS -N "pipe_tmt4k" -s 4k -I 8000 -x tcp -m mt -pipe $OPTS -N "pipe_tmp4k" -s 4k -I 8000 -x tcp -m mp - -#connection $OPTS -N "conn_accept" -B 256 -a - -lmbench_bw_unix -B 11 -L -W - -lmbench_bw_mem $OPTS -N lmbench_bcopy_512 -s 512 -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_1k -s 1k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_2k -s 2k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_4k -s 4k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_8k -s 8k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_16k -s 16k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_32k -s 32k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_64k -s 64k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_128k -s 128k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_256k -s 256k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_512k -s 512k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_1m -s 1m -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bzero_512 -s 512 -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_1k -s 1k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_2k -s 2k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_4k -s 4k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_8k -s 8k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_16k -s 16k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_32k -s 32k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_64k -s 64k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_128k -s 128k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_256k -s 256k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_512k -s 512k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_1m -s 1m -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_512 -s 512 -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_1k -s 1k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_2k -s 2k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_4k -s 4k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_8k -s 8k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_16k -s 16k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_32k -s 32k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_64k -s 64k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_128k -s 128k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_256k -s 256k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_512k -s 512k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_1m -s 1m -x fcp -lmbench_bw_mem $OPTS -N lmbench_cp_512 -s 512 -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_1k -s 1k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_2k -s 2k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_4k -s 4k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_8k -s 8k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_16k -s 16k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_32k -s 32k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_64k -s 64k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_128k -s 128k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_256k -s 256k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_512k -s 512k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_1m -s 1m -x cp -lmbench_bw_mem $OPTS -N lmbench_frd_512 -s 512 -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_1k -s 1k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_2k -s 2k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_4k -s 4k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_8k -s 8k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_16k -s 16k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_32k -s 32k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_64k -s 64k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_128k -s 128k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_256k -s 256k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_512k -s 512k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_1m -s 1m -x frd -lmbench_bw_mem $OPTS -N lmbench_rd_512 -s 512 -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_1k -s 1k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_2k -s 2k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_4k -s 4k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_8k -s 8k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_16k -s 16k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_32k -s 32k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_64k -s 64k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_128k -s 128k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_256k -s 256k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_512k -s 512k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_1m -s 1m -x rd -lmbench_bw_mem $OPTS -N lmbench_fwr_512 -s 512 -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_1k -s 1k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_2k -s 2k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_4k -s 4k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_8k -s 8k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_16k -s 16k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_32k -s 32k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_64k -s 64k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_128k -s 128k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_256k -s 256k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_512k -s 512k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_1m -s 1m -x fwr -lmbench_bw_mem $OPTS -N lmbench_wr_512 -s 512 -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_1k -s 1k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_2k -s 2k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_4k -s 4k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_8k -s 8k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_16k -s 16k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_32k -s 32k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_64k -s 64k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_128k -s 128k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_256k -s 256k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_512k -s 512k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_1m -s 1m -x wr -lmbench_bw_mem $OPTS -N lmbench_rdwr_512 -s 512 -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_1k -s 1k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_2k -s 2k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_4k -s 4k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_8k -s 8k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_16k -s 16k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_32k -s 32k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_64k -s 64k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_128k -s 128k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_256k -s 256k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_512k -s 512k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_1m -s 1m -x rdwr - -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_512 -s 512 -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_1k -s 1k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_2k -s 2k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_4k -s 4k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_8k -s 8k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_16k -s 16k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_32k -s 32k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_64k -s 64k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_128k -s 128k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_256k -s 256k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_512k -s 512k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_1m -s 1m -f $TFILE - -. diff --git a/tools/tests/libMicro/create_stuff.sh b/tools/tests/libMicro/create_stuff.sh deleted file mode 100755 index 7b274cc4a..000000000 --- a/tools/tests/libMicro/create_stuff.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -echo Raising process limits -echo limit maxproc 1000 2000 >> /etc/launchd.conf - -echo Done. diff --git a/tools/tests/libMicro/dup.c b/tools/tests/libMicro/dup.c deleted file mode 100644 index cdce1f1c3..000000000 --- a/tools/tests/libMicro/dup.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * time dup - */ - -#include -#include -#include -#include - -#include "libmicro.h" - -#define DEFF "/dev/null" -static char *optf = DEFF; - -static int fd; - -typedef struct { - int ts_once; - int *ts_fds; -} tsd_t; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - lm_defB = 256; - - (void) sprintf(lm_optstr, "f:"); - - (void) sprintf(lm_usage, - " [-f file-to-dup (default %s)]\n" - "notes: measures dup()\n", - DEFF); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'f': - optf = optarg; - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initrun() -{ - (void) setfdlimit(lm_optB * lm_optT + 10); - fd = (open(optf, O_RDONLY)); - - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - int errors = 0; - - if (ts->ts_once++ == 0) { - ts->ts_fds = (int *)malloc(lm_optB * sizeof (int)); - if (ts->ts_fds == NULL) { - errors ++; - } - for (i = 0; i < lm_optB; i++) { - ts->ts_fds[i] = -1; - } - } - - return (errors); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - for (i = 0; i < lm_optB; i++) { - ts->ts_fds[i] = dup(fd); - if (ts->ts_fds[i] == -1) { - res->re_errors++; - } - } - res->re_count = i; - - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - for (i = 0; i < lm_optB; i++) { - (void) close(ts->ts_fds[i]); - } - - return (0); -} diff --git a/tools/tests/libMicro/elided.c b/tools/tests/libMicro/elided.c deleted file mode 100644 index ab26e6eab..000000000 --- a/tools/tests/libMicro/elided.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * empty benchmark program to substitute for benchmarks - * that don't work/exist on some platforms - */ - -#include -#include -#include -#include - -/*ARGSUSED*/ -int -main(int argc, char *argv[]) -{ - char *tmp = strrchr(argv[0], '/'); - - if (tmp == NULL) - tmp = argv[0]; - else - tmp++; - - (void) printf( - "#\n" - "# benchmark %s not compiled/supported on this platform\n" - "#\n", - tmp); - - return (0); -} diff --git a/tools/tests/libMicro/embd_bench.sh b/tools/tests/libMicro/embd_bench.sh deleted file mode 100755 index 3abdb4368..000000000 --- a/tools/tests/libMicro/embd_bench.sh +++ /dev/null @@ -1,815 +0,0 @@ -#!/bin/sh -# -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms -# of the Common Development and Distribution License -# (the "License"). You may not use this file except -# in compliance with the License. -# -# You can obtain a copy of the license at -# src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing -# permissions and limitations under the License. -# -# When distributing Covered Code, include this CDDL -# HEADER in each file and include the License file at -# usr/src/OPENSOLARIS.LICENSE. If applicable, -# add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your -# own identifying information: Portions Copyright [yyyy] -# [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - - -# usage function - defines all the options that can be given to this script. -function usage { - echo "Usage" - echo "$0 [-l] [-h] [name of test]" - echo "-l : This option runs the lmbench tests along with the default libmicro tests." - echo "-h : Help. This option displays information on how to run the script. " - echo "[name of test] : This option runs only the test that is specified" - echo "" - echo "Examples" - echo "$0 : This is the defualt execution. This will run only the default libmicro tests." - echo "$0 -l : This will run the lmbench tests too " - echo "$0 getppid : This will run only the getppid tests" - exit - -} - -if [ $# -eq 1 ] -then - lmbench=2 # to check if only a single test is to be run. e.g, ./bench.sh getppid -else - lmbench=0 # to run the default libMicro tests, without the lmbench tests. -fi - -while getopts "lh" OPT_LIST -do - case $OPT_LIST in - l) lmbench=1;; # to run the libmicro tests including the lmbench tests. - h) usage;; - *) usage;; - esac -done - -if [ -w / ]; then - #do nothing - echo "/ is mounted" -else - echo "ERROR: the test requires that the / directory be read/writable, please mount using the command: 'mount -uw /' " - exit 1 -fi - - -tattle="./tattle" - -bench_version=0.4.0 -libmicro_version=`$tattle -V` - -case $libmicro_version in -$bench_version) - ;; -*) - echo "ERROR: libMicro version doesn't match 'bench' script version" - exit 1 -esac - -TMPROOT=/private/tmp/libmicro.$$ -VARROOT=/private/var/tmp/libmicro.$$ -mkdir -p $TMPROOT -mkdir -p $VARROOT -trap "rm -rf $TMPROOT $VARROOT && exit" 0 2 - -TFILE=$TMPROOT/data -IFILE=$TMPROOT/ifile -TDIR1=$TMPROOT/0/1/2/3/4/5/6/7/8/9 -TDIR2=$TMPROOT/1/2/3/4/5/6/7/8/9/0 -VFILE=$VARROOT/data -VDIR1=$VARROOT/0/1/2/3/4/5/6/7/8/9 -VDIR2=$VARROOT/1/2/3/4/5/6/7/8/9/0 - - -OPTS="-E -C 200 -L -S -W" - -dd if=/dev/zero of=$TFILE bs=1024k count=10 2>/dev/null -dd if=/dev/zero of=$VFILE bs=1024k count=10 2>/dev/null -mkdir -p $TDIR1 $TDIR2 -mkdir -p $VDIR1 $VDIR2 - -touch $IFILE -/usr/bin/touch /private/var/tmp/lmbench - - -# produce benchmark header for easier comparisons - -hostname=`uname -n` - -if [ -f /usr/sbin/psrinfo ]; then - p_count=`psrinfo|wc -l` - p_mhz=`psrinfo -v | awk '/operates/{print $6 "MHz"; exit }'` - p_type=`psrinfo -vp 2>/dev/null | awk '{if (NR == 3) {print $0; exit}}'` - p_ipaddr=`getent hosts $hostname | awk '{print $1}'` -fi - -if [ -f /proc/cpuinfo ]; then - p_count=`egrep processor /proc/cpuinfo | wc -l` - p_mhz=`awk -F: '/cpu MHz/{printf("%5.0f00Mhz\n",$2/100); exit}' /proc/cpuinfo` - p_type=`awk -F: '/model name/{print $2; exit}' /proc/cpuinfo` - p_ipaddr=`getent hosts $hostname | awk '{print $1}'` -else -## Mac OS X specific stuff -# first, get ugly output, in case pretty output isn't available -# - p_count=`sysctl -n hw.physicalcpu` - p_mhz=`sysctl -n hw.cpufrequency` - p_type=`sysctl -n hw.model` - -if [ -x /usr/sbin/system_profiler ]; then - # requires this hunk of work-around - # grep the XML for the characteristic we need. The key appears twice, so grep for the useful key (with 'string') - # use sed to strip off the and the tabs in front of the string. So much work for so little result. - # - p_mhz=`system_profiler -xml -detailLevel mini SPHardwareDataType | \ - grep -A1 current_processor_speed | grep string | \ - sed -E 's/(.+)<\/string>/\1/' | sed 's- --g'` - p_type=`system_profiler -xml -detailLevel mini SPHardwareDataType | \ - grep -A1 cpu_type | grep string | \ - sed -E 's/(.+)<\/string>/\1/' | sed 's- --g'` -fi - -# look for en0 (usually ethernet) if that isn't there try en1 (usually wireless) else give up - p_ipaddr=`ipconfig getpacket en0 | grep yiaddr | tr "= " "\n" | grep [0-9]` - if [ ! $p_ipaddr ]; then - p_ipaddr=`ipconfig getpacket en1 | grep yiaddr | tr "= " "\n" | grep [0-9]` - elif [ ! $p_ipaddr ]; then - p_ipaddr="unknown" - fi -fi - -printf "\n\n!Libmicro_#: %30s\n" $libmicro_version -printf "!Options: %30s\n" "$OPTS" -printf "!Machine_name: %30s\n" "$hostname" -printf "!OS_name: %30s\n" `uname -s` -printf "!OS_release: %30s\n" `sw_vers -productVersion` -printf "!OS_build: %30.18s\n" "`sw_vers -buildVersion`" -printf "!Processor: %30s\n" `arch` -printf "!#CPUs: %30s\n" $p_count -printf "!CPU_MHz: %30s\n" "$p_mhz" -printf "!CPU_NAME: %30s\n" "$p_type" -printf "!IP_address: %30s\n" "$p_ipaddr" -printf "!Run_by: %30s\n" $LOGNAME -printf "!Date: %30s\n" "`date '+%D %R'`" -printf "!Compiler: %30s\n" `$tattle -c` -printf "!Compiler Ver.:%30s\n" "`$tattle -v`" -printf "!sizeof(long): %30s\n" `$tattle -s` -printf "!extra_CFLAGS: %30s\n" "`$tattle -f`" -printf "!TimerRes: %30s\n\n\n" "`$tattle -r`" - -bin_dir="$TMPROOT/bin" - -mkdir -p $bin_dir -cp bin-*/exec_bin $bin_dir/$A - -cp ./apple/bin-*/posix_spawn_bin $bin_dir/$A - -newline=0 - -# -# Everything below the while loop is input for the while loop if -# you have any tests which can't run in the while loop, put -# them above this comment -# -while read A B -do - # $A contains the command, $B contains the arguments - # we echo blank lines and comments - # we skip anything which fails to match *$1* (useful if - # we only want to test one case, but a nasty hack) - - case $A in - \#*) - echo "$A $B" - newline=1 - continue - ;; - - "") - if [ $newline -eq 1 ] - then - newline=0 - echo - echo - fi - - continue - ;; - - *$1*) - # Default execution without the lmbench tests. - # checks if there is no argument passed by the user. - if [ $lmbench -eq 0 ] - then - string=lmbench - if [ "${A:0:7}" == "$string" ] - then - continue - fi - fi - - ;; - - *) - if [ $lmbench -ne 1 ] - then - continue - fi - ;; - esac - - if [ ! -f $bin_dir/$A ] - then - cp bin-*/$A $bin_dir/$A - fi - - echo - - (cd $TMPROOT && eval "bin/$A $B") - - echo - echo -done <<. - -# -# Obligatory null system call: use very short time -# for default since SuSe implements this "syscall" in userland -# - -getpid $OPTS -N "getpid" -I 5 -getppid $OPTS -N "getppid" -I 5 - -getenv $OPTS -N "getenv" -s 100 -I 100 -getenv $OPTS -N "getenvT2" -s 100 -I 100 -T 2 - -gettimeofday $OPTS -N "gettimeofday" - -log $OPTS -N "log" -I 20 -B 300000 -exp $OPTS -N "exp" -I 20 -B 100000 -lrand48 $OPTS -N "lrand48" - -memset $OPTS -N "memset_10" -s 10 -I 10 -memset $OPTS -N "memset_256" -s 256 -I 20 -memset $OPTS -N "memset_256_u" -s 256 -a 1 -I 20 -memset $OPTS -N "memset_1k" -s 1k -I 100 -B 2000 -memset $OPTS -N "memset_4k" -s 4k -I 250 -B 500 -memset $OPTS -N "memset_4k_uc" -s 4k -u -I 400 - -memset $OPTS -N "memset_10k" -s 10k -I 600 -B 500 -memset $OPTS -N "memset_1m" -s 1m -I 200000 -memset $OPTS -N "memset_10m" -s 10m -I 2000000 -memset $OPTS -N "memsetP2_10m" -s 10m -P 2 -I 2000000 - -memrand $OPTS -N "memrand" -s 40m -B 10000 - -# This is an elided test and is not ported yet. -# Check Makefile.darwin for list of elided tests -# cachetocache $OPTS -N "cachetocache" -s 100k -T 2 -I 200 - -isatty $OPTS -N "isatty_yes" -isatty $OPTS -N "isatty_no" -f $IFILE - -malloc $OPTS -N "malloc_10" -s 10 -g 10 -I 50 -malloc $OPTS -N "malloc_100" -s 100 -g 10 -I 50 -malloc $OPTS -N "malloc_1k" -s 1k -g 10 -I 50 -malloc $OPTS -N "malloc_10k" -s 10k -g 10 -I 50 -malloc $OPTS -N "malloc_100k" -s 100k -g 10 -I 2000 - -malloc $OPTS -N "mallocT2_10" -s 10 -g 10 -T 2 -I 200 -malloc $OPTS -N "mallocT2_100" -s 100 -g 10 -T 2 -I 200 -malloc $OPTS -N "mallocT2_1k" -s 1k -g 10 -T 2 -I 200 -malloc $OPTS -N "mallocT2_10k" -s 10k -g 10 -T 2 -I 200 -malloc $OPTS -N "mallocT2_100k" -s 100k -g 10 -T 2 -I 10000 - -close $OPTS -N "close_bad" -B 96 -b -close $OPTS -N "close_tmp" -B 64 -f $TFILE -close $OPTS -N "close_usr" -B 64 -f $VFILE -close $OPTS -N "close_zero" -B 64 -f /dev/zero -close_tcp $OPTS -N "close_tcp" -B 32 - -memcpy $OPTS -N "memcpy_10" -s 10 -I 10 -memcpy $OPTS -N "memcpy_1k" -s 1k -I 50 -memcpy $OPTS -N "memcpy_10k" -s 10k -I 800 -memcpy $OPTS -N "memcpy_1m" -s 1m -I 500000 -memcpy $OPTS -N "memcpy_10m" -s 10m -I 5000000 - -strcpy $OPTS -N "strcpy_10" -s 10 -I 5 -strcpy $OPTS -N "strcpy_1k" -s 1k -I 100 - -strlen $OPTS -N "strlen_10" -s 10 -I 5 -strlen $OPTS -N "strlen_1k" -s 1k -I 100 - -strchr $OPTS -N "strchr_10" -s 10 -I 5 -strchr $OPTS -N "strchr_1k" -s 1k -I 200 -strcmp $OPTS -N "strcmp_10" -s 10 -I 10 -strcmp $OPTS -N "strcmp_1k" -s 1k -I 200 - -strcasecmp $OPTS -N "scasecmp_10" -s 10 -I 50 -B 2000 -strcasecmp $OPTS -N "scasecmp_1k" -s 1k -I 20000 -B 100 - -strtol $OPTS -N "strtol" -I 20 - -# This is an elided test and is not ported yet. -# Check Makefile.darwin for list of elided tests -# getcontext $OPTS -N "getcontext" -I 100 - -# This is an elided test and is not ported yet. -# Check Makefile.darwin for list of elided tests -# setcontext $OPTS -N "setcontext" -I 100 - -mutex $OPTS -N "mutex_st" -I 10 -mutex $OPTS -N "mutex_mt" -t -I 10 -mutex $OPTS -N "mutex_T2" -T 2 -I 100 - -longjmp $OPTS -N "longjmp" -I 10 -siglongjmp $OPTS -N "siglongjmp" -I 20 - -getrusage $OPTS -N "getrusage" -I 200 - -times $OPTS -N "times" -I 200 -time $OPTS -N "time" -I 50 -localtime_r $OPTS -N "localtime_r" -I 200 -strftime $OPTS -N "strftime" -I 10000 -B 100 - -mktime $OPTS -N "mktime" -I 500 -mktime $OPTS -N "mktimeT2" -T 2 -I 1000 - -cascade_mutex $OPTS -N "c_mutex_1" -I 50 -cascade_mutex $OPTS -N "c_mutex_10" -T 10 -I 5000 -cascade_mutex $OPTS -N "c_mutex_200" -T 200 -I 2000000 - -cascade_cond $OPTS -N "c_cond_1" -I 100 -cascade_cond $OPTS -N "c_cond_10" -T 10 -I 3000 -cascade_cond $OPTS -N "c_cond_200" -T 200 -I 2000000 - -cascade_lockf $OPTS -N "c_lockf_1" -I 1000 -cascade_lockf $OPTS -N "c_lockf_10" -P 10 -I 50000 -#cascade_lockf $OPTS -N "c_lockf_200" -P 200 -I 5000000 - - - -cascade_flock $OPTS -N "c_flock" -I 1000 -cascade_flock $OPTS -N "c_flock_10" -P 10 -I 50000 -#cascade_flock $OPTS -N "c_flock_200" -P 200 -I 5000000 - - - -cascade_fcntl $OPTS -N "c_fcntl_1" -I 2000 -cascade_fcntl $OPTS -N "c_fcntl_10" -P 10 -I 20000 -#cascade_fcntl $OPTS -N "c_fcntl_200" -P 200 -I 5000000 - - -file_lock $OPTS -N "file_lock" -I 1000 - -getsockname $OPTS -N "getsockname" -I 100 -getpeername $OPTS -N "getpeername" -I 100 - -chdir $OPTS -N "chdir_tmp" -I 2000 $TDIR1 $TDIR2 -chdir $OPTS -N "chdir_usr" -I 2000 $VDIR1 $VDIR2 - -chdir $OPTS -N "chgetwd_tmp" -I 3000 -g $TDIR1 $TDIR2 -chdir $OPTS -N "chgetwd_usr" -I 3000 -g $VDIR1 $VDIR2 - -realpath $OPTS -N "realpath_tmp" -I 3000 -f $TDIR1 -realpath $OPTS -N "realpath_usr" -I 3000 -f $VDIR1 - -stat $OPTS -N "stat_tmp" -I 1000 -f $TFILE -stat $OPTS -N "stat_usr" -I 1000 -f $VFILE - -lmbench_stat $OPTS -N "lmbench_stat_tmp" -I 1000 -f $TFILE -lmbench_stat $OPTS -N "lmbench_stat_usr" -I 10000 -B 100 -f /private/var/tmp/lmbench - -# -# lmbench uses a touched empty file in /private/var/tmp -# libMicro uses a 1M file in a directory off /private/var/tmp -# performance difference is ~ 0.2 usecs/call -# -# why? - walking the dir tree, empty file vs. non-empty file, non-empty dir -# in the case of libMicro, etc., etc. -# - -lmbench_stat $OPTS -N "lmbench_stat_usr - Default" -I 10000 -B 100 -f /private/var/tmp/lmbench - -lmbench_fstat $OPTS -N "lmbench_fstat_tmp" -I 1000 -f $TFILE -lmbench_fstat $OPTS -N "lmbench_fstat_usr" -I 10000 -B 100 -f /private/var/tmp/lmbench - -# see stat test to understand why we are using /private/var/tmp/lmbench - -lmbench_fstat $OPTS -N "lmbench_fstat_usr - Default" -I 10000 -B 100 -f /private/var/tmp/lmbench - -lmbench_openclose $OPTS -N "lmbench_openclose - Default" -I 10000 -B 100 -f /private/var/tmp/lmbench - -lmbench_select_file $OPTS -N "lmbench_select_file_10" -n 10 -B 100 -lmbench_select_file $OPTS -N "lmbench_select_file_100" -n 100 -B 100 -lmbench_select_file $OPTS -N "lmbench_select_file_250" -n 250 -B 100 -lmbench_select_file $OPTS -N "lmbench_select_file_500" -n 500 -B 100 - -lmbench_select_tcp $OPTS -N "lmbench_select_tcp_10" -n 10 -B 100 -lmbench_select_tcp $OPTS -N "lmbench_select_tcp_100" -n 100 -B 100 -lmbench_select_tcp $OPTS -N "lmbench_select_tcp_250" -n 250 -B 100 -lmbench_select_tcp $OPTS -N "lmbench_select_tcp_500" -n 500 -B 100 - -fcntl $OPTS -N "fcntl_tmp" -I 100 -f $TFILE -fcntl $OPTS -N "fcntl_usr" -I 100 -f $VFILE -fcntl_ndelay $OPTS -N "fcntl_ndelay" -I 100 - -lseek $OPTS -N "lseek_t8k" -s 8k -I 50 -f $TFILE -lseek $OPTS -N "lseek_u8k" -s 8k -I 50 -f $VFILE - -open $OPTS -N "open_tmp" -B 256 -f $TFILE -open $OPTS -N "open_usr" -B 256 -f $VFILE -open $OPTS -N "open_zero" -B 256 -f /dev/zero - -dup $OPTS -N "dup" -B 512 - -socket $OPTS -N "socket_u" -B 256 -socket $OPTS -N "socket_i" -B 256 -f PF_INET - -socketpair $OPTS -N "socketpair" -B 256 - -setsockopt $OPTS -N "setsockopt" -I 200 - -bind $OPTS -N "bind" -B 100 - -listen $OPTS -N "listen" -B 100 - -#connection $OPTS -N "connection" -B 256 - -poll $OPTS -N "poll_10" -n 10 -I 500 -poll $OPTS -N "poll_100" -n 100 -I 1000 -poll $OPTS -N "poll_1000" -n 1000 -I 5000 - -poll $OPTS -N "poll_w10" -n 10 -I 500 -w 1 -poll $OPTS -N "poll_w100" -n 100 -I 2000 -w 10 -poll $OPTS -N "poll_w1000" -n 1000 -I 40000 -w 100 - -select $OPTS -N "select_10" -n 10 -I 500 -select $OPTS -N "select_100" -n 100 -I 1000 -select $OPTS -N "select_1000" -n 1000 -I 5000 - -select $OPTS -N "select_w10" -n 10 -I 500 -w 1 -select $OPTS -N "select_w100" -n 100 -I 2000 -w 10 -select $OPTS -N "select_w1000" -n 1000 -I 40000 -w 100 - -semop $OPTS -N "semop" -I 200 - -sigaction $OPTS -N "sigaction" -I 100 -signal $OPTS -N "signal" -I 1000 -sigprocmask $OPTS -N "sigprocmask" -I 200 - -lmbench_lat_sig_install $OPTS -N "lmbench_siginstall" -# sigcatch and sigsend need to be evaluated together -# lmbench framework will allow multiple measurements within the same -# benchmark test which allow them to factor out the cost of sending -# a signal from catching one -# -# for our purposes sigcatch results - sigsend results yield -# lmbench sig handler overhead measurements -lmbench_lat_sig_catch $OPTS -N "lmbench_sigcatch" -lmbench_lat_sig_send $OPTS -N "lmbench_sigsend" - - -pthread_create $OPTS -N "pthread_8" -B 8 -pthread_create $OPTS -N "pthread_32" -B 32 -pthread_create $OPTS -N "pthread_128" -B 128 -pthread_create $OPTS -N "pthread_512" -B 512 - -fork $OPTS -N "fork_10" -B 10 -#fork $OPTS -N "fork_100" -B 100 -C 100 - -#fork $OPTS -N "fork_1000" -B 1000 -C 50 - -exit $OPTS -N "exit_10" -B 10 -##exit $OPTS -N "exit_100" -B 100 - -#exit $OPTS -N "exit_1000" -B 1000 -C 50 - -exit $OPTS -N "exit_10_nolibc" -e -B 10 - -exec $OPTS -N "exec" -B 10 - -posix_spawn $OPTS -N "posix_spawn" -B 10 - -system $OPTS -N "system" -I 1000000 - -recurse $OPTS -N "recurse" -B 512 - -read $OPTS -N "read_t1k" -s 1k -B 50 -f $TFILE -read $OPTS -N "read_t10k" -s 10k -B 16 -f $TFILE -read $OPTS -N "read_t100k" -s 100k -B 4 -f $TFILE - -read $OPTS -N "read_u1k" -s 1k -B 50 -f $VFILE -read $OPTS -N "read_u10k" -s 10k -B 16 -f $VFILE -read $OPTS -N "read_u100k" -s 100k -B 4 -f $VFILE - -read $OPTS -N "read_z1k" -s 1k -B 100 -f /dev/zero -read $OPTS -N "read_z10k" -s 10k -B 30 -f /dev/zero -read $OPTS -N "read_z100k" -s 100k -B 4 -f /dev/zero -read $OPTS -N "read_zw100k" -s 100k -B 4 -w -f /dev/zero - -lmbench_read $OPTS -N "read_t1b" -s 1 -B 50 -f $TFILE -lmbench_read $OPTS -N "read_t1k" -s 1k -B 50 -f $TFILE -lmbench_read $OPTS -N "read_t10k" -s 10k -B 16 -f $TFILE -lmbench_read $OPTS -N "read_t100k" -s 100k -B 4 -f $TFILE - -lmbench_read $OPTS -N "read_u1b" -s 1 -B 50 -f $VFILE -lmbench_read $OPTS -N "read_u1k" -s 1k -B 50 -f $VFILE -lmbench_read $OPTS -N "read_u10k" -s 10k -B 16 -f $VFILE -lmbench_read $OPTS -N "read_u100k" -s 100k -B 4 -f $VFILE - -lmbench_read $OPTS -N "read_z1b - Default" -s 1 -B 100 -f /dev/zero -lmbench_read $OPTS -N "read_z1k" -s 1k -B 100 -f /dev/zero -lmbench_read $OPTS -N "read_z10k" -s 10k -B 30 -f /dev/zero -lmbench_read $OPTS -N "read_z100k" -s 100k -B 4 -f /dev/zero -lmbench_read $OPTS -N "read_zw100k" -s 100k -B 4 -w -f /dev/zero - -write $OPTS -N "write_t1k" -s 1k -B 50 -f $TFILE -write $OPTS -N "write_t10k" -s 10k -B 25 -f $TFILE -write $OPTS -N "write_t100k" -s 100k -B 4 -f $TFILE - -write $OPTS -N "write_u1k" -s 1k -B 50 -f $VFILE -write $OPTS -N "write_u10k" -s 10k -B 25 -f $VFILE -write $OPTS -N "write_u100k" -s 100k -B 4 -f $VFILE - -write $OPTS -N "write_n1k" -s 1k -I 100 -B 0 -f /dev/null -write $OPTS -N "write_n10k" -s 10k -I 100 -B 0 -f /dev/null -write $OPTS -N "write_n100k" -s 100k -I 100 -B 0 -f /dev/null - -lmbench_write $OPTS -N "lmbench_write_t1b" -s 1 -B 50 -f $TFILE -lmbench_write $OPTS -N "lmbench_write_t1k" -s 1k -B 50 -f $TFILE -lmbench_write $OPTS -N "lmbench_write_t10k" -s 10k -B 25 -f $TFILE -lmbench_write $OPTS -N "lmbench_write_t100k" -s 100k -B 4 -f $TFILE - -lmbench_write $OPTS -N "lmbench_write_u1b" -s 1 -B 50 -f $VFILE -lmbench_write $OPTS -N "lmbench_write_u1k" -s 1k -B 50 -f $VFILE -lmbench_write $OPTS -N "lmbench_write_u10k" -s 10k -B 25 -f $VFILE -lmbench_write $OPTS -N "lmbench_write_u100k" -s 100k -B 4 -f $VFILE - -lmbench_write $OPTS -N "lmbench_write_n1b - Default" -s 1 -I 100 -B 0 -f /dev/null -lmbench_write $OPTS -N "lmbench_write_n1k" -s 1k -I 100 -B 0 -f /dev/null -lmbench_write $OPTS -N "lmbench_write_n10k" -s 10k -I 100 -B 0 -f /dev/null -lmbench_write $OPTS -N "lmbench_write_n100k" -s 100k -I 100 -B 0 -f /dev/null - -writev $OPTS -N "writev_t1k" -s 1k -B 20 -f $TFILE -writev $OPTS -N "writev_t10k" -s 10k -B 4 -f $TFILE -writev $OPTS -N "writev_t100k" -s 100k -f $TFILE - -writev $OPTS -N "writev_u1k" -s 1k -B 20 -f $VFILE -writev $OPTS -N "writev_u10k" -s 10k -B 4 -f $VFILE -writev $OPTS -N "writev_u100k" -s 100k -f $VFILE - -writev $OPTS -N "writev_n1k" -s 1k -I 100 -B 0 -f /dev/null -writev $OPTS -N "writev_n10k" -s 10k -I 100 -B 0 -f /dev/null -writev $OPTS -N "writev_n100k" -s 100k -I 100 -B 0 -f /dev/null - -pread $OPTS -N "pread_t1k" -s 1k -I 300 -f $TFILE -pread $OPTS -N "pread_t10k" -s 10k -I 1000 -f $TFILE -pread $OPTS -N "pread_t100k" -s 100k -I 10000 -f $TFILE - -pread $OPTS -N "pread_u1k" -s 1k -I 300 -f $VFILE -pread $OPTS -N "pread_u10k" -s 10k -I 1000 -f $VFILE -pread $OPTS -N "pread_u100k" -s 100k -I 10000 -f $VFILE - -pread $OPTS -N "pread_z1k" -s 1k -I 300 -f /dev/zero -pread $OPTS -N "pread_z10k" -s 10k -I 1000 -f /dev/zero -pread $OPTS -N "pread_z100k" -s 100k -I 2000 -f /dev/zero -pread $OPTS -N "pread_zw100k" -s 100k -w -I 10000 -f /dev/zero - -pwrite $OPTS -N "pwrite_t1k" -s 1k -I 500 -f $TFILE -pwrite $OPTS -N "pwrite_t10k" -s 10k -I 1000 -f $TFILE -pwrite $OPTS -N "pwrite_t100k" -s 100k -I 10000 -f $TFILE - -pwrite $OPTS -N "pwrite_u1k" -s 1k -I 500 -f $VFILE -pwrite $OPTS -N "pwrite_u10k" -s 10k -I 1000 -f $VFILE -pwrite $OPTS -N "pwrite_u100k" -s 100k -I 20000 -f $VFILE - -pwrite $OPTS -N "pwrite_n1k" -s 1k -I 100 -f /dev/null -pwrite $OPTS -N "pwrite_n10k" -s 10k -I 100 -f /dev/null -pwrite $OPTS -N "pwrite_n100k" -s 100k -I 100 -f /dev/null - - -mmap $OPTS -N "mmap_t8k" -l 8k -I 1000 -f $TFILE -mmap $OPTS -N "mmap_t128k" -l 128k -I 1000 -f $TFILE -mmap $OPTS -N "mmap_u8k" -l 8k -I 1000 -f $VFILE -mmap $OPTS -N "mmap_u128k" -l 128k -I 1000 -f $VFILE -mmap $OPTS -N "mmap_a8k" -l 8k -I 200 -f MAP_ANON -mmap $OPTS -N "mmap_a128k" -l 128k -I 200 -f MAP_ANON - - - -mmap $OPTS -N "mmap_rt8k" -l 8k -I 2000 -r -f $TFILE -mmap $OPTS -N "mmap_rt128k" -l 128k -I 20000 -r -f $TFILE -mmap $OPTS -N "mmap_ru8k" -l 8k -I 2000 -r -f $VFILE -mmap $OPTS -N "mmap_ru128k" -l 128k -I 20000 -r -f $VFILE -mmap $OPTS -N "mmap_ra8k" -l 8k -I 2000 -r -f MAP_ANON -mmap $OPTS -N "mmap_ra128k" -l 128k -I 20000 -r -f MAP_ANON - - -mmap $OPTS -N "mmap_wt8k" -l 8k -I 5000 -w -f $TFILE -mmap $OPTS -N "mmap_wt128k" -l 128k -I 50000 -w -f $TFILE -mmap $OPTS -N "mmap_wu8k" -l 8k -I 5000 -w -f $VFILE -mmap $OPTS -N "mmap_wu128k" -l 128k -I 500000 -w -f $VFILE -mmap $OPTS -N "mmap_wa8k" -l 8k -I 3000 -w -f MAP_ANON -mmap $OPTS -N "mmap_wa128k" -l 128k -I 50000 -w -f MAP_ANON - - -munmap $OPTS -N "unmap_t8k" -l 8k -I 500 -f $TFILE -munmap $OPTS -N "unmap_t128k" -l 128k -I 500 -f $TFILE -munmap $OPTS -N "unmap_u8k" -l 8k -I 500 -f $VFILE -munmap $OPTS -N "unmap_u128k" -l 128k -I 500 -f $VFILE -munmap $OPTS -N "unmap_a8k" -l 8k -I 500 -f MAP_ANON -munmap $OPTS -N "unmap_a128k" -l 128k -I 500 -f MAP_ANON - - -munmap $OPTS -N "unmap_rt8k" -l 8k -I 1000 -r -f $TFILE -munmap $OPTS -N "unmap_rt128k" -l 128k -I 3000 -r -f $TFILE -munmap $OPTS -N "unmap_ru8k" -l 8k -I 1000 -r -f $VFILE -munmap $OPTS -N "unmap_ru128k" -l 128k -I 3000 -r -f $VFILE -munmap $OPTS -N "unmap_ra8k" -l 8k -I 1000 -r -f MAP_ANON -munmap $OPTS -N "unmap_ra128k" -l 128k -I 2000 -r -f MAP_ANON - -connection $OPTS -N "conn_connect" -B 256 -c - - -munmap $OPTS -N "unmap_wt8k" -l 8k -I 1000 -w -f $TFILE -munmap $OPTS -N "unmap_wt128k" -l 128k -I 10000 -w -f $TFILE -munmap $OPTS -N "unmap_wu8k" -l 8k -I 1000 -w -f $VFILE -munmap $OPTS -N "unmap_wu128k" -l 128k -I 50000 -w -B 10 -f $VFILE -munmap $OPTS -N "unmap_wa8k" -l 8k -I 1000 -w -f MAP_ANON -munmap $OPTS -N "unmap_wa128k" -l 128k -I 10000 -w -f MAP_ANON - -mprotect $OPTS -N "mprot_z8k" -l 8k -I 300 -f /dev/zero -mprotect $OPTS -N "mprot_z128k" -l 128k -I 500 -f /dev/zero -mprotect $OPTS -N "mprot_wz8k" -l 8k -I 500 -w -f /dev/zero -mprotect $OPTS -N "mprot_wz128k" -l 128k -I 1000 -w -f /dev/zero -mprotect $OPTS -N "mprot_twz8k" -l 8k -I 1000 -w -t -f /dev/zero -mprotect $OPTS -N "mprot_tw128k" -l 128k -I 2000 -w -t -f /dev/zero -mprotect $OPTS -N "mprot_tw4m" -l 4m -w -t -B 1 -f /dev/zero - -pipe $OPTS -N "pipe_pst1" -s 1 -I 1000 -x pipe -m st -pipe $OPTS -N "pipe_pmt1" -s 1 -I 8000 -x pipe -m mt -pipe $OPTS -N "pipe_pmp1" -s 1 -I 8000 -x pipe -m mp -pipe $OPTS -N "pipe_pst4k" -s 4k -I 1000 -x pipe -m st -pipe $OPTS -N "pipe_pmt4k" -s 4k -I 8000 -x pipe -m mt -pipe $OPTS -N "pipe_pmp4k" -s 4k -I 8000 -x pipe -m mp - -pipe $OPTS -N "pipe_sst1" -s 1 -I 1000 -x sock -m st -pipe $OPTS -N "pipe_smt1" -s 1 -I 8000 -x sock -m mt -pipe $OPTS -N "pipe_smp1" -s 1 -I 8000 -x sock -m mp -pipe $OPTS -N "pipe_sst4k" -s 4k -I 1000 -x sock -m st -pipe $OPTS -N "pipe_smt4k" -s 4k -I 8000 -x sock -m mt -pipe $OPTS -N "pipe_smp4k" -s 4k -I 8000 -x sock -m mp - -pipe $OPTS -N "pipe_tst1" -s 1 -I 1000 -x tcp -m st -pipe $OPTS -N "pipe_tmt1" -s 1 -I 8000 -x tcp -m mt -pipe $OPTS -N "pipe_tmp1" -s 1 -I 8000 -x tcp -m mp -pipe $OPTS -N "pipe_tst4k" -s 4k -I 1000 -x tcp -m st -pipe $OPTS -N "pipe_tmt4k" -s 4k -I 8000 -x tcp -m mt -pipe $OPTS -N "pipe_tmp4k" -s 4k -I 8000 -x tcp -m mp - -#connection $OPTS -N "conn_accept" -B 256 -a - -lmbench_bw_unix -B 11 -L -W - -lmbench_bw_mem $OPTS -N lmbench_bcopy_512 -s 512 -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_1k -s 1k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_2k -s 2k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_4k -s 4k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_8k -s 8k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_16k -s 16k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_32k -s 32k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_64k -s 64k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_128k -s 128k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_256k -s 256k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_512k -s 512k -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bcopy_1m -s 1m -x bcopy -lmbench_bw_mem $OPTS -N lmbench_bzero_512 -s 512 -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_1k -s 1k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_2k -s 2k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_4k -s 4k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_8k -s 8k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_16k -s 16k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_32k -s 32k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_64k -s 64k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_128k -s 128k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_256k -s 256k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_512k -s 512k -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_1m -s 1m -x bzero -lmbench_bw_mem $OPTS -N lmbench_bzero_512 -s 512 -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_1k -s 1k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_2k -s 2k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_4k -s 4k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_8k -s 8k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_16k -s 16k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_32k -s 32k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_64k -s 64k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_128k -s 128k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_256k -s 256k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_512k -s 512k -x fcp -lmbench_bw_mem $OPTS -N lmbench_bzero_1m -s 1m -x fcp -lmbench_bw_mem $OPTS -N lmbench_cp_512 -s 512 -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_1k -s 1k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_2k -s 2k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_4k -s 4k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_8k -s 8k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_16k -s 16k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_32k -s 32k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_64k -s 64k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_128k -s 128k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_256k -s 256k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_512k -s 512k -x cp -lmbench_bw_mem $OPTS -N lmbench_cp_1m -s 1m -x cp -lmbench_bw_mem $OPTS -N lmbench_frd_512 -s 512 -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_1k -s 1k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_2k -s 2k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_4k -s 4k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_8k -s 8k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_16k -s 16k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_32k -s 32k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_64k -s 64k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_128k -s 128k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_256k -s 256k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_512k -s 512k -x frd -lmbench_bw_mem $OPTS -N lmbench_frd_1m -s 1m -x frd -lmbench_bw_mem $OPTS -N lmbench_rd_512 -s 512 -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_1k -s 1k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_2k -s 2k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_4k -s 4k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_8k -s 8k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_16k -s 16k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_32k -s 32k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_64k -s 64k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_128k -s 128k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_256k -s 256k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_512k -s 512k -x rd -lmbench_bw_mem $OPTS -N lmbench_rd_1m -s 1m -x rd -lmbench_bw_mem $OPTS -N lmbench_fwr_512 -s 512 -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_1k -s 1k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_2k -s 2k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_4k -s 4k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_8k -s 8k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_16k -s 16k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_32k -s 32k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_64k -s 64k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_128k -s 128k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_256k -s 256k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_512k -s 512k -x fwr -lmbench_bw_mem $OPTS -N lmbench_fwr_1m -s 1m -x fwr -lmbench_bw_mem $OPTS -N lmbench_wr_512 -s 512 -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_1k -s 1k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_2k -s 2k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_4k -s 4k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_8k -s 8k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_16k -s 16k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_32k -s 32k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_64k -s 64k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_128k -s 128k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_256k -s 256k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_512k -s 512k -x wr -lmbench_bw_mem $OPTS -N lmbench_wr_1m -s 1m -x wr -lmbench_bw_mem $OPTS -N lmbench_rdwr_512 -s 512 -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_1k -s 1k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_2k -s 2k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_4k -s 4k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_8k -s 8k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_16k -s 16k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_32k -s 32k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_64k -s 64k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_128k -s 128k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_256k -s 256k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_512k -s 512k -x rdwr -lmbench_bw_mem $OPTS -N lmbench_rdwr_1m -s 1m -x rdwr - -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_512 -s 512 -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_1k -s 1k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_2k -s 2k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_4k -s 4k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_8k -s 8k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_16k -s 16k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_32k -s 32k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_64k -s 64k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_128k -s 128k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_256k -s 256k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_512k -s 512k -f $TFILE -lmbench_bw_mmap_rd $OPTS -N bw_mmap_rd_1m -s 1m -f $TFILE - -. diff --git a/tools/tests/libMicro/exec.c b/tools/tests/libMicro/exec.c deleted file mode 100644 index 3110a14c2..000000000 --- a/tools/tests/libMicro/exec.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * exec benchmark - */ - -#include -#include -#include -#include -#include - -#include "libmicro.h" - -static char exec_path[1024]; -static char *argv[3]; - -int -benchmark_init() -{ - lm_defB = 128; - lm_tsdsize = 0; - - (void) sprintf(lm_usage, - "notes: measures execv time of simple process()\n"); - - return (0); -} - -/*ARGSUSED*/ -int -benchmark_initbatch(void *tsd) -{ - char buffer[80]; - - (void) strcpy(exec_path, lm_procpath); - (void) strcat(exec_path, "/exec_bin"); - - (void) sprintf(buffer, "%d", lm_optB); - argv[0] = exec_path; - argv[1] = strdup(buffer); - argv[2] = NULL; - - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int c; - int status; - - switch (c = fork()) { - case -1: - res->re_errors++; - break; - default: - if (waitpid(c, &status, 0) < 0) - res->re_errors++; - - if (WIFEXITED(status) && WEXITSTATUS(status) != 0) - res->re_errors++; - break; - case 0: - if (execv(exec_path, argv) < 0) - res->re_errors++; - } - - res->re_count = lm_optB; - - return (0); -} diff --git a/tools/tests/libMicro/exec_bin.c b/tools/tests/libMicro/exec_bin.c deleted file mode 100644 index 4cddfd311..000000000 --- a/tools/tests/libMicro/exec_bin.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * time program to recursively test exec time - */ - -#include -#include -#include -#include - -int -main(int argc, char *argv[]) -{ - int left; - - if (argc == 1) { - exit(1); - } - - left = atoi(argv[1]); - - left--; - - if (left <= 0) { - exit(0); - } else { - char buffer[80]; - (void) sprintf(buffer, "%d", left); - argv[1] = buffer; - if (execv(argv[0], argv)) { - exit(2); - } - } - - return (0); -} diff --git a/tools/tests/libMicro/exit.c b/tools/tests/libMicro/exit.c deleted file mode 100644 index e2aa54ddb..000000000 --- a/tools/tests/libMicro/exit.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * benchmark exit - */ - -#include -#include -#include -#include -#include - -#include "libmicro.h" - -typedef struct { - int ts_once; - int *ts_pids; -} tsd_t; - -static int opte = 0; -static barrier_t *b; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - (void) sprintf(lm_optstr, "e"); - - (void) sprintf(lm_usage, - " [-e] (uses _exit() rather than exit())" - "notes: measures exit()\n"); - - return (0); -} - -/*ARGSUSED*/ -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'e': - opte = 1; - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initrun() -{ - b = barrier_create(lm_optP * lm_optT * (lm_optB + 1), 0); - - return (0); -} - -int -benchmark_finirun() -{ - (void) barrier_destroy(b); - - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - int errors = 0; - - if (ts->ts_once++ == 0) { - ts->ts_pids = (int *)malloc(lm_optB * sizeof (pid_t)); - if (ts->ts_pids == NULL) { - errors ++; - } - } - - /* - * create processes to exit - */ - - for (i = 0; i < lm_optB; i++) { - ts->ts_pids[i] = fork(); - switch (ts->ts_pids[i]) { - case 0: - (void) barrier_queue(b, NULL); - if (opte) - _exit(0); - exit(0); - break; - case -1: - errors ++; - break; - default: - continue; - } - } - - return (errors); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - - /* - * start them all exiting - */ - - (void) barrier_queue(b, NULL); - - /* - * wait for them all to exit - */ - - for (i = 0; i < lm_optB; i++) { - switch (waitpid((pid_t)-1, NULL, 0)) { - case 0: - continue; - case -1: - res->re_errors++; - } - } - - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/exp.c b/tools/tests/libMicro/exp.c deleted file mode 100644 index 14ad80b68..000000000 --- a/tools/tests/libMicro/exp.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * test exp performance (should add range check) - */ - -#include -#include -#include -#include - -#include "libmicro.h" - -int -benchmark_init() -{ - (void) sprintf(lm_usage, "note: measures exp()"); - lm_nsecs_per_op = 25; - lm_tsdsize = 0; - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - /* Added as part of the fix for radar 7508837 */ - double t = 0.0; - - for (i = 0; i < lm_optB; i += 10) { - double value = 1.0 / (i + .01); -#if 1 /* Apple added code, see radar 7508837 */ - t += exp(value); - t += exp(value + 1.0); - t += exp(value + 2.0); - t += exp(value + 3.0); - t += exp(value + 4.0); - t += exp(value + 5.0); - t += exp(value + 6.0); - t += exp(value + 7.0); - t += exp(value + 8.0); - t += exp(value + 9.0); - } - res->re_count = i; - - return ((int)(t - t)); -#else - (void) exp(value); - (void) exp(value); - (void) exp(value); - (void) exp(value); - (void) exp(value); - (void) exp(value); - (void) exp(value); - (void) exp(value); - (void) exp(value); - (void) exp(value); - } - res->re_count = i; - - return (0); -#endif /* end of Apple fix */ -} diff --git a/tools/tests/libMicro/fcntl.c b/tools/tests/libMicro/fcntl.c deleted file mode 100644 index 95099c136..000000000 --- a/tools/tests/libMicro/fcntl.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * benchmark fcntl getfl - */ - -#include -#include -#include -#include -#include - -#include "libmicro.h" - -#define DEFF "/dev/null" - -static char *optf = DEFF; -static int fd = -1; - -int -benchmark_init() -{ - (void) sprintf(lm_optstr, "f:"); - lm_tsdsize = 0; - - (void) sprintf(lm_usage, - " [-f file-to-fcntl (default %s)]\n" - "notes: measures fcntl()\n", - DEFF); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'f': - optf = optarg; - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initrun() -{ - if ((fd = open(optf, O_RDONLY)) == -1) { - perror("open"); - exit(1); - } - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - int flags; - - for (i = 0; i < lm_optB; i++) { - if (fcntl(fd, F_GETFL, &flags) == -1) - res->re_errors++; - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/fcntl_ndelay.c b/tools/tests/libMicro/fcntl_ndelay.c deleted file mode 100644 index 3f55a181d..000000000 --- a/tools/tests/libMicro/fcntl_ndelay.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * measures O_NDELAY on socket - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libmicro.h" - -static int fd = -1; - -int -benchmark_init() -{ - (void) sprintf(lm_usage, - "notes: measures F_GETFL/F_SETFL O_NDELAY on socket\n"); - - lm_tsdsize = 0; - - return (0); -} - -int -benchmark_initrun() -{ - fd = socket(AF_INET, SOCK_STREAM, 0); - if (fd == -1) { - perror("socket"); - exit(1); - } - - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - int flags; - - for (i = 0; i < lm_optB; i += 4) { - if (fcntl(fd, F_GETFL, &flags) < 0) - res->re_errors++; - flags |= O_NDELAY; - - if (fcntl(fd, F_SETFL, &flags) < 0) - res->re_errors++; - - if (fcntl(fd, F_GETFL, &flags) < 0) - res->re_errors++; - flags &= ~O_NDELAY; - - if (fcntl(fd, F_SETFL, &flags) < 0) - res->re_errors++; - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/file_lock.c b/tools/tests/libMicro/file_lock.c deleted file mode 100644 index fc1196420..000000000 --- a/tools/tests/libMicro/file_lock.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * test file locking - */ - -#include -#include -#include -#include -#include -#include - -#include "libmicro.h" - -static int file; - -int -block(int index) -{ - struct flock fl; - - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - fl.l_start = index; - fl.l_len = 1; - return (fcntl(file, F_SETLKW, &fl) == -1); -} - -int -unblock(int index) -{ - struct flock fl; - - fl.l_type = F_UNLCK; - fl.l_whence = SEEK_SET; - fl.l_start = index; - fl.l_len = 1; - return (fcntl(file, F_SETLK, &fl) == -1); -} -int -benchmark_init() -{ - char fname[80]; - int errors = 0; - - (void) sprintf(fname, "/private/tmp/oneflock.%ld", getpid()); - - file = open(fname, O_CREAT | O_TRUNC | O_RDWR, 0600); - - if (file == -1) { - errors++; - } - if (unlink(fname)) { - errors++; - } - - lm_tsdsize = 0; - - return (errors); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - int e = 0; - - for (i = 0; i < lm_optB; i ++) { - e += block(0); - e += unblock(0); - } - res->re_count = i; - res->re_errors = e; - - return (0); -} diff --git a/tools/tests/libMicro/fork.c b/tools/tests/libMicro/fork.c deleted file mode 100644 index d0336915c..000000000 --- a/tools/tests/libMicro/fork.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * benchmark fork - */ - -#include -#include -#include -#include -#include - -#include "libmicro.h" - -static barrier_t *b; - -typedef struct { - int ts_once; - int *ts_pids; -} tsd_t; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - (void) sprintf(lm_usage, "notes: measures fork()\n"); - - return (0); -} - -int -benchmark_initrun() -{ - b = barrier_create(lm_optP * lm_optT * (lm_optB + 1), 0); - - return (0); -} - -int -benchmark_finirun() -{ - (void) barrier_destroy(b); - - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int errors = 0; - - if (ts->ts_once++ == 0) { - ts->ts_pids = (int *)malloc(lm_optB * sizeof (pid_t)); - if (ts->ts_pids == NULL) { - errors++; - } - } - - return (errors); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - for (i = 0; i < lm_optB; i++) { - ts->ts_pids[i] = fork(); - switch (ts->ts_pids[i]) { - case 0: - (void) barrier_queue(b, NULL); - exit(0); - break; - case -1: - res->re_errors++; - break; - default: - continue; - } - } - res->re_count = lm_optB; - - (void) barrier_queue(b, NULL); - - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - for (i = 0; i < lm_optB; i++) { - if (ts->ts_pids[i] > 0) { - (void) waitpid(ts->ts_pids[i], NULL, 0); - } - } - - return (0); -} diff --git a/tools/tests/libMicro/getcontext.c b/tools/tests/libMicro/getcontext.c deleted file mode 100644 index 524a0169c..000000000 --- a/tools/tests/libMicro/getcontext.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * getcontext - */ - -#include -#include -#include -#include - -#include "libmicro.h" - -int -benchmark_init() -{ - (void) sprintf(lm_usage, "notes: measures getcontext()\n"); - - lm_tsdsize = 0; - - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - - for (i = 0; i < lm_optB; i += 10) { - ucontext_t uc; - (void) getcontext(&uc); - (void) getcontext(&uc); - (void) getcontext(&uc); - (void) getcontext(&uc); - (void) getcontext(&uc); - (void) getcontext(&uc); - (void) getcontext(&uc); - (void) getcontext(&uc); - (void) getcontext(&uc); - (void) getcontext(&uc); - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/getenv.c b/tools/tests/libMicro/getenv.c deleted file mode 100644 index f75bfd476..000000000 --- a/tools/tests/libMicro/getenv.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * test getenv - */ - -#include -#include -#include -#include -#include - -#include "libmicro.h" - -#define DEFS 100 - -static int opts = DEFS; - -int -benchmark_init() -{ - (void) sprintf(lm_optstr, "s:"); - - lm_tsdsize = 0; - - (void) sprintf(lm_usage, - " [-s search-size (default = %d)]\n" - "notes: measures time to search env for missing string\n", - DEFS); - - lm_nsecs_per_op = 200; - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 's': - opts = atoi(optarg); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initrun() -{ - extern char ** environ; - int i, j; - - /* count environment strings */ - - for (i = 0; environ[i++]; ) - ; - - /* - * pad to desired count - */ - - if (opts < i) - opts = i; - - for (j = i; j < opts; j++) { - char buf[80]; - (void) sprintf(buf, "VAR_%d=%d", j, j); - (void) putenv(strdup(buf)); - } - - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - char *search = "RUMPLSTILTSKIN"; - - for (i = 0; i < lm_optB; i += 10) { - (void) getenv(search); - (void) getenv(search); - (void) getenv(search); - (void) getenv(search); - (void) getenv(search); - (void) getenv(search); - (void) getenv(search); - (void) getenv(search); - (void) getenv(search); - (void) getenv(search); - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/getpeername.c b/tools/tests/libMicro/getpeername.c deleted file mode 100644 index 877215d13..000000000 --- a/tools/tests/libMicro/getpeername.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * getpeername test - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libmicro.h" - -#define FIRSTPORT 12345 - -static int sock = -1; - -int -benchmark_init() -{ - (void) sprintf(lm_usage, "notes: measures getpeername()\n"); - lm_tsdsize = 0; - - return (0); -} - -int -benchmark_initrun() -{ - int j; - int opt = 1; - int result; - socklen_t size; - struct hostent *host; - struct sockaddr_in adds; - int sock2, sock3; - - sock2 = socket(AF_INET, SOCK_STREAM, 0); - if (sock2 == -1) { - perror("socket"); - exit(1); - } - - if (setsockopt(sock2, SOL_SOCKET, SO_REUSEADDR, - &opt, sizeof (int)) == -1) { - perror("setsockopt"); - exit(1); - } - - if ((host = gethostbyname("localhost")) == NULL) { - perror("gethostbyname"); - exit(1); - } - - j = FIRSTPORT; - for (;;) { - (void) memset(&adds, 0, sizeof (struct sockaddr_in)); - adds.sin_family = AF_INET; - adds.sin_port = htons(j++); - (void) memcpy(&adds.sin_addr.s_addr, host->h_addr_list[0], - sizeof (struct in_addr)); - - if (bind(sock2, (struct sockaddr *)&adds, - sizeof (struct sockaddr_in)) == 0) { - break; - } - - if (errno != EADDRINUSE) { - perror("bind"); - exit(1); - } - } - - if (listen(sock2, 5) == -1) { - perror("listen"); - exit(1); - } - - sock3 = socket(AF_INET, SOCK_STREAM, 0); - if (sock3 == -1) { - perror("socket"); - exit(1); - } - - if (fcntl(sock3, F_SETFL, O_NDELAY) == -1) { - perror("fcntl"); - exit(1); - } - - result = connect(sock3, (struct sockaddr *)&adds, - sizeof (struct sockaddr_in)); - if ((result == -1) && (errno != EINPROGRESS)) { - perror("connect"); - exit(1); - } - - size = sizeof (struct sockaddr); - sock = accept(sock2, (struct sockaddr *)&adds, &size); - if (sock == -1) { - perror("accept"); - exit(1); - } - - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - struct sockaddr_in adds; - socklen_t size; - - for (i = 0; i < lm_optB; i++) { - size = sizeof (struct sockaddr_in); - if (getpeername(sock, (struct sockaddr *)&adds, &size) == -1) { - perror("getpeername"); - exit(1); - res->re_errors++; - } - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/getpid.c b/tools/tests/libMicro/getpid.c deleted file mode 100644 index 4ac816543..000000000 --- a/tools/tests/libMicro/getpid.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * getpid - */ - - -#include -#include -#include - -#include "libmicro.h" - -int -benchmark_init() -{ - (void) sprintf(lm_usage, "note: measures getpid()"); - - lm_tsdsize = 0; - - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - - for (i = 0; i < lm_optB; i ++) { - (void) getpid(); - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/getrusage.c b/tools/tests/libMicro/getrusage.c deleted file mode 100644 index 2f02213db..000000000 --- a/tools/tests/libMicro/getrusage.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * getrusage - */ - - -#include -#include -#include -#include - -#include "libmicro.h" - -int -benchmark_init() -{ - (void) sprintf(lm_usage, "notes: measures getrusage(RUSAGE_SELF)\n"); - lm_tsdsize = 0; - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - struct rusage u; - - for (i = 0; i < lm_optB; i += 10) { - (void) getrusage(RUSAGE_SELF, &u); - (void) getrusage(RUSAGE_SELF, &u); - (void) getrusage(RUSAGE_SELF, &u); - (void) getrusage(RUSAGE_SELF, &u); - (void) getrusage(RUSAGE_SELF, &u); - (void) getrusage(RUSAGE_SELF, &u); - (void) getrusage(RUSAGE_SELF, &u); - (void) getrusage(RUSAGE_SELF, &u); - (void) getrusage(RUSAGE_SELF, &u); - (void) getrusage(RUSAGE_SELF, &u); - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/getsockname.c b/tools/tests/libMicro/getsockname.c deleted file mode 100644 index e3f7769bc..000000000 --- a/tools/tests/libMicro/getsockname.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * getsockname - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libmicro.h" - -#define FIRSTPORT 12345 - -static struct sockaddr_in adds; -static int sock = -1; - -int -benchmark_init() -{ - (void) sprintf(lm_usage, "notes: measures getsockname()()\n"); - lm_tsdsize = 0; - return (0); -} - -int -benchmark_initrun() -{ - int j; - int opt = 1; - struct hostent *host; - - sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock == -1) { - perror("socket"); - exit(1); - } - - if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, - &opt, sizeof (int)) == -1) { - perror("setsockopt"); - exit(1); - } - - if ((host = gethostbyname("localhost")) == NULL) { - perror("gethostbyname"); - exit(1); - } - - j = FIRSTPORT; - for (;;) { - (void) memset(&adds, 0, sizeof (struct sockaddr_in)); - adds.sin_family = AF_INET; - adds.sin_port = htons(j++); - (void) memcpy(&adds.sin_addr.s_addr, host->h_addr_list[0], - sizeof (struct in_addr)); - - if (bind(sock, (struct sockaddr *)&adds, - sizeof (struct sockaddr_in)) == 0) { - break; - } - - if (errno != EADDRINUSE) { - perror("bind"); - exit(1); - } - } - - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - struct sockaddr_in adds; - socklen_t size; - - for (i = 0; i < lm_optB; i++) { - size = sizeof (struct sockaddr_in); - if (getsockname(sock, (struct sockaddr *)&adds, &size) == -1) - res->re_errors++; - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/gettimeofday.c b/tools/tests/libMicro/gettimeofday.c deleted file mode 100644 index a17bf7519..000000000 --- a/tools/tests/libMicro/gettimeofday.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * gettimeofday test - */ - -#include -#include -#include -#include - -#include "libmicro.h" - -int -benchmark_init() -{ - (void) sprintf(lm_usage, "note: measures gettimeofday()"); - lm_tsdsize = 0; - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - struct timeval t; - - for (i = 0; i < lm_optB; i += 10) { - (void) gettimeofday(&t, NULL); - (void) gettimeofday(&t, NULL); - (void) gettimeofday(&t, NULL); - (void) gettimeofday(&t, NULL); - (void) gettimeofday(&t, NULL); - (void) gettimeofday(&t, NULL); - (void) gettimeofday(&t, NULL); - (void) gettimeofday(&t, NULL); - (void) gettimeofday(&t, NULL); - (void) gettimeofday(&t, NULL); - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/isatty.c b/tools/tests/libMicro/isatty.c deleted file mode 100644 index 68aaf8505..000000000 --- a/tools/tests/libMicro/isatty.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * isatty test - */ - -#include -#include -#include -#include - -#include "libmicro.h" - -#define DEFF "/dev/tty" -static char *optf = DEFF; -static int optb = 0; - -typedef struct { - int ts_fd; -} tsd_t; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "f:b"); - - (void) sprintf(lm_usage, - " [-f file-to-isatty (default %s)]\n" - " [-b] (try to isatty an unopened fd)\n" - "notes: measures isatty()", - DEFF); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'f': - optf = optarg; - break; - case 'b': - optb = 1; - break; - default: - return (-1); - } - - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - - ts->ts_fd = ((optb == 0) ? - open(optf, O_RDONLY) : 1024); - if (ts->ts_fd == -1) { - return (1); - } - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - for (i = 0; i < lm_optB; i++) { - if (isatty(ts->ts_fd) == -1) { - res->re_errors++; - } - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/libmicro.c b/tools/tests/libMicro/libmicro.c deleted file mode 100644 index a3239c63a..000000000 --- a/tools/tests/libMicro/libmicro.c +++ /dev/null @@ -1,1608 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * benchmarking routines - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __sun -#include -#endif - -#include "libmicro.h" - - -#if defined(__APPLE__) -#include - -long long -gethrtime(void) -{ - long long elapsed; - static long long start; - static mach_timebase_info_data_t sTimebaseInfo = { 0, 0 }; - - // If this is the first time we've run, get the timebase. - // We can use denom == 0 to indicate that sTimebaseInfo is - // uninitialised because it makes no sense to have a zero - // denominator in a fraction. - - if ( sTimebaseInfo.denom == 0 ) { - (void) mach_timebase_info(&sTimebaseInfo); - start = mach_absolute_time(); - } - - elapsed = mach_absolute_time() - start; - - // Convert to nanoseconds. - // return (elapsed * (long long)sTimebaseInfo.numer)/(long long)sTimebaseInfo.denom; - - // Provided the final result is representable in 64 bits the following maneuver will - // deliver that result without intermediate overflow. - if (sTimebaseInfo.denom == sTimebaseInfo.numer) - return elapsed; - else if (sTimebaseInfo.denom == 1) - return elapsed * (long long)sTimebaseInfo.numer; - else { - // Decompose elapsed = eta32 * 2^32 + eps32: - long long eta32 = elapsed >> 32; - long long eps32 = elapsed & 0x00000000ffffffffLL; - - long long numer = sTimebaseInfo.numer, denom = sTimebaseInfo.denom; - - // Form product of elapsed64 (decomposed) and numer: - long long mu64 = numer * eta32; - long long lambda64 = numer * eps32; - - // Divide the constituents by denom: - long long q32 = mu64/denom; - long long r32 = mu64 - (q32 * denom); // mu64 % denom - - return (q32 << 32) + ((r32 << 32) + lambda64)/denom; - } -} - -#endif - -/* - * user visible globals - */ - -int lm_argc = 0; -char ** lm_argv = NULL; - -int lm_opt1; -int lm_optA; -int lm_optB; -int lm_optC = 100; -int lm_optD; -int lm_optE; -int lm_optH; -int lm_optI; -int lm_optL = 0; -int lm_optM = 0; -char *lm_optN; -int lm_optP; -int lm_optS; -int lm_optT; -int lm_optW; - -int lm_def1 = 0; -int lm_defB = 0; /* use lm_nsecs_per_op */ -int lm_defD = 10; -int lm_defH = 0; -char *lm_defN = NULL; -int lm_defP = 1; - -int lm_defS = 0; -int lm_defT = 1; - -/* - * default on fast platform, should be overridden by individual - * benchmarks if significantly wrong in either direction. - */ - -int lm_nsecs_per_op = 5; - -char *lm_procpath; -char lm_procname[STRSIZE]; -char lm_usage[STRSIZE]; -char lm_optstr[STRSIZE]; -char lm_header[STRSIZE]; -size_t lm_tsdsize = 0; - - -/* - * Globals we do not export to the user - */ - -static barrier_t *lm_barrier; -static pid_t *pids = NULL; -static pthread_t *tids = NULL; -static int pindex = -1; -static void *tsdseg = NULL; -static size_t tsdsize = 0; - -#ifdef USE_RDTSC -static long long lm_hz = 0; -#endif - - -/* - * Forward references - */ - -static void worker_process(); -static void usage(); -static void print_stats(barrier_t *); -static void print_histo(barrier_t *); -static int remove_outliers(double *, int, stats_t *); -static long long nsecs_overhead; -static long long nsecs_resolution; -static long long get_nsecs_overhead(); -static int crunch_stats(double *, int, stats_t *); -static void compute_stats(barrier_t *); -/* - * main routine; renamed in this file to allow linking with other - * files - */ - -int -actual_main(int argc, char *argv[]) -{ - int i; - int opt; - extern char *optarg; - char *tmp; - char optstr[256]; - barrier_t *b; - long long startnsecs = getnsecs(); - -#ifdef USE_RDTSC - if (getenv("LIBMICRO_HZ") == NULL) { - (void) printf("LIBMICRO_HZ needed but not set\n"); - exit(1); - } - lm_hz = strtoll(getenv("LIBMICRO_HZ"), NULL, 10); -#endif - - lm_argc = argc; - lm_argv = argv; - - /* before we do anything */ - (void) benchmark_init(); - - - nsecs_overhead = get_nsecs_overhead(); - nsecs_resolution = get_nsecs_resolution(); - - /* - * Set defaults - */ - - lm_opt1 = lm_def1; - lm_optB = lm_defB; - lm_optD = lm_defD; - lm_optH = lm_defH; - lm_optN = lm_defN; - lm_optP = lm_defP; - - lm_optS = lm_defS; - lm_optT = lm_defT; - - /* - * squirrel away the path to the current - * binary in a way that works on both - * Linux and Solaris - */ - - if (*argv[0] == '/') { - lm_procpath = strdup(argv[0]); - *strrchr(lm_procpath, '/') = 0; - } else { - char path[1024]; - (void) getcwd(path, 1024); - (void) strcat(path, "/"); - (void) strcat(path, argv[0]); - *strrchr(path, '/') = 0; - lm_procpath = strdup(path); - } - - /* - * name of binary - */ - - if ((tmp = strrchr(argv[0], '/')) == NULL) - (void) strcpy(lm_procname, argv[0]); - else - (void) strcpy(lm_procname, tmp + 1); - - if (lm_optN == NULL) { - lm_optN = lm_procname; - } - - /* - * Parse command line arguments - */ - - (void) sprintf(optstr, "1AB:C:D:EHI:LMN:P:RST:VW?%s", lm_optstr); - while ((opt = getopt(argc, argv, optstr)) != -1) { - switch (opt) { - case '1': - lm_opt1 = 1; - break; - case 'A': - lm_optA = 1; - break; - case 'B': - lm_optB = sizetoint(optarg); - break; - case 'C': - lm_optC = sizetoint(optarg); - break; - case 'D': - lm_optD = sizetoint(optarg); - break; - case 'E': - lm_optE = 1; - break; - case 'H': - lm_optH = 1; - break; - case 'I': - lm_optI = sizetoint(optarg); - break; - case 'L': - lm_optL = 1; - break; - case 'M': - lm_optM = 1; - break; - case 'N': - lm_optN = optarg; - break; - case 'P': - lm_optP = sizetoint(optarg); - break; - case 'S': - lm_optS = 1; - break; - case 'T': - lm_optT = sizetoint(optarg); - break; - case 'V': - (void) printf("%s\n", LIBMICRO_VERSION); - exit(0); - break; - case 'W': - lm_optW = 1; - lm_optS = 1; - break; - case '?': - usage(); - exit(0); - break; - default: - if (benchmark_optswitch(opt, optarg) == -1) { - usage(); - exit(0); - } - } - } - - /* deal with implicit and overriding options */ - if (lm_opt1 && lm_optP > 1) { - lm_optP = 1; - (void) printf("warning: -1 overrides -P\n"); - } - - if (lm_optE) { - (void) fprintf(stderr, "Running:%20s", lm_optN); - (void) fflush(stderr); - } - - if (lm_optB == 0) { - /* - * neither benchmark or user has specified the number - * of cnts/sample, so use computed value - */ - if (lm_optI) - lm_nsecs_per_op = lm_optI; -#define BLOCK_TOCK_DURATION 10000 /* number of raw timer "tocks" ideally comprising a block of work */ - lm_optB = nsecs_resolution * BLOCK_TOCK_DURATION / lm_nsecs_per_op; - if (lm_optB == 0) - lm_optB = 1; - } - - /* - * now that the options are set - */ - - if (benchmark_initrun() == -1) { - exit(1); - } - - /* allocate dynamic data */ - pids = (pid_t *)malloc(lm_optP * sizeof (pid_t)); - if (pids == NULL) { - perror("malloc(pids)"); - exit(1); - } - tids = (pthread_t *)malloc(lm_optT * sizeof (pthread_t)); - if (tids == NULL) { - perror("malloc(tids)"); - exit(1); - } - - /* check that the case defines lm_tsdsize before proceeding */ - if (lm_tsdsize == (size_t)-1) { - (void) fprintf(stderr, "error in benchmark_init: " - "lm_tsdsize not set\n"); - exit(1); - } - - /* round up tsdsize to nearest 128 to eliminate false sharing */ - tsdsize = ((lm_tsdsize + 127) / 128) * 128; - - /* allocate sufficient TSD for each thread in each process */ - tsdseg = (void *)mmap(NULL, lm_optT * lm_optP * tsdsize + 8192, - PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0L); - if (tsdseg == NULL) { - perror("mmap(tsd)"); - exit(1); - } - - /* initialise worker synchronisation */ - b = barrier_create(lm_optT * lm_optP, DATASIZE); - if (b == NULL) { - perror("barrier_create()"); - exit(1); - } - lm_barrier = b; - b->ba_flag = 1; - - /* need this here so that parent and children can call exit() */ - (void) fflush(stdout); - (void) fflush(stderr); - - /* when we started and when to stop */ - - b->ba_starttime = getnsecs(); - b->ba_deadline = (long long) (b->ba_starttime + (lm_optD * 1000000LL)); - - /* do the work */ - if (lm_opt1) { - /* single process, non-fork mode */ - pindex = 0; - worker_process(); - } else { - /* create worker processes */ - for (i = 0; i < lm_optP; i++) { - pids[i] = fork(); - - switch (pids[i]) { - case 0: - pindex = i; - worker_process(); - exit(0); - break; - case -1: - perror("fork"); - exit(1); - break; - default: - continue; - } - } - - /* wait for worker processes */ - for (i = 0; i < lm_optP; i++) { - if (pids[i] > 0) { - (void) waitpid(pids[i], NULL, 0); - } - } - } - - b->ba_endtime = getnsecs(); - - /* compute results */ - - compute_stats(b); - - /* print arguments benchmark was invoked with ? */ - if (lm_optL) { - int l; - (void) printf("# %s ", argv[0]); - for (l = 1; l < argc; l++) { - (void) printf("%s ", argv[l]); - } - (void) printf("\n"); - } - - /* print result header (unless suppressed) */ - if (!lm_optH) { - (void) printf("%12s %3s %3s %12s %12s %8s %8s %s\n", - "", "prc", "thr", - "usecs/call", - "samples", "errors", "cnt/samp", lm_header); - } - - /* print result */ - - (void) printf("%-12s %3d %3d %12.5f %12d %8lld %8d %s\n", - lm_optN, lm_optP, lm_optT, - (lm_optM?b->ba_corrected.st_mean:b->ba_corrected.st_median), - b->ba_batches, b->ba_errors, lm_optB, - benchmark_result()); - - if (lm_optS) { - print_stats(b); - } - - /* just incase something goes awry */ - (void) fflush(stdout); - (void) fflush(stderr); - - /* cleanup by stages */ - (void) benchmark_finirun(); - (void) barrier_destroy(b); - (void) benchmark_fini(); - - if (lm_optE) { - (void) fprintf(stderr, " for %12.5f seconds\n", - (double)(getnsecs() - startnsecs) / - 1.e9); - (void) fflush(stderr); - } - return (0); -} - -void * -worker_thread(void *arg) -{ - result_t r; - long long last_sleep = 0; - long long t; - - r.re_errors = benchmark_initworker(arg); - - while (lm_barrier->ba_flag) { - r.re_count = 0; - r.re_errors += benchmark_initbatch(arg); - - /* sync to clock */ - - if (lm_optA && ((t = getnsecs()) - last_sleep) > 75000000LL) { - (void) poll(0, 0, 10); - last_sleep = t; - } - /* wait for it ... */ - (void) barrier_queue(lm_barrier, NULL); - - /* time the test */ - r.re_t0 = getnsecs(); - (void) benchmark(arg, &r); - r.re_t1 = getnsecs(); - - /* time to stop? */ - if (r.re_t1 > lm_barrier->ba_deadline && - (!lm_optC || lm_optC < lm_barrier->ba_batches)) { - lm_barrier->ba_flag = 0; - } - - /* record results and sync */ - (void) barrier_queue(lm_barrier, &r); - - (void) benchmark_finibatch(arg); - - r.re_errors = 0; - } - - (void) benchmark_finiworker(arg); - - return (0); -} - -void -worker_process() -{ - int i; - void *tsd; - - for (i = 1; i < lm_optT; i++) { - tsd = gettsd(pindex, i); - if (pthread_create(&tids[i], NULL, worker_thread, tsd) != 0) { - perror("pthread_create"); - exit(1); - } - } - - tsd = gettsd(pindex, 0); - (void) worker_thread(tsd); - - for (i = 1; i < lm_optT; i++) { - (void) pthread_join(tids[i], NULL); - } -} - -void -usage() -{ - (void) printf( - "usage: %s\n" - " [-1] (single process; overrides -P > 1)\n" - " [-A] (align with clock)\n" - " [-B batch-size (default %d)]\n" - " [-C minimum number of samples (default 0)]\n" - " [-D duration in msecs (default %ds)]\n" - " [-E (echo name to stderr)]\n" - " [-H] (suppress headers)\n" - " [-I] nsecs per op (used to compute batch size)" - " [-L] (print argument line)\n" - " [-M] (reports mean rather than median)\n" - " [-N test-name (default '%s')]\n" - " [-P processes (default %d)]\n" - " [-S] (print detailed stats)\n" - " [-T threads (default %d)]\n" - " [-V] (print the libMicro version and exit)\n" - " [-W] (flag possible benchmark problems)\n" - "%s\n", - lm_procname, - lm_defB, lm_defD, lm_procname, lm_defP, lm_defT, - lm_usage); -} - -void -print_warnings(barrier_t *b) -{ - int head = 0; - int increase; - - if (b->ba_quant) { - if (!head++) { - (void) printf("#\n# WARNINGS\n"); - } - increase = (int)(floor((nsecs_resolution * 100.0) / - ((double)lm_optB * b->ba_corrected.st_median * 1000.0)) + - 1.0); - (void) printf("# Quantization error likely;" - "increase batch size (-B option) %dX to avoid.\n", - increase); - } - - /* - * XXX should warn on median != mean by a lot - */ - - if (b->ba_errors) { - if (!head++) { - (void) printf("#\n# WARNINGS\n"); - } - (void) printf("# Errors occured during benchmark.\n"); - } -} - -void -print_stats(barrier_t *b) -{ - (void) printf("#\n"); - (void) printf("# STATISTICS %12s %12s\n", - "usecs/call (raw)", - "usecs/call (outliers removed)"); - - if (b->ba_count == 0) { - (void) printf("zero samples\n"); - return; - } - - (void) printf("# min %12.5f %12.5f\n", - b->ba_raw.st_min, - b->ba_corrected.st_min); - - (void) printf("# max %12.5f %12.5f\n", - b->ba_raw.st_max, - b->ba_corrected.st_max); - (void) printf("# mean %12.5f %12.5f\n", - b->ba_raw.st_mean, - b->ba_corrected.st_mean); - (void) printf("# median %12.5f %12.5f\n", - b->ba_raw.st_median, - b->ba_corrected.st_median); - (void) printf("# stddev %12.5f %12.5f\n", - b->ba_raw.st_stddev, - b->ba_corrected.st_stddev); - (void) printf("# standard error %12.5f %12.5f\n", - b->ba_raw.st_stderr, - b->ba_corrected.st_stderr); - (void) printf("# 99%% confidence level %12.5f %12.5f\n", - b->ba_raw.st_99confidence, - b->ba_corrected.st_99confidence); - (void) printf("# skew %12.5f %12.5f\n", - b->ba_raw.st_skew, - b->ba_corrected.st_skew); - (void) printf("# kurtosis %12.5f %12.5f\n", - b->ba_raw.st_kurtosis, - b->ba_corrected.st_kurtosis); - - (void) printf("# time correlation %12.5f %12.5f\n", - b->ba_raw.st_timecorr, - b->ba_corrected.st_timecorr); - (void) printf("#\n"); - - (void) printf("# elasped time %12.5f\n", (b->ba_endtime - - b->ba_starttime) / 1.0e9); - (void) printf("# number of samples %12d\n", b->ba_batches); - (void) printf("# number of outliers %12d\n", b->ba_outliers); - (void) printf("# getnsecs overhead %12d\n", (int)nsecs_overhead); - - (void) printf("#\n"); - (void) printf("# DISTRIBUTION\n"); - - print_histo(b); - - if (lm_optW) { - print_warnings(b); - } -} - -void -update_stats(barrier_t *b, result_t *r) -{ - double time; - double nsecs_per_call; - - if (b->ba_waiters == 0) { - /* first thread only */ - b->ba_t0 = r->re_t0; - b->ba_t1 = r->re_t1; - b->ba_count0 = 0; - b->ba_errors0 = 0; - } else { - /* all but first thread */ - if (r->re_t0 < b->ba_t0) { - b->ba_t0 = r->re_t0; - } - if (r->re_t1 > b->ba_t1) { - b->ba_t1 = r->re_t1; - } - } - - b->ba_count0 += r->re_count; - b->ba_errors0 += r->re_errors; - - if (b->ba_waiters == b->ba_hwm - 1) { - /* last thread only */ - - - time = (double)b->ba_t1 - (double)b->ba_t0 - - (double)nsecs_overhead; - - if (time < 100 * nsecs_resolution) - b->ba_quant++; - - /* - * normalize by procs * threads if not -U - */ - - nsecs_per_call = time / (double)b->ba_count0 * - (double)(lm_optT * lm_optP); - - b->ba_count += b->ba_count0; - b->ba_errors += b->ba_errors0; - - b->ba_data[b->ba_batches % b->ba_datasize] = - nsecs_per_call; - - b->ba_batches++; - } -} - -#ifdef USE_SEMOP -barrier_t * -barrier_create(int hwm, int datasize) -{ - struct sembuf s[1]; - barrier_t *b; - - /*LINTED*/ - b = (barrier_t *)mmap(NULL, - sizeof (barrier_t) + (datasize - 1) * sizeof (double), - PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_ANON, -1, 0L); - if (b == (barrier_t *)MAP_FAILED) { - return (NULL); - } - b->ba_datasize = datasize; - - b->ba_flag = 0; - b->ba_hwm = hwm; - b->ba_semid = semget(IPC_PRIVATE, 3, 0600); - if (b->ba_semid == -1) { - (void) munmap((void *)b, sizeof (barrier_t)); - return (NULL); - } - - /* [hwm - 1, 0, 0] */ - s[0].sem_num = 0; - s[0].sem_op = hwm - 1; - s[0].sem_flg = 0; - if (semop(b->ba_semid, s, 1) == -1) { - perror("semop(1)"); - (void) semctl(b->ba_semid, 0, IPC_RMID); - (void) munmap((void *)b, sizeof (barrier_t)); - return (NULL); - } - - b->ba_waiters = 0; - b->ba_phase = 0; - - b->ba_count = 0; - b->ba_errors = 0; - - return (b); -} - -int -barrier_destroy(barrier_t *b) -{ - (void) semctl(b->ba_semid, 0, IPC_RMID); - (void) munmap((void *)b, sizeof (barrier_t)); - - return (0); -} - -int -barrier_queue(barrier_t *b, result_t *r) -{ - struct sembuf s[2]; - - /* - * {s0(-(hwm-1))} - * if ! nowait {s1(-(hwm-1))} - * (all other threads) - * update shared stats - * {s0(hwm-1), s1(1)} - * {s0(1), s2(-1)} - * else - * (last thread) - * update shared stats - * {s2(hwm-1)} - */ - - s[0].sem_num = 0; - s[0].sem_op = -(b->ba_hwm - 1); - s[0].sem_flg = 0; - if (semop(b->ba_semid, s, 1) == -1) { - perror("semop(2)"); - return (-1); - } - - s[0].sem_num = 1; - s[0].sem_op = -(b->ba_hwm - 1); - s[0].sem_flg = IPC_NOWAIT; - if (semop(b->ba_semid, s, 1) == -1) { - if (errno != EAGAIN) { - perror("semop(3)"); - return (-1); - } - - /* all but the last thread */ - - if (r != NULL) { - update_stats(b, r); - } - - b->ba_waiters++; - - s[0].sem_num = 0; - s[0].sem_op = b->ba_hwm - 1; - s[0].sem_flg = 0; - s[1].sem_num = 1; - s[1].sem_op = 1; - s[1].sem_flg = 0; - if (semop(b->ba_semid, s, 2) == -1) { - perror("semop(4)"); - return (-1); - } - - s[0].sem_num = 0; - s[0].sem_op = 1; - s[0].sem_flg = 0; - s[1].sem_num = 2; - s[1].sem_op = -1; - s[1].sem_flg = 0; - if (semop(b->ba_semid, s, 2) == -1) { - perror("semop(5)"); - return (-1); - } - - } else { - /* the last thread */ - - if (r != NULL) { - update_stats(b, r); - } - - b->ba_waiters = 0; - b->ba_phase++; - - s[0].sem_num = 2; - s[0].sem_op = b->ba_hwm - 1; - s[0].sem_flg = 0; - if (semop(b->ba_semid, s, 1) == -1) { - perror("semop(6)"); - return (-1); - } - } - - return (0); -} - -#else /* USE_SEMOP */ - -barrier_t * -barrier_create(int hwm, int datasize) -{ - pthread_mutexattr_t attr; - pthread_condattr_t cattr; - barrier_t *b; - - /*LINTED*/ - b = (barrier_t *)mmap(NULL, - sizeof (barrier_t) + (datasize - 1) * sizeof (double), - PROT_READ | PROT_WRITE, - MAP_SHARED | MAP_ANON, -1, 0L); - if (b == (barrier_t *)MAP_FAILED) { - return (NULL); - } - b->ba_datasize = datasize; - - b->ba_hwm = hwm; - b->ba_flag = 0; - - (void) pthread_mutexattr_init(&attr); - (void) pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); - - (void) pthread_condattr_init(&cattr); - (void) pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED); - - (void) pthread_mutex_init(&b->ba_lock, &attr); - (void) pthread_cond_init(&b->ba_cv, &cattr); - - b->ba_waiters = 0; - b->ba_phase = 0; - - b->ba_count = 0; - b->ba_errors = 0; - - return (b); -} - -int -barrier_destroy(barrier_t *b) -{ - (void) munmap((void *)b, sizeof (barrier_t)); - - return (0); -} - -int -barrier_queue(barrier_t *b, result_t *r) -{ - int phase; - - (void) pthread_mutex_lock(&b->ba_lock); - - if (r != NULL) { - update_stats(b, r); - } - - phase = b->ba_phase; - - b->ba_waiters++; - if (b->ba_hwm == b->ba_waiters) { - b->ba_waiters = 0; - b->ba_phase++; - (void) pthread_cond_broadcast(&b->ba_cv); - } - - while (b->ba_phase == phase) { - (void) pthread_cond_wait(&b->ba_cv, &b->ba_lock); - } - - (void) pthread_mutex_unlock(&b->ba_lock); - return (0); -} -#endif /* USE_SEMOP */ - -int -gettindex() -{ - int i; - - if (tids == NULL) { - return (-1); - } - - for (i = 1; i < lm_optT; i++) { - if (pthread_self() == tids[i]) { - return (i); - } - } - - return (0); -} - -int -getpindex() -{ - return (pindex); -} - -void * -gettsd(int p, int t) -{ - if ((p < 0) || (p >= lm_optP) || (t < 0) || (t >= lm_optT)) - return (NULL); - - return ((void *)((unsigned long)tsdseg + - (((p * lm_optT) + t) * tsdsize))); -} - -#if defined(__APPLE__) -int -gettsdindex(void *arg){ - /* - * gettindex() can race with pthread_create() filling in tids[]. - * This is an alternative approach to finding the calling thread's tsd in t -sdseg - */ - return tsdsize ? ((unsigned long)arg - (unsigned long)tsdseg)/tsdsize : 0; -} -#endif /* __APPLE__ */ - -#ifdef USE_GETHRTIME -long long -getnsecs() -{ - return (gethrtime()); -} - -long long -getusecs() -{ - return (gethrtime() / 1000); -} - -#elif USE_RDTSC /* USE_GETHRTIME */ - -__inline__ long long -rdtsc(void) -{ - unsigned long long x; - __asm__ volatile(".byte 0x0f, 0x31" : "=A" (x)); - return (x); -} - -long long -getusecs() -{ - return (rdtsc() * 1000000 / lm_hz); -} - -long long -getnsecs() -{ - return (rdtsc() * 1000000000 / lm_hz); -} - -#else /* USE_GETHRTIME */ - -long long -getusecs() -{ - struct timeval tv; - - (void) gettimeofday(&tv, NULL); - - return ((long long)tv.tv_sec * 1000000LL + (long long) tv.tv_usec); -} - -long long -getnsecs() -{ - struct timeval tv; - - (void) gettimeofday(&tv, NULL); - - return ((long long)tv.tv_sec * 1000000000LL + - (long long) tv.tv_usec * 1000LL); -} - -#endif /* USE_GETHRTIME */ - -int -setfdlimit(int limit) -{ - struct rlimit rlimit; - - if (getrlimit(RLIMIT_NOFILE, &rlimit) < 0) { - perror("getrlimit"); - exit(1); - } - - if (rlimit.rlim_cur > limit) - return (0); /* no worries */ - - rlimit.rlim_cur = limit; - - if (rlimit.rlim_max < limit) - rlimit.rlim_max = limit; - - if (setrlimit(RLIMIT_NOFILE, &rlimit) < 0) { - perror("setrlimit"); - exit(3); - } - - return (0); -} - - -#define KILOBYTE 1024 -#define MEGABYTE (KILOBYTE * KILOBYTE) -#define GIGABYTE (KILOBYTE * MEGABYTE) - -long long -sizetoll(const char *arg) -{ - int len = strlen(arg); - int i; - long long mult = 1; - - if (len && isalpha(arg[len - 1])) { - switch (arg[len - 1]) { - - case 'k': - case 'K': - mult = KILOBYTE; - break; - case 'm': - case 'M': - mult = MEGABYTE; - break; - case 'g': - case 'G': - mult = GIGABYTE; - break; - default: - return (-1); - } - - for (i = 0; i < len - 1; i++) - if (!isdigit(arg[i])) - return (-1); - } - - return (mult * strtoll(arg, NULL, 10)); -} - -int -sizetoint(const char *arg) -{ - int len = strlen(arg); - int i; - long long mult = 1; - - if (len && isalpha(arg[len - 1])) { - switch (arg[len - 1]) { - - case 'k': - case 'K': - mult = KILOBYTE; - break; - case 'm': - case 'M': - mult = MEGABYTE; - break; - case 'g': - case 'G': - mult = GIGABYTE; - break; - default: - return (-1); - } - - for (i = 0; i < len - 1; i++) - if (!isdigit(arg[i])) - return (-1); - } - - return (mult * atoi(arg)); -} - -static void -print_bar(long count, long total) -{ - int i; - - (void) putchar_unlocked(count ? '*' : ' '); - for (i = 1; i < (32 * count) / total; i++) - (void) putchar_unlocked('*'); - for (; i < 32; i++) - (void) putchar_unlocked(' '); -} - -static int -doublecmp(const void *p1, const void *p2) -{ - double a = *((double *)p1); - double b = *((double *)p2); - - if (a > b) - return (1); - if (a < b) - return (-1); - return (0); -} - -static void -print_histo(barrier_t *b) -{ - int n; - int i; - int j; - int last; - long long maxcount; - double sum; - long long min; - long long scale; - double x; - long long y; - long long count; - int i95; - double p95; - double r95; - double m95; - histo_t *histo; - - (void) printf("# %12s %12s %32s %12s\n", "counts", "usecs/call", - "", "means"); - - /* calculate how much data we've captured */ - n = b->ba_batches > b->ba_datasize ? b->ba_datasize : b->ba_batches; - - /* find the 95th percentile - index, value and range */ - qsort((void *)b->ba_data, n, sizeof (double), doublecmp); - min = b->ba_data[0] + 0.000001; - i95 = n * 95 / 100; - p95 = b->ba_data[i95]; - r95 = p95 - min + 1; - - /* find a suitable min and scale */ - i = 0; - x = r95 / (HISTOSIZE - 1); - while (x >= 10.0) { - x /= 10.0; - i++; - } - y = x + 0.9999999999; - while (i > 0) { - y *= 10; - i--; - } - min /= y; - min *= y; - scale = y * (HISTOSIZE - 1); - if (scale < (HISTOSIZE - 1)) { - scale = (HISTOSIZE - 1); - } - - /* create and initialise the histogram */ - histo = malloc(HISTOSIZE * sizeof (histo_t)); - for (i = 0; i < HISTOSIZE; i++) { - histo[i].sum = 0.0; - histo[i].count = 0; - } - - /* populate the histogram */ - last = 0; - sum = 0.0; - count = 0; - for (i = 0; i < i95; i++) { - j = (HISTOSIZE - 1) * (b->ba_data[i] - min) / scale; - - if (j >= HISTOSIZE) { - (void) printf("panic!\n"); - j = HISTOSIZE - 1; - } - - histo[j].sum += b->ba_data[i]; - histo[j].count++; - - sum += b->ba_data[i]; - count++; - } - m95 = sum / count; - - /* find the larges bucket */ - maxcount = 0; - for (i = 0; i < HISTOSIZE; i++) - if (histo[i].count > 0) { - last = i; - if (histo[i].count > maxcount) - maxcount = histo[i].count; - } - - /* print the buckets */ - for (i = 0; i <= last; i++) { - (void) printf("# %12lld %12.5f |", histo[i].count, - (min + scale * (double)i / (HISTOSIZE - 1))); - - print_bar(histo[i].count, maxcount); - - if (histo[i].count > 0) - (void) printf("%12.5f\n", - histo[i].sum / histo[i].count); - else - (void) printf("%12s\n", "-"); - } - - /* find the mean of values beyond the 95th percentile */ - sum = 0.0; - count = 0; - for (i = i95; i < n; i++) { - sum += b->ba_data[i]; - count++; - } - - /* print the >95% bucket summary */ - (void) printf("#\n"); - (void) printf("# %12lld %12s |", count, "> 95%"); - print_bar(count, maxcount); - if (count > 0) - (void) printf("%12.5f\n", sum / count); - else - (void) printf("%12s\n", "-"); - (void) printf("#\n"); - (void) printf("# %12s %12.5f\n", "mean of 95%", m95); - (void) printf("# %12s %12.5f\n", "95th %ile", p95); - - /* quantify any buffer overflow */ - if (b->ba_batches > b->ba_datasize) - (void) printf("# %12s %12d\n", "data dropped", - b->ba_batches - b->ba_datasize); -} - -static void -compute_stats(barrier_t *b) -{ - int i; - - if (b->ba_batches > b->ba_datasize) - b->ba_batches = b->ba_datasize; - - /* - * convert to usecs/call - */ - - for (i = 0; i < b->ba_batches; i++) - b->ba_data[i] /= 1000.0; - - /* - * do raw stats - */ - - (void) crunch_stats(b->ba_data, b->ba_batches, &b->ba_raw); - - /* - * recursively apply 3 sigma rule to remove outliers - */ - - b->ba_corrected = b->ba_raw; - b->ba_outliers = 0; - - if (b->ba_batches > 40) { /* remove outliers */ - int removed; - - do { - removed = remove_outliers(b->ba_data, b->ba_batches, - &b->ba_corrected); - b->ba_outliers += removed; - b->ba_batches -= removed; - (void) crunch_stats(b->ba_data, b->ba_batches, - &b->ba_corrected); - } while (removed != 0 && b->ba_batches > 40); - } - -} - -/* - * routine to compute various statistics on array of doubles. - */ - -static int -crunch_stats(double *data, int count, stats_t *stats) -{ - double a; - double std; - double diff; - double sk; - double ku; - double mean; - int i; - int bytes; - double *dupdata; - - /* - * first we need the mean - */ - - mean = 0.0; - - for (i = 0; i < count; i++) { - mean += data[i]; - } - - mean /= count; - - stats->st_mean = mean; - - /* - * malloc and sort so we can do median - */ - - dupdata = malloc(bytes = sizeof (double) * count); - (void) memcpy(dupdata, data, bytes); - qsort((void *)dupdata, count, sizeof (double), doublecmp); - stats->st_median = dupdata[count/2]; - - /* - * reuse dupdata to compute time correlation of data to - * detect interesting time-based trends - */ - - for (i = 0; i < count; i++) - dupdata[i] = (double)i; - - (void) fit_line(dupdata, data, count, &a, &stats->st_timecorr); - free(dupdata); - - std = 0.0; - sk = 0.0; - ku = 0.0; - - stats->st_max = -1; - stats->st_min = 1.0e99; /* hard to find portable values */ - - for (i = 0; i < count; i++) { - if (data[i] > stats->st_max) - stats->st_max = data[i]; - if (data[i] < stats->st_min) - stats->st_min = data[i]; - - diff = data[i] - mean; - std += diff * diff; - sk += diff * diff * diff; - ku += diff * diff * diff * diff; - } - - stats->st_stddev = std = sqrt(std/(double)(count - 1)); - stats->st_stderr = std / sqrt(count); - stats->st_99confidence = stats->st_stderr * 2.326; - stats->st_skew = sk / (std * std * std) / (double)(count); - stats->st_kurtosis = ku / (std * std * std * std) / - (double)(count) - 3; - - return (0); -} - -/* - * does a least squares fit to the set of points x, y and - * fits a line y = a + bx. Returns a, b - */ - -int -fit_line(double *x, double *y, int count, double *a, double *b) -{ - double sumx, sumy, sumxy, sumx2; - double denom; - int i; - - sumx = sumy = sumxy = sumx2 = 0.0; - - for (i = 0; i < count; i++) { - sumx += x[i]; - sumx2 += x[i] * x[i]; - sumy += y[i]; - sumxy += x[i] * y[i]; - } - - denom = count * sumx2 - sumx * sumx; - - if (denom == 0.0) - return (-1); - - *a = (sumy * sumx2 - sumx * sumxy) / denom; - - *b = (count * sumxy - sumx * sumy) / denom; - - return (0); -} - -/* - * empty function for measurement purposes - */ - -int -nop() -{ - return (1); -} - -#define NSECITER 1000 - -static long long -get_nsecs_overhead() -{ - long long s; - - double data[NSECITER]; - stats_t stats; - - int i; - int count; - int outliers; - - (void) getnsecs(); /* warmup */ - (void) getnsecs(); /* warmup */ - (void) getnsecs(); /* warmup */ - - i = 0; - - count = NSECITER; - - for (i = 0; i < count; i++) { - s = getnsecs(); - data[i] = getnsecs() - s; - } - - (void) crunch_stats(data, count, &stats); - - while ((outliers = remove_outliers(data, count, &stats)) != 0) { - count -= outliers; - (void) crunch_stats(data, count, &stats); - } - - return ((long long)stats.st_mean); - -} - -long long -get_nsecs_resolution() -{ - long long y[1000]; - - int i, j, nops, res; - long long start, stop; - - /* - * first, figure out how many nops to use - * to get any delta between time measurements. - * use a minimum of one. - */ - - /* - * warm cache - */ - - stop = start = getnsecs(); - - for (i = 1; i < 10000000; i++) { - start = getnsecs(); - for (j = i; j; j--) - ; - stop = getnsecs(); - if (stop > start) - break; - } - - nops = i; - - /* - * now collect data at linearly varying intervals - */ - - for (i = 0; i < 1000; i++) { - start = getnsecs(); - for (j = nops * i; j; j--) - ; - stop = getnsecs(); - y[i] = stop - start; - } - - /* - * find smallest positive difference between samples; - * this is the timer resolution - */ - - res = 1<<30; - - for (i = 1; i < 1000; i++) { - int diff = y[i] - y[i-1]; - - if (diff > 0 && res > diff) - res = diff; - - } - - return (res); -} - -/* - * remove any data points from the array more than 3 sigma out - */ - -static int -remove_outliers(double *data, int count, stats_t *stats) -{ - double outmin = stats->st_mean - 3 * stats->st_stddev; - double outmax = stats->st_mean + 3 * stats->st_stddev; - - int i, j, outliers; - - for (outliers = i = j = 0; i < count; i++) - if (data[i] > outmax || data[i] < outmin) - outliers++; - else - data[j++] = data[i]; - - return (outliers); -} diff --git a/tools/tests/libMicro/libmicro.h b/tools/tests/libMicro/libmicro.h deleted file mode 100644 index 0359134d1..000000000 --- a/tools/tests/libMicro/libmicro.h +++ /dev/null @@ -1,255 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef LIBMICRO_H -#define LIBMICRO_H - -#include - -#define LIBMICRO_VERSION "0.4.0" - -#define STRSIZE 1024 - -#define STREQ(a,b) (strcmp(a,b) == 0) - -typedef struct { - long long re_count; - long long re_errors; - long long re_t0; - long long re_t1; -} result_t; - -typedef struct { - double sum; - long long count; -} histo_t; - -#define HISTOSIZE 32 -#define DATASIZE 100000 - -/* - * stats we compute on data sets - */ - -typedef struct stats { - double st_min; - double st_max; - double st_mean; - double st_median; - double st_stddev; - double st_stderr; - double st_99confidence; - double st_skew; - double st_kurtosis; - double st_timecorr; /* correlation with respect to time */ -} stats_t; - -/* - * Barrier stuff - */ - -typedef struct { - int ba_hwm; /* barrier setpoint */ - int ba_flag; /* benchmark while true */ - long long ba_deadline; /* when to stop */ - int ba_phase; /* number of time used */ - int ba_waiters; /* how many are waiting */ - -#ifdef USE_SEMOP - int ba_semid; -#else - pthread_mutex_t ba_lock; - pthread_cond_t ba_cv; -#endif - - long long ba_count; /* how many ops */ - long long ba_errors; /* how many errors */ - - int ba_quant; /* how many quant errors */ - int ba_batches; /* how many samples */ - - double ba_starttime; /* test time start */ - double ba_endtime; /* test time end */ - -#ifdef NEVER - double ba_tmin; /* min time taken */ - double ba_tmax; /* max time taken */ - double ba_ctmax; /* max after outliers */ - double ba_mean; /* average value */ - double ba_median; /* median value */ - double ba_rawmedian; /* raw median value */ - double ba_stddev; /* standard deviation */ - double ba_stderr; /* standard error */ - double ba_skew; /* skew */ - double ba_kurtosis; /* kurtosis */ -#endif - stats_t ba_raw; /* raw stats */ - stats_t ba_corrected; /* corrected stats */ - - int ba_outliers; /* outlier count */ - - long long ba_t0; /* first thread/proc */ - long long ba_t1; /* time of last thread */ - long long ba_count0; - long long ba_errors0; - - int ba_datasize; /* possible #items data */ - double ba_data[1]; /* start of data ararry */ -} barrier_t; - - -/* - * Barrier interfaces - */ - -barrier_t *barrier_create(int hwm, int datasize); -int barrier_destroy(barrier_t *bar); -int barrier_queue(barrier_t *bar, result_t *res); - - -/* - * Functions that can be provided by the user - */ - -int benchmark(void *tsd, result_t *res); -int benchmark_init(); -int benchmark_fini(); -int benchmark_initrun(); -int benchmark_finirun(); -int benchmark_initworker(); -int benchmark_finiworker(); -int benchmark_initbatch(void *tsd); -int benchmark_finibatch(void *tsd); -int benchmark_optswitch(int opt, char *optarg); -char *benchmark_result(); - - -/* - * Globals exported to the user - */ - -extern int lm_argc; -extern char **lm_argv; - -extern int lm_optB; -extern int lm_optD; -extern int lm_optH; -extern char *lm_optN; -extern int lm_optP; -extern int lm_optS; -extern int lm_optT; - -extern int lm_defB; -extern int lm_defD; -extern int lm_defH; -extern char *lm_defN; -extern int lm_defP; -extern int lm_defS; -extern int lm_defT; -extern int lm_nsecs_per_op; - -extern char *lm_procpath; -extern char lm_procname[STRSIZE]; -extern char lm_usage[STRSIZE]; -extern char lm_optstr[STRSIZE]; -extern char lm_header[STRSIZE]; -extern size_t lm_tsdsize; - - -/* - * Utility functions - */ - -int getpindex(); -int gettindex(); -void *gettsd(int p, int t); -#if defined(__APPLE__) -int gettsdindex(void *arg); -#endif /* __APPLE__ */ -long long getusecs(); -long long getnsecs(); -int setfdlimit(int limit); -long long sizetoll(); -int sizetoint(); -int fit_line(double *, double *, int, double *, double *); -long long get_nsecs_resolution(); - - -/* Apple Mods Here */ - - - -#ifdef NO_PORTMAPPER -#define TCP_SELECT -31233 -#define TCP_XACT -31234 -#define TCP_CONTROL -31235 -#define TCP_DATA -31236 -#define TCP_CONNECT -31237 -#define UDP_XACT -31238 -#define UDP_DATA -31239 -#else -#define TCP_SELECT (u_long)404038 /* XXX - unregistered */ -#define TCP_XACT (u_long)404039 /* XXX - unregistered */ -#define TCP_CONTROL (u_long)404040 /* XXX - unregistered */ -#define TCP_DATA (u_long)404041 /* XXX - unregistered */ -#define TCP_CONNECT (u_long)404042 /* XXX - unregistered */ -#define UDP_XACT (u_long)404032 /* XXX - unregistered */ -#define UDP_DATA (u_long)404033 /* XXX - unregistered */ -#define VERS (u_long)1 -#endif - -/* -* socket send/recv buffer optimizations -*/ -#define SOCKOPT_READ 0x0001 -#define SOCKOPT_WRITE 0x0002 -#define SOCKOPT_RDWR 0x0003 -#define SOCKOPT_PID 0x0004 -#define SOCKOPT_REUSE 0x0008 -#define SOCKOPT_NONE 0 - -#ifndef SOCKBUF -#define SOCKBUF (1024*1024) -#endif - -#ifndef XFERSIZE -#define XFERSIZE (64*1024) /* all bandwidth I/O should use this */ -#endif - -typedef unsigned long iter_t; - -int tcp_server(int prog, int rdwr); -int tcp_done(int prog); -int tcp_accept(int sock, int rdwr); -int tcp_connect(char *host, int prog, int rdwr); -void sock_optimize(int sock, int rdwr); -int sockport(int s); - -/* end Apple Mods */ - - -#endif /* LIBMICRO_H */ diff --git a/tools/tests/libMicro/libmicro_main.c b/tools/tests/libMicro/libmicro_main.c deleted file mode 100644 index f7bcde105..000000000 --- a/tools/tests/libMicro/libmicro_main.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * Separate file for main so we can link other programs - * with libmicro - */ - -#include - -extern int actual_main(int, char **); - -int -main(int argc, char *argv[]) -{ - return (actual_main(argc, argv)); -} diff --git a/tools/tests/libMicro/listen.c b/tools/tests/libMicro/listen.c deleted file mode 100644 index f8730d7bf..000000000 --- a/tools/tests/libMicro/listen.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * listen benchmark - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libmicro.h" - -#define FIRSTPORT 12345 - -static struct sockaddr_in adds; -static int sock = -1; - -int -benchmark_init() -{ - (void) sprintf(lm_usage, "notes: measures listen()()\n"); - - lm_tsdsize = 0; - - return (0); -} - -int -benchmark_initrun() -{ - int j; - int opt = 1; - struct hostent *host; - - sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock == -1) { - perror("socket"); - exit(1); - } - - if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, - &opt, sizeof (int)) == -1) { - perror("setsockopt"); - exit(1); - } - - if ((host = gethostbyname("localhost")) == NULL) { - perror("gethostbyname"); - exit(1); - } - - j = FIRSTPORT; - for (;;) { - (void) memset(&adds, 0, sizeof (struct sockaddr_in)); - adds.sin_family = AF_INET; - adds.sin_port = htons(j++); - (void) memcpy(&adds.sin_addr.s_addr, host->h_addr_list[0], - sizeof (struct in_addr)); - - if (bind(sock, (struct sockaddr *)&adds, - sizeof (struct sockaddr_in)) == 0) { - break; - } - - if (errno != EADDRINUSE) { - perror("bind"); - exit(1); - } - } - - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - - for (i = 0; i < lm_optB; i += 2) { - if (listen(sock, 4) == -1) - res->re_errors++; - if (listen(sock, 5) == -1) - res->re_errors++; - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/localtime_r.c b/tools/tests/libMicro/localtime_r.c deleted file mode 100644 index 84308844f..000000000 --- a/tools/tests/libMicro/localtime_r.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * localtime benchmark - */ - -#include -#include -#include -#include - -#include "libmicro.h" - -int -benchmark_init() -{ - (void) sprintf(lm_usage, "notes: measures localtime_r()\n"); - lm_tsdsize = 0; - - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - struct tm tms; - static time_t clock1 = 0L; - static time_t clock2 = 1L; - - for (i = 0; i < lm_optB; i += 10) { - (void) localtime_r(&clock1, &tms); - (void) localtime_r(&clock2, &tms); - (void) localtime_r(&clock1, &tms); - (void) localtime_r(&clock2, &tms); - (void) localtime_r(&clock1, &tms); - (void) localtime_r(&clock2, &tms); - (void) localtime_r(&clock1, &tms); - (void) localtime_r(&clock2, &tms); - (void) localtime_r(&clock1, &tms); - (void) localtime_r(&clock2, &tms); - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/log.c b/tools/tests/libMicro/log.c deleted file mode 100644 index 71910e079..000000000 --- a/tools/tests/libMicro/log.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * log benchmark - should do wider range... - */ - -#include -#include -#include -#include - -#include "libmicro.h" - -int -benchmark_init() -{ - (void) sprintf(lm_usage, "note: measures log()"); - lm_nsecs_per_op = 75; - lm_tsdsize = 0; - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - /* Added as part of the fix for radar 7508837 */ - double t = 0.0; - - for (i = 0; i < lm_optB; i += 10) { - double value = i + .01; -#if 1 /* Apple added code, see radar 7508837 */ - t += log(value); - t += log(value + 1.0); - t += log(value + 2.0); - t += log(value + 3.0); - t += log(value + 4.0); - t += log(value + 5.0); - t += log(value + 6.0); - t += log(value + 7.0); - t += log(value + 8.0); - t += log(value + 9.0); - } - res->re_count = i; - - return ((int)(t - t)); -#else - (void) log(value); - (void) log(value); - (void) log(value); - (void) log(value); - (void) log(value); - (void) log(value); - (void) log(value); - (void) log(value); - (void) log(value); - (void) log(value); - } - res->re_count = i; - - return (0); -#endif /* end of Apple fix */ -} diff --git a/tools/tests/libMicro/longjmp.c b/tools/tests/libMicro/longjmp.c deleted file mode 100644 index 43c54d48a..000000000 --- a/tools/tests/libMicro/longjmp.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * benchmark longjmp - */ - -#include -#include -#include -#include - -#include "libmicro.h" - -int -benchmark_init() -{ - (void) sprintf(lm_usage, "notes: measures longjmp()\n"); - lm_tsdsize = 0; - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ -#if 1 /* Apple fix to longjmp/siglongjmp tests, see radar 7440118 */ - volatile int i = 0; -#else - int i = 0; -#endif /*end of Apple fix */ - - jmp_buf env; - - (void) setjmp(env); - i++; - if (i < lm_optB) - longjmp(env, 0); - - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/lrand48.c b/tools/tests/libMicro/lrand48.c deleted file mode 100644 index e82ddfdc1..000000000 --- a/tools/tests/libMicro/lrand48.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * lrand48 - */ - -#include -#include -#include - -#include "libmicro.h" - -int -benchmark_init() -{ - (void) sprintf(lm_usage, "note: measures lrand48()"); - lm_nsecs_per_op = 10; - lm_tsdsize = 0; - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - - for (i = 0; i < lm_optB; i += 10) { - (void) lrand48(); - (void) lrand48(); - (void) lrand48(); - (void) lrand48(); - (void) lrand48(); - (void) lrand48(); - (void) lrand48(); - (void) lrand48(); - (void) lrand48(); - (void) lrand48(); - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/lseek.c b/tools/tests/libMicro/lseek.c deleted file mode 100644 index 6ca4af4cd..000000000 --- a/tools/tests/libMicro/lseek.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * lseek - */ - -#ifdef linux -#define _XOPEN_SOURCE 500 -#endif - -#include -#include -#include -#include - -#include "libmicro.h" - -#define DEFF "/dev/zero" -#define DEFS 1024 - -static char *optf = DEFF; -static long long opts = DEFS; - -typedef struct { - int ts_once; - int ts_fd; -} tsd_t; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "f:s:"); - - (void) sprintf(lm_usage, - " [-f file-to-read (default %s)]\n" - " [-s buffer-size (default %d)]\n" - "notes: measures lseek()\n", - DEFF, DEFS); - - (void) sprintf(lm_header, "%8s", "size"); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'f': - optf = optarg; - break; - case 's': - opts = sizetoll(optarg); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - - if (ts->ts_once++ == 0) { - ts->ts_fd = open(optf, O_RDONLY); - } - - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - for (i = 0; i < lm_optB; i += 2) { - if (lseek(ts->ts_fd, 0L, SEEK_SET) != 0) { - res->re_errors++; - } - if (lseek(ts->ts_fd, opts, SEEK_SET) != opts) { - res->re_errors++; - } - } - res->re_count = i; - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - - (void) sprintf(result, "%8lld", opts); - - return (result); -} diff --git a/tools/tests/libMicro/malloc.c b/tools/tests/libMicro/malloc.c deleted file mode 100644 index 1e2568024..000000000 --- a/tools/tests/libMicro/malloc.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * malloc benchmark (crude) - */ - - -#include -#include -#include -#include -#include - -#include "libmicro.h" - -static int optg = 100; -static int opts[32] = {32}; -static int optscnt = 0; - -typedef struct { - void **ts_glob; -} tsd_t; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "s:g:"); - - (void) sprintf(lm_usage, - " [-g number of mallocs before free (default %d)]\n" - " [-s size to malloc (default %d)." - " Up to 32 sizes accepted\n" - "notes: measures malloc()/free()", - optg, opts[0]); - - (void) sprintf(lm_header, "%6s %6s", "glob", "sizes"); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - int tmp; - switch (opt) { - case 'g': - optg = sizetoint(optarg); - break; - case 's': - opts[optscnt] = sizetoint(optarg); - tmp = ((++optscnt) & (0x1F)); - optscnt = tmp; - break; - default: - return (-1); - } - - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - - if (optscnt == 0) - optscnt = 1; - - ts->ts_glob = malloc(sizeof (void *)* optg); - if (ts->ts_glob == NULL) { - return (1); - } - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i, j, k; - - for (i = 0; i < lm_optB; i++) { - for (k = j = 0; j < optg; j++) { - if ((ts->ts_glob[j] = malloc(opts[k++])) == NULL) - res->re_errors++; - if (k >= optscnt) - k = 0; - } - for (j = 0; j < optg; j++) { - free(ts->ts_glob[j]); - } - } - - res->re_count = i * j; - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - int i; - - (void) sprintf(result, "%6d ", optg); - - for (i = 0; i < optscnt; i++) - (void) sprintf(result + strlen(result), "%d ", opts[i]); - return (result); -} diff --git a/tools/tests/libMicro/memcpy.c b/tools/tests/libMicro/memcpy.c deleted file mode 100644 index 9a9448c34..000000000 --- a/tools/tests/libMicro/memcpy.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * memcpy - */ - -#include -#include -#include -#include - -#include "libmicro.h" - -#define DEFS 8192 -#define DEFR 1 - -static long long opts = DEFS; -static int optf; -static int optt; -static int opta; - -typedef struct { - char *ts_src; - char *ts_dest; - int ts_srcsize; - int ts_destsize; -} tsd_t; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "a:s:ft"); - - (void) sprintf(lm_usage, - " [-s buffer-size (default %d)]\n" - " [-a relative alignment (default page aligned)]\n" - " [-f (rotate \"from\" buffer to keep it out of cache)]\n" - " [-t (rotate \"to\" buffer to keep it out of cache)]\n" - "notes: measures memcpy()\n", - DEFS); - - (void) sprintf(lm_header, "%8s", "size"); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'f': - optf++; - break; - case 't': - optt++; - break; - case 's': - opts = sizetoll(optarg); - break; - case 'a': - opta = sizetoint(optarg); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - - if (optf) - ts->ts_srcsize = 64 * 1024 * 1024; - else - ts->ts_srcsize = opts + opta; - - if (optt) - ts->ts_destsize = 64 * 1024 * 1024; - else - ts->ts_destsize = (int)opts; - - - ts->ts_src = opta + (char *)valloc(ts->ts_srcsize); - ts->ts_dest = valloc(ts->ts_destsize); - - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - char *src = ts->ts_src; - char *dest = ts->ts_dest; - - int bump = (int)opts; - - if (bump < 1024) - bump = 1024; /* avoid prefetched area */ - for (i = 0; i < lm_optB; i++) { - (void) memcpy(dest, src, opts); - if (optf) { - src += bump; - if (src + opts > ts->ts_src + ts->ts_srcsize) - src = ts->ts_src; - } - if (optt) { - dest += bump; - if (dest + opts > ts->ts_dest + ts->ts_destsize) - dest = ts->ts_dest; - } - } - - res->re_count = i; - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - - (void) sprintf(result, "%8lld", opts); - - return (result); -} diff --git a/tools/tests/libMicro/memmove.c b/tools/tests/libMicro/memmove.c deleted file mode 100644 index 822c88597..000000000 --- a/tools/tests/libMicro/memmove.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * memmove - */ - -#include -#include -#include -#include - -#include "libmicro.h" - -#define DEFS 8192 -#define DEFR 1 - -static long long opts = DEFS; -static int optf; -static int optt; -static int opta; - -typedef struct { - char *ts_src; - char *ts_dest; - int ts_srcsize; - int ts_destsize; -} tsd_t; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "a:s:ft"); - - (void) sprintf(lm_usage, - " [-s buffer-size (default %d)]\n" - " [-a relative alignment (default page aligned)]\n" - " [-f (rotate \"from\" buffer to keep it out of cache)]\n" - " [-t (rotate \"to\" buffer to keep it out of cache)]\n" - "notes: measures memmove()\n", - DEFS); - - (void) sprintf(lm_header, "%8s", "size"); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'f': - optf++; - break; - case 't': - optt++; - break; - case 's': - opts = sizetoll(optarg); - break; - case 'a': - opta = sizetoint(optarg); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - - if (optf) - ts->ts_srcsize = 64 * 1024 * 1024; - else - ts->ts_srcsize = opts + opta; - - if (optt) - ts->ts_destsize = 64 * 1024 * 1024; - else - ts->ts_destsize = (int)opts; - - - ts->ts_src = opta + (char *)valloc(ts->ts_srcsize); - ts->ts_dest = valloc(ts->ts_destsize); - - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - char *src = ts->ts_src; - char *dest = ts->ts_dest; - - int bump = (int)opts; - - if (bump < 1024) - bump = 1024; /* avoid prefetched area */ - for (i = 0; i < lm_optB; i++) { - (void) memmove(dest, src, opts); - if (optf) { - src += bump; - if (src + opts > ts->ts_src + ts->ts_srcsize) - src = ts->ts_src; - } - if (optt) { - dest += bump; - if (dest + opts > ts->ts_dest + ts->ts_destsize) - dest = ts->ts_dest; - } - } - - res->re_count = i; - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - - (void) sprintf(result, "%8lld", opts); - - return (result); -} diff --git a/tools/tests/libMicro/memrand.c b/tools/tests/libMicro/memrand.c deleted file mode 100644 index 8a9ccf326..000000000 --- a/tools/tests/libMicro/memrand.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * memory access time check - */ - -#include -#include -#include -#include -#include - -#include "libmicro.h" - -static long opts = 1024*1024; - -typedef struct { - long **ts_data; - long ts_result; -} tsd_t; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "s:"); - - (void) sprintf(lm_usage, - " [-s size] number of bytes to " - " access (default %ld)\n" - "notes: measures \"random\" memory access times\n", - opts); - - (void) sprintf(lm_header, "%8s", "size"); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 's': - opts = sizetoint(optarg); - break; - default: - return (-1); - } - - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i, j; - - ts->ts_data = malloc(opts); - - if (ts->ts_data == NULL) { - return (1); - } - - /* - * use lmbench style backwards stride - */ - - for (i = 0; i < opts / sizeof (long); i++) { - j = i - 128; - if (j < 0) - j = j + opts / sizeof (long); - ts->ts_data[i] = (long *)&(ts->ts_data[j]); - } - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - long **ptr = ts->ts_data; - - - - for (i = 0; i < lm_optB; i += 10) { - ptr = (long **)*ptr; - ptr = (long **)*ptr; - ptr = (long **)*ptr; - ptr = (long **)*ptr; - ptr = (long **)*ptr; - ptr = (long **)*ptr; - ptr = (long **)*ptr; - ptr = (long **)*ptr; - ptr = (long **)*ptr; - ptr = (long **)*ptr; - } - - ts->ts_result = (long)*ptr; - - res->re_count = i; - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - - (void) sprintf(result, "%8ld ", opts); - - - return (result); -} diff --git a/tools/tests/libMicro/memset.c b/tools/tests/libMicro/memset.c deleted file mode 100644 index 8a6345409..000000000 --- a/tools/tests/libMicro/memset.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * memset - */ - -#include -#include -#include -#include - -#include "libmicro.h" - -#define DEFS 8192 - -static long long opts = DEFS; -static int opta = 0; -static int optu = 0; - -static char *optas = "4k"; - -typedef struct { - char *ts_buff; - int ts_size; - int ts_offset; -} tsd_t; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "a:us:"); - - (void) sprintf(lm_usage, - " [-s buffer-size (default %d)]\n" - " [-a alignment (force buffer alignment)]\n" - " [-u (try to always use uncached memory)]" - "notes: measures memset()\n", - DEFS); - - (void) sprintf(lm_header, "%8s%16s", "size", "alignment"); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'u': - optu = 1; - break; - case 's': - opts = sizetoll(optarg); - break; - case 'a': - opta = sizetoll(optarg); - if (opta > 4096) - opta = 0; - else - optas = optarg; - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int errors = 0; - int i; - - if (optu) { - ts->ts_size = 1024 * 1024 * 64; - ts->ts_offset = opta; - } else { - ts->ts_size = opta + opts; - ts->ts_offset = opta; - } - - if ((ts->ts_buff = (char *)valloc(ts->ts_size)) == NULL) - errors++; - - for (i = 0; i < ts->ts_size; i++) - ts->ts_buff[i] = 0; - return (errors); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - tsd_t *ts = (tsd_t *)tsd; - - - if (optu) { - char *buf = ts->ts_buff + ts->ts_offset; - char *end = ts->ts_buff + ts->ts_size; - int offset = ts->ts_offset; - - unsigned long tmp; - - for (i = 0; i < lm_optB; i ++) { - (void) memset(buf, 0, opts); - tmp = (((unsigned long)buf + opts + 4095) & ~4095) + offset; - buf = (char *) tmp; - if (buf + opts > end) - buf = ts->ts_buff + offset; - } - } else { - char *buf = ts->ts_buff + ts->ts_offset; - - for (i = 0; i < lm_optB; i += 10) { - (void) memset(buf, 0, opts); - (void) memset(buf, 0, opts); - (void) memset(buf, 0, opts); - (void) memset(buf, 0, opts); - (void) memset(buf, 0, opts); - (void) memset(buf, 0, opts); - (void) memset(buf, 0, opts); - (void) memset(buf, 0, opts); - (void) memset(buf, 0, opts); - (void) memset(buf, 0, opts); - } - } - res->re_count = i; - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - - (void) sprintf(result, "%8lld%12s", opts, optas); - - return (result); -} diff --git a/tools/tests/libMicro/mk_tarball b/tools/tests/libMicro/mk_tarball deleted file mode 100755 index fcac23e85..000000000 --- a/tools/tests/libMicro/mk_tarball +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/sh -x -# -# Copyright 2003 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# -# -# script to make tarball... args are contents to be inserted -# - -libmicro_version=`bin/getpid -V` -case $libmicro_version in -[0-9]*) - ;; -*) - echo "ERROR: cannot determine libMicro version" - exit 1 -esac -dirname="libMicro-$libmicro_version" - -here=`pwd` -target=$here/libMicro.tar -tmpdir=/private/tmp/libmicro.$$ -mkdir -p $tmpdir/$dirname -cp $* $tmpdir/$dirname -cd $tmpdir -tar cvf $target $dirname -cd $here -rm -rf $tmpdir diff --git a/tools/tests/libMicro/mktime.c b/tools/tests/libMicro/mktime.c deleted file mode 100644 index 9738ce504..000000000 --- a/tools/tests/libMicro/mktime.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * mktime - */ - -#include -#include -#include -#include - -#include "libmicro.h" - -typedef struct { - struct tm ts_tm1; - struct tm ts_tm2; -} tsd_t; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_usage, - "notes: measures mktime()\n"); - - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - - time_t clock1; - time_t clock2; - - clock1 = time(NULL); - clock2 = clock1 + 1; - - (void) localtime_r(&clock1, &ts->ts_tm1); - (void) localtime_r(&clock2, &ts->ts_tm2); - - return (0); -} - - -int -benchmark(void *tsd, result_t *res) -{ - int i; - tsd_t *ts = (tsd_t *)tsd; - struct tm t1, t2; - - for (i = 0; i < lm_optB; i += 10) { - t1 = ts->ts_tm1; - t2 = ts->ts_tm2; - (void) mktime(&t1); - (void) mktime(&t2); - - t1 = ts->ts_tm1; - t2 = ts->ts_tm2; - (void) mktime(&t1); - (void) mktime(&t2); - - t1 = ts->ts_tm1; - t2 = ts->ts_tm2; - (void) mktime(&t1); - (void) mktime(&t2); - - t1 = ts->ts_tm1; - t2 = ts->ts_tm2; - (void) mktime(&t1); - (void) mktime(&t2); - - t1 = ts->ts_tm1; - t2 = ts->ts_tm2; - (void) mktime(&t1); - (void) mktime(&t2); - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/mmap.c b/tools/tests/libMicro/mmap.c deleted file mode 100644 index 44b8b5883..000000000 --- a/tools/tests/libMicro/mmap.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2002 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include -#include -#include -#include - -#include "libmicro.h" - -typedef volatile char vchar_t; - -typedef struct { - int ts_once; - vchar_t ** ts_map; - vchar_t ts_foo; -} tsd_t; - -#define DEFF "/dev/zero" -#define DEFL 8192 - -static char *optf = DEFF; -static long long optl = DEFL; -static int optr = 0; -static int opts = 0; -static int optw = 0; -static int fd = -1; -static int anon = 0; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "f:l:rsw"); - - (void) sprintf(lm_usage, - " [-f file-to-map (default %s)]\n" - " [-l mapping-length (default %d)]\n" - " [-r] (read a byte from each page)\n" - " [-w] (write a byte on each page)\n" - " [-s] (use MAP_SHARED)\n" - "notes: measures mmap()\n", - DEFF, DEFL); - - (void) sprintf(lm_header, "%8s %5s", "length", "flags"); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'f': - optf = optarg; - anon = strcmp(optf, "MAP_ANON") == 0; - break; - case 'l': - optl = sizetoll(optarg); - break; - case 'r': - optr = 1; - break; - case 's': - opts = 1; - break; - case 'w': - optw = 1; - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initrun() -{ - if (!anon) - fd = open(optf, O_RDWR); - - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int errors = 0; - - if (ts->ts_once++ == 0) { - ts->ts_map = (vchar_t **)malloc(lm_optB * sizeof (void *)); - if (ts->ts_map == NULL) { - errors++; - } - } - - return (errors); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i, j; - - for (i = 0; i < lm_optB; i++) { - if (anon) { - ts->ts_map[i] = (vchar_t *)mmap(NULL, optl, - PROT_READ | PROT_WRITE, - MAP_ANON | (opts ? MAP_SHARED : MAP_PRIVATE), - -1, 0L); - } else { - ts->ts_map[i] = (vchar_t *)mmap(NULL, optl, - PROT_READ | PROT_WRITE, - opts ? MAP_SHARED : MAP_PRIVATE, - fd, 0L); - } - - if (ts->ts_map[i] == MAP_FAILED) { - res->re_errors++; - continue; - } - - if (optr) { - for (j = 0; j < optl; j += 4096) { - ts->ts_foo += ts->ts_map[i][j]; - } - } - if (optw) { - for (j = 0; j < optl; j += 4096) { - ts->ts_map[i][j] = 1; - } - } - } - res->re_count = i; - - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - for (i = 0; i < lm_optB; i++) { - (void) munmap((void *)ts->ts_map[i], optl); - } - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - char flags[5]; - - flags[0] = anon ? 'a' : '-'; - flags[1] = optr ? 'r' : '-'; - flags[2] = optw ? 'w' : '-'; - flags[3] = opts ? 's' : '-'; - flags[4] = 0; - - (void) sprintf(result, "%8lld %5s", optl, flags); - - return (result); -} diff --git a/tools/tests/libMicro/mprotect.c b/tools/tests/libMicro/mprotect.c deleted file mode 100644 index db6ecaae4..000000000 --- a/tools/tests/libMicro/mprotect.c +++ /dev/null @@ -1,205 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include -#include -#include -#include - -#include "libmicro.h" - -typedef volatile char vchar_t; - -typedef struct { - int ts_batch; - int ts_res; -} tsd_t; - -#define DEFF "/dev/zero" -#define DEFL 8192 - -static char *optf = DEFF; -static long long optl = DEFL; -static int optr = 0; -static int optw = 0; -static int opts = 0; -static int optt = 0; -static int fd = -1; -static int anon = 0; -static int foo = 0; -static vchar_t *seg; -static int pagesize; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "f:l:rstw"); - - (void) sprintf(lm_usage, - " [-f file-to-map (default %s)]\n" - " [-l mapping-length (default %d)]\n" - " [-r] (read a byte from each page)\n" - " [-w] (write a byte on each page)\n" - " [-s] (use MAP_SHARED)\n" - " [-t] (touch each page after restoring permissions)\n" - "notes: measures mprotect()\n", - DEFF, DEFL); - - (void) sprintf(lm_header, "%8s %5s", "size", "flags"); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'f': - optf = optarg; - anon = strcmp(optf, "MAP_ANON") == 0; - break; - case 'l': - optl = sizetoll(optarg); - break; - case 'r': - optr = 1; - break; - case 's': - opts = 1; - break; - case 't': - optt = 1; - break; - case 'w': - optw = 1; - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initrun() -{ - int flags; - int i; - - if (!anon) - fd = open(optf, O_RDWR); - - flags = opts ? MAP_SHARED : MAP_PRIVATE; - flags |= anon ? MAP_ANON : 0; - - seg = (vchar_t *)mmap(NULL, lm_optB * optl, PROT_READ | PROT_WRITE, - flags, anon ? -1 : fd, 0L); - - if (seg == MAP_FAILED) { - return (-1); - } - - if (optr) { - for (i = 0; i < lm_optB * optl; i += 4096) { - foo += seg[i]; - } - } - - if (optw) { - for (i = 0; i < lm_optB * optl; i += 4096) { - seg[i] = 1; - } - } - - pagesize = getpagesize(); - - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - int us; - int prot = PROT_NONE; - int j, k; - -#if !defined(__APPLE__) - us = (getpindex() * lm_optT) + gettindex(); -#else - us = gettsdindex(tsd); -#endif /* __APPLE__ */ - - for (i = 0; i < lm_optB; i++) { - switch ((us + ts->ts_batch + i) % 2) { - case 0: - prot = PROT_NONE; - if (optt) { - for (j = k = 0; j < optl; j += pagesize) - k += seg[i * optl + j]; - ts->ts_res += k; - } - break; - default: - prot = PROT_READ | PROT_WRITE; - break; - } - - if (mprotect((void *)&seg[i * optl], optl, prot) == -1) { - res->re_errors++; - } - } - res->re_count += lm_optB; - ts->ts_batch++; - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - char flags[6]; - - flags[0] = anon ? 'a' : '-'; - flags[1] = optr ? 'r' : '-'; - flags[2] = optw ? 'w' : '-'; - flags[3] = opts ? 's' : '-'; - flags[4] = optt ? 't' : '-'; - flags[5] = 0; - - (void) sprintf(result, "%8lld %5s", optl, flags); - - return (result); -} diff --git a/tools/tests/libMicro/msync.c b/tools/tests/libMicro/msync.c deleted file mode 100644 index 48b05109d..000000000 --- a/tools/tests/libMicro/msync.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include -#include -#include -#include - -#include "libmicro.h" - -typedef struct { - char *ts_map; - int ts_foo; /* defeat optimizers */ -} tsd_t; - -#define DEFF "/dev/zero" -#define DEFL 8192 - -static char *optf = DEFF; -static long long optl = DEFL; -static int optr = 0; -static int opts = 0; -static int optw = 0; -static int opta = MS_SYNC; -static int opti = 0; -static int anon = 0; -static int pagesize; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "af:il:rsw"); - - (void) sprintf(lm_usage, - " [-f file-to-map (default %s)]\n" - " [-l mapping-length (default %d)]\n" - " [-r] (read a byte from each page between msyncs)\n" - " [-w] (write a byte to each page between msyncs)\n" - " [-s] (use MAP_SHARED instead of MAP_PRIVATE)\n" - " [-a (specify MS_ASYNC rather than default MS_SYNC)\n" - " [-i (specify MS_INVALIDATE)\n" - "notes: measures msync()\n", - DEFF, DEFL); - - (void) sprintf(lm_header, "%8s %6s", "length", "flags"); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'a': - opta = MS_ASYNC; - break; - - case 'f': - optf = optarg; - break; - - case 'i': - opti = MS_INVALIDATE; - break; - - case 'l': - optl = sizetoll(optarg); - break; - case 'r': - optr = 1; - break; - case 's': - opts = 1; - break; - case 'w': - optw = 1; - break; - default: - return (-1); - } - - pagesize = getpagesize(); - - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - - int fd; - - if ((fd = open(optf, O_RDWR)) < 0) { - perror("open:"); - return (1); - } - - (void) ftruncate(fd, optl); - - if ((ts->ts_map = (char *)mmap(NULL, optl, - PROT_READ | PROT_WRITE, opts ? MAP_SHARED : MAP_PRIVATE, - fd, 0L)) == MAP_FAILED) { - perror("mmap:"); - (void) close(fd); - return (1); - } - - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i, j; - - for (i = 0; i < lm_optB; i++) { - - if (msync(ts->ts_map, optl, opta | opti) < 0) { - perror("msync:"); - res->re_errors++; - break; - } - - if (optr) { - for (j = 0; j < optl; j += pagesize) { - ts->ts_foo += ts->ts_map[j]; - } - } - - if (optw) { - for (j = 0; j < optl; j += pagesize) { - ts->ts_map[j] = 1; - } - } - } - res->re_count = i; - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - char flags[6]; - - flags[0] = anon ? 'a' : '-'; - flags[1] = optr ? 'r' : '-'; - flags[2] = optw ? 'w' : '-'; - flags[3] = opts ? 's' : '-'; - flags[4] = opti ? 'i' : '-'; - flags[5] = 0; - - (void) sprintf(result, "%8lld %6s", optl, flags); - - return (result); -} diff --git a/tools/tests/libMicro/multiview.sh b/tools/tests/libMicro/multiview.sh deleted file mode 100755 index c1608f058..000000000 --- a/tools/tests/libMicro/multiview.sh +++ /dev/null @@ -1,201 +0,0 @@ -#!/bin/sh -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms -# of the Common Development and Distribution License -# (the "License"). You may not use this file except -# in compliance with the License. -# -# You can obtain a copy of the license at -# src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing -# permissions and limitations under the License. -# -# When distributing Covered Code, include this CDDL -# HEADER in each file and include the License file at -# usr/src/OPENSOLARIS.LICENSE. If applicable, -# add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your -# own identifying information: Portions Copyright [yyyy] -# [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2005 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# output html comparison of several libmicro output data files -# usage: multiview file1 file2 file3 file4 ... -# -# relative ranking is calculated using first as reference -# color interpolation is done to indicate relative performance; -# the redder the color, the slower the result, the greener the -# faster - -awk ' BEGIN { - benchmark_count = 0; - header_count = 0; -} -/^#/ { - next; - } -/errors/ { - next; - } -/^\!/ { - split($0, A_header, ":"); - name = substr(A_header[1],2); - headers[name]=name; - header_data[name,FILENAME] = substr($0, length(name) + 3); - if (header_names[name] == 0) { - header_names[name] = ++header_count; - headers[header_count] = name; - } - next; -} - - { - if(NF >= 7) { - if (benchmark_names[$1] == 0) { - benchmark_names[$1] = ++benchmark_count; - benchmarks[benchmark_count] = $1; - } - if ($6 == 0) - benchmark_data[$1,FILENAME] = $4; - else - benchmark_data[$1,FILENAME] = -1; - } -} - -END { - printf("\n"); - printf("\n"); - printf("\n"); - printf("\n"); - printf("\n"); - printf("multiview comparison\n") - printf("\n"); - printf("\n"); - printf("\n"); - printf("\n"); - printf("\n"); - for(i = 1; i <= header_count; i++) { - hname = headers[i]; - printf("\n", hname); - - for (j = 1; j < ARGC; j++) { - sub("^[\t ]+", "", header_data[hname, ARGV[j]]); - printf("\n", header_data[hname, ARGV[j]]); - } - printf("\n"); - } - printf("\n"); - printf("\n"); - printf("\n"); - - for (i = 2; i < ARGC; i++) - printf("\n"); - - printf("\n"); - for(i = 1; i < benchmark_count; i++) { - for(j = 1; j < benchmark_count; j++) { - if (benchmarks[j] > benchmarks[j + 1]) { - tmp = benchmarks[j]; - benchmarks[j] = benchmarks[j+1]; - benchmarks[j+1] = tmp; - } - } - } - - for(i = 1; i <= benchmark_count; i++) { - name = benchmarks[i]; - a = benchmark_data[name, ARGV[1]]; - - printf("\n"); - printf("\n", name); - if (a > 0) - printf("\n", a); - else { - if (a < 0) - printf("\n", "ERRORS"); - else - printf("\n", "missing"); - - for (j = 2; j < ARGC; j++) - printf("\n", "not computed"); - continue; - } - - for (j = 2; j < ARGC; j++) { - b = benchmark_data[name, ARGV[j]]; - if (b > 0) { - factor = b/a; - bgcolor = colormap(factor); - if (factor > 1) - percentage = -(factor * 100 - 100); - if (factor <= 1) - percentage = 100/factor - 100; - - printf("\n", - bgcolor, b, percentage); - } - - else if (b < 0) - printf("\n", "ERRORS"); - else - printf("\n", "missing"); - - } - printf("\n"); - - } - printf("
%s%s
BENCHMARKUSECSUSECS [percentage]
%s
%f
%s%s%s
%11.5f[%#+7.1f%%]
%s%25s
\n"); - -} - -function colormap(value, bgcolor, r, g, b) -{ - if (value <= .2) - value = .2; - if (value > 5) - value = 5; - - if (value < .9) { - r = colorcalc(.2, value, .9, 0, 255); - g = colorcalc(.2, value, .9, 153, 255); - b = colorcalc(.2, value, .9, 0, 255); - bgcolor=sprintf("#%2.2x%2.2x%2.2x", r, g, b); - } - else if (value < 1.1) - bgcolor="#ffffff"; - else { - r = 255; - g = colorcalc(1.1, value, 5, 255, 0); - b = colorcalc(1.1, value, 5, 255, 0); - bgcolor=sprintf("#%2.2x%2.2x%2.2x", r, g, b); - } - - return (bgcolor); -} - -function colorcalc(min, value, max, mincolor, maxcolor) -{ - return((value - min)/(max-min) * (maxcolor-mincolor) + mincolor); -} - -' "$@" - - diff --git a/tools/tests/libMicro/munmap.c b/tools/tests/libMicro/munmap.c deleted file mode 100644 index 7979dbba2..000000000 --- a/tools/tests/libMicro/munmap.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2002 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include -#include -#include -#include - -#include "libmicro.h" - -typedef volatile char vchar_t; - -typedef struct { - int ts_once; - vchar_t ** ts_map; - vchar_t ts_foo; -} tsd_t; - -#define DEFF "/dev/zero" -#define DEFL 8192 - -static char *optf = DEFF; -static long long optl = DEFL; -static int optr = 0; -static int optw = 0; -static int opts = 0; -static int fd = -1; -static int anon = 0; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "f:l:rsw"); - - (void) sprintf(lm_usage, - " [-f file-to-map (default %s)]\n" - " [-l mapping-length (default %d)]\n" - " [-r] (read a byte from each page)\n" - " [-w] (write a byte on each page)\n" - " [-s] (use MAP_SHARED)\n" - "notes: measures munmap()\n", - DEFF, DEFL); - - (void) sprintf(lm_header, "%8s %5s", "size", "flags"); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'f': - optf = optarg; - anon = strcmp(optf, "MAP_ANON") == 0; - break; - case 'l': - optl = sizetoll(optarg); - break; - case 'r': - optr = 1; - break; - case 's': - opts = 1; - break; - case 'w': - optw = 1; - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initrun() -{ - if (!anon) - fd = open(optf, O_RDWR); - - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i, j; - int errors = 0; - - if (ts->ts_once++ == 0) { - ts->ts_map = (vchar_t **)malloc(lm_optB * sizeof (void *)); - if (ts->ts_map == NULL) { - errors++; - } - } - - for (i = 0; i < lm_optB; i++) { - if (anon) { - ts->ts_map[i] = (vchar_t *)mmap(NULL, optl, - PROT_READ | PROT_WRITE, - MAP_ANON | (opts ? MAP_SHARED : MAP_PRIVATE), - -1, 0L); - } else { - ts->ts_map[i] = (vchar_t *)mmap(NULL, optl, - PROT_READ | PROT_WRITE, - opts ? MAP_SHARED : MAP_PRIVATE, - fd, 0L); - } - - if (ts->ts_map[i] == MAP_FAILED) { - errors++; - continue; - } - if (optr) { - for (j = 0; j < optl; j += 4096) { - ts->ts_foo += ts->ts_map[i][j]; - } - } - if (optw) { - for (j = 0; j < optl; j += 4096) { - ts->ts_map[i][j] = 1; - } - } - } - - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - for (i = 0; i < lm_optB; i++) { - if (munmap((void *)ts->ts_map[i], optl) == -1) { - res->re_errors++; - } - } - res->re_count += lm_optB; - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - char flags[5]; - - flags[0] = anon ? 'a' : '-'; - flags[1] = optr ? 'r' : '-'; - flags[2] = optw ? 'w' : '-'; - flags[3] = opts ? 's' : '-'; - flags[4] = 0; - - (void) sprintf(result, "%8lld %5s", optl, flags); - - return (result); -} diff --git a/tools/tests/libMicro/mutex.c b/tools/tests/libMicro/mutex.c deleted file mode 100644 index 3c056af2d..000000000 --- a/tools/tests/libMicro/mutex.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * mutex - */ - -#include -#include -#include -#include -#include - -#include "libmicro.h" - -static int optt = 0; -static int optp = 0; -static int opth = 0; -static int opto = 0; - -pthread_mutex_t *lock; - -typedef struct { - int ts_once; - pthread_mutex_t *ts_lock; -} tsd_t; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_usage, - " [-t] (create dummy thread so we are multithreaded)\n" - " [-p] (use inter-process mutex (not support everywhere))\n" - " [-h usecs] (specify mutex hold time (default 0)\n" - "notes: measures uncontended pthread_mutex_[un,]lock\n"); - - (void) sprintf(lm_optstr, "tph:o:"); - - (void) sprintf(lm_header, "%8s", "holdtime"); - - return (0); -} - -/*ARGSUSED*/ -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'p': - optp = 1; - break; - - case 't': - optt = 1; - break; - - case 'h': - opth = sizetoint(optarg); - break; - - case 'o': - opto = sizetoint(optarg); - break; - - default: - return (-1); - } - return (0); -} - -void * -dummy(void *arg) -{ - (void) pause(); - return (arg); -} - -int -benchmark_initrun() -{ - pthread_mutexattr_t attr; - int errors = 0; - - /*LINTED*/ - lock = (pthread_mutex_t *)mmap(NULL, - getpagesize(), - PROT_READ | PROT_WRITE, - optp?(MAP_ANON | MAP_SHARED):MAP_ANON|MAP_PRIVATE, - -1, 0L) + opto; - - if (lock == MAP_FAILED) { - errors++; - } else { - (void) pthread_mutexattr_init(&attr); - if (optp) - (void) pthread_mutexattr_setpshared(&attr, - PTHREAD_PROCESS_SHARED); - - if (pthread_mutex_init(lock, &attr) != 0) - errors++; - } - - return (errors); -} - -int -benchmark_initworker(void *tsd) -{ - int errors = 0; - tsd_t *ts = (tsd_t *)tsd; - - - if (optt) { - pthread_t tid; - - - - if (pthread_create(&tid, NULL, dummy, NULL) != 0) { - errors++; - } - } - - ts->ts_lock = lock; - - return (errors); -} - -void -spinme(int usecs) -{ - long long s = getusecs(); - - while (getusecs() - s < usecs) - ; -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - for (i = 0; i < lm_optB; i ++) { - - (void) pthread_mutex_lock(ts->ts_lock); - if (opth) - spinme(opth); - (void) pthread_mutex_unlock(ts->ts_lock); - - } - - res->re_count = lm_optB; - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - - (void) sprintf(result, "%8d", opth); - - return (result); -} diff --git a/tools/tests/libMicro/nop.c b/tools/tests/libMicro/nop.c deleted file mode 100644 index 815691f76..000000000 --- a/tools/tests/libMicro/nop.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * silly nop benchmark to test infrastructure - */ - - -#include -#include -#include - -#include "libmicro.h" - -int -benchmark_init() -{ - (void) sprintf(lm_usage, "notes: measures nothing()\n"); - - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - int nop(); - - for (i = 0; i < lm_optB; i++) - (void) nop(); /* do nothing but the call */ - - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/od_account_create.sh b/tools/tests/libMicro/od_account_create.sh deleted file mode 100755 index f087cdcad..000000000 --- a/tools/tests/libMicro/od_account_create.sh +++ /dev/null @@ -1,129 +0,0 @@ -#!/bin/bash - - -function sighandler { - echo - echo "Interrupting account creation" - rm -f $TMPF - exit 1 -} - -trap sighandler INT TERM - -# Fixed parameters -# -NAME=`basename $0` -COUNT=$1 -NODE=$2 -PREFIX="od_test_" -GROUP_ID=1211 # A group everybody's in -GROUP_ID2=1212 # A group nobody's in -GROUP_NAME='od_test_group' -UID_BASE=5000 -TMPF=/tmp/.${NAME}.$$ - -usage () { - echo - echo "Usage: ${NAME} count nodename" - echo - echo " ie. ${NAME} 1000 /Local/Default" - echo - echo " will create users 1000 users (from '${PREFIX}1' to '${PREFIX}1000')" - echo " Default password is set to 'test'" - echo " User ID starts from 5000" - echo " Default group is '${GROUP_NAME}', Group ID 1211" - echo - echo "This tool assumes user 'diradmin' with password 'admin' for OD admin" - echo - exit 85 # WRONGARGS -} - -if [ $# -ne 2 ]; then - usage -fi - -# we don't need credentials if its a local node -if [ $NODE != "/Local/Default" ]; then - OD_ADMIN="diradmin" - OD_PASS="admin" -fi - -echo "Creating users ${PREFIX}1 to ${PREFIX}$COUNT" - -# check to see if od_test_group exist. if not, create one -# -result=`dscl $NODE -list Groups/${GROUP_NAME}1 2> /dev/null` -if [ $? -ne 0 ]; then - echo "Group \"${GROUP_NAME}\" does not exist. Creating ${GROUP_NAME}" - if [ -n "$OD_ADMIN" ]; then - dseditgroup -q -o create -n $NODE -u $OD_ADMIN -P $OD_PASS -i ${GROUP_ID} ${GROUP_NAME}1 - dseditgroup -q -o create -n $NODE -u $OD_ADMIN -P $OD_PASS -i ${GROUP_ID2} ${GROUP_NAME}2 - else - dseditgroup -q -o create -n $NODE -i ${GROUP_ID} ${GROUP_NAME}1 - dseditgroup -q -o create -n $NODE -i ${GROUP_ID2} ${GROUP_NAME}2 - fi -fi - -if [ $? -ne 0 ]; then - echo "Failed to create test_group" - exit 1 -fi - -# using dsimport is faster than using dscl -i=1 -uid=$UID_BASE -echo "Writing a temporary import file ..." -while [ $i -le $COUNT ] -do - result=`dscl $NODE -list Users/${PREFIX}${i} 2> /dev/null` - if [ $? -ne 0 ]; then - # Uses standard template - # RecordName:Password:UniqueID:PrimaryGroupID:DistinguishedName:NFSHomeDirectory:UserShell - echo "${PREFIX}${i}:test:${uid}:1211:${PREFIX}${i}:/Users/${PREFIX}${i}:/bin/bash" >> $TMPF - printf "\r${PREFIX}${i} / ${COUNT}" - else - echo "account $PREFIX$i already exist. skipping" - fi - i=`expr $i + 1` - uid=`expr $uid + 1` -done -echo - -# Now do the real work -# -if [[ -f $TMPF ]]; then - echo "Running dsimport to create users. Please be patient. This takes a while ..." - # assume if admin is provided that slapconfig exists - if [ -n "$OD_ADMIN" ]; then - if [[ -x "/usr/sbin/slapconfig" ]]; then - /usr/sbin/slapconfig -setfullsyncmode no - sleep 2 - fi - /usr/bin/time dsimport $TMPF $NODE I --username $OD_ADMIN --password $OD_PASS --template StandardUser - sleep 2 - if [[ -x "/usr/sbin/slapconfig" ]]; then - /usr/sbin/slapconfig -setfullsyncmode yes - fi - else - /usr/bin/time dsimport $TMPF $NODE I --template StandardUser - sleep 2 - fi - - # and now delete the temp file - # - rm -f $TMPF -else - echo "Nothing done. All users already exist" -fi - -echo Create a SACL group for libMicro -# Create a sample SACL group -dseditgroup -q -o create -r "libMicro ACL" com.apple.access_libMicro -i=1 -while [ $i -le $COUNT ]; do - dseditgroup -q -o edit -a ${PREFIX}${i} -t user com.apple.access_libMicro - i=`expr $i + 1` -done - -echo 'Finished' - diff --git a/tools/tests/libMicro/od_account_delete.sh b/tools/tests/libMicro/od_account_delete.sh deleted file mode 100755 index 45fb0e42c..000000000 --- a/tools/tests/libMicro/od_account_delete.sh +++ /dev/null @@ -1,98 +0,0 @@ -#!/bin/bash - -function sighandler { - echo - echo "Interrupting account creation" - rm -f $TMPF - exit 2 -} - -trap sighandler INT TERM - -# Fixed parameters -# -NAME=`basename $0` -COUNT=$1 -PREFIX="od_test_" -GROUP_NAME='od_test_group' -TMPF=/tmp/.${NAME}.$$ -NODE=$2 - -usage () { - echo - echo "Usage: ${NAME} count nodename" - echo - echo " ie. ${NAME} 1000 /Local/Default" - echo - echo " will delete ${GROUPNAME} and 1000 users " - echo " from '${PREFIX}1' to '${PREFIX}1000'" - echo - echo "This tool assumes user 'diradmin' with password 'admin' for OD admin" - echo "when talking to anything other than /Local/Default" - exit 85 # WRONGARGS -} - -if [ $# -ne 2 ]; then - usage -fi - -# we don't need credentials if its a local node -if [ $NODE != "/Local/Default" ]; then - OD_ADMIN="diradmin" - OD_PASS="admin" -fi - -echo "Deleting users ${PREFIX}1 to ${PREFIX}$COUNT" - -# Using a script file and feed it into dscl is much faster than -# calling dscl everytime. -# -i=1 -echo "Writing a temporary script ..." -if [ -n "$OD_ADMIN" ]; then - echo "auth $OD_ADMIN $OD_PASS" >> $TMPF -fi - -while [ $i -le $COUNT ] -do - result=`dscl $NODE -list Users/${PREFIX}${i} 2> /dev/null` - if [ $? -eq 0 ]; then - echo "delete Users/${PREFIX}${i}" >> $TMPF - printf "\r${PREFIX}${i} / ${COUNT}" - fi - i=`expr $i + 1` -done -echo - -echo "Deleting temporary test groups" -if [ -n "$OD_ADMIN" ]; then - result=`dseditgroup -q -o delete -n $NODE -u $OD_ADMIN -P $OD_PASS ${GROUP_NAME}1 2>&1 /dev/null` - result=`dseditgroup -q -o delete -n $NODE -u $OD_ADMIN -P $OD_PASS ${GROUP_NAME}2 2>&1 /dev/null` -else - result=`dseditgroup -q -o delete -n $NODE ${GROUP_NAME}1 2>&1 /dev/null` - result=`dseditgroup -q -o delete -n $NODE ${GROUP_NAME}2 2>&1 /dev/null` -fi - -result=`dseditgroup -q -o delete com.apple.access_libMicro 2>&1 /dev/null` - -# Now do the real work -# -if [[ -f $TMPF ]]; then - echo "Running dscl to delete users. Please be patient. This takes a while ..." - if [[ -x /usr/sbin/slapconfig ]]; then - /usr/sbin/slapconfig -setfullsyncmode no - fi - - /usr/bin/time dscl ${NODE} < $TMPF - - if [[ -x /usr/sbin/slapconfig ]]; then - /usr/sbin/slapconfig -setfullsyncmode yes - fi -fi - -# and now delete the temp file -# -rm -f $TMPF - -echo 'Finished' - diff --git a/tools/tests/libMicro/open.c b/tools/tests/libMicro/open.c deleted file mode 100644 index 7cdcd76f5..000000000 --- a/tools/tests/libMicro/open.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* - * benchmark open - */ - - -#include -#include -#include -#include - -#include "libmicro.h" - -typedef struct { - int ts_once; - int *ts_fds; -} tsd_t; - -#define DEFF "/dev/null" - -static char *optf = DEFF; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - lm_defB = 256; - - (void) sprintf(lm_usage, - " [-f file-to-open (default %s)]\n" - "notes: measures open()\n", - DEFF); - - (void) sprintf(lm_optstr, "f:"); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'f': - optf = optarg; - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initrun() -{ - (void) setfdlimit(lm_optB * lm_optT + 10); - - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - int errors = 0; - - if (ts->ts_once++ == 0) { - ts->ts_fds = (int *)malloc(lm_optB * sizeof (int)); - if (ts->ts_fds == NULL) { - errors++; - } - for (i = 0; i < lm_optB; i++) { - ts->ts_fds[i] = -1; - } - } - - return (errors); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - for (i = 0; i < lm_optB; i++) { - ts->ts_fds[i] = open(optf, O_RDONLY); - if (ts->ts_fds[i] < 0) { - res->re_errors++; - } - } - res->re_count = i; - - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - for (i = 0; i < lm_optB; i++) { - (void) close(ts->ts_fds[i]); - } - - return (0); -} diff --git a/tools/tests/libMicro/pipe.c b/tools/tests/libMicro/pipe.c deleted file mode 100644 index f1b3eb413..000000000 --- a/tools/tests/libMicro/pipe.c +++ /dev/null @@ -1,565 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libmicro.h" - -typedef struct { - int ts_once; - pid_t ts_child; - pthread_t ts_thread; - int ts_in; - int ts_out; - int ts_in2; - int ts_out2; - int ts_lsn; - struct sockaddr_in ts_add; -} tsd_t; - -#define FIRSTPORT 12345 - -static char *modes[] = {"st", "mt", "mp", NULL}; -#define MD_SINGLE 0 -#define MD_MULTITHREAD 1 -#define MD_MULTIPROCESS 2 - -static char *xports[] = {"pipe", "fifo", "sock", "tcp", - NULL}; -#define XP_PIPES 0 -#define XP_FIFOS 1 -#define XP_SOCKETPAIR 2 -#define XP_LOCALTCP 3 - -#define DEFM MD_SINGLE -#define DEFS 1024 -#define DEFX XP_PIPES - -static int optm = DEFM; -static size_t opts = DEFS; -static int optx = DEFX; -static void *rbuf = NULL; -static void *wbuf = NULL; - -int readall(int s, void *buf, size_t len); -void *loopback(void *arg); -int prepare_pipes(tsd_t *tsd); -int prepare_fifos(tsd_t *tsd); -int cleanup_fifos(tsd_t *tsd); -int prepare_socketpair(tsd_t *tsd); -int prepare_localtcp(tsd_t *tsd); -int prepare_localtcp_once(tsd_t *tsd); -char *lookupa(int x, char *names[]); -int lookup(char *x, char *names[]); - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "m:s:x:"); - - (void) sprintf(lm_usage, - " [-m mode (st|mt|mp, default %s)]\n" - " [-s buffer-size (default %d)]\n" - " [-x transport (pipe|fifo|sock|tcp, default %s)]\n" - "notes: measures write()/read() across various transports\n", - lookupa(DEFM, modes), DEFS, lookupa(DEFX, xports)); - - (void) sprintf(lm_header, "%2s %4s", "md", "xprt"); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - int x; - - switch (opt) { - case 'm': - x = lookup(optarg, modes); - if (x == -1) - return (-1); - optm = x; - break; - case 's': - opts = sizetoll(optarg); - break; - case 'x': - x = lookup(optarg, xports); - if (x == -1) - return (-1); - optx = x; - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initrun() -{ - if (optx == XP_FIFOS) { - if (geteuid() != 0) { - (void) printf("sorry, must be root to create fifos\n"); - exit(1); - } - } - - (void) setfdlimit(4 * lm_optT + 10); - - rbuf = malloc(opts); - wbuf = malloc(opts); - - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int result; - pid_t pid; - - switch (optx) { - case XP_SOCKETPAIR: - result = prepare_socketpair(ts); - break; - case XP_LOCALTCP: - result = prepare_localtcp(ts); - break; - case XP_FIFOS: - result = prepare_fifos(ts); - break; - case XP_PIPES: - default: - result = prepare_pipes(ts); - break; - } - if (result == -1) { - return (1); - } - - switch (optm) { - case MD_MULTITHREAD: - result = pthread_create(&ts->ts_thread, NULL, loopback, tsd); - if (result == -1) { - return (1); - } - break; - case MD_MULTIPROCESS: - pid = fork(); - switch (pid) { - case 0: - (void) loopback(tsd); - exit(0); - break; - case -1: - return (-1); - default: - ts->ts_child = pid; - break; - } - break; - case MD_SINGLE: - default: - break; - } - - /* Prime the loopback */ - if (write(ts->ts_out, wbuf, opts) != opts) { - return (1); - } - if (readall(ts->ts_in, rbuf, opts) != opts) { - return (1); - } - - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - int n; - - for (i = 0; i < lm_optB; i++) { - if (write(ts->ts_out, wbuf, opts) != opts) { - res->re_errors++; - continue; - } - - n = readall(ts->ts_in, rbuf, opts); - if (n == -1) { - res->re_errors++; - continue; - } - } - res->re_count = i; - - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - - /* Terminate the loopback */ - (void) write(ts->ts_out, wbuf, opts); - (void) readall(ts->ts_in, rbuf, opts); - - switch (optm) { - case MD_MULTITHREAD: - (void) close(ts->ts_in2); - (void) close(ts->ts_out2); - (void) pthread_join(ts->ts_thread, NULL); - break; - case MD_MULTIPROCESS: - (void) close(ts->ts_in2); - (void) close(ts->ts_out2); - (void) waitpid(ts->ts_child, NULL, 0); - break; - case MD_SINGLE: - default: - break; - } - - (void) close(ts->ts_in); - (void) close(ts->ts_out); - - if (optx == XP_FIFOS) { - (void) cleanup_fifos(ts); - } - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - - (void) sprintf(result, "%2s %4s", - lookupa(optm, modes), lookupa(optx, xports)); - - return (result); -} - -int -readall(int s, void *buf, size_t len) -{ - size_t n; - size_t total = 0; - - for (;;) { - n = read(s, (void *)((long)buf + total), len - total); - if (n < 1) { - return (-1); - } - total += n; - if (total >= len) { - return (total); - } - } -} - -void * -loopback(void *arg) -{ - tsd_t *ts = (tsd_t *)arg; - int i, n, m; - - /* Include priming and termination */ - m = lm_optB + 2; - - for (i = 0; i < m; i++) { - n = readall(ts->ts_in2, rbuf, opts); - if (n == -1) { - break; - } - if (write(ts->ts_out2, wbuf, opts) != opts) { - break; - } - } - - return (NULL); -} - -int -prepare_localtcp_once(tsd_t *ts) -{ - int j; - int opt = 1; - struct hostent *host; - - j = FIRSTPORT; - - ts->ts_lsn = socket(AF_INET, SOCK_STREAM, 0); - if (ts->ts_lsn == -1) { - return (-1); - } - - if (setsockopt(ts->ts_lsn, SOL_SOCKET, SO_REUSEADDR, - &opt, sizeof (int)) == -1) { - return (-1); - } - - if ((host = gethostbyname("localhost")) == NULL) { - return (-1); - } - - for (;;) { - (void) memset(&ts->ts_add, 0, - sizeof (struct sockaddr_in)); - ts->ts_add.sin_family = AF_INET; - ts->ts_add.sin_port = htons(j++); - (void) memcpy(&ts->ts_add.sin_addr.s_addr, - host->h_addr_list[0], sizeof (struct in_addr)); - - if (bind(ts->ts_lsn, - (struct sockaddr *)&ts->ts_add, - sizeof (struct sockaddr_in)) == 0) { - break; - } - - if (errno != EADDRINUSE) { - return (-1); - } - } - - if (listen(ts->ts_lsn, 5) == -1) { - return (-1); - } - - return (0); -} - -int -prepare_localtcp(tsd_t *ts) -{ - int result; - struct sockaddr_in addr; - int opt = 1; - socklen_t size; - - if (ts->ts_once++ == 0) { - if (prepare_localtcp_once(ts) == -1) { - return (-1); - } - } - - ts->ts_out = socket(AF_INET, SOCK_STREAM, 0); - if (ts->ts_out == -1) { - return (-1); - } - - if (fcntl(ts->ts_out, F_SETFL, O_NDELAY) == -1) { - return (-1); - } - - result = connect(ts->ts_out, (struct sockaddr *)&ts->ts_add, - sizeof (struct sockaddr_in)); - if ((result == -1) && (errno != EINPROGRESS)) { - return (-1); - } - - if (fcntl(ts->ts_out, F_SETFL, 0) == -1) { - return (-1); - } - - size = sizeof (struct sockaddr); - result = accept(ts->ts_lsn, (struct sockaddr *)&addr, &size); - if (result == -1) { - return (-1); - } - ts->ts_out2 = result; - - if (setsockopt(ts->ts_out, IPPROTO_TCP, TCP_NODELAY, - &opt, sizeof (int)) == -1) { - return (-1); - } - - if (setsockopt(ts->ts_out2, IPPROTO_TCP, TCP_NODELAY, - &opt, sizeof (int)) == -1) { - return (-1); - } - - if (optm == MD_SINGLE) { - ts->ts_in = ts->ts_out2; - } else { - ts->ts_in = ts->ts_out; - ts->ts_in2 = ts->ts_out2; - } - - return (0); -} - -int -prepare_socketpair(tsd_t *ts) -{ - int s[2]; - - if (socketpair(PF_UNIX, SOCK_STREAM, 0, s) == -1) { - return (-1); - } - - if (optm == MD_SINGLE) { - ts->ts_in = s[0]; - ts->ts_out = s[1]; - } else { - ts->ts_in = s[0]; - ts->ts_out = s[0]; - ts->ts_in2 = s[1]; - ts->ts_out2 = s[1]; - } - - return (0); -} - -int -prepare_fifos(tsd_t *ts) -{ - char path[64]; - - (void) sprintf(path, "/private/tmp/pipe_%ld.%dA", - getpid(), pthread_self()); - if (mknod(path, 0600, S_IFIFO) == -1) { - return (-1); - } - - if (optm == MD_SINGLE) { - ts->ts_in = open(path, O_RDONLY); - ts->ts_out = open(path, O_WRONLY); - } else { - ts->ts_in = open(path, O_RDONLY); - ts->ts_out2 = open(path, O_WRONLY); - - (void) sprintf(path, "/private/tmp/pipe_%ld.%dB", - getpid(), pthread_self()); - if (mknod(path, 0600, S_IFIFO) == -1) { - return (-1); - } - - ts->ts_in2 = open(path, O_RDONLY); - ts->ts_out = open(path, O_WRONLY); - } - - return (0); -} - -/*ARGSUSED*/ -int -cleanup_fifos(tsd_t *ts) -{ - char path[64]; - - (void) sprintf(path, "/private/tmp/pipe_%ld.%dA", getpid(), pthread_self()); - (void) unlink(path); - (void) sprintf(path, "/private/tmp/pipe_%ld.%dB", getpid(), pthread_self()); - (void) unlink(path); - - return (0); -} - -int -prepare_pipes(tsd_t *ts) -{ - int p[2]; - - if (optm == MD_SINGLE) { - if (pipe(p) == -1) { - return (-1); - } - ts->ts_in = p[0]; - ts->ts_out = p[1]; - - } else { - if (pipe(p) == -1) { - return (-1); - } - ts->ts_in = p[0]; - ts->ts_out2 = p[1]; - - if (pipe(p) == -1) { - return (-1); - } - ts->ts_in2 = p[0]; - ts->ts_out = p[1]; - } - - return (0); -} - -char * -lookupa(int x, char *names[]) -{ - int i = 0; - - while (names[i] != NULL) { - if (x == i) { - return (names[i]); - } - i++; - } - return (NULL); -} - -int -lookup(char *x, char *names[]) -{ - int i = 0; - - while (names[i] != NULL) { - if (strcmp(names[i], x) == 0) { - return (i); - } - i++; - } - return (-1); -} diff --git a/tools/tests/libMicro/poll.c b/tools/tests/libMicro/poll.c deleted file mode 100644 index 5ef128738..000000000 --- a/tools/tests/libMicro/poll.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#define MAX(x, y) ((x) > (y) ? (x) : (y)) -#define MIN(x, y) ((x) > (y) ? (y) : (x)) - -#include -#include -#include -#include -#include -#include - -#include "libmicro.h" - -#define DEFN 256 - -static int optn = DEFN; -static int optr = 0; -static int optw = 0; -static int optx = 0; -static int *fds; -static int target = 0; - -typedef struct pollfd pfd_t; - -typedef struct { - int ts_once; - pfd_t *ts_pfds; -} tsd_t; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "n:r:w:x"); - - (void) sprintf(lm_usage, - " [-n fds-per-thread (default %d)]\n" - " [-r readable-fds (default 0)]\n" - " [-w writeable-fds (default 0)]\n" - " [-x] (start -r option with highest fd first; " - "default is lowest first)\n" - "notes: measures poll()\n", - DEFN); - - (void) sprintf(lm_header, "%8s %5s", "nfds", "flags"); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'n': - optn = atoi(optarg); - break; - case 'r': - optr = atoi(optarg); - break; - case 'w': - optw = atoi(optarg); - break; - case 'x': - optx = 1; - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initrun() -{ - int i; - int j; - int pair[2]; - - if (optn % 2 != 0) { - (void) printf("ERROR: -n value must be even\n"); - optn = optr = optw = 0; - return (-1); - } - - if (optn < 0 || optr < 0 || optw < 0) { - (void) printf("ERROR: -n, -r and -w values must be > 0\n"); - optn = optr = optw = 0; - return (-1); - } - - if (optr > optn || optw > optn) { - (void) printf("ERROR: -r and -w values must be <= maxfd\n"); - optn = optr = optw = 0; - return (-1); - } - - fds = (int *)malloc(optn * sizeof (int)); - if (fds == NULL) { - (void) printf("ERROR: malloc() failed\n"); - optn = optr = optw = 0; - return (-1); - } - - (void) setfdlimit(optn + 10); - - - for (i = 0; i < optn; i += 2) { - if (socketpair(PF_UNIX, SOCK_STREAM, 0, pair) == -1) { - (void) printf("ERROR: socketpair() failed\n"); - return (-1); - } - - fds[i] = MIN(pair[0], pair[1]); - fds[i+1] = MAX(pair[0], pair[1]); - } - - if (optx) { - target = MIN(optr + optw, optn); - for (i = 0, j = optn - 1; i < optr; i++, j--) { - (void) write(fds[j+1 - (2*(j%2))], "", 1); - } - } else { - target = MAX(optr, optw); - for (i = 0; i < optr; i++) { - (void) write(fds[i+1 - (2*(i%2))], "", 1); - } - } - - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - int errors = 0; - - if (ts->ts_once++ == 0) { - ts->ts_pfds = (pfd_t *)malloc(optn * sizeof (pfd_t)); - if (ts->ts_pfds == NULL) { - errors++; - } - - for (i = 0; i < optn; i++) { - ts->ts_pfds[i].fd = fds[i]; - ts->ts_pfds[i].events = POLLIN; - } - - for (i = 0; i < optw; i++) { - ts->ts_pfds[i].events |= POLLOUT; - } - } - - return (errors); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - for (i = 0; i < lm_optB; i++) { - if (poll(ts->ts_pfds, optn, 0) != target) { - res->re_errors++; - } - } - res->re_count = i; - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - char flags[4]; - - flags[0] = optr ? 'r' : '-'; - flags[1] = optw ? 'w' : '-'; - flags[2] = optx ? 'x' : '-'; - flags[3] = 0; - - (void) sprintf(result, "%8d %5s", optn, flags); - - return (result); -} diff --git a/tools/tests/libMicro/pread.c b/tools/tests/libMicro/pread.c deleted file mode 100644 index 51e15d962..000000000 --- a/tools/tests/libMicro/pread.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifdef linux -#define _XOPEN_SOURCE 500 -#endif - -#include -#include -#include -#include - -#include "libmicro.h" - -typedef struct { - char *ts_buf; -} tsd_t; - -#define DEFF "/dev/zero" -#define DEFS 1024 - -static char *optf = DEFF; -static long long opts = DEFS; -static int optw = 0; -static int fd = -1; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "wf:s:"); - - (void) sprintf(lm_usage, - " [-f file-to-read (default %s)]\n" - " [-s buffer-size (default %d)]\n" - " [-w (write a byte to each page after read)]\n" - "notes: measures pread()\n", - DEFF, DEFS); - - (void) sprintf(lm_header, "%8s", "size"); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'w': - optw = getpagesize(); - break; - case 'f': - optf = optarg; - break; - case 's': - opts = sizetoll(optarg); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initrun() -{ - fd = open(optf, O_RDONLY); - - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int errors = 0; - - if (ts->ts_buf == NULL) { - ts->ts_buf = malloc(opts); - } - - return (errors); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - int j; - - for (i = 0; i < lm_optB; i++) { - if (pread(fd, ts->ts_buf, opts, 0) != opts) { - res->re_errors++; - } - if (optw) { - for (j = 0; j < opts; j += optw) - ts->ts_buf[j] = 0; - } - } - res->re_count = i; - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - - (void) sprintf(result, "%8lld", opts); - - return (result); -} diff --git a/tools/tests/libMicro/pthread_create.c b/tools/tests/libMicro/pthread_create.c deleted file mode 100644 index 340d35c05..000000000 --- a/tools/tests/libMicro/pthread_create.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include -#include -#include -#include - -#include "libmicro.h" - -typedef struct { - pthread_t *ts_threads; - pthread_attr_t *ts_attr; - pthread_mutex_t ts_lock; -} tsd_t; - -static int opts = 0; - -int -benchmark_init() -{ - lm_defN = "pthread"; - - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_usage, - " [-s stacksize] (specify stacksize)\n" - "notes: measures pthread_create\n"); - - (void) sprintf(lm_optstr, "s:"); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 's': - opts = sizetoll(optarg); - break; - default: - return (-1); - } - - return (0); -} - -int -benchmark_initworker(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int errors = 0; - - ts->ts_threads = calloc(lm_optB, sizeof (pthread_t)); - (void) pthread_mutex_init(&ts->ts_lock, NULL); - - if (opts) { - ts->ts_attr = malloc(sizeof (pthread_attr_t)); - (void) pthread_attr_init(ts->ts_attr); - if ((errors = pthread_attr_setstacksize(ts->ts_attr, opts)) - != 0) { - errno = errors; - perror("pthread_attr_setstacksize"); - } - } else - ts->ts_attr = NULL; - - return (errors?1:0); -} - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - - (void) pthread_mutex_lock(&ts->ts_lock); - - return (0); -} - - -void * -func(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - - (void) pthread_mutex_lock(&ts->ts_lock); - (void) pthread_mutex_unlock(&ts->ts_lock); - - return (tsd); -} - -int -benchmark(void *tsd, result_t *res) -{ - int i; - tsd_t *ts = (tsd_t *)tsd; - int error; - - for (i = 0; i < lm_optB; i++) { - if ((error = pthread_create(ts->ts_threads + i, - ts->ts_attr, func, tsd)) != 0) { - errno = error; - perror("pthread_create"); - ts->ts_threads[i] = 0; - res->re_errors++; - return (0); - } - } - res->re_count = lm_optB; - - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - int errors = 0; - - (void) pthread_mutex_unlock(&ts->ts_lock); - - for (i = 0; i < lm_optB; i++) - if (ts->ts_threads[i] == 0 || - pthread_join(ts->ts_threads[i], NULL) < 0) { - errors++; - } - return (errors); -} diff --git a/tools/tests/libMicro/pwrite.c b/tools/tests/libMicro/pwrite.c deleted file mode 100644 index ab1374c6b..000000000 --- a/tools/tests/libMicro/pwrite.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifdef linux -#define _XOPEN_SOURCE 500 -#endif - -#include -#include -#include -#include - -#include "libmicro.h" - -typedef struct { - char *ts_buf; -} tsd_t; - -#define DEFF "/dev/null" -#define DEFS 1024 - -static int optc = 0; -static char *optf = DEFF; -static long long opts = DEFS; -static int fd = -1; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "cf:s:"); - - (void) sprintf(lm_usage, - " [-f file-to-write (default %s)]\n" - " [-s buffer-size (default %d)]\n" - " [-c ] (make sure buffer is in cache)\n" - "notes: measures pwrite()\n", - DEFF, DEFS); - - (void) sprintf(lm_header, "%8s", "size"); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'c': - optc++; - break; - case 'f': - optf = optarg; - break; - case 's': - opts = sizetoll(optarg); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initrun() -{ - fd = open(optf, O_WRONLY); - if (fd == -1) { - return (-1); - } - - return (0); -} - -int -benchmark_finirun() -{ - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - if (ts->ts_buf == NULL) { - ts->ts_buf = malloc(opts); - - /* - * bring buf into cache if specified. - */ - - if (optc) - for (i = 0; i < opts; i++) - ts->ts_buf[i] = 0; - } - - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - for (i = 0; i < lm_optB; i++) { - if (pwrite(fd, ts->ts_buf, opts, 0) != opts) { - res->re_errors++; - } - } - res->re_count = i; - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - - (void) sprintf(result, "%8lld", opts); - - return (result); -} diff --git a/tools/tests/libMicro/read.c b/tools/tests/libMicro/read.c deleted file mode 100644 index 32faf05ac..000000000 --- a/tools/tests/libMicro/read.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - - -#ifdef linux -#define _XOPEN_SOURCE 500 -#endif - -#include -#include -#include -#include - -#include "libmicro.h" - -typedef struct { - char *ts_buf; - int ts_fd; -} tsd_t; - -#define DEFF "/dev/zero" -#define DEFS 1024 - -static char *optf = DEFF; -static long long opts = DEFS; -int optw = 0; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "f:s:w"); - - (void) sprintf(lm_usage, - " [-f file-to-read (default %s)]\n" - " [-s buffer-size (default %d)]\n" - " [-w (store a byte to each page after read)]\n" - "notes: measures read()\n", - DEFF, DEFS); - - (void) sprintf(lm_header, "%8s", "size"); - - lm_defB = 1; - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'w': - optw = getpagesize(); - break; - case 'f': - optf = optarg; - break; - case 's': - opts = sizetoll(optarg); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initrun() -{ - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - - if (ts->ts_buf == NULL) { - ts->ts_buf = malloc(opts); - ts->ts_fd = open(optf, O_RDONLY); - } - - (void) lseek(ts->ts_fd, 0, SEEK_SET); - - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - int j; - for (i = 0; i < lm_optB; i++) { - if (read(ts->ts_fd, ts->ts_buf, opts) != opts) { - res->re_errors++; - } - if (optw) - for (j = 0; j < opts; j += optw) - ts->ts_buf[j] = 0; - } - res->re_count = i; - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - - (void) sprintf(result, "%8lld", opts); - - return (result); -} diff --git a/tools/tests/libMicro/realpath.c b/tools/tests/libMicro/realpath.c deleted file mode 100644 index 540ebf77a..000000000 --- a/tools/tests/libMicro/realpath.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - - -#include -#include -#include - -#include "libmicro.h" - -#define DEFF "/" -#define MAXPATHLEN 1024 - -static char *optf = DEFF; - -int -benchmark_init() -{ - (void) sprintf(lm_optstr, "f:"); - - lm_tsdsize = 0; - - (void) sprintf(lm_usage, - " [-f directory (default = %s)]\n" - "notes: measures realpath()\n", - DEFF); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'f': - optf = optarg; - break; - default: - return (-1); - } - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - char path[MAXPATHLEN]; - - for (i = 0; i < lm_optB; i++) { - if (realpath(optf, path) == NULL) - res->re_errors++; - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/recurse.c b/tools/tests/libMicro/recurse.c deleted file mode 100644 index 3237b465b..000000000 --- a/tools/tests/libMicro/recurse.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - - -#include -#include -#include -#include - -#include "libmicro.h" - -#define DEFD 100 - -static int optd = DEFD; - -int recurse2(int x, int y, char *s); - -/*ARGSUSED*/ -int -recurse1(int x, int y, char *s) -{ - char str[32]; - - if (x < y) { - return (recurse2(x + 1, y, str)); - } - - return (x); -} - -int -benchmark_init() -{ - lm_tsdsize = 0; - - (void) sprintf(lm_optstr, "d:"); - - (void) sprintf(lm_usage, - " [-d depth-limit (default = %d)]\n" - "notes: measures recursion performance\n", - DEFD); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'd': - optd = atoi(optarg); - break; - default: - return (-1); - } - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - - for (i = 0; i < lm_optB; i++) { - (void) recurse1(0, optd, NULL); - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/recurse2.c b/tools/tests/libMicro/recurse2.c deleted file mode 100644 index 9f228900d..000000000 --- a/tools/tests/libMicro/recurse2.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include - -int recurse1(int x, int y, char *s); - -/*ARGSUSED*/ -int -recurse2(int x, int y, char *s) -{ - char str[32]; - - if (x < y) { - return (recurse1(x + 1, y, str)); - } - - return (x); -} diff --git a/tools/tests/libMicro/select.c b/tools/tests/libMicro/select.c deleted file mode 100644 index 5edc37edb..000000000 --- a/tools/tests/libMicro/select.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#define MAX(x, y) ((x) > (y) ? (x) : (y)) -#define MIN(x, y) ((x) > (y) ? (y) : (x)) - -#include -#include -#include -#include -#include -#include - -#include "libmicro.h" - -#define DEFN 256 - -static int optn = DEFN; -static int optr = 0; -static int optw = 0; -static int optx = 0; -static int *fds; -static fd_set iset; -static fd_set oset; -static int maxfd = 0; -static int target = 0; - -int -benchmark_init() -{ - (void) sprintf(lm_optstr, "n:r:w:x"); - - lm_tsdsize = 0; - - (void) sprintf(lm_usage, - " [-n fds-per-thread (default %d)]\n" - " [-r readable-fds (default 0)]\n" - " [-w writeable-fds (default 0)]\n" - " [-x] (start -r option with highest fd first; " - "default is lowest first)\n" - "notes: measures select()\n", - DEFN); - - (void) sprintf(lm_header, "%8s %5s", "maxfd", "flags"); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'n': - optn = atoi(optarg); - break; - case 'r': - optr = atoi(optarg); - break; - case 'w': - optw = atoi(optarg); - break; - case 'x': - optx = 1; - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initrun() -{ - int i; - int j; - int pair[2]; - - if (optn % 2 != 0) { - (void) printf("ERROR: -n value must be even\n"); - optn = optr = optw = 0; - return (-1); - } - - if (optn < 0 || optr < 0 || optw < 0) { - (void) printf("ERROR: -n, -r and -w values must be > 0\n"); - optn = optr = optw = 0; - return (-1); - } - - if (optr > optn || optw > optn) { - (void) printf("ERROR: -r and -w values must be <= maxfd\n"); - optn = optr = optw = 0; - return (-1); - } - - fds = (int *)malloc(optn * sizeof (int)); - if (fds == NULL) { - (void) printf("ERROR: malloc() failed\n"); - optn = optr = optw = 0; - return (-1); - } - - (void) setfdlimit(optn + 10); - - target = optr + optw; - - FD_ZERO(&iset); - FD_ZERO(&oset); - - for (i = 0; i < optn; i += 2) { - if (socketpair(PF_UNIX, SOCK_STREAM, 0, pair) == -1) { - (void) printf("ERROR: socketpair() failed\n"); - return (-1); - } - - fds[i] = MIN(pair[0], pair[1]); - fds[i+1] = MAX(pair[0], pair[1]); - maxfd = fds[i+1] + 1; - - if (maxfd > FD_SETSIZE) { - (void) printf("WARNING: FD_SETSIZE is too small!\n"); - return (-1); - } - - FD_SET(fds[i], &iset); - FD_SET(fds[i+1], &iset); - } - - for (i = 0; i < optw; i++) { - FD_SET(fds[i], &oset); - } - if (optx) { - for (i = 0, j = optn - 1; i < optr; i++, j--) { - (void) write(fds[j+1 - (2*(j%2))], "", 1); - } - } else { - for (i = 0; i < optr; i++) { - (void) write(fds[i+1 - (2*(i%2))], "", 1); - } - } - - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - fd_set set1; - fd_set set2; - fd_set *my_iset = &set1; - fd_set *my_oset = NULL; - struct timeval tv = {0, 0}; - - if (optw) { - my_oset = &set2; - } - - for (i = 0; i < lm_optB; i++) { - (void) memcpy(&set1, &iset, sizeof (fd_set)); - (void) memcpy(&set2, &oset, sizeof (fd_set)); - - if (select(maxfd, my_iset, my_oset, NULL, &tv) != target) { - res->re_errors++; - } - } - res->re_count = i; - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - char flags[4]; - - flags[0] = optr ? 'r' : '-'; - flags[1] = optw ? 'w' : '-'; - flags[2] = optx ? 'x' : '-'; - flags[3] = 0; - - (void) sprintf(result, "%8d %5s", optn, flags); - - return (result); -} diff --git a/tools/tests/libMicro/semop.c b/tools/tests/libMicro/semop.c deleted file mode 100644 index 9953a799d..000000000 --- a/tools/tests/libMicro/semop.c +++ /dev/null @@ -1,103 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include -#include -#include -#include - -#include "libmicro.h" - - -typedef struct { - int ts_semid; -} tsd_t; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_usage, "notes: measures semop()\n"); - - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - - tsd_t *ts = (tsd_t *)tsd; - - if ((ts->ts_semid = semget(IPC_PRIVATE, 2, 0600)) == -1) { - return (-1); - } - - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - - (void) semctl(ts->ts_semid, 0, IPC_RMID); - - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - int i; - tsd_t *ts = (tsd_t *)tsd; - struct sembuf s[1]; - - for (i = 0; i < lm_optB; i++) { - s[0].sem_num = 0; - s[0].sem_op = 1; - s[0].sem_flg = 0; - if (semop(ts->ts_semid, s, 1) == -1) { - res->re_errors++; - } - s[0].sem_num = 0; - s[0].sem_op = -1; - s[0].sem_flg = 0; - if (semop(ts->ts_semid, s, 1) == -1) { - res->re_errors++; - } - } - - res->re_count += lm_optB; - - return (0); -} diff --git a/tools/tests/libMicro/setcontext.c b/tools/tests/libMicro/setcontext.c deleted file mode 100644 index dad284982..000000000 --- a/tools/tests/libMicro/setcontext.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include -#include - -#include "libmicro.h" - -int -benchmark_init() -{ - - (void) sprintf(lm_usage, "notes: measures setcontext()\n"); - - lm_tsdsize = 0; - - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - volatile int i; - - ucontext_t uc; - - i = 0; - - (void) getcontext(&uc); - - if (i++ < lm_optB) - (void) setcontext(&uc); - - res->re_count += lm_optB; - - return (0); -} diff --git a/tools/tests/libMicro/setsockopt.c b/tools/tests/libMicro/setsockopt.c deleted file mode 100644 index c48672efd..000000000 --- a/tools/tests/libMicro/setsockopt.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libmicro.h" - -typedef struct { - int ts_fd; -} tsd_t; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_usage, "setsockopt(TCP_NODELAY)\n"); - - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - - tsd_t *ts = (tsd_t *)tsd; - - if ((ts->ts_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) - return (1); - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - - (void) close(ts->ts_fd); - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - int i; - tsd_t *ts = (tsd_t *)tsd; - int opt; - - res->re_errors = 0; - - for (i = 0; i < lm_optB; i++) { - opt = 1 & i; - if (setsockopt(ts->ts_fd, IPPROTO_TCP, TCP_NODELAY, - &opt, sizeof (int)) == -1) { - res->re_errors ++; - } - } - res->re_count += lm_optB; - - return (0); -} diff --git a/tools/tests/libMicro/sigaction.c b/tools/tests/libMicro/sigaction.c deleted file mode 100644 index b0053b3e6..000000000 --- a/tools/tests/libMicro/sigaction.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include -#include -#include - -#include "libmicro.h" - -#ifdef __sun -static void -nop() -{ -} -#else -static void -nop(int sig) -{ -} -#endif - - -typedef struct { - struct sigaction ts_act; -} tsd_t; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_usage, "notes: measures sigaction()\n"); - - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - - tsd_t *ts = (tsd_t *)tsd; - ts->ts_act.sa_handler = nop; - ts->ts_act.sa_flags = 0; - (void) sigemptyset(&ts->ts_act.sa_mask); - - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - int i; - tsd_t *ts = (tsd_t *)tsd; - struct sigaction oact; - - res->re_errors = 0; - - for (i = 0; i < lm_optB; i++) { - if (sigaction(SIGUSR1, &ts->ts_act, &oact)) - res->re_errors++; - } - - res->re_count += lm_optB; - - return (0); -} diff --git a/tools/tests/libMicro/siglongjmp.c b/tools/tests/libMicro/siglongjmp.c deleted file mode 100644 index 385530eab..000000000 --- a/tools/tests/libMicro/siglongjmp.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include -#include - -#include "libmicro.h" - -typedef struct { - jmp_buf ts_env; -} tsd_t; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - lm_tsdsize = 0; - - (void) sprintf(lm_usage, "notes: measures siglongjmp()\n"); - - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - -#if 1 /* Apple fix to longjmp/siglongjmp tests, see radar 7440118 */ - volatile int i = 0; -#else - int i = 0; -#endif /* end of Apple fix */ - - (void) sigsetjmp(ts->ts_env, 1); - - if (i++ < lm_optB) - siglongjmp(ts->ts_env, 0); - - res->re_count = lm_optB; - - return (0); -} diff --git a/tools/tests/libMicro/signal.c b/tools/tests/libMicro/signal.c deleted file mode 100644 index 623aa08e9..000000000 --- a/tools/tests/libMicro/signal.c +++ /dev/null @@ -1,100 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include -#include -#include - -#include "libmicro.h" - - -#ifdef __sun -static void -nop() -{ -} -#else -static void -nop(int sig) -{ -} -#endif - -int -benchmark_init() -{ - lm_tsdsize = 0; - - (void) sprintf(lm_usage, "notes: measures signal()\n"); - - return (0); -} - -int -benchmark_initrun() -{ - struct sigaction act; - - act.sa_handler = nop; - act.sa_flags = 0; - - (void) sigemptyset(&act.sa_mask); - (void) sigaction(SIGUSR1, &act, NULL); - - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - int pid; - - pid = getpid(); - - for (i = 0; i < lm_optB; i += 10) { - (void) kill(pid, SIGUSR1); - (void) kill(pid, SIGUSR1); - (void) kill(pid, SIGUSR1); - (void) kill(pid, SIGUSR1); - (void) kill(pid, SIGUSR1); - (void) kill(pid, SIGUSR1); - (void) kill(pid, SIGUSR1); - (void) kill(pid, SIGUSR1); - (void) kill(pid, SIGUSR1); - (void) kill(pid, SIGUSR1); - } - res->re_count += i; - - return (0); -} diff --git a/tools/tests/libMicro/sigprocmask.c b/tools/tests/libMicro/sigprocmask.c deleted file mode 100644 index b94675e5f..000000000 --- a/tools/tests/libMicro/sigprocmask.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include -#include - -#include "libmicro.h" - -int -benchmark_init() -{ - lm_tsdsize = 0; - - (void) sprintf(lm_usage, "notes: measures sigprocmask()\n"); - - return (0); -} - -int -benchmark_initrun() -{ - sigset_t iset; - - (void) sigemptyset(&iset); - (void) sigprocmask(SIG_SETMASK, &iset, NULL); - - return (0); -} -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - sigset_t set0, set1; - - (void) sigemptyset(&set0); - (void) sigaddset(&set0, SIGTERM); - - for (i = 0; i < lm_optB; i += 10) { - (void) sigprocmask(SIG_SETMASK, &set0, &set1); - (void) sigprocmask(SIG_SETMASK, &set1, &set0); - (void) sigprocmask(SIG_SETMASK, &set0, &set1); - (void) sigprocmask(SIG_SETMASK, &set1, &set0); - (void) sigprocmask(SIG_SETMASK, &set0, &set1); - (void) sigprocmask(SIG_SETMASK, &set1, &set0); - (void) sigprocmask(SIG_SETMASK, &set0, &set1); - (void) sigprocmask(SIG_SETMASK, &set1, &set0); - (void) sigprocmask(SIG_SETMASK, &set0, &set1); - (void) sigprocmask(SIG_SETMASK, &set1, &set0); - } - - res->re_count += i; - - return (0); -} diff --git a/tools/tests/libMicro/socket.c b/tools/tests/libMicro/socket.c deleted file mode 100644 index 496966dcd..000000000 --- a/tools/tests/libMicro/socket.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include -#include -#include - -#include "libmicro.h" - -typedef struct { - int ts_once; - int *ts_fds; -} tsd_t; - -#define DEFF "PF_UNIX" - -static char *optf = DEFF; -static int family; - -int -lookup_family(char *name) -{ - if (strcmp("PF_UNIX", name) == 0) { - return (PF_UNIX); - } else if (strcmp("PF_INET", name) == 0) { - return (PF_INET); - } else if (strcmp("PF_INET6", name) == 0) { - return (PF_INET6); - } - - return (-1); -} - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - lm_defB = 256; - - (void) sprintf(lm_optstr, "f:n"); - - (void) sprintf(lm_usage, - " [-f socket-family (default %s)]\n" - "notes: measures socket\n", - DEFF); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'f': - optf = optarg; - break; - default: - return (-1); - } - - return (0); -} - - -int -benchmark_initrun() -{ - (void) setfdlimit(lm_optB * lm_optT + 10); - family = lookup_family(optf); - - return (0); -} - -int -benchmark_finirun() -{ - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - int i; - tsd_t *ts = (tsd_t *)tsd; - - if (ts->ts_once++ == 0) { - ts->ts_fds = (int *)malloc(lm_optB * sizeof (int)); - if (ts->ts_fds == NULL) { - return (1); - } - for (i = 0; i < lm_optB; i++) { - ts->ts_fds[i] = -1; - } - } - - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - int i; - tsd_t *ts = (tsd_t *)tsd; - - for (i = 0; i < lm_optB; i++) { - ts->ts_fds[i] = socket(family, SOCK_STREAM, 0); - if (ts->ts_fds[i] == -1) { - res->re_errors++; - } - } - res->re_count += lm_optB; - - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - int i; - tsd_t *ts = (tsd_t *)tsd; - - for (i = 0; i < lm_optB; i++) { - (void) close(ts->ts_fds[i]); - } - - return (0); -} diff --git a/tools/tests/libMicro/socketpair.c b/tools/tests/libMicro/socketpair.c deleted file mode 100644 index 59e7edb7d..000000000 --- a/tools/tests/libMicro/socketpair.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include -#include -#include - -#include "libmicro.h" - -typedef struct { - int ts_once; - int *ts_fds; -} tsd_t; - -#define DEFN 256 - - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - lm_defB = 256; - - (void) sprintf(lm_usage, - "notes: measures socketpair\n"); - - return (0); -} - - -int -benchmark_initrun() -{ - (void) setfdlimit(lm_optB * lm_optT + 10); - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - int i; - tsd_t *ts = (tsd_t *)tsd; - - if (ts->ts_once++ == 0) { - ts->ts_fds = (int *)malloc(lm_optB * sizeof (int)); - if (ts->ts_fds == NULL) { - return (1); - } - for (i = 0; i < lm_optB; i++) { - ts->ts_fds[i] = -1; - } - } - - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - int i; - tsd_t *ts = (tsd_t *)tsd; - - res->re_count = 0; - res->re_errors = 0; - - for (i = 0; i < lm_optB; i += 2) { - if (socketpair(PF_UNIX, SOCK_STREAM, 0, &ts->ts_fds[i]) - == -1) { - res->re_errors++; - } - } - res->re_count = i / 2; - - return (0); -} - -int -benchmark_finibatch(void *tsd) -{ - int i; - tsd_t *ts = (tsd_t *)tsd; - - for (i = 0; i < lm_optB; i++) { - (void) close(ts->ts_fds[i]); - } - - return (0); -} diff --git a/tools/tests/libMicro/stat.c b/tools/tests/libMicro/stat.c deleted file mode 100644 index cffcceed4..000000000 --- a/tools/tests/libMicro/stat.c +++ /dev/null @@ -1,88 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include -#include -#include - -#include "libmicro.h" - -#define DEFF "/dev/null" -static char *optf = DEFF; - -int -benchmark_init() -{ - - (void) sprintf(lm_optstr, "f:"); - - lm_tsdsize = 0; - - (void) sprintf(lm_usage, - " [-f file-to-stat (default %s)]\n" - "notes: measures stat()\n", - DEFF); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'f': - optf = optarg; - break; - default: - return (-1); - } - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - struct stat sbuf; - - res->re_errors = 0; - - for (i = 0; i < lm_optB; i++) { - if (stat(optf, &sbuf) == -1) - res->re_errors++; - } - - res->re_count += lm_optB; - - return (0); -} diff --git a/tools/tests/libMicro/strcasecmp.c b/tools/tests/libMicro/strcasecmp.c deleted file mode 100644 index c57137b76..000000000 --- a/tools/tests/libMicro/strcasecmp.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include -#include - -#include "libmicro.h" - - -static int unaligned = 0; -static int opts = 100; - -typedef struct { - int ts_once; - char *ts_a; - char *ts_b; - int ts_fakegcc; -} tsd_t; - -int -benchmark_init() -{ - - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "s:n"); - - (void) sprintf(lm_usage, - " [-s string size (default %d)]\n" - " [-n causes unaligned cmp]\n" - "notes: measures strcasecmp()\n", - opts); - - (void) sprintf(lm_header, "%8s", "size"); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'n': - unaligned = 1; - break; - case 's': - opts = sizetoll(optarg); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - - static char *demo = - "The quick brown fox jumps over the lazy dog."; - - if (ts->ts_once++ == 0) { - int l = strlen(demo); - int i; - - ts->ts_a = malloc(opts + 1); - ts->ts_b = malloc(opts + 1 + unaligned); - ts->ts_b += unaligned; - - for (i = 0; i < opts; i++) { - ts->ts_a[i] = ts->ts_b[i] = demo[i%l]; - } - ts->ts_a[opts] = 0; - ts->ts_b[opts] = 0; - } - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - int i; - tsd_t *ts = (tsd_t *)tsd; - - char *src = ts->ts_a; - char *src2 = ts->ts_b; - int *sum = &ts->ts_fakegcc; - - res->re_errors = 0; - - for (i = 0; i < lm_optB; i += 10) { - *sum += strcasecmp(src, src2); - *sum += strcasecmp(src, src2); - *sum += strcasecmp(src, src2); - *sum += strcasecmp(src, src2); - *sum += strcasecmp(src, src2); - *sum += strcasecmp(src, src2); - *sum += strcasecmp(src, src2); - *sum += strcasecmp(src, src2); - *sum += strcasecmp(src, src2); - *sum += strcasecmp(src, src2); - } - - res->re_count = i; - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - - if (unaligned == 0) - (void) sprintf(result, "%8d", opts); - else - (void) sprintf(result, "%8d ", opts); - - return (result); -} diff --git a/tools/tests/libMicro/strchr.c b/tools/tests/libMicro/strchr.c deleted file mode 100644 index 54c74778e..000000000 --- a/tools/tests/libMicro/strchr.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include -#include - -#include "libmicro.h" - -static int unaligned = 0; -static int opts = 100; - -typedef struct { - int ts_once; - char *ts_string; - char *ts_fakegcc; -} tsd_t; - -int -benchmark_init() -{ - - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "s:n"); - - (void) sprintf(lm_usage, - " [-s string size (default %d)]\n" - " [-n causes unaligned strchr]\n" - "notes: measures strchr()\n", - opts); - - (void) sprintf(lm_header, "%8s", "size"); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'n': - unaligned = 1; - break; - case 's': - opts = sizetoll(optarg); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - - static char *demo = - "The quick brown fox jumps over the lazy dog."; - - if (ts->ts_once++ == 0) { - int l = strlen(demo); - int i; - - ts->ts_string = malloc(opts + 1 + unaligned); - ts->ts_string += unaligned; - - - for (i = 0; i < opts; i++) { - ts->ts_string[i] = demo[i%l]; - } - - ts->ts_string[opts] = 0; - - } - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - int i; - tsd_t *ts = (tsd_t *)tsd; - char *src = ts->ts_string; - - for (i = 0; i < lm_optB; i += 10) { - ts->ts_fakegcc = strchr(src, 'X'); - ts->ts_fakegcc = strchr(src, 'X'); - ts->ts_fakegcc = strchr(src, 'X'); - ts->ts_fakegcc = strchr(src, 'X'); - ts->ts_fakegcc = strchr(src, 'X'); - ts->ts_fakegcc = strchr(src, 'X'); - ts->ts_fakegcc = strchr(src, 'X'); - ts->ts_fakegcc = strchr(src, 'X'); - ts->ts_fakegcc = strchr(src, 'X'); - ts->ts_fakegcc = strchr(src, 'X'); - } - - res->re_count = i; - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - - if (unaligned == 0) - (void) sprintf(result, "%8d", opts); - else - (void) sprintf(result, "%8d ", opts); - - return (result); -} diff --git a/tools/tests/libMicro/strcmp.c b/tools/tests/libMicro/strcmp.c deleted file mode 100644 index c3c0da018..000000000 --- a/tools/tests/libMicro/strcmp.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include -#include - -#include "libmicro.h" - -static int unaligned = 0; -static int opts = 100; - -typedef struct { - int ts_once; - char *ts_a; - char *ts_b; - int ts_fakegcc; -} tsd_t; - -int -benchmark_init() -{ - - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "s:n"); - - (void) sprintf(lm_usage, - " [-s string size (default %d)]\n" - " [-n causes unaligned cmp]\n" - "notes: measures strcmp()\n", - opts); - - (void) sprintf(lm_header, "%8s", "size"); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'n': - unaligned = 1; - break; - case 's': - opts = sizetoll(optarg); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - static char *demo = - "The quick brown fox jumps over the lazy dog."; - - if (ts->ts_once++ == 0) { - int l = strlen(demo); - int i; - - ts->ts_a = malloc(opts + 1); - ts->ts_b = malloc(opts + 1 + unaligned); - ts->ts_b += unaligned; - - for (i = 0; i < opts; i++) { - ts->ts_a[i] = ts->ts_b[i] = demo[i%l]; - } - ts->ts_a[opts] = 0; - ts->ts_b[opts] = 0; - } - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - int i; - tsd_t *ts = (tsd_t *)tsd; - int *sum = &ts->ts_fakegcc; - char *src = ts->ts_a; - char *src2 = ts->ts_b; - - res->re_errors = 0; - - for (i = 0; i < lm_optB; i += 10) { - *sum += strcmp(src, src2); - *sum += strcmp(src, src2); - *sum += strcmp(src, src2); - *sum += strcmp(src, src2); - *sum += strcmp(src, src2); - *sum += strcmp(src, src2); - *sum += strcmp(src, src2); - *sum += strcmp(src, src2); - *sum += strcmp(src, src2); - *sum += strcmp(src, src2); - } - - res->re_count = i; - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - - if (unaligned == 0) - (void) sprintf(result, "%8d", opts); - else - (void) sprintf(result, "%8d ", opts); - - return (result); -} diff --git a/tools/tests/libMicro/strcpy.c b/tools/tests/libMicro/strcpy.c deleted file mode 100644 index 3a32353ed..000000000 --- a/tools/tests/libMicro/strcpy.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include -#include - -#include "libmicro.h" - -static int unaligned = 0; -static int opts = 100; - -typedef struct { - int ts_once; - char *ts_a; - char *ts_b; -} tsd_t; - -int -benchmark_init() -{ - - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "s:n"); - - (void) sprintf(lm_usage, - " [-s string size (default %d)]\n" - " [-n causes unaligned cmp]\n" - "notes: measures strcpy()\n", - opts); - - (void) sprintf(lm_header, "%8s", "size"); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'n': - unaligned = 1; - break; - case 's': - opts = sizetoll(optarg); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - static char *demo = - "The quick brown fox jumps over the lazy dog."; - - if (ts->ts_once++ == 0) { - int l = strlen(demo); - int i; - - ts->ts_a = malloc(opts + 1); - ts->ts_b = malloc(opts + 1 + unaligned); - ts->ts_b += unaligned; - - for (i = 0; i < opts; i++) { - ts->ts_b[i] = demo[i%l]; - } - ts->ts_b[opts] = 0; - } - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - int i; - tsd_t *ts = (tsd_t *)tsd; - - char *src = ts->ts_a; - char *src2 = ts->ts_b; - - res->re_errors = 0; - - for (i = 0; i < lm_optB; i += 10) { - (void) strcpy(src, src2); - (void) strcpy(src, src2); - (void) strcpy(src, src2); - (void) strcpy(src, src2); - (void) strcpy(src, src2); - (void) strcpy(src, src2); - (void) strcpy(src, src2); - (void) strcpy(src, src2); - (void) strcpy(src, src2); - (void) strcpy(src, src2); - } - - res->re_count = i; - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - - if (unaligned == 0) - (void) sprintf(result, "%8d", opts); - else - (void) sprintf(result, "%8d ", opts); - - return (result); -} diff --git a/tools/tests/libMicro/strftime.c b/tools/tests/libMicro/strftime.c deleted file mode 100644 index b05646684..000000000 --- a/tools/tests/libMicro/strftime.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include -#include - -#include "libmicro.h" - -#define DEFF "%c" -#define MAXSIZE 80 - -static char *optf = DEFF; - -typedef struct { - int ts_once; - struct tm ts_tm1; - struct tm ts_tm2; -} tsd_t; - -int -benchmark_init() -{ - - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "f:"); - - (void) sprintf(lm_usage, - " [-f format (default = \"%s\")]\n" - "notes: measures strftime()\n", - DEFF); - - (void) sprintf(lm_header, "%8s", "format"); - - return (0); -} -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - - case 'f': - optf = optarg; - break; - default: - return (-1); - } - return (0); -} - - -char * -benchmark_result() -{ - static char result[256]; - - (void) sprintf(result, "%8s", optf); - - return (result); -} - - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - - static time_t clock1 = 0L; - static time_t clock2 = 1L; - - (void) localtime_r(&clock1, &ts->ts_tm1); - (void) localtime_r(&clock2, &ts->ts_tm2); - - return (0); -} - - -int -benchmark(void *tsd, result_t *res) -{ - int i; - tsd_t *ts = (tsd_t *)tsd; - char s[MAXSIZE]; - - for (i = 0; i < lm_optB; i += 10) { - (void) strftime(s, MAXSIZE, optf, &ts->ts_tm1); - (void) strftime(s, MAXSIZE, optf, &ts->ts_tm2); - (void) strftime(s, MAXSIZE, optf, &ts->ts_tm1); - (void) strftime(s, MAXSIZE, optf, &ts->ts_tm2); - (void) strftime(s, MAXSIZE, optf, &ts->ts_tm1); - (void) strftime(s, MAXSIZE, optf, &ts->ts_tm2); - (void) strftime(s, MAXSIZE, optf, &ts->ts_tm1); - (void) strftime(s, MAXSIZE, optf, &ts->ts_tm2); - (void) strftime(s, MAXSIZE, optf, &ts->ts_tm1); - (void) strftime(s, MAXSIZE, optf, &ts->ts_tm2); - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/strlen.c b/tools/tests/libMicro/strlen.c deleted file mode 100644 index bfcce12d3..000000000 --- a/tools/tests/libMicro/strlen.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include -#include - -#include "libmicro.h" - -static int unaligned = 0; -static int opts = 100; - -typedef struct { - int ts_once; - char *ts_string; - int ts_fakegcc; -} tsd_t; - -int -benchmark_init() -{ - - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "s:n"); - - (void) sprintf(lm_usage, - " [-s string size (default %d)]\n" - " [-n causes unaligned strlen]\n" - "notes: measures strlen()\n", - opts); - - (void) sprintf(lm_header, "%8s", "size"); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'n': - unaligned = 1; - break; - case 's': - opts = sizetoll(optarg); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - static char *demo = - "The quick brown fox jumps over the lazy dog."; - - if (ts->ts_once++ == 0) { - int l = strlen(demo); - int i; - - ts->ts_string = malloc(opts + 1 + unaligned); - ts->ts_string += unaligned; - - - for (i = 0; i < opts; i++) { - ts->ts_string[i] = demo[i%l]; - } - - ts->ts_string[opts] = 0; - - } - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - int i; - tsd_t *ts = (tsd_t *)tsd; - char *src = ts->ts_string; - - for (i = 0; i < lm_optB; i += 10) { - ts->ts_fakegcc += strlen(src); - ts->ts_fakegcc += strlen(src); - ts->ts_fakegcc += strlen(src); - ts->ts_fakegcc += strlen(src); - ts->ts_fakegcc += strlen(src); - ts->ts_fakegcc += strlen(src); - ts->ts_fakegcc += strlen(src); - ts->ts_fakegcc += strlen(src); - ts->ts_fakegcc += strlen(src); - ts->ts_fakegcc += strlen(src); - } - - res->re_count = i; - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - - if (unaligned == 0) - (void) sprintf(result, "%8d", opts); - else - (void) sprintf(result, "%8d ", opts); - - return (result); -} diff --git a/tools/tests/libMicro/strtol.c b/tools/tests/libMicro/strtol.c deleted file mode 100644 index 02f8abc75..000000000 --- a/tools/tests/libMicro/strtol.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include -#include - -#include "libmicro.h" - -int -benchmark_init() -{ - (void) sprintf(lm_usage, "note: measures strtol()"); - lm_tsdsize = 0; - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - - for (i = 0; i < lm_optB; i += 10) { - (void) strtol("1", NULL, 10); - (void) strtol("11", NULL, 10); - (void) strtol("123", NULL, 10); - (void) strtol("1234", NULL, 10); - (void) strtol("12345", NULL, 10); - (void) strtol("123456", NULL, 10); - (void) strtol("1234567", NULL, 10); - (void) strtol("12345678", NULL, 10); - (void) strtol("123456789", NULL, 10); - (void) strtol("1234567890", NULL, 10); - } - res->re_count = i; - - return (0); -} diff --git a/tools/tests/libMicro/system.c b/tools/tests/libMicro/system.c deleted file mode 100644 index d70db260f..000000000 --- a/tools/tests/libMicro/system.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include - -#include "libmicro.h" - -#define DEFB 10 -#define DEFC "A=$$" - -static char *optc = DEFC; - -int -benchmark_init() -{ - lm_tsdsize = 0; - - (void) sprintf(lm_optstr, "c:"); - - (void) sprintf(lm_usage, - " [-c command (default %s)]\n" - "notes: measures system()\n", - DEFC); - - (void) sprintf(lm_header, "%8s", "command"); - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'c': - optc = optarg; - break; - default: - return (-1); - } - - return (0); -} - - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - - for (i = 0; i < lm_optB; i++) { - if (system(optc) != 0) { - res->re_errors++; - } - } - res->re_count = lm_optB; - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - - (void) sprintf(result, "%8s", optc); - - return (result); -} diff --git a/tools/tests/libMicro/tattle.c b/tools/tests/libMicro/tattle.c deleted file mode 100644 index 59520f8ce..000000000 --- a/tools/tests/libMicro/tattle.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include -#include -#include -#include -#include -#include "libmicro.h" -#include - - -#ifdef USE_RDTSC -#ifdef __GNUC__ -#define ENABLE_RDTSC 1 -#endif -#endif - -/* - * dummy so we can link w/ libmicro - */ - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - return (0); -} - -static void -cleanup(char *s) -{ - char *o = s; - char *e; - - while (*s == ' ') - s++; - - if (o != s) - (void) strcpy(o, s); - - e = o; - - while (*e != 0) - e++; - - e--; - - while (*e == ' ' && e > o) - *e-- = 0; - -} - - -int -main(int argc, char *argv[]) -{ - int c; - - if (strlen(compiler_version) > 30) - compiler_version[30] = 0; - - cleanup(compiler_version); - cleanup(extra_compiler_flags); - - while ((c = getopt(argc, argv, "vcfrsVTR")) != -1) { - switch (c) { - case 'V': - (void) printf("%s\n", LIBMICRO_VERSION); - break; - case 'v': - (void) printf("%s\n", compiler_version); - break; - case 'c': - (void) printf("%s\n", CC); - break; - case 'f': - if (strlen(extra_compiler_flags) == 0) - (void) printf("[none]\n"); - else - (void) printf("%s\n", extra_compiler_flags); - break; - - case 's': - (void) printf("%d\n", sizeof (long)); - break; - - case 'r': - - (void) printf("%lld nsecs\n", get_nsecs_resolution()); - break; - - case 'R': -#ifdef ENABLE_RDTSC - { - struct timeval s; - struct timeval f; - long long start_nsecs; - long long end_nsecs; - long elapsed_usecs; - - gettimeofday(&s, NULL); - start_nsecs = rdtsc(); - for (;;) { - gettimeofday(&f, NULL); - elapsed_usecs = (f.tv_sec - s.tv_sec) * - 1000000 + (f.tv_usec - s.tv_usec); - if (elapsed_usecs > 1000000) - break; - } - end_nsecs = rdtsc(); - (void) printf("LIBMICRO_HZ=%lld\n", - (long long)elapsed_usecs * - (end_nsecs - start_nsecs) / 1000000LL); - } -#else - (void) printf("\n"); -#endif - break; - } - } - - exit(0); - return (0); -} diff --git a/tools/tests/libMicro/time.c b/tools/tests/libMicro/time.c deleted file mode 100644 index aa46d499f..000000000 --- a/tools/tests/libMicro/time.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include - -#include "libmicro.h" - -int -benchmark_init() -{ - lm_tsdsize = 0; - - (void) sprintf(lm_usage, - "notes: measures time()\n"); - - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - - for (i = 0; i < lm_optB; i += 10) { - (void) time(NULL); - (void) time(NULL); - (void) time(NULL); - (void) time(NULL); - (void) time(NULL); - (void) time(NULL); - (void) time(NULL); - (void) time(NULL); - (void) time(NULL); - (void) time(NULL); - } - res->re_count += i; - - return (0); -} diff --git a/tools/tests/libMicro/times.c b/tools/tests/libMicro/times.c deleted file mode 100644 index 670af9bf8..000000000 --- a/tools/tests/libMicro/times.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include -#include -#include - -#include "libmicro.h" - -int -benchmark_init() -{ - - lm_tsdsize = 0; - - (void) sprintf(lm_usage, - "notes: measures times()\n"); - - return (0); -} - -/*ARGSUSED*/ -int -benchmark(void *tsd, result_t *res) -{ - int i; - struct tms buf; - - for (i = 0; i < lm_optB; i += 10) { - (void) times(&buf); - (void) times(&buf); - (void) times(&buf); - (void) times(&buf); - (void) times(&buf); - (void) times(&buf); - (void) times(&buf); - (void) times(&buf); - (void) times(&buf); - (void) times(&buf); - } - res->re_count += i; - - return (0); -} diff --git a/tools/tests/libMicro/wrapper.sh b/tools/tests/libMicro/wrapper.sh deleted file mode 100755 index 791643dbe..000000000 --- a/tools/tests/libMicro/wrapper.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh -# -# CDDL HEADER START -# -# The contents of this file are subject to the terms -# of the Common Development and Distribution License -# (the "License"). You may not use this file except -# in compliance with the License. -# -# You can obtain a copy of the license at -# src/OPENSOLARIS.LICENSE -# or http://www.opensolaris.org/os/licensing. -# See the License for the specific language governing -# permissions and limitations under the License. -# -# When distributing Covered Code, include this CDDL -# HEADER in each file and include the License file at -# usr/src/OPENSOLARIS.LICENSE. If applicable, -# add the following below this CDDL HEADER, with the -# fields enclosed by brackets "[]" replaced with your -# own identifying information: Portions Copyright [yyyy] -# [name of copyright owner] -# -# CDDL HEADER END -# - -# -# Copyright 2007 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - - -BASENAME=`basename $0` -DIRNAME=`dirname $0` -ARCH=`uname -m` - -exec $DIRNAME/../bin-$ARCH/$BASENAME "$@" diff --git a/tools/tests/libMicro/write.c b/tools/tests/libMicro/write.c deleted file mode 100644 index 078027435..000000000 --- a/tools/tests/libMicro/write.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifdef linux -#define _XOPEN_SOURCE 500 -#endif - -#include -#include -#include -#include - -#include "libmicro.h" - -typedef struct { - char *ts_buf; - int ts_fd; -} tsd_t; - -#define DEFF "/dev/null" -#define DEFS 1024 - -static int optc = 0; -static char *optf = DEFF; -static long long opts = DEFS; -static int optd; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "cdf:s:"); - - (void) sprintf(lm_usage, - " [-f file-to-write (default %s)]\n" - " [-s buffer-size (default %d)]\n" - " [-c ] (make sure buffer is in cache)\n" -#ifdef __sun - " [-d ] use directio" -#endif - "notes: measures write()\n", - DEFF, DEFS); - - (void) sprintf(lm_header, "%8s", "size"); - - lm_defB = 1; - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - - case 'd': - optd++; - break; - case 'c': - optc++; - break; - case 'f': - optf = optarg; - break; - case 's': - opts = sizetoll(optarg); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - if (ts->ts_buf == NULL) { - ts->ts_buf = malloc(opts); - ts->ts_fd = open(optf, O_WRONLY); - -#ifdef __sun - if (optd) - (void) directio(ts->ts_fd, DIRECTIO_ON); -#endif - /* - * bring buf into cache if specified. - */ - - if (optc) - for (i = 0; i < opts; i++) - ts->ts_buf[i] = 0; - } - - (void) lseek(ts->ts_fd, 0, SEEK_SET); - - return (0); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - for (i = 0; i < lm_optB; i++) { - if (write(ts->ts_fd, ts->ts_buf, opts) != opts) { - res->re_errors++; - } - } - res->re_count = i; - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - - (void) sprintf(result, "%8lld", opts); - - return (result); -} diff --git a/tools/tests/libMicro/writev.c b/tools/tests/libMicro/writev.c deleted file mode 100644 index ac1bf2ef3..000000000 --- a/tools/tests/libMicro/writev.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms - * of the Common Development and Distribution License - * (the "License"). You may not use this file except - * in compliance with the License. - * - * You can obtain a copy of the license at - * src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing - * permissions and limitations under the License. - * - * When distributing Covered Code, include this CDDL - * HEADER in each file and include the License file at - * usr/src/OPENSOLARIS.LICENSE. If applicable, - * add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your - * own identifying information: Portions Copyright [yyyy] - * [name of copyright owner] - * - * CDDL HEADER END - */ - -/* - * Copyright 2005 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#include -#include -#include -#include -#include -#include - -#ifndef IOV_MAX -#define IOV_MAX UIO_MAXIOV -#endif - -#include "libmicro.h" - -typedef struct { - int ts_once; - struct iovec *ts_iov; - int ts_fd; -} tsd_t; - -#define DEFF "/dev/null" -#define DEFS 1024 -#define DEFV 10 - -static char *optf = DEFF; -static int opts = DEFS; -static int optv = DEFV; - -int -benchmark_init() -{ - lm_tsdsize = sizeof (tsd_t); - - (void) sprintf(lm_optstr, "f:s:v:"); - - (void) sprintf(lm_usage, - " [-f file-to-write (default %s)]\n" - " [-s buffer-size (default %d)]\n" - " [-v vector-size (default %d)]\n" - "notes: measures writev()\n" - " IOV_MAX is %d\n" - " SSIZE_MAX is %ld\n", - DEFF, DEFS, DEFV, IOV_MAX, SSIZE_MAX); - - (void) sprintf(lm_header, "%8s %4s", "size", "vec"); - - lm_defB = 1; - - return (0); -} - -int -benchmark_optswitch(int opt, char *optarg) -{ - switch (opt) { - case 'f': - optf = optarg; - break; - case 's': - opts = sizetoint(optarg); - break; - case 'v': - optv = atoi(optarg); - break; - default: - return (-1); - } - return (0); -} - -int -benchmark_initbatch(void *tsd) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - int errors = 0; - - if (ts->ts_once++ == 0) { - ts->ts_fd = open(optf, O_WRONLY); - if (ts->ts_fd == -1) { - errors++; - } - ts->ts_iov = (struct iovec *)malloc( - optv * sizeof (struct iovec)); - for (i = 0; i < optv; i++) { - ts->ts_iov[i].iov_base = malloc(opts); - ts->ts_iov[i].iov_len = opts; - } - } - - (void) lseek(ts->ts_fd, 0, SEEK_SET); - - return (errors); -} - -int -benchmark(void *tsd, result_t *res) -{ - tsd_t *ts = (tsd_t *)tsd; - int i; - - for (i = 0; i < lm_optB; i++) { - if (writev(ts->ts_fd, ts->ts_iov, optv) != opts * optv) { - res->re_errors++; - } - } - res->re_count = i; - - return (0); -} - -char * -benchmark_result() -{ - static char result[256]; - - (void) sprintf(result, "%8d %4d", opts, optv); - - return (result); -} diff --git a/tools/trace/bridgetime.lua b/tools/trace/bridgetime.lua new file mode 100755 index 000000000..cba2d522d --- /dev/null +++ b/tools/trace/bridgetime.lua @@ -0,0 +1,97 @@ +#!/usr/local/bin/luatrace -s + +trace_codename = function(codename, callback) + local debugid = trace.debugid(codename) + if debugid ~= 0 then + trace.single(debugid,callback) + else + printf("WARNING: Cannot locate debugid for '%s'\n", codename) + end +end + +initial_timestamp = 0 +get_prefix = function(buf, char) + -- if initial_timestamp == 0 then + -- initial_timestamp = buf.timestamp + -- end + local secs = trace.convert_timestamp_to_nanoseconds(buf.timestamp - initial_timestamp) / 1000000000 + + return string.format("%s %6.9f %-30s", + char, secs, buf.debugname) +end + +initial_arm_timestamp = 0 +format_timestamp_arm = function(ts) + local secs = trace.convert_timestamp_to_nanoseconds(ts - initial_arm_timestamp) / 1000000000 + return string.format("%6.9f", secs); +end + +initial_intel_timestamp = 0 +format_timestamp_intel = function(ts) + local secs = (ts - initial_intel_timestamp) / 1000000000 + return string.format("%6.9f", secs); +end + +format_timestamp_ns = function(ts) + local secs = (ts) / 1000000000 + return string.format("%6.9f", secs); +end + +trace_codename("MACH_CLOCK_BRIDGE_RESET_TS", function(buf) + local prefix = get_prefix(buf, "X") + local reason = "UNKNOWN"; + if buf[3] == 1 then + reason = "RecvSentinel" + elseif buf[3] == 2 then + reason = "ResetTrue" + elseif buf[3] == 3 then + reason = "RateZero" + end + printf("%s %-15s ( %-10s %-10s ) ----------------------------------------\n", + prefix, reason, format_timestamp_arm(buf[1]), format_timestamp_intel(buf[2])) + + -- initial_arm_timestamp = buf[1] + -- initial_intel_timestamp = buf[2] +end) + +trace_codename("MACH_CLOCK_BRIDGE_TS_PARAMS", function(buf) + local prefix = get_prefix(buf, ">") + + local rate + if darwin.uint64_to_double then + rate = darwin.uint64_to_double(buf[3]) + else + rate = math.nan + end + + printf("%s %30s( %-10s %-10s ) rate = %f\n", + prefix, "", format_timestamp_ns(buf[1]), format_timestamp_intel(buf[2]), + rate) +end) + +trace_codename("MACH_CLOCK_BRIDGE_REMOTE_TIME", function(buf) + local prefix = get_prefix(buf, "-") + + printf("%s ( %-10s %-10s ) @ %-20s\n", + prefix, format_timestamp_arm(buf[1]), format_timestamp_intel(buf[2]), format_timestamp_arm(buf[3])) +end) + +trace_codename("MACH_CLOCK_BRIDGE_RCV_TS", function(buf) + local prefix = get_prefix(buf, "<") + + if buf[2] == 0xfffffffffffffffe then + printf("%s ( %-10s Sleep )\n", + prefix, format_timestamp_arm(buf[1]), format_timestamp_intel(buf[2])) + elseif buf[2] == 0xfffffffffffffffd then + printf("%s ( %-10s Wake )\n", + prefix, format_timestamp_arm(buf[1]), format_timestamp_intel(buf[2])) + elseif buf[2] == 0xfffffffffffffffc then + printf("%s ( %-10s Reset )\n", + prefix, format_timestamp_arm(buf[1]), format_timestamp_intel(buf[2])) + else + printf("%s ( %-10s %-10s )\n", + prefix, format_timestamp_arm(buf[1]), format_timestamp_intel(buf[2])) + end + +end) +