提交 42f374dd 编写于 作者: H Haryslee

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

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

close #I43QYJ
Signed-off-by: NHaryslee <lihao189@huawei.com>
Change-Id: I224cca3671c42a94c2f74b2da5a11403849e33d3
上级 024a8f27
......@@ -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 INT32 OsSetProcessScheduler(INT32 which, INT32 pid, UINT16 prio, UINT16 policy);
extern INT32 OsGetProcessPriority(INT32 which, INT32 pid);
extern VOID *OsUserStackAlloc(UINT32 processID, UINT32 *size);
extern UINT32 OsGetUserInitProcessID(VOID);
extern UINT32 OsGetIdleProcessID(VOID);
extern INT32 OsSetProcessGroupID(UINT32 pid, UINT32 gid);
......
......@@ -288,7 +288,6 @@ STATUS_T LOS_VaddrToPaddrMmap(LosVmSpace *space, VADDR_T vaddr, PADDR_T paddr, s
BOOL OsUserVmSpaceInit(LosVmSpace *vmSpace, VADDR_T *virtTtb);
LosVmSpace *OsCreateUserVmSpace(VOID);
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);
STATUS_T OsUnMMap(LosVmSpace *space, VADDR_T addr, size_t size);
/**
......
......@@ -985,73 +985,6 @@ STATUS_T LOS_VaddrToPaddrMmap(LosVmSpace *space, VADDR_T vaddr, PADDR_T paddr, s
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)
{
LosVmSpace *space = &g_vMallocSpace;
......
......@@ -38,6 +38,7 @@
#include "los_vm_syscall.h"
#include "los_vm_phys.h"
#include "los_vm_dump.h"
#include "los_vm_lock.h"
#ifdef LOSCFG_KERNEL_VDSO
#include "los_vdso.h"
#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)
{
UINT32 vmFlags;
INT32 ret;
status_t status;
#ifdef LOSCFG_ASLR
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;
vmFlags = OsCvtProtFlagsToRegionFlags(loadInfo->stackProt, MAP_FIXED);
vmFlags |= VM_MAP_REGION_FLAG_STACK;
status = LOS_UserSpaceVmAlloc((VOID *)loadInfo->newSpace, USER_PARAM_BYTE_MAX,
(VOID **)&loadInfo->stackParamBase, 0, vmFlags);
if (status != LOS_OK) {
PRINT_ERR("%s[%d], Failed to create user stack! status: %d\n", __FUNCTION__, __LINE__, status);
ret = OsStackAlloc((VOID *)loadInfo->newSpace, loadInfo->stackBase, USER_STACK_SIZE,
USER_PARAM_BYTE_MAX, vmFlags);
if (ret != LOS_OK) {
PRINT_ERR("%s[%d], Failed to alloc memory for user stack!\n", __FUNCTION__, __LINE__);
return -ENOMEM;
}
loadInfo->topOfMem = loadInfo->stackTopMax - sizeof(UINTPTR);
......@@ -767,10 +810,8 @@ STATIC INT32 OsPutParamToStack(ELFLoadInfo *loadInfo, const UINTPTR *auxVecInfo,
UINTPTR argStart = loadInfo->topOfMem;
UINTPTR *topMem = (UINTPTR *)ROUNDDOWN(loadInfo->topOfMem, sizeof(UINTPTR));
UINTPTR *argsPtr = NULL;
UINTPTR stackBase;
INT32 items = (loadInfo->argc + 1) + (loadInfo->envc + 1) + 1;
size_t size;
INT32 stackFlags;
loadInfo->topOfMem = ROUNDDOWN((UINTPTR)(topMem - vecIndex - items), STACK_ALIGN_SIZE);
argsPtr = (UINTPTR *)loadInfo->topOfMem;
......@@ -799,17 +840,6 @@ STATIC INT32 OsPutParamToStack(ELFLoadInfo *loadInfo, const UINTPTR *auxVecInfo,
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;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册