Giter Site home page Giter Site logo

xv6-riscv's Introduction

xv6 is a re-implementation of Dennis Ritchie's and Ken Thompson's Unix
Version 6 (v6).  xv6 loosely follows the structure and style of v6,
but is implemented for a modern RISC-V multiprocessor using ANSI C.

ACKNOWLEDGMENTS

xv6 is inspired by John Lions's Commentary on UNIX 6th Edition (Peer
to Peer Communications; ISBN: 1-57398-013-7; 1st edition (June 14,
2000)).  See also https://pdos.csail.mit.edu/6.1810/, which provides
pointers to on-line resources for v6.

The following people have made contributions: Russ Cox (context switching,
locking), Cliff Frey (MP), Xiao Yu (MP), Nickolai Zeldovich, and Austin
Clements.

We are also grateful for the bug reports and patches contributed by
Takahiro Aoyagi, Silas Boyd-Wickizer, Anton Burtsev, carlclone, Ian
Chen, Dan Cross, Cody Cutler, Mike CAT, Tej Chajed, Asami Doi,
eyalz800, Nelson Elhage, Saar Ettinger, Alice Ferrazzi, Nathaniel
Filardo, flespark, Peter Froehlich, Yakir Goaron, Shivam Handa, Matt
Harvey, Bryan Henry, jaichenhengjie, Jim Huang, Matúš Jókay, John
Jolly, Alexander Kapshuk, Anders Kaseorg, kehao95, Wolfgang Keller,
Jungwoo Kim, Jonathan Kimmitt, Eddie Kohler, Vadim Kolontsov, Austin
Liew, l0stman, Pavan Maddamsetti, Imbar Marinescu, Yandong Mao, Matan
Shabtay, Hitoshi Mitake, Carmi Merimovich, Mark Morrissey, mtasm, Joel
Nider, Hayato Ohhashi, OptimisticSide, Harry Porter, Greg Price, Jude
Rich, segfault, Ayan Shafqat, Eldar Sehayek, Yongming Shen, Fumiya
Shigemitsu, Cam Tenny, tyfkda, Warren Toomey, Stephen Tu, Rafael Ubal,
Amane Uehara, Pablo Ventura, Xi Wang, WaheedHafez, Keiichi Watanabe,
Nicolas Wolovick, wxdao, Grant Wu, Jindong Zhang, Icenowy Zheng,
ZhUyU1997, and Zou Chang Wei.


The code in the files that constitute xv6 is
Copyright 2006-2022 Frans Kaashoek, Robert Morris, and Russ Cox.

ERROR REPORTS

Please send errors and suggestions to Frans Kaashoek and Robert Morris
(kaashoek,[email protected]).  The main purpose of xv6 is as a teaching
operating system for MIT's 6.1810, so we are more interested in
simplifications and clarifications than new features.

BUILDING AND RUNNING XV6

You will need a RISC-V "newlib" tool chain from
https://github.com/riscv/riscv-gnu-toolchain, and qemu compiled for
riscv64-softmmu.  Once they are installed, and in your shell
search path, you can run "make qemu".

xv6-riscv's People

Contributors

4ge32 avatar aclements avatar amane-uehara avatar anishathalye avatar d0iasm avatar flespark avatar jjolly avatar jrrk2 avatar k-mrm avatar kaashoek avatar kehao95 avatar kimjungwow avatar kolontsov avatar l0stman avatar matt-har-vey avatar mikecat avatar olf0 avatar phf avatar pmaddams avatar rapidclock avatar ravss avatar rsc avatar rui314 avatar saarett avatar takahirox avatar tchajed avatar waheedhafez avatar xiw avatar zeldovich avatar zhuyu1997 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

xv6-riscv's Issues

mret Exception : Illegal instruction

qemu-system-riscv64 --version
QEMU emulator version 6.1.0
Copyright (c) 2003-2021 Fabrice Bellard and the QEMU Project developers

make kernel/kernel
qemu-system-riscv64 -M virt -kernel kernel/kernel -bios none -serial stdio -display none

there is no output.through my effort, I find mret exception happens

