[PATCH v2] target/i386: clean up comments over 80 chars per line

2019-09-19 Thread Tao Xu
Drop the duplicate definition of CPUID_7_0_ECX_VBMI. And add some
comments, clean up comments over 80 chars per line.

There is an extra line in comment of CPUID_8000_0008_EBX_WBNOINVD,
remove the extra enter and spaces.

Signed-off-by: Tao Xu 
---
 target/i386/cpu.h   | 163 +++-
 target/i386/hvf/x86_cpuid.c |   2 +-
 2 files changed, 107 insertions(+), 58 deletions(-)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 5f6e3a029a..587f96ca60 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -641,63 +641,112 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
 #define CPUID_SVM_PAUSEFILTER  (1U << 10)
 #define CPUID_SVM_PFTHRESHOLD  (1U << 12)
 
-#define CPUID_7_0_EBX_FSGSBASE (1U << 0)
-#define CPUID_7_0_EBX_BMI1 (1U << 3)
-#define CPUID_7_0_EBX_HLE  (1U << 4)
-#define CPUID_7_0_EBX_AVX2 (1U << 5)
-#define CPUID_7_0_EBX_SMEP (1U << 7)
-#define CPUID_7_0_EBX_BMI2 (1U << 8)
-#define CPUID_7_0_EBX_ERMS (1U << 9)
-#define CPUID_7_0_EBX_INVPCID  (1U << 10)
-#define CPUID_7_0_EBX_RTM  (1U << 11)
-#define CPUID_7_0_EBX_MPX  (1U << 14)
-#define CPUID_7_0_EBX_AVX512F  (1U << 16) /* AVX-512 Foundation */
-#define CPUID_7_0_EBX_AVX512DQ (1U << 17) /* AVX-512 Doubleword & Quadword 
Instrs */
-#define CPUID_7_0_EBX_RDSEED   (1U << 18)
-#define CPUID_7_0_EBX_ADX  (1U << 19)
-#define CPUID_7_0_EBX_SMAP (1U << 20)
-#define CPUID_7_0_EBX_AVX512IFMA (1U << 21) /* AVX-512 Integer Fused Multiply 
Add */
-#define CPUID_7_0_EBX_PCOMMIT  (1U << 22) /* Persistent Commit */
-#define CPUID_7_0_EBX_CLFLUSHOPT (1U << 23) /* Flush a Cache Line Optimized */
-#define CPUID_7_0_EBX_CLWB (1U << 24) /* Cache Line Write Back */
-#define CPUID_7_0_EBX_INTEL_PT (1U << 25) /* Intel Processor Trace */
-#define CPUID_7_0_EBX_AVX512PF (1U << 26) /* AVX-512 Prefetch */
-#define CPUID_7_0_EBX_AVX512ER (1U << 27) /* AVX-512 Exponential and 
Reciprocal */
-#define CPUID_7_0_EBX_AVX512CD (1U << 28) /* AVX-512 Conflict Detection */
-#define CPUID_7_0_EBX_SHA_NI   (1U << 29) /* SHA1/SHA256 Instruction 
Extensions */
-#define CPUID_7_0_EBX_AVX512BW (1U << 30) /* AVX-512 Byte and Word 
Instructions */
-#define CPUID_7_0_EBX_AVX512VL (1U << 31) /* AVX-512 Vector Length Extensions 
*/
-
-#define CPUID_7_0_ECX_AVX512BMI (1U << 1)
-#define CPUID_7_0_ECX_VBMI (1U << 1)  /* AVX-512 Vector Byte Manipulation 
Instrs */
-#define CPUID_7_0_ECX_UMIP (1U << 2)
-#define CPUID_7_0_ECX_PKU  (1U << 3)
-#define CPUID_7_0_ECX_OSPKE(1U << 4)
-#define CPUID_7_0_ECX_VBMI2(1U << 6) /* Additional VBMI Instrs */
-#define CPUID_7_0_ECX_GFNI (1U << 8)
-#define CPUID_7_0_ECX_VAES (1U << 9)
-#define CPUID_7_0_ECX_VPCLMULQDQ (1U << 10)
-#define CPUID_7_0_ECX_AVX512VNNI (1U << 11)
-#define CPUID_7_0_ECX_AVX512BITALG (1U << 12)
-#define CPUID_7_0_ECX_AVX512_VPOPCNTDQ (1U << 14) /* POPCNT for vectors of 
DW/QW */
-#define CPUID_7_0_ECX_LA57 (1U << 16)
-#define CPUID_7_0_ECX_RDPID(1U << 22)
-#define CPUID_7_0_ECX_CLDEMOTE (1U << 25)  /* CLDEMOTE Instruction */
-#define CPUID_7_0_ECX_MOVDIRI  (1U << 27)  /* MOVDIRI Instruction */
-#define CPUID_7_0_ECX_MOVDIR64B (1U << 28) /* MOVDIR64B Instruction */
-
-#define CPUID_7_0_EDX_AVX512_4VNNIW (1U << 2) /* AVX512 Neural Network 
Instructions */
-#define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) /* AVX512 Multiply Accumulation 
Single Precision */
-#define CPUID_7_0_EDX_SPEC_CTRL (1U << 26) /* Speculation Control */
-#define CPUID_7_0_EDX_ARCH_CAPABILITIES (1U << 29)  /*Arch Capabilities*/
-#define CPUID_7_0_EDX_CORE_CAPABILITY   (1U << 30)  /*Core Capability*/
-#define CPUID_7_0_EDX_SPEC_CTRL_SSBD  (1U << 31) /* Speculative Store Bypass 
Disable */
-
-#define CPUID_7_1_EAX_AVX512_BF16 (1U << 5) /* AVX512 BFloat16 Instruction */
-
-#define CPUID_8000_0008_EBX_WBNOINVD  (1U << 9)  /* Write back and
- 
do not invalidate cache */
-#define CPUID_8000_0008_EBX_IBPB(1U << 12) /* Indirect Branch Prediction 
Barrier */
+/* Support RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE */
+#define CPUID_7_0_EBX_FSGSBASE  (1U << 0)
+/* 1st Group of Advanced Bit Manipulation Extensions */
+#define CPUID_7_0_EBX_BMI1  (1U << 3)
+/* Hardware Lock Elision */
+#define CPUID_7_0_EBX_HLE   (1U << 4)
+/* Intel Advanced Vector Extensions 2 */
+#define CPUID_7_0_EBX_AVX2  (1U << 5)
+/* Supervisor-mode Execution Prevention */
+#define CPUID_7_0_EBX_SMEP  (1U << 7)
+/* 2nd Group of Advanced Bit Manipulation Extensions */
+#define CPUID_7_0_EBX_BMI2  (1U << 8)
+/* Enhanced REP MOVSB/STOSB */
+#define CPUID_7_0_EBX_ERMS  (1U << 9)
+/* Invalidate Process-Context Identifier */
+#define CPUID_7_0_EBX_INVPCID   (1U << 10)
+/* Restricted Transactional Memory */
+#define CPUID_7_0_EBX_RTM   (1U << 11)
+/* Memory Protection Extension */
+#define CPUID_7_0_EBX_MPX   (1U 

Re: [PATCH v1 1/6] riscv/sifive_u: Add L2-LIM cache memory

2019-09-19 Thread Bin Meng
On Fri, Sep 20, 2019 at 6:32 AM Alistair Francis
 wrote:
>
> 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 
> ---
>  hw/riscv/sifive_u.c | 15 +++
>  include/hw/riscv/sifive_u.h |  1 +
>  2 files changed, 16 insertions(+)
>
> diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
> index 9f8e84bf2e..de6e197882 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,  0x1e0 },

The size should be 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,19 @@ 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.

nits: wrong multi-line comment format

> + * 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,
> --

Regards,
Bin



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

2019-09-19 Thread Bin Meng
On Fri, Sep 20, 2019 at 6:32 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 c3949fb316..b7cd3631cd 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]);
> @@ -544,8 +548,31 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, 
> Error **errp)
>  memmap[SIFIVE_U_GEM_MGMT].base, memmap[SIFIVE_U_GEM_MGMT].size);
>  }
>
> +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);
>
>  }
>
> 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 {

This patch chose a different way from the one used in patch "[v1,6/6]
riscv/virt: Jump to pflash if specified":

- this patch uses reset_vec[6] while patch [6/6] defines a variable start_addr
- this patch adds a "start-in-flash" property to the machine, while
patch [6/6] tests against drive IF_PFLASH

We should be consistent and I would prefer to use the patch [6/6] way.
On Unleashed an SPI flash is mounted so we cannot add a PFlash to
sifive_u machine like what was done on virt machine, so we should test
IF_MTD instead. Thoughts?

Regards,
Bin



Re: [PATCH 18/21] aspeed: Add an AST2600 eval board

2019-09-19 Thread Joel Stanley
On Thu, 19 Sep 2019 at 05:52, Cédric Le Goater  wrote:
>
> Signed-off-by: Cédric Le Goater 
> ---
>  hw/arm/aspeed.c | 18 ++
>  1 file changed, 18 insertions(+)
>
> diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
> index 52993f84b461..4450e71e5547 100644
> --- a/hw/arm/aspeed.c
> +++ b/hw/arm/aspeed.c
> @@ -88,6 +88,9 @@ struct AspeedBoardState {
>  /* Witherspoon hardware value: 0xF10AD216 (but use romulus definition) */
>  #define WITHERSPOON_BMC_HW_STRAP1 ROMULUS_BMC_HW_STRAP1
>
> +/* AST2600 evb hardware value: (QEMU prototype) */
> +#define AST2600_EVB_HW_STRAP1 AST2500_EVB_HW_STRAP1

We can change this to be the actual values if you want:

STRAP1: 0x00C0
STRAP2: 0x0003

> +.name  = MACHINE_TYPE_NAME("ast2600-evb"),
> +.desc  = "Aspeed AST2600 EVB (Cortex A7)",
> +.soc_name  = "ast2600-a0",
> +.hw_strap1 = AST2600_EVB_HW_STRAP1,
> +.fmc_model = "mx25l25635e",
> +.spi_model = "mx25l25635e",
> +.num_cs= 1,
> +.i2c_init  = ast2600_evb_i2c_init,

Can we add a default ram size?

mc->default_ram_size = 2 * GiB;

With these two fixed:

Reviewed-by: Joel Stanley 

Cheers,

Joel



Re: [PATCH v1 3/6] riscv/sifive_u: Manually define the machine

2019-09-19 Thread Bin Meng
On Fri, Sep 20, 2019 at 6:34 AM Alistair Francis
 wrote:
>
> 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 
> ---
>  hw/riscv/sifive_u.c | 27 +++
>  include/hw/riscv/sifive_u.h |  7 ++-
>  2 files changed, 29 insertions(+), 5 deletions(-)
>
> diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
> index 9c5d791320..c3949fb316 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);
> @@ -545,8 +544,15 @@ 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)
> +static void riscv_sifive_u_machine_instance_init(Object *obj)
> +{
> +

nits: remove this blank line

> +}
> +
> +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;
> @@ -554,7 +560,20 @@ static void riscv_sifive_u_machine_init(MachineClass *mc)
>  mc->default_cpus = mc->min_cpus;
>  }
>
> -DEFINE_MACHINE("sifive_u", riscv_sifive_u_machine_init)
> +static const TypeInfo riscv_sifive_u_machine_init_typeinfo = {

nits: riscv_sifive_u_machine_typeinfo (no _init for consistency with others)

> +.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_init_typeinfo);
> +}
> +
> +type_init(riscv_sifive_u_machine_init_register_types)

nits: I would move the machine declaration to after the sifive_u SoC
declaration in this file.

>
>  static void riscv_sifive_u_soc_class_init(ObjectClass *oc, void *data)
>  {
> 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;
> --

Regards,
Bin



Re: [PATCH v1 2/6] riscv/sifive_u: Add QSPI memory region

2019-09-19 Thread Bin Meng
On Fri, Sep 20, 2019 at 6:32 AM Alistair Francis
 wrote:
>
> There doesn't seem to be details on what QSPI the HiFive Unleashed uses.

IMHO, this sentence should be removed as there are details available.
See the hifive-unleashed-a00.dts.

 {
status = "okay";
flash@0 {
compatible = "issi,is25wp256", "jedec,spi-nor";
..

> To allow boot firmware developers to use QEMU to target the Unleashed
> let's add a chunk of memory to represent the QSPI. This can be targeted

nits: to represent the QSPI0 memory-mapped flash

> using QEMU's -device loader command line option.
>
> Signed-off-by: Alistair Francis 
> ---
>  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 de6e197882..9c5d791320 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,  0x200 },

We should map 256MiB per the manual.

>  [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
> --

Regards,
Bin



Re: [PATCH v1 5/6] riscv/virt: Add the PFlash CFI01 device

2019-09-19 Thread Bin Meng
On Fri, Sep 20, 2019 at 6:36 AM Alistair Francis
 wrote:
>
> 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 
> ---
>  hw/riscv/Kconfig|  1 +
>  hw/riscv/virt.c | 81 +
>  include/hw/riscv/virt.h |  3 ++
>  3 files changed, 85 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 d36f5625ec..ca002ecea7 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,72 @@ 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);

alias_prop_name is unused? ARM virt has 2 more calls in the same function here.

> +
> +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");

I don't think we should mirror what is used on ARM virt board to
create 2 flash for sifive_u. For ARM virt, there are 2 flashes because
they need distinguish secure and non-secure. For sifive_u, only one is
enough.

> +}
> +
> +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 +182,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 +379,15 @@ static void create_fdt(RISCVVirtState *s, const struct 
> MemmapEntry *memmap,
>  qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
>  }
>  g_free(nodename);
> +
> +nodename = 

Re: [PATCH 10/21] watchdog/aspeed: Introduce an object class per SoC

2019-09-19 Thread Joel Stanley
On Thu, 19 Sep 2019 at 05:51, Cédric Le Goater  wrote:
>
> It cleanups the current models for the Aspeed AST2400 and AST2500 SoCs
> and prepares ground for future SoCs. It removes the need of the
> 'silicon_rev' property.
>
> Signed-off-by: Cédric Le Goater 

Reviewed-by: Joel Stanley 



Re: [PATCH v1 6/6] riscv/virt: Jump to pflash if specified

2019-09-19 Thread Bin Meng
On Fri, Sep 20, 2019 at 6:35 AM Alistair Francis
 wrote:
>
> 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 
> ---
>  hw/riscv/virt.c | 10 +-
>  1 file changed, 9 insertions(+), 1 deletion(-)
>
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index ca002ecea7..ed25cc6761 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -441,6 +441,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;
>
> @@ -487,6 +488,13 @@ 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

nits: wrong multi-line comment format

> + * 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) */
> @@ -499,7 +507,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: */
>  };
> --

Otherwise,
Reviewed-by: Bin Meng 



Re: [PATCH 01/21] aspeed/wdt: Check correct register for clock source

2019-09-19 Thread Joel Stanley
On Thu, 19 Sep 2019 at 05:50, Cédric Le Goater  wrote:
>
> From: Amithash Prasad 
>
> When WDT_RESTART is written, the data is not the contents
> of the WDT_CTRL register. Hence ensure we are looking at
> WDT_CTRL to check if bit WDT_CTRL_1MHZ_CLK is set or not.
>
> Signed-off-by: Amithash Prasad 
> [clg: improved Suject prefix ]
> Signed-off-by: Cédric Le Goater 

A patch from the Open Source Firmware Conference! Thanks Amithash.

Reviewed-by: Joel Stanley 

> ---
>  hw/watchdog/wdt_aspeed.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c
> index 9b932134172c..f710036535da 100644
> --- a/hw/watchdog/wdt_aspeed.c
> +++ b/hw/watchdog/wdt_aspeed.c
> @@ -140,7 +140,7 @@ static void aspeed_wdt_write(void *opaque, hwaddr offset, 
> uint64_t data,
>  case WDT_RESTART:
>  if ((data & 0x) == WDT_RESTART_MAGIC) {
>  s->regs[WDT_STATUS] = s->regs[WDT_RELOAD_VALUE];
> -aspeed_wdt_reload(s, !(data & WDT_CTRL_1MHZ_CLK));
> +aspeed_wdt_reload(s, !(s->regs[WDT_CTRL] & WDT_CTRL_1MHZ_CLK));
>  }
>  break;
>  case WDT_CTRL:
> --
> 2.21.0
>



Re: [PATCH 12/21] aspeed/smc: Add AST2600 support

2019-09-19 Thread Joel Stanley
On Thu, 19 Sep 2019 at 05:51, Cédric Le Goater  wrote:
>
> The AST2600 SoC SMC controller is a SPI only controller now and has a
> few extensions which we will need to take into account when SW
> requires it.
>
>  - 4BYTE mode
>  - HCLK divider has changed (SPI Training)
>  - CE0-2 Read Timing Compensation registers
>
> This is enough to support u-boot.

As easy as that! I hope the Linux driver is as simple :)


> Signed-off-by: Cédric Le Goater 

Reviewed-by: Joel Stanley 



Re: [PATCH 06/21] aspeed/timer: Add AST2600 support

2019-09-19 Thread Joel Stanley
On Thu, 19 Sep 2019 at 05:50, Cédric Le Goater  wrote:
>
> The AST2600 timer has a third control register that is used to
> implement a set-to-clear feature for the main control register.
>
> On the AST2600, it is not configurable via 0x38 (control register 3)
> as it is on the AST2500.
>
> Based on previous work from Joel Stanley.
>
> Signed-off-by: Cédric Le Goater 

Reviewed-by: Joel Stanley 



Re: [PATCH 15/21] aspeed/i2c: Add AST2600 support

2019-09-19 Thread Joel Stanley
On Thu, 19 Sep 2019 at 05:51, Cédric Le Goater  wrote:
>
> The I2C controller of the AST2400 and AST2500 SoCs have one IRQ shared
> by all I2C busses. The AST2600 SoC I2C controller has one IRQ per bus
> and 16 busses.
>
> Signed-off-by: Cédric Le Goater 

Reviewed-by: Joel Stanley 



Re: [PATCH 07/21] aspeed/timer: Add support for IRQ status register on the AST2600

2019-09-19 Thread Joel Stanley
On Thu, 19 Sep 2019 at 05:51, Cédric Le Goater  wrote:
>
> The AST2600 timer replaces control register 2 with a interrupt status
> register. It is set by hardware when an IRQ occurs and cleared by
> software.
>
> Modify the vmstate version to take into account the new fields.
>
> Based on previous work from Joel Stanley.
>
> Signed-off-by: Cédric Le Goater 

Reviewed-by: Joel Stanley 



Re: [PATCH 20/21] aspeed: add support for the Aspeed MII controller of the AST2600

2019-09-19 Thread Joel Stanley
On Thu, 19 Sep 2019 at 05:52, Cédric Le Goater  wrote:
>
> The AST2600 SoC has an extra controller to set the PHY registers.
>
> Signed-off-by: Cédric Le Goater 

Reviewed-by: Joel Stanley 



Re: [PATCH 14/21] aspeed/i2c: Introduce an object class per SoC

2019-09-19 Thread Joel Stanley
On Thu, 19 Sep 2019 at 05:51, Cédric Le Goater  wrote:
>
> It prepares ground for register differences between SoCs.
>
> Signed-off-by: Cédric Le Goater 

Reviewed-by: Joel Stanley 



Re: [PATCH 16/21] aspeed: Introduce an object class per SoC

2019-09-19 Thread Joel Stanley
On Thu, 19 Sep 2019 at 05:52, Cédric Le Goater  wrote:
>
> It prepares ground for the AST2600.
>
> Signed-off-by: Cédric Le Goater 

Reviewed-by: Joel Stanley 



Re: [PATCH 08/21] aspeed/sdmc: Introduce an object class per SoC

2019-09-19 Thread Joel Stanley
On Thu, 19 Sep 2019 at 05:51, Cédric Le Goater  wrote:
>
> Use class handlers and class constants to differentiate the
> characteristics of the memory controller and remove the 'silicon_rev'
> property.
>
> Signed-off-by: Cédric Le Goater 

Reviewed-by: Joel Stanley 



Re: [PATCH 17/21] aspeed/soc: Add AST2600 support

2019-09-19 Thread Joel Stanley
On Thu, 19 Sep 2019 at 05:52, Cédric Le Goater  wrote:
>
> Initial definitions for a simple machine using an AST2600 SoC (Cortex
> CPU).
>
> The Cortex CPU and its interrupt controller are too complex to handle
> in the common Aspeed SoC framework. We introduce a new Aspeed SoC
> class with instance_init and realize handlers to handle the differences
> with the AST2400 and the AST2500 SoCs. This will add extra work to
> keep in sync both models with future extensions but it makes the code
> clearer.
>
> Signed-off-by: Cédric Le Goater 

Reviewed-by: Joel Stanley 

One small addition below. If you don't resend I can do a follow up patch for it:

> +
> +static const int aspeed_soc_ast2600_irqmap[] = {

> +[ASPEED_ETH1]  = 2,
> +[ASPEED_ETH2]  = 3,

We need to add ETH3 and ETH4 here. They look like this:

[ASPEED_ETH3]  = 32,
[ASPEED_ETH4]  = 33,



Re: [PATCH 03/21] hw: aspeed_scu: Add AST2600 support

2019-09-19 Thread Andrew Jeffery



On Thu, 19 Sep 2019, at 15:19, Cédric Le Goater wrote:
> From: Joel Stanley 
> 
> The SCU controller on the AST2600 SoC has extra registers. Increase
> the number of regs of the model and introduce a new field in the class
> to customize the MemoryRegion operations depending on the SoC model.
> 
> Signed-off-by: Joel Stanley 
> [clg: - improved commit log
>   - changed vmstate version
>   - reworked model integration into new objet class ]
> Signed-off-by: Cédric Le Goater 
> ---
>  include/hw/misc/aspeed_scu.h |   7 +-
>  hw/misc/aspeed_scu.c | 190 +--
>  2 files changed, 189 insertions(+), 8 deletions(-)

...

> +static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset, 
> uint64_t data,
> + unsigned size)
> +{
> +AspeedSCUState *s = ASPEED_SCU(opaque);
> +int reg = TO_REG(offset);
> +
> +if (reg >= ASPEED_AST2600_SCU_NR_REGS) {
> +qemu_log_mask(LOG_GUEST_ERROR,
> +  "%s: Out-of-bounds write at offset 0x%" 
> HWADDR_PRIx "\n",
> +  __func__, offset);
> +return;
> +}
> +
> +if (reg > PROT_KEY && !s->regs[PROT_KEY]) {
> +qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", 
> __func__);
> +}
> +
> +trace_aspeed_scu_write(offset, size, data);
> +
> +switch (reg) {
> +case AST2600_PROT_KEY:
> +s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
> +return;
> +case AST2600_HW_STRAP1:
> +case AST2600_HW_STRAP2:
> +if (s->regs[reg + 2]) {
> +return;
> +}
> +/* fall through */
> +case AST2600_SYS_RST_CTRL:
> +case AST2600_SYS_RST_CTRL2:
> +/* W1S (Write 1 to set) registers */
> +s->regs[reg] |= data;
> +return;
> +case AST2600_SYS_RST_CTRL_CLR:
> +case AST2600_SYS_RST_CTRL2_CLR:
> +case AST2600_HW_STRAP1_CLR:
> +case AST2600_HW_STRAP2_CLR:
> +/* W1C (Write 1 to clear) registers */
> +s->regs[reg] &= ~data;

This clear should respect the protection register for each strap case.

Andrew



Re: [Qemu-devel] [PATCH 00/21] aspeed: Add support for the AST2600 SoC

2019-09-19 Thread Andrew Jeffery



On Fri, 20 Sep 2019, at 06:26, no-re...@patchew.org wrote:
> Patchew URL: https://patchew.org/QEMU/20190919055002.6729-1-...@kaod.org/
> 
> 
> 
> Hi,
> 
> This series failed the docker-quick@centos7 build test. Please find the 
> testing commands and
> their output below. If you have Docker installed, you can probably 
> reproduce it
> locally.
> 
> === TEST SCRIPT BEGIN ===
> #!/bin/bash
> make docker-image-centos7 V=1 NETWORK=1
> time make docker-test-quick@centos7 SHOW_ENV=1 J=14 NETWORK=1
> === TEST SCRIPT END ===
> 
> libudev   no
> default devices   yes
> 
> warning: Python 2 support is deprecated
> warning: Python 3 will be required for building future versions of QEMU
> cross containers  no
> 
> NOTE: guest cross-compilers enabled: cc
> ---
> Property '.cntfrq' not found

Ah, we should drop the patch introducing the CNTFRQ configuration for the 2600
as well given the patch adding support to configure it isn't part of the series.

Andrew



[Bug 1843151] Re: Regression: QEMU 4.1.0 qxl and KMS resoluiton only 4x10

2019-09-19 Thread James Harvey
Yes, I first replicated the issue by removing "max_outputs=1", then
patched spice server, and the issue no longer happens.

QEMU 4.1.0 still changed something.  If I understand correctly, it's now
in some circumstances saying there are 0 monitors, even though there's a
graphic card?

Fixing this in spice to effectively ignore being told 0, and go with 1
instead, gets around the bug, but still makes me think there's something
wrong in QEMU 4.1.0.  Granted, perhaps with this spice fix, it might not
cause any negative effects anymore.

But, I don't know if there are any third party applications especially
on Windows that don't use upstream spice-server and might be thrown off
by this in a similar way.  So, I wonder if QEMU 4.1.0 should still have
something fixed.

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1843151

Title:
  Regression: QEMU 4.1.0 qxl and KMS resoluiton only 4x10

Status in QEMU:
  New

Bug description:
  Host is Arch Linux.  linux 5.2.13, qemu 4.1.0.  virt-viewer 8.0.

  Guest is Arch Linux Sept 2019 ISO.  linux 5.2.11.

  Have replicated this both on a system using amdgpu and one using
  integrated ASPEED graphics.

  Downgrading from 4.1.0 to 4.0.0 works as usual, see:
  https://www.youtube.com/watch?v=NyMdcYwOCvY

  Going back to 4.1.0 reproduces, see:
  https://www.youtube.com/watch?v=H3nGG2Mk6i0

  4.1.0 displays fine until KMS kicks in.

  Using 4.1.0 with virtio-vga doesn't cause this.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1843151/+subscriptions



Re: [PATCH v18 0/6] Add ARMv8 RAS virtualization support in QEMU

2019-09-19 Thread gengdongjiu
Thanks xiang's continue upstream and test.
Hope maintainer can review it.


On 2019/9/17 20:39, Xiang Zheng wrote:
> Hi all,
> 
> This patch series has been tested for both TCG and KVM scenes.
> 
> 1) Test for TCG:
>- Re-compile qemu after applying the patch refered to 
> https://patchwork.kernel.org/cover/10942757/#22640271).
>- Use command line shown below to start qemu:
> ./qemu-system-aarch64 \
> -name guest=ras \
> -machine virt,gic-version=3,ras=on \
> -cpu cortex-a57 \
> -bios /usr/share/edk2/aarch64/QEMU_EFI.fd \
> -nodefaults \
> -kernel ${GUEST_KERNEL} \
> -initrd ${GUEST_FS} \
> -append "rdinit=init console=ttyAMA0 
> earlycon=pl011,0x900" \
> -m 8192 \
> -smp 4 \
> -serial stdio \
> 
>- Send a signal to one of the VCPU threads:
> kill -s SIGBUS 71571
> 
>- The result of test is shown below:
> 
> [   41.194753] {1}[Hardware Error]: Hardware error from APEI Generic 
> Hardware Error Source: 0
> [   41.197329] {1}[Hardware Error]: event severity: recoverable
> [   41.199078] {1}[Hardware Error]:  Error 0, type: recoverable
> [   41.200829] {1}[Hardware Error]:   section_type: memory error
> [   41.202603] {1}[Hardware Error]:   physical_address: 0x400a1000
> [   41.204649] {1}[Hardware Error]:   error_type: 0, unknown
> [   41.206328] EDAC MC0: 1 UE Unknown on unknown label ( page:0x400a1 
> offset:0x0 grain:0)
> [   41.208788] Internal error: synchronous external abort: 96000410 [#1] 
> SMP
> [   41.210879] Modules linked in:
> [   41.211823] CPU: 2 PID: 0 Comm: swapper/2 Not tainted 4.19.0+ #8
> [   41.213698] Hardware name: QEMU KVM Virtual Machine, BIOS 0.0.0 
> 02/06/2015
> [   41.215812] pstate: 60c00085 (nZCv daIf +PAN +UAO)
> [   41.217296] pc : cpu_do_idle+0x8/0xc
> [   41.218400] lr : arch_cpu_idle+0x2c/0x1b8
> [   41.219629] sp : 09f9bf00
> [   41.220649] x29: 09f9bf00 x28: 
> [   41.222310] x27:  x26: 8001fe471d80
> [   41.223945] x25:  x24: 0937ba38
> [   41.225581] x23: 090b3338 x22: 09379000
> [   41.227220] x21: 0937b000 x20: 0004
> [   41.228871] x19: 090a6000 x18: 
> [   41.230517] x17:  x16: 
> [   41.232165] x15:  x14: 
> [   41.233810] x13: 089f4da8 x12: 000e
> [   41.235448] x11: 089f4d80 x10: 0af0
> [   41.237101] x9 : 09f9be80 x8 : 8001fe4728d0
> [   41.238738] x7 : 0004 x6 : 8001fffbaf30
> [   41.240380] x5 : 0c43b940 x4 : 8001f6f0c000
> [   41.242030] x3 : 0001 x2 : 09f9bf00
> [   41.243666] x1 : 8001fffb82c8 x0 : 090a6018
> [   41.245306] Process swapper/2 (pid: 0, stack limit = 
> 0x(ptrval))
> [   41.247378] Call trace:
> [   41.248117]  cpu_do_idle+0x8/0xc
> [   41.249111]  do_idle+0x1dc/0x2a8
> [   41.250111]  cpu_startup_entry+0x28/0x30
> [   41.251319]  secondary_start_kernel+0x180/0x1c8
> [   41.252725] Code: a8c17bfd d65f03c0 d5033f9f d503207f (d65f03c0)
> [   41.254606] ---[ end trace 221bc8a614fb5a1d ]---
> [   41.256030] Kernel panic - not syncing: Fatal exception
> [   41.257644] SMP: stopping secondary CPUs
> [   41.258912] Kernel Offset: disabled
> [   41.260011] CPU features: 0x0,22a00238
> [   41.261178] Memory Limit: none
> [   41.262122] ---[ end Kernel panic - not syncing: Fatal exception ]---
> 
> 2) Test for KVM:
>- Use command line shown below to start qemu:
> ./qemu-system-aarch64 \
> -name guest=ras \
> -machine virt,accel=kvm,gic-version=3,ras=on \
> -cpu host \
> -bios /usr/share/edk2/aarch64/QEMU_EFI.fd \
> -nodefaults \
> -kernel ${GUEST_KERNEL} \
> -initrd ${GUEST_FS} \
> -append "rdinit=init console=ttyAMA0 earlycon=pl011,0x900" \
> -m 8192 \
> -smp 4 \
> -serial stdio \
> 
>- Run mca-recover and get the GPA(IPA) of allocated page which would be 
> corrupted on the later.
>- Convert the GPA to HPA and corrupt this HPA via APEI/EINJ.
>- Go back to guest and continue to read this page.
> 
>- The result of test is shown below:
> 
> root@genericarmv8:~/tools# ./mca-recover
> pagesize: 0x1000
> before clear cache
> flags for page 0x2317b2: uptodate active mmap anon swapbacked
> vtop(0x9c9e8000) = 0x2317b2000
> Hit any key to access: before read
> 
> after read
> Access at Tue Sep 17 01:41:14 2019
> 
> flags for page 0x2317b2: uptodate active 

Re: [PATCH v18 2/6] docs: APEI GHES generation and CPER record description

2019-09-19 Thread Xiang Zheng
Hi Peter, thanks for your review!

On 2019/9/19 21:25, Peter Maydell wrote:
> On Fri, 6 Sep 2019 at 09:33, Xiang Zheng  wrote:
>>
>> From: Dongjiu Geng 
>>
>> Add APEI/GHES detailed design document
>>
>> Signed-off-by: Dongjiu Geng 
>> Signed-off-by: Xiang Zheng 
>> ---
>>  docs/specs/acpi_hest_ghes.txt | 88 +++
>>  1 file changed, 88 insertions(+)
>>  create mode 100644 docs/specs/acpi_hest_ghes.txt
> 
> Hi; new documentation in docs/specs should be in rst format and
> listed in the contents page for the manual at docs/specs/index.rst,
> please. Conversion from plain text should hopefully be fairly
> straightforward.
> 

Got it!

> 
> I've also provided some minor typo/grammar fixes below.
> 
Thanks, I will fix them soon.

> 
>> diff --git a/docs/specs/acpi_hest_ghes.txt b/docs/specs/acpi_hest_ghes.txt
>> new file mode 100644
>> index 00..690d4b2bd0
>> --- /dev/null
>> +++ b/docs/specs/acpi_hest_ghes.txt
>> @@ -0,0 +1,88 @@
>> +APEI tables generating and CPER record
>> +=
>> +
>> +Copyright (C) 2019 Huawei Corporation.
>> +
>> +Design Details:
>> +---
>> +
>> +   etc/acpi/tables etc/hardware_errors
>> +  
>> ==
>> ++ +--++---+
>> +| | HEST ||address| 
>>+--+
>> +| +--+|registers  | 
>>| Error Status |
>> +| | GHES1|| +-+ 
>>| Data Block 1 |
>> +| +--+ +->| |error_block_address1 
>> |--->| ++
>> +| | .| |  | +-+ 
>>| |  CPER  |
>> +| | error_status_address-+-+ +--->| |error_block_address2 
>> |+   | |  CPER  |
>> +| | .|   || +-+
>> |   | |    |
>> +| | read_ack_register+-+ || |..   |
>> |   | |  CPER  |
>> +| | read_ack_preserve| | |+---+
>> |   | ++
>> +| | read_ack_write   | | | +->| |error_block_addressN |--+ 
>> |   | Error Status |
>> ++ +--+ | | |  | +-+  | 
>> |   | Data Block 2 |
>> +| | GHES2| +-+-+->| |read_ack_register1   |  | 
>> +-->| ++
>> ++ +--+   | |  | +-+  |  
>>| |  CPER  |
>> +| | .|   | | +--->| |read_ack_register2   |  |  
>>| |  CPER  |
>> +| | error_status_address-+---+ | || +-+  |  
>>| |    |
>> +| | .| | || |  .  |  |  
>>| |  CPER  |
>> +| | read_ack_register+-+-+| +-+  |  
>>+-++
>> +| | read_ack_preserve| |   +->| |read_ack_registerN   |  |  
>>| |..  |
>> +| | read_ack_write   | |   |  | +-+  |  
>>| ++
>> ++ +--| |   | |  
>>| Error Status |
>> +| | ...  | |   | |  
>>| Data Block N |
>> ++ +--+ |   | 
>> +>| ++
>> +| | GHESN| |   |
>>| |  CPER  |
>> ++ +--+ |   |
>>| |  CPER  |
>> +| | .| |   |
>>| |    |
>> +| | error_status_address-+-+   |
>>| |  CPER  |
>> +| | .| |
>>+-++
>> +| | read_ack_register+-+
>> +| | read_ack_preserve|
>> +| | read_ack_write   |
>> ++ +--+
>> +
>> +(1) QEMU generates the ACPI HEST table. This table goes in the current
>> +"etc/acpi/tables" fw_cfg blob. Each error source has different
>> +notification types.
>> +
>> +(2) A new fw_cfg blob called "etc/hardware_errors" is introduced. QEMU
>> +also need to populate this blob. The "etc/hardwre_errors" fw_cfg blob
> 
> "needs". "hardware_errors".
> 
>> +contains an address registers table and an Error Status Data Block 
>> table.
>> +
>> +(3) The address registers table contains N Error Block Address entries
>> +and N Read Ack Register entries, the size for each entry is 8-byte.
> 
> ". The size".

