Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate Processor Detection from OpenJ9 to OMR part 1 #4662

Merged
merged 1 commit into from
Dec 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions fvtest/porttest/si.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2343,3 +2343,34 @@ TEST(PortSysinfoTest, sysinfo_cgroup_get_memlimit)
reportTestExit(OMRPORTLIB, testName);
return;
}

/**
* Test GetProcessorDescription.
*/
TEST(PortSysinfoTest, GetProcessorDescription)
{
OMRPORT_ACCESS_FROM_OMRPORT(portTestEnv->getPortLibrary());
OMRProcessorDesc desc;

ASSERT_NE(omrsysinfo_get_processor_description(&desc), -1);

#if defined(J9X86) || defined(J9HAMMER)
ASSERT_GE(desc.processor, OMR_PROCESSOR_X86_UNKNOWN);
ASSERT_GE(desc.physicalProcessor, OMR_PROCESSOR_X86_UNKNOWN);
#elif defined(AIXPPC) || defined(LINUXPPC)
ASSERT_GE(desc.processor, OMR_PROCESSOR_PPC_UNKNOWN);
ASSERT_LT(desc.processor, OMR_PROCESSOR_X86_UNKNOWN);
ASSERT_GE(desc.physicalProcessor, OMR_PROCESSOR_PPC_UNKNOWN);
ASSERT_LT(desc.physicalProcessor, OMR_PROCESSOR_X86_UNKNOWN);
#elif defined(S390) || defined(J9ZOS390)
ASSERT_GE(desc.processor, OMR_PROCESSOR_S390_UNKNOWN);
ASSERT_LT(desc.processor, OMR_PROCESSOR_PPC_UNKNOWN);
ASSERT_GE(desc.physicalProcessor, OMR_PROCESSOR_S390_UNKNOWN);
ASSERT_LT(desc.physicalProcessor, OMR_PROCESSOR_PPC_UNKNOWN);
#endif

for (int i = 0; i < OMRPORT_SYSINFO_FEATURES_SIZE * 32; i++) {
BOOLEAN feature = omrsysinfo_processor_has_feature(&desc, i);
ASSERT_TRUE(feature == TRUE || feature == FALSE);
}
}
314 changes: 314 additions & 0 deletions include_core/omrport.h

Large diffs are not rendered by default.

4 changes: 1 addition & 3 deletions port/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,7 @@ list(APPEND OBJECTS
omrsysinfo.c
)

if(OMR_HOST_OS STREQUAL zos)
list(APPEND OBJECTS omrsysinfo_helpers.c)
endif()
list(APPEND OBJECTS omrsysinfo_helpers.c)

list(APPEND OBJECTS omrsyslog.c)

Expand Down
2 changes: 2 additions & 0 deletions port/common/omrport.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ static OMRPortLibrary MasterPortLibraryTable = {
omrsysinfo_get_OS_version, /* sysinfo_get_OS_version */
omrsysinfo_get_env, /* sysinfo_get_env */
omrsysinfo_get_CPU_architecture, /* sysinfo_get_CPU_architecture */
omrsysinfo_get_processor_description, /* omrsysinfo_get_processor_description */
omrsysinfo_processor_has_feature, /* omrsysinfo_processor_has_feature */
omrsysinfo_get_OS_type, /* sysinfo_get_OS_type */
omrsysinfo_get_executable_name, /* sysinfo_get_executable_name */
omrsysinfo_get_username, /* sysinfo_get_username */
Expand Down
6 changes: 6 additions & 0 deletions port/common/omrport.tdf
Original file line number Diff line number Diff line change
Expand Up @@ -1101,3 +1101,9 @@ TraceException=Trc_PRT_vmem_omrvmem_findAvailableMemoryBlockNoMalloc_parseFirstA
TraceException=Trc_PRT_vmem_omrvmem_findAvailableMemoryBlockNoMalloc_parseDashFailed Group=mem Overhead=1 Level=5 NoEnv Template="findAvailableMemoryBlockNoMalloc parser failed to get dash from line (%s)"
TraceException=Trc_PRT_vmem_omrvmem_findAvailableMemoryBlockNoMalloc_parseSecondAddressFailed Group=mem Overhead=1 Level=5 NoEnv Template="findAvailableMemoryBlockNoMalloc parser failed to get second address from line (%s)"
TraceException=Trc_PRT_vmem_omrvmem_findAvailableMemoryBlockNoMalloc_addressesMismatch Group=mem Overhead=1 Level=5 NoEnv Template="findAvailableMemoryBlockNoMalloc parser found addresses mismatch from line (%s)"

TraceEntry=Trc_PRT_sysinfo_get_processor_description_Entered Group=j9sysinfo Overhead=1 Level=5 NoEnv Template="sysinfo_get_processor_description: desc = %p"
TraceExit=Trc_PRT_sysinfo_get_processor_description_Exit Group=j9sysinfo Overhead=1 Level=5 NoEnv Template="sysinfo_get_processor_description: returning with %zd"

TraceEntry=Trc_PRT_sysinfo_processor_has_feature_Entered Group=sysinfo Overhead=1 Level=5 NoEnv Template="sysinfo_processor_has_feature: desc = %p, feature = %d"
TraceExit=Trc_PRT_sysinfo_processor_has_feature_Exit Group=sysinfo Overhead=1 Level=5 NoEnv Template="sysinfo_processor_has_feature: returning with %zu."
36 changes: 36 additions & 0 deletions port/common/omrsysinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,42 @@ omrsysinfo_get_CPU_architecture(struct OMRPortLibrary *portLibrary)
return "unknown";
#endif
}

