/////////////////////////////////////////////////////////////////////////////////// // File : vm_handler.c // Date : 01/07/2012 // Author : alain greiner // Copyright (c) UPMC-LIP6 /////////////////////////////////////////////////////////////////////////////////// // The vm_handler.c and vm_handler.h files are part ot the GIET nano kernel. // They contains the kernel data structures and functions used to dynamically // handle the iommu page table. // // TODO : We must transfer here the functions used to statically build // the page tables associated to the various vspaces (now in boot_handler.c) // /////////////////////////////////////////////////////////////////////////////////// #include #include #include #include ///////////////////////////////////////////////////////////////////////////// // Global variable : IOMMU page table ///////////////////////////////////////////////////////////////////////////// __attribute__((section (".iommu"))) page_table_t _iommu_ptab; ////////////////////////////////////////////////////////////////////////////// // _iommu_add_pte2() ////////////////////////////////////////////////////////////////////////////// void _iommu_add_pte2( unsigned int ix1, unsigned int ix2, unsigned int ppn, unsigned int flags ) { unsigned int ptba; unsigned int* pt_ppn; unsigned int* pt_flags; // get pointer on iommu page table page_table_t* pt = &_iommu_ptab; // get ptba and update PT2 if ( (pt->pt1[ix1] & PTE_V) == 0 ) { _puts("\n[GIET ERROR] in iommu_add_pte2 function\n"); _puts("the IOMMU PT1 entry is not mapped / ix1 = "); _putw( ix1 ); _puts("\n"); _exit(); } else { ptba = pt->pt1[ix1] << 12; pt_flags = (unsigned int*)(ptba + 8*ix2); pt_ppn = (unsigned int*)(ptba + 8*ix2 + 4); *pt_flags = flags; *pt_ppn = ppn; } } // end _iommu_add_pte2() ////////////////////////////////////////////////////////////////////////////// // _iommu_inval_pte2() ////////////////////////////////////////////////////////////////////////////// void _iommu_inval_pte2( unsigned int ix1, unsigned int ix2 ) { unsigned int ptba; unsigned int* pt_flags; // get pointer on iommu page table page_table_t* pt = &_iommu_ptab; // get ptba and inval PTE2 if ( (pt->pt1[ix1] & PTE_V) == 0 ) { _puts("\n[GIET ERROR] in iommu_inval_pte2 function\n"); _puts("the IOMMU PT1 entry is not mapped / ix1 = "); _putw( ix1 ); _puts("\n"); _exit(); } else { ptba = pt->pt1[ix1] << 12; pt_flags = (unsigned int*)(ptba + 8*ix2); *pt_flags = 0; } } // end _iommu_inval_pte2() ////////////////////////////////////////////////////////////////////////////// // _v2p_translate() // Returns 0 if success, 1 if PTE1 or PTE2 unmapped ////////////////////////////////////////////////////////////////////////////// unsigned int _v2p_translate( page_table_t* pt, unsigned int vpn, unsigned int* ppn, unsigned int* flags ) { unsigned int ptba; register unsigned int* pte2; register unsigned int flags_value; register unsigned int ppn_value; unsigned int ix1 = vpn >> 9; unsigned int ix2 = vpn & 0x1FF; // check PTE1 mapping if ( (pt->pt1[ix1] & PTE_V) == 0 ) { return 1; } else { // get physical addresses of pte2 ptba = pt->pt1[ix1] << 12; pte2 = (unsigned int*)(ptba + 8*ix2); // gets ppn_value and flags_value, after temporary DTLB desactivation asm volatile ( "li $27, 0xFFFFFFFE \n" /* Mask for IE bits */ "mfc0 $26, $12 \n" /* save SR */ "and $27, $26, $27 \n" "mtc0 $27, $12 \n" /* disable Interrupts */ "li $27, 0xB \n" "mtc2 $27, $1 \n" /* DTLB unactivated */ "move $27, %2 \n" /* $27 <= pte2 */ "lw %0, 0($27) \n" /* read flags */ "lw %1, 4($27) \n" /* read ppn */ "li $27, 0xF \n" "mtc2 $27, $1 \n" /* DTLB activated */ "mtc0 $26, $12 \n" /* restore SR */ :"=r"(flags_value), "=r"(ppn_value) :"r"(pte2) :"$26","$27","$8" ); // check PTE2 mapping if ( (flags_value & PTE_V) == 0 ) { return 1; } // set return values *ppn = ppn_value; *flags = flags_value; } return 0; } // end _v2p_translate() // Local Variables: // tab-width: 4 // c-basic-offset: 4 // c-file-offsets:((innamespace . 0)(inline-open . 0)) // indent-tabs-mode: nil // End: // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=4:softtabstop=4