Re: [Qemu-devel] vhost, iova, and dirty page tracking

2019-09-19 Thread Jason Wang



On 2019/9/19 下午10:06, Michael S. Tsirkin wrote:

On Thu, Sep 19, 2019 at 05:37:48PM +0800, Jason Wang wrote:

On 2019/9/19 下午3:16, Tian, Kevin wrote:

+Paolo to help clarify here.


From: Jason Wang [mailto:jasow...@redhat.com]
Sent: Thursday, September 19, 2019 2:32 PM


On 2019/9/19 下午2:17, Yan Zhao wrote:

On Thu, Sep 19, 2019 at 02:09:53PM +0800, Jason Wang wrote:

On 2019/9/19 下午1:28, Yan Zhao wrote:

On Thu, Sep 19, 2019 at 09:05:12AM +0800, Jason Wang wrote:

On 2019/9/18 下午4:37, Tian, Kevin wrote:

From: Jason Wang [mailto:jasow...@redhat.com]
Sent: Wednesday, September 18, 2019 2:10 PM


Note that the HVA to GPA mapping is not an 1:1 mapping. One

HVA

range

could be mapped to several GPA ranges.

This is fine. Currently vfio_dma maintains IOVA->HVA mapping.

btw under what condition HVA->GPA is not 1:1 mapping? I didn't

realize it.

I don't remember the details e.g memory region alias? And neither

kvm

nor kvm API does forbid this if my memory is correct.


I checked https://qemu.weilnetz.de/doc/devel/memory.html, which
provides an example of aliased layout. However, its aliasing is all
1:1, instead of N:1. From guest p.o.v every writable GPA implies an
unique location. Why would we hit the situation where multiple
write-able GPAs are mapped to the same HVA (i.e. same physical
memory location)?

I don't know, just want to say current API does not forbid this. So we
probably need to take care it.


yes, in KVM API level, it does not forbid two slots to have the same

HVA(slot->userspace_addr).

But
(1) there's only one kvm instance for each vm for each qemu process.
(2) all ramblock->host (corresponds to HVA and slot->userspace_addr)

in one qemu

process is non-overlapping as it's obtained from mmmap().
(3) qemu ensures two kvm slots will not point to the same section of

one ramblock.

So, as long as kvm instance is not shared in two processes, and
there's no bug in qemu, we can assure that HVA to GPA is 1:1.

Well, you leave this API for userspace, so you can't assume qemu is the
only user or any its behavior. If you had you should limit it in the API
level instead of open window for them.



But even if there are two processes operating on the same kvm

instance

and manipulating on memory slots, adding an extra GPA along side

current

IOVA & HVA to ioctl VFIO_IOMMU_MAP_DMA can still let driver knows

the

right IOVA->GPA mapping, right?

It looks fragile. Consider HVA was mapped to both GPA1 and GPA2.

Guest

maps IOVA to GPA2, so we have IOVA GPA2 HVA in the new ioctl and

then

log through GPA2. If userspace is trying to sync through GPA1, it will
miss the dirty page. So for safety we need log both GPA1 and GPA2. (See
what has been done in log_write_hva() in vhost.c). The only way to do
that is to maintain an independent HVA to GPA mapping like what KVM

or

vhost did.


why GPA1 and GPA2 should be both dirty?
even they have the same HVA due to overlaping virtual address space in
two processes, they still correspond to two physical pages.
don't get what's your meaning :)

The point is not leave any corner case that is hard to debug or fix in
the future.

Let's just start by a single process, the API allows userspace to maps
HVA to both GPA1 and GPA2. Since it knows GPA1 and GPA2 are equivalent,
it's ok to sync just through GPA1. That means if you only log GPA2, it
won't work.


I noted KVM itself doesn't consider such situation (one HVA is mapped
to multiple GPAs), when doing its dirty page tracking. If you look at
kvm_vcpu_mark_page_dirty, it simply finds the unique memslot which
contains the dirty gfn and then set the dirty bit within that slot. It
doesn't attempt to walk all memslots to find out any other GPA which
may be mapped to the same HVA.

So there must be some disconnect here. let's hear from Paolo first and
understand the rationale behind such situation.


Neither did vhost when IOTLB is disabled. And cc Michael who points out this
issue at the beginning.

Thanks



Thanks
Kevin

Yes, we fixed with a kind of a work around, at the time I proposed
a new interace to fix it fully. I don't think we ever got around
to implementing it - right?



Paolo said userspace just need to sync through all GPAs, so my 
understanding is that work around is ok by redundant, so did the API you 
proposed. Anything I miss?


Thanks




Re: [Qemu-devel] [PATCH v12 1/2] block/backup: fix max_transfer handling for copy_range

2019-09-19 Thread John Snow