/**
* Determine CPU type and features.
*
* @param[in] portLibrary The port library.
* @param[out] desc pointer to the struct that will contain the CPU type and features.
* - desc will still be initialized if there is a failure.
*
* @return 0 on success, -1 on failure
*/
intptr_t
omrsysinfo_get_processor_description(struct OMRPortLibrary *portLibrary, OMRProcessorDesc *desc)
{
Trc_PRT_sysinfo_get_processor_description_Entered(desc);
intptr_t rc = OMRPORT_ERROR_NOT_SUPPORTED_ON_THIS_PLATFORM;
Trc_PRT_sysinfo_get_processor_description_Exit(rc);
return rc;
}

/**
* Determine if a CPU feature is present.
*
* @param[in] portLibrary The port library.
* @param[in] desc The struct that will contain the CPU type and features.
* @param[in] feature The feature to check (see j9port.h for list of features J9PORT_{PPC,S390,PPC}_FEATURE_*)
*
* @return TRUE if feature is present, FALSE otherwise.
*/
BOOLEAN
omrsysinfo_processor_has_feature(struct OMRPortLibrary *portLibrary, OMRProcessorDesc *desc, uint32_t feature)
{
Trc_PRT_sysinfo_processor_has_feature_Entered(desc, feature);
BOOLEAN rc = FALSE;
Trc_PRT_sysinfo_processor_has_feature_Exit((uintptr_t)rc);
return rc;
}
/**
* Query the operating system for environment variables.
*
Expand Down
214 changes: 214 additions & 0 deletions port/common/omrsysinfo_helpers.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
/*******************************************************************************
* Copyright (c) 2019, 2019 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
* or the Apache License, Version 2.0 which accompanies this distribution and
* is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* This Source Code may also be made available under the following
* Secondary Licenses when the conditions for such availability set
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
* General Public License, version 2 with the GNU Classpath
* Exception [1] and GNU General Public License, version 2 with the
* OpenJDK Assembly Exception [2].
*
* [1] https://www.gnu.org/software/classpath/license.html
* [2] http://openjdk.java.net/legal/assembly-exception.html
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
*******************************************************************************/
/**
* @file
* @ingroup Port
* @brief System information
*/

#include "omrsysinfo_helpers.h"

#include "omrport.h"
#include "omrporterror.h"
#include "portnls.h"

#include <string.h>
#if defined(WIN32)
#include <intrin.h>
#endif /* defined(WIN32) */

/* defines for the CPUID instruction */
#define CPUID_VENDOR_INFO 0
#define CPUID_FAMILY_INFO 1

#define CPUID_VENDOR_INTEL "GenuineIntel"
#define CPUID_VENDOR_AMD "AuthenticAMD"
#define CPUID_VENDOR_LENGTH 12

#define CPUID_SIGNATURE_FAMILY 0x00000F00
#define CPUID_SIGNATURE_MODEL 0x000000F0
#define CPUID_SIGNATURE_EXTENDEDMODEL 0x000F0000

