From: Richard Henderson Date: Mon, 15 Jul 2013 20:21:10 +0000 (-0700) Subject: Merge git://github.com/hw-claudio/qemu-aarch64-queue into tcg-next X-Git-Tag: v1.6.0-rc0~57^2 X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=f290e4988dd8eb012de0517a1ff93df130e87da1;hp=c6d8ed24b446b1f1e07af87cde54317f54a1d42e;p=qemu.git Merge git://github.com/hw-claudio/qemu-aarch64-queue into tcg-next --- diff --git a/MAINTAINERS b/MAINTAINERS index ad9c8602e..93ad19d90 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -104,6 +104,12 @@ M: Anthony Green S: Maintained F: target-moxie/ +OpenRISC +M: Jia Liu +S: Maintained +F: target-openrisc/ +F: hw/openrisc/ + PowerPC M: Alexander Graf L: qemu-ppc@nongnu.org @@ -155,7 +161,7 @@ Guest CPU Cores (KVM): Overall M: Gleb Natapov -M: Marcelo Tosatti +M: Paolo Bonzini L: kvm@vger.kernel.org S: Supported F: kvm-* @@ -303,11 +309,7 @@ Axis Dev88 M: Edgar E. Iglesias S: Maintained F: hw/cris/axis_dev88.c - -etraxfs -M: Edgar E. Iglesias -S: Maintained -F: hw/cris/etraxfs.c +F: hw/*/etraxfs_*.c LM32 Machines ------------- @@ -343,7 +345,7 @@ MicroBlaze Machines petalogix_s3adsp1800 M: Edgar E. Iglesias S: Maintained -F: hw/microblaze/petalogix_s3adsp1800.c +F: hw/microblaze/petalogix_s3adsp1800_mmu.c petalogix_ml605 M: Peter Crosthwaite @@ -372,6 +374,13 @@ M: Aurelien Jarno S: Maintained F: hw/mips/mips_r4k.c +OpenRISC Machines +----------------- +or1k-sim +M: Jia Liu +S: Maintained +F: hw/openrisc/openrisc_sim.c + PowerPC Machines ---------------- 405 @@ -407,8 +416,8 @@ M: Alexander Graf L: qemu-ppc@nongnu.org S: Maintained F: hw/ppc/mac_newworld.c -F: hw/pci/devices/host-uninorth.c -F: hw/pci/devices/host-dec.[hc] +F: hw/pci-host/uninorth.c +F: hw/pci-bridge/dec.[hc] F: hw/misc/macio/ Old World @@ -416,7 +425,7 @@ M: Alexander Graf L: qemu-ppc@nongnu.org S: Maintained F: hw/ppc/mac_oldworld.c -F: hw/pci/devices/host-grackle.c +F: hw/pci-host/grackle.c F: hw/misc/macio/ PReP @@ -424,7 +433,7 @@ M: Andreas Färber L: qemu-ppc@nongnu.org S: Odd Fixes F: hw/ppc/prep.c -F: hw/pci/devices/host-prep.[hc] +F: hw/pci-host/prep.[hc] F: hw/isa/pc87312.[hc] sPAPR @@ -441,19 +450,19 @@ virtex_ml507 M: Edgar E. Iglesias L: qemu-ppc@nongnu.org S: Odd Fixes -F: hw/pci/virtex_ml507.c +F: hw/ppc/virtex_ml507.c SH4 Machines ------------ R2D M: Magnus Damm S: Maintained -F: hw/sh/r2d.c +F: hw/sh4/r2d.c Shix M: Magnus Damm S: Orphan -F: hw/sh/shix.c +F: hw/sh4/shix.c SPARC Machines -------------- @@ -478,7 +487,7 @@ S390 Machines S390 Virtio M: Alexander Graf S: Maintained -F: hw/s390/s390-*.c +F: hw/s390x/s390-*.c S390 Virtio-ccw M: Cornelia Huck @@ -547,7 +556,7 @@ M: Alexander Graf M: Scott Wood L: qemu-ppc@nongnu.org S: Supported -F: hw/ppc/e500_* +F: hw/ppc/e500* SCSI M: Paolo Bonzini @@ -575,7 +584,7 @@ F: hw/usb/* VFIO M: Alex Williamson S: Supported -F: hw/pci/vfio.c +F: hw/misc/vfio.c vhost M: Michael S. Tsirkin @@ -649,7 +658,7 @@ CPU M: Andreas Färber S: Supported F: qom/cpu.c -F: include/qemu/cpu.h +F: include/qom/cpu.h F: target-i386/cpu.c ICC Bus @@ -662,7 +671,7 @@ Device Tree M: Peter Crosthwaite M: Alexander Graf S: Maintained -F: device-tree.[ch] +F: device_tree.[ch] GDB stub M: qemu-devel@nongnu.org @@ -673,7 +682,7 @@ F: gdb-xml/ SPICE M: Gerd Hoffmann S: Supported -F: ui/qemu-spice.h +F: include/ui/qemu-spice.h F: ui/spice-*.c F: audio/spiceaudio.c F: hw/display/qxl* @@ -772,6 +781,7 @@ Tiny Code Generator (TCG) ------------------------- Common code M: qemu-devel@nongnu.org +M: Richard Henderson S: Maintained F: tcg/ diff --git a/block.c b/block.c index 6c493ad45..b56024113 100644 --- a/block.c +++ b/block.c @@ -417,7 +417,7 @@ int bdrv_create_file(const char* filename, QEMUOptionParameter *options) { BlockDriver *drv; - drv = bdrv_find_protocol(filename); + drv = bdrv_find_protocol(filename, true); if (drv == NULL) { return -ENOENT; } @@ -482,7 +482,8 @@ static BlockDriver *find_hdev_driver(const char *filename) return drv; } -BlockDriver *bdrv_find_protocol(const char *filename) +BlockDriver *bdrv_find_protocol(const char *filename, + bool allow_protocol_prefix) { BlockDriver *drv1; char protocol[128]; @@ -503,9 +504,10 @@ BlockDriver *bdrv_find_protocol(const char *filename) return drv1; } - if (!path_has_protocol(filename)) { + if (!path_has_protocol(filename) || !allow_protocol_prefix) { return bdrv_find_format("file"); } + p = strchr(filename, ':'); assert(p != NULL); len = p - filename; @@ -784,6 +786,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, BlockDriverState *bs; BlockDriver *drv; const char *drvname; + bool allow_protocol_prefix = false; int ret; /* NULL means an empty set of options */ @@ -800,6 +803,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, filename = qdict_get_try_str(options, "filename"); } else if (filename && !qdict_haskey(options, "filename")) { qdict_put(options, "filename", qstring_from_str(filename)); + allow_protocol_prefix = true; } else { qerror_report(ERROR_CLASS_GENERIC_ERROR, "Can't specify 'file' and " "'filename' options at the same time"); @@ -813,7 +817,10 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, drv = bdrv_find_whitelisted_format(drvname, !(flags & BDRV_O_RDWR)); qdict_del(options, "driver"); } else if (filename) { - drv = bdrv_find_protocol(filename); + drv = bdrv_find_protocol(filename, allow_protocol_prefix); + if (!drv) { + qerror_report(ERROR_CLASS_GENERIC_ERROR, "Unknown protocol"); + } } else { qerror_report(ERROR_CLASS_GENERIC_ERROR, "Must specify either driver or file"); @@ -1358,11 +1365,12 @@ void bdrv_reopen_abort(BDRVReopenState *reopen_state) void bdrv_close(BlockDriverState *bs) { - bdrv_flush(bs); if (bs->job) { block_job_cancel_sync(bs->job); } - bdrv_drain_all(); + bdrv_drain_all(); /* complete I/O */ + bdrv_flush(bs); + bdrv_drain_all(); /* in case flush left pending I/O */ notifier_list_notify(&bs->close_notifiers, bs); if (bs->drv) { @@ -2902,13 +2910,19 @@ int bdrv_get_flags(BlockDriverState *bs) return bs->open_flags; } -void bdrv_flush_all(void) +int bdrv_flush_all(void) { BlockDriverState *bs; + int result = 0; QTAILQ_FOREACH(bs, &bdrv_states, list) { - bdrv_flush(bs); + int ret = bdrv_flush(bs); + if (ret < 0 && !result) { + result = ret; + } } + + return result; } int bdrv_has_zero_init_1(BlockDriverState *bs) @@ -4451,7 +4465,7 @@ void bdrv_img_create(const char *filename, const char *fmt, return; } - proto_drv = bdrv_find_protocol(filename); + proto_drv = bdrv_find_protocol(filename, true); if (!proto_drv) { error_setg(errp, "Unknown protocol '%s'", filename); return; diff --git a/block/curl.c b/block/curl.c index 6af8cb757..82d39ff53 100644 --- a/block/curl.c +++ b/block/curl.c @@ -81,6 +81,7 @@ typedef struct BDRVCURLState { CURLState states[CURL_NUM_STATES]; char *url; size_t readahead_size; + bool accept_range; } BDRVCURLState; static void curl_clean_state(CURLState *s); @@ -110,14 +111,15 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, return 0; } -static size_t curl_size_cb(void *ptr, size_t size, size_t nmemb, void *opaque) +static size_t curl_header_cb(void *ptr, size_t size, size_t nmemb, void *opaque) { - CURLState *s = ((CURLState*)opaque); + BDRVCURLState *s = opaque; size_t realsize = size * nmemb; - size_t fsize; + const char *accept_line = "Accept-Ranges: bytes"; - if(sscanf(ptr, "Content-Length: %zd", &fsize) == 1) { - s->s->len = fsize; + if (realsize >= strlen(accept_line) + && strncmp((char *)ptr, accept_line, strlen(accept_line)) == 0) { + s->accept_range = true; } return realsize; @@ -447,8 +449,11 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags) // Get file size + s->accept_range = false; curl_easy_setopt(state->curl, CURLOPT_NOBODY, 1); - curl_easy_setopt(state->curl, CURLOPT_WRITEFUNCTION, (void *)curl_size_cb); + curl_easy_setopt(state->curl, CURLOPT_HEADERFUNCTION, + curl_header_cb); + curl_easy_setopt(state->curl, CURLOPT_HEADERDATA, s); if (curl_easy_perform(state->curl)) goto out; curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d); @@ -456,6 +461,13 @@ static int curl_open(BlockDriverState *bs, QDict *options, int flags) s->len = (size_t)d; else if(!s->len) goto out; + if ((!strncasecmp(s->url, "http://", strlen("http://")) + || !strncasecmp(s->url, "https://", strlen("https://"))) + && !s->accept_range) { + pstrcpy(state->errmsg, CURL_ERROR_SIZE, + "Server does not support 'range' (byte ranges)."); + goto out; + } DPRINTF("CURL: Size = %zd\n", s->len); curl_clean_state(state); diff --git a/block/sheepdog.c b/block/sheepdog.c index b397b5b4d..6a41ad9b3 100644 --- a/block/sheepdog.c +++ b/block/sheepdog.c @@ -1510,7 +1510,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options) BlockDriver *drv; /* Currently, only Sheepdog backing image is supported. */ - drv = bdrv_find_protocol(backing_file); + drv = bdrv_find_protocol(backing_file, true); if (!drv || strcmp(drv->protocol_name, "sheepdog") != 0) { error_report("backing_file must be a sheepdog image"); ret = -EINVAL; diff --git a/block/vmdk.c b/block/vmdk.c index a28fb5e8e..3756333c6 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -1724,6 +1724,23 @@ static int64_t vmdk_get_allocated_file_size(BlockDriverState *bs) return ret; } +static int vmdk_has_zero_init(BlockDriverState *bs) +{ + int i; + BDRVVmdkState *s = bs->opaque; + + /* If has a flat extent and its underlying storage doesn't have zero init, + * return 0. */ + for (i = 0; i < s->num_extents; i++) { + if (s->extents[i].flat) { + if (!bdrv_has_zero_init(s->extents[i].file)) { + return 0; + } + } + } + return 1; +} + static QEMUOptionParameter vmdk_create_options[] = { { .name = BLOCK_OPT_SIZE, @@ -1762,21 +1779,22 @@ static QEMUOptionParameter vmdk_create_options[] = { }; static BlockDriver bdrv_vmdk = { - .format_name = "vmdk", - .instance_size = sizeof(BDRVVmdkState), - .bdrv_probe = vmdk_probe, - .bdrv_open = vmdk_open, - .bdrv_reopen_prepare = vmdk_reopen_prepare, - .bdrv_read = vmdk_co_read, - .bdrv_write = vmdk_co_write, - .bdrv_co_write_zeroes = vmdk_co_write_zeroes, - .bdrv_close = vmdk_close, - .bdrv_create = vmdk_create, - .bdrv_co_flush_to_disk = vmdk_co_flush, - .bdrv_co_is_allocated = vmdk_co_is_allocated, - .bdrv_get_allocated_file_size = vmdk_get_allocated_file_size, - - .create_options = vmdk_create_options, + .format_name = "vmdk", + .instance_size = sizeof(BDRVVmdkState), + .bdrv_probe = vmdk_probe, + .bdrv_open = vmdk_open, + .bdrv_reopen_prepare = vmdk_reopen_prepare, + .bdrv_read = vmdk_co_read, + .bdrv_write = vmdk_co_write, + .bdrv_co_write_zeroes = vmdk_co_write_zeroes, + .bdrv_close = vmdk_close, + .bdrv_create = vmdk_create, + .bdrv_co_flush_to_disk = vmdk_co_flush, + .bdrv_co_is_allocated = vmdk_co_is_allocated, + .bdrv_get_allocated_file_size = vmdk_get_allocated_file_size, + .bdrv_has_zero_init = vmdk_has_zero_init, + + .create_options = vmdk_create_options, }; static void bdrv_vmdk_init(void) diff --git a/blockdev.c b/blockdev.c index b3a57e0c1..c5abd6518 100644 --- a/blockdev.c +++ b/blockdev.c @@ -936,6 +936,7 @@ static void drive_backup_prepare(BlkTransactionState *common, Error **errp) qmp_drive_backup(backup->device, backup->target, backup->has_format, backup->format, + backup->sync, backup->has_mode, backup->mode, backup->has_speed, backup->speed, backup->has_on_source_error, backup->on_source_error, @@ -1421,6 +1422,7 @@ void qmp_block_commit(const char *device, void qmp_drive_backup(const char *device, const char *target, bool has_format, const char *format, + enum MirrorSyncMode sync, bool has_mode, enum NewImageMode mode, bool has_speed, int64_t speed, bool has_on_source_error, BlockdevOnError on_source_error, @@ -1435,6 +1437,10 @@ void qmp_drive_backup(const char *device, const char *target, int64_t size; int ret; + if (sync != MIRROR_SYNC_MODE_FULL) { + error_setg(errp, "only sync mode 'full' is currently supported"); + return; + } if (!has_speed) { speed = 0; } diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c index 5e2051030..93fd9e425 100644 --- a/bsd-user/elfload.c +++ b/bsd-user/elfload.c @@ -98,7 +98,7 @@ enum { static const char *get_elf_platform(void) { static char elf_platform[] = "i386"; - int family = (thread_env->cpuid_version >> 8) & 0xff; + int family = object_property_get_int(OBJECT(thread_cpu), "family", NULL); if (family > 6) family = 6; if (family >= 3) @@ -110,7 +110,9 @@ static const char *get_elf_platform(void) static uint32_t get_elf_hwcap(void) { - return thread_env->features[FEAT_1_EDX]; + X86CPU *cpu = X86_CPU(thread_cpu); + + return cpu->env.features[FEAT_1_EDX]; } #ifdef TARGET_X86_64 diff --git a/bsd-user/main.c b/bsd-user/main.c index 75dbd7f70..1e9255242 100644 --- a/bsd-user/main.c +++ b/bsd-user/main.c @@ -92,7 +92,7 @@ void fork_start(void) void fork_end(int child) { if (child) { - gdbserver_fork(thread_env); + gdbserver_fork((CPUArchState *)thread_cpu->env_ptr); } } @@ -713,7 +713,7 @@ static void usage(void) exit(1); } -THREAD CPUArchState *thread_env; +THREAD CPUState *thread_cpu; /* Assumes contents are already zeroed. */ void init_task_state(TaskState *ts) @@ -915,7 +915,7 @@ int main(int argc, char **argv) #if defined(TARGET_SPARC) || defined(TARGET_PPC) cpu_reset(ENV_GET_CPU(env)); #endif - thread_env = env; + thread_cpu = ENV_GET_CPU(env); if (getenv("QEMU_STRACE")) { do_strace = 1; diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h index a826086da..325f564f8 100644 --- a/bsd-user/qemu.h +++ b/bsd-user/qemu.h @@ -139,7 +139,7 @@ abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6); void gemu_log(const char *fmt, ...) GCC_FMT_ATTR(1, 2); -extern THREAD CPUArchState *thread_env; +extern THREAD CPUState *thread_cpu; void cpu_loop(CPUArchState *env); char *target_strerror(int err); int get_osversion(void); diff --git a/configure b/configure index 8e425ba6e..0214bbc54 100755 --- a/configure +++ b/configure @@ -3445,6 +3445,36 @@ if test "$cpu" = "s390x" ; then roms="$roms s390-ccw" fi +# Probe for the need for relocating the user-only binary. +if test "$pie" = "no" ; then + textseg_addr= + case "$cpu" in + arm | hppa | i386 | m68k | ppc | ppc64 | s390* | sparc | sparc64 | x86_64) + textseg_addr=0x60000000 + ;; + mips) + textseg_addr=0x400000 + ;; + esac + if [ -n "$textseg_addr" ]; then + cat > $TMPC < config-host.ld + textseg_ldflags="-Wl,-T../config-host.ld" + fi + fi +fi + # add pixman flags after all config tests are done QEMU_CFLAGS="$QEMU_CFLAGS $pixman_cflags $fdt_cflags" libs_softmmu="$libs_softmmu $pixman_libs" @@ -4073,9 +4103,6 @@ if test "$gcov" = "yes" ; then echo "GCOV=$gcov_tool" >> $config_host_mak fi -# generate list of library paths for linker script -$ld --verbose -v 2> /dev/null | grep SEARCH_DIR > config-host.ld - # use included Linux headers if test "$linux" = "yes" ; then mkdir -p linux-headers @@ -4438,21 +4465,8 @@ if test "$gprof" = "yes" ; then fi fi -if test "$ARCH" = "tci"; then - linker_script="" -else - linker_script="-Wl,-T../config-host.ld -Wl,-T,\$(SRC_PATH)/ldscripts/\$(ARCH).ld" -fi - if test "$target_linux_user" = "yes" -o "$target_bsd_user" = "yes" ; then - case "$ARCH" in - alpha | s390x | aarch64) - # The default placement of the application is fine. - ;; - *) - ldflags="$linker_script $ldflags" - ;; - esac + ldflags="$ldflags $textseg_ldflags" fi echo "LDFLAGS+=$ldflags" >> $config_target_mak diff --git a/cpu-exec.c b/cpu-exec.c index ec4638043..6c784a7e0 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -213,12 +213,12 @@ int cpu_exec(CPUArchState *env) cpu->halted = 0; } - cpu_single_env = env; + current_cpu = cpu; - /* As long as cpu_single_env is null, up to the assignment just above, + /* As long as current_cpu is null, up to the assignment just above, * requests by other threads to exit the execution loop are expected to * be issued using the exit_request global. We must make sure that our - * evaluation of the global value is performed past the cpu_single_env + * evaluation of the global value is performed past the current_cpu * value transition point, which requires a memory barrier as well as * an instruction scheduling constraint on modern architectures. */ smp_mb(); @@ -331,7 +331,7 @@ int cpu_exec(CPUArchState *env) cpu_svm_check_intercept_param(env, SVM_EXIT_SMI, 0); cpu->interrupt_request &= ~CPU_INTERRUPT_SMI; - do_smm_enter(env); + do_smm_enter(x86_env_get_cpu(env)); next_tb = 0; } else if ((interrupt_request & CPU_INTERRUPT_NMI) && !(env->hflags2 & HF2_NMI_MASK)) { @@ -577,15 +577,15 @@ int cpu_exec(CPUArchState *env) if (qemu_loglevel_mask(CPU_LOG_TB_CPU)) { /* restore flags in standard format */ #if defined(TARGET_I386) - log_cpu_state(env, CPU_DUMP_CCOP); + log_cpu_state(cpu, CPU_DUMP_CCOP); #elif defined(TARGET_M68K) cpu_m68k_flush_flags(env, env->cc_op); env->cc_op = CC_OP_FLAGS; env->sr = (env->sr & 0xffe0) | env->cc_dest | (env->cc_x << 4); - log_cpu_state(env, 0); + log_cpu_state(cpu, 0); #else - log_cpu_state(env, 0); + log_cpu_state(cpu, 0); #endif } #endif /* DEBUG_DISAS */ @@ -673,7 +673,8 @@ int cpu_exec(CPUArchState *env) } else { /* Reload env after longjmp - the compiler may have smashed all * local variables as longjmp is marked 'noreturn'. */ - env = cpu_single_env; + cpu = current_cpu; + env = cpu->env_ptr; } } /* for(;;) */ @@ -707,7 +708,7 @@ int cpu_exec(CPUArchState *env) #error unsupported target CPU #endif - /* fail safe : never use cpu_single_env outside cpu_exec() */ - cpu_single_env = NULL; + /* fail safe : never use current_cpu outside cpu_exec() */ + current_cpu = NULL; return ret; } diff --git a/cpus.c b/cpus.c index 20958e5a5..29277e109 100644 --- a/cpus.c +++ b/cpus.c @@ -60,7 +60,7 @@ #endif /* CONFIG_LINUX */ -static CPUArchState *next_cpu; +static CPUState *next_cpu; static bool cpu_thread_is_idle(CPUState *cpu) { @@ -79,10 +79,10 @@ static bool cpu_thread_is_idle(CPUState *cpu) static bool all_cpu_threads_idle(void) { - CPUArchState *env; + CPUState *cpu; - for (env = first_cpu; env != NULL; env = env->next_cpu) { - if (!cpu_thread_is_idle(ENV_GET_CPU(env))) { + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { + if (!cpu_thread_is_idle(cpu)) { return false; } } @@ -118,10 +118,11 @@ TimersState timers_state; int64_t cpu_get_icount(void) { int64_t icount; - CPUArchState *env = cpu_single_env; + CPUState *cpu = current_cpu; icount = qemu_icount; - if (env) { + if (cpu) { + CPUArchState *env = cpu->env_ptr; if (!can_do_io(env)) { fprintf(stderr, "Bad clock read\n"); } @@ -387,15 +388,13 @@ void configure_icount(const char *option) void hw_error(const char *fmt, ...) { va_list ap; - CPUArchState *env; CPUState *cpu; va_start(ap, fmt); fprintf(stderr, "qemu: hardware error: "); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); - for (env = first_cpu; env != NULL; env = env->next_cpu) { - cpu = ENV_GET_CPU(env); + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { fprintf(stderr, "CPU #%d:\n", cpu->cpu_index); cpu_dump_state(cpu, stderr, fprintf, CPU_DUMP_FPU); } @@ -405,28 +404,28 @@ void hw_error(const char *fmt, ...) void cpu_synchronize_all_states(void) { - CPUArchState *env; + CPUState *cpu; - for (env = first_cpu; env; env = env->next_cpu) { - cpu_synchronize_state(ENV_GET_CPU(env)); + for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) { + cpu_synchronize_state(cpu); } } void cpu_synchronize_all_post_reset(void) { - CPUArchState *cpu; + CPUState *cpu; for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) { - cpu_synchronize_post_reset(ENV_GET_CPU(cpu)); + cpu_synchronize_post_reset(cpu); } } void cpu_synchronize_all_post_init(void) { - CPUArchState *cpu; + CPUState *cpu; for (cpu = first_cpu; cpu; cpu = cpu->next_cpu) { - cpu_synchronize_post_init(ENV_GET_CPU(cpu)); + cpu_synchronize_post_init(cpu); } } @@ -435,17 +434,21 @@ bool cpu_is_stopped(CPUState *cpu) return !runstate_is_running() || cpu->stopped; } -static void do_vm_stop(RunState state) +static int do_vm_stop(RunState state) { + int ret = 0; + if (runstate_is_running()) { cpu_disable_ticks(); pause_all_vcpus(); runstate_set(state); vm_state_notify(0, state); bdrv_drain_all(); - bdrv_flush_all(); + ret = bdrv_flush_all(); monitor_protocol_event(QEVENT_STOP, NULL); } + + return ret; } static bool cpu_can_run(CPUState *cpu) @@ -468,8 +471,8 @@ static void cpu_handle_guest_debug(CPUState *cpu) static void cpu_signal(int sig) { - if (cpu_single_env) { - cpu_exit(ENV_GET_CPU(cpu_single_env)); + if (current_cpu) { + cpu_exit(current_cpu); } exit_request = 1; } @@ -660,10 +663,10 @@ void run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data) qemu_cpu_kick(cpu); while (!wi.done) { - CPUArchState *self_env = cpu_single_env; + CPUState *self_cpu = current_cpu; qemu_cond_wait(&qemu_work_cond, &qemu_global_mutex); - cpu_single_env = self_env; + current_cpu = self_cpu; } } @@ -697,7 +700,7 @@ static void qemu_wait_io_event_common(CPUState *cpu) static void qemu_tcg_wait_io_event(void) { - CPUArchState *env; + CPUState *cpu; while (all_cpu_threads_idle()) { /* Start accounting real time to the virtual clock if the CPUs @@ -710,8 +713,8 @@ static void qemu_tcg_wait_io_event(void) qemu_cond_wait(&qemu_io_proceeded_cond, &qemu_global_mutex); } - for (env = first_cpu; env != NULL; env = env->next_cpu) { - qemu_wait_io_event_common(ENV_GET_CPU(env)); + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { + qemu_wait_io_event_common(cpu); } } @@ -733,7 +736,7 @@ static void *qemu_kvm_cpu_thread_fn(void *arg) qemu_mutex_lock(&qemu_global_mutex); qemu_thread_get_self(cpu->thread); cpu->thread_id = qemu_get_thread_id(); - cpu_single_env = cpu->env_ptr; + current_cpu = cpu; r = kvm_init_vcpu(cpu); if (r < 0) { @@ -781,9 +784,9 @@ static void *qemu_dummy_cpu_thread_fn(void *arg) cpu->created = true; qemu_cond_signal(&qemu_cpu_cond); - cpu_single_env = cpu->env_ptr; + current_cpu = cpu; while (1) { - cpu_single_env = NULL; + current_cpu = NULL; qemu_mutex_unlock_iothread(); do { int sig; @@ -794,7 +797,7 @@ static void *qemu_dummy_cpu_thread_fn(void *arg) exit(1); } qemu_mutex_lock_iothread(); - cpu_single_env = cpu->env_ptr; + current_cpu = cpu; qemu_wait_io_event_common(cpu); } @@ -813,7 +816,6 @@ static void tcg_signal_cpu_creation(CPUState *cpu, void *data) static void *qemu_tcg_cpu_thread_fn(void *arg) { CPUState *cpu = arg; - CPUArchState *env; qemu_tcg_init_cpu_signals(); qemu_thread_get_self(cpu->thread); @@ -823,12 +825,12 @@ static void *qemu_tcg_cpu_thread_fn(void *arg) qemu_cond_signal(&qemu_cpu_cond); /* wait for initial kick-off after machine start */ - while (ENV_GET_CPU(first_cpu)->stopped) { + while (first_cpu->stopped) { qemu_cond_wait(tcg_halt_cond, &qemu_global_mutex); /* process any pending work */ - for (env = first_cpu; env != NULL; env = env->next_cpu) { - qemu_wait_io_event_common(ENV_GET_CPU(env)); + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { + qemu_wait_io_event_common(cpu); } } @@ -894,12 +896,11 @@ void qemu_cpu_kick(CPUState *cpu) void qemu_cpu_kick_self(void) { #ifndef _WIN32 - assert(cpu_single_env); - CPUState *cpu_single_cpu = ENV_GET_CPU(cpu_single_env); + assert(current_cpu); - if (!cpu_single_cpu->thread_kicked) { - qemu_cpu_kick_thread(cpu_single_cpu); - cpu_single_cpu->thread_kicked = true; + if (!current_cpu->thread_kicked) { + qemu_cpu_kick_thread(current_cpu); + current_cpu->thread_kicked = true; } #else abort(); @@ -913,7 +914,7 @@ bool qemu_cpu_is_self(CPUState *cpu) static bool qemu_in_vcpu_thread(void) { - return cpu_single_env && qemu_cpu_is_self(ENV_GET_CPU(cpu_single_env)); + return current_cpu && qemu_cpu_is_self(current_cpu); } void qemu_mutex_lock_iothread(void) @@ -923,7 +924,7 @@ void qemu_mutex_lock_iothread(void) } else { iothread_requesting_mutex = true; if (qemu_mutex_trylock(&qemu_global_mutex)) { - qemu_cpu_kick_thread(ENV_GET_CPU(first_cpu)); + qemu_cpu_kick_thread(first_cpu); qemu_mutex_lock(&qemu_global_mutex); } iothread_requesting_mutex = false; @@ -938,14 +939,13 @@ void qemu_mutex_unlock_iothread(void) static int all_vcpus_paused(void) { - CPUArchState *penv = first_cpu; + CPUState *cpu = first_cpu; - while (penv) { - CPUState *pcpu = ENV_GET_CPU(penv); - if (!pcpu->stopped) { + while (cpu) { + if (!cpu->stopped) { return 0; } - penv = penv->next_cpu; + cpu = cpu->next_cpu; } return 1; @@ -953,25 +953,23 @@ static int all_vcpus_paused(void) void pause_all_vcpus(void) { - CPUArchState *penv = first_cpu; + CPUState *cpu = first_cpu; qemu_clock_enable(vm_clock, false); - while (penv) { - CPUState *pcpu = ENV_GET_CPU(penv); - pcpu->stop = true; - qemu_cpu_kick(pcpu); - penv = penv->next_cpu; + while (cpu) { + cpu->stop = true; + qemu_cpu_kick(cpu); + cpu = cpu->next_cpu; } if (qemu_in_vcpu_thread()) { cpu_stop_current(); if (!kvm_enabled()) { - penv = first_cpu; - while (penv) { - CPUState *pcpu = ENV_GET_CPU(penv); - pcpu->stop = false; - pcpu->stopped = true; - penv = penv->next_cpu; + cpu = first_cpu; + while (cpu) { + cpu->stop = false; + cpu->stopped = true; + cpu = cpu->next_cpu; } return; } @@ -979,10 +977,10 @@ void pause_all_vcpus(void) while (!all_vcpus_paused()) { qemu_cond_wait(&qemu_pause_cond, &qemu_global_mutex); - penv = first_cpu; - while (penv) { - qemu_cpu_kick(ENV_GET_CPU(penv)); - penv = penv->next_cpu; + cpu = first_cpu; + while (cpu) { + qemu_cpu_kick(cpu); + cpu = cpu->next_cpu; } } } @@ -996,13 +994,12 @@ void cpu_resume(CPUState *cpu) void resume_all_vcpus(void) { - CPUArchState *penv = first_cpu; + CPUState *cpu = first_cpu; qemu_clock_enable(vm_clock, true); - while (penv) { - CPUState *pcpu = ENV_GET_CPU(penv); - cpu_resume(pcpu); - penv = penv->next_cpu; + while (cpu) { + cpu_resume(cpu); + cpu = cpu->next_cpu; } } @@ -1069,16 +1066,15 @@ void qemu_init_vcpu(CPUState *cpu) void cpu_stop_current(void) { - if (cpu_single_env) { - CPUState *cpu_single_cpu = ENV_GET_CPU(cpu_single_env); - cpu_single_cpu->stop = false; - cpu_single_cpu->stopped = true; - cpu_exit(cpu_single_cpu); + if (current_cpu) { + current_cpu->stop = false; + current_cpu->stopped = true; + cpu_exit(current_cpu); qemu_cond_signal(&qemu_pause_cond); } } -void vm_stop(RunState state) +int vm_stop(RunState state) { if (qemu_in_vcpu_thread()) { qemu_system_vmstop_request(state); @@ -1087,19 +1083,21 @@ void vm_stop(RunState state) * vm_stop() has been requested. */ cpu_stop_current(); - return; + return 0; } - do_vm_stop(state); + + return do_vm_stop(state); } /* does a state transition even if the VM is already stopped, current state is forgotten forever */ -void vm_stop_force_state(RunState state) +int vm_stop_force_state(RunState state) { if (runstate_is_running()) { - vm_stop(state); + return vm_stop(state); } else { runstate_set(state); + return 0; } } @@ -1152,8 +1150,8 @@ static void tcg_exec_all(void) next_cpu = first_cpu; } for (; next_cpu != NULL && !exit_request; next_cpu = next_cpu->next_cpu) { - CPUArchState *env = next_cpu; - CPUState *cpu = ENV_GET_CPU(env); + CPUState *cpu = next_cpu; + CPUArchState *env = cpu->env_ptr; qemu_clock_enable(vm_clock, (env->singlestep_enabled & SSTEP_NOTIMER) == 0); @@ -1173,12 +1171,10 @@ static void tcg_exec_all(void) void set_numa_modes(void) { - CPUArchState *env; CPUState *cpu; int i; - for (env = first_cpu; env != NULL; env = env->next_cpu) { - cpu = ENV_GET_CPU(env); + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { for (i = 0; i < nb_numa_nodes; i++) { if (test_bit(cpu->cpu_index, node_cpumask[i])) { cpu->numa_node = i; @@ -1198,18 +1194,30 @@ void list_cpus(FILE *f, fprintf_function cpu_fprintf, const char *optarg) CpuInfoList *qmp_query_cpus(Error **errp) { CpuInfoList *head = NULL, *cur_item = NULL; - CPUArchState *env; + CPUState *cpu; - for (env = first_cpu; env != NULL; env = env->next_cpu) { - CPUState *cpu = ENV_GET_CPU(env); + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { CpuInfoList *info; +#if defined(TARGET_I386) + X86CPU *x86_cpu = X86_CPU(cpu); + CPUX86State *env = &x86_cpu->env; +#elif defined(TARGET_PPC) + PowerPCCPU *ppc_cpu = POWERPC_CPU(cpu); + CPUPPCState *env = &ppc_cpu->env; +#elif defined(TARGET_SPARC) + SPARCCPU *sparc_cpu = SPARC_CPU(cpu); + CPUSPARCState *env = &sparc_cpu->env; +#elif defined(TARGET_MIPS) + MIPSCPU *mips_cpu = MIPS_CPU(cpu); + CPUMIPSState *env = &mips_cpu->env; +#endif cpu_synchronize_state(cpu); info = g_malloc0(sizeof(*info)); info->value = g_malloc0(sizeof(*info->value)); info->value->CPU = cpu->cpu_index; - info->value->current = (env == first_cpu); + info->value->current = (cpu == first_cpu); info->value->halted = cpu->halted; info->value->thread_id = cpu->thread_id; #if defined(TARGET_I386) @@ -1317,11 +1325,14 @@ exit: void qmp_inject_nmi(Error **errp) { #if defined(TARGET_I386) - CPUArchState *env; + CPUState *cs; + + for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) { + X86CPU *cpu = X86_CPU(cs); + CPUX86State *env = &cpu->env; - for (env = first_cpu; env != NULL; env = env->next_cpu) { if (!env->apic_state) { - cpu_interrupt(CPU(x86_env_get_cpu(env)), CPU_INTERRUPT_NMI); + cpu_interrupt(cs, CPU_INTERRUPT_NMI); } else { apic_deliver_nmi(env->apic_state); } diff --git a/cputlb.c b/cputlb.c index 80b2a94ad..977c0ca59 100644 --- a/cputlb.c +++ b/cputlb.c @@ -158,6 +158,17 @@ void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry, uintptr_t start, } } +static inline ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr) +{ + ram_addr_t ram_addr; + + if (qemu_ram_addr_from_host(ptr, &ram_addr) == NULL) { + fprintf(stderr, "Bad ram pointer %p\n", ptr); + abort(); + } + return ram_addr; +} + static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry) { ram_addr_t ram_addr; @@ -175,11 +186,13 @@ static inline void tlb_update_dirty(CPUTLBEntry *tlb_entry) void cpu_tlb_reset_dirty_all(ram_addr_t start1, ram_addr_t length) { + CPUState *cpu; CPUArchState *env; - for (env = first_cpu; env != NULL; env = env->next_cpu) { + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { int mmu_idx; + env = cpu->env_ptr; for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) { unsigned int i; diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak index 03deca2dc..4a0fc9c29 100644 --- a/default-configs/i386-softmmu.mak +++ b/default-configs/i386-softmmu.mak @@ -28,11 +28,10 @@ CONFIG_APPLESMC=y CONFIG_I8259=y CONFIG_PFLASH_CFI01=y CONFIG_TPM_TIS=$(CONFIG_TPM) -CONFIG_PCI_HOTPLUG=y +CONFIG_PCI_HOTPLUG_OLD=y CONFIG_MC146818RTC=y CONFIG_PAM=y CONFIG_PCI_PIIX=y -CONFIG_PCI_HOTPLUG=y CONFIG_WDT_IB700=y CONFIG_PC_SYSFW=y CONFIG_XEN_I386=$(CONFIG_XEN) diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak index cb279cbcb..6d1933bbf 100644 --- a/default-configs/ppc64-softmmu.mak +++ b/default-configs/ppc64-softmmu.mak @@ -46,6 +46,6 @@ CONFIG_PSERIES=y CONFIG_E500=y CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM)) # For pSeries -CONFIG_PCI_HOTPLUG=y +CONFIG_XICS=$(CONFIG_PSERIES) # For PReP CONFIG_MC146818RTC=y diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak index 599b63071..10bb0c621 100644 --- a/default-configs/x86_64-softmmu.mak +++ b/default-configs/x86_64-softmmu.mak @@ -28,11 +28,10 @@ CONFIG_APPLESMC=y CONFIG_I8259=y CONFIG_PFLASH_CFI01=y CONFIG_TPM_TIS=$(CONFIG_TPM) -CONFIG_PCI_HOTPLUG=y +CONFIG_PCI_HOTPLUG_OLD=y CONFIG_MC146818RTC=y CONFIG_PAM=y CONFIG_PCI_PIIX=y -CONFIG_PCI_HOTPLUG=y CONFIG_WDT_IB700=y CONFIG_PC_SYSFW=y CONFIG_XEN_I386=$(CONFIG_XEN) diff --git a/device_tree.c b/device_tree.c index 69be9da8e..10cf3d0b6 100644 --- a/device_tree.c +++ b/device_tree.c @@ -21,6 +21,7 @@ #include "config.h" #include "qemu-common.h" #include "sysemu/device_tree.h" +#include "sysemu/sysemu.h" #include "hw/loader.h" #include "qemu/option.h" #include "qemu/config-file.h" @@ -239,15 +240,8 @@ uint32_t qemu_devtree_alloc_phandle(void *fdt) * which phandle id to start allocting phandles. */ if (!phandle) { - QemuOpts *machine_opts; - machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); - if (machine_opts) { - const char *phandle_start; - phandle_start = qemu_opt_get(machine_opts, "phandle_start"); - if (phandle_start) { - phandle = strtoul(phandle_start, NULL, 0); - } - } + phandle = qemu_opt_get_number(qemu_get_machine_opts(), + "phandle_start", 0); } if (!phandle) { @@ -307,15 +301,10 @@ int qemu_devtree_add_subnode(void *fdt, const char *name) void qemu_devtree_dumpdtb(void *fdt, int size) { - QemuOpts *machine_opts; - - machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); - if (machine_opts) { - const char *dumpdtb = qemu_opt_get(machine_opts, "dumpdtb"); - if (dumpdtb) { - /* Dump the dtb to a file and quit */ - exit(g_file_set_contents(dumpdtb, fdt, size, NULL) ? 0 : 1); - } - } + const char *dumpdtb = qemu_opt_get(qemu_get_machine_opts(), "dumpdtb"); + if (dumpdtb) { + /* Dump the dtb to a file and quit */ + exit(g_file_set_contents(dumpdtb, fdt, size, NULL) ? 0 : 1); + } } diff --git a/dma-helpers.c b/dma-helpers.c index 5afba4747..499550fc2 100644 --- a/dma-helpers.c +++ b/dma-helpers.c @@ -34,13 +34,16 @@ int dma_memory_set(AddressSpace *as, dma_addr_t addr, uint8_t c, dma_addr_t len) return error; } -void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint, AddressSpace *as) +void qemu_sglist_init(QEMUSGList *qsg, DeviceState *dev, int alloc_hint, + AddressSpace *as) { qsg->sg = g_malloc(alloc_hint * sizeof(ScatterGatherEntry)); qsg->nsg = 0; qsg->nalloc = alloc_hint; qsg->size = 0; qsg->as = as; + qsg->dev = dev; + object_ref(OBJECT(dev)); } void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len) @@ -57,6 +60,7 @@ void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len) void qemu_sglist_destroy(QEMUSGList *qsg) { + object_unref(OBJECT(qsg->dev)); g_free(qsg->sg); memset(qsg, 0, sizeof(*qsg)); } diff --git a/docs/atomics.txt b/docs/atomics.txt new file mode 100644 index 000000000..6f2997bc6 --- /dev/null +++ b/docs/atomics.txt @@ -0,0 +1,352 @@ +CPUs perform independent memory operations effectively in random order. +but this can be a problem for CPU-CPU interaction (including interactions +between QEMU and the guest). Multi-threaded programs use various tools +to instruct the compiler and the CPU to restrict the order to something +that is consistent with the expectations of the programmer. + +The most basic tool is locking. Mutexes, condition variables and +semaphores are used in QEMU, and should be the default approach to +synchronization. Anything else is considerably harder, but it's +also justified more often than one would like. The two tools that +are provided by qemu/atomic.h are memory barriers and atomic operations. + +Macros defined by qemu/atomic.h fall in three camps: + +- compiler barriers: barrier(); + +- weak atomic access and manual memory barriers: atomic_read(), + atomic_set(), smp_rmb(), smp_wmb(), smp_mb(), smp_read_barrier_depends(); + +- sequentially consistent atomic access: everything else. + + +COMPILER MEMORY BARRIER +======================= + +barrier() prevents the compiler from moving the memory accesses either +side of it to the other side. The compiler barrier has no direct effect +on the CPU, which may then reorder things however it wishes. + +barrier() is mostly used within qemu/atomic.h itself. On some +architectures, CPU guarantees are strong enough that blocking compiler +optimizations already ensures the correct order of execution. In this +case, qemu/atomic.h will reduce stronger memory barriers to simple +compiler barriers. + +Still, barrier() can be useful when writing code that can be interrupted +by signal handlers. + + +SEQUENTIALLY CONSISTENT ATOMIC ACCESS +===================================== + +Most of the operations in the qemu/atomic.h header ensure *sequential +consistency*, where "the result of any execution is the same as if the +operations of all the processors were executed in some sequential order, +and the operations of each individual processor appear in this sequence +in the order specified by its program". + +qemu/atomic.h provides the following set of atomic read-modify-write +operations: + + void atomic_inc(ptr) + void atomic_dec(ptr) + void atomic_add(ptr, val) + void atomic_sub(ptr, val) + void atomic_and(ptr, val) + void atomic_or(ptr, val) + + typeof(*ptr) atomic_fetch_inc(ptr) + typeof(*ptr) atomic_fetch_dec(ptr) + typeof(*ptr) atomic_fetch_add(ptr, val) + typeof(*ptr) atomic_fetch_sub(ptr, val) + typeof(*ptr) atomic_fetch_and(ptr, val) + typeof(*ptr) atomic_fetch_or(ptr, val) + typeof(*ptr) atomic_xchg(ptr, val + typeof(*ptr) atomic_cmpxchg(ptr, old, new) + +all of which return the old value of *ptr. These operations are +polymorphic; they operate on any type that is as wide as an int. + +Sequentially consistent loads and stores can be done using: + + atomic_fetch_add(ptr, 0) for loads + atomic_xchg(ptr, val) for stores + +However, they are quite expensive on some platforms, notably POWER and +ARM. Therefore, qemu/atomic.h provides two primitives with slightly +weaker constraints: + + typeof(*ptr) atomic_mb_read(ptr) + void atomic_mb_set(ptr, val) + +The semantics of these primitives map to Java volatile variables, +and are strongly related to memory barriers as used in the Linux +kernel (see below). + +As long as you use atomic_mb_read and atomic_mb_set, accesses cannot +be reordered with each other, and it is also not possible to reorder +"normal" accesses around them. + +However, and this is the important difference between +atomic_mb_read/atomic_mb_set and sequential consistency, it is important +for both threads to access the same volatile variable. It is not the +case that everything visible to thread A when it writes volatile field f +becomes visible to thread B after it reads volatile field g. The store +and load have to "match" (i.e., be performed on the same volatile +field) to achieve the right semantics. + + +These operations operate on any type that is as wide as an int or smaller. + + +WEAK ATOMIC ACCESS AND MANUAL MEMORY BARRIERS +============================================= + +Compared to sequentially consistent atomic access, programming with +weaker consistency models can be considerably more complicated. +In general, if the algorithm you are writing includes both writes +and reads on the same side, it is generally simpler to use sequentially +consistent primitives. + +When using this model, variables are accessed with atomic_read() and +atomic_set(), and restrictions to the ordering of accesses is enforced +using the smp_rmb(), smp_wmb(), smp_mb() and smp_read_barrier_depends() +memory barriers. + +atomic_read() and atomic_set() prevents the compiler from using +optimizations that might otherwise optimize accesses out of existence +on the one hand, or that might create unsolicited accesses on the other. +In general this should not have any effect, because the same compiler +barriers are already implied by memory barriers. However, it is useful +to do so, because it tells readers which variables are shared with +other threads, and which are local to the current thread or protected +by other, more mundane means. + +Memory barriers control the order of references to shared memory. +They come in four kinds: + +- smp_rmb() guarantees that all the LOAD operations specified before + the barrier will appear to happen before all the LOAD operations + specified after the barrier with respect to the other components of + the system. + + In other words, smp_rmb() puts a partial ordering on loads, but is not + required to have any effect on stores. + +- smp_wmb() guarantees that all the STORE operations specified before + the barrier will appear to happen before all the STORE operations + specified after the barrier with respect to the other components of + the system. + + In other words, smp_wmb() puts a partial ordering on stores, but is not + required to have any effect on loads. + +- smp_mb() guarantees that all the LOAD and STORE operations specified + before the barrier will appear to happen before all the LOAD and + STORE operations specified after the barrier with respect to the other + components of the system. + + smp_mb() puts a partial ordering on both loads and stores. It is + stronger than both a read and a write memory barrier; it implies both + smp_rmb() and smp_wmb(), but it also prevents STOREs coming before the + barrier from overtaking LOADs coming after the barrier and vice versa. + +- smp_read_barrier_depends() is a weaker kind of read barrier. On + most processors, whenever two loads are performed such that the + second depends on the result of the first (e.g., the first load + retrieves the address to which the second load will be directed), + the processor will guarantee that the first LOAD will appear to happen + before the second with respect to the other components of the system. + However, this is not always true---for example, it was not true on + Alpha processors. Whenever this kind of access happens to shared + memory (that is not protected by a lock), a read barrier is needed, + and smp_read_barrier_depends() can be used instead of smp_rmb(). + + Note that the first load really has to have a _data_ dependency and not + a control dependency. If the address for the second load is dependent + on the first load, but the dependency is through a conditional rather + than actually loading the address itself, then it's a _control_ + dependency and a full read barrier or better is required. + + +This is the set of barriers that is required *between* two atomic_read() +and atomic_set() operations to achieve sequential consistency: + + | 2nd operation | + |-----------------------------------------| + 1st operation | (after last) | atomic_read | atomic_set | + ---------------+--------------+-------------+------------| + (before first) | | none | smp_wmb() | + ---------------+--------------+-------------+------------| + atomic_read | smp_rmb() | smp_rmb()* | ** | + ---------------+--------------+-------------+------------| + atomic_set | none | smp_mb()*** | smp_wmb() | + ---------------+--------------+-------------+------------| + + * Or smp_read_barrier_depends(). + + ** This requires a load-store barrier. How to achieve this varies + depending on the machine, but in practice smp_rmb()+smp_wmb() + should have the desired effect. For example, on PowerPC the + lwsync instruction is a combined load-load, load-store and + store-store barrier. + + *** This requires a store-load barrier. On most machines, the only + way to achieve this is a full barrier. + + +You can see that the two possible definitions of atomic_mb_read() +and atomic_mb_set() are the following: + + 1) atomic_mb_read(p) = atomic_read(p); smp_rmb() + atomic_mb_set(p, v) = smp_wmb(); atomic_set(p, v); smp_mb() + + 2) atomic_mb_read(p) = smp_mb() atomic_read(p); smp_rmb() + atomic_mb_set(p, v) = smp_wmb(); atomic_set(p, v); + +Usually the former is used, because smp_mb() is expensive and a program +normally has more reads than writes. Therefore it makes more sense to +make atomic_mb_set() the more expensive operation. + +There are two common cases in which atomic_mb_read and atomic_mb_set +generate too many memory barriers, and thus it can be useful to manually +place barriers instead: + +- when a data structure has one thread that is always a writer + and one thread that is always a reader, manual placement of + memory barriers makes the write side faster. Furthermore, + correctness is easy to check for in this case using the "pairing" + trick that is explained below: + + thread 1 thread 1 + ------------------------- ------------------------ + (other writes) + smp_wmb() + atomic_mb_set(&a, x) atomic_set(&a, x) + smp_wmb() + atomic_mb_set(&b, y) atomic_set(&b, y) + + => + thread 2 thread 2 + ------------------------- ------------------------ + y = atomic_mb_read(&b) y = atomic_read(&b) + smp_rmb() + x = atomic_mb_read(&a) x = atomic_read(&a) + smp_rmb() + +- sometimes, a thread is accessing many variables that are otherwise + unrelated to each other (for example because, apart from the current + thread, exactly one other thread will read or write each of these + variables). In this case, it is possible to "hoist" the implicit + barriers provided by atomic_mb_read() and atomic_mb_set() outside + a loop. For example, the above definition atomic_mb_read() gives + the following transformation: + + n = 0; n = 0; + for (i = 0; i < 10; i++) => for (i = 0; i < 10; i++) + n += atomic_mb_read(&a[i]); n += atomic_read(&a[i]); + smp_rmb(); + + Similarly, atomic_mb_set() can be transformed as follows: + smp_mb(): + + smp_wmb(); + for (i = 0; i < 10; i++) => for (i = 0; i < 10; i++) + atomic_mb_set(&a[i], false); atomic_set(&a[i], false); + smp_mb(); + + +The two tricks can be combined. In this case, splitting a loop in +two lets you hoist the barriers out of the loops _and_ eliminate the +expensive smp_mb(): + + smp_wmb(); + for (i = 0; i < 10; i++) { => for (i = 0; i < 10; i++) + atomic_mb_set(&a[i], false); atomic_set(&a[i], false); + atomic_mb_set(&b[i], false); smb_wmb(); + } for (i = 0; i < 10; i++) + atomic_set(&a[i], false); + smp_mb(); + + The other thread can still use atomic_mb_read()/atomic_mb_set() + + +Memory barrier pairing +---------------------- + +A useful rule of thumb is that memory barriers should always, or almost +always, be paired with another barrier. In the case of QEMU, however, +note that the other barrier may actually be in a driver that runs in +the guest! + +For the purposes of pairing, smp_read_barrier_depends() and smp_rmb() +both count as read barriers. A read barriers shall pair with a write +barrier or a full barrier; a write barrier shall pair with a read +barrier or a full barrier. A full barrier can pair with anything. +For example: + + thread 1 thread 2 + =============== =============== + a = 1; + smp_wmb(); + b = 2; x = b; + smp_rmb(); + y = a; + +Note that the "writing" thread are accessing the variables in the +opposite order as the "reading" thread. This is expected: stores +before the write barrier will normally match the loads after the +read barrier, and vice versa. The same is true for more than 2 +access and for data dependency barriers: + + thread 1 thread 2 + =============== =============== + b[2] = 1; + smp_wmb(); + x->i = 2; + smp_wmb(); + a = x; x = a; + smp_read_barrier_depends(); + y = x->i; + smp_read_barrier_depends(); + z = b[y]; + +smp_wmb() also pairs with atomic_mb_read(), and smp_rmb() also pairs +with atomic_mb_set(). + + +COMPARISON WITH LINUX KERNEL MEMORY BARRIERS +============================================ + +Here is a list of differences between Linux kernel atomic operations +and memory barriers, and the equivalents in QEMU: + +- atomic operations in Linux are always on a 32-bit int type and + use a boxed atomic_t type; atomic operations in QEMU are polymorphic + and use normal C types. + +- atomic_read and atomic_set in Linux give no guarantee at all; + atomic_read and atomic_set in QEMU include a compiler barrier + (similar to the ACCESS_ONCE macro in Linux). + +- most atomic read-modify-write operations in Linux return void; + in QEMU, all of them return the old value of the variable. + +- different atomic read-modify-write operations in Linux imply + a different set of memory barriers; in QEMU, all of them enforce + sequential consistency, which means they imply full memory barriers + before and after the operation. + +- Linux does not have an equivalent of atomic_mb_read() and + atomic_mb_set(). In particular, note that set_mb() is a little + weaker than atomic_mb_set(). + + +SOURCES +======= + +* Documentation/memory-barriers.txt from the Linux kernel + +* "The JSR-133 Cookbook for Compiler Writers", available at + http://g.oswego.edu/dl/jmm/cookbook.html diff --git a/dump.c b/dump.c index c812cfaf2..6a3a72a1f 100644 --- a/dump.c +++ b/dump.c @@ -275,13 +275,11 @@ static inline int cpu_index(CPUState *cpu) static int write_elf64_notes(DumpState *s) { - CPUArchState *env; CPUState *cpu; int ret; int id; - for (env = first_cpu; env != NULL; env = env->next_cpu) { - cpu = ENV_GET_CPU(env); + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { id = cpu_index(cpu); ret = cpu_write_elf64_note(fd_write_vmcore, cpu, id, s); if (ret < 0) { @@ -290,7 +288,7 @@ static int write_elf64_notes(DumpState *s) } } - for (env = first_cpu; env != NULL; env = env->next_cpu) { + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { ret = cpu_write_elf64_qemunote(fd_write_vmcore, cpu, s); if (ret < 0) { dump_error(s, "dump: failed to write CPU status.\n"); @@ -327,13 +325,11 @@ static int write_elf32_note(DumpState *s) static int write_elf32_notes(DumpState *s) { - CPUArchState *env; CPUState *cpu; int ret; int id; - for (env = first_cpu; env != NULL; env = env->next_cpu) { - cpu = ENV_GET_CPU(env); + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { id = cpu_index(cpu); ret = cpu_write_elf32_note(fd_write_vmcore, cpu, id, s); if (ret < 0) { @@ -342,7 +338,7 @@ static int write_elf32_notes(DumpState *s) } } - for (env = first_cpu; env != NULL; env = env->next_cpu) { + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { ret = cpu_write_elf32_qemunote(fd_write_vmcore, cpu, s); if (ret < 0) { dump_error(s, "dump: failed to write CPU status.\n"); @@ -705,7 +701,7 @@ static ram_addr_t get_start_block(DumpState *s) static int dump_init(DumpState *s, int fd, bool paging, bool has_filter, int64_t begin, int64_t length, Error **errp) { - CPUArchState *env; + CPUState *cpu; int nr_cpus; Error *err = NULL; int ret; @@ -738,7 +734,7 @@ static int dump_init(DumpState *s, int fd, bool paging, bool has_filter, */ cpu_synchronize_all_states(); nr_cpus = 0; - for (env = first_cpu; env != NULL; env = env->next_cpu) { + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { nr_cpus++; } diff --git a/exec.c b/exec.c index c49806cd5..c99a8839c 100644 --- a/exec.c +++ b/exec.c @@ -31,6 +31,7 @@ #include "hw/qdev.h" #include "qemu/osdep.h" #include "sysemu/kvm.h" +#include "sysemu/sysemu.h" #include "hw/xen/xen.h" #include "qemu/timer.h" #include "qemu/config-file.h" @@ -53,7 +54,6 @@ //#define DEBUG_SUBPAGE #if !defined(CONFIG_USER_ONLY) -int phys_ram_fd; static int in_migration; RAMList ram_list = { .blocks = QTAILQ_HEAD_INITIALIZER(ram_list.blocks) }; @@ -69,10 +69,10 @@ static MemoryRegion io_mem_unassigned; #endif -CPUArchState *first_cpu; +CPUState *first_cpu; /* current CPU in the current thread. It is only valid inside cpu_exec() */ -DEFINE_TLS(CPUArchState *,cpu_single_env); +DEFINE_TLS(CPUState *, current_cpu); /* 0 = Do not count executed instructions. 1 = Precise instruction counting. 2 = Adaptive rate instruction counting. */ @@ -88,12 +88,15 @@ struct PhysPageEntry { uint16_t ptr : 15; }; +typedef PhysPageEntry Node[L2_SIZE]; + struct AddressSpaceDispatch { /* This is a multi-level map on the physical address space. * The bottom level has pointers to MemoryRegionSections. */ PhysPageEntry phys_map; - MemoryListener listener; + Node *nodes; + MemoryRegionSection *sections; AddressSpace *as; }; @@ -105,16 +108,22 @@ typedef struct subpage_t { uint16_t sub_section[TARGET_PAGE_SIZE]; } subpage_t; -static MemoryRegionSection *phys_sections; -static unsigned phys_sections_nb, phys_sections_nb_alloc; -static uint16_t phys_section_unassigned; -static uint16_t phys_section_notdirty; -static uint16_t phys_section_rom; -static uint16_t phys_section_watch; +#define PHYS_SECTION_UNASSIGNED 0 +#define PHYS_SECTION_NOTDIRTY 1 +#define PHYS_SECTION_ROM 2 +#define PHYS_SECTION_WATCH 3 + +typedef struct PhysPageMap { + unsigned sections_nb; + unsigned sections_nb_alloc; + unsigned nodes_nb; + unsigned nodes_nb_alloc; + Node *nodes; + MemoryRegionSection *sections; +} PhysPageMap; -/* Simple allocator for PhysPageEntry nodes */ -static PhysPageEntry (*phys_map_nodes)[L2_SIZE]; -static unsigned phys_map_nodes_nb, phys_map_nodes_nb_alloc; +static PhysPageMap *prev_map; +static PhysPageMap next_map; #define PHYS_MAP_NODE_NIL (((uint16_t)~0) >> 1) @@ -129,13 +138,13 @@ static MemoryRegion io_mem_watch; static void phys_map_node_reserve(unsigned nodes) { - if (phys_map_nodes_nb + nodes > phys_map_nodes_nb_alloc) { - typedef PhysPageEntry Node[L2_SIZE]; - phys_map_nodes_nb_alloc = MAX(phys_map_nodes_nb_alloc * 2, 16); - phys_map_nodes_nb_alloc = MAX(phys_map_nodes_nb_alloc, - phys_map_nodes_nb + nodes); - phys_map_nodes = g_renew(Node, phys_map_nodes, - phys_map_nodes_nb_alloc); + if (next_map.nodes_nb + nodes > next_map.nodes_nb_alloc) { + next_map.nodes_nb_alloc = MAX(next_map.nodes_nb_alloc * 2, + 16); + next_map.nodes_nb_alloc = MAX(next_map.nodes_nb_alloc, + next_map.nodes_nb + nodes); + next_map.nodes = g_renew(Node, next_map.nodes, + next_map.nodes_nb_alloc); } } @@ -144,22 +153,16 @@ static uint16_t phys_map_node_alloc(void) unsigned i; uint16_t ret; - ret = phys_map_nodes_nb++; + ret = next_map.nodes_nb++; assert(ret != PHYS_MAP_NODE_NIL); - assert(ret != phys_map_nodes_nb_alloc); + assert(ret != next_map.nodes_nb_alloc); for (i = 0; i < L2_SIZE; ++i) { - phys_map_nodes[ret][i].is_leaf = 0; - phys_map_nodes[ret][i].ptr = PHYS_MAP_NODE_NIL; + next_map.nodes[ret][i].is_leaf = 0; + next_map.nodes[ret][i].ptr = PHYS_MAP_NODE_NIL; } return ret; } -static void phys_map_nodes_reset(void) -{ - phys_map_nodes_nb = 0; -} - - static void phys_page_set_level(PhysPageEntry *lp, hwaddr *index, hwaddr *nb, uint16_t leaf, int level) @@ -170,15 +173,15 @@ static void phys_page_set_level(PhysPageEntry *lp, hwaddr *index, if (!lp->is_leaf && lp->ptr == PHYS_MAP_NODE_NIL) { lp->ptr = phys_map_node_alloc(); - p = phys_map_nodes[lp->ptr]; + p = next_map.nodes[lp->ptr]; if (level == 0) { for (i = 0; i < L2_SIZE; i++) { p[i].is_leaf = 1; - p[i].ptr = phys_section_unassigned; + p[i].ptr = PHYS_SECTION_UNASSIGNED; } } } else { - p = phys_map_nodes[lp->ptr]; + p = next_map.nodes[lp->ptr]; } lp = &p[(*index >> (level * L2_BITS)) & (L2_SIZE - 1)]; @@ -205,20 +208,20 @@ static void phys_page_set(AddressSpaceDispatch *d, phys_page_set_level(&d->phys_map, &index, &nb, leaf, P_L2_LEVELS - 1); } -static MemoryRegionSection *phys_page_find(AddressSpaceDispatch *d, hwaddr index) +static MemoryRegionSection *phys_page_find(PhysPageEntry lp, hwaddr index, + Node *nodes, MemoryRegionSection *sections) { - PhysPageEntry lp = d->phys_map; PhysPageEntry *p; int i; for (i = P_L2_LEVELS - 1; i >= 0 && !lp.is_leaf; i--) { if (lp.ptr == PHYS_MAP_NODE_NIL) { - return &phys_sections[phys_section_unassigned]; + return §ions[PHYS_SECTION_UNASSIGNED]; } - p = phys_map_nodes[lp.ptr]; + p = nodes[lp.ptr]; lp = p[(index >> (i * L2_BITS)) & (L2_SIZE - 1)]; } - return &phys_sections[lp.ptr]; + return §ions[lp.ptr]; } bool memory_region_is_unassigned(MemoryRegion *mr) @@ -227,29 +230,30 @@ bool memory_region_is_unassigned(MemoryRegion *mr) && mr != &io_mem_watch; } -static MemoryRegionSection *address_space_lookup_region(AddressSpace *as, +static MemoryRegionSection *address_space_lookup_region(AddressSpaceDispatch *d, hwaddr addr, bool resolve_subpage) { MemoryRegionSection *section; subpage_t *subpage; - section = phys_page_find(as->dispatch, addr >> TARGET_PAGE_BITS); + section = phys_page_find(d->phys_map, addr >> TARGET_PAGE_BITS, + d->nodes, d->sections); if (resolve_subpage && section->mr->subpage) { subpage = container_of(section->mr, subpage_t, iomem); - section = &phys_sections[subpage->sub_section[SUBPAGE_IDX(addr)]]; + section = &d->sections[subpage->sub_section[SUBPAGE_IDX(addr)]]; } return section; } static MemoryRegionSection * -address_space_translate_internal(AddressSpace *as, hwaddr addr, hwaddr *xlat, +address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *xlat, hwaddr *plen, bool resolve_subpage) { MemoryRegionSection *section; Int128 diff; - section = address_space_lookup_region(as, addr, resolve_subpage); + section = address_space_lookup_region(d, addr, resolve_subpage); /* Compute offset within MemoryRegionSection */ addr -= section->offset_within_address_space; @@ -271,7 +275,7 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr, hwaddr len = *plen; for (;;) { - section = address_space_translate_internal(as, addr, &addr, plen, true); + section = address_space_translate_internal(as->dispatch, addr, &addr, plen, true); mr = section->mr; if (!mr->iommu_ops) { @@ -300,7 +304,7 @@ address_space_translate_for_iotlb(AddressSpace *as, hwaddr addr, hwaddr *xlat, hwaddr *plen) { MemoryRegionSection *section; - section = address_space_translate_internal(as, addr, xlat, plen, false); + section = address_space_translate_internal(as->dispatch, addr, xlat, plen, false); assert(!section->mr->iommu_ops); return section; @@ -347,27 +351,26 @@ const VMStateDescription vmstate_cpu_common = { CPUState *qemu_get_cpu(int index) { - CPUArchState *env = first_cpu; - CPUState *cpu = NULL; + CPUState *cpu = first_cpu; - while (env) { - cpu = ENV_GET_CPU(env); + while (cpu) { if (cpu->cpu_index == index) { break; } - env = env->next_cpu; + cpu = cpu->next_cpu; } - return env ? cpu : NULL; + return cpu; } void qemu_for_each_cpu(void (*func)(CPUState *cpu, void *data), void *data) { - CPUArchState *env = first_cpu; + CPUState *cpu; - while (env) { - func(ENV_GET_CPU(env), data); - env = env->next_cpu; + cpu = first_cpu; + while (cpu) { + func(cpu, data); + cpu = cpu->next_cpu; } } @@ -375,17 +378,17 @@ void cpu_exec_init(CPUArchState *env) { CPUState *cpu = ENV_GET_CPU(env); CPUClass *cc = CPU_GET_CLASS(cpu); - CPUArchState **penv; + CPUState **pcpu; int cpu_index; #if defined(CONFIG_USER_ONLY) cpu_list_lock(); #endif - env->next_cpu = NULL; - penv = &first_cpu; + cpu->next_cpu = NULL; + pcpu = &first_cpu; cpu_index = 0; - while (*penv != NULL) { - penv = &(*penv)->next_cpu; + while (*pcpu != NULL) { + pcpu = &(*pcpu)->next_cpu; cpu_index++; } cpu->cpu_index = cpu_index; @@ -395,7 +398,7 @@ void cpu_exec_init(CPUArchState *env) #ifndef CONFIG_USER_ONLY cpu->thread_id = qemu_get_thread_id(); #endif - *penv = env; + *pcpu = cpu; #if defined(CONFIG_USER_ONLY) cpu_list_unlock(); #endif @@ -614,7 +617,7 @@ void cpu_abort(CPUArchState *env, const char *fmt, ...) qemu_log("qemu: fatal: "); qemu_log_vprintf(fmt, ap2); qemu_log("\n"); - log_cpu_state(env, CPU_DUMP_FPU | CPU_DUMP_CCOP); + log_cpu_state(cpu, CPU_DUMP_FPU | CPU_DUMP_CCOP); qemu_log_flush(); qemu_log_close(); } @@ -634,7 +637,6 @@ void cpu_abort(CPUArchState *env, const char *fmt, ...) CPUArchState *cpu_copy(CPUArchState *env) { CPUArchState *new_env = cpu_init(env->cpu_model_str); - CPUArchState *next_cpu = new_env->next_cpu; #if defined(TARGET_HAS_ICE) CPUBreakpoint *bp; CPUWatchpoint *wp; @@ -642,9 +644,6 @@ CPUArchState *cpu_copy(CPUArchState *env) memcpy(new_env, env, sizeof(CPUArchState)); - /* Preserve chaining. */ - new_env->next_cpu = next_cpu; - /* Clone all break/watchpoints. Note: Once we support ptrace with hw-debug register access, make sure BP_CPU break/watchpoints are handled correctly on clone. */ @@ -723,12 +722,12 @@ hwaddr memory_region_section_get_iotlb(CPUArchState *env, iotlb = (memory_region_get_ram_addr(section->mr) & TARGET_PAGE_MASK) + xlat; if (!section->readonly) { - iotlb |= phys_section_notdirty; + iotlb |= PHYS_SECTION_NOTDIRTY; } else { - iotlb |= phys_section_rom; + iotlb |= PHYS_SECTION_ROM; } } else { - iotlb = section - phys_sections; + iotlb = section - address_space_memory.dispatch->sections; iotlb += xlat; } @@ -738,7 +737,7 @@ hwaddr memory_region_section_get_iotlb(CPUArchState *env, if (vaddr == (wp->vaddr & TARGET_PAGE_MASK)) { /* Avoid trapping reads of pages with a write breakpoint. */ if ((prot & PAGE_WRITE) || (wp->flags & BP_MEM_READ)) { - iotlb = phys_section_watch + paddr; + iotlb = PHYS_SECTION_WATCH + paddr; *address |= TLB_MMIO; break; } @@ -754,44 +753,6 @@ hwaddr memory_region_section_get_iotlb(CPUArchState *env, static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end, uint16_t section); static subpage_t *subpage_init(AddressSpace *as, hwaddr base); -static void destroy_page_desc(uint16_t section_index) -{ - MemoryRegionSection *section = &phys_sections[section_index]; - MemoryRegion *mr = section->mr; - - if (mr->subpage) { - subpage_t *subpage = container_of(mr, subpage_t, iomem); - memory_region_destroy(&subpage->iomem); - g_free(subpage); - } -} - -static void destroy_l2_mapping(PhysPageEntry *lp, unsigned level) -{ - unsigned i; - PhysPageEntry *p; - - if (lp->ptr == PHYS_MAP_NODE_NIL) { - return; - } - - p = phys_map_nodes[lp->ptr]; - for (i = 0; i < L2_SIZE; ++i) { - if (!p[i].is_leaf) { - destroy_l2_mapping(&p[i], level - 1); - } else { - destroy_page_desc(p[i].ptr); - } - } - lp->is_leaf = 0; - lp->ptr = PHYS_MAP_NODE_NIL; -} - -static void destroy_all_mappings(AddressSpaceDispatch *d) -{ - destroy_l2_mapping(&d->phys_map, P_L2_LEVELS - 1); - phys_map_nodes_reset(); -} static uint16_t phys_section_add(MemoryRegionSection *section) { @@ -799,20 +760,39 @@ static uint16_t phys_section_add(MemoryRegionSection *section) * pointer to produce the iotlb entries. Thus it should * never overflow into the page-aligned value. */ - assert(phys_sections_nb < TARGET_PAGE_SIZE); + assert(next_map.sections_nb < TARGET_PAGE_SIZE); + + if (next_map.sections_nb == next_map.sections_nb_alloc) { + next_map.sections_nb_alloc = MAX(next_map.sections_nb_alloc * 2, + 16); + next_map.sections = g_renew(MemoryRegionSection, next_map.sections, + next_map.sections_nb_alloc); + } + next_map.sections[next_map.sections_nb] = *section; + memory_region_ref(section->mr); + return next_map.sections_nb++; +} - if (phys_sections_nb == phys_sections_nb_alloc) { - phys_sections_nb_alloc = MAX(phys_sections_nb_alloc * 2, 16); - phys_sections = g_renew(MemoryRegionSection, phys_sections, - phys_sections_nb_alloc); +static void phys_section_destroy(MemoryRegion *mr) +{ + memory_region_unref(mr); + + if (mr->subpage) { + subpage_t *subpage = container_of(mr, subpage_t, iomem); + memory_region_destroy(&subpage->iomem); + g_free(subpage); } - phys_sections[phys_sections_nb] = *section; - return phys_sections_nb++; } -static void phys_sections_clear(void) +static void phys_sections_free(PhysPageMap *map) { - phys_sections_nb = 0; + while (map->sections_nb > 0) { + MemoryRegionSection *section = &map->sections[--map->sections_nb]; + phys_section_destroy(section->mr); + } + g_free(map->sections); + g_free(map->nodes); + g_free(map); } static void register_subpage(AddressSpaceDispatch *d, MemoryRegionSection *section) @@ -820,7 +800,8 @@ static void register_subpage(AddressSpaceDispatch *d, MemoryRegionSection *secti subpage_t *subpage; hwaddr base = section->offset_within_address_space & TARGET_PAGE_MASK; - MemoryRegionSection *existing = phys_page_find(d, base >> TARGET_PAGE_BITS); + MemoryRegionSection *existing = phys_page_find(d->phys_map, base >> TARGET_PAGE_BITS, + next_map.nodes, next_map.sections); MemoryRegionSection subsection = { .offset_within_address_space = base, .size = int128_make64(TARGET_PAGE_SIZE), @@ -857,7 +838,8 @@ static void register_multipage(AddressSpaceDispatch *d, static void mem_add(MemoryListener *listener, MemoryRegionSection *section) { - AddressSpaceDispatch *d = container_of(listener, AddressSpaceDispatch, listener); + AddressSpace *as = container_of(listener, AddressSpace, dispatch_listener); + AddressSpaceDispatch *d = as->next_dispatch; MemoryRegionSection now = *section, remain = *section; Int128 page_size = int128_make64(TARGET_PAGE_SIZE); @@ -1057,12 +1039,10 @@ ram_addr_t last_ram_offset(void) static void qemu_ram_setup_dump(void *addr, ram_addr_t size) { int ret; - QemuOpts *machine_opts; /* Use MADV_DONTDUMP, if user doesn't want the guest memory in the core */ - machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); - if (machine_opts && - !qemu_opt_get_bool(machine_opts, "dump-guest-core", true)) { + if (!qemu_opt_get_bool(qemu_get_machine_opts(), + "dump-guest-core", true)) { ret = qemu_madvise(addr, size, QEMU_MADV_DONTDUMP); if (ret) { perror("qemu_madvise"); @@ -1109,10 +1089,7 @@ void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev) static int memory_try_enable_merging(void *addr, size_t len) { - QemuOpts *opts; - - opts = qemu_opts_find(qemu_find_opts("machine"), 0); - if (opts && !qemu_opt_get_bool(opts, "mem-merge", true)) { + if (!qemu_opt_get_bool(qemu_get_machine_opts(), "mem-merge", true)) { /* disabled by the user */ return 0; } @@ -1316,15 +1293,7 @@ void qemu_ram_remap(ram_addr_t addr, ram_addr_t length) } #endif /* !_WIN32 */ -/* Return a host pointer to ram allocated with qemu_ram_alloc. - With the exception of the softmmu code in this file, this should - only be used for local memory (e.g. video ram) that the device owns, - and knows it isn't going to access beyond the end of the block. - - It should not be used for general purpose DMA. - Use cpu_physical_memory_map/cpu_physical_memory_rw instead. - */ -void *qemu_get_ram_ptr(ram_addr_t addr) +static RAMBlock *qemu_get_ram_block(ram_addr_t addr) { RAMBlock *block; @@ -1344,6 +1313,21 @@ void *qemu_get_ram_ptr(ram_addr_t addr) found: ram_list.mru_block = block; + return block; +} + +/* Return a host pointer to ram allocated with qemu_ram_alloc. + With the exception of the softmmu code in this file, this should + only be used for local memory (e.g. video ram) that the device owns, + and knows it isn't going to access beyond the end of the block. + + It should not be used for general purpose DMA. + Use cpu_physical_memory_map/cpu_physical_memory_rw instead. + */ +void *qemu_get_ram_ptr(ram_addr_t addr) +{ + RAMBlock *block = qemu_get_ram_block(addr); + if (xen_enabled()) { /* We need to check if the requested address is in the RAM * because we don't want to map the entire memory in QEMU. @@ -1418,14 +1402,21 @@ static void *qemu_ram_ptr_length(ram_addr_t addr, ram_addr_t *size) } } -int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr) +/* Some of the softmmu routines need to translate from a host pointer + (typically a TLB entry) back to a ram offset. */ +MemoryRegion *qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr) { RAMBlock *block; uint8_t *host = ptr; if (xen_enabled()) { *ram_addr = xen_ram_addr_from_mapcache(ptr); - return 0; + return qemu_get_ram_block(*ram_addr)->mr; + } + + block = ram_list.mru_block; + if (block && block->host && host - block->host < block->length) { + goto found; } QTAILQ_FOREACH(block, &ram_list.blocks, next) { @@ -1434,25 +1425,15 @@ int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr) continue; } if (host - block->host < block->length) { - *ram_addr = block->offset + (host - block->host); - return 0; + goto found; } } - return -1; -} - -/* Some of the softmmu routines need to translate from a host pointer - (typically a TLB entry) back to a ram offset. */ -ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr) -{ - ram_addr_t ram_addr; + return NULL; - if (qemu_ram_addr_from_host(ptr, &ram_addr)) { - fprintf(stderr, "Bad ram pointer %p\n", ptr); - abort(); - } - return ram_addr; +found: + *ram_addr = block->offset + (host - block->host); + return block->mr; } static void notdirty_mem_write(void *opaque, hwaddr ram_addr, @@ -1481,8 +1462,10 @@ static void notdirty_mem_write(void *opaque, hwaddr ram_addr, cpu_physical_memory_set_dirty_flags(ram_addr, dirty_flags); /* we remove the notdirty callback only if the code has been flushed */ - if (dirty_flags == 0xff) - tlb_set_dirty(cpu_single_env, cpu_single_env->mem_io_vaddr); + if (dirty_flags == 0xff) { + CPUArchState *env = current_cpu->env_ptr; + tlb_set_dirty(env, env->mem_io_vaddr); + } } static bool notdirty_mem_accepts(void *opaque, hwaddr addr, @@ -1500,7 +1483,7 @@ static const MemoryRegionOps notdirty_mem_ops = { /* Generate a debug exception if a watchpoint has been hit. */ static void check_watchpoint(int offset, int len_mask, int flags) { - CPUArchState *env = cpu_single_env; + CPUArchState *env = current_cpu->env_ptr; target_ulong pc, cs_base; target_ulong vaddr; CPUWatchpoint *wp; @@ -1673,14 +1656,14 @@ static subpage_t *subpage_init(AddressSpace *as, hwaddr base) mmio->as = as; mmio->base = base; - memory_region_init_io(&mmio->iomem, &subpage_ops, mmio, + memory_region_init_io(&mmio->iomem, NULL, &subpage_ops, mmio, "subpage", TARGET_PAGE_SIZE); mmio->iomem.subpage = true; #if defined(DEBUG_SUBPAGE) printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__, mmio, base, TARGET_PAGE_SIZE, subpage_memory); #endif - subpage_register(mmio, 0, TARGET_PAGE_SIZE-1, phys_section_unassigned); + subpage_register(mmio, 0, TARGET_PAGE_SIZE-1, PHYS_SECTION_UNASSIGNED); return mmio; } @@ -1699,45 +1682,79 @@ static uint16_t dummy_section(MemoryRegion *mr) MemoryRegion *iotlb_to_region(hwaddr index) { - return phys_sections[index & ~TARGET_PAGE_MASK].mr; + return address_space_memory.dispatch->sections[index & ~TARGET_PAGE_MASK].mr; } static void io_mem_init(void) { - memory_region_init_io(&io_mem_rom, &unassigned_mem_ops, NULL, "rom", UINT64_MAX); - memory_region_init_io(&io_mem_unassigned, &unassigned_mem_ops, NULL, + memory_region_init_io(&io_mem_rom, NULL, &unassigned_mem_ops, NULL, "rom", UINT64_MAX); + memory_region_init_io(&io_mem_unassigned, NULL, &unassigned_mem_ops, NULL, "unassigned", UINT64_MAX); - memory_region_init_io(&io_mem_notdirty, ¬dirty_mem_ops, NULL, + memory_region_init_io(&io_mem_notdirty, NULL, ¬dirty_mem_ops, NULL, "notdirty", UINT64_MAX); - memory_region_init_io(&io_mem_watch, &watch_mem_ops, NULL, + memory_region_init_io(&io_mem_watch, NULL, &watch_mem_ops, NULL, "watch", UINT64_MAX); } static void mem_begin(MemoryListener *listener) { - AddressSpaceDispatch *d = container_of(listener, AddressSpaceDispatch, listener); + AddressSpace *as = container_of(listener, AddressSpace, dispatch_listener); + AddressSpaceDispatch *d = g_new(AddressSpaceDispatch, 1); - destroy_all_mappings(d); - d->phys_map.ptr = PHYS_MAP_NODE_NIL; + d->phys_map = (PhysPageEntry) { .ptr = PHYS_MAP_NODE_NIL, .is_leaf = 0 }; + d->as = as; + as->next_dispatch = d; +} + +static void mem_commit(MemoryListener *listener) +{ + AddressSpace *as = container_of(listener, AddressSpace, dispatch_listener); + AddressSpaceDispatch *cur = as->dispatch; + AddressSpaceDispatch *next = as->next_dispatch; + + next->nodes = next_map.nodes; + next->sections = next_map.sections; + + as->dispatch = next; + g_free(cur); } static void core_begin(MemoryListener *listener) { - phys_sections_clear(); - phys_section_unassigned = dummy_section(&io_mem_unassigned); - phys_section_notdirty = dummy_section(&io_mem_notdirty); - phys_section_rom = dummy_section(&io_mem_rom); - phys_section_watch = dummy_section(&io_mem_watch); + uint16_t n; + + prev_map = g_new(PhysPageMap, 1); + *prev_map = next_map; + + memset(&next_map, 0, sizeof(next_map)); + n = dummy_section(&io_mem_unassigned); + assert(n == PHYS_SECTION_UNASSIGNED); + n = dummy_section(&io_mem_notdirty); + assert(n == PHYS_SECTION_NOTDIRTY); + n = dummy_section(&io_mem_rom); + assert(n == PHYS_SECTION_ROM); + n = dummy_section(&io_mem_watch); + assert(n == PHYS_SECTION_WATCH); +} + +/* This listener's commit run after the other AddressSpaceDispatch listeners'. + * All AddressSpaceDispatch instances have switched to the next map. + */ +static void core_commit(MemoryListener *listener) +{ + phys_sections_free(prev_map); } static void tcg_commit(MemoryListener *listener) { - CPUArchState *env; + CPUState *cpu; /* since each CPU stores ram addresses in its TLB cache, we must reset the modified entries */ /* XXX: slow ! */ - for(env = first_cpu; env != NULL; env = env->next_cpu) { + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { + CPUArchState *env = cpu->env_ptr; + tlb_flush(env, 1); } } @@ -1752,65 +1769,36 @@ static void core_log_global_stop(MemoryListener *listener) cpu_physical_memory_set_dirty_tracking(0); } -static void io_region_add(MemoryListener *listener, - MemoryRegionSection *section) -{ - MemoryRegionIORange *mrio = g_new(MemoryRegionIORange, 1); - - mrio->mr = section->mr; - mrio->offset = section->offset_within_region; - iorange_init(&mrio->iorange, &memory_region_iorange_ops, - section->offset_within_address_space, - int128_get64(section->size)); - ioport_register(&mrio->iorange); -} - -static void io_region_del(MemoryListener *listener, - MemoryRegionSection *section) -{ - isa_unassign_ioport(section->offset_within_address_space, - int128_get64(section->size)); -} - static MemoryListener core_memory_listener = { .begin = core_begin, + .commit = core_commit, .log_global_start = core_log_global_start, .log_global_stop = core_log_global_stop, .priority = 1, }; -static MemoryListener io_memory_listener = { - .region_add = io_region_add, - .region_del = io_region_del, - .priority = 0, -}; - static MemoryListener tcg_memory_listener = { .commit = tcg_commit, }; void address_space_init_dispatch(AddressSpace *as) { - AddressSpaceDispatch *d = g_new(AddressSpaceDispatch, 1); - - d->phys_map = (PhysPageEntry) { .ptr = PHYS_MAP_NODE_NIL, .is_leaf = 0 }; - d->listener = (MemoryListener) { + as->dispatch = NULL; + as->dispatch_listener = (MemoryListener) { .begin = mem_begin, + .commit = mem_commit, .region_add = mem_add, .region_nop = mem_add, .priority = 0, }; - d->as = as; - as->dispatch = d; - memory_listener_register(&d->listener, as); + memory_listener_register(&as->dispatch_listener, as); } void address_space_destroy_dispatch(AddressSpace *as) { AddressSpaceDispatch *d = as->dispatch; - memory_listener_unregister(&d->listener); - destroy_l2_mapping(&d->phys_map, P_L2_LEVELS - 1); + memory_listener_unregister(&as->dispatch_listener); g_free(d); as->dispatch = NULL; } @@ -1818,15 +1806,14 @@ void address_space_destroy_dispatch(AddressSpace *as) static void memory_map_init(void) { system_memory = g_malloc(sizeof(*system_memory)); - memory_region_init(system_memory, "system", INT64_MAX); + memory_region_init(system_memory, NULL, "system", INT64_MAX); address_space_init(&address_space_memory, system_memory, "memory"); system_io = g_malloc(sizeof(*system_io)); - memory_region_init(system_io, "io", 65536); + memory_region_init(system_io, NULL, "io", 65536); address_space_init(&address_space_io, system_io, "I/O"); memory_listener_register(&core_memory_listener, &address_space_memory); - memory_listener_register(&io_memory_listener, &address_space_io); memory_listener_register(&tcg_memory_listener, &address_space_memory); } @@ -1909,15 +1896,37 @@ static inline bool memory_access_is_direct(MemoryRegion *mr, bool is_write) return false; } -static inline int memory_access_size(MemoryRegion *mr, int l, hwaddr addr) +static int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr) { - if (l >= 4 && (((addr & 3) == 0 || mr->ops->impl.unaligned))) { - return 4; + unsigned access_size_min = mr->ops->impl.min_access_size; + unsigned access_size_max = mr->ops->impl.max_access_size; + + /* Regions are assumed to support 1-4 byte accesses unless + otherwise specified. */ + if (access_size_min == 0) { + access_size_min = 1; + } + if (access_size_max == 0) { + access_size_max = 4; } - if (l >= 2 && (((addr & 1) == 0) || mr->ops->impl.unaligned)) { - return 2; + + /* Bound the maximum access by the alignment of the address. */ + if (!mr->ops->impl.unaligned) { + unsigned align_size_max = addr & -addr; + if (align_size_max != 0 && align_size_max < access_size_max) { + access_size_max = align_size_max; + } } - return 1; + + /* Don't attempt accesses larger than the maximum. */ + if (l > access_size_max) { + l = access_size_max; + } + /* ??? The users of this function are wrong, not supporting minimums larger + than the remaining length. C.f. memory.c:access_with_adjusted_size. */ + assert(l >= access_size_min); + + return l; } bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf, @@ -1937,20 +1946,31 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf, if (is_write) { if (!memory_access_is_direct(mr, is_write)) { l = memory_access_size(mr, l, addr1); - /* XXX: could force cpu_single_env to NULL to avoid + /* XXX: could force current_cpu to NULL to avoid potential bugs */ - if (l == 4) { + switch (l) { + case 8: + /* 64 bit write access */ + val = ldq_p(buf); + error |= io_mem_write(mr, addr1, val, 8); + break; + case 4: /* 32 bit write access */ val = ldl_p(buf); error |= io_mem_write(mr, addr1, val, 4); - } else if (l == 2) { + break; + case 2: /* 16 bit write access */ val = lduw_p(buf); error |= io_mem_write(mr, addr1, val, 2); - } else { + break; + case 1: /* 8 bit write access */ val = ldub_p(buf); error |= io_mem_write(mr, addr1, val, 1); + break; + default: + abort(); } } else { addr1 += memory_region_get_ram_addr(mr); @@ -1963,18 +1983,29 @@ bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf, if (!memory_access_is_direct(mr, is_write)) { /* I/O case */ l = memory_access_size(mr, l, addr1); - if (l == 4) { + switch (l) { + case 8: + /* 64 bit read access */ + error |= io_mem_read(mr, addr1, &val, 8); + stq_p(buf, val); + break; + case 4: /* 32 bit read access */ error |= io_mem_read(mr, addr1, &val, 4); stl_p(buf, val); - } else if (l == 2) { + break; + case 2: /* 16 bit read access */ error |= io_mem_read(mr, addr1, &val, 2); stw_p(buf, val); - } else { + break; + case 1: /* 8 bit read access */ error |= io_mem_read(mr, addr1, &val, 1); stb_p(buf, val); + break; + default: + abort(); } } else { /* RAM case */ @@ -2039,6 +2070,7 @@ void cpu_physical_memory_write_rom(hwaddr addr, } typedef struct { + MemoryRegion *mr; void *buffer; hwaddr addr; hwaddr len; @@ -2118,47 +2150,56 @@ void *address_space_map(AddressSpace *as, bool is_write) { hwaddr len = *plen; - hwaddr todo = 0; - hwaddr l, xlat; - MemoryRegion *mr; - ram_addr_t raddr = RAM_ADDR_MAX; - ram_addr_t rlen; - void *ret; + hwaddr done = 0; + hwaddr l, xlat, base; + MemoryRegion *mr, *this_mr; + ram_addr_t raddr; - while (len > 0) { - l = len; - mr = address_space_translate(as, addr, &xlat, &l, is_write); - - if (!memory_access_is_direct(mr, is_write)) { - if (todo || bounce.buffer) { - break; - } - bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE); - bounce.addr = addr; - bounce.len = l; - if (!is_write) { - address_space_read(as, addr, bounce.buffer, l); - } + if (len == 0) { + return NULL; + } - *plen = l; - return bounce.buffer; + l = len; + mr = address_space_translate(as, addr, &xlat, &l, is_write); + if (!memory_access_is_direct(mr, is_write)) { + if (bounce.buffer) { + return NULL; } - if (!todo) { - raddr = memory_region_get_ram_addr(mr) + xlat; - } else { - if (memory_region_get_ram_addr(mr) + xlat != raddr + todo) { - break; - } + bounce.buffer = qemu_memalign(TARGET_PAGE_SIZE, TARGET_PAGE_SIZE); + bounce.addr = addr; + bounce.len = l; + + memory_region_ref(mr); + bounce.mr = mr; + if (!is_write) { + address_space_read(as, addr, bounce.buffer, l); } + *plen = l; + return bounce.buffer; + } + + base = xlat; + raddr = memory_region_get_ram_addr(mr); + + for (;;) { len -= l; addr += l; - todo += l; + done += l; + if (len == 0) { + break; + } + + l = len; + this_mr = address_space_translate(as, addr, &xlat, &l, is_write); + if (this_mr != mr || xlat != base + done) { + break; + } } - rlen = todo; - ret = qemu_ram_ptr_length(raddr, &rlen); - *plen = rlen; - return ret; + + memory_region_ref(mr); + *plen = done; + return qemu_ram_ptr_length(raddr + base, plen); } /* Unmaps a memory region previously mapped by address_space_map(). @@ -2169,8 +2210,12 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len, int is_write, hwaddr access_len) { if (buffer != bounce.buffer) { + MemoryRegion *mr; + ram_addr_t addr1; + + mr = qemu_ram_addr_from_host(buffer, &addr1); + assert(mr != NULL); if (is_write) { - ram_addr_t addr1 = qemu_ram_addr_from_host_nofail(buffer); while (access_len) { unsigned l; l = TARGET_PAGE_SIZE; @@ -2184,6 +2229,7 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len, if (xen_enabled()) { xen_invalidate_map_cache_entry(buffer); } + memory_region_unref(mr); return; } if (is_write) { @@ -2191,6 +2237,7 @@ void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len, } qemu_vfree(bounce.buffer); bounce.buffer = NULL; + memory_region_unref(bounce.mr); cpu_notify_map_clients(); } diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c index 6eaf36dbf..ccfec139a 100644 --- a/fsdev/qemu-fsdev.c +++ b/fsdev/qemu-fsdev.c @@ -76,6 +76,8 @@ int qemu_fsdev_add(QemuOpts *opts) if (fsle->fse.ops->parse_opts) { if (fsle->fse.ops->parse_opts(opts, &fsle->fse)) { + g_free(fsle->fse.fsdev_id); + g_free(fsle); return -1; } } diff --git a/gdbstub.c b/gdbstub.c index 3101a4340..0ee82a944 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -1839,6 +1839,7 @@ static const char *get_feature_xml(const char *p, const char **newp) /* Generate the XML description for this CPU. */ if (!target_xml[0]) { GDBRegisterState *r; + CPUArchState *env = first_cpu->env_ptr; snprintf(target_xml, sizeof(target_xml), "" @@ -1847,7 +1848,7 @@ static const char *get_feature_xml(const char *p, const char **newp) "", GDB_CORE_XML); - for (r = first_cpu->gdb_regs; r; r = r->next) { + for (r = env->gdb_regs; r; r = r->next) { pstrcat(target_xml, sizeof(target_xml), "xml); pstrcat(target_xml, sizeof(target_xml), "\"/>"); @@ -1949,6 +1950,7 @@ static const int xlat_gdb_type[] = { static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type) { + CPUState *cpu; CPUArchState *env; int err = 0; @@ -1958,7 +1960,8 @@ static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type) switch (type) { case GDB_BREAKPOINT_SW: case GDB_BREAKPOINT_HW: - for (env = first_cpu; env != NULL; env = env->next_cpu) { + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { + env = cpu->env_ptr; err = cpu_breakpoint_insert(env, addr, BP_GDB, NULL); if (err) break; @@ -1968,7 +1971,8 @@ static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type) case GDB_WATCHPOINT_WRITE: case GDB_WATCHPOINT_READ: case GDB_WATCHPOINT_ACCESS: - for (env = first_cpu; env != NULL; env = env->next_cpu) { + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { + env = cpu->env_ptr; err = cpu_watchpoint_insert(env, addr, len, xlat_gdb_type[type], NULL); if (err) @@ -1983,6 +1987,7 @@ static int gdb_breakpoint_insert(target_ulong addr, target_ulong len, int type) static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type) { + CPUState *cpu; CPUArchState *env; int err = 0; @@ -1992,7 +1997,8 @@ static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type) switch (type) { case GDB_BREAKPOINT_SW: case GDB_BREAKPOINT_HW: - for (env = first_cpu; env != NULL; env = env->next_cpu) { + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { + env = cpu->env_ptr; err = cpu_breakpoint_remove(env, addr, BP_GDB); if (err) break; @@ -2002,7 +2008,8 @@ static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type) case GDB_WATCHPOINT_WRITE: case GDB_WATCHPOINT_READ: case GDB_WATCHPOINT_ACCESS: - for (env = first_cpu; env != NULL; env = env->next_cpu) { + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { + env = cpu->env_ptr; err = cpu_watchpoint_remove(env, addr, len, xlat_gdb_type[type]); if (err) break; @@ -2016,14 +2023,16 @@ static int gdb_breakpoint_remove(target_ulong addr, target_ulong len, int type) static void gdb_breakpoint_remove_all(void) { + CPUState *cpu; CPUArchState *env; if (kvm_enabled()) { - kvm_remove_all_breakpoints(gdbserver_state->c_cpu); + kvm_remove_all_breakpoints(ENV_GET_CPU(gdbserver_state->c_cpu)); return; } - for (env = first_cpu; env != NULL; env = env->next_cpu) { + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { + env = cpu->env_ptr; cpu_breakpoint_remove_all(env, BP_GDB); #ifndef CONFIG_USER_ONLY cpu_watchpoint_remove_all(env, BP_GDB); @@ -2073,11 +2082,13 @@ static CPUArchState *find_cpu(uint32_t thread_id) { CPUState *cpu; - cpu = qemu_get_cpu(thread_id); - if (cpu == NULL) { - return NULL; + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { + if (cpu_index(cpu) == thread_id) { + return cpu->env_ptr; + } } - return cpu->env_ptr; + + return NULL; } static int gdb_handle_packet(GDBState *s, const char *line_buf) @@ -2390,7 +2401,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) put_packet(s, "QC1"); break; } else if (strcmp(p,"fThreadInfo") == 0) { - s->query_cpu = first_cpu; + s->query_cpu = first_cpu->env_ptr; goto report_cpuinfo; } else if (strcmp(p,"sThreadInfo") == 0) { report_cpuinfo: @@ -2398,7 +2409,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf) snprintf(buf, sizeof(buf), "m%x", cpu_index(ENV_GET_CPU(s->query_cpu))); put_packet(s, buf); - s->query_cpu = s->query_cpu->next_cpu; + s->query_cpu = ENV_GET_CPU(s->query_cpu)->next_cpu->env_ptr; } else put_packet(s, "l"); break; @@ -2865,8 +2876,8 @@ static void gdb_accept(void) socket_set_nodelay(fd); s = g_malloc0(sizeof(GDBState)); - s->c_cpu = first_cpu; - s->g_cpu = first_cpu; + s->c_cpu = first_cpu->env_ptr; + s->g_cpu = first_cpu->env_ptr; s->fd = fd; gdb_has_xml = 0; @@ -3050,8 +3061,8 @@ int gdbserver_start(const char *device) mon_chr = s->mon_chr; memset(s, 0, sizeof(GDBState)); } - s->c_cpu = first_cpu; - s->g_cpu = first_cpu; + s->c_cpu = first_cpu->env_ptr; + s->g_cpu = first_cpu->env_ptr; s->chr = chr; s->state = chr ? RS_IDLE : RS_INACTIVE; s->mon_chr = mon_chr; diff --git a/hmp-commands.hx b/hmp-commands.hx index 915b0d16f..8c6b91a9c 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1056,6 +1056,26 @@ STEXI @findex drive_mirror Start mirroring a block device's writes to a new destination, using the specified target. +ETEXI + + { + .name = "drive_backup", + .args_type = "reuse:-n,full:-f,device:B,target:s,format:s?", + .params = "[-n] [-f] device target [format]", + .help = "initiates a point-in-time\n\t\t\t" + "copy for a device. The device's contents are\n\t\t\t" + "copied to the new image file, excluding data that\n\t\t\t" + "is written after the command is started.\n\t\t\t" + "The -n flag requests QEMU to reuse the image found\n\t\t\t" + "in new-image-file, instead of recreating it from scratch.\n\t\t\t" + "The -f flag requests QEMU to copy the whole disk,\n\t\t\t" + "so that the result does not need a backing file.\n\t\t\t", + .mhandler.cmd = hmp_drive_backup, + }, +STEXI +@item drive_backup +@findex drive_backup +Start a point-in-time copy of a block device to a specificed target. ETEXI { @@ -1077,7 +1097,7 @@ STEXI Add drive to PCI storage controller. ETEXI -#if defined(TARGET_I386) +#if defined(CONFIG_PCI_HOTPLUG_OLD) { .name = "pci_add", .args_type = "pci_addr:s,type:s,opts:s?", @@ -1093,7 +1113,7 @@ STEXI Hot-add PCI device. ETEXI -#if defined(TARGET_I386) +#if defined(CONFIG_PCI_HOTPLUG_OLD) { .name = "pci_del", .args_type = "pci_addr:s", diff --git a/hmp.c b/hmp.c index 2daed430d..dc4d8d453 100644 --- a/hmp.c +++ b/hmp.c @@ -907,6 +907,34 @@ void hmp_drive_mirror(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, &errp); } +void hmp_drive_backup(Monitor *mon, const QDict *qdict) +{ + const char *device = qdict_get_str(qdict, "device"); + const char *filename = qdict_get_str(qdict, "target"); + const char *format = qdict_get_try_str(qdict, "format"); + int reuse = qdict_get_try_bool(qdict, "reuse", 0); + int full = qdict_get_try_bool(qdict, "full", 0); + enum NewImageMode mode; + Error *errp = NULL; + + if (!filename) { + error_set(&errp, QERR_MISSING_PARAMETER, "target"); + hmp_handle_error(mon, &errp); + return; + } + + if (reuse) { + mode = NEW_IMAGE_MODE_EXISTING; + } else { + mode = NEW_IMAGE_MODE_ABSOLUTE_PATHS; + } + + qmp_drive_backup(device, filename, !!format, format, + full ? MIRROR_SYNC_MODE_FULL : MIRROR_SYNC_MODE_TOP, + true, mode, false, 0, false, 0, false, 0, &errp); + hmp_handle_error(mon, &errp); +} + void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict) { const char *device = qdict_get_str(qdict, "device"); diff --git a/hmp.h b/hmp.h index 56d2e92aa..6c3bdcd4c 100644 --- a/hmp.h +++ b/hmp.h @@ -55,6 +55,7 @@ void hmp_balloon(Monitor *mon, const QDict *qdict); void hmp_block_resize(Monitor *mon, const QDict *qdict); void hmp_snapshot_blkdev(Monitor *mon, const QDict *qdict); void hmp_drive_mirror(Monitor *mon, const QDict *qdict); +void hmp_drive_backup(Monitor *mon, const QDict *qdict); void hmp_migrate_cancel(Monitor *mon, const QDict *qdict); void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict); void hmp_migrate_set_speed(Monitor *mon, const QDict *qdict); diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c index dc6f4e404..35e2af47b 100644 --- a/hw/9pfs/virtio-9p-device.c +++ b/hw/9pfs/virtio-9p-device.c @@ -68,14 +68,14 @@ static int virtio_9p_device_init(VirtIODevice *vdev) fprintf(stderr, "Virtio-9p device couldn't find fsdev with the " "id = %s\n", s->fsconf.fsdev_id ? s->fsconf.fsdev_id : "NULL"); - return -1; + goto out; } if (!s->fsconf.tag) { /* we haven't specified a mount_tag */ fprintf(stderr, "fsdev with id %s needs mount_tag arguments\n", s->fsconf.fsdev_id); - return -1; + goto out; } s->ctx.export_flags = fse->export_flags; @@ -85,10 +85,10 @@ static int virtio_9p_device_init(VirtIODevice *vdev) if (len > MAX_TAG_LEN - 1) { fprintf(stderr, "mount tag '%s' (%d bytes) is longer than " "maximum (%d bytes)", s->fsconf.tag, len, MAX_TAG_LEN - 1); - return -1; + goto out; } - s->tag = strdup(s->fsconf.tag); + s->tag = g_strdup(s->fsconf.tag); s->ctx.uid = -1; s->ops = fse->ops; @@ -99,11 +99,11 @@ static int virtio_9p_device_init(VirtIODevice *vdev) if (s->ops->init(&s->ctx) < 0) { fprintf(stderr, "Virtio-9p Failed to initialize fs-driver with id:%s" " and export path:%s\n", s->fsconf.fsdev_id, s->ctx.fs_root); - return -1; + goto out; } if (v9fs_init_worker_threads() < 0) { fprintf(stderr, "worker thread initialization failed\n"); - return -1; + goto out; } /* @@ -115,18 +115,26 @@ static int virtio_9p_device_init(VirtIODevice *vdev) if (s->ops->name_to_path(&s->ctx, NULL, "/", &path) < 0) { fprintf(stderr, "error in converting name to path %s", strerror(errno)); - return -1; + goto out; } if (s->ops->lstat(&s->ctx, &path, &stat)) { fprintf(stderr, "share path %s does not exist\n", fse->path); - return -1; + goto out; } else if (!S_ISDIR(stat.st_mode)) { fprintf(stderr, "share path %s is not a directory\n", fse->path); - return -1; + goto out; } v9fs_path_free(&path); return 0; +out: + g_free(s->ctx.fs_root); + g_free(s->tag); + virtio_cleanup(vdev); + v9fs_path_free(&path); + + return -1; + } /* virtio-9p device */ diff --git a/hw/acpi/core.c b/hw/acpi/core.c index 42eeace6f..b07fedac5 100644 --- a/hw/acpi/core.c +++ b/hw/acpi/core.c @@ -419,7 +419,8 @@ void acpi_pm1_evt_init(ACPIREGS *ar, acpi_update_sci_fn update_sci, MemoryRegion *parent) { ar->pm1.evt.update_sci = update_sci; - memory_region_init_io(&ar->pm1.evt.io, &acpi_pm_evt_ops, ar, "acpi-evt", 4); + memory_region_init_io(&ar->pm1.evt.io, memory_region_owner(parent), + &acpi_pm_evt_ops, ar, "acpi-evt", 4); memory_region_add_subregion(parent, 0, &ar->pm1.evt.io); } @@ -481,7 +482,8 @@ void acpi_pm_tmr_init(ACPIREGS *ar, acpi_update_sci_fn update_sci, { ar->tmr.update_sci = update_sci; ar->tmr.timer = qemu_new_timer_ns(vm_clock, acpi_pm_tmr_timer, ar); - memory_region_init_io(&ar->tmr.io, &acpi_pm_tmr_ops, ar, "acpi-tmr", 4); + memory_region_init_io(&ar->tmr.io, memory_region_owner(parent), + &acpi_pm_tmr_ops, ar, "acpi-tmr", 4); memory_region_add_subregion(parent, 8, &ar->tmr.io); } @@ -552,7 +554,8 @@ void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent, uint8_t s4_val) ar->pm1.cnt.s4_val = s4_val; ar->wakeup.notify = acpi_notify_wakeup; qemu_register_wakeup_notifier(&ar->wakeup); - memory_region_init_io(&ar->pm1.cnt.io, &acpi_pm_cnt_ops, ar, "acpi-cnt", 2); + memory_region_init_io(&ar->pm1.cnt.io, memory_region_owner(parent), + &acpi_pm_cnt_ops, ar, "acpi-cnt", 2); memory_region_add_subregion(parent, 4, &ar->pm1.cnt.io); } diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c index 4a17f32b9..3fb443d06 100644 --- a/hw/acpi/ich9.c +++ b/hw/acpi/ich9.c @@ -205,7 +205,7 @@ static void pm_powerdown_req(Notifier *n, void *opaque) void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm, qemu_irq sci_irq) { - memory_region_init(&pm->io, "ich9-pm", ICH9_PMIO_SIZE); + memory_region_init(&pm->io, OBJECT(lpc_pci), "ich9-pm", ICH9_PMIO_SIZE); memory_region_set_enabled(&pm->io, false); memory_region_add_subregion(pci_address_space_io(lpc_pci), 0, &pm->io); @@ -215,12 +215,12 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm, acpi_pm1_cnt_init(&pm->acpi_regs, &pm->io, 2); acpi_gpe_init(&pm->acpi_regs, ICH9_PMIO_GPE0_LEN); - memory_region_init_io(&pm->io_gpe, &ich9_gpe_ops, pm, "apci-gpe0", - ICH9_PMIO_GPE0_LEN); + memory_region_init_io(&pm->io_gpe, OBJECT(lpc_pci), &ich9_gpe_ops, pm, + "apci-gpe0", ICH9_PMIO_GPE0_LEN); memory_region_add_subregion(&pm->io, ICH9_PMIO_GPE0_STS, &pm->io_gpe); - memory_region_init_io(&pm->io_smi, &ich9_smi_ops, pm, "apci-smi", - 8); + memory_region_init_io(&pm->io_smi, OBJECT(lpc_pci), &ich9_smi_ops, pm, + "apci-smi", 8); memory_region_add_subregion(&pm->io, ICH9_PMIO_SMI_EN, &pm->io_smi); pm->irq = sci_irq; diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index 756df3bee..948ea8795 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -383,14 +383,15 @@ static void piix4_pm_powerdown_req(Notifier *n, void *opaque) static void piix4_pm_machine_ready(Notifier *n, void *opaque) { PIIX4PMState *s = container_of(n, PIIX4PMState, machine_ready); + MemoryRegion *io_as = pci_address_space_io(&s->dev); uint8_t *pci_conf; pci_conf = s->dev.config; - pci_conf[0x5f] = (isa_is_ioport_assigned(0x378) ? 0x80 : 0) | 0x10; + pci_conf[0x5f] = 0x10 | + (memory_region_present(io_as, 0x378) ? 0x80 : 0); pci_conf[0x63] = 0x60; - pci_conf[0x67] = (isa_is_ioport_assigned(0x3f8) ? 0x08 : 0) | - (isa_is_ioport_assigned(0x2f8) ? 0x90 : 0); - + pci_conf[0x67] = (memory_region_present(io_as, 0x3f8) ? 0x08 : 0) | + (memory_region_present(io_as, 0x2f8) ? 0x90 : 0); } static int piix4_pm_initfn(PCIDevice *dev) @@ -423,7 +424,7 @@ static int piix4_pm_initfn(PCIDevice *dev) memory_region_add_subregion(pci_address_space_io(dev), s->smb_io_base, &s->smb.io); - memory_region_init(&s->io, "piix4-pm", 64); + memory_region_init(&s->io, OBJECT(s), "piix4-pm", 64); memory_region_set_enabled(&s->io, false); memory_region_add_subregion(pci_address_space_io(dev), 0, &s->io); @@ -670,19 +671,19 @@ static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, static void piix4_acpi_system_hot_add_init(MemoryRegion *parent, PCIBus *bus, PIIX4PMState *s) { - memory_region_init_io(&s->io_gpe, &piix4_gpe_ops, s, "apci-gpe0", - GPE_LEN); + memory_region_init_io(&s->io_gpe, OBJECT(s), &piix4_gpe_ops, s, + "acpi-gpe0", GPE_LEN); memory_region_add_subregion(parent, GPE_BASE, &s->io_gpe); - memory_region_init_io(&s->io_pci, &piix4_pci_ops, s, "apci-pci-hotplug", - PCI_HOTPLUG_SIZE); + memory_region_init_io(&s->io_pci, OBJECT(s), &piix4_pci_ops, s, + "acpi-pci-hotplug", PCI_HOTPLUG_SIZE); memory_region_add_subregion(parent, PCI_HOTPLUG_ADDR, &s->io_pci); pci_bus_hotplug(bus, piix4_device_hotplug, &s->dev.qdev); qemu_for_each_cpu(piix4_init_cpu_status, &s->gpe_cpu); - memory_region_init_io(&s->io_cpu, &cpu_hotplug_ops, s, "apci-cpu-hotplug", - PIIX4_PROC_LEN); + memory_region_init_io(&s->io_cpu, OBJECT(s), &cpu_hotplug_ops, s, + "acpi-cpu-hotplug", PIIX4_PROC_LEN); memory_region_add_subregion(parent, PIIX4_PROC_BASE, &s->io_cpu); s->cpu_added_notifier.notify = piix4_cpu_added_req; qemu_register_cpu_added_notifier(&s->cpu_added_notifier); diff --git a/hw/alpha/alpha_sys.h b/hw/alpha/alpha_sys.h index 50e7730ca..e11025b4b 100644 --- a/hw/alpha/alpha_sys.h +++ b/hw/alpha/alpha_sys.h @@ -14,7 +14,7 @@ PCIBus *typhoon_init(ram_addr_t, ISABus **, qemu_irq *, AlphaCPU *[4], pci_map_irq_fn); /* alpha_pci.c. */ -extern const MemoryRegionOps alpha_pci_bw_io_ops; +extern const MemoryRegionOps alpha_pci_ignore_ops; extern const MemoryRegionOps alpha_pci_conf1_ops; extern const MemoryRegionOps alpha_pci_iack_ops; diff --git a/hw/alpha/dp264.c b/hw/alpha/dp264.c index 8695efb8e..95fde615b 100644 --- a/hw/alpha/dp264.c +++ b/hw/alpha/dp264.c @@ -73,7 +73,9 @@ static void clipper_init(QEMUMachineInitArgs *args) pci_bus = typhoon_init(ram_size, &isa_bus, &rtc_irq, cpus, clipper_pci_map_irq); - rtc_init(isa_bus, 1980, rtc_irq); + /* Since we have an SRM-compatible PALcode, use the SRM epoch. */ + rtc_init(isa_bus, 1900, rtc_irq); + pit_init(isa_bus, 0x40, 0, NULL); isa_create_simple(isa_bus, "i8042"); @@ -89,7 +91,7 @@ static void clipper_init(QEMUMachineInitArgs *args) /* Network setup. e1000 is good enough, failing Tulip support. */ for (i = 0; i < nb_nics; i++) { - pci_nic_init_nofail(&nd_table[i], "e1000", NULL); + pci_nic_init_nofail(&nd_table[i], pci_bus, "e1000", NULL); } /* IDE disk setup. */ diff --git a/hw/alpha/pci.c b/hw/alpha/pci.c index 7327d488f..d839dd556 100644 --- a/hw/alpha/pci.c +++ b/hw/alpha/pci.c @@ -12,50 +12,32 @@ #include "sysemu/sysemu.h" -/* PCI IO reads/writes, to byte-word addressable memory. */ -/* ??? Doesn't handle multiple PCI busses. */ +/* Fallback for unassigned PCI I/O operations. Avoids MCHK. */ -static uint64_t bw_io_read(void *opaque, hwaddr addr, unsigned size) +static uint64_t ignore_read(void *opaque, hwaddr addr, unsigned size) { - switch (size) { - case 1: - return cpu_inb(addr); - case 2: - return cpu_inw(addr); - case 4: - return cpu_inl(addr); - } - abort(); + return 0; } -static void bw_io_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) +static void ignore_write(void *opaque, hwaddr addr, uint64_t v, unsigned size) { - switch (size) { - case 1: - cpu_outb(addr, val); - break; - case 2: - cpu_outw(addr, val); - break; - case 4: - cpu_outl(addr, val); - break; - default: - abort(); - } } -const MemoryRegionOps alpha_pci_bw_io_ops = { - .read = bw_io_read, - .write = bw_io_write, +const MemoryRegionOps alpha_pci_ignore_ops = { + .read = ignore_read, + .write = ignore_write, .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 1, + .max_access_size = 8, + }, .impl = { .min_access_size = 1, - .max_access_size = 4, + .max_access_size = 8, }, }; + /* PCI config space reads/writes, to byte-word addressable memory. */ static uint64_t bw_conf1_read(void *opaque, hwaddr addr, unsigned size) diff --git a/hw/alpha/typhoon.c b/hw/alpha/typhoon.c index 207dcad2a..3d7a1cd8e 100644 --- a/hw/alpha/typhoon.c +++ b/hw/alpha/typhoon.c @@ -51,9 +51,6 @@ typedef struct TyphoonState { TyphoonPchip pchip; MemoryRegion dchip_region; MemoryRegion ram_region; - - /* QEMU emulation state. */ - uint32_t latch_tmp; } TyphoonState; /* Called when one of DRIR or DIM changes. */ @@ -72,15 +69,10 @@ static void cpu_irq_change(AlphaCPU *cpu, uint64_t req) static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size) { - CPUAlphaState *env = cpu_single_env; + CPUState *cpu = current_cpu; TyphoonState *s = opaque; - CPUState *cpu; uint64_t ret = 0; - if (addr & 4) { - return s->latch_tmp; - } - switch (addr) { case 0x0000: /* CSC: Cchip System Configuration Register. */ @@ -95,7 +87,6 @@ static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size) case 0x0080: /* MISC: Miscellaneous Register. */ - cpu = ENV_GET_CPU(env); ret = s->cchip.misc | (cpu->cpu_index & 3); break; @@ -197,12 +188,10 @@ static uint64_t cchip_read(void *opaque, hwaddr addr, unsigned size) break; default: - cpu = CPU(alpha_env_get_cpu(cpu_single_env)); cpu_unassigned_access(cpu, addr, false, false, 0, size); return -1; } - s->latch_tmp = ret >> 32; return ret; } @@ -215,13 +204,8 @@ static uint64_t dchip_read(void *opaque, hwaddr addr, unsigned size) static uint64_t pchip_read(void *opaque, hwaddr addr, unsigned size) { TyphoonState *s = opaque; - CPUState *cs; uint64_t ret = 0; - if (addr & 4) { - return s->latch_tmp; - } - switch (addr) { case 0x0000: /* WSBA0: Window Space Base Address Register. */ @@ -302,29 +286,18 @@ static uint64_t pchip_read(void *opaque, hwaddr addr, unsigned size) break; default: - cs = CPU(alpha_env_get_cpu(cpu_single_env)); - cpu_unassigned_access(cs, addr, false, false, 0, size); + cpu_unassigned_access(current_cpu, addr, false, false, 0, size); return -1; } - s->latch_tmp = ret >> 32; return ret; } static void cchip_write(void *opaque, hwaddr addr, - uint64_t v32, unsigned size) + uint64_t val, unsigned size) { TyphoonState *s = opaque; - CPUState *cpu_single_cpu = CPU(alpha_env_get_cpu(cpu_single_env)); - uint64_t val, oldval, newval; - - if (addr & 4) { - val = v32 << 32 | s->latch_tmp; - addr ^= 4; - } else { - s->latch_tmp = v32; - return; - } + uint64_t oldval, newval; switch (addr) { case 0x0000: @@ -465,7 +438,7 @@ static void cchip_write(void *opaque, hwaddr addr, break; default: - cpu_unassigned_access(cpu_single_cpu, addr, true, false, 0, size); + cpu_unassigned_access(current_cpu, addr, true, false, 0, size); return; } } @@ -477,19 +450,10 @@ static void dchip_write(void *opaque, hwaddr addr, } static void pchip_write(void *opaque, hwaddr addr, - uint64_t v32, unsigned size) + uint64_t val, unsigned size) { TyphoonState *s = opaque; - CPUState *cs; - uint64_t val, oldval; - - if (addr & 4) { - val = v32 << 32 | s->latch_tmp; - addr ^= 4; - } else { - s->latch_tmp = v32; - return; - } + uint64_t oldval; switch (addr) { case 0x0000: @@ -582,8 +546,7 @@ static void pchip_write(void *opaque, hwaddr addr, break; default: - cs = CPU(alpha_env_get_cpu(cpu_single_env)); - cpu_unassigned_access(cs, addr, true, false, 0, size); + cpu_unassigned_access(current_cpu, addr, true, false, 0, size); return; } } @@ -593,12 +556,12 @@ static const MemoryRegionOps cchip_ops = { .write = cchip_write, .endianness = DEVICE_LITTLE_ENDIAN, .valid = { - .min_access_size = 4, /* ??? Should be 8. */ + .min_access_size = 8, .max_access_size = 8, }, .impl = { - .min_access_size = 4, - .max_access_size = 4, + .min_access_size = 8, + .max_access_size = 8, }, }; @@ -607,11 +570,11 @@ static const MemoryRegionOps dchip_ops = { .write = dchip_write, .endianness = DEVICE_LITTLE_ENDIAN, .valid = { - .min_access_size = 4, /* ??? Should be 8. */ + .min_access_size = 8, .max_access_size = 8, }, .impl = { - .min_access_size = 4, + .min_access_size = 8, .max_access_size = 8, }, }; @@ -621,12 +584,12 @@ static const MemoryRegionOps pchip_ops = { .write = pchip_write, .endianness = DEVICE_LITTLE_ENDIAN, .valid = { - .min_access_size = 4, /* ??? Should be 8. */ + .min_access_size = 8, .max_access_size = 8, }, .impl = { - .min_access_size = 4, - .max_access_size = 4, + .min_access_size = 8, + .max_access_size = 8, }, }; @@ -713,7 +676,6 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus, const uint64_t MB = 1024 * 1024; const uint64_t GB = 1024 * MB; MemoryRegion *addr_space = get_system_memory(); - MemoryRegion *addr_space_io = get_system_io(); DeviceState *dev; TyphoonState *s; PCIHostState *phb; @@ -741,7 +703,7 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus, /* Main memory region, 0x00.0000.0000. Real hardware supports 32GB, but the address space hole reserved at this point is 8TB. */ - memory_region_init_ram(&s->ram_region, "ram", ram_size); + memory_region_init_ram(&s->ram_region, OBJECT(s), "ram", ram_size); vmstate_register_ram_global(&s->ram_region); memory_region_add_subregion(addr_space, 0, &s->ram_region); @@ -750,48 +712,49 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus, the flash ROM. I'm not sure that we need to implement it at all. */ /* Pchip0 CSRs, 0x801.8000.0000, 256MB. */ - memory_region_init_io(&s->pchip.region, &pchip_ops, s, "pchip0", 256*MB); + memory_region_init_io(&s->pchip.region, OBJECT(s), &pchip_ops, s, "pchip0", + 256*MB); memory_region_add_subregion(addr_space, 0x80180000000ULL, &s->pchip.region); /* Cchip CSRs, 0x801.A000.0000, 256MB. */ - memory_region_init_io(&s->cchip.region, &cchip_ops, s, "cchip0", 256*MB); + memory_region_init_io(&s->cchip.region, OBJECT(s), &cchip_ops, s, "cchip0", + 256*MB); memory_region_add_subregion(addr_space, 0x801a0000000ULL, &s->cchip.region); /* Dchip CSRs, 0x801.B000.0000, 256MB. */ - memory_region_init_io(&s->dchip_region, &dchip_ops, s, "dchip0", 256*MB); + memory_region_init_io(&s->dchip_region, OBJECT(s), &dchip_ops, s, "dchip0", + 256*MB); memory_region_add_subregion(addr_space, 0x801b0000000ULL, &s->dchip_region); /* Pchip0 PCI memory, 0x800.0000.0000, 4GB. */ - memory_region_init(&s->pchip.reg_mem, "pci0-mem", 4*GB); + memory_region_init(&s->pchip.reg_mem, OBJECT(s), "pci0-mem", 4*GB); memory_region_add_subregion(addr_space, 0x80000000000ULL, &s->pchip.reg_mem); /* Pchip0 PCI I/O, 0x801.FC00.0000, 32MB. */ - /* ??? Ideally we drop the "system" i/o space on the floor and give the - PCI subsystem the full address space reserved by the chipset. - We can't do that until the MEM and IO paths in memory.c are unified. */ - memory_region_init_io(&s->pchip.reg_io, &alpha_pci_bw_io_ops, NULL, - "pci0-io", 32*MB); + memory_region_init_io(&s->pchip.reg_io, OBJECT(s), &alpha_pci_ignore_ops, + NULL, "pci0-io", 32*MB); memory_region_add_subregion(addr_space, 0x801fc000000ULL, &s->pchip.reg_io); b = pci_register_bus(dev, "pci", typhoon_set_irq, sys_map_irq, s, - &s->pchip.reg_mem, addr_space_io, 0, 64, TYPE_PCI_BUS); + &s->pchip.reg_mem, &s->pchip.reg_io, + 0, 64, TYPE_PCI_BUS); phb->bus = b; /* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB. */ - memory_region_init_io(&s->pchip.reg_iack, &alpha_pci_iack_ops, b, - "pci0-iack", 64*MB); + memory_region_init_io(&s->pchip.reg_iack, OBJECT(s), &alpha_pci_iack_ops, + b, "pci0-iack", 64*MB); memory_region_add_subregion(addr_space, 0x801f8000000ULL, &s->pchip.reg_iack); /* Pchip0 PCI configuration, 0x801.FE00.0000, 16MB. */ - memory_region_init_io(&s->pchip.reg_conf, &alpha_pci_conf1_ops, b, - "pci0-conf", 16*MB); + memory_region_init_io(&s->pchip.reg_conf, OBJECT(s), &alpha_pci_conf1_ops, + b, "pci0-conf", 16*MB); memory_region_add_subregion(addr_space, 0x801fe000000ULL, &s->pchip.reg_conf); @@ -809,7 +772,7 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus, { qemu_irq isa_pci_irq, *isa_irqs; - *isa_bus = isa_bus_new(NULL, addr_space_io); + *isa_bus = isa_bus_new(NULL, &s->pchip.reg_io); isa_pci_irq = *qemu_allocate_irqs(typhoon_set_isa_irq, s, 1); isa_irqs = i8259_init(*isa_bus, isa_pci_irq); isa_bus_irqs(*isa_bus, isa_irqs); diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c index 93422bc7b..5b22e847a 100644 --- a/hw/arm/armv7m.c +++ b/hw/arm/armv7m.c @@ -124,8 +124,8 @@ static int bitband_init(SysBusDevice *dev) { BitBandState *s = FROM_SYSBUS(BitBandState, dev); - memory_region_init_io(&s->iomem, &bitband_ops, &s->base, "bitband", - 0x02000000); + memory_region_init_io(&s->iomem, OBJECT(s), &bitband_ops, &s->base, + "bitband", 0x02000000); sysbus_init_mmio(dev, &s->iomem); return 0; } @@ -203,11 +203,11 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem, #endif /* Flash programming is done via the SCU, so pretend it is ROM. */ - memory_region_init_ram(flash, "armv7m.flash", flash_size); + memory_region_init_ram(flash, NULL, "armv7m.flash", flash_size); vmstate_register_ram_global(flash); memory_region_set_readonly(flash, true); memory_region_add_subregion(address_space_mem, 0, flash); - memory_region_init_ram(sram, "armv7m.sram", sram_size); + memory_region_init_ram(sram, NULL, "armv7m.sram", sram_size); vmstate_register_ram_global(sram); memory_region_add_subregion(address_space_mem, 0x20000000, sram); armv7m_bitband_init(); @@ -247,7 +247,7 @@ qemu_irq *armv7m_init(MemoryRegion *address_space_mem, /* Hack to map an additional page of ram at the top of the address space. This stops qemu complaining about executing code outside RAM when returning from an exception. */ - memory_region_init_ram(hack, "armv7m.hack", 0x1000); + memory_region_init_ram(hack, NULL, "armv7m.hack", 0x1000); vmstate_register_ram_global(hack); memory_region_add_subregion(address_space_mem, 0xfffff000, hack); diff --git a/hw/arm/boot.c b/hw/arm/boot.c index 7c0090ff4..a2e4032f4 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -333,7 +333,7 @@ static void do_cpu_reset(void *opaque) env->regs[15] = info->entry & 0xfffffffe; env->thumb = info->entry & 1; } else { - if (env == first_cpu) { + if (CPU(cpu) == first_cpu) { env->regs[15] = info->loader_start; if (!info->dtb_filename) { if (old_param) { @@ -351,7 +351,7 @@ static void do_cpu_reset(void *opaque) void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info) { - CPUARMState *env = &cpu->env; + CPUState *cs = CPU(cpu); int kernel_size; int initrd_size; int n; @@ -359,7 +359,6 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info) uint64_t elf_entry; hwaddr entry; int big_endian; - QemuOpts *machine_opts; /* Load the kernel. */ if (!info->kernel_filename) { @@ -367,12 +366,7 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info) exit(1); } - machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); - if (machine_opts) { - info->dtb_filename = qemu_opt_get(machine_opts, "dtb"); - } else { - info->dtb_filename = NULL; - } + info->dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb"); if (!info->secondary_cpu_reset_hook) { info->secondary_cpu_reset_hook = default_reset_secondary; @@ -476,9 +470,9 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info) } info->is_linux = is_linux; - for (; env; env = env->next_cpu) { - cpu = arm_env_get_cpu(env); - env->boot_info = info; + for (; cs; cs = cs->next_cpu) { + cpu = ARM_CPU(cs); + cpu->env.boot_info = info; qemu_register_reset(do_cpu_reset, cpu); } } diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c index 8186f1486..216b9b77d 100644 --- a/hw/arm/exynos4210.c +++ b/hw/arm/exynos4210.c @@ -241,20 +241,20 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem, /*** Memory ***/ /* Chip-ID and OMR */ - memory_region_init_io(&s->chipid_mem, &exynos4210_chipid_and_omr_ops, + memory_region_init_io(&s->chipid_mem, NULL, &exynos4210_chipid_and_omr_ops, NULL, "exynos4210.chipid", sizeof(chipid_and_omr)); memory_region_add_subregion(system_mem, EXYNOS4210_CHIPID_ADDR, &s->chipid_mem); /* Internal ROM */ - memory_region_init_ram(&s->irom_mem, "exynos4210.irom", + memory_region_init_ram(&s->irom_mem, NULL, "exynos4210.irom", EXYNOS4210_IROM_SIZE); vmstate_register_ram_global(&s->irom_mem); memory_region_set_readonly(&s->irom_mem, true); memory_region_add_subregion(system_mem, EXYNOS4210_IROM_BASE_ADDR, &s->irom_mem); /* mirror of iROM */ - memory_region_init_alias(&s->irom_alias_mem, "exynos4210.irom_alias", + memory_region_init_alias(&s->irom_alias_mem, NULL, "exynos4210.irom_alias", &s->irom_mem, 0, EXYNOS4210_IROM_SIZE); @@ -263,7 +263,7 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem, &s->irom_alias_mem); /* Internal RAM */ - memory_region_init_ram(&s->iram_mem, "exynos4210.iram", + memory_region_init_ram(&s->iram_mem, NULL, "exynos4210.iram", EXYNOS4210_IRAM_SIZE); vmstate_register_ram_global(&s->iram_mem); memory_region_add_subregion(system_mem, EXYNOS4210_IRAM_BASE_ADDR, @@ -272,14 +272,14 @@ Exynos4210State *exynos4210_init(MemoryRegion *system_mem, /* DRAM */ mem_size = ram_size; if (mem_size > EXYNOS4210_DRAM_MAX_SIZE) { - memory_region_init_ram(&s->dram1_mem, "exynos4210.dram1", + memory_region_init_ram(&s->dram1_mem, NULL, "exynos4210.dram1", mem_size - EXYNOS4210_DRAM_MAX_SIZE); vmstate_register_ram_global(&s->dram1_mem); memory_region_add_subregion(system_mem, EXYNOS4210_DRAM1_BASE_ADDR, &s->dram1_mem); mem_size = EXYNOS4210_DRAM_MAX_SIZE; } - memory_region_init_ram(&s->dram0_mem, "exynos4210.dram0", mem_size); + memory_region_init_ram(&s->dram0_mem, NULL, "exynos4210.dram0", mem_size); vmstate_register_ram_global(&s->dram0_mem); memory_region_add_subregion(system_mem, EXYNOS4210_DRAM0_BASE_ADDR, &s->dram0_mem); diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c index 74f110ba6..7c90b2d78 100644 --- a/hw/arm/exynos4_boards.c +++ b/hw/arm/exynos4_boards.c @@ -131,7 +131,7 @@ static void nuri_init(QEMUMachineInitArgs *args) { exynos4_boards_init_common(args, EXYNOS4_BOARD_NURI); - arm_load_kernel(arm_env_get_cpu(first_cpu), &exynos4_board_binfo); + arm_load_kernel(ARM_CPU(first_cpu), &exynos4_board_binfo); } static void smdkc210_init(QEMUMachineInitArgs *args) @@ -141,7 +141,7 @@ static void smdkc210_init(QEMUMachineInitArgs *args) lan9215_init(SMDK_LAN9118_BASE_ADDR, qemu_irq_invert(s->irq_table[exynos4210_get_irq(37, 1)])); - arm_load_kernel(arm_env_get_cpu(first_cpu), &exynos4_board_binfo); + arm_load_kernel(ARM_CPU(first_cpu), &exynos4_board_binfo); } static QEMUMachine exynos4_machines[EXYNOS4_NUM_OF_BOARDS] = { diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c index 4405dbd3b..be264d3eb 100644 --- a/hw/arm/highbank.c +++ b/hw/arm/highbank.c @@ -149,8 +149,8 @@ static int highbank_regs_init(SysBusDevice *dev) HighbankRegsState *s = FROM_SYSBUS(HighbankRegsState, dev); s->iomem = g_new(MemoryRegion, 1); - memory_region_init_io(s->iomem, &hb_mem_ops, s->regs, "highbank_regs", - 0x1000); + memory_region_init_io(s->iomem, OBJECT(s), &hb_mem_ops, s->regs, + "highbank_regs", 0x1000); sysbus_init_mmio(dev, s->iomem); return 0; @@ -183,20 +183,25 @@ type_init(highbank_regs_register_types) static struct arm_boot_info highbank_binfo; +enum cxmachines { + CALXEDA_HIGHBANK, + CALXEDA_MIDWAY, +}; + /* ram_size must be set to match the upper bound of memory in the * device tree (linux/arch/arm/boot/dts/highbank.dts), which is * normally 0xff900000 or -m 4089. When running this board on a * 32-bit host, set the reg value of memory to 0xf7ff00000 in the * device tree and pass -m 2047 to QEMU. */ -static void highbank_init(QEMUMachineInitArgs *args) +static void calxeda_init(QEMUMachineInitArgs *args, enum cxmachines machine) { ram_addr_t ram_size = args->ram_size; const char *cpu_model = args->cpu_model; const char *kernel_filename = args->kernel_filename; const char *kernel_cmdline = args->kernel_cmdline; const char *initrd_filename = args->initrd_filename; - DeviceState *dev; + DeviceState *dev = NULL; SysBusDevice *busdev; qemu_irq *irqp; qemu_irq pic[128]; @@ -208,7 +213,14 @@ static void highbank_init(QEMUMachineInitArgs *args) char *sysboot_filename; if (!cpu_model) { - cpu_model = "cortex-a9"; + switch (machine) { + case CALXEDA_HIGHBANK: + cpu_model = "cortex-a9"; + break; + case CALXEDA_MIDWAY: + cpu_model = "cortex-a15"; + break; + } } for (n = 0; n < smp_cpus; n++) { @@ -227,12 +239,12 @@ static void highbank_init(QEMUMachineInitArgs *args) sysmem = get_system_memory(); dram = g_new(MemoryRegion, 1); - memory_region_init_ram(dram, "highbank.dram", ram_size); + memory_region_init_ram(dram, NULL, "highbank.dram", ram_size); /* SDRAM at address zero. */ memory_region_add_subregion(sysmem, 0, dram); sysram = g_new(MemoryRegion, 1); - memory_region_init_ram(sysram, "highbank.sysram", 0x8000); + memory_region_init_ram(sysram, NULL, "highbank.sysram", 0x8000); memory_region_add_subregion(sysmem, 0xfff88000, sysram); if (bios_name != NULL) { sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); @@ -246,7 +258,19 @@ static void highbank_init(QEMUMachineInitArgs *args) } } - dev = qdev_create(NULL, "a9mpcore_priv"); + switch (machine) { + case CALXEDA_HIGHBANK: + dev = qdev_create(NULL, "l2x0"); + qdev_init_nofail(dev); + busdev = SYS_BUS_DEVICE(dev); + sysbus_mmio_map(busdev, 0, 0xfff12000); + + dev = qdev_create(NULL, "a9mpcore_priv"); + break; + case CALXEDA_MIDWAY: + dev = qdev_create(NULL, "a15mpcore_priv"); + break; + } qdev_prop_set_uint32(dev, "num-cpu", smp_cpus); qdev_prop_set_uint32(dev, "num-irq", NIRQ_GIC); qdev_init_nofail(dev); @@ -260,11 +284,6 @@ static void highbank_init(QEMUMachineInitArgs *args) pic[n] = qdev_get_gpio_in(dev, n); } - dev = qdev_create(NULL, "l2x0"); - qdev_init_nofail(dev); - busdev = SYS_BUS_DEVICE(dev); - sysbus_mmio_map(busdev, 0, 0xfff12000); - dev = qdev_create(NULL, "sp804"); qdev_prop_set_uint32(dev, "freq0", 150000000); qdev_prop_set_uint32(dev, "freq1", 150000000); @@ -321,7 +340,17 @@ static void highbank_init(QEMUMachineInitArgs *args) highbank_binfo.loader_start = 0; highbank_binfo.write_secondary_boot = hb_write_secondary; highbank_binfo.secondary_cpu_reset_hook = hb_reset_secondary; - arm_load_kernel(arm_env_get_cpu(first_cpu), &highbank_binfo); + arm_load_kernel(ARM_CPU(first_cpu), &highbank_binfo); +} + +static void highbank_init(QEMUMachineInitArgs *args) +{ + calxeda_init(args, CALXEDA_HIGHBANK); +} + +static void midway_init(QEMUMachineInitArgs *args) +{ + calxeda_init(args, CALXEDA_MIDWAY); } static QEMUMachine highbank_machine = { @@ -333,9 +362,19 @@ static QEMUMachine highbank_machine = { DEFAULT_MACHINE_OPTIONS, }; -static void highbank_machine_init(void) +static QEMUMachine midway_machine = { + .name = "midway", + .desc = "Calxeda Midway (ECX-2000)", + .init = midway_init, + .block_default_type = IF_SCSI, + .max_cpus = 4, + DEFAULT_MACHINE_OPTIONS, +}; + +static void calxeda_machines_init(void) { qemu_register_machine(&highbank_machine); + qemu_register_machine(&midway_machine); } -machine_init(highbank_machine_init); +machine_init(calxeda_machines_init); diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c index cca29719e..249a43025 100644 --- a/hw/arm/integratorcp.c +++ b/hw/arm/integratorcp.c @@ -249,10 +249,10 @@ static int integratorcm_init(SysBusDevice *dev) } memcpy(integrator_spd + 73, "QEMU-MEMORY", 11); s->cm_init = 0x00000112; - memory_region_init_ram(&s->flash, "integrator.flash", 0x100000); + memory_region_init_ram(&s->flash, OBJECT(s), "integrator.flash", 0x100000); vmstate_register_ram_global(&s->flash); - memory_region_init_io(&s->iomem, &integratorcm_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &integratorcm_ops, s, "integratorcm", 0x00800000); sysbus_init_mmio(dev, &s->iomem); @@ -374,7 +374,8 @@ static int icp_pic_init(SysBusDevice *dev) qdev_init_gpio_in(&dev->qdev, icp_pic_set_irq, 32); sysbus_init_irq(dev, &s->parent_irq); sysbus_init_irq(dev, &s->parent_fiq); - memory_region_init_io(&s->iomem, &icp_pic_ops, s, "icp-pic", 0x00800000); + memory_region_init_io(&s->iomem, OBJECT(s), &icp_pic_ops, s, + "icp-pic", 0x00800000); sysbus_init_mmio(dev, &s->iomem); return 0; } @@ -424,7 +425,7 @@ static void icp_control_init(hwaddr base) MemoryRegion *io; io = (MemoryRegion *)g_malloc0(sizeof(MemoryRegion)); - memory_region_init_io(io, &icp_control_ops, NULL, + memory_region_init_io(io, NULL, &icp_control_ops, NULL, "control", 0x00800000); memory_region_add_subregion(get_system_memory(), base, io); /* ??? Save/restore. */ @@ -463,14 +464,14 @@ static void integratorcp_init(QEMUMachineInitArgs *args) exit(1); } - memory_region_init_ram(ram, "integrator.ram", ram_size); + memory_region_init_ram(ram, NULL, "integrator.ram", ram_size); vmstate_register_ram_global(ram); /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash. */ /* ??? RAM should repeat to fill physical memory space. */ /* SDRAM at address zero*/ memory_region_add_subregion(address_space_mem, 0, ram); /* And again at address 0x80000000 */ - memory_region_init_alias(ram_alias, "ram.alias", ram, 0, ram_size); + memory_region_init_alias(ram_alias, NULL, "ram.alias", ram, 0, ram_size); memory_region_add_subregion(address_space_mem, 0x80000000, ram_alias); dev = qdev_create(NULL, "integrator_core"); diff --git a/hw/arm/kzm.c b/hw/arm/kzm.c index cf90f5dc7..bd6c05ce1 100644 --- a/hw/arm/kzm.c +++ b/hw/arm/kzm.c @@ -98,14 +98,14 @@ static void kzm_init(QEMUMachineInitArgs *args) /* On a real system, the first 16k is a `secure boot rom' */ - memory_region_init_ram(ram, "kzm.ram", ram_size); + memory_region_init_ram(ram, NULL, "kzm.ram", ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(address_space_mem, KZM_RAMADDRESS, ram); - memory_region_init_alias(ram_alias, "ram.alias", ram, 0, ram_size); + memory_region_init_alias(ram_alias, NULL, "ram.alias", ram, 0, ram_size); memory_region_add_subregion(address_space_mem, 0x88000000, ram_alias); - memory_region_init_ram(sram, "kzm.sram", 0x4000); + memory_region_init_ram(sram, NULL, "kzm.sram", 0x4000); memory_region_add_subregion(address_space_mem, 0x1FFFC000, sram); cpu_pic = arm_pic_init_cpu(cpu); diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c index 260e31481..8e5fc26e1 100644 --- a/hw/arm/mainstone.c +++ b/hw/arm/mainstone.c @@ -113,7 +113,7 @@ static void mainstone_common_init(MemoryRegion *address_space_mem, /* Setup CPU & memory */ mpu = pxa270_init(address_space_mem, mainstone_binfo.ram_size, cpu_model); - memory_region_init_ram(rom, "mainstone.rom", MAINSTONE_ROM); + memory_region_init_ram(rom, NULL, "mainstone.rom", MAINSTONE_ROM); vmstate_register_ram_global(rom); memory_region_set_readonly(rom, true); memory_region_add_subregion(address_space_mem, 0, rom); diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c index fbaf2be70..b06d4426e 100644 --- a/hw/arm/musicpal.c +++ b/hw/arm/musicpal.c @@ -389,8 +389,8 @@ static int mv88w8618_eth_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq); s->nic = qemu_new_nic(&net_mv88w8618_info, &s->conf, object_get_typename(OBJECT(dev)), dev->qdev.id, s); - memory_region_init_io(&s->iomem, &mv88w8618_eth_ops, s, "mv88w8618-eth", - MP_ETH_SIZE); + memory_region_init_io(&s->iomem, OBJECT(s), &mv88w8618_eth_ops, s, + "mv88w8618-eth", MP_ETH_SIZE); sysbus_init_mmio(dev, &s->iomem); return 0; } @@ -612,7 +612,7 @@ static int musicpal_lcd_init(SysBusDevice *dev) s->brightness = 7; - memory_region_init_io(&s->iomem, &musicpal_lcd_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &musicpal_lcd_ops, s, "musicpal-lcd", MP_LCD_SIZE); sysbus_init_mmio(dev, &s->iomem); @@ -740,7 +740,7 @@ static int mv88w8618_pic_init(SysBusDevice *dev) qdev_init_gpio_in(&dev->qdev, mv88w8618_pic_set_irq, 32); sysbus_init_irq(dev, &s->parent_irq); - memory_region_init_io(&s->iomem, &mv88w8618_pic_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &mv88w8618_pic_ops, s, "musicpal-pic", MP_PIC_SIZE); sysbus_init_mmio(dev, &s->iomem); return 0; @@ -905,7 +905,7 @@ static int mv88w8618_pit_init(SysBusDevice *dev) mv88w8618_timer_init(dev, &s->timer[i], 1000000); } - memory_region_init_io(&s->iomem, &mv88w8618_pit_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &mv88w8618_pit_ops, s, "musicpal-pit", MP_PIT_SIZE); sysbus_init_mmio(dev, &s->iomem); return 0; @@ -999,7 +999,7 @@ static int mv88w8618_flashcfg_init(SysBusDevice *dev) mv88w8618_flashcfg_state *s = FROM_SYSBUS(mv88w8618_flashcfg_state, dev); s->cfgr0 = 0xfffe4285; /* Default as set by U-Boot for 8 MB flash */ - memory_region_init_io(&s->iomem, &mv88w8618_flashcfg_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &mv88w8618_flashcfg_ops, s, "musicpal-flashcfg", MP_FLASHCFG_SIZE); sysbus_init_mmio(dev, &s->iomem); return 0; @@ -1074,7 +1074,7 @@ static void musicpal_misc_init(Object *obj) SysBusDevice *sd = SYS_BUS_DEVICE(obj); MusicPalMiscState *s = MUSICPAL_MISC(obj); - memory_region_init_io(&s->iomem, &musicpal_misc_ops, NULL, + memory_region_init_io(&s->iomem, OBJECT(s), &musicpal_misc_ops, NULL, "musicpal-misc", MP_MISC_SIZE); sysbus_init_mmio(sd, &s->iomem); } @@ -1121,7 +1121,7 @@ static int mv88w8618_wlan_init(SysBusDevice *dev) { MemoryRegion *iomem = g_new(MemoryRegion, 1); - memory_region_init_io(iomem, &mv88w8618_wlan_ops, NULL, + memory_region_init_io(iomem, OBJECT(dev), &mv88w8618_wlan_ops, NULL, "musicpal-wlan", MP_WLAN_SIZE); sysbus_init_mmio(dev, iomem); return 0; @@ -1327,7 +1327,7 @@ static int musicpal_gpio_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq); - memory_region_init_io(&s->iomem, &musicpal_gpio_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &musicpal_gpio_ops, s, "musicpal-gpio", MP_GPIO_SIZE); sysbus_init_mmio(dev, &s->iomem); @@ -1484,7 +1484,7 @@ static int musicpal_key_init(SysBusDevice *dev) { musicpal_key_state *s = FROM_SYSBUS(musicpal_key_state, dev); - memory_region_init(&s->iomem, "dummy", 0); + memory_region_init(&s->iomem, OBJECT(s), "dummy", 0); sysbus_init_mmio(dev, &s->iomem); s->kbd_extended = 0; @@ -1564,11 +1564,11 @@ static void musicpal_init(QEMUMachineInitArgs *args) cpu_pic = arm_pic_init_cpu(cpu); /* For now we use a fixed - the original - RAM size */ - memory_region_init_ram(ram, "musicpal.ram", MP_RAM_DEFAULT_SIZE); + memory_region_init_ram(ram, NULL, "musicpal.ram", MP_RAM_DEFAULT_SIZE); vmstate_register_ram_global(ram); memory_region_add_subregion(address_space_mem, 0, ram); - memory_region_init_ram(sram, "musicpal.sram", MP_SRAM_SIZE); + memory_region_init_ram(sram, NULL, "musicpal.sram", MP_SRAM_SIZE); vmstate_register_ram_global(sram); memory_region_add_subregion(address_space_mem, MP_SRAM_BASE, sram); diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c index c06c642ac..19be5fcd0 100644 --- a/hw/arm/omap1.c +++ b/hw/arm/omap1.c @@ -264,7 +264,7 @@ static struct omap_mpu_timer_s *omap_mpu_timer_init(MemoryRegion *system_memory, omap_mpu_timer_reset(s); omap_timer_clk_setup(s); - memory_region_init_io(&s->iomem, &omap_mpu_timer_ops, s, + memory_region_init_io(&s->iomem, NULL, &omap_mpu_timer_ops, s, "omap-mpu-timer", 0x100); memory_region_add_subregion(system_memory, base, &s->iomem); @@ -392,7 +392,7 @@ static struct omap_watchdog_timer_s *omap_wd_timer_init(MemoryRegion *memory, omap_wd_timer_reset(s); omap_timer_clk_setup(&s->timer); - memory_region_init_io(&s->iomem, &omap_wd_timer_ops, s, + memory_region_init_io(&s->iomem, NULL, &omap_wd_timer_ops, s, "omap-wd-timer", 0x100); memory_region_add_subregion(memory, base, &s->iomem); @@ -498,7 +498,7 @@ static struct omap_32khz_timer_s *omap_os_timer_init(MemoryRegion *memory, omap_os_timer_reset(s); omap_timer_clk_setup(&s->timer); - memory_region_init_io(&s->iomem, &omap_os_timer_ops, s, + memory_region_init_io(&s->iomem, NULL, &omap_os_timer_ops, s, "omap-os-timer", 0x800); memory_region_add_subregion(memory, base, &s->iomem); @@ -731,7 +731,7 @@ static void omap_ulpd_pm_init(MemoryRegion *system_memory, hwaddr base, struct omap_mpu_state_s *mpu) { - memory_region_init_io(&mpu->ulpd_pm_iomem, &omap_ulpd_pm_ops, mpu, + memory_region_init_io(&mpu->ulpd_pm_iomem, NULL, &omap_ulpd_pm_ops, mpu, "omap-ulpd-pm", 0x800); memory_region_add_subregion(system_memory, base, &mpu->ulpd_pm_iomem); omap_ulpd_pm_reset(mpu); @@ -949,7 +949,7 @@ static void omap_pin_cfg_init(MemoryRegion *system_memory, hwaddr base, struct omap_mpu_state_s *mpu) { - memory_region_init_io(&mpu->pin_cfg_iomem, &omap_pin_cfg_ops, mpu, + memory_region_init_io(&mpu->pin_cfg_iomem, NULL, &omap_pin_cfg_ops, mpu, "omap-pin-cfg", 0x800); memory_region_add_subregion(system_memory, base, &mpu->pin_cfg_iomem); omap_pin_cfg_reset(mpu); @@ -1021,16 +1021,16 @@ static const MemoryRegionOps omap_id_ops = { static void omap_id_init(MemoryRegion *memory, struct omap_mpu_state_s *mpu) { - memory_region_init_io(&mpu->id_iomem, &omap_id_ops, mpu, + memory_region_init_io(&mpu->id_iomem, NULL, &omap_id_ops, mpu, "omap-id", 0x100000000ULL); - memory_region_init_alias(&mpu->id_iomem_e18, "omap-id-e18", &mpu->id_iomem, + memory_region_init_alias(&mpu->id_iomem_e18, NULL, "omap-id-e18", &mpu->id_iomem, 0xfffe1800, 0x800); memory_region_add_subregion(memory, 0xfffe1800, &mpu->id_iomem_e18); - memory_region_init_alias(&mpu->id_iomem_ed4, "omap-id-ed4", &mpu->id_iomem, + memory_region_init_alias(&mpu->id_iomem_ed4, NULL, "omap-id-ed4", &mpu->id_iomem, 0xfffed400, 0x100); memory_region_add_subregion(memory, 0xfffed400, &mpu->id_iomem_ed4); if (!cpu_is_omap15xx(mpu)) { - memory_region_init_alias(&mpu->id_iomem_ed4, "omap-id-e20", + memory_region_init_alias(&mpu->id_iomem_ed4, NULL, "omap-id-e20", &mpu->id_iomem, 0xfffe2000, 0x800); memory_region_add_subregion(memory, 0xfffe2000, &mpu->id_iomem_e20); } @@ -1115,7 +1115,7 @@ static void omap_mpui_reset(struct omap_mpu_state_s *s) static void omap_mpui_init(MemoryRegion *memory, hwaddr base, struct omap_mpu_state_s *mpu) { - memory_region_init_io(&mpu->mpui_iomem, &omap_mpui_ops, mpu, + memory_region_init_io(&mpu->mpui_iomem, NULL, &omap_mpui_ops, mpu, "omap-mpui", 0x100); memory_region_add_subregion(memory, base, &mpu->mpui_iomem); @@ -1227,7 +1227,7 @@ static struct omap_tipb_bridge_s *omap_tipb_bridge_init( s->abort = abort_irq; omap_tipb_bridge_reset(s); - memory_region_init_io(&s->iomem, &omap_tipb_bridge_ops, s, + memory_region_init_io(&s->iomem, NULL, &omap_tipb_bridge_ops, s, "omap-tipb-bridge", 0x100); memory_region_add_subregion(memory, base, &s->iomem); @@ -1336,7 +1336,7 @@ static void omap_tcmi_reset(struct omap_mpu_state_s *mpu) static void omap_tcmi_init(MemoryRegion *memory, hwaddr base, struct omap_mpu_state_s *mpu) { - memory_region_init_io(&mpu->tcmi_iomem, &omap_tcmi_ops, mpu, + memory_region_init_io(&mpu->tcmi_iomem, NULL, &omap_tcmi_ops, mpu, "omap-tcmi", 0x100); memory_region_add_subregion(memory, base, &mpu->tcmi_iomem); omap_tcmi_reset(mpu); @@ -1418,7 +1418,7 @@ static struct dpll_ctl_s *omap_dpll_init(MemoryRegion *memory, hwaddr base, omap_clk clk) { struct dpll_ctl_s *s = g_malloc0(sizeof(*s)); - memory_region_init_io(&s->iomem, &omap_dpll_ops, s, "omap-dpll", 0x100); + memory_region_init_io(&s->iomem, NULL, &omap_dpll_ops, s, "omap-dpll", 0x100); s->dpll = clk; omap_dpll_reset(s); @@ -1831,9 +1831,9 @@ static void omap_clkm_reset(struct omap_mpu_state_s *s) static void omap_clkm_init(MemoryRegion *memory, hwaddr mpu_base, hwaddr dsp_base, struct omap_mpu_state_s *s) { - memory_region_init_io(&s->clkm_iomem, &omap_clkm_ops, s, + memory_region_init_io(&s->clkm_iomem, NULL, &omap_clkm_ops, s, "omap-clkm", 0x100); - memory_region_init_io(&s->clkdsp_iomem, &omap_clkdsp_ops, s, + memory_region_init_io(&s->clkdsp_iomem, NULL, &omap_clkdsp_ops, s, "omap-clkdsp", 0x1000); s->clkm.arm_idlect1 = 0x03ff; @@ -2090,7 +2090,7 @@ static struct omap_mpuio_s *omap_mpuio_init(MemoryRegion *memory, s->in = qemu_allocate_irqs(omap_mpuio_set, s, 16); omap_mpuio_reset(s); - memory_region_init_io(&s->iomem, &omap_mpuio_ops, s, + memory_region_init_io(&s->iomem, NULL, &omap_mpuio_ops, s, "omap-mpuio", 0x800); memory_region_add_subregion(memory, base, &s->iomem); @@ -2281,7 +2281,7 @@ static struct omap_uwire_s *omap_uwire_init(MemoryRegion *system_memory, s->txdrq = dma; omap_uwire_reset(s); - memory_region_init_io(&s->iomem, &omap_uwire_ops, s, "omap-uwire", 0x800); + memory_region_init_io(&s->iomem, NULL, &omap_uwire_ops, s, "omap-uwire", 0x800); memory_region_add_subregion(system_memory, base, &s->iomem); return s; @@ -2393,7 +2393,7 @@ static struct omap_pwl_s *omap_pwl_init(MemoryRegion *system_memory, omap_pwl_reset(s); - memory_region_init_io(&s->iomem, &omap_pwl_ops, s, + memory_region_init_io(&s->iomem, NULL, &omap_pwl_ops, s, "omap-pwl", 0x800); memory_region_add_subregion(system_memory, base, &s->iomem); @@ -2500,7 +2500,7 @@ static struct omap_pwt_s *omap_pwt_init(MemoryRegion *system_memory, s->clk = clk; omap_pwt_reset(s); - memory_region_init_io(&s->iomem, &omap_pwt_ops, s, + memory_region_init_io(&s->iomem, NULL, &omap_pwt_ops, s, "omap-pwt", 0x800); memory_region_add_subregion(system_memory, base, &s->iomem); return s; @@ -2919,7 +2919,7 @@ static struct omap_rtc_s *omap_rtc_init(MemoryRegion *system_memory, omap_rtc_reset(s); - memory_region_init_io(&s->iomem, &omap_rtc_ops, s, + memory_region_init_io(&s->iomem, NULL, &omap_rtc_ops, s, "omap-rtc", 0x800); memory_region_add_subregion(system_memory, base, &s->iomem); @@ -3452,7 +3452,7 @@ static struct omap_mcbsp_s *omap_mcbsp_init(MemoryRegion *system_memory, s->source_timer = qemu_new_timer_ns(vm_clock, omap_mcbsp_source_tick, s); omap_mcbsp_reset(s); - memory_region_init_io(&s->iomem, &omap_mcbsp_ops, s, "omap-mcbsp", 0x800); + memory_region_init_io(&s->iomem, NULL, &omap_mcbsp_ops, s, "omap-mcbsp", 0x800); memory_region_add_subregion(system_memory, base, &s->iomem); return s; @@ -3627,7 +3627,7 @@ static struct omap_lpg_s *omap_lpg_init(MemoryRegion *system_memory, omap_lpg_reset(s); - memory_region_init_io(&s->iomem, &omap_lpg_ops, s, "omap-lpg", 0x800); + memory_region_init_io(&s->iomem, NULL, &omap_lpg_ops, s, "omap-lpg", 0x800); memory_region_add_subregion(system_memory, base, &s->iomem); omap_clk_adduser(clk, qemu_allocate_irqs(omap_lpg_clk_update, s, 1)[0]); @@ -3666,7 +3666,7 @@ static const MemoryRegionOps omap_mpui_io_ops = { static void omap_setup_mpui_io(MemoryRegion *system_memory, struct omap_mpu_state_s *mpu) { - memory_region_init_io(&mpu->mpui_io_iomem, &omap_mpui_io_ops, mpu, + memory_region_init_io(&mpu->mpui_io_iomem, NULL, &omap_mpui_io_ops, mpu, "omap-mpui-io", 0x7fff); memory_region_add_subregion(system_memory, OMAP_MPUI_BASE, &mpu->mpui_io_iomem); @@ -3747,7 +3747,7 @@ static void omap_setup_dsp_mapping(MemoryRegion *system_memory, for (; map->phys_dsp; map ++) { io = g_new(MemoryRegion, 1); - memory_region_init_alias(io, map->name, + memory_region_init_alias(io, NULL, map->name, system_memory, map->phys_mpu, map->size); memory_region_add_subregion(system_memory, map->phys_dsp, io); } @@ -3851,10 +3851,10 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *system_memory, omap_clk_init(s); /* Memory-mapped stuff */ - memory_region_init_ram(&s->emiff_ram, "omap1.dram", s->sdram_size); + memory_region_init_ram(&s->emiff_ram, NULL, "omap1.dram", s->sdram_size); vmstate_register_ram_global(&s->emiff_ram); memory_region_add_subregion(system_memory, OMAP_EMIFF_BASE, &s->emiff_ram); - memory_region_init_ram(&s->imif_ram, "omap1.sram", s->sram_size); + memory_region_init_ram(&s->imif_ram, NULL, "omap1.sram", s->sram_size); vmstate_register_ram_global(&s->imif_ram); memory_region_add_subregion(system_memory, OMAP_IMIF_BASE, &s->imif_ram); diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c index 2ff43710e..ec9610b7d 100644 --- a/hw/arm/omap2.c +++ b/hw/arm/omap2.c @@ -603,7 +603,7 @@ static struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta, AUD_register_card("OMAP EAC", &s->codec.card); - memory_region_init_io(&s->iomem, &omap_eac_ops, s, "omap.eac", + memory_region_init_io(&s->iomem, NULL, &omap_eac_ops, s, "omap.eac", omap_l4_region_size(ta, 0)); omap_l4_attach(ta, 0, &s->iomem); @@ -791,11 +791,11 @@ static struct omap_sti_s *omap_sti_init(struct omap_target_agent_s *ta, s->chr = chr ?: qemu_chr_new("null", "null", NULL); - memory_region_init_io(&s->iomem, &omap_sti_ops, s, "omap.sti", + memory_region_init_io(&s->iomem, NULL, &omap_sti_ops, s, "omap.sti", omap_l4_region_size(ta, 0)); omap_l4_attach(ta, 0, &s->iomem); - memory_region_init_io(&s->iomem_fifo, &omap_sti_fifo_ops, s, + memory_region_init_io(&s->iomem_fifo, NULL, &omap_sti_fifo_ops, s, "omap.sti.fifo", 0x10000); memory_region_add_subregion(sysmem, channel_base, &s->iomem_fifo); @@ -1809,9 +1809,9 @@ static struct omap_prcm_s *omap_prcm_init(struct omap_target_agent_s *ta, s->mpu = mpu; omap_prcm_coldreset(s); - memory_region_init_io(&s->iomem0, &omap_prcm_ops, s, "omap.pcrm0", + memory_region_init_io(&s->iomem0, NULL, &omap_prcm_ops, s, "omap.pcrm0", omap_l4_region_size(ta, 0)); - memory_region_init_io(&s->iomem1, &omap_prcm_ops, s, "omap.pcrm1", + memory_region_init_io(&s->iomem1, NULL, &omap_prcm_ops, s, "omap.pcrm1", omap_l4_region_size(ta, 1)); omap_l4_attach(ta, 0, &s->iomem0); omap_l4_attach(ta, 1, &s->iomem1); @@ -2185,7 +2185,7 @@ static struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta, s->mpu = mpu; omap_sysctl_reset(s); - memory_region_init_io(&s->iomem, &omap_sysctl_ops, s, "omap.sysctl", + memory_region_init_io(&s->iomem, NULL, &omap_sysctl_ops, s, "omap.sysctl", omap_l4_region_size(ta, 0)); omap_l4_attach(ta, 0, &s->iomem); @@ -2267,10 +2267,10 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sysmem, omap_clk_init(s); /* Memory-mapped stuff */ - memory_region_init_ram(&s->sdram, "omap2.dram", s->sdram_size); + memory_region_init_ram(&s->sdram, NULL, "omap2.dram", s->sdram_size); vmstate_register_ram_global(&s->sdram); memory_region_add_subregion(sysmem, OMAP2_Q2_BASE, &s->sdram); - memory_region_init_ram(&s->sram, "omap2.sram", s->sram_size); + memory_region_init_ram(&s->sram, NULL, "omap2.sram", s->sram_size); vmstate_register_ram_global(&s->sram); memory_region_add_subregion(sysmem, OMAP2_SRAM_BASE, &s->sram); diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c index e421ece02..05b035308 100644 --- a/hw/arm/omap_sx1.c +++ b/hw/arm/omap_sx1.c @@ -120,23 +120,23 @@ static void sx1_init(QEMUMachineInitArgs *args, const int version) mpu = omap310_mpu_init(address_space, sx1_binfo.ram_size, args->cpu_model); /* External Flash (EMIFS) */ - memory_region_init_ram(flash, "omap_sx1.flash0-0", flash_size); + memory_region_init_ram(flash, NULL, "omap_sx1.flash0-0", flash_size); vmstate_register_ram_global(flash); memory_region_set_readonly(flash, true); memory_region_add_subregion(address_space, OMAP_CS0_BASE, flash); - memory_region_init_io(&cs[0], &static_ops, &cs0val, + memory_region_init_io(&cs[0], NULL, &static_ops, &cs0val, "sx1.cs0", OMAP_CS0_SIZE - flash_size); memory_region_add_subregion(address_space, OMAP_CS0_BASE + flash_size, &cs[0]); - memory_region_init_io(&cs[2], &static_ops, &cs2val, + memory_region_init_io(&cs[2], NULL, &static_ops, &cs2val, "sx1.cs2", OMAP_CS2_SIZE); memory_region_add_subregion(address_space, OMAP_CS2_BASE, &cs[2]); - memory_region_init_io(&cs[3], &static_ops, &cs3val, + memory_region_init_io(&cs[3], NULL, &static_ops, &cs3val, "sx1.cs3", OMAP_CS3_SIZE); memory_region_add_subregion(address_space, OMAP_CS2_BASE, &cs[3]); @@ -162,12 +162,12 @@ static void sx1_init(QEMUMachineInitArgs *args, const int version) if ((version == 1) && (dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) { - memory_region_init_ram(flash_1, "omap_sx1.flash1-0", flash1_size); + memory_region_init_ram(flash_1, NULL, "omap_sx1.flash1-0", flash1_size); vmstate_register_ram_global(flash_1); memory_region_set_readonly(flash_1, true); memory_region_add_subregion(address_space, OMAP_CS1_BASE, flash_1); - memory_region_init_io(&cs[1], &static_ops, &cs1val, + memory_region_init_io(&cs[1], NULL, &static_ops, &cs1val, "sx1.cs1", OMAP_CS1_SIZE - flash1_size); memory_region_add_subregion(address_space, OMAP_CS1_BASE + flash1_size, &cs[1]); @@ -182,7 +182,7 @@ static void sx1_init(QEMUMachineInitArgs *args, const int version) } fl_idx++; } else { - memory_region_init_io(&cs[1], &static_ops, &cs1val, + memory_region_init_io(&cs[1], NULL, &static_ops, &cs1val, "sx1.cs1", OMAP_CS1_SIZE); memory_region_add_subregion(address_space, OMAP_CS1_BASE, &cs[1]); diff --git a/hw/arm/palm.c b/hw/arm/palm.c index b13d8108a..cdc3c3a0f 100644 --- a/hw/arm/palm.c +++ b/hw/arm/palm.c @@ -211,22 +211,22 @@ static void palmte_init(QEMUMachineInitArgs *args) mpu = omap310_mpu_init(address_space_mem, sdram_size, cpu_model); /* External Flash (EMIFS) */ - memory_region_init_ram(flash, "palmte.flash", flash_size); + memory_region_init_ram(flash, NULL, "palmte.flash", flash_size); vmstate_register_ram_global(flash); memory_region_set_readonly(flash, true); memory_region_add_subregion(address_space_mem, OMAP_CS0_BASE, flash); - memory_region_init_io(&cs[0], &static_ops, &cs0val, "palmte-cs0", + memory_region_init_io(&cs[0], NULL, &static_ops, &cs0val, "palmte-cs0", OMAP_CS0_SIZE - flash_size); memory_region_add_subregion(address_space_mem, OMAP_CS0_BASE + flash_size, &cs[0]); - memory_region_init_io(&cs[1], &static_ops, &cs1val, "palmte-cs1", + memory_region_init_io(&cs[1], NULL, &static_ops, &cs1val, "palmte-cs1", OMAP_CS1_SIZE); memory_region_add_subregion(address_space_mem, OMAP_CS1_BASE, &cs[1]); - memory_region_init_io(&cs[2], &static_ops, &cs2val, "palmte-cs2", + memory_region_init_io(&cs[2], NULL, &static_ops, &cs2val, "palmte-cs2", OMAP_CS2_SIZE); memory_region_add_subregion(address_space_mem, OMAP_CS2_BASE, &cs[2]); - memory_region_init_io(&cs[3], &static_ops, &cs3val, "palmte-cs3", + memory_region_init_io(&cs[3], NULL, &static_ops, &cs3val, "palmte-cs3", OMAP_CS3_SIZE); memory_region_add_subregion(address_space_mem, OMAP_CS3_BASE, &cs[3]); diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c index 24b03a0d2..3c520d7f2 100644 --- a/hw/arm/pxa2xx.c +++ b/hw/arm/pxa2xx.c @@ -301,8 +301,7 @@ static int pxa2xx_pwrmode_write(CPUARMState *env, const ARMCPRegInfo *ri, #endif /* Suspend */ - cpu_interrupt(CPU(arm_env_get_cpu(cpu_single_env)), - CPU_INTERRUPT_HALT); + cpu_interrupt(current_cpu, CPU_INTERRUPT_HALT); goto message; @@ -764,7 +763,8 @@ static int pxa2xx_ssp_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq); - memory_region_init_io(&s->iomem, &pxa2xx_ssp_ops, s, "pxa2xx-ssp", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_ssp_ops, s, + "pxa2xx-ssp", 0x1000); sysbus_init_mmio(dev, &s->iomem); register_savevm(&dev->qdev, "pxa2xx_ssp", -1, 0, pxa2xx_ssp_save, pxa2xx_ssp_load, s); @@ -1131,7 +1131,8 @@ static int pxa2xx_rtc_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->rtc_irq); - memory_region_init_io(&s->iomem, &pxa2xx_rtc_ops, s, "pxa2xx-rtc", 0x10000); + memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_rtc_ops, s, + "pxa2xx-rtc", 0x10000); sysbus_init_mmio(dev, &s->iomem); return 0; @@ -1481,8 +1482,8 @@ static int pxa2xx_i2c_initfn(SysBusDevice *dev) s->bus = i2c_init_bus(&dev->qdev, "i2c"); - memory_region_init_io(&s->iomem, &pxa2xx_i2c_ops, s, - "pxa2xx-i2x", s->region_size); + memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_i2c_ops, s, + "pxa2xx-i2c", s->region_size); sysbus_init_mmio(dev, &s->iomem); sysbus_init_irq(dev, &s->irq); @@ -1720,7 +1721,7 @@ static PXA2xxI2SState *pxa2xx_i2s_init(MemoryRegion *sysmem, pxa2xx_i2s_reset(s); - memory_region_init_io(&s->iomem, &pxa2xx_i2s_ops, s, + memory_region_init_io(&s->iomem, NULL, &pxa2xx_i2s_ops, s, "pxa2xx-i2s", 0x100000); memory_region_add_subregion(sysmem, base, &s->iomem); @@ -1978,7 +1979,7 @@ static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem, pxa2xx_fir_reset(s); - memory_region_init_io(&s->iomem, &pxa2xx_fir_ops, s, "pxa2xx-fir", 0x1000); + memory_region_init_io(&s->iomem, NULL, &pxa2xx_fir_ops, s, "pxa2xx-fir", 0x1000); memory_region_add_subregion(sysmem, base, &s->iomem); if (chr) { @@ -2027,10 +2028,10 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space, s->reset = qemu_allocate_irqs(pxa2xx_reset, s, 1)[0]; /* SDRAM & Internal Memory Storage */ - memory_region_init_ram(&s->sdram, "pxa270.sdram", sdram_size); + memory_region_init_ram(&s->sdram, NULL, "pxa270.sdram", sdram_size); vmstate_register_ram_global(&s->sdram); memory_region_add_subregion(address_space, PXA2XX_SDRAM_BASE, &s->sdram); - memory_region_init_ram(&s->internal, "pxa270.internal", 0x40000); + memory_region_init_ram(&s->internal, NULL, "pxa270.internal", 0x40000); vmstate_register_ram_global(&s->internal); memory_region_add_subregion(address_space, PXA2XX_INTERNAL_BASE, &s->internal); @@ -2083,7 +2084,7 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space, s->cm_base = 0x41300000; s->cm_regs[CCCR >> 2] = 0x02000210; /* 416.0 MHz */ s->clkcfg = 0x00000009; /* Turbo mode active */ - memory_region_init_io(&s->cm_iomem, &pxa2xx_cm_ops, s, "pxa2xx-cm", 0x1000); + memory_region_init_io(&s->cm_iomem, NULL, &pxa2xx_cm_ops, s, "pxa2xx-cm", 0x1000); memory_region_add_subregion(address_space, s->cm_base, &s->cm_iomem); vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s); @@ -2093,12 +2094,12 @@ PXA2xxState *pxa270_init(MemoryRegion *address_space, s->mm_regs[MDMRS >> 2] = 0x00020002; s->mm_regs[MDREFR >> 2] = 0x03ca4000; s->mm_regs[MECR >> 2] = 0x00000001; /* Two PC Card sockets */ - memory_region_init_io(&s->mm_iomem, &pxa2xx_mm_ops, s, "pxa2xx-mm", 0x1000); + memory_region_init_io(&s->mm_iomem, NULL, &pxa2xx_mm_ops, s, "pxa2xx-mm", 0x1000); memory_region_add_subregion(address_space, s->mm_base, &s->mm_iomem); vmstate_register(NULL, 0, &vmstate_pxa2xx_mm, s); s->pm_base = 0x40f00000; - memory_region_init_io(&s->pm_iomem, &pxa2xx_pm_ops, s, "pxa2xx-pm", 0x100); + memory_region_init_io(&s->pm_iomem, NULL, &pxa2xx_pm_ops, s, "pxa2xx-pm", 0x100); memory_region_add_subregion(address_space, s->pm_base, &s->pm_iomem); vmstate_register(NULL, 0, &vmstate_pxa2xx_pm, s); @@ -2158,10 +2159,10 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size) s->reset = qemu_allocate_irqs(pxa2xx_reset, s, 1)[0]; /* SDRAM & Internal Memory Storage */ - memory_region_init_ram(&s->sdram, "pxa255.sdram", sdram_size); + memory_region_init_ram(&s->sdram, NULL, "pxa255.sdram", sdram_size); vmstate_register_ram_global(&s->sdram); memory_region_add_subregion(address_space, PXA2XX_SDRAM_BASE, &s->sdram); - memory_region_init_ram(&s->internal, "pxa255.internal", + memory_region_init_ram(&s->internal, NULL, "pxa255.internal", PXA2XX_INTERNAL_SIZE); vmstate_register_ram_global(&s->internal); memory_region_add_subregion(address_space, PXA2XX_INTERNAL_BASE, @@ -2214,7 +2215,7 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size) s->cm_base = 0x41300000; s->cm_regs[CCCR >> 2] = 0x02000210; /* 416.0 MHz */ s->clkcfg = 0x00000009; /* Turbo mode active */ - memory_region_init_io(&s->cm_iomem, &pxa2xx_cm_ops, s, "pxa2xx-cm", 0x1000); + memory_region_init_io(&s->cm_iomem, NULL, &pxa2xx_cm_ops, s, "pxa2xx-cm", 0x1000); memory_region_add_subregion(address_space, s->cm_base, &s->cm_iomem); vmstate_register(NULL, 0, &vmstate_pxa2xx_cm, s); @@ -2224,12 +2225,12 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size) s->mm_regs[MDMRS >> 2] = 0x00020002; s->mm_regs[MDREFR >> 2] = 0x03ca4000; s->mm_regs[MECR >> 2] = 0x00000001; /* Two PC Card sockets */ - memory_region_init_io(&s->mm_iomem, &pxa2xx_mm_ops, s, "pxa2xx-mm", 0x1000); + memory_region_init_io(&s->mm_iomem, NULL, &pxa2xx_mm_ops, s, "pxa2xx-mm", 0x1000); memory_region_add_subregion(address_space, s->mm_base, &s->mm_iomem); vmstate_register(NULL, 0, &vmstate_pxa2xx_mm, s); s->pm_base = 0x40f00000; - memory_region_init_io(&s->pm_iomem, &pxa2xx_pm_ops, s, "pxa2xx-pm", 0x100); + memory_region_init_io(&s->pm_iomem, NULL, &pxa2xx_pm_ops, s, "pxa2xx-pm", 0x100); memory_region_add_subregion(address_space, s->pm_base, &s->pm_iomem); vmstate_register(NULL, 0, &vmstate_pxa2xx_pm, s); diff --git a/hw/arm/pxa2xx_gpio.c b/hw/arm/pxa2xx_gpio.c index fa31575ed..f8c3ee073 100644 --- a/hw/arm/pxa2xx_gpio.c +++ b/hw/arm/pxa2xx_gpio.c @@ -283,7 +283,7 @@ static int pxa2xx_gpio_initfn(SysBusDevice *dev) qdev_init_gpio_in(&dev->qdev, pxa2xx_gpio_set, s->lines); qdev_init_gpio_out(&dev->qdev, s->handler, s->lines); - memory_region_init_io(&s->iomem, &pxa_gpio_ops, s, "pxa2xx-gpio", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &pxa_gpio_ops, s, "pxa2xx-gpio", 0x1000); sysbus_init_mmio(dev, &s->iomem); sysbus_init_irq(dev, &s->irq0); sysbus_init_irq(dev, &s->irq1); diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c index 835d07c34..8929b6db4 100644 --- a/hw/arm/pxa2xx_pic.c +++ b/hw/arm/pxa2xx_pic.c @@ -278,7 +278,7 @@ DeviceState *pxa2xx_pic_init(hwaddr base, ARMCPU *cpu) qdev_init_gpio_in(dev, pxa2xx_pic_set_irq, PXA2XX_PIC_SRCS); /* Enable IC memory-mapped registers access. */ - memory_region_init_io(&s->iomem, &pxa2xx_pic_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_pic_ops, s, "pxa2xx-pic", 0x00100000); sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); diff --git a/hw/arm/realview.c b/hw/arm/realview.c index d6f47bf4d..3060f48f7 100644 --- a/hw/arm/realview.c +++ b/hw/arm/realview.c @@ -59,7 +59,7 @@ static void realview_init(QEMUMachineInitArgs *args, qemu_irq *irqp; qemu_irq pic[64]; qemu_irq mmc_irq[2]; - PCIBus *pci_bus; + PCIBus *pci_bus = NULL; NICInfo *nd; i2c_bus *i2c; int n; @@ -114,18 +114,18 @@ static void realview_init(QEMUMachineInitArgs *args, /* Core tile RAM. */ low_ram_size = ram_size - 0x20000000; ram_size = 0x20000000; - memory_region_init_ram(ram_lo, "realview.lowmem", low_ram_size); + memory_region_init_ram(ram_lo, NULL, "realview.lowmem", low_ram_size); vmstate_register_ram_global(ram_lo); memory_region_add_subregion(sysmem, 0x20000000, ram_lo); } - memory_region_init_ram(ram_hi, "realview.highmem", ram_size); + memory_region_init_ram(ram_hi, NULL, "realview.highmem", ram_size); vmstate_register_ram_global(ram_hi); low_ram_size = ram_size; if (low_ram_size > 0x10000000) low_ram_size = 0x10000000; /* SDRAM at address zero. */ - memory_region_init_alias(ram_alias, "realview.alias", + memory_region_init_alias(ram_alias, NULL, "realview.alias", ram_hi, 0, low_ram_size); memory_region_add_subregion(sysmem, 0, ram_alias); if (is_pb) { @@ -250,7 +250,9 @@ static void realview_init(QEMUMachineInitArgs *args, } done_nic = 1; } else { - pci_nic_init_nofail(nd, "rtl8139", NULL); + if (pci_bus) { + pci_nic_init_nofail(nd, pci_bus, "rtl8139", NULL); + } } } @@ -318,7 +320,7 @@ static void realview_init(QEMUMachineInitArgs *args, startup code. I guess this works on real hardware because the BootROM happens to be in ROM/flash or in memory that isn't clobbered until after Linux boots the secondary CPUs. */ - memory_region_init_ram(ram_hack, "realview.hack", 0x1000); + memory_region_init_ram(ram_hack, NULL, "realview.hack", 0x1000); vmstate_register_ram_global(ram_hack); memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, ram_hack); @@ -329,7 +331,7 @@ static void realview_init(QEMUMachineInitArgs *args, realview_binfo.nb_cpus = smp_cpus; realview_binfo.board_id = realview_board_id[board_type]; realview_binfo.loader_start = (board_type == BOARD_PB_A8 ? 0x70000000 : 0); - arm_load_kernel(arm_env_get_cpu(first_cpu), &realview_binfo); + arm_load_kernel(ARM_CPU(first_cpu), &realview_binfo); } static void realview_eb_init(QEMUMachineInitArgs *args) diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c index b5ed10947..593b75e55 100644 --- a/hw/arm/spitz.c +++ b/hw/arm/spitz.c @@ -169,7 +169,7 @@ static int sl_nand_init(SysBusDevice *dev) { nand = drive_get(IF_MTD, 0, 0); s->nand = nand_init(nand ? nand->bdrv : NULL, s->manf_id, s->chip_id); - memory_region_init_io(&s->iomem, &sl_ops, s, "sl", 0x40); + memory_region_init_io(&s->iomem, OBJECT(s), &sl_ops, s, "sl", 0x40); sysbus_init_mmio(dev, &s->iomem); return 0; @@ -896,7 +896,7 @@ static void spitz_common_init(QEMUMachineInitArgs *args, sl_flash_register(mpu, (model == spitz) ? FLASH_128M : FLASH_1024M); - memory_region_init_ram(rom, "spitz.rom", SPITZ_ROM); + memory_region_init_ram(rom, NULL, "spitz.rom", SPITZ_ROM); vmstate_register_ram_global(rom); memory_region_set_readonly(rom, true); memory_region_add_subregion(address_space_mem, 0, rom); diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c index 2b61e3c7f..a2b6b1724 100644 --- a/hw/arm/stellaris.c +++ b/hw/arm/stellaris.c @@ -307,7 +307,7 @@ static int stellaris_gptm_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq); qdev_init_gpio_out(&dev->qdev, &s->trigger, 1); - memory_region_init_io(&s->iomem, &gptm_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &gptm_ops, s, "gptm", 0x1000); sysbus_init_mmio(dev, &s->iomem); @@ -669,7 +669,7 @@ static int stellaris_sys_init(uint32_t base, qemu_irq irq, s->user0 = macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16); s->user1 = macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16); - memory_region_init_io(&s->iomem, &ssys_ops, s, "ssys", 0x00001000); + memory_region_init_io(&s->iomem, NULL, &ssys_ops, s, "ssys", 0x00001000); memory_region_add_subregion(get_system_memory(), base, &s->iomem); ssys_reset(s); vmstate_register(NULL, -1, &vmstate_stellaris_sys, s); @@ -862,7 +862,7 @@ static int stellaris_i2c_init(SysBusDevice * dev) bus = i2c_init_bus(&dev->qdev, "i2c"); s->bus = bus; - memory_region_init_io(&s->iomem, &stellaris_i2c_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &stellaris_i2c_ops, s, "i2c", 0x1000); sysbus_init_mmio(dev, &s->iomem); /* ??? For now we only implement the master interface. */ @@ -1145,7 +1145,7 @@ static int stellaris_adc_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq[n]); } - memory_region_init_io(&s->iomem, &stellaris_adc_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &stellaris_adc_ops, s, "adc", 0x1000); sysbus_init_mmio(dev, &s->iomem); stellaris_adc_reset(s); diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c index 4d49306dd..feaaf4508 100644 --- a/hw/arm/strongarm.c +++ b/hw/arm/strongarm.c @@ -173,7 +173,8 @@ static int strongarm_pic_initfn(SysBusDevice *dev) StrongARMPICState *s = FROM_SYSBUS(StrongARMPICState, dev); qdev_init_gpio_in(&dev->qdev, strongarm_pic_set_irq, SA_PIC_SRCS); - memory_region_init_io(&s->iomem, &strongarm_pic_ops, s, "pic", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_pic_ops, s, + "pic", 0x1000); sysbus_init_mmio(dev, &s->iomem); sysbus_init_irq(dev, &s->irq); sysbus_init_irq(dev, &s->fiq); @@ -383,7 +384,8 @@ static int strongarm_rtc_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->rtc_irq); sysbus_init_irq(dev, &s->rtc_hz_irq); - memory_region_init_io(&s->iomem, &strongarm_rtc_ops, s, "rtc", 0x10000); + memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_rtc_ops, s, + "rtc", 0x10000); sysbus_init_mmio(dev, &s->iomem); return 0; @@ -637,7 +639,8 @@ static int strongarm_gpio_initfn(SysBusDevice *dev) qdev_init_gpio_in(&dev->qdev, strongarm_gpio_set, 28); qdev_init_gpio_out(&dev->qdev, s->handler, 28); - memory_region_init_io(&s->iomem, &strongarm_gpio_ops, s, "gpio", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_gpio_ops, s, + "gpio", 0x1000); sysbus_init_mmio(dev, &s->iomem); for (i = 0; i < 11; i++) { @@ -808,7 +811,8 @@ static int strongarm_ppc_init(SysBusDevice *dev) qdev_init_gpio_in(&dev->qdev, strongarm_ppc_set, 22); qdev_init_gpio_out(&dev->qdev, s->handler, 22); - memory_region_init_io(&s->iomem, &strongarm_ppc_ops, s, "ppc", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_ppc_ops, s, + "ppc", 0x1000); sysbus_init_mmio(dev, &s->iomem); @@ -1204,7 +1208,8 @@ static int strongarm_uart_init(SysBusDevice *dev) { StrongARMUARTState *s = FROM_SYSBUS(StrongARMUARTState, dev); - memory_region_init_io(&s->iomem, &strongarm_uart_ops, s, "uart", 0x10000); + memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_uart_ops, s, + "uart", 0x10000); sysbus_init_mmio(dev, &s->iomem); sysbus_init_irq(dev, &s->irq); @@ -1496,7 +1501,8 @@ static int strongarm_ssp_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq); - memory_region_init_io(&s->iomem, &strongarm_ssp_ops, s, "ssp", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &strongarm_ssp_ops, s, + "ssp", 0x1000); sysbus_init_mmio(dev, &s->iomem); s->bus = ssi_create_bus(&dev->qdev, "ssi"); @@ -1571,7 +1577,7 @@ StrongARMState *sa1110_init(MemoryRegion *sysmem, exit(1); } - memory_region_init_ram(&s->sdram, "strongarm.sdram", sdram_size); + memory_region_init_ram(&s->sdram, NULL, "strongarm.sdram", sdram_size); vmstate_register_ram_global(&s->sdram); memory_region_add_subregion(sysmem, SA_SDCS0, &s->sdram); diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c index 47818a5d0..47d1f4ff9 100644 --- a/hw/arm/tosa.c +++ b/hw/arm/tosa.c @@ -222,7 +222,7 @@ static void tosa_init(QEMUMachineInitArgs *args) mpu = pxa255_init(address_space_mem, tosa_binfo.ram_size); - memory_region_init_ram(rom, "tosa.rom", TOSA_ROM); + memory_region_init_ram(rom, NULL, "tosa.rom", TOSA_ROM); vmstate_register_ram_global(rom); memory_region_set_readonly(rom, true); memory_region_add_subregion(address_space_mem, 0, rom); diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c index 753757ea1..725f60fc5 100644 --- a/hw/arm/versatilepb.c +++ b/hw/arm/versatilepb.c @@ -154,7 +154,8 @@ static int vpb_sic_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->parent[i]); } s->irq = 31; - memory_region_init_io(&s->iomem, &vpb_sic_ops, s, "vpb-sic", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &vpb_sic_ops, s, + "vpb-sic", 0x1000); sysbus_init_mmio(dev, &s->iomem); return 0; } @@ -193,7 +194,7 @@ static void versatile_init(QEMUMachineInitArgs *args, int board_id) fprintf(stderr, "Unable to find CPU definition\n"); exit(1); } - memory_region_init_ram(ram, "versatile.ram", args->ram_size); + memory_region_init_ram(ram, NULL, "versatile.ram", args->ram_size); vmstate_register_ram_global(ram); /* ??? RAM should repeat to fill physical memory space. */ /* SDRAM at address zero. */ @@ -244,7 +245,7 @@ static void versatile_init(QEMUMachineInitArgs *args, int board_id) smc91c111_init(nd, 0x10010000, sic[25]); done_smc = 1; } else { - pci_nic_init_nofail(nd, "rtl8139", NULL); + pci_nic_init_nofail(nd, pci_bus, "rtl8139", NULL); } } if (usb_enabled(false)) { diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c index a077c6274..7d1b8233c 100644 --- a/hw/arm/vexpress.c +++ b/hw/arm/vexpress.c @@ -67,6 +67,7 @@ enum { VE_CLCD, VE_NORFLASH0, VE_NORFLASH1, + VE_NORFLASHALIAS, VE_SRAM, VE_VIDEORAM, VE_ETHERNET, @@ -104,9 +105,11 @@ static hwaddr motherboard_legacy_map[] = { [VE_VIDEORAM] = 0x4c000000, [VE_ETHERNET] = 0x4e000000, [VE_USB] = 0x4f000000, + [VE_NORFLASHALIAS] = -1, /* not present */ }; static hwaddr motherboard_aseries_map[] = { + [VE_NORFLASHALIAS] = 0, /* CS0: 0x08000000 .. 0x0c000000 */ [VE_NORFLASH0] = 0x08000000, /* CS4: 0x0c000000 .. 0x10000000 */ @@ -196,7 +199,7 @@ static void a9_daughterboard_init(const VEDBoardInfo *daughterboard, exit(1); } - memory_region_init_ram(ram, "vexpress.highmem", ram_size); + memory_region_init_ram(ram, NULL, "vexpress.highmem", ram_size); vmstate_register_ram_global(ram); low_ram_size = ram_size; if (low_ram_size > 0x4000000) { @@ -206,7 +209,7 @@ static void a9_daughterboard_init(const VEDBoardInfo *daughterboard, * address space should in theory be remappable to various * things including ROM or RAM; we always map the RAM there. */ - memory_region_init_alias(lowram, "vexpress.lowmem", ram, 0, low_ram_size); + memory_region_init_alias(lowram, NULL, "vexpress.lowmem", ram, 0, low_ram_size); memory_region_add_subregion(sysmem, 0x0, lowram); memory_region_add_subregion(sysmem, 0x60000000, ram); @@ -323,7 +326,7 @@ static void a15_daughterboard_init(const VEDBoardInfo *daughterboard, } } - memory_region_init_ram(ram, "vexpress.highmem", ram_size); + memory_region_init_ram(ram, NULL, "vexpress.highmem", ram_size); vmstate_register_ram_global(ram); /* RAM is from 0x80000000 upwards; there is no low-memory alias for it. */ memory_region_add_subregion(sysmem, 0x80000000, ram); @@ -357,7 +360,7 @@ static void a15_daughterboard_init(const VEDBoardInfo *daughterboard, /* 0x2b060000: SP805 watchdog: not modelled */ /* 0x2b0a0000: PL341 dynamic memory controller: not modelled */ /* 0x2e000000: system SRAM */ - memory_region_init_ram(sram, "vexpress.a15sram", 0x10000); + memory_region_init_ram(sram, NULL, "vexpress.a15sram", 0x10000); vmstate_register_ram_global(sram); memory_region_add_subregion(sysmem, 0x2e000000, sram); @@ -400,10 +403,13 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard, qemu_irq pic[64]; uint32_t sys_id; DriveInfo *dinfo; + pflash_t *pflash0; ram_addr_t vram_size, sram_size; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *vram = g_new(MemoryRegion, 1); MemoryRegion *sram = g_new(MemoryRegion, 1); + MemoryRegion *flashalias = g_new(MemoryRegion, 1); + MemoryRegion *flash0mem; const hwaddr *map = daughterboard->motherboard_map; int i; @@ -471,15 +477,24 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard, sysbus_create_simple("pl111", map[VE_CLCD], pic[14]); dinfo = drive_get_next(IF_PFLASH); - if (!pflash_cfi01_register(map[VE_NORFLASH0], NULL, "vexpress.flash0", + pflash0 = pflash_cfi01_register(map[VE_NORFLASH0], NULL, "vexpress.flash0", VEXPRESS_FLASH_SIZE, dinfo ? dinfo->bdrv : NULL, VEXPRESS_FLASH_SECT_SIZE, VEXPRESS_FLASH_SIZE / VEXPRESS_FLASH_SECT_SIZE, 4, - 0x00, 0x89, 0x00, 0x18, 0)) { + 0x00, 0x89, 0x00, 0x18, 0); + if (!pflash0) { fprintf(stderr, "vexpress: error registering flash 0.\n"); exit(1); } + if (map[VE_NORFLASHALIAS] != -1) { + /* Map flash 0 as an alias into low memory */ + flash0mem = sysbus_mmio_get_region(SYS_BUS_DEVICE(pflash0), 0); + memory_region_init_alias(flashalias, NULL, "vexpress.flashalias", + flash0mem, 0, VEXPRESS_FLASH_SIZE); + memory_region_add_subregion(sysmem, map[VE_NORFLASHALIAS], flashalias); + } + dinfo = drive_get_next(IF_PFLASH); if (!pflash_cfi01_register(map[VE_NORFLASH1], NULL, "vexpress.flash1", VEXPRESS_FLASH_SIZE, dinfo ? dinfo->bdrv : NULL, @@ -491,12 +506,12 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard, } sram_size = 0x2000000; - memory_region_init_ram(sram, "vexpress.sram", sram_size); + memory_region_init_ram(sram, NULL, "vexpress.sram", sram_size); vmstate_register_ram_global(sram); memory_region_add_subregion(sysmem, map[VE_SRAM], sram); vram_size = 0x800000; - memory_region_init_ram(vram, "vexpress.vram", vram_size); + memory_region_init_ram(vram, NULL, "vexpress.vram", vram_size); vmstate_register_ram_global(vram); memory_region_add_subregion(sysmem, map[VE_VIDEORAM], vram); @@ -519,7 +534,7 @@ static void vexpress_common_init(const VEDBoardInfo *daughterboard, vexpress_binfo.smp_loader_start = map[VE_SRAM]; vexpress_binfo.smp_bootreg_addr = map[VE_SYSREGS] + 0x30; vexpress_binfo.gic_cpu_if_addr = daughterboard->gic_cpu_if_addr; - arm_load_kernel(arm_env_get_cpu(first_cpu), &vexpress_binfo); + arm_load_kernel(ARM_CPU(first_cpu), &vexpress_binfo); } static void vexpress_a9_init(QEMUMachineInitArgs *args) diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c index 4602a6f57..3444823f3 100644 --- a/hw/arm/xilinx_zynq.c +++ b/hw/arm/xilinx_zynq.c @@ -132,12 +132,12 @@ static void zynq_init(QEMUMachineInitArgs *args) } /* DDR remapped to address zero. */ - memory_region_init_ram(ext_ram, "zynq.ext_ram", ram_size); + memory_region_init_ram(ext_ram, NULL, "zynq.ext_ram", ram_size); vmstate_register_ram_global(ext_ram); memory_region_add_subregion(address_space_mem, 0, ext_ram); /* 256K of on-chip memory */ - memory_region_init_ram(ocm_ram, "zynq.ocm_ram", 256 << 10); + memory_region_init_ram(ocm_ram, NULL, "zynq.ocm_ram", 256 << 10); vmstate_register_ram_global(ocm_ram); memory_region_add_subregion(address_space_mem, 0xFFFC0000, ocm_ram); @@ -226,7 +226,7 @@ static void zynq_init(QEMUMachineInitArgs *args) zynq_binfo.nb_cpus = 1; zynq_binfo.board_id = 0xd32; zynq_binfo.loader_start = 0; - arm_load_kernel(arm_env_get_cpu(first_cpu), &zynq_binfo); + arm_load_kernel(ARM_CPU(first_cpu), &zynq_binfo); } static QEMUMachine zynq_machine = { diff --git a/hw/audio/ac97.c b/hw/audio/ac97.c index baf138b41..365b2f186 100644 --- a/hw/audio/ac97.c +++ b/hw/audio/ac97.c @@ -1378,8 +1378,10 @@ static int ac97_initfn (PCIDevice *dev) c[PCI_INTERRUPT_LINE] = 0x00; /* intr_ln interrupt line rw */ c[PCI_INTERRUPT_PIN] = 0x01; /* intr_pn interrupt pin ro */ - memory_region_init_io (&s->io_nam, &ac97_io_nam_ops, s, "ac97-nam", 1024); - memory_region_init_io (&s->io_nabm, &ac97_io_nabm_ops, s, "ac97-nabm", 256); + memory_region_init_io (&s->io_nam, OBJECT(s), &ac97_io_nam_ops, s, + "ac97-nam", 1024); + memory_region_init_io (&s->io_nabm, OBJECT(s), &ac97_io_nabm_ops, s, + "ac97-nabm", 256); pci_register_bar (&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_nam); pci_register_bar (&s->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io_nabm); qemu_register_reset (ac97_on_reset, s); diff --git a/hw/audio/adlib.c b/hw/audio/adlib.c index 6a7d377fd..f72e6ee37 100644 --- a/hw/audio/adlib.c +++ b/hw/audio/adlib.c @@ -283,9 +283,17 @@ static void Adlib_fini (AdlibState *s) AUD_remove_card (&s->card); } +static MemoryRegionPortio adlib_portio_list[] = { + { 0x388, 4, 1, .read = adlib_read, .write = adlib_write, }, + { 0, 4, 1, .read = adlib_read, .write = adlib_write, }, + { 0, 2, 1, .read = adlib_read, .write = adlib_write, }, + PORTIO_END_OF_LIST(), +}; + static void adlib_realizefn (DeviceState *dev, Error **errp) { AdlibState *s = ADLIB(dev); + PortioList *port_list = g_new(PortioList, 1); struct audsettings as; if (glob_adlib) { @@ -339,14 +347,10 @@ static void adlib_realizefn (DeviceState *dev, Error **errp) s->samples = AUD_get_buffer_size_out (s->voice) >> SHIFT; s->mixbuf = g_malloc0 (s->samples << SHIFT); - register_ioport_read (0x388, 4, 1, adlib_read, s); - register_ioport_write (0x388, 4, 1, adlib_write, s); - - register_ioport_read (s->port, 4, 1, adlib_read, s); - register_ioport_write (s->port, 4, 1, adlib_write, s); - - register_ioport_read (s->port + 8, 2, 1, adlib_read, s); - register_ioport_write (s->port + 8, 2, 1, adlib_write, s); + adlib_portio_list[1].offset = s->port; + adlib_portio_list[2].offset = s->port + 8; + portio_list_init (port_list, OBJECT(s), adlib_portio_list, s, "adlib"); + portio_list_add (port_list, isa_address_space_io(&s->parent_obj), 0); } static Property adlib_properties[] = { diff --git a/hw/audio/cs4231.c b/hw/audio/cs4231.c index 297533605..fabe9e64a 100644 --- a/hw/audio/cs4231.c +++ b/hw/audio/cs4231.c @@ -144,7 +144,8 @@ static int cs4231_init1(SysBusDevice *dev) { CSState *s = FROM_SYSBUS(CSState, dev); - memory_region_init_io(&s->iomem, &cs_mem_ops, s, "cs4321", CS_SIZE); + memory_region_init_io(&s->iomem, OBJECT(s), &cs_mem_ops, s, "cs4321", + CS_SIZE); sysbus_init_mmio(dev, &s->iomem); sysbus_init_irq(dev, &s->irq); diff --git a/hw/audio/cs4231a.c b/hw/audio/cs4231a.c index 605dad498..7365c3c1d 100644 --- a/hw/audio/cs4231a.c +++ b/hw/audio/cs4231a.c @@ -648,7 +648,8 @@ static void cs4231a_initfn (Object *obj) { CSState *s = CS4231A (obj); - memory_region_init_io (&s->ioports, &cs_ioport_ops, s, "cs4231a", 4); + memory_region_init_io (&s->ioports, OBJECT(s), &cs_ioport_ops, s, + "cs4231a", 4); } static void cs4231a_realizefn (DeviceState *dev, Error **errp) diff --git a/hw/audio/es1370.c b/hw/audio/es1370.c index c1cd169c6..f2c40daec 100644 --- a/hw/audio/es1370.c +++ b/hw/audio/es1370.c @@ -1035,7 +1035,7 @@ static int es1370_initfn (PCIDevice *dev) c[PCI_MIN_GNT] = 0x0c; c[PCI_MAX_LAT] = 0x80; - memory_region_init_io (&s->io, &es1370_io_ops, s, "es1370", 256); + memory_region_init_io (&s->io, OBJECT(s), &es1370_io_ops, s, "es1370", 256); pci_register_bar (&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io); qemu_register_reset (es1370_on_reset, s); diff --git a/hw/audio/intel-hda.c b/hw/audio/intel-hda.c index 3ac90d510..58984dc73 100644 --- a/hw/audio/intel-hda.c +++ b/hw/audio/intel-hda.c @@ -1135,7 +1135,7 @@ static int intel_hda_init(PCIDevice *pci) /* HDCTL off 0x40 bit 0 selects signaling mode (1-HDA, 0 - Ac97) 18.1.19 */ conf[0x40] = 0x01; - memory_region_init_io(&d->mmio, &intel_hda_mmio_ops, d, + memory_region_init_io(&d->mmio, OBJECT(d), &intel_hda_mmio_ops, d, "intel-hda", 0x4000); pci_register_bar(&d->pci, 0, 0, &d->mmio); if (d->msi) { diff --git a/hw/audio/marvell_88w8618.c b/hw/audio/marvell_88w8618.c index c5d88a784..b40ea43c6 100644 --- a/hw/audio/marvell_88w8618.c +++ b/hw/audio/marvell_88w8618.c @@ -244,7 +244,7 @@ static int mv88w8618_audio_init(SysBusDevice *dev) wm8750_data_req_set(s->wm, mv88w8618_audio_callback, s); - memory_region_init_io(&s->iomem, &mv88w8618_audio_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &mv88w8618_audio_ops, s, "audio", MP_AUDIO_SIZE); sysbus_init_mmio(dev, &s->iomem); diff --git a/hw/audio/milkymist-ac97.c b/hw/audio/milkymist-ac97.c index e08e9dca1..133de4e74 100644 --- a/hw/audio/milkymist-ac97.c +++ b/hw/audio/milkymist-ac97.c @@ -300,7 +300,7 @@ static int milkymist_ac97_init(SysBusDevice *dev) s->voice_out = AUD_open_out(&s->card, s->voice_out, "mm_ac97.out", s, ac97_out_cb, &as); - memory_region_init_io(&s->regs_region, &ac97_mmio_ops, s, + memory_region_init_io(&s->regs_region, OBJECT(s), &ac97_mmio_ops, s, "milkymist-ac97", R_MAX * 4); sysbus_init_mmio(dev, &s->regs_region); diff --git a/hw/audio/pcspk.c b/hw/audio/pcspk.c index 5dde0e75d..7ad59a13e 100644 --- a/hw/audio/pcspk.c +++ b/hw/audio/pcspk.c @@ -167,7 +167,7 @@ static void pcspk_initfn(Object *obj) { PCSpkState *s = PC_SPEAKER(obj); - memory_region_init_io(&s->ioport, &pcspk_io_ops, s, "elcr", 1); + memory_region_init_io(&s->ioport, OBJECT(s), &pcspk_io_ops, s, "elcr", 1); } static void pcspk_realizefn(DeviceState *dev, Error **errp) diff --git a/hw/audio/pl041.c b/hw/audio/pl041.c index 653ab4fbb..7d331b957 100644 --- a/hw/audio/pl041.c +++ b/hw/audio/pl041.c @@ -543,7 +543,7 @@ static int pl041_init(SysBusDevice *dev) } /* Connect the device to the sysbus */ - memory_region_init_io(&s->iomem, &pl041_ops, s, "pl041", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &pl041_ops, s, "pl041", 0x1000); sysbus_init_mmio(dev, &s->iomem); sysbus_init_irq(dev, &s->irq); diff --git a/hw/block/fdc.c b/hw/block/fdc.c index 930f191d9..cdc00e59c 100644 --- a/hw/block/fdc.c +++ b/hw/block/fdc.c @@ -2149,7 +2149,8 @@ static int sysbus_fdc_init1(SysBusDevice *dev) FDCtrl *fdctrl = &sys->state; int ret; - memory_region_init_io(&fdctrl->iomem, &fdctrl_mem_ops, fdctrl, "fdc", 0x08); + memory_region_init_io(&fdctrl->iomem, OBJECT(sys), &fdctrl_mem_ops, fdctrl, + "fdc", 0x08); sysbus_init_mmio(dev, &fdctrl->iomem); sysbus_init_irq(dev, &fdctrl->irq); qdev_init_gpio_in(&dev->qdev, fdctrl_handle_tc, 1); @@ -2165,8 +2166,8 @@ static int sun4m_fdc_init1(SysBusDevice *dev) { FDCtrl *fdctrl = &(FROM_SYSBUS(FDCtrlSysBus, dev)->state); - memory_region_init_io(&fdctrl->iomem, &fdctrl_mem_strict_ops, fdctrl, - "fdctrl", 0x08); + memory_region_init_io(&fdctrl->iomem, OBJECT(dev), &fdctrl_mem_strict_ops, + fdctrl, "fdctrl", 0x08); sysbus_init_mmio(dev, &fdctrl->iomem); sysbus_init_irq(dev, &fdctrl->irq); qdev_init_gpio_in(&dev->qdev, fdctrl_handle_tc, 1); diff --git a/hw/block/nvme.c b/hw/block/nvme.c index 58b0d91d0..f15f04a33 100644 --- a/hw/block/nvme.c +++ b/hw/block/nvme.c @@ -777,7 +777,8 @@ static int nvme_init(PCIDevice *pci_dev) n->sq = g_malloc0(sizeof(*n->sq)*n->num_queues); n->cq = g_malloc0(sizeof(*n->cq)*n->num_queues); - memory_region_init_io(&n->iomem, &nvme_mmio_ops, n, "nvme", n->reg_size); + memory_region_init_io(&n->iomem, OBJECT(n), &nvme_mmio_ops, n, + "nvme", n->reg_size); pci_register_bar(&n->parent_obj, 0, PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64, &n->iomem); diff --git a/hw/block/onenand.c b/hw/block/onenand.c index 8b511a79d..2776f6468 100644 --- a/hw/block/onenand.c +++ b/hw/block/onenand.c @@ -113,9 +113,10 @@ static void onenand_mem_setup(OneNANDState *s) /* XXX: We should use IO_MEM_ROMD but we broke it earlier... * Both 0x0000 ... 0x01ff and 0x8000 ... 0x800f can be used to * write boot commands. Also take note of the BWPS bit. */ - memory_region_init(&s->container, "onenand", 0x10000 << s->shift); + memory_region_init(&s->container, OBJECT(s), "onenand", + 0x10000 << s->shift); memory_region_add_subregion(&s->container, 0, &s->iomem); - memory_region_init_alias(&s->mapped_ram, "onenand-mapped-ram", + memory_region_init_alias(&s->mapped_ram, OBJECT(s), "onenand-mapped-ram", &s->ram, 0x0200 << s->shift, 0xbe00 << s->shift); memory_region_add_subregion_overlap(&s->container, @@ -768,7 +769,7 @@ static int onenand_initfn(SysBusDevice *dev) s->blockwp = g_malloc(s->blocks); s->density_mask = (s->id.dev & 0x08) ? (1 << (6 + ((s->id.dev >> 4) & 7))) : 0; - memory_region_init_io(&s->iomem, &onenand_ops, s, "onenand", + memory_region_init_io(&s->iomem, OBJECT(s), &onenand_ops, s, "onenand", 0x10000 << s->shift); if (!s->bdrv) { s->image = memset(g_malloc(size + (size >> 5)), @@ -782,7 +783,8 @@ static int onenand_initfn(SysBusDevice *dev) } s->otp = memset(g_malloc((64 + 2) << PAGE_SHIFT), 0xff, (64 + 2) << PAGE_SHIFT); - memory_region_init_ram(&s->ram, "onenand.ram", 0xc000 << s->shift); + memory_region_init_ram(&s->ram, OBJECT(s), "onenand.ram", + 0xc000 << s->shift); vmstate_register_ram_global(&s->ram); ram = memory_region_get_ram_ptr(&s->ram); s->boot[0] = ram + (0x0000 << s->shift); diff --git a/hw/block/pc_sysfw.c b/hw/block/pc_sysfw.c index 412d1b0f7..0669410cf 100644 --- a/hw/block/pc_sysfw.c +++ b/hw/block/pc_sysfw.c @@ -59,7 +59,7 @@ static void pc_isa_bios_init(MemoryRegion *rom_memory, isa_bios_size = 128 * 1024; } isa_bios = g_malloc(sizeof(*isa_bios)); - memory_region_init_ram(isa_bios, "isa-bios", isa_bios_size); + memory_region_init_ram(isa_bios, NULL, "isa-bios", isa_bios_size); vmstate_register_ram_global(isa_bios); memory_region_add_subregion_overlap(rom_memory, 0x100000 - isa_bios_size, @@ -162,7 +162,7 @@ static void old_pc_system_rom_init(MemoryRegion *rom_memory, bool isapc_ram_fw) goto bios_error; } bios = g_malloc(sizeof(*bios)); - memory_region_init_ram(bios, "pc.bios", bios_size); + memory_region_init_ram(bios, NULL, "pc.bios", bios_size); vmstate_register_ram_global(bios); if (!isapc_ram_fw) { memory_region_set_readonly(bios, true); @@ -183,7 +183,7 @@ static void old_pc_system_rom_init(MemoryRegion *rom_memory, bool isapc_ram_fw) isa_bios_size = 128 * 1024; } isa_bios = g_malloc(sizeof(*isa_bios)); - memory_region_init_alias(isa_bios, "isa-bios", bios, + memory_region_init_alias(isa_bios, NULL, "isa-bios", bios, bios_size - isa_bios_size, isa_bios_size); memory_region_add_subregion_overlap(rom_memory, 0x100000 - isa_bios_size, diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c index 63d7c9951..6898a257d 100644 --- a/hw/block/pflash_cfi01.c +++ b/hw/block/pflash_cfi01.c @@ -579,7 +579,8 @@ static int pflash_cfi01_init(SysBusDevice *dev) #endif memory_region_init_rom_device( - &pfl->mem, pfl->be ? &pflash_cfi01_ops_be : &pflash_cfi01_ops_le, pfl, + &pfl->mem, OBJECT(dev), + pfl->be ? &pflash_cfi01_ops_be : &pflash_cfi01_ops_le, pfl, pfl->name, total_len); vmstate_register_ram(&pfl->mem, DEVICE(pfl)); pfl->storage = memory_region_get_ram_ptr(&pfl->mem); diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c index 5f2524692..d6cd3da46 100644 --- a/hw/block/pflash_cfi02.c +++ b/hw/block/pflash_cfi02.c @@ -100,11 +100,11 @@ static void pflash_setup_mappings(pflash_t *pfl) unsigned i; hwaddr size = memory_region_size(&pfl->orig_mem); - memory_region_init(&pfl->mem, "pflash", pfl->mappings * size); + memory_region_init(&pfl->mem, OBJECT(pfl), "pflash", pfl->mappings * size); pfl->mem_mappings = g_new(MemoryRegion, pfl->mappings); for (i = 0; i < pfl->mappings; ++i) { - memory_region_init_alias(&pfl->mem_mappings[i], "pflash-alias", - &pfl->orig_mem, 0, size); + memory_region_init_alias(&pfl->mem_mappings[i], OBJECT(pfl), + "pflash-alias", &pfl->orig_mem, 0, size); memory_region_add_subregion(&pfl->mem, i * size, &pfl->mem_mappings[i]); } } @@ -600,7 +600,7 @@ static int pflash_cfi02_init(SysBusDevice *dev) return NULL; #endif - memory_region_init_rom_device(&pfl->orig_mem, pfl->be ? + memory_region_init_rom_device(&pfl->orig_mem, OBJECT(pfl), pfl->be ? &pflash_cfi02_ops_be : &pflash_cfi02_ops_le, pfl, pfl->name, chip_len); vmstate_register_ram(&pfl->orig_mem, DEVICE(pfl)); diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c index 205e125de..4d457f8c6 100644 --- a/hw/char/cadence_uart.c +++ b/hw/char/cadence_uart.c @@ -157,7 +157,9 @@ static void uart_rx_reset(UartState *s) { s->rx_wpos = 0; s->rx_count = 0; - qemu_chr_accept_input(s->chr); + if (s->chr) { + qemu_chr_accept_input(s->chr); + } s->r[R_SR] |= UART_SR_INTR_REMPTY; s->r[R_SR] &= ~UART_SR_INTR_RFUL; @@ -442,7 +444,7 @@ static int cadence_uart_init(SysBusDevice *dev) { UartState *s = FROM_SYSBUS(UartState, dev); - memory_region_init_io(&s->iomem, &uart_ops, s, "uart", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &uart_ops, s, "uart", 0x1000); sysbus_init_mmio(dev, &s->iomem); sysbus_init_irq(dev, &s->irq); diff --git a/hw/char/debugcon.c b/hw/char/debugcon.c index f254841ae..03db12fda 100644 --- a/hw/char/debugcon.c +++ b/hw/char/debugcon.c @@ -103,7 +103,7 @@ static void debugcon_isa_realizefn(DeviceState *dev, Error **errp) error_propagate(errp, err); return; } - memory_region_init_io(&s->io, &debugcon_ops, s, + memory_region_init_io(&s->io, OBJECT(dev), &debugcon_ops, s, TYPE_ISA_DEBUGCON_DEVICE, 1); memory_region_add_subregion(isa_address_space_io(d), isa->iobase, &s->io); diff --git a/hw/char/escc.c b/hw/char/escc.c index c2cb07f3b..4c42198cb 100644 --- a/hw/char/escc.c +++ b/hw/char/escc.c @@ -96,14 +96,14 @@ typedef struct ChannelState { uint8_t rx, tx; } ChannelState; -struct SerialState { +typedef struct ESCCState { SysBusDevice busdev; struct ChannelState chn[2]; uint32_t it_shift; MemoryRegion mmio; uint32_t disabled; uint32_t frequency; -}; +} ESCCState; #define SERIAL_CTRL 0 #define SERIAL_DATA 1 @@ -309,7 +309,7 @@ static void escc_reset_chn(ChannelState *s) static void escc_reset(DeviceState *d) { - SerialState *s = container_of(d, SerialState, busdev.qdev); + ESCCState *s = container_of(d, ESCCState, busdev.qdev); escc_reset_chn(&s->chn[0]); escc_reset_chn(&s->chn[1]); @@ -466,7 +466,7 @@ static void escc_update_parameters(ChannelState *s) static void escc_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { - SerialState *serial = opaque; + ESCCState *serial = opaque; ChannelState *s; uint32_t saddr; int newreg, channel; @@ -568,7 +568,7 @@ static void escc_mem_write(void *opaque, hwaddr addr, static uint64_t escc_mem_read(void *opaque, hwaddr addr, unsigned size) { - SerialState *serial = opaque; + ESCCState *serial = opaque; ChannelState *s; uint32_t saddr; uint32_t ret; @@ -677,7 +677,7 @@ static const VMStateDescription vmstate_escc = { .minimum_version_id = 1, .minimum_version_id_old = 1, .fields = (VMStateField []) { - VMSTATE_STRUCT_ARRAY(chn, SerialState, 2, 2, vmstate_escc_chn, + VMSTATE_STRUCT_ARRAY(chn, ESCCState, 2, 2, vmstate_escc_chn, ChannelState), VMSTATE_END_OF_LIST() } @@ -689,7 +689,7 @@ MemoryRegion *escc_init(hwaddr base, qemu_irq irqA, qemu_irq irqB, { DeviceState *dev; SysBusDevice *s; - SerialState *d; + ESCCState *d; dev = qdev_create(NULL, "escc"); qdev_prop_set_uint32(dev, "disabled", 0); @@ -707,7 +707,7 @@ MemoryRegion *escc_init(hwaddr base, qemu_irq irqA, qemu_irq irqB, sysbus_mmio_map(s, 0, base); } - d = FROM_SYSBUS(SerialState, s); + d = FROM_SYSBUS(ESCCState, s); return &d->mmio; } @@ -869,7 +869,7 @@ void slavio_serial_ms_kbd_init(hwaddr base, qemu_irq irq, static int escc_init1(SysBusDevice *dev) { - SerialState *s = FROM_SYSBUS(SerialState, dev); + ESCCState *s = FROM_SYSBUS(ESCCState, dev); unsigned int i; s->chn[0].disabled = s->disabled; @@ -886,7 +886,7 @@ static int escc_init1(SysBusDevice *dev) s->chn[0].otherchn = &s->chn[1]; s->chn[1].otherchn = &s->chn[0]; - memory_region_init_io(&s->mmio, &escc_mem_ops, s, "escc", + memory_region_init_io(&s->mmio, OBJECT(s), &escc_mem_ops, s, "escc", ESCC_SIZE << s->it_shift); sysbus_init_mmio(dev, &s->mmio); @@ -902,13 +902,13 @@ static int escc_init1(SysBusDevice *dev) } static Property escc_properties[] = { - DEFINE_PROP_UINT32("frequency", SerialState, frequency, 0), - DEFINE_PROP_UINT32("it_shift", SerialState, it_shift, 0), - DEFINE_PROP_UINT32("disabled", SerialState, disabled, 0), - DEFINE_PROP_UINT32("chnBtype", SerialState, chn[0].type, 0), - DEFINE_PROP_UINT32("chnAtype", SerialState, chn[1].type, 0), - DEFINE_PROP_CHR("chrB", SerialState, chn[0].chr), - DEFINE_PROP_CHR("chrA", SerialState, chn[1].chr), + DEFINE_PROP_UINT32("frequency", ESCCState, frequency, 0), + DEFINE_PROP_UINT32("it_shift", ESCCState, it_shift, 0), + DEFINE_PROP_UINT32("disabled", ESCCState, disabled, 0), + DEFINE_PROP_UINT32("chnBtype", ESCCState, chn[0].type, 0), + DEFINE_PROP_UINT32("chnAtype", ESCCState, chn[1].type, 0), + DEFINE_PROP_CHR("chrB", ESCCState, chn[0].chr), + DEFINE_PROP_CHR("chrA", ESCCState, chn[1].chr), DEFINE_PROP_END_OF_LIST(), }; @@ -926,7 +926,7 @@ static void escc_class_init(ObjectClass *klass, void *data) static const TypeInfo escc_info = { .name = "escc", .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(SerialState), + .instance_size = sizeof(ESCCState), .class_init = escc_class_init, }; diff --git a/hw/char/etraxfs_ser.c b/hw/char/etraxfs_ser.c index 11820f586..d19af000a 100644 --- a/hw/char/etraxfs_ser.c +++ b/hw/char/etraxfs_ser.c @@ -211,7 +211,8 @@ static int etraxfs_ser_init(SysBusDevice *dev) struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev); sysbus_init_irq(dev, &s->irq); - memory_region_init_io(&s->mmio, &ser_ops, s, "etraxfs-serial", R_MAX * 4); + memory_region_init_io(&s->mmio, OBJECT(s), &ser_ops, s, + "etraxfs-serial", R_MAX * 4); sysbus_init_mmio(dev, &s->mmio); s->chr = qemu_char_get_next_serial(); diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c index 5751816c6..855ce7a2e 100644 --- a/hw/char/exynos4210_uart.c +++ b/hw/char/exynos4210_uart.c @@ -630,8 +630,8 @@ static int exynos4210_uart_init(SysBusDevice *dev) Exynos4210UartState *s = FROM_SYSBUS(Exynos4210UartState, dev); /* memory mapping */ - memory_region_init_io(&s->iomem, &exynos4210_uart_ops, s, "exynos4210.uart", - EXYNOS4210_UART_REGS_MEM_SIZE); + memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_uart_ops, s, + "exynos4210.uart", EXYNOS4210_UART_REGS_MEM_SIZE); sysbus_init_mmio(dev, &s->iomem); sysbus_init_irq(dev, &s->irq); diff --git a/hw/char/grlib_apbuart.c b/hw/char/grlib_apbuart.c index a64453fb1..82e1b95bc 100644 --- a/hw/char/grlib_apbuart.c +++ b/hw/char/grlib_apbuart.c @@ -242,7 +242,7 @@ static int grlib_apbuart_init(SysBusDevice *dev) sysbus_init_irq(dev, &uart->irq); - memory_region_init_io(&uart->iomem, &grlib_apbuart_ops, uart, + memory_region_init_io(&uart->iomem, OBJECT(uart), &grlib_apbuart_ops, uart, "uart", UART_REG_SIZE); sysbus_init_mmio(dev, &uart->iomem); diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c index 2a2c230c5..69b9ed2c4 100644 --- a/hw/char/imx_serial.c +++ b/hw/char/imx_serial.c @@ -386,7 +386,8 @@ static int imx_serial_init(SysBusDevice *dev) IMXSerialState *s = FROM_SYSBUS(IMXSerialState, dev); - memory_region_init_io(&s->iomem, &imx_serial_ops, s, "imx-serial", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &imx_serial_ops, s, + "imx-serial", 0x1000); sysbus_init_mmio(dev, &s->iomem); sysbus_init_irq(dev, &s->irq); diff --git a/hw/char/lm32_uart.c b/hw/char/lm32_uart.c index 99721ab78..37b38ba4e 100644 --- a/hw/char/lm32_uart.c +++ b/hw/char/lm32_uart.c @@ -250,7 +250,8 @@ static int lm32_uart_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq); - memory_region_init_io(&s->iomem, &uart_ops, s, "uart", R_MAX * 4); + memory_region_init_io(&s->iomem, OBJECT(s), &uart_ops, s, + "uart", R_MAX * 4); sysbus_init_mmio(dev, &s->iomem); s->chr = qemu_char_get_next_serial(); diff --git a/hw/char/mcf_uart.c b/hw/char/mcf_uart.c index 3ec470586..98fd44e66 100644 --- a/hw/char/mcf_uart.c +++ b/hw/char/mcf_uart.c @@ -302,6 +302,6 @@ void mcf_uart_mm_init(MemoryRegion *sysmem, mcf_uart_state *s; s = mcf_uart_init(irq, chr); - memory_region_init_io(&s->iomem, &mcf_uart_ops, s, "uart", 0x40); + memory_region_init_io(&s->iomem, NULL, &mcf_uart_ops, s, "uart", 0x40); memory_region_add_subregion(sysmem, base, &s->iomem); } diff --git a/hw/char/milkymist-uart.c b/hw/char/milkymist-uart.c index cbc7d73a6..46deab2c5 100644 --- a/hw/char/milkymist-uart.c +++ b/hw/char/milkymist-uart.c @@ -196,7 +196,7 @@ static int milkymist_uart_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq); - memory_region_init_io(&s->regs_region, &uart_mmio_ops, s, + memory_region_init_io(&s->regs_region, OBJECT(s), &uart_mmio_ops, s, "milkymist-uart", R_MAX * 4); sysbus_init_mmio(dev, &s->regs_region); diff --git a/hw/char/omap_uart.c b/hw/char/omap_uart.c index 5bb36ed2c..0b9169360 100644 --- a/hw/char/omap_uart.c +++ b/hw/char/omap_uart.c @@ -168,7 +168,7 @@ struct omap_uart_s *omap2_uart_init(MemoryRegion *sysmem, struct omap_uart_s *s = omap_uart_init(base, irq, fclk, iclk, txdma, rxdma, label, chr); - memory_region_init_io(&s->iomem, &omap_uart_ops, s, "omap.uart", 0x100); + memory_region_init_io(&s->iomem, NULL, &omap_uart_ops, s, "omap.uart", 0x100); s->ta = ta; diff --git a/hw/char/parallel.c b/hw/char/parallel.c index caa9eb4de..ad96ea59c 100644 --- a/hw/char/parallel.c +++ b/hw/char/parallel.c @@ -587,7 +587,7 @@ bool parallel_mm_init(MemoryRegion *address_space, s->it_shift = it_shift; qemu_register_reset(parallel_reset, s); - memory_region_init_io(&s->iomem, ¶llel_mm_ops, s, + memory_region_init_io(&s->iomem, NULL, ¶llel_mm_ops, s, "parallel", 8 << it_shift); memory_region_add_subregion(address_space, base, &s->iomem); return true; diff --git a/hw/char/pl011.c b/hw/char/pl011.c index 7079ef6be..ebec64f95 100644 --- a/hw/char/pl011.c +++ b/hw/char/pl011.c @@ -265,7 +265,7 @@ static int pl011_init(SysBusDevice *dev, const unsigned char *id) { pl011_state *s = FROM_SYSBUS(pl011_state, dev); - memory_region_init_io(&s->iomem, &pl011_ops, s, "pl011", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &pl011_ops, s, "pl011", 0x1000); sysbus_init_mmio(dev, &s->iomem); sysbus_init_irq(dev, &s->irq); s->id = id; diff --git a/hw/char/serial-isa.c b/hw/char/serial-isa.c index e06a802e2..cea821242 100644 --- a/hw/char/serial-isa.c +++ b/hw/char/serial-isa.c @@ -72,7 +72,7 @@ static void serial_isa_realizefn(DeviceState *dev, Error **errp) serial_realize_core(s, errp); qdev_set_legacy_instance_id(dev, isa->iobase, 3); - memory_region_init_io(&s->io, &serial_io_ops, s, "serial", 8); + memory_region_init_io(&s->io, OBJECT(isa), &serial_io_ops, s, "serial", 8); isa_register_ioport(isadev, &s->io, isa->iobase); } diff --git a/hw/char/serial-pci.c b/hw/char/serial-pci.c index 3bec8ebe7..a17c70262 100644 --- a/hw/char/serial-pci.c +++ b/hw/char/serial-pci.c @@ -63,7 +63,7 @@ static int serial_pci_init(PCIDevice *dev) pci->dev.config[PCI_INTERRUPT_PIN] = 0x01; s->irq = pci->dev.irq[0]; - memory_region_init_io(&s->io, &serial_io_ops, s, "serial", 8); + memory_region_init_io(&s->io, OBJECT(pci), &serial_io_ops, s, "serial", 8); pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io); return 0; } @@ -102,7 +102,7 @@ static int multi_serial_pci_init(PCIDevice *dev) assert(pci->ports <= PCI_SERIAL_MAX_PORTS); pci->dev.config[PCI_INTERRUPT_PIN] = 0x01; - memory_region_init(&pci->iobar, "multiserial", 8 * pci->ports); + memory_region_init(&pci->iobar, OBJECT(pci), "multiserial", 8 * pci->ports); pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->iobar); pci->irqs = qemu_allocate_irqs(multi_serial_irq_mux, pci, pci->ports); @@ -118,7 +118,8 @@ static int multi_serial_pci_init(PCIDevice *dev) } s->irq = pci->irqs[i]; pci->name[i] = g_strdup_printf("uart #%d", i+1); - memory_region_init_io(&s->io, &serial_io_ops, s, pci->name[i], 8); + memory_region_init_io(&s->io, OBJECT(pci), &serial_io_ops, s, + pci->name[i], 8); memory_region_add_subregion(&pci->iobar, 8 * i, &s->io); } return 0; diff --git a/hw/char/serial.c b/hw/char/serial.c index 6382f9838..602559254 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -703,7 +703,7 @@ SerialState *serial_init(int base, qemu_irq irq, int baudbase, vmstate_register(NULL, base, &vmstate_serial, s); - memory_region_init_io(&s->io, &serial_io_ops, s, "serial", 8); + memory_region_init_io(&s->io, NULL, &serial_io_ops, s, "serial", 8); memory_region_add_subregion(system_io, base, &s->io); return s; @@ -766,7 +766,7 @@ SerialState *serial_mm_init(MemoryRegion *address_space, } vmstate_register(NULL, base, &vmstate_serial, s); - memory_region_init_io(&s->io, &serial_mm_ops[end], s, + memory_region_init_io(&s->io, NULL, &serial_mm_ops[end], s, "serial", 8 << it_shift); memory_region_add_subregion(address_space, base, &s->io); diff --git a/hw/char/sh_serial.c b/hw/char/sh_serial.c index b3286438c..6223a557b 100644 --- a/hw/char/sh_serial.c +++ b/hw/char/sh_serial.c @@ -383,14 +383,14 @@ void sh_serial_init(MemoryRegion *sysmem, sh_serial_clear_fifo(s); - memory_region_init_io(&s->iomem, &sh_serial_ops, s, + memory_region_init_io(&s->iomem, NULL, &sh_serial_ops, s, "serial", 0x100000000ULL); - memory_region_init_alias(&s->iomem_p4, "serial-p4", &s->iomem, + memory_region_init_alias(&s->iomem_p4, NULL, "serial-p4", &s->iomem, 0, 0x28); memory_region_add_subregion(sysmem, P4ADDR(base), &s->iomem_p4); - memory_region_init_alias(&s->iomem_a7, "serial-a7", &s->iomem, + memory_region_init_alias(&s->iomem_a7, NULL, "serial-a7", &s->iomem, 0, 0x28); memory_region_add_subregion(sysmem, A7ADDR(base), &s->iomem_a7); diff --git a/hw/char/tpci200.c b/hw/char/tpci200.c index 01706020b..a199e5752 100644 --- a/hw/char/tpci200.c +++ b/hw/char/tpci200.c @@ -588,17 +588,17 @@ static int tpci200_initfn(PCIDevice *pci_dev) pci_set_long(c + 0x48, 0x00024C06); pci_set_long(c + 0x4C, 0x00000003); - memory_region_init_io(&s->mmio, &tpci200_cfg_ops, + memory_region_init_io(&s->mmio, OBJECT(s), &tpci200_cfg_ops, s, "tpci200_mmio", 128); - memory_region_init_io(&s->io, &tpci200_cfg_ops, + memory_region_init_io(&s->io, OBJECT(s), &tpci200_cfg_ops, s, "tpci200_io", 128); - memory_region_init_io(&s->las0, &tpci200_las0_ops, + memory_region_init_io(&s->las0, OBJECT(s), &tpci200_las0_ops, s, "tpci200_las0", 256); - memory_region_init_io(&s->las1, &tpci200_las1_ops, + memory_region_init_io(&s->las1, OBJECT(s), &tpci200_las1_ops, s, "tpci200_las1", 1024); - memory_region_init_io(&s->las2, &tpci200_las2_ops, + memory_region_init_io(&s->las2, OBJECT(s), &tpci200_las2_ops, s, "tpci200_las2", 1024*1024*32); - memory_region_init_io(&s->las3, &tpci200_las3_ops, + memory_region_init_io(&s->las3, OBJECT(s), &tpci200_las3_ops, s, "tpci200_las3", 1024*1024*16); pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio); pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io); diff --git a/hw/char/xilinx_uartlite.c b/hw/char/xilinx_uartlite.c index 3f7e989f3..feca497f5 100644 --- a/hw/char/xilinx_uartlite.c +++ b/hw/char/xilinx_uartlite.c @@ -199,8 +199,8 @@ static int xilinx_uartlite_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq); uart_update_status(s); - memory_region_init_io(&s->mmio, &uart_ops, s, "xlnx.xps-uartlite", - R_MAX * 4); + memory_region_init_io(&s->mmio, OBJECT(s), &uart_ops, s, + "xlnx.xps-uartlite", R_MAX * 4); sysbus_init_mmio(dev, &s->mmio); s->chr = qemu_char_get_next_serial(); diff --git a/hw/core/empty_slot.c b/hw/core/empty_slot.c index 5234a4ddc..e6249912c 100644 --- a/hw/core/empty_slot.c +++ b/hw/core/empty_slot.c @@ -70,7 +70,7 @@ static int empty_slot_init1(SysBusDevice *dev) { EmptySlot *s = FROM_SYSBUS(EmptySlot, dev); - memory_region_init_io(&s->iomem, &empty_slot_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &empty_slot_ops, s, "empty-slot", s->size); sysbus_init_mmio(dev, &s->iomem); return 0; diff --git a/hw/core/loader.c b/hw/core/loader.c index d56963699..44311ff43 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -727,6 +727,7 @@ int rom_load_all(void) addr += rom->romsize; section = memory_region_find(get_system_memory(), rom->addr, 1); rom->isrom = int128_nz(section.size) && memory_region_is_rom(section.mr); + memory_region_unref(section.mr); } qemu_register_reset(rom_reset, NULL); roms_loaded = 1; diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c index 648656d5b..c736257f2 100644 --- a/hw/cpu/a15mpcore.c +++ b/hw/cpu/a15mpcore.c @@ -68,7 +68,8 @@ static int a15mp_priv_init(SysBusDevice *dev) * 0x5000-0x5fff -- GIC virtual interface control (not modelled) * 0x6000-0x7fff -- GIC virtual CPU interface (not modelled) */ - memory_region_init(&s->container, "a15mp-priv-container", 0x8000); + memory_region_init(&s->container, OBJECT(s), + "a15mp-priv-container", 0x8000); memory_region_add_subregion(&s->container, 0x1000, sysbus_mmio_get_region(busdev, 0)); memory_region_add_subregion(&s->container, 0x2000, @@ -81,12 +82,12 @@ static int a15mp_priv_init(SysBusDevice *dev) static Property a15mp_priv_properties[] = { DEFINE_PROP_UINT32("num-cpu", A15MPPrivState, num_cpu, 1), /* The Cortex-A15MP may have anything from 0 to 224 external interrupt - * IRQ lines (with another 32 internal). We default to 64+32, which + * IRQ lines (with another 32 internal). We default to 128+32, which * is the number provided by the Cortex-A15MP test chip in the * Versatile Express A15 development board. * Other boards may differ and should set this property appropriately. */ - DEFINE_PROP_UINT32("num-irq", A15MPPrivState, num_irq, 96), + DEFINE_PROP_UINT32("num-irq", A15MPPrivState, num_irq, 160), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/cpu/a9mpcore.c b/hw/cpu/a9mpcore.c index 0a1a10f37..6c00a59fa 100644 --- a/hw/cpu/a9mpcore.c +++ b/hw/cpu/a9mpcore.c @@ -71,7 +71,7 @@ static int a9mp_priv_init(SysBusDevice *dev) * * We should implement the global timer but don't currently do so. */ - memory_region_init(&s->container, "a9mp-priv-container", 0x2000); + memory_region_init(&s->container, OBJECT(s), "a9mp-priv-container", 0x2000); memory_region_add_subregion(&s->container, 0, sysbus_mmio_get_region(scubusdev, 0)); /* GIC CPU interface */ diff --git a/hw/cpu/arm11mpcore.c b/hw/cpu/arm11mpcore.c index 90dceade7..8eeb53e60 100644 --- a/hw/cpu/arm11mpcore.c +++ b/hw/cpu/arm11mpcore.c @@ -87,8 +87,10 @@ static void mpcore_priv_map_setup(ARM11MPCorePriveState *s) SysBusDevice *gicbusdev = SYS_BUS_DEVICE(s->gic); SysBusDevice *timerbusdev = SYS_BUS_DEVICE(s->mptimer); SysBusDevice *wdtbusdev = SYS_BUS_DEVICE(s->wdtimer); - memory_region_init(&s->container, "mpcode-priv-container", 0x2000); - memory_region_init_io(&s->iomem, &mpcore_scu_ops, s, "mpcore-scu", 0x100); + memory_region_init(&s->container, OBJECT(s), + "mpcode-priv-container", 0x2000); + memory_region_init_io(&s->iomem, OBJECT(s), + &mpcore_scu_ops, s, "mpcore-scu", 0x100); memory_region_add_subregion(&s->container, 0, &s->iomem); /* GIC CPU interfaces: "current CPU" at 0x100, then specific CPUs * at 0x200, 0x300... diff --git a/hw/cpu/icc_bus.c b/hw/cpu/icc_bus.c index 73a1dc985..8788144b9 100644 --- a/hw/cpu/icc_bus.c +++ b/hw/cpu/icc_bus.c @@ -95,7 +95,7 @@ static void icc_bridge_init(Object *obj) /* Do not change order of registering regions, * APIC must be first registered region, board maps it by 0 index */ - memory_region_init(&s->apic_container, "icc-apic-container", + memory_region_init(&s->apic_container, obj, "icc-apic-container", APIC_SPACE_SIZE); sysbus_init_mmio(sb, &s->apic_container); s->icc_bus.apic_address_space = &s->apic_container; diff --git a/hw/cris/axis_dev88.c b/hw/cris/axis_dev88.c index 747567130..9104d6194 100644 --- a/hw/cris/axis_dev88.c +++ b/hw/cris/axis_dev88.c @@ -269,13 +269,13 @@ void axisdev88_init(QEMUMachineInitArgs *args) env = &cpu->env; /* allocate RAM */ - memory_region_init_ram(phys_ram, "axisdev88.ram", ram_size); + memory_region_init_ram(phys_ram, NULL, "axisdev88.ram", ram_size); vmstate_register_ram_global(phys_ram); memory_region_add_subregion(address_space_mem, 0x40000000, phys_ram); /* The ETRAX-FS has 128Kb on chip ram, the docs refer to it as the internal memory. */ - memory_region_init_ram(phys_intmem, "axisdev88.chipram", INTMEM_SIZE); + memory_region_init_ram(phys_intmem, NULL, "axisdev88.chipram", INTMEM_SIZE); vmstate_register_ram_global(phys_intmem); memory_region_add_subregion(address_space_mem, 0x38000000, phys_intmem); @@ -283,13 +283,13 @@ void axisdev88_init(QEMUMachineInitArgs *args) nand = drive_get(IF_MTD, 0, 0); nand_state.nand = nand_init(nand ? nand->bdrv : NULL, NAND_MFR_STMICRO, 0x39); - memory_region_init_io(&nand_state.iomem, &nand_ops, &nand_state, + memory_region_init_io(&nand_state.iomem, NULL, &nand_ops, &nand_state, "nand", 0x05000000); memory_region_add_subregion(address_space_mem, 0x10000000, &nand_state.iomem); gpio_state.nand = &nand_state; - memory_region_init_io(&gpio_state.iomem, &gpio_ops, &gpio_state, + memory_region_init_io(&gpio_state.iomem, NULL, &gpio_ops, &gpio_state, "gpio", 0x5c); memory_region_add_subregion(address_space_mem, 0x3001a000, &gpio_state.iomem); diff --git a/hw/display/cirrus_vga.c b/hw/display/cirrus_vga.c index 0d9eee876..a440575de 100644 --- a/hw/display/cirrus_vga.c +++ b/hw/display/cirrus_vga.c @@ -2805,7 +2805,8 @@ static const MemoryRegionOps cirrus_vga_io_ops = { }, }; -static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci, +static void cirrus_init_common(CirrusVGAState *s, Object *owner, + int device_id, int is_pci, MemoryRegion *system_memory, MemoryRegion *system_io) { @@ -2840,21 +2841,22 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci, } /* Register ioport 0x3b0 - 0x3df */ - memory_region_init_io(&s->cirrus_vga_io, &cirrus_vga_io_ops, s, + memory_region_init_io(&s->cirrus_vga_io, owner, &cirrus_vga_io_ops, s, "cirrus-io", 0x30); memory_region_add_subregion(system_io, 0x3b0, &s->cirrus_vga_io); - memory_region_init(&s->low_mem_container, + memory_region_init(&s->low_mem_container, owner, "cirrus-lowmem-container", 0x20000); - memory_region_init_io(&s->low_mem, &cirrus_vga_mem_ops, s, + memory_region_init_io(&s->low_mem, owner, &cirrus_vga_mem_ops, s, "cirrus-low-memory", 0x20000); memory_region_add_subregion(&s->low_mem_container, 0, &s->low_mem); for (i = 0; i < 2; ++i) { static const char *names[] = { "vga.bank0", "vga.bank1" }; MemoryRegion *bank = &s->cirrus_bank[i]; - memory_region_init_alias(bank, names[i], &s->vga.vram, 0, 0x8000); + memory_region_init_alias(bank, owner, names[i], &s->vga.vram, + 0, 0x8000); memory_region_set_enabled(bank, false); memory_region_add_subregion_overlap(&s->low_mem_container, i * 0x8000, bank, 1); @@ -2866,13 +2868,13 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci, memory_region_set_coalescing(&s->low_mem); /* I/O handler for LFB */ - memory_region_init_io(&s->cirrus_linear_io, &cirrus_linear_io_ops, s, + memory_region_init_io(&s->cirrus_linear_io, owner, &cirrus_linear_io_ops, s, "cirrus-linear-io", s->vga.vram_size_mb * 1024 * 1024); memory_region_set_flush_coalesced(&s->cirrus_linear_io); /* I/O handler for LFB */ - memory_region_init_io(&s->cirrus_linear_bitblt_io, + memory_region_init_io(&s->cirrus_linear_bitblt_io, owner, &cirrus_linear_bitblt_io_ops, s, "cirrus-bitblt-mmio", @@ -2880,7 +2882,7 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci, memory_region_set_flush_coalesced(&s->cirrus_linear_bitblt_io); /* I/O handler for memory-mapped I/O */ - memory_region_init_io(&s->cirrus_mmio_io, &cirrus_mmio_io_ops, s, + memory_region_init_io(&s->cirrus_mmio_io, owner, &cirrus_mmio_io_ops, s, "cirrus-mmio", CIRRUS_PNPMMIO_SIZE); memory_region_set_flush_coalesced(&s->cirrus_mmio_io); @@ -2912,8 +2914,8 @@ static void isa_cirrus_vga_realizefn(DeviceState *dev, Error **errp) ISACirrusVGAState *d = ISA_CIRRUS_VGA(dev); VGACommonState *s = &d->cirrus_vga.vga; - vga_common_init(s); - cirrus_init_common(&d->cirrus_vga, CIRRUS_ID_CLGD5430, 0, + vga_common_init(s, OBJECT(dev)); + cirrus_init_common(&d->cirrus_vga, OBJECT(dev), CIRRUS_ID_CLGD5430, 0, isa_address_space(isadev), isa_address_space_io(isadev)); s->con = graphic_console_init(dev, s->hw_ops, s); @@ -2958,14 +2960,14 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev) int16_t device_id = pc->device_id; /* setup VGA */ - vga_common_init(&s->vga); - cirrus_init_common(s, device_id, 1, pci_address_space(dev), + vga_common_init(&s->vga, OBJECT(dev)); + cirrus_init_common(s, OBJECT(dev), device_id, 1, pci_address_space(dev), pci_address_space_io(dev)); s->vga.con = graphic_console_init(DEVICE(dev), s->vga.hw_ops, &s->vga); /* setup PCI */ - memory_region_init(&s->pci_bar, "cirrus-pci-bar0", 0x2000000); + memory_region_init(&s->pci_bar, OBJECT(dev), "cirrus-pci-bar0", 0x2000000); /* XXX: add byte swapping apertures */ memory_region_add_subregion(&s->pci_bar, 0, &s->cirrus_linear_io); diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c index 0da00a9f9..eb168eaf1 100644 --- a/hw/display/exynos4210_fimd.c +++ b/hw/display/exynos4210_fimd.c @@ -1126,6 +1126,11 @@ static void fimd_update_memory_section(Exynos4210fimdState *s, unsigned win) /* Total number of bytes of virtual screen used by current window */ w->fb_len = fb_mapped_len = (w->virtpage_width + w->virtpage_offsize) * (w->rightbot_y - w->lefttop_y + 1); + + /* TODO: add .exit and unref the region there. Not needed yet since sysbus + * does not support hot-unplug. + */ + memory_region_unref(w->mem_section.mr); w->mem_section = memory_region_find(sysbus_address_space(&s->busdev), fb_start_addr, w->fb_len); assert(w->mem_section.mr); @@ -1154,6 +1159,7 @@ static void fimd_update_memory_section(Exynos4210fimdState *s, unsigned win) return; error_return: + memory_region_unref(w->mem_section.mr); w->mem_section.mr = NULL; w->mem_section.size = int128_zero(); w->host_fb_addr = NULL; @@ -1902,7 +1908,7 @@ static int exynos4210_fimd_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq[1]); sysbus_init_irq(dev, &s->irq[2]); - memory_region_init_io(&s->iomem, &exynos4210_fimd_mmio_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_fimd_mmio_ops, s, "exynos4210.fimd", FIMD_REGS_SIZE); sysbus_init_mmio(dev, &s->iomem); s->console = graphic_console_init(DEVICE(dev), &exynos4210_fimd_ops, s); diff --git a/hw/display/framebuffer.c b/hw/display/framebuffer.c index 49c9e5904..4546e4265 100644 --- a/hw/display/framebuffer.c +++ b/hw/display/framebuffer.c @@ -54,11 +54,11 @@ void framebuffer_update_display( src_len = src_width * rows; mem_section = memory_region_find(address_space, base, src_len); + mem = mem_section.mr; if (int128_get64(mem_section.size) != src_len || !memory_region_is_ram(mem_section.mr)) { - return; + goto out; } - mem = mem_section.mr; assert(mem); assert(mem_section.offset_within_address_space == base); @@ -68,10 +68,10 @@ void framebuffer_update_display( but it's not really worth it as dirty flag tracking will probably already have failed above. */ if (!src_base) - return; + goto out; if (src_len != src_width * rows) { cpu_physical_memory_unmap(src_base, src_len, 0, 0); - return; + goto out; } src = src_base; dest = surface_data(ds); @@ -102,10 +102,12 @@ void framebuffer_update_display( } cpu_physical_memory_unmap(src_base, src_len, 0, 0); if (first < 0) { - return; + goto out; } memory_region_reset_dirty(mem, mem_section.offset_within_region, src_len, DIRTY_MEMORY_VGA); *first_row = first; *last_row = last; +out: + memory_region_unref(mem); } diff --git a/hw/display/g364fb.c b/hw/display/g364fb.c index 2a4047e1e..79a0a5063 100644 --- a/hw/display/g364fb.c +++ b/hw/display/g364fb.c @@ -486,8 +486,8 @@ static void g364fb_init(DeviceState *dev, G364State *s) s->con = graphic_console_init(dev, &g364fb_ops, s); - memory_region_init_io(&s->mem_ctrl, &g364fb_ctrl_ops, s, "ctrl", 0x180000); - memory_region_init_ram_ptr(&s->mem_vram, "vram", + memory_region_init_io(&s->mem_ctrl, NULL, &g364fb_ctrl_ops, s, "ctrl", 0x180000); + memory_region_init_ram_ptr(&s->mem_vram, NULL, "vram", s->vram_size, s->vram); vmstate_register_ram(&s->mem_vram, dev); memory_region_set_coalescing(&s->mem_vram); diff --git a/hw/display/jazz_led.c b/hw/display/jazz_led.c index 52035fcac..7f82037d9 100644 --- a/hw/display/jazz_led.c +++ b/hw/display/jazz_led.c @@ -264,7 +264,7 @@ static int jazz_led_init(SysBusDevice *dev) { LedState *s = FROM_SYSBUS(LedState, dev); - memory_region_init_io(&s->iomem, &led_ops, s, "led", 1); + memory_region_init_io(&s->iomem, OBJECT(s), &led_ops, s, "led", 1); sysbus_init_mmio(dev, &s->iomem); s->con = graphic_console_init(DEVICE(dev), &jazz_led_ops, s); diff --git a/hw/display/milkymist-tmu2.c b/hw/display/milkymist-tmu2.c index b723a04cc..efda0824f 100644 --- a/hw/display/milkymist-tmu2.c +++ b/hw/display/milkymist-tmu2.c @@ -447,7 +447,7 @@ static int milkymist_tmu2_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq); - memory_region_init_io(&s->regs_region, &tmu2_mmio_ops, s, + memory_region_init_io(&s->regs_region, OBJECT(s), &tmu2_mmio_ops, s, "milkymist-tmu2", R_MAX * 4); sysbus_init_mmio(dev, &s->regs_region); diff --git a/hw/display/milkymist-vgafb.c b/hw/display/milkymist-vgafb.c index 3828296a3..870b33958 100644 --- a/hw/display/milkymist-vgafb.c +++ b/hw/display/milkymist-vgafb.c @@ -279,7 +279,7 @@ static int milkymist_vgafb_init(SysBusDevice *dev) { MilkymistVgafbState *s = FROM_SYSBUS(typeof(*s), dev); - memory_region_init_io(&s->regs_region, &vgafb_mmio_ops, s, + memory_region_init_io(&s->regs_region, OBJECT(s), &vgafb_mmio_ops, s, "milkymist-vgafb", R_MAX * 4); sysbus_init_mmio(dev, &s->regs_region); diff --git a/hw/display/omap_dss.c b/hw/display/omap_dss.c index ea3afcef5..24ccbcc7a 100644 --- a/hw/display/omap_dss.c +++ b/hw/display/omap_dss.c @@ -1053,15 +1053,15 @@ struct omap_dss_s *omap_dss_init(struct omap_target_agent_s *ta, s->drq = drq; omap_dss_reset(s); - memory_region_init_io(&s->iomem_diss1, &omap_diss_ops, s, "omap.diss1", + memory_region_init_io(&s->iomem_diss1, NULL, &omap_diss_ops, s, "omap.diss1", omap_l4_region_size(ta, 0)); - memory_region_init_io(&s->iomem_disc1, &omap_disc_ops, s, "omap.disc1", + memory_region_init_io(&s->iomem_disc1, NULL, &omap_disc_ops, s, "omap.disc1", omap_l4_region_size(ta, 1)); - memory_region_init_io(&s->iomem_rfbi1, &omap_rfbi_ops, s, "omap.rfbi1", + memory_region_init_io(&s->iomem_rfbi1, NULL, &omap_rfbi_ops, s, "omap.rfbi1", omap_l4_region_size(ta, 2)); - memory_region_init_io(&s->iomem_venc1, &omap_venc_ops, s, "omap.venc1", + memory_region_init_io(&s->iomem_venc1, NULL, &omap_venc_ops, s, "omap.venc1", omap_l4_region_size(ta, 3)); - memory_region_init_io(&s->iomem_im3, &omap_im3_ops, s, + memory_region_init_io(&s->iomem_im3, NULL, &omap_im3_ops, s, "omap.im3", 0x1000); omap_l4_attach(ta, 0, &s->iomem_diss1); diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c index fb72ebee4..c3b9b6897 100644 --- a/hw/display/omap_lcdc.c +++ b/hw/display/omap_lcdc.c @@ -403,7 +403,7 @@ struct omap_lcd_panel_s *omap_lcdc_init(MemoryRegion *sysmem, s->sysmem = sysmem; omap_lcdc_reset(s); - memory_region_init_io(&s->iomem, &omap_lcdc_ops, s, "omap.lcdc", 0x100); + memory_region_init_io(&s->iomem, NULL, &omap_lcdc_ops, s, "omap.lcdc", 0x100); memory_region_add_subregion(sysmem, base, &s->iomem); s->con = graphic_console_init(NULL, &omap_ops, s); diff --git a/hw/display/pl110.c b/hw/display/pl110.c index f25995540..60afcf39e 100644 --- a/hw/display/pl110.c +++ b/hw/display/pl110.c @@ -453,7 +453,7 @@ static int pl110_init(SysBusDevice *dev) { pl110_state *s = FROM_SYSBUS(pl110_state, dev); - memory_region_init_io(&s->iomem, &pl110_ops, s, "pl110", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &pl110_ops, s, "pl110", 0x1000); sysbus_init_mmio(dev, &s->iomem); sysbus_init_irq(dev, &s->irq); qdev_init_gpio_in(&s->busdev.qdev, pl110_mux_ctrl_set, 1); diff --git a/hw/display/pxa2xx_lcd.c b/hw/display/pxa2xx_lcd.c index 3b68f2678..990931ae4 100644 --- a/hw/display/pxa2xx_lcd.c +++ b/hw/display/pxa2xx_lcd.c @@ -1009,7 +1009,7 @@ PXA2xxLCDState *pxa2xx_lcdc_init(MemoryRegion *sysmem, pxa2xx_lcdc_orientation(s, graphic_rotate); - memory_region_init_io(&s->iomem, &pxa2xx_lcdc_ops, s, + memory_region_init_io(&s->iomem, NULL, &pxa2xx_lcdc_ops, s, "pxa2xx-lcd-controller", 0x00100000); memory_region_add_subregion(sysmem, base, &s->iomem); diff --git a/hw/display/qxl.c b/hw/display/qxl.c index 937a402b2..ddefa0668 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -23,6 +23,7 @@ #include "qemu-common.h" #include "qemu/timer.h" #include "qemu/queue.h" +#include "qemu/atomic.h" #include "monitor/monitor.h" #include "sysemu/sysemu.h" #include "trace.h" @@ -1726,7 +1727,7 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events) trace_qxl_send_events_vm_stopped(d->id, events); return; } - old_pending = __sync_fetch_and_or(&d->ram->int_pending, le_events); + old_pending = atomic_fetch_or(&d->ram->int_pending, le_events); if ((old_pending & le_events) == le_events) { return; } @@ -1981,18 +1982,20 @@ static int qxl_init_common(PCIQXLDevice *qxl) pci_set_byte(&config[PCI_INTERRUPT_PIN], 1); qxl->rom_size = qxl_rom_size(); - memory_region_init_ram(&qxl->rom_bar, "qxl.vrom", qxl->rom_size); + memory_region_init_ram(&qxl->rom_bar, OBJECT(qxl), "qxl.vrom", + qxl->rom_size); vmstate_register_ram(&qxl->rom_bar, &qxl->pci.qdev); init_qxl_rom(qxl); init_qxl_ram(qxl); qxl->guest_surfaces.cmds = g_new0(QXLPHYSICAL, qxl->ssd.num_surfaces); - memory_region_init_ram(&qxl->vram_bar, "qxl.vram", qxl->vram_size); + memory_region_init_ram(&qxl->vram_bar, OBJECT(qxl), "qxl.vram", + qxl->vram_size); vmstate_register_ram(&qxl->vram_bar, &qxl->pci.qdev); - memory_region_init_alias(&qxl->vram32_bar, "qxl.vram32", &qxl->vram_bar, - 0, qxl->vram32_size); + memory_region_init_alias(&qxl->vram32_bar, OBJECT(qxl), "qxl.vram32", + &qxl->vram_bar, 0, qxl->vram32_size); - memory_region_init_io(&qxl->io_bar, &qxl_io_ops, qxl, + memory_region_init_io(&qxl->io_bar, OBJECT(qxl), &qxl_io_ops, qxl, "qxl-ioports", io_size); if (qxl->id == 0) { vga_dirty_log_start(&qxl->vga); @@ -2067,9 +2070,11 @@ static int qxl_init_primary(PCIDevice *dev) qxl->id = 0; qxl_init_ramsize(qxl); vga->vram_size_mb = qxl->vga.vram_size >> 20; - vga_common_init(vga); - vga_init(vga, pci_address_space(dev), pci_address_space_io(dev), false); - portio_list_init(qxl_vga_port_list, qxl_vga_portio_list, vga, "vga"); + vga_common_init(vga, OBJECT(dev)); + vga_init(vga, OBJECT(dev), + pci_address_space(dev), pci_address_space_io(dev), false); + portio_list_init(qxl_vga_port_list, OBJECT(dev), qxl_vga_portio_list, + vga, "vga"); portio_list_add(qxl_vga_port_list, pci_address_space_io(dev), 0x3b0); vga->con = graphic_console_init(DEVICE(dev), &qxl_ops, qxl); @@ -2093,7 +2098,8 @@ static int qxl_init_secondary(PCIDevice *dev) qxl->id = device_id++; qxl_init_ramsize(qxl); - memory_region_init_ram(&qxl->vga.vram, "qxl.vgavram", qxl->vga.vram_size); + memory_region_init_ram(&qxl->vga.vram, OBJECT(dev), "qxl.vgavram", + qxl->vga.vram_size); vmstate_register_ram(&qxl->vga.vram, &qxl->pci.qdev); qxl->vga.vram_ptr = memory_region_get_ram_ptr(&qxl->vga.vram); qxl->vga.con = graphic_console_init(DEVICE(dev), &qxl_ops, qxl); diff --git a/hw/display/sm501.c b/hw/display/sm501.c index f72e4882a..c75d6ac63 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -1408,23 +1408,23 @@ void sm501_init(MemoryRegion *address_space_mem, uint32_t base, s->dc_crt_control = 0x00010000; /* allocate local memory */ - memory_region_init_ram(&s->local_mem_region, "sm501.local", + memory_region_init_ram(&s->local_mem_region, NULL, "sm501.local", local_mem_bytes); vmstate_register_ram_global(&s->local_mem_region); s->local_mem = memory_region_get_ram_ptr(&s->local_mem_region); memory_region_add_subregion(address_space_mem, base, &s->local_mem_region); /* map mmio */ - memory_region_init_io(sm501_system_config, &sm501_system_config_ops, s, + memory_region_init_io(sm501_system_config, NULL, &sm501_system_config_ops, s, "sm501-system-config", 0x6c); memory_region_add_subregion(address_space_mem, base + MMIO_BASE_OFFSET, sm501_system_config); - memory_region_init_io(sm501_disp_ctrl, &sm501_disp_ctrl_ops, s, + memory_region_init_io(sm501_disp_ctrl, NULL, &sm501_disp_ctrl_ops, s, "sm501-disp-ctrl", 0x1000); memory_region_add_subregion(address_space_mem, base + MMIO_BASE_OFFSET + SM501_DC, sm501_disp_ctrl); - memory_region_init_io(sm501_2d_engine, &sm501_2d_engine_ops, s, + memory_region_init_io(sm501_2d_engine, NULL, &sm501_2d_engine_ops, s, "sm501-2d-engine", 0x54); memory_region_add_subregion(address_space_mem, base + MMIO_BASE_OFFSET + SM501_2D_ENGINE, diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c index 0cb87bc06..3dd9b98ec 100644 --- a/hw/display/tc6393xb.c +++ b/hw/display/tc6393xb.c @@ -578,10 +578,10 @@ TC6393xbState *tc6393xb_init(MemoryRegion *sysmem, uint32_t base, qemu_irq irq) nand = drive_get(IF_MTD, 0, 0); s->flash = nand_init(nand ? nand->bdrv : NULL, NAND_MFR_TOSHIBA, 0x76); - memory_region_init_io(&s->iomem, &tc6393xb_ops, s, "tc6393xb", 0x10000); + memory_region_init_io(&s->iomem, NULL, &tc6393xb_ops, s, "tc6393xb", 0x10000); memory_region_add_subregion(sysmem, base, &s->iomem); - memory_region_init_ram(&s->vram, "tc6393xb.vram", 0x100000); + memory_region_init_ram(&s->vram, NULL, "tc6393xb.vram", 0x100000); vmstate_register_ram_global(&s->vram); s->vram_ptr = memory_region_get_ram_ptr(&s->vram); memory_region_add_subregion(sysmem, base + 0x100000, &s->vram); diff --git a/hw/display/tcx.c b/hw/display/tcx.c index 995641c74..9fd48b5f8 100644 --- a/hw/display/tcx.c +++ b/hw/display/tcx.c @@ -528,7 +528,7 @@ static int tcx_init1(SysBusDevice *dev) int size; uint8_t *vram_base; - memory_region_init_ram(&s->vram_mem, "tcx.vram", + memory_region_init_ram(&s->vram_mem, OBJECT(s), "tcx.vram", s->vram_size * (1 + 4 + 4)); vmstate_register_ram_global(&s->vram_mem); vram_base = memory_region_get_ram_ptr(&s->vram_mem); @@ -536,21 +536,23 @@ static int tcx_init1(SysBusDevice *dev) /* 8-bit plane */ s->vram = vram_base; size = s->vram_size; - memory_region_init_alias(&s->vram_8bit, "tcx.vram.8bit", + memory_region_init_alias(&s->vram_8bit, OBJECT(s), "tcx.vram.8bit", &s->vram_mem, vram_offset, size); sysbus_init_mmio(dev, &s->vram_8bit); vram_offset += size; vram_base += size; /* DAC */ - memory_region_init_io(&s->dac, &tcx_dac_ops, s, "tcx.dac", TCX_DAC_NREGS); + memory_region_init_io(&s->dac, OBJECT(s), &tcx_dac_ops, s, + "tcx.dac", TCX_DAC_NREGS); sysbus_init_mmio(dev, &s->dac); /* TEC (dummy) */ - memory_region_init_io(&s->tec, &dummy_ops, s, "tcx.tec", TCX_TEC_NREGS); + memory_region_init_io(&s->tec, OBJECT(s), &dummy_ops, s, + "tcx.tec", TCX_TEC_NREGS); sysbus_init_mmio(dev, &s->tec); /* THC: NetBSD writes here even with 8-bit display: dummy */ - memory_region_init_io(&s->thc24, &dummy_ops, s, "tcx.thc24", + memory_region_init_io(&s->thc24, OBJECT(s), &dummy_ops, s, "tcx.thc24", TCX_THC_NREGS_24); sysbus_init_mmio(dev, &s->thc24); @@ -559,7 +561,7 @@ static int tcx_init1(SysBusDevice *dev) size = s->vram_size * 4; s->vram24 = (uint32_t *)vram_base; s->vram24_offset = vram_offset; - memory_region_init_alias(&s->vram_24bit, "tcx.vram.24bit", + memory_region_init_alias(&s->vram_24bit, OBJECT(s), "tcx.vram.24bit", &s->vram_mem, vram_offset, size); sysbus_init_mmio(dev, &s->vram_24bit); vram_offset += size; @@ -569,14 +571,14 @@ static int tcx_init1(SysBusDevice *dev) size = s->vram_size * 4; s->cplane = (uint32_t *)vram_base; s->cplane_offset = vram_offset; - memory_region_init_alias(&s->vram_cplane, "tcx.vram.cplane", + memory_region_init_alias(&s->vram_cplane, OBJECT(s), "tcx.vram.cplane", &s->vram_mem, vram_offset, size); sysbus_init_mmio(dev, &s->vram_cplane); s->con = graphic_console_init(DEVICE(dev), &tcx24_ops, s); } else { /* THC 8 bit (dummy) */ - memory_region_init_io(&s->thc8, &dummy_ops, s, "tcx.thc8", + memory_region_init_io(&s->thc8, OBJECT(s), &dummy_ops, s, "tcx.thc8", TCX_THC_NREGS_8); sysbus_init_mmio(dev, &s->thc8); diff --git a/hw/display/vga-isa-mm.c b/hw/display/vga-isa-mm.c index ceeb92f8d..8b514cc39 100644 --- a/hw/display/vga-isa-mm.c +++ b/hw/display/vga-isa-mm.c @@ -105,13 +105,13 @@ static void vga_mm_init(ISAVGAMMState *s, hwaddr vram_base, s->it_shift = it_shift; s_ioport_ctrl = g_malloc(sizeof(*s_ioport_ctrl)); - memory_region_init_io(s_ioport_ctrl, &vga_mm_ctrl_ops, s, + memory_region_init_io(s_ioport_ctrl, NULL, &vga_mm_ctrl_ops, s, "vga-mm-ctrl", 0x100000); memory_region_set_flush_coalesced(s_ioport_ctrl); vga_io_memory = g_malloc(sizeof(*vga_io_memory)); /* XXX: endianness? */ - memory_region_init_io(vga_io_memory, &vga_mem_ops, &s->vga, + memory_region_init_io(vga_io_memory, NULL, &vga_mem_ops, &s->vga, "vga-mem", 0x20000); vmstate_register(NULL, 0, &vmstate_vga_common, s); @@ -132,11 +132,11 @@ int isa_vga_mm_init(hwaddr vram_base, s = g_malloc0(sizeof(*s)); s->vga.vram_size_mb = VGA_RAM_SIZE >> 20; - vga_common_init(&s->vga); + vga_common_init(&s->vga, NULL); vga_mm_init(s, vram_base, ctrl_base, it_shift, address_space); s->vga.con = graphic_console_init(NULL, s->vga.hw_ops, s); - vga_init_vbe(&s->vga, address_space); + vga_init_vbe(&s->vga, NULL, address_space); return 0; } diff --git a/hw/display/vga-isa.c b/hw/display/vga-isa.c index d1691a9f9..8d560ecef 100644 --- a/hw/display/vga-isa.c +++ b/hw/display/vga-isa.c @@ -56,9 +56,9 @@ static void vga_isa_realizefn(DeviceState *dev, Error **errp) MemoryRegion *vga_io_memory; const MemoryRegionPortio *vga_ports, *vbe_ports; - vga_common_init(s); + vga_common_init(s, OBJECT(dev)); s->legacy_address_space = isa_address_space(isadev); - vga_io_memory = vga_init_io(s, &vga_ports, &vbe_ports); + vga_io_memory = vga_init_io(s, OBJECT(dev), &vga_ports, &vbe_ports); isa_register_portio_list(isadev, 0x3b0, vga_ports, s, "vga"); if (vbe_ports) { isa_register_portio_list(isadev, 0x1ce, vbe_ports, s, "vbe"); @@ -69,7 +69,7 @@ static void vga_isa_realizefn(DeviceState *dev, Error **errp) memory_region_set_coalescing(vga_io_memory); s->con = graphic_console_init(DEVICE(dev), s->hw_ops, s); - vga_init_vbe(s, isa_address_space(isadev)); + vga_init_vbe(s, OBJECT(dev), isa_address_space(isadev)); /* ROM BIOS */ rom_add_vga(VGABIOS_FILENAME); } diff --git a/hw/display/vga-pci.c b/hw/display/vga-pci.c index cea8db7f1..3e150abe8 100644 --- a/hw/display/vga-pci.c +++ b/hw/display/vga-pci.c @@ -147,8 +147,9 @@ static int pci_std_vga_initfn(PCIDevice *dev) VGACommonState *s = &d->vga; /* vga + console init */ - vga_common_init(s); - vga_init(s, pci_address_space(dev), pci_address_space_io(dev), true); + vga_common_init(s, OBJECT(dev)); + vga_init(s, OBJECT(dev), pci_address_space(dev), pci_address_space_io(dev), + true); s->con = graphic_console_init(DEVICE(dev), s->hw_ops, s); @@ -157,10 +158,10 @@ static int pci_std_vga_initfn(PCIDevice *dev) /* mmio bar for vga register access */ if (d->flags & (1 << PCI_VGA_FLAG_ENABLE_MMIO)) { - memory_region_init(&d->mmio, "vga.mmio", 4096); - memory_region_init_io(&d->ioport, &pci_vga_ioport_ops, d, + memory_region_init(&d->mmio, NULL, "vga.mmio", 4096); + memory_region_init_io(&d->ioport, NULL, &pci_vga_ioport_ops, d, "vga ioports remapped", PCI_VGA_IOPORT_SIZE); - memory_region_init_io(&d->bochs, &pci_vga_bochs_ops, d, + memory_region_init_io(&d->bochs, NULL, &pci_vga_bochs_ops, d, "bochs dispi interface", PCI_VGA_BOCHS_SIZE); memory_region_add_subregion(&d->mmio, PCI_VGA_IOPORT_OFFSET, @@ -172,7 +173,7 @@ static int pci_std_vga_initfn(PCIDevice *dev) if (!dev->rom_bar) { /* compatibility with pc-0.13 and older */ - vga_init_vbe(s, pci_address_space(dev)); + vga_init_vbe(s, OBJECT(dev), pci_address_space(dev)); } return 0; diff --git a/hw/display/vga.c b/hw/display/vga.c index 21a108d8c..06f44a808 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -198,7 +198,8 @@ static void vga_update_memory_access(VGACommonState *s) } base += isa_mem_base; region = g_malloc(sizeof(*region)); - memory_region_init_alias(region, "vga.chain4", &s->vram, offset, size); + memory_region_init_alias(region, memory_region_owner(&s->vram), + "vga.chain4", &s->vram, offset, size); memory_region_add_subregion_overlap(s->legacy_address_space, base, region, 2); s->chain4_alias = region; @@ -2256,7 +2257,7 @@ static const GraphicHwOps vga_ops = { .text_update = vga_update_text, }; -void vga_common_init(VGACommonState *s) +void vga_common_init(VGACommonState *s, Object *obj) { int i, j, v, b; @@ -2292,7 +2293,7 @@ void vga_common_init(VGACommonState *s) s->vram_size_mb = s->vram_size >> 20; s->is_vbe_vmstate = 1; - memory_region_init_ram(&s->vram, "vga.vram", s->vram_size); + memory_region_init_ram(&s->vram, obj, "vga.vram", s->vram_size); vmstate_register_ram_global(&s->vram); xen_register_framebuffer(&s->vram); s->vram_ptr = memory_region_get_ram_ptr(&s->vram); @@ -2333,7 +2334,7 @@ static const MemoryRegionPortio vbe_portio_list[] = { }; /* Used by both ISA and PCI */ -MemoryRegion *vga_init_io(VGACommonState *s, +MemoryRegion *vga_init_io(VGACommonState *s, Object *obj, const MemoryRegionPortio **vga_ports, const MemoryRegionPortio **vbe_ports) { @@ -2343,14 +2344,14 @@ MemoryRegion *vga_init_io(VGACommonState *s, *vbe_ports = vbe_portio_list; vga_mem = g_malloc(sizeof(*vga_mem)); - memory_region_init_io(vga_mem, &vga_mem_ops, s, + memory_region_init_io(vga_mem, obj, &vga_mem_ops, s, "vga-lowmem", 0x20000); memory_region_set_flush_coalesced(vga_mem); return vga_mem; } -void vga_init(VGACommonState *s, MemoryRegion *address_space, +void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space, MemoryRegion *address_space_io, bool init_vga_ports) { MemoryRegion *vga_io_memory; @@ -2364,28 +2365,28 @@ void vga_init(VGACommonState *s, MemoryRegion *address_space, s->legacy_address_space = address_space; - vga_io_memory = vga_init_io(s, &vga_ports, &vbe_ports); + vga_io_memory = vga_init_io(s, obj, &vga_ports, &vbe_ports); memory_region_add_subregion_overlap(address_space, isa_mem_base + 0x000a0000, vga_io_memory, 1); memory_region_set_coalescing(vga_io_memory); if (init_vga_ports) { - portio_list_init(vga_port_list, vga_ports, s, "vga"); + portio_list_init(vga_port_list, obj, vga_ports, s, "vga"); portio_list_add(vga_port_list, address_space_io, 0x3b0); } if (vbe_ports) { - portio_list_init(vbe_port_list, vbe_ports, s, "vbe"); + portio_list_init(vbe_port_list, obj, vbe_ports, s, "vbe"); portio_list_add(vbe_port_list, address_space_io, 0x1ce); } } -void vga_init_vbe(VGACommonState *s, MemoryRegion *system_memory) +void vga_init_vbe(VGACommonState *s, Object *obj, MemoryRegion *system_memory) { /* With pc-0.12 and below we map both the PCI BAR and the fixed VBE region, * so use an alias to avoid double-mapping the same region. */ - memory_region_init_alias(&s->vram_vbe, "vram.vbe", + memory_region_init_alias(&s->vram_vbe, obj, "vram.vbe", &s->vram, 0, memory_region_size(&s->vram)); /* XXX: use optimized standard vga accesses */ memory_region_add_subregion(system_memory, diff --git a/hw/display/vga_int.h b/hw/display/vga_int.h index 66f9f3cee..e6418906a 100644 --- a/hw/display/vga_int.h +++ b/hw/display/vga_int.h @@ -177,10 +177,10 @@ static inline int c6_to_8(int v) return (v << 2) | (b << 1) | b; } -void vga_common_init(VGACommonState *s); -void vga_init(VGACommonState *s, MemoryRegion *address_space, +void vga_common_init(VGACommonState *s, Object *obj); +void vga_init(VGACommonState *s, Object *obj, MemoryRegion *address_space, MemoryRegion *address_space_io, bool init_vga_ports); -MemoryRegion *vga_init_io(VGACommonState *s, +MemoryRegion *vga_init_io(VGACommonState *s, Object *obj, const MemoryRegionPortio **vga_ports, const MemoryRegionPortio **vbe_ports); void vga_common_reset(VGACommonState *s); @@ -198,7 +198,7 @@ void vga_invalidate_scanlines(VGACommonState *s, int y1, int y2); int vga_ioport_invalid(VGACommonState *s, uint32_t addr); -void vga_init_vbe(VGACommonState *s, MemoryRegion *address_space); +void vga_init_vbe(VGACommonState *s, Object *obj, MemoryRegion *address_space); uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr); void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val); void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val); diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c index fd3569d8c..714908f44 100644 --- a/hw/display/vmware_vga.c +++ b/hw/display/vmware_vga.c @@ -1194,12 +1194,12 @@ static void vmsvga_init(DeviceState *dev, struct vmsvga_state_s *s, s->vga.con = graphic_console_init(dev, &vmsvga_ops, s); s->fifo_size = SVGA_FIFO_SIZE; - memory_region_init_ram(&s->fifo_ram, "vmsvga.fifo", s->fifo_size); + memory_region_init_ram(&s->fifo_ram, NULL, "vmsvga.fifo", s->fifo_size); vmstate_register_ram_global(&s->fifo_ram); s->fifo_ptr = memory_region_get_ram_ptr(&s->fifo_ram); - vga_common_init(&s->vga); - vga_init(&s->vga, address_space, io, true); + vga_common_init(&s->vga, OBJECT(dev)); + vga_init(&s->vga, OBJECT(dev), address_space, io, true); vmstate_register(NULL, 0, &vmstate_vga_common, &s->vga); s->new_depth = 32; } @@ -1241,6 +1241,10 @@ static const MemoryRegionOps vmsvga_io_ops = { .valid = { .min_access_size = 4, .max_access_size = 4, + .unaligned = true, + }, + .impl = { + .unaligned = true, }, }; @@ -1253,7 +1257,7 @@ static int pci_vmsvga_initfn(PCIDevice *dev) s->card.config[PCI_LATENCY_TIMER] = 0x40; /* Latency timer */ s->card.config[PCI_INTERRUPT_LINE] = 0xff; /* End */ - memory_region_init_io(&s->io_bar, &vmsvga_io_ops, &s->chip, + memory_region_init_io(&s->io_bar, NULL, &vmsvga_io_ops, &s->chip, "vmsvga-io", 0x10); memory_region_set_flush_coalesced(&s->io_bar); pci_register_bar(&s->card, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar); @@ -1268,7 +1272,7 @@ static int pci_vmsvga_initfn(PCIDevice *dev) if (!dev->rom_bar) { /* compatibility with pc-0.13 and older */ - vga_init_vbe(&s->chip.vga, pci_address_space(dev)); + vga_init_vbe(&s->chip.vga, OBJECT(dev), pci_address_space(dev)); } return 0; diff --git a/hw/dma/etraxfs_dma.c b/hw/dma/etraxfs_dma.c index 6a8c22250..359951341 100644 --- a/hw/dma/etraxfs_dma.c +++ b/hw/dma/etraxfs_dma.c @@ -773,7 +773,7 @@ void *etraxfs_dmac_init(hwaddr base, int nr_channels) ctrl->nr_channels = nr_channels; ctrl->channels = g_malloc0(sizeof ctrl->channels[0] * nr_channels); - memory_region_init_io(&ctrl->mmio, &dma_ops, ctrl, "etraxfs-dma", + memory_region_init_io(&ctrl->mmio, NULL, &dma_ops, ctrl, "etraxfs-dma", nr_channels * 0x2000); memory_region_add_subregion(get_system_memory(), base, &ctrl->mmio); diff --git a/hw/dma/i82374.c b/hw/dma/i82374.c index 6192780fd..a5b891f96 100644 --- a/hw/dma/i82374.c +++ b/hw/dma/i82374.c @@ -124,16 +124,24 @@ static const VMStateDescription vmstate_isa_i82374 = { }, }; +static const MemoryRegionPortio i82374_portio_list[] = { + { 0x0A, 1, 1, .read = i82374_read_isr, }, + { 0x10, 8, 1, .write = i82374_write_command, }, + { 0x18, 8, 1, .read = i82374_read_status, }, + { 0x20, 0x20, 1, + .write = i82374_write_descriptor, .read = i82374_read_descriptor, }, + PORTIO_END_OF_LIST(), +}; + static void i82374_isa_realize(DeviceState *dev, Error **errp) { ISAi82374State *isa = I82374(dev); I82374State *s = &isa->state; + PortioList *port_list = g_new(PortioList, 1); - register_ioport_read(isa->iobase + 0x0A, 1, 1, i82374_read_isr, s); - register_ioport_write(isa->iobase + 0x10, 8, 1, i82374_write_command, s); - register_ioport_read(isa->iobase + 0x18, 8, 1, i82374_read_status, s); - register_ioport_write(isa->iobase + 0x20, 0x20, 1, i82374_write_descriptor, s); - register_ioport_read(isa->iobase + 0x20, 0x20, 1, i82374_read_descriptor, s); + portio_list_init(port_list, OBJECT(isa), i82374_portio_list, s, "i82374"); + portio_list_add(port_list, isa_address_space_io(&isa->parent_obj), + isa->iobase); i82374_realize(s, errp); diff --git a/hw/dma/i8257.c b/hw/dma/i8257.c index eb60d4517..44903723d 100644 --- a/hw/dma/i8257.c +++ b/hw/dma/i8257.c @@ -523,7 +523,7 @@ static void dma_init2(struct dma_cont *d, int base, int dshift, d->dshift = dshift; d->cpu_request_exit = cpu_request_exit; - memory_region_init_io(&d->channel_io, &channel_io_ops, d, + memory_region_init_io(&d->channel_io, NULL, &channel_io_ops, d, "dma-chan", 8 << d->dshift); memory_region_add_subregion(isa_address_space_io(NULL), base, &d->channel_io); @@ -535,7 +535,7 @@ static void dma_init2(struct dma_cont *d, int base, int dshift, "dma-pageh"); } - memory_region_init_io(&d->cont_io, &cont_io_ops, d, "dma-cont", + memory_region_init_io(&d->cont_io, NULL, &cont_io_ops, d, "dma-cont", 8 << d->dshift); memory_region_add_subregion(isa_address_space_io(NULL), base + (8 << d->dshift), &d->cont_io); diff --git a/hw/dma/omap_dma.c b/hw/dma/omap_dma.c index 184fcee1a..0e8cccd27 100644 --- a/hw/dma/omap_dma.c +++ b/hw/dma/omap_dma.c @@ -248,7 +248,7 @@ static void omap_dma_deactivate_channel(struct omap_dma_s *s, /* Don't deactive the channel if it is synchronized and the DMA request is active */ - if (ch->sync && ch->enable && (s->dma->drqbmp & (1 << ch->sync))) + if (ch->sync && ch->enable && (s->dma->drqbmp & (1ULL << ch->sync))) return; if (ch->active) { @@ -268,8 +268,9 @@ static void omap_dma_enable_channel(struct omap_dma_s *s, /* TODO: theoretically if ch->sync && ch->prefetch && * !s->dma->drqbmp[ch->sync], we should also activate and fetch * from source and then stall until signalled. */ - if ((!ch->sync) || (s->dma->drqbmp & (1 << ch->sync))) + if ((!ch->sync) || (s->dma->drqbmp & (1ULL << ch->sync))) { omap_dma_activate_channel(s, ch); + } } } @@ -1551,12 +1552,12 @@ static void omap_dma_request(void *opaque, int drq, int req) struct omap_dma_s *s = (struct omap_dma_s *) opaque; /* The request pins are level triggered in QEMU. */ if (req) { - if (~s->dma->drqbmp & (1 << drq)) { - s->dma->drqbmp |= 1 << drq; + if (~s->dma->drqbmp & (1ULL << drq)) { + s->dma->drqbmp |= 1ULL << drq; omap_dma_process_request(s, drq); } } else - s->dma->drqbmp &= ~(1 << drq); + s->dma->drqbmp &= ~(1ULL << drq); } /* XXX: this won't be needed once soc_dma knows about clocks. */ @@ -1663,7 +1664,7 @@ struct soc_dma_s *omap_dma_init(hwaddr base, qemu_irq *irqs, omap_dma_reset(s->dma); omap_dma_clk_update(s, 0, 1); - memory_region_init_io(&s->iomem, &omap_dma_ops, s, "omap.dma", memsize); + memory_region_init_io(&s->iomem, NULL, &omap_dma_ops, s, "omap.dma", memsize); memory_region_add_subregion(sysmem, base, &s->iomem); mpu->drq = s->dma->drq; @@ -2085,7 +2086,7 @@ struct soc_dma_s *omap_dma4_init(hwaddr base, qemu_irq *irqs, omap_dma_reset(s->dma); omap_dma_clk_update(s, 0, !!s->dma->freq); - memory_region_init_io(&s->iomem, &omap_dma4_ops, s, "omap.dma4", 0x1000); + memory_region_init_io(&s->iomem, NULL, &omap_dma4_ops, s, "omap.dma4", 0x1000); memory_region_add_subregion(sysmem, base, &s->iomem); mpu->drq = s->dma->drq; diff --git a/hw/dma/pl080.c b/hw/dma/pl080.c index 00b66b45b..7937c3ecf 100644 --- a/hw/dma/pl080.c +++ b/hw/dma/pl080.c @@ -359,7 +359,7 @@ static int pl08x_init(SysBusDevice *dev, int nchannels) { pl080_state *s = FROM_SYSBUS(pl080_state, dev); - memory_region_init_io(&s->iomem, &pl080_ops, s, "pl080", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &pl080_ops, s, "pl080", 0x1000); sysbus_init_mmio(dev, &s->iomem); sysbus_init_irq(dev, &s->irq); s->nchannels = nchannels; diff --git a/hw/dma/pl330.c b/hw/dma/pl330.c index 044c0876a..ddcc4135d 100644 --- a/hw/dma/pl330.c +++ b/hw/dma/pl330.c @@ -1528,7 +1528,8 @@ static void pl330_realize(DeviceState *dev, Error **errp) PL330State *s = PL330(dev); sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq_abort); - memory_region_init_io(&s->iomem, &pl330_ops, s, "dma", PL330_IOMEM_SIZE); + memory_region_init_io(&s->iomem, OBJECT(s), &pl330_ops, s, + "dma", PL330_IOMEM_SIZE); sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem); s->timer = qemu_new_timer_ns(vm_clock, pl330_exec_cycle_timer, s); diff --git a/hw/dma/puv3_dma.c b/hw/dma/puv3_dma.c index 32844b5f7..36004ae48 100644 --- a/hw/dma/puv3_dma.c +++ b/hw/dma/puv3_dma.c @@ -80,7 +80,7 @@ static int puv3_dma_init(SysBusDevice *dev) s->reg_CFG[i] = 0x0; } - memory_region_init_io(&s->iomem, &puv3_dma_ops, s, "puv3_dma", + memory_region_init_io(&s->iomem, OBJECT(s), &puv3_dma_ops, s, "puv3_dma", PUV3_REGS_OFFSET); sysbus_init_mmio(dev, &s->iomem); diff --git a/hw/dma/pxa2xx_dma.c b/hw/dma/pxa2xx_dma.c index b60569fd8..bc7bf4c5e 100644 --- a/hw/dma/pxa2xx_dma.c +++ b/hw/dma/pxa2xx_dma.c @@ -465,7 +465,7 @@ static int pxa2xx_dma_init(SysBusDevice *dev) qdev_init_gpio_in(&dev->qdev, pxa2xx_dma_request, PXA2XX_DMA_NUM_REQUESTS); - memory_region_init_io(&s->iomem, &pxa2xx_dma_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_dma_ops, s, "pxa2xx.dma", 0x00010000); sysbus_init_mmio(dev, &s->iomem); sysbus_init_irq(dev, &s->irq); diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c index 03f92f1ab..4ec433f95 100644 --- a/hw/dma/rc4030.c +++ b/hw/dma/rc4030.c @@ -814,10 +814,10 @@ void *rc4030_init(qemu_irq timer, qemu_irq jazz_bus, register_savevm(NULL, "rc4030", 0, 2, rc4030_save, rc4030_load, s); rc4030_reset(s); - memory_region_init_io(&s->iomem_chipset, &rc4030_ops, s, + memory_region_init_io(&s->iomem_chipset, NULL, &rc4030_ops, s, "rc4030.chipset", 0x300); memory_region_add_subregion(sysmem, 0x80000000, &s->iomem_chipset); - memory_region_init_io(&s->iomem_jazzio, &jazzio_ops, s, + memory_region_init_io(&s->iomem_jazzio, NULL, &jazzio_ops, s, "rc4030.jazzio", 0x00001000); memory_region_add_subregion(sysmem, 0xf0000000, &s->iomem_jazzio); diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index fd21533f1..be6275fea 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -274,7 +274,8 @@ static int sparc32_dma_init1(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq); reg_size = s->is_ledma ? DMA_ETH_SIZE : DMA_SIZE; - memory_region_init_io(&s->iomem, &dma_mem_ops, s, "dma", reg_size); + memory_region_init_io(&s->iomem, OBJECT(s), &dma_mem_ops, s, + "dma", reg_size); sysbus_init_mmio(dev, &s->iomem); qdev_init_gpio_in(&dev->qdev, dma_set_irq, 1); diff --git a/hw/dma/sun4m_iommu.c b/hw/dma/sun4m_iommu.c index 8312bff5f..edb93f36a 100644 --- a/hw/dma/sun4m_iommu.c +++ b/hw/dma/sun4m_iommu.c @@ -349,7 +349,7 @@ static int iommu_init1(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq); - memory_region_init_io(&s->iomem, &iommu_mem_ops, s, "iommu", + memory_region_init_io(&s->iomem, OBJECT(s), &iommu_mem_ops, s, "iommu", IOMMU_NREGS * sizeof(uint32_t)); sysbus_init_mmio(dev, &s->iomem); diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c index 50054cf85..a48e3baa9 100644 --- a/hw/dma/xilinx_axidma.c +++ b/hw/dma/xilinx_axidma.c @@ -590,7 +590,7 @@ static void xilinx_axidma_init(Object *obj) sysbus_init_irq(sbd, &s->streams[0].irq); sysbus_init_irq(sbd, &s->streams[1].irq); - memory_region_init_io(&s->iomem, &axidma_ops, s, + memory_region_init_io(&s->iomem, obj, &axidma_ops, s, "xlnx.axi-dma", R_MAX * 4 * 2); sysbus_init_mmio(sbd, &s->iomem); } diff --git a/hw/gpio/omap_gpio.c b/hw/gpio/omap_gpio.c index f5eeaea54..855afae6b 100644 --- a/hw/gpio/omap_gpio.c +++ b/hw/gpio/omap_gpio.c @@ -677,7 +677,7 @@ static int omap_gpio_init(SysBusDevice *dev) qdev_init_gpio_in(&dev->qdev, omap_gpio_set, 16); qdev_init_gpio_out(&dev->qdev, s->omap1.handler, 16); sysbus_init_irq(dev, &s->omap1.irq); - memory_region_init_io(&s->iomem, &omap_gpio_ops, &s->omap1, + memory_region_init_io(&s->iomem, OBJECT(s), &omap_gpio_ops, &s->omap1, "omap.gpio", 0x1000); sysbus_init_mmio(dev, &s->iomem); return 0; @@ -692,7 +692,7 @@ static int omap2_gpio_init(SysBusDevice *dev) } if (s->mpu_model < omap3430) { s->modulecount = (s->mpu_model < omap2430) ? 4 : 5; - memory_region_init_io(&s->iomem, &omap2_gpif_top_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &omap2_gpif_top_ops, s, "omap2.gpio", 0x1000); sysbus_init_mmio(dev, &s->iomem); } else { @@ -712,7 +712,7 @@ static int omap2_gpio_init(SysBusDevice *dev) sysbus_init_irq(dev, &m->irq[0]); /* mpu irq */ sysbus_init_irq(dev, &m->irq[1]); /* dsp irq */ sysbus_init_irq(dev, &m->wkup); - memory_region_init_io(&m->iomem, &omap2_gpio_module_ops, m, + memory_region_init_io(&m->iomem, OBJECT(s), &omap2_gpio_module_ops, m, "omap.gpio-module", 0x1000); sysbus_init_mmio(dev, &m->iomem); } diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c index 74bc10948..a0bbf0854 100644 --- a/hw/gpio/pl061.c +++ b/hw/gpio/pl061.c @@ -276,7 +276,7 @@ static int pl061_init(SysBusDevice *dev, const unsigned char *id) { pl061_state *s = FROM_SYSBUS(pl061_state, dev); s->id = id; - memory_region_init_io(&s->iomem, &pl061_ops, s, "pl061", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &pl061_ops, s, "pl061", 0x1000); sysbus_init_mmio(dev, &s->iomem); sysbus_init_irq(dev, &s->irq); qdev_init_gpio_in(&dev->qdev, pl061_set_irq, 8); diff --git a/hw/gpio/puv3_gpio.c b/hw/gpio/puv3_gpio.c index 5bab97e95..18671eba9 100644 --- a/hw/gpio/puv3_gpio.c +++ b/hw/gpio/puv3_gpio.c @@ -112,7 +112,7 @@ static int puv3_gpio_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOLOW7]); sysbus_init_irq(dev, &s->irq[PUV3_IRQS_GPIOHIGH]); - memory_region_init_io(&s->iomem, &puv3_gpio_ops, s, "puv3_gpio", + memory_region_init_io(&s->iomem, OBJECT(s), &puv3_gpio_ops, s, "puv3_gpio", PUV3_REGS_OFFSET); sysbus_init_mmio(dev, &s->iomem); diff --git a/hw/gpio/zaurus.c b/hw/gpio/zaurus.c index c6cdef321..c235c3e18 100644 --- a/hw/gpio/zaurus.c +++ b/hw/gpio/zaurus.c @@ -169,7 +169,7 @@ static int scoop_init(SysBusDevice *dev) s->status = 0x02; qdev_init_gpio_out(&s->busdev.qdev, s->handler, 16); qdev_init_gpio_in(&s->busdev.qdev, scoop_gpio_set, 16); - memory_region_init_io(&s->iomem, &scoop_ops, s, "scoop", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &scoop_ops, s, "scoop", 0x1000); sysbus_init_mmio(dev, &s->iomem); diff --git a/hw/i2c/bitbang_i2c.c b/hw/i2c/bitbang_i2c.c index 854b8e194..5f8b97291 100644 --- a/hw/i2c/bitbang_i2c.c +++ b/hw/i2c/bitbang_i2c.c @@ -209,7 +209,7 @@ static int gpio_i2c_init(SysBusDevice *dev) GPIOI2CState *s = FROM_SYSBUS(GPIOI2CState, dev); i2c_bus *bus; - memory_region_init(&s->dummy_iomem, "gpio_i2c", 0); + memory_region_init(&s->dummy_iomem, OBJECT(s), "gpio_i2c", 0); sysbus_init_mmio(dev, &s->dummy_iomem); bus = i2c_init_bus(&dev->qdev, "i2c"); diff --git a/hw/i2c/exynos4210_i2c.c b/hw/i2c/exynos4210_i2c.c index 196f88907..52bffa501 100644 --- a/hw/i2c/exynos4210_i2c.c +++ b/hw/i2c/exynos4210_i2c.c @@ -301,8 +301,8 @@ static int exynos4210_i2c_realize(SysBusDevice *dev) { Exynos4210I2CState *s = EXYNOS4_I2C(dev); - memory_region_init_io(&s->iomem, &exynos4210_i2c_ops, s, TYPE_EXYNOS4_I2C, - EXYNOS4_I2C_MEM_SIZE); + memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_i2c_ops, s, + TYPE_EXYNOS4_I2C, EXYNOS4_I2C_MEM_SIZE); sysbus_init_mmio(dev, &s->iomem); sysbus_init_irq(dev, &s->irq); s->bus = i2c_init_bus(&dev->qdev, "i2c"); diff --git a/hw/i2c/omap_i2c.c b/hw/i2c/omap_i2c.c index efb2254ae..f0eb4489c 100644 --- a/hw/i2c/omap_i2c.c +++ b/hw/i2c/omap_i2c.c @@ -448,7 +448,7 @@ static int omap_i2c_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq); sysbus_init_irq(dev, &s->drq[0]); sysbus_init_irq(dev, &s->drq[1]); - memory_region_init_io(&s->iomem, &omap_i2c_ops, s, "omap.i2c", + memory_region_init_io(&s->iomem, OBJECT(s), &omap_i2c_ops, s, "omap.i2c", (s->revision < OMAP2_INTR_REV) ? 0x800 : 0x1000); sysbus_init_mmio(dev, &s->iomem); s->bus = i2c_init_bus(&dev->qdev, NULL); diff --git a/hw/i2c/pm_smbus.c b/hw/i2c/pm_smbus.c index 0b5bb8997..c98e44753 100644 --- a/hw/i2c/pm_smbus.c +++ b/hw/i2c/pm_smbus.c @@ -32,6 +32,18 @@ #define SMBHSTDAT1 0x06 #define SMBBLKDAT 0x07 +#define STS_HOST_BUSY (1) +#define STS_INTR (1<<1) +#define STS_DEV_ERR (1<<2) +#define STS_BUS_ERR (1<<3) +#define STS_FAILED (1<<4) +#define STS_SMBALERT (1<<5) +#define STS_INUSE_STS (1<<6) +#define STS_BYTE_DONE (1<<7) +/* Signs of successfully transaction end : +* ByteDoneStatus = 1 (STS_BYTE_DONE) and INTR = 1 (STS_INTR ) +*/ + //#define DEBUG #ifdef DEBUG @@ -50,9 +62,14 @@ static void smb_transaction(PMSMBus *s) i2c_bus *bus = s->smbus; SMBUS_DPRINTF("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot); + /* Transaction isn't exec if STS_DEV_ERR bit set */ + if ((s->smb_stat & STS_DEV_ERR) != 0) { + goto error; + } switch(prot) { case 0x0: smbus_quick_command(bus, addr, read); + s->smb_stat |= STS_BYTE_DONE | STS_INTR; break; case 0x1: if (read) { @@ -60,6 +77,7 @@ static void smb_transaction(PMSMBus *s) } else { smbus_send_byte(bus, addr, cmd); } + s->smb_stat |= STS_BYTE_DONE | STS_INTR; break; case 0x2: if (read) { @@ -67,6 +85,7 @@ static void smb_transaction(PMSMBus *s) } else { smbus_write_byte(bus, addr, cmd, s->smb_data0); } + s->smb_stat |= STS_BYTE_DONE | STS_INTR; break; case 0x3: if (read) { @@ -77,6 +96,7 @@ static void smb_transaction(PMSMBus *s) } else { smbus_write_word(bus, addr, cmd, (s->smb_data1 << 8) | s->smb_data0); } + s->smb_stat |= STS_BYTE_DONE | STS_INTR; break; case 0x5: if (read) { @@ -84,6 +104,7 @@ static void smb_transaction(PMSMBus *s) } else { smbus_write_block(bus, addr, cmd, s->smb_data, s->smb_data0); } + s->smb_stat |= STS_BYTE_DONE | STS_INTR; break; default: goto error; @@ -91,7 +112,7 @@ static void smb_transaction(PMSMBus *s) return; error: - s->smb_stat |= 0x04; + s->smb_stat |= STS_DEV_ERR; } static void smb_ioport_writeb(void *opaque, hwaddr addr, uint64_t val, @@ -102,7 +123,7 @@ static void smb_ioport_writeb(void *opaque, hwaddr addr, uint64_t val, SMBUS_DPRINTF("SMB writeb port=0x%04x val=0x%02x\n", addr, val); switch(addr) { case SMBHSTSTS: - s->smb_stat = 0; + s->smb_stat = (~(val & 0xff)) & s->smb_stat; s->smb_index = 0; break; case SMBHSTCNT: @@ -181,5 +202,6 @@ static const MemoryRegionOps pm_smbus_ops = { void pm_smbus_init(DeviceState *parent, PMSMBus *smb) { smb->smbus = i2c_init_bus(parent, "i2c"); - memory_region_init_io(&smb->io, &pm_smbus_ops, smb, "pm-smbus", 64); + memory_region_init_io(&smb->io, OBJECT(parent), &pm_smbus_ops, smb, + "pm-smbus", 64); } diff --git a/hw/i2c/versatile_i2c.c b/hw/i2c/versatile_i2c.c index e09c83dda..204dd3d53 100644 --- a/hw/i2c/versatile_i2c.c +++ b/hw/i2c/versatile_i2c.c @@ -79,7 +79,7 @@ static int versatile_i2c_init(SysBusDevice *dev) bus = i2c_init_bus(&dev->qdev, "i2c"); s->bitbang = bitbang_i2c_init(bus); - memory_region_init_io(&s->iomem, &versatile_i2c_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &versatile_i2c_ops, s, "versatile_i2c", 0x1000); sysbus_init_mmio(dev, &s->iomem); return 0; diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c index bd0bdd859..179b806d9 100644 --- a/hw/i386/kvm/apic.c +++ b/hw/i386/kvm/apic.c @@ -173,7 +173,7 @@ static const MemoryRegionOps kvm_apic_io_ops = { static void kvm_apic_init(APICCommonState *s) { - memory_region_init_io(&s->io_memory, &kvm_apic_io_ops, s, "kvm-apic-msi", + memory_region_init_io(&s->io_memory, NULL, &kvm_apic_io_ops, s, "kvm-apic-msi", APIC_SPACE_SIZE); if (kvm_has_gsi_routing()) { diff --git a/hw/i386/kvm/clock.c b/hw/i386/kvm/clock.c index 87d4d0fc9..1022d6717 100644 --- a/hw/i386/kvm/clock.c +++ b/hw/i386/kvm/clock.c @@ -28,55 +28,33 @@ typedef struct KVMClockState { bool clock_valid; } KVMClockState; -static void kvmclock_pre_save(void *opaque) -{ - KVMClockState *s = opaque; - struct kvm_clock_data data; - int ret; - - if (s->clock_valid) { - return; - } - ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data); - if (ret < 0) { - fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret)); - data.clock = 0; - } - s->clock = data.clock; - /* - * If the VM is stopped, declare the clock state valid to avoid re-reading - * it on next vmsave (which would return a different value). Will be reset - * when the VM is continued. - */ - s->clock_valid = !runstate_is_running(); -} - -static int kvmclock_post_load(void *opaque, int version_id) -{ - KVMClockState *s = opaque; - struct kvm_clock_data data; - - data.clock = s->clock; - data.flags = 0; - return kvm_vm_ioctl(kvm_state, KVM_SET_CLOCK, &data); -} static void kvmclock_vm_state_change(void *opaque, int running, RunState state) { KVMClockState *s = opaque; - CPUArchState *penv = first_cpu; + CPUState *cpu = first_cpu; int cap_clock_ctrl = kvm_check_extension(kvm_state, KVM_CAP_KVMCLOCK_CTRL); int ret; if (running) { + struct kvm_clock_data data; + s->clock_valid = false; + data.clock = s->clock; + data.flags = 0; + ret = kvm_vm_ioctl(kvm_state, KVM_SET_CLOCK, &data); + if (ret < 0) { + fprintf(stderr, "KVM_SET_CLOCK failed: %s\n", strerror(ret)); + abort(); + } + if (!cap_clock_ctrl) { return; } - for (penv = first_cpu; penv != NULL; penv = penv->next_cpu) { - ret = kvm_vcpu_ioctl(ENV_GET_CPU(penv), KVM_KVMCLOCK_CTRL, 0); + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { + ret = kvm_vcpu_ioctl(cpu, KVM_KVMCLOCK_CTRL, 0); if (ret) { if (ret != -EINVAL) { fprintf(stderr, "%s: %s\n", __func__, strerror(-ret)); @@ -84,6 +62,26 @@ static void kvmclock_vm_state_change(void *opaque, int running, return; } } + } else { + struct kvm_clock_data data; + int ret; + + if (s->clock_valid) { + return; + } + ret = kvm_vm_ioctl(kvm_state, KVM_GET_CLOCK, &data); + if (ret < 0) { + fprintf(stderr, "KVM_GET_CLOCK failed: %s\n", strerror(ret)); + abort(); + } + s->clock = data.clock; + + /* + * If the VM is stopped, declare the clock state valid to + * avoid re-reading it on next vmsave (which would return + * a different value). Will be reset when the VM is continued. + */ + s->clock_valid = true; } } @@ -100,8 +98,6 @@ static const VMStateDescription kvmclock_vmsd = { .version_id = 1, .minimum_version_id = 1, .minimum_version_id_old = 1, - .pre_save = kvmclock_pre_save, - .post_load = kvmclock_post_load, .fields = (VMStateField[]) { VMSTATE_UINT64(clock, KVMClockState), VMSTATE_END_OF_LIST() @@ -128,9 +124,11 @@ static const TypeInfo kvmclock_info = { /* Note: Must be called after VCPU initialization. */ void kvmclock_create(void) { + X86CPU *cpu = X86_CPU(first_cpu); + if (kvm_enabled() && - first_cpu->features[FEAT_KVM] & ((1ULL << KVM_FEATURE_CLOCKSOURCE) | - (1ULL << KVM_FEATURE_CLOCKSOURCE2))) { + cpu->env.features[FEAT_KVM] & ((1ULL << KVM_FEATURE_CLOCKSOURCE) | + (1ULL << KVM_FEATURE_CLOCKSOURCE2))) { sysbus_create_simple("kvmclock", -1, NULL); } } diff --git a/hw/i386/kvm/i8254.c b/hw/i386/kvm/i8254.c index 93a366974..c1f40948f 100644 --- a/hw/i386/kvm/i8254.c +++ b/hw/i386/kvm/i8254.c @@ -288,7 +288,7 @@ static void kvm_pit_realizefn(DeviceState *dev, Error **errp) return; } - memory_region_init_reservation(&pit->ioports, "kvm-pit", 4); + memory_region_init_reservation(&pit->ioports, NULL, "kvm-pit", 4); qdev_init_gpio_in(dev, kvm_pit_irq_control, 1); diff --git a/hw/i386/kvm/i8259.c b/hw/i386/kvm/i8259.c index 125022422..53e3ca8c6 100644 --- a/hw/i386/kvm/i8259.c +++ b/hw/i386/kvm/i8259.c @@ -119,8 +119,8 @@ static void kvm_pic_realize(DeviceState *dev, Error **errp) PICCommonState *s = PIC_COMMON(dev); KVMPICClass *kpc = KVM_PIC_GET_CLASS(dev); - memory_region_init_reservation(&s->base_io, "kvm-pic", 2); - memory_region_init_reservation(&s->elcr_io, "kvm-elcr", 1); + memory_region_init_reservation(&s->base_io, NULL, "kvm-pic", 2); + memory_region_init_reservation(&s->elcr_io, NULL, "kvm-elcr", 1); kpc->parent_realize(dev, errp); } diff --git a/hw/i386/kvm/ioapic.c b/hw/i386/kvm/ioapic.c index abfac3da7..688cb5cab 100644 --- a/hw/i386/kvm/ioapic.c +++ b/hw/i386/kvm/ioapic.c @@ -129,7 +129,7 @@ static void kvm_ioapic_set_irq(void *opaque, int irq, int level) static void kvm_ioapic_init(IOAPICCommonState *s, int instance_no) { - memory_region_init_reservation(&s->io_memory, "kvm-ioapic", 0x1000); + memory_region_init_reservation(&s->io_memory, NULL, "kvm-ioapic", 0x1000); qdev_init_gpio_in(&s->busdev.qdev, kvm_ioapic_set_irq, IOAPIC_NUM_PINS); } diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c index 1fb7ad44a..ff33dc885 100644 --- a/hw/i386/kvm/pci-assign.c +++ b/hw/i386/kvm/pci-assign.c @@ -226,7 +226,7 @@ static uint32_t slow_bar_readb(void *opaque, hwaddr addr) uint32_t r; r = *in; - DEBUG("slow_bar_readl addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, r); + DEBUG("addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, r); return r; } @@ -238,7 +238,7 @@ static uint32_t slow_bar_readw(void *opaque, hwaddr addr) uint32_t r; r = *in; - DEBUG("slow_bar_readl addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, r); + DEBUG("addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, r); return r; } @@ -250,7 +250,7 @@ static uint32_t slow_bar_readl(void *opaque, hwaddr addr) uint32_t r; r = *in; - DEBUG("slow_bar_readl addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, r); + DEBUG("addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, r); return r; } @@ -260,7 +260,7 @@ static void slow_bar_writeb(void *opaque, hwaddr addr, uint32_t val) AssignedDevRegion *d = opaque; uint8_t *out = d->u.r_virtbase + addr; - DEBUG("slow_bar_writeb addr=0x" TARGET_FMT_plx " val=0x%02x\n", addr, val); + DEBUG("addr=0x" TARGET_FMT_plx " val=0x%02x\n", addr, val); *out = val; } @@ -269,7 +269,7 @@ static void slow_bar_writew(void *opaque, hwaddr addr, uint32_t val) AssignedDevRegion *d = opaque; uint16_t *out = (uint16_t *)(d->u.r_virtbase + addr); - DEBUG("slow_bar_writew addr=0x" TARGET_FMT_plx " val=0x%04x\n", addr, val); + DEBUG("addr=0x" TARGET_FMT_plx " val=0x%04x\n", addr, val); *out = val; } @@ -278,7 +278,7 @@ static void slow_bar_writel(void *opaque, hwaddr addr, uint32_t val) AssignedDevRegion *d = opaque; uint32_t *out = (uint32_t *)(d->u.r_virtbase + addr); - DEBUG("slow_bar_writel addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, val); + DEBUG("addr=0x" TARGET_FMT_plx " val=0x%08x\n", addr, val); *out = val; } @@ -298,8 +298,8 @@ static void assigned_dev_iomem_setup(PCIDevice *pci_dev, int region_num, PCIRegion *real_region = &r_dev->real_device.regions[region_num]; if (e_size > 0) { - memory_region_init(®ion->container, "assigned-dev-container", - e_size); + memory_region_init(®ion->container, OBJECT(pci_dev), + "assigned-dev-container", e_size); memory_region_add_subregion(®ion->container, 0, ®ion->real_iomem); /* deal with MSI-X MMIO page */ @@ -329,9 +329,10 @@ static void assigned_dev_ioport_setup(PCIDevice *pci_dev, int region_num, AssignedDevRegion *region = &r_dev->v_addrs[region_num]; region->e_size = size; - memory_region_init(®ion->container, "assigned-dev-container", size); - memory_region_init_io(®ion->real_iomem, &assigned_dev_ioport_ops, - r_dev->v_addrs + region_num, + memory_region_init(®ion->container, OBJECT(pci_dev), + "assigned-dev-container", size); + memory_region_init_io(®ion->real_iomem, OBJECT(pci_dev), + &assigned_dev_ioport_ops, r_dev->v_addrs + region_num, "assigned-dev-iomem", size); memory_region_add_subregion(®ion->container, 0, ®ion->real_iomem); } @@ -479,7 +480,8 @@ static int assigned_dev_register_regions(PCIRegion *io_regions, "due to that.", i, cur_region->base_addr, cur_region->size); memory_region_init_io(&pci_dev->v_addrs[i].real_iomem, - &slow_bar_ops, &pci_dev->v_addrs[i], + OBJECT(pci_dev), &slow_bar_ops, + &pci_dev->v_addrs[i], "assigned-dev-slow-bar", cur_region->size); } else { @@ -488,8 +490,8 @@ static int assigned_dev_register_regions(PCIRegion *io_regions, snprintf(name, sizeof(name), "%s.bar%d", object_get_typename(OBJECT(pci_dev)), i); memory_region_init_ram_ptr(&pci_dev->v_addrs[i].real_iomem, - name, cur_region->size, - virtbase); + OBJECT(pci_dev), name, + cur_region->size, virtbase); vmstate_register_ram(&pci_dev->v_addrs[i].real_iomem, &pci_dev->dev.qdev); } @@ -1650,8 +1652,8 @@ static int assigned_dev_register_msix_mmio(AssignedDevice *dev) assigned_dev_msix_reset(dev); - memory_region_init_io(&dev->mmio, &assigned_dev_msix_mmio_ops, dev, - "assigned-dev-msix", MSIX_PAGE_SIZE); + memory_region_init_io(&dev->mmio, OBJECT(dev), &assigned_dev_msix_mmio_ops, + dev, "assigned-dev-msix", MSIX_PAGE_SIZE); return 0; } @@ -1916,7 +1918,7 @@ static void assigned_dev_load_option_rom(AssignedDevice *dev) snprintf(name, sizeof(name), "%s.rom", object_get_typename(OBJECT(dev))); - memory_region_init_ram(&dev->dev.rom, name, st.st_size); + memory_region_init_ram(&dev->dev.rom, OBJECT(dev), name, st.st_size); vmstate_register_ram(&dev->dev.rom, &dev->dev.qdev); ptr = memory_region_get_ram_ptr(&dev->dev.rom); memset(ptr, 0xff, st.st_size); diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c index f93629f9d..ccd089a40 100644 --- a/hw/i386/kvmvapic.c +++ b/hw/i386/kvmvapic.c @@ -490,13 +490,15 @@ static void vapic_enable_tpr_reporting(bool enable) VAPICEnableTPRReporting info = { .enable = enable, }; + CPUState *cs; X86CPU *cpu; CPUX86State *env; - for (env = first_cpu; env != NULL; env = env->next_cpu) { - cpu = x86_env_get_cpu(env); + for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) { + cpu = X86_CPU(cs); + env = &cpu->env; info.apic = env->apic_state; - run_on_cpu(CPU(cpu), vapic_do_enable_tpr_reporting, &info); + run_on_cpu(cs, vapic_do_enable_tpr_reporting, &info); } } @@ -601,10 +603,11 @@ static void vapic_map_rom_writable(VAPICROMState *s) rom_paddr &= TARGET_PAGE_MASK; rom_size = TARGET_PAGE_ALIGN(rom_size); - memory_region_init_alias(&s->rom, "kvmvapic-rom", section.mr, rom_paddr, - rom_size); + memory_region_init_alias(&s->rom, OBJECT(s), "kvmvapic-rom", section.mr, + rom_paddr, rom_size); memory_region_add_subregion_overlap(as, rom_paddr, &s->rom, 1000); s->rom_mapped_writable = true; + memory_region_unref(section.mr); } static int vapic_prepare(VAPICROMState *s) @@ -623,11 +626,13 @@ static int vapic_prepare(VAPICROMState *s) static void vapic_write(void *opaque, hwaddr addr, uint64_t data, unsigned int size) { - CPUX86State *env = cpu_single_env; + CPUState *cs = current_cpu; + X86CPU *cpu = X86_CPU(cs); + CPUX86State *env = &cpu->env; hwaddr rom_paddr; VAPICROMState *s = opaque; - cpu_synchronize_state(CPU(x86_env_get_cpu(env))); + cpu_synchronize_state(cs); /* * The VAPIC supports two PIO-based hypercalls, both via port 0x7E. @@ -702,7 +707,7 @@ static int vapic_init(SysBusDevice *dev) { VAPICROMState *s = VAPIC(dev); - memory_region_init_io(&s->io, &vapic_ops, s, "kvmvapic", 2); + memory_region_init_io(&s->io, OBJECT(s), &vapic_ops, s, "kvmvapic", 2); sysbus_add_io(dev, VAPIC_IO_PORT, &s->io); sysbus_init_ioports(dev, VAPIC_IO_PORT, 2); @@ -716,8 +721,9 @@ static int vapic_init(SysBusDevice *dev) static void do_vapic_enable(void *data) { VAPICROMState *s = data; + X86CPU *cpu = X86_CPU(first_cpu); - vapic_enable(s, first_cpu); + vapic_enable(s, &cpu->env); } static int vapic_post_load(void *opaque, int version_id) @@ -740,7 +746,7 @@ static int vapic_post_load(void *opaque, int version_id) } if (s->state == VAPIC_ACTIVE) { if (smp_cpus == 1) { - run_on_cpu(ENV_GET_CPU(first_cpu), do_vapic_enable, s); + run_on_cpu(first_cpu, do_vapic_enable, s); } else { zero = g_malloc0(s->rom_state.vapic_size); cpu_physical_memory_rw(s->vapic_paddr, zero, diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 78f92e29a..c5d8570af 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -160,8 +160,9 @@ void cpu_smm_register(cpu_set_smm_t callback, void *arg) void cpu_smm_update(CPUX86State *env) { - if (smm_set && smm_arg && env == first_cpu) + if (smm_set && smm_arg && CPU(x86_env_get_cpu(env)) == first_cpu) { smm_set(!!(env->hflags & HF_SMM_MASK), smm_arg); + } } @@ -185,18 +186,21 @@ int cpu_get_pic_interrupt(CPUX86State *env) static void pic_irq_request(void *opaque, int irq, int level) { - CPUX86State *env = first_cpu; + CPUState *cs = first_cpu; + X86CPU *cpu = X86_CPU(cs); + CPUX86State *env = &cpu->env; DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", irq); if (env->apic_state) { - while (env) { + while (cs) { + cpu = X86_CPU(cs); + env = &cpu->env; if (apic_accept_pic_intr(env->apic_state)) { apic_deliver_pic_intr(env->apic_state, level); } - env = env->next_cpu; + cs = cs->next_cpu; } } else { - CPUState *cs = CPU(x86_env_get_cpu(env)); if (level) { cpu_interrupt(cs, CPU_INTERRUPT_HARD); } else { @@ -525,7 +529,7 @@ static void port92_initfn(Object *obj) { Port92State *s = PORT92(obj); - memory_region_init_io(&s->io, &port92_ops, s, "port92", 1); + memory_region_init_io(&s->io, OBJECT(s), &port92_ops, s, "port92", 1); s->outport = 0; } @@ -886,8 +890,9 @@ void pc_init_ne2k_isa(ISABus *bus, NICInfo *nd) DeviceState *cpu_get_current_apic(void) { - if (cpu_single_env) { - return cpu_single_env->apic_state; + if (current_cpu) { + X86CPU *cpu = X86_CPU(current_cpu); + return cpu->env.apic_state; } else { return NULL; } @@ -989,6 +994,74 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) } } +/* pci-info ROM file. Little endian format */ +typedef struct PcRomPciInfo { + uint64_t w32_min; + uint64_t w32_max; + uint64_t w64_min; + uint64_t w64_max; +} PcRomPciInfo; + +static void pc_fw_cfg_guest_info(PcGuestInfo *guest_info) +{ + PcRomPciInfo *info; + if (!guest_info->has_pci_info) { + return; + } + + info = g_malloc(sizeof *info); + info->w32_min = cpu_to_le64(guest_info->pci_info.w32.begin); + info->w32_max = cpu_to_le64(guest_info->pci_info.w32.end); + info->w64_min = cpu_to_le64(guest_info->pci_info.w64.begin); + info->w64_max = cpu_to_le64(guest_info->pci_info.w64.end); + /* Pass PCI hole info to guest via a side channel. + * Required so guest PCI enumeration does the right thing. */ + fw_cfg_add_file(guest_info->fw_cfg, "etc/pci-info", info, sizeof *info); +} + +typedef struct PcGuestInfoState { + PcGuestInfo info; + Notifier machine_done; +} PcGuestInfoState; + +static +void pc_guest_info_machine_done(Notifier *notifier, void *data) +{ + PcGuestInfoState *guest_info_state = container_of(notifier, + PcGuestInfoState, + machine_done); + pc_fw_cfg_guest_info(&guest_info_state->info); +} + +PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size, + ram_addr_t above_4g_mem_size) +{ + PcGuestInfoState *guest_info_state = g_malloc0(sizeof *guest_info_state); + PcGuestInfo *guest_info = &guest_info_state->info; + + guest_info->pci_info.w32.end = IO_APIC_DEFAULT_ADDRESS; + if (sizeof(hwaddr) == 4) { + guest_info->pci_info.w64.begin = 0; + guest_info->pci_info.w64.end = 0; + } else { + /* + * BIOS does not set MTRR entries for the 64 bit window, so no need to + * align address to power of two. Align address at 1G, this makes sure + * it can be exactly covered with a PAT entry even when using huge + * pages. + */ + guest_info->pci_info.w64.begin = + ROUND_UP((0x1ULL << 32) + above_4g_mem_size, 0x1ULL << 30); + guest_info->pci_info.w64.end = guest_info->pci_info.w64.begin + + (0x1ULL << 62); + assert(guest_info->pci_info.w64.begin <= guest_info->pci_info.w64.end); + } + + guest_info_state->machine_done.notify = pc_guest_info_machine_done; + qemu_add_machine_init_done_notifier(&guest_info_state->machine_done); + return guest_info; +} + void pc_acpi_init(const char *default_dsdt) { char *filename; @@ -1030,7 +1103,8 @@ FWCfgState *pc_memory_init(MemoryRegion *system_memory, ram_addr_t below_4g_mem_size, ram_addr_t above_4g_mem_size, MemoryRegion *rom_memory, - MemoryRegion **ram_memory) + MemoryRegion **ram_memory, + PcGuestInfo *guest_info) { int linux_boot, i; MemoryRegion *ram, *option_rom_mr; @@ -1044,17 +1118,17 @@ FWCfgState *pc_memory_init(MemoryRegion *system_memory, * with older qemus that used qemu_ram_alloc(). */ ram = g_malloc(sizeof(*ram)); - memory_region_init_ram(ram, "pc.ram", + memory_region_init_ram(ram, NULL, "pc.ram", below_4g_mem_size + above_4g_mem_size); vmstate_register_ram_global(ram); *ram_memory = ram; ram_below_4g = g_malloc(sizeof(*ram_below_4g)); - memory_region_init_alias(ram_below_4g, "ram-below-4g", ram, + memory_region_init_alias(ram_below_4g, NULL, "ram-below-4g", ram, 0, below_4g_mem_size); memory_region_add_subregion(system_memory, 0, ram_below_4g); if (above_4g_mem_size > 0) { ram_above_4g = g_malloc(sizeof(*ram_above_4g)); - memory_region_init_alias(ram_above_4g, "ram-above-4g", ram, + memory_region_init_alias(ram_above_4g, NULL, "ram-above-4g", ram, below_4g_mem_size, above_4g_mem_size); memory_region_add_subregion(system_memory, 0x100000000ULL, ram_above_4g); @@ -1065,7 +1139,7 @@ FWCfgState *pc_memory_init(MemoryRegion *system_memory, pc_system_firmware_init(rom_memory); option_rom_mr = g_malloc(sizeof(*option_rom_mr)); - memory_region_init_ram(option_rom_mr, "pc.rom", PC_ROM_SIZE); + memory_region_init_ram(option_rom_mr, NULL, "pc.rom", PC_ROM_SIZE); vmstate_register_ram_global(option_rom_mr); memory_region_add_subregion_overlap(rom_memory, PC_ROM_MIN_VGA, @@ -1082,6 +1156,7 @@ FWCfgState *pc_memory_init(MemoryRegion *system_memory, for (i = 0; i < nb_option_roms; i++) { rom_add_option(option_rom[i].name, option_rom[i].bootindex); } + guest_info->fw_cfg = fw_cfg; return fw_cfg; } @@ -1106,10 +1181,10 @@ DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus) static void cpu_request_exit(void *opaque, int irq, int level) { - CPUX86State *env = cpu_single_env; + CPUState *cpu = current_cpu; - if (env && level) { - cpu_exit(CPU(x86_env_get_cpu(env))); + if (cpu && level) { + cpu_exit(cpu); } } @@ -1150,10 +1225,10 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, MemoryRegion *ioport80_io = g_new(MemoryRegion, 1); MemoryRegion *ioportF0_io = g_new(MemoryRegion, 1); - memory_region_init_io(ioport80_io, &ioport80_io_ops, NULL, "ioport80", 1); + memory_region_init_io(ioport80_io, NULL, &ioport80_io_ops, NULL, "ioport80", 1); memory_region_add_subregion(isa_bus->address_space_io, 0x80, ioport80_io); - memory_region_init_io(ioportF0_io, &ioportF0_io_ops, NULL, "ioportF0", 1); + memory_region_init_io(ioportF0_io, NULL, &ioportF0_io_ops, NULL, "ioportF0", 1); memory_region_add_subregion(isa_bus->address_space_io, 0xf0, ioportF0_io); /* @@ -1203,8 +1278,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, } } - a20_line = qemu_allocate_irqs(handle_a20_line_change, - x86_env_get_cpu(first_cpu), 2); + a20_line = qemu_allocate_irqs(handle_a20_line_change, first_cpu, 2); i8042 = isa_create_simple(isa_bus, "i8042"); i8042_setup_a20_line(i8042, &a20_line[0]); if (!no_vmport) { @@ -1240,7 +1314,7 @@ void pc_nic_init(ISABus *isa_bus, PCIBus *pci_bus) if (!pci_bus || (nd->model && strcmp(nd->model, "ne2k_isa") == 0)) { pc_init_ne2k_isa(isa_bus, nd); } else { - pci_nic_init_nofail(nd, "e1000", NULL); + pci_nic_init_nofail(nd, pci_bus, "e1000", NULL); } } } diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index fa59a0cb2..b58c25596 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -57,6 +57,7 @@ static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 }; static const int ide_irq[MAX_IDE_BUS] = { 14, 15 }; static bool has_pvpanic = true; +static bool has_pci_info = true; /* PC hardware initialisation */ static void pc_init1(MemoryRegion *system_memory, @@ -90,6 +91,7 @@ static void pc_init1(MemoryRegion *system_memory, MemoryRegion *rom_memory; DeviceState *icc_bridge; FWCfgState *fw_cfg = NULL; + PcGuestInfo *guest_info; if (xen_enabled() && xen_hvm_init() != 0) { fprintf(stderr, "xen hardware virtual machine initialisation failed\n"); @@ -117,19 +119,31 @@ static void pc_init1(MemoryRegion *system_memory, if (pci_enabled) { pci_memory = g_new(MemoryRegion, 1); - memory_region_init(pci_memory, "pci", INT64_MAX); + memory_region_init(pci_memory, NULL, "pci", INT64_MAX); rom_memory = pci_memory; } else { pci_memory = NULL; rom_memory = system_memory; } + guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size); + guest_info->has_pci_info = has_pci_info; + + /* Set PCI window size the way seabios has always done it. */ + /* Power of 2 so bios can cover it with a single MTRR */ + if (ram_size <= 0x80000000) + guest_info->pci_info.w32.begin = 0x80000000; + else if (ram_size <= 0xc0000000) + guest_info->pci_info.w32.begin = 0xc0000000; + else + guest_info->pci_info.w32.begin = 0xe0000000; + /* allocate ram and load rom/bios */ if (!xen_enabled()) { fw_cfg = pc_memory_init(system_memory, kernel_filename, kernel_cmdline, initrd_filename, below_4g_mem_size, above_4g_mem_size, - rom_memory, &ram_memory); + rom_memory, &ram_memory, guest_info); } gsi_state = g_malloc0(sizeof(*gsi_state)); @@ -215,8 +229,7 @@ static void pc_init1(MemoryRegion *system_memory, if (pci_enabled && acpi_enabled) { i2c_bus *smbus; - smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, - x86_env_get_cpu(first_cpu), 1); + smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1); /* TODO: Populate SPD eeprom data. */ smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, gsi[9], *smi_irq, @@ -248,36 +261,36 @@ static void pc_init_pci(QEMUMachineInitArgs *args) initrd_filename, cpu_model, 1, 1); } +static void pc_init_pci_1_5(QEMUMachineInitArgs *args) +{ + has_pci_info = false; + pc_init_pci(args); +} + static void pc_init_pci_1_4(QEMUMachineInitArgs *args) { has_pvpanic = false; x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE); - pc_init_pci(args); + pc_init_pci_1_5(args); } static void pc_init_pci_1_3(QEMUMachineInitArgs *args) { enable_compat_apic_id_mode(); - has_pvpanic = false; - pc_init_pci(args); + pc_init_pci_1_4(args); } /* PC machine init function for pc-1.1 to pc-1.2 */ static void pc_init_pci_1_2(QEMUMachineInitArgs *args) { disable_kvm_pv_eoi(); - enable_compat_apic_id_mode(); - has_pvpanic = false; - pc_init_pci(args); + pc_init_pci_1_3(args); } /* PC machine init function for pc-0.14 to pc-1.0 */ static void pc_init_pci_1_0(QEMUMachineInitArgs *args) { - disable_kvm_pv_eoi(); - enable_compat_apic_id_mode(); - has_pvpanic = false; - pc_init_pci(args); + pc_init_pci_1_2(args); } /* PC init function for pc-0.10 to pc-0.13, and reused by xenfv */ @@ -290,6 +303,7 @@ static void pc_init_pci_no_kvmclock(QEMUMachineInitArgs *args) const char *initrd_filename = args->initrd_filename; const char *boot_device = args->boot_device; has_pvpanic = false; + has_pci_info = false; disable_kvm_pv_eoi(); enable_compat_apic_id_mode(); pc_init1(get_system_memory(), @@ -308,6 +322,7 @@ static void pc_init_isa(QEMUMachineInitArgs *args) const char *initrd_filename = args->initrd_filename; const char *boot_device = args->boot_device; has_pvpanic = false; + has_pci_info = false; if (cpu_model == NULL) cpu_model = "486"; disable_kvm_pv_eoi(); @@ -326,7 +341,7 @@ static void pc_xen_hvm_init(QEMUMachineInitArgs *args) pc_init_pci(args); - bus = pci_find_root_bus(0); + bus = pci_find_primary_bus(); if (bus != NULL) { pci_create_simple(bus, -1, "xen-platform"); } @@ -347,7 +362,7 @@ static QEMUMachine pc_i440fx_machine_v1_6 = { static QEMUMachine pc_i440fx_machine_v1_5 = { .name = "pc-i440fx-1.5", .desc = "Standard PC (i440FX + PIIX, 1996)", - .init = pc_init_pci, + .init = pc_init_pci_1_5, .hot_add_cpu = pc_hot_add_cpu, .max_cpus = 255, .compat_props = (GlobalProperty[]) { diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index bb0ce6ae6..6f10246ed 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -47,6 +47,7 @@ #define MAX_SATA_PORTS 6 static bool has_pvpanic = true; +static bool has_pci_info = true; /* PC hardware initialisation */ static void pc_q35_init(QEMUMachineInitArgs *args) @@ -77,6 +78,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args) ICH9LPCState *ich9_lpc; PCIDevice *ahci; DeviceState *icc_bridge; + PcGuestInfo *guest_info; icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE); object_property_add_child(qdev_get_machine(), "icc-bridge", @@ -98,18 +100,21 @@ static void pc_q35_init(QEMUMachineInitArgs *args) /* pci enabled */ if (pci_enabled) { pci_memory = g_new(MemoryRegion, 1); - memory_region_init(pci_memory, "pci", INT64_MAX); + memory_region_init(pci_memory, NULL, "pci", INT64_MAX); rom_memory = pci_memory; } else { pci_memory = NULL; rom_memory = get_system_memory(); } + guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size); + guest_info->has_pci_info = has_pci_info; + /* allocate ram and load rom/bios */ if (!xen_enabled()) { pc_memory_init(get_system_memory(), kernel_filename, kernel_cmdline, initrd_filename, below_4g_mem_size, above_4g_mem_size, - rom_memory, &ram_memory); + rom_memory, &ram_memory, guest_info); } /* irq lines */ @@ -131,6 +136,7 @@ static void pc_q35_init(QEMUMachineInitArgs *args) q35_host->mch.address_space_io = get_system_io(); q35_host->mch.below_4g_mem_size = below_4g_mem_size; q35_host->mch.above_4g_mem_size = above_4g_mem_size; + q35_host->mch.guest_info = guest_info; /* pci */ qdev_init_nofail(DEVICE(q35_host)); host_bus = q35_host->host.pci.bus; @@ -208,11 +214,17 @@ static void pc_q35_init(QEMUMachineInitArgs *args) } } +static void pc_q35_init_1_5(QEMUMachineInitArgs *args) +{ + has_pci_info = false; + pc_q35_init(args); +} + static void pc_q35_init_1_4(QEMUMachineInitArgs *args) { has_pvpanic = false; x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE); - pc_q35_init(args); + pc_q35_init_1_5(args); } static QEMUMachine pc_q35_machine_v1_6 = { @@ -228,7 +240,7 @@ static QEMUMachine pc_q35_machine_v1_6 = { static QEMUMachine pc_q35_machine_v1_5 = { .name = "pc-q35-1.5", .desc = "Standard PC (Q35 + ICH9, 2009)", - .init = pc_q35_init, + .init = pc_q35_init_1_5, .hot_add_cpu = pc_hot_add_cpu, .max_cpus = 255, .compat_props = (GlobalProperty[]) { diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c index 1adfa0b26..1d863b578 100644 --- a/hw/ide/ahci.c +++ b/hw/ide/ahci.c @@ -650,6 +650,8 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, int offset) int off_idx = -1; int off_pos = -1; int tbl_entry_size; + IDEBus *bus = &ad->port; + BusState *qbus = BUS(bus); if (!sglist_alloc_hint) { DPRINTF(ad->port_no, "no sg list given by guest: 0x%08x\n", opts); @@ -691,7 +693,8 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist, int offset) goto out; } - qemu_sglist_init(sglist, (sglist_alloc_hint - off_idx), ad->hba->as); + qemu_sglist_init(sglist, qbus->parent, (sglist_alloc_hint - off_idx), + ad->hba->as); qemu_sglist_add(sglist, le64_to_cpu(tbl[off_idx].addr + off_pos), le32_to_cpu(tbl[off_idx].flags_size) + 1 - off_pos); @@ -1103,10 +1106,15 @@ static int ahci_dma_add_status(IDEDMA *dma, int status) } static int ahci_dma_set_inactive(IDEDMA *dma) +{ + return 0; +} + +static int ahci_async_cmd_done(IDEDMA *dma) { AHCIDevice *ad = DO_UPCAST(AHCIDevice, dma, dma); - DPRINTF(ad->port_no, "dma done\n"); + DPRINTF(ad->port_no, "async cmd done\n"); /* update d2h status */ ahci_write_fis_d2h(ad, NULL); @@ -1141,6 +1149,7 @@ static const IDEDMAOps ahci_dma_ops = { .set_unit = ahci_dma_set_unit, .add_status = ahci_dma_add_status, .set_inactive = ahci_dma_set_inactive, + .async_cmd_done = ahci_async_cmd_done, .restart_cb = ahci_dma_restart_cb, .reset = ahci_dma_reset, }; @@ -1155,8 +1164,10 @@ void ahci_init(AHCIState *s, DeviceState *qdev, AddressSpace *as, int ports) s->dev = g_malloc0(sizeof(AHCIDevice) * ports); ahci_reg_init(s); /* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */ - memory_region_init_io(&s->mem, &ahci_mem_ops, s, "ahci", AHCI_MEM_BAR_SIZE); - memory_region_init_io(&s->idp, &ahci_idp_ops, s, "ahci-idp", 32); + memory_region_init_io(&s->mem, OBJECT(qdev), &ahci_mem_ops, s, + "ahci", AHCI_MEM_BAR_SIZE); + memory_region_init_io(&s->idp, OBJECT(qdev), &ahci_idp_ops, s, + "ahci-idp", 32); irqs = qemu_allocate_irqs(ahci_irq_set, s, s->ports); diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c index 99167011d..33be3867a 100644 --- a/hw/ide/cmd646.c +++ b/hw/ide/cmd646.c @@ -117,8 +117,10 @@ static void setup_cmd646_bar(PCIIDEState *d, int bus_num) bar->bus = bus; bar->pci_dev = d; - memory_region_init_io(&bar->cmd, &cmd646_cmd_ops, bar, "cmd646-cmd", 4); - memory_region_init_io(&bar->data, &cmd646_data_ops, bar, "cmd646-data", 8); + memory_region_init_io(&bar->cmd, OBJECT(d), &cmd646_cmd_ops, bar, + "cmd646-cmd", 4); + memory_region_init_io(&bar->data, OBJECT(d), &cmd646_data_ops, bar, + "cmd646-data", 8); } static uint64_t bmdma_read(void *opaque, hwaddr addr, @@ -203,13 +205,14 @@ static void bmdma_setup_bar(PCIIDEState *d) BMDMAState *bm; int i; - memory_region_init(&d->bmdma_bar, "cmd646-bmdma", 16); + memory_region_init(&d->bmdma_bar, OBJECT(d), "cmd646-bmdma", 16); for(i = 0;i < 2; i++) { bm = &d->bmdma[i]; - memory_region_init_io(&bm->extra_io, &cmd646_bmdma_ops, bm, + memory_region_init_io(&bm->extra_io, OBJECT(d), &cmd646_bmdma_ops, bm, "cmd646-bmdma-bus", 4); memory_region_add_subregion(&d->bmdma_bar, i * 8, &bm->extra_io); - memory_region_init_io(&bm->addr_ioport, &bmdma_addr_ioport_ops, bm, + memory_region_init_io(&bm->addr_ioport, OBJECT(d), + &bmdma_addr_ioport_ops, bm, "cmd646-bmdma-ioport", 4); memory_region_add_subregion(&d->bmdma_bar, i * 8 + 4, &bm->addr_ioport); } diff --git a/hw/ide/core.c b/hw/ide/core.c index 03d1cfa7d..a73af7252 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -568,10 +568,18 @@ static void dma_buf_commit(IDEState *s) qemu_sglist_destroy(&s->sg); } +static void ide_async_cmd_done(IDEState *s) +{ + if (s->bus->dma->ops->async_cmd_done) { + s->bus->dma->ops->async_cmd_done(s->bus->dma); + } +} + void ide_set_inactive(IDEState *s) { s->bus->dma->aiocb = NULL; s->bus->dma->ops->set_inactive(s->bus->dma); + ide_async_cmd_done(s); } void ide_dma_error(IDEState *s) @@ -804,6 +812,7 @@ static void ide_flush_cb(void *opaque, int ret) bdrv_acct_done(s->bs, &s->acct); s->status = READY_STAT | SEEK_STAT; + ide_async_cmd_done(s); ide_set_irq(s->bus); } diff --git a/hw/ide/internal.h b/hw/ide/internal.h index 03f14896d..048a05214 100644 --- a/hw/ide/internal.h +++ b/hw/ide/internal.h @@ -433,6 +433,7 @@ struct IDEDMAOps { DMAIntFunc *set_unit; DMAIntFunc *add_status; DMAFunc *set_inactive; + DMAFunc *async_cmd_done; DMARestartFunc *restart_cb; DMAFunc *reset; }; diff --git a/hw/ide/macio.c b/hw/ide/macio.c index a1952b077..38ad92423 100644 --- a/hw/ide/macio.c +++ b/hw/ide/macio.c @@ -30,6 +30,22 @@ #include +/* debug MACIO */ +// #define DEBUG_MACIO + +#ifdef DEBUG_MACIO +static const int debug_macio = 1; +#else +static const int debug_macio = 0; +#endif + +#define MACIO_DPRINTF(fmt, ...) do { \ + if (debug_macio) { \ + printf(fmt , ## __VA_ARGS__); \ + } \ + } while (0) + + /***********************************************************/ /* MacIO based PowerPC IDE */ @@ -40,14 +56,26 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) DBDMA_io *io = opaque; MACIOIDEState *m = io->opaque; IDEState *s = idebus_active_if(&m->bus); + int unaligned; if (ret < 0) { m->aiocb = NULL; qemu_sglist_destroy(&s->sg); ide_atapi_io_error(s, ret); + io->remainder_len = 0; goto done; } + if (!m->dma_active) { + MACIO_DPRINTF("waiting for data (%#x - %#x - %x)\n", + s->nsector, io->len, s->status); + /* data not ready yet, wait for the channel to get restarted */ + io->processing = false; + return; + } + + MACIO_DPRINTF("io_buffer_size = %#x\n", s->io_buffer_size); + if (s->io_buffer_size > 0) { m->aiocb = NULL; qemu_sglist_destroy(&s->sg); @@ -55,33 +83,94 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) s->packet_transfer_size -= s->io_buffer_size; s->io_buffer_index += s->io_buffer_size; - s->lba += s->io_buffer_index >> 11; + s->lba += s->io_buffer_index >> 11; s->io_buffer_index &= 0x7ff; } - if (s->packet_transfer_size <= 0) + s->io_buffer_size = MIN(io->len, s->packet_transfer_size); + + MACIO_DPRINTF("remainder: %d io->len: %d size: %d\n", io->remainder_len, + io->len, s->packet_transfer_size); + if (io->remainder_len && io->len) { + /* guest wants the rest of its previous transfer */ + int remainder_len = MIN(io->remainder_len, io->len); + + MACIO_DPRINTF("copying remainder %d bytes\n", remainder_len); + + cpu_physical_memory_write(io->addr, io->remainder + 0x200 - + remainder_len, remainder_len); + + io->addr += remainder_len; + io->len -= remainder_len; + s->io_buffer_size = remainder_len; + io->remainder_len -= remainder_len; + /* treat remainder as individual transfer, start again */ + qemu_sglist_init(&s->sg, DEVICE(m), io->len / MACIO_PAGE_SIZE + 1, + &address_space_memory); + pmac_ide_atapi_transfer_cb(opaque, 0); + return; + } + + if (!s->packet_transfer_size) { + MACIO_DPRINTF("end of transfer\n"); ide_atapi_cmd_ok(s); + m->dma_active = false; + } if (io->len == 0) { + MACIO_DPRINTF("end of DMA\n"); goto done; } /* launch next transfer */ - s->io_buffer_size = io->len; + /* handle unaligned accesses first, get them over with and only do the + remaining bulk transfer using our async DMA helpers */ + unaligned = io->len & 0x1ff; + if (unaligned) { + int sector_num = (s->lba << 2) + (s->io_buffer_index >> 9); + int nsector = io->len >> 9; + + MACIO_DPRINTF("precopying unaligned %d bytes to %#lx\n", + unaligned, io->addr + io->len - unaligned); + + bdrv_read(s->bs, sector_num + nsector, io->remainder, 1); + cpu_physical_memory_write(io->addr + io->len - unaligned, + io->remainder, unaligned); + + io->len -= unaligned; + } + + MACIO_DPRINTF("io->len = %#x\n", io->len); - qemu_sglist_init(&s->sg, io->len / MACIO_PAGE_SIZE + 1, + qemu_sglist_init(&s->sg, DEVICE(m), io->len / MACIO_PAGE_SIZE + 1, &address_space_memory); qemu_sglist_add(&s->sg, io->addr, io->len); - io->addr += io->len; + io->addr += s->io_buffer_size; + io->remainder_len = MIN(s->packet_transfer_size - s->io_buffer_size, + (0x200 - unaligned) & 0x1ff); + MACIO_DPRINTF("set remainder to: %d\n", io->remainder_len); + + /* We would read no data from the block layer, thus not get a callback. + Just fake completion manually. */ + if (!io->len) { + pmac_ide_atapi_transfer_cb(opaque, 0); + return; + } + io->len = 0; + MACIO_DPRINTF("sector_num=%d size=%d, cmd_cmd=%d\n", + (s->lba << 2) + (s->io_buffer_index >> 9), + s->packet_transfer_size, s->dma_cmd); + m->aiocb = dma_bdrv_read(s->bs, &s->sg, (int64_t)(s->lba << 2) + (s->io_buffer_index >> 9), pmac_ide_atapi_transfer_cb, io); return; done: + MACIO_DPRINTF("done DMA\n"); bdrv_acct_done(s->bs, &s->acct); io->dma_end(opaque); } @@ -91,17 +180,29 @@ static void pmac_ide_transfer_cb(void *opaque, int ret) DBDMA_io *io = opaque; MACIOIDEState *m = io->opaque; IDEState *s = idebus_active_if(&m->bus); - int n; + int n = 0; int64_t sector_num; + int unaligned; if (ret < 0) { + MACIO_DPRINTF("DMA error\n"); m->aiocb = NULL; qemu_sglist_destroy(&s->sg); - ide_dma_error(s); + ide_dma_error(s); + io->remainder_len = 0; goto done; } + if (!m->dma_active) { + MACIO_DPRINTF("waiting for data (%#x - %#x - %x)\n", + s->nsector, io->len, s->status); + /* data not ready yet, wait for the channel to get restarted */ + io->processing = false; + return; + } + sector_num = ide_get_sector(s); + MACIO_DPRINTF("io_buffer_size = %#x\n", s->io_buffer_size); if (s->io_buffer_size > 0) { m->aiocb = NULL; qemu_sglist_destroy(&s->sg); @@ -111,36 +212,105 @@ static void pmac_ide_transfer_cb(void *opaque, int ret) s->nsector -= n; } - /* end of transfer ? */ - if (s->nsector == 0) { + MACIO_DPRINTF("remainder: %d io->len: %d nsector: %d sector_num: %ld\n", + io->remainder_len, io->len, s->nsector, sector_num); + if (io->remainder_len && io->len) { + /* guest wants the rest of its previous transfer */ + int remainder_len = MIN(io->remainder_len, io->len); + uint8_t *p = &io->remainder[0x200 - remainder_len]; + + MACIO_DPRINTF("copying remainder %d bytes at %#lx\n", + remainder_len, io->addr); + + switch (s->dma_cmd) { + case IDE_DMA_READ: + cpu_physical_memory_write(io->addr, p, remainder_len); + break; + case IDE_DMA_WRITE: + cpu_physical_memory_read(io->addr, p, remainder_len); + bdrv_write(s->bs, sector_num - 1, io->remainder, 1); + break; + case IDE_DMA_TRIM: + break; + } + io->addr += remainder_len; + io->len -= remainder_len; + io->remainder_len -= remainder_len; + } + + if (s->nsector == 0 && !io->remainder_len) { + MACIO_DPRINTF("end of transfer\n"); s->status = READY_STAT | SEEK_STAT; ide_set_irq(s->bus); + m->dma_active = false; } - /* end of DMA ? */ if (io->len == 0) { + MACIO_DPRINTF("end of DMA\n"); goto done; } /* launch next transfer */ s->io_buffer_index = 0; - s->io_buffer_size = io->len; + s->io_buffer_size = MIN(io->len, s->nsector * 512); + + /* handle unaligned accesses first, get them over with and only do the + remaining bulk transfer using our async DMA helpers */ + unaligned = io->len & 0x1ff; + if (unaligned) { + int nsector = io->len >> 9; + + MACIO_DPRINTF("precopying unaligned %d bytes to %#lx\n", + unaligned, io->addr + io->len - unaligned); + + switch (s->dma_cmd) { + case IDE_DMA_READ: + bdrv_read(s->bs, sector_num + nsector, io->remainder, 1); + cpu_physical_memory_write(io->addr + io->len - unaligned, + io->remainder, unaligned); + break; + case IDE_DMA_WRITE: + /* cache the contents in our io struct */ + cpu_physical_memory_read(io->addr + io->len - unaligned, + io->remainder, unaligned); + break; + case IDE_DMA_TRIM: + break; + } + + io->len -= unaligned; + } + + MACIO_DPRINTF("io->len = %#x\n", io->len); - qemu_sglist_init(&s->sg, io->len / MACIO_PAGE_SIZE + 1, + qemu_sglist_init(&s->sg, DEVICE(m), io->len / MACIO_PAGE_SIZE + 1, &address_space_memory); qemu_sglist_add(&s->sg, io->addr, io->len); - io->addr += io->len; + io->addr += io->len + unaligned; + io->remainder_len = (0x200 - unaligned) & 0x1ff; + MACIO_DPRINTF("set remainder to: %d\n", io->remainder_len); + + /* We would read no data from the block layer, thus not get a callback. + Just fake completion manually. */ + if (!io->len) { + pmac_ide_transfer_cb(opaque, 0); + return; + } + io->len = 0; + MACIO_DPRINTF("sector_num=%" PRId64 " n=%d, nsector=%d, cmd_cmd=%d\n", + sector_num, n, s->nsector, s->dma_cmd); + switch (s->dma_cmd) { case IDE_DMA_READ: m->aiocb = dma_bdrv_read(s->bs, &s->sg, sector_num, - pmac_ide_transfer_cb, io); + pmac_ide_transfer_cb, io); break; case IDE_DMA_WRITE: m->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num, - pmac_ide_transfer_cb, io); + pmac_ide_transfer_cb, io); break; case IDE_DMA_TRIM: m->aiocb = dma_bdrv_io(s->bs, &s->sg, sector_num, @@ -162,6 +332,8 @@ static void pmac_ide_transfer(DBDMA_io *io) MACIOIDEState *m = io->opaque; IDEState *s = idebus_active_if(&m->bus); + MACIO_DPRINTF("\n"); + s->io_buffer_size = 0; if (s->drive_kind == IDE_CD) { bdrv_acct_start(s->bs, &s->acct, io->len, BDRV_ACCT_READ); @@ -322,11 +494,51 @@ static void macio_ide_reset(DeviceState *dev) ide_bus_reset(&d->bus); } +static int ide_nop(IDEDMA *dma) +{ + return 0; +} + +static int ide_nop_int(IDEDMA *dma, int x) +{ + return 0; +} + +static void ide_nop_restart(void *opaque, int x, RunState y) +{ +} + +static void ide_dbdma_start(IDEDMA *dma, IDEState *s, + BlockDriverCompletionFunc *cb) +{ + MACIOIDEState *m = container_of(dma, MACIOIDEState, dma); + + MACIO_DPRINTF("\n"); + m->dma_active = true; + DBDMA_kick(m->dbdma); +} + +static const IDEDMAOps dbdma_ops = { + .start_dma = ide_dbdma_start, + .start_transfer = ide_nop, + .prepare_buf = ide_nop_int, + .rw_buf = ide_nop_int, + .set_unit = ide_nop_int, + .add_status = ide_nop_int, + .set_inactive = ide_nop, + .restart_cb = ide_nop_restart, + .reset = ide_nop, +}; + static void macio_ide_realizefn(DeviceState *dev, Error **errp) { MACIOIDEState *s = MACIO_IDE(dev); ide_init2(&s->bus, s->irq); + + /* Register DMA callbacks */ + s->dma.ops = &dbdma_ops; + s->bus.dma = &s->dma; } static void macio_ide_initfn(Object *obj) @@ -335,7 +547,7 @@ static void macio_ide_initfn(Object *obj) MACIOIDEState *s = MACIO_IDE(obj); ide_bus_new(&s->bus, DEVICE(obj), 0, 2); - memory_region_init_io(&s->mem, &pmac_ide_ops, s, "pmac-ide", 0x1000); + memory_region_init_io(&s->mem, obj, &pmac_ide_ops, s, "pmac-ide", 0x1000); sysbus_init_mmio(d, &s->mem); sysbus_init_irq(d, &s->irq); sysbus_init_irq(d, &s->dma_irq); @@ -363,7 +575,7 @@ static void macio_ide_register_types(void) type_register_static(&macio_ide_type_info); } -/* hd_table must contain 4 block drivers */ +/* hd_table must contain 2 block drivers */ void macio_ide_init_drives(MACIOIDEState *s, DriveInfo **hd_table) { int i; @@ -377,6 +589,7 @@ void macio_ide_init_drives(MACIOIDEState *s, DriveInfo **hd_table) void macio_ide_register_dma(MACIOIDEState *s, void *dbdma, int channel) { + s->dbdma = dbdma; DBDMA_register_channel(dbdma, channel, s->dma_irq, pmac_ide_transfer, pmac_ide_flush, s); } diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c index e80e7e5af..d251ff983 100644 --- a/hw/ide/mmio.c +++ b/hw/ide/mmio.c @@ -124,9 +124,9 @@ static void mmio_ide_realizefn(DeviceState *dev, Error **errp) ide_init2(&s->bus, s->irq); - memory_region_init_io(&s->iomem1, &mmio_ide_ops, s, + memory_region_init_io(&s->iomem1, OBJECT(s), &mmio_ide_ops, s, "ide-mmio.1", 16 << s->shift); - memory_region_init_io(&s->iomem2, &mmio_ide_cs_ops, s, + memory_region_init_io(&s->iomem2, OBJECT(s), &mmio_ide_cs_ops, s, "ide-mmio.2", 2 << s->shift); sysbus_init_mmio(d, &s->iomem1); sysbus_init_mmio(d, &s->iomem2); diff --git a/hw/ide/piix.c b/hw/ide/piix.c index bf2856fb6..58532fe09 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -90,15 +90,15 @@ static void bmdma_setup_bar(PCIIDEState *d) { int i; - memory_region_init(&d->bmdma_bar, "piix-bmdma-container", 16); + memory_region_init(&d->bmdma_bar, OBJECT(d), "piix-bmdma-container", 16); for(i = 0;i < 2; i++) { BMDMAState *bm = &d->bmdma[i]; - memory_region_init_io(&bm->extra_io, &piix_bmdma_ops, bm, + memory_region_init_io(&bm->extra_io, OBJECT(d), &piix_bmdma_ops, bm, "piix-bmdma", 4); memory_region_add_subregion(&d->bmdma_bar, i * 8, &bm->extra_io); - memory_region_init_io(&bm->addr_ioport, &bmdma_addr_ioport_ops, bm, - "bmdma", 4); + memory_region_init_io(&bm->addr_ioport, OBJECT(d), + &bmdma_addr_ioport_ops, bm, "bmdma", 4); memory_region_add_subregion(&d->bmdma_bar, i * 8 + 4, &bm->addr_ioport); } } diff --git a/hw/ide/via.c b/hw/ide/via.c index 5fe053cf9..5a831916f 100644 --- a/hw/ide/via.c +++ b/hw/ide/via.c @@ -92,15 +92,15 @@ static void bmdma_setup_bar(PCIIDEState *d) { int i; - memory_region_init(&d->bmdma_bar, "via-bmdma-container", 16); + memory_region_init(&d->bmdma_bar, OBJECT(d), "via-bmdma-container", 16); for(i = 0;i < 2; i++) { BMDMAState *bm = &d->bmdma[i]; - memory_region_init_io(&bm->extra_io, &via_bmdma_ops, bm, + memory_region_init_io(&bm->extra_io, OBJECT(d), &via_bmdma_ops, bm, "via-bmdma", 4); memory_region_add_subregion(&d->bmdma_bar, i * 8, &bm->extra_io); - memory_region_init_io(&bm->addr_ioport, &bmdma_addr_ioport_ops, bm, - "bmdma", 4); + memory_region_init_io(&bm->addr_ioport, OBJECT(d), + &bmdma_addr_ioport_ops, bm, "bmdma", 4); memory_region_add_subregion(&d->bmdma_bar, i * 8 + 4, &bm->addr_ioport); } } diff --git a/hw/input/milkymist-softusb.c b/hw/input/milkymist-softusb.c index 3edab4ff0..942cb7971 100644 --- a/hw/input/milkymist-softusb.c +++ b/hw/input/milkymist-softusb.c @@ -265,17 +265,17 @@ static int milkymist_softusb_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq); - memory_region_init_io(&s->regs_region, &softusb_mmio_ops, s, + memory_region_init_io(&s->regs_region, OBJECT(s), &softusb_mmio_ops, s, "milkymist-softusb", R_MAX * 4); sysbus_init_mmio(dev, &s->regs_region); /* register pmem and dmem */ - memory_region_init_ram(&s->pmem, "milkymist-softusb.pmem", + memory_region_init_ram(&s->pmem, OBJECT(s), "milkymist-softusb.pmem", s->pmem_size); vmstate_register_ram_global(&s->pmem); s->pmem_ptr = memory_region_get_ram_ptr(&s->pmem); sysbus_init_mmio(dev, &s->pmem); - memory_region_init_ram(&s->dmem, "milkymist-softusb.dmem", + memory_region_init_ram(&s->dmem, OBJECT(s), "milkymist-softusb.dmem", s->dmem_size); vmstate_register_ram_global(&s->dmem); s->dmem_ptr = memory_region_get_ram_ptr(&s->dmem); diff --git a/hw/input/pckbd.c b/hw/input/pckbd.c index fff0a4d1f..ce86237cf 100644 --- a/hw/input/pckbd.c +++ b/hw/input/pckbd.c @@ -424,7 +424,7 @@ void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq, vmstate_register(NULL, 0, &vmstate_kbd, s); - memory_region_init_io(region, &i8042_mmio_ops, s, "i8042", size); + memory_region_init_io(region, NULL, &i8042_mmio_ops, s, "i8042", size); s->kbd = ps2_kbd_init(kbd_update_kbd_irq, s); s->mouse = ps2_mouse_init(kbd_update_aux_irq, s); @@ -494,8 +494,10 @@ static void i8042_initfn(Object *obj) ISAKBDState *isa_s = I8042(obj); KBDState *s = &isa_s->kbd; - memory_region_init_io(isa_s->io + 0, &i8042_data_ops, s, "i8042-data", 1); - memory_region_init_io(isa_s->io + 1, &i8042_cmd_ops, s, "i8042-cmd", 1); + memory_region_init_io(isa_s->io + 0, obj, &i8042_data_ops, s, + "i8042-data", 1); + memory_region_init_io(isa_s->io + 1, obj, &i8042_cmd_ops, s, + "i8042-cmd", 1); } static void i8042_realizefn(DeviceState *dev, Error **errp) diff --git a/hw/input/pl050.c b/hw/input/pl050.c index 7dd8a59dd..2312ffc50 100644 --- a/hw/input/pl050.c +++ b/hw/input/pl050.c @@ -137,7 +137,7 @@ static int pl050_init(SysBusDevice *dev, int is_mouse) { pl050_state *s = FROM_SYSBUS(pl050_state, dev); - memory_region_init_io(&s->iomem, &pl050_ops, s, "pl050", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &pl050_ops, s, "pl050", 0x1000); sysbus_init_mmio(dev, &s->iomem); sysbus_init_irq(dev, &s->irq); s->is_mouse = is_mouse; diff --git a/hw/input/pxa2xx_keypad.c b/hw/input/pxa2xx_keypad.c index 1fd5f2076..846d1370d 100644 --- a/hw/input/pxa2xx_keypad.c +++ b/hw/input/pxa2xx_keypad.c @@ -313,7 +313,7 @@ PXA2xxKeyPadState *pxa27x_keypad_init(MemoryRegion *sysmem, s = (PXA2xxKeyPadState *) g_malloc0(sizeof(PXA2xxKeyPadState)); s->irq = irq; - memory_region_init_io(&s->iomem, &pxa2xx_keypad_ops, s, + memory_region_init_io(&s->iomem, NULL, &pxa2xx_keypad_ops, s, "pxa2xx-keypad", 0x00100000); memory_region_add_subregion(sysmem, base, &s->iomem); diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs index 2ba49d0e4..2851eed25 100644 --- a/hw/intc/Makefile.objs +++ b/hw/intc/Makefile.objs @@ -10,15 +10,16 @@ common-obj-$(CONFIG_REALVIEW) += realview_gic.o common-obj-$(CONFIG_SLAVIO) += slavio_intctl.o common-obj-$(CONFIG_IOAPIC) += ioapic_common.o common-obj-$(CONFIG_ARM_GIC) += arm_gic_common.o +common-obj-$(CONFIG_ARM_GIC) += arm_gic.o +common-obj-$(CONFIG_OPENPIC) += openpic.o obj-$(CONFIG_APIC) += apic.o apic_common.o -obj-$(CONFIG_ARM_GIC) += arm_gic.o obj-$(CONFIG_ARM_GIC_KVM) += arm_gic_kvm.o obj-$(CONFIG_STELLARIS) += armv7m_nvic.o obj-$(CONFIG_EXYNOS4) += exynos4210_gic.o exynos4210_combiner.o obj-$(CONFIG_GRLIB) += grlib_irqmp.o obj-$(CONFIG_IOAPIC) += ioapic.o obj-$(CONFIG_OMAP) += omap_intc.o -obj-$(CONFIG_OPENPIC) += openpic.o obj-$(CONFIG_OPENPIC_KVM) += openpic_kvm.o obj-$(CONFIG_SH4) += sh_intc.o +obj-$(CONFIG_XICS) += xics.o diff --git a/hw/intc/apic.c b/hw/intc/apic.c index 46cb0975d..5e3b96e4d 100644 --- a/hw/intc/apic.c +++ b/hw/intc/apic.c @@ -873,7 +873,7 @@ static const MemoryRegionOps apic_io_ops = { static void apic_init(APICCommonState *s) { - memory_region_init_io(&s->io_memory, &apic_io_ops, s, "apic-msi", + memory_region_init_io(&s->io_memory, OBJECT(s), &apic_io_ops, s, "apic-msi", APIC_SPACE_SIZE); s->timer = qemu_new_timer_ns(vm_clock, apic_timer, s); diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c index bae65721f..8e340049c 100644 --- a/hw/intc/arm_gic.c +++ b/hw/intc/arm_gic.c @@ -20,6 +20,7 @@ #include "hw/sysbus.h" #include "gic_internal.h" +#include "qom/cpu.h" //#define DEBUG_GIC @@ -39,8 +40,7 @@ static const uint8_t gic_id[] = { static inline int gic_get_current_cpu(GICState *s) { if (s->num_cpu > 1) { - CPUState *cpu = ENV_GET_CPU(cpu_single_env); - return cpu->cpu_index; + return current_cpu->cpu_index; } return 0; } @@ -656,7 +656,8 @@ void gic_init_irqs_and_distributor(GICState *s, int num_irq) for (i = 0; i < NUM_CPU(s); i++) { sysbus_init_irq(&s->busdev, &s->parent_irq[i]); } - memory_region_init_io(&s->iomem, &gic_dist_ops, s, "gic_dist", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &gic_dist_ops, s, + "gic_dist", 0x1000); } static void arm_gic_realize(DeviceState *dev, Error **errp) @@ -682,12 +683,12 @@ static void arm_gic_realize(DeviceState *dev, Error **errp) * GIC v2 defines a larger memory region (0x1000) so this will need * to be extended when we implement A15. */ - memory_region_init_io(&s->cpuiomem[0], &gic_thiscpu_ops, s, + memory_region_init_io(&s->cpuiomem[0], OBJECT(s), &gic_thiscpu_ops, s, "gic_cpu", 0x100); for (i = 0; i < NUM_CPU(s); i++) { s->backref[i] = s; - memory_region_init_io(&s->cpuiomem[i+1], &gic_cpu_ops, &s->backref[i], - "gic_cpu", 0x100); + memory_region_init_io(&s->cpuiomem[i+1], OBJECT(s), &gic_cpu_ops, + &s->backref[i], "gic_cpu", 0x100); } /* Distributor */ sysbus_init_mmio(sbd, &s->iomem); diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c index b7564568d..f71397542 100644 --- a/hw/intc/arm_gic_kvm.c +++ b/hw/intc/arm_gic_kvm.c @@ -120,7 +120,8 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp) sysbus_init_irq(sbd, &s->parent_irq[i]); } /* Distributor */ - memory_region_init_reservation(&s->iomem, "kvm-gic_dist", 0x1000); + memory_region_init_reservation(&s->iomem, OBJECT(s), + "kvm-gic_dist", 0x1000); sysbus_init_mmio(sbd, &s->iomem); kvm_arm_register_device(&s->iomem, (KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT) @@ -129,7 +130,8 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp) * provide the "interface for core #N" memory regions, because * cores with a VGIC don't have those. */ - memory_region_init_reservation(&s->cpuiomem[0], "kvm-gic_cpu", 0x1000); + memory_region_init_reservation(&s->cpuiomem[0], OBJECT(s), + "kvm-gic_cpu", 0x1000); sysbus_init_mmio(sbd, &s->cpuiomem[0]); kvm_arm_register_device(&s->cpuiomem[0], (KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT) diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index 25fa43cb2..178344b5a 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -140,6 +140,7 @@ void armv7m_nvic_complete_irq(void *opaque, int irq) static uint32_t nvic_readl(nvic_state *s, uint32_t offset) { + ARMCPU *cpu; uint32_t val; int irq; @@ -171,7 +172,8 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset) case 0x1c: /* SysTick Calibration Value. */ return 10000; case 0xd00: /* CPUID Base. */ - return cpu_single_env->cp15.c0_cpuid; + cpu = ARM_CPU(current_cpu); + return cpu->env.cp15.c0_cpuid; case 0xd04: /* Interrupt Control State. */ /* VECTACTIVE */ val = s->gic.running_irq[0]; @@ -206,7 +208,8 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset) val |= (1 << 31); return val; case 0xd08: /* Vector Table Offset. */ - return cpu_single_env->v7m.vecbase; + cpu = ARM_CPU(current_cpu); + return cpu->env.v7m.vecbase; case 0xd0c: /* Application Interrupt/Reset Control. */ return 0xfa05000; case 0xd10: /* System Control. */ @@ -279,6 +282,7 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset) static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value) { + ARMCPU *cpu; uint32_t oldval; switch (offset) { case 0x10: /* SysTick Control and Status. */ @@ -331,7 +335,8 @@ static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value) } break; case 0xd08: /* Vector Table Offset. */ - cpu_single_env->v7m.vecbase = value & 0xffffff80; + cpu = ARM_CPU(current_cpu); + cpu->env.v7m.vecbase = value & 0xffffff80; break; case 0xd0c: /* Application Interrupt/Reset Control. */ if ((value >> 16) == 0x05fa) { @@ -487,17 +492,18 @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp) * We use overlaying to put the GIC like registers * over the top of the system control register region. */ - memory_region_init(&s->container, "nvic", 0x1000); + memory_region_init(&s->container, OBJECT(s), "nvic", 0x1000); /* The system register region goes at the bottom of the priority * stack as it covers the whole page. */ - memory_region_init_io(&s->sysregmem, &nvic_sysreg_ops, s, + memory_region_init_io(&s->sysregmem, OBJECT(s), &nvic_sysreg_ops, s, "nvic_sysregs", 0x1000); memory_region_add_subregion(&s->container, 0, &s->sysregmem); /* Alias the GIC region so we can get only the section of it * we need, and layer it on top of the system register region. */ - memory_region_init_alias(&s->gic_iomem_alias, "nvic-gic", &s->gic.iomem, + memory_region_init_alias(&s->gic_iomem_alias, OBJECT(s), + "nvic-gic", &s->gic.iomem, 0x100, 0xc00); memory_region_add_subregion_overlap(&s->container, 0x100, &s->gic_iomem_alias, 1); diff --git a/hw/intc/etraxfs_pic.c b/hw/intc/etraxfs_pic.c index 635103c00..ce3a3f6eb 100644 --- a/hw/intc/etraxfs_pic.c +++ b/hw/intc/etraxfs_pic.c @@ -146,7 +146,8 @@ static int etraxfs_pic_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->parent_irq); sysbus_init_irq(dev, &s->parent_nmi); - memory_region_init_io(&s->mmio, &pic_ops, s, "etraxfs-pic", R_MAX * 4); + memory_region_init_io(&s->mmio, OBJECT(s), &pic_ops, s, + "etraxfs-pic", R_MAX * 4); sysbus_init_mmio(dev, &s->mmio); return 0; } diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c index 687428730..3b4097682 100644 --- a/hw/intc/exynos4210_combiner.c +++ b/hw/intc/exynos4210_combiner.c @@ -417,7 +417,7 @@ static int exynos4210_combiner_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->output_irq[i]); } - memory_region_init_io(&s->iomem, &exynos4210_combiner_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_combiner_ops, s, "exynos4210-combiner", IIC_REGION_SIZE); sysbus_init_mmio(dev, &s->iomem); diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c index bad6dde65..6147f04bc 100644 --- a/hw/intc/exynos4210_gic.c +++ b/hw/intc/exynos4210_gic.c @@ -299,15 +299,15 @@ static int exynos4210_gic_init(SysBusDevice *dev) qdev_init_gpio_in(&s->busdev.qdev, exynos4210_gic_set_irq, EXYNOS4210_GIC_NIRQ - 32); - memory_region_init(&s->cpu_container, "exynos4210-cpu-container", + memory_region_init(&s->cpu_container, OBJECT(s), "exynos4210-cpu-container", EXYNOS4210_EXT_GIC_CPU_REGION_SIZE); - memory_region_init(&s->dist_container, "exynos4210-dist-container", + memory_region_init(&s->dist_container, OBJECT(s), "exynos4210-dist-container", EXYNOS4210_EXT_GIC_DIST_REGION_SIZE); for (i = 0; i < s->num_cpu; i++) { /* Map CPU interface per SMP Core */ sprintf(cpu_alias_name, "%s%x", cpu_prefix, i); - memory_region_init_alias(&s->cpu_alias[i], + memory_region_init_alias(&s->cpu_alias[i], OBJECT(s), cpu_alias_name, sysbus_mmio_get_region(busdev, 1), 0, @@ -317,7 +317,7 @@ static int exynos4210_gic_init(SysBusDevice *dev) /* Map Distributor per SMP Core */ sprintf(dist_alias_name, "%s%x", dist_prefix, i); - memory_region_init_alias(&s->dist_alias[i], + memory_region_init_alias(&s->dist_alias[i], OBJECT(s), dist_alias_name, sysbus_mmio_get_region(busdev, 0), 0, diff --git a/hw/intc/grlib_irqmp.c b/hw/intc/grlib_irqmp.c index 68dfe6a4b..181f61429 100644 --- a/hw/intc/grlib_irqmp.c +++ b/hw/intc/grlib_irqmp.c @@ -344,7 +344,7 @@ static int grlib_irqmp_init(SysBusDevice *dev) return -1; } - memory_region_init_io(&irqmp->iomem, &grlib_irqmp_ops, irqmp, + memory_region_init_io(&irqmp->iomem, OBJECT(dev), &grlib_irqmp_ops, irqmp, "irqmp", IRQMP_REG_SIZE); irqmp->state = g_malloc0(sizeof *irqmp->state); diff --git a/hw/intc/heathrow_pic.c b/hw/intc/heathrow_pic.c index beb966118..9818f2430 100644 --- a/hw/intc/heathrow_pic.c +++ b/hw/intc/heathrow_pic.c @@ -205,7 +205,7 @@ qemu_irq *heathrow_pic_init(MemoryRegion **pmem, s = g_malloc0(sizeof(HeathrowPICS)); /* only 1 CPU */ s->irqs = irqs[0]; - memory_region_init_io(&s->mem, &heathrow_pic_ops, s, + memory_region_init_io(&s->mem, NULL, &heathrow_pic_ops, s, "heathrow-pic", 0x1000); *pmem = &s->mem; diff --git a/hw/intc/i8259.c b/hw/intc/i8259.c index 192a0ba68..1415bda93 100644 --- a/hw/intc/i8259.c +++ b/hw/intc/i8259.c @@ -417,8 +417,10 @@ static void pic_realize(DeviceState *dev, Error **err) PICCommonState *s = PIC_COMMON(dev); PICClass *pc = PIC_GET_CLASS(dev); - memory_region_init_io(&s->base_io, &pic_base_ioport_ops, s, "pic", 2); - memory_region_init_io(&s->elcr_io, &pic_elcr_ioport_ops, s, "elcr", 1); + memory_region_init_io(&s->base_io, OBJECT(s), &pic_base_ioport_ops, s, + "pic", 2); + memory_region_init_io(&s->elcr_io, OBJECT(s), &pic_elcr_ioport_ops, s, + "elcr", 1); qdev_init_gpio_out(dev, s->int_out, ARRAY_SIZE(s->int_out)); qdev_init_gpio_in(dev, pic_set_irq, 8); diff --git a/hw/intc/imx_avic.c b/hw/intc/imx_avic.c index ff45dcdc0..75c8ffde2 100644 --- a/hw/intc/imx_avic.c +++ b/hw/intc/imx_avic.c @@ -372,7 +372,8 @@ static int imx_avic_init(SysBusDevice *dev) { IMXAVICState *s = FROM_SYSBUS(IMXAVICState, dev); - memory_region_init_io(&s->iomem, &imx_avic_ops, s, "imx_avic", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &imx_avic_ops, s, + "imx_avic", 0x1000); sysbus_init_mmio(dev, &s->iomem); qdev_init_gpio_in(&dev->qdev, imx_avic_set_irq, IMX_AVIC_NUM_IRQS); diff --git a/hw/intc/ioapic.c b/hw/intc/ioapic.c index c6f09f433..5d064fe3a 100644 --- a/hw/intc/ioapic.c +++ b/hw/intc/ioapic.c @@ -227,7 +227,8 @@ static const MemoryRegionOps ioapic_io_ops = { static void ioapic_init(IOAPICCommonState *s, int instance_no) { - memory_region_init_io(&s->io_memory, &ioapic_io_ops, s, "ioapic", 0x1000); + memory_region_init_io(&s->io_memory, OBJECT(s), &ioapic_io_ops, s, + "ioapic", 0x1000); qdev_init_gpio_in(&s->busdev.qdev, ioapic_set_irq, IOAPIC_NUM_PINS); diff --git a/hw/intc/omap_intc.c b/hw/intc/omap_intc.c index 875eba4e3..bca858528 100644 --- a/hw/intc/omap_intc.c +++ b/hw/intc/omap_intc.c @@ -367,7 +367,7 @@ static int omap_intc_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->parent_intr[0]); sysbus_init_irq(dev, &s->parent_intr[1]); qdev_init_gpio_in(&dev->qdev, omap_set_intr, s->nbanks * 32); - memory_region_init_io(&s->mmio, &omap_inth_mem_ops, s, + memory_region_init_io(&s->mmio, OBJECT(s), &omap_inth_mem_ops, s, "omap-intc", s->size); sysbus_init_mmio(dev, &s->mmio); return 0; @@ -609,7 +609,7 @@ static int omap2_intc_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->parent_intr[0]); sysbus_init_irq(dev, &s->parent_intr[1]); qdev_init_gpio_in(&dev->qdev, omap_set_intr_noedge, s->nbanks * 32); - memory_region_init_io(&s->mmio, &omap2_inth_mem_ops, s, + memory_region_init_io(&s->mmio, OBJECT(s), &omap2_inth_mem_ops, s, "omap2-intc", 0x1000); sysbus_init_mmio(dev, &s->mmio); return 0; diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c index a26c64169..7df72f44f 100644 --- a/hw/intc/openpic.c +++ b/hw/intc/openpic.c @@ -37,10 +37,10 @@ #include "hw/ppc/mac.h" #include "hw/pci/pci.h" #include "hw/ppc/openpic.h" +#include "hw/ppc/ppc_e500.h" #include "hw/sysbus.h" #include "hw/pci/msi.h" #include "qemu/bitops.h" -#include "hw/ppc/ppc.h" //#define DEBUG_OPENPIC @@ -180,14 +180,11 @@ static int output_to_inttgt(int output) static int get_current_cpu(void) { - CPUState *cpu_single_cpu; - - if (!cpu_single_env) { + if (!current_cpu) { return -1; } - cpu_single_cpu = ENV_GET_CPU(cpu_single_env); - return cpu_single_cpu->cpu_index; + return current_cpu->cpu_index; } static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr, @@ -1516,8 +1513,8 @@ static void map_list(OpenPICState *opp, const MemReg *list, int *count) while (list->name) { assert(*count < ARRAY_SIZE(opp->sub_io_mem)); - memory_region_init_io(&opp->sub_io_mem[*count], list->ops, opp, - list->name, list->size); + memory_region_init_io(&opp->sub_io_mem[*count], OBJECT(opp), list->ops, + opp, list->name, list->size); memory_region_add_subregion(&opp->mem, list->start_addr, &opp->sub_io_mem[*count]); @@ -1531,7 +1528,7 @@ static void openpic_init(Object *obj) { OpenPICState *opp = OPENPIC(obj); - memory_region_init(&opp->mem, "openpic", 0x40000); + memory_region_init(&opp->mem, obj, "openpic", 0x40000); } static void openpic_realize(DeviceState *dev, Error **errp) diff --git a/hw/intc/openpic_kvm.c b/hw/intc/openpic_kvm.c index 6775879e0..c7f7b8406 100644 --- a/hw/intc/openpic_kvm.c +++ b/hw/intc/openpic_kvm.c @@ -155,7 +155,7 @@ static void kvm_openpic_init(Object *obj) { KVMOpenPICState *opp = KVM_OPENPIC(obj); - memory_region_init_io(&opp->mem, &kvm_openpic_mem_ops, opp, + memory_region_init_io(&opp->mem, OBJECT(opp), &kvm_openpic_mem_ops, opp, "kvm-openpic", 0x40000); } diff --git a/hw/intc/pl190.c b/hw/intc/pl190.c index 9610673d9..fdb29d7ed 100644 --- a/hw/intc/pl190.c +++ b/hw/intc/pl190.c @@ -236,7 +236,7 @@ static int pl190_init(SysBusDevice *dev) { pl190_state *s = FROM_SYSBUS(pl190_state, dev); - memory_region_init_io(&s->iomem, &pl190_ops, s, "pl190", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &pl190_ops, s, "pl190", 0x1000); sysbus_init_mmio(dev, &s->iomem); qdev_init_gpio_in(&dev->qdev, pl190_set_irq, 32); sysbus_init_irq(dev, &s->irq); diff --git a/hw/intc/puv3_intc.c b/hw/intc/puv3_intc.c index 0cd5e9eae..44b66517f 100644 --- a/hw/intc/puv3_intc.c +++ b/hw/intc/puv3_intc.c @@ -106,7 +106,7 @@ static int puv3_intc_init(SysBusDevice *dev) s->reg_ICMR = 0; s->reg_ICPR = 0; - memory_region_init_io(&s->iomem, &puv3_intc_ops, s, "puv3_intc", + memory_region_init_io(&s->iomem, OBJECT(s), &puv3_intc_ops, s, "puv3_intc", PUV3_REGS_OFFSET); sysbus_init_mmio(dev, &s->iomem); diff --git a/hw/intc/realview_gic.c b/hw/intc/realview_gic.c index 0ec30caa0..e122c2c81 100644 --- a/hw/intc/realview_gic.c +++ b/hw/intc/realview_gic.c @@ -43,7 +43,8 @@ static int realview_gic_init(SysBusDevice *dev) /* Pass through inbound GPIO lines to the GIC */ qdev_init_gpio_in(&s->busdev.qdev, realview_gic_set_irq, numirq - 32); - memory_region_init(&s->container, "realview-gic-container", 0x2000); + memory_region_init(&s->container, OBJECT(s), + "realview-gic-container", 0x2000); memory_region_add_subregion(&s->container, 0, sysbus_mmio_get_region(busdev, 1)); memory_region_add_subregion(&s->container, 0x1000, diff --git a/hw/intc/sh_intc.c b/hw/intc/sh_intc.c index 050bfb63c..55c76e4af 100644 --- a/hw/intc/sh_intc.c +++ b/hw/intc/sh_intc.c @@ -42,16 +42,15 @@ void sh_intc_toggle_source(struct intc_source *source, pending_changed = 1; if (pending_changed) { - CPUState *cpu = CPU(sh_env_get_cpu(first_cpu)); if (source->pending) { source->parent->pending++; if (source->parent->pending == 1) { - cpu_interrupt(cpu, CPU_INTERRUPT_HARD); + cpu_interrupt(first_cpu, CPU_INTERRUPT_HARD); } } else { source->parent->pending--; if (source->parent->pending == 0) { - cpu_reset_interrupt(cpu, CPU_INTERRUPT_HARD); + cpu_reset_interrupt(first_cpu, CPU_INTERRUPT_HARD); } } } @@ -319,11 +318,11 @@ static unsigned int sh_intc_register(MemoryRegion *sysmem, #define SH_INTC_IOMEM_FORMAT "interrupt-controller-%s-%s-%s" snprintf(name, sizeof(name), SH_INTC_IOMEM_FORMAT, type, action, "p4"); - memory_region_init_alias(iomem_p4, name, iomem, INTC_A7(address), 4); + memory_region_init_alias(iomem_p4, NULL, name, iomem, INTC_A7(address), 4); memory_region_add_subregion(sysmem, P4ADDR(address), iomem_p4); snprintf(name, sizeof(name), SH_INTC_IOMEM_FORMAT, type, action, "a7"); - memory_region_init_alias(iomem_a7, name, iomem, INTC_A7(address), 4); + memory_region_init_alias(iomem_a7, NULL, name, iomem, INTC_A7(address), 4); memory_region_add_subregion(sysmem, A7ADDR(address), iomem_a7); #undef SH_INTC_IOMEM_FORMAT @@ -466,7 +465,7 @@ int sh_intc_init(MemoryRegion *sysmem, desc->irqs = qemu_allocate_irqs(sh_intc_set_irq, desc, nr_sources); - memory_region_init_io(&desc->iomem, &sh_intc_ops, desc, + memory_region_init_io(&desc->iomem, NULL, &sh_intc_ops, desc, "interrupt-controller", 0x100000000ULL); #define INT_REG_PARAMS(reg_struct, type, action, j) \ diff --git a/hw/intc/slavio_intctl.c b/hw/intc/slavio_intctl.c index b367752fd..b47d0f0a9 100644 --- a/hw/intc/slavio_intctl.c +++ b/hw/intc/slavio_intctl.c @@ -426,7 +426,7 @@ static int slavio_intctl_init1(SysBusDevice *dev) char slave_name[45]; qdev_init_gpio_in(&dev->qdev, slavio_set_irq_all, 32 + MAX_CPUS); - memory_region_init_io(&s->iomem, &slavio_intctlm_mem_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &slavio_intctlm_mem_ops, s, "master-interrupt-controller", INTCTLM_SIZE); sysbus_init_mmio(dev, &s->iomem); @@ -436,7 +436,8 @@ static int slavio_intctl_init1(SysBusDevice *dev) for (j = 0; j < MAX_PILS; j++) { sysbus_init_irq(dev, &s->cpu_irqs[i][j]); } - memory_region_init_io(&s->slaves[i].iomem, &slavio_intctl_mem_ops, + memory_region_init_io(&s->slaves[i].iomem, OBJECT(s), + &slavio_intctl_mem_ops, &s->slaves[i], slave_name, INTCTL_SIZE); sysbus_init_mmio(dev, &s->slaves[i].iomem); s->slaves[i].cpu = i; diff --git a/hw/intc/xics.c b/hw/intc/xics.c new file mode 100644 index 000000000..091912e2c --- /dev/null +++ b/hw/intc/xics.c @@ -0,0 +1,587 @@ +/* + * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator + * + * PAPR Virtualized Interrupt System, aka ICS/ICP aka xics + * + * Copyright (c) 2010,2011 David Gibson, IBM Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include "hw/hw.h" +#include "trace.h" +#include "hw/ppc/spapr.h" +#include "hw/ppc/xics.h" + +/* + * ICP: Presentation layer + */ + +struct icp_server_state { + uint32_t xirr; + uint8_t pending_priority; + uint8_t mfrr; + qemu_irq output; +}; + +#define XISR_MASK 0x00ffffff +#define CPPR_MASK 0xff000000 + +#define XISR(ss) (((ss)->xirr) & XISR_MASK) +#define CPPR(ss) (((ss)->xirr) >> 24) + +struct ics_state; + +struct icp_state { + long nr_servers; + struct icp_server_state *ss; + struct ics_state *ics; +}; + +static void ics_reject(struct ics_state *ics, int nr); +static void ics_resend(struct ics_state *ics); +static void ics_eoi(struct ics_state *ics, int nr); + +static void icp_check_ipi(struct icp_state *icp, int server) +{ + struct icp_server_state *ss = icp->ss + server; + + if (XISR(ss) && (ss->pending_priority <= ss->mfrr)) { + return; + } + + trace_xics_icp_check_ipi(server, ss->mfrr); + + if (XISR(ss)) { + ics_reject(icp->ics, XISR(ss)); + } + + ss->xirr = (ss->xirr & ~XISR_MASK) | XICS_IPI; + ss->pending_priority = ss->mfrr; + qemu_irq_raise(ss->output); +} + +static void icp_resend(struct icp_state *icp, int server) +{ + struct icp_server_state *ss = icp->ss + server; + + if (ss->mfrr < CPPR(ss)) { + icp_check_ipi(icp, server); + } + ics_resend(icp->ics); +} + +static void icp_set_cppr(struct icp_state *icp, int server, uint8_t cppr) +{ + struct icp_server_state *ss = icp->ss + server; + uint8_t old_cppr; + uint32_t old_xisr; + + old_cppr = CPPR(ss); + ss->xirr = (ss->xirr & ~CPPR_MASK) | (cppr << 24); + + if (cppr < old_cppr) { + if (XISR(ss) && (cppr <= ss->pending_priority)) { + old_xisr = XISR(ss); + ss->xirr &= ~XISR_MASK; /* Clear XISR */ + ss->pending_priority = 0xff; + qemu_irq_lower(ss->output); + ics_reject(icp->ics, old_xisr); + } + } else { + if (!XISR(ss)) { + icp_resend(icp, server); + } + } +} + +static void icp_set_mfrr(struct icp_state *icp, int server, uint8_t mfrr) +{ + struct icp_server_state *ss = icp->ss + server; + + ss->mfrr = mfrr; + if (mfrr < CPPR(ss)) { + icp_check_ipi(icp, server); + } +} + +static uint32_t icp_accept(struct icp_server_state *ss) +{ + uint32_t xirr = ss->xirr; + + qemu_irq_lower(ss->output); + ss->xirr = ss->pending_priority << 24; + ss->pending_priority = 0xff; + + trace_xics_icp_accept(xirr, ss->xirr); + + return xirr; +} + +static void icp_eoi(struct icp_state *icp, int server, uint32_t xirr) +{ + struct icp_server_state *ss = icp->ss + server; + + /* Send EOI -> ICS */ + ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK); + trace_xics_icp_eoi(server, xirr, ss->xirr); + ics_eoi(icp->ics, xirr & XISR_MASK); + if (!XISR(ss)) { + icp_resend(icp, server); + } +} + +static void icp_irq(struct icp_state *icp, int server, int nr, uint8_t priority) +{ + struct icp_server_state *ss = icp->ss + server; + + trace_xics_icp_irq(server, nr, priority); + + if ((priority >= CPPR(ss)) + || (XISR(ss) && (ss->pending_priority <= priority))) { + ics_reject(icp->ics, nr); + } else { + if (XISR(ss)) { + ics_reject(icp->ics, XISR(ss)); + } + ss->xirr = (ss->xirr & ~XISR_MASK) | (nr & XISR_MASK); + ss->pending_priority = priority; + trace_xics_icp_raise(ss->xirr, ss->pending_priority); + qemu_irq_raise(ss->output); + } +} + +/* + * ICS: Source layer + */ + +struct ics_irq_state { + int server; + uint8_t priority; + uint8_t saved_priority; +#define XICS_STATUS_ASSERTED 0x1 +#define XICS_STATUS_SENT 0x2 +#define XICS_STATUS_REJECTED 0x4 +#define XICS_STATUS_MASKED_PENDING 0x8 + uint8_t status; +}; + +struct ics_state { + int nr_irqs; + int offset; + qemu_irq *qirqs; + bool *islsi; + struct ics_irq_state *irqs; + struct icp_state *icp; +}; + +static int ics_valid_irq(struct ics_state *ics, uint32_t nr) +{ + return (nr >= ics->offset) + && (nr < (ics->offset + ics->nr_irqs)); +} + +static void resend_msi(struct ics_state *ics, int srcno) +{ + struct ics_irq_state *irq = ics->irqs + srcno; + + /* FIXME: filter by server#? */ + if (irq->status & XICS_STATUS_REJECTED) { + irq->status &= ~XICS_STATUS_REJECTED; + if (irq->priority != 0xff) { + icp_irq(ics->icp, irq->server, srcno + ics->offset, + irq->priority); + } + } +} + +static void resend_lsi(struct ics_state *ics, int srcno) +{ + struct ics_irq_state *irq = ics->irqs + srcno; + + if ((irq->priority != 0xff) + && (irq->status & XICS_STATUS_ASSERTED) + && !(irq->status & XICS_STATUS_SENT)) { + irq->status |= XICS_STATUS_SENT; + icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority); + } +} + +static void set_irq_msi(struct ics_state *ics, int srcno, int val) +{ + struct ics_irq_state *irq = ics->irqs + srcno; + + trace_xics_set_irq_msi(srcno, srcno + ics->offset); + + if (val) { + if (irq->priority == 0xff) { + irq->status |= XICS_STATUS_MASKED_PENDING; + trace_xics_masked_pending(); + } else { + icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority); + } + } +} + +static void set_irq_lsi(struct ics_state *ics, int srcno, int val) +{ + struct ics_irq_state *irq = ics->irqs + srcno; + + trace_xics_set_irq_lsi(srcno, srcno + ics->offset); + if (val) { + irq->status |= XICS_STATUS_ASSERTED; + } else { + irq->status &= ~XICS_STATUS_ASSERTED; + } + resend_lsi(ics, srcno); +} + +static void ics_set_irq(void *opaque, int srcno, int val) +{ + struct ics_state *ics = (struct ics_state *)opaque; + + if (ics->islsi[srcno]) { + set_irq_lsi(ics, srcno, val); + } else { + set_irq_msi(ics, srcno, val); + } +} + +static void write_xive_msi(struct ics_state *ics, int srcno) +{ + struct ics_irq_state *irq = ics->irqs + srcno; + + if (!(irq->status & XICS_STATUS_MASKED_PENDING) + || (irq->priority == 0xff)) { + return; + } + + irq->status &= ~XICS_STATUS_MASKED_PENDING; + icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority); +} + +static void write_xive_lsi(struct ics_state *ics, int srcno) +{ + resend_lsi(ics, srcno); +} + +static void ics_write_xive(struct ics_state *ics, int nr, int server, + uint8_t priority, uint8_t saved_priority) +{ + int srcno = nr - ics->offset; + struct ics_irq_state *irq = ics->irqs + srcno; + + irq->server = server; + irq->priority = priority; + irq->saved_priority = saved_priority; + + trace_xics_ics_write_xive(nr, srcno, server, priority); + + if (ics->islsi[srcno]) { + write_xive_lsi(ics, srcno); + } else { + write_xive_msi(ics, srcno); + } +} + +static void ics_reject(struct ics_state *ics, int nr) +{ + struct ics_irq_state *irq = ics->irqs + nr - ics->offset; + + trace_xics_ics_reject(nr, nr - ics->offset); + irq->status |= XICS_STATUS_REJECTED; /* Irrelevant but harmless for LSI */ + irq->status &= ~XICS_STATUS_SENT; /* Irrelevant but harmless for MSI */ +} + +static void ics_resend(struct ics_state *ics) +{ + int i; + + for (i = 0; i < ics->nr_irqs; i++) { + /* FIXME: filter by server#? */ + if (ics->islsi[i]) { + resend_lsi(ics, i); + } else { + resend_msi(ics, i); + } + } +} + +static void ics_eoi(struct ics_state *ics, int nr) +{ + int srcno = nr - ics->offset; + struct ics_irq_state *irq = ics->irqs + srcno; + + trace_xics_ics_eoi(nr); + + if (ics->islsi[srcno]) { + irq->status &= ~XICS_STATUS_SENT; + } +} + +/* + * Exported functions + */ + +qemu_irq xics_get_qirq(struct icp_state *icp, int irq) +{ + if (!ics_valid_irq(icp->ics, irq)) { + return NULL; + } + + return icp->ics->qirqs[irq - icp->ics->offset]; +} + +void xics_set_irq_type(struct icp_state *icp, int irq, bool lsi) +{ + assert(ics_valid_irq(icp->ics, irq)); + + icp->ics->islsi[irq - icp->ics->offset] = lsi; +} + +static target_ulong h_cppr(PowerPCCPU *cpu, sPAPREnvironment *spapr, + target_ulong opcode, target_ulong *args) +{ + CPUState *cs = CPU(cpu); + target_ulong cppr = args[0]; + + icp_set_cppr(spapr->icp, cs->cpu_index, cppr); + return H_SUCCESS; +} + +static target_ulong h_ipi(PowerPCCPU *cpu, sPAPREnvironment *spapr, + target_ulong opcode, target_ulong *args) +{ + target_ulong server = args[0]; + target_ulong mfrr = args[1]; + + if (server >= spapr->icp->nr_servers) { + return H_PARAMETER; + } + + icp_set_mfrr(spapr->icp, server, mfrr); + return H_SUCCESS; +} + +static target_ulong h_xirr(PowerPCCPU *cpu, sPAPREnvironment *spapr, + target_ulong opcode, target_ulong *args) +{ + CPUState *cs = CPU(cpu); + uint32_t xirr = icp_accept(spapr->icp->ss + cs->cpu_index); + + args[0] = xirr; + return H_SUCCESS; +} + +static target_ulong h_eoi(PowerPCCPU *cpu, sPAPREnvironment *spapr, + target_ulong opcode, target_ulong *args) +{ + CPUState *cs = CPU(cpu); + target_ulong xirr = args[0]; + + icp_eoi(spapr->icp, cs->cpu_index, xirr); + return H_SUCCESS; +} + +static void rtas_set_xive(PowerPCCPU *cpu, sPAPREnvironment *spapr, + uint32_t token, + uint32_t nargs, target_ulong args, + uint32_t nret, target_ulong rets) +{ + struct ics_state *ics = spapr->icp->ics; + uint32_t nr, server, priority; + + if ((nargs != 3) || (nret != 1)) { + rtas_st(rets, 0, -3); + return; + } + + nr = rtas_ld(args, 0); + server = rtas_ld(args, 1); + priority = rtas_ld(args, 2); + + if (!ics_valid_irq(ics, nr) || (server >= ics->icp->nr_servers) + || (priority > 0xff)) { + rtas_st(rets, 0, -3); + return; + } + + ics_write_xive(ics, nr, server, priority, priority); + + rtas_st(rets, 0, 0); /* Success */ +} + +static void rtas_get_xive(PowerPCCPU *cpu, sPAPREnvironment *spapr, + uint32_t token, + uint32_t nargs, target_ulong args, + uint32_t nret, target_ulong rets) +{ + struct ics_state *ics = spapr->icp->ics; + uint32_t nr; + + if ((nargs != 1) || (nret != 3)) { + rtas_st(rets, 0, -3); + return; + } + + nr = rtas_ld(args, 0); + + if (!ics_valid_irq(ics, nr)) { + rtas_st(rets, 0, -3); + return; + } + + rtas_st(rets, 0, 0); /* Success */ + rtas_st(rets, 1, ics->irqs[nr - ics->offset].server); + rtas_st(rets, 2, ics->irqs[nr - ics->offset].priority); +} + +static void rtas_int_off(PowerPCCPU *cpu, sPAPREnvironment *spapr, + uint32_t token, + uint32_t nargs, target_ulong args, + uint32_t nret, target_ulong rets) +{ + struct ics_state *ics = spapr->icp->ics; + uint32_t nr; + + if ((nargs != 1) || (nret != 1)) { + rtas_st(rets, 0, -3); + return; + } + + nr = rtas_ld(args, 0); + + if (!ics_valid_irq(ics, nr)) { + rtas_st(rets, 0, -3); + return; + } + + ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, 0xff, + ics->irqs[nr - ics->offset].priority); + + rtas_st(rets, 0, 0); /* Success */ +} + +static void rtas_int_on(PowerPCCPU *cpu, sPAPREnvironment *spapr, + uint32_t token, + uint32_t nargs, target_ulong args, + uint32_t nret, target_ulong rets) +{ + struct ics_state *ics = spapr->icp->ics; + uint32_t nr; + + if ((nargs != 1) || (nret != 1)) { + rtas_st(rets, 0, -3); + return; + } + + nr = rtas_ld(args, 0); + + if (!ics_valid_irq(ics, nr)) { + rtas_st(rets, 0, -3); + return; + } + + ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, + ics->irqs[nr - ics->offset].saved_priority, + ics->irqs[nr - ics->offset].saved_priority); + + rtas_st(rets, 0, 0); /* Success */ +} + +static void xics_reset(void *opaque) +{ + struct icp_state *icp = (struct icp_state *)opaque; + struct ics_state *ics = icp->ics; + int i; + + for (i = 0; i < icp->nr_servers; i++) { + icp->ss[i].xirr = 0; + icp->ss[i].pending_priority = 0xff; + icp->ss[i].mfrr = 0xff; + /* Make all outputs are deasserted */ + qemu_set_irq(icp->ss[i].output, 0); + } + + memset(ics->irqs, 0, sizeof(struct ics_irq_state) * ics->nr_irqs); + for (i = 0; i < ics->nr_irqs; i++) { + ics->irqs[i].priority = 0xff; + ics->irqs[i].saved_priority = 0xff; + } +} + +void xics_cpu_setup(struct icp_state *icp, PowerPCCPU *cpu) +{ + CPUState *cs = CPU(cpu); + CPUPPCState *env = &cpu->env; + struct icp_server_state *ss = &icp->ss[cs->cpu_index]; + + assert(cs->cpu_index < icp->nr_servers); + + switch (PPC_INPUT(env)) { + case PPC_FLAGS_INPUT_POWER7: + ss->output = env->irq_inputs[POWER7_INPUT_INT]; + break; + + case PPC_FLAGS_INPUT_970: + ss->output = env->irq_inputs[PPC970_INPUT_INT]; + break; + + default: + fprintf(stderr, "XICS interrupt controller does not support this CPU " + "bus model\n"); + abort(); + } +} + +struct icp_state *xics_system_init(int nr_servers, int nr_irqs) +{ + struct icp_state *icp; + struct ics_state *ics; + + icp = g_malloc0(sizeof(*icp)); + icp->nr_servers = nr_servers; + icp->ss = g_malloc0(icp->nr_servers*sizeof(struct icp_server_state)); + + ics = g_malloc0(sizeof(*ics)); + ics->nr_irqs = nr_irqs; + ics->offset = XICS_IRQ_BASE; + ics->irqs = g_malloc0(nr_irqs * sizeof(struct ics_irq_state)); + ics->islsi = g_malloc0(nr_irqs * sizeof(bool)); + + icp->ics = ics; + ics->icp = icp; + + ics->qirqs = qemu_allocate_irqs(ics_set_irq, ics, nr_irqs); + + spapr_register_hypercall(H_CPPR, h_cppr); + spapr_register_hypercall(H_IPI, h_ipi); + spapr_register_hypercall(H_XIRR, h_xirr); + spapr_register_hypercall(H_EOI, h_eoi); + + spapr_rtas_register("ibm,set-xive", rtas_set_xive); + spapr_rtas_register("ibm,get-xive", rtas_get_xive); + spapr_rtas_register("ibm,int-off", rtas_int_off); + spapr_rtas_register("ibm,int-on", rtas_int_on); + + qemu_register_reset(xics_reset, icp); + + return icp; +} diff --git a/hw/intc/xilinx_intc.c b/hw/intc/xilinx_intc.c index 297f53759..25d2057d7 100644 --- a/hw/intc/xilinx_intc.c +++ b/hw/intc/xilinx_intc.c @@ -160,7 +160,8 @@ static int xilinx_intc_init(SysBusDevice *dev) qdev_init_gpio_in(&dev->qdev, irq_handler, 32); sysbus_init_irq(dev, &p->parent_irq); - memory_region_init_io(&p->mmio, &pic_ops, p, "xlnx.xps-intc", R_MAX * 4); + memory_region_init_io(&p->mmio, OBJECT(p), &pic_ops, p, "xlnx.xps-intc", + R_MAX * 4); sysbus_init_mmio(dev, &p->mmio); return 0; } diff --git a/hw/isa/apm.c b/hw/isa/apm.c index 5f21d2147..f97e7a0c2 100644 --- a/hw/isa/apm.c +++ b/hw/isa/apm.c @@ -96,7 +96,7 @@ void apm_init(PCIDevice *dev, APMState *apm, apm_ctrl_changed_t callback, apm->arg = arg; /* ioport 0xb2, 0xb3 */ - memory_region_init_io(&apm->io, &apm_ops, apm, "apm-io", 2); + memory_region_init_io(&apm->io, OBJECT(dev), &apm_ops, apm, "apm-io", 2); memory_region_add_subregion(pci_address_space_io(dev), APM_CNT_IOPORT, &apm->io); } diff --git a/hw/isa/i82378.c b/hw/isa/i82378.c index a24cb98cb..b25ed04af 100644 --- a/hw/isa/i82378.c +++ b/hw/isa/i82378.c @@ -221,10 +221,12 @@ static int pci_i82378_init(PCIDevice *dev) pci_conf[PCI_INTERRUPT_PIN] = 1; /* interrupt pin 0 */ - memory_region_init_io(&s->io, &i82378_io_ops, s, "i82378-io", 0x00010000); + memory_region_init_io(&s->io, OBJECT(pci), &i82378_io_ops, s, + "i82378-io", 0x00010000); pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->io); - memory_region_init_io(&s->mem, &i82378_mem_ops, s, "i82378-mem", 0x01000000); + memory_region_init_io(&s->mem, OBJECT(pci), &i82378_mem_ops, s, + "i82378-mem", 0x01000000); pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mem); /* Make I/O address read only */ diff --git a/hw/isa/isa-bus.c b/hw/isa/isa-bus.c index 136d17ede..cfd610c68 100644 --- a/hw/isa/isa-bus.c +++ b/hw/isa/isa-bus.c @@ -115,7 +115,7 @@ void isa_register_portio_list(ISADevice *dev, uint16_t start, actually handled e.g. the FDC device. */ isa_init_ioport(dev, start); - portio_list_init(piolist, pio_start, opaque, name); + portio_list_init(piolist, OBJECT(dev), pio_start, opaque, name); portio_list_add(piolist, isabus->address_space_io, start); } diff --git a/hw/isa/isa_mmio.c b/hw/isa/isa_mmio.c index d4dbf1383..00ae8ebc2 100644 --- a/hw/isa/isa_mmio.c +++ b/hw/isa/isa_mmio.c @@ -69,7 +69,7 @@ static const MemoryRegionOps isa_mmio_ops = { void isa_mmio_setup(MemoryRegion *mr, hwaddr size) { - memory_region_init_io(mr, &isa_mmio_ops, NULL, "isa-mmio", size); + memory_region_init_io(mr, NULL, &isa_mmio_ops, NULL, "isa-mmio", size); } void isa_mmio_init(hwaddr base, hwaddr size) diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c index 667e88296..d1921aa63 100644 --- a/hw/isa/lpc_ich9.c +++ b/hw/isa/lpc_ich9.c @@ -380,7 +380,7 @@ static void ich9_apm_ctrl_changed(uint32_t val, void *arg) /* SMI_EN = PMBASE + 30. SMI control and enable register */ if (lpc->pm.smi_en & ICH9_PMIO_SMI_EN_APMC_EN) { - cpu_interrupt(CPU(x86_env_get_cpu(first_cpu)), CPU_INTERRUPT_SMI); + cpu_interrupt(first_cpu, CPU_INTERRUPT_SMI); } } @@ -477,22 +477,23 @@ static const MemoryRegionOps rbca_mmio_ops = { static void ich9_lpc_machine_ready(Notifier *n, void *opaque) { ICH9LPCState *s = container_of(n, ICH9LPCState, machine_ready); + MemoryRegion *io_as = pci_address_space_io(&s->d); uint8_t *pci_conf; pci_conf = s->d.config; - if (isa_is_ioport_assigned(0x3f8)) { + if (memory_region_present(io_as, 0x3f8)) { /* com1 */ pci_conf[0x82] |= 0x01; } - if (isa_is_ioport_assigned(0x2f8)) { + if (memory_region_present(io_as, 0x2f8)) { /* com2 */ pci_conf[0x82] |= 0x02; } - if (isa_is_ioport_assigned(0x378)) { + if (memory_region_present(io_as, 0x378)) { /* lpt */ pci_conf[0x82] |= 0x04; } - if (isa_is_ioport_assigned(0x3f0)) { + if (memory_region_present(io_as, 0x3f0)) { /* floppy */ pci_conf[0x82] |= 0x08; } @@ -534,7 +535,7 @@ static int ich9_lpc_initfn(PCIDevice *d) pci_set_long(d->wmask + ICH9_LPC_PMBASE, ICH9_LPC_PMBASE_BASE_ADDRESS_MASK); - memory_region_init_io(&lpc->rbca_mem, &rbca_mmio_ops, lpc, + memory_region_init_io(&lpc->rbca_mem, OBJECT(d), &rbca_mmio_ops, lpc, "lpc-rbca-mmio", ICH9_CC_SIZE); lpc->isa_bus = isa_bus; @@ -545,7 +546,7 @@ static int ich9_lpc_initfn(PCIDevice *d) lpc->machine_ready.notify = ich9_lpc_machine_ready; qemu_add_machine_init_done_notifier(&lpc->machine_ready); - memory_region_init_io(&lpc->rst_cnt_mem, &ich9_rst_cnt_ops, lpc, + memory_region_init_io(&lpc->rst_cnt_mem, OBJECT(d), &ich9_rst_cnt_ops, lpc, "lpc-reset-control", 1); memory_region_add_subregion_overlap(pci_address_space_io(d), ICH9_RST_CNT_IOPORT, &lpc->rst_cnt_mem, diff --git a/hw/isa/pc87312.c b/hw/isa/pc87312.c index cc426df7f..46a23fb6b 100644 --- a/hw/isa/pc87312.c +++ b/hw/isa/pc87312.c @@ -352,7 +352,7 @@ static void pc87312_initfn(Object *obj) { PC87312State *s = PC87312(obj); - memory_region_init_io(&s->io, &pc87312_io_ops, s, "pc87312", 2); + memory_region_init_io(&s->io, obj, &pc87312_io_ops, s, "pc87312", 2); } static const VMStateDescription vmstate_pc87312 = { diff --git a/hw/isa/vt82c686.c b/hw/isa/vt82c686.c index 391d90d14..2174eaaf8 100644 --- a/hw/isa/vt82c686.c +++ b/hw/isa/vt82c686.c @@ -43,10 +43,12 @@ typedef struct SuperIOConfig typedef struct VT82C686BState { PCIDevice dev; + MemoryRegion superio; SuperIOConfig superio_conf; } VT82C686BState; -static void superio_ioport_writeb(void *opaque, uint32_t addr, uint32_t data) +static void superio_ioport_writeb(void *opaque, hwaddr addr, uint64_t data, + unsigned size) { int can_write; SuperIOConfig *superio_conf = opaque; @@ -93,7 +95,7 @@ static void superio_ioport_writeb(void *opaque, uint32_t addr, uint32_t data) } } -static uint32_t superio_ioport_readb(void *opaque, uint32_t addr) +static uint64_t superio_ioport_readb(void *opaque, hwaddr addr, unsigned size) { SuperIOConfig *superio_conf = opaque; @@ -101,6 +103,16 @@ static uint32_t superio_ioport_readb(void *opaque, uint32_t addr) return (superio_conf->config[superio_conf->index]); } +static const MemoryRegionOps superio_ops = { + .read = superio_ioport_readb, + .write = superio_ioport_writeb, + .endianness = DEVICE_NATIVE_ENDIAN, + .impl = { + .min_access_size = 1, + .max_access_size = 1, + }, +}; + static void vt82c686b_reset(void * opaque) { PCIDevice *d = opaque; @@ -140,17 +152,7 @@ static void vt82c686b_write_config(PCIDevice * d, uint32_t address, pci_default_write_config(d, address, val, len); if (address == 0x85) { /* enable or disable super IO configure */ - if (val & 0x2) { - /* floppy also uses 0x3f0 and 0x3f1. - * But we do not emulate flopy,so just set it here. */ - isa_unassign_ioport(0x3f0, 2); - register_ioport_read(0x3f0, 2, 1, superio_ioport_readb, - &vt686->superio_conf); - register_ioport_write(0x3f0, 2, 1, superio_ioport_writeb, - &vt686->superio_conf); - } else { - isa_unassign_ioport(0x3f0, 2); - } + memory_region_set_enabled(&vt686->superio, val & 0x2); } } @@ -354,7 +356,7 @@ static int vt82c686b_pm_initfn(PCIDevice *dev) apm_init(dev, &s->apm, NULL, s); - memory_region_init(&s->io, "vt82c686-pm", 64); + memory_region_init(&s->io, OBJECT(dev), "vt82c686-pm", 64); memory_region_set_enabled(&s->io, false); memory_region_add_subregion(get_system_io(), 0, &s->io); @@ -423,11 +425,13 @@ static const VMStateDescription vmstate_via = { /* init the PCI-to-ISA bridge */ static int vt82c686b_initfn(PCIDevice *d) { + VT82C686BState *vt82c = DO_UPCAST(VT82C686BState, dev, d); uint8_t *pci_conf; + ISABus *isa_bus; uint8_t *wmask; int i; - isa_bus_new(&d->qdev, pci_address_space_io(d)); + isa_bus = isa_bus_new(&d->qdev, pci_address_space_io(d)); pci_conf = d->config; pci_config_set_prog_interface(pci_conf, 0x0); @@ -439,6 +443,14 @@ static int vt82c686b_initfn(PCIDevice *d) } } + memory_region_init_io(&vt82c->superio, OBJECT(d), &superio_ops, + &vt82c->superio_conf, "superio", 2); + memory_region_set_enabled(&vt82c->superio, false); + /* The floppy also uses 0x3f0 and 0x3f1. + * But we do not emulate a floppy, so just set it here. */ + memory_region_add_subregion(isa_bus->address_space_io, 0x3f0, + &vt82c->superio); + qemu_register_reset(vt82c686b_reset, d); return 0; diff --git a/hw/lm32/lm32_boards.c b/hw/lm32/lm32_boards.c index 1ca94980f..62003b858 100644 --- a/hw/lm32/lm32_boards.c +++ b/hw/lm32/lm32_boards.c @@ -106,7 +106,7 @@ static void lm32_evr_init(QEMUMachineInitArgs *args) reset_info->flash_base = flash_base; - memory_region_init_ram(phys_ram, "lm32_evr.sdram", ram_size); + memory_region_init_ram(phys_ram, NULL, "lm32_evr.sdram", ram_size); vmstate_register_ram_global(phys_ram); memory_region_add_subregion(address_space_mem, ram_base, phys_ram); @@ -203,7 +203,7 @@ static void lm32_uclinux_init(QEMUMachineInitArgs *args) reset_info->flash_base = flash_base; - memory_region_init_ram(phys_ram, "lm32_uclinux.sdram", ram_size); + memory_region_init_ram(phys_ram, NULL, "lm32_uclinux.sdram", ram_size); vmstate_register_ram_global(phys_ram); memory_region_add_subregion(address_space_mem, ram_base, phys_ram); diff --git a/hw/lm32/milkymist.c b/hw/lm32/milkymist.c index cca93748a..7ceedb814 100644 --- a/hw/lm32/milkymist.c +++ b/hw/lm32/milkymist.c @@ -112,7 +112,7 @@ milkymist_init(QEMUMachineInitArgs *args) cpu_lm32_set_phys_msb_ignore(env, 1); - memory_region_init_ram(phys_sdram, "milkymist.sdram", sdram_size); + memory_region_init_ram(phys_sdram, NULL, "milkymist.sdram", sdram_size); vmstate_register_ram_global(phys_sdram); memory_region_add_subregion(address_space_mem, sdram_base, phys_sdram); diff --git a/hw/m68k/an5206.c b/hw/m68k/an5206.c index c4a5626a5..0c03a87ab 100644 --- a/hw/m68k/an5206.c +++ b/hw/m68k/an5206.c @@ -49,12 +49,12 @@ static void an5206_init(QEMUMachineInitArgs *args) env->rambar0 = AN5206_RAMBAR_ADDR | 1; /* DRAM at address zero */ - memory_region_init_ram(ram, "an5206.ram", ram_size); + memory_region_init_ram(ram, NULL, "an5206.ram", ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(address_space_mem, 0, ram); /* Internal SRAM. */ - memory_region_init_ram(sram, "an5206.sram", 512); + memory_region_init_ram(sram, NULL, "an5206.sram", 512); vmstate_register_ram_global(sram); memory_region_add_subregion(address_space_mem, AN5206_RAMBAR_ADDR, sram); diff --git a/hw/m68k/dummy_m68k.c b/hw/m68k/dummy_m68k.c index 544d56b59..f4ed7c6cc 100644 --- a/hw/m68k/dummy_m68k.c +++ b/hw/m68k/dummy_m68k.c @@ -40,7 +40,7 @@ static void dummy_m68k_init(QEMUMachineInitArgs *args) env->vbr = 0; /* RAM at address zero */ - memory_region_init_ram(ram, "dummy_m68k.ram", ram_size); + memory_region_init_ram(ram, NULL, "dummy_m68k.ram", ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(address_space_mem, 0, ram); diff --git a/hw/m68k/mcf5206.c b/hw/m68k/mcf5206.c index bcc619d74..1727a4685 100644 --- a/hw/m68k/mcf5206.c +++ b/hw/m68k/mcf5206.c @@ -532,7 +532,7 @@ qemu_irq *mcf5206_init(MemoryRegion *sysmem, uint32_t base, M68kCPU *cpu) s = (m5206_mbar_state *)g_malloc0(sizeof(m5206_mbar_state)); - memory_region_init_io(&s->iomem, &m5206_mbar_ops, s, + memory_region_init_io(&s->iomem, NULL, &m5206_mbar_ops, s, "mbar", 0x00001000); memory_region_add_subregion(sysmem, base, &s->iomem); diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c index 05efde7ce..9cf000f4c 100644 --- a/hw/m68k/mcf5208.c +++ b/hw/m68k/mcf5208.c @@ -172,14 +172,14 @@ static void mcf5208_sys_init(MemoryRegion *address_space, qemu_irq *pic) int i; /* SDRAMC. */ - memory_region_init_io(iomem, &m5208_sys_ops, NULL, "m5208-sys", 0x00004000); + memory_region_init_io(iomem, NULL, &m5208_sys_ops, NULL, "m5208-sys", 0x00004000); memory_region_add_subregion(address_space, 0xfc0a8000, iomem); /* Timers. */ for (i = 0; i < 2; i++) { s = (m5208_timer_state *)g_malloc0(sizeof(m5208_timer_state)); bh = qemu_bh_new(m5208_timer_trigger, s); s->timer = ptimer_init(bh); - memory_region_init_io(&s->iomem, &m5208_timer_ops, s, + memory_region_init_io(&s->iomem, NULL, &m5208_timer_ops, s, "m5208-timer", 0x00004000); memory_region_add_subregion(address_space, 0xfc080000 + 0x4000 * i, &s->iomem); @@ -217,12 +217,12 @@ static void mcf5208evb_init(QEMUMachineInitArgs *args) /* TODO: Configure BARs. */ /* DRAM at 0x40000000 */ - memory_region_init_ram(ram, "mcf5208.ram", ram_size); + memory_region_init_ram(ram, NULL, "mcf5208.ram", ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(address_space_mem, 0x40000000, ram); /* Internal SRAM. */ - memory_region_init_ram(sram, "mcf5208.sram", 16384); + memory_region_init_ram(sram, NULL, "mcf5208.sram", 16384); vmstate_register_ram_global(sram); memory_region_add_subregion(address_space_mem, 0x80000000, sram); diff --git a/hw/m68k/mcf_intc.c b/hw/m68k/mcf_intc.c index cfe660d0a..621423c3e 100644 --- a/hw/m68k/mcf_intc.c +++ b/hw/m68k/mcf_intc.c @@ -147,7 +147,7 @@ qemu_irq *mcf_intc_init(MemoryRegion *sysmem, s->cpu = cpu; mcf_intc_reset(s); - memory_region_init_io(&s->iomem, &mcf_intc_ops, s, "mcf", 0x100); + memory_region_init_io(&s->iomem, NULL, &mcf_intc_ops, s, "mcf", 0x100); memory_region_add_subregion(sysmem, base, &s->iomem); return qemu_allocate_irqs(mcf_intc_set_irq, s, 64); diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c index 3f1d70ef9..5b057f788 100644 --- a/hw/microblaze/boot.c +++ b/hw/microblaze/boot.c @@ -28,6 +28,7 @@ #include "qemu/config-file.h" #include "qemu-common.h" #include "sysemu/device_tree.h" +#include "sysemu/sysemu.h" #include "hw/loader.h" #include "elf.h" @@ -93,20 +94,18 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base, void (*machine_cpu_reset)(MicroBlazeCPU *)) { QemuOpts *machine_opts; - const char *kernel_filename = NULL; - const char *kernel_cmdline = NULL; - - machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); - if (machine_opts) { - const char *dtb_arg; - kernel_filename = qemu_opt_get(machine_opts, "kernel"); - kernel_cmdline = qemu_opt_get(machine_opts, "append"); - dtb_arg = qemu_opt_get(machine_opts, "dtb"); - if (dtb_arg) { /* Preference a -dtb argument */ - dtb_filename = dtb_arg; - } else { /* default to pcbios dtb as passed by machine_init */ - dtb_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename); - } + const char *kernel_filename; + const char *kernel_cmdline; + const char *dtb_arg; + + machine_opts = qemu_get_machine_opts(); + kernel_filename = qemu_opt_get(machine_opts, "kernel"); + kernel_cmdline = qemu_opt_get(machine_opts, "append"); + dtb_arg = qemu_opt_get(machine_opts, "dtb"); + if (dtb_arg) { /* Preference a -dtb argument */ + dtb_filename = dtb_arg; + } else { /* default to pcbios dtb as passed by machine_init */ + dtb_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename); } boot_info.machine_cpu_reset = machine_cpu_reset; diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c index 334046808..989da25de 100644 --- a/hw/microblaze/petalogix_ml605_mmu.c +++ b/hw/microblaze/petalogix_ml605_mmu.c @@ -98,12 +98,12 @@ petalogix_ml605_init(QEMUMachineInitArgs *args) env = &cpu->env; /* Attach emulated BRAM through the LMB. */ - memory_region_init_ram(phys_lmb_bram, "petalogix_ml605.lmb_bram", + memory_region_init_ram(phys_lmb_bram, NULL, "petalogix_ml605.lmb_bram", LMB_BRAM_SIZE); vmstate_register_ram_global(phys_lmb_bram); memory_region_add_subregion(address_space_mem, 0x00000000, phys_lmb_bram); - memory_region_init_ram(phys_ram, "petalogix_ml605.ram", ram_size); + memory_region_init_ram(phys_ram, NULL, "petalogix_ml605.ram", ram_size); vmstate_register_ram_global(phys_ram); memory_region_add_subregion(address_space_mem, ddr_base, phys_ram); diff --git a/hw/microblaze/petalogix_s3adsp1800_mmu.c b/hw/microblaze/petalogix_s3adsp1800_mmu.c index b3bcd4ea5..a46149443 100644 --- a/hw/microblaze/petalogix_s3adsp1800_mmu.c +++ b/hw/microblaze/petalogix_s3adsp1800_mmu.c @@ -80,12 +80,12 @@ petalogix_s3adsp1800_init(QEMUMachineInitArgs *args) env = &cpu->env; /* Attach emulated BRAM through the LMB. */ - memory_region_init_ram(phys_lmb_bram, + memory_region_init_ram(phys_lmb_bram, NULL, "petalogix_s3adsp1800.lmb_bram", LMB_BRAM_SIZE); vmstate_register_ram_global(phys_lmb_bram); memory_region_add_subregion(sysmem, 0x00000000, phys_lmb_bram); - memory_region_init_ram(phys_ram, "petalogix_s3adsp1800.ram", ram_size); + memory_region_init_ram(phys_ram, NULL, "petalogix_s3adsp1800.ram", ram_size); vmstate_register_ram_global(phys_ram); memory_region_add_subregion(sysmem, ddr_base, phys_ram); diff --git a/hw/mips/gt64xxx_pci.c b/hw/mips/gt64xxx_pci.c index 189e865a6..584341756 100644 --- a/hw/mips/gt64xxx_pci.c +++ b/hw/mips/gt64xxx_pci.c @@ -1108,7 +1108,7 @@ PCIBus *gt64120_register(qemu_irq *pic) get_system_memory(), get_system_io(), PCI_DEVFN(18, 0), 4, TYPE_PCI_BUS); - memory_region_init_io(&d->ISD_mem, &isd_mem_ops, d, "isd-mem", 0x1000); + memory_region_init_io(&d->ISD_mem, OBJECT(dev), &isd_mem_ops, d, "isd-mem", 0x1000); pci_create_simple(phb->bus, PCI_DEVFN(0, 0), "gt64120_pci"); return phb->bus; diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c index 00c9071af..9e305d287 100644 --- a/hw/mips/mips_fulong2e.c +++ b/hw/mips/mips_fulong2e.c @@ -231,7 +231,7 @@ static void audio_init (PCIBus *pci_bus) } /* Network support */ -static void network_init (void) +static void network_init (PCIBus *pci_bus) { int i; @@ -244,16 +244,16 @@ static void network_init (void) default_devaddr = "07"; } - pci_nic_init_nofail(nd, "rtl8139", default_devaddr); + pci_nic_init_nofail(nd, pci_bus, "rtl8139", default_devaddr); } } static void cpu_request_exit(void *opaque, int irq, int level) { - CPUMIPSState *env = cpu_single_env; + CPUState *cpu = current_cpu; - if (env && level) { - cpu_exit(CPU(mips_env_get_cpu(env))); + if (cpu && level) { + cpu_exit(cpu); } } @@ -300,9 +300,9 @@ static void mips_fulong2e_init(QEMUMachineInitArgs *args) bios_size = 1024 * 1024; /* allocate RAM */ - memory_region_init_ram(ram, "fulong2e.ram", ram_size); + memory_region_init_ram(ram, NULL, "fulong2e.ram", ram_size); vmstate_register_ram_global(ram); - memory_region_init_ram(bios, "fulong2e.bios", bios_size); + memory_region_init_ram(bios, NULL, "fulong2e.bios", bios_size); vmstate_register_ram_global(bios); memory_region_set_readonly(bios, true); @@ -393,7 +393,7 @@ static void mips_fulong2e_init(QEMUMachineInitArgs *args) /* Sound card */ audio_init(pci_bus); /* Network card */ - network_init(); + network_init(pci_bus); } static QEMUMachine mips_fulong2e_machine = { diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c index 2ad0c0b41..31e138b05 100644 --- a/hw/mips/mips_jazz.c +++ b/hw/mips/mips_jazz.c @@ -99,10 +99,10 @@ static const MemoryRegionOps dma_dummy_ops = { static void cpu_request_exit(void *opaque, int irq, int level) { - CPUMIPSState *env = cpu_single_env; + CPUState *cpu = current_cpu; - if (env && level) { - cpu_exit(CPU(mips_env_get_cpu(env))); + if (cpu && level) { + cpu_exit(cpu); } } @@ -152,14 +152,14 @@ static void mips_jazz_init(MemoryRegion *address_space, qemu_register_reset(main_cpu_reset, cpu); /* allocate RAM */ - memory_region_init_ram(ram, "mips_jazz.ram", ram_size); + memory_region_init_ram(ram, NULL, "mips_jazz.ram", ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(address_space, 0, ram); - memory_region_init_ram(bios, "mips_jazz.bios", MAGNUM_BIOS_SIZE); + memory_region_init_ram(bios, NULL, "mips_jazz.bios", MAGNUM_BIOS_SIZE); vmstate_register_ram_global(bios); memory_region_set_readonly(bios, true); - memory_region_init_alias(bios2, "mips_jazz.bios", bios, + memory_region_init_alias(bios2, NULL, "mips_jazz.bios", bios, 0, MAGNUM_BIOS_SIZE); memory_region_add_subregion(address_space, 0x1fc00000LL, bios); memory_region_add_subregion(address_space, 0xfff00000LL, bios2); @@ -188,7 +188,7 @@ static void mips_jazz_init(MemoryRegion *address_space, /* Chipset */ rc4030_opaque = rc4030_init(env->irq[6], env->irq[3], &rc4030, &dmas, address_space); - memory_region_init_io(dma_dummy, &dma_dummy_ops, NULL, "dummy_dma", 0x1000); + memory_region_init_io(dma_dummy, NULL, &dma_dummy_ops, NULL, "dummy_dma", 0x1000); memory_region_add_subregion(address_space, 0x8000d000, dma_dummy); /* ISA devices */ @@ -216,7 +216,7 @@ static void mips_jazz_init(MemoryRegion *address_space, { /* Simple ROM, so user doesn't have to provide one */ MemoryRegion *rom_mr = g_new(MemoryRegion, 1); - memory_region_init_ram(rom_mr, "g364fb.rom", 0x80000); + memory_region_init_ram(rom_mr, NULL, "g364fb.rom", 0x80000); vmstate_register_ram_global(rom_mr); memory_region_set_readonly(rom_mr, true); uint8_t *rom = memory_region_get_ram_ptr(rom_mr); @@ -266,7 +266,7 @@ static void mips_jazz_init(MemoryRegion *address_space, /* Real time clock */ rtc_init(isa_bus, 1980, NULL); - memory_region_init_io(rtc, &rtc_ops, NULL, "rtc", 0x1000); + memory_region_init_io(rtc, NULL, &rtc_ops, NULL, "rtc", 0x1000); memory_region_add_subregion(address_space, 0x80004000, rtc); /* Keyboard (i8042) */ diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index 8a4459d0b..de87241e9 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -446,11 +446,11 @@ static MaltaFPGAState *malta_fpga_init(MemoryRegion *address_space, s = (MaltaFPGAState *)g_malloc0(sizeof(MaltaFPGAState)); - memory_region_init_io(&s->iomem, &malta_fpga_ops, s, + memory_region_init_io(&s->iomem, NULL, &malta_fpga_ops, s, "malta-fpga", 0x100000); - memory_region_init_alias(&s->iomem_lo, "malta-fpga", + memory_region_init_alias(&s->iomem_lo, NULL, "malta-fpga", &s->iomem, 0, 0x900); - memory_region_init_alias(&s->iomem_hi, "malta-fpga", + memory_region_init_alias(&s->iomem_hi, NULL, "malta-fpga", &s->iomem, 0xa00, 0x10000-0xa00); memory_region_add_subregion(address_space, base, &s->iomem_lo); @@ -468,7 +468,7 @@ static MaltaFPGAState *malta_fpga_init(MemoryRegion *address_space, } /* Network support */ -static void network_init(void) +static void network_init(PCIBus *pci_bus) { int i; @@ -480,7 +480,7 @@ static void network_init(void) /* The malta board has a PCNet card using PCI SLOT 11 */ default_devaddr = "0b"; - pci_nic_init_nofail(nd, "pcnet", default_devaddr); + pci_nic_init_nofail(nd, pci_bus, "pcnet", default_devaddr); } } @@ -770,10 +770,10 @@ static void main_cpu_reset(void *opaque) static void cpu_request_exit(void *opaque, int irq, int level) { - CPUMIPSState *env = cpu_single_env; + CPUState *cpu = current_cpu; - if (env && level) { - cpu_exit(CPU(mips_env_get_cpu(env))); + if (cpu && level) { + cpu_exit(cpu); } } @@ -844,7 +844,8 @@ void mips_malta_init(QEMUMachineInitArgs *args) cpu_mips_clock_init(env); qemu_register_reset(main_cpu_reset, cpu); } - env = first_cpu; + cpu = MIPS_CPU(first_cpu); + env = &cpu->env; /* allocate RAM */ if (ram_size > (256 << 20)) { @@ -853,7 +854,7 @@ void mips_malta_init(QEMUMachineInitArgs *args) ((unsigned int)ram_size / (1 << 20))); exit(1); } - memory_region_init_ram(ram, "mips_malta.ram", ram_size); + memory_region_init_ram(ram, NULL, "mips_malta.ram", ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(system_memory, 0, ram); @@ -927,7 +928,7 @@ void mips_malta_init(QEMUMachineInitArgs *args) } /* Map the BIOS at a 2nd physical location, as on the real board. */ - memory_region_init_alias(bios_alias, "bios.1fc", bios, 0, BIOS_SIZE); + memory_region_init_alias(bios_alias, NULL, "bios.1fc", bios, 0, BIOS_SIZE); memory_region_add_subregion(system_memory, RESET_ADDRESS, bios_alias); /* Board ID = 0x420 (Malta Board with CoreLV) @@ -985,7 +986,7 @@ void mips_malta_init(QEMUMachineInitArgs *args) fdctrl_init_isa(isa_bus, fd); /* Network card */ - network_init(); + network_init(pci_bus); /* Optional PCI video card */ pci_vga_init(pci_bus); diff --git a/hw/mips/mips_mipssim.c b/hw/mips/mips_mipssim.c index d1681ec2f..a10cf13a9 100644 --- a/hw/mips/mips_mipssim.c +++ b/hw/mips/mips_mipssim.c @@ -168,9 +168,9 @@ mips_mipssim_init(QEMUMachineInitArgs *args) qemu_register_reset(main_cpu_reset, reset_info); /* Allocate RAM. */ - memory_region_init_ram(ram, "mips_mipssim.ram", ram_size); + memory_region_init_ram(ram, NULL, "mips_mipssim.ram", ram_size); vmstate_register_ram_global(ram); - memory_region_init_ram(bios, "mips_mipssim.bios", BIOS_SIZE); + memory_region_init_ram(bios, NULL, "mips_mipssim.bios", BIOS_SIZE); vmstate_register_ram_global(bios); memory_region_set_readonly(bios, true); diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c index 4646ab6db..22beb0a67 100644 --- a/hw/mips/mips_r4k.c +++ b/hw/mips/mips_r4k.c @@ -202,12 +202,12 @@ void mips_r4k_init(QEMUMachineInitArgs *args) ((unsigned int)ram_size / (1 << 20))); exit(1); } - memory_region_init_ram(ram, "mips_r4k.ram", ram_size); + memory_region_init_ram(ram, NULL, "mips_r4k.ram", ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(address_space_mem, 0, ram); - memory_region_init_io(iomem, &mips_qemu_ops, NULL, "mips-qemu", 0x10000); + memory_region_init_io(iomem, NULL, &mips_qemu_ops, NULL, "mips-qemu", 0x10000); memory_region_add_subregion(address_space_mem, 0x1fbf0000, iomem); /* Try to load a BIOS image. If this fails, we continue regardless, @@ -229,7 +229,7 @@ void mips_r4k_init(QEMUMachineInitArgs *args) #endif if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) { bios = g_new(MemoryRegion, 1); - memory_region_init_ram(bios, "mips_r4k.bios", BIOS_SIZE); + memory_region_init_ram(bios, NULL, "mips_r4k.bios", BIOS_SIZE); vmstate_register_ram_global(bios); memory_region_set_readonly(bios, true); memory_region_add_subregion(get_system_memory(), 0x1fc00000, bios); diff --git a/hw/misc/a9scu.c b/hw/misc/a9scu.c index 05897c2fa..601b5733f 100644 --- a/hw/misc/a9scu.c +++ b/hw/misc/a9scu.c @@ -119,7 +119,8 @@ static void a9_scu_realize(DeviceState *dev, Error ** errp) A9SCUState *s = A9_SCU(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); - memory_region_init_io(&s->iomem, &a9_scu_ops, s, "a9-scu", 0x100); + memory_region_init_io(&s->iomem, OBJECT(dev), &a9_scu_ops, s, + "a9-scu", 0x100); sysbus_init_mmio(sbd, &s->iomem); } diff --git a/hw/misc/applesmc.c b/hw/misc/applesmc.c index 46f4fbd00..bfafa518e 100644 --- a/hw/misc/applesmc.c +++ b/hw/misc/applesmc.c @@ -73,6 +73,8 @@ typedef struct AppleSMCState AppleSMCState; struct AppleSMCState { ISADevice parent_obj; + MemoryRegion io_data; + MemoryRegion io_cmd; uint32_t iobase; uint8_t cmd; uint8_t status; @@ -86,7 +88,8 @@ struct AppleSMCState { QLIST_HEAD(, AppleSMCData) data_def; }; -static void applesmc_io_cmd_writeb(void *opaque, uint32_t addr, uint32_t val) +static void applesmc_io_cmd_write(void *opaque, hwaddr addr, uint64_t val, + unsigned size) { AppleSMCState *s = opaque; @@ -115,7 +118,8 @@ static void applesmc_fill_data(AppleSMCState *s) } } -static void applesmc_io_data_writeb(void *opaque, uint32_t addr, uint32_t val) +static void applesmc_io_data_write(void *opaque, hwaddr addr, uint64_t val, + unsigned size) { AppleSMCState *s = opaque; @@ -138,7 +142,8 @@ static void applesmc_io_data_writeb(void *opaque, uint32_t addr, uint32_t val) } } -static uint32_t applesmc_io_data_readb(void *opaque, uint32_t addr1) +static uint64_t applesmc_io_data_read(void *opaque, hwaddr addr1, + unsigned size) { AppleSMCState *s = opaque; uint8_t retval = 0; @@ -162,7 +167,7 @@ static uint32_t applesmc_io_data_readb(void *opaque, uint32_t addr1) return retval; } -static uint32_t applesmc_io_cmd_readb(void *opaque, uint32_t addr1) +static uint64_t applesmc_io_cmd_read(void *opaque, hwaddr addr1, unsigned size) { AppleSMCState *s = opaque; @@ -201,18 +206,39 @@ static void qdev_applesmc_isa_reset(DeviceState *dev) applesmc_add_key(s, "MSSD", 1, "\0x3"); } +static const MemoryRegionOps applesmc_data_io_ops = { + .write = applesmc_io_data_write, + .read = applesmc_io_data_read, + .endianness = DEVICE_NATIVE_ENDIAN, + .impl = { + .min_access_size = 1, + .max_access_size = 1, + }, +}; + +static const MemoryRegionOps applesmc_cmd_io_ops = { + .write = applesmc_io_cmd_write, + .read = applesmc_io_cmd_read, + .endianness = DEVICE_NATIVE_ENDIAN, + .impl = { + .min_access_size = 1, + .max_access_size = 1, + }, +}; + static void applesmc_isa_realize(DeviceState *dev, Error **errp) { AppleSMCState *s = APPLE_SMC(dev); - register_ioport_read(s->iobase + APPLESMC_DATA_PORT, 4, 1, - applesmc_io_data_readb, s); - register_ioport_read(s->iobase + APPLESMC_CMD_PORT, 4, 1, - applesmc_io_cmd_readb, s); - register_ioport_write(s->iobase + APPLESMC_DATA_PORT, 4, 1, - applesmc_io_data_writeb, s); - register_ioport_write(s->iobase + APPLESMC_CMD_PORT, 4, 1, - applesmc_io_cmd_writeb, s); + memory_region_init_io(&s->io_data, OBJECT(s), &applesmc_data_io_ops, s, + "applesmc-data", 4); + isa_register_ioport(&s->parent_obj, &s->io_data, + s->iobase + APPLESMC_DATA_PORT); + + memory_region_init_io(&s->io_cmd, OBJECT(s), &applesmc_cmd_io_ops, s, + "applesmc-cmd", 4); + isa_register_ioport(&s->parent_obj, &s->io_cmd, + s->iobase + APPLESMC_CMD_PORT); if (!s->osk || (strlen(s->osk) != 64)) { fprintf(stderr, "WARNING: Using AppleSMC with invalid key\n"); diff --git a/hw/misc/arm_l2x0.c b/hw/misc/arm_l2x0.c index eb4427d9c..3d6acee69 100644 --- a/hw/misc/arm_l2x0.c +++ b/hw/misc/arm_l2x0.c @@ -157,7 +157,8 @@ static int l2x0_priv_init(SysBusDevice *dev) { l2x0_state *s = FROM_SYSBUS(l2x0_state, dev); - memory_region_init_io(&s->iomem, &l2x0_mem_ops, s, "l2x0_cc", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(dev), &l2x0_mem_ops, s, + "l2x0_cc", 0x1000); sysbus_init_mmio(dev, &s->iomem); return 0; } diff --git a/hw/misc/arm_sysctl.c b/hw/misc/arm_sysctl.c index c8b55a834..5906ae586 100644 --- a/hw/misc/arm_sysctl.c +++ b/hw/misc/arm_sysctl.c @@ -589,7 +589,8 @@ static void arm_sysctl_init(Object *obj) SysBusDevice *sd = SYS_BUS_DEVICE(obj); arm_sysctl_state *s = FROM_SYSBUS(arm_sysctl_state, sd); - memory_region_init_io(&s->iomem, &arm_sysctl_ops, s, "arm-sysctl", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(dev), &arm_sysctl_ops, s, + "arm-sysctl", 0x1000); sysbus_init_mmio(sd, &s->iomem); qdev_init_gpio_in(dev, arm_sysctl_gpio_set, 2); qdev_init_gpio_out(dev, &s->pl110_mux_ctrl, 1); diff --git a/hw/misc/debugexit.c b/hw/misc/debugexit.c index ee254e46d..d754cf1f2 100644 --- a/hw/misc/debugexit.c +++ b/hw/misc/debugexit.c @@ -40,7 +40,7 @@ static void debug_exit_realizefn(DeviceState *d, Error **errp) ISADevice *dev = ISA_DEVICE(d); ISADebugExitState *isa = ISA_DEBUG_EXIT_DEVICE(d); - memory_region_init_io(&isa->io, &debug_exit_ops, isa, + memory_region_init_io(&isa->io, OBJECT(dev), &debug_exit_ops, isa, TYPE_ISA_DEBUG_EXIT_DEVICE, isa->iosize); memory_region_add_subregion(isa_address_space_io(dev), isa->iobase, &isa->io); diff --git a/hw/misc/eccmemctl.c b/hw/misc/eccmemctl.c index 6f4a407cb..3de9675f6 100644 --- a/hw/misc/eccmemctl.c +++ b/hw/misc/eccmemctl.c @@ -296,11 +296,11 @@ static int ecc_init1(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq); s->regs[0] = s->version; - memory_region_init_io(&s->iomem, &ecc_mem_ops, s, "ecc", ECC_SIZE); + memory_region_init_io(&s->iomem, OBJECT(dev), &ecc_mem_ops, s, "ecc", ECC_SIZE); sysbus_init_mmio(dev, &s->iomem); if (s->version == ECC_MCC) { // SS-600MP only - memory_region_init_io(&s->iomem_diag, &ecc_diag_mem_ops, s, + memory_region_init_io(&s->iomem_diag, OBJECT(dev), &ecc_diag_mem_ops, s, "ecc.diag", ECC_DIAG_SIZE); sysbus_init_mmio(dev, &s->iomem_diag); } diff --git a/hw/misc/exynos4210_pmu.c b/hw/misc/exynos4210_pmu.c index ba5aa8d0e..28395bae4 100644 --- a/hw/misc/exynos4210_pmu.c +++ b/hw/misc/exynos4210_pmu.c @@ -458,8 +458,8 @@ static int exynos4210_pmu_init(SysBusDevice *dev) Exynos4210PmuState *s = FROM_SYSBUS(Exynos4210PmuState, dev); /* memory mapping */ - memory_region_init_io(&s->iomem, &exynos4210_pmu_ops, s, "exynos4210.pmu", - EXYNOS4210_PMU_REGS_MEM_SIZE); + memory_region_init_io(&s->iomem, OBJECT(dev), &exynos4210_pmu_ops, s, + "exynos4210.pmu", EXYNOS4210_PMU_REGS_MEM_SIZE); sysbus_init_mmio(dev, &s->iomem); return 0; } diff --git a/hw/misc/imx_ccm.c b/hw/misc/imx_ccm.c index 427ce5cd1..816d5e833 100644 --- a/hw/misc/imx_ccm.c +++ b/hw/misc/imx_ccm.c @@ -281,7 +281,8 @@ static int imx_ccm_init(SysBusDevice *dev) { IMXCCMState *s = FROM_SYSBUS(typeof(*s), dev); - memory_region_init_io(&s->iomem, &imx_ccm_ops, s, "imx_ccm", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(dev), &imx_ccm_ops, s, + "imx_ccm", 0x1000); sysbus_init_mmio(dev, &s->iomem); return 0; diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c index 5658f733f..3594b8425 100644 --- a/hw/misc/ivshmem.c +++ b/hw/misc/ivshmem.c @@ -339,7 +339,7 @@ static void create_shared_memory_BAR(IVShmemState *s, int fd) { ptr = mmap(0, s->ivshmem_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); - memory_region_init_ram_ptr(&s->ivshmem, "ivshmem.bar2", + memory_region_init_ram_ptr(&s->ivshmem, OBJECT(s), "ivshmem.bar2", s->ivshmem_size, ptr); vmstate_register_ram(&s->ivshmem, &s->dev.qdev); memory_region_add_subregion(&s->bar, 0, &s->ivshmem); @@ -467,7 +467,7 @@ static void ivshmem_read(void *opaque, const uint8_t * buf, int flags) /* mmap the region and map into the BAR2 */ map_ptr = mmap(0, s->ivshmem_size, PROT_READ|PROT_WRITE, MAP_SHARED, incoming_fd, 0); - memory_region_init_ram_ptr(&s->ivshmem, + memory_region_init_ram_ptr(&s->ivshmem, OBJECT(s), "ivshmem.bar2", s->ivshmem_size, map_ptr); vmstate_register_ram(&s->ivshmem, &s->dev.qdev); @@ -685,14 +685,14 @@ static int pci_ivshmem_init(PCIDevice *dev) s->shm_fd = 0; - memory_region_init_io(&s->ivshmem_mmio, &ivshmem_mmio_ops, s, + memory_region_init_io(&s->ivshmem_mmio, OBJECT(s), &ivshmem_mmio_ops, s, "ivshmem-mmio", IVSHMEM_REG_BAR_SIZE); /* region for registers*/ pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->ivshmem_mmio); - memory_region_init(&s->bar, "ivshmem-bar2-container", s->ivshmem_size); + memory_region_init(&s->bar, OBJECT(s), "ivshmem-bar2-container", s->ivshmem_size); s->ivshmem_attr = PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_PREFETCH; if (s->ivshmem_64bit) { diff --git a/hw/misc/lm32_sys.c b/hw/misc/lm32_sys.c index aeaf2b7b7..060a5bf9b 100644 --- a/hw/misc/lm32_sys.c +++ b/hw/misc/lm32_sys.c @@ -117,7 +117,8 @@ static int lm32_sys_init(SysBusDevice *dev) { LM32SysState *s = FROM_SYSBUS(typeof(*s), dev); - memory_region_init_io(&s->iomem, &sys_ops , s, "sys", R_MAX * 4); + memory_region_init_io(&s->iomem, OBJECT(dev), &sys_ops , s, + "sys", R_MAX * 4); sysbus_init_mmio(dev, &s->iomem); /* Note: This device is not created in the board initialization, diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c index f797796a3..c0fd7da11 100644 --- a/hw/misc/macio/cuda.c +++ b/hw/misc/macio/cuda.c @@ -703,7 +703,7 @@ static void cuda_initfn(Object *obj) CUDAState *s = CUDA(obj); int i; - memory_region_init_io(&s->mem, &cuda_ops, s, "cuda", 0x2000); + memory_region_init_io(&s->mem, NULL, &cuda_ops, s, "cuda", 0x2000); sysbus_init_mmio(d, &s->mem); sysbus_init_irq(d, &s->irq); diff --git a/hw/misc/macio/mac_dbdma.c b/hw/misc/macio/mac_dbdma.c index 2fc7f87bb..f47a73618 100644 --- a/hw/misc/macio/mac_dbdma.c +++ b/hw/misc/macio/mac_dbdma.c @@ -54,122 +54,10 @@ /* */ -/* - * DBDMA control/status registers. All little-endian. - */ - -#define DBDMA_CONTROL 0x00 -#define DBDMA_STATUS 0x01 -#define DBDMA_CMDPTR_HI 0x02 -#define DBDMA_CMDPTR_LO 0x03 -#define DBDMA_INTR_SEL 0x04 -#define DBDMA_BRANCH_SEL 0x05 -#define DBDMA_WAIT_SEL 0x06 -#define DBDMA_XFER_MODE 0x07 -#define DBDMA_DATA2PTR_HI 0x08 -#define DBDMA_DATA2PTR_LO 0x09 -#define DBDMA_RES1 0x0A -#define DBDMA_ADDRESS_HI 0x0B -#define DBDMA_BRANCH_ADDR_HI 0x0C -#define DBDMA_RES2 0x0D -#define DBDMA_RES3 0x0E -#define DBDMA_RES4 0x0F - -#define DBDMA_REGS 16 -#define DBDMA_SIZE (DBDMA_REGS * sizeof(uint32_t)) - -#define DBDMA_CHANNEL_SHIFT 7 -#define DBDMA_CHANNEL_SIZE (1 << DBDMA_CHANNEL_SHIFT) - -#define DBDMA_CHANNELS (0x1000 >> DBDMA_CHANNEL_SHIFT) - -/* Bits in control and status registers */ - -#define RUN 0x8000 -#define PAUSE 0x4000 -#define FLUSH 0x2000 -#define WAKE 0x1000 -#define DEAD 0x0800 -#define ACTIVE 0x0400 -#define BT 0x0100 -#define DEVSTAT 0x00ff - -/* - * DBDMA command structure. These fields are all little-endian! - */ - -typedef struct dbdma_cmd { - uint16_t req_count; /* requested byte transfer count */ - uint16_t command; /* command word (has bit-fields) */ - uint32_t phy_addr; /* physical data address */ - uint32_t cmd_dep; /* command-dependent field */ - uint16_t res_count; /* residual count after completion */ - uint16_t xfer_status; /* transfer status */ -} dbdma_cmd; - -/* DBDMA command values in command field */ - -#define COMMAND_MASK 0xf000 -#define OUTPUT_MORE 0x0000 /* transfer memory data to stream */ -#define OUTPUT_LAST 0x1000 /* ditto followed by end marker */ -#define INPUT_MORE 0x2000 /* transfer stream data to memory */ -#define INPUT_LAST 0x3000 /* ditto, expect end marker */ -#define STORE_WORD 0x4000 /* write word (4 bytes) to device reg */ -#define LOAD_WORD 0x5000 /* read word (4 bytes) from device reg */ -#define DBDMA_NOP 0x6000 /* do nothing */ -#define DBDMA_STOP 0x7000 /* suspend processing */ - -/* Key values in command field */ - -#define KEY_MASK 0x0700 -#define KEY_STREAM0 0x0000 /* usual data stream */ -#define KEY_STREAM1 0x0100 /* control/status stream */ -#define KEY_STREAM2 0x0200 /* device-dependent stream */ -#define KEY_STREAM3 0x0300 /* device-dependent stream */ -#define KEY_STREAM4 0x0400 /* reserved */ -#define KEY_REGS 0x0500 /* device register space */ -#define KEY_SYSTEM 0x0600 /* system memory-mapped space */ -#define KEY_DEVICE 0x0700 /* device memory-mapped space */ - -/* Interrupt control values in command field */ - -#define INTR_MASK 0x0030 -#define INTR_NEVER 0x0000 /* don't interrupt */ -#define INTR_IFSET 0x0010 /* intr if condition bit is 1 */ -#define INTR_IFCLR 0x0020 /* intr if condition bit is 0 */ -#define INTR_ALWAYS 0x0030 /* always interrupt */ - -/* Branch control values in command field */ - -#define BR_MASK 0x000c -#define BR_NEVER 0x0000 /* don't branch */ -#define BR_IFSET 0x0004 /* branch if condition bit is 1 */ -#define BR_IFCLR 0x0008 /* branch if condition bit is 0 */ -#define BR_ALWAYS 0x000c /* always branch */ - -/* Wait control values in command field */ - -#define WAIT_MASK 0x0003 -#define WAIT_NEVER 0x0000 /* don't wait */ -#define WAIT_IFSET 0x0001 /* wait if condition bit is 1 */ -#define WAIT_IFCLR 0x0002 /* wait if condition bit is 0 */ -#define WAIT_ALWAYS 0x0003 /* always wait */ - -typedef struct DBDMA_channel { - int channel; - uint32_t regs[DBDMA_REGS]; - qemu_irq irq; - DBDMA_io io; - DBDMA_rw rw; - DBDMA_flush flush; - dbdma_cmd current; - int processing; -} DBDMA_channel; - -typedef struct { - MemoryRegion mem; - DBDMA_channel channels[DBDMA_CHANNELS]; -} DBDMAState; +static DBDMAState *dbdma_from_ch(DBDMA_channel *ch) +{ + return container_of(ch, DBDMAState, channels[ch->channel]); +} #ifdef DEBUG_DBDMA static void dump_dbdma_cmd(dbdma_cmd *cmd) @@ -224,7 +112,7 @@ static void conditional_interrupt(DBDMA_channel *ch) uint32_t status; int cond; - DBDMA_DPRINTF("conditional_interrupt\n"); + DBDMA_DPRINTF("%s\n", __func__); intr = le16_to_cpu(current->command) & INTR_MASK; @@ -233,6 +121,7 @@ static void conditional_interrupt(DBDMA_channel *ch) return; case INTR_ALWAYS: /* always interrupt */ qemu_irq_raise(ch->irq); + DBDMA_DPRINTF("%s: raise\n", __func__); return; } @@ -245,12 +134,16 @@ static void conditional_interrupt(DBDMA_channel *ch) switch(intr) { case INTR_IFSET: /* intr if condition bit is 1 */ - if (cond) + if (cond) { qemu_irq_raise(ch->irq); + DBDMA_DPRINTF("%s: raise\n", __func__); + } return; case INTR_IFCLR: /* intr if condition bit is 0 */ - if (!cond) + if (!cond) { qemu_irq_raise(ch->irq); + DBDMA_DPRINTF("%s: raise\n", __func__); + } return; } } @@ -360,7 +253,6 @@ static void conditional_branch(DBDMA_channel *ch) } } -static QEMUBH *dbdma_bh; static void channel_run(DBDMA_channel *ch); static void dbdma_end(DBDMA_io *io) @@ -368,6 +260,8 @@ static void dbdma_end(DBDMA_io *io) DBDMA_channel *ch = io->channel; dbdma_cmd *current = &ch->current; + DBDMA_DPRINTF("%s\n", __func__); + if (conditional_wait(ch)) goto wait; @@ -381,7 +275,9 @@ static void dbdma_end(DBDMA_io *io) conditional_branch(ch); wait: - ch->processing = 0; + /* Indicate that we're ready for a new DMA round */ + ch->io.processing = false; + if ((ch->regs[DBDMA_STATUS] & RUN) && (ch->regs[DBDMA_STATUS] & ACTIVE)) channel_run(ch); @@ -407,7 +303,7 @@ static void start_output(DBDMA_channel *ch, int key, uint32_t addr, ch->io.is_last = is_last; ch->io.dma_end = dbdma_end; ch->io.is_dma_out = 1; - ch->processing = 1; + ch->io.processing = true; if (ch->rw) { ch->rw(&ch->io); } @@ -422,6 +318,7 @@ static void start_input(DBDMA_channel *ch, int key, uint32_t addr, * are not implemented in the mac-io chip */ + DBDMA_DPRINTF("addr 0x%x key 0x%x\n", addr, key); if (!addr || key > KEY_STREAM3) { kill_channel(ch); return; @@ -432,7 +329,7 @@ static void start_input(DBDMA_channel *ch, int key, uint32_t addr, ch->io.is_last = is_last; ch->io.dma_end = dbdma_end; ch->io.is_dma_out = 0; - ch->processing = 1; + ch->io.processing = true; if (ch->rw) { ch->rw(&ch->io); } @@ -474,7 +371,7 @@ static void load_word(DBDMA_channel *ch, int key, uint32_t addr, next(ch); wait: - qemu_bh_schedule(dbdma_bh); + DBDMA_kick(dbdma_from_ch(ch)); } static void store_word(DBDMA_channel *ch, int key, uint32_t addr, @@ -512,7 +409,7 @@ static void store_word(DBDMA_channel *ch, int key, uint32_t addr, next(ch); wait: - qemu_bh_schedule(dbdma_bh); + DBDMA_kick(dbdma_from_ch(ch)); } static void nop(DBDMA_channel *ch) @@ -529,7 +426,7 @@ static void nop(DBDMA_channel *ch) conditional_branch(ch); wait: - qemu_bh_schedule(dbdma_bh); + DBDMA_kick(dbdma_from_ch(ch)); } static void stop(DBDMA_channel *ch) @@ -558,11 +455,11 @@ static void channel_run(DBDMA_channel *ch) switch (cmd) { case DBDMA_NOP: nop(ch); - return; + return; case DBDMA_STOP: stop(ch); - return; + return; } key = le16_to_cpu(current->command) & 0x0700; @@ -578,19 +475,19 @@ static void channel_run(DBDMA_channel *ch) switch (cmd) { case OUTPUT_MORE: start_output(ch, key, phy_addr, req_count, 0); - return; + return; case OUTPUT_LAST: start_output(ch, key, phy_addr, req_count, 1); - return; + return; case INPUT_MORE: start_input(ch, key, phy_addr, req_count, 0); - return; + return; case INPUT_LAST: start_input(ch, key, phy_addr, req_count, 1); - return; + return; } if (key < KEY_REGS) { @@ -615,11 +512,11 @@ static void channel_run(DBDMA_channel *ch) switch (cmd) { case LOAD_WORD: load_word(ch, key, phy_addr, req_count); - return; + return; case STORE_WORD: store_word(ch, key, phy_addr, req_count); - return; + return; } } @@ -630,7 +527,7 @@ static void DBDMA_run(DBDMAState *s) for (channel = 0; channel < DBDMA_CHANNELS; channel++) { DBDMA_channel *ch = &s->channels[channel]; uint32_t status = ch->regs[DBDMA_STATUS]; - if (!ch->processing && (status & RUN) && (status & ACTIVE)) { + if (!ch->io.processing && (status & RUN) && (status & ACTIVE)) { channel_run(ch); } } @@ -645,6 +542,11 @@ static void DBDMA_run_bh(void *opaque) DBDMA_run(s); } +void DBDMA_kick(DBDMAState *dbdma) +{ + qemu_bh_schedule(dbdma->bh); +} + void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq, DBDMA_rw rw, DBDMA_flush flush, void *opaque) @@ -698,10 +600,12 @@ dbdma_control_write(DBDMA_channel *ch) ch->regs[DBDMA_STATUS] = status; - if (status & ACTIVE) - qemu_bh_schedule(dbdma_bh); - if ((status & FLUSH) && ch->flush) + if (status & ACTIVE) { + DBDMA_kick(dbdma_from_ch(ch)); + } + if ((status & FLUSH) && ch->flush) { ch->flush(&ch->io); + } } static void dbdma_write(void *opaque, hwaddr addr, @@ -712,15 +616,16 @@ static void dbdma_write(void *opaque, hwaddr addr, DBDMA_channel *ch = &s->channels[channel]; int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2; - DBDMA_DPRINTF("writel 0x" TARGET_FMT_plx " <= 0x%08x\n", addr, value); + DBDMA_DPRINTF("writel 0x" TARGET_FMT_plx " <= 0x%08"PRIx64"\n", + addr, value); DBDMA_DPRINTF("channel 0x%x reg 0x%x\n", (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg); - /* cmdptr cannot be modified if channel is RUN or ACTIVE */ + /* cmdptr cannot be modified if channel is ACTIVE */ - if (reg == DBDMA_CMDPTR_LO && - (ch->regs[DBDMA_STATUS] & (RUN | ACTIVE))) - return; + if (reg == DBDMA_CMDPTR_LO && (ch->regs[DBDMA_STATUS] & ACTIVE)) { + return; + } ch->regs[reg] = value; @@ -848,12 +753,12 @@ void* DBDMA_init (MemoryRegion **dbdma_mem) s = g_malloc0(sizeof(DBDMAState)); - memory_region_init_io(&s->mem, &dbdma_ops, s, "dbdma", 0x1000); + memory_region_init_io(&s->mem, NULL, &dbdma_ops, s, "dbdma", 0x1000); *dbdma_mem = &s->mem; vmstate_register(NULL, -1, &vmstate_dbdma, s); qemu_register_reset(dbdma_reset, s); - dbdma_bh = qemu_bh_new(DBDMA_run_bh, s); + s->bh = qemu_bh_new(DBDMA_run_bh, s); return s; } diff --git a/hw/misc/macio/macio.c b/hw/misc/macio/macio.c index fd4c8e5f9..c0d0bf728 100644 --- a/hw/misc/macio/macio.c +++ b/hw/misc/macio/macio.c @@ -52,10 +52,10 @@ typedef struct OldWorldMacIOState { MacIOState parent_obj; /*< public >*/ - qemu_irq irqs[3]; + qemu_irq irqs[5]; MacIONVRAMState nvram; - MACIOIDEState ide; + MACIOIDEState ide[2]; } OldWorldMacIOState; #define NEWWORLD_MACIO(obj) \ @@ -104,11 +104,11 @@ static void macio_escc_legacy_setup(MacIOState *macio_state) 0xF0, 0xE0, }; - memory_region_init(escc_legacy, "escc-legacy", 256); + memory_region_init(escc_legacy, NULL, "escc-legacy", 256); for (i = 0; i < ARRAY_SIZE(maps); i += 2) { MemoryRegion *port = g_new(MemoryRegion, 1); - memory_region_init_alias(port, "escc-legacy-port", macio_state->escc_mem, - maps[i+1], 0x2); + memory_region_init_alias(port, NULL, "escc-legacy-port", + macio_state->escc_mem, maps[i+1], 0x2); memory_region_add_subregion(escc_legacy, maps[i], port); } @@ -147,18 +147,32 @@ static int macio_common_initfn(PCIDevice *d) return 0; } +static int macio_initfn_ide(MacIOState *s, MACIOIDEState *ide, qemu_irq irq0, + qemu_irq irq1, int dmaid) +{ + SysBusDevice *sysbus_dev; + + sysbus_dev = SYS_BUS_DEVICE(ide); + sysbus_connect_irq(sysbus_dev, 0, irq0); + sysbus_connect_irq(sysbus_dev, 1, irq1); + macio_ide_register_dma(ide, s->dbdma, dmaid); + return qdev_init(DEVICE(ide)); +} + static int macio_oldworld_initfn(PCIDevice *d) { MacIOState *s = MACIO(d); OldWorldMacIOState *os = OLDWORLD_MACIO(d); SysBusDevice *sysbus_dev; + int i; + int cur_irq = 0; int ret = macio_common_initfn(d); if (ret < 0) { return ret; } sysbus_dev = SYS_BUS_DEVICE(&s->cuda); - sysbus_connect_irq(sysbus_dev, 0, os->irqs[0]); + sysbus_connect_irq(sysbus_dev, 0, os->irqs[cur_irq++]); ret = qdev_init(DEVICE(&os->nvram)); if (ret < 0) { @@ -174,23 +188,39 @@ static int macio_oldworld_initfn(PCIDevice *d) memory_region_add_subregion(&s->bar, 0x00000, s->pic_mem); } - sysbus_dev = SYS_BUS_DEVICE(&os->ide); - sysbus_connect_irq(sysbus_dev, 0, os->irqs[1]); - sysbus_connect_irq(sysbus_dev, 1, os->irqs[2]); - macio_ide_register_dma(&os->ide, s->dbdma, 0x16); - ret = qdev_init(DEVICE(&os->ide)); - if (ret < 0) { - return ret; + /* IDE buses */ + for (i = 0; i < ARRAY_SIZE(os->ide); i++) { + qemu_irq irq0 = os->irqs[cur_irq++]; + qemu_irq irq1 = os->irqs[cur_irq++]; + + ret = macio_initfn_ide(s, &os->ide[i], irq0, irq1, 0x16 + (i * 4)); + if (ret < 0) { + return ret; + } } return 0; } +static void macio_init_ide(MacIOState *s, MACIOIDEState *ide, int index) +{ + gchar *name; + + object_initialize(ide, TYPE_MACIO_IDE); + qdev_set_parent_bus(DEVICE(ide), sysbus_get_default()); + memory_region_add_subregion(&s->bar, 0x1f000 + ((index + 1) * 0x1000), + &ide->mem); + name = g_strdup_printf("ide[%i]", index); + object_property_add_child(OBJECT(s), name, OBJECT(ide), NULL); + g_free(name); +} + static void macio_oldworld_init(Object *obj) { MacIOState *s = MACIO(obj); OldWorldMacIOState *os = OLDWORLD_MACIO(obj); DeviceState *dev; + int i; qdev_init_gpio_out(DEVICE(obj), os->irqs, ARRAY_SIZE(os->irqs)); @@ -199,48 +229,75 @@ static void macio_oldworld_init(Object *obj) qdev_prop_set_uint32(dev, "size", 0x2000); qdev_prop_set_uint32(dev, "it_shift", 4); - object_initialize(&os->ide, TYPE_MACIO_IDE); - qdev_set_parent_bus(DEVICE(&os->ide), sysbus_get_default()); - memory_region_add_subregion(&s->bar, 0x1f000 + (1 * 0x1000), &os->ide.mem); - object_property_add_child(obj, "ide", OBJECT(&os->ide), NULL); + for (i = 0; i < 2; i++) { + macio_init_ide(s, &os->ide[i], i); + } } +static void timer_write(void *opaque, hwaddr addr, uint64_t value, + unsigned size) +{ +} + +static uint64_t timer_read(void *opaque, hwaddr addr, unsigned size) +{ + uint32_t value = 0; + + switch (addr) { + case 0x38: + value = qemu_get_clock_ns(vm_clock); + break; + case 0x3c: + value = qemu_get_clock_ns(vm_clock) >> 32; + break; + } + + return value; +} + +static const MemoryRegionOps timer_ops = { + .read = timer_read, + .write = timer_write, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + static int macio_newworld_initfn(PCIDevice *d) { MacIOState *s = MACIO(d); NewWorldMacIOState *ns = NEWWORLD_MACIO(d); SysBusDevice *sysbus_dev; + MemoryRegion *timer_memory = g_new(MemoryRegion, 1); + int i; + int cur_irq = 0; int ret = macio_common_initfn(d); if (ret < 0) { return ret; } sysbus_dev = SYS_BUS_DEVICE(&s->cuda); - sysbus_connect_irq(sysbus_dev, 0, ns->irqs[0]); + sysbus_connect_irq(sysbus_dev, 0, ns->irqs[cur_irq++]); if (s->pic_mem) { /* OpenPIC */ memory_region_add_subregion(&s->bar, 0x40000, s->pic_mem); } - sysbus_dev = SYS_BUS_DEVICE(&ns->ide[0]); - sysbus_connect_irq(sysbus_dev, 0, ns->irqs[1]); - sysbus_connect_irq(sysbus_dev, 1, ns->irqs[2]); - macio_ide_register_dma(&ns->ide[0], s->dbdma, 0x16); - ret = qdev_init(DEVICE(&ns->ide[0])); - if (ret < 0) { - return ret; - } + /* IDE buses */ + for (i = 0; i < ARRAY_SIZE(ns->ide); i++) { + qemu_irq irq0 = ns->irqs[cur_irq++]; + qemu_irq irq1 = ns->irqs[cur_irq++]; - sysbus_dev = SYS_BUS_DEVICE(&ns->ide[1]); - sysbus_connect_irq(sysbus_dev, 0, ns->irqs[3]); - sysbus_connect_irq(sysbus_dev, 1, ns->irqs[4]); - macio_ide_register_dma(&ns->ide[1], s->dbdma, 0x1a); - ret = qdev_init(DEVICE(&ns->ide[1])); - if (ret < 0) { - return ret; + ret = macio_initfn_ide(s, &ns->ide[i], irq0, irq1, 0x16 + (i * 4)); + if (ret < 0) { + return ret; + } } + /* Timer */ + memory_region_init_io(timer_memory, OBJECT(s), &timer_ops, NULL, "timer", + 0x1000); + memory_region_add_subregion(&s->bar, 0x15000, timer_memory); + return 0; } @@ -249,18 +306,11 @@ static void macio_newworld_init(Object *obj) MacIOState *s = MACIO(obj); NewWorldMacIOState *ns = NEWWORLD_MACIO(obj); int i; - gchar *name; qdev_init_gpio_out(DEVICE(obj), ns->irqs, ARRAY_SIZE(ns->irqs)); for (i = 0; i < 2; i++) { - object_initialize(&ns->ide[i], TYPE_MACIO_IDE); - qdev_set_parent_bus(DEVICE(&ns->ide[i]), sysbus_get_default()); - memory_region_add_subregion(&s->bar, 0x1f000 + ((i + 1) * 0x1000), - &ns->ide[i].mem); - name = g_strdup_printf("ide[%i]", i); - object_property_add_child(obj, name, OBJECT(&ns->ide[i]), NULL); - g_free(name); + macio_init_ide(s, &ns->ide[i], i); } } @@ -269,7 +319,7 @@ static void macio_instance_init(Object *obj) MacIOState *s = MACIO(obj); MemoryRegion *dbdma_mem; - memory_region_init(&s->bar, "macio", 0x80000); + memory_region_init(&s->bar, NULL, "macio", 0x80000); object_initialize(&s->cuda, TYPE_CUDA); qdev_set_parent_bus(DEVICE(&s->cuda), sysbus_get_default()); diff --git a/hw/misc/milkymist-hpdmc.c b/hw/misc/milkymist-hpdmc.c index d922f6ffa..a49888119 100644 --- a/hw/misc/milkymist-hpdmc.c +++ b/hw/misc/milkymist-hpdmc.c @@ -127,7 +127,7 @@ static int milkymist_hpdmc_init(SysBusDevice *dev) { MilkymistHpdmcState *s = FROM_SYSBUS(typeof(*s), dev); - memory_region_init_io(&s->regs_region, &hpdmc_mmio_ops, s, + memory_region_init_io(&s->regs_region, OBJECT(dev), &hpdmc_mmio_ops, s, "milkymist-hpdmc", R_MAX * 4); sysbus_init_mmio(dev, &s->regs_region); diff --git a/hw/misc/milkymist-pfpu.c b/hw/misc/milkymist-pfpu.c index fe1b03955..2b64ee77d 100644 --- a/hw/misc/milkymist-pfpu.c +++ b/hw/misc/milkymist-pfpu.c @@ -497,7 +497,7 @@ static int milkymist_pfpu_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq); - memory_region_init_io(&s->regs_region, &pfpu_mmio_ops, s, + memory_region_init_io(&s->regs_region, OBJECT(dev), &pfpu_mmio_ops, s, "milkymist-pfpu", MICROCODE_END * 4); sysbus_init_mmio(dev, &s->regs_region); diff --git a/hw/misc/mst_fpga.c b/hw/misc/mst_fpga.c index 1dd15054d..604be5eaf 100644 --- a/hw/misc/mst_fpga.c +++ b/hw/misc/mst_fpga.c @@ -208,7 +208,7 @@ static int mst_fpga_init(SysBusDevice *dev) /* alloc the external 16 irqs */ qdev_init_gpio_in(&dev->qdev, mst_fpga_set_irq, MST_NUM_IRQS); - memory_region_init_io(&s->iomem, &mst_fpga_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &mst_fpga_ops, s, "fpga", 0x00100000); sysbus_init_mmio(dev, &s->iomem); return 0; diff --git a/hw/misc/omap_gpmc.c b/hw/misc/omap_gpmc.c index 91adb66c2..204727412 100644 --- a/hw/misc/omap_gpmc.c +++ b/hw/misc/omap_gpmc.c @@ -413,7 +413,7 @@ static void omap_gpmc_cs_map(struct omap_gpmc_s *s, int cs) * constant), the mask should cause wrapping of the address space, so * that the same memory becomes accessible at every size bytes * starting from base. */ - memory_region_init(&f->container, "omap-gpmc-file", size); + memory_region_init(&f->container, NULL, "omap-gpmc-file", size); memory_region_add_subregion(&f->container, 0, omap_gpmc_cs_memregion(s, cs)); memory_region_add_subregion(get_system_memory(), base, @@ -826,7 +826,7 @@ struct omap_gpmc_s *omap_gpmc_init(struct omap_mpu_state_s *mpu, struct omap_gpmc_s *s = (struct omap_gpmc_s *) g_malloc0(sizeof(struct omap_gpmc_s)); - memory_region_init_io(&s->iomem, &omap_gpmc_ops, s, "omap-gpmc", 0x1000); + memory_region_init_io(&s->iomem, NULL, &omap_gpmc_ops, s, "omap-gpmc", 0x1000); memory_region_add_subregion(get_system_memory(), base, &s->iomem); s->irq = irq; @@ -843,14 +843,14 @@ struct omap_gpmc_s *omap_gpmc_init(struct omap_mpu_state_s *mpu, * guest-requested size. */ for (cs = 0; cs < 8; cs++) { - memory_region_init_io(&s->cs_file[cs].nandiomem, + memory_region_init_io(&s->cs_file[cs].nandiomem, NULL, &omap_nand_ops, &s->cs_file[cs], "omap-nand", 256 * 1024 * 1024); } - memory_region_init_io(&s->prefetch.iomem, &omap_prefetch_ops, s, + memory_region_init_io(&s->prefetch.iomem, NULL, &omap_prefetch_ops, s, "omap-gpmc-prefetch", 256 * 1024 * 1024); return s; } diff --git a/hw/misc/omap_l4.c b/hw/misc/omap_l4.c index ac8251f73..f2372500c 100644 --- a/hw/misc/omap_l4.c +++ b/hw/misc/omap_l4.c @@ -136,7 +136,7 @@ struct omap_target_agent_s *omap_l4ta_get(struct omap_l4_s *bus, ta->status = 0x00000000; ta->control = 0x00000200; /* XXX 01000200 for L4TAO */ - memory_region_init_io(&ta->iomem, &omap_l4ta_ops, ta, "omap.l4ta", + memory_region_init_io(&ta->iomem, NULL, &omap_l4ta_ops, ta, "omap.l4ta", omap_l4_region_size(ta, info->ta_region)); omap_l4_attach(ta, info->ta_region, &ta->iomem); diff --git a/hw/misc/omap_sdrc.c b/hw/misc/omap_sdrc.c index e38b57105..ed62caf03 100644 --- a/hw/misc/omap_sdrc.c +++ b/hw/misc/omap_sdrc.c @@ -161,7 +161,7 @@ struct omap_sdrc_s *omap_sdrc_init(MemoryRegion *sysmem, omap_sdrc_reset(s); - memory_region_init_io(&s->iomem, &omap_sdrc_ops, s, "omap.sdrc", 0x1000); + memory_region_init_io(&s->iomem, NULL, &omap_sdrc_ops, s, "omap.sdrc", 0x1000); memory_region_add_subregion(sysmem, base, &s->iomem); return s; diff --git a/hw/misc/omap_tap.c b/hw/misc/omap_tap.c index 99b70d5a7..9d2b71014 100644 --- a/hw/misc/omap_tap.c +++ b/hw/misc/omap_tap.c @@ -110,7 +110,7 @@ static const MemoryRegionOps omap_tap_ops = { void omap_tap_init(struct omap_target_agent_s *ta, struct omap_mpu_state_s *mpu) { - memory_region_init_io(&mpu->tap_iomem, &omap_tap_ops, mpu, "omap.tap", + memory_region_init_io(&mpu->tap_iomem, NULL, &omap_tap_ops, mpu, "omap.tap", omap_l4_region_size(ta, 0)); omap_l4_attach(ta, 0, &mpu->tap_iomem); } diff --git a/hw/misc/pc-testdev.c b/hw/misc/pc-testdev.c index e6707d69d..699a16ffb 100644 --- a/hw/misc/pc-testdev.c +++ b/hw/misc/pc-testdev.c @@ -149,13 +149,13 @@ static void testdev_realizefn(DeviceState *d, Error **errp) MemoryRegion *mem = isa_address_space(isa); MemoryRegion *io = isa_address_space_io(isa); - memory_region_init_io(&dev->ioport, &test_ioport_ops, dev, + memory_region_init_io(&dev->ioport, OBJECT(dev), &test_ioport_ops, dev, "pc-testdev-ioport", 4); - memory_region_init_io(&dev->flush, &test_flush_ops, dev, + memory_region_init_io(&dev->flush, OBJECT(dev), &test_flush_ops, dev, "pc-testdev-flush-page", 4); - memory_region_init_io(&dev->irq, &test_irq_ops, dev, + memory_region_init_io(&dev->irq, OBJECT(dev), &test_irq_ops, dev, "pc-testdev-irq-line", 24); - memory_region_init_io(&dev->iomem, &test_iomem_ops, dev, + memory_region_init_io(&dev->iomem, OBJECT(dev), &test_iomem_ops, dev, "pc-testdev-iomem", IOMEM_LEN); memory_region_add_subregion(io, 0xe0, &dev->ioport); diff --git a/hw/misc/pci-testdev.c b/hw/misc/pci-testdev.c index 71ce5a3e0..8b0b73f9c 100644 --- a/hw/misc/pci-testdev.c +++ b/hw/misc/pci-testdev.c @@ -236,9 +236,9 @@ static int pci_testdev_init(PCIDevice *pci_dev) pci_conf[PCI_INTERRUPT_PIN] = 0; /* no interrupt pin */ - memory_region_init_io(&d->mmio, &pci_testdev_mmio_ops, d, + memory_region_init_io(&d->mmio, OBJECT(d), &pci_testdev_mmio_ops, d, "pci-testdev-mmio", IOTEST_MEMSIZE * 2); - memory_region_init_io(&d->portio, &pci_testdev_pio_ops, d, + memory_region_init_io(&d->portio, OBJECT(d), &pci_testdev_pio_ops, d, "pci-testdev-portio", IOTEST_IOSIZE * 2); pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio); pci_register_bar(&d->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->portio); diff --git a/hw/misc/puv3_pm.c b/hw/misc/puv3_pm.c index 0aacdc2fc..559256001 100644 --- a/hw/misc/puv3_pm.c +++ b/hw/misc/puv3_pm.c @@ -120,7 +120,7 @@ static int puv3_pm_init(SysBusDevice *dev) s->reg_PCGR = 0x0; - memory_region_init_io(&s->iomem, &puv3_pm_ops, s, "puv3_pm", + memory_region_init_io(&s->iomem, OBJECT(s), &puv3_pm_ops, s, "puv3_pm", PUV3_REGS_OFFSET); sysbus_init_mmio(dev, &s->iomem); diff --git a/hw/misc/pvpanic.c b/hw/misc/pvpanic.c index 060099b55..7bb49a574 100644 --- a/hw/misc/pvpanic.c +++ b/hw/misc/pvpanic.c @@ -90,33 +90,36 @@ static void pvpanic_isa_initfn(Object *obj) { PVPanicState *s = ISA_PVPANIC_DEVICE(obj); - memory_region_init_io(&s->io, &pvpanic_ops, s, "pvpanic", 1); + memory_region_init_io(&s->io, OBJECT(s), &pvpanic_ops, s, "pvpanic", 1); } static void pvpanic_isa_realizefn(DeviceState *dev, Error **errp) { ISADevice *d = ISA_DEVICE(dev); PVPanicState *s = ISA_PVPANIC_DEVICE(dev); - static bool port_configured; - FWCfgState *fw_cfg; isa_register_ioport(d, &s->io, s->ioport); +} - if (!port_configured) { - fw_cfg = fw_cfg_find(); - if (fw_cfg) { - fw_cfg_add_file(fw_cfg, "etc/pvpanic-port", - g_memdup(&s->ioport, sizeof(s->ioport)), - sizeof(s->ioport)); - port_configured = true; - } - } +static void pvpanic_fw_cfg(ISADevice *dev, FWCfgState *fw_cfg) +{ + PVPanicState *s = ISA_PVPANIC_DEVICE(dev); + uint16_t *pvpanic_port = g_malloc(sizeof(*pvpanic_port)); + *pvpanic_port = cpu_to_le16(s->ioport); + + fw_cfg_add_file(fw_cfg, "etc/pvpanic-port", pvpanic_port, + sizeof(*pvpanic_port)); } -int pvpanic_init(ISABus *bus) +void pvpanic_init(ISABus *bus) { - isa_create_simple(bus, TYPE_ISA_PVPANIC_DEVICE); - return 0; + ISADevice *dev; + FWCfgState *fw_cfg = fw_cfg_find(); + if (!fw_cfg) { + return; + } + dev = isa_create_simple (bus, TYPE_ISA_PVPANIC_DEVICE); + pvpanic_fw_cfg(dev, fw_cfg); } static Property pvpanic_isa_properties[] = { diff --git a/hw/misc/pxa2xx_pcmcia.c b/hw/misc/pxa2xx_pcmcia.c index 323d45849..ef71a2af7 100644 --- a/hw/misc/pxa2xx_pcmcia.c +++ b/hw/misc/pxa2xx_pcmcia.c @@ -128,7 +128,7 @@ PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem, g_malloc0(sizeof(PXA2xxPCMCIAState)); /* Socket I/O Memory Space */ - memory_region_init_io(&s->iomem, &pxa2xx_pcmcia_io_ops, s, + memory_region_init_io(&s->iomem, NULL, &pxa2xx_pcmcia_io_ops, s, "pxa2xx-pcmcia-io", 0x04000000); memory_region_add_subregion(sysmem, base | 0x00000000, &s->iomem); @@ -136,13 +136,13 @@ PXA2xxPCMCIAState *pxa2xx_pcmcia_init(MemoryRegion *sysmem, /* Then next 64 MB is reserved */ /* Socket Attribute Memory Space */ - memory_region_init_io(&s->attr_iomem, &pxa2xx_pcmcia_attr_ops, s, + memory_region_init_io(&s->attr_iomem, NULL, &pxa2xx_pcmcia_attr_ops, s, "pxa2xx-pcmcia-attribute", 0x04000000); memory_region_add_subregion(sysmem, base | 0x08000000, &s->attr_iomem); /* Socket Common Memory Space */ - memory_region_init_io(&s->common_iomem, &pxa2xx_pcmcia_common_ops, s, + memory_region_init_io(&s->common_iomem, NULL, &pxa2xx_pcmcia_common_ops, s, "pxa2xx-pcmcia-common", 0x04000000); memory_region_add_subregion(sysmem, base | 0x0c000000, &s->common_iomem); diff --git a/hw/misc/slavio_misc.c b/hw/misc/slavio_misc.c index a7a936886..d274fb4a8 100644 --- a/hw/misc/slavio_misc.c +++ b/hw/misc/slavio_misc.c @@ -412,7 +412,7 @@ static int apc_init1(SysBusDevice *dev) sysbus_init_irq(dev, &s->cpu_halt); /* Power management (APC) XXX: not a Slavio device */ - memory_region_init_io(&s->iomem, &apc_mem_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &apc_mem_ops, s, "apc", MISC_SIZE); sysbus_init_mmio(dev, &s->iomem); return 0; @@ -427,39 +427,39 @@ static int slavio_misc_init1(SysBusDevice *dev) /* 8 bit registers */ /* Slavio control */ - memory_region_init_io(&s->cfg_iomem, &slavio_cfg_mem_ops, s, + memory_region_init_io(&s->cfg_iomem, OBJECT(s), &slavio_cfg_mem_ops, s, "configuration", MISC_SIZE); sysbus_init_mmio(dev, &s->cfg_iomem); /* Diagnostics */ - memory_region_init_io(&s->diag_iomem, &slavio_diag_mem_ops, s, + memory_region_init_io(&s->diag_iomem, OBJECT(s), &slavio_diag_mem_ops, s, "diagnostic", MISC_SIZE); sysbus_init_mmio(dev, &s->diag_iomem); /* Modem control */ - memory_region_init_io(&s->mdm_iomem, &slavio_mdm_mem_ops, s, + memory_region_init_io(&s->mdm_iomem, OBJECT(s), &slavio_mdm_mem_ops, s, "modem", MISC_SIZE); sysbus_init_mmio(dev, &s->mdm_iomem); /* 16 bit registers */ /* ss600mp diag LEDs */ - memory_region_init_io(&s->led_iomem, &slavio_led_mem_ops, s, + memory_region_init_io(&s->led_iomem, OBJECT(s), &slavio_led_mem_ops, s, "leds", MISC_SIZE); sysbus_init_mmio(dev, &s->led_iomem); /* 32 bit registers */ /* System control */ - memory_region_init_io(&s->sysctrl_iomem, &slavio_sysctrl_mem_ops, s, + memory_region_init_io(&s->sysctrl_iomem, OBJECT(s), &slavio_sysctrl_mem_ops, s, "system-control", MISC_SIZE); sysbus_init_mmio(dev, &s->sysctrl_iomem); /* AUX 1 (Misc System Functions) */ - memory_region_init_io(&s->aux1_iomem, &slavio_aux1_mem_ops, s, + memory_region_init_io(&s->aux1_iomem, OBJECT(s), &slavio_aux1_mem_ops, s, "misc-system-functions", MISC_SIZE); sysbus_init_mmio(dev, &s->aux1_iomem); /* AUX 2 (Software Powerdown Control) */ - memory_region_init_io(&s->aux2_iomem, &slavio_aux2_mem_ops, s, + memory_region_init_io(&s->aux2_iomem, OBJECT(s), &slavio_aux2_mem_ops, s, "software-powerdown-control", MISC_SIZE); sysbus_init_mmio(dev, &s->aux2_iomem); diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c index 52fb03601..540c377f6 100644 --- a/hw/misc/vfio.c +++ b/hw/misc/vfio.c @@ -1154,7 +1154,7 @@ static void vfio_vga_probe_ati_3c3_quirk(VFIODevice *vdev) quirk->vdev = vdev; quirk->data = (physbar >> 8) & 0xff; - memory_region_init_io(&quirk->mem, &vfio_ati_3c3_quirk, quirk, + memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_ati_3c3_quirk, quirk, "vfio-ati-3c3-quirk", 1); memory_region_add_subregion(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem, 3, &quirk->mem); @@ -1245,7 +1245,7 @@ static void vfio_probe_ati_4010_quirk(VFIODevice *vdev, int nr) quirk = g_malloc0(sizeof(*quirk)); quirk->vdev = vdev; - memory_region_init_io(&quirk->mem, &vfio_ati_4010_quirk, quirk, + memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_ati_4010_quirk, quirk, "vfio-ati-4010-quirk", 8); memory_region_add_subregion_overlap(&vdev->bars[nr].mem, 0, &quirk->mem, 1); @@ -1331,7 +1331,7 @@ static void vfio_probe_ati_f10_quirk(VFIODevice *vdev, int nr) quirk = g_malloc0(sizeof(*quirk)); quirk->vdev = vdev; - memory_region_init_io(&quirk->mem, &vfio_ati_f10_quirk, quirk, + memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_ati_f10_quirk, quirk, "vfio-ati-f10-quirk", 8); memory_region_add_subregion_overlap(&vdev->bars[nr].mem, 0, &quirk->mem, 1); @@ -1451,7 +1451,7 @@ static void vfio_vga_probe_nvidia_3d0_quirk(VFIODevice *vdev) quirk = g_malloc0(sizeof(*quirk)); quirk->vdev = vdev; - memory_region_init_io(&quirk->mem, &vfio_nvidia_3d0_quirk, quirk, + memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_nvidia_3d0_quirk, quirk, "vfio-nvidia-3d0-quirk", 6); memory_region_add_subregion(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem, 0x10, &quirk->mem); @@ -1566,7 +1566,7 @@ static void vfio_probe_nvidia_bar5_window_quirk(VFIODevice *vdev, int nr) quirk = g_malloc0(sizeof(*quirk)); quirk->vdev = vdev; - memory_region_init_io(&quirk->mem, &vfio_nvidia_bar5_window_quirk, quirk, + memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_nvidia_bar5_window_quirk, quirk, "vfio-nvidia-bar5-window-quirk", 16); memory_region_add_subregion_overlap(&vdev->bars[nr].mem, 0, &quirk->mem, 1); @@ -1644,7 +1644,7 @@ static void vfio_probe_nvidia_bar0_88000_quirk(VFIODevice *vdev, int nr) quirk = g_malloc0(sizeof(*quirk)); quirk->vdev = vdev; - memory_region_init_io(&quirk->mem, &vfio_nvidia_bar0_88000_quirk, quirk, + memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_nvidia_bar0_88000_quirk, quirk, "vfio-nvidia-bar0-88000-quirk", TARGET_PAGE_ALIGN(PCIE_CONFIG_SPACE_SIZE)); memory_region_add_subregion_overlap(&vdev->bars[nr].mem, @@ -1723,7 +1723,7 @@ static void vfio_probe_nvidia_bar0_1800_quirk(VFIODevice *vdev, int nr) quirk = g_malloc0(sizeof(*quirk)); quirk->vdev = vdev; - memory_region_init_io(&quirk->mem, &vfio_nvidia_bar0_1800_quirk, quirk, + memory_region_init_io(&quirk->mem, OBJECT(vdev), &vfio_nvidia_bar0_1800_quirk, quirk, "vfio-nvidia-bar0-1800-quirk", TARGET_PAGE_ALIGN(PCI_CONFIG_SPACE_SIZE)); memory_region_add_subregion_overlap(&vdev->bars[nr].mem, @@ -1969,6 +1969,7 @@ static void vfio_listener_region_add(MemoryListener *listener, DPRINTF("region_add %"HWADDR_PRIx" - %"HWADDR_PRIx" [%p]\n", iova, end - 1, vaddr); + memory_region_ref(section->mr); ret = vfio_dma_map(container, iova, end - iova, vaddr, section->readonly); if (ret) { error_report("vfio_dma_map(%p, 0x%"HWADDR_PRIx", " @@ -2010,6 +2011,7 @@ static void vfio_listener_region_del(MemoryListener *listener, iova, end - 1); ret = vfio_dma_unmap(container, iova, end - iova); + memory_region_unref(section->mr); if (ret) { error_report("vfio_dma_unmap(%p, 0x%"HWADDR_PRIx", " "0x%"HWADDR_PRIx") = %d (%m)", @@ -2203,7 +2205,8 @@ static void vfio_unmap_bar(VFIODevice *vdev, int nr) memory_region_destroy(&bar->mem); } -static int vfio_mmap_bar(VFIOBAR *bar, MemoryRegion *mem, MemoryRegion *submem, +static int vfio_mmap_bar(VFIODevice *vdev, VFIOBAR *bar, + MemoryRegion *mem, MemoryRegion *submem, void **map, size_t size, off_t offset, const char *name) { @@ -2228,11 +2231,11 @@ static int vfio_mmap_bar(VFIOBAR *bar, MemoryRegion *mem, MemoryRegion *submem, goto empty_region; } - memory_region_init_ram_ptr(submem, name, size, *map); + memory_region_init_ram_ptr(submem, OBJECT(vdev), name, size, *map); } else { empty_region: /* Create a zero sized sub-region to make cleanup easy. */ - memory_region_init(submem, name, 0); + memory_region_init(submem, OBJECT(vdev), name, 0); } memory_region_add_subregion(mem, offset, submem); @@ -2271,7 +2274,7 @@ static void vfio_map_bar(VFIODevice *vdev, int nr) ~PCI_BASE_ADDRESS_IO_MASK : ~PCI_BASE_ADDRESS_MEM_MASK); /* A "slow" read/write mapping underlies all BARs */ - memory_region_init_io(&bar->mem, &vfio_bar_ops, bar, name, size); + memory_region_init_io(&bar->mem, OBJECT(vdev), &vfio_bar_ops, bar, name, size); pci_register_bar(&vdev->pdev, nr, type, &bar->mem); /* @@ -2283,7 +2286,7 @@ static void vfio_map_bar(VFIODevice *vdev, int nr) } strncat(name, " mmap", sizeof(name) - strlen(name) - 1); - if (vfio_mmap_bar(bar, &bar->mem, + if (vfio_mmap_bar(vdev, bar, &bar->mem, &bar->mmap_mem, &bar->mmap, size, 0, name)) { error_report("%s unsupported. Performance may be slow", name); } @@ -2297,7 +2300,7 @@ static void vfio_map_bar(VFIODevice *vdev, int nr) size = start < bar->size ? bar->size - start : 0; strncat(name, " msix-hi", sizeof(name) - strlen(name) - 1); /* VFIOMSIXInfo contains another MemoryRegion for this mapping */ - if (vfio_mmap_bar(bar, &bar->mem, &vdev->msix->mmap_mem, + if (vfio_mmap_bar(vdev, bar, &bar->mem, &vdev->msix->mmap_mem, &vdev->msix->mmap, size, start, name)) { error_report("%s unsupported. Performance may be slow", name); } @@ -2316,17 +2319,17 @@ static void vfio_map_bars(VFIODevice *vdev) if (vdev->has_vga) { memory_region_init_io(&vdev->vga.region[QEMU_PCI_VGA_MEM].mem, - &vfio_vga_ops, + OBJECT(vdev), &vfio_vga_ops, &vdev->vga.region[QEMU_PCI_VGA_MEM], "vfio-vga-mmio@0xa0000", QEMU_PCI_VGA_MEM_SIZE); memory_region_init_io(&vdev->vga.region[QEMU_PCI_VGA_IO_LO].mem, - &vfio_vga_ops, + OBJECT(vdev), &vfio_vga_ops, &vdev->vga.region[QEMU_PCI_VGA_IO_LO], "vfio-vga-io@0x3b0", QEMU_PCI_VGA_IO_LO_SIZE); memory_region_init_io(&vdev->vga.region[QEMU_PCI_VGA_IO_HI].mem, - &vfio_vga_ops, + OBJECT(vdev), &vfio_vga_ops, &vdev->vga.region[QEMU_PCI_VGA_IO_HI], "vfio-vga-io@0x3c0", QEMU_PCI_VGA_IO_HI_SIZE); @@ -2588,7 +2591,7 @@ static int vfio_load_rom(VFIODevice *vdev) snprintf(name, sizeof(name), "vfio[%04x:%02x:%02x.%x].rom", vdev->host.domain, vdev->host.bus, vdev->host.slot, vdev->host.function); - memory_region_init_ram(&vdev->pdev.rom, name, size); + memory_region_init_ram(&vdev->pdev.rom, OBJECT(vdev), name, size); ptr = memory_region_get_ram_ptr(&vdev->pdev.rom); memset(ptr, 0xff, size); diff --git a/hw/misc/vmport.c b/hw/misc/vmport.c index 8363dfdf9..0b5a5644e 100644 --- a/hw/misc/vmport.c +++ b/hw/misc/vmport.c @@ -43,13 +43,13 @@ typedef struct VMPortState ISADevice parent_obj; MemoryRegion io; - IOPortReadFunc *func[VMPORT_ENTRIES]; + VMPortReadFunc *func[VMPORT_ENTRIES]; void *opaque[VMPORT_ENTRIES]; } VMPortState; static VMPortState *port_state; -void vmport_register(unsigned char command, IOPortReadFunc *func, void *opaque) +void vmport_register(unsigned char command, VMPortReadFunc *func, void *opaque) { if (command >= VMPORT_ENTRIES) return; @@ -62,11 +62,13 @@ static uint64_t vmport_ioport_read(void *opaque, hwaddr addr, unsigned size) { VMPortState *s = opaque; - CPUX86State *env = cpu_single_env; + CPUState *cs = current_cpu; + X86CPU *cpu = X86_CPU(cs); + CPUX86State *env = &cpu->env; unsigned char command; uint32_t eax; - cpu_synchronize_state(CPU(x86_env_get_cpu(env))); + cpu_synchronize_state(cs); eax = env->regs[R_EAX]; if (eax != VMPORT_MAGIC) @@ -89,29 +91,32 @@ static uint64_t vmport_ioport_read(void *opaque, hwaddr addr, static void vmport_ioport_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { - CPUX86State *env = cpu_single_env; + X86CPU *cpu = X86_CPU(current_cpu); - env->regs[R_EAX] = vmport_ioport_read(opaque, addr, 4); + cpu->env.regs[R_EAX] = vmport_ioport_read(opaque, addr, 4); } static uint32_t vmport_cmd_get_version(void *opaque, uint32_t addr) { - CPUX86State *env = cpu_single_env; - env->regs[R_EBX] = VMPORT_MAGIC; + X86CPU *cpu = X86_CPU(current_cpu); + + cpu->env.regs[R_EBX] = VMPORT_MAGIC; return 6; } static uint32_t vmport_cmd_ram_size(void *opaque, uint32_t addr) { - CPUX86State *env = cpu_single_env; - env->regs[R_EBX] = 0x1177; + X86CPU *cpu = X86_CPU(current_cpu); + + cpu->env.regs[R_EBX] = 0x1177; return ram_size; } /* vmmouse helpers */ void vmmouse_get_data(uint32_t *data) { - CPUX86State *env = cpu_single_env; + X86CPU *cpu = X86_CPU(current_cpu); + CPUX86State *env = &cpu->env; data[0] = env->regs[R_EAX]; data[1] = env->regs[R_EBX]; data[2] = env->regs[R_ECX]; data[3] = env->regs[R_EDX]; @@ -120,7 +125,8 @@ void vmmouse_get_data(uint32_t *data) void vmmouse_set_data(const uint32_t *data) { - CPUX86State *env = cpu_single_env; + X86CPU *cpu = X86_CPU(current_cpu); + CPUX86State *env = &cpu->env; env->regs[R_EAX] = data[0]; env->regs[R_EBX] = data[1]; env->regs[R_ECX] = data[2]; env->regs[R_EDX] = data[3]; @@ -142,7 +148,7 @@ static void vmport_realizefn(DeviceState *dev, Error **errp) ISADevice *isadev = ISA_DEVICE(dev); VMPortState *s = VMPORT(dev); - memory_region_init_io(&s->io, &vmport_ops, s, "vmport", 1); + memory_region_init_io(&s->io, OBJECT(s), &vmport_ops, s, "vmport", 1); isa_register_ioport(isadev, &s->io, 0x5658); port_state = s; diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c index 841832726..fc7a85f0d 100644 --- a/hw/misc/zynq_slcr.c +++ b/hw/misc/zynq_slcr.c @@ -494,7 +494,7 @@ static int zynq_slcr_init(SysBusDevice *dev) { ZynqSLCRState *s = FROM_SYSBUS(ZynqSLCRState, dev); - memory_region_init_io(&s->iomem, &slcr_ops, s, "slcr", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &slcr_ops, s, "slcr", 0x1000); sysbus_init_mmio(dev, &s->iomem); return 0; diff --git a/hw/moxie/moxiesim.c b/hw/moxie/moxiesim.c index 649f9a7da..ef4f3a84d 100644 --- a/hw/moxie/moxiesim.c +++ b/hw/moxie/moxiesim.c @@ -136,11 +136,11 @@ static void moxiesim_init(QEMUMachineInitArgs *args) qemu_register_reset(main_cpu_reset, cpu); /* Allocate RAM. */ - memory_region_init_ram(ram, "moxiesim.ram", ram_size); + memory_region_init_ram(ram, NULL, "moxiesim.ram", ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(address_space_mem, ram_base, ram); - memory_region_init_ram(rom, "moxie.rom", 128*0x1000); + memory_region_init_ram(rom, NULL, "moxie.rom", 128*0x1000); vmstate_register_ram_global(rom); memory_region_add_subregion(get_system_memory(), 0x1000, rom); diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index e177057e4..ac929cba6 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c @@ -1163,7 +1163,8 @@ static int gem_init(SysBusDevice *dev) s = FROM_SYSBUS(GemState, dev); gem_init_register_masks(s); - memory_region_init_io(&s->iomem, &gem_ops, s, "enet", sizeof(s->regs)); + memory_region_init_io(&s->iomem, OBJECT(s), &gem_ops, s, + "enet", sizeof(s->regs)); sysbus_init_mmio(dev, &s->iomem); sysbus_init_irq(dev, &s->irq); qemu_macaddr_default_if_unset(&s->conf.macaddr); diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c index 2289f089a..049aa704c 100644 --- a/hw/net/dp8393x.c +++ b/hw/net/dp8393x.c @@ -908,7 +908,7 @@ void dp83932_init(NICInfo *nd, hwaddr base, int it_shift, qemu_register_reset(nic_reset, s); nic_reset(s); - memory_region_init_io(&s->mmio, &dp8393x_ops, s, + memory_region_init_io(&s->mmio, NULL, &dp8393x_ops, s, "dp8393x", 0x40 << it_shift); memory_region_add_subregion(address_space, base, &s->mmio); } diff --git a/hw/net/e1000.c b/hw/net/e1000.c index e6f46f0c5..5f04f135a 100644 --- a/hw/net/e1000.c +++ b/hw/net/e1000.c @@ -556,7 +556,7 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp) uint32_t txd_lower = le32_to_cpu(dp->lower.data); uint32_t dtype = txd_lower & (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D); unsigned int split_size = txd_lower & 0xffff, bytes, sz, op; - unsigned int msh = 0xfffff, hdr = 0; + unsigned int msh = 0xfffff; uint64_t addr; struct e1000_context_desc *xp = (struct e1000_context_desc *)dp; struct e1000_tx *tp = &s->tx; @@ -603,8 +603,7 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp) addr = le64_to_cpu(dp->buffer_addr); if (tp->tse && tp->cptse) { - hdr = tp->hdr_len; - msh = hdr + tp->mss; + msh = tp->hdr_len + tp->mss; do { bytes = split_size; if (tp->size + bytes > msh) @@ -612,14 +611,16 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp) bytes = MIN(sizeof(tp->data) - tp->size, bytes); pci_dma_read(&s->dev, addr, tp->data + tp->size, bytes); - if ((sz = tp->size + bytes) >= hdr && tp->size < hdr) - memmove(tp->header, tp->data, hdr); + sz = tp->size + bytes; + if (sz >= tp->hdr_len && tp->size < tp->hdr_len) { + memmove(tp->header, tp->data, tp->hdr_len); + } tp->size = sz; addr += bytes; if (sz == msh) { xmit_seg(s); - memmove(tp->data, tp->header, hdr); - tp->size = hdr; + memmove(tp->data, tp->header, tp->hdr_len); + tp->size = tp->hdr_len; } } while (split_size -= bytes); } else if (!tp->tse && tp->cptse) { @@ -633,8 +634,9 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp) if (!(txd_lower & E1000_TXD_CMD_EOP)) return; - if (!(tp->tse && tp->cptse && tp->size < hdr)) + if (!(tp->tse && tp->cptse && tp->size < tp->hdr_len)) { xmit_seg(s); + } tp->tso_frames = 0; tp->sum_needed = 0; tp->vlan_needed = 0; @@ -1276,13 +1278,13 @@ e1000_mmio_setup(E1000State *d) E1000_IMC, E1000_TCTL, E1000_TDT, PNPMMIO_SIZE }; - memory_region_init_io(&d->mmio, &e1000_mmio_ops, d, "e1000-mmio", - PNPMMIO_SIZE); + memory_region_init_io(&d->mmio, OBJECT(d), &e1000_mmio_ops, d, + "e1000-mmio", PNPMMIO_SIZE); memory_region_add_coalescing(&d->mmio, 0, excluded_regs[0]); for (i = 0; excluded_regs[i] != PNPMMIO_SIZE; i++) memory_region_add_coalescing(&d->mmio, excluded_regs[i] + 4, excluded_regs[i+1] - excluded_regs[i] - 4); - memory_region_init_io(&d->io, &e1000_io_ops, d, "e1000-io", IOPORT_SIZE); + memory_region_init_io(&d->io, OBJECT(d), &e1000_io_ops, d, "e1000-io", IOPORT_SIZE); } static void diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c index dc99ea6ea..e0befb259 100644 --- a/hw/net/eepro100.c +++ b/hw/net/eepro100.c @@ -1876,15 +1876,15 @@ static int e100_nic_init(PCIDevice *pci_dev) s->eeprom = eeprom93xx_new(&pci_dev->qdev, EEPROM_SIZE); /* Handler for memory-mapped I/O */ - memory_region_init_io(&s->mmio_bar, &eepro100_ops, s, "eepro100-mmio", - PCI_MEM_SIZE); + memory_region_init_io(&s->mmio_bar, OBJECT(s), &eepro100_ops, s, + "eepro100-mmio", PCI_MEM_SIZE); pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->mmio_bar); - memory_region_init_io(&s->io_bar, &eepro100_ops, s, "eepro100-io", - PCI_IO_SIZE); + memory_region_init_io(&s->io_bar, OBJECT(s), &eepro100_ops, s, + "eepro100-io", PCI_IO_SIZE); pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar); /* FIXME: flash aliases to mmio?! */ - memory_region_init_io(&s->flash_bar, &eepro100_ops, s, "eepro100-flash", - PCI_FLASH_SIZE); + memory_region_init_io(&s->flash_bar, OBJECT(s), &eepro100_ops, s, + "eepro100-flash", PCI_FLASH_SIZE); pci_register_bar(&s->dev, 2, 0, &s->flash_bar); qemu_macaddr_default_if_unset(&s->conf.macaddr); diff --git a/hw/net/etraxfs_eth.c b/hw/net/etraxfs_eth.c index 1039913e0..ab9a21525 100644 --- a/hw/net/etraxfs_eth.c +++ b/hw/net/etraxfs_eth.c @@ -610,7 +610,8 @@ static int fs_eth_init(SysBusDevice *dev) s->dma_in->client.opaque = s; s->dma_in->client.pull = NULL; - memory_region_init_io(&s->mmio, ð_ops, s, "etraxfs-eth", 0x5c); + memory_region_init_io(&s->mmio, OBJECT(dev), ð_ops, s, + "etraxfs-eth", 0x5c); sysbus_init_mmio(dev, &s->mmio); qemu_macaddr_default_if_unset(&s->conf.macaddr); diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c index 403fb868a..3323f48d9 100644 --- a/hw/net/lan9118.c +++ b/hw/net/lan9118.c @@ -1328,7 +1328,8 @@ static int lan9118_init1(SysBusDevice *dev) const MemoryRegionOps *mem_ops = s->mode_16bit ? &lan9118_16bit_mem_ops : &lan9118_mem_ops; - memory_region_init_io(&s->mmio, mem_ops, s, "lan9118-mmio", 0x100); + memory_region_init_io(&s->mmio, OBJECT(dev), mem_ops, s, + "lan9118-mmio", 0x100); sysbus_init_mmio(dev, &s->mmio); sysbus_init_irq(dev, &s->irq); qemu_macaddr_default_if_unset(&s->conf.macaddr); diff --git a/hw/net/lance.c b/hw/net/lance.c index 187497c0c..98bcdfce8 100644 --- a/hw/net/lance.c +++ b/hw/net/lance.c @@ -117,7 +117,8 @@ static int lance_init(SysBusDevice *dev) SysBusPCNetState *d = FROM_SYSBUS(SysBusPCNetState, dev); PCNetState *s = &d->state; - memory_region_init_io(&s->mmio, &lance_mem_ops, d, "lance-mmio", 4); + memory_region_init_io(&s->mmio, OBJECT(d), &lance_mem_ops, d, + "lance-mmio", 4); qdev_init_gpio_in(&dev->qdev, parent_lance_reset, 1); diff --git a/hw/net/mcf_fec.c b/hw/net/mcf_fec.c index 2ef5a0d73..4bff3de34 100644 --- a/hw/net/mcf_fec.c +++ b/hw/net/mcf_fec.c @@ -468,7 +468,7 @@ void mcf_fec_init(MemoryRegion *sysmem, NICInfo *nd, s->sysmem = sysmem; s->irq = irq; - memory_region_init_io(&s->iomem, &mcf_fec_ops, s, "fec", 0x400); + memory_region_init_io(&s->iomem, NULL, &mcf_fec_ops, s, "fec", 0x400); memory_region_add_subregion(sysmem, base, &s->iomem); s->conf.macaddr = nd->macaddr; diff --git a/hw/net/milkymist-minimac2.c b/hw/net/milkymist-minimac2.c index 4ef631841..2ef4ac329 100644 --- a/hw/net/milkymist-minimac2.c +++ b/hw/net/milkymist-minimac2.c @@ -461,12 +461,12 @@ static int milkymist_minimac2_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->rx_irq); sysbus_init_irq(dev, &s->tx_irq); - memory_region_init_io(&s->regs_region, &minimac2_ops, s, + memory_region_init_io(&s->regs_region, OBJECT(dev), &minimac2_ops, s, "milkymist-minimac2", R_MAX * 4); sysbus_init_mmio(dev, &s->regs_region); /* register buffers memory */ - memory_region_init_ram(&s->buffers, "milkymist-minimac2.buffers", + memory_region_init_ram(&s->buffers, OBJECT(dev), "milkymist-minimac2.buffers", buffers_size); vmstate_register_ram_global(&s->buffers); s->rx0_buf = memory_region_get_ram_ptr(&s->buffers); diff --git a/hw/net/mipsnet.c b/hw/net/mipsnet.c index ac6193a89..908085073 100644 --- a/hw/net/mipsnet.c +++ b/hw/net/mipsnet.c @@ -235,7 +235,8 @@ static int mipsnet_sysbus_init(SysBusDevice *dev) { MIPSnetState *s = DO_UPCAST(MIPSnetState, busdev, dev); - memory_region_init_io(&s->io, &mipsnet_ioport_ops, s, "mipsnet-io", 36); + memory_region_init_io(&s->io, OBJECT(dev), &mipsnet_ioport_ops, s, + "mipsnet-io", 36); sysbus_init_mmio(dev, &s->io); sysbus_init_irq(dev, &s->irq); diff --git a/hw/net/ne2000-isa.c b/hw/net/ne2000-isa.c index 9232abd46..e3c807638 100644 --- a/hw/net/ne2000-isa.c +++ b/hw/net/ne2000-isa.c @@ -72,7 +72,7 @@ static void isa_ne2000_realizefn(DeviceState *dev, Error **errp) ISANE2000State *isa = ISA_NE2000(dev); NE2000State *s = &isa->ne2000; - ne2000_setup_io(s, 0x20); + ne2000_setup_io(s, DEVICE(isadev), 0x20); isa_register_ioport(isadev, &s->io, isa->iobase); isa_init_irq(isadev, &s->irq, isa->isairq); diff --git a/hw/net/ne2000.c b/hw/net/ne2000.c index 33ee03e68..8d43fd9af 100644 --- a/hw/net/ne2000.c +++ b/hw/net/ne2000.c @@ -699,9 +699,9 @@ static const MemoryRegionOps ne2000_ops = { /***********************************************************/ /* PCI NE2000 definitions */ -void ne2000_setup_io(NE2000State *s, unsigned size) +void ne2000_setup_io(NE2000State *s, DeviceState *dev, unsigned size) { - memory_region_init_io(&s->io, &ne2000_ops, s, "ne2000", size); + memory_region_init_io(&s->io, OBJECT(dev), &ne2000_ops, s, "ne2000", size); } static void ne2000_cleanup(NetClientState *nc) @@ -729,7 +729,7 @@ static int pci_ne2000_init(PCIDevice *pci_dev) pci_conf[PCI_INTERRUPT_PIN] = 1; /* interrupt pin A */ s = &d->ne2000; - ne2000_setup_io(s, 0x100); + ne2000_setup_io(s, DEVICE(pci_dev), 0x100); pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io); s->irq = d->dev.irq[0]; diff --git a/hw/net/ne2000.h b/hw/net/ne2000.h index b31ae030f..e500306aa 100644 --- a/hw/net/ne2000.h +++ b/hw/net/ne2000.h @@ -31,7 +31,7 @@ typedef struct NE2000State { uint8_t mem[NE2000_MEM_SIZE]; } NE2000State; -void ne2000_setup_io(NE2000State *s, unsigned size); +void ne2000_setup_io(NE2000State *s, DeviceState *dev, unsigned size); extern const VMStateDescription vmstate_ne2000; void ne2000_reset(NE2000State *s); int ne2000_can_receive(NetClientState *nc); diff --git a/hw/net/opencores_eth.c b/hw/net/opencores_eth.c index be64bf2a6..46375574e 100644 --- a/hw/net/opencores_eth.c +++ b/hw/net/opencores_eth.c @@ -681,11 +681,11 @@ static int sysbus_open_eth_init(SysBusDevice *dev) { OpenEthState *s = DO_UPCAST(OpenEthState, dev, dev); - memory_region_init_io(&s->reg_io, &open_eth_reg_ops, s, + memory_region_init_io(&s->reg_io, OBJECT(dev), &open_eth_reg_ops, s, "open_eth.regs", 0x54); sysbus_init_mmio(dev, &s->reg_io); - memory_region_init_io(&s->desc_io, &open_eth_desc_ops, s, + memory_region_init_io(&s->desc_io, OBJECT(dev), &open_eth_desc_ops, s, "open_eth.desc", 0x400); sysbus_init_mmio(dev, &s->desc_io); diff --git a/hw/net/pcnet-pci.c b/hw/net/pcnet-pci.c index 9df2b8754..f4a5aef42 100644 --- a/hw/net/pcnet-pci.c +++ b/hw/net/pcnet-pci.c @@ -315,10 +315,10 @@ static int pci_pcnet_init(PCIDevice *pci_dev) pci_conf[PCI_MAX_LAT] = 0xff; /* Handler for memory-mapped I/O */ - memory_region_init_io(&d->state.mmio, &pcnet_mmio_ops, s, "pcnet-mmio", - PCNET_PNPMMIO_SIZE); + memory_region_init_io(&d->state.mmio, OBJECT(d), &pcnet_mmio_ops, s, + "pcnet-mmio", PCNET_PNPMMIO_SIZE); - memory_region_init_io(&d->io_bar, &pcnet_io_ops, s, "pcnet-io", + memory_region_init_io(&d->io_bar, OBJECT(d), &pcnet_io_ops, s, "pcnet-io", PCNET_IOPORT_SIZE); pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &d->io_bar); diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c index 7993f9f5b..a00ff581d 100644 --- a/hw/net/rtl8139.c +++ b/hw/net/rtl8139.c @@ -3486,8 +3486,10 @@ static int pci_rtl8139_init(PCIDevice *dev) * list bit in status register, and offset 0xdc seems unused. */ pci_conf[PCI_CAPABILITY_LIST] = 0xdc; - memory_region_init_io(&s->bar_io, &rtl8139_io_ops, s, "rtl8139", 0x100); - memory_region_init_io(&s->bar_mem, &rtl8139_mmio_ops, s, "rtl8139", 0x100); + memory_region_init_io(&s->bar_io, OBJECT(s), &rtl8139_io_ops, s, + "rtl8139", 0x100); + memory_region_init_io(&s->bar_mem, OBJECT(s), &rtl8139_mmio_ops, s, + "rtl8139", 0x100); pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->bar_io); pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar_mem); diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c index c2feae6eb..c49e37a8b 100644 --- a/hw/net/smc91c111.c +++ b/hw/net/smc91c111.c @@ -747,7 +747,7 @@ static NetClientInfo net_smc91c111_info = { static int smc91c111_init1(SysBusDevice *dev) { smc91c111_state *s = FROM_SYSBUS(smc91c111_state, dev); - memory_region_init_io(&s->mmio, &smc91c111_mem_ops, s, + memory_region_init_io(&s->mmio, OBJECT(s), &smc91c111_mem_ops, s, "smc91c111-mmio", 16); sysbus_init_mmio(dev, &s->mmio); sysbus_init_irq(dev, &s->irq); diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c index 59b84564a..aac7c76fe 100644 --- a/hw/net/stellaris_enet.c +++ b/hw/net/stellaris_enet.c @@ -405,8 +405,8 @@ static int stellaris_enet_init(SysBusDevice *dev) { stellaris_enet_state *s = FROM_SYSBUS(stellaris_enet_state, dev); - memory_region_init_io(&s->mmio, &stellaris_enet_ops, s, "stellaris_enet", - 0x1000); + memory_region_init_io(&s->mmio, OBJECT(s), &stellaris_enet_ops, s, + "stellaris_enet", 0x1000); sysbus_init_mmio(dev, &s->mmio); sysbus_init_irq(dev, &s->irq); qemu_macaddr_default_if_unset(&s->conf.macaddr); diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c index 4c575e55a..b39ff08f2 100644 --- a/hw/net/vmxnet3.c +++ b/hw/net/vmxnet3.c @@ -2073,17 +2073,17 @@ static int vmxnet3_pci_init(PCIDevice *pci_dev) VMW_CBPRN("Starting init..."); - memory_region_init_io(&s->bar0, &b0_ops, s, + memory_region_init_io(&s->bar0, OBJECT(s), &b0_ops, s, "vmxnet3-b0", VMXNET3_PT_REG_SIZE); pci_register_bar(pci_dev, VMXNET3_BAR0_IDX, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar0); - memory_region_init_io(&s->bar1, &b1_ops, s, + memory_region_init_io(&s->bar1, OBJECT(s), &b1_ops, s, "vmxnet3-b1", VMXNET3_VD_REG_SIZE); pci_register_bar(pci_dev, VMXNET3_BAR1_IDX, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar1); - memory_region_init(&s->msix_bar, "vmxnet3-msix-bar", + memory_region_init(&s->msix_bar, OBJECT(s), "vmxnet3-msix-bar", VMXNET3_MSIX_BAR_SIZE); pci_register_bar(pci_dev, VMXNET3_MSIX_BAR_IDX, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->msix_bar); diff --git a/hw/net/xgmac.c b/hw/net/xgmac.c index 1d9074a1d..997a5b59e 100644 --- a/hw/net/xgmac.c +++ b/hw/net/xgmac.c @@ -382,7 +382,8 @@ static int xgmac_enet_init(SysBusDevice *dev) { struct XgmacState *s = FROM_SYSBUS(typeof(*s), dev); - memory_region_init_io(&s->iomem, &enet_mem_ops, s, "xgmac", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &enet_mem_ops, s, + "xgmac", 0x1000); sysbus_init_mmio(dev, &s->iomem); sysbus_init_irq(dev, &s->sbd_irq); sysbus_init_irq(dev, &s->pmt_irq); diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c index 2ca1511c0..f173429ec 100644 --- a/hw/net/xilinx_axienet.c +++ b/hw/net/xilinx_axienet.c @@ -1001,7 +1001,7 @@ static void xilinx_enet_init(Object *obj) sysbus_init_irq(sbd, &s->irq); - memory_region_init_io(&s->iomem, &enet_ops, s, "enet", 0x40000); + memory_region_init_io(&s->iomem, OBJECT(s), &enet_ops, s, "enet", 0x40000); sysbus_init_mmio(sbd, &s->iomem); } diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c index b2e35237f..2afc91ad0 100644 --- a/hw/net/xilinx_ethlite.c +++ b/hw/net/xilinx_ethlite.c @@ -221,8 +221,8 @@ static int xilinx_ethlite_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq); s->rxbuf = 0; - memory_region_init_io(&s->mmio, ð_ops, s, "xlnx.xps-ethernetlite", - R_MAX * 4); + memory_region_init_io(&s->mmio, OBJECT(s), ð_ops, s, + "xlnx.xps-ethernetlite", R_MAX * 4); sysbus_init_mmio(dev, &s->mmio); qemu_macaddr_default_if_unset(&s->conf.macaddr); diff --git a/hw/nvram/ds1225y.c b/hw/nvram/ds1225y.c index 488f1d724..fa218ce70 100644 --- a/hw/nvram/ds1225y.c +++ b/hw/nvram/ds1225y.c @@ -117,7 +117,8 @@ static int nvram_sysbus_initfn(SysBusDevice *dev) s->contents = g_malloc0(s->chip_size); - memory_region_init_io(&s->iomem, &nvram_ops, s, "nvram", s->chip_size); + memory_region_init_io(&s->iomem, OBJECT(s), &nvram_ops, s, + "nvram", s->chip_size); sysbus_init_mmio(dev, &s->iomem); /* Read current file */ diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index 3c255cec0..e45528236 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -526,14 +526,14 @@ static int fw_cfg_init1(SysBusDevice *dev) { FWCfgState *s = FROM_SYSBUS(FWCfgState, dev); - memory_region_init_io(&s->ctl_iomem, &fw_cfg_ctl_mem_ops, s, + memory_region_init_io(&s->ctl_iomem, OBJECT(s), &fw_cfg_ctl_mem_ops, s, "fwcfg.ctl", FW_CFG_SIZE); sysbus_init_mmio(dev, &s->ctl_iomem); - memory_region_init_io(&s->data_iomem, &fw_cfg_data_mem_ops, s, + memory_region_init_io(&s->data_iomem, OBJECT(s), &fw_cfg_data_mem_ops, s, "fwcfg.data", FW_CFG_DATA_SIZE); sysbus_init_mmio(dev, &s->data_iomem); /* In case ctl and data overlap: */ - memory_region_init_io(&s->comb_iomem, &fw_cfg_comb_mem_ops, s, + memory_region_init_io(&s->comb_iomem, OBJECT(s), &fw_cfg_comb_mem_ops, s, "fwcfg", FW_CFG_SIZE); if (s->ctl_iobase + 1 == s->data_iobase) { diff --git a/hw/nvram/mac_nvram.c b/hw/nvram/mac_nvram.c index d76a06c48..2eb008179 100644 --- a/hw/nvram/mac_nvram.c +++ b/hw/nvram/mac_nvram.c @@ -115,8 +115,8 @@ static void macio_nvram_realizefn(DeviceState *dev, Error **errp) s->data = g_malloc0(s->size); - memory_region_init_io(&s->mem, &macio_nvram_ops, s, "macio-nvram", - s->size << s->it_shift); + memory_region_init_io(&s->mem, OBJECT(s), &macio_nvram_ops, s, + "macio-nvram", s->size << s->it_shift); sysbus_init_mmio(d, &s->mem); } diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c index 49bab1f0f..924438bcc 100644 --- a/hw/openrisc/openrisc_sim.c +++ b/hw/openrisc/openrisc_sim.c @@ -115,7 +115,7 @@ static void openrisc_sim_init(QEMUMachineInitArgs *args) } ram = g_malloc(sizeof(*ram)); - memory_region_init_ram(ram, "openrisc.ram", ram_size); + memory_region_init_ram(ram, NULL, "openrisc.ram", ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(get_system_memory(), 0, ram); diff --git a/hw/pci-bridge/dec.c b/hw/pci-bridge/dec.c index cff458b57..efc07c42b 100644 --- a/hw/pci-bridge/dec.c +++ b/hw/pci-bridge/dec.c @@ -98,9 +98,9 @@ static int pci_dec_21154_device_init(SysBusDevice *dev) phb = PCI_HOST_BRIDGE(dev); - memory_region_init_io(&phb->conf_mem, &pci_host_conf_le_ops, + memory_region_init_io(&phb->conf_mem, OBJECT(dev), &pci_host_conf_le_ops, dev, "pci-conf-idx", 0x1000); - memory_region_init_io(&phb->data_mem, &pci_host_data_le_ops, + memory_region_init_io(&phb->data_mem, OBJECT(dev), &pci_host_data_le_ops, dev, "pci-data-idx", 0x1000); sysbus_init_mmio(dev, &phb->conf_mem); sysbus_init_mmio(dev, &phb->data_mem); diff --git a/hw/pci-bridge/pci_bridge_dev.c b/hw/pci-bridge/pci_bridge_dev.c index 971b43247..5f11323fe 100644 --- a/hw/pci-bridge/pci_bridge_dev.c +++ b/hw/pci-bridge/pci_bridge_dev.c @@ -46,7 +46,7 @@ static int pci_bridge_dev_initfn(PCIDevice *dev) if (err) { goto bridge_error; } - memory_region_init(&bridge_dev->bar, "shpc-bar", shpc_bar_size(dev)); + memory_region_init(&bridge_dev->bar, OBJECT(dev), "shpc-bar", shpc_bar_size(dev)); err = shpc_init(dev, &br->sec_bus, &bridge_dev->bar, 0); if (err) { goto shpc_error; diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c index e0996556e..06ace085b 100644 --- a/hw/pci-host/apb.c +++ b/hw/pci-host/apb.c @@ -447,7 +447,7 @@ PCIBus *pci_apb_init(hwaddr special_base, sysbus_mmio_map(s, 2, special_base + 0x2000000ULL); d = FROM_SYSBUS(APBState, s); - memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL); + memory_region_init(&d->pci_mmio, OBJECT(s), "pci-mmio", 0x100000000ULL); memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio); d->bus = pci_register_bus(&d->busdev.qdev, "pci", @@ -525,18 +525,18 @@ static int pci_pbm_init_device(SysBusDevice *dev) s->pci_irq_in = 0ULL; /* apb_config */ - memory_region_init_io(&s->apb_config, &apb_config_ops, s, "apb-config", - 0x10000); + memory_region_init_io(&s->apb_config, OBJECT(s), &apb_config_ops, s, + "apb-config", 0x10000); /* at region 0 */ sysbus_init_mmio(dev, &s->apb_config); - memory_region_init_io(&s->pci_config, &pci_config_ops, s, "apb-pci-config", - 0x1000000); + memory_region_init_io(&s->pci_config, OBJECT(s), &pci_config_ops, s, + "apb-pci-config", 0x1000000); /* at region 1 */ sysbus_init_mmio(dev, &s->pci_config); /* pci_ioport */ - memory_region_init_io(&s->pci_ioport, &pci_ioport_ops, s, + memory_region_init_io(&s->pci_ioport, OBJECT(s), &pci_ioport_ops, s, "apb-pci-ioport", 0x10000); /* at region 2 */ sysbus_init_mmio(dev, &s->pci_ioport); diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c index 974150bfc..592d6666b 100644 --- a/hw/pci-host/bonito.c +++ b/hw/pci-host/bonito.c @@ -722,29 +722,29 @@ static int bonito_initfn(PCIDevice *dev) pci_config_set_prog_interface(dev->config, 0x00); /* set the north bridge register mapping */ - memory_region_init_io(&s->iomem, &bonito_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &bonito_ops, s, "north-bridge-register", BONITO_INTERNAL_REG_SIZE); sysbus_init_mmio(sysbus, &s->iomem); sysbus_mmio_map(sysbus, 0, BONITO_INTERNAL_REG_BASE); /* set the north bridge pci configure mapping */ - memory_region_init_io(&phb->conf_mem, &bonito_pciconf_ops, s, + memory_region_init_io(&phb->conf_mem, OBJECT(s), &bonito_pciconf_ops, s, "north-bridge-pci-config", BONITO_PCICONFIG_SIZE); sysbus_init_mmio(sysbus, &phb->conf_mem); sysbus_mmio_map(sysbus, 1, BONITO_PCICONFIG_BASE); /* set the south bridge pci configure mapping */ - memory_region_init_io(&phb->data_mem, &bonito_spciconf_ops, s, + memory_region_init_io(&phb->data_mem, OBJECT(s), &bonito_spciconf_ops, s, "south-bridge-pci-config", BONITO_SPCICONFIG_SIZE); sysbus_init_mmio(sysbus, &phb->data_mem); sysbus_mmio_map(sysbus, 2, BONITO_SPCICONFIG_BASE); - memory_region_init_io(&s->iomem_ldma, &bonito_ldma_ops, s, + memory_region_init_io(&s->iomem_ldma, OBJECT(s), &bonito_ldma_ops, s, "ldma", 0x100); sysbus_init_mmio(sysbus, &s->iomem_ldma); sysbus_mmio_map(sysbus, 3, 0xbfe00200); - memory_region_init_io(&s->iomem_cop, &bonito_cop_ops, s, + memory_region_init_io(&s->iomem_cop, OBJECT(s), &bonito_cop_ops, s, "cop", 0x100); sysbus_init_mmio(sysbus, &s->iomem_cop); sysbus_mmio_map(sysbus, 4, 0xbfe00300); diff --git a/hw/pci-host/grackle.c b/hw/pci-host/grackle.c index 69344d9f6..4991ec44b 100644 --- a/hw/pci-host/grackle.c +++ b/hw/pci-host/grackle.c @@ -76,8 +76,8 @@ PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic, phb = PCI_HOST_BRIDGE(dev); d = GRACKLE_PCI_HOST_BRIDGE(dev); - memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL); - memory_region_init_alias(&d->pci_hole, "pci-hole", &d->pci_mmio, + memory_region_init(&d->pci_mmio, OBJECT(s), "pci-mmio", 0x100000000ULL); + memory_region_init_alias(&d->pci_hole, OBJECT(s), "pci-hole", &d->pci_mmio, 0x80000000ULL, 0x7e000000ULL); memory_region_add_subregion(address_space_mem, 0x80000000ULL, &d->pci_hole); @@ -104,9 +104,9 @@ static int pci_grackle_init_device(SysBusDevice *dev) phb = PCI_HOST_BRIDGE(dev); - memory_region_init_io(&phb->conf_mem, &pci_host_conf_le_ops, + memory_region_init_io(&phb->conf_mem, OBJECT(dev), &pci_host_conf_le_ops, dev, "pci-conf-idx", 0x1000); - memory_region_init_io(&phb->data_mem, &pci_host_data_le_ops, + memory_region_init_io(&phb->data_mem, OBJECT(dev), &pci_host_data_le_ops, dev, "pci-data-idx", 0x1000); sysbus_init_mmio(dev, &phb->conf_mem); sysbus_init_mmio(dev, &phb->data_mem); diff --git a/hw/pci-host/pam.c b/hw/pci-host/pam.c index 7181bd68e..ec6be4676 100644 --- a/hw/pci-host/pam.c +++ b/hw/pci-host/pam.c @@ -26,6 +26,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ + +#include "qom/object.h" #include "sysemu/sysemu.h" #include "hw/pci-host/pam.h" @@ -49,24 +51,24 @@ void smram_set_smm(uint8_t *host_smm_enabled, int smm, uint8_t smram, } } -void init_pam(MemoryRegion *ram_memory, MemoryRegion *system_memory, - MemoryRegion *pci_address_space, PAMMemoryRegion *mem, - uint32_t start, uint32_t size) +void init_pam(DeviceState *dev, MemoryRegion *ram_memory, + MemoryRegion *system_memory, MemoryRegion *pci_address_space, + PAMMemoryRegion *mem, uint32_t start, uint32_t size) { int i; /* RAM */ - memory_region_init_alias(&mem->alias[3], "pam-ram", ram_memory, + memory_region_init_alias(&mem->alias[3], OBJECT(dev), "pam-ram", ram_memory, start, size); /* ROM (XXX: not quite correct) */ - memory_region_init_alias(&mem->alias[1], "pam-rom", ram_memory, + memory_region_init_alias(&mem->alias[1], OBJECT(dev), "pam-rom", ram_memory, start, size); memory_region_set_readonly(&mem->alias[1], true); /* XXX: should distinguish read/write cases */ - memory_region_init_alias(&mem->alias[0], "pam-pci", pci_address_space, + memory_region_init_alias(&mem->alias[0], OBJECT(dev), "pam-pci", pci_address_space, start, size); - memory_region_init_alias(&mem->alias[2], "pam-pci", pci_address_space, + memory_region_init_alias(&mem->alias[2], OBJECT(dev), "pam-pci", pci_address_space, start, size); for (i = 0; i < 4; ++i) { diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c index f9e68c309..870e38810 100644 --- a/hw/pci-host/piix.c +++ b/hw/pci-host/piix.c @@ -201,12 +201,12 @@ static int i440fx_pcihost_initfn(SysBusDevice *dev) { PCIHostState *s = PCI_HOST_BRIDGE(dev); - memory_region_init_io(&s->conf_mem, &pci_host_conf_le_ops, s, + memory_region_init_io(&s->conf_mem, OBJECT(dev), &pci_host_conf_le_ops, s, "pci-conf-idx", 4); sysbus_add_io(dev, 0xcf8, &s->conf_mem); sysbus_init_ioports(&s->busdev, 0xcf8, 4); - memory_region_init_io(&s->data_mem, &pci_host_data_le_ops, s, + memory_region_init_io(&s->data_mem, OBJECT(dev), &pci_host_data_le_ops, s, "pci-conf-data", 4); sysbus_add_io(dev, 0xcfc, &s->data_mem); sysbus_init_ioports(&s->busdev, 0xcfc, 4); @@ -260,25 +260,25 @@ static PCIBus *i440fx_common_init(const char *device_name, f->system_memory = address_space_mem; f->pci_address_space = pci_address_space; f->ram_memory = ram_memory; - memory_region_init_alias(&f->pci_hole, "pci-hole", f->pci_address_space, + memory_region_init_alias(&f->pci_hole, OBJECT(d), "pci-hole", f->pci_address_space, pci_hole_start, pci_hole_size); memory_region_add_subregion(f->system_memory, pci_hole_start, &f->pci_hole); - memory_region_init_alias(&f->pci_hole_64bit, "pci-hole64", + memory_region_init_alias(&f->pci_hole_64bit, OBJECT(d), "pci-hole64", f->pci_address_space, pci_hole64_start, pci_hole64_size); if (pci_hole64_size) { memory_region_add_subregion(f->system_memory, pci_hole64_start, &f->pci_hole_64bit); } - memory_region_init_alias(&f->smram_region, "smram-region", + memory_region_init_alias(&f->smram_region, OBJECT(d), "smram-region", f->pci_address_space, 0xa0000, 0x20000); memory_region_add_subregion_overlap(f->system_memory, 0xa0000, &f->smram_region, 1); memory_region_set_enabled(&f->smram_region, false); - init_pam(f->ram_memory, f->system_memory, f->pci_address_space, + init_pam(dev, f->ram_memory, f->system_memory, f->pci_address_space, &f->pam_regions[0], PAM_BIOS_BASE, PAM_BIOS_SIZE); for (i = 0; i < 12; ++i) { - init_pam(f->ram_memory, f->system_memory, f->pci_address_space, + init_pam(dev, f->ram_memory, f->system_memory, f->pci_address_space, &f->pam_regions[i+1], PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, PAM_EXPAN_SIZE); } @@ -549,7 +549,8 @@ static int piix3_initfn(PCIDevice *dev) isa_bus_new(DEVICE(d), pci_address_space_io(dev)); - memory_region_init_io(&d->rcr_mem, &rcr_ops, d, "piix3-reset-control", 1); + memory_region_init_io(&d->rcr_mem, OBJECT(dev), &rcr_ops, d, + "piix3-reset-control", 1); memory_region_add_subregion_overlap(pci_address_space_io(dev), RCR_IOPORT, &d->rcr_mem, 1); @@ -629,11 +630,20 @@ static const TypeInfo i440fx_info = { .class_init = i440fx_class_init, }; +static const char *i440fx_pcihost_root_bus_path(PCIHostState *host_bridge, + PCIBus *rootbus) +{ + /* For backwards compat with old device paths */ + return "0000"; +} + static void i440fx_pcihost_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass); + hc->root_bus_path = i440fx_pcihost_root_bus_path; k->init = i440fx_pcihost_initfn; dc->fw_name = "pci"; dc->no_user = 1; diff --git a/hw/pci-host/ppce500.c b/hw/pci-host/ppce500.c index 5e7ad9438..646204e1e 100644 --- a/hw/pci-host/ppce500.c +++ b/hw/pci-host/ppce500.c @@ -330,7 +330,7 @@ static int e500_pcihost_bridge_initfn(PCIDevice *d) (d->config[PCI_HEADER_TYPE] & PCI_HEADER_TYPE_MULTI_FUNCTION) | PCI_HEADER_TYPE_BRIDGE; - memory_region_init_alias(&b->bar0, "e500-pci-bar0", &ccsr->ccsr_space, + memory_region_init_alias(&b->bar0, OBJECT(ccsr), "e500-pci-bar0", &ccsr->ccsr_space, 0, int128_get64(ccsr->ccsr_space.size)); pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &b->bar0); @@ -352,7 +352,7 @@ static int e500_pcihost_initfn(SysBusDevice *dev) sysbus_init_irq(dev, &s->irq[i]); } - memory_region_init(&s->pio, "pci-pio", PCIE500_PCI_IOLEN); + memory_region_init(&s->pio, OBJECT(s), "pci-pio", PCIE500_PCI_IOLEN); b = pci_register_bus(DEVICE(dev), NULL, mpc85xx_pci_set_irq, mpc85xx_pci_map_irq, s->irq, address_space_mem, @@ -361,12 +361,12 @@ static int e500_pcihost_initfn(SysBusDevice *dev) pci_create_simple(b, 0, "e500-host-bridge"); - memory_region_init(&s->container, "pci-container", PCIE500_ALL_SIZE); - memory_region_init_io(&h->conf_mem, &pci_host_conf_be_ops, h, + memory_region_init(&s->container, OBJECT(h), "pci-container", PCIE500_ALL_SIZE); + memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_be_ops, h, "pci-conf-idx", 4); - memory_region_init_io(&h->data_mem, &pci_host_data_le_ops, h, + memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops, h, "pci-conf-data", 4); - memory_region_init_io(&s->iomem, &e500_pci_reg_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &e500_pci_reg_ops, s, "pci.reg", PCIE500_REG_SIZE); memory_region_add_subregion(&s->container, PCIE500_CFGADDR, &h->conf_mem); memory_region_add_subregion(&s->container, PCIE500_CFGDATA, &h->data_mem); diff --git a/hw/pci-host/prep.c b/hw/pci-host/prep.c index 61302539a..b41d5646c 100644 --- a/hw/pci-host/prep.c +++ b/hw/pci-host/prep.c @@ -125,20 +125,20 @@ static void raven_pcihost_realizefn(DeviceState *d, Error **errp) pci_bus_irqs(&s->pci_bus, prep_set_irq, prep_map_irq, s->irq, 4); - memory_region_init_io(&h->conf_mem, &pci_host_conf_be_ops, s, + memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_be_ops, s, "pci-conf-idx", 1); sysbus_add_io(dev, 0xcf8, &h->conf_mem); sysbus_init_ioports(&h->busdev, 0xcf8, 1); - memory_region_init_io(&h->data_mem, &pci_host_data_be_ops, s, + memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_be_ops, s, "pci-conf-data", 1); sysbus_add_io(dev, 0xcfc, &h->data_mem); sysbus_init_ioports(&h->busdev, 0xcfc, 1); - memory_region_init_io(&h->mmcfg, &PPC_PCIIO_ops, s, "pciio", 0x00400000); + memory_region_init_io(&h->mmcfg, OBJECT(s), &PPC_PCIIO_ops, s, "pciio", 0x00400000); memory_region_add_subregion(address_space_mem, 0x80800000, &h->mmcfg); - memory_region_init_io(&s->intack, &PPC_intack_ops, s, "pci-intack", 1); + memory_region_init_io(&s->intack, OBJECT(s), &PPC_intack_ops, s, "pci-intack", 1); memory_region_add_subregion(address_space_mem, 0xbffffff0, &s->intack); /* TODO Remove once realize propagates to child devices. */ diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c index 24df6b55c..8c3ee535f 100644 --- a/hw/pci-host/q35.c +++ b/hw/pci-host/q35.c @@ -40,12 +40,12 @@ static int q35_host_init(SysBusDevice *dev) PCIHostState *pci = FROM_SYSBUS(PCIHostState, dev); Q35PCIHost *s = Q35_HOST_DEVICE(&dev->qdev); - memory_region_init_io(&pci->conf_mem, &pci_host_conf_le_ops, pci, + memory_region_init_io(&pci->conf_mem, OBJECT(pci), &pci_host_conf_le_ops, pci, "pci-conf-idx", 4); sysbus_add_io(dev, MCH_HOST_BRIDGE_CONFIG_ADDR, &pci->conf_mem); sysbus_init_ioports(&pci->busdev, MCH_HOST_BRIDGE_CONFIG_ADDR, 4); - memory_region_init_io(&pci->data_mem, &pci_host_data_le_ops, pci, + memory_region_init_io(&pci->data_mem, OBJECT(pci), &pci_host_data_le_ops, pci, "pci-conf-data", 4); sysbus_add_io(dev, MCH_HOST_BRIDGE_CONFIG_DATA, &pci->data_mem); sysbus_init_ioports(&pci->busdev, MCH_HOST_BRIDGE_CONFIG_DATA, 4); @@ -63,6 +63,13 @@ static int q35_host_init(SysBusDevice *dev) return 0; } +static const char *q35_host_root_bus_path(PCIHostState *host_bridge, + PCIBus *rootbus) +{ + /* For backwards compat with old device paths */ + return "0000"; +} + static Property mch_props[] = { DEFINE_PROP_UINT64("MCFG", Q35PCIHost, host.base_addr, MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT), @@ -73,7 +80,9 @@ static void q35_host_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass); + hc->root_bus_path = q35_host_root_bus_path; k->init = q35_host_init; dc->props = mch_props; dc->fw_name = "pci"; @@ -244,8 +253,16 @@ static int mch_init(PCIDevice *d) hwaddr pci_hole64_size; MCHPCIState *mch = MCH_PCI_DEVICE(d); + /* Leave enough space for the biggest MCFG BAR */ + /* TODO: this matches current bios behaviour, but + * it's not a power of two, which means an MTRR + * can't cover it exactly. + */ + mch->guest_info->pci_info.w32.begin = MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT + + MCH_HOST_BRIDGE_PCIEXBAR_MAX; + /* setup pci memory regions */ - memory_region_init_alias(&mch->pci_hole, "pci-hole", + memory_region_init_alias(&mch->pci_hole, OBJECT(mch), "pci-hole", mch->pci_address_space, mch->below_4g_mem_size, 0x100000000ULL - mch->below_4g_mem_size); @@ -253,7 +270,7 @@ static int mch_init(PCIDevice *d) &mch->pci_hole); pci_hole64_size = (sizeof(hwaddr) == 4 ? 0 : ((uint64_t)1 << 62)); - memory_region_init_alias(&mch->pci_hole_64bit, "pci-hole64", + memory_region_init_alias(&mch->pci_hole_64bit, OBJECT(mch), "pci-hole64", mch->pci_address_space, 0x100000000ULL + mch->above_4g_mem_size, pci_hole64_size); @@ -264,15 +281,15 @@ static int mch_init(PCIDevice *d) } /* smram */ cpu_smm_register(&mch_set_smm, mch); - memory_region_init_alias(&mch->smram_region, "smram-region", + memory_region_init_alias(&mch->smram_region, OBJECT(mch), "smram-region", mch->pci_address_space, 0xa0000, 0x20000); memory_region_add_subregion_overlap(mch->system_memory, 0xa0000, &mch->smram_region, 1); memory_region_set_enabled(&mch->smram_region, false); - init_pam(mch->ram_memory, mch->system_memory, mch->pci_address_space, + init_pam(DEVICE(mch), mch->ram_memory, mch->system_memory, mch->pci_address_space, &mch->pam_regions[0], PAM_BIOS_BASE, PAM_BIOS_SIZE); for (i = 0; i < 12; ++i) { - init_pam(mch->ram_memory, mch->system_memory, mch->pci_address_space, + init_pam(DEVICE(mch), mch->ram_memory, mch->system_memory, mch->pci_address_space, &mch->pam_regions[i+1], PAM_EXPAN_BASE + i * PAM_EXPAN_SIZE, PAM_EXPAN_SIZE); } diff --git a/hw/pci-host/uninorth.c b/hw/pci-host/uninorth.c index fff235d52..91530cdd0 100644 --- a/hw/pci-host/uninorth.c +++ b/hw/pci-host/uninorth.c @@ -152,9 +152,9 @@ static int pci_unin_main_init_device(SysBusDevice *dev) /* Uninorth main bus */ h = PCI_HOST_BRIDGE(dev); - memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops, + memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops, dev, "pci-conf-idx", 0x1000); - memory_region_init_io(&h->data_mem, &unin_data_ops, dev, + memory_region_init_io(&h->data_mem, OBJECT(h), &unin_data_ops, dev, "pci-conf-data", 0x1000); sysbus_init_mmio(dev, &h->conf_mem); sysbus_init_mmio(dev, &h->data_mem); @@ -170,9 +170,9 @@ static int pci_u3_agp_init_device(SysBusDevice *dev) /* Uninorth U3 AGP bus */ h = PCI_HOST_BRIDGE(dev); - memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops, + memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops, dev, "pci-conf-idx", 0x1000); - memory_region_init_io(&h->data_mem, &unin_data_ops, dev, + memory_region_init_io(&h->data_mem, OBJECT(h), &unin_data_ops, dev, "pci-conf-data", 0x1000); sysbus_init_mmio(dev, &h->conf_mem); sysbus_init_mmio(dev, &h->data_mem); @@ -187,9 +187,9 @@ static int pci_unin_agp_init_device(SysBusDevice *dev) /* Uninorth AGP bus */ h = PCI_HOST_BRIDGE(dev); - memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops, + memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops, dev, "pci-conf-idx", 0x1000); - memory_region_init_io(&h->data_mem, &pci_host_data_le_ops, + memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops, dev, "pci-conf-data", 0x1000); sysbus_init_mmio(dev, &h->conf_mem); sysbus_init_mmio(dev, &h->data_mem); @@ -203,9 +203,9 @@ static int pci_unin_internal_init_device(SysBusDevice *dev) /* Uninorth internal bus */ h = PCI_HOST_BRIDGE(dev); - memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops, + memory_region_init_io(&h->conf_mem, OBJECT(h), &pci_host_conf_le_ops, dev, "pci-conf-idx", 0x1000); - memory_region_init_io(&h->data_mem, &pci_host_data_le_ops, + memory_region_init_io(&h->data_mem, OBJECT(h), &pci_host_data_le_ops, dev, "pci-conf-data", 0x1000); sysbus_init_mmio(dev, &h->conf_mem); sysbus_init_mmio(dev, &h->data_mem); @@ -228,8 +228,8 @@ PCIBus *pci_pmac_init(qemu_irq *pic, s = SYS_BUS_DEVICE(dev); h = PCI_HOST_BRIDGE(s); d = UNI_NORTH_PCI_HOST_BRIDGE(dev); - memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL); - memory_region_init_alias(&d->pci_hole, "pci-hole", &d->pci_mmio, + memory_region_init(&d->pci_mmio, OBJECT(d), "pci-mmio", 0x100000000ULL); + memory_region_init_alias(&d->pci_hole, OBJECT(d), "pci-hole", &d->pci_mmio, 0x80000000ULL, 0x70000000ULL); memory_region_add_subregion(address_space_mem, 0x80000000ULL, &d->pci_hole); @@ -294,8 +294,8 @@ PCIBus *pci_pmac_u3_init(qemu_irq *pic, h = PCI_HOST_BRIDGE(dev); d = U3_AGP_HOST_BRIDGE(dev); - memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL); - memory_region_init_alias(&d->pci_hole, "pci-hole", &d->pci_mmio, + memory_region_init(&d->pci_mmio, OBJECT(d), "pci-mmio", 0x100000000ULL); + memory_region_init_alias(&d->pci_hole, OBJECT(d), "pci-hole", &d->pci_mmio, 0x80000000ULL, 0x70000000ULL); memory_region_add_subregion(address_space_mem, 0x80000000ULL, &d->pci_hole); diff --git a/hw/pci-host/versatile.c b/hw/pci-host/versatile.c index 2f996d954..9238d39b0 100644 --- a/hw/pci-host/versatile.c +++ b/hw/pci-host/versatile.c @@ -381,8 +381,8 @@ static void pci_vpb_init(Object *obj) PCIHostState *h = PCI_HOST_BRIDGE(obj); PCIVPBState *s = PCI_VPB(obj); - memory_region_init(&s->pci_io_space, "pci_io", 1ULL << 32); - memory_region_init(&s->pci_mem_space, "pci_mem", 1ULL << 32); + memory_region_init(&s->pci_io_space, OBJECT(s), "pci_io", 1ULL << 32); + memory_region_init(&s->pci_mem_space, OBJECT(s), "pci_mem", 1ULL << 32); pci_bus_new_inplace(&s->pci_bus, DEVICE(obj), "pci", &s->pci_mem_space, &s->pci_io_space, @@ -424,20 +424,20 @@ static void pci_vpb_realize(DeviceState *dev, Error **errp) * 3 : PCI IO window * 4..6 : PCI memory windows */ - memory_region_init_io(&s->controlregs, &pci_vpb_reg_ops, s, "pci-vpb-regs", - 0x1000); + memory_region_init_io(&s->controlregs, OBJECT(s), &pci_vpb_reg_ops, s, + "pci-vpb-regs", 0x1000); sysbus_init_mmio(sbd, &s->controlregs); - memory_region_init_io(&s->mem_config, &pci_vpb_config_ops, s, + memory_region_init_io(&s->mem_config, OBJECT(s), &pci_vpb_config_ops, s, "pci-vpb-selfconfig", 0x1000000); sysbus_init_mmio(sbd, &s->mem_config); - memory_region_init_io(&s->mem_config2, &pci_vpb_config_ops, s, + memory_region_init_io(&s->mem_config2, OBJECT(s), &pci_vpb_config_ops, s, "pci-vpb-config", 0x1000000); sysbus_init_mmio(sbd, &s->mem_config2); /* The window into I/O space is always into a fixed base address; * its size is the same for both realview and versatile. */ - memory_region_init_alias(&s->pci_io_window, "pci-vbp-io-window", + memory_region_init_alias(&s->pci_io_window, OBJECT(s), "pci-vbp-io-window", &s->pci_io_space, 0, 0x100000); sysbus_init_mmio(sbd, &s->pci_io_space); @@ -447,7 +447,7 @@ static void pci_vpb_realize(DeviceState *dev, Error **errp) * offsets are guest controllable via the IMAP registers. */ for (i = 0; i < 3; i++) { - memory_region_init_alias(&s->pci_mem_window[i], "pci-vbp-window", + memory_region_init_alias(&s->pci_mem_window[i], OBJECT(s), "pci-vbp-window", &s->pci_mem_space, 0, s->mem_win_size[i]); sysbus_init_mmio(sbd, &s->pci_mem_window[i]); } diff --git a/hw/pci/Makefile.objs b/hw/pci/Makefile.objs index a7fb9d0c1..720f438ac 100644 --- a/hw/pci/Makefile.objs +++ b/hw/pci/Makefile.objs @@ -8,4 +8,4 @@ common-obj-$(CONFIG_PCI) += pcie.o pcie_aer.o pcie_port.o common-obj-$(CONFIG_NO_PCI) += pci-stub.o common-obj-$(CONFIG_ALL) += pci-stub.o -obj-$(CONFIG_PCI_HOTPLUG) += pci-hotplug.o +common-obj-$(CONFIG_PCI_HOTPLUG_OLD) += pci-hotplug-old.o diff --git a/hw/pci/msix.c b/hw/pci/msix.c index 6da75ec69..3430770f3 100644 --- a/hw/pci/msix.c +++ b/hw/pci/msix.c @@ -280,10 +280,10 @@ int msix_init(struct PCIDevice *dev, unsigned short nentries, msix_mask_all(dev, nentries); - memory_region_init_io(&dev->msix_table_mmio, &msix_table_mmio_ops, dev, + memory_region_init_io(&dev->msix_table_mmio, OBJECT(dev), &msix_table_mmio_ops, dev, "msix-table", table_size); memory_region_add_subregion(table_bar, table_offset, &dev->msix_table_mmio); - memory_region_init_io(&dev->msix_pba_mmio, &msix_pba_mmio_ops, dev, + memory_region_init_io(&dev->msix_pba_mmio, OBJECT(dev), &msix_pba_mmio_ops, dev, "msix-pba", pba_size); memory_region_add_subregion(pba_bar, pba_offset, &dev->msix_pba_mmio); @@ -311,7 +311,7 @@ int msix_init_exclusive_bar(PCIDevice *dev, unsigned short nentries, } name = g_strdup_printf("%s-msix", dev->name); - memory_region_init(&dev->msix_exclusive_bar, name, MSIX_EXCLUSIVE_BAR_SIZE); + memory_region_init(&dev->msix_exclusive_bar, OBJECT(dev), name, MSIX_EXCLUSIVE_BAR_SIZE); g_free(name); ret = msix_init(dev, nentries, &dev->msix_exclusive_bar, bar_nr, diff --git a/hw/pci/pci-hotplug-old.c b/hw/pci/pci-hotplug-old.c new file mode 100644 index 000000000..807728975 --- /dev/null +++ b/hw/pci/pci-hotplug-old.c @@ -0,0 +1,337 @@ +/* + * Deprecated PCI hotplug interface support + * This covers the old pci_add / pci_del command, whereas the more general + * device_add / device_del commands are now preferred. + * + * Copyright (c) 2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "hw/hw.h" +#include "hw/boards.h" +#include "hw/pci/pci.h" +#include "net/net.h" +#include "hw/i386/pc.h" +#include "monitor/monitor.h" +#include "hw/scsi/scsi.h" +#include "hw/virtio/virtio-blk.h" +#include "qemu/config-file.h" +#include "sysemu/blockdev.h" +#include "qapi/error.h" + +static int pci_read_devaddr(Monitor *mon, const char *addr, + int *busp, unsigned *slotp) +{ + int dom; + + /* strip legacy tag */ + if (!strncmp(addr, "pci_addr=", 9)) { + addr += 9; + } + if (pci_parse_devaddr(addr, &dom, busp, slotp, NULL)) { + monitor_printf(mon, "Invalid pci address\n"); + return -1; + } + if (dom != 0) { + monitor_printf(mon, "Multiple PCI domains not supported, use device_add\n"); + return -1; + } + return 0; +} + +static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon, + const char *devaddr, + const char *opts_str) +{ + Error *local_err = NULL; + QemuOpts *opts; + PCIBus *root = pci_find_primary_bus(); + PCIBus *bus; + int ret, devfn; + + if (!root) { + monitor_printf(mon, "no primary PCI bus (if there are multiple" + " PCI roots, you must use device_add instead)"); + return NULL; + } + + bus = pci_get_bus_devfn(&devfn, root, devaddr); + if (!bus) { + monitor_printf(mon, "Invalid PCI device address %s\n", devaddr); + return NULL; + } + if (!((BusState*)bus)->allow_hotplug) { + monitor_printf(mon, "PCI bus doesn't support hotplug\n"); + return NULL; + } + + opts = qemu_opts_parse(qemu_find_opts("net"), opts_str ? opts_str : "", 0); + if (!opts) { + return NULL; + } + + qemu_opt_set(opts, "type", "nic"); + + ret = net_client_init(opts, 0, &local_err); + if (error_is_set(&local_err)) { + qerror_report_err(local_err); + error_free(local_err); + return NULL; + } + if (nd_table[ret].devaddr) { + monitor_printf(mon, "Parameter addr not supported\n"); + return NULL; + } + return pci_nic_init(&nd_table[ret], root, "rtl8139", devaddr); +} + +static int scsi_hot_add(Monitor *mon, DeviceState *adapter, + DriveInfo *dinfo, int printinfo) +{ + SCSIBus *scsibus; + SCSIDevice *scsidev; + + scsibus = (SCSIBus *) + object_dynamic_cast(OBJECT(QLIST_FIRST(&adapter->child_bus)), + TYPE_SCSI_BUS); + if (!scsibus) { + error_report("Device is not a SCSI adapter"); + return -1; + } + + /* + * drive_init() tries to find a default for dinfo->unit. Doesn't + * work at all for hotplug though as we assign the device to a + * specific bus instead of the first bus with spare scsi ids. + * + * Ditch the calculated value and reload from option string (if + * specified). + */ + dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1); + dinfo->bus = scsibus->busnr; + scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit, + false, -1, NULL); + if (!scsidev) { + return -1; + } + dinfo->unit = scsidev->id; + + if (printinfo) + monitor_printf(mon, "OK bus %d, unit %d\n", + scsibus->busnr, scsidev->id); + return 0; +} + +int pci_drive_hot_add(Monitor *mon, const QDict *qdict, DriveInfo *dinfo) +{ + int pci_bus; + unsigned slot; + PCIBus *root = pci_find_primary_bus(); + PCIDevice *dev; + const char *pci_addr = qdict_get_str(qdict, "pci_addr"); + + switch (dinfo->type) { + case IF_SCSI: + if (!root) { + monitor_printf(mon, "no primary PCI bus (if there are multiple" + " PCI roots, you must use device_add instead)"); + goto err; + } + if (pci_read_devaddr(mon, pci_addr, &pci_bus, &slot)) { + goto err; + } + dev = pci_find_device(root, pci_bus, PCI_DEVFN(slot, 0)); + if (!dev) { + monitor_printf(mon, "no pci device with address %s\n", pci_addr); + goto err; + } + if (scsi_hot_add(mon, &dev->qdev, dinfo, 1) != 0) { + goto err; + } + break; + default: + monitor_printf(mon, "Can't hot-add drive to type %d\n", dinfo->type); + goto err; + } + + return 0; +err: + return -1; +} + +static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon, + const char *devaddr, + const char *opts) +{ + PCIDevice *dev; + DriveInfo *dinfo = NULL; + int type = -1; + char buf[128]; + PCIBus *root = pci_find_primary_bus(); + PCIBus *bus; + int devfn; + + if (get_param_value(buf, sizeof(buf), "if", opts)) { + if (!strcmp(buf, "scsi")) + type = IF_SCSI; + else if (!strcmp(buf, "virtio")) { + type = IF_VIRTIO; + } else { + monitor_printf(mon, "type %s not a hotpluggable PCI device.\n", buf); + return NULL; + } + } else { + monitor_printf(mon, "no if= specified\n"); + return NULL; + } + + if (get_param_value(buf, sizeof(buf), "file", opts)) { + dinfo = add_init_drive(opts); + if (!dinfo) + return NULL; + if (dinfo->devaddr) { + monitor_printf(mon, "Parameter addr not supported\n"); + return NULL; + } + } else { + dinfo = NULL; + } + + if (!root) { + monitor_printf(mon, "no primary PCI bus (if there are multiple" + " PCI roots, you must use device_add instead)"); + return NULL; + } + bus = pci_get_bus_devfn(&devfn, root, devaddr); + if (!bus) { + monitor_printf(mon, "Invalid PCI device address %s\n", devaddr); + return NULL; + } + if (!((BusState*)bus)->allow_hotplug) { + monitor_printf(mon, "PCI bus doesn't support hotplug\n"); + return NULL; + } + + switch (type) { + case IF_SCSI: + dev = pci_create(bus, devfn, "lsi53c895a"); + if (qdev_init(&dev->qdev) < 0) + dev = NULL; + if (dev && dinfo) { + if (scsi_hot_add(mon, &dev->qdev, dinfo, 0) != 0) { + qdev_unplug(&dev->qdev, NULL); + dev = NULL; + } + } + break; + case IF_VIRTIO: + if (!dinfo) { + monitor_printf(mon, "virtio requires a backing file/device.\n"); + return NULL; + } + dev = pci_create(bus, devfn, "virtio-blk-pci"); + if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) { + qdev_free(&dev->qdev); + dev = NULL; + break; + } + if (qdev_init(&dev->qdev) < 0) + dev = NULL; + break; + default: + dev = NULL; + } + return dev; +} + +void pci_device_hot_add(Monitor *mon, const QDict *qdict) +{ + PCIDevice *dev = NULL; + const char *pci_addr = qdict_get_str(qdict, "pci_addr"); + const char *type = qdict_get_str(qdict, "type"); + const char *opts = qdict_get_try_str(qdict, "opts"); + + /* strip legacy tag */ + if (!strncmp(pci_addr, "pci_addr=", 9)) { + pci_addr += 9; + } + + if (!opts) { + opts = ""; + } + + if (!strcmp(pci_addr, "auto")) + pci_addr = NULL; + + if (strcmp(type, "nic") == 0) { + dev = qemu_pci_hot_add_nic(mon, pci_addr, opts); + } else if (strcmp(type, "storage") == 0) { + dev = qemu_pci_hot_add_storage(mon, pci_addr, opts); + } else { + monitor_printf(mon, "invalid type: %s\n", type); + } + + if (dev) { + monitor_printf(mon, "OK root bus %s, bus %d, slot %d, function %d\n", + pci_root_bus_path(dev), + pci_bus_num(dev->bus), PCI_SLOT(dev->devfn), + PCI_FUNC(dev->devfn)); + } else + monitor_printf(mon, "failed to add %s\n", opts); +} + +static int pci_device_hot_remove(Monitor *mon, const char *pci_addr) +{ + PCIBus *root = pci_find_primary_bus(); + PCIDevice *d; + int bus; + unsigned slot; + Error *local_err = NULL; + + if (!root) { + monitor_printf(mon, "no primary PCI bus (if there are multiple" + " PCI roots, you must use device_del instead)"); + return -1; + } + + if (pci_read_devaddr(mon, pci_addr, &bus, &slot)) { + return -1; + } + + d = pci_find_device(root, bus, PCI_DEVFN(slot, 0)); + if (!d) { + monitor_printf(mon, "slot %d empty\n", slot); + return -1; + } + + qdev_unplug(&d->qdev, &local_err); + if (error_is_set(&local_err)) { + monitor_printf(mon, "%s\n", error_get_pretty(local_err)); + error_free(local_err); + return -1; + } + + return 0; +} + +void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict) +{ + pci_device_hot_remove(mon, qdict_get_str(qdict, "pci_addr")); +} diff --git a/hw/pci/pci-hotplug.c b/hw/pci/pci-hotplug.c deleted file mode 100644 index 12287d1ef..000000000 --- a/hw/pci/pci-hotplug.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - * QEMU PCI hotplug support - * - * Copyright (c) 2004 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "hw/hw.h" -#include "hw/boards.h" -#include "hw/pci/pci.h" -#include "net/net.h" -#include "hw/i386/pc.h" -#include "monitor/monitor.h" -#include "hw/scsi/scsi.h" -#include "hw/virtio/virtio-blk.h" -#include "qemu/config-file.h" -#include "sysemu/blockdev.h" -#include "qapi/error.h" - -#if defined(TARGET_I386) -static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon, - const char *devaddr, - const char *opts_str) -{ - Error *local_err = NULL; - QemuOpts *opts; - PCIBus *bus; - int ret, devfn; - - bus = pci_get_bus_devfn(&devfn, devaddr); - if (!bus) { - monitor_printf(mon, "Invalid PCI device address %s\n", devaddr); - return NULL; - } - if (!((BusState*)bus)->allow_hotplug) { - monitor_printf(mon, "PCI bus doesn't support hotplug\n"); - return NULL; - } - - opts = qemu_opts_parse(qemu_find_opts("net"), opts_str ? opts_str : "", 0); - if (!opts) { - return NULL; - } - - qemu_opt_set(opts, "type", "nic"); - - ret = net_client_init(opts, 0, &local_err); - if (error_is_set(&local_err)) { - qerror_report_err(local_err); - error_free(local_err); - return NULL; - } - if (nd_table[ret].devaddr) { - monitor_printf(mon, "Parameter addr not supported\n"); - return NULL; - } - return pci_nic_init(&nd_table[ret], "rtl8139", devaddr); -} - -static int scsi_hot_add(Monitor *mon, DeviceState *adapter, - DriveInfo *dinfo, int printinfo) -{ - SCSIBus *scsibus; - SCSIDevice *scsidev; - - scsibus = (SCSIBus *) - object_dynamic_cast(OBJECT(QLIST_FIRST(&adapter->child_bus)), - TYPE_SCSI_BUS); - if (!scsibus) { - error_report("Device is not a SCSI adapter"); - return -1; - } - - /* - * drive_init() tries to find a default for dinfo->unit. Doesn't - * work at all for hotplug though as we assign the device to a - * specific bus instead of the first bus with spare scsi ids. - * - * Ditch the calculated value and reload from option string (if - * specified). - */ - dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1); - dinfo->bus = scsibus->busnr; - scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit, - false, -1, NULL); - if (!scsidev) { - return -1; - } - dinfo->unit = scsidev->id; - - if (printinfo) - monitor_printf(mon, "OK bus %d, unit %d\n", - scsibus->busnr, scsidev->id); - return 0; -} - -int pci_drive_hot_add(Monitor *mon, const QDict *qdict, DriveInfo *dinfo) -{ - int dom, pci_bus; - unsigned slot; - PCIDevice *dev; - const char *pci_addr = qdict_get_str(qdict, "pci_addr"); - - switch (dinfo->type) { - case IF_SCSI: - if (pci_read_devaddr(mon, pci_addr, &dom, &pci_bus, &slot)) { - goto err; - } - dev = pci_find_device(pci_find_root_bus(dom), pci_bus, - PCI_DEVFN(slot, 0)); - if (!dev) { - monitor_printf(mon, "no pci device with address %s\n", pci_addr); - goto err; - } - if (scsi_hot_add(mon, &dev->qdev, dinfo, 1) != 0) { - goto err; - } - break; - default: - monitor_printf(mon, "Can't hot-add drive to type %d\n", dinfo->type); - goto err; - } - - return 0; -err: - return -1; -} - -static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon, - const char *devaddr, - const char *opts) -{ - PCIDevice *dev; - DriveInfo *dinfo = NULL; - int type = -1; - char buf[128]; - PCIBus *bus; - int devfn; - - if (get_param_value(buf, sizeof(buf), "if", opts)) { - if (!strcmp(buf, "scsi")) - type = IF_SCSI; - else if (!strcmp(buf, "virtio")) { - type = IF_VIRTIO; - } else { - monitor_printf(mon, "type %s not a hotpluggable PCI device.\n", buf); - return NULL; - } - } else { - monitor_printf(mon, "no if= specified\n"); - return NULL; - } - - if (get_param_value(buf, sizeof(buf), "file", opts)) { - dinfo = add_init_drive(opts); - if (!dinfo) - return NULL; - if (dinfo->devaddr) { - monitor_printf(mon, "Parameter addr not supported\n"); - return NULL; - } - } else { - dinfo = NULL; - } - - bus = pci_get_bus_devfn(&devfn, devaddr); - if (!bus) { - monitor_printf(mon, "Invalid PCI device address %s\n", devaddr); - return NULL; - } - if (!((BusState*)bus)->allow_hotplug) { - monitor_printf(mon, "PCI bus doesn't support hotplug\n"); - return NULL; - } - - switch (type) { - case IF_SCSI: - dev = pci_create(bus, devfn, "lsi53c895a"); - if (qdev_init(&dev->qdev) < 0) - dev = NULL; - if (dev && dinfo) { - if (scsi_hot_add(mon, &dev->qdev, dinfo, 0) != 0) { - qdev_unplug(&dev->qdev, NULL); - dev = NULL; - } - } - break; - case IF_VIRTIO: - if (!dinfo) { - monitor_printf(mon, "virtio requires a backing file/device.\n"); - return NULL; - } - dev = pci_create(bus, devfn, "virtio-blk-pci"); - if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) { - qdev_free(&dev->qdev); - dev = NULL; - break; - } - if (qdev_init(&dev->qdev) < 0) - dev = NULL; - break; - default: - dev = NULL; - } - return dev; -} - -void pci_device_hot_add(Monitor *mon, const QDict *qdict) -{ - PCIDevice *dev = NULL; - const char *pci_addr = qdict_get_str(qdict, "pci_addr"); - const char *type = qdict_get_str(qdict, "type"); - const char *opts = qdict_get_try_str(qdict, "opts"); - - /* strip legacy tag */ - if (!strncmp(pci_addr, "pci_addr=", 9)) { - pci_addr += 9; - } - - if (!opts) { - opts = ""; - } - - if (!strcmp(pci_addr, "auto")) - pci_addr = NULL; - - if (strcmp(type, "nic") == 0) { - dev = qemu_pci_hot_add_nic(mon, pci_addr, opts); - } else if (strcmp(type, "storage") == 0) { - dev = qemu_pci_hot_add_storage(mon, pci_addr, opts); - } else { - monitor_printf(mon, "invalid type: %s\n", type); - } - - if (dev) { - monitor_printf(mon, "OK domain %d, bus %d, slot %d, function %d\n", - pci_find_domain(dev->bus), - pci_bus_num(dev->bus), PCI_SLOT(dev->devfn), - PCI_FUNC(dev->devfn)); - } else - monitor_printf(mon, "failed to add %s\n", opts); -} -#endif - -static int pci_device_hot_remove(Monitor *mon, const char *pci_addr) -{ - PCIDevice *d; - int dom, bus; - unsigned slot; - Error *local_err = NULL; - - if (pci_read_devaddr(mon, pci_addr, &dom, &bus, &slot)) { - return -1; - } - - d = pci_find_device(pci_find_root_bus(dom), bus, PCI_DEVFN(slot, 0)); - if (!d) { - monitor_printf(mon, "slot %d empty\n", slot); - return -1; - } - - qdev_unplug(&d->qdev, &local_err); - if (error_is_set(&local_err)) { - monitor_printf(mon, "%s\n", error_get_pretty(local_err)); - error_free(local_err); - return -1; - } - - return 0; -} - -void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict) -{ - pci_device_hot_remove(mon, qdict_get_str(qdict, "pci_addr")); -} diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 61b681a91..dcc85ef0a 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -25,6 +25,7 @@ #include "hw/pci/pci.h" #include "hw/pci/pci_bridge.h" #include "hw/pci/pci_bus.h" +#include "hw/pci/pci_host.h" #include "monitor/monitor.h" #include "net/net.h" #include "sysemu/sysemu.h" @@ -89,12 +90,7 @@ static void pci_del_option_rom(PCIDevice *pdev); static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET; static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU; -struct PCIHostBus { - int domain; - struct PCIBus *bus; - QLIST_ENTRY(PCIHostBus) next; -}; -static QLIST_HEAD(, PCIHostBus) host_buses; +static QLIST_HEAD(, PCIHostState) pci_host_bridges; static const VMStateDescription vmstate_pcibus = { .name = "PCIBUS", @@ -237,46 +233,54 @@ static int pcibus_reset(BusState *qbus) return 1; } -static void pci_host_bus_register(int domain, PCIBus *bus) +static void pci_host_bus_register(PCIBus *bus, DeviceState *parent) { - struct PCIHostBus *host; - host = g_malloc0(sizeof(*host)); - host->domain = domain; - host->bus = bus; - QLIST_INSERT_HEAD(&host_buses, host, next); + PCIHostState *host_bridge = PCI_HOST_BRIDGE(parent); + + QLIST_INSERT_HEAD(&pci_host_bridges, host_bridge, next); } -PCIBus *pci_find_root_bus(int domain) +PCIBus *pci_find_primary_bus(void) { - struct PCIHostBus *host; + PCIBus *primary_bus = NULL; + PCIHostState *host; - QLIST_FOREACH(host, &host_buses, next) { - if (host->domain == domain) { - return host->bus; + QLIST_FOREACH(host, &pci_host_bridges, next) { + if (primary_bus) { + /* We have multiple root buses, refuse to select a primary */ + return NULL; } + primary_bus = host->bus; } - return NULL; + return primary_bus; } -int pci_find_domain(const PCIBus *bus) +PCIBus *pci_device_root_bus(const PCIDevice *d) { - PCIDevice *d; - struct PCIHostBus *host; + PCIBus *bus = d->bus; - /* obtain root bus */ while ((d = bus->parent_dev) != NULL) { bus = d->bus; } - QLIST_FOREACH(host, &host_buses, next) { - if (host->bus == bus) { - return host->domain; - } + return bus; +} + +const char *pci_root_bus_path(PCIDevice *dev) +{ + PCIBus *rootbus = pci_device_root_bus(dev); + PCIHostState *host_bridge = PCI_HOST_BRIDGE(rootbus->qbus.parent); + PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_GET_CLASS(host_bridge); + + assert(!rootbus->parent_dev); + assert(host_bridge->bus == rootbus); + + if (hc->root_bus_path) { + return (*hc->root_bus_path)(host_bridge, rootbus); } - abort(); /* should not be reached */ - return -1; + return rootbus->qbus.name; } static void pci_bus_init(PCIBus *bus, DeviceState *parent, @@ -292,7 +296,8 @@ static void pci_bus_init(PCIBus *bus, DeviceState *parent, /* host bridge */ QLIST_INIT(&bus->child); - pci_host_bus_register(0, bus); /* for now only pci domain 0 is supported */ + + pci_host_bus_register(bus, parent); vmstate_register(NULL, -1, &vmstate_pcibus, bus); } @@ -522,7 +527,7 @@ static void pci_set_default_subsystem_id(PCIDevice *pci_dev) * Parse [[:]:], return -1 on error if funcp == NULL * [[:]:]., return -1 on error */ -static int pci_parse_devaddr(const char *addr, int *domp, int *busp, +int pci_parse_devaddr(const char *addr, int *domp, int *busp, unsigned int *slotp, unsigned int *funcp) { const char *p; @@ -581,36 +586,34 @@ static int pci_parse_devaddr(const char *addr, int *domp, int *busp, return 0; } -int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp, - unsigned *slotp) -{ - /* strip legacy tag */ - if (!strncmp(addr, "pci_addr=", 9)) { - addr += 9; - } - if (pci_parse_devaddr(addr, domp, busp, slotp, NULL)) { - monitor_printf(mon, "Invalid pci address\n"); - return -1; - } - return 0; -} - -PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr) +PCIBus *pci_get_bus_devfn(int *devfnp, PCIBus *root, const char *devaddr) { int dom, bus; unsigned slot; + assert(!root->parent_dev); + + if (!root) { + fprintf(stderr, "No primary PCI bus\n"); + return NULL; + } + if (!devaddr) { *devfnp = -1; - return pci_find_bus_nr(pci_find_root_bus(0), 0); + return pci_find_bus_nr(root, 0); } if (pci_parse_devaddr(devaddr, &dom, &bus, &slot, NULL) < 0) { return NULL; } + if (dom != 0) { + fprintf(stderr, "No support for non-zero PCI domains\n"); + return NULL; + } + *devfnp = PCI_DEVFN(slot, 0); - return pci_find_bus_nr(pci_find_root_bus(dom), bus); + return pci_find_bus_nr(root, bus); } static void pci_init_cmask(PCIDevice *dev) @@ -811,7 +814,8 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus, dma_as = &address_space_memory; } - memory_region_init_alias(&pci_dev->bus_master_enable_region, "bus master", + memory_region_init_alias(&pci_dev->bus_master_enable_region, + OBJECT(pci_dev), "bus master", dma_as->root, 0, memory_region_size(dma_as->root)); memory_region_set_enabled(&pci_dev->bus_master_enable_region, false); address_space_init(&pci_dev->bus_master_as, &pci_dev->bus_master_enable_region, @@ -1525,11 +1529,11 @@ static PciInfo *qmp_query_pci_bus(PCIBus *bus, int bus_num) PciInfoList *qmp_query_pci(Error **errp) { PciInfoList *info, *head = NULL, *cur_item = NULL; - struct PCIHostBus *host; + PCIHostState *host_bridge; - QLIST_FOREACH(host, &host_buses, next) { + QLIST_FOREACH(host_bridge, &pci_host_bridges, next) { info = g_malloc0(sizeof(*info)); - info->value = qmp_query_pci_bus(host->bus, 0); + info->value = qmp_query_pci_bus(host_bridge->bus, 0); /* XXX: waiting for the qapi to support GSList */ if (!cur_item) { @@ -1569,7 +1573,8 @@ static const char * const pci_nic_names[] = { /* Initialize a PCI NIC. */ /* FIXME callers should check for failure, but don't */ -PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model, +PCIDevice *pci_nic_init(NICInfo *nd, PCIBus *rootbus, + const char *default_model, const char *default_devaddr) { const char *devaddr = nd->devaddr ? nd->devaddr : default_devaddr; @@ -1583,7 +1588,7 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model, if (i < 0) return NULL; - bus = pci_get_bus_devfn(&devfn, devaddr); + bus = pci_get_bus_devfn(&devfn, rootbus, devaddr); if (!bus) { error_report("Invalid PCI device address %s for device %s", devaddr, pci_nic_names[i]); @@ -1598,7 +1603,8 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model, return pci_dev; } -PCIDevice *pci_nic_init_nofail(NICInfo *nd, const char *default_model, +PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus, + const char *default_model, const char *default_devaddr) { PCIDevice *res; @@ -1606,7 +1612,7 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, const char *default_model, if (qemu_show_nic_models(nd->model, pci_nic_models)) exit(0); - res = pci_nic_init(nd, default_model, default_devaddr); + res = pci_nic_init(nd, rootbus, default_model, default_devaddr); if (!res) exit(1); return res; @@ -1945,7 +1951,7 @@ static int pci_add_option_rom(PCIDevice *pdev, bool is_default_rom) snprintf(name, sizeof(name), "%s.rom", object_get_typename(OBJECT(pdev))); } pdev->has_rom = true; - memory_region_init_ram(&pdev->rom, name, size); + memory_region_init_ram(&pdev->rom, OBJECT(pdev), name, size); vmstate_register_ram(&pdev->rom, &pdev->qdev); ptr = memory_region_get_ram_ptr(&pdev->rom); load_image(path, ptr); @@ -1997,10 +2003,10 @@ int pci_add_capability(PCIDevice *pdev, uint8_t cap_id, for (i = offset; i < offset + size; i++) { overlapping_cap = pci_find_capability_at_offset(pdev, i); if (overlapping_cap) { - fprintf(stderr, "ERROR: %04x:%02x:%02x.%x " + fprintf(stderr, "ERROR: %s:%02x:%02x.%x " "Attempt to add PCI capability %x at offset " "%x overlaps existing capability %x at offset %x\n", - pci_find_domain(pdev->bus), pci_bus_num(pdev->bus), + pci_root_bus_path(pdev), pci_bus_num(pdev->bus), PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), cap_id, offset, overlapping_cap, i); return -EINVAL; @@ -2134,30 +2140,30 @@ static char *pcibus_get_dev_path(DeviceState *dev) * domain:Bus:Slot.Func for systems without nested PCI bridges. * Slot.Function list specifies the slot and function numbers for all * devices on the path from root to the specific device. */ - char domain[] = "DDDD:00"; + const char *root_bus_path; + int root_bus_len; char slot[] = ":SS.F"; - int domain_len = sizeof domain - 1 /* For '\0' */; int slot_len = sizeof slot - 1 /* For '\0' */; int path_len; char *path, *p; int s; + root_bus_path = pci_root_bus_path(d); + root_bus_len = strlen(root_bus_path); + /* Calculate # of slots on path between device and root. */; slot_depth = 0; for (t = d; t; t = t->bus->parent_dev) { ++slot_depth; } - path_len = domain_len + slot_len * slot_depth; + path_len = root_bus_len + slot_len * slot_depth; /* Allocate memory, fill in the terminating null byte. */ path = g_malloc(path_len + 1 /* For '\0' */); path[path_len] = '\0'; - /* First field is the domain. */ - s = snprintf(domain, sizeof domain, "%04x:00", pci_find_domain(d->bus)); - assert(s == domain_len); - memcpy(path, domain, domain_len); + memcpy(path, root_bus_path, root_bus_len); /* Fill in slot numbers. We walk up from device to root, so need to print * them in the reverse order, last to first. */ @@ -2191,11 +2197,11 @@ static int pci_qdev_find_recursive(PCIBus *bus, int pci_qdev_find_device(const char *id, PCIDevice **pdev) { - struct PCIHostBus *host; + PCIHostState *host_bridge; int rc = -ENODEV; - QLIST_FOREACH(host, &host_buses, next) { - int tmp = pci_qdev_find_recursive(host->bus, id, pdev); + QLIST_FOREACH(host_bridge, &pci_host_bridges, next) { + int tmp = pci_qdev_find_recursive(host_bridge->bus, id, pdev); if (!tmp) { rc = 0; break; diff --git a/hw/pci/pci_bridge.c b/hw/pci/pci_bridge.c index 24be6c506..ecdeab0d5 100644 --- a/hw/pci/pci_bridge.c +++ b/hw/pci/pci_bridge.c @@ -147,7 +147,7 @@ static void pci_bridge_init_alias(PCIBridge *bridge, MemoryRegion *alias, * Apparently no way to do this with existing memory APIs. */ pcibus_t size = enabled && limit >= base ? limit + 1 - base : 0; - memory_region_init_alias(alias, name, space, base, size); + memory_region_init_alias(alias, OBJECT(bridge), name, space, base, size); memory_region_add_subregion_overlap(parent_space, base, alias, 1); } @@ -156,13 +156,13 @@ static void pci_bridge_init_vga_aliases(PCIBridge *br, PCIBus *parent, { uint16_t brctl = pci_get_word(br->dev.config + PCI_BRIDGE_CONTROL); - memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_IO_LO], + memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_IO_LO], OBJECT(br), "pci_bridge_vga_io_lo", &br->address_space_io, QEMU_PCI_VGA_IO_LO_BASE, QEMU_PCI_VGA_IO_LO_SIZE); - memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_IO_HI], + memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_IO_HI], OBJECT(br), "pci_bridge_vga_io_hi", &br->address_space_io, QEMU_PCI_VGA_IO_HI_BASE, QEMU_PCI_VGA_IO_HI_SIZE); - memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_MEM], + memory_region_init_alias(&alias_vga[QEMU_PCI_VGA_MEM], OBJECT(br), "pci_bridge_vga_mem", &br->address_space_mem, QEMU_PCI_VGA_MEM_BASE, QEMU_PCI_VGA_MEM_SIZE); @@ -367,9 +367,9 @@ int pci_bridge_initfn(PCIDevice *dev, const char *typename) sec_bus->parent_dev = dev; sec_bus->map_irq = br->map_irq ? br->map_irq : pci_swizzle_map_irq_fn; sec_bus->address_space_mem = &br->address_space_mem; - memory_region_init(&br->address_space_mem, "pci_bridge_pci", INT64_MAX); + memory_region_init(&br->address_space_mem, OBJECT(br), "pci_bridge_pci", INT64_MAX); sec_bus->address_space_io = &br->address_space_io; - memory_region_init(&br->address_space_io, "pci_bridge_io", 65536); + memory_region_init(&br->address_space_io, OBJECT(br), "pci_bridge_io", 65536); br->windows = pci_bridge_region_init(br); QLIST_INIT(&sec_bus->child); QLIST_INSERT_HEAD(&parent->child, sec_bus, sibling); diff --git a/hw/pci/pci_host.c b/hw/pci/pci_host.c index 12254b18a..7dd9b2560 100644 --- a/hw/pci/pci_host.c +++ b/hw/pci/pci_host.c @@ -169,6 +169,7 @@ static const TypeInfo pci_host_type_info = { .name = TYPE_PCI_HOST_BRIDGE, .parent = TYPE_SYS_BUS_DEVICE, .abstract = true, + .class_size = sizeof(PCIHostBridgeClass), .instance_size = sizeof(PCIHostState), }; diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c index 1ce72ce94..ca762ab09 100644 --- a/hw/pci/pcie_aer.c +++ b/hw/pci/pcie_aer.c @@ -817,9 +817,9 @@ void pcie_aer_inject_error_print(Monitor *mon, const QObject *data) qdict = qobject_to_qdict(data); devfn = (int)qdict_get_int(qdict, "devfn"); - monitor_printf(mon, "OK id: %s domain: %x, bus: %x devfn: %x.%x\n", + monitor_printf(mon, "OK id: %s root bus: %s, bus: %x devfn: %x.%x\n", qdict_get_str(qdict, "id"), - (int) qdict_get_int(qdict, "domain"), + qdict_get_str(qdict, "root_bus"), (int) qdict_get_int(qdict, "bus"), PCI_SLOT(devfn), PCI_FUNC(devfn)); } @@ -1020,10 +1020,9 @@ int do_pcie_aer_inject_error(Monitor *mon, ret = pcie_aer_inject_error(dev, &err); *ret_data = qobject_from_jsonf("{'id': %s, " - "'domain': %d, 'bus': %d, 'devfn': %d, " + "'root_bus': %s, 'bus': %d, 'devfn': %d, " "'ret': %d}", - id, - pci_find_domain(dev->bus), + id, pci_root_bus_path(dev), pci_bus_num(dev->bus), dev->devfn, ret); assert(*ret_data); diff --git a/hw/pci/pcie_host.c b/hw/pci/pcie_host.c index b2d942bce..b70e5adc4 100644 --- a/hw/pci/pcie_host.c +++ b/hw/pci/pcie_host.c @@ -130,7 +130,8 @@ void pcie_host_mmcfg_map(PCIExpressHost *e, hwaddr addr, assert(size >= PCIE_MMCFG_SIZE_MIN); assert(size <= PCIE_MMCFG_SIZE_MAX); e->size = size; - memory_region_init_io(&e->mmio, &pcie_mmcfg_ops, e, "pcie-mmcfg", e->size); + memory_region_init_io(&e->mmio, OBJECT(e), &pcie_mmcfg_ops, e, + "pcie-mmcfg", e->size); e->base_addr = addr; memory_region_add_subregion(get_system_memory(), e->base_addr, &e->mmio); } diff --git a/hw/pci/shpc.c b/hw/pci/shpc.c index d35c2ee96..eb092fdb6 100644 --- a/hw/pci/shpc.c +++ b/hw/pci/shpc.c @@ -612,8 +612,8 @@ int shpc_init(PCIDevice *d, PCIBus *sec_bus, MemoryRegion *bar, unsigned offset) } /* TODO: init cmask */ - memory_region_init_io(&shpc->mmio, &shpc_mmio_ops, d, "shpc-mmio", - SHPC_SIZEOF(d)); + memory_region_init_io(&shpc->mmio, OBJECT(d), &shpc_mmio_ops, + d, "shpc-mmio", SHPC_SIZEOF(d)); shpc_cap_update_dword(d); memory_region_add_subregion(bar, offset, &shpc->mmio); pci_bus_hotplug(sec_bus, shpc_device_hotplug, &d->qdev); diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs index be00d1da3..7a1cd5d89 100644 --- a/hw/ppc/Makefile.objs +++ b/hw/ppc/Makefile.objs @@ -1,7 +1,7 @@ # shared objects obj-y += ppc.o ppc_booke.o # IBM pSeries (sPAPR) -obj-$(CONFIG_PSERIES) += spapr.o xics.o spapr_vio.o spapr_events.o +obj-$(CONFIG_PSERIES) += spapr.o spapr_vio.o spapr_events.o obj-$(CONFIG_PSERIES) += spapr_hcall.o spapr_iommu.o spapr_rtas.o obj-$(CONFIG_PSERIES) += spapr_pci.o # PowerPC 4xx boards diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c index 38f799031..f00a62a1c 100644 --- a/hw/ppc/e500.c +++ b/hw/ppc/e500.c @@ -137,7 +137,6 @@ static int ppce500_load_device_tree(CPUPPCState *env, uint32_t clock_freq = 400000000; uint32_t tb_freq = 400000000; int i; - const char *toplevel_compat = NULL; /* user override */ char compatible_sb[] = "fsl,mpc8544-immr\0simple-bus"; char soc[128]; char mpic[128]; @@ -158,14 +157,9 @@ static int ppce500_load_device_tree(CPUPPCState *env, 0x0, 0xe1000000, 0x0, 0x10000, }; - QemuOpts *machine_opts; - const char *dtb_file = NULL; - - machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); - if (machine_opts) { - dtb_file = qemu_opt_get(machine_opts, "dtb"); - toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible"); - } + QemuOpts *machine_opts = qemu_get_machine_opts(); + const char *dtb_file = qemu_opt_get(machine_opts, "dtb"); + const char *toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible"); if (dtb_file) { char *filename; @@ -500,7 +494,6 @@ static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params, qemu_irq **irqs) { DeviceState *dev; - CPUPPCState *env; CPUState *cs; int r; @@ -512,9 +505,7 @@ static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params, return NULL; } - for (env = first_cpu; env != NULL; env = env->next_cpu) { - cs = ENV_GET_CPU(env); - + for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) { if (kvm_openpic_connect_vcpu(dev, cs)) { fprintf(stderr, "%s: failed to connect vcpu to irqchip\n", __func__); @@ -528,7 +519,6 @@ static DeviceState *ppce500_init_mpic_kvm(PPCE500Params *params, static qemu_irq *ppce500_init_mpic(PPCE500Params *params, MemoryRegion *ccsr, qemu_irq **irqs) { - QemuOptsList *list; qemu_irq *mpic; DeviceState *dev = NULL; SysBusDevice *s; @@ -537,15 +527,11 @@ static qemu_irq *ppce500_init_mpic(PPCE500Params *params, MemoryRegion *ccsr, mpic = g_new(qemu_irq, 256); if (kvm_enabled()) { - bool irqchip_allowed = true, irqchip_required = false; - - list = qemu_find_opts("machine"); - if (!QTAILQ_EMPTY(&list->head)) { - irqchip_allowed = qemu_opt_get_bool(QTAILQ_FIRST(&list->head), + QemuOpts *machine_opts = qemu_get_machine_opts(); + bool irqchip_allowed = qemu_opt_get_bool(machine_opts, "kernel_irqchip", true); - irqchip_required = qemu_opt_get_bool(QTAILQ_FIRST(&list->head), - "kernel_irqchip", false); - } + bool irqchip_required = qemu_opt_get_bool(machine_opts, + "kernel_irqchip", false); if (irqchip_allowed) { dev = ppce500_init_mpic_kvm(params, irqs); @@ -651,7 +637,7 @@ void ppce500_init(PPCE500Params *params) params->ram_size = ram_size; /* Register Memory */ - memory_region_init_ram(ram, "mpc8544ds.ram", ram_size); + memory_region_init_ram(ram, NULL, "mpc8544ds.ram", ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(address_space_mem, 0, ram); @@ -707,7 +693,7 @@ void ppce500_init(PPCE500Params *params) if (pci_bus) { /* Register network interfaces. */ for (i = 0; i < nb_nics; i++) { - pci_nic_init_nofail(&nd_table[i], "virtio", NULL); + pci_nic_init_nofail(&nd_table[i], pci_bus, "virtio", NULL); } } @@ -783,7 +769,7 @@ static int e500_ccsr_initfn(SysBusDevice *dev) PPCE500CCSRState *ccsr; ccsr = CCSR(dev); - memory_region_init(&ccsr->ccsr_space, "e500-ccsr", + memory_region_init(&ccsr->ccsr_space, OBJECT(ccsr), "e500-ccsr", MPC8544_CCSRBAR_SIZE); return 0; } diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h index 54efaed62..1e578dd59 100644 --- a/hw/ppc/mac.h +++ b/hw/ppc/mac.h @@ -131,6 +131,9 @@ typedef struct MACIOIDEState { MemoryRegion mem; IDEBus bus; BlockDriverAIOCB *aiocb; + IDEDMA dma; + void *dbdma; + bool dma_active; } MACIOIDEState; void macio_ide_init_drives(MACIOIDEState *ide, DriveInfo **hd_table); diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c index 3badfa3ad..fe803480a 100644 --- a/hw/ppc/mac_newworld.c +++ b/hw/ppc/mac_newworld.c @@ -71,6 +71,7 @@ #define MAX_IDE_BUS 2 #define CFG_ADDR 0xf0000510 +#define TBFREQ (100UL * 1000UL * 1000UL) /* debug UniNorth */ //#define DEBUG_UNIN @@ -191,17 +192,17 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) env = &cpu->env; /* Set time-base frequency to 100 Mhz */ - cpu_ppc_tb_init(env, 100UL * 1000UL * 1000UL); + cpu_ppc_tb_init(env, TBFREQ); qemu_register_reset(ppc_core99_reset, cpu); } /* allocate RAM */ - memory_region_init_ram(ram, "ppc_core99.ram", ram_size); + memory_region_init_ram(ram, NULL, "ppc_core99.ram", ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(get_system_memory(), 0, ram); /* allocate and load BIOS */ - memory_region_init_ram(bios, "ppc_core99.bios", BIOS_SIZE); + memory_region_init_ram(bios, NULL, "ppc_core99.bios", BIOS_SIZE); vmstate_register_ram_global(bios); if (bios_name == NULL) bios_name = PROM_FILENAME; @@ -290,10 +291,10 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) isa_mmio_init(0xf2000000, 0x00800000); /* UniN init: XXX should be a real device */ - memory_region_init_io(unin_memory, &unin_ops, token, "unin", 0x1000); + memory_region_init_io(unin_memory, NULL, &unin_ops, token, "unin", 0x1000); memory_region_add_subregion(get_system_memory(), 0xf8000000, unin_memory); - memory_region_init_io(unin2_memory, &unin_ops, token, "unin", 0x1000); + memory_region_init_io(unin2_memory, NULL, &unin_ops, token, "unin", 0x1000); memory_region_add_subregion(get_system_memory(), 0xf3000000, unin2_memory); openpic_irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *)); @@ -371,11 +372,11 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) escc_mem = escc_init(0, pic[0x25], pic[0x24], serial_hds[0], serial_hds[1], ESCC_CLOCK, 4); - memory_region_init_alias(escc_bar, "escc-bar", + memory_region_init_alias(escc_bar, NULL, "escc-bar", escc_mem, 0, memory_region_size(escc_mem)); for(i = 0; i < nb_nics; i++) - pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL); + pci_nic_init_nofail(&nd_table[i], pci_bus, "ne2k_pci", NULL); ide_drive_get(hd, MAX_IDE_BUS); @@ -460,7 +461,7 @@ static void ppc_core99_init(QEMUMachineInitArgs *args) fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid()); #endif } else { - fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, get_ticks_per_sec()); + fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, TBFREQ); } /* Mac OS X requires a "known good" clock-frequency value; pass it one. */ fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CLOCKFREQ, 266000000); diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c index 8faff300f..8b8c6b93a 100644 --- a/hw/ppc/mac_oldworld.c +++ b/hw/ppc/mac_oldworld.c @@ -45,6 +45,7 @@ #define MAX_IDE_BUS 2 #define CFG_ADDR 0xf0000510 +#define TBFREQ 16600000UL static int fw_cfg_boot_set(void *opaque, const char *boot_device) { @@ -114,7 +115,7 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) env = &cpu->env; /* Set time-base frequency to 16.6 Mhz */ - cpu_ppc_tb_init(env, 16600000UL); + cpu_ppc_tb_init(env, TBFREQ); qemu_register_reset(ppc_heathrow_reset, cpu); } @@ -126,12 +127,12 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) exit(1); } - memory_region_init_ram(ram, "ppc_heathrow.ram", ram_size); + memory_region_init_ram(ram, NULL, "ppc_heathrow.ram", ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(sysmem, 0, ram); /* allocate and load BIOS */ - memory_region_init_ram(bios, "ppc_heathrow.bios", BIOS_SIZE); + memory_region_init_ram(bios, NULL, "ppc_heathrow.bios", BIOS_SIZE); vmstate_register_ram_global(bios); if (bios_name == NULL) bios_name = PROM_FILENAME; @@ -255,11 +256,11 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) escc_mem = escc_init(0, pic[0x0f], pic[0x10], serial_hds[0], serial_hds[1], ESCC_CLOCK, 4); - memory_region_init_alias(escc_bar, "escc-bar", + memory_region_init_alias(escc_bar, NULL, "escc-bar", escc_mem, 0, memory_region_size(escc_mem)); for(i = 0; i < nb_nics; i++) - pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL); + pci_nic_init_nofail(&nd_table[i], pci_bus, "ne2k_pci", NULL); ide_drive_get(hd, MAX_IDE_BUS); @@ -267,20 +268,19 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) macio = pci_create(pci_bus, -1, TYPE_OLDWORLD_MACIO); dev = DEVICE(macio); qdev_connect_gpio_out(dev, 0, pic[0x12]); /* CUDA */ - qdev_connect_gpio_out(dev, 1, pic[0x0D]); /* IDE */ - qdev_connect_gpio_out(dev, 2, pic[0x02]); /* IDE DMA */ + qdev_connect_gpio_out(dev, 1, pic[0x0D]); /* IDE-0 */ + qdev_connect_gpio_out(dev, 2, pic[0x02]); /* IDE-0 DMA */ + qdev_connect_gpio_out(dev, 3, pic[0x0E]); /* IDE-1 */ + qdev_connect_gpio_out(dev, 4, pic[0x03]); /* IDE-1 DMA */ macio_init(macio, pic_mem, escc_bar); - /* First IDE channel is a MAC IDE on the MacIO bus */ macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), - "ide")); + "ide[0]")); macio_ide_init_drives(macio_ide, hd); - /* Second IDE channel is a CMD646 on the PCI bus */ - hd[0] = hd[MAX_IDE_DEVS]; - hd[1] = hd[MAX_IDE_DEVS + 1]; - hd[3] = hd[2] = NULL; - pci_cmd646_ide_init(pci_bus, hd, 0); + macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), + "ide[1]")); + macio_ide_init_drives(macio_ide, &hd[MAX_IDE_DEVS]); dev = DEVICE(object_resolve_path_component(OBJECT(macio), "cuda")); adb_bus = qdev_get_child_bus(dev, "adb.0"); @@ -331,7 +331,7 @@ static void ppc_heathrow_init(QEMUMachineInitArgs *args) fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid()); #endif } else { - fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, get_ticks_per_sec()); + fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, TBFREQ); } /* Mac OS X requires a "known good" clock-frequency value; pass it one. */ fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CLOCKFREQ, 266000000); diff --git a/hw/ppc/mpc8544_guts.c b/hw/ppc/mpc8544_guts.c index d41f61552..a10abe978 100644 --- a/hw/ppc/mpc8544_guts.c +++ b/hw/ppc/mpc8544_guts.c @@ -68,7 +68,8 @@ static uint64_t mpc8544_guts_read(void *opaque, hwaddr addr, unsigned size) { uint32_t value = 0; - CPUPPCState *env = cpu_single_env; + PowerPCCPU *cpu = POWERPC_CPU(current_cpu); + CPUPPCState *env = &cpu->env; addr &= MPC8544_GUTS_MMIO_SIZE - 1; switch (addr) { @@ -119,7 +120,7 @@ static void mpc8544_guts_initfn(Object *obj) SysBusDevice *d = SYS_BUS_DEVICE(obj); GutsState *s = MPC8544_GUTS(obj); - memory_region_init_io(&s->iomem, &mpc8544_guts_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &mpc8544_guts_ops, s, "mpc8544.guts", MPC8544_GUTS_MMIO_SIZE); sysbus_init_mmio(d, &s->iomem); } diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c index fb57b42ea..e1c095c7e 100644 --- a/hw/ppc/ppc.c +++ b/hw/ppc/ppc.c @@ -23,6 +23,7 @@ */ #include "hw/hw.h" #include "hw/ppc/ppc.h" +#include "hw/ppc/ppc_e500.h" #include "qemu/timer.h" #include "sysemu/sysemu.h" #include "hw/timer/m48t59.h" @@ -440,15 +441,14 @@ void ppce500_irq_init(CPUPPCState *env) /* Enable or Disable the E500 EPR capability */ void ppce500_set_mpic_proxy(bool enabled) { - CPUPPCState *env; + CPUState *cs; - for (env = first_cpu; env != NULL; env = env->next_cpu) { - PowerPCCPU *cpu = ppc_env_get_cpu(env); - CPUState *cs = CPU(cpu); + for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) { + PowerPCCPU *cpu = POWERPC_CPU(cs); - env->mpic_proxy = enabled; + cpu->env.mpic_proxy = enabled; if (kvm_enabled()) { - kvmppc_set_mpic_proxy(POWERPC_CPU(cs), enabled); + kvmppc_set_mpic_proxy(cpu, enabled); } } } diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c index f0c7ee9ab..f74e5e52c 100644 --- a/hw/ppc/ppc405_boards.c +++ b/hw/ppc/ppc405_boards.c @@ -164,7 +164,7 @@ static void ref405ep_fpga_init(MemoryRegion *sysmem, uint32_t base) MemoryRegion *fpga_memory = g_new(MemoryRegion, 1); fpga = g_malloc0(sizeof(ref405ep_fpga_t)); - memory_region_init_io(fpga_memory, &ref405ep_fpga_ops, fpga, + memory_region_init_io(fpga_memory, NULL, &ref405ep_fpga_ops, fpga, "fpga", 0x00000100); memory_region_add_subregion(sysmem, base, fpga_memory); qemu_register_reset(&ref405ep_fpga_reset, fpga); @@ -197,11 +197,11 @@ static void ref405ep_init(QEMUMachineInitArgs *args) MemoryRegion *sysmem = get_system_memory(); /* XXX: fix this */ - memory_region_init_ram(&ram_memories[0], "ef405ep.ram", 0x08000000); + memory_region_init_ram(&ram_memories[0], NULL, "ef405ep.ram", 0x08000000); vmstate_register_ram_global(&ram_memories[0]); ram_bases[0] = 0; ram_sizes[0] = 0x08000000; - memory_region_init(&ram_memories[1], "ef405ep.ram1", 0); + memory_region_init(&ram_memories[1], NULL, "ef405ep.ram1", 0); ram_bases[1] = 0x00000000; ram_sizes[1] = 0x00000000; ram_size = 128 * 1024 * 1024; @@ -212,7 +212,7 @@ static void ref405ep_init(QEMUMachineInitArgs *args) 33333333, &pic, kernel_filename == NULL ? 0 : 1); /* allocate SRAM */ sram_size = 512 * 1024; - memory_region_init_ram(sram, "ef405ep.sram", sram_size); + memory_region_init_ram(sram, NULL, "ef405ep.sram", sram_size); vmstate_register_ram_global(sram); memory_region_add_subregion(sysmem, 0xFFF00000, sram); /* allocate and load BIOS */ @@ -244,7 +244,7 @@ static void ref405ep_init(QEMUMachineInitArgs *args) printf("Load BIOS from file\n"); #endif bios = g_new(MemoryRegion, 1); - memory_region_init_ram(bios, "ef405ep.bios", BIOS_SIZE); + memory_region_init_ram(bios, NULL, "ef405ep.bios", BIOS_SIZE); vmstate_register_ram_global(bios); if (bios_name == NULL) bios_name = BIOS_FILENAME; @@ -490,7 +490,7 @@ static void taihu_cpld_init(MemoryRegion *sysmem, uint32_t base) MemoryRegion *cpld_memory = g_new(MemoryRegion, 1); cpld = g_malloc0(sizeof(taihu_cpld_t)); - memory_region_init_io(cpld_memory, &taihu_cpld_ops, cpld, "cpld", 0x100); + memory_region_init_io(cpld_memory, NULL, &taihu_cpld_ops, cpld, "cpld", 0x100); memory_region_add_subregion(sysmem, base, cpld_memory); qemu_register_reset(&taihu_cpld_reset, cpld); } @@ -514,12 +514,12 @@ static void taihu_405ep_init(QEMUMachineInitArgs *args) DriveInfo *dinfo; /* RAM is soldered to the board so the size cannot be changed */ - memory_region_init_ram(&ram_memories[0], + memory_region_init_ram(&ram_memories[0], NULL, "taihu_405ep.ram-0", 0x04000000); vmstate_register_ram_global(&ram_memories[0]); ram_bases[0] = 0; ram_sizes[0] = 0x04000000; - memory_region_init_ram(&ram_memories[1], + memory_region_init_ram(&ram_memories[1], NULL, "taihu_405ep.ram-1", 0x04000000); vmstate_register_ram_global(&ram_memories[1]); ram_bases[1] = 0x04000000; @@ -563,7 +563,7 @@ static void taihu_405ep_init(QEMUMachineInitArgs *args) if (bios_name == NULL) bios_name = BIOS_FILENAME; bios = g_new(MemoryRegion, 1); - memory_region_init_ram(bios, "taihu_405ep.bios", BIOS_SIZE); + memory_region_init_ram(bios, NULL, "taihu_405ep.bios", BIOS_SIZE); vmstate_register_ram_global(bios); filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (filename) { diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index c6c909e05..290f71ab6 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -390,7 +390,7 @@ static void ppc4xx_opba_init(hwaddr base) #ifdef DEBUG_OPBA printf("%s: offset " TARGET_FMT_plx "\n", __func__, base); #endif - memory_region_init_io(&opba->io, &opba_ops, opba, "opba", 0x002); + memory_region_init_io(&opba->io, NULL, &opba_ops, opba, "opba", 0x002); memory_region_add_subregion(get_system_memory(), base, &opba->io); qemu_register_reset(ppc4xx_opba_reset, opba); } @@ -812,7 +812,7 @@ static void ppc405_gpio_init(hwaddr base) #ifdef DEBUG_GPIO printf("%s: offset " TARGET_FMT_plx "\n", __func__, base); #endif - memory_region_init_io(&gpio->io, &ppc405_gpio_ops, gpio, "pgio", 0x038); + memory_region_init_io(&gpio->io, NULL, &ppc405_gpio_ops, gpio, "pgio", 0x038); memory_region_add_subregion(get_system_memory(), base, &gpio->io); qemu_register_reset(&ppc405_gpio_reset, gpio); } @@ -972,9 +972,9 @@ static void ppc405_ocm_init(CPUPPCState *env) ocm = g_malloc0(sizeof(ppc405_ocm_t)); /* XXX: Size is 4096 or 0x04000000 */ - memory_region_init_ram(&ocm->isarc_ram, "ppc405.ocm", 4096); + memory_region_init_ram(&ocm->isarc_ram, NULL, "ppc405.ocm", 4096); vmstate_register_ram_global(&ocm->isarc_ram); - memory_region_init_alias(&ocm->dsarc_ram, "ppc405.dsarc", &ocm->isarc_ram, + memory_region_init_alias(&ocm->dsarc_ram, NULL, "ppc405.dsarc", &ocm->isarc_ram, 0, 4096); qemu_register_reset(&ocm_reset, ocm); ppc_dcr_register(env, OCM0_ISARC, @@ -1222,7 +1222,7 @@ static void ppc405_i2c_init(hwaddr base, qemu_irq irq) #ifdef DEBUG_I2C printf("%s: offset " TARGET_FMT_plx "\n", __func__, base); #endif - memory_region_init_io(&i2c->iomem, &i2c_ops, i2c, "i2c", 0x011); + memory_region_init_io(&i2c->iomem, NULL, &i2c_ops, i2c, "i2c", 0x011); memory_region_add_subregion(get_system_memory(), base, &i2c->iomem); qemu_register_reset(ppc4xx_i2c_reset, i2c); } @@ -1501,7 +1501,7 @@ static void ppc4xx_gpt_init(hwaddr base, qemu_irq irqs[5]) #ifdef DEBUG_GPT printf("%s: offset " TARGET_FMT_plx "\n", __func__, base); #endif - memory_region_init_io(&gpt->iomem, &gpt_ops, gpt, "gpt", 0x0d4); + memory_region_init_io(&gpt->iomem, NULL, &gpt_ops, gpt, "gpt", 0x0d4); memory_region_add_subregion(get_system_memory(), base, &gpt->iomem); qemu_register_reset(ppc4xx_gpt_reset, gpt); } diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c index b0c1c027d..5b039abb3 100644 --- a/hw/ppc/ppc440_bamboo.c +++ b/hw/ppc/ppc440_bamboo.c @@ -243,7 +243,7 @@ static void bamboo_init(QEMUMachineInitArgs *args) for (i = 0; i < nb_nics; i++) { /* There are no PCI NICs on the Bamboo board, but there are * PCI slots, so we can pick whatever default model we want. */ - pci_nic_init_nofail(&nd_table[i], "e1000", NULL); + pci_nic_init_nofail(&nd_table[i], pcibus, "e1000", NULL); } } diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c index d8e3dae25..239aada19 100644 --- a/hw/ppc/ppc4xx_devs.c +++ b/hw/ppc/ppc4xx_devs.c @@ -431,7 +431,7 @@ static void sdram_set_bcr(ppc4xx_sdram_t *sdram, printf("%s: Map RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n", __func__, sdram_base(bcr), sdram_size(bcr)); #endif - memory_region_init(&sdram->containers[n], "sdram-containers", + memory_region_init(&sdram->containers[n], NULL, "sdram-containers", sdram_size(bcr)); memory_region_add_subregion(&sdram->containers[n], 0, &sdram->ram_memories[n]); @@ -696,7 +696,7 @@ ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks, if (bank_size <= size_left) { char name[32]; snprintf(name, sizeof(name), "ppc4xx.sdram%d", i); - memory_region_init_ram(&ram_memories[i], name, bank_size); + memory_region_init_ram(&ram_memories[i], NULL, name, bank_size); vmstate_register_ram_global(&ram_memories[i]); ram_bases[i] = base; ram_sizes[i] = bank_size; diff --git a/hw/ppc/ppc4xx_pci.c b/hw/ppc/ppc4xx_pci.c index 599539bc1..d2d6f65e6 100644 --- a/hw/ppc/ppc4xx_pci.c +++ b/hw/ppc/ppc4xx_pci.c @@ -355,12 +355,12 @@ static int ppc4xx_pcihost_initfn(SysBusDevice *dev) pci_create_simple(b, 0, "ppc4xx-host-bridge"); /* XXX split into 2 memory regions, one for config space, one for regs */ - memory_region_init(&s->container, "pci-container", PCI_ALL_SIZE); - memory_region_init_io(&h->conf_mem, &pci_host_conf_le_ops, h, + memory_region_init(&s->container, OBJECT(s), "pci-container", PCI_ALL_SIZE); + memory_region_init_io(&h->conf_mem, OBJECT(s), &pci_host_conf_le_ops, h, "pci-conf-idx", 4); - memory_region_init_io(&h->data_mem, &pci_host_data_le_ops, h, + memory_region_init_io(&h->data_mem, OBJECT(s), &pci_host_data_le_ops, h, "pci-conf-data", 4); - memory_region_init_io(&s->iomem, &pci_reg_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &pci_reg_ops, s, "pci.reg", PCI_REG_SIZE); memory_region_add_subregion(&s->container, PCIC0_CFGADDR, &h->conf_mem); memory_region_add_subregion(&s->container, PCIC0_CFGDATA, &h->data_mem); diff --git a/hw/ppc/ppce500_spin.c b/hw/ppc/ppce500_spin.c index ea6541413..11b7de2f3 100644 --- a/hw/ppc/ppce500_spin.c +++ b/hw/ppc/ppce500_spin.c @@ -191,8 +191,8 @@ static int ppce500_spin_initfn(SysBusDevice *dev) s = FROM_SYSBUS(SpinState, SYS_BUS_DEVICE(dev)); - memory_region_init_io(&s->iomem, &spin_rw_ops, s, "e500 spin pv device", - sizeof(SpinInfo) * MAX_CPUS); + memory_region_init_io(&s->iomem, OBJECT(s), &spin_rw_ops, s, + "e500 spin pv device", sizeof(SpinInfo) * MAX_CPUS); sysbus_init_mmio(dev, &s->iomem); qemu_register_reset(spin_reset, s); diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c index 90828f263..19f244248 100644 --- a/hw/ppc/prep.c +++ b/hw/ppc/prep.c @@ -417,10 +417,10 @@ static const MemoryRegionOps PPC_prep_io_ops = { static void cpu_request_exit(void *opaque, int irq, int level) { - CPUPPCState *env = cpu_single_env; + CPUState *cpu = current_cpu; - if (env && level) { - cpu_exit(CPU(ppc_env_get_cpu(env))); + if (cpu && level) { + cpu_exit(cpu); } } @@ -434,6 +434,16 @@ static void ppc_prep_reset(void *opaque) cpu->env.nip = 0xfffffffc; } +static const MemoryRegionPortio prep_portio_list[] = { + /* System control ports */ + { 0x0092, 1, 1, .read = PREP_io_800_readb, .write = PREP_io_800_writeb, }, + { 0x0800, 0x52, 1, + .read = PREP_io_800_readb, .write = PREP_io_800_writeb, }, + /* Special port to get debug messages from Open-Firmware */ + { 0x0F00, 4, 1, .write = PPC_debug_write, }, + PORTIO_END_OF_LIST(), +}; + /* PowerPC PREP hardware initialisation */ static void ppc_prep_init(QEMUMachineInitArgs *args) { @@ -450,6 +460,7 @@ static void ppc_prep_init(QEMUMachineInitArgs *args) nvram_t nvram; M48t59State *m48t59; MemoryRegion *PPC_io_memory = g_new(MemoryRegion, 1); + PortioList *port_list = g_new(PortioList, 1); #if 0 MemoryRegion *xcsr = g_new(MemoryRegion, 1); #endif @@ -494,12 +505,12 @@ static void ppc_prep_init(QEMUMachineInitArgs *args) } /* allocate RAM */ - memory_region_init_ram(ram, "ppc_prep.ram", ram_size); + memory_region_init_ram(ram, NULL, "ppc_prep.ram", ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(sysmem, 0, ram); /* allocate and load BIOS */ - memory_region_init_ram(bios, "ppc_prep.bios", BIOS_SIZE); + memory_region_init_ram(bios, NULL, "ppc_prep.bios", BIOS_SIZE); memory_region_set_readonly(bios, true); memory_region_add_subregion(sysmem, (uint32_t)(-BIOS_SIZE), bios); vmstate_register_ram_global(bios); @@ -594,8 +605,9 @@ static void ppc_prep_init(QEMUMachineInitArgs *args) /* PCI -> ISA bridge */ pci = pci_create_simple(pci_bus, PCI_DEVFN(1, 0), "i82378"); cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1); + cpu = POWERPC_CPU(first_cpu); qdev_connect_gpio_out(&pci->qdev, 0, - first_cpu->irq_inputs[PPC6xx_INPUT_INT]); + cpu->env.irq_inputs[PPC6xx_INPUT_INT]); qdev_connect_gpio_out(&pci->qdev, 1, *cpu_exit_irq); sysbus_connect_irq(&pcihost->busdev, 0, qdev_get_gpio_in(&pci->qdev, 9)); sysbus_connect_irq(&pcihost->busdev, 1, qdev_get_gpio_in(&pci->qdev, 11)); @@ -610,7 +622,7 @@ static void ppc_prep_init(QEMUMachineInitArgs *args) qdev_init_nofail(dev); /* Register 8 MB of ISA IO space (needed for non-contiguous map) */ - memory_region_init_io(PPC_io_memory, &PPC_prep_io_ops, sysctrl, + memory_region_init_io(PPC_io_memory, NULL, &PPC_prep_io_ops, sysctrl, "ppc-io", 0x00800000); memory_region_add_subregion(sysmem, 0x80000000, PPC_io_memory); @@ -628,7 +640,7 @@ static void ppc_prep_init(QEMUMachineInitArgs *args) isa_ne2000_init(isa_bus, ne2000_io[i], ne2000_irq[i], &nd_table[i]); } else { - pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL); + pci_nic_init_nofail(&nd_table[i], pci_bus, "ne2k_pci", NULL); } } @@ -640,15 +652,15 @@ static void ppc_prep_init(QEMUMachineInitArgs *args) } isa_create_simple(isa_bus, "i8042"); - sysctrl->reset_irq = first_cpu->irq_inputs[PPC6xx_INPUT_HRESET]; - /* System control ports */ - register_ioport_read(0x0092, 0x01, 1, &PREP_io_800_readb, sysctrl); - register_ioport_write(0x0092, 0x01, 1, &PREP_io_800_writeb, sysctrl); - register_ioport_read(0x0800, 0x52, 1, &PREP_io_800_readb, sysctrl); - register_ioport_write(0x0800, 0x52, 1, &PREP_io_800_writeb, sysctrl); + cpu = POWERPC_CPU(first_cpu); + sysctrl->reset_irq = cpu->env.irq_inputs[PPC6xx_INPUT_HRESET]; + + portio_list_init(port_list, NULL, prep_portio_list, sysctrl, "prep"); + portio_list_add(port_list, get_system_io(), 0x0); + /* PowerPC control and status register group */ #if 0 - memory_region_init_io(xcsr, &PPC_XCSR_ops, NULL, "ppc-xcsr", 0x1000); + memory_region_init_io(xcsr, NULL, &PPC_XCSR_ops, NULL, "ppc-xcsr", 0x1000); memory_region_add_subregion(sysmem, 0xFEFF0000, xcsr); #endif @@ -672,9 +684,6 @@ static void ppc_prep_init(QEMUMachineInitArgs *args) /* XXX: need an option to load a NVRAM image */ 0, graphic_width, graphic_height, graphic_depth); - - /* Special port to get debug messages from Open-Firmware */ - register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL); } static QEMUMachine prep_machine = { diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index fe34291ff..48ae09283 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -131,7 +131,6 @@ int spapr_allocate_irq_block(int num, bool lsi) static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr) { int ret = 0, offset; - CPUPPCState *env; CPUState *cpu; char cpu_model[32]; int smt = kvmppc_smt_threads(); @@ -139,8 +138,7 @@ static int spapr_fixup_cpu_dt(void *fdt, sPAPREnvironment *spapr) assert(spapr->cpu_model); - for (env = first_cpu; env != NULL; env = env->next_cpu) { - cpu = CPU(ppc_env_get_cpu(env)); + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { uint32_t associativity[] = {cpu_to_be32(0x5), cpu_to_be32(0x0), cpu_to_be32(0x0), @@ -231,7 +229,7 @@ static void *spapr_create_fdt_skel(const char *cpu_model, uint32_t epow_irq) { void *fdt; - CPUPPCState *env; + CPUState *cs; uint32_t start_prop = cpu_to_be32(initrd_base); uint32_t end_prop = cpu_to_be32(initrd_base + initrd_size); char hypertas_prop[] = "hcall-pft\0hcall-term\0hcall-dabr\0hcall-interrupt" @@ -304,10 +302,11 @@ static void *spapr_create_fdt_skel(const char *cpu_model, /* This is needed during FDT finalization */ spapr->cpu_model = g_strdup(modelname); - for (env = first_cpu; env != NULL; env = env->next_cpu) { - CPUState *cpu = CPU(ppc_env_get_cpu(env)); - PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); - int index = cpu->cpu_index; + for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) { + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *env = &cpu->env; + PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); + int index = cs->cpu_index; uint32_t servers_prop[smp_threads]; uint32_t gservers_prop[smp_threads * 2]; char *nodename; @@ -632,7 +631,7 @@ static void spapr_reset_htab(sPAPREnvironment *spapr) static void ppc_spapr_reset(void) { - CPUState *first_cpu_cpu; + PowerPCCPU *first_ppc_cpu; /* Reset the hash table & recalc the RMA */ spapr_reset_htab(spapr); @@ -644,11 +643,11 @@ static void ppc_spapr_reset(void) spapr->rtas_size); /* Set up the entry state */ - first_cpu_cpu = ENV_GET_CPU(first_cpu); - first_cpu->gpr[3] = spapr->fdt_addr; - first_cpu->gpr[5] = 0; - first_cpu_cpu->halted = 0; - first_cpu->nip = spapr->entry_point; + first_ppc_cpu = POWERPC_CPU(first_cpu); + first_ppc_cpu->env.gpr[3] = spapr->fdt_addr; + first_ppc_cpu->env.gpr[5] = 0; + first_cpu->halted = 0; + first_ppc_cpu->env.nip = spapr->entry_point; } @@ -676,27 +675,19 @@ static void spapr_cpu_reset(void *opaque) static void spapr_create_nvram(sPAPREnvironment *spapr) { - QemuOpts *machine_opts; - DeviceState *dev; - - dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram"); - - machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); - if (machine_opts) { - const char *drivename; + DeviceState *dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram"); + const char *drivename = qemu_opt_get(qemu_get_machine_opts(), "nvram"); - drivename = qemu_opt_get(machine_opts, "nvram"); - if (drivename) { - BlockDriverState *bs; + if (drivename) { + BlockDriverState *bs; - bs = bdrv_find(drivename); - if (!bs) { - fprintf(stderr, "No such block device \"%s\" for nvram\n", - drivename); - exit(1); - } - qdev_prop_set_drive_nofail(dev, "drive", bs); + bs = bdrv_find(drivename); + if (!bs) { + fprintf(stderr, "No such block device \"%s\" for nvram\n", + drivename); + exit(1); } + qdev_prop_set_drive_nofail(dev, "drive", bs); } qdev_init_nofail(dev); @@ -835,7 +826,7 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args) ram_addr_t nonrma_base = rma_alloc_size; ram_addr_t nonrma_size = spapr->ram_limit - rma_alloc_size; - memory_region_init_ram(ram, "ppc_spapr.ram", nonrma_size); + memory_region_init_ram(ram, NULL, "ppc_spapr.ram", nonrma_size); vmstate_register_ram_global(ram); memory_region_add_subregion(sysmem, nonrma_base, ram); } @@ -887,7 +878,7 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args) if (strcmp(nd->model, "ibmveth") == 0) { spapr_vlan_create(spapr->vio_bus, nd); } else { - pci_nic_init_nofail(&nd_table[i], nd->model, NULL); + pci_nic_init_nofail(&nd_table[i], phb->bus, nd->model, NULL); } } @@ -949,7 +940,10 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args) } } - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, FW_FILE_NAME); + if (bios_name == NULL) { + bios_name = FW_FILE_NAME; + } + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); fw_size = load_image_targphys(filename, 0, FW_MAX_SIZE); if (fw_size < 0) { hw_error("qemu: could not load LPAR rtas '%s'\n", filename); diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index e6f321d53..ed32deceb 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -121,14 +121,14 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPREnvironment *spapr, return H_SUCCESS; } -enum { +typedef enum { REMOVE_SUCCESS = 0, REMOVE_NOT_FOUND = 1, REMOVE_PARM = 2, REMOVE_HW = 3, -}; +} RemoveResult; -static target_ulong remove_hpte(CPUPPCState *env, target_ulong ptex, +static RemoveResult remove_hpte(CPUPPCState *env, target_ulong ptex, target_ulong avpn, target_ulong flags, target_ulong *vp, target_ulong *rp) @@ -165,7 +165,7 @@ static target_ulong h_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr, target_ulong flags = args[0]; target_ulong pte_index = args[1]; target_ulong avpn = args[2]; - int ret; + RemoveResult ret; ret = remove_hpte(env, pte_index, avpn, flags, &args[0], &args[1]); @@ -184,7 +184,7 @@ static target_ulong h_remove(PowerPCCPU *cpu, sPAPREnvironment *spapr, return H_HARDWARE; } - assert(0); + g_assert_not_reached(); } #define H_BULK_REMOVE_TYPE 0xc000000000000000ULL diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c index 91bc8e488..89b33a547 100644 --- a/hw/ppc/spapr_iommu.c +++ b/hw/ppc/spapr_iommu.c @@ -116,7 +116,7 @@ static MemoryRegionIOMMUOps spapr_iommu_ops = { .translate = spapr_tce_translate_iommu, }; -sPAPRTCETable *spapr_tce_new_table(uint32_t liobn, size_t window_size) +sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn, size_t window_size) { sPAPRTCETable *tcet; @@ -151,7 +151,7 @@ sPAPRTCETable *spapr_tce_new_table(uint32_t liobn, size_t window_size) "table @ %p, fd=%d\n", tcet, liobn, tcet->table, tcet->fd); #endif - memory_region_init_iommu(&tcet->iommu, &spapr_iommu_ops, + memory_region_init_iommu(&tcet->iommu, OBJECT(owner), &spapr_iommu_ops, "iommu-spapr", UINT64_MAX); QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list); diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index c8c12c824..318bc9d6e 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -451,7 +451,7 @@ static uint64_t spapr_io_read(void *opaque, hwaddr addr, case 4: return cpu_inl(addr); } - assert(0); + g_assert_not_reached(); } static void spapr_io_write(void *opaque, hwaddr addr, @@ -468,7 +468,7 @@ static void spapr_io_write(void *opaque, hwaddr addr, cpu_outl(addr, data); return; } - assert(0); + g_assert_not_reached(); } static const MemoryRegionOps spapr_io_ops = { @@ -581,10 +581,11 @@ static int spapr_phb_init(SysBusDevice *s) /* Initialize memory regions */ sprintf(namebuf, "%s.mmio", sphb->dtbusname); - memory_region_init(&sphb->memspace, namebuf, INT64_MAX); + memory_region_init(&sphb->memspace, OBJECT(sphb), namebuf, INT64_MAX); sprintf(namebuf, "%s.mmio-alias", sphb->dtbusname); - memory_region_init_alias(&sphb->memwindow, namebuf, &sphb->memspace, + memory_region_init_alias(&sphb->memwindow, OBJECT(sphb), + namebuf, &sphb->memspace, SPAPR_PCI_MEM_WIN_BUS_OFFSET, sphb->mem_win_size); memory_region_add_subregion(get_system_memory(), sphb->mem_win_addr, &sphb->memwindow); @@ -598,12 +599,13 @@ static int spapr_phb_init(SysBusDevice *s) * system_io works around the problem until all the users of * old_portion are updated */ sprintf(namebuf, "%s.io", sphb->dtbusname); - memory_region_init(&sphb->iospace, namebuf, SPAPR_PCI_IO_WIN_SIZE); + memory_region_init(&sphb->iospace, OBJECT(sphb), + namebuf, SPAPR_PCI_IO_WIN_SIZE); /* FIXME: fix to support multiple PHBs */ memory_region_add_subregion(get_system_io(), 0, &sphb->iospace); sprintf(namebuf, "%s.io-alias", sphb->dtbusname); - memory_region_init_io(&sphb->iowindow, &spapr_io_ops, sphb, + memory_region_init_io(&sphb->iowindow, OBJECT(sphb), &spapr_io_ops, sphb, namebuf, SPAPR_PCI_IO_WIN_SIZE); memory_region_add_subregion(get_system_memory(), sphb->io_win_addr, &sphb->iowindow); @@ -613,7 +615,7 @@ static int spapr_phb_init(SysBusDevice *s) * from msi_notify()/msix_notify() */ if (msi_supported) { sprintf(namebuf, "%s.msi", sphb->dtbusname); - memory_region_init_io(&sphb->msiwindow, &spapr_msi_ops, sphb, + memory_region_init_io(&sphb->msiwindow, OBJECT(sphb), &spapr_msi_ops, sphb, namebuf, SPAPR_MSIX_MAX_DEVS * 0x10000); memory_region_add_subregion(get_system_memory(), sphb->msi_win_addr, &sphb->msiwindow); @@ -646,7 +648,8 @@ static int spapr_phb_init(SysBusDevice *s) sphb->dma_window_start = 0; sphb->dma_window_size = 0x40000000; - sphb->tcet = spapr_tce_new_table(sphb->dma_liobn, sphb->dma_window_size); + sphb->tcet = spapr_tce_new_table(DEVICE(sphb), sphb->dma_liobn, + sphb->dma_window_size); if (!sphb->tcet) { fprintf(stderr, "Unable to create TCE table for %s\n", sphb->dtbusname); return -1; @@ -696,11 +699,21 @@ static Property spapr_phb_properties[] = { DEFINE_PROP_END_OF_LIST(), }; +static const char *spapr_phb_root_bus_path(PCIHostState *host_bridge, + PCIBus *rootbus) +{ + sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(host_bridge); + + return sphb->dtbusname; +} + static void spapr_phb_class_init(ObjectClass *klass, void *data) { + PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass); SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); + hc->root_bus_path = spapr_phb_root_bus_path; sdc->init = spapr_phb_init; dc->props = spapr_phb_properties; dc->reset = spapr_phb_reset; diff --git a/hw/ppc/spapr_vio.c b/hw/ppc/spapr_vio.c index 9c18741ce..7c6f6e427 100644 --- a/hw/ppc/spapr_vio.c +++ b/hw/ppc/spapr_vio.c @@ -455,7 +455,7 @@ static int spapr_vio_busdev_init(DeviceState *qdev) if (pc->rtce_window_size) { uint32_t liobn = SPAPR_VIO_BASE_LIOBN | dev->reg; - dev->tcet = spapr_tce_new_table(liobn, pc->rtce_window_size); + dev->tcet = spapr_tce_new_table(qdev, liobn, pc->rtce_window_size); address_space_init(&dev->as, spapr_tce_get_iommu(dev->tcet), qdev->id); } diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c index 709a70724..08e77fbef 100644 --- a/hw/ppc/virtex_ml507.c +++ b/hw/ppc/virtex_ml507.c @@ -190,7 +190,7 @@ static void virtex_init(QEMUMachineInitArgs *args) env = &cpu->env; qemu_register_reset(main_cpu_reset, cpu); - memory_region_init_ram(phys_ram, "ram", ram_size); + memory_region_init_ram(phys_ram, NULL, "ram", ram_size); vmstate_register_ram_global(phys_ram); memory_region_add_subregion(address_space_mem, ram_base, phys_ram); diff --git a/hw/ppc/xics.c b/hw/ppc/xics.c deleted file mode 100644 index 091912e2c..000000000 --- a/hw/ppc/xics.c +++ /dev/null @@ -1,587 +0,0 @@ -/* - * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator - * - * PAPR Virtualized Interrupt System, aka ICS/ICP aka xics - * - * Copyright (c) 2010,2011 David Gibson, IBM Corporation. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - -#include "hw/hw.h" -#include "trace.h" -#include "hw/ppc/spapr.h" -#include "hw/ppc/xics.h" - -/* - * ICP: Presentation layer - */ - -struct icp_server_state { - uint32_t xirr; - uint8_t pending_priority; - uint8_t mfrr; - qemu_irq output; -}; - -#define XISR_MASK 0x00ffffff -#define CPPR_MASK 0xff000000 - -#define XISR(ss) (((ss)->xirr) & XISR_MASK) -#define CPPR(ss) (((ss)->xirr) >> 24) - -struct ics_state; - -struct icp_state { - long nr_servers; - struct icp_server_state *ss; - struct ics_state *ics; -}; - -static void ics_reject(struct ics_state *ics, int nr); -static void ics_resend(struct ics_state *ics); -static void ics_eoi(struct ics_state *ics, int nr); - -static void icp_check_ipi(struct icp_state *icp, int server) -{ - struct icp_server_state *ss = icp->ss + server; - - if (XISR(ss) && (ss->pending_priority <= ss->mfrr)) { - return; - } - - trace_xics_icp_check_ipi(server, ss->mfrr); - - if (XISR(ss)) { - ics_reject(icp->ics, XISR(ss)); - } - - ss->xirr = (ss->xirr & ~XISR_MASK) | XICS_IPI; - ss->pending_priority = ss->mfrr; - qemu_irq_raise(ss->output); -} - -static void icp_resend(struct icp_state *icp, int server) -{ - struct icp_server_state *ss = icp->ss + server; - - if (ss->mfrr < CPPR(ss)) { - icp_check_ipi(icp, server); - } - ics_resend(icp->ics); -} - -static void icp_set_cppr(struct icp_state *icp, int server, uint8_t cppr) -{ - struct icp_server_state *ss = icp->ss + server; - uint8_t old_cppr; - uint32_t old_xisr; - - old_cppr = CPPR(ss); - ss->xirr = (ss->xirr & ~CPPR_MASK) | (cppr << 24); - - if (cppr < old_cppr) { - if (XISR(ss) && (cppr <= ss->pending_priority)) { - old_xisr = XISR(ss); - ss->xirr &= ~XISR_MASK; /* Clear XISR */ - ss->pending_priority = 0xff; - qemu_irq_lower(ss->output); - ics_reject(icp->ics, old_xisr); - } - } else { - if (!XISR(ss)) { - icp_resend(icp, server); - } - } -} - -static void icp_set_mfrr(struct icp_state *icp, int server, uint8_t mfrr) -{ - struct icp_server_state *ss = icp->ss + server; - - ss->mfrr = mfrr; - if (mfrr < CPPR(ss)) { - icp_check_ipi(icp, server); - } -} - -static uint32_t icp_accept(struct icp_server_state *ss) -{ - uint32_t xirr = ss->xirr; - - qemu_irq_lower(ss->output); - ss->xirr = ss->pending_priority << 24; - ss->pending_priority = 0xff; - - trace_xics_icp_accept(xirr, ss->xirr); - - return xirr; -} - -static void icp_eoi(struct icp_state *icp, int server, uint32_t xirr) -{ - struct icp_server_state *ss = icp->ss + server; - - /* Send EOI -> ICS */ - ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK); - trace_xics_icp_eoi(server, xirr, ss->xirr); - ics_eoi(icp->ics, xirr & XISR_MASK); - if (!XISR(ss)) { - icp_resend(icp, server); - } -} - -static void icp_irq(struct icp_state *icp, int server, int nr, uint8_t priority) -{ - struct icp_server_state *ss = icp->ss + server; - - trace_xics_icp_irq(server, nr, priority); - - if ((priority >= CPPR(ss)) - || (XISR(ss) && (ss->pending_priority <= priority))) { - ics_reject(icp->ics, nr); - } else { - if (XISR(ss)) { - ics_reject(icp->ics, XISR(ss)); - } - ss->xirr = (ss->xirr & ~XISR_MASK) | (nr & XISR_MASK); - ss->pending_priority = priority; - trace_xics_icp_raise(ss->xirr, ss->pending_priority); - qemu_irq_raise(ss->output); - } -} - -/* - * ICS: Source layer - */ - -struct ics_irq_state { - int server; - uint8_t priority; - uint8_t saved_priority; -#define XICS_STATUS_ASSERTED 0x1 -#define XICS_STATUS_SENT 0x2 -#define XICS_STATUS_REJECTED 0x4 -#define XICS_STATUS_MASKED_PENDING 0x8 - uint8_t status; -}; - -struct ics_state { - int nr_irqs; - int offset; - qemu_irq *qirqs; - bool *islsi; - struct ics_irq_state *irqs; - struct icp_state *icp; -}; - -static int ics_valid_irq(struct ics_state *ics, uint32_t nr) -{ - return (nr >= ics->offset) - && (nr < (ics->offset + ics->nr_irqs)); -} - -static void resend_msi(struct ics_state *ics, int srcno) -{ - struct ics_irq_state *irq = ics->irqs + srcno; - - /* FIXME: filter by server#? */ - if (irq->status & XICS_STATUS_REJECTED) { - irq->status &= ~XICS_STATUS_REJECTED; - if (irq->priority != 0xff) { - icp_irq(ics->icp, irq->server, srcno + ics->offset, - irq->priority); - } - } -} - -static void resend_lsi(struct ics_state *ics, int srcno) -{ - struct ics_irq_state *irq = ics->irqs + srcno; - - if ((irq->priority != 0xff) - && (irq->status & XICS_STATUS_ASSERTED) - && !(irq->status & XICS_STATUS_SENT)) { - irq->status |= XICS_STATUS_SENT; - icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority); - } -} - -static void set_irq_msi(struct ics_state *ics, int srcno, int val) -{ - struct ics_irq_state *irq = ics->irqs + srcno; - - trace_xics_set_irq_msi(srcno, srcno + ics->offset); - - if (val) { - if (irq->priority == 0xff) { - irq->status |= XICS_STATUS_MASKED_PENDING; - trace_xics_masked_pending(); - } else { - icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority); - } - } -} - -static void set_irq_lsi(struct ics_state *ics, int srcno, int val) -{ - struct ics_irq_state *irq = ics->irqs + srcno; - - trace_xics_set_irq_lsi(srcno, srcno + ics->offset); - if (val) { - irq->status |= XICS_STATUS_ASSERTED; - } else { - irq->status &= ~XICS_STATUS_ASSERTED; - } - resend_lsi(ics, srcno); -} - -static void ics_set_irq(void *opaque, int srcno, int val) -{ - struct ics_state *ics = (struct ics_state *)opaque; - - if (ics->islsi[srcno]) { - set_irq_lsi(ics, srcno, val); - } else { - set_irq_msi(ics, srcno, val); - } -} - -static void write_xive_msi(struct ics_state *ics, int srcno) -{ - struct ics_irq_state *irq = ics->irqs + srcno; - - if (!(irq->status & XICS_STATUS_MASKED_PENDING) - || (irq->priority == 0xff)) { - return; - } - - irq->status &= ~XICS_STATUS_MASKED_PENDING; - icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority); -} - -static void write_xive_lsi(struct ics_state *ics, int srcno) -{ - resend_lsi(ics, srcno); -} - -static void ics_write_xive(struct ics_state *ics, int nr, int server, - uint8_t priority, uint8_t saved_priority) -{ - int srcno = nr - ics->offset; - struct ics_irq_state *irq = ics->irqs + srcno; - - irq->server = server; - irq->priority = priority; - irq->saved_priority = saved_priority; - - trace_xics_ics_write_xive(nr, srcno, server, priority); - - if (ics->islsi[srcno]) { - write_xive_lsi(ics, srcno); - } else { - write_xive_msi(ics, srcno); - } -} - -static void ics_reject(struct ics_state *ics, int nr) -{ - struct ics_irq_state *irq = ics->irqs + nr - ics->offset; - - trace_xics_ics_reject(nr, nr - ics->offset); - irq->status |= XICS_STATUS_REJECTED; /* Irrelevant but harmless for LSI */ - irq->status &= ~XICS_STATUS_SENT; /* Irrelevant but harmless for MSI */ -} - -static void ics_resend(struct ics_state *ics) -{ - int i; - - for (i = 0; i < ics->nr_irqs; i++) { - /* FIXME: filter by server#? */ - if (ics->islsi[i]) { - resend_lsi(ics, i); - } else { - resend_msi(ics, i); - } - } -} - -static void ics_eoi(struct ics_state *ics, int nr) -{ - int srcno = nr - ics->offset; - struct ics_irq_state *irq = ics->irqs + srcno; - - trace_xics_ics_eoi(nr); - - if (ics->islsi[srcno]) { - irq->status &= ~XICS_STATUS_SENT; - } -} - -/* - * Exported functions - */ - -qemu_irq xics_get_qirq(struct icp_state *icp, int irq) -{ - if (!ics_valid_irq(icp->ics, irq)) { - return NULL; - } - - return icp->ics->qirqs[irq - icp->ics->offset]; -} - -void xics_set_irq_type(struct icp_state *icp, int irq, bool lsi) -{ - assert(ics_valid_irq(icp->ics, irq)); - - icp->ics->islsi[irq - icp->ics->offset] = lsi; -} - -static target_ulong h_cppr(PowerPCCPU *cpu, sPAPREnvironment *spapr, - target_ulong opcode, target_ulong *args) -{ - CPUState *cs = CPU(cpu); - target_ulong cppr = args[0]; - - icp_set_cppr(spapr->icp, cs->cpu_index, cppr); - return H_SUCCESS; -} - -static target_ulong h_ipi(PowerPCCPU *cpu, sPAPREnvironment *spapr, - target_ulong opcode, target_ulong *args) -{ - target_ulong server = args[0]; - target_ulong mfrr = args[1]; - - if (server >= spapr->icp->nr_servers) { - return H_PARAMETER; - } - - icp_set_mfrr(spapr->icp, server, mfrr); - return H_SUCCESS; -} - -static target_ulong h_xirr(PowerPCCPU *cpu, sPAPREnvironment *spapr, - target_ulong opcode, target_ulong *args) -{ - CPUState *cs = CPU(cpu); - uint32_t xirr = icp_accept(spapr->icp->ss + cs->cpu_index); - - args[0] = xirr; - return H_SUCCESS; -} - -static target_ulong h_eoi(PowerPCCPU *cpu, sPAPREnvironment *spapr, - target_ulong opcode, target_ulong *args) -{ - CPUState *cs = CPU(cpu); - target_ulong xirr = args[0]; - - icp_eoi(spapr->icp, cs->cpu_index, xirr); - return H_SUCCESS; -} - -static void rtas_set_xive(PowerPCCPU *cpu, sPAPREnvironment *spapr, - uint32_t token, - uint32_t nargs, target_ulong args, - uint32_t nret, target_ulong rets) -{ - struct ics_state *ics = spapr->icp->ics; - uint32_t nr, server, priority; - - if ((nargs != 3) || (nret != 1)) { - rtas_st(rets, 0, -3); - return; - } - - nr = rtas_ld(args, 0); - server = rtas_ld(args, 1); - priority = rtas_ld(args, 2); - - if (!ics_valid_irq(ics, nr) || (server >= ics->icp->nr_servers) - || (priority > 0xff)) { - rtas_st(rets, 0, -3); - return; - } - - ics_write_xive(ics, nr, server, priority, priority); - - rtas_st(rets, 0, 0); /* Success */ -} - -static void rtas_get_xive(PowerPCCPU *cpu, sPAPREnvironment *spapr, - uint32_t token, - uint32_t nargs, target_ulong args, - uint32_t nret, target_ulong rets) -{ - struct ics_state *ics = spapr->icp->ics; - uint32_t nr; - - if ((nargs != 1) || (nret != 3)) { - rtas_st(rets, 0, -3); - return; - } - - nr = rtas_ld(args, 0); - - if (!ics_valid_irq(ics, nr)) { - rtas_st(rets, 0, -3); - return; - } - - rtas_st(rets, 0, 0); /* Success */ - rtas_st(rets, 1, ics->irqs[nr - ics->offset].server); - rtas_st(rets, 2, ics->irqs[nr - ics->offset].priority); -} - -static void rtas_int_off(PowerPCCPU *cpu, sPAPREnvironment *spapr, - uint32_t token, - uint32_t nargs, target_ulong args, - uint32_t nret, target_ulong rets) -{ - struct ics_state *ics = spapr->icp->ics; - uint32_t nr; - - if ((nargs != 1) || (nret != 1)) { - rtas_st(rets, 0, -3); - return; - } - - nr = rtas_ld(args, 0); - - if (!ics_valid_irq(ics, nr)) { - rtas_st(rets, 0, -3); - return; - } - - ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, 0xff, - ics->irqs[nr - ics->offset].priority); - - rtas_st(rets, 0, 0); /* Success */ -} - -static void rtas_int_on(PowerPCCPU *cpu, sPAPREnvironment *spapr, - uint32_t token, - uint32_t nargs, target_ulong args, - uint32_t nret, target_ulong rets) -{ - struct ics_state *ics = spapr->icp->ics; - uint32_t nr; - - if ((nargs != 1) || (nret != 1)) { - rtas_st(rets, 0, -3); - return; - } - - nr = rtas_ld(args, 0); - - if (!ics_valid_irq(ics, nr)) { - rtas_st(rets, 0, -3); - return; - } - - ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, - ics->irqs[nr - ics->offset].saved_priority, - ics->irqs[nr - ics->offset].saved_priority); - - rtas_st(rets, 0, 0); /* Success */ -} - -static void xics_reset(void *opaque) -{ - struct icp_state *icp = (struct icp_state *)opaque; - struct ics_state *ics = icp->ics; - int i; - - for (i = 0; i < icp->nr_servers; i++) { - icp->ss[i].xirr = 0; - icp->ss[i].pending_priority = 0xff; - icp->ss[i].mfrr = 0xff; - /* Make all outputs are deasserted */ - qemu_set_irq(icp->ss[i].output, 0); - } - - memset(ics->irqs, 0, sizeof(struct ics_irq_state) * ics->nr_irqs); - for (i = 0; i < ics->nr_irqs; i++) { - ics->irqs[i].priority = 0xff; - ics->irqs[i].saved_priority = 0xff; - } -} - -void xics_cpu_setup(struct icp_state *icp, PowerPCCPU *cpu) -{ - CPUState *cs = CPU(cpu); - CPUPPCState *env = &cpu->env; - struct icp_server_state *ss = &icp->ss[cs->cpu_index]; - - assert(cs->cpu_index < icp->nr_servers); - - switch (PPC_INPUT(env)) { - case PPC_FLAGS_INPUT_POWER7: - ss->output = env->irq_inputs[POWER7_INPUT_INT]; - break; - - case PPC_FLAGS_INPUT_970: - ss->output = env->irq_inputs[PPC970_INPUT_INT]; - break; - - default: - fprintf(stderr, "XICS interrupt controller does not support this CPU " - "bus model\n"); - abort(); - } -} - -struct icp_state *xics_system_init(int nr_servers, int nr_irqs) -{ - struct icp_state *icp; - struct ics_state *ics; - - icp = g_malloc0(sizeof(*icp)); - icp->nr_servers = nr_servers; - icp->ss = g_malloc0(icp->nr_servers*sizeof(struct icp_server_state)); - - ics = g_malloc0(sizeof(*ics)); - ics->nr_irqs = nr_irqs; - ics->offset = XICS_IRQ_BASE; - ics->irqs = g_malloc0(nr_irqs * sizeof(struct ics_irq_state)); - ics->islsi = g_malloc0(nr_irqs * sizeof(bool)); - - icp->ics = ics; - ics->icp = icp; - - ics->qirqs = qemu_allocate_irqs(ics_set_irq, ics, nr_irqs); - - spapr_register_hypercall(H_CPPR, h_cppr); - spapr_register_hypercall(H_IPI, h_ipi); - spapr_register_hypercall(H_XIRR, h_xirr); - spapr_register_hypercall(H_EOI, h_eoi); - - spapr_rtas_register("ibm,set-xive", rtas_set_xive); - spapr_rtas_register("ibm,get-xive", rtas_get_xive); - spapr_rtas_register("ibm,int-off", rtas_int_off); - spapr_rtas_register("ibm,int-on", rtas_int_on); - - qemu_register_reset(xics_reset, icp); - - return icp; -} diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index eb774d90e..aebbbf175 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -89,7 +89,7 @@ static void ccw_init(QEMUMachineInitArgs *args) virtio_ccw_register_hcalls(); /* allocate RAM */ - memory_region_init_ram(ram, "s390.ram", my_ram_size); + memory_region_init_ram(ram, NULL, "s390.ram", my_ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(sysmem, 0, ram); diff --git a/hw/s390x/s390-virtio.c b/hw/s390x/s390-virtio.c index 30d1118cd..edbde00d4 100644 --- a/hw/s390x/s390-virtio.c +++ b/hw/s390x/s390-virtio.c @@ -256,7 +256,7 @@ static void s390_init(QEMUMachineInitArgs *args) s390_virtio_register_hcalls(); /* allocate RAM */ - memory_region_init_ram(ram, "s390.ram", my_ram_size); + memory_region_init_ram(ram, NULL, "s390.ram", my_ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(sysmem, 0, ram); diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c index e7449573f..8835bd433 100644 --- a/hw/s390x/virtio-ccw.c +++ b/hw/s390x/virtio-ccw.c @@ -1031,6 +1031,9 @@ static Property virtio_ccw_blk_properties[] = { DEFINE_VIRTIO_BLK_PROPERTIES(VirtIOBlkCcw, blk), DEFINE_PROP_BIT("ioeventfd", VirtioCcwDevice, flags, VIRTIO_CCW_FLAG_USE_IOEVENTFD_BIT, true), +#ifdef CONFIG_VIRTIO_BLK_DATA_PLANE + DEFINE_PROP_BIT("x-data-plane", VirtIOBlkCcw, blk.data_plane, 0, false), +#endif DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/scsi/esp-pci.c b/hw/scsi/esp-pci.c index 029789ae3..8f97c5a6e 100644 --- a/hw/scsi/esp-pci.c +++ b/hw/scsi/esp-pci.c @@ -349,7 +349,8 @@ static int esp_pci_scsi_init(PCIDevice *dev) s->dma_memory_write = esp_pci_dma_memory_write; s->dma_opaque = pci; s->chip_id = TCHI_AM53C974; - memory_region_init_io(&pci->io, &esp_pci_io_ops, pci, "esp-io", 0x80); + memory_region_init_io(&pci->io, OBJECT(pci), &esp_pci_io_ops, pci, + "esp-io", 0x80); pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->io); s->irq = pci->dev.irq[0]; diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c index 0c81a5039..c6166c5cc 100644 --- a/hw/scsi/esp.c +++ b/hw/scsi/esp.c @@ -675,8 +675,8 @@ static int sysbus_esp_init(SysBusDevice *dev) assert(sysbus->it_shift != -1); s->chip_id = TCHI_FAS100A; - memory_region_init_io(&sysbus->iomem, &sysbus_esp_mem_ops, sysbus, - "esp", ESP_REGS << sysbus->it_shift); + memory_region_init_io(&sysbus->iomem, OBJECT(sysbus), &sysbus_esp_mem_ops, + sysbus, "esp", ESP_REGS << sysbus->it_shift); sysbus_init_mmio(dev, &sysbus->iomem); qdev_init_gpio_in(&dev->qdev, sysbus_esp_gpio_demux, 2); diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c index 22b8e9869..2c17ae5f2 100644 --- a/hw/scsi/lsi53c895a.c +++ b/hw/scsi/lsi53c895a.c @@ -2090,9 +2090,12 @@ static int lsi_scsi_init(PCIDevice *dev) /* Interrupt pin A */ pci_conf[PCI_INTERRUPT_PIN] = 0x01; - memory_region_init_io(&s->mmio_io, &lsi_mmio_ops, s, "lsi-mmio", 0x400); - memory_region_init_io(&s->ram_io, &lsi_ram_ops, s, "lsi-ram", 0x2000); - memory_region_init_io(&s->io_io, &lsi_io_ops, s, "lsi-io", 256); + memory_region_init_io(&s->mmio_io, OBJECT(s), &lsi_mmio_ops, s, + "lsi-mmio", 0x400); + memory_region_init_io(&s->ram_io, OBJECT(s), &lsi_ram_ops, s, + "lsi-ram", 0x2000); + memory_region_init_io(&s->io_io, OBJECT(s), &lsi_io_ops, s, + "lsi-io", 256); pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io_io); pci_register_bar(&s->dev, 1, 0, &s->mmio_io); diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index 65ccb09ba..45d0c77c4 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -2098,11 +2098,11 @@ static int megasas_scsi_init(PCIDevice *dev) /* Interrupt pin 1 */ pci_conf[PCI_INTERRUPT_PIN] = 0x01; - memory_region_init_io(&s->mmio_io, &megasas_mmio_ops, s, + memory_region_init_io(&s->mmio_io, OBJECT(s), &megasas_mmio_ops, s, "megasas-mmio", 0x4000); - memory_region_init_io(&s->port_io, &megasas_port_ops, s, + memory_region_init_io(&s->port_io, OBJECT(s), &megasas_port_ops, s, "megasas-io", 256); - memory_region_init_io(&s->queue_io, &megasas_queue_ops, s, + memory_region_init_io(&s->queue_io, OBJECT(s), &megasas_queue_ops, s, "megasas-queue", 0x40000); #ifdef USE_MSIX diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index 53ea90643..a92b7c1de 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -505,10 +505,12 @@ SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d, uint32_t tag, uint32_t lun, void *hba_private) { SCSIRequest *req; + SCSIBus *bus = scsi_bus_from_device(d); + BusState *qbus = BUS(bus); req = g_malloc0(reqops->size); req->refcount = 1; - req->bus = scsi_bus_from_device(d); + req->bus = bus; req->dev = d; req->tag = tag; req->lun = lun; @@ -516,6 +518,8 @@ SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d, req->status = -1; req->sense_len = 0; req->ops = reqops; + object_ref(OBJECT(d)); + object_ref(OBJECT(qbus->parent)); trace_scsi_req_alloc(req->dev->id, req->lun, req->tag); return req; } @@ -1498,13 +1502,17 @@ void scsi_req_unref(SCSIRequest *req) { assert(req->refcount > 0); if (--req->refcount == 0) { - SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, req->dev->qdev.parent_bus); + BusState *qbus = req->dev->qdev.parent_bus; + SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, qbus); + if (bus->info->free_request && req->hba_private) { bus->info->free_request(bus, req->hba_private); } if (req->ops->free_req) { req->ops->free_req(req); } + object_unref(OBJECT(req->dev)); + object_unref(OBJECT(qbus->parent)); g_free(req); } } diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index b8a0abf0f..712f0ade2 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -77,10 +77,12 @@ static void virtio_scsi_bad_req(void) exit(1); } -static void qemu_sgl_init_external(QEMUSGList *qsgl, struct iovec *sg, +static void qemu_sgl_init_external(VirtIOSCSIReq *req, struct iovec *sg, hwaddr *addr, int num) { - qemu_sglist_init(qsgl, num, &address_space_memory); + QEMUSGList *qsgl = &req->qsgl; + + qemu_sglist_init(qsgl, DEVICE(req->dev), num, &address_space_memory); while (num--) { qemu_sglist_add(qsgl, *(addr++), (sg++)->iov_len); } @@ -99,11 +101,11 @@ static void virtio_scsi_parse_req(VirtIOSCSI *s, VirtQueue *vq, req->resp.buf = req->elem.in_sg[0].iov_base; if (req->elem.out_num > 1) { - qemu_sgl_init_external(&req->qsgl, &req->elem.out_sg[1], + qemu_sgl_init_external(req, &req->elem.out_sg[1], &req->elem.out_addr[1], req->elem.out_num - 1); } else { - qemu_sgl_init_external(&req->qsgl, &req->elem.in_sg[1], + qemu_sgl_init_external(req, &req->elem.in_sg[1], &req->elem.in_addr[1], req->elem.in_num - 1); } diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c index 7cf404459..97d3aa3e6 100644 --- a/hw/scsi/vmw_pvscsi.c +++ b/hw/scsi/vmw_pvscsi.c @@ -1075,7 +1075,7 @@ pvscsi_init(PCIDevice *pci_dev) /* Interrupt pin A */ pci_config_set_interrupt_pin(pci_dev->config, 1); - memory_region_init_io(&s->io_space, &pvscsi_ops, s, + memory_region_init_io(&s->io_space, OBJECT(s), &pvscsi_ops, s, "pvscsi-io", PVSCSI_MEM_SPACE_SIZE); pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->io_space); diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c index 61a8aaddd..f69775c41 100644 --- a/hw/sd/milkymist-memcard.c +++ b/hw/sd/milkymist-memcard.c @@ -253,7 +253,7 @@ static int milkymist_memcard_init(SysBusDevice *dev) s->card = sd_init(dinfo ? dinfo->bdrv : NULL, false); s->enabled = dinfo ? bdrv_is_inserted(dinfo->bdrv) : 0; - memory_region_init_io(&s->regs_region, &memcard_mmio_ops, s, + memory_region_init_io(&s->regs_region, OBJECT(s), &memcard_mmio_ops, s, "milkymist-memcard", R_MAX * 4); sysbus_init_mmio(dev, &s->regs_region); diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c index ba9f4b309..bf5d1fbf6 100644 --- a/hw/sd/omap_mmc.c +++ b/hw/sd/omap_mmc.c @@ -588,7 +588,7 @@ struct omap_mmc_s *omap_mmc_init(hwaddr base, omap_mmc_reset(s); - memory_region_init_io(&s->iomem, &omap_mmc_ops, s, "omap.mmc", 0x800); + memory_region_init_io(&s->iomem, NULL, &omap_mmc_ops, s, "omap.mmc", 0x800); memory_region_add_subregion(sysmem, base, &s->iomem); /* Instantiate the storage */ @@ -612,7 +612,7 @@ struct omap_mmc_s *omap2_mmc_init(struct omap_target_agent_s *ta, omap_mmc_reset(s); - memory_region_init_io(&s->iomem, &omap_mmc_ops, s, "omap.mmc", + memory_region_init_io(&s->iomem, NULL, &omap_mmc_ops, s, "omap.mmc", omap_l4_region_size(ta, 0)); omap_l4_attach(ta, 0, &s->iomem); diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c index e08fd04e7..f5eb1e401 100644 --- a/hw/sd/pl181.c +++ b/hw/sd/pl181.c @@ -175,7 +175,7 @@ static void pl181_send_command(pl181_state *s) if (rlen < 0) goto error; if (s->cmd & PL181_CMD_RESPONSE) { -#define RWORD(n) ((response[n] << 24) | (response[n + 1] << 16) \ +#define RWORD(n) (((uint32_t)response[n] << 24) | (response[n + 1] << 16) \ | (response[n + 2] << 8) | response[n + 3]) if (rlen == 0 || (rlen == 4 && (s->cmd & PL181_CMD_LONGRESP))) goto error; @@ -479,7 +479,7 @@ static int pl181_init(SysBusDevice *dev) pl181_state *s = FROM_SYSBUS(pl181_state, dev); DriveInfo *dinfo; - memory_region_init_io(&s->iomem, &pl181_ops, s, "pl181", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &pl181_ops, s, "pl181", 0x1000); sysbus_init_mmio(dev, &s->iomem); sysbus_init_irq(dev, &s->irq[0]); sysbus_init_irq(dev, &s->irq[1]); diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c index 0574d6b26..90c955fe6 100644 --- a/hw/sd/pxa2xx_mmci.c +++ b/hw/sd/pxa2xx_mmci.c @@ -533,7 +533,7 @@ PXA2xxMMCIState *pxa2xx_mmci_init(MemoryRegion *sysmem, s->rx_dma = rx_dma; s->tx_dma = tx_dma; - memory_region_init_io(&s->iomem, &pxa2xx_mmci_ops, s, + memory_region_init_io(&s->iomem, NULL, &pxa2xx_mmci_ops, s, "pxa2xx-mmci", 0x00100000); memory_region_add_subregion(sysmem, base, &s->iomem); diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index b9dd4bebc..d2dbddc11 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -1245,7 +1245,7 @@ static void sdhci_realize(DeviceState *dev, Error ** errp) s->buf_maxsz = sdhci_get_fifolen(s); s->fifo_buffer = g_malloc0(s->buf_maxsz); sysbus_init_irq(sbd, &s->irq); - memory_region_init_io(&s->iomem, &sdhci_mmio_ops, s, "sdhci", + memory_region_init_io(&s->iomem, OBJECT(s), &sdhci_mmio_ops, s, "sdhci", SDHC_REGISTERS_MAP_SIZE); sysbus_init_mmio(sbd, &s->iomem); } diff --git a/hw/sh4/r2d.c b/hw/sh4/r2d.c index 3e4818e17..98b3408f4 100644 --- a/hw/sh4/r2d.c +++ b/hw/sh4/r2d.c @@ -186,7 +186,7 @@ static qemu_irq *r2d_fpga_init(MemoryRegion *sysmem, s->irl = irl; - memory_region_init_io(&s->iomem, &r2d_fpga_ops, s, "r2d-fpga", 0x40); + memory_region_init_io(&s->iomem, NULL, &r2d_fpga_ops, s, "r2d-fpga", 0x40); memory_region_add_subregion(sysmem, base, &s->iomem); return qemu_allocate_irqs(r2d_fpga_irq_set, s, NR_IRQS); } @@ -236,6 +236,7 @@ static void r2d_init(QEMUMachineInitArgs *args) DeviceState *dev; SysBusDevice *busdev; MemoryRegion *address_space_mem = get_system_memory(); + PCIBus *pci_bus; if (cpu_model == NULL) { cpu_model = "SH7751R"; @@ -254,7 +255,7 @@ static void r2d_init(QEMUMachineInitArgs *args) qemu_register_reset(main_cpu_reset, reset_info); /* Allocate memory space */ - memory_region_init_ram(sdram, "r2d.sdram", SDRAM_SIZE); + memory_region_init_ram(sdram, NULL, "r2d.sdram", SDRAM_SIZE); vmstate_register_ram_global(sdram); memory_region_add_subregion(address_space_mem, SDRAM_BASE, sdram); /* Register peripherals */ @@ -264,6 +265,7 @@ static void r2d_init(QEMUMachineInitArgs *args) dev = qdev_create(NULL, "sh_pci"); busdev = SYS_BUS_DEVICE(dev); qdev_init_nofail(dev); + pci_bus = PCI_BUS(qdev_get_child_bus(dev, "pci")); sysbus_mmio_map(busdev, 0, P4ADDR(0x1e200000)); sysbus_mmio_map(busdev, 1, A7ADDR(0x1e200000)); sysbus_connect_irq(busdev, 0, irq[PCI_INTA]); @@ -295,7 +297,8 @@ static void r2d_init(QEMUMachineInitArgs *args) /* NIC: rtl8139 on-board, and 2 slots. */ for (i = 0; i < nb_nics; i++) - pci_nic_init_nofail(&nd_table[i], "rtl8139", i==0 ? "2" : NULL); + pci_nic_init_nofail(&nd_table[i], pci_bus, + "rtl8139", i==0 ? "2" : NULL); /* USB keyboard */ usbdevice_create("keyboard"); diff --git a/hw/sh4/sh7750.c b/hw/sh4/sh7750.c index 03e8bd177..1439ba44e 100644 --- a/hw/sh4/sh7750.c +++ b/hw/sh4/sh7750.c @@ -730,34 +730,34 @@ SH7750State *sh7750_init(SuperHCPU *cpu, MemoryRegion *sysmem) s = g_malloc0(sizeof(SH7750State)); s->cpu = cpu; s->periph_freq = 60000000; /* 60MHz */ - memory_region_init_io(&s->iomem, &sh7750_mem_ops, s, + memory_region_init_io(&s->iomem, NULL, &sh7750_mem_ops, s, "memory", 0x1fc01000); - memory_region_init_alias(&s->iomem_1f0, "memory-1f0", + memory_region_init_alias(&s->iomem_1f0, NULL, "memory-1f0", &s->iomem, 0x1f000000, 0x1000); memory_region_add_subregion(sysmem, 0x1f000000, &s->iomem_1f0); - memory_region_init_alias(&s->iomem_ff0, "memory-ff0", + memory_region_init_alias(&s->iomem_ff0, NULL, "memory-ff0", &s->iomem, 0x1f000000, 0x1000); memory_region_add_subregion(sysmem, 0xff000000, &s->iomem_ff0); - memory_region_init_alias(&s->iomem_1f8, "memory-1f8", + memory_region_init_alias(&s->iomem_1f8, NULL, "memory-1f8", &s->iomem, 0x1f800000, 0x1000); memory_region_add_subregion(sysmem, 0x1f800000, &s->iomem_1f8); - memory_region_init_alias(&s->iomem_ff8, "memory-ff8", + memory_region_init_alias(&s->iomem_ff8, NULL, "memory-ff8", &s->iomem, 0x1f800000, 0x1000); memory_region_add_subregion(sysmem, 0xff800000, &s->iomem_ff8); - memory_region_init_alias(&s->iomem_1fc, "memory-1fc", + memory_region_init_alias(&s->iomem_1fc, NULL, "memory-1fc", &s->iomem, 0x1fc00000, 0x1000); memory_region_add_subregion(sysmem, 0x1fc00000, &s->iomem_1fc); - memory_region_init_alias(&s->iomem_ffc, "memory-ffc", + memory_region_init_alias(&s->iomem_ffc, NULL, "memory-ffc", &s->iomem, 0x1fc00000, 0x1000); memory_region_add_subregion(sysmem, 0xffc00000, &s->iomem_ffc); - memory_region_init_io(&s->mmct_iomem, &sh7750_mmct_ops, s, + memory_region_init_io(&s->mmct_iomem, NULL, &sh7750_mmct_ops, s, "cache-and-tlb", 0x08000000); memory_region_add_subregion(sysmem, 0xf0000000, &s->mmct_iomem); diff --git a/hw/sh4/sh_pci.c b/hw/sh4/sh_pci.c index d213a9058..c33a72f80 100644 --- a/hw/sh4/sh_pci.c +++ b/hw/sh4/sh_pci.c @@ -125,10 +125,10 @@ static int sh_pci_device_init(SysBusDevice *dev) get_system_memory(), get_system_io(), PCI_DEVFN(0, 0), 4, TYPE_PCI_BUS); - memory_region_init_io(&s->memconfig_p4, &sh_pci_reg_ops, s, + memory_region_init_io(&s->memconfig_p4, OBJECT(s), &sh_pci_reg_ops, s, "sh_pci", 0x224); - memory_region_init_alias(&s->memconfig_a7, "sh_pci.2", &s->memconfig_p4, - 0, 0x224); + memory_region_init_alias(&s->memconfig_a7, OBJECT(s), "sh_pci.2", + &s->memconfig_p4, 0, 0x224); isa_mmio_setup(&s->isa, 0x40000); sysbus_init_mmio(dev, &s->memconfig_p4); sysbus_init_mmio(dev, &s->memconfig_a7); diff --git a/hw/sh4/shix.c b/hw/sh4/shix.c index ffac621a8..84dd666bd 100644 --- a/hw/sh4/shix.c +++ b/hw/sh4/shix.c @@ -59,16 +59,16 @@ static void shix_init(QEMUMachineInitArgs *args) /* Allocate memory space */ printf("Allocating ROM\n"); - memory_region_init_ram(rom, "shix.rom", 0x4000); + memory_region_init_ram(rom, NULL, "shix.rom", 0x4000); vmstate_register_ram_global(rom); memory_region_set_readonly(rom, true); memory_region_add_subregion(sysmem, 0x00000000, rom); printf("Allocating SDRAM 1\n"); - memory_region_init_ram(&sdram[0], "shix.sdram1", 0x01000000); + memory_region_init_ram(&sdram[0], NULL, "shix.sdram1", 0x01000000); vmstate_register_ram_global(&sdram[0]); memory_region_add_subregion(sysmem, 0x08000000, &sdram[0]); printf("Allocating SDRAM 2\n"); - memory_region_init_ram(&sdram[1], "shix.sdram2", 0x01000000); + memory_region_init_ram(&sdram[1], NULL, "shix.sdram2", 0x01000000); vmstate_register_ram_global(&sdram[1]); memory_region_add_subregion(sysmem, 0x0c000000, &sdram[1]); diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c index 78c77eff4..5ef282fcd 100644 --- a/hw/sparc/leon3.c +++ b/hw/sparc/leon3.c @@ -147,13 +147,13 @@ static void leon3_generic_hw_init(QEMUMachineInitArgs *args) exit(1); } - memory_region_init_ram(ram, "leon3.ram", ram_size); + memory_region_init_ram(ram, NULL, "leon3.ram", ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(address_space_mem, 0x40000000, ram); /* Allocate BIOS */ prom_size = 8 * 1024 * 1024; /* 8Mb */ - memory_region_init_ram(prom, "Leon3.bios", prom_size); + memory_region_init_ram(prom, NULL, "Leon3.bios", prom_size); vmstate_register_ram_global(prom); memory_region_set_readonly(prom, true); memory_region_add_subregion(address_space_mem, 0x00000000, prom); diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 0e86ca765..7a0c1ab77 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -264,9 +264,8 @@ static void secondary_cpu_reset(void *opaque) static void cpu_halt_signal(void *opaque, int irq, int level) { - if (level && cpu_single_env) { - cpu_interrupt(CPU(sparc_env_get_cpu(cpu_single_env)), - CPU_INTERRUPT_HALT); + if (level && current_cpu) { + cpu_interrupt(current_cpu, CPU_INTERRUPT_HALT); } } @@ -582,7 +581,8 @@ static int idreg_init1(SysBusDevice *dev) { IDRegState *s = FROM_SYSBUS(IDRegState, dev); - memory_region_init_ram(&s->mem, "sun4m.idreg", sizeof(idreg_data)); + memory_region_init_ram(&s->mem, OBJECT(s), + "sun4m.idreg", sizeof(idreg_data)); vmstate_register_ram_global(&s->mem); memory_region_set_readonly(&s->mem, true); sysbus_init_mmio(dev, &s->mem); @@ -625,7 +625,7 @@ static int afx_init1(SysBusDevice *dev) { AFXState *s = FROM_SYSBUS(AFXState, dev); - memory_region_init_ram(&s->mem, "sun4m.afx", 4); + memory_region_init_ram(&s->mem, OBJECT(s), "sun4m.afx", 4); vmstate_register_ram_global(&s->mem); sysbus_init_mmio(dev, &s->mem); return 0; @@ -695,7 +695,7 @@ static int prom_init1(SysBusDevice *dev) { PROMState *s = FROM_SYSBUS(PROMState, dev); - memory_region_init_ram(&s->prom, "sun4m.prom", PROM_SIZE_MAX); + memory_region_init_ram(&s->prom, OBJECT(s), "sun4m.prom", PROM_SIZE_MAX); vmstate_register_ram_global(&s->prom); memory_region_set_readonly(&s->prom, true); sysbus_init_mmio(dev, &s->prom); @@ -734,7 +734,7 @@ static int ram_init1(SysBusDevice *dev) { RamDevice *d = FROM_SYSBUS(RamDevice, dev); - memory_region_init_ram(&d->ram, "sun4m.ram", d->size); + memory_region_init_ram(&d->ram, OBJECT(d), "sun4m.ram", d->size); vmstate_register_ram_global(&d->ram); sysbus_init_mmio(dev, &d->ram); return 0; diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index a6a3b76a7..564c1959e 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -680,7 +680,7 @@ static int prom_init1(SysBusDevice *dev) { PROMState *s = FROM_SYSBUS(PROMState, dev); - memory_region_init_ram(&s->prom, "sun4u.prom", PROM_SIZE_MAX); + memory_region_init_ram(&s->prom, OBJECT(s), "sun4u.prom", PROM_SIZE_MAX); vmstate_register_ram_global(&s->prom); memory_region_set_readonly(&s->prom, true); sysbus_init_mmio(dev, &s->prom); @@ -720,7 +720,7 @@ static int ram_init1(SysBusDevice *dev) { RamDevice *d = FROM_SYSBUS(RamDevice, dev); - memory_region_init_ram(&d->ram, "sun4u.ram", d->size); + memory_region_init_ram(&d->ram, OBJECT(d), "sun4u.ram", d->size); vmstate_register_ram_global(&d->ram); sysbus_init_mmio(dev, &d->ram); return 0; @@ -854,7 +854,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem, } for(i = 0; i < nb_nics; i++) - pci_nic_init_nofail(&nd_table[i], "ne2k_pci", NULL); + pci_nic_init_nofail(&nd_table[i], pci_bus, "ne2k_pci", NULL); ide_drive_get(hd, MAX_IDE_BUS); diff --git a/hw/ssi/omap_spi.c b/hw/ssi/omap_spi.c index 11403c411..0ed3b110e 100644 --- a/hw/ssi/omap_spi.c +++ b/hw/ssi/omap_spi.c @@ -354,7 +354,7 @@ struct omap_mcspi_s *omap_mcspi_init(struct omap_target_agent_s *ta, int chnum, } omap_mcspi_reset(s); - memory_region_init_io(&s->iomem, &omap_mcspi_ops, s, "omap.mcspi", + memory_region_init_io(&s->iomem, NULL, &omap_mcspi_ops, s, "omap.mcspi", omap_l4_region_size(ta, 0)); omap_l4_attach(ta, 0, &s->iomem); diff --git a/hw/ssi/pl022.c b/hw/ssi/pl022.c index 536c2166f..711a0c17a 100644 --- a/hw/ssi/pl022.c +++ b/hw/ssi/pl022.c @@ -277,7 +277,7 @@ static int pl022_init(SysBusDevice *dev) { pl022_state *s = FROM_SYSBUS(pl022_state, dev); - memory_region_init_io(&s->iomem, &pl022_ops, s, "pl022", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &pl022_ops, s, "pl022", 0x1000); sysbus_init_mmio(dev, &s->iomem); sysbus_init_irq(dev, &s->irq); s->ssi = ssi_create_bus(&dev->qdev, "ssi"); diff --git a/hw/ssi/xilinx_spi.c b/hw/ssi/xilinx_spi.c index f6bd3bac2..7a9fd8158 100644 --- a/hw/ssi/xilinx_spi.c +++ b/hw/ssi/xilinx_spi.c @@ -330,7 +330,8 @@ static int xilinx_spi_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->cs_lines[i]); } - memory_region_init_io(&s->mmio, &spi_ops, s, "xilinx-spi", R_MAX * 4); + memory_region_init_io(&s->mmio, OBJECT(s), &spi_ops, s, + "xilinx-spi", R_MAX * 4); sysbus_init_mmio(dev, &s->mmio); s->irqline = -1; diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c index 05a3adaa9..6a287464b 100644 --- a/hw/ssi/xilinx_spips.c +++ b/hw/ssi/xilinx_spips.c @@ -663,7 +663,8 @@ static void xilinx_spips_realize(DeviceState *dev, Error **errp) sysbus_init_irq(sbd, &s->cs_lines[i]); } - memory_region_init_io(&s->iomem, xsc->reg_ops, s, "spi", R_MAX*4); + memory_region_init_io(&s->iomem, OBJECT(s), xsc->reg_ops, s, + "spi", R_MAX*4); sysbus_init_mmio(sbd, &s->iomem); s->irqline = -1; @@ -685,7 +686,7 @@ static void xilinx_qspips_realize(DeviceState *dev, Error **errp) s->num_txrx_bytes = 4; xilinx_spips_realize(dev, errp); - memory_region_init_io(&s->mmlqspi, &lqspi_ops, s, "lqspi", + memory_region_init_io(&s->mmlqspi, OBJECT(s), &lqspi_ops, s, "lqspi", (1 << LQSPI_ADDRESS_BITS) * 2); sysbus_init_mmio(sbd, &s->mmlqspi); diff --git a/hw/timer/Makefile.objs b/hw/timer/Makefile.objs index 32b5c1a9b..eca590570 100644 --- a/hw/timer/Makefile.objs +++ b/hw/timer/Makefile.objs @@ -1,4 +1,5 @@ common-obj-$(CONFIG_ARM_TIMER) += arm_timer.o +common-obj-$(CONFIG_ARM_MPTIMER) += arm_mptimer.o common-obj-$(CONFIG_CADENCE) += cadence_ttc.o common-obj-$(CONFIG_DS1338) += ds1338.o common-obj-$(CONFIG_HPET) += hpet.o @@ -25,5 +26,4 @@ obj-$(CONFIG_PXA2XX) += pxa2xx_timer.o obj-$(CONFIG_SH4) += sh_timer.o obj-$(CONFIG_TUSB6010) += tusb6010.o -obj-$(CONFIG_ARM_MPTIMER) += arm_mptimer.o obj-$(CONFIG_MC146818RTC) += mc146818rtc.o diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c index 317f5e43e..0ceb24049 100644 --- a/hw/timer/arm_mptimer.c +++ b/hw/timer/arm_mptimer.c @@ -21,6 +21,7 @@ #include "hw/sysbus.h" #include "qemu/timer.h" +#include "qom/cpu.h" /* This device implements the per-cpu private timer and watchdog block * which is used in both the ARM11MPCore and Cortex-A9MP. @@ -49,13 +50,11 @@ typedef struct { static inline int get_current_cpu(ARMMPTimerState *s) { - CPUState *cpu_single_cpu = ENV_GET_CPU(cpu_single_env); - - if (cpu_single_cpu->cpu_index >= s->num_cpu) { + if (current_cpu->cpu_index >= s->num_cpu) { hw_error("arm_mptimer: num-cpu %d but this cpu is %d!\n", - s->num_cpu, cpu_single_cpu->cpu_index); + s->num_cpu, current_cpu->cpu_index); } - return cpu_single_cpu->cpu_index; + return current_cpu->cpu_index; } static inline void timerblock_update_irq(TimerBlock *tb) @@ -236,14 +235,14 @@ static int arm_mptimer_init(SysBusDevice *dev) * * timer for core 1 * and so on. */ - memory_region_init_io(&s->iomem, &arm_thistimer_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &arm_thistimer_ops, s, "arm_mptimer_timer", 0x20); sysbus_init_mmio(dev, &s->iomem); for (i = 0; i < s->num_cpu; i++) { TimerBlock *tb = &s->timerblock[i]; tb->timer = qemu_new_timer_ns(vm_clock, timerblock_tick, tb); sysbus_init_irq(dev, &tb->irq); - memory_region_init_io(&tb->iomem, &timerblock_ops, tb, + memory_region_init_io(&tb->iomem, OBJECT(s), &timerblock_ops, tb, "arm_mptimer_timerblock", 0x20); sysbus_init_mmio(dev, &tb->iomem); } diff --git a/hw/timer/arm_timer.c b/hw/timer/arm_timer.c index 644987046..798a8dabc 100644 --- a/hw/timer/arm_timer.c +++ b/hw/timer/arm_timer.c @@ -284,7 +284,8 @@ static int sp804_init(SysBusDevice *dev) s->timer[1] = arm_timer_init(s->freq1); s->timer[0]->irq = qi[0]; s->timer[1]->irq = qi[1]; - memory_region_init_io(&s->iomem, &sp804_ops, s, "sp804", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &sp804_ops, s, + "sp804", 0x1000); sysbus_init_mmio(dev, &s->iomem); vmstate_register(&dev->qdev, -1, &vmstate_sp804, s); return 0; @@ -347,7 +348,8 @@ static int icp_pit_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->timer[1]->irq); sysbus_init_irq(dev, &s->timer[2]->irq); - memory_region_init_io(&s->iomem, &icp_pit_ops, s, "icp_pit", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &icp_pit_ops, s, + "icp_pit", 0x1000); sysbus_init_mmio(dev, &s->iomem); /* This device has no state to save/restore. The component timers will save themselves. */ diff --git a/hw/timer/cadence_ttc.c b/hw/timer/cadence_ttc.c index ba584f471..a861049e5 100644 --- a/hw/timer/cadence_ttc.c +++ b/hw/timer/cadence_ttc.c @@ -409,7 +409,8 @@ static int cadence_ttc_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->timer[i].irq); } - memory_region_init_io(&s->iomem, &cadence_ttc_ops, s, "timer", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &cadence_ttc_ops, s, + "timer", 0x1000); sysbus_init_mmio(dev, &s->iomem); return 0; diff --git a/hw/timer/etraxfs_timer.c b/hw/timer/etraxfs_timer.c index 3cd9476bb..6dd107209 100644 --- a/hw/timer/etraxfs_timer.c +++ b/hw/timer/etraxfs_timer.c @@ -323,7 +323,8 @@ static int etraxfs_timer_init(SysBusDevice *dev) sysbus_init_irq(dev, &t->irq); sysbus_init_irq(dev, &t->nmi); - memory_region_init_io(&t->mmio, &timer_ops, t, "etraxfs-timer", 0x5c); + memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t, + "etraxfs-timer", 0x5c); sysbus_init_mmio(dev, &t->mmio); qemu_register_reset(etraxfs_timer_reset, t); return 0; diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c index 38dcc1ac6..28ebe5dc7 100644 --- a/hw/timer/exynos4210_mct.c +++ b/hw/timer/exynos4210_mct.c @@ -1449,8 +1449,8 @@ static int exynos4210_mct_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->l_timer[i].irq); } - memory_region_init_io(&s->iomem, &exynos4210_mct_ops, s, "exynos4210-mct", - MCT_SFR_SIZE); + memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_mct_ops, s, + "exynos4210-mct", MCT_SFR_SIZE); sysbus_init_mmio(dev, &s->iomem); return 0; diff --git a/hw/timer/exynos4210_pwm.c b/hw/timer/exynos4210_pwm.c index 185ccb9a7..8fa0bb2b8 100644 --- a/hw/timer/exynos4210_pwm.c +++ b/hw/timer/exynos4210_pwm.c @@ -390,8 +390,8 @@ static int exynos4210_pwm_init(SysBusDevice *dev) s->timer[i].parent = s; } - memory_region_init_io(&s->iomem, &exynos4210_pwm_ops, s, "exynos4210-pwm", - EXYNOS4210_PWM_REG_MEM_SIZE); + memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_pwm_ops, s, + "exynos4210-pwm", EXYNOS4210_PWM_REG_MEM_SIZE); sysbus_init_mmio(dev, &s->iomem); return 0; diff --git a/hw/timer/exynos4210_rtc.c b/hw/timer/exynos4210_rtc.c index 3ac77f926..7fca071f1 100644 --- a/hw/timer/exynos4210_rtc.c +++ b/hw/timer/exynos4210_rtc.c @@ -559,8 +559,8 @@ static int exynos4210_rtc_init(SysBusDevice *dev) sysbus_init_irq(dev, &s->alm_irq); sysbus_init_irq(dev, &s->tick_irq); - memory_region_init_io(&s->iomem, &exynos4210_rtc_ops, s, "exynos4210-rtc", - EXYNOS4210_RTC_REG_MEM_SIZE); + memory_region_init_io(&s->iomem, OBJECT(s), &exynos4210_rtc_ops, s, + "exynos4210-rtc", EXYNOS4210_RTC_REG_MEM_SIZE); sysbus_init_mmio(dev, &s->iomem); return 0; diff --git a/hw/timer/grlib_gptimer.c b/hw/timer/grlib_gptimer.c index 7043a3468..37ba47d07 100644 --- a/hw/timer/grlib_gptimer.c +++ b/hw/timer/grlib_gptimer.c @@ -365,7 +365,8 @@ static int grlib_gptimer_init(SysBusDevice *dev) ptimer_set_freq(timer->ptimer, unit->freq_hz); } - memory_region_init_io(&unit->iomem, &grlib_gptimer_ops, unit, "gptimer", + memory_region_init_io(&unit->iomem, OBJECT(unit), &grlib_gptimer_ops, + unit, "gptimer", UNIT_REG_SIZE + GPTIMER_REG_SIZE * unit->nr_timers); sysbus_init_mmio(dev, &unit->iomem); diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c index 95dd01d14..90bd5846b 100644 --- a/hw/timer/hpet.c +++ b/hw/timer/hpet.c @@ -722,7 +722,7 @@ static int hpet_init(SysBusDevice *dev) qdev_init_gpio_out(&dev->qdev, &s->pit_enabled, 1); /* HPET Area */ - memory_region_init_io(&s->iomem, &hpet_ram_ops, s, "hpet", 0x400); + memory_region_init_io(&s->iomem, OBJECT(s), &hpet_ram_ops, s, "hpet", 0x400); sysbus_init_mmio(dev, &s->iomem); return 0; } diff --git a/hw/timer/i8254.c b/hw/timer/i8254.c index 16c8dd687..cd5214064 100644 --- a/hw/timer/i8254.c +++ b/hw/timer/i8254.c @@ -333,7 +333,8 @@ static void pit_realizefn(DeviceState *dev, Error **err) s->irq_timer = qemu_new_timer_ns(vm_clock, pit_irq_timer, s); qdev_init_gpio_out(dev, &s->irq, 1); - memory_region_init_io(&pit->ioports, &pit_ioport_ops, pit, "pit", 4); + memory_region_init_io(&pit->ioports, OBJECT(pit), &pit_ioport_ops, + pit, "pit", 4); qdev_init_gpio_in(dev, pit_irq_control, 1); diff --git a/hw/timer/imx_epit.c b/hw/timer/imx_epit.c index 7cdb0060a..e24e0c491 100644 --- a/hw/timer/imx_epit.c +++ b/hw/timer/imx_epit.c @@ -396,7 +396,7 @@ static void imx_epit_realize(DeviceState *dev, Error **errp) DPRINTF("\n"); sysbus_init_irq(sbd, &s->irq); - memory_region_init_io(&s->iomem, &imx_epit_ops, s, TYPE_IMX_EPIT, + memory_region_init_io(&s->iomem, OBJECT(s), &imx_epit_ops, s, TYPE_IMX_EPIT, 0x00001000); sysbus_init_mmio(sbd, &s->iomem); diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c index de53b1328..97fbebbe8 100644 --- a/hw/timer/imx_gpt.c +++ b/hw/timer/imx_gpt.c @@ -514,7 +514,7 @@ static void imx_gpt_realize(DeviceState *dev, Error **errp) QEMUBH *bh; sysbus_init_irq(sbd, &s->irq); - memory_region_init_io(&s->iomem, &imx_gpt_ops, s, TYPE_IMX_GPT, + memory_region_init_io(&s->iomem, OBJECT(s), &imx_gpt_ops, s, TYPE_IMX_GPT, 0x00001000); sysbus_init_mmio(sbd, &s->iomem); diff --git a/hw/timer/lm32_timer.c b/hw/timer/lm32_timer.c index e06fac708..016dade3e 100644 --- a/hw/timer/lm32_timer.c +++ b/hw/timer/lm32_timer.c @@ -180,7 +180,8 @@ static int lm32_timer_init(SysBusDevice *dev) s->ptimer = ptimer_init(s->bh); ptimer_set_freq(s->ptimer, s->freq_hz); - memory_region_init_io(&s->iomem, &timer_ops, s, "timer", R_MAX * 4); + memory_region_init_io(&s->iomem, OBJECT(s), &timer_ops, s, + "timer", R_MAX * 4); sysbus_init_mmio(dev, &s->iomem); return 0; diff --git a/hw/timer/m48t59.c b/hw/timer/m48t59.c index bf6c4c876..be3490bca 100644 --- a/hw/timer/m48t59.c +++ b/hw/timer/m48t59.c @@ -655,7 +655,8 @@ M48t59State *m48t59_init(qemu_irq IRQ, hwaddr mem_base, d = FROM_SYSBUS(M48t59SysBusState, s); state = &d->state; sysbus_connect_irq(s, 0, IRQ); - memory_region_init_io(&d->io, &m48t59_io_ops, state, "m48t59", 4); + memory_region_init_io(&d->io, OBJECT(d), &m48t59_io_ops, state, + "m48t59", 4); if (io_base != 0) { memory_region_add_subregion(get_system_io(), io_base, &d->io); } @@ -683,7 +684,7 @@ M48t59State *m48t59_init_isa(ISABus *bus, uint32_t io_base, uint16_t size, d = ISA_M48T59(isadev); s = &d->state; - memory_region_init_io(&d->io, &m48t59_io_ops, s, "m48t59", 4); + memory_region_init_io(&d->io, OBJECT(d), &m48t59_io_ops, s, "m48t59", 4); if (io_base != 0) { isa_register_ioport(isadev, &d->io, io_base); } @@ -721,7 +722,8 @@ static int m48t59_init1(SysBusDevice *dev) sysbus_init_irq(dev, &s->IRQ); - memory_region_init_io(&s->iomem, &nvram_ops, s, "m48t59.nvram", s->size); + memory_region_init_io(&s->iomem, OBJECT(d), &nvram_ops, s, + "m48t59.nvram", s->size); sysbus_init_mmio(dev, &s->iomem); m48t59_realize_common(s, &err); if (err != NULL) { diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c index 9c4a7bd07..3c3baaccf 100644 --- a/hw/timer/mc146818rtc.c +++ b/hw/timer/mc146818rtc.c @@ -863,7 +863,7 @@ static void rtc_realizefn(DeviceState *dev, Error **errp) s->suspend_notifier.notify = rtc_notify_suspend; qemu_register_suspend_notifier(&s->suspend_notifier); - memory_region_init_io(&s->io, &cmos_ops, s, "rtc", 2); + memory_region_init_io(&s->io, OBJECT(s), &cmos_ops, s, "rtc", 2); isa_register_ioport(isadev, &s->io, base); qdev_set_legacy_instance_id(dev, base, 3); diff --git a/hw/timer/milkymist-sysctl.c b/hw/timer/milkymist-sysctl.c index e083a280c..500939493 100644 --- a/hw/timer/milkymist-sysctl.c +++ b/hw/timer/milkymist-sysctl.c @@ -280,7 +280,7 @@ static int milkymist_sysctl_init(SysBusDevice *dev) ptimer_set_freq(s->ptimer0, s->freq_hz); ptimer_set_freq(s->ptimer1, s->freq_hz); - memory_region_init_io(&s->regs_region, &sysctl_mmio_ops, s, + memory_region_init_io(&s->regs_region, OBJECT(s), &sysctl_mmio_ops, s, "milkymist-sysctl", R_MAX * 4); sysbus_init_mmio(dev, &s->regs_region); diff --git a/hw/timer/omap_gptimer.c b/hw/timer/omap_gptimer.c index 9b0e9dd56..ac389d87e 100644 --- a/hw/timer/omap_gptimer.c +++ b/hw/timer/omap_gptimer.c @@ -480,7 +480,7 @@ struct omap_gp_timer_s *omap_gp_timer_init(struct omap_target_agent_s *ta, omap_gp_timer_reset(s); omap_gp_timer_clk_setup(s); - memory_region_init_io(&s->iomem, &omap_gp_timer_ops, s, "omap.gptimer", + memory_region_init_io(&s->iomem, NULL, &omap_gp_timer_ops, s, "omap.gptimer", omap_l4_region_size(ta, 0)); omap_l4_attach(ta, 0, &s->iomem); diff --git a/hw/timer/omap_synctimer.c b/hw/timer/omap_synctimer.c index a24f35c27..a12aca20d 100644 --- a/hw/timer/omap_synctimer.c +++ b/hw/timer/omap_synctimer.c @@ -94,7 +94,7 @@ struct omap_synctimer_s *omap_synctimer_init(struct omap_target_agent_s *ta, struct omap_synctimer_s *s = g_malloc0(sizeof(*s)); omap_synctimer_reset(s); - memory_region_init_io(&s->iomem, &omap_synctimer_ops, s, "omap.synctimer", + memory_region_init_io(&s->iomem, NULL, &omap_synctimer_ops, s, "omap.synctimer", omap_l4_region_size(ta, 0)); omap_l4_attach(ta, 0, &s->iomem); diff --git a/hw/timer/pl031.c b/hw/timer/pl031.c index 764940be7..3ce6ed8ae 100644 --- a/hw/timer/pl031.c +++ b/hw/timer/pl031.c @@ -192,7 +192,7 @@ static int pl031_init(SysBusDevice *dev) pl031_state *s = FROM_SYSBUS(pl031_state, dev); struct tm tm; - memory_region_init_io(&s->iomem, &pl031_ops, s, "pl031", 0x1000); + memory_region_init_io(&s->iomem, OBJECT(s), &pl031_ops, s, "pl031", 0x1000); sysbus_init_mmio(dev, &s->iomem); sysbus_init_irq(dev, &s->irq); diff --git a/hw/timer/puv3_ost.c b/hw/timer/puv3_ost.c index 0c3d82797..63f2c9f02 100644 --- a/hw/timer/puv3_ost.c +++ b/hw/timer/puv3_ost.c @@ -122,7 +122,7 @@ static int puv3_ost_init(SysBusDevice *dev) s->ptimer = ptimer_init(s->bh); ptimer_set_freq(s->ptimer, 50 * 1000 * 1000); - memory_region_init_io(&s->iomem, &puv3_ost_ops, s, "puv3_ost", + memory_region_init_io(&s->iomem, OBJECT(s), &puv3_ost_ops, s, "puv3_ost", PUV3_REGS_OFFSET); sysbus_init_mmio(dev, &s->iomem); diff --git a/hw/timer/pxa2xx_timer.c b/hw/timer/pxa2xx_timer.c index 8ea2416dd..4d28719bb 100644 --- a/hw/timer/pxa2xx_timer.c +++ b/hw/timer/pxa2xx_timer.c @@ -461,7 +461,7 @@ static int pxa2xx_timer_init(SysBusDevice *dev) } } - memory_region_init_io(&s->iomem, &pxa2xx_timer_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_timer_ops, s, "pxa2xx-timer", 0x00001000); sysbus_init_mmio(dev, &s->iomem); diff --git a/hw/timer/sh_timer.c b/hw/timer/sh_timer.c index f92ff4f73..251a10dbf 100644 --- a/hw/timer/sh_timer.c +++ b/hw/timer/sh_timer.c @@ -319,14 +319,14 @@ void tmu012_init(MemoryRegion *sysmem, hwaddr base, s->timer[2] = sh_timer_init(freq, timer_feat | TIMER_FEAT_CAPT, ch2_irq0); /* ch2_irq1 not supported */ - memory_region_init_io(&s->iomem, &tmu012_ops, s, + memory_region_init_io(&s->iomem, NULL, &tmu012_ops, s, "timer", 0x100000000ULL); - memory_region_init_alias(&s->iomem_p4, "timer-p4", + memory_region_init_alias(&s->iomem_p4, NULL, "timer-p4", &s->iomem, 0, 0x1000); memory_region_add_subregion(sysmem, P4ADDR(base), &s->iomem_p4); - memory_region_init_alias(&s->iomem_a7, "timer-a7", + memory_region_init_alias(&s->iomem_a7, NULL, "timer-a7", &s->iomem, 0, 0x1000); memory_region_add_subregion(sysmem, A7ADDR(base), &s->iomem_a7); /* ??? Save/restore. */ diff --git a/hw/timer/slavio_timer.c b/hw/timer/slavio_timer.c index 1145a8760..7f844d702 100644 --- a/hw/timer/slavio_timer.c +++ b/hw/timer/slavio_timer.c @@ -394,7 +394,7 @@ static int slavio_timer_init1(SysBusDevice *dev) size = i == 0 ? SYS_TIMER_SIZE : CPU_TIMER_SIZE; snprintf(timer_name, sizeof(timer_name), "timer-%i", i); - memory_region_init_io(&tc->iomem, &slavio_timer_mem_ops, tc, + memory_region_init_io(&tc->iomem, OBJECT(s), &slavio_timer_mem_ops, tc, timer_name, size); sysbus_init_mmio(dev, &tc->iomem); diff --git a/hw/timer/tusb6010.c b/hw/timer/tusb6010.c index 50edc063d..47b680922 100644 --- a/hw/timer/tusb6010.c +++ b/hw/timer/tusb6010.c @@ -779,8 +779,8 @@ static int tusb6010_init(SysBusDevice *dev) TUSBState *s = FROM_SYSBUS(TUSBState, dev); s->otg_timer = qemu_new_timer_ns(vm_clock, tusb_otg_tick, s); s->pwr_timer = qemu_new_timer_ns(vm_clock, tusb_power_tick, s); - memory_region_init_io(&s->iomem[1], &tusb_async_ops, s, "tusb-async", - UINT32_MAX); + memory_region_init_io(&s->iomem[1], OBJECT(s), &tusb_async_ops, s, + "tusb-async", UINT32_MAX); sysbus_init_mmio(dev, &s->iomem[0]); sysbus_init_mmio(dev, &s->iomem[1]); sysbus_init_irq(dev, &s->irq); diff --git a/hw/timer/xilinx_timer.c b/hw/timer/xilinx_timer.c index 0c39cff08..ee5383498 100644 --- a/hw/timer/xilinx_timer.c +++ b/hw/timer/xilinx_timer.c @@ -218,7 +218,7 @@ static int xilinx_timer_init(SysBusDevice *dev) ptimer_set_freq(xt->ptimer, t->freq_hz); } - memory_region_init_io(&t->mmio, &timer_ops, t, "xlnx.xps-timer", + memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t, "xlnx.xps-timer", R_MAX * 4 * num_timers(t)); sysbus_init_mmio(dev, &t->mmio); return 0; diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c index d4d815287..abe384ba9 100644 --- a/hw/tpm/tpm_tis.c +++ b/hw/tpm/tpm_tis.c @@ -888,7 +888,8 @@ static void tpm_tis_initfn(Object *obj) ISADevice *dev = ISA_DEVICE(obj); TPMState *s = TPM(obj); - memory_region_init_io(&s->mmio, &tpm_tis_memory_ops, s, "tpm-tis-mmio", + memory_region_init_io(&s->mmio, OBJECT(s), &tpm_tis_memory_ops, + s, "tpm-tis-mmio", TPM_TIS_NUM_LOCALITIES << TPM_TIS_LOCALITY_SHIFT); memory_region_add_subregion(isa_address_space(dev), TPM_TIS_ADDR_BASE, &s->mmio); diff --git a/hw/unicore32/puv3.c b/hw/unicore32/puv3.c index 56d1afa4f..5ff0dc9a0 100644 --- a/hw/unicore32/puv3.c +++ b/hw/unicore32/puv3.c @@ -73,7 +73,7 @@ static void puv3_board_init(CPUUniCore32State *env, ram_addr_t ram_size) MemoryRegion *ram_memory = g_new(MemoryRegion, 1); /* SDRAM at address zero. */ - memory_region_init_ram(ram_memory, "puv3.ram", ram_size); + memory_region_init_ram(ram_memory, NULL, "puv3.ram", ram_size); vmstate_register_ram_global(ram_memory); memory_region_add_subregion(get_system_memory(), 0, ram_memory); } diff --git a/hw/usb/hcd-ehci-sysbus.c b/hw/usb/hcd-ehci-sysbus.c index e7d4f74b8..54147b5fe 100644 --- a/hw/usb/hcd-ehci-sysbus.c +++ b/hw/usb/hcd-ehci-sysbus.c @@ -173,7 +173,7 @@ static void fusbh200_ehci_init(Object *obj) FUSBH200EHCIState *f = FUSBH200_EHCI(obj); EHCIState *s = &i->ehci; - memory_region_init_io(&f->mem_vendor, &fusbh200_ehci_mmio_ops, s, + memory_region_init_io(&f->mem_vendor, OBJECT(f), &fusbh200_ehci_mmio_ops, s, "fusbh200", 0x4c); memory_region_add_subregion(&s->mem, s->opregbase + s->portscbase + 4 * s->portnr, diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 16d6356fa..67e4b2427 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -1241,11 +1241,13 @@ static int ehci_init_transfer(EHCIPacket *p) { uint32_t cpage, offset, bytes, plen; dma_addr_t page; + USBBus *bus = &p->queue->ehci->bus; + BusState *qbus = BUS(bus); cpage = get_field(p->qtd.token, QTD_TOKEN_CPAGE); bytes = get_field(p->qtd.token, QTD_TOKEN_TBYTES); offset = p->qtd.bufptr[0] & ~QTD_BUFPTR_MASK; - qemu_sglist_init(&p->sgl, 5, p->queue->ehci->as); + qemu_sglist_init(&p->sgl, qbus->parent, 5, p->queue->ehci->as); while (bytes > 0) { if (cpage > 4) { @@ -1484,7 +1486,7 @@ static int ehci_process_itd(EHCIState *ehci, return -1; } - qemu_sglist_init(&ehci->isgl, 2, ehci->as); + qemu_sglist_init(&ehci->isgl, DEVICE(ehci), 2, ehci->as); if (off + len > 4096) { /* transfer crosses page border */ uint32_t len2 = off + len - 4096; @@ -2551,12 +2553,12 @@ void usb_ehci_init(EHCIState *s, DeviceState *dev) QTAILQ_INIT(&s->pqueues); usb_packet_init(&s->ipacket); - memory_region_init(&s->mem, "ehci", MMIO_SIZE); - memory_region_init_io(&s->mem_caps, &ehci_mmio_caps_ops, s, + memory_region_init(&s->mem, OBJECT(dev), "ehci", MMIO_SIZE); + memory_region_init_io(&s->mem_caps, OBJECT(dev), &ehci_mmio_caps_ops, s, "capabilities", CAPA_SIZE); - memory_region_init_io(&s->mem_opreg, &ehci_mmio_opreg_ops, s, + memory_region_init_io(&s->mem_opreg, OBJECT(dev), &ehci_mmio_opreg_ops, s, "operational", s->portscbase); - memory_region_init_io(&s->mem_ports, &ehci_mmio_port_ops, s, + memory_region_init_io(&s->mem_ports, OBJECT(dev), &ehci_mmio_port_ops, s, "ports", 4 * s->portnr); memory_region_add_subregion(&s->mem, s->capsbase, &s->mem_caps); diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index 551392413..a096ecf21 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -1830,7 +1830,8 @@ static int usb_ohci_init(OHCIState *ohci, DeviceState *dev, } } - memory_region_init_io(&ohci->mem, &ohci_mem_ops, ohci, "ohci", 256); + memory_region_init_io(&ohci->mem, OBJECT(dev), &ohci_mem_ops, + ohci, "ohci", 256); ohci->localmem_base = localmem_base; ohci->name = object_get_typename(OBJECT(dev)); diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index c85b2038a..066072eb3 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -1259,7 +1259,9 @@ static int usb_uhci_common_initfn(PCIDevice *dev) qemu_register_reset(uhci_reset, s); - memory_region_init_io(&s->io_bar, &uhci_ioport_ops, s, "uhci", 0x20); + memory_region_init_io(&s->io_bar, OBJECT(s), &uhci_ioport_ops, s, + "uhci", 0x20); + /* Use region 4 for consistency with real hardware. BSD guests seem to rely on this. */ pci_register_bar(&s->dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar); diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 91633edbc..d7a54fd53 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -3342,14 +3342,14 @@ static int usb_xhci_initfn(struct PCIDevice *dev) xhci->irq = xhci->pci_dev.irq[0]; - memory_region_init(&xhci->mem, "xhci", LEN_REGS); - memory_region_init_io(&xhci->mem_cap, &xhci_cap_ops, xhci, + memory_region_init(&xhci->mem, OBJECT(xhci), "xhci", LEN_REGS); + memory_region_init_io(&xhci->mem_cap, OBJECT(xhci), &xhci_cap_ops, xhci, "capabilities", LEN_CAP); - memory_region_init_io(&xhci->mem_oper, &xhci_oper_ops, xhci, + memory_region_init_io(&xhci->mem_oper, OBJECT(xhci), &xhci_oper_ops, xhci, "operational", 0x400); - memory_region_init_io(&xhci->mem_runtime, &xhci_runtime_ops, xhci, + memory_region_init_io(&xhci->mem_runtime, OBJECT(xhci), &xhci_runtime_ops, xhci, "runtime", LEN_RUNTIME); - memory_region_init_io(&xhci->mem_doorbell, &xhci_doorbell_ops, xhci, + memory_region_init_io(&xhci->mem_doorbell, OBJECT(xhci), &xhci_doorbell_ops, xhci, "doorbell", LEN_DOORBELL); memory_region_add_subregion(&xhci->mem, 0, &xhci->mem_cap); @@ -3361,7 +3361,7 @@ static int usb_xhci_initfn(struct PCIDevice *dev) XHCIPort *port = &xhci->ports[i]; uint32_t offset = OFF_OPER + 0x400 + 0x10 * i; port->xhci = xhci; - memory_region_init_io(&port->mem, &xhci_port_ops, port, + memory_region_init_io(&port->mem, OBJECT(xhci), &xhci_port_ops, port, port->name, 0x10); memory_region_add_subregion(&xhci->mem, offset, &port->mem); } diff --git a/hw/virtio/dataplane/hostmem.c b/hw/virtio/dataplane/hostmem.c index 7e46723eb..901d98b8a 100644 --- a/hw/virtio/dataplane/hostmem.c +++ b/hw/virtio/dataplane/hostmem.c @@ -64,8 +64,12 @@ out: static void hostmem_listener_commit(MemoryListener *listener) { HostMem *hostmem = container_of(listener, HostMem, listener); + int i; qemu_mutex_lock(&hostmem->current_regions_lock); + for (i = 0; i < hostmem->num_current_regions; i++) { + memory_region_unref(hostmem->current_regions[i].mr); + } g_free(hostmem->current_regions); hostmem->current_regions = hostmem->new_regions; hostmem->num_current_regions = hostmem->num_new_regions; @@ -92,8 +96,11 @@ static void hostmem_append_new_region(HostMem *hostmem, .guest_addr = section->offset_within_address_space, .size = int128_get64(section->size), .readonly = section->readonly, + .mr = section->mr, }; hostmem->num_new_regions++; + + memory_region_ref(section->mr); } static void hostmem_listener_append_region(MemoryListener *listener, diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index baf84ea0b..8f6ab130e 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -16,6 +16,7 @@ #include #include "hw/virtio/vhost.h" #include "hw/hw.h" +#include "qemu/atomic.h" #include "qemu/range.h" #include #include "exec/address-spaces.h" @@ -47,11 +48,9 @@ static void vhost_dev_sync_region(struct vhost_dev *dev, addr += VHOST_LOG_CHUNK; continue; } - /* Data must be read atomically. We don't really - * need the barrier semantics of __sync - * builtins, but it's easier to use them than - * roll our own. */ - log = __sync_fetch_and_and(from, 0); + /* Data must be read atomically. We don't really need barrier semantics + * but it's easier to use atomic_* than roll our own. */ + log = atomic_xchg(from, 0); while ((bit = sizeof(log) > sizeof(int) ? ffsll(log) : ffs(log))) { hwaddr page_addr; @@ -497,6 +496,7 @@ static void vhost_region_add(MemoryListener *listener, dev->mem_sections = g_renew(MemoryRegionSection, dev->mem_sections, dev->n_mem_sections); dev->mem_sections[dev->n_mem_sections - 1] = *section; + memory_region_ref(section->mr); vhost_set_memory(listener, section, true); } @@ -512,6 +512,7 @@ static void vhost_region_del(MemoryListener *listener, } vhost_set_memory(listener, section, false); + memory_region_unref(section->mr); for (i = 0; i < dev->n_mem_sections; ++i) { if (dev->mem_sections[i].offset_within_address_space == section->offset_within_address_space) { diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c index a27051c2e..3fa72a97b 100644 --- a/hw/virtio/virtio-balloon.c +++ b/hw/virtio/virtio-balloon.c @@ -205,6 +205,7 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq) addr = section.offset_within_region; balloon_page(memory_region_get_ram_ptr(section.mr) + addr, !!(vq == s->dvq)); + memory_region_unref(section.mr); } virtqueue_push(vq, &elem, offset); diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index b070b6400..c38cfd151 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -966,8 +966,8 @@ static void virtio_pci_device_plugged(DeviceState *d) size = 1 << qemu_fls(size); } - memory_region_init_io(&proxy->bar, &virtio_pci_config_ops, proxy, - "virtio-pci", size); + memory_region_init_io(&proxy->bar, OBJECT(proxy), &virtio_pci_config_ops, + proxy, "virtio-pci", size); pci_register_bar(&proxy->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &proxy->bar); diff --git a/hw/watchdog/wdt_i6300esb.c b/hw/watchdog/wdt_i6300esb.c index 05af0b1b6..85aebc28a 100644 --- a/hw/watchdog/wdt_i6300esb.c +++ b/hw/watchdog/wdt_i6300esb.c @@ -417,7 +417,8 @@ static int i6300esb_init(PCIDevice *dev) d->timer = qemu_new_timer_ns(vm_clock, i6300esb_timer_expired, d); d->previous_reboot_flag = 0; - memory_region_init_io(&d->io_mem, &i6300esb_ops, d, "i6300esb", 0x10); + memory_region_init_io(&d->io_mem, OBJECT(d), &i6300esb_ops, d, + "i6300esb", 0x10); pci_register_bar(&d->dev, 0, 0, &d->io_mem); /* qemu_register_coalesced_mmio (addr, 0x10); ? */ diff --git a/hw/watchdog/wdt_ib700.c b/hw/watchdog/wdt_ib700.c index d85c8945e..c78855444 100644 --- a/hw/watchdog/wdt_ib700.c +++ b/hw/watchdog/wdt_ib700.c @@ -97,15 +97,23 @@ static const VMStateDescription vmstate_ib700 = { } }; +static const MemoryRegionPortio wdt_portio_list[] = { + { 0x441, 2, 1, .write = ib700_write_disable_reg, }, + { 0x443, 2, 1, .write = ib700_write_enable_reg, }, + PORTIO_END_OF_LIST(), +}; + static void wdt_ib700_realize(DeviceState *dev, Error **errp) { IB700State *s = IB700(dev); + PortioList *port_list = g_new(PortioList, 1); ib700_debug("watchdog init\n"); s->timer = qemu_new_timer_ns(vm_clock, ib700_timer_expired, s); - register_ioport_write(0x441, 2, 1, ib700_write_disable_reg, s); - register_ioport_write(0x443, 2, 1, ib700_write_enable_reg, s); + + portio_list_init(port_list, OBJECT(s), wdt_portio_list, s, "ib700"); + portio_list_add(port_list, isa_address_space_io(&s->parent_obj), 0); } static void wdt_ib700_reset(DeviceState *dev) diff --git a/hw/xen/xen_apic.c b/hw/xen/xen_apic.c index a95878227..9f91e0f0c 100644 --- a/hw/xen/xen_apic.c +++ b/hw/xen/xen_apic.c @@ -38,8 +38,8 @@ static const MemoryRegionOps xen_apic_io_ops = { static void xen_apic_init(APICCommonState *s) { - memory_region_init_io(&s->io_memory, &xen_apic_io_ops, s, "xen-apic-msi", - APIC_SPACE_SIZE); + memory_region_init_io(&s->io_memory, OBJECT(s), &xen_apic_io_ops, s, + "xen-apic-msi", APIC_SPACE_SIZE); #if defined(CONFIG_XEN_CTRL_INTERFACE_VERSION) \ && CONFIG_XEN_CTRL_INTERFACE_VERSION >= 420 diff --git a/hw/xen/xen_platform.c b/hw/xen/xen_platform.c index b6c6793e1..15d7cf0f6 100644 --- a/hw/xen/xen_platform.c +++ b/hw/xen/xen_platform.c @@ -262,16 +262,20 @@ static void platform_fixed_ioport_write(void *opaque, hwaddr addr, static const MemoryRegionOps platform_fixed_io_ops = { .read = platform_fixed_ioport_read, .write = platform_fixed_ioport_write, + .valid = { + .unaligned = true, + }, .impl = { .min_access_size = 1, .max_access_size = 4, + .unaligned = true, }, .endianness = DEVICE_LITTLE_ENDIAN, }; static void platform_fixed_ioport_init(PCIXenPlatformState* s) { - memory_region_init_io(&s->fixed_io, &platform_fixed_io_ops, s, + memory_region_init_io(&s->fixed_io, OBJECT(s), &platform_fixed_io_ops, s, "xen-fixed", 16); memory_region_add_subregion(get_system_io(), XEN_PLATFORM_IOPORT, &s->fixed_io); @@ -315,7 +319,8 @@ static const MemoryRegionOps xen_pci_io_ops = { static void platform_ioport_bar_setup(PCIXenPlatformState *d) { - memory_region_init_io(&d->bar, &xen_pci_io_ops, d, "xen-pci", 0x100); + memory_region_init_io(&d->bar, OBJECT(d), &xen_pci_io_ops, d, + "xen-pci", 0x100); } static uint64_t platform_mmio_read(void *opaque, hwaddr addr, @@ -343,7 +348,7 @@ static const MemoryRegionOps platform_mmio_handler = { static void platform_mmio_setup(PCIXenPlatformState *d) { - memory_region_init_io(&d->mmio_bar, &platform_mmio_handler, d, + memory_region_init_io(&d->mmio_bar, OBJECT(d), &platform_mmio_handler, d, "xen-mmio", 0x1000000); } diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c index c31a28a3a..d7ee7745c 100644 --- a/hw/xen/xen_pt.c +++ b/hw/xen/xen_pt.c @@ -416,7 +416,7 @@ static int xen_pt_register_regions(XenPCIPassthroughState *s) } } - memory_region_init_io(&s->bar[i], &ops, &s->dev, + memory_region_init_io(&s->bar[i], OBJECT(s), &ops, &s->dev, "xen-pci-pt-bar", r->size); pci_register_bar(&s->dev, i, type, &s->bar[i]); @@ -440,7 +440,7 @@ static int xen_pt_register_regions(XenPCIPassthroughState *s) s->bases[PCI_ROM_SLOT].access.maddr = d->rom.base_addr; - memory_region_init_rom_device(&s->rom, NULL, NULL, + memory_region_init_rom_device(&s->rom, OBJECT(s), NULL, NULL, "xen-pci-pt-rom", d->rom.size); pci_register_bar(&s->dev, PCI_ROM_SLOT, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->rom); @@ -606,6 +606,7 @@ static void xen_pt_region_add(MemoryListener *l, MemoryRegionSection *sec) XenPCIPassthroughState *s = container_of(l, XenPCIPassthroughState, memory_listener); + memory_region_ref(sec->mr); xen_pt_region_update(s, sec, true); } @@ -615,6 +616,7 @@ static void xen_pt_region_del(MemoryListener *l, MemoryRegionSection *sec) memory_listener); xen_pt_region_update(s, sec, false); + memory_region_unref(sec->mr); } static void xen_pt_io_region_add(MemoryListener *l, MemoryRegionSection *sec) @@ -622,6 +624,7 @@ static void xen_pt_io_region_add(MemoryListener *l, MemoryRegionSection *sec) XenPCIPassthroughState *s = container_of(l, XenPCIPassthroughState, io_listener); + memory_region_ref(sec->mr); xen_pt_region_update(s, sec, true); } @@ -631,6 +634,7 @@ static void xen_pt_io_region_del(MemoryListener *l, MemoryRegionSection *sec) io_listener); xen_pt_region_update(s, sec, false); + memory_region_unref(sec->mr); } static const MemoryListener xen_pt_memory_listener = { diff --git a/hw/xen/xen_pt_msi.c b/hw/xen/xen_pt_msi.c index db2c84237..6fbe0cc86 100644 --- a/hw/xen/xen_pt_msi.c +++ b/hw/xen/xen_pt_msi.c @@ -544,7 +544,8 @@ int xen_pt_msix_init(XenPCIPassthroughState *s, uint32_t base) msix->msix_entry[i].pirq = XEN_PT_UNASSIGNED_PIRQ; } - memory_region_init_io(&msix->mmio, &pci_msix_ops, s, "xen-pci-pt-msix", + memory_region_init_io(&msix->mmio, OBJECT(s), &pci_msix_ops, + s, "xen-pci-pt-msix", (total_entries * PCI_MSIX_ENTRY_SIZE + XC_PAGE_SIZE - 1) & XC_PAGE_MASK); diff --git a/hw/xtensa/xtensa_lx60.c b/hw/xtensa/xtensa_lx60.c index 650dd31c9..075daf189 100644 --- a/hw/xtensa/xtensa_lx60.c +++ b/hw/xtensa/xtensa_lx60.c @@ -109,7 +109,7 @@ static Lx60FpgaState *lx60_fpga_init(MemoryRegion *address_space, { Lx60FpgaState *s = g_malloc(sizeof(Lx60FpgaState)); - memory_region_init_io(&s->iomem, &lx60_fpga_ops, s, + memory_region_init_io(&s->iomem, NULL, &lx60_fpga_ops, s, "lx60.fpga", 0x10000); memory_region_add_subregion(address_space, base, &s->iomem); lx60_fpga_reset(s); @@ -139,7 +139,7 @@ static void lx60_net_init(MemoryRegion *address_space, sysbus_mmio_get_region(s, 1)); ram = g_malloc(sizeof(*ram)); - memory_region_init_ram(ram, "open_eth.ram", 16384); + memory_region_init_ram(ram, OBJECT(s), "open_eth.ram", 16384); vmstate_register_ram_global(ram); memory_region_add_subregion(address_space, buffers, ram); } @@ -195,12 +195,12 @@ static void lx_init(const LxBoardDesc *board, QEMUMachineInitArgs *args) } ram = g_malloc(sizeof(*ram)); - memory_region_init_ram(ram, "lx60.dram", args->ram_size); + memory_region_init_ram(ram, NULL, "lx60.dram", args->ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(system_memory, 0, ram); system_io = g_malloc(sizeof(*system_io)); - memory_region_init(system_io, "lx60.io", 224 * 1024 * 1024); + memory_region_init(system_io, NULL, "lx60.io", 224 * 1024 * 1024); memory_region_add_subregion(system_memory, 0xf0000000, system_io); lx60_fpga_init(system_io, 0x0d020000); if (nd_table[0].used) { @@ -231,7 +231,7 @@ static void lx_init(const LxBoardDesc *board, QEMUMachineInitArgs *args) /* Use presence of kernel file name as 'boot from SRAM' switch. */ if (kernel_filename) { rom = g_malloc(sizeof(*rom)); - memory_region_init_ram(rom, "lx60.sram", board->sram_size); + memory_region_init_ram(rom, NULL, "lx60.sram", board->sram_size); vmstate_register_ram_global(rom); memory_region_add_subregion(system_memory, 0xfe000000, rom); @@ -262,7 +262,7 @@ static void lx_init(const LxBoardDesc *board, QEMUMachineInitArgs *args) MemoryRegion *flash_mr = pflash_cfi01_get_memory(flash); MemoryRegion *flash_io = g_malloc(sizeof(*flash_io)); - memory_region_init_alias(flash_io, "lx60.flash", + memory_region_init_alias(flash_io, NULL, "lx60.flash", flash_mr, 0, board->flash_size); memory_region_add_subregion(system_memory, 0xfe000000, flash_io); diff --git a/hw/xtensa/xtensa_sim.c b/hw/xtensa/xtensa_sim.c index 5241f8d73..a88707e16 100644 --- a/hw/xtensa/xtensa_sim.c +++ b/hw/xtensa/xtensa_sim.c @@ -75,12 +75,12 @@ static void xtensa_sim_init(QEMUMachineInitArgs *args) } ram = g_malloc(sizeof(*ram)); - memory_region_init_ram(ram, "xtensa.sram", ram_size); + memory_region_init_ram(ram, NULL, "xtensa.sram", ram_size); vmstate_register_ram_global(ram); memory_region_add_subregion(get_system_memory(), 0, ram); rom = g_malloc(sizeof(*rom)); - memory_region_init_ram(rom, "xtensa.rom", 0x1000); + memory_region_init_ram(rom, NULL, "xtensa.rom", 0x1000); vmstate_register_ram_global(rom); memory_region_add_subregion(get_system_memory(), 0xfe000000, rom); diff --git a/include/block/block.h b/include/block/block.h index dd8eca1be..b6b9014a9 100644 --- a/include/block/block.h +++ b/include/block/block.h @@ -111,7 +111,8 @@ bool bdrv_io_limits_enabled(BlockDriverState *bs); void bdrv_init(void); void bdrv_init_with_whitelist(void); -BlockDriver *bdrv_find_protocol(const char *filename); +BlockDriver *bdrv_find_protocol(const char *filename, + bool allow_protocol_prefix); BlockDriver *bdrv_find_format(const char *format_name); BlockDriver *bdrv_find_whitelisted_format(const char *format_name, bool readonly); @@ -266,7 +267,7 @@ void bdrv_clear_incoming_migration_all(void); /* Ensure contents are flushed to disk. */ int bdrv_flush(BlockDriverState *bs); int coroutine_fn bdrv_co_flush(BlockDriverState *bs); -void bdrv_flush_all(void); +int bdrv_flush_all(void); void bdrv_close_all(void); void bdrv_drain_all(void); diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 35bdf858f..508420221 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -20,7 +20,6 @@ #define CPU_ALL_H #include "qemu-common.h" -#include "qemu/tls.h" #include "exec/cpu-common.h" #include "qemu/thread.h" @@ -357,9 +356,6 @@ CPUArchState *cpu_copy(CPUArchState *env); void QEMU_NORETURN cpu_abort(CPUArchState *env, const char *fmt, ...) GCC_FMT_ATTR(2, 3); -extern CPUArchState *first_cpu; -DECLARE_TLS(CPUArchState *,cpu_single_env); -#define cpu_single_env tls_var(cpu_single_env) /* Flags for use in ENV->INTERRUPT_PENDING. @@ -447,7 +443,6 @@ hwaddr cpu_get_phys_page_debug(CPUArchState *env, target_ulong addr); /* memory API */ -extern int phys_ram_fd; extern ram_addr_t ram_size; /* RAM is pre-allocated and passed into qemu_ram_alloc_from_ptr */ diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index 5240ae2ac..e4996e19c 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -52,8 +52,7 @@ typedef uint32_t CPUReadMemoryFunc(void *opaque, hwaddr addr); void qemu_ram_remap(ram_addr_t addr, ram_addr_t length); /* This should not be used by devices. */ -int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr); -ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr); +MemoryRegion *qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr); void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev); void cpu_physical_memory_rw(hwaddr addr, uint8_t *buf, diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h index c4ac92987..5321171ce 100644 --- a/include/exec/cpu-defs.h +++ b/include/exec/cpu-defs.h @@ -154,8 +154,6 @@ typedef struct CPUWatchpoint { memory was accessed */ \ CPU_COMMON_TLB \ struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE]; \ - /* buffer for temporaries in the code generator */ \ - long temp_buf[CPU_TEMP_BUF_NLONGS]; \ \ int64_t icount_extra; /* Instructions until next timer event. */ \ /* Number of cycles left, with interrupt flag in high bit. \ @@ -181,7 +179,6 @@ typedef struct CPUWatchpoint { sigjmp_buf jmp_env; \ int exception_index; \ \ - CPUArchState *next_cpu; /* next CPU sharing TB cache */ \ /* user data */ \ void *opaque; \ \ diff --git a/include/exec/ioport.h b/include/exec/ioport.h index fc28350a3..bdd4e964e 100644 --- a/include/exec/ioport.h +++ b/include/exec/ioport.h @@ -25,7 +25,8 @@ #define IOPORT_H #include "qemu-common.h" -#include "exec/iorange.h" +#include "qom/object.h" +#include "exec/memory.h" typedef uint32_t pio_addr_t; #define FMT_pioaddr PRIx32 @@ -33,18 +34,16 @@ typedef uint32_t pio_addr_t; #define MAX_IOPORTS (64 * 1024) #define IOPORTS_MASK (MAX_IOPORTS - 1) -/* These should really be in isa.h, but are here to make pc.h happy. */ -typedef void (IOPortWriteFunc)(void *opaque, uint32_t address, uint32_t data); -typedef uint32_t (IOPortReadFunc)(void *opaque, uint32_t address); -typedef void (IOPortDestructor)(void *opaque); +typedef struct MemoryRegionPortio { + uint32_t offset; + uint32_t len; + unsigned size; + uint32_t (*read)(void *opaque, uint32_t address); + void (*write)(void *opaque, uint32_t address, uint32_t data); + uint32_t base; /* private field */ +} MemoryRegionPortio; -void ioport_register(IORange *iorange); -int register_ioport_read(pio_addr_t start, int length, int size, - IOPortReadFunc *func, void *opaque); -int register_ioport_write(pio_addr_t start, int length, int size, - IOPortWriteFunc *func, void *opaque); -void isa_unassign_ioport(pio_addr_t start, int length); -bool isa_is_ioport_assigned(pio_addr_t start); +#define PORTIO_END_OF_LIST() { } void cpu_outb(pio_addr_t addr, uint8_t val); void cpu_outw(pio_addr_t addr, uint16_t val); @@ -53,20 +52,17 @@ uint8_t cpu_inb(pio_addr_t addr); uint16_t cpu_inw(pio_addr_t addr); uint32_t cpu_inl(pio_addr_t addr); -struct MemoryRegion; -struct MemoryRegionPortio; - typedef struct PortioList { const struct MemoryRegionPortio *ports; + Object *owner; struct MemoryRegion *address_space; unsigned nr; struct MemoryRegion **regions; - struct MemoryRegion **aliases; void *opaque; const char *name; } PortioList; -void portio_list_init(PortioList *piolist, +void portio_list_init(PortioList *piolist, Object *owner, const struct MemoryRegionPortio *callbacks, void *opaque, const char *name); void portio_list_destroy(PortioList *piolist); diff --git a/include/exec/iorange.h b/include/exec/iorange.h deleted file mode 100644 index cd980a831..000000000 --- a/include/exec/iorange.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef IORANGE_H -#define IORANGE_H - -#include - -typedef struct IORange IORange; -typedef struct IORangeOps IORangeOps; - -struct IORangeOps { - void (*read)(IORange *iorange, uint64_t offset, unsigned width, - uint64_t *data); - void (*write)(IORange *iorange, uint64_t offset, unsigned width, - uint64_t data); - void (*destructor)(IORange *iorange); -}; - -struct IORange { - const IORangeOps *ops; - uint64_t base; - uint64_t len; -}; - -static inline void iorange_init(IORange *iorange, const IORangeOps *ops, - uint64_t base, uint64_t len) -{ - iorange->ops = ops; - iorange->base = base; - iorange->len = len; -} - -#endif diff --git a/include/exec/memory-internal.h b/include/exec/memory-internal.h index 26689fe25..d0e063392 100644 --- a/include/exec/memory-internal.h +++ b/include/exec/memory-internal.h @@ -119,8 +119,6 @@ static inline void cpu_physical_memory_mask_dirty_range(ram_addr_t start, void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end, int dirty_flags); -extern const IORangeOps memory_region_iorange_ops; - #endif #endif diff --git a/include/exec/memory.h b/include/exec/memory.h index 2ddc3c539..ebe0d2418 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -24,8 +24,6 @@ #include "exec/hwaddr.h" #endif #include "qemu/queue.h" -#include "exec/iorange.h" -#include "exec/ioport.h" #include "qemu/int128.h" #include "qemu/notify.h" @@ -33,7 +31,6 @@ #define MAX_PHYS_ADDR (((hwaddr)1 << MAX_PHYS_ADDR_SPACE_BITS) - 1) typedef struct MemoryRegionOps MemoryRegionOps; -typedef struct MemoryRegionPortio MemoryRegionPortio; typedef struct MemoryRegionMmio MemoryRegionMmio; /* Must match *_DIRTY_FLAGS in cpu-all.h. To be replaced with dynamic @@ -48,14 +45,6 @@ struct MemoryRegionMmio { CPUWriteMemoryFunc *write[3]; }; -/* Internal use; thunks between old-style IORange and MemoryRegions. */ -typedef struct MemoryRegionIORange MemoryRegionIORange; -struct MemoryRegionIORange { - IORange iorange; - MemoryRegion *mr; - hwaddr offset; -}; - typedef struct IOMMUTLBEntry IOMMUTLBEntry; /* See address_space_translate: bit 0 is read, bit 1 is write. */ @@ -126,10 +115,6 @@ struct MemoryRegionOps { bool unaligned; } impl; - /* If .read and .write are not present, old_portio may be used for - * backwards compatibility with old portio registration - */ - const MemoryRegionPortio *old_portio; /* If .read and .write are not present, old_mmio may be used for * backwards compatibility with old mmio registration */ @@ -151,6 +136,7 @@ struct MemoryRegion { const MemoryRegionOps *ops; const MemoryRegionIOMMUOps *iommu_ops; void *opaque; + struct Object *owner; MemoryRegion *parent; Int128 size; hwaddr addr; @@ -179,15 +165,38 @@ struct MemoryRegion { NotifierList iommu_notify; }; -struct MemoryRegionPortio { - uint32_t offset; - uint32_t len; - unsigned size; - IOPortReadFunc *read; - IOPortWriteFunc *write; -}; +typedef struct MemoryListener MemoryListener; -#define PORTIO_END_OF_LIST() { } +/** + * MemoryListener: callbacks structure for updates to the physical memory map + * + * Allows a component to adjust to changes in the guest-visible memory map. + * Use with memory_listener_register() and memory_listener_unregister(). + */ +struct MemoryListener { + void (*begin)(MemoryListener *listener); + void (*commit)(MemoryListener *listener); + void (*region_add)(MemoryListener *listener, MemoryRegionSection *section); + void (*region_del)(MemoryListener *listener, MemoryRegionSection *section); + void (*region_nop)(MemoryListener *listener, MemoryRegionSection *section); + void (*log_start)(MemoryListener *listener, MemoryRegionSection *section); + void (*log_stop)(MemoryListener *listener, MemoryRegionSection *section); + void (*log_sync)(MemoryListener *listener, MemoryRegionSection *section); + void (*log_global_start)(MemoryListener *listener); + void (*log_global_stop)(MemoryListener *listener); + void (*eventfd_add)(MemoryListener *listener, MemoryRegionSection *section, + bool match_data, uint64_t data, EventNotifier *e); + void (*eventfd_del)(MemoryListener *listener, MemoryRegionSection *section, + bool match_data, uint64_t data, EventNotifier *e); + void (*coalesced_mmio_add)(MemoryListener *listener, MemoryRegionSection *section, + hwaddr addr, hwaddr len); + void (*coalesced_mmio_del)(MemoryListener *listener, MemoryRegionSection *section, + hwaddr addr, hwaddr len); + /* Lower = earlier (during add), later (during del) */ + unsigned priority; + AddressSpace *address_space_filter; + QTAILQ_ENTRY(MemoryListener) link; +}; /** * AddressSpace: describes a mapping of addresses to #MemoryRegion objects @@ -200,6 +209,9 @@ struct AddressSpace { int ioeventfd_nb; struct MemoryRegionIoeventfd *ioeventfds; struct AddressSpaceDispatch *dispatch; + struct AddressSpaceDispatch *next_dispatch; + MemoryListener dispatch_listener; + QTAILQ_ENTRY(AddressSpace) address_spaces_link; }; @@ -223,39 +235,6 @@ struct MemoryRegionSection { bool readonly; }; -typedef struct MemoryListener MemoryListener; - -/** - * MemoryListener: callbacks structure for updates to the physical memory map - * - * Allows a component to adjust to changes in the guest-visible memory map. - * Use with memory_listener_register() and memory_listener_unregister(). - */ -struct MemoryListener { - void (*begin)(MemoryListener *listener); - void (*commit)(MemoryListener *listener); - void (*region_add)(MemoryListener *listener, MemoryRegionSection *section); - void (*region_del)(MemoryListener *listener, MemoryRegionSection *section); - void (*region_nop)(MemoryListener *listener, MemoryRegionSection *section); - void (*log_start)(MemoryListener *listener, MemoryRegionSection *section); - void (*log_stop)(MemoryListener *listener, MemoryRegionSection *section); - void (*log_sync)(MemoryListener *listener, MemoryRegionSection *section); - void (*log_global_start)(MemoryListener *listener); - void (*log_global_stop)(MemoryListener *listener); - void (*eventfd_add)(MemoryListener *listener, MemoryRegionSection *section, - bool match_data, uint64_t data, EventNotifier *e); - void (*eventfd_del)(MemoryListener *listener, MemoryRegionSection *section, - bool match_data, uint64_t data, EventNotifier *e); - void (*coalesced_mmio_add)(MemoryListener *listener, MemoryRegionSection *section, - hwaddr addr, hwaddr len); - void (*coalesced_mmio_del)(MemoryListener *listener, MemoryRegionSection *section, - hwaddr addr, hwaddr len); - /* Lower = earlier (during add), later (during del) */ - unsigned priority; - AddressSpace *address_space_filter; - QTAILQ_ENTRY(MemoryListener) link; -}; - /** * memory_region_init: Initialize a memory region * @@ -263,12 +242,44 @@ struct MemoryListener { * memory_region_add_subregion() to add subregions. * * @mr: the #MemoryRegion to be initialized + * @owner: the object that tracks the region's reference count * @name: used for debugging; not visible to the user or ABI * @size: size of the region; any subregions beyond this size will be clipped */ void memory_region_init(MemoryRegion *mr, + struct Object *owner, const char *name, uint64_t size); + +/** + * memory_region_ref: Add 1 to a memory region's reference count + * + * Whenever memory regions are accessed outside the BQL, they need to be + * preserved against hot-unplug. MemoryRegions actually do not have their + * own reference count; they piggyback on a QOM object, their "owner". + * This function adds a reference to the owner. + * + * All MemoryRegions must have an owner if they can disappear, even if the + * device they belong to operates exclusively under the BQL. This is because + * the region could be returned at any time by memory_region_find, and this + * is usually under guest control. + * + * @mr: the #MemoryRegion + */ +void memory_region_ref(MemoryRegion *mr); + +/** + * memory_region_unref: Remove 1 to a memory region's reference count + * + * Whenever memory regions are accessed outside the BQL, they need to be + * preserved against hot-unplug. MemoryRegions actually do not have their + * own reference count; they piggyback on a QOM object, their "owner". + * This function removes a reference to the owner and possibly destroys it. + * + * @mr: the #MemoryRegion + */ +void memory_region_unref(MemoryRegion *mr); + /** * memory_region_init_io: Initialize an I/O memory region. * @@ -276,6 +287,7 @@ void memory_region_init(MemoryRegion *mr, * if @size is nonzero, subregions will be clipped to @size. * * @mr: the #MemoryRegion to be initialized. + * @owner: the object that tracks the region's reference count * @ops: a structure containing read and write callbacks to be used when * I/O is performed on the region. * @opaque: passed to to the read and write callbacks of the @ops structure. @@ -283,6 +295,7 @@ void memory_region_init(MemoryRegion *mr, * @size: size of the region. */ void memory_region_init_io(MemoryRegion *mr, + struct Object *owner, const MemoryRegionOps *ops, void *opaque, const char *name, @@ -293,10 +306,12 @@ void memory_region_init_io(MemoryRegion *mr, * region will modify memory directly. * * @mr: the #MemoryRegion to be initialized. + * @owner: the object that tracks the region's reference count * @name: the name of the region. * @size: size of the region. */ void memory_region_init_ram(MemoryRegion *mr, + struct Object *owner, const char *name, uint64_t size); @@ -306,11 +321,13 @@ void memory_region_init_ram(MemoryRegion *mr, * region will modify memory directly. * * @mr: the #MemoryRegion to be initialized. + * @owner: the object that tracks the region's reference count * @name: the name of the region. * @size: size of the region. * @ptr: memory to be mapped; must contain at least @size bytes. */ void memory_region_init_ram_ptr(MemoryRegion *mr, + struct Object *owner, const char *name, uint64_t size, void *ptr); @@ -320,6 +337,7 @@ void memory_region_init_ram_ptr(MemoryRegion *mr, * part of another memory region. * * @mr: the #MemoryRegion to be initialized. + * @owner: the object that tracks the region's reference count * @name: used for debugging; not visible to the user or ABI * @orig: the region to be referenced; @mr will be equivalent to * @orig between @offset and @offset + @size - 1. @@ -327,6 +345,7 @@ void memory_region_init_ram_ptr(MemoryRegion *mr, * @size: size of the region. */ void memory_region_init_alias(MemoryRegion *mr, + struct Object *owner, const char *name, MemoryRegion *orig, hwaddr offset, @@ -337,11 +356,13 @@ void memory_region_init_alias(MemoryRegion *mr, * handled via callbacks. * * @mr: the #MemoryRegion to be initialized. + * @owner: the object that tracks the region's reference count * @ops: callbacks for write access handling. * @name: the name of the region. * @size: size of the region. */ void memory_region_init_rom_device(MemoryRegion *mr, + struct Object *owner, const MemoryRegionOps *ops, void *opaque, const char *name, @@ -356,10 +377,12 @@ void memory_region_init_rom_device(MemoryRegion *mr, * the memory API will cause an abort(). * * @mr: the #MemoryRegion to be initialized + * @owner: the object that tracks the region's reference count * @name: used for debugging; not visible to the user or ABI * @size: size of the region. */ void memory_region_init_reservation(MemoryRegion *mr, + struct Object *owner, const char *name, uint64_t size); @@ -371,11 +394,13 @@ void memory_region_init_reservation(MemoryRegion *mr, * memory region. * * @mr: the #MemoryRegion to be initialized + * @owner: the object that tracks the region's reference count * @ops: a function that translates addresses into the @target region * @name: used for debugging; not visible to the user or ABI * @size: size of the region. */ void memory_region_init_iommu(MemoryRegion *mr, + struct Object *owner, const MemoryRegionIOMMUOps *ops, const char *name, uint64_t size); @@ -389,6 +414,13 @@ void memory_region_init_iommu(MemoryRegion *mr, */ void memory_region_destroy(MemoryRegion *mr); +/** + * memory_region_owner: get a memory region's owner. + * + * @mr: the memory region being queried. + */ +struct Object *memory_region_owner(MemoryRegion *mr); + /** * memory_region_size: get a memory region's size. * @@ -807,6 +839,18 @@ void memory_region_set_address(MemoryRegion *mr, hwaddr addr); void memory_region_set_alias_offset(MemoryRegion *mr, hwaddr offset); +/** + * memory_region_present: translate an address/size relative to a + * MemoryRegion into a #MemoryRegionSection. + * + * Answer whether a #MemoryRegion within @parent covers the address + * @addr. + * + * @parent: a MemoryRegion within which @addr is a relative address + * @addr: the area within @parent to be searched + */ +bool memory_region_present(MemoryRegion *parent, hwaddr addr); + /** * memory_region_find: translate an address/size relative to a * MemoryRegion into a #MemoryRegionSection. diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index a417402bb..61ff154c7 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -3,14 +3,26 @@ #include "qemu-common.h" #include "exec/memory.h" -#include "exec/ioport.h" #include "hw/isa/isa.h" #include "hw/block/fdc.h" #include "net/net.h" #include "hw/i386/ioapic.h" +#include "qemu/range.h" + /* PC-style peripherals (also used by other machines). */ +typedef struct PcPciInfo { + Range w32; + Range w64; +} PcPciInfo; + +struct PcGuestInfo { + PcPciInfo pci_info; + bool has_pci_info; + FWCfgState *fw_cfg; +}; + /* parallel.c */ static inline bool parallel_init(ISABus *bus, int index, CharDriverState *chr) { @@ -56,11 +68,14 @@ typedef struct GSIState { void gsi_handler(void *opaque, int n, int level); /* vmport.c */ +typedef uint32_t (VMPortReadFunc)(void *opaque, uint32_t address); + static inline void vmport_init(ISABus *bus) { isa_create_simple(bus, "vmport"); } -void vmport_register(unsigned char command, IOPortReadFunc *func, void *opaque); + +void vmport_register(unsigned char command, VMPortReadFunc *func, void *opaque); void vmmouse_get_data(uint32_t *data); void vmmouse_set_data(const uint32_t *data); @@ -82,6 +97,10 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level); void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge); void pc_hot_add_cpu(const int64_t id, Error **errp); void pc_acpi_init(const char *default_dsdt); + +PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size, + ram_addr_t above_4g_mem_size); + FWCfgState *pc_memory_init(MemoryRegion *system_memory, const char *kernel_filename, const char *kernel_cmdline, @@ -89,7 +108,8 @@ FWCfgState *pc_memory_init(MemoryRegion *system_memory, ram_addr_t below_4g_mem_size, ram_addr_t above_4g_mem_size, MemoryRegion *rom_memory, - MemoryRegion **ram_memory); + MemoryRegion **ram_memory, + PcGuestInfo *guest_info); qemu_irq *pc_allocate_cpu_irq(void); DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus); void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, @@ -175,7 +195,7 @@ static inline bool isa_ne2000_init(ISABus *bus, int base, int irq, NICInfo *nd) void pc_system_firmware_init(MemoryRegion *rom_memory); /* pvpanic.c */ -int pvpanic_init(ISABus *bus); +void pvpanic_init(ISABus *bus); /* e820 types */ #define E820_RAM 1 diff --git a/include/hw/pci-host/pam.h b/include/hw/pci-host/pam.h index 8e9e349b1..a8b87b89a 100644 --- a/include/hw/pci-host/pam.h +++ b/include/hw/pci-host/pam.h @@ -90,8 +90,8 @@ void smram_update(MemoryRegion *smram_region, uint8_t smram, uint8_t smm_enabled); void smram_set_smm(uint8_t *host_smm_enabled, int smm, uint8_t smram, MemoryRegion *smram_region); -void init_pam(MemoryRegion *ram, MemoryRegion *system, MemoryRegion *pci, - PAMMemoryRegion *mem, uint32_t start, uint32_t size); +void init_pam(DeviceState *dev, MemoryRegion *ram, MemoryRegion *system, + MemoryRegion *pci, PAMMemoryRegion *mem, uint32_t start, uint32_t size); void pam_update(PAMMemoryRegion *mem, int idx, uint8_t val); #endif /* QEMU_PAM_H */ diff --git a/include/hw/pci-host/q35.h b/include/hw/pci-host/q35.h index e182c820a..b0838319a 100644 --- a/include/hw/pci-host/q35.h +++ b/include/hw/pci-host/q35.h @@ -55,6 +55,7 @@ typedef struct MCHPCIState { uint8_t smm_enabled; ram_addr_t below_4g_mem_size; ram_addr_t above_4g_mem_size; + PcGuestInfo *guest_info; } MCHPCIState; typedef struct Q35PCIHost { @@ -81,6 +82,7 @@ typedef struct Q35PCIHost { #define MCH_HOST_BRIDGE_PCIEXBAR 0x60 /* 64bit register */ #define MCH_HOST_BRIDGE_PCIEXBAR_SIZE 8 /* 64bit register */ #define MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT 0xb0000000 +#define MCH_HOST_BRIDGE_PCIEXBAR_MAX (0x10000000) /* 256M */ #define MCH_HOST_BRIDGE_PCIEXBAR_ADMSK Q35_MASK(64, 35, 28) #define MCH_HOST_BRIDGE_PCIEXBAR_128ADMSK ((uint64_t)(1 << 26)) #define MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK ((uint64_t)(1 << 25)) diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 6ef1f9739..ccec2bac3 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -378,9 +378,11 @@ void pci_device_set_intx_routing_notifier(PCIDevice *dev, void pci_device_reset(PCIDevice *dev); void pci_bus_reset(PCIBus *bus); -PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model, +PCIDevice *pci_nic_init(NICInfo *nd, PCIBus *rootbus, + const char *default_model, const char *default_devaddr); -PCIDevice *pci_nic_init_nofail(NICInfo *nd, const char *default_model, +PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus, + const char *default_model, const char *default_devaddr); PCIDevice *pci_vga_init(PCIBus *bus); @@ -389,14 +391,15 @@ int pci_bus_num(PCIBus *s); void pci_for_each_device(PCIBus *bus, int bus_num, void (*fn)(PCIBus *bus, PCIDevice *d, void *opaque), void *opaque); -PCIBus *pci_find_root_bus(int domain); -int pci_find_domain(const PCIBus *bus); +PCIBus *pci_find_primary_bus(void); +PCIBus *pci_device_root_bus(const PCIDevice *d); +const char *pci_root_bus_path(PCIDevice *dev); PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn); int pci_qdev_find_device(const char *id, PCIDevice **pdev); -PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr); +PCIBus *pci_get_bus_devfn(int *devfnp, PCIBus *root, const char *devaddr); -int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp, - unsigned *slotp); +int pci_parse_devaddr(const char *addr, int *domp, int *busp, + unsigned int *slotp, unsigned int *funcp); void pci_device_deassert_intx(PCIDevice *dev); @@ -702,7 +705,7 @@ static inline void pci_dma_unmap(PCIDevice *dev, void *buffer, dma_addr_t len, static inline void pci_dma_sglist_init(QEMUSGList *qsg, PCIDevice *dev, int alloc_hint) { - qemu_sglist_init(qsg, alloc_hint, pci_get_address_space(dev)); + qemu_sglist_init(qsg, DEVICE(dev), alloc_hint, pci_get_address_space(dev)); } extern const VMStateDescription vmstate_pci_device; diff --git a/include/hw/pci/pci_host.h b/include/hw/pci/pci_host.h index 236cd0f75..ba31595fc 100644 --- a/include/hw/pci/pci_host.h +++ b/include/hw/pci/pci_host.h @@ -33,6 +33,10 @@ #define TYPE_PCI_HOST_BRIDGE "pci-host-bridge" #define PCI_HOST_BRIDGE(obj) \ OBJECT_CHECK(PCIHostState, (obj), TYPE_PCI_HOST_BRIDGE) +#define PCI_HOST_BRIDGE_CLASS(klass) \ + OBJECT_CLASS_CHECK(PCIHostBridgeClass, (klass), TYPE_PCI_HOST_BRIDGE) +#define PCI_HOST_BRIDGE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(PCIHostBridgeClass, (obj), TYPE_PCI_HOST_BRIDGE) struct PCIHostState { SysBusDevice busdev; @@ -42,8 +46,16 @@ struct PCIHostState { MemoryRegion mmcfg; uint32_t config_reg; PCIBus *bus; + + QLIST_ENTRY(PCIHostState) next; }; +typedef struct PCIHostBridgeClass { + SysBusDeviceClass parent_class; + + const char *(*root_bus_path)(PCIHostState *, PCIBus *); +} PCIHostBridgeClass; + /* common internal helpers for PCI/PCIe hosts, cut off overflows */ void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr, uint32_t limit, uint32_t val, uint32_t len); diff --git a/include/hw/ppc/mac_dbdma.h b/include/hw/ppc/mac_dbdma.h index 691263eed..90efd277e 100644 --- a/include/hw/ppc/mac_dbdma.h +++ b/include/hw/ppc/mac_dbdma.h @@ -37,12 +37,136 @@ struct DBDMA_io { int is_last; int is_dma_out; DBDMA_end dma_end; + /* DMA is in progress, don't start another one */ + bool processing; + /* unaligned last sector of a request */ + uint8_t remainder[0x200]; + int remainder_len; }; +/* + * DBDMA control/status registers. All little-endian. + */ + +#define DBDMA_CONTROL 0x00 +#define DBDMA_STATUS 0x01 +#define DBDMA_CMDPTR_HI 0x02 +#define DBDMA_CMDPTR_LO 0x03 +#define DBDMA_INTR_SEL 0x04 +#define DBDMA_BRANCH_SEL 0x05 +#define DBDMA_WAIT_SEL 0x06 +#define DBDMA_XFER_MODE 0x07 +#define DBDMA_DATA2PTR_HI 0x08 +#define DBDMA_DATA2PTR_LO 0x09 +#define DBDMA_RES1 0x0A +#define DBDMA_ADDRESS_HI 0x0B +#define DBDMA_BRANCH_ADDR_HI 0x0C +#define DBDMA_RES2 0x0D +#define DBDMA_RES3 0x0E +#define DBDMA_RES4 0x0F + +#define DBDMA_REGS 16 +#define DBDMA_SIZE (DBDMA_REGS * sizeof(uint32_t)) + +#define DBDMA_CHANNEL_SHIFT 7 +#define DBDMA_CHANNEL_SIZE (1 << DBDMA_CHANNEL_SHIFT) + +#define DBDMA_CHANNELS (0x1000 >> DBDMA_CHANNEL_SHIFT) + +/* Bits in control and status registers */ + +#define RUN 0x8000 +#define PAUSE 0x4000 +#define FLUSH 0x2000 +#define WAKE 0x1000 +#define DEAD 0x0800 +#define ACTIVE 0x0400 +#define BT 0x0100 +#define DEVSTAT 0x00ff + +/* + * DBDMA command structure. These fields are all little-endian! + */ + +typedef struct dbdma_cmd { + uint16_t req_count; /* requested byte transfer count */ + uint16_t command; /* command word (has bit-fields) */ + uint32_t phy_addr; /* physical data address */ + uint32_t cmd_dep; /* command-dependent field */ + uint16_t res_count; /* residual count after completion */ + uint16_t xfer_status; /* transfer status */ +} dbdma_cmd; + +/* DBDMA command values in command field */ + +#define COMMAND_MASK 0xf000 +#define OUTPUT_MORE 0x0000 /* transfer memory data to stream */ +#define OUTPUT_LAST 0x1000 /* ditto followed by end marker */ +#define INPUT_MORE 0x2000 /* transfer stream data to memory */ +#define INPUT_LAST 0x3000 /* ditto, expect end marker */ +#define STORE_WORD 0x4000 /* write word (4 bytes) to device reg */ +#define LOAD_WORD 0x5000 /* read word (4 bytes) from device reg */ +#define DBDMA_NOP 0x6000 /* do nothing */ +#define DBDMA_STOP 0x7000 /* suspend processing */ + +/* Key values in command field */ + +#define KEY_MASK 0x0700 +#define KEY_STREAM0 0x0000 /* usual data stream */ +#define KEY_STREAM1 0x0100 /* control/status stream */ +#define KEY_STREAM2 0x0200 /* device-dependent stream */ +#define KEY_STREAM3 0x0300 /* device-dependent stream */ +#define KEY_STREAM4 0x0400 /* reserved */ +#define KEY_REGS 0x0500 /* device register space */ +#define KEY_SYSTEM 0x0600 /* system memory-mapped space */ +#define KEY_DEVICE 0x0700 /* device memory-mapped space */ + +/* Interrupt control values in command field */ + +#define INTR_MASK 0x0030 +#define INTR_NEVER 0x0000 /* don't interrupt */ +#define INTR_IFSET 0x0010 /* intr if condition bit is 1 */ +#define INTR_IFCLR 0x0020 /* intr if condition bit is 0 */ +#define INTR_ALWAYS 0x0030 /* always interrupt */ + +/* Branch control values in command field */ + +#define BR_MASK 0x000c +#define BR_NEVER 0x0000 /* don't branch */ +#define BR_IFSET 0x0004 /* branch if condition bit is 1 */ +#define BR_IFCLR 0x0008 /* branch if condition bit is 0 */ +#define BR_ALWAYS 0x000c /* always branch */ + +/* Wait control values in command field */ + +#define WAIT_MASK 0x0003 +#define WAIT_NEVER 0x0000 /* don't wait */ +#define WAIT_IFSET 0x0001 /* wait if condition bit is 1 */ +#define WAIT_IFCLR 0x0002 /* wait if condition bit is 0 */ +#define WAIT_ALWAYS 0x0003 /* always wait */ + +typedef struct DBDMA_channel { + int channel; + uint32_t regs[DBDMA_REGS]; + qemu_irq irq; + DBDMA_io io; + DBDMA_rw rw; + DBDMA_flush flush; + dbdma_cmd current; +} DBDMA_channel; + +typedef struct { + MemoryRegion mem; + DBDMA_channel channels[DBDMA_CHANNELS]; + QEMUBH *bh; +} DBDMAState; + +/* Externally callable functions */ void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq, DBDMA_rw rw, DBDMA_flush flush, void *opaque); +void DBDMA_kick(DBDMAState *dbdma); void* DBDMA_init (MemoryRegion **dbdma_mem); #endif diff --git a/include/hw/ppc/ppc.h b/include/hw/ppc/ppc.h index dfcad259b..132ab97b5 100644 --- a/include/hw/ppc/ppc.h +++ b/include/hw/ppc/ppc.h @@ -73,8 +73,6 @@ void ppc6xx_irq_init (CPUPPCState *env); void ppc970_irq_init (CPUPPCState *env); void ppcPOWER7_irq_init (CPUPPCState *env); -void ppce500_set_mpic_proxy(bool enabled); - /* PPC machines for OpenBIOS */ enum { ARCH_PREP = 0, diff --git a/include/hw/ppc/ppc_e500.h b/include/hw/ppc/ppc_e500.h new file mode 100644 index 000000000..b66c0e3ee --- /dev/null +++ b/include/hw/ppc/ppc_e500.h @@ -0,0 +1,6 @@ +#ifndef HW_PPC_E500_H +#define HW_PPC_E500_H + +void ppce500_set_mpic_proxy(bool enabled); + +#endif diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 09c457098..de9548073 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -348,7 +348,8 @@ typedef struct sPAPRTCETable sPAPRTCETable; void spapr_iommu_init(void); void spapr_events_init(sPAPREnvironment *spapr); void spapr_events_fdt_skel(void *fdt, uint32_t epow_irq); -sPAPRTCETable *spapr_tce_new_table(uint32_t liobn, size_t window_size); +sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn, + size_t window_size); MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet); void spapr_tce_free(sPAPRTCETable *tcet); void spapr_tce_reset(sPAPRTCETable *tcet); diff --git a/include/hw/virtio/dataplane/hostmem.h b/include/hw/virtio/dataplane/hostmem.h index b2cf09333..2810f4b44 100644 --- a/include/hw/virtio/dataplane/hostmem.h +++ b/include/hw/virtio/dataplane/hostmem.h @@ -18,6 +18,7 @@ #include "qemu/thread.h" typedef struct { + MemoryRegion *mr; void *host_addr; hwaddr guest_addr; uint64_t size; diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h index 10becb610..0aa891330 100644 --- a/include/qemu/atomic.h +++ b/include/qemu/atomic.h @@ -1,68 +1,202 @@ -#ifndef __QEMU_BARRIER_H -#define __QEMU_BARRIER_H 1 +/* + * Simple interface for atomic operations. + * + * Copyright (C) 2013 Red Hat, Inc. + * + * Author: Paolo Bonzini + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + * + */ -/* Compiler barrier */ -#define barrier() asm volatile("" ::: "memory") +#ifndef __QEMU_ATOMIC_H +#define __QEMU_ATOMIC_H 1 -#if defined(__i386__) +#include "qemu/compiler.h" -#include "qemu/compiler.h" /* QEMU_GNUC_PREREQ */ +/* For C11 atomic ops */ -/* - * Because of the strongly ordered x86 storage model, wmb() and rmb() are nops - * on x86(well, a compiler barrier only). Well, at least as long as - * qemu doesn't do accesses to write-combining memory or non-temporal - * load/stores from C code. - */ -#define smp_wmb() barrier() -#define smp_rmb() barrier() +/* Compiler barrier */ +#define barrier() ({ asm volatile("" ::: "memory"); (void)0; }) + +#ifndef __ATOMIC_RELAXED /* - * We use GCC builtin if it's available, as that can use - * mfence on 32 bit as well, e.g. if built with -march=pentium-m. - * However, on i386, there seem to be known bugs as recently as 4.3. - * */ -#if QEMU_GNUC_PREREQ(4, 4) -#define smp_mb() __sync_synchronize() + * We use GCC builtin if it's available, as that can use mfence on + * 32-bit as well, e.g. if built with -march=pentium-m. However, on + * i386 the spec is buggy, and the implementation followed it until + * 4.3 (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36793). + */ +#if defined(__i386__) || defined(__x86_64__) +#if !QEMU_GNUC_PREREQ(4, 4) +#if defined __x86_64__ +#define smp_mb() ({ asm volatile("mfence" ::: "memory"); (void)0; }) #else -#define smp_mb() asm volatile("lock; addl $0,0(%%esp) " ::: "memory") +#define smp_mb() ({ asm volatile("lock; addl $0,0(%%esp) " ::: "memory"); (void)0; }) +#endif +#endif +#endif + + +#ifdef __alpha__ +#define smp_read_barrier_depends() asm volatile("mb":::"memory") #endif -#elif defined(__x86_64__) +#if defined(__i386__) || defined(__x86_64__) || defined(__s390x__) +/* + * Because of the strongly ordered storage model, wmb() and rmb() are nops + * here (a compiler barrier only). QEMU doesn't do accesses to write-combining + * qemu memory or non-temporal load/stores from C code. + */ #define smp_wmb() barrier() #define smp_rmb() barrier() -#define smp_mb() asm volatile("mfence" ::: "memory") + +/* + * __sync_lock_test_and_set() is documented to be an acquire barrier only, + * but it is a full barrier at the hardware level. Add a compiler barrier + * to make it a full barrier also at the compiler level. + */ +#define atomic_xchg(ptr, i) (barrier(), __sync_lock_test_and_set(ptr, i)) + +/* + * Load/store with Java volatile semantics. + */ +#define atomic_mb_set(ptr, i) ((void)atomic_xchg(ptr, i)) #elif defined(_ARCH_PPC) /* * We use an eieio() for wmb() on powerpc. This assumes we don't * need to order cacheable and non-cacheable stores with respect to - * each other + * each other. + * + * smp_mb has the same problem as on x86 for not-very-new GCC + * (http://patchwork.ozlabs.org/patch/126184/, Nov 2011). */ -#define smp_wmb() asm volatile("eieio" ::: "memory") - +#define smp_wmb() ({ asm volatile("eieio" ::: "memory"); (void)0; }) #if defined(__powerpc64__) -#define smp_rmb() asm volatile("lwsync" ::: "memory") +#define smp_rmb() ({ asm volatile("lwsync" ::: "memory"); (void)0; }) #else -#define smp_rmb() asm volatile("sync" ::: "memory") +#define smp_rmb() ({ asm volatile("sync" ::: "memory"); (void)0; }) #endif +#define smp_mb() ({ asm volatile("sync" ::: "memory"); (void)0; }) -#define smp_mb() asm volatile("sync" ::: "memory") +#endif /* _ARCH_PPC */ -#else +#endif /* C11 atomics */ /* * For (host) platforms we don't have explicit barrier definitions * for, we use the gcc __sync_synchronize() primitive to generate a * full barrier. This should be safe on all platforms, though it may - * be overkill for wmb() and rmb(). + * be overkill for smp_wmb() and smp_rmb(). */ +#ifndef smp_mb +#define smp_mb() __sync_synchronize() +#endif + +#ifndef smp_wmb +#ifdef __ATOMIC_RELEASE +#define smp_wmb() __atomic_thread_fence(__ATOMIC_RELEASE) +#else #define smp_wmb() __sync_synchronize() -#define smp_mb() __sync_synchronize() +#endif +#endif + +#ifndef smp_rmb +#ifdef __ATOMIC_ACQUIRE +#define smp_rmb() __atomic_thread_fence(__ATOMIC_ACQUIRE) +#else #define smp_rmb() __sync_synchronize() +#endif +#endif + +#ifndef smp_read_barrier_depends +#ifdef __ATOMIC_CONSUME +#define smp_read_barrier_depends() __atomic_thread_fence(__ATOMIC_CONSUME) +#else +#define smp_read_barrier_depends() barrier() +#endif +#endif +#ifndef atomic_read +#define atomic_read(ptr) (*(__typeof__(*ptr) *volatile) (ptr)) #endif +#ifndef atomic_set +#define atomic_set(ptr, i) ((*(__typeof__(*ptr) *volatile) (ptr)) = (i)) +#endif + +/* These have the same semantics as Java volatile variables. + * See http://gee.cs.oswego.edu/dl/jmm/cookbook.html: + * "1. Issue a StoreStore barrier (wmb) before each volatile store." + * 2. Issue a StoreLoad barrier after each volatile store. + * Note that you could instead issue one before each volatile load, but + * this would be slower for typical programs using volatiles in which + * reads greatly outnumber writes. Alternatively, if available, you + * can implement volatile store as an atomic instruction (for example + * XCHG on x86) and omit the barrier. This may be more efficient if + * atomic instructions are cheaper than StoreLoad barriers. + * 3. Issue LoadLoad and LoadStore barriers after each volatile load." + * + * If you prefer to think in terms of "pairing" of memory barriers, + * an atomic_mb_read pairs with an atomic_mb_set. + * + * And for the few ia64 lovers that exist, an atomic_mb_read is a ld.acq, + * while an atomic_mb_set is a st.rel followed by a memory barrier. + * + * These are a bit weaker than __atomic_load/store with __ATOMIC_SEQ_CST + * (see docs/atomics.txt), and I'm not sure that __ATOMIC_ACQ_REL is enough. + * Just always use the barriers manually by the rules above. + */ +#ifndef atomic_mb_read +#define atomic_mb_read(ptr) ({ \ + typeof(*ptr) _val = atomic_read(ptr); \ + smp_rmb(); \ + _val; \ +}) +#endif + +#ifndef atomic_mb_set +#define atomic_mb_set(ptr, i) do { \ + smp_wmb(); \ + atomic_set(ptr, i); \ + smp_mb(); \ +} while (0) +#endif + +#ifndef atomic_xchg +#ifdef __ATOMIC_SEQ_CST +#define atomic_xchg(ptr, i) ({ \ + typeof(*ptr) _new = (i), _old; \ + __atomic_exchange(ptr, &_new, &_old, __ATOMIC_SEQ_CST); \ + _old; \ +}) +#elif defined __clang__ +#define atomic_xchg(ptr, i) __sync_exchange(ptr, i) +#else +/* __sync_lock_test_and_set() is documented to be an acquire barrier only. */ +#define atomic_xchg(ptr, i) (smp_mb(), __sync_lock_test_and_set(ptr, i)) +#endif +#endif + +/* Provide shorter names for GCC atomic builtins. */ +#define atomic_fetch_inc(ptr) __sync_fetch_and_add(ptr, 1) +#define atomic_fetch_dec(ptr) __sync_fetch_and_add(ptr, -1) +#define atomic_fetch_add __sync_fetch_and_add +#define atomic_fetch_sub __sync_fetch_and_sub +#define atomic_fetch_and __sync_fetch_and_and +#define atomic_fetch_or __sync_fetch_and_or +#define atomic_cmpxchg __sync_val_compare_and_swap + +/* And even shorter names that return void. */ +#define atomic_inc(ptr) ((void) __sync_fetch_and_add(ptr, 1)) +#define atomic_dec(ptr) ((void) __sync_fetch_and_add(ptr, -1)) +#define atomic_add(ptr, n) ((void) __sync_fetch_and_add(ptr, n)) +#define atomic_sub(ptr, n) ((void) __sync_fetch_and_sub(ptr, n)) +#define atomic_and(ptr, n) ((void) __sync_fetch_and_and(ptr, n)) +#define atomic_or(ptr, n) ((void) __sync_fetch_and_or(ptr, n)) + #endif diff --git a/include/qemu/error-report.h b/include/qemu/error-report.h index 14c1719ad..3b098a917 100644 --- a/include/qemu/error-report.h +++ b/include/qemu/error-report.h @@ -14,6 +14,7 @@ #define QEMU_ERROR_H #include +#include #include "qemu/compiler.h" typedef struct Location { @@ -40,5 +41,6 @@ void error_print_loc(void); void error_set_progname(const char *argv0); void error_report(const char *fmt, ...) GCC_FMT_ATTR(1, 2); const char *error_get_progname(void); +extern bool enable_timestamp_msg; #endif diff --git a/include/qemu/int128.h b/include/qemu/int128.h index bfe7678a0..9ed47aafd 100644 --- a/include/qemu/int128.h +++ b/include/qemu/int128.h @@ -1,6 +1,10 @@ #ifndef INT128_H #define INT128_H +#include +#include +#include + typedef struct Int128 Int128; struct Int128 { @@ -55,21 +59,26 @@ static inline Int128 int128_rshift(Int128 a, int n) static inline Int128 int128_add(Int128 a, Int128 b) { - Int128 r = { a.lo + b.lo, a.hi + b.hi }; - r.hi += (r.lo < a.lo) || (r.lo < b.lo); - return r; + uint64_t lo = a.lo + b.lo; + + /* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64). Hence, + * a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo. + * Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k. + * + * So the carry is lo < a.lo. + */ + return (Int128) { lo, (uint64_t)a.hi + b.hi + (lo < a.lo) }; } static inline Int128 int128_neg(Int128 a) { - a.lo = ~a.lo; - a.hi = ~a.hi; - return int128_add(a, int128_one()); + uint64_t lo = -a.lo; + return (Int128) { lo, ~(uint64_t)a.hi + !lo }; } static inline Int128 int128_sub(Int128 a, Int128 b) { - return int128_add(a, int128_neg(b)); + return (Int128){ a.lo - b.lo, a.hi - b.hi - (a.lo < b.lo) }; } static inline bool int128_nonneg(Int128 a) @@ -89,7 +98,7 @@ static inline bool int128_ne(Int128 a, Int128 b) static inline bool int128_ge(Int128 a, Int128 b) { - return int128_nonneg(int128_sub(a, b)); + return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo); } static inline bool int128_lt(Int128 a, Int128 b) diff --git a/include/qemu/log.h b/include/qemu/log.h index a9cf2146c..d5154246e 100644 --- a/include/qemu/log.h +++ b/include/qemu/log.h @@ -5,6 +5,7 @@ #include #include #include "qemu/compiler.h" +#include "qom/cpu.h" #ifdef NEED_CPU_H #include "disas/disas.h" #endif @@ -70,22 +71,37 @@ void GCC_FMT_ATTR(2, 3) qemu_log_mask(int mask, const char *fmt, ...); /* Special cases: */ -#ifdef NEED_CPU_H /* cpu_dump_state() logging functions: */ -static inline void log_cpu_state(CPUArchState *env1, int flags) +/** + * log_cpu_state: + * @cpu: The CPU whose state is to be logged. + * @flags: Flags what to log. + * + * Logs the output of cpu_dump_state(). + */ +static inline void log_cpu_state(CPUState *cpu, int flags) { if (qemu_log_enabled()) { - cpu_dump_state(ENV_GET_CPU(env1), qemu_logfile, fprintf, flags); + cpu_dump_state(cpu, qemu_logfile, fprintf, flags); } } -static inline void log_cpu_state_mask(int mask, CPUArchState *env1, int flags) +/** + * log_cpu_state_mask: + * @mask: Mask when to log. + * @cpu: The CPU whose state is to be logged. + * @flags: Flags what to log. + * + * Logs the output of cpu_dump_state() if loglevel includes @mask. + */ +static inline void log_cpu_state_mask(int mask, CPUState *cpu, int flags) { if (qemu_loglevel & mask) { - log_cpu_state(env1, flags); + log_cpu_state(cpu, flags); } } +#ifdef NEED_CPU_H /* disas() and target_disas() to qemu_logfile: */ static inline void log_target_disas(CPUArchState *env, target_ulong start, target_ulong len, int flags) diff --git a/include/qemu/range.h b/include/qemu/range.h index 350237212..b76cc0df0 100644 --- a/include/qemu/range.h +++ b/include/qemu/range.h @@ -1,6 +1,22 @@ #ifndef QEMU_RANGE_H #define QEMU_RANGE_H +#include + +/* + * Operations on 64 bit address ranges. + * Notes: + * - ranges must not wrap around 0, but can include the last byte ~0x0LL. + * - this can not represent a full 0 to ~0x0LL range. + */ + +/* A structure representing a range of addresses. */ +struct Range { + uint64_t begin; /* First byte of the range, or 0 if empty. */ + uint64_t end; /* 1 + the last byte. 0 if range empty or ends at ~0x0LL. */ +}; +typedef struct Range Range; + /* Get last byte of a range from offset + length. * Undefined for ranges that wrap around 0. */ static inline uint64_t range_get_last(uint64_t offset, uint64_t len) diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h index 698fc03d7..ac9f8d41a 100644 --- a/include/qemu/typedefs.h +++ b/include/qemu/typedefs.h @@ -64,5 +64,6 @@ typedef struct VirtIODevice VirtIODevice; typedef struct QEMUSGList QEMUSGList; typedef struct SHPCDevice SHPCDevice; typedef struct FWCfgState FWCfgState; +typedef struct PcGuestInfo PcGuestInfo; #endif /* QEMU_TYPEDEFS_H */ diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 7cb5e54cf..147c25694 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -24,6 +24,7 @@ #include "hw/qdev-core.h" #include "exec/hwaddr.h" #include "qemu/thread.h" +#include "qemu/tls.h" #include "qemu/typedefs.h" typedef int (*WriteCoreDumpFunction)(void *buf, size_t size, void *opaque); @@ -52,6 +53,7 @@ typedef void (*CPUUnassignedAccess)(CPUState *cpu, hwaddr addr, * @class_by_name: Callback to map -cpu command line model name to an * instantiatable CPU type. * @reset: Callback to reset the #CPUState to its initial state. + * @reset_dump_flags: #CPUDumpFlags to use for reset logging. * @do_interrupt: Callback for interrupt handling. * @do_unassigned_access: Callback for unassigned access handling. * @dump_state: Callback for dumping state. @@ -71,6 +73,7 @@ typedef struct CPUClass { ObjectClass *(*class_by_name)(const char *cpu_model); void (*reset)(CPUState *cpu); + int reset_dump_flags; void (*do_interrupt)(CPUState *cpu); CPUUnassignedAccess do_unassigned_access; void (*dump_state)(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf, @@ -113,6 +116,7 @@ struct kvm_run; * CPU and return to its top level loop. * @env_ptr: Pointer to subclass-specific CPUArchState field. * @current_tb: Currently executing TB. + * @next_cpu: Next CPU sharing TB cache. * @kvm_fd: vCPU file descriptor for KVM. * * State of one CPU core or thread. @@ -145,6 +149,7 @@ struct CPUState { void *env_ptr; /* CPUArchState */ struct TranslationBlock *current_tb; + CPUState *next_cpu; int kvm_fd; bool kvm_vcpu_dirty; @@ -156,6 +161,11 @@ struct CPUState { uint32_t halted; /* used by alpha, cris, ppc TCG */ }; +extern CPUState *first_cpu; + +DECLARE_TLS(CPUState *, current_cpu); +#define current_cpu tls_var(current_cpu) + /** * cpu_paging_enabled: * @cpu: The CPU whose state is to be inspected. diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h index 031d1f5fb..00f21f3da 100644 --- a/include/sysemu/dma.h +++ b/include/sysemu/dma.h @@ -29,6 +29,7 @@ struct QEMUSGList { int nsg; int nalloc; size_t size; + DeviceState *dev; AddressSpace *as; }; @@ -189,7 +190,8 @@ struct ScatterGatherEntry { dma_addr_t len; }; -void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint, AddressSpace *as); +void qemu_sglist_init(QEMUSGList *qsg, DeviceState *dev, int alloc_hint, + AddressSpace *as); void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len); void qemu_sglist_destroy(QEMUSGList *qsg); #endif diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index a14cfe949..1e08a8511 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -169,11 +169,11 @@ void *kvm_arch_ram_alloc(ram_addr_t size); void kvm_setup_guest_memory(void *start, size_t size); void kvm_flush_coalesced_mmio_buffer(void); -int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr, +int kvm_insert_breakpoint(CPUArchState *env, target_ulong addr, target_ulong len, int type); -int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr, +int kvm_remove_breakpoint(CPUArchState *env, target_ulong addr, target_ulong len, int type); -void kvm_remove_all_breakpoints(CPUArchState *current_env); +void kvm_remove_all_breakpoints(CPUState *cpu); int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap); #ifndef _WIN32 int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset); @@ -252,9 +252,9 @@ struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *cpu, int kvm_sw_breakpoints_active(CPUState *cpu); -int kvm_arch_insert_sw_breakpoint(CPUState *current_cpu, +int kvm_arch_insert_sw_breakpoint(CPUState *cpu, struct kvm_sw_breakpoint *bp); -int kvm_arch_remove_sw_breakpoint(CPUState *current_cpu, +int kvm_arch_remove_sw_breakpoint(CPUState *cpu, struct kvm_sw_breakpoint *bp); int kvm_arch_insert_hw_breakpoint(target_ulong addr, target_ulong len, int type); diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index 2fb71afa2..3caeb66eb 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -35,8 +35,8 @@ void vm_state_notify(int running, RunState state); #define VMRESET_REPORT true void vm_start(void); -void vm_stop(RunState state); -void vm_stop_force_state(RunState state); +int vm_stop(RunState state); +int vm_stop_force_state(RunState state); typedef enum WakeupReason { QEMU_WAKEUP_REASON_OTHER = 0, @@ -185,6 +185,8 @@ char *get_boot_devices_list(size_t *size); DeviceState *get_boot_device(uint32_t position); +QemuOpts *qemu_get_machine_opts(void); + bool usb_enabled(bool default_usb); extern QemuOptsList qemu_drive_opts; diff --git a/ioport.c b/ioport.c index a0ac2a0a4..89b17d69f 100644 --- a/ioport.c +++ b/ioport.c @@ -28,285 +28,54 @@ #include "exec/ioport.h" #include "trace.h" #include "exec/memory.h" +#include "exec/address-spaces.h" -/***********************************************************/ -/* IO Port */ - -//#define DEBUG_UNUSED_IOPORT //#define DEBUG_IOPORT -#ifdef DEBUG_UNUSED_IOPORT -# define LOG_UNUSED_IOPORT(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__) -#else -# define LOG_UNUSED_IOPORT(fmt, ...) do{ } while (0) -#endif - #ifdef DEBUG_IOPORT # define LOG_IOPORT(...) qemu_log_mask(CPU_LOG_IOPORT, ## __VA_ARGS__) #else # define LOG_IOPORT(...) do { } while (0) #endif -/* XXX: use a two level table to limit memory usage */ - -static void *ioport_opaque[MAX_IOPORTS]; -static IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS]; -static IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS]; -static IOPortDestructor *ioport_destructor_table[MAX_IOPORTS]; - -static IOPortReadFunc default_ioport_readb, default_ioport_readw, default_ioport_readl; -static IOPortWriteFunc default_ioport_writeb, default_ioport_writew, default_ioport_writel; - -static uint32_t ioport_read(int index, uint32_t address) -{ - static IOPortReadFunc * const default_func[3] = { - default_ioport_readb, - default_ioport_readw, - default_ioport_readl - }; - IOPortReadFunc *func = ioport_read_table[index][address]; - if (!func) - func = default_func[index]; - return func(ioport_opaque[address], address); -} - -static void ioport_write(int index, uint32_t address, uint32_t data) -{ - static IOPortWriteFunc * const default_func[3] = { - default_ioport_writeb, - default_ioport_writew, - default_ioport_writel - }; - IOPortWriteFunc *func = ioport_write_table[index][address]; - if (!func) - func = default_func[index]; - func(ioport_opaque[address], address, data); -} - -static uint32_t default_ioport_readb(void *opaque, uint32_t address) -{ - LOG_UNUSED_IOPORT("unused inb: port=0x%04"PRIx32"\n", address); - return 0xff; -} - -static void default_ioport_writeb(void *opaque, uint32_t address, uint32_t data) -{ - LOG_UNUSED_IOPORT("unused outb: port=0x%04"PRIx32" data=0x%02"PRIx32"\n", - address, data); -} - -/* default is to make two byte accesses */ -static uint32_t default_ioport_readw(void *opaque, uint32_t address) -{ - uint32_t data; - data = ioport_read(0, address); - address = (address + 1) & IOPORTS_MASK; - data |= ioport_read(0, address) << 8; - return data; -} - -static void default_ioport_writew(void *opaque, uint32_t address, uint32_t data) -{ - ioport_write(0, address, data & 0xff); - address = (address + 1) & IOPORTS_MASK; - ioport_write(0, address, (data >> 8) & 0xff); -} - -static uint32_t default_ioport_readl(void *opaque, uint32_t address) -{ - LOG_UNUSED_IOPORT("unused inl: port=0x%04"PRIx32"\n", address); - return 0xffffffff; -} - -static void default_ioport_writel(void *opaque, uint32_t address, uint32_t data) -{ - LOG_UNUSED_IOPORT("unused outl: port=0x%04"PRIx32" data=0x%02"PRIx32"\n", - address, data); -} - -static int ioport_bsize(int size, int *bsize) -{ - if (size == 1) { - *bsize = 0; - } else if (size == 2) { - *bsize = 1; - } else if (size == 4) { - *bsize = 2; - } else { - return -1; - } - return 0; -} - -/* size is the word size in byte */ -int register_ioport_read(pio_addr_t start, int length, int size, - IOPortReadFunc *func, void *opaque) -{ - int i, bsize; - - if (ioport_bsize(size, &bsize)) { - hw_error("register_ioport_read: invalid size"); - return -1; - } - for(i = start; i < start + length; ++i) { - ioport_read_table[bsize][i] = func; - if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque) - hw_error("register_ioport_read: invalid opaque for address 0x%x", - i); - ioport_opaque[i] = opaque; - } - return 0; -} - -/* size is the word size in byte */ -int register_ioport_write(pio_addr_t start, int length, int size, - IOPortWriteFunc *func, void *opaque) -{ - int i, bsize; - - if (ioport_bsize(size, &bsize)) { - hw_error("register_ioport_write: invalid size"); - return -1; - } - for(i = start; i < start + length; ++i) { - ioport_write_table[bsize][i] = func; - if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque) - hw_error("register_ioport_write: invalid opaque for address 0x%x", - i); - ioport_opaque[i] = opaque; - } - return 0; -} - -static uint32_t ioport_readb_thunk(void *opaque, uint32_t addr) -{ - IORange *ioport = opaque; - uint64_t data; - - ioport->ops->read(ioport, addr - ioport->base, 1, &data); - return data; -} - -static uint32_t ioport_readw_thunk(void *opaque, uint32_t addr) -{ - IORange *ioport = opaque; - uint64_t data; - - ioport->ops->read(ioport, addr - ioport->base, 2, &data); - return data; -} - -static uint32_t ioport_readl_thunk(void *opaque, uint32_t addr) -{ - IORange *ioport = opaque; - uint64_t data; - - ioport->ops->read(ioport, addr - ioport->base, 4, &data); - return data; -} - -static void ioport_writeb_thunk(void *opaque, uint32_t addr, uint32_t data) -{ - IORange *ioport = opaque; - - ioport->ops->write(ioport, addr - ioport->base, 1, data); -} - -static void ioport_writew_thunk(void *opaque, uint32_t addr, uint32_t data) -{ - IORange *ioport = opaque; - - ioport->ops->write(ioport, addr - ioport->base, 2, data); -} - -static void ioport_writel_thunk(void *opaque, uint32_t addr, uint32_t data) -{ - IORange *ioport = opaque; - - ioport->ops->write(ioport, addr - ioport->base, 4, data); -} - -static void iorange_destructor_thunk(void *opaque) -{ - IORange *iorange = opaque; - - if (iorange->ops->destructor) { - iorange->ops->destructor(iorange); - } -} - -void ioport_register(IORange *ioport) -{ - register_ioport_read(ioport->base, ioport->len, 1, - ioport_readb_thunk, ioport); - register_ioport_read(ioport->base, ioport->len, 2, - ioport_readw_thunk, ioport); - register_ioport_read(ioport->base, ioport->len, 4, - ioport_readl_thunk, ioport); - register_ioport_write(ioport->base, ioport->len, 1, - ioport_writeb_thunk, ioport); - register_ioport_write(ioport->base, ioport->len, 2, - ioport_writew_thunk, ioport); - register_ioport_write(ioport->base, ioport->len, 4, - ioport_writel_thunk, ioport); - ioport_destructor_table[ioport->base] = iorange_destructor_thunk; -} - -void isa_unassign_ioport(pio_addr_t start, int length) -{ - int i; - - if (ioport_destructor_table[start]) { - ioport_destructor_table[start](ioport_opaque[start]); - ioport_destructor_table[start] = NULL; - } - for(i = start; i < start + length; i++) { - ioport_read_table[0][i] = NULL; - ioport_read_table[1][i] = NULL; - ioport_read_table[2][i] = NULL; - - ioport_write_table[0][i] = NULL; - ioport_write_table[1][i] = NULL; - ioport_write_table[2][i] = NULL; - - ioport_opaque[i] = NULL; - } -} - -bool isa_is_ioport_assigned(pio_addr_t start) -{ - return (ioport_read_table[0][start] || ioport_write_table[0][start] || - ioport_read_table[1][start] || ioport_write_table[1][start] || - ioport_read_table[2][start] || ioport_write_table[2][start]); -} - -/***********************************************************/ +typedef struct MemoryRegionPortioList { + MemoryRegion mr; + void *portio_opaque; + MemoryRegionPortio ports[]; +} MemoryRegionPortioList; void cpu_outb(pio_addr_t addr, uint8_t val) { LOG_IOPORT("outb: %04"FMT_pioaddr" %02"PRIx8"\n", addr, val); trace_cpu_out(addr, val); - ioport_write(0, addr, val); + address_space_write(&address_space_io, addr, &val, 1); } void cpu_outw(pio_addr_t addr, uint16_t val) { + uint8_t buf[2]; + LOG_IOPORT("outw: %04"FMT_pioaddr" %04"PRIx16"\n", addr, val); trace_cpu_out(addr, val); - ioport_write(1, addr, val); + stw_p(buf, val); + address_space_write(&address_space_io, addr, buf, 2); } void cpu_outl(pio_addr_t addr, uint32_t val) { + uint8_t buf[4]; + LOG_IOPORT("outl: %04"FMT_pioaddr" %08"PRIx32"\n", addr, val); trace_cpu_out(addr, val); - ioport_write(2, addr, val); + stl_p(buf, val); + address_space_write(&address_space_io, addr, buf, 4); } uint8_t cpu_inb(pio_addr_t addr) { uint8_t val; - val = ioport_read(0, addr); + + address_space_read(&address_space_io, addr, &val, 1); trace_cpu_in(addr, val); LOG_IOPORT("inb : %04"FMT_pioaddr" %02"PRIx8"\n", addr, val); return val; @@ -314,8 +83,11 @@ uint8_t cpu_inb(pio_addr_t addr) uint16_t cpu_inw(pio_addr_t addr) { + uint8_t buf[2]; uint16_t val; - val = ioport_read(1, addr); + + address_space_read(&address_space_io, addr, buf, 2); + val = lduw_p(buf); trace_cpu_in(addr, val); LOG_IOPORT("inw : %04"FMT_pioaddr" %04"PRIx16"\n", addr, val); return val; @@ -323,14 +95,18 @@ uint16_t cpu_inw(pio_addr_t addr) uint32_t cpu_inl(pio_addr_t addr) { + uint8_t buf[4]; uint32_t val; - val = ioport_read(2, addr); + + address_space_read(&address_space_io, addr, buf, 4); + val = ldl_p(buf); trace_cpu_in(addr, val); LOG_IOPORT("inl : %04"FMT_pioaddr" %08"PRIx32"\n", addr, val); return val; } void portio_list_init(PortioList *piolist, + Object *owner, const MemoryRegionPortio *callbacks, void *opaque, const char *name) { @@ -343,55 +119,104 @@ void portio_list_init(PortioList *piolist, piolist->ports = callbacks; piolist->nr = 0; piolist->regions = g_new0(MemoryRegion *, n); - piolist->aliases = g_new0(MemoryRegion *, n); piolist->address_space = NULL; piolist->opaque = opaque; + piolist->owner = owner; piolist->name = name; } void portio_list_destroy(PortioList *piolist) { g_free(piolist->regions); - g_free(piolist->aliases); } +static const MemoryRegionPortio *find_portio(MemoryRegionPortioList *mrpio, + uint64_t offset, unsigned size, + bool write) +{ + const MemoryRegionPortio *mrp; + + for (mrp = mrpio->ports; mrp->size; ++mrp) { + if (offset >= mrp->offset && offset < mrp->offset + mrp->len && + size == mrp->size && + (write ? (bool)mrp->write : (bool)mrp->read)) { + return mrp; + } + } + return NULL; +} + +static uint64_t portio_read(void *opaque, hwaddr addr, unsigned size) +{ + MemoryRegionPortioList *mrpio = opaque; + const MemoryRegionPortio *mrp = find_portio(mrpio, addr, size, false); + uint64_t data; + + data = ((uint64_t)1 << (size * 8)) - 1; + if (mrp) { + data = mrp->read(mrpio->portio_opaque, mrp->base + addr); + } else if (size == 2) { + mrp = find_portio(mrpio, addr, 1, false); + assert(mrp); + data = mrp->read(mrpio->portio_opaque, mrp->base + addr) | + (mrp->read(mrpio->portio_opaque, mrp->base + addr + 1) << 8); + } + return data; +} + +static void portio_write(void *opaque, hwaddr addr, uint64_t data, + unsigned size) +{ + MemoryRegionPortioList *mrpio = opaque; + const MemoryRegionPortio *mrp = find_portio(mrpio, addr, size, true); + + if (mrp) { + mrp->write(mrpio->portio_opaque, mrp->base + addr, data); + } else if (size == 2) { + mrp = find_portio(mrpio, addr, 1, true); + assert(mrp); + mrp->write(mrpio->portio_opaque, mrp->base + addr, data & 0xff); + mrp->write(mrpio->portio_opaque, mrp->base + addr + 1, data >> 8); + } +} + +static const MemoryRegionOps portio_ops = { + .read = portio_read, + .write = portio_write, + .valid.unaligned = true, + .impl.unaligned = true, +}; + static void portio_list_add_1(PortioList *piolist, const MemoryRegionPortio *pio_init, unsigned count, unsigned start, unsigned off_low, unsigned off_high) { - MemoryRegionPortio *pio; - MemoryRegionOps *ops; - MemoryRegion *region, *alias; + MemoryRegionPortioList *mrpio; unsigned i; /* Copy the sub-list and null-terminate it. */ - pio = g_new(MemoryRegionPortio, count + 1); - memcpy(pio, pio_init, sizeof(MemoryRegionPortio) * count); - memset(pio + count, 0, sizeof(MemoryRegionPortio)); + mrpio = g_malloc0(sizeof(MemoryRegionPortioList) + + sizeof(MemoryRegionPortio) * (count + 1)); + mrpio->portio_opaque = piolist->opaque; + memcpy(mrpio->ports, pio_init, sizeof(MemoryRegionPortio) * count); + memset(mrpio->ports + count, 0, sizeof(MemoryRegionPortio)); /* Adjust the offsets to all be zero-based for the region. */ for (i = 0; i < count; ++i) { - pio[i].offset -= off_low; + mrpio->ports[i].offset -= off_low; + mrpio->ports[i].base = start + off_low; } - ops = g_new0(MemoryRegionOps, 1); - ops->old_portio = pio; - - region = g_new(MemoryRegion, 1); - alias = g_new(MemoryRegion, 1); /* * Use an alias so that the callback is called with an absolute address, * rather than an offset relative to to start + off_low. */ - memory_region_init_io(region, ops, piolist->opaque, piolist->name, - INT64_MAX); - memory_region_init_alias(alias, piolist->name, - region, start + off_low, off_high - off_low); + memory_region_init_io(&mrpio->mr, piolist->owner, &portio_ops, mrpio, + piolist->name, off_high - off_low); memory_region_add_subregion(piolist->address_space, - start + off_low, alias); - piolist->regions[piolist->nr] = region; - piolist->aliases[piolist->nr] = alias; + start + off_low, &mrpio->mr); + piolist->regions[piolist->nr] = &mrpio->mr; ++piolist->nr; } @@ -434,19 +259,14 @@ void portio_list_add(PortioList *piolist, void portio_list_del(PortioList *piolist) { - MemoryRegion *mr, *alias; + MemoryRegionPortioList *mrpio; unsigned i; for (i = 0; i < piolist->nr; ++i) { - mr = piolist->regions[i]; - alias = piolist->aliases[i]; - memory_region_del_subregion(piolist->address_space, alias); - memory_region_destroy(alias); - memory_region_destroy(mr); - g_free((MemoryRegionOps *)mr->ops); - g_free(mr); - g_free(alias); + mrpio = container_of(piolist->regions[i], MemoryRegionPortioList, mr); + memory_region_del_subregion(piolist->address_space, &mrpio->mr); + memory_region_destroy(&mrpio->mr); + g_free(mrpio); piolist->regions[i] = NULL; - piolist->aliases[i] = NULL; } } diff --git a/kvm-all.c b/kvm-all.c index c757dd262..232c39a61 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -789,6 +789,7 @@ static void kvm_set_phys_mem(MemoryRegionSection *section, bool add) static void kvm_region_add(MemoryListener *listener, MemoryRegionSection *section) { + memory_region_ref(section->mr); kvm_set_phys_mem(section, true); } @@ -796,6 +797,7 @@ static void kvm_region_del(MemoryListener *listener, MemoryRegionSection *section) { kvm_set_phys_mem(section, false); + memory_region_unref(section->mr); } static void kvm_log_sync(MemoryListener *listener, @@ -837,6 +839,8 @@ static void kvm_mem_ioeventfd_add(MemoryListener *listener, data, true, int128_get64(section->size), match_data); if (r < 0) { + fprintf(stderr, "%s: error adding ioeventfd: %s\n", + __func__, strerror(-r)); abort(); } } @@ -869,6 +873,8 @@ static void kvm_io_ioeventfd_add(MemoryListener *listener, data, true, int128_get64(section->size), match_data); if (r < 0) { + fprintf(stderr, "%s: error adding ioeventfd: %s\n", + __func__, strerror(-r)); abort(); } } @@ -1012,11 +1018,8 @@ static void kvm_add_routing_entry(KVMState *s, } n = s->irq_routes->nr++; new = &s->irq_routes->entries[n]; - memset(new, 0, sizeof(*new)); - new->gsi = entry->gsi; - new->type = entry->type; - new->flags = entry->flags; - new->u = entry->u; + + *new = *entry; set_gsi(s, entry->gsi); } @@ -1033,9 +1036,11 @@ static int kvm_update_routing_entry(KVMState *s, continue; } - entry->type = new_entry->type; - entry->flags = new_entry->flags; - entry->u = new_entry->u; + if(!memcmp(entry, new_entry, sizeof *entry)) { + return 0; + } + + *entry = *new_entry; kvm_irqchip_commit_routes(s); @@ -1047,7 +1052,7 @@ static int kvm_update_routing_entry(KVMState *s, void kvm_irqchip_add_irq_route(KVMState *s, int irq, int irqchip, int pin) { - struct kvm_irq_routing_entry e; + struct kvm_irq_routing_entry e = {}; assert(pin < s->gsi_count); @@ -1160,7 +1165,7 @@ int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg) return virq; } - route = g_malloc(sizeof(KVMMSIRoute)); + route = g_malloc0(sizeof(KVMMSIRoute)); route->kroute.gsi = virq; route->kroute.type = KVM_IRQ_ROUTING_MSI; route->kroute.flags = 0; @@ -1182,7 +1187,7 @@ int kvm_irqchip_send_msi(KVMState *s, MSIMessage msg) int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg) { - struct kvm_irq_routing_entry kroute; + struct kvm_irq_routing_entry kroute = {}; int virq; if (!kvm_gsi_routing_enabled()) { @@ -1209,7 +1214,7 @@ int kvm_irqchip_add_msi_route(KVMState *s, MSIMessage msg) int kvm_irqchip_update_msi_route(KVMState *s, int virq, MSIMessage msg) { - struct kvm_irq_routing_entry kroute; + struct kvm_irq_routing_entry kroute = {}; if (!kvm_irqchip_in_kernel()) { return -ENOSYS; @@ -1283,12 +1288,9 @@ int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq) static int kvm_irqchip_create(KVMState *s) { - QemuOptsList *list = qemu_find_opts("machine"); int ret; - if (QTAILQ_EMPTY(&list->head) || - !qemu_opt_get_bool(QTAILQ_FIRST(&list->head), - "kernel_irqchip", true) || + if (!qemu_opt_get_bool(qemu_get_machine_opts(), "kernel_irqchip", true) || !kvm_check_extension(s, KVM_CAP_IRQCHIP)) { return 0; } @@ -1898,16 +1900,15 @@ int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap) return data.err; } -int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr, +int kvm_insert_breakpoint(CPUArchState *env, target_ulong addr, target_ulong len, int type) { - CPUState *current_cpu = ENV_GET_CPU(current_env); + CPUState *cpu = ENV_GET_CPU(env); struct kvm_sw_breakpoint *bp; - CPUArchState *env; int err; if (type == GDB_BREAKPOINT_SW) { - bp = kvm_find_sw_breakpoint(current_cpu, addr); + bp = kvm_find_sw_breakpoint(cpu, addr); if (bp) { bp->use_count++; return 0; @@ -1920,14 +1921,13 @@ int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr, bp->pc = addr; bp->use_count = 1; - err = kvm_arch_insert_sw_breakpoint(current_cpu, bp); + err = kvm_arch_insert_sw_breakpoint(cpu, bp); if (err) { g_free(bp); return err; } - QTAILQ_INSERT_HEAD(¤t_cpu->kvm_state->kvm_sw_breakpoints, - bp, entry); + QTAILQ_INSERT_HEAD(&cpu->kvm_state->kvm_sw_breakpoints, bp, entry); } else { err = kvm_arch_insert_hw_breakpoint(addr, len, type); if (err) { @@ -1935,7 +1935,9 @@ int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr, } } - for (env = first_cpu; env != NULL; env = env->next_cpu) { + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { + CPUArchState *env = cpu->env_ptr; + err = kvm_update_guest_debug(env, 0); if (err) { return err; @@ -1944,16 +1946,15 @@ int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr, return 0; } -int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr, +int kvm_remove_breakpoint(CPUArchState *env, target_ulong addr, target_ulong len, int type) { - CPUState *current_cpu = ENV_GET_CPU(current_env); + CPUState *cpu = ENV_GET_CPU(env); struct kvm_sw_breakpoint *bp; - CPUArchState *env; int err; if (type == GDB_BREAKPOINT_SW) { - bp = kvm_find_sw_breakpoint(current_cpu, addr); + bp = kvm_find_sw_breakpoint(cpu, addr); if (!bp) { return -ENOENT; } @@ -1963,12 +1964,12 @@ int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr, return 0; } - err = kvm_arch_remove_sw_breakpoint(current_cpu, bp); + err = kvm_arch_remove_sw_breakpoint(cpu, bp); if (err) { return err; } - QTAILQ_REMOVE(¤t_cpu->kvm_state->kvm_sw_breakpoints, bp, entry); + QTAILQ_REMOVE(&cpu->kvm_state->kvm_sw_breakpoints, bp, entry); g_free(bp); } else { err = kvm_arch_remove_hw_breakpoint(addr, len, type); @@ -1977,7 +1978,9 @@ int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr, } } - for (env = first_cpu; env != NULL; env = env->next_cpu) { + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { + CPUArchState *env = cpu->env_ptr; + err = kvm_update_guest_debug(env, 0); if (err) { return err; @@ -1986,19 +1989,15 @@ int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr, return 0; } -void kvm_remove_all_breakpoints(CPUArchState *current_env) +void kvm_remove_all_breakpoints(CPUState *cpu) { - CPUState *current_cpu = ENV_GET_CPU(current_env); struct kvm_sw_breakpoint *bp, *next; - KVMState *s = current_cpu->kvm_state; - CPUArchState *env; - CPUState *cpu; + KVMState *s = cpu->kvm_state; QTAILQ_FOREACH_SAFE(bp, &s->kvm_sw_breakpoints, entry, next) { - if (kvm_arch_remove_sw_breakpoint(current_cpu, bp) != 0) { + if (kvm_arch_remove_sw_breakpoint(cpu, bp) != 0) { /* Try harder to find a CPU that currently sees the breakpoint. */ - for (env = first_cpu; env != NULL; env = env->next_cpu) { - cpu = ENV_GET_CPU(env); + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { if (kvm_arch_remove_sw_breakpoint(cpu, bp) == 0) { break; } @@ -2009,7 +2008,9 @@ void kvm_remove_all_breakpoints(CPUArchState *current_env) } kvm_arch_remove_all_hw_breakpoints(); - for (env = first_cpu; env != NULL; env = env->next_cpu) { + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { + CPUArchState *env = cpu->env_ptr; + kvm_update_guest_debug(env, 0); } } @@ -2021,19 +2022,19 @@ int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap) return -EINVAL; } -int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr, +int kvm_insert_breakpoint(CPUArchState *env, target_ulong addr, target_ulong len, int type) { return -EINVAL; } -int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr, +int kvm_remove_breakpoint(CPUArchState *env, target_ulong addr, target_ulong len, int type) { return -EINVAL; } -void kvm_remove_all_breakpoints(CPUArchState *current_env) +void kvm_remove_all_breakpoints(CPUState *cpu) { } #endif /* !KVM_CAP_SET_GUEST_DEBUG */ diff --git a/kvm-stub.c b/kvm-stub.c index dec7a836d..370c8371d 100644 --- a/kvm-stub.c +++ b/kvm-stub.c @@ -83,19 +83,19 @@ int kvm_update_guest_debug(CPUArchState *env, unsigned long reinject_trap) return -ENOSYS; } -int kvm_insert_breakpoint(CPUArchState *current_env, target_ulong addr, +int kvm_insert_breakpoint(CPUArchState *env, target_ulong addr, target_ulong len, int type) { return -EINVAL; } -int kvm_remove_breakpoint(CPUArchState *current_env, target_ulong addr, +int kvm_remove_breakpoint(CPUArchState *env, target_ulong addr, target_ulong len, int type) { return -EINVAL; } -void kvm_remove_all_breakpoints(CPUArchState *current_env) +void kvm_remove_all_breakpoints(CPUState *cpu) { } diff --git a/linux-user/alpha/target_cpu.h b/linux-user/alpha/target_cpu.h new file mode 100644 index 000000000..42562452b --- /dev/null +++ b/linux-user/alpha/target_cpu.h @@ -0,0 +1,36 @@ +/* + * Alpha specific CPU ABI and functions for linux-user + * + * Copyright (c) 2007 Jocelyn Mayer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUAlphaState *env, target_ulong newsp) +{ + if (newsp) { + env->ir[IR_SP] = newsp; + } + env->ir[IR_V0] = 0; + env->ir[IR_A3] = 0; +} + +static inline void cpu_set_tls(CPUAlphaState *env, target_ulong newtls) +{ + env->unique = newtls; +} + +#endif diff --git a/linux-user/arm/target_cpu.h b/linux-user/arm/target_cpu.h new file mode 100644 index 000000000..ed323c079 --- /dev/null +++ b/linux-user/arm/target_cpu.h @@ -0,0 +1,35 @@ +/* + * ARM specific CPU ABI and functions for linux-user + * + * Copyright (c) 2003 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp) +{ + if (newsp) { + env->regs[13] = newsp; + } + env->regs[0] = 0; +} + +static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls) +{ + env->cp15.c13_tls2 = newtls; +} + +#endif diff --git a/linux-user/cris/target_cpu.h b/linux-user/cris/target_cpu.h new file mode 100644 index 000000000..4d787e5ff --- /dev/null +++ b/linux-user/cris/target_cpu.h @@ -0,0 +1,36 @@ +/* + * CRIS specific CPU ABI and functions for linux-user + * + * Copyright (c) 2007 AXIS Communications AB + * Written by Edgar E. Iglesias + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 Lesser General Public + * License along with this library; if not, see . + */ +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUCRISState *env, target_ulong newsp) +{ + if (newsp) { + env->regs[14] = newsp; + } + env->regs[10] = 0; +} + +static inline void cpu_set_tls(CPUCRISState *env, target_ulong newtls) +{ + env->pregs[PR_PID] = (env->pregs[PR_PID] & 0xff) | newtls; +} + +#endif diff --git a/linux-user/elfload.c b/linux-user/elfload.c index ddef23e6d..7ce2eab1b 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -125,7 +125,7 @@ typedef abi_int target_pid_t; static const char *get_elf_platform(void) { static char elf_platform[] = "i386"; - int family = (thread_env->cpuid_version >> 8) & 0xff; + int family = object_property_get_int(OBJECT(thread_cpu), "family", NULL); if (family > 6) family = 6; if (family >= 3) @@ -137,7 +137,9 @@ static const char *get_elf_platform(void) static uint32_t get_elf_hwcap(void) { - return thread_env->features[FEAT_1_EDX]; + X86CPU *cpu = X86_CPU(thread_cpu); + + return cpu->env.features[FEAT_1_EDX]; } #ifdef TARGET_X86_64 @@ -404,7 +406,7 @@ static int validate_guest_space(unsigned long guest_base, static uint32_t get_elf_hwcap(void) { - CPUARMState *e = thread_env; + ARMCPU *cpu = ARM_CPU(thread_cpu); uint32_t hwcaps = 0; hwcaps |= ARM_HWCAP_ARM_SWP; @@ -415,7 +417,7 @@ static uint32_t get_elf_hwcap(void) /* probe for the extra features */ #define GET_FEATURE(feat, hwcap) \ - do {if (arm_feature(e, feat)) { hwcaps |= hwcap; } } while (0) + do { if (arm_feature(&cpu->env, feat)) { hwcaps |= hwcap; } } while (0) GET_FEATURE(ARM_FEATURE_VFP, ARM_HWCAP_ARM_VFP); GET_FEATURE(ARM_FEATURE_IWMMXT, ARM_HWCAP_ARM_IWMMXT); GET_FEATURE(ARM_FEATURE_THUMB2EE, ARM_HWCAP_ARM_THUMBEE); @@ -619,13 +621,13 @@ enum { static uint32_t get_elf_hwcap(void) { - CPUPPCState *e = thread_env; + PowerPCCPU *cpu = POWERPC_CPU(thread_cpu); uint32_t features = 0; /* We don't have to be terribly complete here; the high points are Altivec/FP/SPE support. Anything else is just a bonus. */ #define GET_FEATURE(flag, feature) \ - do {if (e->insns_flags & flag) features |= feature; } while(0) + do { if (cpu->env.insns_flags & flag) { features |= feature; } } while (0) GET_FEATURE(PPC_64B, QEMU_PPC_FEATURE_64); GET_FEATURE(PPC_FLOAT, QEMU_PPC_FEATURE_HAS_FPU); GET_FEATURE(PPC_ALTIVEC, QEMU_PPC_FEATURE_HAS_ALTIVEC); @@ -2628,7 +2630,7 @@ static int fill_note_info(struct elf_note_info *info, long signr, const CPUArchState *env) { #define NUMNOTES 3 - CPUArchState *cpu = NULL; + CPUState *cpu = NULL; TaskState *ts = (TaskState *)env->opaque; int i; @@ -2667,9 +2669,10 @@ static int fill_note_info(struct elf_note_info *info, /* read and fill status of all threads */ cpu_list_lock(); for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { - if (cpu == thread_env) + if (cpu == thread_cpu) { continue; - fill_thread_info(info, cpu); + } + fill_thread_info(info, (CPUArchState *)cpu->env_ptr); } cpu_list_unlock(); diff --git a/linux-user/i386/target_cpu.h b/linux-user/i386/target_cpu.h new file mode 100644 index 000000000..abcac79d2 --- /dev/null +++ b/linux-user/i386/target_cpu.h @@ -0,0 +1,33 @@ +/* + * i386 specific CPU ABI and functions for linux-user + * + * Copyright (c) 2003 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUX86State *env, target_ulong newsp) +{ + if (newsp) { + env->regs[R_ESP] = newsp; + } + env->regs[R_EAX] = 0; +} + +/* TODO: need to implement cpu_set_tls() */ + +#endif diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index 8a4776756..439c2a9e3 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -88,8 +88,6 @@ #endif IOCTL(SIOCATMARK, 0, TYPE_NULL) - IOCTL(SIOCADDRT, IOC_W, MK_PTR(MK_STRUCT(STRUCT_rtentry))) - IOCTL(SIOCDELRT, IOC_W, MK_PTR(MK_STRUCT(STRUCT_rtentry))) IOCTL(SIOCGIFNAME, IOC_RW, MK_PTR(TYPE_INT)) IOCTL(SIOCGIFFLAGS, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_short_ifreq))) IOCTL(SIOCSIFFLAGS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_short_ifreq))) @@ -379,3 +377,7 @@ MK_PTR(MK_STRUCT(STRUCT_dm_ioctl))) IOCTL_SPECIAL(DM_DEV_SET_GEOMETRY, IOC_RW, do_ioctl_dm, MK_PTR(MK_STRUCT(STRUCT_dm_ioctl))) + IOCTL_SPECIAL(SIOCADDRT, IOC_W, do_ioctl_rt, + MK_PTR(MK_STRUCT(STRUCT_rtentry))) + IOCTL_SPECIAL(SIOCDELRT, IOC_W, do_ioctl_rt, + MK_PTR(MK_STRUCT(STRUCT_rtentry))) diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c index 381ab8914..5cd6d9155 100644 --- a/linux-user/linuxload.c +++ b/linux-user/linuxload.c @@ -89,7 +89,8 @@ static int prepare_binprm(struct linux_binprm *bprm) abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp, abi_ulong stringp, int push_ptr) { - TaskState *ts = (TaskState *)thread_env->opaque; + CPUArchState *env = thread_cpu->env_ptr; + TaskState *ts = (TaskState *)env->opaque; int n = sizeof(abi_ulong); abi_ulong envp; abi_ulong argv; diff --git a/linux-user/m68k/target_cpu.h b/linux-user/m68k/target_cpu.h new file mode 100644 index 000000000..8a2a305a0 --- /dev/null +++ b/linux-user/m68k/target_cpu.h @@ -0,0 +1,34 @@ +/* + * m68k specific CPU ABI and functions for linux-user + * + * Copyright (c) 2005-2007 CodeSourcery + * Written by Paul Brook + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUM68KState *env, target_ulong newsp) +{ + if (newsp) { + env->aregs[7] = newsp; + } + env->dregs[0] = 0; +} + +/* TODO: need to implement cpu_set_tls() */ + +#endif diff --git a/linux-user/main.c b/linux-user/main.c index af82db87b..7f15d3da2 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -120,15 +120,15 @@ void fork_end(int child) if (child) { /* Child processes created by fork() only have a single thread. Discard information about the parent threads. */ - first_cpu = thread_env; - thread_env->next_cpu = NULL; + first_cpu = thread_cpu; + first_cpu->next_cpu = NULL; pending_cpus = 0; pthread_mutex_init(&exclusive_lock, NULL); pthread_mutex_init(&cpu_list_mutex, NULL); pthread_cond_init(&exclusive_cond, NULL); pthread_cond_init(&exclusive_resume, NULL); pthread_mutex_init(&tcg_ctx.tb_ctx.tb_lock, NULL); - gdbserver_fork(thread_env); + gdbserver_fork((CPUArchState *)thread_cpu->env_ptr); } else { pthread_mutex_unlock(&exclusive_lock); pthread_mutex_unlock(&tcg_ctx.tb_ctx.tb_lock); @@ -148,7 +148,6 @@ static inline void exclusive_idle(void) Must only be called from outside cpu_arm_exec. */ static inline void start_exclusive(void) { - CPUArchState *other; CPUState *other_cpu; pthread_mutex_lock(&exclusive_lock); @@ -156,8 +155,7 @@ static inline void start_exclusive(void) pending_cpus = 1; /* Make all other cpus stop executing. */ - for (other = first_cpu; other; other = other->next_cpu) { - other_cpu = ENV_GET_CPU(other); + for (other_cpu = first_cpu; other_cpu; other_cpu = other_cpu->next_cpu) { if (other_cpu->running) { pending_cpus++; cpu_exit(other_cpu); @@ -234,7 +232,7 @@ void fork_start(void) void fork_end(int child) { if (child) { - gdbserver_fork(thread_env); + gdbserver_fork((CPUArchState *)thread_cpu->env_ptr); } } @@ -1304,11 +1302,12 @@ int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val) #define EXCP_DUMP(env, fmt, ...) \ do { \ + CPUState *cs = ENV_GET_CPU(env); \ fprintf(stderr, fmt , ## __VA_ARGS__); \ - cpu_dump_state(ENV_GET_CPU(env), stderr, fprintf, 0); \ + cpu_dump_state(cs, stderr, fprintf, 0); \ qemu_log(fmt, ## __VA_ARGS__); \ if (qemu_log_enabled()) { \ - log_cpu_state(env, 0); \ + log_cpu_state(cs, 0); \ } \ } while (0) @@ -3152,7 +3151,7 @@ void cpu_loop(CPUS390XState *env) #endif /* TARGET_S390X */ -THREAD CPUArchState *thread_env; +THREAD CPUState *thread_cpu; void task_settid(TaskState *ts) { @@ -3642,7 +3641,7 @@ int main(int argc, char **argv, char **envp) cpu_reset(ENV_GET_CPU(env)); #endif - thread_env = env; + thread_cpu = ENV_GET_CPU(env); if (getenv("QEMU_STRACE")) { do_strace = 1; diff --git a/linux-user/microblaze/target_cpu.h b/linux-user/microblaze/target_cpu.h new file mode 100644 index 000000000..c6386ea9e --- /dev/null +++ b/linux-user/microblaze/target_cpu.h @@ -0,0 +1,35 @@ +/* + * MicroBlaze specific CPU ABI and functions for linux-user + * + * Copyright (c) 2009 Edgar E. Iglesias + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 Lesser General Public + * License along with this library; if not, see . + */ +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUMBState *env, target_ulong newsp) +{ + if (newsp) { + env->regs[R_SP] = newsp; + } + env->regs[3] = 0; +} + +static inline void cpu_set_tls(CPUMBState *env, target_ulong newtls) +{ + env->regs[21] = newtls; +} + +#endif diff --git a/linux-user/mips/target_cpu.h b/linux-user/mips/target_cpu.h new file mode 100644 index 000000000..ba8e9eb1f --- /dev/null +++ b/linux-user/mips/target_cpu.h @@ -0,0 +1,36 @@ +/* + * MIPS specific CPU ABI and functions for linux-user + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUMIPSState *env, target_ulong newsp) +{ + if (newsp) { + env->active_tc.gpr[29] = newsp; + } + env->active_tc.gpr[7] = 0; + env->active_tc.gpr[2] = 0; +} + +static inline void cpu_set_tls(CPUMIPSState *env, target_ulong newtls) +{ + env->tls_value = newtls; +} + +#endif diff --git a/linux-user/mips64/target_cpu.h b/linux-user/mips64/target_cpu.h new file mode 100644 index 000000000..fa36407c6 --- /dev/null +++ b/linux-user/mips64/target_cpu.h @@ -0,0 +1 @@ +#include "../mips/target_cpu.h" diff --git a/linux-user/mmap.c b/linux-user/mmap.c index b412e3fe0..de2219768 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -483,6 +483,10 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, if (!(flags & MAP_ANONYMOUS)) { p = mmap(g2h(start), len, prot, flags | MAP_FIXED, fd, host_offset); + if (p == MAP_FAILED) { + munmap(g2h(start), host_len); + goto fail; + } host_start += offset - host_offset; } start = h2g(host_start); diff --git a/linux-user/openrisc/target_cpu.h b/linux-user/openrisc/target_cpu.h new file mode 100644 index 000000000..501fb8116 --- /dev/null +++ b/linux-user/openrisc/target_cpu.h @@ -0,0 +1,33 @@ +/* + * OpenRISC specific CPU ABI and functions for linux-user + * + * Copyright (c) 2011-2012 Jia Liu + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUOpenRISCState *env, target_ulong newsp) +{ + if (newsp) { + env->gpr[1] = newsp; + } + env->gpr[2] = 0; +} + +/* TODO: need to implement cpu_set_tls() */ + +#endif diff --git a/linux-user/ppc/target_cpu.h b/linux-user/ppc/target_cpu.h new file mode 100644 index 000000000..9cc0c3ba9 --- /dev/null +++ b/linux-user/ppc/target_cpu.h @@ -0,0 +1,41 @@ +/* + * PowerPC specific CPU ABI and functions for linux-user + * + * Copyright (c) 2003-2007 Jocelyn Mayer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp) +{ + if (newsp) { + env->gpr[1] = newsp; + } + env->gpr[3] = 0; +} + +static inline void cpu_set_tls(CPUPPCState *env, target_ulong newtls) +{ +#if defined(TARGET_PPC64) + /* The kernel checks TIF_32BIT here; we don't support loading 32-bit + binaries on PPC64 yet. */ + env->gpr[13] = newtls; +#else + env->gpr[2] = newtls; +#endif +} + +#endif diff --git a/linux-user/qemu.h b/linux-user/qemu.h index b10e9572a..6569608b6 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -16,6 +16,7 @@ #include "exec/user/thunk.h" #include "syscall_defs.h" #include "syscall.h" +#include "target_cpu.h" #include "target_signal.h" #include "exec/gdbstub.h" #include "qemu/queue.h" @@ -197,7 +198,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, abi_long arg5, abi_long arg6, abi_long arg7, abi_long arg8); void gemu_log(const char *fmt, ...) GCC_FMT_ATTR(1, 2); -extern THREAD CPUArchState *thread_env; +extern THREAD CPUState *thread_cpu; void cpu_loop(CPUArchState *env); char *target_strerror(int err); int get_osversion(void); diff --git a/linux-user/s390x/target_cpu.h b/linux-user/s390x/target_cpu.h new file mode 100644 index 000000000..f10abe8e5 --- /dev/null +++ b/linux-user/s390x/target_cpu.h @@ -0,0 +1,39 @@ +/* + * S/390 specific CPU ABI and functions for linux-user + * + * Copyright (c) 2009 Ulrich Hecht + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * Contributions after 2012-10-29 are licensed under the terms of the + * GNU GPL, version 2 or (at your option) any later version. + * + * You should have received a copy of the GNU (Lesser) General Public + * License along with this library; if not, see . + */ +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUS390XState *env, target_ulong newsp) +{ + if (newsp) { + env->regs[15] = newsp; + } + env->regs[2] = 0; +} + +static inline void cpu_set_tls(CPUS390XState *env, target_ulong newtls) +{ + env->aregs[0] = newtls >> 32; + env->aregs[1] = newtls & 0xffffffffULL; +} + +#endif diff --git a/linux-user/sh4/target_cpu.h b/linux-user/sh4/target_cpu.h new file mode 100644 index 000000000..141856f84 --- /dev/null +++ b/linux-user/sh4/target_cpu.h @@ -0,0 +1,35 @@ +/* + * SH4 specific CPU ABI and functions for linux-user + * + * Copyright (c) 2005 Samuel Tardieu + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUSH4State *env, target_ulong newsp) +{ + if (newsp) { + env->gregs[15] = newsp; + } + env->gregs[0] = 0; +} + +static inline void cpu_set_tls(CPUSH4State *env, target_ulong newtls) +{ + env->gbr = newtls; +} + +#endif diff --git a/linux-user/signal.c b/linux-user/signal.c index c4e20dc8b..d0727becc 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -102,14 +102,14 @@ static inline int sas_ss_flags(unsigned long sp) int host_to_target_signal(int sig) { - if (sig >= _NSIG) + if (sig < 0 || sig >= _NSIG) return sig; return host_to_target_signal_table[sig]; } int target_to_host_signal(int sig) { - if (sig >= _NSIG) + if (sig < 0 || sig >= _NSIG) return sig; return target_to_host_signal_table[sig]; } @@ -388,17 +388,18 @@ static inline void free_sigqueue(CPUArchState *env, struct sigqueue *q) /* abort execution with signal */ static void QEMU_NORETURN force_sig(int target_sig) { - TaskState *ts = (TaskState *)thread_env->opaque; + CPUArchState *env = thread_cpu->env_ptr; + TaskState *ts = (TaskState *)env->opaque; int host_sig, core_dumped = 0; struct sigaction act; host_sig = target_to_host_signal(target_sig); - gdb_signalled(thread_env, target_sig); + gdb_signalled(env, target_sig); /* dump core if supported by target binary format */ if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) { stop_all_tasks(); core_dumped = - ((*ts->bprm->core_dump)(target_sig, thread_env) == 0); + ((*ts->bprm->core_dump)(target_sig, env) == 0); } if (core_dumped) { /* we already dumped the core of target process, we don't want @@ -503,6 +504,7 @@ int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info) static void host_signal_handler(int host_signum, siginfo_t *info, void *puc) { + CPUArchState *env = thread_cpu->env_ptr; int sig; target_siginfo_t tinfo; @@ -522,9 +524,9 @@ static void host_signal_handler(int host_signum, siginfo_t *info, fprintf(stderr, "qemu: got signal %d\n", sig); #endif host_to_target_siginfo_noswap(&tinfo, info); - if (queue_signal(thread_env, sig, &tinfo) == 1) { + if (queue_signal(env, sig, &tinfo) == 1) { /* interrupt the virtual CPU as soon as possible */ - cpu_exit(ENV_GET_CPU(thread_env)); + cpu_exit(thread_cpu); } } diff --git a/linux-user/socket.h b/linux-user/socket.h index 339cae5a1..ae1795990 100644 --- a/linux-user/socket.h +++ b/linux-user/socket.h @@ -1,91 +1,104 @@ #if defined(TARGET_MIPS) - // MIPS special values for constants - - /* - * For setsockopt(2) - * - * This defines are ABI conformant as far as Linux supports these ... - */ - #define TARGET_SOL_SOCKET 0xffff - - #define TARGET_SO_DEBUG 0x0001 /* Record debugging information. */ - #define TARGET_SO_REUSEADDR 0x0004 /* Allow reuse of local addresses. */ - #define TARGET_SO_KEEPALIVE 0x0008 /* Keep connections alive and send - SIGPIPE when they die. */ - #define TARGET_SO_DONTROUTE 0x0010 /* Don't do local routing. */ - #define TARGET_SO_BROADCAST 0x0020 /* Allow transmission of - broadcast messages. */ - #define TARGET_SO_LINGER 0x0080 /* Block on close of a reliable - socket to transmit pending data. */ - #define TARGET_SO_OOBINLINE 0x0100 /* Receive out-of-band data in-band. */ - #if 0 - To add: #define TARGET_SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */ - #endif - - #define TARGET_SO_TYPE 0x1008 /* Compatible name for SO_STYLE. */ - #define TARGET_SO_STYLE SO_TYPE /* Synonym */ - #define TARGET_SO_ERROR 0x1007 /* get error status and clear */ - #define TARGET_SO_SNDBUF 0x1001 /* Send buffer size. */ - #define TARGET_SO_RCVBUF 0x1002 /* Receive buffer. */ - #define TARGET_SO_SNDLOWAT 0x1003 /* send low-water mark */ - #define TARGET_SO_RCVLOWAT 0x1004 /* receive low-water mark */ - #define TARGET_SO_SNDTIMEO 0x1005 /* send timeout */ - #define TARGET_SO_RCVTIMEO 0x1006 /* receive timeout */ - #define TARGET_SO_ACCEPTCONN 0x1009 - - /* linux-specific, might as well be the same as on i386 */ - #define TARGET_SO_NO_CHECK 11 - #define TARGET_SO_PRIORITY 12 - #define TARGET_SO_BSDCOMPAT 14 - - #define TARGET_SO_PASSCRED 17 - #define TARGET_SO_PEERCRED 18 - - /* Security levels - as per NRL IPv6 - don't actually do anything */ - #define TARGET_SO_SECURITY_AUTHENTICATION 22 - #define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT 23 - #define TARGET_SO_SECURITY_ENCRYPTION_NETWORK 24 - - #define TARGET_SO_BINDTODEVICE 25 - - /* Socket filtering */ - #define TARGET_SO_ATTACH_FILTER 26 - #define TARGET_SO_DETACH_FILTER 27 - - #define TARGET_SO_PEERNAME 28 - #define TARGET_SO_TIMESTAMP 29 - #define SCM_TIMESTAMP SO_TIMESTAMP - - #define TARGET_SO_PEERSEC 30 - #define TARGET_SO_SNDBUFFORCE 31 - #define TARGET_SO_RCVBUFFORCE 33 - - /** sock_type - Socket types - * - * Please notice that for binary compat reasons MIPS has to - * override the enum sock_type in include/linux/net.h, so - * we define ARCH_HAS_SOCKET_TYPES here. - * - * @SOCK_DGRAM - datagram (conn.less) socket - * @SOCK_STREAM - stream (connection) socket - * @SOCK_RAW - raw socket - * @SOCK_RDM - reliably-delivered message - * @SOCK_SEQPACKET - sequential packet socket - * @SOCK_PACKET - linux specific way of getting packets at the dev level. - * For writing rarp and other similar things on the user level. - */ - enum sock_type { - TARGET_SOCK_DGRAM = 1, - TARGET_SOCK_STREAM = 2, - TARGET_SOCK_RAW = 3, - TARGET_SOCK_RDM = 4, - TARGET_SOCK_SEQPACKET = 5, - TARGET_SOCK_DCCP = 6, - TARGET_SOCK_PACKET = 10, - }; - - #define TARGET_SOCK_MAX (SOCK_PACKET + 1) + /* MIPS special values for constants */ + + /* + * For setsockopt(2) + * + * This defines are ABI conformant as far as Linux supports these ... + */ + #define TARGET_SOL_SOCKET 0xffff + + #define TARGET_SO_DEBUG 0x0001 /* Record debugging information. */ + #define TARGET_SO_REUSEADDR 0x0004 /* Allow reuse of local addresses. */ + #define TARGET_SO_KEEPALIVE 0x0008 /* Keep connections alive and send + SIGPIPE when they die. */ + #define TARGET_SO_DONTROUTE 0x0010 /* Don't do local routing. */ + #define TARGET_SO_BROADCAST 0x0020 /* Allow transmission of + broadcast messages. */ + #define TARGET_SO_LINGER 0x0080 /* Block on close of a reliable + * socket to transmit pending data. + */ + #define TARGET_SO_OOBINLINE 0x0100 /* Receive out-of-band data in-band. + */ + #if 0 + /* To add: Allow local address and port reuse. */ + #define TARGET_SO_REUSEPORT 0x0200 + #endif + + #define TARGET_SO_TYPE 0x1008 /* Compatible name for SO_STYLE. */ + #define TARGET_SO_STYLE SO_TYPE /* Synonym */ + #define TARGET_SO_ERROR 0x1007 /* get error status and clear */ + #define TARGET_SO_SNDBUF 0x1001 /* Send buffer size. */ + #define TARGET_SO_RCVBUF 0x1002 /* Receive buffer. */ + #define TARGET_SO_SNDLOWAT 0x1003 /* send low-water mark */ + #define TARGET_SO_RCVLOWAT 0x1004 /* receive low-water mark */ + #define TARGET_SO_SNDTIMEO 0x1005 /* send timeout */ + #define TARGET_SO_RCVTIMEO 0x1006 /* receive timeout */ + #define TARGET_SO_ACCEPTCONN 0x1009 + + /* linux-specific, might as well be the same as on i386 */ + #define TARGET_SO_NO_CHECK 11 + #define TARGET_SO_PRIORITY 12 + #define TARGET_SO_BSDCOMPAT 14 + + #define TARGET_SO_PASSCRED 17 + #define TARGET_SO_PEERCRED 18 + + /* Security levels - as per NRL IPv6 - don't actually do anything */ + #define TARGET_SO_SECURITY_AUTHENTICATION 22 + #define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT 23 + #define TARGET_SO_SECURITY_ENCRYPTION_NETWORK 24 + + #define TARGET_SO_BINDTODEVICE 25 + + /* Socket filtering */ + #define TARGET_SO_ATTACH_FILTER 26 + #define TARGET_SO_DETACH_FILTER 27 + + #define TARGET_SO_PEERNAME 28 + #define TARGET_SO_TIMESTAMP 29 + #define SCM_TIMESTAMP SO_TIMESTAMP + + #define TARGET_SO_PEERSEC 30 + #define TARGET_SO_SNDBUFFORCE 31 + #define TARGET_SO_RCVBUFFORCE 33 + + /** sock_type - Socket types + * + * Please notice that for binary compat reasons MIPS has to + * override the enum sock_type in include/linux/net.h, so + * we define ARCH_HAS_SOCKET_TYPES here. + * + * @SOCK_DGRAM - datagram (conn.less) socket + * @SOCK_STREAM - stream (connection) socket + * @SOCK_RAW - raw socket + * @SOCK_RDM - reliably-delivered message + * @SOCK_SEQPACKET - sequential packet socket + * @SOCK_DCCP - Datagram Congestion Control Protocol socket + * @SOCK_PACKET - linux specific way of getting packets at the dev level. + * For writing rarp and other similar things on the user + * level. + * @SOCK_CLOEXEC - sets the close-on-exec (FD_CLOEXEC) flag. + * @SOCK_NONBLOCK - sets the O_NONBLOCK file status flag. + */ + + #define ARCH_HAS_SOCKET_TYPES 1 + + enum sock_type { + TARGET_SOCK_DGRAM = 1, + TARGET_SOCK_STREAM = 2, + TARGET_SOCK_RAW = 3, + TARGET_SOCK_RDM = 4, + TARGET_SOCK_SEQPACKET = 5, + TARGET_SOCK_DCCP = 6, + TARGET_SOCK_PACKET = 10, + TARGET_SOCK_CLOEXEC = 02000000, + TARGET_SOCK_NONBLOCK = 0200, + }; + + #define TARGET_SOCK_MAX (TARGET_SOCK_PACKET + 1) + #define TARGET_SOCK_TYPE_MASK 0xf /* Covers up to TARGET_SOCK_MAX-1. */ #elif defined(TARGET_ALPHA) @@ -156,61 +169,167 @@ /* Instruct lower device to use last 4-bytes of skb data as FCS */ #define TARGET_SO_NOFCS 43 + /** sock_type - Socket types + * + * Please notice that for binary compat reasons ALPHA has to + * override the enum sock_type in include/linux/net.h, so + * we define ARCH_HAS_SOCKET_TYPES here. + * + * @SOCK_DGRAM - datagram (conn.less) socket + * @SOCK_STREAM - stream (connection) socket + * @SOCK_RAW - raw socket + * @SOCK_RDM - reliably-delivered message + * @SOCK_SEQPACKET - sequential packet socket + * @SOCK_DCCP - Datagram Congestion Control Protocol socket + * @SOCK_PACKET - linux specific way of getting packets at the dev level. + * For writing rarp and other similar things on the user + * level. + * @SOCK_CLOEXEC - sets the close-on-exec (FD_CLOEXEC) flag. + * @SOCK_NONBLOCK - sets the O_NONBLOCK file status flag. + */ + + #define ARCH_HAS_SOCKET_TYPES 1 + + enum sock_type { + TARGET_SOCK_STREAM = 1, + TARGET_SOCK_DGRAM = 2, + TARGET_SOCK_RAW = 3, + TARGET_SOCK_RDM = 4, + TARGET_SOCK_SEQPACKET = 5, + TARGET_SOCK_DCCP = 6, + TARGET_SOCK_PACKET = 10, + TARGET_SOCK_CLOEXEC = 010000000, + TARGET_SOCK_NONBLOCK = 010000000000, + }; + + #define TARGET_SOCK_MAX (TARGET_SOCK_PACKET + 1) + #define TARGET_SOCK_TYPE_MASK 0xf /* Covers up to TARGET_SOCK_MAX-1. */ #else - /* For setsockopt(2) */ - #define TARGET_SOL_SOCKET 1 - - #define TARGET_SO_DEBUG 1 - #define TARGET_SO_REUSEADDR 2 - #define TARGET_SO_TYPE 3 - #define TARGET_SO_ERROR 4 - #define TARGET_SO_DONTROUTE 5 - #define TARGET_SO_BROADCAST 6 - #define TARGET_SO_SNDBUF 7 - #define TARGET_SO_RCVBUF 8 - #define TARGET_SO_SNDBUFFORCE 32 - #define TARGET_SO_RCVBUFFORCE 33 - #define TARGET_SO_KEEPALIVE 9 - #define TARGET_SO_OOBINLINE 10 - #define TARGET_SO_NO_CHECK 11 - #define TARGET_SO_PRIORITY 12 - #define TARGET_SO_LINGER 13 - #define TARGET_SO_BSDCOMPAT 14 - /* To add :#define TARGET_SO_REUSEPORT 15 */ +#if defined(TARGET_SPARC) + /** sock_type - Socket types + * + * Please notice that for binary compat reasons SPARC has to + * override the enum sock_type in include/linux/net.h, so + * we define ARCH_HAS_SOCKET_TYPES here. + * + * @SOCK_DGRAM - datagram (conn.less) socket + * @SOCK_STREAM - stream (connection) socket + * @SOCK_RAW - raw socket + * @SOCK_RDM - reliably-delivered message + * @SOCK_SEQPACKET - sequential packet socket + * @SOCK_DCCP - Datagram Congestion Control Protocol socket + * @SOCK_PACKET - linux specific way of getting packets at the dev level. + * For writing rarp and other similar things on the user + * level. + * @SOCK_CLOEXEC - sets the close-on-exec (FD_CLOEXEC) flag. + * @SOCK_NONBLOCK - sets the O_NONBLOCK file status flag. + */ + + #define ARCH_HAS_SOCKET_TYPES 1 + + enum sock_type { + TARGET_SOCK_STREAM = 1, + TARGET_SOCK_DGRAM = 2, + TARGET_SOCK_RAW = 3, + TARGET_SOCK_RDM = 4, + TARGET_SOCK_SEQPACKET = 5, + TARGET_SOCK_DCCP = 6, + TARGET_SOCK_PACKET = 10, + TARGET_SOCK_CLOEXEC = 020000000, + TARGET_SOCK_NONBLOCK = 040000, + }; + + #define TARGET_SOCK_MAX (TARGET_SOCK_PACKET + 1) + #define TARGET_SOCK_TYPE_MASK 0xf /* Covers up to TARGET_SOCK_MAX-1. */ +#endif + + /* For setsockopt(2) */ + #define TARGET_SOL_SOCKET 1 + + #define TARGET_SO_DEBUG 1 + #define TARGET_SO_REUSEADDR 2 + #define TARGET_SO_TYPE 3 + #define TARGET_SO_ERROR 4 + #define TARGET_SO_DONTROUTE 5 + #define TARGET_SO_BROADCAST 6 + #define TARGET_SO_SNDBUF 7 + #define TARGET_SO_RCVBUF 8 + #define TARGET_SO_SNDBUFFORCE 32 + #define TARGET_SO_RCVBUFFORCE 33 + #define TARGET_SO_KEEPALIVE 9 + #define TARGET_SO_OOBINLINE 10 + #define TARGET_SO_NO_CHECK 11 + #define TARGET_SO_PRIORITY 12 + #define TARGET_SO_LINGER 13 + #define TARGET_SO_BSDCOMPAT 14 + /* To add :#define TARGET_SO_REUSEPORT 15 */ #if defined(TARGET_PPC) - #define TARGET_SO_RCVLOWAT 16 - #define TARGET_SO_SNDLOWAT 17 - #define TARGET_SO_RCVTIMEO 18 - #define TARGET_SO_SNDTIMEO 19 - #define TARGET_SO_PASSCRED 20 - #define TARGET_SO_PEERCRED 21 + #define TARGET_SO_RCVLOWAT 16 + #define TARGET_SO_SNDLOWAT 17 + #define TARGET_SO_RCVTIMEO 18 + #define TARGET_SO_SNDTIMEO 19 + #define TARGET_SO_PASSCRED 20 + #define TARGET_SO_PEERCRED 21 #else - #define TARGET_SO_PASSCRED 16 - #define TARGET_SO_PEERCRED 17 - #define TARGET_SO_RCVLOWAT 18 - #define TARGET_SO_SNDLOWAT 19 - #define TARGET_SO_RCVTIMEO 20 - #define TARGET_SO_SNDTIMEO 21 + #define TARGET_SO_PASSCRED 16 + #define TARGET_SO_PEERCRED 17 + #define TARGET_SO_RCVLOWAT 18 + #define TARGET_SO_SNDLOWAT 19 + #define TARGET_SO_RCVTIMEO 20 + #define TARGET_SO_SNDTIMEO 21 #endif - /* Security levels - as per NRL IPv6 - don't actually do anything */ - #define TARGET_SO_SECURITY_AUTHENTICATION 22 - #define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT 23 - #define TARGET_SO_SECURITY_ENCRYPTION_NETWORK 24 + /* Security levels - as per NRL IPv6 - don't actually do anything */ + #define TARGET_SO_SECURITY_AUTHENTICATION 22 + #define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT 23 + #define TARGET_SO_SECURITY_ENCRYPTION_NETWORK 24 - #define TARGET_SO_BINDTODEVICE 25 + #define TARGET_SO_BINDTODEVICE 25 - /* Socket filtering */ - #define TARGET_SO_ATTACH_FILTER 26 - #define TARGET_SO_DETACH_FILTER 27 + /* Socket filtering */ + #define TARGET_SO_ATTACH_FILTER 26 + #define TARGET_SO_DETACH_FILTER 27 + + #define TARGET_SO_PEERNAME 28 + #define TARGET_SO_TIMESTAMP 29 + #define TARGET_SCM_TIMESTAMP TARGET_SO_TIMESTAMP - #define TARGET_SO_PEERNAME 28 - #define TARGET_SO_TIMESTAMP 29 - #define TARGET_SCM_TIMESTAMP TARGET_SO_TIMESTAMP + #define TARGET_SO_ACCEPTCONN 30 - #define TARGET_SO_ACCEPTCONN 30 + #define TARGET_SO_PEERSEC 31 + +#endif - #define TARGET_SO_PEERSEC 31 +#ifndef ARCH_HAS_SOCKET_TYPES + /** sock_type - Socket types - default values + * + * + * @SOCK_STREAM - stream (connection) socket + * @SOCK_DGRAM - datagram (conn.less) socket + * @SOCK_RAW - raw socket + * @SOCK_RDM - reliably-delivered message + * @SOCK_SEQPACKET - sequential packet socket + * @SOCK_DCCP - Datagram Congestion Control Protocol socket + * @SOCK_PACKET - linux specific way of getting packets at the dev level. + * For writing rarp and other similar things on the user + * level. + * @SOCK_CLOEXEC - sets the close-on-exec (FD_CLOEXEC) flag. + * @SOCK_NONBLOCK - sets the O_NONBLOCK file status flag. + */ + enum sock_type { + TARGET_SOCK_STREAM = 1, + TARGET_SOCK_DGRAM = 2, + TARGET_SOCK_RAW = 3, + TARGET_SOCK_RDM = 4, + TARGET_SOCK_SEQPACKET = 5, + TARGET_SOCK_DCCP = 6, + TARGET_SOCK_PACKET = 10, + TARGET_SOCK_CLOEXEC = 02000000, + TARGET_SOCK_NONBLOCK = 04000, + }; + + #define TARGET_SOCK_MAX (TARGET_SOCK_PACKET + 1) + #define TARGET_SOCK_TYPE_MASK 0xf /* Covers up to TARGET_SOCK_MAX-1. */ #endif diff --git a/linux-user/sparc/target_cpu.h b/linux-user/sparc/target_cpu.h new file mode 100644 index 000000000..5a620a2bb --- /dev/null +++ b/linux-user/sparc/target_cpu.h @@ -0,0 +1,36 @@ +/* + * SPARC specific CPU ABI and functions for linux-user + * + * Copyright (C) 2003 Thomas M. Ogrisegg + * Copyright (C) 2003-2005 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUSPARCState *env, target_ulong newsp) +{ + if (newsp) { + env->regwptr[22] = newsp; + } + env->regwptr[0] = 0; + /* FIXME: Do we also need to clear CF? */ + /* XXXXX */ + printf("HELPME: %s:%d\n", __FILE__, __LINE__); +} + +/* TODO: need to implement cpu_set_tls() */ + +#endif diff --git a/linux-user/sparc64/target_cpu.h b/linux-user/sparc64/target_cpu.h new file mode 100644 index 000000000..b22263d2d --- /dev/null +++ b/linux-user/sparc64/target_cpu.h @@ -0,0 +1 @@ +#include "../sparc/target_cpu.h" diff --git a/linux-user/syscall.c b/linux-user/syscall.c index cdd0c28ff..00a0390ea 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -105,6 +105,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base, #include #include #include +#include #include "linux_loop.h" #include "cpu-uname.h" @@ -338,6 +339,7 @@ static int sys_openat(int dirfd, const char *pathname, int flags, mode_t mode) } #endif +#ifdef TARGET_NR_utimensat #ifdef CONFIG_UTIMENSAT static int sys_utimensat(int dirfd, const char *pathname, const struct timespec times[2], int flags) @@ -347,12 +349,19 @@ static int sys_utimensat(int dirfd, const char *pathname, else return utimensat(dirfd, pathname, times, flags); } -#else -#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat) +#elif defined(__NR_utimensat) +#define __NR_sys_utimensat __NR_utimensat _syscall4(int,sys_utimensat,int,dirfd,const char *,pathname, const struct timespec *,tsp,int,flags) +#else +static int sys_utimensat(int dirfd, const char *pathname, + const struct timespec times[2], int flags) +{ + errno = ENOSYS; + return -1; +} #endif -#endif /* CONFIG_UTIMENSAT */ +#endif /* TARGET_NR_utimensat */ #ifdef CONFIG_INOTIFY #include @@ -1696,31 +1705,36 @@ static void unlock_iovec(struct iovec *vec, abi_ulong target_addr, free(vec); } -/* do_socket() Must return target values and target errnos. */ -static abi_long do_socket(int domain, int type, int protocol) +static inline void target_to_host_sock_type(int *type) { -#if defined(TARGET_MIPS) - switch(type) { + int host_type = 0; + int target_type = *type; + + switch (target_type & TARGET_SOCK_TYPE_MASK) { case TARGET_SOCK_DGRAM: - type = SOCK_DGRAM; + host_type = SOCK_DGRAM; break; case TARGET_SOCK_STREAM: - type = SOCK_STREAM; - break; - case TARGET_SOCK_RAW: - type = SOCK_RAW; + host_type = SOCK_STREAM; break; - case TARGET_SOCK_RDM: - type = SOCK_RDM; - break; - case TARGET_SOCK_SEQPACKET: - type = SOCK_SEQPACKET; - break; - case TARGET_SOCK_PACKET: - type = SOCK_PACKET; + default: + host_type = target_type & TARGET_SOCK_TYPE_MASK; break; } -#endif + if (target_type & TARGET_SOCK_CLOEXEC) { + host_type |= SOCK_CLOEXEC; + } + if (target_type & TARGET_SOCK_NONBLOCK) { + host_type |= SOCK_NONBLOCK; + } + *type = host_type; +} + +/* do_socket() Must return target values and target errnos. */ +static abi_long do_socket(int domain, int type, int protocol) +{ + target_to_host_sock_type(&type); + if (domain == PF_NETLINK) return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */ return get_errno(socket(domain, type, protocol)); @@ -1953,6 +1967,8 @@ static abi_long do_socketpair(int domain, int type, int protocol, int tab[2]; abi_long ret; + target_to_host_sock_type(&type); + ret = get_errno(socketpair(domain, type, protocol, tab)); if (!is_error(ret)) { if (put_user_s32(tab[0], target_tab_addr) @@ -3551,6 +3567,69 @@ out: return ret; } +static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp, + int fd, abi_long cmd, abi_long arg) +{ + const argtype *arg_type = ie->arg_type; + const StructEntry *se; + const argtype *field_types; + const int *dst_offsets, *src_offsets; + int target_size; + void *argptr; + abi_ulong *target_rt_dev_ptr; + unsigned long *host_rt_dev_ptr; + abi_long ret; + int i; + + assert(ie->access == IOC_W); + assert(*arg_type == TYPE_PTR); + arg_type++; + assert(*arg_type == TYPE_STRUCT); + target_size = thunk_type_size(arg_type, 0); + argptr = lock_user(VERIFY_READ, arg, target_size, 1); + if (!argptr) { + return -TARGET_EFAULT; + } + arg_type++; + assert(*arg_type == (int)STRUCT_rtentry); + se = struct_entries + *arg_type++; + assert(se->convert[0] == NULL); + /* convert struct here to be able to catch rt_dev string */ + field_types = se->field_types; + dst_offsets = se->field_offsets[THUNK_HOST]; + src_offsets = se->field_offsets[THUNK_TARGET]; + for (i = 0; i < se->nb_fields; i++) { + if (dst_offsets[i] == offsetof(struct rtentry, rt_dev)) { + assert(*field_types == TYPE_PTRVOID); + target_rt_dev_ptr = (abi_ulong *)(argptr + src_offsets[i]); + host_rt_dev_ptr = (unsigned long *)(buf_temp + dst_offsets[i]); + if (*target_rt_dev_ptr != 0) { + *host_rt_dev_ptr = (unsigned long)lock_user_string( + tswapal(*target_rt_dev_ptr)); + if (!*host_rt_dev_ptr) { + unlock_user(argptr, arg, 0); + return -TARGET_EFAULT; + } + } else { + *host_rt_dev_ptr = 0; + } + field_types++; + continue; + } + field_types = thunk_convert(buf_temp + dst_offsets[i], + argptr + src_offsets[i], + field_types, THUNK_HOST); + } + unlock_user(argptr, arg, 0); + + ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); + if (*host_rt_dev_ptr != 0) { + unlock_user((void *)*host_rt_dev_ptr, + *target_rt_dev_ptr, 0); + } + return ret; +} + static IOCTLEntry ioctl_entries[] = { #define IOCTL(cmd, access, ...) \ { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } }, @@ -4171,8 +4250,8 @@ static void *clone_func(void *arg) env = info->env; cpu = ENV_GET_CPU(env); - thread_env = env; - ts = (TaskState *)thread_env->opaque; + thread_cpu = cpu; + ts = (TaskState *)env->opaque; info->tid = gettid(); cpu->host_tid = info->tid; task_settid(ts); @@ -4973,6 +5052,30 @@ static int open_self_auxv(void *cpu_env, int fd) return 0; } +static int is_proc_myself(const char *filename, const char *entry) +{ + if (!strncmp(filename, "/proc/", strlen("/proc/"))) { + filename += strlen("/proc/"); + if (!strncmp(filename, "self/", strlen("self/"))) { + filename += strlen("self/"); + } else if (*filename >= '1' && *filename <= '9') { + char myself[80]; + snprintf(myself, sizeof(myself), "%d/", getpid()); + if (!strncmp(filename, myself, strlen(myself))) { + filename += strlen(myself); + } else { + return 0; + } + } else { + return 0; + } + if (!strcmp(filename, entry)) { + return 1; + } + } + return 0; +} + static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode) { struct fake_open { @@ -4981,15 +5084,14 @@ static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode) }; const struct fake_open *fake_open; static const struct fake_open fakes[] = { - { "/proc/self/maps", open_self_maps }, - { "/proc/self/stat", open_self_stat }, - { "/proc/self/auxv", open_self_auxv }, + { "maps", open_self_maps }, + { "stat", open_self_stat }, + { "auxv", open_self_auxv }, { NULL, NULL } }; for (fake_open = fakes; fake_open->filename; fake_open++) { - if (!strncmp(pathname, fake_open->filename, - strlen(fake_open->filename))) { + if (is_proc_myself(pathname, fake_open->filename)) { break; } } @@ -5030,6 +5132,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, abi_long arg5, abi_long arg6, abi_long arg7, abi_long arg8) { +#ifdef CONFIG_USE_NPTL + CPUState *cpu = ENV_GET_CPU(cpu_env); +#endif abi_long ret; struct stat st; struct statfs stfs; @@ -5044,42 +5149,43 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, switch(num) { case TARGET_NR_exit: #ifdef CONFIG_USE_NPTL - /* In old applications this may be used to implement _exit(2). - However in threaded applictions it is used for thread termination, - and _exit_group is used for application termination. - Do thread termination if we have more then one thread. */ - /* FIXME: This probably breaks if a signal arrives. We should probably - be disabling signals. */ - if (first_cpu->next_cpu) { - TaskState *ts; - CPUArchState **lastp; - CPUArchState *p; - - cpu_list_lock(); - lastp = &first_cpu; - p = first_cpu; - while (p && p != (CPUArchState *)cpu_env) { - lastp = &p->next_cpu; - p = p->next_cpu; - } - /* If we didn't find the CPU for this thread then something is - horribly wrong. */ - if (!p) - abort(); - /* Remove the CPU from the list. */ - *lastp = p->next_cpu; - cpu_list_unlock(); - ts = ((CPUArchState *)cpu_env)->opaque; - if (ts->child_tidptr) { - put_user_u32(0, ts->child_tidptr); - sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX, - NULL, NULL, 0); - } - thread_env = NULL; - object_unref(OBJECT(ENV_GET_CPU(cpu_env))); - g_free(ts); - pthread_exit(NULL); - } + /* In old applications this may be used to implement _exit(2). + However in threaded applictions it is used for thread termination, + and _exit_group is used for application termination. + Do thread termination if we have more then one thread. */ + /* FIXME: This probably breaks if a signal arrives. We should probably + be disabling signals. */ + if (first_cpu->next_cpu) { + TaskState *ts; + CPUState **lastp; + CPUState *p; + + cpu_list_lock(); + lastp = &first_cpu; + p = first_cpu; + while (p && p != cpu) { + lastp = &p->next_cpu; + p = p->next_cpu; + } + /* If we didn't find the CPU for this thread then something is + horribly wrong. */ + if (!p) { + abort(); + } + /* Remove the CPU from the list. */ + *lastp = p->next_cpu; + cpu_list_unlock(); + ts = ((CPUArchState *)cpu_env)->opaque; + if (ts->child_tidptr) { + put_user_u32(0, ts->child_tidptr); + sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX, + NULL, NULL, 0); + } + thread_cpu = NULL; + object_unref(OBJECT(ENV_GET_CPU(cpu_env))); + g_free(ts); + pthread_exit(NULL); + } #endif #ifdef TARGET_GPROF _mcleanup(); @@ -6262,20 +6368,18 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif case TARGET_NR_readlink: { - void *p2, *temp; + void *p2; p = lock_user_string(arg1); p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0); - if (!p || !p2) + if (!p || !p2) { ret = -TARGET_EFAULT; - else { - if (strncmp((const char *)p, "/proc/self/exe", 14) == 0) { - char real[PATH_MAX]; - temp = realpath(exec_path,real); - ret = (temp==NULL) ? get_errno(-1) : strlen(real) ; - snprintf((char *)p2, arg3, "%s", real); - } - else - ret = get_errno(readlink(path(p), p2, arg3)); + } else if (is_proc_myself((const char *)p, "exe")) { + char real[PATH_MAX], *temp; + temp = realpath(exec_path, real); + ret = temp == NULL ? get_errno(-1) : strlen(real) ; + snprintf((char *)p2, arg3, "%s", real); + } else { + ret = get_errno(readlink(path(p), p2, arg3)); } unlock_user(p2, arg2, ret); unlock_user(p, arg1, 0); @@ -6287,10 +6391,16 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, void *p2; p = lock_user_string(arg2); p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0); - if (!p || !p2) - ret = -TARGET_EFAULT; - else + if (!p || !p2) { + ret = -TARGET_EFAULT; + } else if (is_proc_myself((const char *)p, "exe")) { + char real[PATH_MAX], *temp; + temp = realpath(exec_path, real); + ret = temp == NULL ? get_errno(-1) : strlen(real) ; + snprintf((char *)p2, arg4, "%s", real); + } else { ret = get_errno(readlinkat(arg1, path(p), p2, arg4)); + } unlock_user(p2, arg3, ret); unlock_user(p, arg2, 0); } @@ -8536,7 +8646,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, goto unimplemented_nowarn; #endif -#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat) +#if defined(TARGET_NR_utimensat) case TARGET_NR_utimensat: { struct timespec *tsp, ts[2]; diff --git a/linux-user/unicore32/target_cpu.h b/linux-user/unicore32/target_cpu.h new file mode 100644 index 000000000..fb7908719 --- /dev/null +++ b/linux-user/unicore32/target_cpu.h @@ -0,0 +1,27 @@ +/* + * UniCore32 specific CPU ABI and functions for linux-user + * + * Copyright (C) 2010-2012 Guan Xuetao + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation, or (at your option) any + * later version. See the COPYING file in the top-level directory. + */ +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUUniCore32State *env, target_ulong newsp) +{ + if (newsp) { + env->regs[29] = newsp; + } + env->regs[0] = 0; +} + +static inline void cpu_set_tls(CPUUniCore32State *env, target_ulong newtls) +{ + env->regs[16] = newtls; +} + +#endif diff --git a/linux-user/x86_64/target_cpu.h b/linux-user/x86_64/target_cpu.h new file mode 100644 index 000000000..9ec7cbb7a --- /dev/null +++ b/linux-user/x86_64/target_cpu.h @@ -0,0 +1 @@ +#include "../i386/target_cpu.h" diff --git a/memory.c b/memory.c index 757e9a559..c8f9a2bfb 100644 --- a/memory.c +++ b/memory.c @@ -17,6 +17,7 @@ #include "exec/address-spaces.h" #include "exec/ioport.h" #include "qemu/bitops.h" +#include "qom/object.h" #include "sysemu/kvm.h" #include @@ -28,12 +29,26 @@ static unsigned memory_region_transaction_depth; static bool memory_region_update_pending; static bool global_dirty_log = false; +/* flat_view_mutex is taken around reading as->current_map; the critical + * section is extremely short, so I'm using a single mutex for every AS. + * We could also RCU for the read-side. + * + * The BQL is taken around transaction commits, hence both locks are taken + * while writing to as->current_map (with the BQL taken outside). + */ +static QemuMutex flat_view_mutex; + static QTAILQ_HEAD(memory_listeners, MemoryListener) memory_listeners = QTAILQ_HEAD_INITIALIZER(memory_listeners); static QTAILQ_HEAD(, AddressSpace) address_spaces = QTAILQ_HEAD_INITIALIZER(address_spaces); +static void memory_init(void) +{ + qemu_mutex_init(&flat_view_mutex); +} + typedef struct AddrRange AddrRange; /* @@ -147,6 +162,7 @@ static bool memory_listener_match(MemoryListener *listener, } \ } while (0) +/* No need to ref/unref .mr, the FlatRange keeps it alive. */ #define MEMORY_LISTENER_UPDATE_REGION(fr, as, dir, callback) \ MEMORY_LISTENER_CALL(callback, dir, (&(MemoryRegionSection) { \ .mr = (fr)->mr, \ @@ -223,6 +239,7 @@ struct FlatRange { * order. */ struct FlatView { + unsigned ref; FlatRange *ranges; unsigned nr; unsigned nr_allocated; @@ -244,6 +261,7 @@ static bool flatrange_equal(FlatRange *a, FlatRange *b) static void flatview_init(FlatView *view) { + view->ref = 1; view->ranges = NULL; view->nr = 0; view->nr_allocated = 0; @@ -262,12 +280,31 @@ static void flatview_insert(FlatView *view, unsigned pos, FlatRange *range) memmove(view->ranges + pos + 1, view->ranges + pos, (view->nr - pos) * sizeof(FlatRange)); view->ranges[pos] = *range; + memory_region_ref(range->mr); ++view->nr; } static void flatview_destroy(FlatView *view) { + int i; + + for (i = 0; i < view->nr; i++) { + memory_region_unref(view->ranges[i].mr); + } g_free(view->ranges); + g_free(view); +} + +static void flatview_ref(FlatView *view) +{ + atomic_inc(&view->ref); +} + +static void flatview_unref(FlatView *view) +{ + if (atomic_fetch_dec(&view->ref) == 1) { + flatview_destroy(view); + } } static bool can_merge(FlatRange *r1, FlatRange *r2) @@ -401,94 +438,6 @@ static void access_with_adjusted_size(hwaddr addr, } } -static const MemoryRegionPortio *find_portio(MemoryRegion *mr, uint64_t offset, - unsigned width, bool write) -{ - const MemoryRegionPortio *mrp; - - for (mrp = mr->ops->old_portio; mrp->size; ++mrp) { - if (offset >= mrp->offset && offset < mrp->offset + mrp->len - && width == mrp->size - && (write ? (bool)mrp->write : (bool)mrp->read)) { - return mrp; - } - } - return NULL; -} - -static void memory_region_iorange_read(IORange *iorange, - uint64_t offset, - unsigned width, - uint64_t *data) -{ - MemoryRegionIORange *mrio - = container_of(iorange, MemoryRegionIORange, iorange); - MemoryRegion *mr = mrio->mr; - - offset += mrio->offset; - if (mr->ops->old_portio) { - const MemoryRegionPortio *mrp = find_portio(mr, offset - mrio->offset, - width, false); - - *data = ((uint64_t)1 << (width * 8)) - 1; - if (mrp) { - *data = mrp->read(mr->opaque, offset); - } else if (width == 2) { - mrp = find_portio(mr, offset - mrio->offset, 1, false); - assert(mrp); - *data = mrp->read(mr->opaque, offset) | - (mrp->read(mr->opaque, offset + 1) << 8); - } - return; - } - *data = 0; - access_with_adjusted_size(offset, data, width, - mr->ops->impl.min_access_size, - mr->ops->impl.max_access_size, - memory_region_read_accessor, mr); -} - -static void memory_region_iorange_write(IORange *iorange, - uint64_t offset, - unsigned width, - uint64_t data) -{ - MemoryRegionIORange *mrio - = container_of(iorange, MemoryRegionIORange, iorange); - MemoryRegion *mr = mrio->mr; - - offset += mrio->offset; - if (mr->ops->old_portio) { - const MemoryRegionPortio *mrp = find_portio(mr, offset - mrio->offset, - width, true); - - if (mrp) { - mrp->write(mr->opaque, offset, data); - } else if (width == 2) { - mrp = find_portio(mr, offset - mrio->offset, 1, true); - assert(mrp); - mrp->write(mr->opaque, offset, data & 0xff); - mrp->write(mr->opaque, offset + 1, data >> 8); - } - return; - } - access_with_adjusted_size(offset, &data, width, - mr->ops->impl.min_access_size, - mr->ops->impl.max_access_size, - memory_region_write_accessor, mr); -} - -static void memory_region_iorange_destructor(IORange *iorange) -{ - g_free(container_of(iorange, MemoryRegionIORange, iorange)); -} - -const IORangeOps memory_region_iorange_ops = { - .read = memory_region_iorange_read, - .write = memory_region_iorange_write, - .destructor = memory_region_iorange_destructor, -}; - static AddressSpace *memory_region_to_address_space(MemoryRegion *mr) { AddressSpace *as; @@ -592,17 +541,18 @@ static void render_memory_region(FlatView *view, } /* Render a memory topology into a list of disjoint absolute ranges. */ -static FlatView generate_memory_topology(MemoryRegion *mr) +static FlatView *generate_memory_topology(MemoryRegion *mr) { - FlatView view; + FlatView *view; - flatview_init(&view); + view = g_new(FlatView, 1); + flatview_init(view); if (mr) { - render_memory_region(&view, mr, int128_zero(), + render_memory_region(view, mr, int128_zero(), addrrange_make(int128_zero(), int128_2_64()), false); } - flatview_simplify(&view); + flatview_simplify(view); return view; } @@ -656,15 +606,28 @@ static void address_space_add_del_ioeventfds(AddressSpace *as, } } +static FlatView *address_space_get_flatview(AddressSpace *as) +{ + FlatView *view; + + qemu_mutex_lock(&flat_view_mutex); + view = as->current_map; + flatview_ref(view); + qemu_mutex_unlock(&flat_view_mutex); + return view; +} + static void address_space_update_ioeventfds(AddressSpace *as) { + FlatView *view; FlatRange *fr; unsigned ioeventfd_nb = 0; MemoryRegionIoeventfd *ioeventfds = NULL; AddrRange tmp; unsigned i; - FOR_EACH_FLAT_RANGE(fr, as->current_map) { + view = address_space_get_flatview(as); + FOR_EACH_FLAT_RANGE(fr, view) { for (i = 0; i < fr->mr->ioeventfd_nb; ++i) { tmp = addrrange_shift(fr->mr->ioeventfds[i].addr, int128_sub(fr->addr.start, @@ -685,11 +648,12 @@ static void address_space_update_ioeventfds(AddressSpace *as) g_free(as->ioeventfds); as->ioeventfds = ioeventfds; as->ioeventfd_nb = ioeventfd_nb; + flatview_unref(view); } static void address_space_update_topology_pass(AddressSpace *as, - FlatView old_view, - FlatView new_view, + const FlatView *old_view, + const FlatView *new_view, bool adding) { unsigned iold, inew; @@ -699,14 +663,14 @@ static void address_space_update_topology_pass(AddressSpace *as, * Kill ranges in the old map, and instantiate ranges in the new map. */ iold = inew = 0; - while (iold < old_view.nr || inew < new_view.nr) { - if (iold < old_view.nr) { - frold = &old_view.ranges[iold]; + while (iold < old_view->nr || inew < new_view->nr) { + if (iold < old_view->nr) { + frold = &old_view->ranges[iold]; } else { frold = NULL; } - if (inew < new_view.nr) { - frnew = &new_view.ranges[inew]; + if (inew < new_view->nr) { + frnew = &new_view->ranges[inew]; } else { frnew = NULL; } @@ -752,14 +716,25 @@ static void address_space_update_topology_pass(AddressSpace *as, static void address_space_update_topology(AddressSpace *as) { - FlatView old_view = *as->current_map; - FlatView new_view = generate_memory_topology(as->root); + FlatView *old_view = address_space_get_flatview(as); + FlatView *new_view = generate_memory_topology(as->root); address_space_update_topology_pass(as, old_view, new_view, false); address_space_update_topology_pass(as, old_view, new_view, true); - *as->current_map = new_view; - flatview_destroy(&old_view); + qemu_mutex_lock(&flat_view_mutex); + flatview_unref(as->current_map); + as->current_map = new_view; + qemu_mutex_unlock(&flat_view_mutex); + + /* Note that all the old MemoryRegions are still alive up to this + * point. This relieves most MemoryListeners from the need to + * ref/unref the MemoryRegions they get---unless they use them + * outside the iothread mutex, in which case precise reference + * counting is necessary. + */ + flatview_unref(old_view); + address_space_update_ioeventfds(as); } @@ -796,6 +771,11 @@ static void memory_region_destructor_ram(MemoryRegion *mr) qemu_ram_free(mr->ram_addr); } +static void memory_region_destructor_alias(MemoryRegion *mr) +{ + memory_region_unref(mr->alias); +} + static void memory_region_destructor_ram_from_ptr(MemoryRegion *mr) { qemu_ram_free_from_ptr(mr->ram_addr); @@ -816,13 +796,16 @@ static bool memory_region_wrong_endianness(MemoryRegion *mr) } void memory_region_init(MemoryRegion *mr, + Object *owner, const char *name, uint64_t size) { mr->ops = &unassigned_mem_ops; mr->opaque = NULL; + mr->owner = owner; mr->iommu_ops = NULL; mr->parent = NULL; + mr->owner = NULL; mr->size = int128_make64(size); if (size == UINT64_MAX) { mr->size = int128_2_64(); @@ -855,9 +838,8 @@ static uint64_t unassigned_mem_read(void *opaque, hwaddr addr, #ifdef DEBUG_UNASSIGNED printf("Unassigned mem read " TARGET_FMT_plx "\n", addr); #endif - if (cpu_single_env != NULL) { - cpu_unassigned_access(ENV_GET_CPU(cpu_single_env), - addr, false, false, 0, size); + if (current_cpu != NULL) { + cpu_unassigned_access(current_cpu, addr, false, false, 0, size); } return 0; } @@ -868,9 +850,8 @@ static void unassigned_mem_write(void *opaque, hwaddr addr, #ifdef DEBUG_UNASSIGNED printf("Unassigned mem write " TARGET_FMT_plx " = 0x%"PRIx64"\n", addr, val); #endif - if (cpu_single_env != NULL) { - cpu_unassigned_access(ENV_GET_CPU(cpu_single_env), - addr, true, false, 0, size); + if (current_cpu != NULL) { + cpu_unassigned_access(current_cpu, addr, true, false, 0, size); } } @@ -1002,12 +983,13 @@ static bool memory_region_dispatch_write(MemoryRegion *mr, } void memory_region_init_io(MemoryRegion *mr, + Object *owner, const MemoryRegionOps *ops, void *opaque, const char *name, uint64_t size) { - memory_region_init(mr, name, size); + memory_region_init(mr, owner, name, size); mr->ops = ops; mr->opaque = opaque; mr->terminates = true; @@ -1015,10 +997,11 @@ void memory_region_init_io(MemoryRegion *mr, } void memory_region_init_ram(MemoryRegion *mr, + Object *owner, const char *name, uint64_t size) { - memory_region_init(mr, name, size); + memory_region_init(mr, owner, name, size); mr->ram = true; mr->terminates = true; mr->destructor = memory_region_destructor_ram; @@ -1026,11 +1009,12 @@ void memory_region_init_ram(MemoryRegion *mr, } void memory_region_init_ram_ptr(MemoryRegion *mr, + Object *owner, const char *name, uint64_t size, void *ptr) { - memory_region_init(mr, name, size); + memory_region_init(mr, owner, name, size); mr->ram = true; mr->terminates = true; mr->destructor = memory_region_destructor_ram_from_ptr; @@ -1038,23 +1022,27 @@ void memory_region_init_ram_ptr(MemoryRegion *mr, } void memory_region_init_alias(MemoryRegion *mr, + Object *owner, const char *name, MemoryRegion *orig, hwaddr offset, uint64_t size) { - memory_region_init(mr, name, size); + memory_region_init(mr, owner, name, size); + memory_region_ref(orig); + mr->destructor = memory_region_destructor_alias; mr->alias = orig; mr->alias_offset = offset; } void memory_region_init_rom_device(MemoryRegion *mr, + Object *owner, const MemoryRegionOps *ops, void *opaque, const char *name, uint64_t size) { - memory_region_init(mr, name, size); + memory_region_init(mr, owner, name, size); mr->ops = ops; mr->opaque = opaque; mr->terminates = true; @@ -1064,21 +1052,23 @@ void memory_region_init_rom_device(MemoryRegion *mr, } void memory_region_init_iommu(MemoryRegion *mr, + Object *owner, const MemoryRegionIOMMUOps *ops, const char *name, uint64_t size) { - memory_region_init(mr, name, size); + memory_region_init(mr, owner, name, size); mr->iommu_ops = ops, mr->terminates = true; /* then re-forwards */ notifier_list_init(&mr->iommu_notify); } void memory_region_init_reservation(MemoryRegion *mr, + Object *owner, const char *name, uint64_t size) { - memory_region_init_io(mr, &unassigned_mem_ops, mr, name, size); + memory_region_init_io(mr, owner, &unassigned_mem_ops, mr, name, size); } void memory_region_destroy(MemoryRegion *mr) @@ -1091,6 +1081,25 @@ void memory_region_destroy(MemoryRegion *mr) g_free(mr->ioeventfds); } +Object *memory_region_owner(MemoryRegion *mr) +{ + return mr->owner; +} + +void memory_region_ref(MemoryRegion *mr) +{ + if (mr && mr->owner) { + object_ref(mr->owner); + } +} + +void memory_region_unref(MemoryRegion *mr) +{ + if (mr && mr->owner) { + object_unref(mr->owner); + } +} + uint64_t memory_region_size(MemoryRegion *mr) { if (int128_eq(mr->size, int128_2_64())) { @@ -1188,11 +1197,13 @@ void memory_region_sync_dirty_bitmap(MemoryRegion *mr) FlatRange *fr; QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) { - FOR_EACH_FLAT_RANGE(fr, as->current_map) { + FlatView *view = address_space_get_flatview(as); + FOR_EACH_FLAT_RANGE(fr, view) { if (fr->mr == mr) { MEMORY_LISTENER_UPDATE_REGION(fr, as, Forward, log_sync); } } + flatview_unref(view); } } @@ -1238,12 +1249,14 @@ void *memory_region_get_ram_ptr(MemoryRegion *mr) static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpace *as) { + FlatView *view; FlatRange *fr; CoalescedMemoryRange *cmr; AddrRange tmp; MemoryRegionSection section; - FOR_EACH_FLAT_RANGE(fr, as->current_map) { + view = address_space_get_flatview(as); + FOR_EACH_FLAT_RANGE(fr, view) { if (fr->mr == mr) { section = (MemoryRegionSection) { .address_space = as, @@ -1268,6 +1281,7 @@ static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpa } } } + flatview_unref(view); } static void memory_region_update_coalesced_range(MemoryRegion *mr) @@ -1400,6 +1414,7 @@ static void memory_region_add_subregion_common(MemoryRegion *mr, memory_region_transaction_begin(); assert(!subregion->parent); + memory_region_ref(subregion); subregion->parent = mr; subregion->addr = offset; QTAILQ_FOREACH(other, &mr->subregions, subregions_link) { @@ -1462,6 +1477,7 @@ void memory_region_del_subregion(MemoryRegion *mr, assert(subregion->parent == mr); subregion->parent = NULL; QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link); + memory_region_unref(subregion); memory_region_update_pending |= mr->enabled && subregion->enabled; memory_region_transaction_commit(); } @@ -1489,12 +1505,14 @@ void memory_region_set_address(MemoryRegion *mr, hwaddr addr) } memory_region_transaction_begin(); + memory_region_ref(mr); memory_region_del_subregion(parent, mr); if (may_overlap) { memory_region_add_subregion_overlap(parent, addr, mr, priority); } else { memory_region_add_subregion(parent, addr, mr); } + memory_region_unref(mr); memory_region_transaction_commit(); } @@ -1530,12 +1548,22 @@ static int cmp_flatrange_addr(const void *addr_, const void *fr_) return 0; } -static FlatRange *address_space_lookup(AddressSpace *as, AddrRange addr) +static FlatRange *flatview_lookup(FlatView *view, AddrRange addr) { - return bsearch(&addr, as->current_map->ranges, as->current_map->nr, + return bsearch(&addr, view->ranges, view->nr, sizeof(FlatRange), cmp_flatrange_addr); } +bool memory_region_present(MemoryRegion *parent, hwaddr addr) +{ + MemoryRegion *mr = memory_region_find(parent, addr, 1).mr; + if (!mr) { + return false; + } + memory_region_unref(mr); + return true; +} + MemoryRegionSection memory_region_find(MemoryRegion *mr, hwaddr addr, uint64_t size) { @@ -1543,6 +1571,7 @@ MemoryRegionSection memory_region_find(MemoryRegion *mr, MemoryRegion *root; AddressSpace *as; AddrRange range; + FlatView *view; FlatRange *fr; addr += mr->addr; @@ -1553,13 +1582,14 @@ MemoryRegionSection memory_region_find(MemoryRegion *mr, as = memory_region_to_address_space(root); range = addrrange_make(int128_make64(addr), int128_make64(size)); - fr = address_space_lookup(as, range); + + view = address_space_get_flatview(as); + fr = flatview_lookup(view, range); if (!fr) { return ret; } - while (fr > as->current_map->ranges - && addrrange_intersects(fr[-1].addr, range)) { + while (fr > view->ranges && addrrange_intersects(fr[-1].addr, range)) { --fr; } @@ -1572,16 +1602,22 @@ MemoryRegionSection memory_region_find(MemoryRegion *mr, ret.size = range.size; ret.offset_within_address_space = int128_get64(range.start); ret.readonly = fr->readonly; + memory_region_ref(ret.mr); + + flatview_unref(view); return ret; } void address_space_sync_dirty_bitmap(AddressSpace *as) { + FlatView *view; FlatRange *fr; - FOR_EACH_FLAT_RANGE(fr, as->current_map) { + view = address_space_get_flatview(as); + FOR_EACH_FLAT_RANGE(fr, view) { MEMORY_LISTENER_UPDATE_REGION(fr, as, Forward, log_sync); } + flatview_unref(view); } void memory_global_dirty_log_start(void) @@ -1599,6 +1635,7 @@ void memory_global_dirty_log_stop(void) static void listener_add_address_space(MemoryListener *listener, AddressSpace *as) { + FlatView *view; FlatRange *fr; if (listener->address_space_filter @@ -1612,7 +1649,8 @@ static void listener_add_address_space(MemoryListener *listener, } } - FOR_EACH_FLAT_RANGE(fr, as->current_map) { + view = address_space_get_flatview(as); + FOR_EACH_FLAT_RANGE(fr, view) { MemoryRegionSection section = { .mr = fr->mr, .address_space = as, @@ -1625,6 +1663,7 @@ static void listener_add_address_space(MemoryListener *listener, listener->region_add(listener, §ion); } } + flatview_unref(view); } void memory_listener_register(MemoryListener *listener, AddressSpace *filter) @@ -1658,6 +1697,10 @@ void memory_listener_unregister(MemoryListener *listener) void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name) { + if (QTAILQ_EMPTY(&address_spaces)) { + memory_init(); + } + memory_region_transaction_begin(); as->root = root; as->current_map = g_new(FlatView, 1); @@ -1679,9 +1722,8 @@ void address_space_destroy(AddressSpace *as) memory_region_transaction_commit(); QTAILQ_REMOVE(&address_spaces, as, address_spaces_link); address_space_destroy_dispatch(as); - flatview_destroy(as->current_map); + flatview_unref(as->current_map); g_free(as->name); - g_free(as->current_map); g_free(as->ioeventfds); } diff --git a/memory_mapping.c b/memory_mapping.c index 5634f813c..515a984e0 100644 --- a/memory_mapping.c +++ b/memory_mapping.c @@ -165,13 +165,13 @@ void memory_mapping_list_init(MemoryMappingList *list) QTAILQ_INIT(&list->head); } -static CPUArchState *find_paging_enabled_cpu(CPUArchState *start_cpu) +static CPUState *find_paging_enabled_cpu(CPUState *start_cpu) { - CPUArchState *env; + CPUState *cpu; - for (env = start_cpu; env != NULL; env = env->next_cpu) { - if (cpu_paging_enabled(ENV_GET_CPU(env))) { - return env; + for (cpu = start_cpu; cpu != NULL; cpu = cpu->next_cpu) { + if (cpu_paging_enabled(cpu)) { + return cpu; } } @@ -180,15 +180,15 @@ static CPUArchState *find_paging_enabled_cpu(CPUArchState *start_cpu) void qemu_get_guest_memory_mapping(MemoryMappingList *list, Error **errp) { - CPUArchState *env, *first_paging_enabled_cpu; + CPUState *cpu, *first_paging_enabled_cpu; RAMBlock *block; ram_addr_t offset, length; first_paging_enabled_cpu = find_paging_enabled_cpu(first_cpu); if (first_paging_enabled_cpu) { - for (env = first_paging_enabled_cpu; env != NULL; env = env->next_cpu) { + for (cpu = first_paging_enabled_cpu; cpu != NULL; cpu = cpu->next_cpu) { Error *err = NULL; - cpu_get_memory_mapping(ENV_GET_CPU(env), list, &err); + cpu_get_memory_mapping(cpu, list, &err); if (err) { error_propagate(errp, err); return; diff --git a/migration.c b/migration.c index a704d4866..0681d8e5f 100644 --- a/migration.c +++ b/migration.c @@ -293,8 +293,7 @@ static void migrate_fd_cleanup(void *opaque) static void migrate_finish_set_state(MigrationState *s, int new_state) { - if (__sync_val_compare_and_swap(&s->state, MIG_STATE_ACTIVE, - new_state) == new_state) { + if (atomic_cmpxchg(&s->state, MIG_STATE_ACTIVE, new_state) == new_state) { trace_migrate_set_state(new_state); } } @@ -528,15 +527,26 @@ static void *migration_thread(void *opaque) if (pending_size && pending_size >= max_size) { qemu_savevm_state_iterate(s->file); } else { + int ret; + DPRINTF("done iterating\n"); qemu_mutex_lock_iothread(); start_time = qemu_get_clock_ms(rt_clock); qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); old_vm_running = runstate_is_running(); - vm_stop_force_state(RUN_STATE_FINISH_MIGRATE); - qemu_file_set_rate_limit(s->file, INT_MAX); - qemu_savevm_state_complete(s->file); + + ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE); + if (ret >= 0) { + qemu_file_set_rate_limit(s->file, INT_MAX); + qemu_savevm_state_complete(s->file); + } qemu_mutex_unlock_iothread(); + + if (ret < 0) { + migrate_finish_set_state(s, MIG_STATE_ERROR); + break; + } + if (!qemu_file_get_error(s->file)) { migrate_finish_set_state(s, MIG_STATE_COMPLETED); break; diff --git a/monitor.c b/monitor.c index 9be515c13..2ba7876b5 100644 --- a/monitor.c +++ b/monitor.c @@ -1806,14 +1806,12 @@ static void do_info_mtree(Monitor *mon, const QDict *qdict) static void do_info_numa(Monitor *mon, const QDict *qdict) { int i; - CPUArchState *env; CPUState *cpu; monitor_printf(mon, "%d nodes\n", nb_numa_nodes); for (i = 0; i < nb_numa_nodes; i++) { monitor_printf(mon, "node %d cpus:", i); - for (env = first_cpu; env != NULL; env = env->next_cpu) { - cpu = ENV_GET_CPU(env); + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { if (cpu->numa_node == i) { monitor_printf(mon, " %d", cpu->cpu_index); } diff --git a/qapi-schema.json b/qapi-schema.json index 5c32528a1..cf57783ca 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -1634,6 +1634,10 @@ # @format: #optional the format of the new destination, default is to # probe if @mode is 'existing', else the format of the source # +# @sync: what parts of the disk image should be copied to the destination +# (all the disk, only the sectors allocated in the topmost image, or +# only new I/O). +# # @mode: #optional whether and how QEMU should create a new image, default is # 'absolute-paths'. # @@ -1655,7 +1659,8 @@ ## { 'type': 'DriveBackup', 'data': { 'device': 'str', 'target': 'str', '*format': 'str', - '*mode': 'NewImageMode', '*speed': 'int', + 'sync': 'MirrorSyncMode', '*mode': 'NewImageMode', + '*speed': 'int', '*on-source-error': 'BlockdevOnError', '*on-target-error': 'BlockdevOnError' } } @@ -1709,16 +1714,7 @@ # # Generates a synchronous snapshot of a block device. # -# @device: the name of the device to generate the snapshot from. -# -# @snapshot-file: the target of the new image. If the file exists, or if it -# is a device, the snapshot will be created in the existing -# file/device. If does not exist, a new file will be created. -# -# @format: #optional the format of the snapshot image, default is 'qcow2'. -# -# @mode: #optional whether and how QEMU should create a new image, default is -# 'absolute-paths'. +# For the arguments, see the documentation of BlockdevSnapshot. # # Returns: nothing on success # If @device is not a valid block device, DeviceNotFound @@ -1726,8 +1722,7 @@ # Since 0.14.0 ## { 'command': 'blockdev-snapshot-sync', - 'data': { 'device': 'str', 'snapshot-file': 'str', '*format': 'str', - '*mode': 'NewImageMode'} } + 'data': 'BlockdevSnapshot' } ## # @human-monitor-command: @@ -1801,42 +1796,14 @@ # The operation can be stopped before it has completed using the # block-job-cancel command. # -# @device: the name of the device which should be copied. -# -# @target: the target of the new image. If the file exists, or if it -# is a device, the existing file/device will be used as the new -# destination. If it does not exist, a new file will be created. -# -# @format: #optional the format of the new destination, default is to -# probe if @mode is 'existing', else the format of the source -# -# @mode: #optional whether and how QEMU should create a new image, default is -# 'absolute-paths'. -# -# @speed: #optional the maximum speed, in bytes per second -# -# @on-source-error: #optional the action to take on an error on the source, -# default 'report'. 'stop' and 'enospc' can only be used -# if the block device supports io-status (see BlockInfo). -# -# @on-target-error: #optional the action to take on an error on the target, -# default 'report' (no limitations, since this applies to -# a different block device than @device). -# -# Note that @on-source-error and @on-target-error only affect background I/O. -# If an error occurs during a guest write request, the device's rerror/werror -# actions will be used. +# For the arguments, see the documentation of DriveBackup. # # Returns: nothing on success # If @device is not a valid block device, DeviceNotFound # # Since 1.6 ## -{ 'command': 'drive-backup', - 'data': { 'device': 'str', 'target': 'str', '*format': 'str', - '*mode': 'NewImageMode', '*speed': 'int', - '*on-source-error': 'BlockdevOnError', - '*on-target-error': 'BlockdevOnError' } } +{ 'command': 'drive-backup', 'data': 'DriveBackup' } ## # @drive-mirror diff --git a/qemu-char.c b/qemu-char.c index 6cec5d711..800d6a62f 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -926,7 +926,6 @@ static void qemu_chr_set_echo_stdio(CharDriverState *chr, bool echo) tty.c_cc[VMIN] = 1; tty.c_cc[VTIME] = 0; } - /* if graphical mode, we allow Ctrl-C handling */ if (!stdio_allow_signal) tty.c_lflag &= ~ISIG; @@ -955,7 +954,6 @@ static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts) chr = qemu_chr_open_fd(0, 1); chr->chr_close = qemu_chr_close_stdio; chr->chr_set_echo = qemu_chr_set_echo_stdio; - stdio_allow_signal = display_type != DT_NOGRAPHIC; if (opts->has_signal) { stdio_allow_signal = opts->signal; } @@ -2932,6 +2930,14 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename) if (strstart(filename, "mon:", &p)) { filename = p; qemu_opt_set(opts, "mux", "on"); + if (strcmp(filename, "stdio") == 0) { + /* Monitor is muxed to stdio: do not exit on Ctrl+C by default + * but pass it to the guest. Handle this only for compat syntax, + * for -chardev syntax we have special option for this. + * This is what -nographic did, redirecting+muxing serial+monitor + * to stdio causing Ctrl+C to be passed to guest. */ + qemu_opt_set(opts, "signal", "off"); + } } if (strcmp(filename, "null") == 0 || @@ -3060,8 +3066,7 @@ static void qemu_chr_parse_stdio(QemuOpts *opts, ChardevBackend *backend, { backend->stdio = g_new0(ChardevStdio, 1); backend->stdio->has_signal = true; - backend->stdio->signal = - qemu_opt_get_bool(opts, "signal", display_type != DT_NOGRAPHIC); + backend->stdio->signal = qemu_opt_get_bool(opts, "signal", true); } static void qemu_chr_parse_serial(QemuOpts *opts, ChardevBackend *backend, @@ -3110,7 +3115,7 @@ static void qemu_chr_parse_memory(QemuOpts *opts, ChardevBackend *backend, backend->memory = g_new0(ChardevMemory, 1); - val = qemu_opt_get_number(opts, "size", 0); + val = qemu_opt_get_size(opts, "size", 0); if (val != 0) { backend->memory->has_size = true; backend->memory->size = val; diff --git a/qemu-img.c b/qemu-img.c index f8c97d34d..c55ca5c55 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -240,7 +240,7 @@ static int print_block_option_help(const char *filename, const char *fmt) return 1; } - proto_drv = bdrv_find_protocol(filename); + proto_drv = bdrv_find_protocol(filename, true); if (!proto_drv) { error_report("Unknown protocol '%s'", filename); return 1; @@ -1261,7 +1261,7 @@ static int img_convert(int argc, char **argv) goto out; } - proto_drv = bdrv_find_protocol(out_filename); + proto_drv = bdrv_find_protocol(out_filename, true); if (!proto_drv) { error_report("Unknown protocol '%s'", out_filename); ret = -1; diff --git a/qemu-options.hx b/qemu-options.hx index 137a39b7a..4e98b4f48 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -842,7 +842,8 @@ STEXI Normally, QEMU uses SDL to display the VGA output. With this option, you can totally disable graphical output so that QEMU is a simple command line application. The emulated serial port is redirected on -the console. Therefore, you can still use QEMU to debug a Linux kernel +the console and muxed with the monitor (unless redirected elsewhere +explicitly). Therefore, you can still use QEMU to debug a Linux kernel with a serial console. ETEXI @@ -2485,14 +2486,15 @@ same as if you had specified @code{-serial tcp} except the unix domain socket @item mon:@var{dev_string} This is a special option to allow the monitor to be multiplexed onto another serial port. The monitor is accessed with key sequence of -@key{Control-a} and then pressing @key{c}. See monitor access -@ref{pcsys_keys} in the -nographic section for more keys. +@key{Control-a} and then pressing @key{c}. @var{dev_string} should be any one of the serial devices specified above. An example to multiplex the monitor onto a telnet server listening on port 4444 would be: @table @code @item -serial mon:telnet::4444,server,nowait @end table +When monitor is multiplexed to stdio this way, Ctrl+C will not terminate +QEMU anymore but will be passed to the guest instead. @item braille Braille device. This will use BrlAPI to display the braille output on a real @@ -3098,6 +3100,17 @@ property must be set. These objects are placed in the '/objects' path. ETEXI +DEF("msg", HAS_ARG, QEMU_OPTION_msg, + "-msg timestamp[=on|off]\n" + " change the format of messages\n" + " on|off controls leading timestamps (default:on)\n", + QEMU_ARCH_ALL) +STEXI +@item -msg timestamp[=on|off] +@findex -msg +prepend a timestamp to each log message.(default:on) +ETEXI + HXCOMM This is the last statement. Insert new options before this line! STEXI @end table diff --git a/qmp-commands.hx b/qmp-commands.hx index 362f0e1ef..e075df423 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -913,7 +913,7 @@ EQMP { .name = "drive-backup", - .args_type = "device:B,target:s,speed:i?,mode:s?,format:s?," + .args_type = "sync:s,device:B,target:s,speed:i?,mode:s?,format:s?," "on-source-error:s?,on-target-error:s?", .mhandler.cmd_new = qmp_marshal_input_drive_backup, }, @@ -939,6 +939,10 @@ Arguments: - "format": the format of the new destination, default is to probe if 'mode' is 'existing', else the format of the source (json-string, optional) +- "sync": what parts of the disk image should be copied to the destination; + possibilities include "full" for all the disk, "top" for only the sectors + allocated in the topmost image, or "none" to only replicate new I/O + (MirrorSyncMode). - "mode": whether and how QEMU should create a new image (NewImageMode, optional, default 'absolute-paths') - "speed": the maximum speed, in bytes per second (json-int, optional) diff --git a/qom/cpu.c b/qom/cpu.c index ee8f632ec..5c45ab533 100644 --- a/qom/cpu.c +++ b/qom/cpu.c @@ -22,6 +22,7 @@ #include "qom/cpu.h" #include "sysemu/kvm.h" #include "qemu/notify.h" +#include "qemu/log.h" #include "sysemu/sysemu.h" typedef struct CPUExistsArgs { @@ -187,6 +188,13 @@ void cpu_reset(CPUState *cpu) static void cpu_common_reset(CPUState *cpu) { + CPUClass *cc = CPU_GET_CLASS(cpu); + + if (qemu_loglevel_mask(CPU_LOG_RESET)) { + qemu_log("CPU Reset (CPU %d)\n", cpu->cpu_index); + log_cpu_state(cpu, cc->reset_dump_flags); + } + cpu->exit_request = 0; cpu->interrupt_request = 0; cpu->current_tb = NULL; diff --git a/qom/object.c b/qom/object.c index 803b94bb6..b2479d1c0 100644 --- a/qom/object.c +++ b/qom/object.c @@ -531,14 +531,14 @@ ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class, #ifdef CONFIG_QOM_CAST_DEBUG int i; - for (i = 0; i < OBJECT_CLASS_CAST_CACHE; i++) { + for (i = 0; class && i < OBJECT_CLASS_CAST_CACHE; i++) { if (class->cast_cache[i] == typename) { ret = class; goto out; } } #else - if (!class->interfaces) { + if (!class || !class->interfaces) { return class; } #endif @@ -551,7 +551,7 @@ ObjectClass *object_class_dynamic_cast_assert(ObjectClass *class, } #ifdef CONFIG_QOM_CAST_DEBUG - if (ret == class) { + if (class && ret == class) { for (i = 1; i < OBJECT_CLASS_CAST_CACHE; i++) { class->cast_cache[i - 1] = class->cast_cache[i]; } @@ -683,16 +683,15 @@ GSList *object_class_get_list(const char *implements_type, void object_ref(Object *obj) { - obj->ref++; + atomic_inc(&obj->ref); } void object_unref(Object *obj) { g_assert(obj->ref > 0); - obj->ref--; /* parent always holds a reference to its children */ - if (obj->ref == 0) { + if (atomic_fetch_dec(&obj->ref) == 1) { object_finalize(obj); } } diff --git a/scripts/qapi.py b/scripts/qapi.py index 02ad668ca..baf13213a 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -78,10 +78,8 @@ def parse(tokens): def evaluate(string): return parse(map(lambda x: x, tokenize(string)))[0] -def parse_schema(fp): - exprs = [] +def get_expr(fp): expr = '' - expr_eval = None for line in fp: if line.startswith('#') or line == '\n': @@ -90,27 +88,36 @@ def parse_schema(fp): if line.startswith(' '): expr += line elif expr: - expr_eval = evaluate(expr) - if expr_eval.has_key('enum'): - add_enum(expr_eval['enum']) - elif expr_eval.has_key('union'): - add_enum('%sKind' % expr_eval['union']) - exprs.append(expr_eval) + yield expr expr = line else: expr += line if expr: + yield expr + +def parse_schema(fp): + exprs = [] + + for expr in get_expr(fp): expr_eval = evaluate(expr) + if expr_eval.has_key('enum'): add_enum(expr_eval['enum']) elif expr_eval.has_key('union'): add_enum('%sKind' % expr_eval['union']) + elif expr_eval.has_key('type'): + add_struct(expr_eval) exprs.append(expr_eval) return exprs def parse_args(typeinfo): + if isinstance(typeinfo, basestring): + struct = find_struct(typeinfo) + assert struct != None + typeinfo = struct['data'] + for member in typeinfo: argname = member argentry = typeinfo[member] @@ -180,6 +187,18 @@ def type_name(name): return name enum_types = [] +struct_types = [] + +def add_struct(definition): + global struct_types + struct_types.append(definition) + +def find_struct(name): + global struct_types + for struct in struct_types: + if struct['type'] == name: + return struct + return None def add_enum(name): global enum_types diff --git a/stubs/vm-stop.c b/stubs/vm-stop.c index 45689354f..f82c897df 100644 --- a/stubs/vm-stop.c +++ b/stubs/vm-stop.c @@ -1,7 +1,7 @@ #include "qemu-common.h" #include "sysemu/sysemu.h" -void vm_stop(RunState state) +int vm_stop(RunState state) { abort(); } diff --git a/target-alpha/cpu-qom.h b/target-alpha/cpu-qom.h index 94e4a547f..60125b19d 100644 --- a/target-alpha/cpu-qom.h +++ b/target-alpha/cpu-qom.h @@ -67,7 +67,7 @@ typedef struct AlphaCPU { static inline AlphaCPU *alpha_env_get_cpu(CPUAlphaState *env) { - return ALPHA_CPU(container_of(env, AlphaCPU, env)); + return container_of(env, AlphaCPU, env); } #define ENV_GET_CPU(e) CPU(alpha_env_get_cpu(e)) diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h index 01f4ebb82..066f0324e 100644 --- a/target-alpha/cpu.h +++ b/target-alpha/cpu.h @@ -498,22 +498,6 @@ static inline void cpu_get_tb_cpu_state(CPUAlphaState *env, target_ulong *pc, *pflags = flags; } -#if defined(CONFIG_USER_ONLY) -static inline void cpu_clone_regs(CPUAlphaState *env, target_ulong newsp) -{ - if (newsp) { - env->ir[IR_SP] = newsp; - } - env->ir[IR_V0] = 0; - env->ir[IR_A3] = 0; -} - -static inline void cpu_set_tls(CPUAlphaState *env, target_ulong newtls) -{ - env->unique = newtls; -} -#endif - static inline bool cpu_has_work(CPUState *cpu) { /* Here we are checking to see if the CPU should wake up from HALT. diff --git a/target-alpha/translate.c b/target-alpha/translate.c index 4db16db46..dd7f0fbf9 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -3375,10 +3375,11 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn) return ret; } -static inline void gen_intermediate_code_internal(CPUAlphaState *env, +static inline void gen_intermediate_code_internal(AlphaCPU *cpu, TranslationBlock *tb, - int search_pc) + bool search_pc) { + CPUAlphaState *env = &cpu->env; DisasContext ctx, *ctxp = &ctx; target_ulong pc_start; uint32_t insn; @@ -3502,12 +3503,12 @@ static inline void gen_intermediate_code_internal(CPUAlphaState *env, void gen_intermediate_code (CPUAlphaState *env, struct TranslationBlock *tb) { - gen_intermediate_code_internal(env, tb, 0); + gen_intermediate_code_internal(alpha_env_get_cpu(env), tb, false); } void gen_intermediate_code_pc (CPUAlphaState *env, struct TranslationBlock *tb) { - gen_intermediate_code_internal(env, tb, 1); + gen_intermediate_code_internal(alpha_env_get_cpu(env), tb, true); } void restore_state_to_opc(CPUAlphaState *env, TranslationBlock *tb, int pc_pos) diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h index ef6261fd1..48ba6054e 100644 --- a/target-arm/cpu-qom.h +++ b/target-arm/cpu-qom.h @@ -127,7 +127,7 @@ typedef struct ARMCPU { static inline ARMCPU *arm_env_get_cpu(CPUARMState *env) { - return ARM_CPU(container_of(env, ARMCPU, env)); + return container_of(env, ARMCPU, env); } #define ENV_GET_CPU(e) CPU(arm_env_get_cpu(e)) diff --git a/target-arm/cpu.c b/target-arm/cpu.c index 1bc227e9a..9f1696f93 100644 --- a/target-arm/cpu.c +++ b/target-arm/cpu.c @@ -63,11 +63,6 @@ static void arm_cpu_reset(CPUState *s) ARMCPUClass *acc = ARM_CPU_GET_CLASS(cpu); CPUARMState *env = &cpu->env; - if (qemu_loglevel_mask(CPU_LOG_RESET)) { - qemu_log("CPU Reset (CPU %d)\n", s->cpu_index); - log_cpu_state(env, 0); - } - acc->parent_reset(s); memset(env, 0, offsetof(CPUARMState, breakpoints)); @@ -162,6 +157,11 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) CPUARMState *env = &cpu->env; /* Some features automatically imply others: */ + if (arm_feature(env, ARM_FEATURE_V8)) { + set_feature(env, ARM_FEATURE_V7); + set_feature(env, ARM_FEATURE_ARM_DIV); + set_feature(env, ARM_FEATURE_LPAE); + } if (arm_feature(env, ARM_FEATURE_V7)) { set_feature(env, ARM_FEATURE_VAPA); set_feature(env, ARM_FEATURE_THUMB2); @@ -749,7 +749,7 @@ static void pxa270c5_initfn(Object *obj) static void arm_any_initfn(Object *obj) { ARMCPU *cpu = ARM_CPU(obj); - set_feature(&cpu->env, ARM_FEATURE_V7); + set_feature(&cpu->env, ARM_FEATURE_V8); set_feature(&cpu->env, ARM_FEATURE_VFP4); set_feature(&cpu->env, ARM_FEATURE_VFP_FP16); set_feature(&cpu->env, ARM_FEATURE_NEON); diff --git a/target-arm/cpu.h b/target-arm/cpu.h index abcc0b4b1..c798b272a 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -249,11 +249,6 @@ int cpu_arm_handle_mmu_fault (CPUARMState *env, target_ulong address, int rw, int mmu_idx); #define cpu_handle_mmu_fault cpu_arm_handle_mmu_fault -static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls) -{ - env->cp15.c13_tls2 = newtls; -} - #define CPSR_M (0x1f) #define CPSR_T (1 << 5) #define CPSR_F (1 << 6) @@ -392,6 +387,7 @@ enum arm_features { ARM_FEATURE_MPIDR, /* has cp15 MPIDR */ ARM_FEATURE_PXN, /* has Privileged Execute Never bit */ ARM_FEATURE_LPAE, /* has Large Physical Address Extension */ + ARM_FEATURE_V8, }; static inline int arm_feature(CPUARMState *env, int feature) @@ -734,15 +730,6 @@ static inline int cpu_mmu_index (CPUARMState *env) return (env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR ? 1 : 0; } -#if defined(CONFIG_USER_ONLY) -static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp) -{ - if (newsp) - env->regs[13] = newsp; - env->regs[0] = 0; -} -#endif - #include "exec/cpu-all.h" /* Bit usage in the TB flags field: */ diff --git a/target-arm/helper.c b/target-arm/helper.c index 5f639fdeb..aeae02416 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -222,15 +222,23 @@ static gint cpreg_key_compare(gconstpointer a, gconstpointer b) return aidx - bidx; } +static void cpreg_make_keylist(gpointer key, gpointer value, gpointer udata) +{ + GList **plist = udata; + + *plist = g_list_prepend(*plist, key); +} + void init_cpreg_list(ARMCPU *cpu) { /* Initialise the cpreg_tuples[] array based on the cp_regs hash. * Note that we require cpreg_tuples[] to be sorted by key ID. */ - GList *keys; + GList *keys = NULL; int arraylen; - keys = g_hash_table_get_keys(cpu->cp_regs); + g_hash_table_foreach(cpu->cp_regs, cpreg_make_keylist, &keys); + keys = g_list_sort(keys, cpreg_key_compare); cpu->cpreg_array_len = 0; @@ -891,6 +899,8 @@ static const ARMCPRegInfo pmsav5_cp_reginfo[] = { static int vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { + int maskshift = extract32(value, 0, 3); + if (arm_feature(env, ARM_FEATURE_LPAE)) { value &= ~((7 << 19) | (3 << 14) | (0xf << 3)); } else { @@ -902,8 +912,8 @@ static int vmsa_ttbcr_raw_write(CPUARMState *env, const ARMCPRegInfo *ri, * and the c2_mask and c2_base_mask values are meaningless. */ env->cp15.c2_control = value; - env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> value); - env->cp15.c2_base_mask = ~((uint32_t)0x3fffu >> value); + env->cp15.c2_mask = ~(((uint32_t)0xffffffffu) >> maskshift); + env->cp15.c2_base_mask = ~((uint32_t)0x3fffu >> maskshift); return 0; } @@ -1378,9 +1388,6 @@ void register_cp_regs_for_features(ARMCPU *cpu) if (arm_feature(env, ARM_FEATURE_DUMMY_C15_REGS)) { define_arm_cp_regs(cpu, dummy_c15_cp_reginfo); } - if (arm_feature(env, ARM_FEATURE_MPIDR)) { - define_arm_cp_regs(cpu, mpidr_cp_reginfo); - } if (arm_feature(env, ARM_FEATURE_LPAE)) { define_arm_cp_regs(cpu, lpae_cp_reginfo); } @@ -1393,12 +1400,17 @@ void register_cp_regs_for_features(ARMCPU *cpu) /* Note that the MIDR isn't a simple constant register because * of the TI925 behaviour where writes to another register can * cause the MIDR value to change. + * + * Unimplemented registers in the c15 0 0 0 space default to + * MIDR. Define MIDR first as this entire space, then CTR, TCMTR + * and friends override accordingly. */ { .name = "MIDR", - .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 0, + .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = CP_ANY, .access = PL1_R, .resetvalue = cpu->midr, .writefn = arm_cp_write_ignore, .raw_writefn = raw_write, - .fieldoffset = offsetof(CPUARMState, cp15.c0_cpuid) }, + .fieldoffset = offsetof(CPUARMState, cp15.c0_cpuid), + .type = ARM_CP_OVERRIDE }, { .name = "CTR", .cp = 15, .crn = 0, .crm = 0, .opc1 = 0, .opc2 = 1, .access = PL1_R, .type = ARM_CP_CONST, .resetvalue = cpu->ctr }, @@ -1435,21 +1447,20 @@ void register_cp_regs_for_features(ARMCPU *cpu) arm_feature(env, ARM_FEATURE_STRONGARM)) { ARMCPRegInfo *r; /* Register the blanket "writes ignored" value first to cover the - * whole space. Then define the specific ID registers, but update - * their access field to allow write access, so that they ignore - * writes rather than causing them to UNDEF. + * whole space. Then update the specific ID registers to allow write + * access, so that they ignore writes rather than causing them to + * UNDEF. */ define_one_arm_cp_reg(cpu, &crn0_wi_reginfo); for (r = id_cp_reginfo; r->type != ARM_CP_SENTINEL; r++) { r->access = PL1_RW; - define_one_arm_cp_reg(cpu, r); } - } else { - /* Just register the standard ID registers (read-only, meaning - * that writes will UNDEF). - */ - define_arm_cp_regs(cpu, id_cp_reginfo); } + define_arm_cp_regs(cpu, id_cp_reginfo); + } + + if (arm_feature(env, ARM_FEATURE_MPIDR)) { + define_arm_cp_regs(cpu, mpidr_cp_reginfo); } if (arm_feature(env, ARM_FEATURE_AUXCR)) { @@ -1607,7 +1618,9 @@ void define_one_arm_cp_reg_with_opaque(ARMCPU *cpu, ARMCPRegInfo *r2 = g_memdup(r, sizeof(ARMCPRegInfo)); int is64 = (r->type & ARM_CP_64BIT) ? 1 : 0; *key = ENCODE_CP_REG(r->cp, is64, r->crn, crm, opc1, opc2); - r2->opaque = opaque; + if (opaque) { + r2->opaque = opaque; + } /* Make sure reginfo passed to helpers for wildcarded regs * has the correct crm/opc1/opc2 for this reg, not CP_ANY: */ diff --git a/target-arm/kvm.c b/target-arm/kvm.c index d3937a260..b92e00dae 100644 --- a/target-arm/kvm.c +++ b/target-arm/kvm.c @@ -233,6 +233,7 @@ static void kvm_arm_machine_init_done(Notifier *notifier, void *data) abort(); } } + memory_region_unref(kd->mr); g_free(kd); } } @@ -258,6 +259,7 @@ void kvm_arm_register_device(MemoryRegion *mr, uint64_t devid) kd->kda.id = devid; kd->kda.addr = -1; QSLIST_INSERT_HEAD(&kvm_devices_head, kd, entries); + memory_region_ref(kd->mr); } bool write_kvmstate_to_list(ARMCPU *cpu) diff --git a/target-arm/translate.c b/target-arm/translate.c index af2aef29e..7b50c8c30 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -42,6 +42,7 @@ #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K) #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2) #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7) +#define ENABLE_ARCH_8 arm_feature(env, ARM_FEATURE_V8) #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0) @@ -3500,7 +3501,8 @@ static void gen_nop_hint(DisasContext *s, int val) break; case 2: /* wfe */ case 4: /* sev */ - /* TODO: Implement SEV and WFE. May help SMP performance. */ + case 5: /* sevl */ + /* TODO: Implement SEV, SEVL and WFE. May help SMP performance. */ default: /* nop */ break; } @@ -7273,14 +7275,72 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s) rd = (insn >> 12) & 0xf; if (insn & (1 << 23)) { /* load/store exclusive */ + int op2 = (insn >> 8) & 3; op1 = (insn >> 21) & 0x3; - if (op1) - ARCH(6K); - else - ARCH(6); + + switch (op2) { + case 0: /* lda/stl */ + if (op1 == 1) { + goto illegal_op; + } + ARCH(8); + break; + case 1: /* reserved */ + goto illegal_op; + case 2: /* ldaex/stlex */ + ARCH(8); + break; + case 3: /* ldrex/strex */ + if (op1) { + ARCH(6K); + } else { + ARCH(6); + } + break; + } + addr = tcg_temp_local_new_i32(); load_reg_var(s, addr, rn); - if (insn & (1 << 20)) { + + /* Since the emulation does not have barriers, + the acquire/release semantics need no special + handling */ + if (op2 == 0) { + if (insn & (1 << 20)) { + tmp = tcg_temp_new_i32(); + switch (op1) { + case 0: /* lda */ + tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s)); + break; + case 2: /* ldab */ + tcg_gen_qemu_ld8u(tmp, addr, IS_USER(s)); + break; + case 3: /* ldah */ + tcg_gen_qemu_ld16u(tmp, addr, IS_USER(s)); + break; + default: + abort(); + } + store_reg(s, rd, tmp); + } else { + rm = insn & 0xf; + tmp = load_reg(s, rm); + switch (op1) { + case 0: /* stl */ + tcg_gen_qemu_st32(tmp, addr, IS_USER(s)); + break; + case 2: /* stlb */ + tcg_gen_qemu_st8(tmp, addr, IS_USER(s)); + break; + case 3: /* stlh */ + tcg_gen_qemu_st16(tmp, addr, IS_USER(s)); + break; + default: + abort(); + } + tcg_temp_free_i32(tmp); + } + } else if (insn & (1 << 20)) { switch (op1) { case 0: /* ldrex */ gen_load_exclusive(s, rd, 15, addr, 2); @@ -8125,7 +8185,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw gen_store_exclusive(s, rd, rs, 15, addr, 2); } tcg_temp_free_i32(addr); - } else if ((insn & (1 << 6)) == 0) { + } else if ((insn & (7 << 5)) == 0) { /* Table Branch. */ if (rn == 15) { addr = tcg_temp_new_i32(); @@ -8151,15 +8211,66 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw tcg_gen_addi_i32(tmp, tmp, s->pc); store_reg(s, 15, tmp); } else { - /* Load/store exclusive byte/halfword/doubleword. */ - ARCH(7); + int op2 = (insn >> 6) & 0x3; op = (insn >> 4) & 0x3; - if (op == 2) { + switch (op2) { + case 0: goto illegal_op; + case 1: + /* Load/store exclusive byte/halfword/doubleword */ + if (op == 2) { + goto illegal_op; + } + ARCH(7); + break; + case 2: + /* Load-acquire/store-release */ + if (op == 3) { + goto illegal_op; + } + /* Fall through */ + case 3: + /* Load-acquire/store-release exclusive */ + ARCH(8); + break; } addr = tcg_temp_local_new_i32(); load_reg_var(s, addr, rn); - if (insn & (1 << 20)) { + if (!(op2 & 1)) { + if (insn & (1 << 20)) { + tmp = tcg_temp_new_i32(); + switch (op) { + case 0: /* ldab */ + tcg_gen_qemu_ld8u(tmp, addr, IS_USER(s)); + break; + case 1: /* ldah */ + tcg_gen_qemu_ld16u(tmp, addr, IS_USER(s)); + break; + case 2: /* lda */ + tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s)); + break; + default: + abort(); + } + store_reg(s, rs, tmp); + } else { + tmp = load_reg(s, rs); + switch (op) { + case 0: /* stlb */ + tcg_gen_qemu_st8(tmp, addr, IS_USER(s)); + break; + case 1: /* stlh */ + tcg_gen_qemu_st16(tmp, addr, IS_USER(s)); + break; + case 2: /* stl */ + tcg_gen_qemu_st32(tmp, addr, IS_USER(s)); + break; + default: + abort(); + } + tcg_temp_free_i32(tmp); + } + } else if (insn & (1 << 20)) { gen_load_exclusive(s, rs, rd, addr, op); } else { gen_store_exclusive(s, rm, rs, rd, addr, op); @@ -9796,10 +9907,11 @@ undef: /* generate intermediate code in gen_opc_buf and gen_opparam_buf for basic block 'tb'. If search_pc is TRUE, also generate PC information for each intermediate instruction. */ -static inline void gen_intermediate_code_internal(CPUARMState *env, +static inline void gen_intermediate_code_internal(ARMCPU *cpu, TranslationBlock *tb, - int search_pc) + bool search_pc) { + CPUARMState *env = &cpu->env; DisasContext dc1, *dc = &dc1; CPUBreakpoint *bp; uint16_t *gen_opc_end; @@ -10072,12 +10184,12 @@ done_generating: void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb) { - gen_intermediate_code_internal(env, tb, 0); + gen_intermediate_code_internal(arm_env_get_cpu(env), tb, false); } void gen_intermediate_code_pc(CPUARMState *env, TranslationBlock *tb) { - gen_intermediate_code_internal(env, tb, 1); + gen_intermediate_code_internal(arm_env_get_cpu(env), tb, true); } static const char *cpu_mode_names[16] = { diff --git a/target-cris/cpu-qom.h b/target-cris/cpu-qom.h index e08bdb1ec..af7d14de4 100644 --- a/target-cris/cpu-qom.h +++ b/target-cris/cpu-qom.h @@ -66,7 +66,7 @@ typedef struct CRISCPU { static inline CRISCPU *cris_env_get_cpu(CPUCRISState *env) { - return CRIS_CPU(container_of(env, CRISCPU, env)); + return container_of(env, CRISCPU, env); } #define ENV_GET_CPU(e) CPU(cris_env_get_cpu(e)) diff --git a/target-cris/cpu.c b/target-cris/cpu.c index 6a3bdf00f..2abb57fc2 100644 --- a/target-cris/cpu.c +++ b/target-cris/cpu.c @@ -34,11 +34,6 @@ static void cris_cpu_reset(CPUState *s) CPUCRISState *env = &cpu->env; uint32_t vr; - if (qemu_loglevel_mask(CPU_LOG_RESET)) { - qemu_log("CPU Reset (CPU %d)\n", s->cpu_index); - log_cpu_state(env, 0); - } - ccc->parent_reset(s); vr = env->pregs[PR_VR]; diff --git a/target-cris/cpu.h b/target-cris/cpu.h index dbd7d3687..c12a8caea 100644 --- a/target-cris/cpu.h +++ b/target-cris/cpu.h @@ -247,20 +247,6 @@ int cpu_cris_handle_mmu_fault(CPUCRISState *env, target_ulong address, int rw, int mmu_idx); #define cpu_handle_mmu_fault cpu_cris_handle_mmu_fault -#if defined(CONFIG_USER_ONLY) -static inline void cpu_clone_regs(CPUCRISState *env, target_ulong newsp) -{ - if (newsp) - env->regs[14] = newsp; - env->regs[10] = 0; -} -#endif - -static inline void cpu_set_tls(CPUCRISState *env, target_ulong newtls) -{ - env->pregs[PR_PID] = (env->pregs[PR_PID] & 0xff) | newtls; -} - /* Support function regs. */ #define SFR_RW_GC_CFG 0][0 #define SFR_RW_MM_CFG env->pregs[PR_SRS]][0 diff --git a/target-cris/translate.c b/target-cris/translate.c index 09d0d2b85..1de974395 100644 --- a/target-cris/translate.c +++ b/target-cris/translate.c @@ -3161,10 +3161,11 @@ static void check_breakpoint(CPUCRISState *env, DisasContext *dc) */ /* generate intermediate code for basic block 'tb'. */ -static void -gen_intermediate_code_internal(CPUCRISState *env, TranslationBlock *tb, - int search_pc) +static inline void +gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb, + bool search_pc) { + CPUCRISState *env = &cpu->env; uint16_t *gen_opc_end; uint32_t pc_start; unsigned int insn_len; @@ -3419,12 +3420,12 @@ gen_intermediate_code_internal(CPUCRISState *env, TranslationBlock *tb, void gen_intermediate_code (CPUCRISState *env, struct TranslationBlock *tb) { - gen_intermediate_code_internal(env, tb, 0); + gen_intermediate_code_internal(cris_env_get_cpu(env), tb, false); } void gen_intermediate_code_pc (CPUCRISState *env, struct TranslationBlock *tb) { - gen_intermediate_code_internal(env, tb, 1); + gen_intermediate_code_internal(cris_env_get_cpu(env), tb, true); } void cris_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c index 83898cd00..10dc2284b 100644 --- a/target-i386/arch_dump.c +++ b/target-i386/arch_dump.c @@ -35,7 +35,7 @@ typedef struct { } x86_64_elf_prstatus; static int x86_64_write_elf64_note(WriteCoreDumpFunction f, - CPUArchState *env, int id, + CPUX86State *env, int id, void *opaque) { x86_64_user_regs_struct regs; @@ -119,7 +119,7 @@ typedef struct { char pad3[4]; } x86_elf_prstatus; -static void x86_fill_elf_prstatus(x86_elf_prstatus *prstatus, CPUArchState *env, +static void x86_fill_elf_prstatus(x86_elf_prstatus *prstatus, CPUX86State *env, int id) { memset(prstatus, 0, sizeof(x86_elf_prstatus)); @@ -144,7 +144,7 @@ static void x86_fill_elf_prstatus(x86_elf_prstatus *prstatus, CPUArchState *env, prstatus->pid = id; } -static int x86_write_elf64_note(WriteCoreDumpFunction f, CPUArchState *env, +static int x86_write_elf64_note(WriteCoreDumpFunction f, CPUX86State *env, int id, void *opaque) { x86_elf_prstatus prstatus; @@ -185,7 +185,8 @@ int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, X86CPU *cpu = X86_CPU(cs); int ret; #ifdef TARGET_X86_64 - bool lma = !!(first_cpu->hflags & HF_LMA_MASK); + X86CPU *first_x86_cpu = X86_CPU(first_cpu); + bool lma = !!(first_x86_cpu->env.hflags & HF_LMA_MASK); if (lma) { ret = x86_64_write_elf64_note(f, &cpu->env, cpuid, opaque); @@ -273,7 +274,7 @@ static void copy_segment(QEMUCPUSegment *d, SegmentCache *s) d->base = s->base; } -static void qemu_get_cpustate(QEMUCPUState *s, CPUArchState *env) +static void qemu_get_cpustate(QEMUCPUState *s, CPUX86State *env) { memset(s, 0, sizeof(QEMUCPUState)); @@ -320,7 +321,7 @@ static void qemu_get_cpustate(QEMUCPUState *s, CPUArchState *env) } static inline int cpu_write_qemu_note(WriteCoreDumpFunction f, - CPUArchState *env, + CPUX86State *env, void *opaque, int type) { @@ -394,7 +395,9 @@ int cpu_get_dump_info(ArchDumpInfo *info) RAMBlock *block; #ifdef TARGET_X86_64 - lma = !!(first_cpu->hflags & HF_LMA_MASK); + X86CPU *first_x86_cpu = X86_CPU(first_cpu); + + lma = !!(first_x86_cpu->env.hflags & HF_LMA_MASK); #endif if (lma) { diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h index b7c70d6dd..7e55e5fd2 100644 --- a/target-i386/cpu-qom.h +++ b/target-i386/cpu-qom.h @@ -72,7 +72,7 @@ typedef struct X86CPU { static inline X86CPU *x86_env_get_cpu(CPUX86State *env) { - return X86_CPU(container_of(env, X86CPU, env)); + return container_of(env, X86CPU, env); } #define ENV_GET_CPU(e) CPU(x86_env_get_cpu(e)) diff --git a/target-i386/cpu.c b/target-i386/cpu.c index b7416fea3..e3f75a81a 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -2175,11 +2175,6 @@ static void x86_cpu_reset(CPUState *s) CPUX86State *env = &cpu->env; int i; - if (qemu_loglevel_mask(CPU_LOG_RESET)) { - qemu_log("CPU Reset (CPU %d)\n", s->cpu_index); - log_cpu_state(env, CPU_DUMP_FPU | CPU_DUMP_CCOP); - } - xcc->parent_reset(s); @@ -2523,6 +2518,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data) xcc->parent_reset = cc->reset; cc->reset = x86_cpu_reset; + cc->reset_dump_flags = CPU_DUMP_FPU | CPU_DUMP_CCOP; cc->do_interrupt = x86_cpu_do_interrupt; cc->dump_state = x86_cpu_dump_state; diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 62e354731..2d005b3ce 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -1125,15 +1125,6 @@ static inline target_long lshift(target_long x, int n) /* translate.c */ void optimize_flags_init(void); -#if defined(CONFIG_USER_ONLY) -static inline void cpu_clone_regs(CPUX86State *env, target_ulong newsp) -{ - if (newsp) - env->regs[R_ESP] = newsp; - env->regs[R_EAX] = 0; -} -#endif - #include "exec/cpu-all.h" #include "svm.h" @@ -1229,7 +1220,7 @@ void cpu_vmexit(CPUX86State *nenv, uint32_t exit_code, uint64_t exit_info_1); /* seg_helper.c */ void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw); -void do_smm_enter(CPUX86State *env1); +void do_smm_enter(X86CPU *cpu); void cpu_report_tpr_access(CPUX86State *env, TPRAccess access); diff --git a/target-i386/helper.c b/target-i386/helper.c index 5e5abe3b8..d6f43d7a2 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1188,6 +1188,7 @@ void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank, uint64_t status, uint64_t mcg_status, uint64_t addr, uint64_t misc, int flags) { + CPUState *cs = CPU(cpu); CPUX86State *cenv = &cpu->env; MCEInjectionParams params = { .mon = mon, @@ -1200,7 +1201,6 @@ void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank, .flags = flags, }; unsigned bank_num = cenv->mcg_cap & 0xff; - CPUX86State *env; if (!cenv->mcg_cap) { monitor_printf(mon, "MCE injection not supported\n"); @@ -1220,19 +1220,22 @@ void cpu_x86_inject_mce(Monitor *mon, X86CPU *cpu, int bank, return; } - run_on_cpu(CPU(cpu), do_inject_x86_mce, ¶ms); + run_on_cpu(cs, do_inject_x86_mce, ¶ms); if (flags & MCE_INJECT_BROADCAST) { + CPUState *other_cs; + params.bank = 1; params.status = MCI_STATUS_VAL | MCI_STATUS_UC; params.mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV; params.addr = 0; params.misc = 0; - for (env = first_cpu; env != NULL; env = env->next_cpu) { - if (cenv == env) { + for (other_cs = first_cpu; other_cs != NULL; + other_cs = other_cs->next_cpu) { + if (other_cs == cs) { continue; } - params.cpu = x86_env_get_cpu(env); - run_on_cpu(CPU(cpu), do_inject_x86_mce, ¶ms); + params.cpu = X86_CPU(other_cs); + run_on_cpu(other_cs, do_inject_x86_mce, ¶ms); } } } diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 39f4fbb3c..831548998 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -318,7 +318,7 @@ int kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr) if ((env->mcg_cap & MCG_SER_P) && addr && (code == BUS_MCEERR_AR || code == BUS_MCEERR_AO)) { - if (qemu_ram_addr_from_host(addr, &ram_addr) || + if (qemu_ram_addr_from_host(addr, &ram_addr) == NULL || !kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) { fprintf(stderr, "Hardware memory error for memory used by " "QEMU itself instead of guest system!\n"); @@ -345,20 +345,22 @@ int kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr) int kvm_arch_on_sigbus(int code, void *addr) { - if ((first_cpu->mcg_cap & MCG_SER_P) && addr && code == BUS_MCEERR_AO) { + X86CPU *cpu = X86_CPU(first_cpu); + + if ((cpu->env.mcg_cap & MCG_SER_P) && addr && code == BUS_MCEERR_AO) { ram_addr_t ram_addr; hwaddr paddr; /* Hope we are lucky for AO MCE */ - if (qemu_ram_addr_from_host(addr, &ram_addr) || - !kvm_physical_memory_addr_from_host(CPU(first_cpu)->kvm_state, + if (qemu_ram_addr_from_host(addr, &ram_addr) == NULL || + !kvm_physical_memory_addr_from_host(first_cpu->kvm_state, addr, &paddr)) { fprintf(stderr, "Hardware memory error for memory used by " "QEMU itself instead of guest system!: %p\n", addr); return 0; } kvm_hwpoison_page_add(ram_addr); - kvm_mce_inject(x86_env_get_cpu(first_cpu), paddr, code); + kvm_mce_inject(X86_CPU(first_cpu), paddr, code); } else { if (code == BUS_MCEERR_AO) { return 0; @@ -741,7 +743,6 @@ static int kvm_get_supported_msrs(KVMState *s) int kvm_arch_init(KVMState *s) { - QemuOptsList *list = qemu_find_opts("machine"); uint64_t identity_base = 0xfffbc000; uint64_t shadow_mem; int ret; @@ -790,15 +791,13 @@ int kvm_arch_init(KVMState *s) } qemu_register_reset(kvm_unpoison_all, NULL); - if (!QTAILQ_EMPTY(&list->head)) { - shadow_mem = qemu_opt_get_size(QTAILQ_FIRST(&list->head), - "kvm_shadow_mem", -1); - if (shadow_mem != -1) { - shadow_mem /= 4096; - ret = kvm_vm_ioctl(s, KVM_SET_NR_MMU_PAGES, shadow_mem); - if (ret < 0) { - return ret; - } + shadow_mem = qemu_opt_get_size(qemu_get_machine_opts(), + "kvm_shadow_mem", -1); + if (shadow_mem != -1) { + shadow_mem /= 4096; + ret = kvm_vm_ioctl(s, KVM_SET_NR_MMU_PAGES, shadow_mem); + if (ret < 0) { + return ret; } } return 0; diff --git a/target-i386/misc_helper.c b/target-i386/misc_helper.c index e345f9a1e..957926ced 100644 --- a/target-i386/misc_helper.c +++ b/target-i386/misc_helper.c @@ -610,7 +610,7 @@ void helper_mwait(CPUX86State *env, int next_eip_addend) cpu = x86_env_get_cpu(env); cs = CPU(cpu); /* XXX: not complete but not completely erroneous */ - if (cs->cpu_index != 0 || env->next_cpu != NULL) { + if (cs->cpu_index != 0 || cs->next_cpu != NULL) { /* more than one CPU: do not sleep because another CPU may wake this one */ } else { diff --git a/target-i386/seg_helper.c b/target-i386/seg_helper.c index 9c799e100..e78910200 100644 --- a/target-i386/seg_helper.c +++ b/target-i386/seg_helper.c @@ -30,11 +30,11 @@ #ifdef DEBUG_PCALL # define LOG_PCALL(...) qemu_log_mask(CPU_LOG_PCALL, ## __VA_ARGS__) -# define LOG_PCALL_STATE(env) \ - log_cpu_state_mask(CPU_LOG_PCALL, (env), CPU_DUMP_CCOP) +# define LOG_PCALL_STATE(cpu) \ + log_cpu_state_mask(CPU_LOG_PCALL, (cpu), CPU_DUMP_CCOP) #else # define LOG_PCALL(...) do { } while (0) -# define LOG_PCALL_STATE(env) do { } while (0) +# define LOG_PCALL_STATE(cpu) do { } while (0) #endif /* return non zero if error */ @@ -1160,9 +1160,11 @@ static void handle_even_inj(CPUX86State *env, int intno, int is_int, * the int instruction. next_eip is the env->eip value AFTER the interrupt * instruction. It is only relevant if is_int is TRUE. */ -static void do_interrupt_all(CPUX86State *env, int intno, int is_int, +static void do_interrupt_all(X86CPU *cpu, int intno, int is_int, int error_code, target_ulong next_eip, int is_hw) { + CPUX86State *env = &cpu->env; + if (qemu_loglevel_mask(CPU_LOG_INT)) { if ((env->cr[0] & CR0_PE_MASK)) { static int count; @@ -1180,7 +1182,7 @@ static void do_interrupt_all(CPUX86State *env, int intno, int is_int, qemu_log(" env->regs[R_EAX]=" TARGET_FMT_lx, env->regs[R_EAX]); } qemu_log("\n"); - log_cpu_state(env, CPU_DUMP_CCOP); + log_cpu_state(CPU(cpu), CPU_DUMP_CCOP); #if 0 { int i; @@ -1252,7 +1254,7 @@ void x86_cpu_do_interrupt(CPUState *cs) /* simulate a real cpu exception. On i386, it can trigger new exceptions, but we do not handle double or triple faults yet. */ - do_interrupt_all(env, env->exception_index, + do_interrupt_all(cpu, env->exception_index, env->exception_is_int, env->error_code, env->exception_next_eip, 0); @@ -1263,7 +1265,7 @@ void x86_cpu_do_interrupt(CPUState *cs) void do_interrupt_x86_hardirq(CPUX86State *env, int intno, int is_hw) { - do_interrupt_all(env, intno, 0, 0, 0, is_hw); + do_interrupt_all(x86_env_get_cpu(env), intno, 0, 0, 0, is_hw); } void helper_enter_level(CPUX86State *env, int level, int data32, @@ -1684,7 +1686,7 @@ void helper_lcall_protected(CPUX86State *env, int new_cs, target_ulong new_eip, next_eip = env->eip + next_eip_addend; LOG_PCALL("lcall %04x:%08x s=%d\n", new_cs, (uint32_t)new_eip, shift); - LOG_PCALL_STATE(env); + LOG_PCALL_STATE(CPU(x86_env_get_cpu(env))); if ((new_cs & 0xfffc) == 0) { raise_exception_err(env, EXCP0D_GPF, 0); } @@ -2018,7 +2020,7 @@ static inline void helper_ret_protected(CPUX86State *env, int shift, } LOG_PCALL("lret new %04x:" TARGET_FMT_lx " s=%d addend=0x%x\n", new_cs, new_eip, shift, addend); - LOG_PCALL_STATE(env); + LOG_PCALL_STATE(CPU(x86_env_get_cpu(env))); if ((new_cs & 0xfffc) == 0) { raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc); } diff --git a/target-i386/smm_helper.c b/target-i386/smm_helper.c index 248957337..6cb45511b 100644 --- a/target-i386/smm_helper.c +++ b/target-i386/smm_helper.c @@ -24,7 +24,7 @@ #if defined(CONFIG_USER_ONLY) -void do_smm_enter(CPUX86State *env) +void do_smm_enter(X86CPU *cpu) { } @@ -40,14 +40,15 @@ void helper_rsm(CPUX86State *env) #define SMM_REVISION_ID 0x00020000 #endif -void do_smm_enter(CPUX86State *env) +void do_smm_enter(X86CPU *cpu) { + CPUX86State *env = &cpu->env; target_ulong sm_state; SegmentCache *dt; int i, offset; qemu_log_mask(CPU_LOG_INT, "SMM: enter\n"); - log_cpu_state_mask(CPU_LOG_INT, env, CPU_DUMP_CCOP); + log_cpu_state_mask(CPU_LOG_INT, CPU(cpu), CPU_DUMP_CCOP); env->hflags |= HF_SMM_MASK; cpu_smm_update(env); @@ -179,6 +180,7 @@ void do_smm_enter(CPUX86State *env) void helper_rsm(CPUX86State *env) { + X86CPU *cpu = x86_env_get_cpu(env); target_ulong sm_state; int i, offset; uint32_t val; @@ -295,7 +297,7 @@ void helper_rsm(CPUX86State *env) cpu_smm_update(env); qemu_log_mask(CPU_LOG_INT, "SMM: after RSM\n"); - log_cpu_state_mask(CPU_LOG_INT, env, CPU_DUMP_CCOP); + log_cpu_state_mask(CPU_LOG_INT, CPU(cpu), CPU_DUMP_CCOP); } #endif /* !CONFIG_USER_ONLY */ diff --git a/target-i386/translate.c b/target-i386/translate.c index 14b029874..6550c2779 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -8251,10 +8251,11 @@ void optimize_flags_init(void) /* generate intermediate code in gen_opc_buf and gen_opparam_buf for basic block 'tb'. If search_pc is TRUE, also generate PC information for each intermediate instruction. */ -static inline void gen_intermediate_code_internal(CPUX86State *env, +static inline void gen_intermediate_code_internal(X86CPU *cpu, TranslationBlock *tb, - int search_pc) + bool search_pc) { + CPUX86State *env = &cpu->env; DisasContext dc1, *dc = &dc1; target_ulong pc_ptr; uint16_t *gen_opc_end; @@ -8428,12 +8429,12 @@ static inline void gen_intermediate_code_internal(CPUX86State *env, void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb) { - gen_intermediate_code_internal(env, tb, 0); + gen_intermediate_code_internal(x86_env_get_cpu(env), tb, false); } void gen_intermediate_code_pc(CPUX86State *env, TranslationBlock *tb) { - gen_intermediate_code_internal(env, tb, 1); + gen_intermediate_code_internal(x86_env_get_cpu(env), tb, true); } void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb, int pc_pos) diff --git a/target-lm32/cpu-qom.h b/target-lm32/cpu-qom.h index 5ef884b97..e3bb619dc 100644 --- a/target-lm32/cpu-qom.h +++ b/target-lm32/cpu-qom.h @@ -64,7 +64,7 @@ typedef struct LM32CPU { static inline LM32CPU *lm32_env_get_cpu(CPULM32State *env) { - return LM32_CPU(container_of(env, LM32CPU, env)); + return container_of(env, LM32CPU, env); } #define ENV_GET_CPU(e) CPU(lm32_env_get_cpu(e)) diff --git a/target-lm32/cpu.c b/target-lm32/cpu.c index 02f8436bf..04327acc0 100644 --- a/target-lm32/cpu.c +++ b/target-lm32/cpu.c @@ -29,11 +29,6 @@ static void lm32_cpu_reset(CPUState *s) LM32CPUClass *lcc = LM32_CPU_GET_CLASS(cpu); CPULM32State *env = &cpu->env; - if (qemu_loglevel_mask(CPU_LOG_RESET)) { - qemu_log("CPU Reset (CPU %d)\n", s->cpu_index); - log_cpu_state(env, 0); - } - lcc->parent_reset(s); /* reset cpu state */ diff --git a/target-lm32/cpu.h b/target-lm32/cpu.h index bfb915058..856bdc745 100644 --- a/target-lm32/cpu.h +++ b/target-lm32/cpu.h @@ -215,20 +215,6 @@ int cpu_lm32_handle_mmu_fault(CPULM32State *env, target_ulong address, int rw, int mmu_idx); #define cpu_handle_mmu_fault cpu_lm32_handle_mmu_fault -#if defined(CONFIG_USER_ONLY) -static inline void cpu_clone_regs(CPULM32State *env, target_ulong newsp) -{ - if (newsp) { - env->regs[R_SP] = newsp; - } - env->regs[R_R1] = 0; -} -#endif - -static inline void cpu_set_tls(CPULM32State *env, target_ulong newtls) -{ -} - #include "exec/cpu-all.h" static inline void cpu_get_tb_cpu_state(CPULM32State *env, target_ulong *pc, diff --git a/target-lm32/helper.c b/target-lm32/helper.c index 03fa5fbe2..615b44e5b 100644 --- a/target-lm32/helper.c +++ b/target-lm32/helper.c @@ -70,7 +70,7 @@ void lm32_cpu_do_interrupt(CPUState *cs) } else { env->pc = env->eba + (env->exception_index * 32); } - log_cpu_state_mask(CPU_LOG_INT, env, 0); + log_cpu_state_mask(CPU_LOG_INT, cs, 0); break; case EXCP_BREAKPOINT: case EXCP_WATCHPOINT: @@ -79,7 +79,7 @@ void lm32_cpu_do_interrupt(CPUState *cs) env->ie |= (env->ie & IE_IE) ? IE_BIE : 0; env->ie &= ~IE_IE; env->pc = env->deba + (env->exception_index * 32); - log_cpu_state_mask(CPU_LOG_INT, env, 0); + log_cpu_state_mask(CPU_LOG_INT, cs, 0); break; default: cpu_abort(env, "unhandled exception type=%d\n", diff --git a/target-lm32/translate.c b/target-lm32/translate.c index 227a8015f..ed12f5074 100644 --- a/target-lm32/translate.c +++ b/target-lm32/translate.c @@ -1011,9 +1011,11 @@ static void check_breakpoint(CPULM32State *env, DisasContext *dc) } /* generate intermediate code for basic block 'tb'. */ -static void gen_intermediate_code_internal(CPULM32State *env, - TranslationBlock *tb, int search_pc) +static inline +void gen_intermediate_code_internal(LM32CPU *cpu, + TranslationBlock *tb, bool search_pc) { + CPULM32State *env = &cpu->env; struct DisasContext ctx, *dc = &ctx; uint16_t *gen_opc_end; uint32_t pc_start; @@ -1133,12 +1135,12 @@ static void gen_intermediate_code_internal(CPULM32State *env, void gen_intermediate_code(CPULM32State *env, struct TranslationBlock *tb) { - gen_intermediate_code_internal(env, tb, 0); + gen_intermediate_code_internal(lm32_env_get_cpu(env), tb, false); } void gen_intermediate_code_pc(CPULM32State *env, struct TranslationBlock *tb) { - gen_intermediate_code_internal(env, tb, 1); + gen_intermediate_code_internal(lm32_env_get_cpu(env), tb, true); } void lm32_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, diff --git a/target-m68k/cpu-qom.h b/target-m68k/cpu-qom.h index 2436c13c5..858bf3008 100644 --- a/target-m68k/cpu-qom.h +++ b/target-m68k/cpu-qom.h @@ -63,7 +63,7 @@ typedef struct M68kCPU { static inline M68kCPU *m68k_env_get_cpu(CPUM68KState *env) { - return M68K_CPU(container_of(env, M68kCPU, env)); + return container_of(env, M68kCPU, env); } #define ENV_GET_CPU(e) CPU(m68k_env_get_cpu(e)) diff --git a/target-m68k/cpu.c b/target-m68k/cpu.c index 799869ff9..1b6ef664f 100644 --- a/target-m68k/cpu.c +++ b/target-m68k/cpu.c @@ -35,11 +35,6 @@ static void m68k_cpu_reset(CPUState *s) M68kCPUClass *mcc = M68K_CPU_GET_CLASS(cpu); CPUM68KState *env = &cpu->env; - if (qemu_loglevel_mask(CPU_LOG_RESET)) { - qemu_log("CPU Reset (CPU %d)\n", s->cpu_index); - log_cpu_state(env, 0); - } - mcc->parent_reset(s); memset(env, 0, offsetof(CPUM68KState, breakpoints)); diff --git a/target-m68k/cpu.h b/target-m68k/cpu.h index c90c40c37..9fdf89ef9 100644 --- a/target-m68k/cpu.h +++ b/target-m68k/cpu.h @@ -241,15 +241,6 @@ int cpu_m68k_handle_mmu_fault(CPUM68KState *env, target_ulong address, int rw, int mmu_idx); #define cpu_handle_mmu_fault cpu_m68k_handle_mmu_fault -#if defined(CONFIG_USER_ONLY) -static inline void cpu_clone_regs(CPUM68KState *env, target_ulong newsp) -{ - if (newsp) - env->aregs[7] = newsp; - env->dregs[0] = 0; -} -#endif - #include "exec/cpu-all.h" static inline void cpu_get_tb_cpu_state(CPUM68KState *env, target_ulong *pc, diff --git a/target-m68k/translate.c b/target-m68k/translate.c index 375209404..2d73af50c 100644 --- a/target-m68k/translate.c +++ b/target-m68k/translate.c @@ -2971,9 +2971,10 @@ static void disas_m68k_insn(CPUM68KState * env, DisasContext *s) /* generate intermediate code for basic block 'tb'. */ static inline void -gen_intermediate_code_internal(CPUM68KState *env, TranslationBlock *tb, - int search_pc) +gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb, + bool search_pc) { + CPUM68KState *env = &cpu->env; DisasContext dc1, *dc = &dc1; uint16_t *gen_opc_end; CPUBreakpoint *bp; @@ -3096,12 +3097,12 @@ gen_intermediate_code_internal(CPUM68KState *env, TranslationBlock *tb, void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb) { - gen_intermediate_code_internal(env, tb, 0); + gen_intermediate_code_internal(m68k_env_get_cpu(env), tb, false); } void gen_intermediate_code_pc(CPUM68KState *env, TranslationBlock *tb) { - gen_intermediate_code_internal(env, tb, 1); + gen_intermediate_code_internal(m68k_env_get_cpu(env), tb, true); } void m68k_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, diff --git a/target-microblaze/cpu-qom.h b/target-microblaze/cpu-qom.h index 3e9c20668..ec2b989a2 100644 --- a/target-microblaze/cpu-qom.h +++ b/target-microblaze/cpu-qom.h @@ -64,7 +64,7 @@ typedef struct MicroBlazeCPU { static inline MicroBlazeCPU *mb_env_get_cpu(CPUMBState *env) { - return MICROBLAZE_CPU(container_of(env, MicroBlazeCPU, env)); + return container_of(env, MicroBlazeCPU, env); } #define ENV_GET_CPU(e) CPU(mb_env_get_cpu(e)) diff --git a/target-microblaze/cpu.c b/target-microblaze/cpu.c index a0fcdf446..dce1c7ea6 100644 --- a/target-microblaze/cpu.c +++ b/target-microblaze/cpu.c @@ -33,11 +33,6 @@ static void mb_cpu_reset(CPUState *s) MicroBlazeCPUClass *mcc = MICROBLAZE_CPU_GET_CLASS(cpu); CPUMBState *env = &cpu->env; - if (qemu_loglevel_mask(CPU_LOG_RESET)) { - qemu_log("CPU Reset (CPU %d)\n", s->cpu_index); - log_cpu_state(env, 0); - } - mcc->parent_reset(s); memset(env, 0, offsetof(CPUMBState, breakpoints)); diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h index 75ae5baf3..6c35475fd 100644 --- a/target-microblaze/cpu.h +++ b/target-microblaze/cpu.h @@ -331,20 +331,6 @@ int cpu_mb_handle_mmu_fault(CPUMBState *env, target_ulong address, int rw, int mmu_idx); #define cpu_handle_mmu_fault cpu_mb_handle_mmu_fault -#if defined(CONFIG_USER_ONLY) -static inline void cpu_clone_regs(CPUMBState *env, target_ulong newsp) -{ - if (newsp) - env->regs[R_SP] = newsp; - env->regs[3] = 0; -} -#endif - -static inline void cpu_set_tls(CPUMBState *env, target_ulong newtls) -{ - env->regs[21] = newtls; -} - static inline int cpu_interrupts_enabled(CPUMBState *env) { return env->sregs[SR_MSR] & MSR_IE; diff --git a/target-microblaze/helper.c b/target-microblaze/helper.c index 01d4bbfe9..c6c96d448 100644 --- a/target-microblaze/helper.c +++ b/target-microblaze/helper.c @@ -152,7 +152,7 @@ void mb_cpu_do_interrupt(CPUState *cs) "hw exception at pc=%x ear=%x esr=%x iflags=%x\n", env->sregs[SR_PC], env->sregs[SR_EAR], env->sregs[SR_ESR], env->iflags); - log_cpu_state_mask(CPU_LOG_INT, env, 0); + log_cpu_state_mask(CPU_LOG_INT, cs, 0); env->iflags &= ~(IMM_FLAG | D_FLAG); env->sregs[SR_PC] = cpu->base_vectors + 0x20; break; @@ -175,7 +175,7 @@ void mb_cpu_do_interrupt(CPUState *cs) "bimm exception at pc=%x iflags=%x\n", env->sregs[SR_PC], env->iflags); env->regs[17] -= 4; - log_cpu_state_mask(CPU_LOG_INT, env, 0); + log_cpu_state_mask(CPU_LOG_INT, cs, 0); } } else if (env->iflags & IMM_FLAG) { D(qemu_log("IMM_FLAG set at exception\n")); @@ -192,7 +192,7 @@ void mb_cpu_do_interrupt(CPUState *cs) qemu_log_mask(CPU_LOG_INT, "exception at pc=%x ear=%x iflags=%x\n", env->sregs[SR_PC], env->sregs[SR_EAR], env->iflags); - log_cpu_state_mask(CPU_LOG_INT, env, 0); + log_cpu_state_mask(CPU_LOG_INT, cs, 0); env->iflags &= ~(IMM_FLAG | D_FLAG); env->sregs[SR_PC] = cpu->base_vectors + 0x20; break; @@ -222,7 +222,7 @@ void mb_cpu_do_interrupt(CPUState *cs) env->sregs[SR_PC], env->sregs[SR_MSR], t, env->iflags, sym); - log_cpu_state(env, 0); + log_cpu_state(cs, 0); } } #endif @@ -236,7 +236,7 @@ void mb_cpu_do_interrupt(CPUState *cs) env->regs[14] = env->sregs[SR_PC]; env->sregs[SR_PC] = cpu->base_vectors + 0x10; - //log_cpu_state_mask(CPU_LOG_INT, env, 0); + //log_cpu_state_mask(CPU_LOG_INT, cs, 0); break; case EXCP_BREAK: @@ -247,7 +247,7 @@ void mb_cpu_do_interrupt(CPUState *cs) qemu_log_mask(CPU_LOG_INT, "break at pc=%x msr=%x %x iflags=%x\n", env->sregs[SR_PC], env->sregs[SR_MSR], t, env->iflags); - log_cpu_state_mask(CPU_LOG_INT, env, 0); + log_cpu_state_mask(CPU_LOG_INT, cs, 0); env->sregs[SR_MSR] &= ~(MSR_VMS | MSR_UMS | MSR_VM | MSR_UM); env->sregs[SR_MSR] |= t; env->sregs[SR_MSR] |= MSR_BIP; diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c index 54f439fc2..eba255b7c 100644 --- a/target-microblaze/translate.c +++ b/target-microblaze/translate.c @@ -1737,10 +1737,11 @@ static void check_breakpoint(CPUMBState *env, DisasContext *dc) } /* generate intermediate code for basic block 'tb'. */ -static void -gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb, - int search_pc) +static inline void +gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb, + bool search_pc) { + CPUMBState *env = &cpu->env; uint16_t *gen_opc_end; uint32_t pc_start; int j, lj; @@ -1776,7 +1777,7 @@ gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb, if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { #if !SIM_COMPAT qemu_log("--------------\n"); - log_cpu_state(env, 0); + log_cpu_state(CPU(cpu), 0); #endif } @@ -1941,12 +1942,12 @@ gen_intermediate_code_internal(CPUMBState *env, TranslationBlock *tb, void gen_intermediate_code (CPUMBState *env, struct TranslationBlock *tb) { - gen_intermediate_code_internal(env, tb, 0); + gen_intermediate_code_internal(mb_env_get_cpu(env), tb, false); } void gen_intermediate_code_pc (CPUMBState *env, struct TranslationBlock *tb) { - gen_intermediate_code_internal(env, tb, 1); + gen_intermediate_code_internal(mb_env_get_cpu(env), tb, true); } void mb_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf, diff --git a/target-mips/cpu-qom.h b/target-mips/cpu-qom.h index a7ff9e6ee..654744a45 100644 --- a/target-mips/cpu-qom.h +++ b/target-mips/cpu-qom.h @@ -67,7 +67,7 @@ typedef struct MIPSCPU { static inline MIPSCPU *mips_env_get_cpu(CPUMIPSState *env) { - return MIPS_CPU(container_of(env, MIPSCPU, env)); + return container_of(env, MIPSCPU, env); } #define ENV_GET_CPU(e) CPU(mips_env_get_cpu(e)) diff --git a/target-mips/cpu.c b/target-mips/cpu.c index b61e20731..60a3faf2f 100644 --- a/target-mips/cpu.c +++ b/target-mips/cpu.c @@ -29,11 +29,6 @@ static void mips_cpu_reset(CPUState *s) MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(cpu); CPUMIPSState *env = &cpu->env; - if (qemu_loglevel_mask(CPU_LOG_RESET)) { - qemu_log("CPU Reset (CPU %d)\n", s->cpu_index); - log_cpu_state(env, 0); - } - mcc->parent_reset(s); memset(env, 0, offsetof(CPUMIPSState, breakpoints)); diff --git a/target-mips/cpu.h b/target-mips/cpu.h index fa0f0d157..7ffd2e36b 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -521,14 +521,6 @@ static inline int cpu_mmu_index (CPUMIPSState *env) return env->hflags & MIPS_HFLAG_KSU; } -static inline void cpu_clone_regs(CPUMIPSState *env, target_ulong newsp) -{ - if (newsp) - env->active_tc.gpr[29] = newsp; - env->active_tc.gpr[7] = 0; - env->active_tc.gpr[2] = 0; -} - static inline int cpu_mips_hw_interrupts_pending(CPUMIPSState *env) { int32_t pending; @@ -679,11 +671,6 @@ static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc, *flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK); } -static inline void cpu_set_tls(CPUMIPSState *env, target_ulong newtls) -{ - env->tls_value = newtls; -} - static inline int mips_vpe_active(CPUMIPSState *env) { int active = 1; diff --git a/target-mips/helper.c b/target-mips/helper.c index 36929ddee..6983b92a1 100644 --- a/target-mips/helper.c +++ b/target-mips/helper.c @@ -276,7 +276,7 @@ int cpu_mips_handle_mmu_fault (CPUMIPSState *env, target_ulong address, int rw, int ret = 0; #if 0 - log_cpu_state(env, 0); + log_cpu_state(CPU(mips_env_get_cpu(env)), 0); #endif qemu_log("%s pc " TARGET_FMT_lx " ad " TARGET_FMT_lx " rw %d mmu_idx %d\n", __func__, env->active_tc.PC, address, rw, mmu_idx); diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c index f6838ecd5..5cf1c3f04 100644 --- a/target-mips/op_helper.c +++ b/target-mips/op_helper.c @@ -1696,39 +1696,38 @@ target_ulong helper_emt(void) target_ulong helper_dvpe(CPUMIPSState *env) { - CPUMIPSState *other_cpu_env = first_cpu; + CPUState *other_cs = first_cpu; target_ulong prev = env->mvp->CP0_MVPControl; do { + MIPSCPU *other_cpu = MIPS_CPU(other_cs); /* Turn off all VPEs except the one executing the dvpe. */ - if (other_cpu_env != env) { - MIPSCPU *other_cpu = mips_env_get_cpu(other_cpu_env); - - other_cpu_env->mvp->CP0_MVPControl &= ~(1 << CP0MVPCo_EVP); + if (&other_cpu->env != env) { + other_cpu->env.mvp->CP0_MVPControl &= ~(1 << CP0MVPCo_EVP); mips_vpe_sleep(other_cpu); } - other_cpu_env = other_cpu_env->next_cpu; - } while (other_cpu_env); + other_cs = other_cs->next_cpu; + } while (other_cs); return prev; } target_ulong helper_evpe(CPUMIPSState *env) { - CPUMIPSState *other_cpu_env = first_cpu; + CPUState *other_cs = first_cpu; target_ulong prev = env->mvp->CP0_MVPControl; do { - MIPSCPU *other_cpu = mips_env_get_cpu(other_cpu_env); + MIPSCPU *other_cpu = MIPS_CPU(other_cs); - if (other_cpu_env != env + if (&other_cpu->env != env /* If the VPE is WFI, don't disturb its sleep. */ && !mips_vpe_is_wfi(other_cpu)) { /* Enable the VPE. */ - other_cpu_env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP); + other_cpu->env.mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP); mips_vpe_wake(other_cpu); /* And wake it up. */ } - other_cpu_env = other_cpu_env->next_cpu; - } while (other_cpu_env); + other_cs = other_cs->next_cpu; + } while (other_cs); return prev; } #endif /* !CONFIG_USER_ONLY */ diff --git a/target-mips/translate.c b/target-mips/translate.c index 160c0c092..8246c200a 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -15540,9 +15540,10 @@ static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch) } static inline void -gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb, - int search_pc) +gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb, + bool search_pc) { + CPUMIPSState *env = &cpu->env; DisasContext ctx; target_ulong pc_start; uint16_t *gen_opc_end; @@ -15698,12 +15699,12 @@ done_generating: void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb) { - gen_intermediate_code_internal(env, tb, 0); + gen_intermediate_code_internal(mips_env_get_cpu(env), tb, false); } void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb) { - gen_intermediate_code_internal(env, tb, 1); + gen_intermediate_code_internal(mips_env_get_cpu(env), tb, true); } static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf, diff --git a/target-moxie/cpu.c b/target-moxie/cpu.c index f3c0d2214..92ca5946b 100644 --- a/target-moxie/cpu.c +++ b/target-moxie/cpu.c @@ -28,11 +28,6 @@ static void moxie_cpu_reset(CPUState *s) MoxieCPUClass *mcc = MOXIE_CPU_GET_CLASS(cpu); CPUMoxieState *env = &cpu->env; - if (qemu_loglevel_mask(CPU_LOG_RESET)) { - qemu_log("CPU Reset (CPU %d)\n", s->cpu_index); - log_cpu_state(env, 0); - } - mcc->parent_reset(s); memset(env, 0, offsetof(CPUMoxieState, breakpoints)); diff --git a/target-moxie/cpu.h b/target-moxie/cpu.h index 374b24af5..72d02c20c 100644 --- a/target-moxie/cpu.h +++ b/target-moxie/cpu.h @@ -106,7 +106,7 @@ typedef struct MoxieCPU { static inline MoxieCPU *moxie_env_get_cpu(CPUMoxieState *env) { - return MOXIE_CPU(container_of(env, MoxieCPU, env)); + return container_of(env, MoxieCPU, env); } #define ENV_GET_CPU(e) CPU(moxie_env_get_cpu(e)) diff --git a/target-moxie/translate.c b/target-moxie/translate.c index b0ae38a4d..664d35943 100644 --- a/target-moxie/translate.c +++ b/target-moxie/translate.c @@ -820,7 +820,7 @@ static int decode_opc(MoxieCPU *cpu, DisasContext *ctx) } /* generate intermediate code for basic block 'tb'. */ -static void +static inline void gen_intermediate_code_internal(MoxieCPU *cpu, TranslationBlock *tb, bool search_pc) { diff --git a/target-openrisc/cpu.c b/target-openrisc/cpu.c index fd90d370b..6d40f1b85 100644 --- a/target-openrisc/cpu.c +++ b/target-openrisc/cpu.c @@ -26,11 +26,6 @@ static void openrisc_cpu_reset(CPUState *s) OpenRISCCPU *cpu = OPENRISC_CPU(s); OpenRISCCPUClass *occ = OPENRISC_CPU_GET_CLASS(cpu); - if (qemu_loglevel_mask(CPU_LOG_RESET)) { - qemu_log("CPU Reset (CPU %d)\n", s->cpu_index); - log_cpu_state(&cpu->env, 0); - } - occ->parent_reset(s); memset(&cpu->env, 0, offsetof(CPUOpenRISCState, breakpoints)); @@ -96,12 +91,14 @@ static void openrisc_cpu_initfn(Object *obj) static ObjectClass *openrisc_cpu_class_by_name(const char *cpu_model) { ObjectClass *oc; + char *typename; if (cpu_model == NULL) { return NULL; } - oc = object_class_by_name(cpu_model); + typename = g_strdup_printf("%s-" TYPE_OPENRISC_CPU, cpu_model); + oc = object_class_by_name(typename); if (oc != NULL && (!object_class_dynamic_cast(oc, TYPE_OPENRISC_CPU) || object_class_is_abstract(oc))) { return NULL; diff --git a/target-openrisc/cpu.h b/target-openrisc/cpu.h index 80a82dfdd..0aff8f20c 100644 --- a/target-openrisc/cpu.h +++ b/target-openrisc/cpu.h @@ -335,7 +335,7 @@ typedef struct OpenRISCCPU { static inline OpenRISCCPU *openrisc_env_get_cpu(CPUOpenRISCState *env) { - return OPENRISC_CPU(container_of(env, OpenRISCCPU, env)); + return container_of(env, OpenRISCCPU, env); } #define ENV_GET_CPU(e) CPU(openrisc_env_get_cpu(e)) @@ -394,16 +394,6 @@ static inline CPUOpenRISCState *cpu_init(const char *cpu_model) return NULL; } -#if defined(CONFIG_USER_ONLY) -static inline void cpu_clone_regs(CPUOpenRISCState *env, target_ulong newsp) -{ - if (newsp) { - env->gpr[1] = newsp; - } - env->gpr[2] = 0; -} -#endif - #include "exec/cpu-all.h" static inline void cpu_get_tb_cpu_state(CPUOpenRISCState *env, diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c index c59fd0208..f222834fc 100644 --- a/target-openrisc/translate.c +++ b/target-openrisc/translate.c @@ -1684,7 +1684,7 @@ static inline void gen_intermediate_code_internal(OpenRISCCPU *cpu, dc->singlestep_enabled = cpu->env.singlestep_enabled; if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) { qemu_log("-----------------------------------------\n"); - log_cpu_state(&cpu->env, 0); + log_cpu_state(CPU(cpu), 0); } next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; diff --git a/target-ppc/cpu-models.c b/target-ppc/cpu-models.c index 9bb68c819..9578ed889 100644 --- a/target-ppc/cpu-models.c +++ b/target-ppc/cpu-models.c @@ -792,17 +792,15 @@ POWERPC_DEF_SVR("MPC8572E", "MPC8572E", CPU_POWERPC_MPC8572E, POWERPC_SVR_8572E, e500v2) /* e600 family */ - POWERPC_DEF("e600", CPU_POWERPC_e600, 7400, + POWERPC_DEF("e600", CPU_POWERPC_e600, e600, "PowerPC e600 core") /* PowerPC e600 microcontrollers */ -#if defined(TODO) POWERPC_DEF_SVR("MPC8610", "MPC8610", - CPU_POWERPC_MPC8610, POWERPC_SVR_8610, 7400) -#endif + CPU_POWERPC_MPC8610, POWERPC_SVR_8610, e600) POWERPC_DEF_SVR("MPC8641", "MPC8641", - CPU_POWERPC_MPC8641, POWERPC_SVR_8641, 7400) + CPU_POWERPC_MPC8641, POWERPC_SVR_8641, e600) POWERPC_DEF_SVR("MPC8641D", "MPC8641D", - CPU_POWERPC_MPC8641D, POWERPC_SVR_8641D, 7400) + CPU_POWERPC_MPC8641D, POWERPC_SVR_8641D, e600) /* 32 bits "classic" PowerPC */ /* PowerPC 6xx family */ POWERPC_DEF("601_v0", CPU_POWERPC_601_v0, 601, @@ -1145,6 +1143,8 @@ "POWER7 v2.1") POWERPC_DEF("POWER7_v2.3", CPU_POWERPC_POWER7_v23, POWER7, "POWER7 v2.3") + POWERPC_DEF("POWER8_v1.0", CPU_POWERPC_POWER8_v10, POWER8, + "POWER8 v1.0") POWERPC_DEF("970", CPU_POWERPC_970, 970, "PowerPC 970") POWERPC_DEF("970fx_v1.0", CPU_POWERPC_970FX_v10, 970FX, @@ -1390,6 +1390,7 @@ PowerPCCPUAlias ppc_cpu_aliases[] = { { "Dino", "POWER3" }, { "POWER3+", "631" }, { "POWER7", "POWER7_v2.3" }, + { "POWER8", "POWER8_v1.0" }, { "970fx", "970fx_v3.1" }, { "970mp", "970mp_v1.1" }, { "Apache", "RS64" }, diff --git a/target-ppc/cpu-models.h b/target-ppc/cpu-models.h index ae8f7c743..01e488f71 100644 --- a/target-ppc/cpu-models.h +++ b/target-ppc/cpu-models.h @@ -556,6 +556,7 @@ enum { CPU_POWERPC_POWER7_v20 = 0x003F0200, CPU_POWERPC_POWER7_v21 = 0x003F0201, CPU_POWERPC_POWER7_v23 = 0x003F0203, + CPU_POWERPC_POWER8_v10 = 0x004B0100, CPU_POWERPC_970 = 0x00390202, CPU_POWERPC_970FX_v10 = 0x00391100, CPU_POWERPC_970FX_v20 = 0x003C0200, @@ -732,9 +733,7 @@ enum { POWERPC_SVR_8568E = 0x807D0011 | POWERPC_SVR_E500, POWERPC_SVR_8572 = 0x80E00010 | POWERPC_SVR_E500, POWERPC_SVR_8572E = 0x80E80010 | POWERPC_SVR_E500, -#if 0 - POWERPC_SVR_8610 = xxx, -#endif + POWERPC_SVR_8610 = 0x80A00011, POWERPC_SVR_8641 = 0x80900021, POWERPC_SVR_8641D = 0x80900121, }; diff --git a/target-ppc/cpu-qom.h b/target-ppc/cpu-qom.h index 84ba1054d..713259951 100644 --- a/target-ppc/cpu-qom.h +++ b/target-ppc/cpu-qom.h @@ -91,7 +91,7 @@ typedef struct PowerPCCPU { static inline PowerPCCPU *ppc_env_get_cpu(CPUPPCState *env) { - return POWERPC_CPU(container_of(env, PowerPCCPU, env)); + return container_of(env, PowerPCCPU, env); } #define ENV_GET_CPU(e) CPU(ppc_env_get_cpu(e)) diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h index 0ede077d7..7a7b1bf35 100644 --- a/target-ppc/cpu.h +++ b/target-ppc/cpu.h @@ -1188,15 +1188,6 @@ static inline int cpu_mmu_index (CPUPPCState *env) return env->mmu_idx; } -#if defined(CONFIG_USER_ONLY) -static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp) -{ - if (newsp) - env->gpr[1] = newsp; - env->gpr[3] = 0; -} -#endif - #include "exec/cpu-all.h" /*****************************************************************************/ @@ -2036,17 +2027,6 @@ static inline void cpu_get_tb_cpu_state(CPUPPCState *env, target_ulong *pc, *flags = env->hflags; } -static inline void cpu_set_tls(CPUPPCState *env, target_ulong newtls) -{ -#if defined(TARGET_PPC64) - /* The kernel checks TIF_32BIT here; we don't support loading 32-bit - binaries on PPC64 yet. */ - env->gpr[13] = newtls; -#else - env->gpr[2] = newtls; -#endif -} - #if !defined(CONFIG_USER_ONLY) static inline int booke206_tlbm_id(CPUPPCState *env, ppcmas_tlb_t *tlbm) { diff --git a/target-ppc/excp_helper.c b/target-ppc/excp_helper.c index 4a0fc6dd5..e9fcad8ef 100644 --- a/target-ppc/excp_helper.c +++ b/target-ppc/excp_helper.c @@ -986,16 +986,19 @@ void helper_msgsnd(target_ulong rb) { int irq = dbell2irq(rb); int pir = rb & DBELL_PIRTAG_MASK; - CPUPPCState *cenv; + CPUState *cs; if (irq < 0) { return; } - for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) { + for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) { + PowerPCCPU *cpu = POWERPC_CPU(cs); + CPUPPCState *cenv = &cpu->env; + if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) { cenv->pending_interrupts |= 1 << irq; - cpu_interrupt(CPU(ppc_env_get_cpu(cenv)), CPU_INTERRUPT_HARD); + cpu_interrupt(cs, CPU_INTERRUPT_HARD); } } } diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c index c89dd5827..b0099e122 100644 --- a/target-ppc/kvm.c +++ b/target-ppc/kvm.c @@ -1560,7 +1560,7 @@ off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem) }; rma_region = g_new(MemoryRegion, 1); - memory_region_init_ram_ptr(rma_region, name, size, rma); + memory_region_init_ram_ptr(rma_region, NULL, name, size, rma); vmstate_register_ram_global(rma_region); memory_region_add_subregion(sysmem, 0, rma_region); @@ -1579,7 +1579,7 @@ uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift) /* Find the largest hardware supported page size that's less than * or equal to the (logical) backing page size of guest RAM */ - kvm_get_smmu_info(ppc_env_get_cpu(first_cpu), &info); + kvm_get_smmu_info(POWERPC_CPU(first_cpu), &info); rampagesize = getrampagesize(); best_page_shift = 0; diff --git a/target-ppc/mmu-hash32.c b/target-ppc/mmu-hash32.c index f6adf2245..6a77dc4f9 100644 --- a/target-ppc/mmu-hash32.c +++ b/target-ppc/mmu-hash32.c @@ -29,10 +29,10 @@ #ifdef DEBUG_MMU # define LOG_MMU(...) qemu_log(__VA_ARGS__) -# define LOG_MMU_STATE(env) log_cpu_state((env), 0) +# define LOG_MMU_STATE(cpu) log_cpu_state((cpu), 0) #else # define LOG_MMU(...) do { } while (0) -# define LOG_MMU_STATE(...) do { } while (0) +# define LOG_MMU_STATE(cpu) do { } while (0) #endif #ifdef DEBUG_BATS diff --git a/target-ppc/mmu-hash64.c b/target-ppc/mmu-hash64.c index 5c67ec3e9..67fc1b5de 100644 --- a/target-ppc/mmu-hash64.c +++ b/target-ppc/mmu-hash64.c @@ -28,10 +28,10 @@ #ifdef DEBUG_MMU # define LOG_MMU(...) qemu_log(__VA_ARGS__) -# define LOG_MMU_STATE(env) log_cpu_state((env), 0) +# define LOG_MMU_STATE(cpu) log_cpu_state((cpu), 0) #else # define LOG_MMU(...) do { } while (0) -# define LOG_MMU_STATE(...) do { } while (0) +# define LOG_MMU_STATE(cpu) do { } while (0) #endif #ifdef DEBUG_SLB diff --git a/target-ppc/mmu_helper.c b/target-ppc/mmu_helper.c index 385b67ab2..77102c4b6 100644 --- a/target-ppc/mmu_helper.c +++ b/target-ppc/mmu_helper.c @@ -32,10 +32,10 @@ #ifdef DEBUG_MMU # define LOG_MMU(...) qemu_log(__VA_ARGS__) -# define LOG_MMU_STATE(env) log_cpu_state((env), 0) +# define LOG_MMU_STATE(cpu) log_cpu_state((cpu), 0) #else # define LOG_MMU(...) do { } while (0) -# define LOG_MMU_STATE(...) do { } while (0) +# define LOG_MMU_STATE(cpu) do { } while (0) #endif #ifdef DEBUG_SOFTWARE_TLB @@ -1508,7 +1508,7 @@ static int cpu_ppc_handle_mmu_fault(CPUPPCState *env, target_ulong address, mmu_idx, TARGET_PAGE_SIZE); ret = 0; } else if (ret < 0) { - LOG_MMU_STATE(env); + LOG_MMU_STATE(CPU(ppc_env_get_cpu(env))); if (access_type == ACCESS_CODE) { switch (ret) { case -1: @@ -2890,7 +2890,7 @@ void helper_booke206_tlbflush(CPUPPCState *env, uint32_t type) void tlb_fill(CPUPPCState *env, target_ulong addr, int is_write, int mmu_idx, uintptr_t retaddr) { - CPUState *cpu = ENV_GET_CPU(env); + CPUState *cpu = CPU(ppc_env_get_cpu(env)); PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); int ret; diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 3643863d5..eb96272b0 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -9726,10 +9726,11 @@ void ppc_cpu_dump_statistics(CPUState *cs, FILE*f, } /*****************************************************************************/ -static inline void gen_intermediate_code_internal(CPUPPCState *env, +static inline void gen_intermediate_code_internal(PowerPCCPU *cpu, TranslationBlock *tb, - int search_pc) + bool search_pc) { + CPUPPCState *env = &cpu->env; DisasContext ctx, *ctxp = &ctx; opc_handler_t **table, *handler; target_ulong pc_start; @@ -9917,12 +9918,12 @@ static inline void gen_intermediate_code_internal(CPUPPCState *env, void gen_intermediate_code (CPUPPCState *env, struct TranslationBlock *tb) { - gen_intermediate_code_internal(env, tb, 0); + gen_intermediate_code_internal(ppc_env_get_cpu(env), tb, false); } void gen_intermediate_code_pc (CPUPPCState *env, struct TranslationBlock *tb) { - gen_intermediate_code_internal(env, tb, 1); + gen_intermediate_code_internal(ppc_env_get_cpu(env), tb, true); } void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb, int pc_pos) diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c index 50e0ee573..79bfcd8df 100644 --- a/target-ppc/translate_init.c +++ b/target-ppc/translate_init.c @@ -6479,6 +6479,131 @@ POWERPC_FAMILY(7457)(ObjectClass *oc, void *data) POWERPC_FLAG_BUS_CLK; } +static void init_proc_e600 (CPUPPCState *env) +{ + gen_spr_ne_601(env); + gen_spr_7xx(env); + /* Time base */ + gen_tbl(env); + /* 74xx specific SPR */ + gen_spr_74xx(env); + /* XXX : not implemented */ + spr_register(env, SPR_UBAMR, "UBAMR", + &spr_read_ureg, SPR_NOACCESS, + &spr_read_ureg, SPR_NOACCESS, + 0x00000000); + /* XXX : not implemented */ + spr_register(env, SPR_LDSTCR, "LDSTCR", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); + /* XXX : not implemented */ + spr_register(env, SPR_ICTRL, "ICTRL", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); + /* XXX : not implemented */ + spr_register(env, SPR_MSSSR0, "MSSSR0", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); + /* XXX : not implemented */ + spr_register(env, SPR_PMC5, "PMC5", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); + /* XXX : not implemented */ + spr_register(env, SPR_UPMC5, "UPMC5", + &spr_read_ureg, SPR_NOACCESS, + &spr_read_ureg, SPR_NOACCESS, + 0x00000000); + /* XXX : not implemented */ + spr_register(env, SPR_PMC6, "PMC6", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); + /* XXX : not implemented */ + spr_register(env, SPR_UPMC6, "UPMC6", + &spr_read_ureg, SPR_NOACCESS, + &spr_read_ureg, SPR_NOACCESS, + 0x00000000); + /* SPRGs */ + spr_register(env, SPR_SPRG4, "SPRG4", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); + spr_register(env, SPR_USPRG4, "USPRG4", + &spr_read_ureg, SPR_NOACCESS, + &spr_read_ureg, SPR_NOACCESS, + 0x00000000); + spr_register(env, SPR_SPRG5, "SPRG5", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); + spr_register(env, SPR_USPRG5, "USPRG5", + &spr_read_ureg, SPR_NOACCESS, + &spr_read_ureg, SPR_NOACCESS, + 0x00000000); + spr_register(env, SPR_SPRG6, "SPRG6", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); + spr_register(env, SPR_USPRG6, "USPRG6", + &spr_read_ureg, SPR_NOACCESS, + &spr_read_ureg, SPR_NOACCESS, + 0x00000000); + spr_register(env, SPR_SPRG7, "SPRG7", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + 0x00000000); + spr_register(env, SPR_USPRG7, "USPRG7", + &spr_read_ureg, SPR_NOACCESS, + &spr_read_ureg, SPR_NOACCESS, + 0x00000000); + /* Memory management */ + gen_low_BATs(env); + gen_high_BATs(env); + gen_74xx_soft_tlb(env, 128, 2); + init_excp_7450(env); + env->dcache_line_size = 32; + env->icache_line_size = 32; + /* Allocate hardware IRQ controller */ + ppc6xx_irq_init(env); +} + +POWERPC_FAMILY(e600)(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); + + dc->desc = "PowerPC e600"; + pcc->init_proc = init_proc_e600; + pcc->check_pow = check_pow_hid0_74xx; + pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB | + PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES | + PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE | + PPC_FLOAT_STFIWX | + PPC_CACHE | PPC_CACHE_ICBI | + PPC_CACHE_DCBA | PPC_CACHE_DCBZ | + PPC_MEM_SYNC | PPC_MEM_EIEIO | + PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | + PPC_MEM_TLBIA | PPC_74xx_TLB | + PPC_SEGMENT | PPC_EXTERN | + PPC_ALTIVEC; + pcc->insns_flags2 = PPC_NONE; + pcc->msr_mask = 0x000000000205FF77ULL; + pcc->mmu_model = POWERPC_MMU_32B; +#if defined(CONFIG_SOFTMMU) + pcc->handle_mmu_fault = ppc_hash32_handle_mmu_fault; +#endif + pcc->excp_model = POWERPC_EXCP_74xx; + pcc->bus_model = PPC_FLAGS_INPUT_6xx; + pcc->bfd_mach = bfd_mach_ppc_7400; + pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE | + POWERPC_FLAG_BE | POWERPC_FLAG_PMM | + POWERPC_FLAG_BUS_CLK; +} + #if defined (TARGET_PPC64) #if defined(CONFIG_USER_ONLY) #define POWERPC970_HID5_INIT 0x00000080 @@ -7011,6 +7136,40 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data) pcc->l1_dcache_size = 0x8000; pcc->l1_icache_size = 0x8000; } + +POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + PowerPCCPUClass *pcc = POWERPC_CPU_CLASS(oc); + + dc->desc = "POWER8"; + pcc->init_proc = init_proc_POWER7; + pcc->check_pow = check_pow_nocheck; + pcc->insns_flags = PPC_INSNS_BASE | PPC_STRING | PPC_MFTB | + PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES | + PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE | + PPC_FLOAT_STFIWX | + PPC_CACHE | PPC_CACHE_ICBI | PPC_CACHE_DCBZ | + PPC_MEM_SYNC | PPC_MEM_EIEIO | + PPC_MEM_TLBIE | PPC_MEM_TLBSYNC | + PPC_64B | PPC_ALTIVEC | + PPC_SEGMENT_64B | PPC_SLBI | + PPC_POPCNTB | PPC_POPCNTWD; + pcc->insns_flags2 = PPC2_VSX | PPC2_DFP | PPC2_DBRX; + pcc->msr_mask = 0x800000000204FF36ULL; + pcc->mmu_model = POWERPC_MMU_2_06; +#if defined(CONFIG_SOFTMMU) + pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault; +#endif + pcc->excp_model = POWERPC_EXCP_POWER7; + pcc->bus_model = PPC_FLAGS_INPUT_POWER7; + pcc->bfd_mach = bfd_mach_ppc64; + pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE | + POWERPC_FLAG_BE | POWERPC_FLAG_PMM | + POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR; + pcc->l1_dcache_size = 0x8000; + pcc->l1_icache_size = 0x8000; +} #endif /* defined (TARGET_PPC64) */ @@ -8171,11 +8330,6 @@ static void ppc_cpu_reset(CPUState *s) CPUPPCState *env = &cpu->env; target_ulong msr; - if (qemu_loglevel_mask(CPU_LOG_RESET)) { - qemu_log("CPU Reset (CPU %d)\n", s->cpu_index); - log_cpu_state(env, 0); - } - pcc->parent_reset(s); msr = (target_ulong)0; diff --git a/target-s390x/cpu-qom.h b/target-s390x/cpu-qom.h index ec32d21f0..4c091e3ea 100644 --- a/target-s390x/cpu-qom.h +++ b/target-s390x/cpu-qom.h @@ -64,7 +64,7 @@ typedef struct S390CPU { static inline S390CPU *s390_env_get_cpu(CPUS390XState *env) { - return S390_CPU(container_of(env, S390CPU, env)); + return container_of(env, S390CPU, env); } #define ENV_GET_CPU(e) CPU(s390_env_get_cpu(e)) diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c index c3697cd94..1ef2fc0e8 100644 --- a/target-s390x/cpu.c +++ b/target-s390x/cpu.c @@ -65,11 +65,6 @@ static void s390_cpu_reset(CPUState *s) S390CPUClass *scc = S390_CPU_GET_CLASS(cpu); CPUS390XState *env = &cpu->env; - if (qemu_loglevel_mask(CPU_LOG_RESET)) { - qemu_log("CPU Reset (CPU %d)\n", s->cpu_index); - log_cpu_state(env, 0); - } - s390_del_running_cpu(cpu); scc->parent_reset(s); diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 741c4e4dd..646268858 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -149,16 +149,6 @@ typedef struct CPUS390XState { #include "cpu-qom.h" -#if defined(CONFIG_USER_ONLY) -static inline void cpu_clone_regs(CPUS390XState *env, target_ulong newsp) -{ - if (newsp) { - env->regs[15] = newsp; - } - env->regs[2] = 0; -} -#endif - /* distinguish between 24 bit and 31 bit addressing */ #define HIGH_ORDER_BIT 0x80000000 @@ -515,12 +505,6 @@ static inline bool css_present(uint8_t cssid) } #endif -static inline void cpu_set_tls(CPUS390XState *env, target_ulong newtls) -{ - env->aregs[0] = newtls >> 32; - env->aregs[1] = newtls & 0xffffffffULL; -} - #define cpu_init(model) (&cpu_s390x_init(model)->env) #define cpu_exec cpu_s390x_exec #define cpu_gen_code cpu_s390x_gen_code diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 42f758fc7..60e94f8ee 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -469,7 +469,7 @@ static int kvm_handle_css_inst(S390CPU *cpu, struct kvm_run *run, int r = 0; int no_cc = 0; CPUS390XState *env = &cpu->env; - CPUState *cs = ENV_GET_CPU(env); + CPUState *cs = CPU(cpu); if (ipa0 != 0xb2) { /* Not handled for now. */ @@ -607,9 +607,10 @@ static int handle_priv(S390CPU *cpu, struct kvm_run *run, return r; } -static int handle_hypercall(CPUS390XState *env, struct kvm_run *run) +static int handle_hypercall(S390CPU *cpu, struct kvm_run *run) { - CPUState *cs = ENV_GET_CPU(env); + CPUState *cs = CPU(cpu); + CPUS390XState *env = &cpu->env; kvm_s390_get_registers_partial(cs); cs->kvm_vcpu_dirty = true; @@ -618,13 +619,13 @@ static int handle_hypercall(CPUS390XState *env, struct kvm_run *run) return 0; } -static int handle_diag(CPUS390XState *env, struct kvm_run *run, int ipb_code) +static int handle_diag(S390CPU *cpu, struct kvm_run *run, int ipb_code) { int r = 0; switch (ipb_code) { case DIAG_KVM_HYPERCALL: - r = handle_hypercall(env, run); + r = handle_hypercall(cpu, run); break; case DIAG_KVM_BREAKPOINT: sleep(10); @@ -735,7 +736,6 @@ out: static int handle_instruction(S390CPU *cpu, struct kvm_run *run) { - CPUS390XState *env = &cpu->env; unsigned int ipa0 = (run->s390_sieic.ipa & 0xff00); uint8_t ipa1 = run->s390_sieic.ipa & 0x00ff; int ipb_code = (run->s390_sieic.ipb & 0x0fff0000) >> 16; @@ -749,7 +749,7 @@ static int handle_instruction(S390CPU *cpu, struct kvm_run *run) r = handle_priv(cpu, run, ipa0 >> 8, ipa1); break; case IPA0_DIAG: - r = handle_diag(env, run, ipb_code); + r = handle_diag(cpu, run, ipb_code); break; case IPA0_SIGP: r = handle_sigp(cpu, run, ipa1); diff --git a/target-s390x/translate.c b/target-s390x/translate.c index cd9880ed7..cba7b8752 100644 --- a/target-s390x/translate.c +++ b/target-s390x/translate.c @@ -4736,10 +4736,11 @@ static ExitStatus translate_one(CPUS390XState *env, DisasContext *s) return ret; } -static inline void gen_intermediate_code_internal(CPUS390XState *env, +static inline void gen_intermediate_code_internal(S390CPU *cpu, TranslationBlock *tb, - int search_pc) + bool search_pc) { + CPUS390XState *env = &cpu->env; DisasContext dc; target_ulong pc_start; uint64_t next_page_start; @@ -4872,12 +4873,12 @@ static inline void gen_intermediate_code_internal(CPUS390XState *env, void gen_intermediate_code (CPUS390XState *env, struct TranslationBlock *tb) { - gen_intermediate_code_internal(env, tb, 0); + gen_intermediate_code_internal(s390_env_get_cpu(env), tb, false); } void gen_intermediate_code_pc (CPUS390XState *env, struct TranslationBlock *tb) { - gen_intermediate_code_internal(env, tb, 1); + gen_intermediate_code_internal(s390_env_get_cpu(env), tb, true); } void restore_state_to_opc(CPUS390XState *env, TranslationBlock *tb, int pc_pos) diff --git a/target-sh4/cpu-qom.h b/target-sh4/cpu-qom.h index 01d16372b..c229a9a29 100644 --- a/target-sh4/cpu-qom.h +++ b/target-sh4/cpu-qom.h @@ -76,7 +76,7 @@ typedef struct SuperHCPU { static inline SuperHCPU *sh_env_get_cpu(CPUSH4State *env) { - return SUPERH_CPU(container_of(env, SuperHCPU, env)); + return container_of(env, SuperHCPU, env); } #define ENV_GET_CPU(e) CPU(sh_env_get_cpu(e)) diff --git a/target-sh4/cpu.c b/target-sh4/cpu.c index e73915693..03487eb32 100644 --- a/target-sh4/cpu.c +++ b/target-sh4/cpu.c @@ -31,11 +31,6 @@ static void superh_cpu_reset(CPUState *s) SuperHCPUClass *scc = SUPERH_CPU_GET_CLASS(cpu); CPUSH4State *env = &cpu->env; - if (qemu_loglevel_mask(CPU_LOG_RESET)) { - qemu_log("CPU Reset (CPU %d)\n", s->cpu_index); - log_cpu_state(env, 0); - } - scc->parent_reset(s); memset(env, 0, offsetof(CPUSH4State, breakpoints)); diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h index fd7da9254..c8df18bab 100644 --- a/target-sh4/cpu.h +++ b/target-sh4/cpu.h @@ -220,11 +220,6 @@ void cpu_sh4_write_mmaped_utlb_data(CPUSH4State *s, hwaddr addr, int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr); -static inline void cpu_set_tls(CPUSH4State *env, target_ulong newtls) -{ - env->gbr = newtls; -} - void cpu_load_tlb(CPUSH4State * env); static inline CPUSH4State *cpu_init(const char *cpu_model) @@ -250,15 +245,6 @@ static inline int cpu_mmu_index (CPUSH4State *env) return (env->sr & SR_MD) == 0 ? 1 : 0; } -#if defined(CONFIG_USER_ONLY) -static inline void cpu_clone_regs(CPUSH4State *env, target_ulong newsp) -{ - if (newsp) - env->gregs[15] = newsp; - env->gregs[0] = 0; -} -#endif - #include "exec/cpu-all.h" /* Memory access type */ diff --git a/target-sh4/helper.c b/target-sh4/helper.c index ce10ca84e..cb6a2d28b 100644 --- a/target-sh4/helper.c +++ b/target-sh4/helper.c @@ -159,7 +159,7 @@ void superh_cpu_do_interrupt(CPUState *cs) } qemu_log("exception 0x%03x [%s] raised\n", irq_vector, expname); - log_cpu_state(env, 0); + log_cpu_state(cs, 0); } env->ssr = env->sr; diff --git a/target-sh4/translate.c b/target-sh4/translate.c index 292c9e970..2fbe6685b 100644 --- a/target-sh4/translate.c +++ b/target-sh4/translate.c @@ -1846,9 +1846,10 @@ static void decode_opc(DisasContext * ctx) } static inline void -gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb, - int search_pc) +gen_intermediate_code_internal(SuperHCPU *cpu, TranslationBlock *tb, + bool search_pc) { + CPUSH4State *env = &cpu->env; DisasContext ctx; target_ulong pc_start; static uint16_t *gen_opc_end; @@ -1969,12 +1970,12 @@ gen_intermediate_code_internal(CPUSH4State * env, TranslationBlock * tb, void gen_intermediate_code(CPUSH4State * env, struct TranslationBlock *tb) { - gen_intermediate_code_internal(env, tb, 0); + gen_intermediate_code_internal(sh_env_get_cpu(env), tb, false); } void gen_intermediate_code_pc(CPUSH4State * env, struct TranslationBlock *tb) { - gen_intermediate_code_internal(env, tb, 1); + gen_intermediate_code_internal(sh_env_get_cpu(env), tb, true); } void restore_state_to_opc(CPUSH4State *env, TranslationBlock *tb, int pc_pos) diff --git a/target-sparc/cpu-qom.h b/target-sparc/cpu-qom.h index 97c1ec7a5..033a5b521 100644 --- a/target-sparc/cpu-qom.h +++ b/target-sparc/cpu-qom.h @@ -68,7 +68,7 @@ typedef struct SPARCCPU { static inline SPARCCPU *sparc_env_get_cpu(CPUSPARCState *env) { - return SPARC_CPU(container_of(env, SPARCCPU, env)); + return container_of(env, SPARCCPU, env); } #define ENV_GET_CPU(e) CPU(sparc_env_get_cpu(e)) diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c index 65ae6f73b..87c3a50c0 100644 --- a/target-sparc/cpu.c +++ b/target-sparc/cpu.c @@ -30,11 +30,6 @@ static void sparc_cpu_reset(CPUState *s) SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(cpu); CPUSPARCState *env = &cpu->env; - if (qemu_loglevel_mask(CPU_LOG_RESET)) { - qemu_log("CPU Reset (CPU %d)\n", s->cpu_index); - log_cpu_state(env, 0); - } - scc->parent_reset(s); memset(env, 0, offsetof(CPUSPARCState, breakpoints)); diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index 021eb157b..41b014a0b 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -690,18 +690,6 @@ static inline int cpu_pil_allowed(CPUSPARCState *env1, int pil) #endif } -#if defined(CONFIG_USER_ONLY) -static inline void cpu_clone_regs(CPUSPARCState *env, target_ulong newsp) -{ - if (newsp) - env->regwptr[22] = newsp; - env->regwptr[0] = 0; - /* FIXME: Do we also need to clear CF? */ - /* XXXXX */ - printf ("HELPME: %s:%d\n", __FILE__, __LINE__); -} -#endif - #include "exec/cpu-all.h" #ifdef TARGET_SPARC64 diff --git a/target-sparc/int32_helper.c b/target-sparc/int32_helper.c index 722146065..d5322380c 100644 --- a/target-sparc/int32_helper.c +++ b/target-sparc/int32_helper.c @@ -86,7 +86,7 @@ void sparc_cpu_do_interrupt(CPUState *cs) } qemu_log("%6d: %s (v=%02x)\n", count, name, intno); - log_cpu_state(env, 0); + log_cpu_state(cs, 0); #if 0 { int i; diff --git a/target-sparc/int64_helper.c b/target-sparc/int64_helper.c index f411884c6..bf7dd86ab 100644 --- a/target-sparc/int64_helper.c +++ b/target-sparc/int64_helper.c @@ -92,7 +92,7 @@ void sparc_cpu_do_interrupt(CPUState *cs) } qemu_log("%6d: %s (v=%04x)\n", count, name, intno); - log_cpu_state(env, 0); + log_cpu_state(cs, 0); #if 0 { int i; diff --git a/target-sparc/mmu_helper.c b/target-sparc/mmu_helper.c index 3983c9658..740cbe8f2 100644 --- a/target-sparc/mmu_helper.c +++ b/target-sparc/mmu_helper.c @@ -845,6 +845,7 @@ hwaddr cpu_get_phys_page_debug(CPUSPARCState *env, target_ulong addr) } } section = memory_region_find(get_system_memory(), phys_addr, 1); + memory_region_unref(section.mr); if (!int128_nz(section.size)) { return -1; } diff --git a/target-sparc/translate.c b/target-sparc/translate.c index eb6e80097..5e771e5da 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -5219,9 +5219,11 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn) } } -static inline void gen_intermediate_code_internal(TranslationBlock * tb, - int spc, CPUSPARCState *env) +static inline void gen_intermediate_code_internal(SPARCCPU *cpu, + TranslationBlock *tb, + bool spc) { + CPUSPARCState *env = &cpu->env; target_ulong pc_start, last_pc; uint16_t *gen_opc_end; DisasContext dc1, *dc = &dc1; @@ -5347,12 +5349,12 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb, void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb) { - gen_intermediate_code_internal(tb, 0, env); + gen_intermediate_code_internal(sparc_env_get_cpu(env), tb, false); } void gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb) { - gen_intermediate_code_internal(tb, 1, env); + gen_intermediate_code_internal(sparc_env_get_cpu(env), tb, true); } void gen_intermediate_code_init(CPUSPARCState *env) diff --git a/target-unicore32/cpu-qom.h b/target-unicore32/cpu-qom.h index 7eec4481c..350d48034 100644 --- a/target-unicore32/cpu-qom.h +++ b/target-unicore32/cpu-qom.h @@ -53,7 +53,7 @@ typedef struct UniCore32CPU { static inline UniCore32CPU *uc32_env_get_cpu(CPUUniCore32State *env) { - return UNICORE32_CPU(container_of(env, UniCore32CPU, env)); + return container_of(env, UniCore32CPU, env); } #define ENV_GET_CPU(e) CPU(uc32_env_get_cpu(e)) diff --git a/target-unicore32/cpu.h b/target-unicore32/cpu.h index 5b2b9d1cc..d4be5252f 100644 --- a/target-unicore32/cpu.h +++ b/target-unicore32/cpu.h @@ -142,19 +142,6 @@ static inline int cpu_mmu_index(CPUUniCore32State *env) return (env->uncached_asr & ASR_M) == ASR_MODE_USER ? 1 : 0; } -static inline void cpu_clone_regs(CPUUniCore32State *env, target_ulong newsp) -{ - if (newsp) { - env->regs[29] = newsp; - } - env->regs[0] = 0; -} - -static inline void cpu_set_tls(CPUUniCore32State *env, target_ulong newtls) -{ - env->regs[16] = newtls; -} - #include "exec/cpu-all.h" #include "cpu-qom.h" #include "exec/exec-all.h" diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c index e1fe4e6bc..d85185df3 100644 --- a/target-unicore32/translate.c +++ b/target-unicore32/translate.c @@ -1876,9 +1876,10 @@ static void disas_uc32_insn(CPUUniCore32State *env, DisasContext *s) /* generate intermediate code in gen_opc_buf and gen_opparam_buf for basic block 'tb'. If search_pc is TRUE, also generate PC information for each intermediate instruction. */ -static inline void gen_intermediate_code_internal(CPUUniCore32State *env, - TranslationBlock *tb, int search_pc) +static inline void gen_intermediate_code_internal(UniCore32CPU *cpu, + TranslationBlock *tb, bool search_pc) { + CPUUniCore32State *env = &cpu->env; DisasContext dc1, *dc = &dc1; CPUBreakpoint *bp; uint16_t *gen_opc_end; @@ -2065,12 +2066,12 @@ done_generating: void gen_intermediate_code(CPUUniCore32State *env, TranslationBlock *tb) { - gen_intermediate_code_internal(env, tb, 0); + gen_intermediate_code_internal(uc32_env_get_cpu(env), tb, false); } void gen_intermediate_code_pc(CPUUniCore32State *env, TranslationBlock *tb) { - gen_intermediate_code_internal(env, tb, 1); + gen_intermediate_code_internal(uc32_env_get_cpu(env), tb, true); } static const char *cpu_mode_names[16] = { diff --git a/target-xtensa/cpu-qom.h b/target-xtensa/cpu-qom.h index 30506cf6d..31e749818 100644 --- a/target-xtensa/cpu-qom.h +++ b/target-xtensa/cpu-qom.h @@ -73,7 +73,7 @@ typedef struct XtensaCPU { static inline XtensaCPU *xtensa_env_get_cpu(const CPUXtensaState *env) { - return XTENSA_CPU(container_of(env, XtensaCPU, env)); + return container_of(env, XtensaCPU, env); } #define ENV_GET_CPU(e) CPU(xtensa_env_get_cpu(e)) diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c index dcb90a54a..e4cf82863 100644 --- a/target-xtensa/translate.c +++ b/target-xtensa/translate.c @@ -2875,9 +2875,11 @@ static void gen_ibreak_check(CPUXtensaState *env, DisasContext *dc) } } -static void gen_intermediate_code_internal( - CPUXtensaState *env, TranslationBlock *tb, int search_pc) +static inline +void gen_intermediate_code_internal(XtensaCPU *cpu, + TranslationBlock *tb, bool search_pc) { + CPUXtensaState *env = &cpu->env; DisasContext dc; int insn_count = 0; int j, lj = -1; @@ -3006,12 +3008,12 @@ static void gen_intermediate_code_internal( void gen_intermediate_code(CPUXtensaState *env, TranslationBlock *tb) { - gen_intermediate_code_internal(env, tb, 0); + gen_intermediate_code_internal(xtensa_env_get_cpu(env), tb, false); } void gen_intermediate_code_pc(CPUXtensaState *env, TranslationBlock *tb) { - gen_intermediate_code_internal(env, tb, 1); + gen_intermediate_code_internal(xtensa_env_get_cpu(env), tb, true); } void xtensa_cpu_dump_state(CPUState *cs, FILE *f, diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h index 97e4a5baa..51e50920b 100644 --- a/tcg/aarch64/tcg-target.h +++ b/tcg/aarch64/tcg-target.h @@ -40,6 +40,7 @@ typedef enum { /* optional instructions */ #define TCG_TARGET_HAS_div_i32 0 +#define TCG_TARGET_HAS_rem_i32 0 #define TCG_TARGET_HAS_ext8s_i32 1 #define TCG_TARGET_HAS_ext16s_i32 1 #define TCG_TARGET_HAS_ext8u_i32 1 @@ -62,6 +63,7 @@ typedef enum { #define TCG_TARGET_HAS_muls2_i32 0 #define TCG_TARGET_HAS_div_i64 0 +#define TCG_TARGET_HAS_rem_i64 0 #define TCG_TARGET_HAS_ext8s_i64 1 #define TCG_TARGET_HAS_ext16s_i64 1 #define TCG_TARGET_HAS_ext32s_i64 1 diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c index 6be736b75..6c4854dbb 100644 --- a/tcg/arm/tcg-target.c +++ b/tcg/arm/tcg-target.c @@ -22,50 +22,43 @@ * THE SOFTWARE. */ -#if defined(__ARM_ARCH_7__) || \ - defined(__ARM_ARCH_7A__) || \ - defined(__ARM_ARCH_7EM__) || \ - defined(__ARM_ARCH_7M__) || \ - defined(__ARM_ARCH_7R__) -#define USE_ARMV7_INSTRUCTIONS +/* The __ARM_ARCH define is provided by gcc 4.8. Construct it otherwise. */ +#ifndef __ARM_ARCH +# if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ + || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \ + || defined(__ARM_ARCH_7EM__) +# define __ARM_ARCH 7 +# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ + || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) \ + || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) +# define __ARM_ARCH 6 +# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5E__) \ + || defined(__ARM_ARCH_5T__) || defined(__ARM_ARCH_5TE__) \ + || defined(__ARM_ARCH_5TEJ__) +# define __ARM_ARCH 5 +# else +# define __ARM_ARCH 4 +# endif #endif -#if defined(USE_ARMV7_INSTRUCTIONS) || \ - defined(__ARM_ARCH_6J__) || \ - defined(__ARM_ARCH_6K__) || \ - defined(__ARM_ARCH_6T2__) || \ - defined(__ARM_ARCH_6Z__) || \ - defined(__ARM_ARCH_6ZK__) -#define USE_ARMV6_INSTRUCTIONS -#endif - -#if defined(USE_ARMV6_INSTRUCTIONS) || \ - defined(__ARM_ARCH_5T__) || \ - defined(__ARM_ARCH_5TE__) || \ - defined(__ARM_ARCH_5TEJ__) -#define USE_ARMV5_INSTRUCTIONS -#endif +static int arm_arch = __ARM_ARCH; -#ifdef USE_ARMV5_INSTRUCTIONS -static const int use_armv5_instructions = 1; +#if defined(__ARM_ARCH_5T__) \ + || defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_5TEJ__) +# define use_armv5t_instructions 1 #else -static const int use_armv5_instructions = 0; +# define use_armv5t_instructions use_armv6_instructions #endif -#undef USE_ARMV5_INSTRUCTIONS -#ifdef USE_ARMV6_INSTRUCTIONS -static const int use_armv6_instructions = 1; -#else -static const int use_armv6_instructions = 0; -#endif -#undef USE_ARMV6_INSTRUCTIONS +#define use_armv6_instructions (__ARM_ARCH >= 6 || arm_arch >= 6) +#define use_armv7_instructions (__ARM_ARCH >= 7 || arm_arch >= 7) -#ifdef USE_ARMV7_INSTRUCTIONS -static const int use_armv7_instructions = 1; -#else -static const int use_armv7_instructions = 0; +#ifndef use_idiv_instructions +bool use_idiv_instructions; +#endif +#ifdef CONFIG_GETAUXVAL +# include #endif -#undef USE_ARMV7_INSTRUCTIONS #ifndef NDEBUG static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { @@ -1023,7 +1016,7 @@ static inline void tcg_out_call(TCGContext *s, uint32_t addr) if (val - 8 < 0x02000000 && val - 8 >= -0x02000000) { if (addr & 1) { /* Use BLX if the target is in Thumb mode */ - if (!use_armv5_instructions) { + if (!use_armv5t_instructions) { tcg_abort(); } tcg_out_blx_imm(s, val); @@ -1042,7 +1035,7 @@ static inline void tcg_out_call(TCGContext *s, uint32_t addr) static inline void tcg_out_callr(TCGContext *s, int cond, int arg) { - if (use_armv5_instructions) { + if (use_armv5t_instructions) { tcg_out_blx(s, cond, arg); } else { tcg_out_dat_reg(s, cond, ARITH_MOV, TCG_REG_R14, 0, @@ -1926,18 +1919,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, case INDEX_op_divu_i32: tcg_out_udiv(s, COND_AL, args[0], args[1], args[2]); break; - case INDEX_op_rem_i32: - tcg_out_sdiv(s, COND_AL, TCG_REG_TMP, args[1], args[2]); - tcg_out_mul32(s, COND_AL, TCG_REG_TMP, TCG_REG_TMP, args[2]); - tcg_out_dat_reg(s, COND_AL, ARITH_SUB, args[0], args[1], TCG_REG_TMP, - SHIFT_IMM_LSL(0)); - break; - case INDEX_op_remu_i32: - tcg_out_udiv(s, COND_AL, TCG_REG_TMP, args[1], args[2]); - tcg_out_mul32(s, COND_AL, TCG_REG_TMP, TCG_REG_TMP, args[2]); - tcg_out_dat_reg(s, COND_AL, ARITH_SUB, args[0], args[1], TCG_REG_TMP, - SHIFT_IMM_LSL(0)); - break; default: tcg_abort(); @@ -2041,18 +2022,31 @@ static const TCGTargetOpDef arm_op_defs[] = { { INDEX_op_deposit_i32, { "r", "0", "rZ" } }, -#if TCG_TARGET_HAS_div_i32 { INDEX_op_div_i32, { "r", "r", "r" } }, - { INDEX_op_rem_i32, { "r", "r", "r" } }, { INDEX_op_divu_i32, { "r", "r", "r" } }, - { INDEX_op_remu_i32, { "r", "r", "r" } }, -#endif { -1 }, }; static void tcg_target_init(TCGContext *s) { +#if defined(CONFIG_GETAUXVAL) + /* Only probe for the platform and capabilities if we havn't already + determined maximum values at compile time. */ +# if !defined(use_idiv_instructions) + { + unsigned long hwcap = getauxval(AT_HWCAP); + use_idiv_instructions = (hwcap & HWCAP_ARM_IDIVA) != 0; + } +# endif + if (__ARM_ARCH < 7) { + const char *pl = (const char *)getauxval(AT_PLATFORM); + if (pl != NULL && pl[0] == 'v' && pl[1] >= '4' && pl[1] <= '9') { + arm_arch = pl[1] - '0'; + } + } +#endif /* GETAUXVAL */ + tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff); tcg_regset_set32(tcg_target_call_clobber_regs, 0, (1 << TCG_REG_R0) | @@ -2094,23 +2088,31 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type, tcg_out_movi32(s, COND_AL, ret, arg); } +/* Compute frame size via macros, to share between tcg_target_qemu_prologue + and tcg_register_jit. */ + +#define PUSH_SIZE ((11 - 4 + 1 + 1) * sizeof(tcg_target_long)) + +#define FRAME_SIZE \ + ((PUSH_SIZE \ + + TCG_STATIC_CALL_ARGS_SIZE \ + + CPU_TEMP_BUF_NLONGS * sizeof(long) \ + + TCG_TARGET_STACK_ALIGN - 1) \ + & -TCG_TARGET_STACK_ALIGN) + static void tcg_target_qemu_prologue(TCGContext *s) { - int frame_size; + int stack_addend; /* Calling convention requires us to save r4-r11 and lr. */ /* stmdb sp!, { r4 - r11, lr } */ tcg_out32(s, (COND_AL << 28) | 0x092d4ff0); - /* Allocate the local stack frame. */ - frame_size = TCG_STATIC_CALL_ARGS_SIZE; - frame_size += CPU_TEMP_BUF_NLONGS * sizeof(long); - /* We saved an odd number of registers above; keep an 8 aligned stack. */ - frame_size = ((frame_size + TCG_TARGET_STACK_ALIGN - 1) - & -TCG_TARGET_STACK_ALIGN) + 4; + /* Reserve callee argument and tcg temp space. */ + stack_addend = FRAME_SIZE - PUSH_SIZE; tcg_out_dat_rI(s, COND_AL, ARITH_SUB, TCG_REG_CALL_STACK, - TCG_REG_CALL_STACK, frame_size, 1); + TCG_REG_CALL_STACK, stack_addend, 1); tcg_set_frame(s, TCG_REG_CALL_STACK, TCG_STATIC_CALL_ARGS_SIZE, CPU_TEMP_BUF_NLONGS * sizeof(long)); @@ -2121,8 +2123,58 @@ static void tcg_target_qemu_prologue(TCGContext *s) /* Epilogue. We branch here via tb_ret_addr. */ tcg_out_dat_rI(s, COND_AL, ARITH_ADD, TCG_REG_CALL_STACK, - TCG_REG_CALL_STACK, frame_size, 1); + TCG_REG_CALL_STACK, stack_addend, 1); /* ldmia sp!, { r4 - r11, pc } */ tcg_out32(s, (COND_AL << 28) | 0x08bd8ff0); } + +typedef struct { + DebugFrameCIE cie; + DebugFrameFDEHeader fde; + uint8_t fde_def_cfa[4]; + uint8_t fde_reg_ofs[18]; +} DebugFrame; + +#define ELF_HOST_MACHINE EM_ARM + +/* We're expecting a 2 byte uleb128 encoded value. */ +QEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14)); + +static DebugFrame debug_frame = { + .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */ + .cie.id = -1, + .cie.version = 1, + .cie.code_align = 1, + .cie.data_align = 0x7c, /* sleb128 -4 */ + .cie.return_column = 14, + + /* Total FDE size does not include the "len" member. */ + .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset), + + .fde_def_cfa = { + 12, 13, /* DW_CFA_def_cfa sp, ... */ + (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */ + (FRAME_SIZE >> 7) + }, + .fde_reg_ofs = { + /* The following must match the stmdb in the prologue. */ + 0x8e, 1, /* DW_CFA_offset, lr, -4 */ + 0x8b, 2, /* DW_CFA_offset, r11, -8 */ + 0x8a, 3, /* DW_CFA_offset, r10, -12 */ + 0x89, 4, /* DW_CFA_offset, r9, -16 */ + 0x88, 5, /* DW_CFA_offset, r8, -20 */ + 0x87, 6, /* DW_CFA_offset, r7, -24 */ + 0x86, 7, /* DW_CFA_offset, r6, -28 */ + 0x85, 8, /* DW_CFA_offset, r5, -32 */ + 0x84, 9, /* DW_CFA_offset, r4, -36 */ + } +}; + +void tcg_register_jit(void *buf, size_t buf_size) +{ + debug_frame.fde.func_start = (tcg_target_long) buf; + debug_frame.fde.func_len = buf_size; + + tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame)); +} diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h index 3be41cce3..5cd9d6a67 100644 --- a/tcg/arm/tcg-target.h +++ b/tcg/arm/tcg-target.h @@ -49,6 +49,13 @@ typedef enum { #define TCG_TARGET_NB_REGS 16 +#ifdef __ARM_ARCH_EXT_IDIV__ +#define use_idiv_instructions 1 +#else +extern bool use_idiv_instructions; +#endif + + /* used for function call generation */ #define TCG_REG_CALL_STACK TCG_REG_R13 #define TCG_TARGET_STACK_ALIGN 8 @@ -73,12 +80,8 @@ typedef enum { #define TCG_TARGET_HAS_deposit_i32 1 #define TCG_TARGET_HAS_movcond_i32 1 #define TCG_TARGET_HAS_muls2_i32 1 - -#ifdef __ARM_ARCH_EXT_IDIV__ -#define TCG_TARGET_HAS_div_i32 1 -#else -#define TCG_TARGET_HAS_div_i32 0 -#endif +#define TCG_TARGET_HAS_div_i32 use_idiv_instructions +#define TCG_TARGET_HAS_rem_i32 0 extern bool tcg_target_deposit_valid(int ofs, int len); #define TCG_TARGET_deposit_i32_valid tcg_target_deposit_valid diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c index 656e73621..68f77ba4d 100644 --- a/tcg/hppa/tcg-target.c +++ b/tcg/hppa/tcg-target.c @@ -1765,29 +1765,12 @@ static void tcg_target_init(TCGContext *s) tcg_add_target_add_op_defs(hppa_op_defs); } -typedef struct { - uint32_t len __attribute__((aligned((sizeof(void *))))); - uint32_t id; - uint8_t version; - char augmentation[1]; - uint8_t code_align; - uint8_t data_align; - uint8_t return_column; -} DebugFrameCIE; - -typedef struct { - uint32_t len __attribute__((aligned((sizeof(void *))))); - uint32_t cie_offset; - tcg_target_long func_start __attribute__((packed)); - tcg_target_long func_len __attribute__((packed)); - uint8_t def_cfa[4]; - uint8_t ret_ofs[3]; - uint8_t reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2]; -} DebugFrameFDE; - typedef struct { DebugFrameCIE cie; - DebugFrameFDE fde; + DebugFrameFDEHeader fde; + uint8_t fde_def_cfa[4]; + uint8_t fde_ret_ofs[3]; + uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2]; } DebugFrame; #define ELF_HOST_MACHINE EM_PARISC @@ -1806,16 +1789,18 @@ static DebugFrame debug_frame = { .cie.data_align = 1, .cie.return_column = 2, - .fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */ - .fde.def_cfa = { + /* Total FDE size does not include the "len" member. */ + .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset), + + .fde_def_cfa = { 0x12, 30, /* DW_CFA_def_cfa_sf sp, ... */ (-FRAME_SIZE & 0x7f) | 0x80, /* ... sleb128 -FRAME_SIZE */ (-FRAME_SIZE >> 7) & 0x7f }, - .fde.ret_ofs = { + .fde_ret_ofs = { 0x11, 2, (-20 / 4) & 0x7f /* DW_CFA_offset_extended_sf r2, 20 */ }, - .fde.reg_ofs = { + .fde_reg_ofs = { /* This must match the ordering in tcg_target_callee_save_regs. */ 0x80 + 4, 0, /* DW_CFA_offset r4, 0 */ 0x80 + 5, 4, /* DW_CFA_offset r5, 4 */ diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h index ebd53d9e3..25467bdd4 100644 --- a/tcg/hppa/tcg-target.h +++ b/tcg/hppa/tcg-target.h @@ -85,6 +85,7 @@ typedef enum { /* optional instructions */ #define TCG_TARGET_HAS_div_i32 0 +#define TCG_TARGET_HAS_rem_i32 0 #define TCG_TARGET_HAS_rot_i32 1 #define TCG_TARGET_HAS_ext8s_i32 1 #define TCG_TARGET_HAS_ext16s_i32 1 diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index 9e95477ef..87eeab3d3 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -2311,30 +2311,16 @@ static void tcg_target_init(TCGContext *s) tcg_add_target_add_op_defs(x86_op_defs); } -typedef struct { - uint32_t len __attribute__((aligned((sizeof(void *))))); - uint32_t id; - uint8_t version; - char augmentation[1]; - uint8_t code_align; - uint8_t data_align; - uint8_t return_column; -} DebugFrameCIE; - -typedef struct { - uint32_t len __attribute__((aligned((sizeof(void *))))); - uint32_t cie_offset; - tcg_target_long func_start __attribute__((packed)); - tcg_target_long func_len __attribute__((packed)); - uint8_t def_cfa[4]; - uint8_t reg_ofs[14]; -} DebugFrameFDE; - typedef struct { DebugFrameCIE cie; - DebugFrameFDE fde; + DebugFrameFDEHeader fde; + uint8_t fde_def_cfa[4]; + uint8_t fde_reg_ofs[14]; } DebugFrame; +/* We're expecting a 2 byte uleb128 encoded value. */ +QEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14)); + #if !defined(__ELF__) /* Host machine without ELF. */ #elif TCG_TARGET_REG_BITS == 64 @@ -2347,13 +2333,15 @@ static DebugFrame debug_frame = { .cie.data_align = 0x78, /* sleb128 -8 */ .cie.return_column = 16, - .fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */ - .fde.def_cfa = { + /* Total FDE size does not include the "len" member. */ + .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset), + + .fde_def_cfa = { 12, 7, /* DW_CFA_def_cfa %rsp, ... */ (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */ (FRAME_SIZE >> 7) }, - .fde.reg_ofs = { + .fde_reg_ofs = { 0x90, 1, /* DW_CFA_offset, %rip, -8 */ /* The following ordering must match tcg_target_callee_save_regs. */ 0x86, 2, /* DW_CFA_offset, %rbp, -16 */ @@ -2374,13 +2362,15 @@ static DebugFrame debug_frame = { .cie.data_align = 0x7c, /* sleb128 -4 */ .cie.return_column = 8, - .fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */ - .fde.def_cfa = { + /* Total FDE size does not include the "len" member. */ + .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset), + + .fde_def_cfa = { 12, 4, /* DW_CFA_def_cfa %esp, ... */ (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */ (FRAME_SIZE >> 7) }, - .fde.reg_ofs = { + .fde_reg_ofs = { 0x88, 1, /* DW_CFA_offset, %eip, -4 */ /* The following ordering must match tcg_target_callee_save_regs. */ 0x85, 2, /* DW_CFA_offset, %ebp, -8 */ @@ -2394,9 +2384,6 @@ static DebugFrame debug_frame = { #if defined(ELF_HOST_MACHINE) void tcg_register_jit(void *buf, size_t buf_size) { - /* We're expecting a 2 byte uleb128 encoded value. */ - assert(FRAME_SIZE >> 14 == 0); - debug_frame.fde.func_start = (tcg_target_long) buf; debug_frame.fde.func_len = buf_size; diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h index e3d72ea52..f32d5199c 100644 --- a/tcg/ia64/tcg-target.h +++ b/tcg/ia64/tcg-target.h @@ -104,7 +104,9 @@ typedef enum { /* optional instructions */ #define TCG_TARGET_HAS_div_i32 0 +#define TCG_TARGET_HAS_rem_i32 0 #define TCG_TARGET_HAS_div_i64 0 +#define TCG_TARGET_HAS_rem_i64 0 #define TCG_TARGET_HAS_andc_i32 1 #define TCG_TARGET_HAS_andc_i64 1 #define TCG_TARGET_HAS_bswap16_i32 1 diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h index 6155327a9..a438950bc 100644 --- a/tcg/mips/tcg-target.h +++ b/tcg/mips/tcg-target.h @@ -79,6 +79,7 @@ typedef enum { /* optional instructions */ #define TCG_TARGET_HAS_div_i32 1 +#define TCG_TARGET_HAS_rem_i32 1 #define TCG_TARGET_HAS_not_i32 1 #define TCG_TARGET_HAS_nor_i32 1 #define TCG_TARGET_HAS_ext8s_i32 1 diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c index 29ca934e6..453ab6b58 100644 --- a/tcg/ppc/tcg-target.c +++ b/tcg/ppc/tcg-target.c @@ -1671,18 +1671,6 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args, tcg_out32 (s, DIVWU | TAB (args[0], args[1], args[2])); break; - case INDEX_op_rem_i32: - tcg_out32 (s, DIVW | TAB (0, args[1], args[2])); - tcg_out32 (s, MULLW | TAB (0, 0, args[2])); - tcg_out32 (s, SUBF | TAB (args[0], 0, args[1])); - break; - - case INDEX_op_remu_i32: - tcg_out32 (s, DIVWU | TAB (0, args[1], args[2])); - tcg_out32 (s, MULLW | TAB (0, 0, args[2])); - tcg_out32 (s, SUBF | TAB (args[0], 0, args[1])); - break; - case INDEX_op_mulu2_i32: if (args[0] == args[2] || args[0] == args[3]) { tcg_out32 (s, MULLW | TAB (0, args[2], args[3])); @@ -1992,8 +1980,6 @@ static const TCGTargetOpDef ppc_op_defs[] = { { INDEX_op_mul_i32, { "r", "r", "ri" } }, { INDEX_op_div_i32, { "r", "r", "r" } }, { INDEX_op_divu_i32, { "r", "r", "r" } }, - { INDEX_op_rem_i32, { "r", "r", "r" } }, - { INDEX_op_remu_i32, { "r", "r", "r" } }, { INDEX_op_mulu2_i32, { "r", "r", "r", "r" } }, { INDEX_op_sub_i32, { "r", "r", "ri" } }, { INDEX_op_and_i32, { "r", "r", "ri" } }, diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h index 17a6bb367..b42d97cc2 100644 --- a/tcg/ppc/tcg-target.h +++ b/tcg/ppc/tcg-target.h @@ -78,6 +78,7 @@ typedef enum { /* optional instructions */ #define TCG_TARGET_HAS_div_i32 1 +#define TCG_TARGET_HAS_rem_i32 0 #define TCG_TARGET_HAS_rot_i32 1 #define TCG_TARGET_HAS_ext8s_i32 1 #define TCG_TARGET_HAS_ext16s_i32 1 diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c index 606b73def..0678de204 100644 --- a/tcg/ppc64/tcg-target.c +++ b/tcg/ppc64/tcg-target.c @@ -1617,18 +1617,6 @@ static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args, tcg_out32 (s, DIVWU | TAB (args[0], args[1], args[2])); break; - case INDEX_op_rem_i32: - tcg_out32 (s, DIVW | TAB (0, args[1], args[2])); - tcg_out32 (s, MULLW | TAB (0, 0, args[2])); - tcg_out32 (s, SUBF | TAB (args[0], 0, args[1])); - break; - - case INDEX_op_remu_i32: - tcg_out32 (s, DIVWU | TAB (0, args[1], args[2])); - tcg_out32 (s, MULLW | TAB (0, 0, args[2])); - tcg_out32 (s, SUBF | TAB (args[0], 0, args[1])); - break; - case INDEX_op_shl_i32: if (const_args[2]) { tcg_out_rlw(s, RLWINM, args[0], args[1], args[2], 0, 31 - args[2]); @@ -1786,16 +1774,6 @@ static void tcg_out_op (TCGContext *s, TCGOpcode opc, const TCGArg *args, case INDEX_op_divu_i64: tcg_out32 (s, DIVDU | TAB (args[0], args[1], args[2])); break; - case INDEX_op_rem_i64: - tcg_out32 (s, DIVD | TAB (0, args[1], args[2])); - tcg_out32 (s, MULLD | TAB (0, 0, args[2])); - tcg_out32 (s, SUBF | TAB (args[0], 0, args[1])); - break; - case INDEX_op_remu_i64: - tcg_out32 (s, DIVDU | TAB (0, args[1], args[2])); - tcg_out32 (s, MULLD | TAB (0, 0, args[2])); - tcg_out32 (s, SUBF | TAB (args[0], 0, args[1])); - break; case INDEX_op_qemu_ld8u: tcg_out_qemu_ld (s, args, 0); @@ -2064,8 +2042,6 @@ static const TCGTargetOpDef ppc_op_defs[] = { { INDEX_op_mul_i32, { "r", "r", "rI" } }, { INDEX_op_div_i32, { "r", "r", "r" } }, { INDEX_op_divu_i32, { "r", "r", "r" } }, - { INDEX_op_rem_i32, { "r", "r", "r" } }, - { INDEX_op_remu_i32, { "r", "r", "r" } }, { INDEX_op_sub_i32, { "r", "rI", "ri" } }, { INDEX_op_and_i32, { "r", "r", "ri" } }, { INDEX_op_or_i32, { "r", "r", "ri" } }, @@ -2108,8 +2084,6 @@ static const TCGTargetOpDef ppc_op_defs[] = { { INDEX_op_mul_i64, { "r", "r", "rI" } }, { INDEX_op_div_i64, { "r", "r", "r" } }, { INDEX_op_divu_i64, { "r", "r", "r" } }, - { INDEX_op_rem_i64, { "r", "r", "r" } }, - { INDEX_op_remu_i64, { "r", "r", "r" } }, { INDEX_op_neg_i64, { "r", "r" } }, { INDEX_op_not_i64, { "r", "r" } }, diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h index cb7763471..48fc6e2e5 100644 --- a/tcg/ppc64/tcg-target.h +++ b/tcg/ppc64/tcg-target.h @@ -76,6 +76,7 @@ typedef enum { /* optional instructions */ #define TCG_TARGET_HAS_div_i32 1 +#define TCG_TARGET_HAS_rem_i32 0 #define TCG_TARGET_HAS_rot_i32 1 #define TCG_TARGET_HAS_ext8s_i32 1 #define TCG_TARGET_HAS_ext16s_i32 1 @@ -96,6 +97,7 @@ typedef enum { #define TCG_TARGET_HAS_muls2_i32 0 #define TCG_TARGET_HAS_div_i64 1 +#define TCG_TARGET_HAS_rem_i64 0 #define TCG_TARGET_HAS_rot_i64 1 #define TCG_TARGET_HAS_ext8s_i64 1 #define TCG_TARGET_HAS_ext16s_i64 1 diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c index 025af9b37..5bfd29c3b 100644 --- a/tcg/sparc/tcg-target.c +++ b/tcg/sparc/tcg-target.c @@ -1646,29 +1646,12 @@ static void tcg_target_init(TCGContext *s) # define ELF_HOST_FLAGS EF_SPARC_32PLUS #endif -typedef struct { - uint32_t len __attribute__((aligned((sizeof(void *))))); - uint32_t id; - uint8_t version; - char augmentation[1]; - uint8_t code_align; - uint8_t data_align; - uint8_t return_column; -} DebugFrameCIE; - -typedef struct { - uint32_t len __attribute__((aligned((sizeof(void *))))); - uint32_t cie_offset; - tcg_target_long func_start __attribute__((packed)); - tcg_target_long func_len __attribute__((packed)); - uint8_t def_cfa[TCG_TARGET_REG_BITS == 64 ? 4 : 2]; - uint8_t win_save; - uint8_t ret_save[3]; -} DebugFrameFDE; - typedef struct { DebugFrameCIE cie; - DebugFrameFDE fde; + DebugFrameFDEHeader fde; + uint8_t fde_def_cfa[TCG_TARGET_REG_BITS == 64 ? 4 : 2]; + uint8_t fde_win_save; + uint8_t fde_ret_save[3]; } DebugFrame; static DebugFrame debug_frame = { @@ -1679,8 +1662,10 @@ static DebugFrame debug_frame = { .cie.data_align = -sizeof(void *) & 0x7f, .cie.return_column = 15, /* o7 */ - .fde.len = sizeof(DebugFrameFDE)-4, /* length after .len member */ - .fde.def_cfa = { + /* Total FDE size does not include the "len" member. */ + .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset), + + .fde_def_cfa = { #if TCG_TARGET_REG_BITS == 64 12, 30, /* DW_CFA_def_cfa i6, 2047 */ (2047 & 0x7f) | 0x80, (2047 >> 7) @@ -1688,8 +1673,8 @@ static DebugFrame debug_frame = { 13, 30 /* DW_CFA_def_cfa_register i6 */ #endif }, - .fde.win_save = 0x2d, /* DW_CFA_GNU_window_save */ - .fde.ret_save = { 9, 15, 31 }, /* DW_CFA_register o7, i7 */ + .fde_win_save = 0x2d, /* DW_CFA_GNU_window_save */ + .fde_ret_save = { 9, 15, 31 }, /* DW_CFA_register o7, i7 */ }; void tcg_register_jit(void *buf, size_t buf_size) diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h index b5217bef2..dab52d717 100644 --- a/tcg/sparc/tcg-target.h +++ b/tcg/sparc/tcg-target.h @@ -86,6 +86,7 @@ typedef enum { /* optional instructions */ #define TCG_TARGET_HAS_div_i32 1 +#define TCG_TARGET_HAS_rem_i32 1 #define TCG_TARGET_HAS_rot_i32 0 #define TCG_TARGET_HAS_ext8s_i32 0 #define TCG_TARGET_HAS_ext16s_i32 0 @@ -109,6 +110,7 @@ typedef enum { #if TCG_TARGET_REG_BITS == 64 #define TCG_TARGET_HAS_div_i64 1 +#define TCG_TARGET_HAS_rem_i64 1 #define TCG_TARGET_HAS_rot_i64 0 #define TCG_TARGET_HAS_ext8s_i64 0 #define TCG_TARGET_HAS_ext16s_i64 0 diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index 94f604378..364964d8d 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -731,8 +731,14 @@ static inline void tcg_gen_div_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) static inline void tcg_gen_rem_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) { - if (TCG_TARGET_HAS_div_i32) { + if (TCG_TARGET_HAS_rem_i32) { tcg_gen_op3_i32(INDEX_op_rem_i32, ret, arg1, arg2); + } else if (TCG_TARGET_HAS_div_i32) { + TCGv_i32 t0 = tcg_temp_new_i32(); + tcg_gen_op3_i32(INDEX_op_div_i32, t0, arg1, arg2); + tcg_gen_mul_i32(t0, t0, arg2); + tcg_gen_sub_i32(ret, arg1, t0); + tcg_temp_free_i32(t0); } else if (TCG_TARGET_HAS_div2_i32) { TCGv_i32 t0 = tcg_temp_new_i32(); tcg_gen_sari_i32(t0, arg1, 31); @@ -769,8 +775,14 @@ static inline void tcg_gen_divu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) static inline void tcg_gen_remu_i32(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2) { - if (TCG_TARGET_HAS_div_i32) { + if (TCG_TARGET_HAS_rem_i32) { tcg_gen_op3_i32(INDEX_op_remu_i32, ret, arg1, arg2); + } else if (TCG_TARGET_HAS_div_i32) { + TCGv_i32 t0 = tcg_temp_new_i32(); + tcg_gen_op3_i32(INDEX_op_divu_i32, t0, arg1, arg2); + tcg_gen_mul_i32(t0, t0, arg2); + tcg_gen_sub_i32(ret, arg1, t0); + tcg_temp_free_i32(t0); } else if (TCG_TARGET_HAS_div2_i32) { TCGv_i32 t0 = tcg_temp_new_i32(); tcg_gen_movi_i32(t0, 0); @@ -1361,8 +1373,14 @@ static inline void tcg_gen_div_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) static inline void tcg_gen_rem_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) { - if (TCG_TARGET_HAS_div_i64) { + if (TCG_TARGET_HAS_rem_i64) { tcg_gen_op3_i64(INDEX_op_rem_i64, ret, arg1, arg2); + } else if (TCG_TARGET_HAS_div_i64) { + TCGv_i64 t0 = tcg_temp_new_i64(); + tcg_gen_op3_i64(INDEX_op_div_i64, t0, arg1, arg2); + tcg_gen_mul_i64(t0, t0, arg2); + tcg_gen_sub_i64(ret, arg1, t0); + tcg_temp_free_i64(t0); } else if (TCG_TARGET_HAS_div2_i64) { TCGv_i64 t0 = tcg_temp_new_i64(); tcg_gen_sari_i64(t0, arg1, 63); @@ -1399,8 +1417,14 @@ static inline void tcg_gen_divu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) static inline void tcg_gen_remu_i64(TCGv_i64 ret, TCGv_i64 arg1, TCGv_i64 arg2) { - if (TCG_TARGET_HAS_div_i64) { + if (TCG_TARGET_HAS_rem_i64) { tcg_gen_op3_i64(INDEX_op_remu_i64, ret, arg1, arg2); + } else if (TCG_TARGET_HAS_div_i64) { + TCGv_i64 t0 = tcg_temp_new_i64(); + tcg_gen_op3_i64(INDEX_op_divu_i64, t0, arg1, arg2); + tcg_gen_mul_i64(t0, t0, arg2); + tcg_gen_sub_i64(ret, arg1, t0); + tcg_temp_free_i64(t0); } else if (TCG_TARGET_HAS_div2_i64) { TCGv_i64 t0 = tcg_temp_new_i64(); tcg_gen_movi_i64(t0, 0); diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h index 4246e9c1f..a8af5b96a 100644 --- a/tcg/tcg-opc.h +++ b/tcg/tcg-opc.h @@ -27,20 +27,24 @@ */ /* predefined ops */ -DEF(end, 0, 0, 0, 0) /* must be kept first */ -DEF(nop, 0, 0, 0, 0) -DEF(nop1, 0, 0, 1, 0) -DEF(nop2, 0, 0, 2, 0) -DEF(nop3, 0, 0, 3, 0) -DEF(nopn, 0, 0, 1, 0) /* variable number of parameters */ +DEF(end, 0, 0, 0, TCG_OPF_NOT_PRESENT) /* must be kept first */ +DEF(nop, 0, 0, 0, TCG_OPF_NOT_PRESENT) +DEF(nop1, 0, 0, 1, TCG_OPF_NOT_PRESENT) +DEF(nop2, 0, 0, 2, TCG_OPF_NOT_PRESENT) +DEF(nop3, 0, 0, 3, TCG_OPF_NOT_PRESENT) -DEF(discard, 1, 0, 0, 0) +/* variable number of parameters */ +DEF(nopn, 0, 0, 1, TCG_OPF_NOT_PRESENT) + +DEF(discard, 1, 0, 0, TCG_OPF_NOT_PRESENT) +DEF(set_label, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_NOT_PRESENT) + +/* variable number of parameters */ +DEF(call, 0, 1, 2, TCG_OPF_CALL_CLOBBER) -DEF(set_label, 0, 0, 1, TCG_OPF_BB_END) -DEF(call, 0, 1, 2, TCG_OPF_CALL_CLOBBER) /* variable number of parameters */ DEF(br, 0, 0, 1, TCG_OPF_BB_END) -#define IMPL(X) (X ? 0 : TCG_OPF_NOT_PRESENT) +#define IMPL(X) (__builtin_constant_p(X) && !(X) ? TCG_OPF_NOT_PRESENT : 0) #if TCG_TARGET_REG_BITS == 32 # define IMPL64 TCG_OPF_64BIT | TCG_OPF_NOT_PRESENT #else @@ -66,8 +70,8 @@ DEF(sub_i32, 1, 2, 0, 0) DEF(mul_i32, 1, 2, 0, 0) DEF(div_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_div_i32)) DEF(divu_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_div_i32)) -DEF(rem_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_div_i32)) -DEF(remu_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_div_i32)) +DEF(rem_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_rem_i32)) +DEF(remu_i32, 1, 2, 0, IMPL(TCG_TARGET_HAS_rem_i32)) DEF(div2_i32, 2, 3, 0, IMPL(TCG_TARGET_HAS_div2_i32)) DEF(divu2_i32, 2, 3, 0, IMPL(TCG_TARGET_HAS_div2_i32)) DEF(and_i32, 1, 2, 0, 0) @@ -126,8 +130,8 @@ DEF(sub_i64, 1, 2, 0, IMPL64) DEF(mul_i64, 1, 2, 0, IMPL64) DEF(div_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div_i64)) DEF(divu_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div_i64)) -DEF(rem_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div_i64)) -DEF(remu_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div_i64)) +DEF(rem_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rem_i64)) +DEF(remu_i64, 1, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_rem_i64)) DEF(div2_i64, 2, 3, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div2_i64)) DEF(divu2_i64, 2, 3, 0, IMPL64 | IMPL(TCG_TARGET_HAS_div2_i64)) DEF(and_i64, 1, 2, 0, IMPL64) @@ -166,9 +170,9 @@ DEF(muls2_i64, 2, 2, 0, IMPL64 | IMPL(TCG_TARGET_HAS_muls2_i64)) /* QEMU specific */ #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS -DEF(debug_insn_start, 0, 0, 2, 0) +DEF(debug_insn_start, 0, 0, 2, TCG_OPF_NOT_PRESENT) #else -DEF(debug_insn_start, 0, 0, 1, 0) +DEF(debug_insn_start, 0, 0, 1, TCG_OPF_NOT_PRESENT) #endif DEF(exit_tb, 0, 0, 1, TCG_OPF_BB_END) DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_END) diff --git a/tcg/tcg.c b/tcg/tcg.c index 1d8099cca..dac822402 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -68,6 +68,24 @@ static void tcg_target_qemu_prologue(TCGContext *s); static void patch_reloc(uint8_t *code_ptr, int type, tcg_target_long value, tcg_target_long addend); +/* The CIE and FDE header definitions will be common to all hosts. */ +typedef struct { + uint32_t len __attribute__((aligned((sizeof(void *))))); + uint32_t id; + uint8_t version; + char augmentation[1]; + uint8_t code_align; + uint8_t data_align; + uint8_t return_column; +} DebugFrameCIE; + +typedef struct QEMU_PACKED { + uint32_t len __attribute__((aligned((sizeof(void *))))); + uint32_t cie_offset; + tcg_target_long func_start; + tcg_target_long func_len; +} DebugFrameFDEHeader; + static void tcg_register_jit_int(void *buf, size_t size, void *debug_frame, size_t debug_frame_size) __attribute__((unused)); @@ -1160,9 +1178,7 @@ void tcg_add_target_add_op_defs(const TCGTargetOpDef *tdefs) i = 0; for (op = 0; op < ARRAY_SIZE(tcg_op_defs); op++) { const TCGOpDef *def = &tcg_op_defs[op]; - if (op < INDEX_op_call - || op == INDEX_op_debug_insn_start - || (def->flags & TCG_OPF_NOT_PRESENT)) { + if (def->flags & TCG_OPF_NOT_PRESENT) { /* Wrong entry in op definitions? */ if (def->used) { fprintf(stderr, "Invalid op definition for %s\n", def->name); @@ -2659,9 +2675,9 @@ static void tcg_register_jit_int(void *buf_ptr, size_t buf_size, img->sym[1].st_size = buf_size; img->di.cu_low_pc = buf; - img->di.cu_high_pc = buf_size; + img->di.cu_high_pc = buf + buf_size; img->di.fn_low_pc = buf; - img->di.fn_high_pc = buf_size; + img->di.fn_high_pc = buf + buf_size; #ifdef DEBUG_JIT /* Enable this block to be able to debug the ELF image file creation. diff --git a/tcg/tcg.h b/tcg/tcg.h index df375cf31..f3f988969 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -60,6 +60,7 @@ typedef uint64_t TCGRegSet; #if TCG_TARGET_REG_BITS == 32 /* Turn some undef macros into false macros. */ #define TCG_TARGET_HAS_div_i64 0 +#define TCG_TARGET_HAS_rem_i64 0 #define TCG_TARGET_HAS_div2_i64 0 #define TCG_TARGET_HAS_rot_i64 0 #define TCG_TARGET_HAS_ext8s_i64 0 @@ -102,11 +103,13 @@ typedef uint64_t TCGRegSet; #define TCG_TARGET_HAS_div2_i32 0 #elif defined(TCG_TARGET_HAS_div2_i32) #define TCG_TARGET_HAS_div_i32 0 +#define TCG_TARGET_HAS_rem_i32 0 #endif #if defined(TCG_TARGET_HAS_div_i64) #define TCG_TARGET_HAS_div2_i64 0 #elif defined(TCG_TARGET_HAS_div2_i64) #define TCG_TARGET_HAS_div_i64 0 +#define TCG_TARGET_HAS_rem_i64 0 #endif typedef enum TCGOpcode { @@ -593,7 +596,8 @@ enum { TCG_OPF_SIDE_EFFECTS = 0x04, /* Instruction operands are 64-bits (otherwise 32-bits). */ TCG_OPF_64BIT = 0x08, - /* Instruction is optional and not implemented by the host. */ + /* Instruction is optional and not implemented by the host, or insn + is generic and should not be implemened by the host. */ TCG_OPF_NOT_PRESENT = 0x10, }; diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h index 0395bbb8e..d7fc14eb1 100644 --- a/tcg/tci/tcg-target.h +++ b/tcg/tci/tcg-target.h @@ -59,9 +59,8 @@ #define TCG_TARGET_HAS_bswap16_i32 1 #define TCG_TARGET_HAS_bswap32_i32 1 -/* Not more than one of the next two defines must be 1. */ #define TCG_TARGET_HAS_div_i32 1 -#define TCG_TARGET_HAS_div2_i32 0 +#define TCG_TARGET_HAS_rem_i32 1 #define TCG_TARGET_HAS_ext8s_i32 1 #define TCG_TARGET_HAS_ext16s_i32 1 #define TCG_TARGET_HAS_ext8u_i32 1 @@ -83,9 +82,8 @@ #define TCG_TARGET_HAS_bswap32_i64 1 #define TCG_TARGET_HAS_bswap64_i64 1 #define TCG_TARGET_HAS_deposit_i64 1 -/* Not more than one of the next two defines must be 1. */ #define TCG_TARGET_HAS_div_i64 0 -#define TCG_TARGET_HAS_div2_i64 0 +#define TCG_TARGET_HAS_rem_i64 0 #define TCG_TARGET_HAS_ext8s_i64 1 #define TCG_TARGET_HAS_ext16s_i64 1 #define TCG_TARGET_HAS_ext32s_i64 1 diff --git a/tests/Makefile b/tests/Makefile index c107489f4..279d5f830 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -44,6 +44,9 @@ check-unit-y += tests/test-cutils$(EXESUF) gcov-files-test-cutils-y += util/cutils.c check-unit-y += tests/test-mul64$(EXESUF) gcov-files-test-mul64-y = util/host-utils.c +check-unit-y += tests/test-int128$(EXESUF) +# all code tested by test-int128 is inside int128.h +gcov-files-test-int128-y = check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh @@ -75,7 +78,7 @@ test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \ tests/test-string-input-visitor.o tests/test-qmp-output-visitor.o \ tests/test-qmp-input-visitor.o tests/test-qmp-input-strict.o \ tests/test-qmp-commands.o tests/test-visitor-serialization.o \ - tests/test-x86-cpuid.o tests/test-mul64.o + tests/test-x86-cpuid.o tests/test-mul64.o tests/test-int128.o test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.o @@ -98,6 +101,7 @@ tests/test-hbitmap$(EXESUF): tests/test-hbitmap.o libqemuutil.a libqemustub.a tests/test-x86-cpuid$(EXESUF): tests/test-x86-cpuid.o tests/test-xbzrle$(EXESUF): tests/test-xbzrle.o xbzrle.o page_cache.o libqemuutil.a tests/test-cutils$(EXESUF): tests/test-cutils.o util/cutils.o +tests/test-int128$(EXESUF): tests/test-int128.o tests/test-qapi-types.c tests/test-qapi-types.h :\ $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py diff --git a/tests/qemu-iotests/051 b/tests/qemu-iotests/051 index 8039e23ab..1cf8bf79b 100755 --- a/tests/qemu-iotests/051 +++ b/tests/qemu-iotests/051 @@ -149,6 +149,18 @@ echo run_qemu -drive file=$TEST_IMG,file.driver=file run_qemu -drive file=$TEST_IMG,file.driver=qcow2 +echo +echo === Parsing protocol from file name === +echo + +# Protocol strings are supposed to be parsed from traditional option strings, +# but not when using driver-specific options. We can distinguish them by the +# error message for non-existing files. + +run_qemu -hda foo:bar +run_qemu -drive file=foo:bar +run_qemu -drive file.filename=foo:bar + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/051.out b/tests/qemu-iotests/051.out index 3d1ac7b7d..95ff245f4 100644 --- a/tests/qemu-iotests/051.out +++ b/tests/qemu-iotests/051.out @@ -23,10 +23,12 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,unknown_opt=foo: could not === Enable and disable lazy refcounting on the command line, plus some invalid values === Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=on -qququiquit +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) qququiquit Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=off -qququiquit +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) qququiquit Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts= QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=: Parameter 'lazy_refcounts' expects 'on' or 'off' @@ -49,112 +51,152 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=on: Lazy ref QEMU_PROG: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=on: could not open disk image TEST_DIR/t.qcow2: Invalid argument Testing: -drive file=TEST_DIR/t.qcow2,format=qcow2,lazy_refcounts=off -qququiquit +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) qququiquit === No medium === Testing: -drive if=floppy -qququiquit +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) qququiquit Testing: -drive if=ide,media=cdrom -qququiquit +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) qququiquit Testing: -drive if=scsi,media=cdrom -qququiquit +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) qququiquit Testing: -drive if=ide -QEMU_PROG: Device needs media, but drive is empty +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) QEMU_PROG: Device needs media, but drive is empty +QEMU_PROG: Device initialization failed. QEMU_PROG: Initialization of device ide-hd failed Testing: -drive if=virtio -QEMU_PROG: -drive if=virtio: Device needs media, but drive is empty +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) QEMU_PROG: -drive if=virtio: Device needs media, but drive is empty +QEMU_PROG: -drive if=virtio: Device initialization failed. +QEMU_PROG: -drive if=virtio: Device initialization failed. QEMU_PROG: -drive if=virtio: Device 'virtio-blk-pci' could not be initialized Testing: -drive if=scsi -QEMU_PROG: -drive if=scsi: Device needs media, but drive is empty +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) QEMU_PROG: -drive if=scsi: Device needs media, but drive is empty +QEMU_PROG: -drive if=scsi: Device initialization failed. +QEMU_PROG: Device initialization failed. QEMU_PROG: Initialization of device lsi53c895a failed Testing: -drive if=none,id=disk -device ide-cd,drive=disk -qququiquit +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) qququiquit Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-cd,drive=disk -qququiquit +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) qququiquit Testing: -drive if=none,id=disk -device ide-drive,drive=disk -QEMU_PROG: -device ide-drive,drive=disk: Device needs media, but drive is empty +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) QEMU_PROG: -device ide-drive,drive=disk: Device needs media, but drive is empty +QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed. QEMU_PROG: -device ide-drive,drive=disk: Device 'ide-drive' could not be initialized Testing: -drive if=none,id=disk -device ide-hd,drive=disk -QEMU_PROG: -device ide-hd,drive=disk: Device needs media, but drive is empty +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) QEMU_PROG: -device ide-hd,drive=disk: Device needs media, but drive is empty +QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed. QEMU_PROG: -device ide-hd,drive=disk: Device 'ide-hd' could not be initialized Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-disk,drive=disk -QEMU_PROG: -device scsi-disk,drive=disk: Device needs media, but drive is empty +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) QEMU_PROG: -device scsi-disk,drive=disk: Device needs media, but drive is empty +QEMU_PROG: -device scsi-disk,drive=disk: Device initialization failed. QEMU_PROG: -device scsi-disk,drive=disk: Device 'scsi-disk' could not be initialized Testing: -drive if=none,id=disk -device lsi53c895a -device scsi-hd,drive=disk -QEMU_PROG: -device scsi-hd,drive=disk: Device needs media, but drive is empty +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) QEMU_PROG: -device scsi-hd,drive=disk: Device needs media, but drive is empty +QEMU_PROG: -device scsi-hd,drive=disk: Device initialization failed. QEMU_PROG: -device scsi-hd,drive=disk: Device 'scsi-hd' could not be initialized === Read-only === Testing: -drive file=TEST_DIR/t.qcow2,if=floppy,readonly=on -qququiquit +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) qququiquit Testing: -drive file=TEST_DIR/t.qcow2,if=ide,media=cdrom,readonly=on -qququiquit +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) qququiquit Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,media=cdrom,readonly=on -qququiquit +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) qququiquit Testing: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=ide,readonly=on: readonly not supported by this bus type Testing: -drive file=TEST_DIR/t.qcow2,if=virtio,readonly=on -qququiquit +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) qququiquit Testing: -drive file=TEST_DIR/t.qcow2,if=scsi,readonly=on -qququiquit +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) qququiquit Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-cd,drive=disk -qququiquit +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) qququiquit Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-cd,drive=disk -qququiquit +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) qququiquit Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-drive,drive=disk -QEMU_PROG: -device ide-drive,drive=disk: Can't use a read-only drive +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) QEMU_PROG: -device ide-drive,drive=disk: Can't use a read-only drive +QEMU_PROG: -device ide-drive,drive=disk: Device initialization failed. QEMU_PROG: -device ide-drive,drive=disk: Device 'ide-drive' could not be initialized Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device ide-hd,drive=disk -QEMU_PROG: -device ide-hd,drive=disk: Can't use a read-only drive +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) QEMU_PROG: -device ide-hd,drive=disk: Can't use a read-only drive +QEMU_PROG: -device ide-hd,drive=disk: Device initialization failed. QEMU_PROG: -device ide-hd,drive=disk: Device 'ide-hd' could not be initialized Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-disk,drive=disk -qququiquit +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) qququiquit Testing: -drive file=TEST_DIR/t.qcow2,if=none,id=disk,readonly=on -device lsi53c895a -device scsi-hd,drive=disk -qququiquit +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) qququiquit === Cache modes === Testing: -drive media=cdrom,cache=none -qququiquit +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) qququiquit Testing: -drive media=cdrom,cache=directsync -qququiquit +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) qququiquit Testing: -drive media=cdrom,cache=writeback -qququiquit +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) qququiquit Testing: -drive media=cdrom,cache=writethrough -qququiquit +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) qququiquit Testing: -drive media=cdrom,cache=unsafe -qququiquit +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) qququiquit Testing: -drive media=cdrom,cache=invalid_value QEMU_PROG: -drive media=cdrom,cache=invalid_value: invalid cache option @@ -163,10 +205,25 @@ QEMU_PROG: -drive media=cdrom,cache=invalid_value: invalid cache option === Specifying the protocol layer === Testing: -drive file=TEST_DIR/t.qcow2,file.driver=file -qququiquit +QEMU 1.5.50 monitor - type 'help' for more information +(qemu) qququiquit Testing: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2 QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2: Can't use 'qcow2' as a block driver for the protocol level QEMU_PROG: -drive file=TEST_DIR/t.qcow2,file.driver=qcow2: could not open disk image TEST_DIR/t.qcow2: Invalid argument + +=== Parsing protocol from file name === + +Testing: -hda foo:bar +QEMU_PROG: -hda foo:bar: Unknown protocol +QEMU_PROG: -hda foo:bar: could not open disk image foo:bar: No such file or directory + +Testing: -drive file=foo:bar +QEMU_PROG: -drive file=foo:bar: Unknown protocol +QEMU_PROG: -drive file=foo:bar: could not open disk image foo:bar: No such file or directory + +Testing: -drive file.filename=foo:bar +QEMU_PROG: -drive file.filename=foo:bar: could not open disk image ide0-hd0: No such file or directory + *** done diff --git a/tests/qemu-iotests/055 b/tests/qemu-iotests/055 index 887c959a3..c66f8dbd7 100755 --- a/tests/qemu-iotests/055 +++ b/tests/qemu-iotests/055 @@ -54,7 +54,7 @@ class TestSingleDrive(iotests.QMPTestCase): self.assert_no_active_block_jobs() result = self.vm.qmp('drive-backup', device='drive0', - target=target_img) + target=target_img, sync='full') self.assert_qmp(result, 'return', {}) event = self.cancel_and_wait() @@ -64,7 +64,7 @@ class TestSingleDrive(iotests.QMPTestCase): self.assert_no_active_block_jobs() result = self.vm.qmp('drive-backup', device='drive0', - target=target_img) + target=target_img, sync='full') self.assert_qmp(result, 'return', {}) result = self.vm.qmp('block-job-pause', device='drive0') @@ -89,17 +89,17 @@ class TestSingleDrive(iotests.QMPTestCase): def test_medium_not_found(self): result = self.vm.qmp('drive-backup', device='ide1-cd0', - target=target_img) + target=target_img, sync='full') self.assert_qmp(result, 'error/class', 'GenericError') def test_image_not_found(self): result = self.vm.qmp('drive-backup', device='drive0', - mode='existing', target=target_img) + target=target_img, sync='full', mode='existing') self.assert_qmp(result, 'error/class', 'GenericError') def test_device_not_found(self): result = self.vm.qmp('drive-backup', device='nonexistent', - target=target_img) + target=target_img, sync='full') self.assert_qmp(result, 'error/class', 'DeviceNotFound') class TestSetSpeed(iotests.QMPTestCase): @@ -119,7 +119,7 @@ class TestSetSpeed(iotests.QMPTestCase): self.assert_no_active_block_jobs() result = self.vm.qmp('drive-backup', device='drive0', - target=target_img) + target=target_img, sync='full') self.assert_qmp(result, 'return', {}) # Default speed is 0 @@ -140,7 +140,7 @@ class TestSetSpeed(iotests.QMPTestCase): # Check setting speed in drive-backup works result = self.vm.qmp('drive-backup', device='drive0', - target=target_img, speed=4*1024*1024) + target=target_img, sync='full', speed=4*1024*1024) self.assert_qmp(result, 'return', {}) result = self.vm.qmp('query-block-jobs') @@ -154,13 +154,13 @@ class TestSetSpeed(iotests.QMPTestCase): self.assert_no_active_block_jobs() result = self.vm.qmp('drive-backup', device='drive0', - target=target_img, speed=-1) + target=target_img, sync='full', speed=-1) self.assert_qmp(result, 'error/class', 'GenericError') self.assert_no_active_block_jobs() result = self.vm.qmp('drive-backup', device='drive0', - target=target_img) + target=target_img, sync='full') self.assert_qmp(result, 'return', {}) result = self.vm.qmp('block-job-set-speed', device='drive0', speed=-1) @@ -196,7 +196,8 @@ class TestSingleTransaction(iotests.QMPTestCase): result = self.vm.qmp('transaction', actions=[{ 'type': 'drive-backup', 'data': { 'device': 'drive0', - 'target': target_img }, + 'target': target_img, + 'sync': 'full' }, } ]) self.assert_qmp(result, 'return', {}) @@ -210,7 +211,8 @@ class TestSingleTransaction(iotests.QMPTestCase): result = self.vm.qmp('transaction', actions=[{ 'type': 'drive-backup', 'data': { 'device': 'drive0', - 'target': target_img }, + 'target': target_img, + 'sync': 'full' }, } ]) self.assert_qmp(result, 'return', {}) @@ -239,7 +241,8 @@ class TestSingleTransaction(iotests.QMPTestCase): result = self.vm.qmp('transaction', actions=[{ 'type': 'drive-backup', 'data': { 'device': 'ide1-cd0', - 'target': target_img }, + 'target': target_img, + 'sync': 'full' }, } ]) self.assert_qmp(result, 'error/class', 'GenericError') @@ -249,7 +252,8 @@ class TestSingleTransaction(iotests.QMPTestCase): 'type': 'drive-backup', 'data': { 'device': 'drive0', 'mode': 'existing', - 'target': target_img }, + 'target': target_img, + 'sync': 'full' }, } ]) self.assert_qmp(result, 'error/class', 'GenericError') @@ -259,7 +263,8 @@ class TestSingleTransaction(iotests.QMPTestCase): 'type': 'drive-backup', 'data': { 'device': 'nonexistent', 'mode': 'existing', - 'target': target_img }, + 'target': target_img, + 'sync': 'full' }, } ]) self.assert_qmp(result, 'error/class', 'DeviceNotFound') @@ -269,7 +274,8 @@ class TestSingleTransaction(iotests.QMPTestCase): 'type': 'drive-backup', 'data': { 'device': 'nonexistent', 'mode': 'existing', - 'target': target_img }, + 'target': target_img, + 'sync': 'full' }, }, { 'type': 'Abort', 'data': {}, diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter index dcf6391ea..9dbcae8d8 100644 --- a/tests/qemu-iotests/common.filter +++ b/tests/qemu-iotests/common.filter @@ -155,7 +155,7 @@ _filter_qemu_io() # replace occurrences of QEMU_PROG with "qemu" _filter_qemu() { - sed -e "s#^$(basename $QEMU_PROG):#QEMU_PROG:#" + sed -e "s#\\(^\\|(qemu) \\)$(basename $QEMU_PROG):#\1QEMU_PROG:#" } # make sure this script returns success diff --git a/tests/test-int128.c b/tests/test-int128.c new file mode 100644 index 000000000..5aca032e0 --- /dev/null +++ b/tests/test-int128.c @@ -0,0 +1,212 @@ +/* + * Test Int128 arithmetic + * + * This work is licensed under the terms of the GNU LGPL, version 2 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#include +#include +#include "qemu/int128.h" +#include "qemu/osdep.h" + +static uint32_t tests[8] = { + 0x00000000, 0x00000001, 0x7FFFFFFE, 0x7FFFFFFF, + 0x80000000, 0x80000001, 0xFFFFFFFE, 0xFFFFFFFF, +}; + +#define LOW 3ULL +#define HIGH (1ULL << 63) +#define MIDDLE (-1ULL & ~LOW & ~HIGH) + +static uint64_t expand16(unsigned x) +{ + return (x & LOW) | ((x & 4) ? MIDDLE : 0) | (x & 0x8000 ? HIGH : 0); +} + +static Int128 expand(uint32_t x) +{ + uint64_t l, h; + l = expand16(x & 65535); + h = expand16(x >> 16); + return (Int128) {l, h}; +}; + +static void test_and(void) +{ + int i, j; + + for (i = 0; i < ARRAY_SIZE(tests); ++i) { + for (j = 0; j < ARRAY_SIZE(tests); ++j) { + Int128 a = expand(tests[i]); + Int128 b = expand(tests[j]); + Int128 r = expand(tests[i] & tests[j]); + Int128 s = int128_and(a, b); + g_assert_cmpuint(r.lo, ==, s.lo); + g_assert_cmpuint(r.hi, ==, s.hi); + } + } +} + +static void test_add(void) +{ + int i, j; + + for (i = 0; i < ARRAY_SIZE(tests); ++i) { + for (j = 0; j < ARRAY_SIZE(tests); ++j) { + Int128 a = expand(tests[i]); + Int128 b = expand(tests[j]); + Int128 r = expand(tests[i] + tests[j]); + Int128 s = int128_add(a, b); + g_assert_cmpuint(r.lo, ==, s.lo); + g_assert_cmpuint(r.hi, ==, s.hi); + } + } +} + +static void test_sub(void) +{ + int i, j; + + for (i = 0; i < ARRAY_SIZE(tests); ++i) { + for (j = 0; j < ARRAY_SIZE(tests); ++j) { + Int128 a = expand(tests[i]); + Int128 b = expand(tests[j]); + Int128 r = expand(tests[i] - tests[j]); + Int128 s = int128_sub(a, b); + g_assert_cmpuint(r.lo, ==, s.lo); + g_assert_cmpuint(r.hi, ==, s.hi); + } + } +} + +static void test_neg(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(tests); ++i) { + Int128 a = expand(tests[i]); + Int128 r = expand(-tests[i]); + Int128 s = int128_neg(a); + g_assert_cmpuint(r.lo, ==, s.lo); + g_assert_cmpuint(r.hi, ==, s.hi); + } +} + +static void test_nz(void) +{ + int i, j; + + for (i = 0; i < ARRAY_SIZE(tests); ++i) { + for (j = 0; j < ARRAY_SIZE(tests); ++j) { + Int128 a = expand(tests[i]); + g_assert_cmpuint(int128_nz(a), ==, tests[i] != 0); + } + } +} + +static void test_le(void) +{ + int i, j; + + for (i = 0; i < ARRAY_SIZE(tests); ++i) { + for (j = 0; j < ARRAY_SIZE(tests); ++j) { + /* Signed comparison */ + int32_t a = (int32_t) tests[i]; + int32_t b = (int32_t) tests[j]; + g_assert_cmpuint(int128_le(expand(a), expand(b)), ==, a <= b); + } + } +} + +static void test_lt(void) +{ + int i, j; + + for (i = 0; i < ARRAY_SIZE(tests); ++i) { + for (j = 0; j < ARRAY_SIZE(tests); ++j) { + /* Signed comparison */ + int32_t a = (int32_t) tests[i]; + int32_t b = (int32_t) tests[j]; + g_assert_cmpuint(int128_lt(expand(a), expand(b)), ==, a < b); + } + } +} + +static void test_ge(void) +{ + int i, j; + + for (i = 0; i < ARRAY_SIZE(tests); ++i) { + for (j = 0; j < ARRAY_SIZE(tests); ++j) { + /* Signed comparison */ + int32_t a = (int32_t) tests[i]; + int32_t b = (int32_t) tests[j]; + g_assert_cmpuint(int128_ge(expand(a), expand(b)), ==, a >= b); + } + } +} + +static void test_gt(void) +{ + int i, j; + + for (i = 0; i < ARRAY_SIZE(tests); ++i) { + for (j = 0; j < ARRAY_SIZE(tests); ++j) { + /* Signed comparison */ + int32_t a = (int32_t) tests[i]; + int32_t b = (int32_t) tests[j]; + g_assert_cmpuint(int128_gt(expand(a), expand(b)), ==, a > b); + } + } +} + +/* Make sure to test undefined behavior at runtime! */ + +static void __attribute__((__noinline__, __noclone__)) +test_rshift_one(uint32_t x, int n, uint64_t h, uint64_t l) +{ + Int128 a = expand(x); + Int128 r = int128_rshift(a, n); + g_assert_cmpuint(r.lo, ==, l); + g_assert_cmpuint(r.hi, ==, h); +} + +static void test_rshift(void) +{ + test_rshift_one(0x00010000U, 64, 0x0000000000000000ULL, 0x0000000000000001ULL); + test_rshift_one(0x80010000U, 64, 0xFFFFFFFFFFFFFFFFULL, 0x8000000000000001ULL); + test_rshift_one(0x7FFE0000U, 64, 0x0000000000000000ULL, 0x7FFFFFFFFFFFFFFEULL); + test_rshift_one(0xFFFE0000U, 64, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFEULL); + test_rshift_one(0x00010000U, 60, 0x0000000000000000ULL, 0x0000000000000010ULL); + test_rshift_one(0x80010000U, 60, 0xFFFFFFFFFFFFFFF8ULL, 0x0000000000000010ULL); + test_rshift_one(0x00018000U, 60, 0x0000000000000000ULL, 0x0000000000000018ULL); + test_rshift_one(0x80018000U, 60, 0xFFFFFFFFFFFFFFF8ULL, 0x0000000000000018ULL); + test_rshift_one(0x7FFE0000U, 60, 0x0000000000000007ULL, 0xFFFFFFFFFFFFFFE0ULL); + test_rshift_one(0xFFFE0000U, 60, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFE0ULL); + test_rshift_one(0x7FFE8000U, 60, 0x0000000000000007ULL, 0xFFFFFFFFFFFFFFE8ULL); + test_rshift_one(0xFFFE8000U, 60, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFE8ULL); + test_rshift_one(0x00018000U, 0, 0x0000000000000001ULL, 0x8000000000000000ULL); + test_rshift_one(0x80018000U, 0, 0x8000000000000001ULL, 0x8000000000000000ULL); + test_rshift_one(0x7FFE0000U, 0, 0x7FFFFFFFFFFFFFFEULL, 0x0000000000000000ULL); + test_rshift_one(0xFFFE0000U, 0, 0xFFFFFFFFFFFFFFFEULL, 0x0000000000000000ULL); + test_rshift_one(0x7FFE8000U, 0, 0x7FFFFFFFFFFFFFFEULL, 0x8000000000000000ULL); + test_rshift_one(0xFFFE8000U, 0, 0xFFFFFFFFFFFFFFFEULL, 0x8000000000000000ULL); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + g_test_add_func("/int128/int128_and", test_and); + g_test_add_func("/int128/int128_add", test_add); + g_test_add_func("/int128/int128_sub", test_sub); + g_test_add_func("/int128/int128_neg", test_neg); + g_test_add_func("/int128/int128_nz", test_nz); + g_test_add_func("/int128/int128_le", test_le); + g_test_add_func("/int128/int128_lt", test_lt); + g_test_add_func("/int128/int128_ge", test_ge); + g_test_add_func("/int128/int128_gt", test_gt); + g_test_add_func("/int128/int128_rshift", test_rshift); + return g_test_run(); +} diff --git a/tests/test-thread-pool.c b/tests/test-thread-pool.c index 22915aac1..b62338f37 100644 --- a/tests/test-thread-pool.c +++ b/tests/test-thread-pool.c @@ -17,15 +17,15 @@ typedef struct { static int worker_cb(void *opaque) { WorkerTestData *data = opaque; - return __sync_fetch_and_add(&data->n, 1); + return atomic_fetch_inc(&data->n); } static int long_cb(void *opaque) { WorkerTestData *data = opaque; - __sync_fetch_and_add(&data->n, 1); + atomic_inc(&data->n); g_usleep(2000000); - __sync_fetch_and_add(&data->n, 1); + atomic_inc(&data->n); return 0; } @@ -169,7 +169,7 @@ static void test_cancel(void) /* Cancel the jobs that haven't been started yet. */ num_canceled = 0; for (i = 0; i < 100; i++) { - if (__sync_val_compare_and_swap(&data[i].n, 0, 3) == 0) { + if (atomic_cmpxchg(&data[i].n, 0, 3) == 0) { data[i].ret = -ECANCELED; bdrv_aio_cancel(data[i].aiocb); active--; diff --git a/translate-all.c b/translate-all.c index 9acb2b177..e8683d2c6 100644 --- a/translate-all.c +++ b/translate-all.c @@ -681,7 +681,7 @@ static void page_flush_tb(void) /* XXX: tb_flush is currently not thread safe */ void tb_flush(CPUArchState *env1) { - CPUArchState *env; + CPUState *cpu; #if defined(DEBUG_FLUSH) printf("qemu: flush code_size=%ld nb_tbs=%d avg_tb_size=%ld\n", @@ -696,7 +696,9 @@ void tb_flush(CPUArchState *env1) } tcg_ctx.tb_ctx.nb_tbs = 0; - for (env = first_cpu; env != NULL; env = env->next_cpu) { + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { + CPUArchState *env = cpu->env_ptr; + memset(env->tb_jmp_cache, 0, TB_JMP_CACHE_SIZE * sizeof(void *)); } @@ -821,7 +823,7 @@ static inline void tb_reset_jump(TranslationBlock *tb, int n) /* invalidate one TB */ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr) { - CPUArchState *env; + CPUState *cpu; PageDesc *p; unsigned int h, n1; tb_page_addr_t phys_pc; @@ -848,7 +850,9 @@ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr) /* remove the TB from the hash list */ h = tb_jmp_cache_hash_func(tb->pc); - for (env = first_cpu; env != NULL; env = env->next_cpu) { + for (cpu = first_cpu; cpu != NULL; cpu = cpu->next_cpu) { + CPUArchState *env = cpu->env_ptr; + if (env->tb_jmp_cache[h] == tb) { env->tb_jmp_cache[h] = NULL; } @@ -999,8 +1003,10 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, int is_cpu_write_access) { TranslationBlock *tb, *tb_next, *saved_tb; - CPUArchState *env = cpu_single_env; - CPUState *cpu = NULL; + CPUState *cpu = current_cpu; +#if defined(TARGET_HAS_PRECISE_SMC) || !defined(CONFIG_USER_ONLY) + CPUArchState *env = NULL; +#endif tb_page_addr_t tb_start, tb_end; PageDesc *p; int n; @@ -1023,9 +1029,11 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end, /* build code bitmap */ build_page_bitmap(p); } - if (env != NULL) { - cpu = ENV_GET_CPU(env); +#if defined(TARGET_HAS_PRECISE_SMC) || !defined(CONFIG_USER_ONLY) + if (cpu != NULL) { + env = cpu->env_ptr; } +#endif /* we remove all the TBs in the range [start, end[ */ /* XXX: see if in some cases it could be faster to invalidate all @@ -1147,8 +1155,8 @@ static void tb_invalidate_phys_page(tb_page_addr_t addr, int n; #ifdef TARGET_HAS_PRECISE_SMC TranslationBlock *current_tb = NULL; - CPUArchState *env = cpu_single_env; - CPUState *cpu = NULL; + CPUState *cpu = current_cpu; + CPUArchState *env = NULL; int current_tb_modified = 0; target_ulong current_pc = 0; target_ulong current_cs_base = 0; @@ -1165,8 +1173,8 @@ static void tb_invalidate_phys_page(tb_page_addr_t addr, if (tb && pc != 0) { current_tb = tb_find_pc(pc); } - if (env != NULL) { - cpu = ENV_GET_CPU(env); + if (cpu != NULL) { + env = cpu->env_ptr; } #endif while (tb != NULL) { diff --git a/user-exec.c b/user-exec.c index fa7f1f1de..d45ca8e87 100644 --- a/user-exec.c +++ b/user-exec.c @@ -20,6 +20,7 @@ #include "cpu.h" #include "disas/disas.h" #include "tcg.h" +#include "qemu/bitops.h" #undef EAX #undef ECX @@ -81,6 +82,7 @@ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address, int is_write, sigset_t *old_set, void *puc) { + CPUArchState *env; int ret; #if defined(DEBUG_SIGNAL) @@ -93,9 +95,9 @@ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address, return 1; } + env = current_cpu->env_ptr; /* see if it is an MMU fault */ - ret = cpu_handle_mmu_fault(cpu_single_env, address, is_write, - MMU_USER_IDX); + ret = cpu_handle_mmu_fault(env, address, is_write, MMU_USER_IDX); if (ret < 0) { return 0; /* not an MMU fault */ } @@ -103,12 +105,12 @@ static inline int handle_cpu_signal(uintptr_t pc, unsigned long address, return 1; /* the MMU fault was handled without causing real CPU fault */ } /* now we have a real cpu fault */ - cpu_restore_state(cpu_single_env, pc); + cpu_restore_state(env, pc); /* we restore the process signal mask as the sigreturn should do it (XXX: use sigsetjmp) */ sigprocmask(SIG_SETMASK, old_set, NULL); - exception_action(cpu_single_env); + exception_action(env); /* never comes here */ return 1; @@ -441,8 +443,11 @@ int cpu_signal_handler(int host_signum, void *pinfo, #else pc = uc->uc_mcontext.arm_pc; #endif - /* XXX: compute is_write */ - is_write = 0; + + /* error_code is the FSR value, in which bit 11 is WnR (assuming a v6 or + * later processor; on v5 we will always report this as a read). + */ + is_write = extract32(uc->uc_mcontext.error_code, 11, 1); return handle_cpu_signal(pc, (unsigned long)info->si_addr, is_write, &uc->uc_sigmask, puc); diff --git a/util/qemu-error.c b/util/qemu-error.c index 08a36f480..fec02c607 100644 --- a/util/qemu-error.c +++ b/util/qemu-error.c @@ -196,6 +196,7 @@ void error_print_loc(void) } } +bool enable_timestamp_msg; /* * Print an error message to current monitor if we have one, else to stderr. * Format arguments like sprintf(). The result should not contain @@ -206,6 +207,15 @@ void error_print_loc(void) void error_report(const char *fmt, ...) { va_list ap; + GTimeVal tv; + gchar *timestr; + + if (enable_timestamp_msg) { + g_get_current_time(&tv); + timestr = g_time_val_to_iso8601(&tv); + error_printf("%s ", timestr); + g_free(timestr); + } error_print_loc(); va_start(ap, fmt); diff --git a/util/qemu-option.c b/util/qemu-option.c index 412c42551..e0ef426da 100644 --- a/util/qemu-option.c +++ b/util/qemu-option.c @@ -706,16 +706,12 @@ QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id) QemuOpts *opts; QTAILQ_FOREACH(opts, &list->head, next) { - if (!opts->id) { - if (!id) { - return opts; - } - continue; + if (!opts->id && !id) { + return opts; } - if (strcmp(opts->id, id) != 0) { - continue; + if (opts->id && id && !strcmp(opts->id, id)) { + return opts; } - return opts; } return NULL; } @@ -918,15 +914,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params, get_opt_value(value, sizeof(value), p+4); id = value; } - if (defaults) { - if (!id && !QTAILQ_EMPTY(&list->head)) { - opts = qemu_opts_find(list, NULL); - } else { - opts = qemu_opts_create(list, id, 0, &local_err); - } - } else { - opts = qemu_opts_create(list, id, 1, &local_err); - } + opts = qemu_opts_create(list, id, !defaults, &local_err); if (opts == NULL) { if (error_is_set(&local_err)) { qerror_report_err(local_err); diff --git a/vl.c b/vl.c index 6d9fd7d80..25b8f2ff3 100644 --- a/vl.c +++ b/vl.c @@ -409,7 +409,7 @@ static QemuOptsList qemu_machine_opts = { .help = "Dump current dtb to a file and quit", }, { .name = "phandle_start", - .type = QEMU_OPT_STRING, + .type = QEMU_OPT_NUMBER, .help = "The first phandle ID we may generate dynamically", }, { .name = "dt_compatible", @@ -516,6 +516,37 @@ static QemuOptsList qemu_realtime_opts = { }, }; +static QemuOptsList qemu_msg_opts = { + .name = "msg", + .head = QTAILQ_HEAD_INITIALIZER(qemu_msg_opts.head), + .desc = { + { + .name = "timestamp", + .type = QEMU_OPT_BOOL, + }, + { /* end of list */ } + }, +}; + +/** + * Get machine options + * + * Returns: machine options (never null). + */ +QemuOpts *qemu_get_machine_opts(void) +{ + QemuOptsList *list; + QemuOpts *opts; + + list = qemu_find_opts("machine"); + assert(list); + opts = qemu_opts_find(list, NULL); + if (!opts) { + opts = qemu_opts_create_nofail(list); + } + return opts; +} + const char *qemu_get_vm_name(void) { return qemu_name; @@ -1017,15 +1048,9 @@ static int parse_sandbox(QemuOpts *opts, void *opaque) return 0; } -/*********QEMU USB setting******/ bool usb_enabled(bool default_usb) { - QemuOpts *mach_opts; - mach_opts = qemu_opts_find(qemu_find_opts("machine"), 0); - if (mach_opts) { - return qemu_opt_get_bool(mach_opts, "usb", default_usb); - } - return default_usb; + return qemu_opt_get_bool(qemu_get_machine_opts(), "usb", default_usb); } #ifndef _WIN32 @@ -1490,6 +1515,12 @@ static void configure_realtime(QemuOpts *opts) } } + +static void configure_msg(QemuOpts *opts) +{ + enable_timestamp_msg = qemu_opt_get_bool(opts, "timestamp", true); +} + /***********************************************************/ /* USB devices */ @@ -2672,17 +2703,13 @@ static struct { static int configure_accelerator(void) { - const char *p = NULL; + const char *p; char buf[10]; int i, ret; bool accel_initialised = false; bool init_failed = false; - QemuOptsList *list = qemu_find_opts("machine"); - if (!QTAILQ_EMPTY(&list->head)) { - p = qemu_opt_get(QTAILQ_FIRST(&list->head), "accel"); - } - + p = qemu_opt_get(qemu_get_machine_opts(), "accel"); if (p == NULL) { /* Use the default "accelerator", tcg */ p = "tcg"; @@ -2933,6 +2960,7 @@ int main(int argc, char **argv, char **envp) qemu_add_opts(&qemu_object_opts); qemu_add_opts(&qemu_tpmdev_opts); qemu_add_opts(&qemu_realtime_opts); + qemu_add_opts(&qemu_msg_opts); runstate_init(); @@ -3829,6 +3857,13 @@ int main(int argc, char **argv, char **envp) } configure_realtime(opts); break; + case QEMU_OPTION_msg: + opts = qemu_opts_parse(qemu_find_opts("msg"), optarg, 0); + if (!opts) { + exit(1); + } + configure_msg(opts); + break; default: os_parse_cmd_args(popt->index, optarg); } @@ -4080,14 +4115,10 @@ int main(int argc, char **argv, char **envp) qtest_init(); } - machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); - if (machine_opts) { - kernel_filename = qemu_opt_get(machine_opts, "kernel"); - initrd_filename = qemu_opt_get(machine_opts, "initrd"); - kernel_cmdline = qemu_opt_get(machine_opts, "append"); - } else { - kernel_filename = initrd_filename = kernel_cmdline = NULL; - } + machine_opts = qemu_get_machine_opts(); + kernel_filename = qemu_opt_get(machine_opts, "kernel"); + initrd_filename = qemu_opt_get(machine_opts, "initrd"); + kernel_cmdline = qemu_opt_get(machine_opts, "append"); if (!boot_order) { boot_order = machine->boot_order; @@ -4130,7 +4161,7 @@ int main(int argc, char **argv, char **envp) exit(1); } - if (!linux_boot && machine_opts && qemu_opt_get(machine_opts, "dtb")) { + if (!linux_boot && qemu_opt_get(machine_opts, "dtb")) { fprintf(stderr, "-dtb only allowed with -kernel option\n"); exit(1); } diff --git a/xen-all.c b/xen-all.c index dcb57a0a5..21246e0ff 100644 --- a/xen-all.c +++ b/xen-all.c @@ -167,7 +167,7 @@ static void xen_ram_init(ram_addr_t ram_size) */ block_len += HVM_BELOW_4G_MMIO_LENGTH; } - memory_region_init_ram(&ram_memory, "xen.ram", block_len); + memory_region_init_ram(&ram_memory, NULL, "xen.ram", block_len); vmstate_register_ram_global(&ram_memory); if (ram_size >= HVM_BELOW_4G_RAM_END) { @@ -177,7 +177,7 @@ static void xen_ram_init(ram_addr_t ram_size) below_4g_mem_size = ram_size; } - memory_region_init_alias(&ram_640k, "xen.ram.640k", + memory_region_init_alias(&ram_640k, NULL, "xen.ram.640k", &ram_memory, 0, 0xa0000); memory_region_add_subregion(sysmem, 0, &ram_640k); /* Skip of the VGA IO memory space, it will be registered later by the VGA @@ -186,11 +186,11 @@ static void xen_ram_init(ram_addr_t ram_size) * The area between 0xc0000 and 0x100000 will be used by SeaBIOS to load * the Options ROM, so it is registered here as RAM. */ - memory_region_init_alias(&ram_lo, "xen.ram.lo", + memory_region_init_alias(&ram_lo, NULL, "xen.ram.lo", &ram_memory, 0xc0000, below_4g_mem_size - 0xc0000); memory_region_add_subregion(sysmem, 0xc0000, &ram_lo); if (above_4g_mem_size > 0) { - memory_region_init_alias(&ram_hi, "xen.ram.hi", + memory_region_init_alias(&ram_hi, NULL, "xen.ram.hi", &ram_memory, 0x100000000ULL, above_4g_mem_size); memory_region_add_subregion(sysmem, 0x100000000ULL, &ram_hi); @@ -459,6 +459,7 @@ static void xen_set_memory(struct MemoryListener *listener, static void xen_region_add(MemoryListener *listener, MemoryRegionSection *section) { + memory_region_ref(section->mr); xen_set_memory(listener, section, true); } @@ -466,6 +467,7 @@ static void xen_region_del(MemoryListener *listener, MemoryRegionSection *section) { xen_set_memory(listener, section, false); + memory_region_unref(section->mr); } static void xen_sync_dirty_bitmap(XenIOState *state,