X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Farch%2Fx86%2Fmm_virt.c;h=6976c6577db0eed8f6d63290d8f8ff28ffb156a1;hb=049de1f2533477716a12a708c097b199eaa8fb6c;hp=f5b89590f4e0c02954ba47ba7fdc2013d2d36a83;hpb=b6c3b3cf61caafbd91bbf3acc81995e472656a5b;p=tpg%2Facess2.git diff --git a/Kernel/arch/x86/mm_virt.c b/Kernel/arch/x86/mm_virt.c index f5b89590..6976c657 100644 --- a/Kernel/arch/x86/mm_virt.c +++ b/Kernel/arch/x86/mm_virt.c @@ -10,28 +10,46 @@ * 0xFF - System Calls / Kernel's User Code */ #define DEBUG 1 -#include +#define SANITY 1 +#include #include #include +#if USE_PAE +# define TAB 21 +# define DIR 30 +#else +# define TAB 22 +#endif + #define KERNEL_STACKS 0xF0000000 -#define KERNEL_STACK_SIZE 0x00002000 -#define KERNEL_STACKS_END 0xFD000000 +#define KERNEL_STACK_SIZE 0x00008000 +#define KERNEL_STACKS_END 0xFC000000 #define WORKER_STACKS 0x00100000 // Thread0 Only! #define WORKER_STACK_SIZE KERNEL_STACK_SIZE #define WORKER_STACKS_END 0xB0000000 #define NUM_WORKER_STACKS ((WORKER_STACKS_END-WORKER_STACKS)/WORKER_STACK_SIZE) -#define PAGE_TABLE_ADDR 0xFD000000 -#define PAGE_DIR_ADDR 0xFD3F4000 -#define PAGE_CR3_ADDR 0xFD3F4FD0 -#define TMP_CR3_ADDR 0xFD3F4FD4 // Part of core instead of temp -#define TMP_DIR_ADDR 0xFD3F5000 // Same -#define TMP_TABLE_ADDR 0xFD400000 -#define HW_MAP_ADDR 0xFD800000 -#define HW_MAP_MAX 0xFEFF0000 + +#define PAE_PAGE_TABLE_ADDR 0xFC000000 // 16 MiB +#define PAE_PAGE_DIR_ADDR 0xFCFC0000 // 16 KiB +#define PAE_PAGE_PDPT_ADDR 0xFCFC3F00 // 32 bytes +#define PAE_TMP_PDPT_ADDR 0xFCFC3F20 // 32 bytes +#define PAE_TMP_DIR_ADDR 0xFCFE0000 // 16 KiB +#define PAE_TMP_TABLE_ADDR 0xFD000000 // 16 MiB + +#define PAGE_TABLE_ADDR 0xFC000000 +#define PAGE_DIR_ADDR 0xFC3F0000 +#define PAGE_CR3_ADDR 0xFC3F0FC0 +#define TMP_CR3_ADDR 0xFC3F0FC4 // Part of core instead of temp +#define TMP_DIR_ADDR 0xFC3F1000 // Same +#define TMP_TABLE_ADDR 0xFC400000 + +#define HW_MAP_ADDR 0xFE000000 +#define HW_MAP_MAX 0xFFEF0000 #define NUM_HW_PAGES ((HW_MAP_MAX-HW_MAP_ADDR)/0x1000) -#define TEMP_MAP_ADDR 0xFEFF0000 // Allows 16 "temp" pages +#define TEMP_MAP_ADDR 0xFFEF0000 // Allows 16 "temp" pages #define NUM_TEMP_PAGES 16 +#define LAST_BLOCK_ADDR 0xFFFF0000 // Free space for kernel provided user code/ *(-1) protection #define PF_PRESENT 0x1 #define PF_WRITE 0x2 @@ -41,29 +59,43 @@ #define INVLPG(addr) __asm__ __volatile__ ("invlpg (%0)"::"r"(addr)) +#if USE_PAE +typedef Uint64 tTabEnt; +#else +typedef Uint32 tTabEnt; +#endif + // === IMPORTS === extern Uint32 gaInitPageDir[1024]; extern Uint32 gaInitPageTable[1024]; -extern void Threads_SegFault(Uint Addr); +extern void Threads_SegFault(tVAddr Addr); extern void Error_Backtrace(Uint eip, Uint ebp); // === PROTOTYPES === void MM_PreinitVirtual(); void MM_InstallVirtual(); -void MM_PageFault(Uint Addr, Uint ErrorCode, tRegs *Regs); +void MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs); void MM_DumpTables(tVAddr Start, tVAddr End); -tPAddr MM_DuplicatePage(Uint VAddr); +tPAddr MM_DuplicatePage(tVAddr VAddr); // === GLOBALS === -tPAddr *gaPageTable = (void*)PAGE_TABLE_ADDR; -tPAddr *gaPageDir = (void*)PAGE_DIR_ADDR; -tPAddr *gaPageCR3 = (void*)PAGE_CR3_ADDR; -tPAddr *gaTmpTable = (void*)TMP_TABLE_ADDR; -tPAddr *gaTmpDir = (void*)TMP_DIR_ADDR; -tPAddr *gTmpCR3 = (void*)TMP_CR3_ADDR; +#define gaPageTable ((tTabEnt*)PAGE_TABLE_ADDR) +#define gaPageDir ((tTabEnt*)PAGE_DIR_ADDR) +#define gaTmpTable ((tTabEnt*)TMP_TABLE_ADDR) +#define gaTmpDir ((tTabEnt*)TMP_DIR_ADDR) +#define gpPageCR3 ((tTabEnt*)PAGE_CR3_ADDR) +#define gpTmpCR3 ((tTabEnt*)TMP_CR3_ADDR) + +#define gaPAE_PageTable ((tTabEnt*)PAE_PAGE_TABLE_ADDR) +#define gaPAE_PageDir ((tTabEnt*)PAE_PAGE_DIR_ADDR) +#define gaPAE_MainPDPT ((tTabEnt*)PAE_PAGE_PDPT_ADDR) +#define gaPAE_TmpTable ((tTabEnt*)PAE_TMP_DIR_ADDR) +#define gaPAE_TmpDir ((tTabEnt*)PAE_TMP_DIR_ADDR) +#define gaPAE_TmpPDPT ((tTabEnt*)PAE_TMP_PDPT_ADDR) + int gbUsePAE = 0; int gilTempMappings = 0; int gilTempFractal = 0; -Uint32 gWorkerStacks[NUM_WORKER_STACKS/32]; +Uint32 gWorkerStacks[(NUM_WORKER_STACKS+31)/32]; int giLastUsedWorker = 0; // === CODE === @@ -73,8 +105,12 @@ Uint32 gWorkerStacks[NUM_WORKER_STACKS/32]; */ void MM_PreinitVirtual() { - gaInitPageDir[ 0 ] = 0; - gaInitPageDir[ PAGE_TABLE_ADDR >> 22 ] = ((Uint)&gaInitPageDir - KERNEL_BASE) | 3; + #if USE_PAE + gaInitPageDir[ ((PAGE_TABLE_ADDR >> TAB)-3*512+3)*2 ] = ((tTabEnt)&gaInitPageDir - KERNEL_BASE) | 3; + #else + gaInitPageDir[ PAGE_TABLE_ADDR >> 22 ] = ((tTabEnt)&gaInitPageDir - KERNEL_BASE) | 3; + #endif + INVLPG( PAGE_TABLE_ADDR ); } /** @@ -85,6 +121,23 @@ void MM_InstallVirtual() { int i; + #if USE_PAE + // --- Pre-Allocate kernel tables + for( i = KERNEL_BASE >> TAB; i < 1024*4; i ++ ) + { + if( gaPAE_PageDir[ i ] ) continue; + + // Skip stack tables, they are process unique + if( i > KERNEL_STACKS >> TAB && i < KERNEL_STACKS_END >> TAB) { + gaPAE_PageDir[ i ] = 0; + continue; + } + // Preallocate table + gaPAE_PageDir[ i ] = MM_AllocPhys() | 3; + INVLPG( &gaPAE_PageTable[i*512] ); + memset( &gaPAE_PageTable[i*512], 0, 0x1000 ); + } + #else // --- Pre-Allocate kernel tables for( i = KERNEL_BASE>>22; i < 1024; i ++ ) { @@ -99,13 +152,26 @@ void MM_InstallVirtual() INVLPG( &gaPageTable[i*1024] ); memset( &gaPageTable[i*1024], 0, 0x1000 ); } + #endif +} + +/** + * \brief Cleans up the SMP required mappings + */ +void MM_FinishVirtualInit() +{ + #if USE_PAE + gaInitPDPT[ 0 ] = 0; + #else + gaInitPageDir[ 0 ] = 0; + #endif } /** - * \fn void MM_PageFault(Uint Addr, Uint ErrorCode, tRegs *Regs) + * \fn void MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs) * \brief Called on a page fault */ -void MM_PageFault(Uint Addr, Uint ErrorCode, tRegs *Regs) +void MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs) { //ENTER("xAddr bErrorCode", Addr, ErrorCode); @@ -122,6 +188,7 @@ void MM_PageFault(Uint Addr, Uint ErrorCode, tRegs *Regs) } else { + //Log("MM_PageFault: COW - MM_DuplicatePage(0x%x)", Addr); paddr = MM_DuplicatePage( Addr ); MM_DerefPhys( gaPageTable[Addr>>12] & ~0xFFF ); gaPageTable[Addr>>12] &= PF_USER; @@ -168,13 +235,13 @@ void MM_PageFault(Uint Addr, Uint ErrorCode, tRegs *Regs) if( gaPageDir[Addr>>22] & PF_PRESENT ) Log("gaPageTable[0x%x] = 0x%x", Addr>>12, gaPageTable[Addr>>12]); - MM_DumpTables(0, -1); + //MM_DumpTables(0, -1); - Panic("Page Fault at 0x%x\n", Regs->eip); + Panic("Page Fault at 0x%x (Accessed 0x%x)", Regs->eip, Addr); } /** - * \fn void MM_DumpTables(Uint Start, Uint End) + * \fn void MM_DumpTables(tVAddr Start, tVAddr End) * \brief Dumps the layout of the page tables */ void MM_DumpTables(tVAddr Start, tVAddr End) @@ -248,18 +315,22 @@ void MM_DumpTables(tVAddr Start, tVAddr End) } /** - * \fn tPAddr MM_Allocate(Uint VAddr) + * \fn tPAddr MM_Allocate(tVAddr VAddr) */ -tPAddr MM_Allocate(Uint VAddr) +tPAddr MM_Allocate(tVAddr VAddr) { tPAddr paddr; + //ENTER("xVAddr", VAddr); + //__asm__ __volatile__ ("xchg %bx,%bx"); // Check if the directory is mapped if( gaPageDir[ VAddr >> 22 ] == 0 ) { // Allocate directory paddr = MM_AllocPhys(); + //LOG("paddr = 0x%llx (new table)", paddr); if( paddr == 0 ) { Warning("MM_Allocate - Out of Memory (Called by %p)", __builtin_return_address(0)); + //LEAVE('i',0); return 0; } // Map @@ -268,19 +339,23 @@ tPAddr MM_Allocate(Uint VAddr) if(VAddr < MM_USER_MAX) gaPageDir[ VAddr >> 22 ] |= PF_USER; INVLPG( &gaPageDir[ VAddr >> 22 ] ); + //LOG("Clearing new table"); memsetd( &gaPageTable[ (VAddr >> 12) & ~0x3FF ], 0, 1024 ); } // Check if the page is already allocated else if( gaPageTable[ VAddr >> 12 ] != 0 ) { Warning("MM_Allocate - Allocating to used address (%p)", VAddr); + //LEAVE('X', gaPageTable[ VAddr >> 12 ] & ~0xFFF); return gaPageTable[ VAddr >> 12 ] & ~0xFFF; } // Allocate paddr = MM_AllocPhys(); + //LOG("paddr = 0x%llx", paddr); if( paddr == 0 ) { Warning("MM_Allocate - Out of Memory when allocating at %p (Called by %p)", VAddr, __builtin_return_address(0)); + //LEAVE('i',0); return 0; } // Map @@ -290,13 +365,14 @@ tPAddr MM_Allocate(Uint VAddr) // Invalidate Cache for address INVLPG( VAddr & ~0xFFF ); + //LEAVE('X', paddr); return paddr; } /** - * \fn void MM_Deallocate(Uint VAddr) + * \fn void MM_Deallocate(tVAddr VAddr) */ -void MM_Deallocate(Uint VAddr) +void MM_Deallocate(tVAddr VAddr) { if( gaPageDir[ VAddr >> 22 ] == 0 ) { Warning("MM_Deallocate - Directory not mapped"); @@ -315,10 +391,10 @@ void MM_Deallocate(Uint VAddr) } /** - * \fn tPAddr MM_GetPhysAddr(Uint Addr) + * \fn tPAddr MM_GetPhysAddr(tVAddr Addr) * \brief Checks if the passed address is accesable */ -tPAddr MM_GetPhysAddr(Uint Addr) +tPAddr MM_GetPhysAddr(tVAddr Addr) { if( !(gaPageDir[Addr >> 22] & 1) ) return 0; @@ -327,20 +403,36 @@ tPAddr MM_GetPhysAddr(Uint Addr) return (gaPageTable[Addr >> 12] & ~0xFFF) | (Addr & 0xFFF); } + /** - * \fn void MM_SetCR3(Uint CR3) + * \fn int MM_IsUser(tVAddr VAddr) + * \brief Checks if a page is user accessable + */ +int MM_IsUser(tVAddr VAddr) +{ + if( !(gaPageDir[VAddr >> 22] & 1) ) + return 0; + if( !(gaPageTable[VAddr >> 12] & 1) ) + return 0; + if( !(gaPageTable[VAddr >> 12] & PF_USER) ) + return 0; + return 1; +} + +/** + * \fn void MM_SetCR3(tPAddr CR3) * \brief Sets the current process space */ -void MM_SetCR3(Uint CR3) +void MM_SetCR3(tPAddr CR3) { __asm__ __volatile__ ("mov %0, %%cr3"::"r"(CR3)); } /** - * \fn int MM_Map(Uint VAddr, tPAddr PAddr) + * \fn int MM_Map(tVAddr VAddr, tPAddr PAddr) * \brief Map a physical page to a virtual one */ -int MM_Map(Uint VAddr, tPAddr PAddr) +int MM_Map(tVAddr VAddr, tPAddr PAddr) { //ENTER("xVAddr xPAddr", VAddr, PAddr); // Sanity check @@ -390,10 +482,10 @@ int MM_Map(Uint VAddr, tPAddr PAddr) } /** - * \fn Uint MM_ClearUser() + * \fn tVAddr MM_ClearUser() * \brief Clear user's address space */ -Uint MM_ClearUser() +tVAddr MM_ClearUser() { Uint i, j; @@ -420,31 +512,31 @@ Uint MM_ClearUser() } INVLPG( gaPageDir ); - return *gaPageCR3; + return *gpPageCR3; } /** - * \fn Uint MM_Clone() + * \fn tPAddr MM_Clone() * \brief Clone the current address space */ -Uint MM_Clone() +tPAddr MM_Clone() { Uint i, j; - Uint ret; + tVAddr ret; Uint page = 0; - Uint kStackBase = Proc_GetCurThread()->KernelStack - KERNEL_STACK_SIZE; + tVAddr kStackBase = Proc_GetCurThread()->KernelStack - KERNEL_STACK_SIZE; void *tmp; LOCK( &gilTempFractal ); // Create Directory Table - *gTmpCR3 = MM_AllocPhys() | 3; + *gpTmpCR3 = MM_AllocPhys() | 3; INVLPG( gaTmpDir ); - //LOG("Allocated Directory (%x)", *gTmpCR3); + //LOG("Allocated Directory (%x)", *gpTmpCR3); memsetd( gaTmpDir, 0, 1024 ); // Copy Tables - for(i=0;i<768;i++) + for( i = 0; i < 768; i ++) { // Check if table is allocated if( !(gaPageDir[i] & PF_PRESENT) ) { @@ -482,7 +574,7 @@ Uint MM_Clone() { // Fractal if( i == (PAGE_TABLE_ADDR >> 22) ) { - gaTmpDir[ PAGE_TABLE_ADDR >> 22 ] = *gTmpCR3; + gaTmpDir[ PAGE_TABLE_ADDR >> 22 ] = *gpTmpCR3; continue; } @@ -542,7 +634,7 @@ Uint MM_Clone() } } - ret = *gTmpCR3 & ~0xFFF; + ret = *gpTmpCR3 & ~0xFFF; RELEASE( &gilTempFractal ); //LEAVE('x', ret); @@ -550,12 +642,12 @@ Uint MM_Clone() } /** - * \fn Uint MM_NewKStack() + * \fn tVAddr MM_NewKStack() * \brief Create a new kernel stack */ -Uint MM_NewKStack() +tVAddr MM_NewKStack() { - Uint base = KERNEL_STACKS; + tVAddr base = KERNEL_STACKS; Uint i; for(;base= NUM_WORKER_STACKS) { Warning("Uh-oh! Out of worker stacks"); @@ -611,19 +704,23 @@ Uint MM_NewWorkerStack() giLastUsedWorker = base; // We have one base = WORKER_STACKS + base * WORKER_STACK_SIZE; + //Log(" MM_NewWorkerStack: base = 0x%x", base); // Acquire the lock for the temp fractal mappings LOCK(&gilTempFractal); // Set the temp fractals to TID0's address space - *gTmpCR3 = (Uint)gaInitPageDir | 3; + *gpTmpCR3 = ((Uint)gaInitPageDir - KERNEL_BASE) | 3; + //Log(" MM_NewWorkerStack: *gpTmpCR3 = 0x%x", *gpTmpCR3); INVLPG( gaTmpDir ); + // Check if the directory is mapped (we are assuming that the stacks - // will fit neatly in a directory + // will fit neatly in a directory) + //Log(" MM_NewWorkerStack: gaTmpDir[ 0x%x ] = 0x%x", base>>22, gaTmpDir[ base >> 22 ]); if(gaTmpDir[ base >> 22 ] == 0) { gaTmpDir[ base >> 22 ] = MM_AllocPhys() | 3; - INVLPG( &gaTmpTable[ (base>>22) & ~0x3FF ] ); + INVLPG( &gaTmpTable[ (base>>12) & ~0x3FF ] ); } // Mapping Time! @@ -632,6 +729,7 @@ Uint MM_NewWorkerStack() pages[ addr >> 12 ] = MM_AllocPhys(); gaTmpTable[ (base + addr) >> 12 ] = pages[addr>>12] | 3; } + *gpTmpCR3 = 0; // Release the temp mapping lock RELEASE(&gilTempFractal); @@ -639,6 +737,9 @@ Uint MM_NewWorkerStack() oldstack = (esp + KERNEL_STACK_SIZE-1) & ~(KERNEL_STACK_SIZE-1); esp = oldstack - esp; // ESP as an offset in the stack + // Make `base` be the top of the stack + base += WORKER_STACK_SIZE; + i = (WORKER_STACK_SIZE>>12) - 1; // Copy the contents of the old stack to the new one, altering the addresses // `addr` is refering to bytes from the stack base (mem downwards) @@ -655,20 +756,21 @@ Uint MM_NewWorkerStack() else // Seems not, best leave it alone tmpPage[j] = stack[j]; } - MM_FreeTemp((Uint)tmpPage); + MM_FreeTemp((tVAddr)tmpPage); i --; } + //Log("MM_NewWorkerStack: RETURN 0x%x", base); return base; } /** - * \fn void MM_SetFlags(Uint VAddr, Uint Flags, Uint Mask) + * \fn void MM_SetFlags(tVAddr VAddr, Uint Flags, Uint Mask) * \brief Sets the flags on a page */ -void MM_SetFlags(Uint VAddr, Uint Flags, Uint Mask) +void MM_SetFlags(tVAddr VAddr, Uint Flags, Uint Mask) { - tPAddr *ent; + tTabEnt *ent; if( !(gaPageDir[VAddr >> 22] & 1) ) return ; if( !(gaPageTable[VAddr >> 12] & 1) ) return ; @@ -703,15 +805,17 @@ void MM_SetFlags(Uint VAddr, Uint Flags, Uint Mask) } /** - * \fn tPAddr MM_DuplicatePage(Uint VAddr) + * \fn tPAddr MM_DuplicatePage(tVAddr VAddr) * \brief Duplicates a virtual page to a physical one */ -tPAddr MM_DuplicatePage(Uint VAddr) +tPAddr MM_DuplicatePage(tVAddr VAddr) { tPAddr ret; Uint temp; int wasRO = 0; + //ENTER("xVAddr", VAddr); + // Check if mapped if( !(gaPageDir [VAddr >> 22] & PF_PRESENT) ) return 0; if( !(gaPageTable[VAddr >> 12] & PF_PRESENT) ) return 0; @@ -736,6 +840,7 @@ tPAddr MM_DuplicatePage(Uint VAddr) if(!wasRO) gaPageTable[VAddr >> 12] |= PF_WRITE; INVLPG(VAddr); + //LEAVE('X', ret); return ret; } @@ -744,7 +849,7 @@ tPAddr MM_DuplicatePage(Uint VAddr) * \brief Create a temporary memory mapping * \todo Show Luigi Barone (C Lecturer) and see what he thinks */ -Uint MM_MapTemp(tPAddr PAddr) +tVAddr MM_MapTemp(tPAddr PAddr) { int i; @@ -775,10 +880,10 @@ Uint MM_MapTemp(tPAddr PAddr) } /** - * \fn void MM_FreeTemp(Uint PAddr) + * \fn void MM_FreeTemp(tVAddr PAddr) * \brief Free's a temp mapping */ -void MM_FreeTemp(Uint VAddr) +void MM_FreeTemp(tVAddr VAddr) { int i = VAddr >> 12; //ENTER("xVAddr", VAddr); @@ -790,10 +895,10 @@ void MM_FreeTemp(Uint VAddr) } /** - * \fn Uint MM_MapHWPage(tPAddr PAddr, Uint Number) + * \fn tVAddr MM_MapHWPages(tPAddr PAddr, Uint Number) * \brief Allocates a contigous number of pages */ -Uint MM_MapHWPage(tPAddr PAddr, Uint Number) +tVAddr MM_MapHWPages(tPAddr PAddr, Uint Number) { int i, j; @@ -828,10 +933,73 @@ Uint MM_MapHWPage(tPAddr PAddr, Uint Number) } /** - * \fn void MM_UnmapHWPage(Uint VAddr, Uint Number) + * \fn tVAddr MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr) + * \brief Allocates DMA physical memory + * \param Pages Number of pages required + * \param MaxBits Maximum number of bits the physical address can have + * \param PhysAddr Pointer to the location to place the physical address allocated + * \return Virtual address allocate + */ +tVAddr MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr) +{ + tPAddr maxCheck = (1 << MaxBits); + tPAddr phys; + tVAddr ret; + + ENTER("iPages iMaxBits pPhysAddr", Pages, MaxBits, PhysAddr); + + // Sanity Check + if(MaxBits < 12 || !PhysAddr) { + LEAVE('i', 0); + return 0; + } + + // Bound + if(MaxBits >= PHYS_BITS) maxCheck = -1; + + // Fast Allocate + if(Pages == 1 && MaxBits >= PHYS_BITS) + { + phys = MM_AllocPhys(); + *PhysAddr = phys; + ret = MM_MapHWPages(phys, 1); + if(ret == 0) { + MM_DerefPhys(phys); + LEAVE('i', 0); + return 0; + } + LEAVE('x', ret); + return ret; + } + + // Slow Allocate + phys = MM_AllocPhysRange(Pages, MaxBits); + // - Was it allocated? + if(phys == 0) { + LEAVE('i', 0); + return 0; + } + + // Allocated successfully, now map + ret = MM_MapHWPages(phys, Pages); + if( ret == 0 ) { + // If it didn't map, free then return 0 + for(;Pages--;phys+=0x1000) + MM_DerefPhys(phys); + LEAVE('i', 0); + return 0; + } + + *PhysAddr = phys; + LEAVE('x', ret); + return ret; +} + +/** + * \fn void MM_UnmapHWPages(tVAddr VAddr, Uint Number) * \brief Unmap a hardware page */ -void MM_UnmapHWPage(Uint VAddr, Uint Number) +void MM_UnmapHWPages(tVAddr VAddr, Uint Number) { int i, j; // Sanity Check @@ -854,5 +1022,6 @@ void MM_UnmapHWPage(Uint VAddr, Uint Number) EXPORT(MM_GetPhysAddr); EXPORT(MM_Map); //EXPORT(MM_Unmap); -EXPORT(MM_MapHWPage); -EXPORT(MM_UnmapHWPage); +EXPORT(MM_MapHWPages); +EXPORT(MM_AllocDMA); +EXPORT(MM_UnmapHWPages);