xv6-lab3: page table

news2024/11/27 5:38:04

文章目录

  • 1.speed up system call
  • 2. print page
  • 3. Detecting which pages have been accessed

  1. where is page table?
  2. function of page table?
  3. how to get arguments from user to kernel? –
    reference:https://stackoverflow.com/questions/46870509/how-to-pass-a-value-into-system-call-xv6

1.speed up system call

Code learning:
在这里插入图片描述
在这里插入图片描述
according to hint, change the code step by step:

  • You can perform the mapping in proc_pagetable() in kernel/proc.c.
  • Choose permission bits that allow userspace to only read the page.
  • You may find that mappages() is a useful utility.
//proc.c
  // map the trapframe just below trapframe, for read-only page mapping
  if(mappages(pagetable, USYSCALL, PGSIZE,
              (uint64)(p->usyscall), PTE_R | PTE_U) < 0){
    uvmunmap(pagetable, TRAMPOLINE, 1, 0);
    uvmunmap(pagetable, TRAPFRAME, 1, 0);
    uvmunmap(pagetable, USYSCALL, 1, 0);
    uvmfree(pagetable, 0);
    return 0;
  }
  • Don’t forget to allocate and initialize the page in allocproc().
...//proc.c
	found:
  // Allocate a pid page.  'allocate and initialize the page'
  if((p->usyscall = (struct usyscall *)kalloc()) == 0){
    freeproc(p);
    release(&p->lock);
    return 0;
  }
  p->usyscall->pid = p->pid;

Make sure to free the page in freeproc().

