]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/CpuHotplugSmm/Smbase.c
OvmfPkg/CpuHotplugSmm: introduce Post-SMM Pen for hot-added CPUs
[mirror_edk2.git] / OvmfPkg / CpuHotplugSmm / Smbase.c
1 /** @file
2 SMBASE relocation for hot-plugged CPUs.
3
4 Copyright (c) 2020, Red Hat, Inc.
5
6 SPDX-License-Identifier: BSD-2-Clause-Patent
7 **/
8
9 #include <Base.h> // BASE_1MB
10 #include <Library/BaseMemoryLib.h> // CopyMem()
11 #include <Library/DebugLib.h> // DEBUG()
12
13 #include "Smbase.h"
14
15 extern CONST UINT8 mPostSmmPen[];
16 extern CONST UINT16 mPostSmmPenSize;
17
18 /**
19 Allocate a non-SMRAM reserved memory page for the Post-SMM Pen for hot-added
20 CPUs.
21
22 This function may only be called from the entry point function of the driver.
23
24 @param[out] PenAddress The address of the allocated (normal RAM) reserved
25 page.
26
27 @param[in] BootServices Pointer to the UEFI boot services table. Used for
28 allocating the normal RAM (not SMRAM) reserved page.
29
30 @retval EFI_SUCCESS Allocation successful.
31
32 @retval EFI_BAD_BUFFER_SIZE The Post-SMM Pen template is not smaller than
33 EFI_PAGE_SIZE.
34
35 @return Error codes propagated from underlying services.
36 DEBUG_ERROR messages have been logged. No
37 resources have been allocated.
38 **/
39 EFI_STATUS
40 SmbaseAllocatePostSmmPen (
41 OUT UINT32 *PenAddress,
42 IN CONST EFI_BOOT_SERVICES *BootServices
43 )
44 {
45 EFI_STATUS Status;
46 EFI_PHYSICAL_ADDRESS Address;
47
48 //
49 // The pen code must fit in one page, and the last byte must remain free for
50 // signaling the SMM Monarch.
51 //
52 if (mPostSmmPenSize >= EFI_PAGE_SIZE) {
53 Status = EFI_BAD_BUFFER_SIZE;
54 DEBUG ((DEBUG_ERROR, "%a: mPostSmmPenSize=%u: %r\n", __FUNCTION__,
55 mPostSmmPenSize, Status));
56 return Status;
57 }
58
59 Address = BASE_1MB - 1;
60 Status = BootServices->AllocatePages (AllocateMaxAddress,
61 EfiReservedMemoryType, 1, &Address);
62 if (EFI_ERROR (Status)) {
63 DEBUG ((DEBUG_ERROR, "%a: AllocatePages(): %r\n", __FUNCTION__, Status));
64 return Status;
65 }
66
67 DEBUG ((DEBUG_INFO, "%a: Post-SMM Pen at 0x%Lx\n", __FUNCTION__, Address));
68 *PenAddress = (UINT32)Address;
69 return EFI_SUCCESS;
70 }
71
72 /**
73 Copy the Post-SMM Pen template code into the reserved page allocated with
74 SmbaseAllocatePostSmmPen().
75
76 Note that this effects an "SMRAM to normal RAM" copy.
77
78 The SMM Monarch is supposed to call this function from the root MMI handler.
79
80 @param[in] PenAddress The allocation address returned by
81 SmbaseAllocatePostSmmPen().
82 **/
83 VOID
84 SmbaseReinstallPostSmmPen (
85 IN UINT32 PenAddress
86 )
87 {
88 CopyMem ((VOID *)(UINTN)PenAddress, mPostSmmPen, mPostSmmPenSize);
89 }
90
91 /**
92 Release the reserved page allocated with SmbaseAllocatePostSmmPen().
93
94 This function may only be called from the entry point function of the driver,
95 on the error path.
96
97 @param[in] PenAddress The allocation address returned by
98 SmbaseAllocatePostSmmPen().
99
100 @param[in] BootServices Pointer to the UEFI boot services table. Used for
101 releasing the normal RAM (not SMRAM) reserved page.
102 **/
103 VOID
104 SmbaseReleasePostSmmPen (
105 IN UINT32 PenAddress,
106 IN CONST EFI_BOOT_SERVICES *BootServices
107 )
108 {
109 BootServices->FreePages (PenAddress, 1);
110 }