Patch by Dustin Howett (GSOC): Move ACPI probing out of the

bootloader's smp init and into its own unit.
ACPI tables can now generally be found with acpi_find_table(signature).


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26538 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stefano Ceccherini
2008-07-21 07:13:51 +00:00
parent 3ef0397bc5
commit 85f2668898
10 changed files with 207 additions and 118 deletions
@@ -1,9 +1,10 @@
/*
* Copyright 2008, Dustin Howett, dustin.howett@gmail.com. All rights reserved.
* Copyright 2007, Michael Lotz, mmlr@mlotz.ch. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _KERNEL_ARCH_x86_SMP_ACPI_H
#define _KERNEL_ARCH_x86_SMP_ACPI_H
#ifndef _KERNEL_ARCH_x86_ARCH_ACPI_H
#define _KERNEL_ARCH_x86_ARCH_ACPI_H
#define ACPI_RSDP_SIGNATURE "RSD PTR "
#define ACPI_RSDT_SIGNATURE "RSDT"
@@ -11,7 +12,7 @@
#define ACPI_LOCAL_APIC_ENABLED 0x01
struct acpi_rsdp {
typedef struct acpi_rsdp {
char signature[8]; /* "RSD PTR " including blank */
uint8 checksum; /* checksum of bytes 0-19 (per ACPI 1.0) */
char oem_id[6]; /* not null terminated */
@@ -21,9 +22,9 @@ struct acpi_rsdp {
uint64 xsdt_address; /* 64bit physical memory address of XSDT */
uint8 extended_checksum; /* including entire table */
uint8 reserved[3];
} _PACKED;
} _PACKED acpi_rsdp;
struct acpi_descriptor_header {
typedef struct acpi_descriptor_header {
char signature[4]; /* table identifier as ASCII string */
uint32 length; /* length in bytes of the entire table */
uint8 revision;
@@ -33,39 +34,39 @@ struct acpi_descriptor_header {
uint32 oem_revision; /* oem supplied revision number */
char creator_id[4]; /* creator / asl compiler id */
uint32 creator_revision; /* compiler revision */
} _PACKED;
} _PACKED acpi_descriptor_header;
struct acpi_madt {
acpi_descriptor_header header; /* "APIC" signature */
typedef struct acpi_madt {
acpi_descriptor_header header; /* "APIC" signature */
uint32 local_apic_address; /* physical address for local CPUs APICs */
uint32 flags;
} _PACKED;
} _PACKED acpi_madt;
enum {
ACPI_MADT_LOCAL_APIC = 0,
ACPI_MADT_IO_APIC = 1
};
struct acpi_apic {
typedef struct acpi_apic {
uint8 type;
uint8 length;
} _PACKED;
} _PACKED acpi_apic;
struct acpi_local_apic {
typedef struct acpi_local_apic {
uint8 type; /* 0 = processor local APIC */
uint8 length; /* 8 bytes */
uint8 acpi_processor_id;
uint8 apic_id; /* the id of this APIC */
uint32 flags; /* 1 = enabled */
} _PACKED;
} _PACKED acpi_local_apic;
struct acpi_io_apic {
typedef struct acpi_io_apic {
uint8 type; /* 1 = I/O APIC */
uint8 length; /* 12 bytes */
uint8 io_apic_id; /* the id of this APIC */
uint8 reserved;
uint32 io_apic_address; /* phyisical address of I/O APIC */
uint32 interrupt_base; /* global system interrupt base */
} _PACKED;
} _PACKED acpi_io_apic;
#endif /* _KERNEL_ARCH_x86_SMP_ACPI_H */
#endif /* _KERNEL_ARCH_x86_ARCH_ACPI_H */
@@ -1,12 +1,13 @@
/*
* Copyright 2008, Dustin Howett, dustin.howett@gmail.com. All rights reserved.
* Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
* Distributed under the terms of the NewOS License.
*/
#ifndef _KERNEL_ARCH_x86_SMP_APIC_H
#define _KERNEL_ARCH_x86_SMP_APIC_H
#ifndef _KERNEL_ARCH_x86_ARCH_APIC_H
#define _KERNEL_ARCH_x86_ARCH_APIC_H
#define MP_FLOATING_SIGNATURE '_PM_'
#define MP_CONFIG_TABLE_SIGNATURE 'PCMP'
@@ -191,4 +192,4 @@ enum {
MP_INTR_TYPE_ExtINT,
};
#endif /* _KERNEL_ARCH_x86_SMP_APIC_H */
#endif /* _KERNEL_ARCH_x86_ARCH_APIC_H */
@@ -29,6 +29,7 @@ KernelMergeObject boot_platform_bios_ia32.o :
menu.cpp
mmu.cpp
cpu.cpp
acpi.cpp
smp.cpp
smp_trampoline.S
support.S
+111
View File
@@ -0,0 +1,111 @@
/*
* Copyright 2008, Dustin Howett, [email protected]. All rights reserved.
* Copyright 2007, Michael Lotz, [email protected]
* Copyright 2004-2005, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License.
*
* Copyright 2001, Travis Geiselbrecht. All rights reserved.
* Distributed under the terms of the NewOS License.
*/
#include "acpi.h"
#include "mmu.h"
#include <KernelExport.h>
#include <arch/x86/arch_acpi.h>
#include <string.h>
//#define TRACE_ACPI
#ifdef TRACE_ACPI
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
static struct scan_spots_struct acpi_scan_spots[] = {
{ 0x0, 0x400, 0x400 - 0x0 },
{ 0xe0000, 0x100000, 0x100000 - 0xe0000 },
{ 0, 0, 0 }
};
static acpi_descriptor_header *sAcpiRsdt; // System Description Table
static status_t
acpi_check_rsdt(acpi_rsdp *rsdp)
{
TRACE(("acpi: found rsdp at %p oem id: %.6s\n", rsdp, rsdp->oem_id));
TRACE(("acpi: rsdp points to rsdt at 0x%lx\n", rsdp->rsdt_address));
// map and validate the root system description table
acpi_descriptor_header *rsdt
= (acpi_descriptor_header *)mmu_map_physical_memory(
rsdp->rsdt_address, B_PAGE_SIZE, kDefaultPageFlags);
if (!rsdt || strncmp(rsdt->signature, ACPI_RSDT_SIGNATURE, 4) != 0) {
TRACE(("acpi: invalid root system description table\n"));
return B_ERROR;
}
sAcpiRsdt = rsdt;
return B_OK;
}
acpi_descriptor_header *
acpi_find_table(char *signature)
{
if (sAcpiRsdt == NULL) {
return NULL;
}
// Tried to keep numEntries a static variable; kept turning up 0 on table scan
// TODO: This calculates numEntries for every acpi probe.
int32 numEntries = (sAcpiRsdt->length - sizeof(acpi_descriptor_header)) / 4;
if (numEntries <= 0) {
TRACE(("acpi: root system description table is empty\n"));
return NULL;
}
TRACE(("acpi: searching %ld entries for table '%.4s'\n", numEntries, signature));
uint32 *pointer = (uint32 *)((uint8 *)sAcpiRsdt + sizeof(acpi_descriptor_header));
for (int32 j = 0; j < numEntries; j++, pointer++) {
acpi_descriptor_header *header = (acpi_descriptor_header *)
mmu_map_physical_memory(*pointer, B_PAGE_SIZE, kDefaultPageFlags);
if (!header || strncmp(header->signature, signature, 4) != 0) {
// not interesting for us
TRACE(("acpi: Looking for '%.4s'. Skipping '%.4s'\n", signature, header->signature));
continue;
}
TRACE(("acpi: Found '%.4s' @ %p\n", signature));
return header;
}
// If we didn't find the table, return NULL.
return NULL;
}
void
acpi_init(void)
{
acpi_rsdp *rsdp = NULL;
// Try to find the ACPI RSDP.
for (int32 i = 0; acpi_scan_spots[i].length > 0; i++) {
char *pointer;
TRACE(("acpi_init: entry base 0x%lx, limit 0x%lx\n", acpi_scan_spots[i].start,
acpi_scan_spots[i].stop));
for (pointer = (char *)acpi_scan_spots[i].start;
(uint32)pointer < acpi_scan_spots[i].stop; pointer += 16) {
if (strncmp(pointer, ACPI_RSDP_SIGNATURE, 8) == 0) {
TRACE(("acpi_init: found ACPI RSDP signature at %p\n", pointer));
rsdp = (acpi_rsdp *)pointer;
}
}
if (acpi_check_rsdt(rsdp) == B_OK)
break;
}
}
+28
View File
@@ -0,0 +1,28 @@
/*
* Copyright 2005, Axel Dörfler, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef ACPI_H
#define ACPI_H
#include <SupportDefs.h>
#include <arch/x86/arch_acpi.h>
#ifdef __cplusplus
extern "C" {
#endif
struct scan_spots_struct {
uint32 start;
uint32 stop;
uint32 length;
};
acpi_descriptor_header *acpi_find_table(char *signature);
void acpi_init(void);
#ifdef __cplusplus
}
#endif
#endif /* ACPI_H */
+41 -96
View File
@@ -1,4 +1,5 @@
/*
* Copyright 2008, Dustin Howett, [email protected]. All rights reserved.
* Copyright 2004-2005, Axel Dörfler, [email protected].
* Distributed under the terms of the MIT License.
*
@@ -9,6 +10,7 @@
#include "smp.h"
#include "mmu.h"
#include "acpi.h"
#include <KernelExport.h>
@@ -16,8 +18,8 @@
#include <safemode.h>
#include <boot/stage2.h>
#include <boot/menu.h>
#include <arch/x86/smp_acpi.h>
#include <arch/x86/smp_apic.h>
#include <arch/x86/arch_acpi.h>
#include <arch/x86/arch_apic.h>
#include <arch/x86/arch_system_info.h>
#include <string.h>
@@ -36,24 +38,12 @@ struct gdt_idt_descr {
uint32 *b;
} _PACKED;
struct smp_scan_spots_struct {
uint32 start;
uint32 stop;
uint32 length;
};
static struct smp_scan_spots_struct smp_scan_spots[] = {
static struct scan_spots_struct smp_scan_spots[] = {
{ 0x9fc00, 0xa0000, 0xa0000 - 0x9fc00 },
{ 0xf0000, 0x100000, 0x100000 - 0xf0000 },
{ 0, 0, 0 }
};
static struct smp_scan_spots_struct acpi_scan_spots[] = {
{ 0x0, 0x400, 0x400 - 0x0 },
{ 0xe0000, 0x100000, 0x100000 - 0xe0000 },
{ 0, 0, 0 }
};
extern "C" void execute_n_instructions(int count);
extern "C" void smp_trampoline(void);
@@ -103,21 +93,6 @@ smp_mp_probe(uint32 base, uint32 limit)
}
static acpi_rsdp *
smp_acpi_probe(uint32 base, uint32 limit)
{
TRACE(("smp_acpi_probe: entry base 0x%lx, limit 0x%lx\n", base, limit));
for (char *pointer = (char *)base; (uint32)pointer < limit; pointer += 16) {
if (strncmp(pointer, ACPI_RSDP_SIGNATURE, 8) == 0) {
TRACE(("smp_acpi_probe: found ACPI RSDP signature at %p\n", pointer));
return (acpi_rsdp *)pointer;
}
}
return NULL;
}
static status_t
smp_do_mp_config(mp_floating_struct *floatingStruct)
{
@@ -241,85 +216,59 @@ smp_do_mp_config(mp_floating_struct *floatingStruct)
static status_t
smp_do_acpi_config(acpi_rsdp *rsdp)
smp_do_acpi_config(void)
{
TRACE(("smp: using ACPI to detect MP configuration\n"));
TRACE(("smp: found rsdp at %p oem id: %.6s\n", rsdp, rsdp->oem_id));
TRACE(("smp: rsdp points to rsdt at 0x%lx\n", rsdp->rsdt_address));
// reset CPU count
gKernelArgs.num_cpus = 0;
// map and validate the root system description table
acpi_descriptor_header *rsdt
= (acpi_descriptor_header *)mmu_map_physical_memory(
rsdp->rsdt_address, B_PAGE_SIZE, kDefaultPageFlags);
if (!rsdt || strncmp(rsdt->signature, ACPI_RSDT_SIGNATURE, 4) != 0) {
TRACE(("smp: invalid root system description table\n"));
acpi_madt *madt = (acpi_madt *)acpi_find_table(ACPI_MADT_SIGNATURE);
if (madt == NULL) {
TRACE(("smp: Failed to find MADT!\n"));
return B_ERROR;
}
int32 numEntries = (rsdt->length - sizeof(acpi_descriptor_header)) / 4;
if (numEntries <= 0) {
TRACE(("smp: root system description table is empty\n"));
return B_ERROR;
}
gKernelArgs.arch_args.apic_phys = madt->local_apic_address;
TRACE(("smp: local apic address is 0x%lx\n", madt->local_apic_address));
TRACE(("smp: searching %ld entries for APIC information\n", numEntries));
uint32 *pointer = (uint32 *)((uint8 *)rsdt + sizeof(acpi_descriptor_header));
for (int32 j = 0; j < numEntries; j++, pointer++) {
acpi_descriptor_header *header = (acpi_descriptor_header *)
mmu_map_physical_memory(*pointer, B_PAGE_SIZE, kDefaultPageFlags);
if (!header || strncmp(header->signature, ACPI_MADT_SIGNATURE, 4) != 0) {
// not interesting for us
TRACE(("smp: skipping uninteresting header '%.4s'\n", header->signature));
continue;
}
acpi_madt *madt = (acpi_madt *)header;
gKernelArgs.arch_args.apic_phys = madt->local_apic_address;
TRACE(("smp: local apic address is 0x%lx\n", madt->local_apic_address));
acpi_apic *apic = (acpi_apic *)((uint8 *)madt + sizeof(acpi_madt));
acpi_apic *end = (acpi_apic *)((uint8 *)madt + header->length);
while (apic < end) {
switch (apic->type) {
case ACPI_MADT_LOCAL_APIC:
{
if (gKernelArgs.num_cpus == MAX_BOOT_CPUS) {
TRACE(("smp: already reached maximum boot CPUs (%d)\n", MAX_BOOT_CPUS));
break;
}
acpi_local_apic *localApic = (acpi_local_apic *)apic;
TRACE(("smp: found local APIC with id %u\n", localApic->apic_id));
if ((localApic->flags & ACPI_LOCAL_APIC_ENABLED) == 0) {
TRACE(("smp: APIC is disabled and will not be used\n"));
break;
}
gKernelArgs.arch_args.cpu_apic_id[gKernelArgs.num_cpus] = localApic->apic_id;
gKernelArgs.arch_args.cpu_os_id[localApic->apic_id] = gKernelArgs.num_cpus;
// ToDo: how to find out? putting 0x10 in to indicate a local apic
gKernelArgs.arch_args.cpu_apic_version[gKernelArgs.num_cpus] = 0x10;
gKernelArgs.num_cpus++;
acpi_apic *apic = (acpi_apic *)((uint8 *)madt + sizeof(acpi_madt));
acpi_apic *end = (acpi_apic *)((uint8 *)madt + madt->header.length);
while (apic < end) {
switch (apic->type) {
case ACPI_MADT_LOCAL_APIC:
{
if (gKernelArgs.num_cpus == MAX_BOOT_CPUS) {
TRACE(("smp: already reached maximum boot CPUs (%d)\n", MAX_BOOT_CPUS));
break;
}
case ACPI_MADT_IO_APIC: {
acpi_io_apic *ioApic = (acpi_io_apic *)apic;
TRACE(("smp: found io APIC with id %u and address 0x%lx\n",
ioApic->io_apic_id, ioApic->io_apic_address));
gKernelArgs.arch_args.ioapic_phys = ioApic->io_apic_address;
acpi_local_apic *localApic = (acpi_local_apic *)apic;
TRACE(("smp: found local APIC with id %u\n", localApic->apic_id));
if ((localApic->flags & ACPI_LOCAL_APIC_ENABLED) == 0) {
TRACE(("smp: APIC is disabled and will not be used\n"));
break;
}
gKernelArgs.arch_args.cpu_apic_id[gKernelArgs.num_cpus] = localApic->apic_id;
gKernelArgs.arch_args.cpu_os_id[localApic->apic_id] = gKernelArgs.num_cpus;
// ToDo: how to find out? putting 0x10 in to indicate a local apic
gKernelArgs.arch_args.cpu_apic_version[gKernelArgs.num_cpus] = 0x10;
gKernelArgs.num_cpus++;
break;
}
apic = (acpi_apic *)((uint8 *)apic + apic->length);
case ACPI_MADT_IO_APIC: {
acpi_io_apic *ioApic = (acpi_io_apic *)apic;
TRACE(("smp: found io APIC with id %u and address 0x%lx\n",
ioApic->io_apic_id, ioApic->io_apic_address));
gKernelArgs.arch_args.ioapic_phys = ioApic->io_apic_address;
break;
}
}
if (gKernelArgs.num_cpus > 0)
break;
apic = (acpi_apic *)((uint8 *)apic + apic->length);
}
return gKernelArgs.num_cpus > 0 ? B_OK : B_ERROR;
@@ -609,12 +558,8 @@ smp_init(void)
// first try to find ACPI tables to get MP configuration as it handles
// physical as well as logical MP configurations as in multiple cpus,
// multiple cores or hyper threading.
for (int32 i = 0; acpi_scan_spots[i].length > 0; i++) {
acpi_rsdp *rsdp = smp_acpi_probe(smp_scan_spots[i].start,
smp_scan_spots[i].stop);
if (rsdp != NULL && smp_do_acpi_config(rsdp) == B_OK)
return;
}
if (smp_do_acpi_config() == B_OK)
return;
// then try to find MPS tables and do configuration based on them
for (int32 i = 0; smp_scan_spots[i].length > 0; i++) {
@@ -10,6 +10,7 @@
#include "cpu.h"
#include "mmu.h"
#include "smp.h"
#include "acpi.h"
#include "keyboard.h"
#include "bios.h"
@@ -132,6 +133,7 @@ _start(void)
serial_enable();
apm_init();
acpi_init();
smp_init();
main(&args);
}
+1 -1
View File
@@ -22,7 +22,7 @@
#include <arch/user_debugger.h>
#include <arch/vm.h>
#include <arch/x86/smp_apic.h>
#include <arch/x86/arch_apic.h>
#include <arch/x86/descriptors.h>
#include <arch/x86/vm86.h>
+1 -1
View File
@@ -20,7 +20,7 @@
#include <timer.h>
#include <arch/x86/smp_priv.h>
#include <arch/x86/smp_apic.h>
#include <arch/x86/arch_apic.h>
#include <arch/x86/timer.h>
#include <string.h>
+1 -1
View File
@@ -11,7 +11,7 @@
#include <arch/x86/timer.h>
#include <int.h>
#include <arch/x86/smp_apic.h>
#include <arch/x86/arch_apic.h>
#include <arch/cpu.h>
#include <arch/smp.h>