fix: 合并进程栈两个地址连续的region

背景:进程加载的时候,先预申请一个页用作参数拷贝,另外通过mmap方式申请
额外的虚拟栈空间,此时便有两个地址连续的区间。
方案:新增内部接口OsStackAlloc,用于申请一个连续的虚拟地址区间,并对其
中指定区间做物理内存的映射。

close #I43QYJ

Signed-off-by: Haryslee <lihao189@huawei.com>
Change-Id: I224cca3671c42a94c2f74b2da5a11403849e33d3
This commit is contained in:
Haryslee 2021-08-09 16:54:22 +08:00
parent 024a8f2771
commit 42f374dd7a
4 changed files with 48 additions and 87 deletions

View File

@ -456,7 +456,6 @@ extern UINT32 OsExecStart(const TSK_ENTRY_FUNC entry, UINTPTR sp, UINTPTR mapBas
extern UINT32 OsSetProcessName(LosProcessCB *processCB, const CHAR *name); extern UINT32 OsSetProcessName(LosProcessCB *processCB, const CHAR *name);
extern INT32 OsSetProcessScheduler(INT32 which, INT32 pid, UINT16 prio, UINT16 policy); extern INT32 OsSetProcessScheduler(INT32 which, INT32 pid, UINT16 prio, UINT16 policy);
extern INT32 OsGetProcessPriority(INT32 which, INT32 pid); extern INT32 OsGetProcessPriority(INT32 which, INT32 pid);
extern VOID *OsUserStackAlloc(UINT32 processID, UINT32 *size);
extern UINT32 OsGetUserInitProcessID(VOID); extern UINT32 OsGetUserInitProcessID(VOID);
extern UINT32 OsGetIdleProcessID(VOID); extern UINT32 OsGetIdleProcessID(VOID);
extern INT32 OsSetProcessGroupID(UINT32 pid, UINT32 gid); extern INT32 OsSetProcessGroupID(UINT32 pid, UINT32 gid);

View File

@ -288,7 +288,6 @@ STATUS_T LOS_VaddrToPaddrMmap(LosVmSpace *space, VADDR_T vaddr, PADDR_T paddr, s
BOOL OsUserVmSpaceInit(LosVmSpace *vmSpace, VADDR_T *virtTtb); BOOL OsUserVmSpaceInit(LosVmSpace *vmSpace, VADDR_T *virtTtb);
LosVmSpace *OsCreateUserVmSpace(VOID); LosVmSpace *OsCreateUserVmSpace(VOID);
STATUS_T LOS_VmSpaceClone(LosVmSpace *oldVmSpace, LosVmSpace *newVmSpace); STATUS_T LOS_VmSpaceClone(LosVmSpace *oldVmSpace, LosVmSpace *newVmSpace);
STATUS_T LOS_UserSpaceVmAlloc(LosVmSpace *space, size_t size, VOID **ptr, UINT8 align_log2, UINT32 regionFlags);
LosMux *OsGVmSpaceMuxGet(VOID); LosMux *OsGVmSpaceMuxGet(VOID);
STATUS_T OsUnMMap(LosVmSpace *space, VADDR_T addr, size_t size); STATUS_T OsUnMMap(LosVmSpace *space, VADDR_T addr, size_t size);
/** /**

View File

@ -985,73 +985,6 @@ STATUS_T LOS_VaddrToPaddrMmap(LosVmSpace *space, VADDR_T vaddr, PADDR_T paddr, s
return LOS_OK; return LOS_OK;
} }
STATUS_T LOS_UserSpaceVmAlloc(LosVmSpace *space, size_t size, VOID **ptr, UINT8 align_log2, UINT32 regionFlags)
{
STATUS_T err = LOS_OK;
VADDR_T vaddr = 0;
size_t sizeCount;
size_t count;
LosVmPage *vmPage = NULL;
VADDR_T vaddrTemp;
PADDR_T paddrTemp;
LosVmMapRegion *region = NULL;
size = ROUNDUP(size, PAGE_SIZE);
if (size == 0) {
return LOS_ERRNO_VM_INVALID_ARGS;
}
sizeCount = (size >> PAGE_SHIFT);
/* if they're asking for a specific spot, copy the address */
if (ptr != NULL) {
vaddr = (VADDR_T)(UINTPTR)*ptr;
}
/* allocate physical memory up front, in case it cant be satisfied */
/* allocate a random pile of pages */
LOS_DL_LIST_HEAD(pageList);
(VOID)LOS_MuxAcquire(&space->regionMux);
count = LOS_PhysPagesAlloc(sizeCount, &pageList);
if (count < sizeCount) {
VM_ERR("failed to allocate enough pages (ask %zu, got %zu)", sizeCount, count);
err = LOS_ERRNO_VM_NO_MEMORY;
goto MEMORY_ALLOC_FAIL;
}
/* allocate a region and put it in the aspace list */
region = LOS_RegionAlloc(space, vaddr, size, regionFlags, 0);
if (!region) {
err = LOS_ERRNO_VM_NO_MEMORY;
VM_ERR("failed to allocate region, vaddr: %#x, size: %#x, space: %#x", vaddr, size, space);
goto MEMORY_ALLOC_FAIL;
}
/* return the vaddr if requested */
if (ptr != NULL) {
*ptr = (VOID *)(UINTPTR)region->range.base;
}
/* map all of the pages */
vaddrTemp = region->range.base;
while ((vmPage = LOS_ListRemoveHeadType(&pageList, LosVmPage, node))) {
paddrTemp = vmPage->physAddr;
LOS_AtomicInc(&vmPage->refCounts);
err = LOS_ArchMmuMap(&space->archMmu, vaddrTemp, paddrTemp, 1, regionFlags);
if (err != 1) {
LOS_Panic("%s %d, LOS_ArchMmuMap failed!, err: %d\n", __FUNCTION__, __LINE__, err);
}
vaddrTemp += PAGE_SIZE;
}
err = LOS_OK;
goto VMM_ALLOC_SUCCEED;
MEMORY_ALLOC_FAIL:
(VOID)LOS_PhysPagesFree(&pageList);
VMM_ALLOC_SUCCEED:
(VOID)LOS_MuxRelease(&space->regionMux);
return err;
}
VOID *LOS_VMalloc(size_t size) VOID *LOS_VMalloc(size_t size)
{ {
LosVmSpace *space = &g_vMallocSpace; LosVmSpace *space = &g_vMallocSpace;

View File

@ -38,6 +38,7 @@
#include "los_vm_syscall.h" #include "los_vm_syscall.h"
#include "los_vm_phys.h" #include "los_vm_phys.h"
#include "los_vm_dump.h" #include "los_vm_dump.h"
#include "los_vm_lock.h"
#ifdef LOSCFG_KERNEL_VDSO #ifdef LOSCFG_KERNEL_VDSO
#include "los_vdso.h" #include "los_vdso.h"
#endif #endif
@ -710,11 +711,53 @@ STATIC VOID OsGetStackProt(ELFLoadInfo *loadInfo)
} }
} }
STATIC UINT32 OsStackAlloc(LosVmSpace *space, VADDR_T vaddr, UINT32 vsize, UINT32 psize, UINT32 regionFlags)
{
LosVmPage *vmPage = NULL;
VADDR_T *kvaddr = NULL;
LosVmMapRegion *region = NULL;
VADDR_T vaddrTemp;
PADDR_T paddrTemp;
UINT32 len;
(VOID)LOS_MuxAcquire(&space->regionMux);
kvaddr = LOS_PhysPagesAllocContiguous(psize >> PAGE_SHIFT);
if (kvaddr == NULL) {
goto OUT;
}
region = LOS_RegionAlloc(space, vaddr, vsize, regionFlags | VM_MAP_REGION_FLAG_FIXED, 0);
if (region == NULL) {
goto PFREE;
}
len = psize;
vaddrTemp = region->range.base + vsize - psize;
paddrTemp = LOS_PaddrQuery(kvaddr);
while (len > 0) {
vmPage = LOS_VmPageGet(paddrTemp);
LOS_AtomicInc(&vmPage->refCounts);
(VOID)LOS_ArchMmuMap(&space->archMmu, vaddrTemp, paddrTemp, 1, region->regionFlags);
paddrTemp += PAGE_SIZE;
vaddrTemp += PAGE_SIZE;
len -= PAGE_SIZE;
}
(VOID)LOS_MuxRelease(&space->regionMux);
return LOS_OK;
PFREE:
(VOID)LOS_PhysPagesFreeContiguous(kvaddr, psize >> PAGE_SHIFT);
OUT:
(VOID)LOS_MuxRelease(&space->regionMux);
return LOS_NOK;
}
STATIC INT32 OsSetArgParams(ELFLoadInfo *loadInfo, CHAR *const *argv, CHAR *const *envp) STATIC INT32 OsSetArgParams(ELFLoadInfo *loadInfo, CHAR *const *argv, CHAR *const *envp)
{ {
UINT32 vmFlags; UINT32 vmFlags;
INT32 ret; INT32 ret;
status_t status;
#ifdef LOSCFG_ASLR #ifdef LOSCFG_ASLR
loadInfo->randomDevFD = open("/dev/urandom", O_RDONLY); loadInfo->randomDevFD = open("/dev/urandom", O_RDONLY);
@ -733,10 +776,10 @@ STATIC INT32 OsSetArgParams(ELFLoadInfo *loadInfo, CHAR *const *argv, CHAR *cons
loadInfo->stackParamBase = loadInfo->stackTopMax - USER_PARAM_BYTE_MAX; loadInfo->stackParamBase = loadInfo->stackTopMax - USER_PARAM_BYTE_MAX;
vmFlags = OsCvtProtFlagsToRegionFlags(loadInfo->stackProt, MAP_FIXED); vmFlags = OsCvtProtFlagsToRegionFlags(loadInfo->stackProt, MAP_FIXED);
vmFlags |= VM_MAP_REGION_FLAG_STACK; vmFlags |= VM_MAP_REGION_FLAG_STACK;
status = LOS_UserSpaceVmAlloc((VOID *)loadInfo->newSpace, USER_PARAM_BYTE_MAX, ret = OsStackAlloc((VOID *)loadInfo->newSpace, loadInfo->stackBase, USER_STACK_SIZE,
(VOID **)&loadInfo->stackParamBase, 0, vmFlags); USER_PARAM_BYTE_MAX, vmFlags);
if (status != LOS_OK) { if (ret != LOS_OK) {
PRINT_ERR("%s[%d], Failed to create user stack! status: %d\n", __FUNCTION__, __LINE__, status); PRINT_ERR("%s[%d], Failed to alloc memory for user stack!\n", __FUNCTION__, __LINE__);
return -ENOMEM; return -ENOMEM;
} }
loadInfo->topOfMem = loadInfo->stackTopMax - sizeof(UINTPTR); loadInfo->topOfMem = loadInfo->stackTopMax - sizeof(UINTPTR);
@ -767,10 +810,8 @@ STATIC INT32 OsPutParamToStack(ELFLoadInfo *loadInfo, const UINTPTR *auxVecInfo,
UINTPTR argStart = loadInfo->topOfMem; UINTPTR argStart = loadInfo->topOfMem;
UINTPTR *topMem = (UINTPTR *)ROUNDDOWN(loadInfo->topOfMem, sizeof(UINTPTR)); UINTPTR *topMem = (UINTPTR *)ROUNDDOWN(loadInfo->topOfMem, sizeof(UINTPTR));
UINTPTR *argsPtr = NULL; UINTPTR *argsPtr = NULL;
UINTPTR stackBase;
INT32 items = (loadInfo->argc + 1) + (loadInfo->envc + 1) + 1; INT32 items = (loadInfo->argc + 1) + (loadInfo->envc + 1) + 1;
size_t size; size_t size;
INT32 stackFlags;
loadInfo->topOfMem = ROUNDDOWN((UINTPTR)(topMem - vecIndex - items), STACK_ALIGN_SIZE); loadInfo->topOfMem = ROUNDDOWN((UINTPTR)(topMem - vecIndex - items), STACK_ALIGN_SIZE);
argsPtr = (UINTPTR *)loadInfo->topOfMem; argsPtr = (UINTPTR *)loadInfo->topOfMem;
@ -799,17 +840,6 @@ STATIC INT32 OsPutParamToStack(ELFLoadInfo *loadInfo, const UINTPTR *auxVecInfo,
return -EFAULT; return -EFAULT;
} }
if ((loadInfo->stackSize - USER_PARAM_BYTE_MAX) > 0) {
/* mmap an external region for user stack */
stackFlags = MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS;
stackBase = (UINTPTR)LOS_MMap(loadInfo->stackBase, (loadInfo->stackSize - USER_PARAM_BYTE_MAX),
loadInfo->stackProt, stackFlags, -1, 0);
if (!LOS_IsUserAddress((VADDR_T)stackBase)) {
PRINT_ERR("%s[%d], Failed to map user stack\n", __FUNCTION__, __LINE__);
return -ENOMEM;
}
}
return LOS_OK; return LOS_OK;
} }