Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/arm64/acpica/acpi_machdep.c
39478 views
1
/*-
2
* Copyright (c) 2001 Mitsuru IWASAKI
3
* Copyright (c) 2015 The FreeBSD Foundation
4
* All rights reserved.
5
*
6
* This software was developed by Andrew Turner under
7
* sponsorship from the FreeBSD Foundation.
8
*
9
* Redistribution and use in source and binary forms, with or without
10
* modification, are permitted provided that the following conditions
11
* are met:
12
* 1. Redistributions of source code must retain the above copyright
13
* notice, this list of conditions and the following disclaimer.
14
* 2. Redistributions in binary form must reproduce the above copyright
15
* notice, this list of conditions and the following disclaimer in the
16
* documentation and/or other materials provided with the distribution.
17
*
18
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
* SUCH DAMAGE.
29
*/
30
31
#include <sys/param.h>
32
#include <sys/bus.h>
33
#include <sys/kernel.h>
34
35
#include <vm/vm.h>
36
#include <vm/pmap.h>
37
38
#include <machine/machdep.h>
39
40
#include <contrib/dev/acpica/include/acpi.h>
41
#include <contrib/dev/acpica/include/accommon.h>
42
#include <contrib/dev/acpica/include/actables.h>
43
44
#include <dev/acpica/acpivar.h>
45
46
extern struct bus_space memmap_bus;
47
48
int
49
acpi_machdep_init(device_t dev)
50
{
51
52
return (0);
53
}
54
55
int
56
acpi_machdep_quirks(int *quirks)
57
{
58
59
return (0);
60
}
61
62
static void *
63
map_table(vm_paddr_t pa, const char *sig)
64
{
65
ACPI_TABLE_HEADER *header;
66
vm_size_t length;
67
void *table;
68
69
header = pmap_mapbios(pa, sizeof(ACPI_TABLE_HEADER));
70
if (strncmp(header->Signature, sig, ACPI_NAMESEG_SIZE) != 0) {
71
pmap_unmapbios(header, sizeof(ACPI_TABLE_HEADER));
72
return (NULL);
73
}
74
length = header->Length;
75
pmap_unmapbios(header, sizeof(ACPI_TABLE_HEADER));
76
77
table = pmap_mapbios(pa, length);
78
if (ACPI_FAILURE(AcpiUtChecksum(table, length))) {
79
if (bootverbose)
80
printf("ACPI: Failed checksum for table %s\n", sig);
81
#if (ACPI_CHECKSUM_ABORT)
82
pmap_unmapbios(table, length);
83
return (NULL);
84
#endif
85
}
86
return (table);
87
}
88
89
/*
90
* See if a given ACPI table is the requested table. Returns the
91
* length of the table if it matches or zero on failure.
92
*/
93
static int
94
probe_table(vm_paddr_t address, const char *sig)
95
{
96
ACPI_TABLE_HEADER *table;
97
98
table = pmap_mapbios(address, sizeof(ACPI_TABLE_HEADER));
99
if (table == NULL) {
100
if (bootverbose)
101
printf("ACPI: Failed to map table at 0x%jx\n",
102
(uintmax_t)address);
103
return (0);
104
}
105
106
if (strncmp(table->Signature, sig, ACPI_NAMESEG_SIZE) != 0) {
107
pmap_unmapbios(table, sizeof(ACPI_TABLE_HEADER));
108
return (0);
109
}
110
pmap_unmapbios(table, sizeof(ACPI_TABLE_HEADER));
111
return (1);
112
}
113
114
/* Unmap a table previously mapped via acpi_map_table(). */
115
void
116
acpi_unmap_table(void *table)
117
{
118
ACPI_TABLE_HEADER *header;
119
120
header = (ACPI_TABLE_HEADER *)table;
121
pmap_unmapbios(table, header->Length);
122
}
123
124
/*
125
* Try to map a table at a given physical address previously returned
126
* by acpi_find_table().
127
*/
128
void *
129
acpi_map_table(vm_paddr_t pa, const char *sig)
130
{
131
132
return (map_table(pa, sig));
133
}
134
135
/*
136
* Return the physical address of the requested table or zero if one
137
* is not found.
138
*/
139
vm_paddr_t
140
acpi_find_table(const char *sig)
141
{
142
ACPI_PHYSICAL_ADDRESS rsdp_ptr;
143
ACPI_TABLE_RSDP *rsdp;
144
ACPI_TABLE_XSDT *xsdt;
145
ACPI_TABLE_HEADER *table;
146
vm_paddr_t addr;
147
int i, count;
148
149
if (resource_disabled("acpi", 0))
150
return (0);
151
152
/*
153
* Map in the RSDP. Since ACPI uses AcpiOsMapMemory() which in turn
154
* calls pmap_mapbios() to find the RSDP, we assume that we can use
155
* pmap_mapbios() to map the RSDP.
156
*/
157
if ((rsdp_ptr = AcpiOsGetRootPointer()) == 0)
158
return (0);
159
rsdp = pmap_mapbios(rsdp_ptr, sizeof(ACPI_TABLE_RSDP));
160
if (rsdp == NULL) {
161
printf("ACPI: Failed to map RSDP\n");
162
return (0);
163
}
164
165
addr = 0;
166
if (rsdp->Revision >= 2 && rsdp->XsdtPhysicalAddress != 0) {
167
/*
168
* AcpiOsGetRootPointer only verifies the checksum for
169
* the version 1.0 portion of the RSDP. Version 2.0 has
170
* an additional checksum that we verify first.
171
*/
172
if (AcpiUtChecksum((UINT8 *)rsdp, ACPI_RSDP_XCHECKSUM_LENGTH)) {
173
printf("ACPI: RSDP failed extended checksum\n");
174
pmap_unmapbios(rsdp, sizeof(ACPI_TABLE_RSDP));
175
return (0);
176
}
177
xsdt = map_table(rsdp->XsdtPhysicalAddress, ACPI_SIG_XSDT);
178
if (xsdt == NULL) {
179
printf("ACPI: Failed to map XSDT\n");
180
pmap_unmapbios(rsdp, sizeof(ACPI_TABLE_RSDP));
181
return (0);
182
}
183
count = (xsdt->Header.Length - sizeof(ACPI_TABLE_HEADER)) /
184
sizeof(UINT64);
185
for (i = 0; i < count; i++)
186
if (probe_table(xsdt->TableOffsetEntry[i], sig)) {
187
addr = xsdt->TableOffsetEntry[i];
188
break;
189
}
190
acpi_unmap_table(xsdt);
191
} else {
192
printf("ACPI: Unsupported RSDP version %d and XSDT %#lx\n",
193
rsdp->Revision, rsdp->XsdtPhysicalAddress);
194
}
195
pmap_unmapbios(rsdp, sizeof(ACPI_TABLE_RSDP));
196
197
if (addr == 0)
198
return (0);
199
200
/*
201
* Verify that we can map the full table and that its checksum is
202
* correct, etc.
203
*/
204
table = map_table(addr, sig);
205
if (table == NULL)
206
return (0);
207
acpi_unmap_table(table);
208
209
return (addr);
210
}
211
212
int
213
acpi_map_addr(struct acpi_generic_address *addr, bus_space_tag_t *tag,
214
bus_space_handle_t *handle, bus_size_t size)
215
{
216
bus_addr_t phys;
217
218
/* Check if the device is Memory mapped */
219
if (addr->SpaceId != 0)
220
return (ENXIO);
221
222
phys = addr->Address;
223
*tag = &memmap_bus;
224
225
return (bus_space_map(*tag, phys, size, 0, handle));
226
}
227
228
#if MAXMEMDOM > 1
229
static void
230
parse_pxm_tables(void *dummy)
231
{
232
uint64_t mmfr0, parange;
233
234
/* Only parse ACPI tables when booting via ACPI */
235
if (arm64_bus_method != ARM64_BUS_ACPI)
236
return;
237
238
if (!get_kernel_reg(ID_AA64MMFR0_EL1, &mmfr0)) {
239
/* chosen arbitrarily */
240
mmfr0 = ID_AA64MMFR0_PARange_1T;
241
}
242
243
switch (ID_AA64MMFR0_PARange_VAL(mmfr0)) {
244
case ID_AA64MMFR0_PARange_4G:
245
parange = (vm_paddr_t)4 << 30 /* GiB */;
246
break;
247
case ID_AA64MMFR0_PARange_64G:
248
parange = (vm_paddr_t)64 << 30 /* GiB */;
249
break;
250
case ID_AA64MMFR0_PARange_1T:
251
parange = (vm_paddr_t)1 << 40 /* TiB */;
252
break;
253
case ID_AA64MMFR0_PARange_4T:
254
parange = (vm_paddr_t)4 << 40 /* TiB */;
255
break;
256
case ID_AA64MMFR0_PARange_16T:
257
parange = (vm_paddr_t)16 << 40 /* TiB */;
258
break;
259
case ID_AA64MMFR0_PARange_256T:
260
parange = (vm_paddr_t)256 << 40 /* TiB */;
261
break;
262
case ID_AA64MMFR0_PARange_4P:
263
parange = (vm_paddr_t)4 << 50 /* PiB */;
264
break;
265
default:
266
/* chosen arbitrarily */
267
parange = (vm_paddr_t)1 << 40 /* TiB */;
268
printf("Unknown value for PARange in mmfr0 (%#lx)\n", mmfr0);
269
break;
270
}
271
272
acpi_pxm_init(MAXCPU, parange);
273
acpi_pxm_parse_tables();
274
acpi_pxm_set_mem_locality();
275
}
276
SYSINIT(parse_pxm_tables, SI_SUB_VM - 1, SI_ORDER_FIRST, parse_pxm_tables,
277
NULL);
278
#endif
279
280