summaryrefslogtreecommitdiffstats
path: root/src/drivers/intel/fsp2_0/ppi/mp_service_ppi.c
blob: 66bbc2f085cb28f318bb53f23571f62c266691e1 (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
/* SPDX-License-Identifier: GPL-2.0-only */

#include <console/console.h>
#include <cpu/cpu.h>
#include <cpu/x86/mp.h>
#include <cpu/intel/microcode.h>
#include <fsp/api.h>
#include <fsp/ppi/mp_service_ppi.h>
#include <intelblocks/cpulib.h>
#include <intelblocks/mp_init.h>
#include <types.h>

#define BSP_CPU_SLOT 0

efi_return_status_t mp_get_number_of_processors(efi_uintn_t *number_of_processors,
	efi_uintn_t *number_of_enabled_processors)
{
	if (number_of_processors == NULL || number_of_enabled_processors ==
			NULL)
		return FSP_INVALID_PARAMETER;

	*number_of_processors = get_cpu_count();
	*number_of_enabled_processors = get_cpu_count();

	return FSP_SUCCESS;
}

efi_return_status_t mp_get_processor_info(efi_uintn_t processor_number,
	efi_processor_information *processor_info_buffer)
{
	int apicid;
	uint8_t package, core, thread;

	if (cpu_index() < 0)
		return FSP_DEVICE_ERROR;

	if (processor_info_buffer == NULL)
		return FSP_INVALID_PARAMETER;

	if (processor_number >= get_cpu_count())
		return FSP_NOT_FOUND;

	apicid = cpu_get_apic_id(processor_number);

	if (apicid < 0)
		return FSP_DEVICE_ERROR;

	processor_info_buffer->ProcessorId = apicid;

	processor_info_buffer->StatusFlag = PROCESSOR_HEALTH_STATUS_BIT
			| PROCESSOR_ENABLED_BIT;

	if (processor_number == BSP_CPU_SLOT)
		processor_info_buffer->StatusFlag |= PROCESSOR_AS_BSP_BIT;

	/* Fill EFI_CPU_PHYSICAL_LOCATION structure information */
	get_cpu_topology_from_apicid(apicid, &package, &core, &thread);

	processor_info_buffer->Location.Package = package;
	processor_info_buffer->Location.Core = core;
	processor_info_buffer->Location.Thread = thread;

	return FSP_SUCCESS;
}

efi_return_status_t mp_startup_all_aps(efi_ap_procedure procedure,
	bool run_serial, efi_uintn_t timeout_usec, void *argument)
{
	if (cpu_index() < 0)
		return FSP_DEVICE_ERROR;

	if (procedure == NULL)
		return FSP_INVALID_PARAMETER;

	if (mp_run_on_all_aps((void *)procedure, argument, timeout_usec, !run_serial) !=
				CB_SUCCESS) {
		printk(BIOS_DEBUG, "%s: Exit with Failure\n", __func__);
		return FSP_NOT_STARTED;
	}

	return FSP_SUCCESS;
}

efi_return_status_t mp_startup_all_cpus(efi_ap_procedure procedure,
	efi_uintn_t timeout_usec, void *argument)
{
	if (cpu_index() < 0)
		return FSP_DEVICE_ERROR;

	if (procedure == NULL)
		return FSP_INVALID_PARAMETER;

	/* Run on BSP */
	procedure(argument);

	/*
	 * Run on APs Serially
	 *
	 * FIXME: As per MP service specification, edk2 is allowed to specify the mode
	 * in which a 'func' routine should be executed on APs (i.e. execute serially
	 * or concurrently).
	 *
	 * MP service API `StartupAllCPUs` doesn't specify such requirement.
	 * Hence, running the `CpuCacheInfoCollectCoreAndCacheData`
	 * (UefiCpuPkg/Library/CpuCacheInfoLib/CpuCacheInfoLib.c#194)
	 * simultaneously on APs results in a coherency issue (hang while executing `func`)
	 * due to lack of acquiring a spin lock while accessing common data structure in
	 * multiprocessor environment.
	 */
	if (mp_run_on_all_aps((void *)procedure, argument, timeout_usec, false) !=
				CB_SUCCESS) {
		printk(BIOS_DEBUG, "%s: Exit with Failure\n", __func__);
		return FSP_NOT_STARTED;
	}

	return FSP_SUCCESS;
}

efi_return_status_t mp_startup_this_ap(efi_ap_procedure procedure,
	efi_uintn_t processor_number, efi_uintn_t timeout_usec, void *argument)
{
	if (cpu_index() < 0)
		return FSP_DEVICE_ERROR;

	if (processor_number > get_cpu_count())
		return FSP_NOT_FOUND;

	if (processor_number == BSP_CPU_SLOT)
		return FSP_INVALID_PARAMETER;

	if (procedure == NULL)
		return FSP_INVALID_PARAMETER;

	if (mp_run_on_aps((void *)procedure, argument,
			processor_number, timeout_usec) != CB_SUCCESS) {
		printk(BIOS_DEBUG, "%s: Exit with Failure\n", __func__);
		return FSP_NOT_STARTED;
	}

	return FSP_SUCCESS;
}

efi_return_status_t mp_identify_processor(efi_uintn_t *processor_number)
{
	int index;

	if (processor_number == NULL)
		return FSP_INVALID_PARAMETER;

	index = cpu_index();

	if (index < 0)
		return FSP_DEVICE_ERROR;

	*processor_number = index;

	return FSP_SUCCESS;
}