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 /* Register live update callbacks. */ 106 sef_setcb_lu_prepare(sef_cb_lu_prepare_always_ready); 107 sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard); 108 109 #if 0 110 /* Register signal callbacks. */ 111 sef_setcb_signal_handler(sef_cb_signal_handler); 112 #endif 113 114 /* Let SEF perform startup. */ 115 sef_startup(); 116 } 117 118 /*===========================================================================* 119 * sef_cb_init_fresh * 120 *===========================================================================*/ 121 static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *UNUSED(info)) 122 { 123 /* Initialize the amddev driver. */ 124 int r, n_maps, n_domains, revision; 125 u16_t flags; 126 u32_t bits; 127 128 printf("amddev: starting\n"); 129 130 r= find_dev(&dev_devind, &dev_capptr); 131 if (!r) 132 return r; 133 flags= pci_attr_r16(dev_devind, dev_capptr+CAP_SD_INFO); 134 printf("amddev`init: flags = 0x%x\n", flags); 135 136 bits= read_reg(DEVF_CAP, 0); 137 n_maps= ((bits & DEVF_CAP_MAPS_MASK) >> DEVF_CAP_MAPS_SHIFT); 138 n_domains= ((bits & DEVF_CAP_DOMS_MASK) >> DEVF_CAP_DOMS_SHIFT); 139 revision= ((bits & DEVF_CAP_REV_MASK) >> DEVF_CAP_REV_SHIFT); 140 printf("amddev`init: DEVF_CAP = 0x%x (%d maps, %d domains, rev 0x%x)\n", 141 bits, n_maps, n_domains, revision); 142 143 printf("status = 0x%x, addr-lo = 0x%x, addr-hi = 0x%x\n", 144 read_reg(DEVF_ERR_STATUS, 0), 145 read_reg(DEVF_ERR_ADDR_LO, 0), 146 read_reg(DEVF_ERR_ADDR_HI, 0)); 147 148 init_domain(0); 149 init_map(0); 150 #if 0 151 init_domain(1); 152 #endif 153 154 write_reg(DEVF_CR, 0, 0x10 | 0x8 | 0x4 | 1); 155 156 printf("after write: DEVF_CR: 0x%x\n", read_reg(DEVF_CR, 0)); 157 158 return(OK); 159 } 160 161 162 #if 0 163 /*===========================================================================* 164 * sef_cb_signal_handler * 165 *===========================================================================*/ 166 static void sef_cb_signal_handler(int signo) 167 { 168 int r; 169 endpoint_t proc_e; 170 phys_bytes base, size; 171 172 /* Only check for termination signal, ignore anything else. */ 173 if (signo != SIGTERM) return; 174 175 for (;;) 176 { 177 r= vm_getdma(&proc_e, &base, &size); 178 if (r == -1) 179 { 180 if (errno != -EAGAIN) 181 { 182 printf( 183 "amddev: vm_getdma failed: %d\n", 184 errno); 185 } 186 break; 187 } 188 189 printf( 190 "amddev: deleting 0x%lx@0x%lx for proc %d\n", 191 size, base, proc_e); 192 del_range(base, size); 193 r= vm_deldma(proc_e, base, size); 194 if (r == -1) 195 { 196 printf("amddev: vm_deldma failed: %d\n", 197 errno); 198 break; 199 } 200 } 201 } 202 #endif 203 204 /* Returns 0 if no device found, or 1 if a device is found. */ 205 static int find_dev(devindp, capaddrp) 206 int *devindp; 207 u8_t *capaddrp; 208 { 209 int r, devind, first; 210 u8_t capptr, type, next, subtype; 211 u16_t vid, did, status; 212 213 pci_init(); 214 215 first= 1; 216 for(;;) 217 { 218 if (first) 219 { 220 first= 0; 221 r= pci_first_dev(&devind, &vid, &did); 222 if (!r) 223 { 224 printf("amddev`find_dev: no first dev\n"); 225 return 0; 226 } 227 } 228 else 229 { 230 r= pci_next_dev(&devind, &vid, &did); 231 if (!r) 232 { 233 printf("amddev`find_dev: no next dev\n"); 234 return 0; 235 } 236 } 237 238 printf("amddev`find_dev: got devind %d, vid 0x%x, did 0x%x\n", 239 devind, vid, did); 240 241 /* Check capabilities bit in the device status register */ 242 status= pci_attr_r16(devind, PCI_SR); 243 if (!(status & PSR_CAPPTR)) 244 continue; 245 246 capptr= (pci_attr_r8(devind, PCI_CAPPTR) & PCI_CP_MASK); 247 while (capptr != 0) 248 { 249 type = pci_attr_r8(devind, capptr+CAP_TYPE); 250 next= (pci_attr_r8(devind, capptr+CAP_NEXT) & 251 PCI_CP_MASK); 252 if (type == CAP_T_SECURE_DEV) 253 { 254 printf( 255 "amddev`find_dev: found secure device\n"); 256 subtype= (pci_attr_r8(devind, capptr+ 257 CAP_SD_INFO) & CAP_SD_SUBTYPE_MASK); 258 if (subtype == CAP_T_SD_DEV) 259 { 260 printf("amddev`find_dev: AMD DEV\n"); 261 pci_reserve(devind); 262 *devindp= devind; 263 *capaddrp= capptr; 264 return 1; 265 } 266 } 267 capptr= next; 268 } 269 } 270 return 0; 271 } 272 273 static u32_t read_reg(int function, int index) 274 { 275 pci_attr_w32(dev_devind, dev_capptr + DEV_OP, ((function << 276 DEV_OP_FUNC_SHIFT) | index)); 277 return pci_attr_r32(dev_devind, dev_capptr + DEV_DATA); 278 } 279 280 static void write_reg(int function, int index, u32_t value) 281 { 282 pci_attr_w32(dev_devind, dev_capptr + DEV_OP, ((function << 283 DEV_OP_FUNC_SHIFT) | index)); 284 pci_attr_w32(dev_devind, dev_capptr + DEV_DATA, value); 285 } 286 287 static void init_domain(int index) 288 { 289 size_t size, memsize; 290 phys_bytes busaddr; 291 292 size= 0x100000 / 8; 293 table= alloc_contig(size, AC_ALIGN4K, &busaddr); 294 if (table == NULL) 295 panic("malloc failed"); 296 if (index == 0) 297 { 298 memset(table, 0, size); 299 memsize= 0x37000 / 8; 300 printf("memsize = 0x%x / 8\n", memsize*8); 301 memset(table, 0xff, memsize); 302 } 303 else 304 { 305 memset(table, 0xff, size); 306 memset(table, 0x00, size); 307 } 308 309 printf("init_domain: busaddr = 0x%lx\n", busaddr); 310 311 write_reg(DEVF_BASE_HI, index, 0); 312 write_reg(DEVF_BASE_LO, index, busaddr | 3); 313 314 printf("after write: DEVF_BASE_LO: 0x%x\n", 315 read_reg(DEVF_BASE_LO, index)); 316 } 317 318 static void init_map(unsigned int ix) 319 { 320 u32_t v, dom, busno, unit0, unit1; 321 322 dom= 1; 323 busno= 7; 324 unit1= 9; 325 unit0= 9; 326 v= (dom << 26) | (dom << 20) | (busno << 12) | 327 (0 << 11) | (unit1 << 6) | 328 (0 << 5) | (unit0 << 0); 329 write_reg(DEVF_MAP, ix, v); 330 331 printf("after write: DEVF_MAP: 0x%x\n", read_reg(DEVF_MAP, ix)); 332 } 333 334 #if 0 335 static int do_add(message *m) 336 { 337 int r; 338 endpoint_t proc; 339 vir_bytes start; 340 size_t size; 341 phys_bytes busaddr; 342 343 proc= m->m_source; 344 start= m->m2_l1; 345 size= m->m2_l2; 346 347 #if 0 348 printf("amddev`do_add: got request for 0x%x@0x%x from %d\n", 349 size, start, proc); 350 #endif 351 352 if (start % PAGE_SIZE) 353 { 354 printf("amddev`do_add: bad start 0x%x from proc %d\n", 355 start, proc); 356 return EINVAL; 357 } 358 if (size % PAGE_SIZE) 359 { 360 printf("amddev`do_add: bad size 0x%x from proc %d\n", 361 size, proc); 362 return EINVAL; 363 } 364 r= sys_umap_remote(proc, SELF, VM_D, (vir_bytes)start, size, &busaddr); 365 if (r != OK) 366 { 367 printf("amddev`do_add: umap failed for 0x%x@0x%x, proc %d\n", 368 size, start, proc); 369 return r; 370 } 371 add_range(busaddr, size); 372 373 } 374 #endif 375 376 377 378 static int do_add4pci(const message *m) 379 { 380 int r, pci_bus, pci_dev, pci_func; 381 endpoint_t proc; 382 vir_bytes start; 383 size_t size; 384 phys_bytes busaddr; 385 386 proc= m->m_source; 387 start= m->m2_l1; 388 size= m->m2_l2; 389 pci_bus= m->m1_i1; 390 pci_dev= m->m1_i2; 391 pci_func= m->m1_i3; 392 393 printf( 394 "amddev`do_add4pci: got request for 0x%x@0x%lx from %d for pci dev %u.%u.%u\n", 395 size, start, proc, pci_bus, pci_dev, pci_func); 396 397 if (start % PAGE_SIZE) 398 { 399 printf("amddev`do_add4pci: bad start 0x%lx from proc %d\n", 400 start, proc); 401 return EINVAL; 402 } 403 if (size % PAGE_SIZE) 404 { 405 printf("amddev`do_add4pci: bad size 0x%x from proc %d\n", 406 size, proc); 407 return EINVAL; 408 } 409 410 printf("amddev`do_add4pci: should check with PCI\n"); 411 412 r= sys_umap_remote(proc, SELF, VM_D, (vir_bytes)start, size, &busaddr); 413 if (r != OK) 414 { 415 printf( 416 "amddev`do_add4pci: umap failed for 0x%x@0x%lx, proc %d: %d\n", 417 size, start, proc, r); 418 return r; 419 } 420 421 #if 0 422 r= vm_adddma(proc, start, size); 423 if (r != 0) 424 { 425 r= -errno; 426 printf("amddev`do_add4pci: vm_adddma failed for 0x%x@0x%lx, " 427 "proc %d: %d\n", size, start, proc, r); 428 return r; 429 } 430 #endif 431 432 add_range(busaddr, size); 433 434 return OK; 435 } 436 437 438 static void add_range(phys_bytes busaddr, phys_bytes size) 439 { 440 phys_bytes o; 441 442 #if 0 443 printf("add_range: mapping 0x%x@0x%x\n", size, busaddr); 444 #endif 445 446 for (o= 0; o<size; o += PAGE_SIZE) 447 { 448 u32_t bit= (busaddr+o)/PAGE_SIZE; 449 table[bit/8] &= ~(1U << (bit % 8)); 450 } 451 } 452 453 #if 0 454 static void del_range(phys_bytes busaddr, phys_bytes size) 455 { 456 phys_bytes o; 457 458 #if 0 459 printf("del_range: mapping 0x%x@0x%x\n", size, busaddr); 460 #endif 461 462 for (o= 0; o<size; o += PAGE_SIZE) 463 { 464 u32_t bit= (busaddr+o)/PAGE_SIZE; 465 table[bit/8] |= (1 << (bit % 8)); 466 } 467 } 468 #endif 469 470 static void report_exceptions(void) 471 { 472 u32_t status; 473 474 status= read_reg(DEVF_ERR_STATUS, 0); 475 if (!(status & 0x80000000)) 476 return; 477 printf("amddev: status = 0x%x, addr-lo = 0x%x, addr-hi = 0x%x\n", 478 status, read_reg(DEVF_ERR_ADDR_LO, 0), 479 read_reg(DEVF_ERR_ADDR_HI, 0)); 480 write_reg(DEVF_ERR_STATUS, 0, 0); 481 } 482