Files
CoreFreq/x86_64/corefreqd.c

10096 lines
278 KiB
C

/*
* CoreFreq
* Copyright (C) 2015-2025 CYRIL COURTIAT
* Licenses: GPL2
*/
#define _GNU_SOURCE
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/sysinfo.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <stdio.h>
#include <signal.h>
#include <stdarg.h>
#include <errno.h>
#include <pthread.h>
#ifndef __USE_GNU
#include <libgen.h>
#endif
#include "bitasm.h"
#include "amd_reg.h"
#include "intel_reg.h"
#include "coretypes.h"
#include "corefreq.h"
#include "corefreqm.h"
#include "corefreq-api.h"
#define AT( _loc_ ) [ _loc_ ]
#define PAGE_SIZE \
( \
sysconf(_SC_PAGESIZE) > 0 ? sysconf(_SC_PAGESIZE) : 4096 \
)
/*Ch:8.10.6.7 Place Locks and Semaphores in Aligned, 128-Byte Blocks of Memory*/
static BitCC roomSeed __attribute__ ((aligned (16))) = InitCC(0x0);
static BitCC roomCore __attribute__ ((aligned (16))) = InitCC(0x0);
static BitCC roomClear __attribute__ ((aligned (16))) = InitCC(0x0);
static BitCC roomReady __attribute__ ((aligned (16))) = InitCC(0x0);
static Bit64 Shutdown __attribute__ ((aligned (8))) = 0x0;
static Bit64 PendingSync __attribute__ ((aligned (8))) = 0x0;
unsigned int Quiet = 0x001, SysGateStartUp = 1;
UBENCH_DECLARE()
typedef struct
{
int drv,
ro,
rw;
} FD;
typedef struct {
sigset_t Signal;
pid_t CPID;
pthread_t KID;
int Started;
struct {
SLICE_FUNC Func;
unsigned long arg;
enum PATTERN pattern;
} Slice;
FD *fd;
RO(SHM_STRUCT) *RO(Shm);
RW(SHM_STRUCT) *RW(Shm);
RO(PROC) *RO(Proc);
RW(PROC) *RW(Proc);
RO(CORE) **RO(Core);
RW(CORE) **RW(Core);
RO(SYSGATE) *RO(SysGate);
} REF;
void Core_ResetSensorLimits(CPU_STRUCT *Cpu)
{
RESET_SENSOR_LIMIT(THERMAL, LOWEST, Cpu->PowerThermal.Limit);
RESET_SENSOR_LIMIT(VOLTAGE, LOWEST, Cpu->Sensors.Voltage.Limit);
RESET_SENSOR_LIMIT(ENERGY, LOWEST, Cpu->Sensors.Energy.Limit);
RESET_SENSOR_LIMIT(POWER, LOWEST, Cpu->Sensors.Power.Limit);
RESET_SENSOR_LIMIT(REL_FREQ, LOWEST, Cpu->Relative.Freq);
RESET_SENSOR_LIMIT(ABS_FREQ, LOWEST, Cpu->Absolute.Freq);
RESET_SENSOR_LIMIT(THERMAL, HIGHEST, Cpu->PowerThermal.Limit);
RESET_SENSOR_LIMIT(VOLTAGE, HIGHEST, Cpu->Sensors.Voltage.Limit);
RESET_SENSOR_LIMIT(ENERGY, HIGHEST, Cpu->Sensors.Energy.Limit);
RESET_SENSOR_LIMIT(POWER, HIGHEST, Cpu->Sensors.Power.Limit);
RESET_SENSOR_LIMIT(REL_FREQ, HIGHEST, Cpu->Relative.Freq);
RESET_SENSOR_LIMIT(ABS_FREQ, HIGHEST, Cpu->Absolute.Freq);
}
void Core_ComputeThermalLimits(CPU_STRUCT *Cpu, struct FLIP_FLOP *CFlip)
{ /* Per Core, computes the Min temperature. */
TEST_AND_SET_SENSOR( THERMAL, LOWEST, CFlip->Thermal.Temp,
Cpu->PowerThermal.Limit );
/* Per Core, computes the Max temperature. */
TEST_AND_SET_SENSOR( THERMAL, HIGHEST, CFlip->Thermal.Temp,
Cpu->PowerThermal.Limit );
}
static void ComputeThermal_None( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
UNUSED(RO(Shm));
UNUSED(cpu);
CFlip->Thermal.Temp = 0;
}
#define ComputeThermal_None_PerSMT ComputeThermal_None
#define ComputeThermal_None_PerCore ComputeThermal_None
#define ComputeThermal_None_PerPkg ComputeThermal_None
static void (*ComputeThermal_None_Matrix[4])( struct FLIP_FLOP*,
RO(SHM_STRUCT)*,
unsigned int ) = \
{
[FORMULA_SCOPE_NONE] = ComputeThermal_None,
[FORMULA_SCOPE_SMT ] = ComputeThermal_None_PerSMT,
[FORMULA_SCOPE_CORE] = ComputeThermal_None_PerCore,
[FORMULA_SCOPE_PKG ] = ComputeThermal_None_PerPkg
};
static void ComputeThermal_Intel( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
COMPUTE_THERMAL(INTEL,
CFlip->Thermal.Temp,
CFlip->Thermal.Param,
CFlip->Thermal.Sensor);
Core_ComputeThermalLimits(&RO(Shm)->Cpu[cpu], CFlip);
}
#define ComputeThermal_Intel_PerSMT ComputeThermal_Intel
static void ComputeThermal_Intel_PerCore( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if ((RO(Shm)->Cpu[cpu].Topology.ThreadID == 0)
|| (RO(Shm)->Cpu[cpu].Topology.ThreadID == -1))
{
ComputeThermal_Intel(CFlip, RO(Shm), cpu);
}
}
static void ComputeThermal_Intel_PerPkg( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if (cpu == RO(Shm)->Proc.Service.Core)
{
ComputeThermal_Intel(CFlip, RO(Shm), cpu);
}
}
static void (*ComputeThermal_Intel_Matrix[4])( struct FLIP_FLOP*,
RO(SHM_STRUCT)*,
unsigned int ) = \
{
[FORMULA_SCOPE_NONE] = ComputeThermal_None,
[FORMULA_SCOPE_SMT ] = ComputeThermal_Intel_PerSMT,
[FORMULA_SCOPE_CORE] = ComputeThermal_Intel_PerCore,
[FORMULA_SCOPE_PKG ] = ComputeThermal_Intel_PerPkg
};
static void ComputeThermal_AMD( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
COMPUTE_THERMAL(AMD,
CFlip->Thermal.Temp,
CFlip->Thermal.Param,
CFlip->Thermal.Sensor);
Core_ComputeThermalLimits(&RO(Shm)->Cpu[cpu], CFlip);
}
#define ComputeThermal_AMD_PerSMT ComputeThermal_AMD
static void ComputeThermal_AMD_PerCore( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if ((RO(Shm)->Cpu[cpu].Topology.ThreadID == 0)
|| (RO(Shm)->Cpu[cpu].Topology.ThreadID == -1))
{
ComputeThermal_AMD(CFlip, RO(Shm), cpu);
}
}
static void ComputeThermal_AMD_PerPkg( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if (cpu == RO(Shm)->Proc.Service.Core)
{
ComputeThermal_AMD(CFlip, RO(Shm), cpu);
}
}
static void (*ComputeThermal_AMD_Matrix[4])( struct FLIP_FLOP*,
RO(SHM_STRUCT)*,
unsigned int ) = \
{
[FORMULA_SCOPE_NONE] = ComputeThermal_None,
[FORMULA_SCOPE_SMT ] = ComputeThermal_AMD_PerSMT,
[FORMULA_SCOPE_CORE] = ComputeThermal_AMD_PerCore,
[FORMULA_SCOPE_PKG ] = ComputeThermal_AMD_PerPkg
};
static void ComputeThermal_AMD_0Fh( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
COMPUTE_THERMAL(AMD_0Fh,
CFlip->Thermal.Temp,
CFlip->Thermal.Param,
CFlip->Thermal.Sensor);
Core_ComputeThermalLimits(&RO(Shm)->Cpu[cpu], CFlip);
}
#define ComputeThermal_AMD_0Fh_PerSMT ComputeThermal_AMD_0Fh
static void ComputeThermal_AMD_0Fh_PerCore( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if ((RO(Shm)->Cpu[cpu].Topology.ThreadID == 0)
|| (RO(Shm)->Cpu[cpu].Topology.ThreadID == -1))
{
ComputeThermal_AMD_0Fh(CFlip, RO(Shm), cpu);
}
}
static void ComputeThermal_AMD_0Fh_PerPkg( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if (cpu == RO(Shm)->Proc.Service.Core)
{
ComputeThermal_AMD_0Fh(CFlip, RO(Shm), cpu);
}
}
static void (*ComputeThermal_AMD_0Fh_Matrix[4])( struct FLIP_FLOP*,
RO(SHM_STRUCT)*,
unsigned int ) = \
{
[FORMULA_SCOPE_NONE] = ComputeThermal_None,
[FORMULA_SCOPE_SMT ] = ComputeThermal_AMD_0Fh_PerSMT,
[FORMULA_SCOPE_CORE] = ComputeThermal_AMD_0Fh_PerCore,
[FORMULA_SCOPE_PKG ] = ComputeThermal_AMD_0Fh_PerPkg
};
static void ComputeThermal_AMD_15h( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if (RO(Shm)->Cpu[cpu].Topology.CoreID == 0)
{
COMPUTE_THERMAL(AMD_15h,
CFlip->Thermal.Temp,
CFlip->Thermal.Param,
CFlip->Thermal.Sensor);
Core_ComputeThermalLimits(&RO(Shm)->Cpu[cpu], CFlip);
}
}
#define ComputeThermal_AMD_15h_PerSMT ComputeThermal_AMD_15h
static void ComputeThermal_AMD_15h_PerCore( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if (RO(Shm)->Cpu[cpu].Topology.CoreID == 0) /* Opteron use case */
{
ComputeThermal_AMD_15h(CFlip, RO(Shm), cpu);
}
}
static void ComputeThermal_AMD_15h_PerPkg( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if (cpu == RO(Shm)->Proc.Service.Core)
{
ComputeThermal_AMD_15h(CFlip, RO(Shm), cpu);
}
}
static void (*ComputeThermal_AMD_15h_Matrix[4])( struct FLIP_FLOP*,
RO(SHM_STRUCT)*,
unsigned int) = \
{
[FORMULA_SCOPE_NONE] = ComputeThermal_None,
[FORMULA_SCOPE_SMT ] = ComputeThermal_AMD_15h_PerSMT,
[FORMULA_SCOPE_CORE] = ComputeThermal_AMD_15h_PerCore,
[FORMULA_SCOPE_PKG ] = ComputeThermal_AMD_15h_PerPkg
};
static void ComputeThermal_AMD_17h( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
COMPUTE_THERMAL(AMD_17h,
CFlip->Thermal.Temp,
CFlip->Thermal.Param,
CFlip->Thermal.Sensor);
Core_ComputeThermalLimits(&RO(Shm)->Cpu[cpu], CFlip);
}
#define ComputeThermal_AMD_17h_PerSMT ComputeThermal_AMD_17h
static void ComputeThermal_AMD_17h_PerCore( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if ((RO(Shm)->Cpu[cpu].Topology.ThreadID == 0)
|| (RO(Shm)->Cpu[cpu].Topology.ThreadID == -1))
{
ComputeThermal_AMD_17h(CFlip, RO(Shm), cpu);
}
}
static void ComputeThermal_AMD_17h_PerPkg( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if (cpu == RO(Shm)->Proc.Service.Core)
{
ComputeThermal_AMD_17h(CFlip, RO(Shm), cpu);
}
}
static void (*ComputeThermal_AMD_17h_Matrix[4])(struct FLIP_FLOP*,
RO(SHM_STRUCT)*,
unsigned int) = \
{
[FORMULA_SCOPE_NONE] = ComputeThermal_None,
[FORMULA_SCOPE_SMT ] = ComputeThermal_AMD_17h_PerSMT,
[FORMULA_SCOPE_CORE] = ComputeThermal_AMD_17h_PerCore,
[FORMULA_SCOPE_PKG ] = ComputeThermal_AMD_17h_PerPkg
};
void Core_ComputeVoltageLimits(CPU_STRUCT *Cpu, struct FLIP_FLOP *CFlip)
{ /* Per Core, computes the Min CPU voltage. */
TEST_AND_SET_SENSOR( VOLTAGE, LOWEST, CFlip->Voltage.Vcore,
Cpu->Sensors.Voltage.Limit );
/* Per Core, computes the Max CPU voltage. */
TEST_AND_SET_SENSOR( VOLTAGE, HIGHEST, CFlip->Voltage.Vcore,
Cpu->Sensors.Voltage.Limit );
}
static void ComputeVoltage_None( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
UNUSED(CFlip);
UNUSED(RO(Shm));
UNUSED(cpu);
}
#define ComputeVoltage_None_PerSMT ComputeVoltage_None
#define ComputeVoltage_None_PerCore ComputeVoltage_None
#define ComputeVoltage_None_PerPkg ComputeVoltage_None
static void (*ComputeVoltage_None_Matrix[4])( struct FLIP_FLOP*,
RO(SHM_STRUCT)*,
unsigned int ) = \
{
[FORMULA_SCOPE_NONE] = ComputeVoltage_None,
[FORMULA_SCOPE_SMT ] = ComputeVoltage_None_PerSMT,
[FORMULA_SCOPE_CORE] = ComputeVoltage_None_PerCore,
[FORMULA_SCOPE_PKG ] = ComputeVoltage_None_PerPkg
};
#define ComputeVoltage_Intel_Matrix ComputeVoltage_None_Matrix
static void ComputeVoltage_Intel_Core2( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{ /* Intel Core 2 Extreme Datasheet Chap. 3.3-Table 2 */
COMPUTE_VOLTAGE(INTEL_CORE2,
CFlip->Voltage.Vcore,
CFlip->Voltage.VID);
Core_ComputeVoltageLimits(&RO(Shm)->Cpu[cpu], CFlip);
}
#define ComputeVoltage_Intel_Core2_PerSMT ComputeVoltage_Intel_Core2
static void ComputeVoltage_Intel_Core2_PerCore( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if ((RO(Shm)->Cpu[cpu].Topology.ThreadID == 0)
|| (RO(Shm)->Cpu[cpu].Topology.ThreadID == -1))
{
ComputeVoltage_Intel_Core2(CFlip, RO(Shm), cpu);
}
}
static void ComputeVoltage_Intel_Core2_PerPkg( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if (cpu == RO(Shm)->Proc.Service.Core)
{
ComputeVoltage_Intel_Core2(CFlip, RO(Shm), cpu);
}
}
static void (*ComputeVoltage_Intel_Core2_Matrix[4])( struct FLIP_FLOP*,
RO(SHM_STRUCT)*,
unsigned int ) = \
{
[FORMULA_SCOPE_NONE] = ComputeVoltage_None,
[FORMULA_SCOPE_SMT ] = ComputeVoltage_Intel_Core2_PerSMT,
[FORMULA_SCOPE_CORE] = ComputeVoltage_Intel_Core2_PerCore,
[FORMULA_SCOPE_PKG ] = ComputeVoltage_Intel_Core2_PerPkg
};
static void ComputeVoltage_Intel_SoC( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{ /* Intel Valleyview-D/M SoC */
COMPUTE_VOLTAGE(INTEL_SOC,
CFlip->Voltage.Vcore,
CFlip->Voltage.VID);
Core_ComputeVoltageLimits(&RO(Shm)->Cpu[cpu], CFlip);
}
#define ComputeVoltage_Intel_SoC_PerSMT ComputeVoltage_Intel_SoC
static void ComputeVoltage_Intel_SoC_PerCore( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if ((RO(Shm)->Cpu[cpu].Topology.ThreadID == 0)
|| (RO(Shm)->Cpu[cpu].Topology.ThreadID == -1))
{
ComputeVoltage_Intel_SoC(CFlip, RO(Shm), cpu);
}
}
static void ComputeVoltage_Intel_SoC_PerPkg( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if (cpu == RO(Shm)->Proc.Service.Core)
{
ComputeVoltage_Intel_SoC(CFlip, RO(Shm), cpu);
}
}
static void (*ComputeVoltage_Intel_SoC_Matrix[4])( struct FLIP_FLOP*,
RO(SHM_STRUCT)*,
unsigned int ) = \
{
[FORMULA_SCOPE_NONE] = ComputeVoltage_None,
[FORMULA_SCOPE_SMT ] = ComputeVoltage_Intel_SoC_PerSMT,
[FORMULA_SCOPE_CORE] = ComputeVoltage_Intel_SoC_PerCore,
[FORMULA_SCOPE_PKG ] = ComputeVoltage_Intel_SoC_PerPkg
};
static void ComputeVoltage_Intel_SNB( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
COMPUTE_VOLTAGE(INTEL_SNB,
CFlip->Voltage.Vcore,
CFlip->Voltage.VID);
Core_ComputeVoltageLimits(&RO(Shm)->Cpu[cpu], CFlip);
}
#define ComputeVoltage_Intel_SNB_PerSMT ComputeVoltage_Intel_SNB
static void ComputeVoltage_Intel_SNB_PerCore( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if ((RO(Shm)->Cpu[cpu].Topology.ThreadID == 0)
|| (RO(Shm)->Cpu[cpu].Topology.ThreadID == -1))
{
ComputeVoltage_Intel_SNB(CFlip, RO(Shm), cpu);
}
}
static void ComputeVoltage_Intel_SNB_PerPkg( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if (cpu == RO(Shm)->Proc.Service.Core)
{
ComputeVoltage_Intel_SNB(CFlip, RO(Shm), cpu);
}
}
static void (*ComputeVoltage_Intel_SNB_Matrix[4])( struct FLIP_FLOP*,
RO(SHM_STRUCT)*,
unsigned int ) = \
{
[FORMULA_SCOPE_NONE] = ComputeVoltage_None,
[FORMULA_SCOPE_SMT ] = ComputeVoltage_Intel_SNB_PerSMT,
[FORMULA_SCOPE_CORE] = ComputeVoltage_Intel_SNB_PerCore,
[FORMULA_SCOPE_PKG ] = ComputeVoltage_Intel_SNB_PerPkg
};
static void ComputeVoltage_Intel_SKL_X( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
COMPUTE_VOLTAGE(INTEL_SKL_X,
CFlip->Voltage.Vcore,
CFlip->Voltage.VID);
Core_ComputeVoltageLimits(&RO(Shm)->Cpu[cpu], CFlip);
}
#define ComputeVoltage_Intel_SKL_X_PerSMT ComputeVoltage_Intel_SKL_X
static void ComputeVoltage_Intel_SKL_X_PerCore( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if ((RO(Shm)->Cpu[cpu].Topology.ThreadID == 0)
|| (RO(Shm)->Cpu[cpu].Topology.ThreadID == -1))
{
ComputeVoltage_Intel_SKL_X(CFlip, RO(Shm), cpu);
}
}
static void ComputeVoltage_Intel_SKL_X_PerPkg( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if (cpu == RO(Shm)->Proc.Service.Core)
{
ComputeVoltage_Intel_SKL_X(CFlip, RO(Shm), cpu);
}
}
static void (*ComputeVoltage_Intel_SKL_X_Matrix[4])( struct FLIP_FLOP*,
RO(SHM_STRUCT)*,
unsigned int ) = \
{
[FORMULA_SCOPE_NONE] = ComputeVoltage_None,
[FORMULA_SCOPE_SMT ] = ComputeVoltage_Intel_SKL_X_PerSMT,
[FORMULA_SCOPE_CORE] = ComputeVoltage_Intel_SKL_X_PerCore,
[FORMULA_SCOPE_PKG ] = ComputeVoltage_Intel_SKL_X_PerPkg
};
static void ComputeVoltage_AMD( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
COMPUTE_VOLTAGE(AMD,
CFlip->Voltage.Vcore,
CFlip->Voltage.VID);
Core_ComputeVoltageLimits(&RO(Shm)->Cpu[cpu], CFlip);
}
#define ComputeVoltage_AMD_PerSMT ComputeVoltage_AMD
static void ComputeVoltage_AMD_PerCore( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if ((RO(Shm)->Cpu[cpu].Topology.ThreadID == 0)
|| (RO(Shm)->Cpu[cpu].Topology.ThreadID == -1))
{
ComputeVoltage_AMD(CFlip, RO(Shm), cpu);
}
}
static void ComputeVoltage_AMD_PerPkg( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if (cpu == RO(Shm)->Proc.Service.Core)
{
ComputeVoltage_AMD(CFlip, RO(Shm), cpu);
}
}
static void (*ComputeVoltage_AMD_Matrix[4])( struct FLIP_FLOP*,
RO(SHM_STRUCT)*,
unsigned int ) = \
{
[FORMULA_SCOPE_NONE] = ComputeVoltage_None,
[FORMULA_SCOPE_SMT ] = ComputeVoltage_AMD_PerSMT,
[FORMULA_SCOPE_CORE] = ComputeVoltage_AMD_PerCore,
[FORMULA_SCOPE_PKG ] = ComputeVoltage_AMD_PerPkg
};
static void ComputeVoltage_AMD_0Fh( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{ /* AMD BKDG Family 0Fh Chap 10.6 Table 70 */
COMPUTE_VOLTAGE(AMD_0Fh,
CFlip->Voltage.Vcore,
CFlip->Voltage.VID);
Core_ComputeVoltageLimits(&RO(Shm)->Cpu[cpu], CFlip);
}
#define ComputeVoltage_AMD_0Fh_PerSMT ComputeVoltage_AMD_0Fh
static void ComputeVoltage_AMD_0Fh_PerCore( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if ((RO(Shm)->Cpu[cpu].Topology.ThreadID == 0)
|| (RO(Shm)->Cpu[cpu].Topology.ThreadID == -1))
{
ComputeVoltage_AMD_0Fh(CFlip, RO(Shm), cpu);
}
}
static void ComputeVoltage_AMD_0Fh_PerPkg( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if (cpu == RO(Shm)->Proc.Service.Core)
{
ComputeVoltage_AMD_0Fh(CFlip, RO(Shm), cpu);
}
}
static void (*ComputeVoltage_AMD_0Fh_Matrix[4])(struct FLIP_FLOP*,
RO(SHM_STRUCT)*,
unsigned int) = \
{
[FORMULA_SCOPE_NONE] = ComputeVoltage_None,
[FORMULA_SCOPE_SMT ] = ComputeVoltage_AMD_0Fh_PerSMT,
[FORMULA_SCOPE_CORE] = ComputeVoltage_AMD_0Fh_PerCore,
[FORMULA_SCOPE_PKG ] = ComputeVoltage_AMD_0Fh_PerPkg
};
static void ComputeVoltage_AMD_15h( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
COMPUTE_VOLTAGE(AMD_15h,
CFlip->Voltage.Vcore,
CFlip->Voltage.VID);
Core_ComputeVoltageLimits(&RO(Shm)->Cpu[cpu], CFlip);
}
#define ComputeVoltage_AMD_15h_PerSMT ComputeVoltage_AMD_15h
static void ComputeVoltage_AMD_15h_PerCore( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if ((RO(Shm)->Cpu[cpu].Topology.ThreadID == 0)
|| (RO(Shm)->Cpu[cpu].Topology.ThreadID == -1))
{
ComputeVoltage_AMD_15h(CFlip, RO(Shm), cpu);
}
}
static void ComputeVoltage_AMD_15h_PerPkg( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if (cpu == RO(Shm)->Proc.Service.Core)
{
ComputeVoltage_AMD_15h(CFlip, RO(Shm), cpu);
}
}
static void (*ComputeVoltage_AMD_15h_Matrix[4])(struct FLIP_FLOP*,
RO(SHM_STRUCT)*,
unsigned int) = \
{
[FORMULA_SCOPE_NONE] = ComputeVoltage_None,
[FORMULA_SCOPE_SMT ] = ComputeVoltage_AMD_15h_PerSMT,
[FORMULA_SCOPE_CORE] = ComputeVoltage_AMD_15h_PerCore,
[FORMULA_SCOPE_PKG ] = ComputeVoltage_AMD_15h_PerPkg
};
static void ComputeVoltage_AMD_17h( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
COMPUTE_VOLTAGE(AMD_17h,
CFlip->Voltage.Vcore,
CFlip->Voltage.VID);
Core_ComputeVoltageLimits(&RO(Shm)->Cpu[cpu], CFlip);
}
#define ComputeVoltage_AMD_17h_PerSMT ComputeVoltage_AMD_17h
static void ComputeVoltage_AMD_17h_PerCore( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if ((RO(Shm)->Cpu[cpu].Topology.ThreadID == 0)
|| (RO(Shm)->Cpu[cpu].Topology.ThreadID == -1))
{
ComputeVoltage_AMD_17h(CFlip, RO(Shm), cpu);
}
}
static void ComputeVoltage_AMD_17h_PerPkg( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if (cpu == RO(Shm)->Proc.Service.Core)
{
ComputeVoltage_AMD_17h(CFlip, RO(Shm), cpu);
}
}
static void (*ComputeVoltage_AMD_17h_Matrix[4])(struct FLIP_FLOP*,
RO(SHM_STRUCT)*,
unsigned int) = \
{
[FORMULA_SCOPE_NONE] = ComputeVoltage_None,
[FORMULA_SCOPE_SMT ] = ComputeVoltage_AMD_17h_PerSMT,
[FORMULA_SCOPE_CORE] = ComputeVoltage_AMD_17h_PerCore,
[FORMULA_SCOPE_PKG ] = ComputeVoltage_AMD_17h_PerPkg
};
static void ComputeVoltage_AMD_RMB( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
COMPUTE_VOLTAGE(AMD_RMB,
CFlip->Voltage.Vcore,
CFlip->Voltage.VID);
Core_ComputeVoltageLimits(&RO(Shm)->Cpu[cpu], CFlip);
}
#define ComputeVoltage_AMD_RMB_PerSMT ComputeVoltage_AMD_RMB
static void ComputeVoltage_AMD_RMB_PerCore( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if ((RO(Shm)->Cpu[cpu].Topology.ThreadID == 0)
|| (RO(Shm)->Cpu[cpu].Topology.ThreadID == -1))
{
ComputeVoltage_AMD_RMB(CFlip, RO(Shm), cpu);
}
}
static void ComputeVoltage_AMD_RMB_PerPkg( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if (cpu == RO(Shm)->Proc.Service.Core)
{
ComputeVoltage_AMD_RMB(CFlip, RO(Shm), cpu);
}
}
static void (*ComputeVoltage_AMD_RMB_Matrix[4])(struct FLIP_FLOP*,
RO(SHM_STRUCT)*,
unsigned int) = \
{
[FORMULA_SCOPE_NONE] = ComputeVoltage_None,
[FORMULA_SCOPE_SMT ] = ComputeVoltage_AMD_RMB_PerSMT,
[FORMULA_SCOPE_CORE] = ComputeVoltage_AMD_RMB_PerCore,
[FORMULA_SCOPE_PKG ] = ComputeVoltage_AMD_RMB_PerPkg
};
static void ComputeVoltage_AMD_VCO( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
COMPUTE_VOLTAGE(AMD_VCO,
CFlip->Voltage.Vcore,
CFlip->Voltage.VID);
Core_ComputeVoltageLimits(&RO(Shm)->Cpu[cpu], CFlip);
}
#define ComputeVoltage_AMD_VCO_PerSMT ComputeVoltage_AMD_VCO
static void ComputeVoltage_AMD_VCO_PerCore( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if ((RO(Shm)->Cpu[cpu].Topology.ThreadID == 0)
|| (RO(Shm)->Cpu[cpu].Topology.ThreadID == -1))
{
ComputeVoltage_AMD_VCO(CFlip, RO(Shm), cpu);
}
}
static void ComputeVoltage_AMD_VCO_PerPkg( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if (cpu == RO(Shm)->Proc.Service.Core)
{
ComputeVoltage_AMD_VCO(CFlip, RO(Shm), cpu);
}
}
static void (*ComputeVoltage_AMD_VCO_Matrix[4])(struct FLIP_FLOP*,
RO(SHM_STRUCT)*,
unsigned int) = \
{
[FORMULA_SCOPE_NONE] = ComputeVoltage_None,
[FORMULA_SCOPE_SMT ] = ComputeVoltage_AMD_VCO_PerSMT,
[FORMULA_SCOPE_CORE] = ComputeVoltage_AMD_VCO_PerCore,
[FORMULA_SCOPE_PKG ] = ComputeVoltage_AMD_VCO_PerPkg
};
static void ComputeVoltage_Winbond_IO( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{ /* Winbond W83627EHF/EF, W83627EHG,EG */
COMPUTE_VOLTAGE(WINBOND_IO,
CFlip->Voltage.Vcore,
CFlip->Voltage.VID);
Core_ComputeVoltageLimits(&RO(Shm)->Cpu[cpu], CFlip);
}
#define ComputeVoltage_Winbond_IO_PerSMT ComputeVoltage_Winbond_IO
static void ComputeVoltage_Winbond_IO_PerCore( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if ((RO(Shm)->Cpu[cpu].Topology.ThreadID == 0)
|| (RO(Shm)->Cpu[cpu].Topology.ThreadID == -1))
{
ComputeVoltage_Winbond_IO(CFlip, RO(Shm), cpu);
}
}
static void ComputeVoltage_Winbond_IO_PerPkg( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if (cpu == RO(Shm)->Proc.Service.Core)
{
ComputeVoltage_Winbond_IO(CFlip, RO(Shm), cpu);
}
}
static void (*ComputeVoltage_Winbond_IO_Matrix[4])( struct FLIP_FLOP*,
RO(SHM_STRUCT)*,
unsigned int ) = \
{
[FORMULA_SCOPE_NONE] = ComputeVoltage_None,
[FORMULA_SCOPE_SMT ] = ComputeVoltage_Winbond_IO_PerSMT,
[FORMULA_SCOPE_CORE] = ComputeVoltage_Winbond_IO_PerCore,
[FORMULA_SCOPE_PKG ] = ComputeVoltage_Winbond_IO_PerPkg
};
static void ComputeVoltage_ITE_Tech_IO( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{ /* ITE Tech IT8720F */
COMPUTE_VOLTAGE(ITETECH_IO,
CFlip->Voltage.Vcore,
CFlip->Voltage.VID);
Core_ComputeVoltageLimits(&RO(Shm)->Cpu[cpu], CFlip);
}
#define ComputeVoltage_ITE_Tech_IO_PerSMT ComputeVoltage_ITE_Tech_IO
static void ComputeVoltage_ITE_Tech_IO_PerCore( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if ((RO(Shm)->Cpu[cpu].Topology.ThreadID == 0)
|| (RO(Shm)->Cpu[cpu].Topology.ThreadID == -1))
{
ComputeVoltage_ITE_Tech_IO(CFlip, RO(Shm), cpu);
}
}
static void ComputeVoltage_ITE_Tech_IO_PerPkg( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if (cpu == RO(Shm)->Proc.Service.Core)
{
ComputeVoltage_ITE_Tech_IO(CFlip, RO(Shm), cpu);
}
}
static void (*ComputeVoltage_ITE_Tech_IO_Matrix[4])( struct FLIP_FLOP*,
RO(SHM_STRUCT)*,
unsigned int ) = \
{
[FORMULA_SCOPE_NONE] = ComputeVoltage_None,
[FORMULA_SCOPE_SMT ] = ComputeVoltage_ITE_Tech_IO_PerSMT,
[FORMULA_SCOPE_CORE] = ComputeVoltage_ITE_Tech_IO_PerCore,
[FORMULA_SCOPE_PKG ] = ComputeVoltage_ITE_Tech_IO_PerPkg
};
void Core_ComputePowerLimits(CPU_STRUCT *Cpu, struct FLIP_FLOP *CFlip)
{ /* Per Core, computes the Min CPU Energy consumed. */
TEST_AND_SET_SENSOR( ENERGY, LOWEST, CFlip->State.Energy,
Cpu->Sensors.Energy.Limit );
/* Per Core, computes the Max CPU Energy consumed. */
TEST_AND_SET_SENSOR( ENERGY, HIGHEST, CFlip->State.Energy,
Cpu->Sensors.Energy.Limit );
/* Per Core, computes the Min CPU Power consumed. */
TEST_AND_SET_SENSOR( POWER, LOWEST, CFlip->State.Power,
Cpu->Sensors.Power.Limit);
/* Per Core, computes the Max CPU Power consumed. */
TEST_AND_SET_SENSOR( POWER, HIGHEST, CFlip->State.Power,
Cpu->Sensors.Power.Limit );
}
static void ComputePower_None( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
UNUSED(CFlip);
UNUSED(RO(Shm));
UNUSED(cpu);
}
#define ComputePower_None_PerSMT ComputePower_None
#define ComputePower_None_PerCore ComputePower_None
#define ComputePower_None_PerPkg ComputePower_None
static void (*ComputePower_None_Matrix[4])( struct FLIP_FLOP*,
RO(SHM_STRUCT)*,
unsigned int ) = \
{
[FORMULA_SCOPE_NONE] = ComputePower_None,
[FORMULA_SCOPE_SMT ] = ComputePower_None_PerSMT,
[FORMULA_SCOPE_CORE] = ComputePower_None_PerCore,
[FORMULA_SCOPE_PKG ] = ComputePower_None_PerPkg
};
#define ComputePower_Intel_Matrix ComputePower_None_Matrix
#define ComputePower_Intel_Atom_Matrix ComputePower_None_Matrix
#define ComputePower_AMD_Matrix ComputePower_None_Matrix
static void ComputePower_AMD_17h( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu)
{
CFlip->State.Energy = (double)CFlip->Delta.Power.ACCU
* RO(Shm)->Proc.Power.Unit.Joules;
CFlip->State.Power = 1000.0 * CFlip->State.Energy;
CFlip->State.Power /= RO(Shm)->Sleep.Interval;
Core_ComputePowerLimits(&RO(Shm)->Cpu[cpu], CFlip);
}
#define ComputePower_AMD_17h_PerSMT ComputePower_AMD_17h
static void ComputePower_AMD_17h_PerCore( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if ((RO(Shm)->Cpu[cpu].Topology.ThreadID == 0)
|| (RO(Shm)->Cpu[cpu].Topology.ThreadID == -1))
{
ComputePower_AMD_17h(CFlip, RO(Shm), cpu);
}
}
static void ComputePower_AMD_17h_PerPkg( struct FLIP_FLOP *CFlip,
RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu )
{
if (cpu == RO(Shm)->Proc.Service.Core)
{
ComputePower_AMD_17h(CFlip, RO(Shm), cpu);
}
}
static void (*ComputePower_AMD_17h_Matrix[4])( struct FLIP_FLOP*,
RO(SHM_STRUCT)*,
unsigned int ) = \
{
[FORMULA_SCOPE_NONE] = ComputePower_None,
[FORMULA_SCOPE_SMT ] = ComputePower_AMD_17h_PerSMT,
[FORMULA_SCOPE_CORE] = ComputePower_AMD_17h_PerCore,
[FORMULA_SCOPE_PKG ] = ComputePower_AMD_17h_PerPkg
};
typedef struct {
REF *Ref;
unsigned int Bind;
pthread_t TID;
} ARG;
static void *Core_Cycle(void *arg)
{
ARG *Arg = (ARG *) arg;
unsigned int cpu = Arg->Bind;
RO(SHM_STRUCT) *RO(Shm) = Arg->Ref->RO(Shm);
RO(CORE) *RO(Core) = Arg->Ref->RO(Core, AT(cpu));
RW(CORE) *RW(Core) = Arg->Ref->RW(Core, AT(cpu));
CPU_STRUCT *Cpu = &RO(Shm)->Cpu[cpu];
pthread_t tid = pthread_self();
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(cpu, &cpuset);
if (pthread_setaffinity_np(tid, sizeof(cpu_set_t), &cpuset) != 0) {
goto EXIT;
}
char *comm = malloc(TASK_COMM_LEN+10+1);
if (comm != NULL) {
snprintf(comm, TASK_COMM_LEN+10+1, "corefreqd/%u", cpu);
pthread_setname_np(tid, comm);
free(comm);
}
void (**ComputeThermalFormula)( struct FLIP_FLOP*,
RO(SHM_STRUCT)*,
unsigned int );
void (**ComputeVoltageFormula)( struct FLIP_FLOP*,
RO(SHM_STRUCT)*,
unsigned int );
void (**ComputePowerFormula)( struct FLIP_FLOP*,
RO(SHM_STRUCT)*,
unsigned int );
switch (KIND_OF_FORMULA(RO(Shm)->Proc.thermalFormula)) {
case THERMAL_KIND_INTEL:
ComputeThermalFormula = ComputeThermal_Intel_Matrix;
break;
case THERMAL_KIND_AMD:
ComputeThermalFormula = ComputeThermal_AMD_Matrix;
break;
case THERMAL_KIND_AMD_0Fh:
ComputeThermalFormula = ComputeThermal_AMD_0Fh_Matrix;
break;
case THERMAL_KIND_AMD_15h:
ComputeThermalFormula = ComputeThermal_AMD_15h_Matrix;
break;
case THERMAL_KIND_AMD_17h:
ComputeThermalFormula = ComputeThermal_AMD_17h_Matrix;
break;
case THERMAL_KIND_NONE:
default:
ComputeThermalFormula = ComputeThermal_None_Matrix;
break;
}
switch (KIND_OF_FORMULA(RO(Shm)->Proc.voltageFormula)) {
case VOLTAGE_KIND_INTEL:
ComputeVoltageFormula = ComputeVoltage_Intel_Matrix;
break;
case VOLTAGE_KIND_INTEL_CORE2:
ComputeVoltageFormula = ComputeVoltage_Intel_Core2_Matrix;
break;
case VOLTAGE_KIND_INTEL_SOC:
ComputeVoltageFormula = ComputeVoltage_Intel_SoC_Matrix;
break;
case VOLTAGE_KIND_INTEL_SNB:
case VOLTAGE_KIND_INTEL_SAV:
ComputeVoltageFormula = ComputeVoltage_Intel_SNB_Matrix;
break;
case VOLTAGE_KIND_INTEL_SKL_X:
ComputeVoltageFormula = ComputeVoltage_Intel_SKL_X_Matrix;
break;
case VOLTAGE_KIND_AMD:
ComputeVoltageFormula = ComputeVoltage_AMD_Matrix;
break;
case VOLTAGE_KIND_AMD_0Fh:
ComputeVoltageFormula = ComputeVoltage_AMD_0Fh_Matrix;
break;
case VOLTAGE_KIND_AMD_15h:
ComputeVoltageFormula = ComputeVoltage_AMD_15h_Matrix;
break;
case VOLTAGE_KIND_AMD_17h:
ComputeVoltageFormula = ComputeVoltage_AMD_17h_Matrix;
break;
case VOLTAGE_KIND_AMD_RMB:
ComputeVoltageFormula = ComputeVoltage_AMD_RMB_Matrix;
break;
case VOLTAGE_KIND_ZEN3_VCO:
ComputeVoltageFormula = ComputeVoltage_AMD_VCO_Matrix;
break;
case VOLTAGE_KIND_ZEN4_VCO:
ComputeVoltageFormula = ComputeVoltage_AMD_VCO_Matrix;
break;
case VOLTAGE_KIND_ZEN5_VCO:
ComputeVoltageFormula = ComputeVoltage_AMD_VCO_Matrix;
break;
case VOLTAGE_KIND_WINBOND_IO:
ComputeVoltageFormula = ComputeVoltage_Winbond_IO_Matrix;
break;
case VOLTAGE_KIND_ITETECH_IO:
ComputeVoltageFormula = ComputeVoltage_ITE_Tech_IO_Matrix;
break;
case VOLTAGE_KIND_NONE:
default:
ComputeVoltageFormula = ComputeVoltage_None_Matrix;
break;
}
switch (KIND_OF_FORMULA(RO(Shm)->Proc.powerFormula)) {
case POWER_KIND_INTEL:
ComputePowerFormula = ComputePower_Intel_Matrix;
break;
case POWER_KIND_INTEL_ATOM:
ComputePowerFormula = ComputePower_Intel_Atom_Matrix;
break;
case POWER_KIND_AMD:
ComputePowerFormula = ComputePower_AMD_Matrix;
break;
case POWER_KIND_AMD_17h:
ComputePowerFormula = ComputePower_AMD_17h_Matrix;
break;
case POWER_KIND_NONE:
default:
ComputePowerFormula = ComputePower_None_Matrix;
break;
}
if (Quiet & 0x100) {
printf(" Thread [%lx] Init CYCLE %03u\n", (long) tid, cpu);
fflush(stdout);
}
BITSET_CC(BUS_LOCK, roomSeed, cpu);
BITSET_CC(BUS_LOCK, roomCore, cpu);
do {
while (!BITCLR(LOCKLESS, RW(Core)->Sync.V, NTFY)
&& !BITVAL(Shutdown, SYNC)
&& !BITVAL(RO(Core)->OffLine, OS)) {
nanosleep(&RO(Shm)->Sleep.pollingWait, NULL);
}
if (!BITVAL(Shutdown, SYNC) && !BITVAL(RO(Core)->OffLine, OS))
{
if (BITCLR_CC(BUS_LOCK, roomCore, cpu)) {
Cpu->Toggle = !Cpu->Toggle;
}
struct FLIP_FLOP *CFlip = &Cpu->FlipFlop[Cpu->Toggle];
/* Refresh this Base Clock. */
CFlip->Clock.Q = RO(Core)->Clock.Q;
CFlip->Clock.R = RO(Core)->Clock.R;
CFlip->Clock.Hz = RO(Core)->Clock.Hz;
/* Copy the Performance & C-States Counters. */
CFlip->Delta.INST = RO(Core)->Delta.INST;
CFlip->Delta.C0.UCC = RO(Core)->Delta.C0.UCC;
CFlip->Delta.C0.URC = RO(Core)->Delta.C0.URC;
CFlip->Delta.C3 = RO(Core)->Delta.C3;
CFlip->Delta.C6 = RO(Core)->Delta.C6;
CFlip->Delta.C7 = RO(Core)->Delta.C7;
CFlip->Delta.TSC = RO(Core)->Delta.TSC;
CFlip->Delta.C1 = RO(Core)->Delta.C1;
/* Update all clock ratios. */
memcpy(Cpu->Boost, RO(Core)->Boost, (BOOST(SIZE))*sizeof(unsigned int));
CFlip->Absolute.Ratio.Perf = (double)RO(Core)->Ratio.COF.Q;
CFlip->Absolute.Ratio.Perf +=(double)RO(Core)->Ratio.COF.R /UNIT_KHz(1);
/* Compute IPS=Instructions per TSC */
CFlip->State.IPS = (double)CFlip->Delta.INST
/ (double)CFlip->Delta.TSC;
/* Compute IPC=Instructions per non-halted reference cycle.
( Protect against a division by zero ) */
if (CFlip->Delta.C0.URC != 0) {
CFlip->State.IPC = (double)CFlip->Delta.INST
/ (double)CFlip->Delta.C0.URC;
} else {
CFlip->State.IPC = 0.0f;
}
/* Compute CPI=Non-halted reference cycles per instruction.
( Protect against a division by zero ) */
if (CFlip->Delta.INST != 0) {
CFlip->State.CPI = (double)CFlip->Delta.C0.URC
/ (double)CFlip->Delta.INST;
} else {
CFlip->State.CPI = 0.0f;
}
/* Compute the Turbo State. */
CFlip->State.Turbo = (double)CFlip->Delta.C0.UCC
/ (double)CFlip->Delta.TSC;
/* Compute the C-States. */
CFlip->State.C0 = (double)CFlip->Delta.C0.URC
/ (double)CFlip->Delta.TSC;
CFlip->State.C3 = (double)CFlip->Delta.C3
/ (double)CFlip->Delta.TSC;
CFlip->State.C6 = (double)CFlip->Delta.C6
/ (double)CFlip->Delta.TSC;
CFlip->State.C7 = (double)CFlip->Delta.C7
/ (double)CFlip->Delta.TSC;
CFlip->State.C1 = (double)CFlip->Delta.C1
/ (double)CFlip->Delta.TSC;
/* Relative Frequency = Relative Ratio x Bus Clock Frequency */
CFlip->Relative.Ratio = (double)(CFlip->Delta.C0.UCC
* Cpu->Boost[BOOST(MAX)])
/ (double)CFlip->Delta.TSC;
CFlip->Relative.Freq = REL_FREQ_MHz( double,
CFlip->Relative.Ratio,
CFlip->Clock,
RO(Shm)->Sleep.Interval );
/* Per Core, compute the Relative Frequency limits. */
TEST_AND_SET_SENSOR( REL_FREQ, LOWEST, CFlip->Relative.Freq,
Cpu->Relative.Freq );
TEST_AND_SET_SENSOR( REL_FREQ, HIGHEST, CFlip->Relative.Freq,
Cpu->Relative.Freq );
/* Per Core, compute the Absolute Frequency limits. */
CFlip->Absolute.Freq = ABS_FREQ_MHz(double, CFlip->Absolute.Ratio.Perf,
(double)CFlip->Clock);
TEST_AND_SET_SENSOR( ABS_FREQ, LOWEST, CFlip->Absolute.Freq,
Cpu->Absolute.Freq );
TEST_AND_SET_SENSOR( ABS_FREQ, HIGHEST, CFlip->Absolute.Freq,
Cpu->Absolute.Freq );
/* Core Processor events */
memcpy( CFlip->Thermal.Events, RO(Core)->PowerThermal.Events,
sizeof(CFlip->Thermal.Events) );
/* Per Core, evaluate thermal properties. */
CFlip->Thermal.Sensor = RO(Core)->PowerThermal.Sensor;
CFlip->Thermal.Param = RO(Core)->PowerThermal.Param;
ComputeThermalFormula[SCOPE_OF_FORMULA(RO(Shm)->Proc.thermalFormula)](
CFlip, RO(Shm), cpu
);
/* Per Core, evaluate the voltage properties. */
CFlip->Voltage.VID = RO(Core)->PowerThermal.VID;
ComputeVoltageFormula[SCOPE_OF_FORMULA(RO(Shm)->Proc.voltageFormula)](
CFlip, RO(Shm), cpu
);
/* Per Core, evaluate the Power properties. */
CFlip->Delta.Power.ACCU = RO(Core)->Delta.Power.ACCU;
CFlip->Delta.RAM.ACCU = RO(Core)->Delta.RAM.ACCU;
ComputePowerFormula[SCOPE_OF_FORMULA(RO(Shm)->Proc.powerFormula)](
CFlip, RO(Shm), cpu
);
/* Copy the Interrupts counters. */
CFlip->Counter.SMI = RO(Core)->Interrupt.SMI;
/* If driver registered, copy any NMI counter. */
if (BITVAL(RO(Shm)->Registration.NMI, BIT_NMI_LOCAL) == 1) {
CFlip->Counter.NMI.LOCAL = RO(Core)->Interrupt.NMI.LOCAL;
}
if (BITVAL(RO(Shm)->Registration.NMI, BIT_NMI_UNKNOWN) == 1) {
CFlip->Counter.NMI.UNKNOWN = RO(Core)->Interrupt.NMI.UNKNOWN;
}
if (BITVAL(RO(Shm)->Registration.NMI, BIT_NMI_SERR) == 1) {
CFlip->Counter.NMI.PCISERR = RO(Core)->Interrupt.NMI.PCISERR;
}
if (BITVAL(RO(Shm)->Registration.NMI, BIT_NMI_IO_CHECK) == 1) {
CFlip->Counter.NMI.IOCHECK = RO(Core)->Interrupt.NMI.IOCHECK;
}
}
} while (!BITVAL(Shutdown, SYNC) && !BITVAL(RO(Core)->OffLine, OS)) ;
BITCLR_CC(BUS_LOCK, roomCore, cpu);
BITCLR_CC(BUS_LOCK, roomSeed, cpu);
EXIT:
if (Quiet & 0x100) {
printf(" Thread [%lx] %s CYCLE %03u\n", (long) tid,
BITVAL(RO(Core)->OffLine, OS) ? "Offline" : "Shutdown",
cpu);
fflush(stdout);
}
return NULL;
}
void SliceScheduling( RO(SHM_STRUCT) *RO(Shm),
unsigned int cpu, enum PATTERN pattern )
{
unsigned int seek = 0;
switch (pattern) {
case RESET_CSP:
for (seek = 0; seek < RO(Shm)->Proc.CPU.Count; seek++) {
if (seek == RO(Shm)->Proc.Service.Core) {
BITSET_CC(LOCKLESS, RO(Shm)->roomSched, seek);
} else {
BITCLR_CC(LOCKLESS, RO(Shm)->roomSched, seek);
}
}
break;
case ALL_SMT:
if (cpu == RO(Shm)->Proc.Service.Core) {
BITSTOR_CC(LOCKLESS, RO(Shm)->roomSched, roomSeed);
}
break;
case RAND_SMT:
do {
#ifdef __GLIBC__
if (random_r(&RO(Shm)->Cpu[cpu].Slice.Random.data,
&RO(Shm)->Cpu[cpu].Slice.Random.value[0]) == 0)
#else
RO(Shm)->Cpu[cpu].Slice.Random.value[0] = (int) random();
#endif /* __GLIBC__ */
{
seek = RO(Shm)->Cpu[cpu].Slice.Random.value[0]
% RO(Shm)->Proc.CPU.Count;
}
} while (BITVAL(RO(Shm)->Cpu[seek].OffLine, OS));
BITCLR_CC(LOCKLESS, RO(Shm)->roomSched, cpu);
BITSET_CC(LOCKLESS, RO(Shm)->roomSched, seek);
break;
case RR_SMT:
seek = cpu;
do {
seek++;
if (seek >= RO(Shm)->Proc.CPU.Count) {
seek = 0;
}
} while (BITVAL(RO(Shm)->Cpu[seek].OffLine, OS));
BITCLR_CC(LOCKLESS, RO(Shm)->roomSched, cpu);
BITSET_CC(LOCKLESS, RO(Shm)->roomSched, seek);
break;
case USR_CPU:
/* NOP */
break;
}
}
static void *Child_Thread(void *arg)
{
ARG *Arg = (ARG *) arg;
unsigned int cpu = Arg->Bind;
RO(SHM_STRUCT) *RO(Shm) = Arg->Ref->RO(Shm);
RW(SHM_STRUCT) *RW(Shm) = Arg->Ref->RW(Shm);
CPU_STRUCT *Cpu = &RO(Shm)->Cpu[cpu];
CALL_FUNC MatrixCallFunc[2][2] = {
{ CallWith_RDTSC_No_RDPMC, CallWith_RDTSC_RDPMC },
{ CallWith_RDTSCP_No_RDPMC, CallWith_RDTSCP_RDPMC }
};
const int withTSCP = ((RO(Shm)->Proc.Features.AdvPower.EDX.Inv_TSC == 1)
|| (RO(Shm)->Proc.Features.ExtInfo.EDX.RDTSCP == 1)),
withRDPMC=((RO(Shm)->Proc.Features.Info.Vendor.CRC == CRC_INTEL)
&& (RO(Shm)->Proc.PM_version >= 1)
&& (BITVAL(Cpu->SystemRegister.CR4, CR4_PCE) == 1));
CALL_FUNC CallSliceFunc = MatrixCallFunc[withTSCP][withRDPMC];
pthread_t tid = pthread_self();
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(cpu, &cpuset);
if (pthread_setaffinity_np(tid, sizeof(cpu_set_t), &cpuset) != 0) {
goto EXIT;
}
char *comm = malloc(TASK_COMM_LEN+10+1);
if (comm != NULL) {
snprintf(comm, TASK_COMM_LEN+10+1, "corefreqd#%u", cpu);
pthread_setname_np(tid, comm);
free(comm);
}
if (Quiet & 0x100) {
printf(" Thread [%lx] Init CHILD %03u\n", (long) tid, cpu);
fflush(stdout);
}
BITSET_CC(BUS_LOCK, roomSeed, cpu);
do {
while (!BITVAL(RW(Shm)->Proc.Sync, BURN)
&& !BITVAL(Shutdown, SYNC)
&& !BITVAL(Cpu->OffLine, OS)) {
nanosleep(&RO(Shm)->Sleep.sliceWaiting, NULL);
}
BITSET_CC(BUS_LOCK, roomCore, cpu);
RESET_Slice(Cpu->Slice);
while ( BITVAL(RW(Shm)->Proc.Sync, BURN)
&& !BITVAL(Shutdown, SYNC) )
{
if (BITVAL_CC(RO(Shm)->roomSched, cpu)) {
CallSliceFunc( RO(Shm), RW(Shm), cpu,
Arg->Ref->Slice.Func,
Arg->Ref->Slice.arg);
SliceScheduling(RO(Shm), cpu, Arg->Ref->Slice.pattern);
if (BITVAL(Cpu->OffLine, OS)) { /* ReSchedule to Service */
SliceScheduling(RO(Shm), RO(Shm)->Proc.Service.Core, RESET_CSP);
break;
}
} else {
nanosleep(&RO(Shm)->Sleep.sliceWaiting, NULL);
if (BITVAL(Cpu->OffLine, OS)) {
break;
}
}
}
BITCLR_CC(BUS_LOCK, roomCore, cpu);
} while (!BITVAL(Shutdown, SYNC) && !BITVAL(Cpu->OffLine, OS)) ;
BITCLR_CC(BUS_LOCK, roomSeed, cpu);
RESET_Slice(Cpu->Slice);
EXIT:
if (Quiet & 0x100) {
printf(" Thread [%lx] %s CHILD %03u\n", (long) tid,
BITVAL(Cpu->OffLine, OS) ? "Offline" : "Shutdown",cpu);
fflush(stdout);
}
return NULL;
}
void Architecture(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc))
{
signed long ix;
Bit32 fTSC = RO(Proc)->Features.Std.EDX.TSC,
aTSC = RO(Proc)->Features.AdvPower.EDX.Inv_TSC;
/* Copy all initial CPUID features. */
memcpy(&RO(Shm)->Proc.Features, &RO(Proc)->Features, sizeof(FEATURES));
/* Copy the fomula identifiers */
RO(Shm)->Proc.thermalFormula = RO(Proc)->thermalFormula;
RO(Shm)->Proc.voltageFormula = RO(Proc)->voltageFormula;
RO(Shm)->Proc.powerFormula = RO(Proc)->powerFormula;
/* Copy the numbers of total & online CPU. */
RO(Shm)->Proc.CPU.Count = RO(Proc)->CPU.Count;
RO(Shm)->Proc.CPU.OnLine = RO(Proc)->CPU.OnLine;
RO(Shm)->Proc.Service.Proc = RO(Proc)->Service.Proc;
/* Architecture and Hypervisor identifiers. */
RO(Shm)->Proc.ArchID = RO(Proc)->ArchID;
RO(Shm)->Proc.HypervisorID = RO(Proc)->HypervisorID;
/* Copy the Architecture name. */
StrCopy(RO(Shm)->Proc.Architecture,RO(Proc)->Architecture,CODENAME_LEN);
/* Make the processor's brand string with no trailing spaces */
ix = BRAND_LENGTH;
do {
if ((RO(Proc)->Features.Info.Brand[ix] == 0x20)
|| (RO(Proc)->Features.Info.Brand[ix] == 0x0)) {
ix--;
} else {
break;
}
} while (ix != 0);
RO(Shm)->Proc.Brand[1 + ix] = '\0';
for (; ix >= 0; ix--) {
RO(Shm)->Proc.Brand[ix] = RO(Proc)->Features.Info.Brand[ix];
}
/* Compute the TSC mode: None, Variant, Invariant */
RO(Shm)->Proc.Features.InvariantTSC = fTSC << aTSC;
}
void PerformanceMonitoring(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc))
{
RO(Shm)->Proc.PM_version = RO(Proc)->Features.PerfMon.EAX.Version;
}
void HyperThreading(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc))
{ /* Update the HyperThreading state. */
RO(Shm)->Proc.Features.HyperThreading = RO(Proc)->Features.HTT_Enable;
}
double ComputeTAU(unsigned char Y, unsigned char Z, double TU)
{
return COMPUTE_TAU(Y, Z, TU);
}
void PowerInterface(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc))
{
unsigned short pwrUnits = 0, pwrVal;
enum PWR_DOMAIN pw;
switch (KIND_OF_FORMULA(RO(Proc)->powerFormula)) {
case POWER_KIND_INTEL:
case POWER_KIND_AMD:
case POWER_KIND_AMD_17h:
RO(Shm)->Proc.Power.Unit.Watts = RO(Proc)->PowerThermal.Unit.PU > 0 ?
1.0 / (double) (1 << RO(Proc)->PowerThermal.Unit.PU) : 0;
RO(Shm)->Proc.Power.Unit.Joules= RO(Proc)->PowerThermal.Unit.ESU > 0 ?
1.0 / (double) (1 << RO(Proc)->PowerThermal.Unit.ESU) :0;
TIME_UNIT:
RO(Shm)->Proc.Power.Unit.Times = RO(Proc)->PowerThermal.Unit.TU > 0 ?
1.0 / (double) (1 << RO(Proc)->PowerThermal.Unit.TU)
: 1.0 / (double) (1 << 10);
pwrUnits = 2 << (RO(Proc)->PowerThermal.Unit.PU - 1);
break;
case POWER_KIND_INTEL_ATOM:
RO(Shm)->Proc.Power.Unit.Watts = RO(Proc)->PowerThermal.Unit.PU > 0 ?
0.001 / (double) (1 << RO(Proc)->PowerThermal.Unit.PU) : 0;
RO(Shm)->Proc.Power.Unit.Joules= RO(Proc)->PowerThermal.Unit.ESU > 0 ?
0.001 / (double) (1 << RO(Proc)->PowerThermal.Unit.ESU) : 0;
goto TIME_UNIT;
break;
case POWER_KIND_NONE:
break;
}
if ( (RO(Shm)->Proc.Features.Info.Vendor.CRC == CRC_AMD)
|| (RO(Shm)->Proc.Features.Info.Vendor.CRC == CRC_HYGON) )
{ /* AMD PowerNow */
if (RO(Proc)->Features.AdvPower.EDX.FID) {
BITSET(LOCKLESS, RO(Shm)->Proc.PowerNow, 0);
} else {
BITCLR(LOCKLESS, RO(Shm)->Proc.PowerNow, 0);
}
if (RO(Proc)->Features.AdvPower.EDX.VID) {
BITSET(LOCKLESS, RO(Shm)->Proc.PowerNow, 1);
} else {
BITCLR(LOCKLESS, RO(Shm)->Proc.PowerNow, 1);
}
if((RO(Shm)->Proc.Features.ACPI_PCT_CAP && RO(Proc)->Features.ACPI_PCT)
|| (RO(Shm)->Proc.Features.ACPI_PSS_CAP && RO(Proc)->Features.ACPI_PSS))
{
BITSET(LOCKLESS, RO(Shm)->Proc.PowerNow, 0);
BITSET(LOCKLESS, RO(Shm)->Proc.PowerNow, 1);
}
RO(Shm)->Proc.Power.PPT = RO(Proc)->PowerThermal.Zen.PWR.PPT;
RO(Shm)->Proc.Power.TDP = RO(Proc)->PowerThermal.Zen.TDP.TDP;
RO(Shm)->Proc.Power.Min = RO(Proc)->PowerThermal.Zen.TDP.TDP2;
RO(Shm)->Proc.Power.Max = RO(Proc)->PowerThermal.Zen.TDP.TDP3;
RO(Shm)->Proc.Power.EDC = RO(Proc)->PowerThermal.Zen.EDC.EDC << 2;
RO(Shm)->Proc.Power.TDC = RO(Proc)->PowerThermal.Zen.EDC.TDC;
for (pw = PWR_DOMAIN(PKG); pw < PWR_DOMAIN(SIZE); pw++)
{
RO(Shm)->Proc.Power.Domain[pw].Feature[PL1].Enable = \
RO(Proc)->PowerThermal.Domain[pw].PowerLimit.Enable_Limit1;
RO(Shm)->Proc.Power.Domain[pw].Feature[PL2].Enable = \
RO(Proc)->PowerThermal.Domain[pw].PowerLimit.Enable_Limit2;
RO(Shm)->Proc.Power.Domain[pw].Feature[PL1].Clamping = \
RO(Proc)->PowerThermal.Domain[pw].PowerLimit.Clamping1;
RO(Shm)->Proc.Power.Domain[pw].Feature[PL2].Clamping = \
RO(Proc)->PowerThermal.Domain[pw].PowerLimit.Clamping2;
pwrVal = RO(Proc)->PowerThermal.Domain[pw].PowerLimit.Domain_Limit1;
RO(Shm)->Proc.Power.Domain[pw].PWL[PL1] = pwrVal;
pwrVal = RO(Proc)->PowerThermal.Domain[pw].PowerLimit.Domain_Limit2;
RO(Shm)->Proc.Power.Domain[pw].PWL[PL2] = pwrVal;
RO(Shm)->Proc.Power.Domain[pw].Feature[PL1].Unlock = \
RO(Shm)->Proc.Power.Domain[pw].Feature[PL2].Unlock = \
RO(Proc)->PowerThermal.Domain[pw].Unlock;
}
}
else if (RO(Shm)->Proc.Features.Info.Vendor.CRC == CRC_INTEL)
{
if (pwrUnits != 0)
{
for (pw = PWR_DOMAIN(PKG); pw < PWR_DOMAIN(SIZE); pw++)
{
RO(Shm)->Proc.Power.Domain[pw].Feature[PL1].Enable = \
RO(Proc)->PowerThermal.Domain[pw].PowerLimit.Enable_Limit1;
RO(Shm)->Proc.Power.Domain[pw].Feature[PL2].Enable = \
RO(Proc)->PowerThermal.Domain[pw].PowerLimit.Enable_Limit2;
RO(Shm)->Proc.Power.Domain[pw].Feature[PL1].Clamping = \
RO(Proc)->PowerThermal.Domain[pw].PowerLimit.Clamping1;
RO(Shm)->Proc.Power.Domain[pw].Feature[PL2].Clamping = \
RO(Proc)->PowerThermal.Domain[pw].PowerLimit.Clamping2;
pwrVal = RO(Proc)->PowerThermal.Domain[pw].PowerLimit.Domain_Limit1
/ pwrUnits;
RO(Shm)->Proc.Power.Domain[pw].PWL[PL1] = pwrVal;
pwrVal = RO(Proc)->PowerThermal.Domain[pw].PowerLimit.Domain_Limit2
/ pwrUnits;
RO(Shm)->Proc.Power.Domain[pw].PWL[PL2] = pwrVal;
}
pwrVal = RO(Proc)->PowerThermal.PowerInfo.ThermalSpecPower / pwrUnits;
RO(Shm)->Proc.Power.TDP = pwrVal;
pwrVal = RO(Proc)->PowerThermal.PowerInfo.MinimumPower / pwrUnits;
RO(Shm)->Proc.Power.Min = pwrVal;
pwrVal = RO(Proc)->PowerThermal.PowerInfo.MaximumPower / pwrUnits;
RO(Shm)->Proc.Power.Max = pwrVal;
}
for (pw = PWR_DOMAIN(PKG); pw < PWR_DOMAIN(SIZE); pw++)
{
RO(Shm)->Proc.Power.Domain[pw].Feature[PL1].TW = \
RO(Proc)->PowerThermal.Domain[pw].PowerLimit.TimeWindow1;
RO(Shm)->Proc.Power.Domain[pw].Feature[PL2].TW = \
RO(Proc)->PowerThermal.Domain[pw].PowerLimit.TimeWindow2;
RO(Shm)->Proc.Power.Domain[pw].TAU[PL1] = ComputeTAU(
RO(Shm)->Proc.Power.Domain[pw].Feature[PL1].TW_Y,
RO(Shm)->Proc.Power.Domain[pw].Feature[PL1].TW_Z,
RO(Shm)->Proc.Power.Unit.Times
);
RO(Shm)->Proc.Power.Domain[pw].TAU[PL2] = ComputeTAU(
RO(Shm)->Proc.Power.Domain[pw].Feature[PL2].TW_Y,
RO(Shm)->Proc.Power.Domain[pw].Feature[PL2].TW_Z,
RO(Shm)->Proc.Power.Unit.Times
);
RO(Shm)->Proc.Power.Domain[pw].Feature[PL1].Unlock = \
RO(Shm)->Proc.Power.Domain[pw].Feature[PL2].Unlock = \
RO(Proc)->PowerThermal.Domain[pw].Unlock;
}
RO(Shm)->Proc.Power.TDC = RO(Proc)->PowerThermal.TDC;
RO(Shm)->Proc.Power.Feature.TDC=RO(Proc)->PowerThermal.Enable_Limit.TDC;
} else {
RO(Shm)->Proc.PowerNow = 0;
}
}
void ThermalPoint(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc))
{
memcpy(&RO(Shm)->Proc.ThermalPoint, &RO(Proc)->ThermalPoint,
sizeof(THERMAL_POINT));
}
void Technology_Update( RO(SHM_STRUCT) *RO(Shm),
RO(PROC) *RO(Proc), RW(PROC) *RW(Proc) )
{ /* Technologies aggregation. */
RO(Shm)->Proc.Technology.PowerNow = (RO(Shm)->Proc.PowerNow == 0b11);
RO(Shm)->Proc.Technology.ODCM = BITCMP_CC(BUS_LOCK,
RW(Proc)->ODCM,
RO(Proc)->ODCM_Mask);
RO(Shm)->Proc.Technology.L1_HW_Prefetch = BITCMP_CC(BUS_LOCK,
RW(Proc)->L1_HW_Prefetch,
RO(Proc)->DCU_Mask);
RO(Shm)->Proc.Technology.L1_HW_IP_Prefetch = BITCMP_CC(BUS_LOCK,
RW(Proc)->L1_HW_IP_Prefetch,
RO(Proc)->DCU_Mask);
RO(Shm)->Proc.Technology.L1_NPP_Prefetch = BITCMP_CC(BUS_LOCK,
RW(Proc)->L1_NPP_Prefetch,
RO(Proc)->DCU_Mask);
RO(Shm)->Proc.Technology.L1_Scrubbing = BITWISEAND_CC(BUS_LOCK,
RW(Proc)->L1_Scrubbing,
RO(Proc)->L1_Scrub_Mask) != 0;
RO(Shm)->Proc.Technology.L2_HW_Prefetch = BITCMP_CC(BUS_LOCK,
RW(Proc)->L2_HW_Prefetch,
RO(Proc)->DCU_Mask);
RO(Shm)->Proc.Technology.L2_HW_CL_Prefetch = BITCMP_CC(BUS_LOCK,
RW(Proc)->L2_HW_CL_Prefetch,
RO(Proc)->DCU_Mask);
RO(Shm)->Proc.Technology.L2_AMP_Prefetch = BITWISEAND_CC(BUS_LOCK,
RW(Proc)->L2_AMP_Prefetch,
RO(Proc)->L2_AMP_Mask) != 0;
RO(Shm)->Proc.Technology.L2_NLP_Prefetch = BITWISEAND_CC(BUS_LOCK,
RW(Proc)->L2_NLP_Prefetch,
RO(Proc)->ECORE_Mask) != 0;
RO(Shm)->Proc.Technology.L1_Stride_Pf = BITCMP_CC(BUS_LOCK,
RW(Proc)->L1_Stride_Pf,
RO(Proc)->DCU_Mask);
RO(Shm)->Proc.Technology.L1_Region_Pf = BITCMP_CC(BUS_LOCK,
RW(Proc)->L1_Region_Pf,
RO(Proc)->DCU_Mask);
RO(Shm)->Proc.Technology.L1_Burst_Pf = BITCMP_CC(BUS_LOCK,
RW(Proc)->L1_Burst_Pf,
RO(Proc)->DCU_Mask);
RO(Shm)->Proc.Technology.L2_Stream_HW_Pf = BITCMP_CC(BUS_LOCK,
RW(Proc)->L2_Stream_HW_Pf,
RO(Proc)->DCU_Mask);
RO(Shm)->Proc.Technology.L2_UpDown_Pf = BITCMP_CC(BUS_LOCK,
RW(Proc)->L2_UpDown_Pf,
RO(Proc)->DCU_Mask);
RO(Shm)->Proc.Technology.LLC_Streamer = BITWISEAND_CC(BUS_LOCK,
RW(Proc)->LLC_Streamer,
RO(Proc)->ECORE_Mask) != 0;
RO(Shm)->Proc.Technology.PowerMgmt = BITCMP_CC(BUS_LOCK,
RW(Proc)->PowerMgmt,
RO(Proc)->PowerMgmt_Mask);
RO(Shm)->Proc.Technology.EIST = BITCMP_CC(BUS_LOCK,
RW(Proc)->SpeedStep,
RO(Proc)->SpeedStep_Mask);
RO(Shm)->Proc.Technology.Turbo = BITWISEAND_CC(BUS_LOCK,
RW(Proc)->TurboBoost,
RO(Proc)->TurboBoost_Mask) != 0;
RO(Shm)->Proc.Technology.C1E = BITCMP_CC(BUS_LOCK,
RW(Proc)->C1E,
RO(Proc)->C1E_Mask);
RO(Shm)->Proc.Technology.C3A = BITCMP_CC(BUS_LOCK,
RW(Proc)->C3A,
RO(Proc)->C3A_Mask);
RO(Shm)->Proc.Technology.C1A = BITCMP_CC(BUS_LOCK,
RW(Proc)->C1A,
RO(Proc)->C1A_Mask);
RO(Shm)->Proc.Technology.C3U = BITCMP_CC(BUS_LOCK,
RW(Proc)->C3U,
RO(Proc)->C3U_Mask);
RO(Shm)->Proc.Technology.C1U = BITCMP_CC(BUS_LOCK,
RW(Proc)->C1U,
RO(Proc)->C1U_Mask);
RO(Shm)->Proc.Technology.CC6 = BITCMP_CC(BUS_LOCK,
RW(Proc)->CC6,
RO(Proc)->CC6_Mask);
RO(Shm)->Proc.Technology.PC6 = BITCMP_CC(BUS_LOCK,
RW(Proc)->PC6,
RO(Proc)->PC6_Mask);
RO(Shm)->Proc.Technology.SMM = BITCMP_CC(BUS_LOCK,
RW(Proc)->SMM,
RO(Proc)->CR_Mask);
RO(Shm)->Proc.Technology.VM = BITCMP_CC(BUS_LOCK,
RW(Proc)->VM,
RO(Proc)->CR_Mask);
RO(Shm)->Proc.Technology.WDT = BITCMP_CC(BUS_LOCK,
RW(Proc)->WDT,
RO(Proc)->WDT_Mask);
/* 000v */
RO(Shm)->Proc.Technology.TM1 = RO(Proc)->Features.Std.EDX.TM1
| RO(Proc)->Features.AdvPower.EDX.TTP;
/* 00v0 */
RO(Shm)->Proc.Technology.TM1 |= BITCMP_CC(BUS_LOCK,
RW(Proc)->TM1,
RO(Proc)->TM_Mask) << 1;
/* 000v */
RO(Shm)->Proc.Technology.TM2 = RO(Proc)->Features.Std.ECX.TM2
| RO(Proc)->Features.AdvPower.EDX.TM;
/* 00v0 */
RO(Shm)->Proc.Technology.TM2 |= BITCMP_CC(BUS_LOCK,
RW(Proc)->TM2,
RO(Proc)->TM_Mask) << 1;
}
void Mitigation_2nd_Stage( RO(SHM_STRUCT) *RO(Shm),
RO(PROC) *RO(Proc), RW(PROC) *RW(Proc) )
{
unsigned short IBRS = BITCMP_CC( BUS_LOCK,
RW(Proc)->IBRS,
RO(Proc)->SPEC_CTRL_Mask ),
STIBP = BITCMP_CC( BUS_LOCK,
RW(Proc)->STIBP,
RO(Proc)->SPEC_CTRL_Mask ),
SSBD = BITCMP_CC( BUS_LOCK,
RW(Proc)->SSBD,
RO(Proc)->SPEC_CTRL_Mask ),
AMD_LS_CFG_SSBD = BITCMP_CC(BUS_LOCK,
RW(Proc)->AMD_LS_CFG_SSBD,
RO(Proc)->SPEC_CTRL_Mask ),
PSFD = BITCMP_CC( BUS_LOCK,
RW(Proc)->PSFD,
RO(Proc)->SPEC_CTRL_Mask );
RO(Shm)->Proc.Mechanisms.IBRS += (2 * IBRS);
RO(Shm)->Proc.Mechanisms.STIBP += (2 * STIBP);
RO(Shm)->Proc.Mechanisms.SSBD += (2 * (SSBD | AMD_LS_CFG_SSBD));
RO(Shm)->Proc.Mechanisms.PSFD += (2 * PSFD);
}
void Mitigation_1st_Stage( RO(SHM_STRUCT) *RO(Shm),
RO(PROC) *RO(Proc), RW(PROC) *RW(Proc) )
{
if (RO(Shm)->Proc.Features.Info.Vendor.CRC == CRC_INTEL)
{
unsigned short RDCL_NO = BITCMP_CC( BUS_LOCK,
RW(Proc)->RDCL_NO,
RO(Proc)->ARCH_CAP_Mask ),
IBRS_ALL = BITCMP_CC( BUS_LOCK,
RW(Proc)->RDCL_NO,
RO(Proc)->ARCH_CAP_Mask ),
RSBA = BITCMP_CC( BUS_LOCK,
RW(Proc)->RSBA,
RO(Proc)->ARCH_CAP_Mask ),
L1DFL_NO = BITCMP_CC( BUS_LOCK,
RW(Proc)->L1DFL_VMENTRY_NO,
RO(Proc)->ARCH_CAP_Mask ),
SSB_NO = BITCMP_CC( BUS_LOCK,
RW(Proc)->SSB_NO,
RO(Proc)->ARCH_CAP_Mask ),
MDS_NO = BITCMP_CC( BUS_LOCK,
RW(Proc)->MDS_NO,
RO(Proc)->ARCH_CAP_Mask ),
PSCHANGE_MC_NO=BITCMP_CC(BUS_LOCK,
RW(Proc)->PSCHANGE_MC_NO,
RO(Proc)->ARCH_CAP_Mask),
TAA_NO = BITCMP_CC( BUS_LOCK,
RW(Proc)->TAA_NO,
RO(Proc)->ARCH_CAP_Mask ),
STLB = BITCMP_CC( BUS_LOCK,
RW(Proc)->STLB,
RO(Proc)->ARCH_CAP_Mask ),
FUSA = BITCMP_CC( BUS_LOCK,
RW(Proc)->FUSA,
RO(Proc)->ARCH_CAP_Mask ),
RSM_CPL0 = BITCMP_CC( BUS_LOCK,
RW(Proc)->RSM_CPL0,
RO(Proc)->ARCH_CAP_Mask ),
SPLA = BITCMP_CC( BUS_LOCK,
RW(Proc)->SPLA,
RO(Proc)->ARCH_CAP_Mask ),
SNOOP_FILTER =BITCMP_CC(BUS_LOCK,
RW(Proc)->SNOOP_FILTER,
RO(Proc)->ARCH_CAP_Mask),
DOITM_MSR = BITCMP_CC( BUS_LOCK,
RW(Proc)->DOITM_MSR,
RO(Proc)->ARCH_CAP_Mask ),
DOITM_EN = BITCMP_CC( BUS_LOCK,
RW(Proc)->DOITM_EN,
RO(Proc)->ARCH_CAP_Mask ),
SBDR_SSDP_NO = BITCMP_CC(BUS_LOCK,
RW(Proc)->SBDR_SSDP_NO,
RO(Proc)->ARCH_CAP_Mask),
FBSDP_NO = BITCMP_CC( BUS_LOCK,
RW(Proc)->FBSDP_NO,
RO(Proc)->ARCH_CAP_Mask ),
PSDP_NO = BITCMP_CC( BUS_LOCK,
RW(Proc)->PSDP_NO,
RO(Proc)->ARCH_CAP_Mask ),
FB_CLEAR = BITCMP_CC( BUS_LOCK,
RW(Proc)->FB_CLEAR,
RO(Proc)->ARCH_CAP_Mask ),
XAPIC_MSR = BITCMP_CC( BUS_LOCK,
RW(Proc)->XAPIC_MSR,
RO(Proc)->ARCH_CAP_Mask ),
XAPIC_DIS = BITCMP_CC( BUS_LOCK,
RW(Proc)->XAPIC_DIS,
RO(Proc)->ARCH_CAP_Mask ),
RNGDS = BITCMP_CC( BUS_LOCK,
RW(Proc)->RNGDS,
RO(Proc)->ARCH_CAP_Mask ),
RTM = BITCMP_CC( BUS_LOCK,
RW(Proc)->RTM,
RO(Proc)->ARCH_CAP_Mask ),
VERW = BITCMP_CC( BUS_LOCK,
RW(Proc)->VERW,
RO(Proc)->ARCH_CAP_Mask ),
RRSBA = BITCMP_CC( BUS_LOCK,
RW(Proc)->RRSBA,
RO(Proc)->ARCH_CAP_Mask ),
BHI_NO = BITCMP_CC( BUS_LOCK,
RW(Proc)->BHI_NO,
RO(Proc)->ARCH_CAP_Mask ),
PBRSB_NO = BITCMP_CC( BUS_LOCK,
RW(Proc)->PBRSB_NO,
RO(Proc)->ARCH_CAP_Mask ),
OC_UTILIZED = BITCMP_CC(BUS_LOCK,
RW(Proc)->OC_UTILIZED,
RO(Proc)->ARCH_CAP_Mask),
OC_UNDERVOLT = BITCMP_CC(BUS_LOCK,
RW(Proc)->OC_UNDERVOLT,
RO(Proc)->ARCH_CAP_Mask),
OC_UNLOCKED = BITCMP_CC(BUS_LOCK,
RW(Proc)->OC_UNLOCKED,
RO(Proc)->ARCH_CAP_Mask),
GDS_NO = BITCMP_CC( BUS_LOCK,
RW(Proc)->GDS_NO,
RO(Proc)->ARCH_CAP_Mask ),
RFDS_NO = BITCMP_CC( BUS_LOCK,
RW(Proc)->RFDS_NO,
RO(Proc)->ARCH_CAP_Mask ),
IPRED_DIS_U = BITCMP_CC(BUS_LOCK,
RW(Proc)->IPRED_DIS_U,
RO(Proc)->SPEC_CTRL_Mask),
IPRED_DIS_S = BITCMP_CC(BUS_LOCK,
RW(Proc)->IPRED_DIS_S,
RO(Proc)->SPEC_CTRL_Mask),
RRSBA_DIS_U = BITCMP_CC(BUS_LOCK,
RW(Proc)->RRSBA_DIS_U,
RO(Proc)->SPEC_CTRL_Mask),
RRSBA_DIS_S = BITCMP_CC(BUS_LOCK,
RW(Proc)->RRSBA_DIS_S,
RO(Proc)->SPEC_CTRL_Mask),
DDPD_U_DIS = BITCMP_CC( BUS_LOCK,
RW(Proc)->DDPD_U_DIS,
RO(Proc)->SPEC_CTRL_Mask ),
BHI_DIS_S = BITCMP_CC( BUS_LOCK,
RW(Proc)->BHI_DIS_S,
RO(Proc)->SPEC_CTRL_Mask );
RO(Shm)->Proc.Mechanisms.IBRS = (
RO(Shm)->Proc.Features.ExtFeature.EDX.IBRS_IBPB_Cap == 1
);
RO(Shm)->Proc.Mechanisms.STIBP = (
RO(Shm)->Proc.Features.ExtFeature.EDX.STIBP_Cap == 1
);
RO(Shm)->Proc.Mechanisms.SSBD = (
RO(Shm)->Proc.Features.ExtFeature.EDX.SSBD_Cap == 1
);
RO(Shm)->Proc.Mechanisms.PSFD = (
(RO(Shm)->Proc.Features.ExtFeature.EAX.MaxSubLeaf >= 2)
&& (RO(Shm)->Proc.Features.ExtFeature_Leaf2_EDX.PSFD_SPEC_CTRL == 1)
);
Mitigation_2nd_Stage(RO(Shm), RO(Proc), RW(Proc));
RO(Shm)->Proc.Mechanisms.RDCL_NO = (
RO(Shm)->Proc.Features.ExtFeature.EDX.IA32_ARCH_CAP
+ (2 * RDCL_NO)
);
RO(Shm)->Proc.Mechanisms.IBRS_ALL = (
RO(Shm)->Proc.Features.ExtFeature.EDX.IA32_ARCH_CAP
+ (2 * IBRS_ALL)
);
RO(Shm)->Proc.Mechanisms.RSBA = (
RO(Shm)->Proc.Features.ExtFeature.EDX.IA32_ARCH_CAP
+ (2 * RSBA)
);
RO(Shm)->Proc.Mechanisms.L1DFL_VMENTRY_NO = (
RO(Shm)->Proc.Features.ExtFeature.EDX.IA32_ARCH_CAP
+ (2 * L1DFL_NO)
);
RO(Shm)->Proc.Mechanisms.SSB_NO = (
RO(Shm)->Proc.Features.ExtFeature.EDX.IA32_ARCH_CAP
+ (2 * SSB_NO)
);
RO(Shm)->Proc.Mechanisms.MDS_NO = (
RO(Shm)->Proc.Features.ExtFeature.EDX.IA32_ARCH_CAP
+ (2 * MDS_NO)
);
RO(Shm)->Proc.Mechanisms.PSCHANGE_MC_NO = (
RO(Shm)->Proc.Features.ExtFeature.EDX.IA32_ARCH_CAP
+ (2 * PSCHANGE_MC_NO)
);
RO(Shm)->Proc.Mechanisms.TAA_NO = (
RO(Shm)->Proc.Features.ExtFeature.EDX.IA32_ARCH_CAP
+ (2 * TAA_NO)
);
RO(Shm)->Proc.Mechanisms.STLB = (
RO(Shm)->Proc.Features.ExtFeature.EDX.IA32_CORE_CAP
+ (2 * STLB)
);
RO(Shm)->Proc.Mechanisms.FUSA = (
RO(Shm)->Proc.Features.ExtFeature.EDX.IA32_CORE_CAP
+ (2 * FUSA)
);
RO(Shm)->Proc.Mechanisms.RSM_CPL0 = (
RO(Shm)->Proc.Features.ExtFeature.EDX.IA32_CORE_CAP
+ (2 * RSM_CPL0)
);
RO(Shm)->Proc.Mechanisms.SPLA = (
RO(Shm)->Proc.Features.ExtFeature.EDX.IA32_CORE_CAP
+ (2 * SPLA)
);
RO(Shm)->Proc.Mechanisms.SNOOP_FILTER = (
RO(Shm)->Proc.Features.ExtFeature.EDX.IA32_CORE_CAP
+ (2 * SNOOP_FILTER)
);
RO(Shm)->Proc.Mechanisms.DOITM_EN = DOITM_MSR + (2 * DOITM_EN);
RO(Shm)->Proc.Mechanisms.SBDR_SSDP_NO = (
RO(Shm)->Proc.Features.ExtFeature.EDX.IA32_ARCH_CAP
+ (2 * SBDR_SSDP_NO)
);
RO(Shm)->Proc.Mechanisms.FBSDP_NO = (
RO(Shm)->Proc.Features.ExtFeature.EDX.IA32_ARCH_CAP
+ (2 * FBSDP_NO)
);
RO(Shm)->Proc.Mechanisms.PSDP_NO = (
RO(Shm)->Proc.Features.ExtFeature.EDX.IA32_ARCH_CAP
+ (2 * PSDP_NO)
);
RO(Shm)->Proc.Mechanisms.FB_CLEAR = (
RO(Shm)->Proc.Features.ExtFeature.EDX.IA32_ARCH_CAP
+ (2 * FB_CLEAR)
);
RO(Shm)->Proc.Mechanisms.RRSBA = (
RO(Shm)->Proc.Features.ExtFeature.EDX.IA32_ARCH_CAP
+ (2 * RRSBA)
);
RO(Shm)->Proc.Mechanisms.BHI_NO = (
RO(Shm)->Proc.Features.ExtFeature.EDX.IA32_ARCH_CAP
+ (2 * BHI_NO)
);
RO(Shm)->Proc.Mechanisms.SRBDS = BITCMP_CC(BUS_LOCK,
RW(Proc)->SRBDS_MSR,
RO(Proc)->ARCH_CAP_Mask);
RO(Shm)->Proc.Mechanisms.RNGDS = RO(Shm)->Proc.Mechanisms.SRBDS
+ (2 * RNGDS);
RO(Shm)->Proc.Mechanisms.RTM = RO(Shm)->Proc.Mechanisms.SRBDS
+ (2 * RTM);
RO(Shm)->Proc.Mechanisms.VERW = RO(Shm)->Proc.Mechanisms.SRBDS
+ (2 * VERW);
RO(Shm)->Proc.Mechanisms.XAPIC_DIS = XAPIC_MSR + (2 * XAPIC_DIS);
RO(Shm)->Proc.Mechanisms.PBRSB_NO = (
RO(Shm)->Proc.Features.ExtFeature.EDX.IA32_ARCH_CAP
+ (2 * PBRSB_NO)
);
RO(Shm)->Proc.Mechanisms.OC_UTILIZED = (
RO(Shm)->Proc.Features.ExtFeature.EDX.IA32_ARCH_CAP
+ (2 * OC_UTILIZED)
);
RO(Shm)->Proc.Mechanisms.OC_UNDERVOLT = (
RO(Shm)->Proc.Features.ExtFeature.EDX.IA32_ARCH_CAP
+ (2 * OC_UNDERVOLT)
);
RO(Shm)->Proc.Mechanisms.OC_UNLOCKED = (
RO(Shm)->Proc.Features.ExtFeature.EDX.IA32_ARCH_CAP
+ (2 * OC_UNLOCKED)
);
RO(Shm)->Proc.Mechanisms.GDS_NO = (
RO(Shm)->Proc.Features.ExtFeature.EDX.IA32_ARCH_CAP
+ (2 * GDS_NO)
);
RO(Shm)->Proc.Mechanisms.RFDS_NO = (
RO(Shm)->Proc.Features.ExtFeature.EDX.IA32_ARCH_CAP
+ (2 * RFDS_NO)
);
RO(Shm)->Proc.Mechanisms.IPRED_DIS_U = (
(RO(Shm)->Proc.Features.ExtFeature.EAX.MaxSubLeaf >= 2)
&& (RO(Shm)->Proc.Features.ExtFeature_Leaf2_EDX.IPRED_SPEC_CTRL == 1)
);
RO(Shm)->Proc.Mechanisms.IPRED_DIS_U += (2 * IPRED_DIS_U);
RO(Shm)->Proc.Mechanisms.IPRED_DIS_S = (
(RO(Shm)->Proc.Features.ExtFeature.EAX.MaxSubLeaf >= 2)
&& (RO(Shm)->Proc.Features.ExtFeature_Leaf2_EDX.IPRED_SPEC_CTRL == 1)
);
RO(Shm)->Proc.Mechanisms.IPRED_DIS_S += (2 * IPRED_DIS_S);
RO(Shm)->Proc.Mechanisms.RRSBA_DIS_U = (
(RO(Shm)->Proc.Features.ExtFeature.EAX.MaxSubLeaf >= 2)
&& (RO(Shm)->Proc.Features.ExtFeature_Leaf2_EDX.RRSBA_SPEC_CTRL == 1)
);
RO(Shm)->Proc.Mechanisms.RRSBA_DIS_U += (2 * RRSBA_DIS_U);
RO(Shm)->Proc.Mechanisms.RRSBA_DIS_S = (
(RO(Shm)->Proc.Features.ExtFeature.EAX.MaxSubLeaf >= 2)
&& (RO(Shm)->Proc.Features.ExtFeature_Leaf2_EDX.RRSBA_SPEC_CTRL == 1)
);
RO(Shm)->Proc.Mechanisms.RRSBA_DIS_S += (2 * RRSBA_DIS_S);
RO(Shm)->Proc.Mechanisms.DDPD_U_DIS = (
(RO(Shm)->Proc.Features.ExtFeature.EAX.MaxSubLeaf >= 2)
&& (RO(Shm)->Proc.Features.ExtFeature_Leaf2_EDX.DDPD_U_SPEC_CTRL ==1)
);
RO(Shm)->Proc.Mechanisms.DDPD_U_DIS += (2 * DDPD_U_DIS);
RO(Shm)->Proc.Mechanisms.BHI_DIS_S = (
(RO(Shm)->Proc.Features.ExtFeature.EAX.MaxSubLeaf >= 2)
&& (RO(Shm)->Proc.Features.ExtFeature_Leaf2_EDX.BHI_SPEC_CTRL == 1)
);
RO(Shm)->Proc.Mechanisms.BHI_DIS_S += (2 * BHI_DIS_S);
RO(Shm)->Proc.Mechanisms.MCDT_NO = (
RO(Shm)->Proc.Features.ExtFeature_Leaf2_EDX.MCDT_NO == 1
);
RO(Shm)->Proc.Mechanisms.MONITOR_MITG_NO = (
RO(Shm)->Proc.Features.ExtFeature_Leaf2_EDX.MONITOR_MITG_NO == 1
);
}
else if ( (RO(Shm)->Proc.Features.Info.Vendor.CRC == CRC_AMD)
|| (RO(Shm)->Proc.Features.Info.Vendor.CRC == CRC_HYGON) )
{
unsigned short BTC_NOBR = BITCMP_CC( BUS_LOCK,
RW(Proc)->BTC_NOBR,
RO(Proc)->BTC_NOBR_Mask );
RO(Shm)->Proc.Mechanisms.IBRS = (
RO(Shm)->Proc.Features.leaf80000008.EBX.IBRS == 1
);
RO(Shm)->Proc.Mechanisms.STIBP = (
RO(Shm)->Proc.Features.leaf80000008.EBX.STIBP == 1
);
RO(Shm)->Proc.Mechanisms.SSBD = (
RO(Shm)->Proc.Features.leaf80000008.EBX.SSBD == 1
);
RO(Shm)->Proc.Mechanisms.PSFD = (
RO(Shm)->Proc.Features.leaf80000008.EBX.PSFD == 1
);
Mitigation_2nd_Stage(RO(Shm), RO(Proc), RW(Proc));
switch (RO(Shm)->Proc.ArchID) {
case AMD_EPYC_Rome_CPK:
case AMD_Zen2_Renoir:
case AMD_Zen2_LCN:
case AMD_Zen2_MTS:
case AMD_Zen2_Ariel:
case AMD_Zen2_Jupiter:
case AMD_Zen2_Galileo:
case AMD_Zen2_MDN:
RO(Shm)->Proc.Mechanisms.BTC_NOBR = (
RO(Shm)->Proc.Features.leaf80000008.EBX.STIBP == 1
);
RO(Shm)->Proc.Mechanisms.BTC_NOBR += (2 * BTC_NOBR);
RO(Shm)->Proc.Mechanisms.XPROC_LEAK = \
BITCMP_CC(BUS_LOCK,
RW(Proc)->XPROC_LEAK,
RO(Proc)->XPROC_LEAK_Mask) ? 0b11 : 0b10;
RO(Shm)->Proc.Mechanisms.AGENPICK = \
BITCMP_CC(BUS_LOCK,
RW(Proc)->AGENPICK,
RO(Proc)->BTC_NOBR_Mask) ? 0b11 : 0b10;
break;
default:
RO(Shm)->Proc.Mechanisms.BTC_NOBR = 0;
RO(Shm)->Proc.Mechanisms.XPROC_LEAK = 0;
RO(Shm)->Proc.Mechanisms.AGENPICK = 0;
break;
}
}
}
#define TIMING(_mc, _cha) RO(Shm)->Uncore.MC[_mc].Channel[_cha].Timing
typedef struct {
unsigned int Q,
R;
} RAM_Ratio;
void P945_MCH(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc))
{
unsigned short mc, cha, slot;
for (mc = 0; mc < RO(Shm)->Uncore.CtrlCount; mc++)
{
RO(Shm)->Uncore.MC[mc].SlotCount = RO(Proc)->Uncore.MC[mc].SlotCount;
RO(Shm)->Uncore.MC[mc].ChannelCount = RO(Proc)->Uncore.MC[mc].ChannelCount;
for (cha = 0; cha < RO(Shm)->Uncore.MC[mc].ChannelCount; cha++)
{
TIMING(mc, cha).tWR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P945.DRT0.tWR;
TIMING(mc, cha).tRTPr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P945.DRT1.tRTPr;
TIMING(mc, cha).tRAS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P945.DRT1.tRAS;
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].P945.DRT1.tRRD) {
case 0b000:
TIMING(mc, cha).tRRD = 1;
break;
case 0b001:
TIMING(mc, cha).tRRD = 2;
break;
}
TIMING(mc, cha).tRFC = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P945.DRT1.tRFC;
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].P945.DRT1.tCL) {
case 0b00:
TIMING(mc, cha).tCL = 5;
break;
case 0b01:
TIMING(mc, cha).tCL = 4;
break;
case 0b10:
TIMING(mc, cha).tCL = 3;
break;
case 0b11:
TIMING(mc, cha).tCL = 6;
break;
}
TIMING(mc, cha).tRCD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P945.DRT1.tRCD + 2;
TIMING(mc, cha).tRP = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P945.DRT1.tRP + 2;
for (slot = 0; slot < RO(Shm)->Uncore.MC[mc].SlotCount; slot++)
{
unsigned long long DIMM_Size;
unsigned short rank, rankCount = (cha == 0) ? 4 : 2;
for (rank = 0; rank < rankCount; rank++) {
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks += \
RO(Proc)->Uncore.MC[mc].Channel[cha].P945.DRB[rank].Boundary;
}
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].P945.BANK.Rank0)
{
case 0b00:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks = 4;
break;
case 0b01:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks = 8;
break;
}
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].P945.WIDTH.Rank0)
{
case 0b00:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows = 16384;
break;
case 0b01:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows = 8192;
break;
}
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols = 1024;
DIMM_Size = RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Size = \
(unsigned int)(DIMM_Size >> 20);
}
TIMING(mc, cha).ECC = 0;
TIMING(mc, cha).tCKE = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P945.DRT2.tCKE;
}
}
}
void P955_MCH(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc))
{
unsigned short mc, cha, slot;
for (mc = 0; mc < RO(Shm)->Uncore.CtrlCount; mc++)
{
RO(Shm)->Uncore.MC[mc].SlotCount = RO(Proc)->Uncore.MC[mc].SlotCount;
RO(Shm)->Uncore.MC[mc].ChannelCount = RO(Proc)->Uncore.MC[mc].ChannelCount;
for (cha = 0; cha < RO(Shm)->Uncore.MC[mc].ChannelCount; cha++)
{
TIMING(mc, cha).tRAS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P955.DRT1.tRAS;
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].P955.DRT1.tCL) {
case 0b00:
TIMING(mc, cha).tCL = 5;
break;
case 0b01:
TIMING(mc, cha).tCL = 4;
break;
case 0b10:
TIMING(mc, cha).tCL = 3;
break;
case 0b11:
TIMING(mc, cha).tCL = 6;
break;
}
TIMING(mc, cha).tRCD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P955.DRT1.tRCD + 2;
TIMING(mc, cha).tRP = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P955.DRT1.tRP + 2;
for (slot = 0; slot < RO(Shm)->Uncore.MC[mc].SlotCount; slot++)
{
unsigned long long DIMM_Size;
unsigned short rank;
for (rank = 0; rank < 4; rank++) {
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks += \
RO(Proc)->Uncore.MC[mc].Channel[cha].P955.DRB[rank].Boundary;
}
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].P955.BANK.Rank0)
{
case 0b00:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks = 4;
break;
case 0b01:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks = 8;
break;
}
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].P955.WIDTH.Rank0)
{
case 0b00:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows = 16384;
break;
case 0b01:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows = 8192;
break;
}
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols = 1024;
DIMM_Size = RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Size = \
(unsigned int)DIMM_Size;
}
TIMING(mc, cha).ECC = 0;
}
}
}
void P945_CLK(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc), RO(CORE) *RO(Core))
{
RAM_Ratio Ratio = {.Q = 1, .R = 1};
switch (RO(Proc)->Uncore.Bus.ClkCfg.FSB_Select) {
case 0b000:
RO(Shm)->Uncore.Bus.Rate = 400;
switch (RO(Proc)->Uncore.Bus.ClkCfg.RAM_Select) {
default:
fallthrough;
case 0b010:
Ratio.Q = 1;
Ratio.R = 1;
break;
case 0b011:
Ratio.Q = 4;
Ratio.R = 3;
break;
case 0b100:
Ratio.Q = 5;
Ratio.R = 3;
break;
}
break;
case 0b001:
RO(Shm)->Uncore.Bus.Rate = 533;
switch (RO(Proc)->Uncore.Bus.ClkCfg.RAM_Select) {
default:
fallthrough;
case 0b010:
Ratio.Q = 3;
Ratio.R = 4;
break;
case 0b011:
Ratio.Q = 1;
Ratio.R = 1;
break;
case 0b001:
Ratio.Q = 5;
Ratio.R = 4;
break;
}
break;
default:
fallthrough;
case 0b011:
RO(Shm)->Uncore.Bus.Rate = 667;
switch (RO(Proc)->Uncore.Bus.ClkCfg.RAM_Select) {
default:
fallthrough;
case 0b010:
Ratio.Q = 3;
Ratio.R = 5;
break;
case 0b011:
Ratio.Q = 4;
Ratio.R = 5;
break;
case 0b100:
Ratio.Q = 1;
Ratio.R = 1;
break;
}
break;
}
RO(Shm)->Uncore.CtrlSpeed = (RO(Core)->Clock.Hz * Ratio.Q * 2)/* DDR2 */
/ (Ratio.R * 1000000L);
RO(Shm)->Uncore.Bus.Speed = (RO(Core)->Clock.Hz
* RO(Shm)->Uncore.Bus.Rate)
/ RO(Shm)->Proc.Features.Factory.Clock.Hz;
RO(Shm)->Uncore.Unit.Bus_Rate = MC_MHZ;
RO(Shm)->Uncore.Unit.BusSpeed = MC_MHZ;
RO(Shm)->Uncore.Unit.DDR_Rate = MC_NIL;
RO(Shm)->Uncore.Unit.DDRSpeed = MC_MHZ;
RO(Shm)->Uncore.Unit.DDR_Ver = 2;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_UNSPEC;
}
void P965_MCH(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc))
{
unsigned short mc, cha, slot;
for (mc = 0; mc < RO(Shm)->Uncore.CtrlCount; mc++)
{
RO(Shm)->Uncore.MC[mc].SlotCount = RO(Proc)->Uncore.MC[mc].SlotCount;
RO(Shm)->Uncore.MC[mc].ChannelCount = RO(Proc)->Uncore.MC[mc].ChannelCount;
for (cha = 0; cha < RO(Shm)->Uncore.MC[mc].ChannelCount; cha++)
{
TIMING(mc, cha).tCL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P965.DRT0.tCL;
TIMING(mc, cha).tCL += 3;
TIMING(mc, cha).tRAS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P965.DRT1.tRAS;
TIMING(mc, cha).tWR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P965.DRT1.tWR;
TIMING(mc, cha).tRFC = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P965.DRT2.tRFC;
TIMING(mc, cha).tRP = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P965.DRT2.tRP;
TIMING(mc, cha).tRRD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P965.DRT2.tRRD;
TIMING(mc, cha).tRCD_WR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P965.DRT3.tRCD_WR;
TIMING(mc, cha).tRCD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P965.DRT4.tRCD_RD;
TIMING(mc, cha).tFAW = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P965.DRT2.ACT_Count;
TIMING(mc, cha).tRTPr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P965.DRT2.ReservedBits;
/* TODO(Timings)
TIMING(mc, cha).tCWL = ?
*/
TIMING(mc, cha).tddRdTWr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P965.DRT3.tRD_WR;
TIMING(mc, cha).tsrRdTRd = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P965.DRT4.tRD_RD_SR;
TIMING(mc, cha).tdrRdTRd = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P965.DRT4.tRD_RD_DR;
TIMING(mc, cha).tsrWrTWr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P965.DRT3.tWR_WR_SR;
TIMING(mc, cha).tdrWrTWr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P965.DRT3.tWR_WR_DR;
TIMING(mc, cha).tsrWrTRd = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P965.DRT4.tWR_RD_SR;
TIMING(mc, cha).tdrWrTRd = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P965.DRT4.tWR_RD_DR;
for (slot = 0; slot < RO(Shm)->Uncore.MC[mc].SlotCount; slot++)
{
unsigned long long DIMM_Size;
/* TODO(Geometry):Hardware missing! */
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks = 0;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks = 0;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows = 0;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols = 0;
DIMM_Size = 8LLU
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Size = \
(unsigned int)(DIMM_Size >> 20);
}
TIMING(mc, cha).ECC = 0;
TIMING(mc, cha).tXS = (cha == 0) ?
RO(Proc)->Uncore.MC[mc].P965.CKE0.tXSNR
: RO(Proc)->Uncore.MC[mc].P965.CKE1.tXSNR;
TIMING(mc, cha).tXP = (cha == 0) ?
RO(Proc)->Uncore.MC[mc].P965.CKE0.tXP
: RO(Proc)->Uncore.MC[mc].P965.CKE1.tXP;
TIMING(mc, cha).tCKE = (cha == 0) ?
RO(Proc)->Uncore.MC[mc].P965.CKE0.tCKE_Low
: RO(Proc)->Uncore.MC[mc].P965.CKE1.tCKE_Low;
}
}
}
void P965_CLK(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc), RO(CORE) *RO(Core))
{
RAM_Ratio Ratio = {.Q = 1, .R = 1};
switch (RO(Proc)->Uncore.Bus.ClkCfg.FSB_Select) {
case 0b111: /* Unknown */
fallthrough;
case 0b000:
RO(Shm)->Uncore.Bus.Rate = 1066;
switch (RO(Proc)->Uncore.Bus.ClkCfg.RAM_Select) {
case 0b001:
Ratio.Q = 1;
Ratio.R = 1;
break;
case 0b010:
Ratio.Q = 5;
Ratio.R = 4;
break;
case 0b011:
Ratio.Q = 3;
Ratio.R = 2;
break;
case 0b100:
Ratio.Q = 2;
Ratio.R = 1;
break;
case 0b101:
Ratio.Q = 5;
Ratio.R = 2;
break;
}
break;
case 0b001:
RO(Shm)->Uncore.Bus.Rate = 533;
switch (RO(Proc)->Uncore.Bus.ClkCfg.RAM_Select) {
case 0b001:
Ratio.Q = 2;
Ratio.R = 1;
break;
case 0b010:
Ratio.Q = 5;
Ratio.R = 2;
break;
case 0b011:
Ratio.Q = 3;
Ratio.R = 1;
break;
}
break;
case 0b011:
RO(Shm)->Uncore.Bus.Rate = 667;
break;
case 0b100:
RO(Shm)->Uncore.Bus.Rate = 1333;
switch (RO(Proc)->Uncore.Bus.ClkCfg.RAM_Select) {
case 0b010:
Ratio.Q = 1;
Ratio.R = 1;
break;
case 0b011:
Ratio.Q = 6;
Ratio.R = 5;
break;
case 0b100:
Ratio.Q = 8;
Ratio.R = 5;
break;
case 0b101:
Ratio.Q = 2;
Ratio.R = 1;
break;
}
break;
case 0b110:
RO(Shm)->Uncore.Bus.Rate = 1600;
switch (RO(Proc)->Uncore.Bus.ClkCfg.RAM_Select) {
case 0b011:
Ratio.Q = 1;
Ratio.R = 1;
break;
case 0b100:
Ratio.Q = 4;
Ratio.R = 3;
break;
case 0b101:
Ratio.Q = 3;
Ratio.R = 2;
break;
case 0b110:
Ratio.Q = 2;
Ratio.R = 1;
break;
}
break;
default:
fallthrough;
case 0b010:
RO(Shm)->Uncore.Bus.Rate = 800;
switch (RO(Proc)->Uncore.Bus.ClkCfg.RAM_Select) {
case 0b000:
Ratio.Q = 1;
Ratio.R = 1;
break;
case 0b001:
Ratio.Q = 5;
Ratio.R = 4;
break;
case 0b010:
Ratio.Q = 5;
Ratio.R = 3;
break;
case 0b011:
Ratio.Q = 2;
Ratio.R = 1;
break;
case 0b100:
Ratio.Q = 8;
Ratio.R = 3;
break;
case 0b101:
Ratio.Q = 10;
Ratio.R = 3;
break;
}
break;
}
RO(Shm)->Uncore.CtrlSpeed = (RO(Core)->Clock.Hz * Ratio.Q * 2) /* DDR2 */
/ (Ratio.R * 1000000L);
RO(Shm)->Uncore.Bus.Speed = (RO(Core)->Clock.Hz
* RO(Shm)->Uncore.Bus.Rate)
/ RO(Shm)->Proc.Features.Factory.Clock.Hz;
RO(Shm)->Uncore.Unit.Bus_Rate = MC_MTS;
RO(Shm)->Uncore.Unit.BusSpeed = MC_MTS;
RO(Shm)->Uncore.Unit.DDR_Rate = MC_NIL;
RO(Shm)->Uncore.Unit.DDRSpeed = MC_MHZ;
RO(Shm)->Uncore.Unit.DDR_Ver = 2;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_UNSPEC;
}
void G965_MCH(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc))
{
unsigned short mc, cha, slot;
for (mc = 0; mc < RO(Shm)->Uncore.CtrlCount; mc++)
{
RO(Shm)->Uncore.MC[mc].SlotCount = RO(Proc)->Uncore.MC[mc].SlotCount;
RO(Shm)->Uncore.MC[mc].ChannelCount = RO(Proc)->Uncore.MC[mc].ChannelCount;
for (cha = 0; cha < RO(Shm)->Uncore.MC[mc].ChannelCount; cha++)
{
TIMING(mc, cha).tWR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].G965.DRT0.tWR;
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].G965.DRT1.tRCD) {
case 0b000:
TIMING(mc, cha).tRCD = 2;
break;
case 0b001:
TIMING(mc, cha).tRCD = 3;
break;
case 0b010:
TIMING(mc, cha).tRCD = 4;
break;
case 0b011:
TIMING(mc, cha).tRCD = 5;
break;
case 0b100:
TIMING(mc, cha).tRCD = 6;
break;
case 0b101:
TIMING(mc, cha).tRCD = 7;
break;
case 0b110:
TIMING(mc, cha).tRCD = 8;
break;
}
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].G965.DRT1.tRP) {
case 0b000:
TIMING(mc, cha).tRP = 2;
break;
case 0b001:
TIMING(mc, cha).tRP = 3;
break;
case 0b010:
TIMING(mc, cha).tRP = 4;
break;
case 0b011:
TIMING(mc, cha).tRP = 5;
break;
case 0b100:
TIMING(mc, cha).tRP = 6;
break;
case 0b101:
TIMING(mc, cha).tRP = 7;
break;
case 0b110:
TIMING(mc, cha).tRP = 8;
break;
}
TIMING(mc, cha).tRAS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].G965.DRT1.tRAS;
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].G965.DRT1.tRRD) {
case 0b000:
TIMING(mc, cha).tRRD = 2;
break;
case 0b001:
TIMING(mc, cha).tRRD = 3;
break;
case 0b010:
TIMING(mc, cha).tRRD = 4;
break;
case 0b011:
TIMING(mc, cha).tRRD = 5;
break;
case 0b100:
TIMING(mc, cha).tRRD = 6;
break;
}
TIMING(mc, cha).tRTPr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].G965.DRT1.tRTPr;
TIMING(mc, cha).tFAW = \
RO(Proc)->Uncore.MC[mc].Channel[cha].G965.DRT2.tFAW;
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].G965.DRT3.tCL) {
case 0b000:
TIMING(mc, cha).tCL = 3;
break;
case 0b001:
TIMING(mc, cha).tCL = 4;
break;
case 0b010:
TIMING(mc, cha).tCL = 5;
break;
case 0b011:
TIMING(mc, cha).tCL = 6;
break;
case 0b100:
TIMING(mc, cha).tCL = 7;
break;
}
TIMING(mc, cha).tRFC = \
RO(Proc)->Uncore.MC[mc].Channel[cha].G965.DRT3.tRFC;
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].G965.DRT3.tCWL) {
case 0b000:
TIMING(mc, cha).tCWL = 2;
break;
case 0b001:
TIMING(mc, cha).tCWL = 3;
break;
case 0b010:
TIMING(mc, cha).tCWL = 4;
break;
case 0b011:
TIMING(mc, cha).tCWL = 5;
break;
case 0b100:
TIMING(mc, cha).tCWL = 6;
break;
default:
TIMING(mc, cha).tCWL = \
TIMING(mc, cha).tCL - 1;
break;
}
for (slot = 0; slot < RO(Shm)->Uncore.MC[mc].SlotCount; slot++)
{
unsigned long long DIMM_Size;
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].DIMM[slot].DRA.Rank1Bank)
{
case 0b00:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks = 4;
break;
case 0b01:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks = 8;
break;
}
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].DIMM[slot].DRA.Rank0Bank)
{
case 0b00:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks += 4;
break;
case 0b01:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks += 8;
break;
}
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].DIMM[slot].DRA.OddRank1)
{
case 0b10:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks = 1;
break;
case 0b11:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks = 2;
break;
}
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].DIMM[slot].DRA.EvenRank0)
{
case 0b10:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks += 1;
break;
case 0b11:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks += 2;
break;
}
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows = 4096;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols = 1024;
DIMM_Size = 8LLU
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Size = \
(unsigned int)(DIMM_Size >> 20);
}
TIMING(mc, cha).ECC = 0;
TIMING(mc, cha).tXS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].G965.DRT3.tXS;
TIMING(mc, cha).tXP = \
RO(Proc)->Uncore.MC[mc].Channel[cha].G965.DRT2.tXP;
TIMING(mc, cha).tCKE = \
RO(Proc)->Uncore.MC[mc].Channel[cha].G965.DRT2.tCKE;
}
}
}
void G965_CLK(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc), RO(CORE) *RO(Core))
{
RAM_Ratio Ratio = {.Q = 1, .R = 1};
switch (RO(Proc)->Uncore.Bus.ClkCfg.FSB_Select) {
case 0b001:
RO(Shm)->Uncore.Bus.Rate = 533;
switch (RO(Proc)->Uncore.Bus.ClkCfg.RAM_Select) {
case 0b001:
Ratio.Q = 5;
Ratio.R = 4;
break;
case 0b010:
Ratio.Q = 3;
Ratio.R = 2;
break;
case 0b011:
Ratio.Q = 2;
Ratio.R = 1;
break;
}
break;
case 0b011:
RO(Shm)->Uncore.Bus.Rate = 667;
switch (RO(Proc)->Uncore.Bus.ClkCfg.RAM_Select) {
case 0b001:
Ratio.Q = 1;
Ratio.R = 1;
break;
case 0b010:
Ratio.Q = 6;
Ratio.R = 5;
break;
case 0b011:
Ratio.Q = 8;
Ratio.R = 5;
break;
case 0b100:
Ratio.Q = 2;
Ratio.R = 1;
break;
case 0b101:
Ratio.Q = 12;
Ratio.R = 5;
break;
}
break;
case 0b110:
RO(Shm)->Uncore.Bus.Rate = 1066;
switch (RO(Proc)->Uncore.Bus.ClkCfg.RAM_Select) {
case 0b101:
Ratio.Q = 3;
Ratio.R = 2;
break;
case 0b110:
Ratio.Q = 2;
Ratio.R = 1;
break;
}
break;
default:
fallthrough;
case 0b010:
RO(Shm)->Uncore.Bus.Rate = 800;
switch (RO(Proc)->Uncore.Bus.ClkCfg.RAM_Select) {
case 0b001:
Ratio.Q = 5;
Ratio.R = 6;
break;
case 0b010:
Ratio.Q = 1;
Ratio.R = 1;
break;
case 0b011:
Ratio.Q = 4;
Ratio.R = 3;
break;
case 0b100:
Ratio.Q = 5;
Ratio.R = 3;
break;
case 0b101:
Ratio.Q = 2;
Ratio.R = 1;
break;
}
break;
}
RO(Shm)->Uncore.CtrlSpeed = (RO(Core)->Clock.Hz * Ratio.Q * 2) /* DDR2 */
/ (Ratio.R * 1000000L);
RO(Shm)->Uncore.Bus.Speed = (RO(Core)->Clock.Hz
* RO(Shm)->Uncore.Bus.Rate)
/ RO(Shm)->Proc.Features.Factory.Clock.Hz;
RO(Shm)->Uncore.Unit.Bus_Rate = MC_MHZ;
RO(Shm)->Uncore.Unit.BusSpeed = MC_MHZ;
RO(Shm)->Uncore.Unit.DDR_Rate = MC_NIL;
RO(Shm)->Uncore.Unit.DDRSpeed = MC_MHZ;
RO(Shm)->Uncore.Unit.DDR_Ver = 2;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_UNSPEC;
}
void P3S_MCH( RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc),
unsigned short mc,unsigned short cha )
{
TIMING(mc, cha).tCL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P35.DRT0.tCL;
TIMING(mc, cha).tWR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P35.DRT1.tWR;
TIMING(mc, cha).tRFC = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P35.DRT2.tRFC;
TIMING(mc, cha).tRP = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P35.DRT2.tRP;
TIMING(mc, cha).tRRD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P35.DRT2.tRRD;
TIMING(mc, cha).tRCD_WR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P35.DRT3.tRCD_WR;
TIMING(mc, cha).tRCD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P35.DRT4.tRCD_RD;
TIMING(mc, cha).tRAS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P35.DRT5.tRAS;
TIMING(mc, cha).tFAW = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P35.DRT2.ACT_Count;
TIMING(mc, cha).tRTPr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P35.DRT2.ReservedBits;
/* TODO(Timings)
TIMING(mc, cha).tCWL = ?
*/
TIMING(mc, cha).tddRdTWr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P35.DRT3.tRD_WR;
TIMING(mc, cha).tsrRdTRd = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P35.DRT4.tRD_RD_SR;
TIMING(mc, cha).tdrRdTRd = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P35.DRT4.tRD_RD_DR;
TIMING(mc, cha).tsrWrTWr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P35.DRT3.tWR_WR_SR;
TIMING(mc, cha).tdrWrTWr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P35.DRT3.tWR_WR_DR;
TIMING(mc, cha).tsrWrTRd = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P35.DRT4.tWR_RD_SR;
TIMING(mc, cha).tdrWrTRd = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P35.DRT4.tWR_RD_DR;
TIMING(mc, cha).tXS = (cha == 0) ?
RO(Proc)->Uncore.MC[mc].P35.CKE0.tXSNR
: RO(Proc)->Uncore.MC[mc].P35.CKE1.tXSNR;
TIMING(mc, cha).tXP = (cha == 0) ?
RO(Proc)->Uncore.MC[mc].P35.CKE0.tXP
: RO(Proc)->Uncore.MC[mc].P35.CKE1.tXP;
TIMING(mc, cha).tCKE = (cha == 0) ?
RO(Proc)->Uncore.MC[mc].P35.CKE0.tCKE_Low
: RO(Proc)->Uncore.MC[mc].P35.CKE1.tCKE_Low;
}
void P35_MCH(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc))
{
unsigned short mc, cha, slot;
for (mc = 0; mc < RO(Shm)->Uncore.CtrlCount; mc++)
{
RO(Shm)->Uncore.MC[mc].SlotCount = RO(Proc)->Uncore.MC[mc].SlotCount;
RO(Shm)->Uncore.MC[mc].ChannelCount = RO(Proc)->Uncore.MC[mc].ChannelCount;
for (cha = 0; cha < RO(Shm)->Uncore.MC[mc].ChannelCount; cha++)
{
P3S_MCH(RO(Shm), RO(Proc), mc, cha);
TIMING(mc, cha).tCL -= 9;
for (slot = 0; slot < RO(Shm)->Uncore.MC[mc].SlotCount; slot++)
{
unsigned long long DIMM_Size;
unsigned short rank;
for (rank = 0; rank < 4; rank++) {
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks += \
RO(Proc)->Uncore.MC[mc].Channel[cha].P35.DRB[rank].Boundary;
switch (rank) {
case 0:
case 2:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P35.DRA[rank >> 1].Rank0;
break;
case 1:
case 3:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks = \
RO(Proc)->Uncore.MC[mc].Channel[cha].P35.DRA[rank >> 1].Rank1;
break;
}
}
/*TODO(Geometry registers)*/
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows = 16384;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols = 1024;
DIMM_Size = RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Size = \
(unsigned int)DIMM_Size;
}
TIMING(mc, cha).ECC = 0;
}
}
}
void P35_CLK(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc), RO(CORE) *RO(Core))
{
P965_CLK(RO(Shm), RO(Proc), RO(Core));
}
void P4S_MCH(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc))
{
unsigned short mc, cha, slot;
for (mc = 0; mc < RO(Shm)->Uncore.CtrlCount; mc++)
{
RO(Shm)->Uncore.MC[mc].SlotCount = RO(Proc)->Uncore.MC[mc].SlotCount;
RO(Shm)->Uncore.MC[mc].ChannelCount = RO(Proc)->Uncore.MC[mc].ChannelCount;
for (cha = 0; cha < RO(Shm)->Uncore.MC[mc].ChannelCount; cha++)
{
P3S_MCH(RO(Shm), RO(Proc), mc, cha);
TIMING(mc, cha).tCL -= 6;
/* TODO(Timings) */
for (slot = 0; slot < RO(Shm)->Uncore.MC[mc].SlotCount; slot++)
{
unsigned long long DIMM_Size;
/* TODO(Geometry):Hardware missing! */
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks = 0;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks = 0;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows = 0;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols = 0;
DIMM_Size = 8LLU
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Size = \
(unsigned int)(DIMM_Size >> 20);
}
TIMING(mc, cha).ECC = 0;
}
}
}
void SLM_PTR(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc), RO(CORE) *RO(Core))
{
unsigned short mc, cha, slot;
/* BUS & DRAM frequency */
RO(Shm)->Uncore.CtrlSpeed = 800LLU + (
((2134LLU * RO(Proc)->Uncore.MC[0].SLM.DTR0.DFREQ) >> 3)
);
RO(Shm)->Uncore.Bus.Rate = 5000;
RO(Shm)->Uncore.Bus.Speed = (RO(Core)->Clock.Hz
* RO(Shm)->Uncore.Bus.Rate)
/ RO(Shm)->Proc.Features.Factory.Clock.Hz;
RO(Shm)->Uncore.Unit.Bus_Rate = MC_MTS;
RO(Shm)->Uncore.Unit.BusSpeed = MC_MTS;
RO(Shm)->Uncore.Unit.DDR_Rate = MC_NIL;
RO(Shm)->Uncore.Unit.DDRSpeed = MC_MHZ;
for (mc = 0; mc < RO(Shm)->Uncore.CtrlCount; mc++)
{
RO(Shm)->Uncore.MC[mc].SlotCount = RO(Proc)->Uncore.MC[mc].SlotCount;
RO(Shm)->Uncore.MC[mc].ChannelCount = RO(Proc)->Uncore.MC[mc].ChannelCount;
for (cha = 0; cha < RO(Shm)->Uncore.MC[mc].ChannelCount; cha++)
{
/* Standard Timings */
TIMING(mc, cha).tCL = RO(Proc)->Uncore.MC[mc].SLM.DTR0.tCL + 5;
TIMING(mc, cha).tRCD = RO(Proc)->Uncore.MC[mc].SLM.DTR0.tRCD + 5;
TIMING(mc, cha).tRP = RO(Proc)->Uncore.MC[mc].SLM.DTR0.tRP + 5;
TIMING(mc, cha).tRAS = RO(Proc)->Uncore.MC[mc].SLM.DTR1.tRAS;
TIMING(mc, cha).tRRD = RO(Proc)->Uncore.MC[mc].SLM.DTR1.tRRD + 4;
TIMING(mc, cha).tRFC = \
RO(Proc)->Uncore.MC[mc].SLM.DTR0.tXS == 0 ? 256 : 384;
switch (RO(Proc)->Uncore.MC[mc].SLM.DRFC.tREFI) {
case 0 ... 1:
TIMING(mc, cha).tREFI = 0;
break;
case 2:
TIMING(mc, cha).tREFI = 39;
break;
case 3:
TIMING(mc, cha).tREFI = 78;
break;
}
TIMING(mc, cha).tREFI *= RO(Shm)->Uncore.CtrlSpeed;
TIMING(mc, cha).tREFI /= 20;
TIMING(mc, cha).tCKE = RO(Proc)->Uncore.MC[mc].SLM.DRMC.CKEVAL;
TIMING(mc, cha).tRTPr = RO(Proc)->Uncore.MC[mc].SLM.DTR1.tRTP + 4;
TIMING(mc, cha).tWTPr = RO(Proc)->Uncore.MC[mc].SLM.DTR1.tWTP + 14;
TIMING(mc, cha).B2B = RO(Proc)->Uncore.MC[mc].SLM.DTR1.tCCD;
switch (RO(Proc)->Uncore.MC[mc].SLM.DTR1.tFAW) {
case 0 ... 1:
TIMING(mc, cha).tFAW = 0;
break;
default:
TIMING(mc, cha).tFAW = \
10 + ((unsigned int)RO(Proc)->Uncore.MC[mc].SLM.DTR1.tFAW << 1);
break;
}
TIMING(mc, cha).tCWL = RO(Proc)->Uncore.MC[mc].SLM.DTR1.tWCL + 3;
/*TODO( Read to Read. Same Rank )
TIMING(mc, cha).tsrRdTRd = RO(Proc)->Uncore.MC[mc].SLM.DTR?.;
*/
TIMING(mc, cha).tsrRdTWr = 6 + RO(Proc)->Uncore.MC[mc].SLM.DTR3.tRWSR;
TIMING(mc, cha).tsrWrTRd = 11 + RO(Proc)->Uncore.MC[mc].SLM.DTR3.tWRSR;
/*TODO( Write to Write. Same Rank )
TIMING(mc, cha).tsrWrTWr = RO(Proc)->Uncore.MC[mc].SLM.DTR?.;
*/
/* Different Rank */
TIMING(mc, cha).tdrRdTRd = RO(Proc)->Uncore.MC[mc].SLM.DTR2.tRRDR;
if (TIMING(mc, cha).tdrRdTRd > 0) {
TIMING(mc, cha).tdrRdTRd += 5;
}
TIMING(mc, cha).tdrRdTWr = RO(Proc)->Uncore.MC[mc].SLM.DTR2.tRWDR;
if (TIMING(mc, cha).tdrRdTWr > 0) {
TIMING(mc, cha).tdrRdTWr += 5;
}
TIMING(mc, cha).tdrWrTRd = RO(Proc)->Uncore.MC[mc].SLM.DTR3.tWRDR;
if (TIMING(mc, cha).tdrWrTRd > 0) {
TIMING(mc, cha).tdrWrTRd += 3;
}
TIMING(mc, cha).tdrWrTWr = 4 + RO(Proc)->Uncore.MC[mc].SLM.DTR2.tWWDR;
/* Different DIMM */
TIMING(mc, cha).tddRdTRd = RO(Proc)->Uncore.MC[mc].SLM.DTR2.tRRDD;
if (TIMING(mc, cha).tddRdTRd > 0) {
TIMING(mc, cha).tddRdTRd += 5;
}
TIMING(mc, cha).tddRdTWr = RO(Proc)->Uncore.MC[mc].SLM.DTR2.tRWDD;
if (TIMING(mc, cha).tddRdTWr > 0) {
TIMING(mc, cha).tddRdTWr += 5;
}
TIMING(mc, cha).tddWrTRd = 4 + RO(Proc)->Uncore.MC[mc].SLM.DTR3.tWRDD;
TIMING(mc, cha).tddWrTWr = 4 + RO(Proc)->Uncore.MC[mc].SLM.DTR2.tWWDD;
/* Command Rate */
TIMING(mc, cha).CMD_Rate = 1 + RO(Proc)->Uncore.MC[mc].SLM.DTR1.tCMD;
TIMING(mc, cha).tXS = RO(Proc)->Uncore.MC[mc].SLM.DTR0.tXS;
TIMING(mc, cha).tXP = RO(Proc)->Uncore.MC[mc].SLM.DTR3.tXP;
/* Topology */
for (slot = 0; slot < RO(Shm)->Uncore.MC[mc].SlotCount; slot++)
{
unsigned long long DIMM_Size;
const struct {
unsigned int Banks,
Rows,
Cols;
} DDR3L[4] = {
{ .Banks = 8, .Rows = 1<<14, .Cols = 1<<10 },
{ .Banks = 8, .Rows = 1<<15, .Cols = 1<<10 },
{ .Banks = 8, .Rows = 1<<16, .Cols = 1<<10 },
{ .Banks = 8, .Rows = 1<<14, .Cols = 1<<10 }
};
if (cha == 0) {
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks = \
RO(Proc)->Uncore.MC[mc].SLM.DRP.RKEN0
+ RO(Proc)->Uncore.MC[mc].SLM.DRP.RKEN1;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks = \
DDR3L[RO(Proc)->Uncore.MC[mc].SLM.DRP.DIMMDDEN0].Banks;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows = \
DDR3L[RO(Proc)->Uncore.MC[mc].SLM.DRP.DIMMDDEN0].Rows;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols = \
DDR3L[RO(Proc)->Uncore.MC[mc].SLM.DRP.DIMMDDEN0].Cols;
} else {
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks = \
RO(Proc)->Uncore.MC[mc].SLM.DRP.RKEN2
+ RO(Proc)->Uncore.MC[mc].SLM.DRP.RKEN3;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks = \
DDR3L[RO(Proc)->Uncore.MC[mc].SLM.DRP.DIMMDDEN1].Banks;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows = \
DDR3L[RO(Proc)->Uncore.MC[mc].SLM.DRP.DIMMDDEN1].Rows;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols = \
DDR3L[RO(Proc)->Uncore.MC[mc].SLM.DRP.DIMMDDEN1].Cols;
}
DIMM_Size = 8LLU
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Size = \
(unsigned int)(DIMM_Size >> 20);
}
/* Error Correcting Code */
TIMING(mc, cha).ECC = \
RO(Proc)->Uncore.MC[mc].SLM.BIOS_CFG.EFF_ECC_EN
| RO(Proc)->Uncore.MC[mc].SLM.BIOS_CFG.ECC_EN;
}
if (RO(Proc)->Uncore.MC[mc].SLM.DRP.DRAMTYPE) {
RO(Shm)->Uncore.Unit.DDR_Ver = 2;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_LPDDR;
} else {
RO(Shm)->Uncore.Unit.DDR_Ver = 3;
if (RO(Proc)->Uncore.MC[mc].SLM.DRP.ENLPDDR3) {
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_LPDDR;
} else {
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_SDRAM;
}
}
}
}
void AMT_MCR(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc), RO(CORE) *RO(Core))
{
unsigned short mc, cha, slot;
/* BUS & DRAM frequency */
switch (RO(Proc)->Uncore.MC[0].SLM.DTR2.AMT.DFREQ) {
case 0b000:
RO(Shm)->Uncore.CtrlSpeed = 400LLU;
RO(Shm)->Uncore.Bus.Rate = 800;
break;
case 0b001:
RO(Shm)->Uncore.CtrlSpeed = 533LLU;
RO(Shm)->Uncore.Bus.Rate = 1066;
break;
case 0b010:
RO(Shm)->Uncore.CtrlSpeed = 666LLU;
RO(Shm)->Uncore.Bus.Rate = 1333;
break;
case 0b011:
RO(Shm)->Uncore.CtrlSpeed = 800LLU;
RO(Shm)->Uncore.Bus.Rate = 1600;
break;
case 0b100:
RO(Shm)->Uncore.CtrlSpeed = 933LLU;
RO(Shm)->Uncore.Bus.Rate = 1866;
break;
case 0b101:
RO(Shm)->Uncore.CtrlSpeed = 1066LLU;
RO(Shm)->Uncore.Bus.Rate = 2133;
break;
default:
RO(Shm)->Uncore.CtrlSpeed = 1066LLU;
RO(Shm)->Uncore.Bus.Rate = 2133;
break;
}
RO(Shm)->Uncore.Bus.Speed = (RO(Core)->Clock.Hz
* RO(Shm)->Uncore.Bus.Rate)
/ RO(Shm)->Proc.Features.Factory.Clock.Hz;
RO(Shm)->Uncore.Unit.Bus_Rate = MC_MTS;
RO(Shm)->Uncore.Unit.BusSpeed = MC_MTS;
RO(Shm)->Uncore.Unit.DDR_Rate = MC_NIL;
RO(Shm)->Uncore.Unit.DDRSpeed = MC_MHZ;
for (mc = 0; mc < RO(Shm)->Uncore.CtrlCount; mc++)
{
RO(Shm)->Uncore.MC[mc].SlotCount = RO(Proc)->Uncore.MC[mc].SlotCount;
RO(Shm)->Uncore.MC[mc].ChannelCount = RO(Proc)->Uncore.MC[mc].ChannelCount;
for (cha = 0; cha < RO(Shm)->Uncore.MC[mc].ChannelCount; cha++)
{
/* Standard Timings */
TIMING(mc, cha).tCL = RO(Proc)->Uncore.MC[mc].SLM.DTR0.AMT.tCL + 5;
TIMING(mc, cha).tRCD = RO(Proc)->Uncore.MC[mc].SLM.DTR0.AMT.tRCD + 5;
TIMING(mc, cha).tRP = RO(Proc)->Uncore.MC[mc].SLM.DTR0.AMT.tRP + 5;
TIMING(mc, cha).tRAS = RO(Proc)->Uncore.MC[mc].SLM.DTR1.AMT.tRAS + 14;
TIMING(mc, cha).tRRD = RO(Proc)->Uncore.MC[mc].SLM.DTR1.AMT.tRRD + 4;
TIMING(mc, cha).tRFC = \
RO(Proc)->Uncore.MC[mc].SLM.DTR0.AMT.tXS == 0 ? 256 : 384;
switch (RO(Proc)->Uncore.MC[mc].SLM.DRFC.AMT.tREFI) {
case 0 ... 1:
TIMING(mc, cha).tREFI = 0;
break;
case 2:
TIMING(mc, cha).tREFI = 39;
break;
case 3:
TIMING(mc, cha).tREFI = 78;
break;
}
TIMING(mc, cha).tREFI *= RO(Shm)->Uncore.CtrlSpeed;
TIMING(mc, cha).tREFI /= 20;
TIMING(mc, cha).tCKE = RO(Proc)->Uncore.MC[mc].SLM.DRMC.AMT.CKEVAL;
TIMING(mc, cha).tRTPr= RO(Proc)->Uncore.MC[mc].SLM.DTR1.AMT.tRTP + 4;
TIMING(mc, cha).tWTPr= RO(Proc)->Uncore.MC[mc].SLM.DTR1.AMT.tWTP + 15;
switch (RO(Proc)->Uncore.MC[mc].SLM.DTR1.AMT.tCCD) {
case 0:
TIMING(mc, cha).B2B = 4;
break;
case 1:
TIMING(mc, cha).B2B = 12;
break;
case 2:
TIMING(mc, cha).B2B = 18;
break;
case 3:
default:
TIMING(mc, cha).B2B = 0;
break;
}
switch (RO(Proc)->Uncore.MC[mc].SLM.DTR1.AMT.tFAW) {
case 0 ... 1:
case 0xd ... 0xf:
TIMING(mc, cha).tFAW = 0;
break;
default:
TIMING(mc, cha).tFAW = \
10 + ((unsigned int)RO(Proc)->Uncore.MC[mc].SLM.DTR1.AMT.tFAW << 1);
break;
}
TIMING(mc, cha).tCWL = RO(Proc)->Uncore.MC[mc].SLM.DTR1.AMT.tWCL + 3;
/*TODO( Read to Read. Same Rank )
TIMING(mc, cha).tsrRdTRd = RO(Proc)->Uncore.MC[mc].SLM.DTR?.;
*/
TIMING(mc, cha).tsrRdTWr = 6
+ RO(Proc)->Uncore.MC[mc].SLM.DTR3.AMT.tRWSR;
TIMING(mc, cha).tsrWrTRd = 11
+ RO(Proc)->Uncore.MC[mc].SLM.DTR3.AMT.tWRSR;
/*TODO( Write to Write. Same Rank )
TIMING(mc, cha).tsrWrTWr = RO(Proc)->Uncore.MC[mc].SLM.DTR?.;
*/
/* Different Rank */
TIMING(mc, cha).tdrRdTRd = RO(Proc)->Uncore.MC[mc].SLM.DTR2.AMT.tRRDR;
if (TIMING(mc, cha).tdrRdTRd > 0) {
TIMING(mc, cha).tdrRdTRd += 5;
}
TIMING(mc, cha).tdrRdTWr = RO(Proc)->Uncore.MC[mc].SLM.DTR2.AMT.tRWDR;
if (TIMING(mc, cha).tdrRdTWr > 0) {
TIMING(mc, cha).tdrRdTWr += 5;
}
TIMING(mc, cha).tdrWrTRd = RO(Proc)->Uncore.MC[mc].SLM.DTR3.AMT.tWRDR;
if (TIMING(mc, cha).tdrWrTRd > 0) {
TIMING(mc, cha).tdrWrTRd += 3;
}
TIMING(mc, cha).tdrWrTWr = RO(Proc)->Uncore.MC[mc].SLM.DTR2.AMT.tWWDR;
if (TIMING(mc, cha).tdrWrTWr > 1) {
TIMING(mc, cha).tdrWrTWr += 4;
}
/*TODO( Different DIMM )
TIMING(mc, cha).tddRdTRd = RO(Proc)->Uncore.MC[mc].SLM.DTR2.AMT.tRRDD;
TIMING(mc, cha).tddRdTWr = RO(Proc)->Uncore.MC[mc].SLM.DTR2.AMT.tRWDD;
TIMING(mc, cha).tddWrTRd = RO(Proc)->Uncore.MC[mc].SLM.DTR3.AMT.tWRDD;
TIMING(mc, cha).tddWrTWr = RO(Proc)->Uncore.MC[mc].SLM.DTR2.AMT.tWWDD;
*/
/* Command Rate */
TIMING(mc, cha).CMD_Rate = 1
+ RO(Proc)->Uncore.MC[mc].SLM.DTR1.AMT.tCMD;
TIMING(mc, cha).tXS = RO(Proc)->Uncore.MC[mc].SLM.DTR0.AMT.tXS;
TIMING(mc, cha).tXP = RO(Proc)->Uncore.MC[mc].SLM.DTR3.AMT.tXP;
/* Topology */
for (slot = 0; slot < RO(Shm)->Uncore.MC[mc].SlotCount; slot++)
{
unsigned long long DIMM_Size;
const struct {
unsigned int Banks,
Rows,
Cols;
} DDR3L[4] = {
{ .Banks = 8, .Rows = 1<<14, .Cols = 1<<10 },
{ .Banks = 8, .Rows = 1<<15, .Cols = 1<<10 },
{ .Banks = 8, .Rows = 1<<16, .Cols = 1<<10 },
{ .Banks = 8, .Rows = 1<<14, .Cols = 1<<10 }
};
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks = \
RO(Proc)->Uncore.MC[mc].SLM.DRP.AMT.RKEN0
+ RO(Proc)->Uncore.MC[mc].SLM.DRP.AMT.RKEN1;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks = \
DDR3L[RO(Proc)->Uncore.MC[mc].SLM.DRP.AMT.DIMMDDEN0].Banks;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows = \
DDR3L[RO(Proc)->Uncore.MC[mc].SLM.DRP.AMT.DIMMDDEN0].Rows;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols = \
DDR3L[RO(Proc)->Uncore.MC[mc].SLM.DRP.AMT.DIMMDDEN0].Cols;
DIMM_Size = 8LLU
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Size = \
(unsigned int)(DIMM_Size >> 20);
}
/* Error Correcting Code */
TIMING(mc, cha).ECC = RO(Proc)->Uncore.MC[mc].SLM.BIOS_CFG.ECC_EN;
}
if (RO(Proc)->Uncore.MC[mc].SLM.DRP.AMT.DRAMTYPE) {
RO(Shm)->Uncore.Unit.DDR_Ver = 2;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_LPDDR;
} else {
RO(Shm)->Uncore.Unit.DDR_Ver = 3;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_SDRAM;
}
}
}
void NHM_IMC(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc))
{
unsigned short mc, cha, slot;
for (mc = 0; mc < RO(Shm)->Uncore.CtrlCount; mc++)
{
RO(Shm)->Uncore.MC[mc].SlotCount = RO(Proc)->Uncore.MC[mc].SlotCount;
RO(Shm)->Uncore.MC[mc].ChannelCount = RO(Proc)->Uncore.MC[mc].ChannelCount;
for (cha = 0; cha < RO(Shm)->Uncore.MC[mc].ChannelCount; cha++)
{
TIMING(mc, cha).tCL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.MR0_1.tCL ?
4 + RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.MR0_1.tCL : 0;
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.MR0_1.tWR) {
case 0b001:
TIMING(mc, cha).tWR = 5;
break;
case 0b010:
TIMING(mc, cha).tWR = 6;
break;
case 0b011:
TIMING(mc, cha).tWR = 7;
break;
case 0b100:
TIMING(mc, cha).tWR = 8;
break;
case 0b101:
TIMING(mc, cha).tWR = 10;
break;
case 0b110:
TIMING(mc, cha).tWR = 12;
break;
}
TIMING(mc, cha).tRCD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.Bank.tRCD;
TIMING(mc, cha).tRP = \
RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.Bank.tRP;
TIMING(mc, cha).tRAS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.Bank.tRAS;
TIMING(mc, cha).tRRD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.Rank_B.tRRD;
TIMING(mc, cha).tRFC = \
RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.Refresh.tRFC;
TIMING(mc, cha).tREFI = \
RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.Refresh.tREFI_8;
TIMING(mc, cha).tCKE = \
RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.CKE_Timing.tCKE;
TIMING(mc, cha).tXS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.CKE_Timing.tXS;
TIMING(mc, cha).tXP = \
RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.CKE_Timing.tXP;
TIMING(mc, cha).tRTPr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.Bank.tRTPr;
TIMING(mc, cha).tWTPr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.Bank.tWTPr;
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.Rank_A.tsrRdTRd) {
case 0b0:
TIMING(mc, cha).tsrRdTRd = 4;
break;
case 0b1:
TIMING(mc, cha).tsrRdTRd = 6;
break;
}
TIMING(mc, cha).tdrRdTRd = 2
+ RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.Rank_A.tdrRdTRd;
TIMING(mc, cha).tddRdTRd = 2
+ RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.Rank_A.tddRdTRd;
TIMING(mc, cha).tsrRdTWr = 2
+ RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.Rank_A.tsrRdTWr;
TIMING(mc, cha).tdrRdTWr = 2
+ RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.Rank_A.tdrRdTWr;
TIMING(mc, cha).tddRdTWr = 2
+ RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.Rank_A.tddRdTWr;
TIMING(mc, cha).tsrWrTRd = 10
+ RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.Rank_A.tsrWrTRd;
TIMING(mc, cha).tdrWrTRd = 1
+ RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.Rank_A.tdrWrTRd;
TIMING(mc, cha).tddWrTRd = 1
+ RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.Rank_A.tddWrTRd;
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.Rank_B.tsrWrTWr) {
case 0b0:
TIMING(mc, cha).tsrWrTWr = 4;
break;
case 0b1:
TIMING(mc, cha).tsrWrTWr = 6;
break;
}
TIMING(mc, cha).tdrWrTWr = 2
+ RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.Rank_B.tdrWrTWr;
TIMING(mc, cha).tddWrTWr = 2
+ RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.Rank_B.tddWrTWr;
TIMING(mc, cha).tFAW = \
RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.Rank_B.tFAW;
TIMING(mc, cha).B2B = \
RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.Rank_B.B2B;
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.MR2_3.tCWL) {
case 0b000:
TIMING(mc, cha).tCWL = 5;
break;
case 0b001:
TIMING(mc, cha).tCWL = 6;
break;
case 0b010:
TIMING(mc, cha).tCWL = 7;
break;
case 0b011:
TIMING(mc, cha).tCWL = 8;
break;
}
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.Sched.ENABLE_2N_3N)
{
case 0b00:
TIMING(mc, cha).CMD_Rate = 1;
break;
case 0b01:
TIMING(mc, cha).CMD_Rate = 2;
break;
case 0b10:
TIMING(mc, cha).CMD_Rate = 3;
break;
}
if (RO(Proc)->Uncore.MC[mc].Channel[cha].NHM.DIMM_Init.REGISTERED_DIMM)
{
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_RDIMM;
} else {
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_SDRAM;
}
for (slot = 0; slot < RO(Shm)->Uncore.MC[mc].SlotCount; slot++) {
if (RO(Proc)->Uncore.MC[mc].Channel[cha].DIMM[slot].DOD.DIMMPRESENT)
{
unsigned long long DIMM_Size;
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].DIMM[slot].DOD.NUMBANK)
{
case 0b00:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks = 4;
break;
case 0b01:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks = 8;
break;
case 0b10:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks = 16;
break;
}
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].DIMM[slot].DOD.NUMRANK)
{
case 0b00:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks = 1;
break;
case 0b01:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks = 2;
break;
case 0b10:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks = 4;
break;
}
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].DIMM[slot].DOD.NUMROW)
{
case 0b000:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows = 1 << 12;
break;
case 0b001:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows = 1 << 13;
break;
case 0b010:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows = 1 << 14;
break;
case 0b011:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows = 1 << 15;
break;
case 0b100:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows = 1 << 16;
break;
}
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].DIMM[slot].DOD.NUMCOL)
{
case 0b000:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols = 1 << 10;
break;
case 0b001:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols = 1 << 11;
break;
case 0b010:
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols = 1 << 12;
break;
}
DIMM_Size = 8LLU
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Size = \
(unsigned int)(DIMM_Size >> 20);
}
}
TIMING(mc, cha).ECC = (unsigned int)\
( RO(Proc)->Uncore.MC[mc].NHM.STATUS.ECC_ENABLED
& RO(Proc)->Uncore.MC[mc].NHM.CONTROL.ECC_ENABLED );
}
}
}
void QPI_CLK(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc), RO(CORE) *RO(Core))
{
switch (RO(Proc)->Uncore.Bus.DimmClock.QCLK_RATIO) {
case 0b00110:
RO(Shm)->Uncore.CtrlSpeed = 800;
break;
case 0b01000:
RO(Shm)->Uncore.CtrlSpeed = 1066;
break;
case 0b01010:
RO(Shm)->Uncore.CtrlSpeed = 1333;
break;
case 0b01100:
RO(Shm)->Uncore.CtrlSpeed = 1600;
break;
case 0b01110:
RO(Shm)->Uncore.CtrlSpeed = 1866;
break;
case 0b10000:
RO(Shm)->Uncore.CtrlSpeed = 2133;
break;
case 0b000000:
fallthrough;
default:
RO(Shm)->Uncore.CtrlSpeed = 800;
break;
}
RO(Shm)->Uncore.CtrlSpeed *= RO(Core)->Clock.Hz;
RO(Shm)->Uncore.CtrlSpeed /= RO(Shm)->Proc.Features.Factory.Clock.Hz;
RO(Shm)->Uncore.Bus.Rate = \
RO(Proc)->Uncore.Bus.QuickPath.X58.QPIFREQSEL == 0b00 ?
4800 : RO(Proc)->Uncore.Bus.QuickPath.X58.QPIFREQSEL == 0b10 ?
6400 : RO(Proc)->Uncore.Bus.QuickPath.X58.QPIFREQSEL == 0b01 ?
5866 : 6400;
RO(Shm)->Uncore.Bus.Speed = (RO(Core)->Clock.Hz
* RO(Shm)->Uncore.Bus.Rate)
/ RO(Shm)->Proc.Features.Factory.Clock.Hz;
RO(Shm)->Uncore.Unit.Bus_Rate = MC_MTS;
RO(Shm)->Uncore.Unit.BusSpeed = MC_MTS;
RO(Shm)->Uncore.Unit.DDR_Rate = MC_NIL;
RO(Shm)->Uncore.Unit.DDRSpeed = MC_MHZ;
RO(Shm)->Uncore.Unit.DDR_Ver = 3;
}
void X58_VTD(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc), RO(CORE) *RO(Core))
{
UNUSED(RO(Core));
RO(Shm)->Proc.Technology.IOMMU = \
!RO(Proc)->Uncore.Bus.QuickPath.X58.VT_d;
RO(Shm)->Proc.Technology.IOMMU_Ver_Major = \
RO(Proc)->Uncore.Bus.IOMMU_Ver.Major;
RO(Shm)->Proc.Technology.IOMMU_Ver_Minor = \
RO(Proc)->Uncore.Bus.IOMMU_Ver.Minor;
}
void DMI_CLK(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc), RO(CORE) *RO(Core))
{
switch (RO(Proc)->Uncore.Bus.DimmClock.QCLK_RATIO) {
case 0b00010:
RO(Shm)->Uncore.CtrlSpeed = 266;
break;
case 0b00100:
RO(Shm)->Uncore.CtrlSpeed = 533;
break;
case 0b00110:
RO(Shm)->Uncore.CtrlSpeed = 800;
break;
case 0b01000:
RO(Shm)->Uncore.CtrlSpeed = 1066;
break;
case 0b01010:
RO(Shm)->Uncore.CtrlSpeed = 1333;
break;
case 0b000000:
fallthrough;
default:
RO(Shm)->Uncore.CtrlSpeed = 266;
break;
}
RO(Shm)->Uncore.CtrlSpeed *= RO(Core)->Clock.Hz;
RO(Shm)->Uncore.CtrlSpeed /= RO(Shm)->Proc.Features.Factory.Clock.Hz;
RO(Shm)->Uncore.Bus.Rate = 2500; /* TODO: hardwired to Lynnfield */
RO(Shm)->Uncore.Bus.Speed = (RO(Core)->Clock.Hz
* RO(Shm)->Uncore.Bus.Rate)
/ RO(Shm)->Proc.Features.Factory.Clock.Hz;
RO(Shm)->Uncore.Unit.Bus_Rate = MC_MTS;
RO(Shm)->Uncore.Unit.BusSpeed = MC_MTS;
RO(Shm)->Uncore.Unit.DDR_Rate = MC_NIL;
RO(Shm)->Uncore.Unit.DDRSpeed = MC_MHZ;
RO(Shm)->Uncore.Unit.DDR_Ver = 3;
}
unsigned int SNB_DimmWidthToRows(unsigned int width)
{
return 1 << (15 + width);
}
void SNB_IMC(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc))
{
unsigned short mc, cha, slot;
for (mc = 0; mc < RO(Shm)->Uncore.CtrlCount; mc++)
{
const unsigned short dimmSize[2][2] = {
{
RO(Proc)->Uncore.MC[mc].SNB.MAD0.Dimm_A_Size,
RO(Proc)->Uncore.MC[mc].SNB.MAD0.Dimm_B_Size
}, {
RO(Proc)->Uncore.MC[mc].SNB.MAD1.Dimm_A_Size,
RO(Proc)->Uncore.MC[mc].SNB.MAD1.Dimm_B_Size
}
};
RO(Shm)->Uncore.MC[mc].SlotCount = RO(Proc)->Uncore.MC[mc].SlotCount;
RO(Shm)->Uncore.MC[mc].ChannelCount = RO(Proc)->Uncore.MC[mc].ChannelCount;
for (cha = 0; cha < RO(Shm)->Uncore.MC[mc].ChannelCount; cha++)
{
TIMING(mc, cha).tCL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.DBP.tCL;
TIMING(mc, cha).tRCD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.DBP.tRCD;
TIMING(mc, cha).tRP = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.DBP.tRP;
TIMING(mc, cha).tRAS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.DBP.tRAS;
TIMING(mc, cha).tRRD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.RAP.tRRD;
TIMING(mc, cha).tRFC = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.RFTP.tRFC;
TIMING(mc, cha).tREFI = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.RFTP.tREFI;
TIMING(mc, cha).tWR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.RAP.tWR;
TIMING(mc, cha).tRTPr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.RAP.tRTPr;
TIMING(mc, cha).tWTPr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.RAP.tWTPr;
TIMING(mc, cha).tFAW = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.RAP.tFAW;
TIMING(mc, cha).tCKE = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.RAP.tCKE;
TIMING(mc, cha).tCWL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.DBP.tCWL;
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.RAP.CMD_Stretch) {
case 0b00:
TIMING(mc, cha).CMD_Rate = 1;
break;
case 0b10:
TIMING(mc, cha).CMD_Rate = 2;
break;
case 0b11:
TIMING(mc, cha).CMD_Rate = 3;
break;
default:
TIMING(mc, cha).CMD_Rate = 0;
break;
}
TIMING(mc, cha).tddWrTRd = 1
+ RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.RWP.tWRDD;
TIMING(mc, cha).tdrWrTRd = 1
+ RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.RWP.tWRDR;
TIMING(mc, cha).tsrWrTRd = 1
+ RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.OTP.tWRSR;
TIMING(mc, cha).tddRdTWr = 1
+ RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.RWP.tRWDD;
TIMING(mc, cha).tdrRdTWr = 1
+ RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.RWP.tRWDR;
TIMING(mc, cha).tsrRdTWr = 1
+ RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.RWP.tRWSR;
TIMING(mc, cha).tddRdTRd = 1
+ RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.OTP.tRRDD;
TIMING(mc, cha).tdrRdTRd = 1
+ RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.RWP.tRRDR;
TIMING(mc, cha).tsrRdTRd = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.RWP.tRRSR;
TIMING(mc, cha).tddWrTWr = 1
+ RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.RWP.tWWDD;
TIMING(mc, cha).tdrWrTWr = 1
+ RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.RWP.tWWDR;
TIMING(mc, cha).tsrWrTWr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.RWP.tWWSR;
TIMING(mc, cha).B2B = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.RWP.tCCD;
TIMING(mc, cha).tXS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.SRFTP.tXS;
TIMING(mc, cha).PDM_EN = \
0 != RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.PDWN.PDWN_Mode;
TIMING(mc, cha).PDM_MODE = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.PDWN.GLPDN;
TIMING(mc, cha).PDM_AGGR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB.PDWN.PDWN_Mode;
for (slot = 0; slot < RO(Shm)->Uncore.MC[mc].SlotCount; slot++)
{
unsigned long long DIMM_Banks;
const unsigned short
Dimm_A_Map = cha & 1 ? RO(Proc)->Uncore.MC[mc].SNB.MAD1.DAS
: RO(Proc)->Uncore.MC[mc].SNB.MAD0.DAS;
if (slot == Dimm_A_Map)
{
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks = \
cha & 1 ? RO(Proc)->Uncore.MC[mc].SNB.MAD1.DANOR
: RO(Proc)->Uncore.MC[mc].SNB.MAD0.DANOR;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows = \
SNB_DimmWidthToRows(cha & 1 ? RO(Proc)->Uncore.MC[mc].SNB.MAD1.DAW
: RO(Proc)->Uncore.MC[mc].SNB.MAD0.DAW);
}
else
{
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks = \
cha & 1 ? RO(Proc)->Uncore.MC[mc].SNB.MAD1.DBNOR
: RO(Proc)->Uncore.MC[mc].SNB.MAD0.DBNOR;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows = \
SNB_DimmWidthToRows(cha & 1 ? RO(Proc)->Uncore.MC[mc].SNB.MAD1.DBW
: RO(Proc)->Uncore.MC[mc].SNB.MAD0.DBW);
}
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks++;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols = 1 << 10;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Size = \
dimmSize[cha][(slot ^ Dimm_A_Map) % 2] * 256;
DIMM_Banks = RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Size;
DIMM_Banks = DIMM_Banks * 1024LLU * 1024LLU;
DIMM_Banks = DIMM_Banks
/ (8LLU * RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols);
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks = DIMM_Banks;
}
TIMING(mc, cha).ECC = (cha == 0) ?
RO(Proc)->Uncore.MC[mc].SNB.MAD0.ECC
: RO(Proc)->Uncore.MC[mc].SNB.MAD1.ECC;
}
}
}
unsigned long long SNB_MCLK_FSB(RO(PROC) *RO(Proc),
const unsigned long long fallback)
{
switch (RO(Proc)->Uncore.Bus.ClkCfg.FSB_Select) {
case 0b111:
return 1067;
case 0b110:
return 1333;
case 0b101:
return 1600;
case 0b100:
return 1867;
case 0b011:
return 2133;
case 0b010:
return 2400;
case 0b001:
return 2667;
case 0b000:
return fallback;
}
return fallback;
}
unsigned long long SNB_MCLK_RAM(RO(PROC) *RO(Proc),
const unsigned long long fallback)
{
switch (RO(Proc)->Uncore.Bus.ClkCfg.RAM_Select) {
case 0b111:
return 1067;
case 0b110:
return 1333;
case 0b101:
return 1600;
case 0b100:
return 1867;
case 0b011:
return 2133;
case 0b010:
return 2400;
case 0b001:
return 2667;
case 0b000:
return SNB_MCLK_FSB(RO(Proc), fallback);
}
return fallback;
}
unsigned short BIOS_DDR(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc),
RO(CORE) *RO(Core))
{
UNUSED(RO(Core));
if (RO(Proc)->Uncore.Bus.BIOS_DDR.MEMCLK != 0)
{
RO(Shm)->Uncore.CtrlSpeed = RO(Proc)->Uncore.Bus.BIOS_DDR.MEMCLK;
if (RO(Proc)->Uncore.Bus.BIOS_DDR.PLL_REF100 == 1) {
RO(Shm)->Uncore.CtrlSpeed = 200 * RO(Shm)->Uncore.CtrlSpeed;
} else {
RO(Shm)->Uncore.CtrlSpeed = 800 * RO(Shm)->Uncore.CtrlSpeed;
RO(Shm)->Uncore.CtrlSpeed = RO(Shm)->Uncore.CtrlSpeed / 3;
}
return RO(Shm)->Uncore.CtrlSpeed;
}
return 0;
}
void SNB_CAP(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc), RO(CORE) *RO(Core))
{
if (BIOS_DDR(RO(Shm), RO(Proc), RO(Core)) == 0) {
switch (RO(Proc)->Uncore.Bus.SNB_Cap.DMFC) {
case 0b111:
RO(Shm)->Uncore.CtrlSpeed = SNB_MCLK_RAM(RO(Proc), 1067);
break;
case 0b110:
RO(Shm)->Uncore.CtrlSpeed = SNB_MCLK_RAM(RO(Proc), 1333);
break;
case 0b101:
RO(Shm)->Uncore.CtrlSpeed = SNB_MCLK_RAM(RO(Proc), 1600);
break;
case 0b100:
RO(Shm)->Uncore.CtrlSpeed = SNB_MCLK_RAM(RO(Proc), 1867);
break;
case 0b011:
RO(Shm)->Uncore.CtrlSpeed = SNB_MCLK_RAM(RO(Proc), 2133);
break;
case 0b010:
RO(Shm)->Uncore.CtrlSpeed = SNB_MCLK_RAM(RO(Proc), 2400);
break;
case 0b001:
RO(Shm)->Uncore.CtrlSpeed = SNB_MCLK_RAM(RO(Proc), 2667);
break;
case 0b000:
RO(Shm)->Uncore.CtrlSpeed = SNB_MCLK_RAM(RO(Proc), 2933);
break;
}
}
RO(Shm)->Uncore.Bus.Rate = RO(Shm)->Uncore.CtrlSpeed;
RO(Shm)->Uncore.Bus.Speed = (RO(Core)->Clock.Hz
* RO(Shm)->Uncore.Bus.Rate)
/ RO(Shm)->Proc.Features.Factory.Clock.Hz;
RO(Shm)->Uncore.Unit.Bus_Rate = MC_MHZ;
RO(Shm)->Uncore.Unit.BusSpeed = MC_MHZ;
RO(Shm)->Uncore.Unit.DDR_Rate = MC_NIL;
RO(Shm)->Uncore.Unit.DDRSpeed = MC_MHZ;
RO(Shm)->Uncore.Unit.DDR_Ver = 3;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_UNSPEC;
RO(Shm)->Proc.Technology.IOMMU = !RO(Proc)->Uncore.Bus.SNB_Cap.VT_d;
}
void SNB_EP_IMC(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc))
{
unsigned short mc, cha, slot;
for (mc = 0; mc < RO(Shm)->Uncore.CtrlCount; mc++)
{
RO(Shm)->Uncore.MC[mc].SlotCount = RO(Proc)->Uncore.MC[mc].SlotCount;
RO(Shm)->Uncore.MC[mc].ChannelCount = RO(Proc)->Uncore.MC[mc].ChannelCount;
for (cha = 0; cha < RO(Shm)->Uncore.MC[mc].ChannelCount; cha++)
{
TIMING(mc, cha).tCL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.DBP.EP.tCL;
TIMING(mc, cha).tRCD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.DBP.EP.tRCD;
TIMING(mc, cha).tRP = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.DBP.EP.tRP;
TIMING(mc, cha).tCWL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.DBP.EP.tCWL;
TIMING(mc, cha).tRAS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.DBP.EP.tRAS;
TIMING(mc, cha).tRRD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.RAP.EP.tRRD;
TIMING(mc, cha).tRFC = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.RFTP.EP.tRFC;
TIMING(mc, cha).tREFI = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.RFTP.EP.tREFI;
TIMING(mc, cha).tWR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.RAP.EP.tWR;
TIMING(mc, cha).tRTPr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.RAP.EP.tRTPr;
TIMING(mc, cha).tWTPr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.RAP.EP.tWTPr;
TIMING(mc, cha).tFAW = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.RAP.EP.tFAW;
TIMING(mc, cha).tCKE = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.RAP.EP.tCKE;
TIMING(mc, cha).tddWrTRd = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.RWP.EP.tWRDD;
TIMING(mc, cha).tdrWrTRd = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.RWP.EP.tWRDR;
/*TODO
TIMING(mc, cha).tsrWrTRd = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.???.EP.t????;
*/
TIMING(mc, cha).tddRdTWr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.OTP.EP.tRWDD;
TIMING(mc, cha).tdrRdTWr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.OTP.EP.tRWDR;
TIMING(mc, cha).tsrRdTWr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.OTP.EP.tRWSR;
TIMING(mc, cha).tddRdTRd = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.RWP.EP.tRRDD;
TIMING(mc, cha).tdrRdTRd = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.RWP.EP.tRRDR;
/* TODO
TIMING(mc, cha).tsrRdTRd = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.???.EP.t????;
*/
TIMING(mc, cha).tddWrTWr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.RWP.EP.tWWDD;
TIMING(mc, cha).tdrWrTWr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.RWP.EP.tWWDR;
/* TODO
TIMING(mc, cha).tsrWrTWr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.???.EP.t????;
*/
TIMING(mc, cha).B2B = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.RWP.EP.tCCD;
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.RAP.EP.CMD_Stretch)
{
case 0b00:
TIMING(mc, cha).CMD_Rate = 1;
break;
case 0b10:
TIMING(mc, cha).CMD_Rate = 2;
break;
case 0b11:
TIMING(mc, cha).CMD_Rate = 3;
break;
default:
TIMING(mc, cha).CMD_Rate = 0;
break;
}
TIMING(mc, cha).tXS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.SRFTP.EP.tXS_DLL;
TIMING(mc, cha).tXP = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SNB_EP.OTP.EP.tXP;
for (slot = 0; slot < RO(Shm)->Uncore.MC[mc].SlotCount; slot++)
{
if (RO(Proc)->Uncore.MC[mc].Channel[cha].DIMM[slot].MTR.DIMM_POP)
{
unsigned long long DIMM_Size;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks = 4 << \
RO(Proc)->Uncore.MC[mc].Channel[cha].DIMM[slot].MTR.DDR3_WIDTH;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks = 1 << \
RO(Proc)->Uncore.MC[mc].Channel[cha].DIMM[slot].MTR.RANK_CNT;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows = 1 << ( 13
+ RO(Proc)->Uncore.MC[mc].Channel[cha].DIMM[slot].MTR.RA_WIDTH);
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols = 1 << ( 10
+ RO(Proc)->Uncore.MC[mc].Channel[cha].DIMM[slot].MTR.CA_WIDTH);
DIMM_Size = 8LLU
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Size = \
(unsigned int)(DIMM_Size >> 20);
}
}
TIMING(mc, cha).ECC = (unsigned int)\
( RO(Proc)->Uncore.MC[mc].SNB_EP.TECH.ECC_EN
& !RO(Proc)->Uncore.Bus.SNB_EP_Cap3.ECC_DIS );
}
}
}
void SNB_EP_CAP(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc), RO(CORE) *RO(Core))
{
switch (RO(Proc)->Uncore.Bus.SNB_EP_Cap1.DMFC) {
case 0b111:
RO(Shm)->Uncore.CtrlSpeed = 1066;
break;
case 0b110:
RO(Shm)->Uncore.CtrlSpeed = 1333;
break;
case 0b101:
RO(Shm)->Uncore.CtrlSpeed = 1600;
break;
case 0b100:
RO(Shm)->Uncore.CtrlSpeed = 1866;
break;
case 0b011:
RO(Shm)->Uncore.CtrlSpeed = 2133;
break;
case 0b010:
RO(Shm)->Uncore.CtrlSpeed = 2400;
break;
case 0b001:
RO(Shm)->Uncore.CtrlSpeed = 2666;
break;
case 0b000:
RO(Shm)->Uncore.CtrlSpeed = 2933;
break;
}
RO(Shm)->Uncore.CtrlSpeed *= RO(Core)->Clock.Hz;
RO(Shm)->Uncore.CtrlSpeed /= RO(Shm)->Proc.Features.Factory.Clock.Hz;
RO(Shm)->Uncore.Bus.Rate = \
RO(Proc)->Uncore.Bus.QuickPath.EP.QPIFREQSEL == 0b010 ?
5600 : RO(Proc)->Uncore.Bus.QuickPath.EP.QPIFREQSEL == 0b011 ?
6400 : RO(Proc)->Uncore.Bus.QuickPath.EP.QPIFREQSEL == 0b100 ?
7200 : RO(Proc)->Uncore.Bus.QuickPath.EP.QPIFREQSEL == 0b101 ?
8000 : 5000;
RO(Shm)->Uncore.Bus.Speed = (RO(Core)->Clock.Hz
* RO(Shm)->Uncore.Bus.Rate)
/ RO(Shm)->Proc.Features.Factory.Clock.Hz;
RO(Shm)->Uncore.Unit.Bus_Rate = MC_MTS;
RO(Shm)->Uncore.Unit.BusSpeed = MC_MTS;
RO(Shm)->Uncore.Unit.DDR_Rate = MC_NIL;
RO(Shm)->Uncore.Unit.DDRSpeed = MC_MHZ;
RO(Shm)->Uncore.Unit.DDR_Ver = 3;
if (RO(Proc)->Uncore.Bus.SNB_EP_Cap3.RDIMM_DIS)
{
if (RO(Proc)->Uncore.Bus.SNB_EP_Cap3.UDIMM_DIS) {
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_UNSPEC;
} else {
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_SDRAM;
}
} else {
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_RDIMM;
}
}
void IVB_CAP(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc), RO(CORE) *RO(Core))
{
if (BIOS_DDR(RO(Shm), RO(Proc), RO(Core)) == 0) {
switch (RO(Proc)->Uncore.Bus.IVB_Cap.DMFC) {
case 0b111:
RO(Shm)->Uncore.CtrlSpeed = SNB_MCLK_RAM(RO(Proc), 1067);
break;
case 0b110:
RO(Shm)->Uncore.CtrlSpeed = SNB_MCLK_RAM(RO(Proc), 1333);
break;
case 0b101:
RO(Shm)->Uncore.CtrlSpeed = SNB_MCLK_RAM(RO(Proc), 1600);
break;
case 0b100:
RO(Shm)->Uncore.CtrlSpeed = SNB_MCLK_RAM(RO(Proc), 1867);
break;
case 0b011:
RO(Shm)->Uncore.CtrlSpeed = SNB_MCLK_RAM(RO(Proc), 2133);
break;
case 0b010:
RO(Shm)->Uncore.CtrlSpeed = SNB_MCLK_RAM(RO(Proc), 2400);
break;
case 0b001:
RO(Shm)->Uncore.CtrlSpeed = SNB_MCLK_RAM(RO(Proc), 2667);
break;
case 0b000:
switch (RO(Proc)->ArchID) {
case IvyBridge:
case Haswell_ULT:
RO(Shm)->Uncore.CtrlSpeed = SNB_MCLK_RAM(RO(Proc),2933);
break;
case Haswell_DT:
case Haswell_EP:
case Haswell_ULX:
RO(Shm)->Uncore.CtrlSpeed = SNB_MCLK_RAM(RO(Proc),2667);
break;
case Broadwell:
case Broadwell_D:
case Broadwell_H:
case Broadwell_EP:
RO(Shm)->Uncore.CtrlSpeed = SNB_MCLK_RAM(RO(Proc),3200);
break;
}
break;
}
}
RO(Shm)->Uncore.Bus.Rate = RO(Shm)->Uncore.CtrlSpeed;
RO(Shm)->Uncore.Bus.Speed = (RO(Core)->Clock.Hz
* RO(Shm)->Uncore.Bus.Rate)
/ RO(Shm)->Proc.Features.Factory.Clock.Hz;
RO(Shm)->Uncore.Unit.Bus_Rate = MC_MHZ;
RO(Shm)->Uncore.Unit.BusSpeed = MC_MHZ;
RO(Shm)->Uncore.Unit.DDR_Rate = MC_NIL;
RO(Shm)->Uncore.Unit.DDRSpeed = MC_MHZ;
RO(Shm)->Uncore.Unit.DDR_Ver = 3;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_UNSPEC;
RO(Shm)->Proc.Technology.IOMMU = !RO(Proc)->Uncore.Bus.SNB_Cap.IVB.VT_d;
RO(Shm)->Proc.Technology.OC = RO(Proc)->Uncore.Bus.IVB_Cap.OC_ENABLED;
}
unsigned int DimmWidthToRows(unsigned int width)
{
unsigned int rows = 0;
switch (width) {
case 0b00:
rows = 8;
break;
case 0b01:
rows = 16;
break;
case 0b10:
rows = 32;
break;
}
return (8 * 1024 * rows);
}
void HSW_IMC(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc))
{
unsigned short mc, cha, slot;
for (mc = 0; mc < RO(Shm)->Uncore.CtrlCount; mc++)
{
const unsigned short dimmSize[2][2] = {
{
RO(Proc)->Uncore.MC[mc].SNB.MAD0.Dimm_A_Size,
RO(Proc)->Uncore.MC[mc].SNB.MAD0.Dimm_B_Size
}, {
RO(Proc)->Uncore.MC[mc].SNB.MAD1.Dimm_A_Size,
RO(Proc)->Uncore.MC[mc].SNB.MAD1.Dimm_B_Size
}
};
RO(Shm)->Uncore.MC[mc].SlotCount = RO(Proc)->Uncore.MC[mc].SlotCount;
RO(Shm)->Uncore.MC[mc].ChannelCount=RO(Proc)->Uncore.MC[mc].ChannelCount;
for (cha = 0; cha < RO(Shm)->Uncore.MC[mc].ChannelCount; cha++)
{
TIMING(mc, cha).tCL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].HSW.Rank.tCL;
TIMING(mc, cha).tCWL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].HSW.Rank.tCWL;
/*TODO(Not Found)
TIMING(mc, cha).tWR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].HSW._.tWR;
TIMING(mc, cha).tFAW = \
RO(Proc)->Uncore.MC[mc].Channel[cha].HSW._.tFAW;
*/
TIMING(mc, cha).tRP = \
RO(Proc)->Uncore.MC[mc].Channel[cha].HSW.REG4C00.tRP;
TIMING(mc, cha).tRRD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].HSW.REG4C00.tRRD;
TIMING(mc, cha).tRCD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].HSW.REG4C00.tRCD;
TIMING(mc, cha).tRAS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].HSW.REG4C00.tRAS;
TIMING(mc, cha).tRFC = \
RO(Proc)->Uncore.MC[mc].Channel[cha].HSW.Refresh.tRFC;
TIMING(mc, cha).tREFI = \
RO(Proc)->Uncore.MC[mc].Channel[cha].HSW.Refresh.tREFI;
TIMING(mc, cha).tsrRdTRd = \
RO(Proc)->Uncore.MC[mc].Channel[cha].HSW.Timing.tsrRdTRd;
TIMING(mc, cha).tdrRdTRd = \
RO(Proc)->Uncore.MC[mc].Channel[cha].HSW.Timing.tdrRdTRd;
TIMING(mc, cha).tddRdTRd = \
RO(Proc)->Uncore.MC[mc].Channel[cha].HSW.Timing.tddRdTRd;
TIMING(mc, cha).tsrWrTRd = \
RO(Proc)->Uncore.MC[mc].Channel[cha].HSW.Rank_A.tsrWrTRd;
TIMING(mc, cha).tdrWrTRd = \
RO(Proc)->Uncore.MC[mc].Channel[cha].HSW.Rank_A.tdrWrTRd;
TIMING(mc, cha).tddWrTRd = \
RO(Proc)->Uncore.MC[mc].Channel[cha].HSW.Rank_A.tddWrTRd;
TIMING(mc, cha).tsrWrTWr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].HSW.Rank_A.tsrWrTWr;
TIMING(mc, cha).tdrWrTWr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].HSW.Rank_A.tdrWrTWr;
TIMING(mc, cha).tddWrTWr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].HSW.Rank_A.tddWrTWr;
TIMING(mc, cha).tsrRdTWr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].HSW.Rank_B.tsrRdTWr;
TIMING(mc, cha).tdrRdTWr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].HSW.Rank_B.tdrRdTWr;
TIMING(mc, cha).tddRdTWr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].HSW.Rank_B.tddRdTWr;
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].HSW.Timing.CMD_Stretch) {
case 0b00:
TIMING(mc, cha).CMD_Rate = 1;
break;
case 0b10:
TIMING(mc, cha).CMD_Rate = 2;
break;
case 0b11:
TIMING(mc, cha).CMD_Rate = 3;
break;
default:
TIMING(mc, cha).CMD_Rate = 0;
break;
}
/*
TIMING(mc, cha).B2B = \
RO(Proc)->Uncore.MC[mc].Channel[cha].HSW._.B2B;
TIMING(mc, cha).tXS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].HSW._.tXS;
*/
TIMING(mc, cha).PDM_EN = \
0 != RO(Proc)->Uncore.MC[mc].Channel[cha].HSW.PDWN.PDWN_Mode;
TIMING(mc, cha).PDM_MODE = \
RO(Proc)->Uncore.MC[mc].Channel[cha].HSW.PDWN.PDWN_Mode;
TIMING(mc, cha).PDM_AGGR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].HSW.PDWN.PDWN_Mode;
for (slot = 0; slot < RO(Shm)->Uncore.MC[mc].SlotCount; slot++)
{
unsigned long long DIMM_Banks;
const unsigned short
Dimm_A_Map = cha & 1 ? RO(Proc)->Uncore.MC[mc].SNB.MAD1.DAS
: RO(Proc)->Uncore.MC[mc].SNB.MAD0.DAS;
if (slot == Dimm_A_Map)
{
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks = \
cha & 1 ? RO(Proc)->Uncore.MC[mc].SNB.MAD1.DANOR
: RO(Proc)->Uncore.MC[mc].SNB.MAD0.DANOR;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows = \
DimmWidthToRows(cha & 1 ? RO(Proc)->Uncore.MC[mc].SNB.MAD1.DAW
: RO(Proc)->Uncore.MC[mc].SNB.MAD0.DAW);
}
else
{
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks = \
cha & 1 ? RO(Proc)->Uncore.MC[mc].SNB.MAD1.DBNOR
: RO(Proc)->Uncore.MC[mc].SNB.MAD0.DBNOR;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows = \
DimmWidthToRows(cha & 1 ? RO(Proc)->Uncore.MC[mc].SNB.MAD1.DBW
: RO(Proc)->Uncore.MC[mc].SNB.MAD0.DBW);
}
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks++;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols = 1 << 10;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Size = \
dimmSize[cha][(slot ^ Dimm_A_Map) % 2] * 256;
DIMM_Banks = RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Size;
DIMM_Banks = DIMM_Banks * 1024LLU * 1024LLU;
DIMM_Banks = DIMM_Banks
/ (8LLU * RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows
* RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols);
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks = DIMM_Banks;
}
TIMING(mc, cha).ECC = (cha == 0) ?
RO(Proc)->Uncore.MC[mc].SNB.MAD0.ECC
: RO(Proc)->Uncore.MC[mc].SNB.MAD1.ECC;
}
if (RO(Proc)->Uncore.MC[mc].SNB.MADCH.LPDDR) {
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_LPDDR;
} else {
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_SDRAM;
}
}
}
#define HSW_CAP IVB_CAP
#define HSW_EP_IMC SNB_EP_IMC
void HSW_EP_CAP(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc), RO(CORE) *RO(Core))
{
switch (RO(Proc)->Uncore.Bus.SNB_EP_Cap1.DMFC) {
case 0b111:
RO(Shm)->Uncore.CtrlSpeed = 1066;
break;
case 0b110:
RO(Shm)->Uncore.CtrlSpeed = 1333;
break;
case 0b101:
RO(Shm)->Uncore.CtrlSpeed = 1600;
break;
case 0b100:
RO(Shm)->Uncore.CtrlSpeed = 1866;
break;
case 0b011:
RO(Shm)->Uncore.CtrlSpeed = 2133;
break;
case 0b010:
RO(Shm)->Uncore.CtrlSpeed = 2400;
break;
case 0b001:
RO(Shm)->Uncore.CtrlSpeed = 2666;
break;
case 0b000:
RO(Shm)->Uncore.CtrlSpeed = 2933;
break;
}
RO(Shm)->Uncore.CtrlSpeed *= RO(Core)->Clock.Hz;
RO(Shm)->Uncore.CtrlSpeed /= RO(Shm)->Proc.Features.Factory.Clock.Hz;
RO(Shm)->Uncore.Bus.Rate = \
RO(Proc)->Uncore.Bus.QuickPath.EP.QPIFREQSEL == 0b010 ?
5600 : RO(Proc)->Uncore.Bus.QuickPath.EP.QPIFREQSEL == 0b011 ?
6400 : RO(Proc)->Uncore.Bus.QuickPath.EP.QPIFREQSEL == 0b100 ?
7200 : RO(Proc)->Uncore.Bus.QuickPath.EP.QPIFREQSEL == 0b101 ?
8000 : RO(Proc)->Uncore.Bus.QuickPath.EP.QPIFREQSEL == 0b111 ?
9600 : 6400;
RO(Shm)->Uncore.Bus.Speed = (RO(Core)->Clock.Hz
* RO(Shm)->Uncore.Bus.Rate)
/ RO(Shm)->Proc.Features.Factory.Clock.Hz;
RO(Shm)->Uncore.Unit.Bus_Rate = MC_MTS;
RO(Shm)->Uncore.Unit.BusSpeed = MC_MTS;
RO(Shm)->Uncore.Unit.DDR_Rate = MC_NIL;
RO(Shm)->Uncore.Unit.DDRSpeed = MC_MHZ;
if (RO(Proc)->Uncore.MC[0].HSW_EP.TECH.DDR4_Mode) {
RO(Shm)->Uncore.Unit.DDR_Ver = 4;
} else {
RO(Shm)->Uncore.Unit.DDR_Ver = 3;
}
if (RO(Proc)->Uncore.Bus.SNB_EP_Cap3.RDIMM_DIS)
{
if (RO(Proc)->Uncore.Bus.SNB_EP_Cap3.UDIMM_DIS) {
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_UNSPEC;
} else {
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_SDRAM;
}
} else {
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_RDIMM;
}
/*TODO(VT-d capability from device 30 in CAPID# registers among offsets 0x80)*/
RO(Shm)->Proc.Technology.IOMMU = 0;
RO(Shm)->Proc.Technology.IOMMU_Ver_Major = 0;
RO(Shm)->Proc.Technology.IOMMU_Ver_Minor = 0;
}
void SKL_IMC(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc))
{
unsigned short mc, cha;
for (mc = 0; mc < RO(Shm)->Uncore.CtrlCount; mc++)
{
RO(Shm)->Uncore.MC[mc].SlotCount = RO(Proc)->Uncore.MC[mc].SlotCount;
RO(Shm)->Uncore.MC[mc].ChannelCount = RO(Proc)->Uncore.MC[mc].ChannelCount;
for (cha = 0; cha < RO(Shm)->Uncore.MC[mc].ChannelCount; cha++)
{
TIMING(mc, cha).tCL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.ODT.tCL;
TIMING(mc, cha).tRCD_RD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.Timing.tRP;
TIMING(mc, cha).tRCD_WR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.ACT.tRCD_WR;
if (TIMING(mc, cha).tRCD_WR == 0) {
/* ACT to CAS (RD or WR) same bank minimum delay in DCLK cycles */
TIMING(mc, cha).tRCD_WR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.Timing.tRP;
}
TIMING(mc, cha).tRP = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.Timing.tRP;
TIMING(mc, cha).tRAS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.Timing.tRAS;
TIMING(mc, cha).tRRDS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.ACT.tRRD_DG;
TIMING(mc, cha).tRRDL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.ACT.tRRD_SG;
TIMING(mc, cha).tRFC = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.Refresh.tRFC;
TIMING(mc, cha).tREFI = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.Refresh.tREFI;
if (RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.Timing.tWRPRE >=
(RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.ODT.tCWL + 4U))
{
TIMING(mc, cha).tWR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.Timing.tWRPRE
- RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.ODT.tCWL -4U;
}
TIMING(mc, cha).tRTPr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.Timing.tRDPRE;
TIMING(mc, cha).tWTPr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.Timing.tWRPRE;
TIMING(mc, cha).tFAW = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.ACT.tFAW;
TIMING(mc, cha).tCWL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.ODT.tCWL;
TIMING(mc, cha).tRDRD_SG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.RDRD.tRDRD_SG;
TIMING(mc, cha).tRDRD_DG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.RDRD.tRDRD_DG;
TIMING(mc, cha).tRDRD_DR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.RDRD.tRDRD_DR;
TIMING(mc, cha).tRDRD_DD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.RDRD.tRDRD_DD;
TIMING(mc, cha).tRDWR_SG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.RDWR.tRDWR_SG;
TIMING(mc, cha).tRDWR_DG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.RDWR.tRDWR_DG;
TIMING(mc, cha).tRDWR_DR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.RDWR.tRDWR_DR;
TIMING(mc, cha).tRDWR_DD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.RDWR.tRDWR_DD;
TIMING(mc, cha).tWRRD_SG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.WRRD.tWRRD_SG;
TIMING(mc, cha).tWRRD_DG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.WRRD.tWRRD_DG;
TIMING(mc, cha).tWRRD_DR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.WRRD.tWRRD_DR;
TIMING(mc, cha).tWRRD_DD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.WRRD.tWRRD_DD;
TIMING(mc, cha).tWRWR_SG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.WRWR.tWRWR_SG;
TIMING(mc, cha).tWRWR_DG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.WRWR.tWRWR_DG;
TIMING(mc, cha).tWRWR_DR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.WRWR.tWRWR_DR;
TIMING(mc, cha).tWRWR_DD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.WRWR.tWRWR_DD;
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.Sched.CMD_Stretch) {
case 0b00:
case 0b11:
TIMING(mc, cha).CMD_Rate = 1;
break;
case 0b01:
TIMING(mc, cha).CMD_Rate = 2;
break;
case 0b10:
TIMING(mc, cha).CMD_Rate = 3;
break;
}
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[0].Banks = \
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[1].Banks = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.Sched.DRAM_Tech == 0b00 ? 16:8;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[0].Cols = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.Sched.x8_device_Dimm0 ?
1024 : 512;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[1].Cols = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.Sched.x8_device_Dimm1 ?
1024 : 512;
TIMING(mc, cha).tCKE = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.Sched.tCKE;
TIMING(mc, cha).tCPDED = \
RO(Proc)->Uncore.MC[mc].Channel[cha].SKL.Sched.tCPDED;
}
RO(Shm)->Uncore.MC[mc].Channel[0].Timing.ECC = \
RO(Proc)->Uncore.MC[mc].SKL.MADC0.ECC;
RO(Shm)->Uncore.MC[mc].Channel[1].Timing.ECC = \
RO(Proc)->Uncore.MC[mc].SKL.MADC1.ECC;
RO(Shm)->Uncore.MC[mc].Channel[0].DIMM[
RO(Proc)->Uncore.MC[mc].SKL.MADC0.Dimm_L_Map
].Size = 1024 * RO(Proc)->Uncore.MC[mc].SKL.MADD0.Dimm_L_Size;
RO(Shm)->Uncore.MC[mc].Channel[0].DIMM[
!RO(Proc)->Uncore.MC[mc].SKL.MADC0.Dimm_L_Map
].Size = 1024 * RO(Proc)->Uncore.MC[mc].SKL.MADD0.Dimm_S_Size;
RO(Shm)->Uncore.MC[mc].Channel[1].DIMM[
RO(Proc)->Uncore.MC[mc].SKL.MADC1.Dimm_L_Map
].Size = 1024 * RO(Proc)->Uncore.MC[mc].SKL.MADD1.Dimm_L_Size;
RO(Shm)->Uncore.MC[mc].Channel[1].DIMM[
!RO(Proc)->Uncore.MC[mc].SKL.MADC1.Dimm_L_Map
].Size = 1024 * RO(Proc)->Uncore.MC[mc].SKL.MADD1.Dimm_S_Size;
RO(Shm)->Uncore.MC[mc].Channel[0].DIMM[
RO(Proc)->Uncore.MC[mc].SKL.MADC0.Dimm_L_Map
].Ranks = 1 + RO(Proc)->Uncore.MC[mc].SKL.MADD0.DLNOR;
RO(Shm)->Uncore.MC[mc].Channel[0].DIMM[
!RO(Proc)->Uncore.MC[mc].SKL.MADC0.Dimm_L_Map
].Ranks = 1 + RO(Proc)->Uncore.MC[mc].SKL.MADD0.DSNOR;
RO(Shm)->Uncore.MC[mc].Channel[1].DIMM[
RO(Proc)->Uncore.MC[mc].SKL.MADC1.Dimm_L_Map
].Ranks = 1 + RO(Proc)->Uncore.MC[mc].SKL.MADD1.DLNOR;
RO(Shm)->Uncore.MC[mc].Channel[1].DIMM[
!RO(Proc)->Uncore.MC[mc].SKL.MADC1.Dimm_L_Map
].Ranks = 1 + RO(Proc)->Uncore.MC[mc].SKL.MADD1.DSNOR;
RO(Shm)->Uncore.MC[mc].Channel[0].DIMM[
RO(Proc)->Uncore.MC[mc].SKL.MADC0.Dimm_L_Map
].Rows = DimmWidthToRows(RO(Proc)->Uncore.MC[mc].SKL.MADD0.DLW);
RO(Shm)->Uncore.MC[mc].Channel[0].DIMM[
!RO(Proc)->Uncore.MC[mc].SKL.MADC0.Dimm_L_Map
].Rows = DimmWidthToRows(RO(Proc)->Uncore.MC[mc].SKL.MADD0.DSW);
RO(Shm)->Uncore.MC[mc].Channel[1].DIMM[
RO(Proc)->Uncore.MC[mc].SKL.MADC1.Dimm_L_Map
].Rows = DimmWidthToRows(RO(Proc)->Uncore.MC[mc].SKL.MADD1.DLW);
RO(Shm)->Uncore.MC[mc].Channel[1].DIMM[
!RO(Proc)->Uncore.MC[mc].SKL.MADC1.Dimm_L_Map
].Rows = DimmWidthToRows(RO(Proc)->Uncore.MC[mc].SKL.MADD1.DSW);
switch (RO(Proc)->Uncore.MC[mc].SKL.MADCH.DDR_TYPE) {
case 0b00:
RO(Shm)->Uncore.Unit.DDR_Ver = 4;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_SDRAM;
break;
case 0b01:
RO(Shm)->Uncore.Unit.DDR_Ver = 3;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_SDRAM;
break;
case 0b10:
RO(Shm)->Uncore.Unit.DDR_Ver = 3;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_LPDDR;
break;
default:
RO(Shm)->Uncore.Unit.DDR_Ver = 4;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_UNSPEC;
break;
}
}
}
void SKL_CAP(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc), RO(CORE) *RO(Core))
{
unsigned int DMFC;
switch (RO(Proc)->ArchID) {
case Skylake_UY:
case Kabylake_UY:
DMFC = RO(Proc)->Uncore.Bus.SKL_Cap_B.DMFC_DDR3;
RO(Shm)->Uncore.Bus.Rate = 4000; /* 4 GT/s QPI */
break;
default:
DMFC = RO(Proc)->Uncore.Bus.SKL_Cap_C.DMFC_DDR4;
RO(Shm)->Uncore.Bus.Rate = 8000; /* 8 GT/s DMI3 */
break;
}
if (RO(Proc)->Uncore.Bus.SKL_SA_Pll.QCLK == 0)
{
switch (DMFC) {
case 0b111:
RO(Shm)->Uncore.CtrlSpeed = 1067;
break;
case 0b110:
RO(Shm)->Uncore.CtrlSpeed = 1333;
break;
case 0b101:
RO(Shm)->Uncore.CtrlSpeed = 1600;
break;
case 0b100:
RO(Shm)->Uncore.CtrlSpeed = 1867;
break;
case 0b011:
RO(Shm)->Uncore.CtrlSpeed = 2133;
break;
case 0b010:
RO(Shm)->Uncore.CtrlSpeed = 2400;
break;
case 0b001:
case 0b000:
RO(Shm)->Uncore.CtrlSpeed = 2667;
break;
}
RO(Shm)->Uncore.Unit.DDRSpeed = MC_MHZ;
}
else
{
unsigned long long Freq_Hz;
if (RO(Proc)->Uncore.Bus.SKL_SA_Pll.QCLK_REF == 0) {
Freq_Hz = 133333333LLU * RO(Proc)->Uncore.Bus.SKL_SA_Pll.QCLK;
Freq_Hz = Freq_Hz / 1000000LLU;
} else {
Freq_Hz = 100LLU * RO(Proc)->Uncore.Bus.SKL_SA_Pll.QCLK;
}
RO(Shm)->Uncore.CtrlSpeed = (unsigned short) Freq_Hz;
RO(Shm)->Uncore.Unit.DDRSpeed = MC_MHZ;
}
RO(Shm)->Uncore.Bus.Speed = (RO(Core)->Clock.Hz
* RO(Shm)->Uncore.Bus.Rate)
/ RO(Shm)->Proc.Features.Factory.Clock.Hz;
RO(Shm)->Uncore.Unit.Bus_Rate = MC_MTS;
RO(Shm)->Uncore.Unit.BusSpeed = MC_MTS;
RO(Shm)->Uncore.Unit.DDR_Rate = MC_NIL;
RO(Shm)->Proc.Technology.IOMMU = !RO(Proc)->Uncore.Bus.SKL_Cap_A.VT_d;
RO(Shm)->Proc.Technology.IOMMU_Ver_Major = \
RO(Proc)->Uncore.Bus.IOMMU_Ver.Major;
RO(Shm)->Proc.Technology.IOMMU_Ver_Minor = \
RO(Proc)->Uncore.Bus.IOMMU_Ver.Minor;
RO(Shm)->Proc.Technology.GNA = !RO(Proc)->Uncore.Bus.SKL_Cap_B.GMM_DIS;
RO(Shm)->Proc.Technology.IPU = !RO(Proc)->Uncore.Bus.SKL_Cap_B.IMGU_DIS;
RO(Shm)->Proc.Technology.OC = RO(Proc)->Uncore.Bus.SKL_Cap_B.OC_ENABLED;
}
void RKL_IMC(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc))
{
unsigned short mc, cha;
for (mc = 0; mc < RO(Shm)->Uncore.CtrlCount; mc++)
{
unsigned int width = 15;
RO(Shm)->Uncore.MC[mc].SlotCount = RO(Proc)->Uncore.MC[mc].SlotCount;
RO(Shm)->Uncore.MC[mc].ChannelCount = RO(Proc)->Uncore.MC[mc].ChannelCount;
for (cha = 0; cha < RO(Shm)->Uncore.MC[mc].ChannelCount; cha++)
{
TIMING(mc, cha).tCL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.ODT.tCL;
TIMING(mc, cha).tRCD_RD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.Timing.tRP;
TIMING(mc, cha).tRCD_WR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.ACT.tRCD_WR;
if (TIMING(mc, cha).tRCD_WR == 0) {
TIMING(mc, cha).tRCD_WR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.Timing.tRP;
}
TIMING(mc, cha).tRP = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.Timing.tRP;
TIMING(mc, cha).tRAS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.Timing.tRAS;
TIMING(mc, cha).tRRDS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.ACT.tRRD_DG;
TIMING(mc, cha).tRRDL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.ACT.tRRD_SG;
TIMING(mc, cha).tRFC = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.Refresh.tRFC;
TIMING(mc, cha).tREFI = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.Refresh.tREFI;
if (RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.Timing.tWRPRE >=
(RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.ODT.tCWL + 4U))
{
TIMING(mc, cha).tWR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.Timing.tWRPRE
- RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.ODT.tCWL -4U;
}
TIMING(mc, cha).tRTPr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.Timing.tRDPRE;
TIMING(mc, cha).tWTPr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.Timing.tWRPRE;
TIMING(mc, cha).tFAW = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.ACT.tFAW;
TIMING(mc, cha).tCWL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.ODT.tCWL;
TIMING(mc, cha).tRDRD_SG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.RDRD.tRDRD_SG;
TIMING(mc, cha).tRDRD_DG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.RDRD.tRDRD_DG;
TIMING(mc, cha).tRDRD_DR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.RDRD.tRDRD_DR;
TIMING(mc, cha).tRDRD_DD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.RDRD.tRDRD_DD;
TIMING(mc, cha).tRDWR_SG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.RDWR.tRDWR_SG;
TIMING(mc, cha).tRDWR_DG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.RDWR.tRDWR_DG;
TIMING(mc, cha).tRDWR_DR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.RDWR.tRDWR_DR;
TIMING(mc, cha).tRDWR_DD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.RDWR.tRDWR_DD;
TIMING(mc, cha).tWRRD_SG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.WRRD.tWRRD_SG;
TIMING(mc, cha).tWRRD_DG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.WRRD.tWRRD_DG;
TIMING(mc, cha).tWRRD_DR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.WRRD.tWRRD_DR;
TIMING(mc, cha).tWRRD_DD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.WRRD.tWRRD_DD;
TIMING(mc, cha).tWRWR_SG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.WRWR.tWRWR_SG;
TIMING(mc, cha).tWRWR_DG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.WRWR.tWRWR_DG;
TIMING(mc, cha).tWRWR_DR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.WRWR.tWRWR_DR;
TIMING(mc, cha).tWRWR_DD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.WRWR.tWRWR_DD;
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.Sched.CMD_Stretch) {
case 0b00:
case 0b11:
TIMING(mc, cha).CMD_Rate = 1;
break;
case 0b01:
TIMING(mc, cha).CMD_Rate = 2;
break;
case 0b10:
TIMING(mc, cha).CMD_Rate = 3;
break;
}
TIMING(mc, cha).tXS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.SRExit.tXSR;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[0].Banks = \
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[1].Banks = \
!RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.Sched.ReservedBits1 ? 16 : 8;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[0].Cols = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.Sched.x8_device_Dimm0 ?
1024 : 512;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[1].Cols = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.Sched.x8_device_Dimm1 ?
1024 : 512;
TIMING(mc, cha).tCKE = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.PWDEN.tCKE;
TIMING(mc, cha).tXP = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.PWDEN.tXP;
TIMING(mc, cha).tCPDED = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.Sched.tCPDED;
TIMING(mc, cha).GEAR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].RKL.Sched.GEAR2 ? 2 : 1;
}
RO(Shm)->Uncore.MC[mc].Channel[0].Timing.ECC = \
RO(Proc)->Uncore.MC[mc].RKL.MADC0.ECC;
RO(Shm)->Uncore.MC[mc].Channel[1].Timing.ECC = \
RO(Proc)->Uncore.MC[mc].RKL.MADC1.ECC;
RO(Shm)->Uncore.MC[mc].Channel[0].DIMM[
RO(Proc)->Uncore.MC[mc].RKL.MADC0.Dimm_L_Map
].Size = 512 * RO(Proc)->Uncore.MC[mc].RKL.MADD0.Dimm_L_Size;
RO(Shm)->Uncore.MC[mc].Channel[0].DIMM[
!RO(Proc)->Uncore.MC[mc].RKL.MADC0.Dimm_L_Map
].Size = 512 * RO(Proc)->Uncore.MC[mc].RKL.MADD0.Dimm_S_Size;
RO(Shm)->Uncore.MC[mc].Channel[1].DIMM[
RO(Proc)->Uncore.MC[mc].RKL.MADC1.Dimm_L_Map
].Size = 512 * RO(Proc)->Uncore.MC[mc].RKL.MADD1.Dimm_L_Size;
RO(Shm)->Uncore.MC[mc].Channel[1].DIMM[
!RO(Proc)->Uncore.MC[mc].RKL.MADC1.Dimm_L_Map
].Size = 512 * RO(Proc)->Uncore.MC[mc].RKL.MADD1.Dimm_S_Size;
RO(Shm)->Uncore.MC[mc].Channel[0].DIMM[
RO(Proc)->Uncore.MC[mc].RKL.MADC0.Dimm_L_Map
].Ranks = 1 + RO(Proc)->Uncore.MC[mc].RKL.MADD0.DLNOR;
RO(Shm)->Uncore.MC[mc].Channel[0].DIMM[
!RO(Proc)->Uncore.MC[mc].RKL.MADC0.Dimm_L_Map
].Ranks = 1 + RO(Proc)->Uncore.MC[mc].RKL.MADD0.DSNOR;
RO(Shm)->Uncore.MC[mc].Channel[1].DIMM[
RO(Proc)->Uncore.MC[mc].RKL.MADC1.Dimm_L_Map
].Ranks = 1 + RO(Proc)->Uncore.MC[mc].RKL.MADD1.DLNOR;
RO(Shm)->Uncore.MC[mc].Channel[1].DIMM[
!RO(Proc)->Uncore.MC[mc].RKL.MADC1.Dimm_L_Map
].Ranks = 1 + RO(Proc)->Uncore.MC[mc].RKL.MADD1.DSNOR;
width += RO(Proc)->Uncore.MC[mc].RKL.MADCH.CH_WIDTH;
RO(Shm)->Uncore.MC[mc].Channel[0].DIMM[
RO(Proc)->Uncore.MC[mc].RKL.MADC0.Dimm_L_Map
].Rows = \
RO(Shm)->Uncore.MC[mc].Channel[0].DIMM[
!RO(Proc)->Uncore.MC[mc].RKL.MADC0.Dimm_L_Map
].Rows = \
RO(Shm)->Uncore.MC[mc].Channel[1].DIMM[
RO(Proc)->Uncore.MC[mc].RKL.MADC1.Dimm_L_Map
].Rows = \
RO(Shm)->Uncore.MC[mc].Channel[1].DIMM[
!RO(Proc)->Uncore.MC[mc].RKL.MADC1.Dimm_L_Map
].Rows = 1 << width;
}
}
void RKL_CAP(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc), RO(CORE) *RO(Core))
{
unsigned int units = 12;
unsigned int Bus_Rate = RO(Proc)->Uncore.Bus.BIOS_DDR.MC_PLL_RATIO;
unsigned short mc, clock_done;
for (mc = 0, clock_done = 0;
mc < RO(Shm)->Uncore.CtrlCount && !clock_done;
mc++)
{
if (RO(Proc)->Uncore.MC[mc].RKL.MADCH.value) {
switch (RO(Proc)->Uncore.MC[mc].RKL.MADCH.DDR_TYPE) {
default:
case 0b00: /* DDR4 */
RO(Shm)->Uncore.Unit.DDR_Ver = 4;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_SDRAM;
if ((RO(Proc)->Uncore.Bus.RKL_Cap_C.DDR4_EN)
&& (RO(Proc)->Uncore.Bus.RKL_Cap_A.DDR_OVERCLOCK == 0))
{
units = RO(Proc)->Uncore.Bus.RKL_Cap_C.DATA_RATE_DDR4;
clock_done = 1;
}
break;
case 0b11: /* LPDDR4 */
RO(Shm)->Uncore.Unit.DDR_Ver = 4;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_LPDDR;
if ((RO(Proc)->Uncore.Bus.RKL_Cap_C.LPDDR4_EN)
&& (RO(Proc)->Uncore.Bus.RKL_Cap_A.DDR_OVERCLOCK == 0))
{
units = RO(Proc)->Uncore.Bus.RKL_Cap_C.DATA_RATE_LPDDR4;
clock_done = 1;
}
break;
case 0b01: /* DDR5 */
RO(Shm)->Uncore.Unit.DDR_Ver = 5;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_SDRAM;
if ((RO(Proc)->Uncore.Bus.TGL_Cap_E.DDR5_EN)
&& (RO(Proc)->Uncore.Bus.TGL_Cap_A.DDR_OVERCLOCK == 0))
{
units = RO(Proc)->Uncore.Bus.TGL_Cap_E.DATA_RATE_DDR5;
clock_done = 1;
}
break;
case 0b10: /* LPDDR5 */
RO(Shm)->Uncore.Unit.DDR_Ver = 5;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_LPDDR;
if ((RO(Proc)->Uncore.Bus.TGL_Cap_E.LPDDR5_EN)
&& (RO(Proc)->Uncore.Bus.TGL_Cap_A.DDR_OVERCLOCK == 0))
{
units = RO(Proc)->Uncore.Bus.TGL_Cap_E.DATA_RATE_LPDDR5;
clock_done = 1;
}
break;
}
}
}
if (RO(Proc)->Uncore.Bus.RKL_SA_Pll.QCLK_RATIO == 0)
{
RO(Shm)->Uncore.CtrlSpeed = (266 * units) + ((334 * units) / 501);
Bus_Rate = Bus_Rate * 100U;
}
else /* Is Memory frequency overclocked ? */
{
unsigned long long Freq_Hz;
if (RO(Proc)->Uncore.Bus.RKL_SA_Pll.QCLK_REF == 0) {
Freq_Hz = RO(Proc)->Uncore.Bus.RKL_SA_Pll.QCLK_RATIO;
Freq_Hz = Freq_Hz * RO(Core)->Clock.Hz * 800LLU;
Freq_Hz = Freq_Hz / RO(Shm)->Proc.Features.Factory.Clock.Hz;
Freq_Hz = Freq_Hz / 3LLU;
Bus_Rate = Bus_Rate * 400U;
Bus_Rate = Bus_Rate / 3U;
} else {
Freq_Hz = RO(Proc)->Uncore.Bus.RKL_SA_Pll.QCLK_RATIO;
Freq_Hz = Freq_Hz * RO(Core)->Clock.Hz * 200LLU;
Freq_Hz = Freq_Hz / RO(Shm)->Proc.Features.Factory.Clock.Hz;
Bus_Rate = Bus_Rate * 100U;
}
RO(Shm)->Uncore.CtrlSpeed = (unsigned short) Freq_Hz;
}
RO(Shm)->Uncore.Bus.Rate = Bus_Rate;
RO(Shm)->Uncore.Bus.Speed = (RO(Core)->Clock.Hz
* RO(Shm)->Uncore.Bus.Rate)
/ RO(Shm)->Proc.Features.Factory.Clock.Hz;
RO(Shm)->Uncore.Unit.Bus_Rate = MC_MHZ;
RO(Shm)->Uncore.Unit.BusSpeed = MC_MHZ;
RO(Shm)->Uncore.Unit.DDR_Rate = MC_NIL;
RO(Shm)->Uncore.Unit.DDRSpeed = MC_MTS;
RO(Shm)->Proc.Technology.IOMMU = !RO(Proc)->Uncore.Bus.RKL_Cap_A.VT_d;
RO(Shm)->Proc.Technology.IOMMU_Ver_Major = \
RO(Proc)->Uncore.Bus.IOMMU_Ver.Major;
RO(Shm)->Proc.Technology.IOMMU_Ver_Minor = \
RO(Proc)->Uncore.Bus.IOMMU_Ver.Minor;
RO(Shm)->Proc.Technology.VMD = !RO(Proc)->Uncore.Bus.RKL_Cap_B.VMD_DIS;
RO(Shm)->Proc.Technology.GNA = !RO(Proc)->Uncore.Bus.RKL_Cap_B.GNA_DIS;
RO(Shm)->Proc.Technology.HDCP= !RO(Proc)->Uncore.Bus.RKL_Cap_B.HDCPD;
RO(Shm)->Proc.Technology.IPU = !RO(Proc)->Uncore.Bus.RKL_Cap_B.IPU_DIS;
RO(Shm)->Proc.Technology.OC = RO(Proc)->Uncore.Bus.RKL_Cap_B.OC_ENABLED;
}
void TGL_IMC(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc))
{
unsigned short mc, cha;
for (mc = 0; mc < RO(Shm)->Uncore.CtrlCount; mc++)
{
unsigned int width = 15;
RO(Shm)->Uncore.MC[mc].SlotCount = RO(Proc)->Uncore.MC[mc].SlotCount;
RO(Shm)->Uncore.MC[mc].ChannelCount = RO(Proc)->Uncore.MC[mc].ChannelCount;
for (cha = 0; cha < RO(Shm)->Uncore.MC[mc].ChannelCount; cha++)
{
TIMING(mc, cha).tCL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.ODT.tCL;
/* ACT to CAS (RD or WR) same bank minimum delay in tCK */
TIMING(mc, cha).tRCD_RD = \
TIMING(mc, cha).tRCD_WR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.Timing.tRCD;
TIMING(mc, cha).tRP = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.Timing.tRP;
TIMING(mc, cha).tRAS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.Timing.tRAS;
TIMING(mc, cha).tRRDS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.ACT.tRRD_DG;
TIMING(mc, cha).tRRDL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.ACT.tRRD_SG;
TIMING(mc, cha).tRFC = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.Refresh.tRFC;
TIMING(mc, cha).tREFI = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.Refresh.tREFI;
if (RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.Timing.tWRPRE >=
(RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.ODT.tCWL + 4U))
{
TIMING(mc, cha).tWR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.Timing.tWRPRE
- RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.ODT.tCWL -4U;
}
TIMING(mc, cha).tRTPr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.Timing.tRDPRE;
TIMING(mc, cha).tWTPr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.Timing.tWRPRE;
TIMING(mc, cha).tFAW = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.ACT.tFAW;
TIMING(mc, cha).tCWL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.ODT.tCWL;
TIMING(mc, cha).tRDRD_SG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.RDRD.tRDRD_SG;
TIMING(mc, cha).tRDRD_DG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.RDRD.tRDRD_DG;
TIMING(mc, cha).tRDRD_DR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.RDRD.tRDRD_DR;
TIMING(mc, cha).tRDRD_DD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.RDRD.tRDRD_DD;
TIMING(mc, cha).tRDWR_SG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.RDWR.tRDWR_SG;
TIMING(mc, cha).tRDWR_DG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.RDWR.tRDWR_DG;
TIMING(mc, cha).tRDWR_DR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.RDWR.tRDWR_DR;
TIMING(mc, cha).tRDWR_DD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.RDWR.tRDWR_DD;
TIMING(mc, cha).tWRRD_SG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.WRRD.tWRRD_SG;
TIMING(mc, cha).tWRRD_DG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.WRRD.tWRRD_DG;
TIMING(mc, cha).tWRRD_DR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.WRRD.tWRRD_DR;
TIMING(mc, cha).tWRRD_DD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.WRRD.tWRRD_DD;
TIMING(mc, cha).tWRWR_SG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.WRWR.tWRWR_SG;
TIMING(mc, cha).tWRWR_DG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.WRWR.tWRWR_DG;
TIMING(mc, cha).tWRWR_DR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.WRWR.tWRWR_DR;
TIMING(mc, cha).tWRWR_DD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.WRWR.tWRWR_DD;
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.Sched.CMD_Stretch) {
case 0b00:
case 0b11:
TIMING(mc, cha).CMD_Rate = 1;
break;
case 0b01:
TIMING(mc, cha).CMD_Rate = 2;
break;
case 0b10:
TIMING(mc, cha).CMD_Rate = 3;
break;
}
TIMING(mc, cha).tXS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.SRExit.tXSR;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[0].Banks = \
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[1].Banks = \
!RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.Sched.ReservedBits1 ? 16 : 8;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[0].Cols = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.Sched.x8_device_Dimm0 ?
1024 : 512;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[1].Cols = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.Sched.x8_device_Dimm1 ?
1024 : 512;
TIMING(mc, cha).tCKE = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.PWDEN.tCKE;
TIMING(mc, cha).tXP = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.PWDEN.tXP;
TIMING(mc, cha).tCPDED = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.Sched.tCPDED;
TIMING(mc, cha).GEAR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].TGL.Sched.GEAR2 ? 2 : 1;
}
RO(Shm)->Uncore.MC[mc].Channel[0].Timing.ECC = \
RO(Proc)->Uncore.MC[mc].TGL.MADC0.ECC;
RO(Shm)->Uncore.MC[mc].Channel[1].Timing.ECC = \
RO(Proc)->Uncore.MC[mc].TGL.MADC1.ECC;
RO(Shm)->Uncore.MC[mc].Channel[0].DIMM[
RO(Proc)->Uncore.MC[mc].TGL.MADC0.Dimm_L_Map
].Size = 512 * RO(Proc)->Uncore.MC[mc].TGL.MADD0.Dimm_L_Size;
RO(Shm)->Uncore.MC[mc].Channel[0].DIMM[
!RO(Proc)->Uncore.MC[mc].TGL.MADC0.Dimm_L_Map
].Size = 512 * RO(Proc)->Uncore.MC[mc].TGL.MADD0.Dimm_S_Size;
RO(Shm)->Uncore.MC[mc].Channel[1].DIMM[
RO(Proc)->Uncore.MC[mc].TGL.MADC1.Dimm_L_Map
].Size = 512 * RO(Proc)->Uncore.MC[mc].TGL.MADD1.Dimm_L_Size;
RO(Shm)->Uncore.MC[mc].Channel[1].DIMM[
!RO(Proc)->Uncore.MC[mc].TGL.MADC1.Dimm_L_Map
].Size = 512 * RO(Proc)->Uncore.MC[mc].TGL.MADD1.Dimm_S_Size;
RO(Shm)->Uncore.MC[mc].Channel[0].DIMM[
RO(Proc)->Uncore.MC[mc].TGL.MADC0.Dimm_L_Map
].Ranks = 1 + RO(Proc)->Uncore.MC[mc].TGL.MADD0.DLNOR;
RO(Shm)->Uncore.MC[mc].Channel[0].DIMM[
!RO(Proc)->Uncore.MC[mc].TGL.MADC0.Dimm_L_Map
].Ranks = 1 + RO(Proc)->Uncore.MC[mc].TGL.MADD0.DSNOR;
RO(Shm)->Uncore.MC[mc].Channel[1].DIMM[
RO(Proc)->Uncore.MC[mc].TGL.MADC1.Dimm_L_Map
].Ranks = 1 + RO(Proc)->Uncore.MC[mc].TGL.MADD1.DLNOR;
RO(Shm)->Uncore.MC[mc].Channel[1].DIMM[
!RO(Proc)->Uncore.MC[mc].TGL.MADC1.Dimm_L_Map
].Ranks = 1 + RO(Proc)->Uncore.MC[mc].TGL.MADD1.DSNOR;
width += RO(Proc)->Uncore.MC[mc].TGL.MADCH.CH_WIDTH;
RO(Shm)->Uncore.MC[mc].Channel[0].DIMM[
RO(Proc)->Uncore.MC[mc].TGL.MADC0.Dimm_L_Map
].Rows = \
RO(Shm)->Uncore.MC[mc].Channel[0].DIMM[
!RO(Proc)->Uncore.MC[mc].TGL.MADC0.Dimm_L_Map
].Rows = \
RO(Shm)->Uncore.MC[mc].Channel[1].DIMM[
RO(Proc)->Uncore.MC[mc].TGL.MADC1.Dimm_L_Map
].Rows = \
RO(Shm)->Uncore.MC[mc].Channel[1].DIMM[
!RO(Proc)->Uncore.MC[mc].TGL.MADC1.Dimm_L_Map
].Rows = 1 << width;
}
}
#define TGL_CAP RKL_CAP
void ADL_IMC(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc))
{
unsigned short mc, cha, virtualCount;
for (mc = 0; mc < RO(Shm)->Uncore.CtrlCount; mc++)
{
RO(Shm)->Uncore.MC[mc].SlotCount = RO(Proc)->Uncore.MC[mc].SlotCount;
RO(Shm)->Uncore.MC[mc].ChannelCount = RO(Proc)->Uncore.MC[mc].ChannelCount;
if (RO(Proc)->Uncore.Bus.ADL_Cap_A.DDPCD == 0) {
switch (RO(Proc)->Uncore.MC[mc].ADL.MADCH.DDR_TYPE) {
case 0b00: /* DDR4 */
virtualCount = 1;
break;
case 0b11: /* LPDDR4 */
case 0b01: /* DDR5 */
case 0b10: /* LPDDR5 */
default:
virtualCount = RO(Shm)->Uncore.MC[mc].ChannelCount;
break;
}
} else {
virtualCount = RO(Shm)->Uncore.MC[mc].ChannelCount;
}
for (cha = 0; cha < virtualCount; cha++)
{
unsigned short tWR_quantity;
TIMING(mc, cha).tCL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.ODT.tCL;
TIMING(mc, cha).tRCD_RD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.Timing.tRCD;
TIMING(mc, cha).tRCD_WR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.Timing.tRCDW;
if (TIMING(mc, cha).tRCD_WR == 0) {
TIMING(mc, cha).tRCD_WR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.Timing.tRCD;
}
TIMING(mc, cha).tRP = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.Timing.tRP;
TIMING(mc, cha).tRAS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.Timing.tRAS;
TIMING(mc, cha).tRRDS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.ACT.tRRD_DG;
TIMING(mc, cha).tRRDL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.ACT.tRRD_SG;
TIMING(mc, cha).tRFC = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.Refresh.tRFC;
TIMING(mc, cha).tREFI = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.Refresh.tREFI;
switch (RO(Shm)->Uncore.Unit.DDR_Ver) {
default:
case 4:
tWR_quantity = 4U;
break;
case 5:
tWR_quantity = 8U;
break;
}
if (RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.Timing.tWRPRE >=
(RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.ODT.tCWL + tWR_quantity))
{
TIMING(mc, cha).tWR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.Timing.tWRPRE
- RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.ODT.tCWL
- tWR_quantity;
}
TIMING(mc, cha).tRTPr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.Timing.tRDPRE;
TIMING(mc, cha).tWTPr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.Timing.tWRPRE;
TIMING(mc, cha).tFAW = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.ACT.tFAW;
TIMING(mc, cha).tCWL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.ODT.tCWL;
TIMING(mc, cha).tRDRD_SG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.RDRD.tRDRD_SG;
TIMING(mc, cha).tRDRD_DG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.RDRD.tRDRD_DG;
TIMING(mc, cha).tRDRD_DR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.RDRD.tRDRD_DR;
TIMING(mc, cha).tRDRD_DD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.RDRD.tRDRD_DD;
TIMING(mc, cha).tRDWR_SG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.RDWR.tRDWR_SG;
TIMING(mc, cha).tRDWR_DG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.RDWR.tRDWR_DG;
TIMING(mc, cha).tRDWR_DR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.RDWR.tRDWR_DR;
TIMING(mc, cha).tRDWR_DD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.RDWR.tRDWR_DD;
TIMING(mc, cha).tWRRD_SG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.WRRD.tWRRD_SG;
TIMING(mc, cha).tWRRD_DG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.WRRD.tWRRD_DG;
TIMING(mc, cha).tWRRD_DR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.WRRD.tWRRD_DR;
TIMING(mc, cha).tWRRD_DD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.WRRD.tWRRD_DD;
TIMING(mc, cha).tWRWR_SG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.WRWR.tWRWR_SG;
TIMING(mc, cha).tWRWR_DG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.WRWR.tWRWR_DG;
TIMING(mc, cha).tWRWR_DR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.WRWR.tWRWR_DR;
TIMING(mc, cha).tWRWR_DD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.WRWR.tWRWR_DD;
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.Sched.CMD_Stretch) {
case 0b00:
case 0b11:
TIMING(mc, cha).CMD_Rate = 1;
break;
case 0b01:
TIMING(mc, cha).CMD_Rate = 2;
break;
case 0b10:
TIMING(mc, cha).CMD_Rate = 3;
break;
}
TIMING(mc, cha).tXS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.SRExit.tXSR;
TIMING(mc, cha).tCKE = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.PWDEN.tCKE;
TIMING(mc, cha).tXP = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.PWDEN.tXP;
TIMING(mc, cha).tCPDED = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.Sched.tCPDED;
TIMING(mc, cha).GEAR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.Sched.GEAR4 ? 4 : \
RO(Proc)->Uncore.MC[mc].Channel[cha].ADL.Sched.GEAR2 ? 2 : 1;
}
switch (RO(Shm)->Uncore.Unit.DDR_Ver) {
case 1 ... 4:
RO(Shm)->Uncore.MC[mc].Channel[0].Timing.ECC = \
RO(Proc)->Uncore.MC[mc].ADL.MADC0.ECC;
RO(Shm)->Uncore.MC[mc].Channel[
RO(Proc)->Uncore.MC[mc].ADL.MADC0.Dimm_L_Map
].DIMM[0].Rows = DimmWidthToRows(RO(Proc)->Uncore.MC[mc].ADL.MADD0.DLW);
RO(Shm)->Uncore.MC[mc].Channel[
!RO(Proc)->Uncore.MC[mc].ADL.MADC0.Dimm_L_Map
].DIMM[0].Rows = DimmWidthToRows(RO(Proc)->Uncore.MC[mc].ADL.MADD0.DSW);
RO(Shm)->Uncore.MC[mc].Channel[
RO(Proc)->Uncore.MC[mc].ADL.MADC0.Dimm_L_Map
].DIMM[0].Size = 512 * RO(Proc)->Uncore.MC[mc].ADL.MADD0.Dimm_L_Size;
RO(Shm)->Uncore.MC[mc].Channel[
!RO(Proc)->Uncore.MC[mc].ADL.MADC0.Dimm_L_Map
].DIMM[0].Size = 512 * RO(Proc)->Uncore.MC[mc].ADL.MADD0.Dimm_S_Size;
RO(Shm)->Uncore.MC[mc].Channel[
RO(Proc)->Uncore.MC[mc].ADL.MADC0.Dimm_L_Map
].DIMM[0].Ranks = 1 + RO(Proc)->Uncore.MC[mc].ADL.MADD0.DLNOR;
RO(Shm)->Uncore.MC[mc].Channel[
!RO(Proc)->Uncore.MC[mc].ADL.MADC0.Dimm_L_Map
].DIMM[0].Ranks = 1 + RO(Proc)->Uncore.MC[mc].ADL.MADD0.DSNOR;
break;
case 5:
default:
RO(Shm)->Uncore.MC[mc].Channel[0].Timing.ECC = \
RO(Proc)->Uncore.MC[mc].ADL.MADC0.ECC;
RO(Shm)->Uncore.MC[mc].Channel[1].Timing.ECC = \
RO(Proc)->Uncore.MC[mc].ADL.MADC1.ECC;
RO(Shm)->Uncore.MC[mc].Channel[
RO(Proc)->Uncore.MC[mc].ADL.MADC0.Dimm_L_Map
].DIMM[0].Rows = 1 << 17;
RO(Shm)->Uncore.MC[mc].Channel[
!RO(Proc)->Uncore.MC[mc].ADL.MADC0.Dimm_L_Map
].DIMM[0].Rows = 1 << 17;
RO(Shm)->Uncore.MC[mc].Channel[
RO(Proc)->Uncore.MC[mc].ADL.MADC1.Dimm_L_Map
].DIMM[0].Rows = 1 << 17;
RO(Shm)->Uncore.MC[mc].Channel[
!RO(Proc)->Uncore.MC[mc].ADL.MADC1.Dimm_L_Map
].DIMM[0].Rows = 1 << 17;
RO(Shm)->Uncore.MC[mc].Channel[
RO(Proc)->Uncore.MC[mc].ADL.MADC0.Dimm_L_Map
].DIMM[0].Size = 1024 * RO(Proc)->Uncore.MC[mc].ADL.MADD0.Dimm_L_Size;
RO(Shm)->Uncore.MC[mc].Channel[
!RO(Proc)->Uncore.MC[mc].ADL.MADC0.Dimm_L_Map
].DIMM[0].Size = 1024 * RO(Proc)->Uncore.MC[mc].ADL.MADD0.Dimm_S_Size;
RO(Shm)->Uncore.MC[mc].Channel[
RO(Proc)->Uncore.MC[mc].ADL.MADC1.Dimm_L_Map
].DIMM[0].Size = 1024 * RO(Proc)->Uncore.MC[mc].ADL.MADD1.Dimm_L_Size;
RO(Shm)->Uncore.MC[mc].Channel[
!RO(Proc)->Uncore.MC[mc].ADL.MADC1.Dimm_L_Map
].DIMM[0].Size = 1024 * RO(Proc)->Uncore.MC[mc].ADL.MADD1.Dimm_S_Size;
RO(Shm)->Uncore.MC[mc].Channel[
RO(Proc)->Uncore.MC[mc].ADL.MADC0.Dimm_L_Map
].DIMM[0].Ranks = 1 + RO(Proc)->Uncore.MC[mc].ADL.MADD0.DLNOR;
RO(Shm)->Uncore.MC[mc].Channel[
!RO(Proc)->Uncore.MC[mc].ADL.MADC0.Dimm_L_Map
].DIMM[0].Ranks = 1 + RO(Proc)->Uncore.MC[mc].ADL.MADD0.DSNOR;
RO(Shm)->Uncore.MC[mc].Channel[
RO(Proc)->Uncore.MC[mc].ADL.MADC1.Dimm_L_Map
].DIMM[0].Ranks = 1 + RO(Proc)->Uncore.MC[mc].ADL.MADD1.DLNOR;
RO(Shm)->Uncore.MC[mc].Channel[
!RO(Proc)->Uncore.MC[mc].ADL.MADC1.Dimm_L_Map
].DIMM[0].Ranks = 1 + RO(Proc)->Uncore.MC[mc].ADL.MADD1.DSNOR;
break;
}
RO(Shm)->Uncore.MC[mc].Channel[0].DIMM[0].Banks = \
!RO(Proc)->Uncore.MC[mc].Channel[0].ADL.Sched.ReservedBits1 ? 16 : 8;
RO(Shm)->Uncore.MC[mc].Channel[1].DIMM[0].Banks = \
!RO(Proc)->Uncore.MC[mc].Channel[1].ADL.Sched.ReservedBits1 ? 16 : 8;
RO(Shm)->Uncore.MC[mc].Channel[0].DIMM[0].Cols = \
RO(Shm)->Uncore.MC[mc].Channel[1].DIMM[0].Cols = 1 << 10;
}
}
void ADL_CAP(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc), RO(CORE) *RO(Core))
{
unsigned int units = 12;
unsigned int Bus_Rate = RO(Proc)->Uncore.Bus.BIOS_DDR.MC_PLL_RATIO;
unsigned short mc, clock_done;
for (mc = 0, clock_done = 0;
mc < RO(Shm)->Uncore.CtrlCount && !clock_done;
mc++)
{
if (RO(Proc)->Uncore.MC[mc].ADL.MADCH.value) {
switch (RO(Proc)->Uncore.MC[mc].ADL.MADCH.DDR_TYPE) {
default:
case 0b00: /* DDR4 */
RO(Shm)->Uncore.Unit.DDR_Ver = 4;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_SDRAM;
if ((RO(Proc)->Uncore.Bus.ADL_Cap_C.DDR4_EN)
&& (RO(Proc)->Uncore.Bus.ADL_Cap_A.DDR_OVERCLOCK == 0))
{
units = RO(Proc)->Uncore.Bus.ADL_Cap_C.DATA_RATE_DDR4;
clock_done = 1;
}
break;
case 0b11: /* LPDDR4 */
RO(Shm)->Uncore.Unit.DDR_Ver = 4;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_LPDDR;
if ((RO(Proc)->Uncore.Bus.ADL_Cap_C.LPDDR4_EN)
&& (RO(Proc)->Uncore.Bus.ADL_Cap_A.DDR_OVERCLOCK == 0))
{
units = RO(Proc)->Uncore.Bus.ADL_Cap_C.DATA_RATE_LPDDR4;
clock_done = 1;
}
break;
case 0b01: /* DDR5 */
RO(Shm)->Uncore.Unit.DDR_Ver = 5;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_SDRAM;
if ((RO(Proc)->Uncore.Bus.ADL_Cap_E.DDR5_EN)
&& (RO(Proc)->Uncore.Bus.ADL_Cap_A.DDR_OVERCLOCK == 0))
{
units = RO(Proc)->Uncore.Bus.ADL_Cap_E.DATA_RATE_DDR5;
clock_done = 1;
}
break;
case 0b10: /* LPDDR5 */
RO(Shm)->Uncore.Unit.DDR_Ver = 5;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_LPDDR;
if ((RO(Proc)->Uncore.Bus.ADL_Cap_E.LPDDR5_EN)
&& (RO(Proc)->Uncore.Bus.ADL_Cap_A.DDR_OVERCLOCK == 0))
{
units = RO(Proc)->Uncore.Bus.ADL_Cap_E.DATA_RATE_LPDDR5;
clock_done = 1;
}
break;
}
}
}
if (RO(Proc)->Uncore.Bus.ADL_SA_Pll.QCLK_RATIO == 0)
{
RO(Shm)->Uncore.CtrlSpeed = (266 * units) + ((334 * units) / 501);
Bus_Rate = Bus_Rate * 100U;
}
else /* Is Memory frequency overclocked ? */
{
unsigned long long Freq_Hz;
if (RO(Proc)->Uncore.Bus.ADL_SA_Pll.QCLK_REF == 0) {
Freq_Hz = RO(Proc)->Uncore.Bus.ADL_SA_Pll.QCLK_RATIO;
Freq_Hz = Freq_Hz * RO(Core)->Clock.Hz * 800LLU;
Freq_Hz = Freq_Hz / RO(Shm)->Proc.Features.Factory.Clock.Hz;
Freq_Hz = Freq_Hz / 3LLU;
Bus_Rate = Bus_Rate * 400U;
Bus_Rate = Bus_Rate / 3U;
} else {
Freq_Hz = RO(Proc)->Uncore.Bus.ADL_SA_Pll.QCLK_RATIO;
Freq_Hz = Freq_Hz * RO(Core)->Clock.Hz * 200LLU;
Freq_Hz = Freq_Hz / RO(Shm)->Proc.Features.Factory.Clock.Hz;
Bus_Rate = Bus_Rate * 100U;
}
RO(Shm)->Uncore.CtrlSpeed = (unsigned short) Freq_Hz;
}
RO(Shm)->Uncore.Bus.Rate = Bus_Rate;
RO(Shm)->Uncore.Bus.Speed = (RO(Core)->Clock.Hz
* RO(Shm)->Uncore.Bus.Rate)
/ RO(Shm)->Proc.Features.Factory.Clock.Hz;
RO(Shm)->Uncore.Unit.Bus_Rate = MC_MHZ;
RO(Shm)->Uncore.Unit.BusSpeed = MC_MHZ;
RO(Shm)->Uncore.Unit.DDR_Rate = MC_NIL;
RO(Shm)->Uncore.Unit.DDRSpeed = MC_MTS;
RO(Shm)->Proc.Technology.IOMMU = !RO(Proc)->Uncore.Bus.ADL_Cap_A.VT_d;
RO(Shm)->Proc.Technology.IOMMU_Ver_Major = \
RO(Proc)->Uncore.Bus.IOMMU_Ver.Major;
RO(Shm)->Proc.Technology.IOMMU_Ver_Minor = \
RO(Proc)->Uncore.Bus.IOMMU_Ver.Minor;
RO(Shm)->Proc.Technology.VMD = !RO(Proc)->Uncore.Bus.ADL_Cap_B.VMD_DIS;
RO(Shm)->Proc.Technology.GNA = !RO(Proc)->Uncore.Bus.ADL_Cap_B.GNA_DIS;
RO(Shm)->Proc.Technology.HDCP= !RO(Proc)->Uncore.Bus.ADL_Cap_B.HDCPD;
RO(Shm)->Proc.Technology.IPU = !RO(Proc)->Uncore.Bus.ADL_Cap_B.IPU_DIS;
RO(Shm)->Proc.Technology.OC = RO(Proc)->Uncore.Bus.ADL_Cap_B.OC_ENABLED;
}
void GLK_CAP(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc), RO(CORE) *RO(Core))
{
RO(Shm)->Uncore.Bus.Rate = 0;
RO(Shm)->Uncore.Bus.Speed = 0;
RO(Shm)->Uncore.CtrlSpeed = 0;
RO(Shm)->Uncore.Unit.DDR_Ver = 4;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_SDRAM;
RO(Shm)->Uncore.Unit.Bus_Rate = MC_NIL;
RO(Shm)->Uncore.Unit.BusSpeed = MC_NIL;
RO(Shm)->Uncore.Unit.DDRSpeed = MC_NIL;
RO(Shm)->Proc.Technology.IOMMU = !RO(Proc)->Uncore.Bus.GLK_Cap_A.VT_d;
RO(Shm)->Proc.Technology.IOMMU_Ver_Major = \
RO(Proc)->Uncore.Bus.IOMMU_Ver.Major;
RO(Shm)->Proc.Technology.IOMMU_Ver_Minor = \
RO(Proc)->Uncore.Bus.IOMMU_Ver.Minor;
RO(Shm)->Proc.Technology.GNA = !RO(Proc)->Uncore.Bus.GLK_Cap_B.GMM_DIS;
RO(Shm)->Proc.Technology.IPU = !RO(Proc)->Uncore.Bus.GLK_Cap_B.IMGU_DIS;
RO(Shm)->Proc.Technology.OC = RO(Proc)->Uncore.Bus.GLK_Cap_B.OC_ENABLED;
}
void GLK_IMC(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc))
{
unsigned short mc, cha;
for (mc = 0; mc < RO(Shm)->Uncore.CtrlCount; mc++)
{
RO(Shm)->Uncore.MC[mc].SlotCount = RO(Proc)->Uncore.MC[mc].SlotCount;
RO(Shm)->Uncore.MC[mc].ChannelCount = RO(Proc)->Uncore.MC[mc].ChannelCount;
for (cha = 0; cha < RO(Shm)->Uncore.MC[mc].ChannelCount; cha++)
{
}
}
}
#define RPL_CAP ADL_CAP
#define RPL_IMC ADL_IMC
void MTL_CAP(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc), RO(CORE) *RO(Core))
{
unsigned short mc, clock_done;
for (mc = 0, clock_done = 0;
mc < RO(Shm)->Uncore.CtrlCount && !clock_done;
mc++)
{
if (RO(Proc)->Uncore.MC[mc].MTL.MADCH.value) {
switch (RO(Proc)->Uncore.MC[mc].MTL.MADCH.DDR_TYPE) {
default:
case 0b00: /* DDR4 */
RO(Shm)->Uncore.Unit.DDR_Ver = 4;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_SDRAM;
if ((RO(Proc)->Uncore.Bus.MTL_Cap_C.DDR4_EN)
&& (RO(Proc)->Uncore.Bus.MTL_Cap_A.DDR_OVERCLOCK == 0))
{
clock_done = 1;
}
break;
case 0b11: /* LPDDR4 */
RO(Shm)->Uncore.Unit.DDR_Ver = 4;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_LPDDR;
if ((RO(Proc)->Uncore.Bus.MTL_Cap_C.LPDDR4_EN)
&& (RO(Proc)->Uncore.Bus.MTL_Cap_A.DDR_OVERCLOCK == 0))
{
clock_done = 1;
}
break;
case 0b01: /* DDR5 */
RO(Shm)->Uncore.Unit.DDR_Ver = 5;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_SDRAM;
if ((RO(Proc)->Uncore.Bus.MTL_Cap_E.DDR5_EN)
&& (RO(Proc)->Uncore.Bus.MTL_Cap_A.DDR_OVERCLOCK == 0))
{
clock_done = 1;
}
break;
case 0b10: /* LPDDR5 */
RO(Shm)->Uncore.Unit.DDR_Ver = 5;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_LPDDR;
if ((RO(Proc)->Uncore.Bus.MTL_Cap_E.LPDDR5_EN)
&& (RO(Proc)->Uncore.Bus.MTL_Cap_A.DDR_OVERCLOCK == 0))
{
clock_done = 1;
}
break;
}
}
}
/* Clock Topology: BCLK drives the Memory Controller clock domain.
* Qclk ratio with reference of 33.33MHz. */
RO(Shm)->Uncore.Bus.Rate = \
( RO(Proc)->Uncore.Bus.MTL_CR_BIOS.REQ.QCLK_RATIO
* RO(Proc)->Uncore.Bus.MTL_BCLK.PCIE_FREQ_KHZ ) / 3000U;
/* BCLK_FREQ_0_0_0_MCHBAR is used by software to calculate
* various clock frequencies that are derived from BCLK
* such as Core, Ring, Memory Controller and GT. */
RO(Shm)->Uncore.Bus.Speed = \
( RO(Proc)->Uncore.Bus.MTL_CR_BIOS.REQ.QCLK_RATIO
* RO(Proc)->Uncore.Bus.MTL_BCLK.SOC_FREQ_KHZ ) / 3000LLU;
/* DDR Transfer Rate (MT/s) */
RO(Shm)->Uncore.CtrlSpeed = 2LLU * RO(Shm)->Uncore.Bus.Speed;
RO(Shm)->Uncore.Unit.Bus_Rate = MC_MHZ;
RO(Shm)->Uncore.Unit.BusSpeed = MC_MHZ;
RO(Shm)->Uncore.Unit.DDR_Rate = MC_NIL;
RO(Shm)->Uncore.Unit.DDRSpeed = MC_MTS;
RO(Shm)->Proc.Technology.IOMMU = !RO(Proc)->Uncore.Bus.MTL_Cap_A.VT_d;
RO(Shm)->Proc.Technology.IOMMU_Ver_Major = \
RO(Proc)->Uncore.Bus.IOMMU_Ver.Major;
RO(Shm)->Proc.Technology.IOMMU_Ver_Minor = \
RO(Proc)->Uncore.Bus.IOMMU_Ver.Minor;
RO(Shm)->Proc.Technology.VMD = !RO(Proc)->Uncore.Bus.MTL_Cap_B.VMD_DIS;
RO(Shm)->Proc.Technology.GNA = !RO(Proc)->Uncore.Bus.MTL_Cap_B.GNA_DIS;
RO(Shm)->Proc.Technology.HDCP= !RO(Proc)->Uncore.Bus.MTL_Cap_B.HDCPD;
RO(Shm)->Proc.Technology.IPU = !RO(Proc)->Uncore.Bus.MTL_Cap_B.IPU_DIS;
RO(Shm)->Proc.Technology.VPU = !RO(Proc)->Uncore.Bus.MTL_Cap_C.VPU_DIS;
RO(Shm)->Proc.Technology.OC = RO(Proc)->Uncore.Bus.MTL_Cap_B.OC_ENABLED;
}
void MTL_IMC(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc))
{
unsigned short mc, cha, virtualCount;
for (mc = 0; mc < RO(Shm)->Uncore.CtrlCount; mc++)
{
RO(Shm)->Uncore.MC[mc].SlotCount = RO(Proc)->Uncore.MC[mc].SlotCount;
RO(Shm)->Uncore.MC[mc].ChannelCount = RO(Proc)->Uncore.MC[mc].ChannelCount;
if (RO(Proc)->Uncore.Bus.MTL_Cap_A.DDPCD == 0) {
switch (RO(Proc)->Uncore.MC[mc].MTL.MADCH.DDR_TYPE) {
case 0b00: /* DDR4 */
virtualCount = 1;
break;
case 0b11: /* LPDDR4 */
case 0b01: /* DDR5 */
case 0b10: /* LPDDR5 */
default:
virtualCount = RO(Shm)->Uncore.MC[mc].ChannelCount;
break;
}
} else {
virtualCount = RO(Shm)->Uncore.MC[mc].ChannelCount;
}
for (cha = 0; cha < virtualCount; cha++)
{
unsigned short tWR_quantity;
TIMING(mc, cha).tCCD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.CAS.tCCD;
TIMING(mc, cha).tCL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.CAS.tCL;
TIMING(mc, cha).tRCD_RD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.ACT.tRCD;
TIMING(mc, cha).tRCD_WR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.ACT.tRCDW;
if (TIMING(mc, cha).tRCD_WR == 0) {
TIMING(mc, cha).tRCD_WR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.ACT.tRCD;
}
TIMING(mc, cha).tRP = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.Timing.tRPpb;
TIMING(mc, cha).tRAS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.Timing.tRAS;
TIMING(mc, cha).tRRDS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.ACT.tRRD_DG;
TIMING(mc, cha).tRRDL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.ACT.tRRD_SG;
TIMING(mc, cha).tRFC = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.Refresh.tRFC;
TIMING(mc, cha).tREFI = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.Refresh.tREFI;
switch (RO(Shm)->Uncore.Unit.DDR_Ver) {
default:
case 4:
tWR_quantity = 4U;
break;
case 5:
tWR_quantity = 10U;
break;
}
if (RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.Timing.tWRPRE >=
(RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.CAS.tCWL + tWR_quantity))
{
TIMING(mc, cha).tWR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.Timing.tWRPRE
- RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.CAS.tCWL
- tWR_quantity;
}
TIMING(mc, cha).tRTPr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.Timing.tRDPRE;
TIMING(mc, cha).tWTPr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.Timing.tWRPRE;
TIMING(mc, cha).tFAW = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.ACT.tFAW;
TIMING(mc, cha).tCWL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.CAS.tCWL;
TIMING(mc, cha).tRDRD_SG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.RDRD.tRDRD_SG;
TIMING(mc, cha).tRDRD_DG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.RDRD.tRDRD_DG;
TIMING(mc, cha).tRDRD_DR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.RDRD.tRDRD_DR;
TIMING(mc, cha).tRDRD_DD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.RDRD.tRDRD_DD;
TIMING(mc, cha).tRDWR_SG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.RDWR.tRDWR_SG;
TIMING(mc, cha).tRDWR_DG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.RDWR.tRDWR_DG;
TIMING(mc, cha).tRDWR_DR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.RDWR.tRDWR_DR;
TIMING(mc, cha).tRDWR_DD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.RDWR.tRDWR_DD;
TIMING(mc, cha).tWRRD_SG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.WRRD.tWRRD_SG;
TIMING(mc, cha).tWRRD_DG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.WRRD.tWRRD_DG;
TIMING(mc, cha).tWRRD_DR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.WRRD.tWRRD_DR;
TIMING(mc, cha).tWRRD_DD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.WRRD.tWRRD_DD;
TIMING(mc, cha).tWRWR_SG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.WRWR.tWRWR_SG;
TIMING(mc, cha).tWRWR_DG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.WRWR.tWRWR_DG;
TIMING(mc, cha).tWRWR_DR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.WRWR.tWRWR_DR;
TIMING(mc, cha).tWRWR_DD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.WRWR.tWRWR_DD;
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.Sched.CMD_Stretch) {
case 0b00:
TIMING(mc, cha).CMD_Rate = 1;
break;
case 0b01:
TIMING(mc, cha).CMD_Rate = 2;
break;
}
TIMING(mc, cha).tXS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.SRExit.tXSR;
TIMING(mc, cha).tCKE = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.PWDEN.tCKE;
TIMING(mc, cha).tXP = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.PWDEN.tXP;
TIMING(mc, cha).tCPDED = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.PWDEN.tCPDED;
TIMING(mc, cha).GEAR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].MTL.Sched.GEAR ? 4 : 2;
}
switch (RO(Shm)->Uncore.Unit.DDR_Ver) {
case 1 ... 4:
RO(Shm)->Uncore.MC[mc].Channel[0].Timing.ECC = \
RO(Proc)->Uncore.MC[mc].MTL.MADC0.ECC;
RO(Shm)->Uncore.MC[mc].Channel[
RO(Proc)->Uncore.MC[mc].MTL.MADC0.Dimm_L_Map
].DIMM[0].Rows = DimmWidthToRows(RO(Proc)->Uncore.MC[mc].MTL.MADD0.DLW);
RO(Shm)->Uncore.MC[mc].Channel[
!RO(Proc)->Uncore.MC[mc].MTL.MADC0.Dimm_L_Map
].DIMM[0].Rows = DimmWidthToRows(RO(Proc)->Uncore.MC[mc].MTL.MADD0.DSW);
RO(Shm)->Uncore.MC[mc].Channel[
RO(Proc)->Uncore.MC[mc].MTL.MADC0.Dimm_L_Map
].DIMM[0].Size = 512 * RO(Proc)->Uncore.MC[mc].MTL.MADD0.Dimm_L_Size;
RO(Shm)->Uncore.MC[mc].Channel[
!RO(Proc)->Uncore.MC[mc].MTL.MADC0.Dimm_L_Map
].DIMM[0].Size = 512 * RO(Proc)->Uncore.MC[mc].MTL.MADD0.Dimm_S_Size;
RO(Shm)->Uncore.MC[mc].Channel[
RO(Proc)->Uncore.MC[mc].MTL.MADC0.Dimm_L_Map
].DIMM[0].Ranks = 1 + RO(Proc)->Uncore.MC[mc].MTL.MADD0.DLNOR;
RO(Shm)->Uncore.MC[mc].Channel[
!RO(Proc)->Uncore.MC[mc].MTL.MADC0.Dimm_L_Map
].DIMM[0].Ranks = 1 + RO(Proc)->Uncore.MC[mc].MTL.MADD0.DSNOR;
break;
case 5:
default:
RO(Shm)->Uncore.MC[mc].Channel[0].Timing.ECC = \
RO(Proc)->Uncore.MC[mc].MTL.MADC0.ECC;
RO(Shm)->Uncore.MC[mc].Channel[1].Timing.ECC = \
RO(Proc)->Uncore.MC[mc].MTL.MADC1.ECC;
RO(Shm)->Uncore.MC[mc].Channel[
RO(Proc)->Uncore.MC[mc].MTL.MADC0.Dimm_L_Map
].DIMM[0].Rows = 1 << 17;
RO(Shm)->Uncore.MC[mc].Channel[
!RO(Proc)->Uncore.MC[mc].MTL.MADC0.Dimm_L_Map
].DIMM[0].Rows = 1 << 17;
RO(Shm)->Uncore.MC[mc].Channel[
RO(Proc)->Uncore.MC[mc].MTL.MADC1.Dimm_L_Map
].DIMM[0].Rows = 1 << 17;
RO(Shm)->Uncore.MC[mc].Channel[
!RO(Proc)->Uncore.MC[mc].MTL.MADC1.Dimm_L_Map
].DIMM[0].Rows = 1 << 17;
RO(Shm)->Uncore.MC[mc].Channel[
RO(Proc)->Uncore.MC[mc].MTL.MADC0.Dimm_L_Map
].DIMM[0].Size = 1024 * RO(Proc)->Uncore.MC[mc].MTL.MADD0.Dimm_L_Size;
RO(Shm)->Uncore.MC[mc].Channel[
!RO(Proc)->Uncore.MC[mc].MTL.MADC0.Dimm_L_Map
].DIMM[0].Size = 1024 * RO(Proc)->Uncore.MC[mc].MTL.MADD0.Dimm_S_Size;
RO(Shm)->Uncore.MC[mc].Channel[
RO(Proc)->Uncore.MC[mc].MTL.MADC1.Dimm_L_Map
].DIMM[0].Size = 1024 * RO(Proc)->Uncore.MC[mc].MTL.MADD1.Dimm_L_Size;
RO(Shm)->Uncore.MC[mc].Channel[
!RO(Proc)->Uncore.MC[mc].MTL.MADC1.Dimm_L_Map
].DIMM[0].Size = 1024 * RO(Proc)->Uncore.MC[mc].MTL.MADD1.Dimm_S_Size;
RO(Shm)->Uncore.MC[mc].Channel[
RO(Proc)->Uncore.MC[mc].MTL.MADC0.Dimm_L_Map
].DIMM[0].Ranks = 1 + RO(Proc)->Uncore.MC[mc].MTL.MADD0.DLNOR;
RO(Shm)->Uncore.MC[mc].Channel[
!RO(Proc)->Uncore.MC[mc].MTL.MADC0.Dimm_L_Map
].DIMM[0].Ranks = 1 + RO(Proc)->Uncore.MC[mc].MTL.MADD0.DSNOR;
RO(Shm)->Uncore.MC[mc].Channel[
RO(Proc)->Uncore.MC[mc].MTL.MADC1.Dimm_L_Map
].DIMM[0].Ranks = 1 + RO(Proc)->Uncore.MC[mc].MTL.MADD1.DLNOR;
RO(Shm)->Uncore.MC[mc].Channel[
!RO(Proc)->Uncore.MC[mc].MTL.MADC1.Dimm_L_Map
].DIMM[0].Ranks = 1 + RO(Proc)->Uncore.MC[mc].MTL.MADD1.DSNOR;
break;
}
RO(Shm)->Uncore.MC[mc].Channel[0].DIMM[0].Banks = \
!RO(Proc)->Uncore.MC[mc].Channel[0].MTL.Sched.ReservedBits1 ? 16 : 8;
RO(Shm)->Uncore.MC[mc].Channel[1].DIMM[0].Banks = \
!RO(Proc)->Uncore.MC[mc].Channel[1].MTL.Sched.ReservedBits1 ? 16 : 8;
RO(Shm)->Uncore.MC[mc].Channel[0].DIMM[0].Cols = \
RO(Shm)->Uncore.MC[mc].Channel[1].DIMM[0].Cols = 1 << 10;
}
}
#define ARL_CAP MTL_CAP
#define ARL_IMC MTL_IMC
#define LNL_CAP MTL_CAP
#define LNL_IMC MTL_IMC
void AMD_0Fh_MCH(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc))
{
struct {
unsigned int size;
} module[] = {
{256}, {512}, {1024}, {1024},
{1024}, {2048}, {2048}, {4096},
{4096}, {8192}, {8192}, {16384},
{0}, {0}, {0}, {0}
};
unsigned int mask;
unsigned short mc, cha, slot, shift, index;
for (mc = 0; mc < RO(Shm)->Uncore.CtrlCount; mc++)
{
RO(Shm)->Uncore.MC[mc].SlotCount = RO(Proc)->Uncore.MC[mc].SlotCount;
RO(Shm)->Uncore.MC[mc].ChannelCount = RO(Proc)->Uncore.MC[mc].ChannelCount;
for (cha = 0; cha < RO(Shm)->Uncore.MC[mc].ChannelCount; cha++) {
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].AMD0Fh.DTRL.tCL) {
case 0b010:
TIMING(mc, cha).tCL = 3;
break;
case 0b011:
TIMING(mc, cha).tCL = 4;
break;
case 0b100:
TIMING(mc, cha).tCL = 5;
break;
case 0b101:
TIMING(mc, cha).tCL = 6;
break;
}
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].AMD0Fh.DTRL.tRCD) {
case 0b00:
TIMING(mc, cha).tRCD = 3;
break;
case 0b01:
TIMING(mc, cha).tRCD = 4;
break;
case 0b10:
TIMING(mc, cha).tRCD = 5;
break;
case 0b11:
TIMING(mc, cha).tRCD = 6;
break;
}
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].AMD0Fh.DTRL.tRP) {
case 0b00:
TIMING(mc, cha).tRP = 3;
break;
case 0b01:
TIMING(mc, cha).tRP = 4;
break;
case 0b10:
TIMING(mc, cha).tRP = 5;
break;
case 0b11:
TIMING(mc, cha).tRP = 6;
break;
}
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].AMD0Fh.DTRL.tRTPr) {
case 0b0:
if (RO(Proc)->Uncore.MC[mc].AMD0Fh.DCRL.BurstLength32 == 0b1) {
TIMING(mc, cha).tRTPr = 2;
} else {
TIMING(mc, cha).tRTPr = 4;
}
break;
case 0b1:
if (RO(Proc)->Uncore.MC[mc].AMD0Fh.DCRL.BurstLength32 == 0b1) {
TIMING(mc, cha).tRTPr = 3;
} else {
TIMING(mc, cha).tRTPr = 5;
}
break;
}
if (RO(Proc)->Uncore.MC[mc].Channel[cha].AMD0Fh.DTRL.tRAS >= 0b0010) {
TIMING(mc, cha).tRAS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD0Fh.DTRL.tRAS+3;
}
TIMING(mc, cha).tRFC = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD0Fh.DTRL.tRC+11;
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].AMD0Fh.DTRL.tWR) {
case 0b00:
TIMING(mc, cha).tWR = 3;
break;
case 0b01:
TIMING(mc, cha).tWR = 4;
break;
case 0b10:
TIMING(mc, cha).tWR = 5;
break;
case 0b11:
TIMING(mc, cha).tWR = 6;
break;
}
switch (RO(Proc)->Uncore.MC[mc].Channel[cha].AMD0Fh.DTRL.tRRD) {
case 0b00:
TIMING(mc, cha).tRRD = 2;
break;
case 0b01:
TIMING(mc, cha).tRRD = 3;
break;
case 0b10:
TIMING(mc, cha).tRRD = 4;
break;
case 0b11:
TIMING(mc, cha).tRRD = 5;
break;
}
if ((RO(Proc)->Uncore.MC[mc].AMD0Fh.DCRH.tFAW > 0b0000)
&& (RO(Proc)->Uncore.MC[mc].AMD0Fh.DCRH.tFAW <= 0b1101)) {
TIMING(mc, cha).tFAW = \
RO(Proc)->Uncore.MC[mc].AMD0Fh.DCRH.tFAW + 7;
}
if (RO(Proc)->Uncore.MC[mc].AMD0Fh.DCRH.SlowAccessMode == 0b1)
TIMING(mc, cha).CMD_Rate = 2;
else
TIMING(mc, cha).CMD_Rate = 1;
shift = 4 * cha;
mask = 0b1111U << shift;
for (slot = 0; slot < RO(Shm)->Uncore.MC[mc].SlotCount; slot++) {
if (RO(Proc)->Uncore.MC[mc].Channel[cha].DIMM[slot].MBA.CSEnable)
{
index =(RO(Proc)->Uncore.MC[mc].MaxDIMMs.AMD0Fh.CS.value & mask)
>> shift;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Size = \
module[index].size;
}
}
TIMING(mc, cha).ECC = \
RO(Proc)->Uncore.MC[mc].AMD0Fh.DCRL.ECC_DIMM_Enable;
}
}
}
void AMD_0Fh_HTT(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc))
{
unsigned int link = 0;
RAM_Ratio Ratio = {.Q = 0, .R = 0};
unsigned long long HTT_Clock = 0;
switch (RO(Proc)->Uncore.MC[0].AMD0Fh.DCRH.MemClkFreq) {
case 0b000:
Ratio.Q = 200;
Ratio.R = 0;
break;
case 0b001:
Ratio.Q = 266;
Ratio.R = 1;
break;
case 0b010:
Ratio.Q = 333;
Ratio.R = 1;
break;
case 0b011:
Ratio.Q = 400;
Ratio.R = 0;
break;
}
RO(Shm)->Uncore.CtrlSpeed = (Ratio.Q * 2) + Ratio.R; /* DDR2 */
if ((link = RO(Proc)->Uncore.Bus.UnitID.McUnit) < 0b11) {
switch (RO(Proc)->Uncore.Bus.LDTi_Freq[link].LinkFreqMax)
{ /* "MHz" */
case 0b0000:
HTT_Clock = 200;
break;
case 0b0010:
HTT_Clock = 400;
break;
case 0b0100:
HTT_Clock = 600;
break;
case 0b0101:
HTT_Clock = 800;
break;
case 0b0110:
HTT_Clock = 1000;
break;
case 0b1111:
HTT_Clock = 100;
break;
}
RO(Shm)->Uncore.Bus.Rate = HTT_Clock * 2; /* "MT/s" */
RO(Shm)->Uncore.Bus.Speed = HTT_Clock * 4; /* "MB/s" */
}
RO(Shm)->Uncore.Unit.Bus_Rate = MC_MTS;
RO(Shm)->Uncore.Unit.BusSpeed = MC_MBS;
RO(Shm)->Uncore.Unit.DDR_Rate = MC_NIL;
RO(Shm)->Uncore.Unit.DDRSpeed = MC_MHZ;
RO(Shm)->Uncore.Unit.DDR_Ver = 2;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_UNSPEC;
}
void AMD_17h_UMC(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc))
{
unsigned short mc;
RO(Shm)->Proc.Mechanisms.DRAM_Scrambler = 0b11;
RO(Shm)->Proc.Mechanisms.TSME = 0b11;
for (mc = 0; mc < RO(Shm)->Uncore.CtrlCount; mc++)
{
RO(Shm)->Uncore.MC[mc].ChannelCount = RO(Proc)->Uncore.MC[mc].ChannelCount;
RO(Shm)->Uncore.MC[mc].SlotCount = RO(Proc)->Uncore.MC[mc].SlotCount;
unsigned short cha;
for (cha = 0; cha < RO(Shm)->Uncore.MC[mc].ChannelCount; cha++)
{
unsigned long long DIMM_Size;
unsigned short slot;
for (slot = 0; slot < RO(Shm)->Uncore.MC[mc].SlotCount; slot++)
{
const unsigned short chipselect_pair = slot << 1;
if (BITVAL(RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.CHIP[
chipselect_pair
][0].Chip.value, 0)
)
{ /* CSEnable */
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks = 8 << \
RO(Proc)->Uncore.MC[mc].Channel[cha].DIMM[slot].AMD17h.DAC.NumBanks;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows = 1 << (10
+ RO(Proc)->Uncore.MC[mc].Channel[cha].DIMM[slot].AMD17h.DAC.NumRowLo);
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols = 1 << (5
+ RO(Proc)->Uncore.MC[mc].Channel[cha].DIMM[slot].AMD17h.DAC.NumCol);
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks = \
RO(Proc)->Uncore.MC[mc].Channel[cha].DIMM[slot].AMD17h.Ranks;
DIMM_Size = 8LLU;
DIMM_Size *= RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Banks;
DIMM_Size *= RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Ranks;
DIMM_Size *= RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Rows;
DIMM_Size *= RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Cols;
RO(Shm)->Uncore.MC[mc].Channel[cha].DIMM[slot].Size = DIMM_Size >> 20;
}
}
TIMING(mc, cha).tCL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR1.tCL;
TIMING(mc, cha).tRCD_RD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR1.tRCD_RD;
TIMING(mc, cha).tRCD_WR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR1.tRCD_WR;
TIMING(mc, cha).tRP = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR2.tRP;
TIMING(mc, cha).tRAS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR1.tRAS;
TIMING(mc, cha).tRRDS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR3.tRRDS;
TIMING(mc, cha).tRRDL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR3.tRRDL;
TIMING(mc, cha).Zen.tRRDDLR =
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR3.tRRDDLR;
TIMING(mc, cha).tRC = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR2.tRC;
TIMING(mc, cha).tRCPB = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR2.tRCPB;
TIMING(mc, cha).tRPPB = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR2.tRPPB;
TIMING(mc, cha).tFAW = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR4.tFAW;
TIMING(mc, cha).tFAWSLR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR4.tFAWSLR;
TIMING(mc, cha).tFAWDLR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR4.tFAWDLR;
TIMING(mc, cha).tWTRS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR5.tWTRS;
TIMING(mc, cha).tWTRL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR5.tWTRL;
TIMING(mc, cha).tWR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR6.tWR;
TIMING(mc, cha).tRCPage = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR7.tRCPage;
TIMING(mc, cha).Zen.tRdRdScl = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR8.tRdRdScl;
TIMING(mc, cha).Zen.tWrWrScl = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR9.tWrWrScl;
TIMING(mc, cha).Zen.tRdRdBan = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR8.tRdRdBan;
TIMING(mc, cha).Zen.tWrWrBan = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR9.tWrWrBan;
TIMING(mc, cha).tCWL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR5.tCWL;
TIMING(mc, cha).tRTP = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR3.tRTP;
TIMING(mc, cha).Zen.tddRdTWr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR10.tddRdTWr;
TIMING(mc, cha).Zen.tddWrTRd = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR10.tddWrTRd;
TIMING(mc, cha).Zen.tscWrTWr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR9.tscWrTWr;
TIMING(mc, cha).Zen.tsdWrTWr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR9.tsdWrTWr;
TIMING(mc, cha).Zen.tddWrTWr = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR9.tddWrTWr;
TIMING(mc, cha).Zen.tscRdTRd = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR8.tscRdTRd;
TIMING(mc, cha).Zen.tsdRdTRd = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR8.tsdRdTRd;
TIMING(mc, cha).Zen.tddRdTRd = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR8.tddRdTRd;
TIMING(mc, cha).Zen.tRdRdScDLR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR8.tRdRdScDLR;
TIMING(mc, cha).Zen.tWrWrScDLR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR9.tWrWrScDLR;
TIMING(mc, cha).Zen.tWrRdScDLR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR10.tWrRdScDLR;
TIMING(mc, cha).tXP = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR21.tXP;
TIMING(mc, cha).tCKE = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR21.tCKE;
TIMING(mc, cha).tCPDED = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR21.tCPDED;
TIMING(mc, cha).tREFI = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR12.tREFI;
switch(RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.CONFIG.BurstLength) {
case 0x0: /* BL2 */
case 0x1: /* BL4 */
case 0x2: /* BL8 */
TIMING(mc, cha).tRFC1 = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTRFC.DDR4.tRFC1;
TIMING(mc, cha).tRFC2 = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTRFC.DDR4.tRFC2;
TIMING(mc, cha).tRFC4 = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTRFC.DDR4.tRFC4;
switch(RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.MISC.DDR4.CMD_Rate) {
case 0b00:
TIMING(mc, cha).CMD_Rate = 1;
break;
case 0b10:
TIMING(mc, cha).CMD_Rate = 2;
break;
default:
TIMING(mc, cha).CMD_Rate = 0;
break;
}
TIMING(mc, cha).GDM = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.MISC.DDR4.GearDownMode;
break;
case 0x3: /* BL16 */
TIMING(mc, cha).tRFC1 = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTRFC.DDR5.tRFC1;
TIMING(mc, cha).tRFC2 = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTRFC.DDR5.tRFC2;
TIMING(mc, cha).tRFCsb = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.RFCSB.DDR5.tRFCsb;
switch(RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.MISC.DDR5.CMD_Rate) {
case 0b01:
TIMING(mc, cha).CMD_Rate = 1;
break;
case 0b10:
TIMING(mc, cha).CMD_Rate = 2;
break;
case 0b00:
default:
TIMING(mc, cha).CMD_Rate = 0;
break;
}
TIMING(mc, cha).GDM = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.MISC.DDR5.GearDownMode;
break;
}
TIMING(mc, cha).ECC = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.ECC.Hi.Enable;
TIMING(mc, cha).BGS = \
!((RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.BGS.value
& AMD_17_UMC_BGS_MASK_OFF) == AMD_17_UMC_BGS_MASK_OFF);
TIMING(mc, cha).BGS_ALT = \
(RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.BGS_ALT.value
& AMD_17_UMC_BGS_ALT_MASK_ON) == AMD_17_UMC_BGS_ALT_MASK_ON;
TIMING(mc, cha).PDM_EN = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.SPAZ.PwrDownEn;
TIMING(mc, cha).PDM_MODE = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.SPAZ.PwrDownMode;
TIMING(mc, cha).PDM_AGGR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.SPAZ.AggrPwrDownEn;
TIMING(mc, cha).tMRD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR13.tMRD;
TIMING(mc, cha).tMOD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR13.tMOD;
TIMING(mc, cha).tMRD_PDA = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR13.tMRD_PDA;
TIMING(mc, cha).tMOD_PDA = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR13.tMOD_PDA;
TIMING(mc, cha).tXS = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR14.tXS;
TIMING(mc, cha).tSTAG = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR20.tSTAG;
TIMING(mc, cha).tPHYWRD = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR22.tPHY_WRDATA;
TIMING(mc, cha).tPHYWRL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR22.tPHY_WRLAT;
TIMING(mc, cha).tPHYRDL = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR22.tPHY_RDLAT;
TIMING(mc, cha).tRDDATA = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR22.tRDDATA_EN;
TIMING(mc, cha).tWRMPR = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.DTR35.tWR_MPR;
if (RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.ENCR.value != 0xffffffff)
{
TIMING(mc, cha).Scramble = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.ENCR.DataScrambleEn;
RO(Shm)->Proc.Mechanisms.DRAM_Scrambler = \
RO(Shm)->Proc.Mechanisms.DRAM_Scrambler
& (0b10 | TIMING(mc, cha).Scramble);
TIMING(mc, cha).TSME = \
((RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.ENCR.DataEncrEn == 1)
|| (RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.ENCR.ForceEncrEn == 1))
&& (RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.ENCR.DisAddrTweak == 0);
RO(Shm)->Proc.Mechanisms.TSME = RO(Shm)->Proc.Mechanisms.TSME
& (0b10 | TIMING(mc, cha).TSME);
}
}
}
}
void AMD_17h_CAP(RO(SHM_STRUCT) *RO(Shm),
RO(PROC) *RO(Proc), RO(CORE) *RO(Core))
{
unsigned short mc, clock_done = 0;
for (mc = 0; mc < RO(Shm)->Uncore.CtrlCount && !clock_done; mc++)
{
unsigned short cha;
for (cha = 0;
cha < RO(Shm)->Uncore.MC[mc].ChannelCount && !clock_done;
cha++)
{
unsigned short slot;
switch(RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.CONFIG.BurstLength) {
case 0x0: /* BL2 */
case 0x1: /* BL4 */
case 0x2: /* BL8 */
if (RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.MISC.DDR4.MEMCLK)
{
RO(Shm)->Uncore.Bus.Rate = \
RO(Shm)->Uncore.Bus.Speed = \
RO(Shm)->Uncore.CtrlSpeed = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.MISC.DDR4.MEMCLK;
RO(Shm)->Uncore.Bus.Rate = \
( RO(Shm)->Uncore.Bus.Rate
* RO(Shm)->Proc.Features.Factory.Clock.Q ) / 3;
RO(Shm)->Uncore.Bus.Speed = \
( RO(Shm)->Uncore.Bus.Speed
* RO(Core)->Clock.Hz * 333333333LLU )
/ ( RO(Shm)->Proc.Features.Factory.Clock.Hz
* ( 1000LLU * PRECISION * PRECISION ) );
RO(Shm)->Uncore.CtrlSpeed = \
( RO(Shm)->Uncore.CtrlSpeed
* RO(Core)->Clock.Hz * 666666666LLU )
/ ( RO(Shm)->Proc.Features.Factory.Clock.Hz
* ( 1000LLU * PRECISION * PRECISION ) );
RO(Shm)->Uncore.Unit.DDR_Ver = 4;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_SDRAM;
clock_done = 1;
}
break;
case 0x3: /* BL16 */
if (RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.MISC.DDR5.MEMCLK)
{
RO(Shm)->Uncore.Bus.Rate = \
RO(Shm)->Uncore.Bus.Speed = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.MISC.DDR5.MEMCLK;
RO(Shm)->Uncore.Bus.Speed = \
( RO(Shm)->Uncore.Bus.Speed * RO(Core)->Clock.Hz )
/ RO(Shm)->Proc.Features.Factory.Clock.Hz;
RO(Shm)->Uncore.CtrlSpeed = 2LLU * RO(Shm)->Uncore.Bus.Speed;
RO(Shm)->Uncore.Unit.DDR_Ver = 5;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_SDRAM;
clock_done = 1;
}
break;
}
for (slot = 0; slot < RO(Shm)->Uncore.MC[mc].SlotCount; slot++)
{
if (RO(Proc)->Uncore.MC[mc].Channel[cha].DIMM[slot].AMD17h\
.CFG.value != 0xffffffff)
{
if (RO(Proc)->Uncore.MC[mc].Channel[cha].DIMM[slot].AMD17h.CFG.RDIMM
|| RO(Proc)->Uncore.MC[mc].Channel[cha].DIMM[slot].AMD17h.CFG.LRDIMM)
{
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_RDIMM;
break;
}
}
}
}
}
RO(Shm)->Uncore.Unit.Bus_Rate = MC_MHZ;
RO(Shm)->Uncore.Unit.BusSpeed = MC_MHZ;
RO(Shm)->Uncore.Unit.DDR_Rate = MC_NIL;
RO(Shm)->Uncore.Unit.DDRSpeed = MC_MTS;
}
void AMD_17h_IOMMU(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc))
{
RO(Shm)->Proc.Technology.IOMMU = RO(Proc)->Uncore.Bus.IOMMU_CR.IOMMU_En;
RO(Shm)->Proc.Technology.IOMMU_Ver_Major = \
(RO(Proc)->Uncore.Bus.IOMMU_HDR.CapRev & 0b10000) >> 5;
RO(Shm)->Proc.Technology.IOMMU_Ver_Minor = \
RO(Proc)->Uncore.Bus.IOMMU_HDR.CapRev & 0b01111;
}
void AMD_1Ah_STX_CAP( RO(SHM_STRUCT) *RO(Shm),
RO(PROC) *RO(Proc), RO(CORE) *RO(Core) )
{
unsigned short mc, clock_done = 0;
for (mc = 0; mc < RO(Shm)->Uncore.CtrlCount && !clock_done; mc++)
{
unsigned short cha;
for (cha = 0;
cha < RO(Shm)->Uncore.MC[mc].ChannelCount && !clock_done;
cha++)
{
const AMD_ZEN_UMC_CFG_MISC MISC = \
RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.MISC;
unsigned short slot;
if (MISC.DDR5.MEMCLK)
{
const unsigned int correction = \
BITEXTRZ((unsigned long long)MISC.value, 0, 3) == 0 ? 0 : 2;
RO(Shm)->Uncore.Bus.Rate = 4U * MISC.DDR5.MEMCLK;
RO(Shm)->Uncore.Bus.Rate = RO(Shm)->Uncore.Bus.Rate + correction;
RO(Shm)->Uncore.Bus.Speed =(unsigned long long)RO(Shm)->Uncore.Bus.Rate;
RO(Shm)->Uncore.Bus.Speed = \
( RO(Shm)->Uncore.Bus.Speed * RO(Core)->Clock.Hz )
/ RO(Shm)->Proc.Features.Factory.Clock.Hz;
RO(Shm)->Uncore.CtrlSpeed = 2LLU * RO(Shm)->Uncore.Bus.Rate;
clock_done = 1;
}
switch(RO(Proc)->Uncore.MC[mc].Channel[cha].AMD17h.CONFIG.BurstLength) {
case 0x0: /* BL2 */
case 0x1: /* BL4 */
case 0x2: /* BL8 */
RO(Shm)->Uncore.Unit.DDR_Ver = 4;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_LPDDR;
break;
case 0x3: /* BL16 */
RO(Shm)->Uncore.Unit.DDR_Ver = 5;
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_LPDDR;
break;
}
for (slot = 0; slot < RO(Shm)->Uncore.MC[mc].SlotCount; slot++)
{
if (RO(Proc)->Uncore.MC[mc].Channel[cha].DIMM[slot].AMD17h\
.CFG.value != 0xffffffff)
{
if (RO(Proc)->Uncore.MC[mc].Channel[cha].DIMM[slot].AMD17h.CFG.RDIMM
|| RO(Proc)->Uncore.MC[mc].Channel[cha].DIMM[slot].AMD17h.CFG.LRDIMM)
{
RO(Shm)->Uncore.Unit.DDR_Std = RAM_STD_RDIMM;
break;
}
}
}
}
}
RO(Shm)->Uncore.Unit.Bus_Rate = MC_MHZ;
RO(Shm)->Uncore.Unit.BusSpeed = MC_MHZ;
RO(Shm)->Uncore.Unit.DDR_Rate = MC_NIL;
RO(Shm)->Uncore.Unit.DDRSpeed = MC_MTS;
}
#undef TIMING
static char *Chipset[CHIPSETS] = {
[IC_CHIPSET] = NULL,
[IC_LAKEPORT] = "82945/Lakeport",
[IC_LAKEPORT_P] = "82946/Lakeport-P",
[IC_LAKEPORT_X] = "82955/Lakeport-X",
[IC_CALISTOGA] = "82945/Calistoga",
[IC_BROADWATER] = "82965/Broadwater",
[IC_CRESTLINE] = "82965/Crestline",
[IC_CANTIGA] = "G45/Cantiga",
[IC_BEARLAKE_Q] = "Q35/Bearlake-Q",
[IC_BEARLAKE_P] = "G33/Bearlake-PG+",
[IC_BEARLAKE_QF] = "Q33/Bearlake-QF",
[IC_BEARLAKE_X] = "X38/Bearlake-X",
[IC_INTEL_3200] = "Intel 3200",
[IC_EAGLELAKE_Q] = "Q45/Eaglelake-Q",
[IC_EAGLELAKE_P] = "G45/Eaglelake-P",
[IC_EAGLELAKE_G] = "G41/Eaglelake-G",
[IC_PINEVIEW] = "Pineview",
[IC_CEDARVIEW] = "Cedarview",
[IC_BAYTRAIL] = "Bay Trail",
[IC_AIRMONT] = "Airmont",
[IC_GOLDMONT_PLUS] = "Goldmont Plus",
[IC_TYLERSBURG] = "X58/Tylersburg",
[IC_IBEXPEAK] = "P55/Ibex Peak",
[IC_IBEXPEAK_M] = "QM57/Ibex Peak-M",
[IC_COUGARPOINT] = "P67/Cougar Point",
[IC_PATSBURG] = "X79/Patsburg",
[IC_CAVECREEK] = "Cave Creek",
[IC_WELLSBURG] = "X99/Wellsburg",
[IC_PANTHERPOINT] = "Panther Point",
[IC_PANTHERPOINT_M] = "Panther Point-M",
[IC_LYNXPOINT] = "Lynx Point",
[IC_LYNXPOINT_M] = "Lynx Point-M",
[IC_WILDCATPOINT] = "Wildcat Point",
[IC_WILDCATPOINT_M] = "Wildcat Point-M",
[IC_SUNRISEPOINT] = "Sunrise Point",
[IC_UNIONPOINT] = "Union Point",
[IC_CANNONPOINT] = "Cannon Point",
[IC_400_SERIES_P] = "400 Series-Prem-U",
[IC_400_SERIES_M] = "400 Series-Base-U",
[IC_495] = "Intel 495",
[IC_H470] = "Intel H470",
[IC_Z490] = "Intel Z490",
[IC_Q470] = "Intel Q470",
[IC_HM470] = "Intel HM470",
[IC_QM480] = "Intel QM480",
[IC_WM490] = "Intel WM490",
[IC_W480] = "Intel W480",
[IC_H510] = "Intel H510",
[IC_B560] = "Intel B560",
[IC_H570] = "Intel H570",
[IC_Q570] = "Intel Q570",
[IC_Z590] = "Intel Z590",
[IC_W580] = "Intel W580",
[IC_H610] = "Intel H610",
[IC_B660] = "Intel B660",
[IC_H670] = "Intel H670",
[IC_Z690] = "Intel Z690",
[IC_Q670] = "Intel Q670",
[IC_W680] = "Intel W680",
[IC_WM690] = "Intel WM690",
[IC_HM670] = "Intel HM670",
[IC_ADL_PCH_P] = "Intel ADL PCH-P",
[IC_ADL_PCH_U] = "Intel ADL PCH-U",
[IC_ADL_PCH_N305] = "Intel ADL N305",
[IC_ADL_PCH_N95] = "Intel ADL N95",
[IC_ADL_PCH_X7000E] = "Intel X7000E",
[IC_ADL_PCH_X7000RE] = "Intel X7000RE",
[IC_Z790] = "Intel Z790",
[IC_H770] = "Intel H770",
[IC_B760] = "Intel B760",
[IC_WM790] = "Intel WM790",
[IC_HM770] = "Intel HM770",
[IC_C262] = "Intel C262",
[IC_C266] = "Intel C266",
[IC_MTL_H] = "Intel MTL-H",
[IC_MTL_U] = "Intel MTL-U",
[IC_MTL_UT4] = "Intel MTL-U Type4",
[IC_ARL_S] = "Intel ARL-S",
[IC_LNL_V] = "Intel LNL-V",
[IC_K8] = "K8/HyperTransport",
[IC_ZEN] = "Zen UMC"
};
#define SET_CHIPSET(ic) \
({ \
RO(Shm)->Uncore.ChipID = DID; \
RO(Shm)->Uncore.Chipset.ArchID = ic; \
})
void PCI_Intel(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc), RO(CORE) *RO(Core),
unsigned short DID)
{
switch (DID) {
case DID_INTEL_82945P_HB:
P945_CLK(RO(Shm), RO(Proc), RO(Core));
P945_MCH(RO(Shm), RO(Proc));
SET_CHIPSET(IC_LAKEPORT);
break;
case DID_INTEL_82945GM_HB:
case DID_INTEL_82945GME_HB:
P945_CLK(RO(Shm), RO(Proc), RO(Core));
P945_MCH(RO(Shm), RO(Proc));
SET_CHIPSET(IC_CALISTOGA);
break;
case DID_INTEL_82955_HB:
P945_CLK(RO(Shm), RO(Proc), RO(Core));
P955_MCH(RO(Shm), RO(Proc));
SET_CHIPSET(IC_LAKEPORT_X);
break;
case DID_INTEL_82946GZ_HB:
P965_CLK(RO(Shm), RO(Proc), RO(Core));
P965_MCH(RO(Shm), RO(Proc));
SET_CHIPSET(IC_LAKEPORT_P);
break;
case DID_INTEL_82965Q_HB:
case DID_INTEL_82965G_HB:
P965_CLK(RO(Shm), RO(Proc), RO(Core));
P965_MCH(RO(Shm), RO(Proc));
SET_CHIPSET(IC_BROADWATER);
break;
case DID_INTEL_82965GM_HB:
case DID_INTEL_82965GME_HB:
G965_CLK(RO(Shm), RO(Proc), RO(Core));
G965_MCH(RO(Shm), RO(Proc));
SET_CHIPSET(IC_CRESTLINE);
break;
case DID_INTEL_GM45_HB:
G965_CLK(RO(Shm), RO(Proc), RO(Core));
G965_MCH(RO(Shm), RO(Proc));
SET_CHIPSET(IC_CANTIGA);
break;
case DID_INTEL_Q35_HB:
P35_CLK(RO(Shm), RO(Proc), RO(Core));
P35_MCH(RO(Shm), RO(Proc));
SET_CHIPSET(IC_BEARLAKE_Q);
break;
case DID_INTEL_G33_HB:
P35_CLK(RO(Shm), RO(Proc), RO(Core));
P35_MCH(RO(Shm), RO(Proc));
SET_CHIPSET(IC_BEARLAKE_P);
break;
case DID_INTEL_Q33_HB:
P35_CLK(RO(Shm), RO(Proc), RO(Core));
P35_MCH(RO(Shm), RO(Proc));
SET_CHIPSET(IC_BEARLAKE_QF);
break;
case DID_INTEL_X38_HB:
P35_CLK(RO(Shm), RO(Proc), RO(Core));
P35_MCH(RO(Shm), RO(Proc));
SET_CHIPSET(IC_BEARLAKE_X);
break;
case DID_INTEL_3200_HB:
P35_CLK(RO(Shm), RO(Proc), RO(Core));
P35_MCH(RO(Shm), RO(Proc));
SET_CHIPSET(IC_INTEL_3200);
break;
case DID_INTEL_Q45_HB:
P35_CLK(RO(Shm), RO(Proc), RO(Core));
P4S_MCH(RO(Shm), RO(Proc));
SET_CHIPSET(IC_EAGLELAKE_Q);
break;
case DID_INTEL_G45_HB:
P35_CLK(RO(Shm), RO(Proc), RO(Core));
P4S_MCH(RO(Shm), RO(Proc));
SET_CHIPSET(IC_EAGLELAKE_P);
break;
case DID_INTEL_G41_HB:
P35_CLK(RO(Shm), RO(Proc), RO(Core));
P4S_MCH(RO(Shm), RO(Proc));
SET_CHIPSET(IC_EAGLELAKE_G);
break;
case DID_INTEL_BONNELL_HB:
P35_CLK(RO(Shm), RO(Proc), RO(Core));
P35_MCH(RO(Shm), RO(Proc));
SET_CHIPSET(IC_PINEVIEW);
break;
case DID_INTEL_SALTWELL_HB:
SLM_PTR(RO(Shm), RO(Proc), RO(Core));
SET_CHIPSET(IC_CEDARVIEW);
break;
case DID_INTEL_SLM_PTR:
SLM_PTR(RO(Shm), RO(Proc), RO(Core));
SET_CHIPSET(IC_BAYTRAIL);
break;
case DID_INTEL_AIRMONT_HB:
AMT_MCR(RO(Shm), RO(Proc), RO(Core));
SET_CHIPSET(IC_AIRMONT);
break;
case DID_INTEL_X58_HUB_CTRL:
QPI_CLK(RO(Shm), RO(Proc), RO(Core));
break;
case DID_INTEL_X58_HUB_CORE:
case DID_INTEL_IIO_CORE_REG:
case DID_INTEL_IVB_EP_IIO_VTD:
X58_VTD(RO(Shm), RO(Proc), RO(Core));
break;
case DID_INTEL_I7_MCR: /* Bloomfield */
case DID_INTEL_NHM_EP_MCR: /* Westmere EP */
NHM_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_TYLERSBURG);
break;
case DID_INTEL_I7_MC_TEST:
case DID_INTEL_LYNNFIELD_MC_TEST:
case DID_INTEL_NHM_EP_MC_TEST:
case DID_INTEL_NHM_EC_MC_TEST:
DMI_CLK(RO(Shm), RO(Proc), RO(Core));
break;
case DID_INTEL_LYNNFIELD_MCR: /* Lynnfield */
case DID_INTEL_NHM_EC_MCR: /* C5500-C3500 */
NHM_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_IBEXPEAK);
break;
case DID_INTEL_SNB_IMC_HA0: /* Sandy Bridge-E */
SNB_EP_CAP(RO(Shm), RO(Proc), RO(Core));
SNB_EP_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_PATSBURG);
break;
case DID_INTEL_SNB_IMC_SA: /* SNB Desktop */
SNB_CAP(RO(Shm), RO(Proc), RO(Core));
SNB_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_COUGARPOINT);
break;
case DID_INTEL_SNB_IMC_0104:
SNB_CAP(RO(Shm), RO(Proc), RO(Core));
SNB_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_IBEXPEAK_M);
break;
case DID_INTEL_SNB_EP_HOST_BRIDGE: /* Xeon E5-2640 */
case DID_INTEL_IVB_EP_HOST_BRIDGE: /* Xeon E5 & E7 v2 */
SNB_EP_CAP(RO(Shm), RO(Proc), RO(Core));
SNB_EP_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_CAVECREEK);
break;
case DID_INTEL_IVB_IMC_SA: /* IVB Desktop */
IVB_CAP(RO(Shm), RO(Proc), RO(Core));
SNB_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_PANTHERPOINT);
break;
case DID_INTEL_IVB_IMC_0154: /* IVB Mobile i5-3337U */
IVB_CAP(RO(Shm), RO(Proc), RO(Core));
SNB_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_PANTHERPOINT_M);
break;
case DID_INTEL_HASWELL_IMC_SA: /* HSW & BDW Desktop */
case DID_INTEL_HASWELL_MH_IMC_HA0: /* HSW Mobile M/H */
HSW_CAP(RO(Shm), RO(Proc), RO(Core));
HSW_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_LYNXPOINT_M);
break;
case DID_INTEL_HASWELL_UY_IMC_HA0: /* HSW Mobile U/Y */
HSW_CAP(RO(Shm), RO(Proc), RO(Core));
HSW_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_LYNXPOINT_M);
break;
case DID_INTEL_HASWELL_IMC_HA0: /* Haswell */
HSW_CAP(RO(Shm), RO(Proc), RO(Core));
HSW_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_LYNXPOINT);
break;
case DID_INTEL_HSW_EP_HOST_BRIDGE:
HSW_EP_CAP(RO(Shm), RO(Proc), RO(Core));
HSW_EP_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_WELLSBURG);
break;
case DID_INTEL_BROADWELL_IMC_HA0: /* Broadwell/Y/U Core m */
HSW_CAP(RO(Shm), RO(Proc), RO(Core));
HSW_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_WILDCATPOINT_M);
break;
case DID_INTEL_BROADWELL_D_IMC_HA0: /* BDW/Desktop */
case DID_INTEL_BROADWELL_H_IMC_HA0: /* Broadwell/H */
case DID_INTEL_BROADWELL_U_IMC_HA0: /* Broadwell/U */
HSW_CAP(RO(Shm), RO(Proc), RO(Core));
HSW_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_WELLSBURG);
break;
case DID_INTEL_SKYLAKE_U_IMC_HA: /* Skylake/U Processor */
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_SUNRISEPOINT);
break;
case DID_INTEL_SKYLAKE_Y_IMC_HA: /* Skylake/Y Processor */
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_SUNRISEPOINT);
break;
case DID_INTEL_SKYLAKE_S_IMC_HAD: /* Skylake/S Dual Core */
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_SUNRISEPOINT);
break;
case DID_INTEL_SKYLAKE_S_IMC_HAQ: /* Skylake/S Quad Core */
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_SUNRISEPOINT);
break;
case DID_INTEL_SKYLAKE_H_IMC_HAD: /* Skylake/H Dual Core */
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_SUNRISEPOINT);
break;
case DID_INTEL_SKYLAKE_H_IMC_HAQ: /* Skylake/H Quad Core */
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_SUNRISEPOINT);
break;
case DID_INTEL_SKYLAKE_DT_IMC_HA: /* Skylake/DT Server */
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_SUNRISEPOINT);
break;
case DID_INTEL_KABYLAKE_U_IMC_HA: /* BGA 1356 */
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_UNIONPOINT);
break;
case DID_INTEL_KABYLAKE_Y_IMC_HA: /* BGA 1515 */
case DID_INTEL_KABYLAKE_Y_IMC_HQ:
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_UNIONPOINT);
break;
case DID_INTEL_KABYLAKE_H_IMC_HAD: /* Kaby Lake/H Dual Core */
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_UNIONPOINT);
break;
case DID_INTEL_KABYLAKE_S_IMC_HAD: /* Kaby Lake/S Dual Core */
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_UNIONPOINT);
break;
case DID_INTEL_KABYLAKE_H_IMC_HAQ: /* Kaby Lake/H Quad Core */
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_UNIONPOINT);
break;
case DID_INTEL_KABYLAKE_DT_IMC_HA: /* Kaby Lake/DT Server */
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_UNIONPOINT);
break;
case DID_INTEL_KABYLAKE_U_IMC_HAQ: /* U-Quad Core BGA 1356 */
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_UNIONPOINT);
break;
case DID_INTEL_KABYLAKE_S_IMC_HAQ: /* Kaby Lake/S Quad Core */
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_UNIONPOINT);
break;
case DID_INTEL_KABYLAKE_X_IMC_HAQ:
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_UNIONPOINT);
break;
case DID_INTEL_COFFEELAKE_S_IMC_HAQ: /* Coffee Lake Quad Core */
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_CANNONPOINT);
break;
case DID_INTEL_COFFEELAKE_S_IMC_HAS: /* Coffee Lake Hexa Core */
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_CANNONPOINT);
break;
case DID_INTEL_COFFEELAKE_R_S_IMC_HAD:
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_CANNONPOINT);
break;
case DID_INTEL_COFFEELAKE_R_U_IMC_HAD:
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_CANNONPOINT);
break;
case DID_INTEL_COFFEELAKE_R_U_IMC_HAQ:
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_CANNONPOINT);
break;
case DID_INTEL_COFFEELAKE_R_H_IMC_HAQ:
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_CANNONPOINT);
break;
case DID_INTEL_COFFEELAKE_R_H_IMC_HAS:
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_CANNONPOINT);
break;
case DID_INTEL_COFFEELAKE_R_H_IMC_HAO:
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_CANNONPOINT);
break;
case DID_INTEL_COFFEELAKE_R_W_IMC_HAQ:
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_CANNONPOINT);
break;
case DID_INTEL_COFFEELAKE_R_W_IMC_HAS:
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_CANNONPOINT);
break;
case DID_INTEL_COFFEELAKE_R_W_IMC_HAO:
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_CANNONPOINT);
break;
case DID_INTEL_COFFEELAKE_R_S_IMC_HAQ:
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_CANNONPOINT);
break;
case DID_INTEL_COFFEELAKE_R_S_IMC_HAS:
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_CANNONPOINT);
break;
case DID_INTEL_COFFEELAKE_R_S_IMC_HAO:
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_CANNONPOINT);
break;
case DID_INTEL_WHISKEYLAKE_U_IMC_HAD: /* WHL Dual Core */
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_CANNONPOINT);
break;
case DID_INTEL_WHISKEYLAKE_U_IMC_HAQ: /* WHL Quad Core */
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_CANNONPOINT);
break;
case DID_INTEL_CANNONLAKE_U_IMC_HB: /* CNL-U */
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_CANNONPOINT);
break;
case DID_INTEL_COMETLAKE_S_IMC_6C:
case DID_INTEL_COMETLAKE_S_IMC_10C:
case DID_INTEL_COMETLAKE_H_IMC_10C:
case DID_INTEL_COMETLAKE_W_IMC_10C:
case DID_INTEL_COMETLAKE_M_IMC_6C:
case DID_INTEL_COMETLAKE_S1_IMC:
case DID_INTEL_COMETLAKE_S2_IMC:
case DID_INTEL_COMETLAKE_S5_IMC:
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
break;
case DID_INTEL_COMETLAKE_U_IMC_HB:
case DID_INTEL_COMETLAKE_U1_IMC:
case DID_INTEL_COMETLAKE_U3_IMC:
RKL_CAP(RO(Shm), RO(Proc), RO(Core));
RKL_IMC(RO(Shm), RO(Proc));
break;
case DID_INTEL_COMETLAKE_PREM_U_PCH:
SET_CHIPSET(IC_400_SERIES_P);
break;
case DID_INTEL_COMETLAKE_BASE_U_PCH:
SET_CHIPSET(IC_400_SERIES_M);
break;
case DID_INTEL_COMETLAKE_U_ES_PCH:
case DID_INTEL_COMETLAKE_Y_ES_PCH:
case DID_INTEL_COMETLAKE_Y_PCH:
case DID_INTEL_ICELAKE_U_PCH:
SET_CHIPSET(IC_495);
break;
case DID_INTEL_COMETLAKE_H470_PCH:
SET_CHIPSET(IC_H470);
break;
case DID_INTEL_COMETLAKE_Z490_PCH:
SET_CHIPSET(IC_Z490);
break;
case DID_INTEL_COMETLAKE_Q470_PCH:
SET_CHIPSET(IC_Q470);
break;
case DID_INTEL_COMETLAKE_HM470_PCH:
SET_CHIPSET(IC_HM470);
break;
case DID_INTEL_COMETLAKE_QM480_PCH:
SET_CHIPSET(IC_QM480);
break;
case DID_INTEL_COMETLAKE_WM490_PCH:
SET_CHIPSET(IC_WM490);
break;
case DID_INTEL_COMETLAKE_W480_PCH:
SET_CHIPSET(IC_W480);
break;
case DID_INTEL_ICELAKE_U_IMC:
case DID_INTEL_ICELAKE_U_4C:
SKL_CAP(RO(Shm), RO(Proc), RO(Core));
SKL_IMC(RO(Shm), RO(Proc));
break;
case DID_INTEL_TIGERLAKE_U1_IMC:
case DID_INTEL_TIGERLAKE_U2_IMC:
case DID_INTEL_TIGERLAKE_U3_IMC:
case DID_INTEL_TIGERLAKE_U4_IMC:
case DID_INTEL_TIGERLAKE_H_IMC:
TGL_CAP(RO(Shm), RO(Proc), RO(Core));
TGL_IMC(RO(Shm), RO(Proc));
break;
case DID_INTEL_ROCKETLAKE_S_8C_IMC_HB:
case DID_INTEL_ROCKETLAKE_S_6C_IMC_HB:
RKL_CAP(RO(Shm), RO(Proc), RO(Core));
RKL_IMC(RO(Shm), RO(Proc));
break;
case DID_INTEL_TIGERLAKE_UP3_IMC:
case DID_INTEL_TIGERLAKE_UP4_IMC:
SET_CHIPSET(IC_H510);
break;
case DID_INTEL_ROCKETLAKE_H510_PCH:
SET_CHIPSET(IC_H510);
break;
case DID_INTEL_ROCKETLAKE_B560_PCH:
SET_CHIPSET(IC_B560);
break;
case DID_INTEL_ROCKETLAKE_H570_PCH:
SET_CHIPSET(IC_H570);
break;
case DID_INTEL_ROCKETLAKE_Q570_PCH:
SET_CHIPSET(IC_Q570);
break;
case DID_INTEL_ROCKETLAKE_Z590_PCH:
SET_CHIPSET(IC_Z590);
break;
case DID_INTEL_ROCKETLAKE_W580_PCH:
SET_CHIPSET(IC_W580);
break;
case DID_INTEL_ALDERLAKE_S_8P_8E_HB:
case DID_INTEL_ALDERLAKE_S_8P_4E_HB:
case DID_INTEL_ALDERLAKE_S_6P_4E_HB:
case DID_INTEL_ALDERLAKE_S_6P_0E_HB:
case DID_INTEL_ALDERLAKE_S_4P_0E_HB:
case DID_INTEL_ALDERLAKE_S_2P_0E_HB:
case DID_INTEL_ALDERLAKE_H_6P_8E_HB:
case DID_INTEL_ALDERLAKE_H_6P_4E_HB:
case DID_INTEL_ALDERLAKE_H_4P_8E_HB:
case DID_INTEL_ALDERLAKE_H_4P_4E_HB:
case DID_INTEL_ALDERLAKE_HL_6P_8E_HB:
case DID_INTEL_ALDERLAKE_U_2P_8E_HB:
case DID_INTEL_ALDERLAKE_U_2P_4E_HB:
case DID_INTEL_ALDERLAKE_U_1P_4E_HB:
case DID_INTEL_ALDERLAKE_N300_8E_HB:
case DID_INTEL_ALDERLAKE_N200_4E_HB:
case DID_INTEL_ALDERLAKE_N100_4E_HB:
case DID_INTEL_ALDERLAKE_X7835RE_8C_HB:
case DID_INTEL_ALDERLAKE_X7433RE_4C_HB:
case DID_INTEL_ALDERLAKE_N97_4E_HB:
case DID_INTEL_ALDERLAKE_X7425E_4C_HB:
case DID_INTEL_ALDERLAKE_N50_2E_HB:
case DID_INTEL_ALDERLAKE_X7213RE_2C_HB:
case DID_INTEL_ALDERLAKE_X7211RE_2C_HB:
case DID_INTEL_ALDERLAKE_X7213E_2C_HB:
case DID_INTEL_ALDERLAKE_X7211E_2C_HB:
ADL_CAP(RO(Shm), RO(Proc), RO(Core));
ADL_IMC(RO(Shm), RO(Proc));
break;
case DID_INTEL_ALDERLAKE_H610_PCH:
SET_CHIPSET(IC_H610);
break;
case DID_INTEL_ALDERLAKE_B660_PCH:
SET_CHIPSET(IC_B660);
break;
case DID_INTEL_ALDERLAKE_H670_PCH:
SET_CHIPSET(IC_H670);
break;
case DID_INTEL_ALDERLAKE_Z690_PCH:
SET_CHIPSET(IC_Z690);
break;
case DID_INTEL_ALDERLAKE_Q670_PCH:
SET_CHIPSET(IC_Q670);
break;
case DID_INTEL_ALDERLAKE_W680_PCH:
SET_CHIPSET(IC_W680);
break;
case DID_INTEL_ALDERLAKE_WM690_PCH:
SET_CHIPSET(IC_WM690);
break;
case DID_INTEL_ALDERLAKE_HM670_PCH:
SET_CHIPSET(IC_HM670);
break;
case DID_INTEL_ALDERLAKE_PCH_P:
SET_CHIPSET(IC_ADL_PCH_P);
break;
case DID_INTEL_ALDERLAKE_PCH_U:
SET_CHIPSET(IC_ADL_PCH_U);
break;
case DID_INTEL_ALDERLAKE_N305_PCH:
SET_CHIPSET(IC_ADL_PCH_N305);
break;
case DID_INTEL_ALDERLAKE_N95_PCH:
SET_CHIPSET(IC_ADL_PCH_N95);
break;
case DID_INTEL_ALDERLAKE_X7000E_PCH:
SET_CHIPSET(IC_ADL_PCH_X7000E);
break;
case DID_INTEL_ALDERLAKE_X7000RE_PCH:
SET_CHIPSET(IC_ADL_PCH_X7000RE);
break;
case DID_INTEL_GEMINILAKE_HB:
GLK_CAP(RO(Shm), RO(Proc), RO(Core));
GLK_IMC(RO(Shm), RO(Proc));
SET_CHIPSET(IC_GOLDMONT_PLUS);
break;
case DID_INTEL_RAPTORLAKE_S_8P_16E_HB:
case DID_INTEL_RAPTORLAKE_S_8P_12E_HB:
case DID_INTEL_RAPTORLAKE_S_8P_8E_HB:
case DID_INTEL_RAPTORLAKE_S_6P_8E_HB1:
case DID_INTEL_RAPTORLAKE_S_6P_4E_HB:
case DID_INTEL_RAPTORLAKE_S_6P_8E_HB2:
case DID_INTEL_RAPTORLAKE_S_4P_0E_HB:
case DID_INTEL_RAPTORLAKE_HX_8P_16E_HB:
case DID_INTEL_RAPTORLAKE_HX_8P_12E_HB:
case DID_INTEL_RAPTORLAKE_HX_8P_8E_HB1:
case DID_INTEL_RAPTORLAKE_HX_6P_8E_HB1:
case DID_INTEL_RAPTORLAKE_HX_6P_4E_HB1:
case DID_INTEL_RAPTORLAKE_HX_8P_8E_HB2:
case DID_INTEL_RAPTORLAKE_HX_6P_8E_HB2:
case DID_INTEL_RAPTORLAKE_HX_6P_4E_HB2:
case DID_INTEL_RAPTORLAKE_H_6P_8E_HB:
case DID_INTEL_RAPTORLAKE_H_4P_8E_HB:
case DID_INTEL_RAPTORLAKE_H_6P_4E_HB:
case DID_INTEL_RAPTORLAKE_H_4P_4E_HB:
case DID_INTEL_RAPTORLAKE_U_2P_8E_HB:
case DID_INTEL_RAPTORLAKE_U_2P_4E_HB:
case DID_INTEL_RAPTORLAKE_U_1P_4E_HB:
case DID_INTEL_RAPTORLAKE_E_8P_0E_HB:
case DID_INTEL_RAPTORLAKE_E_6P_0E_HB:
case DID_INTEL_RAPTORLAKE_E_4P_0E_HB:
case DID_INTEL_RAPTORLAKE_PX_6P_8E_HB:
case DID_INTEL_RAPTORLAKE_PX_4P_8E_HB:
RPL_CAP(RO(Shm), RO(Proc), RO(Core));
RPL_IMC(RO(Shm), RO(Proc));
break;
case DID_INTEL_RAPTORLAKE_Z790_PCH:
SET_CHIPSET(IC_Z790);
break;
case DID_INTEL_RAPTORLAKE_H770_PCH:
SET_CHIPSET(IC_H770);
break;
case DID_INTEL_RAPTORLAKE_B760_PCH:
SET_CHIPSET(IC_B760);
break;
case DID_INTEL_RAPTORLAKE_WM790_PCH:
SET_CHIPSET(IC_WM790);
break;
case DID_INTEL_RAPTORLAKE_HM770_PCH:
SET_CHIPSET(IC_HM770);
break;
case DID_INTEL_RAPTORLAKE_C262_PCH:
SET_CHIPSET(IC_C262);
break;
case DID_INTEL_RAPTORLAKE_C266_PCH:
SET_CHIPSET(IC_C266);
break;
case DID_INTEL_METEORLAKE_UT4_2_8_2_HB:
case DID_INTEL_METEORLAKE_H_6_8_2_HB:
case DID_INTEL_METEORLAKE_U_2_8_2_HB:
case DID_INTEL_METEORLAKE_H_4_8_2_HB:
case DID_INTEL_METEORLAKE_U_2_4_2_HB:
case DID_INTEL_METEORLAKE_M_6_8_2_HB:
case DID_INTEL_METEORLAKE_M_4_8_2_HB:
case DID_INTEL_METEORLAKE_M_2_8_2_HB:
case DID_INTEL_METEORLAKE_M_4_4_2_HB:
MTL_CAP(RO(Shm), RO(Proc), RO(Core));
MTL_IMC(RO(Shm), RO(Proc));
break;
case DID_INTEL_METEORLAKE_H_PCH:
SET_CHIPSET(IC_MTL_H);
break;
case DID_INTEL_METEORLAKE_U_PCH:
SET_CHIPSET(IC_MTL_U);
break;
case DID_INTEL_METEORLAKE_UT4_PCH:
SET_CHIPSET(IC_MTL_UT4);
break;
case DID_INTEL_ARROWLAKE_S_8_16_HB:
case DID_INTEL_ARROWLAKE_S_8_12_HB:
case DID_INTEL_ARROWLAKE_S_6_8_HB:
ARL_CAP(RO(Shm), RO(Proc), RO(Core));
ARL_IMC(RO(Shm), RO(Proc));
break;
case DID_INTEL_ARROWLAKE_S_PCH:
SET_CHIPSET(IC_ARL_S);
break;
case DID_INTEL_LUNARLAKE_V_4P_4E:
LNL_CAP(RO(Shm), RO(Proc), RO(Core));
LNL_IMC(RO(Shm), RO(Proc));
break;
case DID_INTEL_LUNARLAKE_V_PCH:
SET_CHIPSET(IC_LNL_V);
break;
}
}
void PCI_AMD(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc), RO(CORE) *RO(Core),
unsigned short DID)
{
switch (DID) {
case DID_AMD_K8_NB_MEMCTL:
AMD_0Fh_HTT(RO(Shm), RO(Proc));
AMD_0Fh_MCH(RO(Shm), RO(Proc));
SET_CHIPSET(IC_K8);
break;
case DID_AMD_17H_ZEN_PLUS_NB_IOMMU:
case DID_AMD_17H_ZEPPELIN_NB_IOMMU:
case DID_AMD_17H_RAVEN_NB_IOMMU:
case DID_AMD_17H_ZEN2_MTS_NB_IOMMU:
case DID_AMD_17H_STARSHIP_NB_IOMMU:
case DID_AMD_17H_RENOIR_NB_IOMMU:
case DID_AMD_17H_ZEN_APU_NB_IOMMU:
case DID_AMD_17H_ZEN2_APU_NB_IOMMU:
case DID_AMD_17H_FIREFLIGHT_NB_IOMMU:
case DID_AMD_17H_ARDEN_NB_IOMMU:
case DID_AMD_17H_JUPITER_NB_IOMMU:
case DID_AMD_19H_ZEN3_RMB_NB_IOMMU:
case DID_AMD_19H_ZEN4_RPL_NB_IOMMU:
case DID_AMD_19H_ZEN4_GNA_NB_IOMMU:
case DID_AMD_19H_ZEN4_PHX_NB_IOMMU:
case DID_AMD_1AH_ZEN5_TURIN_IOMMU:
case DID_AMD_1AH_ZEN5_STX_IOMMU:
AMD_17h_IOMMU(RO(Shm), RO(Proc));
break;
case DID_AMD_17H_ZEPPELIN_DF_UMC:
case DID_AMD_17H_RAVEN_DF_UMC:
case DID_AMD_17H_MATISSE_DF_UMC:
case DID_AMD_17H_STARSHIP_DF_UMC:
case DID_AMD_17H_RENOIR_DF_UMC:
case DID_AMD_17H_ARIEL_DF_UMC:
case DID_AMD_17H_RAVEN2_DF_UMC:
case DID_AMD_17H_FIREFLIGHT_DF_UMC:
case DID_AMD_17H_ARDEN_DF_UMC:
case DID_AMD_17H_JUPITER_DF_UMC:
case DID_AMD_19H_VERMEER_DF_UMC:
case DID_AMD_19H_CEZANNE_DF_UMC:
case DID_AMD_19H_REMBRANDT_DF_UMC:
case DID_AMD_19H_RAPHAEL_DF_UMC:
case DID_AMD_19H_GENOA_DF_UMC:
case DID_AMD_19H_PHOENIX_DF_UMC:
case DID_AMD_1AH_TURIN_DF_UMC:
AMD_17h_UMC(RO(Shm), RO(Proc));
AMD_17h_CAP(RO(Shm), RO(Proc), RO(Core));
SET_CHIPSET(IC_ZEN);
break;
case DID_AMD_1AH_STX_DF_UMC:
case DID_AMD_1AH_STXH_DF_UMC:
AMD_17h_UMC(RO(Shm), RO(Proc));
AMD_1Ah_STX_CAP(RO(Shm), RO(Proc), RO(Core));
SET_CHIPSET(IC_ZEN);
break;
}
}
#undef SET_CHIPSET
void Uncore_Update( RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc),
RO(CORE) *RO(Core) )
{
unsigned int idx;
/* Copy the # of controllers. */
RO(Shm)->Uncore.CtrlCount = RO(Proc)->Uncore.CtrlCount;
/* Decode the Memory Controller for each found vendor:device */
Chipset[IC_CHIPSET] = RO(Proc)->Features.Info.Vendor.ID;
RO(Shm)->Uncore.ChipID = 0x0;
RO(Shm)->Uncore.Chipset.ArchID = IC_CHIPSET;
for (idx = 0; idx < CHIP_MAX_PCI; idx++) {
switch (RO(Proc)->Uncore.Chip[idx].VID) {
case PCI_VENDOR_ID_INTEL:
PCI_Intel(RO(Shm), RO(Proc), RO(Core), RO(Proc)->Uncore.Chip[idx].DID);
break;
case PCI_VENDOR_ID_AMD:
PCI_AMD(RO(Shm), RO(Proc), RO(Core), RO(Proc)->Uncore.Chip[idx].DID);
break;
}
}
/* Copy the chipset codename. */
StrCopy(RO(Shm)->Uncore.Chipset.CodeName,
Chipset[RO(Shm)->Uncore.Chipset.ArchID],
CODENAME_LEN);
/* Copy the Uncore clock ratios. */
memcpy( RO(Shm)->Uncore.Boost,
RO(Proc)->Uncore.Boost,
(UNCORE_BOOST(SIZE)) * sizeof(unsigned int) );
}
void CPUID_Dump(RO(SHM_STRUCT) *RO(Shm), RO(CORE) **RO(Core), unsigned int cpu)
{ /* Copy the Vendor CPUID dump per Core. */
RO(Shm)->Cpu[cpu].Query.StdFunc = RO(Core, AT(cpu))->Query.StdFunc;
RO(Shm)->Cpu[cpu].Query.ExtFunc = RO(Core, AT(cpu))->Query.ExtFunc;
enum CPUID_ENUM i;
for (i = 0; i < CPUID_MAX_FUNC; i++) {
RO(Shm)->Cpu[cpu].CpuID[i].func = RO(Core, AT(cpu))->CpuID[i].func;
RO(Shm)->Cpu[cpu].CpuID[i].sub = RO(Core, AT(cpu))->CpuID[i].sub;
RO(Shm)->Cpu[cpu].CpuID[i].reg[0] = RO(Core, AT(cpu))->CpuID[i].reg[0];
RO(Shm)->Cpu[cpu].CpuID[i].reg[1] = RO(Core, AT(cpu))->CpuID[i].reg[1];
RO(Shm)->Cpu[cpu].CpuID[i].reg[2] = RO(Core, AT(cpu))->CpuID[i].reg[2];
RO(Shm)->Cpu[cpu].CpuID[i].reg[3] = RO(Core, AT(cpu))->CpuID[i].reg[3];
}
}
unsigned int AMD_L2_L3_Way_Associativity(RO(CORE) **RO(Core),
unsigned int cpu,
unsigned int level)
{
switch (RO(Core, AT(cpu))->T.Cache[level].Way) {
case 0x9:
return ((RO(Core, AT(cpu))->CpuID[
CPUID_8000001D_00000000_CACHE_L1D_PROPERTIES + level
].reg[1] >> 22) + 1);
case 0x6:
return 8;
case 0x8:
return 16;
case 0xa:
return 32;
case 0xb:
return 48;
case 0xc:
return 64;
case 0xd:
return 96;
case 0xe:
return 128;
default:
return RO(Core, AT(cpu))->T.Cache[level].Way;
}
}
void Topology(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc), RO(CORE) **RO(Core),
unsigned int cpu)
{
unsigned int loop;
/* Copy each Core topology. */
RO(Shm)->Cpu[cpu].Topology.MP.BSP= (RO(Core, AT(cpu))->T.Base.BSP)? 1:0;
RO(Shm)->Cpu[cpu].Topology.ApicID = RO(Core,AT(cpu))->T.ApicID;
RO(Shm)->Cpu[cpu].Topology.CoreID = RO(Core,AT(cpu))->T.CoreID;
RO(Shm)->Cpu[cpu].Topology.ThreadID = RO(Core,AT(cpu))->T.ThreadID;
RO(Shm)->Cpu[cpu].Topology.PackageID = RO(Core,AT(cpu))->T.PackageID;
RO(Shm)->Cpu[cpu].Topology.Cluster.ID = RO(Core,AT(cpu))->T.Cluster.ID;
/* x2APIC capability. */
RO(Shm)->Cpu[cpu].Topology.MP.x2APIC= RO(Proc)->Features.Std.ECX.x2APIC;
if ((RO(Shm)->Proc.Features.Info.Vendor.CRC == CRC_AMD)
|| (RO(Shm)->Proc.Features.Info.Vendor.CRC == CRC_HYGON))
{
RO(Shm)->Cpu[cpu].Topology.MP.x2APIC |= \
RO(Proc)->Features.ExtInfo.ECX.ExtApicId;
}
else if ((RO(Shm)->Proc.Features.Info.Vendor.CRC == CRC_INTEL)
&& (RO(Shm)->Proc.Features.ExtFeature.EDX.Hybrid == 1))
{
switch (RO(Core,AT(cpu))->T.Cluster.Hybrid.CoreType) {
case Hybrid_Atom:
RO(Shm)->Cpu[cpu].Topology.MP.Ecore = 1;
break;
case Hybrid_Core:
RO(Shm)->Cpu[cpu].Topology.MP.Pcore = 1;
break;
}
RO(Shm)->Cpu[cpu].Topology.Cluster.Hybrid_ID = \
RO(Core,AT(cpu))->T.Cluster.Hybrid.Model_ID;
}
/* Is local APIC enabled in xAPIC mode ? */
RO(Shm)->Cpu[cpu].Topology.MP.x2APIC &= \
RO(Core, AT(cpu))->T.Base.APIC_EN;
/* Is xAPIC enabled in x2APIC mode ? */
RO(Shm)->Cpu[cpu].Topology.MP.x2APIC = \
RO(Shm)->Cpu[cpu].Topology.MP.x2APIC
<< RO(Core, AT(cpu))->T.Base.x2APIC_EN;
/* Aggregate the Caches topology. */
for (loop = 0; loop < CACHE_MAX_LEVEL; loop++)
{
if (RO(Core, AT(cpu))->T.Cache[loop].Type > 0)
{
unsigned int level = RO(Core, AT(cpu))->T.Cache[loop].Level;
if (RO(Core, AT(cpu))->T.Cache[loop].Type == 2) {/* Instruction */
level = 0;
}
if (RO(Shm)->Proc.Features.Info.Vendor.CRC == CRC_INTEL)
{
RO(Shm)->Cpu[cpu].Topology.Cache[level].Set = \
RO(Core, AT(cpu))->T.Cache[loop].Set + 1;
RO(Shm)->Cpu[cpu].Topology.Cache[level].LineSz = \
RO(Core, AT(cpu))->T.Cache[loop].LineSz + 1;
RO(Shm)->Cpu[cpu].Topology.Cache[level].Part = \
RO(Core, AT(cpu))->T.Cache[loop].Part + 1;
RO(Shm)->Cpu[cpu].Topology.Cache[level].Way = \
RO(Core, AT(cpu))->T.Cache[loop].Way + 1;
RO(Shm)->Cpu[cpu].Topology.Cache[level].Size = \
RO(Shm)->Cpu[cpu].Topology.Cache[level].Set
* RO(Shm)->Cpu[cpu].Topology.Cache[level].LineSz
* RO(Shm)->Cpu[cpu].Topology.Cache[level].Part
* RO(Shm)->Cpu[cpu].Topology.Cache[level].Way;
} else {
if ((RO(Shm)->Proc.Features.Info.Vendor.CRC == CRC_AMD)
|| (RO(Shm)->Proc.Features.Info.Vendor.CRC == CRC_HYGON))
{
RO(Shm)->Cpu[cpu].Topology.Cache[level].Way = \
(loop == 2) || (loop == 3) ?
AMD_L2_L3_Way_Associativity(RO(Core), cpu, loop)
: RO(Core, AT(cpu))->T.Cache[loop].Way;
RO(Shm)->Cpu[cpu].Topology.Cache[level].Size = \
RO(Core, AT(cpu))->T.Cache[loop].Size;
}
}
RO(Shm)->Cpu[cpu].Topology.Cache[level].Feature.WriteBack = \
RO(Core, AT(cpu))->T.Cache[loop].WrBack;
RO(Shm)->Cpu[cpu].Topology.Cache[level].Feature.Inclusive = \
RO(Core, AT(cpu))->T.Cache[loop].Inclus;
}
}
/* Apply various architecture size unit. */
switch (RO(Proc)->ArchID) {
case AMD_Family_15h:
/*TODO: do models 60h & 70h need a 512 KB size unit adjustment ? */
if ((RO(Shm)->Proc.Features.Std.EAX.ExtModel == 0x6)
|| (RO(Shm)->Proc.Features.Std.EAX.ExtModel == 0x7)) {
break;
}
fallthrough;
case AMD_Zen:
case AMD_Zen_APU:
case AMD_ZenPlus:
case AMD_ZenPlus_APU:
case AMD_Zen_Dali:
case AMD_EPYC_Rome_CPK:
case AMD_Zen2_Renoir:
case AMD_Zen2_LCN:
case AMD_Zen2_MTS:
case AMD_Zen2_Ariel:
case AMD_Zen2_Jupiter:
case AMD_Zen2_Galileo:
case AMD_Zen2_MDN:
case AMD_Zen3_VMR:
case AMD_Zen3_CZN:
case AMD_EPYC_Milan:
case AMD_Zen3_Chagall:
case AMD_Zen3_Badami:
case AMD_Zen3Plus_RMB:
case AMD_Zen4_Genoa:
case AMD_Zen4_RPL:
case AMD_Zen4_PHX:
case AMD_Zen4_PHXR:
case AMD_Zen4_PHX2:
case AMD_Zen4_HWK:
case AMD_Zen4_Bergamo:
case AMD_Zen4_STP:
case AMD_Zen5_STX:
case AMD_Zen5_Eldora:
case AMD_Zen5_Turin:
case AMD_Zen5_Turin_Dense:
case AMD_Zen5_KRK:
case AMD_Zen5_STXH:
case AMD_Family_17h:
case Hygon_Family_18h:
case AMD_Family_19h:
case AMD_Family_1Ah:
VIRTUALIZED_L3:
/* CPUID_Fn80000006_EDX: Value in [3FFFh - 0001h] = (<Value> *0.5) MB */
RO(Shm)->Cpu[cpu].Topology.Cache[3].Size *= 512;
break;
default:
if (RO(Shm)->Proc.Features.Std.ECX.Hyperv) { /* Virtualized ? */
goto VIRTUALIZED_L3;
}
break;
}
}
void CStates(RO(SHM_STRUCT) *RO(Shm), RO(CORE) **RO(Core), unsigned int cpu)
{ /* Copy the C-State Configuration Control */
RO(Shm)->Cpu[cpu].Query.CfgLock = RO(Core, AT(cpu))->Query.CfgLock;
RO(Shm)->Cpu[cpu].Query.CStateLimit = \
RO(Core, AT(cpu))->Query.CStateLimit;
/* Copy Intel Max C-State Inclusion */
RO(Shm)->Cpu[cpu].Query.IORedir = RO(Core, AT(cpu))->Query.IORedir;
RO(Shm)->Cpu[cpu].Query.CStateInclude = \
RO(Core, AT(cpu))->Query.CStateInclude;
/* Copy any architectural C-States I/O Base Address */
RO(Shm)->Cpu[cpu].Query.CStateBaseAddr = \
RO(Core, AT(cpu))->Query.CStateBaseAddr;
}
void PowerThermal( RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc),
RO(CORE) **RO(Core), unsigned int cpu )
{
UNUSED(RO(Proc));
RO(Shm)->Cpu[cpu].PowerThermal.DutyCycle.Extended = \
RO(Core, AT(cpu))->PowerThermal.ClockModulation.ECMD;
RO(Shm)->Cpu[cpu].PowerThermal.DutyCycle.ClockMod = \
RO(Core, AT(cpu))->PowerThermal.ClockModulation.DutyCycle
>> !RO(Shm)->Cpu[cpu].PowerThermal.DutyCycle.Extended;
RO(Shm)->Cpu[cpu].PowerThermal.PowerPolicy = \
RO(Core, AT(cpu))->PowerThermal.PerfEnergyBias.PowerPolicy;
RO(Shm)->Cpu[cpu].PowerThermal.HWP.Capabilities.Highest = \
RO(Core, AT(cpu))->PowerThermal.HWP_Capabilities.Highest;
RO(Shm)->Cpu[cpu].PowerThermal.HWP.Capabilities.Guaranteed = \
RO(Core, AT(cpu))->PowerThermal.HWP_Capabilities.Guaranteed;
RO(Shm)->Cpu[cpu].PowerThermal.HWP.Capabilities.Most_Efficient = \
RO(Core, AT(cpu))->PowerThermal.HWP_Capabilities.Most_Efficient;
RO(Shm)->Cpu[cpu].PowerThermal.HWP.Capabilities.Lowest = \
RO(Core, AT(cpu))->PowerThermal.HWP_Capabilities.Lowest;
RO(Shm)->Cpu[cpu].PowerThermal.HWP.Request.Minimum_Perf = \
RO(Core, AT(cpu))->PowerThermal.HWP_Request.Minimum_Perf;
RO(Shm)->Cpu[cpu].PowerThermal.HWP.Request.Maximum_Perf = \
RO(Core, AT(cpu))->PowerThermal.HWP_Request.Maximum_Perf;
RO(Shm)->Cpu[cpu].PowerThermal.HWP.Request.Desired_Perf = \
RO(Core, AT(cpu))->PowerThermal.HWP_Request.Desired_Perf;
RO(Shm)->Cpu[cpu].PowerThermal.HWP.Request.Energy_Pref = \
RO(Core, AT(cpu))->PowerThermal.HWP_Request.Energy_Pref;
memcpy( &RO(Shm)->Cpu[cpu].ThermalPoint,
&RO(Core, AT(cpu))->ThermalPoint,
sizeof(THERMAL_POINT) );
}
void SystemRegisters( RO(SHM_STRUCT) *RO(Shm), RO(CORE) **RO(Core),
unsigned int cpu )
{
RO(Shm)->Cpu[cpu].SystemRegister.RFLAGS = \
RO(Core, AT(cpu))->SystemRegister.RFLAGS;
RO(Shm)->Cpu[cpu].SystemRegister.CR0 = \
RO(Core, AT(cpu))->SystemRegister.CR0;
RO(Shm)->Cpu[cpu].SystemRegister.CR3 = \
RO(Core, AT(cpu))->SystemRegister.CR3;
RO(Shm)->Cpu[cpu].SystemRegister.CR4 = \
RO(Core, AT(cpu))->SystemRegister.CR4;
RO(Shm)->Cpu[cpu].SystemRegister.CR8 = \
RO(Core, AT(cpu))->SystemRegister.CR8;
RO(Shm)->Cpu[cpu].SystemRegister.EFER = \
RO(Core, AT(cpu))->SystemRegister.EFER;
RO(Shm)->Cpu[cpu].SystemRegister.EFCR = \
RO(Core, AT(cpu))->SystemRegister.EFCR;
RO(Shm)->Cpu[cpu].SystemRegister.XCR0 = \
RO(Core, AT(cpu))->SystemRegister.XCR0;
RO(Shm)->Cpu[cpu].SystemRegister.XSS = \
RO(Core, AT(cpu))->SystemRegister.XSS;
RO(Shm)->Cpu[cpu].SystemRegister.SYSCFG = \
RO(Core, AT(cpu))->SystemRegister.SYSCFG;
RO(Shm)->Cpu[cpu].SystemRegister.HWCR = \
RO(Core, AT(cpu))->SystemRegister.HWCR.value;
}
void SysGate_OS_Driver(RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc))
{
memset(&RO(Shm)->SysGate.OS, 0, sizeof(OS_DRIVER));
if (strlen(RO(Proc)->OS.IdleDriver.Name) > 0) {
int idx;
StrCopy(RO(Shm)->SysGate.OS.IdleDriver.Name,
RO(Proc)->OS.IdleDriver.Name,
CPUIDLE_NAME_LEN);
RO(Shm)->SysGate.OS.IdleDriver.stateCount = \
RO(Proc)->OS.IdleDriver.stateCount;
RO(Shm)->SysGate.OS.IdleDriver.stateLimit = \
RO(Proc)->OS.IdleDriver.stateLimit;
for (idx = 0; idx < RO(Shm)->SysGate.OS.IdleDriver.stateCount; idx++)
{
StrCopy(RO(Shm)->SysGate.OS.IdleDriver.State[idx].Name,
RO(Proc)->OS.IdleDriver.State[idx].Name,
CPUIDLE_NAME_LEN);
StrCopy(RO(Shm)->SysGate.OS.IdleDriver.State[idx].Desc,
RO(Proc)->OS.IdleDriver.State[idx].Desc,
CPUIDLE_NAME_LEN);
RO(Shm)->SysGate.OS.IdleDriver.State[idx].exitLatency = \
RO(Proc)->OS.IdleDriver.State[idx].exitLatency;
RO(Shm)->SysGate.OS.IdleDriver.State[idx].powerUsage = \
RO(Proc)->OS.IdleDriver.State[idx].powerUsage;
RO(Shm)->SysGate.OS.IdleDriver.State[idx].targetResidency = \
RO(Proc)->OS.IdleDriver.State[idx].targetResidency;
}
}
if (strlen(RO(Proc)->OS.FreqDriver.Name) > 0) {
StrCopy(RO(Shm)->SysGate.OS.FreqDriver.Name,
RO(Proc)->OS.FreqDriver.Name,
CPUFREQ_NAME_LEN);
}
if (strlen(RO(Proc)->OS.FreqDriver.Governor) > 0) {
StrCopy(RO(Shm)->SysGate.OS.FreqDriver.Governor,
RO(Proc)->OS.FreqDriver.Governor,
CPUFREQ_NAME_LEN);
}
}
void SysGate_Kernel(REF *Ref)
{
RO(SHM_STRUCT) *RO(Shm) = Ref->RO(Shm);
RO(SYSGATE) *SysGate = Ref->RO(SysGate);
RO(Shm)->SysGate.kernel.version = SysGate->kernelVersionNumber >> 16;
RO(Shm)->SysGate.kernel.major = SysGate->kernelVersionNumber >> 8;
RO(Shm)->SysGate.kernel.major = RO(Shm)->SysGate.kernel.major & 0xff;
RO(Shm)->SysGate.kernel.minor = SysGate->kernelVersionNumber & 0xff;
memcpy(RO(Shm)->SysGate.sysname, SysGate->sysname, MAX_UTS_LEN);
memcpy(RO(Shm)->SysGate.release, SysGate->release, MAX_UTS_LEN);
memcpy(RO(Shm)->SysGate.version, SysGate->version, MAX_UTS_LEN);
memcpy(RO(Shm)->SysGate.machine, SysGate->machine, MAX_UTS_LEN);
}
#define CS_Reset_Array(_CS) \
({ \
_CS.index[0] = 0; \
})
#define CS_Seek_Store(_fd, _ptr, _CS) \
({ \
size_t length; \
if (fscanf(_fd, "%s", _ptr) == 1) { \
unsigned char offset; \
length = strlen(_ptr); \
_ptr += length; \
(*_ptr) = 0x0; \
_ptr++; \
length = _ptr - _CS.array; \
offset = (unsigned char) length; \
_CS.index[0]++; \
_CS.index[_CS.index[0]] = offset; \
} \
})
void ClockSource_Update(RO(SHM_STRUCT) *RO(Shm))
{
FILE *fd;
CS_Reset_Array(RO(Shm)->CS);
if ((fd = fopen(CLOCKSOURCE_PATH"/current_clocksource", "r")) != NULL)
{
char *ptr = RO(Shm)->CS.array;
CS_Seek_Store(fd, ptr, RO(Shm)->CS);
fclose(fd);
if ((fd = fopen(CLOCKSOURCE_PATH"/available_clocksource", "r")) != NULL)
{
do {
CS_Seek_Store(fd, ptr, RO(Shm)->CS);
} while (!feof(fd) && (RO(Shm)->CS.index[0] < 7));
fclose(fd);
}
}
}
long ClockSource_Submit(RO(SHM_STRUCT) *RO(Shm), unsigned char index)
{
if (index <= RO(Shm)->CS.index[0])
{
FILE *fd;
if ((fd = fopen(CLOCKSOURCE_PATH"/current_clocksource", "w")) != NULL)
{
char *ptr = &RO(Shm)->CS.array[RO(Shm)->CS.index[index]];
fprintf(fd, "%s", ptr);
fclose(fd);
return 0;
}
}
return -EINVAL;
}
static const int reverseSign[2] = {+1, -1};
static int SortByRuntime(const void *p1, const void *p2, void *arg)
{
TASK_MCB *task1 = (TASK_MCB*) p1, *task2 = (TASK_MCB*) p2;
REF *Ref = (REF*) arg;
int sort = task1->runtime < task2->runtime ? +1 : -1;
sort *= reverseSign[Ref->RO(Shm)->SysGate.reverseOrder];
return sort;
}
static int SortByUsertime(const void *p1, const void *p2, void *arg)
{
TASK_MCB *task1 = (TASK_MCB*) p1, *task2 = (TASK_MCB*) p2;
REF *Ref = (REF*) arg;
int sort = task1->usertime < task2->usertime ? +1 : -1;
sort *= reverseSign[Ref->RO(Shm)->SysGate.reverseOrder];
return sort;
}
static int SortBySystime(const void *p1, const void *p2, void *arg)
{
TASK_MCB *task1 = (TASK_MCB*) p1, *task2 = (TASK_MCB*) p2;
REF *Ref = (REF*) arg;
int sort = task1->systime < task2->systime ? +1 : -1;
sort *= reverseSign[Ref->RO(Shm)->SysGate.reverseOrder];
return sort;
}
static int SortByState(const void *p1, const void *p2, void *arg)
{
TASK_MCB *task1 = (TASK_MCB*) p1, *task2 = (TASK_MCB*) p2;
REF *Ref = (REF*) arg;
int sort = task1->state < task2->state ? -1 : +1;
sort *= reverseSign[Ref->RO(Shm)->SysGate.reverseOrder];
return sort;
}
static int SortByPID(const void *p1, const void *p2, void *arg)
{
TASK_MCB *task1 = (TASK_MCB*) p1, *task2 = (TASK_MCB*) p2;
REF *Ref = (REF*) arg;
int sort = task1->pid < task2->pid ? -1 : +1;
sort *= reverseSign[Ref->RO(Shm)->SysGate.reverseOrder];
return sort;
}
static int SortByCommand(const void *p1, const void *p2, void *arg)
{
TASK_MCB *task1 = (TASK_MCB*) p1, *task2 = (TASK_MCB*) p2;
REF *Ref = (REF*) arg;
int sort = strncmp(task1->comm, task2->comm, TASK_COMM_LEN);
sort *= reverseSign[Ref->RO(Shm)->SysGate.reverseOrder];
return sort;
}
typedef int (*SORTBYFUNC)(const void *, const void *, void *);
static SORTBYFUNC SortByFunc[SORTBYCOUNT] = {
SortByState,
SortByRuntime,
SortByUsertime,
SortBySystime,
SortByPID,
SortByCommand
};
static int SortByTracker(const void *p1, const void *p2, void *arg)
{
TASK_MCB *task1 = (TASK_MCB*) p1, *task2 = (TASK_MCB*) p2;
REF *Ref = (REF*) arg;
int sort = (task1->pid == Ref->RO(Shm)->SysGate.trackTask) ?
-1 : (task2->pid == Ref->RO(Shm)->SysGate.trackTask) ?
+1 : SortByFunc[Ref->RO(Shm)->SysGate.sortByField](p1, p2, Ref);
return sort;
}
void SysGate_Update(REF *Ref)
{
struct sysinfo info;
RO(SHM_STRUCT) *RO(Shm) = Ref->RO(Shm);
RO(SYSGATE) *SysGate = Ref->RO(SysGate);
RO(PROC) *RO(Proc) = Ref->RO(Proc);
RO(Shm)->SysGate.taskCount = SysGate->taskCount;
memcpy( RO(Shm)->SysGate.taskList, SysGate->taskList,
(size_t) RO(Shm)->SysGate.taskCount * sizeof(TASK_MCB));
qsort_r(RO(Shm)->SysGate.taskList,
(size_t) RO(Shm)->SysGate.taskCount, sizeof(TASK_MCB),
RO(Shm)->SysGate.trackTask ?
SortByTracker
: SortByFunc[RO(Shm)->SysGate.sortByField], Ref);
if (sysinfo(&info) == 0) {
RO(Shm)->SysGate.memInfo.totalram = info.totalram >> 10;
RO(Shm)->SysGate.memInfo.sharedram = info.sharedram >> 10;
RO(Shm)->SysGate.memInfo.freeram = info.freeram >> 10;
RO(Shm)->SysGate.memInfo.bufferram = info.bufferram >> 10;
RO(Shm)->SysGate.memInfo.totalhigh = info.totalhigh >> 10;
RO(Shm)->SysGate.memInfo.freehigh = info.freehigh >> 10;
RO(Shm)->SysGate.procCount = info.procs;
}
RO(Shm)->SysGate.OS.IdleDriver.stateLimit =
RO(Proc)->OS.IdleDriver.stateLimit;
}
void Package_Update( RO(SHM_STRUCT) *RO(Shm),
RO(PROC) *RO(Proc), RW(PROC) *RW(Proc) )
{ /* Copy the operational settings. */
RO(Shm)->Registration.AutoClock = RO(Proc)->Registration.AutoClock;
RO(Shm)->Registration.Experimental= RO(Proc)->Registration.Experimental;
RO(Shm)->Registration.HotPlug = RO(Proc)->Registration.HotPlug;
RO(Shm)->Registration.PCI = RO(Proc)->Registration.PCI;
RO(Shm)->Registration.HSMP= RO(Proc)->Features.HSMP_Enable;
BITSTOR(LOCKLESS,RO(Shm)->Registration.NMI, RO(Proc)->Registration.NMI);
RO(Shm)->Registration.Driver = RO(Proc)->Registration.Driver;
/* Copy the timer interval delay. */
RO(Shm)->Sleep.Interval = RO(Proc)->SleepInterval;
/* Compute the polling wait time based on the timer interval. */
RO(Shm)->Sleep.pollingWait=TIMESPEC((RO(Shm)->Sleep.Interval * 1000000L)
/ WAKEUP_RATIO);
/* Copy the SysGate tick steps. */
RO(Shm)->SysGate.tickReset = RO(Proc)->tickReset;
RO(Shm)->SysGate.tickStep = RO(Proc)->tickStep;
Architecture(RO(Shm), RO(Proc));
PerformanceMonitoring(RO(Shm), RO(Proc));
HyperThreading(RO(Shm), RO(Proc));
PowerInterface(RO(Shm), RO(Proc));
ThermalPoint(RO(Shm), RO(Proc));
Mitigation_1st_Stage(RO(Shm), RO(Proc), RW(Proc));
/* Aggregate OS idle driver data and Clock Source */
SysGate_OS_Driver(RO(Shm), RO(Proc));
ClockSource_Update(RO(Shm));
}
void PerCore_Update( RO(SHM_STRUCT) *RO(Shm), RO(PROC) *RO(Proc),
RO(CORE) **RO(Core), unsigned int cpu )
{
if (BITVAL(RO(Core, AT(cpu))->OffLine, HW)) {
BITSET(LOCKLESS, RO(Shm)->Cpu[cpu].OffLine, HW);
} else {
BITCLR(LOCKLESS, RO(Shm)->Cpu[cpu].OffLine, HW);
}
/* Initialize all clock ratios. */
memcpy( RO(Shm)->Cpu[cpu].Boost, RO(Core, AT(cpu))->Boost,
(BOOST(SIZE)) * sizeof(unsigned int) );
RO(Shm)->Cpu[cpu].Query.Microcode = RO(Core, AT(cpu))->Query.Microcode;
Topology(RO(Shm), RO(Proc), RO(Core), cpu);
CStates(RO(Shm), RO(Core), cpu);
PowerThermal(RO(Shm), RO(Proc), RO(Core), cpu);
SystemRegisters(RO(Shm), RO(Core), cpu);
CPUID_Dump(RO(Shm), RO(Core), cpu);
}
#define SysOnce(drv) ioctl(drv, COREFREQ_IOCTL_SYSONCE)
int SysGate_OnDemand(REF *Ref, int operation)
{
int rc = -1;
const size_t allocPages = Ref->RO(Proc)->Gate.ReqMem.Size;
if (operation == 0) {
if (Ref->RO(SysGate) != NULL) {
if ((rc = munmap(Ref->RO(SysGate), allocPages)) == 0) {
Ref->RO(SysGate) = NULL;
}
} else {
rc = -1;
}
} else {
if (Ref->RO(SysGate) == NULL) {
const off_t vm_pgoff = ID_RO_VMA_GATE * PAGE_SIZE;
RO(SYSGATE) *MapGate = mmap(NULL, allocPages,
PROT_READ,
MAP_SHARED,
Ref->fd->drv, vm_pgoff);
if (MapGate != MAP_FAILED) {
Ref->RO(SysGate) = MapGate;
rc = 0;
}
} else {
rc = 0;
}
}
return rc;
}
void SysGate_Toggle(REF *Ref, unsigned int state)
{
if (state == 0) {
if (BITWISEAND(LOCKLESS, Ref->RO(Shm)->SysGate.Operation, 0x1)) {
/* Stop SysGate */
BITCLR(LOCKLESS, Ref->RO(Shm)->SysGate.Operation, 0);
/* Notify */
BITWISESET(LOCKLESS, PendingSync, BIT_MASK_NTFY);
}
} else {
if (!BITWISEAND(LOCKLESS, Ref->RO(Shm)->SysGate.Operation, 0x1)) {
if (SysGate_OnDemand(Ref, 1) == 0) {
/* Start SysGate */
BITSET(LOCKLESS, Ref->RO(Shm)->SysGate.Operation, 0);
/* Notify */
BITWISESET(LOCKLESS, PendingSync,BIT_MASK_NTFY);
}
}
}
if (BITWISEAND(LOCKLESS, Ref->RO(Shm)->SysGate.Operation, 0x1))
if (SysOnce(Ref->fd->drv) == RC_OK_SYSGATE) {
/* Copy system information. */
SysGate_Kernel(Ref);
}
}
void Main_Ring_Handler(REF *Ref, unsigned int rid)
{
if (!RING_NULL(Ref->RW(Shm)->Ring[rid]))
{
RING_CTRL ctrl __attribute__ ((aligned(16)));
RING_READ(Ref->RW(Shm)->Ring[rid], ctrl);
int rc = -EPERM, drc = -EPERM;
if ( (ctrl.cmd >= COREFREQ_IOCTL_SYSUPDT)
&& (ctrl.cmd <= COREFREQ_IOCTL_CLEAR_EVENTS) )
{
rc = ioctl(Ref->fd->drv, ctrl.cmd, ctrl.arg);
drc = errno;
}
if (Quiet & 0x100) {
printf("\tRING[%u](%x,%x)(%llx)>(%d,%d)\n",
rid, ctrl.cmd, ctrl.sub, ctrl.arg, rc, drc);
}
switch (rc) {
case -EPERM:
{
RING_CTRL error __attribute__ ((aligned(16))) = {
.arg = ctrl.arg,
.cmd = ctrl.cmd,
.drc = (unsigned int) drc,
.tds = ELAPSED(Ref->RO(Shm)->StartedAt)
};
RING_WRITE_1xPARAM( error.sub,
Ref->RW(Shm)->Error,
error.cmd,
error.arg );
}
break;
case RC_OK_SYSGATE:
SysGate_OS_Driver(Ref->RO(Shm), Ref->RO(Proc));
fallthrough;
case RC_SUCCESS: /* Platform changed -> pending notification. */
BITWISESET(LOCKLESS, PendingSync, BIT_MASK_NTFY);
break;
case RC_OK_COMPUTE: /* Compute claimed -> pending notification. */
BITWISESET(LOCKLESS, PendingSync, BIT_MASK_COMP);
break;
}
}
}
void Child_Ring_Handler(REF *Ref, unsigned int rid)
{
if (!RING_NULL(Ref->RW(Shm)->Ring[rid]))
{
RING_CTRL ctrl __attribute__ ((aligned(16)));
RING_READ(Ref->RW(Shm)->Ring[rid], ctrl);
switch (ctrl.cmd) {
case COREFREQ_KERNEL_MISC:
switch (ctrl.dl.hi) {
case MACHINE_CLOCK_SOURCE:
if (ClockSource_Submit(Ref->RO(Shm), (unsigned char) ctrl.dl.lo) == 0) {
ClockSource_Update(Ref->RO(Shm));
}
break;
}
break;
case COREFREQ_SESSION_APP:
switch (ctrl.sub) {
case SESSION_CLI:
Ref->RO(Shm)->App.Cli = (pid_t) ctrl.arg;
break;
case SESSION_GUI:
Ref->RO(Shm)->App.GUI = (pid_t) ctrl.arg;
break;
}
break;
case COREFREQ_TASK_MONITORING:
switch (ctrl.sub) {
case TASK_TRACKING:
Ref->RO(Shm)->SysGate.trackTask = (pid_t) ctrl.arg;
break;
case TASK_SORTING:
{
enum SORTBYFIELD sortByField = (enum SORTBYFIELD) ctrl.dl.lo;
Ref->RO(Shm)->SysGate.sortByField = sortByField % SORTBYCOUNT;
}
break;
case TASK_INVERSING:
{
const int reverseOrder = !!!Ref->RO(Shm)->SysGate.reverseOrder;
Ref->RO(Shm)->SysGate.reverseOrder = reverseOrder;
}
break;
}
BITWISESET(LOCKLESS, Ref->RW(Shm)->Proc.Sync, BIT_MASK_NTFY);
break;
case COREFREQ_TOGGLE_SYSGATE:
switch (ctrl.arg) {
case COREFREQ_TOGGLE_OFF:
case COREFREQ_TOGGLE_ON:
SysGate_Toggle(Ref, ctrl.arg);
BITWISESET(LOCKLESS, Ref->RW(Shm)->Proc.Sync, BIT_MASK_NTFY);
break;
}
break;
case COREFREQ_ORDER_MACHINE:
switch (ctrl.arg) {
case COREFREQ_TOGGLE_OFF:
SCHEDULER_STOP:
if (BITVAL(Ref->RW(Shm)->Proc.Sync, BURN))
{
BITCLR(BUS_LOCK, Ref->RW(Shm)->Proc.Sync, BURN);
while (BITWISEAND_CC(BUS_LOCK, roomCore, roomSeed))
{
if (BITVAL(Shutdown, SYNC)) { /* SpinLock */
break;
}
}
BITSTOR_CC(BUS_LOCK, Ref->RO(Shm)->roomSched, roomClear);
Ref->Slice.Func = Slice_NOP;
Ref->Slice.arg = 0;
Ref->Slice.pattern = RESET_CSP;
/* Notify the Slice module has stopped */
BITWISESET(LOCKLESS, Ref->RW(Shm)->Proc.Sync, BIT_MASK_NTFY);
}
break;
}
break;
default:
{
RING_SLICE *porder = order_list;
while (porder->func != NULL)
{
if ((porder->ctrl.cmd == ctrl.cmd) && (porder->ctrl.sub == ctrl.sub))
{
if ( !BITVAL(Ref->RW(Shm)->Proc.Sync, BURN)
|| ((Ref->Slice.Func == Slice_Turbo) && (Ref->Slice.pattern == USR_CPU)
&& (ctrl.cmd == COREFREQ_ORDER_TURBO) && (ctrl.sub == USR_CPU)))
{
if (ctrl.sub == USR_CPU) {
if (BITVAL_CC(Ref->RO(Shm)->roomSched, ctrl.dl.lo))
{
BITCLR_CC(LOCKLESS, Ref->RO(Shm)->roomSched, ctrl.dl.lo);
if (!BITWISEAND_CC(BUS_LOCK, Ref->RO(Shm)->roomSched, roomSeed))
{
goto SCHEDULER_STOP;
}
} else {
BITSET_CC(LOCKLESS, Ref->RO(Shm)->roomSched, ctrl.dl.lo);
goto SCHEDULER_START;
}
} else {
SliceScheduling(Ref->RO(Shm), ctrl.dl.lo, porder->pattern);
SCHEDULER_START:
Ref->Slice.Func = porder->func;
Ref->Slice.arg = porder->ctrl.dl.lo;
Ref->Slice.pattern = porder->pattern;
BITSET(BUS_LOCK, Ref->RW(Shm)->Proc.Sync, BURN);
}
/* Notify the Slice module is starting up */
BITWISESET(LOCKLESS, Ref->RW(Shm)->Proc.Sync, BIT_MASK_NTFY);
}
break;
}
porder++;
}
}
break;
}
if (Quiet & 0x100) {
printf("\tRING[%u](%x,%x)(%hx:%hx,%hx:%hx)\n",
rid, ctrl.cmd, ctrl.sub,
ctrl.dh.hi, ctrl.dh.lo, ctrl.dl.hi, ctrl.dl.lo);
}
}
}
int ServerFollowService(SERVICE_PROC *pPeer,
SERVICE_PROC *pMain,
pthread_t tid)
{
if (pPeer->Proc != pMain->Proc) {
pPeer->Proc = pMain->Proc;
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(pPeer->Core, &cpuset);
if (pPeer->Thread != -1) {
const signed int cpu = pPeer->Thread;
CPU_SET(cpu , &cpuset);
}
return pthread_setaffinity_np(tid, sizeof(cpu_set_t), &cpuset);
}
return -1;
}
static void *Emergency_Handler(void *pRef)
{
REF *Ref = (REF *) pRef;
unsigned int rid = (Ref->CPID == 0);
SERVICE_PROC localService = RESET_SERVICE;
int caught = 0, leave = 0;
char handlerName[TASK_COMM_LEN] = {
'c','o','r','e','f','r','e','q','d','-','r','i','n','g','0',0
};
handlerName[14] += (char) rid;
pthread_t tid = pthread_self();
if(ServerFollowService(&localService, &Ref->RO(Shm)->Proc.Service,tid) == 0)
{
pthread_setname_np(tid, handlerName);
}
while (!leave) {
caught=sigtimedwait(&Ref->Signal,NULL,&Ref->RO(Shm)->Sleep.ringWaiting);
if (caught != -1) {
switch (caught) {
case SIGUSR2:
if (Ref->CPID) { /* Stop SysGate */
SysGate_Toggle(Ref, 0);
}
break;
case SIGUSR1:
if (Ref->CPID) { /* Start SysGate */
SysGate_Toggle(Ref, 1);
}
break;
case SIGCHLD: /* Exit Ring Thread */
leave = 0x1;
fallthrough;
case SIGSTKFLT:
case SIGXFSZ:
case SIGXCPU:
case SIGSEGV:
case SIGTERM:
case SIGQUIT:
case SIGALRM:
case SIGABRT:
case SIGPIPE:
case SIGTRAP:
case SIGSYS:
case SIGFPE:
case SIGBUS:
case SIGILL:
case SIGINT: /* [CTRL] + [C] */
BITSET(LOCKLESS, Shutdown, SYNC);
break;
case SIGVTALRM:
case SIGWINCH:
case SIGTTOU:
case SIGTTIN:
case SIGTSTP:
case SIGPROF:
case SIGHUP:
case SIGPWR:
case SIGIO:
default: /* RTMIN ... RTMAX */
break;
}
} else if (errno == EAGAIN) {
if (Ref->CPID) {
Main_Ring_Handler(Ref, rid);
} else {
Child_Ring_Handler(Ref, rid);
}
}
ServerFollowService(&localService, &Ref->RO(Shm)->Proc.Service, tid);
}
return NULL;
}
void Emergency_Command(REF *Ref, unsigned int cmd)
{
switch (cmd) {
case 0:
if (Ref->Started) {
if (!pthread_kill(Ref->KID, SIGCHLD)) {
if (!pthread_join(Ref->KID, NULL)) {
Ref->Started = 0;
}
}
}
break;
case 1: {
const int ignored[] = {
SIGIO, SIGPROF, SIGPWR, SIGHUP, SIGTSTP,
SIGTTIN, SIGTTOU, SIGVTALRM, SIGWINCH
}, handled[] = {
SIGUSR1, SIGUSR2, SIGCHLD, SIGINT, SIGILL, SIGBUS,
SIGFPE, SIGSYS, SIGTRAP, SIGPIPE, SIGABRT, SIGALRM,
SIGQUIT, SIGTERM, SIGSEGV, SIGXCPU, SIGXFSZ, SIGSTKFLT
};
/* SIGKILL,SIGCONT,SIGSTOP,SIGURG: Reserved */
const ssize_t ignoredCount = sizeof(ignored) / sizeof(int),
handledCount = sizeof(handled) / sizeof(int);
int signo;
sigemptyset(&Ref->Signal);
for (signo = SIGRTMIN; signo <= SIGRTMAX; signo++) {
sigaddset(&Ref->Signal, signo);
}
for (signo = 0; signo < ignoredCount; signo++) {
sigaddset(&Ref->Signal, ignored[signo]);
}
for (signo = 0; signo < handledCount; signo++) {
sigaddset(&Ref->Signal, handled[signo]);
}
if (!pthread_sigmask(SIG_BLOCK, &Ref->Signal, NULL))
{
if(!pthread_create(&Ref->KID, NULL, Emergency_Handler, Ref))
{
Ref->Started = 1;
}
}
}
break;
}
}
static void Pkg_ComputeThermal_None( struct PKG_FLIP_FLOP *PFlip,
struct FLIP_FLOP *SProc )
{
UNUSED(PFlip);
UNUSED(SProc);
}
static void Pkg_ComputeThermal_Intel( struct PKG_FLIP_FLOP *PFlip,
struct FLIP_FLOP *SProc )
{
COMPUTE_THERMAL(INTEL,
PFlip->Thermal.Temp,
SProc->Thermal.Param,
PFlip->Thermal.Sensor);
}
static void Pkg_ComputeThermal_AMD( struct PKG_FLIP_FLOP *PFlip,
struct FLIP_FLOP *SProc )
{
COMPUTE_THERMAL(AMD,
PFlip->Thermal.Temp,
SProc->Thermal.Param,
PFlip->Thermal.Sensor);
}
static void Pkg_ComputeThermal_AMD_0Fh( struct PKG_FLIP_FLOP *PFlip,
struct FLIP_FLOP *SProc )
{
COMPUTE_THERMAL(AMD_0Fh,
PFlip->Thermal.Temp,
SProc->Thermal.Param,
PFlip->Thermal.Sensor);
}
static void Pkg_ComputeThermal_AMD_15h( struct PKG_FLIP_FLOP *PFlip,
struct FLIP_FLOP *SProc )
{
COMPUTE_THERMAL(AMD_15h,
PFlip->Thermal.Temp,
SProc->Thermal.Param,
PFlip->Thermal.Sensor);
}
static void Pkg_ComputeThermal_AMD_17h( struct PKG_FLIP_FLOP *PFlip,
struct FLIP_FLOP *SProc )
{
COMPUTE_THERMAL(AMD_17h,
PFlip->Thermal.Temp,
SProc->Thermal.Param,
PFlip->Thermal.Sensor);
}
static void Pkg_ComputeVoltage_None(struct PKG_FLIP_FLOP *PFlip)
{
UNUSED(PFlip);
}
#define Pkg_ComputeVoltage_Intel Pkg_ComputeVoltage_None
#define Pkg_ComputeVoltage_Intel_Core2 Pkg_ComputeVoltage_None
static void Pkg_ComputeVoltage_Intel_SoC(struct PKG_FLIP_FLOP *PFlip)
{
COMPUTE_VOLTAGE(INTEL_SOC,
PFlip->Voltage.CPU,
PFlip->Voltage.VID.CPU);
}
static void Pkg_ComputeVoltage_Intel_SNB(struct PKG_FLIP_FLOP *PFlip)
{ /* Intel 2nd Generation Datasheet Vol-1 Chap. 7.4 Table 7-1 */
COMPUTE_VOLTAGE(INTEL_SNB,
PFlip->Voltage.CPU,
PFlip->Voltage.VID.CPU);
}
#define Pkg_ComputeVoltage_Intel_SKL_X Pkg_ComputeVoltage_None
static void Pkg_ComputeVoltage_Intel_SAV(struct PKG_FLIP_FLOP *PFlip)
{
COMPUTE_VOLTAGE(INTEL_SNB,
PFlip->Voltage.CPU,
PFlip->Voltage.VID.CPU);
COMPUTE_VOLTAGE(INTEL_SAV,
PFlip->Voltage.SOC,
PFlip->Voltage.VID.SOC);
}
#define Pkg_ComputeVoltage_AMD Pkg_ComputeVoltage_None
#define Pkg_ComputeVoltage_AMD_0Fh Pkg_ComputeVoltage_None
#define Pkg_ComputeVoltage_AMD_15h Pkg_ComputeVoltage_None
static void Pkg_ComputeVoltage_AMD_17h(struct PKG_FLIP_FLOP *PFlip)
{
COMPUTE_VOLTAGE(AMD_17h,
PFlip->Voltage.CPU,
PFlip->Voltage.VID.CPU);
COMPUTE_VOLTAGE(AMD_17h,
PFlip->Voltage.SOC,
PFlip->Voltage.VID.SOC);
}
static void Pkg_ComputeVoltage_AMD_RMB(struct PKG_FLIP_FLOP *PFlip)
{
COMPUTE_VOLTAGE(AMD_RMB,
PFlip->Voltage.CPU,
PFlip->Voltage.VID.CPU);
COMPUTE_VOLTAGE(AMD_RMB,
PFlip->Voltage.SOC,
PFlip->Voltage.VID.SOC);
}
static void Pkg_ComputeVoltage_ZEN3_VCO(struct PKG_FLIP_FLOP *PFlip)
{
COMPUTE_VOLTAGE(AMD_VCO,
PFlip->Voltage.CPU,
PFlip->Voltage.VID.CPU);
COMPUTE_VOLTAGE(AMD_17h,
PFlip->Voltage.SOC,
PFlip->Voltage.VID.SOC);
}
static void Pkg_ComputeVoltage_ZEN4_VCO(struct PKG_FLIP_FLOP *PFlip)
{
COMPUTE_VOLTAGE(AMD_VCO,
PFlip->Voltage.CPU,
PFlip->Voltage.VID.CPU);
COMPUTE_VOLTAGE(AMD_RMB,
PFlip->Voltage.SOC,
PFlip->Voltage.VID.SOC);
}
static void Pkg_ComputeVoltage_ZEN5_VCO(struct PKG_FLIP_FLOP *PFlip)
{
COMPUTE_VOLTAGE(AMD_VCO,
PFlip->Voltage.CPU,
PFlip->Voltage.VID.CPU);
/*TODO(Unknown SOC voltage register)
COMPUTE_VOLTAGE(AMD_VCO,
PFlip->Voltage.SOC,
PFlip->Voltage.VID.SOC); */
}
static void Pkg_ComputeVoltage_Winbond_IO(struct PKG_FLIP_FLOP *PFlip)
{ /* Winbond W83627EHF/EF, W83627EHG,EG */
COMPUTE_VOLTAGE(WINBOND_IO,
PFlip->Voltage.CPU,
PFlip->Voltage.VID.CPU);
}
static void Pkg_ComputeVoltage_ITE_Tech_IO(struct PKG_FLIP_FLOP *PFlip)
{
COMPUTE_VOLTAGE(ITETECH_IO,
PFlip->Voltage.CPU,
PFlip->Voltage.VID.CPU);
}
static void Pkg_ComputePower_None(RW(PROC) *RW(Proc), struct FLIP_FLOP *CFlop)
{
UNUSED(RW(Proc));
UNUSED(CFlop);
}
#define Pkg_ComputePower_Intel Pkg_ComputePower_None
#define Pkg_ComputePower_Intel_Atom Pkg_ComputePower_None
#define Pkg_ComputePower_AMD Pkg_ComputePower_None
static void Pkg_ComputePower_AMD_17h( RW(PROC) *RW(Proc),
struct FLIP_FLOP *CFlop )
{
RW(Proc)->Delta.Power.ACCU[PWR_DOMAIN(CORES)] += CFlop->Delta.Power.ACCU;
RW(Proc)->Delta.Power.ACCU[PWR_DOMAIN(RAM)] += CFlop->Delta.RAM.ACCU;
}
static void Pkg_ResetPower_None(PROC_RW *Proc)
{
UNUSED(Proc);
}
#define Pkg_ResetPower_Intel Pkg_ResetPower_None
#define Pkg_ResetPower_Intel_Atom Pkg_ResetPower_None
#define Pkg_ResetPower_AMD Pkg_ResetPower_None
static void Pkg_ResetPower_AMD_17h(RW(PROC) *RW(Proc))
{
RW(Proc)->Delta.Power.ACCU[PWR_DOMAIN(CORES)] = 0;
RW(Proc)->Delta.Power.ACCU[PWR_DOMAIN(RAM)] = 0;
}
void Pkg_ResetSensorLimits(PROC_STRUCT *Pkg)
{
enum PWR_DOMAIN pw;
for (pw = PWR_DOMAIN(PKG); pw < PWR_DOMAIN(SIZE); pw++)
{
RESET_SENSOR_LIMIT(ENERGY, LOWEST , Pkg->State.Energy[pw].Limit);
RESET_SENSOR_LIMIT(ENERGY, HIGHEST, Pkg->State.Energy[pw].Limit );
RESET_SENSOR_LIMIT(POWER , LOWEST , Pkg->State.Power[pw].Limit );
RESET_SENSOR_LIMIT(POWER , HIGHEST, Pkg->State.Power[pw].Limit );
}
RESET_SENSOR_LIMIT(VOLTAGE, LOWEST, Pkg->State.Voltage.Limit );
RESET_SENSOR_LIMIT(VOLTAGE, HIGHEST,Pkg->State.Voltage.Limit );
}
REASON_CODE Core_Manager(REF *Ref)
{
RO(SHM_STRUCT) *RO(Shm) = Ref->RO(Shm);
RW(SHM_STRUCT) *RW(Shm) = Ref->RW(Shm);
RO(PROC) *RO(Proc) = Ref->RO(Proc);
RW(PROC) *RW(Proc) = Ref->RW(Proc);
RO(CORE) **RO(Core) = Ref->RO(Core);
struct PKG_FLIP_FLOP *PFlip;
struct FLIP_FLOP *SProc;
SERVICE_PROC localService = RESET_SERVICE;
struct {
double RelFreq,
AbsFreq;
} prevTop;
REASON_INIT (reason);
unsigned int cpu = 0;
pthread_t tid = pthread_self();
#ifdef __GLIBC__
RO(Shm)->App.Svr = tid;
#else
RO(Shm)->App.Svr = getpid();
#endif
if (ServerFollowService(&localService, &RO(Shm)->Proc.Service, tid) == 0) {
pthread_setname_np(tid, "corefreqd-pmgr");
}
ARG *Arg = calloc(RO(Shm)->Proc.CPU.Count, sizeof(ARG));
if (Arg != NULL)
{
void (*Pkg_ComputeThermalFormula)( struct PKG_FLIP_FLOP*,
struct FLIP_FLOP* );
void (*Pkg_ComputeVoltageFormula)( struct PKG_FLIP_FLOP* );
void (*Pkg_ComputePowerFormula)( PROC_RW*, struct FLIP_FLOP* );
void (*Pkg_ResetPowerFormula)(PROC_RW*);
switch (KIND_OF_FORMULA(RO(Shm)->Proc.thermalFormula)) {
case THERMAL_KIND_INTEL:
Pkg_ComputeThermalFormula = Pkg_ComputeThermal_Intel;
break;
case THERMAL_KIND_AMD:
Pkg_ComputeThermalFormula = Pkg_ComputeThermal_AMD;
break;
case THERMAL_KIND_AMD_0Fh:
Pkg_ComputeThermalFormula = Pkg_ComputeThermal_AMD_0Fh;
break;
case THERMAL_KIND_AMD_15h:
Pkg_ComputeThermalFormula = Pkg_ComputeThermal_AMD_15h;
break;
case THERMAL_KIND_AMD_17h:
Pkg_ComputeThermalFormula = Pkg_ComputeThermal_AMD_17h;
break;
case THERMAL_KIND_NONE:
default:
Pkg_ComputeThermalFormula = Pkg_ComputeThermal_None;
}
switch (KIND_OF_FORMULA(RO(Shm)->Proc.voltageFormula)) {
case VOLTAGE_KIND_INTEL:
Pkg_ComputeVoltageFormula = Pkg_ComputeVoltage_Intel;
break;
case VOLTAGE_KIND_INTEL_CORE2:
Pkg_ComputeVoltageFormula = Pkg_ComputeVoltage_Intel_Core2;
break;
case VOLTAGE_KIND_INTEL_SOC:
Pkg_ComputeVoltageFormula = Pkg_ComputeVoltage_Intel_SoC;
break;
case VOLTAGE_KIND_INTEL_SNB:
Pkg_ComputeVoltageFormula = Pkg_ComputeVoltage_Intel_SNB;
break;
case VOLTAGE_KIND_INTEL_SKL_X:
Pkg_ComputeVoltageFormula = Pkg_ComputeVoltage_Intel_SKL_X;
break;
case VOLTAGE_KIND_INTEL_SAV:
Pkg_ComputeVoltageFormula = Pkg_ComputeVoltage_Intel_SAV;
break;
case VOLTAGE_KIND_AMD:
Pkg_ComputeVoltageFormula = Pkg_ComputeVoltage_AMD;
break;
case VOLTAGE_KIND_AMD_0Fh:
Pkg_ComputeVoltageFormula = Pkg_ComputeVoltage_AMD_0Fh;
break;
case VOLTAGE_KIND_AMD_15h:
Pkg_ComputeVoltageFormula = Pkg_ComputeVoltage_AMD_15h;
break;
case VOLTAGE_KIND_AMD_17h:
Pkg_ComputeVoltageFormula = Pkg_ComputeVoltage_AMD_17h;
break;
case VOLTAGE_KIND_AMD_RMB:
Pkg_ComputeVoltageFormula = Pkg_ComputeVoltage_AMD_RMB;
break;
case VOLTAGE_KIND_ZEN3_VCO:
Pkg_ComputeVoltageFormula = Pkg_ComputeVoltage_ZEN3_VCO;
break;
case VOLTAGE_KIND_ZEN4_VCO:
Pkg_ComputeVoltageFormula = Pkg_ComputeVoltage_ZEN4_VCO;
break;
case VOLTAGE_KIND_ZEN5_VCO:
Pkg_ComputeVoltageFormula = Pkg_ComputeVoltage_ZEN5_VCO;
break;
case VOLTAGE_KIND_WINBOND_IO:
Pkg_ComputeVoltageFormula = Pkg_ComputeVoltage_Winbond_IO;
break;
case VOLTAGE_KIND_ITETECH_IO:
Pkg_ComputeVoltageFormula = Pkg_ComputeVoltage_ITE_Tech_IO;
break;
case VOLTAGE_KIND_NONE:
default:
Pkg_ComputeVoltageFormula = Pkg_ComputeVoltage_None;
break;
}
switch (KIND_OF_FORMULA(RO(Shm)->Proc.powerFormula)) {
case POWER_KIND_INTEL:
Pkg_ComputePowerFormula = Pkg_ComputePower_Intel;
Pkg_ResetPowerFormula = Pkg_ResetPower_Intel;
break;
case POWER_KIND_INTEL_ATOM:
Pkg_ComputePowerFormula = Pkg_ComputePower_Intel_Atom;
Pkg_ResetPowerFormula = Pkg_ResetPower_Intel_Atom;
break;
case POWER_KIND_AMD:
Pkg_ComputePowerFormula = Pkg_ComputePower_AMD;
Pkg_ResetPowerFormula = Pkg_ResetPower_AMD;
break;
case POWER_KIND_AMD_17h:
Pkg_ComputePowerFormula = Pkg_ComputePower_AMD_17h;
Pkg_ResetPowerFormula = Pkg_ResetPower_AMD_17h;
break;
case POWER_KIND_NONE:
default:
Pkg_ComputePowerFormula = Pkg_ComputePower_None;
Pkg_ResetPowerFormula = Pkg_ResetPower_None;
break;
}
#if defined(LEGACY) && LEGACY > 0
#define ROOM_CLEAR(_room_) \
BITZERO(BUS_LOCK, _room_##Core[CORE_WORD_TOP(CORE_COUNT)])
#else
#define ROOM_CLEAR(_room_) \
BITCMP_CC(BUS_LOCK, _room_##Core, _room_##Clear)
#endif
#define ROOM_RESET(_room_) \
BITSTOR_CC(BUS_LOCK, _room_##Core, _room_##Seed)
#define ROOM_READY(_room_) \
BITCMP_CC(BUS_LOCK, _room_##Ready, _room_##Seed)
#define CONDITION_RDTSCP() \
( (RO(Proc)->Features.AdvPower.EDX.Inv_TSC == 1) \
|| (RO(Proc)->Features.ExtInfo.EDX.RDTSCP == 1) )
#define CONDITION_RDPMC() \
( (RO(Proc)->Features.Info.Vendor.CRC == CRC_INTEL) \
&& (RO(Proc)->Features.PerfMon.EAX.Version >= 1) \
&& (BITVAL(RO(Core, AT(RO(Proc)->Service.Core))->SystemRegister.CR4, \
CR4_PCE) == 1) )
UBENCH_SETUP(CONDITION_RDTSCP(), CONDITION_RDPMC());
Print_uBenchmark((Quiet & 0x100));
while (!BITVAL(Shutdown, SYNC))
{ /* Loop while all the cpu room bits are not cleared. */
while (!BITVAL(Shutdown, SYNC) && !ROOM_CLEAR(room))
{
nanosleep(&RO(Shm)->Sleep.pollingWait, NULL);
}
UBENCH_RDCOUNTER(1);
RO(Shm)->Proc.Toggle = !RO(Shm)->Proc.Toggle;
PFlip = &RO(Shm)->Proc.FlipFlop[RO(Shm)->Proc.Toggle];
SProc = &RO(Shm)->Cpu[RO(Shm)->Proc.Service.Core].FlipFlop[
!RO(Shm)->Cpu[RO(Shm)->Proc.Service.Core].Toggle
];
PFlip->Thermal.Temp = 0;
/* Reset the averages & the max frequency */
RO(Shm)->Proc.Avg.Turbo = 0;
RO(Shm)->Proc.Avg.C0 = 0;
RO(Shm)->Proc.Avg.C3 = 0;
RO(Shm)->Proc.Avg.C6 = 0;
RO(Shm)->Proc.Avg.C7 = 0;
RO(Shm)->Proc.Avg.C1 = 0;
prevTop.RelFreq = 0.0;
prevTop.AbsFreq = 0.0;
Pkg_ResetPowerFormula(RW(Proc));
/* Reset with Package Events */
memcpy( RO(Shm)->ProcessorEvents, PFlip->Thermal.Events,
sizeof(RO(Shm)->ProcessorEvents) );
for (cpu=0; !BITVAL(Shutdown, SYNC)&&(cpu < RO(Shm)->Proc.CPU.Count);cpu++)
{
if (BITVAL(RO(Core, AT(cpu))->OffLine, OS) == 1)
{
if (Arg[cpu].TID)
{ /* Remove this cpu. */
if (pthread_join(Arg[cpu].TID, NULL) == 0)
{
BITCLR_CC(BUS_LOCK, roomReady, cpu);
Arg[cpu].TID = 0;
PerCore_Update(RO(Shm), RO(Proc), RO(Core), cpu);
if (ServerFollowService( &localService,
&RO(Shm)->Proc.Service,
tid ) == 0)
{
SProc = &RO(Shm)->Cpu[RO(Shm)->Proc.Service.Core].FlipFlop[
!RO(Shm)->Cpu[RO(Shm)->Proc.Service.Core].Toggle
];
}
/* Raise these bits up to notify a platform change. */
BITWISESET(LOCKLESS, PendingSync, BIT_MASK_NTFY);
}
}
BITSET(LOCKLESS, RO(Shm)->Cpu[cpu].OffLine, OS);
} else {
struct FLIP_FLOP *CFlop = &RO(Shm)->Cpu[cpu].FlipFlop[
!RO(Shm)->Cpu[cpu].Toggle
];
if (!Arg[cpu].TID)
{ /* Add this cpu. */
Arg[cpu].Ref = Ref;
Arg[cpu].Bind = cpu;
if (pthread_create( &Arg[cpu].TID,
NULL,
Core_Cycle,
&Arg[cpu]) == 0)
{
BITSET_CC(BUS_LOCK, roomReady, cpu);
PerCore_Update(RO(Shm), RO(Proc), RO(Core), cpu);
if (ServerFollowService(&localService,
&RO(Shm)->Proc.Service,
tid) == 0)
{
SProc = &RO(Shm)->Cpu[RO(Shm)->Proc.Service.Core].FlipFlop[
!RO(Shm)->Cpu[RO(Shm)->Proc.Service.Core].Toggle
];
}
if (Quiet & 0x100) {
printf( " CPU #%03u @ %.2f MHz\n", cpu,
ABS_FREQ_MHz(double , RO(Shm)->Cpu[cpu].Boost[BOOST(MAX)],
RO(Core, AT(cpu))->Clock) );
}
/* Notify a CPU has been brought up */
BITWISESET(LOCKLESS, PendingSync, BIT_MASK_NTFY);
}
}
BITCLR(LOCKLESS, RO(Shm)->Cpu[cpu].OffLine, OS);
/* Index CPU with the highest Rel. and Abs frequencies. */
if (CFlop->Relative.Freq > prevTop.RelFreq) {
prevTop.RelFreq = CFlop->Relative.Freq;
RO(Shm)->Proc.Top.Rel = cpu;
}
if (CFlop->Absolute.Freq > prevTop.AbsFreq) {
prevTop.AbsFreq = CFlop->Absolute.Freq;
RO(Shm)->Proc.Top.Abs = cpu;
}
/* Workaround to Package Thermal Management: the hottest Core */
if (!RO(Shm)->Proc.Features.Power.EAX.PTM) {
if (CFlop->Thermal.Temp > PFlip->Thermal.Temp)
PFlip->Thermal.Temp = CFlop->Thermal.Temp;
}
/* Workaround to RAPL Package counter: sum of all Cores */
Pkg_ComputePowerFormula(RW(Proc), CFlop);
/* Sum counters. */
RO(Shm)->Proc.Avg.Turbo += CFlop->State.Turbo;
RO(Shm)->Proc.Avg.C0 += CFlop->State.C0;
RO(Shm)->Proc.Avg.C3 += CFlop->State.C3;
RO(Shm)->Proc.Avg.C6 += CFlop->State.C6;
RO(Shm)->Proc.Avg.C7 += CFlop->State.C7;
RO(Shm)->Proc.Avg.C1 += CFlop->State.C1;
/* Aggregate all Cores Events. */
RO(Shm)->ProcessorEvents[eLOG] |= CFlop->Thermal.Events[eLOG];
RO(Shm)->ProcessorEvents[eSTS] |= CFlop->Thermal.Events[eSTS];
}
}
if (!BITVAL(Shutdown, SYNC) && ROOM_READY(room))
{
unsigned char fRESET = 0;
/* Compute the counters averages. */
RO(Shm)->Proc.Avg.Turbo /= RO(Shm)->Proc.CPU.OnLine;
RO(Shm)->Proc.Avg.C0 /= RO(Shm)->Proc.CPU.OnLine;
RO(Shm)->Proc.Avg.C3 /= RO(Shm)->Proc.CPU.OnLine;
RO(Shm)->Proc.Avg.C6 /= RO(Shm)->Proc.CPU.OnLine;
RO(Shm)->Proc.Avg.C7 /= RO(Shm)->Proc.CPU.OnLine;
RO(Shm)->Proc.Avg.C1 /= RO(Shm)->Proc.CPU.OnLine;
/* Package scope counters */
PFlip->Delta.PCLK = RO(Proc)->Delta.PCLK;
PFlip->Delta.PC02 = RO(Proc)->Delta.PC02;
PFlip->Delta.PC03 = RO(Proc)->Delta.PC03;
PFlip->Delta.PC04 = RO(Proc)->Delta.PC04;
PFlip->Delta.PC06 = RO(Proc)->Delta.PC06;
PFlip->Delta.PC07 = RO(Proc)->Delta.PC07;
PFlip->Delta.PC08 = RO(Proc)->Delta.PC08;
PFlip->Delta.PC09 = RO(Proc)->Delta.PC09;
PFlip->Delta.PC10 = RO(Proc)->Delta.PC10;
PFlip->Delta.MC6 = RO(Proc)->Delta.MC6;
/* Package C-state Residency counters */
RO(Shm)->Proc.State.PC02= (double)PFlip->Delta.PC02
/ (double)PFlip->Delta.PCLK;
RO(Shm)->Proc.State.PC03= (double)PFlip->Delta.PC03
/ (double)PFlip->Delta.PCLK;
RO(Shm)->Proc.State.PC04= (double)PFlip->Delta.PC04
/ (double)PFlip->Delta.PCLK;
RO(Shm)->Proc.State.PC06= (double)PFlip->Delta.PC06
/ (double)PFlip->Delta.PCLK;
RO(Shm)->Proc.State.PC07= (double)PFlip->Delta.PC07
/ (double)PFlip->Delta.PCLK;
RO(Shm)->Proc.State.PC08= (double)PFlip->Delta.PC08
/ (double)PFlip->Delta.PCLK;
RO(Shm)->Proc.State.PC09= (double)PFlip->Delta.PC09
/ (double)PFlip->Delta.PCLK;
RO(Shm)->Proc.State.PC10= (double)PFlip->Delta.PC10
/ (double)PFlip->Delta.PCLK;
RO(Shm)->Proc.State.MC6 = (double)PFlip->Delta.MC6
/ (double)PFlip->Delta.PCLK;
/* Uncore scope counters */
PFlip->Uncore.FC0 = RO(Proc)->Delta.Uncore.FC0;
/* Power & Energy counters */
enum PWR_DOMAIN pw;
for (pw = PWR_DOMAIN(PKG); pw < PWR_DOMAIN(SIZE); pw++)
{
PFlip->Delta.ACCU[pw] = RW(Proc)->Delta.Power.ACCU[pw];
RO(Shm)->Proc.State.Energy[pw].Current = PFlip->Delta.ACCU[pw];
RO(Shm)->Proc.State.Energy[pw].Current *= \
RO(Shm)->Proc.Power.Unit.Joules;
RO(Shm)->Proc.State.Power[pw].Current = \
RO(Shm)->Proc.State.Energy[pw].Current;
RO(Shm)->Proc.State.Power[pw].Current *= 1000.0;
RO(Shm)->Proc.State.Power[pw].Current /= RO(Shm)->Sleep.Interval;
/* Processor scope: computes Min and Max energy consumed. */
TEST_AND_SET_SENSOR( ENERGY, LOWEST,
RO(Shm)->Proc.State.Energy[pw].Current,
RO(Shm)->Proc.State.Energy[pw].Limit );
TEST_AND_SET_SENSOR( ENERGY, HIGHEST,
RO(Shm)->Proc.State.Energy[pw].Current,
RO(Shm)->Proc.State.Energy[pw].Limit );
/* Processor scope: computes Min and Max power consumed. */
TEST_AND_SET_SENSOR( POWER, LOWEST,
RO(Shm)->Proc.State.Power[pw].Current,
RO(Shm)->Proc.State.Power[pw].Limit );
TEST_AND_SET_SENSOR( POWER, HIGHEST,
RO(Shm)->Proc.State.Power[pw].Current,
RO(Shm)->Proc.State.Power[pw].Limit );
}
/* Package Processor & Plaftorm events */
memcpy( PFlip->Thermal.Events, RO(Proc)->PowerThermal.Events,
sizeof(PFlip->Thermal.Events) );
/* Package thermal formulas */
if (RO(Shm)->Proc.Features.Power.EAX.PTM)
{
PFlip->Thermal.Sensor = RO(Proc)->PowerThermal.Sensor;
Pkg_ComputeThermalFormula(PFlip, SProc);
}
/* Package Voltage formulas */
PFlip->Voltage.VID.CPU = RO(Proc)->PowerThermal.VID.CPU;
PFlip->Voltage.VID.SOC = RO(Proc)->PowerThermal.VID.SOC;
Pkg_ComputeVoltageFormula(PFlip);
/* Computes the Min Processor voltage. */
TEST_AND_SET_SENSOR( VOLTAGE, LOWEST, PFlip->Voltage.CPU,
RO(Shm)->Proc.State.Voltage.Limit );
/* Computes the Max Processor voltage. */
TEST_AND_SET_SENSOR( VOLTAGE, HIGHEST, PFlip->Voltage.CPU,
RO(Shm)->Proc.State.Voltage.Limit );
/*
The Driver tick is bound to the Service Core:
1- Tasks collection; Tasks count; and Memory usage.
2- Processor has resumed from Suspend To RAM.
*/
RO(Shm)->SysGate.tickStep = RO(Proc)->tickStep;
if (RO(Shm)->SysGate.tickStep == RO(Shm)->SysGate.tickReset)
{
if (BITWISEAND(LOCKLESS, RO(Shm)->SysGate.Operation, 0x1))
{
if (SysGate_OnDemand(Ref, 1) == 0) {
SysGate_Update(Ref);
}
}
/* OS notifications: such as Resumed from Suspend */
if ( (fRESET = BITCLR(BUS_LOCK, RW(Proc)->OS.Signal, NTFY )) == 1)
{
BITWISESET(LOCKLESS, PendingSync, BIT_MASK_COMP|BIT_MASK_NTFY);
}
}
if (BITWISEAND(LOCKLESS, PendingSync, BIT_MASK_COMP|BIT_MASK_NTFY))
{
Package_Update(RO(Shm), RO(Proc), RW(Proc));
Uncore_Update(RO(Shm), RO(Proc), RO(Core, AT(RO(Proc)->Service.Core)));
for (cpu = 0; cpu < Ref->RO(Shm)->Proc.CPU.Count; cpu++)
{
if (fRESET == 1)
{
Core_ResetSensorLimits(&RO(Shm)->Cpu[cpu]);
}
if (BITVAL(RO(Ref->Core, AT(cpu))->OffLine, OS) == 0)
{
PerCore_Update(Ref->RO(Shm), RO(Ref->Proc), RO(Ref->Core), cpu);
}
}
if (fRESET == 1)
{
Pkg_ResetSensorLimits(&RO(Shm)->Proc);
}
Technology_Update(RO(Shm), RO(Proc), RW(Proc));
if (ServerFollowService(&localService,
&RO(Shm)->Proc.Service,
tid) == 0)
{
SProc = &RO(Shm)->Cpu[RO(Shm)->Proc.Service.Core].FlipFlop[
!RO(Shm)->Cpu[RO(Shm)->Proc.Service.Core].Toggle
];
}
if (Quiet & 0x100) {
printf("\t%s || %s\n",
BITVAL(PendingSync, NTFY0) ? "NTFY":"....",
BITVAL(PendingSync, COMP0) ? "COMP":"....");
}
}
/* All aggregations done: Notify Clients. */
BITWISESET(LOCKLESS, PendingSync, BIT_MASK_SYNC);
BITWISESET(LOCKLESS, RW(Shm)->Proc.Sync, PendingSync);
BITWISECLR(LOCKLESS, PendingSync);
}
/* Reset the Room mask */
ROOM_RESET(room);
UBENCH_RDCOUNTER(2);
UBENCH_COMPUTE();
Print_uBenchmark((Quiet & 0x100));
}
#undef CONDITION_RDPMC
#undef CONDITION_RDTSCP
#undef ROOM_RESET
#undef ROOM_READY
#undef ROOM_CLEAR
for (cpu = 0; cpu < RO(Shm)->Proc.CPU.Count; cpu++) {
if (Arg[cpu].TID) {
pthread_join(Arg[cpu].TID, NULL);
}
}
free(Arg);
} else {
REASON_SET(reason, RC_MEM_ERR, (errno == 0 ? ENOMEM : errno));
}
return reason;
}
REASON_CODE Child_Manager(REF *Ref)
{
RO(SHM_STRUCT) *RO(Shm) = Ref->RO(Shm);
SERVICE_PROC localService = RESET_SERVICE;
REASON_INIT(reason);
unsigned int cpu = 0;
pthread_t tid = pthread_self();
if (ServerFollowService(&localService, &RO(Shm)->Proc.Service, tid) == 0) {
pthread_setname_np(tid, "corefreqd-cmgr");
}
ARG *Arg = calloc(RO(Shm)->Proc.CPU.Count, sizeof(ARG));
if (Arg != NULL)
{
do {
for(cpu=0; !BITVAL(Shutdown, SYNC) && (cpu < RO(Shm)->Proc.CPU.Count);cpu++)
{
if (BITVAL(RO(Shm)->Cpu[cpu].OffLine, OS) == 1) {
if (Arg[cpu].TID) {
/* Remove this child thread. */
pthread_join(Arg[cpu].TID, NULL);
Arg[cpu].TID = 0;
}
} else {
unsigned int seed32;
__asm__ volatile
(
"rdtsc" "\n\t"
"movl %%eax, %0"
: "=m" (seed32)
:
: "%rax", "%rcx", "%rdx", "cc", "memory"
);
#ifdef __GLIBC__
initstate_r( seed32,
RO(Shm)->Cpu[cpu].Slice.Random.state,
sizeof(RO(Shm)->Cpu[cpu].Slice.Random.state),
&RO(Shm)->Cpu[cpu].Slice.Random.data );
#else
initstate(seed32, RO(Shm)->Cpu[cpu].Slice.Random.state, 128);
#endif
if (!Arg[cpu].TID) {
/* Add this child thread. */
Arg[cpu].Ref = Ref;
Arg[cpu].Bind = cpu;
pthread_create( &Arg[cpu].TID,
NULL,
Child_Thread,
&Arg[cpu]);
}
}
}
ServerFollowService(&localService, &RO(Shm)->Proc.Service, tid);
nanosleep(&RO(Shm)->Sleep.childWaiting, NULL);
}
while (!BITVAL(Shutdown, SYNC)) ;
for (cpu = 0; cpu < RO(Shm)->Proc.CPU.Count; cpu++) {
if (Arg[cpu].TID) {
pthread_join(Arg[cpu].TID, NULL);
}
}
free(Arg);
} else {
REASON_SET(reason, RC_MEM_ERR, (errno == 0 ? ENOMEM : errno));
}
return reason;
}
REASON_CODE Shm_Manager(FD *fd, RO(PROC) *RO(Proc), RW(PROC) *RW(Proc),
uid_t uid, uid_t gid, mode_t cmask[2])
{
unsigned int cpu = 0;
RO(CORE) **RO(Core);
RW(CORE) **RW(Core);
RO(SHM_STRUCT) *RO(Shm) = NULL;
RW(SHM_STRUCT) *RW(Shm) = NULL;
struct {
const size_t RO(Core),
RW(Core);
} Size = {
ROUND_TO_PAGES(sizeof(RO(CORE))),
ROUND_TO_PAGES(sizeof(RW(CORE)))
};
REASON_INIT(reason);
if ((RO(Core) = calloc(RO(Proc)->CPU.Count, sizeof(RO(Core)))) == NULL) {
REASON_SET(reason, RC_MEM_ERR, (errno == 0 ? ENOMEM : errno));
}
if ((RW(Core) = calloc(RO(Proc)->CPU.Count, sizeof(RW(Core)))) == NULL) {
REASON_SET(reason, RC_MEM_ERR, (errno == 0 ? ENOMEM : errno));
}
for(cpu = 0;(reason.rc == RC_SUCCESS) && (cpu < RO(Proc)->CPU.Count); cpu++)
{
const off_t vm_ro_pgoff = (ID_RO_VMA_CORE + cpu) * PAGE_SIZE,
vm_rw_pgoff = (ID_RW_VMA_CORE + cpu) * PAGE_SIZE;
if ((RO(Core, AT(cpu)) = mmap(NULL, Size.RO(Core),
PROT_READ,
MAP_SHARED,
fd->drv, vm_ro_pgoff)) == MAP_FAILED)
{
REASON_SET(reason, RC_SHM_MMAP);
}
if ((RW(Core, AT(cpu)) = mmap(NULL, Size.RW(Core),
PROT_READ|PROT_WRITE,
MAP_SHARED,
fd->drv, vm_rw_pgoff)) == MAP_FAILED)
{
REASON_SET(reason, RC_SHM_MMAP);
}
}
if (reason.rc == RC_SUCCESS) {
if (gid != 0) {
if (setregid((gid_t) -1, gid) != 0) {
REASON_SET(reason, RC_SYS_CALL);
}
}
}
if (reason.rc == RC_SUCCESS) {
if (uid != 0) {
if (setreuid((uid_t) -1, uid) != 0) {
REASON_SET(reason, RC_SYS_CALL);
}
}
}
if (reason.rc == RC_SUCCESS)
{ /* Initialize shared memory. */
const size_t shmCpuSize = sizeof(CPU_STRUCT) * RO(Proc)->CPU.Count,
roSize = ROUND_TO_PAGES((sizeof(RO(SHM_STRUCT))
+ shmCpuSize)),
rwSize = ROUND_TO_PAGES(sizeof(RW(SHM_STRUCT)));
if ( ((fd->ro = shm_open(RO(SHM_FILENAME), O_CREAT|O_TRUNC|O_RDWR,
S_IRUSR|S_IWUSR
|S_IRGRP|S_IWGRP
|S_IROTH|S_IWOTH)) != -1)
&& ((fd->rw = shm_open(RW(SHM_FILENAME), O_CREAT|O_TRUNC|O_RDWR,
S_IRUSR|S_IWUSR
|S_IRGRP|S_IWGRP
|S_IROTH|S_IWOTH)) != -1) )
{
pid_t CPID = -1;
if ( (ftruncate(fd->ro, (off_t) roSize) != -1)
&& (ftruncate(fd->rw, (off_t) rwSize) != -1) )
{
fchmod(fd->ro, cmask[0]);
fchmod(fd->rw, cmask[1]);
if ( ( ( RO(Shm) = mmap(NULL, roSize,
PROT_READ|PROT_WRITE, MAP_SHARED,
fd->ro, 0) ) != MAP_FAILED )
&& ( ( RW(Shm) = mmap(NULL, rwSize,
PROT_READ|PROT_WRITE, MAP_SHARED,
fd->rw, 0) ) != MAP_FAILED ) )
{
__typeof__ (errno) fork_err = 0;
/* Clear SHM */
memset(RO(Shm), 0, roSize);
memset(RW(Shm), 0, rwSize);
/* Store version footprint into SHM */
SET_FOOTPRINT(RO(Shm)->FootPrint,MAX_FREQ_HZ,
CORE_COUNT,
TASK_ORDER,
COREFREQ_MAJOR,
COREFREQ_MINOR,
COREFREQ_REV );
/* Reference time the Server is starting at. */
time(&RO(Shm)->StartedAt);
/* Store the daemon gate name. */
StrCopy(RO(Shm)->ShmName, RO(SHM_FILENAME), TASK_COMM_LEN);
/* Initialize the busy wait times. */
RO(Shm)->Sleep.ringWaiting = TIMESPEC(SIG_RING_MS);
RO(Shm)->Sleep.childWaiting = TIMESPEC(CHILD_PS_MS);
RO(Shm)->Sleep.sliceWaiting = TIMESPEC(CHILD_TH_MS);
REF Ref = {
.CPID = -1,
.KID = 0,
.Started = 0,
.Slice.Func = NULL,
.Slice.arg = 0,
.fd = fd,
.RO(Shm) = RO(Shm),
.RW(Shm) = RW(Shm),
.RO(Proc) = RO(Proc),
.RW(Proc) = RW(Proc),
.RO(Core) = RO(Core),
.RW(Core) = RW(Core),
.RO(SysGate) = NULL
};
sigemptyset(&Ref.Signal);
Package_Update(RO(Shm), RO(Proc), RW(Proc));
memcpy(&RO(Shm)->SMB, &RO(Proc)->SMB, sizeof(SMBIOS_ST));
/* Clear notification. */
BITWISECLR(LOCKLESS, RW(Shm)->Proc.Sync);
SysGate_Toggle(&Ref, SysGateStartUp);
/* Welcomes with brand and per CPU base clock. */
if (Quiet & 0x001) {
printf( "CoreFreq Daemon %s" \
" Copyright (C) 2015-2025 CYRIL COURTIAT\n",
COREFREQ_VERSION );
}
if (Quiet & 0x010) {
printf( "\n" \
" Processor [%s]\n" \
" Architecture [%s] %u/%u CPU Online.\n",
RO(Shm)->Proc.Brand,
RO(Shm)->Proc.Architecture,
RO(Shm)->Proc.CPU.OnLine,
RO(Shm)->Proc.CPU.Count );
}
if (Quiet & 0x100) {
printf( " SleepInterval(%u), SysGate(%u), %ld tasks\n\n",
RO(Shm)->Sleep.Interval,
!BITVAL(RO(Shm)->SysGate.Operation, 0) ?
0:RO(Shm)->Sleep.Interval * RO(Shm)->SysGate.tickReset,
TASK_LIMIT );
}
if (Quiet) {
fflush(stdout);
}
CPID = Ref.CPID = fork();
/*-----[ Resources inherited ]----------------------------------*/
fork_err = errno;
Emergency_Command(&Ref, 1);
switch (Ref.CPID) {
case 0:
reason = Child_Manager(&Ref);
break;
case -1:
REASON_SET(reason, RC_EXEC_ERR, fork_err);
break;
default:
reason = Core_Manager(&Ref);
if (gid != 0) {
if (setregid((gid_t) -1, 0) != 0) {
REASON_SET(reason, RC_SYS_CALL);
}
}
if (uid != 0) {
if (setreuid((uid_t) -1, 0) != 0) {
REASON_SET(reason, RC_SYS_CALL);
}
}
if (RO(Shm)->App.Cli) {
if (kill(RO(Shm)->App.Cli, SIGTERM) == -1) {
if (errno != ESRCH)
REASON_SET(reason, RC_EXEC_ERR);
}
}
if (RO(Shm)->App.GUI) {
if (kill(RO(Shm)->App.GUI, SIGTERM) == -1) {
if (errno != ESRCH)
REASON_SET(reason, RC_EXEC_ERR);
}
}
SysGate_OnDemand(&Ref, 0);
if (kill(Ref.CPID, SIGQUIT) == 0) {
if (waitpid(Ref.CPID, NULL, 0) == -1) {
REASON_SET(reason, RC_EXEC_ERR);
}
} else {
REASON_SET(reason, RC_EXEC_ERR);
}
break;
}
Emergency_Command(&Ref, 0);
if (munmap(RO(Shm), roSize) == -1) {
REASON_SET(reason, RC_SHM_MMAP);
}
if (munmap(RW(Shm), rwSize) == -1) {
REASON_SET(reason, RC_SHM_MMAP);
}
} else {
REASON_SET(reason, RC_SHM_MMAP);
}
} else {
REASON_SET(reason, RC_SHM_FILE);
}
if (close(fd->ro) == -1) {
REASON_SET(reason, RC_SHM_FILE);
}
if (close(fd->rw) == -1) {
REASON_SET(reason, RC_SHM_FILE);
}
if (CPID != 0) {
if (shm_unlink(RO(SHM_FILENAME)) == -1) {
REASON_SET(reason, RC_SHM_FILE);
}
if (shm_unlink(RW(SHM_FILENAME)) == -1) {
REASON_SET(reason, RC_SHM_FILE);
}
}
} else {
REASON_SET(reason, RC_SHM_FILE);
}
}
for (cpu = 0; cpu < RO(Proc)->CPU.Count; cpu++)
{
if (RO(Core, AT(cpu)) != NULL) {
if (munmap(RO(Core, AT(cpu)), Size.RO(Core)) == -1) {
REASON_SET(reason, RC_SHM_MMAP);
}
}
if (RW(Core, AT(cpu)) != NULL) {
if (munmap(RW(Core, AT(cpu)), Size.RW(Core)) == -1) {
REASON_SET(reason, RC_SHM_MMAP);
}
}
}
if (RO(Core) != NULL) {
free(RO(Core));
}
if (RW(Core) != NULL) {
free(RW(Core));
}
return reason;
}
REASON_CODE Help(REASON_CODE reason, ...)
{
va_list ap;
va_start(ap, reason);
switch (reason.rc) {
case RC_SUCCESS:
case RC_OK_SYSGATE:
case RC_OK_COMPUTE:
case RC_DRIVER_BASE ... RC_DRIVER_LAST:
break;
case RC_CMD_SYNTAX: {
char *appName = va_arg(ap, char *);
printf( "Usage:\t%s [-option <arguments>]\n" \
"\t-q\t\tQuiet\n" \
"\t-i\t\tInfo\n" \
"\t-d\t\tDebug\n" \
"\t-gon\t\tEnable SysGate\n" \
"\t-goff\t\tDisable SysGate\n" \
"\t-U <decimal>\tSet the effective user ID\n" \
"\t-G <decimal>\tSet the effective group ID\n" \
"\t-M <oct>,<oct>\tShared Memories permission\n"\
"\t-h\t\tPrint out this message\n" \
"\t-v\t\tPrint the version number\n" \
"\nExit status:\n" \
"\t%u\tSUCCESS\t\tSuccessful execution\n" \
"\t%u\tCMD_SYNTAX\tCommand syntax error\n" \
"\t%u\tSHM_FILE\tShared memory file error\n" \
"\t%u\tSHM_MMAP\tShared memory mapping error\n" \
"\t%u\tPERM_ERR\tExecution not permitted\n" \
"\t%u\tMEM_ERR\t\tMemory operation error\n" \
"\t%u\tEXEC_ERR\tGeneral execution error\n" \
"\t%u\tSYS_CALL\tSystem call error\n" \
"\nReport bugs to labs[at]cyring[.]fr\n", appName,
RC_SUCCESS,
RC_CMD_SYNTAX,
RC_SHM_FILE,
RC_SHM_MMAP,
RC_PERM_ERR,
RC_MEM_ERR,
RC_EXEC_ERR,
RC_SYS_CALL);
}
break;
case RC_PERM_ERR:
case RC_MEM_ERR:
case RC_EXEC_ERR: {
char *appName = va_arg(ap, char *);
char *sysMsg = strerror(reason.no);
fprintf(stderr, "%s execution error code %d\n%s @ line %d\n",
appName, reason.no, sysMsg, reason.ln);
}
break;
case RC_SHM_FILE:
case RC_SHM_MMAP: {
char *shmFileName = va_arg(ap, char *);
char *sysMsg = strerror(reason.no);
fprintf(stderr , "Driver connection error code %d\n" \
"%s: '%s' @ line %d\n",
reason.no, shmFileName, sysMsg, reason.ln);
}
break;
case RC_SYS_CALL: {
char *sysMsg = strerror(reason.no);
fprintf(stderr, "System error code %d\n%s @ line %d\n",
reason.no, sysMsg, reason.ln);
}
break;
}
va_end(ap);
return reason;
}
int main(int argc, char *argv[])
{
FD fd = {0, 0, 0};
RO(PROC) *RO(Proc) = NULL; /* Kernel module anchor points. */
RW(PROC) *RW(Proc) = NULL;
uid_t uid = 0, gid = 0;
mode_t cmask[2] = {
S_IRUSR|S_IRGRP|S_IROTH,
S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH
};
char *program = strdup(argv[0]),
*appName = program != NULL ? basename(program) : argv[0];
REASON_INIT(reason);
int i;
for (i = 1; i < argc; i++)
{
if (strlen(argv[i]) > 1) {
if (argv[i][0] == '-')
{
char option = argv[i][1];
switch (option) {
case 'q':
Quiet = 0x000;
break;
case 'i':
Quiet = 0x011;
break;
case 'd':
Quiet = 0x111;
break;
case 'g':
if (argv[i][2]=='o'
&& argv[i][3]=='f'
&& argv[i][4]=='f') {
SysGateStartUp = 0;
} else if ( argv[i][2]=='o'
&& argv[i][3]=='n') {
SysGateStartUp = 1;
} else {
REASON_SET(reason, RC_CMD_SYNTAX, 0);
reason = Help(reason, appName);
}
break;
case 'v':
printf("%s\n", COREFREQ_VERSION);
reason.rc = RC_CMD_SYNTAX;
break;
case 'U': {
char trailing = '\0';
if (argv[++i] == NULL) {
REASON_SET(reason, RC_CMD_SYNTAX, 0);
reason = Help(reason, appName);
} else if (sscanf(argv[i], "%d%c",
&uid,
&trailing) != 1) {
REASON_SET(reason, RC_CMD_SYNTAX);
reason = Help(reason, appName);
}
}
break;
case 'G': {
char trailing = '\0';
if (argv[++i] == NULL) {
REASON_SET(reason, RC_CMD_SYNTAX, 0);
reason = Help(reason, appName);
} else if (sscanf(argv[i], "%d%c",
&gid,
&trailing) != 1) {
REASON_SET(reason, RC_CMD_SYNTAX);
reason = Help(reason, appName);
}
}
break;
case 'M': {
char trailing = '\0';
if (argv[++i] == NULL) {
REASON_SET(reason, RC_CMD_SYNTAX, 0);
reason = Help(reason, appName);
} else if (sscanf(argv[i] , "%o,%o%c",
&cmask[0],
&cmask[1],
&trailing) > 2) {
REASON_SET(reason, RC_CMD_SYNTAX);
reason = Help(reason, appName);
}
}
break;
case 'h':
default: {
REASON_SET(reason, RC_CMD_SYNTAX, 0);
reason = Help(reason, appName);
}
break;
}
} else {
REASON_SET(reason, RC_CMD_SYNTAX, 0);
reason = Help(reason, appName);
}
} else {
REASON_SET(reason, RC_CMD_SYNTAX, 0);
reason = Help(reason, appName);
}
}
if (reason.rc == RC_SUCCESS)
{
if (geteuid() == 0)
{
if ((fd.drv = open(DRV_FILENAME, O_RDWR|O_SYNC)) != -1)
{
const size_t packageSize[] = {
ROUND_TO_PAGES(sizeof(RO(PROC))),
ROUND_TO_PAGES(sizeof(RW(PROC)))
};
const off_t vm_pgoff[] = {
ID_RO_VMA_PROC * PAGE_SIZE,
ID_RW_VMA_PROC * PAGE_SIZE
};
if ((RO(Proc) = mmap(NULL, packageSize[0],
PROT_READ, MAP_SHARED,
fd.drv, vm_pgoff[0])) != MAP_FAILED)
{
if ((RW(Proc) = mmap(NULL, packageSize[1],
PROT_READ|PROT_WRITE, MAP_SHARED,
fd.drv, vm_pgoff[1])) != MAP_FAILED)
{
if (CHK_FOOTPRINT(RO(Proc)->FootPrint,MAX_FREQ_HZ,
CORE_COUNT,
TASK_ORDER,
COREFREQ_MAJOR,
COREFREQ_MINOR,
COREFREQ_REV))
{
reason = Shm_Manager( &fd, RO(Proc), RW(Proc),
uid, gid, cmask );
switch (reason.rc) {
case RC_SUCCESS:
case RC_OK_SYSGATE:
case RC_OK_COMPUTE:
case RC_DRIVER_BASE ... RC_DRIVER_LAST:
break;
case RC_CMD_SYNTAX:
case RC_PERM_ERR:
break;
case RC_SHM_FILE:
case RC_SHM_MMAP:
reason = Help(reason, RO(SHM_FILENAME));
break;
case RC_MEM_ERR:
case RC_EXEC_ERR:
reason = Help(reason, appName);
break;
case RC_SYS_CALL:
reason = Help(reason);
break;
}
} else {
char *wrongVersion = malloc(10+5+5+5+1);
REASON_SET(reason, RC_SHM_MMAP, EACCES);
if (wrongVersion != NULL) {
snprintf(wrongVersion, 10+5+5+5+1,
"Version %hu.%hu.%hu",
RO(Proc)->FootPrint.major,
RO(Proc)->FootPrint.minor,
RO(Proc)->FootPrint.rev);
reason = Help(reason, wrongVersion);
free(wrongVersion);
}
}
if (munmap(RW(Proc), packageSize[1]) == -1) {
REASON_SET(reason, RC_SHM_MMAP);
reason = Help(reason, DRV_FILENAME);
}
}
if (munmap(RO(Proc), packageSize[0]) == -1) {
REASON_SET(reason, RC_SHM_MMAP);
reason = Help(reason, DRV_FILENAME);
}
} else {
REASON_SET(reason, RC_SHM_MMAP);
reason = Help(reason, DRV_FILENAME);
}
if (close(fd.drv) == -1) {
REASON_SET(reason, RC_SHM_FILE);
reason = Help(reason, DRV_FILENAME);
}
} else {
REASON_SET(reason, RC_SHM_FILE);
reason = Help(reason, DRV_FILENAME);
}
} else {
REASON_SET(reason, RC_PERM_ERR, EACCES);
reason = Help(reason, appName);
}
}
if (program != NULL) {
free(program);
}
return reason.rc;
}