[submodule "slirp"]
path = slirp
url = https://git.qemu.org/git/libslirp.git
+[submodule "roms/opensbi"]
+ path = roms/opensbi
+ url = https://git.qemu.org/git/opensbi.git
-The following points clarify the QEMU license:
+The QEMU distribution includes both the QEMU emulator and
+various firmware files. These are separate programs that are
+distributed together for our users' convenience, and they have
+separate licenses.
-1) QEMU as a whole is released under the GNU General Public License,
-version 2.
+The following points clarify the license of the QEMU emulator:
-2) Parts of QEMU have specific licenses which are compatible with the
-GNU General Public License, version 2. Hence each source file contains
-its own licensing information. Source files with no licensing information
-are released under the GNU General Public License, version 2 or (at your
-option) any later version.
+1) The QEMU emulator as a whole is released under the GNU General
+Public License, version 2.
+
+2) Parts of the QEMU emulator have specific licenses which are compatible
+with the GNU General Public License, version 2. Hence each source file
+contains its own licensing information. Source files with no licensing
+information are released under the GNU General Public License, version
+2 or (at your option) any later version.
As of July 2013, contributions under version 2 of the GNU General Public
License (and no later version) are only accepted for the following files
u-boot.e500 u-boot-sam460-20100605.bin \
qemu_vga.ndrv \
edk2-licenses.txt \
-hppa-firmware.img
+hppa-firmware.img \
+opensbi-riscv32-virt-fw_jump.bin \
+opensbi-riscv64-sifive_u-fw_jump.bin opensbi-riscv64-virt-fw_jump.bin
+
DESCS=50-edk2-i386-secure.json 50-edk2-x86_64-secure.json \
60-edk2-aarch64.json 60-edk2-arm.json 60-edk2-i386.json 60-edk2-x86_64.json
*/
#include "qemu/osdep.h"
+#include "qemu-common.h"
#include "qemu/units.h"
#include "qemu/error-report.h"
#include "exec/cpu-defs.h"
# define KERNEL_BOOT_ADDRESS 0x80200000
#endif
+void riscv_find_and_load_firmware(MachineState *machine,
+ const char *default_machine_firmware,
+ hwaddr firmware_load_addr)
+{
+ char *firmware_filename;
+
+ if (!machine->firmware) {
+ /*
+ * The user didn't specify -bios.
+ * At the moment we default to loading nothing when this hapens.
+ * In the future this defaul will change to loading the prebuilt
+ * OpenSBI firmware. Let's warn the user and then continue.
+ */
+ warn_report("No -bios option specified. Not loading a firmware.");
+ warn_report("This default will change in QEMU 4.3. Please use the " \
+ "-bios option to aviod breakages when this happens.");
+ warn_report("See QEMU's deprecation documentation for details");
+ return;
+ }
+
+ if (!strcmp(machine->firmware, "default")) {
+ /*
+ * The user has specified "-bios default". That means we are going to
+ * load the OpenSBI binary included in the QEMU source.
+ *
+ * We can't load the binary by default as it will break existing users
+ * as users are already loading their own firmware.
+ *
+ * Let's try to get everyone to specify the -bios option at all times,
+ * so then in the future we can make "-bios default" the default option
+ * if no -bios option is set without breaking anything.
+ */
+ firmware_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS,
+ default_machine_firmware);
+ if (firmware_filename == NULL) {
+ error_report("Unable to load the default RISC-V firmware \"%s\"",
+ default_machine_firmware);
+ exit(1);
+ }
+ } else {
+ firmware_filename = machine->firmware;
+ }
+
+ if (strcmp(firmware_filename, "none")) {
+ /* If not "none" load the firmware */
+ riscv_load_firmware(firmware_filename, firmware_load_addr);
+ }
+
+ if (!strcmp(machine->firmware, "default")) {
+ g_free(firmware_filename);
+ }
+}
+
target_ulong riscv_load_firmware(const char *firmware_filename,
hwaddr firmware_load_addr)
{
#include <libfdt.h>
+#define BIOS_FILENAME "opensbi-riscv64-sifive_u-fw_jump.bin"
+
static const struct MemmapEntry {
hwaddr base;
hwaddr size;
/* create device tree */
create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline);
- if (machine->firmware) {
- riscv_load_firmware(machine->firmware, memmap[SIFIVE_U_DRAM].base);
- }
+ riscv_find_and_load_firmware(machine, BIOS_FILENAME,
+ memmap[SIFIVE_U_DRAM].base);
if (machine->kernel_filename) {
riscv_load_kernel(machine->kernel_filename);
#include <libfdt.h>
+#if defined(TARGET_RISCV32)
+# define BIOS_FILENAME "opensbi-riscv32-virt-fw_jump.bin"
+#else
+# define BIOS_FILENAME "opensbi-riscv64-virt-fw_jump.bin"
+#endif
+
static const struct MemmapEntry {
hwaddr base;
hwaddr size;
memory_region_add_subregion(system_memory, memmap[VIRT_MROM].base,
mask_rom);
- if (machine->firmware) {
- riscv_load_firmware(machine->firmware, memmap[VIRT_DRAM].base);
- }
+ riscv_find_and_load_firmware(machine, BIOS_FILENAME,
+ memmap[VIRT_DRAM].base);
if (machine->kernel_filename) {
uint64_t kernel_entry = riscv_load_kernel(machine->kernel_filename);
/* All direct uses of g2h and h2g need to go away for usermode softmmu. */
#define g2h(x) ((void *)((unsigned long)(abi_ptr)(x) + guest_base))
+#if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS
+#define guest_addr_valid(x) (1)
+#else
#define guest_addr_valid(x) ((x) <= GUEST_ADDR_MAX)
+#endif
#define h2g_valid(x) guest_addr_valid((unsigned long)(x) - guest_base)
static inline int guest_range_valid(unsigned long start, unsigned long len)
#ifndef RISCV_BOOT_H
#define RISCV_BOOT_H
+void riscv_find_and_load_firmware(MachineState *machine,
+ const char *default_machine_firmware,
+ hwaddr firmware_load_addr);
target_ulong riscv_load_firmware(const char *firmware_filename,
hwaddr firmware_load_addr);
target_ulong riscv_load_kernel(const char *kernel_filename);
IOCTL(SIOCGIWNAME, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_char_ifreq)))
IOCTL(SIOCSPGRP, IOC_W, MK_PTR(TYPE_INT)) /* pid_t */
IOCTL(SIOCGPGRP, IOC_R, MK_PTR(TYPE_INT)) /* pid_t */
- IOCTL(SIOCGSTAMP, IOC_R, MK_PTR(MK_STRUCT(STRUCT_timeval)))
- IOCTL(SIOCGSTAMPNS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_timespec)))
+
+ /*
+ * We can't use IOCTL_SPECIAL() because it will set
+ * host_cmd to XXX_OLD and XXX_NEW and these macros
+ * are not defined with kernel prior to 5.2.
+ * We must set host_cmd to the same value as in target_cmd
+ * otherwise the consistency check in syscall_init()
+ * will trigger an error.
+ * host_cmd is ignored by the do_ioctl_XXX() helpers.
+ * FIXME: create a macro to define this kind of entry
+ */
+ { TARGET_SIOCGSTAMP_OLD, TARGET_SIOCGSTAMP_OLD,
+ "SIOCGSTAMP_OLD", IOC_R, do_ioctl_SIOCGSTAMP },
+ { TARGET_SIOCGSTAMPNS_OLD, TARGET_SIOCGSTAMPNS_OLD,
+ "SIOCGSTAMPNS_OLD", IOC_R, do_ioctl_SIOCGSTAMPNS },
+ { TARGET_SIOCGSTAMP_NEW, TARGET_SIOCGSTAMP_NEW,
+ "SIOCGSTAMP_NEW", IOC_R, do_ioctl_SIOCGSTAMP },
+ { TARGET_SIOCGSTAMPNS_NEW, TARGET_SIOCGSTAMPNS_NEW,
+ "SIOCGSTAMPNS_NEW", IOC_R, do_ioctl_SIOCGSTAMPNS },
IOCTL(RNDGETENTCNT, IOC_R, MK_PTR(TYPE_INT))
IOCTL(RNDADDTOENTCNT, IOC_W, MK_PTR(TYPE_INT))
};
struct target_ucontext {
- target_ulong tuc_flags;
- target_ulong tuc_link;
+ abi_ulong tuc_flags;
+ abi_ulong tuc_link;
target_stack_t tuc_stack;
- target_ulong pad0;
struct target_sigcontext tuc_mcontext;
target_sigset_t tuc_sigmask;
};
static inline int access_ok(int type, abi_ulong addr, abi_ulong size)
{
- return page_check_range((target_ulong)addr, size,
+ return guest_addr_valid(addr) &&
+ (size == 0 || guest_addr_valid(addr + size - 1)) &&
+ page_check_range((target_ulong)addr, size,
(type == VERIFY_READ) ? PAGE_READ : (PAGE_READ | PAGE_WRITE)) == 0;
}
#include <sched.h>
#include <sys/timex.h>
#include <sys/socket.h>
+#include <linux/sockios.h>
#include <sys/un.h>
#include <sys/uio.h>
#include <poll.h>
{
struct target_timeval *target_tv;
- if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1))
+ if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) {
return -TARGET_EFAULT;
+ }
__get_user(tv->tv_sec, &target_tv->tv_sec);
__get_user(tv->tv_usec, &target_tv->tv_usec);
{
struct target_timeval *target_tv;
- if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
+ if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) {
+ return -TARGET_EFAULT;
+ }
+
+ __put_user(tv->tv_sec, &target_tv->tv_sec);
+ __put_user(tv->tv_usec, &target_tv->tv_usec);
+
+ unlock_user_struct(target_tv, target_tv_addr, 1);
+
+ return 0;
+}
+
+static inline abi_long copy_to_user_timeval64(abi_ulong target_tv_addr,
+ const struct timeval *tv)
+{
+ struct target__kernel_sock_timeval *target_tv;
+
+ if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) {
return -TARGET_EFAULT;
+ }
__put_user(tv->tv_sec, &target_tv->tv_sec);
__put_user(tv->tv_usec, &target_tv->tv_usec);
return 0;
}
+static inline abi_long target_to_host_timespec(struct timespec *host_ts,
+ abi_ulong target_addr)
+{
+ struct target_timespec *target_ts;
+
+ if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1)) {
+ return -TARGET_EFAULT;
+ }
+ __get_user(host_ts->tv_sec, &target_ts->tv_sec);
+ __get_user(host_ts->tv_nsec, &target_ts->tv_nsec);
+ unlock_user_struct(target_ts, target_addr, 0);
+ return 0;
+}
+
+static inline abi_long host_to_target_timespec(abi_ulong target_addr,
+ struct timespec *host_ts)
+{
+ struct target_timespec *target_ts;
+
+ if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) {
+ return -TARGET_EFAULT;
+ }
+ __put_user(host_ts->tv_sec, &target_ts->tv_sec);
+ __put_user(host_ts->tv_nsec, &target_ts->tv_nsec);
+ unlock_user_struct(target_ts, target_addr, 1);
+ return 0;
+}
+
+static inline abi_long host_to_target_timespec64(abi_ulong target_addr,
+ struct timespec *host_ts)
+{
+ struct target__kernel_timespec *target_ts;
+
+ if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) {
+ return -TARGET_EFAULT;
+ }
+ __put_user(host_ts->tv_sec, &target_ts->tv_sec);
+ __put_user(host_ts->tv_nsec, &target_ts->tv_nsec);
+ unlock_user_struct(target_ts, target_addr, 1);
+ return 0;
+}
+
static inline abi_long copy_from_user_timezone(struct timezone *tz,
abi_ulong target_tz_addr)
{
return get_errno(safe_ioctl(fd, ie->host_cmd, sig));
}
+static abi_long do_ioctl_SIOCGSTAMP(const IOCTLEntry *ie, uint8_t *buf_temp,
+ int fd, int cmd, abi_long arg)
+{
+ struct timeval tv;
+ abi_long ret;
+
+ ret = get_errno(safe_ioctl(fd, SIOCGSTAMP, &tv));
+ if (is_error(ret)) {
+ return ret;
+ }
+
+ if (cmd == (int)TARGET_SIOCGSTAMP_OLD) {
+ if (copy_to_user_timeval(arg, &tv)) {
+ return -TARGET_EFAULT;
+ }
+ } else {
+ if (copy_to_user_timeval64(arg, &tv)) {
+ return -TARGET_EFAULT;
+ }
+ }
+
+ return ret;
+}
+
+static abi_long do_ioctl_SIOCGSTAMPNS(const IOCTLEntry *ie, uint8_t *buf_temp,
+ int fd, int cmd, abi_long arg)
+{
+ struct timespec ts;
+ abi_long ret;
+
+ ret = get_errno(safe_ioctl(fd, SIOCGSTAMPNS, &ts));
+ if (is_error(ret)) {
+ return ret;
+ }
+
+ if (cmd == (int)TARGET_SIOCGSTAMPNS_OLD) {
+ if (host_to_target_timespec(arg, &ts)) {
+ return -TARGET_EFAULT;
+ }
+ } else{
+ if (host_to_target_timespec64(arg, &ts)) {
+ return -TARGET_EFAULT;
+ }
+ }
+
+ return ret;
+}
+
#ifdef TIOCGPTPEER
static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry *ie, uint8_t *buf_temp,
int fd, int cmd, abi_long arg)
}
#endif
-static inline abi_long target_to_host_timespec(struct timespec *host_ts,
- abi_ulong target_addr)
-{
- struct target_timespec *target_ts;
-
- if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
- return -TARGET_EFAULT;
- __get_user(host_ts->tv_sec, &target_ts->tv_sec);
- __get_user(host_ts->tv_nsec, &target_ts->tv_nsec);
- unlock_user_struct(target_ts, target_addr, 0);
- return 0;
-}
-
-static inline abi_long host_to_target_timespec(abi_ulong target_addr,
- struct timespec *host_ts)
-{
- struct target_timespec *target_ts;
-
- if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
- return -TARGET_EFAULT;
- __put_user(host_ts->tv_sec, &target_ts->tv_sec);
- __put_user(host_ts->tv_nsec, &target_ts->tv_nsec);
- unlock_user_struct(target_ts, target_addr, 1);
- return 0;
-}
-
static inline abi_long target_to_host_itimerspec(struct itimerspec *host_itspec,
abi_ulong target_addr)
{
abi_int l_linger; /* How long to linger for */
};
+#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
+struct target_timeval {
+ abi_long tv_sec;
+ abi_int tv_usec;
+};
+#define target__kernel_sock_timeval target_timeval
+#else
struct target_timeval {
abi_long tv_sec;
abi_long tv_usec;
};
+struct target__kernel_sock_timeval {
+ abi_llong tv_sec;
+ abi_llong tv_usec;
+};
+#endif
+
struct target_timespec {
abi_long tv_sec;
abi_long tv_nsec;
};
+struct target__kernel_timespec {
+ abi_llong tv_sec;
+ abi_llong tv_nsec;
+};
+
struct target_timezone {
abi_int tz_minuteswest;
abi_int tz_dsttime;
#define TARGET_SIOCGPGRP 0x8904
#endif
-#define TARGET_SIOCGSTAMP 0x8906 /* Get stamp (timeval) */
-#define TARGET_SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */
+#if defined(TARGET_SH4)
+#define TARGET_SIOCGSTAMP_OLD TARGET_IOR('s', 100, struct target_timeval)
+#define TARGET_SIOCGSTAMPNS_OLD TARGET_IOR('s', 101, struct target_timespec)
+#else
+#define TARGET_SIOCGSTAMP_OLD 0x8906
+#define TARGET_SIOCGSTAMPNS_OLD 0x8907
+#endif
+
+#define TARGET_SIOCGSTAMP_NEW TARGET_IOR(0x89, 0x06, abi_llong[2])
+#define TARGET_SIOCGSTAMPNS_NEW TARGET_IOR(0x89, 0x07, abi_llong[2])
/* Networking ioctls */
#define TARGET_SIOCADDRT 0x890B /* add routing table entry */
STRUCT(sockaddr,
TYPE_SHORT, MK_ARRAY(TYPE_CHAR, 14))
-STRUCT(timeval,
- MK_ARRAY(TYPE_LONG, 2))
-
-STRUCT(timespec,
- MK_ARRAY(TYPE_LONG, 2))
-
STRUCT(rtentry,
TYPE_ULONG, MK_STRUCT(STRUCT_sockaddr), MK_STRUCT(STRUCT_sockaddr), MK_STRUCT(STRUCT_sockaddr),
TYPE_SHORT, TYPE_SHORT, TYPE_ULONG, TYPE_PTRVOID, TYPE_SHORT, TYPE_PTRVOID,
ARM. Licensing information is given in "edk2-licenses.txt". The image files
are described by the JSON documents in the "pc-bios/descriptors" directory,
which conform to the "docs/interop/firmware.json" schema.
+
+- OpenSBI (https://github.com/riscv/opensbi) aims to provide an open-source
+ reference implementation of the RISC-V Supervisor Binary Interface (SBI)
+ specifications for platform-specific firmwares executing in M-mode. For all
+ supported platforms, OpenSBI provides several runtime firmware examples.
+ These example firmwares can be used to replace the legacy riscv-pk bootloader
+ and enable the use of well-known bootloaders such as U-Boot.
+ OpenSBI is distributed under the terms of the BSD 2-clause license
+ ("Simplified BSD License" or "FreeBSD License", SPDX: BSD-2-Clause). OpenSBI
+ source code also contains code reused from other projects desribed here:
+ https://github.com/riscv/opensbi/blob/master/ThirdPartyNotices.md.
the guest RAM configured with @option{-m} and QEMU will fail to start up if
RAM allocation is unsuccessful.
+@subsection RISC-V -bios (since 4.1)
+
+QEMU 4.1 introduced support for the -bios option in QEMU for RISC-V for the
+RISC-V virt machine and sifive_u machine.
+
+QEMU 4.1 has no changes to the default behaviour to avoid breakages. This
+default will change in a future QEMU release, so please prepare now. All users
+of the virt or sifive_u machine must change their command line usage.
+
+QEMU 4.1 has three options, please migrate to one of these three:
+ 1. ``-bios none`` - This is the current default behavior if no -bios option
+ is included. QEMU will not automatically load any firmware. It is up
+ to the user to load all the images they need.
+ 2. ``-bios default`` - In a future QEMU release this will become the default
+ behaviour if no -bios option is specified. This option will load the
+ default OpenSBI firmware automatically. The firmware is included with
+ the QEMU release and no user interaction is required. All a user needs
+ to do is specify the kernel they want to boot with the -kernel option
+ 3. ``-bios <file>`` - Tells QEMU to load the specified file as the firmwrae.
+
@section QEMU Machine Protocol (QMP) commands
@subsection block-dirty-bitmap-add "autoload" parameter (since 2.12.0)
powerpc64_cross_prefix := $(call find-cross-prefix,powerpc64)
powerpc_cross_prefix := $(call find-cross-prefix,powerpc)
x86_64_cross_prefix := $(call find-cross-prefix,x86_64)
+riscv32_cross_prefix := $(call find-cross-prefix,riscv32)
+riscv64_cross_prefix := $(call find-cross-prefix,riscv64)
# tag our seabios builds
SEABIOS_EXTRAVERSION="-prebuilt.qemu.org"
default:
@echo "nothing is build by default"
@echo "available build targets:"
- @echo " bios -- update bios.bin (seabios)"
- @echo " vgabios -- update vgabios binaries (seabios)"
- @echo " sgabios -- update sgabios binaries"
- @echo " pxerom -- update nic roms (bios only)"
- @echo " efirom -- update nic roms (bios+efi)"
- @echo " slof -- update slof.bin"
- @echo " skiboot -- update skiboot.lid"
- @echo " u-boot.e500 -- update u-boot.e500"
- @echo " u-boot.sam460 -- update u-boot.sam460"
- @echo " efi -- update UEFI (edk2) platform firmware"
- @echo " clean -- delete the files generated by the previous" \
- "build targets"
+ @echo " bios -- update bios.bin (seabios)"
+ @echo " vgabios -- update vgabios binaries (seabios)"
+ @echo " sgabios -- update sgabios binaries"
+ @echo " pxerom -- update nic roms (bios only)"
+ @echo " efirom -- update nic roms (bios+efi)"
+ @echo " slof -- update slof.bin"
+ @echo " skiboot -- update skiboot.lid"
+ @echo " u-boot.e500 -- update u-boot.e500"
+ @echo " u-boot.sam460 -- update u-boot.sam460"
+ @echo " efi -- update UEFI (edk2) platform firmware"
+ @echo " opensbi32-virt -- update OpenSBI for 32-bit virt machine"
+ @echo " opensbi64-virt -- update OpenSBI for 64-bit virt machine"
+ @echo " opensbi64-sifive_u -- update OpenSBI for 64-bit sifive_u machine"
+ @echo " clean -- delete the files generated by the previous" \
+ "build targets"
bios: build-seabios-config-seabios-128k build-seabios-config-seabios-256k
cp seabios/builds/seabios-128k/bios.bin ../pc-bios/bios.bin
efi: edk2-basetools
$(MAKE) -f Makefile.edk2
+opensbi32-virt:
+ $(MAKE) -C opensbi \
+ CROSS_COMPILE=$(riscv32_cross_prefix) \
+ PLATFORM="qemu/virt"
+ cp opensbi/build/platform/qemu/virt/firmware/fw_jump.bin ../pc-bios/opensbi-riscv32-virt-fw_jump.bin
+
+opensbi64-virt:
+ $(MAKE) -C opensbi \
+ CROSS_COMPILE=$(riscv64_cross_prefix) \
+ PLATFORM="qemu/virt"
+ cp opensbi/build/platform/qemu/virt/firmware/fw_jump.bin ../pc-bios/opensbi-riscv64-virt-fw_jump.bin
+
+opensbi64-sifive_u:
+ $(MAKE) -C opensbi \
+ CROSS_COMPILE=$(riscv64_cross_prefix) \
+ PLATFORM="qemu/sifive_u"
+ cp opensbi/build/platform/qemu/virt/firmware/fw_jump.bin ../pc-bios/opensbi-riscv64-sifive_u-fw_jump.bin
+
clean:
rm -rf seabios/.config seabios/out seabios/builds
$(MAKE) -C sgabios clean
$(MAKE) -C u-boot-sam460ex distclean
$(MAKE) -C skiboot clean
$(MAKE) -f Makefile.edk2 clean
+ $(MAKE) -C opensbi clean
--- /dev/null
+Subproject commit ce228ee0919deb9957192d723eecc8aaae2697c6