mirror of
https://github.com/apache/nuttx.git
synced 2025-12-10 20:24:51 +08:00
The previous approach with memfd has 3 problems: 1) The close operation on the memfd isn't tied with optee_shm_close, therefore close(fd) doesn't free the optee_shm struct allocated by the kernel. 2) The kernel unnecessarily maps the file descriptor to its memory, however only userspace should need to do that. 3) Since the kernel doesn't need to map the file descriptor we don't need to unmap it. To use anonymous mapping, the prototype of map_anonymous() was moved from fs/mmap/fs_anonmap.h to include/nuttx/fs/fs.h. Since fs_anonmap.h didn't contain any other information it is deleted. A type from fs/mmap/fs_rammap.h was moved to the public : include/nuttx/fs/fs.h as well. Signed-off-by: Theodore Karatapanis <tkaratapanis@census-labs.com>
160 lines
4.5 KiB
C
160 lines
4.5 KiB
C
/****************************************************************************
|
|
* fs/mmap/fs_anonmap.c
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership. The
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <nuttx/config.h>
|
|
#include <nuttx/fs/fs.h>
|
|
#include <nuttx/kmalloc.h>
|
|
#include <nuttx/sched.h>
|
|
#include <assert.h>
|
|
#include <debug.h>
|
|
|
|
#include "sched/sched.h"
|
|
#include "fs_heap.h"
|
|
|
|
/****************************************************************************
|
|
* Private Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: unmap_anonymous
|
|
****************************************************************************/
|
|
|
|
static int unmap_anonymous(FAR struct task_group_s *group,
|
|
FAR struct mm_map_entry_s *entry,
|
|
FAR void *start,
|
|
size_t length)
|
|
{
|
|
FAR void *newaddr = NULL;
|
|
off_t offset;
|
|
bool kernel = entry->priv.i;
|
|
int ret = OK;
|
|
|
|
/* Get the offset from the beginning of the region and the actual number
|
|
* of bytes to "unmap". All mappings must extend to the end of the region.
|
|
* There is no support for freeing a block of memory but leaving a block of
|
|
* memory at the end. This is a consequence of using kumm_realloc() to
|
|
* simulate the unmapping.
|
|
*/
|
|
|
|
offset = (uintptr_t)start - (uintptr_t)entry->vaddr;
|
|
if (offset + length < entry->length)
|
|
{
|
|
ferr("ERROR: Cannot umap without unmapping to the end\n");
|
|
return -ENOSYS;
|
|
}
|
|
|
|
/* Okay.. the region is being unmapped to the end. Make sure the length
|
|
* indicates that.
|
|
*/
|
|
|
|
length = entry->length - offset;
|
|
|
|
/* Are we unmapping the entire region (offset == 0)? */
|
|
|
|
if (length >= entry->length)
|
|
{
|
|
/* Free the region */
|
|
|
|
if (kernel)
|
|
{
|
|
fs_heap_free(entry->vaddr);
|
|
}
|
|
else
|
|
{
|
|
kumm_free(entry->vaddr);
|
|
}
|
|
|
|
/* Then remove the mapping from the list */
|
|
|
|
ret = mm_map_remove(get_group_mm(group), entry);
|
|
}
|
|
|
|
/* No.. We have been asked to "unmap' only a portion of the memory
|
|
* (offset > 0).
|
|
*/
|
|
|
|
else
|
|
{
|
|
if (kernel)
|
|
{
|
|
newaddr = fs_heap_realloc(entry->vaddr, length);
|
|
}
|
|
else
|
|
{
|
|
newaddr = kumm_realloc(entry->vaddr, length);
|
|
}
|
|
|
|
DEBUGASSERT(newaddr == entry->vaddr);
|
|
entry->vaddr = newaddr;
|
|
entry->length = length;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
int map_anonymous(FAR struct mm_map_entry_s *entry, bool kernel)
|
|
{
|
|
int ret;
|
|
|
|
/* REVISIT: Should reside outside of the heap. That is really the
|
|
* only purpose of MAP_ANONYMOUS: To get non-heap memory. In KERNEL
|
|
* build, this could be accomplished using pgalloc(), provided that
|
|
* you had logic in place to assign a virtual address to the mapping.
|
|
*/
|
|
|
|
entry->vaddr = kernel ?
|
|
fs_heap_zalloc(entry->length) : kumm_zalloc(entry->length);
|
|
if (entry->vaddr == NULL)
|
|
{
|
|
ferr("ERROR: kumm_alloc() failed, enable DEBUG_MM for info!\n");
|
|
return -ENOMEM;
|
|
}
|
|
|
|
entry->munmap = unmap_anonymous;
|
|
entry->priv.i = kernel;
|
|
|
|
ret = mm_map_add(get_current_mm(), entry);
|
|
if (ret < 0)
|
|
{
|
|
if (kernel)
|
|
{
|
|
fs_heap_free(entry->vaddr);
|
|
}
|
|
else
|
|
{
|
|
kumm_free(entry->vaddr);
|
|
}
|
|
|
|
entry->vaddr = NULL;
|
|
}
|
|
|
|
return ret;
|
|
}
|