The issue turned out to be RISC-V's Physical Memory Protection (PMP). QEMU will raise an illegal instruction exception when executing an MRET instruction if no PMP rules have been defined. Adding a PMP entry resolved the issue.

so ,I add setup_pmp function in kernel/start.c

void setup_pmp(void)
{
  // Set up a PMP to permit access to all of memory.
  // Ignore the illegal-instruction trap if PMPs aren't supported.
  unsigned long pmpc = PMP_NAPOT | PMP_R | PMP_W | PMP_X;
  asm volatile ("la t0, 1f\n\t"
                "csrrw t0, mtvec, t0\n\t"
                "csrw pmpaddr0, %1\n\t"
                "csrw pmpcfg0, %0\n\t"
                ".align 2\n\t"
                "1: csrw mtvec, t0"
                : : "r" (pmpc), "r" (-1UL) : "t0");
}

// entry.S jumps here in machine mode on stack0.
void
start()
{
  setup_pmp();
........
}

Lab pgtbl: Cannot read answers-pgtbl.txt

I run make grade, but it said cannot read answers-pgtbl.txt, where is this file?

pte printout: OK (2.1s)
== Test answers-pgtbl.txt == answers-pgtbl.txt: FAIL
Cannot read answers-pgtbl.txt

riscv64-unknown-elf-gdb: E14, cannot fetch $stvec

I'm learning 6.S081 myself, and when I read the Isolation & system call entry/exit, using riscv64-unknown-elf-gdb will receive an error:

Could not fetch register "stvec"; remote failure reply 'E14'

My gdb version is:

