/////////////////////////////////////////////////////////////////////////////////// // 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 = "); _putx( 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 = "); _putx( 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; /* _puts("\n\n********************** entering v2p_translate"); _puts("\n - pt = "); _putx( (unsigned int)pt ); _puts("\n - vpn = "); _putx( vpn << 12 ); _puts("\n - ptba = "); _putx( pt->pt1[ix1] << 12 ) ; _puts("\n - &pte2 = "); _putx( (pt->pt1[ix1] << 12) + 8*ix2 ); _puts("\n - flags = "); _putx( *(unsigned int*)((pt->pt1[ix1] << 12) + 8*ix2) ); _puts("\n"); */ // 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=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4