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*
|
||||
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.
|
||||
|
||||
## 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:
|
||||
|
||||
```
|
||||
$ 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:
|
||||
Then upload the files to the target machine (fpgalogin1 by default):
|
||||
|
||||
```
|
||||
$ 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 = [
|
||||
#"${modulesPath}/profiles/base.nix"
|
||||
#"${modulesPath}/profiles/minimal.nix"
|
||||
"${modulesPath}/profiles/minimal.nix"
|
||||
];
|
||||
|
||||
nixpkgs.crossSystem = {
|
||||
system = "riscv64-linux";
|
||||
nixpkgs = {
|
||||
crossSystem = {
|
||||
system = "riscv64-linux";
|
||||
};
|
||||
|
||||
overlays = [
|
||||
self.inputs.bscpkgs.bscOverlay
|
||||
(import ./overlay.nix)
|
||||
];
|
||||
|
||||
config.allowUnsupportedSystem = true;
|
||||
};
|
||||
|
||||
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; [
|
||||
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
46
flake.lock
@ -1,24 +1,56 @@
|
||||
{
|
||||
"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": {
|
||||
"locked": {
|
||||
"lastModified": 1706092046,
|
||||
"narHash": "sha256-Cbethl95Cu+WVIWfaAnRRBZiz5PmXxQvg4vXNqIZQUg=",
|
||||
"owner": "rodarima",
|
||||
"lastModified": 1700390070,
|
||||
"narHash": "sha256-de9KYi8rSJpqvBfNwscWdalIJXPo8NjdIZcEJum1mH0=",
|
||||
"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",
|
||||
"rev": "57e7c8fa4fdc414a936ce83afd0c70fb0a3a31d5",
|
||||
"rev": "9f4128e00b0ae8ec65918efeba59db998750ead6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "rodarima",
|
||||
"ref": "fix-pkgs-static-gcc-march",
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"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
|
||||
system = "x86_64-linux";
|
||||
overlay = import ./overlay.nix;
|
||||
pkgs = import nixpkgs { inherit system; };
|
||||
nixosSystem = import (nixpkgs + "/nixos/lib/eval-config.nix");
|
||||
mkRoots = pkgs: list: pkgs.writeText "gcroots.json"
|
||||
(builtins.toJSON (map (x: { drv = x; attrs = x.drvAttrs; }) list));
|
||||
in {
|
||||
overlay = import ./overlay.nix;
|
||||
#overlay = import ./overlay.nix;
|
||||
nixosConfigurations = {
|
||||
# The qemu configuration defines a system that runs in the RISC-V
|
||||
# architecture, but is build from an x86 host machine.
|
||||
qemu = nixpkgs.lib.nixosSystem {
|
||||
qemu = nixosSystem {
|
||||
specialArgs = { inherit self; };
|
||||
system = "${system}";
|
||||
modules = [
|
||||
./configuration.nix
|
||||
@ -20,7 +23,8 @@
|
||||
};
|
||||
|
||||
# Same, but disable compressed instructions
|
||||
qemu-nc = nixpkgs.lib.nixosSystem {
|
||||
qemu-nc = nixosSystem {
|
||||
specialArgs = { inherit self; };
|
||||
system = "${system}";
|
||||
modules = [
|
||||
./configuration.nix
|
||||
@ -30,7 +34,8 @@
|
||||
};
|
||||
|
||||
# FPGA Lagarto Hun CPU
|
||||
lagarto-hun = nixpkgs.lib.nixosSystem {
|
||||
lagarto-hun = nixosSystem {
|
||||
specialArgs = { inherit self; };
|
||||
system = "${system}";
|
||||
modules = [
|
||||
./configuration.nix
|
||||
@ -38,35 +43,105 @@
|
||||
./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
|
||||
# machine.
|
||||
devShells.x86_64-linux.default =
|
||||
devShells.x86_64-linux.qemu-lagarto-hun =
|
||||
let
|
||||
nixosconf = self.nixosConfigurations.qemu-nc;
|
||||
syspkgs = nixosconf.pkgs;
|
||||
toplevel = nixosconf.config.system.build.toplevel;
|
||||
in pkgs.mkShell {
|
||||
in syspkgs.mkShell {
|
||||
pname = "qemu-shell";
|
||||
buildInputs = with pkgs; [ qemu e2fsprogs ];
|
||||
nativeBuildInputs = with syspkgs; [ qemu e2fsprogs ];
|
||||
# Here we tell the run script where to find the system
|
||||
NIXOS_SYSTEM_TOPLEVEL = toplevel;
|
||||
OPENSBI = syspkgs.opensbi-uboot;
|
||||
};
|
||||
|
||||
devShells.x86_64-linux.lagarto-hun =
|
||||
let
|
||||
nixosconf = self.nixosConfigurations.lagarto-hun;
|
||||
syspkgs = nixosconf.pkgs;
|
||||
build = nixosconf.config.system.build;
|
||||
in pkgs.mkShell {
|
||||
in syspkgs.mkShell {
|
||||
pname = "lagarto-hun-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;
|
||||
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
|
||||
|
||||
set -x
|
||||
#set -x
|
||||
set -e
|
||||
|
||||
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
|
||||
|
||||
INSTALL_PATH=/home/tools
|
||||
LOAD_BITSTREAM=$INSTALL_PATH/scripts
|
||||
HOSTNAME=$(hostname)
|
||||
function setup_cucu()
|
||||
{
|
||||
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
|
||||
echo "error: DMA_IP_DRIVERS $DMA_IP_DRIVERS directory does not exist" >&2
|
||||
return
|
||||
fi
|
||||
# Select the first FPGA in the node
|
||||
local line=$(grep fpgan /etc/motd | sed -n 2p | tr -d ' ')
|
||||
export FPGACTL_PCIDEV=$(echo "$line" | awk -F'|' '{print $5}')
|
||||
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
|
||||
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
|
||||
# Delta between where we load in the dma device and RAM
|
||||
local delta_addr=-0x60000000
|
||||
|
||||
# See https://gitlab.bsc.es/hwdesign/fpga/integration-lab/fpga-tools/-/blob/6a63bcea6d1d59df3c7d62311aa4935efd54d3a3/boot_riscv/boot_sa.sh#L36-40
|
||||
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() # {{{
|
||||
{
|
||||
pcidir="/sys/bus/pci/devices/0000:08:00.0"
|
||||
|
||||
if [ ! -d "$pcidir/qdma" ]; then
|
||||
if [ ! -d "$pcidir" ]; then
|
||||
echo "missing pci directory: $pcidir" >&2
|
||||
exit 1
|
||||
fi
|
||||
@ -44,48 +42,71 @@ function create_qdma_queue() # {{{
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -c "/dev/qdma08000-MM-1" ]; then
|
||||
echo 2 | sudo dd of="$pcidir/qdma/qmax"
|
||||
|
||||
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"
|
||||
if [ ! -r "$pcidir/qdma/qmax" ]; then
|
||||
echo "cannot read qmax file: $pcidir/qdma/qmax" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -c "/dev/qdma08000-MM-0" ]; then
|
||||
dma-ctl qdma08000 q add mode mm idx 0 dir bi
|
||||
dma-ctl qdma08000 q start idx 0 dir bi
|
||||
sudo chmod go+rw "/dev/qdma08000-MM-0"
|
||||
# There should be two queues
|
||||
local qmax=$(cat "$pcidir/qdma/qmax")
|
||||
if [ "$qmax" != 2 ]; then
|
||||
if [ -w "$pcidir/qdma/qmax" ]; then
|
||||
echo 2 | dd of="$pcidir/qdma/qmax"
|
||||
else
|
||||
echo 2 | sudo dd of="$pcidir/qdma/qmax"
|
||||
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
|
||||
} # }}}
|
||||
function do_system_reset() # {{{
|
||||
function do_cpu_reset() # {{{
|
||||
{
|
||||
# UartBootEn (bit2) + system reset (bit0)
|
||||
dma-ctl qdma08000 reg write bar 2 0x0 0x0 > /dev/null
|
||||
sleep 0.2
|
||||
# Release system reset, we must wait until the memory is filled with 0s
|
||||
dma-ctl qdma08000 reg write bar 2 0x0 0x1 > /dev/null
|
||||
#sleep 5
|
||||
if [ "$model" == "hun" ]; then
|
||||
# UartBootEn (bit2) + system reset (bit0)
|
||||
dma-ctl "${qdmadev}" reg write bar 2 0x0 0x0
|
||||
sleep 0.2
|
||||
dma-ctl "${qdmadev}" reg write bar 2 0x0 0x1
|
||||
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
|
||||
dma-ctl qdma08000 reg write bar 2 0x0 0x3 > /dev/null
|
||||
if [ "$model" == "hun" ]; then
|
||||
# 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() # {{{
|
||||
{
|
||||
ifile="$1"
|
||||
address="$2"
|
||||
|
||||
ofile="/dev/qdma08000-MM-1"
|
||||
bs=$((8*1024*1024)) # 8 MiB
|
||||
ofile="/dev/${qdmadev}-MM-1"
|
||||
#bs=$((8*1024*1024)) # 8 MiB
|
||||
bs=$((1*1024*1024)) # 1 MiB
|
||||
|
||||
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
|
||||
let skip=$skip+1
|
||||
done
|
||||
#dma-to-device -d "$ofile" -s "$total_size" -a "$address" -f "$ifile"
|
||||
|
||||
} # }}}
|
||||
function load_file_in_memory() # {{{
|
||||
@ -110,23 +132,24 @@ function load_file_in_memory() # {{{
|
||||
address=$(($address_hex))
|
||||
|
||||
total_size=$(stat --format "%s" "$file")
|
||||
md5sum=$(md5sum "$file" | cut -d' ' -f1)
|
||||
|
||||
# Previous tests...
|
||||
#strace -f dma-to-device -d /dev/qdma08000-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 fpgakit/fpgadd -i "$file" -a "$address" -d /dev/qdma08000-MM-1 -c 1024 -s 1024
|
||||
#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/${qdmadev}-MM-1 status=progress conv=sync
|
||||
#strace -f fpgakit/fpgadd -i "$file" -a "$address" -d /dev/${qdmadev}-MM-1 -c 1024 -s 1024
|
||||
#ID=08 ./load_image.sh "$file" "$address"
|
||||
|
||||
# Now dd seems to work fine, but I will leave this as fallback:
|
||||
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() # {{{
|
||||
{
|
||||
do_system_reset
|
||||
do_cpu_reset
|
||||
|
||||
./load_image.sh ${OSBI} $((0x80000000)) &&
|
||||
|
||||
@ -135,7 +158,7 @@ function do_boot_only() # {{{
|
||||
sleep 2 &&
|
||||
|
||||
# #Release Ariane's reset
|
||||
dma-ctl qdma08000 reg write bar 2 0x0 0x3 &&
|
||||
dma-ctl "${qdmadev}" reg write bar 2 0x0 0x3 &&
|
||||
|
||||
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 &&
|
||||
|
||||
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
|
||||
fi &&
|
||||
|
||||
@ -155,7 +178,7 @@ function do_boot_only() # {{{
|
||||
} # }}}
|
||||
function do_reload_fs() # {{{
|
||||
{
|
||||
do_system_reset
|
||||
do_cpu_reset
|
||||
|
||||
#~xavim/LAGARTO_LINUX-4.1/./load_image.sh \
|
||||
# /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
|
||||
|
||||
do_system_release
|
||||
do_cpu_release
|
||||
create_qdma_queue
|
||||
|
||||
# uncomment to enable eth-over-pcie
|
||||
@ -180,23 +203,25 @@ function do_reload_fs() # {{{
|
||||
} # }}}
|
||||
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 "$fpgajtag" ]; then
|
||||
echo "error: cannot find JTAG serial" >&2
|
||||
exit 1
|
||||
if [ -z "$bitstream" ]; then
|
||||
>&2 echo "bitstream file required"
|
||||
usage
|
||||
fi
|
||||
|
||||
script=$(mktemp vivado-XXXXXXXXXX.tcl)
|
||||
cat > "$script" <<EOF
|
||||
open_hw_manager
|
||||
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
|
||||
set dev [lindex [get_hw_devices] 0]
|
||||
current_hw_device \$dev
|
||||
set_property PROGRAM.FILE ${bitfile} \$dev
|
||||
set_property PROGRAM.FILE ${bitstream} \$dev
|
||||
program_hw_devices \$dev
|
||||
exit
|
||||
EOF
|
||||
@ -213,7 +238,7 @@ function unload_modules() # {{{
|
||||
# Unload modules
|
||||
for mod in $drvlist; do
|
||||
if is_module_loaded "$mod"; then
|
||||
sudo rmmod $mod
|
||||
sudo rmmod $mod
|
||||
fi
|
||||
done
|
||||
|
||||
@ -223,14 +248,22 @@ function remove_pci_devices() # {{{
|
||||
for slot in $(lspci -mm -d 10ee: | awk '{printf "0000:%s\n",$1}'); do
|
||||
devdir="/sys/bus/pci/devices/$slot"
|
||||
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
|
||||
done
|
||||
|
||||
} # }}}
|
||||
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() # {{{
|
||||
{
|
||||
@ -245,21 +278,91 @@ function load_qdma_modules() # {{{
|
||||
sudo insmod "$drv" "hw_buffers=$hw_buffers"
|
||||
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() # {{{
|
||||
{
|
||||
bitstream="$1"
|
||||
|
||||
unload_modules "xocl xclmgmt qdma_pf xdma" # qdma_vf not removable
|
||||
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
|
||||
preload_hook
|
||||
upload_bitstream_file
|
||||
postload_hook
|
||||
} # }}}
|
||||
|
||||
bitstream=
|
||||
@ -267,34 +370,51 @@ bootloader=
|
||||
kernel=
|
||||
initrd=
|
||||
rootfs=
|
||||
bootrom=
|
||||
resetcpu=
|
||||
verbose=
|
||||
pcidev=
|
||||
model=ox
|
||||
# Internal
|
||||
slot=
|
||||
pcidir=
|
||||
qdmadev=
|
||||
|
||||
bootloader_addr=0x80000000
|
||||
kernel_addr=0x84000000
|
||||
initrd_addr=0x8c300000
|
||||
rootfs_addr=0x180000000
|
||||
bootloader_addr="${FPGACTL_BOOTLOADER_ADDR:-0x80000000}"
|
||||
kernel_addr="${FPGACTL_KERNEL_ADDR:-0x84000000}"
|
||||
initrd_addr="${FPGACTL_INITRD_ADDR:-0x8c300000}"
|
||||
rootfs_addr="${FPGACTL_ROOTFS_ADDR:-0x140000000}"
|
||||
bootrom_addr="${FPGACTL_BOOTROM_ADDR:-0x60000100}"
|
||||
|
||||
hostname="${hostname:-$(hostname)}"
|
||||
echo "hostname=$hostname"
|
||||
|
||||
function usage()
|
||||
{
|
||||
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 "First writes the bitstream if given. Then loads the rest of files" >&2
|
||||
echo "into memory and restarts the CPU." >&2
|
||||
echo "" >&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 " -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 " -k kernel Load the kernel file in $kernel_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 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 "" >&2
|
||||
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
|
||||
v) verbose=1 ;;
|
||||
w) bitstream="${OPTARG}" ;;
|
||||
@ -302,21 +422,32 @@ while getopts "hvw:b:k:i:r:" opt; do
|
||||
k) kernel="${OPTARG}"; resetcpu=1 ;;
|
||||
i) initrd="${OPTARG}"; resetcpu=1 ;;
|
||||
r) rootfs="${OPTARG}"; resetcpu=1 ;;
|
||||
R) bootrom="${OPTARG}"; resetcpu=1 ;;
|
||||
p) pcidev="${OPTARG}" ;;
|
||||
j) jtagserial="${OPTARG}" ;;
|
||||
m) model="${OPTARG}" ;;
|
||||
h) usage ;;
|
||||
*) usage ;;
|
||||
esac
|
||||
done
|
||||
|
||||
jtagserial="${jtagserial:-$FPGACTL_SERIAL}"
|
||||
pcidev="${pcidev:-$FPGACTL_PCIDEV}"
|
||||
|
||||
test "$verbose" && set -x
|
||||
|
||||
check_environment
|
||||
select_pcidev
|
||||
|
||||
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 "$kernel" && load_file_in_memory "$kernel" $kernel_addr
|
||||
test "$initrd" && load_file_in_memory "$initrd" $initrd_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:
|
||||
|
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 -x
|
||||
|
||||
dst=femu:nixos/
|
||||
#dst=femu:nixos
|
||||
dst=fpgalogin1:nixos
|
||||
|
||||
rsync -a fpga/fpgactl "$dst"
|
||||
rsync -a fpga/boot.sh "$dst"
|
||||
rsync -a fpga/env.sh "$dst"
|
||||
rsync "$OPENSBI/share/opensbi/lp64/fpga/openpiton/firmware/fw_payload.bin" "$dst/opensbi.bin"
|
||||
if [ "$1" != "" ]; then
|
||||
dst="$1"
|
||||
fi
|
||||
|
||||
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 "$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"
|
||||
|
||||
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";
|
||||
};
|
||||
|
||||
# Disable hvc0 as it is racing for the same console
|
||||
systemd.services."serial-getty@hvc0" = {
|
||||
enable = lib.mkForce false;
|
||||
wantedBy = lib.mkForce [ ];
|
||||
};
|
||||
|
||||
sdImage = {
|
||||
# The image will be loaded as-is in memory, so no compression
|
||||
compressImage = false;
|
||||
@ -96,13 +102,13 @@
|
||||
initrd = "${config.system.build.initialRamdisk}/initrd";
|
||||
in prev.runCommand "uboot.txt" {} ''
|
||||
cat > $out <<EOF
|
||||
# Create pmem
|
||||
fdt mknode / pmem@0x180000000
|
||||
fdt set /pmem@0x180000000 compatible "pmem-region"
|
||||
fdt set /pmem@0x180000000 reg <0x1 0x80000000 0x0 0x80000000>
|
||||
# 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
|
||||
fdt set /memory@80000000 reg <0x00000000 0x80000000 0x00000001 0x00000000>
|
||||
# Reduce memory to 3 GiB [0x80000000, 0x140000000)
|
||||
fdt set /memory@80000000 reg <0x0 0x80000000 0x0 0xc0000000>
|
||||
|
||||
# Set kernel options
|
||||
setenv bootargs "root=/dev/ram0 loglevel=7 debug rw earlycon=sbi boot.trace console=hvc0 init=${init}"
|
||||
@ -120,6 +126,7 @@
|
||||
"PLATFORM=fpga/openpiton"
|
||||
"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
|
||||
|
||||
{
|
||||
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
|
||||
NETWORK_FILESYSTEMS y
|
||||
OVERLAY_FS y
|
||||
"9P_FS" y
|
||||
"9P_FS_POSIX_ACL" y
|
||||
#"9P_FS" y
|
||||
#"9P_FS_POSIX_ACL" y
|
||||
PCI y
|
||||
VIRTIO_PCI y
|
||||
PCI_HOST_GENERIC y
|
||||
@ -63,7 +63,15 @@
|
||||
|
||||
nixpkgs.overlays = [
|
||||
(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 {
|
||||
# Override preboot to set 'bootcmd' directly to the kernel address in RAM
|
||||
|
Loading…
Reference in New Issue
Block a user