riscv64-unknown-elf-gdb --version
Python Exception <type 'exceptions.ImportError'> No module named gdb: 
riscv64-unknown-elf-gdb: warning: 
Could not load the Python gdb module from `/usr/local/Cellar/riscv-gnu-toolchain/gnu/share/gdb/python'.
Limited Python support is available from the _gdb module.
Suggest passing --data-directory=/path/to/gdb/data-directory.

GNU gdb (GDB) 8.3.0.20190516-git
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

record every instruction

Hi
I want to record every instructions, so i add these to qemu startup "-d cpu,nochain -D cpu.log -singlestep", but i never see the command prompt come up. Please help
Thanks
Peter

Process locks for killed

struct proc::killed is listed among the variables for which struct proc::lock should be held when used. However, this lock is almost invariably not held when killed is read, and it's also not held when written by usertrap.

As far as I can see, the xv6 book does not discuss this issue. I was wondering whether this is a deliberate choice or an oversight.

I believe, with low confidence, that this is not an issue. As far as I can see, it could only ever be a problem if killed is read as 1 while it is actually 0. Since the value of killed is monotonic during a process' lifetime (it only changes from 0 to 1), this seems impossible to happen even if writes to it are not atomic.

Is this assessment correct? If so, I think it would be nice to clarify this both in the source code and in the book.

printf and fprintf without va_end

void
fprintf(int fd, const char *fmt, ...)
{
  va_list ap;

  va_start(ap, fmt);
  vprintf(fd, fmt, ap);
  // va_end(ap);
}

void
printf(const char *fmt, ...)
{
  va_list ap;

  va_start(ap, fmt);
  vprintf(1, fmt, ap);
  // va_end(ap);
}

Qemu hangs after execute instruction "mret" in start

I encounter following issued on my computer, and I have no clue how to solve it or what the problem is.
Here is my environment:

  • Linux kernel: 5.12.12-arch1-1
  • Compiler: riscv64-unknown-elf-gcc (Arch User Repository) 9.2.0
  • qemu-system-riscv64: QEMU emulator version 6.0.0
  • gdb: GNU gdb (GDB) 10.2

The problem is that, my breakpoint does not work in main function. I can step to the line asm volatile("mret"); in function start.
However, the debugger just hangs after this instruction, it does not hit my breakpoint set on main function. I can send interrupt by press Ctrl+C, it seems that sometimes it will stop in function timervec.
I think the timer interrupt is worked as expected.
Have no clue what the problem is and how to fix it. Does anyone face same issue?

riscv64-unknown-elf-gcc: error: riscv64: No such file or directory

Hi, I have trouble to execute make qemu cmd:

vimer@host:~/src/xv6-riscv$ make qemu
riscv64-unknown-elf-gcc -Wall -Werror -O -fno-omit-frame-pointer -ggdb -MD -mcmodel=medany -ffreestanding -fno-common -nostdlib -mno-relax -I. -fno-stack-protector -fno-pie -no-pie riscv64 -c -o kernel/start.o kernel/start.c
riscv64-unknown-elf-gcc: error: riscv64: No such file or directory
<内置>: recipe for target 'kernel/start.o' failed
make: *** [kernel/start.o] Error 1

failed to build some targets

=========================================
My riscv64 gcc and qemu as below:
vimer@host:~/src/xv6-riscv$ riscv64-unknown-elf-gcc --version
riscv64-unknown-elf-gcc (GCC) 10.2.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

vimer@host:~/src/xv6-riscv$ qemu-system-riscv64 --version
QEMU emulator version 5.1.0
Copyright (c) 2003-2020 Fabrice Bellard and the QEMU Project developers

A bug in the FS logging layer of xv6?

Hello, I'm recently studying the principle of xv6 and benefits a lot from the explicit comments and the textbook. I think that there may be a bug in the logging layer in the file system. I'll describe the details below:

This is the code of install_trans() in /kernel/log.c :

static void
install_trans(void)
{
  int tail;

  for (tail = 0; tail < log.lh.n; tail++) {
    struct buf *lbuf = bread(log.dev, log.start+tail+1); // read log block
    struct buf *dbuf = bread(log.dev, log.lh.block[tail]); // read dst
    memmove(dbuf->data, lbuf->data, BSIZE);  // copy block to dst
    bwrite(dbuf);  // write dst to disk
    bunpin(dbuf);
    brelse(lbuf);
    brelse(dbuf);
  }
}

the line bunpin(dbuf) unpins dbuf in the buffer cache so that this block can be evicted out of the memory after brelse(dbuf). The code works correctly if everything goes normally: there is a bpin() in log_write() which pins the block in the buffer cache by incrementing its reference count and the bunpin() here decrements it.

However, if a crash happened during the installation of a transaction, after xv6 reboots, it would call recover_from_log() in initlog() and call install_trans to write logging blocks into their home blocks. At this moment, there isn't a bpin() before, so the bunpin() here will decrement the reference count to zero and in brelse() the reference count will experience an underflow and become UINT_MAX since the refcnt is a uint type variable. As a result, the block will stay in the buffer cache "forever".

We can expose this bug by adding two lines in xv6:

  • We emulate a crash by adding a panic() in install_trans() like this:

        brelse(dbuf);
      }
      
    +  if (log.lh.n != 0) panic("crash");
    }

    Here the condition log.lh.n != 0 ensures that the panic() won't be triggered during the recover procedure.

  • We add an assertion in brelse():

      acquire(&bcache.lock);
    + if (b->refcnt == 0) panic("bug");
      b->refcnt--;
      if (b->refcnt == 0) {
     

    Before decrementing the reference count, b->refcnt >= 1 should always hold.

After we fire up xv6 for the first time, we'll encounter a "crash", and after rebooting, xv6 will panic at panic("bug"). I made a disk image, fs-bug.img, which records a crashed xv6 using the first step. If we load this image, we'll directly get a buggy scene (and can be detected by the assertion in brelse()). The disk image is available here.

A possible solution for this problem is to add a bpin() in read_head() so that the bunpin() during the recover procedure will have corresponding bpin().

I hope that my suggestions will be helpful. Welcome for further discussions, thanks!

qemu hang, command prompt never come up

Hi
qemu hang, command prompt never come up. Any hints?

qemu-system-riscv64 -machine virt -bios none -kernel kernel/kernel -m 128M -smp 3 -nographic -drive file=fs.img,if=none,format=raw,id=x0 -device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0 --trace events=/tmp/events

thanks
Peter

GDB can't step into ecall.

The output is as below, and ecall's address in sh.asm is 0xdec.

(gdb) show step-mode
Mode of the step operation is off.
(gdb) set step-mode on
(gdb) b *0xdec
Breakpoint 1 at 0xdec
(gdb) c
Continuing.

Thread 1 hit Breakpoint 1, 0x0000000000000dec in ?? ()
=> 0x0000000000000dec:  73 00 00 00     ecall
(gdb) delete 1
(gdb) print $pc
$1 = (void (*)()) 0xdec
(gdb) x/2c $a1
0x3e9f: 36 '$'  48 '0'
(gdb) si
0x0000000000000df0 in ?? ()
=> 0x0000000000000df0:  82 80   ret
(gdb) print $pc
$2 = (void (*)()) 0xdf0
(gdb)

My system is Ubuntu 20.04 in WSL2, and GDB is gdb-multiarch.

Package: gdb-multiarch
Version: 9.2-0ubuntu1~20.04
Priority: optional
Section: universe/devel
Source: gdb
Origin: Ubuntu
Maintainer: Ubuntu Developers <[email protected]>
Original-Maintainer: Héctor Orón Martínez <[email protected]>
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Installed-Size: 15.2 MB
Depends: gdb (= 9.2-0ubuntu1~20.04), libbabeltrace1 (>= 1.5.4), libc6 (>= 2.29), libexpat1 (>= 2.0.1), libgcc-s1 (>= 3.4), liblzma5 (>= 5.1.1alpha+20110809), libmpfr6 (>= 3.1.3), libncursesw6 (>= 6), libpython3.8 (>= 3.8.2), libreadline8 (>= 8), libstdc++6 (>= 7), libtinfo6 (>= 6), zlib1g (>= 1:1.2.0)
Homepage: http://www.gnu.org/s/gdb/
Download-Size: 3794 kB
APT-Manual-Installed: yes
APT-Sources: http://archive.ubuntu.com/ubuntu focal-updates/universe amd64 Packages
Description: GNU Debugger (with support for multiple architectures)
 GDB is a source-level debugger, capable of breaking programs at
 any specific line, displaying variable values, and determining
 where errors occurred. Currently, gdb supports C, C++, D,
 Objective-C, Fortran, Java, OpenCL C, Pascal, assembly, Modula-2,
 Go, and Ada. A must-have for any serious programmer.
 .
 This package contains a version of GDB which supports multiple
 target architectures.

can not `make grade`

in my zsh, I want to check code

$ make grade
make: *** No rule to make target `grade'. Stop.

