视频结尾论文部分

VM FOR APPLICATION

原语

论文论述的(primitive)原语及在linux上的实现

  • trap 中断处理函数 ——> sigaction
  • prrt1 减少访问权限 ——> mprotect
  • portN 节省TLB刷新 ——> mprotect
  • unport增加访问权限 ——> mprotect
  • dirty脏页
  • map2 ——> mmap

unix/linux today

  • mmap,unmap 将文件映射到虚拟内存,允许用指针来操作文件
  • mprotect,修改页权限

  • sigaction,定义信号处理程序

USER-LEVEL TRAPS

用户可以设置中断处理程序。中断产生时,跳转到内核,内核发现用户设置了中断处理程序,跳转到中断处理程序,处理完后返回内核,然后内核恢复进程。

应用

calculate

我们可以将昂贵的函数计算值存储在内存中,若我们想控制计算值内存空间的大小,我们可以通过mmapmunmap保持计算值的内存大小。当计算值存储产生page fault时,我们可以选择一个牺牲页,将旧值替换为新值。

garbage collect

  • A copying garbage collector:

    • from space:原来的状态,包含垃圾,从root 遍历图,指针指向能遍历到的节点。

      • ​ forward(转发)
    • to space:新的状态,将指针指向的节点复制过来。

    • Backer’s: real time <— incrementally

  • USE VM

    • 通过map2将未扫描的页面映射到垃圾回收器,实现对未扫描的页面访问。

    • 当页面访问时触发中断,在中断处理程序进行检查,将要访问的对象复制到to space。

    • //TODO

其他特性

  • 5 levels pagetable:页表层数增加
  • ASIO :异步I/O操作
  • 刷新TLB
  • KPTI:将内核页表与用户空间页表隔离

OS Organization

BIG ABSTRACTION

  • PORTABILITY 可移植性

  • HIDE COMPLEXITY 隐藏底层的复杂性

  • RSESOURCE MANAGEMENT 资源管理

  • WHY NOT MONOLITHIC

    • BIG -> complex -> bugs -> security
    • GENERAL -> purpose ->slow
    • Design hard(add module or remove module)

MICRO KERNELS (微内核)

  • IDEA:TINY KERNEL
    • (inter-process communication)IPC 进程间通信
    • TASKS
  • WHY

    • small ——> security
    • small ——> verifiable ——> sel4
    • small ——> fast
    • small ——> flexibility
    • user level ——> modular、customize
  • CHALLENGES

    • minimum syscall API fork、exec
    • rest of O/S
    • fast IPC

L4 kernel

  • small kernel
  • 直接在L4微内核将linux内核作为用户任务运行。
    • 用户任务通过定制的库将系统调用通过IPC发送给linux kernel
    • 任务调度由 l4 kernel负责,linux无法调度。所以这里linux和task的关系更像cs模型
  • 7 syscall
  • support task、address space、thread、IPC
    • 如出现中断等:task通过IPC发送给中断处理程序(如缺页异常),中断处理用户程序将页映射到该task。
  • fast ipc
    • synchronous、unbuffered
    • 想象当两个任务进行pipe通信,当一方send(a,&addr1)且同时一方recv(b, &addr2)时,我们能获得消息的源地址和目的地址。可以直接在两任务间进行IPC传输而不用进入L4内核(避免上下文切换、pipe缓冲区的复制、TLB刷新等操作)
      • 当消息可以被寄存器放下时,可以通过寄存器传输registers —— zero copy
      • 当消息很大时,我们甚至可以直接传输页 PAGE
      • RPC
        • call() —— send + recv
        • 即我们的内核等基础服务像服务器那样监听任务传来的IPC通信讯息
  • dual space mistake(双空间错误)
    • linux将内核线程和用户进程映射到同一个页表,减少系统调用等开支。
    • 即在L4 kernel,内核和用户进程是不共用页表的,但是论文作者想实现linux相似功能(即用户的虚拟地址对内核是可见的),为每个任务分配对应的linux内核副本。但是由于这样导致任务翻倍,效果反而大打折扣。

virtual machines

虚拟机分类

  • 软件模拟:VMware、qemu
  • 硬件辅助:Microsoft Hyper-V、KVM

pure virtual machines software: so slow

VMM实现

HOST: VMM

USER: guest Linux、guest windows

TRAP-AND-EMULATE

  • VMM在监督者模式下运行,用以执行特权指令,客户机(linux)做任何有特权的事时,都会进入trap,然后VMM模拟特权指令。

  • 监视器为每个guest user维护一个virtual state,当执行特权指令时(如stvec、sepc),VMM模拟这些指令的操作,确保它们在虚拟机内部正确执行,同时保护物理硬件不受虚拟机直接访问的威胁。

  • 客户机视角来看,VMM是不存在的,她们直接与硬件进行交互。

  • satp寄存器

    • 当客户机(guest)尝试访问内存时,它会使用虚拟地址(GVA - Guest Virtual Address)。

    • 虚拟机监视器(VMM)需要将这个虚拟地址转换为物理地址(GPA - Guest Physical Address),以便在物理硬件上访问实际的内存位置。

    • 查看期望的客户机虚拟地址:客户机尝试访问的虚拟地址被记录下来。

    • VMM映射:VMM使用其内部的数据结构(如影子页表)来查找GPA对应的物理地址。

    • 影子页表(shadow pagetable)影子页表是VMM维护的一个数据结构,它将GVA映射到GPA,然后将GPA映射到实际的物理地址。

    • 设置satp:一旦VMM找到物理地址,它将这个物理地址加载到satp寄存器中

  • Device

    • EMULATION:将设备地址设置为不可访问,当客户机访问时,进入trap
      • 客户机可以根据访问速度判度她们处在虚拟机中
    • VIRTUAL DEVICE:设备和虚拟硬件是解隅的(减少trap),其设计和实现与物理硬件的接口相匹配
    • PASS-THRU:硬件支持虚拟机。

