Changeset 166
- Timestamp:
- Jul 6, 2012, 10:13:16 AM (12 years ago)
- Location:
- soft/giet_vm
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/Makefile
r165 r166 23 23 24 24 SYS_OBJS_LIST = \ 25 vm_handler.o \ 25 26 sys_handler.o \ 26 27 giet.o \ -
soft/giet_vm/giet_config.h
r165 r166 35 35 #define GIET_NB_PT2_MAX 16 /* max number of level 2 page tables per vspace */ 36 36 #define GIET_TICK_VALUE 65536 /* context switch period (number of cycles) */ 37 #define GIET_IOMMU_ACTIVE 0 /* The IOMMU vspace is defined */ 38 #define GIET_IOMMU_CHANNELS 1 /* number of 2Mbytes segments in IOMMU vspace */ 39 #endif 37 40 38 #endif -
soft/giet_vm/sys/common.c
r165 r166 112 112 unsigned int line_size; 113 113 114 /* 115 * compute data cache line size based on config register (bits 12:10) 116 */ 114 // compute data cache line size based on config register (bits 12:10) 117 115 asm volatile("mfc0 %0, $16, 1" : "=r"(tmp)); 118 116 tmp = ((tmp>>10) & 0x7); 119 117 line_size = 2 << tmp; 120 118 121 / * iterate on cache lines to invalidate each one of them */119 // iterate on cache lines 122 120 for (i = 0; i < size; i += line_size) 123 121 { … … 160 158 val /= 16; 161 159 } 160 } 161 /////////////////////////////////////////////////////////////////////////////////// 162 // _get_ptpr() 163 // Access CP2 and returns PTPR register. 164 /////////////////////////////////////////////////////////////////////////////////// 165 inline unsigned int _get_ptpr() 166 { 167 unsigned int ret; 168 asm volatile("mfc2 %0, $0" : "=r"(ret)); 169 return ret; 162 170 } 163 171 /////////////////////////////////////////////////////////////////////////////////// -
soft/giet_vm/sys/common.h
r165 r166 17 17 typedef struct _ld_symbol_s _ld_symbol_t; 18 18 19 extern _ld_symbol_t seg_iob_base; 19 20 extern _ld_symbol_t seg_icu_base; 20 21 extern _ld_symbol_t seg_timer_base; … … 42 43 43 44 unsigned int _get_epc(); 45 unsigned int _get_ptpr(); 44 46 unsigned int _get_bar(); 45 47 unsigned int _get_cr(); -
soft/giet_vm/sys/drivers.c
r165 r166 34 34 /////////////////////////////////////////////////////////////////////////////////// 35 35 36 #include <vm_handler.h> 36 37 #include <sys_handler.h> 37 38 #include <giet_config.h> … … 87 88 in_unckdata volatile unsigned char _dma_busy[NB_DMAS] = { [0 ... NB_DMAS-1] = 0 }; 88 89 89 in_unckdata volatile unsigned char _ioc_status; 90 in_unckdata volatile unsigned char _ioc_done = 0; 91 in_unckdata volatile unsigned int _ioc_lock = 0; 90 in_unckdata volatile unsigned char _ioc_status = 0; 91 in_unckdata volatile unsigned char _ioc_done = 0; 92 in_unckdata unsigned int _ioc_lock = 0; 93 in_unckdata unsigned int _ioc_iommu_ix1 = 0; 94 in_unckdata unsigned int _ioc_iommu_npages = 0; 92 95 93 96 in_unckdata volatile unsigned char _tty_get_buf[NB_TTYS]; … … 394 397 //////////////////////////////////////////////////////////////////////////////// 395 398 // The VciBlockDevice is a single channel external storage contrÃŽler. 396 // The three functions below use the three variables _ioc_lock _ioc_done, and 397 // _ioc_status for synchronisation. 399 // 400 // The IOMMU can be activated or not: 401 // 402 // 1) When the IOMMU is used, a fixed size 2Mbytes vseg is allocated to 403 // the IOC peripheral, in the I/O virtual space, and the user buffer is 404 // dynamically remapped in the IOMMU page table. The corresponding entry 405 // in the IOMMU PT1 is defined by the kernel _ioc_iommu_ix1 variable. 406 // The number of pages to be unmapped is stored in the _ioc_npages variable. 407 // The number of PT2 entries is dynamically computed and stored in the 408 // kernel _ioc_iommu_npages variable. It cannot be larger than 512. 409 // The user buffer is unmapped by the _ioc_completed() function when 410 // the transfer is completed. 411 // 412 // 2/ If the IOMMU is not used, we check that the user buffer is mapped to a 413 // contiguous physical buffer (this is generally true because the user space 414 // page tables are statically constructed to use contiguous physical memory). 415 // 416 // Finally, the memory buffer must fulfill the following conditions: 417 // - The user buffer must be word aligned, 418 // - The user buffer must be mapped in user address space, 419 // - The user buffer must be writable in case of (to_mem) access, 420 // - The total number of physical pages occupied by the user buffer cannot 421 // be larger than 512 pages if the IOMMU is activated, 422 // - All physical pages occupied by the user buffer must be contiguous 423 // if the IOMMU is not activated. 424 // An error code is returned if these conditions are not verified. 425 // 398 426 // As the IOC component can be used by several programs running in parallel, 399 427 // the _ioc_lock variable guaranties exclusive access to the device. The … … 407 435 // variable. 408 436 // The _ioc_completed() function is polling the _ioc_done variable, waiting for 409 // tran fer conpletion. When the completion is signaled, the _ioc_completed()437 // transfer completion. When the completion is signaled, the _ioc_completed() 410 438 // function reset the _ioc_done variable to zero, and releases the _ioc_lock 411 439 // variable. … … 447 475 448 476 /////////////////////////////////////////////////////////////////////////////// 449 // _ioc_write() 450 // 451 // Transfer data from a memory buffer to a file on the block_device. 452 // The source memory buffer must be in user address space. 453 // - lba : first block index on the disk. 454 // - buffer : base address of the memory buffer. 477 // _ioc_access() 478 // This function transfer data between a memory buffer and the block device. 479 // The buffer lentgth is (count*block_size) bytes. 480 // 481 // Arguments are: 482 // - to_mem : from external storage to memory when non 0 483 // - lba : first block index on the external storage. 484 // - user_vaddr : virtual base address of the memory buffer. 485 // - count : number of blocks to be transfered. 486 // Returns 0 if success, > 0 if error. 487 /////////////////////////////////////////////////////////////////////////////// 488 unsigned int _ioc_access( unsigned int to_mem, 489 unsigned int lba, 490 unsigned int user_vaddr, 491 unsigned int count ) 492 { 493 unsigned int user_vpn_min; 494 unsigned int user_vpn_max; 495 unsigned int vpn; // virtual page number in user space 496 unsigned int ppn; // physical page number 497 unsigned int flags; // page protection flags 498 unsigned int ix2; // Page index (for IOMMU page table) 499 unsigned int addr; // buffer address for IOC 500 page_table_t* user_ptp; // user page table pointer 501 unsigned int ko; // bool returned by _v2p_translate() 502 unsigned int ppn_first; // first physical page number for user buffer 503 504 // check buffer alignment 505 if ( (unsigned int)user_vaddr & 0x3 ) return 1; 506 507 unsigned int* ioc_address = (unsigned int*)&seg_ioc_base; 508 unsigned int block_size = ioc_address[BLOCK_DEVICE_BLOCK_SIZE]; 509 unsigned int length = count*block_size; 510 511 // get user space page table base address 512 user_ptp = (page_table_t*)(_get_ptpr() << 13); 513 514 user_vpn_min = user_vaddr >> 12; 515 user_vpn_max = (user_vaddr + length - 1) >> 12; 516 ix2 = 0; 517 518 // loop on all virtual pages covering the user buffer 519 for ( vpn = user_vpn_min ; vpn <= user_vpn_max ; vpn++ ) 520 { 521 // get ppn and flags for each vpn 522 ko = _v2p_translate( user_ptp, // user page table pointer 523 vpn, // virtual page number 524 &ppn, // physical page number 525 &flags ); // protection flags 526 527 // check access rights 528 if ( ko ) return 2; // unmapped 529 if ( (flags & PTE_U) == 0 ) return 3; // not in user space 530 if ( ( (flags & PTE_W) == 0 ) && to_mem ) return 4; // not writable 531 532 // save first ppn value 533 if ( ix2 == 0 ) ppn_first = ppn; 534 535 if ( GIET_IOMMU_ACTIVE ) // the user buffer must be remapped in the I/0 space 536 { 537 // check buffer length < 2 Mbytes 538 if ( ix2 > 511 ) return 2; 539 540 // map the physical page in IOMMU page table 541 _iommu_add_pte2( _ioc_iommu_ix1, // PT1 index 542 ix2, // PT2 index 543 ppn, // Physical page number 544 flags ); // Protection flags 545 546 // buffer base address for IOC with IOMMU 547 } 548 else // no IOMMU : check that physical pages are contiguous 549 { 550 if ( (ppn - ppn_first) != ix2 ) return 5; // split physical buffer 551 } 552 553 // increment page index 554 ix2++; 555 } // end for vpn 556 557 // register the number of pages to be unmapped 558 _ioc_iommu_npages = (user_vpn_max - user_vpn_min) + 1; 559 560 // invalidate data cache in case of memory write 561 if ( to_mem ) _dcache_buf_invalidate( (void*)user_vaddr, length ); 562 563 // compute buffer base address for IOC depending on IOMMU activation 564 if ( GIET_IOMMU_ACTIVE ) addr = (_ioc_iommu_ix1) << 21 | (user_vaddr & 0xFFF); 565 else addr = ppn_first | (user_vaddr & 0xFFF); 566 567 // get the lock on ioc device 568 _ioc_get_lock(); 569 570 // peripheral configuration 571 ioc_address[BLOCK_DEVICE_BUFFER] = addr; 572 ioc_address[BLOCK_DEVICE_COUNT] = count; 573 ioc_address[BLOCK_DEVICE_LBA] = lba; 574 if ( to_mem == 0 ) ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_WRITE; 575 else ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_READ; 576 577 return 0; 578 } 579 580 ///////////////////////////////////////////////////////////////////////////////// 581 // _ioc_completed() 582 // 583 // This function checks completion of an I/O transfer and reports errors. 584 // As it is a blocking call, the processor is stalled. 585 // If the virtual memory is activated, the pages mapped in the I/O virtual 586 // space are unmapped, and the IOB TLB is cleared. 587 // Returns 0 if success, > 0 if error. 588 ///////////////////////////////////////////////////////////////////////////////// 589 unsigned int _ioc_completed() 590 { 591 unsigned int ret; 592 unsigned int ix2; 593 594 // busy waiting 595 while (_ioc_done == 0) 596 asm volatile("nop"); 597 598 // unmap the buffer from IOMMU page table if IOMMU is activated 599 if ( GIET_IOMMU_ACTIVE ) 600 { 601 unsigned int* iob_address = (unsigned int*)&seg_iob_base; 602 603 for ( ix2 = 0 ; ix2 < _ioc_iommu_npages ; ix2++ ) 604 { 605 // unmap the page in IOMMU page table 606 _iommu_inval_pte2( _ioc_iommu_ix1, // PT1 index 607 ix2 ); // PT2 index 608 609 // clear IOMMU TLB 610 iob_address[IOB_INVAL_PTE] = (_ioc_iommu_ix1 << 21) | (ix2) << 12; 611 } 612 } 613 614 // test IOC status 615 if ((_ioc_status != BLOCK_DEVICE_READ_SUCCESS) 616 && (_ioc_status != BLOCK_DEVICE_WRITE_SUCCESS)) ret = 1; // error 617 else ret = 0; // success 618 619 // reset synchronization variables 620 _ioc_lock =0; 621 _ioc_done =0; 622 623 return ret; 624 } 625 626 /////////////////////////////////////////////////////////////////////////////// 627 // _ioc_read() 628 // Transfer data from the block device to a memory buffer in user space. 629 // - lba : first block index on the block device 630 // - buffer : base address of the memory buffer (must be word aligned) 631 // - count : number of blocks to be transfered. 632 // Returns 0 if success, > 0 if error. 633 /////////////////////////////////////////////////////////////////////////////// 634 unsigned int _ioc_read( unsigned int lba, 635 void* buffer, 636 unsigned int count ) 637 { 638 return _ioc_access( 1, // read 639 lba, 640 (unsigned int)buffer, 641 count ); 642 } 643 644 /////////////////////////////////////////////////////////////////////////////// 645 // _ioc_write() 646 // Transfer data from a memory buffer in user space to the block device. 647 // - lba : first block index on the block device 648 // - buffer : base address of the memory buffer (must be word aligned) 455 649 // - count : number of blocks to be transfered. 456 650 // Returns 0 if success, > 0 if error. … … 458 652 unsigned int _ioc_write( unsigned int lba, 459 653 const void* buffer, 460 unsigned int count) 461 { 462 volatile unsigned int *ioc_address; 463 464 ioc_address = (unsigned int*)&seg_ioc_base; 465 466 /* buffer must be in user space */ 467 unsigned int block_size = ioc_address[BLOCK_DEVICE_BLOCK_SIZE]; 468 469 if (((unsigned int)buffer >= 0x80000000) 470 || (((unsigned int)buffer + block_size*count) >= 0x80000000)) 471 return 1; 472 473 /* get the lock on ioc device */ 474 _ioc_get_lock(); 475 476 /* block_device configuration for the write transfer */ 477 ioc_address[BLOCK_DEVICE_BUFFER] = (unsigned int)buffer; 478 ioc_address[BLOCK_DEVICE_COUNT] = count; 479 ioc_address[BLOCK_DEVICE_LBA] = lba; 480 ioc_address[BLOCK_DEVICE_IRQ_ENABLE] = 1; 481 ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_WRITE; 482 483 return 0; 484 } 485 486 /////////////////////////////////////////////////////////////////////////////// 487 // _ioc_read() 488 // 489 // Transfer data from a file on the block device to a memory buffer. 490 // The destination memory buffer must be in user address space. 491 // - lba : first block index on the disk. 492 // - buffer : base address of the memory buffer. 493 // - count : number of blocks to be transfered. 494 // All cache lines corresponding to the the target buffer are invalidated 495 // for cache coherence. 496 // Returns 0 if success, > 0 if error. 497 /////////////////////////////////////////////////////////////////////////////// 498 unsigned int _ioc_read( unsigned int lba, 499 void* buffer, 500 unsigned int count ) 501 { 502 volatile unsigned int *ioc_address; 503 504 ioc_address = (unsigned int*)&seg_ioc_base; 505 506 /* buffer must be in user space */ 507 unsigned int block_size = ioc_address[BLOCK_DEVICE_BLOCK_SIZE]; 508 509 if (((unsigned int)buffer >= 0x80000000) 510 || (((unsigned int)buffer + block_size*count) >= 0x80000000)) 511 return 1; 512 513 /* get the lock on ioc device */ 514 _ioc_get_lock(); 515 516 /* block_device configuration for the read transfer */ 517 ioc_address[BLOCK_DEVICE_BUFFER] = (unsigned int)buffer; 518 ioc_address[BLOCK_DEVICE_COUNT] = count; 519 ioc_address[BLOCK_DEVICE_LBA] = lba; 520 ioc_address[BLOCK_DEVICE_IRQ_ENABLE] = 1; 521 ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_READ; 522 523 /* invalidation of data cache */ 524 _dcache_buf_invalidate(buffer, block_size*count); 525 526 return 0; 527 } 528 529 ///////////////////////////////////////////////////////////////////////////////// 530 // _ioc_completed() 531 // 532 // This function checks completion of an I/O transfer and reports errors. 533 // As it is a blocking call, the processor is stalled until the next interrupt. 534 // Returns 0 if success, > 0 if error. 535 ///////////////////////////////////////////////////////////////////////////////// 536 unsigned int _ioc_completed() 537 { 538 unsigned int ret; 539 540 /* busy waiting */ 541 while (_ioc_done == 0) 542 asm volatile("nop"); 543 544 /* test IOC status */ 545 if ((_ioc_status != BLOCK_DEVICE_READ_SUCCESS) 546 && (_ioc_status != BLOCK_DEVICE_WRITE_SUCCESS)) ret = 1; /* error */ 547 else ret = 0; /* success */ 548 549 /* reset synchronization variables */ 550 _ioc_lock =0; 551 _ioc_done =0; 552 553 return ret; 654 unsigned int count ) 655 { 656 return _ioc_access( 0, // write 657 lba, 658 (unsigned int)buffer, 659 count ); 554 660 } 555 661 -
soft/giet_vm/sys/drivers.h
r165 r166 18 18 extern volatile unsigned char _ioc_status; 19 19 extern volatile unsigned char _ioc_done; 20 extern volatile unsigned int_ioc_lock;20 extern unsigned int _ioc_lock; 21 21 22 22 extern volatile unsigned char _tty_get_buf[]; -
soft/giet_vm/sys/hwr_mapping.h
r158 r166 86 86 }; 87 87 88 /* IOB */ 89 enum IOB_registers { 90 IOB_IOMMU_PTPR = 0, /* R/W : Page Table Pointer Register */ 91 IOB_IOMMU_ACTIVE = 1, /* R/W : IOMMU activated if not 0 */ 92 IOB_IOMMU_BVAR = 2, /* R : Bad Virtual Address (unmapped) */ 93 IOB_IOMMU_ETR = 3, /* R : Error Type */ 94 IOB_IOMMU_BAD_ID = 4, /* R : Faulty Peripheral Index */ 95 IOB_INVAL_PTE = 5, /* W : Invalidate a PTE (virtual address) */ 96 IOB_IT_ADDR_IOMMU_LO = 6, /* W/R : 32 LSB bits for IOMMU IT*/ 97 IOB_IT_ADDR_IOMMU_HI = 7, /* W/R : 32 MSB bits for IOMMU IT */ 98 IOB_IT_ADDRESS_BEGIN = 8, /* R/W : Peripheral IT address (2 32 bits registers) */ 99 }; 100 88 101 #endif 89 102 -
soft/giet_vm/sys/kernel_init.c
r165 r166 22 22 #include <mips32_registers.h> 23 23 #include <irq_handler.h> 24 #include <vm_handler.h> 24 25 #include <hwr_mapping.h> 25 26 #include <mwmr_channel.h> … … 523 524 524 525 //////////////////////////////////////////////////////////////////////////////// 525 // This function intializes the external periherals such as the TTY controller,526 // the IOC (external disk controller), the NIC (external network controller),527 // the FBDMA (frame buffer controller), etc.526 // This function intializes the external periherals such as the IOB component 527 // (I/O bridge, containing the IOMMU, the IOC (external disk controller), 528 // the NIC (external network controller), the FBDMA (frame buffer controller), 528 529 //////////////////////////////////////////////////////////////////////////////// 529 530 in_kinit void _kernel_peripherals_init() 530 531 { 532 // IOC peripheral initialisation 533 // we simply activate the IOC interrupts... 534 unsigned int* ioc_address = (unsigned int*)&seg_ioc_base; 535 536 ioc_address[BLOCK_DEVICE_IRQ_ENABLE] = 1; 537 538 // IOB peripheral 539 if ( GIET_IOMMU_ACTIVE ) 540 { 541 unsigned int* iob_address = (unsigned int*)&seg_iob_base; 542 unsigned int icu_address = (unsigned int)&seg_icu_base; 543 544 // define IPI address mapping the IOC interrupt ...TODO... 545 546 // set IOMMU page table address 547 iob_address[IOB_IOMMU_PTPR] = (unsigned int)(&_iommu_ptab); 548 549 // activate IOMMU 550 iob_address[IOB_IOMMU_ACTIVE] = 1; 551 } 552 531 553 _puts("\n[INIT] Peripherals initialisation completed at cycle "); 532 554 _putw( _proctime() ); … … 536 558 537 559 //////////////////////////////////////////////////////////////////////////////// 538 // This function intialises the centralised interrupt vector,539 // and the ICUsmask registers for all processors in all clusters.560 // This function intialises the interrupt vector, and initialises 561 // the ICU mask registers for all processors in all clusters. 540 562 // It strongly depends on the actual peripheral hardware wiring. 541 563 // In this peculiar version, all clusters are identical, -
soft/giet_vm/sys/sys.ld
r165 r166 22 22 seg_gcd_base = 0x95000000; /* GCD device */ 23 23 seg_fb_base = 0x96000000; /* FrameBuffer device */ 24 seg_icu_base = 0x9F000000; /* ICU device */ 24 seg_icu_base = 0x9F000000; /* ICU or XICU device */ 25 seg_iob_base = 0x9E000000; /* IOB device */ 25 26 26 27 /*
Note: See TracChangeset
for help on using the changeset viewer.