summaryrefslogtreecommitdiff
path: root/BraswellPlatformPkg/Common/Silicon/IntelSiliconBasic/PiSmmCpuDxeSmm/SmmFeatures.c
blob: 2441d7e7a0627d884b974659a8824dbf87eaa967 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
/** @file
  The CPU specific programming for PiSmmCpuDxeSmm module, such as SMRR, EMRR, IED.
  Currently below CPUs are supported.

  Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>

  This program and the accompanying materials
  are licensed and made available under the terms and conditions of the BSD License
  which accompanies this distribution.  The full text of the license may be found at
  http://opensource.org/licenses/bsd-license.php.

  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.

**/

#include <Base.h>

#include <Library/PcdLib.h>
#include <Library/BaseLib.h>
#include <Library/CpuLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/PciLib.h>
#include <Library/LocalApicLib.h>

#include "PiSmmCpuDxeSmm.h"
#include "SmmFeatures.h"

//
// The CPUID mapping for CherryView
//

CPUID_MAPPING mCherryViewMap[] = {
  {CPUID_SIGNATURE_CHERRYVIEW, CPUID_MASK_NO_STEPPING},
};

//
// The CLASS for CherryView
//
CPU_SMM_CLASS mCherryViewClass = {
  CpuCherryView,
  sizeof(mCherryViewMap)/sizeof(mCherryViewMap[0]),
  mCherryViewMap,
  };

//
// This table defines supported CPU class
//
CPU_SMM_CLASS *mCpuClasstable[] = {
  &mCherryViewClass
  };

////////
// Below section is common definition
////////

//
// Assumes UP, or MP with identical feature set
//
CPU_SMM_FEATURE_CONTEXT  mFeatureContext;

CPU_SMM_CLASS            *mThisCpu;
BOOLEAN                  mSmmCodeAccessCheckEnable = FALSE;
BOOLEAN                  mSmmUseDelayIndication;
BOOLEAN                  mSmmUseBlockIndication;

/**
  Return if SMRR is supported

  @retval TRUE  SMRR is supported.
  @retval FALSE SMRR is not supported.

**/
BOOLEAN
IsSmrrSupported (
  VOID
  )
{
  UINT64                            MtrrCap;

  MtrrCap = AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP);
  if ((MtrrCap & IA32_MTRR_SMRR_SUPPORT_BIT) == 0) {
    return FALSE;
  } else {
    return TRUE;
  }
}

/**
  Initialize SMRR in SMM relocate.

  @param  SmrrBase           The base address of SMRR.
  @param  SmrrSize           The size of SMRR.
**/
VOID
InitSmrr (
  IN UINT32                SmrrBase,
  IN UINT32                SmrrSize
  )
{
  AsmWriteMsr64 (EFI_MSR_SMRR_PHYS_BASE, SmrrBase| CACHE_WRITE_BACK);
  AsmWriteMsr64 (EFI_MSR_SMRR_PHYS_MASK, (~(SmrrSize - 1) & EFI_MSR_SMRR_MASK)); // Valid bit will be set in ConfigSmrr() at first SMI
}

/**
  Configure SMRR register at each SMM entry.
**/
VOID
ConfigSmrr (
  VOID
  )
{
  UINT64 SmrrMask;

  SmrrMask = AsmReadMsr64 (EFI_MSR_SMRR_PHYS_MASK);
  if ((SmrrMask & EFI_MSR_SMRR_PHYS_MASK_VALID) == 0) {
    AsmWriteMsr64(EFI_MSR_SMRR_PHYS_MASK, SmrrMask | EFI_MSR_SMRR_PHYS_MASK_VALID);
  }
}

////////
// Below section is definition for the supported class
////////

/**
  This function will return current CPU_SMM_CLASS accroding to CPUID mapping.

  @return The point to current CPU_SMM_CLASS

**/
CPU_SMM_CLASS *
GetCpuFamily (
  VOID
  )
{
  UINT32         ClassIndex;
  UINT32         Index;
  UINT32         Count;
  CPUID_MAPPING  *CpuMapping;
  UINT32         RegEax;

  AsmCpuid (EFI_CPUID_VERSION_INFO, &RegEax, NULL, NULL, NULL);
  for (ClassIndex = 0; ClassIndex < sizeof(mCpuClasstable)/sizeof(mCpuClasstable[0]); ClassIndex++) {
    CpuMapping = mCpuClasstable[ClassIndex]->MappingTable;
    Count = mCpuClasstable[ClassIndex]->MappingCount;
    for (Index = 0; Index < Count; Index++) {
      if ((CpuMapping[Index].Signature & CpuMapping[Index].Mask) == (RegEax & CpuMapping[Index].Mask)) {
        return mCpuClasstable[ClassIndex];
      }
    }
  }

  // Not found!!! Should not happen
  ASSERT (FALSE);
  return NULL;
}

