Blob Blame History Raw
/*
 * Copyright (c) 2013, Intel Corporation
 * Copyright (c) 2017, IBM Corporation
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *   * Neither the name of Intel Corporation nor the names of its contributors
 *     may be used to endorse or promote products derived from this software
 *     without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <string.h>
#include "../common/include/os/plat.h"
#include "include/types.h"
#include "include/util.h"
#include "include/nhm.h"
#include "include/wsm.h"
#include "include/snb.h"
#include "include/bdw.h"
#include "include/skl.h"

pfn_plat_profiling_config_t
s_plat_profiling_config[CPU_TYPE_NUM] = {
	NULL,
	wsmex_profiling_config,
	snbep_profiling_config,
	nhmex_profiling_config,
	nhmep_profiling_config,
	wsmep_profiling_config,
	snbep_profiling_config,
	snbep_profiling_config,
	bdw_profiling_config,
	skl_profiling_config
};

pfn_plat_ll_config_t
s_plat_ll_config[CPU_TYPE_NUM] = {
	NULL,
	wsmex_ll_config,
	snbep_ll_config,
	nhmex_ll_config,
	nhmep_ll_config,
	wsmep_ll_config,
	snbep_ll_config,
	snbep_ll_config,
	bdw_ll_config,
	skl_ll_config
};

pfn_plat_offcore_num_t
s_plat_offcore_num[CPU_TYPE_NUM] = {
	NULL,
	wsm_offcore_num,
	snb_offcore_num,
	nhm_offcore_num,
	nhm_offcore_num,
	wsm_offcore_num,
	snb_offcore_num,
	snb_offcore_num,
	bdw_offcore_num,
	skl_offcore_num
};

/* ARGSUSED */
static void
cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx,
	unsigned int *edx)
{
#if __x86_64
	__asm volatile(
	    "cpuid\n\t"
	    :"=a" (*eax),
	    "=b" (*ebx),
	    "=c" (*ecx),
	    "=d" (*edx)
	    :"a" (*eax));
#else
	__asm volatile(
	    "push %%ebx\n\t"
	    "cpuid\n\t"
	    "mov %%ebx, (%4)\n\t"
	    "pop %%ebx"
	    :"=a" (*eax),
	    "=c" (*ecx),
	    "=d" (*edx)
	    :"0" (*eax),
	    "S" (ebx)
	    :"memory");
#endif
}

static cpu_type_t
cpu_type_get(void)
{
	unsigned int eax, ebx, ecx, edx;
	int family, model, ext_model;
	cpu_type_t type = CPU_UNSUP;
	char vendor[16];

	eax = 0;
	cpuid(&eax, &ebx, &ecx, &edx);

	(void) strncpy(&vendor[0], (char *)(&ebx), 4);
	(void) strncpy(&vendor[4], (char *)(&ecx), 4);
	(void) strncpy(&vendor[8], (char *)(&edx), 4);
	vendor[12] = 0;

	if (strncmp(vendor, "Genu" "ntel" "ineI", 12) != 0) {
		return (CPU_UNSUP);
	}

	eax = 1;
	cpuid(&eax, &ebx, &ecx, &edx);

	family = CPU_FAMILY(eax);
	model = CPU_MODEL(eax);
	ext_model = CPU_EXT_MODEL(eax);

	if (family == 6) {
		model = (ext_model << 4) + model;

		switch (model) {
		case 26:
			type = CPU_NHM_EP;
			break;
		case 44:
			type = CPU_WSM_EP;
			break;
		case 45:
			type = CPU_SNB_EP;
			break;
		case 46:
			type = CPU_NHM_EX;
			break;
		case 47:
			type = CPU_WSM_EX;
			break;
		case 62:
			type = CPU_IVB_EX;
			break;
		case 63:
			type = CPU_HSX;
			break;
		case 79:
			type = CPU_BDX;
			break;
		case 85:
			type = CPU_SKX;
			break;
		}
	}

	return (type);
}

/*
 * NumaTOP needs some special performance counters,
 * It can only run on WSM-EX/SNB-EP platforms now.
 */
int
plat_detect(void)
{
	int ret = -1;
	cpu_type_t cpu_type;

	if ((cpu_type = cpu_type_get()) == CPU_UNSUP) {
		return (-1);
	}

	switch (cpu_type) {
	case CPU_WSM_EX:
		/* fall through */
	case CPU_SNB_EP:
		/* fall through */
	case CPU_NHM_EX:
		/* fall through */
	case CPU_NHM_EP:
		/* fall through */
	case CPU_WSM_EP:
		/* fall through */
	case CPU_IVB_EX:
		/* fall through */
	case CPU_HSX:
		/* fall through */
	case CPU_BDX:
		/* fall through */
	case CPU_SKX:
		ret = 0;
		s_cpu_type = cpu_type;
		break;
	default:
		break;
	}

	return (ret);
}