#define CPUID_SIGNATURE_FAMILY_SHIFT 8
#define CPUID_SIGNATURE_MODEL_SHIFT 4
#define CPUID_SIGNATURE_EXTENDEDMODEL_SHIFT 12

#define CPUID_FAMILYCODE_INTELPENTIUM 0x05
#define CPUID_FAMILYCODE_INTELCORE 0x06
#define CPUID_FAMILYCODE_INTELPENTIUM4 0x0F

#define CPUID_MODELCODE_INTELHASWELL 0x3A
#define CPUID_MODELCODE_SANDYBRIDGE 0x2A
#define CPUID_MODELCODE_INTELWESTMERE 0x25
#define CPUID_MODELCODE_INTELNEHALEM 0x1E
#define CPUID_MODELCODE_INTELCORE2 0x0F

#define CPUID_FAMILYCODE_AMDKSERIES 0x05
#define CPUID_FAMILYCODE_AMDATHLON 0x06
#define CPUID_FAMILYCODE_AMDOPTERON 0x0F

#define CPUID_MODELCODE_AMDK5 0x04

static void omrsysinfo_get_x86_cpuid(uint32_t leaf, uint32_t *cpuInfo);

/**
* @internal
* Populates OMRProcessorDesc *desc on Windows and Linux (x86)
*
* @param[in] desc pointer to the struct that will contain the CPU type and features.
*
* @return 0 on success, -1 on failure
*/
intptr_t
omrsysinfo_get_x86_description(struct OMRPortLibrary *portLibrary, OMRProcessorDesc *desc)
{
uint32_t CPUInfo[4] = {0};
char vendor[12];
uint32_t familyCode = 0;
uint32_t processorSignature = 0;

desc->processor = OMR_PROCESSOR_X86_UNKNOWN;

/* vendor */
omrsysinfo_get_x86_cpuid(CPUID_VENDOR_INFO, CPUInfo);
memcpy(vendor + 0, &CPUInfo[1], sizeof(uint32_t));
memcpy(vendor + 4, &CPUInfo[3], sizeof(uint32_t));
memcpy(vendor + 8, &CPUInfo[2], sizeof(uint32_t));

/* family and model */
omrsysinfo_get_x86_cpuid(CPUID_FAMILY_INFO, CPUInfo);
processorSignature = CPUInfo[0];
familyCode = (processorSignature & CPUID_SIGNATURE_FAMILY) >> CPUID_SIGNATURE_FAMILY_SHIFT;
if (0 == strncmp(vendor, CPUID_VENDOR_INTEL, CPUID_VENDOR_LENGTH)) {
switch (familyCode) {
case CPUID_FAMILYCODE_INTELPENTIUM:
desc->processor = OMR_PROCESSOR_X86_INTELPENTIUM;
break;
case CPUID_FAMILYCODE_INTELCORE:
{
uint32_t modelCode = (processorSignature & CPUID_SIGNATURE_MODEL) >> CPUID_SIGNATURE_MODEL_SHIFT;
uint32_t extendedModelCode = (processorSignature & CPUID_SIGNATURE_EXTENDEDMODEL) >> CPUID_SIGNATURE_EXTENDEDMODEL_SHIFT;
uint32_t totalModelCode = modelCode + extendedModelCode;

if (totalModelCode > CPUID_MODELCODE_INTELHASWELL) {
desc->processor = OMR_PROCESSOR_X86_INTELHASWELL;
} else if (totalModelCode >= CPUID_MODELCODE_SANDYBRIDGE) {
desc->processor = OMR_PROCESSOR_X86_INTELSANDYBRIDGE;
} else if (totalModelCode >= CPUID_MODELCODE_INTELWESTMERE) {
desc->processor = OMR_PROCESSOR_X86_INTELWESTMERE;
} else if (totalModelCode >= CPUID_MODELCODE_INTELNEHALEM) {
desc->processor = OMR_PROCESSOR_X86_INTELNEHALEM;
} else if (totalModelCode == CPUID_MODELCODE_INTELCORE2) {
desc->processor = OMR_PROCESSOR_X86_INTELCORE2;
} else {
desc->processor = OMR_PROCESSOR_X86_INTELP6;
}
break;
}
case CPUID_FAMILYCODE_INTELPENTIUM4:
desc->processor = OMR_PROCESSOR_X86_INTELPENTIUM4;
break;
}
} else if (0 == strncmp(vendor, CPUID_VENDOR_AMD, CPUID_VENDOR_LENGTH)) {
switch (familyCode) {
case CPUID_FAMILYCODE_AMDKSERIES:
{
uint32_t modelCode = (processorSignature & CPUID_SIGNATURE_FAMILY) >> CPUID_SIGNATURE_MODEL_SHIFT;
if (modelCode < CPUID_MODELCODE_AMDK5) {
desc->processor = OMR_PROCESSOR_X86_AMDK5;
}
desc->processor = OMR_PROCESSOR_X86_AMDK6;
break;
}
case CPUID_FAMILYCODE_AMDATHLON:
desc->processor = OMR_PROCESSOR_X86_AMDATHLONDURON;
break;
case CPUID_FAMILYCODE_AMDOPTERON:
desc->processor = OMR_PROCESSOR_X86_AMDOPTERON;
break;
}
}

desc->physicalProcessor = desc->processor;

/* features */
desc->features[0] = CPUInfo[3];
desc->features[1] = CPUInfo[2];
desc->features[2] = 0; /* reserved for future expansion */

return 0;
}

