1/** 2 * \file 3 * \brief Code responsible for booting application cores 4 */ 5 6/* 7 * Copyright (c) 2007, 2008, 2009, 2010, 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, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <stdlib.h> 16#include <stdio.h> 17#include <string.h> 18#include <assert.h> 19 20#include <barrelfish/barrelfish.h> 21 22#include <if/octopus_defs.h> 23#include <if/octopus_thc.h> 24 25//Manual channel setup includes 26#include <if/pci_defs.h> 27#include <flounder/flounder_txqueue.h> 28//END 29#include <pci/pci.h> 30 31#include <octopus/octopus.h> 32#include <octopus/trigger.h> 33 34#include <skb/skb.h> 35#include <thc/thc.h> 36 37#include "kaluga.h" 38#include <acpi_client/acpi_client.h> 39 40 41static void pci_change_event(octopus_mode_t mode, const char* device_record, 42 void* st); 43 44static void spawnd_up_event(octopus_mode_t mode, const char* spawnd_record, 45 void* st) 46{ 47 assert(mode & OCT_ON_SET); 48 uint64_t iref; 49 errval_t err = oct_read(spawnd_record, "_ { iref: %d }", &iref); 50 if (err_is_fail(err)) { 51 USER_PANIC_ERR(err, "Failed to read iref from spawnd record?"); 52 } 53 54 // Pass the iref as state, this tells pci_change_event that we 55 // don't need to look again for the spawnd iref 56 // XXX: Pointer 57 pci_change_event(OCT_ON_SET, st, (void*)(uintptr_t)iref); 58} 59 60static errval_t wait_for_spawnd(coreid_t core, void* state) 61{ 62 // Check if the core we're spawning on is already up... 63 struct octopus_thc_client_binding_t* cl = oct_get_thc_client(); 64 errval_t error_code; 65 octopus_trigger_t t = oct_mktrigger(OCT_ERR_NO_RECORD, 66 octopus_BINDING_EVENT, OCT_ON_SET, spawnd_up_event, state); 67 68 // Construct service name 69 static char* format = "spawn.%"PRIuCOREID" { iref: _ }"; 70 int length = snprintf(NULL, 0, format, core); 71 char* query = malloc(length+1); 72 snprintf(query, length+1, format, core); 73 74 errval_t err = cl->call_seq.get(cl, query, t, NULL, NULL, &error_code); 75 free(query); 76 77 if (err_is_fail(err)) { 78 return err; 79 } 80 81 return error_code; 82}; 83 84 85 86static void init_pci_device_handler(struct pci_binding *b, 87 uint32_t class_code, uint32_t sub_class, 88 uint32_t prog_if, uint32_t vendor_id, 89 uint32_t device_id, 90 uint32_t bus, uint32_t dev, uint32_t fun) 91{ 92 93 KALUGA_DEBUG("init_pci_device_handler!!! %"PRIu32", %"PRIu32"," 94 "%"PRIu32"\n", bus, dev, fun); 95 96} 97struct pci_rx_vtbl pci_rx_vtbl = { 98 .init_pci_device_call = init_pci_device_handler 99}; 100 101/** 102 * \brief callback when the PCI client connects 103 * 104 * \param st state pointer 105 * \param err status of the connect 106 * \param _b created PCI binding 107 */ 108static void pci_accept_cb(void *st, 109 errval_t err, 110 struct pci_binding *_b) 111{ 112 KALUGA_DEBUG("connection accepted."); 113 _b->rx_vtbl = pci_rx_vtbl; 114} 115 116const int PCI_CHANNEL_SIZE = 2048; 117 118static errval_t frame_to_pci_frameinfo(struct capref frame, struct pci_frameinfo *fi){ 119 struct frame_identity fid; 120 errval_t err; 121 err = invoke_frame_identify(frame, &fid); 122 if(err_is_fail(err)){ 123 DEBUG_ERR(err, "invoke_frame_identify"); 124 return err; 125 } 126 KALUGA_DEBUG("pci ep frame base=0x%lx, size=0x%lx\n", fid.base, fid.bytes); 127 128 void *msg_buf; 129 err = vspace_map_one_frame(&msg_buf, fid.bytes, frame, 130 NULL, NULL); 131 if (err_is_fail(err)) { 132 DEBUG_ERR(err, "vspace_map_one_frame"); 133 return err; 134 } 135 136 *fi = (struct pci_frameinfo) { 137 .sendbase = (lpaddr_t)msg_buf + PCI_CHANNEL_SIZE, 138 .inbuf = msg_buf, 139 .inbufsize = PCI_CHANNEL_SIZE, 140 .outbuf = ((uint8_t *) msg_buf) + PCI_CHANNEL_SIZE, 141 .outbufsize = PCI_CHANNEL_SIZE 142 }; 143 144 return SYS_ERR_OK; 145} 146 147static errval_t start_pci_ump_accept(struct capref out_frame){ 148 assert(!capref_is_null(out_frame)); 149 150 size_t msg_frame_size; 151 errval_t err; 152 //err = frame_alloc(out_frame, 2 * PCI_CHANNEL_SIZE, &msg_frame_size); 153 err = frame_create(out_frame, 2 * PCI_CHANNEL_SIZE, &msg_frame_size); 154 if (err_is_fail(err)) { 155 DEBUG_ERR(err, "frame_create"); 156 return err; 157 } 158 159 struct pci_frameinfo fi; 160 err = frame_to_pci_frameinfo(out_frame, &fi); 161 if (err_is_fail(err)) { 162 DEBUG_ERR(err, "frame_to_frameinfo"); 163 return err; 164 } 165 166 KALUGA_DEBUG("creating channel on %p\n", fi.inbuf); 167 168 err = pci_accept(&fi, NULL, pci_accept_cb, 169 get_default_waitset(), IDC_EXPORT_FLAGS_DEFAULT); 170 171 if (err_is_fail(err)) { 172 DEBUG_ERR(err, "pci_accept"); 173 return err; 174 } 175 return SYS_ERR_OK; 176} 177 178/** 179 * For device at addr, finds and stores the interrupt arguments and caps 180 * into driver_arg. 181 */ 182static errval_t add_pci_ep(struct pci_addr addr, struct driver_argument 183 *driver_arg) 184{ 185 errval_t err; 186 187 struct capref cap = { 188 .cnode = driver_arg->argnode_ref, 189 .slot = PCIARG_SLOT_PCI_EP 190 }; 191 192 err = start_pci_ump_accept(cap); 193 if(err_is_fail(err)){ 194 DEBUG_ERR(err, "start_pci_ump_accept"); 195 return err; 196 } 197 198 return err; 199}; 200 201/** 202 * For device at addr, finds and stores the interrupt arguments and caps 203 * into driver_arg. 204 */ 205static errval_t add_mem_args(struct pci_addr addr, struct driver_argument 206 *driver_arg, char *debug) 207{ 208 errval_t err; 209 210 struct device_mem *bars; 211 size_t bars_len; 212 213 //NOT VERY BEAUTIFUL 214 static bool pci_init=false; 215 if(!pci_init){ 216 pci_client_connect(); 217 pci_init = true; 218 } 219 // 220 221 err = pci_get_bar_caps_for_device(addr, &bars, &bars_len); 222 if(err_is_fail(err)){ 223 DEBUG_ERR(err, "pci_get_caps_for_device"); 224 return err; 225 } 226 227 // Copy the caps into the argument cnode 228 for(int i=0; i<bars_len; i++){ 229 struct capref cap = { 230 .cnode = driver_arg->argnode_ref, 231 .slot = PCIARG_SLOT_BAR0 + i 232 }; 233 234 if(bars[i].type == 0){ 235 cap_copy(cap, bars[i].frame_cap); 236 } else { 237 return KALUGA_ERR_CAP_ACQUIRE; 238 } 239 240 } 241 242 KALUGA_DEBUG("Received %zu bars\n", bars_len); 243 return SYS_ERR_OK; 244}; 245 246/** 247 * For device at addr, finds and stores the interrupt arguments and caps 248 * into driver_arg. 249 */ 250static errval_t add_int_args(struct pci_addr addr, struct driver_argument *driver_arg, char *debug){ 251 errval_t err = SYS_ERR_OK; 252 char debug_msg[100]; 253 strcpy(debug_msg, "none"); 254 // TODO: every driver should specify the int_model in device_db 255 // until then, we treat them like legacy, so they can use the standard 256 // pci client functionality. 257 if(driver_arg->int_arg.model == INT_MODEL_LEGACY || 258 driver_arg->int_arg.model == INT_MODEL_NONE) { 259 KALUGA_DEBUG("Starting driver with legacy interrupts\n"); 260 // No controller has to instantiated, but we need to get caps for the int numbers 261 //err = skb_execute_query("get_pci_legacy_int_range(addr(%"PRIu8",%"PRIu8",%"PRIu8"),Li)," 262 // "writeln(Li).", addr.bus, addr.device, addr.function); 263 err = skb_execute_query( 264 "add_pci_controller(Lbl, addr(%"PRIu8",%"PRIu8",%"PRIu8"))," 265 "write('\n'), print_int_controller(Lbl).", 266 addr.bus, addr.device, addr.function); 267 if(err_is_fail(err)) DEBUG_SKB_ERR(err, "add/print pci controller"); 268 269 } else if(driver_arg->int_arg.model == INT_MODEL_MSI){ 270 printf("Kaluga: Starting driver with MSI interrupts\n"); 271 printf("Kaluga: MSI interrupts are not supported.\n"); 272 // TODO instantiate controller 273 } else if(driver_arg->int_arg.model == INT_MODEL_MSIX){ 274 KALUGA_DEBUG("Starting driver with MSI-x interrupts\n"); 275 276 // TODO need to determine number of MSIx interrupts 277 278 // Add the pci_msix and msix controller 279 err = skb_execute_query( 280 "add_pci_msix_controller(PciMsixLbl, MsixLbl, addr(%"PRIu8",%"PRIu8",%"PRIu8"))" 281 ",write('\n')," 282 "print_int_controller(PciMsixLbl)," 283 "write(MsixLbl).", 284 addr.bus, addr.device, addr.function); 285 if(err_is_fail(err)) DEBUG_SKB_ERR(err, "add/print msix controller"); 286 char * lines[8]; 287 lines[0] = skb_get_output(); 288 for(int i=0; i<7; i++){ 289 if(lines[i] == NULL) break; 290 lines[i+1] = strstr(lines[i], "\n"); 291 if(lines[i+1] != NULL) lines[i+1]++; 292 } 293 strncpy(driver_arg->int_arg.msix_ctrl_name, lines[2], 294 sizeof(driver_arg->int_arg.msix_ctrl_name)); 295 KALUGA_DEBUG("Set msix_ctrl_name for (%d,%d,%d) to %s", 296 add.bus, addr.dev, addr.function, driver_arg->int_arg.msix_ctrl_name); 297 298 } else { 299 KALUGA_DEBUG("No interrupt model specified. No interrupts" 300 " for this driver.\n"); 301 } 302 303 if(err_is_fail(err)) return err; 304 305 // For debugging 306 strncpy(debug_msg, skb_get_output(), sizeof(debug_msg)); 307 char * nl = strchr(debug_msg, '\n'); 308 if(nl) *nl = '\0'; 309 debug_msg[sizeof(debug_msg)-1] = '\0'; 310 311 uint64_t start=0, end=0; 312 char ctrl_label[64]; 313 // Format is: Lbl,Class,InLo,InHi,.... 314 err = skb_read_output("%*[^\n]\n%64[^,],%*[^,],%"SCNu64",%"SCNu64, 315 ctrl_label, 316 &start, &end); 317 if(err_is_fail(err)) DEBUG_SKB_ERR(err, "read response"); 318 319 driver_arg->int_arg.int_range_start = start; 320 driver_arg->int_arg.int_range_end = end; 321 322 //Debug message 323 snprintf(debug_msg, sizeof(debug_msg), 324 "lbl=%s,lo=%"PRIu64",hi=%"PRIu64, 325 driver_arg->int_arg.msix_ctrl_name, 326 start, end); 327 328 err = store_int_cap(start, end, driver_arg); 329 if(err_is_fail(err)){ 330 USER_PANIC_ERR(err, "store_int_cap"); 331 } 332 if(debug) strcpy(debug, debug_msg); 333 return SYS_ERR_OK; 334} 335 336static void pci_change_event(octopus_mode_t mode, const char* device_record, 337 void* st) 338{ 339 errval_t err; 340 char *binary_name = NULL; 341 if (mode & OCT_ON_SET) { 342 KALUGA_DEBUG("pci_change_event: device_record: %s\n", device_record); 343 struct pci_addr addr; 344 struct pci_id id; 345 { 346 uint64_t vendor_id, device_id, bus, dev, fun; 347 err = oct_read(device_record, "_ { vendor: %d, device_id: %d, bus: %d, device: %d," 348 " function: %d }", 349 &vendor_id, &device_id, &bus, &dev, &fun); 350 if (err_is_fail(err)) { 351 USER_PANIC_ERR(err, "Got malformed device record?"); 352 } 353 addr = (struct pci_addr) { 354 .bus = bus, 355 .device = dev, 356 .function = fun 357 }; 358 359 id = (struct pci_id) { 360 .device = device_id, 361 .vendor = vendor_id 362 }; 363 } 364 365 /* duplicate device record as we may need it for later */ 366 device_record = strdup(device_record); 367 assert(device_record); 368 369 370 // Ask the SKB which binary and where to start it... 371 static char* query = "find_pci_driver(pci_card(%"PRIu16", %"PRIu16", _, _, _), Driver)," 372 "writeln(Driver)."; 373 err = skb_execute_query(query, id.vendor, id.device); 374 if (err_no(err) == SKB_ERR_EXECUTION) { 375 KALUGA_DEBUG("No PCI driver found for: VendorId=0x%"PRIx16", " 376 "DeviceId=0x%"PRIx16"\n", 377 id.vendor, id.device); 378 goto out; 379 } 380 else if (err_is_fail(err)) { 381 DEBUG_SKB_ERR(err, "Failed to query SKB.\n"); 382 goto out; 383 } 384 385 // XXX: Find better way to parse binary name from SKB 386 binary_name = malloc(strlen(skb_get_output())); 387 coreid_t core; 388 uint8_t multi; 389 uint8_t int_model_in; 390 391 struct driver_argument driver_arg; 392 err = init_driver_argument(&driver_arg); 393 if(err_is_fail(err)){ 394 USER_PANIC_ERR(err, "Could not initialize driver argument.\n"); 395 } 396 coreid_t offset; 397 err = skb_read_output("driver(%"SCNu8", %"SCNu8", %"SCNu8", %[^,], " 398 "%"SCNu8")", &core, &multi, &offset, binary_name, &int_model_in); 399 if(err_is_fail(err)){ 400 USER_PANIC_SKB_ERR(err, "Could not parse SKB output.\n"); 401 } 402 403 driver_arg.int_arg.model = int_model_in; 404 405 static int irqtests_started = 0; 406 if(strstr(binary_name, "irqtest") != NULL){ 407 if(irqtests_started++ > 0){ 408 debug_printf("Not starting multiple instances of irqtest\n"); 409 goto out; 410 } 411 } 412 413 struct module_info* mi = find_module(binary_name); 414 if (mi == NULL) { 415 KALUGA_DEBUG("Driver %s not loaded. Ignore.\n", binary_name); 416 goto out; 417 } 418 419 set_multi_instance(mi, multi); 420 set_core_id_offset(mi, offset); 421 422 // Build up the driver argument 423 err = add_pci_ep(addr, &driver_arg); 424 assert(err_is_ok(err)); 425 426 char intcaps_debug_msg[100]; 427 err = add_int_args(addr, &driver_arg, intcaps_debug_msg); 428 assert(err_is_ok(err)); 429 430 char memcaps_debug_msg[100]; 431 err = add_mem_args(addr, &driver_arg, memcaps_debug_msg); 432 assert(err_is_ok(err)); 433 434 435 // Wait until the core where we start the driver 436 // is ready 437 if (st == NULL && core != my_core_id) { 438 err = wait_for_spawnd(core, (CONST_CAST)device_record); 439 if (err_no(err) == OCT_ERR_NO_RECORD) { 440 KALUGA_DEBUG("Core where driver %s runs is not up yet.\n", 441 mi->binary); 442 // Don't want to free device record yet... 443 return; 444 } 445 else if (err_is_fail(err)) { 446 DEBUG_ERR(err, "Waiting for core %d failed?\n", core); 447 goto out; 448 } 449 } 450 451 // If we've come here the core where we spawn the driver 452 // is already up 453 printf("Kaluga: Starting \"%s\" for (bus=%"PRIu16",dev=%"PRIu16",fun=%"PRIu16")" 454 ", int: %s, on core %"PRIuCOREID"\n", 455 binary_name, addr.bus, addr.device, addr.function, intcaps_debug_msg, core); 456 457 err = mi->start_function(core, mi, (CONST_CAST)device_record, &driver_arg); 458 switch (err_no(err)) { 459 case SYS_ERR_OK: 460 KALUGA_DEBUG("Spawned PCI driver: %s\n", mi->binary); 461 set_started(mi); 462 break; 463 464 case KALUGA_ERR_DRIVER_ALREADY_STARTED: 465 KALUGA_DEBUG("%s already running.\n", mi->binary); 466 break; 467 468 case KALUGA_ERR_DRIVER_NOT_AUTO: 469 KALUGA_DEBUG("%s not declared as auto, ignore.\n", mi->binary); 470 break; 471 472 default: 473 DEBUG_ERR(err, "Unhandled error while starting %s\n", mi->binary); 474 break; 475 } 476 } 477 478out: 479 free(binary_name); 480} 481 482errval_t watch_for_pci_devices(void) 483{ 484 static char* pci_device = "r'hw\\.pci\\.device\\.[0-9]+' { " 485 " bus: _, device: _, function: _, vendor: _," 486 " device_id: _, class: _, subclass: _, " 487 " prog_if: _ }"; 488 octopus_trigger_id_t tid; 489 return oct_trigger_existing_and_watch(pci_device, pci_change_event, NULL, &tid); 490} 491 492static void bridge_change_event(octopus_mode_t mode, const char* bridge_record, 493 void* st) 494{ 495 if (mode & OCT_ON_SET) { 496 // No need to ask the SKB as we always start pci for 497 // in case we find a root bridge 498 struct module_info* mi = find_module("pci"); 499 if (mi == NULL) { 500 KALUGA_DEBUG("PCI driver not found or not declared as auto."); 501 return; 502 } 503 504 // XXX: always spawn on my_core_id; otherwise we need to check that 505 // the other core is already up 506 errval_t err = mi->start_function(my_core_id, mi, (CONST_CAST)bridge_record, NULL); 507 switch (err_no(err)) { 508 case SYS_ERR_OK: 509 KALUGA_DEBUG("Spawned PCI bus driver: %s\n", mi->binary); 510 set_started(mi); 511 break; 512 513 case KALUGA_ERR_DRIVER_ALREADY_STARTED: 514 KALUGA_DEBUG("%s already running.\n", mi->binary); 515 break; 516 517 case KALUGA_ERR_DRIVER_NOT_AUTO: 518 KALUGA_DEBUG("%s not declared as auto, ignore.\n", mi->binary); 519 break; 520 521 default: 522 DEBUG_ERR(err, "Unhandled error while starting %s\n", mi->binary); 523 break; 524 } 525 } 526} 527 528errval_t watch_for_pci_root_bridge(void) 529{ 530 static char* root_bridge = "r'hw\\.pci\\.rootbridge\\.[0-9]+' { " 531 " bus: _, device: _, function: _, maxbus: _," 532 " acpi_node: _ }"; 533 octopus_trigger_id_t tid; 534 return oct_trigger_existing_and_watch(root_bridge, bridge_change_event, 535 NULL, &tid); 536} 537