On 9/19/19 2:50 AM, Vladimir Sementsov-Ogievskiy wrote:
> 18.09.2019 22:57, John Snow wrote:
>>
>>
>> On 9/17/19 12:07 PM, Vladimir Sementsov-Ogievskiy wrote:
>>> Of course, QEMU_ALIGN_UP is a typo, it should be QEMU_ALIGN_DOWN, as we
>>> are trying to find aligned size which satisfy both source and target.
>>> Also, don't ignore too small max_transfer. In this case seems safer to
>>> disable copy_range.
>>>
>>> Fixes: 9ded4a0114968e
>>> Signed-off-by: Vladimir Sementsov-Ogievskiy 
>>> ---
>>>   block/backup.c | 12 
>>>   1 file changed, 8 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/block/backup.c b/block/backup.c
>>> index 763f0d7ff6..d8fdbfadfe 100644
>>> --- a/block/backup.c
>>> +++ b/block/backup.c
>>> @@ -741,12 +741,16 @@ BlockJob *backup_job_create(const char *job_id, 
>>> BlockDriverState *bs,
>>>   job->cluster_size = cluster_size;
>>>   job->copy_bitmap = copy_bitmap;
>>>   copy_bitmap = NULL;
>>> -    job->use_copy_range = !compress; /* compression isn't supported for it 
>>> */
>>>   job->copy_range_size = 
>>> MIN_NON_ZERO(blk_get_max_transfer(job->common.blk),
>>>   
>>> blk_get_max_transfer(job->target));
>>> -    job->copy_range_size = MAX(job->cluster_size,
>>> -   QEMU_ALIGN_UP(job->copy_range_size,
>>> - job->cluster_size));
>>> +    job->copy_range_size = QEMU_ALIGN_DOWN(job->copy_range_size,
>>> +   job->cluster_size);
>>> +    /*
>>> + * Compression is not supported for copy_range. Also, we don't want to
>>> + * handle small max_transfer for copy_range (which currently don't
>>> + * handle max_transfer at all).
>>> + */
>>> +    job->use_copy_range = !compress && job->copy_range_size > 0;
>>>   /* Required permissions are already taken with target's blk_new() */
>>>   block_job_add_bdrv(>common, "target", target, 0, BLK_PERM_ALL,
>>>
>>
>> I'm clear on the alignment fix, I'm not clear on the comment about 
>> max_transfer and how it relates to copy_range_size being non-zero.
>>
>> "small max transfer" -- what happens when it's zero? we're apparently OK 
>> with a single cluster, but when it's zero, what happens?
> 
> if it zero it means that source or target requires max_transfer less than 
> cluster_size. It seems not valid to call copy_range in this case.
> Still it's OK to use normal read/write, as they handle max_transfer 
> internally in a loop (copy_range doesn't do it).
> 

oh, I'm ... sorry, I just didn't quite understand the comment.

You're just making sure copy_range after all of our checks is non-zero,
plain and simple. If max_transfer was *smaller than a job cluster*, we
might end up with a copy_range size that's zero, which is obviously...
not useful.

So, I might phrase "Also, we don't want to..." as:

"copy_range does not respect max_transfer, so we factor that in here. If
it's smaller than the job->cluster_size, we are unable to use copy_range."

Just a suggestion, though, so:

Reviewed-by: John Snow 


(SHOULD copy_range respect max_transfer? I guess it would be quite
different -- it would only count things it had to fall back and actually
*transfer*, right? I suppose that because it can have that fallback we
need to accommodate it here in backup.c, hence this workaround clamp.)



Re: [Qemu-devel] vhost, iova, and dirty page tracking

2019-09-19 Thread Jason Wang



On 2019/9/20 上午6:54, Tian, Kevin wrote:

From: Paolo Bonzini [mailto:pbonz...@redhat.com]
Sent: Thursday, September 19, 2019 7:14 PM

On 19/09/19 09:16, Tian, Kevin wrote:

why GPA1 and GPA2 should be both dirty?
even they have the same HVA due to overlaping virtual address space

in

two processes, they still correspond to two physical pages.
don't get what's your meaning :)

The point is not leave any corner case that is hard to debug or fix in
the future.

Let's just start by a single process, the API allows userspace to maps
HVA to both GPA1 and GPA2. Since it knows GPA1 and GPA2 are

equivalent,

it's ok to sync just through GPA1. That means if you only log GPA2, it
won't work.

I noted KVM itself doesn't consider such situation (one HVA is mapped
to multiple GPAs), when doing its dirty page tracking. If you look at
kvm_vcpu_mark_page_dirty, it simply finds the unique memslot which
contains the dirty gfn and then set the dirty bit within that slot. It
doesn't attempt to walk all memslots to find out any other GPA which
may be mapped to the same HVA.

So there must be some disconnect here. let's hear from Paolo first and
understand the rationale behind such situation.

In general, userspace cannot assume that it's okay to sync just through
GPA1.  It must sync the host page if *either* GPA1 or GPA2 are marked
dirty.

Agree. In this case the kernel only needs to track whether GPA1 or
GPA2 is dirtied by guest operations.



Not necessarily guest operations.



  The reason why vhost has to
set both GPA1 and GPA2 is due to its own design - it maintains
IOVA->HVA and GPA->HVA mappings thus given a IOVA you have
to reverse lookup GPA->HVA memTable which gives multiple possible
GPAs.



So if userspace need to track both GPA1 and GPA2, vhost can just stop 
when it found a one HVA->GPA mapping there.




  But in concept if vhost can maintain a IOVA->GPA mapping,
then it is straightforward to set the right GPA every time when a IOVA
is tracked.



That means, the translation is done twice by software, IOVA->GPA and 
GPA->HVA for each packet.


Thanks





The situation really only arises in special cases.  For example,
0xfffe..0x and 0xe..0xf might be the same memory.
 From "info mtree" before the guest boots:

 - (prio -1, i/o): pci
   000e-000f (prio 1, i/o): alias isa-bios
@pc.bios 0002-0003
   fffc- (prio 0, rom): pc.bios

However, non-x86 machines may have other cases of aliased memory so
it's
a case that you should cover.


Above example is read-only, thus won't be touched in logdirty path.
But now I agree that a specific architecture may define two
writable GPA ranges with one as the alias to the other, as long as
such case is explicitly documented so guest OS won't treat them as
separate memory pages.

Thanks
Kevin




Re: [Qemu-devel] [PATCH v12 2/2] block/backup: fix backup_cow_with_offload for last cluster

2019-09-19 Thread John Snow



On 9/19/19 3:02 AM, Vladimir Sementsov-Ogievskiy wrote:
> 18.09.2019 23:14, John Snow wrote:
>>
>>
>> On 9/17/19 12:07 PM, Vladimir Sementsov-Ogievskiy wrote:
>>> We shouldn't try to copy bytes beyond EOF. Fix it.
>>>
>>> Fixes: 9ded4a0114968e
>>> Signed-off-by: Vladimir Sementsov-Ogievskiy 
>>> Reviewed-by: Max Reitz 
>>> ---
>>>   block/backup.c | 2 +-
>>>   1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/block/backup.c b/block/backup.c
>>> index d8fdbfadfe..89f7f89200 100644
>>> --- a/block/backup.c
>>> +++ b/block/backup.c
>>> @@ -161,7 +161,7 @@ static int coroutine_fn 
>>> backup_cow_with_offload(BackupBlockJob *job,
>>>   assert(QEMU_IS_ALIGNED(job->copy_range_size, job->cluster_size));
>>>   assert(QEMU_IS_ALIGNED(start, job->cluster_size));
>>> -    nbytes = MIN(job->copy_range_size, end - start);
>>> +    nbytes = MIN(job->copy_range_size, MIN(end, job->len) - start);
>>
>> I'm a little confused. I think the patch as written is correct, but I don't 
>> know what problem it solves.
> 
> last cluster may exceed EOF. And backup_do_cow (who calls  
> backup_cow_with_offload) rounds all to clusters.
> It's not bad, but we need to crop nbytes before calling actual io functions. 
> backup_cow_with_bounce_buffer does the same thing.
> 
>>
>> If we're going to allow the caller to pass in an end that's beyond EOF, does 
>> that mean we are *requiring* the caller to pass in a value that's aligned?
> 
> Actually yes, as we are resetting dirty bitmap.
> 
>>
>> We should probably assert what kind of a value we're accepted here, right? 
>> We do for start, but should we for 'end' as well?
> 
> Yes assertion may be added.
> 
>>
>> Then ...
>>
>>>   nr_clusters = DIV_ROUND_UP(nbytes, job->cluster_size);
>>
>> Don't we just round this right back up immediately anyway? Does that mean we 
>> have callers that are passing in an 'end' that's more than 1 job-cluster 
>> beyond EOF? That seems like something that should be fixed in the caller, 
>> surely?
> 
> nr_clusters are used to set/reset dirty bitmap. It's OK. Still, for last 
> cluster we can drop it and use nbytes directly. No there should not be such 
> callers.
> nbytes is used to call blk_co_copy_range, and must be cropped to not exceed 
> EOF.
> 

Ah, right, right ... I *was* confused. We don't use nr_clusters for the
IO itself, just the bitmap. So we effectively re-calculate aligned and
unaligned values for use in different places.

> Also, backup_cow_with_bounce_buffer behave in similar way: it crops nbytes.
> 
> Of course, there is a place for good refactoring, but I think not in this 
> patch, it's a small bug fix.
> 
>>
>>>   bdrv_reset_dirty_bitmap(job->copy_bitmap, start,
>>>   job->cluster_size * nr_clusters);
>>>
>>
> 
> 

We should make the interface here a little more clear I think, but what
you wrote is correct.

Reviewed-by: John Snow 



Re: [Qemu-devel] [PATCH] target/i386: Correct extra enter and spaces in comment

2019-09-19 Thread Tao Xu

On 9/19/2019 5:41 PM, Philippe Mathieu-Daudé wrote:

Hi Tao,

On 9/19/19 4:06 AM, Tao Xu wrote:

There is an extra line in comment of CPUID_8000_0008_EBX_WBNOINVD,
remove the extra enter and spaces.

Signed-off-by: Tao Xu 
---
  target/i386/cpu.h | 3 +--
  1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 5f6e3a029a..71b6193390 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -695,8 +695,7 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
  
  #define CPUID_7_1_EAX_AVX512_BF16 (1U << 5) /* AVX512 BFloat16 Instruction */
  
-#define CPUID_8000_0008_EBX_WBNOINVD  (1U << 9)  /* Write back and

- 
do not invalidate cache */
+#define CPUID_8000_0008_EBX_WBNOINVD (1U << 9) /* Write back and do not 
invalidate cache */


The QEMU CODING_STYLE [*] recommend a 80 chars per line limit:

Line width
==

Lines should be 80 characters; try not to make them longer.

Sometimes it is hard to do, especially when dealing with QEMU subsystems
that use long function or symbol names.  Even in that case, do not make
lines much longer than 80 characters.

Rationale:

* Some people like to tile their 24" screens with a 6x4 matrix of 80x24
   xterms and use vi in all of them.  The best way to punish them is to
   let them keep doing it.
* Code and especially patches is much more readable if limited to a sane
   line length.  Eighty is traditional.
* The four-space indentation makes the most common excuse ("But look
   at all that white space on the left!") moot.
* It is the QEMU coding style.

[*]
https://git.qemu.org/?p=qemu.git;a=blob;f=CODING_STYLE.rst;h=427699e0e425431ea99d4046e40543bdcc22e9c5;hb=HEAD#l82

Can you repost using correct lenght comments?


Yes, But it is hard to do and in this header file there are lots of 
lines over 80 chars even 90 chars. So how about I correct all the lines 
over 80 like this:


/* Write back and do not invalidate cache */
#define CPUID_8000_0008_EBX_WBNOINVD  (1U << 9)
/* Indirect Branch Prediction Barrier */
#define CPUID_8000_0008_EBX_IBPB(1U << 12)




  #define CPUID_8000_0008_EBX_IBPB(1U << 12) /* Indirect Branch Prediction 
Barrier */
  
  #define CPUID_XSAVE_XSAVEOPT   (1U << 0)







Re: [PATCH v3 13/22] libqtest: make qtest_bufwrite send "atomic"

2019-09-19 Thread John Snow



On 9/19/19 3:36 PM, Oleinik, Alexander wrote:
> On Thu, 2019-09-19 at 14:56 -0400, John Snow wrote:
>> >
>> > On 9/19/19 6:37 AM, Stefan Hajnoczi wrote:
>>> > > On Wed, Sep 18, 2019 at 11:19:40PM +, Oleinik, Alexander wrote:
 > > > When using qtest "in-process" communication, qtest_sendf directly
 > > > calls
 > > > a function in the server (qtest.c). Combining the contents of the
 > > > subsequent socket_sends into the qtest_sendf, makes it so the
 > > > server can
 > > > immediately handle the command, without building a local buffer
 > > > and
 > > > waiting for a newline.
 > > >
 > > > Signed-off-by: Alexander Oleinik >>> >
 > > > ---
 > > >  tests/libqtest.c | 4 +---
 > > >  1 file changed, 1 insertion(+), 3 deletions(-)
 > > >
 > > > diff --git a/tests/libqtest.c b/tests/libqtest.c
 > > > index 19feea9e17..d770462869 100644
 > > > --- a/tests/libqtest.c
 > > > +++ b/tests/libqtest.c
 > > > @@ -1086,9 +1086,7 @@ void qtest_bufwrite(QTestState *s, uint64_t
 > > > addr, const void *data, size_t size)
 > > >  gchar *bdata;
 > > >  
 > > >  bdata = g_base64_encode(data, size);
 > > > -qtest_sendf(s, "b64write 0x%" PRIx64 " 0x%zx ", addr, size);
 > > > -socket_send(s->fd, bdata, strlen(bdata));
 > > > -socket_send(s->fd, "\n", 1);
 > > > +qtest_sendf(s, "b64write 0x%" PRIx64 " 0x%zx %s\n", addr,
 > > > size, bdata);
 > > >  qtest_rsp(s, 0);
 > > >  g_free(bdata);
 > > >  }
 > > > -- 
 > > > 2.23.0
>>> > >
>>> > > Cc John Snow, who added the b64write command.
>>> > >
>>> > > The downside to doing this is that sprintf-formatting needs to be
>>> > > performed on the entire base64 buffer.  This slows things down
>>> > > slightly
>>> > > and a larger temporary buffer needs to be allocated, but I'm not
>>> > > sure it
>>> > > matters.
>>> > >
>> >
>> > *struggles to remember*
>> >
>> > I guess I wanted something that had some space savings while
>> > maintaining
>> > some semblance of debuggability. This is almost certainly meant for
>> > AHCI
>> > tests where it's writing various patterns to large blocks of memory.
>> >
>> > I doubt I really measured the performance of it, but it seemed like
>> > the
>> > way to go for transferring medium amounts of data at the time via the
>> > qtest protocol.
>> >
>> > Looks like I am the only user of it, still:
>> >
>> > tests/ahci-test.c:qtest_bufwrite(ahci->parent->qts, ptr, tx,
>> > bufsize);
>> > tests/ahci-test.c:qtest_bufwrite(ahci->parent->qts, ptr, tx,
>> > bufsize);
>> > tests/libqos/ahci.c:qtest_bufwrite(ahci->parent->qts, ptr,
>> > buffer, bufsize);
>> >
>> > The buffers can be quite large, so you might be re-buffering a decent
>> > amount of data from the sender now.
>> >
>> > 1, Are large transfers like this guaranteed to be atomic anyway? What
>> > kind of socket is it? we're probably eclipsing frame and packet sizes
>> > here.
>> >
>> > 2, I am not sure what being "atomic" affords us in terms of allowing
>> > the server to not wait for newlines, how does this change help?
>> >
>> > --js
> 
> I'm modifying qtest to allow the server and client to co-exist within
> the same process (facilitating coverage-guided fuzzing). One of the
> modifications is making qtest_sendf directly call a function in
> qtest.c. All the other qtest commands are sent with a single
> qtest_sendf call, so the qtest.c function could immediately call
> qtest_process_command. This breaks if the command is sent with
> different qtest_send/socket_send calls, as in b64write.
> 
> It should be simple to change qtest_server_inproc_recv (the qtest.c
> receiver) to wait for an "\n" prior to qtest_process_command, so I will
> probably do that and then normal(socket) qtest will keep the
> memory-reduction benefits of the non-"atomic" approach.
> 

Before you spend the effort, just benchmark it if you can. I'd look at
the before and after of the AHCI tests with and without the pre-buffering.

> As a side note, would qtest_memwrite, also benefit from splitting up the
> send command?
> 
> for (i = 0; i < size; i++) {
> sprintf([i * 2], "%02x", ptr[i]);
> }
> 
> qtest_sendf(s, "write 0x%" PRIx64 " 0x%zx 0x%s\n", addr, size, enc);
> qtest_rsp(s, 0);
> g_free(enc);

Depends on the users. I think at the time I wrote bufwrite it was using
obviously more data. Some of the memwrite users might be writing pretty
small things.

Looks like users are:

tests/ahci-test
tests/ide-test
tests/libqos/e1000e.c
tests/libqos/pci-pc.c
tests/libqos/pci-spapr.c
tests/megasas-test.c
tests/tpm-util.c
tests/virtio-9p-test.c

the libqos ones are used by other tests -- you can give it a skim and
come up with a small list of tests to benchmark and see if it makes any
actual difference.

--js



Re: [Qemu-devel] [PATCH v3 00/22] Add virtual device fuzzing support

2019-09-19 Thread no-reply
Patchew URL: https://patchew.org/QEMU/20190918231846.22538-1-alx...@bu.edu/



Hi,

This series failed the docker-mingw@fedora build test. Please find the testing 
commands and
their output below. If you have Docker installed, you can probably reproduce it
locally.

=== TEST SCRIPT BEGIN ===
#! /bin/bash
export ARCH=x86_64
make docker-image-fedora V=1 NETWORK=1
time make docker-test-mingw@fedora J=14 NETWORK=1
=== TEST SCRIPT END ===

  CC  hw/acpi/cpu_hotplug.o
  CC  hw/acpi/memory_hotplug.o
/tmp/qemu-test/src/vl.c: In function 'qemu_cleanup':
/tmp/qemu-test/src/vl.c:4479:6: error: old-style function definition 
[-Werror=old-style-definition]
 void qemu_cleanup()
  ^~~~
cc1: all warnings being treated as errors


The full log is available at
http://patchew.org/logs/20190918231846.22538-1-alx...@bu.edu/testing.docker-mingw@fedora/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-de...@redhat.com

Re: [Qemu-devel] [PATCH v3 00/22] Add virtual device fuzzing support

2019-09-19 Thread no-reply
Patchew URL: https://patchew.org/QEMU/20190918231846.22538-1-alx...@bu.edu/



Hi,

This series failed the docker-quick@centos7 build test. Please find the testing 
commands and
their output below. If you have Docker installed, you can probably reproduce it
locally.

=== TEST SCRIPT BEGIN ===
#!/bin/bash
make docker-image-centos7 V=1 NETWORK=1
time make docker-test-quick@centos7 SHOW_ENV=1 J=14 NETWORK=1
=== TEST SCRIPT END ===

default devices   yes
fuzzing support   no

warning: Python 2 support is deprecated
warning: Python 3 will be required for building future versions of QEMU
cross containers  no

NOTE: guest cross-compilers enabled: cc
---
  CC  backends/hostmem-ram.o
  CC  backends/hostmem-file.o
/tmp/qemu-test/src/vl.c: In function 'qemu_cleanup':
/tmp/qemu-test/src/vl.c:4479:6: error: old-style function definition 
[-Werror=old-style-definition]
 void qemu_cleanup()
  ^
cc1: all warnings being treated as errors


The full log is available at
http://patchew.org/logs/20190918231846.22538-1-alx...@bu.edu/testing.docker-quick@centos7/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-de...@redhat.com

Re: [Qemu-devel] [PATCH v3 00/22] Add virtual device fuzzing support

2019-09-19 Thread no-reply
Patchew URL: https://patchew.org/QEMU/20190918231846.22538-1-alx...@bu.edu/



Hi,

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

Message-id: 20190918231846.22538-1-alx...@bu.edu
Subject: [Qemu-devel] [PATCH v3 00/22] Add virtual device fuzzing support
Type: series

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Switched to a new branch 'test'
5ad94a8 fuzz: add documentation to docs/devel/
042e172 fuzz: add virtio-net fuzz target
621539a fuzz: add i440fx fuzz targets
dae5ad1 fuzz: add support for qos-assisted fuzz targets
ab8dc3a fuzz: expose fuzz target name
79fdc72 fuzz: add support for fork-based fuzzing.
4b1ba3f fuzz: add fuzzer skeleton
fe16e71 fuzz: Add target/fuzz makefile rules
f95cc25 libqtest: add in-process qtest.c tx/rx handlers
6d9d7dc libqtest: make qtest_bufwrite send "atomic"
918fbde libqos: move useful qos-test funcs to qos_external
fd767d6 libqos: split qos-test and libqos makefile vars
5b787c6 tests: provide test variables to other targets
ddcaa47 qtest: add in-process incoming command handler
8eef87c module: check module wasn't already initialized
3d76929 fuzz: Add target/fuzz makefile rules
72f81a2 fuzz: add configure flag --enable-fuzzing
c8a9bd8 libqtest: Add a layer of abstraciton to send/recv
ccb41d8 qtest: add qtest_server_send abstraction
b556f51 fuzz: Add FUZZ_TARGET module type
4644c02 libqos: Rename i2c_send and i2c_recv
63655ea softmmu: split off vl.c:main() into main.c

=== OUTPUT BEGIN ===
1/22 Checking commit 63655ea72e20 (softmmu: split off vl.c:main() into main.c)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#59: 
new file mode 100644

WARNING: architecture specific defines should be avoided
#68: FILE: main.c:5:
+#if defined(__APPLE__) || defined(main)

ERROR: externs should be avoided in .c files
#70: FILE: main.c:7:
+int qemu_main(int argc, char **argv, char **envp);

total: 1 errors, 2 warnings, 114 lines checked

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

2/22 Checking commit 4644c02486b6 (libqos: Rename i2c_send and i2c_recv)
3/22 Checking commit b556f5132021 (fuzz: Add FUZZ_TARGET module type)
4/22 Checking commit ccb41d8c3bd1 (qtest: add qtest_server_send abstraction)
WARNING: line over 80 characters
#71: FILE: qtest.c:795:
+void qtest_server_set_tx_handler(void (*send)(void*, const char*, size_t), 
void *opaque)

total: 0 errors, 1 warnings, 49 lines checked

Patch 4/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
5/22 Checking commit c8a9bd8d9dd9 (libqtest: Add a layer of abstraciton to 
send/recv)
6/22 Checking commit 72f81a2600dc (fuzz: add configure flag --enable-fuzzing)
7/22 Checking commit 3d769292ca2e (fuzz: Add target/fuzz makefile rules)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#85: 
new file mode 100644

total: 0 errors, 1 warnings, 65 lines checked

Patch 7/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
8/22 Checking commit 8eef87cc2d23 (module: check module wasn't already 
initialized)
9/22 Checking commit ddcaa4751604 (qtest: add in-process incoming command 
handler)
10/22 Checking commit 5b787c6a0543 (tests: provide test variables to other 
targets)
11/22 Checking commit fd767d613cc4 (libqos: split qos-test and libqos makefile 
vars)
12/22 Checking commit 918fbde8252a (libqos: move useful qos-test funcs to 
qos_external)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#27: 
new file mode 100644

total: 0 errors, 1 warnings, 343 lines checked

Patch 12/22 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
13/22 Checking commit 6d9d7dc7f758 (libqtest: make qtest_bufwrite send "atomic")
14/22 Checking commit f95cc251da3e (libqtest: add in-process qtest.c tx/rx 
handlers)
15/22 Checking commit fe16e710bff0 (fuzz: Add target/fuzz makefile rules)
16/22 Checking commit 4b1ba3f2594e (fuzz: add fuzzer skeleton)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#29: 
new file mode 100644

WARNING: Block comments use a leading /* on a separate line
#155: FILE: tests/fuzz/fuzz.c:122:
+/* --trace is useful for outputting a log of qtest commands that trigger

WARNING: Block comments use a trailing */ on a separate line
#156: FILE: tests/fuzz/fuzz.c:123:
+ * a crash. The log can can then be replayed with a simple qtest script. */

total: 0 errors, 3 warnings, 215 lines checked

Patch 16/22 has 

Re: [Qemu-devel] [PATCH v3 00/22] Add virtual device fuzzing support

2019-09-19 Thread no-reply
Patchew URL: https://patchew.org/QEMU/20190918231846.22538-1-alx...@bu.edu/



Hi,

This series failed the asan build test. Please find the testing commands and
their output below. If you have Docker installed, you can probably reproduce it
locally.

=== TEST SCRIPT BEGIN ===
#!/bin/bash
export ARCH=x86_64
make docker-image-fedora V=1 NETWORK=1
time make docker-test-debug@fedora TARGET_LIST=x86_64-softmmu J=14 NETWORK=1
=== TEST SCRIPT END ===

clang -iquote /tmp/qemu-test/build/tests -iquote tests -iquote 
/tmp/qemu-test/src/tcg -iquote /tmp/qemu-test/src/tcg/i386 
-I/tmp/qemu-test/src/linux-headers -I/tmp/qemu-test/build/linux-headers -iquote 
. -iquote /tmp/qemu-test/src -iquote /tmp/qemu-test/src/accel/tcg -iquote 
/tmp/qemu-test/src/include -I/usr/include/pixman-1  
-I/tmp/qemu-test/src/dtc/libfdt -Werror  -pthread -I/usr/include/glib-2.0 
-I/usr/lib64/glib-2.0/include  -fPIE -DPIE -m64 -mcx16 -D_GNU_SOURCE 
-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes 
-Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes 
-fno-strict-aliasing -fno-common -fwrapv -std=gnu99  -Wno-string-plus-int 
-Wno-typedef-redefinition -Wno-initializer-overrides -Wexpansion-to-defined 
-Wendif-labels -Wno-shift-negative-value -Wno-missing-include-dirs -Wempty-body 
-Wnested-externs -Wformat-security -Wformat-y2k -Winit-self 
-Wignored-qualifiers -Wold-style-definition -Wtype-limits 
-fstack-protector-strong  -I/usr/include/p11-kit-1 -I/usr/include/libpng16  
-I/usr/include/spice-1 -I/usr/include/spice-server -I/usr/include/cacard 
-I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/nss3 
-I/usr/include/nspr4 -pthread -I/usr/include/libmount -I/usr/include/blkid 
-I/usr/include/uuid -I/usr/include/pixman-1   -I/tmp/qemu-test/src/tests -MMD 
-MP -MT tests/test-authz-simple.o -MF tests/test-authz-simple.d 
-fsanitize=undefined -fsanitize=address -g   -c -o tests/test-authz-simple.o 
/tmp/qemu-test/src/tests/test-authz-simple.c
clang -iquote /tmp/qemu-test/build/tests -iquote tests -iquote 
/tmp/qemu-test/src/tcg -iquote /tmp/qemu-test/src/tcg/i386 
-I/tmp/qemu-test/src/linux-headers -I/tmp/qemu-test/build/linux-headers -iquote 
. -iquote /tmp/qemu-test/src -iquote /tmp/qemu-test/src/accel/tcg -iquote 
/tmp/qemu-test/src/include -I/usr/include/pixman-1  
-I/tmp/qemu-test/src/dtc/libfdt -Werror  -pthread -I/usr/include/glib-2.0 
-I/usr/lib64/glib-2.0/include  -fPIE -DPIE -m64 -mcx16 -D_GNU_SOURCE 
-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes 
-Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes 
-fno-strict-aliasing -fno-common -fwrapv -std=gnu99  -Wno-string-plus-int 
-Wno-typedef-redefinition -Wno-initializer-overrides -Wexpansion-to-defined 
-Wendif-labels -Wno-shift-negative-value -Wno-missing-include-dirs -Wempty-body 
-Wnested-externs -Wformat-security -Wformat-y2k -Winit-self 
-Wignored-qualifiers -Wold-style-definition -Wtype-limits 
-fstack-protector-strong  -I/usr/include/p11-kit-1 -I/usr/include/libpng16  
-I/usr/include/spice-1 -I/usr/include/spice-server -I/usr/include/cacard 
-I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/nss3 
-I/usr/include/nspr4 -pthread -I/usr/include/libmount -I/usr/include/blkid 
-I/usr/include/uuid -I/usr/include/pixman-1   -I/tmp/qemu-test/src/tests -MMD 
-MP -MT tests/test-authz-list.o -MF tests/test-authz-list.d 
-fsanitize=undefined -fsanitize=address -g   -c -o tests/test-authz-list.o 
/tmp/qemu-test/src/tests/test-authz-list.c
clang -iquote /tmp/qemu-test/build/tests -iquote tests -iquote 
/tmp/qemu-test/src/tcg -iquote /tmp/qemu-test/src/tcg/i386 
-I/tmp/qemu-test/src/linux-headers -I/tmp/qemu-test/build/linux-headers -iquote 
. -iquote /tmp/qemu-test/src -iquote /tmp/qemu-test/src/accel/tcg -iquote 
/tmp/qemu-test/src/include -I/usr/include/pixman-1  
-I/tmp/qemu-test/src/dtc/libfdt -Werror  -pthread -I/usr/include/glib-2.0 
-I/usr/lib64/glib-2.0/include  -fPIE -DPIE -m64 -mcx16 -D_GNU_SOURCE 
-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -Wstrict-prototypes 
-Wredundant-decls -Wall -Wundef -Wwrite-strings -Wmissing-prototypes 
-fno-strict-aliasing -fno-common -fwrapv -std=gnu99  -Wno-string-plus-int 
-Wno-typedef-redefinition -Wno-initializer-overrides -Wexpansion-to-defined 
-Wendif-labels -Wno-shift-negative-value -Wno-missing-include-dirs -Wempty-body 
-Wnested-externs -Wformat-security -Wformat-y2k -Winit-self 
-Wignored-qualifiers -Wold-style-definition -Wtype-limits 
-fstack-protector-strong  -I/usr/include/p11-kit-1 -I/usr/include/libpng16  
-I/usr/include/spice-1 -I/usr/include/spice-server -I/usr/include/cacard 
-I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -I/usr/include/nss3 
-I/usr/include/nspr4 -pthread -I/usr/include/libmount -I/usr/include/blkid 
-I/usr/include/uuid -I/usr/include/pixman-1   -I/tmp/qemu-test/src/tests -MMD 
-MP -MT tests/test-authz-listfile.o -MF tests/test-authz-listfile.d 
-fsanitize=undefined -fsanitize=address -g   -c -o 

[PATCH RFC] docker: automatic dependencies for dockerfiles

2019-09-19 Thread John Snow
This is a demo for using makefile dependencies for image requisites.
Honestly, I don't like it -- Makefile sorcery is a bit beyond my
comprehension.

This is as near as I could stab, and it has the unfortunate requisite
that it will generate all of the *.d files at first run and not in an
on-demand way. Boo.

But, I wanted to raise the point that manually managing the variables
is not long-term viable -- we should manage them automatically if we
can.

As far as "partial" images vs "full" images, we should manage this
too; perhaps by subdirectory on the dockerfiles -- that way these
won't get out of date, either.

Signed-off-by: John Snow 
---
 tests/docker/Makefile.include | 37 -
 tests/docker/deputil.py   | 39 +++
 2 files changed, 48 insertions(+), 28 deletions(-)
 create mode 100755 tests/docker/deputil.py

diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include
index 50a400b573..266395d927 100644
--- a/tests/docker/Makefile.include
+++ b/tests/docker/Makefile.include
@@ -21,6 +21,7 @@ DOCKER_TOOLS := travis
 ENGINE := auto
 
 DOCKER_SCRIPT=$(SRC_PATH)/tests/docker/docker.py --engine $(ENGINE)
+DEPTOOL=$(SRC_PATH)/tests/docker/deputil.py
 
 TESTS ?= %
 IMAGES ?= %
@@ -47,12 +48,12 @@ docker-image: ${DOCKER_TARGETS}
 # invoked with SKIP_DOCKER_BUILD we still check the image is up to date
 # though
 ifdef SKIP_DOCKER_BUILD
-docker-image-%: $(DOCKER_FILES_DIR)/%.docker
+docker-image-%: $(DOCKER_FILES_DIR)/%.docker %.d
$(call quiet-command, \
$(DOCKER_SCRIPT) check --quiet qemu:$* $<, \
"CHECK", "$*")
 else
-docker-image-%: $(DOCKER_FILES_DIR)/%.docker
+docker-image-%: $(DOCKER_FILES_DIR)/%.docker %.d
$(call quiet-command,\
$(DOCKER_SCRIPT) build qemu:$* $< \
$(if $V,,--quiet) $(if $(NOCACHE),--no-cache) \
@@ -88,23 +89,17 @@ docker-binfmt-image-debian-%: 
$(DOCKER_FILES_DIR)/debian-bootstrap.docker
 endif
 
 # Enforce dependencies for composite images
-docker-image-debian9-mxe: docker-image-debian9
+%.d: $(DOCKER_FILES_DIR)/%.docker
+   $(call quiet-command, $(DEPTOOL) $(DOCKER_FILES_DIR)/$*.docker > $@)
+
+DEPFILES := $(DOCKER_IMAGES:%=%.d)
+include $(DEPFILES)
+
 ifeq ($(ARCH),x86_64)
-docker-image-debian-amd64: docker-image-debian9
 DOCKER_PARTIAL_IMAGES += debian-amd64-cross
 else
-docker-image-debian-amd64-cross: docker-image-debian10
 DOCKER_PARTIAL_IMAGES += debian-amd64
 endif
-docker-image-debian-armel-cross: docker-image-debian9
-docker-image-debian-armhf-cross: docker-image-debian9
-docker-image-debian-mips-cross: docker-image-debian9
-docker-image-debian-mipsel-cross: docker-image-debian9
-docker-image-debian-mips64el-cross: docker-image-debian9
-docker-image-debian-ppc64el-cross: docker-image-debian9
-docker-image-debian-s390x-cross: docker-image-debian9
-docker-image-debian-win32-cross: docker-image-debian9-mxe
-docker-image-debian-win64-cross: docker-image-debian9-mxe
 
 # For non-x86 hosts not all cross-compilers have been packaged
 ifneq ($(ARCH),x86_64)
@@ -115,22 +110,8 @@ DOCKER_PARTIAL_IMAGES += debian-win32-cross 
debian-win64-cross
 DOCKER_PARTIAL_IMAGES += fedora travis
 endif
 
-docker-image-debian-alpha-cross: docker-image-debian10
-docker-image-debian-arm64-cross: docker-image-debian10
-docker-image-debian-hppa-cross: docker-image-debian10
-docker-image-debian-m68k-cross: docker-image-debian10
-docker-image-debian-mips64-cross: docker-image-debian10
-docker-image-debian-powerpc-cross: docker-image-debian10
-docker-image-debian-ppc64-cross: docker-image-debian10
-docker-image-debian-riscv64-cross: docker-image-debian10
-docker-image-debian-sh4-cross: docker-image-debian10
-docker-image-debian-sparc64-cross: docker-image-debian10
-
 docker-image-travis: NOUSER=1
 
-# Specialist build images, sometimes very limited tools
-docker-image-tricore-cross: docker-image-debian9
-
 # These images may be good enough for building tests but not for test builds
 DOCKER_PARTIAL_IMAGES += debian-alpha-cross
 DOCKER_PARTIAL_IMAGES += debian-hppa-cross
diff --git a/tests/docker/deputil.py b/tests/docker/deputil.py
new file mode 100755
index 00..69711cf85e
--- /dev/null
+++ b/tests/docker/deputil.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env python3
+import os
+import re
+import sys
+from typing import IO, Optional
+
+def get_dep(infile: IO[str]) -> Optional[str]:
+"""Get a dependency as a string from a dockerfile."""
+for line in infile:
+match = re.match(r'FROM (.+)', line)
+if match:
+return match[1]
+return None
+
+def get_qemu_dep(infile: IO[str]) -> Optional[str]:
+"""Get a dependency on the qemu: namespace from a dockerfile."""
+dep = get_dep(infile) or ''
+match = re.match(r'qemu:(.+)', dep)
+return match[1] if match else None
+
+def main() -> None:
+filename = sys.argv[1]
+basefile = os.path.basename(filename)
+base = os.path.splitext(basefile)[0]
+

[PATCH 3/3] docker: remove unused debian-sid and debian-ports

2019-09-19 Thread John Snow
These are listed as "partial" images, but have no user.
Remove them.

Signed-off-by: John Snow 
---
 tests/docker/Makefile.include|  4 +--
 tests/docker/dockerfiles/debian-ports.docker | 36 
 tests/docker/dockerfiles/debian-sid.docker   | 35 ---
 3 files changed, 2 insertions(+), 73 deletions(-)
 delete mode 100644 tests/docker/dockerfiles/debian-ports.docker
 delete mode 100644 tests/docker/dockerfiles/debian-sid.docker

diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include
index 7af476d957..c282b5c520 100644
--- a/tests/docker/Makefile.include
+++ b/tests/docker/Makefile.include
@@ -5,8 +5,8 @@
 DOCKER_SUFFIX := .docker
 DOCKER_FILES_DIR := $(SRC_PATH)/tests/docker/dockerfiles
 # we don't run tests on intermediate images (used as base by another image)
-DOCKER_PARTIAL_IMAGES := debian8 debian9 debian10 debian-sid
-DEBIAN_PARTIAL_IMAGES += debian-9-mxe debian-ports debian-bootstrap
+DOCKER_PARTIAL_IMAGES := debian8 debian9 debian10
+DEBIAN_PARTIAL_IMAGES += debian-9-mxe debian-bootstrap
 DOCKER_IMAGES := $(sort $(notdir $(basename $(wildcard 
$(DOCKER_FILES_DIR)/*.docker
 DOCKER_TARGETS := $(patsubst %,docker-image-%,$(DOCKER_IMAGES))
 # Use a global constant ccache directory to speed up repetitive builds
diff --git a/tests/docker/dockerfiles/debian-ports.docker 
b/tests/docker/dockerfiles/debian-ports.docker
deleted file mode 100644
index 61bc3f2993..00
--- a/tests/docker/dockerfiles/debian-ports.docker
+++ /dev/null
@@ -1,36 +0,0 @@
-#
-# Docker multiarch cross-compiler target
-#
-# This docker target is builds on Debian Ports cross compiler targets
-# to build distro with a selection of cross compilers for building test 
binaries.
-#
-# On its own you can't build much but the docker-foo-cross targets
-# build on top of the base debian image.
-#
-FROM debian:unstable
-
-MAINTAINER Philippe Mathieu-Daudé 
-
-RUN echo "deb [arch=amd64] http://deb.debian.org/debian unstable main" > 
/etc/apt/sources.list
-
-# Duplicate deb line as deb-src
-RUN cat /etc/apt/sources.list | sed -ne "s/^deb\ \(\[.*\]\ \)\?\(.*\)/deb-src 
\2/p" >> /etc/apt/sources.list
-
-# Setup some basic tools we need
-RUN apt-get update && \
-DEBIAN_FRONTEND=noninteractive apt install -yy eatmydata && \
-DEBIAN_FRONTEND=noninteractive eatmydata \
-apt-get install -y --no-install-recommends \
-bison \
-build-essential \
-ca-certificates \
-clang \
-debian-ports-archive-keyring \
-flex \
-gettext \
-git \
-pkg-config \
-psmisc \
-python \
-texinfo \
-$(apt-get -s build-dep qemu | egrep ^Inst | fgrep '[all]' | cut -d\  
-f2)
diff --git a/tests/docker/dockerfiles/debian-sid.docker 
b/tests/docker/dockerfiles/debian-sid.docker
deleted file mode 100644
index 2a1bcc33b2..00
--- a/tests/docker/dockerfiles/debian-sid.docker
+++ /dev/null
@@ -1,35 +0,0 @@
-#
-# Debian Sid Base
-#
-# Currently we can build all our guests with cross-compilers in the
-# latest Debian release (Buster). However new compilers will first
-# arrive in Sid. However Sid is a rolling distro which may be broken
-# at any particular time. To try and mitigate this we use Debian's
-# snapshot archive which provides a "stable" view of what state Sid
-# was in.
-#
-
-# This must be earlier than the snapshot date we are aiming for
-FROM debian:sid-20190812-slim
-
- # Use a snapshot known to work (see http://snapshot.debian.org/#Usage)
-ENV DEBIAN_SNAPSHOT_DATE "20190820"
-RUN sed -i "s%^deb \(https\?://\)deb.debian.org/debian/\? \(.*\)%deb 
[check-valid-until=no] 
\1snapshot.debian.org/archive/debian/${DEBIAN_SNAPSHOT_DATE} \2%" 
/etc/apt/sources.list
-
-# Duplicate deb line as deb-src
-RUN cat /etc/apt/sources.list | sed "s/^deb\ /deb-src /" >> 
/etc/apt/sources.list
-
-# Install common build utilities
-RUN apt update && \
-DEBIAN_FRONTEND=noninteractive apt install -yy eatmydata && \
-DEBIAN_FRONTEND=noninteractive eatmydata \
-apt install -y --no-install-recommends \
-bison \
-build-essential \
-ca-certificates \
-flex \
-git \
-pkg-config \
-psmisc \
-python \
-texinfo || { echo "Failed to build - see debian-sid.docker notes"; 
exit 1; }
-- 
2.21.0




[PATCH 1/3] docker: remove 'deprecated' image definitions

2019-09-19 Thread John Snow
There isn't a debian.dockerfile anymore,
so perform some ghost-busting.

Signed-off-by: John Snow 
---
 tests/docker/Makefile.include | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include
index 50a400b573..8825821127 100644
--- a/tests/docker/Makefile.include
+++ b/tests/docker/Makefile.include
@@ -4,11 +4,10 @@
 
 DOCKER_SUFFIX := .docker
 DOCKER_FILES_DIR := $(SRC_PATH)/tests/docker/dockerfiles
-DOCKER_DEPRECATED_IMAGES := debian
 # we don't run tests on intermediate images (used as base by another image)
-DOCKER_PARTIAL_IMAGES := debian debian8 debian9 debian10 debian-sid
+DOCKER_PARTIAL_IMAGES := debian8 debian9 debian10 debian-sid
 DEBIAN_PARTIAL_IMAGES += debian8-mxe debian-9-mxe debian-ports debian-bootstrap
-DOCKER_IMAGES := $(filter-out $(DOCKER_DEPRECATED_IMAGES),$(sort $(notdir 
$(basename $(wildcard $(DOCKER_FILES_DIR)/*.docker)
+DOCKER_IMAGES := $(sort $(notdir $(basename $(wildcard 
$(DOCKER_FILES_DIR)/*.docker
 DOCKER_TARGETS := $(patsubst %,docker-image-%,$(DOCKER_IMAGES))
 # Use a global constant ccache directory to speed up repetitive builds
 DOCKER_CCACHE_DIR := $$HOME/.cache/qemu-docker-ccache
@@ -158,7 +157,7 @@ docker-image-debian-powerpc-user-cross: 
docker-binfmt-image-debian-powerpc-user
 DOCKER_USER_IMAGES += debian-powerpc-user
 
 # Expand all the pre-requistes for each docker image and test combination
-$(foreach i,$(filter-out $(DOCKER_PARTIAL_IMAGES),$(DOCKER_IMAGES) 
$(DOCKER_DEPRECATED_IMAGES)), \
+$(foreach i,$(filter-out $(DOCKER_PARTIAL_IMAGES),$(DOCKER_IMAGES)), \
$(foreach t,$(DOCKER_TESTS) $(DOCKER_TOOLS), \
$(eval .PHONY: docker-$t@$i) \
$(eval docker-$t@$i: docker-image-$i docker-run-$t@$i) \
-- 
2.21.0




[PATCH 2/3] docker: remove debian8-mxe definitions

2019-09-19 Thread John Snow
We don't have a debian8-mxe dockerfile anymore.

Signed-off-by: John Snow 
---
 tests/docker/Makefile.include | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include
index 8825821127..7af476d957 100644
--- a/tests/docker/Makefile.include
+++ b/tests/docker/Makefile.include
@@ -6,7 +6,7 @@ DOCKER_SUFFIX := .docker
 DOCKER_FILES_DIR := $(SRC_PATH)/tests/docker/dockerfiles
 # we don't run tests on intermediate images (used as base by another image)
 DOCKER_PARTIAL_IMAGES := debian8 debian9 debian10 debian-sid
-DEBIAN_PARTIAL_IMAGES += debian8-mxe debian-9-mxe debian-ports debian-bootstrap
+DEBIAN_PARTIAL_IMAGES += debian-9-mxe debian-ports debian-bootstrap
 DOCKER_IMAGES := $(sort $(notdir $(basename $(wildcard 
$(DOCKER_FILES_DIR)/*.docker
 DOCKER_TARGETS := $(patsubst %,docker-image-%,$(DOCKER_IMAGES))
 # Use a global constant ccache directory to speed up repetitive builds
-- 
2.21.0




[PATCH 0/3] docker: misc cleanups

2019-09-19 Thread John Snow
Another handful of misc tidyups.

Note: this WILL conflict with the other cleanups already in-flight, but
I didn't have a convenient branch to base against at the time; but
it should be pretty trivial to resolve/respin.

John Snow (3):
  docker: remove 'deprecated' image definitions
  docker: remove debian8-mxe definitions
  docker: remove unused debian-sid and debian-ports

 tests/docker/Makefile.include|  9 +++--
 tests/docker/dockerfiles/debian-ports.docker | 36 
 tests/docker/dockerfiles/debian-sid.docker   | 35 ---
 3 files changed, 4 insertions(+), 76 deletions(-)
 delete mode 100644 tests/docker/dockerfiles/debian-ports.docker
 delete mode 100644 tests/docker/dockerfiles/debian-sid.docker

-- 
2.21.0




[PATCH 4/7] exec: Restrict TARGET_PAGE_BITS_VARY assert to CONFIG_DEBUG_TCG

2019-09-19 Thread Richard Henderson
This reduces the size of a release build by about 10k.
Noticably, within the tlb miss helpers.

Signed-off-by: Richard Henderson 
---
 include/exec/cpu-all.h | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index a53b761b48..b11ee1f711 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -215,7 +215,11 @@ typedef struct {
 int bits;
 } TargetPageBits;
 extern const TargetPageBits target_page;
-#define TARGET_PAGE_BITS (assert(target_page.decided), target_page.bits)
+# ifdef CONFIG_DEBUG_TCG
+#  define TARGET_PAGE_BITS (assert(target_page.decided), target_page.bits)
+# else
+#  define TARGET_PAGE_BITS target_page.bits
+# endif
 #else
 #define TARGET_PAGE_BITS_MIN TARGET_PAGE_BITS
 #endif
-- 
2.17.1




[PATCH 5/7] exec: Promote TARGET_PAGE_MASK to target_long

2019-09-19 Thread Richard Henderson
There are some uint64_t uses that expect TARGET_PAGE_MASK to
extend for a 32-bit, so this must continue to be a signed type.
Define based on TARGET_PAGE_BITS not TARGET_PAGE_SIZE; this
will make a following patch more clear.

This should not have a functional effect so far.

Signed-off-by: Richard Henderson 
---
 include/exec/cpu-all.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index b11ee1f711..34d36cebca 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -225,7 +225,7 @@ extern const TargetPageBits target_page;
 #endif
 
 #define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS)
-#define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1)
+#define TARGET_PAGE_MASK ((target_long)-1 << TARGET_PAGE_BITS)
 #define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & 
TARGET_PAGE_MASK)
 
 /* Using intptr_t ensures that qemu_*_page_mask is sign-extended even
-- 
2.17.1




[PATCH 3/7] exec: Use const alias for TARGET_PAGE_BITS_VARY

2019-09-19 Thread Richard Henderson
Using a variable that is declared "const" for this tells the
compiler that it may read the value once and assume that it
does not change across function calls.

For target_page_size, this means we have only one assert per
function, and one read of the variable.

This reduces the size of qemu-system-aarch64 by 8k.

Signed-off-by: Richard Henderson 
---
 include/exec/cpu-all.h | 10 +
 exec-vary.c| 46 ++
 2 files changed, 44 insertions(+), 12 deletions(-)

diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index e0c8dc540c..a53b761b48 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -210,10 +210,12 @@ static inline void stl_phys_notdirty(AddressSpace *as, 
hwaddr addr, uint32_t val
 /* page related stuff */
 
 #ifdef TARGET_PAGE_BITS_VARY
-extern bool target_page_bits_decided;
-extern int target_page_bits;
-#define TARGET_PAGE_BITS ({ assert(target_page_bits_decided); \
-target_page_bits; })
+typedef struct {
+bool decided;
+int bits;
+} TargetPageBits;
+extern const TargetPageBits target_page;
+#define TARGET_PAGE_BITS (assert(target_page.decided), target_page.bits)
 #else
 #define TARGET_PAGE_BITS_MIN TARGET_PAGE_BITS
 #endif
diff --git a/exec-vary.c b/exec-vary.c
index 48c0ab306c..67cdf57a9c 100644
--- a/exec-vary.c
+++ b/exec-vary.c
@@ -22,8 +22,38 @@
 #include "exec/exec-all.h"
 
 #ifdef TARGET_PAGE_BITS_VARY
-int target_page_bits;
-bool target_page_bits_decided;
+/*
+ * We want to declare the "target_page" variable as const, which tells
+ * the compiler that it can cache any value that it reads across calls.
+ * This avoids multiple assertions and multiple reads within any one user.
+ *
+ * This works because we initialize the target_page data very early, in a
+ * location far removed from the functions that require the final results.
+ *
+ * This also requires that we have a non-constant symbol by which we can
+ * perform the actual initialization, and which forces the data to be
+ * allocated within writable memory.  Thus "init_target_page", and we use
+ * that symbol exclusively in the two functions that initialize this value.
+ *
+ * The "target_page" symbol is created as an alias of "init_target_page".
+ */
+static TargetPageBits init_target_page;
+
+/*
+ * Note that this is *not* a redundant decl, this is the definition of
+ * the "target_page" symbol.  The syntax for this definition requires
+ * the use of the extern keyword.  This seems to be a GCC bug in
+ * either the syntax for the alias attribute or in -Wredundant-decls.
+ *
+ * See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91765
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wredundant-decls"
+
+extern const TargetPageBits target_page
+__attribute__((alias("init_target_page")));
+
+#pragma GCC diagnostic pop
 #endif
 
 bool set_preferred_target_page_bits(int bits)
@@ -36,11 +66,11 @@ bool set_preferred_target_page_bits(int bits)
  */
 #ifdef TARGET_PAGE_BITS_VARY
 assert(bits >= TARGET_PAGE_BITS_MIN);
-if (target_page_bits == 0 || target_page_bits > bits) {
-if (target_page_bits_decided) {
+if (init_target_page.bits == 0 || init_target_page.bits > bits) {
+if (init_target_page.decided) {
 return false;
 }
-target_page_bits = bits;
+init_target_page.bits = bits;
 }
 #endif
 return true;
@@ -49,9 +79,9 @@ bool set_preferred_target_page_bits(int bits)
 void finalize_target_page_bits(void)
 {
 #ifdef TARGET_PAGE_BITS_VARY
-if (target_page_bits == 0) {
-target_page_bits = TARGET_PAGE_BITS_MIN;
+if (init_target_page.bits == 0) {
+init_target_page.bits = TARGET_PAGE_BITS_MIN;
 }
-target_page_bits_decided = true;
+init_target_page.decided = true;
 #endif
 }
-- 
2.17.1




[PATCH 7/7] exec: Cache TARGET_PAGE_MASK for TARGET_PAGE_BITS_VARY

2019-09-19 Thread Richard Henderson
This eliminates a set of runtime shifts.  It turns out that we
require TARGET_PAGE_MASK more often than TARGET_PAGE_SIZE, so
redefine TARGET_PAGE_SIZE based on TARGET_PAGE_MASK instead of
the other way around.

Signed-off-by: Richard Henderson 
---
 include/exec/cpu-all.h | 8 ++--
 exec-vary.c| 1 +
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 5246770271..2db73c7a27 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -213,19 +213,23 @@ static inline void stl_phys_notdirty(AddressSpace *as, 
hwaddr addr, uint32_t val
 typedef struct {
 bool decided;
 int bits;
+target_long mask;
 } TargetPageBits;
 extern const TargetPageBits target_page;
 # ifdef CONFIG_DEBUG_TCG
 #  define TARGET_PAGE_BITS (assert(target_page.decided), target_page.bits)
+#  define TARGET_PAGE_MASK (assert(target_page.decided), target_page.mask)
 # else
 #  define TARGET_PAGE_BITS target_page.bits
+#  define TARGET_PAGE_MASK target_page.mask
 # endif
+# define TARGET_PAGE_SIZE  ((int)-TARGET_PAGE_MASK)
 #else
 #define TARGET_PAGE_BITS_MIN TARGET_PAGE_BITS
+#define TARGET_PAGE_SIZE   (1 << TARGET_PAGE_BITS)
+#define TARGET_PAGE_MASK   ((target_long)-1 << TARGET_PAGE_BITS)
 #endif
 
-#define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS)
-#define TARGET_PAGE_MASK ((target_long)-1 << TARGET_PAGE_BITS)
 #define TARGET_PAGE_ALIGN(addr) \
 (((addr) + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK)
 
diff --git a/exec-vary.c b/exec-vary.c
index 67cdf57a9c..26daf281f2 100644
--- a/exec-vary.c
+++ b/exec-vary.c
@@ -83,5 +83,6 @@ void finalize_target_page_bits(void)
 init_target_page.bits = TARGET_PAGE_BITS_MIN;
 }
 init_target_page.decided = true;
+init_target_page.mask = (target_long)-1 << init_target_page.bits;
 #endif
 }
-- 
2.17.1




[PATCH 0/7] exec: Improve code for TARGET_PAGE_BITS_VARY

2019-09-19 Thread Richard Henderson
There's currently a fair amount of overhead in the way we currently
treat TARGET_PAGE_{BITS,SIZE,MASK} with TARGET_PAGE_BITS_VARY.

We have assertions that TARGET_PAGE_BITS has been finalized.  Which
is fine, but the variable that controls the assertion may be assumed
to be modified by any function call, which means that we have lots
of duplicate assertions.

This re-arranges things using a const symbol, which allows the compiler
to assume that the variable is not modified across calls.  In order to
allow initialization of the variable during startup, use an alias that
is non-const and controls the allocation into a read-write section.

Remove the assertion for release builds.

Precompute TARGET_PAGE_MASK.  This removes a runtime shift and allows
the variable to be used as a direct memory operand on x86.

Size reductions vs master for qemu-system-aarch64 for various hosts:

PPC64LE:
  debug-tcg:  -32264
  release:-44360
AARCH64:
  debug-tcg:  -33304
  relase: -77080
X86_64:
  debug-tcg:   -6685
  relase: -15597


r~


Richard Henderson (7):
  exec: Use TARGET_PAGE_BITS_MIN for TLB flags
  exec: Split out variable page size support to exec-vary.c
  exec: Use const alias for TARGET_PAGE_BITS_VARY
  exec: Restrict TARGET_PAGE_BITS_VARY assert to CONFIG_DEBUG_TCG
  exec: Promote TARGET_PAGE_MASK to target_long
  exec: Tidy TARGET_PAGE_ALIGN
  exec: Cache TARGET_PAGE_MASK for TARGET_PAGE_BITS_VARY

 Makefile.target|  2 +-
 include/exec/cpu-all.h | 41 +---
 include/qemu-common.h  |  6 +++
 exec-vary.c| 88 ++
 exec.c | 34 
 5 files changed, 123 insertions(+), 48 deletions(-)
 create mode 100644 exec-vary.c

-- 
2.17.1




[PATCH 2/7] exec: Split out variable page size support to exec-vary.c

2019-09-19 Thread Richard Henderson
The next patch will play a trick with "const" that will
confuse the compiler about the uses of target_page_bits
within exec.c.  Moving everything to a new file prevents
this confusion.

No functional change so far.

Signed-off-by: Richard Henderson 
---
 Makefile.target   |  2 +-
 include/qemu-common.h |  6 +
 exec-vary.c   | 57 +++
 exec.c| 34 --
 4 files changed, 64 insertions(+), 35 deletions(-)
 create mode 100644 exec-vary.c

diff --git a/Makefile.target b/Makefile.target
index 5e916230c4..ca3d14efe1 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -107,7 +107,7 @@ obj-y += trace/
 
 #
 # cpu emulator library
-obj-y += exec.o
+obj-y += exec.o exec-vary.o
 obj-y += accel/
 obj-$(CONFIG_TCG) += tcg/tcg.o tcg/tcg-op.o tcg/tcg-op-vec.o tcg/tcg-op-gvec.o
 obj-$(CONFIG_TCG) += tcg/tcg-common.o tcg/optimize.o
diff --git a/include/qemu-common.h b/include/qemu-common.h
index 0235cd3b91..3e800c2224 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -74,6 +74,12 @@ void cpu_exec_step_atomic(CPUState *cpu);
  */
 bool set_preferred_target_page_bits(int bits);
 
+/**
+ * finalize_target_page_bits:
+ * Commit the final value set by set_preferred_target_page_bits.
+ */
+void finalize_target_page_bits(void);
+
 /**
  * Sends a (part of) iovec down a socket, yielding when the socket is full, or
  * Receives data into a (part of) iovec from a socket,
diff --git a/exec-vary.c b/exec-vary.c
new file mode 100644
index 00..48c0ab306c
--- /dev/null
+++ b/exec-vary.c
@@ -0,0 +1,57 @@
+/*
+ * Variable page size handling
+ *
+ *  Copyright (c) 2003 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "exec/exec-all.h"
+
+#ifdef TARGET_PAGE_BITS_VARY
+int target_page_bits;
+bool target_page_bits_decided;
+#endif
+
+bool set_preferred_target_page_bits(int bits)
+{
+/*
+ * The target page size is the lowest common denominator for all
+ * the CPUs in the system, so we can only make it smaller, never
+ * larger. And we can't make it smaller once we've committed to
+ * a particular size.
+ */
+#ifdef TARGET_PAGE_BITS_VARY
+assert(bits >= TARGET_PAGE_BITS_MIN);
+if (target_page_bits == 0 || target_page_bits > bits) {
+if (target_page_bits_decided) {
+return false;
+}
+target_page_bits = bits;
+}
+#endif
+return true;
+}
+
+void finalize_target_page_bits(void)
+{
+#ifdef TARGET_PAGE_BITS_VARY
+if (target_page_bits == 0) {
+target_page_bits = TARGET_PAGE_BITS_MIN;
+}
+target_page_bits_decided = true;
+#endif
+}
diff --git a/exec.c b/exec.c
index 8b998974f8..33bd0e36c1 100644
--- a/exec.c
+++ b/exec.c
@@ -92,11 +92,6 @@ MemoryRegion io_mem_rom, io_mem_notdirty;
 static MemoryRegion io_mem_unassigned;
 #endif
 
-#ifdef TARGET_PAGE_BITS_VARY
-int target_page_bits;
-bool target_page_bits_decided;
-#endif
-
 CPUTailQ cpus = QTAILQ_HEAD_INITIALIZER(cpus);
 
 /* current CPU in the current thread. It is only valid inside
@@ -110,37 +105,8 @@ int use_icount;
 uintptr_t qemu_host_page_size;
 intptr_t qemu_host_page_mask;
 
-bool set_preferred_target_page_bits(int bits)
-{
-/* The target page size is the lowest common denominator for all
- * the CPUs in the system, so we can only make it smaller, never
- * larger. And we can't make it smaller once we've committed to
- * a particular size.
- */
-#ifdef TARGET_PAGE_BITS_VARY
-assert(bits >= TARGET_PAGE_BITS_MIN);
-if (target_page_bits == 0 || target_page_bits > bits) {
-if (target_page_bits_decided) {
-return false;
-}
-target_page_bits = bits;
-}
-#endif
-return true;
-}
-
 #if !defined(CONFIG_USER_ONLY)
 
-static void finalize_target_page_bits(void)
-{
-#ifdef TARGET_PAGE_BITS_VARY
-if (target_page_bits == 0) {
-target_page_bits = TARGET_PAGE_BITS_MIN;
-}
-target_page_bits_decided = true;
-#endif
-}
-
 typedef struct PhysPageEntry PhysPageEntry;
 
 struct PhysPageEntry {
-- 
2.17.1




[PATCH 1/7] exec: Use TARGET_PAGE_BITS_MIN for TLB flags

2019-09-19 Thread Richard Henderson
These bits do not need to vary with the actual page size
used by the guest.

Signed-off-by: Richard Henderson 
---
 include/exec/cpu-all.h | 16 ++--
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index d2d443c4f9..e0c8dc540c 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -317,20 +317,24 @@ CPUArchState *cpu_copy(CPUArchState *env);
 
 #if !defined(CONFIG_USER_ONLY)
 
-/* Flags stored in the low bits of the TLB virtual address.  These are
- * defined so that fast path ram access is all zeros.
+/*
+ * Flags stored in the low bits of the TLB virtual address.
+ * These are defined so that fast path ram access is all zeros.
  * The flags all must be between TARGET_PAGE_BITS and
  * maximum address alignment bit.
+ *
+ * Use TARGET_PAGE_BITS_MIN so that these bits are constant
+ * when TARGET_PAGE_BITS_VARY is in effect.
  */
 /* Zero if TLB entry is valid.  */
-#define TLB_INVALID_MASK(1 << (TARGET_PAGE_BITS - 1))
+#define TLB_INVALID_MASK(1 << (TARGET_PAGE_BITS_MIN - 1))
 /* Set if TLB entry references a clean RAM page.  The iotlb entry will
contain the page physical address.  */
-#define TLB_NOTDIRTY(1 << (TARGET_PAGE_BITS - 2))
+#define TLB_NOTDIRTY(1 << (TARGET_PAGE_BITS_MIN - 2))
 /* Set if TLB entry is an IO callback.  */
-#define TLB_MMIO(1 << (TARGET_PAGE_BITS - 3))
+#define TLB_MMIO(1 << (TARGET_PAGE_BITS_MIN - 3))
 /* Set if TLB entry contains a watchpoint.  */
-#define TLB_WATCHPOINT  (1 << (TARGET_PAGE_BITS - 4))
+#define TLB_WATCHPOINT  (1 << (TARGET_PAGE_BITS_MIN - 4))
 
 /* Use this mask to check interception with an alignment mask
  * in a TCG backend.
-- 
2.17.1




[PATCH 6/7] exec: Tidy TARGET_PAGE_ALIGN

2019-09-19 Thread Richard Henderson
Use TARGET_PAGE_MASK twice instead of TARGET_PAGE_SIZE once.
This is functionally identical, but will help a following patch.

Signed-off-by: Richard Henderson 
---
 include/exec/cpu-all.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 34d36cebca..5246770271 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -226,7 +226,8 @@ extern const TargetPageBits target_page;
 
 #define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS)
 #define TARGET_PAGE_MASK ((target_long)-1 << TARGET_PAGE_BITS)
-#define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & 
TARGET_PAGE_MASK)
+#define TARGET_PAGE_ALIGN(addr) \
+(((addr) + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK)
 
 /* Using intptr_t ensures that qemu_*_page_mask is sign-extended even
  * when intptr_t is 32-bit and we are aligning a long long.
-- 
2.17.1




[PATCH] Acceptance tests: use avocado.utils.ssh for SSH interaction

2019-09-19 Thread Cleber Rosa
This replaces paramiko with avocado.utils.ssh module, which is based
on a (open)ssh binary, supposedly more ubiquitous.

Signed-off-by: Cleber Rosa 
---
 tests/acceptance/linux_ssh_mips_malta.py | 74 
 tests/requirements.txt   |  3 +-
 2 files changed, 25 insertions(+), 52 deletions(-)

diff --git a/tests/acceptance/linux_ssh_mips_malta.py 
b/tests/acceptance/linux_ssh_mips_malta.py
index 134f10cac3..30c65568ce 100644
--- a/tests/acceptance/linux_ssh_mips_malta.py
+++ b/tests/acceptance/linux_ssh_mips_malta.py
@@ -9,13 +9,14 @@ import os
 import re
 import base64
 import logging
-import paramiko
 import time
 
 from avocado import skipIf
+from avocado import skipUnless
 from avocado_qemu import Test
 from avocado.utils import process
 from avocado.utils import archive
+from avocado.utils import ssh
 
 
 class LinuxSSH(Test):
@@ -26,35 +27,18 @@ class LinuxSSH(Test):
 VM_IP = '127.0.0.1'
 
 IMAGE_INFO = {
-'be': {
-'image_url': 'https://people.debian.org/~aurel32/qemu/mips/'
- 'debian_wheezy_mips_standard.qcow2',
-'image_hash': '8987a63270df67345b2135a6b7a4885a35e392d5',
-'rsa_hostkey': b'B3NzaC1yc2EDAQABAAABAQCca1VitiyLAdQOld'
-   b'zT43IOEVJZ0wHD78GJi8wDAjMiYWUzNSSn0rXGQsINHuH5'
-   b'IlF+kBZsHinb/FtKCAyS9a8uCHhQI4SuB4QhAb0+39MlUw'
-   b'Mm0CLkctgM2eUUZ6MQMQvDlqnue6CCkxN62EZYbaxmby7j'
-   b'CQa1125o1HRKBvdGm2zrJWxXAfA+f1v6jHLyE8Jnu83eQ+'
-   b'BFY25G+Vzx1PVc3zQBwJ8r0NGTRqy2//oWQP0h+bMsgeFe'
-   b'KH/J3RJM22vg6+I4JAdBFcxnK+l781h1FuRxOn4O/Xslbg'
-   b'go6WtB4V4TOsw2E/KfxI5IZ/icxF+swVcnvF46Hf3uQc/0'
-   b'BBqb',
-},
-'le': {
-'image_url': 'https://people.debian.org/~aurel32/qemu/mipsel/'
- 'debian_wheezy_mipsel_standard.qcow2',
-'image_hash': '7866764d9de3ef536ffca24c9fb9f04ffdb45802',
-'rsa_hostkey': b'B3NzaC1yc2EDAQABAAABAQClXJlBT71HL5yKvv'
-   b'gfC7jmxSWx5zSBCzET6CLZczwAafSIs7YKfNOy/dQTxhuk'
-   b'yIGFUugZFoF3E9PzdhunuyvyTd56MPoNIqFbb5rGokwU5I'
-   b'TOx3dBHZR0mClypL6MVrwe0bsiIb8GhF1zioNwcsaAZnAi'
-   b'KfXStVDtXvn/kLLq+xLABYt48CC5KYWoFaCoICskLAY+qo'
-   b'L+LWyAnQisj4jAH8VSaSKIImFpfkHWEXPhHcC4ZBlDKtnH'
-   b'po9vhfCHgnfW3Pzrqmk8BI4HysqPFVmJWkJGlGUL+sGeg3'
-   b'ZZolAYuDXGuBrw8ooPJq2v2dOH+z6dyD2q/ypmAbyPqj5C'
-   b'rc8H',
-},
-}
+'be': {'image_url': ('https://people.debian.org/~aurel32/qemu/mips/'
+ 'debian_wheezy_mips_standard.qcow2'),
+   'image_hash': '8987a63270df67345b2135a6b7a4885a35e392d5'},
+'le': {'image_url': ('https://people.debian.org/~aurel32/qemu/mipsel/'
+ 'debian_wheezy_mipsel_standard.qcow2'),
+   'image_hash': '7866764d9de3ef536ffca24c9fb9f04ffdb45802'}
+}
+
+
+@skipUnless(ssh.SSH_CLIENT_BINARY, 'No SSH client available')
+def setUp(self):
+super(LinuxSSH, self).setUp()
 
 def wait_for_console_pattern(self, success_message,
  failure_message='Oops'):
@@ -78,23 +62,14 @@ class LinuxSSH(Test):
 self.log.debug("sshd listening on port:" + port)
 return port
 
-def ssh_connect(self, username, password, rsa_hostkey_b64=None):
+def ssh_connect(self, username, password):
 self.ssh_logger = logging.getLogger('ssh')
-self.ssh_username = username
-self.ssh_ps1 = '# ' if username is 'root' else '$ '
-self.ssh_client = paramiko.SSHClient()
 port = self.get_portfwd()
-if rsa_hostkey_b64:
-rsa_hostkey_bin = base64.b64decode(rsa_hostkey_b64)
-rsa_hostkey = paramiko.RSAKey(data = rsa_hostkey_bin)
-ipport = '[%s]:%s' % (self.VM_IP, port)
-self.ssh_logger.debug('ipport ' + ipport)
-self.ssh_client.get_host_keys().add(ipport, 'ssh-rsa', rsa_hostkey)
+self.ssh_session = ssh.Session(self.VM_IP, port=int(port),
+   user=username, password=password)
 for i in range(10):
 try:
-self.ssh_client.connect(self.VM_IP, int(port),
-username, password, banner_timeout=90)
-self.ssh_logger.info("Entering interactive session.")
+self.ssh_session.connect()
 return
 except:
 time.sleep(4)
@@ -102,15 +77,15 @@ class LinuxSSH(Test):
 self.fail("sshd timeout")
 
 def ssh_disconnect_vm(self):
-self.ssh_client.close()
+

RE: [Qemu-devel] vhost, iova, and dirty page tracking

2019-09-19 Thread Tian, Kevin
> From: Paolo Bonzini [mailto:pbonz...@redhat.com]
> Sent: Thursday, September 19, 2019 7:14 PM
> 
> On 19/09/19 09:16, Tian, Kevin wrote:
> >>> why GPA1 and GPA2 should be both dirty?
> >>> even they have the same HVA due to overlaping virtual address space
> in
> >>> two processes, they still correspond to two physical pages.
> >>> don't get what's your meaning :)
> >>
> >> The point is not leave any corner case that is hard to debug or fix in
> >> the future.
> >>
> >> Let's just start by a single process, the API allows userspace to maps
> >> HVA to both GPA1 and GPA2. Since it knows GPA1 and GPA2 are
> equivalent,
> >> it's ok to sync just through GPA1. That means if you only log GPA2, it
> >> won't work.
> >
> > I noted KVM itself doesn't consider such situation (one HVA is mapped
> > to multiple GPAs), when doing its dirty page tracking. If you look at
> > kvm_vcpu_mark_page_dirty, it simply finds the unique memslot which
> > contains the dirty gfn and then set the dirty bit within that slot. It
> > doesn't attempt to walk all memslots to find out any other GPA which
> > may be mapped to the same HVA.
> >
> > So there must be some disconnect here. let's hear from Paolo first and
> > understand the rationale behind such situation.
> 
> In general, userspace cannot assume that it's okay to sync just through
> GPA1.  It must sync the host page if *either* GPA1 or GPA2 are marked
> dirty.

Agree. In this case the kernel only needs to track whether GPA1 or
GPA2 is dirtied by guest operations. The reason why vhost has to
set both GPA1 and GPA2 is due to its own design - it maintains
IOVA->HVA and GPA->HVA mappings thus given a IOVA you have
to reverse lookup GPA->HVA memTable which gives multiple possible
GPAs. But in concept if vhost can maintain a IOVA->GPA mapping,
then it is straightforward to set the right GPA every time when a IOVA
is tracked.

> 
> The situation really only arises in special cases.  For example,
> 0xfffe..0x and 0xe..0xf might be the same memory.
> From "info mtree" before the guest boots:
> 
> - (prio -1, i/o): pci
>   000e-000f (prio 1, i/o): alias isa-bios
> @pc.bios 0002-0003
>   fffc- (prio 0, rom): pc.bios
> 
> However, non-x86 machines may have other cases of aliased memory so
> it's
> a case that you should cover.
> 

Above example is read-only, thus won't be touched in logdirty path.
But now I agree that a specific architecture may define two
writable GPA ranges with one as the alias to the other, as long as
such case is explicitly documented so guest OS won't treat them as
separate memory pages.

Thanks
Kevin


RE: [Qemu-devel] vhost, iova, and dirty page tracking

2019-09-19 Thread Tian, Kevin
> From: Alex Williamson [mailto:alex.william...@redhat.com]
> Sent: Friday, September 20, 2019 1:21 AM
> 
> On Wed, 18 Sep 2019 07:21:05 +
> "Tian, Kevin"  wrote:
> 
> > > From: Jason Wang [mailto:jasow...@redhat.com]
> > > Sent: Wednesday, September 18, 2019 2:04 PM
> > >
> > > On 2019/9/18 上午9:31, Tian, Kevin wrote:
> > > >> From: Alex Williamson [mailto:alex.william...@redhat.com]
> > > >> Sent: Tuesday, September 17, 2019 10:54 PM
> > > >>
> > > >> On Tue, 17 Sep 2019 08:48:36 +
> > > >> "Tian, Kevin"  wrote:
> > > >>
> > >  From: Jason Wang [mailto:jasow...@redhat.com]
> > >  Sent: Monday, September 16, 2019 4:33 PM
> > > 
> > > 
> > >  On 2019/9/16 上午9:51, Tian, Kevin wrote:
> > > > Hi, Jason
> > > >
> > > > We had a discussion about dirty page tracking in VFIO, when
> > > vIOMMU
> > > > is enabled:
> > > >
> > > > https://lists.nongnu.org/archive/html/qemu-devel/2019-
> > >  09/msg02690.html
> > > > It's actually a similar model as vhost - Qemu cannot interpose the
> > > fast-
> > >  path
> > > > DMAs thus relies on the kernel part to track and report dirty page
> > >  information.
> > > > Currently Qemu tracks dirty pages in GFN level, thus demanding a
> > >  translation
> > > > from IOVA to GPA. Then the open in our discussion is where this
> > >  translation
> > > > should happen. Doing the translation in kernel implies a device
> iotlb
> > >  flavor,
> > > > which is what vhost implements today. It requires potentially
> large
> > >  tracking
> > > > structures in the host kernel, but leveraging the existing log_sync
> > > flow
> > > >> in
> > >  Qemu.
> > > > On the other hand, Qemu may perform log_sync for every
> removal
> > > of
> > >  IOVA
> > > > mapping and then do the translation itself, then avoiding the GPA
> > >  awareness
> > > > in the kernel side. It needs some change to current Qemu log-
> sync
> > > >> flow,
> > >  and
> > > > may bring more overhead if IOVA is frequently unmapped.
> > > >
> > > > So we'd like to hear about your opinions, especially about how
> you
> > > >> came
> > > > down to the current iotlb approach for vhost.
> > >  We don't consider too much in the point when introducing vhost.
> And
> > >  before IOTLB, vhost has already know GPA through its mem table
> > >  (GPA->HVA). So it's nature and easier to track dirty pages at GPA
> level
> > >  then it won't any changes in the existing ABI.
> > > >>> This is the same situation as VFIO.
> > > >> It is?  VFIO doesn't know GPAs, it only knows HVA, HPA, and IOVA.
> In
> > > >> some cases IOVA is GPA, but not all.
> > > > Well, I thought vhost has a similar design, that the index of its mem
> table
> > > > is GPA when vIOMMU is off and then becomes IOVA when vIOMMU is
> on.
> > > > But I may be wrong here. Jason, can you help clarify? I saw two
> > > > interfaces which poke the mem table: VHOST_SET_MEM_TABLE (for
> GPA)
> > > > and VHOST_IOTLB_UPDATE (for IOVA). Are they used exclusively or
> > > together?
> > > >
> > >
> > > Actually, vhost maintains two interval trees, mem table GPA->HVA, and
> > > device IOTLB IOVA->HVA. Device IOTLB is only used when vIOMMU is
> > > enabled, and in that case mem table is used only when vhost need to
> > > track dirty pages (do reverse lookup of memtable to get HVA->GPA). So
> in
> > > conclusion, for datapath, they are used exclusively, but they need
> > > cowork for logging dirty pages when device IOTLB is enabled.
> > >
> >
> > OK. Then it's different from current VFIO design, which maintains only
> > one tree which is indexed by either GPA or IOVA exclusively, upon
> > whether vIOMMU is in use.
> 
> Nit, the VFIO tree is only ever indexed by IOVA.  The MAP_DMA ioctl is
> only ever performed with an IOVA.  Userspace decides how that IOVA
> maps
> to GPA, VFIO only needs to know how the IOVA maps to HPA via the HVA.
> Thanks,
> 

I was only referring to its actual meaning from usage p.o.v, not the 
parameter name (which is always called iova) in vfio. 

Thanks
Kevin


[PATCH v1 5/6] riscv/virt: Add the PFlash CFI01 device

2019-09-19 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 
---
 hw/riscv/Kconfig|  1 +
 hw/riscv/virt.c | 81 +
 include/hw/riscv/virt.h |  3 ++
 3 files changed, 85 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 d36f5625ec..ca002ecea7 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,72 @@ 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);
+
+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 +182,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 +379,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, 2, flashsize);
+qemu_fdt_setprop_cell(s->fdt, nodename, "bank-width", 4);
+g_free(nodename);
 }
 
 
@@ -496,6 +568,15 @@ static void riscv_virt_board_init(MachineState *machine)
 0, qdev_get_gpio_in(DEVICE(s->plic), UART0_IRQ), 399193,
 

[PATCH v1 6/6] riscv/virt: Jump to pflash if specified

2019-09-19 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 
---
 hw/riscv/virt.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index ca002ecea7..ed25cc6761 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -441,6 +441,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;
 
@@ -487,6 +488,13 @@ 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) */
@@ -499,7 +507,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 v1 3/6] riscv/sifive_u: Manually define the machine

2019-09-19 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 
---
 hw/riscv/sifive_u.c | 27 +++
 include/hw/riscv/sifive_u.h |  7 ++-
 2 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 9c5d791320..c3949fb316 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);
@@ -545,8 +544,15 @@ 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)
+static void riscv_sifive_u_machine_instance_init(Object *obj)
+{
+
+}
+
+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;
@@ -554,7 +560,20 @@ static void riscv_sifive_u_machine_init(MachineClass *mc)
 mc->default_cpus = mc->min_cpus;
 }
 
-DEFINE_MACHINE("sifive_u", riscv_sifive_u_machine_init)
+static const TypeInfo riscv_sifive_u_machine_init_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_init_typeinfo);
+}
+
+type_init(riscv_sifive_u_machine_init_register_types)
 
 static void riscv_sifive_u_soc_class_init(ObjectClass *oc, void *data)
 {
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 v1 1/6] riscv/sifive_u: Add L2-LIM cache memory

2019-09-19 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 
---
 hw/riscv/sifive_u.c | 15 +++
 include/hw/riscv/sifive_u.h |  1 +
 2 files changed, 16 insertions(+)

diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 9f8e84bf2e..de6e197882 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,  0x1e0 },
 [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,19 @@ 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 v1 2/6] riscv/sifive_u: Add QSPI memory region

