fix: MMU竞态问题修复

背景:同一个进程的多个线程读写同一个PTE时,由于PTE无保护,存在竞态问题。
方案:新增spinlock保护PTE,包括大锁跟小锁。大锁:一个进程只有一个spinlock锁,多个线程
读写PTE时竞争一把锁,锁的内存占用小,但系统性能降低;小锁:每个页表持有一把spinlock,
由于锁是page结构体的一个字段,内存消耗较大,但是相对大锁性能较优。系统默认使用大锁,用
户可根据具体需要配置使用大锁还是小锁。

close #I2WARC

Signed-off-by: Haryslee <lihao189@huawei.com>
Change-Id: I5612eeac1f65507160035eae16af61f285182eda
This commit is contained in:
Haryslee
2021-12-29 21:07:45 +08:00
parent 9995d8e0e4
commit 748e0d8ffb
10 changed files with 303 additions and 80 deletions

View File

@@ -39,6 +39,7 @@
#include "los_typedef.h"
#include "los_arch_mmu.h"
#include "los_mux.h"
#include "los_rbtree.h"
#include "los_vm_syscall.h"
#include "los_vm_zone.h"

View File

@@ -36,6 +36,7 @@
#include "los_bitmap.h"
#include "los_list.h"
#include "los_atomic.h"
#include "los_spinlock.h"
#ifdef __cplusplus
#if __cplusplus
@@ -51,6 +52,9 @@ typedef struct VmPage {
UINT8 order; /**< vm page in which order list */
UINT8 segID; /**< the segment id of vm page */
UINT16 nPages; /**< the vm page is used for kernel heap */
#ifdef LOSCFG_PAGE_TABLE_FINE_LOCK
SPIN_LOCK_S lock; /**< lock for page table entry */
#endif
} LosVmPage;
extern LosVmPage *g_vmPageArray;

View File

@@ -102,6 +102,7 @@ LosVmPage *OsVmVaddrToPage(VOID *ptr);
VOID OsPhysSharePageCopy(PADDR_T oldPaddr, PADDR_T *newPaddr, LosVmPage *newPage);
VOID OsVmPhysPagesFreeContiguous(LosVmPage *page, size_t nPages);
LosVmPage *OsVmPhysToPage(paddr_t pa, UINT8 segID);
LosVmPage *OsVmPaddrToPage(paddr_t paddr);
LosVmPage *LOS_PhysPageAlloc(VOID);
VOID LOS_PhysPageFree(LosVmPage *page);
@@ -110,6 +111,7 @@ size_t LOS_PhysPagesFree(LOS_DL_LIST *list);
VOID *LOS_PhysPagesAllocContiguous(size_t nPages);
VOID LOS_PhysPagesFreeContiguous(VOID *ptr, size_t nPages);
VADDR_T *LOS_PaddrToKVaddr(PADDR_T paddr);
PADDR_T OsKVaddrToPaddr(VADDR_T kvaddr);
#ifdef __cplusplus
#if __cplusplus

View File

@@ -50,6 +50,9 @@ STATIC VOID OsVmPageInit(LosVmPage *page, paddr_t pa, UINT8 segID)
page->segID = segID;
page->order = VM_LIST_ORDER_MAX;
page->nPages = 0;
#ifdef LOSCFG_PAGE_TABLE_FINE_LOCK
LOS_SpinInit(&page->lock);
#endif
}
STATIC INLINE VOID OsVmPageOrderListInit(LosVmPage *page, size_t nPages)

View File

@@ -220,6 +220,20 @@ LosVmPage *OsVmPhysToPage(paddr_t pa, UINT8 segID)
return (seg->pageBase + (offset >> PAGE_SHIFT));
}
LosVmPage *OsVmPaddrToPage(paddr_t paddr)
{
INT32 segID;
LosVmPage *vmPage = NULL;
for (segID = 0; segID < g_vmPhysSegNum; segID++) {
vmPage = OsVmPhysToPage(paddr, segID);
if (vmPage != NULL) {
return vmPage;
}
}
return NULL;
}
VOID *OsVmPageToVaddr(LosVmPage *page)
{
VADDR_T vaddr;
@@ -444,11 +458,23 @@ VOID LOS_PhysPagesFreeContiguous(VOID *ptr, size_t nPages)
LOS_SpinUnlockRestore(&seg->freeListLock, intSave);
}
PADDR_T OsKVaddrToPaddr(VADDR_T kvaddr)
{
if (kvaddr == 0) {
return 0;
}
return (kvaddr - KERNEL_ASPACE_BASE + SYS_MEM_BASE);
}
VADDR_T *LOS_PaddrToKVaddr(PADDR_T paddr)
{
struct VmPhysSeg *seg = NULL;
UINT32 segID;
if (paddr == 0) {
return NULL;
}
for (segID = 0; segID < g_vmPhysSegNum; segID++) {
seg = &g_vmPhysSeg[segID];
if ((paddr >= seg->start) && (paddr < (seg->start + seg->size))) {