[settings] Expose CPUID instruction via settings mechanism

Allow CPUID values to be read using the syntax

  ${cpuid/<register>.<function>}

For example, ${cpuid/2.0x80000001} will give the value of %ecx after
calling CPUID with %eax=0x80000001.  Values for <register> are encoded
as %eax=0, %ebx=1, %ecx=2, %edx=3.

The numeric encoding is more sophisticated than described above,
allowing for settings such as the CPU model (obtained by calling CPUID
with %eax=0x80000002-0x80000004 inclusive and concatenating the values
returned in %eax:%ebx:%ecx:%edx).  See the source code for details.

The "cpuvendor" and "cpumodel" settings provide easy access to these
more complex CPUID settings.

This functionality is intended to complement the "cpuid" command,
which allows for testing individual CPUID feature bits.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown
2013-08-06 19:16:30 +01:00
parent 53c01d6444
commit 55201e2d0e
6 changed files with 303 additions and 19 deletions

View File

@@ -46,6 +46,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define ERRFILE_timer_bios ( ERRFILE_ARCH | ERRFILE_DRIVER | 0x00010000 )
#define ERRFILE_cpuid_cmd ( ERRFILE_ARCH | ERRFILE_OTHER | 0x00000000 )
#define ERRFILE_cpuid_settings ( ERRFILE_ARCH | ERRFILE_OTHER | 0x00010000 )
/** @} */

View File

@@ -30,6 +30,9 @@ struct x86_features {
/** CPUID support flag */
#define CPUID_FLAG 0x00200000UL
/** CPUID extended function */
#define CPUID_EXTENDED 0x80000000UL
/** Get vendor ID and largest standard function */
#define CPUID_VENDOR_ID 0x00000000UL
@@ -48,6 +51,28 @@ struct x86_features {
/** Get extended features */
#define CPUID_AMD_FEATURES 0x80000001UL
/** Get CPU model */
#define CPUID_MODEL 0x80000002UL
/**
* Issue CPUID instruction
*
* @v operation CPUID operation
* @v eax Output via %eax
* @v ebx Output via %ebx
* @v ecx Output via %ecx
* @v edx Output via %edx
*/
static inline __attribute__ (( always_inline )) void
cpuid ( uint32_t operation, uint32_t *eax, uint32_t *ebx, uint32_t *ecx,
uint32_t *edx ) {
__asm__ ( "cpuid"
: "=a" ( *eax ), "=b" ( *ebx ), "=c" ( *ecx ), "=d" ( *edx )
: "0" ( operation ) );
}
extern int cpuid_is_supported ( void );
extern void x86_features ( struct x86_features *features );
#endif /* _IPXE_CPUID_H */