should I modify Makefile?

and I can't find the python srcipt grade-lab-util sleep

Keeping xv6-public up to date

Will you be keeping the x86 version of xv6 up to date with changes that also apply to it? I.e. changes that have nothing to do with the underlying architecture, but are instead operating system specific (for example like fixing a bug in the scheduling algorithm used, or resolving a race condition).

qemu start at 0x1000

Hi
qemu start at 0x1000, and where is the source code of memory location 0x1000?
image

thanks
Peter

Stuck when compiling on m1 chip mac os

I use brew install RISC-V toolchain on m1 mac os, and make qemu

it prints:

qemu-system-riscv64 -machine virt -bios none -kernel kernel/kernel -m 128M -smp 3 -nographic -drive file=fs.img,if=none,format=raw,id=x0 -device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0

then seems like stuck.

Confused about the system call number

In kernel/syscall.c, if checks num > 0, it seems that in xv6, the first system call number is 1,
but how can we call syscalls[0] (fork)?

void
syscall(void)
{
  int num;
  struct proc *p = myproc();

  num = p->trapframe->a7;
  if(num > 0 && num < NELEM(syscalls) && syscalls[num]) {
    p->trapframe->a0 = syscalls[num]();
    if ((1 << num) & p->trace_mask)
      printf("%d: syscall %s -> %d\n", p->pid, sysname[num-1], p->trapframe->a0);
  } else {
    printf("%d %s: unknown sys call %d\n",
            p->pid, p->name, num);
    p->trapframe->a0 = -1;
  }
}

Lab4 why print "test0 pass" after invoke handler

