FreeBSD/sys/x86/x86/mp_x86.c
/*
 * Determine topology of processing units and caches for AMD CPUs.
 * See:
 *  - AMD CPUID Specification (Publication # 25481)
 *  - BKDG For AMD Family 10h Processors (Publication # 31116), section 2.15
 *  - BKDG for AMD NPT Family 0Fh Processors (Publication # 32559)
 * XXX At the moment the code does not recognize grouping of AMD CMT threads,
 * if supported, into cores, so each thread is treated as being in its own
 * core.  In other words, each logical CPU is considered to be a core.
 */
Determine topology of processing units and caches for AMD CPUs.
See:
- AMD CPUID Specification (Publication # 25481)
- BKDG For AMD Family 10h Processors (Publication # 31116), section 2.15
- BKDG for AMD NPT Family 0Fh Processors (Publication # 32559)
XXX At the moment the code does not recognize grouping of AMD CMT threads,
if supported, into cores, so each thread is treated as being in its own
core.  In other words, each logical CPU is considered to be a core.
Determine topology of processing units and caches for AMD CPUs . See : - AMD CPUID Specification ( Publication # 25481 ) - BKDG For AMD Family 10h Processors ( Publication # 31116 ) section 2 . 15 - BKDG for AMD NPT Family 0Fh Processors ( Publication # 32559 ) XXX At the moment the code does not recognize grouping of AMD CMT threads if supported into cores so each thread is treated as being in its own core . In other words each logical CPU is considered to be a core .
static void
topo_probe_amd(void)
{
	u_int p[4];
	int level;
	int share_count;
	int type;
	int i;
	if ((amd_feature2 & AMDID2_CMP) == 0)
		return;
	pkg_id_shift = (cpu_procinfo2 & AMDID_COREID_SIZE) >>
	    AMDID_COREID_SIZE_SHIFT;
	if (pkg_id_shift == 0)
		pkg_id_shift =
		    mask_width((cpu_procinfo2 & AMDID_CMP_CORES) + 1);
	if ((amd_feature2 & AMDID2_TOPOLOGY) != 0) {
		for (i = 0; ; i++) {
			cpuid_count(0x8000001d, i, p);
			type = p[0] & 0x1f;
			level = (p[0] >> 5) & 0x7;
			share_count = 1 + ((p[0] >> 14) & 0xfff);
			if (!add_deterministic_cache(type, level, share_count))
				break;
		}
	} else {
		if (cpu_exthigh >= 0x80000005) {
			cpuid_count(0x80000005, 0, p);
			if (((p[2] >> 24) & 0xff) != 0) {
				caches[0].id_shift = 0;
				caches[0].present = 1;
			}
		}
		if (cpu_exthigh >= 0x80000006) {
			cpuid_count(0x80000006, 0, p);
			if (((p[2] >> 16) & 0xffff) != 0) {
				caches[1].id_shift = 0;
				caches[1].present = 1;
			}
			if (((p[3] >> 18) & 0x3fff) != 0) {
				caches[2].id_shift = pkg_id_shift;
				caches[2].present = 1;
			}
		}
	}
}
static void topo_probe_amd ( void ) { u_int p [ 4 ] ; int level ; int share_count ; int type ; int i ; if ( ( amd_feature2 & AMDID2_CMP ) == 0 ) return ; pkg_id_shift = ( cpu_procinfo2 & AMDID_COREID_SIZE ) >> AMDID_COREID_SIZE_SHIFT ; if ( pkg_id_shift == 0 ) pkg_id_shift = mask_width ( ( cpu_procinfo2 & AMDID_CMP_CORES ) + 1 ) ; if ( ( amd_feature2 & AMDID2_TOPOLOGY ) != 0 ) { for ( i = 0 ; ; i ++ ) { cpuid_count ( 0x8000001d , i , p ) ; type = p [ 0 ] & 0x1f ; level = ( p [ 0 ] >> 5 ) & 0x7 ; share_count = 1 + ( ( p [ 0 ] >> 14 ) & 0xfff ) ; if ( ! add_deterministic_cache ( type , level , share_count ) ) break ; } } else { if ( cpu_exthigh >= 0x80000005 ) { cpuid_count ( 0x80000005 , 0 , p ) ; if ( ( ( p [ 2 ] >> 24 ) & 0xff ) != 0 ) { caches [ 0 ] . id_shift = 0 ; caches [ 0 ] . present = 1 ; } } if ( cpu_exthigh >= 0x80000006 ) { cpuid_count ( 0x80000006 , 0 , p ) ; if ( ( ( p [ 2 ] >> 16 ) & 0xffff ) != 0 ) { caches [ 1 ] . id_shift = 0 ; caches [ 1 ] . present = 1 ; } if ( ( ( p [ 3 ] >> 18 ) & 0x3fff ) != 0 ) { caches [ 2 ] . id_shift = pkg_id_shift ; caches [ 2 ] . present = 1 ; } } } }
Determine topology of processing units and caches for AMD CPUs.
Determine topology of processing units and caches for AMD CPUs .
/* No multi-core capability. */ /* For families 10h and newer. */ /* For 0Fh family. */ /*
				 * TODO: Account for dual-node processors
				 * where each node within a package has its own
				 * L3 cache.
				 */