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