1 /* 2 amddev.c 3 4 Driver for the AMD Device Exclusion Vector (DEV) 5 */ 6 7 #include <minix/driver.h> 8 #include <minix/config.h> 9 #include <minix/type.h> 10 11 #include <errno.h> 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <string.h> 15 #include <unistd.h> 16 #include <machine/vm.h> 17 #include <machine/vmparam.h> 18 #include <signal.h> 19 #include <minix/com.h> 20 #include <minix/const.h> 21 #include <minix/ipc.h> 22 #include <minix/syslib.h> 23 #include <minix/sysutil.h> 24 #include <minix/endpoint.h> 25 #include <machine/pci.h> 26 27 /* Offsets from capability pointer */ 28 #define DEV_OP 4 /* Selects control/status register to access */ 29 #define DEV_OP_FUNC_SHIFT 8 /* Function part in OP reg. */ 30 #define DEV_DATA 8 /* Read/write to access reg. selected */ 31 32 /* Functions */ 33 #define DEVF_BASE_LO 0 34 #define DEVF_BASE_HI 1 35 #define DEVF_MAP 2 36 #define DEVF_CAP 3 37 #define DEVF_CAP_MAPS_MASK 0x00ff0000 38 #define DEVF_CAP_MAPS_SHIFT 16 39 #define DEVF_CAP_DOMS_MASK 0x0000ff00 40 #define DEVF_CAP_DOMS_SHIFT 8 41 #define DEVF_CAP_REV_MASK 0x000000ff 42 #define DEVF_CAP_REV_SHIFT 0 43 #define DEVF_CR 4 44 #define DEVF_ERR_STATUS 5 45 #define DEVF_ERR_ADDR_LO 6 46 #define DEVF_ERR_ADDR_HI 7 47 48 static int dev_devind; 49 static u8_t dev_capptr; 50 static u8_t *table; 51 52 static int find_dev(int *devindp, u8_t *capaddrp); 53 static u32_t read_reg(int function, int index); 54 static void write_reg(int function, int index, u32_t value); 55 static void init_domain(int index); 56 static void init_map(unsigned int ix); 57 static int do_add4pci(const message *m); 58 static void add_range(phys_bytes busaddr, phys_bytes size); 59 #if 0 60 static void del_range(phys_bytes busaddr, phys_bytes size); 61 static void sef_cb_signal_handler(int signo); 62 #endif 63 static void report_exceptions(void); 64 65 /* SEF functions and variables. */ 66 static void sef_local_startup(void); 67 static int sef_cb_init_fresh(int type, sef_init_info_t *info); 68 69 int main(void) 70 { 71 int r; 72 message m; 73 int ipc_status; 74 75 /* SEF local startup. */ 76 sef_local_startup(); 77 78 for(;;) 79 { 80 report_exceptions(); 81 82 r= driver_receive(ANY, &m, &ipc_status); 83 if (r != OK) 84 panic("driver_receive failed: %d", r); 85 if (m.m_type == IOMMU_MAP) { 86 r= do_add4pci(&m); 87 m.m_type= r; 88 ipc_send(m.m_source, &m); 89 continue; 90 } 91 printf("amddev: got message from %d\n", m.m_source); 92 } 93 } 94 95 /*===========================================================================* 96 * sef_local_startup * 97 *===========================================================================*/ 98 static void sef_local_startup() 99 { 100 /* Register init callbacks. */ 101 sef_setcb_init_fresh(sef_cb_init_fresh); 102 sef_setcb_init_lu(sef_cb_init_fresh); 103 sef_setcb_init_restart(sef_cb_init_fresh); 104 105 #if 0 106 /* Register signal callbacks. */ 107 sef_setcb_signal_handler(sef_cb_signal_handler); 108 #endif 109 110 /* Let SEF perform startup. */ 111 sef_startup(); 112 } 113 114 /*===========================================================================* 115 * sef_cb_init_fresh * 116 *===========================================================================*/ 117 static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info)) 118 { 119 /* Initialize the amddev driver. */ 120 int r, n_maps, n_domains, revision; 121 u16_t flags; 122 u32_t bits; 123 124 printf("amddev: starting\n"); 125 126 r= find_dev(&dev_devind, &dev_capptr); 127 if (!r) 128 return r; 129 flags= pci_attr_r16(dev_devind, dev_capptr+CAP_SD_INFO); 130 printf("amddev`init: flags = 0x%x\n", flags); 131 132 bits= read_reg(DEVF_CAP, 0); 133 n_maps= ((bits & DEVF_CAP_MAPS_MASK) >> DEVF_CAP_MAPS_SHIFT); 134 n_domains= ((bits & DEVF_CAP_DOMS_MASK) >> DEVF_CAP_DOMS_SHIFT); 135 revision= ((bits & DEVF_CAP_REV_MASK) >> DEVF_CAP_REV_SHIFT); 136 printf("amddev`init: DEVF_CAP = 0x%x (%d maps, %d domains, rev 0x%x)\n", 137 bits, n_maps, n_domains, revision); 138 139 printf("status = 0x%x, addr-lo = 0x%x, addr-hi = 0x%x\n", 140 read_reg(DEVF_ERR_STATUS, 0), 141 read_reg(DEVF_ERR_ADDR_LO, 0), 142 read_reg(DEVF_ERR_ADDR_HI, 0)); 143 144 init_domain(0); 145 init_map(0); 146 #if 0 147 init_domain(1); 148 #endif 149 150 write_reg(DEVF_CR, 0, 0x10 | 0x8 | 0x4 | 1); 151 152 printf("after write: DEVF_CR: 0x%x\n", read_reg(DEVF_CR, 0)); 153 154 return(OK); 155 } 156 157 158 #if 0 159 /*===========================================================================* 160 * sef_cb_signal_handler * 161 *===========================================================================*/ 162 static void sef_cb_signal_handler(int signo) 163 { 164 int r; 165 endpoint_t proc_e; 166 phys_bytes base, size; 167 168 /* Only check for termination signal, ignore anything else. */ 169 if (signo != SIGTERM) return; 170 171 for (;;) 172 { 173 r= vm_getdma(&proc_e, &base, &size); 174 if (r == -1) 175 { 176 if (errno != -EAGAIN) 177 { 178 printf( 179 "amddev: vm_getdma failed: %d\n", 180 errno); 181 } 182 break; 183 } 184 185 printf( 186 "amddev: deleting 0x%lx@0x%lx for proc %d\n", 187 size, base, proc_e); 188 del_range(base, size); 189 r= vm_deldma(proc_e, base, size); 190 if (r == -1) 191 { 192 printf("amddev: vm_deldma failed: %d\n", 193 errno); 194 break; 195 } 196 } 197 } 198 #endif 199 200 /* Returns 0 if no device found, or 1 if a device is found. */ 201 static int find_dev(devindp, capaddrp) 202 int *devindp; 203 u8_t *capaddrp; 204 { 205 int r, devind, first; 206 u8_t capptr, type, next, subtype; 207 u16_t vid, did, status; 208 209 pci_init(); 210 211 first= 1; 212 for(;;) 213 { 214 if (first) 215 { 216 first= 0; 217 r= pci_first_dev(&devind, &vid, &did); 218 if (!r) 219 { 220 printf("amddev`find_dev: no first dev\n"); 221 return 0; 222 } 223 } 224 else 225 { 226 r= pci_next_dev(&devind, &vid, &did); 227 if (!r) 228 { 229 printf("amddev`find_dev: no next dev\n"); 230 return 0; 231 } 232 } 233 234 printf("amddev`find_dev: got devind %d, vid 0x%x, did 0x%x\n", 235 devind, vid, did); 236 237 /* Check capabilities bit in the device status register */ 238 status= pci_attr_r16(devind, PCI_SR); 239 if (!(status & PSR_CAPPTR)) 240 continue; 241 242 capptr= (pci_attr_r8(devind, PCI_CAPPTR) & PCI_CP_MASK); 243 while (capptr != 0) 244 { 245 type = pci_attr_r8(devind, capptr+CAP_TYPE); 246 next= (pci_attr_r8(devind, capptr+CAP_NEXT) & 247 PCI_CP_MASK); 248 if (type == CAP_T_SECURE_DEV) 249 { 250 printf( 251 "amddev`find_dev: found secure device\n"); 252 subtype= (pci_attr_r8(devind, capptr+ 253 CAP_SD_INFO) & CAP_SD_SUBTYPE_MASK); 254 if (subtype == CAP_T_SD_DEV) 255 { 256 printf("amddev`find_dev: AMD DEV\n"); 257 pci_reserve(devind); 258 *devindp= devind; 259 *capaddrp= capptr; 260 return 1; 261 } 262 } 263 capptr= next; 264 } 265 } 266 return 0; 267 } 268 269 static u32_t read_reg(int function, int index) 270 { 271 pci_attr_w32(dev_devind, dev_capptr + DEV_OP, ((function << 272 DEV_OP_FUNC_SHIFT) | index)); 273 return pci_attr_r32(dev_devind, dev_capptr + DEV_DATA); 274 } 275 276 static void write_reg(int function, int index, u32_t value) 277 { 278 pci_attr_w32(dev_devind, dev_capptr + DEV_OP, ((function << 279 DEV_OP_FUNC_SHIFT) | index)); 280 pci_attr_w32(dev_devind, dev_capptr + DEV_DATA, value); 281 } 282 283 static void init_domain(int index) 284 { 285 size_t size, memsize; 286 phys_bytes busaddr; 287 288 size= 0x100000 / 8; 289 table= alloc_contig(size, AC_ALIGN4K, &busaddr); 290 if (table == NULL) 291 panic("malloc failed"); 292 if (index == 0) 293 { 294 memset(table, 0, size); 295 memsize= 0x37000 / 8; 296 printf("memsize = 0x%x / 8\n", memsize*8); 297 memset(table, 0xff, memsize); 298 } 299 else 300 { 301 memset(table, 0xff, size); 302 memset(table, 0x00, size); 303 } 304 305 printf("init_domain: busaddr = 0x%lx\n", busaddr); 306 307 write_reg(DEVF_BASE_HI, index, 0); 308 write_reg(DEVF_BASE_LO, index, busaddr | 3); 309 310 printf("after write: DEVF_BASE_LO: 0x%x\n", 311 read_reg(DEVF_BASE_LO, index)); 312 } 313 314 static void init_map(unsigned int ix) 315 { 316 u32_t v, dom, busno, unit0, unit1; 317 318 dom= 1; 319 busno= 7; 320 unit1= 9; 321 unit0= 9; 322 v= (dom << 26) | (dom << 20) | (busno << 12) | 323 (0 << 11) | (unit1 << 6) | 324 (0 << 5) | (unit0 << 0); 325 write_reg(DEVF_MAP, ix, v); 326 327 printf("after write: DEVF_MAP: 0x%x\n", read_reg(DEVF_MAP, ix)); 328 } 329 330 #if 0 331 static int do_add(message *m) 332 { 333 int r; 334 endpoint_t proc; 335 vir_bytes start; 336 size_t size; 337 phys_bytes busaddr; 338 339 proc= m->m_source; 340 start= m->m2_l1; 341 size= m->m2_l2; 342 343 #if 0 344 printf("amddev`do_add: got request for 0x%x@0x%x from %d\n", 345 size, start, proc); 346 #endif 347 348 if (start % PAGE_SIZE) 349 { 350 printf("amddev`do_add: bad start 0x%x from proc %d\n", 351 start, proc); 352 return EINVAL; 353 } 354 if (size % PAGE_SIZE) 355 { 356 printf("amddev`do_add: bad size 0x%x from proc %d\n", 357 size, proc); 358 return EINVAL; 359 } 360 r= sys_umap_remote(proc, SELF, VM_D, (vir_bytes)start, size, &busaddr); 361 if (r != OK) 362 { 363 printf("amddev`do_add: umap failed for 0x%x@0x%x, proc %d\n", 364 size, start, proc); 365 return r; 366 } 367 add_range(busaddr, size); 368 369 } 370 #endif 371 372 373 374 static int do_add4pci(const message *m) 375 { 376 int r, pci_bus, pci_dev, pci_func; 377 endpoint_t proc; 378 vir_bytes start; 379 size_t size; 380 phys_bytes busaddr; 381 382 proc= m->m_source; 383 start= m->m2_l1; 384 size= m->m2_l2; 385 pci_bus= m->m1_i1; 386 pci_dev= m->m1_i2; 387 pci_func= m->m1_i3; 388 389 printf( 390 "amddev`do_add4pci: got request for 0x%x@0x%lx from %d for pci dev %u.%u.%u\n", 391 size, start, proc, pci_bus, pci_dev, pci_func); 392 393 if (start % PAGE_SIZE) 394 { 395 printf("amddev`do_add4pci: bad start 0x%lx from proc %d\n", 396 start, proc); 397 return EINVAL; 398 } 399 if (size % PAGE_SIZE) 400 { 401 printf("amddev`do_add4pci: bad size 0x%x from proc %d\n", 402 size, proc); 403 return EINVAL; 404 } 405 406 printf("amddev`do_add4pci: should check with PCI\n"); 407 408 r= sys_umap_remote(proc, SELF, VM_D, (vir_bytes)start, size, &busaddr); 409 if (r != OK) 410 { 411 printf( 412 "amddev`do_add4pci: umap failed for 0x%x@0x%lx, proc %d: %d\n", 413 size, start, proc, r); 414 return r; 415 } 416 417 #if 0 418 r= vm_adddma(proc, start, size); 419 if (r != 0) 420 { 421 r= -errno; 422 printf("amddev`do_add4pci: vm_adddma failed for 0x%x@0x%lx, " 423 "proc %d: %d\n", size, start, proc, r); 424 return r; 425 } 426 #endif 427 428 add_range(busaddr, size); 429 430 return OK; 431 } 432 433 434 static void add_range(phys_bytes busaddr, phys_bytes size) 435 { 436 phys_bytes o; 437 438 #if 0 439 printf("add_range: mapping 0x%x@0x%x\n", size, busaddr); 440 #endif 441 442 for (o= 0; o<size; o += PAGE_SIZE) 443 { 444 u32_t bit= (busaddr+o)/PAGE_SIZE; 445 table[bit/8] &= ~(1U << (bit % 8)); 446 } 447 } 448 449 #if 0 450 static void del_range(phys_bytes busaddr, phys_bytes size) 451 { 452 phys_bytes o; 453 454 #if 0 455 printf("del_range: mapping 0x%x@0x%x\n", size, busaddr); 456 #endif 457 458 for (o= 0; o<size; o += PAGE_SIZE) 459 { 460 u32_t bit= (busaddr+o)/PAGE_SIZE; 461 table[bit/8] |= (1 << (bit % 8)); 462 } 463 } 464 #endif 465 466 static void report_exceptions(void) 467 { 468 u32_t status; 469 470 status= read_reg(DEVF_ERR_STATUS, 0); 471 if (!(status & 0x80000000)) 472 return; 473 printf("amddev: status = 0x%x, addr-lo = 0x%x, addr-hi = 0x%x\n", 474 status, read_reg(DEVF_ERR_ADDR_LO, 0), 475 read_reg(DEVF_ERR_ADDR_HI, 0)); 476 write_reg(DEVF_ERR_STATUS, 0, 0); 477 } 478