Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
mariux64
/
linux
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
2
Pull requests
0
Actions
Projects
0
Wiki
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security
Insights
Files
ecf5636
Documentation
arch
block
crypto
drivers
accessibility
acpi
acpica
apei
pmic
Kconfig
Makefile
ac.c
acpi_cmos_rtc.c
acpi_extlog.c
acpi_ipmi.c
acpi_lpss.c
acpi_memhotplug.c
acpi_pad.c
acpi_platform.c
acpi_pnp.c
acpi_processor.c
battery.c
battery.h
bgrt.c
blacklist.c
bus.c
button.c
cm_sbs.c
container.c
custom_method.c
debugfs.c
device_pm.c
dock.c
ec.c
ec_sys.c
event.c
fan.c
glue.c
hed.c
int340x_thermal.c
internal.h
numa.c
nvs.c
osl.c
pci_irq.c
pci_link.c
pci_root.c
pci_slot.c
power.c
proc.c
processor_core.c
processor_driver.c
processor_idle.c
processor_pdc.c
processor_perflib.c
processor_thermal.c
processor_throttling.c
property.c
reboot.c
resource.c
sbs.c
sbshc.c
sbshc.h
scan.c
sleep.c
sleep.h
sysfs.c
tables.c
thermal.c
utils.c
video.c
video_detect.c
wakeup.c
amba
android
ata
atm
auxdisplay
base
bcma
block
bluetooth
bus
cdrom
char
clk
clocksource
connector
coresight
cpufreq
cpuidle
crypto
dca
devfreq
dio
dma-buf
dma
edac
eisa
extcon
firewire
firmware
fmc
gpio
gpu
hid
hsi
hv
hwmon
hwspinlock
i2c
ide
idle
iio
infiniband
input
iommu
ipack
irqchip
isdn
leds
lguest
macintosh
mailbox
mcb
md
media
memory
memstick
message
mfd
misc
mmc
mtd
net
nfc
ntb
nubus
of
oprofile
parisc
parport
pci
pcmcia
phy
pinctrl
platform
pnp
power
powercap
pps
ps3
ptp
pwm
rapidio
ras
regulator
remoteproc
reset
rpmsg
rtc
s390
sbus
scsi
sfi
sh
sn
soc
spi
spmi
ssb
staging
target
tc
thermal
thunderbolt
tty
uio
usb
uwb
vfio
vhost
video
virt
virtio
vlynq
vme
w1
watchdog
xen
zorro
Kconfig
Makefile
firmware
fs
include
init
ipc
kernel
lib
mm
net
samples
scripts
security
sound
tools
usr
virt
.gitignore
.mailmap
COPYING
CREDITS
Kbuild
Kconfig
MAINTAINERS
Makefile
README
REPORTING-BUGS
Breadcrumbs
linux
/
drivers
/
acpi
/
processor_core.c
Copy path
Blame
Blame
Latest commit
History
History
310 lines (257 loc) · 7.67 KB
Breadcrumbs
linux
/
drivers
/
acpi
/
processor_core.c
Top
File metadata and controls
Code
Blame
310 lines (257 loc) · 7.67 KB
Raw
/* * Copyright (C) 2005 Intel Corporation * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. * * Alex Chiang <achiang@hp.com> * - Unified x86/ia64 implementations * * I/O APIC hotplug support * Yinghai Lu <yinghai@kernel.org> * Jiang Liu <jiang.liu@intel.com> */ #include <linux/export.h> #include <linux/acpi.h> #include <acpi/processor.h> #define _COMPONENT ACPI_PROCESSOR_COMPONENT ACPI_MODULE_NAME("processor_core"); static struct acpi_table_madt *get_madt_table(void) { static struct acpi_table_madt *madt; static int read_madt; if (!read_madt) { if (ACPI_FAILURE(acpi_get_table(ACPI_SIG_MADT, 0, (struct acpi_table_header **)&madt))) madt = NULL; read_madt++; } return madt; } static int map_lapic_id(struct acpi_subtable_header *entry, u32 acpi_id, int *apic_id) { struct acpi_madt_local_apic *lapic = container_of(entry, struct acpi_madt_local_apic, header); if (!(lapic->lapic_flags & ACPI_MADT_ENABLED)) return -ENODEV; if (lapic->processor_id != acpi_id) return -EINVAL; *apic_id = lapic->id; return 0; } static int map_x2apic_id(struct acpi_subtable_header *entry, int device_declaration, u32 acpi_id, int *apic_id) { struct acpi_madt_local_x2apic *apic = container_of(entry, struct acpi_madt_local_x2apic, header); if (!(apic->lapic_flags & ACPI_MADT_ENABLED)) return -ENODEV; if (device_declaration && (apic->uid == acpi_id)) { *apic_id = apic->local_apic_id; return 0; } return -EINVAL; } static int map_lsapic_id(struct acpi_subtable_header *entry, int device_declaration, u32 acpi_id, int *apic_id) { struct acpi_madt_local_sapic *lsapic = container_of(entry, struct acpi_madt_local_sapic, header); if (!(lsapic->lapic_flags & ACPI_MADT_ENABLED)) return -ENODEV; if (device_declaration) { if ((entry->length < 16) || (lsapic->uid != acpi_id)) return -EINVAL; } else if (lsapic->processor_id != acpi_id) return -EINVAL; *apic_id = (lsapic->id << 8) | lsapic->eid; return 0; } static int map_madt_entry(int type, u32 acpi_id) { unsigned long madt_end, entry; int phys_id = -1; /* CPU hardware ID */ struct acpi_table_madt *madt; madt = get_madt_table(); if (!madt) return phys_id; entry = (unsigned long)madt; madt_end = entry + madt->header.length; /* Parse all entries looking for a match. */ entry += sizeof(struct acpi_table_madt); while (entry + sizeof(struct acpi_subtable_header) < madt_end) { struct acpi_subtable_header *header = (struct acpi_subtable_header *)entry; if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) { if (!map_lapic_id(header, acpi_id, &phys_id)) break; } else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) { if (!map_x2apic_id(header, type, acpi_id, &phys_id)) break; } else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) { if (!map_lsapic_id(header, type, acpi_id, &phys_id)) break; } entry += header->length; } return phys_id; } static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *obj; struct acpi_subtable_header *header; int phys_id = -1; if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer))) goto exit; if (!buffer.length || !buffer.pointer) goto exit; obj = buffer.pointer; if (obj->type != ACPI_TYPE_BUFFER || obj->buffer.length < sizeof(struct acpi_subtable_header)) { goto exit; } header = (struct acpi_subtable_header *)obj->buffer.pointer; if (header->type == ACPI_MADT_TYPE_LOCAL_APIC) map_lapic_id(header, acpi_id, &phys_id); else if (header->type == ACPI_MADT_TYPE_LOCAL_SAPIC) map_lsapic_id(header, type, acpi_id, &phys_id); else if (header->type == ACPI_MADT_TYPE_LOCAL_X2APIC) map_x2apic_id(header, type, acpi_id, &phys_id); exit: kfree(buffer.pointer); return phys_id; } int acpi_get_phys_id(acpi_handle handle, int type, u32 acpi_id) { int phys_id; phys_id = map_mat_entry(handle, type, acpi_id); if (phys_id == -1) phys_id = map_madt_entry(type, acpi_id); return phys_id; } int acpi_map_cpuid(int phys_id, u32 acpi_id) { #ifdef CONFIG_SMP int i; #endif if (phys_id == -1) { /* * On UP processor, there is no _MAT or MADT table. * So above phys_id is always set to -1. * * BIOS may define multiple CPU handles even for UP processor. * For example, * * Scope (_PR) * { * Processor (CPU0, 0x00, 0x00000410, 0x06) {} * Processor (CPU1, 0x01, 0x00000410, 0x06) {} * Processor (CPU2, 0x02, 0x00000410, 0x06) {} * Processor (CPU3, 0x03, 0x00000410, 0x06) {} * } * * Ignores phys_id and always returns 0 for the processor * handle with acpi id 0 if nr_cpu_ids is 1. * This should be the case if SMP tables are not found. * Return -1 for other CPU's handle. */ if (nr_cpu_ids <= 1 && acpi_id == 0) return acpi_id; else return phys_id; } #ifdef CONFIG_SMP for_each_possible_cpu(i) { if (cpu_physical_id(i) == phys_id) return i; } #else /* In UP kernel, only processor 0 is valid */ if (phys_id == 0) return phys_id; #endif return -1; } int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id) { int phys_id; phys_id = acpi_get_phys_id(handle, type, acpi_id); return acpi_map_cpuid(phys_id, acpi_id); } EXPORT_SYMBOL_GPL(acpi_get_cpuid); #ifdef CONFIG_ACPI_HOTPLUG_IOAPIC static int get_ioapic_id(struct acpi_subtable_header *entry, u32 gsi_base, u64 *phys_addr, int *ioapic_id) { struct acpi_madt_io_apic *ioapic = (struct acpi_madt_io_apic *)entry; if (ioapic->global_irq_base != gsi_base) return 0; *phys_addr = ioapic->address; *ioapic_id = ioapic->id; return 1; } static int parse_madt_ioapic_entry(u32 gsi_base, u64 *phys_addr) { struct acpi_subtable_header *hdr; unsigned long madt_end, entry; struct acpi_table_madt *madt; int apic_id = -1; madt = get_madt_table(); if (!madt) return apic_id; entry = (unsigned long)madt; madt_end = entry + madt->header.length; /* Parse all entries looking for a match. */ entry += sizeof(struct acpi_table_madt); while (entry + sizeof(struct acpi_subtable_header) < madt_end) { hdr = (struct acpi_subtable_header *)entry; if (hdr->type == ACPI_MADT_TYPE_IO_APIC && get_ioapic_id(hdr, gsi_base, phys_addr, &apic_id)) break; else entry += hdr->length; } return apic_id; } static int parse_mat_ioapic_entry(acpi_handle handle, u32 gsi_base, u64 *phys_addr) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_subtable_header *header; union acpi_object *obj; int apic_id = -1; if (ACPI_FAILURE(acpi_evaluate_object(handle, "_MAT", NULL, &buffer))) goto exit; if (!buffer.length || !buffer.pointer) goto exit; obj = buffer.pointer; if (obj->type != ACPI_TYPE_BUFFER || obj->buffer.length < sizeof(struct acpi_subtable_header)) goto exit; header = (struct acpi_subtable_header *)obj->buffer.pointer; if (header->type == ACPI_MADT_TYPE_IO_APIC) get_ioapic_id(header, gsi_base, phys_addr, &apic_id); exit: kfree(buffer.pointer); return apic_id; } /** * acpi_get_ioapic_id - Get IOAPIC ID and physical address matching @gsi_base * @handle: ACPI object for IOAPIC device * @gsi_base: GSI base to match with * @phys_addr: Pointer to store physical address of matching IOAPIC record * * Walk resources returned by ACPI_MAT method, then ACPI MADT table, to search * for an ACPI IOAPIC record matching @gsi_base. * Return IOAPIC id and store physical address in @phys_addr if found a match, * otherwise return <0. */ int acpi_get_ioapic_id(acpi_handle handle, u32 gsi_base, u64 *phys_addr) { int apic_id; apic_id = parse_mat_ioapic_entry(handle, gsi_base, phys_addr); if (apic_id == -1) apic_id = parse_madt_ioapic_entry(gsi_base, phys_addr); return apic_id; } #endif /* CONFIG_ACPI_HOTPLUG_IOAPIC */
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
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
You can’t perform that action at this time.