qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio
at jcs-hda-dma 177 lines 4.6 kB view raw
1/* 2 * cacheinfo.c - helpers to query the host about its caches 3 * 4 * Copyright (C) 2017, Emilio G. Cota <cota@braap.org> 5 * License: GNU GPL, version 2 or later. 6 * See the COPYING file in the top-level directory. 7 */ 8 9#include "qemu/osdep.h" 10 11int qemu_icache_linesize = 0; 12int qemu_dcache_linesize = 0; 13 14/* 15 * Operating system specific detection mechanisms. 16 */ 17 18#if defined(_WIN32) 19 20static void sys_cache_info(int *isize, int *dsize) 21{ 22 SYSTEM_LOGICAL_PROCESSOR_INFORMATION *buf; 23 DWORD size = 0; 24 BOOL success; 25 size_t i, n; 26 27 /* Check for the required buffer size first. Note that if the zero 28 size we use for the probe results in success, then there is no 29 data available; fail in that case. */ 30 success = GetLogicalProcessorInformation(0, &size); 31 if (success || GetLastError() != ERROR_INSUFFICIENT_BUFFER) { 32 return; 33 } 34 35 n = size / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); 36 size = n * sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); 37 buf = g_new0(SYSTEM_LOGICAL_PROCESSOR_INFORMATION, n); 38 if (!GetLogicalProcessorInformation(buf, &size)) { 39 goto fail; 40 } 41 42 for (i = 0; i < n; i++) { 43 if (buf[i].Relationship == RelationCache 44 && buf[i].Cache.Level == 1) { 45 switch (buf[i].Cache.Type) { 46 case CacheUnified: 47 *isize = *dsize = buf[i].Cache.LineSize; 48 break; 49 case CacheInstruction: 50 *isize = buf[i].Cache.LineSize; 51 break; 52 case CacheData: 53 *dsize = buf[i].Cache.LineSize; 54 break; 55 default: 56 break; 57 } 58 } 59 } 60 fail: 61 g_free(buf); 62} 63 64#elif defined(__APPLE__) \ 65 || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) 66# include <sys/sysctl.h> 67# if defined(__APPLE__) 68# define SYSCTL_CACHELINE_NAME "hw.cachelinesize" 69# else 70# define SYSCTL_CACHELINE_NAME "machdep.cacheline_size" 71# endif 72 73static void sys_cache_info(int *isize, int *dsize) 74{ 75 /* There's only a single sysctl for both I/D cache line sizes. */ 76 long size; 77 size_t len = sizeof(size); 78 if (!sysctlbyname(SYSCTL_CACHELINE_NAME, &size, &len, NULL, 0)) { 79 *isize = *dsize = size; 80 } 81} 82 83#else 84/* POSIX */ 85 86static void sys_cache_info(int *isize, int *dsize) 87{ 88# ifdef _SC_LEVEL1_ICACHE_LINESIZE 89 *isize = sysconf(_SC_LEVEL1_ICACHE_LINESIZE); 90# endif 91# ifdef _SC_LEVEL1_DCACHE_LINESIZE 92 *dsize = sysconf(_SC_LEVEL1_DCACHE_LINESIZE); 93# endif 94} 95#endif /* sys_cache_info */ 96 97/* 98 * Architecture (+ OS) specific detection mechanisms. 99 */ 100 101#if defined(__aarch64__) 102 103static void arch_cache_info(int *isize, int *dsize) 104{ 105 if (*isize == 0 || *dsize == 0) { 106 unsigned long ctr; 107 108 /* The real cache geometry is in CCSIDR_EL1/CLIDR_EL1/CSSELR_EL1, 109 but (at least under Linux) these are marked protected by the 110 kernel. However, CTR_EL0 contains the minimum linesize in the 111 entire hierarchy, and is used by userspace cache flushing. */ 112 asm volatile("mrs\t%0, ctr_el0" : "=r"(ctr)); 113 if (*isize == 0) { 114 *isize = 4 << (ctr & 0xf); 115 } 116 if (*dsize == 0) { 117 *dsize = 4 << ((ctr >> 16) & 0xf); 118 } 119 } 120} 121 122#elif defined(_ARCH_PPC) && defined(__linux__) 123# include "elf.h" 124 125static void arch_cache_info(int *isize, int *dsize) 126{ 127 if (*isize == 0) { 128 *isize = qemu_getauxval(AT_ICACHEBSIZE); 129 } 130 if (*dsize == 0) { 131 *dsize = qemu_getauxval(AT_DCACHEBSIZE); 132 } 133} 134 135#else 136static void arch_cache_info(int *isize, int *dsize) { } 137#endif /* arch_cache_info */ 138 139/* 140 * ... and if all else fails ... 141 */ 142 143static void fallback_cache_info(int *isize, int *dsize) 144{ 145 /* If we can only find one of the two, assume they're the same. */ 146 if (*isize) { 147 if (*dsize) { 148 /* Success! */ 149 } else { 150 *dsize = *isize; 151 } 152 } else if (*dsize) { 153 *isize = *dsize; 154 } else { 155#if defined(_ARCH_PPC) 156 /* For PPC, we're going to use the icache size computed for 157 flush_icache_range. Which means that we must use the 158 architecture minimum. */ 159 *isize = *dsize = 16; 160#else 161 /* Otherwise, 64 bytes is not uncommon. */ 162 *isize = *dsize = 64; 163#endif 164 } 165} 166 167static void __attribute__((constructor)) init_cache_info(void) 168{ 169 int isize = 0, dsize = 0; 170 171 sys_cache_info(&isize, &dsize); 172 arch_cache_info(&isize, &dsize); 173 fallback_cache_info(&isize, &dsize); 174 175 qemu_icache_linesize = isize; 176 qemu_dcache_linesize = dsize; 177}