1*bbb1b6f9SApple OSS Distributions /* 2*bbb1b6f9SApple OSS Distributions * Copyright (c) 2019 Apple Inc. All rights reserved. 3*bbb1b6f9SApple OSS Distributions */ 4*bbb1b6f9SApple OSS Distributions 5*bbb1b6f9SApple OSS Distributions #include <darwintest.h> 6*bbb1b6f9SApple OSS Distributions #include <inttypes.h> 7*bbb1b6f9SApple OSS Distributions #if __arm64__ 8*bbb1b6f9SApple OSS Distributions #include <mach/arm/processor_info.h> 9*bbb1b6f9SApple OSS Distributions #endif /* __arm64__ */ 10*bbb1b6f9SApple OSS Distributions #include <mach/mach.h> 11*bbb1b6f9SApple OSS Distributions #include <stdlib.h> 12*bbb1b6f9SApple OSS Distributions #include <unistd.h> 13*bbb1b6f9SApple OSS Distributions 14*bbb1b6f9SApple OSS Distributions T_GLOBAL_META(T_META_ASROOT(true), 15*bbb1b6f9SApple OSS Distributions T_META_RUN_CONCURRENTLY(true)); 16*bbb1b6f9SApple OSS Distributions 17*bbb1b6f9SApple OSS Distributions T_DECL(processor_cpu_stat64, 18*bbb1b6f9SApple OSS Distributions "ensure 64-bit processor statistics are reported correctly", 19*bbb1b6f9SApple OSS Distributions T_META_NAMESPACE("xnu.arm"), 20*bbb1b6f9SApple OSS Distributions T_META_RADAR_COMPONENT_NAME("xnu"), 21*bbb1b6f9SApple OSS Distributions T_META_RADAR_COMPONENT_VERSION("arm"), 22*bbb1b6f9SApple OSS Distributions T_META_OWNER("mwidmann"), 23*bbb1b6f9SApple OSS Distributions T_META_TAG_VM_PREFERRED, 24*bbb1b6f9SApple OSS Distributions T_META_ENABLED(false /* rdar://133956573 */)) 25*bbb1b6f9SApple OSS Distributions { 26*bbb1b6f9SApple OSS Distributions #if !__arm64__ 27*bbb1b6f9SApple OSS Distributions T_SKIP("processor statistics only available on ARM"); 28*bbb1b6f9SApple OSS Distributions #else /* !__arm64__ */ 29*bbb1b6f9SApple OSS Distributions host_t host = mach_host_self(); 30*bbb1b6f9SApple OSS Distributions host_t priv_port = MACH_PORT_NULL; 31*bbb1b6f9SApple OSS Distributions 32*bbb1b6f9SApple OSS Distributions kern_return_t kr = host_get_host_priv_port(host, &priv_port); 33*bbb1b6f9SApple OSS Distributions T_QUIET; 34*bbb1b6f9SApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "host_get_host_priv_port"); 35*bbb1b6f9SApple OSS Distributions T_QUIET; 36*bbb1b6f9SApple OSS Distributions T_ASSERT_NE(priv_port, MACH_PORT_NULL, "valid host priv port"); 37*bbb1b6f9SApple OSS Distributions 38*bbb1b6f9SApple OSS Distributions processor_port_array_t cpu_ports = NULL; 39*bbb1b6f9SApple OSS Distributions mach_msg_type_number_t cpu_count = 0; 40*bbb1b6f9SApple OSS Distributions kr = host_processors(priv_port, &cpu_ports, &cpu_count); 41*bbb1b6f9SApple OSS Distributions T_QUIET; 42*bbb1b6f9SApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "host_processors"); 43*bbb1b6f9SApple OSS Distributions T_QUIET; 44*bbb1b6f9SApple OSS Distributions T_ASSERT_NOTNULL(cpu_ports, "valid processor port array"); 45*bbb1b6f9SApple OSS Distributions T_QUIET; 46*bbb1b6f9SApple OSS Distributions T_ASSERT_GT(cpu_count, (mach_msg_type_number_t)0, 47*bbb1b6f9SApple OSS Distributions "non-zero CPU count"); 48*bbb1b6f9SApple OSS Distributions 49*bbb1b6f9SApple OSS Distributions T_LOG("found %d CPUs", cpu_count); 50*bbb1b6f9SApple OSS Distributions 51*bbb1b6f9SApple OSS Distributions struct processor_cpu_stat64 *prestats = calloc(cpu_count, 52*bbb1b6f9SApple OSS Distributions sizeof(*prestats)); 53*bbb1b6f9SApple OSS Distributions T_WITH_ERRNO; 54*bbb1b6f9SApple OSS Distributions T_QUIET; 55*bbb1b6f9SApple OSS Distributions T_ASSERT_NOTNULL(prestats, "allocate space for stats (pre)"); 56*bbb1b6f9SApple OSS Distributions memset(prestats, 0xff, cpu_count * sizeof(*prestats)); 57*bbb1b6f9SApple OSS Distributions 58*bbb1b6f9SApple OSS Distributions for (int i = 0; i < (int)cpu_count; i++) { 59*bbb1b6f9SApple OSS Distributions mach_msg_type_number_t info_count = PROCESSOR_CPU_STAT64_COUNT; 60*bbb1b6f9SApple OSS Distributions kr = processor_info(cpu_ports[i], PROCESSOR_CPU_STAT64, &host, 61*bbb1b6f9SApple OSS Distributions (processor_info_t)&prestats[i], &info_count); 62*bbb1b6f9SApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, 63*bbb1b6f9SApple OSS Distributions "processor_info(%d, PROCESSOR_CPU_STAT64, ...)", i); 64*bbb1b6f9SApple OSS Distributions 65*bbb1b6f9SApple OSS Distributions T_QUIET; 66*bbb1b6f9SApple OSS Distributions T_ASSERT_EQ(info_count, PROCESSOR_CPU_STAT64_COUNT, 67*bbb1b6f9SApple OSS Distributions "received enough CPU statistics"); 68*bbb1b6f9SApple OSS Distributions } 69*bbb1b6f9SApple OSS Distributions 70*bbb1b6f9SApple OSS Distributions sleep(1); 71*bbb1b6f9SApple OSS Distributions 72*bbb1b6f9SApple OSS Distributions struct processor_cpu_stat64 *poststats = calloc(cpu_count - 1, 73*bbb1b6f9SApple OSS Distributions sizeof(*poststats)); 74*bbb1b6f9SApple OSS Distributions T_WITH_ERRNO; 75*bbb1b6f9SApple OSS Distributions T_QUIET; 76*bbb1b6f9SApple OSS Distributions T_ASSERT_NOTNULL(poststats, "allocate space for stats (post)"); 77*bbb1b6f9SApple OSS Distributions 78*bbb1b6f9SApple OSS Distributions for (int i = 0; i < (int)cpu_count; i++) { 79*bbb1b6f9SApple OSS Distributions mach_msg_type_number_t info_count = PROCESSOR_CPU_STAT64_COUNT; 80*bbb1b6f9SApple OSS Distributions kr = processor_info(cpu_ports[i], PROCESSOR_CPU_STAT64, &host, 81*bbb1b6f9SApple OSS Distributions (processor_info_t)&poststats[i], &info_count); 82*bbb1b6f9SApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, 83*bbb1b6f9SApple OSS Distributions "processor_info(%d, PROCESSOR_CPU_STAT64, ...)", i); 84*bbb1b6f9SApple OSS Distributions 85*bbb1b6f9SApple OSS Distributions T_QUIET; 86*bbb1b6f9SApple OSS Distributions T_ASSERT_EQ(info_count, PROCESSOR_CPU_STAT64_COUNT, 87*bbb1b6f9SApple OSS Distributions "received enough CPU statistics"); 88*bbb1b6f9SApple OSS Distributions } 89*bbb1b6f9SApple OSS Distributions 90*bbb1b6f9SApple OSS Distributions for (int i = 0; i < (int)cpu_count; i++) { 91*bbb1b6f9SApple OSS Distributions #define CHECK_STAT_FIELD(field) \ 92*bbb1b6f9SApple OSS Distributions T_EXPECT_GE(poststats[i].field, prestats[i].field, \ 93*bbb1b6f9SApple OSS Distributions "CPU %d's " #field " is monotonically increasing (+%" PRIu64 \ 94*bbb1b6f9SApple OSS Distributions ")", i, poststats[i].field - prestats[i].field) 95*bbb1b6f9SApple OSS Distributions 96*bbb1b6f9SApple OSS Distributions CHECK_STAT_FIELD(irq_ex_cnt); 97*bbb1b6f9SApple OSS Distributions CHECK_STAT_FIELD(ipi_cnt); 98*bbb1b6f9SApple OSS Distributions CHECK_STAT_FIELD(timer_cnt); 99*bbb1b6f9SApple OSS Distributions CHECK_STAT_FIELD(undef_ex_cnt); 100*bbb1b6f9SApple OSS Distributions CHECK_STAT_FIELD(unaligned_cnt); 101*bbb1b6f9SApple OSS Distributions CHECK_STAT_FIELD(vfp_cnt); 102*bbb1b6f9SApple OSS Distributions CHECK_STAT_FIELD(vfp_shortv_cnt); 103*bbb1b6f9SApple OSS Distributions CHECK_STAT_FIELD(data_ex_cnt); 104*bbb1b6f9SApple OSS Distributions CHECK_STAT_FIELD(instr_ex_cnt); 105*bbb1b6f9SApple OSS Distributions CHECK_STAT_FIELD(pmi_cnt); 106*bbb1b6f9SApple OSS Distributions 107*bbb1b6f9SApple OSS Distributions #undef CHECK_STAT_FIELD 108*bbb1b6f9SApple OSS Distributions } 109*bbb1b6f9SApple OSS Distributions 110*bbb1b6f9SApple OSS Distributions free(prestats); 111*bbb1b6f9SApple OSS Distributions free(poststats); 112*bbb1b6f9SApple OSS Distributions #endif /* __arm64__ */ 113*bbb1b6f9SApple OSS Distributions } 114*bbb1b6f9SApple OSS Distributions 115*bbb1b6f9SApple OSS Distributions 116*bbb1b6f9SApple OSS Distributions T_DECL(processor_cpu_info_order, 117*bbb1b6f9SApple OSS Distributions "ensure host_processor_info iterates CPU in CPU ID order", T_META_TAG_VM_PREFERRED) 118*bbb1b6f9SApple OSS Distributions { 119*bbb1b6f9SApple OSS Distributions host_t host = mach_host_self(); 120*bbb1b6f9SApple OSS Distributions host_t priv_port = MACH_PORT_NULL; 121*bbb1b6f9SApple OSS Distributions 122*bbb1b6f9SApple OSS Distributions kern_return_t kr = host_get_host_priv_port(host, &priv_port); 123*bbb1b6f9SApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "host_get_host_priv_port"); 124*bbb1b6f9SApple OSS Distributions T_QUIET; T_ASSERT_NE(priv_port, MACH_PORT_NULL, "valid host priv port"); 125*bbb1b6f9SApple OSS Distributions 126*bbb1b6f9SApple OSS Distributions processor_info_array_t info_array = NULL; 127*bbb1b6f9SApple OSS Distributions mach_msg_type_number_t info_count = 0; 128*bbb1b6f9SApple OSS Distributions natural_t processor_count = 0; 129*bbb1b6f9SApple OSS Distributions 130*bbb1b6f9SApple OSS Distributions kr = host_processor_info(mach_host_self(), PROCESSOR_BASIC_INFO, &processor_count, 131*bbb1b6f9SApple OSS Distributions &info_array, &info_count); 132*bbb1b6f9SApple OSS Distributions 133*bbb1b6f9SApple OSS Distributions T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "host_processor_info(PROCESSOR_BASIC_INFO)"); 134*bbb1b6f9SApple OSS Distributions T_QUIET; T_ASSERT_NOTNULL(info_array, "valid processor port array"); 135*bbb1b6f9SApple OSS Distributions T_QUIET; T_ASSERT_GT(info_count, (mach_msg_type_number_t)0, "non-zero array"); 136*bbb1b6f9SApple OSS Distributions T_QUIET; T_ASSERT_GT(processor_count, (natural_t)0, "non-zero processor_count"); 137*bbb1b6f9SApple OSS Distributions 138*bbb1b6f9SApple OSS Distributions processor_basic_info_t basic_info_array = (processor_basic_info_t)info_array; 139*bbb1b6f9SApple OSS Distributions 140*bbb1b6f9SApple OSS Distributions for (natural_t i = 0; i < processor_count; i++) { 141*bbb1b6f9SApple OSS Distributions struct processor_basic_info* processor_info = &basic_info_array[i]; 142*bbb1b6f9SApple OSS Distributions 143*bbb1b6f9SApple OSS Distributions natural_t slot_num = (natural_t)processor_info->slot_num; 144*bbb1b6f9SApple OSS Distributions 145*bbb1b6f9SApple OSS Distributions T_ASSERT_EQ(slot_num, i, "CPU ID must equal array index"); 146*bbb1b6f9SApple OSS Distributions } 147*bbb1b6f9SApple OSS Distributions } 148