parent
1858a86b82
commit
f11911fca7
44
Makefile
44
Makefile
|
@ -98,7 +98,7 @@ endif
|
|||
|
||||
# Compile Kernel
|
||||
$T/kernel: $(OBJS) $(linker) $U/initcode
|
||||
if [ ! -d "./target" ]; then mkdir target; fi
|
||||
@if [ ! -d "./target" ]; then mkdir target; fi
|
||||
@$(LD) $(LDFLAGS) -T $(linker) -o $T/kernel $(OBJS)
|
||||
@$(OBJDUMP) -S $T/kernel > $T/kernel.asm
|
||||
@$(OBJDUMP) -t $T/kernel | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $T/kernel.sym
|
||||
|
@ -130,7 +130,7 @@ QEMUOPTS = -machine virt -bios $(RUSTSBI) -kernel $T/kernel -m 128M -smp $(CPUS)
|
|||
QEMUOPTS += -drive file=fs.img,if=none,format=raw,id=x0
|
||||
QEMUOPTS += -device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0
|
||||
|
||||
run: build fs.img
|
||||
run: build
|
||||
ifeq ($(platform), k210)
|
||||
@$(OBJCOPY) $T/kernel --strip-all -O binary $(image)
|
||||
@$(OBJCOPY) $(RUSTSBI) --strip-all -O binary $(k210)
|
||||
|
@ -142,9 +142,6 @@ else
|
|||
@$(QEMU) $(QEMUOPTS)
|
||||
endif
|
||||
|
||||
fs.img: $(UPROGS)
|
||||
@./fs.sh
|
||||
|
||||
$U/initcode: $U/initcode.S
|
||||
$(CC) $(CFLAGS) -march=rv64g -nostdinc -I. -Ikernel -c $U/initcode.S -o $U/initcode.o
|
||||
$(LD) $(LDFLAGS) -N -e start -Ttext 0 -o $U/initcode.out $U/initcode.o
|
||||
|
@ -173,9 +170,6 @@ $U/_forktest: $U/forktest.o $(ULIB)
|
|||
$(LD) $(LDFLAGS) -N -e main -Ttext 0 -o $U/_forktest $U/forktest.o $U/ulib.o $U/usys.o
|
||||
$(OBJDUMP) -S $U/_forktest > $U/forktest.asm
|
||||
|
||||
mkfs/mkfs: mkfs/mkfs.c $K/include/fs.h $K/include/param.h
|
||||
@gcc -Werror -Wall -I. -o mkfs/mkfs mkfs/mkfs.c
|
||||
|
||||
# Prevent deletion of intermediate files, e.g. cat.o, after first build, so
|
||||
# that disk image changes after first build are persistent until clean. More
|
||||
# details:
|
||||
|
@ -205,23 +199,31 @@ UPROGS=\
|
|||
# $U/_wc\
|
||||
# $U/_zombie\
|
||||
|
||||
UEXTRA = $U/xargstest.sh
|
||||
userprogs: $(UPROGS)
|
||||
|
||||
userprogs: $(UEXTRA) $(UPROGS)
|
||||
dst=/mnt
|
||||
|
||||
# Make fs image
|
||||
fs: mkfs/mkfs README $(UEXTRA) $(UPROGS)
|
||||
@mkfs/mkfs fs.img README $(UEXTRA) $(UPROGS)
|
||||
|
||||
-include kernel/*.d user/*.d
|
||||
|
||||
SDCARD ?= /dev/sdb
|
||||
fs: $(UPROGS)
|
||||
@if [ ! -f "fs.img" ]; then \
|
||||
echo "making fs image..."; \
|
||||
dd if=/dev/zero of=fs.img bs=512k count=1024; \
|
||||
mkfs.vfat -F 32 fs.img; fi
|
||||
@sudo mount fs.img $(dst)
|
||||
@if [ ! -d "$(dst)/bin" ]; then sudo mkdir $(dst)/bin; fi
|
||||
@sudo cp $U/_init $(dst)/init
|
||||
@sudo cp $U/_sh $(dst)/sh
|
||||
@for file in $$( ls $U/_* ); do \
|
||||
sudo cp $$file $(dst)/bin/$${file#$U/_}; done
|
||||
@sudo umount $(dst)
|
||||
|
||||
# Write sdcard
|
||||
sdcard: fs
|
||||
@echo "flashing into sd card..."
|
||||
@sudo dd if=/dev/zero of=$(SDCARD) bs=1M count=50
|
||||
@sudo dd if=fs.img of=$(SDCARD)
|
||||
@if [ "$(sd)" != "" ]; then \
|
||||
echo "flashing into sd card..."; \
|
||||
sudo dd if=fs.img of=$(sd); \
|
||||
else \
|
||||
echo "sd card not detected!"; fi
|
||||
|
||||
clean:
|
||||
rm -f *.tex *.dvi *.idx *.aux *.log *.ind *.ilg \
|
||||
|
@ -229,6 +231,6 @@ clean:
|
|||
$T/* \
|
||||
$U/initcode $U/initcode.out \
|
||||
$K/kernel \
|
||||
mkfs/mkfs .gdbinit \
|
||||
$U/usys.S \
|
||||
.gdbinit \
|
||||
$U/usys.S \
|
||||
$(UPROGS)
|
||||
|
|
19
README.md
19
README.md
|
@ -40,7 +40,12 @@ make build
|
|||
## Run on k210 board
|
||||
Instead of the original file system, xv6-k210 runs with FAT32. You might need an SD card with FAT32 format.
|
||||
To start `shell`, you need to rename the "_init" and "_sh" in the "/xv6-user" to "init" and "sh" after building,
|
||||
then copy them to the root of your SD card.
|
||||
then copy them to the root of your SD card. Or you can directly run the command as below with your SD card connected.
|
||||
|
||||
Warning: this will format your SD card and clean your original data!
|
||||
```bash
|
||||
make sdcard sd="your SD card device's path"
|
||||
```
|
||||
|
||||
To run on k210:
|
||||
```bash
|
||||
|
@ -56,16 +61,12 @@ may help you: [maixpy-doc](https://maixpy.sipeed.com/zh/get_started/env_install_
|
|||
|
||||
## Run on qemu-system-riscv64
|
||||
First, make sure `qemu-system-riscv64` is installed on your system.
|
||||
Second, build the project to compile some user programs like `shell`.
|
||||
Second, make a disk image file with FAT32 file system.
|
||||
```bash
|
||||
make build platform=qemu
|
||||
make fs
|
||||
```
|
||||
Then use the shell script `fs.sh`:
|
||||
```bash
|
||||
./fs.sh
|
||||
```
|
||||
It will generate a disk image file `fs.img`, and copy some programs into the file.
|
||||
As long as the `fs.img` exists, you don't need to run this script every time.
|
||||
It will generate a disk image file `fs.img`, and compile some user programs like `shell` then copy them into the `fs.img`.
|
||||
As long as the `fs.img` exists, you don't need to do this every time before running, unless you want to update it.
|
||||
|
||||
Finally, start running.
|
||||
```bash
|
||||
|
|
20
README_cn.md
20
README_cn.md
|
@ -39,7 +39,13 @@ make build
|
|||
|
||||
## 在 k210 开发板上运行
|
||||
Xv6-k210 采用 FAT32 文件系统,而不是其原本的文件系统。您需要一张 FAT32 格式的 SD 卡才能运行。
|
||||
在编译项目后,您需要将 “/xv6-user” 目录下的 “_init” 和 “_sh” 重命名为 “init” 和 “sh”,并拷贝至SD卡的根目录下。
|
||||
在编译项目后,您需要将 “/xv6-user” 目录下的 “_init” 和 “_sh” 重命名为 “init” 和 “sh”,并拷贝至 SD 卡的根目录下。
|
||||
或者,您可以直接运行以下命令。
|
||||
|
||||
警告:这会格式化您的 SD 卡并清除卡上的原有数据!
|
||||
```bash
|
||||
make sdcard sd="your SD card device's path"
|
||||
```
|
||||
|
||||
运行以下命令以在 `k210` 上运行:
|
||||
```bash
|
||||
|
@ -53,16 +59,12 @@ make run k210-serialport=`USB 端口`(默认是 ttyUSB0)
|
|||
Ps: 在 `Linux` 上这个端口大部分情况是 `ttyUSB0`, 如果您使用 `Windows` 或者 `MacOS`,这个文档可以帮助到您:[maixpy-doc](https://maixpy.sipeed.com/zh/get_started/env_install_driver.html#)
|
||||
|
||||
## 在 qemu-system-riscv64 模拟器上运行
|
||||
首先,确保 `qemu-system-riscv64` 已经下载到您的机器上并且加到了环境变量中。
|
||||
其次,编译项目生成用户程序,如 `shell` 等。
|
||||
首先,确保 `qemu-system-riscv64` 已经下载到您的机器上并且加到了环境变量中;
|
||||
其次,需要一个 FAT32 磁盘镜像文件;
|
||||
```bash
|
||||
make build platform=qemu
|
||||
make fs
|
||||
```
|
||||
然后运行 `fs.sh` 脚本:
|
||||
```bash
|
||||
./fs.sh
|
||||
```
|
||||
该脚本会生成一个镜像文件 `fs.img` 并将编译好的用户程序拷贝至其中。只要 `fs.img` 存在并且不需要修改,您不必每次都使用这个脚本。
|
||||
这会生成一个镜像文件 `fs.img` ,编译一些用户程序(如 `shell`)并拷贝至镜像中。只要 `fs.img` 存在并且不需要修改,您不必每次运行前都执行这个命令。
|
||||
|
||||
最后,开始运行:
|
||||
```bash
|
||||
|
|
|
@ -16,32 +16,5 @@
|
|||
|
||||
对FAT32的支持只是一个简单的实现,还未经过严格的测试,存在许多不足。这里需要说明几点。
|
||||
|
||||
+ 为了简单起见,目前新建文件时无法生成时间戳、未计算文件名校验和、未完成长文件名到短文件名的转换;
|
||||
+ 为了简单起见,目前新建文件时无法生成时间戳,将长文件名转换到短文件名时未排重(这会影响较低版本的 FAT 系统);
|
||||
+ FAT32的文件属性不支持设备类型,而原xv6文件系统中有`mknod`系统调用新建一个设备,并可以使用`open`打开。控制台输入输出就是这样打开的。为打开控制台标准输入输出,我们改用了另一种实现,即直接在内存中初始化控制台。
|
||||
|
||||
## 如何在qemu上挂载文件镜像
|
||||
|
||||
首先需要一个FAT32文件镜像,在Linux下可以通过`dd`命令和`mkfs`命令生成一个镜像,将生成的fs.img文件放在xv6-k210目录下即可。
|
||||
|
||||
```bash
|
||||
$ dd if=/dev/zero of=fs.img bs=512k count=2048
|
||||
$ mkfs.vfat -F 32 fs.img
|
||||
```
|
||||
注意:`dd`命令中的`bs`和`count`的参数只是参考,这会生成1GB的镜像。
|
||||
|
||||
## 如何在镜像中存入用户程序
|
||||
|
||||
首先通过`mount`命令,将镜像挂载到你指定的目录(这里以/mnt为例),然后将build之后xv6-user目录下文件名以"\_"为前缀的用户程序拷贝至镜像中,再取消挂载以保存写入结果即可。也可以在镜像中建立一些文本文件进行读测试。
|
||||
|
||||
注意:必须将xv6-user目录下的"\_init"拷贝至镜像根目录中,并且重命名为"init"(这是xv6原本的设定,目前我们暂未更改),还需拷贝"\_sh"至镜像中,才能启动shell。编写的用户程序也需要放在xv6-user目录下,同时需要添加至Makefile的`UPROGS`目标中,才能连同内核一起编译链接。
|
||||
|
||||
```bash
|
||||
$ make build
|
||||
$ (sudo)mount fs.img /mnt
|
||||
$ (sudo)cp xv6-user/_init /mnt/init
|
||||
$ (sudo)cp xv6-user/_sh /mnt
|
||||
$ (sudo)cp xv6-user/... /mnt
|
||||
$ ...
|
||||
$ (sudo)umount /mnt
|
||||
```
|
||||
PS:可以通过执行fs.sh脚本自动完成上述操作。
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
|
||||
## 如何在qemu上挂载文件镜像
|
||||
|
||||
首先需要一个FAT32文件镜像,在Linux下可以通过`dd`命令和`mkfs`命令生成一个镜像,将生成的fs.img文件放在xv6-k210目录下即可。
|
||||
|
||||
```bash
|
||||
$ dd if=/dev/zero of=fs.img bs=512k count=2048
|
||||
$ mkfs.vfat -F 32 fs.img
|
||||
```
|
||||
注意:`dd`命令中的`bs`和`count`的参数只是参考,这会生成1GB的镜像。
|
||||
|
||||
## 如何在镜像中存入用户程序
|
||||
|
||||
首先通过`mount`命令,将镜像挂载到你指定的目录(这里以/mnt为例),然后将build之后xv6-user目录下文件名以"\_"为前缀的用户程序拷贝至镜像中,再取消挂载以保存写入结果即可。也可以在镜像中建立一些文本文件进行读测试。
|
||||
|
||||
注意:必须将xv6-user目录下的"\_init"拷贝至镜像根目录中,并且重命名为"init"(这是xv6原本的设定,目前我们暂未更改),还需拷贝"\_sh"至镜像中,才能启动shell。编写的用户程序也需要放在xv6-user目录下,同时需要添加至Makefile的`UPROGS`目标中,才能连同内核一起编译链接。
|
||||
|
||||
```bash
|
||||
$ make build
|
||||
$ (sudo)mount fs.img /mnt
|
||||
$ (sudo)cp xv6-user/_init /mnt/init
|
||||
$ (sudo)cp xv6-user/_sh /mnt
|
||||
$ (sudo)cp xv6-user/... /mnt
|
||||
$ ...
|
||||
$ (sudo)umount /mnt
|
||||
```
|
||||
PS:现已可以通过执行 `make fs` 自动完成上述操作。
|
||||
|
||||
## 如何在 SD 卡中存入用户程序
|
||||
将上述操作生成的 `fs.img` 写入 SD 卡即可。可以执行操作:
|
||||
```bash
|
||||
make sdcard sd="your SD card device"
|
||||
```
|
||||
警告:这会覆盖 SD 卡的原有数据与文件系统!
|
20
fs.sh
20
fs.sh
|
@ -1,20 +0,0 @@
|
|||
if [ ! -f "fs.img" ]; then
|
||||
dd if=/dev/zero of=fs.img bs=512k count=1024
|
||||
mkfs.vfat -F 32 fs.img
|
||||
fi
|
||||
|
||||
sudo mount fs.img /mnt
|
||||
sudo mkdir /mnt/bin
|
||||
sudo cp ./xv6-user/_init /mnt/init
|
||||
sudo cp ./xv6-user/_sh /mnt/sh
|
||||
sudo cp ./xv6-user/_cat /mnt/bin/cat
|
||||
sudo cp ./xv6-user/_echo /mnt/bin/echo
|
||||
sudo cp ./xv6-user/_grep /mnt/bin/grep
|
||||
sudo cp ./xv6-user/_ls /mnt/bin/ls
|
||||
sudo cp ./xv6-user/_kill /mnt/bin/kill
|
||||
sudo cp ./xv6-user/_mkdir /mnt/bin/mkdir
|
||||
sudo cp ./xv6-user/_xargs /mnt/bin/xargs
|
||||
sudo cp ./xv6-user/_rm /mnt/bin/rm
|
||||
sudo cp ./xv6-user/_sleep /mnt/bin/sleep
|
||||
sudo cp ./xv6-user/_find /mnt/bin/find
|
||||
sudo umount /mnt
|
|
@ -55,7 +55,9 @@ binit(void)
|
|||
bcache.head.next->prev = b;
|
||||
bcache.head.next = b;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("binit\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Look through buffer cache for block on device dev.
|
||||
|
|
|
@ -24,7 +24,9 @@ void
|
|||
fileinit(void)
|
||||
{
|
||||
initlock(&ftable.lock, "ftable");
|
||||
#ifdef DEBUG
|
||||
printf("fileinit\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Allocate a file structure.
|
||||
|
|
|
@ -4936,5 +4936,7 @@ void fpioa_pin_init() {
|
|||
fpioa_set_function(26, FUNC_SPI0_D1);
|
||||
fpioa_set_function(32, FUNC_GPIOHS7);
|
||||
fpioa_set_function(29, FUNC_SPI0_SS3);
|
||||
#ifdef DEBUG
|
||||
printf("fpioa_pin_init\n");
|
||||
#endif
|
||||
}
|
|
@ -29,7 +29,9 @@ kinit()
|
|||
initlock(&kmem.lock, "kmem");
|
||||
// printf("kernel_end: %p, phystop: %p\n", kernel_end, (void*)PHYSTOP);
|
||||
freerange(kernel_end, (void*)PHYSTOP);
|
||||
#ifdef DEBUG
|
||||
printf("kinit\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -25,7 +25,9 @@ main(unsigned long hartid, unsigned long dtb_pa)
|
|||
consoleinit();
|
||||
printfinit(); // init a lock for printf
|
||||
print_logo();
|
||||
#ifdef DEBUG
|
||||
printf("hart %d enter main()...\n", hartid);
|
||||
#endif
|
||||
kinit(); // physical page allocator
|
||||
kvminit(); // create kernel page table
|
||||
kvminithart(); // turn on paging
|
||||
|
@ -33,7 +35,6 @@ main(unsigned long hartid, unsigned long dtb_pa)
|
|||
trapinithart(); // install kernel trap vector
|
||||
timerinit(); // set up timer interrupt handler
|
||||
procinit();
|
||||
|
||||
#ifndef QEMU
|
||||
fpioa_pin_init();
|
||||
device_init(dtb_pa, hartid);
|
||||
|
@ -41,28 +42,28 @@ main(unsigned long hartid, unsigned long dtb_pa)
|
|||
plicinit();
|
||||
plicinithart();
|
||||
#endif
|
||||
|
||||
disk_init();
|
||||
|
||||
binit(); // buffer cache
|
||||
fileinit(); // file table
|
||||
|
||||
userinit(); // first user process
|
||||
|
||||
printf("hart 0 init done\n");
|
||||
|
||||
for(int i = 1; i < NCPU; i++) {
|
||||
unsigned long mask = 1 << i;
|
||||
sbi_send_ipi(&mask);
|
||||
}
|
||||
__sync_synchronize();
|
||||
started = 1;
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
// hart 1
|
||||
while (started == 0)
|
||||
;
|
||||
__sync_synchronize();
|
||||
#ifdef DEBUG
|
||||
printf("hart %d enter main()...\n", hartid);
|
||||
#endif
|
||||
kvminithart();
|
||||
trapinithart();
|
||||
timerinit(); // set up timer interrupt handler
|
||||
|
|
|
@ -16,7 +16,9 @@ plicinit(void)
|
|||
// set desired IRQ priorities non-zero (otherwise disabled).
|
||||
*(uint32*)(PLIC + UART0_IRQ*4) = 1;
|
||||
*(uint32*)(PLIC + VIRTIO0_IRQ*4) = 1;
|
||||
#ifdef DEBUG
|
||||
printf("plicinit\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -28,7 +30,9 @@ plicinithart(void)
|
|||
*(uint32*)PLIC_SENABLE(hart)= (1 << UART0_IRQ) | (1 << VIRTIO0_IRQ);
|
||||
// set this hart's S-mode priority threshold to 0.
|
||||
*(uint32*)PLIC_SPRIORITY(hart) = 0;
|
||||
#ifdef DEBUG
|
||||
printf("plicinithart\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
// ask the PLIC what interrupt we should serve.
|
||||
|
|
|
@ -62,7 +62,9 @@ procinit(void)
|
|||
p->kstack = va;
|
||||
}
|
||||
kvminithart();
|
||||
#ifdef DEBUG
|
||||
printf("procinit\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Must be called with interrupts disabled,
|
||||
|
@ -286,7 +288,9 @@ userinit(void)
|
|||
p->state = RUNNABLE;
|
||||
|
||||
release(&p->lock);
|
||||
#ifdef DEBUG
|
||||
printf("userinit\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Grow or shrink user memory by n bytes.
|
||||
|
|
|
@ -311,12 +311,12 @@ void sdcard_init(void) {
|
|||
int result = sd_init();
|
||||
initlock(&sdcard_lock, "sdcard");
|
||||
|
||||
if (0 == result) {
|
||||
printf("sdcard_init\n");
|
||||
}
|
||||
else {
|
||||
if (0 != result) {
|
||||
panic("sdcard_init failed");
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("sdcard_init\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void sdcard_read_sector(uint8 *buf, int sectorno) {
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
|
||||
#include "include/types.h"
|
||||
#include "include/param.h"
|
||||
#include "include/memlayout.h"
|
||||
#include "include/riscv.h"
|
||||
#include "include/defs.h"
|
||||
|
||||
void main();
|
||||
void timerinit();
|
||||
|
||||
// entry.S needs one stack per CPU.
|
||||
__attribute__ ((aligned (16))) char stack0[4096 * NCPU];
|
||||
|
||||
// scratch area for timer interrupt, one per CPU.
|
||||
uint64 mscratch0[NCPU * 32];
|
||||
|
||||
// assembly code in kernelvec.S for machine-mode timer interrupt.
|
||||
extern void timervec();
|
||||
|
||||
// entry.S jumps here in machine mode on stack0.
|
||||
void
|
||||
start()
|
||||
{
|
||||
// set M Previous Privilege mode to Supervisor, for mret.
|
||||
unsigned long x = r_mstatus();
|
||||
x &= ~MSTATUS_MPP_MASK;
|
||||
x |= MSTATUS_MPP_S;
|
||||
w_mstatus(x);
|
||||
|
||||
// set M Exception Program Counter to main, for mret.
|
||||
// requires gcc -mcmodel=medany
|
||||
w_mepc((uint64)main);
|
||||
|
||||
// disable paging for now.
|
||||
w_satp(0);
|
||||
|
||||
// delegate all interrupts and exceptions to supervisor mode.
|
||||
w_medeleg(0xffff);
|
||||
w_mideleg(0xffff);
|
||||
w_sie(r_sie() | SIE_SEIE | SIE_STIE | SIE_SSIE);
|
||||
|
||||
// ask for clock interrupts.
|
||||
//timerinit();
|
||||
|
||||
// keep each CPU's hartid in its tp register, for cpuid().
|
||||
int id = r_mhartid();
|
||||
w_tp(id);
|
||||
|
||||
// switch to supervisor mode and jump to main().
|
||||
asm volatile("mret");
|
||||
}
|
||||
|
||||
// set up to receive timer interrupts in machine mode,
|
||||
// which arrive at timervec in kernelvec.S,
|
||||
// which turns them into software interrupts for
|
||||
// devintr() in trap.c.
|
||||
void
|
||||
timerinit()
|
||||
{
|
||||
// each CPU has a separate source of timer interrupts.
|
||||
int id = r_mhartid();
|
||||
|
||||
// ask the CLINT for a timer interrupt.
|
||||
int interval = 1000000; // cycles; about 1/10th second in qemu.
|
||||
*(uint64*)CLINT_MTIMECMP(id) = *(uint64*)CLINT_MTIME + interval;
|
||||
|
||||
// prepare information in scratch[] for timervec.
|
||||
// scratch[0..3] : space for timervec to save registers.
|
||||
// scratch[4] : address of CLINT MTIMECMP register.
|
||||
// scratch[5] : desired interval (in cycles) between timer interrupts.
|
||||
uint64 *scratch = &mscratch0[32 * id];
|
||||
scratch[4] = CLINT_MTIMECMP(id);
|
||||
scratch[5] = interval;
|
||||
w_mscratch((uint64)scratch);
|
||||
|
||||
// set the machine-mode trap handler.
|
||||
w_mtvec((uint64)timervec);
|
||||
|
||||
// enable machine-mode interrupts.
|
||||
w_mstatus(r_mstatus() | MSTATUS_MIE);
|
||||
|
||||
// enable machine-mode timer interrupts.
|
||||
w_mie(r_mie() | MIE_MTIE);
|
||||
}
|
|
@ -15,7 +15,9 @@ void timerinit() {
|
|||
// enable supervisor-mode timer interrupts.
|
||||
w_sie(r_sie() | SIE_STIE);
|
||||
set_next_timeout();
|
||||
#ifdef DEBUG
|
||||
printf("timerinit\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -23,7 +23,9 @@ void
|
|||
trapinit(void)
|
||||
{
|
||||
initlock(&tickslock, "time");
|
||||
#ifdef DEBUG
|
||||
printf("trapinit\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
// set up to take exceptions and traps while in the kernel.
|
||||
|
@ -33,7 +35,9 @@ trapinithart(void)
|
|||
w_stvec((uint64)kernelvec);
|
||||
w_sstatus(r_sstatus() | SSTATUS_SIE);
|
||||
w_sie(r_sie() | SIE_SEIE | SIE_SSIE);
|
||||
#ifdef DEBUG
|
||||
printf("trapinithart\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -240,6 +244,7 @@ supervisor_external_handler() {
|
|||
int irq = *(uint32*)(PLIC + 0x04);
|
||||
if(irq == UARTHS_IRQ) {
|
||||
// UARTHS
|
||||
printf("[supervisor_external_handler]\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -276,5 +281,7 @@ void device_init(unsigned long pa, uint64 hartid) {
|
|||
*((uint32*)0x0c000028) = 0x7;
|
||||
*((uint32*)0x0c201000) = 0x0;
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
printf("device init\n");
|
||||
#endif
|
||||
}
|
|
@ -111,7 +111,9 @@ virtio_disk_init(void)
|
|||
disk.free[i] = 1;
|
||||
|
||||
// plic.c and trap.c arrange for interrupts from VIRTIO0_IRQ.
|
||||
#ifdef DEBUG
|
||||
printf("virtio_disk_init\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
// find a free descriptor, mark it non-free, return its index.
|
||||
|
|
|
@ -75,7 +75,9 @@ kvminit()
|
|||
kvmmap(TRAMPOLINE, (uint64)trampoline, PGSIZE, PTE_R | PTE_X);
|
||||
// kvmmap(TRAMPOLINE, (uint64)trampoline, PGSIZE, PTE_R | PTE_X);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("kvminit\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Switch h/w page table register to the kernel's page table,
|
||||
|
@ -86,7 +88,9 @@ kvminithart()
|
|||
w_satp(MAKE_SATP(kernel_pagetable));
|
||||
// reg_info();
|
||||
sfence_vma();
|
||||
#ifdef DEBUG
|
||||
printf("kvminithart\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Return the address of the PTE in page table pagetable
|
||||
|
|
307
mkfs/mkfs.c
307
mkfs/mkfs.c
|
@ -1,307 +0,0 @@
|
|||
// Copyright (c) 2006-2019 Frans Kaashoek, Robert Morris, Russ Cox,
|
||||
// Massachusetts Institute of Technology
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define stat xv6_stat // avoid clash with host struct stat
|
||||
#include "kernel/include/types.h"
|
||||
#include "kernel/include/fs.h"
|
||||
#include "kernel/include/stat.h"
|
||||
#include "kernel/include/param.h"
|
||||
|
||||
#ifndef static_assert
|
||||
#define static_assert(a, b) do { switch (0) case 0: case (a): ; } while (0)
|
||||
#endif
|
||||
|
||||
#define NINODES 200
|
||||
|
||||
// Disk layout:
|
||||
// [ boot block | sb block | log | inode blocks | free bit map | data blocks ]
|
||||
|
||||
int nbitmap = FSSIZE/(BSIZE*8) + 1;
|
||||
int ninodeblocks = NINODES / IPB + 1;
|
||||
int nlog = LOGSIZE;
|
||||
int nmeta; // Number of meta blocks (boot, sb, nlog, inode, bitmap)
|
||||
int nblocks; // Number of data blocks
|
||||
|
||||
int fsfd;
|
||||
struct superblock sb;
|
||||
char zeroes[BSIZE];
|
||||
uint freeinode = 1;
|
||||
uint freeblock;
|
||||
|
||||
|
||||
void balloc(int);
|
||||
void wsect(uint, void*);
|
||||
void winode(uint, struct dinode*);
|
||||
void rinode(uint inum, struct dinode *ip);
|
||||
void rsect(uint sec, void *buf);
|
||||
uint ialloc(ushort type);
|
||||
void iappend(uint inum, void *p, int n);
|
||||
|
||||
// convert to intel byte order
|
||||
ushort
|
||||
xshort(ushort x)
|
||||
{
|
||||
ushort y;
|
||||
uchar *a = (uchar*)&y;
|
||||
a[0] = x;
|
||||
a[1] = x >> 8;
|
||||
return y;
|
||||
}
|
||||
|
||||
uint
|
||||
xint(uint x)
|
||||
{
|
||||
uint y;
|
||||
uchar *a = (uchar*)&y;
|
||||
a[0] = x;
|
||||
a[1] = x >> 8;
|
||||
a[2] = x >> 16;
|
||||
a[3] = x >> 24;
|
||||
return y;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i, cc, fd;
|
||||
uint rootino, inum, off;
|
||||
struct dirent de;
|
||||
char buf[BSIZE];
|
||||
struct dinode din;
|
||||
|
||||
|
||||
static_assert(sizeof(int) == 4, "Integers must be 4 bytes!");
|
||||
|
||||
if(argc < 2){
|
||||
fprintf(stderr, "Usage: mkfs fs.img files...\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
assert((BSIZE % sizeof(struct dinode)) == 0);
|
||||
assert((BSIZE % sizeof(struct dirent)) == 0);
|
||||
|
||||
fsfd = open(argv[1], O_RDWR|O_CREAT|O_TRUNC, 0666);
|
||||
if(fsfd < 0){
|
||||
perror(argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// 1 fs block = 1 disk sector
|
||||
nmeta = 2 + nlog + ninodeblocks + nbitmap;
|
||||
nblocks = FSSIZE - nmeta;
|
||||
|
||||
sb.magic = FSMAGIC;
|
||||
sb.size = xint(FSSIZE);
|
||||
sb.nblocks = xint(nblocks);
|
||||
sb.ninodes = xint(NINODES);
|
||||
sb.nlog = xint(nlog);
|
||||
sb.logstart = xint(2);
|
||||
sb.inodestart = xint(2+nlog);
|
||||
sb.bmapstart = xint(2+nlog+ninodeblocks);
|
||||
|
||||
printf("nmeta %d (boot, super, log blocks %u inode blocks %u, bitmap blocks %u) blocks %d total %d\n",
|
||||
nmeta, nlog, ninodeblocks, nbitmap, nblocks, FSSIZE);
|
||||
|
||||
freeblock = nmeta; // the first free block that we can allocate
|
||||
|
||||
for(i = 0; i < FSSIZE; i++)
|
||||
wsect(i, zeroes);
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
memmove(buf, &sb, sizeof(sb));
|
||||
wsect(1, buf);
|
||||
|
||||
rootino = ialloc(T_DIR);
|
||||
assert(rootino == ROOTINO);
|
||||
|
||||
bzero(&de, sizeof(de));
|
||||
de.inum = xshort(rootino);
|
||||
strcpy(de.name, ".");
|
||||
iappend(rootino, &de, sizeof(de));
|
||||
|
||||
bzero(&de, sizeof(de));
|
||||
de.inum = xshort(rootino);
|
||||
strcpy(de.name, "..");
|
||||
iappend(rootino, &de, sizeof(de));
|
||||
|
||||
for(i = 2; i < argc; i++){
|
||||
// get rid of "user/"
|
||||
char *shortname;
|
||||
if(strncmp(argv[i], "xv6-user/", 9) == 0)
|
||||
shortname = argv[i] + 9;
|
||||
else
|
||||
shortname = argv[i];
|
||||
|
||||
assert(index(shortname, '/') == 0);
|
||||
|
||||
if((fd = open(argv[i], 0)) < 0){
|
||||
perror(argv[i]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Skip leading _ in name when writing to file system.
|
||||
// The binaries are named _rm, _cat, etc. to keep the
|
||||
// build operating system from trying to execute them
|
||||
// in place of system binaries like rm and cat.
|
||||
if(shortname[0] == '_')
|
||||
shortname += 1;
|
||||
|
||||
inum = ialloc(T_FILE);
|
||||
|
||||
bzero(&de, sizeof(de));
|
||||
de.inum = xshort(inum);
|
||||
strncpy(de.name, shortname, DIRSIZ);
|
||||
iappend(rootino, &de, sizeof(de));
|
||||
|
||||
while((cc = read(fd, buf, sizeof(buf))) > 0)
|
||||
iappend(inum, buf, cc);
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
// fix size of root inode dir
|
||||
rinode(rootino, &din);
|
||||
off = xint(din.size);
|
||||
off = ((off/BSIZE) + 1) * BSIZE;
|
||||
din.size = xint(off);
|
||||
winode(rootino, &din);
|
||||
|
||||
balloc(freeblock);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
wsect(uint sec, void *buf)
|
||||
{
|
||||
if(lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE){
|
||||
perror("lseek");
|
||||
exit(1);
|
||||
}
|
||||
if(write(fsfd, buf, BSIZE) != BSIZE){
|
||||
perror("write");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
winode(uint inum, struct dinode *ip)
|
||||
{
|
||||
char buf[BSIZE];
|
||||
uint bn;
|
||||
struct dinode *dip;
|
||||
|
||||
bn = IBLOCK(inum, sb);
|
||||
rsect(bn, buf);
|
||||
dip = ((struct dinode*)buf) + (inum % IPB);
|
||||
*dip = *ip;
|
||||
wsect(bn, buf);
|
||||
}
|
||||
|
||||
void
|
||||
rinode(uint inum, struct dinode *ip)
|
||||
{
|
||||
char buf[BSIZE];
|
||||
uint bn;
|
||||
struct dinode *dip;
|
||||
|
||||
bn = IBLOCK(inum, sb);
|
||||
rsect(bn, buf);
|
||||
dip = ((struct dinode*)buf) + (inum % IPB);
|
||||
*ip = *dip;
|
||||
}
|
||||
|
||||
void
|
||||
rsect(uint sec, void *buf)
|
||||
{
|
||||
if(lseek(fsfd, sec * BSIZE, 0) != sec * BSIZE){
|
||||
perror("lseek");
|
||||
exit(1);
|
||||
}
|
||||
if(read(fsfd, buf, BSIZE) != BSIZE){
|
||||
perror("read");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uint
|
||||
ialloc(ushort type)
|
||||
{
|
||||
uint inum = freeinode++;
|
||||
struct dinode din;
|
||||
|
||||
bzero(&din, sizeof(din));
|
||||
din.type = xshort(type);
|
||||
din.nlink = xshort(1);
|
||||
din.size = xint(0);
|
||||
winode(inum, &din);
|
||||
return inum;
|
||||
}
|
||||
|
||||
void
|
||||
balloc(int used)
|
||||
{
|
||||
uchar buf[BSIZE];
|
||||
int i;
|
||||
|
||||
printf("balloc: first %d blocks have been allocated\n", used);
|
||||
assert(used < BSIZE*8);
|
||||
bzero(buf, BSIZE);
|
||||
for(i = 0; i < used; i++){
|
||||
buf[i/8] = buf[i/8] | (0x1 << (i%8));
|
||||
}
|
||||
printf("balloc: write bitmap block at sector %d\n", sb.bmapstart);
|
||||
wsect(sb.bmapstart, buf);
|
||||
}
|
||||
|
||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
void
|
||||
iappend(uint inum, void *xp, int n)
|
||||
{
|
||||
char *p = (char*)xp;
|
||||
uint fbn, off, n1;
|
||||
struct dinode din;
|
||||
char buf[BSIZE];
|
||||
uint indirect[NINDIRECT];
|
||||
uint x;
|
||||
|
||||
rinode(inum, &din);
|
||||
off = xint(din.size);
|
||||
// printf("append inum %d at off %d sz %d\n", inum, off, n);
|
||||
while(n > 0){
|
||||
fbn = off / BSIZE;
|
||||
assert(fbn < MAXFILE);
|
||||
if(fbn < NDIRECT){
|
||||
if(xint(din.addrs[fbn]) == 0){
|
||||
din.addrs[fbn] = xint(freeblock++);
|
||||
}
|
||||
x = xint(din.addrs[fbn]);
|
||||
} else {
|
||||
if(xint(din.addrs[NDIRECT]) == 0){
|
||||
din.addrs[NDIRECT] = xint(freeblock++);
|
||||
}
|
||||
rsect(xint(din.addrs[NDIRECT]), (char*)indirect);
|
||||
if(indirect[fbn - NDIRECT] == 0){
|
||||
indirect[fbn - NDIRECT] = xint(freeblock++);
|
||||
wsect(xint(din.addrs[NDIRECT]), (char*)indirect);
|
||||
}
|
||||
x = xint(indirect[fbn-NDIRECT]);
|
||||
}
|
||||
n1 = min(n, (fbn + 1) * BSIZE - off);
|
||||
rsect(x, buf);
|
||||
bcopy(p, buf + off - (fbn * BSIZE), n1);
|
||||
wsect(x, buf);
|
||||
n -= n1;
|
||||
off += n1;
|
||||
p += n1;
|
||||
}
|
||||
din.size = xint(off);
|
||||
winode(inum, &din);
|
||||
}
|
|
@ -62,11 +62,6 @@ int fork1(void); // Fork but panics on failure.
|
|||
void panic(char*);
|
||||
struct cmd *parsecmd(char*);
|
||||
|
||||
#ifndef QEMU
|
||||
char platform[] = "k210";
|
||||
#else
|
||||
char platform[] = "qemu";
|
||||
#endif
|
||||
char mycwd[128];
|
||||
|
||||
int
|
||||
|
@ -254,7 +249,7 @@ runcmd(struct cmd *cmd)
|
|||
int
|
||||
getcmd(char *buf, int nbuf)
|
||||
{
|
||||
fprintf(2, "-> xv6@%s: %s $ ", platform, mycwd);
|
||||
fprintf(2, "-> %s $ ", mycwd);
|
||||
memset(buf, 0, nbuf);
|
||||
gets(buf, nbuf);
|
||||
if(buf[0] == 0) // EOF
|
||||
|
|
Loading…
Reference in New Issue