Am Dienstag, den 14.05.2013, 11:03 +0200 schrieb Paul Menzel:
> Am Montag, den 13.05.2013, 09:04 +0200 schrieb Paul Menzel:
> > 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.
> 
> It looks like it is not the same. The BIOS Timer above is more to fit
> Aaron’s commit.
> 
>         commit c46cc6f149c42653344d6e9f3656a4212fc46cef
>         Author: Aaron Durbin <[email protected]>
>         Date:   Mon Apr 29 16:57:10 2013 -0500
> 
>             haswell: 24MHz monotonic time implementation
> 
>             Haswell ULT devices have a 24MHz package-level counter. Use
>             this counter to provide a timer_monotonic_get()
>         implementation.
> 
>             Reviewed-on: http://review.coreboot.org/3153
> 
> But the problem is, that the register is part of the PCI config space(?)
> and the Root Complex/PCI stuff is not yet available in ramstage?
> 
>         +#include <stdint.h>
>         +#include <pci_ops.h>
>         +#include <timer.h>
>         +
>         +static struct monotonic_counter {
>         +       int initialized;
>         +       struct mono_time time;
>         +       uint32_t last_value;
>         +} mono_counter;
>         +
>         +static inline uint32_t read_counter_msr(void)
>         +{
>         +       /* D0F0xE4_x0130_80F0 BIOS Timer
>         +        *
>         +        * This field increments once every microsecond when the 
> timer is
>         +        * enabled. The counter rolls over and continues counting 
> when it
>         +        * reaches FFFF_FFFFh. A write to this register causes the 
> counter
>         +        * to reset and begin counting from the value written. */
>         +       pci_write_config32(CI_DEV(0, 0, 0), 0xe4, 0x013080F0);

The above was supposed to be `PCI_DEV`. I had not squashed the commits
yet.

>         +
>         +       return pci_read_config32(PCI_DEV(0, 0, 0), 0xe4);
>         +}
>         +
>         +void timer_monotonic_get(struct mono_time *mt)
>         +{
>         +       uint32_t current_tick;
>         +       uint32_t usecs_elapsed;
>         +
>         +       if (!mono_counter.initialized) {
>         +               mono_counter.last_value = read_counter_msr();
>         +               mono_counter.initialized = 1;
>         +       }
>         +
>         +       current_tick = read_counter_msr();
>         +       usecs_elapsed = current_tick - mono_counter.last_value;
>         +
>         +       /* Update current time and tick values only if a full tick 
> occurred. */
>         +       if (usecs_elapsed) {
>         +               mono_time_add_usecs(&mono_counter.time, 
> usecs_elapsed);
>         +               mono_counter.last_value = current_tick;
>         +       }
>         +
>         +       /* Save result. */
>         +       *mt = mono_counter.time;
>         +}
> 
> This results in the following hang.
> 
>         00.000: <00>
>         00.456: 
>         00.456: 
>         00.456: coreboot-4.0-4160-g41f456b-dirty Tue May 14 00:28:53 CEST 
> 2013 starting...
>         00.456: BSP Family_Model: 00500f10 
>         00.457: cpu_init_detectedx = 00000000 
>         00.457: agesawrapper_amdinitmmio passed.
>         00.458: agesawrapper_amdinitreset passed.
>         00.461: agesawrapper_amdinitearly BSP Family_Model: 00500f10 
>         00.486: cpu_init_detectedx = 00000001 
>         00.486: agesawrapper_amdinitmmio passed.
>         00.487: agesawrapper_amdinitreset passed.
>         00.491: agesawrapper_amdinitearly passed.
>         00.627: agesawrapper_amdinitpost passed.
>         00.753: agesawrapper_amdinitenv passed.
>         00.767: Loading image.
>         00.768: CBFS: loading stage fallback/coreboot_ram @ 0x200000 (1343544 
> bytes), entry @ 0x200000
>         00.873: Jumping to image.
>         00.874: coreboot-4.0-4160-g41f456b-dirty Tue May 14 00:28:53 CEST 
> 2013 booting...
>         00.874: get_pbus: dev is NULL!

In #coreboor, CareBear\ suggested that I have to access the PCI register
in a different way. Suggestions very much welcomed.

> > > > 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?
> 
> There are also other timers in the processor cores.
> 
>         2.4.5 Timers
> 
>         Each core includes the following timers. These timers do not
>         vary in frequency regardless of the current P-state or C-state.
>         • MSR0000_0010 [Time Stamp Counter (TSC)]; the TSC increments at
>         the rate specified by MSRC001_0015[TscFreqSel].
>         • The APIC timer (APIC380 and APIC390), which decrements at a
>         rate of 2x CLKIN.
> 
> It looks like that is what AGESA uses and which might be there from the
> “beginning”.


Thanks,

Paul

Attachment: signature.asc
Description: This is a digitally signed message part

-- 
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to