1 /** @file
2   X2Apic feature.
3 
4   Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
5   SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include "CpuCommonFeatures.h"
10 
11 /**
12   Prepares for the data used by CPU feature detection and initialization.
13 
14   @param[in]  NumberOfProcessors  The number of CPUs in the platform.
15 
16   @return  Pointer to a buffer of CPU related configuration data.
17 
18   @note This service could be called by BSP only.
19 **/
20 VOID *
21 EFIAPI
X2ApicGetConfigData(IN UINTN NumberOfProcessors)22 X2ApicGetConfigData (
23   IN UINTN  NumberOfProcessors
24   )
25 {
26   BOOLEAN                            *ConfigData;
27 
28   ConfigData = AllocateZeroPool (sizeof (BOOLEAN) * NumberOfProcessors);
29   ASSERT (ConfigData != NULL);
30   return ConfigData;
31 }
32 
33 /**
34   Detects if X2Apci feature supported on current processor.
35 
36   Detect if X2Apci has been already enabled.
37 
38   @param[in]  ProcessorNumber  The index of the CPU executing this function.
39   @param[in]  CpuInfo          A pointer to the REGISTER_CPU_FEATURE_INFORMATION
40                                structure for the CPU executing this function.
41   @param[in]  ConfigData       A pointer to the configuration buffer returned
42                                by CPU_FEATURE_GET_CONFIG_DATA.  NULL if
43                                CPU_FEATURE_GET_CONFIG_DATA was not provided in
44                                RegisterCpuFeature().
45 
46   @retval TRUE     X2Apci feature is supported.
47   @retval FALSE    X2Apci feature is not supported.
48 
49   @note This service could be called by BSP/APs.
50 **/
51 BOOLEAN
52 EFIAPI
X2ApicSupport(IN UINTN ProcessorNumber,IN REGISTER_CPU_FEATURE_INFORMATION * CpuInfo,IN VOID * ConfigData OPTIONAL)53 X2ApicSupport (
54   IN UINTN                             ProcessorNumber,
55   IN REGISTER_CPU_FEATURE_INFORMATION  *CpuInfo,
56   IN VOID                              *ConfigData  OPTIONAL
57   )
58 {
59   BOOLEAN                            *X2ApicEnabled;
60 
61   ASSERT (ConfigData != NULL);
62   X2ApicEnabled = (BOOLEAN *) ConfigData;
63   //
64   // *ConfigData indicates if X2APIC enabled on current processor
65   //
66   X2ApicEnabled[ProcessorNumber] = (GetApicMode () == LOCAL_APIC_MODE_X2APIC) ? TRUE : FALSE;
67 
68   return (CpuInfo->CpuIdVersionInfoEcx.Bits.x2APIC == 1);
69 }
70 
71 /**
72   Initializes X2Apci feature to specific state.
73 
74   @param[in]  ProcessorNumber  The index of the CPU executing this function.
75   @param[in]  CpuInfo          A pointer to the REGISTER_CPU_FEATURE_INFORMATION
76                                structure for the CPU executing this function.
77   @param[in]  ConfigData       A pointer to the configuration buffer returned
78                                by CPU_FEATURE_GET_CONFIG_DATA.  NULL if
79                                CPU_FEATURE_GET_CONFIG_DATA was not provided in
80                                RegisterCpuFeature().
81   @param[in]  State            If TRUE, then the X2Apci feature must be enabled.
82                                If FALSE, then the X2Apci feature must be disabled.
83 
84   @retval RETURN_SUCCESS       X2Apci feature is initialized.
85 
86   @note This service could be called by BSP only.
87 **/
88 RETURN_STATUS
89 EFIAPI
X2ApicInitialize(IN UINTN ProcessorNumber,IN REGISTER_CPU_FEATURE_INFORMATION * CpuInfo,IN VOID * ConfigData,OPTIONAL IN BOOLEAN State)90 X2ApicInitialize (
91   IN UINTN                             ProcessorNumber,
92   IN REGISTER_CPU_FEATURE_INFORMATION  *CpuInfo,
93   IN VOID                              *ConfigData,  OPTIONAL
94   IN BOOLEAN                           State
95   )
96 {
97   BOOLEAN                            *X2ApicEnabled;
98 
99   //
100   // The scope of the MSR_IA32_APIC_BASE is core for below processor type, only program
101   // MSR_IA32_APIC_BASE for thread 0 in each core.
102   //
103   if (IS_SILVERMONT_PROCESSOR (CpuInfo->DisplayFamily, CpuInfo->DisplayModel)) {
104     if (CpuInfo->ProcessorInfo.Location.Thread != 0) {
105       return RETURN_SUCCESS;
106     }
107   }
108 
109   ASSERT (ConfigData != NULL);
110   X2ApicEnabled = (BOOLEAN *) ConfigData;
111   if (X2ApicEnabled[ProcessorNumber]) {
112     PRE_SMM_CPU_REGISTER_TABLE_WRITE_FIELD (
113       ProcessorNumber,
114       Msr,
115       MSR_IA32_APIC_BASE,
116       MSR_IA32_APIC_BASE_REGISTER,
117       Bits.EXTD,
118       1
119       );
120   } else {
121     //
122     // Enable X2APIC mode only if X2APIC is not enabled,
123     // Needn't to disabe X2APIC mode again if X2APIC is not enabled
124     //
125     if (State) {
126       CPU_REGISTER_TABLE_WRITE_FIELD (
127         ProcessorNumber,
128         Msr,
129         MSR_IA32_APIC_BASE,
130         MSR_IA32_APIC_BASE_REGISTER,
131         Bits.EXTD,
132         1
133         );
134     }
135   }
136   return RETURN_SUCCESS;
137 }
138