Merge branch 'lagarto-ox' into 'master'
Lagarto OX support See merge request rarias/nixos-riscv!1
This commit is contained in:
commit
ccf41b441d
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,4 @@
|
|||||||
*result*
|
*result*
|
||||||
nixos-riscv.qcow2
|
nixos-riscv.qcow2
|
||||||
|
misc/
|
||||||
|
gcroots/
|
||||||
|
6
.gitlab-ci.yml
Normal file
6
.gitlab-ci.yml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
build:lagarto-ox:
|
||||||
|
stage: build
|
||||||
|
tags:
|
||||||
|
- nix
|
||||||
|
script:
|
||||||
|
- nix develop -L .#lagarto-ox --command fpga/run-remotely.sh fpgalogin1:ci
|
5307
JOURNAL.md
Normal file
5307
JOURNAL.md
Normal file
File diff suppressed because one or more lines are too long
52
README.md
52
README.md
@ -2,45 +2,49 @@
|
|||||||
|
|
||||||
This repository contains NixOS configurations for different RISC-V machines.
|
This repository contains NixOS configurations for different RISC-V machines.
|
||||||
|
|
||||||
## QEMU
|
## Lagarto Ox on FPGA Alveo U55C
|
||||||
|
|
||||||
To boot the system in QEMU, first enter the development shell:
|
To build the system and boot it on an FPGA of the MEEP cluster, you can run the
|
||||||
|
following:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ nix develop
|
$ nix develop -L '.#lagarto-ox' --command fpga/run-remotely.sh fpgalogin1:ci
|
||||||
```
|
```
|
||||||
|
|
||||||
Then run the boot script:
|
To do it manually, you can first enter the development shell:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ ./boot.sh
|
$ nix develop -L '.#lagarto-ox'
|
||||||
```
|
```
|
||||||
|
|
||||||
To prevent the GC from erasing the system:
|
Then upload the files to the target machine (fpgalogin1 by default):
|
||||||
|
|
||||||
```
|
|
||||||
$ nix build .#devShells.x86_64-linux.default --out-link result-env
|
|
||||||
```
|
|
||||||
|
|
||||||
## Lagarto Hun on FPGA Alveo U55C
|
|
||||||
|
|
||||||
First build required dependencies:
|
|
||||||
|
|
||||||
```
|
|
||||||
$ nix develop '.#lagarto-hun'
|
|
||||||
```
|
|
||||||
|
|
||||||
Then upload to destination:
|
|
||||||
|
|
||||||
```
|
```
|
||||||
$ fpga/upload.sh
|
$ fpga/upload.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
And then boot the system there:
|
Then connect to the fpgalogin1 machine, allocate a FPGA node and load the
|
||||||
|
environment there:
|
||||||
|
|
||||||
```
|
```
|
||||||
cucu$ ./boot.sh
|
$ cd nixos
|
||||||
...
|
$ . env.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
In the U-Boot prompt, paste the commands of the `uboot.env` file.
|
Flash the images to the FPGA:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ./fpgactl -w bitstream.bit -b opensbi.bin -k kernel.bin -i initrd.bin -r rootfs.img
|
||||||
|
```
|
||||||
|
|
||||||
|
And monitor the serial line:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ picocom -q -b 115200 $FPGACTL_UART
|
||||||
|
```
|
||||||
|
|
||||||
|
It should boot without any user interaction.
|
||||||
|
|
||||||
|
## Lagarto Hun
|
||||||
|
|
||||||
|
WIP
|
||||||
|
3
bootrom/.gitignore
vendored
Normal file
3
bootrom/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
*.o
|
||||||
|
*.elf
|
||||||
|
*.bin
|
23
bootrom/Makefile
Normal file
23
bootrom/Makefile
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
CC ?= riscv64-unknown-elf-gcc
|
||||||
|
OBJCOPY ?= riscv64-unknown-elf-objcopy
|
||||||
|
ROM_BASE ?= 0x00100
|
||||||
|
|
||||||
|
LDFLAGS=-Tlinker.ld -nostdlib -nostartfiles -nodefaultlibs -static -Wl,--no-gc-sections -Wl,--defsym=ROM_BASE=$(ROM_BASE)
|
||||||
|
|
||||||
|
b=rbootrom
|
||||||
|
|
||||||
|
all: $b.elf $b.bin
|
||||||
|
|
||||||
|
$b.o: $b.S
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
$b.elf: $b.o linker.ld
|
||||||
|
$(CC) $(LDFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
$b.bin: $b.elf
|
||||||
|
$(OBJCOPY) -O binary $b.elf $b.bin
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $b.elf $b.bin $b.o
|
||||||
|
|
||||||
|
.PHONY: clean all
|
19
bootrom/linker.ld
Normal file
19
bootrom/linker.ld
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
OUTPUT_ARCH( "riscv" )
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
ROM_BASE = DEFINED(ROM_BASE) ? ROM_BASE : 0x00100; /* Default to 0x00100 if ROM_BASE is not defined */
|
||||||
|
|
||||||
|
. = ROM_BASE;
|
||||||
|
.text.start : { *(.text.start) }
|
||||||
|
. = ROM_BASE + 0x80;
|
||||||
|
.text.hang : { *(.text.hang) }
|
||||||
|
/*
|
||||||
|
. = ROM_BASE + 0xC0;
|
||||||
|
.rodata.dtb : { *(.rodata.dtb) }
|
||||||
|
*/
|
||||||
|
|
||||||
|
. = ALIGN(0x100);
|
||||||
|
.text : { *(.text) }
|
||||||
|
}
|
189
bootrom/rbootrom.S
Normal file
189
bootrom/rbootrom.S
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024, Barcelona Supercomputing Center (BSC)
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* RBOOTROM v1.0
|
||||||
|
* Modified by Rodrigo Arias Mallo <rodrigo.arias@bsc.es>
|
||||||
|
*
|
||||||
|
* This is a custom bootrom that prints some information to the UART when
|
||||||
|
* starting, as well as when it hangs. It assumes the UART is at UART_BASE and
|
||||||
|
* it will jump to DRAM_BASE to continue the boot.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DRAM_BASE 0x80000000
|
||||||
|
#define UART_BASE 0x40001000
|
||||||
|
#define UART_BAUDRATE 115200
|
||||||
|
#define UART_CLOCK 50000000
|
||||||
|
|
||||||
|
#define UART_BDIV ((UART_CLOCK + 8 * UART_BAUDRATE) / (16 * UART_BAUDRATE))
|
||||||
|
#define UART_SHIFT 2
|
||||||
|
|
||||||
|
#define UART_RBR_OFFSET (0<<UART_SHIFT) /* In: Recieve Buffer Register */
|
||||||
|
#define UART_THR_OFFSET (0<<UART_SHIFT) /* Out: Transmitter Holding Register */
|
||||||
|
#define UART_DLL_OFFSET (0<<UART_SHIFT) /* Out: Divisor Latch Low */
|
||||||
|
#define UART_IER_OFFSET (1<<UART_SHIFT) /* I/O: Interrupt Enable Register */
|
||||||
|
#define UART_DLM_OFFSET (1<<UART_SHIFT) /* Out: Divisor Latch High */
|
||||||
|
#define UART_FCR_OFFSET (2<<UART_SHIFT) /* Out: FIFO Control Register */
|
||||||
|
#define UART_IIR_OFFSET (2<<UART_SHIFT) /* I/O: Interrupt Identification Register */
|
||||||
|
#define UART_LCR_OFFSET (3<<UART_SHIFT) /* Out: Line Control Register */
|
||||||
|
#define UART_MCR_OFFSET (4<<UART_SHIFT) /* Out: Modem Control Register */
|
||||||
|
#define UART_LSR_OFFSET (5<<UART_SHIFT) /* In: Line Status Register */
|
||||||
|
#define UART_MSR_OFFSET (6<<UART_SHIFT) /* In: Modem Status Register */
|
||||||
|
#define UART_SCR_OFFSET (7<<UART_SHIFT) /* I/O: Scratch Register */
|
||||||
|
#define UART_MDR1_OFFSET (8<<UART_SHIFT) /* I/O: Mode Register */
|
||||||
|
|
||||||
|
#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
|
||||||
|
#define UART_LSR_DR 0x01 /* Receiver data ready */
|
||||||
|
|
||||||
|
.macro PUTC, ch
|
||||||
|
li a0, \ch
|
||||||
|
jal putchar
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.section .text.start, "ax", @progbits
|
||||||
|
.globl _start
|
||||||
|
_start:
|
||||||
|
jal uart_init // Initialize console
|
||||||
|
jal print_hello // Print initial message on HART 0 only
|
||||||
|
|
||||||
|
la t0, _hang
|
||||||
|
csrw mtvec, t0 // Set the machine trap vector
|
||||||
|
|
||||||
|
csrr a0, mhartid // Load HART ID into a0
|
||||||
|
li s0, DRAM_BASE // Load next address into s0
|
||||||
|
jr s0 // Jump to s0
|
||||||
|
|
||||||
|
.section .text.hang, "ax", @progbits
|
||||||
|
.globl _hang
|
||||||
|
_hang:
|
||||||
|
|
||||||
|
PUTC '\n'
|
||||||
|
PUTC '\r'
|
||||||
|
PUTC 'R'
|
||||||
|
PUTC 'B'
|
||||||
|
PUTC 'O'
|
||||||
|
PUTC 'O'
|
||||||
|
PUTC 'T'
|
||||||
|
PUTC 'R'
|
||||||
|
PUTC 'O'
|
||||||
|
PUTC 'M'
|
||||||
|
PUTC ' '
|
||||||
|
PUTC 'H'
|
||||||
|
PUTC 'A'
|
||||||
|
PUTC 'N'
|
||||||
|
PUTC 'G'
|
||||||
|
PUTC '\n'
|
||||||
|
PUTC '\r'
|
||||||
|
|
||||||
|
/* Hang */
|
||||||
|
csrr a0, mhartid
|
||||||
|
1:
|
||||||
|
wfi
|
||||||
|
j 1b
|
||||||
|
|
||||||
|
.section .text, "ax", @progbits
|
||||||
|
|
||||||
|
putchar:
|
||||||
|
/* Wait until ready to transmit */
|
||||||
|
|
||||||
|
la t0, UART_BASE // Load UART base address
|
||||||
|
1:
|
||||||
|
lb t1, UART_LSR_OFFSET(t0) // Read Line Status Register
|
||||||
|
andi t1, t1, UART_LSR_THRE // Transmitter Holding Register Empty
|
||||||
|
beqz t1, 1b // Repeat if zero (not empty)
|
||||||
|
|
||||||
|
/* Write the character now */
|
||||||
|
sb a0, UART_THR_OFFSET(t0) // Transmit character
|
||||||
|
ret
|
||||||
|
|
||||||
|
uart_init:
|
||||||
|
/* Assume reg_shift = 2 and reg_width = 2 */
|
||||||
|
|
||||||
|
la t0, UART_BASE // Load UART base address
|
||||||
|
|
||||||
|
/* From OpenSBI v1.5 lib/utils/serial/uart8250.c */
|
||||||
|
|
||||||
|
la t1, 0x00 // Disable all interrupts
|
||||||
|
sb t1, UART_IER_OFFSET(t0)
|
||||||
|
la t1, 0x80 // Enable DLAB
|
||||||
|
sb t1, UART_LCR_OFFSET(t0)
|
||||||
|
|
||||||
|
la t1, UART_BDIV & 0xff // Set divisor low byte
|
||||||
|
sb t1, UART_DLL_OFFSET(t0)
|
||||||
|
la t1, (UART_BDIV >> 8) & 0xff // Set divisor high byte
|
||||||
|
sb t1, UART_DLM_OFFSET(t0)
|
||||||
|
|
||||||
|
la t1, 0x03 // 8 bits, no parity, one stop bit
|
||||||
|
sb t1, UART_LCR_OFFSET(t0)
|
||||||
|
la t1, 0x01 // Enable FIFO
|
||||||
|
sb t1, UART_FCR_OFFSET(t0)
|
||||||
|
la t1, 0x00 // No modem control DTR RTS
|
||||||
|
sb t1, UART_MCR_OFFSET(t0)
|
||||||
|
|
||||||
|
/* TODO: Clear line status */
|
||||||
|
/* TODO: Read receive buffer */
|
||||||
|
|
||||||
|
la t1, 0x00 // Set scratchpad to 0
|
||||||
|
sb t1, UART_SCR_OFFSET(t0)
|
||||||
|
|
||||||
|
ret
|
||||||
|
|
||||||
|
print_hello:
|
||||||
|
csrr t0, mhartid // Load HART ID into a0
|
||||||
|
beq t0, zero, 1f // Print message on HART 0 only
|
||||||
|
ret
|
||||||
|
1:
|
||||||
|
mv s0, ra // Save return address
|
||||||
|
PUTC '\n' // Identify bootroom
|
||||||
|
PUTC '\r'
|
||||||
|
PUTC 'R'
|
||||||
|
PUTC 'B'
|
||||||
|
PUTC 'O'
|
||||||
|
PUTC 'O'
|
||||||
|
PUTC 'T'
|
||||||
|
PUTC 'R'
|
||||||
|
PUTC 'O'
|
||||||
|
PUTC 'M'
|
||||||
|
PUTC ' '
|
||||||
|
PUTC 'v'
|
||||||
|
PUTC '1'
|
||||||
|
PUTC '.'
|
||||||
|
PUTC '0'
|
||||||
|
PUTC ' '
|
||||||
|
PUTC ':'
|
||||||
|
PUTC '^'
|
||||||
|
PUTC ')'
|
||||||
|
PUTC '\n'
|
||||||
|
PUTC '\r'
|
||||||
|
|
||||||
|
// Print jumping address
|
||||||
|
PUTC 'J'
|
||||||
|
PUTC 'u'
|
||||||
|
PUTC 'm'
|
||||||
|
PUTC 'p'
|
||||||
|
PUTC 'i'
|
||||||
|
PUTC 'n'
|
||||||
|
PUTC 'g'
|
||||||
|
PUTC ' '
|
||||||
|
PUTC 't'
|
||||||
|
PUTC 'o'
|
||||||
|
PUTC ' '
|
||||||
|
PUTC '0' // TODO: Compute from DRAM_BASE
|
||||||
|
PUTC 'x'
|
||||||
|
PUTC '8'
|
||||||
|
PUTC '0'
|
||||||
|
PUTC '0'
|
||||||
|
PUTC '0'
|
||||||
|
PUTC '_'
|
||||||
|
PUTC '0'
|
||||||
|
PUTC '0'
|
||||||
|
PUTC '0'
|
||||||
|
PUTC '0'
|
||||||
|
PUTC '.'
|
||||||
|
PUTC '.'
|
||||||
|
PUTC '.'
|
||||||
|
PUTC '\n'
|
||||||
|
PUTC '\r'
|
||||||
|
|
||||||
|
mv ra, s0 // Restore return address
|
||||||
|
ret
|
@ -1,13 +1,22 @@
|
|||||||
{ config, lib, pkgs, modulesPath, ... }:
|
{ config, lib, pkgs, modulesPath, self, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
imports = [
|
imports = [
|
||||||
#"${modulesPath}/profiles/base.nix"
|
#"${modulesPath}/profiles/base.nix"
|
||||||
#"${modulesPath}/profiles/minimal.nix"
|
"${modulesPath}/profiles/minimal.nix"
|
||||||
];
|
];
|
||||||
|
|
||||||
nixpkgs.crossSystem = {
|
nixpkgs = {
|
||||||
system = "riscv64-linux";
|
crossSystem = {
|
||||||
|
system = "riscv64-linux";
|
||||||
|
};
|
||||||
|
|
||||||
|
overlays = [
|
||||||
|
self.inputs.bscpkgs.bscOverlay
|
||||||
|
(import ./overlay.nix)
|
||||||
|
];
|
||||||
|
|
||||||
|
config.allowUnsupportedSystem = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
networking.hostName = "nixos-riscv";
|
networking.hostName = "nixos-riscv";
|
||||||
@ -26,5 +35,33 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
systemd.oomd.enable = false;
|
||||||
|
networking.firewall.enable = false;
|
||||||
|
networking.dhcpcd.enable = false;
|
||||||
|
services.timesyncd.enable = false;
|
||||||
|
|
||||||
#environment.systemPackages = with pkgs; [ vim gdb neofetch gcc bintools ];
|
#environment.systemPackages = with pkgs; [ vim gdb neofetch gcc bintools ];
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
rvb riscv-tools stream spec-cpu-mini
|
||||||
|
config.boot.kernelPackages.perf
|
||||||
|
];
|
||||||
|
|
||||||
|
services.getty.helpLine = ''
|
||||||
|
|
||||||
|
|
||||||
|
__________________
|
||||||
|
< Welcome to NixOS >
|
||||||
|
------------------
|
||||||
|
\ ^__^
|
||||||
|
\ (oo)\_______
|
||||||
|
(__)\ )\/\
|
||||||
|
||----w |
|
||||||
|
|| ||
|
||||||
|
|
||||||
|
|
||||||
|
If you can read this message then then you have
|
||||||
|
successfully booted NixOS into the login shell.
|
||||||
|
|
||||||
|
|
||||||
|
'';
|
||||||
}
|
}
|
||||||
|
2
dts/.gitignore
vendored
Normal file
2
dts/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*.pp.dts
|
||||||
|
*.dtb
|
18
dts/Makefile
Normal file
18
dts/Makefile
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
CC?=gcc
|
||||||
|
DTC?=dtc
|
||||||
|
|
||||||
|
CPPFLAGS=-E -C -P -nostdinc -undef -x assembler-with-cpp
|
||||||
|
|
||||||
|
all: lagarto_ox.dtb
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.pp.dts *.dtb
|
||||||
|
|
||||||
|
%.pp.dts: %.dts *.h
|
||||||
|
$(CC) $(CPPFLAGS) $< -o $@
|
||||||
|
sed -i 's/@0x0*/@/' $@
|
||||||
|
|
||||||
|
%.dtb: %.pp.dts
|
||||||
|
dtc -O dtb -o $@ $^
|
||||||
|
|
||||||
|
.PRECIOUS: %.pp.dts
|
255
dts/lagarto_ox.dts
Normal file
255
dts/lagarto_ox.dts
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
#include "lagarto_ox.h"
|
||||||
|
|
||||||
|
/dts-v1/;
|
||||||
|
/ {
|
||||||
|
#address-cells = <2>;
|
||||||
|
#size-cells = <2>; /* 64 bits memory addresses */
|
||||||
|
compatible = "riscv,rv64i";
|
||||||
|
model = "Barcelona Supercomputing Center - Lagarto Ox (NixOS)";
|
||||||
|
|
||||||
|
cpus {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
timebase-frequency = <RTC_FREQ>;
|
||||||
|
CPU0: cpu@0 {
|
||||||
|
clock-frequency = <CPU_FREQ>;
|
||||||
|
device_type = "cpu";
|
||||||
|
reg = <0>;
|
||||||
|
status = "okay";
|
||||||
|
compatible = "riscv";
|
||||||
|
riscv,isa = "rv64imafd";
|
||||||
|
mmu-type = "riscv,sv39";
|
||||||
|
tlb-split;
|
||||||
|
|
||||||
|
i-cache-block-size = <64>; // Guess
|
||||||
|
i-cache-sets = <4>;
|
||||||
|
i-cache-size = <16384>;
|
||||||
|
i-tlb-sets = <1>; // Guess
|
||||||
|
i-tlb-size = <32>; // Guess
|
||||||
|
|
||||||
|
d-cache-block-size = <64>; // Guess
|
||||||
|
d-cache-sets = <4>;
|
||||||
|
d-cache-size = <32768>;
|
||||||
|
d-tlb-sets = <1>; // Guess
|
||||||
|
d-tlb-size = <32>; // Guess
|
||||||
|
|
||||||
|
/* Hart-Level Interrupt Controller: Every interrupt is
|
||||||
|
* ultimately routed through a hart's HLIC before it
|
||||||
|
* interrupts that hart. */
|
||||||
|
HLIC0: interrupt-controller {
|
||||||
|
#interrupt-cells = <1>;
|
||||||
|
interrupt-controller; /* Receives interrupts */
|
||||||
|
compatible = "riscv,cpu-intc";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
cpu-map {
|
||||||
|
cluster0 {
|
||||||
|
core0 {
|
||||||
|
cpu = <&CPU0>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
memory@MEM_ADDR {
|
||||||
|
device_type = "memory";
|
||||||
|
reg = /bits/ 64 <MEM_ADDR MEM_SIZE>;
|
||||||
|
};
|
||||||
|
reserved-memory {
|
||||||
|
#address-cells = <2>; /* Starting address and size */
|
||||||
|
#size-cells = <2>; /* 64 bits memory addresses */
|
||||||
|
ranges;
|
||||||
|
eth_pool: dma_pool@ETHPOOL_ADDR {
|
||||||
|
reg = /bits/ 64 <ETHPOOL_ADDR ETHPOOL_SIZE>;
|
||||||
|
compatible = "shared-dma-pool";
|
||||||
|
};
|
||||||
|
onic_pool: dma_pool@ONICPOOL_ADDR {
|
||||||
|
reg = /bits/ 64 <ONICPOOL_ADDR ONICPOOL_SIZE>;
|
||||||
|
compatible = "shared-dma-pool";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
pmem@PMEM_ADDR {
|
||||||
|
/* volatile; This property indicates that this region is
|
||||||
|
* actually backed by non-persistent memory. This lets the OS
|
||||||
|
* know that it may skip the cache flushes required to ensure
|
||||||
|
* data is made persistent after a write. */
|
||||||
|
volatile;
|
||||||
|
compatible = "pmem-region";
|
||||||
|
reg = /bits/ 64 <PMEM_ADDR PMEM_SIZE>;
|
||||||
|
};
|
||||||
|
soc {
|
||||||
|
#address-cells = <2>;
|
||||||
|
#size-cells = <2>;
|
||||||
|
compatible = "BSC,Lagarto-ox-soc", "simple-bus";
|
||||||
|
ranges;
|
||||||
|
|
||||||
|
/* For bitstream e97dd7b2-397f-11ef-abe0-bbd201a5a630 with two
|
||||||
|
* consoles */
|
||||||
|
|
||||||
|
#ifdef ENABLE_UART0
|
||||||
|
/* The serial for the kernel console */
|
||||||
|
uart_console: serial@UART0_ADDR {
|
||||||
|
compatible = "ns16550";
|
||||||
|
reg = /bits/ 64 <UART0_ADDR UART0_SIZE>;
|
||||||
|
reg-shift = <2>;
|
||||||
|
/* No interrupts for this UART, use console=hvc0 */
|
||||||
|
/* This clock is the SERIAL_CLK */
|
||||||
|
clock-frequency = <CPU_FREQ>;
|
||||||
|
current-speed = <UART0_SPEED>;
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
#endif /* ENABLE_UART0 */
|
||||||
|
|
||||||
|
#ifdef ENABLE_UART1
|
||||||
|
/* The serial for interrupt tests */
|
||||||
|
uart_testing: serial@UART1_ADDR {
|
||||||
|
compatible = "ns16550";
|
||||||
|
reg = /bits/ 64 <UART1_ADDR UART1_SIZE>;
|
||||||
|
reg-shift = <2>;
|
||||||
|
/* Output interrupt 1 (the first one) */
|
||||||
|
interrupts = <1>;
|
||||||
|
interrupt-parent = <&PLIC>;
|
||||||
|
clock-frequency = <CPU_FREQ>;
|
||||||
|
current-speed = <UART1_SPEED>;
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
#endif /* ENABLE_UART1 */
|
||||||
|
|
||||||
|
#ifdef ENABLE_ETHERNET
|
||||||
|
ethernet0 {
|
||||||
|
xlnx,rxmem = <1522>;
|
||||||
|
carv,mtu = <1500>;
|
||||||
|
carv,no-mac;
|
||||||
|
device_type = "network";
|
||||||
|
// 02:$node:00:01:00:$fpga -> 02:05:00:01:00:02
|
||||||
|
// 10.5.1.$N/16 -> 10.5.1.184/16
|
||||||
|
// N = 150 + ($node - 1) * 8 + $fpga
|
||||||
|
local-mac-address = [00 00 00 00 00 00];
|
||||||
|
axistream-connected = <&axi_dma>;
|
||||||
|
compatible = "xlnx,xxv-ethernet-1.0-carv";
|
||||||
|
memory-region = <ð_pool>;
|
||||||
|
};
|
||||||
|
#endif /* ENABLE_ETHERNET */
|
||||||
|
|
||||||
|
#ifdef ENABLE_AXIDMA
|
||||||
|
dma_clk: dma_clk {
|
||||||
|
compatible = "fixed-clock";
|
||||||
|
#clock-cells = <0x0>;
|
||||||
|
clock-frequency = <AXIDMA_FREQ>;
|
||||||
|
};
|
||||||
|
axi_dma: dma@AXIDMA_ADDR {
|
||||||
|
reg = /bits/ 64 <AXIDMA_ADDR AXIDMA_SIZE>;
|
||||||
|
reg-shift = <2>;
|
||||||
|
#address-cells = <2>;
|
||||||
|
#size-cells = <2>;
|
||||||
|
xlnx,include-dre;
|
||||||
|
#dma-cells = <0x1>;
|
||||||
|
compatible = "xlnx,axi-dma-1.00.a";
|
||||||
|
clock-names = "s_axi_lite_aclk", "m_axi_mm2s_aclk",
|
||||||
|
"m_axi_s2mm_aclk", "m_axi_sg_aclk";
|
||||||
|
clocks = <&dma_clk>, <&dma_clk>, <&dma_clk>, <&dma_clk>;
|
||||||
|
interrupt-names = "mm2s_introut", "s2mm_introut";
|
||||||
|
interrupt-parent = <&PLIC>;
|
||||||
|
interrupts = <2 3>;
|
||||||
|
xlnx,addrwidth = <0x28>;
|
||||||
|
xlnx,include-sg;
|
||||||
|
xlnx,sg-length-width = <0x17>;
|
||||||
|
dma-channel@AXIDMA_CH0 {
|
||||||
|
reg = /bits/ 64 <AXIDMA_CH0 0x30>;
|
||||||
|
compatible = "xlnx,axi-dma-mm2s-channel";
|
||||||
|
dma-channels = <0>;
|
||||||
|
interrupts = <2>;
|
||||||
|
xlnx,datawidth = <0x40>;
|
||||||
|
xlnx,device-id = <0x0>;
|
||||||
|
xlnx,include-dre;
|
||||||
|
};
|
||||||
|
dma-channel@AXIDMA_CH1 {
|
||||||
|
reg = /bits/ 64 <AXIDMA_CH1 0x30>;
|
||||||
|
compatible = "xlnx,axi-dma-s2mm-channel";
|
||||||
|
dma-channels = <1>;
|
||||||
|
interrupts = <3>;
|
||||||
|
xlnx,datawidth = <0x40>;
|
||||||
|
xlnx,device-id = <0x0>;
|
||||||
|
xlnx,include-dre;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
#endif /* ENABLE_AXIDMA */
|
||||||
|
|
||||||
|
#ifdef ENABLE_PLIC
|
||||||
|
/* Platform-Level Interrupt Controller: Delivers interrupts to
|
||||||
|
* HARTs. */
|
||||||
|
PLIC: plic@PLIC_ADDR {
|
||||||
|
reg = /bits/ 64 <PLIC_ADDR PLIC_SIZE>;
|
||||||
|
compatible = "riscv,plic0";
|
||||||
|
interrupt-controller; /* Receives interrupts */
|
||||||
|
#address-cells = <0>;
|
||||||
|
#interrupt-cells = <1>;
|
||||||
|
/* Sends interrupts to HART interrupt controllers.
|
||||||
|
* Configures two output targets or contexts:
|
||||||
|
* - context 0: machine mode external interrupt (11)
|
||||||
|
* - context 1: supervisor mode external interrupt (9)
|
||||||
|
*/
|
||||||
|
interrupts-extended = <&HLIC0 11>, <&HLIC0 9>;
|
||||||
|
riscv,ndev = <PLIC_NDEV>;
|
||||||
|
//riscv,max-priority = <0x7>;
|
||||||
|
};
|
||||||
|
#endif /* ENABLE_PLIC */
|
||||||
|
|
||||||
|
#ifdef ENABLE_CLINT
|
||||||
|
/* Core Local Interruptor: It directly connects to the timer and
|
||||||
|
* inter-processor interrupt lines of various HARTs (or CPUs) so
|
||||||
|
* RISC-V per-HART (or per-CPU) local interrupt controller is
|
||||||
|
* the parent interrupt controller for CLINT device. The clock
|
||||||
|
* frequency of CLINT is specified via "timebase-frequency" DT
|
||||||
|
* property of "/cpus" DT node. The "timebase-frequency" DT
|
||||||
|
* property is described in
|
||||||
|
* Documentation/devicetree/bindings/riscv/cpus.yaml
|
||||||
|
*/
|
||||||
|
clint: clint@CLINT_ADDR {
|
||||||
|
reg = /bits/ 64 <CLINT_ADDR CLINT_SIZE>;
|
||||||
|
reg-names = "control";
|
||||||
|
interrupts-extended = <&HLIC0 3>, <&HLIC0 7>;
|
||||||
|
compatible = "riscv,clint0";
|
||||||
|
};
|
||||||
|
#endif /* ENABLE_CLINT */
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* There is another auxiliar clint (timer) at 40010000 for
|
||||||
|
* tests, but we don't tell the kernel so we can use it for
|
||||||
|
* testing interrupts manually. */
|
||||||
|
aux_timer: clint@AUXTIMER_ADDR {
|
||||||
|
reg = /bits/ 64 <AUXTIMER_ADDR AUXTIMER_SIZE>;
|
||||||
|
reg-names = "control";
|
||||||
|
interrupts = <4>; /* PLIC input source 4 */
|
||||||
|
interrupt-parent = <&PLIC>;
|
||||||
|
compatible = "riscv,clint0";
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_SPI
|
||||||
|
serial@UART2_ADDR {
|
||||||
|
compatible = "ns16750";
|
||||||
|
reg = /bits/ 64 <UART2_ADDR UART2_SIZE>;
|
||||||
|
interrupt-parent = <&PLIC>;
|
||||||
|
interrupts = <5>;
|
||||||
|
clock-frequency = <CPU_FREQ>;
|
||||||
|
current-speed = <UART2_SPEED>;
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
spi@SPI_ADDR {
|
||||||
|
compatible = "ti,keystone-spi";
|
||||||
|
reg = /bits/ 64 <SPI_ADDR SPI_SIZE>;
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
interrupt-parent = <&PLIC>;
|
||||||
|
interrupt-names = "intvec0", "intvec1";
|
||||||
|
interrupts = <6 0>, <7 0>;
|
||||||
|
ti,davinci-spi-intr-line = <0>;
|
||||||
|
spi-max-frequency = <24000000>;
|
||||||
|
loopback-mode = <1>;
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
#endif /* ENABLE_SPI */
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
76
dts/lagarto_ox.h
Normal file
76
dts/lagarto_ox.h
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/* Toggles */
|
||||||
|
|
||||||
|
#define ENABLE_UART0
|
||||||
|
#define ENABLE_UART1
|
||||||
|
#define ENABLE_ETHERNET
|
||||||
|
#define ENABLE_AXIDMA
|
||||||
|
#define ENABLE_PLIC
|
||||||
|
#define ENABLE_CLINT
|
||||||
|
//#define ENABLE_SPI
|
||||||
|
|
||||||
|
#define CPU_FREQ 50000000 /* 50 MHz */
|
||||||
|
/* FIXME: The real RTC frequency is around half that, as the divider was wrongly
|
||||||
|
* configured. So for now lets use the real frequency:
|
||||||
|
* 50e6 / (1525*2) = 16393.44262295082 -> 16393 Hz */
|
||||||
|
#define RTC_FREQ 16393
|
||||||
|
|
||||||
|
/* Memory layout:
|
||||||
|
*
|
||||||
|
* [0x0_4000_0000, 0x0_6000_0000) -> IO (512 MiB)
|
||||||
|
* [0x0_6000_0000, 0x0_7000_0000) -> DMA pool (256 MiB)
|
||||||
|
* [0x0_7000_0000, 0x0_8000_0000) -> DMA pool (256 MiB)
|
||||||
|
* [0x0_8000_0000, 0x1_8000_0000) -> RAM memory (4 GiB)
|
||||||
|
* [0x1_8000_0000, 0x1_c000_0000) -> Unused (1 GiB)
|
||||||
|
* [0x1_c000_0000, 0x2_8000_0000) -> PMEM (3 GiB)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define UART0_SPEED 115200
|
||||||
|
#define UART0_ADDR 0x40001000
|
||||||
|
#define UART0_SIZE 0x00001000
|
||||||
|
|
||||||
|
#define UART1_SPEED UART0_SPEED
|
||||||
|
#define UART1_ADDR 0x40003000
|
||||||
|
#define UART1_SIZE 0x00001000
|
||||||
|
|
||||||
|
/* UART2 via SPI */
|
||||||
|
#define UART2_SPEED UART0_SPEED
|
||||||
|
#define UART2_ADDR 0x40005000
|
||||||
|
#define UART2_SIZE 0x00001000
|
||||||
|
|
||||||
|
#define SPI_ADDR 0x40007000
|
||||||
|
#define SPI_SIZE 0x00001000
|
||||||
|
|
||||||
|
#define AUXTIMER_ADDR 0x40010000
|
||||||
|
#define AUXTIMER_SIZE 0x00010000
|
||||||
|
|
||||||
|
#define CLINT_ADDR 0x40100000
|
||||||
|
#define CLINT_SIZE 0x00010000
|
||||||
|
|
||||||
|
#define AXIDMA_ADDR 0x40400000
|
||||||
|
#define AXIDMA_SIZE 0x00400000
|
||||||
|
#define AXIDMA_CH0 0x40400000
|
||||||
|
#define AXIDMA_CH1 0x40400030
|
||||||
|
#define AXIDMA_FREQ 156250000
|
||||||
|
|
||||||
|
#define PLIC_ADDR 0x40800000
|
||||||
|
#define PLIC_SIZE 0x00400000
|
||||||
|
|
||||||
|
#ifdef ENABLE_SPI
|
||||||
|
# define PLIC_NDEV 7 /* extra UART2 + 2 x SPI */
|
||||||
|
#else
|
||||||
|
# define PLIC_NDEV 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ETHPOOL_ADDR 0x60000000
|
||||||
|
#define ETHPOOL_SIZE 0x10000000
|
||||||
|
|
||||||
|
#define ONICPOOL_ADDR 0x70000000
|
||||||
|
#define ONICPOOL_SIZE 0x10000000
|
||||||
|
|
||||||
|
/* Notice addresses > 32 bits from here */
|
||||||
|
|
||||||
|
#define MEM_ADDR 0x080000000
|
||||||
|
#define MEM_SIZE 0x100000000
|
||||||
|
|
||||||
|
#define PMEM_ADDR 0x1c0000000
|
||||||
|
#define PMEM_SIZE 0x0c0000000
|
46
flake.lock
generated
46
flake.lock
generated
@ -1,24 +1,56 @@
|
|||||||
{
|
{
|
||||||
"nodes": {
|
"nodes": {
|
||||||
|
"bscpkgs": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1713974364,
|
||||||
|
"narHash": "sha256-ilZTVWSaNP1ibhQIIRXE+q9Lj2XOH+F9W3Co4QyY1eU=",
|
||||||
|
"ref": "refs/heads/master",
|
||||||
|
"rev": "de89197a4a7b162db7df9d41c9d07759d87c5709",
|
||||||
|
"revCount": 937,
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.sr.ht/~rodarima/bscpkgs"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.sr.ht/~rodarima/bscpkgs"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1706092046,
|
"lastModified": 1700390070,
|
||||||
"narHash": "sha256-Cbethl95Cu+WVIWfaAnRRBZiz5PmXxQvg4vXNqIZQUg=",
|
"narHash": "sha256-de9KYi8rSJpqvBfNwscWdalIJXPo8NjdIZcEJum1mH0=",
|
||||||
"owner": "rodarima",
|
"path": "/nix/store/z7y28qzhk7driiwcw78k0mb24laknm0f-source",
|
||||||
|
"rev": "e4ad989506ec7d71f7302cc3067abd82730a4beb",
|
||||||
|
"type": "path"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"id": "nixpkgs",
|
||||||
|
"type": "indirect"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs_2": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1720031269,
|
||||||
|
"narHash": "sha256-rwz8NJZV+387rnWpTYcXaRNvzUSnnF9aHONoJIYmiUQ=",
|
||||||
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "57e7c8fa4fdc414a936ce83afd0c70fb0a3a31d5",
|
"rev": "9f4128e00b0ae8ec65918efeba59db998750ead6",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "rodarima",
|
"owner": "NixOS",
|
||||||
"ref": "fix-pkgs-static-gcc-march",
|
"ref": "nixos-unstable",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": {
|
"root": {
|
||||||
"inputs": {
|
"inputs": {
|
||||||
"nixpkgs": "nixpkgs"
|
"bscpkgs": "bscpkgs",
|
||||||
|
"nixpkgs": "nixpkgs_2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
99
flake.nix
99
flake.nix
@ -1,17 +1,20 @@
|
|||||||
{
|
{
|
||||||
inputs.nixpkgs.url = "github:rodarima/nixpkgs/fix-pkgs-static-gcc-march";
|
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
|
inputs.bscpkgs.url = "git+https://git.sr.ht/~rodarima/bscpkgs";
|
||||||
|
|
||||||
outputs = { self, nixpkgs, ... }:
|
outputs = {self, nixpkgs, ...}@inputs:
|
||||||
let
|
let
|
||||||
system = "x86_64-linux";
|
system = "x86_64-linux";
|
||||||
overlay = import ./overlay.nix;
|
nixosSystem = import (nixpkgs + "/nixos/lib/eval-config.nix");
|
||||||
pkgs = import nixpkgs { inherit system; };
|
mkRoots = pkgs: list: pkgs.writeText "gcroots.json"
|
||||||
|
(builtins.toJSON (map (x: { drv = x; attrs = x.drvAttrs; }) list));
|
||||||
in {
|
in {
|
||||||
overlay = import ./overlay.nix;
|
#overlay = import ./overlay.nix;
|
||||||
nixosConfigurations = {
|
nixosConfigurations = {
|
||||||
# The qemu configuration defines a system that runs in the RISC-V
|
# The qemu configuration defines a system that runs in the RISC-V
|
||||||
# architecture, but is build from an x86 host machine.
|
# architecture, but is build from an x86 host machine.
|
||||||
qemu = nixpkgs.lib.nixosSystem {
|
qemu = nixosSystem {
|
||||||
|
specialArgs = { inherit self; };
|
||||||
system = "${system}";
|
system = "${system}";
|
||||||
modules = [
|
modules = [
|
||||||
./configuration.nix
|
./configuration.nix
|
||||||
@ -20,7 +23,8 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
# Same, but disable compressed instructions
|
# Same, but disable compressed instructions
|
||||||
qemu-nc = nixpkgs.lib.nixosSystem {
|
qemu-nc = nixosSystem {
|
||||||
|
specialArgs = { inherit self; };
|
||||||
system = "${system}";
|
system = "${system}";
|
||||||
modules = [
|
modules = [
|
||||||
./configuration.nix
|
./configuration.nix
|
||||||
@ -30,7 +34,8 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
# FPGA Lagarto Hun CPU
|
# FPGA Lagarto Hun CPU
|
||||||
lagarto-hun = nixpkgs.lib.nixosSystem {
|
lagarto-hun = nixosSystem {
|
||||||
|
specialArgs = { inherit self; };
|
||||||
system = "${system}";
|
system = "${system}";
|
||||||
modules = [
|
modules = [
|
||||||
./configuration.nix
|
./configuration.nix
|
||||||
@ -38,35 +43,105 @@
|
|||||||
./no-compressed.nix
|
./no-compressed.nix
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# FPGA Lagarto Ox CPU
|
||||||
|
lagarto-ox = nixosSystem {
|
||||||
|
specialArgs = { inherit self; };
|
||||||
|
system = "${system}";
|
||||||
|
modules = [
|
||||||
|
./configuration.nix
|
||||||
|
./lagarto-ox.nix
|
||||||
|
./no-compressed.nix
|
||||||
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# A development shell with QEMU ready to boot the RISC-V system in an x86
|
# A development shell with QEMU ready to boot the RISC-V system in an x86
|
||||||
# machine.
|
# machine.
|
||||||
devShells.x86_64-linux.default =
|
devShells.x86_64-linux.qemu-lagarto-hun =
|
||||||
let
|
let
|
||||||
nixosconf = self.nixosConfigurations.qemu-nc;
|
nixosconf = self.nixosConfigurations.qemu-nc;
|
||||||
syspkgs = nixosconf.pkgs;
|
syspkgs = nixosconf.pkgs;
|
||||||
toplevel = nixosconf.config.system.build.toplevel;
|
toplevel = nixosconf.config.system.build.toplevel;
|
||||||
in pkgs.mkShell {
|
in syspkgs.mkShell {
|
||||||
pname = "qemu-shell";
|
pname = "qemu-shell";
|
||||||
buildInputs = with pkgs; [ qemu e2fsprogs ];
|
nativeBuildInputs = with syspkgs; [ qemu e2fsprogs ];
|
||||||
# Here we tell the run script where to find the system
|
# Here we tell the run script where to find the system
|
||||||
NIXOS_SYSTEM_TOPLEVEL = toplevel;
|
NIXOS_SYSTEM_TOPLEVEL = toplevel;
|
||||||
OPENSBI = syspkgs.opensbi-uboot;
|
OPENSBI = syspkgs.opensbi-uboot;
|
||||||
};
|
};
|
||||||
|
|
||||||
devShells.x86_64-linux.lagarto-hun =
|
devShells.x86_64-linux.lagarto-hun =
|
||||||
let
|
let
|
||||||
nixosconf = self.nixosConfigurations.lagarto-hun;
|
nixosconf = self.nixosConfigurations.lagarto-hun;
|
||||||
syspkgs = nixosconf.pkgs;
|
syspkgs = nixosconf.pkgs;
|
||||||
build = nixosconf.config.system.build;
|
build = nixosconf.config.system.build;
|
||||||
in pkgs.mkShell {
|
in syspkgs.mkShell {
|
||||||
pname = "lagarto-hun-shell";
|
pname = "lagarto-hun-shell";
|
||||||
|
COMMIT = if self ? rev then self.rev else "dirty";
|
||||||
TOPLEVEL = build.toplevel;
|
TOPLEVEL = build.toplevel;
|
||||||
OPENSBI = syspkgs.opensbi;
|
OPENSBI = syspkgs.opensbi;
|
||||||
KERNEL = build.kernel;
|
KERNEL = build.kernel;
|
||||||
INITRD = build.initialRamdisk;
|
INITRD = build.initialRamdisk;
|
||||||
ROOTFS = build.sdImage;
|
ROOTFS = build.sdImage;
|
||||||
UBOOT_ENV = syspkgs.uboot-env;
|
UBOOT_ENV = syspkgs.uboot-env;
|
||||||
|
shellHook = ''
|
||||||
|
echo "Here are the current system pieces:"
|
||||||
|
echo " COMMIT = $COMMIT"
|
||||||
|
echo " TOPLEVEL = $TOPLEVEL"
|
||||||
|
echo " KERNEL = $KERNEL"
|
||||||
|
echo " OPENSBI = $OPENSBI"
|
||||||
|
echo " INITRD = $INITRD"
|
||||||
|
echo " ROOTFS = $ROOTFS"
|
||||||
|
echo " UBOOT_ENV = $UBOOT_ENV"
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
devShells.x86_64-linux.lagarto-ox =
|
||||||
|
let
|
||||||
|
nixosconf = self.nixosConfigurations.lagarto-ox;
|
||||||
|
syspkgs = nixosconf.pkgs;
|
||||||
|
build = nixosconf.config.system.build;
|
||||||
|
in syspkgs.mkShell rec {
|
||||||
|
pname = "lagarto-ox-shell";
|
||||||
|
COMMIT = if self ? rev then self.rev else "dirty";
|
||||||
|
TOPLEVEL = build.toplevel;
|
||||||
|
OPENSBI = syspkgs.opensbi;
|
||||||
|
KERNEL = build.kernel;
|
||||||
|
INITRD = build.initialRamdisk;
|
||||||
|
ROOTFS = build.sdImage;
|
||||||
|
UBOOT_ENV = syspkgs.uboot-env;
|
||||||
|
BITSTREAM = syspkgs.bitstream;
|
||||||
|
BOOTROM = syspkgs.bootrom;
|
||||||
|
GCROOT = mkRoots syspkgs [
|
||||||
|
syspkgs.stdenv KERNEL OPENSBI syspkgs.riscv-tools
|
||||||
|
];
|
||||||
|
shellHook = ''
|
||||||
|
echo "Here are the current system pieces:"
|
||||||
|
echo " COMMIT = $COMMIT"
|
||||||
|
echo " TOPLEVEL = $TOPLEVEL"
|
||||||
|
echo " KERNEL = $KERNEL"
|
||||||
|
echo " OPENSBI = $OPENSBI"
|
||||||
|
echo " INITRD = $INITRD"
|
||||||
|
echo " ROOTFS = $ROOTFS"
|
||||||
|
echo " UBOOT_ENV = $UBOOT_ENV"
|
||||||
|
echo " BITSTREAM = $BITSTREAM"
|
||||||
|
echo " BOOTROM = $BOOTROM"
|
||||||
|
echo " GCROOT = $GCROOT"
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
devShells.x86_64-linux.lagarto-ox-rd =
|
||||||
|
let
|
||||||
|
nixosconf = self.nixosConfigurations.lagarto-ox;
|
||||||
|
syspkgs = nixosconf.pkgs;
|
||||||
|
in self.outputs.devShells.x86_64-linux.lagarto-ox.overrideAttrs (old:{
|
||||||
|
TOPLEVEL = "";
|
||||||
|
ROOTFS = "";
|
||||||
|
GCROOT = mkRoots syspkgs [ syspkgs.stdenv old.OPENSBI ];
|
||||||
|
});
|
||||||
|
|
||||||
|
devShells.x86_64-linux.default =
|
||||||
|
self.outputs.devShells.x86_64-linux.lagarto-ox-rd;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
#!/usr/bin/bash
|
#!/usr/bin/bash
|
||||||
|
|
||||||
set -x
|
#set -x
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
source ./env.sh
|
source ./env.sh
|
||||||
|
|
||||||
#bitstream="-w system-acme_ea-4h2v.bit"
|
bitstream="-w bitstream.bit"
|
||||||
|
|
||||||
./fpgactl $bitstream -b opensbi.bin -k kernel.bin -i initrd.bin -r rootfs.img
|
./fpgactl $bitstream -R bootrom.bin -b opensbi.bin -k kernel.bin -i initrd.bin -r rootfs.img
|
||||||
|
|
||||||
picocom -b 115200 /dev/ttyUSB2
|
picocom -b 115200 $FPGACTL_UART
|
||||||
|
63
fpga/env.sh
63
fpga/env.sh
@ -1,21 +1,56 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
# Source this file to setup the environment
|
# Source this file to setup the environment
|
||||||
|
|
||||||
INSTALL_PATH=/home/tools
|
function setup_cucu()
|
||||||
LOAD_BITSTREAM=$INSTALL_PATH/scripts
|
{
|
||||||
HOSTNAME=$(hostname)
|
INSTALL_PATH=/home/tools
|
||||||
|
LOAD_BITSTREAM=$INSTALL_PATH/scripts
|
||||||
|
|
||||||
|
export DMA_IP_DRIVERS="$INSTALL_PATH/drivers/$hostname/dma_ip_drivers-onic-gamma/xilinx_pcie_drivers"
|
||||||
|
|
||||||
|
if [ ! -d $DMA_IP_DRIVERS ]; then
|
||||||
|
echo "error: DMA_IP_DRIVERS $DMA_IP_DRIVERS directory does not exist" >&2
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
export PATH="$DMA_IP_DRIVERS/QDMA/linux-kernel/bin/:$PATH"
|
||||||
|
|
||||||
|
if [ -x /opt/Xilinx/Vivado/2020.1/settings64.sh ]; then
|
||||||
|
source /opt/Xilinx/Vivado/2020.1/settings64.sh
|
||||||
|
elif [ -x /opt/Xilinx/Vivado/2021.2/settings64.sh ]; then
|
||||||
|
source /opt/Xilinx/Vivado/2021.2/settings64.sh
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
export DMA_IP_DRIVERS="$INSTALL_PATH/drivers/$HOSTNAME/dma_ip_drivers-onic-gamma/xilinx_pcie_drivers"
|
function setup_meep()
|
||||||
|
{
|
||||||
|
. /nfs/apps/XILINX/xilinx_22_env.sh
|
||||||
|
export PATH="$PATH:/apps/QDMA/meep-ionic/2022.1.4.4/linux-kernel/bin/"
|
||||||
|
|
||||||
if [ ! -d $DMA_IP_DRIVERS ]; then
|
# Select the first FPGA in the node
|
||||||
echo "error: DMA_IP_DRIVERS $DMA_IP_DRIVERS directory does not exist" >&2
|
local line=$(grep fpgan /etc/motd | sed -n 2p | tr -d ' ')
|
||||||
return
|
export FPGACTL_PCIDEV=$(echo "$line" | awk -F'|' '{print $5}')
|
||||||
fi
|
export FPGACTL_SERIAL=$(echo "$line" | awk -F'|' '{print $4}')
|
||||||
|
export FPGACTL_UART=$(echo "$line" | awk -F'|' '{print "/dev/"$7}')
|
||||||
|
|
||||||
export PATH="$DMA_IP_DRIVERS/QDMA/linux-kernel/bin/:$PATH"
|
# Setup mappings
|
||||||
|
|
||||||
if [ -x /opt/Xilinx/Vivado/2020.1/settings64.sh ]; then
|
# Delta between where we load in the dma device and RAM
|
||||||
source /opt/Xilinx/Vivado/2020.1/settings64.sh
|
local delta_addr=-0x60000000
|
||||||
elif [ -x /opt/Xilinx/Vivado/2021.2/settings64.sh ]; then
|
|
||||||
source /opt/Xilinx/Vivado/2021.2/settings64.sh
|
# See https://gitlab.bsc.es/hwdesign/fpga/integration-lab/fpga-tools/-/blob/6a63bcea6d1d59df3c7d62311aa4935efd54d3a3/boot_riscv/boot_sa.sh#L36-40
|
||||||
fi
|
export FPGACTL_BOOTLOADER_ADDR=$((0x80000000+$delta_addr))
|
||||||
|
export FPGACTL_KERNEL_ADDR=$((0x84000000+$delta_addr))
|
||||||
|
export FPGACTL_INITRD_ADDR=$((0x8c300000+$delta_addr))
|
||||||
|
export FPGACTL_ROOTFS_ADDR=$((0x1c0000000+$delta_addr))
|
||||||
|
export FPGACTL_BOOTROM_ADDR=$((0x00000100))
|
||||||
|
}
|
||||||
|
|
||||||
|
hostname=$(hostname)
|
||||||
|
|
||||||
|
case "$hostname" in
|
||||||
|
cucu) setup_cucu ;;
|
||||||
|
fpgan*) setup_meep ;;
|
||||||
|
*) echo "ERROR: unknown host $hostname";;
|
||||||
|
esac
|
||||||
|
273
fpga/fpgactl
273
fpga/fpgactl
@ -27,9 +27,7 @@ function check_environment() # {{{
|
|||||||
} # }}}
|
} # }}}
|
||||||
function create_qdma_queue() # {{{
|
function create_qdma_queue() # {{{
|
||||||
{
|
{
|
||||||
pcidir="/sys/bus/pci/devices/0000:08:00.0"
|
if [ ! -d "$pcidir" ]; then
|
||||||
|
|
||||||
if [ ! -d "$pcidir/qdma" ]; then
|
|
||||||
echo "missing pci directory: $pcidir" >&2
|
echo "missing pci directory: $pcidir" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@ -44,48 +42,71 @@ function create_qdma_queue() # {{{
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -c "/dev/qdma08000-MM-1" ]; then
|
if [ ! -r "$pcidir/qdma/qmax" ]; then
|
||||||
echo 2 | sudo dd of="$pcidir/qdma/qmax"
|
echo "cannot read qmax file: $pcidir/qdma/qmax" >&2
|
||||||
|
exit 1
|
||||||
dma-ctl qdma08000 q add mode mm idx 1 dir bi
|
|
||||||
dma-ctl qdma08000 q start idx 1 dir bi
|
|
||||||
|
|
||||||
sudo chmod go+rw "/dev/qdma08000-MM-1"
|
|
||||||
sudo chmod go+rw "$pcidir/resource0"
|
|
||||||
sudo chmod go+rw "$pcidir/resource0_wc"
|
|
||||||
sudo chmod go+rw "$pcidir/resource2"
|
|
||||||
sudo chmod go+rw "$pcidir/resource2_wc"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -c "/dev/qdma08000-MM-0" ]; then
|
# There should be two queues
|
||||||
dma-ctl qdma08000 q add mode mm idx 0 dir bi
|
local qmax=$(cat "$pcidir/qdma/qmax")
|
||||||
dma-ctl qdma08000 q start idx 0 dir bi
|
if [ "$qmax" != 2 ]; then
|
||||||
sudo chmod go+rw "/dev/qdma08000-MM-0"
|
if [ -w "$pcidir/qdma/qmax" ]; then
|
||||||
|
echo 2 | dd of="$pcidir/qdma/qmax"
|
||||||
|
else
|
||||||
|
echo 2 | sudo dd of="$pcidir/qdma/qmax"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Create the two queues if they don't exist
|
||||||
|
if [ ! -c "/dev/${qdmadev}-MM-1" ]; then
|
||||||
|
dma-ctl "${qdmadev}" q add mode mm idx 1 dir bi
|
||||||
|
dma-ctl "${qdmadev}" q start idx 1 dir bi
|
||||||
|
fi
|
||||||
|
if [ ! -c "/dev/${qdmadev}-MM-0" ]; then
|
||||||
|
dma-ctl "${qdmadev}" q add mode mm idx 0 dir bi
|
||||||
|
dma-ctl "${qdmadev}" q start idx 0 dir bi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Wait for udev to process the new devices
|
||||||
|
udevadm settle
|
||||||
|
|
||||||
|
# Ensure we have write access. On some clusters this is automatically done
|
||||||
|
# by udev rules, on others we are expect to use sudo.
|
||||||
|
for f in /dev/${qdmadev}-MM-{0,1} ${pcidir}/resource{0,0_wc,2,2_wc}; do
|
||||||
|
test -w "$f" || sudo chmod go+rw "$f"
|
||||||
|
done
|
||||||
|
|
||||||
sleep 2
|
sleep 2
|
||||||
} # }}}
|
} # }}}
|
||||||
function do_system_reset() # {{{
|
function do_cpu_reset() # {{{
|
||||||
{
|
{
|
||||||
# UartBootEn (bit2) + system reset (bit0)
|
if [ "$model" == "hun" ]; then
|
||||||
dma-ctl qdma08000 reg write bar 2 0x0 0x0 > /dev/null
|
# UartBootEn (bit2) + system reset (bit0)
|
||||||
sleep 0.2
|
dma-ctl "${qdmadev}" reg write bar 2 0x0 0x0
|
||||||
# Release system reset, we must wait until the memory is filled with 0s
|
sleep 0.2
|
||||||
dma-ctl qdma08000 reg write bar 2 0x0 0x1 > /dev/null
|
dma-ctl "${qdmadev}" reg write bar 2 0x0 0x1
|
||||||
#sleep 5
|
elif [ "$model" == "ox" ]; then
|
||||||
|
dma-ctl "${qdmadev}" reg write bar 2 0x0 0x0
|
||||||
|
sleep 0.2
|
||||||
|
fi
|
||||||
} # }}}
|
} # }}}
|
||||||
function do_system_release() # {{{
|
function do_cpu_release() # {{{
|
||||||
{
|
{
|
||||||
# Release Ariane's reset
|
if [ "$model" == "hun" ]; then
|
||||||
dma-ctl qdma08000 reg write bar 2 0x0 0x3 > /dev/null
|
# Release Ariane's reset
|
||||||
|
dma-ctl "${qdmadev}" reg write bar 2 0x0 0x3
|
||||||
|
elif [ "$model" == "ox" ]; then
|
||||||
|
dma-ctl "${qdmadev}" reg write bar 2 0x0 0x1
|
||||||
|
fi
|
||||||
} # }}}
|
} # }}}
|
||||||
function copy_by_dma() # {{{
|
function copy_by_dma() # {{{
|
||||||
{
|
{
|
||||||
ifile="$1"
|
ifile="$1"
|
||||||
address="$2"
|
address="$2"
|
||||||
|
|
||||||
ofile="/dev/qdma08000-MM-1"
|
ofile="/dev/${qdmadev}-MM-1"
|
||||||
bs=$((8*1024*1024)) # 8 MiB
|
#bs=$((8*1024*1024)) # 8 MiB
|
||||||
|
bs=$((1*1024*1024)) # 1 MiB
|
||||||
|
|
||||||
total_size=$(stat --format "%s" "$ifile")
|
total_size=$(stat --format "%s" "$ifile")
|
||||||
|
|
||||||
@ -101,6 +122,7 @@ function copy_by_dma() # {{{
|
|||||||
dd if="$ifile" skip=$skip count=1 bs=$bs of="$ofile" seek=$dst oflag=seek_bytes status=none
|
dd if="$ifile" skip=$skip count=1 bs=$bs of="$ofile" seek=$dst oflag=seek_bytes status=none
|
||||||
let skip=$skip+1
|
let skip=$skip+1
|
||||||
done
|
done
|
||||||
|
#dma-to-device -d "$ofile" -s "$total_size" -a "$address" -f "$ifile"
|
||||||
|
|
||||||
} # }}}
|
} # }}}
|
||||||
function load_file_in_memory() # {{{
|
function load_file_in_memory() # {{{
|
||||||
@ -110,23 +132,24 @@ function load_file_in_memory() # {{{
|
|||||||
address=$(($address_hex))
|
address=$(($address_hex))
|
||||||
|
|
||||||
total_size=$(stat --format "%s" "$file")
|
total_size=$(stat --format "%s" "$file")
|
||||||
|
md5sum=$(md5sum "$file" | cut -d' ' -f1)
|
||||||
|
|
||||||
# Previous tests...
|
# Previous tests...
|
||||||
#strace -f dma-to-device -d /dev/qdma08000-MM-1 -a "$address" -s $((8*1024*1024)) -f "$file"
|
#strace -f dma-to-device -d /dev/${qdmadev}-MM-1 -a "$address" -s $((8*1024*1024)) -f "$file"
|
||||||
#strace -f dd if="$file" bs=16M seek="${address}" oflag=seek_bytes of=/dev/qdma08000-MM-1 status=progress conv=sync
|
#strace -f dd if="$file" bs=16M seek="${address}" oflag=seek_bytes of=/dev/${qdmadev}-MM-1 status=progress conv=sync
|
||||||
#strace -f fpgakit/fpgadd -i "$file" -a "$address" -d /dev/qdma08000-MM-1 -c 1024 -s 1024
|
#strace -f fpgakit/fpgadd -i "$file" -a "$address" -d /dev/${qdmadev}-MM-1 -c 1024 -s 1024
|
||||||
#ID=08 ./load_image.sh "$file" "$address"
|
#ID=08 ./load_image.sh "$file" "$address"
|
||||||
|
|
||||||
# Now dd seems to work fine, but I will leave this as fallback:
|
# Now dd seems to work fine, but I will leave this as fallback:
|
||||||
copy_by_dma "$file" "$address"
|
copy_by_dma "$file" "$address"
|
||||||
|
|
||||||
#dd if="$file" bs=8M seek="${address}" oflag=seek_bytes of=/dev/qdma08000-MM-1 status=none
|
#dd if="$file" bs=8M seek="${address}" oflag=seek_bytes of=/dev/${qdmadev}-MM-1 status=none
|
||||||
|
|
||||||
printf "loaded '%s' at 0x%x with size %d\n" "$file" "$address" "$total_size" >&2
|
printf "loaded '%s' at 0x%x with size %d and md5 %s\n" "$file" "$address" "$total_size" "$md5sum" >&2
|
||||||
} # }}}
|
} # }}}
|
||||||
function do_boot_only() # {{{
|
function do_boot_only() # {{{
|
||||||
{
|
{
|
||||||
do_system_reset
|
do_cpu_reset
|
||||||
|
|
||||||
./load_image.sh ${OSBI} $((0x80000000)) &&
|
./load_image.sh ${OSBI} $((0x80000000)) &&
|
||||||
|
|
||||||
@ -135,7 +158,7 @@ function do_boot_only() # {{{
|
|||||||
sleep 2 &&
|
sleep 2 &&
|
||||||
|
|
||||||
# #Release Ariane's reset
|
# #Release Ariane's reset
|
||||||
dma-ctl qdma08000 reg write bar 2 0x0 0x3 &&
|
dma-ctl "${qdmadev}" reg write bar 2 0x0 0x3 &&
|
||||||
|
|
||||||
sleep 10 &&
|
sleep 10 &&
|
||||||
|
|
||||||
@ -143,7 +166,7 @@ function do_boot_only() # {{{
|
|||||||
|
|
||||||
echo mount -o nolock -o rw -o retrans=10 192.168.0.16:/media/sda2/scratch/xavim/point /root &&
|
echo mount -o nolock -o rw -o retrans=10 192.168.0.16:/media/sda2/scratch/xavim/point /root &&
|
||||||
|
|
||||||
if [ ! -c /dev/qdma08000-MM-0 ] ; then
|
if [ ! -c "/dev/${qdmadev}-MM-0" ] ; then
|
||||||
/home/tools/drivers/`/bin/hostname`/dma_ip_drivers-onic-gamma/create-queue-qdma.sh -2
|
/home/tools/drivers/`/bin/hostname`/dma_ip_drivers-onic-gamma/create-queue-qdma.sh -2
|
||||||
fi &&
|
fi &&
|
||||||
|
|
||||||
@ -155,7 +178,7 @@ function do_boot_only() # {{{
|
|||||||
} # }}}
|
} # }}}
|
||||||
function do_reload_fs() # {{{
|
function do_reload_fs() # {{{
|
||||||
{
|
{
|
||||||
do_system_reset
|
do_cpu_reset
|
||||||
|
|
||||||
#~xavim/LAGARTO_LINUX-4.1/./load_image.sh \
|
#~xavim/LAGARTO_LINUX-4.1/./load_image.sh \
|
||||||
# /home/xavim/ARIANE_LINUX-3.0/recovery/fedora-fs-dx-java-cucu-0.108.raw.recovered \
|
# /home/xavim/ARIANE_LINUX-3.0/recovery/fedora-fs-dx-java-cucu-0.108.raw.recovered \
|
||||||
@ -172,7 +195,7 @@ function do_reload_fs() # {{{
|
|||||||
|
|
||||||
sleep 2
|
sleep 2
|
||||||
|
|
||||||
do_system_release
|
do_cpu_release
|
||||||
create_qdma_queue
|
create_qdma_queue
|
||||||
|
|
||||||
# uncomment to enable eth-over-pcie
|
# uncomment to enable eth-over-pcie
|
||||||
@ -180,23 +203,25 @@ function do_reload_fs() # {{{
|
|||||||
} # }}}
|
} # }}}
|
||||||
function upload_bitstream_file() # {{{
|
function upload_bitstream_file() # {{{
|
||||||
{
|
{
|
||||||
bitfile="$1"
|
if [ -z "$jtagserial" ]; then
|
||||||
|
>&2 echo "JTAG serial required"
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
fpgajtag=$(lsusb -vd 0403: 2>&1 | grep iSerial | awk ' { print $3; }')
|
if [ -z "$bitstream" ]; then
|
||||||
if [ -z "$fpgajtag" ]; then
|
>&2 echo "bitstream file required"
|
||||||
echo "error: cannot find JTAG serial" >&2
|
usage
|
||||||
exit 1
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
script=$(mktemp vivado-XXXXXXXXXX.tcl)
|
script=$(mktemp vivado-XXXXXXXXXX.tcl)
|
||||||
cat > "$script" <<EOF
|
cat > "$script" <<EOF
|
||||||
open_hw_manager
|
open_hw_manager
|
||||||
connect_hw_server -url localhost:3121
|
connect_hw_server -url localhost:3121
|
||||||
current_hw_target "localhost:3121/xilinx_tcf/Xilinx/${fpgajtag}A"
|
current_hw_target "localhost:3121/xilinx_tcf/Xilinx/${jtagserial}A"
|
||||||
open_hw_target
|
open_hw_target
|
||||||
set dev [lindex [get_hw_devices] 0]
|
set dev [lindex [get_hw_devices] 0]
|
||||||
current_hw_device \$dev
|
current_hw_device \$dev
|
||||||
set_property PROGRAM.FILE ${bitfile} \$dev
|
set_property PROGRAM.FILE ${bitstream} \$dev
|
||||||
program_hw_devices \$dev
|
program_hw_devices \$dev
|
||||||
exit
|
exit
|
||||||
EOF
|
EOF
|
||||||
@ -213,7 +238,7 @@ function unload_modules() # {{{
|
|||||||
# Unload modules
|
# Unload modules
|
||||||
for mod in $drvlist; do
|
for mod in $drvlist; do
|
||||||
if is_module_loaded "$mod"; then
|
if is_module_loaded "$mod"; then
|
||||||
sudo rmmod $mod
|
sudo rmmod $mod
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
@ -223,14 +248,22 @@ function remove_pci_devices() # {{{
|
|||||||
for slot in $(lspci -mm -d 10ee: | awk '{printf "0000:%s\n",$1}'); do
|
for slot in $(lspci -mm -d 10ee: | awk '{printf "0000:%s\n",$1}'); do
|
||||||
devdir="/sys/bus/pci/devices/$slot"
|
devdir="/sys/bus/pci/devices/$slot"
|
||||||
if [ -d $devdir ]; then
|
if [ -d $devdir ]; then
|
||||||
echo 1 | sudo dd "of=$devdir/remove"
|
if [ -w "$devdir/remove" ]; then
|
||||||
|
echo 1 | dd "of=$devdir/remove"
|
||||||
|
else
|
||||||
|
echo 1 | sudo dd "of=$devdir/remove"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
} # }}}
|
} # }}}
|
||||||
function rescan_pci_devices() # {{{
|
function rescan_pci_devices() # {{{
|
||||||
{
|
{
|
||||||
echo 1 | sudo dd of=/sys/bus/pci/rescan
|
if [ -w /sys/bus/pci/rescan ]; then
|
||||||
|
echo 1 | dd of=/sys/bus/pci/rescan
|
||||||
|
else
|
||||||
|
echo 1 | sudo dd of=/sys/bus/pci/rescan
|
||||||
|
fi
|
||||||
} # }}}
|
} # }}}
|
||||||
function load_qdma_modules() # {{{
|
function load_qdma_modules() # {{{
|
||||||
{
|
{
|
||||||
@ -245,21 +278,91 @@ function load_qdma_modules() # {{{
|
|||||||
sudo insmod "$drv" "hw_buffers=$hw_buffers"
|
sudo insmod "$drv" "hw_buffers=$hw_buffers"
|
||||||
sleep 4
|
sleep 4
|
||||||
} # }}}
|
} # }}}
|
||||||
|
function select_pcidev() # {{{
|
||||||
|
{
|
||||||
|
if [ -z "$pcidev" ]; then
|
||||||
|
>&2 echo -e "error: missing PCI device (hint: lspci -d 10ee:902f)"
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ensure it is ok
|
||||||
|
local matches=$(lspci -s "$pcidev")
|
||||||
|
if [ -z "$matches" ]; then
|
||||||
|
>&2 echo "no match for PCI device '$pcidev'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local n="$(echo "$matches" | wc -l)"
|
||||||
|
if [ "$n" -gt 1 ]; then
|
||||||
|
>&2 echo "multiple matches for PCI device '$pcidev'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Fill the PCI device with the domain
|
||||||
|
local fulldev=$(lspci -s "$pcidev" -D | cut -d' ' -f1)
|
||||||
|
pcidir="/sys/bus/pci/devices/$fulldev"
|
||||||
|
|
||||||
|
if [ ! -d "$pcidir" ]; then
|
||||||
|
>&2 echo "cannot find PCI dir: $pcidir"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set the PCI device to the full device
|
||||||
|
pcidev="$fulldev"
|
||||||
|
|
||||||
|
# Find slot
|
||||||
|
slot=$(lspci -s "$pcidev" -vm | grep PhySlot | cut -f2)
|
||||||
|
|
||||||
|
if [ -z "$slot" ]; then
|
||||||
|
>&2 echo "cannot find physical slot for PCI '$pcidev'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local devid=$(echo "$pcidev" | cut -d: -f2- | tr -d ':.')
|
||||||
|
qdmadev="qdma${devid}"
|
||||||
|
|
||||||
|
} # }}}
|
||||||
|
function preload_hook() #{{{
|
||||||
|
{
|
||||||
|
case "$hostname" in
|
||||||
|
cucu)
|
||||||
|
unload_modules "xocl xclmgmt qdma_pf xdma" # qdma_vf not removable
|
||||||
|
remove_pci_devices
|
||||||
|
;;
|
||||||
|
fpgan*)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "hostname $hostname not known"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
} #}}}
|
||||||
|
function postload_hook() #{{{
|
||||||
|
{
|
||||||
|
rescan_pci_devices
|
||||||
|
|
||||||
|
case "$hostname" in
|
||||||
|
cucu)
|
||||||
|
unload_modules "qdma_pf xdma" # qdma_vf not removable
|
||||||
|
remove_pci_devices
|
||||||
|
load_qdma_modules
|
||||||
|
rescan_pci_devices
|
||||||
|
;;
|
||||||
|
fpgan*)
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "hostname $hostname not known"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
create_qdma_queue
|
||||||
|
} #}}}
|
||||||
function load_bitstream() # {{{
|
function load_bitstream() # {{{
|
||||||
{
|
{
|
||||||
bitstream="$1"
|
preload_hook
|
||||||
|
upload_bitstream_file
|
||||||
unload_modules "xocl xclmgmt qdma_pf xdma" # qdma_vf not removable
|
postload_hook
|
||||||
remove_pci_devices
|
|
||||||
|
|
||||||
upload_bitstream_file "$bitstream"
|
|
||||||
|
|
||||||
rescan_pci_devices
|
|
||||||
unload_modules "qdma_pf xdma" # qdma_vf not removable
|
|
||||||
remove_pci_devices
|
|
||||||
load_qdma_modules
|
|
||||||
rescan_pci_devices
|
|
||||||
create_qdma_queue
|
|
||||||
} # }}}
|
} # }}}
|
||||||
|
|
||||||
bitstream=
|
bitstream=
|
||||||
@ -267,34 +370,51 @@ bootloader=
|
|||||||
kernel=
|
kernel=
|
||||||
initrd=
|
initrd=
|
||||||
rootfs=
|
rootfs=
|
||||||
|
bootrom=
|
||||||
resetcpu=
|
resetcpu=
|
||||||
verbose=
|
verbose=
|
||||||
|
pcidev=
|
||||||
|
model=ox
|
||||||
|
# Internal
|
||||||
|
slot=
|
||||||
|
pcidir=
|
||||||
|
qdmadev=
|
||||||
|
|
||||||
bootloader_addr=0x80000000
|
bootloader_addr="${FPGACTL_BOOTLOADER_ADDR:-0x80000000}"
|
||||||
kernel_addr=0x84000000
|
kernel_addr="${FPGACTL_KERNEL_ADDR:-0x84000000}"
|
||||||
initrd_addr=0x8c300000
|
initrd_addr="${FPGACTL_INITRD_ADDR:-0x8c300000}"
|
||||||
rootfs_addr=0x180000000
|
rootfs_addr="${FPGACTL_ROOTFS_ADDR:-0x140000000}"
|
||||||
|
bootrom_addr="${FPGACTL_BOOTROM_ADDR:-0x60000100}"
|
||||||
|
|
||||||
|
hostname="${hostname:-$(hostname)}"
|
||||||
|
echo "hostname=$hostname"
|
||||||
|
|
||||||
function usage()
|
function usage()
|
||||||
{
|
{
|
||||||
echo "" >&2
|
echo "" >&2
|
||||||
echo "Usage: $0 [-v] [-w bitstream] [-b bootloader] [-k kernel] [-i initrd]" >&2
|
echo "Usage: $0 [-p pcidev] [-v] [-w bitstream] [-j serial] [-b bootloader] [-k kernel] [-i initrd] [-R bootroom] " >&2
|
||||||
echo "" >&2
|
echo "" >&2
|
||||||
echo "First writes the bitstream if given. Then loads the rest of files" >&2
|
echo "First writes the bitstream if given. Then loads the rest of files" >&2
|
||||||
echo "into memory and restarts the CPU." >&2
|
echo "into memory and restarts the CPU." >&2
|
||||||
echo "" >&2
|
echo "" >&2
|
||||||
echo "Options" >&2
|
echo "Options" >&2
|
||||||
|
echo " -p pcidev Select PCI device (same format as lspci -s)." >&2
|
||||||
|
echo " Read from \$FPGACTL_PCIDEV if not given." >&2
|
||||||
echo " -w bitstream Write the bitstream file to the FPGA" >&2
|
echo " -w bitstream Write the bitstream file to the FPGA" >&2
|
||||||
|
echo " -j serial JTAG serial (can be found by lsusb -v)" >&2
|
||||||
|
echo " Read from \$FPGACTL_SERIAL if not given." >&2
|
||||||
echo " -b bootloader Load the bootloader file in $bootloader_addr" >&2
|
echo " -b bootloader Load the bootloader file in $bootloader_addr" >&2
|
||||||
echo " -k kernel Load the kernel file in $kernel_addr" >&2
|
echo " -k kernel Load the kernel file in $kernel_addr" >&2
|
||||||
echo " -i initrd Load the initrd file in $initrd_addr" >&2
|
echo " -i initrd Load the initrd file in $initrd_addr" >&2
|
||||||
echo " -r rootfs Load the rootfs file in $rootfs_addr" >&2
|
echo " -r rootfs Load the rootfs file in $rootfs_addr" >&2
|
||||||
|
echo " -R bootrom Load the bootrom file in $bootrom_addr" >&2
|
||||||
|
echo " -m model CPU model: Either 'hun' or 'ox' (default ox)" >&2
|
||||||
echo " -v Be verbose" >&2
|
echo " -v Be verbose" >&2
|
||||||
echo "" >&2
|
echo "" >&2
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
while getopts "hvw:b:k:i:r:" opt; do
|
while getopts "hvw:b:k:i:r:p:j:m:R:" opt; do
|
||||||
case "${opt}" in
|
case "${opt}" in
|
||||||
v) verbose=1 ;;
|
v) verbose=1 ;;
|
||||||
w) bitstream="${OPTARG}" ;;
|
w) bitstream="${OPTARG}" ;;
|
||||||
@ -302,21 +422,32 @@ while getopts "hvw:b:k:i:r:" opt; do
|
|||||||
k) kernel="${OPTARG}"; resetcpu=1 ;;
|
k) kernel="${OPTARG}"; resetcpu=1 ;;
|
||||||
i) initrd="${OPTARG}"; resetcpu=1 ;;
|
i) initrd="${OPTARG}"; resetcpu=1 ;;
|
||||||
r) rootfs="${OPTARG}"; resetcpu=1 ;;
|
r) rootfs="${OPTARG}"; resetcpu=1 ;;
|
||||||
|
R) bootrom="${OPTARG}"; resetcpu=1 ;;
|
||||||
|
p) pcidev="${OPTARG}" ;;
|
||||||
|
j) jtagserial="${OPTARG}" ;;
|
||||||
|
m) model="${OPTARG}" ;;
|
||||||
h) usage ;;
|
h) usage ;;
|
||||||
*) usage ;;
|
*) usage ;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
|
jtagserial="${jtagserial:-$FPGACTL_SERIAL}"
|
||||||
|
pcidev="${pcidev:-$FPGACTL_PCIDEV}"
|
||||||
|
|
||||||
test "$verbose" && set -x
|
test "$verbose" && set -x
|
||||||
|
|
||||||
check_environment
|
check_environment
|
||||||
|
select_pcidev
|
||||||
|
|
||||||
test "$bitstream" && load_bitstream "$bitstream"
|
test "$bitstream" && load_bitstream "$bitstream"
|
||||||
test "$resetcpu" && do_system_reset
|
test "$resetcpu" && do_cpu_reset
|
||||||
test "$bootloader" && load_file_in_memory "$bootloader" $bootloader_addr
|
test "$bootloader" && load_file_in_memory "$bootloader" $bootloader_addr
|
||||||
test "$kernel" && load_file_in_memory "$kernel" $kernel_addr
|
test "$kernel" && load_file_in_memory "$kernel" $kernel_addr
|
||||||
test "$initrd" && load_file_in_memory "$initrd" $initrd_addr
|
test "$initrd" && load_file_in_memory "$initrd" $initrd_addr
|
||||||
test "$rootfs" && load_file_in_memory "$rootfs" $rootfs_addr
|
test "$rootfs" && load_file_in_memory "$rootfs" $rootfs_addr
|
||||||
test "$resetcpu" && do_system_release
|
test "$bootrom" && load_file_in_memory "$bootrom" $bootrom_addr
|
||||||
|
test "$resetcpu" && do_cpu_release
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
||||||
# vim:ts=2:sw=2:ai:foldmethod=marker:foldlevel=0:
|
# vim:ts=2:sw=2:ai:foldmethod=marker:foldlevel=0:
|
||||||
|
54
fpga/run-login.sh
Executable file
54
fpga/run-login.sh
Executable file
@ -0,0 +1,54 @@
|
|||||||
|
#!/usr/bin/bash
|
||||||
|
|
||||||
|
# There are several situations in which we may find the jobs:
|
||||||
|
# - There are no jobs queued or running
|
||||||
|
# - There is at least one job running
|
||||||
|
# - There is one job queued
|
||||||
|
# - There was a job running but ended and is now ending
|
||||||
|
|
||||||
|
set -x
|
||||||
|
set -e
|
||||||
|
|
||||||
|
path="$1"
|
||||||
|
allocated=
|
||||||
|
|
||||||
|
# First determine if we already have jobs already
|
||||||
|
n=$(squeue --me -lh | wc -l)
|
||||||
|
|
||||||
|
if [ "$n" -gt 1 ]; then
|
||||||
|
echo "Too many jobs queued already" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$n" == 0 ]; then
|
||||||
|
# No running jobs, so allocate a new job
|
||||||
|
salloc -N 1 --constraint=dmaqdma --no-shell -t 1-00
|
||||||
|
allocated=1
|
||||||
|
|
||||||
|
# Wait until the job is running
|
||||||
|
while [ "$n" != 1 ]; do
|
||||||
|
sleep 2
|
||||||
|
n=$(squeue --me -lh | grep RUNNING | wc -l)
|
||||||
|
done
|
||||||
|
else
|
||||||
|
# There is one job, ensure it is running
|
||||||
|
n=$(squeue --me -lh | grep RUNNING | wc -l)
|
||||||
|
|
||||||
|
if [ "$n" != 1 ]; then
|
||||||
|
echo "The job is not running, stopping" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If this point is reached there is one job running
|
||||||
|
|
||||||
|
host=$(squeue --me -h -o %N)
|
||||||
|
echo "Switching to $host"
|
||||||
|
|
||||||
|
# Continue the execution there
|
||||||
|
ssh "$host" "$path/run-node.sh" "$path"
|
||||||
|
|
||||||
|
# Cancel our job if it was successful
|
||||||
|
if [ "$allocated" ]; then
|
||||||
|
scancel --me
|
||||||
|
fi
|
38
fpga/run-node.sh
Executable file
38
fpga/run-node.sh
Executable file
@ -0,0 +1,38 @@
|
|||||||
|
#!/usr/bin/bash
|
||||||
|
|
||||||
|
#set -x
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "Hello from $(hostname)"
|
||||||
|
|
||||||
|
path="$1"
|
||||||
|
|
||||||
|
cd "$path"
|
||||||
|
|
||||||
|
# First kill any picocom instance
|
||||||
|
killall picocom || true
|
||||||
|
|
||||||
|
# Setup the environment
|
||||||
|
. env.sh
|
||||||
|
|
||||||
|
set -x
|
||||||
|
|
||||||
|
# Then perform the boot
|
||||||
|
./fpgactl -w bitstream.bit -b opensbi.bin -k kernel.bin -i initrd.bin -r rootfs.img
|
||||||
|
|
||||||
|
# Normal timeouts
|
||||||
|
timeout=$((30 * 60)) # Always stop after 30 min
|
||||||
|
timeout_silent=$((3 * 60)) # Stop if 3 min without output
|
||||||
|
|
||||||
|
# Timeouts for SPEC benchmarks
|
||||||
|
#timeout=$((12 * 60 * 60)) # Always stop after 12 h
|
||||||
|
#timeout_silent=$((4 * 60 * 60)) # Stop if 4 h without output (some benchmarks take 1.6h)
|
||||||
|
|
||||||
|
# Set dead switch
|
||||||
|
sleep $timeout && killall picocom &
|
||||||
|
|
||||||
|
# Note: --imap igncr is broken so we replace it with LF.
|
||||||
|
# See https://github.com/npat-efault/picocom/pull/114
|
||||||
|
# It looks like picocom is abandoned, we may want to switch to minicom or
|
||||||
|
# stty+cat
|
||||||
|
picocom --imap crlf -q -x $(($timeout_silent*1000)) -b 115200 $FPGACTL_UART
|
22
fpga/run-remotely.sh
Executable file
22
fpga/run-remotely.sh
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Executes a pipeline in a remote machine taking the values from the environment
|
||||||
|
# Usage fpga/run-remotely.sh <host>:<path>
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
dst=fpgalogin1:nixos
|
||||||
|
|
||||||
|
if [ "$1" != "" ]; then
|
||||||
|
dst="$1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
path=${dst#*:}
|
||||||
|
|
||||||
|
# Copy all required elements to the destination machine
|
||||||
|
fpga/upload.sh "$dst"
|
||||||
|
|
||||||
|
# Launch the pipeline from there
|
||||||
|
set +x
|
||||||
|
#ssh fpgalogin1 "$path/run-login.sh" "$path" | awk -f fpga/verify.awk
|
||||||
|
ssh fpgalogin1 "$path/run-login.sh" "$path"
|
@ -3,15 +3,28 @@
|
|||||||
set -e
|
set -e
|
||||||
set -x
|
set -x
|
||||||
|
|
||||||
dst=femu:nixos/
|
#dst=femu:nixos
|
||||||
|
dst=fpgalogin1:nixos
|
||||||
|
|
||||||
rsync -a fpga/fpgactl "$dst"
|
if [ "$1" != "" ]; then
|
||||||
rsync -a fpga/boot.sh "$dst"
|
dst="$1"
|
||||||
rsync -a fpga/env.sh "$dst"
|
fi
|
||||||
rsync "$OPENSBI/share/opensbi/lp64/fpga/openpiton/firmware/fw_payload.bin" "$dst/opensbi.bin"
|
|
||||||
|
rsync -a fpga/run-login.sh "$dst/"
|
||||||
|
rsync -a fpga/run-node.sh "$dst/"
|
||||||
|
rsync -a fpga/fpgactl "$dst/"
|
||||||
|
rsync -a fpga/boot.sh "$dst/"
|
||||||
|
rsync -a fpga/env.sh "$dst/"
|
||||||
|
rsync $(find "$OPENSBI" -name fw_payload.bin) "$dst/opensbi.bin"
|
||||||
rsync "$KERNEL/Image" "$dst/kernel.bin"
|
rsync "$KERNEL/Image" "$dst/kernel.bin"
|
||||||
rsync "$INITRD/initrd" "$dst/initrd.bin"
|
rsync "$INITRD/initrd" "$dst/initrd.bin"
|
||||||
rsync "$ROOTFS/sd-image/rootfs.img" "$dst/rootfs.img"
|
if [ -n "$ROOTFS" ]; then
|
||||||
|
rsync "$ROOTFS/sd-image/rootfs.img" "$dst/rootfs.img"
|
||||||
|
else
|
||||||
|
echo "Skipping rootfs"
|
||||||
|
fi
|
||||||
|
rsync "$BITSTREAM" "$dst/bitstream.bit"
|
||||||
|
rsync "$BOOTROM" "$dst/bootrom.bin"
|
||||||
rsync "$UBOOT_ENV" "$dst/uboot.env"
|
rsync "$UBOOT_ENV" "$dst/uboot.env"
|
||||||
|
|
||||||
echo "Now go to $dst and run ./boot.sh"
|
echo "Now go to $dst and run ./boot.sh"
|
||||||
|
20
fpga/verify.awk
Normal file
20
fpga/verify.awk
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
BEGIN {
|
||||||
|
bootrom_ok = 0
|
||||||
|
opensbi_ok = 0
|
||||||
|
test_ok = 0
|
||||||
|
}
|
||||||
|
/RBOOTROM/ { bootrom_ok = 1 }
|
||||||
|
/^OpenSBI v/ { opensbi_ok = 1 }
|
||||||
|
/^TEST-RESULT-OK/ { test_ok = 1 }
|
||||||
|
{ printf "line> "; print }
|
||||||
|
END {
|
||||||
|
printf "Test summary:\n"
|
||||||
|
printf " Bootrom: %s\n", bootrom_ok ? "OK" : "FAIL";
|
||||||
|
printf " OpenSBI: %s\n", opensbi_ok ? "OK" : "FAIL";
|
||||||
|
printf " Result: %s\n", test_ok ? "OK" : "FAIL";
|
||||||
|
|
||||||
|
if (test_ok)
|
||||||
|
exit 0;
|
||||||
|
else
|
||||||
|
exit 1;
|
||||||
|
}
|
@ -57,6 +57,12 @@
|
|||||||
serviceConfig.Restart = "always";
|
serviceConfig.Restart = "always";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# Disable hvc0 as it is racing for the same console
|
||||||
|
systemd.services."serial-getty@hvc0" = {
|
||||||
|
enable = lib.mkForce false;
|
||||||
|
wantedBy = lib.mkForce [ ];
|
||||||
|
};
|
||||||
|
|
||||||
sdImage = {
|
sdImage = {
|
||||||
# The image will be loaded as-is in memory, so no compression
|
# The image will be loaded as-is in memory, so no compression
|
||||||
compressImage = false;
|
compressImage = false;
|
||||||
@ -96,13 +102,13 @@
|
|||||||
initrd = "${config.system.build.initialRamdisk}/initrd";
|
initrd = "${config.system.build.initialRamdisk}/initrd";
|
||||||
in prev.runCommand "uboot.txt" {} ''
|
in prev.runCommand "uboot.txt" {} ''
|
||||||
cat > $out <<EOF
|
cat > $out <<EOF
|
||||||
# Create pmem
|
# Create pmem of 3 GiB [0x140000000, 0x200000000)
|
||||||
fdt mknode / pmem@0x180000000
|
fdt mknode / pmem@0x140000000
|
||||||
fdt set /pmem@0x180000000 compatible "pmem-region"
|
fdt set /pmem@0x140000000 compatible "pmem-region"
|
||||||
fdt set /pmem@0x180000000 reg <0x1 0x80000000 0x0 0x80000000>
|
fdt set /pmem@0x140000000 reg <0x1 0x40000000 0x0 0xc0000000>
|
||||||
|
|
||||||
# Reduce memory
|
# Reduce memory to 3 GiB [0x80000000, 0x140000000)
|
||||||
fdt set /memory@80000000 reg <0x00000000 0x80000000 0x00000001 0x00000000>
|
fdt set /memory@80000000 reg <0x0 0x80000000 0x0 0xc0000000>
|
||||||
|
|
||||||
# Set kernel options
|
# Set kernel options
|
||||||
setenv bootargs "root=/dev/ram0 loglevel=7 debug rw earlycon=sbi boot.trace console=hvc0 init=${init}"
|
setenv bootargs "root=/dev/ram0 loglevel=7 debug rw earlycon=sbi boot.trace console=hvc0 init=${init}"
|
||||||
@ -120,6 +126,7 @@
|
|||||||
"PLATFORM=fpga/openpiton"
|
"PLATFORM=fpga/openpiton"
|
||||||
"FW_PAYLOAD_PATH=${final.uboot}/u-boot-nodtb.bin"
|
"FW_PAYLOAD_PATH=${final.uboot}/u-boot-nodtb.bin"
|
||||||
];
|
];
|
||||||
|
patches = [ ./patches/opensbi-lagarto-hun.patch ];
|
||||||
});
|
});
|
||||||
}) ];
|
}) ];
|
||||||
}
|
}
|
||||||
|
617
lagarto-ox.nix
Normal file
617
lagarto-ox.nix
Normal file
@ -0,0 +1,617 @@
|
|||||||
|
{ config, lib, utils, pkgs, modulesPath, self, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
"${modulesPath}/installer/sd-card/sd-image.nix"
|
||||||
|
];
|
||||||
|
|
||||||
|
#nixpkgs.crossSystem = {
|
||||||
|
# system = "riscv64-linux";
|
||||||
|
# gcc.arch = "rv64imafd";
|
||||||
|
# gcc.tune = "generic";
|
||||||
|
#};
|
||||||
|
|
||||||
|
# We don't need any firmware
|
||||||
|
hardware.firmware = lib.mkForce [];
|
||||||
|
|
||||||
|
# Doesn't work, it gets activated via the kernel socket.
|
||||||
|
# # No need for udev
|
||||||
|
# services.udev.enable = false;
|
||||||
|
# systemd.suppressedSystemUnits = [
|
||||||
|
# "systemd-udev-trigger.service"
|
||||||
|
# ];
|
||||||
|
|
||||||
|
# Output the unit name so we can remove it
|
||||||
|
systemd.extraConfig = ''
|
||||||
|
StatusUnitFormat=name
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Prevent executing the nscd program as it seems to hang the CPU
|
||||||
|
system.activationScripts.users = lib.mkForce (
|
||||||
|
let
|
||||||
|
cfg = config.users;
|
||||||
|
spec = pkgs.writeText "users-groups.json" (builtins.toJSON {
|
||||||
|
inherit (cfg) mutableUsers;
|
||||||
|
users = lib.mapAttrsToList (_: u:
|
||||||
|
{
|
||||||
|
inherit (u)
|
||||||
|
name uid group description home homeMode createHome isSystemUser
|
||||||
|
password hashedPasswordFile hashedPassword
|
||||||
|
autoSubUidGidRange subUidRanges subGidRanges
|
||||||
|
initialPassword initialHashedPassword expires;
|
||||||
|
shell = utils.toShellPath u.shell;
|
||||||
|
}) cfg.users;
|
||||||
|
groups = lib.attrValues cfg.groups;
|
||||||
|
});
|
||||||
|
in
|
||||||
|
if !config.systemd.sysusers.enable then {
|
||||||
|
supportsDryActivation = true;
|
||||||
|
text = ''
|
||||||
|
install -m 0700 -d /root
|
||||||
|
install -m 0755 -d /home
|
||||||
|
|
||||||
|
${pkgs.perl.withPackages (p: [ p.FileSlurp p.JSON ])}/bin/perl \
|
||||||
|
-w ${./patches/update-users-groups.pl} ${spec}
|
||||||
|
'';
|
||||||
|
} else "" # keep around for backwards compatibility
|
||||||
|
);
|
||||||
|
|
||||||
|
# Also disable the nscd daemon
|
||||||
|
services.nscd.enable = false;
|
||||||
|
system.nssModules = lib.mkForce []; # Required
|
||||||
|
|
||||||
|
system.build.bootStage2 = let
|
||||||
|
useHostResolvConf = config.networking.resolvconf.enable && config.networking.useHostResolvConf;
|
||||||
|
bootStage2 = pkgs.substituteAll {
|
||||||
|
src = ./patches/stage-2-init.sh;
|
||||||
|
shellDebug = "${pkgs.bashInteractive}/bin/bash";
|
||||||
|
bashInteractive = "${pkgs.bashInteractive}";
|
||||||
|
bench2 = "${pkgs.bench2}";
|
||||||
|
shell = "${pkgs.bash}/bin/bash";
|
||||||
|
inherit (config.boot) readOnlyNixStore systemdExecutable extraSystemdUnitPaths;
|
||||||
|
inherit (config.system.nixos) distroName;
|
||||||
|
isExecutable = true;
|
||||||
|
inherit useHostResolvConf;
|
||||||
|
inherit (config.system.build) earlyMountScript;
|
||||||
|
path = lib.makeBinPath ([
|
||||||
|
pkgs.coreutils
|
||||||
|
pkgs.util-linux
|
||||||
|
pkgs.strace
|
||||||
|
] ++ lib.optional useHostResolvConf pkgs.openresolv);
|
||||||
|
postBootCommands = pkgs.writeText "local-cmds"
|
||||||
|
''
|
||||||
|
${config.boot.postBootCommands}
|
||||||
|
${config.powerManagement.powerUpCommands}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
in lib.mkForce bootStage2;
|
||||||
|
|
||||||
|
boot.kernelPackages = pkgs.linuxPackages_latest;
|
||||||
|
boot = {
|
||||||
|
extraModulePackages = [
|
||||||
|
# Add the custom Ethernet module
|
||||||
|
#pkgs.xilinx-axienet-carv
|
||||||
|
];
|
||||||
|
kernelModules = config.boot.initrd.kernelModules;
|
||||||
|
kernelPatches = [
|
||||||
|
{
|
||||||
|
name = assert false; "sbi-early-console";
|
||||||
|
patch = null;
|
||||||
|
extraConfig =
|
||||||
|
# Early console via SBI
|
||||||
|
''
|
||||||
|
RISCV_SBI y
|
||||||
|
RISCV_SBI_V01 y
|
||||||
|
SERIAL_EARLYCON y
|
||||||
|
SERIAL_EARLYCON_RISCV_SBI y
|
||||||
|
HVC_DRIVER y
|
||||||
|
HVC_RISCV_SBI y
|
||||||
|
''
|
||||||
|
# Enable console driver
|
||||||
|
+''
|
||||||
|
SERIAL_8250 y
|
||||||
|
SERIAL_8250_CONSOLE y
|
||||||
|
SERIAL_OF_PLATFORM y
|
||||||
|
CONSOLE_POLL y
|
||||||
|
''
|
||||||
|
# Allows regions of persistent memory to be described in the device-tree.
|
||||||
|
+ ''
|
||||||
|
OF_PMEM y
|
||||||
|
''
|
||||||
|
# Allow you to use a contiguous range of reserved memory as one or more
|
||||||
|
# persistent block devices (/dev/pmem0)
|
||||||
|
+ ''
|
||||||
|
LIBNVDIMM y
|
||||||
|
BLK_DEV_PMEM y
|
||||||
|
''
|
||||||
|
# No vector extensions
|
||||||
|
+ ''
|
||||||
|
RISCV_ISA_V n
|
||||||
|
RISCV_ISA_V_DEFAULT_ENABLE n
|
||||||
|
''
|
||||||
|
# Debugging
|
||||||
|
+ ''
|
||||||
|
DEBUG_KERNEL y
|
||||||
|
DEBUG_MISC y
|
||||||
|
DEBUG_WX y
|
||||||
|
MAGIC_SYSRQ y
|
||||||
|
SYSRQ_SERIAL y
|
||||||
|
DEBUG_VM y
|
||||||
|
SOFTLOCKUP_DETECTOR y
|
||||||
|
SOFTLOCKUP_DETECTOR_INTR_STORM y
|
||||||
|
HARDLOCKUP_DETECTOR y
|
||||||
|
DETECT_HUNG_TASK y
|
||||||
|
WQ_WATCHDOG y
|
||||||
|
WQ_CPU_INTENSIVE_REPORT y
|
||||||
|
TRACING y
|
||||||
|
BOOTTIME_TRACING y
|
||||||
|
STRICT_DEVMEM n
|
||||||
|
MMIOTRACE y
|
||||||
|
''
|
||||||
|
# Disable SMP so we don't have IPI
|
||||||
|
+ ''
|
||||||
|
SMP n
|
||||||
|
''
|
||||||
|
# SPI driver
|
||||||
|
+ ''
|
||||||
|
COMPILE_TEST y
|
||||||
|
SPI y
|
||||||
|
SPI_DAVINCI m
|
||||||
|
''
|
||||||
|
;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
initrd = {
|
||||||
|
# Avoid zstd as we don't have the tools in "cucu" machine
|
||||||
|
compressor = "gzip";
|
||||||
|
kernelModules = [
|
||||||
|
# DMA for Ethernet
|
||||||
|
#"xilinx_dma"
|
||||||
|
# Load the Ethernet module by default
|
||||||
|
#"xxvnet_carv"
|
||||||
|
|
||||||
|
# For SPI
|
||||||
|
"spi_davinci"
|
||||||
|
"spidev"
|
||||||
|
];
|
||||||
|
|
||||||
|
# Custom init script
|
||||||
|
extraFiles = {
|
||||||
|
"/shell".source = pkgs.writeScript "shell" ''
|
||||||
|
#!${config.system.build.extraUtils}/bin/ash
|
||||||
|
|
||||||
|
set -x
|
||||||
|
|
||||||
|
export PATH=${config.system.build.extraUtils}/bin
|
||||||
|
ash
|
||||||
|
'';
|
||||||
|
|
||||||
|
"/testplic".source = pkgs.writeScript "testplic" ''
|
||||||
|
#!${config.system.build.extraUtils}/bin/ash
|
||||||
|
export PATH=${config.system.build.extraUtils}/bin
|
||||||
|
|
||||||
|
set -x
|
||||||
|
|
||||||
|
(
|
||||||
|
echo "--- Testing threshold register init value"
|
||||||
|
# Ensure that reading a few times the threshold value
|
||||||
|
# always gives the same initial value 0
|
||||||
|
t1=$(devmem 0x40a00000) # Read context 1 threshold value
|
||||||
|
t2=$(devmem 0x40a00000) # Read context 1 threshold value
|
||||||
|
t3=$(devmem 0x40a00000) # Read context 1 threshold value
|
||||||
|
found="$t1 $t2 $t3"
|
||||||
|
expected="0x00000000 0x00000000 0x00000000"
|
||||||
|
if [ "$found" = "$expected" ]; then
|
||||||
|
echo "--- Threshold init value: OK"
|
||||||
|
else
|
||||||
|
echo "found =$found"
|
||||||
|
echo "expected=$expected"
|
||||||
|
echo "--- Threshold init value: FAIL"
|
||||||
|
fi
|
||||||
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
echo "--- Testing threshold register stability"
|
||||||
|
# Write the priority register of an interrupt and ensure
|
||||||
|
# the threshold register didn't change
|
||||||
|
devmem 0x40a00000 32 0 # Write context 1 threshold value 0
|
||||||
|
devmem 0x40800010 32 5 # Write source 4 priority value 5
|
||||||
|
t1=$(devmem 0x40a00000) # Read context 1 threshold value
|
||||||
|
t2=$(devmem 0x40a00000) # Read context 1 threshold value
|
||||||
|
found="$t1 $t2"
|
||||||
|
expected="0x00000000 0x00000000"
|
||||||
|
if [ "$found" = "$expected" ]; then
|
||||||
|
echo "--- Threshold stability: OK"
|
||||||
|
else
|
||||||
|
echo "found =$found"
|
||||||
|
echo "expected=$expected"
|
||||||
|
echo "--- Threshold stability: FAIL"
|
||||||
|
fi
|
||||||
|
)
|
||||||
|
|
||||||
|
(
|
||||||
|
echo "--- Testing claim register"
|
||||||
|
|
||||||
|
# Use aux timer on source 4 for this one
|
||||||
|
pending=$(devmem 0x40801000) # Dump pending bits of sources 0-31
|
||||||
|
|
||||||
|
# Ensure the aux timer is pending
|
||||||
|
if [ "$pending" = "0x00000010" ]; then
|
||||||
|
|
||||||
|
# Make sure the priority is higher than the threshold
|
||||||
|
devmem 0x40800010 32 0x10 # Write source 4 priority value 16
|
||||||
|
devmem 0x40802080 32 0x10 # Enable source 4 in context 1
|
||||||
|
# Writing the threshold has to be last, otherwise it will change
|
||||||
|
devmem 0x40a00000 32 0 # Write context 1 threshold value 0
|
||||||
|
c1=$(devmem 0x40a01004) # Claim context 1
|
||||||
|
c2=$(devmem 0x40a01004) # Claim context 1
|
||||||
|
c3=$(devmem 0x40a01004) # Claim context 1
|
||||||
|
found="$c1 $c2 $c3"
|
||||||
|
expected="0x00000004 0x00000004 0x00000004"
|
||||||
|
if [ "$found" = "$expected" ]; then
|
||||||
|
echo "--- Testing claim register: OK"
|
||||||
|
else
|
||||||
|
echo "found =$found"
|
||||||
|
echo "expected=$expected"
|
||||||
|
echo "--- Testing claim register: FAIL"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "unknown pending bits: $pending"
|
||||||
|
echo "--- Testing claim register: SKIP"
|
||||||
|
fi
|
||||||
|
)
|
||||||
|
set +x
|
||||||
|
#echo "all done, dropping to a shell..."
|
||||||
|
#ash
|
||||||
|
'';
|
||||||
|
|
||||||
|
"/preinit".source = pkgs.writeScript "preinit" ''
|
||||||
|
#!${config.system.build.extraUtils}/bin/ash
|
||||||
|
export PATH=${config.system.build.extraUtils}/bin
|
||||||
|
# csrtool all-in-order
|
||||||
|
|
||||||
|
# ip addr
|
||||||
|
# cat /proc/interrupts
|
||||||
|
|
||||||
|
# modprobe xxvnet_carv
|
||||||
|
|
||||||
|
# plictool -c2
|
||||||
|
# plictool -c2
|
||||||
|
# plictool -c2
|
||||||
|
|
||||||
|
# ip addr
|
||||||
|
|
||||||
|
exec /init
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
# Add riscv-tools to initrd
|
||||||
|
extraUtilsCommands = ''
|
||||||
|
cp -a ${pkgs.riscv-tools}/bin/* $out/bin
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Write a counter to the DMA region, so we can check the kernel is not
|
||||||
|
# dead. Monitor from the host with:
|
||||||
|
# while [ 1 ]; do xxd -s $((0x1bfff0000 - 0x60000000)) \
|
||||||
|
# -l 4 /dev/qdma34000-MM-1; sleep 0.2; done
|
||||||
|
preDeviceCommands = ''
|
||||||
|
# Seed RNG
|
||||||
|
seedrng -d /tmp || true
|
||||||
|
mv /tmp/seed.no-credit /tmp/seed.credit || true
|
||||||
|
seedrng -d /tmp || true
|
||||||
|
echo "Available entropy: $(cat /proc/sys/kernel/random/entropy_avail)"
|
||||||
|
|
||||||
|
# Last chance to enter a shell
|
||||||
|
if read -t 3 -p 'Press enter for shell... '; then
|
||||||
|
allowShell=1
|
||||||
|
fail
|
||||||
|
fi
|
||||||
|
|
||||||
|
# echo "Running tests..."
|
||||||
|
# sh /testplic
|
||||||
|
|
||||||
|
# echo "Creating a heartbeat counter at 0x1bfff0000"
|
||||||
|
# sh -c 'hb=0; while [ 1 ]; do let hb=$hb+1; devmem 0x1bfff0000 32 $hb; done' &
|
||||||
|
''
|
||||||
|
+
|
||||||
|
# Disable proactive compaction. May be better to disable CONFIG_COMPACTION.
|
||||||
|
''
|
||||||
|
echo 0 > /proc/sys/vm/compaction_proactiveness
|
||||||
|
''
|
||||||
|
# +
|
||||||
|
# # Show stacktrace on calls to the hvc_remove function.
|
||||||
|
# ''
|
||||||
|
# echo "Mount debugfs"
|
||||||
|
# mkdir -p /sys/kernel/debug/
|
||||||
|
# mount -t debugfs none /sys/kernel/debug/
|
||||||
|
# td=/sys/kernel/debug/tracing
|
||||||
|
# echo hvc_remove > $td/set_ftrace_filter
|
||||||
|
# echo function > $td/current_tracer
|
||||||
|
# echo 1 > $td/options/func_stack_trace
|
||||||
|
# ''
|
||||||
|
# FIXME: Disable sched_switch for now, as it still hangs the boot...
|
||||||
|
# +
|
||||||
|
# # Exclude the second pid, which is the kthread that will dump the trace to
|
||||||
|
# # the console, otherwise we live lock the kernel. Then enable the
|
||||||
|
# # sched_switch events.
|
||||||
|
# ''
|
||||||
|
# echo "Mount debugfs"
|
||||||
|
# mkdir -p /sys/kernel/debug/
|
||||||
|
# mount -t debugfs none /sys/kernel/debug/
|
||||||
|
# echo "Exclude pid 2 from sched"
|
||||||
|
# echo '(prev_pid != 2 && next_pid != 2)' > /sys/kernel/debug/tracing/events/sched/filter
|
||||||
|
# echo "Enable sched_switch events"
|
||||||
|
# echo 1 > /sys/kernel/debug/tracing/events/sched/sched_switch/enable
|
||||||
|
# ''
|
||||||
|
;
|
||||||
|
};
|
||||||
|
|
||||||
|
loader = {
|
||||||
|
grub.enable = false;
|
||||||
|
generic-extlinux-compatible.enable = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# No network
|
||||||
|
services.openssh.enable = false;
|
||||||
|
networking.useDHCP = false;
|
||||||
|
|
||||||
|
# Run getty on /dev/console and restartt until it works
|
||||||
|
systemd.services."serial-getty@console" = {
|
||||||
|
enable = true;
|
||||||
|
after = [ "network.target" ];
|
||||||
|
wantedBy = [ "getty.target" ]; # to start at boot
|
||||||
|
serviceConfig.Restart = "always";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Disable hvc0 as it is racing for the same console
|
||||||
|
systemd.services."serial-getty@hvc0" = {
|
||||||
|
enable = lib.mkForce false;
|
||||||
|
wantedBy = lib.mkForce [ ];
|
||||||
|
};
|
||||||
|
|
||||||
|
services.getty.autologinUser = lib.mkForce "root";
|
||||||
|
|
||||||
|
sdImage = {
|
||||||
|
# The image will be loaded as-is in memory, so no compression
|
||||||
|
compressImage = false;
|
||||||
|
imageName = "rootfs.img";
|
||||||
|
# Not needed for now
|
||||||
|
expandOnBoot = false;
|
||||||
|
populateFirmwareCommands = "";
|
||||||
|
populateRootCommands = ''
|
||||||
|
mkdir -p ./files/boot
|
||||||
|
${config.boot.loader.generic-extlinux-compatible.populateCmd} \
|
||||||
|
-c ${config.system.build.toplevel} \
|
||||||
|
-d ./files/boot
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
nixpkgs.overlays = [ (final: prev: {
|
||||||
|
#busybox = prev.busybox.overrideAttrs (old: {
|
||||||
|
# # Print some debug lines on switch_root to see where it hangs.
|
||||||
|
# patches = (old.patches or []) ++ [ ./patches/busybox-debug.patch ];
|
||||||
|
#});
|
||||||
|
|
||||||
|
linuxPackages_latest = prev.linuxPackages_latest;
|
||||||
|
#linuxPackages_latest = prev.linuxPackages_latest.extend (lib.const (ksuper: {
|
||||||
|
# kernel = ksuper.kernel.override {
|
||||||
|
# stdenv = prev.gcc8Stdenv;
|
||||||
|
# };
|
||||||
|
#}));
|
||||||
|
|
||||||
|
bench2 = final.writeShellScript "bench2" ''
|
||||||
|
# Performs minimal FS setup and runs the SPEC benchmark
|
||||||
|
mkdir /tmp /bin /root
|
||||||
|
mount -t tmpfs tmpfs /tmp
|
||||||
|
export TMPDIR=/tmp
|
||||||
|
# We need /bin/sh
|
||||||
|
ln -s $(which sh) /bin/sh
|
||||||
|
# Check CPU usage
|
||||||
|
vmstat 5 5
|
||||||
|
bash -x speclaunch
|
||||||
|
cat /tmp/spec/time.csv
|
||||||
|
# Give me a shell at the end
|
||||||
|
bash -l
|
||||||
|
'';
|
||||||
|
|
||||||
|
ox-dtb = prev.stdenv.mkDerivation rec {
|
||||||
|
name = "ox.dtb";
|
||||||
|
src = ./dts;
|
||||||
|
dontConfigure = true;
|
||||||
|
nativeBuildInputs = [ prev.buildPackages.dtc ];
|
||||||
|
buildPhase = ''
|
||||||
|
make lagarto_ox.dtb
|
||||||
|
'';
|
||||||
|
installPhase = ''
|
||||||
|
mkdir $out
|
||||||
|
cp lagarto_ox.* $out
|
||||||
|
'';
|
||||||
|
dontFixup = true;
|
||||||
|
hardeningDisable = [ "all" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
#bitstream = "${final.bitstreams}/lagarto-3-ox/gold.bit";
|
||||||
|
bitstream = "${final.bitstreams}/lagarto-3-ox/ox_u55c_87a14c32_fix_threshold.bit";
|
||||||
|
|
||||||
|
bootrom = "${final.rbootrom}/rbootrom.bin";
|
||||||
|
|
||||||
|
uboot = prev.ubootQemuRiscv64Smode.override {
|
||||||
|
filesToInstall = [ "u-boot-nodtb.bin" ];
|
||||||
|
#version = "2023.07.02-print-cpu-probe";
|
||||||
|
#src = builtins.fetchGit {
|
||||||
|
# url = "file:///home/Computational/rarias/riscv/u-boot";
|
||||||
|
# rev = "f80a22a480f0e4157647bacf90e663be457c72c4";
|
||||||
|
#};
|
||||||
|
patches = [
|
||||||
|
#./patches/u-boot-debug.patch
|
||||||
|
./patches/uboot-debug-ext-interrupts.patch
|
||||||
|
./patches/uboot-exception-extras.patch
|
||||||
|
];
|
||||||
|
# Copy our environment to board/emulation/qemu-riscv/environ.env
|
||||||
|
preConfigure = ''
|
||||||
|
cp ${final.uboot-env} board/emulation/qemu-riscv/environ.env
|
||||||
|
'';
|
||||||
|
#postConfigure = ''
|
||||||
|
# echo --------------------------- generated config:
|
||||||
|
# cat .config
|
||||||
|
# echo ---------------------------
|
||||||
|
#'';
|
||||||
|
#postBuild = ''
|
||||||
|
# echo --------------------------- generated env starts
|
||||||
|
# cat include/generated/env.in
|
||||||
|
# echo --------------------------- generated env ends
|
||||||
|
#'';
|
||||||
|
#
|
||||||
|
# CONFIG_SERIAL_PRESENT=n
|
||||||
|
# CONFIG_SYS_NS16550=n
|
||||||
|
extraConfig = ''
|
||||||
|
CONFIG_RISCV_ISA_C=n
|
||||||
|
CONFIG_REQUIRE_SERIAL_CONSOLE=n
|
||||||
|
CONFIG_SERIAL=y
|
||||||
|
CONFIG_SERIAL_PUTS=y
|
||||||
|
CONFIG_SHOW_BOOT_PROGRESS=y
|
||||||
|
CONFIG_SHOW_REGS=y
|
||||||
|
CONFIG_LIBCOMMON_SUPPORT=y
|
||||||
|
CONFIG_SERIAL_SEARCH_ALL=n
|
||||||
|
CONFIG_SERIAL_PROBE_ALL=n
|
||||||
|
CONFIG_OF_CONTROL=y
|
||||||
|
CONFIG_OF_EMBED=y
|
||||||
|
CONFIG_OF_HAS_PRIOR_STAGE=y
|
||||||
|
CONFIG_BLKMAP=y
|
||||||
|
CONFIG_CMD_BLKMAP=y
|
||||||
|
CONFIG_SBI_V01=y
|
||||||
|
CONFIG_DEBUG_UART=y
|
||||||
|
CONFIG_DEBUG_UART_ANNOUNCE=y
|
||||||
|
CONFIG_DEBUG_SBI_CONSOLE=y
|
||||||
|
CONFIG_SMP=n
|
||||||
|
CONFIG_TRACE_EARLY=y
|
||||||
|
CONFIG_CMD_MEMTEST=y
|
||||||
|
CONFIG_CMD_EXCEPTION=y
|
||||||
|
CONFIG_CMD_TIMER=y
|
||||||
|
CONFIG_ENV_SOURCE_FILE="environ"
|
||||||
|
''
|
||||||
|
# # Enable debug logs
|
||||||
|
# +
|
||||||
|
# ''
|
||||||
|
# CONFIG_LOG=y
|
||||||
|
# CONFIG_LOGLEVEL=9
|
||||||
|
# CONFIG_LOG_MAX_LEVEL=9
|
||||||
|
# CONFIG_LOG_DEFAULT_LEVEL=9
|
||||||
|
# ''
|
||||||
|
;
|
||||||
|
extraMakeFlags = [
|
||||||
|
#"V=1"
|
||||||
|
#"KCPPFLAGS=-DLOG_DEBUG"
|
||||||
|
#"EXT_DTB=${final.ox-dtb}/lagarto_ox.dtb"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
uboot-env = let
|
||||||
|
init = "${config.system.build.toplevel}/init";
|
||||||
|
initrd = "${config.system.build.initialRamdisk}/initrd";
|
||||||
|
# Create pmem of 3 GiB [0x140000000, 0x200000000)
|
||||||
|
#fdt mknode / pmem@0x140000000
|
||||||
|
#fdt set /pmem@0x140000000 compatible "pmem-region"
|
||||||
|
#fdt set /pmem@0x140000000 reg <0x1 0x40000000 0x0 0xc0000000>
|
||||||
|
|
||||||
|
# Reduce memory to 3 GiB [0x80000000, 0x140000000)
|
||||||
|
#fdt set /memory@80000000 reg <0x0 0x80000000 0x0 0xc0000000>
|
||||||
|
|
||||||
|
# Set kernel bootcmd options.
|
||||||
|
# rdinit=/preinit boot custom preinit script
|
||||||
|
# console=ttyS0,115200n8 use serial driver (slow)
|
||||||
|
# Systemd options
|
||||||
|
# systemd.log_level=debug
|
||||||
|
# systemd.log_target=console
|
||||||
|
# NixOS interesting options:
|
||||||
|
# debug1 enable debug shell in stage 1
|
||||||
|
# debug2 enable debug shell in stage 2 (custom)
|
||||||
|
# bench2 run benchmark on stage 2 (custom)
|
||||||
|
# boot.trace enable set -x in stage 1
|
||||||
|
# boot.tracedebug enable set -x in stage 2
|
||||||
|
# Ftrace interesting options:
|
||||||
|
# trace_event=initcall:* trace the init function of drivers
|
||||||
|
# trace_options=sym-addr display function address
|
||||||
|
# tp_printk write ftrace events to console
|
||||||
|
# trace_buf_size=1M set ftrace buffer to 1M
|
||||||
|
#
|
||||||
|
in prev.runCommand "uboot.txt" {} ''
|
||||||
|
cat > $out <<EOF
|
||||||
|
xtrace=yes
|
||||||
|
bootargs=root=/dev/ram0 loglevel=7 rw earlycon=sbi console=hvc0 debug2 init=${init}
|
||||||
|
ramdisk_size=$(stat --format %s $(readlink -f ${initrd}))
|
||||||
|
bootcmd=fdt print; booti \''${kernel_addr_r} \''${ramdisk_addr_r}:\''${ramdisk_size} \''${fdtcontroladdr}
|
||||||
|
EOF
|
||||||
|
'';
|
||||||
|
|
||||||
|
opensbi = prev.opensbi.overrideAttrs (old: rec {
|
||||||
|
#version = "1.4";
|
||||||
|
version = "1.5";
|
||||||
|
src = prev.fetchFromGitHub {
|
||||||
|
owner = "riscv-software-src";
|
||||||
|
repo = "opensbi";
|
||||||
|
rev = "v${version}";
|
||||||
|
#hash = "sha256-T8ZeAzjM9aeTXitjE7s+m+jjGGtDo2jK1qO5EuKiVLU="; #1.4
|
||||||
|
hash = "sha256-vK14P97FcaVz4GDr/0055Z6s/k7BPKPQGZ/MQxbOWu0="; #1.5
|
||||||
|
};
|
||||||
|
#NIX_DEBUG=5;
|
||||||
|
makeFlags = [
|
||||||
|
"PLATFORM=generic"
|
||||||
|
#"CONFIG_SBI_ECALL_RFENCE=n"
|
||||||
|
#"PLATFORM_RISCV_ISA=rv64imafd" # No compressed instructions
|
||||||
|
#"PLATFORM_RISCV_ISA=rv64g" # No compressed instructions
|
||||||
|
#"PLATFORM_RISCV_ABI=lp64d"
|
||||||
|
"FW_PAYLOAD_PATH=${final.uboot}/u-boot-nodtb.bin"
|
||||||
|
"FW_FDT_PATH=${final.ox-dtb}/lagarto_ox.dtb"
|
||||||
|
|
||||||
|
# Ensure it doesn't overlap from the 0x80200000 where the kernel will be
|
||||||
|
# placed.
|
||||||
|
"FW_PAYLOAD_FDT_ADDR=0xc0000000"
|
||||||
|
];
|
||||||
|
patches = [
|
||||||
|
#./patches/opensbi-timer-debug.patch # Print calls to machine trap
|
||||||
|
#./patches/opensbi-enable-meip.patch
|
||||||
|
#./patches/opensbi-enable-seip.patch
|
||||||
|
#./patches/opensbi-test-plic.patch # Working delegation test, disabled for now
|
||||||
|
./patches/opensbi-dump-mregs.patch
|
||||||
|
#./patches/opensbi-dont-delegate.patch
|
||||||
|
#./patches/ox-alveo-platform-plic.patch
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
# Custom kernel driver for the Ethernet
|
||||||
|
xilinx-axienet-carv = let
|
||||||
|
kernel = config.boot.kernelPackages.kernel;
|
||||||
|
in prev.stdenv.mkDerivation rec {
|
||||||
|
pname = "xilinx-axienet-carv";
|
||||||
|
version = src.shortRev;
|
||||||
|
src = builtins.fetchGit {
|
||||||
|
url = "git@gitlab-internal.bsc.es:meep/meep-os/lagarto-openpiton-sdk.git";
|
||||||
|
rev = "d2ae2e788bf1cc60676599184a9ec1128cc81d81";
|
||||||
|
ref = "master";
|
||||||
|
};
|
||||||
|
patches = [
|
||||||
|
./patches/ethernet-driver-poll.patch
|
||||||
|
./patches/ethernet-driver-build.patch
|
||||||
|
./patches/ethernet-driver-kbuild.patch
|
||||||
|
];
|
||||||
|
preConfigure = ''
|
||||||
|
export sourceRoot=$PWD/drivers
|
||||||
|
cd drivers
|
||||||
|
#rm Makefile
|
||||||
|
'';
|
||||||
|
|
||||||
|
nativeBuildInputs = kernel.moduleBuildDependencies;
|
||||||
|
makeFlags = kernel.makeFlags ++ [
|
||||||
|
"-C"
|
||||||
|
"${kernel.dev}/lib/modules/${kernel.modDirVersion}/build"
|
||||||
|
"M=$(PWD)"
|
||||||
|
];
|
||||||
|
buildFlags = [ "modules" ];
|
||||||
|
installFlags = [ "INSTALL_MOD_PATH=${placeholder "out"}" ];
|
||||||
|
installTargets = [ "modules_install" ];
|
||||||
|
};
|
||||||
|
}) ];
|
||||||
|
}
|
92
overlay.nix
92
overlay.nix
@ -3,5 +3,97 @@ final: prev:
|
|||||||
# Changes to packages from nixpkgs
|
# Changes to packages from nixpkgs
|
||||||
|
|
||||||
{
|
{
|
||||||
|
clangEpi = final.callPackage ./pkgs/llvm-epi/default.nix { openmp = null; };
|
||||||
|
clangEpiUnwrapped = final.callPackage ./pkgs/llvm-epi/clang.nix { };
|
||||||
|
stdenvClangEpi = final.stdenv.override { cc = final.buildPackages.clangEpi; allowedRequisites = null; };
|
||||||
|
|
||||||
|
rvb = final.callPackage ./pkgs/rvb/default.nix { };
|
||||||
|
rvb-clang = final.callPackage ./pkgs/rvb/default.nix { stdenv = final.stdenvClangEpi; };
|
||||||
|
stream = final.callPackage ./pkgs/stream/default.nix { };
|
||||||
|
|
||||||
|
spec-cpu-tools = final.callPackage ./pkgs/spec-cpu/tools.nix { };
|
||||||
|
spec-cpu = final.callPackage ./pkgs/spec-cpu/default.nix { };
|
||||||
|
spec-cpu-mini = final.callPackage ./pkgs/spec-cpu/mini.nix { };
|
||||||
|
specinvoke = final.callPackage ./pkgs/spec-cpu/specinvoke.nix { };
|
||||||
|
speclaunch = final.callPackage ./pkgs/spec-cpu/speclaunch.nix { };
|
||||||
|
spec-cpu-clang = final.callPackage ./pkgs/spec-cpu/default.nix { stdenv = final.stdenvClangEpi; };
|
||||||
|
|
||||||
|
blis = ((prev.blis.override {
|
||||||
|
blas64 = true;
|
||||||
|
withArchitecture = "generic";
|
||||||
|
}).overrideAttrs (old: {
|
||||||
|
nativeBuildInputs = (old.nativeBuildInputs or []) ++ [
|
||||||
|
prev.buildPackages.gfortran
|
||||||
|
];
|
||||||
|
})).overrideDerivation (old : {
|
||||||
|
configureFlags = [
|
||||||
|
"--enable-cblas"
|
||||||
|
"--blas-int-size=64"
|
||||||
|
"--enable-threading=openmp"
|
||||||
|
#"--build=x86_64-unknown-linux-gnu"
|
||||||
|
#"--host=riscv64-unknown-linux-gnu"
|
||||||
|
"generic"
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
riscv-tools = prev.pkgsStatic.stdenv.mkDerivation {
|
||||||
|
name = "riscv-tools";
|
||||||
|
src = ./tools;
|
||||||
|
makeFlags = [ "PREFIX=${placeholder "out"}" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
bitstreams = builtins.fetchGit {
|
||||||
|
url = "git@bscpm03.bsc.es:rarias/bitstreams.git";
|
||||||
|
rev = "2f899627a226890c6f9820aa44e34c2ecea03faf";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Baremetal tests for standalone FPGA
|
||||||
|
sa-fpga-tests = prev.pkgsStatic.stdenv.mkDerivation {
|
||||||
|
name = "sa-fpga-tests";
|
||||||
|
src = builtins.fetchGit {
|
||||||
|
url = "git@gitlab-internal.bsc.es:hwdesign/rtl/core-tile/sa-fpga.git";
|
||||||
|
rev = "720be4f1f5dd0ef963135992578be2ab55fb5537";
|
||||||
|
ref = "main";
|
||||||
|
};
|
||||||
|
dontConfigure = true;
|
||||||
|
patches = [
|
||||||
|
#./patches/sa-fpga-crt.patch
|
||||||
|
#./patches/sa-fpga-text-address.patch
|
||||||
|
./patches/sa-fpga-uart.patch
|
||||||
|
./patches/sa-fpga-plic-registers.patch
|
||||||
|
./patches/sa-fpga-add-plic-claim-test.patch
|
||||||
|
];
|
||||||
|
buildPhase = ''
|
||||||
|
cd fpga_core_bridge/simulator/tests/c_tests/
|
||||||
|
make RISCV_PREFIX=riscv64-unknown-linux-musl-
|
||||||
|
|
||||||
|
# Generate binary images to be loaded in memory
|
||||||
|
for f in *.riscv; do
|
||||||
|
# Don't copy 0x40000000 section
|
||||||
|
$OBJCOPY -R .tohost -O binary $f $f.bin
|
||||||
|
done
|
||||||
|
'';
|
||||||
|
installPhase = ''
|
||||||
|
ls -lah
|
||||||
|
make install install_dir=$out
|
||||||
|
cp -a *.bin $out
|
||||||
|
'';
|
||||||
|
dontFixup = true;
|
||||||
|
hardeningDisable = [ "all" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
rbootrom = prev.pkgsStatic.stdenv.mkDerivation {
|
||||||
|
name = "rbootrom";
|
||||||
|
src = ./bootrom;
|
||||||
|
dontConfigure = true;
|
||||||
|
buildPhase = ''
|
||||||
|
make
|
||||||
|
'';
|
||||||
|
installPhase = ''
|
||||||
|
mkdir $out
|
||||||
|
cp rbootrom.bin rbootrom.elf $out/
|
||||||
|
'';
|
||||||
|
dontFixup = true;
|
||||||
|
hardeningDisable = [ "all" ];
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
438
patches/alveo-uart-sbi-hack.patch
Normal file
438
patches/alveo-uart-sbi-hack.patch
Normal file
@ -0,0 +1,438 @@
|
|||||||
|
diff --git a/include/sbi_utils/serial/alveo_uart.h b/include/sbi_utils/serial/alveo_uart.h
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..0b6408c
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/include/sbi_utils/serial/alveo_uart.h
|
||||||
|
@@ -0,0 +1,13 @@
|
||||||
|
+/*
|
||||||
|
+ * SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#ifndef __SERIAL_ALVEO_UART_H__
|
||||||
|
+#define __SERIAL_ALVEO_UART_H__
|
||||||
|
+
|
||||||
|
+#include <sbi/sbi_types.h>
|
||||||
|
+
|
||||||
|
+int alveo_uart_init(unsigned long base, u32 in_freq, u32 baudrate, u32 reg_shift,
|
||||||
|
+ u32 reg_width, u32 reg_offset);
|
||||||
|
+
|
||||||
|
+#endif
|
||||||
|
diff --git a/lib/utils/serial/Kconfig b/lib/utils/serial/Kconfig
|
||||||
|
index e3589ca..b754c7c 100644
|
||||||
|
--- a/lib/utils/serial/Kconfig
|
||||||
|
+++ b/lib/utils/serial/Kconfig
|
||||||
|
@@ -84,6 +84,10 @@ config SERIAL_UART8250
|
||||||
|
bool "8250 UART support"
|
||||||
|
default n
|
||||||
|
|
||||||
|
+config SERIAL_ALVEO_UART
|
||||||
|
+ bool "ALveo UART support"
|
||||||
|
+ default n
|
||||||
|
+
|
||||||
|
config SERIAL_XILINX_UARTLITE
|
||||||
|
bool "Xilinx UART Lite support"
|
||||||
|
default n
|
||||||
|
diff --git a/lib/utils/serial/alveo_uart.c b/lib/utils/serial/alveo_uart.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..a351741
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/lib/utils/serial/alveo_uart.c
|
||||||
|
@@ -0,0 +1,123 @@
|
||||||
|
+/*
|
||||||
|
+ * SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <sbi/riscv_io.h>
|
||||||
|
+#include <sbi/sbi_console.h>
|
||||||
|
+#include <sbi_utils/serial/alveo_uart.h>
|
||||||
|
+
|
||||||
|
+/* clang-format off */
|
||||||
|
+
|
||||||
|
+#define UART_RBR_OFFSET 0 /* In: Recieve Buffer Register */
|
||||||
|
+#define UART_THR_OFFSET 0 /* Out: Transmitter Holding Register */
|
||||||
|
+#define UART_DLL_OFFSET 0 /* Out: Divisor Latch Low */
|
||||||
|
+#define UART_IER_OFFSET 1 /* I/O: Interrupt Enable Register */
|
||||||
|
+#define UART_DLM_OFFSET 1 /* Out: Divisor Latch High */
|
||||||
|
+#define UART_FCR_OFFSET 2 /* Out: FIFO Control Register */
|
||||||
|
+#define UART_IIR_OFFSET 2 /* I/O: Interrupt Identification Register */
|
||||||
|
+#define UART_LCR_OFFSET 3 /* Out: Line Control Register */
|
||||||
|
+#define UART_MCR_OFFSET 4 /* Out: Modem Control Register */
|
||||||
|
+#define UART_LSR_OFFSET 5 /* In: Line Status Register */
|
||||||
|
+#define UART_MSR_OFFSET 6 /* In: Modem Status Register */
|
||||||
|
+#define UART_SCR_OFFSET 7 /* I/O: Scratch Register */
|
||||||
|
+#define UART_MDR1_OFFSET 8 /* I/O: Mode Register */
|
||||||
|
+
|
||||||
|
+#define UART_LSR_FIFOE 0x80 /* Fifo error */
|
||||||
|
+#define UART_LSR_TEMT 0x40 /* Transmitter empty */
|
||||||
|
+#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
|
||||||
|
+#define UART_LSR_BI 0x10 /* Break interrupt indicator */
|
||||||
|
+#define UART_LSR_FE 0x08 /* Frame error indicator */
|
||||||
|
+#define UART_LSR_PE 0x04 /* Parity error indicator */
|
||||||
|
+#define UART_LSR_OE 0x02 /* Overrun error indicator */
|
||||||
|
+#define UART_LSR_DR 0x01 /* Receiver data ready */
|
||||||
|
+#define UART_LSR_BRK_ERROR_BITS 0x1E /* BI, FE, PE, OE bits */
|
||||||
|
+
|
||||||
|
+/* clang-format on */
|
||||||
|
+
|
||||||
|
+static volatile char *alveo_uart_base;
|
||||||
|
+static u32 alveo_uart_in_freq;
|
||||||
|
+static u32 alveo_uart_baudrate;
|
||||||
|
+static u32 alveo_uart_reg_width;
|
||||||
|
+static u32 alveo_uart_reg_shift;
|
||||||
|
+
|
||||||
|
+static u32 get_reg(u32 num)
|
||||||
|
+{
|
||||||
|
+ u32 offset = num << alveo_uart_reg_shift;
|
||||||
|
+
|
||||||
|
+ if (alveo_uart_reg_width == 1)
|
||||||
|
+ return readb(alveo_uart_base + offset);
|
||||||
|
+ else if (alveo_uart_reg_width == 2)
|
||||||
|
+ return readw(alveo_uart_base + offset);
|
||||||
|
+ else
|
||||||
|
+ return readl(alveo_uart_base + offset);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void set_reg(u32 num, u32 val)
|
||||||
|
+{
|
||||||
|
+ u32 offset = num << alveo_uart_reg_shift;
|
||||||
|
+
|
||||||
|
+ if (alveo_uart_reg_width == 1)
|
||||||
|
+ writeb(val, alveo_uart_base + offset);
|
||||||
|
+ else if (alveo_uart_reg_width == 2)
|
||||||
|
+ writew(val, alveo_uart_base + offset);
|
||||||
|
+ else
|
||||||
|
+ writel(val, alveo_uart_base + offset);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void alveo_uart_putc(char ch)
|
||||||
|
+{
|
||||||
|
+ while (!(get_reg(UART_LSR_OFFSET) & UART_LSR_TEMT))
|
||||||
|
+ ;
|
||||||
|
+
|
||||||
|
+ set_reg(UART_THR_OFFSET, ch);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int alveo_uart_getc(void)
|
||||||
|
+{
|
||||||
|
+ if (get_reg(UART_LSR_OFFSET) & UART_LSR_DR)
|
||||||
|
+ return get_reg(UART_RBR_OFFSET);
|
||||||
|
+ return -1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct sbi_console_device alveo_uart_console = {
|
||||||
|
+ .name = "alveo_uart",
|
||||||
|
+ .console_putc = alveo_uart_putc,
|
||||||
|
+ .console_getc = alveo_uart_getc
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+int alveo_uart_init(unsigned long base, u32 in_freq, u32 baudrate, u32 reg_shift,
|
||||||
|
+ u32 reg_width, u32 reg_offset)
|
||||||
|
+{
|
||||||
|
+ u16 bdiv = 0;
|
||||||
|
+
|
||||||
|
+ alveo_uart_base = (volatile char *)base + reg_offset;
|
||||||
|
+ alveo_uart_reg_shift = reg_shift;
|
||||||
|
+ alveo_uart_reg_width = reg_width;
|
||||||
|
+ alveo_uart_in_freq = in_freq;
|
||||||
|
+ alveo_uart_baudrate = baudrate;
|
||||||
|
+
|
||||||
|
+ if (alveo_uart_baudrate) {
|
||||||
|
+ bdiv = alveo_uart_in_freq / (16 * alveo_uart_baudrate);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* Disable all interrupts */
|
||||||
|
+ set_reg(UART_IER_OFFSET, 0x00);
|
||||||
|
+ /* Enable DLAB */
|
||||||
|
+ set_reg(UART_LCR_OFFSET, 0x80);
|
||||||
|
+
|
||||||
|
+ if (bdiv) {
|
||||||
|
+ /* Set divisor low byte */
|
||||||
|
+ set_reg(UART_DLL_OFFSET, bdiv & 0xff);
|
||||||
|
+ /* Set divisor high byte */
|
||||||
|
+ set_reg(UART_DLM_OFFSET, (bdiv >> 8) & 0xff);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* 8 bits, no parity, one stop bit */
|
||||||
|
+ set_reg(UART_LCR_OFFSET, 0x03); // previous was 0x0B
|
||||||
|
+ /* Disable all interrupts*/
|
||||||
|
+ set_reg(UART_IER_OFFSET, 0x00);
|
||||||
|
+
|
||||||
|
+ sbi_console_set_device(&alveo_uart_console);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
diff --git a/lib/utils/serial/objects.mk b/lib/utils/serial/objects.mk
|
||||||
|
index 1e6bd2e..0268bdf 100644
|
||||||
|
--- a/lib/utils/serial/objects.mk
|
||||||
|
+++ b/lib/utils/serial/objects.mk
|
||||||
|
@@ -44,5 +44,6 @@ libsbiutils-objs-$(CONFIG_SERIAL_SHAKTI) += serial/shakti-uart.o
|
||||||
|
libsbiutils-objs-$(CONFIG_SERIAL_SIFIVE) += serial/sifive-uart.o
|
||||||
|
libsbiutils-objs-$(CONFIG_SERIAL_LITEX) += serial/litex-uart.o
|
||||||
|
libsbiutils-objs-$(CONFIG_SERIAL_UART8250) += serial/uart8250.o
|
||||||
|
+libsbiutils-objs-$(CONFIG_SERIAL_ALVEO_UART) += serial/alveo_uart.o
|
||||||
|
libsbiutils-objs-$(CONFIG_SERIAL_XILINX_UARTLITE) += serial/xlnx-uartlite.o
|
||||||
|
libsbiutils-objs-$(CONFIG_SERIAL_SEMIHOSTING) += serial/semihosting.o
|
||||||
|
diff --git a/platform/fpga/sargantana_alveo/Kconfig b/platform/fpga/sargantana_alveo/Kconfig
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..bf3e7e6
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/platform/fpga/sargantana_alveo/Kconfig
|
||||||
|
@@ -0,0 +1,10 @@
|
||||||
|
+# SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
+
|
||||||
|
+config PLATFORM_SARGANTANA_ALVEO_FPGA
|
||||||
|
+ bool
|
||||||
|
+ select FDT
|
||||||
|
+ select IPI_MSWI
|
||||||
|
+ select IRQCHIP_PLIC
|
||||||
|
+ select SERIAL_ALVEO_UART
|
||||||
|
+ select TIMER_MTIMER
|
||||||
|
+ default y
|
||||||
|
diff --git a/platform/fpga/sargantana_alveo/configs/defconfig b/platform/fpga/sargantana_alveo/configs/defconfig
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..e69de29
|
||||||
|
diff --git a/platform/fpga/sargantana_alveo/objects.mk b/platform/fpga/sargantana_alveo/objects.mk
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..d444abe
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/platform/fpga/sargantana_alveo/objects.mk
|
||||||
|
@@ -0,0 +1,87 @@
|
||||||
|
+#
|
||||||
|
+# SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
+#
|
||||||
|
+# Copyright (c) 2019 Western Digital Corporation or its affiliates.
|
||||||
|
+#
|
||||||
|
+
|
||||||
|
+# Compiler pre-processor flags
|
||||||
|
+platform-cppflags-y =
|
||||||
|
+
|
||||||
|
+# C Compiler and assembler flags.
|
||||||
|
+platform-cflags-y =
|
||||||
|
+platform-asflags-y =
|
||||||
|
+
|
||||||
|
+# Linker flags: additional libraries and object files that the platform
|
||||||
|
+# code needs can be added here
|
||||||
|
+platform-ldflags-y =
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Command for platform specific "make run"
|
||||||
|
+# Useful for development and debugging on plaftform simulator (such as QEMU)
|
||||||
|
+#
|
||||||
|
+# platform-runcmd = your_platform_run.sh
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Platform RISC-V XLEN, ABI, ISA and Code Model configuration.
|
||||||
|
+# These are optional parameters but platforms can optionaly provide it.
|
||||||
|
+# Some of these are guessed based on GCC compiler capabilities
|
||||||
|
+#
|
||||||
|
+PLATFORM_RISCV_XLEN = 64
|
||||||
|
+PLATFORM_RISCV_ABI = lp64d
|
||||||
|
+PLATFORM_RISCV_ISA = rv64imafd
|
||||||
|
+PLATFORM_RISCV_CODE_MODEL = medany
|
||||||
|
+
|
||||||
|
+# Space separated list of object file names to be compiled for the platform
|
||||||
|
+platform-objs-y += platform.o
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# If the platform support requires a builtin device tree file, the name of
|
||||||
|
+# the device tree compiled file should be specified here. The device tree
|
||||||
|
+# source file be in the form <dt file name>.dts
|
||||||
|
+#
|
||||||
|
+# platform-objs-y += <dt file name>.o
|
||||||
|
+
|
||||||
|
+# Firmware load address configuration. This is mandatory.
|
||||||
|
+FW_TEXT_START=0x80000000
|
||||||
|
+
|
||||||
|
+# Optional parameter for path to external FDT
|
||||||
|
+# FW_FDT_PATH="path to platform flattened device tree file"
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Dynamic firmware configuration.
|
||||||
|
+# Optional parameters are commented out. Uncomment and define these parameters
|
||||||
|
+# as needed.
|
||||||
|
+#
|
||||||
|
+FW_DYNAMIC=n
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Jump firmware configuration.
|
||||||
|
+# Optional parameters are commented out. Uncomment and define these parameters
|
||||||
|
+# as needed.
|
||||||
|
+#
|
||||||
|
+FW_JUMP=n
|
||||||
|
+# This needs to be 4MB aligned for 32-bit support
|
||||||
|
+# This needs to be 2MB aligned for 64-bit support
|
||||||
|
+# ifeq ($(PLATFORM_RISCV_XLEN), 32)
|
||||||
|
+# FW_JUMP_ADDR=0x80400000
|
||||||
|
+# else
|
||||||
|
+# FW_JUMP_ADDR=0x80200000
|
||||||
|
+# endif
|
||||||
|
+# FW_JUMP_FDT_ADDR=0x82200000
|
||||||
|
+
|
||||||
|
+#
|
||||||
|
+# Firmware with payload configuration.
|
||||||
|
+# Optional parameters are commented out. Uncomment and define these parameters
|
||||||
|
+# as needed.
|
||||||
|
+#
|
||||||
|
+FW_PAYLOAD=y
|
||||||
|
+# This needs to be 4MB aligned for 32-bit support
|
||||||
|
+# This needs to be 2MB aligned for 64-bit support
|
||||||
|
+ifeq ($(PLATFORM_RISCV_XLEN), 32)
|
||||||
|
+FW_PAYLOAD_OFFSET=0x400000
|
||||||
|
+else
|
||||||
|
+FW_PAYLOAD_OFFSET=0x200000
|
||||||
|
+endif
|
||||||
|
+FW_PAYLOAD_ALIGN=0x1000
|
||||||
|
+# FW_PAYLOAD_PATH="path to next boot stage binary image file"
|
||||||
|
+# FW_PAYLOAD_FDT_ADDR=0x82200000
|
||||||
|
diff --git a/platform/fpga/sargantana_alveo/platform.c b/platform/fpga/sargantana_alveo/platform.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..a359b34
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/platform/fpga/sargantana_alveo/platform.c
|
||||||
|
@@ -0,0 +1,146 @@
|
||||||
|
+/*
|
||||||
|
+ * SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
+ *
|
||||||
|
+ * Copyright (c) 2019 Western Digital Corporation or its affiliates.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <sbi/riscv_asm.h>
|
||||||
|
+#include <sbi/riscv_encoding.h>
|
||||||
|
+#include <sbi/sbi_const.h>
|
||||||
|
+#include <sbi/sbi_platform.h>
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Include these files as needed.
|
||||||
|
+ * See objects.mk SARGANTANA_ALVEO_xxx configuration parameters.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <sbi_utils/serial/alveo_uart.h>
|
||||||
|
+#include <sbi/sbi_timer.h>
|
||||||
|
+
|
||||||
|
+#define SARGANTANA_ALVEO_HART_COUNT 1
|
||||||
|
+
|
||||||
|
+#define SARGANTANA_ALVEO_UART_BASE_ADDR 0x40000000
|
||||||
|
+#define SARGANTANA_ALVEO_UART_OFFSET 0x1000
|
||||||
|
+//#define SARGANTANA_ALVEO_UART_ADDR SARGANTANA_ALVEO_UART_BASE_ADDR + SARGANTANA_ALVEO_UART_XLNX_OFFSET
|
||||||
|
+#define SARGANTANA_ALVEO_UART_INPUT_FREQ 50000000
|
||||||
|
+#define SARGANTANA_ALVEO_UART_BAUDRATE 115200
|
||||||
|
+
|
||||||
|
+#define SARGANTANA_ALVEO_TIMER_BASE 0x40170000
|
||||||
|
+#define ADDR_TIME_L 0x0u // 32 lower bits of the time register
|
||||||
|
+#define ADDR_TIME_H 0x1u // 32 higher bits of the time register
|
||||||
|
+#define ADDR_TIMECMP_L 0x2u // 32 lower bits of the time comparator
|
||||||
|
+#define ADDR_TIMECMP_H 0x3u // 32 higher bits of the time comparator
|
||||||
|
+
|
||||||
|
+volatile uint32_t *timer_base_ptr = (uint32_t *)(SARGANTANA_ALVEO_TIMER_BASE);
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Platform early initialization.
|
||||||
|
+ */
|
||||||
|
+static int sargantana_alveo_early_init(bool cold_boot)
|
||||||
|
+{
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Platform final initialization.
|
||||||
|
+ */
|
||||||
|
+static int sargantana_alveo_final_init(bool cold_boot)
|
||||||
|
+{
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Initialize the platform console.
|
||||||
|
+ */
|
||||||
|
+static int sargantana_alveo_console_init(void)
|
||||||
|
+{
|
||||||
|
+ return alveo_uart_init(SARGANTANA_ALVEO_UART_BASE_ADDR,
|
||||||
|
+ SARGANTANA_ALVEO_UART_INPUT_FREQ,
|
||||||
|
+ SARGANTANA_ALVEO_UART_BAUDRATE,
|
||||||
|
+ 2, 4,
|
||||||
|
+ SARGANTANA_ALVEO_UART_OFFSET);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Initialize the platform interrupt controller for current HART.
|
||||||
|
+ */
|
||||||
|
+static int sargantana_alveo_irqchip_init(bool cold_boot)
|
||||||
|
+{
|
||||||
|
+ u32 hartid = current_hartid();
|
||||||
|
+ return hartid;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Initialize IPI for current HART.
|
||||||
|
+ */
|
||||||
|
+static int sargantana_alveo_ipi_init(bool cold_boot)
|
||||||
|
+{
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Get platform timer value.
|
||||||
|
+ */
|
||||||
|
+static u64 sargantana_alveo_timer_value(void)
|
||||||
|
+{
|
||||||
|
+ return ((u64)*(timer_base_ptr + ADDR_TIME_H) << 32) + *(timer_base_ptr + ADDR_TIME_L);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Start platform timer event for current HART.
|
||||||
|
+ */
|
||||||
|
+static void sargantana_alveo_timer_event_start(u64 next_event)
|
||||||
|
+{
|
||||||
|
+ *(timer_base_ptr + ADDR_TIMECMP_H) = next_event >> 32;
|
||||||
|
+ *(timer_base_ptr + ADDR_TIMECMP_L) = next_event;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Stop platform timer event for current HART.
|
||||||
|
+ */
|
||||||
|
+static void sargantana_alveo_timer_event_stop(void)
|
||||||
|
+{
|
||||||
|
+
|
||||||
|
+ *(timer_base_ptr + ADDR_TIMECMP_H) = 0;
|
||||||
|
+ *(timer_base_ptr + ADDR_TIMECMP_L) = 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct sbi_timer_device mtimer = {
|
||||||
|
+ .name = "generic_timer", // TODO Where the timer comes from? I would prefer a better name :p
|
||||||
|
+ .timer_freq = SARGANTANA_ALVEO_UART_INPUT_FREQ,
|
||||||
|
+ .timer_value = sargantana_alveo_timer_value,
|
||||||
|
+ .timer_event_start = sargantana_alveo_timer_event_start,
|
||||||
|
+ .timer_event_stop = sargantana_alveo_timer_event_stop
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Initialize platform timer for current HART.
|
||||||
|
+ */
|
||||||
|
+static int sargantana_alveo_timer_init(bool cold_boot)
|
||||||
|
+{
|
||||||
|
+ *(timer_base_ptr + ADDR_TIMECMP_H) = 0;
|
||||||
|
+ *(timer_base_ptr + ADDR_TIMECMP_L) = 0;
|
||||||
|
+ sbi_timer_set_device(&mtimer);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Platform descriptor.
|
||||||
|
+ */
|
||||||
|
+const struct sbi_platform_operations sargantana_alveo_ops = {
|
||||||
|
+ .early_init = sargantana_alveo_early_init,
|
||||||
|
+ .final_init = sargantana_alveo_final_init,
|
||||||
|
+ .console_init = sargantana_alveo_console_init,
|
||||||
|
+ .irqchip_init = sargantana_alveo_irqchip_init,
|
||||||
|
+ .ipi_init = sargantana_alveo_ipi_init,
|
||||||
|
+ .timer_init = sargantana_alveo_timer_init
|
||||||
|
+};
|
||||||
|
+const struct sbi_platform platform = {
|
||||||
|
+ .opensbi_version = OPENSBI_VERSION,
|
||||||
|
+ .platform_version = SBI_PLATFORM_VERSION(0x0, 0x01),
|
||||||
|
+ .name = "Sargantana (for Xilinx Alveo FPGA)",
|
||||||
|
+ .features = SBI_PLATFORM_DEFAULT_FEATURES,
|
||||||
|
+ .hart_count = SARGANTANA_ALVEO_HART_COUNT,
|
||||||
|
+ .hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE,
|
||||||
|
+ .platform_ops_addr = (unsigned long)&sargantana_alveo_ops
|
||||||
|
+};
|
68
patches/busybox-debug.patch
Normal file
68
patches/busybox-debug.patch
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
Only in busybox-1.36.1-mod: tags
|
||||||
|
diff -up -r busybox-1.36.1/util-linux/switch_root.c busybox-1.36.1-mod/util-linux/switch_root.c
|
||||||
|
--- busybox-1.36.1/util-linux/switch_root.c 2021-09-30 00:04:47.000000000 +0200
|
||||||
|
+++ busybox-1.36.1-mod/util-linux/switch_root.c 2024-07-01 16:08:28.336541504 +0200
|
||||||
|
@@ -181,6 +181,8 @@ int switch_root_main(int argc UNUSED_PAR
|
||||||
|
unsigned dry_run = 0;
|
||||||
|
dev_t rootdev;
|
||||||
|
|
||||||
|
+ printf("HELLO THIS IS SWITCH ROOT STARTING\n");
|
||||||
|
+
|
||||||
|
// Parse args. '+': stop at first non-option
|
||||||
|
if (ENABLE_SWITCH_ROOT && (!ENABLE_RUN_INIT || applet_name[0] == 's')) {
|
||||||
|
//usage:#define switch_root_trivial_usage
|
||||||
|
@@ -241,12 +243,15 @@ int switch_root_main(int argc UNUSED_PAR
|
||||||
|
if (stat("/init", &st) != 0 || !S_ISREG(st.st_mode)) {
|
||||||
|
bb_error_msg_and_die("'%s' is not a regular file", "/init");
|
||||||
|
}
|
||||||
|
+ printf("SWITCH ROOT LINE %d OK\n", __LINE__);
|
||||||
|
statfs("/", &stfs); // this never fails
|
||||||
|
+ printf("SWITCH ROOT LINE %d OK\n", __LINE__);
|
||||||
|
if ((unsigned)stfs.f_type != RAMFS_MAGIC
|
||||||
|
&& (unsigned)stfs.f_type != TMPFS_MAGIC
|
||||||
|
) {
|
||||||
|
bb_simple_error_msg_and_die("root filesystem is not ramfs/tmpfs");
|
||||||
|
}
|
||||||
|
+ printf("SWITCH ROOT LINE %d OK\n", __LINE__);
|
||||||
|
|
||||||
|
if (!dry_run) {
|
||||||
|
// Zap everything out of rootdev
|
||||||
|
@@ -258,19 +263,26 @@ int switch_root_main(int argc UNUSED_PAR
|
||||||
|
bb_simple_perror_msg_and_die("error moving root");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ printf("SWITCH ROOT LINE %d OK\n", __LINE__);
|
||||||
|
+ printf("XCHROOT\n");
|
||||||
|
xchroot(".");
|
||||||
|
+ printf("SWITCH ROOT LINE %d OK\n", __LINE__);
|
||||||
|
// The chdir is needed to recalculate "." and ".." links
|
||||||
|
/*xchdir("/"); - done in xchroot */
|
||||||
|
|
||||||
|
// If a new console specified, redirect stdin/stdout/stderr to it
|
||||||
|
if (console) {
|
||||||
|
+ printf("REDIRECTING CONSOLE\n");
|
||||||
|
+ printf("SWITCH ROOT LINE %d OK\n", __LINE__);
|
||||||
|
int fd = open_or_warn(console, O_RDWR);
|
||||||
|
if (fd >= 0) {
|
||||||
|
xmove_fd(fd, 0);
|
||||||
|
xdup2(0, 1);
|
||||||
|
xdup2(0, 2);
|
||||||
|
}
|
||||||
|
+ printf("SWITCH ROOT LINE %d OK\n", __LINE__);
|
||||||
|
}
|
||||||
|
+ printf("SWITCH ROOT LINE %d OK\n", __LINE__);
|
||||||
|
|
||||||
|
if (dry_run) {
|
||||||
|
// Does NEW_INIT look like it can be executed?
|
||||||
|
@@ -280,8 +292,11 @@ int switch_root_main(int argc UNUSED_PAR
|
||||||
|
if (access(argv[0], X_OK) == 0)
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
+ printf("SWITCH ROOT LINE %d OK\n", __LINE__);
|
||||||
|
+ printf("LAUNCHING EXECV\n");
|
||||||
|
// Exec NEW_INIT
|
||||||
|
execv(argv[0], argv);
|
||||||
|
+ printf("RETURNED FROM EXECV???\n");
|
||||||
|
}
|
||||||
|
bb_perror_msg_and_die("can't execute '%s'", argv[0]);
|
||||||
|
}
|
21
patches/ethernet-driver-build.patch
Normal file
21
patches/ethernet-driver-build.patch
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
diff --git a/drivers/xxvnet_carv.c b/drivers/xxvnet_carv.c
|
||||||
|
index d3f60f9..9fd4c21 100644
|
||||||
|
--- a/drivers/xxvnet_carv.c
|
||||||
|
+++ b/drivers/xxvnet_carv.c
|
||||||
|
@@ -36,6 +36,7 @@
|
||||||
|
#include <linux/iopoll.h>
|
||||||
|
#include <linux/random.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
|
+#include <linux/platform_device.h>
|
||||||
|
|
||||||
|
#include "xxvnet_carv.h"
|
||||||
|
|
||||||
|
@@ -1511,7 +1512,7 @@ axienet_dma_probe(struct platform_device *pdev, struct net_device *ndev)
|
||||||
|
spin_lock_init(&q->tx_lock);
|
||||||
|
spin_lock_init(&q->rx_lock);
|
||||||
|
|
||||||
|
- netif_napi_add(ndev, &lp->napi, axienet_rx_poll, AXIENET_NAPI_WEIGHT);
|
||||||
|
+ netif_napi_add(ndev, &lp->napi, axienet_rx_poll);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
7
patches/ethernet-driver-kbuild.patch
Normal file
7
patches/ethernet-driver-kbuild.patch
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
diff --git a/drivers/Kbuild b/drivers/Kbuild
|
||||||
|
index 28d6c0f..7f02860 100644
|
||||||
|
--- a/drivers/Kbuild
|
||||||
|
+++ b/drivers/Kbuild
|
||||||
|
@@ -1,2 +1 @@
|
||||||
|
obj-m := xxvnet_carv.o
|
||||||
|
-obj-m := xilinx_dma.o
|
23
patches/ethernet-driver-poll.patch
Normal file
23
patches/ethernet-driver-poll.patch
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
diff --git a/drivers/xxvnet_carv.c b/drivers/xxvnet_carv.c
|
||||||
|
index eb664bb..d3f60f9 100644
|
||||||
|
--- a/drivers/xxvnet_carv.c
|
||||||
|
+++ b/drivers/xxvnet_carv.c
|
||||||
|
@@ -1435,12 +1435,12 @@ static void axienet_poll_controller(struct net_device *ndev)
|
||||||
|
{
|
||||||
|
struct axienet_local *lp = netdev_priv(ndev);
|
||||||
|
|
||||||
|
- disable_irq(lp->tx_irq);
|
||||||
|
- disable_irq(lp->rx_irq);
|
||||||
|
- axienet_rx_irq(lp->tx_irq, ndev);
|
||||||
|
- axienet_tx_irq(lp->rx_irq, ndev);
|
||||||
|
- enable_irq(lp->tx_irq);
|
||||||
|
- enable_irq(lp->rx_irq);
|
||||||
|
+ disable_irq(lp->dq->tx_irq);
|
||||||
|
+ disable_irq(lp->dq->rx_irq);
|
||||||
|
+ axienet_rx_irq(lp->dq->tx_irq, ndev);
|
||||||
|
+ axienet_tx_irq(lp->dq->rx_irq, ndev);
|
||||||
|
+ enable_irq(lp->dq->tx_irq);
|
||||||
|
+ enable_irq(lp->dq->rx_irq);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
37
patches/opensbi-dont-delegate.patch
Normal file
37
patches/opensbi-dont-delegate.patch
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
|
||||||
|
index c366701..c5b5249 100644
|
||||||
|
--- a/lib/sbi/sbi_hart.c
|
||||||
|
+++ b/lib/sbi/sbi_hart.c
|
||||||
|
@@ -199,7 +199,7 @@ static int delegate_traps(struct sbi_scratch *scratch)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Send M-mode interrupts and most exceptions to S-mode */
|
||||||
|
- interrupts = MIP_SSIP | MIP_STIP | MIP_SEIP;
|
||||||
|
+ interrupts = MIP_SSIP | MIP_STIP;
|
||||||
|
interrupts |= sbi_pmu_irq_bit();
|
||||||
|
|
||||||
|
exceptions = (1U << CAUSE_MISALIGNED_FETCH) | (1U << CAUSE_BREAKPOINT) |
|
||||||
|
diff --git a/lib/sbi/sbi_irqchip.c b/lib/sbi/sbi_irqchip.c
|
||||||
|
index 0ae604a..dd4592a 100644
|
||||||
|
--- a/lib/sbi/sbi_irqchip.c
|
||||||
|
+++ b/lib/sbi/sbi_irqchip.c
|
||||||
|
@@ -37,8 +37,7 @@ int sbi_irqchip_init(struct sbi_scratch *scratch, bool cold_boot)
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
- if (ext_irqfn != default_irqfn)
|
||||||
|
- csr_set(CSR_MIE, MIP_MEIP);
|
||||||
|
+ csr_set(CSR_MIE, MIP_MEIP);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -47,8 +46,7 @@ void sbi_irqchip_exit(struct sbi_scratch *scratch)
|
||||||
|
{
|
||||||
|
const struct sbi_platform *plat = sbi_platform_ptr(scratch);
|
||||||
|
|
||||||
|
- if (ext_irqfn != default_irqfn)
|
||||||
|
- csr_clear(CSR_MIE, MIP_MEIP);
|
||||||
|
+ csr_clear(CSR_MIE, MIP_MEIP);
|
||||||
|
|
||||||
|
sbi_platform_irqchip_exit(plat);
|
||||||
|
}
|
19
patches/opensbi-dump-mregs.patch
Normal file
19
patches/opensbi-dump-mregs.patch
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
diff --git a/lib/sbi/sbi_hart.c b/lib/sbi/sbi_hart.c
|
||||||
|
index c366701..1ef6145 100644
|
||||||
|
--- a/lib/sbi/sbi_hart.c
|
||||||
|
+++ b/lib/sbi/sbi_hart.c
|
||||||
|
@@ -241,6 +241,14 @@ void sbi_hart_delegation_dump(struct sbi_scratch *scratch,
|
||||||
|
prefix, suffix, csr_read(CSR_MIDELEG));
|
||||||
|
sbi_printf("%sMEDELEG%s: 0x%" PRILX "\n",
|
||||||
|
prefix, suffix, csr_read(CSR_MEDELEG));
|
||||||
|
+ sbi_printf("%sMTVEC%s : 0x%" PRILX "\n",
|
||||||
|
+ prefix, suffix, csr_read(CSR_MTVEC));
|
||||||
|
+ sbi_printf("%sMIE%s : 0x%" PRILX "\n",
|
||||||
|
+ prefix, suffix, csr_read(CSR_MIE));
|
||||||
|
+ sbi_printf("%sMIP%s : 0x%" PRILX "\n",
|
||||||
|
+ prefix, suffix, csr_read(CSR_MIP));
|
||||||
|
+ sbi_printf("%sMSTATUS%s: 0x%" PRILX "\n",
|
||||||
|
+ prefix, suffix, csr_read(CSR_MSTATUS));
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int sbi_hart_mhpm_mask(struct sbi_scratch *scratch)
|
24
patches/opensbi-enable-meip.patch
Normal file
24
patches/opensbi-enable-meip.patch
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
diff --git a/lib/sbi/sbi_irqchip.c b/lib/sbi/sbi_irqchip.c
|
||||||
|
index 0ae604a..dd4592a 100644
|
||||||
|
--- a/lib/sbi/sbi_irqchip.c
|
||||||
|
+++ b/lib/sbi/sbi_irqchip.c
|
||||||
|
@@ -37,8 +37,7 @@ int sbi_irqchip_init(struct sbi_scratch *scratch, bool cold_boot)
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
- if (ext_irqfn != default_irqfn)
|
||||||
|
- csr_set(CSR_MIE, MIP_MEIP);
|
||||||
|
+ csr_set(CSR_MIE, MIP_MEIP);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -47,8 +46,7 @@ void sbi_irqchip_exit(struct sbi_scratch *scratch)
|
||||||
|
{
|
||||||
|
const struct sbi_platform *plat = sbi_platform_ptr(scratch);
|
||||||
|
|
||||||
|
- if (ext_irqfn != default_irqfn)
|
||||||
|
- csr_clear(CSR_MIE, MIP_MEIP);
|
||||||
|
+ csr_clear(CSR_MIE, MIP_MEIP);
|
||||||
|
|
||||||
|
sbi_platform_irqchip_exit(plat);
|
||||||
|
}
|
26
patches/opensbi-enable-seip.patch
Normal file
26
patches/opensbi-enable-seip.patch
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
diff --git a/lib/sbi/sbi_irqchip.c b/lib/sbi/sbi_irqchip.c
|
||||||
|
index 0ae604a..94832c8 100644
|
||||||
|
--- a/lib/sbi/sbi_irqchip.c
|
||||||
|
+++ b/lib/sbi/sbi_irqchip.c
|
||||||
|
@@ -37,8 +37,8 @@ int sbi_irqchip_init(struct sbi_scratch *scratch, bool cold_boot)
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
- if (ext_irqfn != default_irqfn)
|
||||||
|
- csr_set(CSR_MIE, MIP_MEIP);
|
||||||
|
+ csr_set(CSR_MIE, MIP_MEIP | MIP_SEIP);
|
||||||
|
+ csr_set(CSR_MSTATUS, MSTATUS_MIE | MSTATUS_SIE);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -47,8 +47,8 @@ void sbi_irqchip_exit(struct sbi_scratch *scratch)
|
||||||
|
{
|
||||||
|
const struct sbi_platform *plat = sbi_platform_ptr(scratch);
|
||||||
|
|
||||||
|
- if (ext_irqfn != default_irqfn)
|
||||||
|
- csr_clear(CSR_MIE, MIP_MEIP);
|
||||||
|
+ csr_clear(CSR_MIE, MIP_MEIP | MIP_SEIP);
|
||||||
|
+ csr_clear(CSR_MSTATUS, MSTATUS_MIE | MSTATUS_SIE);
|
||||||
|
|
||||||
|
sbi_platform_irqchip_exit(plat);
|
||||||
|
}
|
13
patches/opensbi-lagarto-hun.patch
Normal file
13
patches/opensbi-lagarto-hun.patch
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
--- a/platform/fpga/openpiton/platform.c 2024-03-12 16:27:13.886525365 +0100
|
||||||
|
+++ b/platform/fpga/openpiton/platform.c 2024-05-27 11:42:47.748244398 +0200
|
||||||
|
@@ -24,8 +24,8 @@
|
||||||
|
#define OPENPITON_DEFAULT_UART_REG_WIDTH 1
|
||||||
|
#define OPENPITON_DEFAULT_UART_REG_OFFSET 0
|
||||||
|
#define OPENPITON_DEFAULT_PLIC_ADDR 0xfff1100000
|
||||||
|
-#define OPENPITON_DEFAULT_PLIC_NUM_SOURCES 2
|
||||||
|
-#define OPENPITON_DEFAULT_HART_COUNT 3
|
||||||
|
+#define OPENPITON_DEFAULT_PLIC_NUM_SOURCES 3
|
||||||
|
+#define OPENPITON_DEFAULT_HART_COUNT 20
|
||||||
|
#define OPENPITON_DEFAULT_CLINT_ADDR 0xfff1020000
|
||||||
|
#define OPENPITON_DEFAULT_ACLINT_MTIMER_FREQ 1000000
|
||||||
|
#define OPENPITON_DEFAULT_ACLINT_MSWI_ADDR \
|
200
patches/opensbi-test-plic.patch
Normal file
200
patches/opensbi-test-plic.patch
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
diff --git a/lib/sbi/sbi_irqchip.c b/lib/sbi/sbi_irqchip.c
|
||||||
|
index 0ae604a..e34e90c 100644
|
||||||
|
--- a/lib/sbi/sbi_irqchip.c
|
||||||
|
+++ b/lib/sbi/sbi_irqchip.c
|
||||||
|
@@ -9,6 +9,9 @@
|
||||||
|
|
||||||
|
#include <sbi/sbi_irqchip.h>
|
||||||
|
#include <sbi/sbi_platform.h>
|
||||||
|
+#include <sbi/sbi_console.h>
|
||||||
|
+
|
||||||
|
+static void do_plic_test(void);
|
||||||
|
|
||||||
|
static int default_irqfn(void)
|
||||||
|
{
|
||||||
|
@@ -37,8 +40,10 @@ int sbi_irqchip_init(struct sbi_scratch *scratch, bool cold_boot)
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
- if (ext_irqfn != default_irqfn)
|
||||||
|
- csr_set(CSR_MIE, MIP_MEIP);
|
||||||
|
+ //csr_set(CSR_MIE, MIP_SEIP);
|
||||||
|
+ //csr_set(CSR_MSTATUS, MSTATUS_SIE);
|
||||||
|
+
|
||||||
|
+ do_plic_test();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -47,8 +52,170 @@ void sbi_irqchip_exit(struct sbi_scratch *scratch)
|
||||||
|
{
|
||||||
|
const struct sbi_platform *plat = sbi_platform_ptr(scratch);
|
||||||
|
|
||||||
|
- if (ext_irqfn != default_irqfn)
|
||||||
|
- csr_clear(CSR_MIE, MIP_MEIP);
|
||||||
|
+ //csr_clear(CSR_MIE, MIP_SEIP);
|
||||||
|
+ //csr_clear(CSR_MSTATUS, MSTATUS_SIE);
|
||||||
|
|
||||||
|
sbi_platform_irqchip_exit(plat);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+/* ----------------- PLIC tests ---------------- */
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+#define MIE_MEIE (1UL << 11) // Machine External Interrupt Enable
|
||||||
|
+#define SIE_SEIE (1UL << 9)
|
||||||
|
+#define MIDELEG_SEIE (1UL << 9) // Delegate Machine External Interrupt to Supervisor
|
||||||
|
+#define PLIC_TIMER_PORT 4
|
||||||
|
+// Base address of PLIC
|
||||||
|
+#define PLIC_BASE 0x40800000UL
|
||||||
|
+#define PLIC_PRIORITY_OFFSET 0x0UL
|
||||||
|
+#define PLIC_PENDING_OFFSET 0x1000UL
|
||||||
|
+#define PLIC_ENABLE_OFFSET 0x2080UL
|
||||||
|
+#define PLIC_THRESHOLD_OFFSET 0x201000UL
|
||||||
|
+#define PLIC_CLAIM_OFFSET 0x201004UL
|
||||||
|
+
|
||||||
|
+// Aux timer
|
||||||
|
+#define AUX_TIMER_BASE 0x40010000UL
|
||||||
|
+#define MTIMECMP_OFFSET 0x4000UL
|
||||||
|
+#define MTIME_OFFSET 0xBFF8UL
|
||||||
|
+
|
||||||
|
+#define MSTATUS_MPP_MASK (3 << 11)
|
||||||
|
+#define MSTATUS_MPP_SUPERVISOR (1 << 11)
|
||||||
|
+
|
||||||
|
+static volatile unsigned long *mtime = (unsigned long *)(AUX_TIMER_BASE + MTIME_OFFSET);
|
||||||
|
+static volatile unsigned long *mtimecmp = (unsigned long *)(AUX_TIMER_BASE + MTIMECMP_OFFSET);
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+static void dumpregs(int machine)
|
||||||
|
+{
|
||||||
|
+ char *prefix = "\t";
|
||||||
|
+ char *suffix = "\t";
|
||||||
|
+ sbi_printf("Registers:\n");
|
||||||
|
+ if (machine) {
|
||||||
|
+ sbi_printf("%sMIE%s: 0x%" PRILX "\n",
|
||||||
|
+ prefix, suffix, csr_read(CSR_MIE));
|
||||||
|
+ sbi_printf("%sMIP%s: 0x%" PRILX "\n",
|
||||||
|
+ prefix, suffix, csr_read(CSR_MIP));
|
||||||
|
+ sbi_printf("%sMSTATUS%s: 0x%" PRILX "\n",
|
||||||
|
+ prefix, suffix, csr_read(CSR_MSTATUS));
|
||||||
|
+ sbi_printf("%sMIDELEG%s: 0x%" PRILX "\n",
|
||||||
|
+ prefix, suffix, csr_read(CSR_MIDELEG));
|
||||||
|
+ }
|
||||||
|
+ sbi_printf("%sSIE%s: 0x%" PRILX "\n",
|
||||||
|
+ prefix, suffix, csr_read(CSR_SIE));
|
||||||
|
+ sbi_printf("%sSIP%s: 0x%" PRILX "\n",
|
||||||
|
+ prefix, suffix, csr_read(CSR_SIP));
|
||||||
|
+ sbi_printf("%sSSTATUS%s: 0x%" PRILX "\n",
|
||||||
|
+ prefix, suffix, csr_read(CSR_SSTATUS));
|
||||||
|
+ sbi_printf("%sSTVEC%s: 0x%" PRILX "\n",
|
||||||
|
+ prefix, suffix, csr_read(CSR_STVEC));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void __attribute__((optimize("O0"))) switch_to_supervisor_mode(int (*target_address)(void))
|
||||||
|
+{
|
||||||
|
+ unsigned long mstatus;
|
||||||
|
+
|
||||||
|
+ // Read the current mstatus
|
||||||
|
+ asm volatile("csrr %0, mstatus" : "=r"(mstatus));
|
||||||
|
+
|
||||||
|
+ // Set the MPP field to supervisor mode
|
||||||
|
+ mstatus = (mstatus & ~MSTATUS_MPP_MASK) | MSTATUS_MPP_SUPERVISOR;
|
||||||
|
+
|
||||||
|
+ // Write back the modified mstatus
|
||||||
|
+ asm volatile("csrw mstatus, %0" : : "r"(mstatus));
|
||||||
|
+
|
||||||
|
+ // Set the mepc to the target address
|
||||||
|
+ asm volatile("csrw mepc, %0" : : "r"(target_address));
|
||||||
|
+
|
||||||
|
+ // Use mret to return to the specified address in supervisor mode
|
||||||
|
+ asm volatile("mret");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int supervisor_mode_code(void)
|
||||||
|
+{
|
||||||
|
+ sbi_printf("Hello from supervisor\n");
|
||||||
|
+ dumpregs(0);
|
||||||
|
+
|
||||||
|
+ /* Enable timer interrupt */
|
||||||
|
+ *mtimecmp = *mtime + 10000;
|
||||||
|
+
|
||||||
|
+ sbi_printf("Timer alarm programmed\n");
|
||||||
|
+ sbi_printf("Waiting for interrupt...\n");
|
||||||
|
+ int i = 0;
|
||||||
|
+ char *s = "-\\|/";
|
||||||
|
+ while (1) {
|
||||||
|
+ for (volatile unsigned long j = 0; j < 100000; j++);
|
||||||
|
+ sbi_printf("\r%c", s[i++]);
|
||||||
|
+ if (i >= 4)
|
||||||
|
+ i = 0;
|
||||||
|
+ }
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void __attribute__((aligned(4))) __attribute__((interrupt ("supervisor"))) supervisor_trap_entry(void)
|
||||||
|
+{
|
||||||
|
+ sbi_printf("\nSupervisor Trap Entry Reached!\n");
|
||||||
|
+ sbi_printf("\nTEST-RESULT-OK\n");
|
||||||
|
+ while (1) {
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void do_plic_test(void)
|
||||||
|
+{
|
||||||
|
+ sbi_printf("--- TESTING PLIC ---\n");
|
||||||
|
+
|
||||||
|
+ /* Disable auxiliar timer interrupt */
|
||||||
|
+ *mtimecmp = 0xffffffffUL;
|
||||||
|
+ sbi_printf("Timer interrupt disabled\n");
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+ /* Enable supervisor interrupt delegation */
|
||||||
|
+
|
||||||
|
+ csr_set(CSR_SIE, SIE_SEIE); // Enable supervisor external interrupts
|
||||||
|
+ csr_set(CSR_SSTATUS, SSTATUS_SIE); // Enable global interrupts in supervisor mode
|
||||||
|
+ csr_set(CSR_MIDELEG, MIDELEG_SEIE); // Delegate machine interrupts to supervisor mode
|
||||||
|
+ csr_write(CSR_STVEC, &supervisor_trap_entry);
|
||||||
|
+
|
||||||
|
+ sbi_printf("Enabled supervisor delegation:\n");
|
||||||
|
+
|
||||||
|
+ dumpregs(1);
|
||||||
|
+
|
||||||
|
+ /* Configure PLIC aux timer input */
|
||||||
|
+ volatile unsigned *plic_priority = (unsigned *)(PLIC_BASE + PLIC_PRIORITY_OFFSET + PLIC_TIMER_PORT * 4);
|
||||||
|
+ volatile unsigned *plic_enable = (unsigned *)(PLIC_BASE + PLIC_ENABLE_OFFSET);
|
||||||
|
+ volatile unsigned *plic_threshold = (unsigned *)(PLIC_BASE + PLIC_THRESHOLD_OFFSET);
|
||||||
|
+ volatile unsigned *plic_claim = (unsigned *)(PLIC_BASE + PLIC_CLAIM_OFFSET);
|
||||||
|
+ volatile unsigned *plic_pending = (unsigned *)(PLIC_BASE + PLIC_PENDING_OFFSET);
|
||||||
|
+
|
||||||
|
+ sbi_printf("Enabling timer in PLIC\n");
|
||||||
|
+ *plic_priority = PLIC_TIMER_PORT;
|
||||||
|
+ *plic_threshold = PLIC_TIMER_PORT - 1;
|
||||||
|
+ *plic_enable |= (1 << PLIC_TIMER_PORT);
|
||||||
|
+
|
||||||
|
+ /* Clear interrupt */
|
||||||
|
+ sbi_printf("Pending: %d\n", *plic_pending);
|
||||||
|
+ unsigned claim = *plic_claim;
|
||||||
|
+ sbi_printf("Claim: %d\n", claim);
|
||||||
|
+ *plic_claim = claim;
|
||||||
|
+ sbi_printf("Pending: %d\n", *plic_pending);
|
||||||
|
+
|
||||||
|
+ sbi_printf("Clearing MIP\n");
|
||||||
|
+ csr_write(CSR_MIP, 0);
|
||||||
|
+
|
||||||
|
+ /* Enable external timer interrupts */
|
||||||
|
+ //sbi_printf("Enabling MEIE in MIE register\n");
|
||||||
|
+ //csr_set(CSR_MIE, MIE_MEIE); /* Needed? */
|
||||||
|
+ //sbi_printf("Enabling MIE in MSTATUS register\n");
|
||||||
|
+ //csr_set(CSR_MSTATUS, MSTATUS_MIE); /* Needed? */
|
||||||
|
+
|
||||||
|
+ sbi_printf("Switching to supervisor\n");
|
||||||
|
+
|
||||||
|
+ dumpregs(1);
|
||||||
|
+
|
||||||
|
+ switch_to_supervisor_mode(&supervisor_mode_code);
|
||||||
|
+
|
||||||
|
+ /* Never reached */
|
||||||
|
+ while (1);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+
|
229
patches/opensbi-timer-debug.patch
Normal file
229
patches/opensbi-timer-debug.patch
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
diff --git a/lib/sbi/sbi_timer.c b/lib/sbi/sbi_timer.c
|
||||||
|
index 7b618de..65e42b0 100644
|
||||||
|
--- a/lib/sbi/sbi_timer.c
|
||||||
|
+++ b/lib/sbi/sbi_timer.c
|
||||||
|
@@ -183,13 +183,17 @@ int sbi_timer_init(struct sbi_scratch *scratch, bool cold_boot)
|
||||||
|
u64 *time_delta;
|
||||||
|
const struct sbi_platform *plat = sbi_platform_ptr(scratch);
|
||||||
|
|
||||||
|
+ sbi_printf("sbi_timer_init: begins\n");
|
||||||
|
+
|
||||||
|
if (cold_boot) {
|
||||||
|
time_delta_off = sbi_scratch_alloc_offset(sizeof(*time_delta));
|
||||||
|
if (!time_delta_off)
|
||||||
|
return SBI_ENOMEM;
|
||||||
|
|
||||||
|
- if (sbi_hart_has_extension(scratch, SBI_HART_EXT_ZICNTR))
|
||||||
|
+ if (sbi_hart_has_extension(scratch, SBI_HART_EXT_ZICNTR)) {
|
||||||
|
+ sbi_printf("sbi_timer_init: got Zicntr extension\n");
|
||||||
|
get_time_val = get_ticks;
|
||||||
|
+ }
|
||||||
|
} else {
|
||||||
|
if (!time_delta_off)
|
||||||
|
return SBI_ENOMEM;
|
||||||
|
@@ -198,7 +202,10 @@ int sbi_timer_init(struct sbi_scratch *scratch, bool cold_boot)
|
||||||
|
time_delta = sbi_scratch_offset_ptr(scratch, time_delta_off);
|
||||||
|
*time_delta = 0;
|
||||||
|
|
||||||
|
- return sbi_platform_timer_init(plat, cold_boot);
|
||||||
|
+ int rc = sbi_platform_timer_init(plat, cold_boot);
|
||||||
|
+ if (rc)
|
||||||
|
+ sbi_printf("sbi_platform_timer: sbi_platform_timer_init failed (%d)\n", rc);
|
||||||
|
+ return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sbi_timer_exit(struct sbi_scratch *scratch)
|
||||||
|
diff --git a/lib/sbi/sbi_trap.c b/lib/sbi/sbi_trap.c
|
||||||
|
index b4f3a17..cde2073 100644
|
||||||
|
--- a/lib/sbi/sbi_trap.c
|
||||||
|
+++ b/lib/sbi/sbi_trap.c
|
||||||
|
@@ -283,6 +283,7 @@ static int sbi_trap_aia_irq(void)
|
||||||
|
*/
|
||||||
|
struct sbi_trap_context *sbi_trap_handler(struct sbi_trap_context *tcntx)
|
||||||
|
{
|
||||||
|
+ sbi_printf("<");
|
||||||
|
int rc = SBI_ENOTSUPP;
|
||||||
|
const char *msg = "trap handler failed";
|
||||||
|
struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
|
||||||
|
@@ -295,6 +296,7 @@ struct sbi_trap_context *sbi_trap_handler(struct sbi_trap_context *tcntx)
|
||||||
|
sbi_trap_set_context(scratch, tcntx);
|
||||||
|
|
||||||
|
if (mcause & MCAUSE_IRQ_MASK) {
|
||||||
|
+ sbi_printf("i(%lu)", mcause & ~MCAUSE_IRQ_MASK);
|
||||||
|
if (sbi_hart_has_extension(sbi_scratch_thishart_ptr(),
|
||||||
|
SBI_HART_EXT_SMAIA))
|
||||||
|
rc = sbi_trap_aia_irq();
|
||||||
|
@@ -306,35 +308,42 @@ struct sbi_trap_context *sbi_trap_handler(struct sbi_trap_context *tcntx)
|
||||||
|
|
||||||
|
switch (mcause) {
|
||||||
|
case CAUSE_ILLEGAL_INSTRUCTION:
|
||||||
|
+ sbi_printf("I");
|
||||||
|
rc = sbi_illegal_insn_handler(tcntx);
|
||||||
|
msg = "illegal instruction handler failed";
|
||||||
|
break;
|
||||||
|
case CAUSE_MISALIGNED_LOAD:
|
||||||
|
+ sbi_printf("L");
|
||||||
|
sbi_pmu_ctr_incr_fw(SBI_PMU_FW_MISALIGNED_LOAD);
|
||||||
|
rc = sbi_misaligned_load_handler(tcntx);
|
||||||
|
msg = "misaligned load handler failed";
|
||||||
|
break;
|
||||||
|
case CAUSE_MISALIGNED_STORE:
|
||||||
|
+ sbi_printf("S");
|
||||||
|
sbi_pmu_ctr_incr_fw(SBI_PMU_FW_MISALIGNED_STORE);
|
||||||
|
rc = sbi_misaligned_store_handler(tcntx);
|
||||||
|
msg = "misaligned store handler failed";
|
||||||
|
break;
|
||||||
|
case CAUSE_SUPERVISOR_ECALL:
|
||||||
|
case CAUSE_MACHINE_ECALL:
|
||||||
|
+ sbi_printf("E");
|
||||||
|
rc = sbi_ecall_handler(tcntx);
|
||||||
|
msg = "ecall handler failed";
|
||||||
|
break;
|
||||||
|
case CAUSE_LOAD_ACCESS:
|
||||||
|
+ sbi_printf("l");
|
||||||
|
sbi_pmu_ctr_incr_fw(SBI_PMU_FW_ACCESS_LOAD);
|
||||||
|
rc = sbi_load_access_handler(tcntx);
|
||||||
|
msg = "load fault handler failed";
|
||||||
|
break;
|
||||||
|
case CAUSE_STORE_ACCESS:
|
||||||
|
+ sbi_printf("s");
|
||||||
|
sbi_pmu_ctr_incr_fw(SBI_PMU_FW_ACCESS_STORE);
|
||||||
|
rc = sbi_store_access_handler(tcntx);
|
||||||
|
msg = "store fault handler failed";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
+ sbi_printf("R");
|
||||||
|
/* If the trap came from S or U mode, redirect it there */
|
||||||
|
msg = "trap redirect failed";
|
||||||
|
rc = sbi_trap_redirect(regs, trap);
|
||||||
|
@@ -344,6 +353,8 @@ struct sbi_trap_context *sbi_trap_handler(struct sbi_trap_context *tcntx)
|
||||||
|
trap_done:
|
||||||
|
if (rc)
|
||||||
|
sbi_trap_error(msg, rc, tcntx);
|
||||||
|
+ else
|
||||||
|
+ sbi_printf(">");
|
||||||
|
|
||||||
|
if (((regs->mstatus & MSTATUS_MPP) >> MSTATUS_MPP_SHIFT) != PRV_M)
|
||||||
|
sbi_sse_process_pending_events(regs);
|
||||||
|
diff --git a/lib/utils/timer/fdt_timer.c b/lib/utils/timer/fdt_timer.c
|
||||||
|
index f468730..db20526 100644
|
||||||
|
--- a/lib/utils/timer/fdt_timer.c
|
||||||
|
+++ b/lib/utils/timer/fdt_timer.c
|
||||||
|
@@ -7,6 +7,7 @@
|
||||||
|
* Anup Patel <anup.patel@wdc.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
+#include <sbi/sbi_console.h>
|
||||||
|
#include <sbi/sbi_error.h>
|
||||||
|
#include <sbi/sbi_scratch.h>
|
||||||
|
#include <sbi_utils/fdt/fdt_helper.h>
|
||||||
|
@@ -39,19 +40,26 @@ static int fdt_timer_cold_init(void)
|
||||||
|
void *fdt = fdt_get_address();
|
||||||
|
|
||||||
|
for (pos = 0; pos < fdt_timer_drivers_size; pos++) {
|
||||||
|
+ sbi_printf("fdt_timer_cold_init: pos = %d\n", pos);
|
||||||
|
drv = fdt_timer_drivers[pos];
|
||||||
|
|
||||||
|
noff = -1;
|
||||||
|
while ((noff = fdt_find_match(fdt, noff,
|
||||||
|
drv->match_table, &match)) >= 0) {
|
||||||
|
+
|
||||||
|
+ sbi_printf("fdt_timer_cold_init: got match, name = %s\n", match->compatible);
|
||||||
|
if (!fdt_node_is_enabled(fdt, noff))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
+ sbi_printf("fdt_timer_cold_init: enabled\n");
|
||||||
|
+
|
||||||
|
/* drv->cold_init must not be NULL */
|
||||||
|
if (drv->cold_init == NULL)
|
||||||
|
return SBI_EFAIL;
|
||||||
|
|
||||||
|
rc = drv->cold_init(fdt, noff, match);
|
||||||
|
+ sbi_printf("fdt_timer_cold_init: drc->cold_init = %d\n", rc);
|
||||||
|
+
|
||||||
|
if (rc == SBI_ENODEV)
|
||||||
|
continue;
|
||||||
|
if (rc)
|
||||||
|
@@ -69,6 +77,7 @@ static int fdt_timer_cold_init(void)
|
||||||
|
* We can't fail here since systems with Sstc might not provide
|
||||||
|
* mtimer/clint DT node in the device tree.
|
||||||
|
*/
|
||||||
|
+ sbi_printf("fdt_timer_cold_init: returns 0\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -78,9 +87,15 @@ int fdt_timer_init(bool cold_boot)
|
||||||
|
|
||||||
|
if (cold_boot) {
|
||||||
|
rc = fdt_timer_cold_init();
|
||||||
|
- if (rc)
|
||||||
|
+ if (rc) {
|
||||||
|
+ sbi_printf("fdt_timer_init: fdt_timer_cold_init failed (%d)\n", rc);
|
||||||
|
return rc;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
- return fdt_timer_warm_init();
|
||||||
|
+ rc = fdt_timer_warm_init();
|
||||||
|
+ if (rc)
|
||||||
|
+ sbi_printf("fdt_timer_init: fdt_timer_warm_init failed (%d)\n", rc);
|
||||||
|
+
|
||||||
|
+ return rc;
|
||||||
|
}
|
||||||
|
diff --git a/lib/utils/timer/fdt_timer_mtimer.c b/lib/utils/timer/fdt_timer_mtimer.c
|
||||||
|
index 9e27e3a..cef2ee6 100644
|
||||||
|
--- a/lib/utils/timer/fdt_timer_mtimer.c
|
||||||
|
+++ b/lib/utils/timer/fdt_timer_mtimer.c
|
||||||
|
@@ -8,6 +8,7 @@
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libfdt.h>
|
||||||
|
+#include <sbi/sbi_console.h>
|
||||||
|
#include <sbi/sbi_error.h>
|
||||||
|
#include <sbi/sbi_heap.h>
|
||||||
|
#include <sbi/sbi_list.h>
|
||||||
|
@@ -33,6 +34,7 @@ static struct aclint_mtimer_data *mt_reference = NULL;
|
||||||
|
static int timer_mtimer_cold_init(void *fdt, int nodeoff,
|
||||||
|
const struct fdt_match *match)
|
||||||
|
{
|
||||||
|
+
|
||||||
|
int rc;
|
||||||
|
unsigned long addr[2], size[2];
|
||||||
|
struct timer_mtimer_node *mtn, *n;
|
||||||
|
@@ -40,6 +42,8 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
|
||||||
|
const struct timer_mtimer_quirks *quirks = match->data;
|
||||||
|
bool is_clint = quirks && quirks->is_clint;
|
||||||
|
|
||||||
|
+ sbi_printf("timer_mtimer_cold_init: begins, is_clint = %d\n", (int) is_clint);
|
||||||
|
+
|
||||||
|
mtn = sbi_zalloc(sizeof(*mtn));
|
||||||
|
if (!mtn)
|
||||||
|
return SBI_ENOMEM;
|
||||||
|
@@ -49,6 +53,7 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
|
||||||
|
&addr[0], &size[0], &addr[1], &size[1],
|
||||||
|
&mt->first_hartid, &mt->hart_count);
|
||||||
|
if (rc) {
|
||||||
|
+ sbi_printf("timer_mtimer_cold_init: fdt_parse_aclint_node failed (%d)\n", rc);
|
||||||
|
sbi_free(mtn);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
@@ -57,6 +62,7 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
|
||||||
|
|
||||||
|
rc = fdt_parse_timebase_frequency(fdt, &mt->mtime_freq);
|
||||||
|
if (rc) {
|
||||||
|
+ sbi_printf("timer_mtimer_cold_init: fdt_parse_timebase_frequency failed (%d)\n", rc);
|
||||||
|
sbi_free(mtn);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
@@ -83,6 +89,11 @@ static int timer_mtimer_cold_init(void *fdt, int nodeoff,
|
||||||
|
mt->mtimecmp_size = size[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ sbi_printf("timer_mtimer_cold_init: mtime_addr = 0x%08lx\n", mt->mtime_addr);
|
||||||
|
+ sbi_printf("timer_mtimer_cold_init: mtime_size = 0x%08lx\n", mt->mtime_size);
|
||||||
|
+ sbi_printf("timer_mtimer_cold_init: mtimecmp_addr = 0x%08lx\n", mt->mtimecmp_addr);
|
||||||
|
+ sbi_printf("timer_mtimer_cold_init: mtimecmp_size = 0x%08lx\n", mt->mtimecmp_size);
|
||||||
|
+
|
||||||
|
/* Apply additional quirks */
|
||||||
|
if (quirks) {
|
||||||
|
mt->has_64bit_mmio = quirks->has_64bit_mmio;
|
167
patches/ox-alveo-platform-plic.patch
Normal file
167
patches/ox-alveo-platform-plic.patch
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
diff --git a/platform/fpga/ox_alveo/Kconfig b/platform/fpga/ox_alveo/Kconfig
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..bf3e7e6
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/platform/fpga/ox_alveo/Kconfig
|
||||||
|
@@ -0,0 +1,5 @@
|
||||||
|
+config PLATFORM_OX_ALVEO_FPGA
|
||||||
|
+ bool
|
||||||
|
+ select SERIAL_UART8250
|
||||||
|
+ select IRQCHIP_PLIC
|
||||||
|
+ default y
|
||||||
|
diff --git a/platform/fpga/ox_alveo/configs/defconfig b/platform/fpga/ox_alveo/configs/defconfig
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..e69de29
|
||||||
|
diff --git a/platform/fpga/ox_alveo/objects.mk b/platform/fpga/ox_alveo/objects.mk
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..d444abe
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/platform/fpga/ox_alveo/objects.mk
|
||||||
|
@@ -0,0 +1,19 @@
|
||||||
|
+platform-cppflags-y =
|
||||||
|
+platform-cflags-y =
|
||||||
|
+platform-asflags-y =
|
||||||
|
+platform-ldflags-y =
|
||||||
|
+PLATFORM_RISCV_XLEN = 64
|
||||||
|
+PLATFORM_RISCV_ABI = lp64d
|
||||||
|
+PLATFORM_RISCV_ISA = rv64g
|
||||||
|
+PLATFORM_RISCV_CODE_MODEL = medany
|
||||||
|
+
|
||||||
|
+platform-objs-y += platform.o
|
||||||
|
+
|
||||||
|
+FW_TEXT_START=0x80000000
|
||||||
|
+
|
||||||
|
+FW_DYNAMIC=n
|
||||||
|
+FW_JUMP=n
|
||||||
|
+FW_PAYLOAD=y
|
||||||
|
+
|
||||||
|
+FW_PAYLOAD_OFFSET=0x200000
|
||||||
|
+FW_PAYLOAD_ALIGN=0x1000
|
||||||
|
diff --git a/platform/fpga/ox_alveo/platform.c b/platform/fpga/ox_alveo/platform.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..a359b34
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/platform/fpga/ox_alveo/platform.c
|
||||||
|
@@ -0,0 +1,122 @@
|
||||||
|
+#include <sbi/riscv_asm.h>
|
||||||
|
+#include <sbi/riscv_encoding.h>
|
||||||
|
+#include <sbi/sbi_const.h>
|
||||||
|
+#include <sbi/sbi_platform.h>
|
||||||
|
+#include <sbi_utils/serial/uart8250.h>
|
||||||
|
+#include <sbi/sbi_timer.h>
|
||||||
|
+#include <sbi_utils/irqchip/plic.h>
|
||||||
|
+
|
||||||
|
+#define OX_ALVEO_HART_COUNT 1
|
||||||
|
+
|
||||||
|
+#define OX_ALVEO_UART_BASE_ADDR 0x40000000
|
||||||
|
+#define OX_ALVEO_UART_OFFSET 0x1000
|
||||||
|
+#define OX_ALVEO_UART_INPUT_FREQ 50000000
|
||||||
|
+#define OX_ALVEO_UART_BAUDRATE 115200
|
||||||
|
+#define OX_ALVEO_PLIC_ADDR 0x40800000
|
||||||
|
+#define OX_ALVEO_PLIC_NUM_SOURCES 3
|
||||||
|
+
|
||||||
|
+#define OX_ALVEO_TIMER_BASE 0x40170000
|
||||||
|
+#define ADDR_TIME_L 0x0u // 32 lower bits of the time register
|
||||||
|
+#define ADDR_TIME_H 0x1u // 32 higher bits of the time register
|
||||||
|
+#define ADDR_TIMECMP_L 0x2u // 32 lower bits of the time comparator
|
||||||
|
+#define ADDR_TIMECMP_H 0x3u // 32 higher bits of the time comparator
|
||||||
|
+
|
||||||
|
+volatile uint32_t *timer_base_ptr = (uint32_t *)(OX_ALVEO_TIMER_BASE);
|
||||||
|
+
|
||||||
|
+static struct plic_data plic = {
|
||||||
|
+ .addr = OX_ALVEO_PLIC_ADDR,
|
||||||
|
+ .num_src = OX_ALVEO_PLIC_NUM_SOURCES,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int ox_alveo_early_init(bool cold_boot) // Platform early initialization.
|
||||||
|
+{
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ox_alveo_final_init(bool cold_boot) // Platform final initialization.
|
||||||
|
+{
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ox_alveo_console_init(void) // Initialize the platform console.
|
||||||
|
+{
|
||||||
|
+ return uart8250_init(OX_ALVEO_UART_BASE_ADDR,
|
||||||
|
+ OX_ALVEO_UART_INPUT_FREQ,
|
||||||
|
+ OX_ALVEO_UART_BAUDRATE,
|
||||||
|
+ 2, 4,
|
||||||
|
+ OX_ALVEO_UART_OFFSET);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ox_alveo_irqchip_init(bool cold_boot) // Initialize the platform interrupt controller for current HART.
|
||||||
|
+{
|
||||||
|
+ u32 hartid = current_hartid();
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ /* Example if the generic PLIC driver is used */
|
||||||
|
+ if (cold_boot) {
|
||||||
|
+ ret = plic_cold_irqchip_init(&plic);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return plic_warm_irqchip_init(&plic, 2 * hartid, -1);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ox_alveo_ipi_init(bool cold_boot) // Initialize IPI for current HART.
|
||||||
|
+{
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static u64 ox_alveo_timer_value(void) // Get platform timer value.
|
||||||
|
+{
|
||||||
|
+ return ((u64)*(timer_base_ptr + ADDR_TIME_H) << 32) + *(timer_base_ptr + ADDR_TIME_L);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void ox_alveo_timer_event_start(u64 next_event) // Start platform timer event for current HART.
|
||||||
|
+{
|
||||||
|
+ *(timer_base_ptr + ADDR_TIMECMP_H) = next_event >> 32;
|
||||||
|
+ *(timer_base_ptr + ADDR_TIMECMP_L) = next_event;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void ox_alveo_timer_event_stop(void) // Stop platform timer event for current HART.
|
||||||
|
+{
|
||||||
|
+
|
||||||
|
+ *(timer_base_ptr + ADDR_TIMECMP_H) = 0;
|
||||||
|
+ *(timer_base_ptr + ADDR_TIMECMP_L) = 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct sbi_timer_device mtimer = {
|
||||||
|
+ .name = "axi_timer",
|
||||||
|
+ .timer_freq = OX_ALVEO_UART_INPUT_FREQ,
|
||||||
|
+ .timer_value = ox_alveo_timer_value,
|
||||||
|
+ .timer_event_start = ox_alveo_timer_event_start,
|
||||||
|
+ .timer_event_stop = ox_alveo_timer_event_stop
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int ox_alveo_timer_init(bool cold_boot) // Initialize platform timer for current HART.
|
||||||
|
+{
|
||||||
|
+ *(timer_base_ptr + ADDR_TIMECMP_H) = 0;
|
||||||
|
+ *(timer_base_ptr + ADDR_TIMECMP_L) = 0;
|
||||||
|
+ sbi_timer_set_device(&mtimer);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+const struct sbi_platform_operations ox_alveo_ops = { // Platform descriptor.
|
||||||
|
+ .early_init = ox_alveo_early_init,
|
||||||
|
+ .final_init = ox_alveo_final_init,
|
||||||
|
+ .console_init = ox_alveo_console_init,
|
||||||
|
+ .irqchip_init = ox_alveo_irqchip_init,
|
||||||
|
+ .ipi_init = ox_alveo_ipi_init,
|
||||||
|
+ .timer_init = ox_alveo_timer_init
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+const struct sbi_platform platform = {
|
||||||
|
+ .opensbi_version = OPENSBI_VERSION,
|
||||||
|
+ .platform_version = SBI_PLATFORM_VERSION(0x0, 0x01),
|
||||||
|
+ .name = "ox (Rodrigo NixOS version)",
|
||||||
|
+ .features = SBI_PLATFORM_DEFAULT_FEATURES,
|
||||||
|
+ .hart_count = OX_ALVEO_HART_COUNT,
|
||||||
|
+ .hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE,
|
||||||
|
+ .heap_size = SBI_PLATFORM_DEFAULT_HEAP_SIZE(OX_ALVEO_HART_COUNT),
|
||||||
|
+ .platform_ops_addr = (unsigned long)&ox_alveo_ops
|
||||||
|
+};
|
148
patches/ox-alveo-platform.patch
Normal file
148
patches/ox-alveo-platform.patch
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
diff --git a/platform/fpga/ox_alveo/Kconfig b/platform/fpga/ox_alveo/Kconfig
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..bf3e7e6
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/platform/fpga/ox_alveo/Kconfig
|
||||||
|
@@ -0,0 +1,4 @@
|
||||||
|
+config PLATFORM_OX_ALVEO_FPGA
|
||||||
|
+ bool
|
||||||
|
+ select SERIAL_UART8250
|
||||||
|
+ default y
|
||||||
|
diff --git a/platform/fpga/ox_alveo/configs/defconfig b/platform/fpga/ox_alveo/configs/defconfig
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..e69de29
|
||||||
|
diff --git a/platform/fpga/ox_alveo/objects.mk b/platform/fpga/ox_alveo/objects.mk
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..d444abe
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/platform/fpga/ox_alveo/objects.mk
|
||||||
|
@@ -0,0 +1,19 @@
|
||||||
|
+platform-cppflags-y =
|
||||||
|
+platform-cflags-y =
|
||||||
|
+platform-asflags-y =
|
||||||
|
+platform-ldflags-y =
|
||||||
|
+PLATFORM_RISCV_XLEN = 64
|
||||||
|
+PLATFORM_RISCV_ABI = lp64d
|
||||||
|
+PLATFORM_RISCV_ISA = rv64imafd
|
||||||
|
+PLATFORM_RISCV_CODE_MODEL = medany
|
||||||
|
+
|
||||||
|
+platform-objs-y += platform.o
|
||||||
|
+
|
||||||
|
+FW_TEXT_START=0x80000000
|
||||||
|
+
|
||||||
|
+FW_DYNAMIC=n
|
||||||
|
+FW_JUMP=n
|
||||||
|
+FW_PAYLOAD=y
|
||||||
|
+
|
||||||
|
+FW_PAYLOAD_OFFSET=0x200000
|
||||||
|
+FW_PAYLOAD_ALIGN=0x1000
|
||||||
|
diff --git a/platform/fpga/ox_alveo/platform.c b/platform/fpga/ox_alveo/platform.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..a359b34
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/platform/fpga/ox_alveo/platform.c
|
||||||
|
@@ -0,0 +1,104 @@
|
||||||
|
+#include <sbi/riscv_asm.h>
|
||||||
|
+#include <sbi/riscv_encoding.h>
|
||||||
|
+#include <sbi/sbi_const.h>
|
||||||
|
+#include <sbi/sbi_platform.h>
|
||||||
|
+#include <sbi_utils/serial/uart8250.h>
|
||||||
|
+#include <sbi/sbi_timer.h>
|
||||||
|
+
|
||||||
|
+#define OX_ALVEO_HART_COUNT 1
|
||||||
|
+
|
||||||
|
+#define OX_ALVEO_UART_BASE_ADDR 0x40000000
|
||||||
|
+#define OX_ALVEO_UART_OFFSET 0x1000
|
||||||
|
+#define OX_ALVEO_UART_INPUT_FREQ 50000000
|
||||||
|
+#define OX_ALVEO_UART_BAUDRATE 115200
|
||||||
|
+
|
||||||
|
+#define OX_ALVEO_TIMER_BASE 0x40170000
|
||||||
|
+#define ADDR_TIME_L 0x0u // 32 lower bits of the time register
|
||||||
|
+#define ADDR_TIME_H 0x1u // 32 higher bits of the time register
|
||||||
|
+#define ADDR_TIMECMP_L 0x2u // 32 lower bits of the time comparator
|
||||||
|
+#define ADDR_TIMECMP_H 0x3u // 32 higher bits of the time comparator
|
||||||
|
+
|
||||||
|
+volatile uint32_t *timer_base_ptr = (uint32_t *)(OX_ALVEO_TIMER_BASE);
|
||||||
|
+
|
||||||
|
+static int ox_alveo_early_init(bool cold_boot) // Platform early initialization.
|
||||||
|
+{
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ox_alveo_final_init(bool cold_boot) // Platform final initialization.
|
||||||
|
+{
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ox_alveo_console_init(void) // Initialize the platform console.
|
||||||
|
+{
|
||||||
|
+ return uart8250_init(OX_ALVEO_UART_BASE_ADDR,
|
||||||
|
+ OX_ALVEO_UART_INPUT_FREQ,
|
||||||
|
+ OX_ALVEO_UART_BAUDRATE,
|
||||||
|
+ 2, 4,
|
||||||
|
+ OX_ALVEO_UART_OFFSET);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ox_alveo_irqchip_init(bool cold_boot) // Initialize the platform interrupt controller for current HART.
|
||||||
|
+{
|
||||||
|
+ u32 hartid = current_hartid();
|
||||||
|
+ return hartid;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ox_alveo_ipi_init(bool cold_boot) // Initialize IPI for current HART.
|
||||||
|
+{
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static u64 ox_alveo_timer_value(void) // Get platform timer value.
|
||||||
|
+{
|
||||||
|
+ return ((u64)*(timer_base_ptr + ADDR_TIME_H) << 32) + *(timer_base_ptr + ADDR_TIME_L);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void ox_alveo_timer_event_start(u64 next_event) // Start platform timer event for current HART.
|
||||||
|
+{
|
||||||
|
+ *(timer_base_ptr + ADDR_TIMECMP_H) = next_event >> 32;
|
||||||
|
+ *(timer_base_ptr + ADDR_TIMECMP_L) = next_event;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void ox_alveo_timer_event_stop(void) // Stop platform timer event for current HART.
|
||||||
|
+{
|
||||||
|
+
|
||||||
|
+ *(timer_base_ptr + ADDR_TIMECMP_H) = 0;
|
||||||
|
+ *(timer_base_ptr + ADDR_TIMECMP_L) = 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct sbi_timer_device mtimer = {
|
||||||
|
+ .name = "axi_timer",
|
||||||
|
+ .timer_freq = OX_ALVEO_UART_INPUT_FREQ,
|
||||||
|
+ .timer_value = ox_alveo_timer_value,
|
||||||
|
+ .timer_event_start = ox_alveo_timer_event_start,
|
||||||
|
+ .timer_event_stop = ox_alveo_timer_event_stop
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int ox_alveo_timer_init(bool cold_boot) // Initialize platform timer for current HART.
|
||||||
|
+{
|
||||||
|
+ *(timer_base_ptr + ADDR_TIMECMP_H) = 0;
|
||||||
|
+ *(timer_base_ptr + ADDR_TIMECMP_L) = 0;
|
||||||
|
+ sbi_timer_set_device(&mtimer);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+const struct sbi_platform_operations ox_alveo_ops = { // Platform descriptor.
|
||||||
|
+ .early_init = ox_alveo_early_init,
|
||||||
|
+ .final_init = ox_alveo_final_init,
|
||||||
|
+ .console_init = ox_alveo_console_init,
|
||||||
|
+ .irqchip_init = ox_alveo_irqchip_init,
|
||||||
|
+ .ipi_init = ox_alveo_ipi_init,
|
||||||
|
+ .timer_init = ox_alveo_timer_init
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+const struct sbi_platform platform = {
|
||||||
|
+ .opensbi_version = OPENSBI_VERSION,
|
||||||
|
+ .platform_version = SBI_PLATFORM_VERSION(0x0, 0x01),
|
||||||
|
+ .name = "ox (for Xilinx Alveo FPGA)",
|
||||||
|
+ .features = SBI_PLATFORM_DEFAULT_FEATURES,
|
||||||
|
+ .hart_count = OX_ALVEO_HART_COUNT,
|
||||||
|
+ .hart_stack_size = SBI_PLATFORM_DEFAULT_HART_STACK_SIZE,
|
||||||
|
+ .platform_ops_addr = (unsigned long)&ox_alveo_ops
|
||||||
|
+};
|
92
patches/sa-fpga-add-plic-claim-test.patch
Normal file
92
patches/sa-fpga-add-plic-claim-test.patch
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
commit 1a2c5f12e7676930123cfe7853f1805cf3680c25
|
||||||
|
Author: Rodrigo Arias Mallo <rodrigo.arias@bsc.es>
|
||||||
|
Date: Tue Oct 1 12:59:38 2024 +0200
|
||||||
|
|
||||||
|
Add claim test
|
||||||
|
|
||||||
|
diff --git a/fpga_core_bridge/simulator/tests/c_tests/Makefile b/fpga_core_bridge/simulator/tests/c_tests/Makefile
|
||||||
|
index f744131..91d61b6 100644
|
||||||
|
--- a/fpga_core_bridge/simulator/tests/c_tests/Makefile
|
||||||
|
+++ b/fpga_core_bridge/simulator/tests/c_tests/Makefile
|
||||||
|
@@ -23,6 +23,7 @@ bmarks = \
|
||||||
|
plic \
|
||||||
|
plic_supervisor \
|
||||||
|
plic_threshold \
|
||||||
|
+ plic_claim \
|
||||||
|
clint_supervisor \
|
||||||
|
uart
|
||||||
|
|
||||||
|
diff --git a/fpga_core_bridge/simulator/tests/c_tests/plic_claim/plic_claim.c b/fpga_core_bridge/simulator/tests/c_tests/plic_claim/plic_claim.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..352adb9
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/fpga_core_bridge/simulator/tests/c_tests/plic_claim/plic_claim.c
|
||||||
|
@@ -0,0 +1,68 @@
|
||||||
|
+#include "util.h"
|
||||||
|
+
|
||||||
|
+#define PLIC_BASE 0x40800000
|
||||||
|
+
|
||||||
|
+int main(void)
|
||||||
|
+{
|
||||||
|
+ uart_init();
|
||||||
|
+
|
||||||
|
+ /* This test requires the auxiliar timer to cause a pending
|
||||||
|
+ * interrupt in the source 4. All the other pending bits must be
|
||||||
|
+ * zero. */
|
||||||
|
+
|
||||||
|
+ uint32_t src = 4;
|
||||||
|
+ uint32_t mask = 1 << src;
|
||||||
|
+
|
||||||
|
+ /* 0x001000: Interrupt Source #0 to #31 Pending Bits */
|
||||||
|
+ volatile uint32_t *pending = PLIC_BASE + 0x001000;
|
||||||
|
+
|
||||||
|
+ /* Manually enable the pending register on both timer and serial */
|
||||||
|
+ *pending = (1<<4) | (1<<1);
|
||||||
|
+
|
||||||
|
+ uint32_t p;
|
||||||
|
+ /* Wait for a interrupt on the serial line */
|
||||||
|
+ while ((p = *pending) != (1<<4) | (1<<1)) {
|
||||||
|
+ printf("waiting, pending=");
|
||||||
|
+ printhex(p);
|
||||||
|
+ printf("\n");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* 0x002080: Interrupt Source #0 to #31 Enable Bits on context 1 */
|
||||||
|
+ volatile uint32_t *enable = PLIC_BASE + 0x002080;
|
||||||
|
+ *enable = (1<<4) | (1<<1); /* Enable source 4 (aux timer) and 1
|
||||||
|
+ (serial) */
|
||||||
|
+
|
||||||
|
+ /* 0x000004: Interrupt source 1 priority */
|
||||||
|
+ /* 0x000008: Interrupt source 2 priority */
|
||||||
|
+ /* 0x00000c: Interrupt source 3 priority */
|
||||||
|
+ /* 0x000010: Interrupt source 4 priority */
|
||||||
|
+ for (uint32_t i = 1; i <= 4; i++) {
|
||||||
|
+ volatile uint32_t *priority = PLIC_BASE + i * 4;
|
||||||
|
+ *priority = 1; /* Make priority larger than threshold */
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /* 0x201000: Priority threshold for context 1 */
|
||||||
|
+ volatile uint32_t *threshold = PLIC_BASE + 0x201000;
|
||||||
|
+ *threshold = 0; /* Make threshold small */
|
||||||
|
+
|
||||||
|
+ /* Now the context 1 must be receiving interrupts from the aux
|
||||||
|
+ * timer. Let's try to claim the interrupt. */
|
||||||
|
+
|
||||||
|
+ /* Read claim */
|
||||||
|
+
|
||||||
|
+ /* 0x201004: Interrupt Claim Process for context 1 */
|
||||||
|
+ volatile uint32_t *claim = PLIC_BASE + 0x201004;
|
||||||
|
+ while (1) {
|
||||||
|
+ uint32_t c = *claim;
|
||||||
|
+ if (c == src)
|
||||||
|
+ break;
|
||||||
|
+ printf("ERROR: unexpected claim found, expecting 4: ");
|
||||||
|
+ printhex(c);
|
||||||
|
+ printf("\n");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ while (1)
|
||||||
|
+ printf("SUCCESS: Claim test succeeded\n");
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
15
patches/sa-fpga-crt.patch
Normal file
15
patches/sa-fpga-crt.patch
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
diff --git a/fpga_core_bridge/simulator/tests/c_tests/common/crt.S b/fpga_core_bridge/simulator/tests/c_tests/common/crt.S
|
||||||
|
index 3f5bb2c..bd738b1 100644
|
||||||
|
--- a/fpga_core_bridge/simulator/tests/c_tests/common/crt.S
|
||||||
|
+++ b/fpga_core_bridge/simulator/tests/c_tests/common/crt.S
|
||||||
|
@@ -59,10 +59,6 @@ _start:
|
||||||
|
#else
|
||||||
|
bltz t0, 1f
|
||||||
|
#endif
|
||||||
|
-2:
|
||||||
|
- li a0, 1
|
||||||
|
- sw a0, tohost, t0
|
||||||
|
- j 2b
|
||||||
|
1:
|
||||||
|
|
||||||
|
#ifdef __riscv_flen
|
92
patches/sa-fpga-plic-registers.patch
Normal file
92
patches/sa-fpga-plic-registers.patch
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
diff --git a/fpga_core_bridge/simulator/tests/c_tests/plic_supervisor/plic_supervisor_test.c b/fpga_core_bridge/simulator/tests/c_tests/plic_supervisor/plic_supervisor_test.c
|
||||||
|
index 0cfa681..78d97cb 100644
|
||||||
|
--- a/fpga_core_bridge/simulator/tests/c_tests/plic_supervisor/plic_supervisor_test.c
|
||||||
|
+++ b/fpga_core_bridge/simulator/tests/c_tests/plic_supervisor/plic_supervisor_test.c
|
||||||
|
@@ -68,6 +68,48 @@ uintptr_t handle_trap(uint64_t cause, uint64_t epc, uintptr_t regs[32])
|
||||||
|
return epc;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void dumpregs(int machine)
|
||||||
|
+{
|
||||||
|
+ printf("Registers:");
|
||||||
|
+ if (machine) {
|
||||||
|
+ uint64_t mie;
|
||||||
|
+ asm volatile("csrr %0, mie" : "=r"(mie));
|
||||||
|
+ printf("\n MIE: ");
|
||||||
|
+ printhex(mie);
|
||||||
|
+
|
||||||
|
+ uint64_t mip;
|
||||||
|
+ asm volatile("csrr %0, mip" : "=r"(mip));
|
||||||
|
+ printf("\n MIP: ");
|
||||||
|
+ printhex(mip);
|
||||||
|
+
|
||||||
|
+ uint64_t mstatus;
|
||||||
|
+ asm volatile("csrr %0, mstatus" : "=r"(mstatus));
|
||||||
|
+ printf("\nMSTATUS: ");
|
||||||
|
+ printhex(mstatus);
|
||||||
|
+
|
||||||
|
+ uint64_t mideleg;
|
||||||
|
+ asm volatile("csrr %0, mideleg" : "=r"(mideleg));
|
||||||
|
+ printf("\nMIDELEG: ");
|
||||||
|
+ printhex(mideleg);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ uint64_t sie;
|
||||||
|
+ asm volatile("csrr %0, sie" : "=r"(sie));
|
||||||
|
+ printf("\n SIE: ");
|
||||||
|
+ printhex(sie);
|
||||||
|
+
|
||||||
|
+ uint64_t sip;
|
||||||
|
+ asm volatile("csrr %0, sip" : "=r"(sip));
|
||||||
|
+ printf("\n SIP: ");
|
||||||
|
+ printhex(sip);
|
||||||
|
+
|
||||||
|
+ uint64_t sstatus;
|
||||||
|
+ asm volatile("csrr %0, sstatus" : "=r"(sstatus));
|
||||||
|
+ printf("\nSSTATUS: ");
|
||||||
|
+ printhex(sstatus);
|
||||||
|
+ printf("\n");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
// Define the bit positions for the external interrupt enable in mie and mideleg registers
|
||||||
|
#define SIE_SEIE (1 << 9) // Supervisor External Interrupt Enable
|
||||||
|
#define MIDELEG_MEIE (1 << 11) // Delegate Machine External Interrupt to Supervisor
|
||||||
|
@@ -156,16 +198,19 @@ void __attribute__((optimize("O0"))) switch_to_supervisor_mode(uint64_t* target_
|
||||||
|
asm volatile("mret");
|
||||||
|
}
|
||||||
|
|
||||||
|
-uint64_t supervisor_mode_code() {
|
||||||
|
- int count = 0;
|
||||||
|
- while (1) {
|
||||||
|
- if (count == 10000) {
|
||||||
|
- uart_write_string("\nWaiting for interrupt in supervisor mode...");
|
||||||
|
- count = 0;
|
||||||
|
- }
|
||||||
|
- count++;
|
||||||
|
- }
|
||||||
|
- return 0;
|
||||||
|
+uint64_t supervisor_mode_code()
|
||||||
|
+{
|
||||||
|
+ uart_write_string("\nHello from supervisor mode...");
|
||||||
|
+ dumpregs(0);
|
||||||
|
+ int count = 0;
|
||||||
|
+ while (1) {
|
||||||
|
+ if (count == 10000) {
|
||||||
|
+ uart_write_string("\nWaiting for interrupt in supervisor mode...");
|
||||||
|
+ count = 0;
|
||||||
|
+ }
|
||||||
|
+ count++;
|
||||||
|
+ }
|
||||||
|
+ return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
@@ -181,6 +226,8 @@ void main(void) {
|
||||||
|
// Enable external timer interrupts
|
||||||
|
// enable_external_timer_interrupt();
|
||||||
|
|
||||||
|
+ dumpregs(1);
|
||||||
|
+
|
||||||
|
// Switch to supervisor mode and execute supervisor_mode_code
|
||||||
|
switch_to_supervisor_mode(&supervisor_mode_code);
|
||||||
|
|
13
patches/sa-fpga-text-address.patch
Normal file
13
patches/sa-fpga-text-address.patch
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
diff --git a/fpga_core_bridge/simulator/tests/c_tests/common/test.ld b/fpga_core_bridge/simulator/tests/c_tests/common/test.ld
|
||||||
|
index 8321d86..f83a9ee 100644
|
||||||
|
--- a/fpga_core_bridge/simulator/tests/c_tests/common/test.ld
|
||||||
|
+++ b/fpga_core_bridge/simulator/tests/c_tests/common/test.ld
|
||||||
|
@@ -26,7 +26,7 @@ SECTIONS
|
||||||
|
.tohost : { *(.tohost) }
|
||||||
|
|
||||||
|
/* text: test code section */
|
||||||
|
- . = 0x80000000;
|
||||||
|
+ . = 0x20020000;
|
||||||
|
.text.init : { *(.text.init) }
|
||||||
|
|
||||||
|
. = ALIGN(0x1000);
|
31
patches/sa-fpga-uart.patch
Normal file
31
patches/sa-fpga-uart.patch
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
diff --git a/fpga_core_bridge/simulator/tests/c_tests/common/syscalls.c b/fpga_core_bridge/simulator/tests/c_tests/common/syscalls.c
|
||||||
|
index 278ea97..287e5fc 100644
|
||||||
|
--- a/fpga_core_bridge/simulator/tests/c_tests/common/syscalls.c
|
||||||
|
+++ b/fpga_core_bridge/simulator/tests/c_tests/common/syscalls.c
|
||||||
|
@@ -592,8 +592,18 @@ int uart_is_transmit_empty() {
|
||||||
|
|
||||||
|
// Function to write a character to the UART
|
||||||
|
void uart_write_char(char c) {
|
||||||
|
- while (!uart_is_transmit_empty());
|
||||||
|
+ //while (!uart_is_transmit_empty());
|
||||||
|
+
|
||||||
|
+ /* Delay it a bit, as checking the transmit holding register doesn't seem to
|
||||||
|
+ * work in the FPGA */
|
||||||
|
+ for (volatile long i = 0; i < 10000; i++)
|
||||||
|
+ ;
|
||||||
|
+
|
||||||
|
*(volatile uint8_t *)(UART_BASE + UART_THR) = c;
|
||||||
|
+
|
||||||
|
+ /* Make new line go back to the start of the line */
|
||||||
|
+ if (c == '\n')
|
||||||
|
+ uart_write_char('\r');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to write a string to the UART
|
||||||
|
@@ -602,4 +612,4 @@ void uart_write_string(const char* str) {
|
||||||
|
uart_write_char(*str++);
|
||||||
|
asm("fence");
|
||||||
|
}
|
||||||
|
-}
|
||||||
|
\ No newline at end of file
|
||||||
|
+}
|
157
patches/stage-2-init.sh
Executable file
157
patches/stage-2-init.sh
Executable file
@ -0,0 +1,157 @@
|
|||||||
|
#! @shell@
|
||||||
|
|
||||||
|
#set -x
|
||||||
|
|
||||||
|
systemConfig=@systemConfig@
|
||||||
|
|
||||||
|
export HOME=/root PATH="@path@"
|
||||||
|
|
||||||
|
|
||||||
|
if [ "${IN_NIXOS_SYSTEMD_STAGE1:-}" != true ]; then
|
||||||
|
# Print a greeting.
|
||||||
|
echo
|
||||||
|
echo -e "\e[1;32m<<< @distroName@ Stage 2 >>>\e[0m"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Process the kernel command line.
|
||||||
|
for o in $(</proc/cmdline); do
|
||||||
|
case $o in
|
||||||
|
boot.debugtrace)
|
||||||
|
# Show each command.
|
||||||
|
set -x
|
||||||
|
;;
|
||||||
|
debug2)
|
||||||
|
export PATH="@bashInteractive@/bin:@systemConfig@/sw/bin:$PATH"
|
||||||
|
setsid bash -c "exec bash -l </dev/hvc0 >/dev/hvc0 2>/dev/hvc0"
|
||||||
|
;;
|
||||||
|
bench2)
|
||||||
|
export PATH="@bashInteractive@/bin:@systemConfig@/sw/bin:$PATH"
|
||||||
|
setsid bash -c "exec @bench2@ </dev/hvc0 >/dev/hvc0 2>/dev/hvc0"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Normally, stage 1 mounts the root filesystem read/writable.
|
||||||
|
# However, in some environments, stage 2 is executed directly, and the
|
||||||
|
# root is read-only. So make it writable here.
|
||||||
|
if [ -z "$container" ]; then
|
||||||
|
mount -n -o remount,rw none /
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Likewise, stage 1 mounts /proc, /dev and /sys, so if we don't have a
|
||||||
|
# stage 1, we need to do that here.
|
||||||
|
if [ ! -e /proc/1 ]; then
|
||||||
|
specialMount() {
|
||||||
|
local device="$1"
|
||||||
|
local mountPoint="$2"
|
||||||
|
local options="$3"
|
||||||
|
local fsType="$4"
|
||||||
|
|
||||||
|
# We must not overwrite this mount because it's bind-mounted
|
||||||
|
# from stage 1's /run
|
||||||
|
if [ "${IN_NIXOS_SYSTEMD_STAGE1:-}" = true ] && [ "${mountPoint}" = /run ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
install -m 0755 -d "$mountPoint"
|
||||||
|
mount -n -t "$fsType" -o "$options" "$device" "$mountPoint"
|
||||||
|
}
|
||||||
|
source @earlyMountScript@
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
if [ "${IN_NIXOS_SYSTEMD_STAGE1:-}" = true ] || [ ! -c /dev/kmsg ] ; then
|
||||||
|
echo "booting system configuration ${systemConfig}"
|
||||||
|
else
|
||||||
|
echo "booting system configuration $systemConfig" > /dev/kmsg
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Make /nix/store a read-only bind mount to enforce immutability of
|
||||||
|
# the Nix store. Note that we can't use "chown root:nixbld" here
|
||||||
|
# because users/groups might not exist yet.
|
||||||
|
# Silence chown/chmod to fail gracefully on a readonly filesystem
|
||||||
|
# like squashfs.
|
||||||
|
chown -f 0:30000 /nix/store
|
||||||
|
chmod -f 1775 /nix/store
|
||||||
|
if [ -n "@readOnlyNixStore@" ]; then
|
||||||
|
if ! [[ "$(findmnt --noheadings --output OPTIONS /nix/store)" =~ ro(,|$) ]]; then
|
||||||
|
if [ -z "$container" ]; then
|
||||||
|
mount --bind /nix/store /nix/store
|
||||||
|
else
|
||||||
|
mount --rbind /nix/store /nix/store
|
||||||
|
fi
|
||||||
|
mount -o remount,ro,bind /nix/store
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
if [ "${IN_NIXOS_SYSTEMD_STAGE1:-}" != true ]; then
|
||||||
|
# Use /etc/resolv.conf supplied by systemd-nspawn, if applicable.
|
||||||
|
if [ -n "@useHostResolvConf@" ] && [ -e /etc/resolv.conf ]; then
|
||||||
|
resolvconf -m 1000 -a host </etc/resolv.conf
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# # Log the script output to /dev/kmsg or /run/log/stage-2-init.log.
|
||||||
|
# # Only at this point are all the necessary prerequisites ready for these commands.
|
||||||
|
# exec {logOutFd}>&1 {logErrFd}>&2
|
||||||
|
# if test -w /dev/kmsg; then
|
||||||
|
# exec > >(tee -i /proc/self/fd/"$logOutFd" | while read -r line; do
|
||||||
|
# if test -n "$line"; then
|
||||||
|
# echo "<7>stage-2-init: $line" > /dev/kmsg
|
||||||
|
# fi
|
||||||
|
# done) 2>&1
|
||||||
|
# else
|
||||||
|
# mkdir -p /run/log
|
||||||
|
# exec > >(tee -i /run/log/stage-2-init.log) 2>&1
|
||||||
|
# fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Required by the activation script
|
||||||
|
install -m 0755 -d /etc
|
||||||
|
if [ ! -h "/etc/nixos" ]; then
|
||||||
|
install -m 0755 -d /etc/nixos
|
||||||
|
fi
|
||||||
|
install -m 01777 -d /tmp
|
||||||
|
|
||||||
|
|
||||||
|
# Run the script that performs all configuration activation that does
|
||||||
|
# not have to be done at boot time.
|
||||||
|
echo "running activation script..."
|
||||||
|
#strace -f $systemConfig/activate
|
||||||
|
$systemConfig/activate
|
||||||
|
|
||||||
|
echo "activation script OK"
|
||||||
|
|
||||||
|
# Record the boot configuration.
|
||||||
|
ln -sfn "$systemConfig" /run/booted-system
|
||||||
|
|
||||||
|
|
||||||
|
# Run any user-specified commands.
|
||||||
|
@shell@ @postBootCommands@
|
||||||
|
|
||||||
|
|
||||||
|
# Ensure systemd doesn't try to populate /etc, by forcing its first-boot
|
||||||
|
# heuristic off. It doesn't matter what's in /etc/machine-id for this purpose,
|
||||||
|
# and systemd will immediately fill in the file when it starts, so just
|
||||||
|
# creating it is enough. This `: >>` pattern avoids forking and avoids changing
|
||||||
|
# the mtime if the file already exists.
|
||||||
|
: >> /etc/machine-id
|
||||||
|
|
||||||
|
|
||||||
|
# No need to restore the stdout/stderr streams we never redirected and
|
||||||
|
# especially no need to start systemd
|
||||||
|
if [ "${IN_NIXOS_SYSTEMD_STAGE1:-}" != true ]; then
|
||||||
|
# Reset the logging file descriptors.
|
||||||
|
#exec 1>&$logOutFd 2>&$logErrFd
|
||||||
|
#exec {logOutFd}>&- {logErrFd}>&-
|
||||||
|
|
||||||
|
|
||||||
|
# Start systemd in a clean environment.
|
||||||
|
echo "starting systemd..."
|
||||||
|
exec @systemdExecutable@ "$@"
|
||||||
|
fi
|
83
patches/u-boot-debug.patch
Normal file
83
patches/u-boot-debug.patch
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
diff --git a/common/board_f.c b/common/board_f.c
|
||||||
|
index 1688e27071..216839febb 100644
|
||||||
|
--- a/common/board_f.c
|
||||||
|
+++ b/common/board_f.c
|
||||||
|
@@ -978,6 +978,8 @@ static const init_fnc_t init_sequence_f[] = {
|
||||||
|
|
||||||
|
void board_init_f(ulong boot_flags)
|
||||||
|
{
|
||||||
|
+ puts("board_init_f() called\n");
|
||||||
|
+
|
||||||
|
gd->flags = boot_flags;
|
||||||
|
gd->have_console = 0;
|
||||||
|
|
||||||
|
@@ -990,6 +992,7 @@ void board_init_f(ulong boot_flags)
|
||||||
|
/* NOTREACHED - jump_to_copy() does not return */
|
||||||
|
hang();
|
||||||
|
#endif
|
||||||
|
+ puts("board_init_f() ends ok\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_X86) || defined(CONFIG_ARC)
|
||||||
|
diff --git a/common/board_r.c b/common/board_r.c
|
||||||
|
index d798c00a80..cb8119a603 100644
|
||||||
|
--- a/common/board_r.c
|
||||||
|
+++ b/common/board_r.c
|
||||||
|
@@ -786,6 +786,8 @@ static init_fnc_t init_sequence_r[] = {
|
||||||
|
|
||||||
|
void board_init_r(gd_t *new_gd, ulong dest_addr)
|
||||||
|
{
|
||||||
|
+ puts("board_init_r called\n");
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* The pre-relocation drivers may be using memory that has now gone
|
||||||
|
* away. Mark serial as unavailable - this will fall back to the debug
|
||||||
|
diff --git a/drivers/cpu/riscv_cpu.c b/drivers/cpu/riscv_cpu.c
|
||||||
|
index d6484d7f4b..64a507248d 100644
|
||||||
|
--- a/drivers/cpu/riscv_cpu.c
|
||||||
|
+++ b/drivers/cpu/riscv_cpu.c
|
||||||
|
@@ -92,10 +92,13 @@ static int riscv_cpu_get_count(const struct udevice *dev)
|
||||||
|
|
||||||
|
static int riscv_cpu_bind(struct udevice *dev)
|
||||||
|
{
|
||||||
|
+ puts("riscv_cpu_bind called()\n");
|
||||||
|
+
|
||||||
|
struct cpu_plat *plat = dev_get_parent_plat(dev);
|
||||||
|
struct driver *drv;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
+ puts("looking for timebase-frequency\n");
|
||||||
|
/* save the hart id */
|
||||||
|
plat->cpu_id = dev_read_addr(dev);
|
||||||
|
/* first examine the property in current cpu node */
|
||||||
|
@@ -105,6 +108,8 @@ static int riscv_cpu_bind(struct udevice *dev)
|
||||||
|
dev_read_u32(dev->parent, "timebase-frequency",
|
||||||
|
&plat->timebase_freq);
|
||||||
|
|
||||||
|
+ printf("timebase-frequency=%lu\n", (unsigned long) plat->timebase_freq);
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* Bind riscv-timer driver on boot hart.
|
||||||
|
*
|
||||||
|
@@ -125,6 +130,8 @@ static int riscv_cpu_bind(struct udevice *dev)
|
||||||
|
device_bind_with_driver_data(dev, drv, "riscv_timer",
|
||||||
|
plat->timebase_freq, ofnode_null(),
|
||||||
|
NULL);
|
||||||
|
+ } else {
|
||||||
|
+ printf("ignoring cpu_id=%d\n", plat->cpu_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
diff --git a/lib/hang.c b/lib/hang.c
|
||||||
|
index 2735774f9a..84eff21ffc 100644
|
||||||
|
--- a/lib/hang.c
|
||||||
|
+++ b/lib/hang.c
|
||||||
|
@@ -22,6 +22,8 @@
|
||||||
|
*/
|
||||||
|
void hang(void)
|
||||||
|
{
|
||||||
|
+ puts("oh no, we are in hang()\n");
|
||||||
|
+
|
||||||
|
#if !defined(CONFIG_SPL_BUILD) || \
|
||||||
|
(CONFIG_IS_ENABLED(LIBCOMMON_SUPPORT) && \
|
||||||
|
CONFIG_IS_ENABLED(SERIAL))
|
31
patches/uboot-debug-ext-interrupts.patch
Normal file
31
patches/uboot-debug-ext-interrupts.patch
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
diff --git a/arch/riscv/cpu/start.S b/arch/riscv/cpu/start.S
|
||||||
|
index 6cecadfac5..f649844b23 100644
|
||||||
|
--- a/arch/riscv/cpu/start.S
|
||||||
|
+++ b/arch/riscv/cpu/start.S
|
||||||
|
@@ -81,7 +81,7 @@ _start:
|
||||||
|
#if CONFIG_IS_ENABLED(RISCV_MMODE)
|
||||||
|
li t0, MIE_MSIE
|
||||||
|
#else
|
||||||
|
- li t0, SIE_SSIE
|
||||||
|
+ li t0, (SIE_SSIE + SIE_SEIE + SIE_STIE)
|
||||||
|
#endif
|
||||||
|
csrs MODE_PREFIX(ie), t0
|
||||||
|
#endif
|
||||||
|
diff --git a/arch/riscv/lib/interrupts.c b/arch/riscv/lib/interrupts.c
|
||||||
|
index a26ccc721f..b8d2a71223 100644
|
||||||
|
--- a/arch/riscv/lib/interrupts.c
|
||||||
|
+++ b/arch/riscv/lib/interrupts.c
|
||||||
|
@@ -193,10 +193,13 @@ ulong handle_trap(ulong cause, ulong epc, ulong tval, struct pt_regs *regs)
|
||||||
|
switch (irq) {
|
||||||
|
case IRQ_M_EXT:
|
||||||
|
case IRQ_S_EXT:
|
||||||
|
+ printf("u-boot: got ext interrupt %lu\n", irq);
|
||||||
|
+ show_regs(regs);
|
||||||
|
external_interrupt(0); /* handle external interrupt */
|
||||||
|
break;
|
||||||
|
case IRQ_M_TIMER:
|
||||||
|
case IRQ_S_TIMER:
|
||||||
|
+ printf("u-boot: got timer interrupt %lu\n", irq);
|
||||||
|
timer_interrupt(0); /* handle timer interrupt */
|
||||||
|
break;
|
||||||
|
default:
|
65
patches/uboot-exception-extras.patch
Normal file
65
patches/uboot-exception-extras.patch
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
diff --git a/cmd/riscv/exception.c b/cmd/riscv/exception.c
|
||||||
|
index f38f454a0b..9de4effe47 100644
|
||||||
|
--- a/cmd/riscv/exception.c
|
||||||
|
+++ b/cmd/riscv/exception.c
|
||||||
|
@@ -56,6 +56,40 @@ static int do_undefined(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||||
|
return CMD_RET_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int do_sregs(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||||
|
+ char *const argv[])
|
||||||
|
+{
|
||||||
|
+ ulong stvec, sie, sip, sstatus;
|
||||||
|
+
|
||||||
|
+ asm volatile ("fence");
|
||||||
|
+ asm volatile ("csrr %0, stvec" : "=r"(stvec) : );
|
||||||
|
+ asm volatile ("csrr %0, sie" : "=r"(sie) : );
|
||||||
|
+ asm volatile ("csrr %0, sip" : "=r"(sip) : );
|
||||||
|
+ asm volatile ("csrr %0, sstatus" : "=r"(sstatus) : );
|
||||||
|
+
|
||||||
|
+ printf("stvec : 0x%016lx\n", stvec);
|
||||||
|
+ printf("sie : 0x%016lx\n", sie);
|
||||||
|
+ printf("sip : 0x%016lx\n", sip);
|
||||||
|
+ printf("sstatus : 0x%016lx\n", sstatus);
|
||||||
|
+
|
||||||
|
+ return CMD_RET_SUCCESS;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int do_enable(struct cmd_tbl *cmdtp, int flag, int argc,
|
||||||
|
+ char *const argv[])
|
||||||
|
+{
|
||||||
|
+ ulong which = SIE_SSIE | SIE_SEIE | SIE_STIE;
|
||||||
|
+
|
||||||
|
+ asm volatile (
|
||||||
|
+ "csrsi sstatus, 2\n" /* Enable SIE */
|
||||||
|
+ "csrs sie, %0\n" /* Enable selected interrupts */
|
||||||
|
+ : /* no output */
|
||||||
|
+ : "r" (which)
|
||||||
|
+ );
|
||||||
|
+
|
||||||
|
+ return CMD_RET_SUCCESS;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static struct cmd_tbl cmd_sub[] = {
|
||||||
|
U_BOOT_CMD_MKENT(compressed, CONFIG_SYS_MAXARGS, 1, do_compressed,
|
||||||
|
"", ""),
|
||||||
|
@@ -67,6 +101,10 @@ static struct cmd_tbl cmd_sub[] = {
|
||||||
|
"", ""),
|
||||||
|
U_BOOT_CMD_MKENT(undefined, CONFIG_SYS_MAXARGS, 1, do_undefined,
|
||||||
|
"", ""),
|
||||||
|
+ U_BOOT_CMD_MKENT(sregs, CONFIG_SYS_MAXARGS, 1, do_sregs,
|
||||||
|
+ "", ""),
|
||||||
|
+ U_BOOT_CMD_MKENT(enable, CONFIG_SYS_MAXARGS, 1, do_enable,
|
||||||
|
+ "", ""),
|
||||||
|
};
|
||||||
|
|
||||||
|
static char exception_help_text[] =
|
||||||
|
@@ -77,6 +115,8 @@ static char exception_help_text[] =
|
||||||
|
" ialign16 - 16 bit aligned instruction\n"
|
||||||
|
" undefined - illegal instruction\n"
|
||||||
|
" unaligned - load address misaligned\n"
|
||||||
|
+ " sregs - print supervisor registers\n"
|
||||||
|
+ " enable - enable supervisor interrupts\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
#include <exception.h>
|
379
patches/update-users-groups.pl
Normal file
379
patches/update-users-groups.pl
Normal file
@ -0,0 +1,379 @@
|
|||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
use File::Path qw(make_path);
|
||||||
|
use File::Slurp;
|
||||||
|
use Getopt::Long;
|
||||||
|
use JSON;
|
||||||
|
use Time::Piece;
|
||||||
|
|
||||||
|
# Keep track of deleted uids and gids.
|
||||||
|
my $uidMapFile = "/var/lib/nixos/uid-map";
|
||||||
|
my $uidMap = -e $uidMapFile ? decode_json(read_file($uidMapFile)) : {};
|
||||||
|
|
||||||
|
my $gidMapFile = "/var/lib/nixos/gid-map";
|
||||||
|
my $gidMap = -e $gidMapFile ? decode_json(read_file($gidMapFile)) : {};
|
||||||
|
|
||||||
|
my $is_dry = ($ENV{'NIXOS_ACTION'} // "") eq "dry-activate";
|
||||||
|
GetOptions("dry-activate" => \$is_dry);
|
||||||
|
make_path("/var/lib/nixos", { mode => 0755 }) unless $is_dry;
|
||||||
|
|
||||||
|
sub updateFile {
|
||||||
|
my ($path, $contents, $perms) = @_;
|
||||||
|
return if $is_dry;
|
||||||
|
write_file($path, { atomic => 1, binmode => ':utf8', perms => $perms // 0644 }, $contents) or die;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Converts an ISO date to number of days since 1970-01-01
|
||||||
|
sub dateToDays {
|
||||||
|
my ($date) = @_;
|
||||||
|
my $time = Time::Piece->strptime($date, "%Y-%m-%d");
|
||||||
|
return $time->epoch / 60 / 60 / 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub nscdInvalidate {
|
||||||
|
system("echo", "nscd", "--invalidate", $_[0]) unless $is_dry;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub hashPassword {
|
||||||
|
my ($password) = @_;
|
||||||
|
my $salt = "";
|
||||||
|
my @chars = ('.', '/', 0..9, 'A'..'Z', 'a'..'z');
|
||||||
|
$salt .= $chars[rand 64] for (1..8);
|
||||||
|
return crypt($password, '$6$' . $salt . '$');
|
||||||
|
}
|
||||||
|
|
||||||
|
sub dry_print {
|
||||||
|
if ($is_dry) {
|
||||||
|
print STDERR ("$_[1] $_[2]\n")
|
||||||
|
} else {
|
||||||
|
print STDERR ("$_[0] $_[2]\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Functions for allocating free GIDs/UIDs. FIXME: respect ID ranges in
|
||||||
|
# /etc/login.defs.
|
||||||
|
sub allocId {
|
||||||
|
my ($used, $prevUsed, $idMin, $idMax, $up, $getid) = @_;
|
||||||
|
my $id = $up ? $idMin : $idMax;
|
||||||
|
while ($id >= $idMin && $id <= $idMax) {
|
||||||
|
if (!$used->{$id} && !$prevUsed->{$id} && !defined &$getid($id)) {
|
||||||
|
$used->{$id} = 1;
|
||||||
|
return $id;
|
||||||
|
}
|
||||||
|
$used->{$id} = 1;
|
||||||
|
if ($up) { $id++; } else { $id--; }
|
||||||
|
}
|
||||||
|
die "$0: out of free UIDs or GIDs\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
my (%gidsUsed, %uidsUsed, %gidsPrevUsed, %uidsPrevUsed);
|
||||||
|
|
||||||
|
sub allocGid {
|
||||||
|
my ($name) = @_;
|
||||||
|
my $prevGid = $gidMap->{$name};
|
||||||
|
if (defined $prevGid && !defined $gidsUsed{$prevGid}) {
|
||||||
|
dry_print("reviving", "would revive", "group '$name' with GID $prevGid");
|
||||||
|
$gidsUsed{$prevGid} = 1;
|
||||||
|
return $prevGid;
|
||||||
|
}
|
||||||
|
return allocId(\%gidsUsed, \%gidsPrevUsed, 400, 999, 0, sub { my ($gid) = @_; getgrgid($gid) });
|
||||||
|
}
|
||||||
|
|
||||||
|
sub allocUid {
|
||||||
|
my ($name, $isSystemUser) = @_;
|
||||||
|
my ($min, $max, $up) = $isSystemUser ? (400, 999, 0) : (1000, 29999, 1);
|
||||||
|
my $prevUid = $uidMap->{$name};
|
||||||
|
if (defined $prevUid && $prevUid >= $min && $prevUid <= $max && !defined $uidsUsed{$prevUid}) {
|
||||||
|
dry_print("reviving", "would revive", "user '$name' with UID $prevUid");
|
||||||
|
$uidsUsed{$prevUid} = 1;
|
||||||
|
return $prevUid;
|
||||||
|
}
|
||||||
|
return allocId(\%uidsUsed, \%uidsPrevUsed, $min, $max, $up, sub { my ($uid) = @_; getpwuid($uid) });
|
||||||
|
}
|
||||||
|
|
||||||
|
# Read the declared users/groups
|
||||||
|
my $spec = decode_json(read_file($ARGV[0]));
|
||||||
|
|
||||||
|
# Don't allocate UIDs/GIDs that are manually assigned.
|
||||||
|
foreach my $g (@{$spec->{groups}}) {
|
||||||
|
$gidsUsed{$g->{gid}} = 1 if defined $g->{gid};
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach my $u (@{$spec->{users}}) {
|
||||||
|
$uidsUsed{$u->{uid}} = 1 if defined $u->{uid};
|
||||||
|
}
|
||||||
|
|
||||||
|
# Likewise for previously used but deleted UIDs/GIDs.
|
||||||
|
$uidsPrevUsed{$_} = 1 foreach values %{$uidMap};
|
||||||
|
$gidsPrevUsed{$_} = 1 foreach values %{$gidMap};
|
||||||
|
|
||||||
|
|
||||||
|
# Read the current /etc/group.
|
||||||
|
sub parseGroup {
|
||||||
|
chomp;
|
||||||
|
my @f = split(':', $_, -4);
|
||||||
|
my $gid = $f[2] eq "" ? undef : int($f[2]);
|
||||||
|
$gidsUsed{$gid} = 1 if defined $gid;
|
||||||
|
return ($f[0], { name => $f[0], password => $f[1], gid => $gid, members => $f[3] });
|
||||||
|
}
|
||||||
|
|
||||||
|
my %groupsCur = -f "/etc/group" ? map { parseGroup } read_file("/etc/group", { binmode => ":utf8" }) : ();
|
||||||
|
|
||||||
|
# Read the current /etc/passwd.
|
||||||
|
sub parseUser {
|
||||||
|
chomp;
|
||||||
|
my @f = split(':', $_, -7);
|
||||||
|
my $uid = $f[2] eq "" ? undef : int($f[2]);
|
||||||
|
$uidsUsed{$uid} = 1 if defined $uid;
|
||||||
|
return ($f[0], { name => $f[0], fakePassword => $f[1], uid => $uid,
|
||||||
|
gid => $f[3], description => $f[4], home => $f[5], shell => $f[6] });
|
||||||
|
}
|
||||||
|
my %usersCur = -f "/etc/passwd" ? map { parseUser } read_file("/etc/passwd", { binmode => ":utf8" }) : ();
|
||||||
|
|
||||||
|
# Read the groups that were created declaratively (i.e. not by groups)
|
||||||
|
# in the past. These must be removed if they are no longer in the
|
||||||
|
# current spec.
|
||||||
|
my $declGroupsFile = "/var/lib/nixos/declarative-groups";
|
||||||
|
my %declGroups;
|
||||||
|
$declGroups{$_} = 1 foreach split / /, -e $declGroupsFile ? read_file($declGroupsFile, { binmode => ":utf8" }) : "";
|
||||||
|
|
||||||
|
# Idem for the users.
|
||||||
|
my $declUsersFile = "/var/lib/nixos/declarative-users";
|
||||||
|
my %declUsers;
|
||||||
|
$declUsers{$_} = 1 foreach split / /, -e $declUsersFile ? read_file($declUsersFile, { binmode => ":utf8" }) : "";
|
||||||
|
|
||||||
|
|
||||||
|
# Generate a new /etc/group containing the declared groups.
|
||||||
|
my %groupsOut;
|
||||||
|
foreach my $g (@{$spec->{groups}}) {
|
||||||
|
my $name = $g->{name};
|
||||||
|
my $existing = $groupsCur{$name};
|
||||||
|
|
||||||
|
my %members = map { ($_, 1) } @{$g->{members}};
|
||||||
|
|
||||||
|
if (defined $existing) {
|
||||||
|
$g->{gid} = $existing->{gid} if !defined $g->{gid};
|
||||||
|
if ($g->{gid} != $existing->{gid}) {
|
||||||
|
dry_print("warning: not applying", "warning: would not apply", "GID change of group ‘$name’ ($existing->{gid} -> $g->{gid}) in /etc/group");
|
||||||
|
$g->{gid} = $existing->{gid};
|
||||||
|
}
|
||||||
|
$g->{password} = $existing->{password}; # do we want this?
|
||||||
|
if ($spec->{mutableUsers}) {
|
||||||
|
# Merge in non-declarative group members.
|
||||||
|
foreach my $uname (split /,/, $existing->{members} // "") {
|
||||||
|
$members{$uname} = 1 if !defined $declUsers{$uname};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$g->{gid} = allocGid($name) if !defined $g->{gid};
|
||||||
|
$g->{password} = "x";
|
||||||
|
}
|
||||||
|
|
||||||
|
$g->{members} = join ",", sort(keys(%members));
|
||||||
|
$groupsOut{$name} = $g;
|
||||||
|
|
||||||
|
$gidMap->{$name} = $g->{gid};
|
||||||
|
}
|
||||||
|
|
||||||
|
# Update the persistent list of declarative groups.
|
||||||
|
updateFile($declGroupsFile, join(" ", sort(keys %groupsOut)));
|
||||||
|
|
||||||
|
# Merge in the existing /etc/group.
|
||||||
|
foreach my $name (keys %groupsCur) {
|
||||||
|
my $g = $groupsCur{$name};
|
||||||
|
next if defined $groupsOut{$name};
|
||||||
|
if (!$spec->{mutableUsers} || defined $declGroups{$name}) {
|
||||||
|
dry_print("removing group", "would remove group", "‘$name’");
|
||||||
|
} else {
|
||||||
|
$groupsOut{$name} = $g;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Rewrite /etc/group. FIXME: acquire lock.
|
||||||
|
my @lines = map { join(":", $_->{name}, $_->{password}, $_->{gid}, $_->{members}) . "\n" }
|
||||||
|
(sort { $a->{gid} <=> $b->{gid} } values(%groupsOut));
|
||||||
|
updateFile($gidMapFile, to_json($gidMap, {canonical => 1}));
|
||||||
|
updateFile("/etc/group", \@lines);
|
||||||
|
nscdInvalidate("group");
|
||||||
|
|
||||||
|
# Generate a new /etc/passwd containing the declared users.
|
||||||
|
my %usersOut;
|
||||||
|
foreach my $u (@{$spec->{users}}) {
|
||||||
|
my $name = $u->{name};
|
||||||
|
|
||||||
|
# Resolve the gid of the user.
|
||||||
|
if ($u->{group} =~ /^[0-9]$/) {
|
||||||
|
$u->{gid} = $u->{group};
|
||||||
|
} elsif (defined $groupsOut{$u->{group}}) {
|
||||||
|
$u->{gid} = $groupsOut{$u->{group}}->{gid} // die;
|
||||||
|
} else {
|
||||||
|
warn "warning: user ‘$name’ has unknown group ‘$u->{group}’\n";
|
||||||
|
$u->{gid} = 65534;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $existing = $usersCur{$name};
|
||||||
|
if (defined $existing) {
|
||||||
|
$u->{uid} = $existing->{uid} if !defined $u->{uid};
|
||||||
|
if ($u->{uid} != $existing->{uid}) {
|
||||||
|
dry_print("warning: not applying", "warning: would not apply", "UID change of user ‘$name’ ($existing->{uid} -> $u->{uid}) in /etc/passwd");
|
||||||
|
$u->{uid} = $existing->{uid};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$u->{uid} = allocUid($name, $u->{isSystemUser}) if !defined $u->{uid};
|
||||||
|
|
||||||
|
if (!defined $u->{hashedPassword}) {
|
||||||
|
if (defined $u->{initialPassword}) {
|
||||||
|
$u->{hashedPassword} = hashPassword($u->{initialPassword});
|
||||||
|
} elsif (defined $u->{initialHashedPassword}) {
|
||||||
|
$u->{hashedPassword} = $u->{initialHashedPassword};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ensure home directory incl. ownership and permissions.
|
||||||
|
if ($u->{createHome} and !$is_dry) {
|
||||||
|
make_path($u->{home}, { mode => oct($u->{homeMode}) }) if ! -e $u->{home};
|
||||||
|
chown $u->{uid}, $u->{gid}, $u->{home};
|
||||||
|
chmod oct($u->{homeMode}), $u->{home};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (defined $u->{hashedPasswordFile}) {
|
||||||
|
if (-e $u->{hashedPasswordFile}) {
|
||||||
|
$u->{hashedPassword} = read_file($u->{hashedPasswordFile});
|
||||||
|
chomp $u->{hashedPassword};
|
||||||
|
} else {
|
||||||
|
warn "warning: password file ‘$u->{hashedPasswordFile}’ does not exist\n";
|
||||||
|
}
|
||||||
|
} elsif (defined $u->{password}) {
|
||||||
|
$u->{hashedPassword} = hashPassword($u->{password});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!defined $u->{shell}) {
|
||||||
|
if (defined $existing) {
|
||||||
|
$u->{shell} = $existing->{shell};
|
||||||
|
} else {
|
||||||
|
warn "warning: no declarative or previous shell for ‘$name’, setting shell to nologin\n";
|
||||||
|
$u->{shell} = "/run/current-system/sw/bin/nologin";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$u->{fakePassword} = $existing->{fakePassword} // "x";
|
||||||
|
$usersOut{$name} = $u;
|
||||||
|
|
||||||
|
$uidMap->{$name} = $u->{uid};
|
||||||
|
}
|
||||||
|
|
||||||
|
# Update the persistent list of declarative users.
|
||||||
|
updateFile($declUsersFile, join(" ", sort(keys %usersOut)));
|
||||||
|
|
||||||
|
# Merge in the existing /etc/passwd.
|
||||||
|
foreach my $name (keys %usersCur) {
|
||||||
|
my $u = $usersCur{$name};
|
||||||
|
next if defined $usersOut{$name};
|
||||||
|
if (!$spec->{mutableUsers} || defined $declUsers{$name}) {
|
||||||
|
dry_print("removing user", "would remove user", "‘$name’");
|
||||||
|
} else {
|
||||||
|
$usersOut{$name} = $u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Rewrite /etc/passwd. FIXME: acquire lock.
|
||||||
|
@lines = map { join(":", $_->{name}, $_->{fakePassword}, $_->{uid}, $_->{gid}, $_->{description}, $_->{home}, $_->{shell}) . "\n" }
|
||||||
|
(sort { $a->{uid} <=> $b->{uid} } (values %usersOut));
|
||||||
|
updateFile($uidMapFile, to_json($uidMap, {canonical => 1}));
|
||||||
|
updateFile("/etc/passwd", \@lines);
|
||||||
|
nscdInvalidate("passwd");
|
||||||
|
|
||||||
|
|
||||||
|
# Rewrite /etc/shadow to add new accounts or remove dead ones.
|
||||||
|
my @shadowNew;
|
||||||
|
my %shadowSeen;
|
||||||
|
|
||||||
|
foreach my $line (-f "/etc/shadow" ? read_file("/etc/shadow", { binmode => ":utf8" }) : ()) {
|
||||||
|
chomp $line;
|
||||||
|
# struct name copied from `man 3 shadow`
|
||||||
|
my ($sp_namp, $sp_pwdp, $sp_lstch, $sp_min, $sp_max, $sp_warn, $sp_inact, $sp_expire, $sp_flag) = split(':', $line, -9);
|
||||||
|
my $u = $usersOut{$sp_namp};;
|
||||||
|
next if !defined $u;
|
||||||
|
$sp_pwdp = "!" if !$spec->{mutableUsers};
|
||||||
|
$sp_pwdp = $u->{hashedPassword} if defined $u->{hashedPassword} && !$spec->{mutableUsers}; # FIXME
|
||||||
|
$sp_expire = dateToDays($u->{expires}) if defined $u->{expires};
|
||||||
|
chomp $sp_pwdp;
|
||||||
|
push @shadowNew, join(":", $sp_namp, $sp_pwdp, $sp_lstch, $sp_min, $sp_max, $sp_warn, $sp_inact, $sp_expire, $sp_flag) . "\n";
|
||||||
|
$shadowSeen{$sp_namp} = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach my $u (values %usersOut) {
|
||||||
|
next if defined $shadowSeen{$u->{name}};
|
||||||
|
my $hashedPassword = "!";
|
||||||
|
$hashedPassword = $u->{hashedPassword} if defined $u->{hashedPassword};
|
||||||
|
my $expires = "";
|
||||||
|
$expires = dateToDays($u->{expires}) if defined $u->{expires};
|
||||||
|
# FIXME: set correct value for sp_lstchg.
|
||||||
|
push @shadowNew, join(":", $u->{name}, $hashedPassword, "1::::", $expires, "") . "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
updateFile("/etc/shadow", \@shadowNew, 0640);
|
||||||
|
{
|
||||||
|
my $uid = getpwnam "root";
|
||||||
|
my $gid = getgrnam "shadow";
|
||||||
|
my $path = "/etc/shadow";
|
||||||
|
(chown($uid, $gid, $path) || die "Failed to change ownership of $path: $!") unless $is_dry;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Rewrite /etc/subuid & /etc/subgid to include default container mappings
|
||||||
|
|
||||||
|
my $subUidMapFile = "/var/lib/nixos/auto-subuid-map";
|
||||||
|
my $subUidMap = -e $subUidMapFile ? decode_json(read_file($subUidMapFile)) : {};
|
||||||
|
|
||||||
|
my (%subUidsUsed, %subUidsPrevUsed);
|
||||||
|
|
||||||
|
$subUidsPrevUsed{$_} = 1 foreach values %{$subUidMap};
|
||||||
|
|
||||||
|
sub allocSubUid {
|
||||||
|
my ($name, @rest) = @_;
|
||||||
|
|
||||||
|
# TODO: No upper bounds?
|
||||||
|
my ($min, $max, $up) = (100000, 100000 * 100, 1);
|
||||||
|
my $prevId = $subUidMap->{$name};
|
||||||
|
if (defined $prevId && !defined $subUidsUsed{$prevId}) {
|
||||||
|
$subUidsUsed{$prevId} = 1;
|
||||||
|
return $prevId;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $id = allocId(\%subUidsUsed, \%subUidsPrevUsed, $min, $max, $up, sub { my ($uid) = @_; getpwuid($uid) });
|
||||||
|
my $offset = $id - 100000;
|
||||||
|
my $count = $offset * 65536;
|
||||||
|
my $subordinate = 100000 + $count;
|
||||||
|
return $subordinate;
|
||||||
|
}
|
||||||
|
|
||||||
|
my @subGids;
|
||||||
|
my @subUids;
|
||||||
|
foreach my $u (values %usersOut) {
|
||||||
|
my $name = $u->{name};
|
||||||
|
|
||||||
|
foreach my $range (@{$u->{subUidRanges}}) {
|
||||||
|
my $value = join(":", ($name, $range->{startUid}, $range->{count}));
|
||||||
|
push @subUids, $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach my $range (@{$u->{subGidRanges}}) {
|
||||||
|
my $value = join(":", ($name, $range->{startGid}, $range->{count}));
|
||||||
|
push @subGids, $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($u->{autoSubUidGidRange}) {
|
||||||
|
my $subordinate = allocSubUid($name);
|
||||||
|
$subUidMap->{$name} = $subordinate;
|
||||||
|
my $value = join(":", ($name, $subordinate, 65536));
|
||||||
|
push @subUids, $value;
|
||||||
|
push @subGids, $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateFile("/etc/subuid", join("\n", @subUids) . "\n");
|
||||||
|
updateFile("/etc/subgid", join("\n", @subGids) . "\n");
|
||||||
|
updateFile($subUidMapFile, encode_json($subUidMap) . "\n");
|
124
pkgs/llvm-epi/clang.nix
Normal file
124
pkgs/llvm-epi/clang.nix
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
{
|
||||||
|
stdenv
|
||||||
|
, llvmPackages_latest
|
||||||
|
, lib
|
||||||
|
, fetchFromGitHub
|
||||||
|
, cmake
|
||||||
|
, bash
|
||||||
|
, python3
|
||||||
|
, perl
|
||||||
|
, which
|
||||||
|
, elfutils
|
||||||
|
, libffi
|
||||||
|
, zlib
|
||||||
|
, pkg-config
|
||||||
|
, enableDebug ? false
|
||||||
|
, gitUrl ? "https://repo.hca.bsc.es/gitlab/rferrer/llvm-epi.git"
|
||||||
|
, gitBranch ? "EPI-0.7"
|
||||||
|
, gitCommit ? "479518dc58dfceb23fc90667a5d6253e429f0fc2"
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
llvmPackages = llvmPackages_latest;
|
||||||
|
llvmStdenv = llvmPackages.stdenv;
|
||||||
|
# needed to set the rpath of libstdc++ for clang-tblgen
|
||||||
|
gcc = stdenv.cc;
|
||||||
|
|
||||||
|
git = rec {
|
||||||
|
version = src.shortRev;
|
||||||
|
src = builtins.fetchGit {
|
||||||
|
url = gitUrl;
|
||||||
|
ref = gitBranch;
|
||||||
|
rev = gitCommit;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
source = git;
|
||||||
|
|
||||||
|
in llvmStdenv.mkDerivation rec {
|
||||||
|
pname = "clang-epi";
|
||||||
|
inherit (source) src version;
|
||||||
|
|
||||||
|
enableParallelBuilding = true;
|
||||||
|
isClang = true;
|
||||||
|
|
||||||
|
patches = if (gitBranch == "EPI-0.7") then [
|
||||||
|
./include-cstdint.patch
|
||||||
|
] else [
|
||||||
|
];
|
||||||
|
|
||||||
|
# See https://reviews.llvm.org/D135402
|
||||||
|
env.LDFLAGS = "-Wl,--undefined-version";
|
||||||
|
|
||||||
|
passthru = {
|
||||||
|
CC = "clang";
|
||||||
|
CXX = "clang++";
|
||||||
|
};
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
zlib
|
||||||
|
gcc.cc.lib # Required for libstdc++.so.6
|
||||||
|
];
|
||||||
|
|
||||||
|
buildInputs = [
|
||||||
|
which
|
||||||
|
bash
|
||||||
|
python3
|
||||||
|
perl
|
||||||
|
cmake
|
||||||
|
llvmPackages.lld
|
||||||
|
elfutils
|
||||||
|
libffi
|
||||||
|
pkg-config
|
||||||
|
zlib
|
||||||
|
];
|
||||||
|
|
||||||
|
# Error with -D_FORTIFY_SOURCE=2, see https://bugs.gentoo.org/636604:
|
||||||
|
# /build/source/compiler-rt/lib/tsan/dd/dd_interceptors.cpp:225:20:
|
||||||
|
# error: redefinition of 'realpath'
|
||||||
|
# Requires disabling the "fortify" set of flags, however, for performance we
|
||||||
|
# disable all:
|
||||||
|
hardeningDisable = [ "all" ];
|
||||||
|
|
||||||
|
cmakeBuildType = if enableDebug then "Debug" else "Release";
|
||||||
|
|
||||||
|
dontStrip = enableDebug;
|
||||||
|
|
||||||
|
dontUseCmakeBuildDir = true;
|
||||||
|
|
||||||
|
# Fix shebangs, /usr/bin/env doesn't exist
|
||||||
|
prePatch = ''
|
||||||
|
patchShebangs clang/utils/EPI/generate-epi-builtins-def.py
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Fix the host triple, as it has changed in a newer config.guess:
|
||||||
|
# https://git.savannah.gnu.org/gitweb/?p=config.git;a=commitdiff;h=ca9bfb8cc75a2be1819d89c664a867785c96c9ba
|
||||||
|
preConfigure = ''
|
||||||
|
mkdir -p build
|
||||||
|
cd build
|
||||||
|
cmakeDir="../llvm"
|
||||||
|
cmakeFlagsArray=(
|
||||||
|
"-DLLVM_HOST_TRIPLE=${llvmStdenv.targetPlatform.config}"
|
||||||
|
"-DLLVM_DEFAULT_TARGET_TRIPLE=riscv64-unknown-linux-gnu"
|
||||||
|
"-DLLVM_TARGETS_TO_BUILD=RISCV"
|
||||||
|
"-DLLVM_BUILD_LLVM_DYLIB=ON"
|
||||||
|
"-DLLVM_LINK_LLVM_DYLIB=ON"
|
||||||
|
# Required to run clang-ast-dump and clang-tblgen during build
|
||||||
|
"-DCMAKE_BUILD_RPATH=$PWD/lib:${zlib}/lib:${gcc.cc.lib}/lib"
|
||||||
|
"-DLLVM_ENABLE_LLD=ON"
|
||||||
|
"-DCMAKE_CXX_FLAGS_DEBUG=-g -ggnu-pubnames"
|
||||||
|
"-DCMAKE_EXE_LINKER_FLAGS_DEBUG=-Wl,--gdb-index"
|
||||||
|
"-DLLVM_LIT_ARGS=-sv --xunit-xml-output=xunit.xml"
|
||||||
|
"-DLLVM_ENABLE_PROJECTS=clang;lld"
|
||||||
|
"-DLLVM_ENABLE_ASSERTIONS=ON"
|
||||||
|
"-DLLVM_INSTALL_TOOLCHAIN_ONLY=ON"
|
||||||
|
"-DCMAKE_INSTALL_BINDIR=bin"
|
||||||
|
"-DLLVM_ENABLE_ZLIB=FORCE_ON"
|
||||||
|
"-DLLVM_ENABLE_LIBXML2=OFF"
|
||||||
|
# Set the rpath to include external libraries (zlib) both on build and
|
||||||
|
# install
|
||||||
|
"-DCMAKE_INSTALL_RPATH_USE_LINK_PATH=ON"
|
||||||
|
"-DCMAKE_INSTALL_RPATH=${zlib}/lib:${gcc.cc.lib}/lib"
|
||||||
|
)
|
||||||
|
'';
|
||||||
|
}
|
46
pkgs/llvm-epi/default.nix
Normal file
46
pkgs/llvm-epi/default.nix
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
stdenv
|
||||||
|
, lib
|
||||||
|
, gcc
|
||||||
|
, clangEpiUnwrapped
|
||||||
|
, openmp ? null
|
||||||
|
, wrapCCWith
|
||||||
|
, llvmPackages_latest
|
||||||
|
, ompss2rt ? null
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
# We need to replace the lld linker from bintools with our linker just built,
|
||||||
|
# otherwise we run into incompatibility issues when mixing compiler and linker
|
||||||
|
# versions.
|
||||||
|
bintools-unwrapped = llvmPackages_latest.tools.bintools-unwrapped.override {
|
||||||
|
lld = clangEpiUnwrapped;
|
||||||
|
};
|
||||||
|
bintools = llvmPackages_latest.tools.bintools.override {
|
||||||
|
bintools = bintools-unwrapped;
|
||||||
|
};
|
||||||
|
targetConfig = stdenv.targetPlatform.config;
|
||||||
|
inherit gcc;
|
||||||
|
cc = clangEpiUnwrapped;
|
||||||
|
in wrapCCWith {
|
||||||
|
inherit cc bintools;
|
||||||
|
# extraPackages adds packages to depsTargetTargetPropagated
|
||||||
|
extraPackages = lib.optional (openmp != null) openmp;
|
||||||
|
extraBuildCommands = ''
|
||||||
|
echo "-target ${targetConfig}" >> $out/nix-support/cc-cflags
|
||||||
|
echo "-B${gcc.cc}/lib/gcc/${targetConfig}/${gcc.version}" >> $out/nix-support/cc-cflags
|
||||||
|
echo "-L${gcc.cc}/lib/gcc/${targetConfig}/${gcc.version}" >> $out/nix-support/cc-ldflags
|
||||||
|
echo "-L${gcc.cc.lib}/lib" >> $out/nix-support/cc-ldflags
|
||||||
|
|
||||||
|
for dir in ${gcc.cc}/include/c++/*; do
|
||||||
|
echo "-isystem $dir" >> $out/nix-support/libcxx-cxxflags
|
||||||
|
done
|
||||||
|
for dir in ${gcc.cc}/include/c++/*/${targetConfig}; do
|
||||||
|
echo "-isystem $dir" >> $out/nix-support/libcxx-cxxflags
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "--gcc-toolchain=${gcc}" >> $out/nix-support/cc-cflags
|
||||||
|
|
||||||
|
wrap clang++ $wrapper $ccPath/clang++
|
||||||
|
'';
|
||||||
|
}
|
10
pkgs/llvm-epi/include-cstdint.patch
Normal file
10
pkgs/llvm-epi/include-cstdint.patch
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
--- a/llvm/include/llvm/Support/Signals.h 2024-09-25 08:34:21.257642944 +0200
|
||||||
|
+++ b/llvm/include/llvm/Support/Signals.h 2024-09-25 08:35:12.593556793 +0200
|
||||||
|
@@ -15,6 +15,7 @@
|
||||||
|
#define LLVM_SUPPORT_SIGNALS_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
+#include <cstdint>
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
class StringRef;
|
79
pkgs/rvb/Makefile
Normal file
79
pkgs/rvb/Makefile
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
include Makefile.in
|
||||||
|
|
||||||
|
HPC_BENCHMARKS_DIRS=\
|
||||||
|
axpy \
|
||||||
|
jacobi-2d \
|
||||||
|
somier \
|
||||||
|
# Require submodules:
|
||||||
|
# fft \
|
||||||
|
# fftp \
|
||||||
|
# Require vehave:
|
||||||
|
# lulesh \
|
||||||
|
# Missing compare_array_double:
|
||||||
|
# gemm \
|
||||||
|
# Broken, not found:
|
||||||
|
# spmv
|
||||||
|
|
||||||
|
DESKTOP_BENCHMARKS_DIRS=\
|
||||||
|
blackscholes \
|
||||||
|
canneal \
|
||||||
|
particlefilter \
|
||||||
|
streamcluster \
|
||||||
|
swaptions
|
||||||
|
#pathfinder
|
||||||
|
|
||||||
|
MICRO_BENCHMARKS_DIRS=
|
||||||
|
#BuffCopyUnit \
|
||||||
|
#BuffCopyStrided \
|
||||||
|
#BuffCopyIndexed \
|
||||||
|
#FpuMicroKernel \
|
||||||
|
#InstrNopBalance \
|
||||||
|
#MemArithBalance \
|
||||||
|
#LatencyVrgather
|
||||||
|
|
||||||
|
.PHONY: default all clean $(HPC_BENCHMARKS_DIRS) $(MICRO_BENCHMARKS_DIRS)
|
||||||
|
|
||||||
|
all: base
|
||||||
|
|
||||||
|
default:
|
||||||
|
@cd common; make; cd ..
|
||||||
|
@$(foreach dir,$(HPC_BENCHMARKS_DIRS),${MAKE} -C hpc_benchmarks/$(dir);)
|
||||||
|
@$(foreach dir,$(DESKTOP_BENCHMARKS_DIRS),${MAKE} -C desktop_benchmarks/$(dir);)
|
||||||
|
@$(foreach dir,$(MICRO_BENCHMARKS_DIRS),${MAKE} -C micro_benchmarks/$(dir);)
|
||||||
|
|
||||||
|
all-types:
|
||||||
|
@cd common; make all; cd ..
|
||||||
|
@$(foreach dir,$(HPC_BENCHMARKS_DIRS),${MAKE} -C hpc_benchmarks/$(dir) all ;)
|
||||||
|
@$(foreach dir,$(DESKTOP_BENCHMARKS_DIRS),${MAKE} -C desktop_benchmarks/$(dir) all ;)
|
||||||
|
@$(foreach dir,$(MICRO_BENCHMARKS_DIRS),${MAKE} -C micro_benchmarks/$(dir) all ;)
|
||||||
|
|
||||||
|
base:
|
||||||
|
@cd common; make all; cd ..
|
||||||
|
@$(foreach dir,$(HPC_BENCHMARKS_DIRS),${MAKE} -C hpc_benchmarks/$(dir) base ;)
|
||||||
|
@$(foreach dir,$(DESKTOP_BENCHMARKS_DIRS),${MAKE} -C desktop_benchmarks/$(dir) base ;)
|
||||||
|
@$(foreach dir,$(MICRO_BENCHMARKS_DIRS),${MAKE} -C micro_benchmarks/$(dir) base ;)
|
||||||
|
|
||||||
|
install:
|
||||||
|
@$(foreach dir,$(HPC_BENCHMARKS_DIRS),${MAKE} -C hpc_benchmarks/$(dir) install ;)
|
||||||
|
@$(foreach dir,$(DESKTOP_BENCHMARKS_DIRS),${MAKE} -C desktop_benchmarks/$(dir) install ;)
|
||||||
|
@$(foreach dir,$(MICRO_BENCHMARKS_DIRS),${MAKE} -C micro_benchmarks/$(dir) install ;)
|
||||||
|
|
||||||
|
fftp:
|
||||||
|
${MAKE} -C third_party fftw
|
||||||
|
${MAKE} -C hpc_benchmarks/fftp all
|
||||||
|
${MAKE} -C hpc_benchmarks/fftp/test all
|
||||||
|
|
||||||
|
spmv-ellpack:
|
||||||
|
rm -rf hpc_benchmarks/spmv-ellpack/spmv/build
|
||||||
|
mkdir -p hpc_benchmarks/spmv-ellpack/spmv/build
|
||||||
|
cd hpc_benchmarks/spmv-ellpack/spmv/build;\
|
||||||
|
../configure riscv;\
|
||||||
|
INDEX64=1 EPI_EXT=07 PATH=${EPI_LLVM_HOME}/bin:${PATH} make
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@cd common; make clean; cd ..
|
||||||
|
@$(foreach dir,$(HPC_BENCHMARKS_DIRS),${MAKE} -C hpc_benchmarks/$(dir) clean ;)
|
||||||
|
@$(foreach dir,$(DESKTOP_BENCHMARKS_DIRS),${MAKE} -C desktop_benchmarks/$(dir) clean ;)
|
||||||
|
@$(foreach dir,$(MICRO_BENCHMARKS_DIRS),${MAKE} -C micro_benchmarks/$(dir) clean ;)
|
||||||
|
@rm -rf hpc_benchmarks/spmv-ellpack/spmv/build
|
||||||
|
|
83
pkgs/rvb/Makefile.in
Normal file
83
pkgs/rvb/Makefile.in
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
#Compile all benchmarks with individual settings defined in their Makefiles
|
||||||
|
|
||||||
|
_default-target: default
|
||||||
|
|
||||||
|
# RVB_ROOT defined as argument
|
||||||
|
|
||||||
|
# TODO: RVB_COMMON_DIR should substitute COMMON_DIR
|
||||||
|
COMMON_DIR=$(RVB_ROOT)/common
|
||||||
|
RVB_COMMON_DIR=$(RVB_ROOT)/common
|
||||||
|
|
||||||
|
#CC=clang
|
||||||
|
#CXX=clang++
|
||||||
|
|
||||||
|
# Needs EPI clang
|
||||||
|
#MEPI=-mepi
|
||||||
|
MEPI=
|
||||||
|
|
||||||
|
#VREPORT_FLAGS=-Rpass=loop-vectorize -Rpass-missed=loop-vectorize -Rpass-analysis=loop-vectorize
|
||||||
|
#Available CFLAGS conditional compilation:
|
||||||
|
# -DUSE_MALLOC_HP, redefines the use of malloc and free
|
||||||
|
|
||||||
|
#Makefile: General compiler flags: CFLAGS, CFLAGS_<VERSION_1>, CFLAGS_<VERSION_2>, ...
|
||||||
|
#CFLAGS=-B ${LLVM_BIN} -Wall -Wextra -march=rv64g -O2 -I${RVB_COMMON_DIR}
|
||||||
|
CFLAGS=-B ${LLVM_BIN} -Wall -Wextra -O2 -I${RVB_COMMON_DIR}
|
||||||
|
LDFLAGS=
|
||||||
|
|
||||||
|
#Only scalar instructions
|
||||||
|
CFLAGS_SCALAR=${CFLAGS} -DRVB_USE_SCALAR
|
||||||
|
LDFLAGS_SCALAR=
|
||||||
|
|
||||||
|
#NOVEC=-fno-vectorize
|
||||||
|
NOVEC=
|
||||||
|
|
||||||
|
#Vector instructions using intrinsics
|
||||||
|
CFLAGS_VECTORIAL=${CFLAGS} ${NOVEC} $(MEPI)
|
||||||
|
LDFLAGS_VECTORIAL=
|
||||||
|
|
||||||
|
# TODO: RVV should substitute VECTORIAL (?)
|
||||||
|
#Vector instructions using intrinsics
|
||||||
|
CFLAGS_RVV=${CFLAGS} -DRVB_USE_RVV ${NOVEC} $(MEPI)
|
||||||
|
LDFLAGS_RVV=${LDFLAGS}
|
||||||
|
|
||||||
|
#Vector instructions only when code is annotate
|
||||||
|
CFLAGS_EXPLICIT_AUTOVECTORIZATION=${CFLAGS} -fopenmp-simd ${NOVEC} $(MEPI) ${VREPORT_FLAGS}
|
||||||
|
LDFLAGS_EXPLICIT_AUTOVECTORIZATION=
|
||||||
|
|
||||||
|
# TODO: OMP substitutes EXPLICIT_AUTOVECTORIZATION
|
||||||
|
#Vector instructions only when code is annotate
|
||||||
|
CFLAGS_OMP=${CFLAGS} -DRVB_USE_OMP -fopenmp-simd $(MEPI) ${VREPORT_FLAGS}
|
||||||
|
LDFLAGS_OMP=${LDFLAGS}
|
||||||
|
|
||||||
|
#Vector instructions when compiler decides
|
||||||
|
CFLAGS_AUTOVECTORIZATION=${CFLAGS} -fopenmp-simd $(MEPI) ${VREPORT_FLAGS}
|
||||||
|
LDFLAGS_AUTOVECTORIZATION=
|
||||||
|
|
||||||
|
# TODO: AUTOVECT shoud substitue AUTOVECTORIZATION (?)
|
||||||
|
#Vector instructions when compiler decides
|
||||||
|
CFLAGS_AUTOVECT=${CFLAGS} -DRVB_USE_AUTOVECT -fopenmp-simd $(MEPI) ${VREPORT_FLAGS}
|
||||||
|
LDFLAGS_AUTOVECT=${LDFLAGS}
|
||||||
|
|
||||||
|
# CBLAS library compile and link flags
|
||||||
|
CFLAGS_CBLAS=${CFLAGS} -DRVB_USE_CBLAS -I${CBLAS_INC} -I${LLVM_INC}
|
||||||
|
LDFLAGS_CBLAS=${LDFLAGS} -L${CBLAS_LIB} -lblis -Wl,-rpath,${CBLAS_LIB} -fopenmp
|
||||||
|
|
||||||
|
# BARE-METAL compile and link flags
|
||||||
|
# You may consider to disable OpenPiton Stream: -DDISABLE_OPSTREAM
|
||||||
|
CFLAGS_BMETAL=${CFLAGS} -DRVB_USE_BMETAL -B ${RVB_BMETAL_DIR} \
|
||||||
|
--target=riscv64-unknown-elf \
|
||||||
|
-I../ \
|
||||||
|
-I/apps/riscv/llvm/EPI-0.7/cross/development/riscv64-unknown-linux-gnu/sysroot/usr/include \
|
||||||
|
-I/usr/include/riscv64-linux-gnu \
|
||||||
|
-I/usr/include \
|
||||||
|
-I${RVB_BMETAL_DIR}/env \
|
||||||
|
-I${RVB_BMETAL_DIR} \
|
||||||
|
-DPREALLOCATE=1 -mcmodel=medany \
|
||||||
|
-static -std=gnu99 \
|
||||||
|
-ffast-math \
|
||||||
|
-fno-common \
|
||||||
|
-fno-builtin-printf \
|
||||||
|
${RVB_BMETAL_DIR}/syscalls.c \
|
||||||
|
${RVB_BMETAL_DIR}/crt.S \
|
||||||
|
-static -nostdlib -T \
|
||||||
|
${RVB_BMETAL_DIR}/test.ld
|
35
pkgs/rvb/default.nix
Normal file
35
pkgs/rvb/default.nix
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
stdenv
|
||||||
|
, blis
|
||||||
|
, gitBranch ? "nix-fixes"
|
||||||
|
, gitURL ? "git@gitlab-internal.bsc.es:rarias/risc-v-benchmarks.git"
|
||||||
|
, gitCommit ? "da202d6f818421b72e06c39b5417ad2f8f6ca23c"
|
||||||
|
}:
|
||||||
|
|
||||||
|
stdenv.mkDerivation rec {
|
||||||
|
pname = "rvb";
|
||||||
|
version = "${src.shortRev}";
|
||||||
|
|
||||||
|
src = builtins.fetchGit {
|
||||||
|
url = gitURL;
|
||||||
|
ref = gitBranch;
|
||||||
|
rev = gitCommit;
|
||||||
|
submodules = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
buildInputs = [ blis ];
|
||||||
|
configurePhase = ''
|
||||||
|
export RVB_ROOT=$(readlink -f .)
|
||||||
|
export CBLAS_HOME=${blis}
|
||||||
|
export CBLAS_INC=${blis}/include/blis
|
||||||
|
export CBLAS_LIB=${blis}/lib
|
||||||
|
rm Makefile.in
|
||||||
|
ln -s ${./Makefile.in} Makefile.in
|
||||||
|
rm Makefile
|
||||||
|
ln -s ${./Makefile} Makefile
|
||||||
|
'';
|
||||||
|
enableParallelBuilding = false;
|
||||||
|
hardeningDisable = [ "all" ];
|
||||||
|
installFlags = [ "DESTDIR=$(out)" ];
|
||||||
|
dontStrip = true;
|
||||||
|
}
|
66
pkgs/spec-cpu/Makefile
Normal file
66
pkgs/spec-cpu/Makefile
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
include Makefile.in
|
||||||
|
|
||||||
|
HPC_BENCHMARKS_DIRS=\
|
||||||
|
axpy \
|
||||||
|
jacobi-2d \
|
||||||
|
somier \
|
||||||
|
# Require submodules:
|
||||||
|
# fft \
|
||||||
|
# fftp \
|
||||||
|
# Require vehave:
|
||||||
|
# lulesh \
|
||||||
|
# Missing compare_array_double:
|
||||||
|
# gemm \
|
||||||
|
# Broken, not found:
|
||||||
|
# spmv
|
||||||
|
|
||||||
|
DESKTOP_BENCHMARKS_DIRS=\
|
||||||
|
blackscholes \
|
||||||
|
canneal \
|
||||||
|
particlefilter \
|
||||||
|
pathfinder \
|
||||||
|
streamcluster \
|
||||||
|
swaptions
|
||||||
|
|
||||||
|
MICRO_BENCHMARKS_DIRS=\
|
||||||
|
BuffCopyUnit \
|
||||||
|
BuffCopyStrided \
|
||||||
|
BuffCopyIndexed \
|
||||||
|
FpuMicroKernel \
|
||||||
|
InstrNopBalance \
|
||||||
|
MemArithBalance \
|
||||||
|
LatencyVrgather
|
||||||
|
|
||||||
|
.PHONY: default all clean $(HPC_BENCHMARKS_DIRS) $(MICRO_BENCHMARKS_DIRS)
|
||||||
|
|
||||||
|
default:
|
||||||
|
@cd common; make; cd ..
|
||||||
|
@$(foreach dir,$(HPC_BENCHMARKS_DIRS),${MAKE} -C hpc_benchmarks/$(dir);)
|
||||||
|
@$(foreach dir,$(DESKTOP_BENCHMARKS_DIRS),${MAKE} -C desktop_benchmarks/$(dir);)
|
||||||
|
@$(foreach dir,$(MICRO_BENCHMARKS_DIRS),${MAKE} -C micro_benchmarks/$(dir);)
|
||||||
|
|
||||||
|
all:
|
||||||
|
@cd common; make all; cd ..
|
||||||
|
@$(foreach dir,$(HPC_BENCHMARKS_DIRS),${MAKE} -C hpc_benchmarks/$(dir) all ;)
|
||||||
|
@$(foreach dir,$(DESKTOP_BENCHMARKS_DIRS),${MAKE} -C desktop_benchmarks/$(dir) all ;)
|
||||||
|
@$(foreach dir,$(MICRO_BENCHMARKS_DIRS),${MAKE} -C micro_benchmarks/$(dir) all ;)
|
||||||
|
|
||||||
|
fftp:
|
||||||
|
${MAKE} -C third_party fftw
|
||||||
|
${MAKE} -C hpc_benchmarks/fftp all
|
||||||
|
${MAKE} -C hpc_benchmarks/fftp/test all
|
||||||
|
|
||||||
|
spmv-ellpack:
|
||||||
|
rm -rf hpc_benchmarks/spmv-ellpack/spmv/build
|
||||||
|
mkdir -p hpc_benchmarks/spmv-ellpack/spmv/build
|
||||||
|
cd hpc_benchmarks/spmv-ellpack/spmv/build;\
|
||||||
|
../configure riscv;\
|
||||||
|
INDEX64=1 EPI_EXT=07 PATH=${EPI_LLVM_HOME}/bin:${PATH} make
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@cd common; make clean; cd ..
|
||||||
|
@$(foreach dir,$(HPC_BENCHMARKS_DIRS),${MAKE} -C hpc_benchmarks/$(dir) clean ;)
|
||||||
|
@$(foreach dir,$(DESKTOP_BENCHMARKS_DIRS),${MAKE} -C desktop_benchmarks/$(dir) clean ;)
|
||||||
|
@$(foreach dir,$(MICRO_BENCHMARKS_DIRS),${MAKE} -C micro_benchmarks/$(dir) clean ;)
|
||||||
|
@rm -rf hpc_benchmarks/spmv-ellpack/spmv/build
|
||||||
|
|
80
pkgs/spec-cpu/Makefile.in
Normal file
80
pkgs/spec-cpu/Makefile.in
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
#Compile all benchmarks with individual settings defined in their Makefiles
|
||||||
|
|
||||||
|
_default-target: default
|
||||||
|
|
||||||
|
# RVB_ROOT defined as argument
|
||||||
|
|
||||||
|
# TODO: RVB_COMMON_DIR should substitute COMMON_DIR
|
||||||
|
COMMON_DIR=$(RVB_ROOT)/common
|
||||||
|
RVB_COMMON_DIR=$(RVB_ROOT)/common
|
||||||
|
|
||||||
|
CC=clang
|
||||||
|
CXX=clang++
|
||||||
|
|
||||||
|
# Needs EPI clang
|
||||||
|
#MEPI=-mepi
|
||||||
|
MEPI=
|
||||||
|
|
||||||
|
VREPORT_FLAGS=-Rpass=loop-vectorize -Rpass-missed=loop-vectorize -Rpass-analysis=loop-vectorize
|
||||||
|
#Available CFLAGS conditional compilation:
|
||||||
|
# -DUSE_MALLOC_HP, redefines the use of malloc and free
|
||||||
|
|
||||||
|
#Makefile: General compiler flags: CFLAGS, CFLAGS_<VERSION_1>, CFLAGS_<VERSION_2>, ...
|
||||||
|
#CFLAGS=-B ${LLVM_BIN} -Wall -Wextra -march=rv64g -O2 -I${RVB_COMMON_DIR}
|
||||||
|
CFLAGS=-B ${LLVM_BIN} -Wall -Wextra -O2 -I${RVB_COMMON_DIR}
|
||||||
|
LDFLAGS=
|
||||||
|
|
||||||
|
#Only scalar instructions
|
||||||
|
CFLAGS_SCALAR=${CFLAGS} -DRVB_USE_SCALAR
|
||||||
|
LDFLAGS_SCALAR=
|
||||||
|
|
||||||
|
#Vector instructions using intrinsics
|
||||||
|
CFLAGS_VECTORIAL=${CFLAGS} -fno-vectorize $(MEPI)
|
||||||
|
LDFLAGS_VECTORIAL=
|
||||||
|
|
||||||
|
# TODO: RVV should substitute VECTORIAL (?)
|
||||||
|
#Vector instructions using intrinsics
|
||||||
|
CFLAGS_RVV=${CFLAGS} -DRVB_USE_RVV -fno-vectorize $(MEPI)
|
||||||
|
LDFLAGS_RVV=${LDFLAGS}
|
||||||
|
|
||||||
|
#Vector instructions only when code is annotate
|
||||||
|
CFLAGS_EXPLICIT_AUTOVECTORIZATION=${CFLAGS} -fopenmp-simd -fno-vectorize $(MEPI) ${VREPORT_FLAGS}
|
||||||
|
LDFLAGS_EXPLICIT_AUTOVECTORIZATION=
|
||||||
|
|
||||||
|
# TODO: OMP substitutes EXPLICIT_AUTOVECTORIZATION
|
||||||
|
#Vector instructions only when code is annotate
|
||||||
|
CFLAGS_OMP=${CFLAGS} -DRVB_USE_OMP -fopenmp-simd -fno-vectorize $(MEPI) ${VREPORT_FLAGS}
|
||||||
|
LDFLAGS_OMP=${LDFLAGS}
|
||||||
|
|
||||||
|
#Vector instructions when compiler decides
|
||||||
|
CFLAGS_AUTOVECTORIZATION=${CFLAGS} -fopenmp-simd $(MEPI) ${VREPORT_FLAGS}
|
||||||
|
LDFLAGS_AUTOVECTORIZATION=
|
||||||
|
|
||||||
|
# TODO: AUTOVECT shoud substitue AUTOVECTORIZATION (?)
|
||||||
|
#Vector instructions when compiler decides
|
||||||
|
CFLAGS_AUTOVECT=${CFLAGS} -DRVB_USE_AUTOVECT -fopenmp-simd $(MEPI) ${VREPORT_FLAGS}
|
||||||
|
LDFLAGS_AUTOVECT=${LDFLAGS}
|
||||||
|
|
||||||
|
# CBLAS library compile and link flags
|
||||||
|
CFLAGS_CBLAS=${CFLAGS} -DRVB_USE_CBLAS -I${CBLAS_INC} -I${LLVM_INC}
|
||||||
|
LDFLAGS_CBLAS=${LDFLAGS} -L${CBLAS_LIB} -lblis -Wl,-rpath,${CBLAS_LIB} -fopenmp
|
||||||
|
|
||||||
|
# BARE-METAL compile and link flags
|
||||||
|
# You may consider to disable OpenPiton Stream: -DDISABLE_OPSTREAM
|
||||||
|
CFLAGS_BMETAL=${CFLAGS} -DRVB_USE_BMETAL -B ${RVB_BMETAL_DIR} \
|
||||||
|
--target=riscv64-unknown-elf \
|
||||||
|
-I../ \
|
||||||
|
-I/apps/riscv/llvm/EPI-0.7/cross/development/riscv64-unknown-linux-gnu/sysroot/usr/include \
|
||||||
|
-I/usr/include/riscv64-linux-gnu \
|
||||||
|
-I/usr/include \
|
||||||
|
-I${RVB_BMETAL_DIR}/env \
|
||||||
|
-I${RVB_BMETAL_DIR} \
|
||||||
|
-DPREALLOCATE=1 -mcmodel=medany \
|
||||||
|
-static -std=gnu99 \
|
||||||
|
-ffast-math \
|
||||||
|
-fno-common \
|
||||||
|
-fno-builtin-printf \
|
||||||
|
${RVB_BMETAL_DIR}/syscalls.c \
|
||||||
|
${RVB_BMETAL_DIR}/crt.S \
|
||||||
|
-static -nostdlib -T \
|
||||||
|
${RVB_BMETAL_DIR}/test.ld
|
61
pkgs/spec-cpu/default.nix
Normal file
61
pkgs/spec-cpu/default.nix
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
stdenv
|
||||||
|
, spec-cpu-tools
|
||||||
|
, libarchive
|
||||||
|
, xz
|
||||||
|
, gnutar
|
||||||
|
, gfortran
|
||||||
|
, coreutils
|
||||||
|
, requireFile
|
||||||
|
, autoPatchelfHook
|
||||||
|
, libxcrypt-legacy
|
||||||
|
, lib
|
||||||
|
, benchSize ? "test"
|
||||||
|
}:
|
||||||
|
|
||||||
|
stdenv.mkDerivation rec {
|
||||||
|
pname = "spec-cpu";
|
||||||
|
version = "1.1.7";
|
||||||
|
src = null;
|
||||||
|
unpackPhase = "true";
|
||||||
|
# We need a working specxz binary
|
||||||
|
config = ./gcc-linux-x86.cfg;
|
||||||
|
buildPhase = ''
|
||||||
|
cp ${config} config.cfg
|
||||||
|
chmod +w config.cfg
|
||||||
|
export SPEC_NOCHECK=1
|
||||||
|
mkdir out
|
||||||
|
runcpu \
|
||||||
|
--verbose=80 \
|
||||||
|
--tune=base \
|
||||||
|
--size=${benchSize} \
|
||||||
|
--output_root=$PWD/out \
|
||||||
|
--config=$PWD/config.cfg \
|
||||||
|
--define build_ncpus=$NIX_BUILD_CORES \
|
||||||
|
--action=runsetup \
|
||||||
|
all
|
||||||
|
'';
|
||||||
|
# 519.lbm_r
|
||||||
|
# 502.gcc_r
|
||||||
|
# all
|
||||||
|
|
||||||
|
# We only need the run directories
|
||||||
|
installPhase = ''
|
||||||
|
# Remove build/ and exe/ directories, we only need run/
|
||||||
|
rm -rf out/benchspec/CPU/*/build/
|
||||||
|
rm -rf out/benchspec/CPU/*/exe/
|
||||||
|
|
||||||
|
mkdir -p $out
|
||||||
|
cp -a out/benchspec $out
|
||||||
|
'';
|
||||||
|
|
||||||
|
#buildInputs = [ ];
|
||||||
|
nativeBuildInputs = [ spec-cpu-tools gfortran ];
|
||||||
|
enableParallelBuilding = false;
|
||||||
|
hardeningDisable = [ "all" ];
|
||||||
|
dontStrip = true;
|
||||||
|
|
||||||
|
meta.broken = (stdenv.buildPlatform.config != "x86_64-unknown-linux-gnu") ||
|
||||||
|
(stdenv.hostPlatform.config != "riscv64-unknown-linux-gnu") ||
|
||||||
|
(stdenv.targetPlatform.config != "riscv64-unknown-linux-gnu");
|
||||||
|
}
|
391
pkgs/spec-cpu/gcc-linux-x86.cfg
Normal file
391
pkgs/spec-cpu/gcc-linux-x86.cfg
Normal file
@ -0,0 +1,391 @@
|
|||||||
|
#------------------------------------------------------------------------------
|
||||||
|
# SPEC CPU(R) 2017 config for gcc/g++/gfortran on Linux x86
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# Usage: (1) Copy this to a new name
|
||||||
|
# cd $SPEC/config
|
||||||
|
# cp Example-x.cfg myname.cfg
|
||||||
|
# (2) Change items that are marked 'EDIT' (search for it)
|
||||||
|
#
|
||||||
|
# SPEC tested this config file with:
|
||||||
|
# Compiler version(s): Various. See note "Older GCC" below.
|
||||||
|
# Operating system(s): Oracle Linux Server 6, 7, 8 /
|
||||||
|
# Red Hat Enterprise Linux Server 6, 7, 8
|
||||||
|
# SUSE Linux Enterprise Server 15
|
||||||
|
# Ubuntu 19.04
|
||||||
|
# Hardware: Xeon, EPYC
|
||||||
|
#
|
||||||
|
# If your system differs, this config file might not work.
|
||||||
|
# You might find a better config file at https://www.spec.org/cpu2017/results
|
||||||
|
#
|
||||||
|
# Note: Older GCC
|
||||||
|
#
|
||||||
|
# Please use the newest GCC that you can. The default version packaged with
|
||||||
|
# your operating system may be very old; look for alternate packages with a
|
||||||
|
# newer version.
|
||||||
|
#
|
||||||
|
# If you have no choice and must use an old version, here is what to expect:
|
||||||
|
#
|
||||||
|
# - "peak" tuning: Several benchmarks will fail at peak tuning if you use
|
||||||
|
# compilers older than GCC 7.
|
||||||
|
# In that case, please use base only.
|
||||||
|
# See: https://www.spec.org/cpu2017/Docs/overview.html#Q16
|
||||||
|
# https://www.spec.org/cpu2017/Docs/config.html#tune
|
||||||
|
# Peak tuning is expected to work for all or nearly all
|
||||||
|
# benchmarks as of GCC 7 or later.
|
||||||
|
# Exception:
|
||||||
|
# - See topic "628.pop2_s basepeak", below.
|
||||||
|
#
|
||||||
|
# - "base" tuning: This config file is expected to work for base tuning with
|
||||||
|
# GCC 4.8.5 or later
|
||||||
|
# Exception:
|
||||||
|
# - Compilers vintage about 4.9 may need to turn off the
|
||||||
|
# tree vectorizer, by adding to the base OPTIMIZE flags:
|
||||||
|
# -fno-tree-loop-vectorize
|
||||||
|
#
|
||||||
|
# Unexpected errors? Try reducing the optimization level, or try removing:
|
||||||
|
# -march=native
|
||||||
|
#
|
||||||
|
# Compiler issues: Contact your compiler vendor, not SPEC.
|
||||||
|
# For SPEC help: https://www.spec.org/cpu2017/Docs/techsupport.html
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
#--------- Label --------------------------------------------------------------
|
||||||
|
# Arbitrary string to tag binaries (no spaces allowed)
|
||||||
|
# Two Suggestions: # (1) EDIT this label as you try new ideas.
|
||||||
|
%ifndef %{label}
|
||||||
|
% define label "nix" # (2) Use a label meaningful to *you*.
|
||||||
|
%endif
|
||||||
|
|
||||||
|
|
||||||
|
#--------- Preprocessor -------------------------------------------------------
|
||||||
|
%ifndef %{bits} # EDIT to control 32 or 64 bit compilation. Or,
|
||||||
|
% define bits 64 # you can set it on the command line using:
|
||||||
|
%endif # 'runcpu --define bits=nn'
|
||||||
|
|
||||||
|
%ifndef %{build_ncpus} # EDIT to adjust number of simultaneous compiles.
|
||||||
|
% define build_ncpus 8 # Or, you can set it on the command line:
|
||||||
|
%endif # 'runcpu --define build_ncpus=nn'
|
||||||
|
|
||||||
|
# Don't change this part.
|
||||||
|
%if %{bits} == 64
|
||||||
|
% define model -m64
|
||||||
|
%elif %{bits} == 32
|
||||||
|
% define model -m32
|
||||||
|
%else
|
||||||
|
% error Please define number of bits - see instructions in config file
|
||||||
|
%endif
|
||||||
|
%if %{label} =~ m/ /
|
||||||
|
% error Your label "%{label}" contains spaces. Please try underscores instead.
|
||||||
|
%endif
|
||||||
|
%if %{label} !~ m/^[a-zA-Z0-9._-]+$/
|
||||||
|
% error Illegal character in label "%{label}". Please use only alphanumerics, underscore, hyphen, and period.
|
||||||
|
%endif
|
||||||
|
|
||||||
|
|
||||||
|
#--------- Global Settings ----------------------------------------------------
|
||||||
|
# For info, see:
|
||||||
|
# https://www.spec.org/cpu2017/Docs/config.html#fieldname
|
||||||
|
# Example: https://www.spec.org/cpu2017/Docs/config.html#tune
|
||||||
|
|
||||||
|
command_add_redirect = 1
|
||||||
|
flagsurl = $[top]/config/flags/gcc.xml
|
||||||
|
ignore_errors = 1
|
||||||
|
iterations = 1
|
||||||
|
label = %{label}-m%{bits}
|
||||||
|
line_width = 1020
|
||||||
|
log_line_width = 1020
|
||||||
|
makeflags = --jobs=%{build_ncpus}
|
||||||
|
mean_anyway = 1
|
||||||
|
output_format = txt,html,cfg,pdf,csv
|
||||||
|
preenv = 1
|
||||||
|
reportable = 0
|
||||||
|
tune = base,peak # EDIT if needed: set to "base" for old GCC.
|
||||||
|
# See note "Older GCC" above.
|
||||||
|
|
||||||
|
|
||||||
|
#--------- How Many CPUs? -----------------------------------------------------
|
||||||
|
# Both SPECrate and SPECspeed can test multiple chips / cores / hw threads
|
||||||
|
# - For SPECrate, you set the number of copies.
|
||||||
|
# - For SPECspeed, you set the number of threads.
|
||||||
|
# See: https://www.spec.org/cpu2017/Docs/system-requirements.html#MultipleCPUs
|
||||||
|
#
|
||||||
|
# q. How many should I set?
|
||||||
|
# a. Unknown, you will have to try it and see!
|
||||||
|
#
|
||||||
|
# To get you started, some suggestions:
|
||||||
|
#
|
||||||
|
# copies - This config file defaults to testing only 1 copy. You might
|
||||||
|
# try changing it to match the number of cores on your system,
|
||||||
|
# or perhaps the number of virtual CPUs as reported by:
|
||||||
|
# grep -c processor /proc/cpuinfo
|
||||||
|
# Be sure you have enough memory. See:
|
||||||
|
# https://www.spec.org/cpu2017/Docs/system-requirements.html#memory
|
||||||
|
#
|
||||||
|
# threads - This config file sets a starting point. You could try raising
|
||||||
|
# it. A higher thread count is much more likely to be useful for
|
||||||
|
# fpspeed than for intspeed.
|
||||||
|
#
|
||||||
|
intrate,fprate:
|
||||||
|
copies = 1 # EDIT to change number of copies (see above)
|
||||||
|
intspeed,fpspeed:
|
||||||
|
threads = 4 # EDIT to change number of OpenMP threads (see above)
|
||||||
|
|
||||||
|
|
||||||
|
#------- Compilers ------------------------------------------------------------
|
||||||
|
default:
|
||||||
|
# EDIT: The parent directory for your compiler.
|
||||||
|
# Do not include the trailing /bin/
|
||||||
|
# Do not include a trailing slash
|
||||||
|
# Examples:
|
||||||
|
# 1 On a Red Hat system, you said:
|
||||||
|
# 'yum install devtoolset-9'
|
||||||
|
# Use: % define gcc_dir "/opt/rh/devtoolset-9/root/usr"
|
||||||
|
#
|
||||||
|
# 2 You built GCC in: /disk1/mybuild/gcc-10.1.0/bin/gcc
|
||||||
|
# Use: % define gcc_dir "/disk1/mybuild/gcc-10.1.0"
|
||||||
|
#
|
||||||
|
# 3 You want: /usr/bin/gcc
|
||||||
|
# Use: % define gcc_dir "/usr"
|
||||||
|
# WARNING: See section "Older GCC" above.
|
||||||
|
#
|
||||||
|
#%ifndef %{gcc_dir}
|
||||||
|
#% define gcc_dir "@GCC_DIR@" # EDIT (see above)
|
||||||
|
#%endif
|
||||||
|
|
||||||
|
# EDIT: If your compiler version is 10 or greater, you must enable the next
|
||||||
|
# line to avoid compile errors for several FP benchmarks
|
||||||
|
#
|
||||||
|
%define GCCge10 # EDIT: remove the '#' from column 1 if using GCC 10 or later
|
||||||
|
|
||||||
|
# EDIT if needed: the preENV line adds library directories to the runtime
|
||||||
|
# path. You can adjust it, or add lines for other environment variables.
|
||||||
|
# See: https://www.spec.org/cpu2017/Docs/config.html#preenv
|
||||||
|
# and: https://gcc.gnu.org/onlinedocs/gcc/Environment-Variables.html
|
||||||
|
#preENV_LD_LIBRARY_PATH = %{gcc_dir}/lib64/:%{gcc_dir}/lib/:/lib64
|
||||||
|
#preENV_LD_LIBRARY_PATH = %{gcc_dir}/lib64/:%{gcc_dir}/lib/:/lib64:%{ENV_LD_LIBRARY_PATH}
|
||||||
|
#SPECLANG = %{gcc_dir}/bin/
|
||||||
|
CC = %{ENV_CC} -std=c99
|
||||||
|
CXX = %{ENV_CXX} -std=c++03
|
||||||
|
FC = %{ENV_FC}
|
||||||
|
# How to say "Show me your version, please"
|
||||||
|
CC_VERSION_OPTION = --version
|
||||||
|
CXX_VERSION_OPTION = --version
|
||||||
|
FC_VERSION_OPTION = --version
|
||||||
|
|
||||||
|
default:
|
||||||
|
%if %{bits} == 64
|
||||||
|
sw_base_ptrsize = 64-bit
|
||||||
|
sw_peak_ptrsize = 64-bit
|
||||||
|
%else
|
||||||
|
sw_base_ptrsize = 32-bit
|
||||||
|
sw_peak_ptrsize = 32-bit
|
||||||
|
%endif
|
||||||
|
|
||||||
|
|
||||||
|
#--------- Portability --------------------------------------------------------
|
||||||
|
default: # data model applies to all benchmarks
|
||||||
|
%if %{bits} == 32
|
||||||
|
# Strongly recommended because at run-time, operations using modern file
|
||||||
|
# systems may fail spectacularly and frequently (or, worse, quietly and
|
||||||
|
# randomly) if a program does not accommodate 64-bit metadata.
|
||||||
|
EXTRA_PORTABILITY = -D_FILE_OFFSET_BITS=64
|
||||||
|
%else
|
||||||
|
EXTRA_PORTABILITY = -DSPEC_LP64
|
||||||
|
%endif
|
||||||
|
|
||||||
|
# Benchmark-specific portability (ordered by last 2 digits of bmark number)
|
||||||
|
|
||||||
|
500.perlbench_r,600.perlbench_s: #lang='C'
|
||||||
|
%if %{bits} == 32
|
||||||
|
% define suffix IA32
|
||||||
|
%else
|
||||||
|
% define suffix X64
|
||||||
|
%endif
|
||||||
|
PORTABILITY = -DSPEC_LINUX_%{suffix}
|
||||||
|
|
||||||
|
521.wrf_r,621.wrf_s: #lang='F,C'
|
||||||
|
CPORTABILITY = -DSPEC_CASE_FLAG
|
||||||
|
FPORTABILITY = -fconvert=big-endian
|
||||||
|
|
||||||
|
523.xalancbmk_r,623.xalancbmk_s: #lang='CXX'
|
||||||
|
PORTABILITY = -DSPEC_LINUX
|
||||||
|
|
||||||
|
526.blender_r: #lang='CXX,C'
|
||||||
|
PORTABILITY = -funsigned-char -DSPEC_LINUX
|
||||||
|
|
||||||
|
527.cam4_r,627.cam4_s: #lang='F,C'
|
||||||
|
PORTABILITY = -DSPEC_CASE_FLAG
|
||||||
|
|
||||||
|
628.pop2_s: #lang='F,C'
|
||||||
|
CPORTABILITY = -DSPEC_CASE_FLAG
|
||||||
|
FPORTABILITY = -fconvert=big-endian
|
||||||
|
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
# GCC workarounds that do not count as PORTABILITY
|
||||||
|
#----------------------------------------------------------------------
|
||||||
|
# The workarounds in this section would not qualify under the SPEC CPU
|
||||||
|
# PORTABILITY rule.
|
||||||
|
# - In peak, they can be set as needed for individual benchmarks.
|
||||||
|
# - In base, individual settings are not allowed; set for whole suite.
|
||||||
|
# See:
|
||||||
|
# https://www.spec.org/cpu2017/Docs/runrules.html#portability
|
||||||
|
# https://www.spec.org/cpu2017/Docs/runrules.html#BaseFlags
|
||||||
|
#
|
||||||
|
# Integer workarounds - peak
|
||||||
|
#
|
||||||
|
500.perlbench_r,600.perlbench_s=peak: # https://www.spec.org/cpu2017/Docs/benchmarks/500.perlbench_r.html
|
||||||
|
EXTRA_CFLAGS = -fno-strict-aliasing -fno-unsafe-math-optimizations -fno-finite-math-only
|
||||||
|
502.gcc_r,602.gcc_s=peak: # https://www.spec.org/cpu2017/Docs/benchmarks/502.gcc_r.html
|
||||||
|
EXTRA_CFLAGS = -fno-strict-aliasing -fgnu89-inline
|
||||||
|
505.mcf_r,605.mcf_s=peak: # https://www.spec.org/cpu2017/Docs/benchmarks/505.mcf_r.html
|
||||||
|
EXTRA_CFLAGS = -fno-strict-aliasing
|
||||||
|
525.x264_r,625.x264_s=peak: # https://www.spec.org/cpu2017/Docs/benchmarks/525.x264_r.html
|
||||||
|
EXTRA_CFLAGS = -fcommon
|
||||||
|
#
|
||||||
|
# Integer workarounds - base - combine the above - https://www.spec.org/cpu2017/Docs/runrules.html#BaseFlags
|
||||||
|
#
|
||||||
|
intrate,intspeed=base:
|
||||||
|
EXTRA_CFLAGS = -fno-strict-aliasing -fno-unsafe-math-optimizations -fno-finite-math-only -fgnu89-inline -fcommon
|
||||||
|
#
|
||||||
|
# Floating Point workarounds - peak
|
||||||
|
#
|
||||||
|
511.povray_r=peak: # https://www.spec.org/cpu2017/Docs/benchmarks/511.povray_r.html
|
||||||
|
EXTRA_CFLAGS = -fno-strict-aliasing
|
||||||
|
521.wrf_r,621.wrf_s=peak: # https://www.spec.org/cpu2017/Docs/benchmarks/521.wrf_r.html
|
||||||
|
% ifdef %{GCCge10} # workaround for GCC v10 (and presumably later)
|
||||||
|
EXTRA_FFLAGS = -fallow-argument-mismatch
|
||||||
|
% endif
|
||||||
|
527.cam4_r,627.cam4_s=peak: # https://www.spec.org/cpu2017/Docs/benchmarks/527.cam4_r.html
|
||||||
|
EXTRA_CFLAGS = -fno-strict-aliasing
|
||||||
|
% ifdef %{GCCge10} # workaround for GCC v10 (and presumably later)
|
||||||
|
EXTRA_FFLAGS = -fallow-argument-mismatch
|
||||||
|
% endif
|
||||||
|
# See also topic "628.pop2_s basepeak" below
|
||||||
|
628.pop2_s=peak: # https://www.spec.org/cpu2017/Docs/benchmarks/628.pop2_s.html
|
||||||
|
% ifdef %{GCCge10} # workaround for GCC v10 (and presumably later)
|
||||||
|
EXTRA_FFLAGS = -fallow-argument-mismatch
|
||||||
|
% endif
|
||||||
|
#
|
||||||
|
# FP workarounds - base - combine the above - https://www.spec.org/cpu2017/Docs/runrules.html#BaseFlags
|
||||||
|
#
|
||||||
|
fprate,fpspeed=base:
|
||||||
|
EXTRA_CFLAGS = -fno-strict-aliasing
|
||||||
|
% ifdef %{GCCge10} # workaround for GCC v10 (and presumably later)
|
||||||
|
EXTRA_FFLAGS = -fallow-argument-mismatch
|
||||||
|
% endif
|
||||||
|
|
||||||
|
|
||||||
|
#-------- Tuning Flags common to Base and Peak --------------------------------
|
||||||
|
#
|
||||||
|
# Speed (OpenMP and Autopar allowed)
|
||||||
|
#
|
||||||
|
%if %{bits} == 32
|
||||||
|
intspeed,fpspeed:
|
||||||
|
#
|
||||||
|
# Many of the speed benchmarks (6nn.benchmark_s) do not fit in 32 bits
|
||||||
|
# If you wish to run SPECint2017_speed or SPECfp2017_speed, please use
|
||||||
|
#
|
||||||
|
# runcpu --define bits=64
|
||||||
|
#
|
||||||
|
fail_build = 1
|
||||||
|
%else
|
||||||
|
intspeed,fpspeed:
|
||||||
|
EXTRA_OPTIMIZE = -fopenmp -DSPEC_OPENMP
|
||||||
|
fpspeed:
|
||||||
|
#
|
||||||
|
# 627.cam4 needs a big stack; the preENV will apply it to all
|
||||||
|
# benchmarks in the set, as required by the rules.
|
||||||
|
#
|
||||||
|
preENV_OMP_STACKSIZE = 120M
|
||||||
|
%endif
|
||||||
|
|
||||||
|
#-------- Base Tuning Flags ----------------------------------------------
|
||||||
|
# EDIT if needed -- If you run into errors, you may need to adjust the
|
||||||
|
# optimization - for example you may need to remove
|
||||||
|
# the -march=native. See topic "Older GCC" above.
|
||||||
|
#
|
||||||
|
default=base: # flags for all base
|
||||||
|
OPTIMIZE = -g -O3 -march=native
|
||||||
|
|
||||||
|
|
||||||
|
#-------- Peak Tuning Flags ----------------------------------------------
|
||||||
|
default=peak:
|
||||||
|
OPTIMIZE = -g -Ofast -march=native -flto
|
||||||
|
PASS1_FLAGS = -fprofile-generate
|
||||||
|
PASS2_FLAGS = -fprofile-use
|
||||||
|
|
||||||
|
# 628.pop2_s basepeak: Depending on the interplay of several optimizations,
|
||||||
|
# 628.pop2_s might not validate with peak tuning. Use the base
|
||||||
|
# version instead. See:
|
||||||
|
# https:// www.spec.org/cpu2017/Docs/benchmarks/628.pop2_s.html
|
||||||
|
628.pop2_s=peak:
|
||||||
|
basepeak = yes
|
||||||
|
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
# Tester and System Descriptions - EDIT all sections below this point
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
# For info about any field, see
|
||||||
|
# https://www.spec.org/cpu2017/Docs/config.html#fieldname
|
||||||
|
# Example: https://www.spec.org/cpu2017/Docs/config.html#hw_memory
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#--------- EDIT to match your version -----------------------------------------
|
||||||
|
default:
|
||||||
|
sw_compiler001 = C/C++/Fortran: Version 10.1.0 of GCC, the
|
||||||
|
sw_compiler002 = GNU Compiler Collection
|
||||||
|
|
||||||
|
#--------- EDIT info about you ------------------------------------------------
|
||||||
|
# To understand the difference between hw_vendor/sponsor/tester, see:
|
||||||
|
# https://www.spec.org/cpu2017/Docs/config.html#test_sponsor
|
||||||
|
intrate,intspeed,fprate,fpspeed: # Important: keep this line
|
||||||
|
hw_vendor = My Corporation
|
||||||
|
tester = My Corporation
|
||||||
|
test_sponsor = My Corporation
|
||||||
|
license_num = nnn (Your SPEC license number)
|
||||||
|
# prepared_by = # Ima Pseudonym # Whatever you like: is never output
|
||||||
|
|
||||||
|
|
||||||
|
#--------- EDIT system availability dates -------------------------------------
|
||||||
|
intrate,intspeed,fprate,fpspeed: # Important: keep this line
|
||||||
|
# Example # Brief info about field
|
||||||
|
hw_avail = # Nov-2099 # Date of LAST hardware component to ship
|
||||||
|
sw_avail = # Nov-2099 # Date of LAST software component to ship
|
||||||
|
fw_bios = # Version Mumble released May-2099 # Firmware information
|
||||||
|
|
||||||
|
#--------- EDIT system information --------------------------------------------
|
||||||
|
intrate,intspeed,fprate,fpspeed: # Important: keep this line
|
||||||
|
# Example # Brief info about field
|
||||||
|
# hw_cpu_name = # Intel Xeon E9-9999 v9 # chip name
|
||||||
|
hw_cpu_nominal_mhz = # 9999 # Nominal chip frequency, in MHz
|
||||||
|
hw_cpu_max_mhz = # 9999 # Max chip frequency, in MHz
|
||||||
|
# hw_disk = # 9 x 9 TB SATA III 9999 RPM # Size, type, other perf-relevant info
|
||||||
|
hw_model = # TurboBlaster 3000 # system model name
|
||||||
|
# hw_nchips = # 99 # number chips enabled
|
||||||
|
hw_ncores = # 9999 # number cores enabled
|
||||||
|
hw_ncpuorder = # 1-9 chips # Ordering options
|
||||||
|
hw_nthreadspercore = # 9 # number threads enabled per core
|
||||||
|
hw_other = # TurboNUMA Router 10 Gb # Other perf-relevant hw, or "None"
|
||||||
|
|
||||||
|
# hw_memory001 = # 999 GB (99 x 9 GB 2Rx4 PC4-2133P-R, # The 'PCn-etc' is from the JEDEC
|
||||||
|
# hw_memory002 = # running at 1600 MHz) # label on the DIMM.
|
||||||
|
|
||||||
|
hw_pcache = # 99 KB I + 99 KB D on chip per core # Primary cache size, type, location
|
||||||
|
hw_scache = # 99 KB I+D on chip per 9 cores # Second cache or "None"
|
||||||
|
hw_tcache = # 9 MB I+D on chip per chip # Third cache or "None"
|
||||||
|
hw_ocache = # 9 GB I+D off chip per system board # Other cache or "None"
|
||||||
|
|
||||||
|
# sw_file = # ext99 # File system
|
||||||
|
# sw_os001 = # Linux Sailboat # Operating system
|
||||||
|
# sw_os002 = # Distribution 7.2 SP1 # and version
|
||||||
|
sw_other = # TurboHeap Library V8.1 # Other perf-relevant sw, or "None"
|
||||||
|
# sw_state = # Run level 99 # Software state.
|
||||||
|
|
||||||
|
power_management = # briefly summarize power settings
|
||||||
|
|
||||||
|
# Note: Some commented-out fields above are automatically set to preliminary
|
||||||
|
# values by sysinfo
|
||||||
|
# https://www.spec.org/cpu2017/Docs/config.html#sysinfo
|
||||||
|
# Uncomment lines for which you already know a better answer than sysinfo
|
70
pkgs/spec-cpu/launcher.sh
Normal file
70
pkgs/spec-cpu/launcher.sh
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ -z "$SPEC" ]; then
|
||||||
|
SPEC=$(spec-cpu-mini)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$SPEC" ]; then
|
||||||
|
echo "cannot find spec, set SPEC variable"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
where=$TMPDIR
|
||||||
|
if [ -z "$where" ]; then
|
||||||
|
if [ -d /tmp ]; then
|
||||||
|
where=/tmp
|
||||||
|
else
|
||||||
|
where=$PWD
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
cwd=$(readlink -f $where)
|
||||||
|
# Place the outcome here
|
||||||
|
wd="$cwd/spec"
|
||||||
|
mkdir -p "$wd"
|
||||||
|
|
||||||
|
benchniter=1
|
||||||
|
benchsize=test
|
||||||
|
benchtune=base
|
||||||
|
|
||||||
|
echo "--- Placing output in $wd ---"
|
||||||
|
|
||||||
|
printf 'benchmark\tsize\ttune\titer\ttime_s\n' > "$wd/time.csv"
|
||||||
|
|
||||||
|
for srcbench in $SPEC/benchspec/CPU/*; do
|
||||||
|
name=$(basename $srcbench)
|
||||||
|
bench="$wd/$name"
|
||||||
|
bench_out="$wd/$name.csv"
|
||||||
|
rm -rf "$bench"
|
||||||
|
cp -r "$srcbench" "$bench"
|
||||||
|
chmod +w -R "$bench"
|
||||||
|
|
||||||
|
rundir="$bench/run/run_${benchtune}_${benchsize}_nix-m64.0000"
|
||||||
|
sed -i '/^-C/d' "$rundir/speccmds.cmd"
|
||||||
|
echo "--- Running $name for $benchniter iterations ---"
|
||||||
|
(
|
||||||
|
#set -x
|
||||||
|
cd $rundir
|
||||||
|
specinvoke -i $benchniter -E speccmds.cmd > /dev/null
|
||||||
|
#set +x
|
||||||
|
)
|
||||||
|
# Print time
|
||||||
|
awk '/^run [0-9]* elapsed time/{printf \
|
||||||
|
"%s\t%s\t%s\t%s\t%s\n", \
|
||||||
|
"'$name'","'$benchsize'","'$benchtune'",$2,$7}' \
|
||||||
|
"$rundir/speccmds.out" > "$bench_out"
|
||||||
|
|
||||||
|
cat "$bench_out"
|
||||||
|
|
||||||
|
# Accumulate in main CSV
|
||||||
|
cat "$bench_out" >> "$wd/time.csv"
|
||||||
|
|
||||||
|
# Erase intermediate files as they occupy RAM.
|
||||||
|
rm -rf "$bench"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "--- RESULTS in $wd/time.csv ---"
|
||||||
|
cat "$wd/time.csv"
|
||||||
|
echo "---------------------------------------"
|
60
pkgs/spec-cpu/mini.nix
Normal file
60
pkgs/spec-cpu/mini.nix
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
stdenv
|
||||||
|
, spec-cpu
|
||||||
|
, spec-cpu-tools
|
||||||
|
, specinvoke
|
||||||
|
, speclaunch
|
||||||
|
}:
|
||||||
|
|
||||||
|
stdenv.mkDerivation rec {
|
||||||
|
pname = "spec-cpu-mini";
|
||||||
|
version = spec-cpu.version;
|
||||||
|
src = null;
|
||||||
|
unpackPhase = "true";
|
||||||
|
|
||||||
|
# Select only a subset of the benchmarks:
|
||||||
|
# https://www.spec.org/cpu2017/Docs/#benchdocs
|
||||||
|
benchList = [
|
||||||
|
# -- SPECspeed 2017 Integer --
|
||||||
|
"600.perlbench_s"
|
||||||
|
"602.gcc_s"
|
||||||
|
"605.mcf_s"
|
||||||
|
"620.omnetpp_s"
|
||||||
|
#"623.xalancbmk_s" # Big
|
||||||
|
#"625.x264_s" # Big
|
||||||
|
#"631.deepsjeng_s" # Requires 7 GiB of RAM
|
||||||
|
"641.leela_s"
|
||||||
|
"648.exchange2_s"
|
||||||
|
# "657.xz_s" # Runs out of memory with 700 MiB of RAM
|
||||||
|
];
|
||||||
|
|
||||||
|
dontConfigure = true;
|
||||||
|
buildPhase = ''
|
||||||
|
pwd
|
||||||
|
mkdir -p benchspec/CPU
|
||||||
|
for bench in $benchList; do
|
||||||
|
cp -r ${spec-cpu}/benchspec/CPU/$bench benchspec/CPU/
|
||||||
|
done
|
||||||
|
|
||||||
|
# Make writable
|
||||||
|
chmod -R +w benchspec
|
||||||
|
|
||||||
|
# Remove environment
|
||||||
|
find benchspec -name '*.cmd' | xargs sed -i '/^-E/d'
|
||||||
|
# Remove compare script as it refers to spec-cpu-tools
|
||||||
|
find benchspec -name 'compare.cmd' -delete
|
||||||
|
'';
|
||||||
|
installPhase = ''
|
||||||
|
pwd
|
||||||
|
mkdir -p $out
|
||||||
|
cp -r benchspec/ $out
|
||||||
|
mkdir -p $out/bin
|
||||||
|
echo -e "#!$SHELL\necho $out" > $out/bin/spec-cpu-mini
|
||||||
|
chmod +x $out/bin/spec-cpu-mini
|
||||||
|
cp ${specinvoke}/bin/specinvoke $out/bin
|
||||||
|
cp ${speclaunch}/bin/speclaunch $out/bin
|
||||||
|
'';
|
||||||
|
enableParallelBuilding = false;
|
||||||
|
hardeningDisable = [ "all" ];
|
||||||
|
dontStrip = true;
|
||||||
|
}
|
15
pkgs/spec-cpu/specinvoke-execve.patch
Normal file
15
pkgs/spec-cpu/specinvoke-execve.patch
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
--- a/unix.c 2024-10-08 12:30:18.785111397 +0200
|
||||||
|
+++ b/unix.c 2024-10-08 12:32:09.580923368 +0200
|
||||||
|
@@ -165,7 +165,11 @@ pid_t invoke(copy_info_t *ui, command_in
|
||||||
|
/* We could redirect them here. This might be useful for VMS? */
|
||||||
|
*(si->command_ptr) = cmd;
|
||||||
|
si->invoke_args[0] = si->shell;
|
||||||
|
- execve(si->shell, si->invoke_args, env);
|
||||||
|
+ if (execve(si->shell, si->invoke_args, env) != 0) {
|
||||||
|
+ fprintf (stderr, "Can't execute command: %s(%d)\n",
|
||||||
|
+ STRERROR(errno), errno);
|
||||||
|
+ specinvoke_exit (1, si);
|
||||||
|
+ }
|
||||||
|
} else { /* Parent */
|
||||||
|
ui->pid = pid;
|
||||||
|
fprintf (si->outfp,
|
33
pkgs/spec-cpu/specinvoke.nix
Normal file
33
pkgs/spec-cpu/specinvoke.nix
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
stdenv
|
||||||
|
, libarchive
|
||||||
|
, spec-cpu-tools
|
||||||
|
, runCommandNoCC
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
version = spec-cpu-tools.version;
|
||||||
|
tar = runCommandNoCC "specinvoke-${version}.tar" {
|
||||||
|
src = spec-cpu-tools.src;
|
||||||
|
nativeBuildInputs = [ libarchive ];
|
||||||
|
} ''
|
||||||
|
mkdir iso
|
||||||
|
bsdtar -C iso -xf $src
|
||||||
|
cp iso/install_archives/tools-src.tar $out
|
||||||
|
'';
|
||||||
|
in stdenv.mkDerivation {
|
||||||
|
pname = "specinvoke";
|
||||||
|
version = version;
|
||||||
|
src = tar;
|
||||||
|
sourceRoot = "tools/src/specinvoke/";
|
||||||
|
patches = [
|
||||||
|
./specinvoke-execve.patch
|
||||||
|
];
|
||||||
|
# Almost no bugs
|
||||||
|
preInstall = ''
|
||||||
|
mkdir -p $out/bin
|
||||||
|
'';
|
||||||
|
enableParallelBuilding = false;
|
||||||
|
hardeningDisable = [ "all" ];
|
||||||
|
dontStrip = true;
|
||||||
|
}
|
21
pkgs/spec-cpu/speclaunch.nix
Normal file
21
pkgs/spec-cpu/speclaunch.nix
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
stdenv
|
||||||
|
, bash
|
||||||
|
}:
|
||||||
|
|
||||||
|
stdenv.mkDerivation {
|
||||||
|
name = "speclaunch";
|
||||||
|
src = ./launcher.sh;
|
||||||
|
dontUnpack = true;
|
||||||
|
dontConfigure = true;
|
||||||
|
dontBuild = true;
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out/bin
|
||||||
|
cp $src $out/bin/speclaunch
|
||||||
|
chmod +x $out/bin/speclaunch
|
||||||
|
'';
|
||||||
|
buildInputs = [ bash ];
|
||||||
|
enableParallelBuilding = false;
|
||||||
|
hardeningDisable = [ "all" ];
|
||||||
|
dontStrip = true;
|
||||||
|
}
|
106
pkgs/spec-cpu/tools.nix
Normal file
106
pkgs/spec-cpu/tools.nix
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
{
|
||||||
|
stdenv
|
||||||
|
, libarchive
|
||||||
|
, xz
|
||||||
|
, gnutar
|
||||||
|
, gfortran
|
||||||
|
, coreutils
|
||||||
|
, requireFile
|
||||||
|
, autoPatchelfHook
|
||||||
|
, libxcrypt-legacy
|
||||||
|
, glibc
|
||||||
|
, lib
|
||||||
|
}:
|
||||||
|
|
||||||
|
stdenv.mkDerivation rec {
|
||||||
|
pname = "spec-cpu-tools";
|
||||||
|
version = "1.1.7";
|
||||||
|
|
||||||
|
src = requireFile {
|
||||||
|
name = "cpu2017-1.1.7.iso";
|
||||||
|
sha256 = "02630819h64dyy57wkj33fhwwqgbw6mqc5awh1zm48pkvvl0l600";
|
||||||
|
message = ''
|
||||||
|
Missing SPEC CPU 2017 1.1.7.
|
||||||
|
|
||||||
|
Add it to the store with:
|
||||||
|
|
||||||
|
$ nix-prefetch-url file:/path/to/cpu2017-1.1.7.iso
|
||||||
|
/nix/store/mk4hr8xwd62akp7iw5khq638ssba8qz0-cpu2017-1.1.7.iso
|
||||||
|
|
||||||
|
Notice that the name must match exactly "cpu2017-1.1.7.iso".
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
unpackPhase = ''
|
||||||
|
set -x
|
||||||
|
mkdir iso
|
||||||
|
bsdtar -C iso -xf $src
|
||||||
|
chmod +w -R iso
|
||||||
|
|
||||||
|
#for f in iso/install_archives/benchball/*; do
|
||||||
|
# bsdtar -xf $f
|
||||||
|
#done
|
||||||
|
#mkdir src
|
||||||
|
#bsdtar -C src -xf iso/install_archives/benchball/cpu2017-1.1.7.base.tar.xz
|
||||||
|
#bsdtar -C src -xf iso/install_archives/benchball/519.lbm_r-1.000503.tar.xz
|
||||||
|
|
||||||
|
sourceRoot="$PWD/iso"
|
||||||
|
set +x
|
||||||
|
'';
|
||||||
|
|
||||||
|
# We need a working specxz binary
|
||||||
|
configurePhase = ''
|
||||||
|
patchShebangs install.sh
|
||||||
|
|
||||||
|
set -x
|
||||||
|
|
||||||
|
# Replace "spec*" tools by symlinks to working binaries
|
||||||
|
pushd tools/bin/linux-x86_64
|
||||||
|
ln -fs ${xz}/bin/xz specxz
|
||||||
|
ln -fs ${gnutar}/bin/tar spectar
|
||||||
|
patchelf \
|
||||||
|
--set-interpreter "$(cat $NIX_CC/nix-support/dynamic-linker)" \
|
||||||
|
specsha512sum
|
||||||
|
ls -l spec*
|
||||||
|
./specxz -h
|
||||||
|
./spectar --help
|
||||||
|
ldd ./specsha512sum
|
||||||
|
./specsha512sum --help
|
||||||
|
popd
|
||||||
|
|
||||||
|
# sha512sum requires -e, not provided by coreutils
|
||||||
|
|
||||||
|
export SPEC="$sourceRoot"
|
||||||
|
|
||||||
|
# Don't run the tests
|
||||||
|
sed -i 's/^.*shrc will.*$/exit 0/g' install.sh
|
||||||
|
|
||||||
|
set +x
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
bash -x install.sh -f -d $out -u linux-x86_64
|
||||||
|
'';
|
||||||
|
|
||||||
|
preFixup = ''
|
||||||
|
# Fix temporary directory creation
|
||||||
|
sed -i '/^sub get_tmp_directory/a\ return tempdir(CLEANUP => 1);' \
|
||||||
|
$out/bin/common/util_common.pl
|
||||||
|
|
||||||
|
sed -i '/my $dir = jp($top, $config->resultdir, $subdir);/c\ my $dir = ::get_tmp_directory($config, 1);' \
|
||||||
|
$out/bin/harness/log.pl
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Missing libdb-4.7.so
|
||||||
|
autoPatchelfIgnoreMissingDeps = true;
|
||||||
|
|
||||||
|
nativeBuildInputs = [ libxcrypt-legacy libarchive autoPatchelfHook ];
|
||||||
|
#buildInputs = [ libxcrypt-legacy ];
|
||||||
|
|
||||||
|
enableParallelBuilding = false;
|
||||||
|
hardeningDisable = [ "all" ];
|
||||||
|
dontStrip = true;
|
||||||
|
meta.broken = (stdenv.buildPlatform.config != "x86_64-unknown-linux-gnu") ||
|
||||||
|
(stdenv.hostPlatform.config != "x86_64-unknown-linux-gnu") ||
|
||||||
|
(stdenv.targetPlatform.config != "riscv64-unknown-linux-gnu");
|
||||||
|
}
|
33
pkgs/stream/default.nix
Normal file
33
pkgs/stream/default.nix
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
stdenv
|
||||||
|
, fetchFromGitHub
|
||||||
|
}:
|
||||||
|
|
||||||
|
stdenv.mkDerivation rec {
|
||||||
|
pname = "stream";
|
||||||
|
version = "4dbce1d0";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "jeffhammond";
|
||||||
|
repo = "STREAM";
|
||||||
|
rev = "4dbce1d0fdb7410e8f21b48f3381bc0a1341967f";
|
||||||
|
sha256 = "sha256-sBwdPeaMyI/wH1Nq0yQtb/kvi5913e0azXaulOJIG3A=";
|
||||||
|
};
|
||||||
|
|
||||||
|
# CFLAGS='-O2 -fopenmp -DSTREAM_ARRAY_SIZE=40000000'
|
||||||
|
buildPhase = ''
|
||||||
|
set -x
|
||||||
|
make stream_c.exe CC=$CC FC=$FC CFLAGS=-O2
|
||||||
|
set +x
|
||||||
|
'';
|
||||||
|
|
||||||
|
#nativeBuildInputs = [ gfortran ];
|
||||||
|
dontStrip = true;
|
||||||
|
dontConfigure = true;
|
||||||
|
enableParallelBuilding = false;
|
||||||
|
hardeningDisable = [ "all" ];
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out/bin
|
||||||
|
cp -a stream_c.exe $out/bin/stream
|
||||||
|
'';
|
||||||
|
}
|
4
tools/.gitignore
vendored
Normal file
4
tools/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
plictool
|
||||||
|
csrtool
|
||||||
|
memtool
|
||||||
|
*.bin
|
20
tools/Makefile
Normal file
20
tools/Makefile
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
CFLAGS=-Wall -static
|
||||||
|
PREFIX?=/usr/local
|
||||||
|
bin=plictool csrtool memtool unalign
|
||||||
|
|
||||||
|
all: $(bin)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(bin)
|
||||||
|
|
||||||
|
install:
|
||||||
|
mkdir -p $(PREFIX)/bin
|
||||||
|
cp -a $(bin) $(PREFIX)/bin
|
||||||
|
|
||||||
|
plictool: plictool.c
|
||||||
|
|
||||||
|
csrtool: csrtool.c
|
||||||
|
|
||||||
|
memtool: memtool.c
|
||||||
|
|
||||||
|
unalign: unalign.c
|
34
tools/csrtool.c
Normal file
34
tools/csrtool.c
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
/* Print */
|
||||||
|
if (argc > 1) {
|
||||||
|
// Wait for all memory operations to finish
|
||||||
|
__asm__ volatile ("fence");
|
||||||
|
|
||||||
|
if (strcmp(argv[1], "mem-in-order") == 0) {
|
||||||
|
__asm__ volatile ("fence");
|
||||||
|
__asm__ volatile ("csrwi 0x801, 2");
|
||||||
|
} else if (strcmp(argv[1], "all-in-order") == 0) {
|
||||||
|
__asm__ volatile ("fence");
|
||||||
|
__asm__ volatile ("csrwi 0x801, 7");
|
||||||
|
} else if (strcmp(argv[1], "all-out-of-order") == 0) {
|
||||||
|
__asm__ volatile ("fence");
|
||||||
|
__asm__ volatile ("csrwi 0x801, 0");
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "unknown '%s', use: mem-in-order, all-in-order or all-out-of-order\n", argv[1]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for all memory operations to finish
|
||||||
|
__asm__ volatile ("fence");
|
||||||
|
unsigned result;
|
||||||
|
asm("csrr %0, 0x801" : "=r"(result) : );
|
||||||
|
printf("CSR 0x801 = %xu\n", result);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
214
tools/memtool.c
Normal file
214
tools/memtool.c
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
/* Copyright (c) 2024 Barcelona Supercomputing Center (BSC)
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
* Author: Rodrigo Arias Mallo <rodrigo.arias@bsc.es> */
|
||||||
|
|
||||||
|
/* This is just a small tool to exercise the memory which attempts to
|
||||||
|
* stress the virtual memory, in a crude attempt to reproduce the hangs
|
||||||
|
* that we were observing while booting NixOS. */
|
||||||
|
|
||||||
|
/* Changelog:
|
||||||
|
* v0.0.1 (2024-07-10): Start version with "chain" and "fill" tests.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define MAX_SIZE (1024L * 1024L)
|
||||||
|
|
||||||
|
struct block {
|
||||||
|
struct block *next;
|
||||||
|
size_t size;
|
||||||
|
uint32_t data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct chain {
|
||||||
|
struct block *front;
|
||||||
|
struct block *tail;
|
||||||
|
long maxsize;
|
||||||
|
long nbytes;
|
||||||
|
long nblocks;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
allocate(struct chain *chain)
|
||||||
|
{
|
||||||
|
/* Constraint the number of elements based on the maxsize */
|
||||||
|
long maxn = chain->maxsize / sizeof(uint32_t);
|
||||||
|
long n = (long) rand() % maxn;
|
||||||
|
|
||||||
|
size_t size = sizeof(struct block) + n * sizeof(uint32_t);
|
||||||
|
|
||||||
|
printf("allocating...\n");
|
||||||
|
|
||||||
|
struct block *b = malloc(size);
|
||||||
|
|
||||||
|
/* No mem */
|
||||||
|
if (b == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
b->size = size;
|
||||||
|
b->next = NULL;
|
||||||
|
|
||||||
|
/* Populate the block with some data */
|
||||||
|
printf("filling...\n");
|
||||||
|
for (long i = 0; i < n; i++)
|
||||||
|
b->data[i] = rand();
|
||||||
|
|
||||||
|
/* Add it to the chain */
|
||||||
|
if (chain->tail)
|
||||||
|
chain->tail->next = b;
|
||||||
|
|
||||||
|
chain->tail = b;
|
||||||
|
|
||||||
|
/* And to the front if it is the first */
|
||||||
|
if (!chain->front)
|
||||||
|
chain->front = b;
|
||||||
|
|
||||||
|
chain->nblocks++;
|
||||||
|
chain->nbytes += size;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
deallocate(struct chain *chain)
|
||||||
|
{
|
||||||
|
/* May run out of blocks */
|
||||||
|
if (!chain->front)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
struct block *b = chain->front;
|
||||||
|
|
||||||
|
chain->front = b->next;
|
||||||
|
|
||||||
|
/* Last block */
|
||||||
|
if (chain->tail == b)
|
||||||
|
chain->tail = NULL;
|
||||||
|
|
||||||
|
chain->nblocks--;
|
||||||
|
chain->nbytes -= b->size;
|
||||||
|
|
||||||
|
printf("deallocating...\n");
|
||||||
|
free(b);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_chain(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct chain chain = {0};
|
||||||
|
|
||||||
|
/* Default 1 MiB */
|
||||||
|
chain.maxsize = 1024L * 1024L;
|
||||||
|
|
||||||
|
if (argc > 0)
|
||||||
|
chain.maxsize = atol(argv[0]);
|
||||||
|
|
||||||
|
printf("mode chain: maxsize=%ldK\n", chain.maxsize / 1024);
|
||||||
|
|
||||||
|
srand(123);
|
||||||
|
|
||||||
|
for (long iter = 0; ; iter++) {
|
||||||
|
int p = rand() % 100;
|
||||||
|
int is_alloc = (p > 10);
|
||||||
|
int ret = 0;
|
||||||
|
char c;
|
||||||
|
if (is_alloc) {
|
||||||
|
if (allocate(&chain) == 0)
|
||||||
|
c = 'A';
|
||||||
|
else
|
||||||
|
c = '-';
|
||||||
|
} else {
|
||||||
|
if (deallocate(&chain) == 0)
|
||||||
|
c = 'D';
|
||||||
|
else
|
||||||
|
c = '-';
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("iter=%ld nblocks=%ld allocated=%ldK (%c)\n",
|
||||||
|
iter, chain.nblocks, chain.nbytes / 1024,
|
||||||
|
c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_fill(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
/* Default: 256 MiB */
|
||||||
|
long nbytes = 256L * 1024L * 1024L;
|
||||||
|
|
||||||
|
if (argc > 0)
|
||||||
|
nbytes = atol(argv[0]);
|
||||||
|
|
||||||
|
long n = nbytes / sizeof(int);
|
||||||
|
|
||||||
|
printf("mode fill: nbytes=%ldM, n=%ld\n",
|
||||||
|
nbytes / (1024L * 1024L), n);
|
||||||
|
|
||||||
|
int *buf = malloc(nbytes);
|
||||||
|
|
||||||
|
if (!buf) {
|
||||||
|
perror("malloc failed");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (long i = 0; i < n; i++) {
|
||||||
|
buf[i] = i;
|
||||||
|
if ((i % (1024L * 1024L)) == 0)
|
||||||
|
printf("written=%ldK, addr=%p OK\n",
|
||||||
|
i * sizeof(int) / 1024L,
|
||||||
|
&buf[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
|
||||||
|
printf("fill test OK\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
printf(
|
||||||
|
"Usage: memtool <command> [<options>...]\n"
|
||||||
|
"\n"
|
||||||
|
"Available commands:\n"
|
||||||
|
" chain [<maxsize>]\n"
|
||||||
|
" Creates a chain of blocks of random size, each up to maxsize\n"
|
||||||
|
" or 1MiB if not given. Blocks are freed with 10% probability\n"
|
||||||
|
" starting from the oldest.\n"
|
||||||
|
"\n"
|
||||||
|
" fill [<size>]\n"
|
||||||
|
" Allocates a vector of the given size (or 256 MiB if not given)\n"
|
||||||
|
" and initializes it with a increasing value per element.\n"
|
||||||
|
"\n");
|
||||||
|
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
printf("memtool v0.0.1 - Rodrigo Arias Mallo <rodrigo.arias@bsc.es>\n");
|
||||||
|
|
||||||
|
if (argc < 2)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
/* Skip program name */
|
||||||
|
argc--; argv++;
|
||||||
|
|
||||||
|
const char *mode = argv[0];
|
||||||
|
|
||||||
|
/* Skip mode */
|
||||||
|
argc--; argv++;
|
||||||
|
|
||||||
|
if (strcmp(mode, "chain") == 0)
|
||||||
|
do_chain(argc, argv);
|
||||||
|
else if (strcmp(mode, "fill") == 0)
|
||||||
|
do_fill(argc, argv);
|
||||||
|
else
|
||||||
|
usage();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
388
tools/plictool.c
Normal file
388
tools/plictool.c
Normal file
@ -0,0 +1,388 @@
|
|||||||
|
/* Copyright (c) 2024 Barcelona Supercomputing Center (BSC)
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
* Author: Rodrigo Arias Mallo <rodrigo.arias@bsc.es> */
|
||||||
|
|
||||||
|
/* Small utility to manage the PLIC. */
|
||||||
|
|
||||||
|
/* Changelog:
|
||||||
|
* v0.0.1 (2024-09-03): Initial version.
|
||||||
|
* v0.0.2 (2024-09-04): Print contexts in another line and masked information.
|
||||||
|
* v0.0.3 (2024-09-04): Make output format more clear and add manual.
|
||||||
|
* v0.0.4 (2024-09-30): Implement support for claiming an interrupt.
|
||||||
|
* v0.0.5 (2024-10-02): Support other read/write operations.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define VERSION "v0.0.5"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
int operation;
|
||||||
|
const char *plic_address_str = "0x40800000";
|
||||||
|
long ncontexts = 2L;
|
||||||
|
long maxsources = 1024L;
|
||||||
|
long nsources = 1024L;
|
||||||
|
|
||||||
|
long context = -1;
|
||||||
|
long source = -1;
|
||||||
|
long value = -1;
|
||||||
|
bool value_set = NULL;
|
||||||
|
|
||||||
|
struct ctx {
|
||||||
|
uint32_t threshold;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct source_ctx {
|
||||||
|
bool enabled;
|
||||||
|
bool masked;
|
||||||
|
uint32_t threshold;
|
||||||
|
const char *state;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct source {
|
||||||
|
bool pending;
|
||||||
|
bool show;
|
||||||
|
uint32_t priority;
|
||||||
|
struct source_ctx *ctx;
|
||||||
|
long ncontexts;
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint32_t
|
||||||
|
read_reg(void *base, size_t offset)
|
||||||
|
{
|
||||||
|
volatile uint32_t *p = base + offset;
|
||||||
|
return *p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_reg(void *base, size_t offset, uint32_t value)
|
||||||
|
{
|
||||||
|
volatile uint32_t *p = base + offset;
|
||||||
|
*p = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
claim_get(void *base, uint32_t ctx)
|
||||||
|
{
|
||||||
|
return read_reg(base, 0x200004L + ctx * 0x1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
claim_set(void *base, uint32_t ctx, uint32_t value)
|
||||||
|
{
|
||||||
|
write_reg(base, 0x200004L + ctx * 0x1000, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
thre_get(void *base, uint32_t ctx)
|
||||||
|
{
|
||||||
|
return read_reg(base, 0x200000L + (ctx * 0x1000L));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
thre_set(void *base, uint32_t ctx, uint32_t value)
|
||||||
|
{
|
||||||
|
write_reg(base, 0x200000L + (ctx * 0x1000L), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
prio_get(void *base, uint32_t s)
|
||||||
|
{
|
||||||
|
return read_reg(base, s * 4L);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
prio_set(void *base, uint32_t s, uint32_t value)
|
||||||
|
{
|
||||||
|
write_reg(base, s * 4L, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
pending_get(void *base, uint32_t s)
|
||||||
|
{
|
||||||
|
uint32_t offset = 0x1000L + (s / 32L) * 4L;
|
||||||
|
uint32_t pending = read_reg(base, offset);
|
||||||
|
long shift = s % 32L;
|
||||||
|
|
||||||
|
return (pending >> shift) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pending_set(void *base, uint32_t s, uint32_t value)
|
||||||
|
{
|
||||||
|
uint32_t offset = 0x1000L + (s / 32L) * 4L;
|
||||||
|
uint32_t pending = read_reg(base, offset);
|
||||||
|
long shift = s % 32L;
|
||||||
|
|
||||||
|
if (value)
|
||||||
|
pending |= (1L << shift);
|
||||||
|
else
|
||||||
|
pending &= ~(1L << shift);
|
||||||
|
|
||||||
|
write_reg(base, offset, pending);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
enable_get(void *base, uint32_t c, uint32_t s)
|
||||||
|
{
|
||||||
|
size_t off_en = 0x2000L + 0x80L * c + (s / 32L) * 4L;
|
||||||
|
uint32_t enabled_reg = read_reg(base, off_en);
|
||||||
|
long shift = s % 32L;
|
||||||
|
return (enabled_reg >> shift) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
enable_set(void *base, uint32_t c, uint32_t s, uint32_t value)
|
||||||
|
{
|
||||||
|
size_t off_en = 0x2000L + 0x80L * c + (s / 32L) * 4L;
|
||||||
|
uint32_t enabled_reg = read_reg(base, off_en);
|
||||||
|
long shift = s % 32L;
|
||||||
|
|
||||||
|
if (value)
|
||||||
|
enabled_reg |= (1L << shift);
|
||||||
|
else
|
||||||
|
enabled_reg &= ~(1L << shift);
|
||||||
|
|
||||||
|
write_reg(base, off_en, enabled_reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
source_init(struct source *src, long ncontexts)
|
||||||
|
{
|
||||||
|
memset(src, 0, sizeof(struct source));
|
||||||
|
src->ctx = calloc(ncontexts, sizeof(struct source_ctx));
|
||||||
|
src->ncontexts = ncontexts;
|
||||||
|
if (src->ctx == NULL) {
|
||||||
|
perror("calloc failed");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
source_reset(struct source *src)
|
||||||
|
{
|
||||||
|
src->pending = false;
|
||||||
|
src->show = false;
|
||||||
|
src->priority = 0;
|
||||||
|
|
||||||
|
memset(src->ctx, 0, src->ncontexts * sizeof(struct source_ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
source_free(struct source *src)
|
||||||
|
{
|
||||||
|
free(src->ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
source_read(struct source *src, void *base, long s)
|
||||||
|
{
|
||||||
|
uint32_t pending_reg = read_reg(base, 0x1000L + (s / 32L) * 4L);
|
||||||
|
long shift = s % 32L;
|
||||||
|
src->pending = (pending_reg >> shift) & 1;
|
||||||
|
src->priority = read_reg(base, 0x0000L + (s * 4L));
|
||||||
|
|
||||||
|
bool ctx_show = 0;
|
||||||
|
for (long c = 0; c < src->ncontexts; c++) {
|
||||||
|
struct source_ctx *ctx = &src->ctx[c];
|
||||||
|
|
||||||
|
size_t off_en = 0x2000L + 0x80L * c + (s / 32L) * 4L;
|
||||||
|
uint32_t enabled_reg = read_reg(base, off_en);
|
||||||
|
ctx->enabled = (enabled_reg >> shift) & 1;
|
||||||
|
ctx->threshold = read_reg(base, 0x200000L + (c * 0x1000L));
|
||||||
|
ctx->masked = src->priority <= ctx->threshold;
|
||||||
|
ctx_show = ctx_show || ctx->enabled;
|
||||||
|
|
||||||
|
if (!ctx->enabled)
|
||||||
|
ctx->state = "-";
|
||||||
|
else if (ctx->masked)
|
||||||
|
ctx->state = "masked";
|
||||||
|
else
|
||||||
|
ctx->state = "firing";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show the source if it has some bit to non-zero */
|
||||||
|
src->show = src->pending || src->priority || ctx_show;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
list_sources(void *base)
|
||||||
|
{
|
||||||
|
printf("Source\tPend\tPrio");
|
||||||
|
for (long i = 0; i < ncontexts; i++) {
|
||||||
|
uint32_t threshold = read_reg(base, 0x200000L + (i * 0x1000L));
|
||||||
|
printf("\tC%ld(%u)", i, threshold);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
struct source s;
|
||||||
|
source_init(&s, ncontexts);
|
||||||
|
for (long i = 0; i < nsources; i++) {
|
||||||
|
source_reset(&s);
|
||||||
|
source_read(&s, base, i);
|
||||||
|
|
||||||
|
if (!s.show)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
printf("%ld\t%s\t%u", i, s.pending ? "yes" : "-", s.priority);
|
||||||
|
|
||||||
|
for (long j = 0; j < ncontexts; j++)
|
||||||
|
printf("\t%s", s.ctx[j].state);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
source_free(&s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void usage(void)
|
||||||
|
{
|
||||||
|
printf("plictool "VERSION" -- Rodrigo Arias Mallo <rodrigo.arias@bsc.es>\n");
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
|
"Usage:\n"
|
||||||
|
" plictool [-a addr] [-L] [-n nsrc] [-x nctx] # List (default)\n"
|
||||||
|
" plictool [-a addr] -C ctx [-w value] # Claim\n"
|
||||||
|
" plictool [-a addr] -T ctx [-w value] # Threshold\n"
|
||||||
|
" plictool [-a addr] -I src [-w value] # Priority\n"
|
||||||
|
" plictool [-a addr] -P src [-w value] # Pending\n"
|
||||||
|
" plictool [-a addr] -E src -c ctx [-w value] # Enabled\n"
|
||||||
|
" plictool -v # Version\n"
|
||||||
|
);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
const char *memfile = "/dev/mem";
|
||||||
|
int opt;
|
||||||
|
|
||||||
|
while ((opt = getopt(argc, argv, "f:a:LC:T:P:I:E:n:x:c:w:vh")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
/* Common flags */
|
||||||
|
case 'f':
|
||||||
|
memfile = optarg;
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
plic_address_str = optarg;
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
nsources = atol(optarg);
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
ncontexts = atol(optarg);
|
||||||
|
break;
|
||||||
|
case 'C': /* claim */
|
||||||
|
case 'T': /* threshold */
|
||||||
|
operation = opt;
|
||||||
|
context = atol(optarg);
|
||||||
|
break;
|
||||||
|
case 'P': /* pending */
|
||||||
|
case 'I': /* priority */
|
||||||
|
case 'E': /* enable */
|
||||||
|
operation = opt;
|
||||||
|
source = atol(optarg);
|
||||||
|
break;
|
||||||
|
case 'L': /* list */
|
||||||
|
operation = opt;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
context = atol(optarg);
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
value = atol(optarg);
|
||||||
|
value_set = true;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
printf("plictool "VERSION"\n");
|
||||||
|
exit(0);
|
||||||
|
case 'h':
|
||||||
|
default: /* '?' */
|
||||||
|
usage();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operation == 'P' || operation == 'I' || operation == 'E') {
|
||||||
|
if (source < 0) {
|
||||||
|
fprintf(stderr, "missing source\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operation == 'C' || operation == 'T' || operation == 'E') {
|
||||||
|
if (context < 0) {
|
||||||
|
fprintf(stderr, "missing context\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long long plic_address = strtoull(plic_address_str, NULL, 16);
|
||||||
|
|
||||||
|
//printf("plictool "VERSION" addr=0x%08llx nsrc=%ld nctx=%ld\n",
|
||||||
|
// plic_address, nsources, ncontexts);
|
||||||
|
|
||||||
|
int fd = open(memfile, O_RDWR | O_SYNC);
|
||||||
|
|
||||||
|
if (fd == -1) {
|
||||||
|
fprintf(stderr, "cannot open %s: %s", memfile, strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t map_size = 0x4000000UL;
|
||||||
|
void *map_base = mmap(0, map_size, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||||
|
fd, plic_address);
|
||||||
|
|
||||||
|
if (map_base == MAP_FAILED) {
|
||||||
|
perror("mmap failed");
|
||||||
|
if (errno == EPERM) {
|
||||||
|
fprintf(stderr, "Have you disabled 'CONFIG_STRICT_DEVMEM' and "
|
||||||
|
"'CONFIG_IO_STRICT_DEVMEM' in the kernel config?\n"
|
||||||
|
"Hint: zgrep STRICT_DEVMEM /proc/config.gz\n");
|
||||||
|
}
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operation == 'C') { /* claim */
|
||||||
|
if (value_set)
|
||||||
|
claim_set(map_base, context, value);
|
||||||
|
else
|
||||||
|
printf("%u\n", claim_get(map_base, context));
|
||||||
|
} else if (operation == 'T') { /* threshold */
|
||||||
|
if (value_set)
|
||||||
|
thre_set(map_base, context, value);
|
||||||
|
else
|
||||||
|
printf("%u\n", thre_get(map_base, context));
|
||||||
|
} else if (operation == 'I') { /* priority */
|
||||||
|
if (value_set)
|
||||||
|
prio_set(map_base, source, value);
|
||||||
|
else
|
||||||
|
printf("%u\n", prio_get(map_base, source));
|
||||||
|
} else if (operation == 'P') { /* pending */
|
||||||
|
if (value_set)
|
||||||
|
pending_set(map_base, source, value);
|
||||||
|
else
|
||||||
|
printf("%u\n", pending_get(map_base, source));
|
||||||
|
} else if (operation == 'E') { /* enable */
|
||||||
|
if (value_set)
|
||||||
|
enable_set(map_base, context, source, value);
|
||||||
|
else
|
||||||
|
printf("%u\n", enable_get(map_base, context, source));
|
||||||
|
} else /* list */ {
|
||||||
|
list_sources(map_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
munmap(map_base, map_size);
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
239
tools/unalign.c
Normal file
239
tools/unalign.c
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
/*
|
||||||
|
* unalign_check - check the CPU behaviour on different alignments
|
||||||
|
* Copyright (C) 2021 Matteo Croce <mcroce@linux.microsoft.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
#define ACT_READ 0
|
||||||
|
#define ACT_WRITE 1
|
||||||
|
#define ACT_XOR 2
|
||||||
|
#define ACT_COPY 3
|
||||||
|
|
||||||
|
#define READ(SIZE) \
|
||||||
|
case SIZE / 8: { \
|
||||||
|
volatile uint##SIZE##_t *buf2 = (uint##SIZE##_t *)buf; \
|
||||||
|
int i; \
|
||||||
|
for (i = 0; i < count; i++) \
|
||||||
|
(void)buf2[i]; \
|
||||||
|
break; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define WRITE(SIZE) \
|
||||||
|
case SIZE / 8: { \
|
||||||
|
volatile uint##SIZE##_t *buf2 = (uint##SIZE##_t *)buf; \
|
||||||
|
int i; \
|
||||||
|
for (i = 0; i < count; i++) \
|
||||||
|
buf2[i] = (uint##SIZE##_t)0xaabbccdd11223344; \
|
||||||
|
break; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define XOR(SIZE) \
|
||||||
|
case SIZE / 8: { \
|
||||||
|
volatile uint##SIZE##_t *buf2 = (uint##SIZE##_t *)buf; \
|
||||||
|
int i; \
|
||||||
|
for (i = 0; i < count; i++) \
|
||||||
|
buf2[i] = ~buf2[i]; \
|
||||||
|
break; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define COPY(SIZE) \
|
||||||
|
case SIZE / 8: { \
|
||||||
|
volatile uint##SIZE##_t *buf2 = (uint##SIZE##_t *)buf; \
|
||||||
|
int i; \
|
||||||
|
for (i = 0; i < count / 2; i++) \
|
||||||
|
buf2[i] = buf2[i + count / 2]; \
|
||||||
|
for (i = count / 2; i < count; i++) \
|
||||||
|
buf2[i] = buf2[i - count / 2]; \
|
||||||
|
break; \
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_read(void *buf, size_t count, int size)
|
||||||
|
{
|
||||||
|
switch (size) {
|
||||||
|
READ(8);
|
||||||
|
READ(16);
|
||||||
|
READ(32);
|
||||||
|
READ(64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_write(void *buf, size_t count, int size)
|
||||||
|
{
|
||||||
|
switch (size) {
|
||||||
|
WRITE(8);
|
||||||
|
WRITE(16);
|
||||||
|
WRITE(32);
|
||||||
|
WRITE(64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_xor(void *buf, size_t count, int size)
|
||||||
|
{
|
||||||
|
switch (size) {
|
||||||
|
XOR(8);
|
||||||
|
XOR(16);
|
||||||
|
XOR(32);
|
||||||
|
XOR(64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_copy(void *buf, size_t count, int size)
|
||||||
|
{
|
||||||
|
switch (size) {
|
||||||
|
COPY(8);
|
||||||
|
COPY(16);
|
||||||
|
COPY(32);
|
||||||
|
COPY(64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t time_sub(struct timespec *since, struct timespec *to)
|
||||||
|
{
|
||||||
|
if (to->tv_sec == since->tv_sec)
|
||||||
|
return to->tv_nsec - since->tv_nsec;
|
||||||
|
|
||||||
|
return (to->tv_sec - since->tv_sec) * 1000000000 + to->tv_nsec - since->tv_nsec;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __attribute__ ((noreturn)) usage(char *argv0, int ret)
|
||||||
|
{
|
||||||
|
fprintf(ret ? stderr : stdout,
|
||||||
|
"usage: %s [-rwxc1234h] [-l length] [-u unalignment]\n"
|
||||||
|
"\n"
|
||||||
|
"Options:\n"
|
||||||
|
" -r read memory (default)\n"
|
||||||
|
" -w write memory\n"
|
||||||
|
" -x xor memory\n"
|
||||||
|
" -c copy memory\n"
|
||||||
|
" -l SIZE use SIZE Mb for the test (default 100)\n"
|
||||||
|
" -u BYTE unalign buffer by BYTE bytes (default 0)\n"
|
||||||
|
" -1 read 1 byte at time\n"
|
||||||
|
" -2 read 2 bytes at time\n"
|
||||||
|
" -4 read 4 bytes at time (default)\n"
|
||||||
|
" -8 read 8 bytes at time\n"
|
||||||
|
" -h this help\n",
|
||||||
|
argv0);
|
||||||
|
exit(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *actions[] = {
|
||||||
|
"read",
|
||||||
|
"write",
|
||||||
|
"xor",
|
||||||
|
"copy",
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct timespec before, after;
|
||||||
|
uint64_t elapsed;
|
||||||
|
int action = ACT_READ;
|
||||||
|
size_t len = 100 * 1024 * 1024;
|
||||||
|
int shift = 0;
|
||||||
|
int size = sizeof(long);
|
||||||
|
char *buf;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
while((c = getopt(argc, argv, "hrwxc1248l:u:")) != -1) {
|
||||||
|
switch (c) {
|
||||||
|
case 'r':
|
||||||
|
action = ACT_READ;
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
action = ACT_WRITE;
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
action = ACT_XOR;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
action = ACT_COPY;
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
len = atol(optarg) * 1024 * 1024;
|
||||||
|
if (len <= 0) {
|
||||||
|
fprintf(stderr, "Invalid size %s\n", optarg);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
shift = atoi(optarg);
|
||||||
|
break;
|
||||||
|
case '1':
|
||||||
|
case '2':
|
||||||
|
case '4':
|
||||||
|
case '8':
|
||||||
|
size = c - '0';
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
default:
|
||||||
|
usage(argv[0], c != 'h');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
shift %= size;
|
||||||
|
|
||||||
|
if (optind != argc)
|
||||||
|
usage(argv[0], 1);
|
||||||
|
|
||||||
|
buf = malloc(len);
|
||||||
|
if (!buf) {
|
||||||
|
perror("malloc");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mlock(buf, len)) {
|
||||||
|
perror("mlock");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &before);
|
||||||
|
switch (action) {
|
||||||
|
case ACT_READ:
|
||||||
|
do_read(buf + shift, (len - shift) / size, size);
|
||||||
|
break;
|
||||||
|
case ACT_WRITE:
|
||||||
|
do_write(buf + shift, (len - shift) / size, size);
|
||||||
|
break;
|
||||||
|
case ACT_XOR:
|
||||||
|
do_xor(buf + shift, (len - shift) / size, size);
|
||||||
|
break;
|
||||||
|
case ACT_COPY:
|
||||||
|
do_copy(buf + shift, (len - shift) / size, size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &after);
|
||||||
|
|
||||||
|
elapsed = time_sub(&before, &after);
|
||||||
|
|
||||||
|
printf( "size: %lu Mb\n"
|
||||||
|
"%s size: %d bit\n"
|
||||||
|
"unalignment: %d byte\n"
|
||||||
|
"elapsed time: %.2f sec\n"
|
||||||
|
"throughput: %.2f Mb/s\n",
|
||||||
|
len / 1024 / 1024,
|
||||||
|
actions[action], size * 8,
|
||||||
|
shift,
|
||||||
|
elapsed / 1E9,
|
||||||
|
(len / 1024 / 1024) / (elapsed / 1E9));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
14
vm.nix
14
vm.nix
@ -47,8 +47,8 @@
|
|||||||
INET y
|
INET y
|
||||||
NETWORK_FILESYSTEMS y
|
NETWORK_FILESYSTEMS y
|
||||||
OVERLAY_FS y
|
OVERLAY_FS y
|
||||||
"9P_FS" y
|
#"9P_FS" y
|
||||||
"9P_FS_POSIX_ACL" y
|
#"9P_FS_POSIX_ACL" y
|
||||||
PCI y
|
PCI y
|
||||||
VIRTIO_PCI y
|
VIRTIO_PCI y
|
||||||
PCI_HOST_GENERIC y
|
PCI_HOST_GENERIC y
|
||||||
@ -63,7 +63,15 @@
|
|||||||
|
|
||||||
nixpkgs.overlays = [
|
nixpkgs.overlays = [
|
||||||
(final: prev: {
|
(final: prev: {
|
||||||
qemu = prev.qemu.override { rutabagaSupport = false; };
|
qemu = prev.qemu.override {
|
||||||
|
pulseSupport = false;
|
||||||
|
pipewireSupport = false;
|
||||||
|
sdlSupport = false;
|
||||||
|
jackSupport = false;
|
||||||
|
gtkSupport = false;
|
||||||
|
vncSupport = false;
|
||||||
|
smartcardSupport = false;
|
||||||
|
};
|
||||||
|
|
||||||
uboot-custom = prev.ubootQemuRiscv64Smode.override {
|
uboot-custom = prev.ubootQemuRiscv64Smode.override {
|
||||||
# Override preboot to set 'bootcmd' directly to the kernel address in RAM
|
# Override preboot to set 'bootcmd' directly to the kernel address in RAM
|
||||||
|
Loading…
x
Reference in New Issue
Block a user