xref: /aosp_15_r20/external/coreboot/src/soc/amd/common/block/psp/psp_smm.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <device/mmio.h>
4 #include <cpu/x86/msr.h>
5 #include <cpu/amd/msr.h>
6 #include <region_file.h>
7 #include <console/console.h>
8 #include <amdblocks/psp.h>
9 #include <soc/iomap.h>
10 #include <string.h>
11 
12 #include "psp_def.h"
13 
14 #define C2P_BUFFER_MAXSIZE 0xc00 /* Core-to-PSP buffer */
15 #define P2C_BUFFER_MAXSIZE 0xc00 /* PSP-to-core buffer */
16 
17 struct {
18 	u8 buffer[C2P_BUFFER_MAXSIZE];
19 } __aligned(32) c2p_buffer;
20 
21 struct {
22 	u8 buffer[P2C_BUFFER_MAXSIZE];
23 } __aligned(32) p2c_buffer;
24 
25 static uint32_t smm_flag; /* Non-zero for SMM, clear when not */
26 
set_smm_flag(void)27 static void set_smm_flag(void)
28 {
29 	smm_flag = 1;
30 }
31 
clear_smm_flag(void)32 static void clear_smm_flag(void)
33 {
34 	smm_flag = 0;
35 }
36 
psp_notify_smm(void)37 int psp_notify_smm(void)
38 {
39 	msr_t msr;
40 	int cmd_status;
41 	struct mbox_cmd_smm_info_buffer buffer = {
42 		.header = {
43 			.size = sizeof(buffer)
44 		},
45 		.req = {
46 			.psp_smm_data_region = (uintptr_t)p2c_buffer.buffer,
47 			.psp_smm_data_length = sizeof(p2c_buffer),
48 			.psp_mbox_smm_buffer_address = (uintptr_t)c2p_buffer.buffer,
49 			.psp_mbox_smm_flag_address = (uintptr_t)&smm_flag,
50 		}
51 	};
52 
53 	msr = rdmsr(SMM_ADDR_MSR);
54 	buffer.req.smm_base = msr.raw;
55 	msr = rdmsr(SMM_MASK_MSR);
56 	msr.lo &= 0xffff0000; /* mask SMM_TSEG_VALID and reserved bits */
57 	buffer.req.smm_mask = msr.raw;
58 
59 	soc_fill_smm_trig_info(&buffer.req.smm_trig_info);
60 #if (CONFIG(SOC_AMD_COMMON_BLOCK_PSP_GEN2))
61 	soc_fill_smm_reg_info(&buffer.req.smm_reg_info);
62 #endif
63 
64 	printk(BIOS_DEBUG, "PSP: Notify SMM info... ");
65 
66 	set_smm_flag();
67 	cmd_status = send_psp_command(MBOX_BIOS_CMD_SMM_INFO, &buffer);
68 	clear_smm_flag();
69 
70 	/* buffer's status shouldn't change but report it if it does */
71 	psp_print_cmd_status(cmd_status, &buffer.header);
72 
73 	return cmd_status;
74 }
75 
76 /* Notify PSP the system is going to a sleep state. */
psp_notify_sx_info(u8 sleep_type)77 void psp_notify_sx_info(u8 sleep_type)
78 {
79 	int cmd_status;
80 	struct mbox_cmd_sx_info_buffer *buffer;
81 
82 	/* PSP verifies that this buffer is at the address specified in psp_notify_smm() */
83 	buffer = (struct mbox_cmd_sx_info_buffer *)c2p_buffer.buffer;
84 	memset(buffer, 0, sizeof(*buffer));
85 	buffer->header.size = sizeof(*buffer);
86 
87 	if (sleep_type > MBOX_BIOS_CMD_SX_INFO_SLEEP_TYPE_MAX) {
88 		printk(BIOS_ERR, "PSP: BUG: invalid sleep type 0x%x requested\n", sleep_type);
89 		return;
90 	}
91 
92 	printk(BIOS_DEBUG, "PSP: Prepare to enter sleep state %d... ", sleep_type);
93 
94 	buffer->sleep_type = sleep_type;
95 
96 	set_smm_flag();
97 	cmd_status = send_psp_command(MBOX_BIOS_CMD_SX_INFO, buffer);
98 	clear_smm_flag();
99 
100 	/* buffer's status shouldn't change but report it if it does */
101 	psp_print_cmd_status(cmd_status, &buffer->header);
102 }
103