2019-09-19 Thread Alistair Francis
There doesn't seem to be details on what QSPI the HiFive Unleashed uses.
To allow boot firmware developers to use QEMU to target the Unleashed
let's add a chunk of memory to represent the QSPI. This can be targeted
using QEMU's -device loader command line option.

Signed-off-by: Alistair Francis 
---
 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 de6e197882..9c5d791320 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,  0x200 },
 [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 v1 4/6] riscv/sifive_u: Add the start-in-flash property

2019-09-19 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 
---
 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 c3949fb316..b7cd3631cd 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]);
@@ -544,8 +548,31 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, 
Error **errp)
 memmap[SIFIVE_U_GEM_MGMT].base, memmap[SIFIVE_U_GEM_MGMT].size);
 }
 
+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);
 
 }
 
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 v1 0/6] RISC-V: Add more machine memory

2019-09-19 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.

Alistair Francis (6):
  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: Add the PFlash CFI01 device
  riscv/virt: Jump to pflash if specified

 hw/riscv/Kconfig|  1 +
 hw/riscv/sifive_u.c | 77 +--
 hw/riscv/virt.c | 91 -
 include/hw/riscv/sifive_u.h | 11 -
 include/hw/riscv/virt.h |  3 ++
 5 files changed, 177 insertions(+), 6 deletions(-)

-- 
2.23.0




Re: [PATCH v2 14/16] configure: preserve PKG_CONFIG for subdir builds

2019-09-19 Thread Richard Henderson
On 9/19/19 10:10 AM, Alex Bennée wrote:
> The slirp sub-module complains about not being able to find the glib
> library on cross-compiles because it is using the default pkg-config
> tool (which isn't installed in our cross-build docker images).
> Preserve PKG_CONFIG in our host config and pass it down to slirp.
> 
> Signed-off-by: Alex Bennée 
> ---

Reviewed-by: Richard Henderson 


r~



Re: [PATCH v2 09/16] tests/tcg: add float_madds test to multiarch

2019-09-19 Thread Richard Henderson
On 9/19/19 10:10 AM, Alex Bennée wrote:
> This is a generic floating point multiply and accumulate test for
> single precision floating point values. I've split of the common float
> functions into a helper library so additional tests can use the same
> common code.
> 
> As I don't have references for all architectures I've allowed some
> flexibility for tests to pass without reference files. They can be
> added as we get collect them.
> 
> Signed-off-by: Alex Bennée 
> 
> ---
> v2
>   - allow tests to add addition patterns to the list
>   - conditional diff-out
>   - use __builtin_fmaf instead of forcing optimisation
>   - use hex floating point definitions and output
> v3
>   - remove add_const stuff, make explicit tests explicit
>   - various style clean-ups
> ---

Reviewed-by: Richard Henderson 


r~



Re: [PATCH] Acceptance test machine_m68k_nextcube.py: relax the error code pattern

2019-09-19 Thread Cleber Rosa
On Thu, Sep 19, 2019 at 09:26:35PM +0200, Thomas Huth wrote:
> Am Thu, 19 Sep 2019 18:19:40 +0200
> schrieb Philippe Mathieu-Daudé :
> 
> > Cc'ing Thomas
> > 
> > On 9/19/19 6:14 PM, Cleber Rosa wrote:
> > > Instead of looking for a specific error, let's relax the pattern
> > > because different errors have been seen (I'm consistenly getting 52)
> > > and the real goal of this test is to validate the framebuffer
> > > operation, and not to reproduce one specific error.  
> > 
> > This might be because I wrote this test before Thomas added the serial
> > controller (commit b17bed5b1727e3aa9e37fc8e8c3222130ceab22f).
> 
> That's strange, the travis job worked fine for me ... but sure, let's
> drop the error number, we don't need it here. 
> 
> > > Signed-off-by: Cleber Rosa 
> > > ---
> > >  tests/acceptance/machine_m68k_nextcube.py | 2 +-
> > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > > 
> > > diff --git a/tests/acceptance/machine_m68k_nextcube.py
> > > b/tests/acceptance/machine_m68k_nextcube.py index
> > > e09cab9f20..fcd2c58ee7 100644 ---
> > > a/tests/acceptance/machine_m68k_nextcube.py +++
> > > b/tests/acceptance/machine_m68k_nextcube.py @@ -116,6 +116,6 @@
> > > class NextCubeMachine(Test): if len(line):
> > >  console_logger.debug(line)
> > >  self.assertIn('Testing the FPU, SCC', text)
> > > -self.assertIn('System test failed. Error code 51', text)
> > > +self.assertIn('System test failed. Error code', text)
> > >  self.assertIn('Boot command', text)  
> > >  self.assertIn('Next>', text)  
> > >   
> > 
> > Reviewed-by: Philippe Mathieu-Daudé 
> 
> Reviewed-by: Thomas Huth 

Thanks for the prompt review, queueing on my python-next branch.

- Cleber.



Re: [RFC 4/4] ahci media error reporting

2019-09-19 Thread Tony Asleson
On 9/19/19 3:43 PM, John Snow wrote:
> 
> 
> On 9/19/19 3:48 PM, Tony Asleson wrote:
>> Initial attempt at returning a media error for ahci.  This is certainly
>> wrong and needs serious improvement.
>>
> 
> Hi; I have the unfortunate distinction of being the AHCI maintainer.
> Please CC me on future revisions and discussion if you are interacting
> with my problem child.

Will do and thank you for taking a look at this!

> Also remember to CC qemu-block.
> 
>> Signed-off-by: Tony Asleson 
>> ---
>>  hw/ide/ahci.c | 27 +++
>>  1 file changed, 27 insertions(+)
>>
>> diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
>> index d45393c019..f487764106 100644
>> --- a/hw/ide/ahci.c
>> +++ b/hw/ide/ahci.c
>> @@ -36,6 +36,7 @@
>>  #include "hw/ide/internal.h"
>>  #include "hw/ide/pci.h"
>>  #include "ahci_internal.h"
>> +#include "block/error_inject.h"
>>  
>>  #include "trace.h"
>>  
>> @@ -999,6 +1000,22 @@ static void ncq_err(NCQTransferState *ncq_tfs)
>>  ncq_tfs->used = 0;
>>  }
>>  
>> +/*
>> + * Figure out correct way to report media error, this is at best a guess
>> + * and based on the output of linux kernel, not even remotely close.
>> + */
> 
> Depends on what kind of error, exactly, you're trying to report, and at
> what level. (AHCI, NCQ, SATA, ATA?)

I was trying to return a media error, like a 3/1101 for SCSI device.  I
think that is at the ATA level?


> Keep in mind that you've inserted an error path for SATA drives using
> NCQ, but seemingly haven't touched SATA drives not using NCQ, or ATAPI
> devices using either PATA/SATA, or ATA drives on PATA.

Correct, but for trying out a simple read on a SATA drive for Linux I
end up here first :-)  Well, until the kernel retries a number of times
and finally gives up and returns an error while also disabling NCQ for
the device.


>> +static void ncq_media_err(NCQTransferState *ncq_tfs, uint64_t err_sector)
>> +{
>> +IDEState *ide_state = _tfs->drive->port.ifs[0];
>> +
>> +ide_state->error = ECC_ERR;
>> +ide_state->status = READY_STAT | ERR_STAT;
>> +ncq_tfs->drive->port_regs.scr_err |= (1 << ncq_tfs->tag);
>> +ncq_tfs->lba = err_sector;
>> +qemu_sglist_destroy(_tfs->sglist);
>> +ncq_tfs->used = 0;
>> +}
>> +
> 
> If you are definitely very sure you only want an ide_state error
> difference, you could just as well call ncq_err and then patch
> ide_state->error.
> 
> (I am not sure that's what you want, but... maybe it is?)

As I mentioned above, return an unrecoverable media error.

SCSI sense data can report the first sector in error and I thought I
could do the same for SATA too?

> I'd have to check -- because I can't say the AHCI emulator was designed
> so much as congealed -- but you might need calls to ncq_finish.
> 
> usually, ncq_cb handles the return from any NCQ command and will call
> ncq_err and ncq_finish as appropriate to tidy up the command.
> 
> It might be a mistake that execute_ncq_command issues ncq_err in the
> `default` arm of the switch statement without a call to finish.
> 
> If we do call ncq_finish from this context I'm not sure if we want
> block_acct_done here unconditionally. We may not have started a block
> accounting operation if we never started a backend operation. Everything
> else looks about right to me.
> 
> 
>>  static void ncq_finish(NCQTransferState *ncq_tfs)
>>  {
>>  /* If we didn't error out, set our finished bit. Errored commands
>> @@ -1065,6 +1082,8 @@ static void execute_ncq_command(NCQTransferState 
>> *ncq_tfs)
>>  {
>>  AHCIDevice *ad = ncq_tfs->drive;
>>  IDEState *ide_state = >port.ifs[0];
>> +uint64_t error_sector = 0;
>> +char device_id[32];
>>  int port = ad->port_no;
>>  
>>  g_assert(is_ncq(ncq_tfs->cmd));
>> @@ -1072,6 +1091,14 @@ static void execute_ncq_command(NCQTransferState 
>> *ncq_tfs)
>>  
>>  switch (ncq_tfs->cmd) {
>>  case READ_FPDMA_QUEUED:
>> +sprintf(device_id, "%lu", ide_state->wwn);
> 
> This seems suspicious for your design in general, but I'd like to not
> run sprintf to a buffer in the hotpath for NCQ.

I totally agree.

I started out using integers in the call for error_in_read, as that is
what SCSI uses internally for wwn.  Then I did NVMe and it's using a
string that doesn't apparently need to be an integer for the wwn? so I
changed it to being a string to accommodate.

I also find it interesting that when a SATA device wwid is dumped out
within the guest it doesn't appear to have any correlation with the wwn
that was passed in on the command line, eg.

-device ide-drive,drive=satadisk,bus=ahci.0,wwn=8675309

$cat /sys/block/sda/device/wwid
t10.ATA QEMU HARDDISK   QM5


This does correlate for SCSI

-device scsi-hd,drive=hd,wwn=12345678

$ cat /sys/block/sdc/device/wwid
naa.00bc614e


as 0xbc614e = 12345678


For NVMe, the wwn is in the wwid, but it's not immediately obvious.

Being able to correlate between the command line and what you find in

Re: [PATCH v2 10/16] tests/tcg: add generic version of float_convs

2019-09-19 Thread Richard Henderson
On 9/19/19 10:10 AM, Alex Bennée wrote:
> This is broadly similar to the existing fcvt test for ARM but using
> the generic float testing framework. We should be able to pare down
> the ARM fcvt test case to purely half-precision with or without the
> Alt HP provision.
> 
> Signed-off-by: Alex Bennée 
> ---

Reviewed-by: Richard Henderson 


r~



Re: [Qemu-devel] [PATCH 00/21] aspeed: Add support for the AST2600 SoC

2019-09-19 Thread no-reply
Patchew URL: https://patchew.org/QEMU/20190919055002.6729-1-...@kaod.org/



Hi,

This series failed the docker-quick@centos7 build test. Please find the testing 
commands and
their output below. If you have Docker installed, you can probably reproduce it
locally.

=== TEST SCRIPT BEGIN ===
#!/bin/bash
make docker-image-centos7 V=1 NETWORK=1
time make docker-test-quick@centos7 SHOW_ENV=1 J=14 NETWORK=1
=== TEST SCRIPT END ===

libudev   no
default devices   yes

warning: Python 2 support is deprecated
warning: Python 3 will be required for building future versions of QEMU
cross containers  no

NOTE: guest cross-compilers enabled: cc
---
Property '.cntfrq' not found
Broken pipe
/tmp/qemu-test/src/tests/libqtest.c:149: kill_qemu() detected QEMU death from 
signal 6 (Aborted) (core dumped)
ERROR - too few tests run (expected 6, got 5)
make: *** [check-qtest-aarch64] Error 1
make: *** Waiting for unfinished jobs
  TESTcheck-qtest-x86_64: tests/q35-test


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

Re: [Qemu-devel] [PULL 0/4] Ui 20190919 patches

2019-09-19 Thread no-reply
Patchew URL: https://patchew.org/QEMU/20190919070918.16059-1-kra...@redhat.com/



Hi,

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

Message-id: 20190919070918.16059-1-kra...@redhat.com
Subject: [Qemu-devel] [PULL 0/4] Ui 20190919 patches
Type: series

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
Switched to a new branch 'test'
8c23403 vnc: fix memory leak when vnc disconnect
43a8bdb ui: add an embedded Barrier client
7dc6f4c vnc: fix websocket field in events
aca6a4a ui/egl: fix framebuffer reads

=== OUTPUT BEGIN ===
1/4 Checking commit aca6a4ab1693 (ui/egl: fix framebuffer reads)
2/4 Checking commit 7dc6f4caa2ef (vnc: fix websocket field in events)
3/4 Checking commit 43a8bdb1f7e6 (ui: add an embedded Barrier client)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#60: 
new file mode 100644

total: 0 errors, 1 warnings, 1239 lines checked

Patch 3/4 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
4/4 Checking commit 8c234039a34e (vnc: fix memory leak when vnc disconnect)
ERROR: spaces required around that '*' (ctx:WxB)
#120: FILE: ui/vnc-enc-tight.c:355:
+data = (uint##bpp##_t *)vs->tight->tight.buffer;\
   ^

total: 1 errors, 0 warnings, 869 lines checked

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

=== OUTPUT END ===

Test command exited with code: 1


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

[PATCH 12/15] ipmi: Add an SMBus IPMI interface

2019-09-19 Thread minyard
From: Corey Minyard 

Signed-off-by: Corey Minyard 
---
 default-configs/i386-softmmu.mak |   1 +
 hw/i386/Kconfig  |   1 +
 hw/ipmi/Kconfig  |   5 +
 hw/ipmi/Makefile.objs|   1 +
 hw/ipmi/smbus_ipmi.c | 384 +++
 5 files changed, 392 insertions(+)
 create mode 100644 hw/ipmi/smbus_ipmi.c

diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 2294c0be5a..4229900f57 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -12,6 +12,7 @@
 #CONFIG_ISA_IPMI_KCS=n
 #CONFIG_PCI_IPMI_KCS=n
 #CONFIG_PCI_IPMI_BT=n
+#CONFIG_IPMI_SSIF=n
 #CONFIG_PCI_DEVICES=n
 #CONFIG_PVPANIC=n
 #CONFIG_QXL=n
diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
index d10f4e3e8b..c5c9d4900e 100644
--- a/hw/i386/Kconfig
+++ b/hw/i386/Kconfig
@@ -10,6 +10,7 @@ config PC
 imply ISA_IPMI_BT
 imply PCI_IPMI_KCS
 imply PCI_IPMI_BT
+imply IPMI_SSIF
 imply ISA_DEBUG
 imply PARALLEL
 imply PCI_DEVICES
diff --git a/hw/ipmi/Kconfig b/hw/ipmi/Kconfig
index 12db4e81ad..9befd4f422 100644
--- a/hw/ipmi/Kconfig
+++ b/hw/ipmi/Kconfig
@@ -30,3 +30,8 @@ config PCI_IPMI_BT
 bool
 depends on PCI
 select IPMI
+
+config IPMI_SSIF
+bool
+depends on I2C
+select IPMI
diff --git a/hw/ipmi/Makefile.objs b/hw/ipmi/Makefile.objs
index 2d7f080a86..3cca10bc50 100644
--- a/hw/ipmi/Makefile.objs
+++ b/hw/ipmi/Makefile.objs
@@ -5,3 +5,4 @@ common-obj-$(CONFIG_ISA_IPMI_KCS) += isa_ipmi_kcs.o
 common-obj-$(CONFIG_PCI_IPMI_KCS) += pci_ipmi_kcs.o
 common-obj-$(CONFIG_ISA_IPMI_BT) += isa_ipmi_bt.o
 common-obj-$(CONFIG_PCI_IPMI_BT) += pci_ipmi_bt.o
+common-obj-$(CONFIG_IPMI_SSIF) += smbus_ipmi.o
diff --git a/hw/ipmi/smbus_ipmi.c b/hw/ipmi/smbus_ipmi.c
new file mode 100644
index 00..2a9470d9df
--- /dev/null
+++ b/hw/ipmi/smbus_ipmi.c
@@ -0,0 +1,384 @@
+/*
+ * QEMU IPMI SMBus (SSIF) emulation
+ *
+ * Copyright (c) 2015,2016 Corey Minyard, MontaVista Software, LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "migration/vmstate.h"
+#include "hw/i2c/smbus_slave.h"
+#include "qapi/error.h"
+#include "qemu/error-report.h"
+#include "hw/ipmi/ipmi.h"
+
+#define TYPE_SMBUS_IPMI "smbus-ipmi"
+#define SMBUS_IPMI(obj) OBJECT_CHECK(SMBusIPMIDevice, (obj), TYPE_SMBUS_IPMI)
+
+#define SSIF_IPMI_REQUEST   2
+#define SSIF_IPMI_MULTI_PART_REQUEST_START  6
+#define SSIF_IPMI_MULTI_PART_REQUEST_MIDDLE 7
+#define SSIF_IPMI_MULTI_PART_REQUEST_END8
+#define SSIF_IPMI_RESPONSE  3
+#define SSIF_IPMI_MULTI_PART_RESPONSE_MIDDLE9
+#define SSIF_IPMI_MULTI_PART_RETRY  0xa
+
+#define MAX_SSIF_IPMI_MSG_SIZE 255
+#define MAX_SSIF_IPMI_MSG_CHUNK 32
+
+#define IPMI_GET_SYS_INTF_CAP_CMD 0x57
+
+typedef struct SMBusIPMIDevice {
+SMBusDevice parent;
+
+IPMIBmc *bmc;
+
+uint8_t outmsg[MAX_SSIF_IPMI_MSG_SIZE];
+uint32_t outlen;
+uint32_t currblk;
+
+/* Holds the SMBUS message currently being sent to the host. */
+uint8_t outbuf[MAX_SSIF_IPMI_MSG_CHUNK + 1]; /* len + message. */
+uint32_t outpos;
+
+uint8_t inmsg[MAX_SSIF_IPMI_MSG_SIZE];
+uint32_t inlen;
+
+/*
+ * This is a response number that we send with the command to make
+ * sure that the response matches the command.
+ */
+uint8_t waiting_rsp;
+
+uint32_t uuid;
+} SMBusIPMIDevice;
+
+static void smbus_ipmi_handle_event(IPMIInterface *ii)
+{
+/* No interrupts, so nothing to do here. */
+}
+
+static void smbus_ipmi_handle_rsp(IPMIInterface *ii, uint8_t msg_id,
+  unsigned char *rsp, unsigned int rsp_len)
+{
+SMBusIPMIDevice *sid = SMBUS_IPMI(ii);
+
+if (sid->waiting_rsp == msg_id) {
+sid->waiting_rsp++;
+
+if (rsp_len > MAX_SSIF_IPMI_MSG_SIZE) {
+rsp[2] = IPMI_CC_REQUEST_DATA_TRUNCATED;
+   

Re: [PATCH] edk2 build scripts: work around TianoCore#1607 without forcing Python 2

2019-09-19 Thread Laszlo Ersek
On 09/19/19 21:56, Philippe Mathieu-Daudé wrote:
> On 9/19/19 9:08 PM, Laszlo Ersek wrote:
>> On 09/19/19 18:39, Philippe Mathieu-Daudé wrote:
>>> On 9/18/19 7:11 PM, Laszlo Ersek wrote:
 It turns out that forcing python2 for running the edk2 "build" utility is
 neither necessary nor sufficient.

 Forcing python2 is not sufficient for two reasons:

 - QEMU is moving away from python2, with python2 nearing EOL,

 - according to my most recent testing, the lacking dependency information
   in the makefiles that are generated by edk2's "build" utility can cause
   parallel build failures even when "build" is executed by python2.

 And forcing python2 is not necessary because we can still return to the
 original idea of filtering out jobserver-related options from MAKEFLAGS.
 So do that.
>>>
>>> FYI I tried uninstalling python2 on Fedora 29,
>>>
>>> $ make -C roms efi -j8
>>> make: Entering directory '/home/phil/source/qemu/roms'
>>> make -C edk2/BaseTools \
>>> EXTRA_OPTFLAGS='' \
>>> EXTRA_LDFLAGS=''
> 
> ^ this is the 'edk2-basetools' target from roms/Makefile.
> 
>>> make[1]: Entering directory '/home/phil/source/qemu/roms/edk2/BaseTools'
>>> [...]
>>> make -C Tests
>>> make[2]: Entering directory
>>> '/home/phil/source/qemu/roms/edk2/BaseTools/Tests'
>>> /bin/sh: python: command not found
>>> make[2]: *** [GNUmakefile:11: test] Error 127
>>>
>>> 'python' seems to be provided by python-unversioned-command which is
>>> wired to Python2:
>>>
>>> $ dnf info python-unversioned-command
>>> Last metadata expiration check: 0:03:08 ago on Thu 19 Sep 2019 04:21:21
>>> PM UTC.
>>> Available Packages
>>> Name : python-unversioned-command
>>> Version  : 2.7.16
>>> Release  : 2.fc29
>>> Arch : noarch
>>> Size : 13 k
>>> Source   : python2-2.7.16-2.fc29.src.rpm
>>> Repo : updates
>>> Summary  : The "python" command that runs Python 2
>>> URL  : https://www.python.org/
>>> License  : Python
>>> Description  : This package contains /usr/bin/python - the "python"
>>> command that runs Python 2.
>>>
>>> I had to manually run update-alternatives to continue:
>>>
>>> $ sudo update-alternatives --install /usr/bin/python python
>>> /usr/bin/python3 69
>>>
>>> Not sure this is the expected behavior, it is confusing.
>>>
>>
>> The python detection is not fool-proof in edk2. A description is given at:
>>
>> https://github.com/tianocore/tianocore.github.io/wiki/BaseTools-Support-Python2-Python3
>>
>> To summarize that, it works like this, on Linux:
>>
>> - if you set PYTHON_COMMAND, then the binary pointed to by
>> PYTHON_COMMAND will be used. The edk2 build infrastructure will
>> determine whether the pointed-to binary is python 2 or python 3, and
>> branch to the corresponding implementation of the build tools.
>>
>> - Otherwise, *minor* version auto-detection is attempted. With
>> PYTHON3_ENABLE unset, or set to "TRUE", this minor version autodetection
>> will aim at minor versions of python3.
>>
>> - Otherwise (= PYTHON3_ENABLE set to a string different from "TRUE"),
>> the minor version auto-detection will focus on python2.
> 
> What you document regarding PYTHON3_ENABLE is valid once we sourced
> edksetup.sh which is done in Makefile.edk2, one step after the previous
> call:
> 
> efi: edk2-basetools   # call 1 (python failing)
>   $(MAKE) -f Makefile.edk2  # call 2 sourcing edksetup.sh
> 
>> With this patch applied, the middle case is active. Apparently it fails,
>> because the edk2 build tools developers could not foresee the situations
>> that you've exposed the auto-detection to, on Ubuntu and Fedora. Back
>> when I tested the python3 enablement in edk2, I checked the patches in
>> the following environments:
>>
>> - on RHEL-7 with the system python 2,
>> - on RHEL-7 with python3.4 from EPEL-7,
>> - on RHEL-8 with python3.6,
>> - on RHEL-8 with platform-python.
>>
>> Everything worked fine for me. I have no clue what's going on in Ubuntu
>> and in Fedora.
>>
>> Can we require all build host installations -- where we expect to run
>> "make efi" -- to provide a Python 3 binary on $PATH that is plainly
>> called "python3"?
> 
> Kevin recently suggested a similar patch (in another area):
> https://lists.gnu.org/archive/html/qemu-devel/2019-09/msg04377.html
> 
>> Then I think this patch should work. (If necessary, I could set
>> "PYTHON_COMMAND=python3", too.)
> 
> Yes, I confirm forcing "PYTHON_COMMAND=python3 make -C roms efi" works.
> 
> Not sure what is the cleaner way to fix this although...

Thanks for the analysis!

I understand the issue now.

- "edk2/BaseTools/GNUmakefile" runs $(MAKE) in three subdirs:
  - Source/C,
  - Source/Python,
  - Tests (which depends on the former two)

- "edk2/BaseTools/Source/C/GNUmakefile" builds fine
- "edk2/BaseTools/Source/Python/GNUmakefile" does nothing
- "edk2/BaseTools/Tests/GNUmakefile" depends on PYTHON_COMMAND -- which
  should 

[PATCH 15/15] pc: Add an SMB0 ACPI device to q35

2019-09-19 Thread minyard
From: Corey Minyard 

This is so I2C devices can be found in the ACPI namespace.  Currently
that's only IPMI, but devices can be easily added now.

Adding the devices required some PCI information, and the bus itself
to be added to the PCMachineState structure.

Note that this only works on Q35, the ACPI for PIIX4 is not capable
of handling an SMBus device.

Cc: Michael S. Tsirkin 
Cc: Igor Mammedov 
Signed-off-by: Corey Minyard 
---
 hw/i386/acpi-build.c |  15 +++
 hw/i386/pc_piix.c|  12 ++--
 hw/i386/pc_q35.c |   9 +
 include/hw/i386/pc.h |   2 ++
 tests/data/acpi/q35/DSDT | Bin 7841 -> 7879 bytes
 tests/data/acpi/q35/DSDT.bridge  | Bin 7858 -> 7896 bytes
 tests/data/acpi/q35/DSDT.cphp| Bin 8304 -> 8342 bytes
 tests/data/acpi/q35/DSDT.dimmpxm | Bin 9494 -> 9532 bytes
 tests/data/acpi/q35/DSDT.ipmibt  | Bin 7916 -> 7954 bytes
 tests/data/acpi/q35/DSDT.memhp   | Bin 9200 -> 9238 bytes
 tests/data/acpi/q35/DSDT.mmio64  | Bin 8971 -> 9009 bytes
 tests/data/acpi/q35/DSDT.numamem | Bin 7847 -> 7885 bytes
 12 files changed, 28 insertions(+), 10 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 8acf12df9a..4e0f9f425a 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1809,6 +1809,18 @@ static Aml *build_q35_osc_method(void)
 return method;
 }
 
+static void build_smb0(Aml *table, I2CBus *smbus, int devnr, int func)
+{
+Aml *scope = aml_scope("_SB.PCI0");
+Aml *dev = aml_device("SMB0");
+
+aml_append(dev, aml_name_decl("_HID", aml_eisaid("APP0005")));
+aml_append(dev, aml_name_decl("_ADR", aml_int(devnr << 16 | func)));
+build_acpi_ipmi_devices(dev, BUS(smbus), "\\_SB.PCI0.SMB0");
+aml_append(scope, dev);
+aml_append(table, scope);
+}
+
 static void
 build_dsdt(GArray *table_data, BIOSLinker *linker,
AcpiPmInfo *pm, AcpiMiscInfo *misc,
@@ -1862,6 +1874,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
 build_q35_isa_bridge(dsdt);
 build_isa_devices_aml(dsdt);
 build_q35_pci0_int(dsdt);
+if (pcms->smbus && !pcmc->do_not_add_smb_acpi) {
+build_smb0(dsdt, pcms->smbus, ICH9_SMB_DEV, ICH9_SMB_FUNC);
+}
 }
 
 if (pcmc->legacy_cpu_hotplug) {
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 2362675149..6824b72124 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -283,15 +283,14 @@ else {
 
 if (pcmc->pci_enabled && acpi_enabled) {
 DeviceState *piix4_pm;
-I2CBus *smbus;
 
 smi_irq = qemu_allocate_irq(pc_acpi_smi_interrupt, first_cpu, 0);
 /* TODO: Populate SPD eeprom data.  */
-smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
-  pcms->gsi[9], smi_irq,
-  pc_machine_is_smm_enabled(pcms),
-  _pm);
-smbus_eeprom_init(smbus, 8, NULL, 0);
+pcms->smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
+pcms->gsi[9], smi_irq,
+pc_machine_is_smm_enabled(pcms),
+_pm);
+smbus_eeprom_init(pcms->smbus, 8, NULL, 0);
 
 object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP,
  TYPE_HOTPLUG_HANDLER,
@@ -476,6 +475,7 @@ static void pc_i440fx_3_1_machine_options(MachineClass *m)
 
 pc_i440fx_4_0_machine_options(m);
 m->is_default = 0;
+pcmc->do_not_add_smb_acpi = true;
 m->smbus_no_migration_support = true;
 m->alias = NULL;
 pcmc->pvh_enabled = false;
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index d4e8a1cb9f..8fad20f314 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -316,10 +316,10 @@ static void pc_q35_init(MachineState *machine)
 
 if (pcms->smbus_enabled) {
 /* TODO: Populate SPD eeprom data.  */
-smbus_eeprom_init(ich9_smb_init(host_bus,
-PCI_DEVFN(ICH9_SMB_DEV, ICH9_SMB_FUNC),
-0xb100),
-  8, NULL, 0);
+pcms->smbus = ich9_smb_init(host_bus,
+PCI_DEVFN(ICH9_SMB_DEV, ICH9_SMB_FUNC),
+0xb100);
+smbus_eeprom_init(pcms->smbus, 8, NULL, 0);
 }
 
 pc_cmos_init(pcms, idebus[0], idebus[1], rtc_state);
@@ -421,6 +421,7 @@ static void pc_q35_3_1_machine_options(MachineClass *m)
 
 pc_q35_4_0_machine_options(m);
 m->default_kernel_irqchip_split = false;
+pcmc->do_not_add_smb_acpi = true;
 m->smbus_no_migration_support = true;
 m->alias = NULL;
 pcmc->pvh_enabled = false;
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 062feeb69e..6df4f4b6fb 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -38,6 +38,7 @@ struct PCMachineState {
 HotplugHandler *acpi_dev;
   

[PATCH 08/15] ipmi: Split out BT-specific code from ISA BT code

2019-09-19 Thread minyard
From: Corey Minyard 

Get ready for PCI and other BT interfaces.

No functional changes, just split the code into generic BT code
and ISA-specific BT code.

Signed-off-by: Corey Minyard 
Reviewed-by: Philippe Mathieu-Daudé 
---
 hw/ipmi/Makefile.objs |   2 +-
 hw/ipmi/ipmi_bt.c | 426 
 hw/ipmi/isa_ipmi_bt.c | 441 ++
 include/hw/ipmi/ipmi_bt.h |  72 +++
 4 files changed, 520 insertions(+), 421 deletions(-)
 create mode 100644 hw/ipmi/ipmi_bt.c
 create mode 100644 include/hw/ipmi/ipmi_bt.h

diff --git a/hw/ipmi/Makefile.objs b/hw/ipmi/Makefile.objs
index 6835d2f64a..4ffa45a66c 100644
--- a/hw/ipmi/Makefile.objs
+++ b/hw/ipmi/Makefile.objs
@@ -1,4 +1,4 @@
-common-obj-$(CONFIG_IPMI) += ipmi.o ipmi_kcs.o
+common-obj-$(CONFIG_IPMI) += ipmi.o ipmi_kcs.o ipmi_bt.o
 common-obj-$(CONFIG_IPMI_LOCAL) += ipmi_bmc_sim.o
 common-obj-$(CONFIG_IPMI_EXTERN) += ipmi_bmc_extern.o
 common-obj-$(CONFIG_ISA_IPMI_KCS) += isa_ipmi_kcs.o
diff --git a/hw/ipmi/ipmi_bt.c b/hw/ipmi/ipmi_bt.c
new file mode 100644
index 00..e6765ca4f8
--- /dev/null
+++ b/hw/ipmi/ipmi_bt.c
@@ -0,0 +1,426 @@
+/*
+ * QEMU IPMI BT emulation
+ *
+ * Copyright (c) 2015 Corey Minyard, MontaVista Software, LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "migration/vmstate.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "hw/ipmi/ipmi_bt.h"
+
+/* Control register */
+#define IPMI_BT_CLR_WR_BIT 0
+#define IPMI_BT_CLR_RD_BIT 1
+#define IPMI_BT_H2B_ATN_BIT2
+#define IPMI_BT_B2H_ATN_BIT3
+#define IPMI_BT_SMS_ATN_BIT4
+#define IPMI_BT_HBUSY_BIT  6
+#define IPMI_BT_BBUSY_BIT  7
+
+#define IPMI_BT_GET_CLR_WR(d)  (((d) >> IPMI_BT_CLR_WR_BIT) & 0x1)
+
+#define IPMI_BT_GET_CLR_RD(d)  (((d) >> IPMI_BT_CLR_RD_BIT) & 0x1)
+
+#define IPMI_BT_GET_H2B_ATN(d) (((d) >> IPMI_BT_H2B_ATN_BIT) & 0x1)
+
+#define IPMI_BT_B2H_ATN_MASK   (1 << IPMI_BT_B2H_ATN_BIT)
+#define IPMI_BT_GET_B2H_ATN(d) (((d) >> IPMI_BT_B2H_ATN_BIT) & 0x1)
+#define IPMI_BT_SET_B2H_ATN(d, v)  ((d) = (((d) & ~IPMI_BT_B2H_ATN_MASK) | \
+(!!(v) << IPMI_BT_B2H_ATN_BIT)))
+
+#define IPMI_BT_SMS_ATN_MASK   (1 << IPMI_BT_SMS_ATN_BIT)
+#define IPMI_BT_GET_SMS_ATN(d) (((d) >> IPMI_BT_SMS_ATN_BIT) & 0x1)
+#define IPMI_BT_SET_SMS_ATN(d, v)  ((d) = (((d) & ~IPMI_BT_SMS_ATN_MASK) | \
+(!!(v) << IPMI_BT_SMS_ATN_BIT)))
+
+#define IPMI_BT_HBUSY_MASK (1 << IPMI_BT_HBUSY_BIT)
+#define IPMI_BT_GET_HBUSY(d)   (((d) >> IPMI_BT_HBUSY_BIT) & 0x1)
+#define IPMI_BT_SET_HBUSY(d, v)((d) = (((d) & ~IPMI_BT_HBUSY_MASK) | \
+   (!!(v) << IPMI_BT_HBUSY_BIT)))
+
+#define IPMI_BT_BBUSY_MASK (1 << IPMI_BT_BBUSY_BIT)
+#define IPMI_BT_SET_BBUSY(d, v)((d) = (((d) & ~IPMI_BT_BBUSY_MASK) | \
+   (!!(v) << IPMI_BT_BBUSY_BIT)))
+
+
+/* Mask register */
+#define IPMI_BT_B2H_IRQ_EN_BIT 0
+#define IPMI_BT_B2H_IRQ_BIT1
+
+#define IPMI_BT_B2H_IRQ_EN_MASK  (1 << IPMI_BT_B2H_IRQ_EN_BIT)
+#define IPMI_BT_GET_B2H_IRQ_EN(d)(((d) >> IPMI_BT_B2H_IRQ_EN_BIT) & 0x1)
+#define IPMI_BT_SET_B2H_IRQ_EN(d, v) ((d) = (((d) & ~IPMI_BT_B2H_IRQ_EN_MASK) 
|\
+(!!(v) << IPMI_BT_B2H_IRQ_EN_BIT)))
+
+#define IPMI_BT_B2H_IRQ_MASK (1 << IPMI_BT_B2H_IRQ_BIT)
+#define IPMI_BT_GET_B2H_IRQ(d)   (((d) >> IPMI_BT_B2H_IRQ_BIT) & 0x1)
+#define IPMI_BT_SET_B2H_IRQ(d, v)((d) = (((d) & ~IPMI_BT_B2H_IRQ_MASK) | \
+(!!(v) << IPMI_BT_B2H_IRQ_BIT)))
+
+#define IPMI_CMD_GET_BT_INTF_CAP0x36
+
+static void ipmi_bt_raise_irq(IPMIBT *ib)
+{
+if (ib->use_irq && ib->irqs_enabled && ib->raise_irq) {
+ib->raise_irq(ib);
+}
+}
+

