Re: [PATCH v2 05/21] hw/arm/musicpal.c: Switch to transaction-based ptimer API

2019-10-08 Thread Richard Henderson
On 10/8/19 1:17 PM, Peter Maydell wrote:
> Switch the musicpal code away from bottom-half based ptimers to
> the new transaction-based ptimer API.  This just requires adding
> begin/commit calls around the various places that modify the ptimer
> state, and using the new ptimer_init() function to create the timer.
> 
> Signed-off-by: Peter Maydell 
> ---

Reviewed-by: Richard Henderson 

r~



Re: [PATCH v2 04/21] hw/timer/arm_timer.c: Switch to transaction-based ptimer API

2019-10-08 Thread Richard Henderson
On 10/8/19 1:17 PM, Peter Maydell wrote:
> Switch the arm_timer.c code away from bottom-half based ptimers
> to the new transaction-based ptimer API. This just requires
> adding begin/commit calls around the various arms of
> arm_timer_write() that modify the ptimer state, and using the
> new ptimer_init() function to create the timer.
> 
> Fixes: https://bugs.launchpad.net/qemu/+bug/177
> Signed-off-by: Peter Maydell 
> ---
>  hw/timer/arm_timer.c | 16 +++-
>  1 file changed, 11 insertions(+), 5 deletions(-)

Reviewed-by: Richard Henderson 

r~



Re: [PATCH v2 03/21] tests/ptimer-test: Switch to transaction-based ptimer API

2019-10-08 Thread Richard Henderson
On 10/8/19 1:17 PM, Peter Maydell wrote:
> Convert the ptimer test cases to the transaction-based ptimer API,
> by changing to ptimer_init(), dropping the now-unused QEMUBH
> variables, and surrounding each set of changes to the ptimer
> state in ptimer_transaction_begin/commit calls.
> 
> Signed-off-by: Peter Maydell 
> ---

Reviewed-by: Richard Henderson 

r~



Re: [PATCH v2 02/21] ptimer: Provide new transaction-based API

2019-10-08 Thread Richard Henderson
On 10/8/19 1:17 PM, Peter Maydell wrote:
> Provide the new transaction-based API. If a ptimer is created
> using ptimer_init() rather than ptimer_init_with_bh(), then
> instead of providing a QEMUBH, it provides a pointer to the
> callback function directly, and has opted into the transaction
> API. All calls to functions which modify ptimer state:
>  - ptimer_set_period()
>  - ptimer_set_freq()
>  - ptimer_set_limit()
>  - ptimer_set_count()
>  - ptimer_run()
>  - ptimer_stop()
> must be between matched calls to ptimer_transaction_begin()
> and ptimer_transaction_commit(). When ptimer_transaction_commit()
> is called it will evaluate the state of the timer after all the
> changes in the transaction, and call the callback if necessary.
> 
> In the old API the individual update functions generally would
> call ptimer_trigger() immediately, which would schedule the QEMUBH.
> In the new API the update functions will instead defer the
> "set s->next_event and call ptimer_reload()" work to
> ptimer_transaction_commit().
> 
> Because ptimer_trigger() can now immediately call into the
> device code which may then call other ptimer functions that
> update ptimer_state fields, we must be more careful in
> ptimer_reload() not to cache fields from ptimer_state across
> the ptimer_trigger() call. (This was harmless with the QEMUBH
> mechanism as the BH would not be invoked until much later.)
> 
> We use assertions to check that:
>  * the functions modifying ptimer state are not called outside
>a transaction block
>  * ptimer_transaction_begin() and _commit() calls are paired
>  * the transaction API is not used with a QEMUBH ptimer
> 
> There is some slight repetition of code:
>  * most of the set functions have similar looking "if s->bh
>call ptimer_reload, otherwise set s->need_reload" code
>  * ptimer_init() and ptimer_init_with_bh() have similar code
> We deliberately don't try to avoid this repetition, because
> it will all be deleted when the QEMUBH version of the API
> is removed.
> 
> Signed-off-by: Peter Maydell 
> ---

Reviewed-by: Richard Henderson 

r~



Re: [PATCH 3/3] migration/postcopy: replace have_listen_thread check with PostcopyState check

2019-10-08 Thread Wei Yang
On Tue, Oct 08, 2019 at 08:15:51PM +0100, Dr. David Alan Gilbert wrote:
>* Wei Yang (richardw.y...@linux.intel.com) wrote:
>> After previous cleanup, postcopy thread is running only when
>> PostcopyState is LISTENNING or RUNNING. This means it is not necessary
>> to spare a variable have_listen_thread to represent the state.
>> 
>> Replace the check on have_listen_thread with PostcopyState and remove
>> the variable.
>> 
>> Signed-off-by: Wei Yang 
>> ---
>>  migration/migration.h | 1 -
>>  migration/ram.c   | 2 +-
>>  migration/ram.h   | 1 +
>>  migration/savevm.c| 4 +---
>>  4 files changed, 3 insertions(+), 5 deletions(-)
>> 
>> diff --git a/migration/migration.h b/migration/migration.h
>> index 4f2fe193dc..a4d639663d 100644
>> --- a/migration/migration.h
>> +++ b/migration/migration.h
>> @@ -63,7 +63,6 @@ struct MigrationIncomingState {
>>  /* Set this when we want the fault thread to quit */
>>  bool   fault_thread_quit;
>>  
>> -bool   have_listen_thread;
>>  QemuThread listen_thread;
>>  QemuSemaphore  listen_thread_sem;
>>  
>> diff --git a/migration/ram.c b/migration/ram.c
>> index 769d3f6454..dfc50d57d5 100644
>> --- a/migration/ram.c
>> +++ b/migration/ram.c
>> @@ -4188,7 +4188,7 @@ static bool postcopy_is_advised(void)
>>  return ps >= POSTCOPY_INCOMING_ADVISE && ps < POSTCOPY_INCOMING_END;
>>  }
>>  
>> -static bool postcopy_is_running(void)
>> +bool postcopy_is_running(void)
>>  {
>>  PostcopyState ps = postcopy_state_get();
>>  return ps >= POSTCOPY_INCOMING_LISTENING && ps < POSTCOPY_INCOMING_END;
>> diff --git a/migration/ram.h b/migration/ram.h
>> index bd0eee79b6..44fe4753ad 100644
>> --- a/migration/ram.h
>> +++ b/migration/ram.h
>> @@ -59,6 +59,7 @@ int ram_postcopy_send_discard_bitmap(MigrationState *ms);
>>  /* For incoming postcopy discard */
>>  int ram_discard_range(const char *block_name, uint64_t start, size_t 
>> length);
>>  int ram_postcopy_incoming_init(MigrationIncomingState *mis);
>> +bool postcopy_is_running(void);
>>  
>>  void ram_handle_compressed(void *host, uint8_t ch, uint64_t size);
>>  
>> diff --git a/migration/savevm.c b/migration/savevm.c
>> index dcad8897a3..2a0e0b94df 100644
>> --- a/migration/savevm.c
>> +++ b/migration/savevm.c
>> @@ -1836,7 +1836,6 @@ static void *postcopy_ram_listen_thread(void *opaque)
>>  qemu_loadvm_state_cleanup();
>>  
>>  rcu_unregister_thread();
>> -mis->have_listen_thread = false;
>>  postcopy_state_set(POSTCOPY_INCOMING_END, NULL);
>
>That now needs a big comment saying it must be the last thing in the
>thread, because now it's got meaning that it's here.
>
>>  
>>  return NULL;
>> @@ -1880,7 +1879,6 @@ static int 
>> loadvm_postcopy_handle_listen(MigrationIncomingState *mis)
>>  return -1;
>>  }
>>  
>> -mis->have_listen_thread = true;
>>  /* Start up the listening thread and wait for it to signal ready */
>>  qemu_sem_init(>listen_thread_sem, 0);
>>  qemu_thread_create(>listen_thread, "postcopy/listen",
>> @@ -2518,7 +2516,7 @@ int qemu_loadvm_state(QEMUFile *f)
>>  
>>  trace_qemu_loadvm_state_post_main(ret);
>>  
>> -if (mis->have_listen_thread) {
>> +if (postcopy_is_running()) {
>>  /* Listen thread still going, can't clean up yet */
>>  return ret;
>>  }
>
>Can you explain to me why this is afe in the case of a failure in
>loadvm_postcopy_handle_listen between the start where it sets
>the state to LISTENING, and the point where it currently sets
>hasve_listen_thread ?  Wouldn't this cause qemu_loadvm_state
>not to cleanup?
>

I have to say you are right.  listen_thread may not started when PostcopyState
is already set to LISTENING.

The ugly fix may be set PostcopyState back to original one. Not sure whether
you would like this. 

>Dave
>
>> -- 
>> 2.17.1
>> 
>--
>Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK

-- 
Wei Yang
Help you, Help me



Re: [PATCH v1 1/1] target/riscv: Remove atomic accesses to MIP CSR

2019-10-08 Thread Richard Henderson
On 10/8/19 6:04 PM, Alistair Francis wrote:
> Instead of relying on atomics to access the MIP register let's update
> our helper function to instead just lock the IO mutex thread before
> writing. This follows the same concept as used in PPC for handling
> interrupts
> 
> Signed-off-by: Alistair Francis 
> ---
>  target/riscv/cpu.c|  5 ++--
>  target/riscv/cpu.h|  9 
>  target/riscv/cpu_helper.c | 48 +++
>  target/riscv/csr.c|  2 +-
>  4 files changed, 21 insertions(+), 43 deletions(-)

Reviewed-by: Richard Henderson 

r~



Re: [PATCH 02/19] hw/arm/bcm2835_peripherals: Improve logging

2019-10-08 Thread Cleber Rosa
On Tue, Oct 08, 2019 at 10:00:57AM +0100, Alex Bennée wrote:
> 
> Philippe Mathieu-Daudé  writes:
> 
> > Various logging improvements as once:
> > - Use 0x prefix for hex numbers
> 
> You can use "%#"PRIxNN"" as an alternative I believe but anyway:
>

Unless the value given to the formatting string is zero, then the "0x"
prefix is not applied to the resulting string.

> Reviewed-by: Alex Bennée 

Reviewed-by: Cleber Rosa 



Re: [PATCH 2/3] ppc: rs6000_mc: drop usage of memory_region_allocate_system_memory()

2019-10-08 Thread David Gibson
On Tue, Oct 08, 2019 at 07:33:17AM -0400, Igor Mammedov wrote:
> rs6000mc_realize() violates memory_region_allocate_system_memory() contract
> by calling it multiple times which could break -mem-path. Replace it with
> plain memory_region_init_ram() instead.
> 
> Signed-off-by: Igor Mammedov 

Acked-by: David Gibson 

Or would you like me to merge this through my tree?

-- 
David Gibson| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson


signature.asc
Description: PGP signature


Re: [PATCH 1/4] migration/ram: only possible bit set in invalid_flags is RAM_SAVE_FLAG_COMPRESS_PAGE

2019-10-08 Thread Wei Yang
On Tue, Oct 08, 2019 at 06:38:25PM +0100, Dr. David Alan Gilbert wrote:
>* Wei Yang (richardw.y...@linux.intel.com) wrote:
>> The only possible bit set in invalid_flags is
>> RAM_SAVE_FLAG_COMPRESS_PAGE at the beginning of function
>> ram_load_precopy(), which means it is not necessary to do
>> another check for RAM_SAVE_FLAG_COMPRESS_PAGE bit.
>> 
>> Signed-off-by: Wei Yang 
>> ---
>>  migration/ram.c | 5 +
>>  1 file changed, 1 insertion(+), 4 deletions(-)
>> 
>> diff --git a/migration/ram.c b/migration/ram.c
>> index 31051935c8..769d3f6454 100644
>> --- a/migration/ram.c
>> +++ b/migration/ram.c
>> @@ -4263,10 +4263,7 @@ static int ram_load_precopy(QEMUFile *f)
>>  addr &= TARGET_PAGE_MASK;
>>  
>>  if (flags & invalid_flags) {
>> -if (flags & invalid_flags & RAM_SAVE_FLAG_COMPRESS_PAGE) {
>> -error_report("Received an unexpected compressed page");
>> -}
>> -
>> +error_report("Received an unexpected compressed page");
>>  ret = -EINVAL;
>
>I'd rather keep this one; I think Juan's idea is that we might make
>other flags illegal here and then it's easy to add to invalid_flags at
>the top.
>

Reasonable.

>Dave
>>  break;
>>  }
>> -- 
>> 2.17.1
>> 
>--
>Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK

-- 
Wei Yang
Help you, Help me



Re: [PATCH 2/2] migration/postcopy: map large zero page in postcopy_ram_incoming_setup()

2019-10-08 Thread Wei Yang
On Tue, Oct 08, 2019 at 06:24:23PM +0100, Dr. David Alan Gilbert wrote:
>* Wei Yang (richardw.y...@linux.intel.com) wrote:
>> postcopy_ram_incoming_setup() and postcopy_ram_incoming_cleanup() are
>> counterpart. It is reasonable to map/unmap large zero page in these two
>> functions respectively.
>> 
>> Signed-off-by: Wei Yang 
>
>Yes, OK.
>
>> ---
>>  migration/postcopy-ram.c | 34 +-
>>  1 file changed, 17 insertions(+), 17 deletions(-)
>> 
>> diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c
>> index e554f93eec..813cfa5c42 100644
>> --- a/migration/postcopy-ram.c
>> +++ b/migration/postcopy-ram.c
>> @@ -1142,6 +1142,22 @@ int 
>> postcopy_ram_incoming_setup(MigrationIncomingState *mis)
>>  return -1;
>>  }
>>  
>> +/*
>> + * Map large zero page when kernel can't use UFFDIO_ZEROPAGE for 
>> hugepages
>> + */
>> +mis->postcopy_tmp_zero_page = mmap(NULL, mis->largest_page_size,
>> +   PROT_READ | PROT_WRITE,
>> +   MAP_PRIVATE | MAP_ANONYMOUS,
>> +   -1, 0);
>> +if (mis->postcopy_tmp_zero_page == MAP_FAILED) {
>> +int e = errno;
>> +mis->postcopy_tmp_zero_page = NULL;
>> +error_report("%s: Failed to map large zero page %s",
>> + __func__, strerror(e));
>> +return -e;
>
>Note this starts returning -errno where the rest of this function
>returns 0 or -1;  returning -errno is a good thing I think and it might
>be good to change the other returns.
>

This is reasonable, while I am thinking how caller would handle this.

For example, the return value would be finally returned to
qemu_loadvm_state_main(). If we handle each errno respectively in this
function, the code would be difficult to read and maintain.

Would it be good to classify return value to different category? Like

  POSTCOPY_FATAL
  POSTCOPY_RETRY
  POSTCOPY_DISABLE

>
>Reviewed-by: Dr. David Alan Gilbert 
>
>> +}
>> +memset(mis->postcopy_tmp_zero_page, '\0', mis->largest_page_size);
>> +
>>  /*
>>   * Ballooning can mark pages as absent while we're postcopying
>>   * that would cause false userfaults.
>> @@ -1248,23 +1264,7 @@ int postcopy_place_page_zero(MigrationIncomingState 
>> *mis, void *host,
>> qemu_ram_block_host_offset(rb,
>>
>> host));
>>  } else {
>> -/* The kernel can't use UFFDIO_ZEROPAGE for hugepages */
>> -if (!mis->postcopy_tmp_zero_page) {
>> -mis->postcopy_tmp_zero_page = mmap(NULL, mis->largest_page_size,
>> -   PROT_READ | PROT_WRITE,
>> -   MAP_PRIVATE | MAP_ANONYMOUS,
>> -   -1, 0);
>> -if (mis->postcopy_tmp_zero_page == MAP_FAILED) {
>> -int e = errno;
>> -mis->postcopy_tmp_zero_page = NULL;
>> -error_report("%s: %s mapping large zero page",
>> - __func__, strerror(e));
>> -return -e;
>> -}
>> -memset(mis->postcopy_tmp_zero_page, '\0', 
>> mis->largest_page_size);
>> -}
>> -return postcopy_place_page(mis, host, mis->postcopy_tmp_zero_page,
>> -   rb);
>> +return postcopy_place_page(mis, host, mis->postcopy_tmp_zero_page, 
>> rb);
>>  }
>>  }
>>  
>> -- 
>> 2.17.1
>> 
>--
>Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK

-- 
Wei Yang
Help you, Help me



Re: [PATCH v2 3/8] hw/ide/piix: Convert reset handler to DeviceReset

2019-10-08 Thread Li Qiang
Philippe Mathieu-Daudé  于2019年10月8日周二 下午10:32写道:

> The PIIX3/IDE is a PCI device within the PIIX3 chipset, it will be reset
> when the PCI bus it stands on is reset.
>
> Convert its reset handler into a proper Device reset method.
>
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
>  hw/ide/piix.c | 8 +++-
>  1 file changed, 3 insertions(+), 5 deletions(-)
>
> diff --git a/hw/ide/piix.c b/hw/ide/piix.c
> index fba6bc8bff..18b2c3b722 100644
> --- a/hw/ide/piix.c
> +++ b/hw/ide/piix.c
> @@ -30,7 +30,6 @@
>  #include "sysemu/block-backend.h"
>  #include "sysemu/blockdev.h"
>  #include "sysemu/dma.h"
> -#include "sysemu/reset.h"
>
>  #include "hw/ide/pci.h"
>  #include "trace.h"
> @@ -103,9 +102,9 @@ static void bmdma_setup_bar(PCIIDEState *d)
>  }
>  }
>
> -static void piix3_reset(void *opaque)
> +static void piix3_ide_reset(DeviceState *dev)
>  {
> -PCIIDEState *d = opaque;
> +PCIIDEState *d = PCI_IDE(dev);
>  PCIDevice *pd = PCI_DEVICE(d);
>  uint8_t *pci_conf = pd->config;
>  int i;
> @@ -154,8 +153,6 @@ static void pci_piix_ide_realize(PCIDevice *dev, Error
> **errp)
>
>  pci_conf[PCI_CLASS_PROG] = 0x80; // legacy ATA mode
>
> -qemu_register_reset(piix3_reset, d);
> -
>  bmdma_setup_bar(d);
>  pci_register_bar(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, >bmdma_bar);
>
> @@ -247,6 +244,7 @@ static void piix3_ide_class_init(ObjectClass *klass,
> void *data)
>  DeviceClass *dc = DEVICE_CLASS(klass);
>  PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
>
> +dc->reset = piix3_ide_reset;
>  k->realize = pci_piix_ide_realize;
>  k->exit = pci_piix_ide_exitfn;
>  k->vendor_id = PCI_VENDOR_ID_INTEL;
> --
>


Shouldn't we also add the reset callback for piix4 ide device?

Thanks,
Li Qiang



> 2.21.0
>
>
>


Re: [PATCH v5 0/2] x86: Enable user wait instructions

2019-10-08 Thread Tao Xu

Ping for comments :)

On 9/29/2019 9:57 AM, Xu, Tao3 wrote:

UMONITOR, UMWAIT and TPAUSE are a set of user wait instructions.

UMONITOR arms address monitoring hardware using an address. A store
to an address within the specified address range triggers the
monitoring hardware to wake up the processor waiting in umwait.

UMWAIT instructs the processor to enter an implementation-dependent
optimized state while monitoring a range of addresses. The optimized
state may be either a light-weight power/performance optimized state
(c0.1 state) or an improved power/performance optimized state
(c0.2 state).

TPAUSE instructs the processor to enter an implementation-dependent
optimized state c0.1 or c0.2 state and wake up when time-stamp counter
reaches specified timeout.

Availability of the user wait instructions is indicated by the presence
of the CPUID feature flag WAITPKG CPUID.0x07.0x0:ECX[5].

The patches enable the umonitor, umwait and tpause features in KVM.
Because umwait and tpause can put a (psysical) CPU into a power saving
state, by default we dont't expose it in kvm and provide a capability to
enable it. Use kvm capability to enable UMONITOR, UMWAIT and TPAUSE when
QEMU use "-overcommit cpu-pm=on, a VM can use UMONITOR, UMWAIT and TPAUSE
instructions. If the instruction causes a delay, the amount of time
delayed is called here the physical delay. The physical delay is first
computed by determining the virtual delay (the time to delay relative to
the VM’s timestamp counter). Otherwise, UMONITOR, UMWAIT and TPAUSE cause
an invalid-opcode exception(#UD).

The release document ref below link:
https://software.intel.com/sites/default/files/\
managed/39/c5/325462-sdm-vol-1-2abcd-3abcd.pdf

Changelog:
v5:
Remove CPUID_7_0_ECX_WAITPKG if enable_cpu_pm is not set. (Paolo)
v4:
Set IA32_UMWAIT_CONTROL 32bits
v3:
Simplify the patches, expose user wait instructions when the guest
has CPUID (Paolo)
v2:
Separated from the series
https://www.mail-archive.com/qemu-devel@nongnu.org/msg549526.html
Use kvm capability to enable UMONITOR, UMWAIT and TPAUSE when
QEMU use "-overcommit cpu-pm=on"  
v1:
Sent out with MOVDIRI/MOVDIR64B instructions patches

Tao Xu (2):
   x86/cpu: Add support for UMONITOR/UMWAIT/TPAUSE
   target/i386: Add support for save/load IA32_UMWAIT_CONTROL MSR

  target/i386/cpu.c |  3 ++-
  target/i386/cpu.h |  3 +++
  target/i386/kvm.c | 19 +++
  target/i386/machine.c | 20 
  4 files changed, 44 insertions(+), 1 deletion(-)






Re: [PATCH v2 2/8] hw/isa/piix4: Convert reset handler to DeviceReset

2019-10-08 Thread Li Qiang
Philippe Mathieu-Daudé  于2019年10月8日周二 下午10:49写道:

> The PIIX4/ISA is a PCI device within the PIIX4 chipset, it will be reset
> when the PCI bus it stands on is reset.
>
> Convert its reset handler into a proper Device reset method.
>
> Signed-off-by: Philippe Mathieu-Daudé 
>

Reviewed-by: Li Qiang 



> ---
>  hw/isa/piix4.c | 7 +++
>  1 file changed, 3 insertions(+), 4 deletions(-)
>
> diff --git a/hw/isa/piix4.c b/hw/isa/piix4.c
> index 3294056cd5..890d999abf 100644
> --- a/hw/isa/piix4.c
> +++ b/hw/isa/piix4.c
> @@ -28,7 +28,6 @@
>  #include "hw/isa/isa.h"
>  #include "hw/sysbus.h"
>  #include "migration/vmstate.h"
> -#include "sysemu/reset.h"
>
>  PCIDevice *piix4_dev;
>
> @@ -40,9 +39,9 @@ typedef struct PIIX4State {
>  #define PIIX4_PCI_DEVICE(obj) \
>  OBJECT_CHECK(PIIX4State, (obj), TYPE_PIIX4_PCI_DEVICE)
>
> -static void piix4_reset(void *opaque)
> +static void piix4_isa_reset(DeviceState *dev)
>  {
> -PIIX4State *d = opaque;
> +PIIX4State *d = PIIX4_PCI_DEVICE(dev);
>  uint8_t *pci_conf = d->dev.config;
>
>  pci_conf[0x04] = 0x07; // master, memory and I/O
> @@ -97,7 +96,6 @@ static void piix4_realize(PCIDevice *dev, Error **errp)
>  return;
>  }
>  piix4_dev = >dev;
> -qemu_register_reset(piix4_reset, d);
>  }
>
>  int piix4_init(PCIBus *bus, ISABus **isa_bus, int devfn)
> @@ -118,6 +116,7 @@ static void piix4_class_init(ObjectClass *klass, void
> *data)
>  k->vendor_id = PCI_VENDOR_ID_INTEL;
>  k->device_id = PCI_DEVICE_ID_INTEL_82371AB_0;
>  k->class_id = PCI_CLASS_BRIDGE_ISA;
> +dc->reset = piix4_isa_reset;
>  dc->desc = "ISA bridge";
>  dc->vmsd = _piix4;
>  /*
> --
> 2.21.0
>
>
>


Re: [PATCH 3/3] migration/postcopy: handle POSTCOPY_INCOMING_RUNNING corner case properly

2019-10-08 Thread Wei Yang
On Tue, Oct 08, 2019 at 05:40:46PM +0100, Dr. David Alan Gilbert wrote:
>* Wei Yang (richardw.y...@linux.intel.com) wrote:
>> Currently, we set PostcopyState blindly to RUNNING, even we found the
>> previous state is not LISTENING. This will lead to a corner case.
>> 
>> First let's look at the code flow:
>> 
>> qemu_loadvm_state_main()
>> ret = loadvm_process_command()
>> loadvm_postcopy_handle_run()
>> return -1;
>> if (ret < 0) {
>> if (postcopy_state_get() == POSTCOPY_INCOMING_RUNNING)
>> ...
>> }
>> 
>> From above snippet, the corner case is loadvm_postcopy_handle_run()
>> always sets state to RUNNING. And then it checks the previous state. If
>> the previous state is not LISTENING, it will return -1. But at this
>> moment, PostcopyState is already been set to RUNNING.
>> 
>> Then ret is checked in qemu_loadvm_state_main(), when it is -1
>> PostcopyState is checked. Current logic would pause postcopy and retry
>> if PostcopyState is RUNNING. This is not what we expect, because
>> postcopy is not active yet.
>> 
>> This patch makes sure state is set to RUNNING only previous state is
>> LISTENING by introducing an old_state parameter in postcopy_state_set().
>> New state only would be set when current state equals to old_state.
>> 
>> Signed-off-by: Wei Yang 
>
>OK, it's a shame to use a pointer there, but it works.

You mean second parameter of postcopy_state_set()?

I don't have a better idea. Or we introduce a new state
POSTCOPY_INCOMING_NOCHECK. Do you feel better with this?

>Note, something else; using '-1' as the return value and checking for it
>is something we do a lot; but in this case it's an example of an error
>we could never recover from so it never makes sense to try and recover.
>We should probably look at different types of error.
>
>
>Reviewed-by: Dr. David Alan Gilbert 
>
>Dave
>
>> ---
>>  migration/migration.c|  2 +-
>>  migration/postcopy-ram.c | 13 +
>>  migration/postcopy-ram.h |  3 ++-
>>  migration/savevm.c   | 11 ++-
>>  4 files changed, 18 insertions(+), 11 deletions(-)
>> 
>> diff --git a/migration/migration.c b/migration/migration.c
>> index 34d5e66f06..369cf3826e 100644
>> --- a/migration/migration.c
>> +++ b/migration/migration.c
>> @@ -447,7 +447,7 @@ static void process_incoming_migration_co(void *opaque)
>>  assert(mis->from_src_file);
>>  mis->migration_incoming_co = qemu_coroutine_self();
>>  mis->largest_page_size = qemu_ram_pagesize_largest();
>> -postcopy_state_set(POSTCOPY_INCOMING_NONE);
>> +postcopy_state_set(POSTCOPY_INCOMING_NONE, NULL);
>>  migrate_set_state(>state, MIGRATION_STATUS_NONE,
>>MIGRATION_STATUS_ACTIVE);
>>  ret = qemu_loadvm_state(mis->from_src_file);
>> diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c
>> index b24c4a10c2..8f741d636d 100644
>> --- a/migration/postcopy-ram.c
>> +++ b/migration/postcopy-ram.c
>> @@ -577,7 +577,7 @@ int postcopy_ram_incoming_cleanup(MigrationIncomingState 
>> *mis)
>>  }
>>  }
>>  
>> -postcopy_state_set(POSTCOPY_INCOMING_END);
>> +postcopy_state_set(POSTCOPY_INCOMING_END, NULL);
>>  
>>  if (mis->postcopy_tmp_page) {
>>  munmap(mis->postcopy_tmp_page, mis->largest_page_size);
>> @@ -626,7 +626,7 @@ int postcopy_ram_prepare_discard(MigrationIncomingState 
>> *mis)
>>  return -1;
>>  }
>>  
>> -postcopy_state_set(POSTCOPY_INCOMING_DISCARD);
>> +postcopy_state_set(POSTCOPY_INCOMING_DISCARD, NULL);
>>  
>>  return 0;
>>  }
>> @@ -1457,9 +1457,14 @@ PostcopyState  postcopy_state_get(void)
>>  }
>>  
>>  /* Set the state and return the old state */
>> -PostcopyState postcopy_state_set(PostcopyState new_state)
>> +PostcopyState postcopy_state_set(PostcopyState new_state,
>> + const PostcopyState *old_state)
>>  {
>> -return atomic_xchg(_postcopy_state, new_state);
>> +if (!old_state) {
>> +return atomic_xchg(_postcopy_state, new_state);
>> +} else {
>> +return atomic_cmpxchg(_postcopy_state, *old_state, 
>> new_state);
>> +}
>>  }
>>  
>>  /* Register a handler for external shared memory postcopy
>> diff --git a/migration/postcopy-ram.h b/migration/postcopy-ram.h
>> index d2668cc820..e3dde32155 100644
>> --- a/migration/postcopy-ram.h
>> +++ b/migration/postcopy-ram.h
>> @@ -109,7 +109,8 @@ void *postcopy_get_tmp_page(MigrationIncomingState *mis);
>>  
>>  PostcopyState postcopy_state_get(void);
>>  /* Set the state and return the old state */
>> -PostcopyState postcopy_state_set(PostcopyState new_state);
>> +PostcopyState postcopy_state_set(PostcopyState new_state,
>> + const PostcopyState *old_state);
>>  
>>  void postcopy_fault_thread_notify(MigrationIncomingState *mis);
>>  
>> diff --git a/migration/savevm.c b/migration/savevm.c
>> index f3292eb003..45474d9c95 100644
>> --- a/migration/savevm.c
>> +++ 

Re: [PATCH v2 1/8] hw/acpi/piix4: Convert reset handler to DeviceReset

2019-10-08 Thread Li Qiang
Philippe Mathieu-Daudé  于2019年10月8日周二 下午10:28写道:

> The PIIX4/PM is a PCI device within the PIIX4 chipset, it will be reset
> when the PCI bus it stands on is reset.
>
> Convert its reset handler into a proper Device reset method.
>
> Reviewed-by: Igor Mammedov 
> Signed-off-by: Philippe Mathieu-Daudé 
>


Reviewed-by: Li Qiang 


> ---
>  hw/acpi/piix4.c | 7 +++
>  1 file changed, 3 insertions(+), 4 deletions(-)
>
> diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
> index 5742c3df87..4e079b39bd 100644
> --- a/hw/acpi/piix4.c
> +++ b/hw/acpi/piix4.c
> @@ -27,7 +27,6 @@
>  #include "hw/pci/pci.h"
>  #include "hw/qdev-properties.h"
>  #include "hw/acpi/acpi.h"
> -#include "sysemu/reset.h"
>  #include "sysemu/runstate.h"
>  #include "sysemu/sysemu.h"
>  #include "qapi/error.h"
> @@ -344,9 +343,9 @@ static const VMStateDescription vmstate_acpi = {
>  }
>  };
>
> -static void piix4_reset(void *opaque)
> +static void piix4_pm_reset(DeviceState *dev)
>  {
> -PIIX4PMState *s = opaque;
> +PIIX4PMState *s = PIIX4_PM(dev);
>  PCIDevice *d = PCI_DEVICE(s);
>  uint8_t *pci_conf = d->config;
>
> @@ -542,7 +541,6 @@ static void piix4_pm_realize(PCIDevice *dev, Error
> **errp)
>
>  s->machine_ready.notify = piix4_pm_machine_ready;
>  qemu_add_machine_init_done_notifier(>machine_ready);
> -qemu_register_reset(piix4_reset, s);
>
>  piix4_acpi_system_hot_add_init(pci_address_space_io(dev),
> pci_get_bus(dev), s);
> @@ -692,6 +690,7 @@ static void piix4_pm_class_init(ObjectClass *klass,
> void *data)
>  k->device_id = PCI_DEVICE_ID_INTEL_82371AB_3;
>  k->revision = 0x03;
>  k->class_id = PCI_CLASS_BRIDGE_OTHER;
> +dc->reset = piix4_pm_reset;
>  dc->desc = "PM";
>  dc->vmsd = _acpi;
>  dc->props = piix4_pm_properties;
> --
> 2.21.0
>
>
>


Re: [PATCH 2/3] migration/postcopy: not necessary to do postcopy_ram_incoming_cleanup when state is ADVISE

2019-10-08 Thread Wei Yang
On Tue, Oct 08, 2019 at 05:02:02PM +0100, Dr. David Alan Gilbert wrote:
>* Wei Yang (richardw.y...@linux.intel.com) wrote:
>> postcopy_ram_incoming_cleanup() does cleanup for
>> postcopy_ram_incoming_setup(), while the setup happens only after
>> migration enters LISTEN state.
>> 
>> This means there is nothing to cleanup when migration is still ADVISE
>> state.
>> 
>> Signed-off-by: Wei Yang 
>> ---
>>  migration/migration.c | 1 -
>>  1 file changed, 1 deletion(-)
>> 
>> diff --git a/migration/migration.c b/migration/migration.c
>> index 5f7e4d15e9..34d5e66f06 100644
>> --- a/migration/migration.c
>> +++ b/migration/migration.c
>> @@ -461,7 +461,6 @@ static void process_incoming_migration_co(void *opaque)
>>   * but managed to complete within the precopy period, we can use
>>   * the normal exit.
>>   */
>> -postcopy_ram_incoming_cleanup(mis);
>>  } else if (ret >= 0) {
>>  /*
>>   * Postcopy was started, cleanup should happen at the end of the
>
>I think that misses the cleanup of mlock that corresponds to the
>munlockall in postcopy_ram_supported_by_host - that's called very early
>on; I think in the advise stage.
>

Thanks you are right.

BTW, do we need to check enable_mlock when calling munlockall() in
postcopy_ram_supported_by_host() ?

>Dave
>
>> -- 
>> 2.17.1
>> 
>--
>Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK

-- 
Wei Yang
Help you, Help me



Re: [PATCH v2 7/7] tests/fw_cfg: Run the tests on big-endian targets

2019-10-08 Thread Li Qiang
Laszlo Ersek  于2019年10月9日周三 上午4:27写道:

> On 10/08/19 17:04, Li Qiang wrote:
> > Philippe Mathieu-Daudé  于2019年10月7日周一 下午11:20写道:
> >
> >> We have been restricting our fw_cfg tests to the PC machine,
> >> which is a little-endian architecture.
> >> The fw_cfg device is also used on the SPARC and PowerPC
> >> architectures, which can run in big-endian configuration.
> >>
> >> Since we want to be sure our device does not regress
> >> regardless the endianess used, enable this test one
> >> these targets.
> >>
> >> The NUMA selector is X86 specific, restrict it to this arch.
> >>
> >> Signed-off-by: Philippe Mathieu-Daudé 
> >> ---
> >> v2: test ppc32 too (lvivier)
> >> ---
> >>  tests/Makefile.include |  2 ++
> >>  tests/fw_cfg-test.c| 33 +++--
> >>  2 files changed, 29 insertions(+), 6 deletions(-)
> >>
> >> diff --git a/tests/Makefile.include b/tests/Makefile.include
> >> index 3543451ed3..4ae3d5140a 100644
> >> --- a/tests/Makefile.include
> >> +++ b/tests/Makefile.include
> >> @@ -226,6 +226,7 @@ check-qtest-ppc-y += tests/prom-env-test$(EXESUF)
> >>  check-qtest-ppc-y += tests/drive_del-test$(EXESUF)
> >>  check-qtest-ppc-y += tests/boot-serial-test$(EXESUF)
> >>  check-qtest-ppc-$(CONFIG_M48T59) += tests/m48t59-test$(EXESUF)
> >> +check-qtest-ppc-y += tests/fw_cfg-test$(EXESUF)
> >>
> >>  check-qtest-ppc64-y += $(check-qtest-ppc-y)
> >>  check-qtest-ppc64-$(CONFIG_PSERIES) += tests/device-plug-test$(EXESUF)
> >> @@ -250,6 +251,7 @@ check-qtest-sh4eb-$(CONFIG_ISA_TESTDEV) =
> >> tests/endianness-test$(EXESUF)
> >>  check-qtest-sparc-y += tests/prom-env-test$(EXESUF)
> >>  check-qtest-sparc-y += tests/m48t59-test$(EXESUF)
> >>  check-qtest-sparc-y += tests/boot-serial-test$(EXESUF)
> >> +check-qtest-sparc-y += tests/fw_cfg-test$(EXESUF)
> >>
> >>  check-qtest-sparc64-$(CONFIG_ISA_TESTDEV) =
> tests/endianness-test$(EXESUF)
> >>  check-qtest-sparc64-y += tests/prom-env-test$(EXESUF)
> >> diff --git a/tests/fw_cfg-test.c b/tests/fw_cfg-test.c
> >> index 35af0de7e6..1250e87097 100644
> >> --- a/tests/fw_cfg-test.c
> >> +++ b/tests/fw_cfg-test.c
> >> @@ -210,13 +210,30 @@ static void test_fw_cfg_splash_time(const void
> >> *opaque)
> >>
> >>  int main(int argc, char **argv)
> >>  {
> >> -QTestCtx ctx;
> >> -int ret;
> >> +const char *arch = qtest_get_arch();
> >> +bool has_numa = false;
> >> +QTestCtx ctx = {};
> >> +int ret = 0;
> >>
> >>  g_test_init(, , NULL);
> >>
> >> -ctx.machine_name = "pc";
> >> -ctx.fw_cfg = pc_fw_cfg_init();
> >> +if (g_str_equal(arch, "i386") || g_str_equal(arch, "x86_64")) {
> >> +has_numa = true;
> >> +ctx.machine_name = "pc";
> >> +ctx.fw_cfg = pc_fw_cfg_init();
> >> +} else if (g_str_equal(arch, "sparc")) {
> >> +ctx.machine_name = "SS-5";
> >> +ctx.fw_cfg = mm_fw_cfg_init(0xd0510ULL);
> >> +} else if (g_str_equal(arch, "ppc") || g_str_equal(arch, "ppc64"))
> {
> >> +/*
> >> + * The mac99 machine is different for 32/64-bit target:
> >> + *
> >> + * ppc(32): the G4 which can be either little or big endian,
> >> + * ppc64:   the G5 (970FX) is only big-endian.
> >> + */
> >> +ctx.machine_name = "mac99";
> >> +ctx.fw_cfg = mm_fw_cfg_init(0xf510);
> >> +}
> >>
> >>  qtest_add_data_func("fw_cfg/signature", ,
> test_fw_cfg_signature);
> >>  qtest_add_data_func("fw_cfg/id", , test_fw_cfg_id);
> >> @@ -231,14 +248,18 @@ int main(int argc, char **argv)
> >>  qtest_add_func("fw_cfg/boot_device", test_fw_cfg_boot_device);
> >>  #endif
> >>  qtest_add_data_func("fw_cfg/max_cpus", , test_fw_cfg_max_cpus);
> >> -qtest_add_data_func("fw_cfg/numa", , test_fw_cfg_numa);
> >>  qtest_add_data_func("fw_cfg/boot_menu", ,
> test_fw_cfg_boot_menu);
> >>  qtest_add_data_func("fw_cfg/reboot_timeout", ,
> >>  test_fw_cfg_reboot_timeout);
> >>  qtest_add_data_func("fw_cfg/splash_time", ,
> >> test_fw_cfg_splash_time);
> >>
> >> -ret = g_test_run();
> >> +if (has_numa) {
> >> +qtest_add_data_func("fw_cfg/numa", , test_fw_cfg_numa);
> >> +}
> >>
> >> +if (ctx.machine_name) {
> >> +ret = g_test_run();
> >> +}
> >>
> >
> > I think we can omit this if statement. In which case the ctx.machine_name
> > will be NULL?
>
> When "arch" differs from all of i386, x86_64, sparc, ppc, ppc64.
>

