Am Sonntag, den 12.05.2013, 15:40 +0200 schrieb Peter Stuge:
Paul Menzel wrote:
do you know if the timer mentioned in the BIOS and Kernel Developer’s Guide (BKGD) for the AMD Family 14h processors [1]
2.11.4 BIOS Timer The root complex implements a 32-bit microsecond timer (see D0F0xE4_x0130_80F0 and D0F0xE4_x0130_80F1) that the BIOS can use to accurately time wait operations between initialization steps. To ensure that BIOS waits a minimum number of microseconds between steps BIOS should always wait for one microsecond more than the required minimum wait time.
could be used for implementing `tsc_freq_mhz()` as done for Intel Haswell processors?
Isn't that quite clear from the text that you quoted?
Probably, yes. As this area is new to me, I prefer to ask and get confirmation to be sure.
Suggestions, if this should be shared and how the files should be named are appreciated.
Yes and no. We can do this for coreboot's own code for AMD platforms, but it obviously does not make much sense to hack this into AGESA if there are not already provisions for it.
I totally forgot about that. There is coreboot code for the K8 and Family 10h processors, if I am not mistaken.
AGESA is there for Family 10h to 15h processors.
Since AGESA is the only thing relevant going forward the question is what AGESA needs, timing-wise. Have you checked?
Only a little. Having an ASRock E350M1, I am looking into the Family 14h family. There seems to be no TSC stuff in `src/cpu/amd`. But the AMD vendor code seems to have it.
$ git grep -i tsc src/vendorcode/amd/agesa/f14/
`AGESA.h` has a struct `MEM_DATA_STRUCT` where the frequency is put into.
$ nl -ba src/vendorcode/amd/agesa/f14/AGESA.h | grep -B 40 -A 5 TSC […] 1700 /// 1701 /// Contains all data relevant to Memory Initialization. 1702 /// 1703 typedef struct _MEM_DATA_STRUCT { 1704 IN AMD_CONFIG_PARAMS StdHeader; ///< Standard configuration header 1705 1706 IN MEM_PARAMETER_STRUCT *ParameterListPtr; ///< List of input Parameters 1707 1708 OUT MEM_FUNCTION_STRUCT FunctionList; ///< List of function Pointers 1709 1710 IN OUT AGESA_STATUS (*GetPlatformCfg[MAX_PLATFORM_TYPES]) (struct _MEM_DATA_STRUCT *MemData, UINT8 SocketID, CH_DEF_STRUCT *CurrentChannel); ///< look-up platform info 1711 1712 IN OUT BOOLEAN (*ErrorHandling)(struct _DIE_STRUCT *MCTPtr, UINT8 DCT, UINT16 ChipSelMask, AMD_CONFIG_PARAMS *StdHeader); ///< Error Handling 1713 1714 1715 OUT MEM_SOCKET_STRUCT SocketList[MAX_SOCKETS_SUPPORTED]; ///< Socket list for memory code. 1716 ///< SocketList is a shortcut for IBVs to retrieve training 1717 ///< and timing data for each channel indexed by socket/channel, 1718 ///< eliminating their need to parse die/dct/channel etc. 1719 ///< It contains pointers to the populated data structures for 1720 ///< each channel and skips the channel structures that are 1721 ///< unpopulated. In the case of channels sharing the same DCT, 1722 ///< the pTimings pointers will point to the same DCT Timing data. 1723 1724 OUT DIE_STRUCT *DiesPerSystem; ///< Pointed to an array of DIE_STRUCTs 1725 OUT UINT8 DieCount; ///< Number of MCTs in the system. 1726 1727 IN SPD_DEF_STRUCT *SpdDataStructure; ///< Pointer to SPD Data structure 1728 1729 IN OUT struct _PLATFORM_CONFIGURATION *PlatFormConfig; ///< Platform profile/build option config structure 1730 1731 IN OUT BOOLEAN IsFlowControlSupported; ///< Indicates if flow control is supported 1732 1733 OUT UINT32 TscRate; ///< The rate at which the TSC increments in megahertz. 1734 1735 } MEM_DATA_STRUCT; […]
With
$ git grep -i tsc src/vendorcode/amd/agesa/f14/ | grep -i rate […] src/vendorcode/amd/agesa/f14/Proc/CPU/Family/0x14/cpuF14Utilities.c: * @CpuServiceMethod{::F_CPU_GET_TSC_RATE}. src/vendorcode/amd/agesa/f14/Proc/CPU/Family/0x14/cpuF14Utilities.c:F14GetTscRate ( src/vendorcode/amd/agesa/f14/Proc/CPU/Family/0x14/cpuF14Utilities.h:F14GetTscRate ( […]
I found `F14GetTscRate`.
$ nl -ba src/vendorcode/amd/agesa/f14/Proc/CPU/Family/0x14/cpuF14Utilities.c […] 213 /*---------------------------------------------------------------------------------------*/ 214 /** 215 * Determines the rate at which the executing core's time stamp counter is 216 * incrementing. 217 * 218 * @CpuServiceMethod{::F_CPU_GET_TSC_RATE}. 219 * 220 * @param[in] FamilySpecificServices The current Family Specific Services. 221 * @param[out] FrequencyInMHz TSC actual frequency. 222 * @param[in] StdHeader Header for library and services. 223 * 224 * @return The most severe status of all called services 225 */ 226 AGESA_STATUS 227 F14GetTscRate ( 228 IN CPU_SPECIFIC_SERVICES *FamilySpecificServices, 229 OUT UINT32 *FrequencyInMHz, 230 IN AMD_CONFIG_PARAMS *StdHeader 231 ) 232 { 233 UINT64 MsrReg; 234 PSTATE_CPU_FAMILY_SERVICES *FamilyServices; 235 236 FamilyServices = NULL; 237 GetFeatureServicesOfCurrentCore (&PstateFamilyServiceTable, (const VOID **)&FamilyServices, StdHeader); 238 ASSERT (FamilyServices != NULL); 239 240 LibAmdMsrRead (0xC0010015, &MsrReg, StdHeader); 241 if ((MsrReg & 0x01000000) != 0) { 242 return (FamilyServices->GetPstateFrequency (FamilyServices, 0, FrequencyInMHz, StdHeader)); 243 } else { 244 return (FamilySpecificServices->GetCurrentNbFrequency (FamilySpecificServices, FrequencyInMHz, StdHeader)); 245 } 246 } […]
So there is the infrastructure already. The only problem is how to hook this up into coreboot. Create `src/cpu/amd/agesa/tsc_delay.c` and somehow call the AGESA `F14GetTscRate()` from it?
Thanks,
Paul