[Qemu-devel] [PATCH v2 03/28] s390x/tcg: MVCL: Detect destructive overlaps

2019-09-06 Thread David Hildenbrand
We'll have to zero-out unused bit positions, so amke sure to write the
addresses back.

Signed-off-by: David Hildenbrand 
---
 target/s390x/mem_helper.c | 19 ++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index 3152bdafe2..2361ed6d54 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -52,6 +52,19 @@ static inline bool psw_key_valid(CPUS390XState *env, uint8_t 
psw_key)
 return true;
 }
 
+static bool is_destructive_overlap(CPUS390XState *env, uint64_t dest,
+   uint64_t src, uint32_t len)
+{
+if (!len || src == dest) {
+return false;
+}
+/* Take care of wrapping at the end of address space. */
+if (unlikely(wrap_address(env, src + len - 1) < src)) {
+return dest > src || dest <= wrap_address(env, src + len - 1);
+}
+return dest > src && dest <= src + len - 1;
+}
+
 /* Reduce the length so that addr + len doesn't cross a page boundary.  */
 static inline uint32_t adj_len_to_page(uint32_t len, uint64_t addr)
 {
@@ -788,7 +801,11 @@ uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, 
uint32_t r2)
 uint8_t pad = env->regs[r2 + 1] >> 24;
 uint32_t cc;
 
-cc = do_mvcl(env, , , , , pad, 1, ra);
+if (is_destructive_overlap(env, dest, src, MIN(srclen, destlen))) {
+cc = 3;
+} else {
+cc = do_mvcl(env, , , , , pad, 1, ra);
+}
 
 env->regs[r1 + 1] = deposit64(env->regs[r1 + 1], 0, 24, destlen);
 env->regs[r2 + 1] = deposit64(env->regs[r2 + 1], 0, 24, srclen);
-- 
2.21.0




[Qemu-devel] [PATCH v2 09/28] s390x/tcg: MVCLU/MVCLE: Process max 4k bytes at a time

2019-09-06 Thread David Hildenbrand
... and indicate cc=3 in case there is work remaining. Keep unicode
padding simple.

While reworking, properly wrap the addresses.

