Changeset 58872 in vbox for trunk/src/VBox/HostDrivers/Support/linux
- Timestamp:
- Nov 26, 2015 2:17:48 AM (9 years ago)
- svn:sync-xref-src-repo-rev:
- 104358
- Location:
- trunk/src/VBox/HostDrivers/Support/linux
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/linux/Makefile
r57313 r58872 288 288 289 289 # build defs 290 EXTRA_CFLAGS += -include $(MANGLING) $(INCL) $(KFLAGS) $(KDEBUG) 290 EXTRA_CFLAGS += -include $(MANGLING) $(INCL) $(KFLAGS) $(KDEBUG) -fno-omit-frame-pointer 291 291 292 292 all: $(MODULE) -
trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c
r58340 r58872 65 65 # include <asm/msr.h> 66 66 #endif 67 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) && defined(CONFIG_DYNAMIC_FTRACE) 68 # include <linux/ftrace.h> 69 #endif 70 67 71 #include <iprt/asm-amd64-x86.h> 68 72 … … 940 944 941 945 942 void VBOXCALL supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)943 {944 NOREF(pDevExt); NOREF(pImage);945 }946 947 948 946 int VBOXCALL supdrvOSLdrValidatePointer(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, void *pv, const uint8_t *pbImageBits) 949 947 { … … 962 960 void VBOXCALL supdrvOSLdrUnload(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage) 963 961 { 962 NOREF(pDevExt); NOREF(pImage); 963 } 964 965 966 /** @def VBOX_WITH_NON_PROD_HACK_FOR_PERF_STACKS 967 * A very crude hack for debugging using perf and dtrace. 968 * 969 * DO ABSOLUTELY NOT ENABLE IN PRODUCTION BUILDS! DEVELOPMENT ONLY!! 970 * DO ABSOLUTELY NOT ENABLE IN PRODUCTION BUILDS! DEVELOPMENT ONLY!! 971 * DO ABSOLUTELY NOT ENABLE IN PRODUCTION BUILDS! DEVELOPMENT ONLY!! 972 * 973 */ 974 #if 0 || defined(DOXYGEN_RUNNING) 975 # define VBOX_WITH_NON_PROD_HACK_FOR_PERF_STACKS 976 #endif 977 978 #if defined(VBOX_WITH_NON_PROD_HACK_FOR_PERF_STACKS) && defined(CONFIG_MODULES_TREE_LOOKUP) 979 /** Whether g_pfnModTreeInsert and g_pfnModTreeRemove have been initialized. 980 * @remarks can still be NULL after init. */ 981 static volatile bool g_fLookedForModTreeFunctions = false; 982 static void (*g_pfnModTreeInsert)(struct mod_tree_node *) = NULL; /**< __mod_tree_insert */ 983 static void (*g_pfnModTreeRemove)(struct mod_tree_node *) = NULL; /**< __mod_tree_remove */ 984 #endif 985 986 #if 0 /* instant host lockup, can't be bothered debugging it */ 987 #if defined(VBOX_WITH_NON_PROD_HACK_FOR_PERF_STACKS) \ 988 && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) \ 989 && defined(CONFIG_MODULES_TREE_LOOKUP) \ 990 && defined(CONFIG_DYNAMIC_FTRACE) 991 992 /** 993 * Using a static array here because that's what is suggested in the docs to 994 * avoid/reduce potential race conditions. 995 */ 996 static struct supdrv_ftrace_ops 997 { 998 struct ftrace_ops Core; 999 bool volatile fUsed; 1000 } g_aFTraceOps[16] __read_mostly; 1001 1002 /** Stub function for the ugly debug hack below. */ 1003 static void notrace __attribute__((optimize("-fomit-frame-pointer"))) 1004 supdrvLnxFTraceStub(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *op, struct pt_regs *regs) 1005 { 1006 return; 1007 } 1008 1009 #endif 1010 #endif 1011 1012 1013 void VBOXCALL supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename) 1014 { 1015 #ifdef VBOX_WITH_NON_PROD_HACK_FOR_PERF_STACKS /* Not for production use!! Debugging only! */ 1016 /* 1017 * This trick stops working with 4.2 when CONFIG_MODULES_TREE_LOOKUP is 1018 * defined. The module lookups are done via a tree structure and we 1019 * cannot get at the root of it. :-( 1020 */ 1021 # ifdef CONFIG_KALLSYMS 1022 size_t const cchName = strlen(pImage->szName); 1023 # endif 1024 struct module *pMyMod, *pSelfMod, *pTestMod, *pTestModByName; 1025 IPRT_LINUX_SAVE_EFL_AC(); 1026 1027 pImage->pLnxModHack = NULL; 1028 pImage->pLnxFTraceHack = NULL; 1029 1030 # ifdef CONFIG_MODULES_TREE_LOOKUP 1031 /* 1032 * This is pretty naive, but works for 4.2 on arch linux. I don't think we 1033 * can count on finding __mod_tree_remove in all kernel builds as it's not 1034 * marked noinline like __mod_tree_insert. 1035 */ 1036 if (!g_fLookedForModTreeFunctions) 1037 { 1038 unsigned long ulInsert = kallsyms_lookup_name("__mod_tree_insert"); 1039 unsigned long ulRemove = kallsyms_lookup_name("__mod_tree_remove"); 1040 if (!ulInsert || !ulRemove) 1041 { 1042 g_fLookedForModTreeFunctions = true; 1043 printk(KERN_ERR "vboxdrv: failed to locate __mod_tree_insert and __mod_tree_remove.\n"); 1044 IPRT_LINUX_RESTORE_EFL_AC(); 1045 return; 1046 } 1047 *(unsigned long *)&g_pfnModTreeInsert = ulInsert; 1048 *(unsigned long *)&g_pfnModTreeRemove = ulRemove; 1049 ASMCompilerBarrier(); 1050 g_fLookedForModTreeFunctions = true; 1051 } 1052 else if (!g_pfnModTreeInsert || !g_pfnModTreeRemove) 1053 return; 1054 #endif 1055 1056 /* 1057 * Make sure we've found our own module, otherwise we cannot access the linked list. 1058 */ 1059 mutex_lock(&module_mutex); 1060 pSelfMod = find_module("vboxdrv"); 1061 mutex_unlock(&module_mutex); 1062 if (!pSelfMod) 1063 { 1064 IPRT_LINUX_RESTORE_EFL_AC(); 1065 return; 1066 } 1067 1068 /* 1069 * Cook up a module structure for the image. 1070 * We allocate symbol and string tables in the allocation and the module to keep things simple. 1071 */ 1072 # ifdef CONFIG_KALLSYMS 1073 pMyMod = (struct module *)RTMemAllocZ(sizeof(*pMyMod) 1074 + sizeof(Elf_Sym) * 3 1075 + 1 + cchName * 2 + sizeof("_start") + sizeof("_end") + 4 ); 1076 # else 1077 pMyMod = (struct module *)RTMemAllocZ(sizeof(*pMyMod)); 1078 # endif 1079 if (pMyMod) 1080 { 1081 int rc = VINF_SUCCESS; 1082 //size_t cch; 1083 # ifdef CONFIG_KALLSYMS 1084 Elf_Sym *paSymbols = (Elf_Sym *)(pMyMod + 1); 1085 char *pchStrTab = (char *)(paSymbols + 3); 1086 # endif 1087 1088 pMyMod->state = MODULE_STATE_LIVE; 1089 INIT_LIST_HEAD(&pMyMod->list); /* just in case */ 1090 1091 /* Come up with a good name that perf can translate with minimum help... */ 1092 # if 0 1093 cch = strlen(pszFilename); 1094 if (cch < sizeof(pMyMod->name)) 1095 memcpy(pMyMod->name, pszFilename, cch + 1); 1096 else 1097 { 1098 const char *pszTmp = pszFilename; 1099 for (;;) 1100 { 1101 /* skip one path component. */ 1102 while (*pszTmp == '/') 1103 pszTmp++, cch--; 1104 while (*pszTmp != '/' && *pszTmp != '\0') 1105 pszTmp++, cch--; 1106 1107 /* If we've skipped past the final component, hack something up based on the module name. */ 1108 if (*pszTmp != '/') 1109 { 1110 RTStrPrintf(pMyMod->name, sizeof(pMyMod->name), "/opt/VirtualBox/%s", pImage->szName); 1111 break; 1112 } 1113 /* When we've got space for two dots and the remaining path, we're done. */ 1114 if (cch + 2 < sizeof(pMyMod->name)) 1115 { 1116 pMyMod->name[0] = '.'; 1117 pMyMod->name[1] = '.'; 1118 memcpy(&pMyMod->name[2], pszTmp, cch + 1); 1119 break; 1120 } 1121 } 1122 } 1123 # else 1124 /* Perf only matches up files with a .ko extension (maybe .ko.gz), 1125 so in order for this crap to work smoothly, we append .ko to the 1126 module name and require the user to create symbolic links in 1127 /lib/modules/`uname -r`: 1128 for i in VMMR0.r0 VBoxDDR0.r0 VBoxDD2R0.r0; do 1129 sudo ln -s /mnt/scratch/vbox/svn/trunk/out/linux.amd64/debug/bin/$i /lib/modules/`uname -r`/$i.ko; 1130 done */ 1131 RTStrPrintf(pMyMod->name, sizeof(pMyMod->name), "%s", pImage->szName); 1132 # endif 1133 1134 /* sysfs bits. */ 1135 INIT_LIST_HEAD(&pMyMod->mkobj.kobj.entry); /* rest of kobj is already zeroed, hopefully never accessed... */ 1136 pMyMod->mkobj.mod = pMyMod; 1137 pMyMod->mkobj.drivers_dir = NULL; 1138 pMyMod->mkobj.mp = NULL; 1139 pMyMod->mkobj.kobj_completion = NULL; 1140 1141 pMyMod->modinfo_attrs = NULL; /* hopefully not accessed after setup. */ 1142 pMyMod->holders_dir = NULL; /* hopefully not accessed. */ 1143 pMyMod->version = "N/A"; 1144 pMyMod->srcversion = "N/A"; 1145 1146 /* We export no symbols. */ 1147 pMyMod->num_syms = 0; 1148 pMyMod->syms = NULL; 1149 pMyMod->crcs = NULL; 1150 1151 pMyMod->num_gpl_syms = 0; 1152 pMyMod->gpl_syms = NULL; 1153 pMyMod->gpl_crcs = NULL; 1154 1155 pMyMod->num_gpl_future_syms = 0; 1156 pMyMod->gpl_future_syms = NULL; 1157 pMyMod->gpl_future_crcs = NULL; 1158 1159 # if CONFIG_UNUSED_SYMBOLS 1160 pMyMod->num_unused_syms = 0; 1161 pMyMod->unused_syms = NULL; 1162 pMyMod->unused_crcs = NULL; 1163 1164 pMyMod->num_unused_gpl_syms = 0; 1165 pMyMod->unused_gpl_syms = NULL; 1166 pMyMod->unused_gpl_crcs = NULL; 1167 # endif 1168 /* No kernel parameters either. */ 1169 pMyMod->kp = NULL; 1170 pMyMod->num_kp = 0; 1171 1172 # ifdef CONFIG_MODULE_SIG 1173 /* Pretend ok signature. */ 1174 pMyMod->sig_ok = true; 1175 # endif 1176 /* No exception table. */ 1177 pMyMod->num_exentries = 0; 1178 pMyMod->extable = NULL; 1179 1180 /* No init function */ 1181 pMyMod->init = NULL; 1182 pMyMod->module_init = NULL; 1183 pMyMod->init_size = 0; 1184 pMyMod->init_ro_size = 0; 1185 pMyMod->init_text_size = 0; 1186 1187 /* The module address and size. It's all text. */ 1188 pMyMod->module_core = pImage->pvImage; 1189 pMyMod->core_size = pImage->cbImageBits; 1190 pMyMod->core_text_size = pImage->cbImageBits; 1191 pMyMod->core_ro_size = pImage->cbImageBits; 1192 1193 #ifdef CONFIG_MODULES_TREE_LOOKUP 1194 /* Fill in the self pointers for the tree nodes. */ 1195 pMyMod->mtn_core.mod = pMyMod; 1196 pMyMod->mtn_init.mod = pMyMod; 1197 #endif 1198 /* They invented the tained bit for us, didn't they? */ 1199 pMyMod->taints = 1; 1200 1201 # ifdef CONFIG_GENERIC_BUGS 1202 /* No BUGs in our modules. */ 1203 pMyMod->num_bugs = 0; 1204 INIT_LIST_HEAD(&pMyMod->bug_list); 1205 pMyMod->bug_table = NULL; 1206 # endif 1207 1208 # ifdef CONFIG_KALLSYMS 1209 /* The core stuff is documented as only used when loading. So just zero them. */ 1210 pMyMod->core_num_syms = 0; 1211 pMyMod->core_symtab = NULL; 1212 pMyMod->core_strtab = NULL; 1213 1214 /* Construct a symbol table with start and end symbols. 1215 Note! We don't have our own symbol table at this point, image bit 1216 are not uploaded yet! */ 1217 pMyMod->num_symtab = 3; 1218 pMyMod->symtab = paSymbols; 1219 pMyMod->strtab = pchStrTab; 1220 RT_ZERO(paSymbols[0]); 1221 pchStrTab[0] = '\0'; 1222 paSymbols[1].st_name = 1; 1223 paSymbols[2].st_name = 2 + RTStrPrintf(&pchStrTab[paSymbols[1].st_name], cchName + sizeof("_start"), 1224 "%s_start", pImage->szName); 1225 RTStrPrintf(&pchStrTab[paSymbols[2].st_name], cchName + sizeof("_end"), "%s_end", pImage->szName); 1226 paSymbols[1].st_info = 't'; 1227 paSymbols[2].st_info = 'b'; 1228 paSymbols[1].st_other = 0; 1229 paSymbols[2].st_other = 0; 1230 paSymbols[1].st_shndx = 0; 1231 paSymbols[2].st_shndx = 0; 1232 paSymbols[1].st_value = (uintptr_t)pImage->pvImage; 1233 paSymbols[2].st_value = (uintptr_t)pImage->pvImage + pImage->cbImageBits - 1; 1234 paSymbols[1].st_size = pImage->cbImageBits - 1; 1235 paSymbols[2].st_size = 1; 1236 # endif 1237 /* No arguments, but seems its always non-NULL so put empty string there. */ 1238 pMyMod->args = ""; 1239 1240 # ifdef CONFIG_SMP 1241 /* No per CPU data. */ 1242 pMyMod->percpu = NULL; 1243 pMyMod->percpu_size = 0; 1244 # endif 1245 # ifdef CONFIG_TRACEPOINTS 1246 /* No tracepoints we like to share. */ 1247 pMyMod->num_tracepoints = 0; 1248 pMyMod->tracepoints_ptrs = NULL; 1249 #endif 1250 # ifdef HAVE_JUMP_LABEL 1251 /* No jump lable stuff either. */ 1252 pMyMod->jump_entries = NULL; 1253 pMyMod->num_jump_entries = 0; 1254 # endif 1255 # ifdef CONFIG_TRACING 1256 pMyMod->num_trace_bprintk_fmt = 0; 1257 pMyMod->trace_bprintk_fmt_start = NULL; 1258 # endif 1259 # ifdef CONFIG_EVENT_TRACING 1260 pMyMod->trace_events = NULL; 1261 pMyMod->num_trace_events = 0; 1262 # endif 1263 # ifdef CONFIG_FTRACE_MCOUNT_RECORD 1264 pMyMod->num_ftrace_callsites = 0; 1265 pMyMod->ftrace_callsites = NULL; 1266 # endif 1267 # ifdef CONFIG_MODULE_UNLOAD 1268 /* Dependency lists, not worth sharing */ 1269 INIT_LIST_HEAD(&pMyMod->source_list); 1270 INIT_LIST_HEAD(&pMyMod->target_list); 1271 1272 /* Nobody waiting and no exit function. */ 1273 # if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) 1274 pMyMod->waiter = NULL; 1275 # endif 1276 pMyMod->exit = NULL; 1277 1278 /* References, very important as we must not allow the module 1279 to be unloaded using rmmod. */ 1280 # if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) 1281 atomic_set(&pMyMod->refcnt, 42); 1282 # else 1283 pMyMod->refptr = alloc_percpu(struct module_ref); 1284 if (pMyMod->refptr) 1285 { 1286 int iCpu; 1287 for_each_possible_cpu(iCpu) 1288 { 1289 per_cpu_ptr(pMyMod->refptr, iCpu)->decs = 0; 1290 per_cpu_ptr(pMyMod->refptr, iCpu)->incs = 1; 1291 } 1292 } 1293 else 1294 rc = VERR_NO_MEMORY; 1295 # endif 1296 # endif 1297 # ifdef CONFIG_CONSTRUCTORS 1298 /* No constructors. */ 1299 pMyMod->ctors = NULL; 1300 pMyMod->num_ctors = 0; 1301 # endif 1302 if (RT_SUCCESS(rc)) 1303 { 1304 bool fIsModText; 1305 1306 /* 1307 * Add the module to the list. 1308 */ 1309 mutex_lock(&module_mutex); 1310 list_add_rcu(&pMyMod->list, &pSelfMod->list); 1311 pImage->pLnxModHack = pMyMod; 1312 # ifdef CONFIG_MODULES_TREE_LOOKUP 1313 g_pfnModTreeInsert(&pMyMod->mtn_core); /* __mod_tree_insert */ 1314 # endif 1315 mutex_unlock(&module_mutex); 1316 1317 #if 0 /* Horrible, non-working hack. Debug when __mod_tree_remove can't be found on a box we care about. */ 1318 # if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) && defined(CONFIG_MODULES_TREE_LOOKUP) 1319 # if defined(CONFIG_DYNAMIC_FTRACE) 1320 /* 1321 * Starting with 4.2 there's the module tree lookup which thwarts 1322 * the above module hack. So, we must install an additional hack 1323 * to get the job done. This relies on dynmaic ftrace trampolines 1324 * and is just as ugly as the above. Only for debugging!! 1325 */ 1326 uint32_t i = 0; 1327 while (i < RT_ELEMENTS(g_aFTraceOps) 1328 && ASMAtomicXchgBool(&g_aFTraceOps[i].fUsed, true) == true) 1329 i++; 1330 if (i < RT_ELEMENTS(g_aFTraceOps)) 1331 { 1332 struct supdrv_ftrace_ops *pOps = &g_aFTraceOps[i]; 1333 pOps->Core.func = supdrvLnxFTraceStub; 1334 pOps->Core.flags = /*FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_STUB |*/ FTRACE_OPS_FL_DYNAMIC; 1335 pOps->Core.trampoline = (uintptr_t)pImage->pvImage; 1336 pOps->Core.trampoline_size = (uintptr_t)pImage->cbImageBits; 1337 1338 rc = register_ftrace_function(&pOps->Core); 1339 if (rc == 0) 1340 pImage->pLnxFTraceHack = pOps; 1341 else 1342 printk(KERN_ERR "vboxdrv: register_ftrace_function failed: %d\n", rc); 1343 } 1344 # else 1345 # error "Sorry, without CONFIG_DYNAMIC_FTRACE currently not possible to get proper stack traces" 1346 # endif 1347 # endif 1348 #endif 1349 /* 1350 * Test it. 1351 */ 1352 mutex_lock(&module_mutex); 1353 pTestModByName = find_module(pMyMod->name); 1354 pTestMod = __module_address((uintptr_t)pImage->pvImage + pImage->cbImageBits / 4); 1355 fIsModText = __module_text_address((uintptr_t)pImage->pvImage + pImage->cbImageBits / 2); 1356 mutex_unlock(&module_mutex); 1357 if ( pTestMod == pMyMod 1358 && pTestModByName == pMyMod 1359 && fIsModText) 1360 printk(KERN_ERR "vboxdrv: fake module works for '%s' (%#lx to %#lx)\n", 1361 pMyMod->name, (unsigned long)paSymbols[1].st_value, (unsigned long)paSymbols[2].st_value); 1362 else 1363 printk(KERN_ERR "vboxdrv: failed to find fake module (pTestMod=%p, pTestModByName=%p, pMyMod=%p, fIsModText=%d)\n", 1364 pTestMod, pTestModByName, pMyMod, fIsModText); 1365 } 1366 else 1367 RTMemFree(pMyMod); 1368 } 1369 1370 IPRT_LINUX_RESTORE_EFL_AC(); 1371 #else 1372 pImage->pLnxModHack = NULL; 1373 pImage->pLnxFTraceHack = NULL; 1374 #endif 1375 NOREF(pDevExt); NOREF(pImage); 1376 } 1377 1378 1379 void VBOXCALL supdrvOSLdrNotifyUnloaded(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage) 1380 { 1381 #ifdef VBOX_WITH_NON_PROD_HACK_FOR_PERF_STACKS /* Not for production use!! Debugging only! */ 1382 struct module *pMyMod = pImage->pLnxModHack; 1383 pImage->pLnxModHack = NULL; 1384 if (pMyMod) 1385 { 1386 /* 1387 * Remove the fake module list entry and free it. 1388 */ 1389 IPRT_LINUX_SAVE_EFL_AC(); 1390 mutex_lock(&module_mutex); 1391 list_del_rcu(&pMyMod->list); 1392 # ifdef CONFIG_MODULES_TREE_LOOKUP 1393 g_pfnModTreeRemove(&pMyMod->mtn_core); 1394 # endif 1395 synchronize_sched(); 1396 mutex_unlock(&module_mutex); 1397 1398 # if LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) 1399 free_percpu(pMyMod->refptr); 1400 # endif 1401 RTMemFree(pMyMod); 1402 IPRT_LINUX_RESTORE_EFL_AC(); 1403 } 1404 1405 #if 0 /* Butt-ugly and ain't working yet. */ 1406 # if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) && defined(CONFIG_MODULES_TREE_LOOKUP) 1407 # if defined(CONFIG_DYNAMIC_FTRACE) 1408 { 1409 /* 1410 * Undo the ftrace hack. 1411 */ 1412 struct supdrv_ftrace_ops *pOps = pImage->pLnxFTraceHack; 1413 pImage->pLnxFTraceHack = NULL; 1414 if (pOps) 1415 { 1416 IPRT_LINUX_SAVE_EFL_AC(); 1417 int rc = unregister_ftrace_function(&pOps->Core); 1418 if (rc == 0) 1419 ASMAtomicWriteBool(&pOps->fUsed, false); 1420 else 1421 printk(KERN_ERR "vboxdrv: unregister_ftrace_function failed: %d\n", rc); 1422 IPRT_LINUX_RESTORE_EFL_AC(); 1423 } 1424 } 1425 # else 1426 # error "Sorry, without CONFIG_DYNAMIC_FTRACE currently not possible to get proper stack traces" 1427 # endif 1428 # endif 1429 #endif 1430 1431 #else 1432 Assert(pImage->pLnxModHack == NULL); 1433 #endif 964 1434 NOREF(pDevExt); NOREF(pImage); 965 1435 }
Note:
See TracChangeset
for help on using the changeset viewer.