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

Commit

Permalink
Merge branch 'qemu-for-upstream' into riscv-all
Browse files Browse the repository at this point in the history
  • Loading branch information
Michael Clark committed Aug 6, 2018
2 parents 18a398f + d621573 commit 79fe4f4
Show file tree
Hide file tree
Showing 34 changed files with 2,316 additions and 1,612 deletions.
1 change: 1 addition & 0 deletions Makefile.objs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,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
1 change: 1 addition & 0 deletions hw/riscv/Makefile.objs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
obj-y += boot.o
obj-y += riscv_htif.o
obj-y += riscv_hart.o
obj-y += sifive_e.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

0 comments on commit 79fe4f4

Please sign in to comment.