1/** 2 * \file 3 * \brief Card Configuration 4 */ 5 6/* 7 * Copyright (c) 2014 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 <stdio.h> 16#include <string.h> 17#include <barrelfish/barrelfish.h> 18#include <pci/pci.h> 19 20#include <dev/xeon_phi/xeon_phi_boot_dev.h> 21 22#include "xeon_phi_internal.h" 23#include "interrupts.h" 24#include "sleep.h" 25#include "smpt.h" 26#include "sysmem_caps.h" 27 28#define XEON_PHI_RESET_TIME 3000 29#define XEON_PHI_RESET_TIME_UNIT 100 30 31 32/// PCI Vendor ID of Intel 33#define PCI_VENDOR_ID_INTEL 0x8086 34 35#define PCI_SUBSYSTEM_DEVICE 0x2500 36 37#define PCI_SUBSYSTEM_VENDOR 0x8086 38 39/* 40 * These are the possible device IDs of the Xeon PHi according to the 41 * Intel MPSS implementation. 42 * 43 * Querying the host with lspci -nn | grep "8086:225" gives the actual 44 * device ID of the built in cards to be the last one. 45 * 46 * 07:00.0 Co-processor [0b40]: Intel Corporation Device [8086:225e] (rev 11) 47 * 82:00.0 Co-processor [0b40]: Intel Corporation Device [8086:225e] (rev 11) 48 */ 49#define PCI_DEVICE_KNC_2250 0x2250 50#define PCI_DEVICE_KNC_2251 0x2251 51#define PCI_DEVICE_KNC_2252 0x2252 52#define PCI_DEVICE_KNC_2253 0x2253 53#define PCI_DEVICE_KNC_2254 0x2254 54#define PCI_DEVICE_KNC_2255 0x2255 55#define PCI_DEVICE_KNC_2256 0x2256 56#define PCI_DEVICE_KNC_2257 0x2257 57#define PCI_DEVICE_KNC_2258 0x2258 58#define PCI_DEVICE_KNC_2259 0x2259 59#define PCI_DEVICE_KNC_225a 0x225a 60#define PCI_DEVICE_KNC_225b 0x225b 61#define PCI_DEVICE_KNC_225c 0x225c 62#define PCI_DEVICE_KNC_225d 0x225d 63#define PCI_DEVICE_KNC_225e 0x225e 64 65#define XEON_PHI_APT_BAR 0 66#define XEON_PHI_MMIO_BAR 1 67#define XEON_PHI_MMIO_BAR_SIZE (128*1024) 68#define XEON_PHI_APT_BAR_SIZE (8ULL << 30) 69#define XEON_PHI_BAR_TYPE 0 70 71static void device_init(struct xeon_phi *phi) 72{ 73 74#if 0 75 scratch13 = SBOX_READ(mic_ctx->mmio.va, SBOX_SCRATCH13); 76 mic_ctx->bi_stepping = SCRATCH13_STEP_ID(scratch13); 77 mic_ctx->bi_substepping = SCRATCH13_SUB_STEP(scratch13); 78#ifdef MIC_IS_EMULATION 79 mic_ctx->bi_platform = PLATFORM_EMULATOR; 80#else 81 mic_ctx->bi_platform = SCRATCH13_PLATFORM_ID(scratch13); 82#endif 83 mic_enable_msi_interrupts(mic_ctx); 84 mic_enable_interrupts(mic_ctx); 85 86 mic_reg_irqhandler(mic_ctx, 1, "MIC SHUTDOWN DoorBell 1", 87 mic_shutdown_host_doorbell_intr_handler); 88 89#endif 90} 91 92 93#if 0 94static void pci_init_card(void *arg, struct device_mem* bar_info, 95 int bar_count) 96{ 97 errval_t err; 98 99 if (initialized) { 100 debug_printf("WARNING > Device already initialized\n"); 101 return; 102 } 103 104 printf("Got: %i bars\n", bar_count); 105 for (int i = 0; i < bar_count; ++i) { 106 printf("> Bar[%i]: {type=%i, paddr=0x%lx, size=%u}\n", i, bar_info[i].type, bar_info[i].paddr, (uint32_t)(bar_info[i].bytes/1024)); 107 } 108 109 if (bar_count != 2) { 110 USER_PANIC("There is something wrong. The Card should have 2 MBARs."); 111 } 112 113 114 /* 115 * TODO> install some checks that we got the correct caps 116 */ 117 assert(bar_info[XEON_PHI_MMIO_BAR].bytes == XEON_PHI_MMIO_BAR_SIZE); 118 assert(bar_info[XEON_PHI_APT_BAR].bytes >= XEON_PHI_APT_BAR_SIZE); 119 assert(bar_info[XEON_PHI_MMIO_BAR].type == XEON_PHI_BAR_TYPE); 120 assert(bar_info[XEON_PHI_APT_BAR].type == XEON_PHI_BAR_TYPE); 121 122 struct frame_identity id; 123 assert(!capref_is_null(bar_info[XEON_PHI_APT_BAR].frame_cap)); 124 card->apt.cap = bar_info[XEON_PHI_APT_BAR].frame_cap; 125 err = frame_identify(card->apt.cap, &id); 126 if (err_is_fail(err)) { 127 USER_PANIC_ERR(err, "failed to identify the aperture cap"); 128 } 129 card->apt.length = id.bytes; 130 card->apt.pbase = id.base; 131 card->apt.bytes = bar_info[XEON_PHI_APT_BAR].bytes; 132 133 assert(!capref_is_null(bar_info[XEON_PHI_MMIO_BAR].frame_cap)); 134 card->mmio.cap = bar_info[XEON_PHI_MMIO_BAR].frame_cap; 135 136 err = frame_identify(card->mmio.cap, &id); 137 if (err_is_fail(err)) { 138 USER_PANIC_ERR(err, "failed to identify the aperture cap"); 139 } 140 card->mmio.length = id.bytes; 141 card->mmio.pbase = id.base; 142 card->mmio.bytes = bar_info[XEON_PHI_MMIO_BAR].bytes; 143 144 err = xeon_phi_map_aperture(card, XEON_PHI_APERTURE_INIT_SIZE); 145 if (err_is_fail(err)) { 146 USER_PANIC_ERR(err, "Failed to map aperture range"); 147 } 148 149 err = sysmem_cap_manager_init(card->apt.cap); 150 if (err_is_fail(err)) { 151 USER_PANIC_ERR(err, "could not initialize the cap manager"); 152 } 153 154 err = map_device(&bar_info[XEON_PHI_MMIO_BAR]); 155 if (err_is_fail(err)) { 156 USER_PANIC_ERR(err, "Failed to map MMIO range"); 157 } 158 159 card->mmio.vbase = (lvaddr_t) bar_info[XEON_PHI_MMIO_BAR].vaddr; 160 card->mmio.length = bar_info[XEON_PHI_MMIO_BAR].bytes; 161 162 card->state = XEON_PHI_STATE_PCI_OK; 163} 164 165 166static void pci_register(struct xeon_phi *phi, uint32_t bus, uint32_t dev, uint32_t fun) 167{ 168 errval_t err; 169 170 err = pci_client_connect(); 171 if (err_is_fail(err)) { 172 USER_PANIC_ERR(err, "Could not connect to PCI\n"); 173 } 174 175 err = pci_register_driver_irq(pci_init_card, NULL, 176 PCI_DONT_CARE, 177 PCI_DONT_CARE, 178 PCI_DONT_CARE, 179 PCI_VENDOR_ID_INTEL, 180 PCI_DEVICE_KNC_225e, 181 bus, 182 dev, 183 fun, 184 interrupt_handler, 185 phi); 186 187 if (err_is_fail(err)) { 188 USER_PANIC_ERR(err, "Could not register the PCI device"); 189 } 190} 191#endif 192 193 194static errval_t xeon_phi_init_with_caps(struct xeon_phi *card, struct capref mmio, 195 struct capref apt) 196{ 197 errval_t err; 198 199 struct frame_identity id; 200 assert(!capref_is_null(apt)); 201 card->apt.cap = apt; 202 err = frame_identify(card->apt.cap, &id); 203 if (err_is_fail(err)) { 204 return err_push(err, LIB_ERR_FRAME_IDENTIFY); 205 } 206 207 card->apt.pbase = id.base; 208 card->apt.bytes = id.bytes; 209 210 assert(!capref_is_null(mmio)); 211 card->mmio.cap = mmio; 212 213 err = frame_identify(card->mmio.cap, &id); 214 if (err_is_fail(err)) { 215 return err_push(err, LIB_ERR_FRAME_IDENTIFY); 216 } 217 218 card->mmio.pbase = id.base; 219 card->mmio.bytes = id.bytes; 220 221 222 err = xeon_phi_map_aperture(card, XEON_PHI_APERTURE_INIT_SIZE); 223 if (err_is_fail(err)) { 224 return err; 225 } 226 227 err = sysmem_cap_manager_init(card->apt.cap); 228 if (err_is_fail(err)) { 229 return err; 230 } 231 232 err = vspace_map_one_frame_attr((void **)&card->mmio.vbase, card->mmio.bytes, 233 card->mmio.cap, VREGION_FLAGS_READ_WRITE_NOCACHE, 234 NULL, NULL); 235 if (err_is_fail(err)) { 236 return err_push(err, LIB_ERR_VSPACE_MAP); 237 } 238 239 card->state = XEON_PHI_STATE_PCI_OK; 240 241 return SYS_ERR_OK; 242} 243 244/** 245 * \brief initializes the coprocessor card 246 * 247 * \param phi pointer to the information structure 248 */ 249errval_t xeon_phi_init(struct xeon_phi *phi, struct capref mmio, struct capref apt) 250{ 251 errval_t err; 252 253 #if 0 254 pci_register(phi, bus, dev, fun); 255 #endif 256 257 err = xeon_phi_init_with_caps(phi, mmio, apt); 258 if (err_is_fail(err)) { 259 return err; 260 } 261 262 xeon_phi_reset(phi); 263 264 interrupts_init(phi); 265 266 device_init(phi); 267 268 smpt_init(phi); 269 270 xeon_phi_serial_init(phi); 271 272 return SYS_ERR_OK; 273} 274 275/** 276 * \brief performs a soft reset of the card 277 * 278 * \param phi pointer to the card information 279 */ 280errval_t xeon_phi_reset(struct xeon_phi *phi) 281{ 282 if (phi->state == XEON_PHI_STATE_NULL) { 283 return SYS_ERR_ILLEGAL_INVOCATION; 284 } 285 286 phi->state = XEON_PHI_STATE_RESET; 287 288 xeon_phi_boot_t boot_registers; 289 290 xeon_phi_boot_initialize(&boot_registers, 291 XEON_PHI_MMIO_TO_SBOX(phi), 292 XEON_PHI_MMIO_TO_DBOX(phi)); 293 294 // clearing the download status register before rest. 295 xeon_phi_boot_download_wr(&boot_registers, 0x0); 296 297 // perform the actual reset sequence 298 xeon_phi_boot_reset_t res = xeon_phi_boot_reset_rd(&boot_registers); 299 res = xeon_phi_boot_reset_reset_insert(res, 0x1); 300 xeon_phi_boot_reset_wr(&boot_registers, res); 301 302 // wait a bit to prevent potential problems 303 milli_sleep(1000); 304 305 xeon_phi_boot_postcode_t postcode; 306 xeon_phi_boot_postcodes_t pc, pc_prev = 0; 307 for (uint32_t time = 0; time < XEON_PHI_RESET_TIME; ++time) { 308 postcode = xeon_phi_boot_postcode_rd(&boot_registers); 309 pc = xeon_phi_boot_postcode_code_extract(postcode); 310 if (pc_prev != pc) { 311 debug_printf("Resetting: %s\n", xeon_phi_boot_postcodes_describe(pc)); 312 } 313 if (postcode == xeon_phi_boot_postcode_invalid || postcode 314 == xeon_phi_boot_postcode_fatal 315 || pc == xeon_phi_boot_postcode_memtf 316 || pc == xeon_phi_boot_postcode_mempf) { 317 break; 318 } 319 320 if (xeon_phi_boot_download_status_rdf(&boot_registers)) { 321 phi->state = XEON_PHI_STATE_READY; 322 debug_printf("Reset successful\n"); 323 /* 324 * XXX; Maybe we should re-enable the IRQ if they were enabled beforehand 325 * if (mic_ctx->msie) 326 mic_enable_msi_interrupts(mic_ctx); 327 mic_enable_interrupts(mic_ctx); 328 mic_smpt_restore(mic_ctx); 329 micscif_start(mic_ctx); 330 */ 331 return SYS_ERR_OK; 332 } 333 334 pc_prev = pc; 335 milli_sleep(XEON_PHI_RESET_TIME_UNIT); 336 } 337 338 if (phi->state != XEON_PHI_STATE_READY) { 339 debug_printf("Reset Failed; %s\n", xeon_phi_boot_postcodes_describe(pc)); 340 XBOOT_DEBUG("Reset Failed (Post Code %c%c)\n", 341 xeon_phi_boot_postcode_raw_code0_extract(postcode), 342 xeon_phi_boot_postcode_raw_code1_extract(postcode)); 343 344 return 1; // todo> error code 345 } 346 347#if 0 348#define ENABLE_MIC_INTERRUPTS(mmio) { \ 349 uint32_t sboxSice0reg = SBOX_READ((mmio), SBOX_SICE0); \ 350 sboxSice0reg |= SBOX_SICE0_DBR_BITS(0xf) | SBOX_SICE0_DMA_BITS(0xff); \ 351 SBOX_WRITE(sboxSice0reg, (mmio), SBOX_SICE0); } 352#endif 353 return SYS_ERR_OK; 354} 355 356 357/** 358 * \brief maps the aperture memory range of the Xeon Phi into the drivers 359 * vspace to be able to load the coprocessor OS onto the card 360 * 361 * \param phi pointer to the Xeon Phi structure holding aperture information 362 * \param range how much bytes to map 363 * 364 * \returns SYS_ERR_OK on success 365 */ 366errval_t xeon_phi_map_aperture(struct xeon_phi *phi, 367 size_t range) 368{ 369 if (phi->apt.vbase != 0) { 370 return SYS_ERR_VM_ALREADY_MAPPED; 371 } 372 373 errval_t err; 374 void *addr; 375 err = vspace_map_one_frame(&addr, range, phi->apt.cap, NULL, NULL); 376 if (err_is_fail(err)) { 377 DEBUG_ERR(err, "vspace_map_one_frame failed for the apt mbar"); 378 return err_push(err, LIB_ERR_VSPACE_MAP); 379 } 380 381 phi->apt.vbase = (lvaddr_t)addr; 382 383 return SYS_ERR_OK; 384} 385 386/** 387 * \brief unmaps the previously mapped aperture range when the programming 388 * completes. 389 * 390 * \param phi pointer to the Xeon Phi structure holiding mapping information 391 * 392 * \return SYS_ERR_OK on success 393 */ 394errval_t xeon_phi_unmap_aperture(struct xeon_phi *phi) 395{ 396 errval_t err; 397 398 if (phi->apt.vbase == 0) { 399 return SYS_ERR_OK; 400 } 401 402 err = vspace_unmap((void *)phi->apt.vbase); 403 if (err_is_fail(err)) { 404 DEBUG_ERR(err, "vspace_map_one_frame failed for the apt mbar"); 405 return err_push(err, LIB_ERR_VSPACE_MAP); 406 } 407 408 phi->apt.vbase = 0; 409 410 return SYS_ERR_OK; 411} 412