2 * Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
3 * Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
4 * Copyright (C) 2012, Red Hat, Inc.
5 * Copyright (c) 2014, Pluribus Networks, Inc.
7 * SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "AcpiPlatform.h"
11 #include <Library/BaseMemoryLib.h>
12 #include <Library/MemoryAllocationLib.h>
13 #include <Library/BhyveFwCtlLib.h>
18 BhyveInstallAcpiMadtTable (
19 IN EFI_ACPI_TABLE_PROTOCOL
*AcpiProtocol
,
20 IN VOID
*AcpiTableBuffer
,
21 IN UINTN AcpiTableBufferSize
,
28 EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER
*Madt
;
29 EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE
*LocalApic
;
30 EFI_ACPI_1_0_IO_APIC_STRUCTURE
*IoApic
;
31 EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE
*Iso
;
36 ASSERT (AcpiTableBufferSize
>= sizeof (EFI_ACPI_DESCRIPTION_HEADER
));
38 // Query the host for the number of vCPUs
40 cSize
= sizeof(CpuCount
);
41 if (BhyveFwCtlGet ("hw.ncpu", &CpuCount
, &cSize
) == RETURN_SUCCESS
) {
42 DEBUG ((DEBUG_INFO
, "Retrieved CpuCount %d\n", CpuCount
));
43 ASSERT (CpuCount
>= 1);
45 DEBUG ((DEBUG_INFO
, "CpuCount retrieval error\n"));
49 NewBufferSize
= 1 * sizeof (*Madt
) +
50 CpuCount
* sizeof (*LocalApic
) +
51 1 * sizeof (*IoApic
) +
54 Madt
= AllocatePool (NewBufferSize
);
56 return EFI_OUT_OF_RESOURCES
;
59 CopyMem (&(Madt
->Header
), AcpiTableBuffer
, sizeof (EFI_ACPI_DESCRIPTION_HEADER
));
60 Madt
->Header
.Length
= (UINT32
) NewBufferSize
;
61 Madt
->LocalApicAddress
= 0xFEE00000;
62 Madt
->Flags
= EFI_ACPI_1_0_PCAT_COMPAT
;
66 for (Loop
= 0; Loop
< CpuCount
; ++Loop
) {
67 LocalApic
->Type
= EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC
;
68 LocalApic
->Length
= sizeof (*LocalApic
);
69 LocalApic
->AcpiProcessorId
= (UINT8
) Loop
;
70 LocalApic
->ApicId
= (UINT8
) Loop
;
71 LocalApic
->Flags
= 1; // enabled
77 IoApic
->Type
= EFI_ACPI_1_0_IO_APIC
;
78 IoApic
->Length
= sizeof (*IoApic
);
79 IoApic
->IoApicId
= (UINT8
) CpuCount
;
80 IoApic
->Reserved
= EFI_ACPI_RESERVED_BYTE
;
81 IoApic
->IoApicAddress
= 0xFEC00000;
82 IoApic
->SystemVectorBase
= 0x00000000;
86 // IRQ0 (8254 Timer) => IRQ2 (PIC) Interrupt Source Override Structure
89 Iso
->Type
= EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE
;
90 Iso
->Length
= sizeof (*Iso
);
91 Iso
->Bus
= 0x00; // ISA
92 Iso
->Source
= 0x00; // IRQ0
93 Iso
->GlobalSystemInterruptVector
= 0x00000002;
94 Iso
->Flags
= 0x0000; // Conforms to specs of the bus
97 ASSERT ((UINTN
) ((UINT8
*)Ptr
- (UINT8
*)Madt
) == NewBufferSize
);
98 Status
= InstallAcpiTable (AcpiProtocol
, Madt
, NewBufferSize
, TableKey
);
107 BhyveInstallAcpiTable (
108 IN EFI_ACPI_TABLE_PROTOCOL
*AcpiProtocol
,
109 IN VOID
*AcpiTableBuffer
,
110 IN UINTN AcpiTableBufferSize
,
114 EFI_ACPI_DESCRIPTION_HEADER
*Hdr
;
115 EFI_ACPI_TABLE_INSTALL_ACPI_TABLE TableInstallFunction
;
117 Hdr
= (EFI_ACPI_DESCRIPTION_HEADER
*) AcpiTableBuffer
;
118 switch (Hdr
->Signature
) {
119 case EFI_ACPI_1_0_APIC_SIGNATURE
:
120 TableInstallFunction
= BhyveInstallAcpiMadtTable
;
123 TableInstallFunction
= InstallAcpiTable
;
126 return TableInstallFunction (