1 /* 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. 6 * 7 * SPDX-License-Identifier: BSD-2-Clause-Patent 8 */ 9 #include "AcpiPlatform.h" 10 11 #include <Library/BaseMemoryLib.h> 12 #include <Library/BhyveFwCtlLib.h> 13 #include <Library/MemoryAllocationLib.h> 14 15 STATIC 16 EFI_STATUS 17 EFIAPI 18 BhyveInstallAcpiMadtTable ( 19 IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol, 20 IN VOID *AcpiTableBuffer, 21 IN UINTN AcpiTableBufferSize, 22 OUT UINTN *TableKey 23 ) 24 { 25 UINT32 CpuCount; 26 UINTN cSize; 27 UINTN NewBufferSize; 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; 32 VOID *Ptr; 33 UINTN Loop; 34 EFI_STATUS Status; 35 36 ASSERT (AcpiTableBufferSize >= sizeof (EFI_ACPI_DESCRIPTION_HEADER)); 37 38 // Query the host for the number of vCPUs 39 CpuCount = 0; 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); 44 } else { 45 DEBUG ((DEBUG_INFO, "CpuCount retrieval error\n")); 46 CpuCount = 1; 47 } 48 49 NewBufferSize = 1 * sizeof (*Madt) + 50 CpuCount * sizeof (*LocalApic) + 51 1 * sizeof (*IoApic) + 52 1 * sizeof (*Iso); 53 54 Madt = AllocatePool (NewBufferSize); 55 if (Madt == NULL) { 56 return EFI_OUT_OF_RESOURCES; 57 } 58 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; 63 Ptr = Madt + 1; 64 65 LocalApic = Ptr; 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 72 ++LocalApic; 73 } 74 Ptr = LocalApic; 75 76 IoApic = Ptr; 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; 83 Ptr = IoApic + 1; 84 85 // 86 // IRQ0 (8254 Timer) => IRQ2 (PIC) Interrupt Source Override Structure 87 // 88 Iso = Ptr; 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 95 Ptr = Iso + 1; 96 97 ASSERT ((UINTN) ((UINT8 *)Ptr - (UINT8 *)Madt) == NewBufferSize); 98 Status = InstallAcpiTable (AcpiProtocol, Madt, NewBufferSize, TableKey); 99 100 FreePool (Madt); 101 102 return Status; 103 } 104 105 EFI_STATUS 106 EFIAPI 107 BhyveInstallAcpiTable ( 108 IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol, 109 IN VOID *AcpiTableBuffer, 110 IN UINTN AcpiTableBufferSize, 111 OUT UINTN *TableKey 112 ) 113 { 114 EFI_ACPI_DESCRIPTION_HEADER *Hdr; 115 EFI_ACPI_TABLE_INSTALL_ACPI_TABLE TableInstallFunction; 116 117 Hdr = (EFI_ACPI_DESCRIPTION_HEADER*) AcpiTableBuffer; 118 switch (Hdr->Signature) { 119 case EFI_ACPI_1_0_APIC_SIGNATURE: 120 TableInstallFunction = BhyveInstallAcpiMadtTable; 121 break; 122 default: 123 TableInstallFunction = InstallAcpiTable; 124 } 125 126 return TableInstallFunction ( 127 AcpiProtocol, 128 AcpiTableBuffer, 129 AcpiTableBufferSize, 130 TableKey 131 ); 132 } 133