[coreboot] Use the constant TSC for AMD Family 10h–15h processors?

Paul Menzel paulepanter at users.sourceforge.net
Mon May 13 09:04:46 CEST 2013


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
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: This is a digitally signed message part
URL: <http://www.coreboot.org/pipermail/coreboot/attachments/20130513/7fad391c/attachment.sig>


More information about the coreboot mailing list