After n ticks of cpu time,I set epc's value to the address of handler,so when it return to the user space,it will run handler.
But why it 'll print "test0 pass" after invoke handler ? I think it should just print alarm because sigreturn just return 0,but it still print "test0 pass". which one set pc's value to the value before being interrupted by the clock ?
the output is
image
I think the output should be
image
handler return and process will finish

There may have a bug in printf.c.

the error function is :

printf.c -> void printf(char *fmt, ...)

i find printf(char *fmt, ...) function may drop the character '%' in the end of any string.
Such as printf("i can print last %\n") can work as expected , but printf("i can print last %") can't.
The error behavior is reason for
c = fmt[++i] & 0xff; if (c == 0) break; .
I think it can be changed as

if (c == 0) {
// when string is '\0' , this loop break at 'for' . So it is security using i - 1 in here.
if (fmt[i - 1] == '%') consputc('%');
break;
}

Adding -ggdb to ASFLAGS?

Though has little impact to TUI, generating debug info for assembly files would make IDE debugging less painful.

mret Exception : Illegal instruction

qemu-system-riscv64 --version
QEMU emulator version 6.1.0
Copyright (c) 2003-2021 Fabrice Bellard and the QEMU Project developers

make kernel/kernel
qemu-system-riscv64 -M virt -kernel kernel/kernel -bios none -serial stdio -display none

there is no output.through my effort, I find mret exception happens

The issue turned out to be RISC-V's Physical Memory Protection (PMP). QEMU will raise an illegal instruction exception when executing an MRET instruction if no PMP rules have been defined. Adding a PMP entry resolved the issue.

so ,I add setup_pmp function in kernel/start.c

`
void setup_pmp(void)
{
// Set up a PMP to permit access to all of memory.
// Ignore the illegal-instruction trap if PMPs aren't supported.
unsigned long pmpc = PMP_NAPOT | PMP_R | PMP_W | PMP_X;
asm volatile ("la t0, 1f\n\t"
"csrrw t0, mtvec, t0\n\t"
"csrw pmpaddr0, %1\n\t"
"csrw pmpcfg0, %0\n\t"
".align 2\n\t"
"1: csrw mtvec, t0"
: : "r" (pmpc), "r" (-1UL) : "t0");
}

// entry.S jumps here in machine mode on stack0.
void
start()
{
setup_pmp();
........
}

`

mret Exception : Illegal instruction

qemu-system-riscv64 --version
QEMU emulator version 6.1.0
Copyright (c) 2003-2021 Fabrice Bellard and the QEMU Project developers

make kernel/kernel
qemu-system-riscv64 -M virt -kernel kernel/kernel -bios none -serial stdio -display none

there is no output.through my effort, I find mret exception happens

The issue turned out to be RISC-V's Physical Memory Protection (PMP). QEMU will raise an illegal instruction exception when executing an MRET instruction if no PMP rules have been defined. Adding a PMP entry resolved the issue.

so ,I add setup_pmp function in kernel/start.c

`
void setup_pmp(void)
{
// Set up a PMP to permit access to all of memory.
// Ignore the illegal-instruction trap if PMPs aren't supported.
unsigned long pmpc = PMP_NAPOT | PMP_R | PMP_W | PMP_X;
asm volatile ("la t0, 1f\n\t"
"csrrw t0, mtvec, t0\n\t"
"csrw pmpaddr0, %1\n\t"
"csrw pmpcfg0, %0\n\t"
".align 2\n\t"
"1: csrw mtvec, t0"
: : "r" (pmpc), "r" (-1UL) : "t0");
}

// entry.S jumps here in machine mode on stack0.
void
start()
{
setup_pmp();
........
}

`

Should kinit initialize kmem.freelist?

In kernel/kalloc.c, I found that kmem.freelist is not initialized. As a general approach, we set NULL to be the end of a list. Why does kmem.freelist not be initialized?

fix instruction synchronization bug on a real RISC-V processor

@kaashoek Hi, I think the bug reported by #5 is still a problem. I am trying to explain in detail.