Yes, I just found the setting 'arch' lost 'else' branch.
Then in this case, I prefer 'just return'.  There is no need do other
things for non-support arch.
This is just like some other case, such as usb-hcd-ehci-test.c and
ahci-test.c.
Also, I don't find any conditional 'g_test_run' calling.

Thanks,
Li Qiang



>
> In that case, the original initializer will remain in effect, from:
>
>   QTestCtx ctx = {};
>
> (Admittedly, this is an ugly GNU-ism; for standard C, it should be
>
>   QTestCtx ctx = { 0 };
>
> but the GNU-ism is used quite 

Re: [PATCH 01/19] hw/arm/raspi: Use the IEC binary prefix definitions

2019-10-08 Thread Cleber Rosa
On Thu, Sep 26, 2019 at 07:34:09PM +0200, Philippe Mathieu-Daudé wrote:
> IEC binary prefixes ease code review: the unit is explicit.
> 
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
>  hw/arm/raspi.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
> index 74c062d05e..615d755879 100644
> --- a/hw/arm/raspi.c
> +++ b/hw/arm/raspi.c
> @@ -230,7 +230,7 @@ static void raspi2_machine_init(MachineClass *mc)
>  mc->max_cpus = BCM283X_NCPUS;
>  mc->min_cpus = BCM283X_NCPUS;
>  mc->default_cpus = BCM283X_NCPUS;
> -mc->default_ram_size = 1024 * 1024 * 1024;
> +mc->default_ram_size = 1 * GiB;
>  mc->ignore_memory_transaction_failures = true;
>  };
>  DEFINE_MACHINE("raspi2", raspi2_machine_init)
> @@ -252,7 +252,7 @@ static void raspi3_machine_init(MachineClass *mc)
>  mc->max_cpus = BCM283X_NCPUS;
>  mc->min_cpus = BCM283X_NCPUS;
>  mc->default_cpus = BCM283X_NCPUS;
> -mc->default_ram_size = 1024 * 1024 * 1024;
> +mc->default_ram_size = 1 * GiB;
>  }
>  DEFINE_MACHINE("raspi3", raspi3_machine_init)
>  #endif
> -- 
> 2.20.1
> 

Reviewed-by: Cleber Rosa 



[PATCH v3 7/7] riscv/virt: Jump to pflash if specified

2019-10-08 Thread Alistair Francis
If the user supplied pflash to QEMU then change the reset code to jump
to the pflash base address instead of the DRAM base address.

Signed-off-by: Alistair Francis 
Reviewed-by: Bin Meng 
Reviewed-by: Philippe Mathieu-Daudé 
Tested-by: Bin Meng 
---
 hw/riscv/virt.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index ad29e14d5f..a79d16d99a 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -445,6 +445,7 @@ static void riscv_virt_board_init(MachineState *machine)
 MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
 char *plic_hart_config;
 size_t plic_hart_config_len;
+target_ulong start_addr = memmap[VIRT_DRAM].base;
 int i;
 unsigned int smp_cpus = machine->smp.cpus;
 
@@ -491,6 +492,14 @@ static void riscv_virt_board_init(MachineState *machine)
 }
 }
 
+if (drive_get(IF_PFLASH, 0, 0)) {
+/*
+ * Pflash was supplied, let's overwrite the address we jump to after
+ * reset to the base of the flash.
+ */
+start_addr = virt_memmap[VIRT_FLASH].base;
+}
+
 /* reset vector */
 uint32_t reset_vec[8] = {
 0x0297,  /* 1:  auipc  t0, %pcrel_hi(dtb) */
@@ -503,7 +512,7 @@ static void riscv_virt_board_init(MachineState *machine)
 #endif
 0x00028067,  /* jr t0 */
 0x,
-memmap[VIRT_DRAM].base,  /* start: .dword memmap[VIRT_DRAM].base */
+start_addr,  /* start: .dword */
 0x,
  /* dtb: */
 };
-- 
2.23.0




[PATCH v3 6/7] riscv/virt: Add the PFlash CFI01 device

2019-10-08 Thread Alistair Francis
Add the CFI01 PFlash to the RISC-V virt board. This is the same PFlash
from the ARM Virt board and the implementation is based on the ARM Virt
board. This allows users to specify flash files from the command line.

Signed-off-by: Alistair Francis 
Reviewed-by: Bin Meng 
Tested-by: Bin Meng 
---
 hw/riscv/Kconfig|  1 +
 hw/riscv/virt.c | 86 +
 include/hw/riscv/virt.h |  3 ++
 3 files changed, 90 insertions(+)

diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index fb19b2df3a..b12660b9f8 100644
--- a/hw/riscv/Kconfig
+++ b/hw/riscv/Kconfig
@@ -36,4 +36,5 @@ config RISCV_VIRT
 select SERIAL
 select VIRTIO_MMIO
 select PCI_EXPRESS_GENERIC_BRIDGE
+select PFLASH_CFI01
 select SIFIVE
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index e4dcbadcb5..ad29e14d5f 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -26,6 +26,7 @@
 #include "hw/boards.h"
 #include "hw/loader.h"
 #include "hw/sysbus.h"
+#include "hw/qdev-properties.h"
 #include "hw/char/serial.h"
 #include "target/riscv/cpu.h"
 #include "hw/riscv/riscv_hart.h"
@@ -61,12 +62,77 @@ static const struct MemmapEntry {
 [VIRT_PLIC] ={  0xc00, 0x400 },
 [VIRT_UART0] =   { 0x1000, 0x100 },
 [VIRT_VIRTIO] =  { 0x10001000,0x1000 },
+[VIRT_FLASH] =   { 0x2000, 0x200 },
 [VIRT_DRAM] ={ 0x8000,   0x0 },
 [VIRT_PCIE_MMIO] =   { 0x4000,0x4000 },
 [VIRT_PCIE_PIO] ={ 0x0300,0x0001 },
 [VIRT_PCIE_ECAM] =   { 0x3000,0x1000 },
 };
 
+#define VIRT_FLASH_SECTOR_SIZE (256 * KiB)
+
+static PFlashCFI01 *virt_flash_create1(RISCVVirtState *s,
+   const char *name,
+   const char *alias_prop_name)
+{
+/*
+ * Create a single flash device.  We use the same parameters as
+ * the flash devices on the ARM virt board.
+ */
+DeviceState *dev = qdev_create(NULL, TYPE_PFLASH_CFI01);
+
+qdev_prop_set_uint64(dev, "sector-length", VIRT_FLASH_SECTOR_SIZE);
+qdev_prop_set_uint8(dev, "width", 4);
+qdev_prop_set_uint8(dev, "device-width", 2);
+qdev_prop_set_bit(dev, "big-endian", false);
+qdev_prop_set_uint16(dev, "id0", 0x89);
+qdev_prop_set_uint16(dev, "id1", 0x18);
+qdev_prop_set_uint16(dev, "id2", 0x00);
+qdev_prop_set_uint16(dev, "id3", 0x00);
+qdev_prop_set_string(dev, "name", name);
+
+object_property_add_child(OBJECT(s), name, OBJECT(dev),
+  _abort);
+object_property_add_alias(OBJECT(s), alias_prop_name,
+  OBJECT(dev), "drive", _abort);
+
+return PFLASH_CFI01(dev);
+}
+
+static void virt_flash_create(RISCVVirtState *s)
+{
+s->flash[0] = virt_flash_create1(s, "virt.flash0", "pflash0");
+s->flash[1] = virt_flash_create1(s, "virt.flash1", "pflash1");
+}
+
+static void virt_flash_map1(PFlashCFI01 *flash,
+hwaddr base, hwaddr size,
+MemoryRegion *sysmem)
+{
+DeviceState *dev = DEVICE(flash);
+
+assert(size % VIRT_FLASH_SECTOR_SIZE == 0);
+assert(size / VIRT_FLASH_SECTOR_SIZE <= UINT32_MAX);
+qdev_prop_set_uint32(dev, "num-blocks", size / VIRT_FLASH_SECTOR_SIZE);
+qdev_init_nofail(dev);
+
+memory_region_add_subregion(sysmem, base,
+sysbus_mmio_get_region(SYS_BUS_DEVICE(dev),
+   0));
+}
+
+static void virt_flash_map(RISCVVirtState *s,
+   MemoryRegion *sysmem)
+{
+hwaddr flashsize = virt_memmap[VIRT_FLASH].size / 2;
+hwaddr flashbase = virt_memmap[VIRT_FLASH].base;
+
+virt_flash_map1(s->flash[0], flashbase, flashsize,
+sysmem);
+virt_flash_map1(s->flash[1], flashbase + flashsize, flashsize,
+sysmem);
+}
+
 static void create_pcie_irq_map(void *fdt, char *nodename,
 uint32_t plic_phandle)
 {
@@ -121,6 +187,8 @@ static void create_fdt(RISCVVirtState *s, const struct 
MemmapEntry *memmap,
 char *nodename;
 uint32_t plic_phandle, phandle = 1;
 int i;
+hwaddr flashsize = virt_memmap[VIRT_FLASH].size / 2;
+hwaddr flashbase = virt_memmap[VIRT_FLASH].base;
 
 fdt = s->fdt = create_device_tree(>fdt_size);
 if (!fdt) {
@@ -316,6 +384,15 @@ static void create_fdt(RISCVVirtState *s, const struct 
MemmapEntry *memmap,
 qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
 }
 g_free(nodename);
+
+nodename = g_strdup_printf("/flash@%" PRIx64, flashbase);
+qemu_fdt_add_subnode(s->fdt, nodename);
+qemu_fdt_setprop_string(s->fdt, nodename, "compatible", "cfi-flash");
+qemu_fdt_setprop_sized_cells(s->fdt, nodename, "reg",
+ 2, flashbase, 2, flashsize,
+ 2, flashbase + flashsize, 

[PATCH v3 3/7] riscv/sifive_u: Manually define the machine

2019-10-08 Thread Alistair Francis
Instead of using the DEFINE_MACHINE() macro to define the machine let's
do it manually. This allows us to specify machine properties.

This patch is no functional change.

Signed-off-by: Alistair Francis 
Reviewed-by: Bin Meng 
Tested-by: Bin Meng 
---
 hw/riscv/sifive_u.c | 44 ++---
 include/hw/riscv/sifive_u.h |  7 +-
 2 files changed, 37 insertions(+), 14 deletions(-)

diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index bc0e01242b..f5741e9a38 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -310,8 +310,7 @@ static void create_fdt(SiFiveUState *s, const struct 
MemmapEntry *memmap,
 static void riscv_sifive_u_init(MachineState *machine)
 {
 const struct MemmapEntry *memmap = sifive_u_memmap;
-
-SiFiveUState *s = g_new0(SiFiveUState, 1);
+SiFiveUState *s = RISCV_U_MACHINE(machine);
 MemoryRegion *system_memory = get_system_memory();
 MemoryRegion *main_mem = g_new(MemoryRegion, 1);
 MemoryRegion *flash0 = g_new(MemoryRegion, 1);
@@ -433,6 +432,10 @@ static void riscv_sifive_u_soc_init(Object *obj)
   TYPE_CADENCE_GEM);
 }
 
+static void riscv_sifive_u_machine_instance_init(Object *obj)
+{
+}
+
 static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp)
 {
 MachineState *ms = MACHINE(qdev_get_machine());
@@ -546,17 +549,6 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, 
Error **errp)
 memmap[SIFIVE_U_GEM_MGMT].base, memmap[SIFIVE_U_GEM_MGMT].size);
 }
 
-static void riscv_sifive_u_machine_init(MachineClass *mc)
-{
-mc->desc = "RISC-V Board compatible with SiFive U SDK";
-mc->init = riscv_sifive_u_init;
-mc->max_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + SIFIVE_U_COMPUTE_CPU_COUNT;
-mc->min_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + 1;
-mc->default_cpus = mc->min_cpus;
-}
-
-DEFINE_MACHINE("sifive_u", riscv_sifive_u_machine_init)
-
 static void riscv_sifive_u_soc_class_init(ObjectClass *oc, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(oc);
@@ -580,3 +572,29 @@ static void riscv_sifive_u_soc_register_types(void)
 }
 
 type_init(riscv_sifive_u_soc_register_types)
+
+static void riscv_sifive_u_machine_class_init(ObjectClass *oc, void *data)
+{
+MachineClass *mc = MACHINE_CLASS(oc);
+
+mc->desc = "RISC-V Board compatible with SiFive U SDK";
+mc->init = riscv_sifive_u_init;
+mc->max_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + SIFIVE_U_COMPUTE_CPU_COUNT;
+mc->min_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + 1;
+mc->default_cpus = mc->min_cpus;
+}
+
+static const TypeInfo riscv_sifive_u_machine_typeinfo = {
+.name   = MACHINE_TYPE_NAME("sifive_u"),
+.parent = TYPE_MACHINE,
+.class_init = riscv_sifive_u_machine_class_init,
+.instance_init = riscv_sifive_u_machine_instance_init,
+.instance_size = sizeof(SiFiveUState),
+};
+
+static void riscv_sifive_u_machine_init_register_types(void)
+{
+type_register_static(_sifive_u_machine_typeinfo);
+}
+
+type_init(riscv_sifive_u_machine_init_register_types)
diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h
index 2a08e2a5db..a921079fbe 100644
--- a/include/hw/riscv/sifive_u.h
+++ b/include/hw/riscv/sifive_u.h
@@ -44,12 +44,17 @@ typedef struct SiFiveUSoCState {
 CadenceGEMState gem;
 } SiFiveUSoCState;
 
+#define TYPE_RISCV_U_MACHINE MACHINE_TYPE_NAME("sifive_u")
+#define RISCV_U_MACHINE(obj) \
+OBJECT_CHECK(SiFiveUState, (obj), TYPE_RISCV_U_MACHINE)
+
 typedef struct SiFiveUState {
 /*< private >*/
-SysBusDevice parent_obj;
+MachineState parent_obj;
 
 /*< public >*/
 SiFiveUSoCState soc;
+
 void *fdt;
 int fdt_size;
 } SiFiveUState;
-- 
2.23.0




[PATCH v3 2/7] riscv/sifive_u: Add QSPI memory region

2019-10-08 Thread Alistair Francis
The HiFive Unleashed uses is25wp256 SPI NOR flash. There is currently no
model of this in QEMU, so to allow boot firmware developers to use QEMU
to target the Unleashed let's add a chunk of memory to represent the QSPI0
memory mapped flash. This can be targeted using QEMU's -device loader
command line option.

In the future we can look at adding a model for the is25wp256 flash.

Signed-off-by: Alistair Francis 
Reviewed-by: Bin Meng 
---
 hw/riscv/sifive_u.c | 8 
 include/hw/riscv/sifive_u.h | 1 +
 2 files changed, 9 insertions(+)

diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 1d255ad13e..bc0e01242b 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -71,6 +71,7 @@ static const struct MemmapEntry {
 [SIFIVE_U_UART0] ={ 0x1001, 0x1000 },
 [SIFIVE_U_UART1] ={ 0x10011000, 0x1000 },
 [SIFIVE_U_OTP] =  { 0x1007, 0x1000 },
+[SIFIVE_U_FLASH0] =   { 0x2000, 0x1000 },
 [SIFIVE_U_DRAM] = { 0x8000,0x0 },
 [SIFIVE_U_GEM] =  { 0x1009, 0x2000 },
 [SIFIVE_U_GEM_MGMT] = { 0x100a, 0x1000 },
@@ -313,6 +314,7 @@ static void riscv_sifive_u_init(MachineState *machine)
 SiFiveUState *s = g_new0(SiFiveUState, 1);
 MemoryRegion *system_memory = get_system_memory();
 MemoryRegion *main_mem = g_new(MemoryRegion, 1);
+MemoryRegion *flash0 = g_new(MemoryRegion, 1);
 int i;
 
 /* Initialize SoC */
@@ -328,6 +330,12 @@ static void riscv_sifive_u_init(MachineState *machine)
 memory_region_add_subregion(system_memory, memmap[SIFIVE_U_DRAM].base,
 main_mem);
 
+/* register QSPI0 Flash */
+memory_region_init_ram(flash0, NULL, "riscv.sifive.u.flash0",
+   memmap[SIFIVE_U_FLASH0].size, _fatal);
+memory_region_add_subregion(system_memory, memmap[SIFIVE_U_FLASH0].base,
+flash0);
+
 /* create device tree */
 create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline);
 
diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h
index 50e3620c02..2a08e2a5db 100644
--- a/include/hw/riscv/sifive_u.h
+++ b/include/hw/riscv/sifive_u.h
@@ -64,6 +64,7 @@ enum {
 SIFIVE_U_UART0,
 SIFIVE_U_UART1,
 SIFIVE_U_OTP,
+SIFIVE_U_FLASH0,
 SIFIVE_U_DRAM,
 SIFIVE_U_GEM,
 SIFIVE_U_GEM_MGMT
-- 
2.23.0




[PATCH v3 4/7] riscv/sifive_u: Add the start-in-flash property

2019-10-08 Thread Alistair Francis
Add a property that when set to true QEMU will jump from the ROM code to
the start of flash memory instead of DRAM which is the default
behaviour.

Signed-off-by: Alistair Francis 
---
v3:
 - Use the start_addr variable instead of editing reset vector
 - Fix function names

 hw/riscv/sifive_u.c | 30 +-
 include/hw/riscv/sifive_u.h |  2 ++
 2 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index f5741e9a38..43e9f744a3 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -314,6 +314,7 @@ static void riscv_sifive_u_init(MachineState *machine)
 MemoryRegion *system_memory = get_system_memory();
 MemoryRegion *main_mem = g_new(MemoryRegion, 1);
 MemoryRegion *flash0 = g_new(MemoryRegion, 1);
+target_ulong start_addr = memmap[SIFIVE_U_DRAM].base;
 int i;
 
 /* Initialize SoC */
@@ -356,6 +357,10 @@ static void riscv_sifive_u_init(MachineState *machine)
 }
 }
 
+if (s->start_in_flash) {
+start_addr = memmap[SIFIVE_U_FLASH0].base;
+}
+
 /* reset vector */
 uint32_t reset_vec[8] = {
 0x0297,/* 1:  auipc  t0, %pcrel_hi(dtb) */
@@ -368,7 +373,7 @@ static void riscv_sifive_u_init(MachineState *machine)
 #endif
 0x00028067,/* jr t0 */
 0x,
-memmap[SIFIVE_U_DRAM].base, /* start: .dword DRAM_BASE */
+start_addr,/* start: .dword */
 0x,
/* dtb: */
 };
@@ -432,8 +437,31 @@ static void riscv_sifive_u_soc_init(Object *obj)
   TYPE_CADENCE_GEM);
 }
 
+static bool sifive_u_get_start_in_flash(Object *obj, Error **errp)
+{
+SiFiveUState *s = RISCV_U_MACHINE(obj);
+
+return s->start_in_flash;
+}
+
+static void sifive_u_set_start_in_flash(Object *obj, bool value, Error **errp)
+{
+SiFiveUState *s = RISCV_U_MACHINE(obj);
+
+s->start_in_flash = value;
+}
+
 static void riscv_sifive_u_machine_instance_init(Object *obj)
 {
+SiFiveUState *s = RISCV_U_MACHINE(obj);
+
+s->start_in_flash = false;
+object_property_add_bool(obj, "start-in-flash", 
sifive_u_get_start_in_flash,
+ sifive_u_set_start_in_flash, NULL);
+object_property_set_description(obj, "start-in-flash",
+"Set on to tell QEMU's ROM to jump to " \
+"flash. Otherwise QEMU will jump to DRAM",
+NULL);
 }
 
 static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp)
diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h
index a921079fbe..2656b43c58 100644
--- a/include/hw/riscv/sifive_u.h
+++ b/include/hw/riscv/sifive_u.h
@@ -57,6 +57,8 @@ typedef struct SiFiveUState {
 
 void *fdt;
 int fdt_size;
+
+bool start_in_flash;
 } SiFiveUState;
 
 enum {
-- 
2.23.0




[PATCH v3 1/7] riscv/sifive_u: Add L2-LIM cache memory

2019-10-08 Thread Alistair Francis
On reset only a single L2 cache way is enabled, the others are exposed
as memory that can be used by early boot firmware. This L2 region is
generally disabled using the WayEnable register at a later stage in the
boot process. To allow firmware to target QEMU and the HiFive Unleashed
let's add the L2 LIM (LooselyIntegrated Memory).

Ideally we would want to adjust the size of this chunk of memory as the
L2 Cache Controller WayEnable register is incremented. Unfortunately I
don't see a nice way to handle reducing or blocking out the L2 LIM while
still allowing it be re returned to all enabled from a reset.

Signed-off-by: Alistair Francis 
Reviewed-by: Bin Meng 
---
 hw/riscv/sifive_u.c | 16 
 include/hw/riscv/sifive_u.h |  1 +
 2 files changed, 17 insertions(+)

diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 9f8e84bf2e..1d255ad13e 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -65,6 +65,7 @@ static const struct MemmapEntry {
 [SIFIVE_U_DEBUG] ={0x0,  0x100 },
 [SIFIVE_U_MROM] = { 0x1000,0x11000 },
 [SIFIVE_U_CLINT] ={  0x200,0x1 },
+[SIFIVE_U_L2LIM] ={  0x800,  0x200 },
 [SIFIVE_U_PLIC] = {  0xc00,  0x400 },
 [SIFIVE_U_PRCI] = { 0x1000, 0x1000 },
 [SIFIVE_U_UART0] ={ 0x1001, 0x1000 },
@@ -431,6 +432,7 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, 
Error **errp)
 const struct MemmapEntry *memmap = sifive_u_memmap;
 MemoryRegion *system_memory = get_system_memory();
 MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
+MemoryRegion *l2lim_mem = g_new(MemoryRegion, 1);
 qemu_irq plic_gpios[SIFIVE_U_PLIC_NUM_SOURCES];
 char *plic_hart_config;
 size_t plic_hart_config_len;
@@ -459,6 +461,20 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, 
Error **errp)
 memory_region_add_subregion(system_memory, memmap[SIFIVE_U_MROM].base,
 mask_rom);
 
+/*
+ * Add L2-LIM at reset size.
+ * This should be reduced in size as the L2 Cache Controller WayEnable
+ * register is incremented. Unfortunately I don't see a nice (or any) way
+ * to handle reducing or blocking out the L2 LIM while still allowing it
+ * be re returned to all enabled after a reset. For the time being, just
+ * leave it enabled all the time. This won't break anything, but will be
+ * too generous to misbehaving guests.
+ */
+memory_region_init_ram(l2lim_mem, NULL, "riscv.sifive.u.l2lim",
+   memmap[SIFIVE_U_L2LIM].size, _fatal);
+memory_region_add_subregion(system_memory, memmap[SIFIVE_U_L2LIM].base,
+l2lim_mem);
+
 /* create PLIC hart topology configuration string */
 plic_hart_config_len = (strlen(SIFIVE_U_PLIC_HART_CONFIG) + 1) *
