]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[cpuid] Allow hypervisor CPUID leaves to be accessed as settings
authorMichael Brown <mcb30@ipxe.org>
Wed, 31 Jul 2024 15:43:27 +0000 (16:43 +0100)
committerMichael Brown <mcb30@ipxe.org>
Thu, 1 Aug 2024 11:54:49 +0000 (12:54 +0100)
Redefine bit 30 of an SMBIOS numerical setting to be part of the
function number, in order to allow access to hypervisor CPUID leaves.

This technically breaks backwards compatibility with scripts
attempting to read more than 64 consecutive functions.  Since there is
no meaningful block of 64 consecutive related functions, it is
vanishingly unlikely that this capability has ever been used.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/arch/x86/core/cpuid_settings.c

index 0b67ee91dba244d12fd1068e13669e1733f04f66..9bc69f47771e400710649da73e507dd680a8f543 100644 (file)
@@ -38,7 +38,8 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
  *
  *  Bit  31    Extended function
  *  Bits 30-24 (bit 22 = 1) Subfunction number
- *             (bit 22 = 0) Number of consecutive functions to call, minus one
+ *  Bit  30    (bit 22 = 0) Hypervisor function
+ *  Bits 29-24 (bit 22 = 0) Number of consecutive functions to call, minus one
  *  Bit  23    Return result as little-endian (used for strings)
  *  Bit  22    Interpret bits 30-24 as a subfunction number
  *  Bits 21-18 Unused
@@ -98,7 +99,7 @@ enum cpuid_flags {
  * @v tag              Setting tag
  * @ret function       Starting function number
  */
-#define CPUID_FUNCTION( tag ) ( (tag) & 0x800000ffUL )
+#define CPUID_FUNCTION( tag ) ( (tag) & 0xc00000ffUL )
 
 /**
  * Extract subfunction number from CPUID setting tag
@@ -108,6 +109,14 @@ enum cpuid_flags {
  */
 #define CPUID_SUBFUNCTION( tag ) ( ( (tag) >> 24 ) & 0x7f )
 
+/**
+ * Extract number of consecutive functions from CPUID setting tag
+ *
+ * @v tag              Setting tag
+ * @ret num_functions  Number of consecutive functions
+ */
+#define CPUID_NUM_FUNCTIONS( tag ) ( ( ( (tag) >> 24 ) & 0x3f ) + 1 )
+
 /**
  * Extract register array from CPUID setting tag
  *
@@ -165,12 +174,13 @@ static int cpuid_settings_fetch ( struct settings *settings,
 
        /* Call each function in turn */
        function = CPUID_FUNCTION ( setting->tag );
-       subfunction = CPUID_SUBFUNCTION ( setting->tag );
        if ( setting->tag & CPUID_USE_SUBFUNCTION ) {
+               function &= ~CPUID_HYPERVISOR;
+               subfunction = CPUID_SUBFUNCTION ( setting->tag );
                num_functions = 1;
        } else {
-               num_functions = ( subfunction + 1 );
                subfunction = 0;
+               num_functions = CPUID_NUM_FUNCTIONS ( setting->tag );
        }
        for ( ; num_functions-- ; function++ ) {