【x86架构】MTRR Dear 丶 2024-04-18 22:55 12阅读 0赞 ## MTRR是什么 ## MTRR的全称是Memory Type Range Registers。 它们是一组组的MSR寄存器对(目前最多有96组),用来指定特定的系统内存段的类型。 这里说的类型,是指**内存的CACHE类型**,有如下的值: ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppYW5nd2VpMDUxMg_size_16_color_FFFFFF_t_70][] 对应的C代码中的实现: // // Memory cache types // typedef enum { CacheUncacheable = 0, CacheWriteCombining = 1, CacheWriteThrough = 4, CacheWriteProtected = 5, CacheWriteBack = 6, CacheInvalid = 7 } MTRR_MEMORY_CACHE_TYPE; 通过MTRR,系统可以优化RAM/ROM/MMIO等不同类型的内存的访问速度。 下面是一个设置MTRR的例子: ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppYW5nd2VpMDUxMg_size_16_color_FFFFFF_t_70 1][] ## 如何判断MTRR的支持情况 ## 因为MTRR是MSR寄存器,因此它是跟CPU有关的,并不是所有的CPU都支持。 不过现在的x86平台CPU都支持该功能,事实上从P6型号开始就只是MTRR了。 要判断是否支持MTRR,需要使用CPUID命令,对应的是CPUID.EAX=01H,返回的结果在EDX: ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppYW5nd2VpMDUxMg_size_16_color_FFFFFF_t_70 2][] 当确定是否支持之后,还需要确定MTRR的支持情况,这对应于一个MSR寄存器(IA32\_MTRRCAP): ![20190913110655959.png][] 它是一个只读的寄存器,具体的BIT位说明如下: **SMRR**:确定是否支持System-Management Range Register; **FIX**:确定是否支持Fixed Range MTRR(两种类型的MTRR,可变和固定); **WC**:Write Combining的CACHE类型是否支持; **VCNT**:可变MTRR的支持个数。 这里没有说固定MTRR的个数,是否意味着它的个数是固定的?(目前来看是固定的11个,后面再介绍) 对应判断MTRR是否支持的代码如下: /** Checks if MTRR is supported. @retval TRUE MTRR is supported. @retval FALSE MTRR is not supported. **/ BOOLEAN EFIAPI IsMtrrSupported ( VOID ) { CPUID_VERSION_INFO_EDX Edx; MSR_IA32_MTRRCAP_REGISTER MtrrCap; // // Check CPUID(1).EDX[12] for MTRR capability // AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &Edx.Uint32); if (Edx.Bits.MTRR == 0) { return FALSE; } // // Check number of variable MTRRs and fixed MTRRs existence. // If number of variable MTRRs is zero, or fixed MTRRs do not // exist, return false. // MtrrCap.Uint64 = AsmReadMsr64 (MSR_IA32_MTRRCAP); if ((MtrrCap.Bits.VCNT == 0) || (MtrrCap.Bits.FIX == 0)) { return FALSE; } return TRUE; } ## MTRR的设置 ## 硬件复位之后,CPU会Disable掉所有的MTRR,此时所有的系统内存都是UNCACHEABLE的。 需要BIOS来完成MTRR,且在多处理器的系统中,各个处理器的设置必须是一致的。 MTRR的设置对应到3类寄存器,首先是一个全局的MSR(IA32\_MTRR\_DEF\_TYPE): ![20190913112203926.png][] **E**:MTRR的开关; **FE**:固定MTRR的开关; **Type**:系统内存的默认CACHE类型,对于没有被MTRR覆盖到的内存段,就使用默认的CACHE类型; 第二类是固定MTRR,因为它们对应的内存段是固定的,所以也比较好理解,下面是所有的固定MTRR: ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppYW5nd2VpMDUxMg_size_16_color_FFFFFF_t_70 3][] 每一个寄存器又将内存段分为8个小段,可以分别设置。 第三类是可变MTRR,它通过一组MSR寄存器来设置一段内存的属性,这组MSR如下所示: ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppYW5nd2VpMDUxMg_size_16_color_FFFFFF_t_70 4][] 第一个寄存器设定了内存的基址和类型,而第二个寄存器设置了它的大小以及使能与否。 这里还有一个概念,就是MAXPHYADDR,它表示的是最大支持的系统内存。 虽然我们说现在x86是64位的系统,但是CPU真正只是的系统内存却不是2^64,而是2^MAXPHYADDR,而这个MAXPHYADDR的大小不同系统有不同的值。关于这个值,可以通过CPUID.80000008H获取,下面是具体的代码: /** Initializes the valid bits mask and valid address mask for MTRRs. This function initializes the valid bits mask and valid address mask for MTRRs. @param[out] MtrrValidBitsMask The mask for the valid bit of the MTRR @param[out] MtrrValidAddressMask The valid address mask for the MTRR **/ VOID MtrrLibInitializeMtrrMask ( OUT UINT64 *MtrrValidBitsMask, OUT UINT64 *MtrrValidAddressMask ) { UINT32 MaxExtendedFunction; CPUID_VIR_PHY_ADDRESS_SIZE_EAX VirPhyAddressSize; AsmCpuid (CPUID_EXTENDED_FUNCTION, &MaxExtendedFunction, NULL, NULL, NULL); if (MaxExtendedFunction >= CPUID_VIR_PHY_ADDRESS_SIZE) { AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &VirPhyAddressSize.Uint32, NULL, NULL, NULL); } else { VirPhyAddressSize.Bits.PhysicalAddressBits = 36; } *MtrrValidBitsMask = LShiftU64 (1, VirPhyAddressSize.Bits.PhysicalAddressBits) - 1; *MtrrValidAddressMask = *MtrrValidBitsMask & 0xfffffffffffff000ULL; } 当MAXPHYADDR确定之后,基址的设置没有什么特别好介绍的,不过大小需要说明下。 一个可变MTRR可以存放的内存大小通过如下的方式计算: Address_Within_Range AND PhysMask = PhysBase AND PhysMask 其中Address\_Within\_Range就是可用的内存地址。 对应到代码如下: Mask = ((~(Length - 1)) & MtrrValidAddressMask) | BIT11; 其中的MtrrValidAddressMask是可用的地址的掩码(即MAXPHYADDR个1,前面的MtrrLibInitializeMtrrMask()有计算方式)。 ## MTRR查看 ## Linux下查看MTRR的方式: ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppYW5nd2VpMDUxMg_size_16_color_FFFFFF_t_70 5][] [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppYW5nd2VpMDUxMg_size_16_color_FFFFFF_t_70]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/18/11d36198bd5042108341a801c08369f3.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppYW5nd2VpMDUxMg_size_16_color_FFFFFF_t_70 1]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/18/e0c95610a8804889aa7bf4f67239e810.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppYW5nd2VpMDUxMg_size_16_color_FFFFFF_t_70 2]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/18/e0687acf57c649b894cee3090d4cc4d4.png [20190913110655959.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/18/4e46481ca396407fb8a24e1bb075b05c.png [20190913112203926.png]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/18/bd89b3fc201f4e8f8b78628ebb1d7390.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppYW5nd2VpMDUxMg_size_16_color_FFFFFF_t_70 3]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/18/5c5aec164154412b978810c39997ac0a.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppYW5nd2VpMDUxMg_size_16_color_FFFFFF_t_70 4]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/18/226ae33dceff4b8d8dc1f2896cbaa1af.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2ppYW5nd2VpMDUxMg_size_16_color_FFFFFF_t_70 5]: https://image.dandelioncloud.cn/pgy_files/images/2024/04/18/99afafaa9b6b4c55a7e20e7370cbc0ea.png
还没有评论,来说两句吧...