From c0a6af0e8c4840c370e819cd44925502fae8c4ba Mon Sep 17 00:00:00 2001 From: John Hodge Date: Fri, 11 Nov 2011 21:56:39 +0800 Subject: [PATCH] Kernel - Fixing very slow CheckMem function - Blit from AxWin3 is down to 30ms in qemu :) --- Kernel/arch/armv7/mm_virt.c | 29 +++++++++++++++++ Kernel/arch/armv7/proc.c | 9 ++---- Kernel/arch/x86/lib.c | 10 +++--- Kernel/arch/x86/mm_virt.c | 39 +++++++++++++++++++++++ Kernel/arch/x86_64/mm_virt.c | 59 ++++++++++++++++++++++++++++++++-- Kernel/drv/vterm.c | 3 +- Kernel/include/hal_proc.h | 7 ++++ Kernel/lib.c | 62 ++++++++++-------------------------- 8 files changed, 158 insertions(+), 60 deletions(-) diff --git a/Kernel/arch/armv7/mm_virt.c b/Kernel/arch/armv7/mm_virt.c index 64b5d570..d74313fd 100644 --- a/Kernel/arch/armv7/mm_virt.c +++ b/Kernel/arch/armv7/mm_virt.c @@ -391,6 +391,33 @@ void MM_SetFlags(tVAddr VAddr, Uint Flags, Uint Mask) MM_int_SetPageInfo(VAddr, &pi); } +int MM_IsValidBuffer(tVAddr Addr, size_t Size) +{ + tMM_PageInfo pi; + int bUser = 0; + + Size += Addr & (PAGE_SIZE-1); + Addr &= ~(PAGE_SIZE-1); + + if( MM_int_GetPageInfo(Addr, &pi) ) return 0; + Addr += PAGE_SIZE; + + if(pi.AP != AP_KRW_ONLY && pi.AP != AP_KRO_ONLY) + bUser = 1; + + while( Size >= PAGE_SIZE ) + { + if( MM_int_GetPageInfo(Addr, &pi) ) + return 0; + if(bUser && (pi.AP == AP_KRW_ONLY || pi.AP == AP_KRO_ONLY)) + return 0; + Addr += PAGE_SIZE; + Size -= PAGE_SIZE; + } + + return 1; +} + int MM_Map(tVAddr VAddr, tPAddr PAddr) { tMM_PageInfo pi = {0}; @@ -923,6 +950,8 @@ void MM_DumpTables(tVAddr Start, tVAddr End) int i = 0, inRange=0; pi_old.Size = 0; + pi_old.AP = 0; + pi_old.PhysAddr = 0; Debug("Page Table Dump (%p to %p):", Start, End); range_start = Start; diff --git a/Kernel/arch/armv7/proc.c b/Kernel/arch/armv7/proc.c index 54951e11..b5a867cf 100644 --- a/Kernel/arch/armv7/proc.c +++ b/Kernel/arch/armv7/proc.c @@ -13,7 +13,7 @@ extern tThread gThreadZero; extern void SwitchTask(Uint32 NewSP, Uint32 *OldSP, Uint32 NewIP, Uint32 *OldIP, Uint32 MemPtr); extern void KernelThreadHeader(void); // Actually takes args on stack -extern void Proc_int_DropToUser(Uint32 IP, Uint32 SP) NORETURN; +extern void Proc_int_DropToUser(Uint32 IP, Uint32 SP) NORETURN __attribute__((long_call)); extern Uint32 Proc_int_SwapUserSP(Uint32 NewSP); extern Uint32 Proc_CloneInt(Uint32 *SP, Uint32 *MemPtr); extern tVAddr MM_NewKStack(int bGlobal); // TODO: Move out into a header @@ -91,12 +91,7 @@ void Proc_StartUser(Uint Entrypoint, Uint Base, int ArgC, char **ArgV, int DataS // Drop to user code Log_Debug("Proc", "Proc_int_DropToUser(%p, %p)", Entrypoint, usr_sp); - - // Needed to get around relocation truncation - { - void (*drop)(Uint32, Uint32) NORETURN = Proc_int_DropToUser; - drop(Entrypoint, (Uint32)usr_sp); - } + Proc_int_DropToUser(Entrypoint, (Uint32)usr_sp); } void Proc_ClearThread(tThread *Thread) diff --git a/Kernel/arch/x86/lib.c b/Kernel/arch/x86/lib.c index db05d936..5c2bf648 100644 --- a/Kernel/arch/x86/lib.c +++ b/Kernel/arch/x86/lib.c @@ -334,29 +334,30 @@ void *memcpy(void *Dest, const void *Src, size_t Num) #if 1 else if( Num > 128 && (dst & 15) == (src & 15) ) { + char tmp[16+15]; // Note, this is a hack to save/restor xmm0 int count = 16 - (dst & 15); // Debug("\nmemcpy:Num=0x%x by %p (SSE)", Num, __builtin_return_address(0)); if( count < 16 ) { Num -= count; -// Debug("dst = %p, src = %p, count = %i (Num=0x%x) (head)", dst, src, count, Num); __asm__ __volatile__ ("rep movsb" : "=D"(dst),"=S"(src): "0"(dst), "1"(src), "c"(count)); } count = Num / 16; -// Debug("dst = %p, src = %p, count = %i (bulk)", dst, src, count); __asm__ __volatile__ ( + "movdqa 0(%5), %%xmm0;\n\t" "1:\n\t" "movdqa 0(%1), %%xmm0;\n\t" "movdqa %%xmm0, 0(%0);\n\t" "add $16,%0;\n\t" "add $16,%1;\n\t" "loop 1b;\n\t" - : "=r"(dst),"=r"(src) : "0"(dst), "1"(src), "c"(count) + "movdqa %%xmm0, 0(%5);\n\t" + : "=r"(dst),"=r"(src) + : "0"(dst), "1"(src), "c"(count), "r" (((tVAddr)tmp+15)&~15) ); count = Num & 15; -// Debug("dst = %p, src = %p, count = %i (tail)", dst, src, count); if(count) __asm__ __volatile__ ("rep movsb" :: "D"(dst), "S"(src), "c"(count)); } @@ -372,6 +373,7 @@ void *memcpy(void *Dest, const void *Src, size_t Num) } return Dest; } + /** * \fn void *memcpyd(void *Dest, const void *Src, size_t Num) * \brief Copy \a Num DWORDs from \a Src to \a Dest diff --git a/Kernel/arch/x86/mm_virt.c b/Kernel/arch/x86/mm_virt.c index e616fc71..e2442ae1 100644 --- a/Kernel/arch/x86/mm_virt.c +++ b/Kernel/arch/x86/mm_virt.c @@ -827,6 +827,45 @@ Uint MM_GetFlags(tVAddr VAddr) return ret; } +/** + * \brief Check if the provided buffer is valid + * \return Boolean valid + */ +int MM_IsValidBuffer(tVAddr Addr, size_t Size) +{ + int bIsUser; + int dir, tab; + + Size += Addr & (PAGE_SIZE-1); + Addr &= ~(PAGE_SIZE-1); + + dir = Addr >> 22; + tab = Addr >> 12; + +// Debug("Addr = %p, Size = 0x%x, dir = %i, tab = %i", Addr, Size, dir, tab); + + if( !(gaPageDir[dir] & 1) ) return 0; + if( !(gaPageTable[tab] & 1) ) return 0; + + bIsUser = !!(gaPageTable[tab] & PF_USER); + + while( Size >= PAGE_SIZE ) + { + if( (tab & 1023) == 0 ) + { + dir ++; + if( !(gaPageDir[dir] & 1) ) return 0; + } + + if( !(gaPageTable[tab] & 1) ) return 0; + if( bIsUser && !(gaPageTable[tab] & PF_USER) ) return 0; + + tab ++; + Size -= PAGE_SIZE; + } + return 1; +} + /** * \fn tPAddr MM_DuplicatePage(tVAddr VAddr) * \brief Duplicates a virtual page to a physical one diff --git a/Kernel/arch/x86_64/mm_virt.c b/Kernel/arch/x86_64/mm_virt.c index c7b7a224..8b560439 100644 --- a/Kernel/arch/x86_64/mm_virt.c +++ b/Kernel/arch/x86_64/mm_virt.c @@ -8,6 +8,7 @@ #include #include #include +#include // === CONSTANTS === #define PHYS_BITS 52 // TODO: Move out @@ -64,13 +65,13 @@ void MM_InitVirt(void); void MM_int_ClonePageEnt( Uint64 *Ent, void *NextLevel, tVAddr Addr, int bTable ); int MM_PageFault(tVAddr Addr, Uint ErrorCode, tRegs *Regs); void MM_int_DumpTablesEnt(tVAddr RangeStart, size_t Length, tPAddr Expected); -void MM_DumpTables(tVAddr Start, tVAddr End); +//void MM_DumpTables(tVAddr Start, tVAddr End); int MM_GetPageEntryPtr(tVAddr Addr, BOOL bTemp, BOOL bAllocate, BOOL bLargePage, tPAddr **Pointer); int MM_MapEx(tVAddr VAddr, tPAddr PAddr, BOOL bTemp, BOOL bLarge); // int MM_Map(tVAddr VAddr, tPAddr PAddr); void MM_Unmap(tVAddr VAddr); void MM_int_ClearTableLevel(tVAddr VAddr, int LevelBits, int MaxEnts); -void MM_ClearUser(void); +//void MM_ClearUser(void); int MM_GetPageEntry(tVAddr Addr, tPAddr *Phys, Uint *Flags); // === GLOBALS === @@ -669,6 +670,60 @@ Uint MM_GetFlags(tVAddr VAddr) return ret; } +/** + * \brief Check if the provided buffer is valid + * \return Boolean valid + */ +int MM_IsValidBuffer(tVAddr Addr, size_t Size) +{ + int bIsUser; + int pml4, pdp, dir, tab; + + Size += Addr & (PAGE_SIZE-1); + Addr &= ~(PAGE_SIZE-1); + Addr &= ((1UL << 48)-1); // Clap to address space + + pml4 = Addr >> 39; + pdp = Addr >> 30; + dir = Addr >> 21; + tab = Addr >> 12; + +// Debug("Addr = %p, Size = 0x%x, dir = %i, tab = %i", Addr, Size, dir, tab); + + if( !(PAGEMAPLVL4(pml4) & 1) ) return 0; + if( !(PAGEDIRPTR(pdp) & 1) ) return 0; + if( !(PAGEDIR(dir) & 1) ) return 0; + if( !(PAGETABLE(tab) & 1) ) return 0; + + bIsUser = !!(PAGETABLE(tab) & PF_USER); + + while( Size >= PAGE_SIZE ) + { + if( (tab & 511) == 0 ) + { + dir ++; + if( ((dir >> 9) & 511) == 0 ) + { + pdp ++; + if( ((pdp >> 18) & 511) == 0 ) + { + pml4 ++; + if( !(PAGEMAPLVL4(pml4) & 1) ) return 0; + } + if( !(PAGEDIRPTR(pdp) & 1) ) return 0; + } + if( !(PAGEDIR(dir) & 1) ) return 0; + } + + if( !(PAGETABLE(tab) & 1) ) return 0; + if( bIsUser && !(PAGETABLE(tab) & PF_USER) ) return 0; + + tab ++; + Size -= PAGE_SIZE; + } + return 1; +} + // --- Hardware Mappings --- /** * \brief Map a range of hardware pages diff --git a/Kernel/drv/vterm.c b/Kernel/drv/vterm.c index 634865b6..9488b3ea 100644 --- a/Kernel/drv/vterm.c +++ b/Kernel/drv/vterm.c @@ -589,7 +589,8 @@ Uint64 VT_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) } return 0; } - else { + else + { return VFS_WriteAt( giVT_OutputDevHandle, Offset, Length, Buffer ); } } diff --git a/Kernel/include/hal_proc.h b/Kernel/include/hal_proc.h index 0df05567..a189d568 100644 --- a/Kernel/include/hal_proc.h +++ b/Kernel/include/hal_proc.h @@ -80,4 +80,11 @@ extern void MM_ClearUser(void); */ extern void MM_DumpTables(tVAddr Start, tVAddr End); +/** + * \brief Check if a buffer is valid (and all user if originally user) + * \param Addr Base address + * \param Size Size of the buffer in bytes + * \return Boolean valid (0: invalid, non-0: Valid) + */ +extern int MM_IsValidBuffer(tVAddr Addr, size_t Size); #endif diff --git a/Kernel/lib.c b/Kernel/lib.c index 73b6432e..369b7b0b 100644 --- a/Kernel/lib.c +++ b/Kernel/lib.c @@ -3,6 +3,7 @@ * Common Library Functions */ #include +#include // === CONSTANTS === #define RANDOM_SEED 0xACE55052 @@ -821,35 +822,29 @@ int rand(void) */ int CheckString(const char *String) { - if( !MM_GetPhysAddr( (tVAddr)String ) ) + tVAddr addr; + int bUser; + + addr = (tVAddr)String; + + if( !MM_GetPhysAddr( addr ) ) return 0; // Check 1st page - if( MM_IsUser( (tVAddr)String ) ) + bUser = MM_IsUser( addr ); + + while( *(char*)addr ) { - // Traverse String - while( *String ) + if( (addr & (PAGE_SIZE-1)) == 0 ) { - if( !MM_IsUser( (tVAddr)String ) ) + if(bUser && !MM_IsUser(addr) ) return 0; - // Increment string pointer - String ++; - } - return 1; - } - else if( MM_GetPhysAddr( (tVAddr)String ) ) - { - // Traverse String - while( *String ) - { - if( !MM_GetPhysAddr( (tVAddr)String ) ) + if(!bUser && !MM_GetPhysAddr(addr) ) return 0; - // Increment string pointer - String ++; } - return 1; + addr ++; } - return 0; + return 1; } /** @@ -858,32 +853,7 @@ int CheckString(const char *String) */ int CheckMem(const void *Mem, int NumBytes) { - tVAddr addr = (tVAddr)Mem; - - if( !MM_GetPhysAddr( addr ) ) - return 0; - - if( MM_IsUser( addr ) ) - { - while( NumBytes-- ) - { - if( !MM_IsUser( addr ) ) - return 0; - addr ++; - } - return 1; - } - else if( MM_GetPhysAddr( addr ) ) - { - while( NumBytes-- ) - { - if( !MM_GetPhysAddr( addr ) ) - return 0; - addr ++; - } - return 1; - } - return 0; + return MM_IsValidBuffer( (tVAddr)Mem, NumBytes ); } /* * * \} -- 2.20.1