Skip to content

Commit 0b5c772

Browse files
committed
修复 ACPICA 初始化顺序不一致问题与 PCIE 表映射缺失问题.
1 parent 416482d commit 0b5c772

File tree

2 files changed

+119
-56
lines changed

2 files changed

+119
-56
lines changed

src/driver/acpica/acpi.c

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ void acpi_init() {
99
if (ACPI_FAILURE(st)) goto error;
1010
st = AcpiInitializeTables(NULL, 16, TRUE);
1111
if (ACPI_FAILURE(st)) goto error;
12-
st = AcpiLoadTables();
13-
if (ACPI_FAILURE(st)) goto error;
1412
return;
1513
error:
1614
kerror("acpica initialize failure");
@@ -20,6 +18,8 @@ void acpi_init() {
2018

2119
void acpi_namespace_setup() {
2220
ACPI_STATUS st;
21+
st = AcpiLoadTables();
22+
if (ACPI_FAILURE(st)) goto error;
2323
st = AcpiEnableSubsystem(ACPI_FULL_INITIALIZATION);
2424
if (ACPI_FAILURE(st)) goto error;
2525
st = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION);
@@ -30,36 +30,28 @@ void acpi_namespace_setup() {
3030
}
3131

3232
ACPI_STATUS acpi_table_find_by_signature(const char *signature, acpi_table_handle_t *out_table) {
33-
size_t i;
33+
size_t i;
3434
ACPI_STATUS st;
3535

36-
if (!signature || !out_table) {
37-
return AE_BAD_PARAMETER;
38-
}
36+
if (!signature || !out_table) { return AE_BAD_PARAMETER; }
3937

4038
memset(out_table, 0, sizeof(*out_table));
4139
for (i = 0; i < 4 && signature[i]; i++) {
4240
out_table->signature[i] = signature[i];
4341
}
44-
if (i < 4) {
45-
return AE_BAD_PARAMETER;
46-
}
42+
if (i < 4) { return AE_BAD_PARAMETER; }
4743
out_table->signature[4] = '\0';
48-
out_table->instance = 1;
44+
out_table->instance = 1;
4945

5046
st = AcpiGetTable(out_table->signature, out_table->instance, &out_table->hdr);
51-
if (ACPI_FAILURE(st)) {
52-
out_table->hdr = NULL;
53-
}
47+
if (ACPI_FAILURE(st)) { out_table->hdr = NULL; }
5448
return st;
5549
}
5650

5751
ACPI_STATUS acpi_table_find_next_with_same_signature(acpi_table_handle_t *in_out_table) {
5852
ACPI_STATUS st;
5953

60-
if (!in_out_table || !in_out_table->signature[0]) {
61-
return AE_BAD_PARAMETER;
62-
}
54+
if (!in_out_table || !in_out_table->signature[0]) { return AE_BAD_PARAMETER; }
6355

6456
if (in_out_table->hdr) {
6557
AcpiPutTable(in_out_table->hdr);
@@ -68,16 +60,12 @@ ACPI_STATUS acpi_table_find_next_with_same_signature(acpi_table_handle_t *in_out
6860

6961
in_out_table->instance++;
7062
st = AcpiGetTable(in_out_table->signature, in_out_table->instance, &in_out_table->hdr);
71-
if (ACPI_FAILURE(st)) {
72-
in_out_table->hdr = NULL;
73-
}
63+
if (ACPI_FAILURE(st)) { in_out_table->hdr = NULL; }
7464
return st;
7565
}
7666

7767
void acpi_table_put(acpi_table_handle_t *table) {
78-
if (!table || !table->hdr) {
79-
return;
80-
}
68+
if (!table || !table->hdr) { return; }
8169
AcpiPutTable(table->hdr);
8270
table->hdr = NULL;
8371
}

src/driver/pci/pci.c

Lines changed: 109 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -144,40 +144,76 @@ ACPI_MCFG_ALLOCATION *mcfg_entries[PCI_MCFG_MAX_ENTRIES_LEN];
144144
uint64_t mcfg_entries_len = 0;
145145
pci_device_t *pci_devices[PCI_DEVICE_MAX];
146146
uint32_t pci_device_number = 0;
147+
static bool pci_use_mcfg = false;
148+
static uint64_t mcfg_virt_bases[PCI_MCFG_MAX_ENTRIES_LEN];
149+
150+
#if defined(__x86_64__) || defined(__amd64__)
151+
uint32_t pci_read0(uint32_t b, uint32_t d, uint32_t f, uint32_t arg, uint32_t registeroffset);
152+
void pci_write0(uint32_t b, uint32_t d, uint32_t f, uint32_t arg, uint32_t registeroffset,
153+
uint32_t value);
154+
#endif
147155

148156
void mcfg_addr_to_entries(ACPI_TABLE_MCFG *mcfg, ACPI_MCFG_ALLOCATION **entries, uint64_t *num) {
149157
ACPI_MCFG_ALLOCATION *entry =
150158
(ACPI_MCFG_ALLOCATION *)((uint64_t)mcfg + sizeof(ACPI_TABLE_MCFG));
151159
int length = mcfg->Header.Length - sizeof(ACPI_TABLE_MCFG);
152-
*num = length / sizeof(ACPI_MCFG_ALLOCATION);
160+
if (length < 0) {
161+
*num = 0;
162+
return;
163+
}
164+
*num = (uint64_t)length / sizeof(ACPI_MCFG_ALLOCATION);
165+
if (*num > PCI_MCFG_MAX_ENTRIES_LEN) {
166+
*num = PCI_MCFG_MAX_ENTRIES_LEN;
167+
}
153168
for (uint64_t i = 0; i < *num; i++) {
154169
entries[i] = entry + i;
155170
}
156171
}
157172

158-
uint64_t get_device_mmio_physical_address(uint16_t segment_group, uint8_t bus, uint8_t device,
159-
uint8_t function) {
173+
static bool mcfg_find_entry(uint16_t segment_group, uint8_t bus, uint64_t *index_out) {
160174
for (uint64_t i = 0; i < mcfg_entries_len; i++) {
161-
if (mcfg_entries[i]->PciSegment == segment_group) {
162-
return mcfg_entries[i]->Address +
163-
(((uint64_t)bus - (uint64_t)mcfg_entries[i]->StartBusNumber) << 20) +
164-
((uint64_t)device << 15) + ((uint64_t)function << 12);
175+
if (mcfg_entries[i]->PciSegment != segment_group) { continue; }
176+
if (mcfg_entries[i]->Address == 0) { continue; }
177+
if (bus < mcfg_entries[i]->StartBusNumber || bus > mcfg_entries[i]->EndBusNumber) {
178+
continue;
165179
}
180+
if (index_out) { *index_out = i; }
181+
return true;
166182
}
167-
return 0;
183+
return false;
184+
}
185+
186+
uint64_t get_device_mmio_physical_address(uint16_t segment_group, uint8_t bus, uint8_t device,
187+
uint8_t function) {
188+
uint64_t idx;
189+
if (!mcfg_find_entry(segment_group, bus, &idx)) { return 0; }
190+
return mcfg_entries[idx]->Address +
191+
(((uint64_t)bus - (uint64_t)mcfg_entries[idx]->StartBusNumber) << 20) +
192+
((uint64_t)device << 15) + ((uint64_t)function << 12);
168193
}
169194

170195
uint64_t get_mmio_address(uint32_t pci_address, uint16_t offset) {
196+
if (!pci_use_mcfg) { return 0; }
197+
171198
uint16_t segment = (pci_address >> 16) & 0xFFFF;
172199
uint8_t bus = (pci_address >> 8) & 0xFF;
173200
uint8_t device = (pci_address >> 3) & 0x1F;
174201
uint8_t function = pci_address & 0x07;
175202

176-
uint64_t phys = get_device_mmio_physical_address(segment, bus, device, function);
177-
if (phys == 0) { return 0; }
203+
uint64_t idx;
204+
if (!mcfg_find_entry(segment, bus, &idx)) { return 0; }
205+
206+
uint64_t bus_off =
207+
(((uint64_t)bus - (uint64_t)mcfg_entries[idx]->StartBusNumber) << 20) +
208+
((uint64_t)device << 15) + ((uint64_t)function << 12);
209+
210+
if (mcfg_virt_bases[idx] != 0) {
211+
return mcfg_virt_bases[idx] + bus_off + offset;
212+
}
213+
214+
uint64_t phys = mcfg_entries[idx]->Address + bus_off;
178215
uint64_t virt = (uint64_t)phys_to_virt(phys);
179216
page_map_range(get_kernel_pagedir(), virt, phys, PAGE_SIZE * 4, KERNEL_PTE_FLAGS);
180-
181217
return virt + offset;
182218
}
183219

@@ -190,14 +226,25 @@ uint32_t segment_bus_device_functon_to_pci_address(uint16_t segment, uint8_t bus
190226
uint32_t pci_read(uint32_t b, uint32_t d, uint32_t f, uint32_t s, uint32_t offset) {
191227
uint32_t pci_address = segment_bus_device_functon_to_pci_address(s, b, d, f);
192228
uint64_t mmio_address = get_mmio_address(pci_address, offset);
193-
if (mmio_address == 0) { printk("Cannot read pci: failed to get mmio address\n"); }
229+
if (mmio_address == 0) {
230+
#if defined(__x86_64__) || defined(__amd64__)
231+
return pci_read0(b, d, f, s, offset);
232+
#else
233+
return 0xFFFFFFFFU;
234+
#endif
235+
}
194236
return *(volatile uint32_t *)mmio_address;
195237
}
196238

197239
void pci_write(uint32_t b, uint32_t d, uint32_t f, uint32_t s, uint32_t offset, uint32_t value) {
198240
uint32_t pci_address = segment_bus_device_functon_to_pci_address(s, b, d, f);
199241
uint64_t mmio_address = get_mmio_address(pci_address, offset);
200-
if (mmio_address == 0) { printk("Cannot write pci: failed to get mmio address\n"); }
242+
if (mmio_address == 0) {
243+
#if defined(__x86_64__) || defined(__amd64__)
244+
pci_write0(b, d, f, s, offset, value);
245+
#endif
246+
return;
247+
}
201248
*(volatile uint32_t *)mmio_address = value;
202249
}
203250

@@ -279,22 +326,19 @@ pci_device_t *pci_find_bdfs(uint8_t bus, uint8_t slot, uint8_t func, uint16_t se
279326
}
280327

281328
void pci_scan_function(uint16_t segment_group, uint8_t bus, uint8_t device, uint8_t function) {
282-
uint32_t pci_address =
283-
segment_bus_device_functon_to_pci_address(segment_group, bus, device, function);
284-
285-
uint64_t id_mmio_addr = get_mmio_address(pci_address, 0x00);
286-
uint16_t vendor_id = *(volatile uint16_t *)id_mmio_addr;
329+
uint32_t id_value = pci_read(bus, device, function, segment_group, 0x00);
330+
uint16_t vendor_id = (uint16_t)(id_value & 0xFFFF);
287331
if (vendor_id == 0xFFFF) { return; }
288-
uint16_t device_id = *(volatile uint16_t *)(id_mmio_addr + 2);
332+
uint16_t device_id = (uint16_t)(id_value >> 16);
289333

290-
uint64_t field_mmio_addr = get_mmio_address(pci_address, PCI_CONF_REVISION);
291-
uint8_t device_revision = EXPORT_BYTE(*(volatile uint8_t *)field_mmio_addr, true);
292-
uint8_t device_class = *((uint8_t *)field_mmio_addr + 3);
293-
uint8_t device_subclass = *((uint8_t *)field_mmio_addr + 2);
294-
uint8_t device_interface = *((uint8_t *)field_mmio_addr + 1);
334+
uint32_t class_reg = pci_read(bus, device, function, segment_group, PCI_CONF_REVISION);
335+
uint8_t device_revision = (uint8_t)(class_reg & 0xFF);
336+
uint8_t device_interface = (uint8_t)((class_reg >> 8) & 0xFF);
337+
uint8_t device_subclass = (uint8_t)((class_reg >> 16) & 0xFF);
338+
uint8_t device_class = (uint8_t)((class_reg >> 24) & 0xFF);
295339

296-
uint64_t header_type_mmio_addr = get_mmio_address(pci_address, 0x0c);
297-
uint8_t header_type = (*((uint8_t *)header_type_mmio_addr + 2)) & 0x7F;
340+
uint32_t header_reg = pci_read(bus, device, function, segment_group, 0x0c);
341+
uint8_t header_type = (uint8_t)((header_reg >> 16) & 0x7F);
298342

299343
pci_device_t *pci_device = (pci_device_t *)malloc(sizeof(pci_device_t));
300344
memset(pci_device, 0, sizeof(pci_device_t));
@@ -462,9 +506,8 @@ void pci_scan_function(uint16_t segment_group, uint8_t bus, uint8_t device, uint
462506
void pci_scan_bus(uint16_t segment_group, uint8_t bus) {
463507
for (int i = 0; i < 32; i++) {
464508
pci_scan_function(segment_group, bus, i, 0);
465-
uint32_t pci_address = segment_bus_device_functon_to_pci_address(segment_group, bus, i, 0);
466-
uint64_t mmio_addr = get_mmio_address(pci_address, 0x0c);
467-
if (*(volatile uint32_t *)mmio_addr & (1UL << 23)) {
509+
uint32_t header_reg = pci_read(bus, i, 0, segment_group, 0x0c);
510+
if (header_reg != 0xFFFFFFFF && (header_reg & (1UL << 23))) {
468511
for (int j = 1; j < 8; j++) {
469512
pci_scan_function(segment_group, bus, i, j);
470513
}
@@ -474,9 +517,8 @@ void pci_scan_bus(uint16_t segment_group, uint8_t bus) {
474517

475518
void pci_scan_segment(uint16_t segment_group) {
476519
pci_scan_bus(segment_group, 0);
477-
uint32_t pci_address = segment_bus_device_functon_to_pci_address(segment_group, 0, 0, 0);
478-
uint64_t mmio_addr = get_mmio_address(pci_address, 0x0c);
479-
if (*(volatile uint32_t *)mmio_addr & (1UL << 23)) {
520+
uint32_t header_reg = pci_read(0, 0, 0, segment_group, 0x0c);
521+
if (header_reg != 0xFFFFFFFF && (header_reg & (1UL << 23))) {
480522
for (int i = 1; i < 8; i++) {
481523
pci_scan_bus(segment_group, i);
482524
}
@@ -486,17 +528,50 @@ void pci_scan_segment(uint16_t segment_group) {
486528
void pci_init() {
487529
ACPI_TABLE_MCFG *mcfg = NULL;
488530
ACPI_STATUS status = AcpiGetTable(ACPI_SIG_MCFG, 1, (ACPI_TABLE_HEADER **)&mcfg);
489-
490531
if (ACPI_FAILURE(status)) {
491532
kwarn("MCFG table not found (System switch to Legacy PCI model).");
492533
arch_pci_legacy_enum();
493534
return;
494535
}
495536

496537
mcfg_addr_to_entries(mcfg, mcfg_entries, &mcfg_entries_len);
538+
pci_use_mcfg = (mcfg_entries_len != 0);
539+
if (!pci_use_mcfg) {
540+
kwarn("MCFG table invalid or empty (System switch to Legacy PCI model).");
541+
arch_pci_legacy_enum();
542+
return;
543+
}
544+
545+
bool has_valid_entry = false;
546+
for (uint64_t i = 0; i < mcfg_entries_len; i++) {
547+
if (mcfg_entries[i]->Address == 0) { continue; }
548+
if (mcfg_entries[i]->EndBusNumber < mcfg_entries[i]->StartBusNumber) { continue; }
549+
has_valid_entry = true;
550+
break;
551+
}
552+
553+
if (!has_valid_entry) {
554+
kwarn("MCFG entries invalid (System switch to Legacy PCI model).");
555+
pci_use_mcfg = false;
556+
arch_pci_legacy_enum();
557+
return;
558+
}
497559

498560
for (uint64_t i = 0; i < mcfg_entries_len; i++) {
499561
uint16_t segment_group = mcfg_entries[i]->PciSegment;
500-
pci_scan_segment(segment_group);
562+
uint8_t start_bus = mcfg_entries[i]->StartBusNumber;
563+
uint8_t end_bus = mcfg_entries[i]->EndBusNumber;
564+
if (mcfg_entries[i]->Address == 0) { continue; }
565+
if (end_bus < start_bus) { continue; }
566+
uint64_t size = ((uint64_t)(end_bus - start_bus + 1)) << 20;
567+
uint64_t virt = (uint64_t)phys_to_virt(mcfg_entries[i]->Address);
568+
page_map_range(get_kernel_pagedir(), virt, mcfg_entries[i]->Address, size,
569+
KERNEL_PTE_FLAGS);
570+
mcfg_virt_bases[i] = virt;
571+
kinfo("MCFG map: seg=%u bus=%u-%u phys=%#llx virt=%#llx size=%#llx",
572+
segment_group, start_bus, end_bus, mcfg_entries[i]->Address, virt, size);
573+
for (uint16_t bus = start_bus; bus <= end_bus; bus++) {
574+
pci_scan_bus(segment_group, (uint8_t)bus);
575+
}
501576
}
502577
}

0 commit comments

Comments
 (0)