NINJA='/usr/local/bin/ninja'
PACKAGING_COMMAND='pkg'
PIP3='/usr/local/bin/pip-3.8'
-PKGS='alsa-lib bash bison bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage cmocka ctags curl cyrus-sasl dbus diffutils dtc flex fusefs-libs3 gettext git glib gmake gnutls gsed gtk3 json-c libepoxy libffi libgcrypt libjpeg-turbo libnfs libslirp libspice-server libssh libtasn1 llvm lzo2 meson ncurses nettle ninja opencv pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy sndio socat spice-protocol tesseract usbredir virglrenderer vte3 zstd'
+PKGS='alsa-lib bash bison bzip2 ca_root_nss capstone4 ccache cmocka ctags curl cyrus-sasl dbus diffutils dtc flex fusefs-libs3 gettext git glib gmake gnutls gsed gtk3 json-c libepoxy libffi libgcrypt libjpeg-turbo libnfs libslirp libspice-server libssh libtasn1 llvm lzo2 meson mtools ncurses nettle ninja opencv pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy sndio socat spice-protocol tesseract usbredir virglrenderer vte3 xorriso zstd'
PYPI_PKGS=''
PYTHON='/usr/local/bin/python3'
NINJA='/opt/homebrew/bin/ninja'
PACKAGING_COMMAND='brew'
PIP3='/opt/homebrew/bin/pip3'
-PKGS='bash bc bison bzip2 capstone ccache cmocka ctags curl dbus diffutils dtc flex gcovr gettext git glib gnu-sed gnutls gtk+3 jemalloc jpeg-turbo json-c libepoxy libffi libgcrypt libiscsi libnfs libpng libslirp libssh libtasn1 libusb llvm lzo make meson ncurses nettle ninja pixman pkg-config python3 rpm2cpio sdl2 sdl2_image snappy socat sparse spice-protocol tesseract usbredir vde vte3 zlib zstd'
+PKGS='bash bc bison bzip2 capstone ccache cmocka ctags curl dbus diffutils dtc flex gcovr gettext git glib gnu-sed gnutls gtk+3 jemalloc jpeg-turbo json-c libepoxy libffi libgcrypt libiscsi libnfs libpng libslirp libssh libtasn1 libusb llvm lzo make meson mtools ncurses nettle ninja pixman pkg-config python3 rpm2cpio sdl2 sdl2_image snappy socat sparse spice-protocol tesseract usbredir vde vte3 xorriso zlib zstd'
PYPI_PKGS='PyYAML numpy pillow sphinx sphinx-rtd-theme'
PYTHON='/opt/homebrew/bin/python3'
#endif
}
+const char *target_name(void)
+{
+ return TARGET_NAME;
+}
+
void page_size_init(void)
{
/* NOTE: we can always suppose that qemu_host_page_size >=
The HAXM project has been retired (see https://github.com/intel/haxm#status).
Use "whpx" (on Windows) or "hvf" (on macOS) instead.
+``-async-teardown`` (since 8.1)
+'''''''''''''''''''''''''''''''
+
+Use ``-run-with async-teardown=on`` instead.
+
``-singlestep`` (since 8.1)
'''''''''''''''''''''''''''
- Yes
- A configurable 32 bit soft core now owned by Cadence
-A number of features are are only available when running under
+A number of features are only available when running under
emulation including :ref:`Record/Replay<replay>` and :ref:`TCG Plugins`.
.. _Semihosting:
contains the ``mappings.yml`` update. Then add the prerequisite and
run ``make lcitool-refresh``.
+ * Please also trigger gitlab container generation pipelines on your change
+ for as many OS distros as practical to make sure that there are no
+ obvious breakages when adding the new pre-requisite. Please see
+ `CI <https://www.qemu.org/docs/master/devel/ci.html>`__ documentation
+ page on how to trigger gitlab CI pipelines on your change.
+
For enterprise distros that default to old, end-of-life versions of the
Python runtime, QEMU uses a separate set of mappings that work with more
recent versions. These can be found in ``tests/lcitool/mappings.yml``.
#include "sysemu/runstate.h"
#include "sysemu/sysemu.h"
-static void cpustate_to_cpuinfo_s390(CpuInfoS390 *info, const CPUState *cpu)
-{
-#ifdef TARGET_S390X
- S390CPU *s390_cpu = S390_CPU(cpu);
- CPUS390XState *env = &s390_cpu->env;
-
- info->cpu_state = env->cpu_state;
-#else
- abort();
-#endif
-}
-
/*
* fast means: we NEVER interrupt vCPU threads to retrieve
* information from KVM.
MachineState *ms = MACHINE(qdev_get_machine());
MachineClass *mc = MACHINE_GET_CLASS(ms);
CpuInfoFastList *head = NULL, **tail = &head;
- SysEmuTarget target = qapi_enum_parse(&SysEmuTarget_lookup, TARGET_NAME,
+ SysEmuTarget target = qapi_enum_parse(&SysEmuTarget_lookup, target_name(),
-1, &error_abort);
CPUState *cpu;
}
value->target = target;
- if (target == SYS_EMU_TARGET_S390X) {
- cpustate_to_cpuinfo_s390(&value->u.s390x, cpu);
+ if (cpu->cc->query_cpu_fast) {
+ cpu->cc->query_cpu_fast(cpu, value);
}
QAPI_LIST_APPEND(tail, value);
{
TargetInfo *info = g_malloc0(sizeof(*info));
- info->arch = qapi_enum_parse(&SysEmuTarget_lookup, TARGET_NAME, -1,
+ info->arch = qapi_enum_parse(&SysEmuTarget_lookup, target_name(), -1,
&error_abort);
return info;
'gpio.c',
'loader.c',
'machine-hmp-cmds.c',
+ 'machine-qmp-cmds.c',
'machine.c',
'nmi.c',
'null-machine.c',
'vm-change-state-handler.c',
'clock-vmstate.c',
))
-
-specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: files(
- 'machine-qmp-cmds.c',
-))
softmmu_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_eth.c'))
softmmu_ss.add(when: 'CONFIG_COLDFIRE', if_true: files('mcf_fec.c'))
specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_llan.c'))
-specific_ss.add(when: 'CONFIG_XILINX_ETHLITE', if_true: files('xilinx_ethlite.c'))
+softmmu_ss.add(when: 'CONFIG_XILINX_ETHLITE', if_true: files('xilinx_ethlite.c'))
softmmu_ss.add(when: 'CONFIG_VIRTIO_NET', if_true: files('net_rx_pkt.c'))
specific_ss.add(when: 'CONFIG_VIRTIO_NET', if_true: files('virtio-net.c'))
#include "qemu/osdep.h"
#include "qemu/module.h"
#include "qom/object.h"
-#include "cpu.h" /* FIXME should not use tswap* */
+#include "exec/tswap.h"
#include "hw/sysbus.h"
#include "hw/irq.h"
#include "hw/qdev-properties.h"
}
}
-static PCIBridgeWindows *pci_bridge_region_init(PCIBridge *br)
+static void pci_bridge_region_init(PCIBridge *br)
{
PCIDevice *pd = PCI_DEVICE(br);
PCIBus *parent = pci_get_bus(pd);
- PCIBridgeWindows *w = g_new(PCIBridgeWindows, 1);
+ PCIBridgeWindows *w = &br->windows;
uint16_t cmd = pci_get_word(pd->config + PCI_COMMAND);
pci_bridge_init_alias(br, &w->alias_pref_mem,
cmd & PCI_COMMAND_IO);
pci_bridge_init_vga_aliases(br, parent, w->alias_vga);
-
- return w;
}
static void pci_bridge_region_del(PCIBridge *br, PCIBridgeWindows *w)
object_unparent(OBJECT(&w->alias_vga[QEMU_PCI_VGA_IO_LO]));
object_unparent(OBJECT(&w->alias_vga[QEMU_PCI_VGA_IO_HI]));
object_unparent(OBJECT(&w->alias_vga[QEMU_PCI_VGA_MEM]));
- g_free(w);
}
void pci_bridge_update_mappings(PCIBridge *br)
{
- PCIBridgeWindows *w = br->windows;
+ PCIBridgeWindows *w = &br->windows;
/* Make updates atomic to: handle the case of one VCPU updating the bridge
* while another accesses an unaffected region. */
memory_region_transaction_begin();
- pci_bridge_region_del(br, br->windows);
+ pci_bridge_region_del(br, w);
pci_bridge_region_cleanup(br, w);
- br->windows = pci_bridge_region_init(br);
+ pci_bridge_region_init(br);
memory_region_transaction_commit();
}
sec_bus->address_space_io = &br->address_space_io;
memory_region_init(&br->address_space_io, OBJECT(br), "pci_bridge_io",
4 * GiB);
- br->windows = pci_bridge_region_init(br);
+ pci_bridge_region_init(br);
QLIST_INIT(&sec_bus->child);
QLIST_INSERT_HEAD(&parent->child, sec_bus, sibling);
}
PCIBridge *s = PCI_BRIDGE(pci_dev);
assert(QLIST_EMPTY(&s->sec_bus.child));
QLIST_REMOVE(&s->sec_bus, sibling);
- pci_bridge_region_del(s, s->windows);
- pci_bridge_region_cleanup(s, s->windows);
+ pci_bridge_region_del(s, &s->windows);
+ pci_bridge_region_cleanup(s, &s->windows);
/* object_unparent() is called automatically during device deletion */
}
#include <linux/kvm.h>
+#include "qemu/units.h"
#include "qapi/error.h"
#include "qemu/error-report.h"
#include "sysemu/kvm.h"
return NULL;
}
-bool s390_pv_vm_try_disable_async(void)
+bool s390_pv_vm_try_disable_async(S390CcwMachineState *ms)
{
/*
* t is only needed to create the thread; once qemu_thread_create
*/
QemuThread t;
- if (!kvm_check_extension(kvm_state, KVM_CAP_S390_PROTECTED_ASYNC_DISABLE)) {
+ /*
+ * If the feature is not present or if the VM is not larger than 2 GiB,
+ * KVM_PV_ASYNC_CLEANUP_PREPARE fill fail; no point in attempting it.
+ */
+ if ((MACHINE(ms)->maxram_size <= 2 * GiB) ||
+ !kvm_check_extension(kvm_state, KVM_CAP_S390_PROTECTED_ASYNC_DISABLE)) {
return false;
}
if (s390_pv_cmd(KVM_PV_ASYNC_CLEANUP_PREPARE, NULL) != 0) {
static void s390_machine_unprotect(S390CcwMachineState *ms)
{
- if (!s390_pv_vm_try_disable_async()) {
+ if (!s390_pv_vm_try_disable_async(ms)) {
s390_pv_vm_disable();
}
ms->pv = false;
* @has_work: Callback for checking if there is work to do.
* @memory_rw_debug: Callback for GDB memory access.
* @dump_state: Callback for dumping state.
+ * @query_cpu_fast:
+ * Fill in target specific information for the "query-cpus-fast"
+ * QAPI call.
* @get_arch_id: Callback for getting architecture-dependent CPU ID.
* @set_pc: Callback for setting the Program Counter register. This
* should have the semantics used by the target architecture when
int (*memory_rw_debug)(CPUState *cpu, vaddr addr,
uint8_t *buf, int len, bool is_write);
void (*dump_state)(CPUState *cpu, FILE *, int flags);
+ void (*query_cpu_fast)(CPUState *cpu, CpuInfoFast *value);
int64_t (*get_arch_id)(CPUState *cpu);
void (*set_pc)(CPUState *cpu, vaddr value);
vaddr (*get_pc)(CPUState *cpu);
*/
bool target_words_bigendian(void);
+const char *target_name(void);
+
void page_size_init(void);
#ifdef NEED_CPU_H
MemoryRegion address_space_mem;
MemoryRegion address_space_io;
- PCIBridgeWindows *windows;
+ PCIBridgeWindows windows;
pci_map_irq_fn map_irq;
const char *bus_name;
#include "qapi/error.h"
#include "sysemu/kvm.h"
+#include "hw/s390x/s390-virtio-ccw.h"
#ifdef CONFIG_KVM
#include "cpu.h"
-#include "hw/s390x/s390-virtio-ccw.h"
static inline bool s390_is_pv(void)
{
int s390_pv_query_info(void);
int s390_pv_vm_enable(void);
void s390_pv_vm_disable(void);
-bool s390_pv_vm_try_disable_async(void);
+bool s390_pv_vm_try_disable_async(S390CcwMachineState *ms);
int s390_pv_set_sec_parms(uint64_t origin, uint64_t length);
int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak);
void s390_pv_prep_reset(void);
static inline int s390_pv_query_info(void) { return 0; }
static inline int s390_pv_vm_enable(void) { return 0; }
static inline void s390_pv_vm_disable(void) {}
-static inline bool s390_pv_vm_try_disable_async(void) { return false; }
+static inline bool s390_pv_vm_try_disable_async(S390CcwMachineState *ms) { return false; }
static inline int s390_pv_set_sec_parms(uint64_t origin, uint64_t length) { return 0; }
static inline int s390_pv_unpack(uint64_t addr, uint64_t size, uint64_t tweak) { return 0; }
static inline void s390_pv_prep_reset(void) {}
typedef struct ConfidentialGuestSupport ConfidentialGuestSupport;
typedef struct CPUAddressSpace CPUAddressSpace;
typedef struct CPUArchState CPUArchState;
+typedef struct CpuInfoFast CpuInfoFast;
typedef struct CPUJumpCache CPUJumpCache;
typedef struct CPUState CPUState;
typedef struct CPUTLBEntryFull CPUTLBEntryFull;
#ifndef QEMU_KVM_H
#define QEMU_KVM_H
-#include "qemu/queue.h"
-#include "hw/core/cpu.h"
-#include "exec/memattrs.h"
#include "qemu/accel.h"
#include "qom/object.h"
#include "qemu/osdep.h"
#include "qemu/error-report.h"
#include <zlib.h>
+#include "hw/core/cpu.h"
#include "qapi/error.h"
#include "exec/ramblock.h"
#include "exec/target_page.h"
#include "qemu/log.h"
#include "sysemu/runstate.h"
#include "qemu/cutils.h"
+#include "qemu/config-file.h"
+#include "qemu/option.h"
#ifdef CONFIG_LINUX
#include <sys/prctl.h>
daemonize = 1;
break;
#if defined(CONFIG_LINUX)
+ /* deprecated */
case QEMU_OPTION_asyncteardown:
init_async_teardown();
break;
+ case QEMU_OPTION_run_with: {
+ QemuOpts *opts = qemu_opts_parse_noisily(qemu_find_opts("run-with"),
+ optarg, false);
+ if (!opts) {
+ exit(1);
+ }
+ if (qemu_opt_get_bool(opts, "async-teardown", false)) {
+ init_async_teardown();
+ }
+ break;
+ }
#endif
default:
return -1;
DEF("async-teardown", 0, QEMU_OPTION_asyncteardown,
"-async-teardown enable asynchronous teardown\n",
QEMU_ARCH_ALL)
-#endif
SRST
``-async-teardown``
- Enable asynchronous teardown. A new process called "cleanup/<QEMU_PID>"
- will be created at startup sharing the address space with the main qemu
- process, using clone. It will wait for the main qemu process to
- terminate completely, and then exit.
- This allows qemu to terminate very quickly even if the guest was
- huge, leaving the teardown of the address space to the cleanup
- process. Since the cleanup process shares the same cgroups as the
- main qemu process, accounting is performed correctly. This only
- works if the cleanup process is not forcefully killed with SIGKILL
- before the main qemu process has terminated completely.
+ This option is deprecated and should no longer be used. The new option
+ ``-run-with async-teardown=on`` is a replacement.
ERST
+DEF("run-with", HAS_ARG, QEMU_OPTION_run_with,
+ "-run-with async-teardown[=on|off]\n"
+ " misc QEMU process lifecycle options\n"
+ " async-teardown=on enables asynchronous teardown\n",
+ QEMU_ARCH_ALL)
+SRST
+``-run-with``
+ Set QEMU process lifecycle options.
+
+ ``async-teardown=on`` enables asynchronous teardown. A new process called
+ "cleanup/<QEMU_PID>" will be created at startup sharing the address
+ space with the main QEMU process, using clone. It will wait for the
+ main QEMU process to terminate completely, and then exit. This allows
+ QEMU to terminate very quickly even if the guest was huge, leaving the
+ teardown of the address space to the cleanup process. Since the cleanup
+ process shares the same cgroups as the main QEMU process, accounting is
+ performed correctly. This only works if the cleanup process is not
+ forcefully killed with SIGKILL before the main QEMU process has
+ terminated completely.
+ERST
+#endif
DEF("msg", HAS_ARG, QEMU_OPTION_msg,
"-msg [timestamp[=on|off]][,guest-name=[on|off]]\n"
os.symlink(source, bundle_dest)
except BaseException as e:
if not isinstance(e, OSError) or e.errno != errno.EEXIST:
+ if os.name == 'nt':
+ print('Please enable Developer Mode to support soft link '
+ 'without Administrator permission')
print(f'error making symbolic link {dest}', file=sys.stderr)
raise e
return s390_cpu_has_int(cpu);
}
+static void s390_query_cpu_fast(CPUState *cpu, CpuInfoFast *value)
+{
+ S390CPU *s390_cpu = S390_CPU(cpu);
+
+ value->u.s390x.cpu_state = s390_cpu->env.cpu_state;
+}
+
/* S390CPUClass::reset() */
static void s390_cpu_reset(CPUState *s, cpu_reset_type type)
{
cc->class_by_name = s390_cpu_class_by_name,
cc->has_work = s390_cpu_has_work;
cc->dump_state = s390_cpu_dump_state;
+ cc->query_cpu_fast = s390_query_cpu_fast;
cc->set_pc = s390_cpu_set_pc;
cc->get_pc = s390_cpu_get_pc;
cc->gdb_read_register = s390_cpu_gdb_read_register;
F(0xed04, LDEB, RXE, Z, 0, m2_32u, new, f1, ldeb, 0, IF_BFP)
F(0xed05, LXDB, RXE, Z, 0, m2_64, new_x, x1, lxdb, 0, IF_BFP)
F(0xed06, LXEB, RXE, Z, 0, m2_32u, new_x, x1, lxeb, 0, IF_BFP)
- F(0xb324, LDER, RXE, Z, 0, e2, new, f1, lde, 0, IF_AFP1)
+ F(0xb324, LDER, RRE, Z, 0, e2, new, f1, lde, 0, IF_AFP1)
F(0xed24, LDE, RXE, Z, 0, m2_32u, new, f1, lde, 0, IF_AFP1)
/* LOAD ROUNDED */
F(0xb344, LEDBR, RRF_e, Z, 0, f2, new, e1, ledb, 0, IF_BFP)
}
}
+/*
+ * Disassemble the target of a branch. The results are returned in a form
+ * suitable for passing into help_branch():
+ *
+ * - bool IS_IMM reflects whether the target is fixed or computed. Non-EXECUTEd
+ * branches, whose DisasContext *S contains the relative immediate field RI,
+ * are considered fixed. All the other branches are considered computed.
+ * - int IMM is the value of RI.
+ * - TCGv_i64 CDEST is the address of the computed target.
+ */
+#define disas_jdest(s, ri, is_imm, imm, cdest) do { \
+ if (have_field(s, ri)) { \
+ if (unlikely(s->ex_value)) { \
+ cdest = tcg_temp_new_i64(); \
+ tcg_gen_ld_i64(cdest, cpu_env, offsetof(CPUS390XState, ex_target));\
+ tcg_gen_addi_i64(cdest, cdest, (int64_t)get_field(s, ri) * 2); \
+ is_imm = false; \
+ } else { \
+ is_imm = true; \
+ } \
+ } else { \
+ is_imm = false; \
+ } \
+ imm = is_imm ? get_field(s, ri) : 0; \
+} while (false)
+
static DisasJumpType op_basi(DisasContext *s, DisasOps *o)
{
+ DisasCompare c;
+ bool is_imm;
+ int imm;
+
pc_to_link_info(o->out, s, s->pc_tmp);
- return help_goto_direct(s, s->base.pc_next + (int64_t)get_field(s, i2) * 2);
+
+ disas_jdest(s, i2, is_imm, imm, o->in2);
+ disas_jcc(s, &c, 0xf);
+ return help_branch(s, &c, is_imm, imm, o->in2);
}
static DisasJumpType op_bc(DisasContext *s, DisasOps *o)
{
int m1 = get_field(s, m1);
- bool is_imm = have_field(s, i2);
- int imm = is_imm ? get_field(s, i2) : 0;
DisasCompare c;
+ bool is_imm;
+ int imm;
/* BCR with R2 = 0 causes no branching */
if (have_field(s, r2) && get_field(s, r2) == 0) {
return DISAS_NEXT;
}
+ disas_jdest(s, i2, is_imm, imm, o->in2);
disas_jcc(s, &c, m1);
return help_branch(s, &c, is_imm, imm, o->in2);
}
static DisasJumpType op_bct32(DisasContext *s, DisasOps *o)
{
int r1 = get_field(s, r1);
- bool is_imm = have_field(s, i2);
- int imm = is_imm ? get_field(s, i2) : 0;
DisasCompare c;
+ bool is_imm;
TCGv_i64 t;
+ int imm;
c.cond = TCG_COND_NE;
c.is_64 = false;
c.u.s32.b = tcg_constant_i32(0);
tcg_gen_extrl_i64_i32(c.u.s32.a, t);
+ disas_jdest(s, i2, is_imm, imm, o->in2);
return help_branch(s, &c, is_imm, imm, o->in2);
}
static DisasJumpType op_bct64(DisasContext *s, DisasOps *o)
{
int r1 = get_field(s, r1);
- bool is_imm = have_field(s, i2);
- int imm = is_imm ? get_field(s, i2) : 0;
DisasCompare c;
+ bool is_imm;
+ int imm;
c.cond = TCG_COND_NE;
c.is_64 = true;
c.u.s64.a = regs[r1];
c.u.s64.b = tcg_constant_i64(0);
+ disas_jdest(s, i2, is_imm, imm, o->in2);
return help_branch(s, &c, is_imm, imm, o->in2);
}
{
int r1 = get_field(s, r1);
int r3 = get_field(s, r3);
- bool is_imm = have_field(s, i2);
- int imm = is_imm ? get_field(s, i2) : 0;
DisasCompare c;
+ bool is_imm;
TCGv_i64 t;
+ int imm;
c.cond = (s->insn->data ? TCG_COND_LE : TCG_COND_GT);
c.is_64 = false;
tcg_gen_extrl_i64_i32(c.u.s32.b, regs[r3 | 1]);
store_reg32_i64(r1, t);
+ disas_jdest(s, i2, is_imm, imm, o->in2);
return help_branch(s, &c, is_imm, imm, o->in2);
}
{
int r1 = get_field(s, r1);
int r3 = get_field(s, r3);
- bool is_imm = have_field(s, i2);
- int imm = is_imm ? get_field(s, i2) : 0;
DisasCompare c;
+ bool is_imm;
+ int imm;
c.cond = (s->insn->data ? TCG_COND_LE : TCG_COND_GT);
c.is_64 = true;
tcg_gen_add_i64(regs[r1], regs[r1], regs[r3]);
c.u.s64.a = regs[r1];
+ disas_jdest(s, i2, is_imm, imm, o->in2);
return help_branch(s, &c, is_imm, imm, o->in2);
}
c.u.s64.a = o->in1;
c.u.s64.b = o->in2;
- is_imm = have_field(s, i4);
- if (is_imm) {
- imm = get_field(s, i4);
- } else {
+ o->out = NULL;
+ disas_jdest(s, i4, is_imm, imm, o->out);
+ if (!is_imm && !o->out) {
imm = 0;
o->out = get_address(s, 0, get_field(s, b4),
get_field(s, d4));
static TCGv gen_ri2(DisasContext *s)
{
- int64_t delta = (int64_t)get_field(s, i2) * 2;
- TCGv ri2;
+ TCGv ri2 = NULL;
+ bool is_imm;
+ int imm;
- if (unlikely(s->ex_value)) {
- ri2 = tcg_temp_new_i64();
- tcg_gen_ld_i64(ri2, cpu_env, offsetof(CPUS390XState, ex_target));
- tcg_gen_addi_i64(ri2, ri2, delta);
- } else {
- ri2 = tcg_constant_i64(s->base.pc_next + delta);
+ disas_jdest(s, i2, is_imm, imm, ri2);
+ if (is_imm) {
+ ri2 = tcg_constant_i64(s->base.pc_next + imm * 2);
}
return ri2;
KERNEL_COMMAND_LINE = "printk.time=0 console=ttyS0 rdinit=/bin/bash"
KERNEL_URL = (
- "https://archives.fedoraproject.org/pub/fedora"
+ "https://archives.fedoraproject.org/pub/archive/fedora"
"/linux/releases/33/Everything/x86_64/os/images"
"/pxeboot/vmlinuz"
)
KERNEL_HASH = '1433cfe3f2ffaa44de4ecfb57ec25dc2399cdecf'
INITRD_URL = (
- "https://archives.fedoraproject.org/pub/fedora"
+ "https://archives.fedoraproject.org/pub/archive/fedora"
"/linux/releases/33/Everything/x86_64/os/images"
"/pxeboot/initrd.img"
)
ca-certificates \
capstone-dev \
ccache \
- cdrkit \
ceph-dev \
clang \
cmocka-dev \
make \
mesa-dev \
meson \
+ mtools \
multipath-tools \
musl-dev \
ncurses-dev \
which \
xen-dev \
xfsprogs-dev \
+ xorriso \
zlib-dev \
zlib-static \
zstd \
fuse3-devel \
gcc \
gcc-c++ \
- genisoimage \
gettext \
git \
glib2-devel \
lzo-devel \
make \
mesa-libgbm-devel \
+ mtools \
ncurses-devel \
nettle-devel \
ninja-build \
vte291-devel \
which \
xfsprogs-devel \
+ xorriso \
zlib-devel \
zlib-static \
zstd && \
findutils \
flex \
gcovr \
- genisoimage \
gettext \
git \
hostname \
locales \
make \
meson \
+ mtools \
ncat \
ninja-build \
openssh-client \
tar \
tesseract-ocr \
tesseract-ocr-eng \
+ xorriso \
zstd && \
eatmydata apt-get autoremove -y && \
eatmydata apt-get autoclean -y && \
g++ \
gcc \
gcovr \
- genisoimage \
gettext \
git \
hostname \
locales \
make \
meson \
+ mtools \
multipath-tools \
ncat \
nettle-dev \
tesseract-ocr \
tesseract-ocr-eng \
xfslibs-dev \
+ xorriso \
zlib1g-dev \
zstd && \
eatmydata apt-get autoremove -y && \
findutils \
flex \
gcovr \
- genisoimage \
gettext \
git \
hostname \
locales \
make \
meson \
+ mtools \
ncat \
ninja-build \
openssh-client \
tar \
tesseract-ocr \
tesseract-ocr-eng \
+ xorriso \
zstd && \
eatmydata apt-get autoremove -y && \
eatmydata apt-get autoclean -y && \
findutils \
flex \
gcovr \
- genisoimage \
gettext \
git \
hostname \
locales \
make \
meson \
+ mtools \
ncat \
ninja-build \
openssh-client \
tar \
tesseract-ocr \
tesseract-ocr-eng \
+ xorriso \
zstd && \
eatmydata apt-get autoremove -y && \
eatmydata apt-get autoclean -y && \
findutils \
flex \
gcovr \
- genisoimage \
gettext \
git \
hostname \
locales \
make \
meson \
+ mtools \
ncat \
ninja-build \
openssh-client \
tar \
tesseract-ocr \
tesseract-ocr-eng \
+ xorriso \
zstd && \
eatmydata apt-get autoremove -y && \
eatmydata apt-get autoclean -y && \
findutils \
flex \
gcovr \
- genisoimage \
gettext \
git \
hostname \
locales \
make \
meson \
+ mtools \
ncat \
ninja-build \
openssh-client \
tar \
tesseract-ocr \
tesseract-ocr-eng \
+ xorriso \
zstd && \
eatmydata apt-get autoremove -y && \
eatmydata apt-get autoclean -y && \
findutils \
flex \
gcovr \
- genisoimage \
gettext \
git \
hostname \
locales \
make \
meson \
+ mtools \
ncat \
ninja-build \
openssh-client \
tar \
tesseract-ocr \
tesseract-ocr-eng \
+ xorriso \
zstd && \
eatmydata apt-get autoremove -y && \
eatmydata apt-get autoclean -y && \
findutils \
flex \
gcovr \
- genisoimage \
gettext \
git \
hostname \
locales \
make \
meson \
+ mtools \
ncat \
ninja-build \
openssh-client \
tar \
tesseract-ocr \
tesseract-ocr-eng \
+ xorriso \
zstd && \
eatmydata apt-get autoremove -y && \
eatmydata apt-get autoclean -y && \
findutils \
flex \
gcovr \
- genisoimage \
gettext \
git \
hostname \
locales \
make \
meson \
+ mtools \
ncat \
ninja-build \
openssh-client \
tar \
tesseract-ocr \
tesseract-ocr-eng \
+ xorriso \
zstd && \
eatmydata apt-get autoremove -y && \
eatmydata apt-get autoclean -y && \
findutils \
flex \
gcovr \
- genisoimage \
git \
glib2-devel \
glibc-langpack-en \
llvm \
make \
meson \
+ mtools \
ninja-build \
nmap-ncat \
openssh-clients \
tesseract-langpack-eng \
util-linux \
which \
+ xorriso \
zstd && \
nosync dnf autoremove -y && \
nosync dnf clean all -y
findutils \
flex \
gcovr \
- genisoimage \
git \
glib2-devel \
glibc-langpack-en \
llvm \
make \
meson \
+ mtools \
ninja-build \
nmap-ncat \
openssh-clients \
tesseract-langpack-eng \
util-linux \
which \
+ xorriso \
zstd && \
nosync dnf autoremove -y && \
nosync dnf clean all -y
gcc \
gcc-c++ \
gcovr \
- genisoimage \
gettext \
git \
glib2-devel \
make \
mesa-libgbm-devel \
meson \
+ mtools \
ncurses-devel \
nettle-devel \
ninja-build \
which \
xen-devel \
xfsprogs-devel \
+ xorriso \
zlib-devel \
zlib-static \
zstd && \
lttng-ust-devel \
lzo-devel \
make \
- mkisofs \
+ mtools \
ncat \
ncurses-devel \
ninja \
which \
xen-devel \
xfsprogs-devel \
+ xorriso \
zlib-devel \
zlib-devel-static \
zstd && \
g++ \
gcc \
gcovr \
- genisoimage \
gettext \
git \
hostname \
llvm \
locales \
make \
+ mtools \
multipath-tools \
ncat \
nettle-dev \
tesseract-ocr \
tesseract-ocr-eng \
xfslibs-dev \
+ xorriso \
zlib1g-dev \
zstd && \
eatmydata apt-get autoremove -y && \
g++ \
gcc \
gcovr \
- genisoimage \
gettext \
git \
hostname \
locales \
make \
meson \
+ mtools \
multipath-tools \
ncat \
nettle-dev \
tesseract-ocr \
tesseract-ocr-eng \
xfslibs-dev \
+ xorriso \
zlib1g-dev \
zstd && \
eatmydata apt-get autoremove -y && \
-Subproject commit 85487e140415b2ac54b01a9a6b600fd7c21edc2f
+Subproject commit c8971e90ac169ee2b539c747f74d96c876debdf9
- gcc
- gcovr
- gettext
- - genisoimage
- glib2
- glib2-native
- glib2-static
- llvm
- lttng-ust
- lzo
+ - mtools
- netcat
- nettle
- ninja
- which
- xen
- xfsprogs
+ - xorriso
- zstdtools
- zlib
- zlib-static
#include "hw/pci/pci_ids.h"
#include "hw/pci/pci_regs.h"
-/* TODO actually test the results and get rid of this */
-#define qmp_discard_response(s, ...) qobject_unref(qtest_qmp(s, __VA_ARGS__))
-
/* Test images sizes in MB */
#define TEST_IMAGE_SIZE_MB_LARGE (200 * 1024)
#define TEST_IMAGE_SIZE_MB_SMALL 64
rsp = qtest_qmp_receive(ahci->parent->qts);
qobject_unref(rsp);
- qmp_discard_response(ahci->parent->qts,
- "{'execute': 'blockdev-remove-medium', "
- "'arguments': {'id': 'cd0'}}");
+ qtest_qmp_assert_success(ahci->parent->qts,
+ "{'execute': 'blockdev-remove-medium', "
+ "'arguments': {'id': 'cd0'}}");
/* Test the tray without a medium */
ahci_atapi_load(ahci, port);
atapi_wait_tray(ahci, true);
/* Re-insert media */
- qmp_discard_response(ahci->parent->qts,
- "{'execute': 'blockdev-add', "
- "'arguments': {'node-name': 'node0', "
- "'driver': 'raw', "
- "'file': { 'driver': 'file', "
- "'filename': %s }}}", iso);
- qmp_discard_response(ahci->parent->qts,
- "{'execute': 'blockdev-insert-medium',"
- "'arguments': { 'id': 'cd0', "
- "'node-name': 'node0' }}");
+ qtest_qmp_assert_success(
+ ahci->parent->qts,
+ "{'execute': 'blockdev-add', "
+ "'arguments': {'node-name': 'node0', "
+ "'driver': 'raw', "
+ "'file': { 'driver': 'file', "
+ "'filename': %s }}}", iso);
+ qtest_qmp_assert_success(
+ ahci->parent->qts,
+ "{'execute': 'blockdev-insert-medium',"
+ "'arguments': { 'id': 'cd0', "
+ "'node-name': 'node0' }}");
/* Again, the event shows up first */
qtest_qmp_send(ahci->parent->qts, "{'execute': 'blockdev-close-tray', "
#include "qapi/qmp/qdict.h"
#include "standard-headers/linux/qemu_fw_cfg.h"
-/* TODO actually test the results and get rid of this */
-#define qmp_discard_response(qs, ...) qobject_unref(qtest_qmp(qs, __VA_ARGS__))
-
typedef struct {
const char *args;
uint64_t expected_boot;
machine ?: "", test_args);
actual = read_boot_order(qts);
g_assert_cmphex(actual, ==, expected_boot);
- qmp_discard_response(qts, "{ 'execute': 'system_reset' }");
+ qtest_qmp_assert_success(qts, "{ 'execute': 'system_reset' }");
/*
* system_reset only requests reset. We get a RESET event after
* the actual reset completes. Need to wait for that.
static char isoimage[] = "cdrom-boot-iso-XXXXXX";
-static int exec_genisoimg(const char **args)
+static int exec_xorrisofs(const char **args)
{
gchar *out_err = NULL;
gint exit_status = -1;
char *codefile = NULL;
int ifh, ret = -1;
const char *args[] = {
- "genisoimage", "-quiet", "-l", "-no-emul-boot",
+ "xorrisofs", "-quiet", "-l", "-no-emul-boot",
"-b", NULL, "-o", isoimage, srcdir, NULL
};
}
args[5] = strchr(codefile, '/') + 1;
- ret = exec_genisoimg(args);
+ ret = exec_xorrisofs(args);
if (ret) {
- fprintf(stderr, "genisoimage failed: %i\n", ret);
+ fprintf(stderr, "xorrisofs failed: %i\n", ret);
}
unlink(codefile);
{
int ret;
const char *arch = qtest_get_arch();
- const char *genisocheck[] = { "genisoimage", "-version", NULL };
+ const char *xorrisocheck[] = { "xorrisofs", "-version", NULL };
g_test_init(&argc, &argv, NULL);
- if (exec_genisoimg(genisocheck)) {
- /* genisoimage not available - so can't run tests */
+ if (exec_xorrisofs(xorrisocheck)) {
+ /* xorrisofs not available - so can't run tests */
return g_test_run();
}
#include "libqtest-single.h"
#include "qapi/qmp/qdict.h"
-/* TODO actually test the results and get rid of this */
-#define qmp_discard_response(...) qobject_unref(qmp(__VA_ARGS__))
-
#define DRIVE_FLOPPY_BLANK \
"-drive if=floppy,file=null-co://,file.read-zeroes=on,format=raw,size=1440k"
/* Insert media in drive. DSKCHK should not be reset until a step pulse
* is sent. */
- qmp_discard_response("{'execute':'blockdev-change-medium', 'arguments':{"
- " 'id':'floppy0', 'filename': %s, 'format': 'raw' }}",
- test_image);
+ qtest_qmp_assert_success(global_qtest,
+ "{'execute':'blockdev-change-medium', 'arguments':{"
+ " 'id':'floppy0', 'filename': %s, 'format': 'raw' }}",
+ test_image);
dir = inb(FLOPPY_BASE + reg_dir);
assert_bit_set(dir, DSKCHG);
/* Eject the floppy and check that DSKCHG is set. Reading it out doesn't
* reset the bit. */
- qmp_discard_response("{'execute':'eject', 'arguments':{"
- " 'id':'floppy0' }}");
+ qtest_qmp_assert_success(global_qtest,
+ "{'execute':'eject', 'arguments':{"
+ " 'id':'floppy0' }}");
dir = inb(FLOPPY_BASE + reg_dir);
assert_bit_set(dir, DSKCHG);
#include "hw/pci/pci_ids.h"
#include "hw/pci/pci_regs.h"
-/* TODO actually test the results and get rid of this */
-#define qmp_discard_response(q, ...) qobject_unref(qtest_qmp(q, __VA_ARGS__))
-
#define TEST_IMAGE_SIZE 64 * 1024 * 1024
#define IDE_PCI_DEV 1
qtest_qmp_eventwait(qts, "STOP");
/* Complete the command */
- qmp_discard_response(qts, "{'execute':'cont' }");
+ qtest_qmp_assert_success(qts, "{'execute':'cont' }");
/* Check registers */
data = qpci_io_readb(dev, ide_bar, reg_device);
#include "linux/kvm.h"
#endif
-/* TODO actually test the results and get rid of this */
-#define qtest_qmp_discard_response(...) qobject_unref(qtest_qmp(__VA_ARGS__))
-
unsigned start_address;
unsigned end_address;
static bool uffd_feature_thread_id;
usleep(1000 * 10);
} while (dest_byte_a == dest_byte_b);
- qtest_qmp_discard_response(to, "{ 'execute' : 'stop'}");
+ qtest_qmp_assert_success(to, "{ 'execute' : 'stop'}");
/* With it stopped, check nothing changes */
qtest_memread(to, start_address, &dest_byte_c, 1);
qobject_unref(resp);
}
-static void test_stream_inet_reconnect(void)
+static void test_stream_unix_reconnect(void)
{
QTestState *qts0, *qts1;
- int port;
SocketAddress *addr;
+ gchar *path;
- port = inet_get_free_port(false);
+ path = g_strconcat(tmpdir, "/stream_unix_reconnect", NULL);
qts0 = qtest_initf("-nodefaults -M none "
- "-netdev stream,id=st0,server=true,addr.type=inet,"
- "addr.ipv4=on,addr.ipv6=off,"
- "addr.host=127.0.0.1,addr.port=%d", port);
+ "-netdev stream,id=st0,server=true,addr.type=unix,"
+ "addr.path=%s", path);
EXPECT_STATE(qts0, "st0: index=0,type=stream,\r\n", 0);
qts1 = qtest_initf("-nodefaults -M none "
- "-netdev stream,server=false,id=st0,addr.type=inet,"
- "addr.ipv4=on,addr.ipv6=off,reconnect=1,"
- "addr.host=127.0.0.1,addr.port=%d", port);
+ "-netdev stream,server=false,id=st0,addr.type=unix,"
+ "addr.path=%s,reconnect=1", path);
wait_stream_connected(qts0, "st0", &addr);
- g_assert_cmpint(addr->type, ==, SOCKET_ADDRESS_TYPE_INET);
- g_assert_cmpstr(addr->u.inet.host, ==, "127.0.0.1");
+ g_assert_cmpint(addr->type, ==, SOCKET_ADDRESS_TYPE_UNIX);
+ g_assert_cmpstr(addr->u.q_unix.path, ==, path);
qapi_free_SocketAddress(addr);
/* kill server */
/* restart server */
qts0 = qtest_initf("-nodefaults -M none "
- "-netdev stream,id=st0,server=true,addr.type=inet,"
- "addr.ipv4=on,addr.ipv6=off,"
- "addr.host=127.0.0.1,addr.port=%d", port);
+ "-netdev stream,id=st0,server=true,addr.type=unix,"
+ "addr.path=%s", path);
/* wait connection events*/
wait_stream_connected(qts0, "st0", &addr);
- g_assert_cmpint(addr->type, ==, SOCKET_ADDRESS_TYPE_INET);
- g_assert_cmpstr(addr->u.inet.host, ==, "127.0.0.1");
+ g_assert_cmpint(addr->type, ==, SOCKET_ADDRESS_TYPE_UNIX);
+ g_assert_cmpstr(addr->u.q_unix.path, ==, path);
qapi_free_SocketAddress(addr);
wait_stream_connected(qts1, "st0", &addr);
- g_assert_cmpint(addr->type, ==, SOCKET_ADDRESS_TYPE_INET);
- g_assert_cmpstr(addr->u.inet.host, ==, "127.0.0.1");
- g_assert_cmpint(atoi(addr->u.inet.port), ==, port);
+ g_assert_cmpint(addr->type, ==, SOCKET_ADDRESS_TYPE_UNIX);
+ g_assert_cmpstr(addr->u.q_unix.path, ==, path);
qapi_free_SocketAddress(addr);
qtest_quit(qts1);
qtest_quit(qts0);
+ g_free(path);
}
static void test_stream_inet_ipv6(void)
#ifndef _WIN32
qtest_add_func("/netdev/dgram/mcast", test_dgram_mcast);
#endif
- qtest_add_func("/netdev/stream/inet/reconnect",
- test_stream_inet_reconnect);
}
if (has_ipv6) {
qtest_add_func("/netdev/stream/inet/ipv6", test_stream_inet_ipv6);
qtest_add_func("/netdev/dgram/unix", test_dgram_unix);
#endif
qtest_add_func("/netdev/stream/unix", test_stream_unix);
+ qtest_add_func("/netdev/stream/unix/reconnect",
+ test_stream_unix_reconnect);
#ifdef CONFIG_LINUX
qtest_add_func("/netdev/stream/unix/abstract",
test_stream_unix_abstract);
#include "qemu/error-report.h"
#include "qemu/main-loop.h"
-/* TODO actually test the results and get rid of this */
-#define qmp_discard_response(qs, ...) qobject_unref(qtest_qmp(qs, __VA_ARGS__))
-
static void test_mirror(void)
{
int send_sock[2], recv_sock[2];
};
/* send a qmp command to guarantee that 'connected' is setting to true. */
- qmp_discard_response(qts, "{ 'execute' : 'query-status'}");
+ qtest_qmp_assert_success(qts, "{ 'execute' : 'query-status'}");
ret = iov_send(send_sock[0], iov, 2, 0, sizeof(size) + sizeof(send_buf));
g_assert_cmpint(ret, ==, sizeof(send_buf) + sizeof(size));
close(send_sock[0]);
#include "qemu/error-report.h"
#include "qemu/main-loop.h"
-/* TODO actually test the results and get rid of this */
-#define qmp_discard_response(qs, ...) qobject_unref(qtest_qmp(qs, __VA_ARGS__))
-
static void test_redirector_tx(void)
{
int backend_sock[2], recv_sock;
g_assert_cmpint(recv_sock, !=, -1);
/* send a qmp command to guarantee that 'connected' is setting to true. */
- qmp_discard_response(qts, "{ 'execute' : 'query-status'}");
+ qtest_qmp_assert_success(qts, "{ 'execute' : 'query-status'}");
struct iovec iov[] = {
{
send_sock = unix_connect(sock_path1, NULL);
g_assert_cmpint(send_sock, !=, -1);
/* send a qmp command to guarantee that 'connected' is setting to true. */
- qmp_discard_response(qts, "{ 'execute' : 'query-status'}");
+ qtest_qmp_assert_success(qts, "{ 'execute' : 'query-status'}");
ret = iov_send(send_sock, iov, 2, 0, sizeof(size) + sizeof(send_buf));
g_assert_cmpint(ret, ==, sizeof(send_buf) + sizeof(size));
#include "libqos/qgraph.h"
#include "libqos/virtio-blk.h"
-/* TODO actually test the results and get rid of this */
-#define qmp_discard_response(...) qobject_unref(qmp(__VA_ARGS__))
-
#define TEST_IMAGE_SIZE (64 * 1024 * 1024)
#define QVIRTIO_BLK_TIMEOUT_US (30 * 1000 * 1000)
#define PCI_SLOT_HP 0x06
qvirtio_set_driver_ok(dev);
- qmp_discard_response("{ 'execute': 'block_resize', "
- " 'arguments': { 'device': 'drive0', "
- " 'size': %d } }", n_size);
+ qtest_qmp_assert_success(global_qtest,
+ "{ 'execute': 'block_resize', "
+ " 'arguments': { 'device': 'drive0', "
+ " 'size': %d } }", n_size);
qvirtio_wait_config_isr(dev, QVIRTIO_BLK_TIMEOUT_US);
capacity = qvirtio_config_readq(dev, 0);
qvirtio_set_driver_ok(dev);
- qmp_discard_response("{ 'execute': 'block_resize', "
- " 'arguments': { 'device': 'drive0', "
- " 'size': %d } }", n_size);
+ qtest_qmp_assert_success(global_qtest,
+ "{ 'execute': 'block_resize', "
+ " 'arguments': { 'device': 'drive0', "
+ " 'size': %d } }", n_size);
qvirtio_wait_config_isr(dev, QVIRTIO_BLK_TIMEOUT_US);
vq = test_basic(dev, t_alloc);
- qmp_discard_response("{ 'execute': 'block_resize', "
- " 'arguments': { 'device': 'drive0', "
- " 'size': %d } }", n_size);
+ qtest_qmp_assert_success(global_qtest,
+ "{ 'execute': 'block_resize', "
+ " 'arguments': { 'device': 'drive0', "
+ " 'size': %d } }", n_size);
qvirtio_wait_queue_isr(qts, dev, vq, QVIRTIO_BLK_TIMEOUT_US);
}
/*
- * Helper macros for shift/extract so we can keep our endian handling
- * in one place.
+ * Helper macros for endian handling.
*/
-#define BYTE_SHIFT(b, pos) ((uint64_t)b << (pos * 8))
-#define BYTE_EXTRACT(b, pos) ((b >> (pos * 8)) & 0xff)
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define BYTE_SHIFT(b, pos) (b << (pos * 8))
+#define BYTE_NEXT(b) ((b)++)
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#define BYTE_SHIFT(b, pos) (b << ((sizeof(b) - 1 - (pos)) * 8))
+#define BYTE_NEXT(b) (--(b))
+#else
+#error Unsupported __BYTE_ORDER__
+#endif
/*
- * Fill the data with ascending value bytes.
- *
- * Currently we only support Little Endian machines so write in
- * ascending address order. When we read higher address bytes should
- * either be zero or higher than the lower bytes.
+ * Fill the data with ascending (for little-endian) or descending (for
+ * big-endian) value bytes.
*/
static void init_test_data_u8(int unused_offset)
ml_printf("Filling test area with u8:");
for (i = 0; i < TEST_SIZE; i++) {
- *ptr++ = count++;
+ *ptr++ = BYTE_NEXT(count);
pdot(i);
}
ml_printf("done\n");
}
/*
- * Full the data with alternating positive and negative bytes. This
+ * Fill the data with alternating positive and negative bytes. This
* should mean for reads larger than a byte all subsequent reads will
* stay either negative or positive. We never write 0.
*/
reset_start_data(offset);
for (i = 0; i < max; i++) {
- uint8_t low = count++, high = count++;
+ uint16_t low = BYTE_NEXT(count), high = BYTE_NEXT(count);
word = BYTE_SHIFT(high, 1) | BYTE_SHIFT(low, 0);
*ptr++ = word;
pdot(i);
reset_start_data(offset);
for (i = 0; i < max; i++) {
- uint8_t b4 = count++, b3 = count++;
- uint8_t b2 = count++, b1 = count++;
- word = BYTE_SHIFT(b1, 3) | BYTE_SHIFT(b2, 2) | BYTE_SHIFT(b3, 1) | b4;
+ uint32_t b4 = BYTE_NEXT(count), b3 = BYTE_NEXT(count);
+ uint32_t b2 = BYTE_NEXT(count), b1 = BYTE_NEXT(count);
+ word = BYTE_SHIFT(b1, 3) | BYTE_SHIFT(b2, 2) | BYTE_SHIFT(b3, 1) |
+ BYTE_SHIFT(b4, 0);
*ptr++ = word;
pdot(i);
}
reset_start_data(offset);
for (i = 0; i < max; i++) {
- uint8_t b8 = count++, b7 = count++;
- uint8_t b6 = count++, b5 = count++;
- uint8_t b4 = count++, b3 = count++;
- uint8_t b2 = count++, b1 = count++;
+ uint64_t b8 = BYTE_NEXT(count), b7 = BYTE_NEXT(count);
+ uint64_t b6 = BYTE_NEXT(count), b5 = BYTE_NEXT(count);
+ uint64_t b4 = BYTE_NEXT(count), b3 = BYTE_NEXT(count);
+ uint64_t b2 = BYTE_NEXT(count), b1 = BYTE_NEXT(count);
word = BYTE_SHIFT(b1, 7) | BYTE_SHIFT(b2, 6) | BYTE_SHIFT(b3, 5) |
BYTE_SHIFT(b4, 4) | BYTE_SHIFT(b5, 3) | BYTE_SHIFT(b6, 2) |
- BYTE_SHIFT(b7, 1) | b8;
+ BYTE_SHIFT(b7, 1) | BYTE_SHIFT(b8, 0);
*ptr++ = word;
pdot(i);
}
ml_printf("Reading s16 from %#lx (offset %d, %s):", ptr,
offset, neg_first ? "neg" : "pos");
+ /*
+ * If the first byte is negative, then the last byte is positive.
+ * Therefore the logic below must be flipped for big-endian.
+ */
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ neg_first = !neg_first;
+#endif
+
for (i = 0; i < max; i++) {
int32_t data = *ptr++;
if (neg_first && data < 0) {
pdot(i);
- } else if (data > 0) {
+ } else if (!neg_first && data > 0) {
pdot(i);
} else {
ml_printf("Error %d %c 0\n", data, neg_first ? '<' : '>');
ml_printf("Reading s32 from %#lx (offset %d, %s):",
ptr, offset, neg_first ? "neg" : "pos");
+ /*
+ * If the first byte is negative, then the last byte is positive.
+ * Therefore the logic below must be flipped for big-endian.
+ */
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ neg_first = !neg_first;
+#endif
+
for (i = 0; i < max; i++) {
int64_t data = *ptr++;
if (neg_first && data < 0) {
pdot(i);
- } else if (data > 0) {
+ } else if (!neg_first && data > 0) {
pdot(i);
} else {
ml_printf("Error %d %c 0\n", data, neg_first ? '<' : '>');
* Read the test data and verify at various offsets
*
* For everything except bytes all our reads should be either positive
- * or negative depending on what offset we are reading from. Currently
- * we only handle LE systems.
+ * or negative depending on what offset we are reading from.
*/
read_sfn read_sfns[] = { read_test_data_s8,
read_test_data_s16,
S390X_SRC=$(SRC_PATH)/tests/tcg/s390x
VPATH+=$(S390X_SRC)
-QEMU_OPTS=-action panic=exit-failure -kernel
+QEMU_OPTS=-action panic=exit-failure -nographic -kernel
LINK_SCRIPT=$(S390X_SRC)/softmmu.ld
-LDFLAGS=-nostdlib -static -Wl,-T$(LINK_SCRIPT) -Wl,--build-id=none
+CFLAGS+=-ggdb -O0
+LDFLAGS=-nostdlib -static
%.o: %.S
$(CC) -march=z13 -m64 -c $< -o $@
-%: %.o $(LINK_SCRIPT)
+%.o: %.c
+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -march=z13 -m64 -c $< -o $@
+
+%: %.o
$(CC) $< -o $@ $(LDFLAGS)
-TESTS += unaligned-lowcore
-TESTS += bal
-TESTS += sam
-TESTS += lpsw
-TESTS += lpswe-early
-TESTS += ssm-early
-TESTS += stosm-early
-TESTS += exrl-ssm-early
+ASM_TESTS = \
+ bal \
+ exrl-ssm-early \
+ sam \
+ lpsw \
+ lpswe-early \
+ ssm-early \
+ stosm-early \
+ unaligned-lowcore
include $(S390X_SRC)/pgm-specification.mak
$(PGM_SPECIFICATION_TESTS): pgm-specification-softmmu.o
$(PGM_SPECIFICATION_TESTS): LDFLAGS+=pgm-specification-softmmu.o
-TESTS += $(PGM_SPECIFICATION_TESTS)
+ASM_TESTS += $(PGM_SPECIFICATION_TESTS)
+
+$(ASM_TESTS): LDFLAGS += -Wl,-T$(LINK_SCRIPT) -Wl,--build-id=none
+$(ASM_TESTS): $(LINK_SCRIPT)
+TESTS += $(ASM_TESTS)
-# We don't currently support the multiarch system tests
-undefine MULTIARCH_TESTS
+S390X_MULTIARCH_RUNTIME_OBJS = head64.o console.o $(MINILIB_OBJS)
+$(MULTIARCH_TESTS): $(S390X_MULTIARCH_RUNTIME_OBJS)
+$(MULTIARCH_TESTS): LDFLAGS += $(S390X_MULTIARCH_RUNTIME_OBJS)
+$(MULTIARCH_TESTS): CFLAGS += $(MINILIB_INC)
+memory: CFLAGS += -DCHECK_UNALIGNED=0
TESTS+=chrl
TESTS+=rxsbg
TESTS+=ex-relative-long
+TESTS+=ex-branch
cdsg: CFLAGS+=-pthread
cdsg: LDFLAGS+=-pthread
--- /dev/null
+/*
+ * Console code for multiarch tests.
+ * Reuses the pc-bios/s390-ccw implementation.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#include "../../../pc-bios/s390-ccw/sclp.c"
+
+void __sys_outc(char c)
+{
+ write(1, &c, sizeof(c));
+}
--- /dev/null
+/* Check EXECUTE with relative branch instructions as targets. */
+#include <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct test {
+ const char *name;
+ void (*func)(long *link, long *magic);
+ long exp_link;
+};
+
+/* Branch instructions and their expected effects. */
+#define LINK_64(test) ((long)test ## _exp_link)
+#define LINK_NONE(test) -1L
+#define FOR_EACH_INSN(F) \
+ F(bras, "%[link]", LINK_64) \
+ F(brasl, "%[link]", LINK_64) \
+ F(brc, "0x8", LINK_NONE) \
+ F(brcl, "0x8", LINK_NONE) \
+ F(brct, "%%r0", LINK_NONE) \
+ F(brctg, "%%r0", LINK_NONE) \
+ F(brxh, "%%r2,%%r0", LINK_NONE) \
+ F(brxhg, "%%r2,%%r0", LINK_NONE) \
+ F(brxle, "%%r0,%%r1", LINK_NONE) \
+ F(brxlg, "%%r0,%%r1", LINK_NONE) \
+ F(crj, "%%r0,%%r0,8", LINK_NONE) \
+ F(cgrj, "%%r0,%%r0,8", LINK_NONE) \
+ F(cij, "%%r0,0,8", LINK_NONE) \
+ F(cgij, "%%r0,0,8", LINK_NONE) \
+ F(clrj, "%%r0,%%r0,8", LINK_NONE) \
+ F(clgrj, "%%r0,%%r0,8", LINK_NONE) \
+ F(clij, "%%r0,0,8", LINK_NONE) \
+ F(clgij, "%%r0,0,8", LINK_NONE)
+
+#define INIT_TEST \
+ "xgr %%r0,%%r0\n" /* %r0 = 0; %cc = 0 */ \
+ "lghi %%r1,1\n" /* %r1 = 1 */ \
+ "lghi %%r2,2\n" /* %r2 = 2 */
+
+#define CLOBBERS_TEST "cc", "0", "1", "2"
+
+#define DEFINE_TEST(insn, args, exp_link) \
+ extern char insn ## _exp_link[]; \
+ static void test_ ## insn(long *link, long *magic) \
+ { \
+ asm(INIT_TEST \
+ #insn " " args ",0f\n" \
+ ".globl " #insn "_exp_link\n" \
+ #insn "_exp_link:\n" \
+ ".org . + 90\n" \
+ "0: lgfi %[magic],0x12345678\n" \
+ : [link] "+r" (*link) \
+ , [magic] "+r" (*magic) \
+ : : CLOBBERS_TEST); \
+ } \
+ extern char ex_ ## insn ## _exp_link[]; \
+ static void test_ex_ ## insn(long *link, long *magic) \
+ { \
+ unsigned long target; \
+ \
+ asm(INIT_TEST \
+ "larl %[target],0f\n" \
+ "ex %%r0,0(%[target])\n" \
+ ".globl ex_" #insn "_exp_link\n" \
+ "ex_" #insn "_exp_link:\n" \
+ ".org . + 60\n" \
+ "0: " #insn " " args ",1f\n" \
+ ".org . + 120\n" \
+ "1: lgfi %[magic],0x12345678\n" \
+ : [target] "=r" (target) \
+ , [link] "+r" (*link) \
+ , [magic] "+r" (*magic) \
+ : : CLOBBERS_TEST); \
+ } \
+ extern char exrl_ ## insn ## _exp_link[]; \
+ static void test_exrl_ ## insn(long *link, long *magic) \
+ { \
+ asm(INIT_TEST \
+ "exrl %%r0,0f\n" \
+ ".globl exrl_" #insn "_exp_link\n" \
+ "exrl_" #insn "_exp_link:\n" \
+ ".org . + 60\n" \
+ "0: " #insn " " args ",1f\n" \
+ ".org . + 120\n" \
+ "1: lgfi %[magic],0x12345678\n" \
+ : [link] "+r" (*link) \
+ , [magic] "+r" (*magic) \
+ : : CLOBBERS_TEST); \
+ }
+
+/* Test functions. */
+FOR_EACH_INSN(DEFINE_TEST)
+
+/* Test definitions. */
+#define REGISTER_TEST(insn, args, _exp_link) \
+ { \
+ .name = #insn, \
+ .func = test_ ## insn, \
+ .exp_link = (_exp_link(insn)), \
+ }, \
+ { \
+ .name = "ex " #insn, \
+ .func = test_ex_ ## insn, \
+ .exp_link = (_exp_link(ex_ ## insn)), \
+ }, \
+ { \
+ .name = "exrl " #insn, \
+ .func = test_exrl_ ## insn, \
+ .exp_link = (_exp_link(exrl_ ## insn)), \
+ },
+
+static const struct test tests[] = {
+ FOR_EACH_INSN(REGISTER_TEST)
+};
+
+int main(int argc, char **argv)
+{
+ const struct test *test;
+ int ret = EXIT_SUCCESS;
+ bool verbose = false;
+ long link, magic;
+ size_t i;
+
+ for (i = 1; i < argc; i++) {
+ if (strcmp(argv[i], "-v") == 0) {
+ verbose = true;
+ }
+ }
+
+ for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
+ test = &tests[i];
+ if (verbose) {
+ fprintf(stderr, "[ RUN ] %s\n", test->name);
+ }
+ link = -1;
+ magic = -1;
+ test->func(&link, &magic);
+#define ASSERT_EQ(expected, actual) do { \
+ if (expected != actual) { \
+ fprintf(stderr, "%s: " #expected " (0x%lx) != " #actual " (0x%lx)\n", \
+ test->name, expected, actual); \
+ ret = EXIT_FAILURE; \
+ } \
+} while (0)
+ ASSERT_EQ(test->exp_link, link);
+ ASSERT_EQ(0x12345678L, magic);
+#undef ASSERT_EQ
+ }
+
+ if (verbose) {
+ fprintf(stderr, ret == EXIT_SUCCESS ? "[ PASSED ]\n" :
+ "[ FAILED ]\n");
+ }
+
+ return ret;
+}
--- /dev/null
+/*
+ * Startup code for multiarch tests.
+ * Reuses the pc-bios/s390-ccw implementation.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+#define main main_pre
+#include "../../../pc-bios/s390-ccw/start.S"
+#undef main
+
+main_pre:
+ aghi %r15,-160 /* reserve stack for C code */
+ brasl %r14,sclp_setup
+ brasl %r14,main
+ larl %r1,success_psw /* check main() return code */
+ ltgr %r2,%r2
+ je 0f
+ larl %r1,failure_psw
+0:
+ lpswe 0(%r1)
+
+ .align 8
+success_psw:
+ .quad 0x2000180000000,0xfff /* see is_special_wait_psw() */
+failure_psw:
+ .quad 0x2000180000000,0 /* disabled wait */
+
+ .section .bss
+ .align 0x1000
+stack:
+ .skip 0x8000
*/
#include "qemu/osdep.h"
+#include "qemu/config-file.h"
+#include "qemu/option.h"
+#include "qemu/module.h"
#include <dirent.h>
#include <sys/prctl.h>
#include <sched.h>
clone(async_teardown_fn, new_stack_for_clone(), CLONE_VM, NULL);
sigprocmask(SIG_SETMASK, &old_signals, NULL);
}
+
+static QemuOptsList qemu_run_with_opts = {
+ .name = "run-with",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_run_with_opts.head),
+ .desc = {
+ {
+ .name = "async-teardown",
+ .type = QEMU_OPT_BOOL,
+ },
+ { /* end of list */ }
+ },
+};
+
+static void register_teardown(void)
+{
+ qemu_add_opts(&qemu_run_with_opts);
+}
+opts_init(register_teardown);