This bug is related to instruction cache (ICache) in hardware.

  1. Process A loads its code to a new physical page P0 in xv6-riscv/kernel/exec.c. We assume that P0 is not in the ICache before loading the code. Note that from the aspect of hardware, loading code is similar to an invocation of memcpy(). This means that loading code does not cause such code to enter ICache, since it only involves ordinary load and store instructions. For a processor with data cache (DCache), the code may be even located in DCache.
  2. A executes code. Since P0 is not in the ICache, this will cause ICache miss. ICache will get the correct code from DCache or from memory.
  3. A exits, and P0 is reclaimed.
  4. Now a new process B is loaded, and B get exactly the same physical page P0 to load its code. Remember that the loaded code is not in the ICache after loading.
  5. B executes code. Now disaster happens. When B is going to access ICache, it may get a hit since the code of A is still in the ICache! This causes B to execute wrong code!

The key to avoid such disaster is to update ICache every time new code is loaded. Such update can be performed in either hardware or software.

  • For the hardware method, hardware will examine the address of every store instructions to see whether ICache is also holding the same cache block. If it is the case, ICache will invalidate such block it holds. This guarantees that ICache will not get a hit next time it access the same address. x86 is such case.
  • For the software method, we should execute some special instructions to explicitly update the state of ICache. This operation is also called synchronization according to the RISC-V manual. In RISC-V, there are three special instructions belong to this type.
    • SFENCE.VMA. This instruction is used to update the state of hardware components related to virtual memory, such as TLB. Note that SFENCE.VMA is NOT guaranteed to update ICache. It depends on the hardware implementation.
      • If the ICache is implemented as PIPT (physically indexed, physically tagged), it is nothing to do with virtual memory and unnecessary to be updated under SFENCE.VMA.
      • Even though the ICache is implemented as VIPT (virtually indexed, physically tagged), it is still unnecessary to update ICache under SFENCE.VMA. This is because the index field of an address keeps the same after address translation.
      • But if the ICache is implemented as VIVT (virtually indexed, virtually tagged), it is necessary to update ICache under SFENCE.VMA. This is because the tag is from virtual address, and the mapping to the physical address may be changed after SFENCE.VMA.
    • FENCE. This instruction is used to synchronize the visibility of store instructions before the FENCE itself. Every load instructions on other CPUs after FENCE should see the result of store instructions before FENCE. Note that FENCE is defined to only guarantee the visibility to load instructions. FENCE does NOT guarantee the visibility to instruction fetches. Therefore, executing FENCE will not guarantee to update ICache.
    • FENCE.I (different from FENCE). According to the RISC-V manual,
Currently, this instruction is the only standard mechanism to ensure that stores visible to a hart will also be visible to its instruction fetches.

Therefore, the solution to the bug above is FENCE.I. The discussion about memory barrier at the end of section 9.3 in the text book is about FENCE. This discussion is still irrelevant to such bug, since memory barrier is talking about ordinary load instructions, but not instruction fetches.

We encounter this bug when we are trying to run xv6 on a simple in-order RISC-V processor designed by undergraduates. There are some buffers and caches in the processor. The table below shows the behavior of the three instructions discussed above (F = flush, K = keep).

ICache DCache TLB BTB
SFENCE.VMA K K F F
FENCE K K K K
FENCE.I F K K F

Since TLB and BTB is indexed by virtual address, they should be flushed under SFENCE.VMA. ICache and DCache are simply implemented as PIPT, so they are not flushed under SFENCE.VMA. For FENCE.I, ICache and BTB will be flushed, since they are related to instruction. Note that the processor is in-order, the behavior required by FENCE is naturally satisfied. Therefore FENCE can be implemented as nop and does not flush anything. This processor can successfully boot Linux and Debian, but fails to run xv6 without applying the patch #5 to fix this bug.

The bug is not exposed in QEMU. This is because in QEMU, all buffers and caches related to instruction are virtually indexed. They will be flushed under SFENCE.VMA. xv6 will always execute SFENCE.VMA on context switch. At this time, the code cache (a key component to implement JIT) in QEMU will also be flushed. Compared to our simple RISC-V processor, the main difference is that there is a PIPT ICache in the processor, which is not affected by SFENCE.VMA and FENCE.