[PATCH 11/15] ipmi: Add PCI IPMI interfaces

2019-09-19 Thread minyard
From: Corey Minyard 

Pretty straightforward, just hook the current KCS and BT code into
the PCI system with the proper configuration.

Cc: Michael S. Tsirkin 
Cc: M: Marcel Apfelbaum 
Signed-off-by: Corey Minyard 
---
 default-configs/i386-softmmu.mak |   2 +
 hw/i386/Kconfig  |   2 +
 hw/ipmi/Kconfig  |  10 +++
 hw/ipmi/Makefile.objs|   2 +
 hw/ipmi/pci_ipmi_bt.c| 146 +++
 hw/ipmi/pci_ipmi_kcs.c   | 146 +++
 include/hw/pci/pci.h |   1 +
 7 files changed, 309 insertions(+)
 create mode 100644 hw/ipmi/pci_ipmi_bt.c
 create mode 100644 hw/ipmi/pci_ipmi_kcs.c

diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index ba3fb3ff50..2294c0be5a 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -10,6 +10,8 @@
 #CONFIG_ISA_DEBUG=n
 #CONFIG_ISA_IPMI_BT=n
 #CONFIG_ISA_IPMI_KCS=n
+#CONFIG_PCI_IPMI_KCS=n
+#CONFIG_PCI_IPMI_BT=n
 #CONFIG_PCI_DEVICES=n
 #CONFIG_PVPANIC=n
 #CONFIG_QXL=n
diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
index c7a9d6315c..d10f4e3e8b 100644
--- a/hw/i386/Kconfig
+++ b/hw/i386/Kconfig
@@ -8,6 +8,8 @@ config PC
 imply HYPERV
 imply ISA_IPMI_KCS
 imply ISA_IPMI_BT
+imply PCI_IPMI_KCS
+imply PCI_IPMI_BT
 imply ISA_DEBUG
 imply PARALLEL
 imply PCI_DEVICES
diff --git a/hw/ipmi/Kconfig b/hw/ipmi/Kconfig
index b944fae100..12db4e81ad 100644
--- a/hw/ipmi/Kconfig
+++ b/hw/ipmi/Kconfig
@@ -20,3 +20,13 @@ config ISA_IPMI_BT
 bool
 depends on ISA_BUS
 select IPMI
+
+config PCI_IPMI_KCS
+bool
+depends on PCI
+select IPMI
+
+config PCI_IPMI_BT
+bool
+depends on PCI
+select IPMI
diff --git a/hw/ipmi/Makefile.objs b/hw/ipmi/Makefile.objs
index 4ffa45a66c..2d7f080a86 100644
--- a/hw/ipmi/Makefile.objs
+++ b/hw/ipmi/Makefile.objs
@@ -2,4 +2,6 @@ common-obj-$(CONFIG_IPMI) += ipmi.o ipmi_kcs.o ipmi_bt.o
 common-obj-$(CONFIG_IPMI_LOCAL) += ipmi_bmc_sim.o
 common-obj-$(CONFIG_IPMI_EXTERN) += ipmi_bmc_extern.o
 common-obj-$(CONFIG_ISA_IPMI_KCS) += isa_ipmi_kcs.o
+common-obj-$(CONFIG_PCI_IPMI_KCS) += pci_ipmi_kcs.o
 common-obj-$(CONFIG_ISA_IPMI_BT) += isa_ipmi_bt.o
+common-obj-$(CONFIG_PCI_IPMI_BT) += pci_ipmi_bt.o
diff --git a/hw/ipmi/pci_ipmi_bt.c b/hw/ipmi/pci_ipmi_bt.c
new file mode 100644
index 00..6ed925a665
--- /dev/null
+++ b/hw/ipmi/pci_ipmi_bt.c
@@ -0,0 +1,146 @@
+/*
+ * QEMU PCI IPMI BT emulation
+ *
+ * Copyright (c) 2017 Corey Minyard, MontaVista Software, LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "migration/vmstate.h"
+#include "qapi/error.h"
+#include "hw/ipmi/ipmi_bt.h"
+#include "hw/pci/pci.h"
+
+#define TYPE_PCI_IPMI_BT "pci-ipmi-bt"
+#define PCI_IPMI_BT(obj) OBJECT_CHECK(PCIIPMIBTDevice, (obj), \
+   TYPE_PCI_IPMI_BT)
+
+typedef struct PCIIPMIBTDevice {
+PCIDevice dev;
+IPMIBT bt;
+bool irq_enabled;
+uint32_t uuid;
+} PCIIPMIBTDevice;
+
+static void pci_ipmi_raise_irq(IPMIBT *ik)
+{
+PCIIPMIBTDevice *pik = ik->opaque;
+
+pci_set_irq(>dev, true);
+}
+
+static void pci_ipmi_lower_irq(IPMIBT *ik)
+{
+PCIIPMIBTDevice *pik = ik->opaque;
+
+pci_set_irq(>dev, false);
+}
+
+static void pci_ipmi_bt_realize(PCIDevice *pd, Error **errp)
+{
+PCIIPMIBTDevice *pik = PCI_IPMI_BT(pd);
+IPMIInterface *ii = IPMI_INTERFACE(pd);
+IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii);
+
+if (!pik->bt.bmc) {
+error_setg(errp, "IPMI device requires a bmc attribute to be set");
+return;
+}
+
+pik->uuid = ipmi_next_uuid();
+
+pik->bt.bmc->intf = ii;
+pik->bt.opaque = pik;
+
+pci_config_set_prog_interface(pd->config, 0x02); /* BT */
+pci_config_set_interrupt_pin(pd->config, 0x01);
+pik->bt.use_irq = 1;
+pik->bt.raise_irq = pci_ipmi_raise_irq;
+

Re: [PATCH v2 08/16] tests/tcg: re-enable linux-test for ppc64abi32

2019-09-19 Thread Richard Henderson
On 9/19/19 10:10 AM, Alex Bennée wrote:
> diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
> index 6c4a471aeae..e8a1a1495fc 100755
> --- a/tests/tcg/configure.sh
> +++ b/tests/tcg/configure.sh
> @@ -54,6 +54,7 @@ fi
>  : ${cross_cc_cflags_ppc="-m32"}
>  : ${cross_cc_ppc64="powerpc-linux-gnu-gcc"}
>  : ${cross_cc_cflags_ppc64="-m64"}
> +: ${cross_cc_cflags_ppc64abi32="-mcpu=power8"}

I don't see why this is required.  Indeed, ppc64abi32 was much more common when
G4 was the hot cpu of the day.


r~



[PATCH v4 19/24] audio: replace shift in audio_pcm_info with bytes_per_frame

2019-09-19 Thread Kővágó, Zoltán
The bit shifting trick worked because the number of bytes per frame was
always a power-of-two (since QEMU only supports mono, stereo and 8, 16
and 32 bit samples).  But if we want to add support for surround sound,
this no longer holds true.

Signed-off-by: Kővágó, Zoltán 
---
 audio/alsaaudio.c   | 11 +++---
 audio/audio.c   | 74 -
 audio/audio_int.h   |  3 +-
 audio/coreaudio.c   |  4 +--
 audio/dsound_template.h | 10 +++---
 audio/dsoundaudio.c |  4 +--
 audio/noaudio.c |  2 +-
 audio/ossaudio.c| 14 
 audio/spiceaudio.c  |  3 +-
 audio/wavaudio.c|  6 ++--
 10 files changed, 66 insertions(+), 65 deletions(-)

diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c
index cfe42284a6..eddf013a53 100644
--- a/audio/alsaaudio.c
+++ b/audio/alsaaudio.c
@@ -602,7 +602,7 @@ static size_t alsa_write(HWVoiceOut *hw, void *buf, size_t 
len)
 {
 ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
 size_t pos = 0;
-size_t len_frames = len >> hw->info.shift;
+size_t len_frames = len / hw->info.bytes_per_frame;
 
 while (len_frames) {
 char *src = advance(buf, pos);
@@ -648,7 +648,7 @@ static size_t alsa_write(HWVoiceOut *hw, void *buf, size_t 
len)
 }
 }
 
-pos += written << hw->info.shift;
+pos += written * hw->info.bytes_per_frame;
 if (written < len_frames) {
 break;
 }
@@ -802,7 +802,8 @@ static size_t alsa_read(HWVoiceIn *hw, void *buf, size_t 
len)
 void *dst = advance(buf, pos);
 snd_pcm_sframes_t nread;
 
-nread = snd_pcm_readi(alsa->handle, dst, len >> hw->info.shift);
+nread = snd_pcm_readi(
+alsa->handle, dst, len / hw->info.bytes_per_frame);
 
 if (nread <= 0) {
 switch (nread) {
@@ -828,8 +829,8 @@ static size_t alsa_read(HWVoiceIn *hw, void *buf, size_t 
len)
 }
 }
 
-pos += nread << hw->info.shift;
-len -= nread << hw->info.shift;
+pos += nread * hw->info.bytes_per_frame;
+len -= nread * hw->info.bytes_per_frame;
 }
 
 return pos;
diff --git a/audio/audio.c b/audio/audio.c
index f1c145dfcd..c00f4deddd 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -299,12 +299,13 @@ static int audio_pcm_info_eq (struct audio_pcm_info 
*info, struct audsettings *a
 
 void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as)
 {
-int bits = 8, sign = 0, shift = 0;
+int bits = 8, sign = 0, mul;
 
 switch (as->fmt) {
 case AUDIO_FORMAT_S8:
 sign = 1;
 case AUDIO_FORMAT_U8:
+mul = 1;
 break;
 
 case AUDIO_FORMAT_S16:
@@ -312,7 +313,7 @@ void audio_pcm_init_info (struct audio_pcm_info *info, 
struct audsettings *as)
 /* fall through */
 case AUDIO_FORMAT_U16:
 bits = 16;
-shift = 1;
+mul = 2;
 break;
 
 case AUDIO_FORMAT_S32:
@@ -320,7 +321,7 @@ void audio_pcm_init_info (struct audio_pcm_info *info, 
struct audsettings *as)
 /* fall through */
 case AUDIO_FORMAT_U32:
 bits = 32;
-shift = 2;
+mul = 4;
 break;
 
 default:
@@ -331,9 +332,8 @@ void audio_pcm_init_info (struct audio_pcm_info *info, 
struct audsettings *as)
 info->bits = bits;
 info->sign = sign;
 info->nchannels = as->nchannels;
-info->shift = (as->nchannels == 2) + shift;
-info->align = (1 << info->shift) - 1;
-info->bytes_per_second = info->freq << info->shift;
+info->bytes_per_frame = as->nchannels * mul;
+info->bytes_per_second = info->freq * info->bytes_per_frame;
 info->swap_endianness = (as->endianness != AUDIO_HOST_ENDIANNESS);
 }
 
@@ -344,26 +344,25 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info 
*info, void *buf, int len)
 }
 
 if (info->sign) {
-memset (buf, 0x00, len << info->shift);
+memset(buf, 0x00, len * info->bytes_per_frame);
 }
 else {
 switch (info->bits) {
 case 8:
-memset (buf, 0x80, len << info->shift);
+memset(buf, 0x80, len * info->bytes_per_frame);
 break;
 
 case 16:
 {
 int i;
 uint16_t *p = buf;
-int shift = info->nchannels - 1;
 short s = INT16_MAX;
 
 if (info->swap_endianness) {
 s = bswap16 (s);
 }
 
-for (i = 0; i < len << shift; i++) {
+for (i = 0; i < len * info->nchannels; i++) {
 p[i] = s;
 }
 }
@@ -373,14 +372,13 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info 
*info, void *buf, int len)
 {
 int i;
 uint32_t *p = buf;
-int shift = info->nchannels - 1;
 int32_t s = INT32_MAX;
 
 if (info->swap_endianness) {
 s 

[PATCH 05/15] qdev: Add a no default uuid property

2019-09-19 Thread minyard
From: Corey Minyard 

This is for IPMI, which will behave differently if the UUID is
not set.

Signed-off-by: Corey Minyard 
Cc: Fam Zheng 
Cc: Michael S. Tsirkin 
Cc: Marc-André Lureau 
---
 include/hw/qdev-properties.h | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h
index 2e98dd60db..c6a8cb5516 100644
--- a/include/hw/qdev-properties.h
+++ b/include/hw/qdev-properties.h
@@ -238,6 +238,13 @@ extern const PropertyInfo qdev_prop_pcie_link_width;
 #define DEFINE_PROP_AUDIODEV(_n, _s, _f) \
 DEFINE_PROP(_n, _s, _f, qdev_prop_audiodev, QEMUSoundCard)
 
+#define DEFINE_PROP_UUID_NODEFAULT(_name, _state, _field) {\
+.name  = (_name),  \
+.info  = _prop_uuid,  \
+.offset= offsetof(_state, _field)  \
++ type_check(QemuUUID, typeof_field(_state, _field)),  \
+}
+
 #define DEFINE_PROP_END_OF_LIST()   \
 {}
 
-- 
2.17.1




[PATCH 13/15] acpi: Add i2c serial bus CRS handling

2019-09-19 Thread minyard
From: Corey Minyard 

This will be required for getting IPMI SSIF (SMBus interface) into
the ACPI tables.

Cc: Michael S. Tsirkin 
Cc: Igor Mammedov 
Signed-off-by: Corey Minyard 
---
 hw/acpi/aml-build.c | 40 +
 include/hw/acpi/aml-build.h | 18 +
 2 files changed, 58 insertions(+)

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 78aee1a2f9..2c3702b882 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1874,3 +1874,43 @@ build_hdr:
 build_header(linker, tbl, (void *)(tbl->data + fadt_start),
  "FACP", tbl->len - fadt_start, f->rev, oem_id, oem_table_id);
 }
+
+/* ACPI 5.0: 6.4.3.8.2 Serial Bus Connection Descriptors */
+static Aml *aml_serial_bus_device(uint8_t serial_bus_type, uint8_t flags,
+  uint16_t type_flags,
+  uint8_t revid, uint16_t data_length,
+  uint16_t resource_source_len)
+{
+Aml *var = aml_alloc();
+uint16_t length = data_length + resource_source_len + 9;
+
+build_append_byte(var->buf, 0x8e); /* Serial Bus Connection Descriptor */
+build_append_int_noprefix(var->buf, length, sizeof(length));
+build_append_byte(var->buf, 1);/* Revision ID */
+build_append_byte(var->buf, 0);/* Resource Source Index */
+build_append_byte(var->buf, serial_bus_type); /* Serial Bus Type */
+build_append_byte(var->buf, flags); /* General Flags */
+build_append_int_noprefix(var->buf, type_flags, /* Type Specific Flags */
+  sizeof(type_flags));
+build_append_byte(var->buf, revid); /* Type Specification Revision ID */
+build_append_int_noprefix(var->buf, data_length, sizeof(data_length));
+
+return var;
+}
+
+/* ACPI 5.0: 6.4.3.8.2.1 I2C Serial Bus Connection Resource Descriptor */
+Aml *aml_i2c_serial_bus_device(uint16_t address, const char *resource_source)
+{
+uint16_t resource_source_len = strlen(resource_source) + 1;
+Aml *var = aml_serial_bus_device(AML_SERIAL_BUS_TYPE_I2C, 0, 0, 1,
+ 6, resource_source_len);
+
+/* Connection Speed.  Just set to 100K for now, it doesn't really matter. 
*/
+build_append_int_noprefix(var->buf, 10, 4);
+build_append_int_noprefix(var->buf, address, sizeof(address));
+
+/* This is a string, not a name, so just copy it directly in. */
+g_array_append_vals(var->buf, resource_source, resource_source_len);
+
+return var;
+}
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index 991cf05134..de4a406568 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -223,6 +223,23 @@ struct AcpiBuildTables {
 BIOSLinker *linker;
 } AcpiBuildTables;
 
+/*
+ * ACPI 5.0: 6.4.3.8.2 Serial Bus Connection Descriptors
+ * Serial Bus Type
+ */
+#define AML_SERIAL_BUS_TYPE_I2C  1
+#define AML_SERIAL_BUS_TYPE_SPI  2
+#define AML_SERIAL_BUS_TYPE_UART 3
+
+/*
+ * ACPI 5.0: 6.4.3.8.2 Serial Bus Connection Descriptors
+ * General Flags
+ */
+/* Slave Mode */
+#define AML_SERIAL_BUS_FLAG_MASTER_DEVICE   (1 << 0)
+/* Consumer/Producer */
+#define AML_SERIAL_BUS_FLAG_CONSUME_ONLY(1 << 1)
+
 /**
  * init_aml_allocator:
  *
@@ -347,6 +364,7 @@ Aml *aml_qword_memory(AmlDecode dec, AmlMinFixed min_fixed,
 Aml *aml_dma(AmlDmaType typ, AmlDmaBusMaster bm, AmlTransferSize sz,
  uint8_t channel);
 Aml *aml_sleep(uint64_t msec);
+Aml *aml_i2c_serial_bus_device(uint16_t address, const char *resource_source);
 
 /* Block AML object primitives */
 Aml *aml_scope(const char *name_format, ...) GCC_FMT_ATTR(1, 2);
-- 
2.17.1




[PATCH v4 14/24] audio: split ctl_* functions into enable_* and volume_*

2019-09-19 Thread Kővágó, Zoltán
This way we no longer need vararg functions, improving compile time
error detection.  Also now it's possible to check actually what commands
are supported, without needing to manually update ctl_caps.

Signed-off-by: Kővágó, Zoltán 
---
 audio/alsaaudio.c  |  62 --
 audio/audio.c  |  45 -
 audio/audio_int.h  |  15 ++---
 audio/audio_template.h |   1 -
 audio/coreaudio.c  |  13 ++--
 audio/dsoundaudio.c|  50 ++-
 audio/noaudio.c|  14 ++---
 audio/ossaudio.c   |  79 +--
 audio/paaudio.c| 139 +
 audio/sdlaudio.c   |  17 +
 audio/spiceaudio.c | 102 +-
 audio/wavaudio.c   |   7 +--
 12 files changed, 223 insertions(+), 321 deletions(-)

diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c
index 19124d09d8..cfe42284a6 100644
--- a/audio/alsaaudio.c
+++ b/audio/alsaaudio.c
@@ -731,34 +731,28 @@ static int alsa_voice_ctl (snd_pcm_t *handle, const char 
*typ, int ctl)
 return 0;
 }
 
-static int alsa_ctl_out (HWVoiceOut *hw, int cmd, ...)
+static void alsa_enable_out(HWVoiceOut *hw, bool enable)
 {
 ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
 AudiodevAlsaPerDirectionOptions *apdo = alsa->dev->u.alsa.out;
 
-switch (cmd) {
-case VOICE_ENABLE:
-{
-bool poll_mode = apdo->try_poll;
+if (enable) {
+bool poll_mode = apdo->try_poll;
 
-ldebug ("enabling voice\n");
-if (poll_mode && alsa_poll_out (hw)) {
-poll_mode = 0;
-}
-hw->poll_mode = poll_mode;
-return alsa_voice_ctl (alsa->handle, "playback", 
VOICE_CTL_PREPARE);
+ldebug("enabling voice\n");
+if (poll_mode && alsa_poll_out(hw)) {
+poll_mode = 0;
 }
-
-case VOICE_DISABLE:
-ldebug ("disabling voice\n");
+hw->poll_mode = poll_mode;
+alsa_voice_ctl(alsa->handle, "playback", VOICE_CTL_PREPARE);
+} else {
+ldebug("disabling voice\n");
 if (hw->poll_mode) {
 hw->poll_mode = 0;
-alsa_fini_poll (>pollhlp);
+alsa_fini_poll(>pollhlp);
 }
-return alsa_voice_ctl (alsa->handle, "playback", VOICE_CTL_PAUSE);
+alsa_voice_ctl(alsa->handle, "playback", VOICE_CTL_PAUSE);
 }
-
-return -1;
 }
 
 static int alsa_init_in(HWVoiceIn *hw, struct audsettings *as, void 
*drv_opaque)
@@ -841,35 +835,29 @@ static size_t alsa_read(HWVoiceIn *hw, void *buf, size_t 
len)
 return pos;
 }
 
-static int alsa_ctl_in (HWVoiceIn *hw, int cmd, ...)
+static void alsa_enable_in(HWVoiceIn *hw, bool enable)
 {
 ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
 AudiodevAlsaPerDirectionOptions *apdo = alsa->dev->u.alsa.in;
 
-switch (cmd) {
-case VOICE_ENABLE:
-{
-bool poll_mode = apdo->try_poll;
+if (enable) {
+bool poll_mode = apdo->try_poll;
 
-ldebug ("enabling voice\n");
-if (poll_mode && alsa_poll_in (hw)) {
-poll_mode = 0;
-}
-hw->poll_mode = poll_mode;
-
-return alsa_voice_ctl (alsa->handle, "capture", VOICE_CTL_START);
+ldebug("enabling voice\n");
+if (poll_mode && alsa_poll_in(hw)) {
+poll_mode = 0;
 }
+hw->poll_mode = poll_mode;
 
-case VOICE_DISABLE:
+alsa_voice_ctl(alsa->handle, "capture", VOICE_CTL_START);
+} else {
 ldebug ("disabling voice\n");
 if (hw->poll_mode) {
 hw->poll_mode = 0;
-alsa_fini_poll (>pollhlp);
+alsa_fini_poll(>pollhlp);
 }
-return alsa_voice_ctl (alsa->handle, "capture", VOICE_CTL_PAUSE);
+alsa_voice_ctl(alsa->handle, "capture", VOICE_CTL_PAUSE);
 }
-
-return -1;
 }
 
 static void alsa_init_per_direction(AudiodevAlsaPerDirectionOptions *apdo)
@@ -924,12 +912,12 @@ static struct audio_pcm_ops alsa_pcm_ops = {
 .init_out = alsa_init_out,
 .fini_out = alsa_fini_out,
 .write= alsa_write,
-.ctl_out  = alsa_ctl_out,
+.enable_out = alsa_enable_out,
 
 .init_in  = alsa_init_in,
 .fini_in  = alsa_fini_in,
 .read = alsa_read,
-.ctl_in   = alsa_ctl_in,
+.enable_in = alsa_enable_in,
 };
 
 static struct audio_driver alsa_audio_driver = {
diff --git a/audio/audio.c b/audio/audio.c
index fab1e35718..7128ee98dc 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -636,7 +636,7 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, 
size_t size)
 total += isamp;
 }
 
-if (!(hw->ctl_caps & VOICE_VOLUME_CAP)) {
+if (!hw->pcm_ops->volume_in) {
 mixeng_volume (sw->buf, ret, >vol);
 }
 
@@ -723,7 +723,7 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, 
size_t size)
 if (swlim) {
 sw->conv (sw->buf, buf, swlim);
 
-if (!(sw->hw->ctl_caps & VOICE_VOLUME_CAP)) {
+   

[PATCH 03/15] ipmi: Generate an interrupt on watchdog pretimeout expiry

2019-09-19 Thread minyard
From: Corey Minyard 

Add the watchdog pretimeout to the bits that cause an interrupt on attn.
Otherwise the user won't know.

Signed-off-by: Corey Minyard 
---
 hw/ipmi/ipmi_bmc_sim.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index afb99e33d7..6e6cd1b47d 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -477,7 +477,9 @@ static int attn_set(IPMIBmcSim *ibs)
 
 static int attn_irq_enabled(IPMIBmcSim *ibs)
 {
-return (IPMI_BMC_MSG_INTS_ON(ibs) && 
IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs))
+return (IPMI_BMC_MSG_INTS_ON(ibs) &&
+(IPMI_BMC_MSG_FLAG_RCV_MSG_QUEUE_SET(ibs) ||
+ IPMI_BMC_MSG_FLAG_WATCHDOG_TIMEOUT_MASK_SET(ibs)))
 || (IPMI_BMC_EVBUF_FULL_INT_ENABLED(ibs) &&
 IPMI_BMC_MSG_FLAG_EVT_BUF_FULL_SET(ibs));
 }
-- 
2.17.1




[PATCH 14/15] ipmi: Fix SSIF ACPI handling to use the right CRS

2019-09-19 Thread minyard
From: Corey Minyard 

Pass in the CRS so that it can be set to the SMBus for IPMI later.

Cc: Michael S. Tsirkin 
Cc: Igor Mammedov 
Signed-off-by: Corey Minyard 
---
 hw/acpi/ipmi-stub.c|  2 +-
 hw/acpi/ipmi.c | 13 +++--
 hw/i386/acpi-build.c   |  2 +-
 include/hw/acpi/ipmi.h |  2 +-
 4 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/hw/acpi/ipmi-stub.c b/hw/acpi/ipmi-stub.c
index f525f71c2d..8634fb325c 100644
--- a/hw/acpi/ipmi-stub.c
+++ b/hw/acpi/ipmi-stub.c
@@ -10,6 +10,6 @@
 #include "qemu/osdep.h"
 #include "hw/acpi/ipmi.h"
 
-void build_acpi_ipmi_devices(Aml *table, BusState *bus)
+void build_acpi_ipmi_devices(Aml *table, BusState *bus, const char *resource)
 {
 }
diff --git a/hw/acpi/ipmi.c b/hw/acpi/ipmi.c
index 651e2e94ea..96e48eba15 100644
--- a/hw/acpi/ipmi.c
+++ b/hw/acpi/ipmi.c
@@ -13,7 +13,7 @@
 #include "hw/acpi/acpi.h"
 #include "hw/acpi/ipmi.h"
 
-static Aml *aml_ipmi_crs(IPMIFwInfo *info)
+static Aml *aml_ipmi_crs(IPMIFwInfo *info, const char *resource)
 {
 Aml *crs = aml_resource_template();
 
@@ -48,7 +48,8 @@ static Aml *aml_ipmi_crs(IPMIFwInfo *info)
 info->register_spacing, info->register_length));
 break;
 case IPMI_MEMSPACE_SMBUS:
-aml_append(crs, aml_return(aml_int(info->base_address)));
+aml_append(crs, aml_i2c_serial_bus_device(info->base_address,
+  resource));
 break;
 default:
 abort();
@@ -61,7 +62,7 @@ static Aml *aml_ipmi_crs(IPMIFwInfo *info)
 return crs;
 }
 
-static Aml *aml_ipmi_device(IPMIFwInfo *info)
+static Aml *aml_ipmi_device(IPMIFwInfo *info, const char *resource)
 {
 Aml *dev;
 uint16_t version = ((info->ipmi_spec_major_revision << 8)
@@ -74,14 +75,14 @@ static Aml *aml_ipmi_device(IPMIFwInfo *info)
 aml_append(dev, aml_name_decl("_STR", aml_string("ipmi_%s",
  info->interface_name)));
 aml_append(dev, aml_name_decl("_UID", aml_int(info->uuid)));
-aml_append(dev, aml_name_decl("_CRS", aml_ipmi_crs(info)));
+aml_append(dev, aml_name_decl("_CRS", aml_ipmi_crs(info, resource)));
 aml_append(dev, aml_name_decl("_IFT", aml_int(info->interface_type)));
 aml_append(dev, aml_name_decl("_SRV", aml_int(version)));
 
 return dev;
 }
 
-void build_acpi_ipmi_devices(Aml *scope, BusState *bus)
+void build_acpi_ipmi_devices(Aml *scope, BusState *bus, const char *resource)
 {
 
 BusChild *kid;
@@ -101,6 +102,6 @@ void build_acpi_ipmi_devices(Aml *scope, BusState *bus)
 iic = IPMI_INTERFACE_GET_CLASS(obj);
 memset(, 0, sizeof(info));
 iic->get_fwinfo(ii, );
-aml_append(scope, aml_ipmi_device());
+aml_append(scope, aml_ipmi_device(, resource));
 }
 }
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index e54e571a75..8acf12df9a 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1290,7 +1290,7 @@ static void build_isa_devices_aml(Aml *table)
 } else if (!obj) {
 error_report("No ISA bus, unable to define IPMI ACPI data");
 } else {
-build_acpi_ipmi_devices(scope, BUS(obj));
+build_acpi_ipmi_devices(scope, BUS(obj), "\\_SB.PCI0.ISA");
 }
 
 aml_append(table, scope);
diff --git a/include/hw/acpi/ipmi.h b/include/hw/acpi/ipmi.h
index c38483565c..c14ad682ac 100644
--- a/include/hw/acpi/ipmi.h
+++ b/include/hw/acpi/ipmi.h
@@ -16,6 +16,6 @@
  * bus matches the given bus.  The resource is the ACPI resource that
  * contains the IPMI device, this is required for the I2C CRS.
  */
-void build_acpi_ipmi_devices(Aml *table, BusState *bus);
+void build_acpi_ipmi_devices(Aml *table, BusState *bus, const char *resource);
 
 #endif /* HW_ACPI_IPMI_H */
-- 
2.17.1




[PATCH 07/15] ipmi: Split out KCS-specific code from ISA KCS code

2019-09-19 Thread minyard
From: Corey Minyard 

Get ready for PCI and other KCS interfaces.

No functional changes, just split the code into the generic KCS code
and the ISA-specific code.

Signed-off-by: Corey Minyard 
Reviewed-by: Philippe Mathieu-Daudé 
---
 hw/ipmi/Makefile.objs  |   2 +-
 hw/ipmi/ipmi_kcs.c | 408 
 hw/ipmi/isa_ipmi_kcs.c | 417 ++---
 include/hw/ipmi/ipmi_kcs.h |  75 +++
 4 files changed, 505 insertions(+), 397 deletions(-)
 create mode 100644 hw/ipmi/ipmi_kcs.c
 create mode 100644 include/hw/ipmi/ipmi_kcs.h

diff --git a/hw/ipmi/Makefile.objs b/hw/ipmi/Makefile.objs
index 1b422bbee0..6835d2f64a 100644
--- a/hw/ipmi/Makefile.objs
+++ b/hw/ipmi/Makefile.objs
@@ -1,4 +1,4 @@
-common-obj-$(CONFIG_IPMI) += ipmi.o
+common-obj-$(CONFIG_IPMI) += ipmi.o ipmi_kcs.o
 common-obj-$(CONFIG_IPMI_LOCAL) += ipmi_bmc_sim.o
 common-obj-$(CONFIG_IPMI_EXTERN) += ipmi_bmc_extern.o
 common-obj-$(CONFIG_ISA_IPMI_KCS) += isa_ipmi_kcs.o
diff --git a/hw/ipmi/ipmi_kcs.c b/hw/ipmi/ipmi_kcs.c
new file mode 100644
index 00..dab1af8bc8
--- /dev/null
+++ b/hw/ipmi/ipmi_kcs.c
@@ -0,0 +1,408 @@
+/*
+ * QEMU IPMI KCS emulation
+ *
+ * Copyright (c) 2015,2017 Corey Minyard, MontaVista Software, LLC
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "qemu/osdep.h"
+#include "migration/vmstate.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "hw/ipmi/ipmi_kcs.h"
+
+#define IPMI_KCS_OBF_BIT0
+#define IPMI_KCS_IBF_BIT1
+#define IPMI_KCS_SMS_ATN_BIT2
+#define IPMI_KCS_CD_BIT 3
+
+#define IPMI_KCS_OBF_MASK  (1 << IPMI_KCS_OBF_BIT)
+#define IPMI_KCS_GET_OBF(d)(((d) >> IPMI_KCS_OBF_BIT) & 0x1)
+#define IPMI_KCS_SET_OBF(d, v) (d) = (((d) & ~IPMI_KCS_OBF_MASK) | \
+   (((v) & 1) << IPMI_KCS_OBF_BIT))
+#define IPMI_KCS_IBF_MASK  (1 << IPMI_KCS_IBF_BIT)
+#define IPMI_KCS_GET_IBF(d)(((d) >> IPMI_KCS_IBF_BIT) & 0x1)
+#define IPMI_KCS_SET_IBF(d, v) (d) = (((d) & ~IPMI_KCS_IBF_MASK) | \
+   (((v) & 1) << IPMI_KCS_IBF_BIT))
+#define IPMI_KCS_SMS_ATN_MASK  (1 << IPMI_KCS_SMS_ATN_BIT)
+#define IPMI_KCS_GET_SMS_ATN(d)(((d) >> IPMI_KCS_SMS_ATN_BIT) & 0x1)
+#define IPMI_KCS_SET_SMS_ATN(d, v) (d) = (((d) & ~IPMI_KCS_SMS_ATN_MASK) | \
+   (((v) & 1) << IPMI_KCS_SMS_ATN_BIT))
+#define IPMI_KCS_CD_MASK   (1 << IPMI_KCS_CD_BIT)
+#define IPMI_KCS_GET_CD(d) (((d) >> IPMI_KCS_CD_BIT) & 0x1)
+#define IPMI_KCS_SET_CD(d, v)  (d) = (((d) & ~IPMI_KCS_CD_MASK) | \
+   (((v) & 1) << IPMI_KCS_CD_BIT))
+
+#define IPMI_KCS_IDLE_STATE0
+#define IPMI_KCS_READ_STATE1
+#define IPMI_KCS_WRITE_STATE   2
+#define IPMI_KCS_ERROR_STATE   3
+
+#define IPMI_KCS_GET_STATE(d)(((d) >> 6) & 0x3)
+#define IPMI_KCS_SET_STATE(d, v) ((d) = ((d) & ~0xc0) | (((v) & 0x3) << 6))
+
+#define IPMI_KCS_ABORT_STATUS_CMD   0x60
+#define IPMI_KCS_WRITE_START_CMD0x61
+#define IPMI_KCS_WRITE_END_CMD  0x62
+#define IPMI_KCS_READ_CMD   0x68
+
+#define IPMI_KCS_STATUS_NO_ERR  0x00
+#define IPMI_KCS_STATUS_ABORTED_ERR 0x01
+#define IPMI_KCS_STATUS_BAD_CC_ERR  0x02
+#define IPMI_KCS_STATUS_LENGTH_ERR  0x06
+
+static void ipmi_kcs_raise_irq(IPMIKCS *ik)
+{
+if (ik->use_irq && ik->irqs_enabled && ik->raise_irq) {
+ik->raise_irq(ik);
+}
+}
+
+static void ipmi_kcs_lower_irq(IPMIKCS *ik)
+{
+if (ik->lower_irq) {
+ik->lower_irq(ik);
+}
+}
+
+#define SET_OBF() \
+do {  \
+IPMI_KCS_SET_OBF(ik->status_reg, 1);  \
+if (!ik->obf_irq_set) {   \
+ik->obf_irq_set = 1;  

[PATCH v4 21/24] paaudio: channel-map option

2019-09-19 Thread Kővágó, Zoltán
Add an option to change the channel map used by pulseaudio.  If not
specified, falls back to an OSS compatible channel map.

Signed-off-by: Kővágó, Zoltán 
---
 audio/paaudio.c | 18 ++
 qapi/audio.json |  7 +--
 qemu-options.hx |  9 +
 3 files changed, 28 insertions(+), 6 deletions(-)

diff --git a/audio/paaudio.c b/audio/paaudio.c
index d195b1caa8..20402b0718 100644
--- a/audio/paaudio.c
+++ b/audio/paaudio.c
@@ -338,17 +338,27 @@ static pa_stream *qpa_simple_new (
 pa_stream_direction_t dir,
 const char *dev,
 const pa_sample_spec *ss,
-const pa_channel_map *map,
+const char *map,
 const pa_buffer_attr *attr,
 int *rerror)
 {
 int r;
 pa_stream *stream;
 pa_stream_flags_t flags;
+pa_channel_map pa_map;
 
 pa_threaded_mainloop_lock(c->mainloop);
 
-stream = pa_stream_new(c->context, name, ss, map);
+if (map && !pa_channel_map_parse(_map, map)) {
+dolog("Invalid channel map specified: '%s'\n", map);
+map = NULL;
+}
+if (!map) {
+pa_channel_map_init_extend(_map, ss->channels,
+   PA_CHANNEL_MAP_OSS);
+}
+
+stream = pa_stream_new(c->context, name, ss, _map);
 if (!stream) {
 goto fail;
 }
@@ -421,7 +431,7 @@ static int qpa_init_out(HWVoiceOut *hw, struct audsettings 
*as,
 PA_STREAM_PLAYBACK,
 ppdo->has_name ? ppdo->name : NULL,
 ,
-NULL,   /* channel map */
+ppdo->has_channel_map ? ppdo->channel_map : NULL,
 ,/* buffering attributes */
 
 );
