Skip to content
This repository has been archived by the owner on Apr 13, 2019. It is now read-only.

SiFive CLIC (Core Level Interrupt Controller) test-beta1 #157

Open
wants to merge 41 commits into
base: qemu-for-upstream
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
59a2a11
RISC-V: Update address bits to support sv39 and sv48
Mar 5, 2018
67110fb
RISC-V: Improve page table walker spec compliance
Mar 4, 2018
458d08e
RISC-V: Use atomic_cmpxchg to update PLIC bitmaps
Apr 10, 2018
0461550
RISC-V: Simplify riscv_cpu_local_irqs_pending
Apr 19, 2018
dabcc50
RISC-V: Allow setting and clearing multiple irqs
Apr 8, 2018
970b95b
RISC-V: Move non-ops from op_helper to cpu_helper
Apr 10, 2018
e0bc582
RISC-V: Update CSR and interrupt definitions
Mar 5, 2018
0bf5716
RISC-V: Implement modular CSR helper interface
Apr 8, 2018
31aa0b4
RISC-V: Implement atomic mip/sip CSR updates
Apr 10, 2018
5fe21a8
RISC-V: Implement existential predicates for CSRs
Apr 11, 2018
3737960
RISC-V: Split out mstatus_fs from tb_flags
rth7680 Mar 28, 2018
24ece65
RISC-V: Mark mstatus.fs dirty
rth7680 Mar 28, 2018
0a656f3
RISC-V: Implement mstatus.TSR/TW/TVM
Apr 15, 2018
b379f5a
RISC-V: Add public API for the CSR dispatch table
Apr 20, 2018
c2901dd
RISC-V: Add hartid and \n to interrupt logging
Apr 22, 2018
f4399d2
RISC-V: Use riscv prefix consistently on cpu helpers
Apr 23, 2018
ad21000
RISC-V: Replace __builtin_popcount with ctpop8 in PLIC
Apr 29, 2018
8812433
RISC-V: Add missing free for plic_hart_config
Apr 30, 2018
bea8bb0
RISC-V: Allow interrupt controllers to claim interrupts
May 6, 2018
764aa94
RISC-V: Add misa to DisasContext
May 12, 2018
fc5d882
RISC-V: Add misa.MAFD checks to translate
May 9, 2018
2ad9b10
RISC-V: Add misa runtime write support
May 9, 2018
eec015a
RISC-V: Fix CLINT timecmp low 32-bit writes
May 12, 2018
e8ae79c
RISC-V: Fix PLIC pending bitfield reads
May 12, 2018
e8b5944
RISC-V: Enable second UART on sifive_e and sifive_u
May 12, 2018
25571ed
RISC-V: Remove unnecessary disassembler constraints
May 16, 2018
fc4d86d
elf: Add RISC-V PSABI ELF header defines
May 17, 2018
34f9902
RISC-V: linux-user support for RVE ABI
kito-cheng Jun 16, 2017
9d4473b
RISC-V: Don't add NULL bootargs to device-tree
May 22, 2018
6338416
RISC-V: Support separate firmware and kernel payload
May 19, 2018
3e20277
RISC-V: Change local interrupts from edge to level
May 25, 2018
27016af
RISC-V: Add SiFive Test device to E and U series machines
Jun 19, 2018
c7b1e00
RISC-V: Add support for vectored interrupts
Jun 21, 2018
884c701
RISC-V: Convert trap debugging to trace events
Jun 21, 2018
0a13267
RISC-V: Update load reservation comment in do_interrupt
Jun 22, 2018
0b22435
sifive_prci: Read and write PRCI registers
nategraff-sifive Jul 24, 2018
d7e5d78
sifive_uart: Implement interrupt pending register
nategraff-sifive Jul 24, 2018
577f7aa
target/riscv/pmp.c: Fix PMP NAPOT decoding bug
dayeol Jul 17, 2018
cf5f50f
target/riscv/pmp.c: Fix PMP range boundary address bug
dayeol Jul 17, 2018
63801b3
riscv: remove define cpu_init()
May 15, 2018
206d9ac
SiFive CLIC (Core Level Interrupt Controller) test-beta1
Jun 23, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Makefile.objs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ trace-events-subdirs += hw/nvram
trace-events-subdirs += hw/pci
trace-events-subdirs += hw/pci-host
trace-events-subdirs += hw/ppc
trace-events-subdirs += hw/riscv
trace-events-subdirs += hw/rdma
trace-events-subdirs += hw/rdma/vmw
trace-events-subdirs += hw/s390x
Expand All @@ -253,6 +254,7 @@ trace-events-subdirs += target/arm
trace-events-subdirs += target/i386
trace-events-subdirs += target/mips
trace-events-subdirs += target/ppc
trace-events-subdirs += target/riscv
trace-events-subdirs += target/s390x
trace-events-subdirs += target/sparc
trace-events-subdirs += ui
Expand Down
138 changes: 0 additions & 138 deletions disas/riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,33 +87,10 @@ typedef enum {

typedef enum {
rvc_end,
rvc_simm_6,
rvc_imm_6,
rvc_imm_7,
rvc_imm_8,
rvc_imm_9,
rvc_imm_10,
rvc_imm_12,
rvc_imm_18,
rvc_imm_nz,
rvc_imm_x2,
rvc_imm_x4,
rvc_imm_x8,
rvc_imm_x16,
rvc_rd_b3,
rvc_rs1_b3,
rvc_rs2_b3,
rvc_rd_eq_rs1,
rvc_rd_eq_ra,
rvc_rd_eq_sp,
rvc_rd_eq_x0,
rvc_rs1_eq_sp,
rvc_rs1_eq_x0,
rvc_rs2_eq_x0,
rvc_rd_ne_x0_x2,
rvc_rd_ne_x0,
rvc_rs1_ne_x0,
rvc_rs2_ne_x0,
rvc_rs2_eq_rs1,
rvc_rs1_eq_ra,
rvc_imm_eq_zero,
Expand Down Expand Up @@ -2522,111 +2499,16 @@ static bool check_constraints(rv_decode *dec, const rvc_constraint *c)
uint8_t rd = dec->rd, rs1 = dec->rs1, rs2 = dec->rs2;
while (*c != rvc_end) {
switch (*c) {
case rvc_simm_6:
if (!(imm >= -32 && imm < 32)) {
return false;
}
break;
case rvc_imm_6:
if (!(imm <= 63)) {
return false;
}
break;
case rvc_imm_7:
if (!(imm <= 127)) {
return false;
}
break;
case rvc_imm_8:
if (!(imm <= 255)) {
return false;
}
break;
case rvc_imm_9:
if (!(imm <= 511)) {
return false;
}
break;
case rvc_imm_10:
if (!(imm <= 1023)) {
return false;
}
break;
case rvc_imm_12:
if (!(imm <= 4095)) {
return false;
}
break;
case rvc_imm_18:
if (!(imm <= 262143)) {
return false;
}
break;
case rvc_imm_nz:
if (!(imm != 0)) {
return false;
}
break;
case rvc_imm_x2:
if (!((imm & 0b1) == 0)) {
return false;
}
break;
case rvc_imm_x4:
if (!((imm & 0b11) == 0)) {
return false;
}
break;
case rvc_imm_x8:
if (!((imm & 0b111) == 0)) {
return false;
}
break;
case rvc_imm_x16:
if (!((imm & 0b1111) == 0)) {
return false;
}
break;
case rvc_rd_b3:
if (!(rd >= 8 && rd <= 15)) {
return false;
}
break;
case rvc_rs1_b3:
if (!(rs1 >= 8 && rs1 <= 15)) {
return false;
}
break;
case rvc_rs2_b3:
if (!(rs2 >= 8 && rs2 <= 15)) {
return false;
}
break;
case rvc_rd_eq_rs1:
if (!(rd == rs1)) {
return false;
}
break;
case rvc_rd_eq_ra:
if (!(rd == 1)) {
return false;
}
break;
case rvc_rd_eq_sp:
if (!(rd == 2)) {
return false;
}
break;
case rvc_rd_eq_x0:
if (!(rd == 0)) {
return false;
}
break;
case rvc_rs1_eq_sp:
if (!(rs1 == 2)) {
return false;
}
break;
case rvc_rs1_eq_x0:
if (!(rs1 == 0)) {
return false;
Expand All @@ -2637,26 +2519,6 @@ static bool check_constraints(rv_decode *dec, const rvc_constraint *c)
return false;
}
break;
case rvc_rd_ne_x0_x2:
if (!(rd != 0 && rd != 2)) {
return false;
}
break;
case rvc_rd_ne_x0:
if (!(rd != 0)) {
return false;
}
break;
case rvc_rs1_ne_x0:
if (!(rs1 != 0)) {
return false;
}
break;
case rvc_rs2_ne_x0:
if (!(rs2 != 0)) {
return false;
}
break;
case rvc_rs2_eq_rs1:
if (!(rs2 == rs1)) {
return false;
Expand Down
2 changes: 2 additions & 0 deletions hw/riscv/Makefile.objs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
obj-y += boot.o
obj-y += riscv_htif.o
obj-y += riscv_hart.o
obj-y += sifive_e.o
obj-y += sifive_clic.o
obj-y += sifive_clint.o
obj-y += sifive_prci.o
obj-y += sifive_plic.o
Expand Down
172 changes: 172 additions & 0 deletions hw/riscv/boot.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
/*
* QEMU RISCV firmware and kernel loader
*
* Copyright (c) 2017-2018 SiFive, Inc.
*
* Holds the state of a heterogenous array of RISC-V harts
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2 or later, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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 <http://www.gnu.org/licenses/>.
*/

#include "qemu/osdep.h"
#include "qemu/log.h"
#include "qemu/error-report.h"
#include "hw/loader.h"
#include "hw/boards.h"
#include "sysemu/device_tree.h"
#include "elf.h"
#include "hw/riscv/boot.h"

#define RISCV_BOOT_DEBUG 0

#define boot_debug(fs, ...) \
if (RISCV_BOOT_DEBUG) { \
fprintf(stderr, "boot: %s: "fs, __func__, ##__VA_ARGS__); \
}

static uint64_t kernel_offset;

static uint64_t kernel_translate(void *opaque, uint64_t addr)
{
/* mask kernel virtual address and offset by load address */
if (kernel_offset) {
return (addr & 0x7fffffff) + kernel_offset;
} else {
return addr;
}
}

hwaddr riscv_load_firmware(const char *filename)
{
uint64_t firmware_entry, firmware_start, firmware_end;

if (load_elf(filename, NULL, NULL,
&firmware_entry, &firmware_start, &firmware_end,
0, EM_RISCV, 1, 0) < 0) {
error_report("riscv_boot: could not load firmware '%s'", filename);
exit(1);
}

/* align kernel load address to the megapage after the firmware */
#if defined(TARGET_RISCV32)
kernel_offset = (firmware_end + 0x3fffff) & ~0x3fffff;
#else
kernel_offset = (firmware_end + 0x1fffff) & ~0x1fffff;
#endif

boot_debug("entry=0x" TARGET_FMT_plx " start=0x" TARGET_FMT_plx " "
"end=0x" TARGET_FMT_plx " kernel_offset=0x" TARGET_FMT_plx "\n",
firmware_entry, firmware_start, firmware_end, kernel_offset);

return firmware_entry;
}

hwaddr riscv_load_kernel(const char *filename, void *fdt)
{
uint64_t kernel_entry, kernel_start, kernel_end;

if (load_elf(filename, kernel_translate, NULL,
&kernel_entry, &kernel_start, &kernel_end,
0, EM_RISCV, 1, 0) < 0) {
error_report("riscv_boot: could not load kernel '%s'", filename);
exit(1);
}

boot_debug("entry=0x" TARGET_FMT_plx " start=0x" TARGET_FMT_plx " "
"end=0x" TARGET_FMT_plx "\n", kernel_entry, kernel_start,
kernel_end);

/*
* pass kernel load address via device-tree to firmware
*
* BBL reads the kernel address from device-tree
*/
if (fdt) {
qemu_fdt_setprop_cells(fdt, "/chosen", "riscv,kernel-end",
kernel_end >> 32, kernel_end);
qemu_fdt_setprop_cells(fdt, "/chosen", "riscv,kernel-start",
kernel_start >> 32, kernel_start);
}

return kernel_entry;
}

void riscv_load_initrd(const char *filename, uint64_t mem_size,
hwaddr firmware_entry, void *fdt)
{
uint64_t start, size;

/* We want to put the initrd far enough into RAM that when the
* kernel is uncompressed it will not clobber the initrd. However
* on boards without much RAM we must ensure that we still leave
* enough room for a decent sized initrd, and on boards with large
* amounts of RAM we must avoid the initrd being so far up in RAM
* that it is outside lowmem and inaccessible to the kernel.
* So for boards with less than 256MB of RAM we put the initrd
* halfway into RAM, and for boards with 256MB of RAM or more we put
* the initrd at 128MB.
*/
start = firmware_entry + MIN(mem_size / 2, 128 * 1024 * 1024);

size = load_ramdisk(filename, start, mem_size - start);
if (size == -1) {
size = load_image_targphys(filename, start, mem_size - start);
if (size == -1) {
error_report("riscv_boot: could not load ramdisk '%s'", filename);
exit(1);
}
}

boot_debug("start=0x" TARGET_FMT_plx " end=0x" TARGET_FMT_plx "\n",
start, start + size);

/*
* pass initrd load address via device-tree to kernel
*
* linux-kernel reads the initrd address from device-tree
*/
if (fdt) {
qemu_fdt_setprop_cells(fdt, "/chosen", "linux,initrd-end",
(start + size) >> 32, start + size);
qemu_fdt_setprop_cells(fdt, "/chosen", "linux,initrd-start",
start >> 32, start);
}
}

hwaddr riscv_load_firmware_kernel_initrd(MachineState *machine, void *fdt)
{
hwaddr firmware_entry = 0;

/* load firmware e.g. -bios bbl */
if (machine->firmware) {
firmware_entry = riscv_load_firmware(machine->firmware);
}

/* load combined bbl+kernel or separate kernel */
if (machine->kernel_filename) {
if (machine->firmware) {
/* load separate bios and kernel e.g. -bios bbl -kernel vmlinux */
riscv_load_kernel(machine->kernel_filename, fdt);
} else {
/* load traditional combined bbl+kernel e.g. -kernel bbl_vmlimux */
firmware_entry = riscv_load_kernel(machine->kernel_filename, NULL);
}
if (machine->initrd_filename) {
/* load separate initrd */
riscv_load_initrd(machine->initrd_filename, machine->ram_size,
firmware_entry, fdt);
}
}

return firmware_entry;
}
Loading