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
signature.asc
Description: This is a digitally signed message part
-- coreboot mailing list: [email protected] http://www.coreboot.org/mailman/listinfo/coreboot

