1/** 2 * \file 3 * \brief PCI 4 */ 5 6/* 7 * Copyright (c) 2007, 2008, 2009, 2011, 2016 ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <barrelfish/barrelfish.h> 16#include <barrelfish/capabilities.h> 17#include <barrelfish/nameservice_client.h> 18#include <stdio.h> 19#include <stdlib.h> 20#include <mm/mm.h> 21#include <if/monitor_blocking_defs.h> 22 23#include <octopus/octopus.h> 24#include <skb/skb.h> 25#include <hw_records.h> 26 27#include "acpi_debug.h" 28#include "acpi_shared.h" 29#include "acpi_allocators.h" 30#include "acpidump.h" 31 32 33 34uintptr_t my_hw_id; 35 36 37static errval_t setup_skb_info(void) 38{ 39 skb_execute("[pci_queries]."); 40 errval_t err = skb_read_error_code(); 41 if (err_is_fail(err)) { 42 ACPI_DEBUG("\npcimain.c: Could not load pci_queries.pl.\n" 43 "SKB returned: %s\nSKB error: %s\n", 44 skb_get_output(), skb_get_error_output()); 45 return err; 46 } 47 48 skb_add_fact("mem_region_type(%d,ram).", RegionType_Empty); 49 skb_add_fact("mem_region_type(%d,roottask).", RegionType_RootTask); 50 skb_add_fact("mem_region_type(%d,phyaddr).", RegionType_PhyAddr); 51 skb_add_fact("mem_region_type(%d,multiboot_module).", RegionType_Module); 52 skb_add_fact("mem_region_type(%d,platform_data).", RegionType_PlatformData); 53 54 55 return acpi_arch_skb_set_info(); 56} 57 58extern int ApDumpAllTables (void); 59static void wait_for_iommu(void) 60{ 61 errval_t err; 62 char**names = NULL; 63 size_t len = 0; 64 65 err = oct_get_names(&names, &len, HW_PCI_IOMMU_RECORD_REGEX); 66 if (err_is_fail(err)) { 67 if (err == OCT_ERR_NO_RECORD) { 68 debug_printf("No Iommus available, continue withouth waiting\n"); 69 return; 70 } 71 goto out; 72 } 73 74 if (len > 0) { 75 76 char* key; 77 char* record; 78 uint64_t type, flags, segment, address, idx; 79 err = oct_get(&record, names[0]); 80 if (err_is_fail(err)) { 81 goto out; 82 } 83 84 err = oct_read(record, "%s { " HW_PCI_IOMMU_RECORD_FIELDS_READ " }", 85 &key, &idx, &type, &flags, &segment, &address); 86 if (err_is_fail(err)) { 87 goto out; 88 } 89 90 if (type == HW_PCI_IOMMU_DMAR_FAIL) { 91 debug_printf("Reading DMAR failed, not waiting for iommus \n"); 92 goto out; 93 } 94 95 debug_printf("Waiting for all iommus to start up (num_iommu=%zu) \n", len); 96 err = oct_barrier_enter("barrier.iommu", &record ,2); 97 if (err_is_fail(err)) { 98 goto out; 99 } 100 if (record) { 101 free(record); 102 } 103 } 104 105out: 106 oct_free_names(names, len); 107} 108 109int main(int argc, char *argv[]) 110{ 111 errval_t err; 112 113 // Parse CMD Arguments 114 bool got_apic_id = false; 115 bool do_video_init = false; 116 bool ignore_irq_override = false; 117 bool dump_acpi_tables = false; 118 119 for (int i = 1; i < argc; i++) { 120 if(sscanf(argv[i], "apicid=%" PRIuPTR, &my_hw_id) == 1) { 121 got_apic_id = true; 122 } else if (strcmp(argv[i], "video_init") == 0) { 123 do_video_init = true; 124 } else if (strncmp(argv[i], "dump_tables", strlen("dump_tables")) == 0) { 125 dump_acpi_tables = true; 126 } else if (strncmp(argv[i], "ignore_irq_override", strlen("ignore_irq_override")) == 0) { 127 ignore_irq_override = true; 128 } 129 130 } 131 132 if(got_apic_id == false) { 133 fprintf(stderr, "Usage: %s APIC_ID\n", argv[0]); 134 fprintf(stderr, "Wrong monitor version?\n"); 135 return EXIT_FAILURE; 136 } 137 138 err = oct_init(); 139 if (err_is_fail(err)) { 140 USER_PANIC_ERR(err, "Initialize dist"); 141 } 142 143 //connect to the SKB 144 ACPI_DEBUG("acpi: connecting to the SKB...\n"); 145 err = skb_client_connect(); 146 if (err_is_fail(err)) { 147 USER_PANIC_ERR(err, "Connecting to SKB failed."); 148 } 149 150 ACPI_DEBUG("acpi: connecting to the SKB...\n"); 151 err = setup_skb_info(); 152 if (err_is_fail(err)) { 153 USER_PANIC_ERR(err, "Populating SKB failed."); 154 } 155 156 err = acpi_allocators_init(); 157 if (err_is_fail(err)) { 158 USER_PANIC_ERR(err, "Init memory allocator"); 159 } 160 161 err = acpi_arch_copy_bios_mem(); 162 if (err_is_fail(err)) { 163 USER_PANIC_ERR(err, "Copy BIOS Memory"); 164 } 165 166 167 if (dump_acpi_tables) { 168 debug_printf("DUMPING ACPI TABLES.\n"); 169 debug_printf("======================================\n"); 170 AcpiOsInitialize (); 171 Gbl_OutputFile = stdout; 172 ApDumpAllTables (); 173 debug_printf("======================================\n"); 174 } 175 176 177 178 err = acpi_arch_load_irq_routing_new(); 179 if (err_is_fail(err)) { 180 USER_PANIC_ERR(err, "load irq routing new."); 181 } 182 183 int r = init_acpi(); 184 assert(r == 0); 185 186 buttons_init(); 187 188 if (do_video_init) { 189 acpi_arch_video_init(); 190 } 191 192 start_service(); 193 194 wait_for_iommu(); 195 196 // synchronize ACPI/KALUGA/PCI 197 char* record = NULL; 198 debug_printf("barrier.pci.bridges\n"); 199 err = oct_barrier_enter("barrier.pci.bridges", &record, 3); 200 if (err_is_fail(err)) { 201 USER_PANIC_ERR(err, "Could not wait for PCI Barrier 'barrier.pci.bridges'\n"); 202 } 203 204 err = acpi_interrupts_arch_setup(); 205 if (err_is_fail(err)) { 206 USER_PANIC_ERR(err, "setup skb irq controllers"); 207 } 208 209 if(ignore_irq_override){ 210 err = skb_execute("retractall(interrupt_override(_,_,_,_))."); 211 if(err_is_fail(err)){ 212 DEBUG_SKB_ERR(err, "couldnt remove interrupt overrides"); 213 } 214 } 215 216 ACPI_DEBUG("####################### Entering message handler loop \n"); 217 messages_handler_loop(); 218} 219