////////
// Below section is external function
////////
/**
  Read MSR or CSR based on the CPU type Register to read.

  NOTE: Since platform may uses I/O ports 0xCF8 and 0xCFC to access
        CSR, we need to use SPIN_LOCK to avoid collision on MP System.

  @param[in]  CpuIndex  The processor index.
  @param[in]  RegName   Register name.

  @return 64-bit value read from register.

**/
UINT64
SmmReadReg64 (
  IN  UINTN           CpuIndex,
  IN  SMM_REG_NAME    RegName
  )
{
  UINT64      RetVal;

  RetVal = 0;
    switch (RegName) {
    //
    // Client uses MSR
    //
    case  SmmRegFeatureControl:
      RetVal = AsmReadMsr64 (EFI_MSR_HASWELL_SMM_FEATURE_CONTROL);
      break;
    case  SmmRegSmmDelayed:
      RetVal = AsmReadMsr64 (EFI_MSR_HASWELL_SMM_DELAYED);
      break;
    case  SmmRegSmmBlocked:
      RetVal = AsmReadMsr64 (EFI_MSR_HASWELL_SMM_BLOCKED);
      break;
    default:
      ASSERT (FALSE);
    }
  return  RetVal;
}

/**
  Write MSR or CSR based on the CPU type Register to write.

  NOTE: Since platform may uses I/O ports 0xCF8 and 0xCFC to access
        CSR, we need to use SPIN_LOCK to avoid collision on MP System.

  @param[in]  CpuIndex  The processor index.
  @param[in]  RegName   Register name.
  @param[in]  RegValue  64-bit Register value.

**/
VOID
SmmWriteReg64 (
  IN  UINTN           CpuIndex,
  IN  SMM_REG_NAME    RegName,
  IN  UINT64          RegValue
  )
{
    switch (RegName) {
    //
    // Client uses MSR
    //
    case  SmmRegFeatureControl:
      AsmWriteMsr64 (EFI_MSR_HASWELL_SMM_FEATURE_CONTROL, RegValue);
      break;
    default:
      ASSERT (FALSE);
    }
}

/**
  This function will return logical processor index in package.

  @param[in]  ProcessorNumber        The processor number.
  @param[out] LogProcIndexPackage    The logical processor index.

  @retval EFI_NOT_FOUND Cannot find the specified processor by ProcessorNumber.
  @retval EFI_SUCCESS   Logical processor index return in LogProcIndexPackage.

**/
EFI_STATUS
GetLogProcIndexInPackage (
  IN  UINTN   ProcessorNumber,
  OUT UINT16  *LogProcIndexPackage
  )
{
  UINT64      ProcessorId;
  UINT32      PackageId;
  UINTN       Index;
  UINT16      LogProcIndex;

  ProcessorId  = gSmmCpuPrivate->ProcessorInfo[ProcessorNumber].ProcessorId;
  if (ProcessorId == INVALID_APIC_ID) {
    return EFI_NOT_FOUND;
  }

  PackageId    = gSmmCpuPrivate->ProcessorInfo[ProcessorNumber].Location.Package;
  LogProcIndex = 0;
  for (Index = 0; Index < mMaxNumberOfCpus; Index++) {
    if (gSmmCpuPrivate->ProcessorInfo[Index].Location.Package == PackageId) {
      if (gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId < ProcessorId) {
        //
        // The logical processor number in the same packet
        //
        LogProcIndex++;
      }
    }
  }

  *LogProcIndexPackage = LogProcIndex;
  return  EFI_SUCCESS;
}

/**
  Return if it is needed to configure MTRR to set TSEG cacheability.

  @retval  TRUE  - we need configure MTRR
  @retval  FALSE - we do not need configure MTRR
**/
BOOLEAN
NeedConfigureMtrrs (
  VOID
  )
{
  ASSERT (mThisCpu != NULL);

  switch (mThisCpu->Family) {
  case CpuCherryView:
    return FALSE;
  default:
    return TRUE;
  }
}

/**
  Processor specific hook point at each SMM entry.

  @param  CpuIndex    The index of the cpu which need to check.

**/
VOID
SmmRendezvousEntry (
  IN UINTN  CpuIndex
  )
{

  ASSERT (mThisCpu != NULL);

  switch (mThisCpu->Family) {
  case CpuCherryView:
    if (mFeatureContext.SmrrEnabled) {
      ConfigSmrr ();
    }
    return;
  default:
    return ;
  }
}

/**
  Processor specific hook point at each SMM exit.

  @param  CpuIndex    The index of the cpu which need to check.
**/
VOID
SmmRendezvousExit (
  IN UINTN  CpuIndex
  )
{

  ASSERT (mThisCpu != NULL);

  switch (mThisCpu->Family) {
  case CpuCherryView:
  default:
    return ;
  }
}

