Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/cva6 #19

Merged
merged 1 commit into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ out_dir = "custom"
members = [
"libpresifuzz_feedbacks",
"libpresifuzz_observers",
"libpresifuzz_schedulers"
"libpresifuzz_schedulers",
"libpresifuzz_ec",
"libpresifuzz_mutators",
"libpresifuzz_riscv",
"libpresifuzz_stages",
]
exclude = [
"fuzzers",
Expand Down
39 changes: 39 additions & 0 deletions fuzzers/cva6-vcs-fuzzer/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
[package]
name = "cva6_vcs_fuzzer"
version = "0.0.1"
edition = "2021"
authors = ["Nassim Corteggiani <[email protected]>"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[profile.release]
panic = "abort"
lto = true
codegen-units = 1
opt-level = 3
debug = false

[profile.dev]
opt-level = 0
strip = "debuginfo"
lto = false
debug = true
panic = "unwind"

[dependencies]
libpresifuzz_riscv = { path = "../../libpresifuzz_riscv"}
libpresifuzz_ec = { path = "../../libpresifuzz_ec", features=["debug"]}
libpresifuzz_mutators = {path="../../libpresifuzz_mutators"}
libpresifuzz_observers = { path = "../../libpresifuzz_observers"}
libpresifuzz_feedbacks = { path = "../../libpresifuzz_feedbacks"}
libpresifuzz_stages = { path = "../../libpresifuzz_stages"}
libafl = { version = "0.11.2"}
libafl_bolts = { version = "0.11.2"}
yaml-rust = "0.4.5"
rand = "0.8.5"
serde_yaml = "0.9.27"
tempdir = "0.3.7"
serde = { version = "1.0", default-features = false, features = ["alloc"] } # serialization lib
clap = { version = "3.2", features = ["default"] }
fs_extra = "1.2.0"

54 changes: 54 additions & 0 deletions fuzzers/cva6-vcs-fuzzer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Fuzzer Overview

This documentation outlines the process of setting up and using an RTL fuzzer for CVA6 architecture using libAFL and PreSiFuzz.
This setup demonstrates feedback-guided fuzzing using hardware code coverage reported by commercial simulator.

# Prerequisites

The following tools need to be installed on your own.

* Latest version of [Spike](https://github.com/riscv-software-src/riscv-isa-sim), the RISC-V ISA simulator, installed.
Follow the installation instructions from the Spike GitHub repository.

* Synopsys VCS (Verilog Compiler Simulator) installed and properly initialized. VCS is a widely used Verilog simulator.
Ensure it is configured and ready for simulation tasks.

* [RISC-V GNU Compiler Toolchain] (https://github.com/riscv-collab/riscv-gnu-toolchain)

## Building

The build.rs script performs the following tasks:

* Initially, it downloads the `cva6` mainstream, initializes submodules, and applies the `cva6.patch` patch.
* Next, it downloads the source code for `libfesvr` and builds it.
* Finally, it compiles the `./src/testcase.S` file and builds the simv self-contained simulator. Generated files are then copied into the `build` folder.

To complete the steps above, simply run:
```sh
$ cargo build
```
## Troubleshooting

It may happened that some environement variables are not properly define and the build script may fail.
Please, check `./cva6/verif/simv/setup-env.sh` and make sure that settings are valid.

## Running the fuzzer

When starting, the fuzzer creates a work directory where it saves intermediates files such as mutants, and symbolic links to the `simv` and its dependencies in `./build`.
Work directory are saved into `TMPDIR` with a unique directory per fuzzer instance. Naming follows `presifuzz_<id>`.
Synchronization information are saved into the `sync` directory, it includes `testcase` and associated `coverage map`.

```
$ cp ../../target/debug/cva6_vcs_fuzzer .
$ mkdir sync
```

To run a single fuzzer instance:
```
$ AFL_LAUNCHER_CLIENT=1 ./cva6_vcs_fuzzer
```

To run multiple fuzzer instances:
```
for i in {1..10}; do AFL_LAUNCHER_CLIENT=$i ./cva6_vcs_fuzzer ; done
```
164 changes: 164 additions & 0 deletions fuzzers/cva6-vcs-fuzzer/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
// SPDX-FileCopyrightText: 2022 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0

use std::path::{Path};
use std::env;
use std::path::PathBuf;
use std::process::{Command, Stdio};
use std::fs;

fn main() {
println!("cargo:warning=MESSAGE");

// if Path::new("./build").is_dir() {
// assert!(fs::remove_dir_all("./build").is_ok());
// }
// assert!(fs::create_dir("./build").is_ok());

let rtl_dir = PathBuf::from("cva6");
if !rtl_dir.exists() {

println!("INFO: Cloning cva6 repository..");

assert!(Command::new("git")
.arg("clone")
.arg("https://github.com/openhwgroup/cva6.git")
.arg(rtl_dir.as_os_str())
.status()
.unwrap()
.success());

let popd = env::current_dir().unwrap();

let cva6_dir = PathBuf::from("./cva6".to_string());
let cva6_dir = cva6_dir.as_os_str().to_str().unwrap().to_string();
std::env::set_current_dir(&cva6_dir).expect("Unable to change into cva6 directory");

println!("INFO: updating submodules");

assert!(Command::new("git")
.arg("submodule")
.arg("update")
.arg("--init")
.arg("--recursive")
.status()
.unwrap()
.success());

println!("INFO: cheking out good commit");

assert!(Command::new("git")
.arg("checkout")
.arg("b401ab3868d053a00779add51ea37cf3b8c98b21")
.status()
.unwrap()
.success());

assert!(Command::new("git")
.arg("apply")
.arg("../cva6.patch")
.status()
.unwrap()
.success());

let popd = popd.as_os_str().to_str().unwrap().to_string();
std::env::set_current_dir(&popd).expect("Unable to change into cva6-vcs-fuzzer directory");
}


let binding = env::current_dir().unwrap();
let cur_dir = binding.to_str().unwrap();
let mut cur_dir = String::from(cur_dir);
cur_dir.push_str("/cva6");

env::set_var("CVA6_HOME_DIR", cur_dir.clone());

if !Path::new("./cva6/tools/spike/lib/libfesvr.so").exists() {
println!("INFO: building fesvr..");

assert!(Command::new("mkdir")
.arg("-p")
.arg("./cva6/tools/spike/lib/")
.status()
.unwrap()
.success());
}

if !Path::new("./cva6/tmp").is_dir() {
assert!(Command::new("mkdir")
.arg("./cva6/tmp")
.status()
.unwrap()
.success());

assert!(Command::new("bash")
.arg("-c")
.arg("cd ./cva6 \
&& RISCV=$CVA6_HOME_DIR/tools/spike source ./ci/install-fesvr.sh")
.env("CVA6_HOME_DIR", cur_dir.clone())
.status()
.unwrap()
.success());
}


if !Path::new("./build/simv").is_file() {
println!("INFO: building cva6..");

assert!(Command::new("bash")
.arg("-c")
.arg("echo $CVA6_HOME_DIR && cd ./cva6/verif/sim/ && source ./setup-env.sh && python3 ./cva6.py --target cv32a60x --iss=vcs-testharness --iss_yaml=cva6.yaml \
--asm_tests $CVA6_HOME_DIR/../src/testcase.S \
--linker=../tests/custom/common/test.ld \
--gcc_opts='-static -mcmodel=medany -fvisibility=hidden -nostdlib \
-nostartfiles -g \
../tests/custom/common/crt.S -lgcc \
-I../tests/custom/env -I../tests/custom/common'")
.stdout(Stdio::inherit())
.env("CVA6_HOME_DIR", cur_dir)
.env("SPIKE_INSTALL_DIR", "/home/nasm/riscv_official")
.status()
.unwrap()
.success());
}

println!("cargo:rerun-if-changed=cva6_project");
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=build");

println!("INFO: creating build dir..");

assert!(Command::new("bash")
.arg("-c")
.arg("cp -r ./cva6/work-vcs/* ./build")
.status()
.unwrap()
.success());

assert!(Command::new("bash")
.arg("-c")
.arg("cp ./cva6/verif/sim/out_*/directed_asm_tests/testcase.o ./build/iram.elf")
.status()
.unwrap()
.success());


let key = "VERDI_HOME";
let mut verdi_lib = match env::var(key) {
Ok(val) => val,
Err(_e) => "".to_string(),
};

if verdi_lib.is_empty() {
println!("The env variable 'VERDI_HOME' is not set");
return;
}

verdi_lib.push_str("/share/NPI/lib/linux64");

println!("cargo:rustc-link-search=native=./build");
println!("cargo:rustc-link-search=native={}", verdi_lib);

}

12 changes: 12 additions & 0 deletions fuzzers/cva6-vcs-fuzzer/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
fuzzer:
max_testcase_size: 128
simv:
vcs_args: "+permissive +tohost_addr=80001000 +elf_file=./testcase.elf +permissive-off ++./testcase.elf +debug_disable=1 +ntb_random_seed=1 -sv_lib /home/nasm/riscv/lib/libfesvr"
plus_args:
cov_enable: true
coverage_metrics: "line+fsm+cond+tgl+branch"
coverage_directory: "Coverage.vdb"
reset_coverage_before_use: true
system_timeout_s: 180
vcs_timeout: "30us"
multi_seed: 0
Loading