Welcome for further discussion. :)

Unable to run make qemu command

Successfully built the toolchain but failing to run make qemu command on Arch Linux

Output:
riscv64-unknown-elf-gcc -c -o kernel/entry.o kernel/entry.SAssembler messages: Fatal error: invalid -march= option: rv64imafdc' make: *** [: kernel/entry.o] Error 1`

Unable to run properly in MacBook m1

I download the necessary dependencies and type make qemu in xv6's directory, it seems some troubles happened:

qemu-system-riscv64 -machine virt -bios none -kernel kernel/kernel -m 128M -smp 3 -nographic -drive file=fs.img,if=none,format=raw,id=x0 -device virtio-blk-device,drive=x0,bus=virtio-mmio-bus.0
qemu-system-riscv64: qemu_mprotect__osdep: mprotect failed: Permission denied
qemu-system-riscv64: qemu_mprotect__osdep: mprotect failed: Permission denied
qemu-system-riscv64: qemu_mprotect__osdep: mprotect failed: Permission denied
qemu-system-riscv64: qemu_mprotect__osdep: mprotect failed: Permission denied
qemu-system-riscv64: qemu_mprotect__osdep: mprotect failed: Permission denied
qemu-system-riscv64: qemu_mprotect__osdep: mprotect failed: Permission denied
qemu-system-riscv64: qemu_mprotect__osdep: mprotect failed: Permission denied
qemu-system-riscv64: qemu_mprotect__osdep: mprotect failed: Permission denied
qemu-system-riscv64: qemu_mprotect__osdep: mprotect failed: Permission denied
qemu-system-riscv64: qemu_mprotect__osdep: mprotect failed: Permission denied
qemu-system-riscv64: qemu_mprotect__osdep: mprotect failed: Permission denied
qemu-system-riscv64: qemu_mprotect__osdep: mprotect failed: Permission denied
qemu-system-riscv64: qemu_mprotect__osdep: mprotect failed: Permission denied
qemu-system-riscv64: qemu_mprotect__osdep: mprotect failed: Permission denied
qemu-system-riscv64: qemu_mprotect__osdep: mprotect failed: Permission denied
qemu-system-riscv64: qemu_mprotect__osdep: mprotect failed: Permission denied
qemu-system-riscv64: qemu_mprotect__osdep: mprotect failed: Permission denied
qemu-system-riscv64: qemu_mprotect__osdep: mprotect failed: Permission denied
qemu-system-riscv64: qemu_mprotect__osdep: mprotect failed: Permission denied
qemu-system-riscv64: qemu_mprotect__osdep: mprotect failed: Permission denied
qemu-system-riscv64: qemu_mprotect__osdep: mprotect failed: Permission denied
qemu-system-riscv64: qemu_mprotect__osdep: mprotect failed: Permission denied
qemu-system-riscv64: qemu_mprotect__osdep: mprotect failed: Permission denied
qemu-system-riscv64: qemu_mprotect__osdep: mprotect failed: Permission denied

I don't know what does it means and how to solve it. But it seems I have to exit it by ctrl + A + x rather than ctrl + c, which indicates that the problem may come from qemu.

My device:

MacBook Pro m1,
macOS 11.4,
qemu 6.0,
riscv64-unknown-elf-gcc (GCC) 10.2.0

Linker can't find kernel entry symbol.

Hello, when compiling the kernel, the linker (riscv64-elf-ld) issues the following warning:

riscv64-elf-ld: warning: cannot find entry symbol _entry; defaulting to 0000000080000000

The linker can't find the _entry symbol, so it defaults to an address that just so happens, one can see from reading the comments in the file kernel/entry.S, to be the location of the _entry symbol. Everything works, but it's a bit of a kludge.

After troubleshooting, I found that _entry isn't exported as a global symbol. putting a .global _entry directive in kernel/entry.S fixes the problem and removes the linker warning.

Clean shutdown from shell prompt