/**
  Initialize SMRR context in SMM Init.
**/
VOID
InitializeSmmMtrrManager (
  VOID
  )
{
  mThisCpu = GetCpuFamily ();
  ASSERT (mThisCpu != NULL);

  switch (mThisCpu->Family) {
  case CpuCherryView:
    if (!IsSmrrSupported ()) {
      return ;
    }
    mFeatureContext.SmrrEnabled = TRUE;
    return ;
  default:
    return ;
  }
}

/**
  Initialize SMRR/SMBASE/SMM Sync features in SMM Relocate.

  @param  ProcessorNumber    The processor number
  @param  SmrrBase           The base address of SMRR.
  @param  SmrrSize           The size of SMRR.
  @param  SmBase             The SMBASE value.
  @param  IsBsp              If this processor treated as BSP.
**/
VOID
SmmInitiFeatures (
  IN UINTN   ProcessorNumber,
  IN UINT32  SmrrBase,
  IN UINT32  SmrrSize,
  IN UINT32  SmBase,
  IN BOOLEAN IsBsp
  )
{
  SOCKET_LGA_775_SMM_CPU_STATE      *CpuState;
  SMM_CPU_SYNC_FEATURE              *SyncFeature;

  SyncFeature = &(gSmmCpuPrivate->SmmSyncFeature[ProcessorNumber]);
  SyncFeature->DelayIndicationSupported = FALSE;
  SyncFeature->BlockIndicationSupported = FALSE;
  SyncFeature->HaswellLogProcEnBit = (UINT64)(INT64)(-1);

  mThisCpu = GetCpuFamily ();
  ASSERT (mThisCpu != NULL);

  //
  // Configure SMBASE.
  //
  switch (mThisCpu->Family) {
  case CpuCherryView:
    //
    // Fall back to legacy SMBASE setup.
    //
    CpuState = (SOCKET_LGA_775_SMM_CPU_STATE *)(UINTN)(SMM_DEFAULT_SMBASE + SMM_CPU_STATE_OFFSET);
    CpuState->x86.SMBASE = SmBase;
    break ;
  default:
    return ;
  }

  switch (mThisCpu->Family) {
  case CpuCherryView:
    if (IsSmrrSupported ()) {
      InitSmrr (SmrrBase, SmrrSize);
    }
    return ;
  default:
    ASSERT (FALSE);
    return ;
  }
}

/**
  Configure SMM Code Access Check feature on an AP.
  SMM Feature Control MSR will be locked after configuration.

  @param[in,out] Buffer  Pointer to private data buffer.
**/
VOID
EFIAPI
ConfigSmmCodeAccessCheckOnCurrentProcessor (
  IN OUT VOID  *Buffer
  )
{
  UINT64 SmmFeatureControlMsr;
  UINTN  CpuIndex;

  CpuIndex = *(UINTN *)Buffer;

  SmmFeatureControlMsr = SmmReadReg64 (CpuIndex, SmmRegFeatureControl);
  //
  // The SMM Feature Control MSR is package scope. If lock bit is set, don't set it again.
  //
  if ((SmmFeatureControlMsr & SMM_FEATURE_CONTROL_LOCK_BIT) == 0) {
    if (mSmmCodeAccessCheckEnable) {
      SmmFeatureControlMsr |= SMM_CODE_CHK_EN_BIT;
    }
    if (FeaturePcdGet (PcdCpuSmmFeatureControlMsrLock)) {
      SmmFeatureControlMsr |=SMM_FEATURE_CONTROL_LOCK_BIT;
    }
    SmmWriteReg64 (CpuIndex, SmmRegFeatureControl, SmmFeatureControlMsr);
  }
}

/**
  Configure SMM Code Access Check feature for all processors.
  SMM Feature Control MSR will be locked after configuration.
**/
VOID
ConfigSmmCodeAccessCheck (
  VOID
  )
{
  UINTN      Index;
  EFI_STATUS Status;

  //
  // SMM Code Access Check feature is supported since Haswell.
  //
  if (FALSE /*mThisCpu->Family == CpuHaswell*/) {
    if ((AsmReadMsr64 (EFI_MSR_HASWELL_SMM_MCA_CAP) & SMM_CODE_ACCESS_CHK_BIT) == 0) {
      mSmmCodeAccessCheckEnable = FALSE;
      if (!FeaturePcdGet (PcdCpuSmmFeatureControlMsrLock)) {
        return;
      }
    }
    //
    // Enable SMM Code Access Check feature for the BSP.
    //
    ConfigSmmCodeAccessCheckOnCurrentProcessor (NULL);
    //
    // Enable SMM Code Access Check feature for the APs.
    //
    for (Index = 0; Index < mNumberOfCpus; Index++) {
      if (Index != gSmmCpuPrivate->SmmCoreEntryContext.CurrentlyExecutingCpu) {
        //
        // Don't call gSmst->SmmStartupThisAp() because it may be implemented in a blocking or non-blocking fashion.
        //
        Status = SmmBlockingStartupThisAp (ConfigSmmCodeAccessCheckOnCurrentProcessor, Index, NULL);
        ASSERT_EFI_ERROR (Status);
      }
    }
  }
}