host.c
1 #include <darlingserver/duct-tape/stubs.h> 2 3 #include <kern/host.h> 4 #include <mach_debug/mach_debug.h> 5 6 #include <libsimple/lock.h> 7 8 // Linux sysinfo (from the sysinfo man page) 9 struct sysinfo { 10 long uptime; 11 unsigned long loads[3]; 12 unsigned long totalram; 13 unsigned long freeram; 14 unsigned long sharedram; 15 unsigned long bufferram; 16 unsigned long totalswap; 17 unsigned long freeswap; 18 unsigned short procs; 19 unsigned long totalhigh; 20 unsigned long freehigh; 21 unsigned int mem_unit; 22 char _f[20 - 2 * sizeof(long) - sizeof(int)]; 23 }; 24 int sysinfo(struct sysinfo *info); 25 26 // Linux sysconf 27 long sysconf(int name); 28 #define _SC_NPROCESSORS_CONF 83 29 #define _SC_NPROCESSORS_ONLN 84 30 31 static void cache_sysinfo(void* context) { 32 struct sysinfo* cached_sysinfo = context; 33 34 if (sysinfo(cached_sysinfo) < 0) { 35 panic("Failed to retrieve sysinfo"); 36 } 37 }; 38 39 kern_return_t host_info(host_t host, host_flavor_t flavor, host_info_t info, mach_msg_type_number_t* count) { 40 static libsimple_once_t once_token = LIBSIMPLE_ONCE_INITIALIZER; 41 static struct sysinfo cached_sysinfo; 42 43 if (host == HOST_NULL) { 44 return KERN_INVALID_ARGUMENT; 45 } 46 47 switch (flavor) { 48 case HOST_BASIC_INFO: { 49 host_basic_info_t basic_info = (host_basic_info_t)info; 50 51 // need at least enough space for the legacy structure 52 if (*count < HOST_BASIC_INFO_OLD_COUNT) { 53 return KERN_FAILURE; 54 } 55 56 libsimple_once(&once_token, cache_sysinfo, &cached_sysinfo); 57 58 uint64_t memsize = cached_sysinfo.totalram * cached_sysinfo.mem_unit; 59 60 basic_info->memory_size = memsize; 61 #if __x86_64__ || __i386__ 62 basic_info->cpu_type = CPU_TYPE_X86; 63 #if __x86_64__ 64 basic_info->cpu_subtype = CPU_SUBTYPE_X86_64_ALL; 65 #else 66 basic_info->cpu_subtype = CPU_SUBTYPE_I386_ALL; 67 #endif 68 #else 69 #error Unknown CPU type 70 #endif 71 basic_info->max_cpus = sysconf(_SC_NPROCESSORS_CONF); 72 basic_info->avail_cpus = sysconf(_SC_NPROCESSORS_ONLN); 73 74 // if there's room for the modern structure, fill in some additional info 75 if (*count >= HOST_BASIC_INFO_COUNT) { 76 // TODO: properly differentiate physical vs. logical cores 77 dtape_stub_safe("modern HOST_BASIC_INFO"); 78 basic_info->cpu_threadtype = CPU_THREADTYPE_NONE; 79 basic_info->physical_cpu = basic_info->avail_cpus; 80 basic_info->physical_cpu_max = basic_info->max_cpus; 81 basic_info->logical_cpu = basic_info->avail_cpus; 82 basic_info->logical_cpu_max = basic_info->max_cpus; 83 84 basic_info->max_mem = memsize; 85 86 *count = HOST_BASIC_INFO_COUNT; 87 } else { 88 *count = HOST_BASIC_INFO_OLD_COUNT; 89 } 90 91 return KERN_SUCCESS; 92 } 93 94 case HOST_PRIORITY_INFO: { 95 // <copied from="xnu://7195.141.2/osfmk/kern/host.c"> 96 host_priority_info_t priority_info; 97 98 if (*count < HOST_PRIORITY_INFO_COUNT) { 99 return KERN_FAILURE; 100 } 101 102 priority_info = (host_priority_info_t)info; 103 104 priority_info->kernel_priority = MINPRI_KERNEL; 105 priority_info->system_priority = MINPRI_KERNEL; 106 priority_info->server_priority = MINPRI_RESERVED; 107 priority_info->user_priority = BASEPRI_DEFAULT; 108 priority_info->depress_priority = DEPRESSPRI; 109 priority_info->idle_priority = IDLEPRI; 110 priority_info->minimum_priority = MINPRI_USER; 111 priority_info->maximum_priority = MAXPRI_RESERVED; 112 113 *count = HOST_PRIORITY_INFO_COUNT; 114 115 return KERN_SUCCESS; 116 // </copied> 117 } 118 119 case HOST_DEBUG_INFO_INTERNAL: 120 return KERN_NOT_SUPPORTED; 121 122 case HOST_PREFERRED_USER_ARCH: { 123 host_preferred_user_arch_t user_arch_info; 124 125 if (*count < HOST_PREFERRED_USER_ARCH_COUNT) { 126 return KERN_FAILURE; 127 } 128 129 *count = HOST_PREFERRED_USER_ARCH_COUNT; 130 131 user_arch_info = (void*)info; 132 133 #if __x86_64__ || __i386__ 134 user_arch_info->cpu_type = CPU_TYPE_X86; 135 #if __x86_64__ 136 user_arch_info->cpu_subtype = CPU_SUBTYPE_X86_64_ALL; 137 #else 138 user_arch_info->cpu_subtype = CPU_SUBTYPE_I386_ALL; 139 #endif 140 #elif __aarch64__ 141 // TODO: check whether this is actually what ARM64 macOS returns 142 user_arch_info->cpu_type = CPU_TYPE_ARM64; 143 user_arch_info->cpu_subtype = CPU_SUBTYPE_ARM64_ALL; 144 #else 145 #error HOST_PREFERRED_USER_ARCH not implemented for this architecture 146 #endif 147 148 return KERN_SUCCESS; 149 }; 150 151 case HOST_SCHED_INFO: 152 dtape_stub_unsafe("HOST_SCHED_INFO"); 153 case HOST_RESOURCE_SIZES: 154 dtape_stub_unsafe("HOST_RESOURCE_SIZES"); 155 case HOST_CAN_HAS_DEBUGGER: 156 dtape_stub_unsafe("HOST_CAN_HAS_DEBUGGER"); 157 case HOST_VM_PURGABLE: 158 dtape_stub_unsafe("HOST_VM_PURGABLE"); 159 160 case HOST_MACH_MSG_TRAP: 161 case HOST_SEMAPHORE_TRAPS: 162 *count = 0; 163 return KERN_SUCCESS; 164 165 default: 166 return KERN_INVALID_ARGUMENT; 167 } 168 }; 169 170 kern_return_t host_default_memory_manager(host_priv_t host_priv, memory_object_default_t* default_manager, memory_object_cluster_size_t cluster_size) { 171 dtape_stub_unsafe(); 172 }; 173 174 kern_return_t host_get_boot_info(host_priv_t host_priv, kernel_boot_info_t boot_info) { 175 dtape_stub_unsafe(); 176 }; 177 178 kern_return_t host_get_UNDServer(host_priv_t host_priv, UNDServerRef* serverp) { 179 dtape_stub_unsafe(); 180 }; 181 182 kern_return_t host_set_UNDServer(host_priv_t host_priv, UNDServerRef server) { 183 dtape_stub_unsafe(); 184 }; 185 186 kern_return_t host_lockgroup_info(host_t host, lockgroup_info_array_t* lockgroup_infop, mach_msg_type_number_t* lockgroup_infoCntp) { 187 dtape_stub_unsafe(); 188 }; 189 190 kern_return_t host_reboot(host_priv_t host_priv, int options) { 191 dtape_stub_unsafe(); 192 }; 193 194 kern_return_t host_security_create_task_token(host_security_t host_security, task_t parent_task, security_token_t sec_token, audit_token_t audit_token, host_priv_t host_priv, ledger_port_array_t ledger_ports, mach_msg_type_number_t num_ledger_ports, boolean_t inherit_memory, task_t* child_task) { 195 dtape_stub_safe(); 196 return KERN_NOT_SUPPORTED; 197 }; 198 199 kern_return_t host_security_set_task_token(host_security_t host_security, task_t task, security_token_t sec_token, audit_token_t audit_token, host_priv_t host_priv) { 200 dtape_stub_unsafe(); 201 }; 202 203 kern_return_t host_virtual_physical_table_info(host_t host, hash_info_bucket_array_t* infop, mach_msg_type_number_t* countp) { 204 dtape_stub_unsafe(); 205 }; 206 207 kern_return_t host_statistics(host_t host, host_flavor_t flavor, host_info_t info, mach_msg_type_number_t* count) { 208 switch (flavor) { 209 // we can get away with not implementing it 210 case HOST_VM_INFO: { 211 vm_statistics_t stat32 = (vm_statistics_t)info; 212 213 if (*count < HOST_VM_INFO_REV0_COUNT) { 214 return KERN_FAILURE; 215 } 216 217 dtape_stub_safe("HOST_VM_INFO"); 218 memset(stat32, 0, (*count) * sizeof(integer_t)); 219 220 return KERN_SUCCESS; 221 } 222 223 case HOST_CPU_LOAD_INFO: 224 dtape_stub_safe("HOST_CPU_LOAD_INFO"); 225 return KERN_INVALID_ARGUMENT; 226 227 default: 228 dtape_stub_unsafe(); 229 } 230 }; 231 232 kern_return_t vm_stats(void* info, unsigned int* count) { 233 vm_statistics64_t stat = (vm_statistics64_t)info; 234 235 if (*count < HOST_VM_INFO64_COUNT) 236 return (KERN_FAILURE); 237 238 memset(stat, 0, sizeof(*stat)); 239 240 dtape_stub("TODO: actually fill in the values with something useful"); 241 242 *count = HOST_VM_INFO64_COUNT; 243 244 return KERN_SUCCESS; 245 };