Signed-off-by: David Hildenbrand 
---
 target/s390x/mem_helper.c | 54 ++-
 1 file changed, 31 insertions(+), 23 deletions(-)

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index 947a4277f0..6d8ebd18fa 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -769,8 +769,8 @@ static inline uint32_t do_mvcl(CPUS390XState *env,
uint64_t *src, uint64_t *srclen,
uint16_t pad, int wordsize, uintptr_t ra)
 {
-uint64_t len = MIN(*srclen, *destlen);
-uint32_t cc;
+int len = MIN(*destlen, TARGET_PAGE_SIZE);
+int i, cc;
 
 if (*destlen == *srclen) {
 cc = 0;
@@ -780,32 +780,40 @@ static inline uint32_t do_mvcl(CPUS390XState *env,
 cc = 2;
 }
 
-/* Copy the src array */
-fast_memmove(env, *dest, *src, len, ra);
-*src += len;
-*srclen -= len;
-*dest += len;
-*destlen -= len;
+if (!*destlen) {
+return cc;
+}
 
-/* Pad the remaining area */
-if (wordsize == 1) {
-fast_memset(env, *dest, pad, *destlen, ra);
-*dest += *destlen;
-*destlen = 0;
+/*
+ * Only perform one type of type of operation (move/pad) at a time.
+ * Process up to 4k bytes.
+ */
+if (*srclen) {
+/* Copy the src array */
+len = MIN(len, *srclen);
+*destlen -= len;
+*srclen -= len;
+fast_memmove(env, *dest, *src, len, ra);
+*src = wrap_address(env, *src + len);
+*dest = wrap_address(env, *dest + len);
+} else if (wordsize == 1) {
+/* Pad the remaining area */
+*destlen -= len;
+fast_memset(env, *dest, pad, len, ra);
+*dest = wrap_address(env, *dest + len);
 } else {
-/* If remaining length is odd, pad with odd byte first.  */
-if (*destlen & 1) {
-cpu_stb_data_ra(env, *dest, pad & 0xff, ra);
-*dest += 1;
-*destlen -= 1;
-}
-/* The remaining length is even, pad using words.  */
-for (; *destlen; *dest += 2, *destlen -= 2) {
-cpu_stw_data_ra(env, *dest, pad, ra);
+/* The remaining length selects the padding byte. */
+for (i = 0; i < len; (*destlen)--, i++) {
+if (*destlen & 1) {
+cpu_stb_data_ra(env, *dest, pad, ra);
+} else {
+cpu_stb_data_ra(env, *dest, pad >> 8, ra);
+}
+*dest = wrap_address(env, *dest + 1);
 }
 }
 
-return cc;
+return *destlen ? 3 : cc;
 }
 
 /* move long */
-- 
2.21.0




[Qemu-devel] [PATCH v2 10/28] s390x/tcg: MVCS/MVCP: Check for special operation exceptions

2019-09-06 Thread David Hildenbrand
Let's perform the documented checks.

Signed-off-by: David Hildenbrand 
---
 target/s390x/mem_helper.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index 6d8ebd18fa..041d01d63d 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -1961,12 +1961,18 @@ uint32_t HELPER(rrbe)(CPUS390XState *env, uint64_t r2)
 
 uint32_t HELPER(mvcs)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2)
 {
+const uint8_t psw_as = (env->psw.mask & PSW_MASK_ASC) >> PSW_SHIFT_ASC;
 uintptr_t ra = GETPC();
 int cc = 0, i;
 
 HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
__func__, l, a1, a2);
 
+if (!(env->psw.mask & PSW_MASK_DAT) || !(env->cregs[0] & CR0_SECONDARY) ||
+psw_as == AS_HOME || psw_as == AS_ACCREG) {
+s390_program_interrupt(env, PGM_SPECIAL_OP, ILEN_AUTO, ra);
+}
+
 if (l > 256) {
 /* max 256 */
 l = 256;
@@ -1984,12 +1990,18 @@ uint32_t HELPER(mvcs)(CPUS390XState *env, uint64_t l, 
uint64_t a1, uint64_t a2)
 
 uint32_t HELPER(mvcp)(CPUS390XState *env, uint64_t l, uint64_t a1, uint64_t a2)
 {
+const uint8_t psw_as = (env->psw.mask & PSW_MASK_ASC) >> PSW_SHIFT_ASC;
 uintptr_t ra = GETPC();
 int cc = 0, i;
 
 HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
__func__, l, a1, a2);
 
+if (!(env->psw.mask & PSW_MASK_DAT) || !(env->cregs[0] & CR0_SECONDARY) ||
+psw_as == AS_HOME || psw_as == AS_ACCREG) {
+s390_program_interrupt(env, PGM_SPECIAL_OP, ILEN_AUTO, ra);
+}
+
 if (l > 256) {
 /* max 256 */
 l = 256;
-- 
2.21.0




[Qemu-devel] [PATCH v2 02/28] s390x/tcg: MVCL: Zero out unused bits of address

2019-09-06 Thread David Hildenbrand
We have to zero out unused bits in 24 and 31-bit addressing mode.
Provide a new helper.

Signed-off-by: David Hildenbrand 
---
 target/s390x/mem_helper.c | 24 ++--
 1 file changed, 22 insertions(+), 2 deletions(-)

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index 39ee9b3175..3152bdafe2 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -469,6 +469,26 @@ static inline uint64_t get_address(CPUS390XState *env, int 
reg)
 return wrap_address(env, env->regs[reg]);
 }
 
+/*
+ * Store the address to the given register, zeroing out unused leftmost
+ * bits in bit positions 32-63 (24-bit and 31-bit mode only).
+ */
+static inline void set_address_zero(CPUS390XState *env, int reg,
+uint64_t address)
+{
+if (env->psw.mask & PSW_MASK_64) {
+env->regs[reg] = address;
+} else {
+if (!(env->psw.mask & PSW_MASK_32)) {
+address &= 0x00ff;
+env->regs[reg] = deposit64(env->regs[reg], 0, 32, address);
+} else {
+address &= 0x7fff;
+env->regs[reg] = deposit64(env->regs[reg], 0, 32, address);
+}
+}
+}
+
 static inline void set_address(CPUS390XState *env, int reg, uint64_t address)
 {
 if (env->psw.mask & PSW_MASK_64) {
@@ -772,8 +792,8 @@ uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, 
uint32_t r2)
 
 env->regs[r1 + 1] = deposit64(env->regs[r1 + 1], 0, 24, destlen);
 env->regs[r2 + 1] = deposit64(env->regs[r2 + 1], 0, 24, srclen);
-set_address(env, r1, dest);
-set_address(env, r2, src);
+set_address_zero(env, r1, dest);
+set_address_zero(env, r2, src);
 
 return cc;
 }
-- 
2.21.0




[Qemu-devel] Cross-posted : Odd QXL/KVM performance issue with a Windows 7 Guest

2019-09-06 Thread Brad Campbell

On 2/9/19 6:23 pm, Brad Campbell wrote:



Here is the holdup :

11725@1567416625.003504:qxl_ring_command_check 0 native
11725@1567416625.102653:qxl_io_write 0 native addr=0 (QXL_IO_NOTIFY_CMD) 
val=0 size=1 async=0


~100ms delay prior to each logged QXL_IO_NOTIFY_CMD on the AMD box which 
explains the performance difference. Now I just need to figure out if 
that lies in the guest, the guest QXL driver, QEMU or SPICE and why it 
exhibits on the AMD box and not the i7.


To get to this point, I recompiled the kernel on the i7 box with both 
AMD and Intel KVM modules. Once that was running I cloned the drive and 
put it in the AMD box, so the OS, software stack and all dependencies 
are identical.


Reacp :

I have a machine with a Windows 7 VM which is running on an i7-3770. 
This works perfectly.


Clone the disk and put it in a new(ish) AMD Ryzen 1500x machine and the 
display output using qxl/spice is now limited to ~5-7fps.


I originally cloned the entire machine to keep the software versions 
identical.


To simplify debugging and reproduction I'm now using :
- An identical SPICE version to that on the i7.
- A fresh 64 bit Windows 7 VM.
- The D2D benchmark from Crystalmark 2004R7.

The machine is booted with :

qemu -enable-kvm \
 -m 8192\
 -rtc base=localtime\
 -vga qxl\
 -device qxl\
 -global qxl-vga.guestdebug=3\
 -global qxl-vga.cmdlog=1\
 -global qxl-vga.vram_size=65536\
 -global qxl.vram_size=65536\
 -global qxl-vga.ram_size=65536\
 -global qxl.ram_size=65536\
 -net nic,model=virtio\
 -net tap,ifname=tap0,script=/etc/qemu-ifup,vhost=on\
 -usbdevice tablet\
 -spice port=5930,disable-ticketing\
 -device virtio-serial\
 -chardev spicevmc,id=vdagent,name=vdagent\
 -device virtserialport,chardev=vdagent,name=com.redhat.spice.0\
 -smp 3,maxcpus=3,cores=3,threads=1,sockets=1\
 -cpu qemu64,hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time \
 -drive 
file=/server/VM/Cadbox.raw,if=virtio,aio=threads,format=raw,cache=unsafe 
-boot c \
 -drive 
file=/server/VM/Cadbox_swap.raw,if=virtio,aio=threads,format=raw,cache=unsafe 
\



The D2D benchmark runs through a series of Sprites (stars) and it just 
shuffles them around the screen.


With KVM enabled I get :

Sprite10 - 8.66fps
Sprite   100 - 8.47fps
Sprite   500 - 8.45fps
Sprite  1000 - 8.18fps
Sprite  5000 - 7.64fps
Sprite 1 - 7.26fps

With the identical system, with KVM disabled I get :

Sprite10 - 28.97fps
Sprite   100 - 27.24fps
Sprite   500 - 23.85fps
Sprite  1000 - 22.00fps
Sprite  5000 - 11.11fps
Sprite 1 -  4.50fps

On the i7 with the same software version and kvm enabled  :

Sprite10 - 88.58fps
Sprite   100 - 88.35fps
Sprite   500 - 85.64fps
Sprite  1000 - 83.33fps
Sprite  5000 - 58.08fps
Sprite 1 - 45.29fps


cpuinfo from the host :
processor   : 7
vendor_id   : AuthenticAMD
cpu family  : 23
model   : 1
model name  : AMD Ryzen 5 1500X Quad-Core Processor
stepping: 1
microcode   : 0x8001138
cpu MHz : 2877.596
cache size  : 512 KB
physical id : 0
siblings: 8
core id : 5
cpu cores   : 4
apicid  : 11
initial apicid  : 11
fpu : yes
fpu_exception   : yes
cpuid level : 13
wp  : yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov 
pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt 
pdpe1gb rdtscp lm constant_tsc rep_good nopl nonstop_tsc cpuid 
extd_apicid aperfmperf pni pclmulqdq monitor ssse3 fma cx16 sse4_1 
sse4_2 movbe popcnt aes xsave avx f16c rdrand lahf_lm cmp_legacy svm 
extapic cr8_legacy abm sse4a misalignsse 3dnowprefetch osvw skinit wdt 
tce topoext perfctr_core perfctr_nb bpext perfctr_llc mwaitx cpb 
hw_pstate sme ssbd sev ibpb vmmcall fsgsbase bmi1 avx2 smep bmi2 rdseed 
adx smap clflushopt sha_ni xsaveopt xsavec xgetbv1 xsaves clzero irperf 
xsaveerptr arat npt lbrv svm_lock nrip_save tsc_scale vmcb_clean 
flushbyasid decodeassists pausefilter pfthreshold avic v_vmsave_vmload 
vgif overflow_recov succor smca

bugs: sysret_ss_attrs null_seg spectre_v1 spectre_v2 
spec_store_bypass
bogomips: 6985.80
TLB size: 2560 4K pages
clflush size: 64
cache_alignment : 64
address sizes   : 43 bits physical, 48 bits virtual
power management: ts ttp tm hwpstate eff_freq_ro [13] [14]

qemu configured with : 
PKG_CONFIG_PATH=/usr/local/libvirt/lib/pkgconfig:/usr/local/libvirt/share/pkgconfig/ 
./configure --target-list=x86_64-softmmu --disable-gtk && make -j6

test:~# uname -a

Linux test 5.2.9 #42 SMP Tue Aug 20 16:41:13 AWST 2019 x86_64 GNU/Linux

test:~# zgrep KVM /proc/config.gz
CONFIG_HAVE_KVM=y
CONFIG_HAVE_KVM_IRQCHIP=y
CONFIG_HAVE_KVM_IRQFD=y
CONFIG_HAVE_KVM_IRQ_ROUTING=y
CONFIG_HAVE_KVM_EVENTFD=y
CONFIG_KVM_MMIO=y
CONFIG_KVM_ASYNC_PF=y
CONFIG_HAVE_KVM_MSI=y
CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y
CONFIG_KVM_VFIO=y
CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y
CONFIG_KVM_COMPAT=y
CONFIG_HAVE_KVM_IRQ_BYPASS=y
CONFIG_KVM=m
# CONFIG_KVM_INTEL is not set

Re: [Qemu-devel] [PATCH] Check correct register for clock source

2019-09-06 Thread Cédric Le Goater
On 06/09/2019 03:16, Joel Stanley wrote:
> On Fri, 6 Sep 2019 at 01:10, Amithash Prasad  wrote:
>>
>> 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 
> 
> Reviewed-by: Joel Stanley 
> 
> Thanks for the patch!

yes. I have pushed it on the aspeed-4.2 branch but it can go independently
as there are no conflicts. I changed the title slightly to reflect the
area being changed.

On the clock topic, we should consider looking at the "Clock framework API" 
from  Damien Hedde :

http://patchwork.ozlabs.org/cover/1157671/

Thanks,

C. 

> 
>> ---
>>  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 9b93213417..f710036535 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
>>




[Qemu-devel] [PATCH v18 1/6] hw/arm/virt: Introduce RAS platform version and RAS machine option

2019-09-06 Thread Xiang Zheng
From: Dongjiu Geng 

Support RAS Virtualization feature since version 4.2, disable it by
default in the old versions. Also add a machine option which allows user
to enable it explicitly.

Signed-off-by: Dongjiu Geng 
Signed-off-by: Xiang Zheng 
---
 hw/arm/virt.c | 33 +
 include/hw/arm/virt.h |  2 ++
 2 files changed, 35 insertions(+)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index d74538b021..e0451433c8 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -1783,6 +1783,20 @@ static void virt_set_its(Object *obj, bool value, Error 
**errp)
 vms->its = value;
 }
 
+static bool virt_get_ras(Object *obj, Error **errp)
+{
+VirtMachineState *vms = VIRT_MACHINE(obj);
+
+return vms->ras;
+}
+
+static void virt_set_ras(Object *obj, bool value, Error **errp)
+{
+VirtMachineState *vms = VIRT_MACHINE(obj);
+
+vms->ras = value;
+}
+
 static char *virt_get_gic_version(Object *obj, Error **errp)
 {
 VirtMachineState *vms = VIRT_MACHINE(obj);
@@ -2026,6 +2040,19 @@ static void virt_instance_init(Object *obj)
 "Valid values are none and smmuv3",
 NULL);
 
+if (vmc->no_ras) {
+vms->ras = false;
+} else {
+/* Default disallows RAS instantiation */
+vms->ras = false;
+object_property_add_bool(obj, "ras", virt_get_ras,
+ virt_set_ras, NULL);
+object_property_set_description(obj, "ras",
+"Set on/off to enable/disable "
+"RAS instantiation",
+NULL);
+}
+
 vms->irqmap = a15irqmap;
 
 virt_flash_create(vms);
@@ -2058,8 +2085,14 @@ DEFINE_VIRT_MACHINE_AS_LATEST(4, 2)
 
 static void virt_machine_4_1_options(MachineClass *mc)
 {
+VirtMachineClass *vmc = VIRT_MACHINE_CLASS(OBJECT_CLASS(mc));
+
 virt_machine_4_2_options(mc);
 compat_props_add(mc->compat_props, hw_compat_4_1, hw_compat_4_1_len);
+/* Disable memory recovery feature for 4.1 as RAS support was
+ * introduced with 4.2.
+ */
+vmc->no_ras = true;
 }
 DEFINE_VIRT_MACHINE(4, 1)
 
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
index a72094204e..04ab42ca42 100644
--- a/include/hw/arm/virt.h
+++ b/include/hw/arm/virt.h
@@ -103,6 +103,7 @@ typedef struct {
 bool disallow_affinity_adjustment;
 bool no_its;
 bool no_pmu;
+bool no_ras;
 bool claim_edge_triggered_timers;
 bool smbios_old_sys_ver;
 bool no_highmem_ecam;
@@ -119,6 +120,7 @@ typedef struct {
 bool highmem_ecam;
 bool its;
 bool virt;
+bool ras;
 int32_t gic_version;
 VirtIOMMUType iommu;
 struct arm_boot_info bootinfo;
-- 
2.19.1





[Qemu-devel] [PATCH v18 5/6] target-arm: kvm64: inject synchronous External Abort

2019-09-06 Thread Xiang Zheng
From: Dongjiu Geng 

Introduce kvm_inject_arm_sea() function in which we will setup the type
of exception and the syndrome information in order to inject a virtual
synchronous external abort. When switching to guest, it will jump to the
synchronous external abort vector table entry.

The ESR_ELx.DFSC is set to synchronous external abort(0x10), and
ESR_ELx.FnV is set to not valid(0x1), which will tell guest that FAR is
not valid and hold an UNKNOWN value. These values will be set to KVM
register structures through KVM_SET_ONE_REG IOCTL.

Signed-off-by: Dongjiu Geng 
Signed-off-by: Xiang Zheng 
---
 target/arm/helper.c |  2 +-
 target/arm/internals.h  |  5 +++--
 target/arm/kvm64.c  | 34 ++
 target/arm/tlb_helper.c |  2 +-
 4 files changed, 39 insertions(+), 4 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 507026c915..a13baeb085 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -3005,7 +3005,7 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t 
value,
  * Report exception with ESR indicating a fault due to a
  * translation table walk for a cache maintenance instruction.
  */
-syn = syn_data_abort_no_iss(current_el == target_el,
+syn = syn_data_abort_no_iss(current_el == target_el, 0,
 fi.ea, 1, fi.s1ptw, 1, fsc);
 env->exception.vaddress = value;
 env->exception.fsr = fsr;
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 232d963875..98cde702ad 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -451,13 +451,14 @@ static inline uint32_t syn_insn_abort(int same_el, int 
ea, int s1ptw, int fsc)
 | ARM_EL_IL | (ea << 9) | (s1ptw << 7) | fsc;
 }
 
-static inline uint32_t syn_data_abort_no_iss(int same_el,
+static inline uint32_t syn_data_abort_no_iss(int same_el, int fnv,
  int ea, int cm, int s1ptw,
  int wnr, int fsc)
 {
 return (EC_DATAABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
| ARM_EL_IL
-   | (ea << 9) | (cm << 8) | (s1ptw << 7) | (wnr << 6) | fsc;
+   | (fnv << 10) | (ea << 9) | (cm << 8) | (s1ptw << 7)
+   | (wnr << 6) | fsc;
 }
 
 static inline uint32_t syn_data_abort_with_iss(int same_el,
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index 28f6db57d5..bf6edaa3f6 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -710,6 +710,40 @@ int kvm_arm_cpreg_level(uint64_t regidx)
 return KVM_PUT_RUNTIME_STATE;
 }
 
+/* Inject synchronous external abort */
+static void kvm_inject_arm_sea(CPUState *c)
+{
+ARMCPU *cpu = ARM_CPU(c);
+CPUARMState *env = >env;
+CPUClass *cc = CPU_GET_CLASS(c);
+uint32_t esr;
+bool same_el;
+
+/**
+ * Set the exception type to synchronous data abort
+ * and the target exception Level to EL1.
+ */
+c->exception_index = EXCP_DATA_ABORT;
+env->exception.target_el = 1;
+
+/*
+ * Set the DFSC to synchronous external abort and set FnV to not valid,
+ * this will tell guest the FAR_ELx is UNKNOWN for this abort.
+ */
+
+/* This exception comes from lower or current exception level. */
+same_el = arm_current_el(env) == env->exception.target_el;
+esr = syn_data_abort_no_iss(same_el, 1, 0, 0, 0, 0, 0x10);
+
+env->exception.syndrome = esr;
+
+/**
+ * The vcpu thread already hold BQL, so no need hold again when
+ * calling do_interrupt
+ */
+cc->do_interrupt(c);
+}
+
 #define AARCH64_CORE_REG(x)   (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
  KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
 
diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c
index 5feb312941..499672ebbc 100644
--- a/target/arm/tlb_helper.c
+++ b/target/arm/tlb_helper.c
@@ -33,7 +33,7 @@ static inline uint32_t merge_syn_data_abort(uint32_t 
template_syn,
  * ISV field.
  */
 if (!(template_syn & ARM_EL_ISV) || target_el != 2 || s1ptw) {
-syn = syn_data_abort_no_iss(same_el,
+syn = syn_data_abort_no_iss(same_el, 0,
 ea, 0, s1ptw, is_write, fsc);
 } else {
 /*
-- 
2.19.1





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

2019-09-06 Thread Xiang Zheng
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

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
+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 Error Status Data Block table contains N Error Status Data Block
+entries, the size for each entry is 4096(0x1000) bytes. The total size
+for "etc/hardware_errors" fw_cfg blob is (N * 8 * 2 + N * 4096) bytes.
+N is the kinds of hardware error sources.
+
+(4) QEMU generates the ACPI linker/loader script for the firmware, the
+firmware pre-allocates memory for "etc/acpi/tables", "etc/hardware_errors"
+and copies blobs content there.
+
+(5) QEMU generates N ADD_POINTER commands, which patch address in the
+"error_status_address" fields of the HEST table with a pointer to the
+corresponding "address registers" in "etc/hardware_errors" blob.
+
+(6) QEMU generates N ADD_POINTER commands, which patch address in the
+"read_ack_register" fields of the HEST table with 

[Qemu-devel] [PATCH v2 07/28] s390x/tcg: MVPG: Check for specification exceptions

2019-09-06 Thread David Hildenbrand
Perform the checks documented in the PoP.

Signed-off-by: David Hildenbrand 
---
 target/s390x/mem_helper.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index 3c23c403cd..a763482ae0 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -673,6 +673,13 @@ uint64_t HELPER(clst)(CPUS390XState *env, uint64_t c, 
uint64_t s1, uint64_t s2)
 /* move page */
 uint32_t HELPER(mvpg)(CPUS390XState *env, uint64_t r0, uint64_t r1, uint64_t 
r2)
 {
+const bool f = extract64(r0, 11, 1);
+const bool s = extract64(r0, 10, 1);
+
+if ((f && s) || extract64(r0, 12, 4)) {
+s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, GETPC());
+}
+
 /* ??? missing r0 handling, which includes access keys, but more
importantly optional suppression of the exception!  */
 fast_memmove(env, r1, r2, TARGET_PAGE_SIZE, GETPC());
-- 
2.21.0




[Qemu-devel] [PATCH v2 12/28] s390x/tcg: MVST: Check for specification exceptions

2019-09-06 Thread David Hildenbrand
Bit position 32-55 of general register 0 must be zero.

Signed-off-by: David Hildenbrand 
---
 target/s390x/mem_helper.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index de5e69b500..afcd452a00 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -699,6 +699,9 @@ uint64_t HELPER(mvst)(CPUS390XState *env, uint64_t c, 
uint64_t d, uint64_t s)
 uintptr_t ra = GETPC();
 uint32_t len;
 
+if (c & 0xff00ull) {
+s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, ra);
+}
 c = c & 0xff;
 d = wrap_address(env, d);
 s = wrap_address(env, s);
-- 
2.21.0




[Qemu-devel] [PATCH v2 11/28] s390x/tcg: MVCS/MVCP: Properly wrap the length

2019-09-06 Thread David Hildenbrand
... and don't perform any move in case the length is zero.

Signed-off-by: David Hildenbrand 
---
 target/s390x/mem_helper.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index 041d01d63d..de5e69b500 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -1973,10 +1973,13 @@ uint32_t HELPER(mvcs)(CPUS390XState *env, uint64_t l, 
uint64_t a1, uint64_t a2)
 s390_program_interrupt(env, PGM_SPECIAL_OP, ILEN_AUTO, ra);
 }
 
+l = wrap_length(env, l);
 if (l > 256) {
 /* max 256 */
 l = 256;
 cc = 3;
+} else if (!l) {
+return cc;
 }
 
 /* XXX replace w/ memcpy */
@@ -2002,10 +2005,13 @@ uint32_t HELPER(mvcp)(CPUS390XState *env, uint64_t l, 
uint64_t a1, uint64_t a2)
 s390_program_interrupt(env, PGM_SPECIAL_OP, ILEN_AUTO, ra);
 }
 
+l = wrap_length(env, l);
 if (l > 256) {
 /* max 256 */
 l = 256;
 cc = 3;
+} else if (!l) {
+return cc;
 }
 
 /* XXX replace w/ memcpy */
-- 
2.21.0




[Qemu-devel] [PATCH v2 16/28] s390x/tcg: Fault-safe memmove

2019-09-06 Thread David Hildenbrand
Replace fast_memmove() variants by access_memmove() variants, that
first try to probe access to all affected pages (maximum is two pages).

In MVCOS, simply always call access_memmove_as() and drop the TODO
about LAP. LAP is already handled in the MMU.

Get rid of adj_len_to_page(), which is now unused.

Signed-off-by: David Hildenbrand 
---
 target/s390x/mem_helper.c | 204 +-
 1 file changed, 115 insertions(+), 89 deletions(-)

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index 8d654b24e7..db678ddf47 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -65,17 +65,6 @@ static bool is_destructive_overlap(CPUS390XState *env, 
uint64_t dest,
 return dest > src && dest <= src + len - 1;
 }
 
-/* Reduce the length so that addr + len doesn't cross a page boundary.  */
-static inline uint32_t adj_len_to_page(uint32_t len, uint64_t addr)
-{
-#ifndef CONFIG_USER_ONLY
-if ((addr & ~TARGET_PAGE_MASK) + len - 1 >= TARGET_PAGE_SIZE) {
-return -(addr | TARGET_PAGE_MASK);
-}
-#endif
-return len;
-}
-
 /* Trigger a SPECIFICATION exception if an address or a length is not
naturally aligned.  */
 static inline void check_alignment(CPUS390XState *env, uint64_t v,
@@ -129,6 +118,7 @@ typedef struct S390Access {
 char *haddr2;
 uint16_t size1;
 uint16_t size2;
+int mmu_idx;
 } S390Access;
 
 static S390Access access_prepare_idx(CPUS390XState *env, vaddr vaddr, int size,
@@ -138,6 +128,7 @@ static S390Access access_prepare_idx(CPUS390XState *env, 
vaddr vaddr, int size,
 S390Access access = {
 .vaddr1 = vaddr,
 .size1 = MIN(size, -(vaddr | TARGET_PAGE_MASK)),
+.mmu_idx = mmu_idx,
 };
 
 g_assert(size > 0 && size <= 4096);
@@ -195,42 +186,112 @@ static void access_memset(CPUS390XState *env, vaddr 
vaddr, uint8_t byte,
 access_memset_idx(env, vaddr, byte, size, mmu_idx, ra);
 }
 
-#ifndef CONFIG_USER_ONLY
-static void fast_memmove_idx(CPUS390XState *env, uint64_t dest, uint64_t src,
- uint32_t len, int dest_idx, int src_idx,
- uintptr_t ra)
-{
-TCGMemOpIdx oi_dest = make_memop_idx(MO_UB, dest_idx);
-TCGMemOpIdx oi_src = make_memop_idx(MO_UB, src_idx);
-uint32_t len_adj;
-void *src_p;
-void *dest_p;
-uint8_t x;
-
-while (len > 0) {
-src = wrap_address(env, src);
-dest = wrap_address(env, dest);
-src_p = tlb_vaddr_to_host(env, src, MMU_DATA_LOAD, src_idx);
-dest_p = tlb_vaddr_to_host(env, dest, MMU_DATA_STORE, dest_idx);
-
-if (src_p && dest_p) {
-/* Access to both whole pages granted.  */
-len_adj = adj_len_to_page(adj_len_to_page(len, src), dest);
-memmove(dest_p, src_p, len_adj);
+static uint8_t access_get_byte(CPUS390XState *env, const S390Access *access,
+   int offset, uintptr_t ra)
+{
+#ifdef CONFIG_USER_ONLY
+if (offset < access->size1) {
+return ldub_p(access->haddr1 + offset);
+} else {
+return ldub_p(access->haddr2 + offset - access->size1);
+}
+#else
+TCGMemOpIdx oi = make_memop_idx(MO_UB, access->mmu_idx);
+
+if (offset < access->size1) {
+if (likely(access->haddr1)) {
+return ldub_p(access->haddr1 + offset);
+}
+return helper_ret_ldub_mmu(env, access->vaddr1 + offset, oi, ra);
+}
+if (access->haddr2) {
+return ldub_p(access->haddr2 + offset - access->size1);
+}
+return helper_ret_ldub_mmu(env, access->vaddr2 + offset - access->size1, 
oi,
+   ra);
+#endif
+}
+
+static void access_set_byte(CPUS390XState *env, const S390Access *access,
+int offset, uint8_t byte, uintptr_t ra)
+{
+#ifdef CONFIG_USER_ONLY
+if (offset < access->size1) {
+stb_p(access->haddr1 + offset, byte);
+} else {
+stb_p(access->haddr2 + offset - access->size1, byte);
+}
+#else
+TCGMemOpIdx oi = make_memop_idx(MO_UB, access->mmu_idx);
+
+if (offset < access->size1) {
+if (likely(access->haddr1)) {
+stb_p(access->haddr1 + offset, byte);
 } else {
-/* We failed to get access to one or both whole pages. The next
-   read or write access will likely fill the QEMU TLB for the
-   next iteration.  */
-len_adj = 1;
-x = helper_ret_ldub_mmu(env, src, oi_src, ra);
-helper_ret_stb_mmu(env, dest, x, oi_dest, ra);
+helper_ret_stb_mmu(env, access->vaddr1 + offset, byte, oi, ra);
+}
+} else {
+if (likely(access->haddr2)) {
+stb_p(access->haddr2 + offset - access->size1, byte);
+} else {
+helper_ret_stb_mmu(env, access->vaddr2 + offset - access->size1,
+   byte, oi, ra);
+}
+}
+#endif
+}
+
+/*
+ * Move data with the same semantics as 

[Qemu-devel] [PATCH v2 22/28] s390x/tcg: NC: Fault-safe handling

2019-09-06 Thread David Hildenbrand
We can process a maximum of 256 bytes, crossing two pages.

Signed-off-by: David Hildenbrand 
---
 target/s390x/mem_helper.c | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index 88ff6c21ed..49b4879859 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -329,17 +329,25 @@ static void access_memmove_as(CPUS390XState *env, 
uint64_t dest, uint64_t src,
 static uint32_t do_helper_nc(CPUS390XState *env, uint32_t l, uint64_t dest,
  uint64_t src, uintptr_t ra)
 {
+S390Access srca1, srca2, desta;
 uint32_t i;
 uint8_t c = 0;
 
 HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
__func__, l, dest, src);
 
-for (i = 0; i <= l; i++) {
-uint8_t x = cpu_ldub_data_ra(env, src + i, ra);
-x &= cpu_ldub_data_ra(env, dest + i, ra);
+/* NC always processes one more byte than specified - maximum is 256 */
+l++;
+
+srca1 = access_prepare(env, src, l, MMU_DATA_LOAD, ra);
+srca2 = access_prepare(env, dest, l, MMU_DATA_LOAD, ra);
+desta = access_prepare(env, dest, l, MMU_DATA_STORE, ra);
+for (i = 0; i < l; i++) {
+const uint8_t x = access_get_byte(env, , i, ra) &
+  access_get_byte(env, , i, ra);
+
 c |= x;
-cpu_stb_data_ra(env, dest + i, x, ra);
+access_set_byte(env, , i, x, ra);
 }
 return c != 0;
 }
-- 
2.21.0




Re: [Qemu-devel] [PATCH v6 1/4] block: Add zoned device model property

2019-09-06 Thread Stefano Garzarella
On Wed, Sep 04, 2019 at 05:00:57PM -0400, Dmitry Fomichev wrote:
> This commit adds Zoned Device Model (as defined in T10 ZBC and
> T13 ZAC standards) as a block driver property, along with some
> useful access functions.
> 
> A new backend driver permission, BLK_PERM_SUPPORT_HM_ZONED, is also
> introduced. Only the drivers having this permission will be allowed
> to open host managed zoned block devices.
> 
> No code is added yet to initialize or check the value of this new
> property, therefore this commit doesn't change any functionality.
> 
> Signed-off-by: Dmitry Fomichev 
> ---
>  block.c   | 15 +++
>  include/block/block.h | 19 ++-
>  include/block/block_int.h |  3 +++
>  3 files changed, 36 insertions(+), 1 deletion(-)
> 
> diff --git a/block.c b/block.c
> index 874a29a983..69f565e1e9 100644
> --- a/block.c
> +++ b/block.c
> @@ -4679,6 +4679,21 @@ void bdrv_get_geometry(BlockDriverState *bs, uint64_t 
> *nb_sectors_ptr)
>  *nb_sectors_ptr = nb_sectors < 0 ? 0 : nb_sectors;
>  }
>  
> +BdrvZonedModel bdrv_get_zoned_model(BlockDriverState *bs)
> +{
> +return bs->bl.zoned_model;
> +}
> +
> +bool bdrv_is_hm_zoned(BlockDriverState *bs)
> +{
> +/*
> + * Host Aware zone devices are supposed to be able to work
> + * just like regular block devices. Thus, we only consider
> + * Host Managed devices to be zoned here.
> + */
> +return bdrv_get_zoned_model(bs) == BDRV_ZONED_MODEL_HM;
> +}
> +
>  bool bdrv_is_sg(BlockDriverState *bs)
>  {
>  return bs->sg;
> diff --git a/include/block/block.h b/include/block/block.h
> index 124ad40809..28d065ed80 100644
> --- a/include/block/block.h
> +++ b/include/block/block.h
> @@ -271,18 +271,33 @@ enum {
>   */
>  BLK_PERM_GRAPH_MOD  = 0x10,
>  
> +/**
> + * This permission is required to open host-managed zoned block devices.
> + */
> +BLK_PERM_SUPPORT_HM_ZONED   = 0x20,
> +
>  BLK_PERM_ALL= 0x1f,

Should we update BLK_PERM_ALL to 0x3f?

Thanks,
Stefano




[Qemu-devel] [PATCH v2 15/28] s390x/tcg: Fault-safe memset

2019-09-06 Thread David Hildenbrand
Replace fast_memset() by access_memset(), that first tries to probe
access to all affected pages (maximum is two). We'll use the same
mechanism for other types of accesses soon.

Only in very rare cases (especially TLB_NOTDIRTY), we'll have to
fallback to ld/st helpers.

Signed-off-by: David Hildenbrand 
---
 target/s390x/mem_helper.c | 99 ++-
 1 file changed, 77 insertions(+), 22 deletions(-)

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index 8dd58b3ab1..8d654b24e7 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -117,27 +117,82 @@ static inline void cpu_stsize_data_ra(CPUS390XState *env, 
uint64_t addr,
 }
 }
 
-static void fast_memset(CPUS390XState *env, uint64_t dest, uint8_t byte,
-uint32_t l, uintptr_t ra)
-{
-int mmu_idx = cpu_mmu_index(env, false);
+/*
+ * An access covers at most 4096 bytes and therefore at most two pages. If
+ * we can't access the host page directly, we'll have to do I/O access
+ * via ld/st helpers.
+ */
+typedef struct S390Access {
+target_ulong vaddr1;
+target_ulong vaddr2;
+char *haddr1;
+char *haddr2;
+uint16_t size1;
+uint16_t size2;
+} S390Access;
+
+static S390Access access_prepare_idx(CPUS390XState *env, vaddr vaddr, int size,
+ MMUAccessType access_type, int mmu_idx,
+ uintptr_t ra)
+{
+S390Access access = {
+.vaddr1 = vaddr,
+.size1 = MIN(size, -(vaddr | TARGET_PAGE_MASK)),
+};
+
+g_assert(size > 0 && size <= 4096);
+access.haddr1 = probe_access(env, access.vaddr1, access.size1, access_type,
+ mmu_idx, ra);
+
+if (unlikely(access.size1 != size)) {
+/* The access crosses page boundaries. */
+access.vaddr2 = wrap_address(env, vaddr + access.size1);
+access.size2 = size - access.size1;
+access.haddr2 = probe_access(env, access.vaddr2, access.size2,
+ access_type, mmu_idx, ra);
+}
+return access;
+}
+
+static void access_memset_idx(CPUS390XState *env, vaddr vaddr, uint8_t byte,
+  int size, int mmu_idx, uintptr_t ra)
+{
+S390Access desta = access_prepare_idx(env, vaddr, size, MMU_DATA_STORE,
+  mmu_idx, ra);
+#ifdef CONFIG_USER_ONLY
+g_assert(desta.haddr1 && (desta.haddr2 || !desta.size2));
+memset(desta.haddr1, byte, desta.size1);
+memset(desta.haddr2, byte, desta.size2);
+#else
+TCGMemOpIdx oi = make_memop_idx(MO_UB, mmu_idx);
+int i;
 
-while (l > 0) {
-void *p = tlb_vaddr_to_host(env, dest, MMU_DATA_STORE, mmu_idx);
-if (p) {
-/* Access to the whole page in write mode granted.  */
-uint32_t l_adj = adj_len_to_page(l, dest);
-memset(p, byte, l_adj);
-dest += l_adj;
-l -= l_adj;
-} else {
-/* We failed to get access to the whole page. The next write
-   access will likely fill the QEMU TLB for the next iteration.  */
-cpu_stb_data_ra(env, dest, byte, ra);
-dest++;
-l--;
+if (likely(desta.haddr1)) {
+memset(desta.haddr1, byte, desta.size1);
+} else {
+for (i = 0; i < desta.size1; i++) {
+helper_ret_stb_mmu(env, desta.vaddr1 + i, byte, oi, ra);
+}
+}
+if (likely(!desta.size2)) {
+return;
+}
+if (likely(desta.haddr2)) {
+memset(desta.haddr2, byte, desta.size2);
+} else {
+for (i = 0; i < desta.size2; i++) {
+helper_ret_stb_mmu(env, desta.vaddr2 + i, byte, oi, ra);
 }
 }
+#endif
+}
+
+static void access_memset(CPUS390XState *env, vaddr vaddr, uint8_t byte,
+  int size, uintptr_t ra)
+{
+int mmu_idx = cpu_mmu_index(env, false);
+
+access_memset_idx(env, vaddr, byte, size, mmu_idx, ra);
 }
 
 #ifndef CONFIG_USER_ONLY
@@ -267,7 +322,7 @@ static uint32_t do_helper_xc(CPUS390XState *env, uint32_t 
l, uint64_t dest,
 
 /* xor with itself is the same as memset(0) */
 if (src == dest) {
-fast_memset(env, dest, 0, l + 1, ra);
+access_memset(env, dest, 0, l + 1, ra);
 return 0;
 }
 
@@ -329,7 +384,7 @@ static uint32_t do_helper_mvc(CPUS390XState *env, uint32_t 
l, uint64_t dest,
  * behave like memmove().
  */
 if (dest == src + 1) {
-fast_memset(env, dest, cpu_ldub_data_ra(env, src, ra), l, ra);
+access_memset(env, dest, cpu_ldub_data_ra(env, src, ra), l, ra);
 } else if (!is_destructive_overlap(env, dest, src, l)) {
 fast_memmove(env, dest, src, l, ra);
 } else {
@@ -798,7 +853,7 @@ static inline uint32_t do_mvcl(CPUS390XState *env,
 } else if (wordsize == 1) {
 /* Pad the remaining area */
 *destlen -= len;
-fast_memset(env, *dest, pad, len, 

[Qemu-devel] [PATCH v18 0/6] Add ARMv8 RAS virtualization support in QEMU

2019-09-06 Thread Xiang Zheng
In the ARMv8 platform, the CPU error types are synchronous external abort(SEA)
and SError Interrupt (SEI). If exception happens in guest, sometimes it's better
for guest to perform the recovery, because host does not know the detailed
information of guest. For example, if an exception happens in a user-space
application within guest, host does not know which application encounters
errors.

For the ARMv8 SEA/SEI, KVM or host kernel delivers SIGBUS to notify userspace.
After user space gets the notification, it will record the CPER into guest GHES
buffer and inject an exception or IRQ into guest.

In the current implementation, if the type of SIGBUS is BUS_MCEERR_AR, we will
treat it as a synchronous exception, and notify guest with ARMv8 SEA
notification type after recording CPER into guest.

This series of patches are based on Qemu 4.1, which include two parts:
1. Generate APEI/GHES table.
2. Handle the SIGBUS signal, record the CPER in runtime and fill it into guest
   memory, then notify guest according to the type of SIGBUS.

The whole solution was suggested by James(james.mo...@arm.com); The solution of
APEI section was suggested by Laszlo(ler...@redhat.com).
Show some discussions in [1].

This series of patches have already been tested on ARM64 platform with RAS
feature enabled:
Show the APEI part verification result in [2].
Show the BUS_MCEERR_AR SIGBUS handling verification result in [3].

---

Since Dongjiu is too busy to do this work, I will finish the rest work on behalf
of him.

---
Change since v17:
1. Improve some commit messages and comments.
2. Fix some code-style problems.
3. Add a *ras* machine option.
4. Move HEST/GHES related structures and macros into "hw/acpi/acpi_ghes.*".
5. Move HWPoison page functions into "include/sysemu/kvm_int.h".
6. Fix some bugs.
7. Improve the design document.

Change since v16:
1. check whether ACPI table is enabled when handling the memory error in the 
SIGBUS handler.

Change since v15:
1. Add a doc-comment in the proper format for 'include/exec/ram_addr.h'
2. Remove write_part_cpustate_to_list() because there is another bug fix patch
   has been merged "arm: Allow system registers for KVM guests to be changed by 
QEMU code"
3. Add some comments for kvm_inject_arm_sea() in 'target/arm/kvm64.c'
4. Compare the arm_current_el() return value to 0,1,2,3, not to PSTATE_MODE_* 
constants.
5. Change the RAS support wasn't introduced before 4.1 QEMU version.
6. Move the no_ras flag  patch to begin in this series

Change since v14:
1. Remove the BUS_MCEERR_AO handling logic because this asynchronous signal was 
masked by main thread
2. Address some Igor Mammedov's comments(ACPI part)
   1) change the comments for the enum AcpiHestNotifyType definition and remove 
ditto in patch 1
   2) change some patch commit messages and separate "APEI GHES table 
generation" patch to more patches.
3. Address some peter's comments(arm64 Synchronous External Abort injection)
   1) change some code notes
   2) using arm_current_el() for current EL
   2) use the helper functions for those (syn_data_abort_*).

Change since v13:
1. Move the patches that set guest ESR and inject virtual SError out of this 
series
2. Clean and optimize the APEI part patches
3. Update the commit messages and add some comments for the code

Change since v12:
1. Address Paolo's comments to move HWPoisonPage definition to 
accel/kvm/kvm-all.c
2. Only call kvm_cpu_synchronize_state() when get the BUS_MCEERR_AR signal
3. Only add and enable GPIO-Signal and ARMv8 SEA two hardware error sources
4. Address Michael's comments to not sync SPDX from Linux kernel header file

Change since v11:
Address James's comments(james.mo...@arm.com)
1. Check whether KVM has the capability to to set ESR instead of detecting host 
CPU RAS capability
2. For SIGBUS_MCEERR_AR SIGBUS, use Synchronous-External-Abort(SEA) 
notification type
   for SIGBUS_MCEERR_AO SIGBUS, use GPIO-Signal notification


Address Shannon's comments(for ACPI part):
1. Unify hest_ghes.c and hest_ghes.h license declaration
2. Remove unnecessary including "qmp-commands.h" in hest_ghes.c
3. Unconditionally add guest APEI table based on James's 
comments(james.mo...@arm.com)
4. Add a option to virt machine for migration compatibility. On new virt 
machine it's on
   by default while off for old ones, we enabled it since 2.12
5. Refer to the ACPI spec version which introduces Hardware Error Notification 
first time
6. Add ACPI_HEST_NOTIFY_RESERVED notification type

Address Igor's comments(for ACPI part):
1. Add doc patch first which will describe how it's supposed to work between 
QEMU/firmware/guest
   OS with expected flows.
2. Move APEI diagrams into doc/spec patch
3. Remove redundant g_malloc in ghes_record_cper()
4. Use build_append_int_noprefix() API to compose whole error status block and 
whole APEI table,
   and try to get rid of most structures in patch 1, as they will be left 
unused after that
5. Reuse something like 

[Qemu-devel] [PATCH v4 0/6] Add the STM32F405 and Netduino Plus 2 machine

2019-09-06 Thread Alistair Francis


Now that the Arm-M4 CPU has been added to QEMU we can add the Netduino
Plus 2 machine. This is very similar to the STM32F205 and Netduino 2 SoC
and machine.

v4:
 - Rebase on master
v3:
 - Remove custom reset handler
 - Add init-entry and init-sp properties
 - Rebase on master (including Kconfig changes)
v2:
 - Reorder patchset
 - Return the kernel entry point instead of using a pointer
 - Address Peter's comments


Alistair Francis (6):
  armv7m: Allow entry information to be returned
  target/arm: Allow setting M mode entry and sp
  hw/misc: Add the STM32F4xx Sysconfig device
  hw/misc: Add the STM32F4xx EXTI device
  hw/arm: Add the STM32F4xx SoC
  hw/arm: Add the Netduino Plus 2

 MAINTAINERS|  14 ++
 default-configs/arm-softmmu.mak|   1 +
 hw/arm/Kconfig |  16 ++
 hw/arm/Makefile.objs   |   2 +
 hw/arm/armv7m.c|   4 +-
 hw/arm/netduinoplus2.c |  58 ++
 hw/arm/stm32f405_soc.c | 301 +
 hw/misc/Kconfig|   6 +
 hw/misc/Makefile.objs  |   2 +
 hw/misc/stm32f4xx_exti.c   | 187 ++
 hw/misc/stm32f4xx_syscfg.c | 168 
 hw/misc/trace-events   |  11 ++
 include/hw/arm/boot.h  |   4 +-
 include/hw/arm/stm32f405_soc.h |  73 +++
 include/hw/misc/stm32f4xx_exti.h   |  60 ++
 include/hw/misc/stm32f4xx_syscfg.h |  61 ++
 target/arm/cpu.c   |  52 -
 target/arm/cpu.h   |   3 +
 18 files changed, 1016 insertions(+), 7 deletions(-)
 create mode 100644 hw/arm/netduinoplus2.c
 create mode 100644 hw/arm/stm32f405_soc.c
 create mode 100644 hw/misc/stm32f4xx_exti.c
 create mode 100644 hw/misc/stm32f4xx_syscfg.c
 create mode 100644 include/hw/arm/stm32f405_soc.h
 create mode 100644 include/hw/misc/stm32f4xx_exti.h
 create mode 100644 include/hw/misc/stm32f4xx_syscfg.h

-- 
2.22.0




[Qemu-devel] [PATCH v4 1/6] armv7m: Allow entry information to be returned

2019-09-06 Thread Alistair Francis
Allow the kernel's entry point information to be returned when loading a
kernel.

Signed-off-by: Alistair Francis 
Reviewed-by: Philippe Mathieu-Daudé 
Tested-by: Philippe Mathieu-Daudé 
---
 hw/arm/armv7m.c   | 4 +++-
 include/hw/arm/boot.h | 4 +++-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index 7a3c48f002..40755d77db 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -306,7 +306,7 @@ static void armv7m_reset(void *opaque)
 cpu_reset(CPU(cpu));
 }
 
-void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
+uint64_t armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int 
mem_size)
 {
 int image_size;
 uint64_t entry;
@@ -353,6 +353,8 @@ void armv7m_load_kernel(ARMCPU *cpu, const char 
*kernel_filename, int mem_size)
  * board must call this function!
  */
 qemu_register_reset(armv7m_reset, cpu);
+
+return entry;
 }
 
 static Property bitband_properties[] = {
diff --git a/include/hw/arm/boot.h b/include/hw/arm/boot.h
index 7f4d0ca7cd..e35b83c0d2 100644
--- a/include/hw/arm/boot.h
+++ b/include/hw/arm/boot.h
@@ -27,11 +27,13 @@ typedef enum {
  * @kernel_filename: file to load
  * @mem_size: mem_size: maximum image size to load
  *
+ * returns: location of the kernel's entry point
+ *
  * Load the guest image for an ARMv7M system. This must be called by
  * any ARMv7M board. (This is necessary to ensure that the CPU resets
  * correctly on system reset, as well as for kernel loading.)
  */
-void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int 
mem_size);
+uint64_t armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int 
mem_size);
 
 /* arm_boot.c */
 struct arm_boot_info {
-- 
2.22.0




[Qemu-devel] [PATCH v4 4/6] hw/misc: Add the STM32F4xx EXTI device

2019-09-06 Thread Alistair Francis
Signed-off-by: Alistair Francis 
Reviewed-by: Peter Maydell 
---
 hw/arm/Kconfig   |   1 +
 hw/misc/Kconfig  |   3 +
 hw/misc/Makefile.objs|   1 +
 hw/misc/stm32f4xx_exti.c | 187 +++
 hw/misc/trace-events |   5 +
 include/hw/misc/stm32f4xx_exti.h |  60 ++
 6 files changed, 257 insertions(+)
 create mode 100644 hw/misc/stm32f4xx_exti.c
 create mode 100644 include/hw/misc/stm32f4xx_exti.h

diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 9019c9fa50..68a3b27685 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -311,6 +311,7 @@ config STM32F405_SOC
 bool
 select ARM_V7M
 select STM32F4XX_SYSCFG
+select STM32F4XX_EXTI
 
 config XLNX_ZYNQMP_ARM
 bool
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index b9097ab2e0..fa56e5d375 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -85,6 +85,9 @@ config STM32F2XX_SYSCFG
 config STM32F4XX_SYSCFG
 bool
 
+config STM32F4XX_EXTI
+bool
+
 config MIPS_ITU
 bool
 
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 51da9abf2a..fdceae0c51 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -58,6 +58,7 @@ obj-$(CONFIG_ZYNQ) += zynq_slcr.o
 obj-$(CONFIG_ZYNQ) += zynq-xadc.o
 obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o
 obj-$(CONFIG_STM32F4XX_SYSCFG) += stm32f4xx_syscfg.o
+obj-$(CONFIG_STM32F4XX_EXTI) += stm32f4xx_exti.o
 obj-$(CONFIG_MIPS_CPS) += mips_cmgcr.o
 obj-$(CONFIG_MIPS_CPS) += mips_cpc.o
 obj-$(CONFIG_MIPS_ITU) += mips_itu.o
diff --git a/hw/misc/stm32f4xx_exti.c b/hw/misc/stm32f4xx_exti.c
new file mode 100644
index 00..04ac82ae26
--- /dev/null
+++ b/hw/misc/stm32f4xx_exti.c
@@ -0,0 +1,187 @@
+/*
+ * STM32F4XX EXTI
+ *
+ * Copyright (c) 2014 Alistair Francis 
+ *
+ * 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 "qemu/log.h"
+#include "trace.h"
+#include "hw/misc/stm32f4xx_exti.h"
+
+static void stm32f4xx_exti_reset(DeviceState *dev)
+{
+STM32F4xxExtiState *s = STM32F4XX_EXTI(dev);
+
+s->exti_imr = 0x;
+s->exti_emr = 0x;
+s->exti_rtsr = 0x;
+s->exti_ftsr = 0x;
+s->exti_swier = 0x;
+s->exti_pr = 0x;
+}
+
+static void stm32f4xx_exti_set_irq(void *opaque, int irq, int level)
+{
+STM32F4xxExtiState *s = opaque;
+
+if (!((1 << irq) & s->exti_imr)) {
+/* Interrupt is masked */
+return;
+}
+
+trace_stm32f4xx_exti_set_irq(irq, level);
+
+if (((1 << irq) & s->exti_rtsr) && level) {
+/* Rising Edge */
+qemu_irq_pulse(s->irq[irq]);
+s->exti_pr |= 1 << irq;
+}
+
+if (((1 << irq) & s->exti_ftsr) && !level) {
+/* Falling Edge */
+qemu_irq_pulse(s->irq[irq]);
+s->exti_pr |= 1 << irq;
+}
+}
+
+static uint64_t stm32f4xx_exti_read(void *opaque, hwaddr addr,
+ unsigned int size)
+{
+STM32F4xxExtiState *s = opaque;
+
+trace_stm32f4xx_exti_read(addr);
+
+switch (addr) {
+case EXTI_IMR:
+return s->exti_imr;
+case EXTI_EMR:
+return s->exti_emr;
+case EXTI_RTSR:
+return s->exti_rtsr;
+case EXTI_FTSR:
+return s->exti_ftsr;
+case EXTI_SWIER:
+return s->exti_swier;
+case EXTI_PR:
+return s->exti_pr;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+  "STM32F4XX_exti_read: Bad offset %x\n", (int)addr);
+return 0;
+}
+return 0;
+}
+
+static void stm32f4xx_exti_write(void *opaque, hwaddr addr,
+   uint64_t val64, unsigned int size)
+{
+STM32F4xxExtiState *s = opaque;
+uint32_t value = (uint32_t) val64;
+
+trace_stm32f4xx_exti_write(addr, value);
+
+switch (addr) {
+case EXTI_IMR:
+s->exti_imr = value;
+return;
+case EXTI_EMR:
+s->exti_emr = value;
+return;

[Qemu-devel] [PATCH v4 3/6] hw/misc: Add the STM32F4xx Sysconfig device

2019-09-06 Thread Alistair Francis
Signed-off-by: Alistair Francis 
Reviewed-by: Peter Maydell 
---
 default-configs/arm-softmmu.mak|   1 +
 hw/arm/Kconfig |   9 ++
 hw/misc/Kconfig|   3 +
 hw/misc/Makefile.objs  |   1 +
 hw/misc/stm32f4xx_syscfg.c | 168 +
 hw/misc/trace-events   |   6 ++
 include/hw/misc/stm32f4xx_syscfg.h |  61 +++
 7 files changed, 249 insertions(+)
 create mode 100644 hw/misc/stm32f4xx_syscfg.c
 create mode 100644 include/hw/misc/stm32f4xx_syscfg.h

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 1f2e0e7fde..645e6201bb 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -30,6 +30,7 @@ CONFIG_Z2=y
 CONFIG_COLLIE=y
 CONFIG_ASPEED_SOC=y
 CONFIG_NETDUINO2=y
+CONFIG_NETDUINOPLUS2=y
 CONFIG_MPS2=y
 CONFIG_RASPI=y
 CONFIG_DIGIC=y
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 76a2a6bcbf..9019c9fa50 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -97,6 +97,10 @@ config NETDUINO2
 bool
 select STM32F205_SOC
 
+config NETDUINOPLUS2
+bool
+select STM32F405_SOC
+
 config NSERIES
 bool
 select OMAP
@@ -303,6 +307,11 @@ config STM32F205_SOC
 select STM32F2XX_ADC
 select STM32F2XX_SPI
 
+config STM32F405_SOC
+bool
+select ARM_V7M
+select STM32F4XX_SYSCFG
+
 config XLNX_ZYNQMP_ARM
 bool
 select AHCI
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 51754bb47c..b9097ab2e0 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -82,6 +82,9 @@ config IMX
 config STM32F2XX_SYSCFG
 bool
 
+config STM32F4XX_SYSCFG
+bool
+
 config MIPS_ITU
 bool
 
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index e4aad707fb..51da9abf2a 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -57,6 +57,7 @@ obj-$(CONFIG_SLAVIO) += slavio_misc.o
 obj-$(CONFIG_ZYNQ) += zynq_slcr.o
 obj-$(CONFIG_ZYNQ) += zynq-xadc.o
 obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o
+obj-$(CONFIG_STM32F4XX_SYSCFG) += stm32f4xx_syscfg.o
 obj-$(CONFIG_MIPS_CPS) += mips_cmgcr.o
 obj-$(CONFIG_MIPS_CPS) += mips_cpc.o
 obj-$(CONFIG_MIPS_ITU) += mips_itu.o
diff --git a/hw/misc/stm32f4xx_syscfg.c b/hw/misc/stm32f4xx_syscfg.c
new file mode 100644
index 00..b34fb34885
--- /dev/null
+++ b/hw/misc/stm32f4xx_syscfg.c
@@ -0,0 +1,168 @@
+/*
+ * STM32F4xx SYSCFG
+ *
+ * Copyright (c) 2014 Alistair Francis 
+ *
+ * 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 "qemu/log.h"
+#include "trace.h"
+#include "hw/misc/stm32f4xx_syscfg.h"
+
+static void stm32f4xx_syscfg_reset(DeviceState *dev)
+{
+STM32F4xxSyscfgState *s = STM32F4XX_SYSCFG(dev);
+
+s->syscfg_memrmp = 0x;
+s->syscfg_pmc = 0x;
+s->syscfg_exticr[0] = 0x;
+s->syscfg_exticr[1] = 0x;
+s->syscfg_exticr[2] = 0x;
+s->syscfg_exticr[3] = 0x;
+s->syscfg_cmpcr = 0x;
+}
+
+static void stm32f4xx_syscfg_set_irq(void *opaque, int irq, int level)
+{
+STM32F4xxSyscfgState *s = opaque;
+int icrreg = irq / 4;
+int startbit = (irq & 3) * 4;
+uint8_t config = config = irq / 16;
+
+trace_stm32f4xx_syscfg_set_irq(irq / 16, irq % 16, level);
+
+g_assert(icrreg < SYSCFG_NUM_EXTICR);
+
+if (extract32(s->syscfg_exticr[icrreg], startbit, 4) == config) {
+   qemu_set_irq(s->gpio_out[irq], level);
+   trace_stm32f4xx_pulse_exti(irq);
+   }
+}
+
+static uint64_t stm32f4xx_syscfg_read(void *opaque, hwaddr addr,
+ unsigned int size)
+{
+STM32F4xxSyscfgState *s = opaque;
+
+trace_stm32f4xx_syscfg_read(addr);
+
+switch (addr) {
+case SYSCFG_MEMRMP:
+return s->syscfg_memrmp;
+case SYSCFG_PMC:
+return s->syscfg_pmc;
+case SYSCFG_EXTICR1...SYSCFG_EXTICR4:
+return s->syscfg_exticr[addr / 4 - SYSCFG_EXTICR1 / 4];
+case 

[Qemu-devel] [PATCH v4 2/6] target/arm: Allow setting M mode entry and sp

2019-09-06 Thread Alistair Francis
Add M mode initial entry PC and SP properties.

Signed-off-by: Alistair Francis 
---
 target/arm/cpu.c | 52 +++-
 target/arm/cpu.h |  3 +++
 2 files changed, 50 insertions(+), 5 deletions(-)

diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index 2399c14471..315aa503f6 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -311,6 +311,9 @@ static void arm_cpu_reset(CPUState *s)
  */
 initial_msp = ldl_p(rom);
 initial_pc = ldl_p(rom + 4);
+} else if (cpu->init_sp || cpu->init_entry) {
+initial_msp = cpu->init_sp;
+initial_pc = cpu->init_entry;
 } else {
 /* Address zero not covered by a ROM blob, or the ROM blob
  * is in non-modifiable memory and this is a second reset after
@@ -1055,6 +1058,38 @@ static void arm_set_init_svtor(Object *obj, Visitor *v, 
const char *name,
 visit_type_uint32(v, name, >init_svtor, errp);
 }
 
+static void arm_get_init_sp(Object *obj, Visitor *v, const char *name,
+void *opaque, Error **errp)
+{
+ARMCPU *cpu = ARM_CPU(obj);
+
+visit_type_uint32(v, name, >init_sp, errp);
+}
+
+static void arm_set_init_sp(Object *obj, Visitor *v, const char *name,
+void *opaque, Error **errp)
+{
+ARMCPU *cpu = ARM_CPU(obj);
+
+visit_type_uint32(v, name, >init_sp, errp);
+}
+
+static void arm_get_init_entry(Object *obj, Visitor *v, const char *name,
+void *opaque, Error **errp)
+{
+ARMCPU *cpu = ARM_CPU(obj);
+
+visit_type_uint32(v, name, >init_entry, errp);
+}
+
+static void arm_set_init_entry(Object *obj, Visitor *v, const char *name,
+void *opaque, Error **errp)
+{
+ARMCPU *cpu = ARM_CPU(obj);
+
+visit_type_uint32(v, name, >init_entry, errp);
+}
+
 void arm_cpu_post_init(Object *obj)
 {
 ARMCPU *cpu = ARM_CPU(obj);
@@ -1155,19 +1190,26 @@ void arm_cpu_post_init(Object *obj)
 }
 }
 
+/*
+ * M profile: initial value of the SP, entry and Secure VTOR.
+ * We can't just use a simple DEFINE_PROP_UINT32 for this because we want
+ * to permit the property to be set after realize.
+ */
 if (arm_feature(>env, ARM_FEATURE_M_SECURITY)) {
 object_property_add_link(obj, "idau", TYPE_IDAU_INTERFACE, >idau,
  qdev_prop_allow_set_link_before_realize,
  OBJ_PROP_LINK_STRONG,
  _abort);
-/*
- * M profile: initial value of the Secure VTOR. We can't just use
- * a simple DEFINE_PROP_UINT32 for this because we want to permit
- * the property to be set after realize.
- */
 object_property_add(obj, "init-svtor", "uint32",
 arm_get_init_svtor, arm_set_init_svtor,
 NULL, NULL, _abort);
+} else if (arm_feature(>env, ARM_FEATURE_M)) {
+object_property_add(obj, "init-sp", "uint32",
+arm_get_init_sp, arm_set_init_sp,
+NULL, NULL, _abort);
+object_property_add(obj, "init-entry", "uint32",
+arm_get_init_entry, arm_set_init_entry,
+NULL, NULL, _abort);
 }
 
 qdev_property_add_static(DEVICE(obj), _cpu_cfgend_property,
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 297ad5e47a..4856d4c36b 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -805,6 +805,9 @@ struct ARMCPU {
  */
 uint32_t psci_conduit;
 
+/* For M, initial value of the entry and SP */
+uint32_t init_sp, init_entry;
+
 /* For v8M, initial value of the Secure VTOR */
 uint32_t init_svtor;
 
-- 
2.22.0




[Qemu-devel] [PATCH v4 5/6] hw/arm: Add the STM32F4xx SoC

2019-09-06 Thread Alistair Francis
Signed-off-by: Alistair Francis 
Reviewed-by: Peter Maydell 
---
 MAINTAINERS|   8 +
 hw/arm/Kconfig |   3 +
 hw/arm/Makefile.objs   |   1 +
 hw/arm/stm32f405_soc.c | 301 +
 include/hw/arm/stm32f405_soc.h |  73 
 5 files changed, 386 insertions(+)
 create mode 100644 hw/arm/stm32f405_soc.c
 create mode 100644 include/hw/arm/stm32f405_soc.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 65d8a7c2d2..4aea8cb3fa 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -814,6 +814,14 @@ F: hw/adc/*
 F: hw/ssi/stm32f2xx_spi.c
 F: include/hw/*/stm32*.h
 
+STM32F405
+M: Alistair Francis 
+M: Peter Maydell 
+S: Maintained
+F: hw/arm/stm32f405_soc.c
+F: hw/misc/stm32f4xx_syscfg.c
+F: hw/misc/stm32f4xx_exti.c
+
 Netduino 2
 M: Alistair Francis 
 M: Peter Maydell 
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 68a3b27685..46a4f052e9 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -313,6 +313,9 @@ config STM32F405_SOC
 select STM32F4XX_SYSCFG
 select STM32F4XX_EXTI
 
+config STM32F405_SOC
+bool
+
 config XLNX_ZYNQMP_ARM
 bool
 select AHCI
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 43ce8d5b19..0191c22c4f 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -36,6 +36,7 @@ obj-$(CONFIG_STRONGARM) += strongarm.o
 obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
 obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
 obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
+obj-$(CONFIG_STM32F405_SOC) += stm32f405_soc.o
 obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o
 obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o xlnx-versal-virt.o
 obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
diff --git a/hw/arm/stm32f405_soc.c b/hw/arm/stm32f405_soc.c
new file mode 100644
index 00..498bc1192c
--- /dev/null
+++ b/hw/arm/stm32f405_soc.c
@@ -0,0 +1,301 @@
+/*
+ * STM32F405 SoC
+ *
+ * Copyright (c) 2014 Alistair Francis 
+ *
+ * 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 "qapi/error.h"
+#include "qemu-common.h"
+#include "exec/address-spaces.h"
+#include "hw/arm/stm32f405_soc.h"
+#include "hw/misc/unimp.h"
+
+#define SYSCFG_ADD 0x40013800
+static const uint32_t usart_addr[] = { 0x40011000, 0x40004400, 0x40004800,
+   0x40004C00, 0x40005000, 0x40011400,
+   0x40007800, 0x40007C00 };
+/* At the moment only Timer 2 to 5 are modelled */
+static const uint32_t timer_addr[] = { 0x4000, 0x4400,
+   0x4800, 0x4C00 };
+#define ADC_ADDR   0x40012000
+static const uint32_t spi_addr[] =   { 0x40013000, 0x40003800, 0x40003C00,
+   0x40013400, 0x40015000, 0x40015400 };
+#define EXTI_ADDR  0x40013C00
+
+#define SYSCFG_IRQ   71
+static const int usart_irq[] = { 37, 38, 39, 52, 53, 71, 82, 83 };
+static const int timer_irq[] = { 28, 29, 30, 50 };
+#define ADC_IRQ 18
+static const int spi_irq[] =   { 35, 36, 51, 0, 0, 0 };
+static const int exti_irq[] =  { 6, 7, 8, 9, 10, 23, 23, 23, 23, 23, 40,
+ 40, 40, 40, 40, 40} ;
+
+
+static void stm32f405_soc_initfn(Object *obj)
+{
+STM32F405State *s = STM32F405_SOC(obj);
+int i;
+
+sysbus_init_child_obj(obj, "armv7m", >armv7m, sizeof(s->armv7m),
+  TYPE_ARMV7M);
+
+sysbus_init_child_obj(obj, "syscfg", >syscfg, sizeof(s->syscfg),
+  TYPE_STM32F4XX_SYSCFG);
+
+for (i = 0; i < STM_NUM_USARTS; i++) {
+sysbus_init_child_obj(obj, "usart[*]", >usart[i],
+  sizeof(s->usart[i]), TYPE_STM32F2XX_USART);
+}
+
+for (i = 0; i < STM_NUM_TIMERS; i++) {
+sysbus_init_child_obj(obj, "timer[*]", >timer[i],
+  

[Qemu-devel] [PATCH v4 6/6] hw/arm: Add the Netduino Plus 2

2019-09-06 Thread Alistair Francis
Signed-off-by: Alistair Francis 
---
 MAINTAINERS|  6 +
 hw/arm/Kconfig |  3 +++
 hw/arm/Makefile.objs   |  1 +
 hw/arm/netduinoplus2.c | 58 ++
 4 files changed, 68 insertions(+)
 create mode 100644 hw/arm/netduinoplus2.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 4aea8cb3fa..5f23865ce3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -828,6 +828,12 @@ M: Peter Maydell 
 S: Maintained
 F: hw/arm/netduino2.c
 
+Netduino Plus 2
+M: Alistair Francis 
+M: Peter Maydell 
+S: Maintained
+F: hw/arm/netduinoplus2.c
+
 SmartFusion2
 M: Subbaraya Sundeep 
 M: Peter Maydell 
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 46a4f052e9..c153ac0975 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -101,6 +101,9 @@ config NETDUINOPLUS2
 bool
 select STM32F405_SOC
 
+config NETDUINOPLUS2
+bool
+
 config NSERIES
 bool
 select OMAP
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 0191c22c4f..4267805dc9 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -11,6 +11,7 @@ obj-$(CONFIG_MAINSTONE) += mainstone.o
 obj-$(CONFIG_MICROBIT) += microbit.o
 obj-$(CONFIG_MUSICPAL) += musicpal.o
 obj-$(CONFIG_NETDUINO2) += netduino2.o
+obj-$(CONFIG_NETDUINOPLUS2) += netduinoplus2.o
 obj-$(CONFIG_NSERIES) += nseries.o
 obj-$(CONFIG_SX1) += omap_sx1.o
 obj-$(CONFIG_CHEETAH) += palm.o
diff --git a/hw/arm/netduinoplus2.c b/hw/arm/netduinoplus2.c
new file mode 100644
index 00..4a75da8543
--- /dev/null
+++ b/hw/arm/netduinoplus2.c
@@ -0,0 +1,58 @@
+/*
+ * Netduino Plus 2 Machine Model
+ *
+ * Copyright (c) 2014 Alistair Francis 
+ *
+ * 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 "qapi/error.h"
+#include "hw/boards.h"
+#include "qemu/error-report.h"
+#include "hw/arm/stm32f405_soc.h"
+#include "hw/arm/boot.h"
+
+static void netduinoplus2_init(MachineState *machine)
+{
+DeviceState *dev;
+uint32_t kernel_entry;
+
+dev = qdev_create(NULL, TYPE_STM32F405_SOC);
+qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4"));
+object_property_set_bool(OBJECT(dev), true, "realized", _fatal);
+
+kernel_entry = armv7m_load_kernel(ARM_CPU(first_cpu),
+  machine->kernel_filename,
+  FLASH_SIZE);
+
+object_property_set_int(OBJECT(first_cpu), kernel_entry,
+"init-entry", _fatal);
+object_property_set_int(OBJECT(first_cpu),
+SRAM_BASE_ADDRESS + (SRAM_SIZE * 2) / 3,
+"init-sp", _fatal);
+}
+
+static void netduinoplus2_machine_init(MachineClass *mc)
+{
+mc->desc = "Netduino Plus 2 Machine";
+mc->init = netduinoplus2_init;
+}
+
+DEFINE_MACHINE("netduinoplus2", netduinoplus2_machine_init)
-- 
2.22.0




Re: [Qemu-devel] [PATCH v4 0/6] Add the STM32F405 and Netduino Plus 2 machine

2019-09-06 Thread no-reply
Patchew URL: 
https://patchew.org/QEMU/cover.1567750222.git.alist...@alistair23.me/



Hi,

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

Subject: [Qemu-devel] [PATCH v4 0/6] Add the STM32F405 and Netduino Plus 2 
machine
Message-id: cover.1567750222.git.alist...@alistair23.me
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'
8b0ecd4 hw/arm: Add the Netduino Plus 2
407f73f hw/arm: Add the STM32F4xx SoC
512fff3 hw/misc: Add the STM32F4xx EXTI device
2caad5c hw/misc: Add the STM32F4xx Sysconfig device
955f060 target/arm: Allow setting M mode entry and sp
d81d27f armv7m: Allow entry information to be returned

=== OUTPUT BEGIN ===
1/6 Checking commit d81d27f0996a (armv7m: Allow entry information to be 
returned)
WARNING: line over 80 characters
#24: FILE: hw/arm/armv7m.c:309:
+uint64_t armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int 
mem_size)

WARNING: line over 80 characters
#52: FILE: include/hw/arm/boot.h:36:
+uint64_t armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int 
mem_size);

total: 0 errors, 2 warnings, 30 lines checked

Patch 1/6 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
2/6 Checking commit 955f06078662 (target/arm: Allow setting M mode entry and sp)
3/6 Checking commit 2caad5c67035 (hw/misc: Add the STM32F4xx Sysconfig device)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#77: 
new file mode 100644

ERROR: suspect code indent for conditional statements (4, 7)
#135: FILE: hw/misc/stm32f4xx_syscfg.c:54:
+if (extract32(s->syscfg_exticr[icrreg], startbit, 4) == config) {
+   qemu_set_irq(s->gpio_out[irq], level);

WARNING: line over 80 characters
#222: FILE: hw/misc/stm32f4xx_syscfg.c:141:
+VMSTATE_UINT32_ARRAY(syscfg_exticr, STM32F4xxSyscfgState, 
SYSCFG_NUM_EXTICR),

total: 1 errors, 2 warnings, 285 lines checked

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

4/6 Checking commit 512fff3fab76 (hw/misc: Add the STM32F4xx EXTI device)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#50: 
new file mode 100644

total: 0 errors, 1 warnings, 281 lines checked

Patch 4/6 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
5/6 Checking commit 407f73fb3229 (hw/arm: Add the STM32F4xx SoC)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#57: 
new file mode 100644

total: 0 errors, 1 warnings, 404 lines checked

Patch 5/6 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
6/6 Checking commit 8b0ecd413bdc (hw/arm: Add the Netduino Plus 2)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#54: 
new file mode 100644

total: 0 errors, 1 warnings, 86 lines checked

Patch 6/6 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/cover.1567750222.git.alist...@alistair23.me/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-de...@redhat.com

Re: [Qemu-devel] [PATCH v5 13/17] target/arm: Split out arm_mmu_idx_el

2019-09-06 Thread Philippe Mathieu-Daudé
On 8/20/19 11:07 PM, Richard Henderson wrote:
> Avoid calling arm_current_el() twice.
> 
> Signed-off-by: Richard Henderson 

Reviewed-by: Philippe Mathieu-Daudé 

> ---
>  target/arm/internals.h |  9 +
>  target/arm/helper.c| 12 +++-
>  2 files changed, 16 insertions(+), 5 deletions(-)
> 
> diff --git a/target/arm/internals.h b/target/arm/internals.h
> index 232d963875..f5313dd3d4 100644
> --- a/target/arm/internals.h
> +++ b/target/arm/internals.h
> @@ -949,6 +949,15 @@ void arm_cpu_update_virq(ARMCPU *cpu);
>   */
>  void arm_cpu_update_vfiq(ARMCPU *cpu);
>  
> +/**
> + * arm_mmu_idx_el:
> + * @env: The cpu environment
> + * @el: The EL to use.
> + *
> + * Return the full ARMMMUIdx for the translation regime for EL.
> + */
> +ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el);
> +
>  /**
>   * arm_mmu_idx:
>   * @env: The cpu environment
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 83ae33dae5..19bdb9b9d6 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -10988,15 +10988,12 @@ ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState 
> *env, bool secstate)
>  }
>  #endif
>  
> -ARMMMUIdx arm_mmu_idx(CPUARMState *env)
> +ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el)
>  {
> -int el;
> -
>  if (arm_feature(env, ARM_FEATURE_M)) {
>  return arm_v7m_mmu_idx_for_secstate(env, env->v7m.secure);
>  }
>  
> -el = arm_current_el(env);
>  if (el < 2 && arm_is_secure_below_el3(env)) {
>  return ARMMMUIdx_S1SE0 + el;
>  } else {
> @@ -11004,6 +11001,11 @@ ARMMMUIdx arm_mmu_idx(CPUARMState *env)
>  }
>  }
>  
> +ARMMMUIdx arm_mmu_idx(CPUARMState *env)
> +{
> +return arm_mmu_idx_el(env, arm_current_el(env));
> +}
> +
>  int cpu_mmu_index(CPUARMState *env, bool ifetch)
>  {
>  return arm_to_core_mmu_idx(arm_mmu_idx(env));
> @@ -11164,7 +11166,7 @@ static uint32_t rebuild_hflags_internal(CPUARMState 
> *env)
>  {
>  int el = arm_current_el(env);
>  int fp_el = fp_exception_el(env, el);
> -ARMMMUIdx mmu_idx = arm_mmu_idx(env);
> +ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, el);
>  
>  if (is_a64(env)) {
>  return rebuild_hflags_a64(env, el, fp_el, mmu_idx);
> 



[Qemu-devel] [PATCH v2 00/28] s390x/tcg: mem_helper: Fault-safe handling

2019-09-06 Thread David Hildenbrand
This is the successor of
"[PATCH v1 0/4] s390x/tcg: MOVE (MVC): Fault-safe handling"



This series fixes a bunch of issues related to some mem helpers and makes
sure that they are fault-safe, meaning no system state is modified in case
a fault is triggered.

I can spot tons of other issues with other mem helpers that will have
to be fixed later. Also, fault-safe handling for some instructions
(especially TR) might be harder to implement (you don't know what will
actually be accessed upfront - we might need a buffer and go over
inputs twice). Focusing on the MOVE instructions for now.



Newer versions of glibc use memcpy() in memmove() for forward moves. The
implementation makese use of MVC. The TCG implementation of MVC is
currently not able to handle faults reliably when crossing pages. MVC
can cross with 256 bytes at most two pages.

In case we get a fault on the second page, we already moved data. When
continuing after the fault we might try to move already overwritten data,
which is very bad in case we have overlapping data on a forward move.

Triggered for now only by rpmbuild (crashes when checking the spec file)
and rpm (database corruptions). This fixes installing Fedora rawhide (31)
under TCG.

This was horrible to debug as it barely triggers and we fail at completely
different places.

Cc: Stefano Brivio 
Cc: Florian Weimer 

v1 -> v2:
- Include many fixes
- Fix more instructions
- Use the new probe_access() function
- Include "tests/tcg: target/s390x: Test MVO"

David Hildenbrand (28):
  s390x/tcg: Reset exception_index to -1 instead of 0
  s390x/tcg: MVCL: Zero out unused bits of address
  s390x/tcg: MVCL: Detect destructive overlaps
  s390x/tcg: MVCL: Process max 2k bytes at a time
  s390x/tcg: MVC: Increment the length once
  s390x/tcg: MVC: Use is_destructive_overlap()
  s390x/tcg: MVPG: Check for specification exceptions
  s390x/tcg: MVPG: Properly wrap the addresses
  s390x/tcg: MVCLU/MVCLE: Process max 4k bytes at a time
  s390x/tcg: MVCS/MVCP: Check for special operation exceptions
  s390x/tcg: MVCS/MVCP: Properly wrap the length
  s390x/tcg: MVST: Check for specification exceptions
  s390x/tcg: MVST: Fix storing back the addresses to registers
  s390x/tcg: Always use MMU_USER_IDX for CONFIG_USER_ONLY
  s390x/tcg: Fault-safe memset
  s390x/tcg: Fault-safe memmove
  s390x/tcg: MVCS/MVCP: Use access_memmove_idx()
  s390x/tcg: MVC: Fault-safe handling on destructive overlaps
  s390x/tcg: MVCLU: Fault-safe handling
  s390x/tcg: OC: Fault-safe handling
  s390x/tcg: XC: Fault-safe handling
  s390x/tcg: NC: Fault-safe handling
  s390x/tcg: MVCIN: Fault-safe handling
  s390x/tcg: MVN: Fault-safe handling
  s390x/tcg: MVZ: Fault-safe handling
  s390x/tcg: MVST: Fault-safe handling
  s390x/tcg: MVO: Fault-safe handling
  tests/tcg: target/s390x: Test MVO

 target/s390x/cpu.h  |   4 +
 target/s390x/helper.h   |   2 +-
 target/s390x/insn-data.def  |   2 +-
 target/s390x/mem_helper.c   | 672 ++--
 target/s390x/translate.c|  12 +-
 tests/tcg/s390x/Makefile.target |   1 +
 tests/tcg/s390x/mvo.c   |  25 ++
 7 files changed, 507 insertions(+), 211 deletions(-)
 create mode 100644 tests/tcg/s390x/mvo.c

-- 
2.21.0




[Qemu-devel] [PATCH v2 05/28] s390x/tcg: MVC: Increment the length once

2019-09-06 Thread David Hildenbrand
Let's increment the length once.

While at it, cleanup the comment. The memset() example is given as a
programming note in the PoP, so drop the description.

Reviewed-by: Richard Henderson 
Signed-off-by: David Hildenbrand 
---
 target/s390x/mem_helper.c | 20 
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index 2e22c183bd..2bc2cd09c1 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -320,16 +320,20 @@ static uint32_t do_helper_mvc(CPUS390XState *env, 
uint32_t l, uint64_t dest,
 HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
__func__, l, dest, src);
 
-/* mvc and memmove do not behave the same when areas overlap! */
-/* mvc with source pointing to the byte after the destination is the
-   same as memset with the first source byte */
+/* MVC always copies one more byte than specified - maximum is 256 */
+l++;
+
+/*
+ * "When the operands overlap, the result is obtained as if the operands
+ * were processed one byte at a time". Only non-destructive overlaps
+ * behave like memmove().
+ */
 if (dest == src + 1) {
-fast_memset(env, dest, cpu_ldub_data_ra(env, src, ra), l + 1, ra);
-} else if (dest < src || src + l < dest) {
-fast_memmove(env, dest, src, l + 1, ra);
+fast_memset(env, dest, cpu_ldub_data_ra(env, src, ra), l, ra);
+} else if (dest < src || src + l <= dest) {
+fast_memmove(env, dest, src, l, ra);
 } else {
-/* slow version with byte accesses which always work */
-for (i = 0; i <= l; i++) {
+for (i = 0; i < l; i++) {
 uint8_t x = cpu_ldub_data_ra(env, src + i, ra);
 cpu_stb_data_ra(env, dest + i, x, ra);
 }
-- 
2.21.0




[Qemu-devel] [PATCH v2 01/28] s390x/tcg: Reset exception_index to -1 instead of 0

2019-09-06 Thread David Hildenbrand
We use the marker "-1" for "no exception". s390_cpu_do_interrupt() might
get confused by that.

Signed-off-by: David Hildenbrand 
---
 target/s390x/mem_helper.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index 29fcce426e..39ee9b3175 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -1747,7 +1747,7 @@ uint32_t HELPER(tprot)(CPUS390XState *env, uint64_t a1, 
uint64_t a2)
 
 if (env->int_pgm_code == PGM_PROTECTION) {
 /* retry if reading is possible */
-cs->exception_index = 0;
+cs->exception_index = -1;
 if (!s390_cpu_virt_mem_check_read(cpu, a1, 0, 1)) {
 /* Fetching permitted; storing not permitted */
 return 1;
@@ -1757,7 +1757,7 @@ uint32_t HELPER(tprot)(CPUS390XState *env, uint64_t a1, 
uint64_t a2)
 switch (env->int_pgm_code) {
 case PGM_PROTECTION:
 /* Fetching not permitted; storing not permitted */
-cs->exception_index = 0;
+cs->exception_index = -1;
 return 2;
 case PGM_ADDRESSING:
 case PGM_TRANS_SPEC:
@@ -1767,7 +1767,7 @@ uint32_t HELPER(tprot)(CPUS390XState *env, uint64_t a1, 
uint64_t a2)
 }
 
 /* Translation not available */
-cs->exception_index = 0;
+cs->exception_index = -1;
 return 3;
 }
 
-- 
2.21.0




[Qemu-devel] [PATCH v2 13/28] s390x/tcg: MVST: Fix storing back the addresses to registers

2019-09-06 Thread David Hildenbrand
24 and 31-bit address space handling is wrong when it comes to storing
back the addresses to the register.

Signed-off-by: David Hildenbrand 
---
 target/s390x/helper.h  |  2 +-
 target/s390x/insn-data.def |  2 +-
 target/s390x/mem_helper.c  | 20 
 target/s390x/translate.c   |  8 ++--
 4 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/target/s390x/helper.h b/target/s390x/helper.h
index e9aff83b05..b32fce22ca 100644
--- a/target/s390x/helper.h
+++ b/target/s390x/helper.h
@@ -20,7 +20,7 @@ DEF_HELPER_FLAGS_4(mvn, TCG_CALL_NO_WG, void, env, i32, i64, 
i64)
 DEF_HELPER_FLAGS_4(mvo, TCG_CALL_NO_WG, void, env, i32, i64, i64)
 DEF_HELPER_FLAGS_4(mvpg, TCG_CALL_NO_WG, i32, env, i64, i64, i64)
 DEF_HELPER_FLAGS_4(mvz, TCG_CALL_NO_WG, void, env, i32, i64, i64)
-DEF_HELPER_4(mvst, i64, env, i64, i64, i64)
+DEF_HELPER_4(mvst, i32, env, i64, i32, i32)
 DEF_HELPER_4(ex, void, env, i32, i64, i64)
 DEF_HELPER_FLAGS_4(stam, TCG_CALL_NO_WG, void, env, i32, i64, i32)
 DEF_HELPER_FLAGS_4(lam, TCG_CALL_NO_WG, void, env, i32, i64, i32)
diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def
index f421184fcd..449eee1662 100644
--- a/target/s390x/insn-data.def
+++ b/target/s390x/insn-data.def
@@ -637,7 +637,7 @@
 /* MOVE PAGE */
 C(0xb254, MVPG,RRE,   Z,   r1_o, r2_o, 0, 0, mvpg, 0)
 /* MOVE STRING */
-C(0xb255, MVST,RRE,   Z,   r1_o, r2_o, 0, 0, mvst, 0)
+C(0xb255, MVST,RRE,   Z,   0, 0, 0, 0, mvst, 0)
 /* MOVE WITH OPTIONAL SPECIFICATION */
 C(0xc800, MVCOS,   SSF,   MVCOS, la1, a2, 0, 0, mvcos, 0)
 /* MOVE WITH OFFSET */
diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index afcd452a00..8dd58b3ab1 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -694,8 +694,10 @@ uint32_t HELPER(mvpg)(CPUS390XState *env, uint64_t r0, 
uint64_t r1, uint64_t r2)
 }
 
 /* string copy (c is string terminator) */
-uint64_t HELPER(mvst)(CPUS390XState *env, uint64_t c, uint64_t d, uint64_t s)
+uint32_t HELPER(mvst)(CPUS390XState *env, uint64_t c, uint32_t r1, uint32_t r2)
 {
+const uint64_t d = get_address(env, r1);
+const uint64_t s = get_address(env, r2);
 uintptr_t ra = GETPC();
 uint32_t len;
 
@@ -703,8 +705,6 @@ uint64_t HELPER(mvst)(CPUS390XState *env, uint64_t c, 
uint64_t d, uint64_t s)
 s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, ra);
 }
 c = c & 0xff;
-d = wrap_address(env, d);
-s = wrap_address(env, s);
 
 /* Lest we fail to service interrupts in a timely manner, limit the
amount of work we're willing to do.  For now, let's cap at 8k.  */
@@ -712,17 +712,13 @@ uint64_t HELPER(mvst)(CPUS390XState *env, uint64_t c, 
uint64_t d, uint64_t s)
 uint8_t v = cpu_ldub_data_ra(env, s + len, ra);
 cpu_stb_data_ra(env, d + len, v, ra);
 if (v == c) {
-/* Complete.  Set CC=1 and advance R1.  */
-env->cc_op = 1;
-env->retxl = s;
-return d + len;
+set_address_zero(env, r1, d + len);
+return 1;
 }
 }
-
-/* Incomplete.  Set CC=3 and signal to advance R1 and R2.  */
-env->cc_op = 3;
-env->retxl = s + len;
-return d + len;
+set_address_zero(env, r1, d + len);
+set_address_zero(env, r2, s + len);
+return 3;
 }
 
 /* load access registers r1 to r3 from memory at a2 */
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index 2927247c82..b76e10d832 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -3488,9 +3488,13 @@ static DisasJumpType op_mvpg(DisasContext *s, DisasOps 
*o)
 
 static DisasJumpType op_mvst(DisasContext *s, DisasOps *o)
 {
-gen_helper_mvst(o->in1, cpu_env, regs[0], o->in1, o->in2);
+TCGv_i32 t1 = tcg_const_i32(get_field(s->fields, r1));
+TCGv_i32 t2 = tcg_const_i32(get_field(s->fields, r2));
+
+gen_helper_mvst(cc_op, cpu_env, regs[0], t1, t2);
+tcg_temp_free_i32(t1);
+tcg_temp_free_i32(t2);
 set_cc_static(s);
-return_low128(o->in2);
 return DISAS_NEXT;
 }
 
-- 
2.21.0




[Qemu-devel] [PATCH v2 23/28] s390x/tcg: MVCIN: Fault-safe handling

2019-09-06 Thread David Hildenbrand
We can process a maximum of 256 bytes, crossing two pages. Calculate the
accessed range upfront - src is accessed right-to-left.

Signed-off-by: David Hildenbrand 
---
 target/s390x/mem_helper.c | 14 +++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index 49b4879859..ba8a657e18 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -473,12 +473,20 @@ void HELPER(mvc)(CPUS390XState *env, uint32_t l, uint64_t 
dest, uint64_t src)
 /* move inverse  */
 void HELPER(mvcin)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
 {
+S390Access srca, desta;
 uintptr_t ra = GETPC();
 int i;
 
-for (i = 0; i <= l; i++) {
-uint8_t v = cpu_ldub_data_ra(env, src - i, ra);
-cpu_stb_data_ra(env, dest + i, v, ra);
+/* MVCIN always copies one more byte than specified - maximum is 256 */
+l++;
+
+src = wrap_address(env, src - l + 1);
+srca = access_prepare(env, src, l, MMU_DATA_LOAD, ra);
+desta = access_prepare(env, dest, l, MMU_DATA_STORE, ra);
+for (i = 0; i < l; i++) {
+const uint8_t x = access_get_byte(env, , l - i - 1, ra);
+
+access_set_byte(env, , i, x, ra);
 }
 }
 
-- 
2.21.0




[Qemu-devel] [PATCH v2 06/28] s390x/tcg: MVC: Use is_destructive_overlap()

2019-09-06 Thread David Hildenbrand
Let's use the new helper, that also detects destructive overlaps when
wrapping.

Signed-off-by: David Hildenbrand 
---
 target/s390x/mem_helper.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index 2bc2cd09c1..3c23c403cd 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -330,7 +330,7 @@ static uint32_t do_helper_mvc(CPUS390XState *env, uint32_t 
l, uint64_t dest,
  */
 if (dest == src + 1) {
 fast_memset(env, dest, cpu_ldub_data_ra(env, src, ra), l, ra);
-} else if (dest < src || src + l <= dest) {
+} else if (!is_destructive_overlap(env, dest, src, l)) {
 fast_memmove(env, dest, src, l, ra);
 } else {
 for (i = 0; i < l; i++) {
-- 
2.21.0




[Qemu-devel] [PATCH v2 27/28] s390x/tcg: MVO: Fault-safe handling

2019-09-06 Thread David Hildenbrand
Each operand can have a maximum length of 16. Make sure to prepare all
reads/writes before writing.

Signed-off-by: David Hildenbrand 
---
 target/s390x/mem_helper.c | 26 ++
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index 73b00b582b..7403124763 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -514,31 +514,33 @@ void HELPER(mvn)(CPUS390XState *env, uint32_t l, uint64_t 
dest, uint64_t src)
 /* move with offset  */
 void HELPER(mvo)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
 {
+/* MVO always processes one more byte than specified - maximum is 16 */
+const int len_dest = (l >> 4) + 1;
+const int len_src = (l & 0xf) + 1;
 uintptr_t ra = GETPC();
-int len_dest = l >> 4;
-int len_src = l & 0xf;
 uint8_t byte_dest, byte_src;
-int i;
+S390Access srca, desta;
+int i, j;
 
-src += len_src;
-dest += len_dest;
+srca = access_prepare(env, src, len_src, MMU_DATA_LOAD, ra);
+desta = access_prepare(env, dest, len_dest, MMU_DATA_STORE, ra);
 
 /* Handle rightmost byte */
-byte_src = cpu_ldub_data_ra(env, src, ra);
-byte_dest = cpu_ldub_data_ra(env, dest, ra);
+byte_dest = cpu_ldub_data_ra(env, dest + len_dest - 1, ra);
+byte_src = access_get_byte(env, , len_src - 1, ra);
 byte_dest = (byte_dest & 0x0f) | (byte_src << 4);
-cpu_stb_data_ra(env, dest, byte_dest, ra);
+access_set_byte(env, , len_dest - 1, byte_dest, ra);
 
 /* Process remaining bytes from right to left */
-for (i = 1; i <= len_dest; i++) {
+for (i = len_dest - 2, j = len_src - 2; i >= 0; i--, j--) {
 byte_dest = byte_src >> 4;
-if (len_src - i >= 0) {
-byte_src = cpu_ldub_data_ra(env, src - i, ra);
+if (j >= 0) {
+byte_src = access_get_byte(env, , j, ra);
 } else {
 byte_src = 0;
 }
 byte_dest |= byte_src << 4;
-cpu_stb_data_ra(env, dest - i, byte_dest, ra);
+access_set_byte(env, , i, byte_dest, ra);
 }
 }
 
-- 
2.21.0




[Qemu-devel] [PATCH v2 26/28] s390x/tcg: MVST: Fault-safe handling

2019-09-06 Thread David Hildenbrand
Access at most single pages and document why. Using the access helpers
might over-indicate watchpoints within the same page, I guess we can
live with that.

Signed-off-by: David Hildenbrand 
---
 target/s390x/mem_helper.c | 23 ---
 1 file changed, 16 insertions(+), 7 deletions(-)

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index 4c67c6f37e..73b00b582b 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -845,21 +845,30 @@ uint32_t HELPER(mvst)(CPUS390XState *env, uint64_t c, 
uint32_t r1, uint32_t r2)
 {
 const uint64_t d = get_address(env, r1);
 const uint64_t s = get_address(env, r2);
+const int len = MIN(-(d | TARGET_PAGE_MASK), -(s | TARGET_PAGE_MASK));
+S390Access srca, desta;
 uintptr_t ra = GETPC();
-uint32_t len;
+int i;
 
 if (c & 0xff00ull) {
 s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, ra);
 }
 c = c & 0xff;
 
-/* Lest we fail to service interrupts in a timely manner, limit the
-   amount of work we're willing to do.  For now, let's cap at 8k.  */
-for (len = 0; len < 0x2000; ++len) {
-uint8_t v = cpu_ldub_data_ra(env, s + len, ra);
-cpu_stb_data_ra(env, d + len, v, ra);
+/*
+ * Our access should not exceed single pages, as we must not report access
+ * exceptions exceeding the actually copied range (which we don't know at
+ * this point). We might over-indicate watchpoints within the pages
+ * (if we ever care, we have to limit processing to a single byte).
+ */
+srca = access_prepare(env, s, len, MMU_DATA_LOAD, ra);
+desta = access_prepare(env, d, len, MMU_DATA_STORE, ra);
+for (i = 0; i < len; i++) {
+const uint8_t v = access_get_byte(env, , i, ra);
+
+access_set_byte(env, , i, v, ra);
 if (v == c) {
-set_address_zero(env, r1, d + len);
+set_address_zero(env, r1, d + i);
 return 1;
 }
 }
-- 
2.21.0




[Qemu-devel] [PATCH v2 25/28] s390x/tcg: MVZ: Fault-safe handling

2019-09-06 Thread David Hildenbrand
We can process a maximum of 256 bytes, crossing two pages.

Signed-off-by: David Hildenbrand 
---
 target/s390x/mem_helper.c | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index 5e38b2c4d8..4c67c6f37e 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -545,13 +545,21 @@ void HELPER(mvo)(CPUS390XState *env, uint32_t l, uint64_t 
dest, uint64_t src)
 /* move zones  */
 void HELPER(mvz)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
 {
+S390Access srca1, srca2, desta;
 uintptr_t ra = GETPC();
 int i;
 
-for (i = 0; i <= l; i++) {
-uint8_t b = cpu_ldub_data_ra(env, dest + i, ra) & 0x0f;
-b |= cpu_ldub_data_ra(env, src + i, ra) & 0xf0;
-cpu_stb_data_ra(env, dest + i, b, ra);
+/* MVZ always copies one more byte than specified - maximum is 256 */
+l++;
+
+srca1 = access_prepare(env, src, l, MMU_DATA_LOAD, ra);
+srca2 = access_prepare(env, dest, l, MMU_DATA_LOAD, ra);
+desta = access_prepare(env, dest, l, MMU_DATA_STORE, ra);
+for (i = 0; i < l; i++) {
+const uint8_t x = (access_get_byte(env, , i, ra) & 0xf0) |
+  (access_get_byte(env, , i, ra) & 0x0f);
+
+access_set_byte(env, , i, x, ra);
 }
 }
 
-- 
2.21.0




[Qemu-devel] [PATCH v18 3/6] ACPI: Add APEI GHES table generation support

2019-09-06 Thread Xiang Zheng
From: Dongjiu Geng 

This patch implements APEI GHES Table generation via fw_cfg blobs. Now
it only supports ARMv8 SEA, a type of GHESv2 error source. Afterwards,
we can extend the supported types if needed. For the CPER section,
currently it is memory section because kernel mainly wants userspace to
handle the memory errors.

This patch follows the spec ACPI 6.2 to build the Hardware Error Source
table. For more detailed information, please refer to document:
docs/specs/acpi_hest_ghes.txt

Suggested-by: Laszlo Ersek 
Signed-off-by: Dongjiu Geng 
Signed-off-by: Xiang Zheng 
---
 default-configs/arm-softmmu.mak |   1 +
 hw/acpi/Kconfig |   4 +
 hw/acpi/Makefile.objs   |   1 +
 hw/acpi/acpi_ghes.c | 210 
 hw/acpi/aml-build.c |   2 +
 hw/arm/virt-acpi-build.c|  12 ++
 include/hw/acpi/acpi_ghes.h | 103 
 include/hw/acpi/aml-build.h |   1 +
 8 files changed, 334 insertions(+)
 create mode 100644 hw/acpi/acpi_ghes.c
 create mode 100644 include/hw/acpi/acpi_ghes.h

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 1f2e0e7fde..5722f3130e 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -40,3 +40,4 @@ CONFIG_FSL_IMX25=y
 CONFIG_FSL_IMX7=y
 CONFIG_FSL_IMX6UL=y
 CONFIG_SEMIHOSTING=y
+CONFIG_ACPI_APEI=y
diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig
index 7c59cf900b..2c4d0b9826 100644
--- a/hw/acpi/Kconfig
+++ b/hw/acpi/Kconfig
@@ -23,6 +23,10 @@ config ACPI_NVDIMM
 bool
 depends on ACPI
 
+config ACPI_APEI
+bool
+depends on ACPI
+
 config ACPI_PCI
 bool
 depends on ACPI && PCI
diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
index 9bb2101e3b..93fd8e8f64 100644
--- a/hw/acpi/Makefile.objs
+++ b/hw/acpi/Makefile.objs
@@ -5,6 +5,7 @@ common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu_hotplug.o
 common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o
 common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu.o
 common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o
+common-obj-$(CONFIG_ACPI_APEI) += acpi_ghes.o
 common-obj-$(CONFIG_ACPI_VMGENID) += vmgenid.o
 common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o
 
diff --git a/hw/acpi/acpi_ghes.c b/hw/acpi/acpi_ghes.c
new file mode 100644
index 00..20c45179ff
--- /dev/null
+++ b/hw/acpi/acpi_ghes.c
@@ -0,0 +1,210 @@
+/* Support for generating APEI tables and record CPER for Guests
+ *
+ * Copyright (C) 2019 Huawei Corporation.
+ *
+ * Author: Dongjiu Geng 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "hw/acpi/acpi.h"
+#include "hw/acpi/aml-build.h"
+#include "hw/acpi/acpi_ghes.h"
+#include "hw/nvram/fw_cfg.h"
+#include "sysemu/sysemu.h"
+#include "qemu/error-report.h"
+
+/* Hardware Error Notification
+ * ACPI 4.0: 17.3.2.7 Hardware Error Notification
+ */
+static void acpi_ghes_build_notify(GArray *table, const uint8_t type,
+   uint8_t length, uint16_t 
config_write_enable,
+   uint32_t poll_interval, uint32_t vector,
+   uint32_t polling_threshold_value,
+   uint32_t polling_threshold_window,
+   uint32_t error_threshold_value,
+   uint32_t error_threshold_window)
+{
+/* Type */
+build_append_int_noprefix(table, type, 1);
+/* Length */
+build_append_int_noprefix(table, length, 1);
+/* Configuration Write Enable */
+build_append_int_noprefix(table, config_write_enable, 2);
+/* Poll Interval */
+build_append_int_noprefix(table, poll_interval, 4);
+/* Vector */
+build_append_int_noprefix(table, vector, 4);
+/* Switch To Polling Threshold Value */
+build_append_int_noprefix(table, polling_threshold_value, 4);
+/* Switch To Polling Threshold Window */
+build_append_int_noprefix(table, polling_threshold_window, 4);
+/* Error Threshold Value */
+build_append_int_noprefix(table, error_threshold_value, 4);
+/* Error Threshold Window */
+build_append_int_noprefix(table, error_threshold_window, 4);
+}
+
+/* Build table for the hardware error fw_cfg blob */
+void acpi_ghes_build_error_table(GArray 

[Qemu-devel] [PATCH v2 08/28] s390x/tcg: MVPG: Properly wrap the addresses

2019-09-06 Thread David Hildenbrand
We have to mask of any unused bits. While at it, document what exactly is
missing.

Signed-off-by: David Hildenbrand 
---
 target/s390x/mem_helper.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index a763482ae0..947a4277f0 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -680,8 +680,15 @@ uint32_t HELPER(mvpg)(CPUS390XState *env, uint64_t r0, 
uint64_t r1, uint64_t r2)
 s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, GETPC());
 }
 
-/* ??? missing r0 handling, which includes access keys, but more
-   importantly optional suppression of the exception!  */
+r1 = wrap_address(env, r1 & TARGET_PAGE_MASK);
+r2 = wrap_address(env, r2 & TARGET_PAGE_MASK);
+
+/*
+ * TODO:
+ * - Access key handling
+ * - CC-option with surpression of page-translation exceptions
+ * - Store r1/r2 register identifiers at real location 162
+ */
 fast_memmove(env, r1, r2, TARGET_PAGE_SIZE, GETPC());
 return 0; /* data moved */
 }
-- 
2.21.0




[Qemu-devel] [PATCH v2 18/28] s390x/tcg: MVC: Fault-safe handling on destructive overlaps

2019-09-06 Thread David Hildenbrand
The last remaining bit for MVC is handling destructive overlaps in a
fault-safe way.

Signed-off-by: David Hildenbrand 
---
 target/s390x/mem_helper.c | 16 ++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index 2607dd1677..f636f3a011 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -145,6 +145,14 @@ static S390Access access_prepare_idx(CPUS390XState *env, 
vaddr vaddr, int size,
 return access;
 }
 
+static S390Access access_prepare(CPUS390XState *env, vaddr vaddr, int size,
+ MMUAccessType access_type, uintptr_t ra)
+{
+int mmu_idx = cpu_mmu_index(env, false);
+
+return access_prepare_idx(env, vaddr, size, access_type, mmu_idx, ra);
+}
+
 static void access_memset_idx(CPUS390XState *env, vaddr vaddr, uint8_t byte,
   int size, int mmu_idx, uintptr_t ra)
 {
@@ -420,9 +428,13 @@ static uint32_t do_helper_mvc(CPUS390XState *env, uint32_t 
l, uint64_t dest,
 } else if (!is_destructive_overlap(env, dest, src, l)) {
 access_memmove(env, dest, src, l, ra);
 } else {
+S390Access srca = access_prepare(env, src, l, MMU_DATA_LOAD, ra);
+S390Access desta = access_prepare(env, dest, l, MMU_DATA_STORE, ra);
+
 for (i = 0; i < l; i++) {
-uint8_t x = cpu_ldub_data_ra(env, src + i, ra);
-cpu_stb_data_ra(env, dest + i, x, ra);
+uint8_t byte = access_get_byte(env, , i, ra);
+
+access_set_byte(env, , i, byte, ra);
 }
 }
 
-- 
2.21.0




[Qemu-devel] [PATCH v2 17/28] s390x/tcg: MVCS/MVCP: Use access_memmove_idx()

2019-09-06 Thread David Hildenbrand
As we are moving between address spaces, we can use access_memmove_idx()
without checking for destructive overlaps (especially of real storage
locations):
"Each storage operand is processed left to right. The
storage-operand-consistency rules are the same as
for MOVE (MVC), except that when the operands
overlap in real storage, the use of the common real-
storage locations is not necessarily recognized."

Signed-off-by: David Hildenbrand 
---
 target/s390x/mem_helper.c | 20 ++--
 1 file changed, 6 insertions(+), 14 deletions(-)

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index db678ddf47..2607dd1677 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -2049,7 +2049,7 @@ uint32_t HELPER(mvcs)(CPUS390XState *env, uint64_t l, 
uint64_t a1, uint64_t a2)
 {
 const uint8_t psw_as = (env->psw.mask & PSW_MASK_ASC) >> PSW_SHIFT_ASC;
 uintptr_t ra = GETPC();
-int cc = 0, i;
+int cc = 0;
 
 HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
__func__, l, a1, a2);
@@ -2068,12 +2068,8 @@ uint32_t HELPER(mvcs)(CPUS390XState *env, uint64_t l, 
uint64_t a1, uint64_t a2)
 return cc;
 }
 
-/* XXX replace w/ memcpy */
-for (i = 0; i < l; i++) {
-uint8_t x = cpu_ldub_primary_ra(env, a2 + i, ra);
-cpu_stb_secondary_ra(env, a1 + i, x, ra);
-}
-
+/* TODO: Access key handling */
+access_memmove_idx(env, a1, a2, l, MMU_SECONDARY_IDX, MMU_PRIMARY_IDX, ra);
 return cc;
 }
 
@@ -2081,7 +2077,7 @@ uint32_t HELPER(mvcp)(CPUS390XState *env, uint64_t l, 
uint64_t a1, uint64_t a2)
 {
 const uint8_t psw_as = (env->psw.mask & PSW_MASK_ASC) >> PSW_SHIFT_ASC;
 uintptr_t ra = GETPC();
-int cc = 0, i;
+int cc = 0;
 
 HELPER_LOG("%s: %16" PRIx64 " %16" PRIx64 " %16" PRIx64 "\n",
__func__, l, a1, a2);
@@ -2100,12 +2096,8 @@ uint32_t HELPER(mvcp)(CPUS390XState *env, uint64_t l, 
uint64_t a1, uint64_t a2)
 return cc;
 }
 
-/* XXX replace w/ memcpy */
-for (i = 0; i < l; i++) {
-uint8_t x = cpu_ldub_secondary_ra(env, a2 + i, ra);
-cpu_stb_primary_ra(env, a1 + i, x, ra);
-}
-
+/* TODO: Access key handling */
+access_memmove_idx(env, a1, a2, l, MMU_PRIMARY_IDX, MMU_SECONDARY_IDX, ra);
 return cc;
 }
 
-- 
2.21.0




[Qemu-devel] [PATCH v2 20/28] s390x/tcg: OC: Fault-safe handling

2019-09-06 Thread David Hildenbrand
We can process a maximum of 256 bytes, crossing two pages.

Signed-off-by: David Hildenbrand 
---
 target/s390x/mem_helper.c | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index 0366cbc753..ff57fec8de 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -385,17 +385,25 @@ uint32_t HELPER(xc)(CPUS390XState *env, uint32_t l, 
uint64_t dest,
 static uint32_t do_helper_oc(CPUS390XState *env, uint32_t l, uint64_t dest,
  uint64_t src, uintptr_t ra)
 {
+S390Access srca1, srca2, desta;
 uint32_t i;
 uint8_t c = 0;
 
 HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
__func__, l, dest, src);
 
-for (i = 0; i <= l; i++) {
-uint8_t x = cpu_ldub_data_ra(env, src + i, ra);
-x |= cpu_ldub_data_ra(env, dest + i, ra);
+/* OC always processes one more byte than specified - maximum is 256 */
+l++;
+
+srca1 = access_prepare(env, src, l, MMU_DATA_LOAD, ra);
+srca2 = access_prepare(env, dest, l, MMU_DATA_LOAD, ra);
+desta = access_prepare(env, dest, l, MMU_DATA_STORE, ra);
+for (i = 0; i < l; i++) {
+const uint8_t x = access_get_byte(env, , i, ra) |
+  access_get_byte(env, , i, ra);
+
 c |= x;
-cpu_stb_data_ra(env, dest + i, x, ra);
+access_set_byte(env, , i, x, ra);
 }
 return c != 0;
 }
-- 
2.21.0




[Qemu-devel] [PATCH v2 21/28] s390x/tcg: XC: Fault-safe handling

2019-09-06 Thread David Hildenbrand
We can process a maximum of 256 bytes, crossing two pages. While at it,
increment the length once.

Signed-off-by: David Hildenbrand 
---
 target/s390x/mem_helper.c | 18 +-
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index ff57fec8de..88ff6c21ed 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -354,23 +354,31 @@ uint32_t HELPER(nc)(CPUS390XState *env, uint32_t l, 
uint64_t dest,
 static uint32_t do_helper_xc(CPUS390XState *env, uint32_t l, uint64_t dest,
  uint64_t src, uintptr_t ra)
 {
+S390Access srca1, srca2, desta;
 uint32_t i;
 uint8_t c = 0;
 
 HELPER_LOG("%s l %d dest %" PRIx64 " src %" PRIx64 "\n",
__func__, l, dest, src);
 
+/* XC always processes one more byte than specified - maximum is 256 */
+l++;
+
 /* xor with itself is the same as memset(0) */
 if (src == dest) {
-access_memset(env, dest, 0, l + 1, ra);
+access_memset(env, dest, 0, l, ra);
 return 0;
 }
 
-for (i = 0; i <= l; i++) {
-uint8_t x = cpu_ldub_data_ra(env, src + i, ra);
-x ^= cpu_ldub_data_ra(env, dest + i, ra);
+srca1 = access_prepare(env, src, l, MMU_DATA_LOAD, ra);
+srca2 = access_prepare(env, dest, l, MMU_DATA_LOAD, ra);
+desta = access_prepare(env, dest, l, MMU_DATA_STORE, ra);
+for (i = 0; i < l; i++) {
+const uint8_t x = access_get_byte(env, , i, ra) ^
+  access_get_byte(env, , i, ra);
+
 c |= x;
-cpu_stb_data_ra(env, dest + i, x, ra);
+access_set_byte(env, , i, x, ra);
 }
 return c != 0;
 }
-- 
2.21.0




Re: [Qemu-devel] [PATCH] memory: Set notdirty_mem_ops validator

2019-09-06 Thread Philippe Mathieu-Daudé
On 9/2/19 3:26 AM, Tony Nguyen wrote:
> Existing read rejecting validator was mistakenly cleared.
> 
> Reads dispatched to io_mem_notdirty then segfaults as there is no read
> handler.
> 
> Signed-off-by: Tony Nguyen 
> ---
>  exec.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/exec.c b/exec.c
> index 1df966d17a..05d664541f 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -2796,12 +2796,12 @@ static bool notdirty_mem_accepts(void *opaque, hwaddr 
> addr,
>  
>  static const MemoryRegionOps notdirty_mem_ops = {
>  .write = notdirty_mem_write,
> -.valid.accepts = notdirty_mem_accepts,
>  .endianness = DEVICE_NATIVE_ENDIAN,
>  .valid = {
>  .min_access_size = 1,
>  .max_access_size = 8,
>  .unaligned = false,
> +.accepts = notdirty_mem_accepts,

I'm surprised the compiler doesn't emit any warning...

>  },
>  .impl = {
>  .min_access_size = 1,
> 

mcayland provided a verbose backtrace running Solaris, can we amend it
to this commit?

Thread 4 "qemu-system-spa" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x71d44700 (LWP 23749)]
0x in ?? ()
(gdb) bt
#0  0x in  ()
#1  0x557eae4c in memory_region_read_with_attrs_accessor
(mr=0x5633d360 , addr=531677168,
value=0x71d42eb8, size=4, shift=0, mask=4294967295, attrs=...)
at /home/build/src/qemu/git/qemu/memory.c:461
#2  0x557eb1c4 in access_with_adjusted_size (addr=531677168,
value=0x71d42eb8, size=4, access_size_min=1, access_size_max=8,
access_fn=
0x557eadf0 ,
mr=0x5633d360 , attrs=...) at
/home/build/src/qemu/git/qemu/memory.c:559
#3  0x557edeb0 in memory_region_dispatch_read1
(mr=0x5633d360 , addr=531677168,
pval=0x71d42eb8, size=4, attrs=...) at
/home/build/src/qemu/git/qemu/memory.c:1429
#4  0x557edf47 in memory_region_dispatch_read (mr=0x5633d360
, addr=531677168, pval=0x71d42eb8, op=MO_32,
attrs=...) at /home/build/src/qemu/git/qemu/memory.c:1451
#5  0x55803846 in io_readx (env=0x564b15c0,
iotlbentry=0x7fffe831e190, mmu_idx=2, addr=1880588272,
retaddr=140736889685638, access_type=MMU_DATA_LOAD, op=MO_32)
at /home/build/src/qemu/git/qemu/accel/tcg/cputlb.c:923
#6  0x558063ca in load_helper (full_load=0x55805ffb
, code_read=false, op=MO_BEUL,
retaddr=140736889685638, oi=162, addr=1880588272, env=0x564b15c0)
at /home/build/src/qemu/git/qemu/accel/tcg/cputlb.c:1346
#7  0x558063ca in full_be_ldul_mmu (env=0x564b15c0,
addr=1880588272, oi=162, retaddr=140736889685638) at
/home/build/src/qemu/git/qemu/accel/tcg/cputlb.c:1469
#8  0x55806665 in helper_be_ldul_mmu (env=0x564b15c0,
addr=1880588272, oi=162, retaddr=140736889685638) at
/home/build/src/qemu/git/qemu/accel/tcg/cputlb.c:1476
#9  0x7fffdc5106cd in code_gen_buffer ()
#10 0x558280da in cpu_tb_exec (cpu=0x564a8820,
itb=0x7fffdc50f7c0 ) at
/home/build/src/qemu/git/qemu/accel/tcg/cpu-exec.c:172
#11 0x55828ec7 in cpu_loop_exec_tb (cpu=0x564a8820,
tb=0x7fffdc50f7c0 , last_tb=0x71d43598,
tb_exit=0x71d43590) at
/home/build/src/qemu/git/qemu/accel/tcg/cpu-exec.c:620
#12 0x558291d5 in cpu_exec (cpu=0x564a8820) at
/home/build/src/qemu/git/qemu/accel/tcg/cpu-exec.c:731
#13 0x557dc460 in tcg_cpu_exec (cpu=0x564a8820) at
/home/build/src/qemu/git/qemu/cpus.c:1445
#14 0x557dc76b in qemu_tcg_rr_cpu_thread_fn (arg=0x564a8820)
at /home/build/src/qemu/git/qemu/cpus.c:1547
#15 0x55c562d4 in qemu_thread_start (args=0x564c8020) at
/home/build/src/qemu/git/qemu/util/qemu-thread-posix.c:502
#16 0x76296fa3 in start_thread (arg=) at
pthread_create.c:486
#17 0x761c74cf in clone () at
../sysdeps/unix/sysv/linux/x86_64/clone.S:95
(gdb)

Reviewed-by: Philippe Mathieu-Daudé 



[Qemu-devel] [PATCH v3] ui: add an embedded Barrier client

2019-09-06 Thread Laurent Vivier
This allows to receive mouse and keyboard events from
a Barrier server.

This is enabled by adding the following parameter on the
command line

... -object input-barrier,id=$id,name=$name ...

Where $name is the name declared in the screens section of barrier.conf

The barrier server (barriers) must be configured and must run on the
local host.

For instance:

  section: screens
  localhost:
  ...
  VM-1:
  ...
  end

  section: links
  localhost:
  right = VM-1
  VM-1:
  left = localhost
  end

Then on the QEMU command line:

... -object input-barrier,id=barrie0,name=VM-1 ...

When the mouse will move out of the screen of the local host on
the right, the mouse and the keyboard will be grabbed and all
related events will be send to the guest OS.

This is usefull when qemu is configured without emulated graphic card
but with a VFIO attached graphic card.

More information about Barrier can be found at:

  https://github.com/debauchee/barrier

This avoids to install the Barrier server in the guest OS,
for instance when it is not supported or during the installation.

Signed-off-by: Laurent Vivier 
---

Notes:
v3: remove typo in barrier.txt

v2: use qemu_input_map_xorgkbd_to_qcode[] to convert button field
use keyboard_layout to convert keys if button field is not available
fix some command in the protocol
add ui/input-barrier.h
rework read/write functions
add server/port properties
add display properties
rework protocol
allow to reconnect (object_del + object_add)
add documentation

 docs/barrier.txt   | 370 ++
 ui/Makefile.objs   |   1 +
 ui/input-barrier.c | 750 +
 ui/input-barrier.h | 112 +++
 4 files changed, 1233 insertions(+)
 create mode 100644 docs/barrier.txt
 create mode 100644 ui/input-barrier.c
 create mode 100644 ui/input-barrier.h

diff --git a/docs/barrier.txt b/docs/barrier.txt
new file mode 100644
index ..b21d15015d96
--- /dev/null
+++ b/docs/barrier.txt
@@ -0,0 +1,370 @@
+QEMU Barrier Client
+
+
+* About
+
+Barrier is a KVM (Keyboard-Video-Mouse) software forked from Symless's
+synergy 1.9 codebase.
+
+See https://github.com/debauchee/barrier
+
+* QEMU usage
+
+Generally, mouse and keyboard are grabbed through the QEMU video
+interface emulation.
+
+But when we want to use a video graphic adapter via a PCI passthrough
+there is no way to provide the keyboard and mouse inputs to the VM
+except by plugging a second set of mouse and keyboard to the host
+or by installing a KVM software in the guest OS.
+
+The QEMU Barrier client avoids this by implementing directly the Barrier
+protocol into QEMU.
+
+This protocol is enabled by adding an input-barrier object to QEMU.
+
+Syntax: input-barrier,id=,name=
+[,server=][,port=]
+[,x-origin=][,y-origin=]
+[,width=][,height=]
+
+The object can be added on the QEMU command line, for instance with:
+
+... -object input-barrier,id=barrier0,name=VM-1 ...
+
+where VM-1 is the name the display configured int the Barrier server
+on the host providing the mouse and the keyboard events.
+
+by default  is "localhost", port is 24800,
+ and  are set to 0,  and  to
+1920 and 1080.
+
+If Barrier server is stopped QEMU needs to be reconnected manually,
+by removing and re-adding the input-barrier object, for instance
+with the help of the HMP monitor:
+
+(qemu) object_del barrier0
+(qemu) object_add input-barrier,id=barrier0,name=VM-1
+
+* Message format
+
+Message format between the server and client is in two parts:
+
+1- the payload length is a 32bit integer in network endianness,
+2- the payload
+
+The payload starts with a 4byte string (without NUL) which is the
+command. The first command between the server and the client
+is the only command not encoded on 4 bytes ("Barrier").
+The remaining part of the payload is decoded according to the command.
+
+* Protocol Description (from barrier/src/lib/barrier/protocol_types.h)
+
+- barrierCmdHello  "Barrier"
+
+  Direction:  server -> client
+  Parameters: { int16_t minor, int16_t major }
+  Description:
+
+  Say hello to client
+  minor = protocol major version number supported by server
+  major = protocol minor version number supported by server
+
+- barrierCmdHelloBack  "Barrier"
+
+  Direction:  client ->server
+  Parameters: { int16_t minor, int16_t major, char *name}
+  Description:
+
+  Respond to hello from server
+  minor = protocol major version number supported by client
+  major = protocol minor version number supported by client
+  name  = client name
+
+- 

Re: [Qemu-devel] [RFC Patch] xen/pt: Emulate FLR capability

2019-09-06 Thread Chao Gao
On Thu, Aug 29, 2019 at 12:21:11PM +0200, Roger Pau Monné wrote:
>On Thu, Aug 29, 2019 at 05:02:27PM +0800, Chao Gao wrote:
>> Currently, for a HVM on Xen, no reset method is virtualized. So in a VM's
>> perspective, assigned devices cannot be reset. But some devices rely on PCI
>> reset to recover from hardware hangs. When being assigned to a VM, those
>> devices cannot be reset and won't work any longer if a hardware hang occurs.
>> We have to reboot VM to trigger PCI reset on host to recover the device.
>>
>> This patch exposes FLR capability to VMs if the assigned device can be reset 
>> on
>> host. When VM initiates an FLR to a device, qemu cleans up the device state,
>> (including disabling of intx and/or MSI and unmapping BARs from guest, 
>> deleting
>> emulated registers), then initiate PCI reset through 'reset' knob under the
>> device's sysfs, finally initialize the device again.
>
>I think you likely need to deassign the device from the VM, perform
>the reset, and then assign the device again, so that there's no Xen
>internal state carried over prior to the reset?

Yes. It is the safest way. But here I want to present the feature as FLR
(such that the device driver in guest can issue PCI reset whenever
needed and no change is needed to device driver).  Current device
deassignment notifies guest that the device is going to be removed
It is not the standard PCI reset. Is it possible to make guest unaware
of the device deassignment to emulate a standard PCI reset? In my mind,
we can expose do_pci_remove/add to qemu or rewrite them in qemu (but
don't remove the device from guest's PCI hierarchy). Do you think it is
the right direction?

Thanks
Chao



[Qemu-devel] [PATCH v2 04/28] s390x/tcg: MVCL: Process max 2k bytes at a time

2019-09-06 Thread David Hildenbrand
Process max 2k bytes at a time, writing back registers between the
accesses. The instruction is interruptible.
"For operands longer than 2K bytes, access exceptions are not
recognized for locations more than 2K bytes beyond the current location
being processed."

MVCL handling is quite different than MVCLE/MVCLU handling, so split up
the handlers.

We'll deal with fast_memmove() and fast_memset() not probing
reads/writes properly later. Also, we'll defer interrupt handling, as
that will require more thought, add a TODO for that.

Signed-off-by: David Hildenbrand 
---
 target/s390x/mem_helper.c | 44 +--
 1 file changed, 38 insertions(+), 6 deletions(-)

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index 2361ed6d54..2e22c183bd 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -799,19 +799,51 @@ uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, 
uint32_t r2)
 uint64_t srclen = env->regs[r2 + 1] & 0xff;
 uint64_t src = get_address(env, r2);
 uint8_t pad = env->regs[r2 + 1] >> 24;
-uint32_t cc;
+uint32_t cc, cur_len;
 
 if (is_destructive_overlap(env, dest, src, MIN(srclen, destlen))) {
 cc = 3;
+} else if (srclen == destlen) {
+cc = 0;
+} else if (destlen < srclen) {
+cc = 1;
 } else {
-cc = do_mvcl(env, , , , , pad, 1, ra);
+cc = 2;
 }
 
-env->regs[r1 + 1] = deposit64(env->regs[r1 + 1], 0, 24, destlen);
-env->regs[r2 + 1] = deposit64(env->regs[r2 + 1], 0, 24, srclen);
-set_address_zero(env, r1, dest);
-set_address_zero(env, r2, src);
+/* We might have to zero-out some bits even if there was no action. */
+if (unlikely(!destlen || cc == 3)) {
+set_address_zero(env, r2, src);
+set_address_zero(env, r1, dest);
+return cc;
+} else if (!srclen) {
+set_address_zero(env, r2, src);
+}
 
+/*
+ * Only perform one type of type of operation (move/pad) in one step.
+ * Process up to 2k bytes.
+ */
+while (destlen) {
+cur_len = MIN(destlen, 2048);
+if (!srclen) {
+fast_memset(env, dest, pad, cur_len, ra);
+} else {
+cur_len = MIN(cur_len, srclen);
+
+fast_memmove(env, dest, src, cur_len, ra);
+src = wrap_address(env, src + cur_len);
+srclen -= cur_len;
+env->regs[r2 + 1] = deposit64(env->regs[r2 + 1], 0, 24, srclen);
+set_address_zero(env, r2, src);
+}
+dest = wrap_address(env, dest + cur_len);
+destlen -= cur_len;
+env->regs[r1 + 1] = deposit64(env->regs[r1 + 1], 0, 24, destlen);
+set_address_zero(env, r1, dest);
+
+/* TODO: Deliver interrupts. */
+}
 return cc;
 }
 
-- 
2.21.0




[Qemu-devel] [PATCH v2 19/28] s390x/tcg: MVCLU: Fault-safe handling

2019-09-06 Thread David Hildenbrand
The last remaining bit is padding with two bytes.

Signed-off-by: David Hildenbrand 
---
 target/s390x/mem_helper.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index f636f3a011..0366cbc753 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -900,15 +900,17 @@ static inline uint32_t do_mvcl(CPUS390XState *env,
 access_memset(env, *dest, pad, len, ra);
 *dest = wrap_address(env, *dest + len);
 } else {
+S390Access desta = access_prepare(env, *dest, len, MMU_DATA_STORE, ra);
+
 /* The remaining length selects the padding byte. */
 for (i = 0; i < len; (*destlen)--, i++) {
 if (*destlen & 1) {
-cpu_stb_data_ra(env, *dest, pad, ra);
+access_set_byte(env, , i, pad, ra);
 } else {
-cpu_stb_data_ra(env, *dest, pad >> 8, ra);
+access_set_byte(env, , i, pad >> 8, ra);
 }
-*dest = wrap_address(env, *dest + 1);
 }
+*dest = wrap_address(env, *dest + len);
 }
 
 return *destlen ? 3 : cc;
-- 
2.21.0




[Qemu-devel] [PATCH v2 14/28] s390x/tcg: Always use MMU_USER_IDX for CONFIG_USER_ONLY

2019-09-06 Thread David Hildenbrand
Although we basically ignore the index all the time for CONFIG_USER_ONLY,
let's simply skip all the checks and always return MMU_USER_IDX in
cpu_mmu_index() and get_mem_index().

Signed-off-by: David Hildenbrand 
---
 target/s390x/cpu.h   | 4 
 target/s390x/translate.c | 4 
 2 files changed, 8 insertions(+)

diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index 79202c0980..163dae13d7 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -328,6 +328,9 @@ extern const VMStateDescription vmstate_s390_cpu;
 
 static inline int cpu_mmu_index(CPUS390XState *env, bool ifetch)
 {
+#ifdef CONFIG_USER_ONLY
+return MMU_USER_IDX;
+#else
 if (!(env->psw.mask & PSW_MASK_DAT)) {
 return MMU_REAL_IDX;
 }
@@ -351,6 +354,7 @@ static inline int cpu_mmu_index(CPUS390XState *env, bool 
ifetch)
 default:
 abort();
 }
+#endif
 }
 
 static inline void cpu_get_tb_cpu_state(CPUS390XState* env, target_ulong *pc,
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index b76e10d832..50124520c9 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -318,6 +318,9 @@ static inline uint64_t ld_code4(CPUS390XState *env, 
uint64_t pc)
 
 static int get_mem_index(DisasContext *s)
 {
+#ifdef CONFIG_USER_ONLY
+return MMU_USER_IDX;
+#else
 if (!(s->base.tb->flags & FLAG_MASK_DAT)) {
 return MMU_REAL_IDX;
 }
@@ -333,6 +336,7 @@ static int get_mem_index(DisasContext *s)
 tcg_abort();
 break;
 }
+#endif
 }
 
 static void gen_exception(int excp)
-- 
2.21.0




[Qemu-devel] [PATCH v2 24/28] s390x/tcg: MVN: Fault-safe handling

2019-09-06 Thread David Hildenbrand
We can process a maximum of 256 bytes, crossing two pages.

Signed-off-by: David Hildenbrand 
---
 target/s390x/mem_helper.c | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index ba8a657e18..5e38b2c4d8 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -493,13 +493,21 @@ void HELPER(mvcin)(CPUS390XState *env, uint32_t l, 
uint64_t dest, uint64_t src)
 /* move numerics  */
 void HELPER(mvn)(CPUS390XState *env, uint32_t l, uint64_t dest, uint64_t src)
 {
+S390Access srca1, srca2, desta;
 uintptr_t ra = GETPC();
 int i;
 
-for (i = 0; i <= l; i++) {
-uint8_t v = cpu_ldub_data_ra(env, dest + i, ra) & 0xf0;
-v |= cpu_ldub_data_ra(env, src + i, ra) & 0x0f;
-cpu_stb_data_ra(env, dest + i, v, ra);
+/* MVN always copies one more byte than specified - maximum is 256 */
+l++;
+
+srca1 = access_prepare(env, src, l, MMU_DATA_LOAD, ra);
+srca2 = access_prepare(env, dest, l, MMU_DATA_LOAD, ra);
+desta = access_prepare(env, dest, l, MMU_DATA_STORE, ra);
+for (i = 0; i < l; i++) {
+const uint8_t x = (access_get_byte(env, , i, ra) & 0x0f) |
+  (access_get_byte(env, , i, ra) & 0xf0);
+
+access_set_byte(env, , i, x, ra);
 }
 }
 
-- 
2.21.0




[Qemu-devel] [PATCH v2 28/28] tests/tcg: target/s390x: Test MVO

2019-09-06 Thread David Hildenbrand
Let's add the simple test based on the example from the PoP.

Signed-off-by: David Hildenbrand 
---
 tests/tcg/s390x/Makefile.target |  1 +
 tests/tcg/s390x/mvo.c   | 25 +
 2 files changed, 26 insertions(+)
 create mode 100644 tests/tcg/s390x/mvo.c

diff --git a/tests/tcg/s390x/Makefile.target b/tests/tcg/s390x/Makefile.target
index 151dc075aa..6a3bfa8b29 100644
--- a/tests/tcg/s390x/Makefile.target
+++ b/tests/tcg/s390x/Makefile.target
@@ -6,3 +6,4 @@ TESTS+=ipm
 TESTS+=exrl-trt
 TESTS+=exrl-trtr
 TESTS+=pack
+TESTS+=mvo
diff --git a/tests/tcg/s390x/mvo.c b/tests/tcg/s390x/mvo.c
new file mode 100644
index 00..5546fe2a97
--- /dev/null
+++ b/tests/tcg/s390x/mvo.c
@@ -0,0 +1,25 @@
+#include 
+#include 
+
+int main(void)
+{
+uint8_t dest[6] = {0xff, 0x77, 0x88, 0x99, 0x0c, 0xff};
+uint8_t src[5] = {0xee, 0x12, 0x34, 0x56, 0xee};
+uint8_t expected[6] = {0xff, 0x01, 0x23, 0x45, 0x6c, 0xff};
+int i;
+
+asm volatile (
+"mvo 0(4,%[dest]),0(3,%[src])\n"
+:
+: [dest] "d" (dest + 1),
+  [src] "d" (src + 1)
+: "memory");
+
+for (i = 0; i < sizeof(expected); i++) {
+if (dest[i] != expected[i]) {
+fprintf(stderr, "bad data\n");
+return 1;
+}
+}
+return 0;
+}
-- 
2.21.0




[Qemu-devel] [PATCH v18 6/6] target-arm: kvm64: handle SIGBUS signal from kernel or KVM

2019-09-06 Thread Xiang Zheng
From: Dongjiu Geng 

Add a SIGBUS signal handler. In this handler, it checks the SIGBUS type,
translates the host VA delivered by host to guest PA, then fills this PA
to guest APEI GHES memory, then notifies guest according to the SIGBUS
type.

If guest accesses the poisoned memory, it generates Synchronous External
Abort(SEA). Then host kernel gets an APEI notification and calls
memory_failure() to unmapped the affected page in stage 2, finally
returns to guest.

Guest continues to access PG_hwpoison page, it will trap to KVM as
stage2 fault, then a SIGBUS_MCEERR_AR synchronous signal is delivered to
Qemu, Qemu records this error address into guest APEI GHES memory and
notifes guest using Synchronous-External-Abort(SEA).

Suggested-by: James Morse 
Signed-off-by: Dongjiu Geng 
Signed-off-by: Xiang Zheng 
---
 hw/acpi/acpi_ghes.c | 252 
 include/hw/acpi/acpi_ghes.h |  40 ++
 include/sysemu/kvm.h|   2 +-
 target/arm/kvm64.c  |  39 ++
 4 files changed, 332 insertions(+), 1 deletion(-)

diff --git a/hw/acpi/acpi_ghes.c b/hw/acpi/acpi_ghes.c
index 20c45179ff..2d17c88045 100644
--- a/hw/acpi/acpi_ghes.c
+++ b/hw/acpi/acpi_ghes.c
@@ -26,6 +26,168 @@
 #include "sysemu/sysemu.h"
 #include "qemu/error-report.h"
 
+/* Total size for Generic Error Status Block
+ * ACPI 6.2: 18.3.2.7.1 Generic Error Data,
+ * Table 18-380 Generic Error Status Block
+ */
+#define ACPI_GHES_GESB_SIZE 20
+/* The offset of Data Length in Generic Error Status Block */
+#define ACPI_GHES_GESB_DATA_LENGTH_OFFSET   12
+
+/* Record the value of data length for each error status block to avoid getting
+ * this value from guest.
+ */
+static uint32_t acpi_ghes_data_length[ACPI_GHES_ERROR_SOURCE_COUNT];
+
+/* Generic Error Data Entry
+ * ACPI 6.1: 18.3.2.7.1 Generic Error Data
+ */
+static void acpi_ghes_generic_error_data(GArray *table, QemuUUID section_type,
+uint32_t error_severity, uint16_t revision,
+uint8_t validation_bits, uint8_t flags,
+uint32_t error_data_length, QemuUUID fru_id,
+uint8_t *fru_text, uint64_t time_stamp)
+{
+QemuUUID uuid_le;
+
+/* Section Type */
+uuid_le = qemu_uuid_bswap(section_type);
+g_array_append_vals(table, uuid_le.data, ARRAY_SIZE(uuid_le.data));
+
+/* Error Severity */
+build_append_int_noprefix(table, error_severity, 4);
+/* Revision */
+build_append_int_noprefix(table, revision, 2);
+/* Validation Bits */
+build_append_int_noprefix(table, validation_bits, 1);
+/* Flags */
+build_append_int_noprefix(table, flags, 1);
+/* Error Data Length */
+build_append_int_noprefix(table, error_data_length, 4);
+
+/* FRU Id */
+uuid_le = qemu_uuid_bswap(fru_id);
+g_array_append_vals(table, uuid_le.data, ARRAY_SIZE(uuid_le.data));
+
+/* FRU Text */
+g_array_append_vals(table, fru_text, 20);
+/* Timestamp */
+build_append_int_noprefix(table, time_stamp, 8);
+}
+
+/* Generic Error Status Block
+ * ACPI 6.1: 18.3.2.7.1 Generic Error Data
+ */
+static void acpi_ghes_generic_error_status(GArray *table, uint32_t 
block_status,
+uint32_t raw_data_offset, uint32_t raw_data_length,
+uint32_t data_length, uint32_t error_severity)
+{
+/* Block Status */
+build_append_int_noprefix(table, block_status, 4);
+/* Raw Data Offset */
+build_append_int_noprefix(table, raw_data_offset, 4);
+/* Raw Data Length */
+build_append_int_noprefix(table, raw_data_length, 4);
+/* Data Length */
+build_append_int_noprefix(table, data_length, 4);
+/* Error Severity */
+build_append_int_noprefix(table, error_severity, 4);
+}
+
+/* UEFI 2.6: N.2.5 Memory Error Section */
+static void acpi_ghes_build_append_mem_cper(GArray *table,
+uint64_t error_physical_addr)
+{
+/*
+ * Memory Error Record
+ */
+
+/* Validation Bits */
+build_append_int_noprefix(table,
+  (1UL << 14) | /* Type Valid */
+  (1UL << 1) /* Physical Address Valid */,
+  8);
+/* Error Status */
+build_append_int_noprefix(table, 0, 8);
+/* Physical Address */
+build_append_int_noprefix(table, error_physical_addr, 8);
+/* Skip all the detailed information normally found in such a record */
+build_append_int_noprefix(table, 0, 48);
+/* Memory Error Type */
+build_append_int_noprefix(table, 0 /* Unknown error */, 1);
+/* Skip all the detailed information normally found in such a record */
+build_append_int_noprefix(table, 0, 7);
+}
+
+static int acpi_ghes_record_mem_error(uint64_t error_block_address,
+  uint64_t error_physical_addr,
+  uint32_t data_length)
+{
+GArray *block;
+uint64_t current_block_length;
+/* Memory Error Section 

[Qemu-devel] [PATCH v18 4/6] KVM: Move hwpoison page related functions into include/sysemu/kvm_int.h

2019-09-06 Thread Xiang Zheng
From: Dongjiu Geng 

kvm_hwpoison_page_add() and kvm_unpoison_all() will both be used by X86
and ARM platforms, so moving them into "include/sysemu/kvm_int.h" to
avoid duplicate code.

Signed-off-by: Dongjiu Geng 
Signed-off-by: Xiang Zheng 
---
 accel/kvm/kvm-all.c  | 33 +
 include/sysemu/kvm_int.h | 23 +++
 target/arm/kvm.c |  3 +++
 target/i386/kvm.c| 34 --
 4 files changed, 59 insertions(+), 34 deletions(-)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index b09bad0804..c6c052ba57 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -821,6 +821,39 @@ int kvm_vm_check_extension(KVMState *s, unsigned int 
extension)
 return ret;
 }
 
+typedef struct HWPoisonPage {
+ram_addr_t ram_addr;
+QLIST_ENTRY(HWPoisonPage) list;
+} HWPoisonPage;
+
+static QLIST_HEAD(, HWPoisonPage) hwpoison_page_list =
+QLIST_HEAD_INITIALIZER(hwpoison_page_list);
+
+void kvm_unpoison_all(void *param)
+{
+HWPoisonPage *page, *next_page;
+
+QLIST_FOREACH_SAFE(page, _page_list, list, next_page) {
+QLIST_REMOVE(page, list);
+qemu_ram_remap(page->ram_addr, TARGET_PAGE_SIZE);
+g_free(page);
+}
+}
+
+void kvm_hwpoison_page_add(ram_addr_t ram_addr)
+{
+HWPoisonPage *page;
+
+QLIST_FOREACH(page, _page_list, list) {
+if (page->ram_addr == ram_addr) {
+return;
+}
+}
+page = g_new(HWPoisonPage, 1);
+page->ram_addr = ram_addr;
+QLIST_INSERT_HEAD(_page_list, page, list);
+}
+
 static uint32_t adjust_ioeventfd_endianness(uint32_t val, uint32_t size)
 {
 #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
diff --git a/include/sysemu/kvm_int.h b/include/sysemu/kvm_int.h
index 72b2d1b3ae..3ad49f9a28 100644
--- a/include/sysemu/kvm_int.h
+++ b/include/sysemu/kvm_int.h
@@ -41,4 +41,27 @@ typedef struct KVMMemoryListener {
 void kvm_memory_listener_register(KVMState *s, KVMMemoryListener *kml,
   AddressSpace *as, int as_id);
 
+/**
+ * kvm_hwpoison_page_add:
+ *
+ * Parameters:
+ *  @ram_addr: the address in the RAM for the poisoned page
+ *
+ * Add a poisoned page to the list
+ *
+ * Return: None.
+ */
+void kvm_hwpoison_page_add(ram_addr_t ram_addr);
+
+/**
+ * kvm_unpoison_all:
+ *
+ * Parameters:
+ *  @param: some data may be passed to this function
+ *
+ * Free and remove all the poisoned pages in the list
+ *
+ * Return: None.
+ */
+void kvm_unpoison_all(void *param);
 #endif
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index b2eaa50b8d..3a110be7b8 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -20,6 +20,7 @@
 #include "sysemu/sysemu.h"
 #include "sysemu/kvm.h"
 #include "sysemu/kvm_int.h"
+#include "sysemu/reset.h"
 #include "kvm_arm.h"
 #include "cpu.h"
 #include "trace.h"
@@ -195,6 +196,8 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
 
 cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
 
+qemu_register_reset(kvm_unpoison_all, NULL);
+
 return 0;
 }
 
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index 8023c679ea..4f9f3682ee 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -476,40 +476,6 @@ uint32_t kvm_arch_get_supported_msr_feature(KVMState *s, 
uint32_t index)
 return msr_data.entries[0].data;
 }
 
-
-typedef struct HWPoisonPage {
-ram_addr_t ram_addr;
-QLIST_ENTRY(HWPoisonPage) list;
-} HWPoisonPage;
-
-static QLIST_HEAD(, HWPoisonPage) hwpoison_page_list =
-QLIST_HEAD_INITIALIZER(hwpoison_page_list);
-
-static void kvm_unpoison_all(void *param)
-{
-HWPoisonPage *page, *next_page;
-
-QLIST_FOREACH_SAFE(page, _page_list, list, next_page) {
-QLIST_REMOVE(page, list);
-qemu_ram_remap(page->ram_addr, TARGET_PAGE_SIZE);
-g_free(page);
-}
-}
-
-static void kvm_hwpoison_page_add(ram_addr_t ram_addr)
-{
-HWPoisonPage *page;
-
-QLIST_FOREACH(page, _page_list, list) {
-if (page->ram_addr == ram_addr) {
-return;
-}
-}
-page = g_new(HWPoisonPage, 1);
-page->ram_addr = ram_addr;
-QLIST_INSERT_HEAD(_page_list, page, list);
-}
-
 static int kvm_get_mce_cap_supported(KVMState *s, uint64_t *mce_cap,
  int *max_banks)
 {
-- 
2.19.1





Re: [Qemu-devel] QEMU as ISS (Instruction Set Simulator)

2019-09-06 Thread Alex Bennée


Libo Zhou  writes:

> Hi Alex,
>
>
> I just need to log the registers and memory after the program finishes
> its execution. Is it possible to add this functionality myself?

You'll need to set some sort of breakpoint on the last instruction so
gdb can inspect things before the program is unloaded. I think it's
possible to wire poweroff events to the gdbstub but I haven't looked
into that myself.

> As for the GDB option, can you tell me the specific steps to do that? I've 
> tried it myself but I had no luck getting it running due to me being new to 
> all this.
>

For linux-user:

  $QEMU -g 1234 $PRG

for system emulation

  $QEMU -s -S

and then on the gdb end:

  gdb $BIN -ex "target remote localhost:1234"

and then you can operate as you normally do with a gdb session. GDB has
two scripting interfaces. The command mode is basically a list of gdb
commands but might work for what you want. If you want to be a bit more
programatic you can use python. See the example in
tests/guest-debug/test-gdbstub.py

>
> Thanks,
> Libo
>
>
>
> -- Original --
> From:  "Alex Bennée";;
> Send time: Thursday, Sep 5, 2019 8:58 PM
> To: "qemu-devel";
> Cc: "Aleksandar Markovic";
> Subject:  Re: [Qemu-devel] QEMU as ISS (Instruction Set Simulator)
>
>
>
>
> Libo Zhou  writes:
>
>> Do you know where in the source file I should look into to add my custom 
>> logging functionality?
>>
>>
>> Or, would you suggest using gdb to look at my target register and memory 
>> contents? The answer in this link below looks really promising. I'm gonna 
>> give it a try first.
>>
>> https://stackoverflow.com/questions/39503997/how-to-run-a-single-line-of-assembly-then-see-r1-and-condition-flags
>
> The gdbstub should allow you do full introspection and adding
> additional registers is fairly easy, see FOO_gdb_[set|get]_reg helpers
> in the appropriate target/FOO directories.
>
>> However, if I am able to customize log, it will be super convenient.
>
> So you want something above what -d cpu will show you?
>
>>
>>
>>
>> Cheers,
>>
>> Libo
>>
>>
>>
>> -- Original --
>> From:  "Aleksandar Markovic";;
>> Send time: Thursday, Sep 5, 2019 6:54 PM
>> To: "Libo Zhou";
>> Cc: "qemu-devel";
>> Subject:  Re: [Qemu-devel] QEMU as ISS (Instruction Set Simulator)
>>
>>
>>
>> 04.09.2019. 05.23, "Libo Zhou"  ?е написао/ла:
>>>
>>> Hi Aleksandar,
>>>
>>> I have spent some time looking at your MXU ASE patch. It's super helpful.
>> I need to do exactly the same thing as you did.
>>>
>>> Now I just need a way to observe the memory and register file contents to
>> debug my instruction set simulator. I played with the "-d" switch to log a
>> bunch of information, but it seems that none of the items is of my
>> interest. The "-d cpu_reset" option displays all zeros in the GPR log.
>>>
>>
>> It looks you need a custom logging tailored to your needs, based on
>> intercepting the instructions you added.
>>
>> Aleksandar
>>
>>> Please take your time, as I fully understand you need to work on Qemu
>> while answering all my questions. Again, thank you very much for your help!
>>>
>>> Cheers,
>>> Libo
>>>


--
Alex Bennée



Re: [Qemu-devel] [RFC Patch] xen/pt: Emulate FLR capability

2019-09-06 Thread Paul Durrant
> -Original Message-
> From: Chao Gao 
> Sent: 06 September 2019 10:01
> To: Roger Pau Monne 
> Cc: xen-de...@lists.xenproject.org; qemu-devel@nongnu.org; Stefano Stabellini
> ; Anthony Perard ; Paul 
> Durrant
> ; Jan Beulich 
> Subject: Re: [RFC Patch] xen/pt: Emulate FLR capability
> 
> On Thu, Aug 29, 2019 at 12:21:11PM +0200, Roger Pau Monné wrote:
> >On Thu, Aug 29, 2019 at 05:02:27PM +0800, Chao Gao wrote:
> >> Currently, for a HVM on Xen, no reset method is virtualized. So in a VM's
> >> perspective, assigned devices cannot be reset. But some devices rely on PCI
> >> reset to recover from hardware hangs. When being assigned to a VM, those
> >> devices cannot be reset and won't work any longer if a hardware hang 
> >> occurs.
> >> We have to reboot VM to trigger PCI reset on host to recover the device.
> >>
> >> This patch exposes FLR capability to VMs if the assigned device can be 
> >> reset on
> >> host. When VM initiates an FLR to a device, qemu cleans up the device 
> >> state,
> >> (including disabling of intx and/or MSI and unmapping BARs from guest, 
> >> deleting
> >> emulated registers), then initiate PCI reset through 'reset' knob under the
> >> device's sysfs, finally initialize the device again.
> >
> >I think you likely need to deassign the device from the VM, perform
> >the reset, and then assign the device again, so that there's no Xen
> >internal state carried over prior to the reset?
> 
> Yes. It is the safest way. But here I want to present the feature as FLR
> (such that the device driver in guest can issue PCI reset whenever
> needed and no change is needed to device driver).  Current device
> deassignment notifies guest that the device is going to be removed
> It is not the standard PCI reset. Is it possible to make guest unaware
> of the device deassignment to emulate a standard PCI reset?

It should be, I would have thought. QEMU emulates all config space so any 
config access by the guest would be unaffected by de-assignment. The BARs and 
interrupts would be unmapped... but that's what you'd want anyway.

> In my mind,
> we can expose do_pci_remove/add to qemu or rewrite them in qemu (but
> don't remove the device from guest's PCI hierarchy). Do you think it is
> the right direction?

Long term I think we want to get pass-through emulation out of QEMU and into 
Xen.

  Paul

> 
> Thanks
> Chao



Re: [Qemu-devel] [EXTERNAL][PATCH for 4.2 v4 12/12] linux-user: Add support for semtimedop() syscall

2019-09-06 Thread Laurent Vivier
Le 31/07/2019 à 20:22, Aleksandar Markovic a écrit :
>> From: Aleksandar Rikalo 
>>
>> Add support for semtimedop() emulation. It is based on invocation
>> of safe_semtimedop().
> 
> Hi, Laurent,
> 
> Aleksandar R. is considering submitting this part too:
> 
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index b5bc6e4..0e56b8d 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -4194,6 +4194,17 @@ static abi_long do_ipc(CPUArchState *cpu_env,
>  case IPCOP_shmctl:
>  ret = do_shmctl(first, second, ptr);
>  break;
> +#ifdef __NR_ipc
> +case IPCOP_semtimedop: {
> +struct sembuf sops[nsops];
> +if (target_to_host_sembuf(first, ptr, second)) {
> +ret = -TARGET_EFAULT;
> +} else {
> +ret = get_errno(safe_ipc(IPCOP_semtimedop, first, second, 0, 
> sops, 0));
> +}
> +break;
> +}
> +#endif

You should do something like that:

case IPCOP_semtimedop
ret = do_semtimedop( ... );
break;

Thanks,
Laurent





Re: [Qemu-devel] [PATCH v6 3/8] linux-user: Add support for FIOGETOWN and FIOSETOWN ioctls

2019-09-06 Thread Laurent Vivier
Le 04/09/2019 à 14:59, Aleksandar Markovic a écrit :
> From: Aleksandar Markovic 
> 
> FIOGETOWN and FIOSETOWN ioctls have platform-specific definitions,
> hence non-standard definition in QEMU too.
> 
> Other than that, they both have a single integer argument, and their
> functionality is emulated in a straightforward way.
> 
> Signed-off-by: Aleksandar Markovic 
> ---
>  linux-user/ioctls.h   | 2 ++
>  linux-user/syscall_defs.h | 4 
>  2 files changed, 6 insertions(+)
> 
> diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
> index cd9b6f9..1830de9 100644
> --- a/linux-user/ioctls.h
> +++ b/linux-user/ioctls.h
> @@ -177,6 +177,8 @@
>  #endif
>  #endif /* CONFIG_USBFS */
>  
> +  IOCTL(FIOGETOWN, IOC_R, MK_PTR(TYPE_INT))
> +  IOCTL(FIOSETOWN, IOC_W, MK_PTR(TYPE_INT))
>IOCTL(SIOCATMARK, IOC_R, MK_PTR(TYPE_INT))
>IOCTL(SIOCGIFNAME, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_int_ifreq)))
>IOCTL(SIOCGIFFLAGS, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
> diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
> index 19a1d39..498223b 100644
> --- a/linux-user/syscall_defs.h
> +++ b/linux-user/syscall_defs.h
> @@ -758,10 +758,14 @@ struct target_pollfd {
>  
>  #if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SH4) ||  
>   \
> defined(TARGET_XTENSA)
> +#define TARGET_FIOGETOWN   TARGET_IOR('f', 123, int)
> +#define TARGET_FIOSETOWN   TARGET_IOW('f', 124, int)
>  #define TARGET_SIOCATMARK  TARGET_IOR('s', 7, int)
>  #define TARGET_SIOCSPGRP   TARGET_IOW('s', 8, pid_t)
>  #define TARGET_SIOCGPGRP   TARGET_IOR('s', 9, pid_t)
>  #else
> +#define TARGET_FIOGETOWN   0x8903
> +#define TARGET_FIOSETOWN   0x8901
>  #define TARGET_SIOCATMARK  0x8905
>  #define TARGET_SIOCSPGRP   0x8902
>  #define TARGET_SIOCGPGRP   0x8904
> 

Reviewed-by: Laurent Vivier 



Re: [Qemu-devel] [PATCH v6 5/8] linux-user: Add support for FDMSGON and FDMSGOFF ioctls

2019-09-06 Thread Laurent Vivier
Le 04/09/2019 à 14:59, Aleksandar Markovic a écrit :
> From: Aleksandar Markovic 
> 
> FDMSGON and FDMSGOFF switch informational messages of floppy drives
> on and off.
> 
> Signed-off-by: Aleksandar Markovic 
> Reviewed-by: Laurent Vivier 
> ---
>  linux-user/ioctls.h   | 2 ++
>  linux-user/syscall_defs.h | 2 ++
>  2 files changed, 4 insertions(+)
> 
> diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
> index bc19448..b253469 100644
> --- a/linux-user/ioctls.h
> +++ b/linux-user/ioctls.h
> @@ -112,6 +112,8 @@
>   IOCTL(BLKZEROOUT, IOC_W, MK_PTR(MK_ARRAY(TYPE_ULONGLONG, 2)))
>  #endif
>  
> + IOCTL(FDMSGON, 0, TYPE_NULL)
> + IOCTL(FDMSGOFF, 0, TYPE_NULL)
>   IOCTL(FDFLUSH, 0, TYPE_NULL)
>  
>  #ifdef FIBMAP
> diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
> index 917202a..4e33ef3 100644
> --- a/linux-user/syscall_defs.h
> +++ b/linux-user/syscall_defs.h
> @@ -890,6 +890,8 @@ struct target_pollfd {
>  
>  /* From  */
>  
> +#define TARGET_FDMSGONTARGET_IO(2, 0x45)
> +#define TARGET_FDMSGOFF   TARGET_IO(2, 0x46)
>  #define TARGET_FDFLUSHTARGET_IO(2, 0x4b)
>  
>  #define TARGET_FIBMAP TARGET_IO(0x00,1)  /* bmap access */
> 

Reviewed-by: Laurent Vivier 



Re: [Qemu-devel] [PATCH v6 7/8] linux-user: Add support for FDFMTBEG, FDFMTTRK, and FDFMTEND ioctls

2019-09-06 Thread Laurent Vivier
Le 04/09/2019 à 14:59, Aleksandar Markovic a écrit :
> From: Aleksandar Markovic 
> 
> FDFMTBEG, FDFMTTRK, and FDFMTEND ioctls provide means for controlling
> formatting of a floppy drive.
> 
> Signed-off-by: Aleksandar Markovic 
> ---
>  linux-user/ioctls.h| 3 +++
>  linux-user/syscall_defs.h  | 3 +++
>  linux-user/syscall_types.h | 5 +
>  3 files changed, 11 insertions(+)
> 
> diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
> index c6b9d6a..622874b 100644
> --- a/linux-user/ioctls.h
> +++ b/linux-user/ioctls.h
> @@ -114,6 +114,9 @@
>  
>   IOCTL(FDMSGON, 0, TYPE_NULL)
>   IOCTL(FDMSGOFF, 0, TYPE_NULL)
> + IOCTL(FDFMTBEG, 0, TYPE_NULL)
> + IOCTL(FDFMTTRK, IOC_W, MK_PTR(MK_STRUCT(STRUCT_format_descr)))
> + IOCTL(FDFMTEND, 0, TYPE_NULL)
>   IOCTL(FDFLUSH, 0, TYPE_NULL)
>   IOCTL(FDRESET, 0, TYPE_NULL)
>   IOCTL(FDRAWCMD, 0, TYPE_NULL)
> diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
> index fa69c6a..834a085 100644
> --- a/linux-user/syscall_defs.h
> +++ b/linux-user/syscall_defs.h
> @@ -892,6 +892,9 @@ struct target_pollfd {
>  
>  #define TARGET_FDMSGONTARGET_IO(2, 0x45)
>  #define TARGET_FDMSGOFF   TARGET_IO(2, 0x46)
> +#define TARGET_FDFMTBEG   TARGET_IO(2, 0x47)
> +#define TARGET_FDFMTTRK  TARGET_IOW(2, 0x48, struct target_format_descr)
> +#define TARGET_FDFMTEND   TARGET_IO(2, 0x49)
>  #define TARGET_FDFLUSHTARGET_IO(2, 0x4b)
>  #define TARGET_FDRESETTARGET_IO(2, 0x54)
>  #define TARGET_FDRAWCMD   TARGET_IO(2, 0x58)
> diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h
> index 4e36983..d82d1a5 100644
> --- a/linux-user/syscall_types.h
> +++ b/linux-user/syscall_types.h
> @@ -261,6 +261,11 @@ STRUCT(blkpg_ioctl_arg,
> TYPE_INT, /* datalen */
> TYPE_PTRVOID) /* data */
>  
> +STRUCT(format_descr,
> +   TYPE_INT, /* device */
> +   TYPE_INT, /* head */
> +   TYPE_INT) /* track */
> +
>  #if defined(CONFIG_USBFS)
>  /* usb device ioctls */
>  STRUCT(usbdevfs_ctrltransfer,
> 

Reviewed-by: Laurent Vivier 



Re: [Qemu-devel] [PATCH] hw/arm/raspi: avoid reparenting the sd card during qbus tree reset

2019-09-06 Thread Peter Maydell
On Wed, 4 Sep 2019 at 17:23, Damien Hedde  wrote:
>
> In the raspi machine, the sd card can be on several sd bus (in reality
> there is one bus but several controllers). It is initially created in
> the "sd-bus" child in the gpio peripheral. Then is moved (parent bus
> changes) during machine reset in the "sdhci-bus". It can be moved again
> by software between the "sdhci-bus" and another bus ("bcm2835-sdhost-bus").
> Here's the corresponding qbus tree of the raspi machine:
>  + sysbus
>* bcm2835_gpio
>  + sd-bus
>* sd-card
>* bcm2835-sdhost
>  + bcm2835-sdhost-bus
>* generic-sdhci
>  + sdhci-bus
>
> During the initial machine reset, the sd card is moved. Since reset is
> based on qbus tree, moving the card during the reset seems odd (it changes
> the qbus tree). In this case, because of the order the qbus tree is
> walked, the sd card ends up being reset twice; the effective reset order call
> follows:
>  1 sd-card
>  2 sd-bus
>  3 bcm2835_gpio-> move the sd-card to sdhci_bus
>  4 bcm2835-sdhost-bus
>  5 bcm2835-sdhost
>  6 sd-card (again)
>  7 sdhci-bus
>  8 generic-sdhci
>
> This patch adds a raspi machine reset method which moves the sd card
> to the sdhci-bus before doing the whole reset (which will try to do the
> move too). By anticipating the move we avoid changing the qdev tree while
> resetting it.
>
> In consequence the step 1 is skipped in the previous list: when reset starts
> the sd-card is already not a child of bcm2835_gpio.

The solution proposed in this patch pushes something that should
really be the business just of the SoC model out to the machine
model level; it would be nice to be able to avoid that.

thanks
-- PMM



Re: [Qemu-devel] [PATCH RFC] gpio: Add Virtual Aggregator GPIO Driver

2019-09-06 Thread Geert Uytterhoeven
Hi Bartosz,

On Fri, Jul 12, 2019 at 11:27 AM Bartosz Golaszewski
 wrote:
> wt., 9 lip 2019 o 17:59 Geert Uytterhoeven  napisał(a):
> > On Tue, Jul 9, 2019 at 4:59 PM Bartosz Golaszewski
> >  wrote:
> > > pon., 8 lip 2019 o 12:24 Geert Uytterhoeven  
> > > napisał(a):
> > > > On Mon, Jul 8, 2019 at 11:45 AM Bartosz Golaszewski
> > > >  wrote:
> > > > > pt., 5 lip 2019 o 18:05 Geert Uytterhoeven  
> > > > > napisał(a):
> > > > > > GPIO controllers are exported to userspace using /dev/gpiochip*
> > > > > > character devices.  Access control to these devices is provided by
> > > > > > standard UNIX file system permissions, on an all-or-nothing basis:
> > > > > > either a GPIO controller is accessible for a user, or it is not.
> > > > > > Currently no mechanism exists to control access to individual GPIOs.
> > > > > >
> > > > > > Hence add a virtual GPIO driver to aggregate existing GPIOs (up to 
> > > > > > 32),
> > > > > > and expose them as a new gpiochip.  This is useful for implementing
> > > > > > access control, and assigning a set of GPIOs to a specific user.
> > > > > > Furthermore, it would simplify and harden exporting GPIOs to a 
> > > > > > virtual
> > > > > > machine, as the VM can just grab the full virtual GPIO controller, 
> > > > > > and
> > > > > > no longer needs to care about which GPIOs to grab and which not,
> > > > > > reducing the attack surface.
> > > > > >
> > > > > > Virtual GPIO controllers are instantiated by writing to the 
> > > > > > "new_device"
> > > > > > attribute file in sysfs:
> > > > > >
> > > > > > $ echo "  [ ...]"
> > > > > >"[,   [ ...]] ...]"
> > > > > > > /sys/bus/platform/drivers/gpio-virt-agg/new_device
> > > > > >
> > > > > > Likewise, virtual GPIO controllers can be destroyed after use:
> > > > > >
> > > > > > $ echo gpio-virt-agg. \
> > > > > > > /sys/bus/platform/drivers/gpio-virt-agg/delete_device
> >
> > > Am I doing it right? I'm trying to create a device and am only getting 
> > > this:
> > >
> > > # echo gpiochip2 23 > new_device
> > > [  707.507039] gpio-virt-agg gpio-virt-agg.0: Cannot find gpiochip 
> > > gpiochip2
> > >
> > > gpiochip2 *does* exist in the system.
> >
> > Please try the name of the platform device instead.
> > I.e. for my koelsch (R-Car M2-W), it needs "e6052000.gpio" instead
> > of "gpiochip2".
> >
> > Probably the driver should match on both.
> >
> > > I see. I'll try to review it more thoroughly once I get to play with
> > > it. So far I'm stuck on creating the virtual chip.
>
> This is not a show-stopper but one thing that's bothering me in this
> is that lines used by the aggregator are considered 'used' in regard
> to the original chip. I'm wondering how much effort would it take to
> have them be 'muxed' into two (real and virtual) chips at once.

Is that really what you want?
If a GPIO is aggregated with othrs, it's intended to be used only through
the aggregator, isn't it?

> Other than that - seems to works pretty nice other than the matching
> by chip name and by line names.

Thanks, working on that...

Gr{oetje,eeting}s,

Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds



[Qemu-devel] [PATCH] tests/qemu-iotests/check: Replace "tests" with "iotests" in final status text

2019-09-06 Thread Thomas Huth
When running "make check -j8" or something similar, the iotests are
running in parallel with the other tests. So when they are printing
out "Passed all xx tests" or a similar status message at the end,
it might not be quite clear that this message belongs to the iotests,
since the output might be mixed with the other tests. Thus change the
word "tests" here to "iotests" instead to avoid confusion.

Signed-off-by: Thomas Huth 
---
 tests/qemu-iotests/check | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/tests/qemu-iotests/check b/tests/qemu-iotests/check
index c24874ff4a..2f1cf72abc 100755
--- a/tests/qemu-iotests/check
+++ b/tests/qemu-iotests/check
@@ -694,12 +694,12 @@ END{ if (NR > 0) {
 if [ ! -z "$n_bad" -a $n_bad != 0 ]
 then
 echo "Failures:$bad"
-echo "Failed $n_bad of $try tests"
+echo "Failed $n_bad of $try iotests"
 echo "Failures:$bad" | fmt >>check.log
-echo "Failed $n_bad of $try tests" >>check.log
+echo "Failed $n_bad of $try iotests" >>check.log
 else
-echo "Passed all $try tests"
-echo "Passed all $try tests" >>check.log
+echo "Passed all $try iotests"
+echo "Passed all $try iotests" >>check.log
 fi
 needwrap=false
 fi
-- 
2.18.1




Re: [Qemu-devel] [PATCH v2 04/13] qcrypto-luks: don't overwrite cipher_mode in header

2019-09-06 Thread Daniel P . Berrangé
On Mon, Aug 26, 2019 at 04:50:54PM +0300, Maxim Levitsky wrote:
> This way we can store the header we loaded, which
> will be used in key management code
> 
> Signed-off-by: Maxim Levitsky 
> ---
>  crypto/block-luks.c | 9 ++---
>  1 file changed, 6 insertions(+), 3 deletions(-)
> 
> diff --git a/crypto/block-luks.c b/crypto/block-luks.c
> index f12fa2d270..e9ae3f6baa 100644
> --- a/crypto/block-luks.c
> +++ b/crypto/block-luks.c
> @@ -645,6 +645,7 @@ qcrypto_block_luks_open(QCryptoBlock *block,
>  QCryptoHashAlgorithm hash;
>  QCryptoHashAlgorithm ivhash;
>  g_autofree char *password = NULL;
> +g_autofree char *cipher_mode = NULL;
>  
>  if (!(flags & QCRYPTO_BLOCK_OPEN_NO_IO)) {
>  if (!options->u.luks.key_secret) {
> @@ -701,6 +702,8 @@ qcrypto_block_luks_open(QCryptoBlock *block,
>  goto fail;
>  }
>  
> +cipher_mode = g_strdup(luks->header.cipher_mode);
> +
>  /*
>   * The cipher_mode header contains a string that we have
>   * to further parse, of the format
> @@ -709,11 +712,11 @@ qcrypto_block_luks_open(QCryptoBlock *block,
>   *
>   * eg  cbc-essiv:sha256, cbc-plain64
>   */
> -ivgen_name = strchr(luks->header.cipher_mode, '-');
> +ivgen_name = strchr(cipher_mode, '-');
>  if (!ivgen_name) {
>  ret = -EINVAL;
>  error_setg(errp, "Unexpected cipher mode string format %s",
> -   luks->header.cipher_mode);
> +cipher_mode);

nitpick - align with the (

>  goto fail;
>  }
>  *ivgen_name = '\0';
> @@ -735,7 +738,7 @@ qcrypto_block_luks_open(QCryptoBlock *block,
>  }
>  }
>  
> -ciphermode = 
> qcrypto_block_luks_cipher_mode_lookup(luks->header.cipher_mode,
> +ciphermode = qcrypto_block_luks_cipher_mode_lookup(cipher_mode,
> _err);
>  if (local_err) {
>  ret = -ENOTSUP;

Reviewed-by: Daniel P. Berrangé 


Regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|



Re: [Qemu-devel] [PATCH v2 03/13] qcrypto-luks: rename some fields in QCryptoBlockLUKSHeader

2019-09-06 Thread Daniel P . Berrangé
On Mon, Aug 26, 2019 at 04:50:53PM +0300, Maxim Levitsky wrote:
> * key_bytes -> master_key_len
> * payload_offset = payload_offset_sector (to emphasise that this isn't byte 
> offset)
> * key_offset -> key_offset_sector - same as above for luks slots
> 
> Signed-off-by: Maxim Levitsky 
> ---
>  crypto/block-luks.c | 91 +++--
>  1 file changed, 47 insertions(+), 44 deletions(-)

Reviewed-by: Daniel P. Berrangé 


Regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|



[Qemu-devel] [PATCH v3 3/4] target/arm: remove run time semihosting checks

2019-09-06 Thread Alex Bennée
Now we do all our checking and use a common EXCP_SEMIHOST for
semihosting operations we can make helper code a lot simpler.

Signed-off-by: Alex Bennée 
Reviewed-by: Richard Henderson 
---
v2
  - fix re-base conflicts
  - hoist EXCP_SEMIHOST check
  - comment cleanups
v5
  - move CONFIG_TCG ifdefs
---
 target/arm/helper.c | 96 +++--
 1 file changed, 22 insertions(+), 74 deletions(-)

diff --git a/target/arm/helper.c b/target/arm/helper.c
index 507026c9154..a87ae6d46a1 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -8339,88 +8339,32 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
   new_el, env->pc, pstate_read(env));
 }
 
-static inline bool check_for_semihosting(CPUState *cs)
-{
+/*
+ * Do semihosting call and set the appropriate return value. All the
+ * permission and validity checks have been done at translate time.
+ *
+ * We only see semihosting exceptions in TCG only as they are not
+ * trapped to the hypervisor in KVM.
+ */
 #ifdef CONFIG_TCG
-/* Check whether this exception is a semihosting call; if so
- * then handle it and return true; otherwise return false.
- */
+static void handle_semihosting(CPUState *cs)
+{
 ARMCPU *cpu = ARM_CPU(cs);
 CPUARMState *env = >env;
 
 if (is_a64(env)) {
-if (cs->exception_index == EXCP_SEMIHOST) {
-/* This is always the 64-bit semihosting exception.
- * The "is this usermode" and "is semihosting enabled"
- * checks have been done at translate time.
- */
-qemu_log_mask(CPU_LOG_INT,
-  "...handling as semihosting call 0x%" PRIx64 "\n",
-  env->xregs[0]);
-env->xregs[0] = do_arm_semihosting(env);
-return true;
-}
-return false;
+qemu_log_mask(CPU_LOG_INT,
+  "...handling as semihosting call 0x%" PRIx64 "\n",
+  env->xregs[0]);
+env->xregs[0] = do_arm_semihosting(env);
 } else {
-uint32_t imm;
-
-/* Only intercept calls from privileged modes, to provide some
- * semblance of security.
- */
-if (cs->exception_index != EXCP_SEMIHOST &&
-(!semihosting_enabled() ||
- ((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR))) {
-return false;
-}
-
-switch (cs->exception_index) {
-case EXCP_SEMIHOST:
-/* This is always a semihosting call; the "is this usermode"
- * and "is semihosting enabled" checks have been done at
- * translate time.
- */
-break;
-case EXCP_SWI:
-/* Check for semihosting interrupt.  */
-if (env->thumb) {
-imm = arm_lduw_code(env, env->regs[15] - 2, arm_sctlr_b(env))
-& 0xff;
-if (imm == 0xab) {
-break;
-}
-} else {
-imm = arm_ldl_code(env, env->regs[15] - 4, arm_sctlr_b(env))
-& 0xff;
-if (imm == 0x123456) {
-break;
-}
-}
-return false;
-case EXCP_BKPT:
-/* See if this is a semihosting syscall.  */
-if (env->thumb) {
-imm = arm_lduw_code(env, env->regs[15], arm_sctlr_b(env))
-& 0xff;
-if (imm == 0xab) {
-env->regs[15] += 2;
-break;
-}
-}
-return false;
-default:
-return false;
-}
-
 qemu_log_mask(CPU_LOG_INT,
   "...handling as semihosting call 0x%x\n",
   env->regs[0]);
 env->regs[0] = do_arm_semihosting(env);
-return true;
 }
-#else
-return false;
-#endif
 }
+#endif
 
 /* Handle a CPU exception for A and R profile CPUs.
  * Do any appropriate logging, handle PSCI calls, and then hand off
@@ -8451,13 +8395,17 @@ void arm_cpu_do_interrupt(CPUState *cs)
 return;
 }
 
-/* Semihosting semantics depend on the register width of the
- * code that caused the exception, not the target exception level,
- * so must be handled here.
+/*
+ * Semihosting semantics depend on the register width of the code
+ * that caused the exception, not the target exception level, so
+ * must be handled here.
  */
-if (check_for_semihosting(cs)) {
+#ifdef CONFIG_TCG
+if (cs->exception_index == EXCP_SEMIHOST) {
+handle_semihosting(cs);
 return;
 }
+#endif
 
 /* Hooks may change global state so BQL should be held, also the
  * BQL needs to be held for any modification of
-- 
2.20.1




[Qemu-devel] [PATCH v3 2/4] target/arm: handle A-profile semihosting at translate time

2019-09-06 Thread Alex Bennée
As for the other semihosting calls we can resolve this at translate
time.

Signed-off-by: Alex Bennée 

---
v2
  - update for change to gen_exception_internal_insn API
v3
  - update for decode tree, merge T32 & A32 commits
  - dropped r-b due to changes
---
 target/arm/translate.c | 19 +++
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/target/arm/translate.c b/target/arm/translate.c
index 4cda7812bcb..ed4a97cfb44 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -10222,14 +10222,25 @@ static bool trans_CBZ(DisasContext *s, arg_CBZ *a)
 }
 
 /*
- * Supervisor call
+ * Supervisor call - both T32 & A32 come here so we need to check
+ * which mode we are in when checking for semihosting.
  */
 
 static bool trans_SVC(DisasContext *s, arg_SVC *a)
 {
-gen_set_pc_im(s, s->base.pc_next);
-s->svc_imm = a->imm;
-s->base.is_jmp = DISAS_SWI;
+const uint32_t semihost_imm = s->thumb ? 0xab : 0x123456;
+
+if (semihosting_enabled() &&
+#ifndef CONFIG_USER_ONLY
+s->current_el != 0 &&
+#endif
+(a->imm == semihost_imm)) {
+gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST);
+} else {
+gen_set_pc_im(s, s->base.pc_next);
+s->svc_imm = a->imm;
+s->base.is_jmp = DISAS_SWI;
+}
 return true;
 }
 
-- 
2.20.1




[Qemu-devel] [PATCH v3 4/4] atomic_template: fix indentation in GEN_ATOMIC_HELPER

2019-09-06 Thread Alex Bennée
From: "Emilio G. Cota" 

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

diff --git a/accel/tcg/atomic_template.h b/accel/tcg/atomic_template.h
index df9c8388178..287433d809b 100644
--- a/accel/tcg/atomic_template.h
+++ b/accel/tcg/atomic_template.h
@@ -149,7 +149,7 @@ ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong 
addr,
 
 #define GEN_ATOMIC_HELPER(X)\
 ABI_TYPE ATOMIC_NAME(X)(CPUArchState *env, target_ulong addr,   \
- ABI_TYPE val EXTRA_ARGS)   \
+ABI_TYPE val EXTRA_ARGS)\
 {   \
 ATOMIC_MMU_DECLS;   \
 DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;   \
-- 
2.20.1




[Qemu-devel] [PATCH v3 0/4] semihosting fixes

2019-09-06 Thread Alex Bennée
Hi Peter,

I've re-based and re-tested on the post-decodetree changes. In the end
I merged the A32/T32 patches and dropped Richard's r-b as the code has
changed a bit.

Alex Bennée (3):
  target/arm: handle M-profile semihosting at translate time
  target/arm: handle A-profile semihosting at translate time
  target/arm: remove run time semihosting checks

Emilio G. Cota (1):
  atomic_template: fix indentation in GEN_ATOMIC_HELPER

 accel/tcg/atomic_template.h |  2 +-
 target/arm/helper.c | 96 +
 target/arm/m_helper.c   | 18 +++
 target/arm/translate.c  | 30 ++--
 4 files changed, 54 insertions(+), 92 deletions(-)

-- 
2.20.1




[Qemu-devel] [PATCH v3 1/4] target/arm: handle M-profile semihosting at translate time

2019-09-06 Thread Alex Bennée
We do this for other semihosting calls so we might as well do it for
M-profile as well.

Signed-off-by: Alex Bennée 
Reviewed-by: Richard Henderson 

---
v2
  - update for change to gen_exception_internal_insn API
v3
  - update for decode tree
---
 target/arm/m_helper.c  | 18 ++
 target/arm/translate.c | 11 ++-
 2 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
index 884d35d2b02..27cd2f3f964 100644
--- a/target/arm/m_helper.c
+++ b/target/arm/m_helper.c
@@ -2114,19 +2114,13 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
 break;
 }
 break;
+case EXCP_SEMIHOST:
+qemu_log_mask(CPU_LOG_INT,
+  "...handling as semihosting call 0x%x\n",
+  env->regs[0]);
+env->regs[0] = do_arm_semihosting(env);
+return;
 case EXCP_BKPT:
-if (semihosting_enabled()) {
-int nr;
-nr = arm_lduw_code(env, env->regs[15], arm_sctlr_b(env)) & 0xff;
-if (nr == 0xab) {
-env->regs[15] += 2;
-qemu_log_mask(CPU_LOG_INT,
-  "...handling as semihosting call 0x%x\n",
-  env->regs[0]);
-env->regs[0] = do_arm_semihosting(env);
-return;
-}
-}
 armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG, false);
 break;
 case EXCP_IRQ:
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 34bb280e3da..4cda7812bcb 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -8424,7 +8424,16 @@ static bool trans_BKPT(DisasContext *s, arg_BKPT *a)
 if (!ENABLE_ARCH_5) {
 return false;
 }
-gen_exception_bkpt_insn(s, syn_aa32_bkpt(a->imm, false));
+if (arm_dc_feature(s, ARM_FEATURE_M) &&
+semihosting_enabled() &&
+#ifndef CONFIG_USER_ONLY
+s->current_el != 0 &&
+#endif
+(a->imm == 0xab)) {
+gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST);
+} else {
+gen_exception_bkpt_insn(s, syn_aa32_bkpt(a->imm, false));
+}
 return true;
 }
 
-- 
2.20.1




Re: [Qemu-devel] [PATCH v2 08/13] qcrypto-luks: extract store and load header

2019-09-06 Thread Daniel P . Berrangé
On Mon, Aug 26, 2019 at 04:50:58PM +0300, Maxim Levitsky wrote:
> Signed-off-by: Maxim Levitsky 
> ---
>  crypto/block-luks.c | 166 +++-
>  1 file changed, 102 insertions(+), 64 deletions(-)
> 
> diff --git a/crypto/block-luks.c b/crypto/block-luks.c
> index cad65ae0aa..b4dc6fc899 100644
> --- a/crypto/block-luks.c
> +++ b/crypto/block-luks.c
> @@ -409,6 +409,105 @@ qcrypto_block_luks_essiv_cipher(QCryptoCipherAlgorithm 
> cipher,
>  }
>  }
>  
> +/*
> + * Stores the main LUKS header, taking care of endianess
> + */
> +static int
> +qcrypto_block_luks_store_header(QCryptoBlock *block,
> +QCryptoBlockWriteFunc writefunc,
> +void *opaque,
> +Error **errp)
> +{
> +const QCryptoBlockLUKS *luks = block->opaque;
> +Error *local_err = NULL;
> +size_t i;
> +QCryptoBlockLUKSHeader *hdr_copy;

Initialize to NULL and mark with g_autofree

> +
> +/* Create a copy of the header */
> +hdr_copy = g_new0(QCryptoBlockLUKSHeader, 1);
> +memcpy(hdr_copy, >header, sizeof(QCryptoBlockLUKSHeader));
> +
> +/*
> + * Everything on disk uses Big Endian (tm), so flip header fields
> + * before writing them
> + */
> +cpu_to_be16s(_copy->version);
> +cpu_to_be32s(_copy->payload_offset_sector);
> +cpu_to_be32s(_copy->master_key_len);
> +cpu_to_be32s(_copy->master_key_iterations);
> +
> +for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
> +cpu_to_be32s(_copy->key_slots[i].active);
> +cpu_to_be32s(_copy->key_slots[i].iterations);
> +cpu_to_be32s(_copy->key_slots[i].key_offset_sector);
> +cpu_to_be32s(_copy->key_slots[i].stripes);
> +}
> +
> +/* Write out the partition header and key slot headers */
> +writefunc(block, 0, (const uint8_t *)hdr_copy, sizeof(*hdr_copy),
> +  opaque, _err);
> +
> +g_free(hdr_copy);

And then this can be removed

> +
> +if (local_err) {
> +error_propagate(errp, local_err);
> +return -1;
> +}
> +return 0;
> +}
> +
> +/*
> + * Loads the main LUKS header,and byteswaps it to native endianess
> + * And run basic sanity checks on it
> + */
> +static int
> +qcrypto_block_luks_load_header(QCryptoBlock *block,
> +QCryptoBlockReadFunc readfunc,
> +void *opaque,
> +Error **errp)
> +{
> +ssize_t rv;
> +size_t i;
> +int ret = 0;
> +QCryptoBlockLUKS *luks = block->opaque;
> +
> +/*
> + * Read the entire LUKS header, minus the key material from
> + * the underlying device
> + */
> +
> +rv = readfunc(block, 0,
> +  (uint8_t *)>header,
> +  sizeof(luks->header),
> +  opaque,
> +  errp);
> +if (rv < 0) {
> +ret = rv;
> +goto fail;

Nothing happens at the fail: label, so you can just 'return rv'
straightaway IMHO

> +}
> +
> +/*
> + * The header is always stored in big-endian format, so
> + * convert everything to native
> + */
> +be16_to_cpus(>header.version);
> +be32_to_cpus(>header.payload_offset_sector);
> +be32_to_cpus(>header.master_key_len);
> +be32_to_cpus(>header.master_key_iterations);
> +
> +for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
> +be32_to_cpus(>header.key_slots[i].active);
> +be32_to_cpus(>header.key_slots[i].iterations);
> +be32_to_cpus(>header.key_slots[i].key_offset_sector);
> +be32_to_cpus(>header.key_slots[i].stripes);
> +}
> +
> +
> +return 0;
> +fail:
> +return ret;
> +}

> -/* Read the entire LUKS header, minus the key material from
> - * the underlying device */
> -rv = readfunc(block, 0,
> -  (uint8_t *)>header,
> -  sizeof(luks->header),
> -  opaque,
> -  errp);
> -if (rv < 0) {
> -ret = rv;
> +ret = qcrypto_block_luks_load_header(block, readfunc, opaque, errp);
> +if (ret) {

if (ret < 0)

>  goto fail;
>  }
>  
> -/* The header is always stored in big-endian format, so
> - * convert everything to native */
> -be16_to_cpus(>header.version);
> -be32_to_cpus(>header.payload_offset_sector);
> -be32_to_cpus(>header.master_key_len);
> -be32_to_cpus(>header.master_key_iterations);
> -
> -for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
> -be32_to_cpus(>header.key_slots[i].active);
> -be32_to_cpus(>header.key_slots[i].iterations);
> -be32_to_cpus(>header.key_slots[i].key_offset_sector);
> -be32_to_cpus(>header.key_slots[i].stripes);
> -}
>  
>  if (memcmp(luks->header.magic, qcrypto_block_luks_magic,
> QCRYPTO_BLOCK_LUKS_MAGIC_LEN) != 0) {
> @@ -1235,46 +1312,7 @@ qcrypto_block_luks_create(QCryptoBlock 

Re: [Qemu-devel] [PATCH] memory: Set notdirty_mem_ops validator

2019-09-06 Thread Eric Blake
On 9/6/19 3:28 AM, Philippe Mathieu-Daudé wrote:
> On 9/2/19 3:26 AM, Tony Nguyen wrote:
>> Existing read rejecting validator was mistakenly cleared.
>>
>> Reads dispatched to io_mem_notdirty then segfaults as there is no read
>> handler.
>>
>> Signed-off-by: Tony Nguyen 
>> ---
>>  exec.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/exec.c b/exec.c
>> index 1df966d17a..05d664541f 100644
>> --- a/exec.c
>> +++ b/exec.c
>> @@ -2796,12 +2796,12 @@ static bool notdirty_mem_accepts(void *opaque, 
>> hwaddr addr,
>>  
>>  static const MemoryRegionOps notdirty_mem_ops = {
>>  .write = notdirty_mem_write,
>> -.valid.accepts = notdirty_mem_accepts,
>>  .endianness = DEVICE_NATIVE_ENDIAN,
>>  .valid = {
>>  .min_access_size = 1,
>>  .max_access_size = 8,
>>  .unaligned = false,
>> +.accepts = notdirty_mem_accepts,
> 
> I'm surprised the compiler doesn't emit any warning...

Same here.

But reading
https://en.cppreference.com/w/c/language/struct_initialization, this is
compliant behavior:

"However, when an initializer begins with a left open brace, its current
object is fully re-initialized and any prior explicit initializers for
any of its subobjects are ignored:"

so it is worth filing a gcc bug asking for a QoI improvement in adding a
warning (since the code does not violate the C standard, but does cause
surprises in the reinitialization of omitted members in the later {} to
go back to 0 in spite of the earlier initialization by nested name).

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org



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

2019-09-06 Thread Eric Blake
On 9/6/19 4:24 AM, Daniel P. Berrangé wrote:

>>
>> I'm going to apply this, but something I thought of looking at
>> the diffstat: should some or all of this be in the docs/devel
>> manual rather than free-floating rst files in the root directory?
> 
> The answer really hinges on whether moving CODING_STYLE into the
> docs/devel directory will make it less obvious to users.

A git symlink would allow us to keep the file at the top level (for easy
location while browsing the repository) as well as under docs (for easy
incorporation into the doc build recipes).  I don't know if tooling
would require the original in one place (forcing the other to be the
link), or if you can do it in either direction.

> 
> So we could just move CODING_STYLE into the docs/devel dir and link
> to it from a CONTRIBUTING.md (well .rst) file.

A textual link in an actual file is slightly different than a git
symlink, but yes, that would probably also work (even if it requires
chasing through one more layer of files).

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org



signature.asc
Description: OpenPGP digital signature


Re: [Qemu-devel] [PATCH v2 10/13] qcrypto-luks: refactoring: extract store key function

2019-09-06 Thread Daniel P . Berrangé
On Mon, Aug 26, 2019 at 04:51:00PM +0300, Maxim Levitsky wrote:
> This function will be used later to store
> new keys to the luks metadata
> 
> Signed-off-by: Maxim Levitsky 
> ---
>  crypto/block-luks.c | 310 ++--
>  1 file changed, 184 insertions(+), 126 deletions(-)
> 
> diff --git a/crypto/block-luks.c b/crypto/block-luks.c
> index cc9a52c9af..d713125925 100644
> --- a/crypto/block-luks.c
> +++ b/crypto/block-luks.c
> @@ -650,6 +650,176 @@ out:
>  
>  }
>  
> +/*
> + * Given a key slot,  user password, and the master key,
> + * will store the encrypted master key there, and update the
> + * in-memory header. User must then write the in-memory header
> + *
> + * Returns:
> + *0 if the keyslot was written successfully
> + *  with the provided password
> + *   -1 if a fatal error occurred while storing the key
> + */
> +static int
> +qcrypto_block_luks_store_key(QCryptoBlock *block,
> + unsigned int slot_idx,
> + const char *password,
> + uint8_t *masterkey,
> + uint64_t iter_time,
> + QCryptoBlockWriteFunc writefunc,
> + void *opaque,
> + Error **errp)
> +{
> +QCryptoBlockLUKS *luks = block->opaque;
> +QCryptoBlockLUKSKeySlot *slot = >header.key_slots[slot_idx];
> +g_autofree uint8_t *splitkey = NULL;
> +size_t splitkeylen;
> +g_autofree uint8_t *slotkey = NULL;
> +g_autoptr(QCryptoCipher) cipher = NULL;
> +g_autoptr(QCryptoIVGen) ivgen = NULL;
> +Error *local_err = NULL;
> +uint64_t iters;
> +int ret = -1;
> +
> +if (qcrypto_random_bytes(slot->salt,
> + QCRYPTO_BLOCK_LUKS_SALT_LEN,
> + errp) < 0) {
> +goto cleanup;
> +}
> +
> +splitkeylen = luks->header.master_key_len * slot->stripes;
> +
> +/*
> + * Determine how many iterations are required to
> + * hash the user password while consuming 1 second of compute
> + * time
> + */
> +iters = qcrypto_pbkdf2_count_iters(luks->hash_alg,
> +   (uint8_t *)password, strlen(password),
> +   slot->salt,
> +   QCRYPTO_BLOCK_LUKS_SALT_LEN,
> +   luks->header.master_key_len,
> +   _err);
> +if (local_err) {
> +error_propagate(errp, local_err);
> +goto cleanup;
> +}
> +
> +if (iters > (ULLONG_MAX / iter_time)) {
> +error_setg_errno(errp, ERANGE,
> + "PBKDF iterations %llu too large to scale",
> + (unsigned long long)iters);
> +goto cleanup;
> +}
> +
> +/* iter_time was in millis, but count_iters reported for secs */
> +iters = iters * iter_time / 1000;
> +
> +if (iters > UINT32_MAX) {
> +error_setg_errno(errp, ERANGE,
> + "PBKDF iterations %llu larger than %u",
> + (unsigned long long)iters, UINT32_MAX);
> +goto cleanup;
> +}
> +
> +slot->iterations =
> +MAX(iters, QCRYPTO_BLOCK_LUKS_MIN_SLOT_KEY_ITERS);
> +
> +
> +/*
> + * Generate a key that we'll use to encrypt the master
> + * key, from the user's password
> + */
> +slotkey = g_new0(uint8_t, luks->header.master_key_len);
> +if (qcrypto_pbkdf2(luks->hash_alg,
> +   (uint8_t *)password, strlen(password),
> +   slot->salt,
> +   QCRYPTO_BLOCK_LUKS_SALT_LEN,
> +   slot->iterations,
> +   slotkey, luks->header.master_key_len,
> +   errp) < 0) {
> +goto cleanup;
> +}
> +
> +
> +/*
> + * Setup the encryption objects needed to encrypt the
> + * master key material
> + */
> +cipher = qcrypto_cipher_new(luks->cipher_alg,
> +luks->cipher_mode,
> +slotkey, luks->header.master_key_len,
> +errp);
> +if (!cipher) {
> +goto cleanup;
> +}
> +
> +ivgen = qcrypto_ivgen_new(luks->ivgen_alg,
> +  luks->ivgen_cipher_alg,
> +  luks->ivgen_hash_alg,
> +  slotkey, luks->header.master_key_len,
> +  errp);
> +if (!ivgen) {
> +goto cleanup;
> +}
> +
> +/*
> + * Before storing the master key, we need to vastly
> + * increase its size, as protection against forensic
> + * disk data recovery
> + */
> +splitkey = g_new0(uint8_t, splitkeylen);
> +
> +if (qcrypto_afsplit_encode(luks->hash_alg,
> +   luks->header.master_key_len,
> +

Re: [Qemu-devel] Cross-posted : Odd QXL/KVM performance issue with a Windows 7 Guest

2019-09-06 Thread Brad Campbell

On 6/9/19 16:49, Brad Campbell wrote:

On 2/9/19 6:23 pm, Brad Campbell wrote:



Here is the holdup :

11725@1567416625.003504:qxl_ring_command_check 0 native
11725@1567416625.102653:qxl_io_write 0 native addr=0 (QXL_IO_NOTIFY_CMD) val=0 
size=1 async=0

~100ms delay prior to each logged QXL_IO_NOTIFY_CMD on the AMD box which 
explains the performance difference. Now I just need to figure out if that lies 
in the guest, the guest QXL driver, QEMU or SPICE and why it exhibits on the 
AMD box and not the i7.

To get to this point, I recompiled the kernel on the i7 box with both AMD and 
Intel KVM modules. Once that was running I cloned the drive and put it in the 
AMD box, so the OS, software stack and all dependencies are identical.




Had a bit more of a poke and traced kvm and qxl on both machines at 
approximately comparative times of the same benchmark. From what I can 
ascertain in this context ioctl type 0xc008ae67 is KVM_IRQ_LINE_STATUS.

The i7 trace shows maybe 10ms spent hitting that. The Ryzen trace below shows 
the majority of the frame spent hitting that ioctl (some ~110ms).

i7 :

qxl/guest-0: 161680464256: qxldd: DrvCopyBits
7022@1567775823.999850:kvm_vcpu_ioctl cpu_index 1, type 0xae80, arg (nil)
7022@1567775824.000106:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c970
7022@1567775824.000115:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c980
7022@1567775824.001106:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c970
7022@1567775824.001117:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c980
7022@1567775824.002106:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c970
7022@1567775824.002115:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c980
7022@1567775824.003122:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c970
7022@1567775824.003145:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c980
7022@1567775824.004122:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c970
7022@1567775824.004144:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c980
7022@1567775824.005122:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c970
7022@1567775824.005144:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c980
7022@1567775824.006122:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c970
7022@1567775824.006144:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c980
7022@1567775824.007122:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c970
7022@1567775824.007144:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c980
7022@1567775824.008128:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c970
7022@1567775824.008150:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c980
7022@1567775824.009122:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c970
7022@1567775824.009144:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c980
7022@1567775824.010118:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c970
7022@1567775824.010139:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c980
7022@1567775824.08:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c970
7022@1567775824.011139:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c980
7022@1567775824.012117:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c970
7022@1567775824.012138:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c980
7022@1567775824.012200:kvm_run_exit cpu_index 1, reason 2
7022@1567775824.012214:qxl_io_write 0 native addr=4 (QXL_IO_NOTIFY_OOM) val=0 
size=1 async=0
7022@1567775824.012226:qxl_spice_oom 0
7022@1567775824.012238:kvm_vcpu_ioctl cpu_index 1, type 0xae80, arg (nil)
7022@1567775824.012280:qxl_ring_command_check 0 native
7022@1567775824.012288:qxl_ring_res_push 0 native s#=0 res#=2 
last=0x7faee4c2d458 notify=yes
7022@1567775824.012296:qxl_ring_res_push_rest 0 ring 1/8 [2399,2398]
7022@1567775824.012307:qxl_send_events 0 1
7022@1567775824.012319:qxl_ring_cursor_check 0 native
7022@1567775824.012325:qxl_ring_command_check 0 native
7022@1567775824.012332:qxl_ring_cursor_check 0 native
7022@1567775824.012336:qxl_ring_command_check 0 native
7022@1567775824.012342:qxl_ring_cursor_check 0 native
7022@1567775824.012349:qxl_ring_command_check 0 native
7022@1567775824.012367:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c890
7022@1567775824.012388:kvm_run_exit cpu_index 1, reason 2
7022@1567775824.012399:qxl_io_write 0 native addr=3 (QXL_IO_UPDATE_IRQ) val=0 
size=1 async=0
7022@1567775824.012416:kvm_vm_ioctl type 0xc008ae67, arg 0x7fb4f5a296b0
7022@1567775824.012426:kvm_vcpu_ioctl cpu_index 1, type 0xae80, arg (nil)
7022@1567775824.012444:kvm_run_exit cpu_index 1, reason 2
7022@1567775824.012452:qxl_io_write 0 native addr=3 (QXL_IO_UPDATE_IRQ) val=0 
size=1 async=0
7022@1567775824.012466:kvm_vcpu_ioctl cpu_index 1, type 0xae80, arg (nil)
7022@1567775824.013106:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c970
7022@1567775824.013124:kvm_vm_ioctl type 0xc008ae67, arg 0x7ffe13b0c980
7022@1567775824.013642:kvm_run_exit cpu_index 1, reason 2
7022@1567775824.013652:qxl_io_write 0 native addr=0 (QXL_IO_NOTIFY_CMD) val=0 
size=1 async=0
7022@1567775824.013667:kvm_vcpu_ioctl cpu_index 1, type 0xae80, arg (nil)
7022@1567775824.013726:qxl_ring_cursor_check 0 native

Re: [Qemu-devel] [PATCH] memory: Set notdirty_mem_ops validator

2019-09-06 Thread Eric Blake
On 9/6/19 8:24 AM, Philippe Mathieu-Daudé wrote:

  static const MemoryRegionOps notdirty_mem_ops = {
  .write = notdirty_mem_write,
 -.valid.accepts = notdirty_mem_accepts,
  .endianness = DEVICE_NATIVE_ENDIAN,
  .valid = {
  .min_access_size = 1,
  .max_access_size = 8,
  .unaligned = false,
 +.accepts = notdirty_mem_accepts,
>>>
>>> I'm surprised the compiler doesn't emit any warning...
>>
>> Same here.
>>
>> But reading
>> https://en.cppreference.com/w/c/language/struct_initialization, this is
>> compliant behavior:
>>
>> "However, when an initializer begins with a left open brace, its current
>> object is fully re-initialized and any prior explicit initializers for
>> any of its subobjects are ignored:"
>>
>> so it is worth filing a gcc bug asking for a QoI improvement in adding a
>> warning (since the code does not violate the C standard, but does cause
>> surprises in the reinitialization of omitted members in the later {} to
>> go back to 0 in spite of the earlier initialization by nested name).
> 
> Just remembered another case of (correct) reinitialization in
> hw/arm/palm.c:101:

We use nested reinitialization in multiple places. A gcc warning would
have to be discriminating enough to NOT warn merely when something is
listed twice...:

> 
> static struct {
> int row;
> int column;
> } palmte_keymap[0x80] = {
> [0 ... 0x7f] = { -1, -1 },
> [0x3b] = { 0, 0 },/* F1   -> Calendar */

Here, [0x3b].row and [0x3b].column are listed twice, but both of the
second listings are explicit.

Similarly, in qobject/json-lexer.c:

static const uint8_t json_lexer[][256] =  {
/* Relies on default initialization to IN_ERROR! */
...

/*
 * Two start states:
 * - IN_START recognizes JSON tokens with our string extensions
 * - IN_START_INTERP additionally recognizes interpolation.
 */
[IN_START ... IN_START_INTERP] = {
['"'] = IN_DQ_STRING,
...
['\n'] = IN_START,
},
[IN_START_INTERP]['%'] = IN_INTERP,
};

Done that way on purpose (I actually remember scratching my head on the
best way to compress things while reviewing Markus' patch that ended up
as 2cbd15aa6f; it took me a couple of tries off-list to end up at that
override).

...rather, the gcc warning that I envision should ONLY be when a later
partial ={} causes a zero-initialization override of an earlier explicit
.member, and NOT when a later complete ={} or explicit member overrides
an earlier init (whether the earlier one was explicit due to .member or
implicit due to partial ={}).

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.   +1-919-301-3226
Virtualization:  qemu.org | libvirt.org



Re: [Qemu-devel] [PATCH 02/10] qcrypto-luks: extend the create options for upcoming encryption key management

2019-09-06 Thread Daniel P . Berrangé
On Fri, Aug 30, 2019 at 11:56:00PM +0300, Maxim Levitsky wrote:
> Now you can specify which slot to put the encryption key to
> Plus add 'active' option which will let  user erase the key secret
> instead of adding it.
> Check that it is true for creation
> 
> Signed-off-by: Maxim Levitsky 
> ---
>  block/crypto.c |  2 ++
>  block/crypto.h | 16 +++
>  block/qcow2.c  |  2 ++
>  crypto/block-luks.c| 26 +++---
>  qapi/crypto.json   | 19 ++
>  tests/qemu-iotests/082.out | 54 ++
>  6 files changed, 115 insertions(+), 4 deletions(-)
> 
> diff --git a/block/crypto.c b/block/crypto.c
> index 6e822c6e50..a6a3e1f1d8 100644
> --- a/block/crypto.c
> +++ b/block/crypto.c
> @@ -144,6 +144,8 @@ static QemuOptsList block_crypto_create_opts_luks = {
>  BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG(""),
>  BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG(""),
>  BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME(""),
> +BLOCK_CRYPTO_OPT_DEF_LUKS_SLOT(""),
> +BLOCK_CRYPTO_OPT_DEF_LUKS_ACTIVE(""),
>  { /* end of list */ }
>  },
>  };
> diff --git a/block/crypto.h b/block/crypto.h
> index b935695e79..05cc43d9bc 100644
> --- a/block/crypto.h
> +++ b/block/crypto.h
> @@ -35,12 +35,14 @@
>  "ID of the secret that provides the AES encryption key")
>  
>  #define BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET "key-secret"
> +#define BLOCK_CRYPTO_OPT_LUKS_SLOT "slot"
>  #define BLOCK_CRYPTO_OPT_LUKS_CIPHER_ALG "cipher-alg"
>  #define BLOCK_CRYPTO_OPT_LUKS_CIPHER_MODE "cipher-mode"
>  #define BLOCK_CRYPTO_OPT_LUKS_IVGEN_ALG "ivgen-alg"
>  #define BLOCK_CRYPTO_OPT_LUKS_IVGEN_HASH_ALG "ivgen-hash-alg"
>  #define BLOCK_CRYPTO_OPT_LUKS_HASH_ALG "hash-alg"
>  #define BLOCK_CRYPTO_OPT_LUKS_ITER_TIME "iter-time"
> +#define BLOCK_CRYPTO_OPT_LUKS_ACTIVE "active"
>  
>  #define BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET(prefix)\
>  BLOCK_CRYPTO_OPT_DEF_KEY_SECRET(prefix, \
> @@ -88,6 +90,20 @@
>  .help = "Time to spend in PBKDF in milliseconds", \
>  }
>  
> +#define BLOCK_CRYPTO_OPT_DEF_LUKS_SLOT(prefix)   \
> +{ \
> +.name = prefix BLOCK_CRYPTO_OPT_LUKS_SLOT,   \
> +.type = QEMU_OPT_NUMBER,  \
> +.help = "Controls the slot where the secret is added/erased", \
> +}
> +
> +#define BLOCK_CRYPTO_OPT_DEF_LUKS_ACTIVE(prefix)   \
> +{ \
> +.name = prefix BLOCK_CRYPTO_OPT_LUKS_ACTIVE,   \
> +.type = QEMU_OPT_BOOL,  \
> +.help = "Controls if the added secret is added or erased", \
> +}

Do we actually need the "active" property for initial
creation. I think its only needed for amend, so perhaps
we shuold not register this at all ?

> +
>  QCryptoBlockCreateOptions *
>  block_crypto_create_opts_init(QDict *opts, Error **errp);
>  
> diff --git a/block/qcow2.c b/block/qcow2.c
> index 7c5a4859f7..be4a5063e5 100644
> --- a/block/qcow2.c
> +++ b/block/qcow2.c
> @@ -5167,6 +5167,8 @@ static QemuOptsList qcow2_create_opts = {
>  BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG("encrypt."),
>  BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG("encrypt."),
>  BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME("encrypt."),
> +BLOCK_CRYPTO_OPT_DEF_LUKS_SLOT("encrypt."),
> +BLOCK_CRYPTO_OPT_DEF_LUKS_ACTIVE("encrypt."),
>  {
>  .name = BLOCK_OPT_CLUSTER_SIZE,
>  .type = QEMU_OPT_SIZE,
> diff --git a/crypto/block-luks.c b/crypto/block-luks.c
> index 3af137e364..ba20d55246 100644
> --- a/crypto/block-luks.c
> +++ b/crypto/block-luks.c
> @@ -1230,6 +1230,7 @@ qcrypto_block_luks_create(QCryptoBlock *block,
>  const char *hash_alg;
>  g_autofree char *cipher_mode_spec = NULL;
>  uint64_t iters;
> +unsigned int slot_idx = 0;
>  
>  memcpy(_opts, >u.luks, sizeof(luks_opts));
>  if (!luks_opts.has_iter_time) {
> @@ -1263,12 +1264,30 @@ qcrypto_block_luks_create(QCryptoBlock *block,
>  luks->ivgen_hash_alg = luks_opts.ivgen_hash_alg;
>  luks->hash_alg = luks_opts.hash_alg;
>  
> +if (luks_opts.has_active && !luks_opts.active) {
> +error_setg(errp,
> +   "For image creation, the added secret must be active!");
> +goto error;
> +
> +}
> +
> +if (luks_opts.has_slot) {
> +if (luks_opts.slot >= QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS ||
> +luks_opts.slot < 0) {
> +error_setg(errp,
> +   "Invalid slot %" PRId64 " is specified",
> +   luks_opts.slot);
> +goto error;
> +}
> +slot_idx = (unsigned int)luks_opts.slot;
> +}
> +
>  
>  /* Note we're allowing ivgen_hash_alg to be set even for
>   * non-essiv 

Re: [Qemu-devel] [PATCH 05/10] block/crypto: implement the encryption key management

2019-09-06 Thread Daniel P . Berrangé
On Fri, Aug 30, 2019 at 11:56:03PM +0300, Maxim Levitsky wrote:
> This implements the encryption key management
> using the generic code in qcrypto layer
> (currently only for qemu-img amend)
> 
> This code adds another 'write_func' because the initialization
> write_func works directly on the underlying file,
> because during the creation, there is no open instance
> of the luks driver, but during regular use, we have it,
> and should use it instead.
> 
> Signed-off-by: Maxim Levitsky 
> ---
>  block/crypto.c | 106 +++--
>  1 file changed, 103 insertions(+), 3 deletions(-)
> 
> diff --git a/block/crypto.c b/block/crypto.c
> index a6a3e1f1d8..dbd95a99ba 100644
> --- a/block/crypto.c
> +++ b/block/crypto.c
> @@ -36,6 +36,7 @@ typedef struct BlockCrypto BlockCrypto;
>  
>  struct BlockCrypto {
>  QCryptoBlock *block;
> +bool updating_keys;
>  };
>  
>  
> @@ -70,6 +71,24 @@ static ssize_t block_crypto_read_func(QCryptoBlock *block,
>  return ret;
>  }
>  
> +static ssize_t block_crypto_write_func(QCryptoBlock *block,
> +  size_t offset,
> +  const uint8_t *buf,
> +  size_t buflen,
> +  void *opaque,
> +  Error **errp)

Indent off-by-1 - align with param on the first line

> +{
> +BlockDriverState *bs = opaque;
> +ssize_t ret;
> +
> +ret = bdrv_pwrite(bs->file, offset, buf, buflen);
> +if (ret < 0) {
> +error_setg_errno(errp, -ret, "Could not write encryption header");
> +return ret;
> +}
> +return ret;
> +}
> +
>  
>  struct BlockCryptoCreateData {
>  BlockBackend *blk;
> @@ -647,6 +666,88 @@ block_crypto_get_specific_info_luks(BlockDriverState 
> *bs, Error **errp)
>  return spec_info;
>  }
>  
> +
> +static int
> +block_crypto_amend_options(BlockDriverState *bs,
> +   QemuOpts *opts,
> +   BlockDriverAmendStatusCB *status_cb,
> +   void *cb_opaque,
> +   bool force,
> +   Error **errp)
> +{
> +BlockCrypto *crypto = bs->opaque;
> +QDict *cryptoopts = NULL;
> +QCryptoBlockCreateOptions *amend_options = NULL;
> +int ret;
> +
> +assert(crypto);
> +assert(crypto->block);
> +
> +crypto->updating_keys = true;
> +
> +ret = bdrv_child_refresh_perms(bs, bs->file, errp);
> +if (ret) {

I can;'t remember - does this need to be "ret < 0" or
does refresh_perms return positive errnos ?

> +goto cleanup;
> +}
> +
> +cryptoopts = qemu_opts_to_qdict_filtered(opts, NULL,
> + _crypto_create_opts_luks,
> + true);
> +
> +qdict_put_str(cryptoopts, "format", "luks");
> +amend_options = block_crypto_create_opts_init(cryptoopts, errp);
> +if (!amend_options) {
> +ret = -EINVAL;
> +goto cleanup;
> +}
> +
> +ret = qcrypto_block_amend_options(crypto->block,
> +  block_crypto_read_func,
> +  block_crypto_write_func,
> +  bs,
> +  amend_options,
> +  force,
> +  errp);
> +cleanup:
> +crypto->updating_keys = false;
> +bdrv_child_refresh_perms(bs, bs->file, errp);
> +qapi_free_QCryptoBlockCreateOptions(amend_options);
> +qobject_unref(cryptoopts);
> +return ret;
> +}
> +
> +
> +static void
> +block_crypto_child_perms(BlockDriverState *bs, BdrvChild *c,
> + const BdrvChildRole *role,
> + BlockReopenQueue *reopen_queue,
> + uint64_t perm, uint64_t shared,
> + uint64_t *nperm, uint64_t *nshared)
> +{
> +
> +BlockCrypto *crypto = bs->opaque;
> +
> +/*
> + * This driver doesn't modify LUKS metadata except
> + * when updating the encryption slots.
> + * Allow share-rw=on as a special case.
> + *
> + * Encryption update will set the crypto->updating_keys
> + * during that period and refresh permissions
> + *
> + * */
> +
> +if (crypto->updating_keys) {
> +/*need exclusive write access for header update  */
> +perm |= BLK_PERM_WRITE;
> +shared &= ~BLK_PERM_WRITE;
> +}
> +
> +bdrv_filter_default_perms(bs, c, role, reopen_queue,
> +perm, shared, nperm, nshared);
> +}
> +
> +
>  static const char *const block_crypto_strong_runtime_opts[] = {
>  BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET,
>  
> @@ -659,9 +760,7 @@ static BlockDriver bdrv_crypto_luks = {
>  .bdrv_probe = block_crypto_probe_luks,
>  .bdrv_open  = block_crypto_open_luks,
>  

Re: [Qemu-devel] [PATCH] memory: Set notdirty_mem_ops validator

2019-09-06 Thread Peter Maydell
On Wed, 4 Sep 2019 at 03:41, Peter Xu  wrote:
> On Tue, Sep 03, 2019 at 05:50:56PM +0100, Peter Maydell wrote:
> > Do you have a backtrace of QEMU from the segfault? I'm having trouble
> > thinking of what the situation is when we'd try to invoke the
> > read handler on io_mem_notdirty...
>
> I've no good understanding of how PHYS_SECTION_NOTDIRTY is used
> yet... though from what I understand that's the thing this patch wants
> to fix.  Because after the broken commit, this line will be
> overwritten:
>
> .valid.accepts = notdirty_mem_accepts,
>
> and accept() will be reset to NULL.
>
> With that, memory_region_access_valid(is_write=false) could return
> valid now (so a read could happen), while it should never, logically?

Having looked into this a bit further, I think that the problem here
is that in commit 30d7e098d5c38644359 we accidentally removed the
code for TLB_RECHECK-type TLB entries that handled the "actually this
is a RAM access" case after repeating the tlb_fill(). So instead of
read accesses to notdirty-mem going through that code and never getting
into the io_readx() function, now they do. That combined with the
bug where we made the .valid.accepts assignment stop working means
you can get into this segfault. This is quite rare because I think
only Arm M-profile CPUs and Sparc when using the 'invert endian'
page table bit (ie Solaris guests doing PCI stuff) will do this.

If we apply this patch to reinstate .valid.accepts then instead
of a segfault we'll get a guest exception; which is still not
the right behaviour.

So I think we need to:
 (1) fix the cputlb code to reinstate the "handle RAM immediately"
 codepath
 (2) either allow reads to notdirty-mem MRs (ie make them just
 read from the host backing RAM), or define them to be a QEMU
 bug and make them assert immediately the read is attempted

thanks
-- PMM



Re: [Qemu-devel] [PATCH 08/10] block/crypto: implement blockdev-amend

2019-09-06 Thread Daniel P . Berrangé
On Fri, Aug 30, 2019 at 11:56:06PM +0300, Maxim Levitsky wrote:
> Signed-off-by: Maxim Levitsky 
> ---
>  block/crypto.c   | 86 +---
>  qapi/block-core.json |  4 +--
>  2 files changed, 68 insertions(+), 22 deletions(-)

Reviewed-by: Daniel P. Berrangé 


>  static int
>  block_crypto_amend_options(BlockDriverState *bs,
> QemuOpts *opts,
> @@ -678,44 +722,45 @@ block_crypto_amend_options(BlockDriverState *bs,
>  BlockCrypto *crypto = bs->opaque;
>  QDict *cryptoopts = NULL;
>  QCryptoBlockCreateOptions *amend_options = NULL;
> -int ret;
> +int ret= -EINVAL;

nitpick - space before '='

>  
>  assert(crypto);
>  assert(crypto->block);
>  
> -crypto->updating_keys = true;
> -
> -ret = bdrv_child_refresh_perms(bs, bs->file, errp);
> -if (ret) {
> -goto cleanup;
> -}
> -
>  cryptoopts = qemu_opts_to_qdict_filtered(opts, NULL,
>   _crypto_create_opts_luks,
>   true);
>  
>  qdict_put_str(cryptoopts, "format", "luks");
>  amend_options = block_crypto_create_opts_init(cryptoopts, errp);
> +
>  if (!amend_options) {
> -ret = -EINVAL;
> -goto cleanup;
> +goto out;
>  }
>  
> -ret = qcrypto_block_amend_options(crypto->block,
> -  block_crypto_read_func,
> -  block_crypto_write_func,
> -  bs,
> -  amend_options,
> -  force,
> -  errp);
> -cleanup:
> -crypto->updating_keys = false;
> -bdrv_child_refresh_perms(bs, bs->file, errp);
> +ret = block_crypto_amend_options_generic(bs, amend_options, force, errp);
> +out:

No need to rename the "cleanup" label to "out"

>  qapi_free_QCryptoBlockCreateOptions(amend_options);
>  qobject_unref(cryptoopts);
>  return ret;
>  }
>  
> +static int
> +coroutine_fn block_crypto_co_amend(BlockDriverState *bs,
> +   BlockdevCreateOptions *opts,
> +   bool force,
> +   Error **errp)
> +{
> +QCryptoBlockCreateOptions amend_opts;
> +
> +amend_opts = (QCryptoBlockCreateOptions) {
> +.format = Q_CRYPTO_BLOCK_FORMAT_LUKS,
> +.u.luks = *qapi_BlockdevCreateOptionsLUKS_base(>u.luks),
> +};
> +
> +return block_crypto_amend_options_generic(bs, _opts, force, errp);
> +}
> +
>  
>  static void
>  block_crypto_child_perms(BlockDriverState *bs, BdrvChild *c,
> @@ -774,6 +819,7 @@ static BlockDriver bdrv_crypto_luks = {
>  .bdrv_get_info  = block_crypto_get_info_luks,
>  .bdrv_get_specific_info = block_crypto_get_specific_info_luks,
>  .bdrv_amend_options = block_crypto_amend_options,
> +.bdrv_co_amend  = block_crypto_co_amend,
>  
>  .strong_runtime_opts = block_crypto_strong_runtime_opts,
>  };
> diff --git a/qapi/block-core.json b/qapi/block-core.json
> index 7900914506..02375fb59a 100644
> --- a/qapi/block-core.json
> +++ b/qapi/block-core.json
> @@ -4220,8 +4220,8 @@
>  ##
>  { 'struct': 'BlockdevCreateOptionsLUKS',
>'base': 'QCryptoBlockCreateOptionsLUKS',
> -  'data': { 'file': 'BlockdevRef',
> -'size': 'size',
> +  'data': { '*file': 'BlockdevRef',
> +'*size': 'size',

Docs comment to explain they are mandatory for create 

>  '*preallocation':   'PreallocMode' } }
>  
>  ##
> -- 
> 2.17.2
> 

Regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|



Re: [Qemu-devel] [PATCH v3 2/4] target/arm: handle A-profile semihosting at translate time

2019-09-06 Thread Peter Maydell
On Fri, 6 Sep 2019 at 13:47, Alex Bennée  wrote:
>
> As for the other semihosting calls we can resolve this at translate
> time.
>
> Signed-off-by: Alex Bennée 
>
> ---
> v2
>   - update for change to gen_exception_internal_insn API
> v3
>   - update for decode tree, merge T32 & A32 commits
>   - dropped r-b due to changes
> ---
>  target/arm/translate.c | 19 +++
>  1 file changed, 15 insertions(+), 4 deletions(-)
>
> diff --git a/target/arm/translate.c b/target/arm/translate.c
> index 4cda7812bcb..ed4a97cfb44 100644
> --- a/target/arm/translate.c
> +++ b/target/arm/translate.c
> @@ -10222,14 +10222,25 @@ static bool trans_CBZ(DisasContext *s, arg_CBZ *a)
>  }
>
>  /*
> - * Supervisor call
> + * Supervisor call - both T32 & A32 come here so we need to check
> + * which mode we are in when checking for semihosting.
>   */
>
>  static bool trans_SVC(DisasContext *s, arg_SVC *a)
>  {
> -gen_set_pc_im(s, s->base.pc_next);
> -s->svc_imm = a->imm;
> -s->base.is_jmp = DISAS_SWI;
> +const uint32_t semihost_imm = s->thumb ? 0xab : 0x123456;
> +
> +if (semihosting_enabled() &&
> +#ifndef CONFIG_USER_ONLY
> +s->current_el != 0 &&
> +#endif
> +(a->imm == semihost_imm)) {
> +gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST);
> +} else {
> +gen_set_pc_im(s, s->base.pc_next);
> +s->svc_imm = a->imm;
> +s->base.is_jmp = DISAS_SWI;
> +}
>  return true;
>  }

Doesn't this accidentally enable semihosting via SVC for
M-profile ?

thanks
-- PMM



Re: [Qemu-devel] [PULL 4/9] block: workaround for unaligned byte range in fallocate()

2019-09-06 Thread Andrey Shinkevich
Many thanks

Andrey

On 05/09/2019 21:21, Eric Blake wrote:
> From: Andrey Shinkevich 
> 
> Revert the commit 118f99442d 'block/io.c: fix for the allocation failure'
> and use better error handling for file systems that do not support
> fallocate() for an unaligned byte range. Allow falling back to pwrite
> in case fallocate() returns EINVAL.
> 
> Suggested-by: Kevin Wolf 
> Suggested-by: Eric Blake 
> Signed-off-by: Andrey Shinkevich 
> Reviewed-by: Eric Blake 
> Reviewed-by: Denis V. Lunev 
> Message-Id: 
> <1566913973-15490-1-git-send-email-andrey.shinkev...@virtuozzo.com>
> Signed-off-by: Eric Blake 
> ---
>   block/io.c | 2 +-
>   block/file-posix.c | 7 +++
>   2 files changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/block/io.c b/block/io.c
> index 0fa10831edb7..16a598fd0857 100644
> --- a/block/io.c
> +++ b/block/io.c
> @@ -1746,7 +1746,7 @@ static int coroutine_fn 
> bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
>   assert(!bs->supported_zero_flags);
>   }
> 
> -if (ret < 0 && !(flags & BDRV_REQ_NO_FALLBACK)) {
> +if (ret == -ENOTSUP && !(flags & BDRV_REQ_NO_FALLBACK)) {
>   /* Fall back to bounce buffer if write zeroes is unsupported */
>   BdrvRequestFlags write_flags = flags & ~BDRV_REQ_ZERO_WRITE;
> 
> diff --git a/block/file-posix.c b/block/file-posix.c
> index 71f168ee2f13..87c5a4ccbdc8 100644
> --- a/block/file-posix.c
> +++ b/block/file-posix.c
> @@ -1588,6 +1588,13 @@ static int handle_aiocb_write_zeroes(void *opaque)
>   if (s->has_write_zeroes) {
>   int ret = do_fallocate(s->fd, FALLOC_FL_ZERO_RANGE,
>  aiocb->aio_offset, aiocb->aio_nbytes);
> +if (ret == -EINVAL) {
> +/*
> + * Allow falling back to pwrite for file systems that
> + * do not support fallocate() for an unaligned byte range.
> + */
> +return -ENOTSUP;
> +}
>   if (ret == 0 || ret != -ENOTSUP) {
>   return ret;
>   }
> 

-- 
With the best regards,
Andrey Shinkevich


Re: [Qemu-devel] [PATCH v3 2/4] target/arm: handle A-profile semihosting at translate time

2019-09-06 Thread Alex Bennée


Peter Maydell  writes:

> On Fri, 6 Sep 2019 at 13:47, Alex Bennée  wrote:
>>
>> As for the other semihosting calls we can resolve this at translate
>> time.
>>
>> Signed-off-by: Alex Bennée 
>>
>> ---
>> v2
>>   - update for change to gen_exception_internal_insn API
>> v3
>>   - update for decode tree, merge T32 & A32 commits
>>   - dropped r-b due to changes
>> ---
>>  target/arm/translate.c | 19 +++
>>  1 file changed, 15 insertions(+), 4 deletions(-)
>>
>> diff --git a/target/arm/translate.c b/target/arm/translate.c
>> index 4cda7812bcb..ed4a97cfb44 100644
>> --- a/target/arm/translate.c
>> +++ b/target/arm/translate.c
>> @@ -10222,14 +10222,25 @@ static bool trans_CBZ(DisasContext *s, arg_CBZ *a)
>>  }
>>
>>  /*
>> - * Supervisor call
>> + * Supervisor call - both T32 & A32 come here so we need to check
>> + * which mode we are in when checking for semihosting.
>>   */
>>
>>  static bool trans_SVC(DisasContext *s, arg_SVC *a)
>>  {
>> -gen_set_pc_im(s, s->base.pc_next);
>> -s->svc_imm = a->imm;
>> -s->base.is_jmp = DISAS_SWI;
>> +const uint32_t semihost_imm = s->thumb ? 0xab : 0x123456;
>> +
>> +if (semihosting_enabled() &&
>> +#ifndef CONFIG_USER_ONLY
>> +s->current_el != 0 &&
>> +#endif
>> +(a->imm == semihost_imm)) {
>> +gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST);
>> +} else {
>> +gen_set_pc_im(s, s->base.pc_next);
>> +s->svc_imm = a->imm;
>> +s->base.is_jmp = DISAS_SWI;
>> +}
>>  return true;
>>  }
>
> Doesn't this accidentally enable semihosting via SVC for
> M-profile ?

We must have done that before then. Just gate it with &&
!arm_dc_feature(s, ARM_FEATURE_M) then?

>
> thanks
> -- PMM


--
Alex Bennée



Re: [Qemu-devel] [PATCH] memory: Set notdirty_mem_ops validator

2019-09-06 Thread Philippe Mathieu-Daudé
On 9/6/19 3:08 PM, Eric Blake wrote:
> On 9/6/19 3:28 AM, Philippe Mathieu-Daudé wrote:
>> On 9/2/19 3:26 AM, Tony Nguyen wrote:
>>> Existing read rejecting validator was mistakenly cleared.
>>>
>>> Reads dispatched to io_mem_notdirty then segfaults as there is no read
>>> handler.
>>>
>>> Signed-off-by: Tony Nguyen 
>>> ---
>>>  exec.c | 2 +-
>>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>>
>>> diff --git a/exec.c b/exec.c
>>> index 1df966d17a..05d664541f 100644
>>> --- a/exec.c
>>> +++ b/exec.c
>>> @@ -2796,12 +2796,12 @@ static bool notdirty_mem_accepts(void *opaque, 
>>> hwaddr addr,
>>>  
>>>  static const MemoryRegionOps notdirty_mem_ops = {
>>>  .write = notdirty_mem_write,
>>> -.valid.accepts = notdirty_mem_accepts,
>>>  .endianness = DEVICE_NATIVE_ENDIAN,
>>>  .valid = {
>>>  .min_access_size = 1,
>>>  .max_access_size = 8,
>>>  .unaligned = false,
>>> +.accepts = notdirty_mem_accepts,
>>
>> I'm surprised the compiler doesn't emit any warning...
> 
> Same here.
> 
> But reading
> https://en.cppreference.com/w/c/language/struct_initialization, this is
> compliant behavior:
> 
> "However, when an initializer begins with a left open brace, its current
> object is fully re-initialized and any prior explicit initializers for
> any of its subobjects are ignored:"
> 
> so it is worth filing a gcc bug asking for a QoI improvement in adding a
> warning (since the code does not violate the C standard, but does cause
> surprises in the reinitialization of omitted members in the later {} to
> go back to 0 in spite of the earlier initialization by nested name).

Just remembered another case of (correct) reinitialization in
hw/arm/palm.c:101:

static struct {
int row;
int column;
} palmte_keymap[0x80] = {
[0 ... 0x7f] = { -1, -1 },
[0x3b] = { 0, 0 },  /* F1   -> Calendar */
[0x3c] = { 1, 0 },  /* F2   -> Contacts */
[0x3d] = { 2, 0 },  /* F3   -> Tasks List */
[0x3e] = { 3, 0 },  /* F4   -> Note Pad */
[0x01] = { 4, 0 },  /* Esc  -> Power */
[0x4b] = { 0, 1 },  /* Left */
[0x50] = { 1, 1 },  /* Down */
[0x48] = { 2, 1 },  /* Up */
[0x4d] = { 3, 1 },  /* Right */
[0x4c] = { 4, 1 },  /* Centre */
[0x39] = { 4, 1 },  /* Spc  -> Centre */
};



Re: [Qemu-devel] [PATCH v3 2/4] target/arm: handle A-profile semihosting at translate time

2019-09-06 Thread Peter Maydell
On Fri, 6 Sep 2019 at 14:16, Alex Bennée  wrote:
>
>
> Peter Maydell  writes:
>
> > On Fri, 6 Sep 2019 at 13:47, Alex Bennée  wrote:
>
> >
> > Doesn't this accidentally enable semihosting via SVC for
> > M-profile ?
>
> We must have done that before then.

No, we didn't do it before, because we were handling it in
arm_cpu_do_interrupt(), which is A/R-profile only. The
M-profile code goes via arm_v7m_cpu_do_interrupt() which doesn't
check for semihosting when it sees an EXCP_SWI.

> Just gate it with && !arm_dc_feature(s, ARM_FEATURE_M) then?

Yes, I think that's the right fix.

thanks
-- PMM



Re: [Qemu-devel] [PATCH 02/10] qcrypto-luks: extend the create options for upcoming encryption key management

2019-09-06 Thread Maxim Levitsky
On Fri, 2019-09-06 at 14:49 +0100, Daniel P. Berrangé wrote:
> On Fri, Aug 30, 2019 at 11:56:00PM +0300, Maxim Levitsky wrote:
> > Now you can specify which slot to put the encryption key to
> > Plus add 'active' option which will let  user erase the key secret
> > instead of adding it.
> > Check that it is true for creation
> > 
> > Signed-off-by: Maxim Levitsky 
> > ---
> >  block/crypto.c |  2 ++
> >  block/crypto.h | 16 +++
> >  block/qcow2.c  |  2 ++
> >  crypto/block-luks.c| 26 +++---
> >  qapi/crypto.json   | 19 ++
> >  tests/qemu-iotests/082.out | 54 ++
> >  6 files changed, 115 insertions(+), 4 deletions(-)
> > 
> > diff --git a/block/crypto.c b/block/crypto.c
> > index 6e822c6e50..a6a3e1f1d8 100644
> > --- a/block/crypto.c
> > +++ b/block/crypto.c
> > @@ -144,6 +144,8 @@ static QemuOptsList block_crypto_create_opts_luks = {
> >  BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG(""),
> >  BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG(""),
> >  BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME(""),
> > +BLOCK_CRYPTO_OPT_DEF_LUKS_SLOT(""),
> > +BLOCK_CRYPTO_OPT_DEF_LUKS_ACTIVE(""),
> >  { /* end of list */ }
> >  },
> >  };
> > diff --git a/block/crypto.h b/block/crypto.h
> > index b935695e79..05cc43d9bc 100644
> > --- a/block/crypto.h
> > +++ b/block/crypto.h
> > @@ -35,12 +35,14 @@
> >  "ID of the secret that provides the AES encryption key")
> >  
> >  #define BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET "key-secret"
> > +#define BLOCK_CRYPTO_OPT_LUKS_SLOT "slot"
> >  #define BLOCK_CRYPTO_OPT_LUKS_CIPHER_ALG "cipher-alg"
> >  #define BLOCK_CRYPTO_OPT_LUKS_CIPHER_MODE "cipher-mode"
> >  #define BLOCK_CRYPTO_OPT_LUKS_IVGEN_ALG "ivgen-alg"
> >  #define BLOCK_CRYPTO_OPT_LUKS_IVGEN_HASH_ALG "ivgen-hash-alg"
> >  #define BLOCK_CRYPTO_OPT_LUKS_HASH_ALG "hash-alg"
> >  #define BLOCK_CRYPTO_OPT_LUKS_ITER_TIME "iter-time"
> > +#define BLOCK_CRYPTO_OPT_LUKS_ACTIVE "active"
> >  
> >  #define BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET(prefix)\
> >  BLOCK_CRYPTO_OPT_DEF_KEY_SECRET(prefix, \
> > @@ -88,6 +90,20 @@
> >  .help = "Time to spend in PBKDF in milliseconds", \
> >  }
> >  
> > +#define BLOCK_CRYPTO_OPT_DEF_LUKS_SLOT(prefix)   \
> > +{ \
> > +.name = prefix BLOCK_CRYPTO_OPT_LUKS_SLOT,   \
> > +.type = QEMU_OPT_NUMBER,  \
> > +.help = "Controls the slot where the secret is added/erased", \
> > +}
> > +
> > +#define BLOCK_CRYPTO_OPT_DEF_LUKS_ACTIVE(prefix)   \
> > +{ \
> > +.name = prefix BLOCK_CRYPTO_OPT_LUKS_ACTIVE,   \
> > +.type = QEMU_OPT_BOOL,  \
> > +.help = "Controls if the added secret is added or erased", \
> > +}
> 
> Do we actually need the "active" property for initial
> creation. I think its only needed for amend, so perhaps
> we shuold not register this at all ?

Sadly we kind of do, since both amend and create use the same option list 
currently.
I tried to duplicate it, and it is possible, but then you end up
with significant code duplication in qcow2 with its huge create option list.

I am now thinking that we could have had , 'create only' option list, 'amend 
only' option list,
and 'common' option list.
What do you think?


[...]

Best regards,
Maxim Levitsky







Re: [Qemu-devel] [PATCH 10/10] iotests : add tests for encryption key management

2019-09-06 Thread Daniel P . Berrangé
On Fri, Aug 30, 2019 at 11:56:08PM +0300, Maxim Levitsky wrote:
> Note that currently I add tests 300-302, which are
> placeholders to ease the rebase. In final version
> of these patches I will update these.
> 
> Signed-off-by: Maxim Levitsky 
> ---
>  tests/qemu-iotests/087.out   |   6 +-
>  tests/qemu-iotests/134.out   |   2 +-
>  tests/qemu-iotests/158.out   |   4 +-
>  tests/qemu-iotests/188.out   |   2 +-
>  tests/qemu-iotests/189.out   |   4 +-
>  tests/qemu-iotests/198.out   |   4 +-
>  tests/qemu-iotests/300   | 202 +
>  tests/qemu-iotests/300.out   |  98 
>  tests/qemu-iotests/301   |  90 +++
>  tests/qemu-iotests/301.out   |  30 
>  tests/qemu-iotests/302   | 247 +++
>  tests/qemu-iotests/302.out   |  18 +++
>  tests/qemu-iotests/common.filter |   6 +-
>  tests/qemu-iotests/group |   8 +
>  14 files changed, 708 insertions(+), 13 deletions(-)
>  create mode 100755 tests/qemu-iotests/300
>  create mode 100644 tests/qemu-iotests/300.out
>  create mode 100755 tests/qemu-iotests/301
>  create mode 100644 tests/qemu-iotests/301.out
>  create mode 100644 tests/qemu-iotests/302
>  create mode 100644 tests/qemu-iotests/302.out
> 
> diff --git a/tests/qemu-iotests/087.out b/tests/qemu-iotests/087.out
> index 2d92ea847b..b61ba638af 100644
> --- a/tests/qemu-iotests/087.out
> +++ b/tests/qemu-iotests/087.out
> @@ -34,7 +34,7 @@ QMP_VERSION
>  
>  === Encrypted image QCow ===
>  
> -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on 
> encrypt.key-secret=sec0
> +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on

Why is the output format changing ? There's no code changes in
this patch. If the change is due to an earlier patch, then this
patch chunk should be put in the earlier patch that causes it.

Likewise for the changed output to other files in this patch.

>  Testing:
>  QMP_VERSION
>  {"return": {}}
> @@ -46,7 +46,7 @@ QMP_VERSION
>  
>  === Encrypted image LUKS ===
>  
> -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 
> encrypt.format=luks encrypt.key-secret=sec0
> +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728
>  Testing:
>  QMP_VERSION
>  {"return": {}}
> @@ -58,7 +58,7 @@ QMP_VERSION
>  
>  === Missing driver ===
>  
> -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on 
> encrypt.key-secret=sec0
> +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on
>  Testing: -S
>  QMP_VERSION
>  {"return": {}}
> diff --git a/tests/qemu-iotests/134.out b/tests/qemu-iotests/134.out
> index 09d46f6b17..4abc5b5f7d 100644
> --- a/tests/qemu-iotests/134.out
> +++ b/tests/qemu-iotests/134.out
> @@ -1,5 +1,5 @@
>  QA output created by 134
> -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on 
> encrypt.key-secret=sec0
> +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on
>  
>  == reading whole image ==
>  read 134217728/134217728 bytes at offset 0
> diff --git a/tests/qemu-iotests/158.out b/tests/qemu-iotests/158.out
> index 6def216e55..f28a17626b 100644
> --- a/tests/qemu-iotests/158.out
> +++ b/tests/qemu-iotests/158.out
> @@ -1,6 +1,6 @@
>  QA output created by 158
>  == create base ==
> -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 encryption=on 
> encrypt.key-secret=sec0
> +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=134217728 encryption=on
>  
>  == writing whole image ==
>  wrote 134217728/134217728 bytes at offset 0
> @@ -10,7 +10,7 @@ wrote 134217728/134217728 bytes at offset 0
>  read 134217728/134217728 bytes at offset 0
>  128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
>  == create overlay ==
> -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 
> backing_file=TEST_DIR/t.IMGFMT.base encryption=on encrypt.key-secret=sec0
> +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 
> backing_file=TEST_DIR/t.IMGFMT.base encryption=on
>  
>  == writing part of a cluster ==
>  wrote 1024/1024 bytes at offset 0
> diff --git a/tests/qemu-iotests/188.out b/tests/qemu-iotests/188.out
> index c568ef3701..5426861b18 100644
> --- a/tests/qemu-iotests/188.out
> +++ b/tests/qemu-iotests/188.out
> @@ -1,5 +1,5 @@
>  QA output created by 188
> -Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=16777216 encrypt.format=luks 
> encrypt.key-secret=sec0 encrypt.iter-time=10
> +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=16777216
>  
>  == reading whole image ==
>  read 16777216/16777216 bytes at offset 0
> diff --git a/tests/qemu-iotests/189.out b/tests/qemu-iotests/189.out
> index a0b7c9c24c..bc213cbe14 100644
> --- a/tests/qemu-iotests/189.out
> +++ b/tests/qemu-iotests/189.out
> @@ -1,6 +1,6 @@
>  QA output created by 189
>  == create base ==
> -Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=16777216 
> encrypt.format=luks encrypt.key-secret=sec0 encrypt.iter-time=10
> +Formatting 

[Qemu-devel] [PATCH] migration: Fix postcopy bw for recovery

2019-09-06 Thread Peter Xu
We've got max-postcopy-bandwidth parameter but it's not applied
correctly after a postcopy recovery so the recovered migration stream
will still eat the whole net bandwidth.  Fix that up.

Reported-by: Xiaohui Li 
Signed-off-by: Peter Xu 
---
 migration/migration.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/migration/migration.c b/migration/migration.c
index 8b9f2fe30a..b307813aa3 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -3327,7 +3327,8 @@ void migrate_fd_connect(MigrationState *s, Error 
*error_in)
 
 if (resume) {
 /* This is a resumed migration */
-rate_limit = INT64_MAX;
+rate_limit = s->parameters.max_postcopy_bandwidth /
+XFER_LIMIT_RATIO;
 } else {
 /* This is a fresh new migration */
 rate_limit = s->parameters.max_bandwidth / XFER_LIMIT_RATIO;
-- 
2.21.0




Re: [Qemu-devel] [PATCH v2 09/13] qcrypto-block: extract check and parse header

2019-09-06 Thread Daniel P . Berrangé
On Mon, Aug 26, 2019 at 04:50:59PM +0300, Maxim Levitsky wrote:
> This is just to make qcrypto_block_luks_open more
> reasonable in size.
> 
> Signed-off-by: Maxim Levitsky 
> ---
>  crypto/block-luks.c | 254 +---
>  1 file changed, 146 insertions(+), 108 deletions(-)
> 
> diff --git a/crypto/block-luks.c b/crypto/block-luks.c
> index b4dc6fc899..cc9a52c9af 100644
> --- a/crypto/block-luks.c
> +++ b/crypto/block-luks.c
> @@ -508,6 +508,148 @@ fail:
>  return ret;
>  }
>  
> +/*
> + * Does basic sanity checks on the LUKS header
> + */
> +static int
> +qcrypto_block_luks_check_header(const QCryptoBlockLUKS *luks, Error **errp)
> +{
> +int ret;
> +
> +if (memcmp(luks->header.magic, qcrypto_block_luks_magic,
> +   QCRYPTO_BLOCK_LUKS_MAGIC_LEN) != 0) {
> +error_setg(errp, "Volume is not in LUKS format");
> +ret = -EINVAL;
> +goto fail;
> +}

Just 'return -1' here immediately - don't return an errno, as we're
using Error objects for reporting.

> +
> +if (luks->header.version != QCRYPTO_BLOCK_LUKS_VERSION) {
> +error_setg(errp, "LUKS version %" PRIu32 " is not supported",
> +   luks->header.version);
> +ret = -ENOTSUP;
> +goto fail;
> +}
> +
> +return 0;
> +fail:
> +return ret;
> +}
> +
> +/*
> + * Parses the crypto parameters that are stored in the LUKS header
> + */
> +
> +static int
> +qcrypto_block_luks_parse_header(QCryptoBlockLUKS *luks, Error **errp)
> +{
> +g_autofree char *cipher_mode = g_strdup(luks->header.cipher_mode);
> +char *ivgen_name, *ivhash_name;
> +int ret = -1;
> +Error *local_err = NULL;
> +
> +/*
> + * The cipher_mode header contains a string that we have
> + * to further parse, of the format
> + *
> + *-[:]
> + *
> + * eg  cbc-essiv:sha256, cbc-plain64
> + */
> +ivgen_name = strchr(cipher_mode, '-');
> +if (!ivgen_name) {
> +ret = -EINVAL;

Again, don't use errnos - just return -1 in this method.

> +error_setg(errp, "Unexpected cipher mode string format %s",
> +   luks->header.cipher_mode);
> +goto out;
> +}
> +*ivgen_name = '\0';
> +ivgen_name++;
> +
> +ivhash_name = strchr(ivgen_name, ':');
> +if (!ivhash_name) {
> +luks->ivgen_hash_alg = 0;
> +} else {
> +*ivhash_name = '\0';
> +ivhash_name++;
> +
> +luks->ivgen_hash_alg = 
> qcrypto_block_luks_hash_name_lookup(ivhash_name,
> +   
> _err);
> +if (local_err) {
> +ret = -ENOTSUP;
> +error_propagate(errp, local_err);
> +goto out;
> +}
> +}
> +
> +luks->cipher_mode = qcrypto_block_luks_cipher_mode_lookup(cipher_mode,
> +  _err);
> +if (local_err) {
> +ret = -ENOTSUP;
> +error_propagate(errp, local_err);
> +goto out;
> +}
> +
> +luks->cipher_alg =
> +qcrypto_block_luks_cipher_name_lookup(luks->header.cipher_name,
> +  luks->cipher_mode,
> +  
> luks->header.master_key_len,
> +  _err);
> +if (local_err) {
> +ret = -ENOTSUP;
> +error_propagate(errp, local_err);
> +goto out;
> +}
> +
> +luks->hash_alg =
> +qcrypto_block_luks_hash_name_lookup(luks->header.hash_spec,
> +   _err);
> +if (local_err) {
> +ret = -ENOTSUP;
> +error_propagate(errp, local_err);
> +goto out;
> +}
> +
> +luks->ivgen_alg = qcrypto_block_luks_ivgen_name_lookup(ivgen_name,
> +   _err);
> +if (local_err) {
> +ret = -ENOTSUP;
> +error_propagate(errp, local_err);
> +goto out;
> +}
> +
> +if (luks->ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) {
> +if (!ivhash_name) {
> +ret = -EINVAL;
> +error_setg(errp, "Missing IV generator hash specification");
> +goto out;
> +}
> +luks->ivgen_cipher_alg =
> +qcrypto_block_luks_essiv_cipher(luks->cipher_alg,
> +luks->ivgen_hash_alg,
> +_err);
> +if (local_err) {
> +ret = -ENOTSUP;
> +error_propagate(errp, local_err);
> +goto out;
> +}
> +} else {
> +
> +/*
> + * Note we parsed the ivhash_name earlier in the cipher_mode
> + * spec string even with plain/plain64 ivgens, but we
> + * will ignore it, since it is irrelevant for these ivgens.
> + * This is for compat with dm-crypt which will silently
> +

Re: [Qemu-devel] [PATCH v2 11/13] qcrypto-luks: refactoring: simplify the math used for keyslot locations

2019-09-06 Thread Daniel P . Berrangé
On Mon, Aug 26, 2019 at 04:51:01PM +0300, Maxim Levitsky wrote:
> Signed-off-by: Maxim Levitsky 
> ---
>  crypto/block-luks.c | 64 +
>  1 file changed, 41 insertions(+), 23 deletions(-)
> 
> diff --git a/crypto/block-luks.c b/crypto/block-luks.c
> index d713125925..6a43d97ce5 100644
> --- a/crypto/block-luks.c
> +++ b/crypto/block-luks.c
> @@ -409,6 +409,32 @@ qcrypto_block_luks_essiv_cipher(QCryptoCipherAlgorithm 
> cipher,
>  }
>  }
>  
> +/*
> + * Returns number of sectors needed to store the key material
> + * given number of anti forensic stripes
> + */
> +static int
> +qcrypto_block_luks_splitkeylen_sectors(const QCryptoBlockLUKS *luks,
> +   unsigned int stripes)
> +{
> +/*
> + * This calculation doesn't match that shown in the spec,
> + * but instead follows the cryptsetup implementation.
> + */
> +
> +size_t header_sectors = QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET /
> +QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;

The caller already calculated that so just pass it in

> +
> +size_t splitkeylen = luks->header.master_key_len * stripes;
> +
> +/* First align the key material size to block size*/
> +size_t splitkeylen_sectors =
> +DIV_ROUND_UP(splitkeylen, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE);
> +
> +/* Then also align the key material size to the size of the header */
> +return ROUND_UP(splitkeylen_sectors, header_sectors);
> +}
> +
>  /*
>   * Stores the main LUKS header, taking care of endianess
>   */
> @@ -1151,7 +1177,8 @@ qcrypto_block_luks_create(QCryptoBlock *block,
>  QCryptoBlockCreateOptionsLUKS luks_opts;
>  Error *local_err = NULL;
>  g_autofree uint8_t *masterkey = NULL;
> -size_t splitkeylen = 0;
> +size_t header_sectors;
> +size_t split_key_sectors;
>  size_t i;
>  g_autofree char *password;
>  const char *cipher_alg;
> @@ -1370,37 +1397,28 @@ qcrypto_block_luks_create(QCryptoBlock *block,
>  goto error;
>  }
>  
> +/* start with the sector that follows the header*/
> +header_sectors = QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET /
> +QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
> +
> +split_key_sectors =
> +qcrypto_block_luks_splitkeylen_sectors(luks,
> +   QCRYPTO_BLOCK_LUKS_STRIPES);
>  
> -/* Although LUKS has multiple key slots, we're just going
> - * to use the first key slot */
> -splitkeylen = luks->header.master_key_len * QCRYPTO_BLOCK_LUKS_STRIPES;
>  for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
> -luks->header.key_slots[i].active = 
> QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED;
> -luks->header.key_slots[i].stripes = QCRYPTO_BLOCK_LUKS_STRIPES;
> +QCryptoBlockLUKSKeySlot *slot = >header.key_slots[i];
> +slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED;
>  
> -/* This calculation doesn't match that shown in the spec,
> - * but instead follows the cryptsetup implementation.
> - */
> -luks->header.key_slots[i].key_offset_sector =
> -(QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET /
> - QCRYPTO_BLOCK_LUKS_SECTOR_SIZE) +
> -(ROUND_UP(DIV_ROUND_UP(splitkeylen, 
> QCRYPTO_BLOCK_LUKS_SECTOR_SIZE),
> -  (QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET /
> -   QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) * i);
> +slot->key_offset_sector = header_sectors + i * split_key_sectors;
> +slot->stripes = QCRYPTO_BLOCK_LUKS_STRIPES;
>  }
>  
> -
>  /* The total size of the LUKS headers is the partition header + key
>   * slot headers, rounded up to the nearest sector, combined with
>   * the size of each master key material region, also rounded up
>   * to the nearest sector */
> -luks->header.payload_offset_sector =
> -(QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET /
> - QCRYPTO_BLOCK_LUKS_SECTOR_SIZE) +
> -(ROUND_UP(DIV_ROUND_UP(splitkeylen, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE),
> -  (QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET /
> -   QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) *
> - QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS);
> +luks->header.payload_offset_sector = header_sectors +
> +QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS * split_key_sectors;
>  
>  block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
>  block->payload_offset = luks->header.payload_offset_sector *

Reviewed-by: Daniel P. Berrangé 

Regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|



Re: [Qemu-devel] [PATCH v2 13/13] qcrypto-luks: implement more rigorous header checking

2019-09-06 Thread Daniel P . Berrangé
On Mon, Aug 26, 2019 at 04:51:03PM +0300, Maxim Levitsky wrote:
> Check that keyslots don't overlap with the data,
> and check that keyslots don't overlap with each other.
> (this is done using naive O(n^2) nested loops,
> but since there are just 8 keyslots, this doesn't really matter.
> 
> Signed-off-by: Maxim Levitsky 
> ---
>  crypto/block-luks.c | 46 +++--
>  1 file changed, 44 insertions(+), 2 deletions(-)
> 
> diff --git a/crypto/block-luks.c b/crypto/block-luks.c
> index db0fb764b4..fdf4c41f8a 100644
> --- a/crypto/block-luks.c
> +++ b/crypto/block-luks.c
> @@ -541,12 +541,12 @@ fail:
>  static int
>  qcrypto_block_luks_check_header(const QCryptoBlockLUKS *luks, Error **errp)
>  {
> -int ret;
> +int ret = -EINVAL;

As before, no need to use errnos, just return -1 immediately.

> +size_t i, j;
>  
>  if (memcmp(luks->header.magic, qcrypto_block_luks_magic,
> QCRYPTO_BLOCK_LUKS_MAGIC_LEN) != 0) {
>  error_setg(errp, "Volume is not in LUKS format");
> -ret = -EINVAL;
>  goto fail;
>  }
>  
> @@ -557,6 +557,48 @@ qcrypto_block_luks_check_header(const QCryptoBlockLUKS 
> *luks, Error **errp)
>  goto fail;
>  }
>  
> +/* Check all keyslots for corruption  */
> +for (i = 0 ; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS ; i++) {
> +
> +const QCryptoBlockLUKSKeySlot *slot1 = >header.key_slots[i];
> +unsigned int start1 = slot1->key_offset_sector;
> +unsigned int len1 =
> +qcrypto_block_luks_splitkeylen_sectors(luks, slot1->stripes);
> +
> +if (slot1->stripes == 0) {
> +error_setg(errp, "Keyslot %zu is corrupted (stripes == 0)", i);
> +goto fail;
> +}

How about checking stripes != QCRYPTO_BLOCK_LUKS_STRIPES because
AFAIR, you're required to use 4k stripes in luks v1.

Also how about  checkingiters >= MIN_SLOT_KEY_ITERS

> +
> +if (slot1->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED &&
> +slot1->active != QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED) {

Align the two lines with (

> +error_setg(errp,
> +   "Keyslot %zu state (active/disable) is corrupted", i);
> +goto fail;
> +}
> +
> +if (start1 + len1 > luks->header.payload_offset_sector) {
> +error_setg(errp,
> +   "Keyslot %zu is overlapping with the encrypted 
> payload",
> +   i);
> +goto fail;
> +}
> +
> +for (j = i + 1 ; j < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS ; j++) {
> +const QCryptoBlockLUKSKeySlot *slot2 = 
> >header.key_slots[j];
> +unsigned int start2 = slot2->key_offset_sector;
> +unsigned int len2 =
> +qcrypto_block_luks_splitkeylen_sectors(luks, slot2->stripes);
> +
> +if (start1 + len1 > start2 && start2 + len2 > start1) {
> +error_setg(errp,
> +   "Keyslots %zu and %zu are overlapping in the 
> header",
> +   i, j);
> +goto fail;
> +}
> +}
> +
> +}
>  return 0;
>  fail:
>  return ret;
> -- 
> 2.17.2
> 

Regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|



Re: [Qemu-devel] [PATCH] migration: Fix postcopy bw for recovery

2019-09-06 Thread Juan Quintela
Peter Xu  wrote:
> We've got max-postcopy-bandwidth parameter but it's not applied
> correctly after a postcopy recovery so the recovered migration stream
> will still eat the whole net bandwidth.  Fix that up.
>
> Reported-by: Xiaohui Li 
> Signed-off-by: Peter Xu 
> ---
>  migration/migration.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)

Reviewed-by: Juan Quintela 

> diff --git a/migration/migration.c b/migration/migration.c
> index 8b9f2fe30a..b307813aa3 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -3327,7 +3327,8 @@ void migrate_fd_connect(MigrationState *s, Error 
> *error_in)
>  
>  if (resume) {
>  /* This is a resumed migration */
> -rate_limit = INT64_MAX;
> +rate_limit = s->parameters.max_postcopy_bandwidth /
> +XFER_LIMIT_RATIO;
>  } else {
>  /* This is a fresh new migration */
>  rate_limit = s->parameters.max_bandwidth / XFER_LIMIT_RATIO;

I was confused thinking that the two assignations were the same O:-)



Re: [Qemu-devel] [PATCH 01/10] qcrypto: add suport for amend options

2019-09-06 Thread Daniel P . Berrangé
On Fri, Aug 30, 2019 at 11:55:59PM +0300, Maxim Levitsky wrote:
> This adds the qcrypto_amend_options and corresponding
> crypto driver callbacks for the  for encrypted
> key managedment
> 
> Signed-off-by: Maxim Levitsky 
> ---
>  crypto/block.c | 31 +++
>  crypto/blockpriv.h |  8 
>  include/crypto/block.h | 22 ++
>  3 files changed, 61 insertions(+)

Reviewed-by: Daniel P. Berrangé 


Regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|



Re: [Qemu-devel] [PATCH 03/10] qcrypto-luks: implement the encryption key management

2019-09-06 Thread Daniel P . Berrangé
On Fri, Aug 30, 2019 at 11:56:01PM +0300, Maxim Levitsky wrote:
> Signed-off-by: Maxim Levitsky 
> ---
>  crypto/block-luks.c | 366 +++-
>  1 file changed, 364 insertions(+), 2 deletions(-)
> 
> diff --git a/crypto/block-luks.c b/crypto/block-luks.c
> index ba20d55246..21325fbc79 100644
> --- a/crypto/block-luks.c
> +++ b/crypto/block-luks.c
> @@ -70,6 +70,9 @@ typedef struct QCryptoBlockLUKSKeySlot 
> QCryptoBlockLUKSKeySlot;
>  
>  #define QCRYPTO_BLOCK_LUKS_SECTOR_SIZE 512LL
>  
> +#define QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME 2000

Perhaps use  ITER_TIME_MS to make it clear it is millisecs

> +#define QCRYPTO_BLOCK_LUKS_ERASE_ITERATIONS 40
> +
>  static const char qcrypto_block_luks_magic[QCRYPTO_BLOCK_LUKS_MAGIC_LEN] = {
>  'L', 'U', 'K', 'S', 0xBA, 0xBE
>  };
> @@ -219,6 +222,9 @@ struct QCryptoBlockLUKS {
>  
>  /* Hash algorithm used in pbkdf2 function */
>  QCryptoHashAlgorithm hash_alg;
> +
> +/* Name of the secret that was used to open the image */
> +char *secret;

> +
> +/*
> + * Returns true if a slot i is marked as active
> + * (contains encrypted copy of the master key)
> + */
> +
> +static bool

No blank line is wanted between the comment & function.
Likewise for the rest of this patch series

> +qcrypto_block_luks_slot_active(const QCryptoBlockLUKS *luks,
> +   unsigned int slot_idx)
> +{
> +uint32_t val = luks->header.key_slots[slot_idx].active;
> +return val ==  QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED;
> +}



> +static int
> +qcrypto_block_luks_erase_key(QCryptoBlock *block,
> + unsigned int slot_idx,
> + QCryptoBlockWriteFunc writefunc,
> + void *opaque,
> + Error **errp)
> +{
> +QCryptoBlockLUKS *luks = block->opaque;
> +QCryptoBlockLUKSKeySlot *slot = >header.key_slots[slot_idx];
> +g_autofree uint8_t *garbagesplitkey = NULL;
> +size_t splitkeylen = luks->header.master_key_len * slot->stripes;
> +size_t i;
> +
> +assert(slot_idx < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS);
> +assert(splitkeylen > 0);
> +
> +garbagesplitkey = g_malloc0(splitkeylen);

I'd prefer   g_new0(uint8_t, splitkeylen)

> +
> +/* Reset the key slot header */
> +memset(slot->salt, 0, QCRYPTO_BLOCK_LUKS_SALT_LEN);
> +slot->iterations = 0;
> +slot->active = QCRYPTO_BLOCK_LUKS_KEY_SLOT_DISABLED;
> +


> @@ -1522,6 +1700,187 @@ qcrypto_block_luks_create(QCryptoBlock *block,
>  }
>  
>  
> +#define CHECK_NON_AMEND_OPTION(luks, luks_opts, name) \
> +if (luks_opts.has_##name && luks_opts.name != luks->name) { \
> +error_setg(errp, "Option \"" #name "\" can't be amended"); \
> +goto cleanup; \
> +}
> +
> +static int
> +qcrypto_block_luks_amend_options(QCryptoBlock *block,
> + QCryptoBlockReadFunc readfunc,
> + QCryptoBlockWriteFunc writefunc,
> + void *opaque,
> + QCryptoBlockCreateOptions *options,
> + bool force,
> + Error **errp)
> +{
> +QCryptoBlockLUKS *luks = block->opaque;
> +QCryptoBlockCreateOptionsLUKS luks_opts;
> +g_autofree char *old_password = NULL;
> +g_autofree char *password = NULL;
> +const char *unlock_secret = luks->secret;
> +g_autofree uint8_t *masterkey = NULL;
> +int slot = -1;
> +int ret = -1;
> +bool active = true;
> +int64_t iter_time = QCRYPTO_BLOCK_LUKS_DEFAULT_ITER_TIME;
> +
> +memcpy(_opts, >u.luks, sizeof(luks_opts));
> +
> +CHECK_NON_AMEND_OPTION(luks, luks_opts, cipher_alg);
> +CHECK_NON_AMEND_OPTION(luks, luks_opts, cipher_mode);
> +CHECK_NON_AMEND_OPTION(luks, luks_opts, ivgen_alg);
> +CHECK_NON_AMEND_OPTION(luks, luks_opts, ivgen_hash_alg);
> +CHECK_NON_AMEND_OPTION(luks, luks_opts, hash_alg);
> +
> +/* Read given slot and check it */
> +if (luks_opts.has_slot) {
> +slot = luks_opts.slot;
> +if (slot < 0 || slot >= QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS) {
> +error_setg(errp,
> +   "Given key slot %i is not supported by LUKS", slot);
> + goto cleanup;

Off by 1 one indent

> +}
> +}
> +
> +if (luks_opts.has_iter_time) {
> +iter_time = luks_opts.iter_time;
> +}
> +
> +if (luks_opts.has_active && luks_opts.active == false) {
> +active = false;
> +}
> +
> +if (active) {
> +
> +/* Check that we are not overwriting an active slot */
> +if (!force && slot != -1 &&
> +qcrypto_block_luks_slot_active(luks, slot)) {
> +
> +error_setg(errp, "Can't update an active key slot %i",
> +   slot);
> +goto cleanup;
> +}
> +
> +/* check that we have the passwords*/
> +if 

Re: [Qemu-devel] [PATCH 04/10] block: amend: add 'force' option

2019-09-06 Thread Daniel P . Berrangé
On Fri, Aug 30, 2019 at 11:56:02PM +0300, Maxim Levitsky wrote:

This could do with some text to explain what this will be
used for.

> Signed-off-by: Maxim Levitsky 
> ---
>  block.c   | 4 +++-
>  block/qcow2.c | 1 +
>  include/block/block.h | 1 +
>  include/block/block_int.h | 1 +
>  qemu-img-cmds.hx  | 4 ++--
>  qemu-img.c| 8 +++-
>  qemu-img.texi | 6 +-
>  7 files changed, 20 insertions(+), 5 deletions(-)

For the code

Reviewed-by: Daniel P. Berrangé 


Regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|



Re: [Qemu-devel] [PATCH 06/10] qcow2: implement crypto amend options

2019-09-06 Thread Daniel P . Berrangé
On Fri, Aug 30, 2019 at 11:56:04PM +0300, Maxim Levitsky wrote:
> ---
>  block/qcow2.c | 79 ---
>  1 file changed, 63 insertions(+), 16 deletions(-)
> 

> @@ -4888,9 +4899,22 @@ static int qcow2_amend_options(BlockDriverState *bs, 
> QemuOpts *opts,
>  return -ENOTSUP;
>  }
>  } else if (g_str_has_prefix(desc->name, "encrypt.")) {
> -error_setg(errp,
> -   "Changing the encryption parameters is not 
> supported");
> -return -ENOTSUP;
> +
> +if (!s->crypto) {
> +error_setg(errp,
> +   "Can't amend encryption options - encryption not 
> supported");
> +return -ENOTSUP;
> +
> +}

Perhaps  ' - encryption not present', and -EINVAL

> +
> +if (s->crypt_method_header != QCOW_CRYPT_LUKS) {
> +error_setg(errp,
> +   "Only LUKS encryption options can be amended");
> +return -ENOTSUP;
> +}
> +
> +encryption_update = true;
> +
>  } else if (!strcmp(desc->name, BLOCK_OPT_CLUSTER_SIZE)) {
>  cluster_size = qemu_opt_get_size(opts, BLOCK_OPT_CLUSTER_SIZE,
>   cluster_size);
> @@ -4927,7 +4951,7 @@ static int qcow2_amend_options(BlockDriverState *bs, 
> QemuOpts *opts,
>   "images");
>  return -EINVAL;
>  }
> -} else {
> +} else  {

Accidental change

>  /* if this point is reached, this probably means a new option was
>   * added without having it covered here */
>  abort();
> @@ -4940,7 +4964,8 @@ static int qcow2_amend_options(BlockDriverState *bs, 
> QemuOpts *opts,
>  .original_status_cb = status_cb,
>  .original_cb_opaque = cb_opaque,
>  .total_operations = (new_version < old_version)
> -  + (s->refcount_bits != refcount_bits)
> +  + (s->refcount_bits != refcount_bits) +
> +  (encryption_update == true)
>  };
>  
>  /* Upgrade first (some features may require compat=1.1) */
> @@ -4954,6 +4979,28 @@ static int qcow2_amend_options(BlockDriverState *bs, 
> QemuOpts *opts,
>  }
>  }
>  
> +if (encryption_update) {
> +

Redundant blank line

> +QCryptoBlockCreateOptions *cryptoopts;
> +
> +cryptoopts = qcow2_extract_crypto_create_opts(opts, "luks", errp);
> +if (!cryptoopts)
> +return -EINVAL;
> +
> +helper_cb_info.current_operation = QCOW2_UPDATING_ENCRYPTION;
> +
> +ret = qcrypto_block_amend_options(s->crypto,
> +  qcow2_crypto_hdr_read_func,
> +  qcow2_crypto_hdr_write_func,
> +  bs,
> +  cryptoopts,
> +  force,
> +  errp);
> +if (ret) {

Check  ret < 0

> +return ret;
> +}
> +}
> +

Regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|



Re: [Qemu-devel] [PATCH 09/10] block/qcow2: implement blockdev-amend

2019-09-06 Thread Daniel P . Berrangé
On Fri, Aug 30, 2019 at 11:56:07PM +0300, Maxim Levitsky wrote:
> Currently only for changing crypto parameters
> 
> Signed-off-by: Maxim Levitsky 
> ---
>  block/qcow2.c| 71 
>  qapi/block-core.json |  4 +--
>  2 files changed, 73 insertions(+), 2 deletions(-)
> 
> diff --git a/block/qcow2.c b/block/qcow2.c
> index 8dff4c6b5f..327d2afd9f 100644
> --- a/block/qcow2.c
> +++ b/block/qcow2.c
> @@ -3082,6 +3082,18 @@ qcow2_co_create(BlockdevCreateOptions *create_options, 
> Error **errp)
>  assert(create_options->driver == BLOCKDEV_DRIVER_QCOW2);
>  qcow2_opts = _options->u.qcow2;
>  
> +if (!qcow2_opts->has_size) {
> +error_setg(errp, "Size is manadatory for image creation");
> +return -EINVAL;
> +
> +}
> +
> +if (!qcow2_opts->has_file) {
> +error_setg(errp, "'file' is manadatory for image creation");
> +return -EINVAL;
> +
> +}
> +
>  bs = bdrv_open_blockdev_ref(qcow2_opts->file, errp);
>  if (bs == NULL) {
>  return -EIO;
> @@ -5112,6 +5124,64 @@ static int qcow2_amend_options(BlockDriverState *bs, 
> QemuOpts *opts,
>  return 0;
>  }
>  
> +
> +static int coroutine_fn qcow2_co_amend(BlockDriverState *bs,
> +   BlockdevCreateOptions *opts,
> +   bool force,
> +   Error **errp)
> +{
> +BlockdevCreateOptionsQcow2 *qopts = >u.qcow2;
> +BDRVQcow2State *s = bs->opaque;
> +int ret;
> +
> +/*
> + * This is ugly as hell, in later versions of this patch
> + * something has to be done about this
> + */
> +if (qopts->has_file || qopts->has_size || qopts->has_data_file ||
> +qopts->has_data_file_raw || qopts->has_version ||
> +qopts->has_backing_file || qopts->has_backing_fmt ||
> +qopts->has_cluster_size || qopts->has_preallocation ||
> +qopts->has_lazy_refcounts || qopts->has_refcount_bits) {
> +
> +error_setg(errp,
> +"Only LUKS encryption options can be amended for qcow2 with 
> blockdev-amend");
> +return -EOPNOTSUPP;
> +
> +}
> +
> +if (qopts->has_encrypt) {
> +if (!s->crypto) {
> +error_setg(errp, "QCOW2 image is not encrypted, can't amend");
> +return -EOPNOTSUPP;
> +}
> +
> +if (qopts->encrypt->format != Q_CRYPTO_BLOCK_FORMAT_LUKS) {
> +error_setg(errp,
> +   "Amend can't be used to change the qcow2 encryption 
> format");
> +return -EOPNOTSUPP;
> +}
> +
> +if (s->crypt_method_header != QCOW_CRYPT_LUKS) {
> +error_setg(errp,
> +   "Only LUKS encryption options can be amended for 
> qcow2 with blockdev-amend");
> +return -EOPNOTSUPP;
> +}
> +
> +ret = qcrypto_block_amend_options(s->crypto,
> +  qcow2_crypto_hdr_read_func,
> +  qcow2_crypto_hdr_write_func,
> +  bs,
> +  qopts->encrypt,
> +  force,
> +  errp);
> +if (ret) {
> +return ret;
> +}
> +}
> +return 0;
> +}
> +
>  /*
>   * If offset or size are negative, respectively, they will not be included in
>   * the BLOCK_IMAGE_CORRUPTED event emitted.
> @@ -5304,6 +5374,7 @@ BlockDriver bdrv_qcow2 = {
>  .mutable_opts= mutable_opts,
>  .bdrv_co_check   = qcow2_co_check,
>  .bdrv_amend_options  = qcow2_amend_options,
> +.bdrv_co_amend   = qcow2_co_amend,
>  
>  .bdrv_detach_aio_context  = qcow2_detach_aio_context,
>  .bdrv_attach_aio_context  = qcow2_attach_aio_context,
> diff --git a/qapi/block-core.json b/qapi/block-core.json
> index 02375fb59a..ba41744427 100644
> --- a/qapi/block-core.json
> +++ b/qapi/block-core.json
> @@ -4312,10 +4312,10 @@
>  # Since: 2.12
>  ##
>  { 'struct': 'BlockdevCreateOptionsQcow2',
> -  'data': { 'file': 'BlockdevRef',
> +  'data': { '*file':'BlockdevRef',
>  '*data-file':   'BlockdevRef',
>  '*data-file-raw':   'bool',
> -'size': 'size',
> +'*size':'size',
>  '*version': 'BlockdevQcow2Version',
>  '*backing-file':'str',
>  '*backing-fmt': 'BlockdevDriver',

Docs comment to say they  are mandatory for creation.


Regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|



Re: [Qemu-devel] [PATCH 02/10] qcrypto-luks: extend the create options for upcoming encryption key management

2019-09-06 Thread Daniel P . Berrangé
On Fri, Sep 06, 2019 at 04:57:22PM +0300, Maxim Levitsky wrote:
> On Fri, 2019-09-06 at 14:49 +0100, Daniel P. Berrangé wrote:
> > On Fri, Aug 30, 2019 at 11:56:00PM +0300, Maxim Levitsky wrote:
> > > Now you can specify which slot to put the encryption key to
> > > Plus add 'active' option which will let  user erase the key secret
> > > instead of adding it.
> > > Check that it is true for creation
> > > 
> > > Signed-off-by: Maxim Levitsky 
> > > ---
> > >  block/crypto.c |  2 ++
> > >  block/crypto.h | 16 +++
> > >  block/qcow2.c  |  2 ++
> > >  crypto/block-luks.c| 26 +++---
> > >  qapi/crypto.json   | 19 ++
> > >  tests/qemu-iotests/082.out | 54 ++
> > >  6 files changed, 115 insertions(+), 4 deletions(-)
> > > 
> > > diff --git a/block/crypto.c b/block/crypto.c
> > > index 6e822c6e50..a6a3e1f1d8 100644
> > > --- a/block/crypto.c
> > > +++ b/block/crypto.c
> > > @@ -144,6 +144,8 @@ static QemuOptsList block_crypto_create_opts_luks = {
> > >  BLOCK_CRYPTO_OPT_DEF_LUKS_IVGEN_HASH_ALG(""),
> > >  BLOCK_CRYPTO_OPT_DEF_LUKS_HASH_ALG(""),
> > >  BLOCK_CRYPTO_OPT_DEF_LUKS_ITER_TIME(""),
> > > +BLOCK_CRYPTO_OPT_DEF_LUKS_SLOT(""),
> > > +BLOCK_CRYPTO_OPT_DEF_LUKS_ACTIVE(""),
> > >  { /* end of list */ }
> > >  },
> > >  };
> > > diff --git a/block/crypto.h b/block/crypto.h
> > > index b935695e79..05cc43d9bc 100644
> > > --- a/block/crypto.h
> > > +++ b/block/crypto.h
> > > @@ -35,12 +35,14 @@
> > >  "ID of the secret that provides the AES encryption key")
> > >  
> > >  #define BLOCK_CRYPTO_OPT_LUKS_KEY_SECRET "key-secret"
> > > +#define BLOCK_CRYPTO_OPT_LUKS_SLOT "slot"
> > >  #define BLOCK_CRYPTO_OPT_LUKS_CIPHER_ALG "cipher-alg"
> > >  #define BLOCK_CRYPTO_OPT_LUKS_CIPHER_MODE "cipher-mode"
> > >  #define BLOCK_CRYPTO_OPT_LUKS_IVGEN_ALG "ivgen-alg"
> > >  #define BLOCK_CRYPTO_OPT_LUKS_IVGEN_HASH_ALG "ivgen-hash-alg"
> > >  #define BLOCK_CRYPTO_OPT_LUKS_HASH_ALG "hash-alg"
> > >  #define BLOCK_CRYPTO_OPT_LUKS_ITER_TIME "iter-time"
> > > +#define BLOCK_CRYPTO_OPT_LUKS_ACTIVE "active"
> > >  
> > >  #define BLOCK_CRYPTO_OPT_DEF_LUKS_KEY_SECRET(prefix)\
> > >  BLOCK_CRYPTO_OPT_DEF_KEY_SECRET(prefix, \
> > > @@ -88,6 +90,20 @@
> > >  .help = "Time to spend in PBKDF in milliseconds", \
> > >  }
> > >  
> > > +#define BLOCK_CRYPTO_OPT_DEF_LUKS_SLOT(prefix)   \
> > > +{ \
> > > +.name = prefix BLOCK_CRYPTO_OPT_LUKS_SLOT,   \
> > > +.type = QEMU_OPT_NUMBER,  \
> > > +.help = "Controls the slot where the secret is added/erased",
> > >  \
> > > +}
> > > +
> > > +#define BLOCK_CRYPTO_OPT_DEF_LUKS_ACTIVE(prefix)   \
> > > +{ \
> > > +.name = prefix BLOCK_CRYPTO_OPT_LUKS_ACTIVE,   \
> > > +.type = QEMU_OPT_BOOL,  \
> > > +.help = "Controls if the added secret is added or erased", \
> > > +}
> > 
> > Do we actually need the "active" property for initial
> > creation. I think its only needed for amend, so perhaps
> > we shuold not register this at all ?
> 
> Sadly we kind of do, since both amend and create use the same option list 
> currently.
> I tried to duplicate it, and it is possible, but then you end up
> with significant code duplication in qcow2 with its huge create option list.

Ah, I see now.

> I am now thinking that we could have had , 'create only' option list, 'amend 
> only' option list,
> and 'common' option list.
> What do you think?

I'm not too fussed - either way is fine with me.


Regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|



Re: [Qemu-devel] [PATCH 1/3] block/qcow2: refactoring of threaded encryption code

2019-09-06 Thread Maxim Levitsky
On Fri, 2019-09-06 at 14:00 -0500, Eric Blake wrote:
> On 9/6/19 1:55 PM, Maxim Levitsky wrote:
> 
> > > > +/*
> > > > + * qcow2_co_encrypt()
> > > > + *
> > > > + * Encrypts a sector size aligned contiguous area
> > > > + *
> > > > + * @host_cluster_offset - on disk offset of the cluster in which
> > > > + *the buffer resides
> > > > + *
> > > > + * @guest_offset - guest (virtual) offset of the buffer
> > > > + * @buf - buffer with the data to encrypt
> > > > + * @len - length of the buffer
> > > > + *
> > > > + * Note that the area is not cluster aligned and might cross a cluster
> > > > + * boundary
> > > 
> > > Umm, how is it possible for a sector to cross a cluster boundary?  All
> > > clusters are sector-aligned, and encryption only works on aligned
> > > sectors.  Oh, I see - if @len is a multiple larger than sector size,
> > > then we have multiple sectors, and then indeed we may cross clusters.
> > > But then the docs about being 'a sector size aligned contiguous area' is
> > > not quite right.
> > 
> > Why? the written area is always both aligned on _sector_ boundary
> > and multiple of the sector size. At least that what I see from
> > the existing asserts.
> 
> I'm thinking it should read something like:
> 
> Encrypts one or more contiguous aligned sectors
> 
> to make it obvious that because there can be multiple sectors, there may
> indeed be a cluster boundary mid-length.  My complaint was that the
> original text made it sound like there was exactly one sector (at which
> point @len is redundant, unless sectors are variably-sized)
> 
I agree with you completely, I will change that.

Best regards,
Maxim Levitsky






[Qemu-devel] [RFC 2 PATCH 03/16] hw/i386: Introduce X86CPUTopoInfo to contain topology info

2019-09-06 Thread Moger, Babu
This is an effort to re-arrange few data structure for better
readability. Add X86CPUTopoInfo which will have all the topology
informations required to build the cpu topology. There is no
functional changes.

Signed-off-by: Babu Moger 
---
 hw/i386/pc.c   |   40 +++-
 include/hw/i386/topology.h |   40 ++--
 2 files changed, 53 insertions(+), 27 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index ada445f8f3..95aab8e5e7 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -930,11 +930,15 @@ static uint32_t x86_cpu_apic_id_from_index(PCMachineState 
*pcms,
 {
 MachineState *ms = MACHINE(pcms);
 PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
+X86CPUTopoInfo topo_info;
 uint32_t correct_id;
 static bool warned;
 
-correct_id = x86_apicid_from_cpu_idx(pcms->smp_dies, ms->smp.cores,
- ms->smp.threads, cpu_index);
+topo_info.nr_dies = pcms->smp_dies;
+topo_info.nr_cores = ms->smp.cores;
+topo_info.nr_threads = ms->smp.threads;
+
+correct_id = x86_apicid_from_cpu_idx(_info, cpu_index);
 if (pcmc->compat_apic_id_mode) {
 if (cpu_index != correct_id && !warned && !qtest_enabled()) {
 error_report("APIC IDs set in compatibility mode, "
@@ -2386,6 +2390,7 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
 PCMachineState *pcms = PC_MACHINE(hotplug_dev);
 unsigned int smp_cores = ms->smp.cores;
 unsigned int smp_threads = ms->smp.threads;
+X86CPUTopoInfo topo_info;
 
 if(!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) {
 error_setg(errp, "Invalid CPU type, expected cpu type: '%s'",
@@ -2393,6 +2398,10 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
 return;
 }
 
+topo_info.nr_dies = pcms->smp_dies;
+topo_info.nr_cores = smp_cores;
+topo_info.nr_threads = smp_threads;
+
 env->nr_dies = pcms->smp_dies;
 
 /*
@@ -2436,16 +2445,14 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
 topo_ids.die_id = cpu->die_id;
 topo_ids.core_id = cpu->core_id;
 topo_ids.smt_id = cpu->thread_id;
-cpu->apic_id = apicid_from_topo_ids(pcms->smp_dies, smp_cores,
-smp_threads, _ids);
+cpu->apic_id = apicid_from_topo_ids(_info, _ids);
 }
 
 cpu_slot = pc_find_cpu_slot(MACHINE(pcms), cpu->apic_id, );
 if (!cpu_slot) {
 MachineState *ms = MACHINE(pcms);
 
-x86_topo_ids_from_apicid(cpu->apic_id, pcms->smp_dies,
- smp_cores, smp_threads, _ids);
+x86_topo_ids_from_apicid(cpu->apic_id, _info, _ids);
 error_setg(errp,
 "Invalid CPU [socket: %u, die: %u, core: %u, thread: %u] with"
 " APIC ID %" PRIu32 ", valid index range 0:%d",
@@ -2466,8 +2473,7 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev,
 /* TODO: move socket_id/core_id/thread_id checks into x86_cpu_realizefn()
  * once -smp refactoring is complete and there will be CPU private
  * CPUState::nr_cores and CPUState::nr_threads fields instead of globals */
-x86_topo_ids_from_apicid(cpu->apic_id, pcms->smp_dies,
- smp_cores, smp_threads, _ids);
+x86_topo_ids_from_apicid(cpu->apic_id, _info, _ids);
 if (cpu->socket_id != -1 && cpu->socket_id != topo_ids.pkg_id) {
 error_setg(errp, "property socket-id: %u doesn't match set apic-id:"
 " 0x%x (socket-id: %u)", cpu->socket_id, cpu->apic_id, 
topo_ids.pkg_id);
@@ -2842,19 +2848,28 @@ static int64_t pc_get_default_cpu_node_id(const 
MachineState *ms, int idx)
 {
X86CPUTopoIDs topo_ids;
PCMachineState *pcms = PC_MACHINE(ms);
+   X86CPUTopoInfo topo_info;
+
+   topo_info.nr_dies = pcms->smp_dies;
+   topo_info.nr_cores = ms->smp.cores;
+   topo_info.nr_threads = ms->smp.threads;
 
assert(idx < ms->possible_cpus->len);
x86_topo_ids_from_apicid(ms->possible_cpus->cpus[idx].arch_id,
-pcms->smp_dies, ms->smp.cores,
-ms->smp.threads, _ids);
+_info, _ids);
return topo_ids.pkg_id % nb_numa_nodes;
 }
 
 static const CPUArchIdList *pc_possible_cpu_arch_ids(MachineState *ms)
 {
 PCMachineState *pcms = PC_MACHINE(ms);
-int i;
 unsigned int max_cpus = ms->smp.max_cpus;
+X86CPUTopoInfo topo_info;
+int i;
+
+topo_info.nr_dies = pcms->smp_dies;
+topo_info.nr_cores = ms->smp.cores;
+topo_info.nr_threads = ms->smp.threads;
 
 if (ms->possible_cpus) {
 /*
@@ -2875,8 +2890,7 @@ static const CPUArchIdList 
*pc_possible_cpu_arch_ids(MachineState *ms)
 ms->possible_cpus->cpus[i].vcpus_count = 1;
 ms->possible_cpus->cpus[i].arch_id = x86_cpu_apic_id_from_index(pcms, 
i);
 x86_topo_ids_from_apicid(ms->possible_cpus->cpus[i].arch_id,
- 

[Qemu-devel] [RFC 2 PATCH 07/16] hw/386: Add new epyc mode topology decoding functions

2019-09-06 Thread Moger, Babu
These functions add support for building new epyc mode topology
given smp details like numa nodes, cores, threads and sockets.
Subsequent patches will use these functions to build the topology.

The topology details are available in Processor Programming Reference (PPR)
for AMD Family 17h Model 01h, Revision B1 Processors.
It is available at https://www.amd.com/en/support/tech-docs

Signed-off-by: Babu Moger 
---
 include/hw/i386/topology.h |  174 
 1 file changed, 174 insertions(+)

diff --git a/include/hw/i386/topology.h b/include/hw/i386/topology.h
index 5a61d53f05..6fd4184f07 100644
--- a/include/hw/i386/topology.h
+++ b/include/hw/i386/topology.h
@@ -62,6 +62,22 @@ typedef struct X86CPUTopoInfo {
 unsigned nr_threads;
 } X86CPUTopoInfo;
 
+/*
+ * Definitions used for building CPUID Leaf 0x801D and 0x801E
+ * Please refer to the AMD64 Architecture Programmer’s Manual Volume 3.
+ * Define the constants to build the cpu topology. Right now, TOPOEXT
+ * feature is enabled only on EPYC. So, these constants are based on
+ * EPYC supported configurations. We may need to handle the cases if
+ * these values change in future.
+ */
+
+/* Maximum core complexes in a node */
+#define MAX_CCX  2
+/* Maximum cores in a core complex */
+#define MAX_CORES_IN_CCX 4
+/* Maximum cores in a node */
+#define MAX_CORES_IN_NODE8
+
 /* Return the bit width needed for 'count' IDs
  */
 static unsigned apicid_bitwidth_for_count(unsigned count)
@@ -116,6 +132,164 @@ static inline unsigned apicid_pkg_offset(unsigned nr_dies,
apicid_die_width(nr_dies);
 }
 
+/* Bit offset of the CCX_ID field */
+static inline unsigned apicid_ccx_offset(unsigned nr_cores,
+ unsigned nr_threads)
+{
+return apicid_core_offset(nr_threads) +
+   apicid_core_width(nr_cores);
+}
+
+/* Bit width of the Die_ID field */
+static inline unsigned apicid_ccx_width(unsigned nr_ccxs)
+{
+return apicid_bitwidth_for_count(nr_ccxs);
+}
+
+/* Bit offset of the node_id field */
+static inline unsigned apicid_node_offset(unsigned nr_ccxs,
+  unsigned nr_cores,
+  unsigned nr_threads)
+{
+return apicid_ccx_offset(nr_cores, nr_threads) +
+   apicid_ccx_width(nr_ccxs);
+}
+
+/* Bit width of the node_id field */
+static inline unsigned apicid_node_width(unsigned nr_nodes)
+{
+return apicid_bitwidth_for_count(nr_nodes);
+}
+
+/* Bit offset of the node_id field */
+static inline unsigned apicid_pkg_offset_epyc(unsigned nr_nodes,
+  unsigned nr_ccxs,
+  unsigned nr_cores,
+  unsigned nr_threads)
+{
+return apicid_node_offset(nr_ccxs, nr_cores, nr_threads) +
+   apicid_node_width(nr_nodes);
+}
+
+/*
+ * Figure out the number of nodes required to build this config.
+ * Max cores in a nodes is 8
+ */
+static inline int nodes_in_pkg(X86CPUTopoInfo *topo_info)
+{
+/*
+ * Create a config with user given (nr_nodes > 1) numa node config,
+ * else go with a standard configuration
+ */
+if (topo_info->numa_nodes > 1) {
+return DIV_ROUND_UP(topo_info->numa_nodes, topo_info->nr_sockets);
+} else {
+return DIV_ROUND_UP(topo_info->nr_cores, MAX_CORES_IN_NODE);
+}
+}
+
+/*
+ * Decide the number of cores in a core complex with the given nr_cores using
+ * following set constants MAX_CCX, MAX_CORES_IN_CCX, MAX_CORES_IN_DIE and
+ * MAX_NODES_PER_SOCKET. Maintain symmetry as much as possible
+ * L3 cache is shared across all cores in a core complex. So, this will also
+ * tell us how many cores are sharing the L3 cache.
+ */
+static inline int cores_in_ccx(X86CPUTopoInfo *topo_info)
+{
+int nodes;
+
+/* Get the number of nodes required to build this config */
+nodes = nodes_in_pkg(topo_info);
+
+/*
+ * Divide the cores accros all the core complexes
+ * Return rounded up value
+ */
+return DIV_ROUND_UP(topo_info->nr_cores, nodes * MAX_CCX);
+}
+
+/*
+ * Make APIC ID for the CPU based on Pkg_ID, Core_ID, SMT_ID
+ *
+ * The caller must make sure core_id < nr_cores and smt_id < nr_threads.
+ */
+static inline apic_id_t x86_apicid_from_topo_ids_epyc(X86CPUTopoInfo 
*topo_info,
+  const X86CPUTopoIDs 
*topo_ids)
+{
+unsigned nr_ccxs = MAX_CCX;
+unsigned nr_nodes = nodes_in_pkg(topo_info);
+unsigned nr_cores = MAX_CORES_IN_CCX;
+unsigned nr_threads = topo_info->nr_threads;
+
+return (topo_ids->pkg_id  << apicid_pkg_offset_epyc(nr_nodes, nr_ccxs,
+nr_cores, nr_threads)) 
|
+   (topo_ids->node_id  << apicid_node_offset(nr_ccxs, nr_cores,
+ nr_threads)) |
+   

[Qemu-devel] [RFC 2 PATCH 04/16] machine: Add SMP Sockets in CpuTopology

2019-09-06 Thread Moger, Babu
Store the  smp Sockets in CpuTopology. Socket information
is required to build the cpu topology in new epyc mode.

Signed-off-by: Babu Moger 
---
 hw/core/machine.c   |1 +
 hw/i386/pc.c|1 +
 include/hw/boards.h |2 ++
 vl.c|1 +
 4 files changed, 5 insertions(+)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index c58a8e594e..4034b7e903 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -795,6 +795,7 @@ static void smp_parse(MachineState *ms, QemuOpts *opts)
 ms->smp.cpus = cpus;
 ms->smp.cores = cores;
 ms->smp.threads = threads;
+ms->smp.sockets = sockets;
 }
 
 if (ms->smp.cpus > 1) {
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 95aab8e5e7..9e1c3f9f57 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1609,6 +1609,7 @@ void pc_smp_parse(MachineState *ms, QemuOpts *opts)
 ms->smp.cpus = cpus;
 ms->smp.cores = cores;
 ms->smp.threads = threads;
+ms->smp.sockets = sockets;
 pcms->smp_dies = dies;
 }
 
diff --git a/include/hw/boards.h b/include/hw/boards.h
index a71d1a53a5..12eb5032a5 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -245,12 +245,14 @@ typedef struct DeviceMemoryState {
  * @cpus: the number of present logical processors on the machine
  * @cores: the number of cores in one package
  * @threads: the number of threads in one core
+ * @sockets: the number of sockets on the machine
  * @max_cpus: the maximum number of logical processors on the machine
  */
 typedef struct CpuTopology {
 unsigned int cpus;
 unsigned int cores;
 unsigned int threads;
+unsigned int sockets;
 unsigned int max_cpus;
 } CpuTopology;
 
diff --git a/vl.c b/vl.c
index 711d2ae5da..473a688779 100644
--- a/vl.c
+++ b/vl.c
@@ -3981,6 +3981,7 @@ int main(int argc, char **argv, char **envp)
 current_machine->smp.max_cpus = machine_class->default_cpus;
 current_machine->smp.cores = 1;
 current_machine->smp.threads = 1;
+current_machine->smp.sockets = 1;
 
 machine_class->smp_parse(current_machine,
 qemu_opts_find(qemu_find_opts("smp-opts"), NULL));



[Qemu-devel] [PATCH 3/3] qemu-iotests: test for bz #1745922

2019-09-06 Thread Maxim Levitsky
Signed-off-by: Maxim Levitsky 
---
 tests/qemu-iotests/263 | 76 ++
 tests/qemu-iotests/263.out | 19 ++
 tests/qemu-iotests/group   |  1 +
 3 files changed, 96 insertions(+)
 create mode 100755 tests/qemu-iotests/263
 create mode 100644 tests/qemu-iotests/263.out

diff --git a/tests/qemu-iotests/263 b/tests/qemu-iotests/263
new file mode 100755
index 00..9cb23aa81e
--- /dev/null
+++ b/tests/qemu-iotests/263
@@ -0,0 +1,76 @@
+#!/usr/bin/env bash
+#
+# Test encrypted write that crosses cluster boundary of two unallocated 
clusters
+# Based on 188
+#
+# Copyright (C) 2017 Red Hat, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see .
+#
+
+# creator
+owner=mlevi...@redhat.com
+
+seq=`basename $0`
+echo "QA output created by $seq"
+
+status=1   # failure is the default!
+
+_cleanup()
+{
+   _cleanup_test_img
+}
+trap "_cleanup; exit \$status" 0 1 2 3 15
+
+# get standard environment, filters and checks
+. ./common.rc
+. ./common.filter
+
+_supported_fmt qcow2
+_supported_proto generic
+_supported_os Linux
+
+
+size=1M
+
+SECRET="secret,id=sec0,data=astrochicken"
+SECRETALT="secret,id=sec0,data=platypus"
+
+_make_test_img --object $SECRET -o 
"encrypt.format=luks,encrypt.key-secret=sec0,encrypt.iter-time=10,cluster_size=64K"
 $size
+
+IMGSPEC="driver=$IMGFMT,encrypt.key-secret=sec0,file.filename=$TEST_IMG"
+
+QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT
+
+echo
+echo "== reading whole image =="
+$QEMU_IO --object $SECRET -c "read -P 0 0 $size" --image-opts $IMGSPEC | 
_filter_qemu_io | _filter_testdir
+
+echo
+echo "== write two 512 byte sectors on a cluster boundary =="
+$QEMU_IO --object $SECRET -c "write -P 0xAA 0xFE00 0x400" --image-opts 
$IMGSPEC | _filter_qemu_io | _filter_testdir
+
+echo
+echo "== verify that the rest of the image is not changed =="
+$QEMU_IO --object $SECRET -c "read -P 0x00 0x0 0xFE00" --image-opts 
$IMGSPEC | _filter_qemu_io | _filter_testdir
+$QEMU_IO --object $SECRET -c "read -P 0xAA 0x0FE00 0x400" --image-opts 
$IMGSPEC | _filter_qemu_io | _filter_testdir
+$QEMU_IO --object $SECRET -c "read -P 0x00 0x10200 0xEFE00" --image-opts 
$IMGSPEC | _filter_qemu_io | _filter_testdir
+
+_cleanup_test_img
+
+
+# success, all done
+echo "*** done"
+rm -f $seq.full
+status=0
diff --git a/tests/qemu-iotests/263.out b/tests/qemu-iotests/263.out
new file mode 100644
index 00..fa4e4e0e4a
--- /dev/null
+++ b/tests/qemu-iotests/263.out
@@ -0,0 +1,19 @@
+QA output created by 263
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 encrypt.format=luks 
encrypt.key-secret=sec0 encrypt.iter-time=10
+
+== reading whole image ==
+read 1048576/1048576 bytes at offset 0
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== write two 512 byte sectors on a cluster boundary ==
+wrote 1024/1024 bytes at offset 65024
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+
+== verify that the rest of the image is not changed ==
+read 65024/65024 bytes at offset 0
+63.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 1024/1024 bytes at offset 65024
+1 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+read 982528/982528 bytes at offset 66048
+959.500 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+*** done
diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group
index d95d556414..be1c4a3baa 100644
--- a/tests/qemu-iotests/group
+++ b/tests/qemu-iotests/group
@@ -274,3 +274,4 @@
 257 rw
 258 rw quick
 262 rw quick migration
+263 rw quick
-- 
2.17.2




  1   2   3   >