@@ -470,7 +480,7 @@ static int qpa_init_in(HWVoiceIn *hw, struct audsettings 
*as, void *drv_opaque)
 PA_STREAM_RECORD,
 ppdo->has_name ? ppdo->name : NULL,
 ,
-NULL,   /* channel map */
+ppdo->has_channel_map ? ppdo->channel_map : NULL,
 ,/* buffering attributes */
 
 );
diff --git a/qapi/audio.json b/qapi/audio.json
index 0535eff794..07003808cb 100644
--- a/qapi/audio.json
+++ b/qapi/audio.json
@@ -214,13 +214,16 @@
 # @latency: latency you want PulseAudio to achieve in microseconds
 #   (default 15000)
 #
+# @channel-map: channel map to use (default: OSS compatible map, since: 4.2)
+#
 # Since: 4.0
 ##
 { 'struct': 'AudiodevPaPerDirectionOptions',
   'base': 'AudiodevPerDirectionOptions',
   'data': {
-'*name': 'str',
-'*latency': 'uint32' } }
+'*name':'str',
+'*latency': 'uint32',
+'*channel-map': 'str' } }
 
 ##
 # @AudiodevPaOptions:
diff --git a/qemu-options.hx b/qemu-options.hx
index 395427422a..f3bc342f98 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -471,6 +471,7 @@ DEF("audiodev", HAS_ARG, QEMU_OPTION_audiodev,
 "-audiodev pa,id=id[,prop[=value][,...]]\n"
 "server= PulseAudio server address\n"
 "in|out.name= source/sink device name\n"
+"in|out.channel-map= channel map to use\n"
 #endif
 #ifdef CONFIG_AUDIO_SDL
 "-audiodev sdl,id=id[,prop[=value][,...]]\n"
@@ -636,6 +637,14 @@ Sets the PulseAudio @var{server} to connect to.
 @item in|out.name=@var{sink}
 Use the specified source/sink for recording/playback.
 
+@item in|out.channel-map=@var{map}
+Use the specified channel map.  The default is an OSS compatible
+channel map.  Do not forget to escape commas inside the map:
+
+@example
+-audiodev pa,id=example,sink.channel-map=front-left,,front-right
+@end example
+
 @end table
 
 @item -audiodev sdl,id=@var{id}[,@var{prop}[=@var{value}][,...]]
-- 
2.23.0




[PATCH 09/15] ipmi: Allow a size value to be passed for I/O space

2019-09-19 Thread minyard
From: Corey Minyard 

PCI device I/O must be >= 8 bytes in length or they don't work.
Allow the size to be passed in, the default size of 2 or 3
won't work.

Signed-off-by: Corey Minyard 
---
 hw/ipmi/ipmi_bt.c  | 19 +++
 hw/ipmi/ipmi_kcs.c | 23 +++
 hw/ipmi/isa_ipmi_bt.c  |  2 +-
 hw/ipmi/isa_ipmi_kcs.c |  2 +-
 include/hw/ipmi/ipmi.h |  7 ++-
 include/hw/ipmi/ipmi_bt.h  |  1 +
 include/hw/ipmi/ipmi_kcs.h |  1 +
 7 files changed, 44 insertions(+), 11 deletions(-)

diff --git a/hw/ipmi/ipmi_bt.c b/hw/ipmi/ipmi_bt.c
index e6765ca4f8..22f94fb98d 100644
--- a/hw/ipmi/ipmi_bt.c
+++ b/hw/ipmi/ipmi_bt.c
@@ -189,7 +189,7 @@ static uint64_t ipmi_bt_ioport_read(void *opaque, hwaddr 
addr, unsigned size)
 IPMIBT *ib = iic->get_backend_data(ii);
 uint32_t ret = 0xff;
 
-switch (addr & 3) {
+switch (addr & ib->size_mask) {
 case 0:
 ret = ib->control_reg;
 break;
@@ -208,6 +208,9 @@ static uint64_t ipmi_bt_ioport_read(void *opaque, hwaddr 
addr, unsigned size)
 case 2:
 ret = ib->mask_reg;
 break;
+default:
+ret = 0xff;
+break;
 }
 return ret;
 }
@@ -230,7 +233,7 @@ static void ipmi_bt_ioport_write(void *opaque, hwaddr addr, 
uint64_t val,
 IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii);
 IPMIBT *ib = iic->get_backend_data(ii);
 
-switch (addr & 3) {
+switch (addr & ib->size_mask) {
 case 0:
 if (IPMI_BT_GET_CLR_WR(val)) {
 ib->inlen = 0;
@@ -285,6 +288,9 @@ static void ipmi_bt_ioport_write(void *opaque, hwaddr addr, 
uint64_t val,
 ipmi_bt_lower_irq(ib);
 }
 break;
+default:
+/* Ignore. */
+break;
 }
 }
 
@@ -346,14 +352,19 @@ static void ipmi_bt_set_irq_enable(IPMIInterface *ii, int 
val)
 ib->irqs_enabled = val;
 }
 
-static void ipmi_bt_init(IPMIInterface *ii, Error **errp)
+static void ipmi_bt_init(IPMIInterface *ii, unsigned int min_size, Error 
**errp)
 {
 IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii);
 IPMIBT *ib = iic->get_backend_data(ii);
 
+if (min_size == 0) {
+min_size = 4;
+}
+ib->size_mask = min_size - 1;
 ib->io_length = 3;
 
-memory_region_init_io(>io, NULL, _bt_io_ops, ii, "ipmi-bt", 3);
+memory_region_init_io(>io, NULL, _bt_io_ops, ii, "ipmi-bt",
+  min_size);
 }
 
 int ipmi_bt_vmstate_post_load(void *opaque, int version)
diff --git a/hw/ipmi/ipmi_kcs.c b/hw/ipmi/ipmi_kcs.c
index dab1af8bc8..a77612946a 100644
--- a/hw/ipmi/ipmi_kcs.c
+++ b/hw/ipmi/ipmi_kcs.c
@@ -232,7 +232,7 @@ static uint64_t ipmi_kcs_ioport_read(void *opaque, hwaddr 
addr, unsigned size)
 IPMIKCS *ik = iic->get_backend_data(ii);
 uint32_t ret;
 
-switch (addr & 1) {
+switch (addr & ik->size_mask) {
 case 0:
 ret = ik->data_out_reg;
 IPMI_KCS_SET_OBF(ik->status_reg, 0);
@@ -243,6 +243,7 @@ static uint64_t ipmi_kcs_ioport_read(void *opaque, hwaddr 
addr, unsigned size)
 }
 }
 break;
+
 case 1:
 ret = ik->status_reg;
 if (ik->atn_irq_set) {
@@ -252,6 +253,9 @@ static uint64_t ipmi_kcs_ioport_read(void *opaque, hwaddr 
addr, unsigned size)
 }
 }
 break;
+
+default:
+ret = 0xff;
 }
 return ret;
 }
@@ -267,7 +271,7 @@ static void ipmi_kcs_ioport_write(void *opaque, hwaddr 
addr, uint64_t val,
 return;
 }
 
-switch (addr & 1) {
+switch (addr & ik->size_mask) {
 case 0:
 ik->data_in_reg = val;
 break;
@@ -275,6 +279,10 @@ static void ipmi_kcs_ioport_write(void *opaque, hwaddr 
addr, uint64_t val,
 case 1:
 ik->cmd_reg = val;
 break;
+
+default:
+/* Ignore. */
+break;
 }
 IPMI_KCS_SET_IBF(ik->status_reg, 1);
 ipmi_kcs_signal(ik, ii);
@@ -321,13 +329,20 @@ static void ipmi_kcs_set_irq_enable(IPMIInterface *ii, 
int val)
 ik->irqs_enabled = val;
 }
 
-static void ipmi_kcs_init(IPMIInterface *ii, Error **errp)
+/* min_size must be a power of 2. */
+static void ipmi_kcs_init(IPMIInterface *ii, unsigned int min_size,
+  Error **errp)
 {
 IPMIInterfaceClass *iic = IPMI_INTERFACE_GET_CLASS(ii);
 IPMIKCS *ik = iic->get_backend_data(ii);
 
+if (min_size == 0) {
+min_size = 2;
+}
+ik->size_mask = min_size - 1;
 ik->io_length = 2;
-memory_region_init_io(>io, NULL, _kcs_io_ops, ii, "ipmi-kcs", 2);
+memory_region_init_io(>io, NULL, _kcs_io_ops, ii, "ipmi-kcs",
+  min_size);
 }
 
 int ipmi_kcs_vmstate_post_load(void *opaque, int version)
diff --git a/hw/ipmi/isa_ipmi_bt.c b/hw/ipmi/isa_ipmi_bt.c
index c102778712..9a87ffd3f0 100644
--- a/hw/ipmi/isa_ipmi_bt.c
+++ b/hw/ipmi/isa_ipmi_bt.c
@@ -85,7 +85,7 @@ static void isa_ipmi_bt_realize(DeviceState *dev, Error 
**errp)
 iib->bt.bmc->intf = ii;
 iib->bt.opaque = 

[PATCH 10/15] smbios:ipmi: Ignore IPMI devices with no fwinfo function

2019-09-19 Thread minyard
From: Corey Minyard 

Not all devices have fwinfo (like the coming PCI one), so ignore
them if the their fwinfo function is NULL.

Cc: Michael S. Tsirkin 
Cc: Igor Mammedov 
Signed-off-by: Corey Minyard 
---
 hw/smbios/smbios_type_38.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/hw/smbios/smbios_type_38.c b/hw/smbios/smbios_type_38.c
index 0c08f282de..168b886647 100644
--- a/hw/smbios/smbios_type_38.c
+++ b/hw/smbios/smbios_type_38.c
@@ -94,6 +94,9 @@ static void smbios_add_ipmi_devices(BusState *bus)
 ii = IPMI_INTERFACE(obj);
 iic = IPMI_INTERFACE_GET_CLASS(obj);
 memset(, 0, sizeof(info));
+if (!iic->get_fwinfo) {
+continue;
+}
 iic->get_fwinfo(ii, );
 smbios_build_one_type_38();
 continue;
-- 
2.17.1




[PATCH 00/15] ipmi: Bug fixes, add new interfaces

2019-09-19 Thread minyard
I haven't gotten a lot of commentary on this, but I assume that means
that everything is ok.  It's been posted a few times and the last time
I received no issues, just a couple of reviews.  I would like more
review.  But I'm not quite sure what to do about that, I've been
hanging on to these changes far too long.

The following changes since commit a77d20bafcd4cb7684168a9b4c6dc2a321aaeb50:

  Merge remote-tracking branch 'remotes/kraxel/tags/ui-20190919-pull-request' 
into staging (2019-09-19 17:16:07 +0100)

are available in the Git repository at:

  https://github.com/cminyard/qemu.git tags/ipmi-for-release-2019-09-19

for you to fetch changes up to d9b74295c6528fd68cebdea116b283e46543b2a2:

  pc: Add an SMB0 ACPI device to q35 (2019-09-19 14:41:58 -0500)


ipmi: Some bug fixes and new interfaces

Some bug fixes for the watchdog and hopeful the BT tests.

Change the IPMI UUID handling to give the user the ability to set it or
not have it.

Add a PCI interface.

Add an SMBus interfaces.

-corey


Corey Minyard (15):
  ipmi: Fix watchdog NMI handling
  ipmi: Fix the get watchdog command
  ipmi: Generate an interrupt on watchdog pretimeout expiry
  tests:ipmi: Fix IPMI BT tests
  qdev: Add a no default uuid property
  ipmi: Add a UUID device property
  ipmi: Split out KCS-specific code from ISA KCS code
  ipmi: Split out BT-specific code from ISA BT code
  ipmi: Allow a size value to be passed for I/O space
  smbios:ipmi: Ignore IPMI devices with no fwinfo function
  ipmi: Add PCI IPMI interfaces
  ipmi: Add an SMBus IPMI interface
  acpi: Add i2c serial bus CRS handling
  ipmi: Fix SSIF ACPI handling to use the right CRS
  pc: Add an SMB0 ACPI device to q35

 default-configs/i386-softmmu.mak |   3 +
 hw/acpi/aml-build.c  |  40 
 hw/acpi/ipmi-stub.c  |   2 +-
 hw/acpi/ipmi.c   |  13 +-
 hw/i386/Kconfig  |   3 +
 hw/i386/acpi-build.c |  17 +-
 hw/i386/pc_piix.c|  12 +-
 hw/i386/pc_q35.c |   9 +-
 hw/ipmi/Kconfig  |  15 ++
 hw/ipmi/Makefile.objs|   5 +-
 hw/ipmi/ipmi.c   |   6 +-
 hw/ipmi/ipmi_bmc_sim.c   |  30 ++-
 hw/ipmi/ipmi_bt.c| 437 ++
 hw/ipmi/ipmi_kcs.c   | 423 +
 hw/ipmi/isa_ipmi_bt.c| 443 ++-
 hw/ipmi/isa_ipmi_kcs.c   | 419 ++--
 hw/ipmi/pci_ipmi_bt.c| 146 +
 hw/ipmi/pci_ipmi_kcs.c   | 146 +
 hw/ipmi/smbus_ipmi.c | 384 +
 hw/smbios/smbios_type_38.c   |   3 +
 include/hw/acpi/aml-build.h  |  18 ++
 include/hw/acpi/ipmi.h   |   2 +-
 include/hw/i386/pc.h |   2 +
 include/hw/ipmi/ipmi.h   |   7 +-
 include/hw/ipmi/ipmi_bt.h|  73 +++
 include/hw/ipmi/ipmi_kcs.h   |  76 +++
 include/hw/pci/pci.h |   1 +
 include/hw/qdev-properties.h |   7 +
 qemu-options.hx  |  10 +-
 tests/Makefile.include   |   3 +-
 tests/data/acpi/q35/DSDT | Bin 7841 -> 7879 bytes
 tests/data/acpi/q35/DSDT.bridge  | Bin 7858 -> 7896 bytes
 tests/data/acpi/q35/DSDT.cphp| Bin 8304 -> 8342 bytes
 tests/data/acpi/q35/DSDT.dimmpxm | Bin 9494 -> 9532 bytes
 tests/data/acpi/q35/DSDT.ipmibt  | Bin 7916 -> 7954 bytes
 tests/data/acpi/q35/DSDT.memhp   | Bin 9200 -> 9238 bytes
 tests/data/acpi/q35/DSDT.mmio64  | Bin 8971 -> 9009 bytes
 tests/data/acpi/q35/DSDT.numamem | Bin 7847 -> 7885 bytes
 tests/ipmi-bt-test.c |   6 +-
 39 files changed, 1902 insertions(+), 859 deletions(-)
 create mode 100644 hw/ipmi/ipmi_bt.c
 create mode 100644 hw/ipmi/ipmi_kcs.c
 create mode 100644 hw/ipmi/pci_ipmi_bt.c
 create mode 100644 hw/ipmi/pci_ipmi_kcs.c
 create mode 100644 hw/ipmi/smbus_ipmi.c
 create mode 100644 include/hw/ipmi/ipmi_bt.h
 create mode 100644 include/hw/ipmi/ipmi_kcs.h






[PATCH v4 12/24] audio: unify input and output mixeng buffer management

2019-09-19 Thread Kővágó, Zoltán
Usage notes: hw->samples became hw->{mix,conv}_buf->size, except before
initialization (audio_pcm_hw_alloc_resources_*), hw->samples gives the
initial size of the STSampleBuffer.  The next commit tries to fix this
inconsistency.

Signed-off-by: Kővágó, Zoltán 
---
 audio/audio.c  | 122 +
 audio/audio_int.h  |  12 ++--
 audio/audio_template.h |  19 +++
 audio/ossaudio.c   |   3 +-
 4 files changed, 80 insertions(+), 76 deletions(-)

diff --git a/audio/audio.c b/audio/audio.c
index 435bcf20c1..ba07fb77dd 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -544,8 +544,8 @@ static size_t audio_pcm_hw_find_min_in (HWVoiceIn *hw)
 static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw)
 {
 size_t live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw);
