📄 mem.c
字号:
/* Copyright (C) 2005 David Decotigny This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <sos/assert.h>#include <sos/kmalloc.h>#include <sos/physmem.h>#include <hwcore/paging.h>#include <sos/kmem_slab.h>#include <sos/list.h>#include <hwcore/paging.h>#include "mem.h"/** * A mapped mem/kmem resource */struct kernel_remapped_resource{ int ref_cnt; struct sos_umem_vmm_mapped_resource mr;};/** Called after the virtual region has been inserted inside its address space */static void resource_ref(struct sos_umem_vmm_vr * vr){ /* Retrieve the mem/kmem structure associated with the mapped resource */ struct kernel_remapped_resource * resource; resource = (struct kernel_remapped_resource*) sos_umem_vmm_get_mapped_resource_of_vr(vr)->custom_data; /* Increment ref counter */ resource->ref_cnt ++;}/** Called when the virtual region is removed from its address space */static void resource_unref(struct sos_umem_vmm_vr * vr){ /* Retrieve the mem/kmem structure associated with the mapped resource */ struct kernel_remapped_resource * resource; resource = (struct kernel_remapped_resource*) sos_umem_vmm_get_mapped_resource_of_vr(vr)->custom_data; /* Decrement ref coutner */ SOS_ASSERT_FATAL(resource->ref_cnt > 0); resource->ref_cnt --; /* Free the resource if it becomes unused */ if (resource->ref_cnt == 0) sos_kfree((sos_vaddr_t)resource);}/** MOST IMPORTANT callback ! Called when a thread page faults on the resource's mapping */static sos_ret_t kmem_page_in(struct sos_umem_vmm_vr * vr, sos_uaddr_t uaddr, sos_bool_t write_access){ sos_vaddr_t vaddr; sos_ret_t retval = SOS_OK; sos_paddr_t ppage_paddr; /* Compute address of kernel page */ vaddr = uaddr - sos_umem_vmm_get_start_of_vr(vr) + sos_umem_vmm_get_offset_in_resource(vr); /* Don't allow demand paging of non kernel pages */ if (vaddr >= SOS_PAGING_BASE_USER_ADDRESS) return -SOS_EFAULT; /* Lookup physical kernel page */ ppage_paddr = sos_paging_get_paddr(SOS_PAGE_ALIGN_INF(vaddr)); /* Cannot access unmapped kernel pages */ if (! ppage_paddr) return -SOS_EFAULT; /* Remap it in user space */ retval = sos_paging_map(ppage_paddr, SOS_PAGE_ALIGN_INF(uaddr), TRUE, sos_umem_vmm_get_prot_of_vr(vr)); return retval;}/** The callbacks for a mapped kmem resource */static struct sos_umem_vmm_vr_ops kmem_ops = (struct sos_umem_vmm_vr_ops){ .ref = resource_ref, .unref = resource_unref, .page_in = kmem_page_in,};/** The callback that gets called when the resource gets mapped */static sos_ret_t kmem_mmap(struct sos_umem_vmm_vr *vr){ return sos_umem_vmm_set_ops_of_vr(vr, &kmem_ops);}/** The function responsible for mapping the /dev/kmem resource in user space */sos_ret_t sos_dev_kmem_map(struct sos_umem_vmm_as * dest_as, sos_uaddr_t *uaddr, sos_size_t size, sos_vaddr_t offset, sos_ui32_t access_rights, sos_ui32_t flags){ sos_ret_t retval; struct kernel_remapped_resource * kmem_resource; /* Allocate a new "descriptor" for the resource */ kmem_resource = (struct kernel_remapped_resource*) sos_kmalloc(sizeof(*kmem_resource), 0); if (! kmem_resource) return -SOS_ENOMEM; memset(kmem_resource, 0x0, sizeof(*kmem_resource)); kmem_resource->mr.allowed_access_rights = SOS_VM_MAP_PROT_READ | SOS_VM_MAP_PROT_WRITE | SOS_VM_MAP_PROT_EXEC; kmem_resource->mr.custom_data = kmem_resource; kmem_resource->mr.mmap = kmem_mmap; /* Map it in user space */ retval = sos_umem_vmm_map(dest_as, uaddr, size, access_rights, flags, & kmem_resource->mr, offset); if (SOS_OK != retval) { sos_kfree((sos_vaddr_t)kmem_resource); return retval; } return SOS_OK;}/** MOST IMPORTANT callback ! Called when a thread page faults on the resource's mapping */static sos_ret_t physmem_page_in(struct sos_umem_vmm_vr * vr, sos_uaddr_t uaddr, sos_bool_t write_access){ sos_ret_t retval = SOS_OK; sos_paddr_t ppage_paddr; /* Compute address of kernel page */ ppage_paddr = uaddr - sos_umem_vmm_get_start_of_vr(vr) + sos_umem_vmm_get_offset_in_resource(vr); /* Remap page in user space */ retval = sos_paging_map(SOS_PAGE_ALIGN_INF(ppage_paddr), SOS_PAGE_ALIGN_INF(uaddr), TRUE, sos_umem_vmm_get_prot_of_vr(vr)); return retval;}/** The callbacks for a mapped physmem resource */static struct sos_umem_vmm_vr_ops physmem_ops = (struct sos_umem_vmm_vr_ops){ .ref = resource_ref, .unref = resource_unref, .page_in = physmem_page_in,};/** The callback that gets called when the resource gets mapped */static sos_ret_t physmem_mmap(struct sos_umem_vmm_vr *vr){ return sos_umem_vmm_set_ops_of_vr(vr, &physmem_ops);}/** The function responsible for mapping the /dev/mem resource in user space */sos_ret_t sos_dev_physmem_map(struct sos_umem_vmm_as * dest_as, sos_uaddr_t *uaddr, sos_size_t size, sos_paddr_t offset, sos_ui32_t access_rights, sos_ui32_t flags){ sos_ret_t retval; struct kernel_remapped_resource * physmem_resource; physmem_resource = (struct kernel_remapped_resource*) sos_kmalloc(sizeof(*physmem_resource), 0); if (! physmem_resource) return -SOS_ENOMEM; memset(physmem_resource, 0x0, sizeof(*physmem_resource)); physmem_resource->mr.allowed_access_rights = SOS_VM_MAP_PROT_READ | SOS_VM_MAP_PROT_WRITE | SOS_VM_MAP_PROT_EXEC; physmem_resource->mr.custom_data = physmem_resource; physmem_resource->mr.mmap = physmem_mmap; retval = sos_umem_vmm_map(dest_as, uaddr, size, access_rights, flags, & physmem_resource->mr, offset); if (SOS_OK != retval) { sos_kfree((sos_vaddr_t)physmem_resource); return retval; } return SOS_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -