⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mem.c

📁 Simple Operating Systems (简称SOS)是一个可以运行在X86平台上(包括QEMU
💻 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 + -