summaryrefslogtreecommitdiff
path: root/OvmfPkg/PlatformPei/FeatureControl.c
blob: d2ec496b74a8d3398a6865046b18358441fc28a3 (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
/**@file
  Install a callback when necessary for setting the Feature Control MSR on all
  processors.

  Copyright (C) 2016, Red Hat, Inc.

  SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#include <Library/DebugLib.h>
#include <Library/HobLib.h>
#include <Library/PeiServicesLib.h>
#include <Library/QemuFwCfgLib.h>
#include <Ppi/MpServices.h>
#include <Register/ArchitecturalMsr.h>
#include <IndustryStandard/Tdx.h>

#include "Platform.h"

/**
  Write the Feature Control MSR on an Application Processor or the Boot
  Processor.

  All APs execute this function in parallel. The BSP executes the function
  separately.

  @param[in,out] WorkSpace  Pointer to the input/output argument workspace
                            shared by all processors.
**/
STATIC
VOID
EFIAPI
WriteFeatureControl (
  IN OUT VOID  *WorkSpace
  )
{
  EFI_HOB_PLATFORM_INFO  *PlatformInfoHob = WorkSpace;

  if (TdIsEnabled ()) {
    TdVmCall (
      TDVMCALL_WRMSR,
      (UINT64)MSR_IA32_FEATURE_CONTROL,
      PlatformInfoHob->FeatureControlValue,
      0,
      0,
      0
      );
  } else {
    AsmWriteMsr64 (
      MSR_IA32_FEATURE_CONTROL,
      PlatformInfoHob->FeatureControlValue
      );
  }
}

/**
  Notification function called when EFI_PEI_MP_SERVICES_PPI becomes available.

  @param[in] PeiServices      Indirect reference to the PEI Services Table.
  @param[in] NotifyDescriptor Address of the notification descriptor data
                              structure.
  @param[in] Ppi              Address of the PPI that was installed.

  @return  Status of the notification. The status code returned from this
           function is ignored.
**/
STATIC
EFI_STATUS
EFIAPI
OnMpServicesAvailable (
  IN EFI_PEI_SERVICES           **PeiServices,
  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
  IN VOID                       *Ppi
  )
{
  EFI_PEI_MP_SERVICES_PPI  *MpServices;
  EFI_STATUS               Status;
  EFI_HOB_PLATFORM_INFO    *PlatformInfoHob;
  EFI_HOB_GUID_TYPE        *GuidHob;

  GuidHob = GetFirstGuidHob (&gUefiOvmfPkgPlatformInfoGuid);
  if (GuidHob == NULL) {
    return EFI_UNSUPPORTED;
  }

  PlatformInfoHob = (EFI_HOB_PLATFORM_INFO *)GET_GUID_HOB_DATA (GuidHob);

  DEBUG ((DEBUG_VERBOSE, "%a: %a\n", gEfiCallerBaseName, __func__));

  //
  // Write the MSR on all the APs in parallel.
  //
  MpServices = Ppi;
  Status     = MpServices->StartupAllAPs (
                             (CONST EFI_PEI_SERVICES **)PeiServices,
                             MpServices,
                             WriteFeatureControl, // Procedure
                             FALSE,               // SingleThread
                             0,                   // TimeoutInMicroSeconds: inf.
                             PlatformInfoHob      // ProcedureArgument
                             );
  if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {
    DEBUG ((DEBUG_ERROR, "%a: StartupAllAps(): %r\n", __func__, Status));
    return Status;
  }

  //
  // Now write the MSR on the BSP too.
  //
  WriteFeatureControl (PlatformInfoHob);
  return EFI_SUCCESS;
}

//
// Notification object for registering the callback, for when
// EFI_PEI_MP_SERVICES_PPI becomes available.
//
STATIC CONST EFI_PEI_NOTIFY_DESCRIPTOR  mMpServicesNotify = {
  EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | // Flags
  EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
  &gEfiPeiMpServicesPpiGuid,               // Guid
  OnMpServicesAvailable                    // Notify
};

VOID
InstallFeatureControlCallback (
  IN OUT EFI_HOB_PLATFORM_INFO  *PlatformInfoHob
  )
{
  EFI_STATUS            Status;
  FIRMWARE_CONFIG_ITEM  FwCfgItem;
  UINTN                 FwCfgSize;

  Status = QemuFwCfgFindFile (
             "etc/msr_feature_control",
             &FwCfgItem,
             &FwCfgSize
             );
  if (EFI_ERROR (Status) || (FwCfgSize != sizeof (PlatformInfoHob->FeatureControlValue))) {
    //
    // Nothing to do.
    //
    return;
  }

  QemuFwCfgSelectItem (FwCfgItem);
  QemuFwCfgReadBytes (
    sizeof (PlatformInfoHob->FeatureControlValue),
    &(PlatformInfoHob->FeatureControlValue)
    );

  Status = PeiServicesNotifyPpi (&mMpServicesNotify);
  if (EFI_ERROR (Status)) {
    DEBUG ((
      DEBUG_ERROR,
      "%a: failed to set up MP Services callback: %r\n",
      __func__,
      Status
      ));
  }
}