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/BhyveFwCtlLib.h>
13 #include <Library/MemoryAllocationLib.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
78 IoApic
->Type
= EFI_ACPI_1_0_IO_APIC
;
79 IoApic
->Length
= sizeof (*IoApic
);
80 IoApic
->IoApicId
= (UINT8
)CpuCount
;
81 IoApic
->Reserved
= EFI_ACPI_RESERVED_BYTE
;
82 IoApic
->IoApicAddress
= 0xFEC00000;
83 IoApic
->SystemVectorBase
= 0x00000000;
87 // IRQ0 (8254 Timer) => IRQ2 (PIC) Interrupt Source Override Structure
90 Iso
->Type
= EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE
;
91 Iso
->Length
= sizeof (*Iso
);
92 Iso
->Bus
= 0x00; // ISA
93 Iso
->Source
= 0x00; // IRQ0
94 Iso
->GlobalSystemInterruptVector
= 0x00000002;
95 Iso
->Flags
= 0x0000; // Conforms to specs of the bus
98 ASSERT ((UINTN
)((UINT8
*)Ptr
- (UINT8
*)Madt
) == NewBufferSize
);
99 Status
= InstallAcpiTable (AcpiProtocol
, Madt
, NewBufferSize
, TableKey
);
108 BhyveInstallAcpiTable (
109 IN EFI_ACPI_TABLE_PROTOCOL
*AcpiProtocol
,
110 IN VOID
*AcpiTableBuffer
,
111 IN UINTN AcpiTableBufferSize
,
115 EFI_ACPI_DESCRIPTION_HEADER
*Hdr
;
116 EFI_ACPI_TABLE_INSTALL_ACPI_TABLE TableInstallFunction
;
118 Hdr
= (EFI_ACPI_DESCRIPTION_HEADER
*)AcpiTableBuffer
;
119 switch (Hdr
->Signature
) {
120 case EFI_ACPI_1_0_APIC_SIGNATURE
:
121 TableInstallFunction
= BhyveInstallAcpiMadtTable
;
124 TableInstallFunction
= InstallAcpiTable
;
127 return TableInstallFunction (