We added a "halt" command to xv6 for the x86. I was wondering if anyone has done so for the riscv version. Here are our changes for x86.

sysproc.c:
#ifdef PDX_XV6
// shutdown QEMU
int
sys_halt(void)
{
do_shutdown(); // never returns
return 0;
}
#endif // PDX_XV6

console.c:
#ifdef PDX_XV6
void
do_shutdown()
{
cprintf("\nShutting down ...\n");
outw( 0x604, 0x0 | 0x2000); // signal QEMU to shutdown
return; // not reached
}
#endif // PDX_XV6

Else, I will track this down. We didn't add it to the official as it seemed that the authors were comfortable with just using c-a x. Is qemu mapped to the same range of addresses? I hope so.

[riscv64-unknown-elf-gdb] undefined command "tui"

➜ xv6-labs-2020 git:(syscall) riscv64-unknown-elf-gdb
GNU gdb (GDB) 9.1
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-pc-linux-gnu --target=riscv64-unknown-elf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
http://www.gnu.org/software/gdb/bugs/.
Find the GDB manual and other documentation resources online at:
http://www.gnu.org/software/gdb/documentation/.
For help, type "help".
Type "apropos word" to search for commands related to "word".
The target architecture is assumed to be riscv:rv64
warning: No executable has been specified and target does not support
determining executable automatically. Try using the "file" command.
0x0000000000001000 in ?? ()
(gdb) tui enable
Undefined command: "tui". Try "help".

Cannot build xv6 with LLVM

Hi, I'm using LLVM to build xv6 and when building it, I got this error:

clang -cc1as: fatal error: error in backend: unable to write nop sequence of 1 bytes

This is my make command

make TOOLPREFIX= CC="clang -target riscv64-elf" AS="clang -target riscv64-elf" LD="ld.lld" OBJCOPY="llvm-objcopy" OBJDUMP="llvm-objdump"

About qemu

I'd like to know what happens when I type make qemu in my terminal, and how to configure the qemu emulator to run the xv6 os.

Error flag of shell

It lies in line 391 of user/sh.c sh.c#L391

 case '+':  // >>
 cmd = redircmd(cmd, q, eq, O_WRONLY|O_CREATE, 1);
 break;

When the symbol is '>>', the flag should be O_APPEND | O_WRONLY | O_CREATE instead of O_WRONLY|O_CREATE.

XV6 signals clash with macOS signals

I'm trying to implement signals support on XV6-riscv version
And in order to d so I defined a sigaction struct and some signals macros like SIG_IGN.
The problem is that when I compile it using make clean qemu I got the following errors:

In file included from mkfs/mkfs.c:9:
./kernel/types.h:12:8: error: redefinition of 'sigaction'
struct sigaction {
       ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/signal.h:286:9: note: previous definition is here
struct  sigaction {
        ^
In file included from mkfs/mkfs.c:9:
./kernel/types.h:13:12: error: expected ')'
    void (*sa_handler) (int);
           ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/signal.h:295:38: note: expanded from macro 'sa_handler'
#define sa_handler      __sigaction_u.__sa_handler
                                     ^
./kernel/types.h:13:10: note: to match this '('
    void (*sa_handler) (int);
         ^
In file included from mkfs/mkfs.c:12:
./kernel/param.h:14:9: error: 'SIG_DFL' macro redefined [-Werror,-Wmacro-redefined]
#define SIG_DFL      0       // default signal handling
        ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/signal.h:131:9: note: previous definition is here
#define SIG_DFL         (void (*)(int))0
        ^
In file included from mkfs/mkfs.c:12:
./kernel/param.h:15:9: error: 'SIG_IGN' macro redefined [-Werror,-Wmacro-redefined]
#define SIG_IGN      1       // ignore signal
        ^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/sys/signal.h:132:9: note: previous definition is here
#define SIG_IGN         (void (*)(int))1
        ^
4 errors generated.
make: *** [mkfs/mkfs] Error 1

From what I understand sys the new definitions I made already exist in the macOS signal.h file and I do not understand why the compiler even checking this file? since it is in no way relevant for the XV6 and how can I fix this?
Any help would be very appreciated!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.