[Qemu-devel] [PATCH 0/2] optimize waiting for free thread to do compression

2018-12-12 Thread guangrong . xiao
From: Xiao Guangrong 

Currently we have two behaviors if all threads are busy to do compression,
the main thread mush wait one of them becoming free if @compress-wait-thread
set to on or the main thread can directly return without wait and post
the page out as normal one

Both of them have its profits and short-comes, however, if the bandwidth is
not limited extremely so that compression can not use out all of it bandwidth,
at the same time, the migration process is easily throttled if we posted too
may pages as normal pages. None of them can work properly under this case

In order to use the bandwidth more effectively, we introduce the third
behavior, compress-wait-thread-adaptive, which make the main thread wait
if there is no bandwidth left or let the page go out as normal page if there
has enough bandwidth to make sure the migration process will not be
throttled

Another patch introduces a new statistic, pages-per-second, as bandwidth
or mbps is not enough to measure the performance of posting pages out as
we have compression, xbzrle, which can significantly reduce the amount of
the data size, instead, pages-per-second if the one we want

Performance data

We have limited the bandwidth to 300

Used Bandwidth Pages-per-Second
compress-wait-thread = on 951.66 mbps 131784

compress-wait-thread = off2491.74 mbps93495
compress-wait-thread-adaptive 1982.94 mbps162529
   = on

Xiao Guangrong (2):
  migration: introduce compress-wait-thread-adaptive
  migration: introduce pages-per-second

 hmp.c |  13 ++
 migration/migration.c |  49 +++-
 migration/migration.h |  12 +
 migration/ram.c   | 124 ++
 qapi/migration.json   |  31 +++--
 5 files changed, 215 insertions(+), 14 deletions(-)

-- 
2.14.5




[Qemu-devel] [PATCH 2/2] migration: introduce pages-per-second

2018-12-12 Thread guangrong . xiao
From: Xiao Guangrong 

It introduces a new statistic, pages-per-second, as bandwidth or mbps is
not enough to measure the performance of posting pages out as we have
compression, xbzrle, which can significantly reduce the amount of the
data size, instead, pages-per-second if the one we want

Signed-off-by: Xiao Guangrong 
---
 hmp.c |  2 ++
 migration/migration.c | 12 +++-
 migration/migration.h |  8 
 migration/ram.c   |  6 ++
 qapi/migration.json   |  5 -
 5 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/hmp.c b/hmp.c
index 2c5bb504d4..bd7e30cc2e 100644
--- a/hmp.c
+++ b/hmp.c
@@ -236,6 +236,8 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict)
info->ram->page_size >> 10);
 monitor_printf(mon, "multifd bytes: %" PRIu64 " kbytes\n",
info->ram->multifd_bytes >> 10);
+monitor_printf(mon, "pages-per-second: %" PRIu64 "\n",
+   info->ram->pages_per_second);
 
 if (info->ram->dirty_pages_rate) {
 monitor_printf(mon, "dirty pages rate: %" PRIu64 " pages\n",
diff --git a/migration/migration.c b/migration/migration.c
index d19935b529..2a54cd3423 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -780,6 +780,7 @@ static void populate_ram_info(MigrationInfo *info, 
MigrationState *s)
 info->ram->postcopy_requests = ram_counters.postcopy_requests;
 info->ram->page_size = qemu_target_page_size();
 info->ram->multifd_bytes = ram_counters.multifd_bytes;
+info->ram->pages_per_second = s->pages_per_second;
 
 if (migrate_use_xbzrle()) {
 info->has_xbzrle_cache = true;
@@ -1578,6 +1579,7 @@ void migrate_init(MigrationState *s)
 s->rp_state.from_dst_file = NULL;
 s->rp_state.error = false;
 s->mbps = 0.0;
+s->pages_per_second = 0.0;
 s->downtime = 0;
 s->expected_downtime = 0;
 s->setup_time = 0;
@@ -2914,7 +2916,7 @@ static void migration_calculate_complete(MigrationState 
*s)
 static void migration_update_counters(MigrationState *s,
   int64_t current_time)
 {
-uint64_t transferred, time_spent;
+uint64_t transferred, transferred_pages, time_spent;
 uint64_t current_bytes; /* bytes transferred since the beginning */
 double bandwidth;
 
@@ -2931,6 +2933,12 @@ static void migration_update_counters(MigrationState *s,
 s->mbps = (((double) transferred * 8.0) /
((double) time_spent / 1000.0)) / 1000.0 / 1000.0;
 
+
+transferred_pages = ram_get_total_transferred_pages() -
+s->iteration_initial_pages;
+s->pages_per_second = (double) transferred_pages /
+ (((double) time_spent / 1000.0));
+
 compress_adaptive_update(s->mbps);
 
 /*
@@ -2945,6 +2953,7 @@ static void migration_update_counters(MigrationState *s,
 
 s->iteration_start_time = current_time;
 s->iteration_initial_bytes = current_bytes;
+s->iteration_initial_pages = ram_get_total_transferred_pages();
 
 trace_migrate_transferred(transferred, time_spent,
   bandwidth, s->threshold_size);
@@ -3351,6 +3360,7 @@ static void migration_instance_init(Object *obj)
 
 ms->state = MIGRATION_STATUS_NONE;
 ms->mbps = -1;
+ms->pages_per_second = -1;
 qemu_sem_init(>pause_sem, 0);
 qemu_mutex_init(>error_mutex);
 
diff --git a/migration/migration.h b/migration/migration.h
index d631776230..73a6803cc4 100644
--- a/migration/migration.h
+++ b/migration/migration.h
@@ -126,6 +126,12 @@ struct MigrationState
  */
 QemuSemaphore rate_limit_sem;
 
+/* pages already send at the beggining of current interation */
+uint64_t iteration_initial_pages;
+
+/* pages transferred per second */
+double pages_per_second;
+
 /* bytes already send at the beggining of current interation */
 uint64_t iteration_initial_bytes;
 /* time at the start of current iteration */
@@ -279,6 +285,8 @@ int migrate_compress_wait_thread(void);
 int migrate_compress_wait_thread_adaptive(void);
 void compress_adaptive_update(double mbps);
 
+uint64_t ram_get_total_transferred_pages(void);
+
 int migrate_decompress_threads(void);
 bool migrate_use_events(void);
 bool migrate_postcopy_blocktime(void);
diff --git a/migration/ram.c b/migration/ram.c
index 3b08a605e4..b6b08a4800 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -1613,6 +1613,12 @@ uint64_t ram_pagesize_summary(void)
 return summary;
 }
 
+uint64_t ram_get_total_transferred_pages(void)
+{
+return  ram_counters.normal + ram_counters.duplicate +
+compression_counters.pages + xbzrle_counters.pages;
+}
+
 static void compress_adaptive_init(void)
 {
 /* fully wait on default. */
diff --git a/qapi/migration.json b/qapi/migration.json
index 6d925c73fc..e64b2e3901 100644
--- a/qapi/migration.json
+++ b/qapi/migration.json
@@ -41,6 +41,9 @@
 #
 # @multifd-bytes: 

Re: [Qemu-devel] [PULL 00/27] ppc-for-4.0 queue 20181213

2018-12-12 Thread no-reply
Patchew URL: 
https://patchew.org/QEMU/20181213040126.6768-1-da...@gibson.dropbear.id.au/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 20181213040126.6768-1-da...@gibson.dropbear.id.au
Subject: [Qemu-devel] [PULL 00/27] ppc-for-4.0 queue 20181213

=== TEST SCRIPT BEGIN ===
#!/bin/bash

BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0

git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram

commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..."
if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
failed=1
echo
fi
n=$((n+1))
done

exit $failed
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
ad20d15 spapr/xive: use the VCPU id as a NVT identifier
936bcd5 spapr/xive: introduce a XIVE interrupt controller
c13abc0 ppc/xive: notify the CPU when the interrupt priority is more privileged
58a0735 ppc/xive: introduce a simplified XIVE presenter
f463196 ppc/xive: introduce the XIVE interrupt thread context
b5b9c85 ppc/xive: add support for the END Event State Buffers
11d0460 Changes requirement for "vsubsbs" instruction
37e7503 spapr: export and rename the xics_max_server_number() routine
4d7a081 spapr: introduce a spapr_irq_init() routine
22e14d8 spapr: initialize VSMT before initializing the IRQ backend
e85821f ppc/xive: introduce the XIVE Event Notification Descriptors
37adf84 ppc/xive: introduce the XiveRouter model
b17c216 ppc/xive: introduce the XiveNotifier interface
e9aa0c9 ppc/xive: add support for the LSI interrupt sources
afa26a0 ppc/xive: introduce a XIVE interrupt source model
4052b1a e500: simplify IRQ wiring
f01edd5 mac_newworld: simplify IRQ wiring
dd09168 virtex_ml507: use g_new(T, n) instead of g_malloc(sizeof(T) * n)
001 sam460ex: use g_new(T, n) instead of g_malloc(sizeof(T) * n)
ae12a4c ppc440_bamboo: use g_new(T, n) instead of g_malloc(sizeof(T) * n)
0126aee ppc405_uc: use g_new(T, n) instead of g_malloc(sizeof(T) * n)
f9a1d51 ppc405_boards: use g_new(T, n) instead of g_malloc(sizeof(T) * n)
1dc1282 spapr: use g_new(T, n) instead of g_malloc(sizeof(T) * n)
61eb9c6 target/ppc: use g_new(T, n) instead of g_malloc(sizeof(T) * n)
db6492f spapr: drop redundant statement in spapr_populate_drconf_memory()
61d6352 target/ppc: tcg: Implement addex instruction
17ee949 spapr: Fix ibm, max-associativity-domains property number of nodes

=== OUTPUT BEGIN ===
Checking PATCH 1/27: spapr: Fix ibm, max-associativity-domains property number 
of nodes...
Checking PATCH 2/27: target/ppc: tcg: Implement addex instruction...
ERROR: space required after that ',' (ctx:VxV)
#42: FILE: disas/ppc.c:3737:
+{ "addex",   XO(31,170,0,0), XO_MASK,   POWER9, { RT, RA, RB } },
   ^

ERROR: space required after that ',' (ctx:VxV)
#42: FILE: disas/ppc.c:3737:
+{ "addex",   XO(31,170,0,0), XO_MASK,   POWER9, { RT, RA, RB } },
   ^

ERROR: space required after that ',' (ctx:VxV)
#42: FILE: disas/ppc.c:3737:
+{ "addex",   XO(31,170,0,0), XO_MASK,   POWER9, { RT, RA, RB } },
 ^

total: 3 errors, 0 warnings, 156 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 3/27: spapr: drop redundant statement in 
spapr_populate_drconf_memory()...
Checking PATCH 4/27: target/ppc: use g_new(T, n) instead of g_malloc(sizeof(T) 
* n)...
Checking PATCH 5/27: spapr: use g_new(T, n) instead of g_malloc(sizeof(T) * 
n)...
Checking PATCH 6/27: ppc405_boards: use g_new(T, n) instead of 
g_malloc(sizeof(T) * n)...
Checking PATCH 7/27: ppc405_uc: use g_new(T, n) instead of g_malloc(sizeof(T) * 
n)...
Checking PATCH 8/27: ppc440_bamboo: use g_new(T, n) instead of 
g_malloc(sizeof(T) * n)...
Checking PATCH 9/27: sam460ex: use g_new(T, n) instead of g_malloc(sizeof(T) * 
n)...
Checking PATCH 10/27: virtex_ml507: use g_new(T, n) instead of 
g_malloc(sizeof(T) * n)...
Checking PATCH 11/27: mac_newworld: simplify IRQ wiring...
Checking PATCH 12/27: e500: simplify IRQ wiring...
Checking PATCH 13/27: ppc/xive: introduce a XIVE interrupt source model...
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#61: 
new file mode 100644

total: 0 errors, 1 warnings, 656 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
Checking PATCH 14/27: ppc/xive: add support for the LSI interrupt sources...
Checking PATCH 15/27: ppc/xive: introduce the XiveNotifier interface...
Checking PATCH 16/27: ppc/xive: introduce the XiveRouter model...
WARNING: added, moved or deleted 

Re: [Qemu-devel] [PATCH for-4.0 v8 6/7] qemu_thread_create: propagate the error to callers to handle

2018-12-12 Thread Markus Armbruster
There's a question for David Gibson inline.  Please search for /ppc/.

Fei Li  writes:

> Make qemu_thread_create() return a Boolean to indicate if it succeeds
> rather than failing with an error. And add an Error parameter to hold
> the error message and let the callers handle it.

The "rather than failing with an error" is misleading.  Before the
patch, we report to stderr and abort().  What about:

qemu-thread: Make qemu_thread_create() handle errors properly

qemu_thread_create() abort()s on error.  Not nice.  Give it a
return value and an Error ** argument, so it can return success /
failure.

Still missing from the commit message then: how you update the callers.
Let's see below.

>
> Cc: Markus Armbruster 
> Cc: Daniel P. Berrangé 
> Cc: Dr. David Alan Gilbert 
> Signed-off-by: Fei Li 
> ---
>  cpus.c  | 45 -
>  dump.c  |  6 +++--
>  hw/misc/edu.c   |  6 +++--
>  hw/ppc/spapr_hcall.c| 10 +++--
>  hw/rdma/rdma_backend.c  |  4 +++-
>  hw/usb/ccid-card-emulated.c | 16 ++
>  include/qemu/thread.h   |  4 ++--
>  io/task.c   |  3 ++-
>  iothread.c  | 16 +-
>  migration/migration.c   | 54 
> +
>  migration/postcopy-ram.c| 14 ++--
>  migration/ram.c | 40 -
>  migration/savevm.c  | 11 ++---
>  tests/atomic_add-bench.c|  3 ++-
>  tests/iothread.c|  2 +-
>  tests/qht-bench.c   |  3 ++-
>  tests/rcutorture.c  |  3 ++-
>  tests/test-aio.c|  2 +-
>  tests/test-rcu-list.c   |  3 ++-
>  ui/vnc-jobs.c   | 17 +-
>  ui/vnc-jobs.h   |  2 +-
>  ui/vnc.c|  4 +++-
>  util/compatfd.c | 12 --
>  util/oslib-posix.c  | 17 ++
>  util/qemu-thread-posix.c| 24 +---
>  util/qemu-thread-win32.c| 16 ++
>  util/rcu.c  |  3 ++-
>  util/thread-pool.c  |  4 +++-
>  28 files changed, 243 insertions(+), 101 deletions(-)
>
> diff --git a/cpus.c b/cpus.c
> index 7b091bda53..e8450e518a 100644
> --- a/cpus.c
> +++ b/cpus.c
> @@ -1961,15 +1961,20 @@ static void qemu_tcg_init_vcpu(CPUState *cpu, Error 
> **errp)
>  snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/TCG",
>   cpu->cpu_index);
>  
> -qemu_thread_create(cpu->thread, thread_name, 
> qemu_tcg_cpu_thread_fn,
> -   cpu, QEMU_THREAD_JOINABLE);
> +if (!qemu_thread_create(cpu->thread, thread_name,
> +qemu_tcg_cpu_thread_fn, cpu,
> +QEMU_THREAD_JOINABLE, errp)) {
> +return;
> +}
>  
>  } else {
>  /* share a single thread for all cpus with TCG */
>  snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "ALL CPUs/TCG");
> -qemu_thread_create(cpu->thread, thread_name,
> -   qemu_tcg_rr_cpu_thread_fn,
> -   cpu, QEMU_THREAD_JOINABLE);
> +if (!qemu_thread_create(cpu->thread, thread_name,
> +qemu_tcg_rr_cpu_thread_fn, cpu,
> +QEMU_THREAD_JOINABLE, errp)) {
> +return;
> +}
>  
>  single_tcg_halt_cond = cpu->halt_cond;
>  single_tcg_cpu_thread = cpu->thread;

This is a caller that sets an error on failure.  You make it set an
error on qemu_thread_create() failure.  Makes sense.

> @@ -1997,8 +2002,10 @@ static void qemu_hax_start_vcpu(CPUState *cpu, Error 
> **errp)
>  
>  snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/HAX",
>   cpu->cpu_index);
> -qemu_thread_create(cpu->thread, thread_name, qemu_hax_cpu_thread_fn,
> -   cpu, QEMU_THREAD_JOINABLE);
> +if (!qemu_thread_create(cpu->thread, thread_name, qemu_hax_cpu_thread_fn,
> +cpu, QEMU_THREAD_JOINABLE, errp)) {
> +return;
> +}
>  #ifdef _WIN32
>  cpu->hThread = qemu_thread_get_handle(cpu->thread);
>  #endif

Likewise.  I'll stop commenting on this pattern now.

> @@ -2013,8 +2020,10 @@ static void qemu_kvm_start_vcpu(CPUState *cpu, Error 
> **errp)
>  qemu_cond_init(cpu->halt_cond);
>  snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/KVM",
>   cpu->cpu_index);
> -qemu_thread_create(cpu->thread, thread_name, qemu_kvm_cpu_thread_fn,
> -   cpu, QEMU_THREAD_JOINABLE);
> +if (!qemu_thread_create(cpu->thread, thread_name, qemu_kvm_cpu_thread_fn,
> +cpu, QEMU_THREAD_JOINABLE, errp)) {
> +/* keep 'if' here in case there is further error handling logic */
> +}
>  }
>  
>  

[Qemu-devel] [PATCH] qemu-options: Remove deprecated "-virtioconsole" option

2018-12-12 Thread Thomas Huth
It's been deprecated since QEMU 3.0, and nobody complained so far, so
it is time to remove this option now.

Signed-off-by: Thomas Huth 
---
 docs/qdev-device-use.txt |  4 
 include/hw/boards.h  |  1 -
 qemu-deprecated.texi |  5 
 qemu-options.hx  | 10 
 vl.c | 61 +---
 5 files changed, 1 insertion(+), 80 deletions(-)

diff --git a/docs/qdev-device-use.txt b/docs/qdev-device-use.txt
index 98229b3..cc53e97 100644
--- a/docs/qdev-device-use.txt
+++ b/docs/qdev-device-use.txt
@@ -190,10 +190,6 @@ The appropriate DEVNAME depends on the machine type.  For 
type "pc":
 
   -device usb-braille,chardev=braille -chardev braille,id=braille
 
-* -virtioconsole becomes
-  -device virtio-serial-pci,class=C,vectors=V,ioeventfd=IOEVENTFD,max_ports=N
-  -device virtconsole,is_console=NUM,nr=NR,name=NAME
-
 LEGACY-CHARDEV translates to -chardev HOST-OPTS... as follows:
 
 * null becomes -chardev null
