/////////////////////////////////////////////////////////////////////////////////// // 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. /////////////////////////////////////////////////////////////////////////////////// #include #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) { _get_lock(&_tty_put_lock); _puts("\n[GIET ERROR] in iommu_add_pte2 function\n"); _puts("the IOMMU PT1 entry is not mapped / ix1 = "); _putx( ix1 ); _puts("\n"); _release_lock(&_tty_put_lock); _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) { paddr_t ptba; paddr_t pte2; register unsigned int pte2_msb; register unsigned int pte2_lsb; 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 = (paddr_t) (pt->pt1[ix1] & 0x0FFFFFFF) << 12; pte2 = ptba + 8 * ix2; pte2_lsb = (unsigned int) pte2; pte2_msb = (unsigned int) (pte2 >> 32); // gets ppn_value and flags_value, after temporary DTLB desactivation asm volatile ( "li $2, 0xFFFFFFFE \n" /* Mask for IE bits */ "mfc0 $4, $12 \n" /* $4 <= SR */ "and $2, $2, $4 \n" "mtc0 $2, $12 \n" /* disable Interrupts */ "li $3, 0xB \n" "mtc2 $3, $1 \n" /* DTLB unactivated */ "mtc2 %2, $24 \n" /* PADDR_EXT <= msb */ "lw %0, 0(%3) \n" /* read flags */ "lw %1, 4(%3) \n" /* read ppn */ "mtc2 $0, $24 \n" /* PADDR_EXT <= 0 */ "li $3, 0xF \n" "mtc2 $3, $1 \n" /* DTLB activated */ "mtc0 $4, $12 \n" /* restore SR */ : "=r" (flags_value), "=r" (ppn_value) : "r" (pte2_msb), "r" (pte2_lsb) : "$2","$3","$4"); // 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