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