diff --git a/include/hw/boards.h b/include/hw/boards.h
index f82f284..5df67d2 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -181,7 +181,6 @@ struct MachineClass {
 int default_cpus;
 unsigned int no_serial:1,
 no_parallel:1,
-use_virtcon:1,
 no_floppy:1,
 no_cdrom:1,
 no_sdcard:1,
diff --git a/qemu-deprecated.texi b/qemu-deprecated.texi
index 72b8191..5cc18b4 100644
--- a/qemu-deprecated.texi
+++ b/qemu-deprecated.texi
@@ -60,11 +60,6 @@ The @code{--no-frame} argument works with SDL 1.2 only. The 
other user
 interfaces never implemented this in the first place. So this will be
 removed together with SDL 1.2 support.
 
-@subsection -virtioconsole (since 3.0.0)
-
-Option @option{-virtioconsole} has been replaced by
-@option{-device virtconsole}.
-
 @subsection -clock (since 3.0.0)
 
 The @code{-clock} option is ignored since QEMU version 1.7.0. There is no
diff --git a/qemu-options.hx b/qemu-options.hx
index 269eda7..5330603 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3635,16 +3635,6 @@ character to Control-t.
 @end table
 ETEXI
 
-DEF("virtioconsole", HAS_ARG, QEMU_OPTION_virtiocon, \
-"-virtioconsole c\n" \
-"set virtio console\n", QEMU_ARCH_ALL)
-STEXI
-@item -virtioconsole @var{c}
-@findex -virtioconsole
-Set virtio console.
-This option is deprecated, please use @option{-device virtconsole} instead.
-ETEXI
-
 DEF("show-cursor", 0, QEMU_OPTION_show_cursor, \
 "-show-cursorshow cursor\n", QEMU_ARCH_ALL)
 STEXI
diff --git a/vl.c b/vl.c
index a5ae5f2..595d610 100644
--- a/vl.c
+++ b/vl.c
@@ -164,7 +164,6 @@ int no_frame;
 static int num_serial_hds;
 static Chardev **serial_hds;
 Chardev *parallel_hds[MAX_PARALLEL_PORTS];
-Chardev *virtcon_hds[MAX_VIRTIO_CONSOLES];
 int win2k_install_hack = 0;
 int singlestep = 0;
 int smp_cpus;
@@ -215,7 +214,6 @@ bool xen_domid_restrict;
 static int has_defaults = 1;
 static int default_serial = 1;
 static int default_parallel = 1;
-static int default_virtcon = 1;
 static int default_monitor = 1;
 static int default_floppy = 1;
 static int default_cdrom = 1;
@@ -236,8 +234,6 @@ static struct {
 { .driver = "ide-drive",.flag = _cdrom },
 { .driver = "scsi-cd",  .flag = _cdrom },
 { .driver = "scsi-hd",  .flag = _cdrom },
-{ .driver = "virtio-serial-pci",.flag = _virtcon   },
-{ .driver = "virtio-serial",.flag = _virtcon   },
 { .driver = "VGA",  .flag = _vga   },
 { .driver = "isa-vga",  .flag = _vga   },
 { .driver = "cirrus-vga",   .flag = _vga   },
@@ -2374,7 +2370,6 @@ struct device_config {
 DEV_BT,/* -bt*/
 DEV_SERIAL,/* -serial*/
 DEV_PARALLEL,  /* -parallel  */
-DEV_VIRTCON,   /* -virtioconsole */
 DEV_DEBUGCON,  /* -debugcon */
 DEV_GDB,   /* -gdb, -s */
 DEV_SCLP,  /* s390 sclp */
@@ -2472,39 +2467,6 @@ static int parallel_parse(const char *devname)
 return 0;
 }
 
-static int virtcon_parse(const char *devname)
-{
-QemuOptsList *device = qemu_find_opts("device");
-static int index = 0;
-char label[32];
-QemuOpts *bus_opts, *dev_opts;
-
-if (strcmp(devname, "none") == 0)
-return 0;
-if (index == MAX_VIRTIO_CONSOLES) {
-error_report("too many virtio consoles");
-exit(1);
-}
-
-bus_opts = qemu_opts_create(device, NULL, 0, _abort);
-qemu_opt_set(bus_opts, "driver", "virtio-serial", _abort);
-
-dev_opts = qemu_opts_create(device, NULL, 0, _abort);
-qemu_opt_set(dev_opts, "driver", "virtconsole", _abort);
-
-snprintf(label, sizeof(label), "virtcon%d", index);
-virtcon_hds[index] = qemu_chr_new_mux_mon(label, devname);
-if (!virtcon_hds[index]) {
-error_report("could not connect virtio console"
- " to character backend '%s'", devname);
-

Re: [Qemu-devel] [PATCH v3 1/3] Deprecate QMP `cpu-add`

2018-12-12 Thread Thomas Huth
On 2018-10-30 13:35, Kashyap Chamarthy wrote:
> The intended functionality of QMP `cpu-add` is replaced with
> `device_add` (and `query-hotpluggable-cpus`).  So let's deprecate
> `cpu-add`.
> 
> A complete example of vCPU hotplug with the recommended way (using
> `device_add`) is provided as part of a seperate docs patch.
> 
> Suggested-by: Eduardo Habkost  Signed-off-by: Kashyap Chamarthy 
> ---
[...]
> diff --git a/qemu-deprecated.texi b/qemu-deprecated.texi
> index 1b9c007f12..c86924ad9a 100644
> --- a/qemu-deprecated.texi
> +++ b/qemu-deprecated.texi
> @@ -155,6 +155,11 @@ The ``query-cpus'' command is replaced by the 
> ``query-cpus-fast'' command.
>  The ``arch'' output member of the ``query-cpus-fast'' command is
>  replaced by the ``target'' output member.
>  
> +@subsection cpu-add (since 3.1)

 Hi Kashyap,

could you please send a follow-up patch to change this into 4.0 now?

Please also provide a patch to add the HMP command to
qemu-deprecated.texi, too.

 Thanks,
  Thomas



Re: [Qemu-devel] [qemu-s390x] [PATCH] hw/s390/ccw.c: Don't take address of packed members

2018-12-12 Thread Thomas Huth
On 2018-12-10 14:58, Peter Maydell wrote:
> Taking the address of a field in a packed struct is a bad idea, because
> it might not be actually aligned enough for that pointer type (and
> thus cause a crash on dereference on some host architectures). Newer
> versions of clang warn about this.
> 
> Avoid the problem by using local copies of the PMCW and SCSW
> struct fields in copy_schib_from_guest() and copy_schib_to_guest().
> 
> Signed-off-by: Peter Maydell 
> ---
> This seemed like a not totally ugly and reasonably localised fix
> that satisfies clang. Oddly, this makes the generated object file
> 15K smaller (421K vs 406K), so it might even be better code...
> 
>  hw/s390x/css.c | 20 
>  1 file changed, 16 insertions(+), 4 deletions(-)
> 
> diff --git a/hw/s390x/css.c b/hw/s390x/css.c
> index 04ec5cc9705..ef07691e36b 100644
> --- a/hw/s390x/css.c
> +++ b/hw/s390x/css.c
> @@ -1290,9 +1290,15 @@ void copy_scsw_to_guest(SCSW *dest, const SCSW *src)
>  static void copy_schib_to_guest(SCHIB *dest, const SCHIB *src)
>  {
>  int i;
> +PMCW srcpmcw, destpmcw;
> +SCSW srcscsw, destscsw;
>  
> -copy_pmcw_to_guest(>pmcw, >pmcw);
> -copy_scsw_to_guest(>scsw, >scsw);
> +srcpmcw = src->pmcw;
> +copy_pmcw_to_guest(, );
> +dest->pmcw = destpmcw;
> +srcscsw = src->scsw;
> +copy_scsw_to_guest(, );
> +dest->scsw = destscsw;
>  dest->mba = cpu_to_be64(src->mba);
>  for (i = 0; i < ARRAY_SIZE(dest->mda); i++) {
>  dest->mda[i] = src->mda[i];
> @@ -1339,9 +1345,15 @@ static void copy_scsw_from_guest(SCSW *dest, const 
> SCSW *src)
>  static void copy_schib_from_guest(SCHIB *dest, const SCHIB *src)
>  {
>  int i;
> +PMCW srcpmcw, destpmcw;
> +SCSW srcscsw, destscsw;
>  
> -copy_pmcw_from_guest(>pmcw, >pmcw);
> -copy_scsw_from_guest(>scsw, >scsw);
> +srcpmcw = src->pmcw;
> +copy_pmcw_from_guest(, );
> +dest->pmcw = destpmcw;
> +srcscsw = src->scsw;
> +copy_scsw_from_guest(, );
> +dest->scsw = destscsw;
>  dest->mba = be64_to_cpu(src->mba);
>  for (i = 0; i < ARRAY_SIZE(dest->mda); i++) {
>  dest->mda[i] = src->mda[i];
> 

May I suggest to add a comment to the code here a la:

  /* Use a local copy to avoid unaligned access to packed structs */

or something similar? Otherwise, I'm pretty sure somebody will revert
this in a couple of years because they thinks the local copy is not
really necessary here...

 Thomas



Re: [Qemu-devel] [PATCH v2 0/7] bitmaps: remove x- prefix from QMP api

2018-12-12 Thread no-reply
Patchew URL: https://patchew.org/QEMU/20181213015013.15350-1-js...@redhat.com/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 20181213015013.15350-1-js...@redhat.com
Subject: [Qemu-devel] [PATCH v2 0/7] bitmaps: remove x- prefix from QMP api

=== TEST SCRIPT BEGIN ===
#!/bin/bash

BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0

git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram

commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
echo "Checking PATCH $n/$total: $(git log -n 1 --format=%s $c)..."
if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
failed=1
echo
fi
n=$((n+1))
done

exit $failed
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
7edca32 iotests: add iotest 236 for testing bitmap merge
4760f12 iotests: allow pretty-print for qmp_log
18479b6 iotests: add filter_generated_node_ids
e74d8c5 iotests.py: don't abort if IMGKEYSECRET is undefined
32d68bd4 block: remove 'x' prefix from experimental bitmap APIs
82059d7 blockdev: n-ary bitmap merge
51b6f48 blockdev: abort transactions in reverse order

=== OUTPUT BEGIN ===
Checking PATCH 1/7: blockdev: abort transactions in reverse order...
Checking PATCH 2/7: blockdev: n-ary bitmap merge...
ERROR: externs should be avoided in .c files
#27: FILE: blockdev.c:2125:
+void do_block_dirty_bitmap_merge(const char *node, const char *target,

total: 1 errors, 0 warnings, 147 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 3/7: block: remove 'x' prefix from experimental bitmap APIs...
Checking PATCH 4/7: iotests.py: don't abort if IMGKEYSECRET is undefined...
Checking PATCH 5/7: iotests: add filter_generated_node_ids...
Checking PATCH 6/7: iotests: allow pretty-print for qmp_log...
Checking PATCH 7/7: iotests: add iotest 236 for testing bitmap merge...
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#12: 
new file mode 100755

total: 0 errors, 1 warnings, 392 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
=== OUTPUT END ===

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/20181213015013.15350-1-js...@redhat.com/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-de...@redhat.com

Re: [Qemu-devel] [PATCH for-4.0 v8 3/7] migration: fix the multifd code when receiving less channels

2018-12-12 Thread Markus Armbruster
Fei Li  writes:

> In our current code, when multifd is used during migration, if there
> is an error before the destination receives all new channels, the
> source keeps running, however the destination does not exit but keeps
> waiting until the source is killed deliberately.
>
> Fix this by dumping the specific error and let users decide whether
> to quit from the destination side when failing to receive packet via
> some channel.
>
> Cc: Dr. David Alan Gilbert 
> Signed-off-by: Fei Li 
> Reviewed-by: Peter Xu 
> ---
>  migration/channel.c   | 11 ++-
>  migration/migration.c |  9 +++--
>  migration/migration.h |  2 +-
>  migration/ram.c   | 10 --
>  migration/ram.h   |  2 +-
>  5 files changed, 23 insertions(+), 11 deletions(-)
>
> diff --git a/migration/channel.c b/migration/channel.c
> index 33e0e9b82f..20e4c8e2dc 100644
> --- a/migration/channel.c
> +++ b/migration/channel.c
> @@ -30,6 +30,7 @@
>  void migration_channel_process_incoming(QIOChannel *ioc)
>  {
>  MigrationState *s = migrate_get_current();
> +Error *local_err = NULL;
>  
>  trace_migration_set_incoming_channel(
>  ioc, object_get_typename(OBJECT(ioc)));
> @@ -38,13 +39,13 @@ void migration_channel_process_incoming(QIOChannel *ioc)
>  *s->parameters.tls_creds &&
>  !object_dynamic_cast(OBJECT(ioc),
>   TYPE_QIO_CHANNEL_TLS)) {
> -Error *local_err = NULL;
>  migration_tls_channel_process_incoming(s, ioc, _err);
> -if (local_err) {
> -error_report_err(local_err);
> -}
>  } else {
> -migration_ioc_process_incoming(ioc);
> +migration_ioc_process_incoming(ioc, _err);
> +}
> +
> +if (local_err) {
> +error_report_err(local_err);
>  }
>  }
>  
> diff --git a/migration/migration.c b/migration/migration.c
> index 49ffb9997a..72106bddf0 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -541,7 +541,7 @@ void migration_fd_process_incoming(QEMUFile *f)
>  migration_incoming_process();
>  }
>  
> -void migration_ioc_process_incoming(QIOChannel *ioc)
> +void migration_ioc_process_incoming(QIOChannel *ioc, Error **errp)
>  {
>  MigrationIncomingState *mis = migration_incoming_get_current();
>  bool start_migration;
> @@ -563,9 +563,14 @@ void migration_ioc_process_incoming(QIOChannel *ioc)
>   */
>  start_migration = !migrate_use_multifd();
>  } else {
> +Error *local_err = NULL;
>  /* Multiple connections */
>  assert(migrate_use_multifd());
> -start_migration = multifd_recv_new_channel(ioc);
> +start_migration = multifd_recv_new_channel(ioc, _err);
> +if (local_err) {
> +error_propagate(errp, local_err);
> +return;
> +}
>  }
>  
>  if (start_migration) {
> diff --git a/migration/migration.h b/migration/migration.h
> index e413d4d8b6..02b7304610 100644
> --- a/migration/migration.h
> +++ b/migration/migration.h
> @@ -229,7 +229,7 @@ struct MigrationState
>  void migrate_set_state(int *state, int old_state, int new_state);
>  
>  void migration_fd_process_incoming(QEMUFile *f);
> -void migration_ioc_process_incoming(QIOChannel *ioc);
> +void migration_ioc_process_incoming(QIOChannel *ioc, Error **errp);
>  void migration_incoming_process(void);
>  
>  bool  migration_has_all_channels(void);
> diff --git a/migration/ram.c b/migration/ram.c
> index 7e7deec4d8..c7e3d6b0fd 100644
> --- a/migration/ram.c
> +++ b/migration/ram.c
> @@ -1323,7 +1323,7 @@ bool multifd_recv_all_channels_created(void)
>  }
>  
>  /* Return true if multifd is ready for the migration, otherwise false */
> -bool multifd_recv_new_channel(QIOChannel *ioc)
> +bool multifd_recv_new_channel(QIOChannel *ioc, Error **errp)
>  {
>  MultiFDRecvParams *p;
>  Error *local_err = NULL;
> @@ -1331,6 +1331,10 @@ bool multifd_recv_new_channel(QIOChannel *ioc)
>  
>  id = multifd_recv_initial_packet(ioc, _err);
>  if (id < 0) {
> +error_propagate_prepend(errp, local_err,
> +"failed to receive packet"
> +" via multifd channel %d: ",
> +atomic_read(_recv_state->count));
>  multifd_recv_terminate_threads(local_err);
>  return false;

Here, we return false without setting an error.

>  }
> @@ -1340,6 +1344,7 @@ bool multifd_recv_new_channel(QIOChannel *ioc)
>  error_setg(_err, "multifd: received id '%d' already setup'",
> id);
>  multifd_recv_terminate_threads(local_err);
> +error_propagate(errp, local_err);
>  return false;

Here, we return false with setting an error.

>  }
>  p->c = ioc;
> @@ -1351,7 +1356,8 @@ bool multifd_recv_new_channel(QIOChannel *ioc)
>  qemu_thread_create(>thread, p->name, multifd_recv_thread, p,
> QEMU_THREAD_JOINABLE);
>  

Re: [Qemu-devel] [PATCH for-4.0 v7 00/27] Hi,

2018-12-12 Thread Markus Armbruster
Marc-André Lureau  writes:

> Hi
>
> On Wed, Dec 12, 2018 at 9:18 PM Markus Armbruster  wrote:
>>
>> Marc-André Lureau  writes:
>>
>> > This is the second part of the "add #if pre-processor conditions to
>> > generated code" series, adding schema member conditions (roughly
>> > 16-38/49).
>> >
>> > Members can be exploded as dictionnary with 'type'/'if' keys:
>> >
>> > { 'struct': 'TestIfStruct', 'data':
>> >   { 'foo': 'int',
>> > 'bar': { 'type': 'int', 'if': 'defined(TEST_IF_STRUCT_BAR)'} } }
>> >
>> > Enum values can be exploded as dictionnary with 'type'/'if' keys:
>> >
>> > { 'enum': 'TestIfEnum', 'data':
>> >   [ 'foo',
>> > { 'name' : 'bar', 'if': 'defined(TEST_IF_ENUM_BAR)' } ] }
>>
>> PATCH 03,18,20,25 are only losely related to this second part.  They are
>> also ready.  Queued on branch qapi-next in my public repository, with
>> PATCH 18 and 20 squashed together.
>>
>> I took the liberty to implement the the idea on normalization I
>> mentioned in review of PATCH 08.  I also squashed a few patches that are
>> essentially fixups into the patches they fix.  I did not address any
>> other review comments.  Result is on branch qapi-if-2.  Please have a
>> look.
>>
>
> Looks good to me.  Is there something left to rework from this branch
> or it is good to go?
> thanks

I adressed only the one review comment that was hard to explain, plus
some patch squashing.  The other review comments still need to be
considered and worked in.




[Qemu-devel] [PATCH v5 65/73] s390x: convert to cpu_has_work_with_iothread_lock

2018-12-12 Thread Emilio G. Cota
Soon we will call cpu_has_work without the BQL.

Cc: Cornelia Huck 
Cc: Alexander Graf 
Cc: David Hildenbrand 
Cc: qemu-s3...@nongnu.org
Reviewed-by: Richard Henderson 
Signed-off-by: Emilio G. Cota 
---
 target/s390x/cpu.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
index d1594c90d9..5c38abaa49 100644
--- a/target/s390x/cpu.c
+++ b/target/s390x/cpu.c
@@ -59,6 +59,8 @@ static bool s390_cpu_has_work(CPUState *cs)
 {
 S390CPU *cpu = S390_CPU(cs);
 
+g_assert(qemu_mutex_iothread_locked());
+
 /* STOPPED cpus can never wake up */
 if (s390_cpu_get_state(cpu) != S390_CPU_STATE_LOAD &&
 s390_cpu_get_state(cpu) != S390_CPU_STATE_OPERATING) {
@@ -473,7 +475,7 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data)
 scc->initial_cpu_reset = s390_cpu_initial_reset;
 cc->reset = s390_cpu_full_reset;
 cc->class_by_name = s390_cpu_class_by_name,
-cc->has_work = s390_cpu_has_work;
+cc->has_work_with_iothread_lock = s390_cpu_has_work;
 #ifdef CONFIG_TCG
 cc->do_interrupt = s390_cpu_do_interrupt;
 #endif
-- 
2.17.1




[Qemu-devel] [PATCH v5 67/73] sparc: convert to cpu_has_work_with_iothread_lock

2018-12-12 Thread Emilio G. Cota
Soon we will call cpu_has_work without the BQL.

Cc: Mark Cave-Ayland 
Cc: Artyom Tarasenko 
Reviewed-by: Richard Henderson 
Signed-off-by: Emilio G. Cota 
---
 target/sparc/cpu.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
index 88427283c1..54bffc1a6c 100644
--- a/target/sparc/cpu.c
+++ b/target/sparc/cpu.c
@@ -709,6 +709,8 @@ static bool sparc_cpu_has_work(CPUState *cs)
 SPARCCPU *cpu = SPARC_CPU(cs);
 CPUSPARCState *env = >env;
 
+g_assert(qemu_mutex_iothread_locked());
+
 return (cpu_interrupt_request(cs) & CPU_INTERRUPT_HARD) &&
cpu_interrupts_enabled(env);
 }
@@ -870,7 +872,7 @@ static void sparc_cpu_class_init(ObjectClass *oc, void 
*data)
 
 cc->class_by_name = sparc_cpu_class_by_name;
 cc->parse_features = sparc_cpu_parse_features;
-cc->has_work = sparc_cpu_has_work;
+cc->has_work_with_iothread_lock = sparc_cpu_has_work;
 cc->do_interrupt = sparc_cpu_do_interrupt;
 cc->cpu_exec_interrupt = sparc_cpu_exec_interrupt;
 cc->dump_state = sparc_cpu_dump_state;
-- 
2.17.1




[Qemu-devel] [PATCH v5 18/73] ppc: convert to cpu_halted

2018-12-12 Thread Emilio G. Cota
In ppce500_spin.c, acquire the lock just once to update
both cpu->halted and cpu->stopped.

In hw/ppc/spapr_hcall.c, acquire the lock just once to
update cpu->halted and call cpu_has_work, since later
in the series we'll acquire the BQL (if not already held)
from cpu_has_work.

Cc: David Gibson 
Cc: Alexander Graf 
Cc: qemu-...@nongnu.org
Reviewed-by: Richard Henderson 
Signed-off-by: Emilio G. Cota 
---
 target/ppc/helper_regs.h|  2 +-
 hw/ppc/e500.c   |  4 ++--
 hw/ppc/ppc.c| 10 +-
 hw/ppc/ppce500_spin.c   |  6 --
 hw/ppc/spapr_cpu_core.c |  4 ++--
 hw/ppc/spapr_hcall.c|  4 +++-
 hw/ppc/spapr_rtas.c |  6 +++---
 target/ppc/excp_helper.c|  4 ++--
 target/ppc/kvm.c|  4 ++--
 target/ppc/translate_init.inc.c |  6 +++---
 10 files changed, 27 insertions(+), 23 deletions(-)

diff --git a/target/ppc/helper_regs.h b/target/ppc/helper_regs.h
index 5efd18049e..9298052ac5 100644
--- a/target/ppc/helper_regs.h
+++ b/target/ppc/helper_regs.h
@@ -161,7 +161,7 @@ static inline int hreg_store_msr(CPUPPCState *env, 
target_ulong value,
 #if !defined(CONFIG_USER_ONLY)
 if (unlikely(msr_pow == 1)) {
 if (!env->pending_interrupts && (*env->check_pow)(env)) {
-cs->halted = 1;
+cpu_halted_set(cs, 1);
 excp = EXCP_HALTED;
 }
 }
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index e6747fce28..6843c545b7 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -657,7 +657,7 @@ static void ppce500_cpu_reset_sec(void *opaque)
 
 /* Secondary CPU starts in halted state for now. Needs to change when
implementing non-kernel boot. */
-cs->halted = 1;
+cpu_halted_set(cs, 1);
 cs->exception_index = EXCP_HLT;
 }
 
@@ -671,7 +671,7 @@ static void ppce500_cpu_reset(void *opaque)
 cpu_reset(cs);
 
 /* Set initial guest state. */
-cs->halted = 0;
+cpu_halted_set(cs, 0);
 env->gpr[1] = (16 * MiB) - 8;
 env->gpr[3] = bi->dt_base;
 env->gpr[4] = 0;
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index ec4be25f49..d1a5a0b877 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -151,7 +151,7 @@ static void ppc6xx_set_irq(void *opaque, int pin, int level)
 /* XXX: Note that the only way to restart the CPU is to reset it */
 if (level) {
 LOG_IRQ("%s: stop the CPU\n", __func__);
-cs->halted = 1;
+cpu_halted_set(cs, 1);
 }
 break;
 case PPC6xx_INPUT_HRESET:
@@ -230,10 +230,10 @@ static void ppc970_set_irq(void *opaque, int pin, int 
level)
 /* XXX: TODO: relay the signal to CKSTP_OUT pin */
 if (level) {
 LOG_IRQ("%s: stop the CPU\n", __func__);
-cs->halted = 1;
+cpu_halted_set(cs, 1);
 } else {
 LOG_IRQ("%s: restart the CPU\n", __func__);
-cs->halted = 0;
+cpu_halted_set(cs, 0);
 qemu_cpu_kick(cs);
 }
 break;
@@ -361,10 +361,10 @@ static void ppc40x_set_irq(void *opaque, int pin, int 
level)
 /* Level sensitive - active low */
 if (level) {
 LOG_IRQ("%s: stop the CPU\n", __func__);
-cs->halted = 1;
+cpu_halted_set(cs, 1);
 } else {
 LOG_IRQ("%s: restart the CPU\n", __func__);
-cs->halted = 0;
+cpu_halted_set(cs, 0);
 qemu_cpu_kick(cs);
 }
 break;
diff --git a/hw/ppc/ppce500_spin.c b/hw/ppc/ppce500_spin.c
index c45fc858de..4b3532730f 100644
--- a/hw/ppc/ppce500_spin.c
+++ b/hw/ppc/ppce500_spin.c
@@ -107,9 +107,11 @@ static void spin_kick(CPUState *cs, run_on_cpu_data data)
 map_start = ldq_p(>addr) & ~(map_size - 1);
 mmubooke_create_initial_mapping(env, 0, map_start, map_size);
 
-cs->halted = 0;
-cs->exception_index = -1;
+cpu_mutex_lock(cs);
+cpu_halted_set(cs, 0);
 cs->stopped = false;
+cpu_mutex_unlock(cs);
+cs->exception_index = -1;
 qemu_cpu_kick(cs);
 }
 
diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c
index 2398ce62c0..4c9c60b53b 100644
--- a/hw/ppc/spapr_cpu_core.c
+++ b/hw/ppc/spapr_cpu_core.c
@@ -37,7 +37,7 @@ static void spapr_cpu_reset(void *opaque)
 /* All CPUs start halted.  CPU0 is unhalted from the machine level
  * reset code and the rest are explicitly started up by the guest
  * using an RTAS call */
-cs->halted = 1;
+cpu_halted_set(cs, 1);
 
 /* Set compatibility mode to match the boot CPU, which was either set
  * by the machine reset code or by CAS. This should never fail.
@@ -91,7 +91,7 @@ void spapr_cpu_set_entry_state(PowerPCCPU *cpu, target_ulong 
nip, target_ulong r
 env->nip = nip;
 env->gpr[3] = r3;
 kvmppc_set_reg_ppc_online(cpu, 1);
-CPU(cpu)->halted = 0;
+

[Qemu-devel] [PATCH v5 73/73] cputlb: queue async flush jobs without the BQL

2018-12-12 Thread Emilio G. Cota
This yields sizable scalability improvements, as the below results show.

Host: Two Intel E5-2683 v3 14-core CPUs at 2.00 GHz (Haswell)

Workload: Ubuntu 18.04 ppc64 compiling the linux kernel with
"make -j N", where N is the number of cores in the guest.

  Speedup vs a single thread (higher is better):

 14 +---+
|   ++   +  +   +  +  $$  + |
|$  |
|  $$   |
 12 |-+$A$$   +-|
|$$ |
| $$$   |
 10 |-+ $$##D#D   +-|
|$$$ #**B   |
|  $$*   *  |
|A$#* B |
  8 |-+$$B**  +-|
|$$**   |
|   $** |
  6 |-+   $$* +-|
|A**|
|   $B  |
|   $   |
  4 |-+$* +-|
|  $|
| $ |
  2 |-+  $+-|
|$ +cputlb-no-bql $$A$$ |
|   A   +per-cpu-lock ##D## |
|   ++   +  +   +  + baseline **B** |
  0 +---+
14   8  12  16 20  24 28
   Guest vCPUs
  png: https://imgur.com/zZRvS7q

Some notes:
- baseline corresponds to the commit before this series

- per-cpu-lock is the commit that converts the CPU loop to per-cpu locks.

- cputlb-no-bql is this commit.

- I'm using taskset to assign cores to threads, favouring locality whenever
  possible but not using SMT. When N=1, I'm using a single host core, which
  leads to superlinear speedups (since with more cores the I/O thread can 
execute
  while vCPU threads sleep). In the future I might use N+1 host cores for N
  guest cores to avoid this, or perhaps pin guest threads to cores one-by-one.

- Scalability is not good at 64 cores, where the BQL for handling
  interrupts dominates. I got this from another machine (a 64-core one),
  that unfortunately is much slower than this 28-core one, so I don't have
  the numbers for 1-16 cores. The plot is normalized at 16-core baseline
  performance, and therefore very ugly :-) https://imgur.com/XyKGkAw
  See below for an example of the *huge* amount of waiting on the BQL:

(qemu) info sync-profile
Type   Object  Call site Wait Time (s)  
   Count  Average (us)
--
BQL mutex  0x55ba286c9800  accel/tcg/cpu-exec.c:545 2868.85676  
14872596192.90
BQL mutex  0x55ba286c9800  hw/ppc/ppc.c:70   539.58924  
 3666820147.15
BQL mutex  0x55ba286c9800  target/ppc/helper_regs.h:105  323.49283  
 2544959127.11
mutex  [   2]  util/qemu-timer.c:426 181.38420  
 3666839 49.47
condvar[  61]  cpus.c:1327   136.50872  
   15379   8876.31
BQL mutex  0x55ba286c9800  accel/tcg/cpu-exec.c:516   86.14785  
  946301 91.04
condvar0x55ba286eb6a0  cpus-common.c:196  78.41010  
 126 622302.35
BQL mutex  0x55ba286c9800  util/main-loop.c:236   28.14795  
  272940103.13
mutex  [  64]  include/qom/cpu.h:514  17.87662  
75139413  0.24
BQL mutex  0x55ba286c9800  target/ppc/translate_init.inc.c:86657.04738  
   36528192.93
--

Single-threaded performance is affected very lightly. Results

[Qemu-devel] [PATCH v5 71/73] cpus-common: release BQL earlier in run_on_cpu

2018-12-12 Thread Emilio G. Cota
After completing the conversion to per-CPU locks, there is no need
to release the BQL after having called cpu_kick.

Reviewed-by: Richard Henderson 
Signed-off-by: Emilio G. Cota 
---
 cpus-common.c | 20 +---
 1 file changed, 5 insertions(+), 15 deletions(-)

diff --git a/cpus-common.c b/cpus-common.c
index 36ce9872bd..08031e37f4 100644
--- a/cpus-common.c
+++ b/cpus-common.c
@@ -145,6 +145,11 @@ void run_on_cpu(CPUState *cpu, run_on_cpu_func func, 
run_on_cpu_data data)
 return;
 }
 
+/* We are going to sleep on the CPU lock, so release the BQL */
+if (has_bql) {
+qemu_mutex_unlock_iothread();
+}
+
 wi.func = func;
 wi.data = data;
 wi.done = false;
@@ -153,21 +158,6 @@ void run_on_cpu(CPUState *cpu, run_on_cpu_func func, 
run_on_cpu_data data)
 
 cpu_mutex_lock(cpu);
 queue_work_on_cpu_locked(cpu, );
-
-/*
- * We are going to sleep on the CPU lock, so release the BQL.
- *
- * During the transition to per-CPU locks, we release the BQL _after_
- * having kicked the destination CPU (from queue_work_on_cpu_locked above).
- * This makes sure that the enqueued work will be seen by the CPU
- * after being woken up from the kick, since the CPU sleeps on the BQL.
- * Once we complete the transition to per-CPU locks, we will release
- * the BQL earlier in this function.
- */
-if (has_bql) {
-qemu_mutex_unlock_iothread();
-}
-
 while (!atomic_mb_read()) {
 CPUState *self_cpu = current_cpu;
 
-- 
2.17.1




[Qemu-devel] [PATCH v5 69/73] cpu: rename all_cpu_threads_idle to qemu_tcg_rr_all_cpu_threads_idle

2018-12-12 Thread Emilio G. Cota
This function is only called from TCG rr mode, so add
a prefix to mark this as well as an assertion.

Signed-off-by: Emilio G. Cota 
---
 cpus.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/cpus.c b/cpus.c
index fa66d84bc7..b89d3790d7 100644
--- a/cpus.c
+++ b/cpus.c
@@ -211,10 +211,12 @@ static bool cpu_thread_is_idle(CPUState *cpu)
 return true;
 }
 
-static bool all_cpu_threads_idle(void)
+static bool qemu_tcg_rr_all_cpu_threads_idle(void)
 {
 CPUState *cpu;
 
+g_assert(qemu_is_tcg_rr());
+
 CPU_FOREACH(cpu) {
 if (!cpu_thread_is_idle(cpu)) {
 return false;
@@ -692,7 +694,7 @@ void qemu_start_warp_timer(void)
 }
 
 if (replay_mode != REPLAY_MODE_PLAY) {
-if (!all_cpu_threads_idle()) {
+if (!qemu_tcg_rr_all_cpu_threads_idle()) {
 return;
 }
 
@@ -1325,7 +1327,7 @@ static void qemu_tcg_rr_wait_io_event(void)
 {
 CPUState *cpu;
 
-while (all_cpu_threads_idle()) {
+while (qemu_tcg_rr_all_cpu_threads_idle()) {
 stop_tcg_kick_timer();
 qemu_cond_wait(first_cpu->halt_cond, _global_mutex);
 }
@@ -1659,7 +1661,7 @@ static void *qemu_tcg_rr_cpu_thread_fn(void *arg)
 atomic_mb_set(>exit_request, 0);
 }
 
-if (use_icount && all_cpu_threads_idle()) {
+if (use_icount && qemu_tcg_rr_all_cpu_threads_idle()) {
 /*
  * When all cpus are sleeping (e.g in WFI), to avoid a deadlock
  * in the main_loop, wake it up in order to start the warp timer.
-- 
2.17.1




[Qemu-devel] [PATCH v5 44/73] ppc: convert to cpu_interrupt_request

2018-12-12 Thread Emilio G. Cota
Cc: David Gibson 
Cc: Alexander Graf 
Cc: qemu-...@nongnu.org
Reviewed-by: Richard Henderson 
Signed-off-by: Emilio G. Cota 
---
 hw/ppc/ppc.c|  2 +-
 target/ppc/excp_helper.c|  2 +-
 target/ppc/kvm.c|  4 ++--
 target/ppc/translate_init.inc.c | 14 +++---
 4 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index d1a5a0b877..bc1cefa13f 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -91,7 +91,7 @@ void ppc_set_irq(PowerPCCPU *cpu, int n_IRQ, int level)
 
 LOG_IRQ("%s: %p n_IRQ %d level %d => pending %08" PRIx32
 "req %08x\n", __func__, env, n_IRQ, level,
-env->pending_interrupts, CPU(cpu)->interrupt_request);
+env->pending_interrupts, cpu_interrupt_request(CPU(cpu)));
 
 if (locked) {
 qemu_mutex_unlock_iothread();
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 737c9c72be..75a434f46b 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -753,7 +753,7 @@ static void ppc_hw_interrupt(CPUPPCState *env)
 
 qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
   __func__, env, env->pending_interrupts,
-  cs->interrupt_request, (int)msr_me, (int)msr_ee);
+  cpu_interrupt_request(cs), (int)msr_me, (int)msr_ee);
 #endif
 /* External reset */
 if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
index 557faa3637..cebb73bd98 100644
--- a/target/ppc/kvm.c
+++ b/target/ppc/kvm.c
@@ -1336,7 +1336,7 @@ void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
  * interrupt, reset, etc) in PPC-specific env->irq_input_state. */
 if (!cap_interrupt_level &&
 run->ready_for_interrupt_injection &&
-(cs->interrupt_request & CPU_INTERRUPT_HARD) &&
+(cpu_interrupt_request(cs) & CPU_INTERRUPT_HARD) &&
 (env->irq_input_state & (1interrupt_request & CPU_INTERRUPT_HARD) && (msr_ee)) {
+if (!(cpu_interrupt_request(cs) & CPU_INTERRUPT_HARD) && (msr_ee)) {
 cpu_halted_set(cs, 1);
 cs->exception_index = EXCP_HLT;
 }
diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index 986bbd7eb4..757eb6df16 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -8463,7 +8463,7 @@ static bool cpu_has_work_POWER7(CPUState *cs)
 CPUPPCState *env = >env;
 
 if (cpu_halted(cs)) {
-if (!(cs->interrupt_request & CPU_INTERRUPT_HARD)) {
+if (!(cpu_interrupt_request(cs) & CPU_INTERRUPT_HARD)) {
 return false;
 }
 if ((env->pending_interrupts & (1u << PPC_INTERRUPT_EXT)) &&
@@ -8487,7 +8487,7 @@ static bool cpu_has_work_POWER7(CPUState *cs)
 }
 return false;
 } else {
-return msr_ee && (cs->interrupt_request & CPU_INTERRUPT_HARD);
+return msr_ee && (cpu_interrupt_request(cs) & CPU_INTERRUPT_HARD);
 }
 }
 
@@ -8617,7 +8617,7 @@ static bool cpu_has_work_POWER8(CPUState *cs)
 CPUPPCState *env = >env;
 
 if (cpu_halted(cs)) {
-if (!(cs->interrupt_request & CPU_INTERRUPT_HARD)) {
+if (!(cpu_interrupt_request(cs) & CPU_INTERRUPT_HARD)) {
 return false;
 }
 if ((env->pending_interrupts & (1u << PPC_INTERRUPT_EXT)) &&
@@ -8649,7 +8649,7 @@ static bool cpu_has_work_POWER8(CPUState *cs)
 }
 return false;
 } else {
-return msr_ee && (cs->interrupt_request & CPU_INTERRUPT_HARD);
+return msr_ee && (cpu_interrupt_request(cs) & CPU_INTERRUPT_HARD);
 }
 }
 
@@ -8809,7 +8809,7 @@ static bool cpu_has_work_POWER9(CPUState *cs)
 CPUPPCState *env = >env;
 
 if (cpu_halted(cs)) {
-if (!(cs->interrupt_request & CPU_INTERRUPT_HARD)) {
+if (!(cpu_interrupt_request(cs) & CPU_INTERRUPT_HARD)) {
 return false;
 }
 /* External Exception */
@@ -8842,7 +8842,7 @@ static bool cpu_has_work_POWER9(CPUState *cs)
 }
 return false;
 } else {
-return msr_ee && (cs->interrupt_request & CPU_INTERRUPT_HARD);
+return msr_ee && (cpu_interrupt_request(cs) & CPU_INTERRUPT_HARD);
 }
 }
 
@@ -10253,7 +10253,7 @@ static bool ppc_cpu_has_work(CPUState *cs)
 PowerPCCPU *cpu = POWERPC_CPU(cs);
 CPUPPCState *env = >env;
 
-return msr_ee && (cs->interrupt_request & CPU_INTERRUPT_HARD);
+return msr_ee && (cpu_interrupt_request(cs) & CPU_INTERRUPT_HARD);
 }
 
 /* CPUClass::reset() */
-- 
2.17.1




[Qemu-devel] [PATCH v5 66/73] riscv: convert to cpu_has_work_with_iothread_lock

2018-12-12 Thread Emilio G. Cota
Soon we will call cpu_has_work without the BQL.

Cc: Michael Clark 
Cc: Palmer Dabbelt 
Cc: Sagar Karandikar 
Cc: Bastian Koppelmann 
Reviewed-by: Palmer Dabbelt 
Reviewed-by: Richard Henderson 
Signed-off-by: Emilio G. Cota 
---
 target/riscv/cpu.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index a025a0a3ba..9de76be471 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -251,6 +251,9 @@ static bool riscv_cpu_has_work(CPUState *cs)
 #ifndef CONFIG_USER_ONLY
 RISCVCPU *cpu = RISCV_CPU(cs);
 CPURISCVState *env = >env;
+
+g_assert(qemu_mutex_iothread_locked());
+
 /*
  * Definition of the WFI instruction requires it to ignore the privilege
  * mode and delegation registers, but respect individual enables
@@ -337,7 +340,7 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data)
 cc->reset = riscv_cpu_reset;
 
 cc->class_by_name = riscv_cpu_class_by_name;
-cc->has_work = riscv_cpu_has_work;
+cc->has_work_with_iothread_lock = riscv_cpu_has_work;
 cc->do_interrupt = riscv_cpu_do_interrupt;
 cc->cpu_exec_interrupt = riscv_cpu_exec_interrupt;
 cc->dump_state = riscv_cpu_dump_state;
-- 
2.17.1




[Qemu-devel] [PATCH v5 51/73] nios: convert to cpu_interrupt_request

2018-12-12 Thread Emilio G. Cota
Cc: Chris Wulff 
Cc: Marek Vasut 
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 target/nios2/cpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/nios2/cpu.c b/target/nios2/cpu.c
index fbfaa2ce26..49a75414d3 100644
--- a/target/nios2/cpu.c
+++ b/target/nios2/cpu.c
@@ -36,7 +36,7 @@ static void nios2_cpu_set_pc(CPUState *cs, vaddr value)
 
 static bool nios2_cpu_has_work(CPUState *cs)
 {
-return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
+return cpu_interrupt_request(cs) & (CPU_INTERRUPT_HARD | 
CPU_INTERRUPT_NMI);
 }
 
 /* CPUClass::reset() */
-- 
2.17.1




[Qemu-devel] [PATCH v5 17/73] arm: convert to cpu_halted

2018-12-12 Thread Emilio G. Cota
Cc: Andrzej Zaborowski 
Cc: Peter Maydell 
Cc: qemu-...@nongnu.org
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 hw/arm/omap1.c| 4 ++--
 hw/arm/pxa2xx_gpio.c  | 2 +-
 hw/arm/pxa2xx_pic.c   | 2 +-
 target/arm/arm-powerctl.c | 4 ++--
 target/arm/cpu.c  | 2 +-
 target/arm/op_helper.c| 2 +-
 6 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
index 539d29ef9c..55a7672976 100644
--- a/hw/arm/omap1.c
+++ b/hw/arm/omap1.c
@@ -1769,7 +1769,7 @@ static uint64_t omap_clkdsp_read(void *opaque, hwaddr 
addr,
 case 0x18: /* DSP_SYSST */
 cpu = CPU(s->cpu);
 return (s->clkm.clocking_scheme << 11) | s->clkm.cold_start |
-(cpu->halted << 6);  /* Quite useless... */
+(cpu_halted(cpu) << 6);  /* Quite useless... */
 }
 
 OMAP_BAD_REG(addr);
@@ -3790,7 +3790,7 @@ void omap_mpu_wakeup(void *opaque, int irq, int req)
 struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
 CPUState *cpu = CPU(mpu->cpu);
 
-if (cpu->halted) {
+if (cpu_halted(cpu)) {
 cpu_interrupt(cpu, CPU_INTERRUPT_EXITTB);
 }
 }
diff --git a/hw/arm/pxa2xx_gpio.c b/hw/arm/pxa2xx_gpio.c
index e15070188e..5c3fea42e9 100644
--- a/hw/arm/pxa2xx_gpio.c
+++ b/hw/arm/pxa2xx_gpio.c
@@ -128,7 +128,7 @@ static void pxa2xx_gpio_set(void *opaque, int line, int 
level)
 pxa2xx_gpio_irq_update(s);
 
 /* Wake-up GPIOs */
-if (cpu->halted && (mask & ~s->dir[bank] & pxa2xx_gpio_wake[bank])) {
+if (cpu_halted(cpu) && (mask & ~s->dir[bank] & pxa2xx_gpio_wake[bank])) {
 cpu_interrupt(cpu, CPU_INTERRUPT_EXITTB);
 }
 }
diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c
index 61275fa040..46ab4c3fc2 100644
--- a/hw/arm/pxa2xx_pic.c
+++ b/hw/arm/pxa2xx_pic.c
@@ -58,7 +58,7 @@ static void pxa2xx_pic_update(void *opaque)
 PXA2xxPICState *s = (PXA2xxPICState *) opaque;
 CPUState *cpu = CPU(s->cpu);
 
-if (cpu->halted) {
+if (cpu_halted(cpu)) {
 mask[0] = s->int_pending[0] & (s->int_enabled[0] | s->int_idle);
 mask[1] = s->int_pending[1] & (s->int_enabled[1] | s->int_idle);
 if (mask[0] || mask[1]) {
diff --git a/target/arm/arm-powerctl.c b/target/arm/arm-powerctl.c
index 2b856930fb..003bf6c184 100644
--- a/target/arm/arm-powerctl.c
+++ b/target/arm/arm-powerctl.c
@@ -64,7 +64,7 @@ static void arm_set_cpu_on_async_work(CPUState 
*target_cpu_state,
 
 /* Initialize the cpu we are turning on */
 cpu_reset(target_cpu_state);
-target_cpu_state->halted = 0;
+cpu_halted_set(target_cpu_state, 0);
 
 if (info->target_aa64) {
 if ((info->target_el < 3) && arm_feature(_cpu->env,
@@ -238,7 +238,7 @@ static void arm_set_cpu_off_async_work(CPUState 
*target_cpu_state,
 
 assert(qemu_mutex_iothread_locked());
 target_cpu->power_state = PSCI_OFF;
-target_cpu_state->halted = 1;
+cpu_halted_set(target_cpu_state, 1);
 target_cpu_state->exception_index = EXCP_HLT;
 }
 
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 60411f6bfe..8baa5bb891 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -149,7 +149,7 @@ static void arm_cpu_reset(CPUState *s)
 env->vfp.xregs[ARM_VFP_MVFR2] = cpu->isar.mvfr2;
 
 cpu->power_state = cpu->start_powered_off ? PSCI_OFF : PSCI_ON;
-s->halted = cpu->start_powered_off;
+cpu_halted_set(s, cpu->start_powered_off);
 
 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
 env->iwmmxt.cregs[ARM_IWMMXT_wCID] = 0x69051000 | 'Q';
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index 0d6e89e474..4c8c7204d4 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -465,7 +465,7 @@ void HELPER(wfi)(CPUARMState *env, uint32_t insn_len)
 }
 
 cs->exception_index = EXCP_HLT;
-cs->halted = 1;
+cpu_halted_set(cs, 1);
 cpu_loop_exit(cs);
 }
 
-- 
2.17.1




[Qemu-devel] [PATCH v5 63/73] ppc: convert to cpu_has_work_with_iothread_lock

2018-12-12 Thread Emilio G. Cota
Soon we will call cpu_has_work without the BQL.

Cc: David Gibson 
Cc: Alexander Graf 
Cc: qemu-...@nongnu.org
Reviewed-by: Richard Henderson 
Signed-off-by: Emilio G. Cota 
---
 target/ppc/translate_init.inc.c | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index 757eb6df16..cf453cb099 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -8462,6 +8462,8 @@ static bool cpu_has_work_POWER7(CPUState *cs)
 PowerPCCPU *cpu = POWERPC_CPU(cs);
 CPUPPCState *env = >env;
 
+g_assert(qemu_mutex_iothread_locked());
+
 if (cpu_halted(cs)) {
 if (!(cpu_interrupt_request(cs) & CPU_INTERRUPT_HARD)) {
 return false;
@@ -8505,7 +8507,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
 pcc->pcr_supported = PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
 pcc->init_proc = init_proc_POWER7;
 pcc->check_pow = check_pow_nocheck;
-cc->has_work = cpu_has_work_POWER7;
+cc->has_work_with_iothread_lock = cpu_has_work_POWER7;
 pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -8616,6 +8618,8 @@ static bool cpu_has_work_POWER8(CPUState *cs)
 PowerPCCPU *cpu = POWERPC_CPU(cs);
 CPUPPCState *env = >env;
 
+g_assert(qemu_mutex_iothread_locked());
+
 if (cpu_halted(cs)) {
 if (!(cpu_interrupt_request(cs) & CPU_INTERRUPT_HARD)) {
 return false;
@@ -8667,7 +8671,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
 pcc->pcr_supported = PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
 pcc->init_proc = init_proc_POWER8;
 pcc->check_pow = check_pow_nocheck;
-cc->has_work = cpu_has_work_POWER8;
+cc->has_work_with_iothread_lock = cpu_has_work_POWER8;
 pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -8808,6 +8812,8 @@ static bool cpu_has_work_POWER9(CPUState *cs)
 PowerPCCPU *cpu = POWERPC_CPU(cs);
 CPUPPCState *env = >env;
 
+g_assert(qemu_mutex_iothread_locked());
+
 if (cpu_halted(cs)) {
 if (!(cpu_interrupt_request(cs) & CPU_INTERRUPT_HARD)) {
 return false;
@@ -8861,7 +8867,7 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
  PCR_COMPAT_2_05;
 pcc->init_proc = init_proc_POWER9;
 pcc->check_pow = check_pow_nocheck;
-cc->has_work = cpu_has_work_POWER9;
+cc->has_work_with_iothread_lock = cpu_has_work_POWER9;
 pcc->insns_flags = PPC_INSNS_BASE | PPC_ISEL | PPC_STRING | PPC_MFTB |
PPC_FLOAT | PPC_FLOAT_FSEL | PPC_FLOAT_FRES |
PPC_FLOAT_FSQRT | PPC_FLOAT_FRSQRTE |
@@ -10253,6 +10259,8 @@ static bool ppc_cpu_has_work(CPUState *cs)
 PowerPCCPU *cpu = POWERPC_CPU(cs);
 CPUPPCState *env = >env;
 
+g_assert(qemu_mutex_iothread_locked());
+
 return msr_ee && (cpu_interrupt_request(cs) & CPU_INTERRUPT_HARD);
 }
 
@@ -10452,7 +10460,7 @@ static void ppc_cpu_class_init(ObjectClass *oc, void 
*data)
 cc->class_by_name = ppc_cpu_class_by_name;
 pcc->parent_parse_features = cc->parse_features;
 cc->parse_features = ppc_cpu_parse_featurestr;
-cc->has_work = ppc_cpu_has_work;
+cc->has_work_with_iothread_lock = ppc_cpu_has_work;
 cc->do_interrupt = ppc_cpu_do_interrupt;
 cc->cpu_exec_interrupt = ppc_cpu_exec_interrupt;
 cc->dump_state = ppc_cpu_dump_state;
-- 
2.17.1




[Qemu-devel] [PATCH v5 64/73] mips: convert to cpu_has_work_with_iothread_lock

2018-12-12 Thread Emilio G. Cota
Soon we will call cpu_has_work without the BQL.

Cc: Aurelien Jarno 
Cc: Aleksandar Markovic 
Reviewed-by: Richard Henderson 
Signed-off-by: Emilio G. Cota 
---
 target/mips/cpu.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index fdae8cf440..de1eb771fa 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -58,6 +58,8 @@ static bool mips_cpu_has_work(CPUState *cs)
 bool has_work = false;
 uint32_t interrupt_request = cpu_interrupt_request(cs);
 
+g_assert(qemu_mutex_iothread_locked());
+
 /* Prior to MIPS Release 6 it is implementation dependent if non-enabled
interrupts wake-up the CPU, however most of the implementations only
check for interrupts that can be taken. */
@@ -190,7 +192,7 @@ static void mips_cpu_class_init(ObjectClass *c, void *data)
 cc->reset = mips_cpu_reset;
 
 cc->class_by_name = mips_cpu_class_by_name;
-cc->has_work = mips_cpu_has_work;
+cc->has_work_with_iothread_lock = mips_cpu_has_work;
 cc->do_interrupt = mips_cpu_do_interrupt;
 cc->cpu_exec_interrupt = mips_cpu_exec_interrupt;
 cc->dump_state = mips_cpu_dump_state;
-- 
2.17.1




[Qemu-devel] [PATCH v5 62/73] cpu: introduce cpu_has_work_with_iothread_lock

2018-12-12 Thread Emilio G. Cota
It will gain some users soon.

Suggested-by: Paolo Bonzini 
Reviewed-by: Richard Henderson 
Signed-off-by: Emilio G. Cota 
---
 include/qom/cpu.h | 36 +---
 1 file changed, 33 insertions(+), 3 deletions(-)

diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 8d4160689f..8c239c54d8 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -26,6 +26,7 @@
 #include "exec/memattrs.h"
 #include "qapi/qapi-types-run-state.h"
 #include "qemu/bitmap.h"
+#include "qemu/main-loop.h"
 #include "qemu/rcu_queue.h"
 #include "qemu/queue.h"
 #include "qemu/thread.h"
@@ -86,6 +87,8 @@ struct TranslationBlock;
  * @reset_dump_flags: #CPUDumpFlags to use for reset logging.
  * @has_work: Callback for checking if there is work to do. Called with the
  * CPU lock held.
+ * @has_work_with_iothread_lock: Callback for checking if there is work to do.
+ * Called with both the BQL and the CPU lock held.
  * @do_interrupt: Callback for interrupt handling.
  * @do_unassigned_access: Callback for unassigned access handling.
  * (this is deprecated: new targets should use do_transaction_failed instead)
@@ -157,6 +160,7 @@ typedef struct CPUClass {
 void (*reset)(CPUState *cpu);
 int reset_dump_flags;
 bool (*has_work)(CPUState *cpu);
+bool (*has_work_with_iothread_lock)(CPUState *cpu);
 void (*do_interrupt)(CPUState *cpu);
 CPUUnassignedAccess do_unassigned_access;
 void (*do_unaligned_access)(CPUState *cpu, vaddr addr,
@@ -788,14 +792,40 @@ const char *parse_cpu_model(const char *cpu_model);
 static inline bool cpu_has_work(CPUState *cpu)
 {
 CPUClass *cc = CPU_GET_CLASS(cpu);
+bool has_cpu_lock = cpu_mutex_locked(cpu);
+bool (*func)(CPUState *cpu);
 bool ret;
 
+if (cc->has_work_with_iothread_lock) {
+if (qemu_mutex_iothread_locked()) {
+func = cc->has_work_with_iothread_lock;
+goto call_func;
+}
+
+if (has_cpu_lock) {
+/* avoid deadlock by acquiring the locks in order */
+cpu_mutex_unlock(cpu);
+}
+qemu_mutex_lock_iothread();
+cpu_mutex_lock(cpu);
+
+ret = cc->has_work_with_iothread_lock(cpu);
+
+qemu_mutex_unlock_iothread();
+if (!has_cpu_lock) {
+cpu_mutex_unlock(cpu);
+}
+return ret;
+}
+
 g_assert(cc->has_work);
-if (cpu_mutex_locked(cpu)) {
-return cc->has_work(cpu);
+func = cc->has_work;
+ call_func:
+if (has_cpu_lock) {
+return func(cpu);
 }
 cpu_mutex_lock(cpu);
-ret = cc->has_work(cpu);
+ret = func(cpu);
 cpu_mutex_unlock(cpu);
 return ret;
 }
-- 
2.17.1




Re: [Qemu-devel] [PATCH v2 6/6] pvrdma: check return value from pvrdma_idx_ring_has_ routines

2018-12-12 Thread Yuval Shaia
On Thu, Dec 13, 2018 at 01:00:39AM +0530, P J P wrote:
> From: Prasad J Pandit 
> 
> pvrdma_idx_ring_has_[data/space] routines also return invalid
> index PVRDMA_INVALID_IDX[=-1], if ring has no data/space. Check
> return value from these routines to avoid plausible infinite loops.
> 
> Reported-by: Li Qiang 
> Signed-off-by: Prasad J Pandit 
> ---
>  hw/rdma/vmw/pvrdma_dev_ring.c | 29 +++--
>  1 file changed, 11 insertions(+), 18 deletions(-)
> 
> Update: revert use of idx variable in pvrdma_ring_next_elem_read()
>   -> https://lists.gnu.org/archive/html/qemu-devel/2018-12/msg02814.html
> 
> diff --git a/hw/rdma/vmw/pvrdma_dev_ring.c b/hw/rdma/vmw/pvrdma_dev_ring.c
> index 01247fc041..e8e5b502f6 100644
> --- a/hw/rdma/vmw/pvrdma_dev_ring.c
> +++ b/hw/rdma/vmw/pvrdma_dev_ring.c
> @@ -73,23 +73,16 @@ out:
>  
>  void *pvrdma_ring_next_elem_read(PvrdmaRing *ring)
>  {
> +int e;
>  unsigned int idx = 0, offset;
>  
> -/*
> -pr_dbg("%s: t=%d, h=%d\n", ring->name, ring->ring_state->prod_tail,
> -   ring->ring_state->cons_head);
> -*/
> -
> -if (!pvrdma_idx_ring_has_data(ring->ring_state, ring->max_elems, )) {
> +e = pvrdma_idx_ring_has_data(ring->ring_state, ring->max_elems, );
> +if (e <= 0) {
>  pr_dbg("No more data in ring\n");
>  return NULL;
>  }
>  
>  offset = idx * ring->elem_sz;
> -/*
> -pr_dbg("idx=%d\n", idx);
> -pr_dbg("offset=%d\n", offset);
> -*/
>  return ring->pages[offset / TARGET_PAGE_SIZE] + (offset % 
> TARGET_PAGE_SIZE);
>  }
>  
> @@ -105,20 +98,20 @@ void pvrdma_ring_read_inc(PvrdmaRing *ring)
>  
>  void *pvrdma_ring_next_elem_write(PvrdmaRing *ring)
>  {
> -unsigned int idx, offset, tail;
> +int idx;
> +unsigned int offset, tail;
>  
> -/*
> -pr_dbg("%s: t=%d, h=%d\n", ring->name, ring->ring_state->prod_tail,
> -   ring->ring_state->cons_head);
> -*/
> -
> -if (!pvrdma_idx_ring_has_space(ring->ring_state, ring->max_elems, 
> )) {
> +idx = pvrdma_idx_ring_has_space(ring->ring_state, ring->max_elems, 
> );
> +if (idx <= 0) {
>  pr_dbg("CQ is full\n");
>  return NULL;
>  }
>  
>  idx = pvrdma_idx(>ring_state->prod_tail, ring->max_elems);
> -/* TODO: tail == idx */
> +if (idx < 0 || tail != idx) {
> +pr_dbg("invalid idx\n");
> +return NULL;
> +}
>  
>  offset = idx * ring->elem_sz;
>  return ring->pages[offset / TARGET_PAGE_SIZE] + (offset % 
> TARGET_PAGE_SIZE);

Thanks.

Reviewed-by: Yuval Shaia 

> -- 
> 2.19.2
> 



[Qemu-devel] [PATCH v5 68/73] xtensa: convert to cpu_has_work_with_iothread_lock

2018-12-12 Thread Emilio G. Cota
Soon we will call cpu_has_work without the BQL.

Cc: Max Filippov 
Reviewed-by: Richard Henderson 
Signed-off-by: Emilio G. Cota 
---
 target/xtensa/cpu.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
index d4ca35e6cc..5f3b4a70b0 100644
--- a/target/xtensa/cpu.c
+++ b/target/xtensa/cpu.c
@@ -47,6 +47,8 @@ static bool xtensa_cpu_has_work(CPUState *cs)
 #ifndef CONFIG_USER_ONLY
 XtensaCPU *cpu = XTENSA_CPU(cs);
 
+g_assert(qemu_mutex_iothread_locked());
+
 return !cpu->env.runstall && cpu->env.pending_irq_level;
 #else
 return true;
@@ -173,7 +175,7 @@ static void xtensa_cpu_class_init(ObjectClass *oc, void 
*data)
 cc->reset = xtensa_cpu_reset;
 
 cc->class_by_name = xtensa_cpu_class_by_name;
-cc->has_work = xtensa_cpu_has_work;
+cc->has_work_with_iothread_lock = xtensa_cpu_has_work;
 cc->do_interrupt = xtensa_cpu_do_interrupt;
 cc->cpu_exec_interrupt = xtensa_cpu_exec_interrupt;
 cc->dump_state = xtensa_cpu_dump_state;
-- 
2.17.1




[Qemu-devel] [PATCH v5 52/73] s390x: convert to cpu_interrupt_request

2018-12-12 Thread Emilio G. Cota
Cc: Cornelia Huck 
Cc: Christian Borntraeger 
Cc: Alexander Graf 
Cc: David Hildenbrand 
Cc: qemu-s3...@nongnu.org
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Reviewed-by: Cornelia Huck 
Signed-off-by: Emilio G. Cota 
---
 hw/intc/s390_flic.c | 2 +-
 target/s390x/cpu.c  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c
index bfb5cf1d07..d944824e67 100644
--- a/hw/intc/s390_flic.c
+++ b/hw/intc/s390_flic.c
@@ -189,7 +189,7 @@ static void qemu_s390_flic_notify(uint32_t type)
 CPU_FOREACH(cs) {
 S390CPU *cpu = S390_CPU(cs);
 
-cs->interrupt_request |= CPU_INTERRUPT_HARD;
+cpu_interrupt_request_or(cs, CPU_INTERRUPT_HARD);
 
 /* ignore CPUs that are not sleeping */
 if (s390_cpu_get_state(cpu) != S390_CPU_STATE_OPERATING &&
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
index 4d70ba785c..d1594c90d9 100644
--- a/target/s390x/cpu.c
+++ b/target/s390x/cpu.c
@@ -65,7 +65,7 @@ static bool s390_cpu_has_work(CPUState *cs)
 return false;
 }
 
-if (!(cs->interrupt_request & CPU_INTERRUPT_HARD)) {
+if (!(cpu_interrupt_request(cs) & CPU_INTERRUPT_HARD)) {
 return false;
 }
 
-- 
2.17.1




[Qemu-devel] [PATCH v5 61/73] cpu: call .cpu_has_work with the CPU lock held

2018-12-12 Thread Emilio G. Cota
Reviewed-by: Richard Henderson 
Signed-off-by: Emilio G. Cota 
---
 include/qom/cpu.h | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 95747f5abf..8d4160689f 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -84,7 +84,8 @@ struct TranslationBlock;
  * @parse_features: Callback to parse command line arguments.
  * @reset: Callback to reset the #CPUState to its initial state.
  * @reset_dump_flags: #CPUDumpFlags to use for reset logging.
- * @has_work: Callback for checking if there is work to do.
+ * @has_work: Callback for checking if there is work to do. Called with the
+ * CPU lock held.
  * @do_interrupt: Callback for interrupt handling.
  * @do_unassigned_access: Callback for unassigned access handling.
  * (this is deprecated: new targets should use do_transaction_failed instead)
@@ -787,9 +788,16 @@ const char *parse_cpu_model(const char *cpu_model);
 static inline bool cpu_has_work(CPUState *cpu)
 {
 CPUClass *cc = CPU_GET_CLASS(cpu);
+bool ret;
 
 g_assert(cc->has_work);
-return cc->has_work(cpu);
+if (cpu_mutex_locked(cpu)) {
+return cc->has_work(cpu);
+}
+cpu_mutex_lock(cpu);
+ret = cc->has_work(cpu);
+cpu_mutex_unlock(cpu);
+return ret;
 }
 
 /**
-- 
2.17.1




Re: [Qemu-devel] [PATCH v2 5/6] rdma: remove unused VENDOR_ERR_NO_SGE macro

2018-12-12 Thread Yuval Shaia
On Thu, Dec 13, 2018 at 01:00:38AM +0530, P J P wrote:
> From: Prasad J Pandit 
> 
> With commit 4481985c (rdma: check num_sge does not exceed MAX_SGE)
> macro VENDOR_ERR_NO_SGE is no longer in use - delete it.
> 
> Signed-off-by: Prasad J Pandit 
> ---
>  hw/rdma/rdma_backend.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> Update: change commit log message
>   -> https://lists.gnu.org/archive/html/qemu-devel/2018-12/msg02793.html
> 
> diff --git a/hw/rdma/rdma_backend.c b/hw/rdma/rdma_backend.c
> index bd4710d16f..c28bfbd44d 100644
> --- a/hw/rdma/rdma_backend.c
> +++ b/hw/rdma/rdma_backend.c
> @@ -37,12 +37,11 @@
>  #define VENDOR_ERR_TOO_MANY_SGES0x202
>  #define VENDOR_ERR_NOMEM0x203
>  #define VENDOR_ERR_QP0  0x204
> -#define VENDOR_ERR_NO_SGE   0x205
> +#define VENDOR_ERR_INV_NUM_SGE  0x205
>  #define VENDOR_ERR_MAD_SEND 0x206
>  #define VENDOR_ERR_INVLKEY  0x207
>  #define VENDOR_ERR_MR_SMALL 0x208
>  #define VENDOR_ERR_INV_MAD_BUFF 0x209
> -#define VENDOR_ERR_INV_NUM_SGE  0x210
>  
>  #define THR_NAME_LEN 16
>  #define THR_POLL_TO  5000

Thanks.

Reviewed-by: Yuval Shaia 

> -- 
> 2.19.2
> 



[Qemu-devel] [PATCH v5 36/73] s390x: use cpu_reset_interrupt

2018-12-12 Thread Emilio G. Cota
From: Paolo Bonzini 

Cc: Cornelia Huck 
Cc: Alexander Graf 
Cc: David Hildenbrand 
Cc: qemu-s3...@nongnu.org
Reviewed-by: David Hildenbrand 
Reviewed-by: Richard Henderson 
Reviewed-by: Cornelia Huck 
Reviewed-by: Alex Bennée 
Signed-off-by: Paolo Bonzini 
Signed-off-by: Emilio G. Cota 
---
 target/s390x/excp_helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c
index d22c5b3ce5..7ca50b3df6 100644
--- a/target/s390x/excp_helper.c
+++ b/target/s390x/excp_helper.c
@@ -454,7 +454,7 @@ try_deliver:
 
 /* we might still have pending interrupts, but not deliverable */
 if (!env->pending_int && !qemu_s390_flic_has_any(flic)) {
-cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
+cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
 }
 
 /* WAIT PSW during interrupt injection or STOP interrupt */
-- 
2.17.1




[Qemu-devel] [PATCH v5 70/73] cpu: protect CPU state with cpu->lock instead of the BQL

2018-12-12 Thread Emilio G. Cota
Use the per-CPU locks to protect the CPUs' state, instead of
using the BQL. These locks are uncontended (they are mostly
acquired by the corresponding vCPU thread), so acquiring them
is cheaper than acquiring the BQL, which particularly in
MTTCG can be contended at high core counts.

In this conversion we drop qemu_cpu_cond and qemu_pause_cond,
and use cpu->cond instead.

In qom/cpu.c we can finally remove the ugliness that
results from having to hold both the BQL and the CPU lock;
now we just have to grab the CPU lock.

Signed-off-by: Emilio G. Cota 
---
 include/qom/cpu.h |  20 ++--
 cpus.c| 280 ++
 qom/cpu.c |  29 +
 3 files changed, 225 insertions(+), 104 deletions(-)

diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 8c239c54d8..bcb46c3946 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -291,10 +291,6 @@ struct qemu_work_item;
  * valid under cpu_list_lock.
  * @created: Indicates whether the CPU thread has been successfully created.
  * @interrupt_request: Indicates a pending interrupt request.
- * @halted: Nonzero if the CPU is in suspended state.
- * @stop: Indicates a pending stop request.
- * @stopped: Indicates the CPU has been artificially stopped.
- * @unplug: Indicates a pending CPU unplug request.
  * @crash_occurred: Indicates the OS reported a crash (panic) for this CPU
  * @singlestep_enabled: Flags for single-stepping.
  * @icount_extra: Instructions until next timer event.
@@ -323,6 +319,10 @@ struct qemu_work_item;
  * @lock: Lock to prevent multiple access to per-CPU fields.
  * @cond: Condition variable for per-CPU events.
  * @work_list: List of pending asynchronous work.
+ * @halted: Nonzero if the CPU is in suspended state.
+ * @stop: Indicates a pending stop request.
+ * @stopped: Indicates the CPU has been artificially stopped.
+ * @unplug: Indicates a pending CPU unplug request.
  * @trace_dstate_delayed: Delayed changes to trace_dstate (includes all changes
  *to @trace_dstate).
  * @trace_dstate: Dynamic tracing state of events for this vCPU (bitmask).
@@ -346,12 +346,7 @@ struct CPUState {
 #endif
 int thread_id;
 bool running, has_waiter;
-struct QemuCond *halt_cond;
 bool thread_kicked;
-bool created;
-bool stop;
-bool stopped;
-bool unplug;
 bool crash_occurred;
 bool exit_request;
 uint32_t cflags_next_tb;
@@ -365,7 +360,13 @@ struct CPUState {
 QemuMutex *lock;
 /* fields below protected by @lock */
 QemuCond cond;
+QemuCond *halt_cond;
 QSIMPLEQ_HEAD(, qemu_work_item) work_list;
+uint32_t halted;
+bool created;
+bool stop;
+bool stopped;
+bool unplug;
 
 CPUAddressSpace *cpu_ases;
 int num_ases;
@@ -412,7 +413,6 @@ struct CPUState {
 
 /* TODO Move common fields from CPUArchState here. */
 int cpu_index;
-uint32_t halted;
 uint32_t can_do_io;
 int32_t exception_index;
 
diff --git a/cpus.c b/cpus.c
index b89d3790d7..d8261903ac 100644
--- a/cpus.c
+++ b/cpus.c
@@ -181,24 +181,30 @@ bool cpu_mutex_locked(const CPUState *cpu)
 return test_bit(cpu->cpu_index + 1, cpu_lock_bitmap);
 }
 
-bool cpu_is_stopped(CPUState *cpu)
+/* Called with the CPU's lock held */
+static bool cpu_is_stopped_locked(CPUState *cpu)
 {
 return cpu->stopped || !runstate_is_running();
 }
 
-static inline bool cpu_work_list_empty(CPUState *cpu)
+bool cpu_is_stopped(CPUState *cpu)
 {
-bool ret;
+if (!cpu_mutex_locked(cpu)) {
+bool ret;
 
-cpu_mutex_lock(cpu);
-ret = QSIMPLEQ_EMPTY(>work_list);
-cpu_mutex_unlock(cpu);
-return ret;
+cpu_mutex_lock(cpu);
+ret = cpu_is_stopped_locked(cpu);
+cpu_mutex_unlock(cpu);
+return ret;
+}
+return cpu_is_stopped_locked(cpu);
 }
 
 static bool cpu_thread_is_idle(CPUState *cpu)
 {
-if (cpu->stop || !cpu_work_list_empty(cpu)) {
+g_assert(cpu_mutex_locked(cpu));
+
+if (cpu->stop || !QSIMPLEQ_EMPTY(>work_list)) {
 return false;
 }
 if (cpu_is_stopped(cpu)) {
@@ -216,9 +222,17 @@ static bool qemu_tcg_rr_all_cpu_threads_idle(void)
 CPUState *cpu;
 
 g_assert(qemu_is_tcg_rr());
+g_assert(qemu_mutex_iothread_locked());
+g_assert(no_cpu_mutex_locked());
 
 CPU_FOREACH(cpu) {
-if (!cpu_thread_is_idle(cpu)) {
+bool is_idle;
+
+cpu_mutex_lock(cpu);
+is_idle = cpu_thread_is_idle(cpu);
+cpu_mutex_unlock(cpu);
+
+if (!is_idle) {
 return false;
 }
 }
@@ -780,6 +794,8 @@ void qemu_start_warp_timer(void)
 
 static void qemu_account_warp_timer(void)
 {
+g_assert(qemu_mutex_iothread_locked());
+
 if (!use_icount || !icount_sleep) {
 return;
 }
@@ -1090,6 +1106,7 @@ static void kick_tcg_thread(void *opaque)
 static void start_tcg_kick_timer(void)
 {
 assert(!mttcg_enabled);
+g_assert(qemu_mutex_iothread_locked());
 if (!tcg_kick_vcpu_timer && 

[Qemu-devel] [PATCH v5 57/73] unicore32: convert to cpu_interrupt_request

2018-12-12 Thread Emilio G. Cota
Cc: Guan Xuetao 
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 target/unicore32/cpu.c | 2 +-
 target/unicore32/softmmu.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/unicore32/cpu.c b/target/unicore32/cpu.c
index 2b49d1ca40..65c5334551 100644
--- a/target/unicore32/cpu.c
+++ b/target/unicore32/cpu.c
@@ -29,7 +29,7 @@ static void uc32_cpu_set_pc(CPUState *cs, vaddr value)
 
 static bool uc32_cpu_has_work(CPUState *cs)
 {
-return cs->interrupt_request &
+return cpu_interrupt_request(cs) &
 (CPU_INTERRUPT_HARD | CPU_INTERRUPT_EXITTB);
 }
 
diff --git a/target/unicore32/softmmu.c b/target/unicore32/softmmu.c
index 00c7e0d028..f58e2361e0 100644
--- a/target/unicore32/softmmu.c
+++ b/target/unicore32/softmmu.c
@@ -119,7 +119,7 @@ void uc32_cpu_do_interrupt(CPUState *cs)
 /* The PC already points to the proper instruction.  */
 env->regs[30] = env->regs[31];
 env->regs[31] = addr;
-cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
+cpu_interrupt_request_or(cs, CPU_INTERRUPT_EXITTB);
 }
 
 static int get_phys_addr_ucv2(CPUUniCore32State *env, uint32_t address,
-- 
2.17.1




[Qemu-devel] [PATCH v5 38/73] arm: convert to cpu_interrupt_request

2018-12-12 Thread Emilio G. Cota
Cc: Peter Maydell 
Cc: qemu-...@nongnu.org
Reviewed-by: Richard Henderson 
Signed-off-by: Emilio G. Cota 
---
 target/arm/cpu.c|  6 +++---
 target/arm/helper.c | 16 +++-
 2 files changed, 10 insertions(+), 12 deletions(-)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 8baa5bb891..738b80944c 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -49,7 +49,7 @@ static bool arm_cpu_has_work(CPUState *cs)
 ARMCPU *cpu = ARM_CPU(cs);
 
 return (cpu->power_state != PSCI_OFF)
-&& cs->interrupt_request &
+&& cpu_interrupt_request(cs) &
 (CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD
  | CPU_INTERRUPT_VFIQ | CPU_INTERRUPT_VIRQ
  | CPU_INTERRUPT_EXITTB);
@@ -448,7 +448,7 @@ void arm_cpu_update_virq(ARMCPU *cpu)
 bool new_state = (env->cp15.hcr_el2 & HCR_VI) ||
 (env->irq_line_state & CPU_INTERRUPT_VIRQ);
 
-if (new_state != ((cs->interrupt_request & CPU_INTERRUPT_VIRQ) != 0)) {
+if (new_state != ((cpu_interrupt_request(cs) & CPU_INTERRUPT_VIRQ) != 0)) {
 if (new_state) {
 cpu_interrupt(cs, CPU_INTERRUPT_VIRQ);
 } else {
@@ -469,7 +469,7 @@ void arm_cpu_update_vfiq(ARMCPU *cpu)
 bool new_state = (env->cp15.hcr_el2 & HCR_VF) ||
 (env->irq_line_state & CPU_INTERRUPT_VFIQ);
 
-if (new_state != ((cs->interrupt_request & CPU_INTERRUPT_VFIQ) != 0)) {
+if (new_state != ((cpu_interrupt_request(cs) & CPU_INTERRUPT_VFIQ) != 0)) {
 if (new_state) {
 cpu_interrupt(cs, CPU_INTERRUPT_VFIQ);
 } else {
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 0da1424f72..8c9b1210b2 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -1328,23 +1328,24 @@ static uint64_t isr_read(CPUARMState *env, const 
ARMCPRegInfo *ri)
 {
 CPUState *cs = ENV_GET_CPU(env);
 uint64_t ret = 0;
+uint32_t interrupt_request = cpu_interrupt_request(cs);
 
 if (arm_hcr_el2_imo(env)) {
-if (cs->interrupt_request & CPU_INTERRUPT_VIRQ) {
+if (interrupt_request & CPU_INTERRUPT_VIRQ) {
 ret |= CPSR_I;
 }
 } else {
-if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
+if (interrupt_request & CPU_INTERRUPT_HARD) {
 ret |= CPSR_I;
 }
 }
 
 if (arm_hcr_el2_fmo(env)) {
-if (cs->interrupt_request & CPU_INTERRUPT_VFIQ) {
+if (interrupt_request & CPU_INTERRUPT_VFIQ) {
 ret |= CPSR_F;
 }
 } else {
-if (cs->interrupt_request & CPU_INTERRUPT_FIQ) {
+if (interrupt_request & CPU_INTERRUPT_FIQ) {
 ret |= CPSR_F;
 }
 }
@@ -8693,10 +8694,7 @@ void arm_cpu_do_interrupt(CPUState *cs)
 return;
 }
 
-/* Hooks may change global state so BQL should be held, also the
- * BQL needs to be held for any modification of
- * cs->interrupt_request.
- */
+/* Hooks may change global state so BQL should be held */
 g_assert(qemu_mutex_iothread_locked());
 
 arm_call_pre_el_change_hook(cpu);
@@ -8711,7 +8709,7 @@ void arm_cpu_do_interrupt(CPUState *cs)
 arm_call_el_change_hook(cpu);
 
 if (!kvm_enabled()) {
-cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
+cpu_interrupt_request_or(cs, CPU_INTERRUPT_EXITTB);
 }
 }
 
-- 
2.17.1




[Qemu-devel] [PATCH v5 72/73] cpu: add async_run_on_cpu_no_bql

2018-12-12 Thread Emilio G. Cota
Some async jobs do not need the BQL.

Reviewed-by: Richard Henderson 
Signed-off-by: Emilio G. Cota 
---
 include/qom/cpu.h | 14 ++
 cpus-common.c | 39 ++-
 2 files changed, 48 insertions(+), 5 deletions(-)

diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index bcb46c3946..7ef0120213 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -876,9 +876,23 @@ void run_on_cpu(CPUState *cpu, run_on_cpu_func func, 
run_on_cpu_data data);
  * @data: Data to pass to the function.
  *
  * Schedules the function @func for execution on the vCPU @cpu asynchronously.
+ * See also: async_run_on_cpu_no_bql()
  */
 void async_run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data 
data);
 
+/**
+ * async_run_on_cpu_no_bql:
+ * @cpu: The vCPU to run on.
+ * @func: The function to be executed.
+ * @data: Data to pass to the function.
+ *
+ * Schedules the function @func for execution on the vCPU @cpu asynchronously.
+ * This function is run outside the BQL.
+ * See also: async_run_on_cpu()
+ */
+void async_run_on_cpu_no_bql(CPUState *cpu, run_on_cpu_func func,
+ run_on_cpu_data data);
+
 /**
  * async_safe_run_on_cpu:
  * @cpu: The vCPU to run on.
diff --git a/cpus-common.c b/cpus-common.c
index 08031e37f4..a8f913b918 100644
--- a/cpus-common.c
+++ b/cpus-common.c
@@ -109,6 +109,7 @@ struct qemu_work_item {
 run_on_cpu_func func;
 run_on_cpu_data data;
 bool free, exclusive, done;
+bool bql;
 };
 
 /* Called with the CPU's lock held */
@@ -155,6 +156,7 @@ void run_on_cpu(CPUState *cpu, run_on_cpu_func func, 
run_on_cpu_data data)
 wi.done = false;
 wi.free = false;
 wi.exclusive = false;
+wi.bql = true;
 
 cpu_mutex_lock(cpu);
 queue_work_on_cpu_locked(cpu, );
@@ -179,6 +181,21 @@ void async_run_on_cpu(CPUState *cpu, run_on_cpu_func func, 
run_on_cpu_data data)
 wi->func = func;
 wi->data = data;
 wi->free = true;
+wi->bql = true;
+
+queue_work_on_cpu(cpu, wi);
+}
+
+void async_run_on_cpu_no_bql(CPUState *cpu, run_on_cpu_func func,
+ run_on_cpu_data data)
+{
+struct qemu_work_item *wi;
+
+wi = g_malloc0(sizeof(struct qemu_work_item));
+wi->func = func;
+wi->data = data;
+wi->free = true;
+/* wi->bql initialized to false */
 
 queue_work_on_cpu(cpu, wi);
 }
@@ -323,6 +340,7 @@ void async_safe_run_on_cpu(CPUState *cpu, run_on_cpu_func 
func,
 wi->data = data;
 wi->free = true;
 wi->exclusive = true;
+/* wi->bql initialized to false */
 
 queue_work_on_cpu(cpu, wi);
 }
@@ -347,6 +365,7 @@ static void process_queued_cpu_work_locked(CPUState *cpu)
  * BQL, so it goes to sleep; start_exclusive() is sleeping too, so
  * neither CPU can proceed.
  */
+g_assert(!wi->bql);
 if (has_bql) {
 qemu_mutex_unlock_iothread();
 }
@@ -357,12 +376,22 @@ static void process_queued_cpu_work_locked(CPUState *cpu)
 qemu_mutex_lock_iothread();
 }
 } else {
-if (has_bql) {
-wi->func(cpu, wi->data);
+if (wi->bql) {
+if (has_bql) {
+wi->func(cpu, wi->data);
+} else {
+qemu_mutex_lock_iothread();
+wi->func(cpu, wi->data);
+qemu_mutex_unlock_iothread();
+}
 } else {
-qemu_mutex_lock_iothread();
-wi->func(cpu, wi->data);
-qemu_mutex_unlock_iothread();
+if (has_bql) {
+qemu_mutex_unlock_iothread();
+wi->func(cpu, wi->data);
+qemu_mutex_lock_iothread();
+} else {
+wi->func(cpu, wi->data);
+}
 }
 }
 cpu_mutex_lock(cpu);
-- 
2.17.1




[Qemu-devel] [PATCH v5 40/73] i386/kvm: convert to cpu_interrupt_request

2018-12-12 Thread Emilio G. Cota
Reviewed-by: Richard Henderson 
Signed-off-by: Emilio G. Cota 
---
 target/i386/kvm.c | 54 +++
 1 file changed, 31 insertions(+), 23 deletions(-)

diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index a3d1f47556..61b9473403 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -2875,11 +2875,14 @@ static int kvm_put_vcpu_events(X86CPU *cpu, int level)
 events.smi.smm = !!(env->hflags & HF_SMM_MASK);
 events.smi.smm_inside_nmi = !!(env->hflags2 & HF2_SMM_INSIDE_NMI_MASK);
 if (kvm_irqchip_in_kernel()) {
+uint32_t interrupt_request;
+
 /* As soon as these are moved to the kernel, remove them
  * from cs->interrupt_request.
  */
-events.smi.pending = cs->interrupt_request & CPU_INTERRUPT_SMI;
-events.smi.latched_init = cs->interrupt_request & 
CPU_INTERRUPT_INIT;
+interrupt_request = cpu_interrupt_request(cs);
+events.smi.pending = interrupt_request & CPU_INTERRUPT_SMI;
+events.smi.latched_init = interrupt_request & CPU_INTERRUPT_INIT;
 cpu_reset_interrupt(cs, CPU_INTERRUPT_INIT | CPU_INTERRUPT_SMI);
 } else {
 /* Keep these in cs->interrupt_request.  */
@@ -3170,14 +3173,14 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run 
*run)
 {
 X86CPU *x86_cpu = X86_CPU(cpu);
 CPUX86State *env = _cpu->env;
+uint32_t interrupt_request;
 int ret;
 
+interrupt_request = cpu_interrupt_request(cpu);
 /* Inject NMI */
-if (cpu->interrupt_request & (CPU_INTERRUPT_NMI | CPU_INTERRUPT_SMI)) {
-if (cpu->interrupt_request & CPU_INTERRUPT_NMI) {
-qemu_mutex_lock_iothread();
+if (interrupt_request & (CPU_INTERRUPT_NMI | CPU_INTERRUPT_SMI)) {
+if (interrupt_request & CPU_INTERRUPT_NMI) {
 cpu_reset_interrupt(cpu, CPU_INTERRUPT_NMI);
-qemu_mutex_unlock_iothread();
 DPRINTF("injected NMI\n");
 ret = kvm_vcpu_ioctl(cpu, KVM_NMI);
 if (ret < 0) {
@@ -3185,10 +3188,8 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
 strerror(-ret));
 }
 }
-if (cpu->interrupt_request & CPU_INTERRUPT_SMI) {
-qemu_mutex_lock_iothread();
+if (interrupt_request & CPU_INTERRUPT_SMI) {
 cpu_reset_interrupt(cpu, CPU_INTERRUPT_SMI);
-qemu_mutex_unlock_iothread();
 DPRINTF("injected SMI\n");
 ret = kvm_vcpu_ioctl(cpu, KVM_SMI);
 if (ret < 0) {
@@ -3202,16 +3203,18 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run 
*run)
 qemu_mutex_lock_iothread();
 }
 
+interrupt_request = cpu_interrupt_request(cpu);
+
 /* Force the VCPU out of its inner loop to process any INIT requests
  * or (for userspace APIC, but it is cheap to combine the checks here)
  * pending TPR access reports.
  */
-if (cpu->interrupt_request & (CPU_INTERRUPT_INIT | CPU_INTERRUPT_TPR)) {
-if ((cpu->interrupt_request & CPU_INTERRUPT_INIT) &&
+if (interrupt_request & (CPU_INTERRUPT_INIT | CPU_INTERRUPT_TPR)) {
+if ((interrupt_request & CPU_INTERRUPT_INIT) &&
 !(env->hflags & HF_SMM_MASK)) {
 cpu->exit_request = 1;
 }
-if (cpu->interrupt_request & CPU_INTERRUPT_TPR) {
+if (interrupt_request & CPU_INTERRUPT_TPR) {
 cpu->exit_request = 1;
 }
 }
@@ -3219,7 +3222,7 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
 if (!kvm_pic_in_kernel()) {
 /* Try to inject an interrupt if the guest can accept it */
 if (run->ready_for_interrupt_injection &&
-(cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
+(interrupt_request & CPU_INTERRUPT_HARD) &&
 (env->eflags & IF_MASK)) {
 int irq;
 
@@ -3243,7 +3246,7 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
  * interrupt, request an interrupt window exit.  This will
  * cause a return to userspace as soon as the guest is ready to
  * receive interrupts. */
-if ((cpu->interrupt_request & CPU_INTERRUPT_HARD)) {
+if ((cpu_interrupt_request(cpu) & CPU_INTERRUPT_HARD)) {
 run->request_interrupt_window = 1;
 } else {
 run->request_interrupt_window = 0;
@@ -3289,8 +3292,9 @@ int kvm_arch_process_async_events(CPUState *cs)
 {
 X86CPU *cpu = X86_CPU(cs);
 CPUX86State *env = >env;
+uint32_t interrupt_request;
 
-if (cs->interrupt_request & CPU_INTERRUPT_MCE) {
+if (cpu_interrupt_request(cs) & CPU_INTERRUPT_MCE) {
 /* We must not raise CPU_INTERRUPT_MCE if it's not supported. */
 assert(env->mcg_cap);
 
@@ -3313,7 +3317,7 @@ int kvm_arch_process_async_events(CPUState *cs)
 }
 }
 
-if ((cs->interrupt_request & CPU_INTERRUPT_INIT) &&
+if 

[Qemu-devel] [PATCH v5 56/73] openrisc: convert to cpu_interrupt_request

2018-12-12 Thread Emilio G. Cota
Cc: Stafford Horne 
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 hw/openrisc/cputimer.c | 2 +-
 target/openrisc/cpu.c  | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/openrisc/cputimer.c b/hw/openrisc/cputimer.c
index 850f88761c..739404e4f5 100644
--- a/hw/openrisc/cputimer.c
+++ b/hw/openrisc/cputimer.c
@@ -102,7 +102,7 @@ static void openrisc_timer_cb(void *opaque)
 CPUState *cs = CPU(cpu);
 
 cpu->env.ttmr |= TTMR_IP;
-cs->interrupt_request |= CPU_INTERRUPT_TIMER;
+cpu_interrupt_request_or(cs, CPU_INTERRUPT_TIMER);
 }
 
 switch (cpu->env.ttmr & TTMR_M) {
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
index fb7cb5c507..cdbc9353b7 100644
--- a/target/openrisc/cpu.c
+++ b/target/openrisc/cpu.c
@@ -32,8 +32,8 @@ static void openrisc_cpu_set_pc(CPUState *cs, vaddr value)
 
 static bool openrisc_cpu_has_work(CPUState *cs)
 {
-return cs->interrupt_request & (CPU_INTERRUPT_HARD |
-CPU_INTERRUPT_TIMER);
+return cpu_interrupt_request(cs) & (CPU_INTERRUPT_HARD |
+CPU_INTERRUPT_TIMER);
 }
 
 static void openrisc_disas_set_info(CPUState *cpu, disassemble_info *info)
-- 
2.17.1




[Qemu-devel] [PATCH v5 25/73] s390x: convert to cpu_halted

2018-12-12 Thread Emilio G. Cota
Cc: Cornelia Huck 
Cc: Christian Borntraeger 
Cc: Alexander Graf 
Cc: David Hildenbrand 
Cc: qemu-s3...@nongnu.org
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 hw/intc/s390_flic.c|  2 +-
 target/s390x/cpu.c | 22 +++---
 target/s390x/excp_helper.c |  2 +-
 target/s390x/kvm.c |  2 +-
 target/s390x/sigp.c|  8 
 5 files changed, 22 insertions(+), 14 deletions(-)

diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c
index 5f8168f0f0..bfb5cf1d07 100644
--- a/hw/intc/s390_flic.c
+++ b/hw/intc/s390_flic.c
@@ -198,7 +198,7 @@ static void qemu_s390_flic_notify(uint32_t type)
 }
 
 /* we always kick running CPUs for now, this is tricky */
-if (cs->halted) {
+if (cpu_halted(cs)) {
 /* don't check for subclasses, CPUs double check when waking up */
 if (type & FLIC_PENDING_SERVICE) {
 if (!(cpu->env.psw.mask & PSW_MASK_EXT)) {
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
index 18ba7f85a5..4d70ba785c 100644
--- a/target/s390x/cpu.c
+++ b/target/s390x/cpu.c
@@ -288,7 +288,7 @@ static void s390_cpu_initfn(Object *obj)
 CPUS390XState *env = >env;
 
 cs->env_ptr = env;
-cs->halted = 1;
+cpu_halted_set(cs, 1);
 cs->exception_index = EXCP_HLT;
 object_property_add(obj, "crash-information", "GuestPanicInformation",
 s390_cpu_get_crash_info_qom, NULL, NULL, NULL, NULL);
@@ -313,8 +313,8 @@ static void s390_cpu_finalize(Object *obj)
 #if !defined(CONFIG_USER_ONLY)
 static bool disabled_wait(CPUState *cpu)
 {
-return cpu->halted && !(S390_CPU(cpu)->env.psw.mask &
-(PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK));
+return cpu_halted(cpu) && !(S390_CPU(cpu)->env.psw.mask &
+(PSW_MASK_IO | PSW_MASK_EXT | 
PSW_MASK_MCHECK));
 }
 
 static unsigned s390_count_running_cpus(void)
@@ -340,10 +340,16 @@ unsigned int s390_cpu_halt(S390CPU *cpu)
 CPUState *cs = CPU(cpu);
 trace_cpu_halt(cs->cpu_index);
 
-if (!cs->halted) {
-cs->halted = 1;
+/*
+ * cpu_halted and cpu_halted_set acquire the cpu lock if it
+ * isn't already held, so acquire it first.
+ */
+cpu_mutex_lock(cs);
+if (!cpu_halted(cs)) {
+cpu_halted_set(cs, 1);
 cs->exception_index = EXCP_HLT;
 }
+cpu_mutex_unlock(cs);
 
 return s390_count_running_cpus();
 }
@@ -353,10 +359,12 @@ void s390_cpu_unhalt(S390CPU *cpu)
 CPUState *cs = CPU(cpu);
 trace_cpu_unhalt(cs->cpu_index);
 
-if (cs->halted) {
-cs->halted = 0;
+cpu_mutex_lock(cs);
+if (cpu_halted(cs)) {
+cpu_halted_set(cs, 0);
 cs->exception_index = -1;
 }
+cpu_mutex_unlock(cs);
 }
 
 unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu)
diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c
index 2a33222f7e..d22c5b3ce5 100644
--- a/target/s390x/excp_helper.c
+++ b/target/s390x/excp_helper.c
@@ -461,7 +461,7 @@ try_deliver:
 if ((env->psw.mask & PSW_MASK_WAIT) || stopped) {
 /* don't trigger a cpu_loop_exit(), use an interrupt instead */
 cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HALT);
-} else if (cs->halted) {
+} else if (cpu_halted(cs)) {
 /* unhalt if we had a WAIT PSW somehwere in our injection chain */
 s390_cpu_unhalt(cpu);
 }
diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c
index 2ebf26adfe..ffb52888c0 100644
--- a/target/s390x/kvm.c
+++ b/target/s390x/kvm.c
@@ -1005,7 +1005,7 @@ MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run 
*run)
 
 int kvm_arch_process_async_events(CPUState *cs)
 {
-return cs->halted;
+return cpu_halted(cs);
 }
 
 static int s390_kvm_irq_to_interrupt(struct kvm_s390_irq *irq,
diff --git a/target/s390x/sigp.c b/target/s390x/sigp.c
index c1f9245797..d410da797a 100644
--- a/target/s390x/sigp.c
+++ b/target/s390x/sigp.c
@@ -115,7 +115,7 @@ static void sigp_stop(CPUState *cs, run_on_cpu_data arg)
 }
 
 /* disabled wait - sleeping in user space */
-if (cs->halted) {
+if (cpu_halted(cs)) {
 s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu);
 } else {
 /* execute the stop function */
@@ -131,7 +131,7 @@ static void sigp_stop_and_store_status(CPUState *cs, 
run_on_cpu_data arg)
 SigpInfo *si = arg.host_ptr;
 
 /* disabled wait - sleeping in user space */
-if (s390_cpu_get_state(cpu) == S390_CPU_STATE_OPERATING && cs->halted) {
+if (s390_cpu_get_state(cpu) == S390_CPU_STATE_OPERATING && cpu_halted(cs)) 
{
 s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu);
 }
 
@@ -313,7 +313,7 @@ static void sigp_cond_emergency(S390CPU *src_cpu, S390CPU 
*dst_cpu,
 }
 
 /* this looks racy, but these values are only used when STOPPED */
-idle = CPU(dst_cpu)->halted;
+idle = cpu_halted(CPU(dst_cpu));
 psw_addr = dst_cpu->env.psw.addr;
 

[Qemu-devel] [PATCH v5 59/73] accel/tcg: convert to cpu_interrupt_request

2018-12-12 Thread Emilio G. Cota
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 accel/tcg/cpu-exec.c  | 15 ---
 accel/tcg/tcg-all.c   | 12 +---
 accel/tcg/translate-all.c |  2 +-
 3 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index b4f46134d3..d7331d3370 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -428,7 +428,7 @@ static inline bool cpu_handle_halt_locked(CPUState *cpu)
 
 if (cpu_halted(cpu)) {
 #if defined(TARGET_I386) && !defined(CONFIG_USER_ONLY)
-if ((cpu->interrupt_request & CPU_INTERRUPT_POLL)
+if ((cpu_interrupt_request(cpu) & CPU_INTERRUPT_POLL)
 && replay_interrupt()) {
 X86CPU *x86_cpu = X86_CPU(cpu);
 
@@ -541,16 +541,17 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
  */
 atomic_mb_set(>icount_decr.u16.high, 0);
 
-if (unlikely(atomic_read(>interrupt_request))) {
+if (unlikely(cpu_interrupt_request(cpu))) {
 int interrupt_request;
+
 qemu_mutex_lock_iothread();
-interrupt_request = cpu->interrupt_request;
+interrupt_request = cpu_interrupt_request(cpu);
 if (unlikely(cpu->singlestep_enabled & SSTEP_NOIRQ)) {
 /* Mask out external interrupts for this step. */
 interrupt_request &= ~CPU_INTERRUPT_SSTEP_MASK;
 }
 if (interrupt_request & CPU_INTERRUPT_DEBUG) {
-cpu->interrupt_request &= ~CPU_INTERRUPT_DEBUG;
+cpu_reset_interrupt(cpu, CPU_INTERRUPT_DEBUG);
 cpu->exception_index = EXCP_DEBUG;
 qemu_mutex_unlock_iothread();
 return true;
@@ -559,7 +560,7 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
 /* Do nothing */
 } else if (interrupt_request & CPU_INTERRUPT_HALT) {
 replay_interrupt();
-cpu->interrupt_request &= ~CPU_INTERRUPT_HALT;
+cpu_reset_interrupt(cpu, CPU_INTERRUPT_HALT);
 cpu_halted_set(cpu, 1);
 cpu->exception_index = EXCP_HLT;
 qemu_mutex_unlock_iothread();
@@ -596,10 +597,10 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
 }
 /* The target hook may have updated the 'cpu->interrupt_request';
  * reload the 'interrupt_request' value */
-interrupt_request = cpu->interrupt_request;
+interrupt_request = cpu_interrupt_request(cpu);
 }
 if (interrupt_request & CPU_INTERRUPT_EXITTB) {
-cpu->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
+cpu_reset_interrupt(cpu, CPU_INTERRUPT_EXITTB);
 /* ensure that no TB jump will be modified as
the program flow was changed */
 *last_tb = NULL;
diff --git a/accel/tcg/tcg-all.c b/accel/tcg/tcg-all.c
index 3d25bdcc17..4e2fe70350 100644
--- a/accel/tcg/tcg-all.c
+++ b/accel/tcg/tcg-all.c
@@ -39,10 +39,16 @@ unsigned long tcg_tb_size;
 static void tcg_handle_interrupt(CPUState *cpu, int mask)
 {
 int old_mask;
-g_assert(qemu_mutex_iothread_locked());
 
-old_mask = cpu->interrupt_request;
-cpu->interrupt_request |= mask;
+if (!cpu_mutex_locked(cpu)) {
+cpu_mutex_lock(cpu);
+old_mask = cpu_interrupt_request(cpu);
+cpu_interrupt_request_or(cpu, mask);
+cpu_mutex_unlock(cpu);
+} else {
+old_mask = cpu_interrupt_request(cpu);
+cpu_interrupt_request_or(cpu, mask);
+}
 
 /*
  * If called from iothread context, wake the target cpu in
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index 639f0b2728..e67654370b 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -2344,7 +2344,7 @@ void dump_opcount_info(FILE *f, fprintf_function 
cpu_fprintf)
 void cpu_interrupt(CPUState *cpu, int mask)
 {
 g_assert(qemu_mutex_iothread_locked());
-cpu->interrupt_request |= mask;
+cpu_interrupt_request_or(cpu, mask);
 atomic_set(>icount_decr.u16.high, -1);
 }
 
-- 
2.17.1




[Qemu-devel] [PATCH v5 54/73] moxie: convert to cpu_interrupt_request

2018-12-12 Thread Emilio G. Cota
Cc: Anthony Green 
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 target/moxie/cpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/moxie/cpu.c b/target/moxie/cpu.c
index 8d67eb6727..bad92cfc61 100644
--- a/target/moxie/cpu.c
+++ b/target/moxie/cpu.c
@@ -33,7 +33,7 @@ static void moxie_cpu_set_pc(CPUState *cs, vaddr value)
 
 static bool moxie_cpu_has_work(CPUState *cs)
 {
-return cs->interrupt_request & CPU_INTERRUPT_HARD;
+return cpu_interrupt_request(cs) & CPU_INTERRUPT_HARD;
 }
 
 static void moxie_cpu_reset(CPUState *s)
-- 
2.17.1




[Qemu-devel] [PATCH v5 46/73] cris: convert to cpu_interrupt_request

2018-12-12 Thread Emilio G. Cota
Cc: "Edgar E. Iglesias" 
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 target/cris/cpu.c| 2 +-
 target/cris/helper.c | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/target/cris/cpu.c b/target/cris/cpu.c
index a23aba2688..3cdba581e6 100644
--- a/target/cris/cpu.c
+++ b/target/cris/cpu.c
@@ -37,7 +37,7 @@ static void cris_cpu_set_pc(CPUState *cs, vaddr value)
 
 static bool cris_cpu_has_work(CPUState *cs)
 {
-return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
+return cpu_interrupt_request(cs) & (CPU_INTERRUPT_HARD | 
CPU_INTERRUPT_NMI);
 }
 
 /* CPUClass::reset() */
diff --git a/target/cris/helper.c b/target/cris/helper.c
index d2ec349191..e3fa19363f 100644
--- a/target/cris/helper.c
+++ b/target/cris/helper.c
@@ -116,7 +116,7 @@ int cris_cpu_handle_mmu_fault(CPUState *cs, vaddr address, 
int size, int rw,
 if (r > 0) {
 qemu_log_mask(CPU_LOG_MMU,
 "%s returns %d irqreq=%x addr=%" VADDR_PRIx " phy=%x vec=%x"
-" pc=%x\n", __func__, r, cs->interrupt_request, address,
+" pc=%x\n", __func__, r, cpu_interrupt_request(cs), address,
 res.phy, res.bf_vec, env->pc);
 }
 return r;
@@ -130,7 +130,7 @@ void crisv10_cpu_do_interrupt(CPUState *cs)
 
 D_LOG("exception index=%d interrupt_req=%d\n",
   cs->exception_index,
-  cs->interrupt_request);
+  cpu_interrupt_request(cs));
 
 if (env->dslot) {
 /* CRISv10 never takes interrupts while in a delay-slot.  */
@@ -192,7 +192,7 @@ void cris_cpu_do_interrupt(CPUState *cs)
 
 D_LOG("exception index=%d interrupt_req=%d\n",
   cs->exception_index,
-  cs->interrupt_request);
+  cpu_interrupt_request(cs));
 
 switch (cs->exception_index) {
 case EXCP_BREAK:
-- 
2.17.1




[Qemu-devel] [PATCH v5 58/73] microblaze: convert to cpu_interrupt_request

2018-12-12 Thread Emilio G. Cota
Cc: "Edgar E. Iglesias" 
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 target/microblaze/cpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c
index 9b546a2c18..206fdd8651 100644
--- a/target/microblaze/cpu.c
+++ b/target/microblaze/cpu.c
@@ -84,7 +84,7 @@ static void mb_cpu_set_pc(CPUState *cs, vaddr value)
 
 static bool mb_cpu_has_work(CPUState *cs)
 {
-return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI);
+return cpu_interrupt_request(cs) & (CPU_INTERRUPT_HARD | 
CPU_INTERRUPT_NMI);
 }
 
 #ifndef CONFIG_USER_ONLY
-- 
2.17.1




[Qemu-devel] [PATCH v5 55/73] sparc: convert to cpu_interrupt_request

2018-12-12 Thread Emilio G. Cota
Cc: Mark Cave-Ayland 
Cc: Artyom Tarasenko 
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 hw/sparc64/sparc64.c | 4 ++--
 target/sparc/cpu.c   | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/sparc64/sparc64.c b/hw/sparc64/sparc64.c
index 372bbd4f5b..58faeb111a 100644
--- a/hw/sparc64/sparc64.c
+++ b/hw/sparc64/sparc64.c
@@ -56,7 +56,7 @@ void cpu_check_irqs(CPUSPARCState *env)
 /* The bit corresponding to psrpil is (1<< psrpil), the next bit
is (2 << psrpil). */
 if (pil < (2 << env->psrpil)) {
-if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
+if (cpu_interrupt_request(cs) & CPU_INTERRUPT_HARD) {
 trace_sparc64_cpu_check_irqs_reset_irq(env->interrupt_index);
 env->interrupt_index = 0;
 cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
@@ -87,7 +87,7 @@ void cpu_check_irqs(CPUSPARCState *env)
 break;
 }
 }
-} else if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
+} else if (cpu_interrupt_request(cs) & CPU_INTERRUPT_HARD) {
 trace_sparc64_cpu_check_irqs_disabled(pil, env->pil_in, env->softint,
   env->interrupt_index);
 env->interrupt_index = 0;
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
index 0f090ece54..88427283c1 100644
--- a/target/sparc/cpu.c
+++ b/target/sparc/cpu.c
@@ -709,7 +709,7 @@ static bool sparc_cpu_has_work(CPUState *cs)
 SPARCCPU *cpu = SPARC_CPU(cs);
 CPUSPARCState *env = >env;
 
-return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
+return (cpu_interrupt_request(cs) & CPU_INTERRUPT_HARD) &&
cpu_interrupts_enabled(env);
 }
 
-- 
2.17.1




[Qemu-devel] [PATCH v5 50/73] mips: convert to cpu_interrupt_request

2018-12-12 Thread Emilio G. Cota
Cc: Aurelien Jarno 
Cc: Aleksandar Markovic 
Cc: James Hogan 
Reviewed-by: Richard Henderson 
Signed-off-by: Emilio G. Cota 
---
 target/mips/cpu.c | 7 ---
 target/mips/kvm.c | 2 +-
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index e217fb3e36..fdae8cf440 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -56,11 +56,12 @@ static bool mips_cpu_has_work(CPUState *cs)
 MIPSCPU *cpu = MIPS_CPU(cs);
 CPUMIPSState *env = >env;
 bool has_work = false;
+uint32_t interrupt_request = cpu_interrupt_request(cs);
 
 /* Prior to MIPS Release 6 it is implementation dependent if non-enabled
interrupts wake-up the CPU, however most of the implementations only
check for interrupts that can be taken. */
-if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
+if ((interrupt_request & CPU_INTERRUPT_HARD) &&
 cpu_mips_hw_interrupts_pending(env)) {
 if (cpu_mips_hw_interrupts_enabled(env) ||
 (env->insn_flags & ISA_MIPS32R6)) {
@@ -72,7 +73,7 @@ static bool mips_cpu_has_work(CPUState *cs)
 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
 /* The QEMU model will issue an _WAKE request whenever the CPUs
should be woken up.  */
-if (cs->interrupt_request & CPU_INTERRUPT_WAKE) {
+if (interrupt_request & CPU_INTERRUPT_WAKE) {
 has_work = true;
 }
 
@@ -82,7 +83,7 @@ static bool mips_cpu_has_work(CPUState *cs)
 }
 /* MIPS Release 6 has the ability to halt the CPU.  */
 if (env->CP0_Config5 & (1 << CP0C5_VP)) {
-if (cs->interrupt_request & CPU_INTERRUPT_WAKE) {
+if (interrupt_request & CPU_INTERRUPT_WAKE) {
 has_work = true;
 }
 if (!mips_vp_active(env)) {
diff --git a/target/mips/kvm.c b/target/mips/kvm.c
index 0b177a7577..568c3d8f4a 100644
--- a/target/mips/kvm.c
+++ b/target/mips/kvm.c
@@ -135,7 +135,7 @@ void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
 
 qemu_mutex_lock_iothread();
 
-if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
+if ((cpu_interrupt_request(cs) & CPU_INTERRUPT_HARD) &&
 cpu_mips_io_interrupts_pending(cpu)) {
 intr.cpu = -1;
 intr.irq = 2;
-- 
2.17.1




[Qemu-devel] [PATCH v5 41/73] i386/hax-all: convert to cpu_interrupt_request

2018-12-12 Thread Emilio G. Cota
Reviewed-by: Richard Henderson 
Signed-off-by: Emilio G. Cota 
---
 target/i386/hax-all.c | 30 +-
 1 file changed, 17 insertions(+), 13 deletions(-)

diff --git a/target/i386/hax-all.c b/target/i386/hax-all.c
index 8b53a9708f..70cea8b1a1 100644
--- a/target/i386/hax-all.c
+++ b/target/i386/hax-all.c
@@ -293,7 +293,7 @@ int hax_vm_destroy(struct hax_vm *vm)
 
 static void hax_handle_interrupt(CPUState *cpu, int mask)
 {
-cpu->interrupt_request |= mask;
+cpu_interrupt_request_or(cpu, mask);
 
 if (!qemu_cpu_is_self(cpu)) {
 qemu_cpu_kick(cpu);
@@ -427,7 +427,7 @@ static int hax_vcpu_interrupt(CPUArchState *env)
  * Unlike KVM, HAX kernel check for the eflags, instead of qemu
  */
 if (ht->ready_for_interrupt_injection &&
-(cpu->interrupt_request & CPU_INTERRUPT_HARD)) {
+(cpu_interrupt_request(cpu) & CPU_INTERRUPT_HARD)) {
 int irq;
 
 irq = cpu_get_pic_interrupt(env);
@@ -441,7 +441,7 @@ static int hax_vcpu_interrupt(CPUArchState *env)
  * interrupt, request an interrupt window exit.  This will
  * cause a return to userspace as soon as the guest is ready to
  * receive interrupts. */
-if ((cpu->interrupt_request & CPU_INTERRUPT_HARD)) {
+if ((cpu_interrupt_request(cpu) & CPU_INTERRUPT_HARD)) {
 ht->request_interrupt_window = 1;
 } else {
 ht->request_interrupt_window = 0;
@@ -482,19 +482,19 @@ static int hax_vcpu_hax_exec(CPUArchState *env)
 
 cpu_halted_set(cpu, 0);
 
-if (cpu->interrupt_request & CPU_INTERRUPT_POLL) {
+if (cpu_interrupt_request(cpu) & CPU_INTERRUPT_POLL) {
 cpu_reset_interrupt(cpu, CPU_INTERRUPT_POLL);
 apic_poll_irq(x86_cpu->apic_state);
 }
 
-if (cpu->interrupt_request & CPU_INTERRUPT_INIT) {
+if (cpu_interrupt_request(cpu) & CPU_INTERRUPT_INIT) {
 DPRINTF("\nhax_vcpu_hax_exec: handling INIT for %d\n",
 cpu->cpu_index);
 do_cpu_init(x86_cpu);
 hax_vcpu_sync_state(env, 1);
 }
 
-if (cpu->interrupt_request & CPU_INTERRUPT_SIPI) {
+if (cpu_interrupt_request(cpu) & CPU_INTERRUPT_SIPI) {
 DPRINTF("hax_vcpu_hax_exec: handling SIPI for %d\n",
 cpu->cpu_index);
 hax_vcpu_sync_state(env, 0);
@@ -553,13 +553,17 @@ static int hax_vcpu_hax_exec(CPUArchState *env)
 ret = -1;
 break;
 case HAX_EXIT_HLT:
-if (!(cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
-!(cpu->interrupt_request & CPU_INTERRUPT_NMI)) {
-/* hlt instruction with interrupt disabled is shutdown */
-env->eflags |= IF_MASK;
-cpu_halted_set(cpu, 1);
-cpu->exception_index = EXCP_HLT;
-ret = 1;
+{
+uint32_t interrupt_request = cpu_interrupt_request(cpu);
+
+if (!(interrupt_request & CPU_INTERRUPT_HARD) &&
+!(interrupt_request & CPU_INTERRUPT_NMI)) {
+/* hlt instruction with interrupt disabled is shutdown */
+env->eflags |= IF_MASK;
+cpu_halted_set(cpu, 1);
+cpu->exception_index = EXCP_HLT;
+ret = 1;
+}
 }
 break;
 /* these situations will continue to hax module */
-- 
2.17.1




[Qemu-devel] [PATCH v5 47/73] hppa: convert to cpu_interrupt_request

2018-12-12 Thread Emilio G. Cota
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 target/hppa/cpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c
index 00bf444620..1ab4e62850 100644
--- a/target/hppa/cpu.c
+++ b/target/hppa/cpu.c
@@ -60,7 +60,7 @@ static void hppa_cpu_synchronize_from_tb(CPUState *cs, 
TranslationBlock *tb)
 
 static bool hppa_cpu_has_work(CPUState *cs)
 {
-return cs->interrupt_request & CPU_INTERRUPT_HARD;
+return cpu_interrupt_request(cs) & CPU_INTERRUPT_HARD;
 }
 
 static void hppa_cpu_disas_set_info(CPUState *cs, disassemble_info *info)
-- 
2.17.1




[Qemu-devel] [PATCH v5 49/73] m68k: convert to cpu_interrupt_request

2018-12-12 Thread Emilio G. Cota
Cc: Laurent Vivier 
Reviewed-by: Richard Henderson 
Reviewed-by: Laurent Vivier 
Signed-off-by: Emilio G. Cota 
---
 target/m68k/cpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
index 582e3a73b3..99a7eb4340 100644
--- a/target/m68k/cpu.c
+++ b/target/m68k/cpu.c
@@ -34,7 +34,7 @@ static void m68k_cpu_set_pc(CPUState *cs, vaddr value)
 
 static bool m68k_cpu_has_work(CPUState *cs)
 {
-return cs->interrupt_request & CPU_INTERRUPT_HARD;
+return cpu_interrupt_request(cs) & CPU_INTERRUPT_HARD;
 }
 
 static void m68k_set_feature(CPUM68KState *env, int feature)
-- 
2.17.1




[Qemu-devel] [PATCH v5 60/73] cpu: convert to interrupt_request

2018-12-12 Thread Emilio G. Cota
This finishes the conversion to interrupt_request.

Signed-off-by: Emilio G. Cota 
---
 qom/cpu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/qom/cpu.c b/qom/cpu.c
index 44b78f1892..7452109833 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -275,7 +275,7 @@ static void cpu_common_reset(CPUState *cpu)
 log_cpu_state(cpu, cc->reset_dump_flags);
 }
 
-cpu->interrupt_request = 0;
+cpu_interrupt_request_set(cpu, 0);
 cpu_halted_set(cpu, 0);
 cpu->mem_io_pc = 0;
 cpu->mem_io_vaddr = 0;
@@ -410,7 +410,7 @@ static vaddr cpu_adjust_watchpoint_address(CPUState *cpu, 
vaddr addr, int len)
 
 static void generic_handle_interrupt(CPUState *cpu, int mask)
 {
-cpu->interrupt_request |= mask;
+cpu_interrupt_request_or(cpu, mask);
 
 if (!qemu_cpu_is_self(cpu)) {
 qemu_cpu_kick(cpu);
-- 
2.17.1




[Qemu-devel] [PATCH v5 29/73] openrisc: convert to cpu_halted

2018-12-12 Thread Emilio G. Cota
Cc: Stafford Horne 
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 target/openrisc/sys_helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c
index b66a45c1e0..ab4d8fb520 100644
--- a/target/openrisc/sys_helper.c
+++ b/target/openrisc/sys_helper.c
@@ -137,7 +137,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, 
target_ulong rb)
 if (env->pmr & PMR_DME || env->pmr & PMR_SME) {
 cpu_restore_state(cs, GETPC(), true);
 env->pc += 4;
-cs->halted = 1;
+cpu_halted_set(cs, 1);
 raise_exception(cpu, EXCP_HALTED);
 }
 break;
-- 
2.17.1




[Qemu-devel] [PATCH v5 35/73] i386: use cpu_reset_interrupt

2018-12-12 Thread Emilio G. Cota
From: Paolo Bonzini 

Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Paolo Bonzini 
Signed-off-by: Emilio G. Cota 
---
 target/i386/hax-all.c|  4 ++--
 target/i386/hvf/x86hvf.c |  8 
 target/i386/kvm.c| 14 +++---
 target/i386/seg_helper.c | 13 ++---
 target/i386/svm_helper.c |  2 +-
 target/i386/whpx-all.c   | 10 +-
 6 files changed, 25 insertions(+), 26 deletions(-)

diff --git a/target/i386/hax-all.c b/target/i386/hax-all.c
index f095c527e3..8b53a9708f 100644
--- a/target/i386/hax-all.c
+++ b/target/i386/hax-all.c
@@ -433,7 +433,7 @@ static int hax_vcpu_interrupt(CPUArchState *env)
 irq = cpu_get_pic_interrupt(env);
 if (irq >= 0) {
 hax_inject_interrupt(env, irq);
-cpu->interrupt_request &= ~CPU_INTERRUPT_HARD;
+cpu_reset_interrupt(cpu, CPU_INTERRUPT_HARD);
 }
 }
 
@@ -483,7 +483,7 @@ static int hax_vcpu_hax_exec(CPUArchState *env)
 cpu_halted_set(cpu, 0);
 
 if (cpu->interrupt_request & CPU_INTERRUPT_POLL) {
-cpu->interrupt_request &= ~CPU_INTERRUPT_POLL;
+cpu_reset_interrupt(cpu, CPU_INTERRUPT_POLL);
 apic_poll_irq(x86_cpu->apic_state);
 }
 
diff --git a/target/i386/hvf/x86hvf.c b/target/i386/hvf/x86hvf.c
index 163bbed23f..e8b13ed534 100644
--- a/target/i386/hvf/x86hvf.c
+++ b/target/i386/hvf/x86hvf.c
@@ -402,7 +402,7 @@ bool hvf_inject_interrupts(CPUState *cpu_state)
 
 if (cpu_state->interrupt_request & CPU_INTERRUPT_NMI) {
 if (!(env->hflags2 & HF2_NMI_MASK) && !(info & VMCS_INTR_VALID)) {
-cpu_state->interrupt_request &= ~CPU_INTERRUPT_NMI;
+cpu_reset_interrupt(cpu_state, CPU_INTERRUPT_NMI);
 info = VMCS_INTR_VALID | VMCS_INTR_T_NMI | NMI_VEC;
 wvmcs(cpu_state->hvf_fd, VMCS_ENTRY_INTR_INFO, info);
 } else {
@@ -414,7 +414,7 @@ bool hvf_inject_interrupts(CPUState *cpu_state)
 (cpu_state->interrupt_request & CPU_INTERRUPT_HARD) &&
 (EFLAGS(env) & IF_MASK) && !(info & VMCS_INTR_VALID)) {
 int line = cpu_get_pic_interrupt(>env);
-cpu_state->interrupt_request &= ~CPU_INTERRUPT_HARD;
+cpu_reset_interrupt(cpu_state, CPU_INTERRUPT_HARD);
 if (line >= 0) {
 wvmcs(cpu_state->hvf_fd, VMCS_ENTRY_INTR_INFO, line |
   VMCS_INTR_VALID | VMCS_INTR_T_HWINTR);
@@ -440,7 +440,7 @@ int hvf_process_events(CPUState *cpu_state)
 }
 
 if (cpu_state->interrupt_request & CPU_INTERRUPT_POLL) {
-cpu_state->interrupt_request &= ~CPU_INTERRUPT_POLL;
+cpu_reset_interrupt(cpu_state, CPU_INTERRUPT_POLL);
 apic_poll_irq(cpu->apic_state);
 }
 if (((cpu_state->interrupt_request & CPU_INTERRUPT_HARD) &&
@@ -453,7 +453,7 @@ int hvf_process_events(CPUState *cpu_state)
 do_cpu_sipi(cpu);
 }
 if (cpu_state->interrupt_request & CPU_INTERRUPT_TPR) {
-cpu_state->interrupt_request &= ~CPU_INTERRUPT_TPR;
+cpu_reset_interrupt(cpu_state, CPU_INTERRUPT_TPR);
 hvf_cpu_synchronize_state(cpu_state);
 apic_handle_tpr_access_report(cpu->apic_state, env->eip,
   env->tpr_access_type);
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index a739d43a4e..a3d1f47556 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -2880,7 +2880,7 @@ static int kvm_put_vcpu_events(X86CPU *cpu, int level)
  */
 events.smi.pending = cs->interrupt_request & CPU_INTERRUPT_SMI;
 events.smi.latched_init = cs->interrupt_request & 
CPU_INTERRUPT_INIT;
-cs->interrupt_request &= ~(CPU_INTERRUPT_INIT | CPU_INTERRUPT_SMI);
+cpu_reset_interrupt(cs, CPU_INTERRUPT_INIT | CPU_INTERRUPT_SMI);
 } else {
 /* Keep these in cs->interrupt_request.  */
 events.smi.pending = 0;
@@ -3176,7 +3176,7 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
 if (cpu->interrupt_request & (CPU_INTERRUPT_NMI | CPU_INTERRUPT_SMI)) {
 if (cpu->interrupt_request & CPU_INTERRUPT_NMI) {
 qemu_mutex_lock_iothread();
-cpu->interrupt_request &= ~CPU_INTERRUPT_NMI;
+cpu_reset_interrupt(cpu, CPU_INTERRUPT_NMI);
 qemu_mutex_unlock_iothread();
 DPRINTF("injected NMI\n");
 ret = kvm_vcpu_ioctl(cpu, KVM_NMI);
@@ -3187,7 +3187,7 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
 }
 if (cpu->interrupt_request & CPU_INTERRUPT_SMI) {
 qemu_mutex_lock_iothread();
-cpu->interrupt_request &= ~CPU_INTERRUPT_SMI;
+cpu_reset_interrupt(cpu, CPU_INTERRUPT_SMI);
 qemu_mutex_unlock_iothread();
 DPRINTF("injected SMI\n");
 ret = kvm_vcpu_ioctl(cpu, KVM_SMI);
@@ -3223,7 +3223,7 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
 (env->eflags & IF_MASK)) {
 int irq;
 
-

[Qemu-devel] [PATCH v5 53/73] alpha: convert to cpu_interrupt_request

2018-12-12 Thread Emilio G. Cota
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 target/alpha/cpu.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/target/alpha/cpu.c b/target/alpha/cpu.c
index a953897fcc..4e8965fb6c 100644
--- a/target/alpha/cpu.c
+++ b/target/alpha/cpu.c
@@ -42,10 +42,10 @@ static bool alpha_cpu_has_work(CPUState *cs)
assume that if a CPU really wants to stay asleep, it will mask
interrupts at the chipset level, which will prevent these bits
from being set in the first place.  */
-return cs->interrupt_request & (CPU_INTERRUPT_HARD
-| CPU_INTERRUPT_TIMER
-| CPU_INTERRUPT_SMP
-| CPU_INTERRUPT_MCHK);
+return cpu_interrupt_request(cs) & (CPU_INTERRUPT_HARD
+| CPU_INTERRUPT_TIMER
+| CPU_INTERRUPT_SMP
+| CPU_INTERRUPT_MCHK);
 }
 
 static void alpha_cpu_disas_set_info(CPUState *cpu, disassemble_info *info)
-- 
2.17.1




[Qemu-devel] [PATCH v5 31/73] cpu: convert to cpu_halted

2018-12-12 Thread Emilio G. Cota
This finishes the conversion to cpu_halted.

Signed-off-by: Emilio G. Cota 
---
 cpus.c| 8 
 qom/cpu.c | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/cpus.c b/cpus.c
index e85dbbb166..fa66d84bc7 100644
--- a/cpus.c
+++ b/cpus.c
@@ -204,7 +204,7 @@ static bool cpu_thread_is_idle(CPUState *cpu)
 if (cpu_is_stopped(cpu)) {
 return true;
 }
-if (!cpu->halted || cpu_has_work(cpu) ||
+if (!cpu_halted(cpu) || cpu_has_work(cpu) ||
 kvm_halt_in_kernel()) {
 return false;
 }
@@ -1686,7 +1686,7 @@ static void *qemu_hax_cpu_thread_fn(void *arg)
 
 cpu->thread_id = qemu_get_thread_id();
 cpu->created = true;
-cpu->halted = 0;
+cpu_halted_set(cpu, 0);
 current_cpu = cpu;
 
 hax_init_vcpu(cpu);
@@ -1845,7 +1845,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
  *
  * cpu->halted should ensure we sleep in wait_io_event
  */
-g_assert(cpu->halted);
+g_assert(cpu_halted(cpu));
 break;
 case EXCP_ATOMIC:
 qemu_mutex_unlock_iothread();
@@ -2342,7 +2342,7 @@ CpuInfoList *qmp_query_cpus(Error **errp)
 info->value = g_malloc0(sizeof(*info->value));
 info->value->CPU = cpu->cpu_index;
 info->value->current = (cpu == first_cpu);
-info->value->halted = cpu->halted;
+info->value->halted = cpu_halted(cpu);
 info->value->qom_path = object_get_canonical_path(OBJECT(cpu));
 info->value->thread_id = cpu->thread_id;
 #if defined(TARGET_I386)
diff --git a/qom/cpu.c b/qom/cpu.c
index 2ea5b1da08..4e964255bf 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -261,7 +261,7 @@ static void cpu_common_reset(CPUState *cpu)
 }
 
 cpu->interrupt_request = 0;
-cpu->halted = 0;
+cpu_halted_set(cpu, 0);
 cpu->mem_io_pc = 0;
 cpu->mem_io_vaddr = 0;
 cpu->icount_extra = 0;
-- 
2.17.1




[Qemu-devel] [PATCH v5 32/73] cpu: define cpu_interrupt_request helpers

2018-12-12 Thread Emilio G. Cota
Add a comment about how atomic_read works here. The comment refers to
a "BQL-less CPU loop", which will materialize toward the end
of this series.

Note that the modifications to cpu_reset_interrupt are there to
avoid deadlock during the CPU lock transition; once that is complete,
cpu_interrupt_request will be simple again.

Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 include/qom/cpu.h | 37 +
 qom/cpu.c | 27 +--
 2 files changed, 58 insertions(+), 6 deletions(-)

diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 9c5aad1797..95747f5abf 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -505,6 +505,43 @@ static inline void cpu_halted_set(CPUState *cpu, uint32_t 
val)
 cpu_mutex_unlock(cpu);
 }
 
+/*
+ * When sending an interrupt, setters OR the appropriate bit and kick the
+ * destination vCPU. The latter can then read interrupt_request without
+ * acquiring the CPU lock, because once the kick-induced completes, they'll 
read
+ * an up-to-date interrupt_request.
+ * Setters always acquire the lock, which guarantees that (1) concurrent
+ * updates from different threads won't result in data races, and (2) the
+ * BQL-less CPU loop will always see an up-to-date interrupt_request, since the
+ * loop holds the CPU lock.
+ */
+static inline uint32_t cpu_interrupt_request(CPUState *cpu)
+{
+return atomic_read(>interrupt_request);
+}
+
+static inline void cpu_interrupt_request_or(CPUState *cpu, uint32_t mask)
+{
+if (cpu_mutex_locked(cpu)) {
+atomic_set(>interrupt_request, cpu->interrupt_request | mask);
+return;
+}
+cpu_mutex_lock(cpu);
+atomic_set(>interrupt_request, cpu->interrupt_request | mask);
+cpu_mutex_unlock(cpu);
+}
+
+static inline void cpu_interrupt_request_set(CPUState *cpu, uint32_t val)
+{
+if (cpu_mutex_locked(cpu)) {
+atomic_set(>interrupt_request, val);
+return;
+}
+cpu_mutex_lock(cpu);
+atomic_set(>interrupt_request, val);
+cpu_mutex_unlock(cpu);
+}
+
 static inline void cpu_tb_jmp_cache_clear(CPUState *cpu)
 {
 unsigned int i;
diff --git a/qom/cpu.c b/qom/cpu.c
index 4e964255bf..44b78f1892 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -98,14 +98,29 @@ static void cpu_common_get_memory_mapping(CPUState *cpu,
  * BQL here if we need to.  cpu_interrupt assumes it is held.*/
 void cpu_reset_interrupt(CPUState *cpu, int mask)
 {
-bool need_lock = !qemu_mutex_iothread_locked();
+bool has_bql = qemu_mutex_iothread_locked();
+bool has_cpu_lock = cpu_mutex_locked(cpu);
 
-if (need_lock) {
-qemu_mutex_lock_iothread();
+if (has_bql) {
+if (has_cpu_lock) {
+atomic_set(>interrupt_request, cpu->interrupt_request & 
~mask);
+} else {
+cpu_mutex_lock(cpu);
+atomic_set(>interrupt_request, cpu->interrupt_request & 
~mask);
+cpu_mutex_unlock(cpu);
+}
+return;
+}
+
+if (has_cpu_lock) {
+cpu_mutex_unlock(cpu);
 }
-cpu->interrupt_request &= ~mask;
-if (need_lock) {
-qemu_mutex_unlock_iothread();
+qemu_mutex_lock_iothread();
+cpu_mutex_lock(cpu);
+atomic_set(>interrupt_request, cpu->interrupt_request & ~mask);
+qemu_mutex_unlock_iothread();
+if (!has_cpu_lock) {
+cpu_mutex_unlock(cpu);
 }
 }
 
-- 
2.17.1




[Qemu-devel] [PATCH v5 37/73] openrisc: use cpu_reset_interrupt

2018-12-12 Thread Emilio G. Cota
From: Paolo Bonzini 

Cc: Stafford Horne 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Paolo Bonzini 
Signed-off-by: Emilio G. Cota 
---
 target/openrisc/sys_helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c
index ab4d8fb520..c645cc896d 100644
--- a/target/openrisc/sys_helper.c
+++ b/target/openrisc/sys_helper.c
@@ -170,7 +170,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, 
target_ulong rb)
 env->ttmr = (rb & ~TTMR_IP) | ip;
 } else {/* Clear IP bit.  */
 env->ttmr = rb & ~TTMR_IP;
-cs->interrupt_request &= ~CPU_INTERRUPT_TIMER;
+cpu_reset_interrupt(cs, CPU_INTERRUPT_TIMER);
 }
 
 cpu_openrisc_timer_update(cpu);
-- 
2.17.1




[Qemu-devel] [PATCH v5 33/73] ppc: use cpu_reset_interrupt

2018-12-12 Thread Emilio G. Cota
From: Paolo Bonzini 

Cc: David Gibson 
Cc: Alexander Graf 
Cc: qemu-...@nongnu.org
Acked-by: David Gibson 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Paolo Bonzini 
Signed-off-by: Emilio G. Cota 
---
 target/ppc/excp_helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index 5e1778584a..737c9c72be 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -880,7 +880,7 @@ bool ppc_cpu_exec_interrupt(CPUState *cs, int 
interrupt_request)
 if (interrupt_request & CPU_INTERRUPT_HARD) {
 ppc_hw_interrupt(env);
 if (env->pending_interrupts == 0) {
-cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
+cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
 }
 return true;
 }
-- 
2.17.1




[Qemu-devel] [PATCH v5 28/73] gdbstub: convert to cpu_halted

2018-12-12 Thread Emilio G. Cota
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 gdbstub.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gdbstub.c b/gdbstub.c
index c4e4f9f082..4e809ceddb 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1304,7 +1304,7 @@ static int gdb_handle_packet(GDBState *s, const char 
*line_buf)
 /* memtohex() doubles the required space */
 len = snprintf((char *)mem_buf, sizeof(buf) / 2,
"CPU#%d [%s]", cpu->cpu_index,
-   cpu->halted ? "halted " : "running");
+   cpu_halted(cpu) ? "halted " : "running");
 trace_gdbstub_op_extra_info((char *)mem_buf);
 memtohex(buf, mem_buf, len);
 put_packet(s, buf);
-- 
2.17.1




[Qemu-devel] [PATCH v5 34/73] exec: use cpu_reset_interrupt

2018-12-12 Thread Emilio G. Cota
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 exec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/exec.c b/exec.c
index bb6170dbff..04d505500b 100644
--- a/exec.c
+++ b/exec.c
@@ -776,7 +776,7 @@ static int cpu_common_post_load(void *opaque, int 
version_id)
 
 /* 0x01 was CPU_INTERRUPT_EXIT. This line can be removed when the
version_id is increased. */
-cpu->interrupt_request &= ~0x01;
+cpu_reset_interrupt(cpu, 1);
 tlb_flush(cpu);
 
 /* loadvm has just updated the content of RAM, bypassing the
-- 
2.17.1




[Qemu-devel] [PATCH v5 45/73] sh4: convert to cpu_interrupt_request

2018-12-12 Thread Emilio G. Cota
Cc: Aurelien Jarno 
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 target/sh4/cpu.c| 2 +-
 target/sh4/helper.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
index b9f393b7c7..58ea212f53 100644
--- a/target/sh4/cpu.c
+++ b/target/sh4/cpu.c
@@ -45,7 +45,7 @@ static void superh_cpu_synchronize_from_tb(CPUState *cs, 
TranslationBlock *tb)
 
 static bool superh_cpu_has_work(CPUState *cs)
 {
-return cs->interrupt_request & CPU_INTERRUPT_HARD;
+return cpu_interrupt_request(cs) & CPU_INTERRUPT_HARD;
 }
 
 /* CPUClass::reset() */
diff --git a/target/sh4/helper.c b/target/sh4/helper.c
index 2ff0cf4060..8463da5bc8 100644
--- a/target/sh4/helper.c
+++ b/target/sh4/helper.c
@@ -83,7 +83,7 @@ void superh_cpu_do_interrupt(CPUState *cs)
 {
 SuperHCPU *cpu = SUPERH_CPU(cs);
 CPUSH4State *env = >env;
-int do_irq = cs->interrupt_request & CPU_INTERRUPT_HARD;
+int do_irq = cpu_interrupt_request(cs) & CPU_INTERRUPT_HARD;
 int do_exp, irq_vector = cs->exception_index;
 
 /* prioritize exceptions over interrupts */
-- 
2.17.1




[Qemu-devel] [PATCH v5 26/73] sparc: convert to cpu_halted

2018-12-12 Thread Emilio G. Cota
Cc: Fabien Chouteau 
Cc: Mark Cave-Ayland 
Cc: Artyom Tarasenko 
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 hw/sparc/leon3.c  | 2 +-
 hw/sparc/sun4m.c  | 8 
 hw/sparc64/sparc64.c  | 4 ++--
 target/sparc/helper.c | 2 +-
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c
index fa98ab8177..0746001f91 100644
--- a/hw/sparc/leon3.c
+++ b/hw/sparc/leon3.c
@@ -61,7 +61,7 @@ static void main_cpu_reset(void *opaque)
 
 cpu_reset(cpu);
 
-cpu->halted = 0;
+cpu_halted_set(cpu, 0);
 env->pc = s->entry;
 env->npc= s->entry + 4;
 env->regbase[6] = s->sp;
diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c
index 3c29b68e67..5bd6512b2b 100644
--- a/hw/sparc/sun4m.c
+++ b/hw/sparc/sun4m.c
@@ -168,7 +168,7 @@ static void cpu_kick_irq(SPARCCPU *cpu)
 CPUSPARCState *env = >env;
 CPUState *cs = CPU(cpu);
 
-cs->halted = 0;
+cpu_halted_set(cs, 0);
 cpu_check_irqs(env);
 qemu_cpu_kick(cs);
 }
@@ -199,7 +199,7 @@ static void main_cpu_reset(void *opaque)
 CPUState *cs = CPU(cpu);
 
 cpu_reset(cs);
-cs->halted = 0;
+cpu_halted_set(cs, 0);
 }
 
 static void secondary_cpu_reset(void *opaque)
@@ -208,7 +208,7 @@ static void secondary_cpu_reset(void *opaque)
 CPUState *cs = CPU(cpu);
 
 cpu_reset(cs);
-cs->halted = 1;
+cpu_halted_set(cs, 1);
 }
 
 static void cpu_halt_signal(void *opaque, int irq, int level)
@@ -825,7 +825,7 @@ static void cpu_devinit(const char *cpu_type, unsigned int 
id,
 } else {
 qemu_register_reset(secondary_cpu_reset, cpu);
 cs = CPU(cpu);
-cs->halted = 1;
+cpu_halted_set(cs, 1);
 }
 *cpu_irqs = qemu_allocate_irqs(cpu_set_irq, cpu, MAX_PILS);
 env->prom_addr = prom_addr;
diff --git a/hw/sparc64/sparc64.c b/hw/sparc64/sparc64.c
index 408388945e..372bbd4f5b 100644
--- a/hw/sparc64/sparc64.c
+++ b/hw/sparc64/sparc64.c
@@ -100,7 +100,7 @@ static void cpu_kick_irq(SPARCCPU *cpu)
 CPUState *cs = CPU(cpu);
 CPUSPARCState *env = >env;
 
-cs->halted = 0;
+cpu_halted_set(cs, 0);
 cpu_check_irqs(env);
 qemu_cpu_kick(cs);
 }
@@ -115,7 +115,7 @@ void sparc64_cpu_set_ivec_irq(void *opaque, int irq, int 
level)
 if (!(env->ivec_status & 0x20)) {
 trace_sparc64_cpu_ivec_raise_irq(irq);
 cs = CPU(cpu);
-cs->halted = 0;
+cpu_halted_set(cs, 0);
 env->interrupt_index = TT_IVEC;
 env->ivec_status |= 0x20;
 env->ivec_data[0] = (0x1f << 6) | irq;
diff --git a/target/sparc/helper.c b/target/sparc/helper.c
index 46232788c8..dd00cf7cac 100644
--- a/target/sparc/helper.c
+++ b/target/sparc/helper.c
@@ -245,7 +245,7 @@ void helper_power_down(CPUSPARCState *env)
 {
 CPUState *cs = CPU(sparc_env_get_cpu(env));
 
-cs->halted = 1;
+cpu_halted_set(cs, 1);
 cs->exception_index = EXCP_HLT;
 env->pc = env->npc;
 env->npc = env->pc + 4;
-- 
2.17.1




[Qemu-devel] [PATCH v5 42/73] i386/whpx-all: convert to cpu_interrupt_request

2018-12-12 Thread Emilio G. Cota
Reviewed-by: Richard Henderson 
Signed-off-by: Emilio G. Cota 
---
 target/i386/whpx-all.c | 41 -
 1 file changed, 24 insertions(+), 17 deletions(-)

diff --git a/target/i386/whpx-all.c b/target/i386/whpx-all.c
index 9673bdc219..0d8cfa3a19 100644
--- a/target/i386/whpx-all.c
+++ b/target/i386/whpx-all.c
@@ -690,12 +690,14 @@ static int whpx_handle_portio(CPUState *cpu,
 static int whpx_handle_halt(CPUState *cpu)
 {
 struct CPUX86State *env = (CPUArchState *)(cpu->env_ptr);
+uint32_t interrupt_request;
 int ret = 0;
 
 qemu_mutex_lock_iothread();
-if (!((cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
+interrupt_request = cpu_interrupt_request(cpu);
+if (!((interrupt_request & CPU_INTERRUPT_HARD) &&
   (env->eflags & IF_MASK)) &&
-!(cpu->interrupt_request & CPU_INTERRUPT_NMI)) {
+!(interrupt_request & CPU_INTERRUPT_NMI)) {
 cpu->exception_index = EXCP_HLT;
 cpu_halted_set(cpu, true);
 ret = 1;
@@ -713,6 +715,7 @@ static void whpx_vcpu_pre_run(CPUState *cpu)
 struct CPUX86State *env = (CPUArchState *)(cpu->env_ptr);
 X86CPU *x86_cpu = X86_CPU(cpu);
 int irq;
+uint32_t interrupt_request;
 uint8_t tpr;
 WHV_X64_PENDING_INTERRUPTION_REGISTER new_int;
 UINT32 reg_count = 0;
@@ -724,17 +727,19 @@ static void whpx_vcpu_pre_run(CPUState *cpu)
 
 qemu_mutex_lock_iothread();
 
+interrupt_request = cpu_interrupt_request(cpu);
+
 /* Inject NMI */
 if (!vcpu->interruption_pending &&
-cpu->interrupt_request & (CPU_INTERRUPT_NMI | CPU_INTERRUPT_SMI)) {
-if (cpu->interrupt_request & CPU_INTERRUPT_NMI) {
+interrupt_request & (CPU_INTERRUPT_NMI | CPU_INTERRUPT_SMI)) {
+if (interrupt_request & CPU_INTERRUPT_NMI) {
 cpu_reset_interrupt(cpu, CPU_INTERRUPT_NMI);
 vcpu->interruptable = false;
 new_int.InterruptionType = WHvX64PendingNmi;
 new_int.InterruptionPending = 1;
 new_int.InterruptionVector = 2;
 }
-if (cpu->interrupt_request & CPU_INTERRUPT_SMI) {
+if (interrupt_request & CPU_INTERRUPT_SMI) {
 cpu_reset_interrupt(cpu, CPU_INTERRUPT_SMI);
 }
 }
@@ -743,12 +748,12 @@ static void whpx_vcpu_pre_run(CPUState *cpu)
  * Force the VCPU out of its inner loop to process any INIT requests or
  * commit pending TPR access.
  */
-if (cpu->interrupt_request & (CPU_INTERRUPT_INIT | CPU_INTERRUPT_TPR)) {
-if ((cpu->interrupt_request & CPU_INTERRUPT_INIT) &&
+if (interrupt_request & (CPU_INTERRUPT_INIT | CPU_INTERRUPT_TPR)) {
+if ((interrupt_request & CPU_INTERRUPT_INIT) &&
 !(env->hflags & HF_SMM_MASK)) {
 cpu->exit_request = 1;
 }
-if (cpu->interrupt_request & CPU_INTERRUPT_TPR) {
+if (interrupt_request & CPU_INTERRUPT_TPR) {
 cpu->exit_request = 1;
 }
 }
@@ -757,7 +762,7 @@ static void whpx_vcpu_pre_run(CPUState *cpu)
 if (!vcpu->interruption_pending &&
 vcpu->interruptable && (env->eflags & IF_MASK)) {
 assert(!new_int.InterruptionPending);
-if (cpu->interrupt_request & CPU_INTERRUPT_HARD) {
+if (interrupt_request & CPU_INTERRUPT_HARD) {
 cpu_reset_interrupt(cpu, CPU_INTERRUPT_HARD);
 irq = cpu_get_pic_interrupt(env);
 if (irq >= 0) {
@@ -787,7 +792,7 @@ static void whpx_vcpu_pre_run(CPUState *cpu)
 
 /* Update the state of the interrupt delivery notification */
 if (!vcpu->window_registered &&
-cpu->interrupt_request & CPU_INTERRUPT_HARD) {
+cpu_interrupt_request(cpu) & CPU_INTERRUPT_HARD) {
 reg_values[reg_count].DeliverabilityNotifications.InterruptNotification
 = 1;
 vcpu->window_registered = 1;
@@ -840,8 +845,9 @@ static void whpx_vcpu_process_async_events(CPUState *cpu)
 struct CPUX86State *env = (CPUArchState *)(cpu->env_ptr);
 X86CPU *x86_cpu = X86_CPU(cpu);
 struct whpx_vcpu *vcpu = get_whpx_vcpu(cpu);
+uint32_t interrupt_request;
 
-if ((cpu->interrupt_request & CPU_INTERRUPT_INIT) &&
+if ((cpu_interrupt_request(cpu) & CPU_INTERRUPT_INIT) &&
 !(env->hflags & HF_SMM_MASK)) {
 
 do_cpu_init(x86_cpu);
@@ -849,25 +855,26 @@ static void whpx_vcpu_process_async_events(CPUState *cpu)
 vcpu->interruptable = true;
 }
 
-if (cpu->interrupt_request & CPU_INTERRUPT_POLL) {
+if (cpu_interrupt_request(cpu) & CPU_INTERRUPT_POLL) {
 cpu_reset_interrupt(cpu, CPU_INTERRUPT_POLL);
 apic_poll_irq(x86_cpu->apic_state);
 }
 
-if (((cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
+interrupt_request = cpu_interrupt_request(cpu);
+if (((interrupt_request & CPU_INTERRUPT_HARD) &&
  (env->eflags & IF_MASK)) ||
-(cpu->interrupt_request & CPU_INTERRUPT_NMI)) {
+(interrupt_request & CPU_INTERRUPT_NMI)) {
 

[Qemu-devel] [PATCH v5 22/73] m68k: convert to cpu_halted

2018-12-12 Thread Emilio G. Cota
Cc: Laurent Vivier 
Reviewed-by: Richard Henderson 
Reviewed-by: Laurent Vivier 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 target/m68k/op_helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c
index 8d09ed91c4..61ba1a6dec 100644
--- a/target/m68k/op_helper.c
+++ b/target/m68k/op_helper.c
@@ -237,7 +237,7 @@ static void cf_interrupt_all(CPUM68KState *env, int is_hw)
 do_m68k_semihosting(env, env->dregs[0]);
 return;
 }
-cs->halted = 1;
+cpu_halted_set(cs, 1);
 cs->exception_index = EXCP_HLT;
 cpu_loop_exit(cs);
 return;
-- 
2.17.1




[Qemu-devel] [PATCH v5 14/73] microblaze: convert to helper_cpu_halted_set

2018-12-12 Thread Emilio G. Cota
Cc: "Edgar E. Iglesias" 
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 target/microblaze/translate.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c
index 78ca265b04..008b84d456 100644
--- a/target/microblaze/translate.c
+++ b/target/microblaze/translate.c
@@ -1233,9 +1233,7 @@ static void dec_br(DisasContext *dc)
 LOG_DIS("sleep\n");
 
 t_sync_flags(dc);
-tcg_gen_st_i32(tmp_1, cpu_env,
-   -offsetof(MicroBlazeCPU, env)
-   +offsetof(CPUState, halted));
+gen_helper_cpu_halted_set(cpu_env, tmp_1);
 tcg_gen_movi_i64(cpu_SR[SR_PC], dc->pc + 4);
 gen_helper_raise_exception(cpu_env, tmp_hlt);
 tcg_temp_free_i32(tmp_hlt);
-- 
2.17.1




[Qemu-devel] [PATCH v5 23/73] mips: convert to cpu_halted

2018-12-12 Thread Emilio G. Cota
Cc: Aurelien Jarno 
Cc: Aleksandar Markovic 
Cc: James Hogan 
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 hw/mips/cps.c   | 2 +-
 hw/misc/mips_itu.c  | 4 ++--
 target/mips/kvm.c   | 2 +-
 target/mips/op_helper.c | 8 
 target/mips/translate.c | 4 ++--
 5 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/hw/mips/cps.c b/hw/mips/cps.c
index 4285d1964e..a8b27eee78 100644
--- a/hw/mips/cps.c
+++ b/hw/mips/cps.c
@@ -49,7 +49,7 @@ static void main_cpu_reset(void *opaque)
 cpu_reset(cs);
 
 /* All VPs are halted on reset. Leave powering up to CPC. */
-cs->halted = 1;
+cpu_halted_set(cs, 1);
 }
 
 static bool cpu_mips_itu_supported(CPUMIPSState *env)
diff --git a/hw/misc/mips_itu.c b/hw/misc/mips_itu.c
index 43bbec46cf..7c383939a7 100644
--- a/hw/misc/mips_itu.c
+++ b/hw/misc/mips_itu.c
@@ -162,7 +162,7 @@ static void wake_blocked_threads(ITCStorageCell *c)
 {
 CPUState *cs;
 CPU_FOREACH(cs) {
-if (cs->halted && (c->blocked_threads & (1ULL << cs->cpu_index))) {
+if (cpu_halted(cs) && (c->blocked_threads & (1ULL << cs->cpu_index))) {
 cpu_interrupt(cs, CPU_INTERRUPT_WAKE);
 }
 }
@@ -172,7 +172,7 @@ static void wake_blocked_threads(ITCStorageCell *c)
 static void QEMU_NORETURN block_thread_and_exit(ITCStorageCell *c)
 {
 c->blocked_threads |= 1ULL << current_cpu->cpu_index;
-current_cpu->halted = 1;
+cpu_halted_set(current_cpu, 1);
 current_cpu->exception_index = EXCP_HLT;
 cpu_loop_exit_restore(current_cpu, current_cpu->mem_io_pc);
 }
diff --git a/target/mips/kvm.c b/target/mips/kvm.c
index 8e72850962..0b177a7577 100644
--- a/target/mips/kvm.c
+++ b/target/mips/kvm.c
@@ -156,7 +156,7 @@ MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run 
*run)
 
 int kvm_arch_process_async_events(CPUState *cs)
 {
-return cs->halted;
+return cpu_halted(cs);
 }
 
 int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c
index d1f1d1aa35..601f5a47f6 100644
--- a/target/mips/op_helper.c
+++ b/target/mips/op_helper.c
@@ -649,7 +649,7 @@ static bool mips_vpe_is_wfi(MIPSCPU *c)
 
 /* If the VPE is halted but otherwise active, it means it's waiting for
an interrupt.  */
-return cpu->halted && mips_vpe_active(env);
+return cpu_halted(cpu) && mips_vpe_active(env);
 }
 
 static bool mips_vp_is_wfi(MIPSCPU *c)
@@ -657,7 +657,7 @@ static bool mips_vp_is_wfi(MIPSCPU *c)
 CPUState *cpu = CPU(c);
 CPUMIPSState *env = >env;
 
-return cpu->halted && mips_vp_active(env);
+return cpu_halted(cpu) && mips_vp_active(env);
 }
 
 static inline void mips_vpe_wake(MIPSCPU *c)
@@ -674,7 +674,7 @@ static inline void mips_vpe_sleep(MIPSCPU *cpu)
 
 /* The VPE was shut off, really go to bed.
Reset any old _WAKE requests.  */
-cs->halted = 1;
+cpu_halted_set(cs, 1);
 cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE);
 }
 
@@ -2605,7 +2605,7 @@ void helper_wait(CPUMIPSState *env)
 {
 CPUState *cs = CPU(mips_env_get_cpu(env));
 
-cs->halted = 1;
+cpu_halted_set(cs, 1);
 cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE);
 /* Last instruction in the block, PC was updated before
- no need to recover PC and icount */
diff --git a/target/mips/translate.c b/target/mips/translate.c
index e9c23a594b..9b2a45963c 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -29204,7 +29204,7 @@ void cpu_state_reset(CPUMIPSState *env)
 env->tcs[i].CP0_TCHalt = 1;
 }
 env->active_tc.CP0_TCHalt = 1;
-cs->halted = 1;
+cpu_halted_set(cs, 1);
 
 if (cs->cpu_index == 0) {
 /* VPE0 starts up enabled.  */
@@ -29212,7 +29212,7 @@ void cpu_state_reset(CPUMIPSState *env)
 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
 
 /* TC0 starts up unhalted.  */
-cs->halted = 0;
+cpu_halted_set(cs, 0);
 env->active_tc.CP0_TCHalt = 0;
 env->tcs[0].CP0_TCHalt = 0;
 /* With thread 0 active.  */
-- 
2.17.1




[Qemu-devel] [PATCH v5 43/73] i386/hvf: convert to cpu_request_interrupt

2018-12-12 Thread Emilio G. Cota
Reviewed-by: Richard Henderson 
Signed-off-by: Emilio G. Cota 
---
 target/i386/hvf/hvf.c|  8 +---
 target/i386/hvf/x86hvf.c | 26 +++---
 2 files changed, 20 insertions(+), 14 deletions(-)

diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
index c1ff220985..619a4dd565 100644
--- a/target/i386/hvf/hvf.c
+++ b/target/i386/hvf/hvf.c
@@ -249,7 +249,7 @@ void update_apic_tpr(CPUState *cpu)
 
 static void hvf_handle_interrupt(CPUState * cpu, int mask)
 {
-cpu->interrupt_request |= mask;
+cpu_interrupt_request_or(cpu, mask);
 if (!qemu_cpu_is_self(cpu)) {
 qemu_cpu_kick(cpu);
 }
@@ -706,10 +706,12 @@ int hvf_vcpu_exec(CPUState *cpu)
 ret = 0;
 switch (exit_reason) {
 case EXIT_REASON_HLT: {
+uint32_t interrupt_request = cpu_interrupt_request(cpu);
+
 macvm_set_rip(cpu, rip + ins_len);
-if (!((cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
+if (!((interrupt_request & CPU_INTERRUPT_HARD) &&
 (EFLAGS(env) & IF_MASK))
-&& !(cpu->interrupt_request & CPU_INTERRUPT_NMI) &&
+&& !(interrupt_request & CPU_INTERRUPT_NMI) &&
 !(idtvec_info & VMCS_IDT_VEC_VALID)) {
 cpu_halted_set(cpu, 1);
 ret = EXCP_HLT;
diff --git a/target/i386/hvf/x86hvf.c b/target/i386/hvf/x86hvf.c
index e8b13ed534..91feafeedc 100644
--- a/target/i386/hvf/x86hvf.c
+++ b/target/i386/hvf/x86hvf.c
@@ -358,6 +358,7 @@ bool hvf_inject_interrupts(CPUState *cpu_state)
 
 uint8_t vector;
 uint64_t intr_type;
+uint32_t interrupt_request;
 bool have_event = true;
 if (env->interrupt_injected != -1) {
 vector = env->interrupt_injected;
@@ -400,7 +401,7 @@ bool hvf_inject_interrupts(CPUState *cpu_state)
 };
 }
 
-if (cpu_state->interrupt_request & CPU_INTERRUPT_NMI) {
+if (cpu_interrupt_request(cpu_state) & CPU_INTERRUPT_NMI) {
 if (!(env->hflags2 & HF2_NMI_MASK) && !(info & VMCS_INTR_VALID)) {
 cpu_reset_interrupt(cpu_state, CPU_INTERRUPT_NMI);
 info = VMCS_INTR_VALID | VMCS_INTR_T_NMI | NMI_VEC;
@@ -411,7 +412,7 @@ bool hvf_inject_interrupts(CPUState *cpu_state)
 }
 
 if (!(env->hflags & HF_INHIBIT_IRQ_MASK) &&
-(cpu_state->interrupt_request & CPU_INTERRUPT_HARD) &&
+(cpu_interrupt_request(cpu_state) & CPU_INTERRUPT_HARD) &&
 (EFLAGS(env) & IF_MASK) && !(info & VMCS_INTR_VALID)) {
 int line = cpu_get_pic_interrupt(>env);
 cpu_reset_interrupt(cpu_state, CPU_INTERRUPT_HARD);
@@ -420,39 +421,42 @@ bool hvf_inject_interrupts(CPUState *cpu_state)
   VMCS_INTR_VALID | VMCS_INTR_T_HWINTR);
 }
 }
-if (cpu_state->interrupt_request & CPU_INTERRUPT_HARD) {
+if (cpu_interrupt_request(cpu_state) & CPU_INTERRUPT_HARD) {
 vmx_set_int_window_exiting(cpu_state);
 }
-return (cpu_state->interrupt_request
-& (CPU_INTERRUPT_INIT | CPU_INTERRUPT_TPR));
+return cpu_interrupt_request(cpu_state) & (CPU_INTERRUPT_INIT |
+   CPU_INTERRUPT_TPR);
 }
 
 int hvf_process_events(CPUState *cpu_state)
 {
 X86CPU *cpu = X86_CPU(cpu_state);
 CPUX86State *env = >env;
+uint32_t interrupt_request;
 
 EFLAGS(env) = rreg(cpu_state->hvf_fd, HV_X86_RFLAGS);
 
-if (cpu_state->interrupt_request & CPU_INTERRUPT_INIT) {
+if (cpu_interrupt_request(cpu_state) & CPU_INTERRUPT_INIT) {
 hvf_cpu_synchronize_state(cpu_state);
 do_cpu_init(cpu);
 }
 
-if (cpu_state->interrupt_request & CPU_INTERRUPT_POLL) {
+if (cpu_interrupt_request(cpu_state) & CPU_INTERRUPT_POLL) {
 cpu_reset_interrupt(cpu_state, CPU_INTERRUPT_POLL);
 apic_poll_irq(cpu->apic_state);
 }
-if (((cpu_state->interrupt_request & CPU_INTERRUPT_HARD) &&
+
+interrupt_request = cpu_interrupt_request(cpu_state);
+if (((interrupt_request & CPU_INTERRUPT_HARD) &&
 (EFLAGS(env) & IF_MASK)) ||
-(cpu_state->interrupt_request & CPU_INTERRUPT_NMI)) {
+(interrupt_request & CPU_INTERRUPT_NMI)) {
 cpu_halted_set(cpu_state, 0);
 }
-if (cpu_state->interrupt_request & CPU_INTERRUPT_SIPI) {
+if (interrupt_request & CPU_INTERRUPT_SIPI) {
 hvf_cpu_synchronize_state(cpu_state);
 do_cpu_sipi(cpu);
 }
-if (cpu_state->interrupt_request & CPU_INTERRUPT_TPR) {
+if (cpu_interrupt_request(cpu_state) & CPU_INTERRUPT_TPR) {
 cpu_reset_interrupt(cpu_state, CPU_INTERRUPT_TPR);
 hvf_cpu_synchronize_state(cpu_state);
 apic_handle_tpr_access_report(cpu->apic_state, env->eip,
-- 
2.17.1




[Qemu-devel] [PATCH v5 16/73] tcg-runtime: convert to cpu_halted_set

2018-12-12 Thread Emilio G. Cota
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 accel/tcg/tcg-runtime.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/accel/tcg/tcg-runtime.c b/accel/tcg/tcg-runtime.c
index 4aa038465f..70e3c9de71 100644
--- a/accel/tcg/tcg-runtime.c
+++ b/accel/tcg/tcg-runtime.c
@@ -172,5 +172,5 @@ void HELPER(cpu_halted_set)(CPUArchState *env, uint32_t val)
 {
 CPUState *cpu = ENV_GET_CPU(env);
 
-cpu->halted = val;
+cpu_halted_set(cpu, val);
 }
-- 
2.17.1




[Qemu-devel] [PATCH v5 20/73] i386: convert to cpu_halted

2018-12-12 Thread Emilio G. Cota
Cc: Eduardo Habkost 
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 target/i386/cpu.h |  2 +-
 target/i386/cpu.c |  2 +-
 target/i386/hax-all.c |  4 ++--
 target/i386/helper.c  |  4 ++--
 target/i386/hvf/hvf.c |  8 
 target/i386/hvf/x86hvf.c  |  4 ++--
 target/i386/kvm.c | 10 +-
 target/i386/misc_helper.c |  2 +-
 target/i386/whpx-all.c|  6 +++---
 9 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 9c52d0cbeb..3401273d58 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1611,7 +1611,7 @@ static inline void cpu_x86_load_seg_cache_sipi(X86CPU 
*cpu,
sipi_vector << 12,
env->segs[R_CS].limit,
env->segs[R_CS].flags);
-cs->halted = 0;
+cpu_halted_set(cs, 0);
 }
 
 int cpu_x86_get_descr_debug(CPUX86State *env, unsigned int selector,
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index f81d35e1f9..22cca17b9e 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -4690,7 +4690,7 @@ static void x86_cpu_reset(CPUState *s)
 /* We hard-wire the BSP to the first CPU. */
 apic_designate_bsp(cpu->apic_state, s->cpu_index == 0);
 
-s->halted = !cpu_is_bsp(cpu);
+cpu_halted_set(s, !cpu_is_bsp(cpu));
 
 if (kvm_enabled()) {
 kvm_arch_reset_vcpu(cpu);
diff --git a/target/i386/hax-all.c b/target/i386/hax-all.c
index d2e512856b..f095c527e3 100644
--- a/target/i386/hax-all.c
+++ b/target/i386/hax-all.c
@@ -480,7 +480,7 @@ static int hax_vcpu_hax_exec(CPUArchState *env)
 return 0;
 }
 
-cpu->halted = 0;
+cpu_halted_set(cpu, 0);
 
 if (cpu->interrupt_request & CPU_INTERRUPT_POLL) {
 cpu->interrupt_request &= ~CPU_INTERRUPT_POLL;
@@ -557,7 +557,7 @@ static int hax_vcpu_hax_exec(CPUArchState *env)
 !(cpu->interrupt_request & CPU_INTERRUPT_NMI)) {
 /* hlt instruction with interrupt disabled is shutdown */
 env->eflags |= IF_MASK;
-cpu->halted = 1;
+cpu_halted_set(cpu, 1);
 cpu->exception_index = EXCP_HLT;
 ret = 1;
 }
diff --git a/target/i386/helper.c b/target/i386/helper.c
index e695f8ba7a..a75278f954 100644
--- a/target/i386/helper.c
+++ b/target/i386/helper.c
@@ -454,7 +454,7 @@ void x86_cpu_dump_state(CPUState *cs, FILE *f, 
fprintf_function cpu_fprintf,
 (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
 (env->a20_mask >> 20) & 1,
 (env->hflags >> HF_SMM_SHIFT) & 1,
-cs->halted);
+cpu_halted(cs));
 } else
 #endif
 {
@@ -481,7 +481,7 @@ void x86_cpu_dump_state(CPUState *cs, FILE *f, 
fprintf_function cpu_fprintf,
 (env->hflags >> HF_INHIBIT_IRQ_SHIFT) & 1,
 (env->a20_mask >> 20) & 1,
 (env->hflags >> HF_SMM_SHIFT) & 1,
-cs->halted);
+cpu_halted(cs));
 }
 
 for(i = 0; i < 6; i++) {
diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c
index e193022c03..c1ff220985 100644
--- a/target/i386/hvf/hvf.c
+++ b/target/i386/hvf/hvf.c
@@ -499,7 +499,7 @@ void hvf_reset_vcpu(CPUState *cpu) {
 }
 
 hv_vm_sync_tsc(0);
-cpu->halted = 0;
+cpu_halted_set(cpu, 0);
 hv_vcpu_invalidate_tlb(cpu->hvf_fd);
 hv_vcpu_flush(cpu->hvf_fd);
 }
@@ -659,7 +659,7 @@ int hvf_vcpu_exec(CPUState *cpu)
 int ret = 0;
 uint64_t rip = 0;
 
-cpu->halted = 0;
+cpu_halted_set(cpu, 0);
 
 if (hvf_process_events(cpu)) {
 return EXCP_HLT;
@@ -677,7 +677,7 @@ int hvf_vcpu_exec(CPUState *cpu)
 vmx_update_tpr(cpu);
 
 qemu_mutex_unlock_iothread();
-if (!cpu_is_bsp(X86_CPU(cpu)) && cpu->halted) {
+if (!cpu_is_bsp(X86_CPU(cpu)) && cpu_halted(cpu)) {
 qemu_mutex_lock_iothread();
 return EXCP_HLT;
 }
@@ -711,7 +711,7 @@ int hvf_vcpu_exec(CPUState *cpu)
 (EFLAGS(env) & IF_MASK))
 && !(cpu->interrupt_request & CPU_INTERRUPT_NMI) &&
 !(idtvec_info & VMCS_IDT_VEC_VALID)) {
-cpu->halted = 1;
+cpu_halted_set(cpu, 1);
 ret = EXCP_HLT;
 }
 ret = EXCP_INTERRUPT;
diff --git a/target/i386/hvf/x86hvf.c b/target/i386/hvf/x86hvf.c
index df8e946fbc..163bbed23f 100644
--- a/target/i386/hvf/x86hvf.c
+++ b/target/i386/hvf/x86hvf.c
@@ -446,7 +446,7 @@ int hvf_process_events(CPUState *cpu_state)
 if (((cpu_state->interrupt_request & CPU_INTERRUPT_HARD) &&
 (EFLAGS(env) & IF_MASK)) ||
 (cpu_state->interrupt_request & CPU_INTERRUPT_NMI)) {
-cpu_state->halted = 0;
+cpu_halted_set(cpu_state, 0);
 }
 if (cpu_state->interrupt_request & CPU_INTERRUPT_SIPI) {
 

[Qemu-devel] [PATCH v5 48/73] lm32: convert to cpu_interrupt_request

2018-12-12 Thread Emilio G. Cota
Cc: Michael Walle 
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 target/lm32/cpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/lm32/cpu.c b/target/lm32/cpu.c
index b7499cb627..1508bb6199 100644
--- a/target/lm32/cpu.c
+++ b/target/lm32/cpu.c
@@ -101,7 +101,7 @@ static void lm32_cpu_init_cfg_reg(LM32CPU *cpu)
 
 static bool lm32_cpu_has_work(CPUState *cs)
 {
-return cs->interrupt_request & CPU_INTERRUPT_HARD;
+return cpu_interrupt_request(cs) & CPU_INTERRUPT_HARD;
 }
 
 /* CPUClass::reset() */
-- 
2.17.1




[Qemu-devel] [PATCH v5 13/73] alpha: convert to helper_cpu_halted_set

2018-12-12 Thread Emilio G. Cota
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 target/alpha/translate.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/target/alpha/translate.c b/target/alpha/translate.c
index e5d62850c5..25cd95931d 100644
--- a/target/alpha/translate.c
+++ b/target/alpha/translate.c
@@ -1226,8 +1226,7 @@ static DisasJumpType gen_call_pal(DisasContext *ctx, int 
palcode)
 /* WTINT */
 {
 TCGv_i32 tmp = tcg_const_i32(1);
-tcg_gen_st_i32(tmp, cpu_env, -offsetof(AlphaCPU, env) +
- offsetof(CPUState, halted));
+gen_helper_cpu_halted_set(cpu_env, tmp);
 tcg_temp_free_i32(tmp);
 }
 tcg_gen_movi_i64(ctx->ir[IR_V0], 0);
@@ -1382,8 +1381,7 @@ static DisasJumpType gen_mtpr(DisasContext *ctx, TCGv vb, 
int regno)
 /* WAIT */
 {
 TCGv_i32 tmp = tcg_const_i32(1);
-tcg_gen_st_i32(tmp, cpu_env, -offsetof(AlphaCPU, env) +
- offsetof(CPUState, halted));
+gen_helper_cpu_halted_set(cpu_env, tmp);
 tcg_temp_free_i32(tmp);
 }
 return gen_excp(ctx, EXCP_HALTED, 0);
-- 
2.17.1




[Qemu-devel] [PATCH v5 05/73] cpu: move run_on_cpu to cpus-common

2018-12-12 Thread Emilio G. Cota
We don't pass a pointer to qemu_global_mutex anymore.

Reviewed-by: Richard Henderson 
Signed-off-by: Emilio G. Cota 
---
 include/qom/cpu.h | 10 --
 cpus-common.c |  2 +-
 cpus.c|  5 -
 3 files changed, 1 insertion(+), 16 deletions(-)

diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index aff42c41dd..f0fc0bccd9 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -760,16 +760,6 @@ void qemu_cpu_kick(CPUState *cpu);
  */
 bool cpu_is_stopped(CPUState *cpu);
 
-/**
- * do_run_on_cpu:
- * @cpu: The vCPU to run on.
- * @func: The function to be executed.
- * @data: Data to pass to the function.
- *
- * Used internally in the implementation of run_on_cpu.
- */
-void do_run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data data);
-
 /**
  * run_on_cpu:
  * @cpu: The vCPU to run on.
diff --git a/cpus-common.c b/cpus-common.c
index 71469c85ce..3fccee5585 100644
--- a/cpus-common.c
+++ b/cpus-common.c
@@ -127,7 +127,7 @@ static void queue_work_on_cpu(CPUState *cpu, struct 
qemu_work_item *wi)
 cpu_mutex_unlock(cpu);
 }
 
-void do_run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data data)
+void run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data data)
 {
 struct qemu_work_item wi;
 bool has_bql = qemu_mutex_iothread_locked();
diff --git a/cpus.c b/cpus.c
index 7ae859f35c..cc683895d8 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1234,11 +1234,6 @@ void qemu_init_cpu_loop(void)
 qemu_thread_get_self(_thread);
 }
 
-void run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data data)
-{
-do_run_on_cpu(cpu, func, data);
-}
-
 static void qemu_kvm_destroy_vcpu(CPUState *cpu)
 {
 if (kvm_destroy_vcpu(cpu) < 0) {
-- 
2.17.1




[Qemu-devel] [PATCH v5 39/73] i386: convert to cpu_interrupt_request

2018-12-12 Thread Emilio G. Cota
Reviewed-by: Richard Henderson 
Signed-off-by: Emilio G. Cota 
---
 target/i386/cpu.c| 2 +-
 target/i386/helper.c | 4 ++--
 target/i386/svm_helper.c | 4 ++--
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 22cca17b9e..35d1d2d10a 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -5641,7 +5641,7 @@ int x86_cpu_pending_interrupt(CPUState *cs, int 
interrupt_request)
 
 static bool x86_cpu_has_work(CPUState *cs)
 {
-return x86_cpu_pending_interrupt(cs, cs->interrupt_request) != 0;
+return x86_cpu_pending_interrupt(cs, cpu_interrupt_request(cs)) != 0;
 }
 
 static void x86_disas_set_info(CPUState *cs, disassemble_info *info)
diff --git a/target/i386/helper.c b/target/i386/helper.c
index a75278f954..9197fb4edc 100644
--- a/target/i386/helper.c
+++ b/target/i386/helper.c
@@ -1035,12 +1035,12 @@ void do_cpu_init(X86CPU *cpu)
 CPUState *cs = CPU(cpu);
 CPUX86State *env = >env;
 CPUX86State *save = g_new(CPUX86State, 1);
-int sipi = cs->interrupt_request & CPU_INTERRUPT_SIPI;
+int sipi = cpu_interrupt_request(cs) & CPU_INTERRUPT_SIPI;
 
 *save = *env;
 
 cpu_reset(cs);
-cs->interrupt_request = sipi;
+cpu_interrupt_request_set(cs, sipi);
 memcpy(>start_init_save, >start_init_save,
offsetof(CPUX86State, end_init_save) -
offsetof(CPUX86State, start_init_save));
diff --git a/target/i386/svm_helper.c b/target/i386/svm_helper.c
index a6d33e55d8..ebf3643ba7 100644
--- a/target/i386/svm_helper.c
+++ b/target/i386/svm_helper.c
@@ -316,7 +316,7 @@ void helper_vmrun(CPUX86State *env, int aflag, int 
next_eip_addend)
 if (int_ctl & V_IRQ_MASK) {
 CPUState *cs = CPU(x86_env_get_cpu(env));
 
-cs->interrupt_request |= CPU_INTERRUPT_VIRQ;
+cpu_interrupt_request_or(cs, CPU_INTERRUPT_VIRQ);
 }
 
 /* maybe we need to inject an event */
@@ -674,7 +674,7 @@ void do_vmexit(CPUX86State *env, uint32_t exit_code, 
uint64_t exit_info_1)
env->vm_vmcb + offsetof(struct vmcb, control.int_ctl));
 int_ctl &= ~(V_TPR_MASK | V_IRQ_MASK);
 int_ctl |= env->v_tpr & V_TPR_MASK;
-if (cs->interrupt_request & CPU_INTERRUPT_VIRQ) {
+if (cpu_interrupt_request(cs) & CPU_INTERRUPT_VIRQ) {
 int_ctl |= V_IRQ_MASK;
 }
 x86_stl_phys(cs,
-- 
2.17.1




[Qemu-devel] [PATCH v5 08/73] tcg-runtime: define helper_cpu_halted_set

2018-12-12 Thread Emilio G. Cota
Reviewed-by: Richard Henderson 
Signed-off-by: Emilio G. Cota 
---
 accel/tcg/tcg-runtime.h | 2 ++
 accel/tcg/tcg-runtime.c | 7 +++
 2 files changed, 9 insertions(+)

diff --git a/accel/tcg/tcg-runtime.h b/accel/tcg/tcg-runtime.h
index 1bd39d136d..d767f8515b 100644
--- a/accel/tcg/tcg-runtime.h
+++ b/accel/tcg/tcg-runtime.h
@@ -28,6 +28,8 @@ DEF_HELPER_FLAGS_1(lookup_tb_ptr, TCG_CALL_NO_WG_SE, ptr, env)
 
 DEF_HELPER_FLAGS_1(exit_atomic, TCG_CALL_NO_WG, noreturn, env)
 
+DEF_HELPER_FLAGS_2(cpu_halted_set, TCG_CALL_NO_RWG, void, env, i32)
+
 #ifdef CONFIG_SOFTMMU
 
 DEF_HELPER_FLAGS_5(atomic_cmpxchgb, TCG_CALL_NO_WG,
diff --git a/accel/tcg/tcg-runtime.c b/accel/tcg/tcg-runtime.c
index d0d4484406..4aa038465f 100644
--- a/accel/tcg/tcg-runtime.c
+++ b/accel/tcg/tcg-runtime.c
@@ -167,3 +167,10 @@ void HELPER(exit_atomic)(CPUArchState *env)
 {
 cpu_loop_exit_atomic(ENV_GET_CPU(env), GETPC());
 }
+
+void HELPER(cpu_halted_set)(CPUArchState *env, uint32_t val)
+{
+CPUState *cpu = ENV_GET_CPU(env);
+
+cpu->halted = val;
+}
-- 
2.17.1




[Qemu-devel] [PATCH v5 19/73] sh4: convert to cpu_halted

2018-12-12 Thread Emilio G. Cota
Cc: Aurelien Jarno 
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 target/sh4/op_helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/sh4/op_helper.c b/target/sh4/op_helper.c
index 4f825bae5a..57cc363ccc 100644
--- a/target/sh4/op_helper.c
+++ b/target/sh4/op_helper.c
@@ -105,7 +105,7 @@ void helper_sleep(CPUSH4State *env)
 {
 CPUState *cs = CPU(sh_env_get_cpu(env));
 
-cs->halted = 1;
+cpu_halted_set(cs, 1);
 env->in_sleep = 1;
 raise_exception(env, EXCP_HLT, 0);
 }
-- 
2.17.1




[Qemu-devel] [PATCH v5 07/73] cpu: make per-CPU locks an alias of the BQL in TCG rr mode

2018-12-12 Thread Emilio G. Cota
Before we can switch from the BQL to per-CPU locks in
the CPU loop, we have to accommodate the fact that TCG
rr mode (i.e. !MTTCG) cannot work with separate per-vCPU
locks. That would lead to deadlock since we need a single
lock/condvar pair on which to wait for events that affect
any vCPU, e.g. in qemu_tcg_rr_wait_io_event.

At the same time, we are moving towards an interface where
the BQL and CPU locks are independent, and the only requirement
is that the locking order is respected, i.e. the BQL is
acquired first if both locks have to be held at the same time.

In this patch we make the BQL a recursive lock under the hood.
This allows us to (1) keep the BQL and CPU locks interfaces
separate, and (2) use a single lock for all vCPUs in TCG rr mode.

Note that the BQL's API (qemu_mutex_lock/unlock_iothread) remains
non-recursive.

Signed-off-by: Emilio G. Cota 
---
 include/qom/cpu.h |  2 +-
 cpus-common.c |  2 +-
 cpus.c| 91 +--
 qom/cpu.c |  1 -
 stubs/cpu-lock.c  |  6 ++--
 5 files changed, 85 insertions(+), 17 deletions(-)

diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index f0fc0bccd9..505daa6ce9 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -357,7 +357,7 @@ struct CPUState {
 int64_t icount_extra;
 sigjmp_buf jmp_env;
 
-QemuMutex lock;
+QemuMutex *lock;
 /* fields below protected by @lock */
 QemuCond cond;
 QSIMPLEQ_HEAD(, qemu_work_item) work_list;
diff --git a/cpus-common.c b/cpus-common.c
index c2ad554d54..36ce9872bd 100644
--- a/cpus-common.c
+++ b/cpus-common.c
@@ -171,7 +171,7 @@ void run_on_cpu(CPUState *cpu, run_on_cpu_func func, 
run_on_cpu_data data)
 while (!atomic_mb_read()) {
 CPUState *self_cpu = current_cpu;
 
-qemu_cond_wait(>cond, >lock);
+qemu_cond_wait(>cond, cpu->lock);
 current_cpu = self_cpu;
 }
 cpu_mutex_unlock(cpu);
diff --git a/cpus.c b/cpus.c
index cc683895d8..e85dbbb166 100644
--- a/cpus.c
+++ b/cpus.c
@@ -83,6 +83,12 @@ static unsigned int throttle_percentage;
 #define CPU_THROTTLE_PCT_MAX 99
 #define CPU_THROTTLE_TIMESLICE_NS 1000
 
+static inline bool qemu_is_tcg_rr(void)
+{
+/* in `make check-qtest', "use_icount && !tcg_enabled()" might be true */
+return use_icount || (tcg_enabled() && !qemu_tcg_mttcg_enabled());
+}
+
 /* XXX: is this really the max number of CPUs? */
 #define CPU_LOCK_BITMAP_SIZE 2048
 
@@ -98,25 +104,76 @@ bool no_cpu_mutex_locked(void)
 return bitmap_empty(cpu_lock_bitmap, CPU_LOCK_BITMAP_SIZE);
 }
 
-void cpu_mutex_lock_impl(CPUState *cpu, const char *file, int line)
+static QemuMutex qemu_global_mutex;
+static __thread bool iothread_locked;
+/*
+ * In TCG rr mode, we make the BQL a recursive mutex, so that we can use it for
+ * all vCPUs while keeping the interface as if the locks were per-CPU.
+ *
+ * The fact that the BQL is implemented recursively is invisible to BQL users;
+ * the mutex API we export (qemu_mutex_lock_iothread() etc.) is non-recursive.
+ *
+ * Locking order: the BQL is always acquired before CPU locks.
+ */
+static __thread int iothread_lock_count;
+
+static void rr_cpu_mutex_lock(void)
+{
+if (iothread_lock_count++ == 0) {
+/*
+ * Circumvent qemu_mutex_lock_iothread()'s state keeping by
+ * acquiring the BQL directly.
+ */
+qemu_mutex_lock(_global_mutex);
+}
+}
+
+static void rr_cpu_mutex_unlock(void)
+{
+g_assert(iothread_lock_count > 0);
+if (--iothread_lock_count == 0) {
+/*
+ * Circumvent qemu_mutex_unlock_iothread()'s state keeping by
+ * releasing the BQL directly.
+ */
+qemu_mutex_unlock(_global_mutex);
+}
+}
+
+static void do_cpu_mutex_lock(CPUState *cpu, const char *file, int line)
 {
-/* coverity gets confused by the indirect function call */
+/* coverity gets confused by the indirect function call */
 #ifdef __COVERITY__
-qemu_mutex_lock_impl(>lock, file, line);
+qemu_mutex_lock_impl(cpu->lock, file, line);
 #else
 QemuMutexLockFunc f = atomic_read(_mutex_lock_func);
 
+f(cpu->lock, file, line);
+#endif
+}
+
+void cpu_mutex_lock_impl(CPUState *cpu, const char *file, int line)
+{
 g_assert(!cpu_mutex_locked(cpu));
 set_bit(cpu->cpu_index + 1, cpu_lock_bitmap);
-f(>lock, file, line);
-#endif
+
+if (qemu_is_tcg_rr()) {
+rr_cpu_mutex_lock();
+} else {
+do_cpu_mutex_lock(cpu, file, line);
+}
 }
 
 void cpu_mutex_unlock_impl(CPUState *cpu, const char *file, int line)
 {
 g_assert(cpu_mutex_locked(cpu));
-qemu_mutex_unlock_impl(>lock, file, line);
 clear_bit(cpu->cpu_index + 1, cpu_lock_bitmap);
+
+if (qemu_is_tcg_rr()) {
+rr_cpu_mutex_unlock();
+return;
+}
+qemu_mutex_unlock_impl(cpu->lock, file, line);
 }
 
 bool cpu_mutex_locked(const CPUState *cpu)
@@ -1215,8 +1272,6 @@ static void qemu_init_sigbus(void)
 }
 #endif /* !CONFIG_LINUX */
 
-static 

[Qemu-devel] [PATCH v5 30/73] cpu-exec: convert to cpu_halted

2018-12-12 Thread Emilio G. Cota
Reviewed-by: Richard Henderson 
Signed-off-by: Emilio G. Cota 
---
 accel/tcg/cpu-exec.c | 25 +
 1 file changed, 21 insertions(+), 4 deletions(-)

diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
index 870027d435..b4f46134d3 100644
--- a/accel/tcg/cpu-exec.c
+++ b/accel/tcg/cpu-exec.c
@@ -422,14 +422,21 @@ static inline TranslationBlock *tb_find(CPUState *cpu,
 return tb;
 }
 
-static inline bool cpu_handle_halt(CPUState *cpu)
+static inline bool cpu_handle_halt_locked(CPUState *cpu)
 {
-if (cpu->halted) {
+g_assert(cpu_mutex_locked(cpu));
+
+if (cpu_halted(cpu)) {
 #if defined(TARGET_I386) && !defined(CONFIG_USER_ONLY)
 if ((cpu->interrupt_request & CPU_INTERRUPT_POLL)
 && replay_interrupt()) {
 X86CPU *x86_cpu = X86_CPU(cpu);
+
+/* prevent deadlock; cpu_mutex must be acquired _after_ the BQL */
+cpu_mutex_unlock(cpu);
 qemu_mutex_lock_iothread();
+cpu_mutex_lock(cpu);
+
 apic_poll_irq(x86_cpu->apic_state);
 cpu_reset_interrupt(cpu, CPU_INTERRUPT_POLL);
 qemu_mutex_unlock_iothread();
@@ -439,12 +446,22 @@ static inline bool cpu_handle_halt(CPUState *cpu)
 return true;
 }
 
-cpu->halted = 0;
+cpu_halted_set(cpu, 0);
 }
 
 return false;
 }
 
+static inline bool cpu_handle_halt(CPUState *cpu)
+{
+bool ret;
+
+cpu_mutex_lock(cpu);
+ret = cpu_handle_halt_locked(cpu);
+cpu_mutex_unlock(cpu);
+return ret;
+}
+
 static inline void cpu_handle_debug_exception(CPUState *cpu)
 {
 CPUClass *cc = CPU_GET_CLASS(cpu);
@@ -543,7 +560,7 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
 } else if (interrupt_request & CPU_INTERRUPT_HALT) {
 replay_interrupt();
 cpu->interrupt_request &= ~CPU_INTERRUPT_HALT;
-cpu->halted = 1;
+cpu_halted_set(cpu, 1);
 cpu->exception_index = EXCP_HLT;
 qemu_mutex_unlock_iothread();
 return true;
-- 
2.17.1




[Qemu-devel] [PATCH v5 21/73] lm32: convert to cpu_halted

2018-12-12 Thread Emilio G. Cota
Cc: Michael Walle 
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 target/lm32/op_helper.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/lm32/op_helper.c b/target/lm32/op_helper.c
index 234d55e056..392634441b 100644
--- a/target/lm32/op_helper.c
+++ b/target/lm32/op_helper.c
@@ -31,7 +31,7 @@ void HELPER(hlt)(CPULM32State *env)
 {
 CPUState *cs = CPU(lm32_env_get_cpu(env));
 
-cs->halted = 1;
+cpu_halted_set(cs, 1);
 cs->exception_index = EXCP_HLT;
 cpu_loop_exit(cs);
 }
@@ -44,7 +44,7 @@ void HELPER(ill)(CPULM32State *env)
 "Connect a debugger or switch to the monitor console "
 "to find out more.\n");
 vm_stop(RUN_STATE_PAUSED);
-cs->halted = 1;
+cpu_halted_set(cs, 1);
 raise_exception(env, EXCP_HALTED);
 #endif
 }
-- 
2.17.1




[Qemu-devel] [PATCH v5 27/73] xtensa: convert to cpu_halted

2018-12-12 Thread Emilio G. Cota
Cc: Max Filippov 
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 target/xtensa/cpu.c   | 2 +-
 target/xtensa/helper.c| 2 +-
 target/xtensa/op_helper.c | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
index a54dbe4260..d4ca35e6cc 100644
--- a/target/xtensa/cpu.c
+++ b/target/xtensa/cpu.c
@@ -86,7 +86,7 @@ static void xtensa_cpu_reset(CPUState *s)
 
 #ifndef CONFIG_USER_ONLY
 reset_mmu(env);
-s->halted = env->runstall;
+cpu_halted_set(s, env->runstall);
 #endif
 }
 
diff --git a/target/xtensa/helper.c b/target/xtensa/helper.c
index 501082f55b..dd6819fbad 100644
--- a/target/xtensa/helper.c
+++ b/target/xtensa/helper.c
@@ -807,7 +807,7 @@ void xtensa_runstall(CPUXtensaState *env, bool runstall)
 CPUState *cpu = CPU(xtensa_env_get_cpu(env));
 
 env->runstall = runstall;
-cpu->halted = runstall;
+cpu_halted_set(cpu, runstall);
 if (runstall) {
 cpu_interrupt(cpu, CPU_INTERRUPT_HALT);
 } else {
diff --git a/target/xtensa/op_helper.c b/target/xtensa/op_helper.c
index e4b42ab3e5..510040b593 100644
--- a/target/xtensa/op_helper.c
+++ b/target/xtensa/op_helper.c
@@ -414,7 +414,7 @@ void HELPER(waiti)(CPUXtensaState *env, uint32_t pc, 
uint32_t intlevel)
 }
 
 cpu = CPU(xtensa_env_get_cpu(env));
-cpu->halted = 1;
+cpu_halted_set(cpu, 1);
 HELPER(exception)(env, EXCP_HLT);
 }
 
-- 
2.17.1




[Qemu-devel] [PATCH v5 04/73] cpu: make qemu_work_cond per-cpu

2018-12-12 Thread Emilio G. Cota
This eliminates the need to use the BQL to queue CPU work.

While at it, give the per-cpu field a generic name ("cond") since
it will soon be used for more than just queueing CPU work.

Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 include/qom/cpu.h |  6 ++--
 cpus-common.c | 72 ++-
 cpus.c|  2 +-
 qom/cpu.c |  1 +
 4 files changed, 63 insertions(+), 18 deletions(-)

diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index bb5a36a324..aff42c41dd 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -316,6 +316,7 @@ struct qemu_work_item;
  * @mem_io_vaddr: Target virtual address at which the memory was accessed.
  * @kvm_fd: vCPU file descriptor for KVM.
  * @lock: Lock to prevent multiple access to per-CPU fields.
+ * @cond: Condition variable for per-CPU events.
  * @work_list: List of pending asynchronous work.
  * @trace_dstate_delayed: Delayed changes to trace_dstate (includes all changes
  *to @trace_dstate).
@@ -358,6 +359,7 @@ struct CPUState {
 
 QemuMutex lock;
 /* fields below protected by @lock */
+QemuCond cond;
 QSIMPLEQ_HEAD(, qemu_work_item) work_list;
 
 CPUAddressSpace *cpu_ases;
@@ -763,12 +765,10 @@ bool cpu_is_stopped(CPUState *cpu);
  * @cpu: The vCPU to run on.
  * @func: The function to be executed.
  * @data: Data to pass to the function.
- * @mutex: Mutex to release while waiting for @func to run.
  *
  * Used internally in the implementation of run_on_cpu.
  */
-void do_run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data data,
-   QemuMutex *mutex);
+void do_run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data data);
 
 /**
  * run_on_cpu:
diff --git a/cpus-common.c b/cpus-common.c
index 2913294cb7..71469c85ce 100644
--- a/cpus-common.c
+++ b/cpus-common.c
@@ -26,7 +26,6 @@
 static QemuMutex qemu_cpu_list_lock;
 static QemuCond exclusive_cond;
 static QemuCond exclusive_resume;
-static QemuCond qemu_work_cond;
 
 /* >= 1 if a thread is inside start_exclusive/end_exclusive.  Written
  * under qemu_cpu_list_lock, read with atomic operations.
@@ -42,7 +41,6 @@ void qemu_init_cpu_list(void)
 qemu_mutex_init(_cpu_list_lock);
 qemu_cond_init(_cond);
 qemu_cond_init(_resume);
-qemu_cond_init(_work_cond);
 }
 
 void cpu_list_lock(void)
@@ -113,23 +111,37 @@ struct qemu_work_item {
 bool free, exclusive, done;
 };
 
-static void queue_work_on_cpu(CPUState *cpu, struct qemu_work_item *wi)
+/* Called with the CPU's lock held */
+static void queue_work_on_cpu_locked(CPUState *cpu, struct qemu_work_item *wi)
 {
-qemu_mutex_lock(>lock);
 QSIMPLEQ_INSERT_TAIL(>work_list, wi, node);
 wi->done = false;
-qemu_mutex_unlock(>lock);
 
 qemu_cpu_kick(cpu);
 }
 
-void do_run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data data,
-   QemuMutex *mutex)
+static void queue_work_on_cpu(CPUState *cpu, struct qemu_work_item *wi)
+{
+cpu_mutex_lock(cpu);
+queue_work_on_cpu_locked(cpu, wi);
+cpu_mutex_unlock(cpu);
+}
+
+void do_run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data data)
 {
 struct qemu_work_item wi;
+bool has_bql = qemu_mutex_iothread_locked();
+
+g_assert(no_cpu_mutex_locked());
 
 if (qemu_cpu_is_self(cpu)) {
-func(cpu, data);
+if (has_bql) {
+func(cpu, data);
+} else {
+qemu_mutex_lock_iothread();
+func(cpu, data);
+qemu_mutex_unlock_iothread();
+}
 return;
 }
 
@@ -139,13 +151,34 @@ void do_run_on_cpu(CPUState *cpu, run_on_cpu_func func, 
run_on_cpu_data data,
 wi.free = false;
 wi.exclusive = false;
 
-queue_work_on_cpu(cpu, );
+cpu_mutex_lock(cpu);
+queue_work_on_cpu_locked(cpu, );
+
+/*
+ * We are going to sleep on the CPU lock, so release the BQL.
+ *
+ * During the transition to per-CPU locks, we release the BQL _after_
+ * having kicked the destination CPU (from queue_work_on_cpu_locked above).
+ * This makes sure that the enqueued work will be seen by the CPU
+ * after being woken up from the kick, since the CPU sleeps on the BQL.
+ * Once we complete the transition to per-CPU locks, we will release
+ * the BQL earlier in this function.
+ */
+if (has_bql) {
+qemu_mutex_unlock_iothread();
+}
+
 while (!atomic_mb_read()) {
 CPUState *self_cpu = current_cpu;
 
-qemu_cond_wait(_work_cond, mutex);
+qemu_cond_wait(>cond, >lock);
 current_cpu = self_cpu;
 }
+cpu_mutex_unlock(cpu);
+
+if (has_bql) {
+qemu_mutex_lock_iothread();
+}
 }
 
 void async_run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data 
data)
@@ -307,6 +340,7 @@ void async_safe_run_on_cpu(CPUState *cpu, run_on_cpu_func 
func,
 void process_queued_cpu_work(CPUState *cpu)
 {
 struct 

[Qemu-devel] [PATCH v5 15/73] cpu: define cpu_halted helpers

2018-12-12 Thread Emilio G. Cota
cpu->halted will soon be protected by cpu->lock.
We will use these helpers to ease the transition,
since right now cpu->halted has many direct callers.

Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 include/qom/cpu.h | 24 
 1 file changed, 24 insertions(+)

diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 505daa6ce9..9c5aad1797 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -481,6 +481,30 @@ bool cpu_mutex_locked(const CPUState *cpu);
  */
 bool no_cpu_mutex_locked(void);
 
+static inline uint32_t cpu_halted(CPUState *cpu)
+{
+uint32_t ret;
+
+if (cpu_mutex_locked(cpu)) {
+return cpu->halted;
+}
+cpu_mutex_lock(cpu);
+ret = cpu->halted;
+cpu_mutex_unlock(cpu);
+return ret;
+}
+
+static inline void cpu_halted_set(CPUState *cpu, uint32_t val)
+{
+if (cpu_mutex_locked(cpu)) {
+cpu->halted = val;
+return;
+}
+cpu_mutex_lock(cpu);
+cpu->halted = val;
+cpu_mutex_unlock(cpu);
+}
+
 static inline void cpu_tb_jmp_cache_clear(CPUState *cpu)
 {
 unsigned int i;
-- 
2.17.1




[Qemu-devel] [PATCH v5 12/73] m68k: convert to helper_cpu_halted_set

2018-12-12 Thread Emilio G. Cota
Cc: Laurent Vivier 
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Reviewed-by: Laurent Vivier 
Signed-off-by: Emilio G. Cota 
---
 target/m68k/translate.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/target/m68k/translate.c b/target/m68k/translate.c
index 752e46ef63..5bd4220e06 100644
--- a/target/m68k/translate.c
+++ b/target/m68k/translate.c
@@ -43,7 +43,6 @@
 #undef DEFO32
 #undef DEFO64
 
-static TCGv_i32 cpu_halted;
 static TCGv_i32 cpu_exception_index;
 
 static char cpu_reg_names[2 * 8 * 3 + 5 * 4];
@@ -79,9 +78,6 @@ void m68k_tcg_init(void)
 #undef DEFO32
 #undef DEFO64
 
-cpu_halted = tcg_global_mem_new_i32(cpu_env,
--offsetof(M68kCPU, env) +
-offsetof(CPUState, halted), "HALTED");
 cpu_exception_index = tcg_global_mem_new_i32(cpu_env,
  -offsetof(M68kCPU, env) +
  offsetof(CPUState, 
exception_index),
@@ -4637,6 +4633,7 @@ DISAS_INSN(halt)
 DISAS_INSN(stop)
 {
 uint16_t ext;
+TCGv_i32 tmp;
 
 if (IS_USER(s)) {
 gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE);
@@ -4646,7 +4643,9 @@ DISAS_INSN(stop)
 ext = read_im16(env, s);
 
 gen_set_sr_im(s, ext, 0);
-tcg_gen_movi_i32(cpu_halted, 1);
+tmp = tcg_const_i32(1);
+gen_helper_cpu_halted_set(cpu_env, tmp);
+tcg_temp_free_i32(tmp);
 gen_exception(s, s->pc, EXCP_HLT);
 }
 
-- 
2.17.1




[Qemu-devel] [PATCH v5 24/73] riscv: convert to cpu_halted

2018-12-12 Thread Emilio G. Cota
Cc: Michael Clark 
Cc: Palmer Dabbelt 
Cc: Sagar Karandikar 
Cc: Bastian Koppelmann 
Cc: Alistair Francis 
Reviewed-by: Palmer Dabbelt 
Reviewed-by: Richard Henderson 
Signed-off-by: Emilio G. Cota 
---
 target/riscv/op_helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 3726299d4a..9b110835de 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -708,7 +708,7 @@ void helper_wfi(CPURISCVState *env)
 {
 CPUState *cs = CPU(riscv_env_get_cpu(env));
 
-cs->halted = 1;
+cpu_halted_set(cs, 1);
 cs->exception_index = EXCP_HLT;
 cpu_loop_exit(cs);
 }
-- 
2.17.1




[Qemu-devel] [PATCH v5 09/73] ppc: convert to helper_cpu_halted_set

2018-12-12 Thread Emilio G. Cota
Cc: David Gibson 
Cc: Alexander Graf 
Cc: qemu-...@nongnu.org
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 target/ppc/translate.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 2b37910248..4bb78f403e 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -1609,8 +1609,7 @@ GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER);
 static void gen_pause(DisasContext *ctx)
 {
 TCGv_i32 t0 = tcg_const_i32(0);
-tcg_gen_st_i32(t0, cpu_env,
-   -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
+gen_helper_cpu_halted_set(cpu_env, t0);
 tcg_temp_free_i32(t0);
 
 /* Stop translation, this gives other CPUs a chance to run */
@@ -3584,8 +3583,7 @@ static void gen_sync(DisasContext *ctx)
 static void gen_wait(DisasContext *ctx)
 {
 TCGv_i32 t0 = tcg_const_i32(1);
-tcg_gen_st_i32(t0, cpu_env,
-   -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
+gen_helper_cpu_halted_set(cpu_env, t0);
 tcg_temp_free_i32(t0);
 /* Stop translation, as the CPU is supposed to sleep from now */
 gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
-- 
2.17.1




[Qemu-devel] [PATCH v5 10/73] cris: convert to helper_cpu_halted_set

2018-12-12 Thread Emilio G. Cota
And fix the temp leak along the way.

Cc: "Edgar E. Iglesias" 
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 target/cris/translate.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/target/cris/translate.c b/target/cris/translate.c
index 11b2c11174..f059745ec0 100644
--- a/target/cris/translate.c
+++ b/target/cris/translate.c
@@ -2829,8 +2829,9 @@ static int dec_rfe_etc(CPUCRISState *env, DisasContext 
*dc)
 cris_cc_mask(dc, 0);
 
 if (dc->op2 == 15) {
-tcg_gen_st_i32(tcg_const_i32(1), cpu_env,
-   -offsetof(CRISCPU, env) + offsetof(CPUState, halted));
+TCGv_i32 tmp = tcg_const_i32(1);
+gen_helper_cpu_halted_set(cpu_env, tmp);
+tcg_temp_free_i32(tmp);
 tcg_gen_movi_tl(env_pc, dc->pc + 2);
 t_gen_raise_exception(EXCP_HLT);
 return 2;
-- 
2.17.1




[Qemu-devel] [PATCH v5 01/73] cpu: convert queued work to a QSIMPLEQ

2018-12-12 Thread Emilio G. Cota
Instead of open-coding it.

While at it, make sure that all accesses to the list are
performed while holding the list's lock.

Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 include/qom/cpu.h |  6 +++---
 cpus-common.c | 25 -
 cpus.c| 14 --
 qom/cpu.c |  1 +
 4 files changed, 24 insertions(+), 22 deletions(-)

diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 1396f53e5b..10a408c999 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -315,8 +315,8 @@ struct qemu_work_item;
  * @mem_io_pc: Host Program Counter at which the memory was accessed.
  * @mem_io_vaddr: Target virtual address at which the memory was accessed.
  * @kvm_fd: vCPU file descriptor for KVM.
- * @work_mutex: Lock to prevent multiple access to queued_work_*.
- * @queued_work_first: First asynchronous work pending.
+ * @work_mutex: Lock to prevent multiple access to @work_list.
+ * @work_list: List of pending asynchronous work.
  * @trace_dstate_delayed: Delayed changes to trace_dstate (includes all changes
  *to @trace_dstate).
  * @trace_dstate: Dynamic tracing state of events for this vCPU (bitmask).
@@ -357,7 +357,7 @@ struct CPUState {
 sigjmp_buf jmp_env;
 
 QemuMutex work_mutex;
-struct qemu_work_item *queued_work_first, *queued_work_last;
+QSIMPLEQ_HEAD(, qemu_work_item) work_list;
 
 CPUAddressSpace *cpu_ases;
 int num_ases;
diff --git a/cpus-common.c b/cpus-common.c
index 98dd8c6ff1..a2a6cd93a1 100644
--- a/cpus-common.c
+++ b/cpus-common.c
@@ -107,7 +107,7 @@ void cpu_list_remove(CPUState *cpu)
 }
 
 struct qemu_work_item {
-struct qemu_work_item *next;
+QSIMPLEQ_ENTRY(qemu_work_item) node;
 run_on_cpu_func func;
 run_on_cpu_data data;
 bool free, exclusive, done;
@@ -116,13 +116,7 @@ struct qemu_work_item {
 static void queue_work_on_cpu(CPUState *cpu, struct qemu_work_item *wi)
 {
 qemu_mutex_lock(>work_mutex);
-if (cpu->queued_work_first == NULL) {
-cpu->queued_work_first = wi;
-} else {
-cpu->queued_work_last->next = wi;
-}
-cpu->queued_work_last = wi;
-wi->next = NULL;
+QSIMPLEQ_INSERT_TAIL(>work_list, wi, node);
 wi->done = false;
 qemu_mutex_unlock(>work_mutex);
 
@@ -314,17 +308,14 @@ void process_queued_cpu_work(CPUState *cpu)
 {
 struct qemu_work_item *wi;
 
-if (cpu->queued_work_first == NULL) {
+qemu_mutex_lock(>work_mutex);
+if (QSIMPLEQ_EMPTY(>work_list)) {
+qemu_mutex_unlock(>work_mutex);
 return;
 }
-
-qemu_mutex_lock(>work_mutex);
-while (cpu->queued_work_first != NULL) {
-wi = cpu->queued_work_first;
-cpu->queued_work_first = wi->next;
-if (!cpu->queued_work_first) {
-cpu->queued_work_last = NULL;
-}
+while (!QSIMPLEQ_EMPTY(>work_list)) {
+wi = QSIMPLEQ_FIRST(>work_list);
+QSIMPLEQ_REMOVE_HEAD(>work_list, node);
 qemu_mutex_unlock(>work_mutex);
 if (wi->exclusive) {
 /* Running work items outside the BQL avoids the following 
deadlock:
diff --git a/cpus.c b/cpus.c
index 0ddeeefc14..7531723d61 100644
--- a/cpus.c
+++ b/cpus.c
@@ -88,9 +88,19 @@ bool cpu_is_stopped(CPUState *cpu)
 return cpu->stopped || !runstate_is_running();
 }
 
+static inline bool cpu_work_list_empty(CPUState *cpu)
+{
+bool ret;
+
+qemu_mutex_lock(>work_mutex);
+ret = QSIMPLEQ_EMPTY(>work_list);
+qemu_mutex_unlock(>work_mutex);
+return ret;
+}
+
 static bool cpu_thread_is_idle(CPUState *cpu)
 {
-if (cpu->stop || cpu->queued_work_first) {
+if (cpu->stop || !cpu_work_list_empty(cpu)) {
 return false;
 }
 if (cpu_is_stopped(cpu)) {
@@ -1513,7 +1523,7 @@ static void *qemu_tcg_rr_cpu_thread_fn(void *arg)
 cpu = first_cpu;
 }
 
-while (cpu && !cpu->queued_work_first && !cpu->exit_request) {
+while (cpu && cpu_work_list_empty(cpu) && !cpu->exit_request) {
 
 atomic_mb_set(_current_rr_cpu, cpu);
 current_cpu = cpu;
diff --git a/qom/cpu.c b/qom/cpu.c
index 9ad1372d57..eb270169ed 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -372,6 +372,7 @@ static void cpu_common_initfn(Object *obj)
 cpu->nr_threads = 1;
 
 qemu_mutex_init(>work_mutex);
+QSIMPLEQ_INIT(>work_list);
 QTAILQ_INIT(>breakpoints);
 QTAILQ_INIT(>watchpoints);
 
-- 
2.17.1




[Qemu-devel] [PATCH v5 11/73] hppa: convert to helper_cpu_halted_set

2018-12-12 Thread Emilio G. Cota
Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 target/hppa/translate.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index ce05d5619d..df9179e70f 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -2845,8 +2845,7 @@ static DisasJumpType trans_pause(DisasContext *ctx, 
uint32_t insn,
 
 /* Tell the qemu main loop to halt until this cpu has work.  */
 tmp = tcg_const_i32(1);
-tcg_gen_st_i32(tmp, cpu_env, -offsetof(HPPACPU, env) +
- offsetof(CPUState, halted));
+gen_helper_cpu_halted_set(cpu_env, tmp);
 tcg_temp_free_i32(tmp);
 gen_excp_1(EXCP_HALTED);
 
-- 
2.17.1




[Qemu-devel] [PATCH v5 06/73] cpu: introduce process_queued_cpu_work_locked

2018-12-12 Thread Emilio G. Cota
This completes the conversion to cpu_mutex_lock/unlock in the file.

Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 cpus-common.c | 17 +++--
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/cpus-common.c b/cpus-common.c
index 3fccee5585..c2ad554d54 100644
--- a/cpus-common.c
+++ b/cpus-common.c
@@ -337,20 +337,19 @@ void async_safe_run_on_cpu(CPUState *cpu, run_on_cpu_func 
func,
 queue_work_on_cpu(cpu, wi);
 }
 
-void process_queued_cpu_work(CPUState *cpu)
+/* Called with the CPU's lock held */
+static void process_queued_cpu_work_locked(CPUState *cpu)
 {
 struct qemu_work_item *wi;
 bool has_bql = qemu_mutex_iothread_locked();
 
-qemu_mutex_lock(>lock);
 if (QSIMPLEQ_EMPTY(>work_list)) {
-qemu_mutex_unlock(>lock);
 return;
 }
 while (!QSIMPLEQ_EMPTY(>work_list)) {
 wi = QSIMPLEQ_FIRST(>work_list);
 QSIMPLEQ_REMOVE_HEAD(>work_list, node);
-qemu_mutex_unlock(>lock);
+cpu_mutex_unlock(cpu);
 if (wi->exclusive) {
 /* Running work items outside the BQL avoids the following 
deadlock:
  * 1) start_exclusive() is called with the BQL taken while another
@@ -376,13 +375,19 @@ void process_queued_cpu_work(CPUState *cpu)
 qemu_mutex_unlock_iothread();
 }
 }
-qemu_mutex_lock(>lock);
+cpu_mutex_lock(cpu);
 if (wi->free) {
 g_free(wi);
 } else {
 atomic_mb_set(>done, true);
 }
 }
-qemu_mutex_unlock(>lock);
 qemu_cond_broadcast(>cond);
 }
+
+void process_queued_cpu_work(CPUState *cpu)
+{
+cpu_mutex_lock(cpu);
+process_queued_cpu_work_locked(cpu);
+cpu_mutex_unlock(cpu);
+}
-- 
2.17.1




[Qemu-devel] [PATCH v5 02/73] cpu: rename cpu->work_mutex to cpu->lock

2018-12-12 Thread Emilio G. Cota
This lock will soon protect more fields of the struct. Give
it a more appropriate name.

Reviewed-by: Richard Henderson 
Reviewed-by: Alex Bennée 
Signed-off-by: Emilio G. Cota 
---
 include/qom/cpu.h |  5 +++--
 cpus-common.c | 14 +++---
 cpus.c|  4 ++--
 qom/cpu.c |  2 +-
 4 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 10a408c999..86ce773388 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -315,7 +315,7 @@ struct qemu_work_item;
  * @mem_io_pc: Host Program Counter at which the memory was accessed.
  * @mem_io_vaddr: Target virtual address at which the memory was accessed.
  * @kvm_fd: vCPU file descriptor for KVM.
- * @work_mutex: Lock to prevent multiple access to @work_list.
+ * @lock: Lock to prevent multiple access to per-CPU fields.
  * @work_list: List of pending asynchronous work.
  * @trace_dstate_delayed: Delayed changes to trace_dstate (includes all changes
  *to @trace_dstate).
@@ -356,7 +356,8 @@ struct CPUState {
 int64_t icount_extra;
 sigjmp_buf jmp_env;
 
-QemuMutex work_mutex;
+QemuMutex lock;
+/* fields below protected by @lock */
 QSIMPLEQ_HEAD(, qemu_work_item) work_list;
 
 CPUAddressSpace *cpu_ases;
diff --git a/cpus-common.c b/cpus-common.c
index a2a6cd93a1..2913294cb7 100644
--- a/cpus-common.c
+++ b/cpus-common.c
@@ -115,10 +115,10 @@ struct qemu_work_item {
 
 static void queue_work_on_cpu(CPUState *cpu, struct qemu_work_item *wi)
 {
-qemu_mutex_lock(>work_mutex);
+qemu_mutex_lock(>lock);
 QSIMPLEQ_INSERT_TAIL(>work_list, wi, node);
 wi->done = false;
-qemu_mutex_unlock(>work_mutex);
+qemu_mutex_unlock(>lock);
 
 qemu_cpu_kick(cpu);
 }
@@ -308,15 +308,15 @@ void process_queued_cpu_work(CPUState *cpu)
 {
 struct qemu_work_item *wi;
 
-qemu_mutex_lock(>work_mutex);
+qemu_mutex_lock(>lock);
 if (QSIMPLEQ_EMPTY(>work_list)) {
-qemu_mutex_unlock(>work_mutex);
+qemu_mutex_unlock(>lock);
 return;
 }
 while (!QSIMPLEQ_EMPTY(>work_list)) {
 wi = QSIMPLEQ_FIRST(>work_list);
 QSIMPLEQ_REMOVE_HEAD(>work_list, node);
-qemu_mutex_unlock(>work_mutex);
+qemu_mutex_unlock(>lock);
 if (wi->exclusive) {
 /* Running work items outside the BQL avoids the following 
deadlock:
  * 1) start_exclusive() is called with the BQL taken while another
@@ -332,13 +332,13 @@ void process_queued_cpu_work(CPUState *cpu)
 } else {
 wi->func(cpu, wi->data);
 }
-qemu_mutex_lock(>work_mutex);
+qemu_mutex_lock(>lock);
 if (wi->free) {
 g_free(wi);
 } else {
 atomic_mb_set(>done, true);
 }
 }
-qemu_mutex_unlock(>work_mutex);
+qemu_mutex_unlock(>lock);
 qemu_cond_broadcast(_work_cond);
 }
diff --git a/cpus.c b/cpus.c
index 7531723d61..895013b56a 100644
--- a/cpus.c
+++ b/cpus.c
@@ -92,9 +92,9 @@ static inline bool cpu_work_list_empty(CPUState *cpu)
 {
 bool ret;
 
-qemu_mutex_lock(>work_mutex);
+qemu_mutex_lock(>lock);
 ret = QSIMPLEQ_EMPTY(>work_list);
-qemu_mutex_unlock(>work_mutex);
+qemu_mutex_unlock(>lock);
 return ret;
 }
 
diff --git a/qom/cpu.c b/qom/cpu.c
index eb270169ed..411b9b2eec 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -371,7 +371,7 @@ static void cpu_common_initfn(Object *obj)
 cpu->nr_cores = 1;
 cpu->nr_threads = 1;
 
-qemu_mutex_init(>work_mutex);
+qemu_mutex_init(>lock);
 QSIMPLEQ_INIT(>work_list);
 QTAILQ_INIT(>breakpoints);
 QTAILQ_INIT(>watchpoints);
-- 
2.17.1




[Qemu-devel] [PATCH v5 03/73] cpu: introduce cpu_mutex_lock/unlock

2018-12-12 Thread Emilio G. Cota
The few direct users of >lock will be converted soon.

Reviewed-by: Richard Henderson 
Signed-off-by: Emilio G. Cota 
---
 include/qom/cpu.h   | 33 +++
 cpus.c  | 48 +++--
 stubs/cpu-lock.c| 28 ++
 stubs/Makefile.objs |  1 +
 4 files changed, 108 insertions(+), 2 deletions(-)
 create mode 100644 stubs/cpu-lock.c

diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 86ce773388..bb5a36a324 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -446,6 +446,39 @@ extern struct CPUTailQ cpus;
 
 extern __thread CPUState *current_cpu;
 
+/**
+ * cpu_mutex_lock - lock a CPU's mutex
+ * @cpu: the CPU whose mutex is to be locked
+ *
+ * To avoid deadlock, a CPU's mutex must be acquired after the BQL.
+ */
+#define cpu_mutex_lock(cpu) \
+cpu_mutex_lock_impl(cpu, __FILE__, __LINE__)
+void cpu_mutex_lock_impl(CPUState *cpu, const char *file, int line);
+
+/**
+ * cpu_mutex_unlock - unlock a CPU's mutex
+ * @cpu: the CPU whose mutex is to be unlocked
+ */
+#define cpu_mutex_unlock(cpu)   \
+cpu_mutex_unlock_impl(cpu, __FILE__, __LINE__)
+void cpu_mutex_unlock_impl(CPUState *cpu, const char *file, int line);
+
+/**
+ * cpu_mutex_locked - check whether a CPU's mutex is locked
+ * @cpu: the CPU of interest
+ *
+ * Returns true if the calling thread is currently holding the CPU's mutex.
+ */
+bool cpu_mutex_locked(const CPUState *cpu);
+
+/**
+ * no_cpu_mutex_locked - check whether any CPU mutex is held
+ *
+ * Returns true if the calling thread is not holding any CPU mutex.
+ */
+bool no_cpu_mutex_locked(void);
+
 static inline void cpu_tb_jmp_cache_clear(CPUState *cpu)
 {
 unsigned int i;
diff --git a/cpus.c b/cpus.c
index 895013b56a..980d62cd58 100644
--- a/cpus.c
+++ b/cpus.c
@@ -83,6 +83,47 @@ static unsigned int throttle_percentage;
 #define CPU_THROTTLE_PCT_MAX 99
 #define CPU_THROTTLE_TIMESLICE_NS 1000
 
+/* XXX: is this really the max number of CPUs? */
+#define CPU_LOCK_BITMAP_SIZE 2048
+
+/*
+ * Note: we index the bitmap with cpu->cpu_index + 1 so that the logic
+ * also works during early CPU initialization, when cpu->cpu_index is set to
+ * UNASSIGNED_CPU_INDEX == -1.
+ */
+static __thread DECLARE_BITMAP(cpu_lock_bitmap, CPU_LOCK_BITMAP_SIZE);
+
+bool no_cpu_mutex_locked(void)
+{
+return bitmap_empty(cpu_lock_bitmap, CPU_LOCK_BITMAP_SIZE);
+}
+
+void cpu_mutex_lock_impl(CPUState *cpu, const char *file, int line)
+{
+/* coverity gets confused by the indirect function call */
+#ifdef __COVERITY__
+qemu_mutex_lock_impl(>lock, file, line);
+#else
+QemuMutexLockFunc f = atomic_read(_mutex_lock_func);
+
+g_assert(!cpu_mutex_locked(cpu));
+set_bit(cpu->cpu_index + 1, cpu_lock_bitmap);
+f(>lock, file, line);
+#endif
+}
+
+void cpu_mutex_unlock_impl(CPUState *cpu, const char *file, int line)
+{
+g_assert(cpu_mutex_locked(cpu));
+qemu_mutex_unlock_impl(>lock, file, line);
+clear_bit(cpu->cpu_index + 1, cpu_lock_bitmap);
+}
+
+bool cpu_mutex_locked(const CPUState *cpu)
+{
+return test_bit(cpu->cpu_index + 1, cpu_lock_bitmap);
+}
+
 bool cpu_is_stopped(CPUState *cpu)
 {
 return cpu->stopped || !runstate_is_running();
@@ -92,9 +133,9 @@ static inline bool cpu_work_list_empty(CPUState *cpu)
 {
 bool ret;
 
-qemu_mutex_lock(>lock);
+cpu_mutex_lock(cpu);
 ret = QSIMPLEQ_EMPTY(>work_list);
-qemu_mutex_unlock(>lock);
+cpu_mutex_unlock(cpu);
 return ret;
 }
 
@@ -1855,6 +1896,9 @@ void qemu_mutex_lock_iothread_impl(const char *file, int 
line)
 {
 QemuMutexLockFunc bql_lock = atomic_read(_bql_mutex_lock_func);
 
+/* prevent deadlock with CPU mutex */
+g_assert(no_cpu_mutex_locked());
+
 g_assert(!qemu_mutex_iothread_locked());
 bql_lock(_global_mutex, file, line);
 iothread_locked = true;
diff --git a/stubs/cpu-lock.c b/stubs/cpu-lock.c
new file mode 100644
index 00..3f07d3a28b
--- /dev/null
+++ b/stubs/cpu-lock.c
@@ -0,0 +1,28 @@
+#include "qemu/osdep.h"
+#include "qom/cpu.h"
+
+void cpu_mutex_lock_impl(CPUState *cpu, const char *file, int line)
+{
+/* coverity gets confused by the indirect function call */
+#ifdef __COVERITY__
+qemu_mutex_lock_impl(>lock, file, line);
+#else
+QemuMutexLockFunc f = atomic_read(_mutex_lock_func);
+f(>lock, file, line);
+#endif
+}
+
+void cpu_mutex_unlock_impl(CPUState *cpu, const char *file, int line)
+{
+qemu_mutex_unlock_impl(>lock, file, line);
+}
+
+bool cpu_mutex_locked(const CPUState *cpu)
+{
+return true;
+}
+
+bool no_cpu_mutex_locked(void)
+{
+return true;
+}
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index 5dd0aeeec6..49f83cf7ff 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -8,6 +8,7 @@ stub-obj-y += blockdev-close-all-bdrv-states.o
 stub-obj-y += clock-warp.o
 stub-obj-y += cpu-get-clock.o
 stub-obj-y += cpu-get-icount.o
+stub-obj-y += cpu-lock.o
 

[Qemu-devel] [PATCH v5 00/73] per-CPU locks

2018-12-12 Thread Emilio G. Cota
v4: https://lists.gnu.org/archive/html/qemu-devel/2018-10/msg05624.html

Changes since v4:

- Add R-b's -- thanks everyone!

- Rebase on v3.1.0
  + Add an additional conversion to cpu_interrupt_request in target/arm
due to 89430fc6f8 ("target/arm: Correctly implement handling of
HCR_EL2.{VI, VF}", 2018-11-13)

- s390x: add comment on why we explicitly acquire the cpu
  lock around cpu_halted and cpu_halted_set, as suggested
  by Alex and Cornelia.

- Drop the patch that reworked exclusive work.

- Add a couple of patches to finish the conversion of qom/cpu
  to cpu_halted and cpu_interrupt_request. I did this to try
  to reduce the diff of the main patch in this series (the
  one that converts the CPU loops to use per-CPU locks), but
  it's still pretty large.

- Rename all_cpu_threads_idle to qemu_tcg_rr_all_cpu_threads_idle.

- Upgrade from RFC to PATCH series. This series used to be an RFC because
  I was concerned about 3 issues:

  1. pause_all_vcpus() and start_exclusive() running at the same
  time, both called from vCPU threads. It turns out that
  pause_all_vcpus() is only called from a vCPU thread in KVM, and
  in KVM we don't use start/end_exclusive. So this should work fine,
  and in fact my concern is not new (we probably want to remove
  calls to pause_all_vcpus() from vCPU threads, but that is a
  fix that is orthogonal to this series).

  2. Possible deadlock if hotplug CPUs are added while
  pause_all_vcpus() executes, since after this series the latter
  function waits on the CPUs that are being shut down without the
  BQL held. I added a final check to pause_all_vcpus() to make sure
  that if such a race occurs, we detect it and redo the shut down
  for all vCPUs.

  3. TCG rr. Having a single condvar/mutex to wait on is very useful,
  since that way we can be woken up whenever _any_ CPU is kicked (via
  cpu->halt_cond). I managed to keep this logic by making the BQL recursive
  under the hood and pointing cpu->lock to the BQL. Note that the
  public interface of the BQL remains non-recursive (i.e. if we call
  qemu_mutex_lock_iothread() twice in a row, we'll hit an assert.);
  it is only in TCG rr mode where we use the BQL recursively.

I've tested all patches with `make check-qtest -j 30' for all targets.
The series is checkpatch-clean (just some warnings about __COVERITY__).

You can fetch it from:
  https://github.com/cota/qemu/tree/cpu-lock-v5

Thanks,

Emilio
---
 accel/tcg/cpu-exec.c|  40 ++--
 accel/tcg/cputlb.c  |  10 +-
 accel/tcg/tcg-all.c |  12 +-
 accel/tcg/tcg-runtime.c |   7 +
 accel/tcg/tcg-runtime.h |   2 +
 accel/tcg/translate-all.c   |   2 +-
 cpus-common.c   | 129 
 cpus.c  | 422 
 exec.c  |   2 +-
 gdbstub.c   |   2 +-
 hw/arm/omap1.c  |   4 +-
 hw/arm/pxa2xx_gpio.c|   2 +-
 hw/arm/pxa2xx_pic.c |   2 +-
 hw/intc/s390_flic.c |   4 +-
 hw/mips/cps.c   |   2 +-
 hw/misc/mips_itu.c  |   4 +-
 hw/openrisc/cputimer.c  |   2 +-
 hw/ppc/e500.c   |   4 +-
 hw/ppc/ppc.c|  12 +-
 hw/ppc/ppce500_spin.c   |   6 +-
 hw/ppc/spapr_cpu_core.c |   4 +-
 hw/ppc/spapr_hcall.c|   4 +-
 hw/ppc/spapr_rtas.c |   6 +-
 hw/sparc/leon3.c|   2 +-
 hw/sparc/sun4m.c|   8 +-
 hw/sparc64/sparc64.c|   8 +-
 include/qom/cpu.h   | 189 +++---
 qom/cpu.c   |  25 ++-
 stubs/Makefile.objs |   1 +
 stubs/cpu-lock.c|  28 +++
 target/alpha/cpu.c  |   8 +-
 target/alpha/translate.c|   6 +-
 target/arm/arm-powerctl.c   |   4 +-
 target/arm/cpu.c|   8 +-
 target/arm/helper.c |  16 +-
 target/arm/op_helper.c  |   2 +-
 target/cris/cpu.c   |   2 +-
 target/cris/helper.c|   6 +-
 target/cris/translate.c |   5 +-
 target/hppa/cpu.c   |   2 +-
 target/hppa/translate.c |   3 +-
 target/i386/cpu.c   |   4 +-
 target/i386/cpu.h   |   2 +-
 target/i386/hax-all.c   |  36 ++--
 target/i386/helper.c|   8 +-
 target/i386/hvf/hvf.c   |  16 +-
 target/i386/hvf/x86hvf.c|  38 ++--
 target/i386/kvm.c   |  78 
 target/i386/misc_helper.c   |   2 +-
 target/i386/seg_helper.c|  13 +-
 target/i386/svm_helper.c|   6 +-
 target/i386/whpx-all.c  |  57 +++---
 target/lm32/cpu.c   |   2 +-
 target/lm32/op_helper.c |   4 +-
 target/m68k/cpu.c   |   2 +-
 target/m68k/op_helper.c |   2 +-
 target/m68k/translate.c |   9 +-
 target/microblaze/cpu.c |   2 +-
 

[Qemu-devel] [PULL 27/27] spapr/xive: use the VCPU id as a NVT identifier

2018-12-12 Thread David Gibson
From: Cédric Le Goater 

The IVPE scans the O/S CAM line of the XIVE thread interrupt contexts
to find a matching Notification Virtual Target (NVT) among the NVTs
dispatched on the HW processor threads.

On a real system, the thread interrupt contexts are updated by the
hypervisor when a Virtual Processor is scheduled to run on a HW
thread. Under QEMU, the model will emulate the same behavior by
hardwiring the NVT identifier in the thread context registers at
reset.

The NVT identifier used by the sPAPRXive model is the VCPU id. The END
identifier is also derived from the VCPU id. A set of helpers doing
the conversion between identifiers are provided for the hcalls
configuring the sources and the ENDs.

The model does not need a NVT table but the XiveRouter NVT operations
are provided to perform some extra checks in the routing algorithm.

Signed-off-by: Cédric Le Goater 
Signed-off-by: David Gibson 
---
 hw/intc/spapr_xive.c | 56 +++-
 1 file changed, 55 insertions(+), 1 deletion(-)

diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
index eef5830d45..3ade419fdb 100644
--- a/hw/intc/spapr_xive.c
+++ b/hw/intc/spapr_xive.c
@@ -26,6 +26,26 @@
 #define SPAPR_XIVE_VC_BASE   0x00060100ull
 #define SPAPR_XIVE_TM_BASE   0x000603020318ull
 
+/*
+ * The allocation of VP blocks is a complex operation in OPAL and the
+ * VP identifiers have a relation with the number of HW chips, the
+ * size of the VP blocks, VP grouping, etc. The QEMU sPAPR XIVE
+ * controller model does not have the same constraints and can use a
+ * simple mapping scheme of the CPU vcpu_id
+ *
+ * These identifiers are never returned to the OS.
+ */
+
+#define SPAPR_XIVE_NVT_BASE 0x400
+
+/*
+ * sPAPR NVT and END indexing helpers
+ */
+static uint32_t spapr_xive_nvt_to_target(uint8_t nvt_blk, uint32_t nvt_idx)
+{
+return nvt_idx - SPAPR_XIVE_NVT_BASE;
+}
+
 /*
  * On sPAPR machines, use a simplified output for the XIVE END
  * structure dumping only the information related to the OS EQ.
@@ -40,7 +60,8 @@ static void spapr_xive_end_pic_print_info(sPAPRXive *xive, 
XiveEND *end,
 uint32_t nvt = GETFIELD_BE32(END_W6_NVT_INDEX, end->w6);
 uint8_t priority = GETFIELD_BE32(END_W7_F0_PRIORITY, end->w7);
 
-monitor_printf(mon, "%3d/%d % 6d/%5d ^%d", nvt,
+monitor_printf(mon, "%3d/%d % 6d/%5d ^%d",
+   spapr_xive_nvt_to_target(0, nvt),
priority, qindex, qentries, qgen);
 
 xive_end_queue_pic_print_info(end, 6, mon);
@@ -246,6 +267,37 @@ static int spapr_xive_write_end(XiveRouter *xrtr, uint8_t 
end_blk,
 return 0;
 }
 
+static int spapr_xive_get_nvt(XiveRouter *xrtr,
+  uint8_t nvt_blk, uint32_t nvt_idx, XiveNVT *nvt)
+{
+uint32_t vcpu_id = spapr_xive_nvt_to_target(nvt_blk, nvt_idx);
+PowerPCCPU *cpu = spapr_find_cpu(vcpu_id);
+
+if (!cpu) {
+/* TODO: should we assert() if we can find a NVT ? */
+return -1;
+}
+
+/*
+ * sPAPR does not maintain a NVT table. Return that the NVT is
+ * valid if we have found a matching CPU
+ */
+nvt->w0 = cpu_to_be32(NVT_W0_VALID);
+return 0;
+}
+
+static int spapr_xive_write_nvt(XiveRouter *xrtr, uint8_t nvt_blk,
+uint32_t nvt_idx, XiveNVT *nvt,
+uint8_t word_number)
+{
+/*
+ * We don't need to write back to the NVTs because the sPAPR
+ * machine should never hit a non-scheduled NVT. It should never
+ * get called.
+ */
+g_assert_not_reached();
+}
+
 static const VMStateDescription vmstate_spapr_xive_end = {
 .name = TYPE_SPAPR_XIVE "/end",
 .version_id = 1,
@@ -308,6 +360,8 @@ static void spapr_xive_class_init(ObjectClass *klass, void 
*data)
 xrc->get_eas = spapr_xive_get_eas;
 xrc->get_end = spapr_xive_get_end;
 xrc->write_end = spapr_xive_write_end;
+xrc->get_nvt = spapr_xive_get_nvt;
+xrc->write_nvt = spapr_xive_write_nvt;
 }
 
 static const TypeInfo spapr_xive_info = {
-- 
2.19.2




[Qemu-devel] [PULL 21/27] Changes requirement for "vsubsbs" instruction

2018-12-12 Thread David Gibson
From: "Paul A. Clarke" 

Changes requirement for "vsubsbs" instruction, which has been supported
since ISA 2.03. (Please see section 5.9.1.2 of ISA 2.03)

Reported-by: Paul A. Clarke 
Signed-off-by: Paul A. Clarke 
Signed-off-by: Leonardo Bras 
Signed-off-by: David Gibson 
---
 target/ppc/translate/vmx-ops.inc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/ppc/translate/vmx-ops.inc.c 
b/target/ppc/translate/vmx-ops.inc.c
index 139f80cb24..84e05fb827 100644
--- a/target/ppc/translate/vmx-ops.inc.c
+++ b/target/ppc/translate/vmx-ops.inc.c
@@ -143,7 +143,7 @@ GEN_VXFORM(vaddsws, 0, 14),
 GEN_VXFORM_DUAL(vsububs, bcdadd, 0, 24, PPC_ALTIVEC, PPC_NONE),
 GEN_VXFORM_DUAL(vsubuhs, bcdsub, 0, 25, PPC_ALTIVEC, PPC_NONE),
 GEN_VXFORM(vsubuws, 0, 26),
-GEN_VXFORM_DUAL(vsubsbs, bcdtrunc, 0, 28, PPC_NONE, PPC2_ISA300),
+GEN_VXFORM_DUAL(vsubsbs, bcdtrunc, 0, 28, PPC_ALTIVEC, PPC2_ISA300),
 GEN_VXFORM(vsubshs, 0, 29),
 GEN_VXFORM_DUAL(vsubsws, xpnd04_2, 0, 30, PPC_ALTIVEC, PPC_NONE),
 GEN_VXFORM_207(vadduqm, 0, 4),
-- 
2.19.2




[Qemu-devel] [PULL 25/27] ppc/xive: notify the CPU when the interrupt priority is more privileged

2018-12-12 Thread David Gibson
From: Cédric Le Goater 

After the event data was enqueued in the O/S Event Queue, the IVPE
raises the bit corresponding to the priority of the pending interrupt
in the register IBP (Interrupt Pending Buffer) to indicate there is an
event pending in one of the 8 priority queues. The Pending Interrupt
Priority Register (PIPR) is also updated using the IPB. This register
represent the priority of the most favored pending notification.

The PIPR is then compared to the the Current Processor Priority
Register (CPPR). If it is more favored (numerically less than), the
CPU interrupt line is raised and the EO bit of the Notification Source
Register (NSR) is updated to notify the presence of an exception for
the O/S. The check needs to be done whenever the PIPR or the CPPR are
changed.

The O/S acknowledges the interrupt with a special load in the Thread
Interrupt Management Area. If the EO bit of the NSR is set, the CPPR
takes the value of PIPR. The bit number in the IBP corresponding to
the priority of the pending interrupt is reseted and so is the EO bit
of the NSR.

Signed-off-by: Cédric Le Goater 
Reviewed-by: David Gibson 
Signed-off-by: David Gibson 
---
 hw/intc/xive.c | 94 +-
 1 file changed, 93 insertions(+), 1 deletion(-)

diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index 3eecffe99b..ea5385ff77 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -22,9 +22,73 @@
  * XIVE Thread Interrupt Management context
  */
 
+/* Convert a priority number to an Interrupt Pending Buffer (IPB)
+ * register, which indicates a pending interrupt at the priority
+ * corresponding to the bit number
+ */
+static uint8_t priority_to_ipb(uint8_t priority)
+{
+return priority > XIVE_PRIORITY_MAX ?
+0 : 1 << (XIVE_PRIORITY_MAX - priority);
+}
+
+/* Convert an Interrupt Pending Buffer (IPB) register to a Pending
+ * Interrupt Priority Register (PIPR), which contains the priority of
+ * the most favored pending notification.
+ */
+static uint8_t ipb_to_pipr(uint8_t ibp)
+{
+return ibp ? clz32((uint32_t)ibp << 24) : 0xff;
+}
+
+static void ipb_update(uint8_t *regs, uint8_t priority)
+{
+regs[TM_IPB] |= priority_to_ipb(priority);
+regs[TM_PIPR] = ipb_to_pipr(regs[TM_IPB]);
+}
+
+static uint8_t exception_mask(uint8_t ring)
+{
+switch (ring) {
+case TM_QW1_OS:
+return TM_QW1_NSR_EO;
+default:
+g_assert_not_reached();
+}
+}
+
 static uint64_t xive_tctx_accept(XiveTCTX *tctx, uint8_t ring)
 {
-return 0;
+uint8_t *regs = >regs[ring];
+uint8_t nsr = regs[TM_NSR];
+uint8_t mask = exception_mask(ring);
+
+qemu_irq_lower(tctx->output);
+
+if (regs[TM_NSR] & mask) {
+uint8_t cppr = regs[TM_PIPR];
+
+regs[TM_CPPR] = cppr;
+
+/* Reset the pending buffer bit */
+regs[TM_IPB] &= ~priority_to_ipb(cppr);
+regs[TM_PIPR] = ipb_to_pipr(regs[TM_IPB]);
+
+/* Drop Exception bit */
+regs[TM_NSR] &= ~mask;
+}
+
+return (nsr << 8) | regs[TM_CPPR];
+}
+
+static void xive_tctx_notify(XiveTCTX *tctx, uint8_t ring)
+{
+uint8_t *regs = >regs[ring];
+
+if (regs[TM_PIPR] < regs[TM_CPPR]) {
+regs[TM_NSR] |= exception_mask(ring);
+qemu_irq_raise(tctx->output);
+}
 }
 
 static void xive_tctx_set_cppr(XiveTCTX *tctx, uint8_t ring, uint8_t cppr)
@@ -34,6 +98,9 @@ static void xive_tctx_set_cppr(XiveTCTX *tctx, uint8_t ring, 
uint8_t cppr)
 }
 
 tctx->regs[ring + TM_CPPR] = cppr;
+
+/* CPPR has changed, check if we need to raise a pending exception */
+xive_tctx_notify(tctx, ring);
 }
 
 /*
@@ -189,6 +256,17 @@ static void xive_tm_set_os_cppr(XiveTCTX *tctx, hwaddr 
offset,
 xive_tctx_set_cppr(tctx, TM_QW1_OS, value & 0xff);
 }
 
+/*
+ * Adjust the IPB to allow a CPU to process event queues of other
+ * priorities during one physical interrupt cycle.
+ */
+static void xive_tm_set_os_pending(XiveTCTX *tctx, hwaddr offset,
+   uint64_t value, unsigned size)
+{
+ipb_update(>regs[TM_QW1_OS], value & 0xff);
+xive_tctx_notify(tctx, TM_QW1_OS);
+}
+
 /*
  * Define a mapping of "special" operations depending on the TIMA page
  * offset and the size of the operation.
@@ -211,6 +289,7 @@ static const XiveTmOp xive_tm_operations[] = {
 
 /* MMIOs above 2K : special operations with side effects */
 { XIVE_TM_OS_PAGE, TM_SPC_ACK_OS_REG, 2, NULL, xive_tm_ack_os_reg },
+{ XIVE_TM_OS_PAGE, TM_SPC_SET_OS_PENDING, 1, xive_tm_set_os_pending, NULL 
},
 };
 
 static const XiveTmOp *xive_tm_find_op(hwaddr offset, unsigned size, bool 
write)
@@ -373,6 +452,13 @@ static void xive_tctx_reset(void *dev)
 tctx->regs[TM_QW1_OS + TM_LSMFB] = 0xFF;
 tctx->regs[TM_QW1_OS + TM_ACK_CNT] = 0xFF;
 tctx->regs[TM_QW1_OS + TM_AGE] = 0xFF;
+
+/*
+ * Initialize PIPR to 0xFF to avoid phantom interrupts when the
+ * CPPR is first set.
+ */
+tctx->regs[TM_QW1_OS + TM_PIPR] =
+

[Qemu-devel] [PULL 26/27] spapr/xive: introduce a XIVE interrupt controller

2018-12-12 Thread David Gibson
From: Cédric Le Goater 

sPAPRXive models the XIVE interrupt controller of the sPAPR machine.
It inherits from the XiveRouter and provisions storage for the routing
tables :

  - Event Assignment Structure (EAS)
  - Event Notification Descriptor (END)

The sPAPRXive model incorporates an internal XiveSource for the IPIs
and for the interrupts of the virtual devices of the guest. This model
is consistent with XIVE architecture which also incorporates an
internal IVSE for IPIs and accelerator interrupts in the IVRE
sub-engine.

The sPAPRXive model exports two memory regions, one for the ESB
trigger and management pages used to control the sources and one for
the TIMA pages. They are mapped by default at the addresses found on
chip 0 of a baremetal system. This is also consistent with the XIVE
architecture which defines a Virtualization Controller BAR for the
internal IVSE ESB pages and a Thread Managment BAR for the TIMA.

Signed-off-by: Cédric Le Goater 
Reviewed-by: David Gibson 
Signed-off-by: David Gibson 
---
 default-configs/ppc64-softmmu.mak |   1 +
 hw/intc/Makefile.objs |   1 +
 hw/intc/spapr_xive.c  | 366 ++
 include/hw/ppc/spapr_xive.h   |  45 
 4 files changed, 413 insertions(+)
 create mode 100644 hw/intc/spapr_xive.c
 create mode 100644 include/hw/ppc/spapr_xive.h

diff --git a/default-configs/ppc64-softmmu.mak 
b/default-configs/ppc64-softmmu.mak
index 2d1e7c5c46..7f34ad0528 100644
--- a/default-configs/ppc64-softmmu.mak
+++ b/default-configs/ppc64-softmmu.mak
@@ -17,6 +17,7 @@ CONFIG_XICS=$(CONFIG_PSERIES)
 CONFIG_XICS_SPAPR=$(CONFIG_PSERIES)
 CONFIG_XICS_KVM=$(call land,$(CONFIG_PSERIES),$(CONFIG_KVM))
 CONFIG_XIVE=$(CONFIG_PSERIES)
+CONFIG_XIVE_SPAPR=$(CONFIG_PSERIES)
 CONFIG_MEM_DEVICE=y
 CONFIG_DIMM=y
 CONFIG_SPAPR_RNG=y
diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
index 72a46ed91c..301a8e972d 100644
--- a/hw/intc/Makefile.objs
+++ b/hw/intc/Makefile.objs
@@ -38,6 +38,7 @@ obj-$(CONFIG_XICS) += xics.o
 obj-$(CONFIG_XICS_SPAPR) += xics_spapr.o
 obj-$(CONFIG_XICS_KVM) += xics_kvm.o
 obj-$(CONFIG_XIVE) += xive.o
+obj-$(CONFIG_XIVE_SPAPR) += spapr_xive.o
 obj-$(CONFIG_POWERNV) += xics_pnv.o
 obj-$(CONFIG_ALLWINNER_A10_PIC) += allwinner-a10-pic.o
 obj-$(CONFIG_S390_FLIC) += s390_flic.o
diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c
new file mode 100644
index 00..eef5830d45
--- /dev/null
+++ b/hw/intc/spapr_xive.c
@@ -0,0 +1,366 @@
+/*
+ * QEMU PowerPC sPAPR XIVE interrupt controller model
+ *
+ * Copyright (c) 2017-2018, IBM Corporation.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "qemu/error-report.h"
+#include "target/ppc/cpu.h"
+#include "sysemu/cpus.h"
+#include "monitor/monitor.h"
+#include "hw/ppc/spapr.h"
+#include "hw/ppc/spapr_xive.h"
+#include "hw/ppc/xive.h"
+#include "hw/ppc/xive_regs.h"
+
+/*
+ * XIVE Virtualization Controller BAR and Thread Managment BAR that we
+ * use for the ESB pages and the TIMA pages
+ */
+#define SPAPR_XIVE_VC_BASE   0x00060100ull
+#define SPAPR_XIVE_TM_BASE   0x000603020318ull
+
+/*
+ * On sPAPR machines, use a simplified output for the XIVE END
+ * structure dumping only the information related to the OS EQ.
+ */
+static void spapr_xive_end_pic_print_info(sPAPRXive *xive, XiveEND *end,
+  Monitor *mon)
+{
+uint32_t qindex = GETFIELD_BE32(END_W1_PAGE_OFF, end->w1);
+uint32_t qgen = GETFIELD_BE32(END_W1_GENERATION, end->w1);
+uint32_t qsize = GETFIELD_BE32(END_W0_QSIZE, end->w0);
+uint32_t qentries = 1 << (qsize + 10);
+uint32_t nvt = GETFIELD_BE32(END_W6_NVT_INDEX, end->w6);
+uint8_t priority = GETFIELD_BE32(END_W7_F0_PRIORITY, end->w7);
+
+monitor_printf(mon, "%3d/%d % 6d/%5d ^%d", nvt,
+   priority, qindex, qentries, qgen);
+
+xive_end_queue_pic_print_info(end, 6, mon);
+monitor_printf(mon, "]");
+}
+
+void spapr_xive_pic_print_info(sPAPRXive *xive, Monitor *mon)
+{
+XiveSource *xsrc = >source;
+int i;
+
+monitor_printf(mon, "  LSIN PQEISN CPU/PRIO EQ\n");
+
+for (i = 0; i < xive->nr_irqs; i++) {
+uint8_t pq = xive_source_esb_get(xsrc, i);
+XiveEAS *eas = >eat[i];
+
+if (!xive_eas_is_valid(eas)) {
+continue;
+}
+
+monitor_printf(mon, "  %08x %s %c%c%c %s %08x ", i,
+   xive_source_irq_is_lsi(xsrc, i) ? "LSI" : "MSI",
+   pq & XIVE_ESB_VAL_P ? 'P' : '-',
+   pq & XIVE_ESB_VAL_Q ? 'Q' : '-',
+   xsrc->status[i] & XIVE_STATUS_ASSERTED ? 'A' : ' ',
+   xive_eas_is_masked(eas) ? "M" : " ",
+   (int) GETFIELD_BE64(EAS_END_DATA, eas->w));
+
+if (!xive_eas_is_masked(eas)) {
+uint32_t 

[Qemu-devel] [PULL 13/27] ppc/xive: introduce a XIVE interrupt source model

2018-12-12 Thread David Gibson
From: Cédric Le Goater 

The first sub-engine of the overall XIVE architecture is the Interrupt
Virtualization Source Engine (IVSE). An IVSE can be integrated into
another logic, like in a PCI PHB or in the main interrupt controller
to manage IPIs.

Each IVSE instance is associated with an Event State Buffer (ESB) that
contains a two bit state entry for each possible event source. When an
event is signaled to the IVSE, by MMIO or some other means, the
associated interrupt state bits are fetched from the ESB and
modified. Depending on the resulting ESB state, the event is forwarded
to the IVRE sub-engine of the controller doing the routing.

Each supported ESB entry is associated with either a single or a
even/odd pair of pages which provides commands to manage the source:
to EOI, to turn off the source for instance.

On a sPAPR machine, the O/S will obtain the page address of the ESB
entry associated with a source and its characteristic using the
H_INT_GET_SOURCE_INFO hcall. On PowerNV, a similar OPAL call is used.

The xive_source_notify() routine is in charge forwarding the source
event notification to the routing engine. It will be filled later on.

Signed-off-by: Cédric Le Goater 
Signed-off-by: David Gibson 
---
 default-configs/ppc64-softmmu.mak |   1 +
 hw/intc/Makefile.objs |   1 +
 hw/intc/xive.c| 382 ++
 include/hw/ppc/xive.h | 260 
 4 files changed, 644 insertions(+)
 create mode 100644 hw/intc/xive.c
 create mode 100644 include/hw/ppc/xive.h

diff --git a/default-configs/ppc64-softmmu.mak 
b/default-configs/ppc64-softmmu.mak
index aec2855750..2d1e7c5c46 100644
--- a/default-configs/ppc64-softmmu.mak
+++ b/default-configs/ppc64-softmmu.mak
@@ -16,6 +16,7 @@ CONFIG_VIRTIO_VGA=y
 CONFIG_XICS=$(CONFIG_PSERIES)
 CONFIG_XICS_SPAPR=$(CONFIG_PSERIES)
 CONFIG_XICS_KVM=$(call land,$(CONFIG_PSERIES),$(CONFIG_KVM))
+CONFIG_XIVE=$(CONFIG_PSERIES)
 CONFIG_MEM_DEVICE=y
 CONFIG_DIMM=y
 CONFIG_SPAPR_RNG=y
diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
index 0e9963f5ee..72a46ed91c 100644
--- a/hw/intc/Makefile.objs
+++ b/hw/intc/Makefile.objs
@@ -37,6 +37,7 @@ obj-$(CONFIG_SH4) += sh_intc.o
 obj-$(CONFIG_XICS) += xics.o
 obj-$(CONFIG_XICS_SPAPR) += xics_spapr.o
 obj-$(CONFIG_XICS_KVM) += xics_kvm.o
+obj-$(CONFIG_XIVE) += xive.o
 obj-$(CONFIG_POWERNV) += xics_pnv.o
 obj-$(CONFIG_ALLWINNER_A10_PIC) += allwinner-a10-pic.o
 obj-$(CONFIG_S390_FLIC) += s390_flic.o
diff --git a/hw/intc/xive.c b/hw/intc/xive.c
new file mode 100644
index 00..6389bd8323
--- /dev/null
+++ b/hw/intc/xive.c
@@ -0,0 +1,382 @@
+/*
+ * QEMU PowerPC XIVE interrupt controller model
+ *
+ * Copyright (c) 2017-2018, IBM Corporation.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "target/ppc/cpu.h"
+#include "sysemu/cpus.h"
+#include "sysemu/dma.h"
+#include "hw/qdev-properties.h"
+#include "monitor/monitor.h"
+#include "hw/ppc/xive.h"
+
+/*
+ * XIVE ESB helpers
+ */
+
+static uint8_t xive_esb_set(uint8_t *pq, uint8_t value)
+{
+uint8_t old_pq = *pq & 0x3;
+
+*pq &= ~0x3;
+*pq |= value & 0x3;
+
+return old_pq;
+}
+
+static bool xive_esb_trigger(uint8_t *pq)
+{
+uint8_t old_pq = *pq & 0x3;
+
+switch (old_pq) {
+case XIVE_ESB_RESET:
+xive_esb_set(pq, XIVE_ESB_PENDING);
+return true;
+case XIVE_ESB_PENDING:
+case XIVE_ESB_QUEUED:
+xive_esb_set(pq, XIVE_ESB_QUEUED);
+return false;
+case XIVE_ESB_OFF:
+xive_esb_set(pq, XIVE_ESB_OFF);
+return false;
+default:
+ g_assert_not_reached();
+}
+}
+
+static bool xive_esb_eoi(uint8_t *pq)
+{
+uint8_t old_pq = *pq & 0x3;
+
+switch (old_pq) {
+case XIVE_ESB_RESET:
+case XIVE_ESB_PENDING:
+xive_esb_set(pq, XIVE_ESB_RESET);
+return false;
+case XIVE_ESB_QUEUED:
+xive_esb_set(pq, XIVE_ESB_PENDING);
+return true;
+case XIVE_ESB_OFF:
+xive_esb_set(pq, XIVE_ESB_OFF);
+return false;
+default:
+ g_assert_not_reached();
+}
+}
+
+/*
+ * XIVE Interrupt Source (or IVSE)
+ */
+
+uint8_t xive_source_esb_get(XiveSource *xsrc, uint32_t srcno)
+{
+assert(srcno < xsrc->nr_irqs);
+
+return xsrc->status[srcno] & 0x3;
+}
+
+uint8_t xive_source_esb_set(XiveSource *xsrc, uint32_t srcno, uint8_t pq)
+{
+assert(srcno < xsrc->nr_irqs);
+
+return xive_esb_set(>status[srcno], pq);
+}
+
+/*
+ * Returns whether the event notification should be forwarded.
+ */
+static bool xive_source_esb_trigger(XiveSource *xsrc, uint32_t srcno)
+{
+assert(srcno < xsrc->nr_irqs);
+
+return xive_esb_trigger(>status[srcno]);
+}
+
+/*
+ * Returns whether the event notification should be forwarded.
+ */
+static bool xive_source_esb_eoi(XiveSource *xsrc, uint32_t srcno)
+{
+

[Qemu-devel] [PULL 20/27] spapr: export and rename the xics_max_server_number() routine

2018-12-12 Thread David Gibson
From: Cédric Le Goater 

The XIVE sPAPR IRQ backend will use it to define the number of ENDs of
the IC controller.

Signed-off-by: Cédric Le Goater 
Signed-off-by: David Gibson 
---
 hw/ppc/spapr.c | 8 
 include/hw/ppc/spapr.h | 1 +
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 625f467c3e..0293a23739 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -150,7 +150,7 @@ static void pre_2_10_vmstate_unregister_dummy_icp(int i)
(void *)(uintptr_t) i);
 }
 
-static int xics_max_server_number(sPAPRMachineState *spapr)
+int spapr_max_server_number(sPAPRMachineState *spapr)
 {
 assert(spapr->vsmt);
 return DIV_ROUND_UP(max_cpus * spapr->vsmt, smp_threads);
@@ -1268,7 +1268,7 @@ static void *spapr_build_fdt(sPAPRMachineState *spapr,
 _FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2));
 
 /* /interrupt controller */
-spapr_dt_xics(xics_max_server_number(spapr), fdt, PHANDLE_XICP);
+spapr_dt_xics(spapr_max_server_number(spapr), fdt, PHANDLE_XICP);
 
 ret = spapr_populate_memory(spapr, fdt);
 if (ret < 0) {
@@ -2467,7 +2467,7 @@ static void spapr_init_cpus(sPAPRMachineState *spapr)
 if (smc->pre_2_10_has_unused_icps) {
 int i;
 
-for (i = 0; i < xics_max_server_number(spapr); i++) {
+for (i = 0; i < spapr_max_server_number(spapr); i++) {
 /* Dummy entries get deregistered when real ICPState objects
  * are registered during CPU core hotplug.
  */
@@ -2587,7 +2587,7 @@ static void spapr_machine_init(MachineState *machine)
 load_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR) - FW_OVERHEAD;
 
 /* VSMT must be set in order to be able to compute VCPU ids, ie to
- * call xics_max_server_number() or spapr_vcpu_id().
+ * call spapr_max_server_number() or spapr_vcpu_id().
  */
 spapr_set_vsmt_mode(spapr, _fatal);
 
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 6279711fe8..198764066d 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -737,6 +737,7 @@ int spapr_hpt_shift_for_ramsize(uint64_t ramsize);
 void spapr_reallocate_hpt(sPAPRMachineState *spapr, int shift,
   Error **errp);
 void spapr_clear_pending_events(sPAPRMachineState *spapr);
+int spapr_max_server_number(sPAPRMachineState *spapr);
 
 /* CPU and LMB DRC release callbacks. */
 void spapr_core_release(DeviceState *dev);
-- 
2.19.2




[Qemu-devel] [PULL 17/27] ppc/xive: introduce the XIVE Event Notification Descriptors

2018-12-12 Thread David Gibson
From: Cédric Le Goater 

To complete the event routing, the IVRE sub-engine uses a second table
containing Event Notification Descriptor (END) structures.

An END specifies on which Event Queue (EQ) the event notification
data, defined in the associated EAS, should be posted when an
exception occurs. It also defines which Notification Virtual Target
(NVT) should be notified.

The Event Queue is a memory page provided by the O/S defining a
circular buffer, one per server and priority couple, containing Event
Queue entries. These are 4 bytes long, the first bit being a
'generation' bit and the 31 following bits the END Data field. They
are pulled by the O/S when the exception occurs.

The END Data field is a way to set an invariant logical event source
number for an IRQ. On sPAPR machines, it is set with the
H_INT_SET_SOURCE_CONFIG hcall when the EISN flag is used.

Signed-off-by: Cédric Le Goater 
Signed-off-by: David Gibson 
---
 hw/intc/xive.c | 174 +
 include/hw/ppc/xive.h  |  18 
 include/hw/ppc/xive_regs.h |  57 
 3 files changed, 249 insertions(+)

diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index d21df6674d..41d8ba1540 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -443,6 +443,95 @@ static const TypeInfo xive_source_info = {
 .class_init= xive_source_class_init,
 };
 
+/*
+ * XiveEND helpers
+ */
+
+void xive_end_queue_pic_print_info(XiveEND *end, uint32_t width, Monitor *mon)
+{
+uint64_t qaddr_base = (uint64_t) be32_to_cpu(end->w2 & 0x0fff) << 32
+| be32_to_cpu(end->w3);
+uint32_t qsize = GETFIELD_BE32(END_W0_QSIZE, end->w0);
+uint32_t qindex = GETFIELD_BE32(END_W1_PAGE_OFF, end->w1);
+uint32_t qentries = 1 << (qsize + 10);
+int i;
+
+/*
+ * print out the [ (qindex - (width - 1)) .. (qindex + 1)] window
+ */
+monitor_printf(mon, " [ ");
+qindex = (qindex - (width - 1)) & (qentries - 1);
+for (i = 0; i < width; i++) {
+uint64_t qaddr = qaddr_base + (qindex << 2);
+uint32_t qdata = -1;
+
+if (dma_memory_read(_space_memory, qaddr, ,
+sizeof(qdata))) {
+qemu_log_mask(LOG_GUEST_ERROR, "XIVE: failed to read EQ @0x%"
+  HWADDR_PRIx "\n", qaddr);
+return;
+}
+monitor_printf(mon, "%s%08x ", i == width - 1 ? "^" : "",
+   be32_to_cpu(qdata));
+qindex = (qindex + 1) & (qentries - 1);
+}
+}
+
+void xive_end_pic_print_info(XiveEND *end, uint32_t end_idx, Monitor *mon)
+{
+uint64_t qaddr_base = (uint64_t) be32_to_cpu(end->w2 & 0x0fff) << 32
+| be32_to_cpu(end->w3);
+uint32_t qindex = GETFIELD_BE32(END_W1_PAGE_OFF, end->w1);
+uint32_t qgen = GETFIELD_BE32(END_W1_GENERATION, end->w1);
+uint32_t qsize = GETFIELD_BE32(END_W0_QSIZE, end->w0);
+uint32_t qentries = 1 << (qsize + 10);
+
+uint32_t nvt = GETFIELD_BE32(END_W6_NVT_INDEX, end->w6);
+uint8_t priority = GETFIELD_BE32(END_W7_F0_PRIORITY, end->w7);
+
+if (!xive_end_is_valid(end)) {
+return;
+}
+
+monitor_printf(mon, "  %08x %c%c%c%c%c prio:%d nvt:%04x eq:@%08"PRIx64
+   "% 6d/%5d ^%d", end_idx,
+   xive_end_is_valid(end)? 'v' : '-',
+   xive_end_is_enqueue(end)  ? 'q' : '-',
+   xive_end_is_notify(end)   ? 'n' : '-',
+   xive_end_is_backlog(end)  ? 'b' : '-',
+   xive_end_is_escalate(end) ? 'e' : '-',
+   priority, nvt, qaddr_base, qindex, qentries, qgen);
+
+xive_end_queue_pic_print_info(end, 6, mon);
+monitor_printf(mon, "]\n");
+}
+
+static void xive_end_enqueue(XiveEND *end, uint32_t data)
+{
+uint64_t qaddr_base = (uint64_t) be32_to_cpu(end->w2 & 0x0fff) << 32
+| be32_to_cpu(end->w3);
+uint32_t qsize = GETFIELD_BE32(END_W0_QSIZE, end->w0);
+uint32_t qindex = GETFIELD_BE32(END_W1_PAGE_OFF, end->w1);
+uint32_t qgen = GETFIELD_BE32(END_W1_GENERATION, end->w1);
+
+uint64_t qaddr = qaddr_base + (qindex << 2);
+uint32_t qdata = cpu_to_be32((qgen << 31) | (data & 0x7fff));
+uint32_t qentries = 1 << (qsize + 10);
+
+if (dma_memory_write(_space_memory, qaddr, , sizeof(qdata))) 
{
+qemu_log_mask(LOG_GUEST_ERROR, "XIVE: failed to write END data @0x%"
+  HWADDR_PRIx "\n", qaddr);
+return;
+}
+
+qindex = (qindex + 1) & (qentries - 1);
+if (qindex == 0) {
+qgen ^= 1;
+end->w1 = SETFIELD_BE32(END_W1_GENERATION, end->w1, qgen);
+}
+end->w1 = SETFIELD_BE32(END_W1_PAGE_OFF, end->w1, qindex);
+}
+
 /*
  * XIVE Router (aka. Virtualization Controller or IVRE)
  */
@@ -455,6 +544,83 @@ int xive_router_get_eas(XiveRouter *xrtr, uint8_t eas_blk, 
uint32_t eas_idx,
 return xrc->get_eas(xrtr, eas_blk, eas_idx, eas);
 }
 
+int xive_router_get_end(XiveRouter *xrtr, uint8_t end_blk, uint32_t end_idx,
+ 

[Qemu-devel] [PULL 23/27] ppc/xive: introduce the XIVE interrupt thread context

2018-12-12 Thread David Gibson
From: Cédric Le Goater 

Each POWER9 processor chip has a XIVE presenter that can generate four
different exceptions to its threads:

  - hypervisor exception,
  - O/S exception
  - Event-Based Branch (EBB)
  - msgsnd (doorbell).

Each exception has a state independent from the others called a Thread
Interrupt Management context. This context is a set of registers which
lets the thread handle priority management and interrupt acknowledgment
among other things. The most important ones being :

  - Interrupt Priority Register  (PIPR)
  - Interrupt Pending Buffer (IPB)
  - Current Processor Priority   (CPPR)
  - Notification Source Register (NSR)

These registers are accessible through a specific MMIO region, called
the Thread Interrupt Management Area (TIMA), four aligned pages, each
exposing a different view of the registers. First page (page address
ending in 0b00) gives access to the entire context and is reserved for
the ring 0 view for the physical thread context. The second (page
address ending in 0b01) is for the hypervisor, ring 1 view. The third
(page address ending in 0b10) is for the operating system, ring 2
view. The fourth (page address ending in 0b11) is for user level, ring
3 view.

The thread interrupt context is modeled with a XiveTCTX object
containing the values of the different exception registers. The TIMA
region is mapped at the same address for each CPU.

Signed-off-by: Cédric Le Goater 
Reviewed-by: David Gibson 
Signed-off-by: David Gibson 
---
 hw/intc/xive.c | 424 +
 include/hw/ppc/xive.h  |  44 
 include/hw/ppc/xive_regs.h |  82 +++
 3 files changed, 550 insertions(+)

diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index 2196ce8de0..2615d16b74 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -16,6 +16,429 @@
 #include "hw/qdev-properties.h"
 #include "monitor/monitor.h"
 #include "hw/ppc/xive.h"
+#include "hw/ppc/xive_regs.h"
+
+/*
+ * XIVE Thread Interrupt Management context
+ */
+
+static uint64_t xive_tctx_accept(XiveTCTX *tctx, uint8_t ring)
+{
+return 0;
+}
+
+static void xive_tctx_set_cppr(XiveTCTX *tctx, uint8_t ring, uint8_t cppr)
+{
+if (cppr > XIVE_PRIORITY_MAX) {
+cppr = 0xff;
+}
+
+tctx->regs[ring + TM_CPPR] = cppr;
+}
+
+/*
+ * XIVE Thread Interrupt Management Area (TIMA)
+ */
+
+/*
+ * Define an access map for each page of the TIMA that we will use in
+ * the memory region ops to filter values when doing loads and stores
+ * of raw registers values
+ *
+ * Registers accessibility bits :
+ *
+ *0x0 - no access
+ *0x1 - write only
+ *0x2 - read only
+ *0x3 - read/write
+ */
+
+static const uint8_t xive_tm_hw_view[] = {
+/* QW-0 User */   3, 0, 0, 0,   0, 0, 0, 0,   3, 3, 3, 3,   0, 0, 0, 0,
+/* QW-1 OS   */   3, 3, 3, 3,   3, 3, 0, 3,   3, 3, 3, 3,   0, 0, 0, 0,
+/* QW-2 POOL */   0, 0, 3, 3,   0, 0, 0, 0,   3, 3, 3, 3,   0, 0, 0, 0,
+/* QW-3 PHYS */   3, 3, 3, 3,   0, 3, 0, 3,   3, 0, 0, 3,   3, 3, 3, 0,
+};
+
+static const uint8_t xive_tm_hv_view[] = {
+/* QW-0 User */   3, 0, 0, 0,   0, 0, 0, 0,   3, 3, 3, 3,   0, 0, 0, 0,
+/* QW-1 OS   */   3, 3, 3, 3,   3, 3, 0, 3,   3, 3, 3, 3,   0, 0, 0, 0,
+/* QW-2 POOL */   0, 0, 3, 3,   0, 0, 0, 0,   0, 3, 3, 3,   0, 0, 0, 0,
+/* QW-3 PHYS */   3, 3, 3, 3,   0, 3, 0, 3,   3, 0, 0, 3,   0, 0, 0, 0,
+};
+
+static const uint8_t xive_tm_os_view[] = {
+/* QW-0 User */   3, 0, 0, 0,   0, 0, 0, 0,   3, 3, 3, 3,   0, 0, 0, 0,
+/* QW-1 OS   */   2, 3, 2, 2,   2, 2, 0, 2,   0, 0, 0, 0,   0, 0, 0, 0,
+/* QW-2 POOL */   0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,
+/* QW-3 PHYS */   0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,
+};
+
+static const uint8_t xive_tm_user_view[] = {
+/* QW-0 User */   3, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,
+/* QW-1 OS   */   0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,
+/* QW-2 POOL */   0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,
+/* QW-3 PHYS */   0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,   0, 0, 0, 0,
+};
+
+/*
+ * Overall TIMA access map for the thread interrupt management context
+ * registers
+ */
+static const uint8_t *xive_tm_views[] = {
+[XIVE_TM_HW_PAGE]   = xive_tm_hw_view,
+[XIVE_TM_HV_PAGE]   = xive_tm_hv_view,
+[XIVE_TM_OS_PAGE]   = xive_tm_os_view,
+[XIVE_TM_USER_PAGE] = xive_tm_user_view,
+};
+
+/*
+ * Computes a register access mask for a given offset in the TIMA
+ */
+static uint64_t xive_tm_mask(hwaddr offset, unsigned size, bool write)
+{
+uint8_t page_offset = (offset >> TM_SHIFT) & 0x3;
+uint8_t reg_offset = offset & 0x3F;
+uint8_t reg_mask = write ? 0x1 : 0x2;
+uint64_t mask = 0x0;
+int i;
+
+for (i = 0; i < size; i++) {
+if (xive_tm_views[page_offset][reg_offset + i] & reg_mask) {
+mask |= (uint64_t) 0xff << (8 * (size - i - 1));
+}
+}
+
+return mask;
+}
+
+static void xive_tm_raw_write(XiveTCTX 

[Qemu-devel] [PULL 12/27] e500: simplify IRQ wiring

2018-12-12 Thread David Gibson
From: Greg Kurz 

The OpenPIC have 5 outputs per connected CPU. The machine init code hence
needs a bi-dimensional array (smp_cpu lines, 5 columns) to wire up the irqs
between the PIC and the CPUs.

The current code first allocates an array of smp_cpus pointers to qemu_irq
type, then it allocates another array of smp_cpus * 5 qemu_irq and fills the
first array with pointers to each line of the second array. This is rather
convoluted.

Simplify the logic by introducing a structured type that describes all the
OpenPIC outputs for a single CPU, ie, fixed size of 5 qemu_irq, and only
allocate a smp_cpu sized array of those.

This also allows to use g_new(T, n) instead of g_malloc(sizeof(T) * n)
as recommended in HACKING.

Signed-off-by: Greg Kurz 
Signed-off-by: David Gibson 
---
 hw/ppc/e500.c | 18 --
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index e6747fce28..b20fea0dfc 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -685,7 +685,7 @@ static void ppce500_cpu_reset(void *opaque)
 }
 
 static DeviceState *ppce500_init_mpic_qemu(PPCE500MachineState *pms,
-   qemu_irq **irqs)
+   IrqLines  *irqs)
 {
 DeviceState *dev;
 SysBusDevice *s;
@@ -705,7 +705,7 @@ static DeviceState 
*ppce500_init_mpic_qemu(PPCE500MachineState *pms,
 k = 0;
 for (i = 0; i < smp_cpus; i++) {
 for (j = 0; j < OPENPIC_OUTPUT_NB; j++) {
-sysbus_connect_irq(s, k++, irqs[i][j]);
+sysbus_connect_irq(s, k++, irqs[i].irq[j]);
 }
 }
 
@@ -713,7 +713,7 @@ static DeviceState 
*ppce500_init_mpic_qemu(PPCE500MachineState *pms,
 }
 
 static DeviceState *ppce500_init_mpic_kvm(const PPCE500MachineClass *pmc,
-  qemu_irq **irqs, Error **errp)
+  IrqLines *irqs, Error **errp)
 {
 Error *err = NULL;
 DeviceState *dev;
@@ -742,7 +742,7 @@ static DeviceState *ppce500_init_mpic_kvm(const 
PPCE500MachineClass *pmc,
 
 static DeviceState *ppce500_init_mpic(PPCE500MachineState *pms,
   MemoryRegion *ccsr,
-  qemu_irq **irqs)
+  IrqLines *irqs)
 {
 MachineState *machine = MACHINE(pms);
 const PPCE500MachineClass *pmc = PPCE500_MACHINE_GET_CLASS(pms);
@@ -806,15 +806,14 @@ void ppce500_init(MachineState *machine)
 /* irq num for pin INTA, INTB, INTC and INTD is 1, 2, 3 and
  * 4 respectively */
 unsigned int pci_irq_nrs[PCI_NUM_PINS] = {1, 2, 3, 4};
-qemu_irq **irqs;
+IrqLines *irqs;
 DeviceState *dev, *mpicdev;
 CPUPPCState *firstenv = NULL;
 MemoryRegion *ccsr_addr_space;
 SysBusDevice *s;
 PPCE500CCSRState *ccsr;
 
-irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *));
-irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB);
+irqs = g_new0(IrqLines, smp_cpus);
 for (i = 0; i < smp_cpus; i++) {
 PowerPCCPU *cpu;
 CPUState *cs;
@@ -834,10 +833,9 @@ void ppce500_init(MachineState *machine)
 firstenv = env;
 }
 
-irqs[i] = irqs[0] + (i * OPENPIC_OUTPUT_NB);
 input = (qemu_irq *)env->irq_inputs;
-irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT];
-irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];
+irqs[i].irq[OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT];
+irqs[i].irq[OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];
 env->spr_cb[SPR_BOOKE_PIR].default_value = cs->cpu_index = i;
 env->mpic_iack = pmc->ccsrbar_base + MPC8544_MPIC_REGS_OFFSET + 0xa0;
 
-- 
2.19.2




[Qemu-devel] [PULL 22/27] ppc/xive: add support for the END Event State Buffers

2018-12-12 Thread David Gibson
From: Cédric Le Goater 

The Event Notification Descriptor (END) XIVE structure also contains
two Event State Buffers providing further coalescing of interrupts,
one for the notification event (ESn) and one for the escalation events
(ESe). A MMIO page is assigned for each to control the EOI through
loads only. Stores are not allowed.

The END ESBs are modeled through an object resembling the 'XiveSource'
It is stateless as the END state bits are backed into the XiveEND
structure under the XiveRouter and the MMIO accesses follow the same
rules as for the XiveSource ESBs.

END ESBs are not supported by the Linux drivers neither on OPAL nor on
sPAPR. Nevetherless, it provides a mean to study the question in the
future and validates a bit more the XIVE model.

Signed-off-by: Cédric Le Goater 
Signed-off-by: David Gibson 
---
 hw/intc/xive.c| 160 +-
 include/hw/ppc/xive.h |  21 ++
 2 files changed, 179 insertions(+), 2 deletions(-)

diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index 41d8ba1540..2196ce8de0 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -612,8 +612,18 @@ static void xive_router_end_notify(XiveRouter *xrtr, 
uint8_t end_blk,
  * even futher coalescing in the Router
  */
 if (!xive_end_is_notify()) {
-qemu_log_mask(LOG_UNIMP, "XIVE: !UCOND_NOTIFY not implemented\n");
-return;
+uint8_t pq = GETFIELD_BE32(END_W1_ESn, end.w1);
+bool notify = xive_esb_trigger();
+
+if (pq != GETFIELD_BE32(END_W1_ESn, end.w1)) {
+end.w1 = SETFIELD_BE32(END_W1_ESn, end.w1, pq);
+xive_router_write_end(xrtr, end_blk, end_idx, , 1);
+}
+
+/* ESn[Q]=1 : end of notification */
+if (!notify) {
+return;
+}
 }
 
 /*
@@ -692,6 +702,151 @@ void xive_eas_pic_print_info(XiveEAS *eas, uint32_t lisn, 
Monitor *mon)
(uint32_t) GETFIELD_BE64(EAS_END_DATA, eas->w));
 }
 
+/*
+ * END ESB MMIO loads
+ */
+static uint64_t xive_end_source_read(void *opaque, hwaddr addr, unsigned size)
+{
+XiveENDSource *xsrc = XIVE_END_SOURCE(opaque);
+uint32_t offset = addr & 0xFFF;
+uint8_t end_blk;
+uint32_t end_idx;
+XiveEND end;
+uint32_t end_esmask;
+uint8_t pq;
+uint64_t ret = -1;
+
+end_blk = xsrc->block_id;
+end_idx = addr >> (xsrc->esb_shift + 1);
+
+if (xive_router_get_end(xsrc->xrtr, end_blk, end_idx, )) {
+qemu_log_mask(LOG_GUEST_ERROR, "XIVE: No END %x/%x\n", end_blk,
+  end_idx);
+return -1;
+}
+
+if (!xive_end_is_valid()) {
+qemu_log_mask(LOG_GUEST_ERROR, "XIVE: END %x/%x is invalid\n",
+  end_blk, end_idx);
+return -1;
+}
+
+end_esmask = addr_is_even(addr, xsrc->esb_shift) ? END_W1_ESn : END_W1_ESe;
+pq = GETFIELD_BE32(end_esmask, end.w1);
+
+switch (offset) {
+case XIVE_ESB_LOAD_EOI ... XIVE_ESB_LOAD_EOI + 0x7FF:
+ret = xive_esb_eoi();
+
+/* Forward the source event notification for routing ?? */
+break;
+
+case XIVE_ESB_GET ... XIVE_ESB_GET + 0x3FF:
+ret = pq;
+break;
+
+case XIVE_ESB_SET_PQ_00 ... XIVE_ESB_SET_PQ_00 + 0x0FF:
+case XIVE_ESB_SET_PQ_01 ... XIVE_ESB_SET_PQ_01 + 0x0FF:
+case XIVE_ESB_SET_PQ_10 ... XIVE_ESB_SET_PQ_10 + 0x0FF:
+case XIVE_ESB_SET_PQ_11 ... XIVE_ESB_SET_PQ_11 + 0x0FF:
+ret = xive_esb_set(, (offset >> 8) & 0x3);
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid END ESB load addr %d\n",
+  offset);
+return -1;
+}
+
+if (pq != GETFIELD_BE32(end_esmask, end.w1)) {
+end.w1 = SETFIELD_BE32(end_esmask, end.w1, pq);
+xive_router_write_end(xsrc->xrtr, end_blk, end_idx, , 1);
+}
+
+return ret;
+}
+
+/*
+ * END ESB MMIO stores are invalid
+ */
+static void xive_end_source_write(void *opaque, hwaddr addr,
+  uint64_t value, unsigned size)
+{
+qemu_log_mask(LOG_GUEST_ERROR, "XIVE: invalid ESB write addr 0x%"
+  HWADDR_PRIx"\n", addr);
+}
+
+static const MemoryRegionOps xive_end_source_ops = {
+.read = xive_end_source_read,
+.write = xive_end_source_write,
+.endianness = DEVICE_BIG_ENDIAN,
+.valid = {
+.min_access_size = 8,
+.max_access_size = 8,
+},
+.impl = {
+.min_access_size = 8,
+.max_access_size = 8,
+},
+};
+
+static void xive_end_source_realize(DeviceState *dev, Error **errp)
+{
+XiveENDSource *xsrc = XIVE_END_SOURCE(dev);
+Object *obj;
+Error *local_err = NULL;
+
+obj = object_property_get_link(OBJECT(dev), "xive", _err);
+if (!obj) {
+error_propagate(errp, local_err);
+error_prepend(errp, "required link 'xive' not found: ");
+return;
+}
+
+xsrc->xrtr = XIVE_ROUTER(obj);
+
+if (!xsrc->nr_ends) {
+error_setg(errp, "Number of interrupt needs to 

[Qemu-devel] [PULL 14/27] ppc/xive: add support for the LSI interrupt sources

2018-12-12 Thread David Gibson
From: Cédric Le Goater 

The 'sent' status of the LSI interrupt source is modeled with the 'P'
bit of the ESB and the assertion status of the source is maintained
with an extra bit under the main XiveSource object. The type of the
source is stored in the same array for practical reasons.

Signed-off-by: Cédric Le Goater 
Signed-off-by: David Gibson 
---
 hw/intc/xive.c| 66 +++
 include/hw/ppc/xive.h | 19 -
 2 files changed, 78 insertions(+), 7 deletions(-)

diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index 6389bd8323..11c7aac962 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -89,14 +89,42 @@ uint8_t xive_source_esb_set(XiveSource *xsrc, uint32_t 
srcno, uint8_t pq)
 return xive_esb_set(>status[srcno], pq);
 }
 
+/*
+ * Returns whether the event notification should be forwarded.
+ */
+static bool xive_source_lsi_trigger(XiveSource *xsrc, uint32_t srcno)
+{
+uint8_t old_pq = xive_source_esb_get(xsrc, srcno);
+
+xsrc->status[srcno] |= XIVE_STATUS_ASSERTED;
+
+switch (old_pq) {
+case XIVE_ESB_RESET:
+xive_source_esb_set(xsrc, srcno, XIVE_ESB_PENDING);
+return true;
+default:
+return false;
+}
+}
+
 /*
  * Returns whether the event notification should be forwarded.
  */
 static bool xive_source_esb_trigger(XiveSource *xsrc, uint32_t srcno)
 {
+bool ret;
+
 assert(srcno < xsrc->nr_irqs);
 
-return xive_esb_trigger(>status[srcno]);
+ret = xive_esb_trigger(>status[srcno]);
+
+if (xive_source_irq_is_lsi(xsrc, srcno) &&
+xive_source_esb_get(xsrc, srcno) == XIVE_ESB_QUEUED) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "XIVE: queued an event on LSI IRQ %d\n", srcno);
+}
+
+return ret;
 }
 
 /*
@@ -104,9 +132,22 @@ static bool xive_source_esb_trigger(XiveSource *xsrc, 
uint32_t srcno)
  */
 static bool xive_source_esb_eoi(XiveSource *xsrc, uint32_t srcno)
 {
+bool ret;
+
 assert(srcno < xsrc->nr_irqs);
 
-return xive_esb_eoi(>status[srcno]);
+ret = xive_esb_eoi(>status[srcno]);
+
+/* LSI sources do not set the Q bit but they can still be
+ * asserted, in which case we should forward a new event
+ * notification
+ */
+if (xive_source_irq_is_lsi(xsrc, srcno) &&
+xsrc->status[srcno] & XIVE_STATUS_ASSERTED) {
+ret = xive_source_lsi_trigger(xsrc, srcno);
+}
+
+return ret;
 }
 
 /*
@@ -271,8 +312,16 @@ static void xive_source_set_irq(void *opaque, int srcno, 
int val)
 XiveSource *xsrc = XIVE_SOURCE(opaque);
 bool notify = false;
 
-if (val) {
-notify = xive_source_esb_trigger(xsrc, srcno);
+if (xive_source_irq_is_lsi(xsrc, srcno)) {
+if (val) {
+notify = xive_source_lsi_trigger(xsrc, srcno);
+} else {
+xsrc->status[srcno] &= ~XIVE_STATUS_ASSERTED;
+}
+} else {
+if (val) {
+notify = xive_source_esb_trigger(xsrc, srcno);
+}
 }
 
 /* Forward the source event notification for routing */
@@ -292,9 +341,11 @@ void xive_source_pic_print_info(XiveSource *xsrc, uint32_t 
offset, Monitor *mon)
 continue;
 }
 
-monitor_printf(mon, "  %08x %c%c\n", i + offset,
+monitor_printf(mon, "  %08x %s %c%c%c\n", i + offset,
+   xive_source_irq_is_lsi(xsrc, i) ? "LSI" : "MSI",
pq & XIVE_ESB_VAL_P ? 'P' : '-',
-   pq & XIVE_ESB_VAL_Q ? 'Q' : '-');
+   pq & XIVE_ESB_VAL_Q ? 'Q' : '-',
+   xsrc->status[i] & XIVE_STATUS_ASSERTED ? 'A' : ' ');
 }
 }
 
@@ -302,6 +353,8 @@ static void xive_source_reset(void *dev)
 {
 XiveSource *xsrc = XIVE_SOURCE(dev);
 
+/* Do not clear the LSI bitmap */
+
 /* PQs are initialized to 0b01 (Q=1) which corresponds to "ints off" */
 memset(xsrc->status, XIVE_ESB_OFF, xsrc->nr_irqs);
 }
@@ -324,6 +377,7 @@ static void xive_source_realize(DeviceState *dev, Error 
**errp)
 }
 
 xsrc->status = g_malloc0(xsrc->nr_irqs);
+xsrc->lsi_map = bitmap_new(xsrc->nr_irqs);
 
 memory_region_init_io(>esb_mmio, OBJECT(xsrc),
   _source_esb_ops, xsrc, "xive.esb",
diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h
index 7aa2e38012..7cebc32eba 100644
--- a/include/hw/ppc/xive.h
+++ b/include/hw/ppc/xive.h
@@ -162,8 +162,9 @@ typedef struct XiveSource {
 /* IRQs */
 uint32_tnr_irqs;
 qemu_irq*qirqs;
+unsigned long   *lsi_map;
 
-/* PQ bits */
+/* PQ bits and LSI assertion bit */
 uint8_t *status;
 
 /* ESB memory region */
@@ -219,6 +220,7 @@ static inline hwaddr xive_source_esb_mgmt(XiveSource *xsrc, 
int srcno)
  * When doing an EOI, the Q bit will indicate if the interrupt
  * needs to be re-triggered.
  */
+#define XIVE_STATUS_ASSERTED  0x4  /* Extra bit for LSI */
 #define XIVE_ESB_VAL_P0x2
 #define XIVE_ESB_VAL_Q0x1
 
@@ 

[Qemu-devel] [PULL 24/27] ppc/xive: introduce a simplified XIVE presenter

2018-12-12 Thread David Gibson
From: Cédric Le Goater 

The last sub-engine of the XIVE architecture is the Interrupt
Virtualization Presentation Engine (IVPE). On HW, the IVRE and the
IVPE share elements, the Power Bus interface (CQ), the routing table
descriptors, and they can be combined in the same HW logic. We do the
same in QEMU and combine both engines in the XiveRouter for
simplicity.

When the IVRE has completed its job of matching an event source with a
Notification Virtual Target (NVT) to notify, it forwards the event
notification to the IVPE sub-engine. The IVPE scans the thread
interrupt contexts of the Notification Virtual Targets (NVT)
dispatched on the HW processor threads and if a match is found, it
signals the thread. If not, the IVPE escalates the notification to
some other targets and records the notification in a backlog queue.

The IVPE maintains the thread interrupt context state for each of its
NVTs not dispatched on HW processor threads in the Notification
Virtual Target table (NVTT).

The model currently only supports single NVT notifications.

Signed-off-by: Cédric Le Goater 
Signed-off-by: David Gibson 
---
 hw/intc/xive.c | 185 +
 include/hw/ppc/xive.h  |  14 +++
 include/hw/ppc/xive_regs.h |  24 +
 3 files changed, 223 insertions(+)

diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index 2615d16b74..3eecffe99b 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -983,6 +983,183 @@ int xive_router_write_end(XiveRouter *xrtr, uint8_t 
end_blk, uint32_t end_idx,
return xrc->write_end(xrtr, end_blk, end_idx, end, word_number);
 }
 
+int xive_router_get_nvt(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx,
+XiveNVT *nvt)
+{
+   XiveRouterClass *xrc = XIVE_ROUTER_GET_CLASS(xrtr);
+
+   return xrc->get_nvt(xrtr, nvt_blk, nvt_idx, nvt);
+}
+
+int xive_router_write_nvt(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx,
+XiveNVT *nvt, uint8_t word_number)
+{
+   XiveRouterClass *xrc = XIVE_ROUTER_GET_CLASS(xrtr);
+
+   return xrc->write_nvt(xrtr, nvt_blk, nvt_idx, nvt, word_number);
+}
+
+/*
+ * The thread context register words are in big-endian format.
+ */
+static int xive_presenter_tctx_match(XiveTCTX *tctx, uint8_t format,
+ uint8_t nvt_blk, uint32_t nvt_idx,
+ bool cam_ignore, uint32_t logic_serv)
+{
+uint32_t cam = xive_nvt_cam_line(nvt_blk, nvt_idx);
+uint32_t qw2w2 = xive_tctx_word2(>regs[TM_QW2_HV_POOL]);
+uint32_t qw1w2 = xive_tctx_word2(>regs[TM_QW1_OS]);
+uint32_t qw0w2 = xive_tctx_word2(>regs[TM_QW0_USER]);
+
+/* TODO (PowerNV): ignore mode. The low order bits of the NVT
+ * identifier are ignored in the "CAM" match.
+ */
+
+if (format == 0) {
+if (cam_ignore == true) {
+/* F=0 & i=1: Logical server notification (bits ignored at
+ * the end of the NVT identifier)
+ */
+qemu_log_mask(LOG_UNIMP, "XIVE: no support for LS NVT %x/%x\n",
+  nvt_blk, nvt_idx);
+ return -1;
+}
+
+/* F=0 & i=0: Specific NVT notification */
+
+/* TODO (PowerNV) : PHYS ring */
+
+/* HV POOL ring */
+if ((be32_to_cpu(qw2w2) & TM_QW2W2_VP) &&
+cam == GETFIELD_BE32(TM_QW2W2_POOL_CAM, qw2w2)) {
+return TM_QW2_HV_POOL;
+}
+
+/* OS ring */
+if ((be32_to_cpu(qw1w2) & TM_QW1W2_VO) &&
+cam == GETFIELD_BE32(TM_QW1W2_OS_CAM, qw1w2)) {
+return TM_QW1_OS;
+}
+} else {
+/* F=1 : User level Event-Based Branch (EBB) notification */
+
+/* USER ring */
+if  ((be32_to_cpu(qw1w2) & TM_QW1W2_VO) &&
+ (cam == GETFIELD_BE32(TM_QW1W2_OS_CAM, qw1w2)) &&
+ (be32_to_cpu(qw0w2) & TM_QW0W2_VU) &&
+ (logic_serv == GETFIELD_BE32(TM_QW0W2_LOGIC_SERV, qw0w2))) {
+return TM_QW0_USER;
+}
+}
+return -1;
+}
+
+typedef struct XiveTCTXMatch {
+XiveTCTX *tctx;
+uint8_t ring;
+} XiveTCTXMatch;
+
+static bool xive_presenter_match(XiveRouter *xrtr, uint8_t format,
+ uint8_t nvt_blk, uint32_t nvt_idx,
+ bool cam_ignore, uint8_t priority,
+ uint32_t logic_serv, XiveTCTXMatch *match)
+{
+CPUState *cs;
+
+/* TODO (PowerNV): handle chip_id overwrite of block field for
+ * hardwired CAM compares */
+
+CPU_FOREACH(cs) {
+PowerPCCPU *cpu = POWERPC_CPU(cs);
+XiveTCTX *tctx = XIVE_TCTX(cpu->intc);
+int ring;
+
+/*
+ * HW checks that the CPU is enabled in the Physical Thread
+ * Enable Register (PTER).
+ */
+
+/*
+ * Check the thread context CAM lines and record matches. We
+ * will handle CPU exception delivery later
+ */
+ring = xive_presenter_tctx_match(tctx, 

[Qemu-devel] [PULL 08/27] ppc440_bamboo: use g_new(T, n) instead of g_malloc(sizeof(T) * n)

2018-12-12 Thread David Gibson
From: Greg Kurz 

Because it is a recommended coding practice (see HACKING).

Signed-off-by: Greg Kurz 
Reviewed-by: Philippe Mathieu-Daudé 
Reviewed-by: Edgar E. Iglesias 
Signed-off-by: David Gibson 
---
 hw/ppc/ppc440_bamboo.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index f5720f979e..b8aa55d526 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -169,8 +169,7 @@ static void bamboo_init(MachineState *machine)
 unsigned int pci_irq_nrs[4] = { 28, 27, 26, 25 };
 MemoryRegion *address_space_mem = get_system_memory();
 MemoryRegion *isa = g_new(MemoryRegion, 1);
-MemoryRegion *ram_memories
-= g_malloc(PPC440EP_SDRAM_NR_BANKS * sizeof(*ram_memories));
+MemoryRegion *ram_memories = g_new(MemoryRegion, PPC440EP_SDRAM_NR_BANKS);
 hwaddr ram_bases[PPC440EP_SDRAM_NR_BANKS];
 hwaddr ram_sizes[PPC440EP_SDRAM_NR_BANKS];
 qemu_irq *pic;
@@ -200,7 +199,7 @@ static void bamboo_init(MachineState *machine)
 ppc_dcr_init(env, NULL, NULL);
 
 /* interrupt controller */
-irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
+irqs = g_new0(qemu_irq, PPCUIC_OUTPUT_NB);
 irqs[PPCUIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC40x_INPUT_INT];
 irqs[PPCUIC_OUTPUT_CINT] = ((qemu_irq 
*)env->irq_inputs)[PPC40x_INPUT_CINT];
 pic = ppcuic_init(env, irqs, 0x0C0, 0, 1);
-- 
2.19.2




[Qemu-devel] [PULL 15/27] ppc/xive: introduce the XiveNotifier interface

2018-12-12 Thread David Gibson
From: Cédric Le Goater 

The XiveNotifier offers a simple interface, between the XiveSource
object and the main interrupt controller of the machine. It will
forward event notifications to the XIVE Interrupt Virtualization
Routing Engine (IVRE).

Signed-off-by: Cédric Le Goater 
[dwg: Adjust type name string for XiveNotifier]
Signed-off-by: David Gibson 
---
 hw/intc/xive.c| 25 +
 include/hw/ppc/xive.h | 23 +++
 2 files changed, 48 insertions(+)

diff --git a/hw/intc/xive.c b/hw/intc/xive.c
index 11c7aac962..79238eb57f 100644
--- a/hw/intc/xive.c
+++ b/hw/intc/xive.c
@@ -155,7 +155,11 @@ static bool xive_source_esb_eoi(XiveSource *xsrc, uint32_t 
srcno)
  */
 static void xive_source_notify(XiveSource *xsrc, int srcno)
 {
+XiveNotifierClass *xnc = XIVE_NOTIFIER_GET_CLASS(xsrc->xive);
 
+if (xnc->notify) {
+xnc->notify(xsrc->xive, srcno);
+}
 }
 
 /*
@@ -362,6 +366,17 @@ static void xive_source_reset(void *dev)
 static void xive_source_realize(DeviceState *dev, Error **errp)
 {
 XiveSource *xsrc = XIVE_SOURCE(dev);
+Object *obj;
+Error *local_err = NULL;
+
+obj = object_property_get_link(OBJECT(dev), "xive", _err);
+if (!obj) {
+error_propagate(errp, local_err);
+error_prepend(errp, "required link 'xive' not found: ");
+return;
+}
+
+xsrc->xive = XIVE_NOTIFIER(obj);
 
 if (!xsrc->nr_irqs) {
 error_setg(errp, "Number of interrupt needs to be greater than 0");
@@ -428,9 +443,19 @@ static const TypeInfo xive_source_info = {
 .class_init= xive_source_class_init,
 };
 
+/*
+ * XIVE Fabric
+ */
+static const TypeInfo xive_fabric_info = {
+.name = TYPE_XIVE_NOTIFIER,
+.parent = TYPE_INTERFACE,
+.class_size = sizeof(XiveNotifierClass),
+};
+
 static void xive_register_types(void)
 {
 type_register_static(_source_info);
+type_register_static(_fabric_info);
 }
 
 type_init(xive_register_types)
diff --git a/include/hw/ppc/xive.h b/include/hw/ppc/xive.h
index 7cebc32eba..436f1bf756 100644
--- a/include/hw/ppc/xive.h
+++ b/include/hw/ppc/xive.h
@@ -142,6 +142,27 @@
 
 #include "hw/qdev-core.h"
 
+/*
+ * XIVE Fabric (Interface between Source and Router)
+ */
+
+typedef struct XiveNotifier {
+Object parent;
+} XiveNotifier;
+
+#define TYPE_XIVE_NOTIFIER "xive-notifier"
+#define XIVE_NOTIFIER(obj) \
+OBJECT_CHECK(XiveNotifier, (obj), TYPE_XIVE_NOTIFIER)
+#define XIVE_NOTIFIER_CLASS(klass) \
+OBJECT_CLASS_CHECK(XiveNotifierClass, (klass), TYPE_XIVE_NOTIFIER)
+#define XIVE_NOTIFIER_GET_CLASS(obj)   \
+OBJECT_GET_CLASS(XiveNotifierClass, (obj), TYPE_XIVE_NOTIFIER)
+
+typedef struct XiveNotifierClass {
+InterfaceClass parent;
+void (*notify)(XiveNotifier *xn, uint32_t lisn);
+} XiveNotifierClass;
+
 /*
  * XIVE Interrupt Source
  */
@@ -171,6 +192,8 @@ typedef struct XiveSource {
 uint64_tesb_flags;
 uint32_tesb_shift;
 MemoryRegionesb_mmio;
+
+XiveNotifier*xive;
 } XiveSource;
 
 /*
-- 
2.19.2




  1   2   3   4   5   6   >