ms->smp.cpus;
diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h
index e4df298c23..50e3620c02 100644
--- a/include/hw/riscv/sifive_u.h
+++ b/include/hw/riscv/sifive_u.h
@@ -58,6 +58,7 @@ enum {
 SIFIVE_U_DEBUG,
 SIFIVE_U_MROM,
 SIFIVE_U_CLINT,
+SIFIVE_U_L2LIM,
 SIFIVE_U_PLIC,
 SIFIVE_U_PRCI,
 SIFIVE_U_UART0,
-- 
2.23.0




[PATCH v3 5/7] riscv/virt: Manually define the machine

2019-10-08 Thread Alistair Francis
Instead of using the DEFINE_MACHINE() macro to define the machine let's
do it manually. This allows us to use the machine object to create
RISCVVirtState. This is required to add children and aliases to the
machine.

This patch is no functional change.

Signed-off-by: Alistair Francis 
Reviewed-by: Bin Meng 
Tested-by: Bin Meng 
---
 hw/riscv/virt.c | 30 --
 include/hw/riscv/virt.h |  7 ++-
 2 files changed, 30 insertions(+), 7 deletions(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index d36f5625ec..e4dcbadcb5 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -362,8 +362,7 @@ static inline DeviceState *gpex_pcie_init(MemoryRegion 
*sys_mem,
 static void riscv_virt_board_init(MachineState *machine)
 {
 const struct MemmapEntry *memmap = virt_memmap;
-
-RISCVVirtState *s = g_new0(RISCVVirtState, 1);
+RISCVVirtState *s = RISCV_VIRT_MACHINE(machine);
 MemoryRegion *system_memory = get_system_memory();
 MemoryRegion *main_mem = g_new(MemoryRegion, 1);
 MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
@@ -499,12 +498,31 @@ static void riscv_virt_board_init(MachineState *machine)
 g_free(plic_hart_config);
 }
 
-static void riscv_virt_board_machine_init(MachineClass *mc)
+static void riscv_virt_machine_instance_init(Object *obj)
 {
-mc->desc = "RISC-V VirtIO Board (Privileged ISA v1.10)";
+}
+
+static void riscv_virt_machine_class_init(ObjectClass *oc, void *data)
+{
+MachineClass *mc = MACHINE_CLASS(oc);
+
+mc->desc = "RISC-V VirtIO board";
 mc->init = riscv_virt_board_init;
-mc->max_cpus = 8; /* hardcoded limit in BBL */
+mc->max_cpus = 8;
 mc->default_cpu_type = VIRT_CPU;
 }
 
-DEFINE_MACHINE("virt", riscv_virt_board_machine_init)
+static const TypeInfo riscv_virt_machine_typeinfo = {
+.name   = MACHINE_TYPE_NAME("virt"),
+.parent = TYPE_MACHINE,
+.class_init = riscv_virt_machine_class_init,
+.instance_init = riscv_virt_machine_instance_init,
+.instance_size = sizeof(RISCVVirtState),
+};
+
+static void riscv_virt_machine_init_register_types(void)
+{
+type_register_static(_virt_machine_typeinfo);
+}
+
+type_init(riscv_virt_machine_init_register_types)
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
index 6e5fbe5d3b..ffcdcc6dcc 100644
--- a/include/hw/riscv/virt.h
+++ b/include/hw/riscv/virt.h
@@ -22,13 +22,18 @@
 #include "hw/riscv/riscv_hart.h"
 #include "hw/sysbus.h"
 
+#define TYPE_RISCV_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
+#define RISCV_VIRT_MACHINE(obj) \
+OBJECT_CHECK(RISCVVirtState, (obj), TYPE_RISCV_VIRT_MACHINE)
+
 typedef struct {
 /*< private >*/
-SysBusDevice parent_obj;
+MachineState parent;
 
 /*< public >*/
 RISCVHartArrayState soc;
 DeviceState *plic;
+
 void *fdt;
 int fdt_size;
 } RISCVVirtState;
-- 
2.23.0




[PATCH v3 0/7] RISC-V: Add more machine memory

2019-10-08 Thread Alistair Francis


This series aims to improve the use of QEMU for developing boot code. It
does a few things:

 - sifive_u machine:
   - Adds a chunk of memory in the Flash area. This allows boot loaders
   to use this memory. I can't find details on the QSPI flash used on
   the real board, so this is the best bet at the moment.
   - Adds a chunk of memory in the L2-LIM area. This is actualy the L2
   cache and should shrink as the L2 cache is enalbed. Unfortunatley I
   don't see a nice way to shrink this memory.
   - Adds a property that allows users to specify if QEMU should jump to
   flash or DRAM after the ROM code.

 - virt machine:
   - Add the pflash_cfi01 flash device. This is based on the ARM virt
   board implementation
   - Adjusts QEMU to jump to the flash if a user has speciefied any
   pflash.

Both machines have been tested with oreboot, but this should also help
the coreboot developers.

v3:
 - Use the start_addr variable instead of editing reset vector
 - Fix function names
v2:
 - Address comments
 - Fixup addresses
 - Don't use macro for machine definition of RISC-V virt machine



Alistair Francis (7):
  riscv/sifive_u: Add L2-LIM cache memory
  riscv/sifive_u: Add QSPI memory region
  riscv/sifive_u: Manually define the machine
  riscv/sifive_u: Add the start-in-flash property
  riscv/virt: Manually define the machine
  riscv/virt: Add the PFlash CFI01 device
  riscv/virt: Jump to pflash if specified

 hw/riscv/Kconfig|   1 +
 hw/riscv/sifive_u.c |  98 
 hw/riscv/virt.c | 127 ++--
 include/hw/riscv/sifive_u.h |  11 +++-
 include/hw/riscv/virt.h |  10 ++-
 5 files changed, 224 insertions(+), 23 deletions(-)

-- 
2.23.0




Re: [PATCH 5/5] tests/boot_linux_console: Add sdcard test for the Exynos4210

2019-10-08 Thread Cleber Rosa
On Sat, Oct 05, 2019 at 05:47:48PM +0200, Philippe Mathieu-Daudé wrote:
> This test boots a Linux kernel on a smdkc210 board and verify
> the serial output is working.
> 
> The cpio image used comes from the linux-build-test project:
> https://github.com/groeck/linux-build-test
> 
> Since this test is not reliable due to clock timing issues,
> it is disabled with the 'skip' property.
> 
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
>  tests/acceptance/boot_linux_console.py | 47 ++
>  1 file changed, 47 insertions(+)
> 
> diff --git a/tests/acceptance/boot_linux_console.py 
> b/tests/acceptance/boot_linux_console.py
> index 197358a69c..2d0d82b013 100644
> --- a/tests/acceptance/boot_linux_console.py
> +++ b/tests/acceptance/boot_linux_console.py
> @@ -14,6 +14,7 @@ import lzma
>  import gzip
>  import shutil
>  
> +from avocado import skip
>  from avocado_qemu import Test
>  from avocado.utils import process
>  from avocado.utils import archive
> @@ -359,6 +360,52 @@ class BootLinuxConsole(Test):
>  self.wait_for_console_pattern('Boot successful.')
>  # TODO user command, for now the uart is stuck
>  
> +@skip("unstable clock timings")

On the topic of skipping unstable tests, don't you think this is
something that should check for some type of flag?

Just for the sake of brainstorming, other possiblity is to build on
Avocado's "WARN" test status, and instead of failing a test (and
affecting the overall job execution), simply warn the user.  A
decorator such as "@warn_on" could be implemented similar to the
existing "@fail_on" and "@cancel_on".

> +def test_arm_exynos4210_sdcard(self):
> +"""
> +:avocado: tags=arch:arm
> +:avocado: tags=machine:smdkc210
> +"""
> +deb_url = ('https://snapshot.debian.org/archive/debian/'
> +   '20190928T224601Z/pool/main/l/linux/'
> +   'linux-image-4.19.0-6-armmp_4.19.67-2+deb10u1_armhf.deb')
> +deb_hash = 'fa9df4a0d38936cb50084838f2cb933f570d7d82'
> +deb_path = self.fetch_asset(deb_url, asset_hash=deb_hash)
> +kernel_path = self.extract_from_deb(deb_path,
> +'/boot/vmlinuz-4.19.0-6-armmp')
> +dtb_path = 
> '/usr/lib/linux-image-4.19.0-6-armmp/exynos4210-smdkv310.dtb'
> +dtb_path = self.extract_from_deb(deb_path, dtb_path)
> +
> +rootfs_url = ('https://github.com/groeck/linux-build-test/raw/'
> +  '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
> +  'arm/rootfs-armv5.ext2.gz')
> +rootfs_hash = '093e89d2b4d982234bf528bc9fb2f2f17a9d1f93'
> +rootfs_path_gz = self.fetch_asset(rootfs_url, asset_hash=rootfs_hash)
> +rootfs_path = os.path.join(self.workdir, 'rootfs.ext2')
> +gunzip(rootfs_path_gz, rootfs_path)

I was going to suggest the same thing as the previous patch, but this
turned out to be quite interesting.  Basically, both compressed and
uncompressed verions of this file seems to disguise themselves pretty
well as a tar file:

 $ tar vtf rootfs-armv5.ext2.gz
 $ gzip -dc rootfs-armv5.ext2.gz | tar vtf -
 $ python3 -m tarfile -l rootfs-armv5.ext2.gz
 $ python3 -m tarfile -l rootfs-armv5.ext2

Even though it is not.  This affects how "avocado.utils.uncompress"
detects the file, and consequently how it tries to uncompress it.
So, here, you could instead use:

  archive.gzip_uncompress(rootfs_path_gz, rootfs_path)

To avoid relying on the broken tar file detection.

- Cleber.

> +
> +self.vm.set_machine('smdkc210')
> +self.vm.set_console(console_id=1)
> +kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
> +   'earlycon=exynos4210,0x1381 earlyprintk ' 
> +
> +   'console=ttySAC1,115200n8 ' +
> +   'random.trust_cpu=off cryptomgr.notests ' +
> +   'root=/dev/mmcblk0 rootwait rw ' +
> +   'cpuidle.off=1 panic=-1 noreboot')
> +
> +self.vm.add_args('-kernel', kernel_path,
> + '-dtb', dtb_path,
> + '-append', kernel_command_line,
> + # The external MMC is on the 3rd slot
> + '-drive', 'if=sd,driver=null-co',
> + '-drive', 'if=sd,driver=null-co',
> + '-drive', 'if=sd,file=' + rootfs_path + 
> ',format=raw',
> + '-no-reboot')
> +self.vm.launch()
> +
> +self.wait_for_console_pattern('Boot successful.')
> +# TODO user command, for now the uart is stuck
> +
>  def test_s390x_s390_ccw_virtio(self):
>  """
>  :avocado: tags=arch:s390x
> -- 
> 2.20.1
> 
> 



Re: [PATCH 1/5] tests/boot_linux_console: Add initrd test for the Exynos4210

2019-10-08 Thread Guenter Roeck
On Tue, Oct 08, 2019 at 05:49:07PM -0400, Cleber Rosa wrote:
> On Mon, Oct 07, 2019 at 05:28:49PM +0100, Peter Maydell wrote:
> > On Sat, 5 Oct 2019 at 16:47, Philippe Mathieu-Daudé  wrote:
> > >
> > > This test boots a Linux kernel on a smdkc210 board and verify
> > > the serial output is working.
> > >
> > > The cpio image used comes from the linux-build-test project:
> > > https://github.com/groeck/linux-build-test
> > 
> > Thanks for putting this test case together, very helpful.
> > 
> > > +initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
> > > +  '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
> > > +  'arm/rootfs-armv5.cpio.gz')
> > 
> > Do our other acceptance tests download random third-party
> > (ie "not a well-known distro") binaries for the tests ?
> > It seems a bit hazardous for reproducability and trustability
> > reasons...
> > 

FWIW, the root file system was generated with buildroot, with
minor modifications. It should be possible to create a clean
root file system from there.

Guenter



Re: [PULL v2 0/8] Ide patches

2019-10-08 Thread Laszlo Ersek
On 10/08/19 23:58, Laszlo Ersek wrote:
> On 10/07/19 19:55, Philippe Mathieu-Daudé wrote:
>> On 10/7/19 7:35 PM, John Snow wrote:
>>> On 10/7/19 8:33 AM, Peter Maydell wrote:
 On Thu, 3 Oct 2019 at 20:33, John Snow  wrote:
>
> The following changes since commit
> 7f21573c822805a8e6be379d9bcf3ad9effef3dc:
>
>    Merge remote-tracking branch
> 'remotes/huth-gitlab/tags/pull-request-2019-10-01' into staging
> (2019-10-01 13:13:38 +0100)
>
> are available in the Git repository at:
>
>    https://github.com/jnsnow/qemu.git tags/ide-pull-request
>
> for you to fetch changes up to
> f6d61c9509c56eea3cdd2d23b40d285601b1c1ca:
>
>    hd-geo-test: Add tests for lchs override (2019-10-03 14:36:54 -0400)
>
> 
> Pull request V2
>
> - Added signoff into the mirrored commits themselves (vs just the
> email)
> - Kudos to `stg-foreach stg edit --sign`
>
> 

 Hi; the new tests in hd-geo-test seem to hang on
 big-endian hosts (both s390x and ppc64 hung here):

 linux1@lxub05:~/qemu/build/all$ QTEST_QEMU_IMG=./qemu-img
 QTEST_QEMU_BINARY=x86_64-softmmu/qemu-system-x86_64
 ./tests/hd-geo-test
 /x86_64/hd-geo/ide/none: OK
 /x86_64/hd-geo/ide/drive/cd_0: OK
 /x86_64/hd-geo/ide/drive/mbr/blank: OK
 /x86_64/hd-geo/ide/drive/mbr/lba: OK
 /x86_64/hd-geo/ide/drive/mbr/chs: OK
 /x86_64/hd-geo/ide/device/mbr/blank: OK
 /x86_64/hd-geo/ide/device/mbr/lba: OK
 /x86_64/hd-geo/ide/device/mbr/chs: OK
 /x86_64/hd-geo/ide/device/user/chs: OK
 /x86_64/hd-geo/ide/device/user/chst: OK
 /x86_64/hd-geo/override/ide:

>>>
>>> :(
>>>

 thanks
 -- PMM

>>>
>>> Sam, can you investigate this?
>>
>> Not seeing my T-b tags makes me grumble because I don't remember which I
>> reviewed and need to go check on the list.
>>
>> If the error is a endianess bug related to fw_cfg, you can add the
>> "-trace fw_cfg*" in hd-geo-test::create_args() and rerun the tests on a
>> BE system, the bug should appear straightly on stdout.
>>
>> Are FWLCHSEntry fields little-endian? Shouldn't
>> get_boot_devices_lchs_list() use some le32_to_cpu() call for the LCHS
>> values?
>>
> 
> *One* problem is most likely in the find_fw_cfg_file() function, in patch 8.
> 
> +static uint16_t find_fw_cfg_file(QFWCFG *fw_cfg,
> + const char *filename)
> +{
> +struct QemuCfgFile qfile;
> +uint32_t count, e;
> +uint16_t select;
> +
> +count = qfw_cfg_get_u32(fw_cfg, FW_CFG_FILE_DIR);
> +count = be32_to_cpu(count);
> +for (select = 0, e = 0; e < count; e++) {
> +qfw_cfg_read_data(fw_cfg, , sizeof(qfile));
> +if (!strcmp(filename, qfile.name)) {
> +select = be16_to_cpu(qfile.select);
> +}
> +}
> +
> +return select;
> +}
> 
> Note qfw_cfg_get_u32():
> 
> uint32_t qfw_cfg_get_u32(QFWCFG *fw_cfg, uint16_t key)
> {
> uint32_t value;
> qfw_cfg_get(fw_cfg, key, , sizeof(value));
> return le32_to_cpu(value);
> }
> 
> This function assumes that the wire encoding of the value read is little
> endian. So, calling this function is wrong; and calling be32_to_cpu()
> afterwards does not help. Namely:
> 
> * On LE hosts, the find_fw_cfg_file() function happens to work, because:
> 
> - the le32_to_cpu() call in qfw_cfg_get_u32() does nothing (it's identity),
> - the subsequent be32_to_cpu() call in find_fw_cfg_file() corresponds to
> the *blob-specific* encoding of the "count" field, in the fw_cfg
> directory blob. (Which is BE) Therefore we perform the one byte-swap
> that we need.
> 
> * On BE hosts, stuff breaks, because:
> 
> - the le32_to_cpu() call in qfw_cfg_get_u32() swaps the byte-order,
> - the subsequent be32_to_cpu() call in find_fw_cfg_file() does nothing,
> - thus, ultimately we have byte-swapped the contents of the "count"
> field of the directory blob, even though the blob-specific wire format
> thereof is *already* BE (= host-endian). On a BE host, all in all, there
> should be zero byte swaps for consuming "count".

And the hang is probably due to the loop in find_fw_cfg_file() counting
up to cca. 0x2000_:

- The file directory currently has room for 0x20 files, and if you
byte-swap that as a uint32_t, you get 0x2000_. (You minimally get
0x0100_, if there's just one entry in the directory -- still
16,777,216 in decimal.)

- Additionally, the loop body does not contain a "break" statement for
when strcmp() matches; so even if there is a hit in the low numbers, the
loop continues to the limit.

Thanks
Laszlo

> Now, how to fix this: eliminate
> - QemuCfgFile,
> - find_fw_cfg_file(),
> - and read_fw_cfg_file()
> 
> altogether, and call qfw_cfg_get_file(), from "tests/libqos/fw_cfg.c".
> 
> Some other tests look up fw_cfg directory entries with that 

[PATCH v1 1/1] target/riscv: Remove atomic accesses to MIP CSR

2019-10-08 Thread Alistair Francis
Instead of relying on atomics to access the MIP register let's update
our helper function to instead just lock the IO mutex thread before
writing. This follows the same concept as used in PPC for handling
interrupts

Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.c|  5 ++--
 target/riscv/cpu.h|  9 
 target/riscv/cpu_helper.c | 48 +++
 target/riscv/csr.c|  2 +-
 4 files changed, 21 insertions(+), 43 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index f13e298a36..e09dd7aa23 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -224,8 +224,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int 
flags)
 #ifndef CONFIG_USER_ONLY
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", env->mstatus);
-qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mip ",
- (target_ulong)atomic_read(>mip));
+qemu_fprintf(f, " %s 0x%x\n", "mip ", env->mip);
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mie ", env->mie);
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mideleg ", env->mideleg);
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "medeleg ", env->medeleg);
@@ -275,7 +274,7 @@ static bool riscv_cpu_has_work(CPUState *cs)
  * Definition of the WFI instruction requires it to ignore the privilege
  * mode and delegation registers, but respect individual enables
  */
-return (atomic_read(>mip) & env->mie) != 0;
+return (env->mip & env->mie) != 0;
 #else
 return true;
 #endif
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 124ed33ee4..a71473b243 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -121,15 +121,6 @@ struct CPURISCVState {
 target_ulong mhartid;
 target_ulong mstatus;
 
-/*
- * CAUTION! Unlike the rest of this struct, mip is accessed asynchonously
- * by I/O threads. It should be read with atomic_read. It should be updated
- * using riscv_cpu_update_mip with the iothread mutex held. The iothread
- * mutex must be held because mip must be consistent with the CPU inturrept
- * state. riscv_cpu_update_mip calls cpu_interrupt or cpu_reset_interrupt
- * wuth the invariant that CPU_INTERRUPT_HARD is set iff mip is non-zero.
- * mip is 32-bits to allow atomic_read on 32-bit hosts.
- */
 uint32_t mip;
 uint32_t miclaim;
 
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 87dd6a6ece..4334978c2e 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -19,6 +19,7 @@
 
 #include "qemu/osdep.h"
 #include "qemu/log.h"
+#include "qemu/main-loop.h"
 #include "cpu.h"
 #include "exec/exec-all.h"
 #include "tcg-op.h"
@@ -38,7 +39,7 @@ static int riscv_cpu_local_irq_pending(CPURISCVState *env)
 {
 target_ulong mstatus_mie = get_field(env->mstatus, MSTATUS_MIE);
 target_ulong mstatus_sie = get_field(env->mstatus, MSTATUS_SIE);
-target_ulong pending = atomic_read(>mip) & env->mie;
+target_ulong pending = env->mip & env->mie;
 target_ulong mie = env->priv < PRV_M || (env->priv == PRV_M && 
mstatus_mie);
 target_ulong sie = env->priv < PRV_S || (env->priv == PRV_S && 
mstatus_sie);
 target_ulong irqs = (pending & ~env->mideleg & -mie) |
@@ -92,42 +93,29 @@ int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint32_t 
interrupts)
 }
 }
 
-struct CpuAsyncInfo {
-uint32_t new_mip;
-};
-
-static void riscv_cpu_update_mip_irqs_async(CPUState *target_cpu_state,
-run_on_cpu_data data)
-{
-struct CpuAsyncInfo *info = (struct CpuAsyncInfo *) data.host_ptr;
-
-if (info->new_mip) {
-cpu_interrupt(target_cpu_state, CPU_INTERRUPT_HARD);
-} else {
-cpu_reset_interrupt(target_cpu_state, CPU_INTERRUPT_HARD);
-}
-
-g_free(info);
-}
-
 uint32_t riscv_cpu_update_mip(RISCVCPU *cpu, uint32_t mask, uint32_t value)
 {
 CPURISCVState *env = >env;
 CPUState *cs = CPU(cpu);
-struct CpuAsyncInfo *info;
-uint32_t old, new, cmp = atomic_read(>mip);
+uint32_t old = env->mip;
+bool locked = false;
+
+if (!qemu_mutex_iothread_locked()) {
+locked = true;
+qemu_mutex_lock_iothread();
+}
 
-do {
-old = cmp;
-new = (old & ~mask) | (value & mask);
-cmp = atomic_cmpxchg(>mip, old, new);
-} while (old != cmp);
+env->mip = (env->mip & ~mask) | (value & mask);
 
-info = g_new(struct CpuAsyncInfo, 1);
-info->new_mip = new;
+if (env->mip) {
+cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+} else {
+cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+}
 
-async_run_on_cpu(cs, riscv_cpu_update_mip_irqs_async,
- RUN_ON_CPU_HOST_PTR(info));
+if (locked) {
+qemu_mutex_unlock_iothread();
+}
 
 return old;
 }
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 

Re: [PULL v2 0/8] Ide patches

2019-10-08 Thread Laszlo Ersek
On 10/07/19 19:55, Philippe Mathieu-Daudé wrote:
> On 10/7/19 7:35 PM, John Snow wrote:
>> On 10/7/19 8:33 AM, Peter Maydell wrote:
>>> On Thu, 3 Oct 2019 at 20:33, John Snow  wrote:

 The following changes since commit
 7f21573c822805a8e6be379d9bcf3ad9effef3dc:

    Merge remote-tracking branch
 'remotes/huth-gitlab/tags/pull-request-2019-10-01' into staging
 (2019-10-01 13:13:38 +0100)

 are available in the Git repository at:

    https://github.com/jnsnow/qemu.git tags/ide-pull-request

 for you to fetch changes up to
 f6d61c9509c56eea3cdd2d23b40d285601b1c1ca:

    hd-geo-test: Add tests for lchs override (2019-10-03 14:36:54 -0400)

 
 Pull request V2

 - Added signoff into the mirrored commits themselves (vs just the
 email)
 - Kudos to `stg-foreach stg edit --sign`

 
>>>
>>> Hi; the new tests in hd-geo-test seem to hang on
>>> big-endian hosts (both s390x and ppc64 hung here):
>>>
>>> linux1@lxub05:~/qemu/build/all$ QTEST_QEMU_IMG=./qemu-img
>>> QTEST_QEMU_BINARY=x86_64-softmmu/qemu-system-x86_64
>>> ./tests/hd-geo-test
>>> /x86_64/hd-geo/ide/none: OK
>>> /x86_64/hd-geo/ide/drive/cd_0: OK
>>> /x86_64/hd-geo/ide/drive/mbr/blank: OK
>>> /x86_64/hd-geo/ide/drive/mbr/lba: OK
>>> /x86_64/hd-geo/ide/drive/mbr/chs: OK
>>> /x86_64/hd-geo/ide/device/mbr/blank: OK
>>> /x86_64/hd-geo/ide/device/mbr/lba: OK
>>> /x86_64/hd-geo/ide/device/mbr/chs: OK
>>> /x86_64/hd-geo/ide/device/user/chs: OK
>>> /x86_64/hd-geo/ide/device/user/chst: OK
>>> /x86_64/hd-geo/override/ide:
>>>
>>
>> :(
>>
>>>
>>> thanks
>>> -- PMM
>>>
>>
>> Sam, can you investigate this?
> 
> Not seeing my T-b tags makes me grumble because I don't remember which I
> reviewed and need to go check on the list.
> 
> If the error is a endianess bug related to fw_cfg, you can add the
> "-trace fw_cfg*" in hd-geo-test::create_args() and rerun the tests on a
> BE system, the bug should appear straightly on stdout.
> 
> Are FWLCHSEntry fields little-endian? Shouldn't
> get_boot_devices_lchs_list() use some le32_to_cpu() call for the LCHS
> values?
> 

*One* problem is most likely in the find_fw_cfg_file() function, in patch 8.

+static uint16_t find_fw_cfg_file(QFWCFG *fw_cfg,
+ const char *filename)
+{
+struct QemuCfgFile qfile;
+uint32_t count, e;
+uint16_t select;
+
+count = qfw_cfg_get_u32(fw_cfg, FW_CFG_FILE_DIR);
+count = be32_to_cpu(count);
+for (select = 0, e = 0; e < count; e++) {
+qfw_cfg_read_data(fw_cfg, , sizeof(qfile));
+if (!strcmp(filename, qfile.name)) {
+select = be16_to_cpu(qfile.select);
+}
+}
+
+return select;
+}

Note qfw_cfg_get_u32():

uint32_t qfw_cfg_get_u32(QFWCFG *fw_cfg, uint16_t key)
{
uint32_t value;
qfw_cfg_get(fw_cfg, key, , sizeof(value));
return le32_to_cpu(value);
}

This function assumes that the wire encoding of the value read is little
endian. So, calling this function is wrong; and calling be32_to_cpu()
afterwards does not help. Namely:

* On LE hosts, the find_fw_cfg_file() function happens to work, because:

- the le32_to_cpu() call in qfw_cfg_get_u32() does nothing (it's identity),
- the subsequent be32_to_cpu() call in find_fw_cfg_file() corresponds to
the *blob-specific* encoding of the "count" field, in the fw_cfg
directory blob. (Which is BE) Therefore we perform the one byte-swap
that we need.

* On BE hosts, stuff breaks, because:

- the le32_to_cpu() call in qfw_cfg_get_u32() swaps the byte-order,
- the subsequent be32_to_cpu() call in find_fw_cfg_file() does nothing,
- thus, ultimately we have byte-swapped the contents of the "count"
field of the directory blob, even though the blob-specific wire format
thereof is *already* BE (= host-endian). On a BE host, all in all, there
should be zero byte swaps for consuming "count".

Now, how to fix this: eliminate
- QemuCfgFile,
- find_fw_cfg_file(),
- and read_fw_cfg_file()

altogether, and call qfw_cfg_get_file(), from "tests/libqos/fw_cfg.c".

Some other tests look up fw_cfg directory entries with that function
already (see call sites in "tests/fw_cfg-test.c").

Thanks
Laszlo



Re: [PATCH 2/5] hw/sd/sdhci: Add a comment to distinct the i.MX eSDHC functions

2019-10-08 Thread Cleber Rosa
On Sat, Oct 05, 2019 at 05:47:45PM +0200, Philippe Mathieu-Daudé wrote:
> This file keeps the various QDev blocks separated by comments.
> 
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
>  hw/sd/sdhci.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
> index e08ec3e398..82ec5c1b4a 100644
> --- a/hw/sd/sdhci.c
> +++ b/hw/sd/sdhci.c
> @@ -1532,6 +1532,8 @@ static const TypeInfo sdhci_bus_info = {
>  .class_init = sdhci_bus_class_init,
>  };
>  
> +/* --- qdev i.MX eSDHC --- */
> +
>  static uint64_t usdhc_read(void *opaque, hwaddr offset, unsigned size)
>  {
>  SDHCIState *s = SYSBUS_SDHCI(opaque);
> @@ -1734,7 +1736,6 @@ usdhc_write(void *opaque, hwaddr offset, uint64_t val, 
> unsigned size)
>  }
>  }
>  
> -
>  static const MemoryRegionOps usdhc_mmio_ops = {
>  .read = usdhc_read,
>  .write = usdhc_write,
> -- 
> 2.20.1
> 
> 

Reviewed-by: Cleber Rosa 



Re: [PATCH 1/5] tests/boot_linux_console: Add initrd test for the Exynos4210

2019-10-08 Thread Cleber Rosa
On Mon, Oct 07, 2019 at 05:28:49PM +0100, Peter Maydell wrote:
> On Sat, 5 Oct 2019 at 16:47, Philippe Mathieu-Daudé  wrote:
> >
> > This test boots a Linux kernel on a smdkc210 board and verify
> > the serial output is working.
> >
> > The cpio image used comes from the linux-build-test project:
> > https://github.com/groeck/linux-build-test
> 
> Thanks for putting this test case together, very helpful.
> 
> > +initrd_url = ('https://github.com/groeck/linux-build-test/raw/'
> > +  '2eb0a73b5d5a28df3170c546ddaaa9757e1e0848/rootfs/'
> > +  'arm/rootfs-armv5.cpio.gz')
> 
> Do our other acceptance tests download random third-party
> (ie "not a well-known distro") binaries for the tests ?
> It seems a bit hazardous for reproducability and trustability
> reasons...
> 
> thanks
> -- PMM

A quick and dirty grep shows (excluding comments and docs):

   boot_linux_console.py:kernel_url = 
('https://archives.fedoraproject.org/pub/archive/fedora'
   boot_linux_console.py:deb_url = 
('http://snapshot.debian.org/archive/debian/'
   boot_linux_console.py:deb_url = 
('http://snapshot.debian.org/archive/debian/'
   boot_linux_console.py:deb_url = 
('http://snapshot.debian.org/archive/debian/'
   boot_linux_console.py:initrd_url = 
('https://github.com/groeck/linux-build-test/raw/'
   boot_linux_console.py:kernel_url = 
('https://mipsdistros.mips.com/LinuxDistro/nanomips/'
   boot_linux_console.py:kernel_url = 
('https://mipsdistros.mips.com/LinuxDistro/nanomips/'
   boot_linux_console.py:kernel_url = 
('https://mipsdistros.mips.com/LinuxDistro/nanomips/'
   boot_linux_console.py:kernel_url = 
('https://archives.fedoraproject.org/pub/archive/fedora'
   boot_linux_console.py:kernel_url = 
('https://archives.fedoraproject.org/pub/archive/fedora'
   boot_linux_console.py:uboot_url = 
('https://raw.githubusercontent.com/'
   boot_linux_console.py:spi_url = ('https://raw.githubusercontent.com/'
   boot_linux_console.py:kernel_url = 
('https://archives.fedoraproject.org/pub/archive'
   boot_linux_console.py:kernel_url = 
('http://archive.debian.org/debian/dists/lenny/main/'
   boot_linux_console.py:kernel_url = 
('https://archives.fedoraproject.org/pub/archive'
   linux_initrd.py:kernel_url = 
('https://archives.fedoraproject.org/pub/archive/fedora/li'
   linux_initrd.py:kernel_url = 
('https://archives.fedoraproject.org/pub/archive/fedora'
   linux_ssh_mips_malta.py:'be': {'image_url': 
('https://people.debian.org/~aurel32/qemu/mips/'
   linux_ssh_mips_malta.py:'le': {'image_url': 
('https://people.debian.org/~aurel32/qemu/mipsel/'
   linux_ssh_mips_malta.py:kernel_url = 
('https://people.debian.org/~aurel32/qemu/mips/'
   linux_ssh_mips_malta.py:kernel_url = 
('https://people.debian.org/~aurel32/qemu/mipsel/'
   linux_ssh_mips_malta.py:kernel_url = 
('https://people.debian.org/~aurel32/qemu/mips/'
   linux_ssh_mips_malta.py:kernel_url = 
('https://people.debian.org/~aurel32/qemu/mipsel/'
   machine_m68k_nextcube.py:rom_url = 
('http://www.nextcomputers.org/NeXTfiles/Software/ROM_Files/'

I find it hard to judge precisely how much of a third-party some of
these are.  I remember Philippe mentioning that one of them, I guess
the images used on linux_ssh_mips_malta.py, were "as official as it
gets" (my words, from my often misleading memory).

Reproducibility is definitely an issue, in the sense given that some
of these can indeed go away, but as long as they're available the hash
recorded in the test should guarantee that we're running the same
images.

Do you think we should do something different here?

Thanks!
- Cleber.



Re: [PATCH 1/5] tests/boot_linux_console: Add initrd test for the Exynos4210

2019-10-08 Thread Cleber Rosa
On Sat, Oct 05, 2019 at 05:47:44PM +0200, Philippe Mathieu-Daudé wrote:
> This test boots a Linux kernel on a smdkc210 board and verify
> the serial output is working.
> 
> The cpio image used comes from the linux-build-test project:
> https://github.com/groeck/linux-build-test
> 
> If ARM is a target being built, "make check-acceptance" will
> automatically include this test by the use of the "arch:arm" tags.
> 
> This test can be run using:
> 
>   $ avocado --show=app,console run -t machine:smdkc210 
> tests/acceptance/boot_linux_console.py
>   console: Booting Linux on physical CPU 0x900
>   console: Linux version 4.19.0-6-armmp (debian-ker...@lists.debian.org) (gcc 
> version 8.3.0 (Debian 8.3.0-6)) #1 SMP Debian 4.19.67-2+deb10u1 (2019-09-20)
>   console: CPU: ARMv7 Processor [410fc090] revision 0 (ARMv7), cr=10c5387d
>   console: CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing 
> instruction cache
>   console: OF: fdt: Machine model: Samsung smdkv310 evaluation board based on 
> Exynos4210
>   [...]
>   console: Samsung CPU ID: 0x43210211
>   console: random: get_random_bytes called from start_kernel+0xa0/0x504 with 
> crng_init=0
>   console: percpu: Embedded 17 pages/cpu s39756 r8192 d21684 u69632
>   console: Built 1 zonelists, mobility grouping on.  Total pages: 249152
>   console: Kernel command line: printk.time=0 console=ttySAC0,115200n8 
> earlyprintk random.trust_cpu=off cryptomgr.notests cpuidle.off=1 panic=-1 
> noreboot
>   [...]
>   console: L2C: platform modifies aux control register: 0x0202 -> 
> 0x3e420001
>   console: L2C: platform provided aux values permit register corruption.
>   console: L2C: DT/platform modifies aux control register: 0x0202 -> 
> 0x3e420001
>   console: L2C-310 erratum 769419 enabled
>   console: L2C-310 enabling early BRESP for Cortex-A9
>   console: L2C-310: enabling full line of zeros but not enabled in Cortex-A9
>   console: L2C-310 ID prefetch enabled, offset 1 lines
>   console: L2C-310 dynamic clock gating disabled, standby mode disabled
>   console: L2C-310 cache controller enabled, 8 ways, 128 kB
>   console: L2C-310: CACHE_ID 0x41c8, AUX_CTRL 0x7e420001
>   console: Exynos4210 clocks: sclk_apll = 1200, sclk_mpll = 1200
>   console: sclk_epll = 1200, sclk_vpll = 1200, arm_clk = 1200
>   [...]
>   console: s3c-i2c 1386.i2c: slave address 0x00
>   console: s3c-i2c 1386.i2c: bus frequency set to 93 KHz
>   console: s3c-i2c 1386.i2c: i2c-0: S3C I2C adapter
>   [...]
>   console: dma-pl330 1268.pdma: Loaded driver for PL330 DMAC-241330
>   console: dma-pl330 1268.pdma:   DBUFF-256x8bytes Num_Chans-8 
> Num_Peri-32 Num_Events-16
>   console: dma-pl330 1269.pdma: Loaded driver for PL330 DMAC-241330
>   console: dma-pl330 1269.pdma:   DBUFF-256x8bytes Num_Chans-8 
> Num_Peri-32 Num_Events-16
>   console: dma-pl330 1285.mdma: Loaded driver for PL330 DMAC-241330
>   console: dma-pl330 1285.mdma:   DBUFF-256x8bytes Num_Chans-8 
> Num_Peri-1 Num_Events-16
>   console: dma-pl330 1285.mdma: PM domain LCD0 will not be powered off
>   console: Serial: 8250/16550 driver, 4 ports, IRQ sharing disabled
>   console: Serial: AMBA driver
>   console: 1380.serial: ttySAC0 at MMIO 0x1380 (irq = 40, base_baud = 
> 0) is a S3C6400/10
>   console: console [ttySAC0] enabled
>   console: 1381.serial: ttySAC1 at MMIO 0x1381 (irq = 41, base_baud = 
> 0) is a S3C6400/10
>   console: 1382.serial: ttySAC2 at MMIO 0x1382 (irq = 42, base_baud = 
> 0) is a S3C6400/10
>   console: 1383.serial: ttySAC3 at MMIO 0x1383 (irq = 43, base_baud = 
> 0) is a S3C6400/10
>   [...]
>   console: Freeing unused kernel memory: 2048K
>   console: Run /init as init process
>   console: mount: mounting devtmpfs on /dev failed: Device or resource busy
>   console: Starting logging: OK
>   console: Initializing random number generator... random: dd: uninitialized 
> urandom read (512 bytes read)
>   console: done.
>   console: Starting network: OK
>   console: Found console ttySAC0
>   console: Linux version 4.19.0-6-armmp (debian-ker...@lists.debian.org) (gcc 
> version 8.3.0 (Debian 8.3.0-6)) #1 SMP Debian 4.19.67-2+deb10u1 (2019-09-20)
>   console: Boot successful.
>   PASS (37.98 s)
> 
> Signed-off-by: Philippe Mathieu-Daudé 
> ---
> serial input is not working :(
> 
> I sometime get (not always):
> 
> Starting network: OK
> [   70.403690] rcu: INFO: rcu_preempt detected stalls on CPUs/tasks:
> [   70.423212] rcu: 0-...!: (36 GPs behind) idle=c7a/1/0x4000 
> softirq=287/288 fqs=1
> [   70.428209] rcu: (detected by 1, t=2602 jiffies, g=-443, q=2209)
> [   70.432826] Sending NMI from CPU 1 to CPUs 0:
> [   70.473866] NMI backtrace for cpu 0
> [   70.476621] CPU: 0 PID: 112 Comm: cat Not tainted 4.19.0 #1
> [   70.476711] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
> [   70.476916] PC is at mntput_no_expire+0x88/0x464
> [   70.476996] LR is at 

Re: [PATCH v2 0/2] RISC-V: Convert to do_transaction_failed hook

2019-10-08 Thread Palmer Dabbelt

On Tue, 08 Oct 2019 13:51:46 PDT (-0700), Alistair Francis wrote:


The do_unassigned_access hook has been deprecated and RISC-V is the last
user of it. Let's instead update the RISC-V implementation to use
do_transaction_failed instead.

After this series I used the 'git grep' regexes in
docs/devel/loads-stores.rst and these are the memory accesses inside
target/riscv:

monitor.c:102:cpu_physical_memory_read(pte_addr, , ptesize);

cpu_helper.c:262:target_ulong pte = address_space_ldl(cs->as, pte_addr, 
attrs, );
cpu_helper.c:264:target_ulong pte = address_space_ldq(cs->as, pte_addr, 
attrs, );

translate.c:782:ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);

gdbstub.c:328:env->fpr[n] = ldq_p(mem_buf); /* always 64-bit */

All of these look safe to me.

v2:
 - Rebase on master


Palmer Dabbelt (2):
  RISC-V: Handle bus errors in the page table walker
  RISC-V: Implement cpu_do_transaction_failed

 target/riscv/cpu.c|  2 +-
 target/riscv/cpu.h|  7 +--
 target/riscv/cpu_helper.c | 23 ---
 3 files changed, 22 insertions(+), 10 deletions(-)


Thanks, these are in the queue.



[PATCH v2 2/2] RISC-V: Implement cpu_do_transaction_failed

2019-10-08 Thread Alistair Francis
From: Palmer Dabbelt 

This converts our port over from cpu_do_unassigned_access to
cpu_do_transaction_failed, as cpu_do_unassigned_access has been
deprecated.

Signed-off-by: Palmer Dabbelt 
Signed-off-by: Alistair Francis 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 target/riscv/cpu.c|  2 +-
 target/riscv/cpu.h|  7 +--
 target/riscv/cpu_helper.c | 11 +++
 3 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index f13e298a36..3939963b71 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -484,7 +484,7 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data)
 cc->gdb_stop_before_watchpoint = true;
 cc->disas_set_info = riscv_cpu_disas_set_info;
 #ifndef CONFIG_USER_ONLY
-cc->do_unassigned_access = riscv_cpu_unassigned_access;
+cc->do_transaction_failed = riscv_cpu_do_transaction_failed;
 cc->do_unaligned_access = riscv_cpu_do_unaligned_access;
 cc->get_phys_page_debug = riscv_cpu_get_phys_page_debug;
 #endif
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 124ed33ee4..8c64c68538 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -264,8 +264,11 @@ void  riscv_cpu_do_unaligned_access(CPUState *cs, vaddr 
addr,
 bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
 MMUAccessType access_type, int mmu_idx,
 bool probe, uintptr_t retaddr);
-void riscv_cpu_unassigned_access(CPUState *cpu, hwaddr addr, bool is_write,
- bool is_exec, int unused, unsigned size);
+void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
+ vaddr addr, unsigned size,
+ MMUAccessType access_type,
+ int mmu_idx, MemTxAttrs attrs,
+ MemTxResult response, uintptr_t retaddr);
 char *riscv_isa_string(RISCVCPU *cpu);
 void riscv_cpu_list(void);
 
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index c82e7ed52b..917252f71b 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -408,20 +408,23 @@ hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr 
addr)
 return phys_addr;
 }
 
-void riscv_cpu_unassigned_access(CPUState *cs, hwaddr addr, bool is_write,
- bool is_exec, int unused, unsigned size)
+void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
+ vaddr addr, unsigned size,
+ MMUAccessType access_type,
+ int mmu_idx, MemTxAttrs attrs,
+ MemTxResult response, uintptr_t retaddr)
 {
 RISCVCPU *cpu = RISCV_CPU(cs);
 CPURISCVState *env = >env;
 
-if (is_write) {
+if (access_type == MMU_DATA_STORE) {
 cs->exception_index = RISCV_EXCP_STORE_AMO_ACCESS_FAULT;
 } else {
 cs->exception_index = RISCV_EXCP_LOAD_ACCESS_FAULT;
 }
 
 env->badaddr = addr;
-riscv_raise_exception(>env, cs->exception_index, GETPC());
+riscv_raise_exception(>env, cs->exception_index, retaddr);
 }
 
 void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
-- 
2.23.0




[PATCH v2 0/2] RISC-V: Convert to do_transaction_failed hook

2019-10-08 Thread Alistair Francis


The do_unassigned_access hook has been deprecated and RISC-V is the last
user of it. Let's instead update the RISC-V implementation to use
do_transaction_failed instead.

After this series I used the 'git grep' regexes in
docs/devel/loads-stores.rst and these are the memory accesses inside
target/riscv:

monitor.c:102:cpu_physical_memory_read(pte_addr, , ptesize);

cpu_helper.c:262:target_ulong pte = address_space_ldl(cs->as, pte_addr, 
attrs, );
cpu_helper.c:264:target_ulong pte = address_space_ldq(cs->as, pte_addr, 
attrs, );

translate.c:782:ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);

gdbstub.c:328:env->fpr[n] = ldq_p(mem_buf); /* always 64-bit */

All of these look safe to me.

v2:
 - Rebase on master


Palmer Dabbelt (2):
  RISC-V: Handle bus errors in the page table walker
  RISC-V: Implement cpu_do_transaction_failed

 target/riscv/cpu.c|  2 +-
 target/riscv/cpu.h|  7 +--
 target/riscv/cpu_helper.c | 23 ---
 3 files changed, 22 insertions(+), 10 deletions(-)

-- 
2.23.0




Re: [PATCH] memory: Replace DEBUG_UNASSIGNED printf calls by trace events

2019-10-08 Thread Alistair Francis
On Tue, Oct 8, 2019 at 1:41 PM Alistair Francis  wrote:
>
> On Tue, Oct 8, 2019 at 1:41 PM Palmer Dabbelt  wrote:
> >
> > On Fri, 20 Sep 2019 07:20:34 PDT (-0700), Peter Maydell wrote:
> > > On Fri, 20 Sep 2019 at 15:17, Paolo Bonzini  wrote:
> > >> I think it's simplest if all series (RISC-V, remove unassigned_access,
> > >> this one) go through the RISC-V tree.
> > >
> > > I don't inherently object but IME the risc-v tree tends to move
> > > comparatively slowly. The initial risc-v conversion patchset
> > > should definitely go via the risc-v tree, anyway.
> >
> > We still don't have the riscv_cpu_unassigned_access() removal patches in, 
> > which
> > IIRC got blocked on review but I can no longer dig out of my inbox.  IIRC 
> > the
> > patches Alistair sent were still "From: Palmer", which means I can't review
> > them.
>
> The patches are reviewed by Richard and Philippe, they should be ready to 
> merge.

Just sent a v2, so you should be able to find them now.

Alistair

>
> Alistair
>
> >
> > I'm fine taking this on top of those, but it looks like there's still some
> > debate about the patch itself.  I don't see a v2.
> >



[PATCH v2 1/2] RISC-V: Handle bus errors in the page table walker

2019-10-08 Thread Alistair Francis
From: Palmer Dabbelt 

We directly access physical memory while walking the page tables on
RISC-V, but while doing so we were using cpu_ld*() which does not report
bus errors.  This patch converts the page table walker over to use
address_space_ld*(), which allows bus errors to be detected.

Signed-off-by: Palmer Dabbelt 
Signed-off-by: Alistair Francis 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 target/riscv/cpu_helper.c | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 87dd6a6ece..c82e7ed52b 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -169,7 +169,8 @@ static int get_physical_address(CPURISCVState *env, hwaddr 
*physical,
 /* NOTE: the env->pc value visible here will not be
  * correct, but the value visible to the exception handler
  * (riscv_cpu_do_interrupt) is correct */
-
+MemTxResult res;
+MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
 int mode = mmu_idx;
 
 if (mode == PRV_M && access_type != MMU_INST_FETCH) {
@@ -256,11 +257,16 @@ restart:
 1 << MMU_DATA_LOAD, PRV_S)) {
 return TRANSLATE_PMP_FAIL;
 }
+
 #if defined(TARGET_RISCV32)
-target_ulong pte = ldl_phys(cs->as, pte_addr);
+target_ulong pte = address_space_ldl(cs->as, pte_addr, attrs, );
 #elif defined(TARGET_RISCV64)
-target_ulong pte = ldq_phys(cs->as, pte_addr);
+target_ulong pte = address_space_ldq(cs->as, pte_addr, attrs, );
 #endif
+if (res != MEMTX_OK) {
+return TRANSLATE_FAIL;
+}
+
 hwaddr ppn = pte >> PTE_PPN_SHIFT;
 
 if (!(pte & PTE_V)) {
-- 
2.23.0




Re: [PATCH] memory: Replace DEBUG_UNASSIGNED printf calls by trace events

2019-10-08 Thread Alistair Francis
On Tue, Oct 8, 2019 at 1:41 PM Palmer Dabbelt  wrote:
>
> On Fri, 20 Sep 2019 07:20:34 PDT (-0700), Peter Maydell wrote:
> > On Fri, 20 Sep 2019 at 15:17, Paolo Bonzini  wrote:
> >> I think it's simplest if all series (RISC-V, remove unassigned_access,
> >> this one) go through the RISC-V tree.
> >
> > I don't inherently object but IME the risc-v tree tends to move
> > comparatively slowly. The initial risc-v conversion patchset
> > should definitely go via the risc-v tree, anyway.
>
> We still don't have the riscv_cpu_unassigned_access() removal patches in, 
> which
> IIRC got blocked on review but I can no longer dig out of my inbox.  IIRC the
> patches Alistair sent were still "From: Palmer", which means I can't review
> them.

The patches are reviewed by Richard and Philippe, they should be ready to merge.

Alistair

>
> I'm fine taking this on top of those, but it looks like there's still some
> debate about the patch itself.  I don't see a v2.
>



Re: [PATCH] memory: Replace DEBUG_UNASSIGNED printf calls by trace events

2019-10-08 Thread Palmer Dabbelt

On Fri, 20 Sep 2019 07:20:34 PDT (-0700), Peter Maydell wrote:

On Fri, 20 Sep 2019 at 15:17, Paolo Bonzini  wrote:

I think it's simplest if all series (RISC-V, remove unassigned_access,
this one) go through the RISC-V tree.


I don't inherently object but IME the risc-v tree tends to move
comparatively slowly. The initial risc-v conversion patchset
should definitely go via the risc-v tree, anyway.


We still don't have the riscv_cpu_unassigned_access() removal patches in, which 
IIRC got blocked on review but I can no longer dig out of my inbox.  IIRC the 
patches Alistair sent were still "From: Palmer", which means I can't review 
them.


I'm fine taking this on top of those, but it looks like there's still some 
debate about the patch itself.  I don't see a v2.




Re: [PATCH v2 4/7] riscv/sifive_u: Add the start-in-flash property

2019-10-08 Thread Alistair Francis
On Tue, Oct 8, 2019 at 1:12 PM Palmer Dabbelt  wrote:
>
> On Mon, 30 Sep 2019 11:04:45 PDT (-0700), alistai...@gmail.com wrote:
> > On Fri, Sep 27, 2019 at 12:57 AM Bin Meng  wrote:
> >>
> >> On Fri, Sep 27, 2019 at 8:55 AM Alistair Francis
> >>  wrote:
> >> >
> >> > Add a property that when set to true QEMU will jump from the ROM code to
> >> > the start of flash memory instead of DRAM which is the default
> >> > behaviour.
> >> >
> >> > Signed-off-by: Alistair Francis 
> >> > ---
> >> >  hw/riscv/sifive_u.c | 27 +++
> >> >  include/hw/riscv/sifive_u.h |  2 ++
> >> >  2 files changed, 29 insertions(+)
> >> >
> >> > diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
> >> > index f5741e9a38..33b55d0d5b 100644
> >> > --- a/hw/riscv/sifive_u.c
> >> > +++ b/hw/riscv/sifive_u.c
> >> > @@ -373,6 +373,10 @@ static void riscv_sifive_u_init(MachineState 
> >> > *machine)
> >> > /* dtb: */
> >> >  };
> >> >
> >> > +if (s->start_in_flash) {
> >> > +reset_vec[6] = memmap[SIFIVE_U_FLASH0].base; /* start: .dword 
> >> > FLASH0_BASE */
> >> > +}
> >>
> >> Please change to use the way that patch "[v2,7/7] riscv/virt: Jump to
> >> pflash if specified" does for consistency, ie:
> >>
> >> if (s->start_in_flash) {
> >> start_addr = memmap[SIFIVE_U_FLASH0].base; /* start: .dword
> >> FLASH0_BASE */
> >> }
> >>
> >> > +
> >> >  /* copy in the reset vector in little_endian byte order */
> >> >  for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
> >> >  reset_vec[i] = cpu_to_le32(reset_vec[i]);
> >> > @@ -432,8 +436,31 @@ static void riscv_sifive_u_soc_init(Object *obj)
> >> >TYPE_CADENCE_GEM);
> >> >  }
> >> >
> >> > +static bool virt_get_start_in_flash(Object *obj, Error **errp)
> >>
> >> sifive_u_get_start_in_flash()
> >>
> >> > +{
> >> > +SiFiveUState *s = RISCV_U_MACHINE(obj);
> >> > +
> >> > +return s->start_in_flash;
> >> > +}
> >> > +
> >> > +static void virt_set_start_in_flash(Object *obj, bool value, Error 
> >> > **errp)
> >>
> >> sifive_u_set_start_in_flash()
> >
> > Yep, I have fixed all of these.
>
> Did I miss the v3?

Nope, I'll send it today.

Alistair

>
> >
> > Alistair
> >
> >>
> >> > +{
> >> > +SiFiveUState *s = RISCV_U_MACHINE(obj);
> >> > +
> >> > +s->start_in_flash = value;
> >> > +}
> >> > +
> >> >  static void riscv_sifive_u_machine_instance_init(Object *obj)
> >> >  {
> >> > +SiFiveUState *s = RISCV_U_MACHINE(obj);
> >> > +
> >> > +s->start_in_flash = false;
> >> > +object_property_add_bool(obj, "start-in-flash", 
> >> > virt_get_start_in_flash,
> >> > + virt_set_start_in_flash, NULL);
> >> > +object_property_set_description(obj, "start-in-flash",
> >> > +"Set on to tell QEMU's ROM to jump 
> >> > to " \
> >> > +"flash. Otherwise QEMU will jump to 
> >> > DRAM",
> >> > +NULL);
> >> >  }
> >> >
> >> >  static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp)
> >> > diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h
> >> > index a921079fbe..2656b43c58 100644
> >> > --- a/include/hw/riscv/sifive_u.h
> >> > +++ b/include/hw/riscv/sifive_u.h
> >> > @@ -57,6 +57,8 @@ typedef struct SiFiveUState {
> >> >
> >> >  void *fdt;
> >> >  int fdt_size;
> >> > +
> >> > +bool start_in_flash;
> >> >  } SiFiveUState;
> >> >
> >>
> >> Regards,
> >> Bin



Re: [PATCH v2 7/7] tests/fw_cfg: Run the tests on big-endian targets

2019-10-08 Thread Peter Maydell
On Tue, 8 Oct 2019 at 21:29, Laszlo Ersek  wrote:
> In that case, the original initializer will remain in effect, from:
>
>   QTestCtx ctx = {};
>
> (Admittedly, this is an ugly GNU-ism; for standard C, it should be
>
>   QTestCtx ctx = { 0 };
>
> but the GNU-ism is used quite frequently in QEMU elsewhere, so meh :) )

This is deliberate -- some compilers grumble about "{ 0 }" in
some situations, so we generally recommend using "{}" which
is accepted by all compilers we care about. (Cf commit message
for commit 039d4e3df0049bdd.)

thanks
-- PMM



Re: [PATCH v2 7/7] tests/fw_cfg: Run the tests on big-endian targets

2019-10-08 Thread Laszlo Ersek
On 10/08/19 17:04, Li Qiang wrote:
> Philippe Mathieu-Daudé  于2019年10月7日周一 下午11:20写道:
> 
>> We have been restricting our fw_cfg tests to the PC machine,
>> which is a little-endian architecture.
>> The fw_cfg device is also used on the SPARC and PowerPC
>> architectures, which can run in big-endian configuration.
>>
>> Since we want to be sure our device does not regress
>> regardless the endianess used, enable this test one
>> these targets.
>>
>> The NUMA selector is X86 specific, restrict it to this arch.
>>
>> Signed-off-by: Philippe Mathieu-Daudé 
>> ---
>> v2: test ppc32 too (lvivier)
>> ---
>>  tests/Makefile.include |  2 ++
>>  tests/fw_cfg-test.c| 33 +++--
>>  2 files changed, 29 insertions(+), 6 deletions(-)
>>
>> diff --git a/tests/Makefile.include b/tests/Makefile.include
>> index 3543451ed3..4ae3d5140a 100644
>> --- a/tests/Makefile.include
>> +++ b/tests/Makefile.include
>> @@ -226,6 +226,7 @@ check-qtest-ppc-y += tests/prom-env-test$(EXESUF)
>>  check-qtest-ppc-y += tests/drive_del-test$(EXESUF)
>>  check-qtest-ppc-y += tests/boot-serial-test$(EXESUF)
>>  check-qtest-ppc-$(CONFIG_M48T59) += tests/m48t59-test$(EXESUF)
>> +check-qtest-ppc-y += tests/fw_cfg-test$(EXESUF)
>>
>>  check-qtest-ppc64-y += $(check-qtest-ppc-y)
>>  check-qtest-ppc64-$(CONFIG_PSERIES) += tests/device-plug-test$(EXESUF)
>> @@ -250,6 +251,7 @@ check-qtest-sh4eb-$(CONFIG_ISA_TESTDEV) =
>> tests/endianness-test$(EXESUF)
>>  check-qtest-sparc-y += tests/prom-env-test$(EXESUF)
>>  check-qtest-sparc-y += tests/m48t59-test$(EXESUF)
>>  check-qtest-sparc-y += tests/boot-serial-test$(EXESUF)
>> +check-qtest-sparc-y += tests/fw_cfg-test$(EXESUF)
>>
>>  check-qtest-sparc64-$(CONFIG_ISA_TESTDEV) = tests/endianness-test$(EXESUF)
>>  check-qtest-sparc64-y += tests/prom-env-test$(EXESUF)
>> diff --git a/tests/fw_cfg-test.c b/tests/fw_cfg-test.c
>> index 35af0de7e6..1250e87097 100644
>> --- a/tests/fw_cfg-test.c
>> +++ b/tests/fw_cfg-test.c
>> @@ -210,13 +210,30 @@ static void test_fw_cfg_splash_time(const void
>> *opaque)
>>
>>  int main(int argc, char **argv)
>>  {
>> -QTestCtx ctx;
>> -int ret;
>> +const char *arch = qtest_get_arch();
>> +bool has_numa = false;
>> +QTestCtx ctx = {};
>> +int ret = 0;
>>
>>  g_test_init(, , NULL);
>>
>> -ctx.machine_name = "pc";
>> -ctx.fw_cfg = pc_fw_cfg_init();
>> +if (g_str_equal(arch, "i386") || g_str_equal(arch, "x86_64")) {
>> +has_numa = true;
>> +ctx.machine_name = "pc";
>> +ctx.fw_cfg = pc_fw_cfg_init();
>> +} else if (g_str_equal(arch, "sparc")) {
>> +ctx.machine_name = "SS-5";
>> +ctx.fw_cfg = mm_fw_cfg_init(0xd0510ULL);
>> +} else if (g_str_equal(arch, "ppc") || g_str_equal(arch, "ppc64")) {
>> +/*
>> + * The mac99 machine is different for 32/64-bit target:
>> + *
>> + * ppc(32): the G4 which can be either little or big endian,
>> + * ppc64:   the G5 (970FX) is only big-endian.
>> + */
>> +ctx.machine_name = "mac99";
>> +ctx.fw_cfg = mm_fw_cfg_init(0xf510);
>> +}
>>
>>  qtest_add_data_func("fw_cfg/signature", , test_fw_cfg_signature);
>>  qtest_add_data_func("fw_cfg/id", , test_fw_cfg_id);
>> @@ -231,14 +248,18 @@ int main(int argc, char **argv)
>>  qtest_add_func("fw_cfg/boot_device", test_fw_cfg_boot_device);
>>  #endif
>>  qtest_add_data_func("fw_cfg/max_cpus", , test_fw_cfg_max_cpus);
>> -qtest_add_data_func("fw_cfg/numa", , test_fw_cfg_numa);
>>  qtest_add_data_func("fw_cfg/boot_menu", , test_fw_cfg_boot_menu);
>>  qtest_add_data_func("fw_cfg/reboot_timeout", ,
>>  test_fw_cfg_reboot_timeout);
>>  qtest_add_data_func("fw_cfg/splash_time", ,
>> test_fw_cfg_splash_time);
>>
>> -ret = g_test_run();
>> +if (has_numa) {
>> +qtest_add_data_func("fw_cfg/numa", , test_fw_cfg_numa);
>> +}
>>
>> +if (ctx.machine_name) {
>> +ret = g_test_run();
>> +}
>>
> 
> I think we can omit this if statement. In which case the ctx.machine_name
> will be NULL?

When "arch" differs from all of i386, x86_64, sparc, ppc, ppc64.

In that case, the original initializer will remain in effect, from:

  QTestCtx ctx = {};

(Admittedly, this is an ugly GNU-ism; for standard C, it should be

  QTestCtx ctx = { 0 };

but the GNU-ism is used quite frequently in QEMU elsewhere, so meh :) )

Thanks
Laszlo



Re: [PATCH 2/2] riscv: sifive_u: Add ethernet0 to the aliases node

2019-10-08 Thread Palmer Dabbelt

On Fri, 20 Sep 2019 02:19:02 PDT (-0700), bmeng...@gmail.com wrote:

U-Boot expects this alias to be in place in order to fix up the mac
address of the ethernet node.

This is to keep in sync with Linux kernel commit below:
https://patchwork.kernel.org/patch/11133033/

Signed-off-by: Bin Meng 
---

 hw/riscv/sifive_u.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 02dd761..1ac51e3 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -270,6 +270,10 @@ static void create_fdt(SiFiveUState *s, const struct 
MemmapEntry *memmap,
 s->soc.gem.conf.macaddr.a, ETH_ALEN);
 qemu_fdt_setprop_cell(fdt, nodename, "#address-cells", 1);
 qemu_fdt_setprop_cell(fdt, nodename, "#size-cells", 0);
+
+qemu_fdt_add_subnode(fdt, "/aliases");
+qemu_fdt_setprop_string(fdt, "/aliases", "ethernet0", nodename);
+
 g_free(nodename);

 nodename = g_strdup_printf("/soc/ethernet@%lx/ethernet-phy@0",
@@ -297,7 +301,6 @@ static void create_fdt(SiFiveUState *s, const struct 
MemmapEntry *memmap,
 qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
 }

-qemu_fdt_add_subnode(fdt, "/aliases");
 qemu_fdt_setprop_string(fdt, "/aliases", "serial0", nodename);

 g_free(nodename);


Thanks.  These two are in the patch queue.



Re: [PATCH v2 4/7] riscv/sifive_u: Add the start-in-flash property

2019-10-08 Thread Palmer Dabbelt

On Mon, 30 Sep 2019 11:04:45 PDT (-0700), alistai...@gmail.com wrote:

On Fri, Sep 27, 2019 at 12:57 AM Bin Meng  wrote:


On Fri, Sep 27, 2019 at 8:55 AM Alistair Francis
 wrote:
>
> Add a property that when set to true QEMU will jump from the ROM code to
> the start of flash memory instead of DRAM which is the default
> behaviour.
>
> Signed-off-by: Alistair Francis 
> ---
>  hw/riscv/sifive_u.c | 27 +++
>  include/hw/riscv/sifive_u.h |  2 ++
>  2 files changed, 29 insertions(+)
>
> diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
> index f5741e9a38..33b55d0d5b 100644
> --- a/hw/riscv/sifive_u.c
> +++ b/hw/riscv/sifive_u.c
> @@ -373,6 +373,10 @@ static void riscv_sifive_u_init(MachineState *machine)
> /* dtb: */
>  };
>
> +if (s->start_in_flash) {
> +reset_vec[6] = memmap[SIFIVE_U_FLASH0].base; /* start: .dword 
FLASH0_BASE */
> +}

Please change to use the way that patch "[v2,7/7] riscv/virt: Jump to
pflash if specified" does for consistency, ie:

if (s->start_in_flash) {
start_addr = memmap[SIFIVE_U_FLASH0].base; /* start: .dword
FLASH0_BASE */
}

> +
>  /* copy in the reset vector in little_endian byte order */
>  for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
>  reset_vec[i] = cpu_to_le32(reset_vec[i]);
> @@ -432,8 +436,31 @@ static void riscv_sifive_u_soc_init(Object *obj)
>TYPE_CADENCE_GEM);
>  }
>
> +static bool virt_get_start_in_flash(Object *obj, Error **errp)

sifive_u_get_start_in_flash()

> +{
> +SiFiveUState *s = RISCV_U_MACHINE(obj);
> +
> +return s->start_in_flash;
> +}
> +
> +static void virt_set_start_in_flash(Object *obj, bool value, Error **errp)

sifive_u_set_start_in_flash()


Yep, I have fixed all of these.


Did I miss the v3?



Alistair



> +{
> +SiFiveUState *s = RISCV_U_MACHINE(obj);
> +
> +s->start_in_flash = value;
> +}
> +
>  static void riscv_sifive_u_machine_instance_init(Object *obj)
>  {
> +SiFiveUState *s = RISCV_U_MACHINE(obj);
> +
> +s->start_in_flash = false;
> +object_property_add_bool(obj, "start-in-flash", virt_get_start_in_flash,
> + virt_set_start_in_flash, NULL);
> +object_property_set_description(obj, "start-in-flash",
> +"Set on to tell QEMU's ROM to jump to " \
> +"flash. Otherwise QEMU will jump to 
DRAM",
> +NULL);
>  }
>
>  static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp)
> diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h
> index a921079fbe..2656b43c58 100644
> --- a/include/hw/riscv/sifive_u.h
> +++ b/include/hw/riscv/sifive_u.h
> @@ -57,6 +57,8 @@ typedef struct SiFiveUState {
>
>  void *fdt;
>  int fdt_size;
> +
> +bool start_in_flash;
>  } SiFiveUState;
>

Regards,
Bin




Re: [PATCH v2 4/7] riscv/sifive_u: Add the start-in-flash property

2019-10-08 Thread Palmer Dabbelt

On Thu, 26 Sep 2019 17:44:28 PDT (-0700), Alistair Francis wrote:

Add a property that when set to true QEMU will jump from the ROM code to
the start of flash memory instead of DRAM which is the default
behaviour.

Signed-off-by: Alistair Francis 
---
 hw/riscv/sifive_u.c | 27 +++
 include/hw/riscv/sifive_u.h |  2 ++
 2 files changed, 29 insertions(+)

diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index f5741e9a38..33b55d0d5b 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -373,6 +373,10 @@ static void riscv_sifive_u_init(MachineState *machine)
/* dtb: */
 };

+if (s->start_in_flash) {
+reset_vec[6] = memmap[SIFIVE_U_FLASH0].base; /* start: .dword 
FLASH0_BASE */
+}
+
 /* copy in the reset vector in little_endian byte order */
 for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
 reset_vec[i] = cpu_to_le32(reset_vec[i]);
@@ -432,8 +436,31 @@ static void riscv_sifive_u_soc_init(Object *obj)
   TYPE_CADENCE_GEM);
 }

+static bool virt_get_start_in_flash(Object *obj, Error **errp)
+{
+SiFiveUState *s = RISCV_U_MACHINE(obj);
+
+return s->start_in_flash;
+}
+
+static void virt_set_start_in_flash(Object *obj, bool value, Error **errp)
+{
+SiFiveUState *s = RISCV_U_MACHINE(obj);
+
+s->start_in_flash = value;
+}
+
 static void riscv_sifive_u_machine_instance_init(Object *obj)
 {
+SiFiveUState *s = RISCV_U_MACHINE(obj);
+
+s->start_in_flash = false;
+object_property_add_bool(obj, "start-in-flash", virt_get_start_in_flash,
+ virt_set_start_in_flash, NULL);
+object_property_set_description(obj, "start-in-flash",
+"Set on to tell QEMU's ROM to jump to " \
+"flash. Otherwise QEMU will jump to DRAM",
+NULL);
 }

 static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp)
diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h
index a921079fbe..2656b43c58 100644
--- a/include/hw/riscv/sifive_u.h
+++ b/include/hw/riscv/sifive_u.h
@@ -57,6 +57,8 @@ typedef struct SiFiveUState {

 void *fdt;
 int fdt_size;
+
+bool start_in_flash;
 } SiFiveUState;

 enum {


Reviewed-by: Palmer Dabbelt 



Re: [PATCH v9 12/13] tb-stats: adding TBStatistics info into perf dump

2019-10-08 Thread Richard Henderson
On 10/7/19 11:28 AM, Alex Bennée wrote:
> diff --git a/accel/tcg/perf/jitdump.c b/accel/tcg/perf/jitdump.c
> index e1d6f2214e..e7b86173e0 100644
> --- a/accel/tcg/perf/jitdump.c
> +++ b/accel/tcg/perf/jitdump.c
> @@ -146,7 +146,20 @@ void start_jitdump_file(void)
>  
>  void append_load_in_jitdump_file(TranslationBlock *tb)
>  {
> -gchar *func_name = g_strdup_printf("TB virt:0x"TARGET_FMT_lx, tb->pc);
> +g_autoptr(GString) func_name = g_string_new("TB virt:");
> +
> +g_string_append_printf(func_name, "0x"TARGET_FMT_lx, tb->pc);

I think it was clearer as a single printf.  Use g_string_printf().

But now I see where the missing GString went -- bad patch splitting.  ;-)

> +if (tb->tb_stats) {
> +TBStatistics *tbs = tb->tb_stats;
> +unsigned g = stat_per_translation(tbs, code.num_guest_inst);
> +unsigned ops = stat_per_translation(tbs, code.num_tcg_ops);
> +unsigned ops_opt = stat_per_translation(tbs, code.num_tcg_ops_opt);
> +unsigned spills = stat_per_translation(tbs, code.spills);
> +
> +g_string_append_printf(func_name, " (g:%u op:%u opt:%u spills:%d)",
> +   g, ops, ops_opt, spills);
> +}

Oh, hum.  Does it really make sense to have accumulated averages here?  Why
does it not make more sense to have the statistics about this particular TB?
After all, different TB -- even for the same guest code -- will appear at
different places within the code_gen_buffer, and so have different entries in
this log.


r~



Re: [PATCH v9 13/13] configure: remove the final bits of --profiler support

2019-10-08 Thread Richard Henderson
On 10/7/19 11:28 AM, Alex Bennée wrote:
> Signed-off-by: Alex Bennée 
> ---
>  configure | 5 -
>  1 file changed, 5 deletions(-)

Merge this with the patch that removes CONFIG_PROFILER.


r~



Re: [PATCH v9 09/13] Adding info [tb-list|tb] commands to HMP (WIP)

2019-10-08 Thread Alex Bennée


Richard Henderson  writes:

> On 10/7/19 11:28 AM, Alex Bennée wrote:
>> From: "Vanderson M. do Rosario" 
>>
>> These commands allow the exploration of TBs generated by the TCG.
>> Understand which one hotter, with more guest/host instructions... and
>> examine their guest, host and IR code.
>>
>> The goal of this command is to allow the dynamic exploration of TCG
>> behavior and code quality. Therefore, for now, a corresponding QMP
>> command is not worthwhile.
>>
>> [AJB: WIP - we still can't be safely sure a translation will succeed]

I'll fix up all the other points...

>
>> +/*
>> + * We cannot always re-generate the code even if we know there are
>> + * valid translations still in the cache. The reason being the guest
>> + * may have un-mapped the page code.
>
> Um... unless I mistake what's being described here, that wouldn't be a valid
> translation.  Or do you just mean that the page mapping isn't present within
> the TLB?  Which is not quite the same thing as "unmapping".

A page entry can get dropped without invalidating the TB (for example
the guest OS sets a page as non-exec). The TLB flush takes care of the
jump cache and there are no inter-page hardwired links so if a tb_find
goes there we would get the fault.

>> + * TODO: can we do this safely? We need to
>> + *  a) somehow recover the mmu_idx for this translation
>
> We could add an interface for this, yes.  The value *must* be able to be
> derived from tb->flags, but of course in a target-dependent way.
>
>> + *  b) probe MMU_INST_FETCH to know it will succeed
>
> We *do* have this now, sort of: tlb_vaddr_to_host.
>
> So far all use of this function originates from target/foo/,
> and so some targets have not been updated to work with this.
> I've marked these with asserts within foo_cpu_tlb_fill.
>
> Notable targets for which it won't work: i386, sparc.
>
>
>> +static GString *get_code_string(TBStatistics *tbs, int log_flags)
>> +{
>> +int old_log_flags = qemu_loglevel;
>> +
>> +CPUState *cpu = first_cpu;
>> +uint32_t cflags = curr_cflags() | CF_NOCACHE;
>> +TranslationBlock *tb = NULL;
>> +
>> +GString *code_s = g_string_new(NULL);
>> +qemu_log_to_string(true, code_s);
>> +
>> +qemu_set_log(log_flags);
>> +
>> +if (sigsetjmp(cpu->jmp_env, 0) == 0) {
>> +mmap_lock();
>> +tb = tb_gen_code(cpu, tbs->pc, tbs->cs_base, tbs->flags, cflags);
>> +tb_phys_invalidate(tb, -1);
>> +mmap_unlock();
>
> Ew.  No.
>
> Let us not go through tb_gen_code, just to get logging output from the
> translator.  What are we really after here?  Input assembly?

All of it - in_asm, op, op_opt, out_asm potentially. But I agree it's
far too hacky - c.f. above because we end up potentially delivering a
fault to the guest when we fail.

It would be nice if we could run the translation phase independently of
the CPU environment. Maybe the monitor could have it's own TCGContext
and call tcg_gen_code directly just for debug output? It would avoid
having to use safe work and all the rest of the stuff we don't actually
care about in tb_gen_code. I guess you could still use the sigsetjmp to
catch the inevitable exceptions from the code load?

--
Alex Bennée



Re: [PATCH v9 11/13] accel/tcg: adding integration with linux perf

2019-10-08 Thread Richard Henderson
On 10/7/19 11:28 AM, Alex Bennée wrote:
> +static uint32_t get_e_machine(void)
> +{
> +uint32_t e_machine = EM_NONE;
> +Elf64_Ehdr elf_header;

Not ideal, as this appears to not work on 32-bit hosts, but the two structures
do match up within the first 24 bytes, in which this is located.

That said, this value is present within tcg/host/tcg-target.inc.c as
ELF_HOST_MACHINE.  So we really don't have to play /proc/self/exec games.

> +void start_jitdump_file(void)
> +{
> +g_autofree gchar *dumpfile_name = g_strdup_printf("./jit-%d.dump", 
> getpid());
> +dumpfile = fopen(dumpfile_name, "w+");
> +
> +/* 'Perf record' saves mmaped files during the execution of a program and
> + * 'perf inject' iterate over them to reconstruct all used/executed 
> binary.
> + * So, we create a mmap with the path of our jitdump that is processed
> + * and used by 'perf inject' to reconstruct jitted binaries.
> + */
> +perf_marker = mmap(NULL, sysconf(_SC_PAGESIZE),
> +  PROT_READ | PROT_EXEC,
> +  MAP_PRIVATE,
> +  fileno(dumpfile), 0);

(1) sysconf(_SC_PAGESIZE) is qemu_real_host_page_size.
(2) This is a page-sized mapping of a new, zero-sized file?
I assume this mapping event gets logged, and that it its
only purpose?
(3) I really need to read the kernel docs...

> +void append_load_in_jitdump_file(TranslationBlock *tb)
> +{
> +gchar *func_name = g_strdup_printf("TB virt:0x"TARGET_FMT_lx, tb->pc);
> +
> +/* Serialise the writing of the dump file */
> +qemu_mutex_lock(_lock);
> +
> +struct jr_code_load load_event;
> +load_event.p.id = JIT_CODE_LOAD;
> +load_event.p.total_size =
> +sizeof(struct jr_code_load) + func_name->len + 1 + tb->tc.size;

How does a "gchar *func_name" have ->len?  Did this used to be GString, but a
last-minute change means it no longer compiles?

> +fflush(dumpfile);

Why fflushing all of the time?  Surely the file contents doesn't matter until
after the final close.

> +qemu_mutex_unlock(_lock);

Why a separate qemu locking instead of using stdio's own locking (flockfile).

> diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
> index 871d91d559..3fafb656e7 100644
> --- a/accel/tcg/translate-all.c
> +++ b/accel/tcg/translate-all.c
> @@ -58,6 +58,10 @@
>  #include "sysemu/cpus.h"
>  #include "sysemu/tcg.h"
>  
> +#ifdef __linux__
> +#include "perf/jitdump.h"
> +#endif

Why the ifdefs?  We're not dependent on other headers are we?
Not that there's a "perf" on other hosts, but AFACT it should
at least compile...


r~



Re: [PATCH v9 08/13] tb-stats: reset the tracked TBs on a tb_flush

2019-10-08 Thread Alex Bennée


Richard Henderson  writes:

> On 10/7/19 11:28 AM, Alex Bennée wrote:
>> We keep track of translations but can only do so up until the
>> translation cache is flushed. At that point we really have no idea if
>> we can re-create a translation because all the active tracking
>> information has been reset.
>>
>> Signed-off-by: Alex Bennée 
>> ---
>>  accel/tcg/tb-stats.c  | 19 +++
>>  accel/tcg/translate-all.c |  2 +-
>>  include/exec/tb-stats.h   |  8 
>>  3 files changed, 28 insertions(+), 1 deletion(-)
>
> I still don't understand what the tbs array is for,
> but resetting it at flush is fine.

In Vanderson's original patch he kept a reference to the last translated
tb which was incorrect - I changed it to track all the TBs associated
with the stats entry. However the coverset and cfg commands aren't in
this series which needed to iterate down through the TBs to their jump
targets to build the full hot block. I suspect for now we can just drop
the entry.

>
> Reviewed-by: Richard Henderson 
>
>
> r~


--
Alex Bennée



Re: [PATCH 3/3] migration/postcopy: replace have_listen_thread check with PostcopyState check

2019-10-08 Thread Dr. David Alan Gilbert
* Wei Yang (richardw.y...@linux.intel.com) wrote:
> After previous cleanup, postcopy thread is running only when
> PostcopyState is LISTENNING or RUNNING. This means it is not necessary
> to spare a variable have_listen_thread to represent the state.
> 
> Replace the check on have_listen_thread with PostcopyState and remove
> the variable.
> 
> Signed-off-by: Wei Yang 
> ---
>  migration/migration.h | 1 -
>  migration/ram.c   | 2 +-
>  migration/ram.h   | 1 +
>  migration/savevm.c| 4 +---
>  4 files changed, 3 insertions(+), 5 deletions(-)
> 
> diff --git a/migration/migration.h b/migration/migration.h
> index 4f2fe193dc..a4d639663d 100644
> --- a/migration/migration.h
> +++ b/migration/migration.h
> @@ -63,7 +63,6 @@ struct MigrationIncomingState {
>  /* Set this when we want the fault thread to quit */
>  bool   fault_thread_quit;
>  
> -bool   have_listen_thread;
>  QemuThread listen_thread;
>  QemuSemaphore  listen_thread_sem;
>  
> diff --git a/migration/ram.c b/migration/ram.c
> index 769d3f6454..dfc50d57d5 100644
> --- a/migration/ram.c
> +++ b/migration/ram.c
> @@ -4188,7 +4188,7 @@ static bool postcopy_is_advised(void)
>  return ps >= POSTCOPY_INCOMING_ADVISE && ps < POSTCOPY_INCOMING_END;
>  }
>  
> -static bool postcopy_is_running(void)
> +bool postcopy_is_running(void)
>  {
>  PostcopyState ps = postcopy_state_get();
>  return ps >= POSTCOPY_INCOMING_LISTENING && ps < POSTCOPY_INCOMING_END;
> diff --git a/migration/ram.h b/migration/ram.h
> index bd0eee79b6..44fe4753ad 100644
> --- a/migration/ram.h
> +++ b/migration/ram.h
> @@ -59,6 +59,7 @@ int ram_postcopy_send_discard_bitmap(MigrationState *ms);
>  /* For incoming postcopy discard */
>  int ram_discard_range(const char *block_name, uint64_t start, size_t length);
>  int ram_postcopy_incoming_init(MigrationIncomingState *mis);
> +bool postcopy_is_running(void);
>  
>  void ram_handle_compressed(void *host, uint8_t ch, uint64_t size);
>  
> diff --git a/migration/savevm.c b/migration/savevm.c
> index dcad8897a3..2a0e0b94df 100644
> --- a/migration/savevm.c
> +++ b/migration/savevm.c
> @@ -1836,7 +1836,6 @@ static void *postcopy_ram_listen_thread(void *opaque)
>  qemu_loadvm_state_cleanup();
>  
>  rcu_unregister_thread();
> -mis->have_listen_thread = false;
>  postcopy_state_set(POSTCOPY_INCOMING_END, NULL);

That now needs a big comment saying it must be the last thing in the
thread, because now it's got meaning that it's here.

>  
>  return NULL;
> @@ -1880,7 +1879,6 @@ static int 
> loadvm_postcopy_handle_listen(MigrationIncomingState *mis)
>  return -1;
>  }
>  
> -mis->have_listen_thread = true;
>  /* Start up the listening thread and wait for it to signal ready */
>  qemu_sem_init(>listen_thread_sem, 0);
>  qemu_thread_create(>listen_thread, "postcopy/listen",
> @@ -2518,7 +2516,7 @@ int qemu_loadvm_state(QEMUFile *f)
>  
>  trace_qemu_loadvm_state_post_main(ret);
>  
> -if (mis->have_listen_thread) {
> +if (postcopy_is_running()) {
>  /* Listen thread still going, can't clean up yet */
>  return ret;
>  }

Can you explain to me why this is afe in the case of a failure in
loadvm_postcopy_handle_listen between the start where it sets
the state to LISTENING, and the point where it currently sets
hasve_listen_thread ?  Wouldn't this cause qemu_loadvm_state
not to cleanup?

Dave

> -- 
> 2.17.1
> 
--
Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK



Re: [PATCH v9 10/13] tb-stats: dump hot TBs at the end of the execution

2019-10-08 Thread Richard Henderson
On 10/7/19 11:28 AM, Alex Bennée wrote:
> @@ -337,7 +336,8 @@ int qemu_str_to_log_mask(const char *str)
>  enable_collect_tb_stats();
>  } else if (tb_stats_collection_enabled() &&
> g_str_has_prefix(*tmp, "dump_limit=")) {
> -max_num_hot_tbs_to_dump = atoi((*tmp) + 11);
> +int hot_tbs = atoi((*tmp) + 11);
> +set_tbstats_max_tbs(hot_tbs);

I think qemu_strtoi() is preferred over atoi().

My guess it that it's better to export a variable than a set_tbstats_max_tbs()
function.  I don't see any reason why stubs.c can't define variables -- they're
probably no larger than empty functions in many cases.


r~



Re: [PATCH 2/3] migration/postcopy: postpone setting PostcopyState to END

2019-10-08 Thread Dr. David Alan Gilbert
* Wei Yang (richardw.y...@linux.intel.com) wrote:
> There are two places to call function postcopy_ram_incoming_cleanup()
> 
> postcopy_ram_listen_thread on migration success
> loadvm_postcopy_handle_listen one setup failure
> 
> On success, the vm will never accept another migration. On failure,
> PostcopyState is transited from LISTENING to END and would be checked in
> qemu_loadvm_state_main(). If PostcopyState is RUNNING, migration would
> be paused and retried.
> 
> Currently PostcopyState is set to END in function
> postcopy_ram_incoming_cleanup(). With above analysis, we can take this
> step out and postpone this till the end of listen thread to indicate the
> listen thread is done.
> 
> This is a preparation patch for later cleanup.
> 
> Signed-off-by: Wei Yang 

Yes, I think that's OK - I couldn't see anywhere that's currently
checking the state in between.


Reviewed-by: Dr. David Alan Gilbert 

> ---
>  migration/postcopy-ram.c | 2 --
>  migration/savevm.c   | 2 ++
>  2 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c
> index a394c7c3a6..5da6de8c8b 100644
> --- a/migration/postcopy-ram.c
> +++ b/migration/postcopy-ram.c
> @@ -577,8 +577,6 @@ int postcopy_ram_incoming_cleanup(MigrationIncomingState 
> *mis)
>  }
>  }
>  
> -postcopy_state_set(POSTCOPY_INCOMING_END, NULL);
> -
>  if (mis->postcopy_tmp_page) {
>  munmap(mis->postcopy_tmp_page, mis->largest_page_size);
>  mis->postcopy_tmp_page = NULL;
> diff --git a/migration/savevm.c b/migration/savevm.c
> index eaa4cf58ef..dcad8897a3 100644
> --- a/migration/savevm.c
> +++ b/migration/savevm.c
> @@ -1837,6 +1837,8 @@ static void *postcopy_ram_listen_thread(void *opaque)
>  
>  rcu_unregister_thread();
>  mis->have_listen_thread = false;
> +postcopy_state_set(POSTCOPY_INCOMING_END, NULL);
> +
>  return NULL;
>  }
>  
> -- 
> 2.17.1
> 
--
Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK



Re: [PATCH 3/4] hw/i386: add facility to expose CPU topology over fw-cfg

2019-10-08 Thread Laszlo Ersek
Eduardo, Igor,

On 10/08/19 12:52, Laszlo Ersek wrote:
> FW_CFG_MAX_CPUS exposes the (exclusive) maximum APIC ID to guest firmware,
> due to historical reasons. That value is not useful to edk2, however. For
> supporting VCPU hotplug, edk2 needs:
> 
> - the boot CPU count (already exposed in FW_CFG_NB_CPUS),
> 
> - and the maximum foreseen CPU count (tracked in
>   "MachineState.smp.max_cpus", but not currently exposed).
> 
> Add a new fw-cfg file to expose "max_cpus".
> 
> While at it, expose the rest of the topology too (die / core / thread
> counts), because I expect that the VCPU hotplug feature for OVMF will
> ultimately need those too, and the data size is not large.

In fact, it seems like OVMF will have to synthesize the new
(hot-plugged) VCPU's *APIC-ID* from the following information sources:

- the topology information described above (die / core / thread counts), and

- the "modern" CPU hotplug interface (docs/specs/acpi_cpu_hotplug.txt).

Now, if I understand correctly, the "CPU selector" ([0x0-0x3]) specifies
a CPU *index*. Therefore, in the hotplug SMI handler (running on one of
the pre-existent CPUs), OVMF will have to translate the new CPU's
selector (the new CPU's *index*) to its *APIC-ID*, based on the topology
information (numbers of dies / cores / threads).

(That's because existent SMM infrastructure in edk2 uses the initial
APIC-ID as the key for referencing CPUs.)

Algorithmically, I think this translation is doable in OVMF  -- after
all, it is implemented in the x86_apicid_from_cpu_idx() function
already, in "include/hw/i386/topology.h". And that function does not
need more information either:

static inline apic_id_t x86_apicid_from_cpu_idx(unsigned nr_dies,
unsigned nr_cores,
unsigned nr_threads,
unsigned cpu_index)

Therefore, my plan is to implement the same translation logic in OVMF.

Now, the questions:

- Am I right to think that the "CPU selector" register in the "modern"
ACPI hotplug interface operates in the *same domain* as the "cpu_index"
parameter of x86_apicid_from_cpu_idx()?

- As we progress through CPU indices, x86_apicid_from_cpu_idx() first
fills threads in a core, then cores in a die, then dies in a socket.
Will this logic remain the same, forever?

If any of the two questions above is answered with "no", then OVMF will
need an fw_cfg blob that is different from the current proposal.

Namely, OVMF will need a *full* "cpu_index -> APIC-ID" map, up to (and
excluding) "max_cpus".

The pc_possible_cpu_arch_ids() function in "hw/i386/pc.c" already
calculates a similar map:

ms->possible_cpus->cpus[i].arch_id =
x86_cpu_apic_id_from_index(pcms, i);

So, basically that map is what OVMF would have to receive over fw_cfg,
*if* the "cpu_index -> APIC-ID" mapping is not considered guest ABI.
Should I write v2 for that?

Please comment!

Thanks,
Laszlo


> This is
> slightly complicated by the fact that the die count is specific to
> PCMachineState, but fw_cfg_arch_create() intends to be PC-independent (see
> commit 149c50cabcc4).
> 
> For now, the feature is temporarily disabled.
> 
> Cc: "Michael S. Tsirkin" 
> Cc: Eduardo Habkost 
> Cc: Igor Mammedov 
> Cc: Marcel Apfelbaum 
> Cc: Paolo Bonzini 
> Cc: Philippe Mathieu-Daudé 
> Cc: Richard Henderson 
> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1515
> Signed-off-by: Laszlo Ersek 
> ---
>  hw/i386/fw_cfg.h | 30 +-
>  hw/i386/fw_cfg.c | 26 --
>  hw/i386/pc.c |  4 ++--
>  3 files changed, 55 insertions(+), 5 deletions(-)
> 
> diff --git a/hw/i386/fw_cfg.h b/hw/i386/fw_cfg.h
> index e0856a376996..d742435b9793 100644
> --- a/hw/i386/fw_cfg.h
> +++ b/hw/i386/fw_cfg.h
> @@ -18,9 +18,37 @@
>  #define FW_CFG_E820_TABLE   (FW_CFG_ARCH_LOCAL + 3)
>  #define FW_CFG_HPET (FW_CFG_ARCH_LOCAL + 4)
>  
> +/**
> + * FWCfgX86Topology: expose the X86 CPU topology to guest firmware over 
> fw-cfg.
> + *
> + * All fields have little-endian encoding.
> + *
> + * @dies: Number of dies per package (aka socket). Set it to 1 unless the
> + *concrete MachineState subclass defines it differently.
> + * @cores:Corresponds to @CpuTopology.@cores.
> + * @threads:  Corresponds to @CpuTopology.@threads.
> + * @max_cpus: Corresponds to @CpuTopology.@max_cpus.
> + *
> + * Firmware can derive the package (aka socket) count with the following
> + * formula:
> + *
> + *   DIV_ROUND_UP(@max_cpus, @dies * @cores * @threads)
> + *
> + * Firmware can derive APIC ID field widths and offsets per the standard
> + * calculations in "include/hw/i386/topology.h".
> + */
> +typedef struct FWCfgX86Topology {
> +  uint32_t dies;
> +  uint32_t cores;
> +  uint32_t threads;
> +  uint32_t max_cpus;
> +} QEMU_PACKED FWCfgX86Topology;
> +
>  FWCfgState *fw_cfg_arch_create(MachineState *ms,
> 

Re: [PATCH v1 28/28] target/riscv: Allow enabling the Hypervisor extension

2019-10-08 Thread Palmer Dabbelt

On Fri, 23 Aug 2019 16:39:03 PDT (-0700), Alistair Francis wrote:

Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.c | 5 +
 target/riscv/cpu.h | 1 +
 2 files changed, 6 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 06ee551ebe..39e1c130df 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -447,6 +447,9 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 if (cpu->cfg.ext_u) {
 target_misa |= RVU;
 }
+if (cpu->cfg.ext_h) {
+target_misa |= RVH;
+}

 set_misa(env, RVXLEN | target_misa);
 }
@@ -493,6 +496,8 @@ static Property riscv_cpu_properties[] = {
 DEFINE_PROP_BOOL("c", RISCVCPU, cfg.ext_c, true),
 DEFINE_PROP_BOOL("s", RISCVCPU, cfg.ext_s, true),
 DEFINE_PROP_BOOL("u", RISCVCPU, cfg.ext_u, true),
+/* This is experimental so mark with 'x-' */
+DEFINE_PROP_BOOL("x-h", RISCVCPU, cfg.ext_h, false),
 DEFINE_PROP_BOOL("Counters", RISCVCPU, cfg.ext_counters, true),
 DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
 DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index b63f1f3cdc..500496a3be 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -268,6 +268,7 @@ typedef struct RISCVCPU {
 bool ext_c;
 bool ext_s;
 bool ext_u;
+bool ext_h;
 bool ext_counters;
 bool ext_ifencei;
 bool ext_icsr;


Reviewed-by: Palmer Dabbelt 



Re: [PATCH v9 09/13] Adding info [tb-list|tb] commands to HMP (WIP)

2019-10-08 Thread Richard Henderson
On 10/7/19 11:28 AM, Alex Bennée wrote:
> From: "Vanderson M. do Rosario" 
> 
> These commands allow the exploration of TBs generated by the TCG.
> Understand which one hotter, with more guest/host instructions... and
> examine their guest, host and IR code.
> 
> The goal of this command is to allow the dynamic exploration of TCG
> behavior and code quality. Therefore, for now, a corresponding QMP
> command is not worthwhile.
> 
> [AJB: WIP - we still can't be safely sure a translation will succeed]
> 
> Example of output:
> 
> TB id:1 | phys:0x34d54 virt:0x00034d54 flags:0xf0
>   | exec:4828932/0 guest inst cov:16.38%
>   | trans:1 ints: g:3 op:82 op_opt:34 spills:3
>   | h/g (host bytes / guest insts): 90.64
>   | time to gen at 2.4GHz => code:3150.83(ns) IR:712.08(ns)
>   | targets: 0x00034d5e (id:11), 0x00034d0d (id:2)
> 
> TB id:2 | phys:0x34d0d virt:0x00034d0d flags:0xf0
>   | exec:4825842/0 guest inst cov:21.82%
>   | trans:1 ints: g:4 op:80 op_opt:38 spills:2
>   | h/g (host bytes / guest insts): 84.00
>   | time to gen at 2.4GHz => code:3362.92(ns) IR:793.75(ns)
>   | targets: 0x00034d19 (id:12), 0x00034d54 (id:1)
> 
> TB id:2 | phys:0x34d0d virt:0x00034d0d flags:0xf0
>   | exec:6956495/0  guest inst cov:21.82%
>   | trans:2 ints: g:2 op:40 op_opt:19 spills:1
>   | h/g (host bytes / guest insts): 84.00
>   | time to gen at 2.4GHz => code:3130.83(ns) IR:722.50(ns)
>   | targets: 0x00034d19 (id:12), 0x00034d54 (id:1)
> 
> 
> IN:
> 0x00034d0d:  89 demovl %ebx, %esi
> 0x00034d0f:  26 8b 0e movl %es:(%esi), %ecx
> 0x00034d12:  26 f6 46 08 80   testb$0x80, %es:8(%esi)
> 0x00034d17:  75 3bjne  0x34d54
> 
> --
> 
> TB id:1 | phys:0x34d54 virt:0x00034d54 flags:0xf0
>   | exec:5202686/0 guest inst cov:11.28%
>   | trans:1 ints: g:3 op:82 op_opt:34 spills:3
>   | h/g (host bytes / guest insts): 90.64
>   | time to gen at 2.4GHz => code:2793.75(ns) IR:614.58(ns)
>   | targets: 0x00034d5e (id:3), 0x00034d0d (id:2)
> 
> TB id:2 | phys:0x34d0d virt:0x00034d0d flags:0xf0
>   | exec:5199468/0 guest inst cov:15.03%
>   | trans:1 ints: g:4 op:80 op_opt:38 spills:2
>   | h/g (host bytes / guest insts): 84.00
>   | time to gen at 2.4GHz => code:2958.75(ns) IR:719.58(ns)
>   | targets: 0x00034d19 (id:4), 0x00034d54 (id:1)
> 
> --
> 2 TBs to reach 25% of guest inst exec coverage
> Total of guest insts exec: 138346727
> 

Is there too much cut-and-paste in this commit message?
I certainly hope that identical information about TB id:2
is not output 3 times within the same report...

Or, alternately, that we are not generating multiple TBs
for the { phys:0x34d0d virt:0x34d0d flags:0xf0 } tuple.

Also, I think you probably need to output cs_base.  Depending
on the target, that might have been different, and so it
might make sense that you have 3 copies of the above.

> +static gint
> +inverse_sort_tbs(gconstpointer p1, gconstpointer p2, gpointer psort_by)

What about this makes the sort "inverse"?

> +int sort_by = *((int *) psort_by);

Why is this not enum SortBy?

> +if (likely(sort_by == SORT_BY_SPILLS)) {
...
> +} else if (likely(sort_by == SORT_BY_HOTNESS)) {
...
> +} else if (likely(sort_by == SORT_BY_HG)) {

Surely these options are not all "likely".

> +float a =
> +(float) stat_per_translation(tbs1, code.out_len) / 
> tbs1->code.num_guest_inst;
> +float b =
> +(float) stat_per_translation(tbs2, code.out_len) / 
> tbs2->code.num_guest_inst;

I don't understand why we're suddenly introducing floats, when the division
hidden within stat_per_translation is integer.

Think about what units being compared here, because I don't think that "average
host code length / sum of guest insn count" makes sense.  Certainly as time
progresses, average / sum -> ((sum / sum) / sum) -> (sum / sum**2) -> (1 / sum)
is going to approach 0.

I think you actually want "sum of host code length / sum of guest insn length",
which could be stated as "host/guest code ratio" or "jit code expansion factor".

> +c1 = a <= b ? 0 : 1;
> +c2 = a <= b ? 1 : 0;

Please do recall that (x < y ? 1 : 0) => (x < y).

In addition, there's no point in having these comparisons feed...

> +return c1 < c2 ? 1 : c1 == c2 ? 0 : -1;

... these comparisions.

> +for (i = last_search; i; i = i->next) {
> +TBStatistics *tbs = (TBStatistics *) i->data;
> +uint64_t tb_total_execs =
> +(tbs->executions.atomic + tbs->executions.normal) * 
> tbs->code.num_guest_inst;
> +tbs->executions.coverage = (1 * tb_total_execs) / 
> (total_exec_count + 1);

If 

Re: [PATCH 1/3] migration/postcopy: mis->have_listen_thread check will never be touched

2019-10-08 Thread Dr. David Alan Gilbert
* Wei Yang (richardw.y...@linux.intel.com) wrote:
> If mis->have_listen_thread is true, this means current PostcopyState
> must be LISTENING or RUNNING. While the check at the beginning of the
> function makes sure the state transaction happens when its previous
> PostcopyState is ADVISE or DISCARD.
> 
> This means we would never touch this check.
> 
> Signed-off-by: Wei Yang 

Yes, OK - although I think it's OK sometimes to leave in checks
for things you don't expect to happen!


Reviewed-by: Dr. David Alan Gilbert 

> ---
>  migration/savevm.c | 5 -
>  1 file changed, 5 deletions(-)
> 
> diff --git a/migration/savevm.c b/migration/savevm.c
> index feb757de79..eaa4cf58ef 100644
> --- a/migration/savevm.c
> +++ b/migration/savevm.c
> @@ -1878,11 +1878,6 @@ static int 
> loadvm_postcopy_handle_listen(MigrationIncomingState *mis)
>  return -1;
>  }
>  
> -if (mis->have_listen_thread) {
> -error_report("CMD_POSTCOPY_RAM_LISTEN already has a listen thread");
> -return -1;
> -}
> -
>  mis->have_listen_thread = true;
>  /* Start up the listening thread and wait for it to signal ready */
>  qemu_sem_init(>listen_thread_sem, 0);
> -- 
> 2.17.1
> 
--
Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK



Re: [PATCH v1 26/28] target/riscv: Add support for the 32-bit MSTATUSH CSR

2019-10-08 Thread Palmer Dabbelt

On Fri, 23 Aug 2019 16:38:58 PDT (-0700), Alistair Francis wrote:

Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.c|  6 ++
 target/riscv/cpu.h|  7 +++
 target/riscv/cpu_bits.h   |  3 +++
 target/riscv/cpu_helper.c |  7 +++
 target/riscv/csr.c| 23 +++
 target/riscv/op_helper.c  |  4 
 6 files changed, 50 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 371d5845af..06ee551ebe 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -229,6 +229,9 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int 
flags)
 #ifndef CONFIG_USER_ONLY
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", *env->mstatus);
+#ifdef TARGET_RISCV32
+qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatush ", *env->mstatush);
+#endif
 if (riscv_has_ext(env, RVH)) {
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hstatus ", env->hstatus);
 qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "bstatus ", env->vsstatus);
@@ -468,6 +471,9 @@ static void riscv_cpu_init(Object *obj)
 #ifndef CONFIG_USER_ONLY
 env->mie = >mie_novirt;
 env->mstatus = >mstatus_novirt;
+# ifdef TARGET_RISCV32
+env->mstatush = >mstatush_novirt;
+# endif
 #endif
 }

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 05957f32a8..b63f1f3cdc 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -124,6 +124,10 @@ struct CPURISCVState {
 target_ulong mhartid;
 target_ulong *mstatus;

+#ifdef TARGET_RISCV32
+target_ulong *mstatush;
+#endif
+
 /*
  * CAUTION! Unlike the rest of this struct, mip and mip_novirt is accessed
  * asynchonously by I/O threads. It should be read with atomic_read. It 
should
@@ -164,6 +168,9 @@ struct CPURISCVState {
  */
 target_ulong mie_novirt;
 target_ulong mstatus_novirt;
+#ifdef TARGET_RISCV32
+target_ulong mstatush_novirt;
+#endif

 /* Hypervisor CSRs */
 target_ulong hstatus;
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 353fc9a24a..55e20af6d9 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -135,6 +135,9 @@
 #define CSR_MTVEC   0x305
 #define CSR_MCOUNTEREN  0x306

+/* 32-bit only */
+#define CSR_MSTATUSH0x310
+
 /* Legacy Counter Setup (priv v1.9.1) */
 /* Update to #define CSR_MCOUNTINHIBIT 0x320 for 1.11.0 */
 #define CSR_MUCOUNTEREN 0x320
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 0761191f11..8c80486dd0 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -949,10 +949,17 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 if (riscv_cpu_virt_enabled(env)) {
 riscv_cpu_swap_hypervisor_regs(env);
 }
+#ifdef TARGET_RISCV32
+*env->mstatush = set_field(*env->mstatush, MSTATUS_MPV,
+   riscv_cpu_virt_enabled(env));
+*env->mstatush = set_field(*env->mstatush, MSTATUS_MTL,
+   riscv_cpu_force_hs_excep_enabled(env));
+#else
 *env->mstatus = set_field(*env->mstatus, MSTATUS_MPV,
   riscv_cpu_virt_enabled(env));
 *env->mstatus = set_field(*env->mstatus, MSTATUS_MTL,
   riscv_cpu_force_hs_excep_enabled(env));
+#endif

 /* Trapping to M mode, virt is disabled */
 riscv_cpu_set_virt_enabled(env, VIRT_OFF);
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 47be4b1d42..b7d6d009dc 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -364,6 +364,25 @@ static int write_mstatus(CPURISCVState *env, int csrno, 
target_ulong val)
 return 0;
 }

+#ifdef TARGET_RISCV32
+static int read_mstatush(CPURISCVState *env, int csrno, target_ulong *val)
+{
+*val = *env->mstatush;
+return 0;
+}
+
+static int write_mstatush(CPURISCVState *env, int csrno, target_ulong val)
+{
+if ((val ^ *env->mstatush) & (MSTATUS_MPV)) {
+tlb_flush(env_cpu(env));
+}
+
+*env->mstatush = val;


The unsupported bits need to be masked off before writing them in.


+
+return 0;
+}
+#endif
+
 static int read_misa(CPURISCVState *env, int csrno, target_ulong *val)
 {
 *val = env->misa;
@@ -1095,6 +1114,10 @@ static riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 [CSR_MTVEC] =   { any,  read_mtvec,   write_mtvec   },
 [CSR_MCOUNTEREN] =  { any,  read_mcounteren,  write_mcounteren  },

+#if defined(TARGET_RISCV32)
+[CSR_MSTATUSH] ={ any,  read_mstatush,write_mstatush},
+#endif
+
 /* Legacy Counter Setup (priv v1.9.1) */
 [CSR_MUCOUNTEREN] = { any,  read_mucounteren, write_mucounteren },
 [CSR_MSCOUNTEREN] = { any,  read_mscounteren, write_mscounteren },
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 

Re: [PATCH v1 27/28] target/riscv: Add the MSTATUS_MPV_ISSET helper macro

2019-10-08 Thread Palmer Dabbelt

On Fri, 23 Aug 2019 16:39:00 PDT (-0700), Alistair Francis wrote:

Add a helper macro MSTATUS_MPV_ISSET() which will determine if the
MSTATUS_MPV bit is set for both 32-bit and 64-bit RISC-V.

Signed-off-by: Alistair Francis 
---
 target/riscv/cpu_bits.h   | 11 +++
 target/riscv/cpu_helper.c |  4 ++--
 target/riscv/op_helper.c  |  2 +-
 target/riscv/translate.c  |  2 +-
 4 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 55e20af6d9..7056d9218b 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -365,8 +365,19 @@
 #define MSTATUS_TVM 0x0010 /* since: priv-1.10 */
 #define MSTATUS_TW  0x2000 /* since: priv-1.10 */
 #define MSTATUS_TSR 0x4000 /* since: priv-1.10 */
+#if defined(TARGET_RISCV64)
 #define MSTATUS_MTL 0x40ULL
 #define MSTATUS_MPV 0x80ULL
+#elif defined(TARGET_RISCV32)
+#define MSTATUS_MTL 0x0040
+#define MSTATUS_MPV 0x0080
+#endif
+
+#ifdef TARGET_RISCV32
+# define MSTATUS_MPV_ISSET(env)  get_field(*env->mstatush, MSTATUS_MPV)
+#else
+# define MSTATUS_MPV_ISSET(env)  get_field(*env->mstatus, MSTATUS_MPV)
+#endif

 #define MSTATUS64_UXL   0x0003ULL
 #define MSTATUS64_SXL   0x000CULL
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 8c80486dd0..2b88f756bb 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -351,7 +351,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr 
*physical,
 mode = get_field(*env->mstatus, MSTATUS_MPP);

 if (riscv_has_ext(env, RVH) &&
-get_field(*env->mstatus, MSTATUS_MPV)) {
+MSTATUS_MPV_ISSET(env)) {
 use_background = true;
 }
 }
@@ -730,7 +730,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int 
size,
 m_mode_two_stage = env->priv == PRV_M &&
access_type != MMU_INST_FETCH &&
get_field(*env->mstatus, MSTATUS_MPRV) &&
-   get_field(*env->mstatus, MSTATUS_MPV);
+   MSTATUS_MPV_ISSET(env);

 hs_mode_two_stage = env->priv == PRV_S &&
 !riscv_cpu_virt_enabled(env) &&
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 8dec1aee99..6149cd9c15 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -146,7 +146,7 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong 
cpu_pc_deb)

 target_ulong mstatus = *env->mstatus;
 target_ulong prev_priv = get_field(mstatus, MSTATUS_MPP);
-target_ulong prev_virt = get_field(mstatus, MSTATUS_MPV);
+target_ulong prev_virt = MSTATUS_MPV_ISSET(env);
 mstatus = set_field(mstatus,
 env->priv_ver >= PRIV_VERSION_1_10_0 ?
 MSTATUS_MIE : MSTATUS_UIE << prev_priv,
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index ea19ba9c5d..f0d9860429 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -754,7 +754,7 @@ static void riscv_tr_init_disas_context(DisasContextBase 
*dcbase, CPUState *cs)
 ctx->virt_enabled = riscv_cpu_virt_enabled(env);
 if (env->priv_ver == PRV_M &&
 get_field(*env->mstatus, MSTATUS_MPRV) &&
-get_field(*env->mstatus, MSTATUS_MPV)) {
+MSTATUS_MPV_ISSET(env)) {
 ctx->virt_enabled = true;
 } else if (env->priv == PRV_S &&
!riscv_cpu_virt_enabled(env) &&


This should be either ordered before or atomic with the patch that allows 
mstatush.mpv to be set, as otherwise there's point at which QEMU doesn't match 
the ISA.




Re: [PATCH 3/4] hw/i386: add facility to expose CPU topology over fw-cfg

2019-10-08 Thread Laszlo Ersek
On 10/08/19 15:29, Philippe Mathieu-Daudé wrote:
> Hi Laszlo,
> 
> On 10/8/19 12:52 PM, Laszlo Ersek wrote:
>> FW_CFG_MAX_CPUS exposes the (exclusive) maximum APIC ID to guest
>> firmware,
>> due to historical reasons. That value is not useful to edk2, however. For
>> supporting VCPU hotplug, edk2 needs:
>>
>> - the boot CPU count (already exposed in FW_CFG_NB_CPUS),
>>
>> - and the maximum foreseen CPU count (tracked in
>>    "MachineState.smp.max_cpus", but not currently exposed).
>>
>> Add a new fw-cfg file to expose "max_cpus".
>>
>> While at it, expose the rest of the topology too (die / core / thread
>> counts), because I expect that the VCPU hotplug feature for OVMF will
>> ultimately need those too, and the data size is not large. This is
>> slightly complicated by the fact that the die count is specific to
>> PCMachineState, but fw_cfg_arch_create() intends to be PC-independent
>> (see
>> commit 149c50cabcc4).
> 
> The X86 topology is generic to the architecture (not machine specific)
> so it is well placed in fw_cfg_arch_create().

Certainly -- I didn't mean to "complain" in the commit message, just to
point out why I added a new parameter to fw_cfg_arch_create().

Because, my first instinct was to change fw_cfg_arch_create() to simply
take a (PCMachineState*), and then fw_cfg_arch_create() could fetch
whatever it needed, internally.

But, upon finding your commit 149c50cabcc4, I realized that adding a new
parameter was the correct approach (just "slightly complicated" relative
to passing (PCMachineState*) whole-sale.)

To wit, I didn't write "*tries* to be PC-independent", but "*intends* to
be PC-independent". I agree with the intent :)

> 
>>
>> For now, the feature is temporarily disabled.
> 
> I see you enable it in the PC machine in the next patch.
> Do you plan to remove the 'expose_topology' argument and expose the key
> later, or is this comment simply related to this patch?
> 
> Ah, now I see you disable it previous to pc-4.2, OK.

Right, the sentence only refers to the "false" argument in this patch,
for the "expose_topology" parameter.

It took me some time to come up with this solution. I certainly wanted
to separate the feature from the versioned machine type changes. One
approach could have been to introduce the fw_cfg_expose_topology()
function in itself, in a separate patch -- but then bisection would
break at that commit, because gcc doesn't like static functions
(functions with internal linkage) that are never called. So I wanted to
call the new function at once, but short-circuit it too.

(I tend to build patch series at every stage, before posting them.)

> 
>> Cc: "Michael S. Tsirkin" 
>> Cc: Eduardo Habkost 
>> Cc: Igor Mammedov 
>> Cc: Marcel Apfelbaum 
>> Cc: Paolo Bonzini 
>> Cc: Philippe Mathieu-Daudé 
>> Cc: Richard Henderson 
>> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1515
>> Signed-off-by: Laszlo Ersek 
>> ---
>>   hw/i386/fw_cfg.h | 30 +-
>>   hw/i386/fw_cfg.c | 26 --
>>   hw/i386/pc.c |  4 ++--
>>   3 files changed, 55 insertions(+), 5 deletions(-)
>>
>> diff --git a/hw/i386/fw_cfg.h b/hw/i386/fw_cfg.h
>> index e0856a376996..d742435b9793 100644
>> --- a/hw/i386/fw_cfg.h
>> +++ b/hw/i386/fw_cfg.h
>> @@ -18,9 +18,37 @@
>>   #define FW_CFG_E820_TABLE   (FW_CFG_ARCH_LOCAL + 3)
>>   #define FW_CFG_HPET (FW_CFG_ARCH_LOCAL + 4)
>>   +/**
>> + * FWCfgX86Topology: expose the X86 CPU topology to guest firmware
>> over fw-cfg.
>> + *
>> + * All fields have little-endian encoding.
>> + *
>> + * @dies: Number of dies per package (aka socket). Set it to 1
>> unless the
>> + *    concrete MachineState subclass defines it differently.
>> + * @cores:    Corresponds to @CpuTopology.@cores.
>> + * @threads:  Corresponds to @CpuTopology.@threads.
>> + * @max_cpus: Corresponds to @CpuTopology.@max_cpus.
>> + *
>> + * Firmware can derive the package (aka socket) count with the following
>> + * formula:
>> + *
>> + *   DIV_ROUND_UP(@max_cpus, @dies * @cores * @threads)
>> + *
>> + * Firmware can derive APIC ID field widths and offsets per the standard
>> + * calculations in "include/hw/i386/topology.h".
>> + */
>> +typedef struct FWCfgX86Topology {
>> +  uint32_t dies;
>> +  uint32_t cores;
>> +  uint32_t threads;
>> +  uint32_t max_cpus;
>> +} QEMU_PACKED FWCfgX86Topology;
>> +
>>   FWCfgState *fw_cfg_arch_create(MachineState *ms,
>>  uint16_t boot_cpus,
>> -   uint16_t apic_id_limit);
>> +   uint16_t apic_id_limit,
>> +   unsigned smp_dies,
>> +   bool expose_topology);
>>   void fw_cfg_build_smbios(MachineState *ms, FWCfgState *fw_cfg);
>>   void fw_cfg_build_feature_control(MachineState *ms, FWCfgState
>> *fw_cfg);
>>   diff --git a/hw/i386/fw_cfg.c b/hw/i386/fw_cfg.c
>> index 39b6bc60520c..33d09875014f 100644
>> --- a/hw/i386/fw_cfg.c
>> +++ 

Re: [PATCH v4 04/31] error: auto propagated local_err

2019-10-08 Thread Markus Armbruster
Greg Kurz  writes:

> On Tue, 08 Oct 2019 18:03:13 +0200
> Markus Armbruster  wrote:
>
>> Vladimir Sementsov-Ogievskiy  writes:
>> 
>> > Here is introduced ERRP_AUTO_PROPAGATE macro, to be used at start of
>> > functions with errp OUT parameter.
>> >
>> > It has three goals:
>> >
>> > 1. Fix issue with error_fatal & error_prepend/error_append_hint: user
>> > can't see this additional information, because exit() happens in
>> > error_setg earlier than information is added. [Reported by Greg Kurz]
>> >
>> > 2. Fix issue with error_abort & error_propagate: when we wrap
>> > error_abort by local_err+error_propagate, resulting coredump will
>> > refer to error_propagate and not to the place where error happened.
>> > (the macro itself doesn't fix the issue, but it allows to [3.] drop all
>> > local_err+error_propagate pattern, which will definitely fix the issue)
>> > [Reported by Kevin Wolf]
>> >
>> > 3. Drop local_err+error_propagate pattern, which is used to workaround
>> > void functions with errp parameter, when caller wants to know resulting
>> > status. (Note: actually these functions could be merely updated to
>> > return int error code).
>> 
>> Starting with stating your goals is an excellent idea.  But I'd love to
>> next read a high-level description of how your patch achieves or enables
>> achieving these goals.
>> 
>> > Signed-off-by: Vladimir Sementsov-Ogievskiy 
>> > ---
>> [...]
>> > diff --git a/include/qapi/error.h b/include/qapi/error.h
>> > index 9376f59c35..02f967ac1d 100644
>> > --- a/include/qapi/error.h
>> > +++ b/include/qapi/error.h
>> > @@ -322,6 +322,43 @@ void error_set_internal(Error **errp,
>> >  ErrorClass err_class, const char *fmt, ...)
>> >  GCC_FMT_ATTR(6, 7);
>> >  
>> > +typedef struct ErrorPropagator {
>> > +Error *local_err;
>> > +Error **errp;
>> > +} ErrorPropagator;
>> > +
>> > +static inline void error_propagator_cleanup(ErrorPropagator *prop)
>> > +{
>> > +error_propagate(prop->errp, prop->local_err);
>> > +}
>> > +
>> > +G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(ErrorPropagator, 
>> > error_propagator_cleanup);
>> > +
>> > +/*
>> > + * ERRP_AUTO_PROPAGATE
>> > + *
>> > + * This macro is created to be the first line of a function with Error 
>> > **errp
>> > + * OUT parameter. It's needed only in cases where we want to use 
>> > error_prepend,
>> > + * error_append_hint or dereference *errp. It's still safe (but useless) 
>> > in
>> > + * other cases.
>> > + *
>> > + * If errp is NULL or points to error_fatal, it is rewritten to point to a
>> > + * local Error object, which will be automatically propagated to the 
>> > original
>> > + * errp on function exit (see error_propagator_cleanup).
>> > + *
>> > + * After invocation of this macro it is always safe to dereference errp
>> > + * (as it's not NULL anymore) and to append hints (by error_append_hint)
>> > + * (as, if it was error_fatal, we swapped it with a local_error to be
>> > + * propagated on cleanup).
>> 
>> Well, appending hints was always safe, it just didn't work with
>> _fatal.  Don't worry about that now, I'll probably want to polish
>> this contract comment a bit anyway, but later.
>> 
>
> FWIW I've already posted this:
>
> Author: Greg Kurz 
> Date:   Mon Oct 7 15:45:46 2019 +0200
>
> error: Update error_append_hint()'s documenation
> 
> error_setg() and error_propagate(), as well as their variants, cause
> QEMU to terminate when called with _fatal or _abort. This
> prevents to add hints since error_append_hint() isn't even called in
> this case.
> 
> It means that error_append_hint() should only be used with a local
> error object, and then propagate this local error to the caller.
> 
> Document this in  .
> 
> Signed-off-by: Greg Kurz 
>
> Message-id: <156871563702.196432.5964411202152101367.st...@bahia.lan>
> https://patchwork.ozlabs.org/patch/1163278/

I marked your series containing this patch for review.  I decided to
review this one first.  I clearly need look at yours as well before I
can advise on how to proceed.

[...]



Re: [PATCH 2/4] target/i386: remove useless enable_compat_apic_id_mode() prototype

2019-10-08 Thread Laszlo Ersek
On 10/08/19 15:35, Philippe Mathieu-Daudé wrote:
> On 10/8/19 12:52 PM, Laszlo Ersek wrote:
>> The enable_compat_apic_id_mode() function definition was removed earlier;
> 
> "in 457cfcccdd1"

Thanks. I'll add that to the commit message if I need to post a v2.

> 
>> there are no callers left. Remove the function declaration too.
>>
>> Cc: Eduardo Habkost 
>> Cc: Igor Mammedov 
>> Cc: Paolo Bonzini 
>> Cc: Richard Henderson 
>> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1515
>> Signed-off-by: Laszlo Ersek 
>> ---
>>   target/i386/cpu.h | 2 --
>>   1 file changed, 2 deletions(-)
>>
>> diff --git a/target/i386/cpu.h b/target/i386/cpu.h
>> index eaa5395aa539..c9ab1a367939 100644
>> --- a/target/i386/cpu.h
>> +++ b/target/i386/cpu.h
>> @@ -2126,8 +2126,6 @@ void x86_cpu_set_default_version(X86CPUVersion
>> version);
>>   /* Return name of 32-bit register, from a R_* constant */
>>   const char *get_register_name_32(unsigned int reg);
>>   -void enable_compat_apic_id_mode(void);
>> -
>>   #define APIC_DEFAULT_ADDRESS 0xfee0
>>   #define APIC_SPACE_SIZE  0x10
>>  
> 
> Reviewed-by: Philippe Mathieu-Daudé 

Cheers!
Laszlo



Re: [PATCH v2] Makefile: Remove generated files when doing 'distclean' (and 'clean')

2019-10-08 Thread Markus Armbruster
Daniel P. Berrangé  writes:

> Given that we're aiming to convert to meson, how much effort do we really
> want to put into fixing this inconsistency ?
>
> I'd argue the best way to fix "clean" and "distclean" is to delete them
> entirely. Instead enforce that builddir != srcdir when running configure,
> so cleaning up simply means deleting the builddir sub-tree entirely.

I don't wish to belittle anybody's efforts at improving make targets
clean and distclean, but like Daniel, I've long given up on them[*].  My
"make distclean" is "rm -rf BUILD-DIR", and my "make clean" is "nuke-bld
BUILD-DIR", where nuke-bld is the script below.

#!/bin/sh -e

if [ $# -gt 1 ]
then
echo "Usage: $0 [bld-dir]" >&2
exit 1
fi

[ $# -eq 1 ] && cd "$1"

if [ ! -e config.status ]
then
echo "$0: not a build tree" >&2
exit 1
fi

rm -f .config.status
mv config.status .config.status
rm -r *
mv .config.status config.status
./config.status


[*] Along with .gitignore.



Re: [PATCH v9 08/13] tb-stats: reset the tracked TBs on a tb_flush

2019-10-08 Thread Richard Henderson
On 10/7/19 11:28 AM, Alex Bennée wrote:
> We keep track of translations but can only do so up until the
> translation cache is flushed. At that point we really have no idea if
> we can re-create a translation because all the active tracking
> information has been reset.
> 
> Signed-off-by: Alex Bennée 
> ---
>  accel/tcg/tb-stats.c  | 19 +++
>  accel/tcg/translate-all.c |  2 +-
>  include/exec/tb-stats.h   |  8 
>  3 files changed, 28 insertions(+), 1 deletion(-)

I still don't understand what the tbs array is for,
but resetting it at flush is fine.

Reviewed-by: Richard Henderson 


r~



Re: [PATCH 3/4] migration: pass in_postcopy instead of check state again

2019-10-08 Thread Dr. David Alan Gilbert
* Wei Yang (richardw.y...@linux.intel.com) wrote:
> Not necessary to do the check again.
> 
> Signed-off-by: Wei Yang 

Reviewed-by: Dr. David Alan Gilbert 

> ---
>  migration/migration.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/migration/migration.c b/migration/migration.c
> index c8eaa85867..56031305e3 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -3148,8 +3148,7 @@ static MigIterateState 
> migration_iteration_run(MigrationState *s)
>  return MIG_ITERATE_SKIP;
>  }
>  /* Just another iteration step */
> -qemu_savevm_state_iterate(s->to_dst_file,
> -s->state == MIGRATION_STATUS_POSTCOPY_ACTIVE);
> +qemu_savevm_state_iterate(s->to_dst_file, in_postcopy);
>  } else {
>  trace_migration_thread_low_pending(pending_size);
>  migration_completion(s);
> -- 
> 2.17.1
> 
--
Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK



Re: [PATCH v1 25/28] target/riscv: Call the second stage MMU in virtualisation mode

2019-10-08 Thread Palmer Dabbelt

On Fri, 23 Aug 2019 16:38:55 PDT (-0700), Alistair Francis wrote:

The qemu_log_mask(CPU_LOG_MMU,... calls trigger false positive
checkpatch errors which are being ignored.

Signed-off-by: Alistair Francis 
---
 target/riscv/cpu_helper.c | 94 +++
 1 file changed, 86 insertions(+), 8 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 188d5cb39f..0761191f11 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -642,15 +642,23 @@ static void raise_mmu_exception(CPURISCVState *env, 
target_ulong address,
 hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
 {
 RISCVCPU *cpu = RISCV_CPU(cs);
+CPURISCVState *env = >env;
 hwaddr phys_addr;
 int prot;
 int mmu_idx = cpu_mmu_index(>env, false);

-if (get_physical_address(>env, _addr, , addr, 0, mmu_idx,
- true, false)) {
+if (get_physical_address(env, _addr, , addr, 0, mmu_idx,
+ true, riscv_cpu_virt_enabled(env))) {
 return -1;
 }

+if (riscv_cpu_virt_enabled(env)) {
+if (get_physical_address(env, _addr, , phys_addr,
+ 0, mmu_idx, false, true)) {
+return -1;
+}
+}
+
 return phys_addr;
 }

@@ -701,17 +709,35 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int 
size,
 #ifndef CONFIG_USER_ONLY
 RISCVCPU *cpu = RISCV_CPU(cs);
 CPURISCVState *env = >env;
+vaddr im_address;
 hwaddr pa = 0;
 int prot;
 bool pmp_violation = false;
+bool m_mode_two_stage = false;
+bool hs_mode_two_stage = false;
+bool first_stage_error = true;
 int ret = TRANSLATE_FAIL;
 int mode = mmu_idx;

 qemu_log_mask(CPU_LOG_MMU, "%s ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
   __func__, address, access_type, mmu_idx);

-ret = get_physical_address(env, , , address, access_type, mmu_idx,
-   true, false);
+/*
+ * Determine if we are in M mode and MPRV is set or in HS mode and SPRV is
+ * set and we want to access a virtulisation address.
+ */
+if (riscv_has_ext(env, RVH)) {
+m_mode_two_stage = env->priv == PRV_M &&
+   access_type != MMU_INST_FETCH &&
+   get_field(*env->mstatus, MSTATUS_MPRV) &&
+   get_field(*env->mstatus, MSTATUS_MPV);
+
+hs_mode_two_stage = env->priv == PRV_S &&
+!riscv_cpu_virt_enabled(env) &&
+access_type != MMU_INST_FETCH &&
+get_field(env->hstatus, HSTATUS_SPRV) &&
+get_field(env->hstatus, HSTATUS_SPV);
+}

 if (mode == PRV_M && access_type != MMU_INST_FETCH) {
 if (get_field(*env->mstatus, MSTATUS_MPRV)) {
@@ -719,10 +745,58 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int 
size,
 }
 }

-qemu_log_mask(CPU_LOG_MMU,
-  "%s address=%" VADDR_PRIx " ret %d physical " TARGET_FMT_plx
-  " prot %d\n", __func__, address, ret, pa, prot);
+if (riscv_cpu_virt_enabled(env) || m_mode_two_stage || hs_mode_two_stage) {
+/* Two stage lookup */
+ret = get_physical_address(env, , , address, access_type,
+   mmu_idx, true, true);
+
+qemu_log_mask(CPU_LOG_MMU,
+  "%s 1st-stage address=%" VADDR_PRIx " ret %d physical "
+  TARGET_FMT_plx " prot %d\n",
+  __func__, address, ret, pa, prot);
+
+if (ret == TRANSLATE_FAIL) {
+goto tlb_lookup_done;
+}
+
+/* Second stage lookup */
+im_address = pa;

+ret = get_physical_address(env, , , im_address, access_type, 
mmu_idx,
+   false, true);
+
+qemu_log_mask(CPU_LOG_MMU,
+"%s 2nd-stage address=%" VADDR_PRIx " ret %d physical "
+TARGET_FMT_plx " prot %d\n",
+__func__, im_address, ret, pa, prot);
+
+if (riscv_feature(env, RISCV_FEATURE_PMP) &&
+(ret == TRANSLATE_SUCCESS) &&
+!pmp_hart_has_privs(env, pa, size, 1 << access_type, mode)) {
+ret = TRANSLATE_PMP_FAIL;
+}
+
+if (ret != TRANSLATE_SUCCESS) {
+/*
+ * Guest physical address translation failed, this is a HS
+ * level exception
+ */
+first_stage_error = false;
+address = im_address | (address & (TARGET_PAGE_SIZE - 1));
+goto tlb_lookup_done;
+}
+} else {
+/* Single stage lookup */
+ret = get_physical_address(env, , , address, access_type,
+   mmu_idx, true, false);
+
+qemu_log_mask(CPU_LOG_MMU,
+  "%s address=%" VADDR_PRIx " ret %d physical "
+  

Re: [PULL 0/4] Block patches

2019-10-08 Thread Peter Maydell
On Tue, 8 Oct 2019 at 15:55, Stefan Hajnoczi  wrote:
>
> The following changes since commit 560009f2c8b57b7cdd31a5693ea86ab369382f49:
>
>   Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging 
> (2019-10-07 15:40:53 +0100)
>
> are available in the Git repository at:
>
>   https://github.com/stefanha/qemu.git tags/block-pull-request
>
> for you to fetch changes up to 4d804b5305ffb4d5fa414c38d4f1bdfb987c8d0b:
>
>   iotests/262: Switch source/dest VM launch order (2019-10-08 14:28:25 +0100)
>
> 
> Pull request
>
> This pull request also contains the two commits from the previous pull request
> that was dropped due to a mingw compilation error.  The compilation should now
> be fixed.
>
> 
>


Applied, thanks.

Please update the changelog at https://wiki.qemu.org/ChangeLog/4.2
for any user-visible changes.

-- PMM



[PATCH v2 21/21] hw/net/lan9118.c: Switch to transaction-based ptimer API

2019-10-08 Thread Peter Maydell
Switch the cmsdk-apb-watchdog code away from bottom-half based
ptimers to the new transaction-based ptimer API.  This just requires
adding begin/commit calls around the various places that modify the
ptimer state, and using the new ptimer_init() function to create the
timer.

Signed-off-by: Peter Maydell 
---
 hw/net/lan9118.c | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
index 0ea51433dca..ed551f2178b 100644
--- a/hw/net/lan9118.c
+++ b/hw/net/lan9118.c
@@ -21,7 +21,6 @@
 #include "hw/ptimer.h"
 #include "hw/qdev-properties.h"
 #include "qemu/log.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 /* For crc32 */
 #include 
@@ -450,8 +449,10 @@ static void lan9118_reset(DeviceState *d)
 s->e2p_data = 0;
 s->free_timer_start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / 40;
 
+ptimer_transaction_begin(s->timer);
 ptimer_stop(s->timer);
 ptimer_set_count(s->timer, 0x);
+ptimer_transaction_commit(s->timer);
 s->gpt_cfg = 0x;
 
 s->mac_cr = MAC_CR_PRMS;
@@ -1100,6 +1101,7 @@ static void lan9118_writel(void *opaque, hwaddr offset,
 break;
 case CSR_GPT_CFG:
 if ((s->gpt_cfg ^ val) & GPT_TIMER_EN) {
+ptimer_transaction_begin(s->timer);
 if (val & GPT_TIMER_EN) {
 ptimer_set_count(s->timer, val & 0x);
 ptimer_run(s->timer, 0);
@@ -1107,6 +1109,7 @@ static void lan9118_writel(void *opaque, hwaddr offset,
 ptimer_stop(s->timer);
 ptimer_set_count(s->timer, 0x);
 }
+ptimer_transaction_commit(s->timer);
 }
 s->gpt_cfg = val & (GPT_TIMER_EN | 0x);
 break;
@@ -1328,7 +1331,6 @@ static void lan9118_realize(DeviceState *dev, Error 
**errp)
 {
 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 lan9118_state *s = LAN9118(dev);
-QEMUBH *bh;
 int i;
 const MemoryRegionOps *mem_ops =
 s->mode_16bit ? _16bit_mem_ops : _mem_ops;
@@ -1349,10 +1351,11 @@ static void lan9118_realize(DeviceState *dev, Error 
**errp)
 s->pmt_ctrl = 1;
 s->txp = >tx_packet;
 
-bh = qemu_bh_new(lan9118_tick, s);
-s->timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
+s->timer = ptimer_init(lan9118_tick, s, PTIMER_POLICY_DEFAULT);
+ptimer_transaction_begin(s->timer);
 ptimer_set_freq(s->timer, 1);
 ptimer_set_limit(s->timer, 0x, 1);
+ptimer_transaction_commit(s->timer);
 }
 
 static Property lan9118_properties[] = {
-- 
2.20.1




Re: [PATCH 1/4] migration/ram: only possible bit set in invalid_flags is RAM_SAVE_FLAG_COMPRESS_PAGE

2019-10-08 Thread Dr. David Alan Gilbert
* Wei Yang (richardw.y...@linux.intel.com) wrote:
> The only possible bit set in invalid_flags is
> RAM_SAVE_FLAG_COMPRESS_PAGE at the beginning of function
> ram_load_precopy(), which means it is not necessary to do
> another check for RAM_SAVE_FLAG_COMPRESS_PAGE bit.
> 
> Signed-off-by: Wei Yang 
> ---
>  migration/ram.c | 5 +
>  1 file changed, 1 insertion(+), 4 deletions(-)
> 
> diff --git a/migration/ram.c b/migration/ram.c
> index 31051935c8..769d3f6454 100644
> --- a/migration/ram.c
> +++ b/migration/ram.c
> @@ -4263,10 +4263,7 @@ static int ram_load_precopy(QEMUFile *f)
>  addr &= TARGET_PAGE_MASK;
>  
>  if (flags & invalid_flags) {
> -if (flags & invalid_flags & RAM_SAVE_FLAG_COMPRESS_PAGE) {
> -error_report("Received an unexpected compressed page");
> -}
> -
> +error_report("Received an unexpected compressed page");
>  ret = -EINVAL;

I'd rather keep this one; I think Juan's idea is that we might make
other flags illegal here and then it's easy to add to invalid_flags at
the top.

Dave
>  break;
>  }
> -- 
> 2.17.1
> 
--
Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK



[PATCH v2 20/21] hw/watchdog/cmsdk-apb-watchdog.c: Switch to transaction-based ptimer API

2019-10-08 Thread Peter Maydell
Switch the cmsdk-apb-watchdog code away from bottom-half based
ptimers to the new transaction-based ptimer API.  This just requires
adding begin/commit calls around the various places that modify the
ptimer state, and using the new ptimer_init() function to create the
timer.

Signed-off-by: Peter Maydell 
---
 hw/watchdog/cmsdk-apb-watchdog.c | 13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/hw/watchdog/cmsdk-apb-watchdog.c b/hw/watchdog/cmsdk-apb-watchdog.c
index e42c3ebd29d..e6f3b93c44e 100644
--- a/hw/watchdog/cmsdk-apb-watchdog.c
+++ b/hw/watchdog/cmsdk-apb-watchdog.c
@@ -24,7 +24,6 @@
 #include "qemu/log.h"
 #include "trace.h"
 #include "qapi/error.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "sysemu/watchdog.h"
 #include "hw/sysbus.h"
@@ -200,8 +199,10 @@ static void cmsdk_apb_watchdog_write(void *opaque, hwaddr 
offset,
  * Reset the load value and the current count, and make sure
  * we're counting.
  */
+ptimer_transaction_begin(s->timer);
 ptimer_set_limit(s->timer, value, 1);
 ptimer_run(s->timer, 0);
+ptimer_transaction_commit(s->timer);
 break;
 case A_WDOGCONTROL:
 if (s->is_luminary && 0 != (R_WDOGCONTROL_INTEN_MASK & s->control)) {
@@ -217,7 +218,9 @@ static void cmsdk_apb_watchdog_write(void *opaque, hwaddr 
offset,
 break;
 case A_WDOGINTCLR:
 s->intstatus = 0;
+ptimer_transaction_begin(s->timer);
 ptimer_set_count(s->timer, ptimer_get_limit(s->timer));
+ptimer_transaction_commit(s->timer);
 cmsdk_apb_watchdog_update(s);
 break;
 case A_WDOGLOCK:
@@ -299,8 +302,10 @@ static void cmsdk_apb_watchdog_reset(DeviceState *dev)
 s->itop = 0;
 s->resetstatus = 0;
 /* Set the limit and the count */
+ptimer_transaction_begin(s->timer);
 ptimer_set_limit(s->timer, 0x, 1);
 ptimer_run(s->timer, 0);
+ptimer_transaction_commit(s->timer);
 }
 
 static void cmsdk_apb_watchdog_init(Object *obj)
@@ -320,7 +325,6 @@ static void cmsdk_apb_watchdog_init(Object *obj)
 static void cmsdk_apb_watchdog_realize(DeviceState *dev, Error **errp)
 {
 CMSDKAPBWatchdog *s = CMSDK_APB_WATCHDOG(dev);
-QEMUBH *bh;
 
 if (s->wdogclk_frq == 0) {
 error_setg(errp,
@@ -328,14 +332,15 @@ static void cmsdk_apb_watchdog_realize(DeviceState *dev, 
Error **errp)
 return;
 }
 
-bh = qemu_bh_new(cmsdk_apb_watchdog_tick, s);
-s->timer = ptimer_init_with_bh(bh,
+s->timer = ptimer_init(cmsdk_apb_watchdog_tick, s,
PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD |
PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT |
PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
 
+ptimer_transaction_begin(s->timer);
 ptimer_set_freq(s->timer, s->wdogclk_frq);
+ptimer_transaction_commit(s->timer);
 }
 
 static const VMStateDescription cmsdk_apb_watchdog_vmstate = {
-- 
2.20.1




Re: [PATCH 2/2] migration/postcopy: map large zero page in postcopy_ram_incoming_setup()

2019-10-08 Thread Dr. David Alan Gilbert
* Wei Yang (richardw.y...@linux.intel.com) wrote:
> postcopy_ram_incoming_setup() and postcopy_ram_incoming_cleanup() are
> counterpart. It is reasonable to map/unmap large zero page in these two
> functions respectively.
> 
> Signed-off-by: Wei Yang 

Yes, OK.

> ---
>  migration/postcopy-ram.c | 34 +-
>  1 file changed, 17 insertions(+), 17 deletions(-)
> 
> diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c
> index e554f93eec..813cfa5c42 100644
> --- a/migration/postcopy-ram.c
> +++ b/migration/postcopy-ram.c
> @@ -1142,6 +1142,22 @@ int postcopy_ram_incoming_setup(MigrationIncomingState 
> *mis)
>  return -1;
>  }
>  
> +/*
> + * Map large zero page when kernel can't use UFFDIO_ZEROPAGE for 
> hugepages
> + */
> +mis->postcopy_tmp_zero_page = mmap(NULL, mis->largest_page_size,
> +   PROT_READ | PROT_WRITE,
> +   MAP_PRIVATE | MAP_ANONYMOUS,
> +   -1, 0);
> +if (mis->postcopy_tmp_zero_page == MAP_FAILED) {
> +int e = errno;
> +mis->postcopy_tmp_zero_page = NULL;
> +error_report("%s: Failed to map large zero page %s",
> + __func__, strerror(e));
> +return -e;

Note this starts returning -errno where the rest of this function
returns 0 or -1;  returning -errno is a good thing I think and it might
be good to change the other returns.


Reviewed-by: Dr. David Alan Gilbert 

> +}
> +memset(mis->postcopy_tmp_zero_page, '\0', mis->largest_page_size);
> +
>  /*
>   * Ballooning can mark pages as absent while we're postcopying
>   * that would cause false userfaults.
> @@ -1248,23 +1264,7 @@ int postcopy_place_page_zero(MigrationIncomingState 
> *mis, void *host,
> qemu_ram_block_host_offset(rb,
>host));
>  } else {
> -/* The kernel can't use UFFDIO_ZEROPAGE for hugepages */
> -if (!mis->postcopy_tmp_zero_page) {
> -mis->postcopy_tmp_zero_page = mmap(NULL, mis->largest_page_size,
> -   PROT_READ | PROT_WRITE,
> -   MAP_PRIVATE | MAP_ANONYMOUS,
> -   -1, 0);
> -if (mis->postcopy_tmp_zero_page == MAP_FAILED) {
> -int e = errno;
> -mis->postcopy_tmp_zero_page = NULL;
> -error_report("%s: %s mapping large zero page",
> - __func__, strerror(e));
> -return -e;
> -}
> -memset(mis->postcopy_tmp_zero_page, '\0', 
> mis->largest_page_size);
> -}
> -return postcopy_place_page(mis, host, mis->postcopy_tmp_zero_page,
> -   rb);
> +return postcopy_place_page(mis, host, mis->postcopy_tmp_zero_page, 
> rb);
>  }
>  }
>  
> -- 
> 2.17.1
> 
--
Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK



[PATCH v2 19/21] hw/timer/mss-timerc: Switch to transaction-based ptimer API

2019-10-08 Thread Peter Maydell
Switch the mss-timer code away from bottom-half based ptimers to
the new transaction-based ptimer API.  This just requires adding
begin/commit calls around the various places that modify the ptimer
state, and using the new ptimer_init() function to create the timer.

Signed-off-by: Peter Maydell 
---
 include/hw/timer/mss-timer.h |  1 -
 hw/timer/mss-timer.c | 11 ---
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/include/hw/timer/mss-timer.h b/include/hw/timer/mss-timer.h
index d15d1732f81..e5a784b27e4 100644
--- a/include/hw/timer/mss-timer.h
+++ b/include/hw/timer/mss-timer.h
@@ -46,7 +46,6 @@
 #define R_TIM1_MAX6
 
 struct Msf2Timer {
-QEMUBH *bh;
 ptimer_state *ptimer;
 
 uint32_t regs[R_TIM1_MAX];
diff --git a/hw/timer/mss-timer.c b/hw/timer/mss-timer.c
index a34c2402b00..b1c9a805011 100644
--- a/hw/timer/mss-timer.c
+++ b/hw/timer/mss-timer.c
@@ -24,7 +24,6 @@
  */
 
 #include "qemu/osdep.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "qemu/log.h"
 #include "hw/irq.h"
@@ -67,6 +66,7 @@ static void timer_update_irq(struct Msf2Timer *st)
 qemu_set_irq(st->irq, (ier && isr));
 }
 
+/* Must be called from within a ptimer_transaction_begin/commit block */
 static void timer_update(struct Msf2Timer *st)
 {
 uint64_t count;
@@ -159,7 +159,9 @@ timer_write(void *opaque, hwaddr offset,
 switch (addr) {
 case R_TIM_CTRL:
 st->regs[R_TIM_CTRL] = value;
+ptimer_transaction_begin(st->ptimer);
 timer_update(st);
+ptimer_transaction_commit(st->ptimer);
 break;
 
 case R_TIM_RIS:
@@ -171,7 +173,9 @@ timer_write(void *opaque, hwaddr offset,
 case R_TIM_LOADVAL:
 st->regs[R_TIM_LOADVAL] = value;
 if (st->regs[R_TIM_CTRL] & TIMER_CTRL_ENBL) {
+ptimer_transaction_begin(st->ptimer);
 timer_update(st);
+ptimer_transaction_commit(st->ptimer);
 }
 break;
 
@@ -228,9 +232,10 @@ static void mss_timer_init(Object *obj)
 for (i = 0; i < NUM_TIMERS; i++) {
 struct Msf2Timer *st = >timers[i];
 
-st->bh = qemu_bh_new(timer_hit, st);
-st->ptimer = ptimer_init_with_bh(st->bh, PTIMER_POLICY_DEFAULT);
+st->ptimer = ptimer_init(timer_hit, st, PTIMER_POLICY_DEFAULT);
+ptimer_transaction_begin(st->ptimer);
 ptimer_set_freq(st->ptimer, t->freq_hz);
+ptimer_transaction_commit(st->ptimer);
 sysbus_init_irq(SYS_BUS_DEVICE(obj), >irq);
 }
 
-- 
2.20.1




Re: [PATCH 1/2] migration/postcopy: allocate tmp_page in setup stage

2019-10-08 Thread Dr. David Alan Gilbert
* Wei Yang (richardw.y...@linux.intel.com) wrote:
> During migration, a tmp page is allocated so that we could place a whole
> host page during postcopy.
> 
> Currently the page is allocated during load stage, this is a little bit
> late. And more important, if we failed to allocate it, the error is not
> checked properly. Even it is NULL, we would still use it.

Oops, yes.


Reviewed-by: Dr. David Alan Gilbert 

> 
> This patch moves the allocation to setup stage and if failed error
> message would be printed and caller would notice it.
> 
> Signed-off-by: Wei Yang 
> ---
>  migration/postcopy-ram.c | 40 ++--
>  migration/postcopy-ram.h |  7 ---
>  migration/ram.c  |  2 +-
>  3 files changed, 11 insertions(+), 38 deletions(-)
> 
> diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c
> index 51dc164693..e554f93eec 100644
> --- a/migration/postcopy-ram.c
> +++ b/migration/postcopy-ram.c
> @@ -1132,6 +1132,16 @@ int postcopy_ram_incoming_setup(MigrationIncomingState 
> *mis)
>  return -1;
>  }
>  
> +mis->postcopy_tmp_page = mmap(NULL, mis->largest_page_size,
> +  PROT_READ | PROT_WRITE, MAP_PRIVATE |
> +  MAP_ANONYMOUS, -1, 0);
> +if (mis->postcopy_tmp_page == MAP_FAILED) {
> +mis->postcopy_tmp_page = NULL;
> +error_report("%s: Failed to map postcopy_tmp_page %s",
> + __func__, strerror(errno));
> +return -1;
> +}
> +
>  /*
>   * Ballooning can mark pages as absent while we're postcopying
>   * that would cause false userfaults.
> @@ -1258,30 +1268,6 @@ int postcopy_place_page_zero(MigrationIncomingState 
> *mis, void *host,
>  }
>  }
>  
> -/*
> - * Returns a target page of memory that can be mapped at a later point in 
> time
> - * using postcopy_place_page
> - * The same address is used repeatedly, postcopy_place_page just takes the
> - * backing page away.
> - * Returns: Pointer to allocated page
> - *
> - */
> -void *postcopy_get_tmp_page(MigrationIncomingState *mis)
> -{
> -if (!mis->postcopy_tmp_page) {
> -mis->postcopy_tmp_page = mmap(NULL, mis->largest_page_size,
> - PROT_READ | PROT_WRITE, MAP_PRIVATE |
> - MAP_ANONYMOUS, -1, 0);
> -if (mis->postcopy_tmp_page == MAP_FAILED) {
> -mis->postcopy_tmp_page = NULL;
> -error_report("%s: %s", __func__, strerror(errno));
> -return NULL;
> -}
> -}
> -
> -return mis->postcopy_tmp_page;
> -}
> -
>  #else
>  /* No target OS support, stubs just fail */
>  void fill_destination_postcopy_migration_info(MigrationInfo *info)
> @@ -1339,12 +1325,6 @@ int postcopy_place_page_zero(MigrationIncomingState 
> *mis, void *host,
>  return -1;
>  }
>  
> -void *postcopy_get_tmp_page(MigrationIncomingState *mis)
> -{
> -assert(0);
> -return NULL;
> -}
> -
>  int postcopy_wake_shared(struct PostCopyFD *pcfd,
>   uint64_t client_addr,
>   RAMBlock *rb)
> diff --git a/migration/postcopy-ram.h b/migration/postcopy-ram.h
> index e3dde32155..c0ccf64a96 100644
> --- a/migration/postcopy-ram.h
> +++ b/migration/postcopy-ram.h
> @@ -100,13 +100,6 @@ typedef enum {
>  POSTCOPY_INCOMING_END
>  } PostcopyState;
>  
> -/*
> - * Allocate a page of memory that can be mapped at a later point in time
> - * using postcopy_place_page
> - * Returns: Pointer to allocated page
> - */
> -void *postcopy_get_tmp_page(MigrationIncomingState *mis);
> -
>  PostcopyState postcopy_state_get(void);
>  /* Set the state and return the old state */
>  PostcopyState postcopy_state_set(PostcopyState new_state,
> diff --git a/migration/ram.c b/migration/ram.c
> index 4c15162bd6..adbaf0b11a 100644
> --- a/migration/ram.c
> +++ b/migration/ram.c
> @@ -4048,7 +4048,7 @@ static int ram_load_postcopy(QEMUFile *f)
>  bool matches_target_page_size = false;
>  MigrationIncomingState *mis = migration_incoming_get_current();
>  /* Temporary page that is later 'placed' */
> -void *postcopy_host_page = postcopy_get_tmp_page(mis);
> +void *postcopy_host_page = mis->postcopy_tmp_page;
>  void *last_host = NULL;
>  bool all_zero = false;
>  
> -- 
> 2.17.1
> 
--
Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK



[PATCH v2 13/21] hw/timer/exynos4210_mct.c: Switch ltick to transaction-based ptimer API

2019-10-08 Thread Peter Maydell
Switch the ltick ptimer over to the ptimer transaction API.

Signed-off-by: Peter Maydell 
---
 hw/timer/exynos4210_mct.c | 31 +--
 1 file changed, 25 insertions(+), 6 deletions(-)

diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c
index 82803ef9a02..72257584145 100644
--- a/hw/timer/exynos4210_mct.c
+++ b/hw/timer/exynos4210_mct.c
@@ -58,7 +58,6 @@
 #include "hw/sysbus.h"
 #include "migration/vmstate.h"
 #include "qemu/timer.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "hw/ptimer.h"
 
@@ -735,6 +734,7 @@ static uint32_t exynos4210_ltick_int_get_cnto(struct 
tick_timer *s)
 
 /*
  * Start local tick cnt timer.
+ * Must be called within exynos4210_ltick_tx_begin/commit block.
  */
 static void exynos4210_ltick_cnt_start(struct tick_timer *s)
 {
@@ -750,6 +750,7 @@ static void exynos4210_ltick_cnt_start(struct tick_timer *s)
 
 /*
  * Stop local tick cnt timer.
+ * Must be called within exynos4210_ltick_tx_begin/commit block.
  */
 static void exynos4210_ltick_cnt_stop(struct tick_timer *s)
 {
@@ -767,6 +768,18 @@ static void exynos4210_ltick_cnt_stop(struct tick_timer *s)
 }
 }
 
+/* Start ptimer transaction for local tick timer */
+static void exynos4210_ltick_tx_begin(struct tick_timer *s)
+{
+ptimer_transaction_begin(s->ptimer_tick);
+}
+
+/* Commit ptimer transaction for local tick timer */
+static void exynos4210_ltick_tx_commit(struct tick_timer *s)
+{
+ptimer_transaction_commit(s->ptimer_tick);
+}
+
 /*
  * Get counter for CNT timer
  */
@@ -812,6 +825,7 @@ static uint32_t exynos4210_ltick_cnt_get_cnto(struct 
tick_timer *s)
 
 /*
  * Set new values of counters for CNT and INT timers
+ * Must be called within exynos4210_ltick_tx_begin/commit block.
  */
 static void exynos4210_ltick_set_cntb(struct tick_timer *s, uint32_t new_cnt,
 uint32_t new_int)
@@ -885,7 +899,9 @@ static void exynos4210_ltick_recalc_count(struct tick_timer 
*s)
 static void exynos4210_ltick_timer_init(struct tick_timer *s)
 {
 exynos4210_ltick_int_stop(s);
+exynos4210_ltick_tx_begin(s);
 exynos4210_ltick_cnt_stop(s);
+exynos4210_ltick_tx_commit(s);
 
 s->count = 0;
 s->distance = 0;
@@ -995,9 +1011,9 @@ static void exynos4210_mct_update_freq(Exynos4210MCTState 
*s)
 tx_ptimer_set_freq(s->g_timer.ptimer_frc, s->freq);
 
 /* local timer */
-ptimer_set_freq(s->l_timer[0].tick_timer.ptimer_tick, s->freq);
+tx_ptimer_set_freq(s->l_timer[0].tick_timer.ptimer_tick, s->freq);
 tx_ptimer_set_freq(s->l_timer[0].ptimer_frc, s->freq);
-ptimer_set_freq(s->l_timer[1].tick_timer.ptimer_tick, s->freq);
+tx_ptimer_set_freq(s->l_timer[1].tick_timer.ptimer_tick, s->freq);
 tx_ptimer_set_freq(s->l_timer[1].ptimer_frc, s->freq);
 }
 }
@@ -1304,6 +1320,7 @@ static void exynos4210_mct_write(void *opaque, hwaddr 
offset,
 s->l_timer[lt_i].reg.wstat |= L_WSTAT_TCON_WRITE;
 s->l_timer[lt_i].reg.tcon = value;
 
+exynos4210_ltick_tx_begin(>l_timer[lt_i].tick_timer);
 /* Stop local CNT */
 if ((value & L_TCON_TICK_START) <
 (old_val & L_TCON_TICK_START)) {
@@ -1331,6 +1348,7 @@ static void exynos4210_mct_write(void *opaque, hwaddr 
offset,
 DPRINTF("local timer[%d] start int\n", lt_i);
 exynos4210_ltick_int_start(>l_timer[lt_i].tick_timer);
 }
+exynos4210_ltick_tx_commit(>l_timer[lt_i].tick_timer);
 
 /* Start or Stop local FRC if TCON changed */
 exynos4210_lfrc_tx_begin(>l_timer[lt_i]);
@@ -1356,8 +1374,10 @@ static void exynos4210_mct_write(void *opaque, hwaddr 
offset,
  * Due to this we should reload timer to nearest moment when CNT is
  * expired and then in event handler update tcntb to new TCNTB value.
  */
+exynos4210_ltick_tx_begin(>l_timer[lt_i].tick_timer);
 exynos4210_ltick_set_cntb(>l_timer[lt_i].tick_timer, value,
 s->l_timer[lt_i].tick_timer.icntb);
+exynos4210_ltick_tx_commit(>l_timer[lt_i].tick_timer);
 
 s->l_timer[lt_i].reg.wstat |= L_WSTAT_TCNTB_WRITE;
 s->l_timer[lt_i].reg.cnt[L_REG_CNT_TCNTB] = value;
@@ -1486,7 +1506,6 @@ static void exynos4210_mct_init(Object *obj)
 int i;
 Exynos4210MCTState *s = EXYNOS4210_MCT(obj);
 SysBusDevice *dev = SYS_BUS_DEVICE(obj);
-QEMUBH *bh[2];
 
 /* Global timer */
 s->g_timer.ptimer_frc = ptimer_init(exynos4210_gfrc_event, s,
@@ -1495,9 +1514,9 @@ static void exynos4210_mct_init(Object *obj)
 
 /* Local timers */
 for (i = 0; i < 2; i++) {
-bh[0] = qemu_bh_new(exynos4210_ltick_event, >l_timer[i]);
 s->l_timer[i].tick_timer.ptimer_tick =
-ptimer_init_with_bh(bh[0], PTIMER_POLICY_DEFAULT);
+ptimer_init(exynos4210_ltick_event, >l_timer[i],
+PTIMER_POLICY_DEFAULT);
 s->l_timer[i].ptimer_frc =
 

[PATCH v2 18/21] hw/timer/imx_gpt.c: Switch to transaction-based ptimer API

2019-10-08 Thread Peter Maydell
Switch the imx_epit.c code away from bottom-half based ptimers to
the new transaction-based ptimer API.  This just requires adding
begin/commit calls around the various places that modify the ptimer
state, and using the new ptimer_init() function to create the timer.

Signed-off-by: Peter Maydell 
---
 hw/timer/imx_gpt.c | 21 +
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c
index c535d191292..5c0d9a269ce 100644
--- a/hw/timer/imx_gpt.c
+++ b/hw/timer/imx_gpt.c
@@ -16,7 +16,6 @@
 #include "hw/irq.h"
 #include "hw/timer/imx_gpt.h"
 #include "migration/vmstate.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "qemu/log.h"
 
@@ -127,6 +126,7 @@ static const IMXClk imx7_gpt_clocks[] = {
 CLK_NONE,  /* 111 not defined */
 };
 
+/* Must be called from within ptimer_transaction_begin/commit block */
 static void imx_gpt_set_freq(IMXGPTState *s)
 {
 uint32_t clksrc = extract32(s->cr, GPT_CR_CLKSRC_SHIFT, 3);
@@ -167,6 +167,7 @@ static inline uint32_t imx_gpt_find_limit(uint32_t count, 
uint32_t reg,
 return timeout;
 }
 
+/* Must be called from within ptimer_transaction_begin/commit block */
 static void imx_gpt_compute_next_timeout(IMXGPTState *s, bool event)
 {
 uint32_t timeout = GPT_TIMER_MAX;
@@ -313,6 +314,7 @@ static uint64_t imx_gpt_read(void *opaque, hwaddr offset, 
unsigned size)
 
 static void imx_gpt_reset_common(IMXGPTState *s, bool is_soft_reset)
 {
+ptimer_transaction_begin(s->timer);
 /* stop timer */
 ptimer_stop(s->timer);
 
@@ -350,6 +352,7 @@ static void imx_gpt_reset_common(IMXGPTState *s, bool 
is_soft_reset)
 if (s->freq && (s->cr & GPT_CR_EN)) {
 ptimer_run(s->timer, 1);
 }
+ptimer_transaction_commit(s->timer);
 }
 
 static void imx_gpt_soft_reset(DeviceState *dev)
@@ -382,6 +385,7 @@ static void imx_gpt_write(void *opaque, hwaddr offset, 
uint64_t value,
 imx_gpt_soft_reset(DEVICE(s));
 } else {
 /* set our freq, as the source might have changed */
+ptimer_transaction_begin(s->timer);
 imx_gpt_set_freq(s);
 
 if ((oldreg ^ s->cr) & GPT_CR_EN) {
@@ -397,12 +401,15 @@ static void imx_gpt_write(void *opaque, hwaddr offset, 
uint64_t value,
 ptimer_stop(s->timer);
 }
 }
+ptimer_transaction_commit(s->timer);
 }
 break;
 
 case 1: /* Prescaler */
 s->pr = value & 0xfff;
+ptimer_transaction_begin(s->timer);
 imx_gpt_set_freq(s);
+ptimer_transaction_commit(s->timer);
 break;
 
 case 2: /* SR */
@@ -414,13 +421,16 @@ static void imx_gpt_write(void *opaque, hwaddr offset, 
uint64_t value,
 s->ir = value & 0x3f;
 imx_gpt_update_int(s);
 
+ptimer_transaction_begin(s->timer);
 imx_gpt_compute_next_timeout(s, false);
+ptimer_transaction_commit(s->timer);
 
 break;
 
 case 4: /* OCR1 -- output compare register */
 s->ocr1 = value;
 
+ptimer_transaction_begin(s->timer);
 /* In non-freerun mode, reset count when this register is written */
 if (!(s->cr & GPT_CR_FRR)) {
 s->next_timeout = GPT_TIMER_MAX;
@@ -429,6 +439,7 @@ static void imx_gpt_write(void *opaque, hwaddr offset, 
uint64_t value,
 
 /* compute the new timeout */
 imx_gpt_compute_next_timeout(s, false);
+ptimer_transaction_commit(s->timer);
 
 break;
 
@@ -436,7 +447,9 @@ static void imx_gpt_write(void *opaque, hwaddr offset, 
uint64_t value,
 s->ocr2 = value;
 
 /* compute the new timeout */
+ptimer_transaction_begin(s->timer);
 imx_gpt_compute_next_timeout(s, false);
+ptimer_transaction_commit(s->timer);
 
 break;
 
@@ -444,7 +457,9 @@ static void imx_gpt_write(void *opaque, hwaddr offset, 
uint64_t value,
 s->ocr3 = value;
 
 /* compute the new timeout */
+ptimer_transaction_begin(s->timer);
 imx_gpt_compute_next_timeout(s, false);
+ptimer_transaction_commit(s->timer);
 
 break;
 
@@ -484,15 +499,13 @@ static void imx_gpt_realize(DeviceState *dev, Error 
**errp)
 {
 IMXGPTState *s = IMX_GPT(dev);
 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
-QEMUBH *bh;
 
 sysbus_init_irq(sbd, >irq);
 memory_region_init_io(>iomem, OBJECT(s), _gpt_ops, s, TYPE_IMX_GPT,
   0x1000);
 sysbus_init_mmio(sbd, >iomem);
 
-bh = qemu_bh_new(imx_gpt_timeout, s);
-s->timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
+s->timer = ptimer_init(imx_gpt_timeout, s, PTIMER_POLICY_DEFAULT);
 }
 
 static void imx_gpt_class_init(ObjectClass *klass, void *data)
-- 
2.20.1




[PATCH v2 15/21] hw/timer/exynos4210_rtc.c: Switch 1Hz ptimer to transaction-based API

2019-10-08 Thread Peter Maydell
Switch the exynos41210_rtc 1Hz ptimer over to the transaction-based
API. (We will switch the other ptimer used by this device in a
separate commit.)

Signed-off-by: Peter Maydell 
---
 hw/timer/exynos4210_rtc.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/hw/timer/exynos4210_rtc.c b/hw/timer/exynos4210_rtc.c
index d5d7c91fb15..b7ae99e9aa7 100644
--- a/hw/timer/exynos4210_rtc.c
+++ b/hw/timer/exynos4210_rtc.c
@@ -401,6 +401,7 @@ static void exynos4210_rtc_write(void *opaque, hwaddr 
offset,
 }
 break;
 case RTCCON:
+ptimer_transaction_begin(s->ptimer_1Hz);
 if (value & RTC_ENABLE) {
 exynos4210_rtc_update_freq(s, value);
 }
@@ -430,6 +431,7 @@ static void exynos4210_rtc_write(void *opaque, hwaddr 
offset,
 ptimer_stop(s->ptimer);
 }
 }
+ptimer_transaction_commit(s->ptimer_1Hz);
 s->reg_rtccon = value;
 break;
 case TICCNT:
@@ -539,7 +541,9 @@ static void exynos4210_rtc_reset(DeviceState *d)
 
 exynos4210_rtc_update_freq(s, s->reg_rtccon);
 ptimer_stop(s->ptimer);
+ptimer_transaction_begin(s->ptimer_1Hz);
 ptimer_stop(s->ptimer_1Hz);
+ptimer_transaction_commit(s->ptimer_1Hz);
 }
 
 static const MemoryRegionOps exynos4210_rtc_ops = {
@@ -562,9 +566,11 @@ static void exynos4210_rtc_init(Object *obj)
 ptimer_set_freq(s->ptimer, RTC_BASE_FREQ);
 exynos4210_rtc_update_freq(s, 0);
 
-bh = qemu_bh_new(exynos4210_rtc_1Hz_tick, s);
-s->ptimer_1Hz = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
+s->ptimer_1Hz = ptimer_init(exynos4210_rtc_1Hz_tick,
+s, PTIMER_POLICY_DEFAULT);
+ptimer_transaction_begin(s->ptimer_1Hz);
 ptimer_set_freq(s->ptimer_1Hz, RTC_BASE_FREQ);
+ptimer_transaction_commit(s->ptimer_1Hz);
 
 sysbus_init_irq(dev, >alm_irq);
 sysbus_init_irq(dev, >tick_irq);
-- 
2.20.1




[PATCH v2 17/21] hw/timer/imx_epit.c: Switch to transaction-based ptimer API

2019-10-08 Thread Peter Maydell
Switch the imx_epit.c code away from bottom-half based ptimers to
the new transaction-based ptimer API.  This just requires adding
begin/commit calls around the various places that modify the ptimer
state, and using the new ptimer_init() function to create the timer.

Signed-off-by: Peter Maydell 
---
 hw/timer/imx_epit.c | 32 +++-
 1 file changed, 27 insertions(+), 5 deletions(-)

diff --git a/hw/timer/imx_epit.c b/hw/timer/imx_epit.c
index 39810ac8b03..baf6338e1a6 100644
--- a/hw/timer/imx_epit.c
+++ b/hw/timer/imx_epit.c
@@ -17,7 +17,6 @@
 #include "migration/vmstate.h"
 #include "hw/irq.h"
 #include "hw/misc/imx_ccm.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "qemu/log.h"
 
@@ -74,6 +73,10 @@ static void imx_epit_update_int(IMXEPITState *s)
 }
 }
 
+/*
+ * Must be called from within a ptimer_transaction_begin/commit block
+ * for both s->timer_cmp and s->timer_reload.
+ */
 static void imx_epit_set_freq(IMXEPITState *s)
 {
 uint32_t clksrc;
@@ -105,6 +108,8 @@ static void imx_epit_reset(DeviceState *dev)
 s->lr = EPIT_TIMER_MAX;
 s->cmp = 0;
 s->cnt = 0;
+ptimer_transaction_begin(s->timer_cmp);
+ptimer_transaction_begin(s->timer_reload);
 /* stop both timers */
 ptimer_stop(s->timer_cmp);
 ptimer_stop(s->timer_reload);
@@ -117,6 +122,8 @@ static void imx_epit_reset(DeviceState *dev)
 /* if the timer is still enabled, restart it */
 ptimer_run(s->timer_reload, 0);
 }
+ptimer_transaction_commit(s->timer_cmp);
+ptimer_transaction_commit(s->timer_reload);
 }
 
 static uint32_t imx_epit_update_count(IMXEPITState *s)
@@ -164,6 +171,7 @@ static uint64_t imx_epit_read(void *opaque, hwaddr offset, 
unsigned size)
 return reg_value;
 }
 
+/* Must be called from ptimer_transaction_begin/commit block for s->timer_cmp 
*/
 static void imx_epit_reload_compare_timer(IMXEPITState *s)
 {
 if ((s->cr & (CR_EN | CR_OCIEN)) == (CR_EN | CR_OCIEN))  {
@@ -191,6 +199,8 @@ static void imx_epit_write(void *opaque, hwaddr offset, 
uint64_t value,
 
 switch (offset >> 2) {
 case 0: /* CR */
+ptimer_transaction_begin(s->timer_cmp);
+ptimer_transaction_begin(s->timer_reload);
 
 oldcr = s->cr;
 s->cr = value & 0x03ff;
@@ -231,6 +241,9 @@ static void imx_epit_write(void *opaque, hwaddr offset, 
uint64_t value,
 } else {
 ptimer_stop(s->timer_cmp);
 }
+
+ptimer_transaction_commit(s->timer_cmp);
+ptimer_transaction_commit(s->timer_reload);
 break;
 
 case 1: /* SR - ACK*/
@@ -244,6 +257,8 @@ static void imx_epit_write(void *opaque, hwaddr offset, 
uint64_t value,
 case 2: /* LR - set ticks */
 s->lr = value;
 
+ptimer_transaction_begin(s->timer_cmp);
+ptimer_transaction_begin(s->timer_reload);
 if (s->cr & CR_RLD) {
 /* Also set the limit if the LRD bit is set */
 /* If IOVW bit is set then set the timer value */
@@ -255,12 +270,16 @@ static void imx_epit_write(void *opaque, hwaddr offset, 
uint64_t value,
 }
 
 imx_epit_reload_compare_timer(s);
+ptimer_transaction_commit(s->timer_cmp);
+ptimer_transaction_commit(s->timer_reload);
 break;
 
 case 3: /* CMP */
 s->cmp = value;
 
+ptimer_transaction_begin(s->timer_cmp);
 imx_epit_reload_compare_timer(s);
+ptimer_transaction_commit(s->timer_cmp);
 
 break;
 
@@ -281,6 +300,11 @@ static void imx_epit_cmp(void *opaque)
 imx_epit_update_int(s);
 }
 
+static void imx_epit_reload(void *opaque)
+{
+/* No action required on rollover of timer_reload */
+}
+
 static const MemoryRegionOps imx_epit_ops = {
 .read = imx_epit_read,
 .write = imx_epit_write,
@@ -308,7 +332,6 @@ static void imx_epit_realize(DeviceState *dev, Error **errp)
 {
 IMXEPITState *s = IMX_EPIT(dev);
 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
-QEMUBH *bh;
 
 DPRINTF("\n");
 
@@ -317,10 +340,9 @@ static void imx_epit_realize(DeviceState *dev, Error 
**errp)
   0x1000);
 sysbus_init_mmio(sbd, >iomem);
 
-s->timer_reload = ptimer_init_with_bh(NULL, PTIMER_POLICY_DEFAULT);
+s->timer_reload = ptimer_init(imx_epit_reload, s, PTIMER_POLICY_DEFAULT);
 
-bh = qemu_bh_new(imx_epit_cmp, s);
-s->timer_cmp = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
+s->timer_cmp = ptimer_init(imx_epit_cmp, s, PTIMER_POLICY_DEFAULT);
 }
 
 static void imx_epit_class_init(ObjectClass *klass, void *data)
-- 
2.20.1




[PATCH v2 12/21] hw/timer/exynos4210_mct.c: Switch LFRC to transaction-based ptimer API

2019-10-08 Thread Peter Maydell
Switch the exynos MCT LFRC timers over to the ptimer transaction API.

Signed-off-by: Peter Maydell 
---
 hw/timer/exynos4210_mct.c | 27 +++
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c
index fcf91c75cc5..82803ef9a02 100644
--- a/hw/timer/exynos4210_mct.c
+++ b/hw/timer/exynos4210_mct.c
@@ -608,6 +608,7 @@ static uint64_t exynos4210_lfrc_get_count(Exynos4210MCTLT 
*s)
 
 /*
  * Set counter of FRC local timer.
+ * Must be called from within exynos4210_lfrc_tx_begin/commit block.
  */
 static void exynos4210_lfrc_update_count(Exynos4210MCTLT *s)
 {
@@ -620,6 +621,7 @@ static void exynos4210_lfrc_update_count(Exynos4210MCTLT *s)
 
 /*
  * Start local FRC timer
+ * Must be called from within exynos4210_lfrc_tx_begin/commit block.
  */
 static void exynos4210_lfrc_start(Exynos4210MCTLT *s)
 {
@@ -628,12 +630,25 @@ static void exynos4210_lfrc_start(Exynos4210MCTLT *s)
 
 /*
  * Stop local FRC timer
+ * Must be called from within exynos4210_lfrc_tx_begin/commit block.
  */
 static void exynos4210_lfrc_stop(Exynos4210MCTLT *s)
 {
 ptimer_stop(s->ptimer_frc);
 }
 
+/* Start ptimer transaction for local FRC timer */
+static void exynos4210_lfrc_tx_begin(Exynos4210MCTLT *s)
+{
+ptimer_transaction_begin(s->ptimer_frc);
+}
+
+/* Commit ptimer transaction for local FRC timer */
+static void exynos4210_lfrc_tx_commit(Exynos4210MCTLT *s)
+{
+ptimer_transaction_commit(s->ptimer_frc);
+}
+
 /*
  * Local timer free running counter tick handler
  */
@@ -981,9 +996,9 @@ static void exynos4210_mct_update_freq(Exynos4210MCTState 
*s)
 
 /* local timer */
 ptimer_set_freq(s->l_timer[0].tick_timer.ptimer_tick, s->freq);
-ptimer_set_freq(s->l_timer[0].ptimer_frc, s->freq);
+tx_ptimer_set_freq(s->l_timer[0].ptimer_frc, s->freq);
 ptimer_set_freq(s->l_timer[1].tick_timer.ptimer_tick, s->freq);
-ptimer_set_freq(s->l_timer[1].ptimer_frc, s->freq);
+tx_ptimer_set_freq(s->l_timer[1].ptimer_frc, s->freq);
 }
 }
 
@@ -1012,7 +1027,9 @@ static void exynos4210_mct_reset(DeviceState *d)
 s->l_timer[i].tick_timer.count = 0;
 s->l_timer[i].tick_timer.distance = 0;
 s->l_timer[i].tick_timer.progress = 0;
+exynos4210_lfrc_tx_begin(>l_timer[i]);
 ptimer_stop(s->l_timer[i].ptimer_frc);
+exynos4210_lfrc_tx_commit(>l_timer[i]);
 
 exynos4210_ltick_timer_init(>l_timer[i].tick_timer);
 }
@@ -1316,6 +1333,7 @@ static void exynos4210_mct_write(void *opaque, hwaddr 
offset,
 }
 
 /* Start or Stop local FRC if TCON changed */
+exynos4210_lfrc_tx_begin(>l_timer[lt_i]);
 if ((value & L_TCON_FRC_START) >
 (s->l_timer[lt_i].reg.tcon & L_TCON_FRC_START)) {
 DPRINTF("local timer[%d] start frc\n", lt_i);
@@ -1326,6 +1344,7 @@ static void exynos4210_mct_write(void *opaque, hwaddr 
offset,
 DPRINTF("local timer[%d] stop frc\n", lt_i);
 exynos4210_lfrc_stop(>l_timer[lt_i]);
 }
+exynos4210_lfrc_tx_commit(>l_timer[lt_i]);
 break;
 
 case L0_TCNTB: case L1_TCNTB:
@@ -1477,11 +1496,11 @@ static void exynos4210_mct_init(Object *obj)
 /* Local timers */
 for (i = 0; i < 2; i++) {
 bh[0] = qemu_bh_new(exynos4210_ltick_event, >l_timer[i]);
-bh[1] = qemu_bh_new(exynos4210_lfrc_event, >l_timer[i]);
 s->l_timer[i].tick_timer.ptimer_tick =
 ptimer_init_with_bh(bh[0], PTIMER_POLICY_DEFAULT);
 s->l_timer[i].ptimer_frc =
-ptimer_init_with_bh(bh[1], PTIMER_POLICY_DEFAULT);
+ptimer_init(exynos4210_lfrc_event, >l_timer[i],
+PTIMER_POLICY_DEFAULT);
 s->l_timer[i].id = i;
 }
 
-- 
2.20.1




[PATCH v2 16/21] hw/timer/exynos4210_rtc.c: Switch main ptimer to transaction-based API

2019-10-08 Thread Peter Maydell
Switch the exynos41210_rtc main ptimer over to the transaction-based
API, completing the transition for this device.

Signed-off-by: Peter Maydell 
---
 hw/timer/exynos4210_rtc.c | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/hw/timer/exynos4210_rtc.c b/hw/timer/exynos4210_rtc.c
index b7ae99e9aa7..f85483a07f8 100644
--- a/hw/timer/exynos4210_rtc.c
+++ b/hw/timer/exynos4210_rtc.c
@@ -28,7 +28,6 @@
 #include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "qemu/log.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "hw/sysbus.h"
 #include "migration/vmstate.h"
@@ -195,6 +194,7 @@ static void check_alarm_raise(Exynos4210RTCState *s)
  * RTC update frequency
  * Parameters:
  * reg_value - current RTCCON register or his new value
+ * Must be called within a ptimer_transaction_begin/commit block for s->ptimer.
  */
 static void exynos4210_rtc_update_freq(Exynos4210RTCState *s,
uint32_t reg_value)
@@ -402,6 +402,7 @@ static void exynos4210_rtc_write(void *opaque, hwaddr 
offset,
 break;
 case RTCCON:
 ptimer_transaction_begin(s->ptimer_1Hz);
+ptimer_transaction_begin(s->ptimer);
 if (value & RTC_ENABLE) {
 exynos4210_rtc_update_freq(s, value);
 }
@@ -432,6 +433,7 @@ static void exynos4210_rtc_write(void *opaque, hwaddr 
offset,
 }
 }
 ptimer_transaction_commit(s->ptimer_1Hz);
+ptimer_transaction_commit(s->ptimer);
 s->reg_rtccon = value;
 break;
 case TICCNT:
@@ -539,8 +541,10 @@ static void exynos4210_rtc_reset(DeviceState *d)
 
 s->reg_curticcnt = 0;
 
+ptimer_transaction_begin(s->ptimer);
 exynos4210_rtc_update_freq(s, s->reg_rtccon);
 ptimer_stop(s->ptimer);
+ptimer_transaction_commit(s->ptimer);
 ptimer_transaction_begin(s->ptimer_1Hz);
 ptimer_stop(s->ptimer_1Hz);
 ptimer_transaction_commit(s->ptimer_1Hz);
@@ -559,12 +563,12 @@ static void exynos4210_rtc_init(Object *obj)
 {
 Exynos4210RTCState *s = EXYNOS4210_RTC(obj);
 SysBusDevice *dev = SYS_BUS_DEVICE(obj);
-QEMUBH *bh;
 
-bh = qemu_bh_new(exynos4210_rtc_tick, s);
-s->ptimer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
+s->ptimer = ptimer_init(exynos4210_rtc_tick, s, PTIMER_POLICY_DEFAULT);
+ptimer_transaction_begin(s->ptimer);
 ptimer_set_freq(s->ptimer, RTC_BASE_FREQ);
 exynos4210_rtc_update_freq(s, 0);
+ptimer_transaction_commit(s->ptimer);
 
 s->ptimer_1Hz = ptimer_init(exynos4210_rtc_1Hz_tick,
 s, PTIMER_POLICY_DEFAULT);
-- 
2.20.1




[PATCH v2 11/21] hw/timer/exynos4210_mct.c: Switch GFRC to transaction-based ptimer API

2019-10-08 Thread Peter Maydell
We want to switch the exynos MCT code away from bottom-half based ptimers to
the new transaction-based ptimer API. The MCT is complicated
and uses multiple different ptimers, so it's clearer to switch
it a piece at a time. Here we change over only the GFRC.

Signed-off-by: Peter Maydell 
---
 hw/timer/exynos4210_mct.c | 48 ---
 1 file changed, 45 insertions(+), 3 deletions(-)

diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c
index 9f2e8dd0a42..fcf91c75cc5 100644
--- a/hw/timer/exynos4210_mct.c
+++ b/hw/timer/exynos4210_mct.c
@@ -364,6 +364,7 @@ static void exynos4210_mct_update_freq(Exynos4210MCTState 
*s);
 
 /*
  * Set counter of FRC global timer.
+ * Must be called within exynos4210_gfrc_tx_begin/commit block.
  */
 static void exynos4210_gfrc_set_count(Exynos4210MCTGT *s, uint64_t count)
 {
@@ -385,6 +386,7 @@ static uint64_t exynos4210_gfrc_get_count(Exynos4210MCTGT 
*s)
 
 /*
  * Stop global FRC timer
+ * Must be called within exynos4210_gfrc_tx_begin/commit block.
  */
 static void exynos4210_gfrc_stop(Exynos4210MCTGT *s)
 {
@@ -395,6 +397,7 @@ static void exynos4210_gfrc_stop(Exynos4210MCTGT *s)
 
 /*
  * Start global FRC timer
+ * Must be called within exynos4210_gfrc_tx_begin/commit block.
  */
 static void exynos4210_gfrc_start(Exynos4210MCTGT *s)
 {
@@ -403,6 +406,21 @@ static void exynos4210_gfrc_start(Exynos4210MCTGT *s)
 ptimer_run(s->ptimer_frc, 1);
 }
 
+/*
+ * Start ptimer transaction for global FRC timer; this is just for
+ * consistency with the way we wrap operations like stop and run.
+ */
+static void exynos4210_gfrc_tx_begin(Exynos4210MCTGT *s)
+{
+ptimer_transaction_begin(s->ptimer_frc);
+}
+
+/* Commit ptimer transaction for global FRC timer. */
+static void exynos4210_gfrc_tx_commit(Exynos4210MCTGT *s)
+{
+ptimer_transaction_commit(s->ptimer_frc);
+}
+
 /*
  * Find next nearest Comparator. If current Comparator value equals to other
  * Comparator value, skip them both
@@ -492,6 +510,7 @@ static uint64_t 
exynos4210_gcomp_get_distance(Exynos4210MCTState *s, int32_t id)
 
 /*
  * Restart global FRC timer
+ * Must be called within exynos4210_gfrc_tx_begin/commit block.
  */
 static void exynos4210_gfrc_restart(Exynos4210MCTState *s)
 {
@@ -933,6 +952,19 @@ static void exynos4210_ltick_event(void *opaque)
 exynos4210_ltick_int_start(>tick_timer);
 }
 
+static void tx_ptimer_set_freq(ptimer_state *s, uint32_t freq)
+{
+/*
+ * callers of exynos4210_mct_update_freq() never do anything
+ * else that needs to be in the same ptimer transaction, so
+ * to avoid a lot of repetition we have a convenience function
+ * for begin/set_freq/commit.
+ */
+ptimer_transaction_begin(s);
+ptimer_set_freq(s, freq);
+ptimer_transaction_commit(s);
+}
+
 /* update timer frequency */
 static void exynos4210_mct_update_freq(Exynos4210MCTState *s)
 {
@@ -945,7 +977,7 @@ static void exynos4210_mct_update_freq(Exynos4210MCTState 
*s)
 DPRINTF("freq=%dHz\n", s->freq);
 
 /* global timer */
-ptimer_set_freq(s->g_timer.ptimer_frc, s->freq);
+tx_ptimer_set_freq(s->g_timer.ptimer_frc, s->freq);
 
 /* local timer */
 ptimer_set_freq(s->l_timer[0].tick_timer.ptimer_tick, s->freq);
@@ -965,7 +997,9 @@ static void exynos4210_mct_reset(DeviceState *d)
 
 /* global timer */
 memset(>g_timer.reg, 0, sizeof(s->g_timer.reg));
+exynos4210_gfrc_tx_begin(>g_timer);
 exynos4210_gfrc_stop(>g_timer);
+exynos4210_gfrc_tx_commit(>g_timer);
 
 /* local timer */
 memset(s->l_timer[0].reg.cnt, 0, sizeof(s->l_timer[0].reg.cnt));
@@ -1144,7 +1178,9 @@ static void exynos4210_mct_write(void *opaque, hwaddr 
offset,
 }
 
 s->g_timer.reg.cnt = new_frc;
+exynos4210_gfrc_tx_begin(>g_timer);
 exynos4210_gfrc_restart(s);
+exynos4210_gfrc_tx_commit(>g_timer);
 break;
 
 case G_CNT_WSTAT:
@@ -1168,7 +1204,9 @@ static void exynos4210_mct_write(void *opaque, hwaddr 
offset,
 s->g_timer.reg.wstat |= G_WSTAT_COMP_L(index);
 }
 
+exynos4210_gfrc_tx_begin(>g_timer);
 exynos4210_gfrc_restart(s);
+exynos4210_gfrc_tx_commit(>g_timer);
 break;
 
 case G_TCON:
@@ -1178,6 +1216,8 @@ static void exynos4210_mct_write(void *opaque, hwaddr 
offset,
 
 DPRINTF("global timer write to reg.g_tcon %llx\n", value);
 
+exynos4210_gfrc_tx_begin(>g_timer);
+
 /* Start FRC if transition from disabled to enabled */
 if ((value & G_TCON_TIMER_ENABLE) > (old_val &
 G_TCON_TIMER_ENABLE)) {
@@ -1195,6 +1235,8 @@ static void exynos4210_mct_write(void *opaque, hwaddr 
offset,
 exynos4210_gfrc_restart(s);
 }
 }
+
+exynos4210_gfrc_tx_commit(>g_timer);
 break;
 
 case G_INT_CSTAT:
@@ -1428,8 +1470,8 @@ static void exynos4210_mct_init(Object *obj)
 QEMUBH *bh[2];
 
 /* Global timer */
-  

[PATCH v2 14/21] hw/timer/exynos4210_pwm.c: Switch to transaction-based ptimer API

2019-10-08 Thread Peter Maydell
Switch the exynos4210_pwm code away from bottom-half based ptimers to
the new transaction-based ptimer API.  This just requires adding
begin/commit calls around the various places that modify the ptimer
state, and using the new ptimer_init() function to create the timer.

Signed-off-by: Peter Maydell 
---
 hw/timer/exynos4210_pwm.c | 17 -
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/hw/timer/exynos4210_pwm.c b/hw/timer/exynos4210_pwm.c
index aa5dca68ef7..59a8c08db0f 100644
--- a/hw/timer/exynos4210_pwm.c
+++ b/hw/timer/exynos4210_pwm.c
@@ -25,7 +25,6 @@
 #include "hw/sysbus.h"
 #include "migration/vmstate.h"
 #include "qemu/timer.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "hw/ptimer.h"
 
@@ -150,7 +149,9 @@ static const VMStateDescription 
vmstate_exynos4210_pwm_state = {
 };
 
 /*
- * PWM update frequency
+ * PWM update frequency.
+ * Must be called within a ptimer_transaction_begin/commit block
+ * for s->timer[id].ptimer.
  */
 static void exynos4210_pwm_update_freq(Exynos4210PWMState *s, uint32_t id)
 {
@@ -281,12 +282,15 @@ static void exynos4210_pwm_write(void *opaque, hwaddr 
offset,
 
 /* update timers frequencies */
 for (i = 0; i < EXYNOS4210_PWM_TIMERS_NUM; i++) {
+ptimer_transaction_begin(s->timer[i].ptimer);
 exynos4210_pwm_update_freq(s, s->timer[i].id);
+ptimer_transaction_commit(s->timer[i].ptimer);
 }
 break;
 
 case TCON:
 for (i = 0; i < EXYNOS4210_PWM_TIMERS_NUM; i++) {
+ptimer_transaction_begin(s->timer[i].ptimer);
 if ((value & TCON_TIMER_MANUAL_UPD(i)) >
 (s->reg_tcon & TCON_TIMER_MANUAL_UPD(i))) {
 /*
@@ -315,6 +319,7 @@ static void exynos4210_pwm_write(void *opaque, hwaddr 
offset,
 ptimer_stop(s->timer[i].ptimer);
 DPRINTF("stop timer %d\n", i);
 }
+ptimer_transaction_commit(s->timer[i].ptimer);
 }
 s->reg_tcon = value;
 break;
@@ -369,8 +374,10 @@ static void exynos4210_pwm_reset(DeviceState *d)
 s->timer[i].reg_tcmpb = 0;
 s->timer[i].reg_tcntb = 0;
 
+ptimer_transaction_begin(s->timer[i].ptimer);
 exynos4210_pwm_update_freq(s, s->timer[i].id);
 ptimer_stop(s->timer[i].ptimer);
+ptimer_transaction_commit(s->timer[i].ptimer);
 }
 }
 
@@ -388,12 +395,12 @@ static void exynos4210_pwm_init(Object *obj)
 Exynos4210PWMState *s = EXYNOS4210_PWM(obj);
 SysBusDevice *dev = SYS_BUS_DEVICE(obj);
 int i;
-QEMUBH *bh;
 
 for (i = 0; i < EXYNOS4210_PWM_TIMERS_NUM; i++) {
-bh = qemu_bh_new(exynos4210_pwm_tick, >timer[i]);
 sysbus_init_irq(dev, >timer[i].irq);
-s->timer[i].ptimer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
+s->timer[i].ptimer = ptimer_init(exynos4210_pwm_tick,
+ >timer[i],
+ PTIMER_POLICY_DEFAULT);
 s->timer[i].id = i;
 s->timer[i].parent = s;
 }
-- 
2.20.1




[PATCH v2 10/21] hw/timer/digic-timer.c: Switch to transaction-based ptimer API

2019-10-08 Thread Peter Maydell
Switch the digic-timer.c code away from bottom-half based ptimers to
the new transaction-based ptimer API.  This just requires adding
begin/commit calls around the various places that modify the ptimer
state, and using the new ptimer_init() function to create the timer.

Signed-off-by: Peter Maydell 
---
 hw/timer/digic-timer.c | 16 ++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/hw/timer/digic-timer.c b/hw/timer/digic-timer.c
index b111e1fe643..32612228daf 100644
--- a/hw/timer/digic-timer.c
+++ b/hw/timer/digic-timer.c
@@ -29,7 +29,6 @@
 #include "qemu/osdep.h"
 #include "hw/sysbus.h"
 #include "hw/ptimer.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "qemu/log.h"
 
@@ -52,7 +51,9 @@ static void digic_timer_reset(DeviceState *dev)
 {
 DigicTimerState *s = DIGIC_TIMER(dev);
 
+ptimer_transaction_begin(s->ptimer);
 ptimer_stop(s->ptimer);
+ptimer_transaction_commit(s->ptimer);
 s->control = 0;
 s->relvalue = 0;
 }
@@ -93,16 +94,20 @@ static void digic_timer_write(void *opaque, hwaddr offset,
 break;
 }
 
+ptimer_transaction_begin(s->ptimer);
 if (value & DIGIC_TIMER_CONTROL_EN) {
 ptimer_run(s->ptimer, 0);
 }
 
 s->control = (uint32_t)value;
+ptimer_transaction_commit(s->ptimer);
 break;
 
 case DIGIC_TIMER_RELVALUE:
 s->relvalue = extract32(value, 0, 16);
+ptimer_transaction_begin(s->ptimer);
 ptimer_set_limit(s->ptimer, s->relvalue, 1);
+ptimer_transaction_commit(s->ptimer);
 break;
 
 case DIGIC_TIMER_VALUE:
@@ -125,17 +130,24 @@ static const MemoryRegionOps digic_timer_ops = {
 .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
+static void digic_timer_tick(void *opaque)
+{
+/* Nothing to do on timer rollover */
+}
+
 static void digic_timer_init(Object *obj)
 {
 DigicTimerState *s = DIGIC_TIMER(obj);
 
-s->ptimer = ptimer_init_with_bh(NULL, PTIMER_POLICY_DEFAULT);
+s->ptimer = ptimer_init(digic_timer_tick, NULL, PTIMER_POLICY_DEFAULT);
 
 /*
  * FIXME: there is no documentation on Digic timer
  * frequency setup so let it always run at 1 MHz
  */
+ptimer_transaction_begin(s->ptimer);
 ptimer_set_freq(s->ptimer, 1 * 1000 * 1000);
+ptimer_transaction_commit(s->ptimer);
 
 memory_region_init_io(>iomem, OBJECT(s), _timer_ops, s,
   TYPE_DIGIC_TIMER, 0x100);
-- 
2.20.1




[PATCH v2 08/21] hw/timer/cmsdk-apb-dualtimer.c: Switch to transaction-based ptimer API

2019-10-08 Thread Peter Maydell
Switch the cmsdk-apb-dualtimer code away from bottom-half based
ptimers to the new transaction-based ptimer API.  This just requires
adding begin/commit calls around the various places that modify the
ptimer state, and using the new ptimer_init() function to create the
timer.

Signed-off-by: Peter Maydell 
---
 hw/timer/cmsdk-apb-dualtimer.c | 14 +++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/hw/timer/cmsdk-apb-dualtimer.c b/hw/timer/cmsdk-apb-dualtimer.c
index 44d23c80364..e28ba9c90a8 100644
--- a/hw/timer/cmsdk-apb-dualtimer.c
+++ b/hw/timer/cmsdk-apb-dualtimer.c
@@ -20,7 +20,6 @@
 #include "qemu/log.h"
 #include "trace.h"
 #include "qapi/error.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "hw/sysbus.h"
 #include "hw/irq.h"
@@ -112,6 +111,8 @@ static void 
cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule *m,
 /* Handle a write to the CONTROL register */
 uint32_t changed;
 
+ptimer_transaction_begin(m->timer);
+
 newctrl &= R_CONTROL_VALID_MASK;
 
 changed = m->control ^ newctrl;
@@ -213,6 +214,8 @@ static void 
cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule *m,
 }
 
 m->control = newctrl;
+
+ptimer_transaction_commit(m->timer);
 }
 
 static uint64_t cmsdk_apb_dualtimer_read(void *opaque, hwaddr offset,
@@ -330,6 +333,7 @@ static void cmsdk_apb_dualtimer_write(void *opaque, hwaddr 
offset,
 if (!(m->control & R_CONTROL_SIZE_MASK)) {
 value &= 0x;
 }
+ptimer_transaction_begin(m->timer);
 if (!(m->control & R_CONTROL_MODE_MASK)) {
 /*
  * In free-running mode this won't set the limit but will
@@ -346,6 +350,7 @@ static void cmsdk_apb_dualtimer_write(void *opaque, hwaddr 
offset,
 ptimer_run(m->timer, 1);
 }
 }
+ptimer_transaction_commit(m->timer);
 break;
 case A_TIMER1BGLOAD:
 /* Set the limit, but not the current count */
@@ -357,7 +362,9 @@ static void cmsdk_apb_dualtimer_write(void *opaque, hwaddr 
offset,
 if (!(m->control & R_CONTROL_SIZE_MASK)) {
 value &= 0x;
 }
+ptimer_transaction_begin(m->timer);
 ptimer_set_limit(m->timer, value, 0);
+ptimer_transaction_commit(m->timer);
 break;
 case A_TIMER1CONTROL:
 cmsdk_dualtimermod_write_control(m, value);
@@ -398,6 +405,7 @@ static void 
cmsdk_dualtimermod_reset(CMSDKAPBDualTimerModule *m)
 m->intstatus = 0;
 m->load = 0;
 m->value = 0x;
+ptimer_transaction_begin(m->timer);
 ptimer_stop(m->timer);
 /*
  * We start in free-running mode, with VALUE at 0x, and
@@ -406,6 +414,7 @@ static void 
cmsdk_dualtimermod_reset(CMSDKAPBDualTimerModule *m)
  */
 ptimer_set_limit(m->timer, 0x, 1);
 ptimer_set_freq(m->timer, m->parent->pclk_frq);
+ptimer_transaction_commit(m->timer);
 }
 
 static void cmsdk_apb_dualtimer_reset(DeviceState *dev)
@@ -450,10 +459,9 @@ static void cmsdk_apb_dualtimer_realize(DeviceState *dev, 
Error **errp)
 
 for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
 CMSDKAPBDualTimerModule *m = >timermod[i];
-QEMUBH *bh = qemu_bh_new(cmsdk_dualtimermod_tick, m);
 
 m->parent = s;
-m->timer = ptimer_init_with_bh(bh,
+m->timer = ptimer_init(cmsdk_dualtimermod_tick, m,
PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD |
PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT |
PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
-- 
2.20.1




[PATCH v2 07/21] hw/timer/arm_mptimer.c: Switch to transaction-based ptimer API

2019-10-08 Thread Peter Maydell
Switch the arm_mptimer.c code away from bottom-half based ptimers to
the new transaction-based ptimer API.  This just requires adding
begin/commit calls around the various places that modify the ptimer
state, and using the new ptimer_init() function to create the timer.

Signed-off-by: Peter Maydell 
---
 hw/timer/arm_mptimer.c | 14 +++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/hw/timer/arm_mptimer.c b/hw/timer/arm_mptimer.c
index 2a54a011431..fdf97d1800f 100644
--- a/hw/timer/arm_mptimer.c
+++ b/hw/timer/arm_mptimer.c
@@ -27,7 +27,6 @@
 #include "hw/timer/arm_mptimer.h"
 #include "migration/vmstate.h"
 #include "qapi/error.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "hw/core/cpu.h"
 
@@ -65,6 +64,7 @@ static inline uint32_t timerblock_scale(uint32_t control)
 return (((control >> 8) & 0xff) + 1) * 10;
 }
 
+/* Must be called within a ptimer transaction block */
 static inline void timerblock_set_count(struct ptimer_state *timer,
 uint32_t control, uint64_t *count)
 {
@@ -77,6 +77,7 @@ static inline void timerblock_set_count(struct ptimer_state 
*timer,
 ptimer_set_count(timer, *count);
 }
 
+/* Must be called within a ptimer transaction block */
 static inline void timerblock_run(struct ptimer_state *timer,
   uint32_t control, uint32_t load)
 {
@@ -124,6 +125,7 @@ static void timerblock_write(void *opaque, hwaddr addr,
 uint32_t control = tb->control;
 switch (addr) {
 case 0: /* Load */
+ptimer_transaction_begin(tb->timer);
 /* Setting load to 0 stops the timer without doing the tick if
  * prescaler = 0.
  */
@@ -132,8 +134,10 @@ static void timerblock_write(void *opaque, hwaddr addr,
 }
 ptimer_set_limit(tb->timer, value, 1);
 timerblock_run(tb->timer, control, value);
+ptimer_transaction_commit(tb->timer);
 break;
 case 4: /* Counter.  */
+ptimer_transaction_begin(tb->timer);
 /* Setting counter to 0 stops the one-shot timer, or periodic with
  * load = 0, without doing the tick if prescaler = 0.
  */
@@ -143,8 +147,10 @@ static void timerblock_write(void *opaque, hwaddr addr,
 }
 timerblock_set_count(tb->timer, control, );
 timerblock_run(tb->timer, control, value);
+ptimer_transaction_commit(tb->timer);
 break;
 case 8: /* Control.  */
+ptimer_transaction_begin(tb->timer);
 if ((control & 3) != (value & 3)) {
 ptimer_stop(tb->timer);
 }
@@ -160,6 +166,7 @@ static void timerblock_write(void *opaque, hwaddr addr,
 timerblock_run(tb->timer, value, count);
 }
 tb->control = value;
+ptimer_transaction_commit(tb->timer);
 break;
 case 12: /* Interrupt status.  */
 tb->status &= ~value;
@@ -212,9 +219,11 @@ static void timerblock_reset(TimerBlock *tb)
 tb->control = 0;
 tb->status = 0;
 if (tb->timer) {
+ptimer_transaction_begin(tb->timer);
 ptimer_stop(tb->timer);
 ptimer_set_limit(tb->timer, 0, 1);
 ptimer_set_period(tb->timer, timerblock_scale(0));
+ptimer_transaction_commit(tb->timer);
 }
 }
 
@@ -260,8 +269,7 @@ static void arm_mptimer_realize(DeviceState *dev, Error 
**errp)
  */
 for (i = 0; i < s->num_cpu; i++) {
 TimerBlock *tb = >timerblock[i];
-QEMUBH *bh = qemu_bh_new(timerblock_tick, tb);
-tb->timer = ptimer_init_with_bh(bh, PTIMER_POLICY);
+tb->timer = ptimer_init(timerblock_tick, tb, PTIMER_POLICY);
 sysbus_init_irq(sbd, >irq);
 memory_region_init_io(>iomem, OBJECT(s), _ops, tb,
   "arm_mptimer_timerblock", 0x20);
-- 
2.20.1




[PATCH v2 09/21] hw/timer/cmsdk-apb-timer.c: Switch to transaction-based ptimer API

2019-10-08 Thread Peter Maydell
Switch the cmsdk-apb-timer code away from bottom-half based ptimers
to the new transaction-based ptimer API.  This just requires adding
begin/commit calls around the various places that modify the ptimer
state, and using the new ptimer_init() function to create the timer.

Signed-off-by: Peter Maydell 
---
 hw/timer/cmsdk-apb-timer.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/hw/timer/cmsdk-apb-timer.c b/hw/timer/cmsdk-apb-timer.c
index c9ce9770cef..40728e85e20 100644
--- a/hw/timer/cmsdk-apb-timer.c
+++ b/hw/timer/cmsdk-apb-timer.c
@@ -29,7 +29,6 @@
 
 #include "qemu/osdep.h"
 #include "qemu/log.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "qapi/error.h"
 #include "trace.h"
@@ -121,14 +120,17 @@ static void cmsdk_apb_timer_write(void *opaque, hwaddr 
offset, uint64_t value,
   "CMSDK APB timer: EXTIN input not supported\n");
 }
 s->ctrl = value & 0xf;
+ptimer_transaction_begin(s->timer);
 if (s->ctrl & R_CTRL_EN_MASK) {
 ptimer_run(s->timer, ptimer_get_limit(s->timer) == 0);
 } else {
 ptimer_stop(s->timer);
 }
+ptimer_transaction_commit(s->timer);
 break;
 case A_RELOAD:
 /* Writing to reload also sets the current timer value */
+ptimer_transaction_begin(s->timer);
 if (!value) {
 ptimer_stop(s->timer);
 }
@@ -140,8 +142,10 @@ static void cmsdk_apb_timer_write(void *opaque, hwaddr 
offset, uint64_t value,
  */
 ptimer_run(s->timer, 0);
 }
+ptimer_transaction_commit(s->timer);
 break;
 case A_VALUE:
+ptimer_transaction_begin(s->timer);
 if (!value && !ptimer_get_limit(s->timer)) {
 ptimer_stop(s->timer);
 }
@@ -149,6 +153,7 @@ static void cmsdk_apb_timer_write(void *opaque, hwaddr 
offset, uint64_t value,
 if (value && (s->ctrl & R_CTRL_EN_MASK)) {
 ptimer_run(s->timer, ptimer_get_limit(s->timer) == 0);
 }
+ptimer_transaction_commit(s->timer);
 break;
 case A_INTSTATUS:
 /* Just one bit, which is W1C. */
@@ -191,9 +196,11 @@ static void cmsdk_apb_timer_reset(DeviceState *dev)
 trace_cmsdk_apb_timer_reset();
 s->ctrl = 0;
 s->intstatus = 0;
+ptimer_transaction_begin(s->timer);
 ptimer_stop(s->timer);
 /* Set the limit and the count */
 ptimer_set_limit(s->timer, 0, 1);
+ptimer_transaction_commit(s->timer);
 }
 
 static void cmsdk_apb_timer_init(Object *obj)
@@ -210,21 +217,21 @@ static void cmsdk_apb_timer_init(Object *obj)
 static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
 {
 CMSDKAPBTIMER *s = CMSDK_APB_TIMER(dev);
-QEMUBH *bh;
 
 if (s->pclk_frq == 0) {
 error_setg(errp, "CMSDK APB timer: pclk-frq property must be set");
 return;
 }
 
-bh = qemu_bh_new(cmsdk_apb_timer_tick, s);
-s->timer = ptimer_init_with_bh(bh,
+s->timer = ptimer_init(cmsdk_apb_timer_tick, s,
PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD |
PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT |
PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
 
+ptimer_transaction_begin(s->timer);
 ptimer_set_freq(s->timer, s->pclk_frq);
+ptimer_transaction_commit(s->timer);
 }
 
 static const VMStateDescription cmsdk_apb_timer_vmstate = {
-- 
2.20.1




[PATCH v2 06/21] hw/timer/allwinner-a10-pit.c: Switch to transaction-based ptimer API

2019-10-08 Thread Peter Maydell
Switch the allwinner-a10-pit code away from bottom-half based ptimers to
the new transaction-based ptimer API.  This just requires adding
begin/commit calls around the various places that modify the ptimer
state, and using the new ptimer_init() function to create the timer.

Signed-off-by: Peter Maydell 
---
 hw/timer/allwinner-a10-pit.c | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/hw/timer/allwinner-a10-pit.c b/hw/timer/allwinner-a10-pit.c
index 28d055e42f3..aae880f5b35 100644
--- a/hw/timer/allwinner-a10-pit.c
+++ b/hw/timer/allwinner-a10-pit.c
@@ -22,7 +22,6 @@
 #include "hw/timer/allwinner-a10-pit.h"
 #include "migration/vmstate.h"
 #include "qemu/log.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 
 static void a10_pit_update_irq(AwA10PITState *s)
@@ -80,6 +79,7 @@ static uint64_t a10_pit_read(void *opaque, hwaddr offset, 
unsigned size)
 return 0;
 }
 
+/* Must be called inside a ptimer transaction block for s->timer[index] */
 static void a10_pit_set_freq(AwA10PITState *s, int index)
 {
 uint32_t prescaler, source, source_freq;
@@ -118,6 +118,7 @@ static void a10_pit_write(void *opaque, hwaddr offset, 
uint64_t value,
 switch (offset & 0x0f) {
 case AW_A10_PIT_TIMER_CONTROL:
 s->control[index] = value;
+ptimer_transaction_begin(s->timer[index]);
 a10_pit_set_freq(s, index);
 if (s->control[index] & AW_A10_PIT_TIMER_RELOAD) {
 ptimer_set_count(s->timer[index], s->interval[index]);
@@ -131,10 +132,13 @@ static void a10_pit_write(void *opaque, hwaddr offset, 
uint64_t value,
 } else {
 ptimer_stop(s->timer[index]);
 }
+ptimer_transaction_commit(s->timer[index]);
 break;
 case AW_A10_PIT_TIMER_INTERVAL:
 s->interval[index] = value;
+ptimer_transaction_begin(s->timer[index]);
 ptimer_set_limit(s->timer[index], s->interval[index], 1);
+ptimer_transaction_commit(s->timer[index]);
 break;
 case AW_A10_PIT_TIMER_COUNT:
 s->count[index] = value;
@@ -225,8 +229,10 @@ static void a10_pit_reset(DeviceState *dev)
 s->control[i] = AW_A10_PIT_DEFAULT_CLOCK;
 s->interval[i] = 0;
 s->count[i] = 0;
+ptimer_transaction_begin(s->timer[i]);
 ptimer_stop(s->timer[i]);
 a10_pit_set_freq(s, i);
+ptimer_transaction_commit(s->timer[i]);
 }
 s->watch_dog_mode = 0;
 s->watch_dog_control = 0;
@@ -255,7 +261,6 @@ static void a10_pit_init(Object *obj)
 {
 AwA10PITState *s = AW_A10_PIT(obj);
 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
-QEMUBH * bh[AW_A10_PIT_TIMER_NR];
 uint8_t i;
 
 for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) {
@@ -270,8 +275,7 @@ static void a10_pit_init(Object *obj)
 
 tc->container = s;
 tc->index = i;
-bh[i] = qemu_bh_new(a10_pit_timer_cb, tc);
-s->timer[i] = ptimer_init_with_bh(bh[i], PTIMER_POLICY_DEFAULT);
+s->timer[i] = ptimer_init(a10_pit_timer_cb, tc, PTIMER_POLICY_DEFAULT);
 }
 }
 
-- 
2.20.1




[PATCH v2 01/21] ptimer: Rename ptimer_init() to ptimer_init_with_bh()

2019-10-08 Thread Peter Maydell
Currently the ptimer design uses a QEMU bottom-half as its
mechanism for calling back into the device model using the
ptimer when the timer has expired. Unfortunately this design
is fatally flawed, because it means that there is a lag
between the ptimer updating its own state and the device
callback function updating device state, and guest accesses
to device registers between the two can return inconsistent
device state.

We want to replace the bottom-half design with one where
the guest device's callback is called either immediately
(when the ptimer triggers by timeout) or when the device
model code closes a transaction-begin/end section (when the
ptimer triggers because the device model changed the
ptimer's count value or other state). As the first step,
rename ptimer_init() to ptimer_init_with_bh(), to free up
the ptimer_init() name for the new API. We can then convert
all the ptimer users away from ptimer_init_with_bh() before
removing it entirely.

(Commit created with
 git grep -l ptimer_init | xargs sed -i -e 's/ptimer_init/ptimer_init_with_bh/'
and three overlong lines folded by hand.)

Signed-off-by: Peter Maydell 
Reviewed-by: Richard Henderson 
---
 include/hw/ptimer.h  | 11 ++-
 hw/arm/musicpal.c|  2 +-
 hw/core/ptimer.c |  2 +-
 hw/dma/xilinx_axidma.c   |  2 +-
 hw/m68k/mcf5206.c|  2 +-
 hw/m68k/mcf5208.c|  2 +-
 hw/net/fsl_etsec/etsec.c |  2 +-
 hw/net/lan9118.c |  2 +-
 hw/timer/allwinner-a10-pit.c |  2 +-
 hw/timer/altera_timer.c  |  2 +-
 hw/timer/arm_mptimer.c   |  6 +++---
 hw/timer/arm_timer.c |  2 +-
 hw/timer/cmsdk-apb-dualtimer.c   |  2 +-
 hw/timer/cmsdk-apb-timer.c   |  2 +-
 hw/timer/digic-timer.c   |  2 +-
 hw/timer/etraxfs_timer.c |  6 +++---
 hw/timer/exynos4210_mct.c|  7 ---
 hw/timer/exynos4210_pwm.c|  2 +-
 hw/timer/exynos4210_rtc.c|  4 ++--
 hw/timer/grlib_gptimer.c |  2 +-
 hw/timer/imx_epit.c  |  4 ++--
 hw/timer/imx_gpt.c   |  2 +-
 hw/timer/lm32_timer.c|  2 +-
 hw/timer/milkymist-sysctl.c  |  4 ++--
 hw/timer/mss-timer.c |  2 +-
 hw/timer/puv3_ost.c  |  2 +-
 hw/timer/sh_timer.c  |  2 +-
 hw/timer/slavio_timer.c  |  2 +-
 hw/timer/xilinx_timer.c  |  2 +-
 hw/watchdog/cmsdk-apb-watchdog.c |  2 +-
 tests/ptimer-test.c  | 22 +++---
 31 files changed, 56 insertions(+), 54 deletions(-)

diff --git a/include/hw/ptimer.h b/include/hw/ptimer.h
index 9c770552290..2fb9ba1915e 100644
--- a/include/hw/ptimer.h
+++ b/include/hw/ptimer.h
@@ -72,7 +72,7 @@
  * ptimer_set_count() or ptimer_set_limit() will not trigger the timer
  * (though it will cause a reload). Only a counter decrement to "0"
  * will cause a trigger. Not compatible with NO_IMMEDIATE_TRIGGER;
- * ptimer_init() will assert() that you don't set both.
+ * ptimer_init_with_bh() will assert() that you don't set both.
  */
 #define PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT (1 << 5)
 
@@ -81,7 +81,7 @@ typedef struct ptimer_state ptimer_state;
 typedef void (*ptimer_cb)(void *opaque);
 
 /**
- * ptimer_init - Allocate and return a new ptimer
+ * ptimer_init_with_bh - Allocate and return a new ptimer
  * @bh: QEMU bottom half which is run on timer expiry
  * @policy: PTIMER_POLICY_* bits specifying behaviour
  *
@@ -89,13 +89,13 @@ typedef void (*ptimer_cb)(void *opaque);
  * The ptimer takes ownership of @bh and will delete it
  * when the ptimer is eventually freed.
  */
-ptimer_state *ptimer_init(QEMUBH *bh, uint8_t policy_mask);
+ptimer_state *ptimer_init_with_bh(QEMUBH *bh, uint8_t policy_mask);
 
 /**
  * ptimer_free - Free a ptimer
  * @s: timer to free
  *
- * Free a ptimer created using ptimer_init() (including
+ * Free a ptimer created using ptimer_init_with_bh() (including
  * deleting the bottom half which it is using).
  */
 void ptimer_free(ptimer_state *s);
@@ -178,7 +178,8 @@ void ptimer_set_count(ptimer_state *s, uint64_t count);
  * @oneshot: non-zero if this timer should only count down once
  *
  * Start a ptimer counting down; when it reaches zero the bottom half
- * passed to ptimer_init() will be invoked. If the @oneshot argument is zero,
+ * passed to ptimer_init_with_bh() will be invoked.
+ * If the @oneshot argument is zero,
  * the counter value will then be reloaded from the limit and it will
  * start counting down again. If @oneshot is non-zero, then the counter
  * will disable itself when it reaches zero.
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index 246cbb13363..b3624d5e280 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -849,7 +849,7 @@ static void mv88w8618_timer_init(SysBusDevice *dev, 
mv88w8618_timer_state *s,
 s->freq = freq;
 
 bh = qemu_bh_new(mv88w8618_timer_tick, s);
-s->ptimer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
+

[PATCH v2 04/21] hw/timer/arm_timer.c: Switch to transaction-based ptimer API

2019-10-08 Thread Peter Maydell
Switch the arm_timer.c code away from bottom-half based ptimers
to the new transaction-based ptimer API. This just requires
adding begin/commit calls around the various arms of
arm_timer_write() that modify the ptimer state, and using the
new ptimer_init() function to create the timer.

Fixes: https://bugs.launchpad.net/qemu/+bug/177
Signed-off-by: Peter Maydell 
---
 hw/timer/arm_timer.c | 16 +++-
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/hw/timer/arm_timer.c b/hw/timer/arm_timer.c
index 848fbcb0e25..255def3deec 100644
--- a/hw/timer/arm_timer.c
+++ b/hw/timer/arm_timer.c
@@ -14,7 +14,6 @@
 #include "hw/irq.h"
 #include "hw/ptimer.h"
 #include "hw/qdev-properties.h"
-#include "qemu/main-loop.h"
 #include "qemu/module.h"
 #include "qemu/log.h"
 #include "trace.h"
@@ -79,7 +78,10 @@ static uint32_t arm_timer_read(void *opaque, hwaddr offset)
 }
 }
 
-/* Reset the timer limit after settings have changed.  */
+/*
+ * Reset the timer limit after settings have changed.
+ * May only be called from inside a ptimer transaction block.
+ */
 static void arm_timer_recalibrate(arm_timer_state *s, int reload)
 {
 uint32_t limit;
@@ -106,13 +108,16 @@ static void arm_timer_write(void *opaque, hwaddr offset,
 switch (offset >> 2) {
 case 0: /* TimerLoad */
 s->limit = value;
+ptimer_transaction_begin(s->timer);
 arm_timer_recalibrate(s, 1);
+ptimer_transaction_commit(s->timer);
 break;
 case 1: /* TimerValue */
 /* ??? Linux seems to want to write to this readonly register.
Ignore it.  */
 break;
 case 2: /* TimerControl */
+ptimer_transaction_begin(s->timer);
 if (s->control & TIMER_CTRL_ENABLE) {
 /* Pause the timer if it is running.  This may cause some
inaccuracy dure to rounding, but avoids a whole lot of other
@@ -132,13 +137,16 @@ static void arm_timer_write(void *opaque, hwaddr offset,
 /* Restart the timer if still enabled.  */
 ptimer_run(s->timer, (s->control & TIMER_CTRL_ONESHOT) != 0);
 }
+ptimer_transaction_commit(s->timer);
 break;
 case 3: /* TimerIntClr */
 s->int_level = 0;
 break;
 case 6: /* TimerBGLoad */
 s->limit = value;
+ptimer_transaction_begin(s->timer);
 arm_timer_recalibrate(s, 0);
+ptimer_transaction_commit(s->timer);
 break;
 default:
 qemu_log_mask(LOG_GUEST_ERROR,
@@ -170,14 +178,12 @@ static const VMStateDescription vmstate_arm_timer = {
 static arm_timer_state *arm_timer_init(uint32_t freq)
 {
 arm_timer_state *s;
-QEMUBH *bh;
 
 s = (arm_timer_state *)g_malloc0(sizeof(arm_timer_state));
 s->freq = freq;
 s->control = TIMER_CTRL_IE;
 
-bh = qemu_bh_new(arm_timer_tick, s);
-s->timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
+s->timer = ptimer_init(arm_timer_tick, s, PTIMER_POLICY_DEFAULT);
 vmstate_register(NULL, -1, _arm_timer, s);
 return s;
 }
-- 
2.20.1




[PATCH v2 03/21] tests/ptimer-test: Switch to transaction-based ptimer API

2019-10-08 Thread Peter Maydell
Convert the ptimer test cases to the transaction-based ptimer API,
by changing to ptimer_init(), dropping the now-unused QEMUBH
variables, and surrounding each set of changes to the ptimer
state in ptimer_transaction_begin/commit calls.

Signed-off-by: Peter Maydell 
---
 tests/ptimer-test.c | 106 +++-
 1 file changed, 84 insertions(+), 22 deletions(-)

diff --git a/tests/ptimer-test.c b/tests/ptimer-test.c
index a3c82d1d147..e16c30ce573 100644
--- a/tests/ptimer-test.c
+++ b/tests/ptimer-test.c
@@ -67,12 +67,13 @@ static void qemu_clock_step(uint64_t ns)
 static void check_set_count(gconstpointer arg)
 {
 const uint8_t *policy = arg;
-QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
-ptimer_state *ptimer = ptimer_init_with_bh(bh, *policy);
+ptimer_state *ptimer = ptimer_init(ptimer_trigger, NULL, *policy);
 
 triggered = false;
 
+ptimer_transaction_begin(ptimer);
 ptimer_set_count(ptimer, 1000);
+ptimer_transaction_commit(ptimer);
 g_assert_cmpuint(ptimer_get_count(ptimer), ==, 1000);
 g_assert_false(triggered);
 ptimer_free(ptimer);
@@ -81,17 +82,20 @@ static void check_set_count(gconstpointer arg)
 static void check_set_limit(gconstpointer arg)
 {
 const uint8_t *policy = arg;
-QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
-ptimer_state *ptimer = ptimer_init_with_bh(bh, *policy);
+ptimer_state *ptimer = ptimer_init(ptimer_trigger, NULL, *policy);
 
 triggered = false;
 
+ptimer_transaction_begin(ptimer);
 ptimer_set_limit(ptimer, 1000, 0);
+ptimer_transaction_commit(ptimer);
 g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
 g_assert_cmpuint(ptimer_get_limit(ptimer), ==, 1000);
 g_assert_false(triggered);
 
+ptimer_transaction_begin(ptimer);
 ptimer_set_limit(ptimer, 2000, 1);
+ptimer_transaction_commit(ptimer);
 g_assert_cmpuint(ptimer_get_count(ptimer), ==, 2000);
 g_assert_cmpuint(ptimer_get_limit(ptimer), ==, 2000);
 g_assert_false(triggered);
@@ -101,22 +105,25 @@ static void check_set_limit(gconstpointer arg)
 static void check_oneshot(gconstpointer arg)
 {
 const uint8_t *policy = arg;
-QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
-ptimer_state *ptimer = ptimer_init_with_bh(bh, *policy);
+ptimer_state *ptimer = ptimer_init(ptimer_trigger, NULL, *policy);
 bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
 
 triggered = false;
 
+ptimer_transaction_begin(ptimer);
 ptimer_set_period(ptimer, 200);
 ptimer_set_count(ptimer, 10);
 ptimer_run(ptimer, 1);
+ptimer_transaction_commit(ptimer);
 
 qemu_clock_step(200 * 2 + 1);
 
 g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 8 : 7);
 g_assert_false(triggered);
 
+ptimer_transaction_begin(ptimer);
 ptimer_stop(ptimer);
+ptimer_transaction_commit(ptimer);
 
 g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 8 : 7);
 g_assert_false(triggered);
@@ -126,7 +133,9 @@ static void check_oneshot(gconstpointer arg)
 g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 8 : 7);
 g_assert_false(triggered);
 
+ptimer_transaction_begin(ptimer);
 ptimer_run(ptimer, 1);
+ptimer_transaction_commit(ptimer);
 
 qemu_clock_step(200 * 7 + 1);
 
@@ -157,28 +166,36 @@ static void check_oneshot(gconstpointer arg)
 g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
 g_assert_false(triggered);
 
+ptimer_transaction_begin(ptimer);
 ptimer_set_count(ptimer, 10);
+ptimer_transaction_commit(ptimer);
 
 qemu_clock_step(2000 + 1);
 
 g_assert_cmpuint(ptimer_get_count(ptimer), ==, 10);
 g_assert_false(triggered);
 
+ptimer_transaction_begin(ptimer);
 ptimer_set_limit(ptimer, 9, 1);
+ptimer_transaction_commit(ptimer);
 
 qemu_clock_step(2000 + 1);
 
 g_assert_cmpuint(ptimer_get_count(ptimer), ==, 9);
 g_assert_false(triggered);
 
+ptimer_transaction_begin(ptimer);
 ptimer_run(ptimer, 1);
+ptimer_transaction_commit(ptimer);
 
 qemu_clock_step(200 + 1);
 
 g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 8 : 7);
 g_assert_false(triggered);
 
+ptimer_transaction_begin(ptimer);
 ptimer_set_count(ptimer, 20);
+ptimer_transaction_commit(ptimer);
 
 qemu_clock_step(200 * 19 + 1);
 
@@ -190,7 +207,9 @@ static void check_oneshot(gconstpointer arg)
 g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
 g_assert_true(triggered);
 
+ptimer_transaction_begin(ptimer);
 ptimer_stop(ptimer);
+ptimer_transaction_commit(ptimer);
 
 triggered = false;
 
@@ -204,8 +223,7 @@ static void check_oneshot(gconstpointer arg)
 static void check_periodic(gconstpointer arg)
 {
 const uint8_t *policy = arg;
-QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL);
-ptimer_state *ptimer = ptimer_init_with_bh(bh, *policy);
+ptimer_state *ptimer = 

[PATCH v2 02/21] ptimer: Provide new transaction-based API

2019-10-08 Thread Peter Maydell
Provide the new transaction-based API. If a ptimer is created
using ptimer_init() rather than ptimer_init_with_bh(), then
instead of providing a QEMUBH, it provides a pointer to the
callback function directly, and has opted into the transaction
API. All calls to functions which modify ptimer state:
 - ptimer_set_period()
 - ptimer_set_freq()
 - ptimer_set_limit()
 - ptimer_set_count()
 - ptimer_run()
 - ptimer_stop()
must be between matched calls to ptimer_transaction_begin()
and ptimer_transaction_commit(). When ptimer_transaction_commit()
is called it will evaluate the state of the timer after all the
changes in the transaction, and call the callback if necessary.

In the old API the individual update functions generally would
call ptimer_trigger() immediately, which would schedule the QEMUBH.
In the new API the update functions will instead defer the
"set s->next_event and call ptimer_reload()" work to
ptimer_transaction_commit().

Because ptimer_trigger() can now immediately call into the
device code which may then call other ptimer functions that
update ptimer_state fields, we must be more careful in
ptimer_reload() not to cache fields from ptimer_state across
the ptimer_trigger() call. (This was harmless with the QEMUBH
mechanism as the BH would not be invoked until much later.)

We use assertions to check that:
 * the functions modifying ptimer state are not called outside
   a transaction block
 * ptimer_transaction_begin() and _commit() calls are paired
 * the transaction API is not used with a QEMUBH ptimer

There is some slight repetition of code:
 * most of the set functions have similar looking "if s->bh
   call ptimer_reload, otherwise set s->need_reload" code
 * ptimer_init() and ptimer_init_with_bh() have similar code
We deliberately don't try to avoid this repetition, because
it will all be deleted when the QEMUBH version of the API
is removed.

Signed-off-by: Peter Maydell 
---
Changes since v1:
 * ptimer_transaction_begin() now sets need_reload to false
 * fixed assert condition in ptimer_transaction_begin()
 * ptimer_transaction_commit() now has a loop to call
   ptimer_reload() again if the callback function updated
   the ptimer state such that it needs to trigger again
 * fixed callback_opaque arg name mismatch in doc comment
 * don't cache delta, period, etc across ptimer_trigger() call

RTH: I know you gave a reviewed-by-with-caveats to v1 of
this patch but I feel like there turned out to be enough
things needing fixing that I'd rather you looked at v2 afresh.
---
 include/hw/ptimer.h |  72 +
 hw/core/ptimer.c| 152 +++-
 2 files changed, 209 insertions(+), 15 deletions(-)

diff --git a/include/hw/ptimer.h b/include/hw/ptimer.h
index 2fb9ba1915e..4c321f65dcb 100644
--- a/include/hw/ptimer.h
+++ b/include/hw/ptimer.h
@@ -91,6 +91,38 @@ typedef void (*ptimer_cb)(void *opaque);
  */
 ptimer_state *ptimer_init_with_bh(QEMUBH *bh, uint8_t policy_mask);
 
+/**
+ * ptimer_init - Allocate and return a new ptimer
+ * @callback: function to call on ptimer expiry
+ * @callback_opaque: opaque pointer passed to @callback
+ * @policy: PTIMER_POLICY_* bits specifying behaviour
+ *
+ * The ptimer returned must be freed using ptimer_free().
+ *
+ * If a ptimer is created using this API then will use the
+ * transaction-based API for modifying ptimer state: all calls
+ * to functions which modify ptimer state:
+ *  - ptimer_set_period()
+ *  - ptimer_set_freq()
+ *  - ptimer_set_limit()
+ *  - ptimer_set_count()
+ *  - ptimer_run()
+ *  - ptimer_stop()
+ * must be between matched calls to ptimer_transaction_begin()
+ * and ptimer_transaction_commit(). When ptimer_transaction_commit()
+ * is called it will evaluate the state of the timer after all the
+ * changes in the transaction, and call the callback if necessary.
+ *
+ * The callback function is always called from within a transaction
+ * begin/commit block, so the callback should not call the
+ * ptimer_transaction_begin() function itself. If the callback changes
+ * the ptimer state such that another ptimer expiry is triggered, then
+ * the callback will be called a second time after the first call returns.
+ */
+ptimer_state *ptimer_init(ptimer_cb callback,
+  void *callback_opaque,
+  uint8_t policy_mask);
+
 /**
  * ptimer_free - Free a ptimer
  * @s: timer to free
@@ -100,6 +132,28 @@ ptimer_state *ptimer_init_with_bh(QEMUBH *bh, uint8_t 
policy_mask);
  */
 void ptimer_free(ptimer_state *s);
 
+/**
+ * ptimer_transaction_begin() - Start a ptimer modification transaction
+ *
+ * This function must be called before making any calls to functions
+ * which modify the ptimer's state (see the ptimer_init() documentation
+ * for a list of these), and must always have a matched call to
+ * ptimer_transaction_commit().
+ * It is an error to call this function for a BH-based ptimer;
+ * attempting to do this will trigger an assert.
+ */

[PATCH v2 05/21] hw/arm/musicpal.c: Switch to transaction-based ptimer API

2019-10-08 Thread Peter Maydell
Switch the musicpal code away from bottom-half based ptimers to
the new transaction-based ptimer API.  This just requires adding
begin/commit calls around the various places that modify the ptimer
state, and using the new ptimer_init() function to create the timer.

Signed-off-by: Peter Maydell 
---
 hw/arm/musicpal.c | 16 ++--
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index b3624d5e280..f68a399a984 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -843,13 +843,10 @@ static void mv88w8618_timer_tick(void *opaque)
 static void mv88w8618_timer_init(SysBusDevice *dev, mv88w8618_timer_state *s,
  uint32_t freq)
 {
-QEMUBH *bh;
-
 sysbus_init_irq(dev, >irq);
 s->freq = freq;
 
-bh = qemu_bh_new(mv88w8618_timer_tick, s);
-s->ptimer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
+s->ptimer = ptimer_init(mv88w8618_timer_tick, s, PTIMER_POLICY_DEFAULT);
 }
 
 static uint64_t mv88w8618_pit_read(void *opaque, hwaddr offset,
@@ -879,16 +876,19 @@ static void mv88w8618_pit_write(void *opaque, hwaddr 
offset,
 case MP_PIT_TIMER1_LENGTH ... MP_PIT_TIMER4_LENGTH:
 t = >timer[offset >> 2];
 t->limit = value;
+ptimer_transaction_begin(t->ptimer);
 if (t->limit > 0) {
 ptimer_set_limit(t->ptimer, t->limit, 1);
 } else {
 ptimer_stop(t->ptimer);
 }
+ptimer_transaction_commit(t->ptimer);
 break;
 
 case MP_PIT_CONTROL:
 for (i = 0; i < 4; i++) {
 t = >timer[i];
+ptimer_transaction_begin(t->ptimer);
 if (value & 0xf && t->limit > 0) {
 ptimer_set_limit(t->ptimer, t->limit, 0);
 ptimer_set_freq(t->ptimer, t->freq);
@@ -896,6 +896,7 @@ static void mv88w8618_pit_write(void *opaque, hwaddr offset,
 } else {
 ptimer_stop(t->ptimer);
 }
+ptimer_transaction_commit(t->ptimer);
 value >>= 4;
 }
 break;
@@ -914,8 +915,11 @@ static void mv88w8618_pit_reset(DeviceState *d)
 int i;
 
 for (i = 0; i < 4; i++) {
-ptimer_stop(s->timer[i].ptimer);
-s->timer[i].limit = 0;
+mv88w8618_timer_state *t = >timer[i];
+ptimer_transaction_begin(t->ptimer);
+ptimer_stop(t->ptimer);
+ptimer_transaction_commit(t->ptimer);
+t->limit = 0;
 }
 }
 
-- 
2.20.1




[PATCH v2 00/21] transaction-based ptimer API

2019-10-08 Thread Peter Maydell
Currently the ptimer design uses a QEMU bottom-half as its mechanism
for calling back into the device model using the ptimer when the
timer has expired.  Unfortunately this design is fatally flawed,
because it means that there is a lag between the ptimer updating its
own state and the device callback function updating device state, and
guest accesses to device registers between the two can return
inconsistent device state. This was reported as a bug in a specific
timer device but it's a problem with the generic ptimer code:
https://bugs.launchpad.net/qemu/+bug/177

This patchset introduces a change to the ptimer API so that instead
of using a bottom-half for the trigger a device can choose to use a
new 'transaction' based approach.  In this design (suggested by RTH)
all calls which modify ptimer state:
 - ptimer_set_period()
 - ptimer_set_freq()
 - ptimer_set_limit()
 - ptimer_set_count()
 - ptimer_run()
 - ptimer_stop()
must be between matched calls to ptimer_transaction_begin() and
ptimer_transaction_commit().  When ptimer_transaction_commit() is
called it will evaluate the state of the timer after all the changes
in the transaction, and call the callback if necessary.
The callback itself is called from within a transaction block,
so any changes it makes to ptimer state that re-trigger the
timer will mean the callback is called again once it has returned.

Changes since the v1 RFC patchset:
 - In the ptimer implementation patch itself:
 * ptimer_transaction_begin() now sets need_reload to false
 * fixed assert condition in ptimer_transaction_begin()
 * ptimer_transaction_commit() now has a loop to call
   ptimer_reload() again if the callback function updated
   the ptimer state such that it needs to trigger again
 * fixed callback_opaque arg name mismatch in doc comment
 * don't cache delta, period, etc across ptimer_trigger() call,
   because the device's trigger function might update ptimer
   state
 - New patches which update all the devices used in various
   Arm boards to the new transaction-based API

(Most of the bugfixes listed are the result of the extra testing
in the wider variety of ptimer use cases. Thanks in particular
to Philippe for putting together a test image for the exynos4210,
which has several ptimer-using devices some of which are pretty
complicated.)

There are ten non-arm devices using ptimer:

microblaze and ppc:
  hw/timer/xilinx_timer.c
ppc:
  hw/net/fsl_etsec/etsec.c
nios2:
  hw/timer/altera_timer.c
cris:
  hw/timer/etraxfs_timer.c
lm32:
  hw/timer/lm32_timer.c
  hw/timer/milkymist-sysctl.c
sparc:
  hw/timer/grlib_gptimer.c
  hw/timer/slavio_timer.c
sh4:
  hw/timer/sh_timer.c
unicore32:
  hw/timer/puv3_ost.c

I do plan to convert those as well but this series seems big
enough to be going on with, and it means I can avoid the
awkwardness of getting acks from multiple submaintainers
on top of wrangling a big patchset.

thanks
-- PMM

Peter Maydell (21):
  ptimer: Rename ptimer_init() to ptimer_init_with_bh()
  ptimer: Provide new transaction-based API
  tests/ptimer-test: Switch to transaction-based ptimer API
  hw/timer/arm_timer.c: Switch to transaction-based ptimer API
  hw/arm/musicpal.c: Switch to transaction-based ptimer API
  hw/timer/allwinner-a10-pit.c: Switch to transaction-based ptimer API
  hw/timer/arm_mptimer.c: Switch to transaction-based ptimer API
  hw/timer/cmsdk-apb-dualtimer.c: Switch to transaction-based ptimer API
  hw/timer/cmsdk-apb-timer.c: Switch to transaction-based ptimer API
  hw/timer/digic-timer.c: Switch to transaction-based ptimer API
  hw/timer/exynos4210_mct.c: Switch GFRC to transaction-based ptimer API
  hw/timer/exynos4210_mct.c: Switch LFRC to transaction-based ptimer API
  hw/timer/exynos4210_mct.c: Switch ltick to transaction-based ptimer
API
  hw/timer/exynos4210_pwm.c: Switch to transaction-based ptimer API
  hw/timer/exynos4210_rtc.c: Switch 1Hz ptimer to transaction-based API
  hw/timer/exynos4210_rtc.c: Switch main ptimer to transaction-based API
  hw/timer/imx_epit.c: Switch to transaction-based ptimer API
  hw/timer/imx_gpt.c: Switch to transaction-based ptimer API
  hw/timer/mss-timerc: Switch to transaction-based ptimer API
  hw/watchdog/cmsdk-apb-watchdog.c: Switch to transaction-based ptimer
API
  hw/net/lan9118.c: Switch to transaction-based ptimer API

 include/hw/ptimer.h  |  83 -
 include/hw/timer/mss-timer.h |   1 -
 hw/arm/musicpal.c|  16 ++--
 hw/core/ptimer.c | 154 +++
 hw/dma/xilinx_axidma.c   |   2 +-
 hw/m68k/mcf5206.c|   2 +-
 hw/m68k/mcf5208.c|   2 +-
 hw/net/fsl_etsec/etsec.c |   2 +-
 hw/net/lan9118.c |  11 ++-
 hw/timer/allwinner-a10-pit.c |  12 ++-
 hw/timer/altera_timer.c  |   2 +-
 hw/timer/arm_mptimer.c   |  18 +++-
 hw/timer/arm_timer.c |  16 +++-
 

Re: [PATCH] Test netmap on FreeBSD

2019-10-08 Thread Vincenzo Maffione
This is an example command line for a qemu VM with a vtnet interface
connected to a port of a VALE switch called 'vale1':

qemu-system-x86_64 fbsd-head.qcow2 -smp 2 -m 2G -vga std -device
e1000,netdev=mgmt,mac=00:AA:BB:CC:0a:99 -netdev
user,id=mgmt,hostfwd=tcp::20010-:22 -device
virtio-net-pci,netdev=data10,mac=00:AA:BB:CC:0a:0a,ioeventfd=on,mrg_rxbuf=on
-netdev netmap,ifname=vale1:10,id=data10

Cheers,
  Vincenzo


Re: [PATCH] Test netmap on FreeBSD

2019-10-08 Thread Vincenzo Maffione
Il giorno mar 8 ott 2019 alle ore 11:53 Li-Wen Hsu  ha
scritto:

> On Tue, Oct 8, 2019 at 5:49 PM Stefano Garzarella 
> wrote:
> >
> > Hi Thomas,
> >
> > On Tue, Oct 8, 2019 at 10:49 AM Thomas Huth  wrote:
> > >
> > > FreeBSD offers a package for "netmap", thus let's install it in our
> > > FreeBSD tests to get some compile test coverage for net/netmap.c, too.
> > >
> > > Signed-off-by: Thomas Huth 
> > > ---
> > >  .cirrus.yml  | 2 +-
> > >  tests/vm/freebsd | 3 +++
> > >  2 files changed, 4 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/.cirrus.yml b/.cirrus.yml
> > > index 8326a3a4b1..44fea2c29e 100644
> > > --- a/.cirrus.yml
> > > +++ b/.cirrus.yml
> > > @@ -8,7 +8,7 @@ freebsd_12_task:
> > >  memory: 8G
> > >install_script: pkg install -y
> > >  bash bison curl cyrus-sasl git glib gmake gnutls gsed
> > > -nettle perl5 pixman pkgconf png usbredir
> > > +netmap nettle perl5 pixman pkgconf png usbredir
> >
> > >script:
> > >  - mkdir build
> > >  - cd build
> > > diff --git a/tests/vm/freebsd b/tests/vm/freebsd
> > > index 2a19461a90..45821702bd 100755
> > > --- a/tests/vm/freebsd
> > > +++ b/tests/vm/freebsd
> > > @@ -54,6 +54,9 @@ class FreeBSDVM(basevm.BaseVM):
> > >  # libs: opengl
> > >  "libepoxy",
> > >  "mesa-libs",
> > > +
> > > +# libs: network
> > > +"netmap",
> >
> > IIRC netmap is shipped with the FreeBSD kernel, so we shouldn't need to
> > install it.
> >
> > I tried to understand what is the 'netmap' pkg and I found the following
> > in my FreeBSD 12 VM:
> >
> > # pkg search netmap
> > netmap-0.1.3_1 Make a graphical representation of the
> surrounding network
> >
> > I don't think we are installing the right 'netmap' (I know, it is a bit
> > confusing :) )
> >
> > I'll tried "make vm-build-freebsd" without this patch and I noticed
> > "netmap supportyes" in the configure output. So I think we're
> > already compiling the netmap backend in the 'vm-buil-freebsd' target and
> > maybe also in cirrus.
> >
> > Maybe Ed and Li-Wen can confirm (or not).
>
> Yes netmap(4) is a built-in and default feature on FreeBSD. netmap
> package from ports is not related to it.
>
> BTW, I haven't tried qemu's netmap feature on FreeBSD.  Is there
> anything we can test this more?
>

This is an example command line for a qemu VM with a vtnet interface
connected to a port of a VALE switch called 'vale1':

qemu-system-x86_64 fbsd-head.qcow2 -smp 2 -m 2G -vga std -device
e1000,netdev=mgmt,mac=00:AA:BB:CC:0a:99 -netdev
user,id=mgmt,hostfwd=tcp::20010-:22 -device
virtio-net-pci,netdev=data10,mac=00:AA:BB:CC:0a:0a,ioeventfd=on,mrg_rxbuf=on
-netdev netmap,ifname=vale1:10,id=data10

Cheers,
  Vincenzo

>
> Best,
> Li-Wen
>


Re: [PATCH v3 3/3] target/riscv: Make the priv register writable by GDB

2019-10-08 Thread Alistair Francis
On Mon, Oct 7, 2019 at 5:20 PM Jonathan Behrens  wrote:
>
> Currently only PRV_U, PRV_S and PRV_M are supported, so this patch ensures 
> that
> the privilege mode is set to one of them. Once support for the H-extension is
> added, this code will also need to properly update the virtualization status
> when switching between VU/VS-modes and M-mode.
>
> Signed-off-by: Jonathan Behrens 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/gdbstub.c | 9 +
>  1 file changed, 9 insertions(+)
>
> diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
> index 33cf7c4c7d..bc84b599c2 100644
> --- a/target/riscv/gdbstub.c
> +++ b/target/riscv/gdbstub.c
> @@ -387,6 +387,15 @@ static int riscv_gdb_get_virtual(CPURISCVState *cs, 
> uint8_t *mem_buf, int n)
>
>  static int riscv_gdb_set_virtual(CPURISCVState *cs, uint8_t *mem_buf, int n)
>  {
> +if (n == 0) {
> +#ifndef CONFIG_USER_ONLY
> +cs->priv = ldtul_p(mem_buf) & 0x3;
> +if (cs->priv == PRV_H) {
> +cs->priv = PRV_S;
> +}
> +#endif
> +return sizeof(target_ulong);
> +}
>  return 0;
>  }
>
> --
> 2.23.0
>



Re: [PATCH v2] target/riscv: Expose "priv" register for GDB

2019-10-08 Thread Jim Wilson
On Tue, Oct 8, 2019 at 2:00 AM Bin Meng  wrote:
> My gdb does not list "priv" register after applying this patch.

I didn't try the patch, I didn't have time for that.  I would expect
priv to be in the "info registers" output if you are adding it to the
cpu register set.  Shrug.  Anyways, defining priv as a virtual
register is the right way to do this, as it isn't a cpu register, and
gdb already has support for virtual registers like priv.

Jim



Re: [PATCH 3/3] migration/postcopy: handle POSTCOPY_INCOMING_RUNNING corner case properly

2019-10-08 Thread Dr. David Alan Gilbert
* Wei Yang (richardw.y...@linux.intel.com) wrote:
> Currently, we set PostcopyState blindly to RUNNING, even we found the
> previous state is not LISTENING. This will lead to a corner case.
> 
> First let's look at the code flow:
> 
> qemu_loadvm_state_main()
> ret = loadvm_process_command()
> loadvm_postcopy_handle_run()
> return -1;
> if (ret < 0) {
> if (postcopy_state_get() == POSTCOPY_INCOMING_RUNNING)
> ...
> }
> 
> From above snippet, the corner case is loadvm_postcopy_handle_run()
> always sets state to RUNNING. And then it checks the previous state. If
> the previous state is not LISTENING, it will return -1. But at this
> moment, PostcopyState is already been set to RUNNING.
> 
> Then ret is checked in qemu_loadvm_state_main(), when it is -1
> PostcopyState is checked. Current logic would pause postcopy and retry
> if PostcopyState is RUNNING. This is not what we expect, because
> postcopy is not active yet.
> 
> This patch makes sure state is set to RUNNING only previous state is
> LISTENING by introducing an old_state parameter in postcopy_state_set().
> New state only would be set when current state equals to old_state.
> 
> Signed-off-by: Wei Yang 

OK, it's a shame to use a pointer there, but it works.
Note, something else; using '-1' as the return value and checking for it
is something we do a lot; but in this case it's an example of an error
we could never recover from so it never makes sense to try and recover.
We should probably look at different types of error.


Reviewed-by: Dr. David Alan Gilbert 

Dave

> ---
>  migration/migration.c|  2 +-
>  migration/postcopy-ram.c | 13 +
>  migration/postcopy-ram.h |  3 ++-
>  migration/savevm.c   | 11 ++-
>  4 files changed, 18 insertions(+), 11 deletions(-)
> 
> diff --git a/migration/migration.c b/migration/migration.c
> index 34d5e66f06..369cf3826e 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -447,7 +447,7 @@ static void process_incoming_migration_co(void *opaque)
>  assert(mis->from_src_file);
>  mis->migration_incoming_co = qemu_coroutine_self();
>  mis->largest_page_size = qemu_ram_pagesize_largest();
> -postcopy_state_set(POSTCOPY_INCOMING_NONE);
> +postcopy_state_set(POSTCOPY_INCOMING_NONE, NULL);
>  migrate_set_state(>state, MIGRATION_STATUS_NONE,
>MIGRATION_STATUS_ACTIVE);
>  ret = qemu_loadvm_state(mis->from_src_file);
> diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c
> index b24c4a10c2..8f741d636d 100644
> --- a/migration/postcopy-ram.c
> +++ b/migration/postcopy-ram.c
> @@ -577,7 +577,7 @@ int postcopy_ram_incoming_cleanup(MigrationIncomingState 
> *mis)
>  }
>  }
>  
> -postcopy_state_set(POSTCOPY_INCOMING_END);
> +postcopy_state_set(POSTCOPY_INCOMING_END, NULL);
>  
>  if (mis->postcopy_tmp_page) {
>  munmap(mis->postcopy_tmp_page, mis->largest_page_size);
> @@ -626,7 +626,7 @@ int postcopy_ram_prepare_discard(MigrationIncomingState 
> *mis)
>  return -1;
>  }
>  
> -postcopy_state_set(POSTCOPY_INCOMING_DISCARD);
> +postcopy_state_set(POSTCOPY_INCOMING_DISCARD, NULL);
>  
>  return 0;
>  }
> @@ -1457,9 +1457,14 @@ PostcopyState  postcopy_state_get(void)
>  }
>  
>  /* Set the state and return the old state */
> -PostcopyState postcopy_state_set(PostcopyState new_state)
> +PostcopyState postcopy_state_set(PostcopyState new_state,
> + const PostcopyState *old_state)
>  {
> -return atomic_xchg(_postcopy_state, new_state);
> +if (!old_state) {
> +return atomic_xchg(_postcopy_state, new_state);
> +} else {
> +return atomic_cmpxchg(_postcopy_state, *old_state, 
> new_state);
> +}
>  }
>  
>  /* Register a handler for external shared memory postcopy
> diff --git a/migration/postcopy-ram.h b/migration/postcopy-ram.h
> index d2668cc820..e3dde32155 100644
> --- a/migration/postcopy-ram.h
> +++ b/migration/postcopy-ram.h
> @@ -109,7 +109,8 @@ void *postcopy_get_tmp_page(MigrationIncomingState *mis);
>  
>  PostcopyState postcopy_state_get(void);
>  /* Set the state and return the old state */
> -PostcopyState postcopy_state_set(PostcopyState new_state);
> +PostcopyState postcopy_state_set(PostcopyState new_state,
> + const PostcopyState *old_state);
>  
>  void postcopy_fault_thread_notify(MigrationIncomingState *mis);
>  
> diff --git a/migration/savevm.c b/migration/savevm.c
> index f3292eb003..45474d9c95 100644
> --- a/migration/savevm.c
> +++ b/migration/savevm.c
> @@ -1599,7 +1599,7 @@ enum LoadVMExitCodes {
>  static int loadvm_postcopy_handle_advise(MigrationIncomingState *mis,
>   uint16_t len)
>  {
> -PostcopyState ps = postcopy_state_set(POSTCOPY_INCOMING_ADVISE);
> +PostcopyState ps = postcopy_state_set(POSTCOPY_INCOMING_ADVISE, NULL);
>  uint64_t 

Re: [PATCH v3 1/3] target/riscv: Tell gdbstub the correct number of CSRs

2019-10-08 Thread Alistair Francis
On Mon, Oct 7, 2019 at 5:16 PM Jonathan Behrens  wrote:
>
> If the number of registers reported to the gdbstub code does not match the
> number in the associated XML file, then the register numbers used by the stub
> may get out of sync with a remote GDB instance.
>
> Signed-off-by: Jonathan Behrens 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/gdbstub.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
> index ded140e8d8..cb5bfd3d50 100644
> --- a/target/riscv/gdbstub.c
> +++ b/target/riscv/gdbstub.c
> @@ -384,7 +384,7 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState 
> *cs)
>  }
>
>  gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr,
> - 4096, "riscv-32bit-csr.xml", 0);
> + 240, "riscv-32bit-csr.xml", 0);
>  #elif defined(TARGET_RISCV64)
>  if (env->misa & RVF) {
>  gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu,
> @@ -392,6 +392,6 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState 
> *cs)
>  }
>
>  gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr,
> - 4096, "riscv-64bit-csr.xml", 0);
> + 240, "riscv-64bit-csr.xml", 0);
>  #endif
>  }
> --
> 2.23.0
>



  1   2   3   >