HARDWARE VMS-VT-s

  • 让客户机直接通过硬件执行特权指令
    • 虚拟机:”NON-ROOT”
    • VMM: “ROOT”
    • 通过硬件支持特权指令的检测
    • 通过VMM指令开启启动关闭客户机
    • EPT:VMM通过设置EPT指向一个页表来控制客户机可访问的物理内存

Dune(VT-X support)

  • 进程通过Dune设置EPT实现独立的页表

  • 获得user mode和 super mode

    • 沙箱支持,被检测的程序在用户状态下运行,检测程序在监督者模式下运行,使得可以追踪系统调用等情况
    • 垃圾回收,可以对扫描过的节点检测PTE 的Dirty位来判断时候需要重新扫描。

kernels and high level language

C

  • 优点

    • 可以精确控制内存分配和释放

    • 易于理解的代码(指linux之父能从c看到汇编(人肉编译器))

    • 直接访问内存(通过指针)

    • 低依赖,指通过几条汇编指令设置寄存器后即可跳转到C代码

  • 缺点

    • 缓冲区溢出
    • 使用已经释放的内存
    • 线程共享的内存释放问题

高级语言

  • 优点
    • 类型安全
    • 垃圾回收机制
    • 对并发的支持
    • 支持更好的抽象,模块化代码
  • 缺点
    • 低性能
      • 边界检查,类型转换等操作消耗性能
      • 垃圾回收
    • 不适用于内核编程
      • 不能直接访问内存
      • 难以集成汇编,如c和cpp提供了内联汇编的功能,也可以在链接时链接到汇编程序‘’
      • 编程语言本身支持的并发与内核需要的并发并不一致

meltdown

  • KASLR:内核地址随机化

  • 预测执行:根据分支预测的结果来提前执行指令的过程。

    • 如果预测正确,则能显著提升性能;如果预测失败,

    • 则所有推测执行的结果会被抛弃,并且流水线会被清空。

    • 影子寄存器暂存推测执行的结果,直到分支预测的结果被确认。

  • 漏洞原因:intel cpu在执行命令时会先加载内存的值,当加载退出时才会检测标志
  • caches结构:

    • core

      L1: va | data | perms TLB: va -> pa

      L2、L3: pa | data

      RAM

    • 在多核处理器系统中,L2缓存通常是每个核心私有的,而L3缓存是多个核心共享的。如果L2和L3缓存使用虚拟地址,那么在处理缓存一致性问题时会变得复杂,因为不同的核心可能有不同的虚拟地址映射到相同的物理地址。使用物理地址可以简化这个问题,因为物理地址在所有核心之间是一致的。

  • 缓存刷新:FLUSH + RELOAD —-x

    • clFlush x 刷新缓冲
    • f()
    • a = rdtsc 获取加载时间
    • junk = x
    • b = rdtsc 再次获取时间
    • b - a = c 若c时间短则说明使用了x内存。
  • 漏洞原理:逐步获取内核每一位

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    char buf[8192];

    //FLUSH + RELOAD
    clflush buf[0];
    clfush bf[4096];

    //消耗cpu时间的指令,延长`加载`退出时间

    r1 = kernel addr;
    r2 = r1 & 1;
    r2 = r2 * 4096; //r2为0或4098
    r3 = buf[r2]; //将buf[r2]加载到缓存中
    < handle the page fault from "r2 = *r1" > //不恢复缓存

    //计算加载时间,通过时长判断是否在缓存
    // the reload of flush+reload
    a = rdtsc;
    r0 = buf[0];
    b = rdtsc;
    r1 = buf[4096];
    c = rdtsc
    if b - a < c - b //buf[0]在缓存中
    //0 & 1 = 0, 0 * 4096 = 0,则该bit为0

  • 解决方案:
    • 像xv6将内核和用户空间反别使用虚拟地址空间
    • 在读取指令时获取指令权限
    • 通过操作系统修复

RCU(读远多于写)

  • multiple reader,only one writer

    • 维持write锁和read锁(一个变量n,-1表示写,0表示没有进程使用,>=1表示有一个或多个读者),通过Compare and Swap(CAS)实现原子操作
      • 如果有多个 读写者,则陷入竞争
      • 如果是多核机器,需要保持缓存一致性(标记其他cpu的缓存无效),导致O(n^2)的消耗。
  • IDEA

    • 更新数据分配一个副本,再将指针指向副本(commit 原子的, 需要在编写时添加屏障(读写者都需要)),同时不要释放原来数据,因为可能有读者正在访问
    • 延迟冻结
      • 读者不能进行上下文切换
      • 将释放延迟到每个cpu至少切换过一次上下文。