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