/////////////////////////////////////////////////////////////////////////////////// // File : vmem.c // Date : 01/07/2012 // Author : alain greiner // Copyright (c) UPMC-LIP6 /////////////////////////////////////////////////////////////////////////////////// #include #include #include #include ///////////////////////////////////////// void _v2p_translate( page_table_t* ptab, unsigned int vpn, unsigned int* ppn, unsigned int* flags ) { unsigned long long ptba; unsigned long long pte2_paddr; unsigned int pte2_msb; unsigned int pte2_lsb; unsigned int flags_value; unsigned int ppn_value; unsigned int ix1 = vpn >> 9; unsigned int ix2 = vpn & 0x1FF; unsigned int save_sr; // get PTE1 unsigned int pte1 = ptab->pt1[ix1]; // check PTE1 mapping if ( (pte1 & PTE_V) == 0 ) { _printf("\n[VMEM ERROR] _v2p_translate() : pte1 unmapped\n" " vpn = %x / ptab = %x / pte1_vaddr = %x / pte1_value = %x\n", vpn , (unsigned int)ptab, &(ptab->pt1[ix1]) , pte1 ); _exit(); } // test big/small page if ( (pte1 & PTE_T) == 0 ) // big page { // set return values *ppn = ((pte1 << 9) & 0x0FFFFE00) | (vpn & 0X000001FF); *flags = pte1 & 0xFFC00000; } else // small page { // get physical addresses of pte2 ptba = ((unsigned long long)(pte1 & 0x0FFFFFFF)) << 12; pte2_paddr = ptba + 8*ix2; // split physical address in two 32 bits words pte2_lsb = (unsigned int) pte2_paddr; pte2_msb = (unsigned int) (pte2_paddr >> 32); // disable interrupts and save status register _it_disable( &save_sr ); // get ppn_value and flags_value, using a physical read // after temporary DTLB desactivation asm volatile ( "mfc2 $2, $1 \n" /* $2 <= MMU_MODE */ "andi $3, $2, 0xb \n" "mtc2 $3, $1 \n" /* DTLB off */ "move $4, %3 \n" /* $4 <= pte_lsb */ "mtc2 %2, $24 \n" /* PADDR_EXT <= pte_msb */ "lw %0, 0($4) \n" /* read flags */ "lw %1, 4($4) \n" /* read ppn */ "mtc2 $0, $24 \n" /* PADDR_EXT <= 0 */ "mtc2 $2, $1 \n" /* restore MMU_MODE */ : "=r" (flags_value), "=r" (ppn_value) : "r" (pte2_msb) , "r" (pte2_lsb) : "$2", "$3", "$4" ); // restore saved status register _it_restore( &save_sr ); // set return values *ppn = ppn_value & 0x0FFFFFFF; *flags = flags_value & 0xFFC00000; // check PTE2 mapping if ( (flags_value & PTE_V) == 0 ) { _printf("\n[VMEM ERROR] _v2p_translate() : pte2 unmapped\n" " vpn = %x / ptab = %x / pte1_value = %x\n" " pte2_paddr = %l / ppn = %x / flags = %x\n", vpn , ptab , pte1 , pte2_paddr , ppn_value , flags_value ); _exit(); } } } // 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