//proc.c
// free a proc structure and the data hanging from it,
// including user pages.
// p->lock must be held.
static void
freeproc(struct proc *p)
{
...
  if(p->trapframe)
    kfree((void*)p->trapframe);
  p->trapframe = 0;
  if(p->usyscall)
    kfree((void*)p->usyscall);
  p->usyscall = 0;
 ...
//proc.c
// Free a process's page table, and free the
// physical memory it refers to.
void
proc_freepagetable(pagetable_t pagetable, uint64 sz)
{
  uvmunmap(pagetable, TRAMPOLINE, 1, 0);
  uvmunmap(pagetable, TRAPFRAME, 1, 0);
  uvmunmap(pagetable, USYSCALL, 1, 0);

  uvmfree(pagetable, sz);
}

2. print page

You can put vmprint() in kernel/vm.c.

int
exec(char *path, char **argv)
{
...
  if(p->pid==1){
    vmprint(p->pagetable);
  }
return argc

Use the macros at the end of the file kernel/riscv.h.
The function freewalk may be inspirational.
Define the prototype for vmprint in kernel/defs.h so that you can call it from exec.c.
Use %p in your printf calls to print out full 64-bit hex PTEs and addresses as shown in the example.

// Recursively free page-table pages.
// All leaf mappings must already have been removed.
void
freewalk(pagetable_t pagetable)
{
  // there are 2^9 = 512 PTEs in a page table.
  for(int i = 0; i < 512; i++){
    pte_t pte = pagetable[i];
    if((pte & PTE_V) && (pte & (PTE_R|PTE_W|PTE_X)) == 0){
      // this PTE points to a lower-level page table.
      uint64 child = PTE2PA(pte);
      freewalk((pagetable_t)child);
      pagetable[i] = 0;
    } else if(pte & PTE_V){
      panic("freewalk: leaf");
    }
  }
  kfree((void*)pagetable);
}
// Recursively check valid page-table pages.
void
vmprint(pagetable_t pagetable, int depth)
{
  char* buf = "";
  switch (depth)
  {
  case 0:
    printf("page table %p\n", pagetable);
    buf = "..";
    break;
  case 1:
    buf = ".. ..";
    break;
  case 2:
    buf = ".. .. ..";
    break;
  }
  // there are 2^9 = 512 PTEs in a page table.
  for(int i = 0; i < 512; i++){
    pte_t pte = pagetable[i];
    if(pte & PTE_V){
      // ..0: pte 0x0000000021fda801 pa 0x0000000087f6a000
      // this PTE points to a lower-level page table.
      uint64 child = PTE2PA(pte);
      printf("%s%d: pte %p pa %p\n", buf, i, pte, child);
      if(depth != 2)
      vmprint((pagetable_t)child, ++depth);
    }
  }
}

3. Detecting which pages have been accessed

Look at the user program, found that it uses a buffer.

  • buffer has 32 pages.
  • For 1,2,30 page, we set 1 as they’ve been accessed.
  • we call the pageccess(), store the access result in the abits, then compare abits and assumption.
pgaccess_test()
{
  char *buf;
  unsigned int abits;
  printf("pgaccess_test starting\n");
  testname = "pgaccess_test";
  buf = malloc(32 * PGSIZE);
  if (pgaccess(buf, 32, &abits) < 0)
    err("pgaccess failed");
  buf[PGSIZE * 1] += 1;
  buf[PGSIZE * 2] += 1;
  buf[PGSIZE * 30] += 1;
  if (pgaccess(buf, 32, &abits) < 0)
    err("pgaccess failed");
  if (abits != ((1 << 1) | (1 << 2) | (1 << 30)))
    err("incorrect access bits set");
  free(buf);
  printf("pgaccess_test: OK\n");
}

You’ll need to parse arguments using argaddr() and argint().

we see the two functions below, found that they can get arguments from pgaccess() by the kernel.
the way of getting arguments is access to trapframe register.

// Fetch the nth 32-bit system call argument.
int
argint(int n, int *ip)
{
  *ip = argraw(n);
  return 0;
}

// Retrieve an argument as a pointer.
// Doesn't check for legality, since
// copyin/copyout will do that.
int
argaddr(int n, uint64 *ip)
{
  *ip = argraw(n);
  return 0;
}

static uint64
argraw(int n)
{
  struct proc *p = myproc();
  switch (n) {
  case 0:
    return p->trapframe->a0;
  case 1:
    return p->trapframe->a1;
  case 2:
    return p->trapframe->a2;
  case 3:
    return p->trapframe->a3;
  case 4:
    return p->trapframe->a4;
  case 5:
    return p->trapframe->a5;
  }
  panic("argraw");
  return -1;
}

So, we use them to input arguments from user program.

  uint64 *buffer;
  int pg_amount;
  uint64 *abits
  if(argaddr(0, %buffer) < 0) return -1;
  if(argint(1, &pg_amount) < 0) return -1;
  if(argaddr(2, abits) < 0) return -1;

result:

abits = 0x0000000000000000
pgtbltest: pgaccess_test failed: incorrect access bits set, pid=3

walk() in kernel/vm.c is very useful for finding the right PTEs.

check the walk() function, found that it can return the PTE’s address if valid. So, we use it for finding valid PTE

// Return the address of the PTE in page table pagetable
// that corresponds to virtual address va.  If alloc!=0,
// create any required page-table pages.
//
// The risc-v Sv39 scheme has three levels of page-table
// pages. A page-table page contains 512 64-bit PTEs.
// A 64-bit virtual address is split into five fields:
//   39..63 -- must be zero.
//   30..38 -- 9 bits of level-2 index.
//   21..29 -- 9 bits of level-1 index.
//   12..20 -- 9 bits of level-0 index.
//    0..11 -- 12 bits of byte offset within the page.
pte_t *
walk(pagetable_t pagetable, uint64 va, int alloc)
{
  if(va >= MAXVA)
    panic("walk");

  for(int level = 2; level > 0; level--) {
    pte_t *pte = &pagetable[PX(level, va)];
    if(*pte & PTE_V) {
      pagetable = (pagetable_t)PTE2PA(*pte);
    } else {
      if(!alloc || (pagetable = (pde_t*)kalloc()) == 0)
        return 0;
      memset(pagetable, 0, PGSIZE);
      *pte = PA2PTE(pagetable) | PTE_V;
    }
  }
  return &pagetable[PX(0, va)];
}
//vm.c
//check accessed page
//return uint 32 mask for showing every page's condition of access
uint32
check_page(pagetable_t pagetable, uint64 start_va, int pg_amount)
{
  if(start_va >= MAXVA)
    panic("walk");
  uint32 mask = 0;
  for(int i = 0; i < pg_amount; i++){
    pte_t * pte = walk(pagetable, start_va + i * PGSIZE, 0);
    if(*pte & PTE_A) {
      printf("i = %d\t", i);
      mask |= 1 << i;
      printf("mask = %p\n", mask);
      *pte &=  ~PTE_A; // 0 << 6 for bit clear
    }
  }
  return mask;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/153579.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

风速记录仪大屏幕液晶显示全中文操作菜单操作简单

风速记录仪功能特点◆本机体积小巧美观&#xff0c;大屏幕液晶显示&#xff0c;全中文操作菜单&#xff0c;操作简单&#xff0c;性能可靠&#xff0c;记录间隔可根据要求从1分至24小时任意设置。&#xff08;但由于存储器空间有限&#xff0c;设置后也可随时查看存储信息&…

【阶段三】Python机器学习09篇:机器学习项目实战:决策树回归模型

本篇的思维导图: 项目背景 决策树除了能进行分类分析,还能进行回归分析,即预测连续变量,此时的决策树称为回归决策树。回归问题是一类预测连续值的问题,而能满足这样要求的数学模型称作回归模型,本项目应用决策树回归模型进行探索新冠疫情、原材料、人工、物流等因素对…

generalized focal loss之quality focal loss(附代码)

参见paper 其中包含有Quality Focal Loss 和 Distribution Focal Loss。 先来说一下Quality Focal Loss, 在这之前&#xff0c;先要了解一下Focal Loss, 在这篇文章里有写过。 它主要是解决class imbalance&#xff0c;同时降低容易分类的weight&#xff0c;使训练更集中到难…

集成开发工具IDEA导入新项目,update index时间过程

集成开发工具IDEA导入新项目&#xff0c;update index时间过程&#xff0c;一般这种场景出现在&#xff1a; 1.继承开发工具比较新&#xff08;使用了优化的索引算法&#xff0c;这种算法一般是前期编译比较慢&#xff0c;一旦编译完&#xff0c;存入缓存&#xff0c;后期搜索就…

C语言经典100例(008,009,010)

题目&#xff1a;输出9*9口诀。 程序分析&#xff1a;分行与列考虑&#xff0c;共 9 行 9 列&#xff0c;i 控制行&#xff0c;j 控制列。 程序源代码&#xff1a; #include<stdio.h> int main() {int i,j,result;printf("\n");for (i1;i<10;i){for(j1;j…

fork()||fork(),循环fork()与\n

fork()||fork()输出几个A&#xff1f;父进程左边的fork()产生一个子进程&#xff08;1&#xff09;&#xff0c;父进程fork返回值>0,||不执行右边。子进程&#xff08;1&#xff09;中fork()返回0&#xff0c;执行||右边的fork()产生第二个子进程&#xff08;2&#xff09;到…

电脑蓝屏怎么解决?一键快速解决蓝屏问题

电脑蓝屏也是一个经常出现的情况&#xff0c;让人十分头疼。蓝屏的原因有很多&#xff0c;但大多数是由内存条、硬盘或散热系统造成的。电脑蓝屏怎么解决&#xff1f;遇到这个问题&#xff0c;可以从下面四个方法来入手&#xff0c;一键快速解决电脑蓝屏问题&#xff01; 操作环…

Android 深入系统完全讲解(9)

3 JNI 调试 开发 android 应用&#xff0c;主要围绕着 java 语言&#xff0c;可是&#xff0c;如果我们需要追求性能&#xff0c;或者需要调用之前我们已经写好的 c c so 库的时候&#xff0c;或者和硬件打交道的时候&#xff0c;那么我们就会接触到 JNI&#xff08;java nati…

Cadence:层次化电路+信号线束

之前用Altium Designer做工程&#xff0c;偏向于使用层次化电路信号线束的方式画图&#xff0c;类似下图&#xff1a; 现在工作需求使用Cadence&#xff0c;继续采用层次化电路设计信号线束的方式&#xff0c;总结如下&#xff1a; 打开OrCAD Capture&#xff0c;创建一个工程…

libtorch在windows使用(c++项目中部署.pt)

狗头pytorch官网教程&#xff1a;Loading a TorchScript Model in C — PyTorch Tutorials 1.13.1cu117 documentation首先我已经有了个model.pt&#xff0c;就不需要做前面序列化为文件之类的操作&#xff0c;直接从在C中加载开始最后成功的版本&#xff1a;example-app.cpp 内…

计算机CCF-C的SCI期刊,值得投稿吗? - 易智编译EaseEditing

ccf应该说是比较权威的&#xff0c;哪怕是C类。 目前不少SCI期刊开始在投稿时&#xff0c;就建议非英语母语作者进行SCI润色后再投稿。 甚至有的杂志还将润色后的English editing certificate作为硬性上传文件指标&#xff0c;列在投稿系统中。 英语润色也是为了避免学术上的…

超优化文章记录之NeurIPS2022_Gradient Descent: The Ultimate Optimizer

作者&#xff1a;Kartik Chandra 单位&#xff1a;MIT 官网链接&#xff1a;Github 下面将首先以简单翻译文章重要内容&#xff0c;穿插一些讲解&#xff0c;并进行简单的复现实验。之后总结各种资料&#xff0c;如review意见等。最后讲解代码&#xff0c;研究具体实现。 文章…

VUE_关于Vue.use()详解

问题 相信很多人在用Vue使用别人的组件时&#xff0c;会用到 Vue.use() 。例如&#xff1a;Vue.use(VueRouter)、Vue.use(MintUI)。但是用 axios时&#xff0c;就不需要用 Vue.use(axios)&#xff0c;就能直接使用。那这是为什么呐&#xff1f; 答案 因为 axios 没有 instal…

Arduino工程的创建和实例使用

下载安装 网址&#xff1a;https://www.arduino.cc/en/software&#xff0c;如下图&#xff0c;选择合适的版本下载使用 下载后直接安装就行 因为这是一个完全开源免费的软件不需要破解&#xff0c;只需要注意安装目录就行 可以参考https://blog.csdn.net/impossible_Jesse…

Kubernetes(k8s) 笔记总结(三)

提示&#xff1a;针对kubernetes的服务网络学习。 文章目录一、Kubernetes的 Service服务发现 ClusterIP方式1. Service 介绍2. Service 暴露ClusterIP的方式(集群内部访问)3. Service 暴露NodePort方式(集群外也可以访问)二、Kubernets 之 Ingress1. Ingress 介绍2. Ingress 安…

十一、51单片机之串口通信

1、通信的关键 (1)事先约定。通信之前规定好的&#xff0c;如通信速率&#xff0c;起始信号&#xff0c;结束信号等。 (2)通信传输的基本信息单元。 (3)信息的编码、传输、解码。 2、通信相关的概念 2.1、同步和异步 (1)同步通信要求接收端时钟频率与发送端时钟频率一致&a…

【Python爬虫项目实战】Python爬虫采集弹幕数据

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言一、开发工具二、环境搭建三、数据来源查询分析四、代码实现1. 发送请求2.设置编码格式3.解析数据4.保存数据总结前言 今天给大家介绍的是Python爬虫采集弹幕数…

django项目中使用logging记录日志

前提 基于已有项目https://blog.csdn.net/qq_38122800/article/details/128583379?spm1001.2014.3001.5502 1、修改settings.py 在settings.py文件中添加如下代码: 先导入模块: import os,time#配置日志cur_path os.path.dirname(os.path.realpath(__file__)) # log_pat…

Vue3——第九章(依赖注入:provide、inject)

一、Prop 逐级透传问题 通常情况下&#xff0c;当我们需要从父组件向子组件传递数据时&#xff0c;会使用 props。如果需要给深层子组件传递数据&#xff0c;会非常麻烦&#xff0c;如下图&#xff1a; provide 和 inject 可以帮助我们解决这一问题。一个父组件相对于其所有的…

【memcpy和memove函数的详解】

1.memcpy函数详解 模拟实现memcpy函数 2.memmove函数详解 模拟实现memmove函数 memset函数详解 memcpy函数 了解一个函数&#xff0c;就查询该函数的相关信息 memcpy函数在库中的声明如下&#xff1a; void * memcpy ( void * destination, const void * source, size_…