summaryrefslogtreecommitdiffstats
path: root/MdePkg/Library/BaseSynchronizationLib/Ia32/InternalGetSpinLockProperties.c
blob: aba0825c7c451886da563ee1c253ea0649a49017 (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
/** @file
  Internal function to get spin lock alignment.

  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
  SPDX-License-Identifier: BSD-2-Clause-Patent

**/

#include "BaseSynchronizationLibInternals.h"

/**
  Internal function to retrieve the architecture specific spin lock alignment
  requirements for optimal spin lock performance.

  @return The architecture specific spin lock alignment.

**/
UINTN
InternalGetSpinLockProperties (
  VOID
  )
{
  UINT32  RegEax;
  UINT32  RegEbx;
  UINTN   FamilyId;
  UINTN   ModelId;
  UINTN   CacheLineSize;

  //
  // Retrieve CPUID Version Information
  //
  AsmCpuid (0x01, &RegEax, &RegEbx, NULL, NULL);
  //
  // EBX: Bits 15 - 08: CLFLUSH line size (Value * 8 = cache line size)
  //
  CacheLineSize = ((RegEbx >> 8) & 0xff) * 8;
  //
  // Retrieve CPU Family and Model
  //
  FamilyId = (RegEax >> 8) & 0xf;
  ModelId  = (RegEax >> 4) & 0xf;
  if (FamilyId == 0x0f) {
    //
    // In processors based on Intel NetBurst microarchitecture, use two cache lines
    //
    ModelId = ModelId | ((RegEax >> 12) & 0xf0);
    if ((ModelId <= 0x04) || (ModelId == 0x06)) {
      CacheLineSize *= 2;
    }
  }

  if (CacheLineSize < 32) {
    CacheLineSize = 32;
  }

  return CacheLineSize;
}