-if (audio_bug(__func__, live > hw->samples)) {
-dolog("live=%zu hw->samples=%zu\n", live, hw->samples);
+if (audio_bug(__func__, live > hw->conv_buf->size)) {
+dolog("live=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size);
 return 0;
 }
 return live;
@@ -554,17 +554,17 @@ static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw)
 static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len)
 {
 size_t clipped = 0;
-size_t pos = hw->rpos;
+size_t pos = hw->mix_buf->pos;
 
 while (len) {
-st_sample *src = hw->mix_buf + pos;
+st_sample *src = hw->mix_buf->samples + pos;
 uint8_t *dst = advance(pcm_buf, clipped << hw->info.shift);
-size_t samples_till_end_of_buf = hw->samples - pos;
+size_t samples_till_end_of_buf = hw->mix_buf->size - pos;
 size_t samples_to_clip = MIN(len, samples_till_end_of_buf);
 
 hw->clip(dst, src, samples_to_clip);
 
-pos = (pos + samples_to_clip) % hw->samples;
+pos = (pos + samples_to_clip) % hw->mix_buf->size;
 len -= samples_to_clip;
 clipped += samples_to_clip;
 }
@@ -579,17 +579,17 @@ static size_t audio_pcm_sw_get_rpos_in(SWVoiceIn *sw)
 ssize_t live = hw->total_samples_captured - sw->total_hw_samples_acquired;
 ssize_t rpos;
 
-if (audio_bug(__func__, live < 0 || live > hw->samples)) {
-dolog("live=%zu hw->samples=%zu\n", live, hw->samples);
+if (audio_bug(__func__, live < 0 || live > hw->conv_buf->size)) {
+dolog("live=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size);
 return 0;
 }
 
-rpos = hw->wpos - live;
+rpos = hw->conv_buf->pos - live;
 if (rpos >= 0) {
 return rpos;
 }
 else {
-return hw->samples + rpos;
+return hw->conv_buf->size + rpos;
 }
 }
 
@@ -599,11 +599,11 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, 
size_t size)
 size_t samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0;
 struct st_sample *src, *dst = sw->buf;
 
-rpos = audio_pcm_sw_get_rpos_in (sw) % hw->samples;
+rpos = audio_pcm_sw_get_rpos_in(sw) % hw->conv_buf->size;
 
 live = hw->total_samples_captured - sw->total_hw_samples_acquired;
-if (audio_bug(__func__, live > hw->samples)) {
-dolog("live_in=%zu hw->samples=%zu\n", live, hw->samples);
+if (audio_bug(__func__, live > hw->conv_buf->size)) {
+dolog("live_in=%zu hw->conv_buf->size=%zu\n", live, 
hw->conv_buf->size);
 return 0;
 }
 
@@ -616,11 +616,11 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, 
size_t size)
 swlim = MIN (swlim, samples);
 
 while (swlim) {
-src = hw->conv_buf + rpos;
-if (hw->wpos > rpos) {
-isamp = hw->wpos - rpos;
+src = hw->conv_buf->samples + rpos;
+if (hw->conv_buf->pos > rpos) {
+isamp = hw->conv_buf->pos - rpos;
 } else {
-isamp = hw->samples - rpos;
+isamp = hw->conv_buf->size - rpos;
 }
 
 if (!isamp) {
@@ -630,7 +630,7 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, 
size_t size)
 
 st_rate_flow (sw->rate, src, dst, , );
 swlim -= osamp;
-rpos = (rpos + isamp) % hw->samples;
+rpos = (rpos + isamp) % hw->conv_buf->size;
 dst += osamp;
 ret += osamp;
 total += isamp;
@@ -678,8 +678,8 @@ static size_t audio_pcm_hw_get_live_out (HWVoiceOut *hw, 
int *nb_live)
 if (nb_live1) {
 size_t live = smin;
 
-if (audio_bug(__func__, live > hw->samples)) {
-dolog("live=%zu hw->samples=%zu\n", live, hw->samples);
+if (audio_bug(__func__, live > hw->mix_buf->size)) {
+dolog("live=%zu hw->mix_buf->size=%zu\n", live, hw->mix_buf->size);
 return 0;
 }
 return live;
@@ -699,11 +699,11 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void 
*buf, size_t size)
 return size;
 }
 
-hwsamples = sw->hw->samples;
+hwsamples = sw->hw->mix_buf->size;
 
 live = sw->total_hw_samples_mixed;
 if 

[PATCH 06/15] ipmi: Add a UUID device property

2019-09-19 Thread minyard
From: Corey Minyard 

Using the UUID that qemu generates probably isn't the best thing
to do, allow it to be passed in via properties, and use QemuUUID
for the type.

If the UUID is not set, return an unsupported command error.  This
way we are not providing an all-zero (or randomly generated) GUID
to the IPMI user.  This lets the host fall back to the other
method of using the get device id command to determind the BMC
being accessed.

Signed-off-by: Corey Minyard 
Cc: Cédric Le Goater 
Cc: David Gibson 
Cc: Michael S. Tsirkin 
Cc: Paolo Bonzini 
---
 hw/ipmi/ipmi_bmc_sim.c | 22 ++
 qemu-options.hx| 10 +++---
 2 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index 6e6cd1b47d..71e56f3b13 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -223,7 +223,7 @@ struct IPMIBmcSim {
 uint8_t restart_cause;
 
 uint8_t acpi_power_state[2];
-uint8_t uuid[16];
+QemuUUID uuid;
 
 IPMISel sel;
 IPMISdr sdr;
@@ -941,8 +941,19 @@ static void get_device_guid(IPMIBmcSim *ibs,
 {
 unsigned int i;
 
+/* An uninitialized uuid is all zeros, use that to know if it is set. */
 for (i = 0; i < 16; i++) {
-rsp_buffer_push(rsp, ibs->uuid[i]);
+if (ibs->uuid.data[i]) {
+goto uuid_set;
+}
+}
+/* No uuid is set, return an error. */
+rsp_buffer_set_error(rsp, IPMI_CC_INVALID_CMD);
+return;
+
+ uuid_set:
+for (i = 0; i < 16; i++) {
+rsp_buffer_push(rsp, ibs->uuid.data[i]);
 }
 }
 
@@ -1986,12 +1997,6 @@ static void ipmi_sim_realize(DeviceState *dev, Error 
**errp)
 ibs->acpi_power_state[0] = 0;
 ibs->acpi_power_state[1] = 0;
 
-if (qemu_uuid_set) {
-memcpy(>uuid, _uuid, 16);
-} else {
-memset(>uuid, 0, 16);
-}
-
 ipmi_init_sensors_from_sdrs(ibs);
 register_cmds(ibs);
 
@@ -2011,6 +2016,7 @@ static Property ipmi_sim_properties[] = {
 DEFINE_PROP_UINT8("fwrev2", IPMIBmcSim, fwrev2, 0),
 DEFINE_PROP_UINT32("mfg_id", IPMIBmcSim, mfg_id, 0),
 DEFINE_PROP_UINT16("product_id", IPMIBmcSim, product_id, 0),
+DEFINE_PROP_UUID_NODEFAULT("guid", IPMIBmcSim, uuid),
 DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/qemu-options.hx b/qemu-options.hx
index bbfd936d29..ed9292f65e 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -701,7 +701,7 @@ possible drivers and properties, use @code{-device help} and
 @code{-device @var{driver},help}.
 
 Some drivers are:
-@item -device 
ipmi-bmc-sim,id=@var{id}[,slave_addr=@var{val}][,sdrfile=@var{file}][,furareasize=@var{val}][,furdatafile=@var{file}]
+@item -device 
ipmi-bmc-sim,id=@var{id}[,slave_addr=@var{val}][,sdrfile=@var{file}][,furareasize=@var{val}][,furdatafile=@var{file}][,guid=@var{uuid}]
 
 Add an IPMI BMC.  This is a simulation of a hardware management
 interface processor that normally sits on a system.  It provides
@@ -714,8 +714,8 @@ controllers.  If you don't know what this means, it is safe 
to ignore
 it.
 
 @table @option
-@item bmc=@var{id}
-The BMC to connect to, one of ipmi-bmc-sim or ipmi-bmc-extern above.
+@item id=@var{id}
+The BMC id for interfaces to use this device.
 @item slave_addr=@var{val}
 Define slave address to use for the BMC.  The default is 0x20.
 @item sdrfile=@var{file}
@@ -724,6 +724,10 @@ file containing raw Sensor Data Records (SDR) data. The 
default is none.
 size of a Field Replaceable Unit (FRU) area.  The default is 1024.
 @item frudatafile=@var{file}
 file containing raw Field Replaceable Unit (FRU) inventory data. The default 
is none.
+@item guid=@var{uuid}
+value for the GUID for the BMC, in standard UUID format.  If this is set,
+get "Get GUID" command to the BMC will return it.  Otherwise "Get GUID"
+will return an error.
 @end table
 
 @item -device 
ipmi-bmc-extern,id=@var{id},chardev=@var{id}[,slave_addr=@var{val}]
-- 
2.17.1




[PATCH 01/15] ipmi: Fix watchdog NMI handling

2019-09-19 Thread minyard
From: Corey Minyard 

The wrong logic was used for detection (so it wouldn't work at all)
and the wrong interface was used to inject the NMI if the detection
logic was correct.

Signed-off-by: Corey Minyard 
---
 hw/ipmi/ipmi.c | 6 +++---
 hw/ipmi/ipmi_bmc_sim.c | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/ipmi/ipmi.c b/hw/ipmi/ipmi.c
index 136c86b7a7..cbe158f815 100644
--- a/hw/ipmi/ipmi.c
+++ b/hw/ipmi/ipmi.c
@@ -28,9 +28,8 @@
 #include "qom/object_interfaces.h"
 #include "sysemu/runstate.h"
 #include "qapi/error.h"
-#include "qapi/qapi-commands-misc.h"
-#include "qapi/visitor.h"
 #include "qemu/module.h"
+#include "hw/nmi.h"
 
 static uint32_t ipmi_current_uuid = 1;
 
@@ -60,7 +59,8 @@ static int ipmi_do_hw_op(IPMIInterface *s, enum ipmi_op op, 
int checkonly)
 if (checkonly) {
 return 0;
 }
-qmp_inject_nmi(NULL);
+/* We don't care what CPU we use. */
+nmi_monitor_handle(0, NULL);
 return 0;
 
 case IPMI_SHUTDOWN_VIA_ACPI_OVERTEMP:
diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index 246a6d390c..8f63bb7181 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -1194,7 +1194,7 @@ static void set_watchdog_timer(IPMIBmcSim *ibs,
 break;
 
 case IPMI_BMC_WATCHDOG_PRE_NMI:
-if (!k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
+if (k->do_hw_op(s, IPMI_SEND_NMI, 1)) {
 /* NMI not supported. */
 rsp_buffer_set_error(rsp, IPMI_CC_INVALID_DATA_FIELD);
 return;
-- 
2.17.1




[PATCH v4 16/24] audio: make mixeng optional

2019-09-19 Thread Kővágó, Zoltán
Implementation of the previously added mixing-engine option.

Signed-off-by: Kővágó, Zoltán 
---
 audio/audio.c  | 70 ++
 audio/audio_template.h | 20 
 2 files changed, 78 insertions(+), 12 deletions(-)

diff --git a/audio/audio.c b/audio/audio.c
index 7128ee98dc..d616a4af98 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -838,32 +838,46 @@ static void audio_timer (void *opaque)
  */
 size_t AUD_write(SWVoiceOut *sw, void *buf, size_t size)
 {
+HWVoiceOut *hw;
+
 if (!sw) {
 /* XXX: Consider options */
 return size;
 }
+hw = sw->hw;
 
-if (!sw->hw->enabled) {
+if (!hw->enabled) {
 dolog ("Writing to disabled voice %s\n", SW_NAME (sw));
 return 0;
 }
 
-return audio_pcm_sw_write(sw, buf, size);
+if (audio_get_pdo_out(hw->s->dev)->mixing_engine) {
+return audio_pcm_sw_write(sw, buf, size);
+} else {
+return hw->pcm_ops->write(hw, buf, size);
+}
 }
 
 size_t AUD_read(SWVoiceIn *sw, void *buf, size_t size)
 {
+HWVoiceIn *hw;
+
 if (!sw) {
 /* XXX: Consider options */
 return size;
 }
+hw = sw->hw;
 
-if (!sw->hw->enabled) {
+if (!hw->enabled) {
 dolog ("Reading from disabled voice %s\n", SW_NAME (sw));
 return 0;
 }
 
-return audio_pcm_sw_read(sw, buf, size);
+if (audio_get_pdo_in(hw->s->dev)->mixing_engine) {
+return audio_pcm_sw_read(sw, buf, size);
+} else {
+return hw->pcm_ops->read(hw, buf, size);
+}
 }
 
 int AUD_get_buffer_size_out (SWVoiceOut *sw)
@@ -1090,6 +1104,26 @@ static void audio_run_out (AudioState *s)
 HWVoiceOut *hw = NULL;
 SWVoiceOut *sw;
 
+if (!audio_get_pdo_out(s->dev)->mixing_engine) {
+while ((hw = audio_pcm_hw_find_any_enabled_out(s, hw))) {
+/* there is exactly 1 sw for each hw with no mixeng */
+sw = hw->sw_head.lh_first;
+
+if (hw->pending_disable) {
+hw->enabled = 0;
+hw->pending_disable = 0;
+if (hw->pcm_ops->enable_out) {
+hw->pcm_ops->enable_out(hw, false);
+}
+}
+
+if (sw->active) {
+sw->callback.fn(sw->callback.opaque, INT_MAX);
+}
+}
+return;
+}
+
 while ((hw = audio_pcm_hw_find_any_enabled_out(s, hw))) {
 size_t played, live, prev_rpos, free;
 int nb_live, cleanup_required;
@@ -1227,6 +1261,17 @@ static void audio_run_in (AudioState *s)
 {
 HWVoiceIn *hw = NULL;
 
+if (!audio_get_pdo_in(s->dev)->mixing_engine) {
+while ((hw = audio_pcm_hw_find_any_enabled_in(s, hw))) {
+/* there is exactly 1 sw for each hw with no mixeng */
+SWVoiceIn *sw = hw->sw_head.lh_first;
+if (sw->active) {
+sw->callback.fn(sw->callback.opaque, INT_MAX);
+}
+}
+return;
+}
+
 while ((hw = audio_pcm_hw_find_any_enabled_in(s, hw))) {
 SWVoiceIn *sw;
 size_t captured = 0, min;
@@ -1751,6 +1796,11 @@ CaptureVoiceOut *AUD_add_capture(
 s = audio_init(NULL, NULL);
 }
 
+if (!audio_get_pdo_out(s->dev)->mixing_engine) {
+dolog("Can't capture with mixeng disabled\n");
+return NULL;
+}
+
 if (audio_validate_settings (as)) {
 dolog ("Invalid settings were passed when trying to add capture\n");
 audio_print_settings (as);
@@ -1905,9 +1955,13 @@ void audio_create_pdos(Audiodev *dev)
 static void audio_validate_per_direction_opts(
 AudiodevPerDirectionOptions *pdo, Error **errp)
 {
+if (!pdo->has_mixing_engine) {
+pdo->has_mixing_engine = true;
+pdo->mixing_engine = true;
+}
 if (!pdo->has_fixed_settings) {
 pdo->has_fixed_settings = true;
-pdo->fixed_settings = true;
+pdo->fixed_settings = pdo->mixing_engine;
 }
 if (!pdo->fixed_settings &&
 (pdo->has_frequency || pdo->has_channels || pdo->has_format)) {
@@ -1915,6 +1969,10 @@ static void audio_validate_per_direction_opts(
"You can't use frequency, channels or format with 
fixed-settings=off");
 return;
 }
+if (!pdo->mixing_engine && pdo->fixed_settings) {
+error_setg(errp, "You can't use fixed-settings without mixeng");
+return;
+}
 
 if (!pdo->has_frequency) {
 pdo->has_frequency = true;
@@ -1926,7 +1984,7 @@ static void audio_validate_per_direction_opts(
 }
 if (!pdo->has_voices) {
 pdo->has_voices = true;
-pdo->voices = 1;
+pdo->voices = pdo->mixing_engine ? 1 : INT_MAX;
 }
 if (!pdo->has_format) {
 pdo->has_format = true;
diff --git a/audio/audio_template.h b/audio/audio_template.h
index 235d1acbbe..b6c5466cff 100644
--- a/audio/audio_template.h
+++ b/audio/audio_template.h
@@ -78,13 +78,17 @@ static void glue 

[PATCH 02/15] ipmi: Fix the get watchdog command

2019-09-19 Thread minyard
From: Corey Minyard 

It wasn't returning the set timeout like it should have been.

Signed-off-by: Corey Minyard 
---
 hw/ipmi/ipmi_bmc_sim.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/ipmi/ipmi_bmc_sim.c b/hw/ipmi/ipmi_bmc_sim.c
index 8f63bb7181..afb99e33d7 100644
--- a/hw/ipmi/ipmi_bmc_sim.c
+++ b/hw/ipmi/ipmi_bmc_sim.c
@@ -1228,6 +1228,8 @@ static void get_watchdog_timer(IPMIBmcSim *ibs,
 rsp_buffer_push(rsp, ibs->watchdog_action);
 rsp_buffer_push(rsp, ibs->watchdog_pretimeout);
 rsp_buffer_push(rsp, ibs->watchdog_expired);
+rsp_buffer_push(rsp, ibs->watchdog_timeout & 0xff);
+rsp_buffer_push(rsp, (ibs->watchdog_timeout >> 8) & 0xff);
 if (ibs->watchdog_running) {
 long timeout;
 timeout = ((ibs->watchdog_expiry - ipmi_getmonotime() + 5000)
-- 
2.17.1




[PATCH 04/15] tests:ipmi: Fix IPMI BT tests

2019-09-19 Thread minyard
From: Corey Minyard 

The IPMI BT tests had a race condition, if it receive an IPMI command
to enable interrupt, it would write the message to enable interrupts
after it wrote the command response.  So the test code could
receive the command response and issue the next command before the
device handled the interrupt enable command, and thus no interrupt.

So send the message to enable interrupt before the command response.

Also add some sleeps to give qemu time to handle responses, there was
no delay before, and it could result in an invalid timeout.

And re-enable the tests, as hopefully they are fixed now.

Note that I was unable to reproduce this even with the instructions
Peter gave me, but hopefully this fixes the issue.

Cc: Peter Maydell 
Signed-off-by: Corey Minyard 
---
 tests/Makefile.include | 3 +--
 tests/ipmi-bt-test.c   | 6 --
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/tests/Makefile.include b/tests/Makefile.include
index 793632ca72..479664f899 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -170,8 +170,7 @@ check-qtest-i386-$(CONFIG_SGA) += 
tests/boot-serial-test$(EXESUF)
 check-qtest-i386-$(CONFIG_SLIRP) += tests/pxe-test$(EXESUF)
 check-qtest-i386-y += tests/rtc-test$(EXESUF)
 check-qtest-i386-$(CONFIG_ISA_IPMI_KCS) += tests/ipmi-kcs-test$(EXESUF)
-# Disabled temporarily as it fails intermittently especially under NetBSD VM
-# check-qtest-i386-$(CONFIG_ISA_IPMI_BT) += tests/ipmi-bt-test$(EXESUF)
+check-qtest-i386-$(CONFIG_ISA_IPMI_BT) += tests/ipmi-bt-test$(EXESUF)
 check-qtest-i386-y += tests/i440fx-test$(EXESUF)
 check-qtest-i386-y += tests/fw_cfg-test$(EXESUF)
 check-qtest-i386-y += tests/device-plug-test$(EXESUF)
diff --git a/tests/ipmi-bt-test.c b/tests/ipmi-bt-test.c
index fc4c83b5db..a42207d416 100644
--- a/tests/ipmi-bt-test.c
+++ b/tests/ipmi-bt-test.c
@@ -30,7 +30,7 @@
 #include 
 
 
-#include "libqtest.h"
+#include "libqtest-single.h"
 #include "qemu-common.h"
 
 #define IPMI_IRQ5
@@ -99,6 +99,7 @@ static void bt_wait_b_busy(void)
 unsigned int count = 1000;
 while (IPMI_BT_CTLREG_GET_B_BUSY() != 0) {
 g_assert(--count != 0);
+usleep(100);
 }
 }
 
@@ -107,6 +108,7 @@ static void bt_wait_b2h_atn(void)
 unsigned int count = 1000;
 while (IPMI_BT_CTLREG_GET_B2H_ATN() == 0) {
 g_assert(--count != 0);
+usleep(100);
 }
 }
 
@@ -240,13 +242,13 @@ static void emu_msg_handler(void)
 write_emu_msg(msg, msg_len);
 } else if ((msg[1] == set_bmc_globals_cmd[0]) &&
(msg[2] == set_bmc_globals_cmd[1])) {
+write_emu_msg(enable_irq_cmd, sizeof(enable_irq_cmd));
 memcpy(msg + 1, set_bmc_globals_rsp, sizeof(set_bmc_globals_rsp));
 msg_len = sizeof(set_bmc_globals_rsp) + 1;
 msg[msg_len] = -ipmb_checksum(msg, msg_len, 0);
 msg_len++;
 msg[msg_len++] = 0xa0;
 write_emu_msg(msg, msg_len);
-write_emu_msg(enable_irq_cmd, sizeof(enable_irq_cmd));
 } else {
 g_assert(0);
 }
-- 
2.17.1




[PATCH v4 22/24] usb-audio: do not count on avail bytes actually available

2019-09-19 Thread Kővágó, Zoltán
This assumption is no longer true when mixeng is turned off.

Signed-off-by: Kővágó, Zoltán 
---
 hw/usb/dev-audio.c | 28 +---
 1 file changed, 17 insertions(+), 11 deletions(-)

diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c
index ae42e5a2f1..74c99b1f12 100644
--- a/hw/usb/dev-audio.c
+++ b/hw/usb/dev-audio.c
@@ -319,30 +319,31 @@ static int streambuf_put(struct streambuf *buf, USBPacket 
*p)
 {
 uint32_t free = buf->size - (buf->prod - buf->cons);
 
-if (!free) {
+if (free < USBAUDIO_PACKET_SIZE) {
 return 0;
 }
 if (p->iov.size != USBAUDIO_PACKET_SIZE) {
 return 0;
 }
-assert(free >= USBAUDIO_PACKET_SIZE);
+
 usb_packet_copy(p, buf->data + (buf->prod % buf->size),
 USBAUDIO_PACKET_SIZE);
 buf->prod += USBAUDIO_PACKET_SIZE;
 return USBAUDIO_PACKET_SIZE;
 }
 
-static uint8_t *streambuf_get(struct streambuf *buf)
+static uint8_t *streambuf_get(struct streambuf *buf, size_t *len)
 {
 uint32_t used = buf->prod - buf->cons;
 uint8_t *data;
 
 if (!used) {
+*len = 0;
 return NULL;
 }
-assert(used >= USBAUDIO_PACKET_SIZE);
 data = buf->data + (buf->cons % buf->size);
-buf->cons += USBAUDIO_PACKET_SIZE;
+*len = MIN(buf->prod - buf->cons,
+   buf->size - (buf->cons % buf->size));
 return data;
 }
 
@@ -374,16 +375,21 @@ static void output_callback(void *opaque, int avail)
 USBAudioState *s = opaque;
 uint8_t *data;
 
-for (;;) {
-if (avail < USBAUDIO_PACKET_SIZE) {
+while (avail) {
+size_t written, len;
+
+data = streambuf_get(>out.buf, );
+if (!data) {
 return;
 }
-data = streambuf_get(>out.buf);
-if (!data) {
+
+written = AUD_write(s->out.voice, data, len);
+avail -= written;
+s->out.buf.cons += written;
+
+if (written < len) {
 return;
 }
-AUD_write(s->out.voice, data, USBAUDIO_PACKET_SIZE);
-avail -= USBAUDIO_PACKET_SIZE;
 }
 }
 
-- 
2.23.0




[PATCH v4 13/24] audio: common rate control code for timer based outputs

2019-09-19 Thread Kővágó, Zoltán
This commit removes the ad-hoc rate-limiting code from noaudio and
wavaudio, and replaces them with a (slightly modified) code from
spiceaudio.  This way multiple write calls (for example when the
circular buffer wraps around) do not cause problems.

Signed-off-by: Kővágó, Zoltán 
---
 audio/audio.c  | 30 +++
 audio/audio_int.h  |  9 
 audio/noaudio.c| 49 
 audio/spiceaudio.c | 51 --
 audio/wavaudio.c   | 21 +--
 5 files changed, 79 insertions(+), 81 deletions(-)

diff --git a/audio/audio.c b/audio/audio.c
index ba07fb77dd..fab1e35718 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -2051,3 +2051,33 @@ const char *audio_get_id(QEMUSoundCard *card)
 return "";
 }
 }
+
+void audio_rate_start(RateCtl *rate)
+{
+memset(rate, 0, sizeof(RateCtl));
+rate->start_ticks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+}
+
+size_t audio_rate_get_bytes(struct audio_pcm_info *info, RateCtl *rate,
+size_t bytes_avail)
+{
+int64_t now;
+int64_t ticks;
+int64_t bytes;
+int64_t samples;
+size_t ret;
+
+now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ticks = now - rate->start_ticks;
+bytes = muldiv64(ticks, info->bytes_per_second, NANOSECONDS_PER_SECOND);
+samples = (bytes - rate->bytes_sent) >> info->shift;
+if (samples < 0 || samples > 65536) {
+AUD_log(NULL, "Resetting rate control (%" PRId64 " samples)\n", 
samples);
+audio_rate_start(rate);
+samples = 0;
+}
+
+ret = MIN(samples << info->shift, bytes_avail);
+rate->bytes_sent += ret;
+return ret;
+}
diff --git a/audio/audio_int.h b/audio/audio_int.h
index 20021df9e8..778615ccaf 100644
--- a/audio/audio_int.h
+++ b/audio/audio_int.h
@@ -242,6 +242,15 @@ void *audio_calloc (const char *funcname, int nmemb, 
size_t size);
 
 void audio_run(AudioState *s, const char *msg);
 
+typedef struct RateCtl {
+int64_t start_ticks;
+int64_t bytes_sent;
+} RateCtl;
+
+void audio_rate_start(RateCtl *rate);
+size_t audio_rate_get_bytes(struct audio_pcm_info *info, RateCtl *rate,
+size_t bytes_avail);
+
 #define VOICE_ENABLE 1
 #define VOICE_DISABLE 2
 #define VOICE_VOLUME 3
diff --git a/audio/noaudio.c b/audio/noaudio.c
index b054fd225b..9f1cc67df9 100644
--- a/audio/noaudio.c
+++ b/audio/noaudio.c
@@ -33,33 +33,27 @@
 
 typedef struct NoVoiceOut {
 HWVoiceOut hw;
-int64_t old_ticks;
+RateCtl rate;
 } NoVoiceOut;
 
 typedef struct NoVoiceIn {
 HWVoiceIn hw;
-int64_t old_ticks;
+RateCtl rate;
 } NoVoiceIn;
 
 static size_t no_write(HWVoiceOut *hw, void *buf, size_t len)
 {
 NoVoiceOut *no = (NoVoiceOut *) hw;
-int64_t now;
-int64_t ticks;
-int64_t bytes;
-
-now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-ticks = now - no->old_ticks;
-bytes = muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND);
-
-no->old_ticks = now;
-return MIN(len, bytes);
+return audio_rate_get_bytes(>info, >rate, len);
 }
 
 static int no_init_out(HWVoiceOut *hw, struct audsettings *as, void 
*drv_opaque)
 {
+NoVoiceOut *no = (NoVoiceOut *) hw;
+
 audio_pcm_init_info (>info, as);
 hw->samples = 1024;
+audio_rate_start(>rate);
 return 0;
 }
 
@@ -70,15 +64,21 @@ static void no_fini_out (HWVoiceOut *hw)
 
 static int no_ctl_out (HWVoiceOut *hw, int cmd, ...)
 {
-(void) hw;
-(void) cmd;
+NoVoiceOut *no = (NoVoiceOut *) hw;
+
+if (cmd == VOICE_ENABLE) {
+audio_rate_start(>rate);
+}
 return 0;
 }
 
 static int no_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
 {
+NoVoiceIn *no = (NoVoiceIn *) hw;
+
 audio_pcm_init_info (>info, as);
 hw->samples = 1024;
+audio_rate_start(>rate);
 return 0;
 }
 
@@ -89,25 +89,20 @@ static void no_fini_in (HWVoiceIn *hw)
 
 static size_t no_read(HWVoiceIn *hw, void *buf, size_t size)
 {
-size_t to_clear;
 NoVoiceIn *no = (NoVoiceIn *) hw;
+int64_t bytes = audio_rate_get_bytes(>info, >rate, size);
 
-int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-int64_t ticks = now - no->old_ticks;
-int64_t bytes =
-muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND);
-
-no->old_ticks = now;
-to_clear = MIN(bytes, size);
-
-audio_pcm_info_clear_buf(>info, buf, to_clear >> hw->info.shift);
-return to_clear;
+audio_pcm_info_clear_buf(>info, buf, bytes >> hw->info.shift);
+return bytes;
 }
 
 static int no_ctl_in (HWVoiceIn *hw, int cmd, ...)
 {
-(void) hw;
-(void) cmd;
+NoVoiceIn *no = (NoVoiceIn *) hw;
+
+if (cmd == VOICE_ENABLE) {
+audio_rate_start(>rate);
+}
 return 0;
 }
 
diff --git a/audio/spiceaudio.c b/audio/spiceaudio.c
index ff4e4dcbb0..4ce4f94c6d 100644
--- a/audio/spiceaudio.c
+++ b/audio/spiceaudio.c
@@ -40,15 +40,10 @@
 #define 

[PATCH v4 08/24] sdlaudio: port to the new audio backend api

2019-09-19 Thread Kővágó, Zoltán
Signed-off-by: Kővágó, Zoltán 
---
 audio/sdlaudio.c | 87 +++-
 1 file changed, 42 insertions(+), 45 deletions(-)

diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c
index 14b11f0335..f7ac8cd101 100644
--- a/audio/sdlaudio.c
+++ b/audio/sdlaudio.c
@@ -41,8 +41,6 @@
 
 typedef struct SDLVoiceOut {
 HWVoiceOut hw;
-size_t live;
-size_t decr;
 } SDLVoiceOut;
 
 static struct SDLAudioState {
@@ -184,62 +182,59 @@ static void sdl_callback (void *opaque, Uint8 *buf, int 
len)
 SDLVoiceOut *sdl = opaque;
 SDLAudioState *s = _sdl;
 HWVoiceOut *hw = >hw;
-size_t samples = len >> hw->info.shift;
-size_t to_mix, decr;
 
-if (s->exit || !sdl->live) {
+if (s->exit) {
 return;
 }
 
 /* dolog ("in callback samples=%zu live=%zu\n", samples, sdl->live); */
 
-to_mix = MIN(samples, sdl->live);
-decr = to_mix;
-while (to_mix) {
-size_t chunk = MIN(to_mix, hw->samples - hw->rpos);
-struct st_sample *src = hw->mix_buf + hw->rpos;
-
-/* dolog ("in callback to_mix %zu, chunk %zu\n", to_mix, chunk); */
-hw->clip(buf, src, chunk);
-hw->rpos = (hw->rpos + chunk) % hw->samples;
-to_mix -= chunk;
-buf += chunk << hw->info.shift;
+while (hw->pending_emul && len) {
+size_t write_len;
+ssize_t start = ((ssize_t) hw->pos_emul) - hw->pending_emul;
+if (start < 0) {
+start += hw->size_emul;
+}
+assert(start >= 0 && start < hw->size_emul);
+
+write_len = MIN(MIN(hw->pending_emul, len),
+hw->size_emul - start);
+
+memcpy(buf, hw->buf_emul + start, write_len);
+hw->pending_emul -= write_len;
+len -= write_len;
+buf += write_len;
 }
-samples -= decr;
-sdl->live -= decr;
-sdl->decr += decr;
 
-/* dolog ("done len=%zu\n", len); */
-
-/* SDL2 does not clear the remaining buffer for us, so do it on our own */
-if (samples) {
-memset(buf, 0, samples << hw->info.shift);
+/* clear remaining buffer that we couldn't fill with data */
+if (len) {
+memset(buf, 0, len);
 }
 }
 
-static size_t sdl_run_out(HWVoiceOut *hw, size_t live)
-{
-size_t decr;
-SDLVoiceOut *sdl = (SDLVoiceOut *) hw;
-
-SDL_LockAudio();
-
-if (sdl->decr > live) {
-ldebug ("sdl->decr %d live %d sdl->live %d\n",
-sdl->decr,
-live,
-sdl->live);
+#define SDL_WRAPPER_FUNC(name, ret_type, args_decl, args, fail, unlock) \
+static ret_type glue(sdl_, name)args_decl   \
+{   \
+ret_type ret;   \
+\
+SDL_LockAudio();\
+\
+ret = glue(audio_generic_, name)args;   \
+\
+SDL_UnlockAudio();  \
+return ret; \
 }
 
-decr = MIN (sdl->decr, live);
-sdl->decr -= decr;
-
-sdl->live = live;
+SDL_WRAPPER_FUNC(get_buffer_out, void *, (HWVoiceOut *hw, size_t *size),
+ (hw, size), *size = 0, sdl_unlock)
+SDL_WRAPPER_FUNC(put_buffer_out_nowrite, size_t,
+ (HWVoiceOut *hw, void *buf, size_t size), (hw, buf, size),
+ /*nothing*/, sdl_unlock_and_post)
+SDL_WRAPPER_FUNC(write, size_t,
+ (HWVoiceOut *hw, void *buf, size_t size), (hw, buf, size),
+ /*nothing*/, sdl_unlock_and_post)
 
-SDL_UnlockAudio();
-
-return decr;
-}
+#undef SDL_WRAPPER_FUNC
 
 static void sdl_fini_out (HWVoiceOut *hw)
 {
@@ -336,7 +331,9 @@ static void sdl_audio_fini (void *opaque)
 static struct audio_pcm_ops sdl_pcm_ops = {
 .init_out = sdl_init_out,
 .fini_out = sdl_fini_out,
-.run_out  = sdl_run_out,
+.write= sdl_write,
+.get_buffer_out = sdl_get_buffer_out,
+.put_buffer_out = sdl_put_buffer_out_nowrite,
 .ctl_out  = sdl_ctl_out,
 };
 
-- 
2.23.0




[PATCH v4 24/24] usbaudio: change playback counters to 64 bit

2019-09-19 Thread Kővágó, Zoltán
With stereo playback, they need about 375 minutes of continuous audio
playback to overflow, which is usually not a problem (as stopping and
later resuming playback resets the counters).  But with 7.1 audio, they
only need about 95 minutes to overflow.

After the overflow, the buf->prod % USBAUDIO_PACKET_SIZE(channels)
assertion no longer holds true, which will result in overflowing the
buffer.  With 64 bit variables, it would take about 762000 years to
overflow.

Signed-off-by: Kővágó, Zoltán 
---
 hw/usb/dev-audio.c | 14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c
index e42bdfbdc1..ea604bbb8e 100644
--- a/hw/usb/dev-audio.c
+++ b/hw/usb/dev-audio.c
@@ -578,9 +578,9 @@ static const USBDesc desc_audio_multi = {
 
 struct streambuf {
 uint8_t *data;
-uint32_t size;
-uint32_t prod;
-uint32_t cons;
+size_t size;
+uint64_t prod;
+uint64_t cons;
 };
 
 static void streambuf_init(struct streambuf *buf, uint32_t size,
@@ -601,7 +601,7 @@ static void streambuf_fini(struct streambuf *buf)
 
 static int streambuf_put(struct streambuf *buf, USBPacket *p, uint32_t 
channels)
 {
-uint32_t free = buf->size - (buf->prod - buf->cons);
+int64_t free = buf->size - (buf->prod - buf->cons);
 
 if (free < USBAUDIO_PACKET_SIZE(channels)) {
 return 0;
@@ -610,6 +610,8 @@ static int streambuf_put(struct streambuf *buf, USBPacket 
*p, uint32_t channels)
 return 0;
 }
 
+/* can happen if prod overflows */
+assert(buf->prod % USBAUDIO_PACKET_SIZE(channels) == 0);
 usb_packet_copy(p, buf->data + (buf->prod % buf->size),
 USBAUDIO_PACKET_SIZE(channels));
 buf->prod += USBAUDIO_PACKET_SIZE(channels);
@@ -618,10 +620,10 @@ static int streambuf_put(struct streambuf *buf, USBPacket 
*p, uint32_t channels)
 
 static uint8_t *streambuf_get(struct streambuf *buf, size_t *len)
 {
-uint32_t used = buf->prod - buf->cons;
+int64_t used = buf->prod - buf->cons;
 uint8_t *data;
 
-if (!used) {
+if (used <= 0) {
 *len = 0;
 return NULL;
 }
-- 
2.23.0




Re: [Qemu-devel] [PULL 00/26] Audio 20190919 patches

2019-09-19 Thread Zoltán Kővágó

On 2019-09-19 17:28, Eric Blake wrote:

On 9/19/19 10:15 AM, Peter Maydell wrote:

On Thu, 19 Sep 2019 at 09:38, Gerd Hoffmann  wrote:


The following changes since commit f8c3db33a5e863291182f8862ddf81618a7c6194:

   target/sparc: Switch to do_transaction_failed() hook (2019-09-17 12:01:00 
+0100)

are available in the Git repository at:

   git://git.kraxel.org/qemu tags/audio-20190919-pull-request

for you to fetch changes up to cf0c1c2aa32db5d658c3c797ad995a6d571bad96:

   audio: fix ALSA period-length typo in documentation (2019-09-19 10:32:48 
+0200)


audio: make mixeng optional.
audio: add surround sound support.
audio: documentation fixes.



Hi; I'm afraid this fails to build on OSX/FreeBSD/OpenBSD/Windows,
with format string issues:

/Users/pm215/src/qemu-for-merges/audio/wavaudio.c:50:15: error: format
specifies type 'size_t' (aka 'unsigned long') but the argument has
type 'int64_t' (aka 'long long') [-Werror,-Wformat]
   bytes, strerror(errno));
   ^


As long as you spin a v2, it's also worth fixing a typo I found in 15/26.



Thanks, fixed in v4, along with the compilation problem.



[PATCH v4 15/24] audio: add mixing-engine option (documentation)

2019-09-19 Thread Kővágó, Zoltán
This will allow us to disable mixeng when we use a decent backend.

Disabling mixeng have a few advantages:
* we no longer convert the audio output from one format to another, when
  the underlying audio system would just convert it to a third format.
  We no longer convert, only the underlying system, when needed.
* the underlying system probably has better resampling and sample format
  converting methods anyway...
* we may support formats that the mixeng currently does not support (S24
  or float samples, more than two channels)
* when using an audio server (like pulseaudio) different sound card
  outputs will show up as separate streams, even if we use only one
  backend

Disadvantages:
* audio capturing no longer works (wavcapture, and vnc audio extension)
* some backends only support a single playback stream or very picky
  about the audio format.  In this case we can't disable mixeng.

However mixeng is not removed, only made optional, so this shouldn't be
a big concern.

Signed-off-by: Kővágó, Zoltán 
---

Notes:
Changes from v1:

* renamed mixeng to mixing-engine

 qapi/audio.json | 5 +
 qemu-options.hx | 6 ++
 2 files changed, 11 insertions(+)

diff --git a/qapi/audio.json b/qapi/audio.json
index 9fefdf5186..0535eff794 100644
--- a/qapi/audio.json
+++ b/qapi/audio.json
@@ -11,6 +11,10 @@
 # General audio backend options that are used for both playback and
 # recording.
 #
+# @mixing-engine: use QEMU's mixing engine to mix all streams inside QEMU. When
+# set to off, fixed-settings must be also off. Not every 
backend
+# compatible with the off setting (default on, since 4.2)
+#
 # @fixed-settings: use fixed settings for host input/output. When off,
 #  frequency, channels and format must not be
 #  specified (default true)
@@ -31,6 +35,7 @@
 ##
 { 'struct': 'AudiodevPerDirectionOptions',
   'data': {
+'*mixing-engine':  'bool',
 '*fixed-settings': 'bool',
 '*frequency':  'uint32',
 '*channels':   'uint32',
diff --git a/qemu-options.hx b/qemu-options.hx
index bbfd936d29..395427422a 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -433,6 +433,7 @@ DEF("audiodev", HAS_ARG, QEMU_OPTION_audiodev,
 "specifies the audio backend to use\n"
 "id= identifier of the backend\n"
 "timer-period= timer period in microseconds\n"
+"in|out.mixing-engine= use mixing engine to mix streams 
inside QEMU\n"
 "in|out.fixed-settings= use fixed settings for host 
audio\n"
 "in|out.frequency= frequency to use with fixed settings\n"
 "in|out.channels= number of channels to use with fixed 
settings\n"
@@ -503,6 +504,11 @@ Identifies the audio backend.
 Sets the timer @var{period} used by the audio subsystem in microseconds.
 Default is 1 (10 ms).
 
+@item in|out.mixing-engine=on|off
+Use QEMU's mixing engine to mix all streams inside QEMU.  When off,
+@var{fixed-settings} must be off too.  Not every backend is fully
+compatible with the off setting.  Default is on.
+
 @item in|out.fixed-settings=on|off
 Use fixed settings for host audio.  When off, it will change based on
 how the guest opens the sound card.  In this case you must not specify
-- 
2.23.0




[PATCH v4 10/24] wavaudio: port to the new audio backend api

2019-09-19 Thread Kővágó, Zoltán
Signed-off-by: Kővágó, Zoltán 
---

Notes:
Changes from v3:

* fix compilation on 32-bit targets

 audio/wavaudio.c | 54 
 1 file changed, 9 insertions(+), 45 deletions(-)

diff --git a/audio/wavaudio.c b/audio/wavaudio.c
index b6eeeb4e26..78af2f1338 100644
--- a/audio/wavaudio.c
+++ b/audio/wavaudio.c
@@ -36,52 +36,28 @@ typedef struct WAVVoiceOut {
 HWVoiceOut hw;
 FILE *f;
 int64_t old_ticks;
-void *pcm_buf;
 int total_samples;
 } WAVVoiceOut;
 
-static size_t wav_run_out(HWVoiceOut *hw, size_t live)
+static size_t wav_write_out(HWVoiceOut *hw, void *buf, size_t len)
 {
 WAVVoiceOut *wav = (WAVVoiceOut *) hw;
-size_t rpos, decr, samples;
-uint8_t *dst;
-struct st_sample *src;
 int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 int64_t ticks = now - wav->old_ticks;
 int64_t bytes =
 muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND);
 
-if (bytes > INT_MAX) {
-samples = INT_MAX >> hw->info.shift;
-}
-else {
-samples = bytes >> hw->info.shift;
-}
-
+bytes = MIN(bytes, len);
+bytes = bytes >> hw->info.shift << hw->info.shift;
 wav->old_ticks = now;
-decr = MIN (live, samples);
-samples = decr;
-rpos = hw->rpos;
-while (samples) {
-int left_till_end_samples = hw->samples - rpos;
-int convert_samples = MIN (samples, left_till_end_samples);
-
-src = hw->mix_buf + rpos;
-dst = advance (wav->pcm_buf, rpos << hw->info.shift);
-
-hw->clip (dst, src, convert_samples);
-if (fwrite (dst, convert_samples << hw->info.shift, 1, wav->f) != 1) {
-dolog ("wav_run_out: fwrite of %d bytes failed\nReaons: %s\n",
-   convert_samples << hw->info.shift, strerror (errno));
-}
 
-rpos = (rpos + convert_samples) % hw->samples;
-samples -= convert_samples;
-wav->total_samples += convert_samples;
+if (bytes && fwrite(buf, bytes, 1, wav->f) != 1) {
+dolog("wav_write_out: fwrite of %" PRId64 " bytes failed\nReason: 
%s\n",
+  bytes, strerror(errno));
 }
 
-hw->rpos = rpos;
-return decr;
+wav->total_samples += bytes >> hw->info.shift;
+return bytes;
 }
 
 /* VICE code: Store number as little endian. */
@@ -137,13 +113,6 @@ static int wav_init_out(HWVoiceOut *hw, struct audsettings 
*as,
 audio_pcm_init_info (>info, _as);
 
 hw->samples = 1024;
-wav->pcm_buf = audio_calloc(__func__, hw->samples, 1 << hw->info.shift);
-if (!wav->pcm_buf) {
-dolog("Could not allocate buffer (%zu bytes)\n",
-  hw->samples << hw->info.shift);
-return -1;
-}
-
 le_store (hdr + 22, hw->info.nchannels, 2);
 le_store (hdr + 24, hw->info.freq, 4);
 le_store (hdr + 28, hw->info.freq << (bits16 + stereo), 4);
@@ -153,8 +122,6 @@ static int wav_init_out(HWVoiceOut *hw, struct audsettings 
*as,
 if (!wav->f) {
 dolog ("Failed to open wave file `%s'\nReason: %s\n",
wav_path, strerror(errno));
-g_free (wav->pcm_buf);
-wav->pcm_buf = NULL;
 return -1;
 }
 
@@ -208,9 +175,6 @@ static void wav_fini_out (HWVoiceOut *hw)
wav->f, strerror (errno));
 }
 wav->f = NULL;
-
-g_free (wav->pcm_buf);
-wav->pcm_buf = NULL;
 }
 
 static int wav_ctl_out (HWVoiceOut *hw, int cmd, ...)
@@ -234,7 +198,7 @@ static void wav_audio_fini (void *opaque)
 static struct audio_pcm_ops wav_pcm_ops = {
 .init_out = wav_init_out,
 .fini_out = wav_fini_out,
-.run_out  = wav_run_out,
+.write= wav_write_out,
 .ctl_out  = wav_ctl_out,
 };
 
-- 
2.23.0




[PATCH v4 18/24] audio: support more than two channels in volume setting

2019-09-19 Thread Kővágó, Zoltán
Signed-off-by: Kővágó, Zoltán 
---
 audio/audio.c  | 30 ++
 audio/audio.h  | 10 ++
 audio/audio_int.h  |  4 ++--
 audio/paaudio.c| 20 
 audio/spiceaudio.c | 14 --
 5 files changed, 54 insertions(+), 24 deletions(-)

diff --git a/audio/audio.c b/audio/audio.c
index d616a4af98..f1c145dfcd 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -1891,31 +1891,45 @@ void AUD_del_capture (CaptureVoiceOut *cap, void 
*cb_opaque)
 }
 
 void AUD_set_volume_out (SWVoiceOut *sw, int mute, uint8_t lvol, uint8_t rvol)
+{
+Volume vol = { .mute = mute, .channels = 2, .vol = { lvol, rvol } };
+audio_set_volume_out(sw, );
+}
+
+void audio_set_volume_out(SWVoiceOut *sw, Volume *vol)
 {
 if (sw) {
 HWVoiceOut *hw = sw->hw;
 
-sw->vol.mute = mute;
-sw->vol.l = nominal_volume.l * lvol / 255;
-sw->vol.r = nominal_volume.r * rvol / 255;
+sw->vol.mute = vol->mute;
+sw->vol.l = nominal_volume.l * vol->vol[0] / 255;
+sw->vol.r = nominal_volume.l * vol->vol[vol->channels > 1 ? 1 : 0] /
+255;
 
 if (hw->pcm_ops->volume_out) {
-hw->pcm_ops->volume_out(hw, >vol);
+hw->pcm_ops->volume_out(hw, vol);
 }
 }
 }
 
 void AUD_set_volume_in (SWVoiceIn *sw, int mute, uint8_t lvol, uint8_t rvol)
+{
+Volume vol = { .mute = mute, .channels = 2, .vol = { lvol, rvol } };
+audio_set_volume_in(sw, );
+}
+
+void audio_set_volume_in(SWVoiceIn *sw, Volume *vol)
 {
 if (sw) {
 HWVoiceIn *hw = sw->hw;
 
-sw->vol.mute = mute;
-sw->vol.l = nominal_volume.l * lvol / 255;
-sw->vol.r = nominal_volume.r * rvol / 255;
+sw->vol.mute = vol->mute;
+sw->vol.l = nominal_volume.l * vol->vol[0] / 255;
+sw->vol.r = nominal_volume.r * vol->vol[vol->channels > 1 ? 1 : 0] /
+255;
 
 if (hw->pcm_ops->volume_in) {
-hw->pcm_ops->volume_in(hw, >vol);
+hw->pcm_ops->volume_in(hw, vol);
 }
 }
 }
diff --git a/audio/audio.h b/audio/audio.h
index c74abb8c47..0db3c7dd5e 100644
--- a/audio/audio.h
+++ b/audio/audio.h
@@ -124,6 +124,16 @@ uint64_t AUD_get_elapsed_usec_out (SWVoiceOut *sw, 
QEMUAudioTimeStamp *ts);
 void AUD_set_volume_out (SWVoiceOut *sw, int mute, uint8_t lvol, uint8_t rvol);
 void AUD_set_volume_in (SWVoiceIn *sw, int mute, uint8_t lvol, uint8_t rvol);
 
+#define AUDIO_MAX_CHANNELS 16
+typedef struct Volume {
+bool mute;
+int channels;
+uint8_t vol[AUDIO_MAX_CHANNELS];
+} Volume;
+
+void audio_set_volume_out(SWVoiceOut *sw, Volume *vol);
+void audio_set_volume_in(SWVoiceIn *sw, Volume *vol);
+
 SWVoiceIn *AUD_open_in (
 QEMUSoundCard *card,
 SWVoiceIn *sw,
diff --git a/audio/audio_int.h b/audio/audio_int.h
index 22a703c13e..9176db249b 100644
--- a/audio/audio_int.h
+++ b/audio/audio_int.h
@@ -166,7 +166,7 @@ struct audio_pcm_ops {
  */
 size_t (*put_buffer_out)(HWVoiceOut *hw, void *buf, size_t size);
 void   (*enable_out)(HWVoiceOut *hw, bool enable);
-void   (*volume_out)(HWVoiceOut *hw, struct mixeng_volume *vol);
+void   (*volume_out)(HWVoiceOut *hw, Volume *vol);
 
 int(*init_in) (HWVoiceIn *hw, audsettings *as, void *drv_opaque);
 void   (*fini_in) (HWVoiceIn *hw);
@@ -174,7 +174,7 @@ struct audio_pcm_ops {
 void  *(*get_buffer_in)(HWVoiceIn *hw, size_t *size);
 void   (*put_buffer_in)(HWVoiceIn *hw, void *buf, size_t size);
 void   (*enable_in)(HWVoiceIn *hw, bool enable);
-void   (*volume_in)(HWVoiceIn *hw, struct mixeng_volume *vol);
+void   (*volume_in)(HWVoiceIn *hw, Volume *vol);
 };
 
 void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size);
diff --git a/audio/paaudio.c b/audio/paaudio.c
index 6ccdf31415..d195b1caa8 100644
--- a/audio/paaudio.c
+++ b/audio/paaudio.c
@@ -531,20 +531,22 @@ static void qpa_fini_in (HWVoiceIn *hw)
 }
 }
 
-static void qpa_volume_out(HWVoiceOut *hw, struct mixeng_volume *vol)
+static void qpa_volume_out(HWVoiceOut *hw, Volume *vol)
 {
 PAVoiceOut *pa = (PAVoiceOut *) hw;
 pa_operation *op;
 pa_cvolume v;
 PAConnection *c = pa->g->conn;
+int i;
 
 #ifdef PA_CHECK_VERSION/* macro is present in 0.9.16+ */
 pa_cvolume_init ();  /* function is present in 0.9.13+ */
 #endif
 
-v.channels = 2;
-v.values[0] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * vol->l) / UINT32_MAX;
-v.values[1] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * vol->r) / UINT32_MAX;
+v.channels = vol->channels;
+for (i = 0; i < vol->channels; ++i) {
+v.values[i] = ((PA_VOLUME_NORM - PA_VOLUME_MUTED) * vol->vol[i]) / 255;
+}
 
 pa_threaded_mainloop_lock(c->mainloop);
 
@@ -571,20 +573,22 @@ static void qpa_volume_out(HWVoiceOut *hw, struct 
mixeng_volume *vol)
 pa_threaded_mainloop_unlock(c->mainloop);
 }
 
-static void qpa_volume_in(HWVoiceIn *hw, struct mixeng_volume *vol)
+static void qpa_volume_in(HWVoiceIn 

[PATCH v4 11/24] audio: remove remains of the old backend api

2019-09-19 Thread Kővágó, Zoltán
Signed-off-by: Kővágó, Zoltán 
---
 audio/audio.c | 42 ++
 audio/audio_int.h |  7 ---
 2 files changed, 6 insertions(+), 43 deletions(-)

diff --git a/audio/audio.c b/audio/audio.c
index e29a1e15eb..435bcf20c1 100644
--- a/audio/audio.c
+++ b/audio/audio.c
@@ -541,7 +541,7 @@ static size_t audio_pcm_hw_find_min_in (HWVoiceIn *hw)
 return m;
 }
 
-size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw)
+static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw)
 {
 size_t live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw);
 if (audio_bug(__func__, live > hw->samples)) {
@@ -551,29 +551,7 @@ size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw)
 return live;
 }
 
-size_t audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf,
- size_t live, size_t pending)
-{
-size_t left = hw->samples - pending;
-size_t len = MIN (left, live);
-size_t clipped = 0;
-
-while (len) {
-struct st_sample *src = hw->mix_buf + hw->rpos;
-uint8_t *dst = advance (pcm_buf, hw->rpos << hw->info.shift);
-size_t samples_till_end_of_buf = hw->samples - hw->rpos;
-size_t samples_to_clip = MIN (len, samples_till_end_of_buf);
-
-hw->clip (dst, src, samples_to_clip);
-
-hw->rpos = (hw->rpos + samples_to_clip) % hw->samples;
-len -= samples_to_clip;
-clipped += samples_to_clip;
-}
-return clipped;
-}
-
-static void audio_pcm_hw_clip_out2(HWVoiceOut *hw, void *pcm_buf, size_t len)
+static void audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf, size_t len)
 {
 size_t clipped = 0;
 size_t pos = hw->rpos;
@@ -1083,7 +1061,7 @@ static size_t audio_pcm_hw_run_out(HWVoiceOut *hw, size_t 
live)
 }
 
 decr = MIN(size >> hw->info.shift, live);
-audio_pcm_hw_clip_out2(hw, buf, decr);
+audio_pcm_hw_clip_out(hw, buf, decr);
 proc = hw->pcm_ops->put_buffer_out(hw, buf, decr << hw->info.shift) >>
 hw->info.shift;
 
@@ -1146,11 +1124,7 @@ static void audio_run_out (AudioState *s)
 }
 
 prev_rpos = hw->rpos;
-if (hw->pcm_ops->run_out) {
-played = hw->pcm_ops->run_out(hw, live);
-} else {
-played = audio_pcm_hw_run_out(hw, live);
-}
+played = audio_pcm_hw_run_out(hw, live);
 replay_audio_out();
 if (audio_bug(__func__, hw->rpos >= hw->samples)) {
 dolog("hw->rpos=%zu hw->samples=%zu played=%zu\n",
@@ -1247,12 +1221,8 @@ static void audio_run_in (AudioState *s)
 size_t captured = 0, min;
 
 if (replay_mode != REPLAY_MODE_PLAY) {
-if (hw->pcm_ops->run_in) {
-captured = hw->pcm_ops->run_in(hw);
-} else {
-captured = audio_pcm_hw_run_in(
-hw, hw->samples - audio_pcm_hw_get_live_in(hw));
-}
+captured = audio_pcm_hw_run_in(
+hw, hw->samples - audio_pcm_hw_get_live_in(hw));
 }
 replay_audio_in(, hw->conv_buf, >wpos, hw->samples);
 
diff --git a/audio/audio_int.h b/audio/audio_int.h
index 8fb1ca8a8d..c76d7c39e8 100644
--- a/audio/audio_int.h
+++ b/audio/audio_int.h
@@ -153,7 +153,6 @@ struct audio_driver {
 struct audio_pcm_ops {
 int(*init_out)(HWVoiceOut *hw, audsettings *as, void *drv_opaque);
 void   (*fini_out)(HWVoiceOut *hw);
-size_t (*run_out)(HWVoiceOut *hw, size_t live);
 size_t (*write)   (HWVoiceOut *hw, void *buf, size_t size);
 /*
  * get a buffer that after later can be passed to put_buffer_out; optional
@@ -171,7 +170,6 @@ struct audio_pcm_ops {
 
 int(*init_in) (HWVoiceIn *hw, audsettings *as, void *drv_opaque);
 void   (*fini_in) (HWVoiceIn *hw);
-size_t (*run_in)(HWVoiceIn *hw);
 size_t (*read)(HWVoiceIn *hw, void *buf, size_t size);
 void  *(*get_buffer_in)(HWVoiceIn *hw, size_t *size);
 void   (*put_buffer_in)(HWVoiceIn *hw, void *buf, size_t size);
@@ -237,11 +235,6 @@ audio_driver *audio_driver_lookup(const char *name);
 void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as);
 void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int 
len);
 
-size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw);
-
-size_t audio_pcm_hw_clip_out(HWVoiceOut *hw, void *pcm_buf,
- size_t live, size_t pending);
-
 int audio_bug (const char *funcname, int cond);
 void *audio_calloc (const char *funcname, int nmemb, size_t size);
 
-- 
2.23.0




[PATCH v4 06/24] ossaudio: port to the new audio backend api

2019-09-19 Thread Kővágó, Zoltán
Signed-off-by: Kővágó, Zoltán 
---
 audio/ossaudio.c | 272 +--
 1 file changed, 96 insertions(+), 176 deletions(-)

diff --git a/audio/ossaudio.c b/audio/ossaudio.c
index 1696933688..2782512706 100644
--- a/audio/ossaudio.c
+++ b/audio/ossaudio.c
@@ -40,19 +40,15 @@
 
 typedef struct OSSVoiceOut {
 HWVoiceOut hw;
-void *pcm_buf;
 int fd;
-int wpos;
 int nfrags;
 int fragsize;
 int mmapped;
-int pending;
 Audiodev *dev;
 } OSSVoiceOut;
 
 typedef struct OSSVoiceIn {
 HWVoiceIn hw;
-void *pcm_buf;
 int fd;
 int nfrags;
 int fragsize;
@@ -371,98 +367,87 @@ static int oss_open(int in, struct oss_params *req, 
audsettings *as,
 return -1;
 }
 
-static void oss_write_pending (OSSVoiceOut *oss)
+static size_t oss_get_available_bytes(OSSVoiceOut *oss)
 {
-HWVoiceOut *hw = >hw;
+int err;
+struct count_info cntinfo;
+assert(oss->mmapped);
 
-if (oss->mmapped) {
-return;
+err = ioctl(oss->fd, SNDCTL_DSP_GETOPTR, );
+if (err < 0) {
+oss_logerr(errno, "SNDCTL_DSP_GETOPTR failed\n");
+return 0;
 }
 
-while (oss->pending) {
-int samples_written;
-ssize_t bytes_written;
-int samples_till_end = hw->samples - oss->wpos;
-int samples_to_write = MIN (oss->pending, samples_till_end);
-int bytes_to_write = samples_to_write << hw->info.shift;
-void *pcm = advance (oss->pcm_buf, oss->wpos << hw->info.shift);
+return audio_ring_dist(cntinfo.ptr, oss->hw.pos_emul, oss->hw.size_emul);
+}
 
-bytes_written = write (oss->fd, pcm, bytes_to_write);
-if (bytes_written < 0) {
-if (errno != EAGAIN) {
-oss_logerr (errno, "failed to write %d bytes\n",
-bytes_to_write);
-}
-break;
-}
+static void *oss_get_buffer_out(HWVoiceOut *hw, size_t *size)
+{
+OSSVoiceOut *oss = (OSSVoiceOut *) hw;
+if (oss->mmapped) {
+*size = MIN(oss_get_available_bytes(oss), hw->size_emul - 
hw->pos_emul);
+return hw->buf_emul + hw->pos_emul;
+} else {
+return audio_generic_get_buffer_out(hw, size);
+}
+}
 
-if (bytes_written & hw->info.align) {
-dolog ("misaligned write asked for %d, but got %zd\n",
-   bytes_to_write, bytes_written);
-return;
-}
+static size_t oss_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size)
+{
+OSSVoiceOut *oss = (OSSVoiceOut *) hw;
+if (oss->mmapped) {
+assert(buf == hw->buf_emul + hw->pos_emul && size < hw->size_emul);
 
-samples_written = bytes_written >> hw->info.shift;
-oss->pending -= samples_written;
-oss->wpos = (oss->wpos + samples_written) % hw->samples;
-if (bytes_written - bytes_to_write) {
-break;
-}
+hw->pos_emul = (hw->pos_emul + size) % hw->size_emul;
+return size;
+} else {
+return audio_generic_put_buffer_out(hw, buf, size);
 }
 }
 
-static size_t oss_run_out(HWVoiceOut *hw, size_t live)
+static size_t oss_write(HWVoiceOut *hw, void *buf, size_t len)
 {
 OSSVoiceOut *oss = (OSSVoiceOut *) hw;
-int err;
-size_t decr;
-struct audio_buf_info abinfo;
-struct count_info cntinfo;
-size_t bufsize;
-
-bufsize = hw->samples << hw->info.shift;
+size_t pos;
 
 if (oss->mmapped) {
-int bytes, pos;
+size_t total_len;
+len = MIN(len, oss_get_available_bytes(oss));
 
-err = ioctl (oss->fd, SNDCTL_DSP_GETOPTR, );
-if (err < 0) {
-oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n");
-return 0;
-}
+total_len = len;
+while (len) {
+size_t to_copy = MIN(len, hw->size_emul - hw->pos_emul);
+memcpy(hw->buf_emul + hw->pos_emul, buf, to_copy);
 
-pos = hw->rpos << hw->info.shift;
-bytes = audio_ring_dist (cntinfo.ptr, pos, bufsize);
-decr = MIN (bytes >> hw->info.shift, live);
-}
-else {
-err = ioctl (oss->fd, SNDCTL_DSP_GETOSPACE, );
-if (err < 0) {
-oss_logerr (errno, "SNDCTL_DSP_GETOPTR failed\n");
-return 0;
+hw->pos_emul = (hw->pos_emul + to_copy) % hw->pos_emul;
+buf += to_copy;
+len -= to_copy;
 }
+return total_len;
+}
 
-if (abinfo.bytes > bufsize) {
-trace_oss_invalid_available_size(abinfo.bytes, bufsize);
-abinfo.bytes = bufsize;
-}
+pos = 0;
+while (len) {
+ssize_t bytes_written;
+void *pcm = advance(buf, pos);
 
-if (abinfo.bytes < 0) {
-trace_oss_invalid_available_size(abinfo.bytes, bufsize);
-return 0;
+bytes_written = write(oss->fd, pcm, len);
+if (bytes_written < 0) {
+if (errno != EAGAIN) {
+oss_logerr(errno, 

[PATCH v4 05/24] noaudio: port to the new audio backend api

2019-09-19 Thread Kővágó, Zoltán
Signed-off-by: Kővágó, Zoltán 
---
 audio/noaudio.c | 43 +--
 1 file changed, 17 insertions(+), 26 deletions(-)

diff --git a/audio/noaudio.c b/audio/noaudio.c
index 0fb2629cf2..b054fd225b 100644
--- a/audio/noaudio.c
+++ b/audio/noaudio.c
@@ -41,10 +41,9 @@ typedef struct NoVoiceIn {
 int64_t old_ticks;
 } NoVoiceIn;
 
-static size_t no_run_out(HWVoiceOut *hw, size_t live)
+static size_t no_write(HWVoiceOut *hw, void *buf, size_t len)
 {
 NoVoiceOut *no = (NoVoiceOut *) hw;
-size_t decr, samples;
 int64_t now;
 int64_t ticks;
 int64_t bytes;
@@ -52,13 +51,9 @@ static size_t no_run_out(HWVoiceOut *hw, size_t live)
 now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 ticks = now - no->old_ticks;
 bytes = muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND);
-bytes = MIN(bytes, SIZE_MAX);
-samples = bytes >> hw->info.shift;
 
 no->old_ticks = now;
-decr = MIN (live, samples);
-hw->rpos = (hw->rpos + decr) % hw->samples;
-return decr;
+return MIN(len, bytes);
 }
 
 static int no_init_out(HWVoiceOut *hw, struct audsettings *as, void 
*drv_opaque)
@@ -92,25 +87,21 @@ static void no_fini_in (HWVoiceIn *hw)
 (void) hw;
 }
 
-static size_t no_run_in(HWVoiceIn *hw)
+static size_t no_read(HWVoiceIn *hw, void *buf, size_t size)
 {
+size_t to_clear;
 NoVoiceIn *no = (NoVoiceIn *) hw;
-size_t live = audio_pcm_hw_get_live_in(hw);
-size_t dead = hw->samples - live;
-size_t samples = 0;
-
-if (dead) {
-int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
-int64_t ticks = now - no->old_ticks;
-int64_t bytes =
-muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND);
-
-no->old_ticks = now;
-bytes = MIN (bytes, SIZE_MAX);
-samples = bytes >> hw->info.shift;
-samples = MIN (samples, dead);
-}
-return samples;
+
+int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+int64_t ticks = now - no->old_ticks;
+int64_t bytes =
+muldiv64(ticks, hw->info.bytes_per_second, NANOSECONDS_PER_SECOND);
+
+no->old_ticks = now;
+to_clear = MIN(bytes, size);
+
+audio_pcm_info_clear_buf(>info, buf, to_clear >> hw->info.shift);
+return to_clear;
 }
 
 static int no_ctl_in (HWVoiceIn *hw, int cmd, ...)
@@ -133,12 +124,12 @@ static void no_audio_fini (void *opaque)
 static struct audio_pcm_ops no_pcm_ops = {
 .init_out = no_init_out,
 .fini_out = no_fini_out,
-.run_out  = no_run_out,
+.write= no_write,
 .ctl_out  = no_ctl_out,
 
 .init_in  = no_init_in,
 .fini_in  = no_fini_in,
-.run_in   = no_run_in,
+.read = no_read,
 .ctl_in   = no_ctl_in
 };
 
-- 
2.23.0




[PATCH v4 04/24] dsoundaudio: port to the new audio backend api

2019-09-19 Thread Kővágó, Zoltán
Signed-off-by: Kővágó, Zoltán 
---
 audio/dsound_template.h |  47 ---
 audio/dsoundaudio.c | 305 +---
 2 files changed, 91 insertions(+), 261 deletions(-)

diff --git a/audio/dsound_template.h b/audio/dsound_template.h
index 8ece870c9e..9f10b688df 100644
--- a/audio/dsound_template.h
+++ b/audio/dsound_template.h
@@ -29,6 +29,8 @@
 #define BUFPTR LPDIRECTSOUNDCAPTUREBUFFER
 #define FIELD dsound_capture_buffer
 #define FIELD2 dsound_capture
+#define HWVOICE HWVoiceIn
+#define DSOUNDVOICE DSoundVoiceIn
 #else
 #define NAME "playback buffer"
 #define NAME2 "DirectSound"
@@ -37,6 +39,8 @@
 #define BUFPTR LPDIRECTSOUNDBUFFER
 #define FIELD dsound_buffer
 #define FIELD2 dsound
+#define HWVOICE HWVoiceOut
+#define DSOUNDVOICE DSoundVoiceOut
 #endif
 
 static int glue (dsound_unlock_, TYPE) (
@@ -72,8 +76,6 @@ static int glue (dsound_lock_, TYPE) (
 )
 {
 HRESULT hr;
-LPVOID p1 = NULL, p2 = NULL;
-DWORD blen1 = 0, blen2 = 0;
 DWORD flag;
 
 #ifdef DSBTYPE_IN
@@ -81,7 +83,7 @@ static int glue (dsound_lock_, TYPE) (
 #else
 flag = entire ? DSBLOCK_ENTIREBUFFER : 0;
 #endif
-hr = glue(IFACE, _Lock)(buf, pos, len, , , , , flag);
+hr = glue(IFACE, _Lock)(buf, pos, len, p1p, blen1p, p2p, blen2p, flag);
 
 if (FAILED (hr)) {
 #ifndef DSBTYPE_IN
@@ -96,34 +98,34 @@ static int glue (dsound_lock_, TYPE) (
 goto fail;
 }
 
-if ((p1 && (blen1 & info->align)) || (p2 && (blen2 & info->align))) {
-dolog ("DirectSound returned misaligned buffer %ld %ld\n",
-   blen1, blen2);
-glue (dsound_unlock_, TYPE) (buf, p1, p2, blen1, blen2);
+if ((p1p && *p1p && (*blen1p & info->align)) ||
+(p2p && *p2p && (*blen2p & info->align))) {
+dolog("DirectSound returned misaligned buffer %ld %ld\n",
+  *blen1p, *blen2p);
+glue(dsound_unlock_, TYPE)(buf, *p1p, p2p ? *p2p : NULL, *blen1p,
+   blen2p ? *blen2p : 0);
 goto fail;
 }
 
-if (!p1 && blen1) {
-dolog ("warning: !p1 && blen1=%ld\n", blen1);
-blen1 = 0;
+if (p1p && !*p1p && *blen1p) {
+dolog("warning: !p1 && blen1=%ld\n", *blen1p);
+*blen1p = 0;
 }
 
-if (!p2 && blen2) {
-dolog ("warning: !p2 && blen2=%ld\n", blen2);
-blen2 = 0;
+if (p2p && !*p2p && *blen2p) {
+dolog("warning: !p2 && blen2=%ld\n", *blen2p);
+*blen2p = 0;
 }
 
-*p1p = p1;
-*p2p = p2;
-*blen1p = blen1;
-*blen2p = blen2;
 return 0;
 
  fail:
 *p1p = NULL - 1;
-*p2p = NULL - 1;
 *blen1p = -1;
-*blen2p = -1;
+if (p2p) {
+*p2p = NULL - 1;
+*blen2p = -1;
+}
 return -1;
 }
 
@@ -242,7 +244,6 @@ static int dsound_init_out(HWVoiceOut *hw, struct 
audsettings *as,
 goto fail0;
 }
 
-ds->first_time = 1;
 obt_as.endianness = 0;
 audio_pcm_init_info (>info, _as);
 
@@ -252,15 +253,13 @@ static int dsound_init_out(HWVoiceOut *hw, struct 
audsettings *as,
 bc.dwBufferBytes, hw->info.align + 1
 );
 }
+hw->size_emul = bc.dwBufferBytes;
 hw->samples = bc.dwBufferBytes >> hw->info.shift;
 ds->s = s;
 
 #ifdef DEBUG_DSOUND
 dolog ("caps %ld, desc %ld\n",
bc.dwBufferBytes, bd.dwBufferBytes);
-
-dolog ("bufsize %d, freq %d, chan %d, fmt %d\n",
-   hw->bufsize, settings.freq, settings.nchannels, settings.fmt);
 #endif
 return 0;
 
@@ -276,3 +275,5 @@ static int dsound_init_out(HWVoiceOut *hw, struct 
audsettings *as,
 #undef BUFPTR
 #undef FIELD
 #undef FIELD2
+#undef HWVOICE
+#undef DSOUNDVOICE
diff --git a/audio/dsoundaudio.c b/audio/dsoundaudio.c
index 2fc118b795..9960247814 100644
--- a/audio/dsoundaudio.c
+++ b/audio/dsoundaudio.c
@@ -53,19 +53,11 @@ typedef struct {
 typedef struct {
 HWVoiceOut hw;
 LPDIRECTSOUNDBUFFER dsound_buffer;
-DWORD old_pos;
-int first_time;
 dsound *s;
-#ifdef DEBUG_DSOUND
-DWORD old_ppos;
-DWORD played;
-DWORD mixed;
-#endif
 } DSoundVoiceOut;
 
 typedef struct {
 HWVoiceIn hw;
-int first_time;
 LPDIRECTSOUNDCAPTUREBUFFER dsound_capture_buffer;
 dsound *s;
 } DSoundVoiceIn;
@@ -243,11 +235,6 @@ static void GCC_FMT_ATTR (3, 4) dsound_logerr2 (
 dsound_log_hresult (hr);
 }
 
-static uint64_t usecs_to_bytes(struct audio_pcm_info *info, uint32_t usecs)
-{
-return muldiv64(usecs, info->bytes_per_second, 100);
-}
-
 #ifdef DEBUG_DSOUND
 static void print_wave_format (WAVEFORMATEX *wfx)
 {
@@ -312,33 +299,6 @@ static int dsound_get_status_in 
(LPDIRECTSOUNDCAPTUREBUFFER dscb,
 return 0;
 }
 
-static void dsound_write_sample (HWVoiceOut *hw, uint8_t *dst, int dst_len)
-{
-int src_len1 = dst_len;
-int src_len2 = 0;
-int pos = hw->rpos + dst_len;
-struct st_sample *src1 = hw->mix_buf + hw->rpos;
-struct st_sample *src2 = NULL;
-
-if (pos > hw->samples) {
-src_len1 = hw->samples - 

[PATCH v4 03/24] coreaudio: port to the new audio backend api

2019-09-19 Thread Kővágó, Zoltán
Signed-off-by: Kővágó, Zoltán 
---
 audio/coreaudio.c | 130 --
 1 file changed, 69 insertions(+), 61 deletions(-)

diff --git a/audio/coreaudio.c b/audio/coreaudio.c
index d1be58b40a..5cde42f982 100644
--- a/audio/coreaudio.c
+++ b/audio/coreaudio.c
@@ -43,9 +43,6 @@ typedef struct coreaudioVoiceOut {
 UInt32 audioDevicePropertyBufferFrameSize;
 AudioStreamBasicDescription outputStreamBasicDescription;
 AudioDeviceIOProcID ioprocid;
-size_t live;
-size_t decr;
-size_t rpos;
 } coreaudioVoiceOut;
 
 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
@@ -397,31 +394,29 @@ static int coreaudio_unlock (coreaudioVoiceOut *core, 
const char *fn_name)
 return 0;
 }
 
-static size_t coreaudio_run_out(HWVoiceOut *hw, size_t live)
-{
-size_t decr;
-coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw;
-
-if (coreaudio_lock (core, "coreaudio_run_out")) {
-return 0;
+#define COREAUDIO_WRAPPER_FUNC(name, ret_type, args_decl, args) \
+static ret_type glue(coreaudio_, name)args_decl \
+{   \
+coreaudioVoiceOut *core = (coreaudioVoiceOut *) hw; \
+ret_type ret;   \
+\
+if (coreaudio_lock(core, "coreaudio_" #name)) { \
+return 0;   \
+}   \
+\
+ret = glue(audio_generic_, name)args;   \
+\
+coreaudio_unlock(core, "coreaudio_" #name); \
+return ret; \
 }
-
-if (core->decr > live) {
-ldebug ("core->decr %d live %d core->live %d\n",
-core->decr,
-live,
-core->live);
-}
-
-decr = MIN (core->decr, live);
-core->decr -= decr;
-
-core->live = live - decr;
-hw->rpos = core->rpos;
-
-coreaudio_unlock (core, "coreaudio_run_out");
-return decr;
-}
+COREAUDIO_WRAPPER_FUNC(get_buffer_out, void *, (HWVoiceOut *hw, size_t *size),
+   (hw, size))
+COREAUDIO_WRAPPER_FUNC(put_buffer_out_nowrite, size_t,
+   (HWVoiceOut *hw, void *buf, size_t size),
+   (hw, buf, size))
+COREAUDIO_WRAPPER_FUNC(write, size_t, (HWVoiceOut *hw, void *buf, size_t size),
+   (hw, buf, size))
+#undef COREAUDIO_WRAPPER_FUNC
 
 /* callback to feed audiooutput buffer */
 static OSStatus audioDeviceIOProc(
@@ -433,19 +428,11 @@ static OSStatus audioDeviceIOProc(
 const AudioTimeStamp* inOutputTime,
 void* hwptr)
 {
-UInt32 frame, frameCount;
-float *out = outOutputData->mBuffers[0].mData;
+UInt32 frameCount, pending_frames;
+void *out = outOutputData->mBuffers[0].mData;
 HWVoiceOut *hw = hwptr;
 coreaudioVoiceOut *core = (coreaudioVoiceOut *) hwptr;
-int rpos, live;
-struct st_sample *src;
-#ifndef FLOAT_MIXENG
-#ifdef RECIPROCAL
-const float scale = 1.f / UINT_MAX;
-#else
-const float scale = UINT_MAX;
-#endif
-#endif
+size_t len;
 
 if (coreaudio_lock (core, "audioDeviceIOProc")) {
 inInputTime = 0;
@@ -453,42 +440,51 @@ static OSStatus audioDeviceIOProc(
 }
 
 frameCount = core->audioDevicePropertyBufferFrameSize;
-live = core->live;
+pending_frames = hw->pending_emul >> hw->info.shift;
 
 /* if there are not enough samples, set signal and return */
-if (live < frameCount) {
+if (pending_frames < frameCount) {
 inInputTime = 0;
 coreaudio_unlock (core, "audioDeviceIOProc(empty)");
 return 0;
 }
 
-rpos = core->rpos;
-src = hw->mix_buf + rpos;
+len = frameCount << hw->info.shift;
+while (len) {
+size_t write_len;
+ssize_t start = ((ssize_t) hw->pos_emul) - hw->pending_emul;
+if (start < 0) {
+start += hw->size_emul;
+}
+assert(start >= 0 && start < hw->size_emul);
 
-/* fill buffer */
-for (frame = 0; frame < frameCount; frame++) {
-#ifdef FLOAT_MIXENG
-*out++ = src[frame].l; /* left channel */
-*out++ = src[frame].r; /* right channel */
-#else
-#ifdef RECIPROCAL
-*out++ = src[frame].l * scale; /* left channel */
-*out++ = src[frame].r * scale; /* right channel */
-#else
-*out++ = src[frame].l / scale; /* left channel */
-*out++ = src[frame].r / scale; /* right channel */
-#endif
-#endif
-}
+write_len = MIN(MIN(hw->pending_emul, len),
+hw->size_emul - start);
 
-rpos = (rpos + frameCount) % hw->samples;
-core->decr += frameCount;
-core->rpos = rpos;
+memcpy(out, 

  1   2   3   4   5   >