监督模式执行环境 (SEE, Supervisor Execution Environment) 运行在 M(Mashine)机器模式上,这是站在运行在 S 模式上的软件的视角来看,它的下面也需要一层执行环境支撑,因此被命名为 SEE,它需要在相比 S 模式更高的特权级下运行, 一般情况下在 M 模式上运行。
按需实现 RISC-V 特权级 RISC-V 架构中,只有 M 模式是必须实现的,剩下的特权级则可以根据跑在 CPU 上应用的实际需求进行调整:
简单的嵌入式应用只需要实现 M 模式;
带有一定保护能力的嵌入式系统需要实现 M/U 模式;
复杂的多任务系统则需要实现 M/S/U 模式。
到目前为止,(Hypervisor, H)模式的特权规范还没完全制定好,所以暂时不会涉及。
执行环境的其中一种功能是在执行它支持的上层软件之前进行一些初始化工作。我们之前提到的引导加载程序会在加电后对整个系统进行 初始化,它实际上是 SEE 功能的一部分,也就是说 在 RISC-V 架构上引导加载程序一般运行在 M 模式上。此外,编程语言的标准库也会在执行程序员 编写的逻辑之前进行一些初始化工作,但是在这张图中我们并没有将其展开,而是统一归类到 U 模式软件,也就是应用程序中。
简单的支持单个裸机应用的库级别的“三叶虫”操作系统 和应用程序全程运行在 S 模式下,应用程序很容易破坏没有任何保护的执行环境–操作系统。
在后续的章节中,我们会涉及到RISC-V的 M/S/U 三种特权级:其中应用程序和用户态支持库运行在 U 模式的最低特权级;操作系统内核运行在 S 模式特权级(在本章表现为一个简单的批处理系统),形成支撑应用程序和用户态支持库的执行环境;而第一章提到的预编译的 bootloader – RustSBI 实际上是运行在更底层的 M 模式特权级下的软件,是操作系统内核的执行环境。整个软件系统就由这三层运行在不同特权级下的不同软件组成。
在特权级相关机制方面,本书正文中我们重点关心RISC-V的 S/U 特权级, M 特权级的机制细节则是作为可选内容在 深入机器模式:RustSBI 中讲解,有兴趣的读者可以参考。
与特权级无关的一般的指令和通用寄存器 x0~x31 在任何特权级都可以任意执行。而每个特权级都对应一些特殊指令和 控制状态寄存器 (CSR, Control and Status Register),来控制该特权级的某些行为并描述其状态,当然特权指令不只是具有有读写 CSR 的指令,还有其他功能的特权指令。
本节主要讲解如何设计实现被批处理系统逐个加载并运行的应用程序,它们是假定在 U 特权级模式运行的前提下而设计、编写的。实际上,如果应用程序的代码都符合它要运行的某特权级的约束,那它完全可能在某特权级中运行。保证应用程序的代码在 U 模式运行是我们接下来将实现的批处理系统的任务,其涉及的设计实现要点是:
ecall 作为异常的一种,操作系统和CPU对它的处理方式其实和其他各种异常没什么区别。U态进行ecall调用具体的异常编号是8-Environment call from U-mode。
RISCV处理异常需要引入几个特殊的寄存器——CSR 控制状态寄存器 (Control and Status Register) ,这些寄存器会 记录异常和中断处理流程所需要或保存的各种信息 。几个比较关键的CSR寄存器如下(需要注意的是下面这些寄存器是S态的CSR寄存器,M态还有一套自己的CSR寄存器mcause,mtvec等):
.section .text
.globl trampoline
trampoline:.align 4.globl uservec
uservec:
#
#trap.c sets stvec to point here, so#trapsfrom user space start here,#insupervisor mode, but with a#userpage table.
#
#sscratchpoints to where the process's p->trapframe is#mappedinto user space, at TRAPFRAME.
#
#swapa0 and sscratch#sothat a0 is TRAPFRAME
csrrw a0, sscratch, a0
#savethe user registers in TRAPFRAME
sd ra,40(a0)...
sd t6,280(a0)#savethe user a0 in p->trapframe->a0
csrr t0, sscratch
sd t0,112(a0)
csrr t1, sepc
sd t1,24(a0)
ld sp,8(a0)
ld tp,32(a0)
ld t1,0(a0)#csrwsatp, t1#sfence.vma zero, zero
ld t0,16(a0)
jr t0
trapinit 这个函数在main的初始化之中已经调用了。
// os/trap.c// set up to take exceptions and traps while in the kernel.voidtrapinit(void){w_stvec((uint64)uservec &~0x3);// 写 stvec, 最后两位表明跳转模式,该实验始终为 0}
voidusertrapret(structtrapframe*trapframe, uint64 kstack){
trapframe->kernel_satp =r_satp();// kernel page table
trapframe->kernel_sp = kstack + PGSIZE;// process's kernel stack
trapframe->kernel_trap =(uint64)usertrap;
trapframe->kernel_hartid =r_tp();// hartid for cpuid()w_sepc(trapframe->epc);// 设置了sepc寄存器的值。// set up the registers that trampoline.S's sret will use// to get to user space.// set S Previous Privilege mode to User.
uint64 x =r_sstatus();
x &=~SSTATUS_SPP;// clear SPP to 0 for user mode
x |= SSTATUS_SPIE;// enable interrupts in user modew_sstatus(x);// tell trampoline.S the user page table to switch to.// uint64 satp = MAKE_SATP(p->pagetable);userret((uint64)trapframe);}
.globl userret
userret:#userret(TRAPFRAME, pagetable)#switchfrom kernel to user.#usertrapret() calls here.#a0: TRAPFRAME, in user page table.#a1: user page table,for satp.#switchto the user page table.在第四章才会有具体作用。
csrw satp, a1
sfence.vma zero, zero
#putthe saved user a0 in sscratch, so we#canswap it with our a0(TRAPFRAME) in the last step.
ld t0,112(a0)
csrw sscratch, t0
#restoreall but a0 from TRAPFRAME
ld ra,40(a0)
ld sp,48(a0)
ld gp,56(a0)
ld tp,64(a0)
ld t0,72(a0)
ld t1,80(a0)
ld t2,88(a0)...
ld t4,264(a0)
ld t5,272(a0)
ld t6,280(a0)#restoreuser a0,and save TRAPFRAME in sscratch
csrrw a0, sscratch, a0
#returnto user mode and user pc.#usertrapret() set up sstatus and sepc.
sret
1、增加的数据库
ALTER TABLE eb_store_order ADD cart_number VARCHAR(255) NOT NULL DEFAULT COMMENT 车牌 AFTER erp_order_id, ADD curmileage VARCHAR(255) NOT NULL DEFAULT COMMENT 当前里程 AFTER cart_number;
ALTER TABLE eb_store_cart ADD cart_number VARCHAR(…
1.go下载trpc
go install trpc.group/trpc-go/trpc-cmdline/trpclatest
有报错的话尝试配置一些代理(选一个)
go env -w GOPROXYhttps://goproxy.cn,direct
go env -w GOPROXYhttps://goproxy.io,direct
go env -w GOPROXYhttps://goproxy.baidu.com/…