/**
* Assembly code to get the register data from CPUID instruction
* This function executes the CPUID instruction based on which we can detect
* if the environment is virtualized or not, and also get the Hypervisor Vendor
* Name based on the same instruction. The leaf value specifies what information
* to return.
*
* @param[in] leaf The leaf value to the CPUID instruction.
* @param[out] cpuInfo Reference to the an integer array which holds the data
* of EAX,EBX,ECX and EDX registers.
* cpuInfo[0] To hold the EAX register data, value in this register at
* the time of CPUID tells what information to return
* EAX=0x1,returns the processor Info and feature bits
* in EBX,ECX,EDX registers.
* EAX=0x40000000 returns the Hypervisor Vendor Names
* in the EBX,ECX,EDX registers.
* cpuInfo[1] For EAX = 0x40000000 hold first 4 characters of the
* Hypervisor Vendor String
* cpuInfo[2] For EAX = 0x1, the 31st bit of ECX tells if its
* running on Hypervisor or not,For EAX = 0x40000000 holds the second
* 4 characters of the the Hypervisor Vendor String
* cpuInfo[3] For EAX = 0x40000000 hold the last 4 characters of the
* Hypervisor Vendor String
*
*/

static void
omrsysinfo_get_x86_cpuid(uint32_t leaf, uint32_t *cpuInfo)
{
cpuInfo[0] = leaf;

/* Implemented for x86 & x86_64 bit platforms */
#if defined(WIN32)
/* Specific CPUID instruction available in Windows */
__cpuid(cpuInfo, cpuInfo[0]);

#elif defined(LINUX) || defined(OSX)
#if defined(J9X86)
__asm volatile
("mov %%ebx, %%edi;"
"cpuid;"
"mov %%ebx, %%esi;"
"mov %%edi, %%ebx;"
:"+a" (cpuInfo[0]), "=S" (cpuInfo[1]), "=c" (cpuInfo[2]), "=d" (cpuInfo[3])
: :"edi");

#elif defined(J9HAMMER)
__asm volatile(
"cpuid;"
:"+a" (cpuInfo[0]), "=b" (cpuInfo[1]), "=c" (cpuInfo[2]), "=d" (cpuInfo[3])
);
#endif
#endif
}
36 changes: 36 additions & 0 deletions port/common/omrsysinfo_helpers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*******************************************************************************
* Copyright (c) 2019, 2019 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
* or the Apache License, Version 2.0 which accompanies this distribution and
* is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* This Source Code may also be made available under the following
* Secondary Licenses when the conditions for such availability set
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
* General Public License, version 2 with the GNU Classpath
* Exception [1] and GNU General Public License, version 2 with the
* OpenJDK Assembly Exception [2].
*
* [1] https://www.gnu.org/software/classpath/license.html
* [2] http://openjdk.java.net/legal/assembly-exception.html
*
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
*******************************************************************************/
/**
* @file
* @ingroup Port
* @brief System information
*/

#ifndef SYSINFOHELPERS_H_
#define SYSINFOHELPERS_H_

#include "omrport.h"

extern intptr_t
omrsysinfo_get_x86_description(struct OMRPortLibrary *portLibrary, OMRProcessorDesc *desc);

#endif /* SYSINFOHELPERS_H_ */
Loading